Logo AND Algorithmique Numérique Distribuée

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