Logo AND Algorithmique Numérique Distribuée

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