Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of framagit.org:Adrien.Gougeon/simgrid into master
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Sat, 26 Sep 2020 19:56:02 +0000 (21:56 +0200)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Sat, 26 Sep 2020 19:56:02 +0000 (21:56 +0200)
1  2 
CMakeLists.txt
NEWS
docs/source/ns3.rst
src/surf/network_ns3.cpp
src/surf/ns3/ns3_simulator.hpp

diff --combined CMakeLists.txt
@@@ -179,7 -179,7 +179,7 @@@ if(WIN32
    unset(CMAKE_INCLUDE_WIN)
  endif()
  
 -# library dependency cannot start with a space (CMP0004), so initialize it with something that is never desactivated.
 +# library dependency cannot start with a space (CMP0004), so initialize it with something that is never deactivated.
  set(SIMGRID_DEP "-lm") 
  
  ### Determine the assembly flavor that we need today
@@@ -230,7 -230,7 +230,7 @@@ if(enable_ns3
    include(FindNS3)
    if (SIMGRID_HAVE_NS3)
      set(SIMGRID_HAVE_NS3 1)
-     foreach(lib core csma point-to-point internet network applications)
+     foreach(lib core csma point-to-point internet network applications wifi)
        set(SIMGRID_DEP "${SIMGRID_DEP} -lns${NS3_VERSION}-${lib}${NS3_SUFFIX}")
      endforeach()
    else()
@@@ -555,10 -555,10 +555,10 @@@ file(READ ${CMAKE_HOME_DIRECTORY}/src/s
  
  ### SMPI script used when simgrid is installed
  set(exec_prefix ${CMAKE_INSTALL_PREFIX})
 -set(includeflag "-I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR} -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/smpi")
  set(includedir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
  set(libdir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
 -set(CMAKE_SMPI_COMMAND "export LD_LIBRARY_PATH=\"${CMAKE_INSTALL_LIBDIR}")
 +set(includeflag "-I${includedir} -I${includedir}/smpi")
 +set(CMAKE_SMPI_COMMAND "export LD_LIBRARY_PATH=\"${libdir}")
  if(NS3_LIBRARY_PATH)
    set(CMAKE_SMPI_COMMAND "${CMAKE_SMPI_COMMAND}:${NS3_LIBRARY_PATH}")
  endif()
@@@ -583,17 -583,17 +583,17 @@@ endforeach(
  
  ### SMPI scripts used when compiling simgrid 
  set(exec_prefix "${CMAKE_BINARY_DIR}/smpi_script/")
 -set(includeflag "-I${CMAKE_HOME_DIRECTORY}/include -I${CMAKE_HOME_DIRECTORY}/include/smpi")
 -set(includeflag "${includeflag} -I${CMAKE_BINARY_DIR}/include -I${CMAKE_BINARY_DIR}/include/smpi")
  set(includedir "${CMAKE_HOME_DIRECTORY}/include")
  set(libdir "${CMAKE_BINARY_DIR}/lib")
 -set(CMAKE_SMPI_COMMAND "export LD_LIBRARY_PATH=\"${CMAKE_BINARY_DIR}/lib")
 +set(includeflag "-I${includedir} -I${includedir}/smpi")
 +set(includeflag "${includeflag} -I${CMAKE_BINARY_DIR}/include -I${CMAKE_BINARY_DIR}/include/smpi")
 +set(CMAKE_SMPI_COMMAND "export LD_LIBRARY_PATH=\"${libdir}")
  if(NS3_LIBRARY_PATH)
    set(CMAKE_SMPI_COMMAND "${CMAKE_SMPI_COMMAND}:${NS3_LIBRARY_PATH}")
  endif()
  set(CMAKE_SMPI_COMMAND "${CMAKE_SMPI_COMMAND}\${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}\"")
 -set(SMPIMAIN ${CMAKE_BINARY_DIR}/lib/simgrid/smpimain)
 -set(SMPIREPLAYMAIN ${CMAKE_BINARY_DIR}/lib/simgrid/smpireplaymain)
 +set(SMPIMAIN ${libdir}/simgrid/smpimain)
 +set(SMPIREPLAYMAIN ${libdir}/simgrid/smpireplaymain)
  
  foreach(script cc cxx ff f90 run)
    configure_file(${CMAKE_HOME_DIRECTORY}/src/smpi/smpi${script}.in ${CMAKE_BINARY_DIR}/smpi_script/bin/smpi${script} @ONLY)
diff --combined NEWS
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -5,6 -5,6 +5,7 @@@ __   _____ _ __ ___(_) ___  _ __   |__
    \_/ \___|_|  |___/_|\___/|_| |_| |____(_)_____|\___/
                 (unreleased)
  
++ * SMPI: improved support of the proxy apps (including those using petsc)
                      _               _____  ____  ____
  __   _____ _ __ ___(_) ___  _ __   |___ / |___ \| ___|
  \ \ / / _ \ '__/ __| |/ _ \| '_ \    |_ \   __) |___ \
diff --combined docs/source/ns3.rst
@@@ -18,14 -18,27 +18,14 @@@ SimGrid requires ns-3 version 3.26 or h
  recent version of both SimGrid and ns-3. While the Debian package of SimGrid
  don't have the ns-3 bindings activated, you can still use the packaged version
  of ns-3 by grabbing the ``libns3-dev ns3`` packages. Alternatively, you can
 -install ns-3 from scratch as follows:
 -
 -.. code-block:: shell
 -
 -  # Download the source
 -  wget http://www.nsnam.org/release/ns-allinone-3.29.tar.bz2
 -  tar -xf ns-allinone-3.29.tar.bz2
 -  cd ns-allinone-3.29/ns-3.29/
 -  # Configure, build and install
 -  ./waf configure --prefix="/opt/ns3" # or give another path if you prefer
 -  ./waf
 -  ./waf install
 -
 -For more information, please refer to the ns-3 documentation
 -(`official website <http://www.nsnam.org>`_).
 +install ns-3 from scratch (see the `ns-3 documentation <http://www.nsnam.org>`_).
  
  Enabling ns-3 in SimGrid
  ========================
  
  SimGrid must be recompiled with the ``enable_ns3`` option activated in cmake.
 -Optionally, use ``NS3_HINT`` to hint cmake about where to find ns-3.
 +Optionally, use ``NS3_HINT`` to tell cmake where ns3 is installed on
 +your disk.
  
  .. code-block:: shell
  
@@@ -56,10 -69,9 +56,11 @@@ version of either SimGrid or ns-3, try 
  Using ns-3 from SimGrid
  ***********************
  
--The SimGrid/ns-3 binding only contains features that are common to both
- systems: ns-3 wireless models are not available, while SimGrid routes
- cannot be longer than 1. Also, the platform built in ns-3 from the
 -systems. Also, the platform built in ns-3 from the
--SimGrid description is very basic.
++The SimGrid/ns-3 binding only contains features that are common to
++both systems. Not all ns-3 models are available (only the TCP and wifi
++ones are), while not all SimGrid platform file can be used with ns-3
++(routes must be of length 1). Also, the platform built in ns-3 from
++the SimGrid description is very basic.
  
  Platform files compatibility
  ============================
  Any route longer than one will be ignored when using ns-3. They are
  harmless, but you still need to connect your hosts using one-hop routes.
  The best solution is to add routers to split your route. Here is an
 -example of invalid platform:
 +example of an invalid platform:
  
  .. code-block:: shell
  
-    <platform>
-      <zone id="zone0" routing="Full">
 -      <?xml version='1.0'?><!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd">
 -      <platform version="4.1">
 -              <AS id="AS0" routing="Floyd">
 -
 -                      <host id="alice" speed="1Gf" />
 -                      <host id="bob"   speed="1Gf" />
 -      
 -                      <link id="l1" bandwidth="1Mbps" latency="5ms" />
 -                      <link id="l2" bandwidth="1Mbps" latency="5ms" />
 -      
 -                      <route src="alice" dst="bob">
 -                              <link_ctn id="l1"/>            <!-- !!!! INVALID WITH ns-3    !!!! -->
 -                              <link_ctn id="l2"/>            <!-- !!!! length=2 IS TOO MUCH !!!! -->
 -                      </route>
 -              </AS>
 -      </platform>
 -
++   <?xml version='1.0'?>
++   <!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
++   <platform version="4.1">
++     <zone id="zone0" routing="Floyd">
 +       <host id="alice" speed="1Gf" />
 +       <host id="bob"   speed="1Gf" />
 +  
-        <link id="l1" bw="1Mbps" />
-        <link id="l2" bw="1Mbps" />
++       <link id="l1" bandwidth="1Mbps" latency="5ms" />
++       <link id="l2" bandwidth="1Mbps" latency="5ms" />
 +
 +       <route src="alice" dst="bob">
 +         <link_ctn id="l1"/>            <!-- !!!! INVALID WITH ns-3    !!!! -->
 +         <link_ctn id="l2"/>            <!-- !!!! length=2 IS TOO MUCH !!!! -->
 +       </route>
 +     </zone>
 +   </platform>
 +  
  This can be reformulated as follows to make it usable with the ns-3 binding.
  There is no direct connection from alice to bob, but that's OK because
  ns-3 automatically routes from point to point.
  
  .. code-block:: shell
  
-    <platform>
 -      <?xml version='1.0'?><!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd">
 -      <platform version="4.1">
 -              <AS id="AS0" routing="Floyd">
++   <?xml version='1.0'?>
++   <!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
++   <platform version="4.1">
 +     <zone id="zone0" routing="Full">
 +       <host id="alice" speed="1Gf" />
 +       <host id="bob"   speed="1Gf" />
  
 -                      <host id="alice" speed="1Gf"/>
 -                      <host id="bob"   speed="1Gf"/>
 +       <router id="r1" /> <!-- routers are compute-less hosts -->
  
-        <link id="l1" bw="1Mbps" />
-        <link id="l2" bw="1Mbps" />
 -                      <router id="r1"/>       <!-- routers are compute-less hosts -->
++       <link id="l1" bandwidth="1Mbps" latency="5ms"/>
++       <link id="l2" bandwidth="1Mbps" latency="5ms"/>
  
 -                      <link id="l1" bandwidth="1Mbps" latency="5ms"/>
 -                      <link id="l2" bandwidth="1Mbps" latency="5ms"/>
 -
 -                      <route src="alice" dst="r1">
 -                              <link_ctn id="l1"/> 
 -                      </route>
 -
 -                      <route src="r1" dst="bob">
 -                              <link_ctn id="l2"/> 
 -                      </route>
 -              </AS>
 -      </platform>
 +       <route src="alice" dst="r1">
 +         <link_ctn id="l1"/> 
 +       </route>
 +  
 +       <route src="r1" dst="bob">
 +         <link_ctn id="l2"/> 
 +       </route>
 +     </zone>
 +   </platform>
  
  Once your platform is OK, just change the :ref:`network/model
- <options_model_select>` configuration option to "ns-3" as follows. The rest
+ <options_model_select>`_ configuration option to "ns-3" as follows. The rest
  is unchanged.
  
  .. code-block:: shell
     ./network-ns3 --cfg=network/model:ns-3 (other parameters)
  
  Many other files from the ``examples/platform directory`` are usable with the
 -ns-3 model.
 +ns-3 model, such as `examples/platforms/dogbone.xml <https://framagit.org/simgrid/simgrid/tree/master/examples/platforms/dogbone.xml>`_.
 +Check the file  `examples/s4u/network-ns3/network-ns3.tesh <https://framagit.org/simgrid/simgrid/tree/master/examples/s4u/network-ns3/network-ns3.tesh>`_
 +to see which ones are used in our regression tests.
  
 -between two simgrid hosts.
+ Build a wifi-compatible platform
+ ===================================
+ We describe here a simple platform allowing ns3 wifi communication
 -      <?xml version='1.0'?><!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd">
++between two SimGrid hosts.
+ First, here are the mandatory information necessary to create a
+ simgrid platform:
+ .. code-block:: shell
 -              <AS id="AS0" routing="Floyd">
++      <?xml version='1.0'?>
++      <!DOCTYPE platform SYSTEM "http://simgrid.org/simgrid.dtd">
+       <platform version="4.1">
 -.. code-block:: shell``
++              <zone id="zone" routing="Floyd">
+ Then, we create our access point and station hosts:
+ .. code-block:: shell
+                       <host id="alice" speed="1Gf"/>
+                       <host id="bob"   speed="1Gf"/>
+ We must specify that alice will be our access point. To do that we
+ simply add the property ``wifi_link`` to the host ``alice``: 
+ .. code-block:: shell
+                       <host id="alice" speed="1Gf">
+                               <prop id="wifi_link" value="net0"/>
+                       </host>
+                       <host id="bob"   speed="1Gf"/>
+ The value ``net0`` of this property defines the name of the wifi network
+ generated. To generate this wifi network we create a wifi link:
 -              </AS>
++.. code-block:: shell
+                       <link id="net0" bandwidth="0" latency="0" sharing_policy="WIFI"/>
+ The important information here are:
+       * The id of the link, ``net0``, must match the network name defined by the property ``wifi_link`` of the access point node
+       * The sharing policy must be set to ``WIFI``
+ Note: bandwidth and latency are mandatory by simgrid to create a link but are NOT used to create a wifi network. Instead the
+ wifi network capabilities are defined by its MCS, NSS and distance from access point to station. Those properties are described in section :ref:`Optional access point node properties <optional_prop>`_
+ To connect the station node to the access point node, we
+ create a route between the hosts:
+ .. code-block:: shell
+                       <route src="alice" dst="bob">
+                               <link_ctn id="net0" />
+                       </route>
+ Finally, we end the xml file with the missing closing tags:
+ .. code-block:: shell
++              </zone>
+       </platform>
+ .. _optional_prop:
+ Optional access point node properties
+ --------------------------------------
+ The MCS (`Modulation and Coding Scheme <https://en.wikipedia.org/wiki/Link_adaptation>`_) can be set with the property ``wifi_mcs``:
+ .. code-block:: shell
+                        <host id="alice" speed="1Gf">
+                               <prop id="wifi_link" value="net0"/>
+                               <prop id="wifi_mcs" value="5"/>
+                       </host>
+ Its default value is 3.
+ The NSS (Number of Spatial Streams, also known as the `number of antennas <https://en.wikipedia.org/wiki/IEEE_802.11n-2009#Number_of_antennas>`_) can be set with the property ``wifi_nss``:
+ .. code-block:: shell
+                       <host id="alice" speed="1Gf">
+                               <prop id="wifi_link" value="net0"/>
+                               <prop id="wifi_nss" value="2"/>
+                       </host>
+                       
+ Its default value is 1.
+ Note: not all value of MCS and NSS are valid nor compatible. Check `802.11n standard <https://en.wikipedia.org/wiki/IEEE_802.11n-2009#Data_rates>`_ for more information.
+ Optional station node properties
+ ---------------------------------
+ The distance in meter at which the station is placed from the access point can
+ be set with the property ``wifi_distance``.
+ .. code-block:: shell
+                       <host id="alice" speed="100.0Mf,50.0Mf,20.0Mf" pstate="0">
+                               <prop id="wifi_distance" value="30" />
+                       </host>
+ Its default value is 10. 
  Limitations
  ===========
  
  A ns-3 platform is automatically created from the provided SimGrid
  platform. However, there are some known caveats:
  
-   * The default values (e.g., TCP parameters) are the ns-3 default values.
-   * ns-3 networks are routed using the shortest path algorithm, using
-     ``ns3::Ipv4GlobalRoutingHelper::PopulateRoutingTables``.
-   * End hosts cannot have more than one interface card. So, your
-     SimGrid hosts should be connected to the platform through only
-     one link. Otherwise, your SimGrid host will be considered as a
-     router.
+       * The default values (e.g., TCP parameters) are the ns-3 default values.
+       * ns-3 networks are routed using the shortest path algorithm, using
+               ``ns3::Ipv4GlobalRoutingHelper::PopulateRoutingTables``.
 -
++        * End hosts cannot have more than one interface card. So, your
++          SimGrid hosts should be connected to the platform through only
++          one link. Otherwise, your SimGrid host will be considered as a
++          router (FIXME: is it still true?).
++           
  Our goal is to keep the ns-3 plugin of SimGrid as easy (and hopefully readable)
  as possible. If the current state does not fit your needs, you should modify
  this plugin, and/or create your own plugin from the existing one. If you come up
diff --combined src/surf/network_ns3.cpp
@@@ -20,6 -20,9 +20,9 @@@
  #include <ns3/application-container.h>
  #include <ns3/event-id.h>
  
 -#include "ns3/wifi-module.h"
+ #include "ns3/mobility-module.h"
++#include "ns3/wifi-module.h"
  #include "network_ns3.hpp"
  #include "ns3/ns3_simulator.hpp"
  
@@@ -34,6 -37,9 +37,6 @@@
  
  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ns3, surf, "Logging specific to the SURF network ns-3 module");
  
 -std::vector<std::string> IPV4addr;
 -static std::string transformIpv4Address(ns3::Ipv4Address from);
 -
  /*****************
   * Crude globals *
   *****************/
@@@ -42,61 -48,97 +45,127 @@@ extern std::map<std::string, SgFlow*> f
  extern std::map<std::string, ns3::ApplicationContainer> sink_from_sock;
  
  static ns3::InternetStackHelper stack;
 -static ns3::NodeContainer nodes;
 -static ns3::NodeContainer Cluster_nodes;
 -static ns3::Ipv4InterfaceContainer interfaces;
  
 -static int number_of_nodes = 0;
 -static int number_of_clusters_nodes = 0;
  static int number_of_links = 1;
  static int number_of_networks = 1;
  
 -static ns3::YansWifiPhyHelper wifiPhy = ns3::YansWifiPhyHelper::Default ();
 -static ns3::YansWifiChannelHelper wifiChannel = ns3::YansWifiChannelHelper::Default ();
+ /* wifi globals */
+ static ns3::WifiHelper wifi;
++static ns3::YansWifiPhyHelper wifiPhy         = ns3::YansWifiPhyHelper::Default();
++static ns3::YansWifiChannelHelper wifiChannel = ns3::YansWifiChannelHelper::Default();
+ static ns3::WifiMacHelper wifiMac;
+ static ns3::MobilityHelper mobility;
  simgrid::xbt::Extension<simgrid::kernel::routing::NetPoint, NetPointNs3> NetPointNs3::EXTENSION_ID;
  
++static std::string transformIpv4Address(ns3::Ipv4Address from)
++{
++  std::stringstream sstream;
++  sstream << from;
++  return sstream.str();
++}
++
  NetPointNs3::NetPointNs3() : ns3_node_(ns3::CreateObject<ns3::Node>(0))
  {
    stack.Install(ns3_node_);
 -  nodes.Add(ns3_node_);
 -  node_num = number_of_nodes++;
  }
  
 -                   ns3::Ptr<ns3::YansWifiChannel> channel_, int mcs_, int nss_, int network_, int link_) :
 -    name(name_), host(host_), ap_node(ap_node_), channel(channel_), mcs(mcs_), nss(nss_),
 -    network(network_), link(link_) {
 -    n_sta_nodes = 0;
 -    wifi_zones[name_] = this;
+ WifiZone::WifiZone(std::string name_, simgrid::s4u::Host* host_, ns3::Ptr<ns3::Node> ap_node_,
 -bool WifiZone::is_ap(ns3::Ptr<ns3::Node> node){
 -    for (std::pair<std::string, WifiZone*> zone : wifi_zones)
 -        if (zone.second->get_ap_node() == node)
 -            return true;
 -    return false;
++                   ns3::Ptr<ns3::YansWifiChannel> channel_, int mcs_, int nss_, int network_, int link_)
++    : name(name_)
++    , host(host_)
++    , ap_node(ap_node_)
++    , channel(channel_)
++    , mcs(mcs_)
++    , nss(nss_)
++    , network(network_)
++    , link(link_)
++{
++  n_sta_nodes       = 0;
++  wifi_zones[name_] = this;
+ }
 -WifiZone* WifiZone::by_name(std::string name) {
 -    WifiZone* zone;
 -    try {
 -        zone = wifi_zones.at(name);
 -    }
 -    catch (const std::out_of_range& oor) {
 -        return nullptr;
 -    }
 -    return zone;
++bool WifiZone::is_ap(ns3::Ptr<ns3::Node> node)
++{
++  for (std::pair<std::string, WifiZone*> zone : wifi_zones)
++    if (zone.second->get_ap_node() == node)
++      return true;
++  return false;
+ }
 -static void initialize_ns3_wifi() {
 -    wifi.SetStandard (ns3::WIFI_PHY_STANDARD_80211n_5GHZ);
++WifiZone* WifiZone::by_name(std::string name)
++{
++  WifiZone* zone;
++  try {
++    zone = wifi_zones.at(name);
++  } catch (const std::out_of_range& oor) {
++    return nullptr;
++  }
++  return zone;
+ }
+ std::unordered_map<std::string, WifiZone*> WifiZone::wifi_zones;
 -    for (auto host : simgrid::s4u::Engine::get_instance()->get_all_hosts()) {
 -        const char* wifi_link = host->get_property("wifi_link");
 -        const char* wifi_mcs = host->get_property("wifi_mcs");
 -        const char* wifi_nss = host->get_property("wifi_nss");
++static void initialize_ns3_wifi()
++{
++  wifi.SetStandard(ns3::WIFI_PHY_STANDARD_80211n_5GHZ);
 -        if (wifi_link)
 -          new WifiZone(wifi_link, host, host->get_netpoint()->extension<NetPointNs3>()->ns3_node_,
 -                       wifiChannel.Create (), wifi_mcs ? atoi(wifi_mcs) : 3, wifi_nss ? atoi(wifi_nss) : 1, 0, 0);
 -    }
++  for (auto host : simgrid::s4u::Engine::get_instance()->get_all_hosts()) {
++    const char* wifi_link = host->get_property("wifi_link");
++    const char* wifi_mcs  = host->get_property("wifi_mcs");
++    const char* wifi_nss  = host->get_property("wifi_nss");
++    if (wifi_link)
++      new WifiZone(wifi_link, host, host->get_netpoint()->extension<NetPointNs3>()->ns3_node_, wifiChannel.Create(),
++                   wifi_mcs ? atoi(wifi_mcs) : 3, wifi_nss ? atoi(wifi_nss) : 1, 0, 0);
++  }
+ }
  /*************
   * Callbacks *
   *************/
  
  static void clusterCreation_cb(simgrid::kernel::routing::ClusterCreationArgs const& cluster)
  {
 -  for (int const& i : *cluster.radicals) {
 -    // Routers don't create a router on the other end of the private link by themselves.
 -    // We just need this router to be given an ID so we create a temporary NetPointNS3 so that it gets one
 -    auto* host_dst = new NetPointNs3();
 +  ns3::NodeContainer Nodes;
  
 +  for (int const& i : *cluster.radicals) {
      // Create private link
      std::string host_id = cluster.prefix + std::to_string(i) + cluster.suffix;
 -    auto* host_src      = simgrid::s4u::Host::by_name(host_id)->get_netpoint()->extension<NetPointNs3>();
 -    xbt_assert(host_src, "Cannot find a ns-3 host of name %s", host_id.c_str());
 +    auto* src           = simgrid::s4u::Host::by_name(host_id)->get_netpoint();
 +    auto* dst           = simgrid::s4u::Engine::get_instance()->netpoint_by_name_or_null(cluster.router_id);
 +    xbt_assert(dst != nullptr, "No router named %s", cluster.router_id.c_str());
  
-     ns3_add_direct_route(src, dst, cluster.bw, cluster.lat, cluster.sharing_policy); // Any ns-3 route is symmetrical
 -    // Any ns-3 route is symmetrical
 -    ns3_add_direct_route(host_src, host_dst, cluster.bw, cluster.lat, cluster.id, cluster.sharing_policy);
++    ns3_add_direct_route(src, dst, cluster.bw, cluster.lat, cluster.id,
++                         cluster.sharing_policy); // Any ns-3 route is symmetrical
  
 -    delete host_dst;
 +    // Also add the host to the list of hosts that will be connected to the backbone
 +    Nodes.Add(src->extension<NetPointNs3>()->ns3_node_);
    }
  
 -  //Create link backbone
 -  ns3_add_cluster(cluster.id.c_str(), cluster.bb_bw, cluster.bb_lat);
 +  // Create link backbone
 +
 +  xbt_assert(Nodes.GetN() <= 65000, "Cluster with ns-3 is limited to 65000 nodes");
 +  ns3::CsmaHelper csma;
 +  csma.SetChannelAttribute("DataRate",
 +                           ns3::DataRateValue(ns3::DataRate(cluster.bb_bw * 8))); // ns-3 takes bps, but we provide Bps
 +  csma.SetChannelAttribute("Delay", ns3::TimeValue(ns3::Seconds(cluster.bb_lat)));
 +  ns3::NetDeviceContainer devices = csma.Install(Nodes);
 +  XBT_DEBUG("Create CSMA");
 +
 +  std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
 +  XBT_DEBUG("Assign IP Addresses %s to CSMA.", addr.c_str());
 +  ns3::Ipv4AddressHelper ipv4;
 +  ipv4.SetBase(addr.c_str(), "255.255.0.0");
 +  ipv4.Assign(devices);
 +
 +  if (number_of_links == 255) {
 +    xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
 +    number_of_links = 1;
 +    number_of_networks++;
 +  } else {
 +    number_of_links++;
 +  }
  }
  
  static void routeCreation_cb(bool symmetrical, simgrid::kernel::routing::NetPoint* src,
      //   XBT_DEBUG("src (%s), dst (%s), src_id = %d, dst_id = %d",src,dst, src_id, dst_id);
      XBT_DEBUG("\tLink (%s) bw:%fbps lat:%fs", link->get_cname(), link->get_bandwidth(), link->get_latency());
  
-     ns3_add_direct_route(src, dst, link->get_bandwidth(), link->get_latency(), link->get_sharing_policy());
 -    // create link ns3
 -    auto* host_src = src->extension<NetPointNs3>();
 -    auto* host_dst = dst->extension<NetPointNs3>();
 -
 -    host_src->set_name(src->get_name());
 -    host_dst->set_name(dst->get_name());
 -
 -    xbt_assert(host_src != nullptr, "Network element %s does not seem to be ns-3-ready", src->get_cname());
 -    xbt_assert(host_dst != nullptr, "Network element %s does not seem to be ns-3-ready", dst->get_cname());
 -
 -    ns3_add_direct_route(host_src, host_dst, link->get_bandwidth(), link->get_latency(), link->get_name(), link->get_sharing_policy());
++    ns3_add_direct_route(src, dst, link->get_bandwidth(), link->get_latency(), link->get_name(),
++                         link->get_sharing_policy());
    } else {
      static bool warned_about_long_routes = false;
  
    }
  }
  
 -/* Create the ns3 topology based on routing strategy */
 -static void postparse_cb()
 -{
 -  IPV4addr.shrink_to_fit();
 -  ns3::GlobalRouteManager::BuildGlobalRoutingDatabase();
 -  ns3::GlobalRouteManager::InitializeRoutes();
 -}
 -
  /*********
   * Model *
   *********/
@@@ -155,36 -215,22 +225,36 @@@ NetworkNS3Model::NetworkNS3Model() : Ne
  
    NetPointNs3::EXTENSION_ID = routing::NetPoint::extension_create<NetPointNs3>();
  
 -  ns3_initialize(ns3_tcp_model.get());
 +  ns3::Config::SetDefault("ns3::TcpSocket::SegmentSize", ns3::UintegerValue(1000));
 +  ns3::Config::SetDefault("ns3::TcpSocket::DelAckCount", ns3::UintegerValue(1));
 +  ns3::Config::SetDefault("ns3::TcpSocketBase::Timestamp", ns3::BooleanValue(false));
 +
 +  auto TcpProtocol = ns3_tcp_model.get();
 +  if (TcpProtocol == "default") {
 +    /* nothing to do */
 +
 +  } else if (TcpProtocol == "Reno" || TcpProtocol == "NewReno" || TcpProtocol == "Tahoe") {
 +    XBT_INFO("Switching Tcp protocol to '%s'", TcpProtocol.c_str());
 +    ns3::Config::SetDefault("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::Tcp" + TcpProtocol));
 +
 +  } else {
 +    xbt_die("The ns3/TcpModel must be: NewReno or Reno or Tahoe");
 +  }
  
    routing::NetPoint::on_creation.connect([](routing::NetPoint& pt) {
      pt.extension_set<NetPointNs3>(new NetPointNs3());
 -    XBT_VERB("SimGrid's %s is known as node %d within ns-3", pt.get_cname(), pt.extension<NetPointNs3>()->node_num);
 +    XBT_VERB("Declare SimGrid's %s within ns-3", pt.get_cname());
    });
 -  routing::on_cluster_creation.connect(&clusterCreation_cb);
  
 -  s4u::Engine::on_platform_created.connect(&postparse_cb);
 +  s4u::Engine::on_platform_created.connect([]() {
 +    /* Create the ns3 topology based on routing strategy */
 +    ns3::GlobalRouteManager::BuildGlobalRoutingDatabase();
 +    ns3::GlobalRouteManager::InitializeRoutes();
 +  });
 +  routing::on_cluster_creation.connect(&clusterCreation_cb);
    s4u::NetZone::on_route_creation.connect(&routeCreation_cb);
  }
  
 -NetworkNS3Model::~NetworkNS3Model() {
 -  IPV4addr.clear();
 -}
 -
  LinkImpl* NetworkNS3Model::create_link(const std::string& name, const std::vector<double>& bandwidths, double latency,
                                         s4u::Link::SharingPolicy policy)
  {
@@@ -214,14 -260,14 +284,14 @@@ double NetworkNS3Model::next_occurring_
      return -1.0;
  
    XBT_DEBUG("doing a ns3 simulation for a duration of %f", now);
-   ns3_simulator(now);  
+   ns3_simulator(now);
    time_to_next_flow_completion = ns3::Simulator::Now().GetSeconds() - surf_get_clock();
    // NS-3 stops as soon as a flow ends,
    // but it does not process the other flows that may finish at the same (simulated) time.
    // If another flow ends at the same time, time_to_next_flow_completion = 0
    if(double_equals(time_to_next_flow_completion, 0, sg_surf_precision))
-     time_to_next_flow_completion = 0.0; 
-  
+     time_to_next_flow_completion = 0.0;
    XBT_DEBUG("min       : %f", now);
    XBT_DEBUG("ns3  time : %f", ns3::Simulator::Now().GetSeconds());
    XBT_DEBUG("surf time : %f", surf_get_clock());
@@@ -291,13 -337,64 +361,61 @@@ void NetworkNS3Model::update_actions_st
  
  LinkNS3::LinkNS3(NetworkNS3Model* model, const std::string& name, double bandwidth, double latency,
                   s4u::Link::SharingPolicy policy)
 -    : LinkImpl(model, name, nullptr)
 +    : LinkImpl(model, name, nullptr), sharing_policy_(policy)
  {
    bandwidth_.peak = bandwidth;
    latency_.peak   = latency;
 -  sharing_policy_ = policy;
 +
 +  /* If wifi, create the wifizone now. If not, don't do anything: the links will be created in routeCreate_cb */
  
 -      static bool wifi_init = false;
 -      if (!wifi_init) {
 -          initialize_ns3_wifi();
 -          wifi_init = true;
 -      }
 -
 -      ns3::NetDeviceContainer netA;
 -      WifiZone* zone = WifiZone::by_name(name);
 -      xbt_assert(zone != 0, "Link name '%s' does not match the 'wifi_link' property of a host.", name.c_str());
 -      NetPointNs3* netpoint_ns3 = zone->get_host()->get_netpoint()->extension<NetPointNs3>();     
 -
 -      wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
 -                                    "ControlMode", ns3::StringValue ("HtMcs0"),
 -                                    "DataMode", ns3::StringValue ("HtMcs" + std::to_string(zone->get_mcs())));
 -
 -      wifiPhy.SetChannel (zone->get_channel());
 -      wifiPhy.Set("Antennas", ns3::UintegerValue(zone->get_nss()));
 -      wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
 -      wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
 -
 -      wifiMac.SetType("ns3::ApWifiMac");
 -
 -      netA.Add(wifi.Install (wifiPhy, wifiMac, zone->get_ap_node()));
 -
 -      ns3::Ptr<ns3::ListPositionAllocator> positionAllocS = ns3::CreateObject<ns3::ListPositionAllocator> ();
 -      positionAllocS->Add(ns3::Vector(0, 0, 0));
 -      mobility.SetPositionAllocator(positionAllocS);
 -      mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
 -      mobility.Install(zone->get_ap_node());
 -
 -      ns3::Ipv4AddressHelper address;
 -      std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
 -      address.SetBase(addr.c_str(), "255.255.0.0");
 -      XBT_DEBUG("\tInterface stack '%s'", addr.c_str());
 -      interfaces.Add(address.Assign (netA));
 -      zone->set_network(number_of_networks);
 -      zone->set_link(number_of_links);
 -
 -      int nodeNum = netpoint_ns3->node_num;
 -      if (IPV4addr.size() <= (unsigned)nodeNum)
 -        IPV4addr.resize(nodeNum + 1);
 -      IPV4addr[nodeNum] = transformIpv4Address(interfaces.GetAddress(interfaces.GetN() - 1));
 -
 -      if (number_of_links == 255){
 -        xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
 -        number_of_links = 1;
 -        number_of_networks++;
 -      } else {
 -        number_of_links++;
 -      }
+   if (policy == simgrid::s4u::Link::SharingPolicy::WIFI) {
++    static bool wifi_init = false;
++    if (!wifi_init) {
++      initialize_ns3_wifi();
++      wifi_init = true;
++    }
++
++    ns3::NetDeviceContainer netA;
++    WifiZone* zone = WifiZone::by_name(name);
++    xbt_assert(zone != 0, "Link name '%s' does not match the 'wifi_link' property of a host.", name.c_str());
++    NetPointNs3* netpoint_ns3 = zone->get_host()->get_netpoint()->extension<NetPointNs3>();
++
++    wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", "ControlMode", ns3::StringValue("HtMcs0"), "DataMode",
++                                 ns3::StringValue("HtMcs" + std::to_string(zone->get_mcs())));
++
++    wifiPhy.SetChannel(zone->get_channel());
++    wifiPhy.Set("Antennas", ns3::UintegerValue(zone->get_nss()));
++    wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
++    wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
++
++    wifiMac.SetType("ns3::ApWifiMac");
++
++    netA.Add(wifi.Install(wifiPhy, wifiMac, zone->get_ap_node()));
++
++    ns3::Ptr<ns3::ListPositionAllocator> positionAllocS = ns3::CreateObject<ns3::ListPositionAllocator>();
++    positionAllocS->Add(ns3::Vector(0, 0, 0));
++    mobility.SetPositionAllocator(positionAllocS);
++    mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
++    mobility.Install(zone->get_ap_node());
++
++    ns3::Ipv4AddressHelper address;
++    std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
++    address.SetBase(addr.c_str(), "255.255.0.0");
++    XBT_DEBUG("\tInterface stack '%s'", addr.c_str());
++    auto addresses = address.Assign(netA);
++    zone->set_network(number_of_networks);
++    zone->set_link(number_of_links);
++
++    netpoint_ns3->ipv4_address_ = transformIpv4Address(addresses.GetAddress(addresses.GetN() - 1));
++
++    if (number_of_links == 255) {
++      xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
++      number_of_links = 1;
++      number_of_networks++;
++    } else {
++      number_of_links++;
++    }
+   }
    s4u::Link::on_creation(*this->get_iface());
  }
  
@@@ -335,15 -432,19 +453,15 @@@ NetworkNS3Action::NetworkNS3Action(Mode
  
    static int port_number = 1025; // Port number is limited from 1025 to 65 000
  
 -  unsigned int node1 = src->get_netpoint()->extension<NetPointNs3>()->node_num;
 -  unsigned int node2 = dst->get_netpoint()->extension<NetPointNs3>()->node_num;
 -
    ns3::Ptr<ns3::Node> src_node = src->get_netpoint()->extension<NetPointNs3>()->ns3_node_;
    ns3::Ptr<ns3::Node> dst_node = dst->get_netpoint()->extension<NetPointNs3>()->ns3_node_;
  
 -  xbt_assert(node2 < IPV4addr.size(), "Element %s is unknown to ns-3. Is it connected to any one-hop link?",
 -             dst->get_netpoint()->get_cname());
 -  std::string& addr = IPV4addr[node2];
 +  std::string& addr = dst->get_netpoint()->extension<NetPointNs3>()->ipv4_address_;
    xbt_assert(not addr.empty(), "Element %s is unknown to ns-3. Is it connected to any one-hop link?",
               dst->get_netpoint()->get_cname());
  
 -  XBT_DEBUG("ns3: Create flow of %.0f Bytes from %u to %u with Interface %s", totalBytes, node1, node2, addr.c_str());
 +  XBT_DEBUG("ns3: Create flow of %.0f Bytes from %s to %s with Interface %s", totalBytes, src->get_cname(),
 +            dst->get_cname(), addr.c_str());
    ns3::PacketSinkHelper sink("ns3::TcpSocketFactory", ns3::InetSocketAddress(ns3::Ipv4Address::GetAny(), port_number));
    ns3::ApplicationContainer apps = sink.Install(dst_node);
  
      port_number = 1025;
      XBT_WARN("Too many connections! Port number is saturated. Trying to use the oldest ports.");
    }
 -  xbt_assert(port_number <= 65000, "Too many connections! Port number is saturated.");
  
    s4u::Link::on_communicate(*this);
  }
@@@ -388,7 -490,7 +506,7 @@@ void NetworkNS3Action::update_remains_l
  
  void ns3_simulator(double maxSeconds)
  {
-   ns3::EventId id; 
+   ns3::EventId id;
    if (maxSeconds > 0.0) // If there is a maximum amount of time to run
      id = ns3::Simulator::Schedule(ns3::Seconds(maxSeconds), &ns3::Simulator::Stop);
  
      id.Cancel();
  }
  
 -// initialize the ns-3 interface and environment
 -void ns3_initialize(std::string TcpProtocol)
 -{
 -  //  tcpModel are:
 -  //  "ns3::TcpNewReno"
 -  //  "ns3::TcpReno"
 -  //  "ns3::TcpTahoe"
 -
 -  ns3::Config::SetDefault ("ns3::TcpSocket::SegmentSize", ns3::UintegerValue (1000));
 -  ns3::Config::SetDefault ("ns3::TcpSocket::DelAckCount", ns3::UintegerValue (1));
 -  ns3::Config::SetDefault ("ns3::TcpSocketBase::Timestamp", ns3::BooleanValue (false));
 -
 -  if (TcpProtocol == "default") {
 -    /* nothing to do */
 -
 -  } else if (TcpProtocol == "Reno") {
 -    XBT_INFO("Switching Tcp protocol to '%s'", TcpProtocol.c_str());
 -    ns3::Config::SetDefault ("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::TcpReno"));
 -
 -  } else if (TcpProtocol == "NewReno") {
 -    XBT_INFO("Switching Tcp protocol to '%s'", TcpProtocol.c_str());
 -    ns3::Config::SetDefault ("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::TcpNewReno"));
 -
 -  } else if (TcpProtocol == "Tahoe") {
 -    XBT_INFO("Switching Tcp protocol to '%s'", TcpProtocol.c_str());
 -    ns3::Config::SetDefault ("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::TcpTahoe"));
 -
 -  } else {
 -    xbt_die("The ns3/TcpModel must be: NewReno or Reno or Tahoe");
 -  }
 -}
 -
 -void ns3_add_cluster(const char* /*id*/, double bw, double lat)
 -{
 -  ns3::NodeContainer Nodes;
 -
 -  for (unsigned int i = number_of_clusters_nodes; i < Cluster_nodes.GetN(); i++) {
 -    Nodes.Add(Cluster_nodes.Get(i));
 -    XBT_DEBUG("Add node %u to cluster", i);
 -  }
 -  number_of_clusters_nodes = Cluster_nodes.GetN();
 -
 -  XBT_DEBUG("Add router %u to cluster", nodes.GetN() - Nodes.GetN() - 1);
 -  Nodes.Add(nodes.Get(nodes.GetN()-Nodes.GetN()-1));
 -
 -  xbt_assert(Nodes.GetN() <= 65000, "Cluster with ns-3 is limited to 65000 nodes");
 -  ns3::CsmaHelper csma;
 -  csma.SetChannelAttribute("DataRate", ns3::DataRateValue(ns3::DataRate(bw * 8))); // ns-3 takes bps, but we provide Bps
 -  csma.SetChannelAttribute("Delay", ns3::TimeValue(ns3::Seconds(lat)));
 -  ns3::NetDeviceContainer devices = csma.Install(Nodes);
 -  XBT_DEBUG("Create CSMA");
 -
 -  std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
 -  XBT_DEBUG("Assign IP Addresses %s to CSMA.", addr.c_str());
 -  ns3::Ipv4AddressHelper ipv4;
 -  ipv4.SetBase(addr.c_str(), "255.255.0.0");
 -  interfaces.Add(ipv4.Assign (devices));
 -
 -  if(number_of_links == 255){
 -    xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
 -    number_of_links = 1;
 -    number_of_networks++;
 -  }else{
 -    number_of_links++;
 -  }
 -  XBT_DEBUG("Number of nodes in Cluster_nodes: %u", Cluster_nodes.GetN());
 -}
 -
