Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge pull request #2 from mquinson/master
[simgrid.git] / src / surf / surf_routing.cpp
index 2fa1297..3028a23 100644 (file)
@@ -8,10 +8,8 @@
 #include "surf_routing_private.hpp"
 #include "surf_routing_cluster.hpp"
 
-#include "simgrid/platf_interface.h"    // platform creation API internal interface
 #include "simgrid/sg_config.h"
 #include "storage_interface.hpp"
-#include "src/surf/platform.hpp"
 #include "surf/surfxml_parse_values.h"
 
 #include "src/surf/surf_routing_cluster_torus.hpp"
@@ -20,6 +18,9 @@
 #include "src/surf/surf_routing_floyd.hpp"
 #include "src/surf/surf_routing_full.hpp"
 #include "src/surf/surf_routing_vivaldi.hpp"
+#include "src/surf/xml/platf.hpp" // FIXME: move that back to the parsing area
+
+#include <vector>
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route, surf, "Routing part of surf");
 
@@ -38,6 +39,10 @@ namespace surf {
     xbt_dict_free(&sons_);
     xbt_dynar_free(&vertices_);
     xbt_dynar_free(&upDownLinks);
+    if (nullptr != bypassRoutes_)
+      for (auto &kv : *bypassRoutes_)
+        delete kv.second;
+    delete bypassRoutes_;
     xbt_free(name_);
     delete netcard_;
   }
@@ -46,9 +51,6 @@ namespace surf {
     sealed_ = true;
   }
 
-  sg_platf_route_cbarg_t As::getBypassRoute(NetCard * /*src*/, NetCard * /*dst*/, double * /*lat*/) {
-    return NULL;
-  }
   xbt_dynar_t As::getOneLinkRoutes() {
     return NULL;
   }
