Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Kill "if" before free, and useless cast of free argument.
[simgrid.git] / src / surf / surf_routing.c
1 /* Copyright (c) 2009, 2010, 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 <pcre.h>               /* regular expression library */
8
9 #include "simgrid/platf_interface.h"    // platform creation API internal interface
10
11 #include "surf_routing_private.h"
12 #include "surf/surf_routing.h"
13 #include "surf/surfxml_parse_values.h"
14
15 xbt_lib_t host_lib;
16 int ROUTING_HOST_LEVEL;         //Routing level
17 int SURF_CPU_LEVEL;             //Surf cpu level
18 int SURF_WKS_LEVEL;             //Surf workstation level
19 int SIMIX_HOST_LEVEL;           //Simix level
20 int MSG_HOST_LEVEL;             //Msg level
21 int SD_HOST_LEVEL;              //Simdag level
22 int COORD_HOST_LEVEL;           //Coordinates level
23 int NS3_HOST_LEVEL;             //host node for ns3
24
25 xbt_lib_t link_lib;
26 int SD_LINK_LEVEL;              //Simdag level
27 int SURF_LINK_LEVEL;            //Surf level
28 int NS3_LINK_LEVEL;             //link for ns3
29
30 xbt_lib_t as_router_lib;
31 int ROUTING_ASR_LEVEL;          //Routing level
32 int COORD_ASR_LEVEL;            //Coordinates level
33 int NS3_ASR_LEVEL;              //host node for ns3
34
35 static xbt_dict_t patterns = NULL;
36 static xbt_dict_t random_value = NULL;
37
38 /* Global vars */
39 routing_global_t global_routing = NULL;
40 routing_component_t current_routing = NULL;
41 model_type_t current_routing_model = NULL;
42
43 /* global parse functions */
44 xbt_dynar_t link_list = NULL;   /* temporary store of current list link of a route */
45 static const char *src = NULL;  /* temporary store the source name of a route */
46 static const char *dst = NULL;  /* temporary store the destination name of a route */
47 static char *gw_src = NULL;     /* temporary store the gateway source name of a route */
48 static char *gw_dst = NULL;     /* temporary store the gateway destination name of a route */
49 static double_f_cpvoid_t get_link_latency = NULL;
50
51 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route, surf, "Routing part of surf");
52
53 static void routing_parse_peer(sg_platf_peer_cbarg_t peer);     /* peer bypass */
54 static void routing_parse_Srandom(void);        /* random bypass */
55
56 static char *replace_random_parameter(char *chaine);
57 static void routing_parse_postparse(void);
58
59 /* this lines are only for replace use like index in the model table */
60 typedef enum {
61   SURF_MODEL_FULL = 0,
62   SURF_MODEL_FLOYD,
63   SURF_MODEL_DIJKSTRA,
64   SURF_MODEL_DIJKSTRACACHE,
65   SURF_MODEL_NONE,
66   SURF_MODEL_RULEBASED,
67   SURF_MODEL_VIVALDI,
68   SURF_MODEL_CLUSTER
69 } e_routing_types;
70
71 struct s_model_type routing_models[] = {
72   {"Full",
73    "Full routing data (fast, large memory requirements, fully expressive)",
74    model_full_create, model_full_load, model_full_unload, model_full_end},
75   {"Floyd",
76    "Floyd routing data (slow initialization, fast lookup, lesser memory requirements, shortest path routing only)",
77    model_floyd_create, model_floyd_load, model_floyd_unload, model_floyd_end},
78   {"Dijkstra",
79    "Dijkstra routing data (fast initialization, slow lookup, small memory requirements, shortest path routing only)",
80    model_dijkstra_create, model_dijkstra_both_load,
81    model_dijkstra_both_unload, model_dijkstra_both_end},
82   {"DijkstraCache",
83    "Dijkstra routing data (fast initialization, fast lookup, small memory requirements, shortest path routing only)",
84    model_dijkstracache_create, model_dijkstra_both_load,
85    model_dijkstra_both_unload, model_dijkstra_both_end},
86   {"none", "No routing (usable with Constant network only)",
87    model_none_create, model_none_load, model_none_unload, model_none_end},
88   {"RuleBased", "Rule-Based routing data (...)",
89    model_rulebased_create, model_none_load, model_none_unload, model_none_end},
90   {"Vivaldi", "Vivaldi routing",
91    model_vivaldi_create, model_none_load, model_none_unload, model_none_end},
92   {"Cluster", "Cluster routing",
93    model_cluster_create, model_none_load, model_cluster_unload, model_none_end},
94   {NULL, NULL, NULL, NULL, NULL, NULL}
95 };
96
97 /**
98  * \brief Add a "host" to the network element list
99  */
100 static void parse_S_host(sg_platf_host_cbarg_t host)
101 {
102   network_element_info_t info = NULL;
103   if (current_routing->hierarchy == SURF_ROUTING_NULL)
104     current_routing->hierarchy = SURF_ROUTING_BASE;
105   xbt_assert(!xbt_lib_get_or_null(host_lib, host->id, ROUTING_HOST_LEVEL),
106              "Reading a host, processing unit \"%s\" already exists", host->id);
107   xbt_assert(current_routing->set_processing_unit,
108              "no defined method \"set_processing_unit\" in \"%s\"",
109              current_routing->name);
110   (*(current_routing->set_processing_unit)) (current_routing, host->id);
111   info = xbt_new0(s_network_element_info_t, 1);
112   info->rc_component = current_routing;
113   info->rc_type = SURF_NETWORK_ELEMENT_HOST;
114   xbt_lib_set(host_lib, host->id, ROUTING_HOST_LEVEL, (void *) info);
115   if (host->coord && strcmp(host->coord, "")) {
116     if (!COORD_HOST_LEVEL)
117       xbt_die
118           ("To use coordinates, you must set configuration 'coordinates' to 'yes'");
119     xbt_dynar_t ctn = xbt_str_split_str(host->coord, " ");
120     xbt_dynar_shrink(ctn, 0);
121     xbt_lib_set(host_lib, host->id, COORD_HOST_LEVEL, (void *) ctn);
122   }
123 }
124
125 /**
126  * \brief Add a "router" to the network element list
127  */
128 static void parse_S_router(sg_platf_router_cbarg_t router)
129 {
130   network_element_info_t info = NULL;
131   if (current_routing->hierarchy == SURF_ROUTING_NULL)
132     current_routing->hierarchy = SURF_ROUTING_BASE;
133   xbt_assert(!xbt_lib_get_or_null(as_router_lib, router->id, ROUTING_ASR_LEVEL),
134              "Reading a router, processing unit \"%s\" already exists",
135              router->id);
136   xbt_assert(current_routing->set_processing_unit,
137              "no defined method \"set_processing_unit\" in \"%s\"",
138              current_routing->name);
139   (*(current_routing->set_processing_unit)) (current_routing, router->id);
140   info = xbt_new0(s_network_element_info_t, 1);
141   info->rc_component = current_routing;
142   info->rc_type = SURF_NETWORK_ELEMENT_ROUTER;
143
144   xbt_lib_set(as_router_lib, router->id, ROUTING_ASR_LEVEL, (void *) info);
145   if (strcmp(router->coord, "")) {
146     if (!COORD_ASR_LEVEL)
147       xbt_die
148           ("To use coordinates, you must set configuration 'coordinates' to 'yes'");
149     xbt_dynar_t ctn = xbt_str_split_str(router->coord, " ");
150     xbt_dynar_shrink(ctn, 0);
151     xbt_lib_set(as_router_lib, router->id, COORD_ASR_LEVEL, (void *) ctn);
152   }
153 }
154
155
156 /**
157  * \brief Set the end points for a route
158  */
159 static void routing_parse_S_route(void)
160 {
161   if (src != NULL && dst != NULL && link_list != NULL)
162     THROWF(arg_error, 0, "Route between %s to %s can not be defined",
163            A_surfxml_route_src, A_surfxml_route_dst);
164   src = A_surfxml_route_src;
165   dst = A_surfxml_route_dst;
166   xbt_assert(strlen(src) > 0 || strlen(dst) > 0,
167              "Some limits are null in the route between \"%s\" and \"%s\"",
168              src, dst);
169   link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
170 }
171
172 /**
173  * \brief Set the end points and gateways for a ASroute
174  */
175 static void routing_parse_S_ASroute(void)
176 {
177   if (src != NULL && dst != NULL && link_list != NULL)
178     THROWF(arg_error, 0, "Route between %s to %s can not be defined",
179            A_surfxml_ASroute_src, A_surfxml_ASroute_dst);
180   src = A_surfxml_ASroute_src;
181   dst = A_surfxml_ASroute_dst;
182   gw_src = A_surfxml_ASroute_gw_src;
183   gw_dst = A_surfxml_ASroute_gw_dst;
184   xbt_assert(strlen(src) > 0 || strlen(dst) > 0 || strlen(gw_src) > 0
185              || strlen(gw_dst) > 0,
186              "Some limits are null in the route between \"%s\" and \"%s\"",
187              src, dst);
188   link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
189 }
190
191 /**
192  * \brief Set the end points for a bypassRoute
193  */
194 static void routing_parse_S_bypassRoute(void)
195 {
196   if (src != NULL && dst != NULL && link_list != NULL)
197     THROWF(arg_error, 0,
198            "Bypass Route between %s to %s can not be defined",
199            A_surfxml_bypassRoute_src, A_surfxml_bypassRoute_dst);
200   src = A_surfxml_bypassRoute_src;
201   dst = A_surfxml_bypassRoute_dst;
202   gw_src = A_surfxml_bypassRoute_gw_src;
203   gw_dst = A_surfxml_bypassRoute_gw_dst;
204   xbt_assert(strlen(src) > 0 || strlen(dst) > 0 || strlen(gw_src) > 0
205              || strlen(gw_dst) > 0,
206              "Some limits are null in the route between \"%s\" and \"%s\"",
207              src, dst);
208   link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
209 }
210
211 /**
212  * \brief Set a new link on the actual list of link for a route or ASroute from XML
213  */
214
215 static void routing_parse_link_ctn(void)
216 {
217   char *link_id;
218   switch (A_surfxml_link_ctn_direction) {
219   case AU_surfxml_link_ctn_direction:
220   case A_surfxml_link_ctn_direction_NONE:
221     link_id = xbt_strdup(A_surfxml_link_ctn_id);
222     break;
223   case A_surfxml_link_ctn_direction_UP:
224     link_id = bprintf("%s_UP", A_surfxml_link_ctn_id);
225     break;
226   case A_surfxml_link_ctn_direction_DOWN:
227     link_id = bprintf("%s_DOWN", A_surfxml_link_ctn_id);
228     break;
229   }
230   xbt_dynar_push(link_list, &link_id);
231 }
232
233 /**
234  * \brief Store the route by calling the set_route function of the current routing component
235  */
236 static void routing_parse_E_route(void)
237 {
238   name_route_extended_t route = xbt_new0(s_name_route_extended_t, 1);
239   route->generic_route.link_list = link_list;
240   xbt_assert(current_routing->set_route,
241              "no defined method \"set_route\" in \"%s\"",
242              current_routing->name);
243   (*(current_routing->set_route)) (current_routing, src, dst, route);
244   link_list = NULL;
245   src = NULL;
246   dst = NULL;
247 }
248
249 /**
250  * \brief Store the ASroute by calling the set_ASroute function of the current routing component
251  */
252 static void routing_parse_E_ASroute(void)
253 {
254   name_route_extended_t e_route = xbt_new0(s_name_route_extended_t, 1);
255   e_route->generic_route.link_list = link_list;
256   e_route->src_gateway = xbt_strdup(gw_src);
257   e_route->dst_gateway = xbt_strdup(gw_dst);
258   xbt_assert(current_routing->set_ASroute,
259              "no defined method \"set_ASroute\" in \"%s\"",
260              current_routing->name);
261   (*(current_routing->set_ASroute)) (current_routing, src, dst, e_route);
262   link_list = NULL;
263   src = NULL;
264   dst = NULL;
265   gw_src = NULL;
266   gw_dst = NULL;
267 }
268
269 /**
270  * \brief Store the bypass route by calling the set_bypassroute function of the current routing component
271  */
272 static void routing_parse_E_bypassRoute(void)
273 {
274   route_extended_t e_route = xbt_new0(s_route_extended_t, 1);
275   e_route->generic_route.link_list = link_list;
276   e_route->src_gateway = xbt_strdup(gw_src);
277   e_route->dst_gateway = xbt_strdup(gw_dst);
278   xbt_assert(current_routing->set_bypassroute,
279              "Bypassing mechanism not implemented by routing '%s'",
280              current_routing->name);
281   (*(current_routing->set_bypassroute)) (current_routing, src, dst, e_route);
282   link_list = NULL;
283   src = NULL;
284   dst = NULL;
285   gw_src = NULL;
286   gw_dst = NULL;
287 }
288
289 /**
290  * \brief Make a new routing component to the platform
291  *
292  * Add a new autonomous system to the platform. Any elements (such as host,
293  * router or sub-AS) added after this call and before the corresponding call
294  * to sg_platf_new_AS_close() will be added to this AS.
295  *
296  * Once this function was called, the configuration concerning the used
297  * models cannot be changed anymore.
298  *
299  * @param AS_id name of this autonomous system. Must be unique in the platform
300  * @param wanted_routing_type one of Full, Floyd, Dijkstra or similar. Full list in the variable routing_models, in src/surf/surf_routing.c
301  */
302 void routing_AS_open(const char *AS_id, const char *wanted_routing_type)
303 {
304   routing_component_t new_routing;
305   model_type_t model = NULL;
306   int cpt;
307
308   surf_parse_models_setup();    /* ensure that the models are created after the last <config> tag and before the first <AS>-like */
309
310   /* search the routing model */
311   for (cpt = 0; routing_models[cpt].name; cpt++)
312     if (!strcmp(wanted_routing_type, routing_models[cpt].name))
313       model = &routing_models[cpt];
314   /* if its not exist, error */
315   if (model == NULL) {
316     fprintf(stderr, "Routing model %s not found. Existing models:\n",
317             wanted_routing_type);
318     for (cpt = 0; routing_models[cpt].name; cpt++)
319       fprintf(stderr, "   %s: %s\n", routing_models[cpt].name,
320               routing_models[cpt].desc);
321     xbt_die(NULL);
322   }
323
324   /* make a new routing component */
325   new_routing = (routing_component_t) (*(model->create)) ();
326   new_routing->routing = model;
327   new_routing->hierarchy = SURF_ROUTING_NULL;
328   new_routing->name = xbt_strdup(AS_id);
329   new_routing->routing_sons = xbt_dict_new();
330
331   if (current_routing == NULL && global_routing->root == NULL) {
332
333     /* it is the first one */
334     new_routing->routing_father = NULL;
335     global_routing->root = new_routing;
336
337   } else if (current_routing != NULL && global_routing->root != NULL) {
338
339     xbt_assert(!xbt_dict_get_or_null
340                (current_routing->routing_sons, AS_id),
341                "The AS \"%s\" already exists", AS_id);
342     /* it is a part of the tree */
343     new_routing->routing_father = current_routing;
344     /* set the father behavior */
345     if (current_routing->hierarchy == SURF_ROUTING_NULL)
346       current_routing->hierarchy = SURF_ROUTING_RECURSIVE;
347     /* add to the sons dictionary */
348     xbt_dict_set(current_routing->routing_sons, AS_id,
349                  (void *) new_routing, NULL);
350     /* add to the father element list */
351     (*(current_routing->set_autonomous_system)) (current_routing, AS_id);
352     /* unload the prev parse rules */
353     (*(current_routing->routing->unload)) ();
354
355   } else {
356     THROWF(arg_error, 0, "All defined components must be belong to a AS");
357   }
358   /* set the new parse rules */
359   (*(new_routing->routing->load)) ();
360   /* set the new current component of the tree */
361   current_routing = new_routing;
362 }
363
364 /**
365  * \brief Specify that the current description of AS is finished
366  *
367  * Once you've declared all the content of your AS, you have to close
368  * it with this call. Your AS is not usable until you call this function.
369  *
370  * @fixme: this call is not as robust as wanted: bad things WILL happen
371  * if you call it twice for the same AS, or if you forget calling it, or
372  * even if you add stuff to a closed AS
373  *
374  */
375 void routing_AS_close()
376 {
377
378   if (current_routing == NULL) {
379     THROWF(arg_error, 0, "Close an AS, but none was under construction");
380   } else {
381     network_element_info_t info = NULL;
382     xbt_assert(!xbt_lib_get_or_null
383                (as_router_lib, current_routing->name, ROUTING_ASR_LEVEL),
384                "The AS \"%s\" already exists", current_routing->name);
385     info = xbt_new0(s_network_element_info_t, 1);
386     info->rc_component = current_routing->routing_father;
387     info->rc_type = SURF_NETWORK_ELEMENT_AS;
388     xbt_lib_set(as_router_lib, current_routing->name, ROUTING_ASR_LEVEL,
389                 (void *) info);
390
391     (*(current_routing->routing->unload)) ();
392     (*(current_routing->routing->end)) ();
393     current_routing = current_routing->routing_father;
394     if (current_routing != NULL)
395       (*(current_routing->routing->load)) ();
396   }
397 }
398
399 /* Aux Business methods */
400
401 /**
402  * \brief Get the AS name of the element
403  *
404  * \param name the host name
405  *
406  */
407 static char *elements_As_name(const char *name)
408 {
409   routing_component_t as_comp;
410
411   /* (1) find the as where the host is located */
412   as_comp = ((network_element_info_t)
413              xbt_lib_get_or_null(host_lib, name,
414                                  ROUTING_HOST_LEVEL))->rc_component;
415   return as_comp->name;
416 }
417
418
419 /**
420  * \brief Get the AS father and the first elements of the chain
421  *
422  * \param src the source host name 
423  * \param dst the destination host name
424  * 
425  * Get the common father of the to processing units, and the first different 
426  * father in the chain
427  */
428 static void elements_father(const char *src, const char *dst,
429                             routing_component_t * res_father,
430                             routing_component_t * res_src,
431                             routing_component_t * res_dst)
432 {
433   xbt_assert(src && dst, "bad parameters for \"elements_father\" method");
434 #define ELEMENTS_FATHER_MAXDEPTH 16     /* increase if it is not enough */
435   routing_component_t src_as, dst_as;
436   routing_component_t path_src[ELEMENTS_FATHER_MAXDEPTH];
437   routing_component_t path_dst[ELEMENTS_FATHER_MAXDEPTH];
438   int index_src = 0;
439   int index_dst = 0;
440   routing_component_t current;
441   routing_component_t current_src;
442   routing_component_t current_dst;
443   routing_component_t father;
444
445   /* (1) find the as where the src and dst are located */
446   network_element_info_t src_data = xbt_lib_get_or_null(host_lib, src,
447                                                         ROUTING_HOST_LEVEL);
448   network_element_info_t dst_data = xbt_lib_get_or_null(host_lib, dst,
449                                                         ROUTING_HOST_LEVEL);
450   if (!src_data)
451     src_data = xbt_lib_get_or_null(as_router_lib, src, ROUTING_ASR_LEVEL);
452   if (!dst_data)
453     dst_data = xbt_lib_get_or_null(as_router_lib, dst, ROUTING_ASR_LEVEL);
454   src_as = src_data->rc_component;
455   dst_as = dst_data->rc_component;
456
457   xbt_assert(src_as && dst_as,
458              "Ask for route \"from\"(%s) or \"to\"(%s) no found", src, dst);
459
460   /* (2) find the path to the root routing component */
461   for (current = src_as; current != NULL; current = current->routing_father) {
462     if (index_src >= ELEMENTS_FATHER_MAXDEPTH)
463       xbt_die("ELEMENTS_FATHER_MAXDEPTH should be increased for path_src");
464     path_src[index_src++] = current;
465   }
466   for (current = dst_as; current != NULL; current = current->routing_father) {
467     if (index_dst >= ELEMENTS_FATHER_MAXDEPTH)
468       xbt_die("ELEMENTS_FATHER_MAXDEPTH should be increased for path_dst");
469     path_dst[index_dst++] = current;
470   }
471
472   /* (3) find the common father */
473   do {
474     current_src = path_src[--index_src];
475     current_dst = path_dst[--index_dst];
476   } while (index_src > 0 && index_dst > 0 && current_src == current_dst);
477
478   /* (4) they are not in the same routing component, make the path */
479   if (current_src == current_dst)
480     father = current_src;
481   else
482     father = path_src[index_src + 1];
483
484   /* (5) result generation */
485   *res_father = father;         /* first the common father of src and dst */
486   *res_src = current_src;       /* second the first different father of src */
487   *res_dst = current_dst;       /* three  the first different father of dst */
488
489 #undef ELEMENTS_FATHER_MAXDEPTH
490 }
491
492 /* Global Business methods */
493
494 /**
495  * \brief Recursive function for get_route_latency
496  *
497  * \param src the source host name 
498  * \param dst the destination host name
499  * \param *e_route the route where the links are stored
500  * \param *latency the latency, if needed
501  * 
502  * This function is called by "get_route" and "get_latency". It allows to walk
503  * recursively through the routing components tree.
504  */
505 static void _get_route_latency(const char *src, const char *dst,
506                                xbt_dynar_t * route, double *latency)
507 {
508   XBT_DEBUG("Solve route/latency  \"%s\" to \"%s\"", src, dst);
509   xbt_assert(src && dst, "bad parameters for \"_get_route_latency\" method");
510
511   routing_component_t common_father;
512   routing_component_t src_father;
513   routing_component_t dst_father;
514   elements_father(src, dst, &common_father, &src_father, &dst_father);
515
516   if (src_father == dst_father) {       /* SURF_ROUTING_BASE */
517
518     route_extended_t e_route = NULL;
519     if (route) {
520       e_route = common_father->get_route(common_father, src, dst);
521       xbt_assert(e_route, "no route between \"%s\" and \"%s\"", src, dst);
522       *route = e_route->generic_route.link_list;
523     }
524     if (latency) {
525       *latency = common_father->get_latency(common_father, src, dst, e_route);
526       xbt_assert(*latency >= 0.0,
527                  "latency error on route between \"%s\" and \"%s\"", src, dst);
528     }
529     if (e_route) {
530       xbt_free(e_route->src_gateway);
531       xbt_free(e_route->dst_gateway);
532       xbt_free(e_route);
533     }
534
535   } else {                      /* SURF_ROUTING_RECURSIVE */
536
537     route_extended_t e_route_bypass = NULL;
538     if (common_father->get_bypass_route)
539       e_route_bypass = common_father->get_bypass_route(common_father, src, dst);
540
541     xbt_assert(!latency || !e_route_bypass,
542                "Bypass cannot work yet with get_latency");
543
544     route_extended_t e_route_cnt = e_route_bypass
545         ? e_route_bypass : common_father->get_route(common_father,
546                                                     src_father->name,
547                                                     dst_father->name);
548
549     xbt_assert(e_route_cnt, "no route between \"%s\" and \"%s\"",
550                src_father->name, dst_father->name);
551
552     xbt_assert((e_route_cnt->src_gateway == NULL) ==
553                (e_route_cnt->dst_gateway == NULL),
554                "bad gateway for route between \"%s\" and \"%s\"", src, dst);
555
556     if (route) {
557       *route = xbt_dynar_new(global_routing->size_of_link, NULL);
558     }
559     if (latency) {
560       *latency = common_father->get_latency(common_father,
561                                             src_father->name, dst_father->name,
562                                             e_route_cnt);
563       xbt_assert(*latency >= 0.0,
564                  "latency error on route between \"%s\" and \"%s\"",
565                  src_father->name, dst_father->name);
566     }
567
568     void *link;
569     unsigned int cpt;
570
571     if (strcmp(src, e_route_cnt->src_gateway)) {
572       double latency_src;
573       xbt_dynar_t route_src;
574
575       _get_route_latency(src, e_route_cnt->src_gateway,
576                          (route ? &route_src : NULL),
577                          (latency ? &latency_src : NULL));
578       if (route) {
579         xbt_assert(route_src, "no route between \"%s\" and \"%s\"",
580                    src, e_route_cnt->src_gateway);
581         xbt_dynar_foreach(route_src, cpt, link) {
582           xbt_dynar_push(*route, &link);
583         }
584         xbt_dynar_free(&route_src);
585       }
586       if (latency) {
587         xbt_assert(latency_src >= 0.0,
588                    "latency error on route between \"%s\" and \"%s\"",
589                    src, e_route_cnt->src_gateway);
590         *latency += latency_src;
591       }
592     }
593
594     if (route) {
595       xbt_dynar_foreach(e_route_cnt->generic_route.link_list, cpt, link) {
596         xbt_dynar_push(*route, &link);
597       }
598     }
599
600     if (strcmp(e_route_cnt->dst_gateway, dst)) {
601       double latency_dst;
602       xbt_dynar_t route_dst;
603
604       _get_route_latency(e_route_cnt->dst_gateway, dst,
605                          (route ? &route_dst : NULL),
606                          (latency ? &latency_dst : NULL));
607       if (route) {
608         xbt_assert(route_dst, "no route between \"%s\" and \"%s\"",
609                    e_route_cnt->dst_gateway, dst);
610         xbt_dynar_foreach(route_dst, cpt, link) {
611           xbt_dynar_push(*route, &link);
612         }
613         xbt_dynar_free(&route_dst);
614       }
615       if (latency) {
616         xbt_assert(latency_dst >= 0.0,
617                    "latency error on route between \"%s\" and \"%s\"",
618                    e_route_cnt->dst_gateway, dst);
619         *latency += latency_dst;
620       }
621     }
622
623     generic_free_extended_route(e_route_cnt);
624   }
625 }
626
627 /**
628  * \brief Generic function for get_route, get_route_no_cleanup, and get_latency
629  */
630 static void get_route_latency(const char *src, const char *dst,
631                               xbt_dynar_t * route, double *latency, int cleanup)
632 {
633   _get_route_latency(src, dst, route, latency);
634   xbt_assert(!route || *route, "no route between \"%s\" and \"%s\"", src, dst);
635   xbt_assert(!latency || *latency >= 0.0,
636              "latency error on route between \"%s\" and \"%s\"", src, dst);
637   if (route) {
638     xbt_dynar_free(&global_routing->last_route);
639     global_routing->last_route = cleanup ? *route : NULL;
640   }
641 }
642
643 /**
644  * \brief Generic method: find a route between hosts
645  *
646  * \param src the source host name 
647  * \param dst the destination host name
648  * 
649  * walk through the routing components tree and find a route between hosts
650  * by calling the differents "get_route" functions in each routing component.
651  * No need to free the returned dynar. It will be freed at the next call.
652  */
653 static xbt_dynar_t get_route(const char *src, const char *dst)
654 {
655   xbt_dynar_t route = NULL;
656   get_route_latency(src, dst, &route, NULL, 1);
657   return route;
658 }
659
660 /**
661  * \brief Generic method: find a route between hosts
662  *
663  * \param src the source host name
664  * \param dst the destination host name
665  *
666  * same as get_route, but return NULL if any exception is raised.
667  */
668 static xbt_dynar_t get_route_or_null(const char *src, const char *dst)
669 {
670   xbt_dynar_t route = NULL;
671   xbt_ex_t exception;
672   TRY {
673     get_route_latency(src, dst, &route, NULL, 1);
674   } CATCH(exception) {
675     xbt_ex_free(exception);
676     return NULL;
677   }
678   return route;
679 }
680
681 /**
682  * \brief Generic method: find a route between hosts
683  *
684  * \param src the source host name
685  * \param dst the destination host name
686  *
687  * walk through the routing components tree and find a route between hosts
688  * by calling the differents "get_route" functions in each routing component.
689  * Leaves the caller the responsability to clean the returned dynar.
690  */
691 static xbt_dynar_t get_route_no_cleanup(const char *src, const char *dst)
692 {
693   xbt_dynar_t route = NULL;
694   get_route_latency(src, dst, &route, NULL, 0);
695   return route;
696 }
697
698 /*Get Latency*/
699 static double get_latency(const char *src, const char *dst)
700 {
701   double latency = -1.0;
702   get_route_latency(src, dst, NULL, &latency, 0);
703   return latency;
704 }
705
706 static int surf_parse_models_setup_already_called = 0;
707 /* Call the last initialization functions, that must be called after the
708  * <config> tag, if any, and before the first of cluster|peer|AS|trace|trace_connect
709  */
710 void surf_parse_models_setup()
711 {
712   if (surf_parse_models_setup_already_called)
713     return;
714   surf_parse_models_setup_already_called = 1;
715   surf_config_models_setup();
716 }
717
718
719 /**
720  * \brief Recursive function for finalize
721  *
722  * \param rc the source host name 
723  * 
724  * This fuction is call by "finalize". It allow to finalize the 
725  * AS or routing components. It delete all the structures.
726  */
727 static void _finalize(routing_component_t rc)
728 {
729   if (rc) {
730     xbt_dict_cursor_t cursor = NULL;
731     char *key;
732     routing_component_t elem;
733     xbt_dict_foreach(rc->routing_sons, cursor, key, elem) {
734       _finalize(elem);
735     }
736     xbt_dict_t tmp_sons = rc->routing_sons;
737     char *tmp_name = rc->name;
738     xbt_dict_free(&tmp_sons);
739     xbt_free(tmp_name);
740     xbt_assert(rc->finalize, "no defined method \"finalize\" in \"%s\"",
741                current_routing->name);
742     (*(rc->finalize)) (rc);
743   }
744 }
745
746 /**
747  * \brief Generic method: delete all the routing structures
748  * 
749  * walk through the routing components tree and delete the structures
750  * by calling the differents "finalize" functions in each routing component
751  */
752 static void finalize(void)
753 {
754   /* delete recursively all the tree */
755   _finalize(global_routing->root);
756   /* delete last_route */
757   xbt_dynar_free(&(global_routing->last_route));
758   /* delete global routing structure */
759   xbt_free(global_routing);
760   /* make sure that we will reinit the models while loading the platf once reinited -- HACK but there is no proper surf_routing_init() */
761   surf_parse_models_setup_already_called = 0;
762 }
763
764 static xbt_dynar_t recursive_get_onelink_routes(routing_component_t rc)
765 {
766   xbt_dynar_t ret = xbt_dynar_new(sizeof(onelink_t), xbt_free);
767
768   //adding my one link routes
769   unsigned int cpt;
770   void *link;
771   xbt_dynar_t onelink_mine = rc->get_onelink_routes(rc);
772   if (onelink_mine) {
773     xbt_dynar_foreach(onelink_mine, cpt, link) {
774       xbt_dynar_push(ret, &link);
775     }
776   }
777   //recursing
778   char *key;
779   xbt_dict_cursor_t cursor = NULL;
780   routing_component_t rc_child;
781   xbt_dict_foreach(rc->routing_sons, cursor, key, rc_child) {
782     xbt_dynar_t onelink_child = recursive_get_onelink_routes(rc_child);
783     if (onelink_child) {
784       xbt_dynar_foreach(onelink_child, cpt, link) {
785         xbt_dynar_push(ret, &link);
786       }
787     }
788   }
789   return ret;
790 }
791
792 static xbt_dynar_t get_onelink_routes(void)
793 {
794   return recursive_get_onelink_routes(global_routing->root);
795 }
796
797 e_surf_network_element_type_t get_network_element_type(const char *name)
798 {
799   network_element_info_t rc = NULL;
800
801   rc = xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL);
802   if (rc)
803     return rc->rc_type;
804
805   rc = xbt_lib_get_or_null(as_router_lib, name, ROUTING_ASR_LEVEL);
806   if (rc)
807     return rc->rc_type;
808
809   return SURF_NETWORK_ELEMENT_NULL;
810 }
811
812 /**
813  * \brief Generic method: create the global routing schema
814  * 
815  * Make a global routing structure and set all the parsing functions.
816  */
817 void routing_model_create(size_t size_of_links, void *loopback,
818                           double_f_cpvoid_t get_link_latency_fun)
819 {
820   /* config the uniq global routing */
821   global_routing = xbt_new0(s_routing_global_t, 1);
822   global_routing->root = NULL;
823   global_routing->get_route = get_route;
824   global_routing->get_route_or_null = get_route_or_null;
825   global_routing->get_latency = get_latency;
826   global_routing->get_route_no_cleanup = get_route_no_cleanup;
827   global_routing->get_onelink_routes = get_onelink_routes;
828   global_routing->get_route_latency = get_route_latency;
829   global_routing->get_network_element_type = get_network_element_type;
830   global_routing->finalize = finalize;
831   global_routing->loopback = loopback;
832   global_routing->size_of_link = size_of_links;
833   global_routing->last_route = NULL;
834   get_link_latency = get_link_latency_fun;
835   /* no current routing at moment */
836   current_routing = NULL;
837 }
838
839
840 /* ************************************************** */
841 /* ********** PATERN FOR NEW ROUTING **************** */
842
843 /* The minimal configuration of a new routing model need the next functions,
844  * also you need to set at the start of the file, the new model in the model
845  * list. Remember keep the null ending of the list.
846  */
847 /*** Routing model structure ***/
848 // typedef struct {
849 //   s_routing_component_t generic_routing;
850 //   /* things that your routing model need */
851 // } s_routing_component_NEW_t,*routing_component_NEW_t;
852
853 /*** Parse routing model functions ***/
854 // static void model_NEW_set_processing_unit(routing_component_t rc, const char* name) {}
855 // static void model_NEW_set_autonomous_system(routing_component_t rc, const char* name) {}
856 // static void model_NEW_set_route(routing_component_t rc, const char* src, const char* dst, route_t route) {}
857 // static void model_NEW_set_ASroute(routing_component_t rc, const char* src, const char* dst, route_extended_t route) {}
858 // static void model_NEW_set_bypassroute(routing_component_t rc, const char* src, const char* dst, route_extended_t e_route) {}
859
860 /*** Business methods ***/
861 // static route_extended_t NEW_get_route(routing_component_t rc, const char* src,const char* dst) {return NULL;}
862 // static route_extended_t NEW_get_bypass_route(routing_component_t rc, const char* src,const char* dst) {return NULL;}
863 // static void NEW_finalize(routing_component_t rc) { xbt_free(rc);}
864
865 /*** Creation routing model functions ***/
866 // static void* model_NEW_create(void) {
867 //   routing_component_NEW_t new_component =  xbt_new0(s_routing_component_NEW_t,1);
868 //   new_component->generic_routing.set_processing_unit = model_NEW_set_processing_unit;
869 //   new_component->generic_routing.set_autonomous_system = model_NEW_set_autonomous_system;
870 //   new_component->generic_routing.set_route = model_NEW_set_route;
871 //   new_component->generic_routing.set_ASroute = model_NEW_set_ASroute;
872 //   new_component->generic_routing.set_bypassroute = model_NEW_set_bypassroute;
873 //   new_component->generic_routing.get_route = NEW_get_route;
874 //   new_component->generic_routing.get_bypass_route = NEW_get_bypass_route;
875 //   new_component->generic_routing.finalize = NEW_finalize;
876 //   /* initialization of internal structures */
877 //   return new_component;
878 // } /* mandatory */
879 // static void  model_NEW_load(void) {}   /* mandatory */
880 // static void  model_NEW_unload(void) {} /* mandatory */
881 // static void  model_NEW_end(void) {}    /* mandatory */
882
883 /* ************************************************************************** */
884 /* ************************* GENERIC PARSE FUNCTIONS ************************ */
885
886 void generic_set_processing_unit(routing_component_t rc, const char *name)
887 {
888   XBT_DEBUG("Load process unit \"%s\"", name);
889   int *id = xbt_new0(int, 1);
890   xbt_dict_t _to_index;
891   _to_index = current_routing->to_index;
892   *id = xbt_dict_length(_to_index);
893   xbt_dict_set(_to_index, name, id, xbt_free);
894 }
895
896 void generic_set_autonomous_system(routing_component_t rc, const char *name)
897 {
898   XBT_DEBUG("Load Autonomous system \"%s\"", name);
899   int *id = xbt_new0(int, 1);
900   xbt_dict_t _to_index;
901   _to_index = current_routing->to_index;
902   *id = xbt_dict_length(_to_index);
903   xbt_dict_set(_to_index, name, id, xbt_free);
904 }
905
906 int surf_pointer_resource_cmp(const void *a, const void *b)
907 {
908   return a != b;
909 }
910
911 int surf_link_resource_cmp(const void *a, const void *b)
912 {
913   return ! !memcmp(a, b, global_routing->size_of_link);
914 }
915
916 void generic_set_bypassroute(routing_component_t rc,
917                              const char *src, const char *dst,
918                              route_extended_t e_route)
919 {
920   XBT_DEBUG("Load bypassRoute from \"%s\" to \"%s\"", src, dst);
921   xbt_dict_t dict_bypassRoutes = rc->bypassRoutes;
922   char *route_name;
923
924   route_name = bprintf("%s#%s", src, dst);
925   xbt_assert(xbt_dynar_length(e_route->generic_route.link_list) > 0,
926              "Invalid count of links, must be greater than zero (%s,%s)",
927              src, dst);
928   xbt_assert(!xbt_dict_get_or_null(dict_bypassRoutes, route_name),
929              "The bypass route between \"%s\"(\"%s\") and \"%s\"(\"%s\") already exists",
930              src, e_route->src_gateway, dst, e_route->dst_gateway);
931
932   route_extended_t new_e_route =
933       generic_new_extended_route(SURF_ROUTING_RECURSIVE, e_route, 0);
934   xbt_dynar_free(&(e_route->generic_route.link_list));
935   xbt_free(e_route);
936
937   xbt_dict_set(dict_bypassRoutes, route_name, new_e_route,
938                (void (*)(void *)) generic_free_extended_route);
939   xbt_free(route_name);
940 }
941
942 /* ************************************************************************** */
943 /* *********************** GENERIC BUSINESS METHODS ************************* */
944
945 double generic_get_link_latency(routing_component_t rc,
946                                 const char *src, const char *dst,
947                                 route_extended_t route)
948 {
949   int need_to_clean = route ? 0 : 1;
950   void *link;
951   unsigned int i;
952   double latency = 0.0;
953
954   route = route ? route : rc->get_route(rc, src, dst);
955
956   xbt_dynar_foreach(route->generic_route.link_list, i, link) {
957     latency += get_link_latency(link);
958   }
959   if (need_to_clean)
960     generic_free_extended_route(route);
961   return latency;
962 }
963
964 xbt_dynar_t generic_get_onelink_routes(routing_component_t rc)
965 {
966   xbt_die("\"generic_get_onelink_routes\" not implemented yet");
967 }
968
969 route_extended_t generic_get_bypassroute(routing_component_t rc,
970                                          const char *src, const char *dst)
971 {
972   xbt_dict_t dict_bypassRoutes = rc->bypassRoutes;
973   routing_component_t src_as, dst_as;
974   int index_src, index_dst;
975   xbt_dynar_t path_src = NULL;
976   xbt_dynar_t path_dst = NULL;
977   routing_component_t current = NULL;
978   routing_component_t *current_src = NULL;
979   routing_component_t *current_dst = NULL;
980
981   /* (1) find the as where the src and dst are located */
982   void *src_data = xbt_lib_get_or_null(host_lib, src, ROUTING_HOST_LEVEL);
983   void *dst_data = xbt_lib_get_or_null(host_lib, dst, ROUTING_HOST_LEVEL);
984   if (!src_data)
985     src_data = xbt_lib_get_or_null(as_router_lib, src, ROUTING_ASR_LEVEL);
986   if (!dst_data)
987     dst_data = xbt_lib_get_or_null(as_router_lib, dst, ROUTING_ASR_LEVEL);
988
989   if (src_data == NULL || dst_data == NULL)
990     xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"",
991             src, dst, rc->name);
992
993   src_as = ((network_element_info_t) src_data)->rc_component;
994   dst_as = ((network_element_info_t) dst_data)->rc_component;
995
996   /* (2) find the path to the root routing component */
997   path_src = xbt_dynar_new(sizeof(routing_component_t), NULL);
998   current = src_as;
999   while (current != NULL) {
1000     xbt_dynar_push(path_src, &current);
1001     current = current->routing_father;
1002   }
1003   path_dst = xbt_dynar_new(sizeof(routing_component_t), NULL);
1004   current = dst_as;
1005   while (current != NULL) {
1006     xbt_dynar_push(path_dst, &current);
1007     current = current->routing_father;
1008   }
1009
1010   /* (3) find the common father */
1011   index_src = path_src->used - 1;
1012   index_dst = path_dst->used - 1;
1013   current_src = xbt_dynar_get_ptr(path_src, index_src);
1014   current_dst = xbt_dynar_get_ptr(path_dst, index_dst);
1015   while (index_src >= 0 && index_dst >= 0 && *current_src == *current_dst) {
1016     xbt_dynar_pop_ptr(path_src);
1017     xbt_dynar_pop_ptr(path_dst);
1018     index_src--;
1019     index_dst--;
1020     current_src = xbt_dynar_get_ptr(path_src, index_src);
1021     current_dst = xbt_dynar_get_ptr(path_dst, index_dst);
1022   }
1023
1024   int max_index_src = path_src->used - 1;
1025   int max_index_dst = path_dst->used - 1;
1026
1027   int max_index = max(max_index_src, max_index_dst);
1028   int i, max;
1029
1030   route_extended_t e_route_bypass = NULL;
1031
1032   for (max = 0; max <= max_index; max++) {
1033     for (i = 0; i < max; i++) {
1034       if (i <= max_index_src && max <= max_index_dst) {
1035         char *route_name = bprintf("%s#%s",
1036                                    (*(routing_component_t *)
1037                                     (xbt_dynar_get_ptr(path_src, i)))->name,
1038                                    (*(routing_component_t *)
1039                                     (xbt_dynar_get_ptr(path_dst, max)))->name);
1040         e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
1041         xbt_free(route_name);
1042       }
1043       if (e_route_bypass)
1044         break;
1045       if (max <= max_index_src && i <= max_index_dst) {
1046         char *route_name = bprintf("%s#%s",
1047                                    (*(routing_component_t *)
1048                                     (xbt_dynar_get_ptr(path_src, max)))->name,
1049                                    (*(routing_component_t *)
1050                                     (xbt_dynar_get_ptr(path_dst, i)))->name);
1051         e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
1052         xbt_free(route_name);
1053       }
1054       if (e_route_bypass)
1055         break;
1056     }
1057
1058     if (e_route_bypass)
1059       break;
1060
1061     if (max <= max_index_src && max <= max_index_dst) {
1062       char *route_name = bprintf("%s#%s",
1063                                  (*(routing_component_t *)
1064                                   (xbt_dynar_get_ptr(path_src, max)))->name,
1065                                  (*(routing_component_t *)
1066                                   (xbt_dynar_get_ptr(path_dst, max)))->name);
1067       e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
1068       xbt_free(route_name);
1069     }
1070     if (e_route_bypass)
1071       break;
1072   }
1073
1074   xbt_dynar_free(&path_src);
1075   xbt_dynar_free(&path_dst);
1076
1077   route_extended_t new_e_route = NULL;
1078
1079   if (e_route_bypass) {
1080     void *link;
1081     unsigned int cpt = 0;
1082     new_e_route = xbt_new0(s_route_extended_t, 1);
1083     new_e_route->src_gateway = xbt_strdup(e_route_bypass->src_gateway);
1084     new_e_route->dst_gateway = xbt_strdup(e_route_bypass->dst_gateway);
1085     new_e_route->generic_route.link_list =
1086         xbt_dynar_new(global_routing->size_of_link, NULL);
1087     xbt_dynar_foreach(e_route_bypass->generic_route.link_list, cpt, link) {
1088       xbt_dynar_push(new_e_route->generic_route.link_list, &link);
1089     }
1090   }
1091
1092   return new_e_route;
1093 }
1094
1095 /* ************************************************************************** */
1096 /* ************************* GENERIC AUX FUNCTIONS ************************** */
1097
1098 route_t
1099 generic_new_route(e_surf_routing_hierarchy_t hierarchy, void *data, int order)
1100 {
1101
1102   char *link_name;
1103   route_t new_route;
1104   unsigned int cpt;
1105   xbt_dynar_t links = NULL, links_id = NULL;
1106
1107   new_route = xbt_new0(s_route_t, 1);
1108   new_route->link_list = xbt_dynar_new(global_routing->size_of_link, NULL);
1109
1110   xbt_assert(hierarchy == SURF_ROUTING_BASE,
1111              "the hierarchy type is not SURF_ROUTING_BASE");
1112
1113   links = ((route_t) data)->link_list;
1114
1115
1116   links_id = new_route->link_list;
1117
1118   xbt_dynar_foreach(links, cpt, link_name) {
1119
1120     void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
1121     if (link) {
1122       if (order)
1123         xbt_dynar_push(links_id, &link);
1124       else
1125         xbt_dynar_unshift(links_id, &link);
1126     } else
1127       THROWF(mismatch_error, 0, "Link %s not found", link_name);
1128   }
1129
1130   return new_route;
1131 }
1132
1133 route_extended_t
1134 generic_new_extended_route(e_surf_routing_hierarchy_t hierarchy,
1135                            void *data, int order)
1136 {
1137
1138   char *link_name;
1139   route_extended_t e_route, new_e_route;
1140   route_t route;
1141   unsigned int cpt;
1142   xbt_dynar_t links = NULL, links_id = NULL;
1143
1144   new_e_route = xbt_new0(s_route_extended_t, 1);
1145   new_e_route->generic_route.link_list =
1146       xbt_dynar_new(global_routing->size_of_link, NULL);
1147   new_e_route->src_gateway = NULL;
1148   new_e_route->dst_gateway = NULL;
1149
1150   xbt_assert(hierarchy == SURF_ROUTING_BASE
1151              || hierarchy == SURF_ROUTING_RECURSIVE,
1152              "the hierarchy type is not defined");
1153
1154   if (hierarchy == SURF_ROUTING_BASE) {
1155
1156     route = (route_t) data;
1157     links = route->link_list;
1158
1159   } else if (hierarchy == SURF_ROUTING_RECURSIVE) {
1160
1161     e_route = (route_extended_t) data;
1162     xbt_assert(e_route->src_gateway
1163                && e_route->dst_gateway, "bad gateway, is null");
1164     links = e_route->generic_route.link_list;
1165
1166     /* remeber not erase the gateway names */
1167     new_e_route->src_gateway = strdup(e_route->src_gateway);
1168     new_e_route->dst_gateway = strdup(e_route->dst_gateway);
1169   }
1170
1171   links_id = new_e_route->generic_route.link_list;
1172
1173   xbt_dynar_foreach(links, cpt, link_name) {
1174
1175     void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
1176     if (link) {
1177       if (order)
1178         xbt_dynar_push(links_id, &link);
1179       else
1180         xbt_dynar_unshift(links_id, &link);
1181     } else
1182       THROWF(mismatch_error, 0, "Link %s not found", link_name);
1183   }
1184
1185   return new_e_route;
1186 }
1187
1188 void generic_free_route(route_t route)
1189 {
1190   if (route) {
1191     xbt_dynar_free(&(route->link_list));
1192     xbt_free(route);
1193   }
1194 }
1195
1196 void generic_free_extended_route(route_extended_t e_route)
1197 {
1198   if (e_route) {
1199     xbt_dynar_free(&(e_route->generic_route.link_list));
1200     xbt_free(e_route->src_gateway);
1201     xbt_free(e_route->dst_gateway);
1202     xbt_free(e_route);
1203   }
1204 }
1205
1206 static routing_component_t generic_as_exist(routing_component_t find_from,
1207                                             routing_component_t to_find)
1208 {
1209   //return to_find; // FIXME: BYPASSERROR OF FOREACH WITH BREAK
1210   xbt_dict_cursor_t cursor = NULL;
1211   char *key;
1212   int found = 0;
1213   routing_component_t elem;
1214   xbt_dict_foreach(find_from->routing_sons, cursor, key, elem) {
1215     if (to_find == elem || generic_as_exist(elem, to_find)) {
1216       found = 1;
1217       break;
1218     }
1219   }
1220   if (found)
1221     return to_find;
1222   return NULL;
1223 }
1224
1225 routing_component_t
1226 generic_autonomous_system_exist(routing_component_t rc, char *element)
1227 {
1228   //return rc; // FIXME: BYPASSERROR OF FOREACH WITH BREAK
1229   routing_component_t element_as, result, elem;
1230   xbt_dict_cursor_t cursor = NULL;
1231   char *key;
1232   element_as = ((network_element_info_t)
1233                 xbt_lib_get_or_null(as_router_lib, element,
1234                                     ROUTING_ASR_LEVEL))->rc_component;
1235   result = ((routing_component_t) - 1);
1236   if (element_as != rc)
1237     result = generic_as_exist(rc, element_as);
1238
1239   int found = 0;
1240   if (result) {
1241     xbt_dict_foreach(element_as->routing_sons, cursor, key, elem) {
1242       found = !strcmp(elem->name, element);
1243       if (found)
1244         break;
1245     }
1246     if (found)
1247       return element_as;
1248   }
1249   return NULL;
1250 }
1251
1252 routing_component_t
1253 generic_processing_units_exist(routing_component_t rc, char *element)
1254 {
1255   routing_component_t element_as;
1256   element_as = ((network_element_info_t)
1257                 xbt_lib_get_or_null(host_lib,
1258                                     element, ROUTING_HOST_LEVEL))->rc_component;
1259   if (element_as == rc)
1260     return element_as;
1261   return generic_as_exist(rc, element_as);
1262 }
1263
1264 void generic_src_dst_check(routing_component_t rc, const char *src,
1265                            const char *dst)
1266 {
1267
1268   void *src_data = xbt_lib_get_or_null(host_lib, src, ROUTING_HOST_LEVEL);
1269   void *dst_data = xbt_lib_get_or_null(host_lib, dst, ROUTING_HOST_LEVEL);
1270   if (!src_data)
1271     src_data = xbt_lib_get_or_null(as_router_lib, src, ROUTING_ASR_LEVEL);
1272   if (!dst_data)
1273     dst_data = xbt_lib_get_or_null(as_router_lib, dst, ROUTING_ASR_LEVEL);
1274
1275   if (src_data == NULL || dst_data == NULL)
1276     xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"",
1277             src, dst, rc->name);
1278
1279   routing_component_t src_as =
1280       ((network_element_info_t) src_data)->rc_component;
1281   routing_component_t dst_as =
1282       ((network_element_info_t) dst_data)->rc_component;
1283
1284   if (src_as != dst_as)
1285     xbt_die("The src(%s in %s) and dst(%s in %s) are in differents AS",
1286             src, src_as->name, dst, dst_as->name);
1287   if (rc != dst_as)
1288     xbt_die
1289         ("The routing component of src'%s' and dst'%s' is not the same as the network elements belong (%s?=%s?=%s)",
1290          src, dst, src_as->name, dst_as->name, rc->name);
1291 }
1292
1293 static void routing_parse_cluster(void)
1294 {
1295   char *host_id, *groups, *link_id = NULL;
1296
1297   s_sg_platf_host_cbarg_t host;
1298   s_sg_platf_link_cbarg_t link;
1299
1300   if (strcmp(struct_cluster->availability_trace, "")
1301       || strcmp(struct_cluster->state_trace, "")) {
1302     if (xbt_dict_size(patterns) == 0)
1303       patterns = xbt_dict_new();
1304     xbt_dict_set(patterns, "id", xbt_strdup(struct_cluster->id), free);
1305     xbt_dict_set(patterns, "prefix", xbt_strdup(struct_cluster->prefix), free);
1306     xbt_dict_set(patterns, "suffix", xbt_strdup(struct_cluster->suffix), free);
1307   }
1308
1309   unsigned int iter;
1310   int start, end, i;
1311   xbt_dynar_t radical_elements;
1312   xbt_dynar_t radical_ends;
1313
1314   XBT_DEBUG("<AS id=\"%s\"\trouting=\"Cluster\">", struct_cluster->id);
1315   sg_platf_new_AS_open(struct_cluster->id, "Cluster");
1316
1317   //Make all hosts
1318   radical_elements = xbt_str_split(struct_cluster->radical, ",");
1319   xbt_dynar_foreach(radical_elements, iter, groups) {
1320     memset(&host, 0, sizeof(host));
1321
1322     radical_ends = xbt_str_split(groups, "-");
1323     start = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 0, char *));
1324
1325     switch (xbt_dynar_length(radical_ends)) {
1326     case 1:
1327       end = start;
1328       break;
1329     case 2:
1330       end = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 1, char *));
1331       break;
1332     default:
1333       surf_parse_error("Malformed radical");
1334       break;
1335     }
1336     for (i = start; i <= end; i++) {
1337       host_id =
1338           bprintf("%s%d%s", struct_cluster->prefix, i, struct_cluster->suffix);
1339       link_id = bprintf("%s_link_%d", struct_cluster->id, i);
1340
1341       XBT_DEBUG("<host\tid=\"%s\"\tpower=\"%f\">", host_id,
1342                 struct_cluster->power);
1343       host.id = host_id;
1344       if (strcmp(struct_cluster->availability_trace, "")) {
1345         xbt_dict_set(patterns, "radical", bprintf("%d", i), xbt_free);
1346         char *tmp_availability_file =
1347             xbt_strdup(struct_cluster->availability_trace);
1348         xbt_str_varsubst(tmp_availability_file, patterns);
1349         XBT_DEBUG("\tavailability_file=\"%s\"", tmp_availability_file);
1350         host.power_trace = tmgr_trace_new(tmp_availability_file);
1351         xbt_free(tmp_availability_file);
1352       } else {
1353         XBT_DEBUG("\tavailability_file=\"\"");
1354       }
1355       if (strcmp(struct_cluster->state_trace, "")) {
1356         char *tmp_state_file = xbt_strdup(struct_cluster->state_trace);
1357         xbt_str_varsubst(tmp_state_file, patterns);
1358         XBT_DEBUG("\tstate_file=\"%s\"", tmp_state_file);
1359         host.state_trace = tmgr_trace_new(tmp_state_file);
1360         xbt_free(tmp_state_file);
1361       } else {
1362         XBT_DEBUG("\tstate_file=\"\"");
1363       }
1364
1365       host.power_peak = struct_cluster->power;
1366       host.power_scale = 1.0;
1367       host.core_amount = struct_cluster->core_amount;
1368       host.initial_state = SURF_RESOURCE_ON;
1369       host.coord = "";
1370       sg_platf_new_host(&host);
1371       XBT_DEBUG("</host>");
1372
1373       XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_id,
1374                 struct_cluster->bw, struct_cluster->lat);
1375
1376       memset(&link, 0, sizeof(link));
1377       link.id = link_id;
1378       link.bandwidth = struct_cluster->bw;
1379       link.latency = struct_cluster->lat;
1380       link.state = SURF_RESOURCE_ON;
1381
1382       switch (struct_cluster->sharing_policy) {
1383       case A_surfxml_cluster_sharing_policy_SHARED:
1384         link.policy = SURF_LINK_SHARED;
1385         break;
1386       case A_surfxml_cluster_sharing_policy_FULLDUPLEX:
1387         link.policy = SURF_LINK_FULLDUPLEX;
1388         break;
1389       case A_surfxml_cluster_sharing_policy_FATPIPE:
1390         link.policy = SURF_LINK_FATPIPE;
1391         break;
1392       default:
1393         surf_parse_error(bprintf
1394                          ("Invalid cluster sharing policy for cluster %s",
1395                           struct_cluster->id));
1396         break;
1397       }
1398       sg_platf_new_link(&link);
1399
1400       surf_parsing_link_up_down_t info =
1401           xbt_new0(s_surf_parsing_link_up_down_t, 1);
1402       if (link.policy == SURF_LINK_FULLDUPLEX) {
1403         char *tmp_link = bprintf("%s_UP", link_id);
1404         info->link_up =
1405             xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
1406         free(tmp_link);
1407         tmp_link = bprintf("%s_DOWN", link_id);
1408         info->link_down =
1409             xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
1410         free(tmp_link);
1411       } else {
1412         info->link_up = xbt_lib_get_or_null(link_lib, link_id, SURF_LINK_LEVEL);
1413         info->link_down = info->link_up;
1414       }
1415       surf_routing_cluster_add_link(host_id, info);
1416
1417       xbt_free(link_id);
1418       xbt_free(host_id);
1419     }
1420
1421     xbt_dynar_free(&radical_ends);
1422   }
1423   xbt_dynar_free(&radical_elements);
1424
1425   // Add a router. It is magically used thanks to the way in which surf_routing_cluster is written, and it's very useful to connect clusters together
1426   XBT_DEBUG(" ");
1427   XBT_DEBUG("<router id=\"%s\"/>", struct_cluster->router_id);
1428   s_sg_platf_router_cbarg_t router;
1429   char *newid = NULL;
1430   memset(&router, 0, sizeof(router));
1431   router.id = struct_cluster->router_id;
1432   router.coord = "";
1433   if (!router.id || !strcmp(router.id, ""))
1434     router.id = newid =
1435         bprintf("%s%s_router%s", struct_cluster->prefix, struct_cluster->id,
1436                 struct_cluster->suffix);
1437   sg_platf_new_router(&router);
1438   free(newid);
1439
1440   //Make the backbone
1441   if ((struct_cluster->bb_bw != 0) && (struct_cluster->bb_lat != 0)) {
1442     char *link_backbone = bprintf("%s_backbone", struct_cluster->id);
1443     XBT_DEBUG("<link\tid=\"%s\" bw=\"%f\" lat=\"%f\"/>", link_backbone,
1444               struct_cluster->bb_bw, struct_cluster->bb_lat);
1445
1446     memset(&link, 0, sizeof(link));
1447     link.id = link_backbone;
1448     link.bandwidth = struct_cluster->bb_bw;
1449     link.latency = struct_cluster->bb_lat;
1450     link.state = SURF_RESOURCE_ON;
1451
1452     switch (struct_cluster->bb_sharing_policy) {
1453     case A_surfxml_cluster_bb_sharing_policy_FATPIPE:
1454       link.policy = SURF_LINK_FATPIPE;
1455       break;
1456     case A_surfxml_cluster_bb_sharing_policy_SHARED:
1457       link.policy = SURF_LINK_SHARED;
1458       break;
1459     default:
1460       surf_parse_error(bprintf
1461                        ("Invalid bb sharing policy in cluster %s",
1462                         struct_cluster->id));
1463       break;
1464     }
1465
1466     sg_platf_new_link(&link);
1467
1468     surf_parsing_link_up_down_t info =
1469         xbt_new0(s_surf_parsing_link_up_down_t, 1);
1470     info->link_up =
1471         xbt_lib_get_or_null(link_lib, link_backbone, SURF_LINK_LEVEL);
1472     info->link_down = info->link_up;
1473     surf_routing_cluster_add_link(struct_cluster->id, info);
1474
1475     free(link_backbone);
1476   }
1477
1478   XBT_DEBUG(" ");
1479
1480   char *new_suffix = xbt_strdup("");
1481
1482   radical_elements = xbt_str_split(struct_cluster->suffix, ".");
1483   xbt_dynar_foreach(radical_elements, iter, groups) {
1484     if (strcmp(groups, "")) {
1485       char *old_suffix = new_suffix;
1486       new_suffix = bprintf("%s\\.%s", old_suffix, groups);
1487       free(old_suffix);
1488     }
1489   }
1490
1491   xbt_dynar_free(&radical_elements);
1492   xbt_free(new_suffix);
1493
1494   if (strcmp(struct_cluster->availability_trace, "")
1495       || strcmp(struct_cluster->state_trace, ""))
1496     xbt_dict_free(&patterns);
1497
1498   XBT_DEBUG("</AS>");
1499   sg_platf_new_AS_close();
1500   XBT_DEBUG(" ");
1501 }
1502
1503 /*
1504  * This function take a string and replace parameters from patterns dict.
1505  * It returns the new value.
1506  */
1507 static char *replace_random_parameter(char *string)
1508 {
1509   char *test_string = NULL;
1510
1511   if (xbt_dict_size(random_value) == 0)
1512     return string;
1513
1514   string = xbt_str_varsubst(string, patterns);  // for patterns of cluster
1515   test_string = bprintf("${%s}", string);
1516   test_string = xbt_str_varsubst(test_string, random_value);    //Add ${xxxxx} for random Generator
1517
1518   if (strcmp(test_string, "")) {        //if not empty, keep this value.
1519     xbt_free(string);
1520     string = test_string;
1521   }                             //In other case take old value (without ${})
1522   else
1523     free(test_string);
1524   return string;
1525 }
1526
1527 static void routing_parse_postparse(void)
1528 {
1529   xbt_dict_free(&random_value);
1530   xbt_dict_free(&patterns);
1531 }
1532
1533 static void routing_parse_peer(sg_platf_peer_cbarg_t peer)
1534 {
1535   static int AX_ptr = 0;
1536   char *host_id = NULL;
1537   char *router_id, *link_router, *link_backbone, *link_id_up, *link_id_down;
1538
1539   static unsigned int surfxml_buffer_stack_stack_ptr = 1;
1540   static unsigned int surfxml_buffer_stack_stack[1024];
1541
1542   surfxml_buffer_stack_stack[0] = 0;
1543
1544   surfxml_bufferstack_push(1);
1545
1546   XBT_DEBUG("<AS id=\"%s\"\trouting=\"Full\">", peer->id);
1547   sg_platf_new_AS_open(peer->id, "Full");
1548
1549   XBT_DEBUG(" ");
1550   host_id = HOST_PEER(peer->id);
1551   router_id = ROUTER_PEER(peer->id);
1552   link_id_up = LINK_UP_PEER(peer->id);
1553   link_id_down = LINK_DOWN_PEER(peer->id);
1554
1555   link_router = bprintf("%s_link_router", peer->id);
1556   link_backbone = bprintf("%s_backbone", peer->id);
1557
1558   XBT_DEBUG("<host\tid=\"%s\"\tpower=\"%f\"/>", host_id, peer->power);
1559   s_sg_platf_host_cbarg_t host;
1560   memset(&host, 0, sizeof(host));
1561   host.initial_state = SURF_RESOURCE_ON;
1562   host.id = host_id;
1563   host.power_peak = peer->power;
1564   host.power_scale = 1.0;
1565   host.power_trace = peer->availability_trace;
1566   host.state_trace = peer->state_trace;
1567   host.core_amount = 1;
1568   sg_platf_new_host(&host);
1569
1570
1571   XBT_DEBUG("<router id=\"%s\"\tcoordinates=\"%s\"/>", router_id, peer->coord);
1572   s_sg_platf_router_cbarg_t router;
1573   memset(&router, 0, sizeof(router));
1574   router.id = router_id;
1575   router.coord = peer->coord;
1576   sg_platf_new_router(&router);
1577
1578   XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_id_up,
1579             peer->bw_in, peer->lat);
1580   s_sg_platf_link_cbarg_t link;
1581   memset(&link, 0, sizeof(link));
1582   link.state = SURF_RESOURCE_ON;
1583   link.policy = SURF_LINK_SHARED;
1584   link.id = link_id_up;
1585   link.bandwidth = peer->bw_in;
1586   link.latency = peer->lat;
1587   sg_platf_new_link(&link);
1588
1589   // FIXME: dealing with full duplex is not the role of this piece of code, I'd say [Mt]
1590   // Instead, it should be created fullduplex, and the models will do what's needed in this case
1591   XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_id_down,
1592             peer->bw_out, peer->lat);
1593   link.id = link_id_down;
1594   sg_platf_new_link(&link);
1595
1596   XBT_DEBUG(" ");
1597
1598   // begin here
1599   XBT_DEBUG("<route\tsrc=\"%s\"\tdst=\"%s\"", host_id, router_id);
1600   XBT_DEBUG("symmetrical=\"NO\">");
1601   SURFXML_BUFFER_SET(route_src, host_id);
1602   SURFXML_BUFFER_SET(route_dst, router_id);
1603   A_surfxml_route_symmetrical = A_surfxml_route_symmetrical_NO;
1604   SURFXML_START_TAG(route);
1605
1606   XBT_DEBUG("<link_ctn\tid=\"%s\"/>", link_id_up);
1607   SURFXML_BUFFER_SET(link_ctn_id, link_id_up);
1608   A_surfxml_link_ctn_direction = A_surfxml_link_ctn_direction_NONE;
1609   SURFXML_START_TAG(link_ctn);
1610   SURFXML_END_TAG(link_ctn);
1611
1612   XBT_DEBUG("</route>");
1613   SURFXML_END_TAG(route);
1614
1615   //Opposite Route
1616   XBT_DEBUG("<route\tsrc=\"%s\"\tdst=\"%s\"", router_id, host_id);
1617   XBT_DEBUG("symmetrical=\"NO\">");
1618   SURFXML_BUFFER_SET(route_src, router_id);
1619   SURFXML_BUFFER_SET(route_dst, host_id);
1620   A_surfxml_route_symmetrical = A_surfxml_route_symmetrical_NO;
1621   SURFXML_START_TAG(route);
1622
1623   XBT_DEBUG("<link_ctn\tid=\"%s\"/>", link_id_down);
1624   SURFXML_BUFFER_SET(link_ctn_id, link_id_down);
1625   A_surfxml_link_ctn_direction = A_surfxml_link_ctn_direction_NONE;
1626   SURFXML_START_TAG(link_ctn);
1627   SURFXML_END_TAG(link_ctn);
1628
1629   XBT_DEBUG("</route>");
1630   SURFXML_END_TAG(route);
1631
1632   XBT_DEBUG("</AS>");
1633   sg_platf_new_AS_close();
1634   XBT_DEBUG(" ");
1635
1636   //xbt_dynar_free(&tab_elements_num);
1637   free(host_id);
1638   free(router_id);
1639   free(link_router);
1640   free(link_backbone);
1641   free(link_id_up);
1642   free(link_id_down);
1643   surfxml_bufferstack_pop(1);
1644 }
1645
1646 static void routing_parse_Srandom(void)
1647 {
1648   double mean, std, min, max, seed;
1649   char *random_id = A_surfxml_random_id;
1650   char *random_radical = A_surfxml_random_radical;
1651   char *rd_name = NULL;
1652   char *rd_value;
1653   mean = surf_parse_get_double(A_surfxml_random_mean);
1654   std = surf_parse_get_double(A_surfxml_random_std_deviation);
1655   min = surf_parse_get_double(A_surfxml_random_min);
1656   max = surf_parse_get_double(A_surfxml_random_max);
1657   seed = surf_parse_get_double(A_surfxml_random_seed);
1658
1659   double res = 0;
1660   int i = 0;
1661   random_data_t random = xbt_new0(s_random_data_t, 1);
1662   char *tmpbuf;
1663
1664   xbt_dynar_t radical_elements;
1665   unsigned int iter;
1666   char *groups;
1667   int start, end;
1668   xbt_dynar_t radical_ends;
1669
1670   random->generator = A_surfxml_random_generator;
1671   random->seed = seed;
1672   random->min = min;
1673   random->max = max;
1674
1675   /* Check user stupidities */
1676   if (max < min)
1677     THROWF(arg_error, 0, "random->max < random->min (%f < %f)", max, min);
1678   if (mean < min)
1679     THROWF(arg_error, 0, "random->mean < random->min (%f < %f)", mean, min);
1680   if (mean > max)
1681     THROWF(arg_error, 0, "random->mean > random->max (%f > %f)", mean, max);
1682
1683   /* normalize the mean and standard deviation before storing */
1684   random->mean = (mean - min) / (max - min);
1685   random->std = std / (max - min);
1686
1687   if (random->mean * (1 - random->mean) < random->std * random->std)
1688     THROWF(arg_error, 0, "Invalid mean and standard deviation (%f and %f)",
1689            random->mean, random->std);
1690
1691   XBT_DEBUG
1692       ("id = '%s' min = '%f' max = '%f' mean = '%f' std_deviatinon = '%f' generator = '%d' seed = '%ld' radical = '%s'",
1693        random_id, random->min, random->max, random->mean, random->std,
1694        random->generator, random->seed, random_radical);
1695
1696   if (xbt_dict_size(random_value) == 0)
1697     random_value = xbt_dict_new();
1698
1699   if (!strcmp(random_radical, "")) {
1700     res = random_generate(random);
1701     rd_value = bprintf("%f", res);
1702     xbt_dict_set(random_value, random_id, rd_value, free);
1703   } else {
1704     radical_elements = xbt_str_split(random_radical, ",");
1705     xbt_dynar_foreach(radical_elements, iter, groups) {
1706       radical_ends = xbt_str_split(groups, "-");
1707       switch (xbt_dynar_length(radical_ends)) {
1708       case 1:
1709         xbt_assert(!xbt_dict_get_or_null(random_value, random_id),
1710                    "Custom Random '%s' already exists !", random_id);
1711         res = random_generate(random);
1712         tmpbuf =
1713             bprintf("%s%d", random_id,
1714                     atoi(xbt_dynar_getfirst_as(radical_ends, char *)));
1715         xbt_dict_set(random_value, tmpbuf, bprintf("%f", res), free);
1716         xbt_free(tmpbuf);
1717         break;
1718
1719       case 2:
1720         start = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 0, char *));
1721         end = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 1, char *));
1722         for (i = start; i <= end; i++) {
1723           xbt_assert(!xbt_dict_get_or_null(random_value, random_id),
1724                      "Custom Random '%s' already exists !", bprintf("%s%d",
1725                                                                     random_id,
1726                                                                     i));
1727           res = random_generate(random);
1728           tmpbuf = bprintf("%s%d", random_id, i);
1729           xbt_dict_set(random_value, tmpbuf, bprintf("%f", res), free);
1730           xbt_free(tmpbuf);
1731         }
1732         break;
1733       default:
1734         XBT_INFO("Malformed radical");
1735         break;
1736       }
1737       res = random_generate(random);
1738       rd_name = bprintf("%s_router", random_id);
1739       rd_value = bprintf("%f", res);
1740       xbt_dict_set(random_value, rd_name, rd_value, free);
1741
1742       xbt_dynar_free(&radical_ends);
1743     }
1744     free(rd_name);
1745     xbt_dynar_free(&radical_elements);
1746   }
1747 }
1748
1749 void routing_register_callbacks()
1750 {
1751   sg_platf_host_add_cb(parse_S_host);
1752   sg_platf_router_add_cb(parse_S_router);
1753
1754   surfxml_add_callback(STag_surfxml_random_cb_list, &routing_parse_Srandom);
1755
1756   surfxml_add_callback(STag_surfxml_route_cb_list, &routing_parse_S_route);
1757   surfxml_add_callback(STag_surfxml_ASroute_cb_list, &routing_parse_S_ASroute);
1758   surfxml_add_callback(STag_surfxml_bypassRoute_cb_list,
1759                        &routing_parse_S_bypassRoute);
1760
1761   surfxml_add_callback(ETag_surfxml_link_ctn_cb_list, &routing_parse_link_ctn);
1762
1763   surfxml_add_callback(ETag_surfxml_route_cb_list, &routing_parse_E_route);
1764   surfxml_add_callback(ETag_surfxml_ASroute_cb_list, &routing_parse_E_ASroute);
1765   surfxml_add_callback(ETag_surfxml_bypassRoute_cb_list,
1766                        &routing_parse_E_bypassRoute);
1767
1768   surfxml_add_callback(STag_surfxml_cluster_cb_list, &routing_parse_cluster);
1769
1770   sg_platf_peer_add_cb(routing_parse_peer);
1771   sg_platf_postparse_add_cb(routing_parse_postparse);
1772
1773 #ifdef HAVE_TRACING
1774   instr_routing_define_callbacks();
1775 #endif
1776 }