--static std::string transformIpv4Address(ns3::Ipv4Address from)
--{
--  std::stringstream sstream;
--  sstream << from ;
--  return sstream.str();
--}
--
 -void ns3_add_direct_route(NetPointNs3* src, NetPointNs3* dst, double bw, double lat, std::string link_name,
 -                          simgrid::s4u::Link::SharingPolicy policy)
 +void ns3_add_direct_route(simgrid::kernel::routing::NetPoint* src, simgrid::kernel::routing::NetPoint* dst, double bw,
-                           double lat, simgrid::s4u::Link::SharingPolicy policy)
++                          double lat, std::string link_name, simgrid::s4u::Link::SharingPolicy policy)
  {
    ns3::Ipv4AddressHelper address;
    ns3::NetDeviceContainer netA;
  
 -  int srcNum = src->node_num;
 -  int dstNum = dst->node_num;
 +  // create link ns3
 +  auto* host_src = src->extension<NetPointNs3>();
 +  auto* host_dst = dst->extension<NetPointNs3>();
  
 -  ns3::Ptr<ns3::Node> a = src->ns3_node_;
 -  ns3::Ptr<ns3::Node> b = dst->ns3_node_;
 +  xbt_assert(host_src != nullptr, "Network element %s does not seem to be ns-3-ready", src->get_cname());
 +  xbt_assert(host_dst != nullptr, "Network element %s does not seem to be ns-3-ready", dst->get_cname());
  
    if (policy == simgrid::s4u::Link::SharingPolicy::WIFI) {
-     /* Install a ns3::WifiHelper */
 -      xbt_assert(WifiZone::is_ap(a) != WifiZone::is_ap(b), "A wifi route can only exist between an access point node and a station node.");
++    auto a = host_src->ns3_node_;
++    auto b = host_dst->ns3_node_;
++    xbt_assert(WifiZone::is_ap(a) != WifiZone::is_ap(b),
++               "A wifi route can only exist between an access point node and a station node.");
 -      ns3::Ptr<ns3::Node> apNode = WifiZone::is_ap(a) ? a : b;
 -      ns3::Ptr<ns3::Node> staNode = apNode == a ? b : a;
++    ns3::Ptr<ns3::Node> apNode  = WifiZone::is_ap(a) ? a : b;
++    ns3::Ptr<ns3::Node> staNode = apNode == a ? b : a;
 -      WifiZone* zone = WifiZone::by_name(link_name);
++    WifiZone* zone = WifiZone::by_name(link_name);
 -      wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
 -                                    "ControlMode", ns3::StringValue ("HtMcs0"),
 -                                    "DataMode", ns3::StringValue ("HtMcs" + std::to_string(zone->get_mcs())));
++    wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", "ControlMode", ns3::StringValue("HtMcs0"), "DataMode",
++                                 ns3::StringValue("HtMcs" + std::to_string(zone->get_mcs())));
 -      wifiPhy.SetChannel (zone->get_channel());
 -      wifiPhy.Set("Antennas", ns3::UintegerValue(zone->get_nss()));
 -      wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
 -      wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
