Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
kill link_set (use surf_network_model->resource_set instead)
[simgrid.git] / src / surf / network.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2004 Arnaud Legrand. 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_private.h"
9 #include "xbt/log.h"
10 #include "xbt/str.h"
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network, surf,
13                                 "Logging specific to the SURF network module");
14
15 surf_model_t surf_network_model = NULL;
16 static lmm_system_t network_maxmin_system = NULL;
17 static void (*network_solve) (lmm_system_t) = NULL;
18
19 double latency_factor = 1.0;    /* default value */
20 double bandwidth_factor = 1.0;  /* default value */
21 double weight_S_parameter = 0.0;        /* default value */
22
23 int card_number = 0;
24 int host_count = 0;
25 double sg_tcp_gamma = 0.0;
26
27
28 static void link_free(void *nw_link)
29 {
30   xbt_dict_free(&(((link_CM02_t) nw_link)->properties));
31   surf_resource_free(nw_link);
32 }
33
34 static link_CM02_t link_new(char *name,
35                             double bw_initial,
36                             tmgr_trace_t bw_trace,
37                             double lat_initial,
38                             tmgr_trace_t lat_trace,
39                             e_surf_link_state_t
40                             state_initial,
41                             tmgr_trace_t state_trace,
42                             e_surf_link_sharing_policy_t
43                             policy, xbt_dict_t properties)
44 {
45   link_CM02_t nw_link = xbt_new0(s_link_CM02_t, 1);
46   xbt_assert1(!xbt_dict_get_or_null(surf_network_model->resource_set, name),
47               "Link '%s' declared several times in the platform file.", name);
48
49   nw_link->generic_resource.model = surf_network_model;
50   nw_link->generic_resource.name = name;
51   nw_link->bw_current = bw_initial;
52   if (bw_trace)
53     nw_link->bw_event =
54       tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
55   nw_link->lat_current = lat_initial;
56   if (lat_trace)
57     nw_link->lat_event =
58       tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
59   nw_link->state_current = state_initial;
60   if (state_trace)
61     nw_link->state_event =
62       tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
63
64   nw_link->constraint =
65     lmm_constraint_new(network_maxmin_system, nw_link,
66                        bandwidth_factor * nw_link->bw_current);
67
68   if (policy == SURF_LINK_FATPIPE)
69     lmm_constraint_shared(nw_link->constraint);
70
71   nw_link->properties = properties;
72
73   current_property_set = properties;
74
75   xbt_dict_set(surf_network_model->resource_set, name, nw_link, link_free);
76
77   return nw_link;
78 }
79
80 static void parse_link_init(void)
81 {
82   char *name_link;
83   double bw_initial;
84   tmgr_trace_t bw_trace;
85   double lat_initial;
86   tmgr_trace_t lat_trace;
87   e_surf_link_state_t state_initial_link = SURF_LINK_ON;
88   e_surf_link_sharing_policy_t policy_initial_link = SURF_LINK_SHARED;
89   tmgr_trace_t state_trace;
90
91   name_link = xbt_strdup(A_surfxml_link_id);
92   surf_parse_get_double(&bw_initial, A_surfxml_link_bandwidth);
93   surf_parse_get_trace(&bw_trace, A_surfxml_link_bandwidth_file);
94   surf_parse_get_double(&lat_initial, A_surfxml_link_latency);
95   surf_parse_get_trace(&lat_trace, A_surfxml_link_latency_file);
96
97   xbt_assert0((A_surfxml_link_state == A_surfxml_link_state_ON)
98               || (A_surfxml_link_state ==
99                   A_surfxml_link_state_OFF), "Invalid state");
100   if (A_surfxml_link_state == A_surfxml_link_state_ON)
101     state_initial_link = SURF_LINK_ON;
102   else if (A_surfxml_link_state == A_surfxml_link_state_OFF)
103     state_initial_link = SURF_LINK_OFF;
104
105   if (A_surfxml_link_sharing_policy == A_surfxml_link_sharing_policy_SHARED)
106     policy_initial_link = SURF_LINK_SHARED;
107   else if (A_surfxml_link_sharing_policy ==
108            A_surfxml_link_sharing_policy_FATPIPE)
109     policy_initial_link = SURF_LINK_FATPIPE;
110
111   surf_parse_get_trace(&state_trace, A_surfxml_link_state_file);
112
113   link_new(name_link, bw_initial, bw_trace,
114            lat_initial, lat_trace, state_initial_link, state_trace,
115            policy_initial_link, xbt_dict_new());
116
117 }
118
119 static void add_traces(void)
120 {
121   xbt_dict_cursor_t cursor = NULL;
122   char *trace_name, *elm;
123
124   static int called = 0;
125   if (called)
126     return;
127   called = 1;
128
129   /* connect all traces relative to network */
130   xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) {
131     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
132     link_CM02_t link = xbt_dict_get_or_null(surf_network_model->resource_set, elm);
133
134     xbt_assert2(link, "Cannot connect trace %s to link %s: link undefined",
135                 trace_name, elm);
136     xbt_assert2(trace, "Cannot connect trace %s to link %s: trace undefined",
137                 trace_name, elm);
138
139     link->state_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
140   }
141
142   xbt_dict_foreach(trace_connect_list_bandwidth, cursor, trace_name, elm) {
143     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
144     link_CM02_t link = xbt_dict_get_or_null(surf_network_model->resource_set, elm);
145
146     xbt_assert2(link, "Cannot connect trace %s to link %s: link undefined",
147                 trace_name, elm);
148     xbt_assert2(trace, "Cannot connect trace %s to link %s: trace undefined",
149                 trace_name, elm);
150
151     link->bw_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
152   }
153
154   xbt_dict_foreach(trace_connect_list_latency, cursor, trace_name, elm) {
155     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
156     link_CM02_t link = xbt_dict_get_or_null(surf_network_model->resource_set, elm);
157
158     xbt_assert2(link, "Cannot connect trace %s to link %s: link undefined",
159                 trace_name, elm);
160     xbt_assert2(trace, "Cannot connect trace %s to link %s: trace undefined",
161                 trace_name, elm);
162
163     link->lat_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
164   }
165 }
166
167 static void define_callbacks(const char *file)
168 {
169   /* Figuring out the network links */
170   surfxml_add_callback(STag_surfxml_link_cb_list, &parse_link_init);
171   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_traces);
172 }
173
174 static int resource_used(void *resource_id)
175 {
176   return lmm_constraint_used(network_maxmin_system,
177                              ((link_CM02_t) resource_id)->constraint);
178 }
179
180 static int action_unref(surf_action_t action)
181 {
182   action->refcount--;
183   if (!action->refcount) {
184     xbt_swag_remove(action, action->state_set);
185     if (((surf_action_network_CM02_t) action)->variable)
186       lmm_variable_free(network_maxmin_system,
187                         ((surf_action_network_CM02_t) action)->variable);
188     free(action);
189     return 1;
190   }
191   return 0;
192 }
193
194 static void action_cancel(surf_action_t action)
195 {
196   return;
197 }
198
199 static void action_recycle(surf_action_t action)
200 {
201   return;
202 }
203
204 static double share_resources(double now)
205 {
206   s_surf_action_network_CM02_t s_action;
207   surf_action_network_CM02_t action = NULL;
208   xbt_swag_t running_actions = surf_network_model->states.running_action_set;
209   double min;
210
211   min = generic_maxmin_share_resources(running_actions,
212                                        xbt_swag_offset(s_action,
213                                                        variable),
214                                        network_maxmin_system, network_solve);
215
216 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + xbt_swag_offset(s_action, variable)  )))
217
218   xbt_swag_foreach(action, running_actions) {
219     if (action->latency > 0) {
220       if (min < 0)
221         min = action->latency;
222       else if (action->latency < min)
223         min = action->latency;
224     }
225   }
226
227   return min;
228 }
229
230 static void update_actions_state(double now, double delta)
231 {
232   double deltap = 0.0;
233   surf_action_network_CM02_t action = NULL;
234   surf_action_network_CM02_t next_action = NULL;
235   xbt_swag_t running_actions = surf_network_model->states.running_action_set;
236   /*
237      xbt_swag_t failed_actions =
238      surf_network_model->states.failed_action_set;
239    */
240
241   xbt_swag_foreach_safe(action, next_action, running_actions) {
242     deltap = delta;
243     if (action->latency > 0) {
244       if (action->latency > deltap) {
245         double_update(&(action->latency), deltap);
246         deltap = 0.0;
247       } else {
248         double_update(&(deltap), action->latency);
249         action->latency = 0.0;
250       }
251       if ((action->latency == 0.0) && !(action->suspended))
252         lmm_update_variable_weight(network_maxmin_system, action->variable,
253                                    action->weight);
254     }
255     double_update(&(action->generic_action.remains),
256                   lmm_variable_getvalue(action->variable) * deltap);
257     if (action->generic_action.max_duration != NO_MAX_DURATION)
258       double_update(&(action->generic_action.max_duration), delta);
259
260     if ((action->generic_action.remains <= 0) &&
261         (lmm_get_variable_weight(action->variable) > 0)) {
262       action->generic_action.finish = surf_get_clock();
263       surf_network_model->action_state_set((surf_action_t) action, SURF_ACTION_DONE);
264     } else if ((action->generic_action.max_duration != NO_MAX_DURATION) &&
265                (action->generic_action.max_duration <= 0)) {
266       action->generic_action.finish = surf_get_clock();
267       surf_network_model->action_state_set((surf_action_t) action, SURF_ACTION_DONE);
268     }
269   }
270
271   return;
272 }
273
274 static void update_resource_state(void *id,
275                                   tmgr_trace_event_t event_type,
276                                   double value, double date)
277 {
278   link_CM02_t nw_link = id;
279   /*   printf("[" "%lg" "] Asking to update network card \"%s\" with value " */
280   /*     "%lg" " for event %p\n", surf_get_clock(), nw_link->name, */
281   /*     value, event_type); */
282
283   if (event_type == nw_link->bw_event) {
284     double delta =
285       weight_S_parameter / value - weight_S_parameter / nw_link->bw_current;
286     lmm_variable_t var = NULL;
287     lmm_element_t elem = NULL;
288     surf_action_network_CM02_t action = NULL;
289
290     nw_link->bw_current = value;
291     lmm_update_constraint_bound(network_maxmin_system, nw_link->constraint,
292                                 bandwidth_factor * nw_link->bw_current);
293     if (weight_S_parameter > 0) {
294       while ((var = lmm_get_var_from_cnst
295               (network_maxmin_system, nw_link->constraint, &elem))) {
296         action = lmm_variable_id(var);
297         action->weight += delta;
298         if (!(action->suspended))
299           lmm_update_variable_weight(network_maxmin_system, action->variable,
300                                      action->weight);
301       }
302     }
303   } else if (event_type == nw_link->lat_event) {
304     double delta = value - nw_link->lat_current;
305     lmm_variable_t var = NULL;
306     lmm_element_t elem = NULL;
307     surf_action_network_CM02_t action = NULL;
308
309     nw_link->lat_current = value;
310     while ((var = lmm_get_var_from_cnst
311             (network_maxmin_system, nw_link->constraint, &elem))) {
312       action = lmm_variable_id(var);
313       action->lat_current += delta;
314       action->weight += delta;
315       if (action->rate < 0)
316         lmm_update_variable_bound(network_maxmin_system, action->variable,
317                                   sg_tcp_gamma / (2.0 * action->lat_current));
318       else
319         lmm_update_variable_bound(network_maxmin_system, action->variable,
320                                   min(action->rate,
321                                       sg_tcp_gamma / (2.0 *
322                                                       action->lat_current)));
323       if (!(action->suspended))
324         lmm_update_variable_weight(network_maxmin_system, action->variable,
325                                    action->weight);
326
327     }
328   } else if (event_type == nw_link->state_event) {
329     if (value > 0)
330       nw_link->state_current = SURF_LINK_ON;
331     else {
332       lmm_constraint_t cnst = nw_link->constraint;
333       lmm_variable_t var = NULL;
334       lmm_element_t elem = NULL;
335
336       nw_link->state_current = SURF_LINK_OFF;
337       while ((var = lmm_get_var_from_cnst
338               (network_maxmin_system, cnst, &elem))) {
339         surf_action_t action = lmm_variable_id(var);
340
341         if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
342             surf_action_state_get(action) == SURF_ACTION_READY) {
343           action->finish = date;
344           surf_network_model->action_state_set(action, SURF_ACTION_FAILED);
345         }
346       }
347     }
348   } else {
349     CRITICAL0("Unknown event ! \n");
350     xbt_abort();
351   }
352
353   return;
354 }
355
356 static surf_action_t communicate(const char *src_name, const char *dst_name,int src, int dst, double size,
357                                  double rate)
358 {
359   surf_action_network_CM02_t action = NULL;
360   /* LARGE PLATFORMS HACK:
361      Add a link_CM02_t *link and a int link_nb to network_card_CM02_t. It will represent local links for this node
362      Use the cluster_id for ->id */
363   xbt_dynar_t route = used_routing->get_route(src, dst);
364   /* LARGE PLATFORMS HACK:
365      total_route_size = route_size + src->link_nb + dst->nb */
366   unsigned int i;
367
368   XBT_IN4("(%s,%s,%g,%g)", src_name, dst_name, size, rate);
369   /* LARGE PLATFORMS HACK:
370      assert on total_route_size */
371   xbt_assert2(xbt_dynar_length(route),
372               "You're trying to send data from %s to %s but there is no connection between these two hosts.",
373               src_name, dst_name);
374
375   action = xbt_new0(s_surf_action_network_CM02_t, 1);
376
377   action->generic_action.refcount = 1;
378   action->generic_action.cost = size;
379   action->generic_action.remains = size;
380   action->generic_action.max_duration = NO_MAX_DURATION;
381   action->generic_action.start = surf_get_clock();
382   action->generic_action.finish = -1.0;
383   action->generic_action.model_type = surf_network_model;
384   action->suspended = 0;        /* Should be useless because of the
385                                    calloc but it seems to help valgrind... */
386   action->generic_action.state_set =
387     surf_network_model->states.running_action_set;
388
389   link_CM02_t link;
390   xbt_dynar_foreach(route,i,link) {
391     if (link->state_current == SURF_LINK_OFF) {
392       action->generic_action.state_set =
393         surf_network_model->states.failed_action_set;
394       break;
395     }
396   }
397
398   xbt_swag_insert(action, action->generic_action.state_set);
399   action->rate = rate;
400
401   action->latency = 0.0;
402   action->weight = 0.0;
403   xbt_dynar_foreach(route,i,link) {
404     action->latency += link->lat_current;
405     action->weight +=
406       link->lat_current + weight_S_parameter / link->bw_current;
407   }
408   /* LARGE PLATFORMS HACK:
409      Add src->link and dst->link latencies */
410   action->lat_current = action->latency;
411   action->latency *= latency_factor;
412
413   /* LARGE PLATFORMS HACK:
414      lmm_variable_new(..., total_route_size) */
415   if (action->latency > 0)
416     action->variable =
417       lmm_variable_new(network_maxmin_system, action, 0.0, -1.0, xbt_dynar_length(route));
418   else
419     action->variable =
420       lmm_variable_new(network_maxmin_system, action, 1.0, -1.0, xbt_dynar_length(route));
421
422   if (action->rate < 0) {
423     if (action->lat_current > 0)
424       lmm_update_variable_bound(network_maxmin_system, action->variable,
425                                 sg_tcp_gamma / (2.0 * action->lat_current));
426     else
427       lmm_update_variable_bound(network_maxmin_system, action->variable,
428                                 -1.0);
429   } else {
430     if (action->lat_current > 0)
431       lmm_update_variable_bound(network_maxmin_system, action->variable,
432                                 min(action->rate,
433                                     sg_tcp_gamma / (2.0 *
434                                                     action->lat_current)));
435     else
436       lmm_update_variable_bound(network_maxmin_system, action->variable,
437                                 action->rate);
438   }
439
440   xbt_dynar_foreach(route,i,link) {
441     lmm_expand(network_maxmin_system, link->constraint,
442                action->variable, 1.0);
443   }
444   /* LARGE PLATFORMS HACK:
445      expand also with src->link and dst->link */
446
447   XBT_OUT;
448
449   return (surf_action_t) action;
450 }
451
452 static double get_link_bandwidth(const void *link)
453 {
454   return ((link_CM02_t) link)->bw_current;
455 }
456
457 static double get_link_latency(const void *link)
458 {
459   return ((link_CM02_t) link)->lat_current;
460 }
461
462 static int link_shared(const void *link)
463 {
464   return lmm_constraint_is_shared(((link_CM02_t) link)->constraint);
465 }
466
467 static xbt_dict_t get_properties(void *link)
468 {
469   return ((link_CM02_t) link)->properties;
470 }
471
472 static void action_suspend(surf_action_t action)
473 {
474   ((surf_action_network_CM02_t) action)->suspended = 1;
475   lmm_update_variable_weight(network_maxmin_system,
476                              ((surf_action_network_CM02_t) action)->variable,
477                              0.0);
478 }
479
480 static void action_resume(surf_action_t action)
481 {
482   if (((surf_action_network_CM02_t) action)->suspended) {
483     lmm_update_variable_weight(network_maxmin_system,
484                                ((surf_action_network_CM02_t)
485                                 action)->variable,
486                                ((surf_action_network_CM02_t) action)->weight);
487     ((surf_action_network_CM02_t) action)->suspended = 0;
488   }
489 }
490
491 static int action_is_suspended(surf_action_t action)
492 {
493   return ((surf_action_network_CM02_t) action)->suspended;
494 }
495
496 static void action_set_max_duration(surf_action_t action, double duration)
497 {
498   action->max_duration = duration;
499 }
500
501 static void finalize(void)
502 {
503   surf_model_exit(surf_network_model);
504   surf_network_model = NULL;
505
506   used_routing->finalize();
507   host_count = 0;
508   lmm_system_free(network_maxmin_system);
509   network_maxmin_system = NULL;
510 }
511
512 static void surf_network_model_init_internal(void)
513 {
514   surf_network_model = surf_model_init();
515
516   surf_network_model->name = "network";
517   surf_network_model->action_unref = action_unref;
518   surf_network_model->action_cancel = action_cancel;
519   surf_network_model->action_recycle = action_recycle;
520
521   surf_network_model->model_private->resource_used = resource_used;
522   surf_network_model->model_private->share_resources = share_resources;
523   surf_network_model->model_private->update_actions_state =
524     update_actions_state;
525   surf_network_model->model_private->update_resource_state =
526     update_resource_state;
527   surf_network_model->model_private->finalize = finalize;
528
529   surf_network_model->suspend = action_suspend;
530   surf_network_model->resume = action_resume;
531   surf_network_model->is_suspended = action_is_suspended;
532   surf_cpu_model->set_max_duration = action_set_max_duration;
533
534   surf_network_model->extension.network.communicate = communicate;
535   surf_network_model->extension.network.get_link_bandwidth =
536     get_link_bandwidth;
537   surf_network_model->extension.network.get_link_latency = get_link_latency;
538   surf_network_model->extension.network.link_shared = link_shared;
539
540   surf_network_model->get_properties = get_properties;
541
542   if (!network_maxmin_system)
543     network_maxmin_system = lmm_system_new();
544
545   routing_model_full_create(sizeof(link_CM02_t),
546       link_new(xbt_strdup("__loopback__"),
547           498000000, NULL, 0.000015, NULL,
548           SURF_LINK_ON, NULL, SURF_LINK_FATPIPE, NULL));
549 }
550
551 /************************************************************************/
552 /* New model based on optimizations discussed during this thesis        */
553 /************************************************************************/
554 void surf_network_model_init_LegrandVelho(const char *filename)
555 {
556
557   if (surf_network_model)
558     return;
559   surf_network_model_init_internal();
560   define_callbacks(filename);
561   xbt_dynar_push(model_list, &surf_network_model);
562   network_solve = lmm_solve;
563
564   latency_factor = 10.4;
565   bandwidth_factor = 0.92;
566   weight_S_parameter = 8775;
567
568   update_model_description(surf_network_model_description,
569                            "LegrandVelho", surf_network_model);
570 }
571
572 /***************************************************************************/
573 /* The nice TCP sharing model designed by Loris Marchal and Henri Casanova */
574 /***************************************************************************/
575 /* @TechReport{      rr-lip2002-40, */
576 /*   author        = {Henri Casanova and Loris Marchal}, */
577 /*   institution   = {LIP}, */
578 /*   title         = {A Network Model for Simulation of Grid Application}, */
579 /*   number        = {2002-40}, */
580 /*   month         = {oct}, */
581 /*   year          = {2002} */
582 /* } */
583 void surf_network_model_init_CM02(const char *filename)
584 {
585
586   if (surf_network_model)
587     return;
588   surf_network_model_init_internal();
589   define_callbacks(filename);
590   xbt_dynar_push(model_list, &surf_network_model);
591   network_solve = lmm_solve;
592
593   update_model_description(surf_network_model_description,
594                            "CM02", surf_network_model);
595 }
596
597 void surf_network_model_init_Reno(const char *filename)
598 {
599   if (surf_network_model)
600     return;
601   surf_network_model_init_internal();
602   define_callbacks(filename);
603
604   xbt_dynar_push(model_list, &surf_network_model);
605   lmm_set_default_protocol_function(func_reno_f, func_reno_fp, func_reno_fpi);
606   network_solve = lagrange_solve;
607
608   latency_factor = 10.4;
609   bandwidth_factor = 0.92;
610   weight_S_parameter = 8775;
611
612   update_model_description(surf_network_model_description,
613                            "Reno", surf_network_model);
614 }
615
616
617 void surf_network_model_init_Reno2(const char *filename)
618 {
619   if (surf_network_model)
620     return;
621   surf_network_model_init_internal();
622   define_callbacks(filename);
623
624   xbt_dynar_push(model_list, &surf_network_model);
625   lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp,
626                                     func_reno2_fpi);
627   network_solve = lagrange_solve;
628
629   latency_factor = 10.4;
630   bandwidth_factor = 0.92;
631   weight_S_parameter = 8775;
632
633   update_model_description(surf_network_model_description,
634                            "Reno2", surf_network_model);
635 }
636
637 void surf_network_model_init_Vegas(const char *filename)
638 {
639   if (surf_network_model)
640     return;
641   surf_network_model_init_internal();
642   define_callbacks(filename);
643
644   xbt_dynar_push(model_list, &surf_network_model);
645   lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp,
646                                     func_vegas_fpi);
647   network_solve = lagrange_solve;
648
649   latency_factor = 10.4;
650   bandwidth_factor = 0.92;
651   weight_S_parameter = 8775;
652
653   update_model_description(surf_network_model_description,
654                            "Vegas", surf_network_model);
655 }
656
657 #ifdef HAVE_SDP
658 void surf_network_model_init_SDP(const char *filename)
659 {
660   if (surf_network_model)
661     return;
662   surf_network_model_init_internal();
663   define_callbacks(filename);
664
665   xbt_dynar_push(model_list, &surf_network_model);
666   network_solve = sdp_solve;
667
668   update_model_description(surf_network_model_description,
669                            "SDP", surf_network_model);
670 }
671 #endif