1 /* Copyright (c) 2009-2011, 2013-2015. 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. */
7 #include "surf_routing.hpp"
8 #include "surf_routing_private.hpp"
9 #include "surf_routing_cluster.hpp"
11 #include "simgrid/platf_interface.h" // platform creation API internal interface
12 #include "simgrid/sg_config.h"
13 #include "storage_interface.hpp"
14 #include "src/surf/platform.hpp"
15 #include "surf/surfxml_parse_values.h"
24 simgrid::xbt::signal<void(simgrid::surf::NetCard*)> netcardCreatedCallbacks;
25 simgrid::xbt::signal<void(simgrid::surf::As*)> asCreatedCallbacks;
31 * @ingroup SURF_build_api
32 * @brief A library containing all known hosts
36 int COORD_HOST_LEVEL=0; //Coordinates level
38 int MSG_FILE_LEVEL; //Msg file level
40 int SIMIX_STORAGE_LEVEL; //Simix storage level
41 int MSG_STORAGE_LEVEL; //Msg storage level
43 xbt_lib_t as_router_lib;
44 int ROUTING_ASR_LEVEL; //Routing level
45 int COORD_ASR_LEVEL; //Coordinates level
46 int NS3_ASR_LEVEL; //host node for ns3
47 int ROUTING_PROP_ASR_LEVEL; //Where the properties are stored
49 /** @brief Retrieve a netcard from its name
51 * Netcards are the thing that connect host or routers to the network
53 simgrid::surf::NetCard *sg_netcard_by_name_or_null(const char *name)
55 sg_host_t h = sg_host_by_name(name);
56 simgrid::surf::NetCard *net_elm = h==NULL?NULL: h->pimpl_netcard;
58 net_elm = (simgrid::surf::NetCard*) xbt_lib_get_or_null(as_router_lib, name, ROUTING_ASR_LEVEL);
63 simgrid::surf::RoutingPlatf *routing_platf = NULL;
65 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route, surf, "Routing part of surf");
67 /** The current AS in the parsing */
68 static simgrid::surf::As *current_routing = NULL;
69 simgrid::surf::As* routing_get_current()
71 return current_routing;
74 /* this lines are only for replace use like index in the model table */
79 SURF_MODEL_DIJKSTRACACHE,
83 SURF_MODEL_TORUS_CLUSTER,
84 SURF_MODEL_FAT_TREE_CLUSTER,
87 struct s_model_type routing_models[] = {
89 "Full routing data (fast, large memory requirements, fully expressive)",
92 "Floyd routing data (slow initialization, fast lookup, lesser memory requirements, shortest path routing only)",
95 "Dijkstra routing data (fast initialization, slow lookup, small memory requirements, shortest path routing only)",
96 model_dijkstra_create},
98 "Dijkstra routing data (fast initialization, fast lookup, small memory requirements, shortest path routing only)",
99 model_dijkstracache_create},
100 {"none", "No routing (Unless you know what you are doing, avoid using this mode in combination with a non Constant network model).",
102 {"Vivaldi", "Vivaldi routing", model_vivaldi_create},
103 {"Cluster", "Cluster routing", model_cluster_create},
104 {"TorusCluster", "Torus Cluster routing", model_torus_cluster_create},
105 {"FatTreeCluster", "Fat Tree Cluster routing", model_fat_tree_cluster_create},
110 * \brief Add a netcard connecting an host to the network element list
111 * FIXME: integrate into host constructor
113 void sg_platf_new_netcard(sg_platf_host_link_cbarg_t netcard)
115 simgrid::surf::NetCard *info = sg_host_by_name(netcard->id)->pimpl_netcard;
116 xbt_assert(info, "Host '%s' not found!", netcard->id);
117 xbt_assert(current_routing->p_modelDesc == &routing_models[SURF_MODEL_CLUSTER] ||
118 current_routing->p_modelDesc == &routing_models[SURF_MODEL_VIVALDI],
119 "You have to be in model Cluster to use tag host_link!");
121 s_surf_parsing_link_up_down_t link_up_down;
122 link_up_down.link_up = Link::byName(netcard->link_up);
123 link_up_down.link_down = Link::byName(netcard->link_down);
125 xbt_assert(link_up_down.link_up, "Link '%s' not found!",netcard->link_up);
126 xbt_assert(link_up_down.link_down, "Link '%s' not found!",netcard->link_down);
128 // If dynar is is greater than netcard id and if the host_link is already defined
129 if((int)xbt_dynar_length(current_routing->p_linkUpDownList) > info->getId() &&
130 xbt_dynar_get_as(current_routing->p_linkUpDownList, info->getId(), void*))
131 surf_parse_error("Host_link for '%s' is already defined!",netcard->id);
133 XBT_DEBUG("Push Host_link for host '%s' to position %d", info->getName(), info->getId());
134 xbt_dynar_set_as(current_routing->p_linkUpDownList, info->getId(), s_surf_parsing_link_up_down_t, link_up_down);
137 void sg_platf_new_trace(sg_platf_trace_cbarg_t trace)
139 tmgr_trace_t tmgr_trace;
140 if (!trace->file || strcmp(trace->file, "") != 0) {
141 tmgr_trace = tmgr_trace_new_from_file(trace->file);
143 xbt_assert(strcmp(trace->pc_data, ""),
144 "Trace '%s' must have either a content, or point to a file on disk.",trace->id);
145 tmgr_trace = tmgr_trace_new_from_string(trace->id, trace->pc_data, trace->periodicity);
147 xbt_dict_set(traces_set_list, trace->id, (void *) tmgr_trace, NULL);
151 * \brief Make a new routing component to the platform
153 * Add a new autonomous system to the platform. Any elements (such as host,
154 * router or sub-AS) added after this call and before the corresponding call
155 * to sg_platf_new_AS_close() will be added to this AS.
157 * Once this function was called, the configuration concerning the used
158 * models cannot be changed anymore.
160 * @param AS_id name of this autonomous system. Must be unique in the platform
161 * @param wanted_routing_type one of Full, Floyd, Dijkstra or similar. Full list in the variable routing_models, in src/surf/surf_routing.c
163 void routing_AS_begin(sg_platf_AS_cbarg_t AS)
165 XBT_DEBUG("routing_AS_begin");
166 routing_model_description_t model = NULL;
168 xbt_assert(NULL == xbt_lib_get_or_null(as_router_lib, AS->id, ROUTING_ASR_LEVEL),
169 "Refusing to create a second AS called \"%s\".", AS->id);
171 _sg_cfg_init_status = 2; /* horrible hack: direct access to the global
172 * controlling the level of configuration to prevent
173 * any further config */
175 /* search the routing model */
177 case A_surfxml_AS_routing_Cluster: model = &routing_models[SURF_MODEL_CLUSTER];break;
178 case A_surfxml_AS_routing_ClusterTorus: model = &routing_models[SURF_MODEL_TORUS_CLUSTER];break;
179 case A_surfxml_AS_routing_ClusterFatTree: model = &routing_models[SURF_MODEL_FAT_TREE_CLUSTER];break;
180 case A_surfxml_AS_routing_Dijkstra: model = &routing_models[SURF_MODEL_DIJKSTRA];break;
181 case A_surfxml_AS_routing_DijkstraCache: model = &routing_models[SURF_MODEL_DIJKSTRACACHE];break;
182 case A_surfxml_AS_routing_Floyd: model = &routing_models[SURF_MODEL_FLOYD];break;
183 case A_surfxml_AS_routing_Full: model = &routing_models[SURF_MODEL_FULL];break;
184 case A_surfxml_AS_routing_None: model = &routing_models[SURF_MODEL_NONE];break;
185 case A_surfxml_AS_routing_Vivaldi: model = &routing_models[SURF_MODEL_VIVALDI];break;
186 default: xbt_die("Not a valid model!!!");
190 /* make a new routing component */
191 simgrid::surf::As *new_as = model->create();
193 new_as->p_modelDesc = model;
194 new_as->p_hierarchy = SURF_ROUTING_NULL;
195 new_as->p_name = xbt_strdup(AS->id);
197 simgrid::surf::NetCard *netcard = new simgrid::surf::NetCardImpl(new_as->p_name, SURF_NETWORK_ELEMENT_AS, current_routing);
198 if (current_routing == NULL && routing_platf->p_root == NULL) {
200 /* it is the first one */
201 new_as->p_routingFather = NULL;
202 routing_platf->p_root = new_as;
204 } else if (current_routing != NULL && routing_platf->p_root != NULL) {
206 xbt_assert(!xbt_dict_get_or_null
207 (current_routing->p_routingSons, AS->id),
208 "The AS \"%s\" already exists", AS->id);
209 /* it is a part of the tree */
210 new_as->p_routingFather = current_routing;
211 /* set the father behavior */
212 if (current_routing->p_hierarchy == SURF_ROUTING_NULL)
213 current_routing->p_hierarchy = SURF_ROUTING_RECURSIVE;
214 /* add to the sons dictionary */
215 xbt_dict_set(current_routing->p_routingSons, AS->id,
216 (void *) new_as, NULL);
217 /* add to the father element list */
218 netcard->setId(current_routing->parseAS(netcard));
220 THROWF(arg_error, 0, "All defined components must belong to a AS");
223 xbt_lib_set(as_router_lib, netcard->getName(), ROUTING_ASR_LEVEL,
225 XBT_DEBUG("Having set name '%s' id '%d'", new_as->p_name, netcard->getId());
227 /* set the new current component of the tree */
228 current_routing = new_as;
229 current_routing->p_netcard = netcard;
231 simgrid::surf::netcardCreatedCallbacks(netcard);
232 simgrid::surf::asCreatedCallbacks(new_as);
236 * \brief Specify that the current description of AS is finished
238 * Once you've declared all the content of your AS, you have to close
239 * it with this call. Your AS is not usable until you call this function.
241 * @fixme: this call is not as robust as wanted: bad things WILL happen
242 * if you call it twice for the same AS, or if you forget calling it, or
243 * even if you add stuff to a closed AS
246 void routing_AS_end()
248 xbt_assert(current_routing, "Cannot seal the current AS: none under construction");
249 current_routing->Seal();
250 current_routing = current_routing->p_routingFather;
253 /* Aux Business methods */
256 * \brief Get the AS father and the first elements of the chain
258 * \param src the source host name
259 * \param dst the destination host name
261 * Get the common father of the to processing units, and the first different
262 * father in the chain
264 static void elements_father(sg_netcard_t src, sg_netcard_t dst,
269 xbt_assert(src && dst, "bad parameters for \"elements_father\" method");
270 #define ELEMENTS_FATHER_MAXDEPTH 16 /* increase if it is not enough */
271 simgrid::surf::As *src_as, *dst_as;
272 simgrid::surf::As *path_src[ELEMENTS_FATHER_MAXDEPTH];
273 simgrid::surf::As *path_dst[ELEMENTS_FATHER_MAXDEPTH];
276 simgrid::surf::As *current;
277 simgrid::surf::As *current_src;
278 simgrid::surf::As *current_dst;
279 simgrid::surf::As *father;
281 /* (1) find the as where the src and dst are located */
282 sg_netcard_t src_data = src;
283 sg_netcard_t dst_data = dst;
284 src_as = src_data->getRcComponent();
285 dst_as = dst_data->getRcComponent();
287 char* src_name = src_data->getName();
288 char* dst_name = dst_data->getName();
291 xbt_assert(src_as && dst_as,
292 "Ask for route \"from\"(%s) or \"to\"(%s) no found", src_name, dst_name);
294 /* (2) find the path to the root routing component */
295 for (current = src_as; current != NULL; current = current->p_routingFather) {
296 if (index_src >= ELEMENTS_FATHER_MAXDEPTH)
297 xbt_die("ELEMENTS_FATHER_MAXDEPTH should be increased for path_src");
298 path_src[index_src++] = current;
300 for (current = dst_as; current != NULL; current = current->p_routingFather) {
301 if (index_dst >= ELEMENTS_FATHER_MAXDEPTH)
302 xbt_die("ELEMENTS_FATHER_MAXDEPTH should be increased for path_dst");
303 path_dst[index_dst++] = current;
306 /* (3) find the common father */
308 current_src = path_src[--index_src];
309 current_dst = path_dst[--index_dst];
310 } while (index_src > 0 && index_dst > 0 && current_src == current_dst);
312 /* (4) they are not in the same routing component, make the path */
313 if (current_src == current_dst)
314 father = current_src;
316 father = path_src[index_src + 1];
318 /* (5) result generation */
319 *res_father = father; /* first the common father of src and dst */
320 *res_src = current_src; /* second the first different father of src */
321 *res_dst = current_dst; /* three the first different father of dst */
323 #undef ELEMENTS_FATHER_MAXDEPTH
326 /* Global Business methods */
329 * \brief Recursive function for get_route_latency
331 * \param src the source host name
332 * \param dst the destination host name
333 * \param *route the route where the links are stored. It is either NULL or a ready to use dynar
334 * \param *latency the latency, if needed
336 * This function is called by "get_route" and "get_latency". It allows to walk
337 * recursively through the ASes tree.
339 static void _get_route_and_latency(
340 simgrid::surf::NetCard *src, simgrid::surf::NetCard *dst,
341 xbt_dynar_t * links, double *latency)
343 s_sg_platf_route_cbarg_t route = SG_PLATF_ROUTE_INITIALIZER;
344 memset(&route,0,sizeof(route));
346 xbt_assert(src && dst, "bad parameters for \"_get_route_latency\" method");
347 XBT_DEBUG("Solve route/latency \"%s\" to \"%s\"", src->getName(), dst->getName());
349 /* Find how src and dst are interconnected */
350 simgrid::surf::As *common_father, *src_father, *dst_father;
351 elements_father(src, dst, &common_father, &src_father, &dst_father);
352 XBT_DEBUG("elements_father: common father '%s' src_father '%s' dst_father '%s'",
353 common_father->p_name, src_father->p_name, dst_father->p_name);
355 /* Check whether a direct bypass is defined */
356 sg_platf_route_cbarg_t e_route_bypass = NULL;
357 //FIXME:REMOVE:if (common_father->get_bypass_route)
359 e_route_bypass = common_father->getBypassRoute(src, dst, latency);
361 /* Common ancestor is kind enough to declare a bypass route from src to dst -- use it and bail out */
362 if (e_route_bypass) {
363 xbt_dynar_merge(links, &e_route_bypass->link_list);
364 routing_route_free(e_route_bypass);
368 /* If src and dst are in the same AS, life is good */
369 if (src_father == dst_father) { /* SURF_ROUTING_BASE */
370 route.link_list = *links;
371 common_father->getRouteAndLatency(src, dst, &route, latency);
372 // if vivaldi latency+=vivaldi(src,dst)
376 /* Not in the same AS, no bypass. We'll have to find our path between the ASes recursively*/
378 route.link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
379 // Find the net_card corresponding to father
380 simgrid::surf::NetCard *src_father_netcard = src_father->p_netcard;
381 simgrid::surf::NetCard *dst_father_netcard = dst_father->p_netcard;
383 common_father->getRouteAndLatency(src_father_netcard, dst_father_netcard,
386 xbt_assert((route.gw_src != NULL) && (route.gw_dst != NULL),
387 "bad gateways for route from \"%s\" to \"%s\"", src->getName(), dst->getName());
389 sg_netcard_t src_gateway_net_elm = route.gw_src;
390 sg_netcard_t dst_gateway_net_elm = route.gw_dst;
392 /* If source gateway is not our source, we have to recursively find our way up to this point */
393 if (src != src_gateway_net_elm)
394 _get_route_and_latency(src, src_gateway_net_elm, links, latency);
395 xbt_dynar_merge(links, &route.link_list);
397 /* If dest gateway is not our destination, we have to recursively find our way from this point */
398 if (dst_gateway_net_elm != dst)
399 _get_route_and_latency(dst_gateway_net_elm, dst, links, latency);
403 AS_t surf_platf_get_root(routing_platf_t platf){
404 return platf->p_root;
407 e_surf_network_element_type_t surf_routing_edge_get_rc_type(sg_netcard_t netcard){
408 return netcard->getRcType();
415 * \brief Find a route between hosts
417 * \param src the network_element_t for src host
418 * \param dst the network_element_t for dst host
419 * \param route where to store the list of links.
420 * If *route=NULL, create a short lived dynar. Else, fill the provided dynar
421 * \param latency where to store the latency experienced on the path (or NULL if not interested)
422 * It is the caller responsability to initialize latency to 0 (we add to provided route)
425 * walk through the routing components tree and find a route between hosts
426 * by calling each "get_route" function in each routing component.
428 void RoutingPlatf::getRouteAndLatency(NetCard *src, NetCard *dst, xbt_dynar_t* route, double *latency)
430 XBT_DEBUG("getRouteAndLatency from %s to %s", src->getName(), dst->getName());
431 if (NULL == *route) {
432 xbt_dynar_reset(routing_platf->p_lastRoute);
433 *route = routing_platf->p_lastRoute;
436 _get_route_and_latency(src, dst, route, latency);
438 xbt_assert(!latency || *latency >= 0.0,
439 "negative latency on route between \"%s\" and \"%s\"", src->getName(), dst->getName());
442 xbt_dynar_t RoutingPlatf::getOneLinkRoutes(){
443 return recursiveGetOneLinkRoutes(p_root);
446 xbt_dynar_t RoutingPlatf::recursiveGetOneLinkRoutes(As *rc)
448 xbt_dynar_t ret = xbt_dynar_new(sizeof(Onelink*), xbt_free_f);
450 //adding my one link routes
451 xbt_dynar_t onelink_mine = rc->getOneLinkRoutes();
453 xbt_dynar_merge(&ret,&onelink_mine);
457 xbt_dict_cursor_t cursor = NULL;
459 xbt_dict_foreach(rc->p_routingSons, cursor, key, rc_child) {
460 xbt_dynar_t onelink_child = recursiveGetOneLinkRoutes(rc_child);
462 xbt_dynar_merge(&ret,&onelink_child);
470 e_surf_network_element_type_t routing_get_network_element_type(const char *name)
472 simgrid::surf::NetCard *rc = sg_netcard_by_name_or_null(name);
474 return rc->getRcType();
476 return SURF_NETWORK_ELEMENT_NULL;
479 /** @brief create the root AS */
480 void routing_model_create( void *loopback)
482 routing_platf = new simgrid::surf::RoutingPlatf(loopback);
485 /* ************************************************************************** */
486 /* ************************* GENERIC PARSE FUNCTIONS ************************ */
488 void routing_cluster_add_backbone(void* bb) {
489 xbt_assert(current_routing->p_modelDesc == &routing_models[SURF_MODEL_CLUSTER],
490 "You have to be in model Cluster to use tag backbone!");
491 xbt_assert(!static_cast<simgrid::surf::AsCluster*>(current_routing)->p_backbone, "The backbone link is already defined!");
492 static_cast<simgrid::surf::AsCluster*>(current_routing)->p_backbone =
493 static_cast<simgrid::surf::Link*>(bb);
494 XBT_DEBUG("Add a backbone to AS '%s'", current_routing->p_name);
497 void sg_platf_new_cabinet(sg_platf_cabinet_cbarg_t cabinet)
500 char *groups , *host_id , *link_id = NULL;
502 xbt_dynar_t radical_elements;
503 xbt_dynar_t radical_ends;
506 radical_elements = xbt_str_split(cabinet->radical, ",");
507 xbt_dynar_foreach(radical_elements, iter, groups) {
509 radical_ends = xbt_str_split(groups, "-");
510 start = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 0, char *));
512 switch (xbt_dynar_length(radical_ends)) {
517 end = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 1, char *));
520 surf_parse_error("Malformed radical");
523 s_sg_platf_host_cbarg_t host = SG_PLATF_HOST_INITIALIZER;
524 memset(&host, 0, sizeof(host));
525 host.initiallyOn = 1;
527 host.speed_scale = 1.0;
528 host.core_amount = 1;
530 s_sg_platf_link_cbarg_t link = SG_PLATF_LINK_INITIALIZER;
531 memset(&link, 0, sizeof(link));
532 link.initiallyOn = 1;
533 link.policy = SURF_LINK_FULLDUPLEX;
534 link.latency = cabinet->lat;
535 link.bandwidth = cabinet->bw;
537 s_sg_platf_host_link_cbarg_t host_link = SG_PLATF_HOST_LINK_INITIALIZER;
538 memset(&host_link, 0, sizeof(host_link));
540 for (i = start; i <= end; i++) {
541 host_id = bprintf("%s%d%s",cabinet->prefix,i,cabinet->suffix);
542 link_id = bprintf("link_%s%d%s",cabinet->prefix,i,cabinet->suffix);
545 host.speed_peak = xbt_dynar_new(sizeof(double), NULL);
546 xbt_dynar_push(host.speed_peak,&cabinet->speed);
547 sg_platf_new_host(&host);
548 xbt_dynar_free(&host.speed_peak);
549 sg_platf_new_link(&link);
551 char* link_up = bprintf("%s_UP",link_id);
552 char* link_down = bprintf("%s_DOWN",link_id);
553 host_link.id = host_id;
554 host_link.link_up = link_up;
555 host_link.link_down = link_down;
556 sg_platf_new_netcard(&host_link);
564 xbt_dynar_free(&radical_ends);
566 xbt_dynar_free(&radical_elements);
569 void sg_platf_new_peer(sg_platf_peer_cbarg_t peer)
571 using simgrid::surf::NetCard;
572 using simgrid::surf::AsCluster;
574 char *host_id = NULL;
575 char *link_id = NULL;
576 char *router_id = NULL;
579 host_id = HOST_PEER(peer->id);
580 link_id = LINK_PEER(peer->id);
581 router_id = ROUTER_PEER(peer->id);
583 XBT_DEBUG("<AS id=\"%s\"\trouting=\"Cluster\">", peer->id);
584 s_sg_platf_AS_cbarg_t AS = SG_PLATF_AS_INITIALIZER;
586 AS.routing = A_surfxml_AS_routing_Cluster;
587 sg_platf_new_AS_begin(&AS);
589 XBT_DEBUG("<host\tid=\"%s\"\tpower=\"%f\"/>", host_id, peer->speed);
590 s_sg_platf_host_cbarg_t host = SG_PLATF_HOST_INITIALIZER;
591 memset(&host, 0, sizeof(host));
592 host.initiallyOn = 1;
595 host.speed_peak = xbt_dynar_new(sizeof(double), NULL);
596 xbt_dynar_push(host.speed_peak,&peer->speed);
598 //host.power_peak = peer->power;
599 host.speed_scale = 1.0;
600 host.speed_trace = peer->availability_trace;
601 host.state_trace = peer->state_trace;
602 host.core_amount = 1;
603 sg_platf_new_host(&host);
604 xbt_dynar_free(&host.speed_peak);
606 s_sg_platf_link_cbarg_t link = SG_PLATF_LINK_INITIALIZER;
607 memset(&link, 0, sizeof(link));
608 link.initiallyOn = 1;
609 link.policy = SURF_LINK_SHARED;
610 link.latency = peer->lat;
612 char* link_up = bprintf("%s_UP",link_id);
613 XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_up,
614 peer->bw_out, peer->lat);
616 link.bandwidth = peer->bw_out;
617 sg_platf_new_link(&link);
619 char* link_down = bprintf("%s_DOWN",link_id);
620 XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_down,
621 peer->bw_in, peer->lat);
623 link.bandwidth = peer->bw_in;
624 sg_platf_new_link(&link);
626 XBT_DEBUG("<host_link\tid=\"%s\"\tup=\"%s\"\tdown=\"%s\" />", host_id,link_up,link_down);
627 s_sg_platf_host_link_cbarg_t host_link = SG_PLATF_HOST_LINK_INITIALIZER;
628 memset(&host_link, 0, sizeof(host_link));
629 host_link.id = host_id;
630 host_link.link_up = link_up;
631 host_link.link_down = link_down;
632 sg_platf_new_netcard(&host_link);
634 XBT_DEBUG("<router id=\"%s\"/>", router_id);
635 s_sg_platf_router_cbarg_t router = SG_PLATF_ROUTER_INITIALIZER;
636 memset(&router, 0, sizeof(router));
637 router.id = router_id;
638 router.coord = peer->coord;
639 sg_platf_new_router(&router);
640 static_cast<AsCluster*>(current_routing)->p_router = static_cast<NetCard*>(xbt_lib_get_or_null(as_router_lib, router.id, ROUTING_ASR_LEVEL));
643 sg_platf_new_AS_end();
646 //xbt_dynar_free(&tab_elements_num);
654 // static void routing_parse_Srandom(void)
656 // double mean, std, min, max, seed;
657 // char *random_id = A_surfxml_random_id;
658 // char *random_radical = A_surfxml_random_radical;
659 // char *rd_name = NULL;
661 // mean = surf_parse_get_double(A_surfxml_random_mean);
662 // std = surf_parse_get_double(A_surfxml_random_std___deviation);
663 // min = surf_parse_get_double(A_surfxml_random_min);
664 // max = surf_parse_get_double(A_surfxml_random_max);
665 // seed = surf_parse_get_double(A_surfxml_random_seed);
669 // random_data_t random = xbt_new0(s_random_data_t, 1);
672 // xbt_dynar_t radical_elements;
673 // unsigned int iter;
676 // xbt_dynar_t radical_ends;
678 // switch (A_surfxml_random_generator) {
679 // case AU_surfxml_random_generator:
680 // case A_surfxml_random_generator_NONE:
681 // random->generator = NONE;
683 // case A_surfxml_random_generator_DRAND48:
684 // random->generator = DRAND48;
686 // case A_surfxml_random_generator_RAND:
687 // random->generator = RAND;
689 // case A_surfxml_random_generator_RNGSTREAM:
690 // random->generator = RNGSTREAM;
693 // surf_parse_error("Invalid random generator");
696 // random->seed = seed;
697 // random->min = min;
698 // random->max = max;
700 // /* Check user stupidities */
702 // THROWF(arg_error, 0, "random->max < random->min (%f < %f)", max, min);
704 // THROWF(arg_error, 0, "random->mean < random->min (%f < %f)", mean, min);
706 // THROWF(arg_error, 0, "random->mean > random->max (%f > %f)", mean, max);
708 // /* normalize the mean and standard deviation before storing */
709 // random->mean = (mean - min) / (max - min);
710 // random->std = std / (max - min);
712 // if (random->mean * (1 - random->mean) < random->std * random->std)
713 // THROWF(arg_error, 0, "Invalid mean and standard deviation (%f and %f)",
714 // random->mean, random->std);
717 // ("id = '%s' min = '%f' max = '%f' mean = '%f' std_deviatinon = '%f' generator = '%d' seed = '%ld' radical = '%s'",
718 // random_id, random->min, random->max, random->mean, random->std,
719 // (int)random->generator, random->seed, random_radical);
721 // if (!random_value)
722 // random_value = xbt_dict_new_homogeneous(free);
724 // if (!strcmp(random_radical, "")) {
725 // res = random_generate(random);
726 // rd_value = bprintf("%f", res);
727 // xbt_dict_set(random_value, random_id, rd_value, NULL);
729 // radical_elements = xbt_str_split(random_radical, ",");
730 // xbt_dynar_foreach(radical_elements, iter, groups) {
731 // radical_ends = xbt_str_split(groups, "-");
732 // switch (xbt_dynar_length(radical_ends)) {
734 // xbt_assert(!xbt_dict_get_or_null(random_value, random_id),
735 // "Custom Random '%s' already exists !", random_id);
736 // res = random_generate(random);
738 // bprintf("%s%d", random_id,
739 // atoi(xbt_dynar_getfirst_as(radical_ends, char *)));
740 // xbt_dict_set(random_value, tmpbuf, bprintf("%f", res), NULL);
745 // start = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 0, char *));
746 // end = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 1, char *));
747 // for (i = start; i <= end; i++) {
748 // xbt_assert(!xbt_dict_get_or_null(random_value, random_id),
749 // "Custom Random '%s' already exists !", bprintf("%s%d",
752 // res = random_generate(random);
753 // tmpbuf = bprintf("%s%d", random_id, i);
754 // xbt_dict_set(random_value, tmpbuf, bprintf("%f", res), NULL);
759 // XBT_CRITICAL("Malformed radical");
762 // res = random_generate(random);
763 // rd_name = bprintf("%s_router", random_id);
764 // rd_value = bprintf("%f", res);
765 // xbt_dict_set(random_value, rd_name, rd_value, NULL);
767 // xbt_dynar_free(&radical_ends);
770 // xbt_dynar_free(&radical_elements);
774 static void check_disk_attachment()
776 xbt_lib_cursor_t cursor;
779 simgrid::surf::NetCard *host_elm;
780 xbt_lib_foreach(storage_lib, cursor, key, data) {
781 if(xbt_lib_get_level(xbt_lib_get_elm_or_null(storage_lib, key), SURF_STORAGE_LEVEL) != NULL) {
782 simgrid::surf::Storage *storage = static_cast<simgrid::surf::Storage*>(xbt_lib_get_level(xbt_lib_get_elm_or_null(storage_lib, key), SURF_STORAGE_LEVEL));
783 host_elm = sg_netcard_by_name_or_null(storage->p_attach);
785 surf_parse_error("Unable to attach storage %s: host %s doesn't exist.", storage->getName(), storage->p_attach);
790 void routing_register_callbacks()
792 simgrid::surf::on_postparse.connect(check_disk_attachment);
794 instr_routing_define_callbacks();
798 * \brief Recursive function for finalize
800 * \param rc the source host name
802 * This fuction is call by "finalize". It allow to finalize the
803 * AS or routing components. It delete all the structures.
805 static void finalize_rec(simgrid::surf::As *as) {
806 xbt_dict_cursor_t cursor = NULL;
810 xbt_dict_foreach(as->p_routingSons, cursor, key, elem) {
817 /** \brief Frees all memory allocated by the routing module */
818 void routing_exit(void) {
819 delete routing_platf;
825 RoutingPlatf::RoutingPlatf(void *loopback)
826 : p_loopback(loopback)
829 RoutingPlatf::~RoutingPlatf()
831 xbt_dynar_free(&p_lastRoute);
832 finalize_rec(p_root);
838 AS_t surf_AS_get_routing_root() {
839 return routing_platf->p_root;
842 const char *surf_AS_get_name(simgrid::surf::As *as) {
846 static simgrid::surf::As *surf_AS_recursive_get_by_name(
847 simgrid::surf::As *current, const char * name)
849 xbt_dict_cursor_t cursor = NULL;
852 simgrid::surf::As *tmp = NULL;
854 if(!strcmp(current->p_name, name))
857 xbt_dict_foreach(current->p_routingSons, cursor, key, elem) {
858 tmp = surf_AS_recursive_get_by_name(elem, name);
866 simgrid::surf::As *surf_AS_get_by_name(const char * name)
868 simgrid::surf::As *as = surf_AS_recursive_get_by_name(routing_platf->p_root, name);
870 XBT_WARN("Impossible to find an AS with name %s, please check your input", name);
874 xbt_dict_t surf_AS_get_routing_sons(simgrid::surf::As *as)
876 return as->p_routingSons;
879 xbt_dynar_t surf_AS_get_hosts(simgrid::surf::As *as)
881 xbt_dynar_t elms = as->p_indexNetworkElm;
882 int count = xbt_dynar_length(elms);
883 xbt_dynar_t res = xbt_dynar_new(sizeof(sg_host_t), NULL);
884 for (int index = 0; index < count; index++) {
886 xbt_dynar_get_as(elms, index, simgrid::surf::NetCard*);
887 sg_host_t delm = simgrid::s4u::Host::by_name_or_null(relm->getName());
889 xbt_dynar_push(res, &delm);
895 void surf_AS_get_graph(AS_t as, xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges) {
896 as->getGraph(graph, nodes, edges);