@@ -62,8 +64,151 @@ namespace surf {
   void As::addRoute(sg_platf_route_cbarg_t /*route*/){
     xbt_die("AS %s does not accept new routes (wrong class).",name_);
   }
-  void As::parseBypassroute(sg_platf_route_cbarg_t /*e_route*/){
-    xbt_die("AS %s does not accept new bypass routes (wrong class).",name_);
+
+  std::vector<Link*> *As::getBypassRoute(NetCard *src, NetCard *dst)
+  {
+    // If never set a bypass route return NULL without any further computations
+    XBT_DEBUG("generic_get_bypassroute from %s to %s", src->name(), dst->name());
+    if (bypassRoutes_ == nullptr)
+      return nullptr;
+
+    std::vector<Link*> *bypassedRoute = nullptr;
+
+    if(dst->containingAS() == this && src->containingAS() == this ){
+      char *route_name = bprintf("%s#%s", src->name(), dst->name());
+      if (bypassRoutes_->find(route_name) != bypassRoutes_->end()) {
+        bypassedRoute = bypassRoutes_->at(route_name);
+        XBT_DEBUG("Found a bypass route with %zu links",bypassedRoute->size());
+      }
+      free(route_name);
+      return bypassedRoute;
+    }
+
+    int index_src, index_dst;
+    As **current_src = NULL;
+    As **current_dst = NULL;
+
+    As *src_as = src->containingAS();
+    As *dst_as = dst->containingAS();
+
+    /* (2) find the path to the root routing component */
+    xbt_dynar_t path_src = xbt_dynar_new(sizeof(As*), NULL);
+    As *current = src_as;
+    while (current != NULL) {
+      xbt_dynar_push(path_src, &current);
+      current = current->father_;
+    }
+    xbt_dynar_t path_dst = xbt_dynar_new(sizeof(As*), NULL);
+    current = dst_as;
+    while (current != NULL) {
+      xbt_dynar_push(path_dst, &current);
+      current = current->father_;
+    }
+
+    /* (3) find the common father */
+    index_src = path_src->used - 1;
+    index_dst = path_dst->used - 1;
+    current_src = (As **) xbt_dynar_get_ptr(path_src, index_src);
+    current_dst = (As **) xbt_dynar_get_ptr(path_dst, index_dst);
+    while (index_src >= 0 && index_dst >= 0 && *current_src == *current_dst) {
+      xbt_dynar_pop_ptr(path_src);
+      xbt_dynar_pop_ptr(path_dst);
+      index_src--;
+      index_dst--;
+      current_src = (As **) xbt_dynar_get_ptr(path_src, index_src);
+      current_dst = (As **) xbt_dynar_get_ptr(path_dst, index_dst);
+    }
+
+    int max_index_src = path_src->used - 1;
+    int max_index_dst = path_dst->used - 1;
+
+    int max_index = std::max(max_index_src, max_index_dst);
+
+    for (int max = 0; max <= max_index; max++) {
+      for (int i = 0; i < max; i++) {
+        if (i <= max_index_src && max <= max_index_dst) {
+          char *route_name = bprintf("%s#%s",
+              (*(As **) (xbt_dynar_get_ptr(path_src, i)))->name_,
+              (*(As **) (xbt_dynar_get_ptr(path_dst, max)))->name_);
+          if (bypassRoutes_->find(route_name) != bypassRoutes_->end())
+            bypassedRoute = bypassRoutes_->at(route_name);
+          xbt_free(route_name);
+        }
+        if (bypassedRoute)
+          break;
+        if (max <= max_index_src && i <= max_index_dst) {
+          char *route_name = bprintf("%s#%s",
+              (*(As **) (xbt_dynar_get_ptr(path_src, max)))->name_,
+              (*(As **) (xbt_dynar_get_ptr(path_dst, i)))->name_);
+          if (bypassRoutes_->find(route_name) != bypassRoutes_->end())
+            bypassedRoute = bypassRoutes_->at(route_name);
+          xbt_free(route_name);
+        }
+        if (bypassedRoute)
+          break;
+      }
+
+      if (bypassedRoute)
+        break;
+
+      if (max <= max_index_src && max <= max_index_dst) {
+        char *route_name = bprintf("%s#%s",
+            (*(As **) (xbt_dynar_get_ptr(path_src, max)))->name_,
+            (*(As **) (xbt_dynar_get_ptr(path_dst, max)))->name_);
+
+        if (bypassRoutes_->find(route_name) != bypassRoutes_->end())
+          bypassedRoute = bypassRoutes_->at(route_name);
+        xbt_free(route_name);
+      }
+      if (bypassedRoute)
+        break;
+    }
+
+    xbt_dynar_free(&path_src);
+    xbt_dynar_free(&path_dst);
+
+    return bypassedRoute;
+  }
+
+  void As::addBypassRoute(sg_platf_route_cbarg_t e_route){
+    const char *src = e_route->src;
+    const char *dst = e_route->dst;
+
+    if(bypassRoutes_ == nullptr)
+      bypassRoutes_ = new std::map<std::string, std::vector<Link*>*>();
+
+    char *route_name = bprintf("%s#%s", src, dst);
+
+    /* Argument validity checks */
+    if (e_route->gw_dst) {
+      XBT_DEBUG("Load bypassASroute from %s@%s to %s@%s",
+          src, e_route->gw_src->name(), dst, e_route->gw_dst->name());
+      xbt_assert(!xbt_dynar_is_empty(e_route->link_list), "Bypass route between %s@%s and %s@%s cannot be empty.",
+          src, e_route->gw_src->name(), dst, e_route->gw_dst->name());
+      xbt_assert(bypassRoutes_->find(route_name) == bypassRoutes_->end(),
+          "The bypass route between %s@%s and %s@%s already exists.",
+          src, e_route->gw_src->name(), dst, e_route->gw_dst->name());
+    } else {
+      XBT_DEBUG("Load bypassRoute from %s to %s", src, dst);
+      xbt_assert(!xbt_dynar_is_empty(e_route->link_list),                 "Bypass route between %s and %s cannot be empty.",    src, dst);
+      xbt_assert(bypassRoutes_->find(route_name) == bypassRoutes_->end(), "The bypass route between %s and %s already exists.", src, dst);
+    }
+
+    /* Build the value that will be stored in the dict */
+    std::vector<Link*> *newRoute = new std::vector<Link*>();
+    char *linkName;
+    unsigned int cpt;
+    xbt_dynar_foreach(e_route->link_list, cpt, linkName) {
+      Link *link = Link::byName(linkName);
+      if (link)
+        newRoute->push_back(link);
+      else
+        THROWF(mismatch_error, 0, "Link '%s' not found", linkName);
+    }
+
+    /* Store it */
+    bypassRoutes_->insert({route_name, newRoute});
+    xbt_free(route_name);
   }
 
 }} // namespace simgrid::surf