++    wifiPhy.SetChannel(zone->get_channel());
++    wifiPhy.Set("Antennas", ns3::UintegerValue(zone->get_nss()));
++    wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
++    wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(zone->get_nss()));
 -      wifiMac.SetType ("ns3::StaWifiMac");
++    wifiMac.SetType("ns3::StaWifiMac");
 -      netA.Add(wifi.Install (wifiPhy, wifiMac, staNode));
++    netA.Add(wifi.Install(wifiPhy, wifiMac, staNode));
 -      ns3::Config::Set ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", ns3::UintegerValue (40));
++    ns3::Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", ns3::UintegerValue(40));
 -      NetPointNs3* sta_netpointNs3 = WifiZone::is_ap(src->ns3_node_) ? dst : src;
 -      const char* wifi_distance = simgrid::s4u::Host::by_name(sta_netpointNs3->name_)->get_property("wifi_distance");
 -      ns3::Ptr<ns3::ListPositionAllocator> positionAllocS = ns3::CreateObject<ns3::ListPositionAllocator> ();
 -      positionAllocS->Add(ns3::Vector( wifi_distance ? atof(wifi_distance) : 10.0 , 0, 0));
 -      mobility.SetPositionAllocator(positionAllocS);
 -      mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
 -      mobility.Install(staNode);
