Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add a test trying to access the properties of a remote host -- it works
[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_length(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     xbt_free(action->category);
322 #endif
323     surf_action_free(&action);
324     return 1;
325   }
326   return 0;
327 }
328
329 static void net_action_cancel(surf_action_t action)
330 {
331   surf_network_model->action_state_set(action, SURF_ACTION_FAILED);
332 }
333
334 void net_action_recycle(surf_action_t action)
335 {
336   return;
337 }
338
339 #ifdef HAVE_LATENCY_BOUND_TRACKING
340 int net_get_link_latency_limited(surf_action_t action)
341 {
342   return action->latency_limited;
343 }
344 #endif
345
346 double net_action_get_remains(surf_action_t action)
347 {
348   return action->remains;
349 }
350
351 static double net_share_resources(double now)
352 {
353   s_surf_action_network_CM02_t s_action;
354   surf_action_network_CM02_t action = NULL;
355   xbt_swag_t running_actions =
356       surf_network_model->states.running_action_set;
357   double min;
358
359   min = generic_maxmin_share_resources(running_actions,
360                                        xbt_swag_offset(s_action,
361                                                        variable),
362                                        network_maxmin_system,
363                                        network_solve);
364
365 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + xbt_swag_offset(s_action, variable)  )))
366
367   xbt_swag_foreach(action, running_actions) {
368 #ifdef HAVE_LATENCY_BOUND_TRACKING
369     if (lmm_is_variable_limited_by_latency(action->variable)) {
370       (action->generic_action).latency_limited = 1;
371     } else {
372       (action->generic_action).latency_limited = 0;
373     }
374 #endif
375     if (action->latency > 0) {
376       if (min < 0)
377         min = action->latency;
378       else if (action->latency < min)
379         min = action->latency;
380     }
381   }
382
383   XBT_DEBUG("Min of share resources %f", min);
384
385   return min;
386 }
387
388 static void net_update_actions_state(double now, double delta)
389 {
390   double deltap = 0.0;
391   surf_action_network_CM02_t action = NULL;
392   surf_action_network_CM02_t next_action = NULL;
393   xbt_swag_t running_actions =
394       surf_network_model->states.running_action_set;
395   /*
396      xbt_swag_t failed_actions =
397      surf_network_model->states.failed_action_set;
398    */
399
400   xbt_swag_foreach_safe(action, next_action, running_actions) {
401     deltap = delta;
402     if (action->latency > 0) {
403       if (action->latency > deltap) {
404         double_update(&(action->latency), deltap);
405         deltap = 0.0;
406       } else {
407         double_update(&(deltap), action->latency);
408         action->latency = 0.0;
409       }
410       if ((action->latency == 0.0) && !(action->suspended))
411         lmm_update_variable_weight(network_maxmin_system, action->variable,
412                                    action->weight);
413     }
414 #ifdef HAVE_TRACING
415     if (TRACE_is_enabled()) {
416       xbt_dynar_t route=NULL;
417       routing_get_route_and_latency(action->src_name, action->dst_name,&route,NULL);
418       link_CM02_t link;
419       unsigned int i;
420       xbt_dynar_foreach(route, i, link) {
421         TRACE_surf_link_set_utilization(link->lmm_resource.generic_resource.name,
422                                         action->generic_action.data,
423                                         (surf_action_t) action,
424                                         lmm_variable_getvalue
425                                         (action->variable), now - delta,
426                                         delta);
427       }
428     }
429 #endif
430     if(!lmm_get_number_of_cnst_from_var(network_maxmin_system, action->variable)) {
431                                 /* There is actually no link used, hence an infinite bandwidth.
432                                  * This happens often when using models like vivaldi.
433                                  * In such case, just make sure that the action completes immediately.
434                                  */
435         double_update(&(action->generic_action.remains),
436                         action->generic_action.remains);
437     }
438     double_update(&(action->generic_action.remains),
439                   lmm_variable_getvalue(action->variable) * deltap);
440     if (action->generic_action.max_duration != NO_MAX_DURATION)
441       double_update(&(action->generic_action.max_duration), delta);
442
443     if ((action->generic_action.remains <= 0) &&
444         (lmm_get_variable_weight(action->variable) > 0)) {
445       action->generic_action.finish = surf_get_clock();
446       surf_network_model->action_state_set((surf_action_t) action,
447                                            SURF_ACTION_DONE);
448       gap_remove(action);
449     } else if ((action->generic_action.max_duration != NO_MAX_DURATION)
450                && (action->generic_action.max_duration <= 0)) {
451       action->generic_action.finish = surf_get_clock();
452       surf_network_model->action_state_set((surf_action_t) action,
453                                            SURF_ACTION_DONE);
454       gap_remove(action);
455     }
456   }
457
458   return;
459 }
460
461 static void net_update_resource_state(void *id,
462                                       tmgr_trace_event_t event_type,
463                                       double value, double date)
464 {
465   link_CM02_t nw_link = id;
466   /*   printf("[" "%lg" "] Asking to update network card \"%s\" with value " */
467   /*     "%lg" " for event %p\n", surf_get_clock(), nw_link->name, */
468   /*     value, event_type); */
469
470   if (event_type == nw_link->lmm_resource.power.event) {
471     double delta =
472         sg_weight_S_parameter / value - sg_weight_S_parameter /
473         (nw_link->lmm_resource.power.peak *
474          nw_link->lmm_resource.power.scale);
475     lmm_variable_t var = NULL;
476     lmm_element_t elem = NULL;
477     surf_action_network_CM02_t action = NULL;
478
479     nw_link->lmm_resource.power.peak = value;
480     lmm_update_constraint_bound(network_maxmin_system,
481                                 nw_link->lmm_resource.constraint,
482                                 sg_bandwidth_factor *
483                                 (nw_link->lmm_resource.power.peak *
484                                  nw_link->lmm_resource.power.scale));
485 #ifdef HAVE_TRACING
486     TRACE_surf_link_set_bandwidth(date, nw_link->lmm_resource.generic_resource.name,
487                                   sg_bandwidth_factor *
488                                   (nw_link->lmm_resource.power.peak *
489                                    nw_link->lmm_resource.power.scale));
490 #endif
491     if (sg_weight_S_parameter > 0) {
492       while ((var = lmm_get_var_from_cnst
493               (network_maxmin_system, nw_link->lmm_resource.constraint,
494                &elem))) {
495         action = lmm_variable_id(var);
496         action->weight += delta;
497         if (!(action->suspended))
498           lmm_update_variable_weight(network_maxmin_system,
499                                      action->variable, action->weight);
500       }
501     }
502     if (tmgr_trace_event_free(event_type))
503       nw_link->lmm_resource.power.event = NULL;
504   } else if (event_type == nw_link->lat_event) {
505     double delta = value - nw_link->lat_current;
506     lmm_variable_t var = NULL;
507     lmm_element_t elem = NULL;
508     surf_action_network_CM02_t action = NULL;
509
510     nw_link->lat_current = value;
511     while ((var = lmm_get_var_from_cnst
512             (network_maxmin_system, nw_link->lmm_resource.constraint,
513              &elem))) {
514       action = lmm_variable_id(var);
515       action->lat_current += delta;
516       action->weight += delta;
517       if (action->rate < 0)
518         lmm_update_variable_bound(network_maxmin_system, action->variable,
519                                   sg_tcp_gamma / (2.0 *
520                                                   action->lat_current));
521       else {
522         lmm_update_variable_bound(network_maxmin_system, action->variable,
523                                   min(action->rate,
524                                       sg_tcp_gamma / (2.0 *
525                                                       action->lat_current)));
526
527         if (action->rate < sg_tcp_gamma / (2.0 * action->lat_current)) {
528           XBT_INFO("Flow is limited BYBANDWIDTH");
529         } else {
530           XBT_INFO("Flow is limited BYLATENCY, latency of flow is %f",
531                 action->lat_current);
532         }
533       }
534       if (!(action->suspended))
535         lmm_update_variable_weight(network_maxmin_system, action->variable,
536                                    action->weight);
537
538     }
539     if (tmgr_trace_event_free(event_type))
540       nw_link->lat_event = NULL;
541   } else if (event_type == nw_link->lmm_resource.state_event) {
542     if (value > 0)
543       nw_link->lmm_resource.state_current = SURF_RESOURCE_ON;
544     else {
545       lmm_constraint_t cnst = nw_link->lmm_resource.constraint;
546       lmm_variable_t var = NULL;
547       lmm_element_t elem = NULL;
548
549       nw_link->lmm_resource.state_current = SURF_RESOURCE_OFF;
550       while ((var = lmm_get_var_from_cnst
551               (network_maxmin_system, cnst, &elem))) {
552         surf_action_t action = lmm_variable_id(var);
553
554         if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
555             surf_action_state_get(action) == SURF_ACTION_READY) {
556           action->finish = date;
557           surf_network_model->action_state_set(action, SURF_ACTION_FAILED);
558         }
559       }
560     }
561     if (tmgr_trace_event_free(event_type))
562       nw_link->lmm_resource.state_event = NULL;
563   } else {
564     XBT_CRITICAL("Unknown event ! \n");
565     xbt_abort();
566   }
567
568   return;
569 }
570
571
572 static surf_action_t net_communicate(const char *src_name,
573                                      const char *dst_name, double size,
574                                      double rate)
575 {
576   unsigned int i;
577   link_CM02_t link;
578   int failed = 0;
579   surf_action_network_CM02_t action = NULL;
580   double bandwidth_bound;
581   double latency=0.0;
582   /* LARGE PLATFORMS HACK:
583      Add a link_CM02_t *link and a int link_nb to network_card_CM02_t. It will represent local links for this node
584      Use the cluster_id for ->id */
585
586   xbt_dynar_t back_route = NULL;
587   int constraints_per_variable = 0;
588   xbt_dynar_t route = xbt_dynar_new(sizeof(void*),NULL);
589   // I need to have the forward and backward routes at the same time, so allocate "route". That way, the routing wont clean it up
590   routing_get_route_and_latency(src_name, dst_name, &route, &latency);
591
592   if (sg_network_fullduplex == 1) {
593     // FIXME: fill route directly
594     routing_get_route_and_latency(dst_name, src_name, &back_route,NULL);
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_is_empty(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_is_empty(route)) {
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   xbt_dynar_t route=NULL;
728   routing_get_route_and_latency(src, dst,&route, NULL);
729   return route;
730 }
731
732 static double net_get_link_bandwidth(const void *link)
733 {
734   surf_resource_lmm_t lmm = (surf_resource_lmm_t) link;
735   return lmm->power.peak * lmm->power.scale;
736 }
737
738 static double net_get_link_latency(const void *link)
739 {
740   return ((link_CM02_t) link)->lat_current;
741 }
742
743 static int net_link_shared(const void *link)
744 {
745   return
746       lmm_constraint_is_shared(((surf_resource_lmm_t) link)->constraint);
747 }
748
749 static void net_action_suspend(surf_action_t action)
750 {
751   ((surf_action_network_CM02_t) action)->suspended = 1;
752   lmm_update_variable_weight(network_maxmin_system,
753                              ((surf_action_network_CM02_t)
754                               action)->variable, 0.0);
755 }
756
757 static void net_action_resume(surf_action_t action)
758 {
759   if (((surf_action_network_CM02_t) action)->suspended) {
760     lmm_update_variable_weight(network_maxmin_system,
761                                ((surf_action_network_CM02_t)
762                                 action)->variable,
763                                ((surf_action_network_CM02_t)
764                                 action)->weight);
765     ((surf_action_network_CM02_t) action)->suspended = 0;
766   }
767 }
768
769 static int net_action_is_suspended(surf_action_t action)
770 {
771   return ((surf_action_network_CM02_t) action)->suspended;
772 }
773
774 void net_action_set_max_duration(surf_action_t action, double duration)
775 {
776   action->max_duration = duration;
777 }
778
779 #ifdef HAVE_TRACING
780 static void net_action_set_category(surf_action_t action, const char *category)
781 {
782   action->category = xbt_strdup (category);
783 }
784 #endif
785
786 static void net_finalize(void)
787 {
788   surf_model_exit(surf_network_model);
789   surf_network_model = NULL;
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 }
845
846
847
848 /************************************************************************/
849 /* New model based on LV08 and experimental results of MPI ping-pongs   */
850 /************************************************************************/
851 void surf_network_model_init_SMPI(void)
852 {
853
854   if (surf_network_model)
855     return;
856   surf_network_model_init_internal();
857   latency_factor_callback = &smpi_latency_factor;
858   bandwidth_factor_callback = &smpi_bandwidth_factor;
859   bandwidth_constraint_callback = &smpi_bandwidth_constraint;
860   net_define_callbacks();
861   xbt_dynar_push(model_list, &surf_network_model);
862   network_solve = lmm_solve;
863
864   xbt_cfg_setdefault_double(_surf_cfg_set, "network/sender_gap", 10e-6);
865   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
866
867 }
868
869 /************************************************************************/
870 /* New model based on optimizations discussed during this thesis        */
871 /************************************************************************/
872 void surf_network_model_init_LegrandVelho(void)
873 {
874
875   if (surf_network_model)
876     return;
877   surf_network_model_init_internal();
878   net_define_callbacks();
879   xbt_dynar_push(model_list, &surf_network_model);
880   network_solve = lmm_solve;
881
882   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
883   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
884                             0.92);
885   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
886
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
911 void surf_network_model_init_Reno(void)
912 {
913   if (surf_network_model)
914     return;
915   surf_network_model_init_internal();
916   net_define_callbacks();
917
918   xbt_dynar_push(model_list, &surf_network_model);
919   lmm_set_default_protocol_function(func_reno_f, func_reno_fp,
920                                     func_reno_fpi);
921   network_solve = lagrange_solve;
922
923   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
924   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
925                             0.92);
926   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
927 }
928
929
930 void surf_network_model_init_Reno2(void)
931 {
932   if (surf_network_model)
933     return;
934   surf_network_model_init_internal();
935   net_define_callbacks();
936
937   xbt_dynar_push(model_list, &surf_network_model);
938   lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp,
939                                     func_reno2_fpi);
940   network_solve = lagrange_solve;
941
942   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
943   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
944                             0.92);
945   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S_parameter",
946                             8775);
947 }
948
949 void surf_network_model_init_Vegas(void)
950 {
951   if (surf_network_model)
952     return;
953   surf_network_model_init_internal();
954   net_define_callbacks();
955
956   xbt_dynar_push(model_list, &surf_network_model);
957   lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp,
958                                     func_vegas_fpi);
959   network_solve = lagrange_solve;
960
961   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
962   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
963                             0.92);
964   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
965 }