@@ -94,10 +239,10 @@ int ROUTING_PROP_ASR_LEVEL;     //Where the properties are stored
 simgrid::surf::NetCard *sg_netcard_by_name_or_null(const char *name)
 {
   sg_host_t h = sg_host_by_name(name);
-  simgrid::surf::NetCard *net_elm = h==NULL?NULL: h->pimpl_netcard;
-  if (!net_elm)
-    net_elm = (simgrid::surf::NetCard*) xbt_lib_get_or_null(as_router_lib, name, ROUTING_ASR_LEVEL);
-  return net_elm;
+  simgrid::surf::NetCard *netcard = h==NULL ? NULL: h->pimpl_netcard;
+  if (!netcard)
+    netcard = (simgrid::surf::NetCard*) xbt_lib_get_or_null(as_router_lib, name, ROUTING_ASR_LEVEL);
+  return netcard;
 }
 
 /* Global vars */
@@ -166,7 +311,7 @@ void routing_AS_begin(sg_platf_AS_cbarg_t AS)
 {
   XBT_DEBUG("routing_AS_begin");
 
-  xbt_assert(NULL == xbt_lib_get_or_null(as_router_lib, AS->id, ROUTING_ASR_LEVEL),
+  xbt_assert(nullptr == xbt_lib_get_or_null(as_router_lib, AS->id, ROUTING_ASR_LEVEL),
       "Refusing to create a second AS called \"%s\".", AS->id);
 
   _sg_cfg_init_status = 2; /* HACK: direct access to the global controlling the level of configuration to prevent
@@ -214,8 +359,7 @@ void routing_AS_begin(sg_platf_AS_cbarg_t AS)
     THROWF(arg_error, 0, "All defined components must belong to a AS");
   }
 
-  xbt_lib_set(as_router_lib, netcard->name(), ROUTING_ASR_LEVEL,
-              (void *) netcard);
+  xbt_lib_set(as_router_lib, netcard->name(), ROUTING_ASR_LEVEL, (void *) netcard);
   XBT_DEBUG("Having set name '%s' id '%d'", new_as->name_, netcard->id());
 
   /* set the new current component of the tree */
@@ -316,8 +460,6 @@ static void elements_father(sg_netcard_t src, sg_netcard_t dst,
  * \param dst the destination host name
  * \param *route the route where the links are stored. It is either NULL or a ready to use dynar
  * \param *latency the latency, if needed
- *
- * This function is called by "get_route" and "get_latency". It allows to walk recursively through the ASes tree.
  */
 static void _get_route_and_latency(simgrid::surf::NetCard *src, simgrid::surf::NetCard *dst,
   xbt_dynar_t * links, double *latency)
@@ -335,10 +477,13 @@ static void _get_route_and_latency(simgrid::surf::NetCard *src, simgrid::surf::N
       common_father->name_, src_father->name_, dst_father->name_);
 
   /* Check whether a direct bypass is defined. If so, use it and bail out */
-  sg_platf_route_cbarg_t bypassed_route = common_father->getBypassRoute(src, dst, latency);
-  if (bypassed_route) {
-    xbt_dynar_merge(links, &bypassed_route->link_list);
-    routing_route_free(bypassed_route);
+  std::vector<Link*> *bypassed_route = common_father->getBypassRoute(src, dst);
+  if (nullptr != bypassed_route) {
+    for (Link *link : *bypassed_route) {
+      xbt_dynar_push(*links,&link);
+      if (latency)
+        *latency += link->getLatency();
+    }
     return;
   }
 
@@ -368,14 +513,6 @@ static void _get_route_and_latency(simgrid::surf::NetCard *src, simgrid::surf::N
 
 }
 
-AS_t surf_platf_get_root(routing_platf_t platf){
-  return platf->root_;
-}
-
-e_surf_network_element_type_t surf_routing_edge_get_rc_type(sg_netcard_t netcard){
-  return netcard->getRcType();
-}
-
 namespace simgrid {
 namespace surf {
 
@@ -432,15 +569,6 @@ xbt_dynar_t RoutingPlatf::getOneLinkRoutes(){
 }
 }
 
-e_surf_network_element_type_t routing_get_network_element_type(const char *name)
-{
-  simgrid::surf::NetCard *rc = sg_netcard_by_name_or_null(name);
-  if (rc)
-    return rc->getRcType();
-
-  return SURF_NETWORK_ELEMENT_NULL;
-}
-
 /** @brief create the root AS */
 void routing_model_create( void *loopback)
 {