++    NetPointNs3* sta_netpointNs3 = WifiZone::is_ap(host_src->ns3_node_) ? host_src : host_dst;
++    const char* wifi_distance    = simgrid::s4u::Host::by_name(sta_netpointNs3->name_)->get_property("wifi_distance");
++    ns3::Ptr<ns3::ListPositionAllocator> positionAllocS = ns3::CreateObject<ns3::ListPositionAllocator>();
++    positionAllocS->Add(ns3::Vector(wifi_distance ? atof(wifi_distance) : 10.0, 0, 0));
++    mobility.SetPositionAllocator(positionAllocS);
++    mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
++    mobility.Install(staNode);
 -      std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", zone->get_network(), zone->get_link());
 -      address.SetBase(addr.c_str(), "255.255.0.0", ("0.0.0." + std::to_string(zone->get_n_sta_nodes() + 2)).c_str());
 -      zone->add_sta_node();
 -      XBT_DEBUG("\tInterface stack '%s'", addr.c_str());
 -      interfaces.Add(address.Assign (netA));
 -      if (IPV4addr.size() <= (unsigned)dstNum)
 -        IPV4addr.resize(dstNum + 1);
 -      IPV4addr[dstNum] = transformIpv4Address(interfaces.GetAddress(interfaces.GetN() - 1));
