Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
67213b5aaf153355b0ba34b46175fa7133068476
[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     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 = global_routing->get_route(action->src_name,
417                                                     action->dst_name);
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 will need this route for some time so require for no cleanup
590   global_routing->get_route_latency(src_name, dst_name, &route, &latency, 0);
591
592   if (sg_network_fullduplex == 1) {
593     back_route = global_routing->get_route(dst_name, src_name);
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_length(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_length(route) > 0) {
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   return global_routing->get_route(src, dst);
727 }
728
729 static double net_get_link_bandwidth(const void *link)
730 {
731   surf_resource_lmm_t lmm = (surf_resource_lmm_t) link;
732   return lmm->power.peak * lmm->power.scale;
733 }
734
735 static double net_get_link_latency(const void *link)
736 {
737   return ((link_CM02_t) link)->lat_current;
738 }
739
740 static int net_link_shared(const void *link)
741 {
742   return
743       lmm_constraint_is_shared(((surf_resource_lmm_t) link)->constraint);
744 }
745
746 static void net_action_suspend(surf_action_t action)
747 {
748   ((surf_action_network_CM02_t) action)->suspended = 1;
749   lmm_update_variable_weight(network_maxmin_system,
750                              ((surf_action_network_CM02_t)
751                               action)->variable, 0.0);
752 }
753
754 static void net_action_resume(surf_action_t action)
755 {
756   if (((surf_action_network_CM02_t) action)->suspended) {
757     lmm_update_variable_weight(network_maxmin_system,
758                                ((surf_action_network_CM02_t)
759                                 action)->variable,
760                                ((surf_action_network_CM02_t)
761                                 action)->weight);
762     ((surf_action_network_CM02_t) action)->suspended = 0;
763   }
764 }
765
766 static int net_action_is_suspended(surf_action_t action)
767 {
768   return ((surf_action_network_CM02_t) action)->suspended;
769 }
770
771 void net_action_set_max_duration(surf_action_t action, double duration)
772 {
773   action->max_duration = duration;
774 }
775
776 #ifdef HAVE_TRACING
777 static void net_action_set_category(surf_action_t action, const char *category)
778 {
779   action->category = xbt_strdup (category);
780 }
781 #endif
782
783 static void net_finalize(void)
784 {
785   surf_model_exit(surf_network_model);
786   surf_network_model = NULL;
787
788   lmm_system_free(network_maxmin_system);
789   network_maxmin_system = NULL;
790 }
791
792 static void surf_network_model_init_internal(void)
793 {
794   surf_network_model = surf_model_init();
795
796   surf_network_model->name = "network";
797   surf_network_model->action_unref = net_action_unref;
798   surf_network_model->action_cancel = net_action_cancel;
799   surf_network_model->action_recycle = net_action_recycle;
800   surf_network_model->get_remains = net_action_get_remains;
801 #ifdef HAVE_LATENCY_BOUND_TRACKING
802   surf_network_model->get_latency_limited = net_get_link_latency_limited;
803 #endif
804
805   surf_network_model->model_private->resource_used = net_resource_used;
806   surf_network_model->model_private->share_resources = net_share_resources;
807   surf_network_model->model_private->update_actions_state =
808       net_update_actions_state;
809   surf_network_model->model_private->update_resource_state =
810       net_update_resource_state;
811   surf_network_model->model_private->finalize = net_finalize;
812
813   surf_network_model->suspend = net_action_suspend;
814   surf_network_model->resume = net_action_resume;
815   surf_network_model->is_suspended = net_action_is_suspended;
816   surf_network_model->set_max_duration = net_action_set_max_duration;
817 #ifdef HAVE_TRACING
818   surf_network_model->set_category = net_action_set_category;
819 #endif
820
821   surf_network_model->extension.network.communicate = net_communicate;
822   surf_network_model->extension.network.get_route = net_get_route;
823   surf_network_model->extension.network.get_link_bandwidth =
824       net_get_link_bandwidth;
825   surf_network_model->extension.network.get_link_latency =
826       net_get_link_latency;
827   surf_network_model->extension.network.link_shared = net_link_shared;
828   surf_network_model->extension.network.add_traces = net_add_traces;
829   surf_network_model->extension.network.create_resource =
830       net_create_resource;
831
832   if (!network_maxmin_system)
833     network_maxmin_system = lmm_system_new();
834
835   routing_model_create(sizeof(link_CM02_t),
836                        net_create_resource("__loopback__",
837                                            498000000, NULL,
838                                            0.000015, NULL,
839                                            SURF_RESOURCE_ON, NULL,
840                                            SURF_LINK_FATPIPE, NULL));
841 }
842
843
844
845 /************************************************************************/
846 /* New model based on LV08 and experimental results of MPI ping-pongs   */
847 /************************************************************************/
848 void surf_network_model_init_SMPI(void)
849 {
850
851   if (surf_network_model)
852     return;
853   surf_network_model_init_internal();
854   latency_factor_callback = &smpi_latency_factor;
855   bandwidth_factor_callback = &smpi_bandwidth_factor;
856   bandwidth_constraint_callback = &smpi_bandwidth_constraint;
857   net_define_callbacks();
858   xbt_dynar_push(model_list, &surf_network_model);
859   network_solve = lmm_solve;
860
861   xbt_cfg_setdefault_double(_surf_cfg_set, "network/sender_gap", 10e-6);
862   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
863
864 }
865
866 /************************************************************************/
867 /* New model based on optimizations discussed during this thesis        */
868 /************************************************************************/
869 void surf_network_model_init_LegrandVelho(void)
870 {
871
872   if (surf_network_model)
873     return;
874   surf_network_model_init_internal();
875   net_define_callbacks();
876   xbt_dynar_push(model_list, &surf_network_model);
877   network_solve = lmm_solve;
878
879   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
880   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
881                             0.92);
882   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
883
884 }
885
886 /***************************************************************************/
887 /* The nice TCP sharing model designed by Loris Marchal and Henri Casanova */
888 /***************************************************************************/
889 /* @TechReport{      rr-lip2002-40, */
890 /*   author        = {Henri Casanova and Loris Marchal}, */
891 /*   institution   = {LIP}, */
892 /*   title         = {A Network Model for Simulation of Grid Application}, */
893 /*   number        = {2002-40}, */
894 /*   month         = {oct}, */
895 /*   year          = {2002} */
896 /* } */
897 void surf_network_model_init_CM02(void)
898 {
899
900   if (surf_network_model)
901     return;
902   surf_network_model_init_internal();
903   net_define_callbacks();
904   xbt_dynar_push(model_list, &surf_network_model);
905   network_solve = lmm_solve;
906 }
907
908 void surf_network_model_init_Reno(void)
909 {
910   if (surf_network_model)
911     return;
912   surf_network_model_init_internal();
913   net_define_callbacks();
914
915   xbt_dynar_push(model_list, &surf_network_model);
916   lmm_set_default_protocol_function(func_reno_f, func_reno_fp,
917                                     func_reno_fpi);
918   network_solve = lagrange_solve;
919
920   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
921   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
922                             0.92);
923   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
924 }
925
926
927 void surf_network_model_init_Reno2(void)
928 {
929   if (surf_network_model)
930     return;
931   surf_network_model_init_internal();
932   net_define_callbacks();
933
934   xbt_dynar_push(model_list, &surf_network_model);
935   lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp,
936                                     func_reno2_fpi);
937   network_solve = lagrange_solve;
938
939   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
940   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
941                             0.92);
942   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S_parameter",
943                             8775);
944 }
945
946 void surf_network_model_init_Vegas(void)
947 {
948   if (surf_network_model)
949     return;
950   surf_network_model_init_internal();
951   net_define_callbacks();
952
953   xbt_dynar_push(model_list, &surf_network_model);
954   lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp,
955                                     func_vegas_fpi);
956   network_solve = lagrange_solve;
957
958   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
959   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
960                             0.92);
961   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
962 }