+/* ***************** GENERIC PARSE FUNCTIONS (declarations) ***************** */
+
+static void generic_set_processing_units(routing_component_t rc, const char* name);
+static void generic_set_autonomous_system(routing_component_t rc, const char* name);
+static void generic_set_route(routing_component_t rc, const char* src, const char* dst, route_t route);
+static void generic_set_ASroute(routing_component_t rc, const char* src, const char* dst, route_extended_t e_route);
+static void generic_set_bypassroute(routing_component_t rc, const char* src, const char* dst, route_extended_t e_route);
+
+/* ************************************************************************** */
+/* *************** GENERIC BUSINESS METHODS (declarations) ****************** */
+
+static route_extended_t generic_get_bypassroute(routing_component_t rc, const char* src, const char* dst);
+
+/* ************************************************************************** */
+/* ****************** GENERIC AUX FUNCTIONS (declarations) ****************** */
+
+static route_extended_t generic_new_extended_route(e_surf_routing_hierarchy_t hierarchy, void* data, int order);
+static void generic_free_extended_route(route_extended_t e_route);
+static routing_component_t generic_autonomous_system_exist(routing_component_t rc, char* element);
+static routing_component_t generic_processing_units_exist(routing_component_t rc, char* element);
+static void generic_src_dst_check(routing_component_t rc, const char* src, const char* dst);
+
+/* ************************************************************************** */
+/* **************************** GLOBAL FUNCTIONS **************************** */
+
+/* global parse functions */
+static char* src = NULL; /* temporary store the source name of a route */
+static char* dst = NULL; /* temporary store the destination name of a route */
+static char* gw_src = NULL; /* temporary store the gateway source name of a route */
+static char* gw_dst = NULL; /* temporary store the gateway destination name of a route */
+static xbt_dynar_t link_list = NULL; /* temporary store of current list link of a route */
+
+/**
+ * \brief Add a "host" to the network element list
+ */
+static void parse_S_host(void) {
+ if( current_routing->hierarchy == SURF_ROUTING_NULL ) current_routing->hierarchy = SURF_ROUTING_BASE;
+ xbt_assert1(!xbt_dict_get_or_null(global_routing->where_network_elements,A_surfxml_host_id),
+ "Reading a host, processing unit \"%s\" already exist",A_surfxml_host_id);
+ xbt_assert1(current_routing->set_processing_units,
+ "no defined method \"set_processing_units\" in \"%s\"",current_routing->name);
+ (*(current_routing->set_processing_units))(current_routing,A_surfxml_host_id);
+ xbt_dict_set(global_routing->where_network_elements,A_surfxml_host_id,(void*)current_routing,NULL);
+}
+
+/**
+ * \brief Add a "router" to the network element list
+ */
+static void parse_S_router(void) {
+ if( current_routing->hierarchy == SURF_ROUTING_NULL ) current_routing->hierarchy = SURF_ROUTING_BASE;
+ xbt_assert1(!xbt_dict_get_or_null(global_routing->where_network_elements,A_surfxml_router_id),
+ "Reading a router, processing unit \"%s\" already exist",A_surfxml_router_id);
+ xbt_assert1(current_routing->set_processing_units,
+ "no defined method \"set_processing_units\" in \"%s\"",current_routing->name);
+ (*(current_routing->set_processing_units))(current_routing,A_surfxml_router_id);
+ xbt_dict_set(global_routing->where_network_elements,A_surfxml_router_id,(void*)current_routing,NULL);
+}
+
+/**
+ * \brief Set the endponints for a route
+ */
+static void parse_S_route_new_and_endpoints(void) {
+ if( src != NULL && dst != NULL && link_list != NULL )
+ THROW2(arg_error,0,"Route between %s to %s can not be defined",A_surfxml_route_src,A_surfxml_route_dst);
+ src = A_surfxml_route_src;
+ dst = A_surfxml_route_dst;
+ xbt_assert2(strlen(src)>0||strlen(dst)>0,
+ "Some limits are null in the route between \"%s\" and \"%s\"",src,dst);
+ link_list = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
+}
+
+/**
+ * \brief Set the endponints and gateways for a ASroute
+ */
+static void parse_S_ASroute_new_and_endpoints(void) {
+ if( src != NULL && dst != NULL && link_list != NULL )
+ THROW2(arg_error,0,"Route between %s to %s can not be defined",A_surfxml_ASroute_src,A_surfxml_ASroute_dst);
+ src = A_surfxml_ASroute_src;
+ dst = A_surfxml_ASroute_dst;
+ gw_src = A_surfxml_ASroute_gw_src;
+ gw_dst = A_surfxml_ASroute_gw_dst;
+ xbt_assert2(strlen(src)>0||strlen(dst)>0||strlen(gw_src)>0||strlen(gw_dst)>0,
+ "Some limits are null in the route between \"%s\" and \"%s\"",src,dst);
+ link_list = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
+}
+
+/**
+ * \brief Set the endponints for a bypassRoute
+ */
+static void parse_S_bypassRoute_new_and_endpoints(void) {
+ if( src != NULL && dst != NULL && link_list != NULL )
+ THROW2(arg_error,0,"Bypass Route between %s to %s can not be defined",A_surfxml_bypassRoute_src,A_surfxml_bypassRoute_dst);
+ src = A_surfxml_bypassRoute_src;
+ dst = A_surfxml_bypassRoute_dst;
+ gw_src = A_surfxml_bypassRoute_gw_src;
+ gw_dst = A_surfxml_bypassRoute_gw_dst;
+ xbt_assert2(strlen(src)>0||strlen(dst)>0||strlen(gw_src)>0||strlen(gw_dst)>0,
+ "Some limits are null in the route between \"%s\" and \"%s\"",src,dst);
+ link_list = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
+}
+
+/**
+ * \brief Set a new link on the actual list of link for a route or ASroute
+ */
+static void parse_E_link_c_ctn_new_elem(void) {
+ char *val;
+ val = xbt_strdup(A_surfxml_link_c_ctn_id);
+ xbt_dynar_push(link_list, &val);
+}
+
+/**
+ * \brief Store the route by calling the set_route function of the current routing component
+ */
+static void parse_E_route_store_route(void) {
+ route_t route = xbt_new0(s_route_t,1);
+ route->link_list = link_list;
+ xbt_assert1(generic_processing_units_exist(current_routing,src),"the \"%s\" processing units gateway does not exist",src);
+ xbt_assert1(generic_processing_units_exist(current_routing,dst),"the \"%s\" processing units gateway does not exist",dst);
+ xbt_assert1(current_routing->set_route,"no defined method \"set_route\" in \"%s\"",current_routing->name);
+ (*(current_routing->set_route))(current_routing,src,dst,route);
+ link_list = NULL;
+ src = NULL;
+ dst = NULL;
+}
+
+/**
+ * \brief Store the ASroute by calling the set_ASroute function of the current routing component
+ */
+static void parse_E_ASroute_store_route(void) {
+ route_extended_t e_route = xbt_new0(s_route_extended_t,1);
+ e_route->generic_route.link_list = link_list;
+ e_route->src_gateway = xbt_strdup(gw_src);
+ e_route->dst_gateway = xbt_strdup(gw_dst);
+ xbt_assert1(generic_autonomous_system_exist(current_routing,src),"the \"%s\" autonomous system does not exist",src);
+ xbt_assert1(generic_autonomous_system_exist(current_routing,dst),"the \"%s\" autonomous system does not exist",dst);
+ xbt_assert1(generic_processing_units_exist(current_routing,gw_src),"the \"%s\" processing units gateway does not exist",gw_src);
+ xbt_assert1(generic_processing_units_exist(current_routing,gw_dst),"the \"%s\" processing units gateway does not exist",gw_dst);
+ xbt_assert1(current_routing->set_ASroute,"no defined method \"set_ASroute\" in \"%s\"",current_routing->name);
+ (*(current_routing->set_ASroute))(current_routing,src,dst,e_route);
+ link_list = NULL;
+ src = NULL;
+ dst = NULL;
+ gw_src = NULL;
+ gw_dst = NULL;
+}
+
+/**
+ * \brief Store the bypass route by calling the set_bypassroute function of the current routing component
+ */
+static void parse_E_bypassRoute_store_route(void) {
+ route_extended_t e_route = xbt_new0(s_route_extended_t,1);
+ e_route->generic_route.link_list = link_list;
+ e_route->src_gateway = xbt_strdup(gw_src);
+ e_route->dst_gateway = xbt_strdup(gw_dst);
+ xbt_assert1(generic_autonomous_system_exist(current_routing,src),"the \"%s\" autonomous system does not exist",src);
+ xbt_assert1(generic_autonomous_system_exist(current_routing,dst),"the \"%s\" autonomous system does not exist",dst);
+ xbt_assert1(generic_processing_units_exist(current_routing,gw_src),"the \"%s\" processing units gateway does not exist",gw_src);
+ xbt_assert1(generic_processing_units_exist(current_routing,gw_dst),"the \"%s\" processing units gateway does not exist",gw_dst);
+ xbt_assert1(current_routing->set_bypassroute,"no defined method \"set_bypassroute\" in \"%s\"",current_routing->name);
+ (*(current_routing->set_bypassroute))(current_routing,src,dst,e_route);
+ link_list = NULL;
+ src = NULL;
+ dst = NULL;
+ gw_src = NULL;
+ gw_dst = NULL;
+}
+
+/**
+ * \brief Make a new routing component
+ *
+ * Detect the routing model type of the routing component, make the new structure and
+ * set the parsing functions to allows parsing the part of the routing tree
+ */
+static void parse_S_AS(void) {
+ routing_component_t new_routing;
+ model_type_t model = NULL;
+ char* wanted = A_surfxml_AS_routing;
+ int cpt;
+ /* seach the routing model */
+ for (cpt=0;routing_models[cpt].name;cpt++)
+ if (!strcmp(wanted,routing_models[cpt].name))
+ model = &routing_models[cpt];
+ /* if its not exist, error */
+ if( model == NULL ) {
+ fprintf(stderr,"Routing model %s not found. Existing models:\n",wanted);
+ for (cpt=0;routing_models[cpt].name;cpt++)
+ if (!strcmp(wanted,routing_models[cpt].name))
+ fprintf(stderr," %s: %s\n",routing_models[cpt].name,routing_models[cpt].desc);
+ xbt_die(NULL);
+ }
+
+ /* make a new routing component */
+ new_routing = (routing_component_t)(*(model->create))();
+ new_routing->routing = model;
+ new_routing->hierarchy = SURF_ROUTING_NULL;
+ new_routing->name = xbt_strdup(A_surfxml_AS_id);
+ new_routing->routing_sons = xbt_dict_new();
+ INFO2("Routing %s for AS %s",A_surfxml_AS_routing,A_surfxml_AS_id);
+
+ if( current_routing == NULL && global_routing->root == NULL ){
+
+ /* it is the first one */
+ new_routing->routing_father = NULL;
+ global_routing->root = new_routing;
+
+ } else if( current_routing != NULL && global_routing->root != NULL ) {
+
+ xbt_assert1(!xbt_dict_get_or_null(current_routing->routing_sons,A_surfxml_AS_id),
+ "The AS \"%s\" already exist",A_surfxml_AS_id);
+ /* it is a part of the tree */
+ new_routing->routing_father = current_routing;
+ /* set the father behavior */
+ if( current_routing->hierarchy == SURF_ROUTING_NULL ) current_routing->hierarchy = SURF_ROUTING_RECURSIVE;
+ /* add to the sons dictionary */
+ xbt_dict_set(current_routing->routing_sons,A_surfxml_AS_id,(void*)new_routing,NULL);
+ /* add to the father element list */
+ (*(current_routing->set_autonomous_system))(current_routing,A_surfxml_AS_id);
+ /* unload the prev parse rules */
+ (*(current_routing->routing->unload))();
+
+ } else {
+ THROW0(arg_error,0,"All defined components must be belong to a AS");
+ }
+ /* set the new parse rules */
+ (*(new_routing->routing->load))();
+ /* set the new current component of the tree */
+ current_routing = new_routing;
+}
+
+/**
+ * \brief Finish the creation of a new routing component
+ *
+ * When you finish to read the routing component, other structures must be created.
+ * the "end" method allow to do that for any routing model type
+ */
+static void parse_E_AS(void) {
+
+ if( current_routing == NULL ) {
+ THROW1(arg_error,0,"Close AS(%s), that never open",A_surfxml_AS_id);
+ } else {
+ xbt_assert1(!xbt_dict_get_or_null(global_routing->where_network_elements,current_routing->name),
+ "The AS \"%s\" already exist",current_routing->name);
+ xbt_dict_set(global_routing->where_network_elements,current_routing->name,current_routing->routing_father,NULL);
+ (*(current_routing->routing->unload))();
+ (*(current_routing->routing->end))();
+ current_routing = current_routing->routing_father;
+ if( current_routing != NULL )
+ (*(current_routing->routing->load))();
+ }
+}
+
+/* Aux Business methods */
+
+/**
+ * \brief Get the AS father and the first elements of the chain
+ *
+ * \param src the source host name
+ * \param dst the destination host name
+ *
+ * Get the common father of the to processing units, and the first different
+ * father in the chain
+ */
+static xbt_dynar_t elements_father(const char* src,const char* dst) {
+
+ xbt_assert0(src&&dst,"bad parameters for \"elements_father\" method");
+
+ xbt_dynar_t result = xbt_dynar_new(sizeof(char*), NULL);
+
+ routing_component_t src_as, dst_as;
+ int index_src, index_dst, index_father_src, index_father_dst;
+ xbt_dynar_t path_src = NULL;
+ xbt_dynar_t path_dst = NULL;
+ routing_component_t current = NULL;
+ routing_component_t* current_src = NULL;
+ routing_component_t* current_dst = NULL;
+ routing_component_t* father = NULL;
+
+ /* (1) find the as where the src and dst are located */
+ src_as = xbt_dict_get_or_null(global_routing->where_network_elements,src);
+ dst_as = xbt_dict_get_or_null(global_routing->where_network_elements,dst);
+ xbt_assert2(src_as&&dst_as, "Ask for route \"from\"(%s) or \"to\"(%s) no found",src,dst);
+
+ /* (2) find the path to the root routing component */
+ path_src = xbt_dynar_new(sizeof(routing_component_t), NULL);
+ current = src_as;
+ while( current != NULL ) {
+ xbt_dynar_push(path_src,¤t);
+ current = current->routing_father;
+ }
+ path_dst = xbt_dynar_new(sizeof(routing_component_t), NULL);
+ current = dst_as;
+ while( current != NULL ) {
+ xbt_dynar_push(path_dst,¤t);
+ current = current->routing_father;
+ }
+
+ /* (3) find the common father */
+ index_src = (path_src->used)-1;
+ index_dst = (path_dst->used)-1;
+ current_src = xbt_dynar_get_ptr(path_src,index_src);
+ current_dst = xbt_dynar_get_ptr(path_dst,index_dst);
+ while( index_src >= 0 && index_dst >= 0 && *current_src == *current_dst ) {
+ current_src = xbt_dynar_get_ptr(path_src,index_src);
+ current_dst = xbt_dynar_get_ptr(path_dst,index_dst);
+ index_src--;
+ index_dst--;
+ }
+ index_src++;
+ index_dst++;
+ current_src = xbt_dynar_get_ptr(path_src,index_src);
+ current_dst = xbt_dynar_get_ptr(path_dst,index_dst);
+
+ /* (4) they are not in the same routing component, make the path */
+ index_father_src = index_src+1;
+ index_father_dst = index_dst+1;
+
+ if(*current_src==*current_dst)
+ father = current_src;
+ else
+ father = xbt_dynar_get_ptr(path_src,index_father_src);
+
+ /* (5) result generation */
+ xbt_dynar_push(result,father); /* first same the father of src and dst */
+ xbt_dynar_push(result,current_src); /* second the first different father of src */
+ xbt_dynar_push(result,current_dst); /* three the first different father of dst */
+
+ xbt_dynar_free(&path_src);
+ xbt_dynar_free(&path_dst);
+
+ return result;
+}