Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
kill routing_get_route(), use routing_get_route_and_latency() instead
[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;
417       routing_get_route_and_latency(action->src_name, action->dst_name,&route,NULL,1);
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;
589   // I need to have the forward and backward routes at the same time, so I don't ask the routing to cleanup the route right away for me
590   routing_get_route_and_latency(src_name, dst_name, &route, &latency, 0);
591
592   if (sg_network_fullduplex == 1) {
593     routing_get_route_and_latency(dst_name, src_name, &back_route,NULL,1);
594   }
595
596   /* LARGE PLATFORMS HACK:
597      total_route_size = route_size + src->link_nb + dst->nb */
598
599   XBT_IN("(%s,%s,%g,%g)", src_name, dst_name, size, rate);
600   /* LARGE PLATFORMS HACK:
601      assert on total_route_size */
602   xbt_assert(!xbt_dynar_is_empty(route) || latency,
603               "You're trying to send data from %s to %s but there is no connection at all between these two hosts.",
604               src_name, dst_name);
605
606   xbt_dynar_foreach(route, i, link) {
607     if (link->lmm_resource.state_current == SURF_RESOURCE_OFF) {
608       failed = 1;
609       break;
610     }
611   }
612   action =
613       surf_action_new(sizeof(s_surf_action_network_CM02_t), size,
614                       surf_network_model, failed);
615 #ifdef HAVE_LATENCY_BOUND_TRACKING
616   (action->generic_action).latency_limited = 0;
617 #endif
618   action->weight = action->latency = latency;
619
620   xbt_swag_insert(action, action->generic_action.state_set);
621   action->rate = rate;
622
623   bandwidth_bound = -1.0;
624
625   xbt_dynar_foreach(route, i, link) {
626     action->weight +=
627         sg_weight_S_parameter /
628         (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
629     if (bandwidth_bound < 0.0)
630       bandwidth_bound =
631           bandwidth_factor_callback(size) *
632           (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
633     else
634       bandwidth_bound =
635           min(bandwidth_bound,
636               bandwidth_factor_callback(size) *
637               (link->lmm_resource.power.peak *
638                link->lmm_resource.power.scale));
639   }
640   /* LARGE PLATFORMS HACK:
641      Add src->link and dst->link latencies */
642   action->lat_current = action->latency;
643   action->latency *= latency_factor_callback(size);
644   action->rate =
645       bandwidth_constraint_callback(action->rate, bandwidth_bound,
646                                         size);
647
648   if(!xbt_dynar_is_empty(route)) {
649     link = *(link_CM02_t*)xbt_dynar_get_ptr(route, 0);
650     gap_append(size, link, action);
651     XBT_DEBUG("Comm %p: %s -> %s gap=%f (lat=%f)",
652            action, src_name, dst_name, action->sender.gap, action->latency);
653   } else {
654     gap_unknown(action);
655   }
656
657
658   /* LARGE PLATFORMS HACK:
659      lmm_variable_new(..., total_route_size) */
660   if (back_route != NULL) {
661     constraints_per_variable =
662         xbt_dynar_length(route) + xbt_dynar_length(back_route);
663   } else {
664     constraints_per_variable = xbt_dynar_length(route);
665   }
666
667   if (action->latency > 0)
668     action->variable =
669         lmm_variable_new(network_maxmin_system, action, 0.0, -1.0,
670                          constraints_per_variable);
671   else
672     action->variable =
673         lmm_variable_new(network_maxmin_system, action, 1.0, -1.0,
674                          constraints_per_variable);
675
676   if (action->rate < 0) {
677     if (action->lat_current > 0)
678       lmm_update_variable_bound(network_maxmin_system, action->variable,
679                                 sg_tcp_gamma / (2.0 *
680                                                 action->lat_current));
681     else
682       lmm_update_variable_bound(network_maxmin_system, action->variable,
683                                 -1.0);
684   } else {
685     if (action->lat_current > 0)
686       lmm_update_variable_bound(network_maxmin_system, action->variable,
687                                 min(action->rate,
688                                     sg_tcp_gamma / (2.0 *
689                                                     action->lat_current)));
690     else
691       lmm_update_variable_bound(network_maxmin_system, action->variable,
692                                 action->rate);
693   }
694
695   xbt_dynar_foreach(route, i, link) {
696     lmm_expand(network_maxmin_system, link->lmm_resource.constraint,
697                action->variable, 1.0);
698   }
699
700   if (sg_network_fullduplex == 1) {
701     XBT_DEBUG("Fullduplex active adding backward flow using 5%c", '%');
702     xbt_dynar_foreach(back_route, i, link) {
703       lmm_expand(network_maxmin_system, link->lmm_resource.constraint,
704                  action->variable, .05);
705     }
706   }
707   /* LARGE PLATFORMS HACK:
708      expand also with src->link and dst->link */
709 #ifdef HAVE_TRACING
710   if (TRACE_is_enabled()) {
711     action->src_name = xbt_strdup(src_name);
712     action->dst_name = xbt_strdup(dst_name);
713   } else {
714     action->src_name = action->dst_name = NULL;
715   }
716 #endif
717
718   xbt_dynar_free(&route);
719   XBT_OUT();
720
721   return (surf_action_t) action;
722 }
723
724 static xbt_dynar_t net_get_route(const char *src, const char *dst)
725 {
726   xbt_dynar_t route;
727   routing_get_route_and_latency(src, dst,&route, NULL,1);
728   return route;
729 }
730
731 static double net_get_link_bandwidth(const void *link)
732 {
733   surf_resource_lmm_t lmm = (surf_resource_lmm_t) link;
734   return lmm->power.peak * lmm->power.scale;
735 }
736
737 static double net_get_link_latency(const void *link)
738 {
739   return ((link_CM02_t) link)->lat_current;
740 }
741
742 static int net_link_shared(const void *link)
743 {
744   return
745       lmm_constraint_is_shared(((surf_resource_lmm_t) link)->constraint);
746 }
747
748 static void net_action_suspend(surf_action_t action)
749 {
750   ((surf_action_network_CM02_t) action)->suspended = 1;
751   lmm_update_variable_weight(network_maxmin_system,
752                              ((surf_action_network_CM02_t)
753                               action)->variable, 0.0);
754 }
755
756 static void net_action_resume(surf_action_t action)
757 {
758   if (((surf_action_network_CM02_t) action)->suspended) {
759     lmm_update_variable_weight(network_maxmin_system,
760                                ((surf_action_network_CM02_t)
761                                 action)->variable,
762                                ((surf_action_network_CM02_t)
763                                 action)->weight);
764     ((surf_action_network_CM02_t) action)->suspended = 0;
765   }
766 }
767
768 static int net_action_is_suspended(surf_action_t action)
769 {
770   return ((surf_action_network_CM02_t) action)->suspended;
771 }
772
773 void net_action_set_max_duration(surf_action_t action, double duration)
774 {
775   action->max_duration = duration;
776 }
777
778 #ifdef HAVE_TRACING
779 static void net_action_set_category(surf_action_t action, const char *category)
780 {
781   action->category = xbt_strdup (category);
782 }
783 #endif
784
785 static void net_finalize(void)
786 {
787   surf_model_exit(surf_network_model);
788   surf_network_model = NULL;
789
790   lmm_system_free(network_maxmin_system);
791   network_maxmin_system = NULL;
792 }
793
794 static void surf_network_model_init_internal(void)
795 {
796   surf_network_model = surf_model_init();
797
798   surf_network_model->name = "network";
799   surf_network_model->action_unref = net_action_unref;
800   surf_network_model->action_cancel = net_action_cancel;
801   surf_network_model->action_recycle = net_action_recycle;
802   surf_network_model->get_remains = net_action_get_remains;
803 #ifdef HAVE_LATENCY_BOUND_TRACKING
804   surf_network_model->get_latency_limited = net_get_link_latency_limited;
805 #endif
806
807   surf_network_model->model_private->resource_used = net_resource_used;
808   surf_network_model->model_private->share_resources = net_share_resources;
809   surf_network_model->model_private->update_actions_state =
810       net_update_actions_state;
811   surf_network_model->model_private->update_resource_state =
812       net_update_resource_state;
813   surf_network_model->model_private->finalize = net_finalize;
814
815   surf_network_model->suspend = net_action_suspend;
816   surf_network_model->resume = net_action_resume;
817   surf_network_model->is_suspended = net_action_is_suspended;
818   surf_network_model->set_max_duration = net_action_set_max_duration;
819 #ifdef HAVE_TRACING
820   surf_network_model->set_category = net_action_set_category;
821 #endif
822
823   surf_network_model->extension.network.communicate = net_communicate;
824   surf_network_model->extension.network.get_route = net_get_route;
825   surf_network_model->extension.network.get_link_bandwidth =
826       net_get_link_bandwidth;
827   surf_network_model->extension.network.get_link_latency =
828       net_get_link_latency;
829   surf_network_model->extension.network.link_shared = net_link_shared;
830   surf_network_model->extension.network.add_traces = net_add_traces;
831   surf_network_model->extension.network.create_resource =
832       net_create_resource;
833
834   if (!network_maxmin_system)
835     network_maxmin_system = lmm_system_new();
836
837   routing_model_create(sizeof(link_CM02_t),
838                        net_create_resource("__loopback__",
839                                            498000000, NULL,
840                                            0.000015, NULL,
841                                            SURF_RESOURCE_ON, NULL,
842                                            SURF_LINK_FATPIPE, NULL));
843 }
844
845
846
847 /************************************************************************/
848 /* New model based on LV08 and experimental results of MPI ping-pongs   */
849 /************************************************************************/
850 void surf_network_model_init_SMPI(void)
851 {
852
853   if (surf_network_model)
854     return;
855   surf_network_model_init_internal();
856   latency_factor_callback = &smpi_latency_factor;
857   bandwidth_factor_callback = &smpi_bandwidth_factor;
858   bandwidth_constraint_callback = &smpi_bandwidth_constraint;
859   net_define_callbacks();
860   xbt_dynar_push(model_list, &surf_network_model);
861   network_solve = lmm_solve;
862
863   xbt_cfg_setdefault_double(_surf_cfg_set, "network/sender_gap", 10e-6);
864   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
865
866 }
867
868 /************************************************************************/
869 /* New model based on optimizations discussed during this thesis        */
870 /************************************************************************/
871 void surf_network_model_init_LegrandVelho(void)
872 {
873
874   if (surf_network_model)
875     return;
876   surf_network_model_init_internal();
877   net_define_callbacks();
878   xbt_dynar_push(model_list, &surf_network_model);
879   network_solve = lmm_solve;
880
881   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
882   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
883                             0.92);
884   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
885
886 }
887
888 /***************************************************************************/
889 /* The nice TCP sharing model designed by Loris Marchal and Henri Casanova */
890 /***************************************************************************/
891 /* @TechReport{      rr-lip2002-40, */
892 /*   author        = {Henri Casanova and Loris Marchal}, */
893 /*   institution   = {LIP}, */
894 /*   title         = {A Network Model for Simulation of Grid Application}, */
895 /*   number        = {2002-40}, */
896 /*   month         = {oct}, */
897 /*   year          = {2002} */
898 /* } */
899 void surf_network_model_init_CM02(void)
900 {
901
902   if (surf_network_model)
903     return;
904   surf_network_model_init_internal();
905   net_define_callbacks();
906   xbt_dynar_push(model_list, &surf_network_model);
907   network_solve = lmm_solve;
908 }
909
910 void surf_network_model_init_Reno(void)
911 {
912   if (surf_network_model)
913     return;
914   surf_network_model_init_internal();
915   net_define_callbacks();
916
917   xbt_dynar_push(model_list, &surf_network_model);
918   lmm_set_default_protocol_function(func_reno_f, func_reno_fp,
919                                     func_reno_fpi);
920   network_solve = lagrange_solve;
921
922   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
923   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
924                             0.92);
925   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
926 }
927
928
929 void surf_network_model_init_Reno2(void)
930 {
931   if (surf_network_model)
932     return;
933   surf_network_model_init_internal();
934   net_define_callbacks();
935
936   xbt_dynar_push(model_list, &surf_network_model);
937   lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp,
938                                     func_reno2_fpi);
939   network_solve = lagrange_solve;
940
941   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
942   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
943                             0.92);
944   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S_parameter",
945                             8775);
946 }
947
948 void surf_network_model_init_Vegas(void)
949 {
950   if (surf_network_model)
951     return;
952   surf_network_model_init_internal();
953   net_define_callbacks();
954
955   xbt_dynar_push(model_list, &surf_network_model);
956   lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp,
957                                     func_vegas_fpi);
958   network_solve = lagrange_solve;
959
960   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
961   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
962                             0.92);
963   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
964 }