++    std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", zone->get_network(), zone->get_link());
++    address.SetBase(addr.c_str(), "255.255.0.0", ("0.0.0." + std::to_string(zone->get_n_sta_nodes() + 2)).c_str());
++    zone->add_sta_node();
++    XBT_DEBUG("\tInterface stack '%s'", addr.c_str());
++    auto addresses          = address.Assign(netA);
++    host_dst->ipv4_address_ = transformIpv4Address(addresses.GetAddress(addresses.GetN() - 1));
    } else {
      ns3::PointToPointHelper pointToPoint;
 -    XBT_DEBUG("\tAdd PTP from %d to %d bw:'%f Bps' lat:'%fs'", srcNum, dstNum, bw, lat);
 +
 +    XBT_DEBUG("\tAdd PTP from %s to %s bw:'%f Bps' lat:'%fs'", src->get_cname(), dst->get_cname(), bw, lat);
      pointToPoint.SetDeviceAttribute("DataRate",
                                      ns3::DataRateValue(ns3::DataRate(bw * 8))); // ns-3 takes bps, but we provide Bps
      pointToPoint.SetChannelAttribute("Delay", ns3::TimeValue(ns3::Seconds(lat)));
  
 -    netA.Add(pointToPoint.Install(a, b));
 +    netA.Add(pointToPoint.Install(host_src->ns3_node_, host_dst->ns3_node_));
-   }
  
