+static void* model_dijkstracache_create(void) {
+ return model_dijkstra_both_create(1);
+}
+
+static void model_dijkstra_both_load(void) {
+ /* use "surfxml_add_callback" to add a parse function call */
+}
+
+static void model_dijkstra_both_unload(void) {
+ /* use "surfxml_del_callback" to remove a parse function call */
+}
+
+static void model_dijkstra_both_end(void) {
+ routing_component_dijkstra_t routing = (routing_component_dijkstra_t) current_routing;
+ xbt_dict_cursor_t cursor = NULL;
+ char *key, *data, *end;
+ const char *sep = "#";
+ xbt_dynar_t keys;
+ xbt_node_t node = NULL;
+ unsigned int cursor2;
+ xbt_dynar_t nodes = NULL;
+ int src_id, dst_id;
+ route_t route;
+
+ /* Create the topology graph */
+ routing->route_graph = xbt_graph_new_graph(1, NULL);
+ routing->graph_node_map = xbt_dict_new();
+
+ if(routing->cached)
+ routing->route_cache = xbt_dict_new();
+
+ /* Put the routes in position */
+ xbt_dict_foreach(routing->parse_routes, cursor, key, data) {
+ keys = xbt_str_split_str(key, sep);
+ src_id = strtol(xbt_dynar_get_as(keys, 0, char *), &end, 10);
+ dst_id = strtol(xbt_dynar_get_as(keys, 1, char *), &end, 10);
+ route_extended_t e_route = generic_new_extended_route(current_routing->hierarchy,data,0);
+ route_new_dijkstra(routing,src_id,dst_id,e_route);
+ xbt_dynar_free(&keys);
+ }
+
+ /* delete the parse table */
+ xbt_dict_foreach(routing->parse_routes, cursor, key, data) {
+ route = (route_t)data;
+ xbt_dynar_free(&(route->link_list));
+ xbt_free(data);
+ }
+
+ /* delete parse dict */
+ xbt_dict_free(&(routing->parse_routes));
+
+ /* Add the loopback if needed */
+ if(current_routing->hierarchy == SURF_ROUTING_BASE)
+ add_loopback_dijkstra(routing);
+
+ /* initialize graph indexes in nodes after graph has been built */
+ nodes = xbt_graph_get_nodes(routing->route_graph);
+
+ xbt_dynar_foreach(nodes, cursor2, node) {
+ graph_node_data_t data = xbt_graph_node_get_data(node);
+ data->graph_id = cursor2;
+ }
+
+}
+
+/* ************************************************** */
+/* ************** RULE-BASED ROUTING **************** */
+
+/* Routing model structure */
+
+typedef struct {
+ s_routing_component_t generic_routing;
+ xbt_dict_t dict_processing_units;
+ xbt_dict_t dict_autonomous_systems;
+ xbt_dynar_t list_route;
+ xbt_dynar_t list_ASroute;
+} s_routing_component_rulebased_t,*routing_component_rulebased_t;
+
+typedef struct s_rule_route s_rule_route_t, *rule_route_t;
+typedef struct s_rule_route_extended s_rule_route_extended_t, *rule_route_extended_t;
+
+struct s_rule_route {
+ xbt_dynar_t re_str_link; // dynar of char*
+ pcre* re_src;
+ pcre* re_dst;
+};
+
+struct s_rule_route_extended {
+ s_rule_route_t generic_rule_route;
+ char* re_src_gateway;
+ char* re_dst_gateway;
+};
+
+static void rule_route_free(void *e) {
+ rule_route_t* elem = (rule_route_t*)(e);
+ if (*elem) {
+ xbt_dynar_free(&(*elem)->re_str_link);
+ pcre_free((*elem)->re_src);
+ pcre_free((*elem)->re_dst);
+ xbt_free((*elem));
+ }
+ (*elem) = NULL;
+}
+
+static void rule_route_extended_free(void *e) {
+ rule_route_extended_t* elem = (rule_route_extended_t*)e;
+ if (*elem) {
+ xbt_dynar_free(&(*elem)->generic_rule_route.re_str_link);
+ pcre_free((*elem)->generic_rule_route.re_src);
+ pcre_free((*elem)->generic_rule_route.re_dst);
+ xbt_free((*elem)->re_src_gateway);
+ xbt_free((*elem)->re_dst_gateway);
+ xbt_free((*elem));
+ }
+}
+
+/* Parse routing model functions */
+
+static void model_rulebased_set_processing_unit(routing_component_t rc, const char* name) {
+ routing_component_rulebased_t routing = (routing_component_rulebased_t) rc;
+ xbt_dict_set(routing->dict_processing_units, name, (void*)(-1), NULL);
+}
+
+static void model_rulebased_set_autonomous_system(routing_component_t rc, const char* name) {
+ routing_component_rulebased_t routing = (routing_component_rulebased_t) rc;
+ xbt_dict_set(routing->dict_autonomous_systems, name, (void*)(-1), NULL);
+}
+
+static void model_rulebased_set_route(routing_component_t rc, const char* src, const char* dst, route_t route) {
+ routing_component_rulebased_t routing = (routing_component_rulebased_t) rc;
+ rule_route_t ruleroute = xbt_new0(s_rule_route_t,1);
+ const char *error;
+ int erroffset;
+ ruleroute->re_src = pcre_compile(src,0,&error,&erroffset,NULL);
+ xbt_assert3(ruleroute->re_src,"PCRE compilation failed at offset %d (\"%s\"): %s\n", erroffset, src, error);
+ ruleroute->re_dst = pcre_compile(dst,0,&error,&erroffset,NULL);
+ xbt_assert3(ruleroute->re_src,"PCRE compilation failed at offset %d (\"%s\"): %s\n", erroffset, dst, error);
+ ruleroute->re_str_link = route->link_list;
+ xbt_dynar_push(routing->list_route,&ruleroute);
+ xbt_free(route);
+}
+
+static void model_rulebased_set_ASroute(routing_component_t rc, const char* src, const char* dst, route_extended_t route) {
+ routing_component_rulebased_t routing = (routing_component_rulebased_t) rc;
+ rule_route_extended_t ruleroute_e = xbt_new0(s_rule_route_extended_t,1);
+ const char *error;
+ int erroffset;
+ ruleroute_e->generic_rule_route.re_src = pcre_compile(src,0,&error,&erroffset,NULL);
+ xbt_assert3(ruleroute_e->generic_rule_route.re_src,"PCRE compilation failed at offset %d (\"%s\"): %s\n", erroffset, src, error);
+ ruleroute_e->generic_rule_route.re_dst = pcre_compile(dst,0,&error,&erroffset,NULL);
+ xbt_assert3(ruleroute_e->generic_rule_route.re_src,"PCRE compilation failed at offset %d (\"%s\"): %s\n", erroffset, dst, error);
+ ruleroute_e->generic_rule_route.re_str_link = route->generic_route.link_list;
+ ruleroute_e->re_src_gateway = route->src_gateway;
+ ruleroute_e->re_dst_gateway = route->dst_gateway;
+ xbt_dynar_push(routing->list_ASroute,&ruleroute_e);
+ xbt_free(route->src_gateway);
+ xbt_free(route->dst_gateway);
+ xbt_free(route);
+}
+
+static void model_rulebased_set_bypassroute(routing_component_t rc, const char* src, const char* dst, route_extended_t e_route) {
+ xbt_die("bypass routing not supported for Route-Based model");
+}
+
+#define BUFFER_SIZE 4096 /* result buffer size */
+#define OVECCOUNT 30 /* should be a multiple of 3 */
+
+static char* remplace(char* value, const char** src_list, int src_size, const char** dst_list, int dst_size ) {
+
+ char result_result[BUFFER_SIZE];
+ int i_result_buffer;
+ int value_length = (int)strlen(value);
+ int number=0;
+
+ int i=0;
+ i_result_buffer = 0;
+ do {
+ if( value[i] == '$' ) {
+ i++; // skip $
+
+ // find the number
+ int number_length = 0;
+ while( '0' <= value[i+number_length] && value[i+number_length] <= '9' ) {
+ number_length++;
+ }
+ xbt_assert2( number_length!=0, "bad string parameter, no number indication, at offset: %d (\"%s\")",i,value);
+
+ // solve number
+ number = atoi(value+i);
+ i=i+number_length;
+ xbt_assert2(i+2<value_length,"bad string parameter, too few chars, at offset: %d (\"%s\")",i,value);
+
+ // solve the indication
+ const char** param_list;
+ int param_size;
+ if( value[i] == 's' && value[i+1] == 'r' && value[i+2] == 'c' ) {
+ param_list = src_list;
+ param_size = src_size;
+ } else if( value[i] == 'd' && value[i+1] == 's' && value[i+2] == 't' ) {
+ param_list = dst_list;
+ param_size = dst_size;
+ } else {
+ xbt_assert2(0,"bad string parameter, support only \"src\" and \"dst\", at offset: %d (\"%s\")",i,value);
+ }
+ i=i+3;
+
+ xbt_assert4( param_size >= number, "bad string parameter, not enough length param_size, at offset: %d (\"%s\") %d %d",i,value,param_size,number);
+
+ const char* param = param_list[number];
+ int size = strlen(param);
+ int cp;
+ for(cp = 0; cp < size; cp++ ) {
+ result_result[i_result_buffer] = param[cp];
+ i_result_buffer++;
+ if( i_result_buffer >= BUFFER_SIZE ) break;
+ }
+ } else {
+ result_result[i_result_buffer] = value[i];
+ i_result_buffer++;
+ i++; // next char
+ }
+
+ } while(i<value_length && i_result_buffer < BUFFER_SIZE);
+
+ xbt_assert2( i_result_buffer < BUFFER_SIZE, "solving string \"%s\", small buffer size (%d)",value,BUFFER_SIZE);
+ result_result[i_result_buffer] = 0;
+ return xbt_strdup(result_result);
+}
+
+static xbt_dict_t rulebased_get_onelink_routes(void)
+{
+ xbt_die("\"rulebased_get_onelink_routes\" function not implemented yet");
+}
+
+static int rulebased_is_router(const char *name)
+{
+ xbt_die("\"rulebased_is_router\" function not implemented yet");
+}
+
+/* Business methods */
+static route_extended_t rulebased_get_route(routing_component_t rc, const char* src,const char* dst) {
+ xbt_assert1(rc&&src&&dst, "Invalid params for \"get_route\" function at AS \"%s\"",rc->name);
+
+ /* set utils vars */
+ routing_component_rulebased_t routing = (routing_component_rulebased_t) rc;
+
+ int are_processing_units;
+ xbt_dynar_t rule_list;
+ if( xbt_dict_get_or_null(routing->dict_processing_units,src) && xbt_dict_get_or_null(routing->dict_processing_units,dst) ) {
+ are_processing_units = 1;
+ rule_list = routing->list_route;
+ } else if( xbt_dict_get_or_null(routing->dict_autonomous_systems,src) && xbt_dict_get_or_null(routing->dict_autonomous_systems,dst) ) {
+ are_processing_units = 0;
+ rule_list = routing->list_ASroute;
+ } else
+ xbt_assert2(NULL, "Ask for route \"from\"(%s) or \"to\"(%s) no found in the local table",src,dst);
+
+ int rc_src = -1;
+ int rc_dst = -1;
+ int src_length = (int)strlen(src);
+ int dst_length = (int)strlen(dst);
+
+ xbt_dynar_t links_list = xbt_dynar_new(global_routing->size_of_link,NULL);
+
+ rule_route_t ruleroute;
+ unsigned int cpt;
+ int ovector_src[OVECCOUNT];
+ int ovector_dst[OVECCOUNT];
+ const char** list_src = NULL;
+ const char** list_dst = NULL;
+ xbt_dynar_foreach(rule_list, cpt, ruleroute) {
+ rc_src = pcre_exec(ruleroute->re_src,NULL,src,src_length,0,0,ovector_src,OVECCOUNT);
+ if( rc_src >= 0 ) {
+ rc_dst = pcre_exec(ruleroute->re_dst,NULL,dst,dst_length,0,0,ovector_dst,OVECCOUNT);
+ if( rc_dst >= 0 ) {
+ xbt_assert1(!pcre_get_substring_list(src,ovector_src,rc_src,&list_src),"error solving substring list for src \"%s\"",src);
+ xbt_assert1(!pcre_get_substring_list(dst,ovector_dst,rc_dst,&list_dst),"error solving substring list for src \"%s\"",dst);
+ char* link_name;
+ xbt_dynar_foreach(ruleroute->re_str_link, cpt, link_name) {
+ char* new_link_name = remplace(link_name,list_src,rc_src,list_dst,rc_dst);
+ void* link = xbt_dict_get_or_null(surf_network_model->resource_set, new_link_name);
+ if (link)
+ xbt_dynar_push(links_list,&link);
+ else
+ THROW1(mismatch_error,0,"Link %s not found", new_link_name);
+ xbt_free(new_link_name);
+ }
+ }
+ }
+ if( rc_src >= 0 && rc_dst >= 0 ) break;
+ }
+
+ route_extended_t new_e_route = NULL;
+ if(rc_src >= 0 && rc_dst >= 0) {
+ new_e_route = xbt_new0(s_route_extended_t,1);
+ new_e_route->generic_route.link_list = links_list;
+ } else if( !strcmp(src,dst) && are_processing_units ) {
+ new_e_route = xbt_new0(s_route_extended_t,1);
+ xbt_dynar_push(links_list,&(global_routing->loopback));
+ new_e_route->generic_route.link_list = links_list;
+ } else {
+ xbt_dynar_free(&link_list);
+ }
+
+ if(!are_processing_units && new_e_route)
+ {
+ rule_route_extended_t ruleroute_extended = (rule_route_extended_t)ruleroute;
+ new_e_route->src_gateway = remplace(ruleroute_extended->re_src_gateway,list_src,rc_src,list_dst,rc_dst);
+ new_e_route->dst_gateway = remplace(ruleroute_extended->re_dst_gateway,list_src,rc_src,list_dst,rc_dst);
+ }
+
+ if(list_src) pcre_free_substring_list(list_src);
+ if(list_dst) pcre_free_substring_list(list_dst);
+
+ return new_e_route;
+}