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 xbt_dynar_t parsed_link_list;
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_rulebased, surf, "Routing part of surf");
15 /* Routing model structure */
18 s_as_t generic_routing;
19 xbt_dict_t dict_processing_units;
20 xbt_dict_t dict_autonomous_systems;
21 xbt_dynar_t list_route;
22 xbt_dynar_t list_ASroute;
23 } s_AS_rulebased_t, *AS_rulebased_t;
25 typedef struct s_rule_route s_rule_route_t, *rule_route_t;
26 typedef struct s_rule_route_extended s_rule_route_extended_t,
27 *rule_route_extended_t;
30 xbt_dynar_t re_str_link; // dynar of char*
35 struct s_rule_route_extended {
36 s_rule_route_t generic_rule_route;
41 static void rule_route_free(void *e)
43 rule_route_t *elem = (rule_route_t *) (e);
45 xbt_dynar_free(&(*elem)->re_str_link);
46 pcre_free((*elem)->re_src);
47 pcre_free((*elem)->re_dst);
53 static void rule_route_extended_free(void *e)
55 rule_route_extended_t *elem = (rule_route_extended_t *) e;
57 xbt_dynar_free(&(*elem)->generic_rule_route.re_str_link);
58 pcre_free((*elem)->generic_rule_route.re_src);
59 pcre_free((*elem)->generic_rule_route.re_dst);
60 xbt_free((*elem)->re_src_gateway);
61 xbt_free((*elem)->re_dst_gateway);
66 /* Parse routing model functions */
68 static void model_rulebased_parse_PU(AS_t rc, const char *name)
70 AS_rulebased_t routing = (AS_rulebased_t) rc;
71 xbt_dict_set(routing->dict_processing_units, name, (void *) (-1), NULL);
74 static void model_rulebased_parse_AS(AS_t rc, const char *name)
76 AS_rulebased_t routing = (AS_rulebased_t) rc;
77 xbt_dict_set(routing->dict_autonomous_systems, name, (void *) (-1),
81 static void model_rulebased_parse_route(AS_t rc,
82 const char *src, const char *dst,
85 AS_rulebased_t routing = (AS_rulebased_t) rc;
86 rule_route_t ruleroute = xbt_new0(s_rule_route_t, 1);
90 if(!strcmp(rc->model_desc->name,"Vivaldi")){
91 if(!xbt_dynar_is_empty(route->link_list))
92 xbt_die("You can't have link_ctn with Model Vivaldi.");
95 ruleroute->re_src = pcre_compile(src, 0, &error, &erroffset, NULL);
96 xbt_assert(ruleroute->re_src,
97 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
98 erroffset, src, error);
99 ruleroute->re_dst = pcre_compile(dst, 0, &error, &erroffset, NULL);
100 xbt_assert(ruleroute->re_src,
101 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
102 erroffset, dst, error);
103 ruleroute->re_str_link = route->link_list;
104 xbt_dynar_push(routing->list_route, &ruleroute);
108 static void model_rulebased_parse_ASroute(AS_t rc,
109 const char *src, const char *dst,
112 AS_rulebased_t routing = (AS_rulebased_t) rc;
113 rule_route_extended_t ruleroute_e = xbt_new0(s_rule_route_extended_t, 1);
117 if(!strcmp(rc->model_desc->name,"Vivaldi")){
118 if(!xbt_dynar_is_empty(route->link_list))
119 xbt_die("You can't have link_ctn with Model Vivaldi.");
122 ruleroute_e->generic_rule_route.re_src =
123 pcre_compile(src, 0, &error, &erroffset, NULL);
124 xbt_assert(ruleroute_e->generic_rule_route.re_src,
125 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
126 erroffset, src, error);
127 ruleroute_e->generic_rule_route.re_dst =
128 pcre_compile(dst, 0, &error, &erroffset, NULL);
129 xbt_assert(ruleroute_e->generic_rule_route.re_src,
130 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
131 erroffset, dst, error);
132 ruleroute_e->generic_rule_route.re_str_link =
134 ruleroute_e->re_src_gateway = route->src_gateway;
135 ruleroute_e->re_dst_gateway = route->dst_gateway;
136 xbt_dynar_push(routing->list_ASroute, &ruleroute_e);
137 // xbt_free(route->src_gateway);
138 // xbt_free(route->dst_gateway);
142 static void model_rulebased_parse_bypassroute(AS_t rc,
147 xbt_die("bypass routing not supported for Route-Based model");
150 #define BUFFER_SIZE 4096 /* result buffer size */
151 #define OVECCOUNT 30 /* should be a multiple of 3 */
153 static char *remplace(char *value, const char **src_list, int src_size,
154 const char **dst_list, int dst_size)
156 char result[BUFFER_SIZE];
161 if (value[i] == '$') {
162 i++; /* skip the '$' */
163 if (value[i] < '0' || value[i] > '9')
164 xbt_die("bad string parameter, no number indication, at offset: "
165 "%d (\"%s\")", i, value);
167 /* solve the number */
168 int number = value[i++] - '0';
169 while (value[i] >= '0' && value[i] <= '9')
170 number = 10 * number + (value[i++] - '0');
172 /* solve the indication */
173 const char **param_list;
174 _XBT_GNUC_UNUSED int param_size;
175 if (value[i] == 's' && value[i + 1] == 'r' && value[i + 2] == 'c') {
176 param_list = src_list;
177 param_size = src_size;
178 } else if (value[i] == 'd' && value[i + 1] == 's'
179 && value[i + 2] == 't') {
180 param_list = dst_list;
181 param_size = dst_size;
183 xbt_die("bad string parameter, support only \"src\" and \"dst\", "
184 "at offset: %d (\"%s\")", i, value);
188 xbt_assert(number < param_size,
189 "bad string parameter, not enough length param_size, "
190 "at offset: %d (\"%s\") %d %d", i, value, param_size, number);
192 const char *param = param_list[number];
194 while (param[j] && i_res < BUFFER_SIZE)
195 result[i_res++] = param[j++];
197 result[i_res++] = value[i++]; /* next char */
199 if (i_res >= BUFFER_SIZE)
200 xbt_die("solving string \"%s\", small buffer size (%d)",
203 result[i_res++] = '\0';
204 char *res = xbt_malloc(i_res);
205 return memcpy(res, result, i_res);
208 static void rulebased_get_route(AS_t rc,
209 const char *src, const char *dst,
211 static xbt_dynar_t rulebased_get_onelink_routes(AS_t rc)
213 xbt_dynar_t ret = xbt_dynar_new (sizeof(onelink_t), xbt_free);
215 //We have already bypass cluster routes with network NS3
216 if(!strcmp(surf_network_model->name,"network NS3"))
219 AS_rulebased_t routing = (AS_rulebased_t)rc;
221 xbt_dict_cursor_t c1 = NULL;
226 xbt_dict_foreach(routing->dict_processing_units, c1, k1, d1) {
227 if (routing_get_network_element_type(k1) == SURF_NETWORK_ELEMENT_ROUTER){
234 xbt_die ("rulebased_get_onelink_routes works only if the AS is a cluster, sorry.");
236 xbt_dict_foreach(routing->dict_processing_units, c1, k1, d1) {
237 route_t route = xbt_new0(s_route_t,1);
238 route->link_list = xbt_dynar_new(global_routing->size_of_link,NULL);
239 rulebased_get_route (rc, router, k1, route);
241 int number_of_links = xbt_dynar_length(route->link_list);
243 if(number_of_links == 1) {
247 if (number_of_links != 2) {
248 xbt_die ("rulebased_get_onelink_routes works only if the AS is a cluster, sorry.");
252 xbt_dynar_get_cpy (route->link_list, 1, &link_ptr);
253 onelink_t onelink = xbt_new0 (s_onelink_t, 1);
254 onelink->src = xbt_strdup (k1);
255 onelink->dst = xbt_strdup (router);
256 onelink->link_ptr = link_ptr;
257 xbt_dynar_push (ret, &onelink);
263 /* Business methods */
264 static void rulebased_get_route(AS_t rc,
265 const char *src, const char *dst,
270 "Invalid params for \"get_route\" function at AS \"%s\"",
274 AS_rulebased_t routing = (AS_rulebased_t) rc;
276 int are_processing_units=0;
277 xbt_dynar_t rule_list;
278 if (xbt_dict_get_or_null(routing->dict_processing_units, src)
279 && xbt_dict_get_or_null(routing->dict_processing_units, dst)) {
280 are_processing_units = 1;
281 rule_list = routing->list_route;
282 } else if (xbt_dict_get_or_null(routing->dict_autonomous_systems, src)
283 && xbt_dict_get_or_null(routing->dict_autonomous_systems,
285 are_processing_units = 0;
286 rule_list = routing->list_ASroute;
288 THROWF(arg_error,0,"No route from '%s' to '%s'",src,dst);
292 int src_length = (int) strlen(src);
293 int dst_length = (int) strlen(dst);
295 rule_route_t ruleroute;
297 int ovector_src[OVECCOUNT];
298 int ovector_dst[OVECCOUNT];
299 const char **list_src = NULL;
300 const char **list_dst = NULL;
301 _XBT_GNUC_UNUSED int res;
302 xbt_dynar_foreach(rule_list, cpt, ruleroute) {
304 pcre_exec(ruleroute->re_src, NULL, src, src_length, 0, 0,
305 ovector_src, OVECCOUNT);
308 pcre_exec(ruleroute->re_dst, NULL, dst, dst_length, 0, 0,
309 ovector_dst, OVECCOUNT);
311 res = pcre_get_substring_list(src, ovector_src, rc_src, &list_src);
312 xbt_assert(!res, "error solving substring list for src \"%s\"", src);
313 res = pcre_get_substring_list(dst, ovector_dst, rc_dst, &list_dst);
314 xbt_assert(!res, "error solving substring list for src \"%s\"", dst);
316 xbt_dynar_foreach(ruleroute->re_str_link, cpt, link_name) {
317 char *new_link_name =
318 remplace(link_name, list_src, rc_src, list_dst, rc_dst);
320 xbt_lib_get_or_null(link_lib, new_link_name, SURF_LINK_LEVEL);
322 xbt_dynar_push(route->link_list, &link);
324 THROWF(mismatch_error, 0, "Link %s not found", new_link_name);
325 xbt_free(new_link_name);
329 if (rc_src >= 0 && rc_dst >= 0)
333 if (rc_src >= 0 && rc_dst >= 0) {
334 /* matched src and dest, nothing more to do (?) */
335 } else if (!strcmp(src, dst) && are_processing_units) {
336 xbt_dynar_push(route->link_list, &(global_routing->loopback));
338 THROWF(arg_error,0,"No route from '%s' to '%s'??",src,dst);
339 //xbt_dynar_reset(route->link_list);
342 if (!are_processing_units && !xbt_dynar_is_empty(route->link_list)) {
343 rule_route_extended_t ruleroute_extended =
344 (rule_route_extended_t) ruleroute;
346 remplace(ruleroute_extended->re_src_gateway, list_src, rc_src,
349 remplace(ruleroute_extended->re_dst_gateway, list_src, rc_src,
354 pcre_free_substring_list(list_src);
356 pcre_free_substring_list(list_dst);
359 static route_t rulebased_get_bypass_route(AS_t rc, const char *src, const char *dst) {
363 static void rulebased_finalize(AS_t rc)
365 AS_rulebased_t routing =
368 xbt_dict_free(&routing->dict_processing_units);
369 xbt_dict_free(&routing->dict_autonomous_systems);
370 xbt_dynar_free(&routing->list_route);
371 xbt_dynar_free(&routing->list_ASroute);
372 /* Delete structure */
377 /* Creation routing model functions */
378 AS_t model_rulebased_create(void) {
380 AS_rulebased_t new_component = (AS_rulebased_t)
381 model_generic_create_sized(sizeof(s_AS_rulebased_t));
383 new_component->generic_routing.parse_PU = model_rulebased_parse_PU;
384 new_component->generic_routing.parse_AS = model_rulebased_parse_AS;
385 new_component->generic_routing.parse_route = model_rulebased_parse_route;
386 new_component->generic_routing.parse_ASroute = model_rulebased_parse_ASroute;
387 new_component->generic_routing.parse_bypassroute = model_rulebased_parse_bypassroute;
388 new_component->generic_routing.get_onelink_routes = rulebased_get_onelink_routes;
389 new_component->generic_routing.get_route = rulebased_get_route;
390 new_component->generic_routing.get_bypass_route = rulebased_get_bypass_route;
391 new_component->generic_routing.finalize = rulebased_finalize;
392 /* initialization of internal structures */
393 new_component->dict_processing_units = xbt_dict_new();
394 new_component->dict_autonomous_systems = xbt_dict_new();
395 new_component->list_route = xbt_dynar_new(sizeof(rule_route_t), &rule_route_free);
396 new_component->list_ASroute =
397 xbt_dynar_new(sizeof(rule_route_extended_t),
398 &rule_route_extended_free);
400 return (AS_t) new_component;