-   std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
-   address.SetBase(addr.c_str(), "255.255.0.0");
-   XBT_DEBUG("\tInterface stack '%s'", addr.c_str());
-   auto addresses = address.Assign(netA);
+     std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
+     address.SetBase(addr.c_str(), "255.255.0.0");
+     XBT_DEBUG("\tInterface stack '%s'", addr.c_str());
 -    interfaces.Add(address.Assign (netA));
 -
 -    if (IPV4addr.size() <= (unsigned)srcNum)
 -        IPV4addr.resize(srcNum + 1);
 -    IPV4addr[srcNum] = transformIpv4Address(interfaces.GetAddress(interfaces.GetN() - 2));
++    auto addresses = address.Assign(netA);
  
-   host_src->ipv4_address_ = transformIpv4Address(addresses.GetAddress(0));
-   host_dst->ipv4_address_ = transformIpv4Address(addresses.GetAddress(1));
 -    if (IPV4addr.size() <= (unsigned)dstNum)
 -        IPV4addr.resize(dstNum + 1);
 -    IPV4addr[dstNum] = transformIpv4Address(interfaces.GetAddress(interfaces.GetN() - 1));
++    host_src->ipv4_address_ = transformIpv4Address(addresses.GetAddress(0));
++    host_dst->ipv4_address_ = transformIpv4Address(addresses.GetAddress(1));
  
