Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
5879b62f694c478944a21ed9a2e896565ab54238
[simgrid.git] / src / surf / network.c
1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "network_private.h"
8 #include "xbt/log.h"
9 #include "xbt/str.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network, surf,
12                                 "Logging specific to the SURF network module");
13
14 surf_model_t surf_network_model = NULL;
15 static lmm_system_t network_maxmin_system = NULL;
16 static void (*network_solve) (lmm_system_t) = NULL;
17
18 double sg_latency_factor = 1.0; /* default value; can be set by model or from command line */
19 double sg_bandwidth_factor = 1.0;       /* default value; can be set by model or from command line */
20 double sg_weight_S_parameter = 0.0;     /* default value; can be set by model or from command line */
21
22 double sg_tcp_gamma = 0.0;
23 int sg_network_fullduplex = 0;
24
25
26 /******************************************************************************/
27 /*                           Factors callbacks                                */
28 /******************************************************************************/
29 static double constant_latency_factor(double size)
30 {
31   return sg_latency_factor;
32 }
33
34 static double constant_bandwidth_factor(double size)
35 {
36   return sg_bandwidth_factor;
37 }
38
39 static double constant_bandwidth_constraint(double rate, double bound,
40                                             double size)
41 {
42   return rate;
43 }
44
45 /**********************/
46 /*   SMPI callbacks   */
47 /**********************/
48 static double smpi_latency_factor(double size)
49 {
50   /* 1 B <= size <= 1 KiB */
51   if (size <= 1024.0) {
52     return 1.0056;
53   }
54
55   /* 2 KiB <= size <= 32 KiB */
56   if (size <= 32768.0) {
57     return 1.8805;
58   }
59
60   /* 64 KiB <= size <= 4 MiB */
61   return 22.7111;
62 }
63
64 static double smpi_bandwidth_factor(double size)
65 {
66   /* 1 B <= size <= 1 KiB */
67   if (size <= 1024.0) {
68     return 0.2758;
69   }
70
71   /* 2 KiB <= size <= 32 KiB */
72   if (size <= 32768.0) {
73     return 0.5477;
74   }
75
76   /* 64 KiB <= size <= 4 MiB */
77   return 0.9359;
78 }
79
80 static double smpi_bandwidth_constraint(double rate, double bound,
81                                         double size)
82 {
83   return rate < 0 ? bound : min(bound, rate * smpi_bandwidth_factor(size));
84 }
85
86
87 static double (*latency_factor_callback) (double) =
88     &constant_latency_factor;
89 static double (*bandwidth_factor_callback) (double) =
90     &constant_bandwidth_factor;
91 static double (*bandwidth_constraint_callback) (double, double, double) =
92     &constant_bandwidth_constraint;
93
94
95 static link_CM02_t net_link_new(char *name,
96                                 double bw_initial,
97                                 tmgr_trace_t bw_trace,
98                                 double lat_initial,
99                                 tmgr_trace_t lat_trace,
100                                 e_surf_resource_state_t
101                                 state_initial,
102                                 tmgr_trace_t state_trace,
103                                 e_surf_link_sharing_policy_t
104                                 policy, xbt_dict_t properties)
105 {
106   link_CM02_t nw_link = (link_CM02_t)
107       surf_resource_lmm_new(sizeof(s_link_CM02_t),
108                             surf_network_model, name, properties,
109                             network_maxmin_system,
110                             sg_bandwidth_factor * bw_initial,
111                             history,
112                             state_initial, state_trace,
113                             bw_initial, bw_trace);
114
115   xbt_assert1(!xbt_dict_get_or_null
116               (surf_network_model->resource_set, name),
117               "Link '%s' declared several times in the platform file.",
118               name);
119
120   nw_link->lat_current = lat_initial;
121   if (lat_trace)
122     nw_link->lat_event =
123         tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
124
125   if (policy == SURF_LINK_FATPIPE)
126     lmm_constraint_shared(nw_link->lmm_resource.constraint);
127
128   xbt_dict_set(surf_network_model->resource_set, name, nw_link,
129                surf_resource_free);
130 #ifdef HAVE_TRACING
131   TRACE_surf_link_declaration(nw_link, name, bw_initial, lat_initial);
132 #endif
133
134   return nw_link;
135 }
136
137 static void net_parse_link_init(void)
138 {
139   char *name_link;
140   double bw_initial;
141   tmgr_trace_t bw_trace;
142   double lat_initial;
143   tmgr_trace_t lat_trace;
144   e_surf_resource_state_t state_initial_link = SURF_RESOURCE_ON;
145   e_surf_link_sharing_policy_t policy_initial_link = SURF_LINK_SHARED;
146   tmgr_trace_t state_trace;
147
148   name_link = xbt_strdup(A_surfxml_link_id);
149   surf_parse_get_double(&bw_initial, A_surfxml_link_bandwidth);
150   bw_trace = tmgr_trace_new(A_surfxml_link_bandwidth_file);
151   surf_parse_get_double(&lat_initial, A_surfxml_link_latency);
152   lat_trace = tmgr_trace_new(A_surfxml_link_latency_file);
153
154   xbt_assert0((A_surfxml_link_state == A_surfxml_link_state_ON)
155               || (A_surfxml_link_state ==
156                   A_surfxml_link_state_OFF), "Invalid state");
157   if (A_surfxml_link_state == A_surfxml_link_state_ON)
158     state_initial_link = SURF_RESOURCE_ON;
159   else if (A_surfxml_link_state == A_surfxml_link_state_OFF)
160     state_initial_link = SURF_RESOURCE_OFF;
161
162   if (A_surfxml_link_sharing_policy ==
163       A_surfxml_link_sharing_policy_SHARED)
164     policy_initial_link = SURF_LINK_SHARED;
165   else if (A_surfxml_link_sharing_policy ==
166            A_surfxml_link_sharing_policy_FATPIPE)
167     policy_initial_link = SURF_LINK_FATPIPE;
168
169   state_trace = tmgr_trace_new(A_surfxml_link_state_file);
170
171   net_link_new(name_link, bw_initial, bw_trace,
172                lat_initial, lat_trace, state_initial_link, state_trace,
173                policy_initial_link, xbt_dict_new());
174
175 }
176
177 static void net_create_resource(char *name,
178                                 double bw_initial,
179                                 tmgr_trace_t bw_trace,
180                                 double lat_initial,
181                                 tmgr_trace_t lat_trace,
182                                 e_surf_resource_state_t
183                                 state_initial,
184                                 tmgr_trace_t state_trace,
185                                 e_surf_link_sharing_policy_t policy,
186                                 xbt_dict_t properties)
187 {
188   net_link_new(name, bw_initial, bw_trace,
189                lat_initial, lat_trace, state_initial, state_trace,
190                policy, xbt_dict_new());
191 }
192
193 static void net_add_traces(void)
194 {
195   xbt_dict_cursor_t cursor = NULL;
196   char *trace_name, *elm;
197
198   static int called = 0;
199   if (called)
200     return;
201   called = 1;
202
203   /* connect all traces relative to network */
204   xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) {
205     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
206     link_CM02_t link =
207         xbt_dict_get_or_null(surf_network_model->resource_set, elm);
208
209     xbt_assert2(link, "Cannot connect trace %s to link %s: link undefined",
210                 trace_name, elm);
211     xbt_assert2(trace,
212                 "Cannot connect trace %s to link %s: trace undefined",
213                 trace_name, elm);
214
215     link->lmm_resource.state_event =
216         tmgr_history_add_trace(history, trace, 0.0, 0, link);
217   }
218
219   xbt_dict_foreach(trace_connect_list_bandwidth, cursor, trace_name, elm) {
220     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
221     link_CM02_t link =
222         xbt_dict_get_or_null(surf_network_model->resource_set, elm);
223
224     xbt_assert2(link, "Cannot connect trace %s to link %s: link undefined",
225                 trace_name, elm);
226     xbt_assert2(trace,
227                 "Cannot connect trace %s to link %s: trace undefined",
228                 trace_name, elm);
229
230     link->lmm_resource.power.event =
231         tmgr_history_add_trace(history, trace, 0.0, 0, link);
232   }
233
234   xbt_dict_foreach(trace_connect_list_latency, cursor, trace_name, elm) {
235     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
236     link_CM02_t link =
237         xbt_dict_get_or_null(surf_network_model->resource_set, elm);
238
239     xbt_assert2(link, "Cannot connect trace %s to link %s: link undefined",
240                 trace_name, elm);
241     xbt_assert2(trace,
242                 "Cannot connect trace %s to link %s: trace undefined",
243                 trace_name, elm);
244
245     link->lat_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
246   }
247 }
248
249 static void net_define_callbacks(const char *file)
250 {
251   /* Figuring out the network links */
252   surfxml_add_callback(STag_surfxml_link_cb_list, &net_parse_link_init);
253   surfxml_add_callback(ETag_surfxml_platform_cb_list, &net_add_traces);
254 }
255
256 static int net_resource_used(void *resource_id)
257 {
258   return lmm_constraint_used(network_maxmin_system,
259                              ((surf_resource_lmm_t)
260                               resource_id)->constraint);
261 }
262
263 static int net_action_unref(surf_action_t action)
264 {
265   action->refcount--;
266   if (!action->refcount) {
267     xbt_swag_remove(action, action->state_set);
268     if (((surf_action_network_CM02_t) action)->variable)
269       lmm_variable_free(network_maxmin_system,
270                         ((surf_action_network_CM02_t) action)->variable);
271 #ifdef HAVE_TRACING
272     xbt_free(((surf_action_network_CM02_t) action)->src_name);
273     xbt_free(((surf_action_network_CM02_t) action)->dst_name);
274     if (action->category)
275       xbt_free(action->category);
276 #endif
277     free(action);
278     return 1;
279   }
280   return 0;
281 }
282
283 static void net_action_cancel(surf_action_t action)
284 {
285   surf_network_model->action_state_set(action, SURF_ACTION_FAILED);
286 }
287
288 void net_action_recycle(surf_action_t action)
289 {
290   return;
291 }
292
293 #ifdef HAVE_LATENCY_BOUND_TRACKING
294 int net_get_link_latency_limited(surf_action_t action)
295 {
296   return action->latency_limited;
297 }
298 #endif
299
300 double net_action_get_remains(surf_action_t action)
301 {
302   return action->remains;
303 }
304
305 static double net_share_resources(double now)
306 {
307   s_surf_action_network_CM02_t s_action;
308   surf_action_network_CM02_t action = NULL;
309   xbt_swag_t running_actions =
310       surf_network_model->states.running_action_set;
311   double min;
312
313   min = generic_maxmin_share_resources(running_actions,
314                                        xbt_swag_offset(s_action,
315                                                        variable),
316                                        network_maxmin_system,
317                                        network_solve);
318
319 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + xbt_swag_offset(s_action, variable)  )))
320
321   xbt_swag_foreach(action, running_actions) {
322 #ifdef HAVE_LATENCY_BOUND_TRACKING
323     if (lmm_is_variable_limited_by_latency(action->variable)) {
324       (action->generic_action).latency_limited = 1;
325     } else {
326       (action->generic_action).latency_limited = 0;
327     }
328 #endif
329     if (action->latency > 0) {
330       if (min < 0)
331         min = action->latency;
332       else if (action->latency < min)
333         min = action->latency;
334     }
335   }
336
337   return min;
338 }
339
340 static void net_update_actions_state(double now, double delta)
341 {
342   double deltap = 0.0;
343   surf_action_network_CM02_t action = NULL;
344   surf_action_network_CM02_t next_action = NULL;
345   xbt_swag_t running_actions =
346       surf_network_model->states.running_action_set;
347   /*
348      xbt_swag_t failed_actions =
349      surf_network_model->states.failed_action_set;
350    */
351
352   xbt_swag_foreach_safe(action, next_action, running_actions) {
353     deltap = delta;
354     if (action->latency > 0) {
355       if (action->latency > deltap) {
356         double_update(&(action->latency), deltap);
357         deltap = 0.0;
358       } else {
359         double_update(&(deltap), action->latency);
360         action->latency = 0.0;
361       }
362       if ((action->latency == 0.0) && !(action->suspended))
363         lmm_update_variable_weight(network_maxmin_system, action->variable,
364                                    action->weight);
365     }
366 #ifdef HAVE_TRACING
367     xbt_dynar_t route =
368         global_routing->get_route(action->src_name, action->dst_name);
369     link_CM02_t link;
370     unsigned int i;
371     xbt_dynar_foreach(route, i, link) {
372       TRACE_surf_link_set_utilization(link,
373                                       action->generic_action.data,
374                                       (surf_action_t) action,
375                                       lmm_variable_getvalue
376                                       (action->variable), now - delta,
377                                       delta);
378     }
379 #endif
380     double_update(&(action->generic_action.remains),
381                   lmm_variable_getvalue(action->variable) * deltap);
382     if (action->generic_action.max_duration != NO_MAX_DURATION)
383       double_update(&(action->generic_action.max_duration), delta);
384
385     if ((action->generic_action.remains <= 0) &&
386         (lmm_get_variable_weight(action->variable) > 0)) {
387       action->generic_action.finish = surf_get_clock();
388       surf_network_model->action_state_set((surf_action_t) action,
389                                            SURF_ACTION_DONE);
390     } else if ((action->generic_action.max_duration != NO_MAX_DURATION)
391                && (action->generic_action.max_duration <= 0)) {
392       action->generic_action.finish = surf_get_clock();
393       surf_network_model->action_state_set((surf_action_t) action,
394                                            SURF_ACTION_DONE);
395     }
396   }
397
398   return;
399 }
400
401 static void net_update_resource_state(void *id,
402                                       tmgr_trace_event_t event_type,
403                                       double value, double date)
404 {
405   link_CM02_t nw_link = id;
406   /*   printf("[" "%lg" "] Asking to update network card \"%s\" with value " */
407   /*     "%lg" " for event %p\n", surf_get_clock(), nw_link->name, */
408   /*     value, event_type); */
409
410   if (event_type == nw_link->lmm_resource.power.event) {
411     double delta =
412         sg_weight_S_parameter / value - sg_weight_S_parameter /
413         (nw_link->lmm_resource.power.peak *
414          nw_link->lmm_resource.power.scale);
415     lmm_variable_t var = NULL;
416     lmm_element_t elem = NULL;
417     surf_action_network_CM02_t action = NULL;
418
419     nw_link->lmm_resource.power.peak = value;
420     lmm_update_constraint_bound(network_maxmin_system,
421                                 nw_link->lmm_resource.constraint,
422                                 sg_bandwidth_factor *
423                                 (nw_link->lmm_resource.power.peak *
424                                  nw_link->lmm_resource.power.scale));
425 #ifdef HAVE_TRACING
426     TRACE_surf_link_set_bandwidth(date, nw_link,
427                                   sg_bandwidth_factor *
428                                   (nw_link->lmm_resource.power.peak *
429                                    nw_link->lmm_resource.power.scale));
430 #endif
431     if (sg_weight_S_parameter > 0) {
432       while ((var = lmm_get_var_from_cnst
433               (network_maxmin_system, nw_link->lmm_resource.constraint,
434                &elem))) {
435         action = lmm_variable_id(var);
436         action->weight += delta;
437         if (!(action->suspended))
438           lmm_update_variable_weight(network_maxmin_system,
439                                      action->variable, action->weight);
440       }
441     }
442     if (tmgr_trace_event_free(event_type))
443       nw_link->lmm_resource.power.event = NULL;
444   } else if (event_type == nw_link->lat_event) {
445     double delta = value - nw_link->lat_current;
446     lmm_variable_t var = NULL;
447     lmm_element_t elem = NULL;
448     surf_action_network_CM02_t action = NULL;
449
450     nw_link->lat_current = value;
451     while ((var = lmm_get_var_from_cnst
452             (network_maxmin_system, nw_link->lmm_resource.constraint,
453              &elem))) {
454       action = lmm_variable_id(var);
455       action->lat_current += delta;
456       action->weight += delta;
457       if (action->rate < 0)
458         lmm_update_variable_bound(network_maxmin_system, action->variable,
459                                   sg_tcp_gamma / (2.0 *
460                                                   action->lat_current));
461       else {
462         lmm_update_variable_bound(network_maxmin_system, action->variable,
463                                   min(action->rate,
464                                       sg_tcp_gamma / (2.0 *
465                                                       action->lat_current)));
466
467         if (action->rate < sg_tcp_gamma / (2.0 * action->lat_current)) {
468           INFO0("Flow is limited BYBANDWIDTH");
469         } else {
470           INFO1("Flow is limited BYLATENCY, latency of flow is %f",
471                 action->lat_current);
472         }
473       }
474       if (!(action->suspended))
475         lmm_update_variable_weight(network_maxmin_system, action->variable,
476                                    action->weight);
477
478     }
479     if (tmgr_trace_event_free(event_type))
480       nw_link->lat_event = NULL;
481   } else if (event_type == nw_link->lmm_resource.state_event) {
482     if (value > 0)
483       nw_link->lmm_resource.state_current = SURF_RESOURCE_ON;
484     else {
485       lmm_constraint_t cnst = nw_link->lmm_resource.constraint;
486       lmm_variable_t var = NULL;
487       lmm_element_t elem = NULL;
488
489       nw_link->lmm_resource.state_current = SURF_RESOURCE_OFF;
490       while ((var = lmm_get_var_from_cnst
491               (network_maxmin_system, cnst, &elem))) {
492         surf_action_t action = lmm_variable_id(var);
493
494         if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
495             surf_action_state_get(action) == SURF_ACTION_READY) {
496           action->finish = date;
497           surf_network_model->action_state_set(action, SURF_ACTION_FAILED);
498         }
499       }
500     }
501     if (tmgr_trace_event_free(event_type))
502       nw_link->lmm_resource.state_event = NULL;
503   } else {
504     CRITICAL0("Unknown event ! \n");
505     xbt_abort();
506   }
507
508   return;
509 }
510
511
512 static surf_action_t net_communicate(const char *src_name,
513                                      const char *dst_name, double size,
514                                      double rate)
515 {
516   unsigned int i;
517   link_CM02_t link;
518   int failed = 0;
519   surf_action_network_CM02_t action = NULL;
520   double bandwidth_bound;
521   /* LARGE PLATFORMS HACK:
522      Add a link_CM02_t *link and a int link_nb to network_card_CM02_t. It will represent local links for this node
523      Use the cluster_id for ->id */
524
525   xbt_dynar_t route = global_routing->get_route(src_name, dst_name);
526   xbt_dynar_t back_route = NULL;
527   int constraints_per_variable = 0;
528
529   if (sg_network_fullduplex == 1) {
530     back_route = global_routing->get_route(src_name, dst_name);
531   }
532
533   /* LARGE PLATFORMS HACK:
534      total_route_size = route_size + src->link_nb + dst->nb */
535
536   XBT_IN4("(%s,%s,%g,%g)", src_name, dst_name, size, rate);
537   /* LARGE PLATFORMS HACK:
538      assert on total_route_size */
539   xbt_assert2(xbt_dynar_length(route),
540               "You're trying to send data from %s to %s but there is no connection between these two hosts.",
541               src_name, dst_name);
542
543   xbt_dynar_foreach(route, i, link) {
544     if (link->lmm_resource.state_current == SURF_RESOURCE_OFF) {
545       failed = 1;
546       break;
547     }
548   }
549   action =
550       surf_action_new(sizeof(s_surf_action_network_CM02_t), size,
551                       surf_network_model, failed);
552 #ifdef HAVE_LATENCY_BOUND_TRACKING
553   (action->generic_action).latency_limited = 0;
554 #endif
555
556   xbt_swag_insert(action, action->generic_action.state_set);
557   action->rate = rate;
558
559   action->latency = 0.0;
560   action->weight = 0.0;
561   bandwidth_bound = -1.0;
562   xbt_dynar_foreach(route, i, link) {
563     action->latency += link->lat_current;
564     action->weight +=
565         link->lat_current +
566         sg_weight_S_parameter /
567         (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
568     if (bandwidth_bound < 0.0)
569       bandwidth_bound =
570           (*bandwidth_factor_callback) (size) *
571           (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
572     else
573       bandwidth_bound =
574           min(bandwidth_bound,
575               (*bandwidth_factor_callback) (size) *
576               (link->lmm_resource.power.peak *
577                link->lmm_resource.power.scale));
578   }
579   /* LARGE PLATFORMS HACK:
580      Add src->link and dst->link latencies */
581   action->lat_current = action->latency;
582   action->latency *= (*latency_factor_callback) (size);
583   action->rate =
584       (*bandwidth_constraint_callback) (action->rate, bandwidth_bound,
585                                         size);
586
587   /* LARGE PLATFORMS HACK:
588      lmm_variable_new(..., total_route_size) */
589   if (back_route != NULL) {
590     constraints_per_variable =
591         xbt_dynar_length(route) + xbt_dynar_length(back_route);
592   } else {
593     constraints_per_variable = xbt_dynar_length(route);
594   }
595
596   if (action->latency > 0)
597     action->variable =
598         lmm_variable_new(network_maxmin_system, action, 0.0, -1.0,
599                          constraints_per_variable);
600   else
601     action->variable =
602         lmm_variable_new(network_maxmin_system, action, 1.0, -1.0,
603                          constraints_per_variable);
604
605   if (action->rate < 0) {
606     if (action->lat_current > 0)
607       lmm_update_variable_bound(network_maxmin_system, action->variable,
608                                 sg_tcp_gamma / (2.0 *
609                                                 action->lat_current));
610     else
611       lmm_update_variable_bound(network_maxmin_system, action->variable,
612                                 -1.0);
613   } else {
614     if (action->lat_current > 0)
615       lmm_update_variable_bound(network_maxmin_system, action->variable,
616                                 min(action->rate,
617                                     sg_tcp_gamma / (2.0 *
618                                                     action->lat_current)));
619     else
620       lmm_update_variable_bound(network_maxmin_system, action->variable,
621                                 action->rate);
622   }
623
624   xbt_dynar_foreach(route, i, link) {
625     lmm_expand(network_maxmin_system, link->lmm_resource.constraint,
626                action->variable, 1.0);
627   }
628
629   if (sg_network_fullduplex == 1) {
630     DEBUG1("Fullduplex active adding backward flow using 5%c", '%');
631     xbt_dynar_foreach(back_route, i, link) {
632       lmm_expand(network_maxmin_system, link->lmm_resource.constraint,
633                  action->variable, .05);
634     }
635   }
636   /* LARGE PLATFORMS HACK:
637      expand also with src->link and dst->link */
638 #ifdef HAVE_TRACING
639   action->src_name = xbt_new(char, strlen(src_name) + 1);
640   strncpy(action->src_name, src_name, strlen(src_name) + 1);
641
642   action->dst_name = xbt_new(char, strlen(dst_name) + 1);
643   strncpy(action->dst_name, dst_name, strlen(dst_name) + 1);
644 #endif
645
646   XBT_OUT;
647
648   return (surf_action_t) action;
649 }
650
651 static xbt_dynar_t net_get_route(const char *src, const char *dst)
652 {
653   return global_routing->get_route(src, dst);
654 }
655
656 static double net_get_link_bandwidth(const void *link)
657 {
658   surf_resource_lmm_t lmm = (surf_resource_lmm_t) link;
659   return lmm->power.peak * lmm->power.scale;
660 }
661
662 static double net_get_link_latency(const void *link)
663 {
664   return ((link_CM02_t) link)->lat_current;
665 }
666
667 static int net_link_shared(const void *link)
668 {
669   return
670       lmm_constraint_is_shared(((surf_resource_lmm_t) link)->constraint);
671 }
672
673 static void net_action_suspend(surf_action_t action)
674 {
675   ((surf_action_network_CM02_t) action)->suspended = 1;
676   lmm_update_variable_weight(network_maxmin_system,
677                              ((surf_action_network_CM02_t)
678                               action)->variable, 0.0);
679 }
680
681 static void net_action_resume(surf_action_t action)
682 {
683   if (((surf_action_network_CM02_t) action)->suspended) {
684     lmm_update_variable_weight(network_maxmin_system,
685                                ((surf_action_network_CM02_t)
686                                 action)->variable,
687                                ((surf_action_network_CM02_t)
688                                 action)->weight);
689     ((surf_action_network_CM02_t) action)->suspended = 0;
690   }
691 }
692
693 static int net_action_is_suspended(surf_action_t action)
694 {
695   return ((surf_action_network_CM02_t) action)->suspended;
696 }
697
698 void net_action_set_max_duration(surf_action_t action, double duration)
699 {
700   action->max_duration = duration;
701 }
702
703 static void net_finalize(void)
704 {
705   surf_model_exit(surf_network_model);
706   surf_network_model = NULL;
707
708   global_routing->finalize();
709
710   lmm_system_free(network_maxmin_system);
711   network_maxmin_system = NULL;
712 }
713
714 static void surf_network_model_init_internal(void)
715 {
716   surf_network_model = surf_model_init();
717
718   surf_network_model->name = "network";
719   surf_network_model->action_unref = net_action_unref;
720   surf_network_model->action_cancel = net_action_cancel;
721   surf_network_model->action_recycle = net_action_recycle;
722   surf_network_model->get_remains = net_action_get_remains;
723 #ifdef HAVE_LATENCY_BOUND_TRACKING
724   surf_network_model->get_latency_limited = net_get_link_latency_limited;
725 #endif
726
727   surf_network_model->model_private->resource_used = net_resource_used;
728   surf_network_model->model_private->share_resources = net_share_resources;
729   surf_network_model->model_private->update_actions_state =
730       net_update_actions_state;
731   surf_network_model->model_private->update_resource_state =
732       net_update_resource_state;
733   surf_network_model->model_private->finalize = net_finalize;
734
735   surf_network_model->suspend = net_action_suspend;
736   surf_network_model->resume = net_action_resume;
737   surf_network_model->is_suspended = net_action_is_suspended;
738   surf_cpu_model->set_max_duration = net_action_set_max_duration;
739
740   surf_network_model->extension.network.communicate = net_communicate;
741   surf_network_model->extension.network.get_route = net_get_route;
742   surf_network_model->extension.network.get_link_bandwidth =
743       net_get_link_bandwidth;
744   surf_network_model->extension.network.get_link_latency =
745       net_get_link_latency;
746   surf_network_model->extension.network.link_shared = net_link_shared;
747   surf_network_model->extension.network.add_traces = net_add_traces;
748   surf_network_model->extension.network.create_resource =
749       net_create_resource;
750
751   if (!network_maxmin_system)
752     network_maxmin_system = lmm_system_new();
753
754   routing_model_create(sizeof(link_CM02_t),
755                        net_link_new(xbt_strdup("__loopback__"),
756                                     498000000, NULL, 0.000015, NULL,
757                                     SURF_RESOURCE_ON, NULL,
758                                     SURF_LINK_FATPIPE, NULL));
759 }
760
761
762
763 /************************************************************************/
764 /* New model based on LV08 and experimental results of MPI ping-pongs   */
765 /************************************************************************/
766 void surf_network_model_init_SMPI(const char *filename)
767 {
768
769   if (surf_network_model)
770     return;
771   surf_network_model_init_internal();
772   latency_factor_callback = &smpi_latency_factor;
773   bandwidth_factor_callback = &smpi_bandwidth_factor;
774   bandwidth_constraint_callback = &smpi_bandwidth_constraint;
775   net_define_callbacks(filename);
776   xbt_dynar_push(model_list, &surf_network_model);
777   network_solve = lmm_solve;
778
779   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
780
781   update_model_description(surf_network_model_description,
782                            "SMPI", surf_network_model);
783 }
784
785 /************************************************************************/
786 /* New model based on optimizations discussed during this thesis        */
787 /************************************************************************/
788 void surf_network_model_init_LegrandVelho(const char *filename)
789 {
790
791   if (surf_network_model)
792     return;
793   surf_network_model_init_internal();
794   net_define_callbacks(filename);
795   xbt_dynar_push(model_list, &surf_network_model);
796   network_solve = lmm_solve;
797
798   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
799   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
800                             0.92);
801   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
802
803   update_model_description(surf_network_model_description,
804                            "LV08", surf_network_model);
805 }
806
807 /***************************************************************************/
808 /* The nice TCP sharing model designed by Loris Marchal and Henri Casanova */
809 /***************************************************************************/
810 /* @TechReport{      rr-lip2002-40, */
811 /*   author        = {Henri Casanova and Loris Marchal}, */
812 /*   institution   = {LIP}, */
813 /*   title         = {A Network Model for Simulation of Grid Application}, */
814 /*   number        = {2002-40}, */
815 /*   month         = {oct}, */
816 /*   year          = {2002} */
817 /* } */
818 void surf_network_model_init_CM02(const char *filename)
819 {
820
821   if (surf_network_model)
822     return;
823   surf_network_model_init_internal();
824   net_define_callbacks(filename);
825   xbt_dynar_push(model_list, &surf_network_model);
826   network_solve = lmm_solve;
827
828   update_model_description(surf_network_model_description,
829                            "CM02", surf_network_model);
830 }
831
832 void surf_network_model_init_Reno(const char *filename)
833 {
834   if (surf_network_model)
835     return;
836   surf_network_model_init_internal();
837   net_define_callbacks(filename);
838
839   xbt_dynar_push(model_list, &surf_network_model);
840   lmm_set_default_protocol_function(func_reno_f, func_reno_fp,
841                                     func_reno_fpi);
842   network_solve = lagrange_solve;
843
844   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
845   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
846                             0.92);
847   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
848
849   update_model_description(surf_network_model_description,
850                            "Reno", surf_network_model);
851 }
852
853
854 void surf_network_model_init_Reno2(const char *filename)
855 {
856   if (surf_network_model)
857     return;
858   surf_network_model_init_internal();
859   net_define_callbacks(filename);
860
861   xbt_dynar_push(model_list, &surf_network_model);
862   lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp,
863                                     func_reno2_fpi);
864   network_solve = lagrange_solve;
865
866   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
867   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
868                             0.92);
869   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S_parameter",
870                             8775);
871
872   update_model_description(surf_network_model_description,
873                            "Reno2", surf_network_model);
874 }
875
876 void surf_network_model_init_Vegas(const char *filename)
877 {
878   if (surf_network_model)
879     return;
880   surf_network_model_init_internal();
881   net_define_callbacks(filename);
882
883   xbt_dynar_push(model_list, &surf_network_model);
884   lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp,
885                                     func_vegas_fpi);
886   network_solve = lagrange_solve;
887
888   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
889   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
890                             0.92);
891   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
892
893   update_model_description(surf_network_model_description,
894                            "Vegas", surf_network_model);
895 }