Logo AND Algorithmique Numérique Distribuée

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