-   if (number_of_links == 255){
-     xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
-     number_of_links = 1;
-     number_of_networks++;
-   } else {
-     number_of_links++;
 -    if (number_of_links == 255){
 -        xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
 -        number_of_links = 1;
 -        number_of_networks++;
++    if (number_of_links == 255) {
++      xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
++      number_of_links = 1;
++      number_of_networks++;
+     } else {
 -        number_of_links++;
++      number_of_links++;
+     }
    }
  }
@@@ -9,24 -9,30 +9,29 @@@
  #include "simgrid/s4u/Host.hpp"
  #include "src/surf/network_ns3.hpp"
  
++#include "ns3/wifi-module.h"
  #include <ns3/node.h>
  #include <ns3/tcp-socket-factory.h>
 -#include "ns3/wifi-module.h"
  
  #include <cstdint>
  
 -class NetPointNs3 {
 +class XBT_PRIVATE NetPointNs3 {
  public:
    static simgrid::xbt::Extension<simgrid::kernel::routing::NetPoint, NetPointNs3> EXTENSION_ID;
  
 -  void set_name(std::string name) {name_ = name;}
++  void set_name(std::string name) { name_ = name; }
    explicit NetPointNs3();
 -  int node_num;
+   std::string name_;
    ns3::Ptr<ns3::Node> ns3_node_;
 -
 +  std::string ipv4_address_;
  };
  
 -XBT_PUBLIC void ns3_initialize(std::string TcpProtocol);
 -XBT_PUBLIC void ns3_simulator(double max_seconds);
 -XBT_PUBLIC void ns3_add_direct_route(NetPointNs3* src, NetPointNs3* dst, double bw, double lat, std::string link_name,
 -                                     simgrid::s4u::Link::SharingPolicy policy);
 -XBT_PUBLIC void ns3_add_cluster(const char* id, double bw, double lat);
 +XBT_PRIVATE void ns3_initialize(std::string TcpProtocol);
 +XBT_PRIVATE void ns3_simulator(double max_seconds);
 +XBT_PRIVATE void ns3_add_direct_route(simgrid::kernel::routing::NetPoint* src, simgrid::kernel::routing::NetPoint* dst,
-                                       double bw, double lat, simgrid::s4u::Link::SharingPolicy policy);
++                                      double bw, double lat, std::string link_name,
++                                      simgrid::s4u::Link::SharingPolicy policy);
  
  class XBT_PRIVATE SgFlow {
  public:
@@@ -41,7 -47,7 +46,7 @@@
    simgrid::kernel::resource::NetworkNS3Action* action_;
  };
  
 -void start_flow(ns3::Ptr<ns3::Socket> sock, const char* to, uint16_t port_number);
 +XBT_PRIVATE void start_flow(ns3::Ptr<ns3::Socket> sock, const char* to, uint16_t port_number);
  
  static inline std::string transform_socket_ptr(ns3::Ptr<ns3::Socket> local_socket)
  {
    return sstream.str();
  }
  
 -  const char* get_cname() {return name.c_str();}
 -  simgrid::s4u::Host* get_host(){return host;}
 -  ns3::Ptr<ns3::Node> get_ap_node() {return ap_node;}
 -  ns3::Ptr<ns3::YansWifiChannel> get_channel() {return channel;}
 -  int get_mcs() {return mcs;}
 -  int get_nss() {return nss;}
 -  int get_network() {return network;}
 -  int get_link() {return link;}
 -  int get_n_sta_nodes() {return n_sta_nodes;}
 -
 -  void set_network(int network_) {network = network_;}
 -  void set_link(int link_) {link = link_;}
 -  void add_sta_node() {n_sta_nodes++;}
