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. */
6 #include "surf_routing_private.h"
7 #include <pcre.h> /* regular expression library */
10 extern routing_global_t global_routing;
11 extern routing_component_t current_routing;
12 extern model_type_t current_routing_model;
13 extern xbt_dynar_t link_list;
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_rulebased, surf, "Routing part of surf");
17 /* Routing model structure */
20 s_routing_component_t generic_routing;
21 xbt_dict_t dict_processing_units;
22 xbt_dict_t dict_autonomous_systems;
23 xbt_dynar_t list_route;
24 xbt_dynar_t list_ASroute;
25 } s_routing_component_rulebased_t, *routing_component_rulebased_t;
27 typedef struct s_rule_route s_rule_route_t, *rule_route_t;
28 typedef struct s_rule_route_extended s_rule_route_extended_t,
29 *rule_route_extended_t;
32 xbt_dynar_t re_str_link; // dynar of char*
37 struct s_rule_route_extended {
38 s_rule_route_t generic_rule_route;
43 static void rule_route_free(void *e)
45 rule_route_t *elem = (rule_route_t *) (e);
47 xbt_dynar_free(&(*elem)->re_str_link);
48 pcre_free((*elem)->re_src);
49 pcre_free((*elem)->re_dst);
55 static void rule_route_extended_free(void *e)
57 rule_route_extended_t *elem = (rule_route_extended_t *) e;
59 xbt_dynar_free(&(*elem)->generic_rule_route.re_str_link);
60 pcre_free((*elem)->generic_rule_route.re_src);
61 pcre_free((*elem)->generic_rule_route.re_dst);
62 xbt_free((*elem)->re_src_gateway);
63 xbt_free((*elem)->re_dst_gateway);
68 /* Parse routing model functions */
70 static void model_rulebased_set_processing_unit(routing_component_t rc,
73 routing_component_rulebased_t routing =
74 (routing_component_rulebased_t) rc;
75 xbt_dict_set(routing->dict_processing_units, name, (void *) (-1), NULL);
78 static void model_rulebased_set_autonomous_system(routing_component_t rc,
81 routing_component_rulebased_t routing =
82 (routing_component_rulebased_t) rc;
83 xbt_dict_set(routing->dict_autonomous_systems, name, (void *) (-1),
87 static void model_rulebased_set_route(routing_component_t rc,
88 const char *src, const char *dst,
89 name_route_extended_t route)
91 routing_component_rulebased_t routing =
92 (routing_component_rulebased_t) rc;
93 rule_route_t ruleroute = xbt_new0(s_rule_route_t, 1);
97 if(!strcmp(rc->routing->name,"Vivaldi")){
98 if(xbt_dynar_length(route->generic_route.link_list) != 0)
99 xbt_die("You can't have link_ctn with Model Vivaldi.");
102 ruleroute->re_src = pcre_compile(src, 0, &error, &erroffset, NULL);
103 xbt_assert(ruleroute->re_src,
104 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
105 erroffset, src, error);
106 ruleroute->re_dst = pcre_compile(dst, 0, &error, &erroffset, NULL);
107 xbt_assert(ruleroute->re_src,
108 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
109 erroffset, dst, error);
110 ruleroute->re_str_link = route->generic_route.link_list;
111 xbt_dynar_push(routing->list_route, &ruleroute);
115 static void model_rulebased_set_ASroute(routing_component_t rc,
116 const char *src, const char *dst,
117 name_route_extended_t route)
119 routing_component_rulebased_t routing =
120 (routing_component_rulebased_t) rc;
121 rule_route_extended_t ruleroute_e = xbt_new0(s_rule_route_extended_t, 1);
125 if(!strcmp(rc->routing->name,"Vivaldi")){
126 if(xbt_dynar_length(route->generic_route.link_list) != 0)
127 xbt_die("You can't have link_ctn with Model Vivaldi.");
130 ruleroute_e->generic_rule_route.re_src =
131 pcre_compile(src, 0, &error, &erroffset, NULL);
132 xbt_assert(ruleroute_e->generic_rule_route.re_src,
133 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
134 erroffset, src, error);
135 ruleroute_e->generic_rule_route.re_dst =
136 pcre_compile(dst, 0, &error, &erroffset, NULL);
137 xbt_assert(ruleroute_e->generic_rule_route.re_src,
138 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
139 erroffset, dst, error);
140 ruleroute_e->generic_rule_route.re_str_link =
141 route->generic_route.link_list;
142 ruleroute_e->re_src_gateway = route->src_gateway;
143 ruleroute_e->re_dst_gateway = route->dst_gateway;
144 xbt_dynar_push(routing->list_ASroute, &ruleroute_e);
145 // xbt_free(route->src_gateway);
146 // xbt_free(route->dst_gateway);
150 static void model_rulebased_set_bypassroute(routing_component_t rc,
153 route_extended_t e_route)
155 xbt_die("bypass routing not supported for Route-Based model");
158 #define BUFFER_SIZE 4096 /* result buffer size */
159 #define OVECCOUNT 30 /* should be a multiple of 3 */
161 static char *remplace(char *value, const char **src_list, int src_size,
162 const char **dst_list, int dst_size)
164 char result[BUFFER_SIZE];
169 if (value[i] == '$') {
170 i++; /* skip the '$' */
171 if (value[i] < '0' || value[i] > '9')
172 xbt_die("bad string parameter, no number indication, at offset: "
173 "%d (\"%s\")", i, value);
175 /* solve the number */
176 int number = value[i++] - '0';
177 while (value[i] >= '0' && value[i] <= '9')
178 number = 10 * number + (value[i++] - '0');
180 /* solve the indication */
181 const char **param_list;
183 if (value[i] == 's' && value[i + 1] == 'r' && value[i + 2] == 'c') {
184 param_list = src_list;
185 param_size = src_size;
186 } else if (value[i] == 'd' && value[i + 1] == 's'
187 && value[i + 2] == 't') {
188 param_list = dst_list;
189 param_size = dst_size;
191 xbt_die("bad string parameter, support only \"src\" and \"dst\", "
192 "at offset: %d (\"%s\")", i, value);
196 xbt_assert(number < param_size,
197 "bad string parameter, not enough length param_size, "
198 "at offset: %d (\"%s\") %d %d", i, value, param_size, number);
200 const char *param = param_list[number];
202 while (param[j] && i_res < BUFFER_SIZE)
203 result[i_res++] = param[j++];
205 result[i_res++] = value[i++]; /* next char */
207 if (i_res >= BUFFER_SIZE)
208 xbt_die("solving string \"%s\", small buffer size (%d)",
211 result[i_res++] = '\0';
212 char *res = xbt_malloc(i_res);
213 return memcpy(res, result, i_res);
216 static route_extended_t rulebased_get_route(routing_component_t rc,
219 static xbt_dynar_t rulebased_get_onelink_routes(routing_component_t rc)
221 xbt_dynar_t ret = xbt_dynar_new (sizeof(onelink_t), xbt_free);
223 //We have already bypass cluster routes with network NS3
224 if(!strcmp(surf_network_model->name,"network NS3"))
227 routing_component_rulebased_t routing = (routing_component_rulebased_t)rc;
229 xbt_dict_cursor_t c1 = NULL;
234 xbt_dict_foreach(routing->dict_processing_units, c1, k1, d1) {
235 if (rc->get_network_element_type(k1) == SURF_NETWORK_ELEMENT_ROUTER){
241 xbt_die ("rulebased_get_onelink_routes works only if the AS is a cluster, sorry.");
244 xbt_dict_foreach(routing->dict_processing_units, c1, k1, d1) {
245 route_extended_t route = rulebased_get_route (rc, router, k1);
247 int number_of_links = xbt_dynar_length(route->generic_route.link_list);
249 if(number_of_links == 1) {
253 if (number_of_links != 2) {
254 xbt_die ("rulebased_get_onelink_routes works only if the AS is a cluster, sorry.");
258 xbt_dynar_get_cpy (route->generic_route.link_list, 1, &link_ptr);
259 onelink_t onelink = xbt_new0 (s_onelink_t, 1);
260 onelink->src = xbt_strdup (k1);
261 onelink->dst = xbt_strdup (router);
262 onelink->link_ptr = link_ptr;
263 xbt_dynar_push (ret, &onelink);
269 /* Business methods */
270 static route_extended_t rulebased_get_route(routing_component_t rc,
276 "Invalid params for \"get_route\" function at AS \"%s\"",
280 routing_component_rulebased_t routing =
281 (routing_component_rulebased_t) rc;
283 int are_processing_units=0;
284 xbt_dynar_t rule_list;
285 if (xbt_dict_get_or_null(routing->dict_processing_units, src)
286 && xbt_dict_get_or_null(routing->dict_processing_units, dst)) {
287 are_processing_units = 1;
288 rule_list = routing->list_route;
289 } else if (xbt_dict_get_or_null(routing->dict_autonomous_systems, src)
290 && xbt_dict_get_or_null(routing->dict_autonomous_systems,
292 are_processing_units = 0;
293 rule_list = routing->list_ASroute;
295 xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found in "
296 "the local table", src, dst);
300 int src_length = (int) strlen(src);
301 int dst_length = (int) strlen(dst);
303 xbt_dynar_t links_list =
304 xbt_dynar_new(global_routing->size_of_link, NULL);
306 rule_route_t ruleroute;
308 int ovector_src[OVECCOUNT];
309 int ovector_dst[OVECCOUNT];
310 const char **list_src = NULL;
311 const char **list_dst = NULL;
313 xbt_dynar_foreach(rule_list, cpt, ruleroute) {
315 pcre_exec(ruleroute->re_src, NULL, src, src_length, 0, 0,
316 ovector_src, OVECCOUNT);
319 pcre_exec(ruleroute->re_dst, NULL, dst, dst_length, 0, 0,
320 ovector_dst, OVECCOUNT);
322 res = pcre_get_substring_list(src, ovector_src, rc_src, &list_src);
323 xbt_assert(!res, "error solving substring list for src \"%s\"", src);
324 res = pcre_get_substring_list(dst, ovector_dst, rc_dst, &list_dst);
325 xbt_assert(!res, "error solving substring list for src \"%s\"", dst);
327 xbt_dynar_foreach(ruleroute->re_str_link, cpt, link_name) {
328 char *new_link_name =
329 remplace(link_name, list_src, rc_src, list_dst, rc_dst);
331 xbt_lib_get_or_null(link_lib, new_link_name, SURF_LINK_LEVEL);
333 xbt_dynar_push(links_list, &link);
335 THROWF(mismatch_error, 0, "Link %s not found", new_link_name);
336 xbt_free(new_link_name);
340 if (rc_src >= 0 && rc_dst >= 0)
344 route_extended_t new_e_route = NULL;
345 if (rc_src >= 0 && rc_dst >= 0) {
346 new_e_route = xbt_new0(s_route_extended_t, 1);
347 new_e_route->generic_route.link_list = links_list;
348 } else if (!strcmp(src, dst) && are_processing_units) {
349 new_e_route = xbt_new0(s_route_extended_t, 1);
350 xbt_dynar_push(links_list, &(global_routing->loopback));
351 new_e_route->generic_route.link_list = links_list;
353 xbt_dynar_free(&link_list);
356 if (!are_processing_units && new_e_route) {
357 rule_route_extended_t ruleroute_extended =
358 (rule_route_extended_t) ruleroute;
359 new_e_route->src_gateway =
360 remplace(ruleroute_extended->re_src_gateway, list_src, rc_src,
362 new_e_route->dst_gateway =
363 remplace(ruleroute_extended->re_dst_gateway, list_src, rc_src,
368 pcre_free_substring_list(list_src);
370 pcre_free_substring_list(list_dst);
375 static route_extended_t rulebased_get_bypass_route(routing_component_t rc,
382 static void rulebased_finalize(routing_component_t rc)
384 routing_component_rulebased_t routing =
385 (routing_component_rulebased_t) rc;
387 xbt_dict_free(&routing->dict_processing_units);
388 xbt_dict_free(&routing->dict_autonomous_systems);
389 xbt_dynar_free(&routing->list_route);
390 xbt_dynar_free(&routing->list_ASroute);
391 /* Delete structure */
396 /* Creation routing model functions */
397 void *model_rulebased_create(void)
399 routing_component_rulebased_t new_component =
400 xbt_new0(s_routing_component_rulebased_t, 1);
401 new_component->generic_routing.set_processing_unit =
402 model_rulebased_set_processing_unit;
403 new_component->generic_routing.set_autonomous_system =
404 model_rulebased_set_autonomous_system;
405 new_component->generic_routing.set_route = model_rulebased_set_route;
406 new_component->generic_routing.set_ASroute = model_rulebased_set_ASroute;
407 new_component->generic_routing.set_bypassroute = model_rulebased_set_bypassroute;
408 new_component->generic_routing.get_onelink_routes = rulebased_get_onelink_routes;
409 new_component->generic_routing.get_route = rulebased_get_route;
410 new_component->generic_routing.get_latency = generic_get_link_latency;
411 new_component->generic_routing.get_bypass_route = rulebased_get_bypass_route;
412 new_component->generic_routing.finalize = rulebased_finalize;
413 new_component->generic_routing.get_network_element_type = get_network_element_type;
414 /* initialization of internal structures */
415 new_component->dict_processing_units = xbt_dict_new();
416 new_component->dict_autonomous_systems = xbt_dict_new();
417 new_component->list_route = xbt_dynar_new(sizeof(rule_route_t), &rule_route_free);
418 new_component->list_ASroute =
419 xbt_dynar_new(sizeof(rule_route_extended_t),
420 &rule_route_extended_free);
421 return new_component;
424 void model_rulebased_load(void)
426 /* use "surfxml_add_callback" to add a parse function call */
429 void model_rulebased_unload(void)
431 /* use "surfxml_del_callback" to remove a parse function call */
434 void model_rulebased_end(void)