Logo AND Algorithmique Numérique Distribuée

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