+ class XBT_PRIVATE WifiZone {
+ public:
+   WifiZone(std::string name_, simgrid::s4u::Host* host_, ns3::Ptr<ns3::Node> ap_node_,
+            ns3::Ptr<ns3::YansWifiChannel> channel_, int mcs_, int nss_, int network_, int link_);
++  const char* get_cname() { return name.c_str(); }
++  simgrid::s4u::Host* get_host() { return host; }
++  ns3::Ptr<ns3::Node> get_ap_node() { return ap_node; }
++  ns3::Ptr<ns3::YansWifiChannel> get_channel() { return channel; }
++  int get_mcs() { return mcs; }
++  int get_nss() { return nss; }
++  int get_network() { return network; }
++  int get_link() { return link; }
++  int get_n_sta_nodes() { return n_sta_nodes; }
++
++  void set_network(int network_) { network = network_; }
++  void set_link(int link_) { link = link_; }
++  void add_sta_node() { n_sta_nodes++; }
+   static bool is_ap(ns3::Ptr<ns3::Node> node);
+   static WifiZone* by_name(std::string name);
+ private:
+   std::string name;
+   simgrid::s4u::Host* host;
+   ns3::Ptr<ns3::Node> ap_node;
+   ns3::Ptr<ns3::YansWifiChannel> channel;
+   int mcs;
+   int nss;
+   int network;
+   int link;
+   int n_sta_nodes = 0;
+   static std::unordered_map<std::string, WifiZone*> wifi_zones;
+ };
  #endif