1 /* Copyright (c) 2009, 2010, 2011. The SimGrid Team.
2 * All rights reserved. */
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. */
7 #include "surf_routing_private.h"
10 extern routing_global_t global_routing;
11 extern int surf_parse_lineno;
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_full, surf, "Routing part of surf");
15 #define TO_ROUTE_FULL(i,j) routing->routing_table[(i)+(j)*table_size]
17 /* Routing model structure */
19 typedef struct s_routing_component_full {
20 s_as_t generic_routing;
21 route_t *routing_table;
22 } s_routing_component_full_t, *routing_component_full_t;
24 /* Business methods */
25 static xbt_dynar_t full_get_onelink_routes(AS_t rc)
27 xbt_dynar_t ret = xbt_dynar_new(sizeof(onelink_t), xbt_free);
29 // routing_component_full_t routing = (routing_component_full_t) rc;
30 // size_t table_size = routing->generic_routing.nb_index;
31 // xbt_dict_cursor_t c1 = NULL, c2 = NULL;
32 // char *k1, *d1, *k2, *d2;
33 // xbt_dict_foreach(routing->generic_routing.to_index, c1, k1, d1) {
34 // xbt_dict_foreach(routing->generic_routing.to_index, c2, k2, d2) {
35 // int *src_id = xbt_dict_get_or_null(routing->generic_routing.to_index, k1);
36 // int *dst_id = xbt_dict_get_or_null(routing->generic_routing.to_index, k2);
37 // xbt_assert(src_id && dst_id,
38 // "Ask for route \"from\"(%s) or \"to\"(%s) "
39 // "no found in the local table", k1, k2);
40 // route_t route = TO_ROUTE_FULL(*src_id, *dst_id);
42 // if (xbt_dynar_length(route->link_list) == 1) {
43 // void *link = *(void **) xbt_dynar_get_ptr(route->link_list, 0);
44 // onelink_t onelink = xbt_new0(s_onelink_t, 1);
45 // onelink->link_ptr = link;
46 // if (routing->generic_routing.hierarchy == SURF_ROUTING_BASE) {
47 // onelink->src->routing_obj->name = xbt_strdup(k1);
48 // onelink->src->routing_obj->id = atoi(k1);
49 // onelink->dst->routing_obj->name = xbt_strdup(k2);
50 // onelink->dst->routing_obj->id = atoi(k2);
51 // } else if (routing->generic_routing.hierarchy ==
52 // SURF_ROUTING_RECURSIVE) {
53 // onelink->src = route->src_gateway;
54 // onelink->dst = route->dst_gateway;
56 // xbt_dynar_push(ret, &onelink);
64 static void full_get_route_and_latency(AS_t rc,
65 network_element_t src, network_element_t dst,
66 route_t res, double *lat)
68 XBT_DEBUG("full_get_route_and_latency from %s[%d] to %s[%d]",
75 routing_component_full_t routing = (routing_component_full_t) rc;
76 size_t table_size = routing->generic_routing.nb_index;
78 route_t e_route = NULL;
82 e_route = TO_ROUTE_FULL(src->id, dst->id);
85 res->src_gateway = e_route->src_gateway;
86 res->dst_gateway = e_route->dst_gateway;
87 xbt_dynar_foreach(e_route->link_list, cpt, link) {
88 xbt_dynar_push(res->link_list, &link);
90 *lat += surf_network_model->extension.network.get_link_latency(link);
95 static void full_finalize(AS_t rc)
97 routing_component_full_t routing = (routing_component_full_t) rc;
98 size_t table_size = routing->generic_routing.nb_index;
101 /* Delete routing table */
102 for (i = 0; i < table_size; i++)
103 for (j = 0; j < table_size; j++)
104 generic_free_route(TO_ROUTE_FULL(i, j));
105 xbt_free(routing->routing_table);
106 model_generic_finalize(rc);
110 /* Creation routing model functions */
112 AS_t model_full_create(void)
114 routing_component_full_t new_component = (routing_component_full_t)
115 model_generic_create_sized(sizeof(s_routing_component_full_t));
117 new_component->generic_routing.parse_route = model_full_set_route;
118 new_component->generic_routing.parse_ASroute = model_full_set_route;
119 new_component->generic_routing.get_route_and_latency =
120 full_get_route_and_latency;
121 new_component->generic_routing.get_onelink_routes = full_get_onelink_routes;
122 new_component->generic_routing.finalize = full_finalize;
124 return (AS_t) new_component;
127 void model_full_end(AS_t current_routing)
133 routing_component_full_t routing =
134 ((routing_component_full_t) current_routing);
135 size_t table_size = routing->generic_routing.nb_index;
137 /* Create table if necessary */
138 if (!routing->routing_table)
139 routing->routing_table = xbt_new0(route_t, table_size * table_size);
141 /* Add the loopback if needed */
142 if (global_routing->loopback && current_routing->hierarchy == SURF_ROUTING_BASE) {
143 for (i = 0; i < table_size; i++) {
144 e_route = TO_ROUTE_FULL(i, i);
146 e_route = xbt_new0(s_route_t, 1);
147 e_route->src_gateway = NULL;
148 e_route->dst_gateway = NULL;
149 e_route->link_list = xbt_dynar_new(global_routing->size_of_link, NULL);
150 xbt_dynar_push(e_route->link_list, &global_routing->loopback);
151 TO_ROUTE_FULL(i, i) = e_route;
157 static int full_pointer_resource_cmp(const void *a, const void *b)
162 void model_full_set_route(AS_t rc, const char *src,
163 const char *dst, route_t route)
165 network_element_t src_net_elm, dst_net_elm;
167 src_net_elm = (network_element_t)xbt_lib_get_or_null(host_lib, src, ROUTING_HOST_LEVEL);
168 dst_net_elm = (network_element_t)xbt_lib_get_or_null(host_lib, dst, ROUTING_HOST_LEVEL);
169 if(!src_net_elm) src_net_elm = (network_element_t)xbt_lib_get_or_null(as_router_lib, src, ROUTING_ASR_LEVEL);
170 if(!dst_net_elm) dst_net_elm = (network_element_t)xbt_lib_get_or_null(as_router_lib, dst, ROUTING_ASR_LEVEL);
172 xbt_assert(src_net_elm, "Network elements %s not found", src);
173 xbt_assert(dst_net_elm, "Network elements %s not found", dst);
175 routing_component_full_t routing = (routing_component_full_t) rc;
176 size_t table_size = routing->generic_routing.nb_index;
178 xbt_assert(!xbt_dynar_is_empty(route->link_list),
179 "Invalid count of links, must be greater than zero (%s,%s)",
182 if (!routing->routing_table)
183 routing->routing_table = xbt_new0(route_t, table_size * table_size);
185 if (TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id)) {
188 xbt_dynar_t link_route_to_test =
189 xbt_dynar_new(global_routing->size_of_link, NULL);
190 xbt_dynar_foreach(route->link_list, i, link_name) {
191 void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
192 xbt_assert(link, "Link : '%s' doesn't exists.", link_name);
193 xbt_dynar_push(link_route_to_test, &link);
195 if (xbt_dynar_compare(TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id)->link_list,
196 link_route_to_test, full_pointer_resource_cmp)) {
197 surf_parse_error("A route between \"%s\" and \"%s\" already exists "
198 "with a different content. "
199 "If you are trying to define a reverse route, "
200 "you must set the symmetrical=no attribute to "
201 "your routes tags.", src, dst);
203 surf_parse_warn("Ignoring the identical redefinition of the route "
204 "between \"%s\" and \"%s\"", src, dst);
207 if (!route->dst_gateway && !route->src_gateway)
208 XBT_DEBUG("Load Route from \"%s\" to \"%s\"", src, dst);
210 // FIXME We can call a gw wich is down the current AS (cf g5k.xml) but not upper.
211 // AS_t subas = xbt_dict_get_or_null(rc->routing_sons, src);
212 // if (subas == NULL)
213 // surf_parse_error("The source of an ASroute must be a sub-AS "
214 // "declared within the current AS, "
215 // "but '%s' is not an AS within '%s'", src, rc->name);
216 // if (subas->to_index
217 // && xbt_dict_get_or_null(subas->to_index, route->src_gateway) == NULL)
218 // surf_parse_error("In an ASroute, source gateway must be part of "
219 // "the source sub-AS (in particular, being in a "
220 // "sub-sub-AS is not allowed), "
221 // "but '%s' is not in '%s'.",
222 // route->src_gateway, subas->name);
224 // subas = xbt_dict_get_or_null(rc->routing_sons, dst);
225 // if (subas == NULL)
226 // surf_parse_error("The destination of an ASroute must be a sub-AS "
227 // "declared within the current AS, "
228 // "but '%s' is not an AS within '%s'", dst, rc->name);
229 // if (subas->to_index
230 // && xbt_dict_get_or_null(subas->to_index, route->dst_gateway) == NULL)
231 // surf_parse_error("In an ASroute, destination gateway must be "
232 // "part of the destination sub-AS (in particular, "
233 // "in a sub-sub-AS is not allowed), "
234 // "but '%s' is not in '%s'.",
235 // route->dst_gateway, subas->name);
237 XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"",
238 src, route->src_gateway->name, dst, route->dst_gateway->name);
239 if (route->dst_gateway->rc_type == SURF_NETWORK_ELEMENT_NULL)
240 xbt_die("The dst_gateway '%s' does not exist!", route->dst_gateway->name);
241 if (route->src_gateway->rc_type == SURF_NETWORK_ELEMENT_NULL)
242 xbt_die("The src_gateway '%s' does not exist!", route->src_gateway->name);
244 TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id) =
245 generic_new_extended_route(rc->hierarchy, route, 1);
246 xbt_dynar_shrink(TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id)->link_list, 0);
249 if (A_surfxml_route_symmetrical == A_surfxml_route_symmetrical_YES
250 || A_surfxml_ASroute_symmetrical == A_surfxml_ASroute_symmetrical_YES) {
251 if (route->dst_gateway && route->src_gateway) {
252 network_element_t gw_tmp;
253 gw_tmp = route->src_gateway;
254 route->src_gateway = route->dst_gateway;
255 route->dst_gateway = gw_tmp;
257 if (TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id)) {
260 xbt_dynar_t link_route_to_test =
261 xbt_dynar_new(global_routing->size_of_link, NULL);
262 for (i = xbt_dynar_length(route->link_list); i > 0; i--) {
263 link_name = xbt_dynar_get_as(route->link_list, i - 1, void *);
264 void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
265 xbt_assert(link, "Link : '%s' doesn't exists.", link_name);
266 xbt_dynar_push(link_route_to_test, &link);
268 xbt_assert(!xbt_dynar_compare(TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id)->link_list,
270 full_pointer_resource_cmp),
271 "The route between \"%s\" and \"%s\" already exists", src,
274 if (!route->dst_gateway && !route->src_gateway)
275 XBT_DEBUG("Load Route from \"%s\" to \"%s\"", dst, src);
277 XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"",
278 dst, route->src_gateway->name, src, route->dst_gateway->name);
279 TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id) =
280 generic_new_extended_route(rc->hierarchy, route, 0);
281 xbt_dynar_shrink(TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id)->link_list, 0);