Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
populate the routing_none_finalize to make sure that we always call these functions
[simgrid.git] / src / surf / surf_routing_generic.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_LOG_NEW_DEFAULT_SUBCATEGORY(surf_routing_generic, surf_route, "Generic implementation of the surf routing");
16
17 AS_t model_generic_create_sized(size_t childsize) {
18   AS_t new_component = model_none_create_sized(childsize);
19
20   new_component->parse_PU = generic_parse_PU;
21   new_component->parse_AS = generic_parse_AS;
22   new_component->parse_route = NULL;
23   new_component->parse_ASroute = NULL;
24   new_component->parse_bypassroute = generic_parse_bypassroute;
25   new_component->get_route = NULL;
26   new_component->get_latency = generic_get_link_latency;
27   new_component->get_onelink_routes = NULL;
28   new_component->get_bypass_route =
29       generic_get_bypassroute;
30   new_component->finalize = model_none_finalize;
31   new_component->to_index = xbt_dict_new();
32   new_component->bypassRoutes = xbt_dict_new();
33
34   return new_component;
35 }
36
37
38 void generic_parse_PU(AS_t as, const char *name)
39 {
40   XBT_DEBUG("Load process unit \"%s\"", name);
41   int *id = xbt_new0(int, 1);
42   xbt_dict_t _to_index;
43   _to_index = as->to_index;
44   *id = xbt_dict_length(_to_index);
45   xbt_dict_set(_to_index, name, id, xbt_free);
46 }
47
48 void generic_parse_AS(AS_t as, const char *name)
49 {
50   XBT_DEBUG("Load Autonomous system \"%s\"", name);
51   int *id = xbt_new0(int, 1);
52   xbt_dict_t _to_index;
53   _to_index = as->to_index;
54   *id = xbt_dict_length(_to_index);
55   xbt_dict_set(_to_index, name, id, xbt_free);
56 }
57
58 void generic_parse_bypassroute(AS_t rc,
59                              const char *src, const char *dst,
60                              route_extended_t e_route)
61 {
62   XBT_DEBUG("Load bypassRoute from \"%s\" to \"%s\"", src, dst);
63   xbt_dict_t dict_bypassRoutes = rc->bypassRoutes;
64   char *route_name;
65
66   route_name = bprintf("%s#%s", src, dst);
67   xbt_assert(xbt_dynar_length(e_route->generic_route.link_list) > 0,
68              "Invalid count of links, must be greater than zero (%s,%s)",
69              src, dst);
70   xbt_assert(!xbt_dict_get_or_null(dict_bypassRoutes, route_name),
71              "The bypass route between \"%s\"(\"%s\") and \"%s\"(\"%s\") already exists",
72              src, e_route->src_gateway, dst, e_route->dst_gateway);
73
74   route_extended_t new_e_route =
75       generic_new_extended_route(SURF_ROUTING_RECURSIVE, e_route, 0);
76   xbt_dynar_free(&(e_route->generic_route.link_list));
77   xbt_free(e_route);
78
79   xbt_dict_set(dict_bypassRoutes, route_name, new_e_route,
80                (void (*)(void *)) generic_free_extended_route);
81   xbt_free(route_name);
82 }
83
84 /* ************************************************************************** */
85 /* *********************** GENERIC BUSINESS METHODS ************************* */
86
87 double generic_get_link_latency(AS_t rc,
88                                 const char *src, const char *dst,
89                                 route_extended_t route)
90 {
91   int need_to_clean = route ? 0 : 1;
92   void *link;
93   unsigned int i;
94   double latency = 0.0;
95
96   route = route ? route : rc->get_route(rc, src, dst);
97
98   xbt_dynar_foreach(route->generic_route.link_list, i, link) {
99     latency += surf_network_model->extension.network.get_link_latency(link);
100   }
101   if (need_to_clean)
102     generic_free_extended_route(route);
103   return latency;
104 }
105
106 xbt_dynar_t generic_get_onelink_routes(AS_t rc)
107 {
108   xbt_die("\"generic_get_onelink_routes\" not implemented yet");
109 }
110
111 route_extended_t generic_get_bypassroute(AS_t rc,
112                                          const char *src, const char *dst)
113 {
114   xbt_dict_t dict_bypassRoutes = rc->bypassRoutes;
115   AS_t src_as, dst_as;
116   int index_src, index_dst;
117   xbt_dynar_t path_src = NULL;
118   xbt_dynar_t path_dst = NULL;
119   AS_t current = NULL;
120   AS_t *current_src = NULL;
121   AS_t *current_dst = NULL;
122
123   /* (1) find the as where the src and dst are located */
124   void *src_data = xbt_lib_get_or_null(host_lib, src, ROUTING_HOST_LEVEL);
125   void *dst_data = xbt_lib_get_or_null(host_lib, dst, ROUTING_HOST_LEVEL);
126   if (!src_data)
127     src_data = xbt_lib_get_or_null(as_router_lib, src, ROUTING_ASR_LEVEL);
128   if (!dst_data)
129     dst_data = xbt_lib_get_or_null(as_router_lib, dst, ROUTING_ASR_LEVEL);
130
131   if (src_data == NULL || dst_data == NULL)
132     xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"",
133             src, dst, rc->name);
134
135   src_as = ((network_element_info_t) src_data)->rc_component;
136   dst_as = ((network_element_info_t) dst_data)->rc_component;
137
138   /* (2) find the path to the root routing component */
139   path_src = xbt_dynar_new(sizeof(AS_t), NULL);
140   current = src_as;
141   while (current != NULL) {
142     xbt_dynar_push(path_src, &current);
143     current = current->routing_father;
144   }
145   path_dst = xbt_dynar_new(sizeof(AS_t), NULL);
146   current = dst_as;
147   while (current != NULL) {
148     xbt_dynar_push(path_dst, &current);
149     current = current->routing_father;
150   }
151
152   /* (3) find the common father */
153   index_src = path_src->used - 1;
154   index_dst = path_dst->used - 1;
155   current_src = xbt_dynar_get_ptr(path_src, index_src);
156   current_dst = xbt_dynar_get_ptr(path_dst, index_dst);
157   while (index_src >= 0 && index_dst >= 0 && *current_src == *current_dst) {
158     xbt_dynar_pop_ptr(path_src);
159     xbt_dynar_pop_ptr(path_dst);
160     index_src--;
161     index_dst--;
162     current_src = xbt_dynar_get_ptr(path_src, index_src);
163     current_dst = xbt_dynar_get_ptr(path_dst, index_dst);
164   }
165
166   int max_index_src = path_src->used - 1;
167   int max_index_dst = path_dst->used - 1;
168
169   int max_index = max(max_index_src, max_index_dst);
170   int i, max;
171
172   route_extended_t e_route_bypass = NULL;
173
174   for (max = 0; max <= max_index; max++) {
175     for (i = 0; i < max; i++) {
176       if (i <= max_index_src && max <= max_index_dst) {
177         char *route_name = bprintf("%s#%s",
178                                    (*(AS_t *)
179                                     (xbt_dynar_get_ptr(path_src, i)))->name,
180                                    (*(AS_t *)
181                                     (xbt_dynar_get_ptr(path_dst, max)))->name);
182         e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
183         xbt_free(route_name);
184       }
185       if (e_route_bypass)
186         break;
187       if (max <= max_index_src && i <= max_index_dst) {
188         char *route_name = bprintf("%s#%s",
189                                    (*(AS_t *)
190                                     (xbt_dynar_get_ptr(path_src, max)))->name,
191                                    (*(AS_t *)
192                                     (xbt_dynar_get_ptr(path_dst, i)))->name);
193         e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
194         xbt_free(route_name);
195       }
196       if (e_route_bypass)
197         break;
198     }
199
200     if (e_route_bypass)
201       break;
202
203     if (max <= max_index_src && max <= max_index_dst) {
204       char *route_name = bprintf("%s#%s",
205                                  (*(AS_t *)
206                                   (xbt_dynar_get_ptr(path_src, max)))->name,
207                                  (*(AS_t *)
208                                   (xbt_dynar_get_ptr(path_dst, max)))->name);
209       e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
210       xbt_free(route_name);
211     }
212     if (e_route_bypass)
213       break;
214   }
215
216   xbt_dynar_free(&path_src);
217   xbt_dynar_free(&path_dst);
218
219   route_extended_t new_e_route = NULL;
220
221   if (e_route_bypass) {
222     void *link;
223     unsigned int cpt = 0;
224     new_e_route = xbt_new0(s_route_extended_t, 1);
225     new_e_route->src_gateway = xbt_strdup(e_route_bypass->src_gateway);
226     new_e_route->dst_gateway = xbt_strdup(e_route_bypass->dst_gateway);
227     new_e_route->generic_route.link_list =
228         xbt_dynar_new(global_routing->size_of_link, NULL);
229     xbt_dynar_foreach(e_route_bypass->generic_route.link_list, cpt, link) {
230       xbt_dynar_push(new_e_route->generic_route.link_list, &link);
231     }
232   }
233
234   return new_e_route;
235 }
236
237 /* ************************************************************************** */
238 /* ************************* GENERIC AUX FUNCTIONS ************************** */
239
240 route_t
241 generic_new_route(e_surf_routing_hierarchy_t hierarchy, void *data, int order)
242 {
243
244   char *link_name;
245   route_t new_route;
246   unsigned int cpt;
247   xbt_dynar_t links = NULL, links_id = NULL;
248
249   new_route = xbt_new0(s_route_t, 1);
250   new_route->link_list = xbt_dynar_new(global_routing->size_of_link, NULL);
251
252   xbt_assert(hierarchy == SURF_ROUTING_BASE,
253              "the hierarchy type is not SURF_ROUTING_BASE");
254
255   links = ((route_t) data)->link_list;
256
257
258   links_id = new_route->link_list;
259
260   xbt_dynar_foreach(links, cpt, link_name) {
261
262     void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
263     if (link) {
264       if (order)
265         xbt_dynar_push(links_id, &link);
266       else
267         xbt_dynar_unshift(links_id, &link);
268     } else
269       THROWF(mismatch_error, 0, "Link %s not found", link_name);
270   }
271
272   return new_route;
273 }
274
275 route_extended_t
276 generic_new_extended_route(e_surf_routing_hierarchy_t hierarchy,
277                            void *data, int order)
278 {
279
280   char *link_name;
281   route_extended_t e_route, new_e_route;
282   route_t route;
283   unsigned int cpt;
284   xbt_dynar_t links = NULL, links_id = NULL;
285
286   new_e_route = xbt_new0(s_route_extended_t, 1);
287   new_e_route->generic_route.link_list =
288       xbt_dynar_new(global_routing->size_of_link, NULL);
289   new_e_route->src_gateway = NULL;
290   new_e_route->dst_gateway = NULL;
291
292   xbt_assert(hierarchy == SURF_ROUTING_BASE
293              || hierarchy == SURF_ROUTING_RECURSIVE,
294              "the hierarchy type is not defined");
295
296   if (hierarchy == SURF_ROUTING_BASE) {
297
298     route = (route_t) data;
299     links = route->link_list;
300
301   } else if (hierarchy == SURF_ROUTING_RECURSIVE) {
302
303     e_route = (route_extended_t) data;
304     xbt_assert(e_route->src_gateway
305                && e_route->dst_gateway, "bad gateway, is null");
306     links = e_route->generic_route.link_list;
307
308     /* remeber not erase the gateway names */
309     new_e_route->src_gateway = strdup(e_route->src_gateway);
310     new_e_route->dst_gateway = strdup(e_route->dst_gateway);
311   }
312
313   links_id = new_e_route->generic_route.link_list;
314
315   xbt_dynar_foreach(links, cpt, link_name) {
316
317     void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
318     if (link) {
319       if (order)
320         xbt_dynar_push(links_id, &link);
321       else
322         xbt_dynar_unshift(links_id, &link);
323     } else
324       THROWF(mismatch_error, 0, "Link %s not found", link_name);
325   }
326
327   return new_e_route;
328 }
329
330 void generic_free_route(route_t route)
331 {
332   if (route) {
333     xbt_dynar_free(&(route->link_list));
334     xbt_free(route);
335   }
336 }
337
338 void generic_free_extended_route(route_extended_t e_route)
339 {
340   if (e_route) {
341     xbt_dynar_free(&(e_route->generic_route.link_list));
342     xbt_free(e_route->src_gateway);
343     xbt_free(e_route->dst_gateway);
344     xbt_free(e_route);
345   }
346 }
347
348 static AS_t generic_as_exist(AS_t find_from,
349                                             AS_t to_find)
350 {
351   //return to_find; // FIXME: BYPASSERROR OF FOREACH WITH BREAK
352   xbt_dict_cursor_t cursor = NULL;
353   char *key;
354   int found = 0;
355   AS_t elem;
356   xbt_dict_foreach(find_from->routing_sons, cursor, key, elem) {
357     if (to_find == elem || generic_as_exist(elem, to_find)) {
358       found = 1;
359       break;
360     }
361   }
362   if (found)
363     return to_find;
364   return NULL;
365 }
366
367 AS_t
368 generic_autonomous_system_exist(AS_t rc, char *element)
369 {
370   //return rc; // FIXME: BYPASSERROR OF FOREACH WITH BREAK
371   AS_t element_as, result, elem;
372   xbt_dict_cursor_t cursor = NULL;
373   char *key;
374   element_as = ((network_element_info_t)
375                 xbt_lib_get_or_null(as_router_lib, element,
376                                     ROUTING_ASR_LEVEL))->rc_component;
377   result = ((AS_t) - 1);
378   if (element_as != rc)
379     result = generic_as_exist(rc, element_as);
380
381   int found = 0;
382   if (result) {
383     xbt_dict_foreach(element_as->routing_sons, cursor, key, elem) {
384       found = !strcmp(elem->name, element);
385       if (found)
386         break;
387     }
388     if (found)
389       return element_as;
390   }
391   return NULL;
392 }
393
394 AS_t
395 generic_processing_units_exist(AS_t rc, char *element)
396 {
397   AS_t element_as;
398   element_as = ((network_element_info_t)
399                 xbt_lib_get_or_null(host_lib,
400                                     element, ROUTING_HOST_LEVEL))->rc_component;
401   if (element_as == rc)
402     return element_as;
403   return generic_as_exist(rc, element_as);
404 }
405
406 void generic_src_dst_check(AS_t rc, const char *src,
407                            const char *dst)
408 {
409
410   void *src_data = xbt_lib_get_or_null(host_lib, src, ROUTING_HOST_LEVEL);
411   void *dst_data = xbt_lib_get_or_null(host_lib, dst, ROUTING_HOST_LEVEL);
412   if (!src_data)
413     src_data = xbt_lib_get_or_null(as_router_lib, src, ROUTING_ASR_LEVEL);
414   if (!dst_data)
415     dst_data = xbt_lib_get_or_null(as_router_lib, dst, ROUTING_ASR_LEVEL);
416
417   if (src_data == NULL || dst_data == NULL)
418     xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"",
419             src, dst, rc->name);
420
421   AS_t src_as =
422       ((network_element_info_t) src_data)->rc_component;
423   AS_t dst_as =
424       ((network_element_info_t) dst_data)->rc_component;
425
426   if (src_as != dst_as)
427     xbt_die("The src(%s in %s) and dst(%s in %s) are in differents AS",
428             src, src_as->name, dst, dst_as->name);
429   if (rc != dst_as)
430     xbt_die
431         ("The routing component of src'%s' and dst'%s' is not the same as the network elements belong (%s?=%s?=%s)",
432          src, dst, src_as->name, dst_as->name, rc->name);
433 }