Logo AND Algorithmique Numérique Distribuée

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