Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
keep documentation in sync with implementation
[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 =
107       xbt_dict_get_or_null(network_card_set, name);
108
109   if (!card) {
110     /* KF: Increment the card counter for GTNetS */
111     card_count++;
112
113     /* KF: just use the dictionary to map link names to link indices */
114     card = xbt_new0(s_network_card_GTNETS_t, 1);
115     card->name = xbt_strdup(name);
116     card->id = card_count;
117     xbt_dict_set(network_card_set, name, card, network_card_free);
118   }
119   
120   LOG1(xbt_log_priority_trace, "   return %d",card->id);
121   XBT_OUT;
122   /* KF: just return the GTNetS ID as the SURF ID */
123   return card->id;
124 }
125
126 /* Instantiate a new route: MODIFY BY KF */
127 static void route_new(int src_id, int dst_id, network_link_GTNETS_t *links, 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, network_link_GTNETS_t *links, int nb_link)
149 {
150   int linkid;
151
152   if (nb_link != 1) {
153     xbt_assert0(0, "In onehop_new, nb_link should be 1");
154   }
155
156   /* KF: Build the linbst of gtnets link IDs */
157   linkid = links[0]->id;
158
159   /* KF: Create the GTNets route */
160   if (gtnets_add_onehop_route(src_id, dst_id, linkid)) {
161     xbt_assert0(0, "Cannot create GTNetS route");
162   }
163 }
164
165
166
167 /* Parse the XML for a network link */
168 static void parse_link_init(void)
169 {
170   char *name;
171   double bw;
172   double lat;
173   e_surf_link_state_t state;
174
175   name = xbt_strdup(A_surfxml_link_id);
176   surf_parse_get_double(&bw, A_surfxml_link_bandwidth);
177   surf_parse_get_double(&lat, A_surfxml_link_latency);
178   state = SURF_LINK_ON;
179
180   tmgr_trace_t bw_trace;
181   tmgr_trace_t state_trace;
182   tmgr_trace_t lat_trace;
183   
184   surf_parse_get_trace(&bw_trace, A_surfxml_link_bandwidth_file);
185   surf_parse_get_trace(&lat_trace, A_surfxml_link_latency_file);
186   surf_parse_get_trace(&state_trace, A_surfxml_link_state_file);
187
188   if (bw_trace)
189     INFO0("The GTNetS network model doesn't support bandwidth state traces");
190   if (lat_trace)
191     INFO0("The GTNetS network model doesn't support latency state traces");
192   if (state_trace)
193     INFO0("The GTNetS network model doesn't support link state traces");
194
195   current_property_set = xbt_dict_new();
196   link_new(name, bw, lat, current_property_set);
197 }
198
199 /* Parses a route from the XML: UNMODIFIED BY HC */
200 static void parse_route_set_endpoints(void)
201 {
202   src_id = network_card_new(A_surfxml_route_src);
203   dst_id = network_card_new(A_surfxml_route_dst);
204   route_action = A_surfxml_route_action;
205 }
206
207 /* KF*/
208 static void parse_route_set_routers(void)
209 {
210   int id = network_card_new(A_surfxml_router_id);
211
212   /* KF: Create the GTNets router */
213   if (gtnets_add_router(id)) {
214     xbt_assert0(0, "Cannot add GTNetS router");
215   }
216 }
217
218 /* Create the route (more than one hops): MODIFIED BY KF */
219 static void parse_route_set_route(void)
220 {
221   char *name;
222   if (src_id != -1 && dst_id != -1) {
223     name = bprintf("%x#%x",src_id, dst_id);
224     manage_route(route_table, name, route_action, 0);
225     free(name);    
226   }
227 }
228
229 static void add_route()
230 {
231   xbt_ex_t e;
232   unsigned int cpt = 0;    
233   int link_list_capacity = 0;
234   int nb_link = 0;
235   xbt_dict_cursor_t cursor = NULL;
236   char *key,*data, *end;
237   const char *sep = "#";
238   xbt_dynar_t links, keys;
239   static network_link_GTNETS_t *link_list = NULL;
240
241
242   XBT_IN;
243   xbt_dict_foreach(route_table, cursor, key, data) {
244     char *link = NULL;
245     nb_link = 0;
246     links = (xbt_dynar_t)data;
247     keys = xbt_str_split_str(key, sep);
248
249     link_list_capacity = xbt_dynar_length(links);
250     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
251
252     src_id = strtol(xbt_dynar_get_as(keys, 0, char*), &end, 16);
253     dst_id = strtol(xbt_dynar_get_as(keys, 1, char*), &end, 16);
254     xbt_dynar_free(&keys);
255
256     xbt_dynar_foreach (links, cpt, link) {
257       TRY {
258         link_list[nb_link++] = xbt_dict_get(link_set, link);
259       }
260       CATCH(e) {
261         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
262       }     
263     }
264     if (nb_link == 1)
265       route_onehop_new(src_id, dst_id, link_list, nb_link);
266    }
267
268   xbt_dict_foreach(route_table, cursor, key, data) {
269     char *link = NULL;
270     nb_link = 0;
271     links = (xbt_dynar_t)data;
272     keys = xbt_str_split_str(key, sep);
273
274     link_list_capacity = xbt_dynar_length(links);
275     link_list = xbt_new(network_link_GTNETS_t, link_list_capacity);
276
277     src_id = strtol(xbt_dynar_get_as(keys, 0, char*), &end, 16);
278     dst_id = strtol(xbt_dynar_get_as(keys, 1, char*), &end, 16);
279     xbt_dynar_free(&keys);
280
281     xbt_dynar_foreach (links, cpt, link) {
282       TRY {
283         link_list[nb_link++] = xbt_dict_get(link_set, link);
284       }
285       CATCH(e) {
286         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
287       }     
288     }
289     if (nb_link >= 1)
290       route_new(src_id, dst_id, link_list, nb_link);
291    }
292
293   xbt_dict_free(&route_table);
294   gtnets_print_topology();
295   XBT_OUT;
296 }
297
298 /* Main XML parsing */
299 static void define_callbacks(const char *file)
300 {
301   surfxml_add_callback(STag_surfxml_router_cb_list,   &parse_route_set_routers);
302   surfxml_add_callback(STag_surfxml_link_cb_list,     &parse_link_init);
303   surfxml_add_callback(STag_surfxml_route_cb_list,    &parse_route_set_endpoints);
304   surfxml_add_callback(ETag_surfxml_route_cb_list,      &parse_route_set_route);
305   surfxml_add_callback(ETag_surfxml_platform_cb_list,   &add_route);
306 }
307
308 static void *name_service(const char *name)
309 {
310   return xbt_dict_get_or_null(network_card_set, name);
311 }
312
313 static const char *get_resource_name(void *resource_id)
314 {
315   return ((network_card_GTNETS_t) resource_id)->name;
316 }
317
318 static xbt_dict_t get_properties(void *link)
319 {
320   return ((network_card_GTNETS_t) link)->properties;
321 }
322
323
324 /* We do not care about this: only used for traces */
325 static int resource_used(void *resource_id)
326 {
327   return 0;                     /* We don't care */
328 }
329
330 static int action_free(surf_action_t action)
331 {
332   action->refcount--;
333   if (!action->refcount) {
334     xbt_swag_remove(action, action->state_set);
335     /* KF: No explicit freeing needed for GTNeTS here */
336     free(action);
337     return 1;
338   }
339   return 0;
340 }
341
342 static void action_use(surf_action_t action)
343 {
344   action->refcount++;
345 }
346
347 static void action_cancel(surf_action_t action)
348 {
349   xbt_assert0(0, "Cannot cancel GTNetS flow");
350   return;
351 }
352
353 static void action_recycle(surf_action_t action)
354 {
355   xbt_assert0(0, "Cannot recycle GTNetS flow");
356   return;
357 }
358
359 static void action_change_state(surf_action_t action,
360                                 e_surf_action_state_t state)
361 {
362 /*   if((state==SURF_ACTION_DONE) || (state==SURF_ACTION_FAILED)) */
363 /*     if(((surf_action_network_GTNETS_t)action)->variable) { */
364 /*       lmm_variable_disable(maxmin_system, ((surf_action_network_GTNETS_t)action)->variable); */
365 /*       ((surf_action_network_GTNETS_t)action)->variable = NULL; */
366 /*     } */
367
368   surf_action_change_state(action, state);
369   return;
370 }
371
372
373 /* share_resources() */
374 static double share_resources(double now)
375 {
376   xbt_swag_t running_actions = surf_network_model->common_public->states.running_action_set;
377
378   //get the first relevant value from the running_actions list
379   if (!xbt_swag_size(running_actions))
380     return -1.0;
381
382   xbt_assert0(time_to_next_flow_completion, "Time to next flow completion not initialized!\n");
383   
384   time_to_next_flow_completion = gtnets_get_time_to_next_flow_completion();
385
386   return time_to_next_flow_completion;
387 }
388
389 /* delta: by how many time units the simulation must advance */
390 /* In this function: change the state of actions that terminate */
391 /* The delta may not come from the network, and thus may be different (smaller) 
392    than the one returned by the function above */
393 /* If the delta is a network-caused min, then do not emulate any timer in the
394    network simulation, otherwise fake a timer somehow to advance the simulation of min seconds */
395
396 static void update_actions_state(double now, double delta)
397 {
398   surf_action_network_GTNETS_t action = NULL;
399   //  surf_action_network_GTNETS_t next_action = NULL;
400   xbt_swag_t running_actions =
401       surf_network_model->common_public->states.running_action_set;
402
403   /* If there are no renning flows, just return */
404   if (time_to_next_flow_completion < 0.0) {
405     return;
406   }
407
408   /*KF: if delta == time_to_next_flow_completion, too. */
409   if (time_to_next_flow_completion <= delta) {  /* run until the first flow completes */
410     void **metadata;
411     int i, num_flows;
412
413     num_flows = 0;
414
415     if (gtnets_run_until_next_flow_completion(&metadata, &num_flows)) {
416       xbt_assert0(0,
417                   "Cannot run GTNetS simulation until next flow completion");
418     }
419     if (num_flows < 1) {
420       xbt_assert0(0,
421                   "GTNetS simulation couldn't find a flow that would complete");
422     }
423
424     xbt_swag_foreach(action, running_actions) {
425       DEBUG2("Action (%p) remains old value: %f", action, action->generic_action.remains);
426       double remain = gtnets_get_flow_rx(action);
427       DEBUG1("Remain value returned by GTNetS : %f", remain);
428       //need to trust this remain value
429       if(remain == 0){
430         action->generic_action.remains=0;
431       }else {
432         action->generic_action.remains=action->generic_action.cost-remain;
433       }
434       DEBUG2("Action (%p) remains new value: %f", action, action->generic_action.remains);
435     }
436
437     for (i = 0; i < num_flows; i++) {
438       action =  (surf_action_network_GTNETS_t) (metadata[i]);
439       
440       action->generic_action.finish = now + time_to_next_flow_completion;
441       action_change_state((surf_action_t) action, SURF_ACTION_DONE);
442       DEBUG1("----> Action (%p) just terminated",action);
443     }
444
445
446   } else {                      /* run for a given number of seconds */
447     if (gtnets_run(delta)) {
448       xbt_assert0(0, "Cannot run GTNetS simulation");
449     }
450   }
451
452   return;
453 }
454
455 /* UNUSED HERE: no traces */
456 static void update_resource_state(void *id,
457                                   tmgr_trace_event_t event_type,
458                                   double value, double date)
459 {
460   xbt_assert0(0, "Cannot update model state for GTNetS simulation");
461   return;
462 }
463
464 /* KF: Rate not supported */
465 static surf_action_t communicate(void *src, void *dst, double size,
466                                  double rate)
467 {
468   surf_action_network_GTNETS_t action = NULL;
469   network_card_GTNETS_t card_src = src;
470   network_card_GTNETS_t card_dst = dst;
471 /*
472   int route_size = ROUTE_SIZE(card_src->id, card_dst->id);
473   network_link_GTNETS_t *route = ROUTE(card_src->id, card_dst->id);
474 */
475
476 /*
477   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);
478 */
479
480   action = xbt_new0(s_surf_action_network_GTNETS_t, 1);
481
482   action->generic_action.refcount = 1;
483   action->generic_action.cost = size;
484   action->generic_action.remains = size;
485   /* Max durations are not supported */
486   action->generic_action.max_duration = NO_MAX_DURATION;
487   action->generic_action.start = surf_get_clock();
488   action->generic_action.finish = -1.0;
489   action->generic_action.model_type =
490       (surf_model_t) surf_network_model;
491
492   action->generic_action.state_set =
493       surf_network_model->common_public->states.running_action_set;
494
495   xbt_swag_insert(action, action->generic_action.state_set);
496
497   /* KF: Add a flow to the GTNets Simulation, associated to this action */
498   if (gtnets_create_flow(card_src->id, card_dst->id, size, (void *) action)
499       < 0) {
500     xbt_assert2(0, "Not route between host %s and host %s", card_src->name,
501                 card_dst->name);
502   }
503
504   return (surf_action_t) action;
505 }
506
507 /* Suspend a flow() */
508 static void action_suspend(surf_action_t action)
509 {
510   xbt_assert0(0,
511               "action_suspend() not supported for the GTNets network model");
512 }
513
514 /* Resume a flow() */
515 static void action_resume(surf_action_t action)
516 {
517   xbt_assert0(0,
518               "action_resume() not supported for the GTNets network model");
519 }
520
521 /* Test whether a flow is suspended */
522 static int action_is_suspended(surf_action_t action)
523 {
524   return 0;
525 }
526
527 static void finalize(void)
528 {
529 #if 0
530   int i, j;
531 #endif
532   xbt_dict_free(&network_card_set);
533   xbt_dict_free(&link_set);
534   xbt_swag_free(surf_network_model->common_public->states.
535                 ready_action_set);
536   xbt_swag_free(surf_network_model->common_public->states.
537                 running_action_set);
538   xbt_swag_free(surf_network_model->common_public->states.
539                 failed_action_set);
540   xbt_swag_free(surf_network_model->common_public->states.
541                 done_action_set);
542   free(surf_network_model->common_public);
543   free(surf_network_model->common_private);
544   free(surf_network_model->extension_public);
545
546   free(surf_network_model);
547   surf_network_model = NULL;
548
549   gtnets_finalize();
550 }
551
552 static void surf_network_model_init_internal(void)
553 {
554   s_surf_action_t action;
555
556   surf_network_model = xbt_new0(s_surf_network_model_t, 1);
557
558   surf_network_model->common_private =
559       xbt_new0(s_surf_model_private_t, 1);
560   surf_network_model->common_public =
561       xbt_new0(s_surf_model_public_t, 1);
562   surf_network_model->extension_public =
563       xbt_new0(s_surf_network_model_extension_public_t, 1);
564
565   surf_network_model->common_public->states.ready_action_set =
566       xbt_swag_new(xbt_swag_offset(action, state_hookup));
567   surf_network_model->common_public->states.running_action_set =
568       xbt_swag_new(xbt_swag_offset(action, state_hookup));
569   surf_network_model->common_public->states.failed_action_set =
570       xbt_swag_new(xbt_swag_offset(action, state_hookup));
571   surf_network_model->common_public->states.done_action_set =
572       xbt_swag_new(xbt_swag_offset(action, state_hookup));
573
574   surf_network_model->common_public->name_service = name_service;
575   surf_network_model->common_public->get_resource_name =
576       get_resource_name;
577   surf_network_model->common_public->action_get_state =
578       surf_action_get_state;
579   surf_network_model->common_public->action_use = action_use;
580   surf_network_model->common_public->action_free = action_free;
581   surf_network_model->common_public->action_cancel = action_cancel;
582   surf_network_model->common_public->action_recycle = action_recycle;
583   surf_network_model->common_public->action_change_state =
584       action_change_state;
585   surf_network_model->common_public->action_set_data =
586       surf_action_set_data;
587   surf_network_model->common_public->name = "network";
588
589   surf_network_model->common_private->resource_used = resource_used;
590   surf_network_model->common_private->share_resources = share_resources;
591   surf_network_model->common_private->update_actions_state =
592       update_actions_state;
593   surf_network_model->common_private->update_resource_state = update_resource_state;
594   surf_network_model->common_private->finalize = finalize;
595
596   surf_network_model->common_public->suspend = action_suspend;
597   surf_network_model->common_public->resume = action_resume;
598   surf_network_model->common_public->is_suspended = action_is_suspended;
599
600   surf_network_model->extension_public->communicate = communicate;
601
602   /*for the props of the link*/
603   surf_network_model->common_public->get_properties =  get_properties;
604
605   link_set = xbt_dict_new();
606   network_card_set = xbt_dict_new();
607
608   /* KF: Added the initialization for GTNetS interface */
609   if (gtnets_initialize()) {
610     xbt_assert0(0, "impossible to initialize GTNetS interface");
611   }
612 }
613
614 #ifdef HAVE_GTNETS
615 void surf_network_model_init_GTNETS(const char *filename)
616 {
617   if (surf_network_model)
618     return;
619   surf_network_model_init_internal();
620   define_callbacks(filename);
621   xbt_dynar_push(model_list, &surf_network_model);
622
623   update_model_description(surf_network_model_description,
624                            "GTNets",
625                            (surf_model_t) surf_network_model);
626 }
627 #endif