Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e35c649e3dc4b353e2520b9bc2ee45efdc7bc669
[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     if(!lmm_get_number_of_cnst_from_var(network_maxmin_system, action->variable)) {
396                                 /* There is actually no link used, hence an infinite bandwidth.
397                                  * This happens often when using models like vivaldi.
398                                  * In such case, just make sure that the action completes immediately.
399                                  */
400         double_update(&(action->generic_action.remains),
401                         action->generic_action.remains);
402     }
403     double_update(&(action->generic_action.remains),
404                   lmm_variable_getvalue(action->variable) * deltap);
405     if (action->generic_action.max_duration != NO_MAX_DURATION)
406       double_update(&(action->generic_action.max_duration), delta);
407
408     if ((action->generic_action.remains <= 0) &&
409         (lmm_get_variable_weight(action->variable) > 0)) {
410       action->generic_action.finish = surf_get_clock();
411       surf_network_model->action_state_set((surf_action_t) action,
412                                            SURF_ACTION_DONE);
413     } else if ((action->generic_action.max_duration != NO_MAX_DURATION)
414                && (action->generic_action.max_duration <= 0)) {
415       action->generic_action.finish = surf_get_clock();
416       surf_network_model->action_state_set((surf_action_t) action,
417                                            SURF_ACTION_DONE);
418     }
419   }
420
421   return;
422 }
423
424 static void net_update_resource_state(void *id,
425                                       tmgr_trace_event_t event_type,
426                                       double value, double date)
427 {
428   link_CM02_t nw_link = id;
429   /*   printf("[" "%lg" "] Asking to update network card \"%s\" with value " */
430   /*     "%lg" " for event %p\n", surf_get_clock(), nw_link->name, */
431   /*     value, event_type); */
432
433   if (event_type == nw_link->lmm_resource.power.event) {
434     double delta =
435         sg_weight_S_parameter / value - sg_weight_S_parameter /
436         (nw_link->lmm_resource.power.peak *
437          nw_link->lmm_resource.power.scale);
438     lmm_variable_t var = NULL;
439     lmm_element_t elem = NULL;
440     surf_action_network_CM02_t action = NULL;
441
442     nw_link->lmm_resource.power.peak = value;
443     lmm_update_constraint_bound(network_maxmin_system,
444                                 nw_link->lmm_resource.constraint,
445                                 sg_bandwidth_factor *
446                                 (nw_link->lmm_resource.power.peak *
447                                  nw_link->lmm_resource.power.scale));
448 #ifdef HAVE_TRACING
449     TRACE_surf_link_set_bandwidth(date, nw_link,
450                                   sg_bandwidth_factor *
451                                   (nw_link->lmm_resource.power.peak *
452                                    nw_link->lmm_resource.power.scale));
453 #endif
454     if (sg_weight_S_parameter > 0) {
455       while ((var = lmm_get_var_from_cnst
456               (network_maxmin_system, nw_link->lmm_resource.constraint,
457                &elem))) {
458         action = lmm_variable_id(var);
459         action->weight += delta;
460         if (!(action->suspended))
461           lmm_update_variable_weight(network_maxmin_system,
462                                      action->variable, action->weight);
463       }
464     }
465     if (tmgr_trace_event_free(event_type))
466       nw_link->lmm_resource.power.event = NULL;
467   } else if (event_type == nw_link->lat_event) {
468     double delta = value - nw_link->lat_current;
469     lmm_variable_t var = NULL;
470     lmm_element_t elem = NULL;
471     surf_action_network_CM02_t action = NULL;
472
473     nw_link->lat_current = value;
474     while ((var = lmm_get_var_from_cnst
475             (network_maxmin_system, nw_link->lmm_resource.constraint,
476              &elem))) {
477       action = lmm_variable_id(var);
478       action->lat_current += delta;
479       action->weight += delta;
480       if (action->rate < 0)
481         lmm_update_variable_bound(network_maxmin_system, action->variable,
482                                   sg_tcp_gamma / (2.0 *
483                                                   action->lat_current));
484       else {
485         lmm_update_variable_bound(network_maxmin_system, action->variable,
486                                   min(action->rate,
487                                       sg_tcp_gamma / (2.0 *
488                                                       action->lat_current)));
489
490         if (action->rate < sg_tcp_gamma / (2.0 * action->lat_current)) {
491           INFO0("Flow is limited BYBANDWIDTH");
492         } else {
493           INFO1("Flow is limited BYLATENCY, latency of flow is %f",
494                 action->lat_current);
495         }
496       }
497       if (!(action->suspended))
498         lmm_update_variable_weight(network_maxmin_system, action->variable,
499                                    action->weight);
500
501     }
502     if (tmgr_trace_event_free(event_type))
503       nw_link->lat_event = NULL;
504   } else if (event_type == nw_link->lmm_resource.state_event) {
505     if (value > 0)
506       nw_link->lmm_resource.state_current = SURF_RESOURCE_ON;
507     else {
508       lmm_constraint_t cnst = nw_link->lmm_resource.constraint;
509       lmm_variable_t var = NULL;
510       lmm_element_t elem = NULL;
511
512       nw_link->lmm_resource.state_current = SURF_RESOURCE_OFF;
513       while ((var = lmm_get_var_from_cnst
514               (network_maxmin_system, cnst, &elem))) {
515         surf_action_t action = lmm_variable_id(var);
516
517         if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
518             surf_action_state_get(action) == SURF_ACTION_READY) {
519           action->finish = date;
520           surf_network_model->action_state_set(action, SURF_ACTION_FAILED);
521         }
522       }
523     }
524     if (tmgr_trace_event_free(event_type))
525       nw_link->lmm_resource.state_event = NULL;
526   } else {
527     CRITICAL0("Unknown event ! \n");
528     xbt_abort();
529   }
530
531   return;
532 }
533
534
535 static surf_action_t net_communicate(const char *src_name,
536                                      const char *dst_name, double size,
537                                      double rate)
538 {
539   unsigned int i;
540   link_CM02_t link;
541   int failed = 0;
542   surf_action_network_CM02_t action = NULL;
543   double bandwidth_bound;
544   double latency=0.0;
545   /* LARGE PLATFORMS HACK:
546      Add a link_CM02_t *link and a int link_nb to network_card_CM02_t. It will represent local links for this node
547      Use the cluster_id for ->id */
548
549   xbt_dynar_t back_route = NULL;
550   int constraints_per_variable = 0;
551   // I will need this route for some time so let's call get_route_no_cleanup
552   xbt_dynar_t route = global_routing->get_route_no_cleanup(src_name, dst_name);
553
554
555   if (sg_network_fullduplex == 1) {
556     back_route = global_routing->get_route(dst_name, src_name);
557   }
558
559   /* LARGE PLATFORMS HACK:
560      total_route_size = route_size + src->link_nb + dst->nb */
561
562   XBT_IN4("(%s,%s,%g,%g)", src_name, dst_name, size, rate);
563   /* LARGE PLATFORMS HACK:
564      assert on total_route_size */
565   latency = global_routing->get_latency(src_name,dst_name);
566   xbt_assert2(xbt_dynar_length(route) || latency,
567               "You're trying to send data from %s to %s but there is no connection at all between these two hosts.",
568               src_name, dst_name);
569
570   xbt_dynar_foreach(route, i, link) {
571     if (link->lmm_resource.state_current == SURF_RESOURCE_OFF) {
572       failed = 1;
573       break;
574     }
575   }
576   action =
577       surf_action_new(sizeof(s_surf_action_network_CM02_t), size,
578                       surf_network_model, failed);
579 #ifdef HAVE_LATENCY_BOUND_TRACKING
580   (action->generic_action).latency_limited = 0;
581 #endif
582   action->weight = action->latency = latency;
583
584   xbt_swag_insert(action, action->generic_action.state_set);
585   action->rate = rate;
586
587   bandwidth_bound = -1.0;
588
589   xbt_dynar_foreach(route, i, link) {
590     action->weight +=
591         sg_weight_S_parameter /
592         (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
593     if (bandwidth_bound < 0.0)
594       bandwidth_bound =
595           (*bandwidth_factor_callback) (size) *
596           (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
597     else
598       bandwidth_bound =
599           min(bandwidth_bound,
600               (*bandwidth_factor_callback) (size) *
601               (link->lmm_resource.power.peak *
602                link->lmm_resource.power.scale));
603   }
604   /* LARGE PLATFORMS HACK:
605      Add src->link and dst->link latencies */
606   action->lat_current = action->latency;
607   action->latency *= (*latency_factor_callback) (size);
608   action->rate =
609       (*bandwidth_constraint_callback) (action->rate, bandwidth_bound,
610                                         size);
611
612   /* LARGE PLATFORMS HACK:
613      lmm_variable_new(..., total_route_size) */
614   if (back_route != NULL) {
615     constraints_per_variable =
616         xbt_dynar_length(route) + xbt_dynar_length(back_route);
617   } else {
618     constraints_per_variable = xbt_dynar_length(route);
619   }
620
621   if (action->latency > 0)
622     action->variable =
623         lmm_variable_new(network_maxmin_system, action, 0.0, -1.0,
624                          constraints_per_variable);
625   else
626     action->variable =
627         lmm_variable_new(network_maxmin_system, action, 1.0, -1.0,
628                          constraints_per_variable);
629
630   if (action->rate < 0) {
631     if (action->lat_current > 0)
632       lmm_update_variable_bound(network_maxmin_system, action->variable,
633                                 sg_tcp_gamma / (2.0 *
634                                                 action->lat_current));
635     else
636       lmm_update_variable_bound(network_maxmin_system, action->variable,
637                                 -1.0);
638   } else {
639     if (action->lat_current > 0)
640       lmm_update_variable_bound(network_maxmin_system, action->variable,
641                                 min(action->rate,
642                                     sg_tcp_gamma / (2.0 *
643                                                     action->lat_current)));
644     else
645       lmm_update_variable_bound(network_maxmin_system, action->variable,
646                                 action->rate);
647   }
648
649   xbt_dynar_foreach(route, i, link) {
650     lmm_expand(network_maxmin_system, link->lmm_resource.constraint,
651                action->variable, 1.0);
652   }
653
654   if (sg_network_fullduplex == 1) {
655     DEBUG1("Fullduplex active adding backward flow using 5%c", '%');
656     xbt_dynar_foreach(back_route, i, link) {
657       lmm_expand(network_maxmin_system, link->lmm_resource.constraint,
658                  action->variable, .05);
659     }
660   }
661   /* LARGE PLATFORMS HACK:
662      expand also with src->link and dst->link */
663 #ifdef HAVE_TRACING
664   action->src_name = xbt_new(char, strlen(src_name) + 1);
665   strncpy(action->src_name, src_name, strlen(src_name) + 1);
666
667   action->dst_name = xbt_new(char, strlen(dst_name) + 1);
668   strncpy(action->dst_name, dst_name, strlen(dst_name) + 1);
669 #endif
670
671   xbt_dynar_free(&route);
672   XBT_OUT;
673
674   return (surf_action_t) action;
675 }
676
677 static xbt_dynar_t net_get_route(const char *src, const char *dst)
678 {
679   return global_routing->get_route(src, dst);
680 }
681
682 static double net_get_link_bandwidth(const void *link)
683 {
684   surf_resource_lmm_t lmm = (surf_resource_lmm_t) link;
685   return lmm->power.peak * lmm->power.scale;
686 }
687
688 static double net_get_link_latency(const void *link)
689 {
690   return ((link_CM02_t) link)->lat_current;
691 }
692
693 static int net_link_shared(const void *link)
694 {
695   return
696       lmm_constraint_is_shared(((surf_resource_lmm_t) link)->constraint);
697 }
698
699 static void net_action_suspend(surf_action_t action)
700 {
701   ((surf_action_network_CM02_t) action)->suspended = 1;
702   lmm_update_variable_weight(network_maxmin_system,
703                              ((surf_action_network_CM02_t)
704                               action)->variable, 0.0);
705 }
706
707 static void net_action_resume(surf_action_t action)
708 {
709   if (((surf_action_network_CM02_t) action)->suspended) {
710     lmm_update_variable_weight(network_maxmin_system,
711                                ((surf_action_network_CM02_t)
712                                 action)->variable,
713                                ((surf_action_network_CM02_t)
714                                 action)->weight);
715     ((surf_action_network_CM02_t) action)->suspended = 0;
716   }
717 }
718
719 static int net_action_is_suspended(surf_action_t action)
720 {
721   return ((surf_action_network_CM02_t) action)->suspended;
722 }
723
724 void net_action_set_max_duration(surf_action_t action, double duration)
725 {
726   action->max_duration = duration;
727 }
728
729 static void net_finalize(void)
730 {
731   surf_model_exit(surf_network_model);
732   surf_network_model = NULL;
733
734   global_routing->finalize();
735
736   lmm_system_free(network_maxmin_system);
737   network_maxmin_system = NULL;
738 }
739
740 static void surf_network_model_init_internal(void)
741 {
742   surf_network_model = surf_model_init();
743
744   surf_network_model->name = "network";
745   surf_network_model->action_unref = net_action_unref;
746   surf_network_model->action_cancel = net_action_cancel;
747   surf_network_model->action_recycle = net_action_recycle;
748   surf_network_model->get_remains = net_action_get_remains;
749 #ifdef HAVE_LATENCY_BOUND_TRACKING
750   surf_network_model->get_latency_limited = net_get_link_latency_limited;
751 #endif
752
753   surf_network_model->model_private->resource_used = net_resource_used;
754   surf_network_model->model_private->share_resources = net_share_resources;
755   surf_network_model->model_private->update_actions_state =
756       net_update_actions_state;
757   surf_network_model->model_private->update_resource_state =
758       net_update_resource_state;
759   surf_network_model->model_private->finalize = net_finalize;
760
761   surf_network_model->suspend = net_action_suspend;
762   surf_network_model->resume = net_action_resume;
763   surf_network_model->is_suspended = net_action_is_suspended;
764   surf_cpu_model->set_max_duration = net_action_set_max_duration;
765
766   surf_network_model->extension.network.communicate = net_communicate;
767   surf_network_model->extension.network.get_route = net_get_route;
768   surf_network_model->extension.network.get_link_bandwidth =
769       net_get_link_bandwidth;
770   surf_network_model->extension.network.get_link_latency =
771       net_get_link_latency;
772   surf_network_model->extension.network.link_shared = net_link_shared;
773   surf_network_model->extension.network.add_traces = net_add_traces;
774   surf_network_model->extension.network.create_resource =
775       net_create_resource;
776
777   if (!network_maxmin_system)
778     network_maxmin_system = lmm_system_new();
779
780   routing_model_create(sizeof(link_CM02_t),
781                        net_link_new(xbt_strdup("__loopback__"),
782                                     498000000, NULL, 0.000015, NULL,
783                                     SURF_RESOURCE_ON, NULL,
784                                     SURF_LINK_FATPIPE, NULL),
785                        net_get_link_latency);
786 }
787
788
789
790 /************************************************************************/
791 /* New model based on LV08 and experimental results of MPI ping-pongs   */
792 /************************************************************************/
793 void surf_network_model_init_SMPI(const char *filename)
794 {
795
796   if (surf_network_model)
797     return;
798   surf_network_model_init_internal();
799   latency_factor_callback = &smpi_latency_factor;
800   bandwidth_factor_callback = &smpi_bandwidth_factor;
801   bandwidth_constraint_callback = &smpi_bandwidth_constraint;
802   net_define_callbacks(filename);
803   xbt_dynar_push(model_list, &surf_network_model);
804   network_solve = lmm_solve;
805
806   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
807
808   update_model_description(surf_network_model_description,
809                            "SMPI", surf_network_model);
810 }
811
812 /************************************************************************/
813 /* New model based on optimizations discussed during this thesis        */
814 /************************************************************************/
815 void surf_network_model_init_LegrandVelho(const char *filename)
816 {
817
818   if (surf_network_model)
819     return;
820   surf_network_model_init_internal();
821   net_define_callbacks(filename);
822   xbt_dynar_push(model_list, &surf_network_model);
823   network_solve = lmm_solve;
824
825   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
826   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
827                             0.92);
828   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
829
830   update_model_description(surf_network_model_description,
831                            "LV08", surf_network_model);
832 }
833
834 /***************************************************************************/
835 /* The nice TCP sharing model designed by Loris Marchal and Henri Casanova */
836 /***************************************************************************/
837 /* @TechReport{      rr-lip2002-40, */
838 /*   author        = {Henri Casanova and Loris Marchal}, */
839 /*   institution   = {LIP}, */
840 /*   title         = {A Network Model for Simulation of Grid Application}, */
841 /*   number        = {2002-40}, */
842 /*   month         = {oct}, */
843 /*   year          = {2002} */
844 /* } */
845 void surf_network_model_init_CM02(const char *filename)
846 {
847
848   if (surf_network_model)
849     return;
850   surf_network_model_init_internal();
851   net_define_callbacks(filename);
852   xbt_dynar_push(model_list, &surf_network_model);
853   network_solve = lmm_solve;
854
855   update_model_description(surf_network_model_description,
856                            "CM02", surf_network_model);
857 }
858
859 void surf_network_model_init_Reno(const char *filename)
860 {
861   if (surf_network_model)
862     return;
863   surf_network_model_init_internal();
864   net_define_callbacks(filename);
865
866   xbt_dynar_push(model_list, &surf_network_model);
867   lmm_set_default_protocol_function(func_reno_f, func_reno_fp,
868                                     func_reno_fpi);
869   network_solve = lagrange_solve;
870
871   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
872   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
873                             0.92);
874   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
875
876   update_model_description(surf_network_model_description,
877                            "Reno", surf_network_model);
878 }
879
880
881 void surf_network_model_init_Reno2(const char *filename)
882 {
883   if (surf_network_model)
884     return;
885   surf_network_model_init_internal();
886   net_define_callbacks(filename);
887
888   xbt_dynar_push(model_list, &surf_network_model);
889   lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp,
890                                     func_reno2_fpi);
891   network_solve = lagrange_solve;
892
893   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
894   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
895                             0.92);
896   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S_parameter",
897                             8775);
898
899   update_model_description(surf_network_model_description,
900                            "Reno2", surf_network_model);
901 }
902
903 void surf_network_model_init_Vegas(const char *filename)
904 {
905   if (surf_network_model)
906     return;
907   surf_network_model_init_internal();
908   net_define_callbacks(filename);
909
910   xbt_dynar_push(model_list, &surf_network_model);
911   lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp,
912                                     func_vegas_fpi);
913   network_solve = lagrange_solve;
914
915   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
916   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
917                             0.92);
918   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
919
920   update_model_description(surf_network_model_description,
921                            "Vegas", surf_network_model);
922 }