Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
6debb30f0c80a76380bfb920a3386a55c9690a82
[simgrid.git] / src / surf / surf_routing_generic.cpp
1 /* Copyright (c) 2009-2013. 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 "simgrid/platf_interface.h"    // platform creation API internal interface
8
9 #include "surf_routing_generic.hpp"
10 #include "network.hpp"
11 #include "xbt/graph.h"
12
13 extern "C" {
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_routing_generic, surf_route, "Generic implementation of the surf routing");
15 }
16
17 static int no_bypassroute_declared = 1;
18
19 void generic_free_route(sg_platf_route_cbarg_t route)
20 {
21   if (route) {
22     xbt_dynar_free(&route->link_list);
23     xbt_free(route);
24   }
25 }
26
27 void AsGeneric::parseRoute(sg_platf_route_cbarg_t /*route*/){
28   THROW_IMPOSSIBLE;
29 }
30
31 void AsGeneric::parseASroute(sg_platf_route_cbarg_t /*route*/){
32   THROW_IMPOSSIBLE;
33 }
34
35 void AsGeneric::getRouteAndLatency(RoutingEdgePtr /*src*/, RoutingEdgePtr /*dst*/, sg_platf_route_cbarg_t /*into*/, double */*latency*/){
36   THROW_IMPOSSIBLE;
37 }
38
39 AsGeneric::AsGeneric() {
40   p_bypassRoutes = xbt_dict_new_homogeneous((void (*)(void *)) generic_free_route);
41 }
42
43 AsGeneric::~AsGeneric() {
44   xbt_dict_free(&p_bypassRoutes);
45 }
46
47 int AsGeneric::parsePU(RoutingEdgePtr elm)
48 {
49   XBT_DEBUG("Load process unit \"%s\"", elm->p_name);
50   xbt_dynar_push_as(p_indexNetworkElm, RoutingEdgePtr, elm);
51   return xbt_dynar_length(p_indexNetworkElm)-1;
52 }
53
54 int AsGeneric::parseAS(RoutingEdgePtr elm)
55 {
56   XBT_DEBUG("Load Autonomous system \"%s\"", elm->p_name);
57   xbt_dynar_push_as(p_indexNetworkElm, RoutingEdgePtr, elm);
58   return xbt_dynar_length(p_indexNetworkElm)-1;
59 }
60
61 void AsGeneric::parseBypassroute(sg_platf_route_cbarg_t e_route)
62 {
63   char *src = (char*)(e_route->src);
64   char *dst = (char*)(e_route->dst);
65
66   if(e_route->gw_dst)
67     XBT_DEBUG("Load bypassASroute from \"%s\" to \"%s\"", src, dst);
68   else
69     XBT_DEBUG("Load bypassRoute from \"%s\" to \"%s\"", src, dst);
70   xbt_dict_t dict_bypassRoutes = p_bypassRoutes;
71   char *route_name;
72
73   route_name = bprintf("%s#%s", src, dst);
74   xbt_assert(!xbt_dynar_is_empty(e_route->link_list),
75       "Invalid count of links, must be greater than zero (%s,%s)",
76       src, dst);
77   xbt_assert(!xbt_dict_get_or_null(dict_bypassRoutes, route_name),
78       "The bypass route between \"%s\"(\"%s\") and \"%s\"(\"%s\") already exists",
79       src, e_route->gw_src->p_name, dst, e_route->gw_dst->p_name);
80
81   sg_platf_route_cbarg_t new_e_route = NULL;
82   if(e_route->gw_dst)
83     new_e_route =  newExtendedRoute(SURF_ROUTING_RECURSIVE, e_route, 1);
84   else
85     new_e_route =  newExtendedRoute(SURF_ROUTING_BASE, e_route, 1);
86
87   xbt_dynar_free(&(e_route->link_list));
88
89   xbt_dict_set(dict_bypassRoutes, route_name, new_e_route, NULL);
90   no_bypassroute_declared = 0;
91   xbt_free(route_name);
92 }
93
94 /* ************************************************************************** */
95 /* *********************** GENERIC BUSINESS METHODS ************************* */
96
97 xbt_dynar_t AsGeneric::getOneLinkRoutes() { // FIXME: kill that stub
98   xbt_die("\"generic_get_onelink_routes\" not implemented yet");
99   return NULL;
100 }
101
102 static const char *instr_node_name(xbt_node_t node)
103 {
104   void *data = xbt_graph_node_get_data(node);
105   char *str = (char *) data;
106   return str;
107 }
108
109 xbt_node_t new_xbt_graph_node(xbt_graph_t graph, const char *name,
110                               xbt_dict_t nodes)
111 {
112   xbt_node_t ret = (xbt_node_t) xbt_dict_get_or_null(nodes, name);
113   if (ret)
114     return ret;
115
116   ret = xbt_graph_new_node(graph, xbt_strdup(name));
117   xbt_dict_set(nodes, name, ret, NULL);
118   return ret;
119 }
120
121 xbt_edge_t new_xbt_graph_edge(xbt_graph_t graph, xbt_node_t s, xbt_node_t d,
122                               xbt_dict_t edges)
123 {
124   xbt_edge_t ret;
125
126   const char *sn = instr_node_name(s);
127   const char *dn = instr_node_name(d);
128   int len = strlen(sn) + strlen(dn) + 1;
129   char *name = (char *) xbt_malloc(len * sizeof(char));
130
131
132   snprintf(name, len, "%s%s", sn, dn);
133   ret = (xbt_edge_t) xbt_dict_get_or_null(edges, name);
134   if (ret == NULL) {
135     snprintf(name, len, "%s%s", dn, sn);
136     ret = (xbt_edge_t) xbt_dict_get_or_null(edges, name);
137   }
138
139   if (ret == NULL) {
140     ret = xbt_graph_new_edge(graph, s, d, NULL);
141     xbt_dict_set(edges, name, ret, NULL);
142   }
143   free(name);
144   return ret;
145 }
146
147 void AsGeneric::getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges)
148 {
149   int src, dst;
150   int table_size = xbt_dynar_length(p_indexNetworkElm);
151
152
153   for (src = 0; src < table_size; src++) {
154     RoutingEdgePtr my_src =
155         xbt_dynar_get_as(p_indexNetworkElm, src, RoutingEdgePtr);
156     for (dst = 0; dst < table_size; dst++) {
157       if (src == dst)
158         continue;
159       RoutingEdgePtr my_dst =
160           xbt_dynar_get_as(p_indexNetworkElm, dst, RoutingEdgePtr);
161
162       sg_platf_route_cbarg_t route = xbt_new0(s_sg_platf_route_cbarg_t, 1);
163       route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
164
165       getRouteAndLatency(my_src, my_dst, route, NULL);
166
167       XBT_DEBUG ("get_route_and_latency %s -> %s", my_src->p_name, my_dst->p_name);
168
169       unsigned int cpt;
170       void *link;
171
172       xbt_node_t current, previous;
173       const char *previous_name, *current_name;
174
175       if (route->gw_src) {
176         previous = new_xbt_graph_node(graph, route->gw_src->p_name, nodes);
177         previous_name = route->gw_src->p_name;
178       } else {
179         previous = new_xbt_graph_node(graph, my_src->p_name, nodes);
180         previous_name = my_src->p_name;
181       }
182
183       xbt_dynar_foreach(route->link_list, cpt, link) {
184         const char *link_name = ((ResourcePtr) link)->m_name;
185         current = new_xbt_graph_node(graph, link_name, nodes);
186         current_name = link_name;
187         new_xbt_graph_edge(graph, previous, current, edges);
188         XBT_DEBUG ("  %s -> %s", previous_name, current_name);
189         previous = current;
190         previous_name = current_name;
191       }
192
193       if (route->gw_dst) {
194         current = new_xbt_graph_node(graph, route->gw_dst->p_name, nodes);
195         current_name = route->gw_dst->p_name;
196       } else {
197         current = new_xbt_graph_node(graph, my_dst->p_name, nodes);
198         current_name = my_dst->p_name;
199       }
200       new_xbt_graph_edge(graph, previous, current, edges);
201       XBT_DEBUG ("  %s -> %s", previous_name, current_name);
202
203       xbt_dynar_free (&(route->link_list));
204       xbt_free (route);
205     }
206   }
207 }
208
209 sg_platf_route_cbarg_t AsGeneric::getBypassRoute(RoutingEdgePtr src,
210                                                RoutingEdgePtr dst,
211                                                double *lat)
212 {
213   // If never set a bypass route return NULL without any further computations
214   XBT_DEBUG("generic_get_bypassroute from %s to %s", src->p_name, dst->p_name);
215   if (no_bypassroute_declared)
216     return NULL;
217
218   sg_platf_route_cbarg_t e_route_bypass = NULL;
219   xbt_dict_t dict_bypassRoutes = p_bypassRoutes;
220
221   if(dst->p_rcComponent == this && src->p_rcComponent == this ){
222     char *route_name = bprintf("%s#%s", src->p_name, dst->p_name);
223     e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name);
224     if(e_route_bypass)
225       XBT_DEBUG("Find bypass route with %ld links",xbt_dynar_length(e_route_bypass->link_list));
226     free(route_name);
227   }
228   else{
229     AsPtr src_as, dst_as;
230     int index_src, index_dst;
231     xbt_dynar_t path_src = NULL;
232     xbt_dynar_t path_dst = NULL;
233     AsPtr current = NULL;
234     AsPtr *current_src = NULL;
235     AsPtr *current_dst = NULL;
236
237     if (src == NULL || dst == NULL)
238       xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"",
239           src->p_name, dst->p_name, p_name);
240
241     src_as = src->p_rcComponent;
242     dst_as = dst->p_rcComponent;
243
244     /* (2) find the path to the root routing component */
245     path_src = xbt_dynar_new(sizeof(AsPtr), NULL);
246     current = src_as;
247     while (current != NULL) {
248       xbt_dynar_push(path_src, &current);
249       current = current->p_routingFather;
250     }
251     path_dst = xbt_dynar_new(sizeof(AsPtr), NULL);
252     current = dst_as;
253     while (current != NULL) {
254       xbt_dynar_push(path_dst, &current);
255       current = current->p_routingFather;
256     }
257
258     /* (3) find the common father */
259     index_src = path_src->used - 1;
260     index_dst = path_dst->used - 1;
261     current_src = (AsPtr *) xbt_dynar_get_ptr(path_src, index_src);
262     current_dst = (AsPtr *) xbt_dynar_get_ptr(path_dst, index_dst);
263     while (index_src >= 0 && index_dst >= 0 && *current_src == *current_dst) {
264       xbt_dynar_pop_ptr(path_src);
265       xbt_dynar_pop_ptr(path_dst);
266       index_src--;
267       index_dst--;
268       current_src = (AsPtr *) xbt_dynar_get_ptr(path_src, index_src);
269       current_dst = (AsPtr *) xbt_dynar_get_ptr(path_dst, index_dst);
270     }
271
272     int max_index_src = path_src->used - 1;
273     int max_index_dst = path_dst->used - 1;
274
275     int max_index = max(max_index_src, max_index_dst);
276     int i, max;
277
278     for (max = 0; max <= max_index; max++) {
279       for (i = 0; i < max; i++) {
280         if (i <= max_index_src && max <= max_index_dst) {
281           char *route_name = bprintf("%s#%s",
282               (*(AsPtr *)
283                   (xbt_dynar_get_ptr(path_src, i)))->p_name,
284                   (*(AsPtr *)
285                       (xbt_dynar_get_ptr(path_dst, max)))->p_name);
286           e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name);
287           xbt_free(route_name);
288         }
289         if (e_route_bypass)
290           break;
291         if (max <= max_index_src && i <= max_index_dst) {
292           char *route_name = bprintf("%s#%s",
293               (*(AsPtr *)
294                   (xbt_dynar_get_ptr(path_src, max)))->p_name,
295                   (*(AsPtr *)
296                       (xbt_dynar_get_ptr(path_dst, i)))->p_name);
297           e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name);
298           xbt_free(route_name);
299         }
300         if (e_route_bypass)
301           break;
302       }
303
304       if (e_route_bypass)
305         break;
306
307       if (max <= max_index_src && max <= max_index_dst) {
308         char *route_name = bprintf("%s#%s",
309             (*(AsPtr *)
310                 (xbt_dynar_get_ptr(path_src, max)))->p_name,
311                 (*(AsPtr *)
312                     (xbt_dynar_get_ptr(path_dst, max)))->p_name);
313         e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name);
314         xbt_free(route_name);
315       }
316       if (e_route_bypass)
317         break;
318     }
319
320     xbt_dynar_free(&path_src);
321     xbt_dynar_free(&path_dst);
322   }
323
324   sg_platf_route_cbarg_t new_e_route = NULL;
325   if (e_route_bypass) {
326     NetworkCm02LinkPtr link;
327     unsigned int cpt = 0;
328     new_e_route = xbt_new0(s_sg_platf_route_cbarg_t, 1);
329     new_e_route->gw_src = e_route_bypass->gw_src;
330     new_e_route->gw_dst = e_route_bypass->gw_dst;
331     new_e_route->link_list =
332         xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
333     xbt_dynar_foreach(e_route_bypass->link_list, cpt, link) {
334       xbt_dynar_push(new_e_route->link_list, &link);
335       if (lat)
336         *lat += link->getLatency();
337     }
338   }
339
340   return new_e_route;
341 }
342
343 /* ************************************************************************** */
344 /* ************************* GENERIC AUX FUNCTIONS ************************** */
345 /* change a route containing link names into a route containing link entities */
346 sg_platf_route_cbarg_t AsGeneric::newExtendedRoute(e_surf_routing_hierarchy_t hierarchy,
347       sg_platf_route_cbarg_t routearg, int change_order) {
348
349   sg_platf_route_cbarg_t result;
350   char *link_name;
351   unsigned int cpt;
352
353   result = xbt_new0(s_sg_platf_route_cbarg_t, 1);
354   result->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
355
356   xbt_assert(hierarchy == SURF_ROUTING_BASE
357       || hierarchy == SURF_ROUTING_RECURSIVE,
358       "The hierarchy of this AS is neither BASIC nor RECURSIVE, I'm lost here.");
359
360   if (hierarchy == SURF_ROUTING_RECURSIVE) {
361
362     xbt_assert(routearg->gw_src && routearg->gw_dst,
363         "NULL is obviously a bad gateway");
364
365     /* remeber not erase the gateway names */
366     result->gw_src = routearg->gw_src;
367     result->gw_dst = routearg->gw_dst;
368   }
369
370   xbt_dynar_foreach(routearg->link_list, cpt, link_name) {
371
372     void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
373     if (link) {
374       if (change_order)
375         xbt_dynar_push(result->link_list, &link);
376       else
377         xbt_dynar_unshift(result->link_list, &link);
378     } else
379       THROWF(mismatch_error, 0, "Link %s not found", link_name);
380   }
381
382   return result;
383 }
384
385
386
387 AsPtr AsGeneric::asExist(AsPtr to_find)
388 {
389   //return to_find; // FIXME: BYPASSERROR OF FOREACH WITH BREAK
390   xbt_dict_cursor_t cursor = NULL;
391   char *key;
392   int found = 0;
393   AsGenericPtr elem;
394   xbt_dict_foreach(p_routingSons, cursor, key, elem) {
395     if (to_find == elem || elem->asExist(to_find)) {
396       found = 1;
397       break;
398     }
399   }
400   if (found)
401     return to_find;
402   return NULL;
403 }
404
405 AsPtr AsGeneric::autonomousSystemExist(char *element)
406 {
407   //return rc; // FIXME: BYPASSERROR OF FOREACH WITH BREAK
408   AsPtr element_as, result, elem;
409   xbt_dict_cursor_t cursor = NULL;
410   char *key;
411   element_as = ((RoutingEdgePtr)
412       xbt_lib_get_or_null(as_router_lib, element,
413           ROUTING_ASR_LEVEL))->p_rcComponent;
414   result = ((AsPtr) - 1);
415   if (element_as != this)
416     result = asExist(element_as);
417
418   int found = 0;
419   if (result) {
420     xbt_dict_foreach(element_as->p_routingSons, cursor, key, elem) {
421       found = !strcmp(elem->p_name, element);
422       if (found)
423         break;
424     }
425     if (found)
426       return element_as;
427   }
428   return NULL;
429 }
430
431 AsPtr AsGeneric::processingUnitsExist(char *element)
432 {
433   AsPtr element_as;
434   element_as = ((RoutingEdgePtr)
435       xbt_lib_get_or_null(host_lib,
436           element, ROUTING_HOST_LEVEL))->p_rcComponent;
437   if (element_as == this)
438     return element_as;
439   return asExist(element_as);
440 }
441
442 void AsGeneric::srcDstCheck(RoutingEdgePtr src, RoutingEdgePtr dst)
443 {
444
445   RoutingEdgePtr src_data = src;
446   RoutingEdgePtr dst_data = dst;
447
448   if (src_data == NULL || dst_data == NULL)
449     xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"",
450         src->p_name,
451         dst->p_name,
452         p_name);
453
454   AsPtr src_as =
455       (src_data)->p_rcComponent;
456   AsPtr dst_as =
457       (dst_data)->p_rcComponent;
458
459   if (src_as != dst_as)
460     xbt_die("The src(%s in %s) and dst(%s in %s) are in differents AS",
461         src->p_name, src_as->p_name,
462         dst->p_name, dst_as->p_name);
463
464   if (this != dst_as)
465     xbt_die
466     ("The routing component of src'%s' and dst'%s' is not the same as the network elements belong (%s?=%s?=%s)",
467         src->p_name,
468         dst->p_name,
469         src_as->p_name,
470         dst_as->p_name,
471         p_name);
472 }