Logo AND Algorithmique Numérique Distribuée

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