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 --cc CMakeLists.txt
Simple merge
diff --cc 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)
                      _               _____  ____  ____
  __   _____ _ __ ___(_) ___  _ __   |___ / |___ \| ___|
  \ \ / / _ \ '__/ __| |/ _ \| '_ \    |_ \   __) |___ \
@@@ -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
  ============================
@@@ -71,49 -83,53 +72,53 @@@ 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
@@@ -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"
  
@@@ -46,57 -55,90 +49,123 @@@ static ns3::InternetStackHelper stack
  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;
  
@@@ -295,9 -341,60 +365,57 @@@ LinkNS3::LinkNS3(NetworkNS3Model* model
  {
    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());
  }
  
@@@ -400,52 -502,160 +518,82 @@@ void ns3_simulator(double maxSeconds
      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,8 -9,9 +9,9 @@@
  #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>
  
@@@ -18,15 -19,20 +19,19 @@@ 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:
@@@ -50,4 -56,39 +55,39 @@@ static inline std::string transform_soc
    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