Logo AND Algorithmique Numérique Distribuée

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