Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Change --surf-path into --cfg=path
[simgrid.git] / src / surf / network_gtnets.c
1 /*     $Id$     */
2
3 /* Copyright (c) 2005 Henri Casanova. All rights reserved.                  */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "network_gtnets_private.h"
9 #include "gtnets/gtnets_interface.h"
10 #include "xbt/str.h"
11
12
13 static double time_to_next_flow_completion = -1;
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network_gtnets, surf,
16                                 "Logging specific to the SURF network module");
17
18 /** QUESTIONS for GTNetS integration
19  **   1. Check that we did the right thing with name_service and get_resource_name
20  **   2. Right now there is no "kill flow" in our GTNetS implementation. Do we
21  **      need to do something about this?
22  **   3. We ignore the fact there is some max_duration on flows (see #2 above)
23  **   4. share_resources() returns a duration, not a date, right?
24  **   5. We don't suppoer "rates"
25  **   6. We don't update "remaining" for ongoing flows. Is it bad?
26  **/
27
28 static int src_id = -1;
29 static int dst_id = -1;
30
31 /* Free memory for a network link */
32 static void link_free(void *nw_link)
33 {
34   free(((network_link_GTNETS_t) nw_link)->name);
35   xbt_dict_free(&(((network_link_GTNETS_t) nw_link)->properties));
36   free(nw_link);
37 }
38
39 /* Instantiate a new network link */
40 /* name: some name for the link, from the XML */
41 /* bw: The bandwidth value            */
42 /* lat: The latency value             */
43 static void link_new(char *name, double bw, double lat, xbt_dict_t props)
44 {
45   static int link_count = -1;
46   network_link_GTNETS_t gtnets_link;
47
48   /* If link already exists, nothing to do (FIXME: check that multiple definition match?) */
49   if (xbt_dict_get_or_null(link_set, name)) {
50     return;
51   }
52
53   /* KF: Increment the link counter for GTNetS */
54   link_count++;
55
56 /*
57   nw_link->model = (surf_model_t) surf_network_model;
58   nw_link->name = name;
59   nw_link->bw_current = bw_initial;
60   if (bw_trace)
61     nw_link->bw_event =
62         tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
63   nw_link->lat_current = lat_initial;
64   if (lat_trace)
65     nw_link->lat_event =
66         tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
67   nw_link->state_current = state_initial;
68   if (state_trace)
69     nw_link->state_event =
70         tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
71 */
72
73   /* KF: Add the link to the GTNetS simulation */
74   if (gtnets_add_link(link_count, bw, lat)) {
75     xbt_assert0(0, "Cannot create GTNetS link");
76   }
77
78   /* KF: Insert entry in the dictionary */
79   gtnets_link = xbt_new0(s_network_link_GTNETS_t, 1);
80   gtnets_link->name = name;
81   gtnets_link->bw_current = bw;
82   gtnets_link->lat_current = lat;
83   gtnets_link->id = link_count;
84   /* Add the properties */
85   gtnets_link->properties = props;
86
87   xbt_dict_set(link_set, name, gtnets_link, link_free);
88
89   return;
90 }
91
92 /* free the network card */
93 static void network_card_free(void *nw_card)
94 {
95   free(((network_card_GTNETS_t) nw_card)->name);
96   free(nw_card);
97 }
98
99 /* Instantiate a new network card: MODIFYED BY KF */
100 static int network_card_new(const char *name)
101 {
102   static int card_count = -1;
103
104   XBT_IN1("(%s)", name);
105   /* KF: Check that we haven't seen the network card before */
106   network_card_GTNETS_t card = xbt_dict_get_or_null(network_card_set, name);
107
108   if (!card) {
109     /* KF: Increment the card counter for GTNetS */
110     card_count++;
111
112     /* KF: just use the dictionary to map link names to link indices */
113     card = xbt_new0(s_network_card_GTNETS_t, 1);
114     card->name = xbt_strdup(name);
115     card->id = card_count;
116     xbt_dict_set(network_card_set, name, card, network_card_free);
117   }
118
119   LOG1(xbt_log_priority_trace, "   return %d", card->id);
120   XBT_OUT;
121   /* KF: just return the GTNetS ID as the SURF ID */
122   return card->id;
123 }
124
125 /* Instantiate a new route: MODIFY BY KF */
126 static void route_new(int src_id, int dst_id, network_link_GTNETS_t * links,
127                       int nb_link)
128 {
129   int i;
130   int *gtnets_links;
131   XBT_IN4("(src_id=%d, dst_id=%d, links=%p, nb_link=%d)",
132           src_id, dst_id, links, nb_link);
133
134   /* KF: Build the list of gtnets link IDs */
135   gtnets_links = (int *) calloc(nb_link, sizeof(int));
136   for (i = 0; i < nb_link; i++) {
137     gtnets_links[i] = links[i]->id;
138   }
139
140   /* KF: Create the GTNets route */
141   if (gtnets_add_route(src_id, dst_id, gtnets_links, nb_link)) {
142     xbt_assert0(0, "Cannot create GTNetS route");
143   }
144   XBT_OUT;
145 }
146
147 /* Instantiate a new route: MODIFY BY KF */
148 static void route_onehop_new(int src_id, int dst_id,
149                              network_link_GTNETS_t * links, int nb_link)
150 {
151   int linkid;
152
153   if (nb_link != 1) {
154     xbt_assert0(0, "In onehop_new, nb_link should be 1");
155   }
156
157   /* KF: Build the linbst of gtnets link IDs */
158   linkid = links[0]->id;
159
160   /* KF: Create the GTNets route */
161   if (gtnets_add_onehop_route(src_id, dst_id, linkid)) {
162     xbt_assert0(0, "Cannot create GTNetS route");
163   }
164 }
165
166
167
168 /* Parse the XML for a network link */
169 static void parse_link_init(void)
170 {
171   char *name;
172   double bw;
173   double lat;
174   e_surf_link_state_t state;
175
176   name = xbt_strdup(A_surfxml_link_id);
177   surf_parse_get_double(&bw, A_surfxml_link_bandwidth);
178   surf_parse_get_double(&lat, A_surfxml_link_latency);
179   state = SURF_LINK_ON;
180
181   tmgr_trace_t bw_trace;
182   tmgr_trace_t state_trace;
183   tmgr_trace_t lat_trace;
184
185   surf_parse_get_trace(&bw_trace, A_surfxml_link_bandwidth_file);
186   surf_parse_get_trace(&lat_trace, A_surfxml_link_latency_file);
187   surf_parse_get_trace(&state_trace, A_surfxml_link_state_file);
188
189   if (bw_trace)
190     INFO0("The GTNetS network model doesn't support bandwidth state traces");
191   if (lat_trace)
192     INFO0("The GTNetS network model doesn't support latency state traces");
193   if (state_trace)
194     INFO0("The GTNetS network model doesn't support link state traces");
195
196   current_property_set = xbt_dict_new();
197   link_new(name, bw, lat, current_property_set);
198 }
199
200 /* Parses a route from the XML: UNMODIFIED BY HC */
201 static void parse_route_set_endpoints(void)
202 {
203   src_id = network_card_new(A_surfxml_route_src);
204   dst_id = network_card_new(A_surfxml_route_dst);
205   route_action = A_surfxml_route_action;
206 }
207
208 /* KF*/
209 static void parse_route_set_routers(void)
210 {
211   int id = network_card_new(A_surfxml_router_id);
212
213   /* KF: Create the GTNets router */
214   if (gtnets_add_router(id)) {
215     xbt_assert0(0, "Cannot add GTNetS router");
216   }
217 }
218
219 /* Create the route (more than one hops): MODIFIED BY KF */
220 static void parse_route_set_route(void)
221 {
222   char *name;
223   if (src_id != -1 && dst_id != -1) {
224     name = bprintf("%x#%x", src_id, dst_id);
225     manage_route(route_table, name, route_action, 0);
226     free(name);
227   }
228 }
229
230 static void add_route()
231 {
232   xbt_ex_t e;
233   unsigned int cpt = 0;
234   int link_list_capacity = 0;
235   int nb_link = 0;
236   xbt_dict_cursor_t cursor = NULL;
237   char *key, *data, *end;
238   const char *sep = "#";
239   xbt_dynar_t links, keys;
240   static network_link_GTNETS_t *link_list = NULL;
241
242
243   XBT_IN;
244   xbt_dict_foreach(route_table, cursor, key, data) {
245     char *link = NULL;
246     nb_link = 0;
247     links = (xbt_dynar_t) data;
248     keys = xbt_str_split_str(key, sep);
249
250     link_list_capacity = xbt_dynar_length(links);
251     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
252
253     src_id = strtol(xbt_dynar_get_as(keys, 0, char *), &end, 16);
254     dst_id = strtol(xbt_dynar_get_as(keys, 1, char *), &end, 16);
255     xbt_dynar_free(&keys);
256
257     xbt_dynar_foreach(links, cpt, link) {
258       TRY {
259         link_list[nb_link++] = xbt_dict_get(link_set, link);
260       }
261       CATCH(e) {
262         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
263       }
264     }
265     if (nb_link == 1)
266       route_onehop_new(src_id, dst_id, link_list, nb_link);
267   }
268
269   xbt_dict_foreach(route_table, cursor, key, data) {
270     char *link = NULL;
271     nb_link = 0;
272     links = (xbt_dynar_t) data;
273     keys = xbt_str_split_str(key, sep);
274
275     link_list_capacity = xbt_dynar_length(links);
276     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
277
278     src_id = strtol(xbt_dynar_get_as(keys, 0, char *), &end, 16);
279     dst_id = strtol(xbt_dynar_get_as(keys, 1, char *), &end, 16);
280     xbt_dynar_free(&keys);
281
282     xbt_dynar_foreach(links, cpt, link) {
283       TRY {
284         link_list[nb_link++] = xbt_dict_get(link_set, link);
285       }
286       CATCH(e) {
287         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
288       }
289     }
290     if (nb_link >= 1)
291       route_new(src_id, dst_id, link_list, nb_link);
292   }
293
294   xbt_dict_free(&route_table);
295   gtnets_print_topology();
296   XBT_OUT;
297 }
298
299 /* Main XML parsing */
300 static void define_callbacks(const char *file)
301 {
302   surfxml_add_callback(STag_surfxml_router_cb_list, &parse_route_set_routers);
303   surfxml_add_callback(STag_surfxml_link_cb_list, &parse_link_init);
304   surfxml_add_callback(STag_surfxml_route_cb_list,
305                        &parse_route_set_endpoints);
306   surfxml_add_callback(ETag_surfxml_route_cb_list, &parse_route_set_route);
307   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_route);
308 }
309
310 static void *name_service(const char *name)
311 {
312   return xbt_dict_get_or_null(network_card_set, name);
313 }
314
315 static const char *get_resource_name(void *resource_id)
316 {
317   return ((network_card_GTNETS_t) resource_id)->name;
318 }
319
320 static xbt_dict_t get_properties(void *link)
321 {
322   return ((network_card_GTNETS_t) link)->properties;
323 }
324
325
326 /* We do not care about this: only used for traces */
327 static int resource_used(void *resource_id)
328 {
329   return 0;                     /* We don't care */
330 }
331
332 static int action_free(surf_action_t action)
333 {
334   action->refcount--;
335   if (!action->refcount) {
336     xbt_swag_remove(action, action->state_set);
337     /* KF: No explicit freeing needed for GTNeTS here */
338     free(action);
339     return 1;
340   }
341   return 0;
342 }
343
344 static void action_use(surf_action_t action)
345 {
346   action->refcount++;
347 }
348
349 static void action_cancel(surf_action_t action)
350 {
351   xbt_assert0(0, "Cannot cancel GTNetS flow");
352   return;
353 }
354
355 static void action_recycle(surf_action_t action)
356 {
357   xbt_assert0(0, "Cannot recycle GTNetS flow");
358   return;
359 }
360
361 static void action_change_state(surf_action_t action,
362                                 e_surf_action_state_t state)
363 {
364 /*   if((state==SURF_ACTION_DONE) || (state==SURF_ACTION_FAILED)) */
365 /*     if(((surf_action_network_GTNETS_t)action)->variable) { */
366 /*       lmm_variable_disable(maxmin_system, ((surf_action_network_GTNETS_t)action)->variable); */
367 /*       ((surf_action_network_GTNETS_t)action)->variable = NULL; */
368 /*     } */
369
370   surf_action_change_state(action, state);
371   return;
372 }
373
374
375 /* share_resources() */
376 static double share_resources(double now)
377 {
378   xbt_swag_t running_actions =
379     surf_network_model->common_public->states.running_action_set;
380
381   //get the first relevant value from the running_actions list
382   if (!xbt_swag_size(running_actions))
383     return -1.0;
384
385   xbt_assert0(time_to_next_flow_completion,
386               "Time to next flow completion not initialized!\n");
387
388   time_to_next_flow_completion = gtnets_get_time_to_next_flow_completion();
389
390   return time_to_next_flow_completion;
391 }
392
393 /* delta: by how many time units the simulation must advance */
394 /* In this function: change the state of actions that terminate */
395 /* The delta may not come from the network, and thus may be different (smaller) 
396    than the one returned by the function above */
397 /* If the delta is a network-caused min, then do not emulate any timer in the
398    network simulation, otherwise fake a timer somehow to advance the simulation of min seconds */
399
400 static void update_actions_state(double now, double delta)
401 {
402   surf_action_network_GTNETS_t action = NULL;
403   //  surf_action_network_GTNETS_t next_action = NULL;
404   xbt_swag_t running_actions =
405     surf_network_model->common_public->states.running_action_set;
406
407   /* If there are no renning flows, just return */
408   if (time_to_next_flow_completion < 0.0) {
409     return;
410   }
411
412   /*KF: if delta == time_to_next_flow_completion, too. */
413   if (time_to_next_flow_completion <= delta) {  /* run until the first flow completes */
414     void **metadata;
415     int i, num_flows;
416
417     num_flows = 0;
418
419     if (gtnets_run_until_next_flow_completion(&metadata, &num_flows)) {
420       xbt_assert0(0,
421                   "Cannot run GTNetS simulation until next flow completion");
422     }
423     if (num_flows < 1) {
424       xbt_assert0(0,
425                   "GTNetS simulation couldn't find a flow that would complete");
426     }
427
428     xbt_swag_foreach(action, running_actions) {
429       DEBUG2("Action (%p) remains old value: %f", action,
430              action->generic_action.remains);
431       double remain = gtnets_get_flow_rx(action);
432       DEBUG1("Remain value returned by GTNetS : %f", remain);
433       //need to trust this remain value
434       if (remain == 0) {
435         action->generic_action.remains = 0;
436       } else {
437         action->generic_action.remains = action->generic_action.cost - remain;
438       }
439       DEBUG2("Action (%p) remains new value: %f", action,
440              action->generic_action.remains);
441     }
442
443     for (i = 0; i < num_flows; i++) {
444       action = (surf_action_network_GTNETS_t) (metadata[i]);
445
446       action->generic_action.finish = now + time_to_next_flow_completion;
447       action_change_state((surf_action_t) action, SURF_ACTION_DONE);
448       DEBUG1("----> Action (%p) just terminated", action);
449     }
450
451
452   } else {                      /* run for a given number of seconds */
453     if (gtnets_run(delta)) {
454       xbt_assert0(0, "Cannot run GTNetS simulation");
455     }
456   }
457
458   return;
459 }
460
461 /* UNUSED HERE: no traces */
462 static void update_resource_state(void *id,
463                                   tmgr_trace_event_t event_type,
464                                   double value, double date)
465 {
466   xbt_assert0(0, "Cannot update model state for GTNetS simulation");
467   return;
468 }
469
470 /* KF: Rate not supported */
471 static surf_action_t communicate(void *src, void *dst, double size,
472                                  double rate)
473 {
474   surf_action_network_GTNETS_t action = NULL;
475   network_card_GTNETS_t card_src = src;
476   network_card_GTNETS_t card_dst = dst;
477 /*
478   int route_size = ROUTE_SIZE(card_src->id, card_dst->id);
479   network_link_GTNETS_t *route = ROUTE(card_src->id, card_dst->id);
480 */
481
482 /*
483   xbt_assert2(route_size,"You're trying to send data from %s to %s but there is no connexion between these two cards.", card_src->name, card_dst->name);
484 */
485
486   action = xbt_new0(s_surf_action_network_GTNETS_t, 1);
487
488   action->generic_action.refcount = 1;
489   action->generic_action.cost = size;
490   action->generic_action.remains = size;
491   /* Max durations are not supported */
492   action->generic_action.max_duration = NO_MAX_DURATION;
493   action->generic_action.start = surf_get_clock();
494   action->generic_action.finish = -1.0;
495   action->generic_action.model_type = (surf_model_t) surf_network_model;
496
497   action->generic_action.state_set =
498     surf_network_model->common_public->states.running_action_set;
499
500   xbt_swag_insert(action, action->generic_action.state_set);
501
502   /* KF: Add a flow to the GTNets Simulation, associated to this action */
503   if (gtnets_create_flow(card_src->id, card_dst->id, size, (void *) action)
504       < 0) {
505     xbt_assert2(0, "Not route between host %s and host %s", card_src->name,
506                 card_dst->name);
507   }
508
509   return (surf_action_t) action;
510 }
511
512 /* Suspend a flow() */
513 static void action_suspend(surf_action_t action)
514 {
515   xbt_assert0(0,
516               "action_suspend() not supported for the GTNets network model");
517 }
518
519 /* Resume a flow() */
520 static void action_resume(surf_action_t action)
521 {
522   xbt_assert0(0,
523               "action_resume() not supported for the GTNets network model");
524 }
525
526 /* Test whether a flow is suspended */
527 static int action_is_suspended(surf_action_t action)
528 {
529   return 0;
530 }
531
532 static void finalize(void)
533 {
534 #if 0
535   int i, j;
536 #endif
537   xbt_dict_free(&network_card_set);
538   xbt_dict_free(&link_set);
539   xbt_swag_free(surf_network_model->common_public->states.ready_action_set);
540   xbt_swag_free(surf_network_model->common_public->states.running_action_set);
541   xbt_swag_free(surf_network_model->common_public->states.failed_action_set);
542   xbt_swag_free(surf_network_model->common_public->states.done_action_set);
543   free(surf_network_model->common_public);
544   free(surf_network_model->common_private);
545   free(surf_network_model->extension_public);
546
547   free(surf_network_model);
548   surf_network_model = NULL;
549
550   gtnets_finalize();
551 }
552
553 static void surf_network_model_init_internal(void)
554 {
555   s_surf_action_t action;
556
557   surf_network_model = xbt_new0(s_surf_network_model_t, 1);
558
559   surf_network_model->common_private = xbt_new0(s_surf_model_private_t, 1);
560   surf_network_model->common_public = xbt_new0(s_surf_model_public_t, 1);
561   surf_network_model->extension_public =
562     xbt_new0(s_surf_network_model_extension_public_t, 1);
563
564   surf_network_model->common_public->states.ready_action_set =
565     xbt_swag_new(xbt_swag_offset(action, state_hookup));
566   surf_network_model->common_public->states.running_action_set =
567     xbt_swag_new(xbt_swag_offset(action, state_hookup));
568   surf_network_model->common_public->states.failed_action_set =
569     xbt_swag_new(xbt_swag_offset(action, state_hookup));
570   surf_network_model->common_public->states.done_action_set =
571     xbt_swag_new(xbt_swag_offset(action, state_hookup));
572
573   surf_network_model->common_public->name_service = name_service;
574   surf_network_model->common_public->get_resource_name = get_resource_name;
575   surf_network_model->common_public->action_get_state = surf_action_get_state;
576   surf_network_model->common_public->action_use = action_use;
577   surf_network_model->common_public->action_free = action_free;
578   surf_network_model->common_public->action_cancel = action_cancel;
579   surf_network_model->common_public->action_recycle = action_recycle;
580   surf_network_model->common_public->action_change_state =
581     action_change_state;
582   surf_network_model->common_public->action_set_data = surf_action_set_data;
583   surf_network_model->common_public->name = "network";
584
585   surf_network_model->common_private->resource_used = resource_used;
586   surf_network_model->common_private->share_resources = share_resources;
587   surf_network_model->common_private->update_actions_state =
588     update_actions_state;
589   surf_network_model->common_private->update_resource_state =
590     update_resource_state;
591   surf_network_model->common_private->finalize = finalize;
592
593   surf_network_model->common_public->suspend = action_suspend;
594   surf_network_model->common_public->resume = action_resume;
595   surf_network_model->common_public->is_suspended = action_is_suspended;
596
597   surf_network_model->extension_public->communicate = communicate;
598
599   /*for the props of the link */
600   surf_network_model->common_public->get_properties = get_properties;
601
602   link_set = xbt_dict_new();
603   network_card_set = xbt_dict_new();
604
605   /* KF: Added the initialization for GTNetS interface */
606   if (gtnets_initialize()) {
607     xbt_assert0(0, "impossible to initialize GTNetS interface");
608   }
609 }
610
611 #ifdef HAVE_GTNETS
612 void surf_network_model_init_GTNETS(const char *filename)
613 {
614   if (surf_network_model)
615     return;
616   surf_network_model_init_internal();
617   define_callbacks(filename);
618   xbt_dynar_push(model_list, &surf_network_model);
619
620   update_model_description(surf_network_model_description,
621                            "GTNets", (surf_model_t) surf_network_model);
622 }
623 #endif