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_platf_t routing_platf;
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_rulebased, surf, "Routing part of surf");
14 /* Routing model structure */
17 s_as_t generic_routing;
18 xbt_dynar_t list_route;
19 xbt_dynar_t list_ASroute;
20 } s_AS_rulebased_t, *AS_rulebased_t;
22 typedef struct s_rule_route s_rule_route_t, *rule_route_t;
23 typedef struct s_rule_route_extended s_rule_route_extended_t, *rule_route_extended_t;
26 xbt_dynar_t re_str_link; // dynar of char*
31 struct s_rule_route_extended {
32 s_rule_route_t generic_rule_route;
37 static void rule_route_free(void *e)
39 rule_route_t *elem = (rule_route_t *) (e);
41 xbt_dynar_free(&(*elem)->re_str_link);
42 pcre_free((*elem)->re_src);
43 pcre_free((*elem)->re_dst);
49 static void rule_route_extended_free(void *e)
51 rule_route_extended_t *elem = (rule_route_extended_t *) e;
53 xbt_dynar_free(&(*elem)->generic_rule_route.re_str_link);
54 pcre_free((*elem)->generic_rule_route.re_src);
55 pcre_free((*elem)->generic_rule_route.re_dst);
56 xbt_free((*elem)->re_src_gateway);
57 xbt_free((*elem)->re_dst_gateway);
62 /* Parse routing model functions */
64 static int model_rulebased_parse_PU(AS_t rc, sg_routing_edge_t elm)
66 AS_rulebased_t routing = (AS_rulebased_t) rc;
67 xbt_dynar_push(routing->generic_routing.index_network_elm,(void *)elm);
71 static int model_rulebased_parse_AS(AS_t rc, sg_routing_edge_t elm)
73 AS_rulebased_t routing = (AS_rulebased_t) rc;
74 xbt_dynar_push(routing->generic_routing.index_network_elm,(void *)elm);
78 static void model_rulebased_parse_route(AS_t rc,
79 const char *src, const char *dst,
82 AS_rulebased_t routing = (AS_rulebased_t) rc;
83 rule_route_t ruleroute = xbt_new0(s_rule_route_t, 1);
87 if(!strcmp(rc->model_desc->name,"Vivaldi")){
88 if(!xbt_dynar_is_empty(route->link_list))
89 xbt_die("You can't have link_ctn with Model Vivaldi.");
92 ruleroute->re_src = pcre_compile(src, 0, &error, &erroffset, NULL);
93 xbt_assert(ruleroute->re_src,
94 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
95 erroffset, src, error);
96 ruleroute->re_dst = pcre_compile(dst, 0, &error, &erroffset, NULL);
97 xbt_assert(ruleroute->re_src,
98 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
99 erroffset, dst, error);
101 ruleroute->re_str_link = route->link_list;
102 route->link_list = NULL; // Don't free it twice in each container
104 xbt_dynar_push(routing->list_route, &ruleroute);
107 static void model_rulebased_parse_ASroute(AS_t rc,
108 const char *src, const char *dst,
111 AS_rulebased_t routing = (AS_rulebased_t) rc;
112 rule_route_extended_t ruleroute_e = xbt_new0(s_rule_route_extended_t, 1);
116 if(!strcmp(rc->model_desc->name,"Vivaldi")){
117 if(!xbt_dynar_is_empty(route->link_list))
118 xbt_die("You can't have link_ctn with Model Vivaldi.");
121 ruleroute_e->generic_rule_route.re_src =
122 pcre_compile(src, 0, &error, &erroffset, NULL);
123 xbt_assert(ruleroute_e->generic_rule_route.re_src,
124 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
125 erroffset, src, error);
126 ruleroute_e->generic_rule_route.re_dst =
127 pcre_compile(dst, 0, &error, &erroffset, NULL);
128 xbt_assert(ruleroute_e->generic_rule_route.re_src,
129 "PCRE compilation failed at offset %d (\"%s\"): %s\n",
130 erroffset, dst, error);
131 ruleroute_e->generic_rule_route.re_str_link =
134 // DIRTY PERL HACK AHEAD: with the rulebased routing, the {src,dst}_gateway fields
135 // store the provided name instead of the entity directly (routing_parse_E_ASroute knows)
137 // This is because the user will provide something like "^AS_(.*)$" instead of the proper name of a given entity
138 ruleroute_e->re_src_gateway = xbt_strdup((char *)route->src_gateway);
139 ruleroute_e->re_dst_gateway = xbt_strdup((char *)route->dst_gateway);
140 xbt_dynar_push(routing->list_ASroute, &ruleroute_e);
142 /* make sure that they don't get freed */
143 route->link_list = NULL;
144 route->src_gateway = route->dst_gateway = NULL;
147 static void model_rulebased_parse_bypassroute(AS_t rc,
152 xbt_die("bypass routing not supported for Route-Based model");
155 #define BUFFER_SIZE 4096 /* result buffer size */
156 #define OVECCOUNT 30 /* should be a multiple of 3 */
158 static char *remplace(char *value, const char **src_list, int src_size,
159 const char **dst_list, int dst_size)
161 char result[BUFFER_SIZE];
166 if (value[i] == '$') {
167 i++; /* skip the '$' */
168 if (value[i] < '0' || value[i] > '9')
169 xbt_die("bad string parameter, no number indication, at offset: "
170 "%d (\"%s\")", i, value);
172 /* solve the number */
173 int number = value[i++] - '0';
174 while (value[i] >= '0' && value[i] <= '9')
175 number = 10 * number + (value[i++] - '0');
177 /* solve the indication */
178 const char **param_list;
179 _XBT_GNUC_UNUSED int param_size;
180 if (value[i] == 's' && value[i + 1] == 'r' && value[i + 2] == 'c') {
181 param_list = src_list;
182 param_size = src_size;
183 } else if (value[i] == 'd' && value[i + 1] == 's'
184 && value[i + 2] == 't') {
185 param_list = dst_list;
186 param_size = dst_size;
188 xbt_die("bad string parameter, support only \"src\" and \"dst\", "
189 "at offset: %d (\"%s\")", i, value);
193 xbt_assert(number < param_size,
194 "bad string parameter, not enough length param_size, "
195 "at offset: %d (\"%s\") %d %d", i, value, param_size, number);
197 const char *param = param_list[number];
199 while (param[j] && i_res < BUFFER_SIZE)
200 result[i_res++] = param[j++];
202 result[i_res++] = value[i++]; /* next char */
204 if (i_res >= BUFFER_SIZE)
205 xbt_die("solving string \"%s\", small buffer size (%d)",
208 result[i_res++] = '\0';
209 char *res = xbt_malloc(i_res);
210 return memcpy(res, result, i_res);
213 static void rulebased_get_route_and_latency(AS_t rc,
214 sg_routing_edge_t src, sg_routing_edge_t dst,
215 route_t res,double*lat);
216 static xbt_dynar_t rulebased_get_onelink_routes(AS_t rc)
218 xbt_dynar_t ret = xbt_dynar_new (sizeof(onelink_t), xbt_free);
219 //We have already bypass cluster routes with network NS3
220 if(!strcmp(surf_network_model->name,"network NS3"))
226 sg_routing_edge_t router = NULL;
227 xbt_lib_cursor_t cursor;
228 xbt_lib_foreach(as_router_lib, cursor, k1, router)
230 if (router->rc_type == SURF_NETWORK_ELEMENT_ROUTER)
235 xbt_die ("rulebased_get_onelink_routes works only if the AS is a cluster, sorry.");
237 sg_routing_edge_t host = NULL;
238 xbt_lib_foreach(as_router_lib, cursor, k1, host){
240 route_t route = xbt_new0(s_route_t,1);
241 route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t),NULL);
242 rulebased_get_route_and_latency (rc, router, host, route,NULL);
244 switch (xbt_dynar_length(route->link_list)) {
249 xbt_dynar_get_cpy (route->link_list, 1, &link_ptr);
250 onelink_t onelink = xbt_new0 (s_onelink_t, 1);
252 onelink->dst = router;
253 onelink->link_ptr = link_ptr;
254 xbt_dynar_push (ret, &onelink);
257 xbt_die("rulebased_get_onelink_routes works only if the AS is a cluster, sorry.");
264 /* Business methods */
265 static void rulebased_get_route_and_latency(AS_t rc,
266 sg_routing_edge_t src, sg_routing_edge_t dst,
267 route_t route, double *lat)
269 XBT_DEBUG("rulebased_get_route_and_latency from '%s' to '%s'",src->name,dst->name);
272 "Invalid params for \"get_route\" function at AS \"%s\"",
276 AS_rulebased_t routing = (AS_rulebased_t) rc;
278 char* src_name = src->name;
279 char* dst_name = dst->name;
281 int are_processing_units=0;
282 xbt_dynar_t rule_list;
283 if ((src->rc_type == SURF_NETWORK_ELEMENT_HOST || src->rc_type == SURF_NETWORK_ELEMENT_ROUTER)&&
284 (dst->rc_type == SURF_NETWORK_ELEMENT_HOST || dst->rc_type == SURF_NETWORK_ELEMENT_ROUTER)){
285 are_processing_units = 1;
286 rule_list = routing->list_route;
287 } else if (src->rc_type == SURF_NETWORK_ELEMENT_AS && dst->rc_type == SURF_NETWORK_ELEMENT_AS) {
288 are_processing_units = 0;
289 rule_list = routing->list_ASroute;
291 THROWF(arg_error,0,"No route from '%s' to '%s'",src_name,dst_name);
295 int src_length = (int) strlen(src_name);
296 int dst_length = (int) strlen(dst_name);
298 rule_route_t ruleroute;
300 int ovector_src[OVECCOUNT];
301 int ovector_dst[OVECCOUNT];
302 const char **list_src = NULL;
303 const char **list_dst = NULL;
304 _XBT_GNUC_UNUSED int res;
305 xbt_dynar_foreach(rule_list, cpt, ruleroute) {
307 pcre_exec(ruleroute->re_src, NULL, src_name, src_length, 0, 0,
308 ovector_src, OVECCOUNT);
311 pcre_exec(ruleroute->re_dst, NULL, dst_name, dst_length, 0, 0,
312 ovector_dst, OVECCOUNT);
314 res = pcre_get_substring_list(src_name, ovector_src, rc_src, &list_src);
315 xbt_assert(!res, "error solving substring list for src \"%s\"", src_name);
316 res = pcre_get_substring_list(dst_name, ovector_dst, rc_dst, &list_dst);
317 xbt_assert(!res, "error solving substring list for dst \"%s\"", dst_name);
319 xbt_dynar_foreach(ruleroute->re_str_link, cpt, link_name) {
320 char *new_link_name =
321 remplace(link_name, list_src, rc_src, list_dst, rc_dst);
323 xbt_lib_get_or_null(link_lib, new_link_name, SURF_LINK_LEVEL);
325 xbt_dynar_push(route->link_list, &link);
327 *lat += surf_network_model->extension.network.get_link_latency(link);
329 THROWF(mismatch_error, 0, "Link %s not found", new_link_name);
330 xbt_free(new_link_name);
334 if (rc_src >= 0 && rc_dst >= 0)
338 if (rc_src >= 0 && rc_dst >= 0) {
339 /* matched src and dest, nothing more to do (?) */
340 } else if (!strcmp(src_name, dst_name) && are_processing_units) {
341 xbt_dynar_push(route->link_list, &(routing_platf->loopback));
343 *lat += surf_network_model->extension.network.get_link_latency(routing_platf->loopback);
345 THROWF(arg_error,0,"No route from '%s' to '%s'??",src_name,dst_name);
346 //xbt_dynar_reset(route->link_list);
349 if (!are_processing_units && !xbt_dynar_is_empty(route->link_list)) {
350 rule_route_extended_t ruleroute_extended =
351 (rule_route_extended_t) ruleroute;
352 char *gw_src_name = remplace(ruleroute_extended->re_src_gateway, list_src, rc_src,
354 route->src_gateway = sg_routing_edge_by_name_or_null(gw_src_name);
355 xbt_free(gw_src_name);
357 char *gw_dst_name = remplace(ruleroute_extended->re_dst_gateway, list_src, rc_src,
359 route->dst_gateway = sg_routing_edge_by_name_or_null(gw_dst_name);
360 xbt_free(gw_dst_name);
364 pcre_free_substring_list(list_src);
366 pcre_free_substring_list(list_dst);
369 static route_t rulebased_get_bypass_route(AS_t rc, sg_routing_edge_t src, sg_routing_edge_t dst, double *lat) {
373 static void rulebased_finalize(AS_t rc)
375 AS_rulebased_t routing =
378 xbt_dynar_free(&routing->list_route);
379 xbt_dynar_free(&routing->list_ASroute);
380 model_generic_finalize(rc);
384 /* Creation routing model functions */
385 AS_t model_rulebased_create(void) {
387 AS_rulebased_t new_component = (AS_rulebased_t)
388 model_generic_create_sized(sizeof(s_AS_rulebased_t));
390 new_component->generic_routing.parse_PU = model_rulebased_parse_PU;
391 new_component->generic_routing.parse_AS = model_rulebased_parse_AS;
392 new_component->generic_routing.parse_route = model_rulebased_parse_route;
393 new_component->generic_routing.parse_ASroute = model_rulebased_parse_ASroute;
394 new_component->generic_routing.parse_bypassroute = model_rulebased_parse_bypassroute;
395 new_component->generic_routing.get_onelink_routes = rulebased_get_onelink_routes;
396 new_component->generic_routing.get_route_and_latency = rulebased_get_route_and_latency;
397 new_component->generic_routing.get_bypass_route = rulebased_get_bypass_route;
398 new_component->generic_routing.finalize = rulebased_finalize;
399 /* initialization of internal structures */
400 new_component->list_route = xbt_dynar_new(sizeof(rule_route_t), &rule_route_free);
401 new_component->list_ASroute =
402 xbt_dynar_new(sizeof(rule_route_extended_t),
403 &rule_route_extended_free);
405 return (AS_t) new_component;