Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into 'master'
authorAdrien <adrien.gougeon@inria.fr>
Thu, 22 Oct 2020 09:36:39 +0000 (11:36 +0200)
committerAdrien <adrien.gougeon@inria.fr>
Thu, 22 Oct 2020 09:36:39 +0000 (11:36 +0200)
# Conflicts:
#   docs/source/ns3.rst
#   src/surf/network_ns3.cpp

1  2 
docs/source/ns3.rst
src/kernel/routing/RoutedZone.cpp
src/kernel/routing/WifiZone.cpp
src/surf/network_ns3.cpp

diff --combined docs/source/ns3.rst
@@@ -12,7 -12,7 +12,7 @@@ The SimGrid/ns-3 binding only contains 
  Not all ns-3 models are available from SimGrid (only the TCP and WiFi ones are),
  while not all SimGrid platform files can be used in conjunction ns-3 (routes
  must be of length 1). Also, the platform built in ns-3 from the SimGrid
- description is very basic. Finally, communicating from an host to
+ description is very basic. Finally, communicating from a host to
  itself is forbidden in ns-3, so every such communication completes
  immediately upon startup.
  
@@@ -139,118 -139,74 +139,118 @@@ to see which ones are used in our regre
  WiFi platforms
  --------------
  
 -In SimGrid, WiFi networks are modeled as regular links with a specific
 -attribute, and these links are then added to routes between hosts. The main
 -difference When using ns-3 WiFi networks is that the network performance is not
 -given by the link bandwidth and latency but by the access point WiFi
 -characteristics, and the distance between the access point and the hosts (called
 -station in the WiFi world).
 -
 -So, to declare a new WiFi network, simply declare a link with the ``WiFi``
 -sharing policy as you would do in a pure SimGrid simulation (you must still
 -provide the ``bandwidth`` and ``latency`` attributes even if they are ignored,
 -because they are mandatory to the SimGrid XML parser).
 +In SimGrid, WiFi networks are modeled with WiFi zones, where a zone contains 
 +the access point of the WiFi network and the hosts connected to it (called 
 +station in the WiFi world). Links inside WiFi zones are modeled as regular 
 +links with a specific attribute, and these links are then added to routes 
 +between hosts. The main difference When using ns-3 WiFi networks is that 
 +the network performance is not given by the link bandwidth and latency but 
 +by the access point WiFi characteristics, and the distance between the access 
 +point and the hosts.
 +
 +So, to declare a new WiFi network, simply declare a zone with the ``WIFI``
 +routing.
  
  .. code-block:: xml
  
 -       <link id="net0" bandwidth="0" latency="0" sharing_policy="WIFI"/>
 +      <zone id="SSID_1" routing="WIFI">
  
 -To declare that a given host is connected to this WiFi zone, use the
 -``wifi_link`` property of that host. The property value must be the link id that
 -you want to use as a WiFi zone. This is not needed when using pure SimGrid wifi,
 -only when using ns-3 wifi, because the wifi performance is :ref:`configured <ns3_wifi_perf>`.
 +Inside this zone you must declare which host or router will be the access point
 +of the WiFi network.
  
  .. code-block:: xml
  
 -   <host id="alice" speed="1Gf">
 -     <prop id="wifi_link" value="net0"/>
 -   </host>
 +      <prop id="access_point" value="alice"/>
  
 -To connect the station node to the access point node, simply create a route
 -between them:
 +Afterward simply declare the hosts and routers inside the WiFi network. Remember 
 +that one must have the same name as declared in the property "access point".
  
  .. code-block:: xml
  
 -   <route src="alice" dst="bob">
 -     <link_ctn id="net0" />
 -   </route>
 +      <router id="alice" speed="1Gf"/>
 +      <host id="STA0-0" speed="1Gf"/>
 +      <host id="STA0-1" speed="1Gf"/> 
  
 -.. _ns3_wifi_perf:
 +Finally, close the WiFi zone.
 +
 +.. code-block:: xml
 +
 +      </zone>
 +
 +The WiFi zone may be connected to another zone using a traditional link and 
 +a zoneRoute. Note that the connection between two zones is always wired.
 +
 +.. code-block:: xml
 +
 +      <link id="wireline" bandwidth="100Mbps" latency="2ms" sharing_policy="SHARED"/>
 +
 +      <zoneRoute src="SSID_1" dst="SSID_2" gw_src="alice" gw_dst="bob">
 +          <link_ctn id="wireline"/>
 +      </zoneRoute>
  
  WiFi network performance
  ^^^^^^^^^^^^^^^^^^^^^^^^
  
  
  The performance of a wifi network is controlled by 3 property that can be added
 -to the a host connected to the wifi zone:
 +to hosts connected to the wifi zone:
  
 - * ``wifi_mcs`` (`Modulation and Coding Scheme <https://en.wikipedia.org/wiki/Link_adaptation>`_)
 + * ``mcs`` (`Modulation and Coding Scheme <https://en.wikipedia.org/wiki/Link_adaptation>`_)
     Roughly speaking, it defines the speed at which the access point is
     exchanging data with all stations. It depends on its model and configuration,
     and the possible values are listed for example on Wikipedia.
 -   |br| By default, ``wifi_mcs=3``.
 - * ``wifi_nss`` (Number of Spatial Streams, or `number of antennas <https://en.wikipedia.org/wiki/IEEE_802.11n-2009#Number_of_antennas>`_)
 +   |br| By default, ``mcs=3``. 
 +   It is a property of the WiFi zone.
 + * ``nss`` (Number of Spatial Streams, or `number of antennas <https://en.wikipedia.org/wiki/IEEE_802.11n-2009#Number_of_antennas>`_)
     defines the amount of simultaneous data streams that the AP can sustain.
     Not all value of MCS and NSS are valid nor compatible (cf. `802.11n standard <https://en.wikipedia.org/wiki/IEEE_802.11n-2009#Data_rates>`_).
 -   |br| By default, ``wifi_nss=1``.
 +   |br| By default, ``nss=1``.
 +   It is a property of the WiFi zone.
   * ``wifi_distance`` is the distance from the station to the access point. Each
     station can have a specific value.
     |br| By default, ``wifi_distance=10``.
 +   It is a property of stations of the WiFi network.
 +
 +Here is an example of a zone changing ``mcs`` and ``nss`` values.
 +
 +.. code-block:: xml
 +
 +      <zone id="SSID_1" routing="WIFI">
 +          <prop id="access_point" value="alice"/>
 +          <prop id="mcs" value="2"/>
 +          <prop id="nss" value="2"/>
 +      ...
 +      </zone>
 +
 +Here is an example of a host changing ``wifi_distance`` value.
 +
 +.. code-block:: xml
 +
 +      <host id="STA0-0" speed="1Gf">
 +          <prop id="wifi_distance" value="37"/>
 +      </host>
 +
 +Random Number Generator
 +=======================
  
 -Here is an example of host changing all these values:
 +It is possible to define a fixed or random seed to the ns3 random number 
 +generator using the config tag.
  
  .. code-block:: xml
  
 -   <host id="alice" speed="100.0Mf,50.0Mf,20.0Mf" pstate="0">
 -     <prop id="wifi_link" value="net0"/>
 -     <prop id="wifi_mcs" value="5"/>
 -     <prop id="wifi_nss" value="2"/>
 -     <prop id="wifi_distance" value="30" />
 -   </host>
 +      <?xml version='1.0'?><!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
 +      <platform version="4.1">
 +          <config>
 +                  <prop id = "network/model" value = "ns-3" />
 +                  <prop id = "ns3/seed" value = "time" /> 
 +          </config>
 +      ... 
 +      </platform>
 +
 +The first property defines that this platform will be used with the ns3 model.
 +The second property defines the seed that will be used. Defined to ``time`` 
 +it will use a random seed, defined to a number it will use this number as 
 +the seed.
  
  Limitations
  ===========
@@@ -169,12 -169,11 +169,12 @@@ void RoutedZone::add_route_check_params
      xbt_assert(dst, "Cannot add a route from %s to %s: %s does not exist.", srcName, dstName, dstName);
      xbt_assert(not link_list.empty(), "Empty route (between %s and %s) forbidden.", srcName, dstName);
      xbt_assert(not src->is_netzone(),
-                "When defining a route, src cannot be a netzone such as '%s'. Did you meant to have an NetzoneRoute?",
+                "When defining a route, src cannot be a netzone such as '%s'. Did you meant to have a NetzoneRoute?",
                 srcName);
      xbt_assert(not dst->is_netzone(),
-                "When defining a route, dst cannot be a netzone such as '%s'. Did you meant to have an NetzoneRoute?",
+                "When defining a route, dst cannot be a netzone such as '%s'. Did you meant to have a NetzoneRoute?",
                 dstName);
 +    s4u::NetZone::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, link_list);
    } else {
      XBT_DEBUG("Load NetzoneRoute from %s@%s to %s@%s", srcName, gw_src->get_cname(), dstName, gw_dst->get_cname());
      xbt_assert(src->is_netzone(), "When defining a NetzoneRoute, src must be a netzone but '%s' is not", srcName);
      xbt_assert(gw_dst->is_host() || gw_dst->is_router(),
                 "When defining a NetzoneRoute, gw_dst must be a host or a router but '%s' is not.", dstName);
  
-     xbt_assert(gw_src != gw_dst, "Cannot define an NetzoneRoute from '%s' to itself", gw_src->get_cname());
+     xbt_assert(gw_src != gw_dst, "Cannot define a NetzoneRoute from '%s' to itself", gw_src->get_cname());
  
      xbt_assert(src, "Cannot add a route from %s@%s to %s@%s: %s does not exist.", srcName, gw_src->get_cname(), dstName,
                 gw_dst->get_cname(), srcName);
                 gw_dst->get_cname(), dstName);
      xbt_assert(not link_list.empty(), "Empty route (between %s@%s and %s@%s) forbidden.", srcName, gw_src->get_cname(),
                 dstName, gw_dst->get_cname());
 +    s4u::NetZone::on_route_creation(symmetrical,  gw_src, gw_dst, gw_src, gw_dst, link_list);
    }
 -
 -  s4u::NetZone::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, link_list);
  }
  } // namespace routing
  } // namespace kernel
@@@ -29,7 -29,7 +29,7 @@@ void WifiZone::seal(
      xbt_assert(access_point_ != nullptr, "Access point '%s' of WIFI zone '%s' does not exist: no such host or router.",
                 AP_name, get_cname());
      xbt_assert(access_point_->is_host() || access_point_->is_router(),
-                "Access point '%s' of WIFI zone '%s' must be either an host or a router.", AP_name, get_cname());
+                "Access point '%s' of WIFI zone '%s' must be either a host or a router.", AP_name, get_cname());
    }
  }
  
@@@ -39,7 -39,7 +39,7 @@@ void WifiZone::get_local_route(NetPoint
  
    if (wifi_link_ != nullptr) {
      // If src and dst are nodes, not access_point, we need to traverse the link twice
 -    // Otherwise (if src or dst is access_poit), we need to traverse the link only once
 +    // Otherwise (if src or dst is access_point), we need to traverse the link only once
  
      if (src != access_point_) {
        XBT_DEBUG("src %s is not our gateway", src->get_cname());
diff --combined src/surf/network_ns3.cpp
@@@ -28,7 -28,6 +28,7 @@@
  #include "ns3/ns3_simulator.hpp"
  
  #include "simgrid/kernel/routing/NetPoint.hpp"
 +#include "simgrid/kernel/routing/WifiZone.hpp"
  #include "simgrid/plugins/energy.h"
  #include "simgrid/s4u/Engine.hpp"
  #include "simgrid/s4u/NetZone.hpp"
@@@ -72,88 -71,60 +72,88 @@@ NetPointNs3::NetPointNs3() : ns3_node_(
    stack.Install(ns3_node_);
  }
  
 -WifiZone::WifiZone(const 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_)
 -    : 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;
 -}
 +/*************
 + * Callbacks *
 + *************/
  
 -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 zoneCreation_cb(simgrid::s4u::NetZone const& zone) {
 +    simgrid::kernel::routing::WifiZone* wifizone = dynamic_cast<simgrid::kernel::routing::WifiZone*> (zone.get_impl());
 +    if (wifizone == nullptr) return;
 +
 +    wifi.SetStandard(ns3::WIFI_PHY_STANDARD_80211n_5GHZ);
 +
 +    std::string ssid = wifizone->get_name();
 +    const char* mcs = wifizone->get_property("mcs");
 +    const char* nss = wifizone->get_property("nss");
 +    int mcs_value = mcs ? atoi(mcs) : 3;
 +    int nss_value = nss ? atoi(nss) : 1;
 +    wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
 +                                 "ControlMode", ns3::StringValue("HtMcs0"),
 +                                 "DataMode", ns3::StringValue("HtMcs" + std::to_string(mcs_value)));
 +    wifiPhy.SetChannel(wifiChannel.Create());
 +    wifiPhy.Set("Antennas", ns3::UintegerValue(nss_value));
 +    wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(nss_value));
 +    wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(nss_value));
 +    wifiMac.SetType("ns3::ApWifiMac",
 +                    "Ssid", ns3::SsidValue(ssid));
  
 -WifiZone* WifiZone::by_name(const std::string& name)
 -{
 -  WifiZone* zone;
 -  try {
 -    zone = wifi_zones.at(name);
 -  } catch (const std::out_of_range& oor) {
 -    return nullptr;
 -  }
 -  return zone;
 -}
 +    mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
 +    ns3::Ptr<ns3::ListPositionAllocator> positionAllocS = ns3::CreateObject<ns3::ListPositionAllocator>();
 +    positionAllocS->Add(ns3::Vector(0, 0, 255 * 100 * number_of_networks + 100 * number_of_links));
  
 -std::unordered_map<std::string, WifiZone*> WifiZone::wifi_zones;
 +    ns3::NetDeviceContainer netDevices;
 +    NetPointNs3* access_point_netpoint_ns3 = wifizone->get_access_point()->extension<NetPointNs3>();
  
 -static void initialize_ns3_wifi()
 -{
 -  wifi.SetStandard(ns3::WIFI_PHY_STANDARD_80211n_5GHZ);
 +    ns3::Ptr<ns3::Node> access_point_ns3_node = access_point_netpoint_ns3->ns3_node_;
 +    ns3::NodeContainer nodes = {access_point_ns3_node};
 +    std::vector<NetPointNs3*> hosts_netpoints = {access_point_netpoint_ns3};
 +    netDevices.Add(wifi.Install(wifiPhy, wifiMac,access_point_ns3_node));
  
 -  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");
 +    wifiMac.SetType ("ns3::StaWifiMac",
 +                     "Ssid", ns3::SsidValue(ssid),
 +                     "ActiveProbing", ns3::BooleanValue(false));
  
 -    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);
 -  }
 -}
 +    NetPointNs3* station_netpoint_ns3 = nullptr;
 +    ns3::Ptr<ns3::Node> station_ns3_node = nullptr;
 +    double distance;
 +    double angle = 0;
 +    int nb_stations = wifizone->get_all_hosts().size() - 1;
 +    double step = 2 * M_PI / nb_stations;
 +    for (auto station_host : wifizone->get_all_hosts()) {
 +        station_netpoint_ns3 = station_host->get_netpoint()->extension<NetPointNs3>();
 +        if (station_netpoint_ns3 == access_point_netpoint_ns3)
 +            continue;
 +        hosts_netpoints.push_back(station_netpoint_ns3);
 +        distance = station_host->get_property("wifi_distance") ? atof(station_host->get_property("wifi_distance")) : 10.0;
 +        positionAllocS->Add(ns3::Vector(distance * std::cos(angle), distance * std::sin(angle), 255 * 100 * number_of_networks + 100 * number_of_links));
 +        angle += step;
 +        station_ns3_node = station_netpoint_ns3->ns3_node_;
 +        nodes.Add(station_ns3_node);
 +        netDevices.Add(wifi.Install(wifiPhy, wifiMac, station_ns3_node));
 +    }
  
 -/*************
 - * Callbacks *
 - *************/
 +    ns3::Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", ns3::UintegerValue(40));
 +
 +    mobility.SetPositionAllocator(positionAllocS);
 +    mobility.Install(nodes);
 +
 +    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());
 +    ns3::Ipv4InterfaceContainer addresses = address.Assign(netDevices);
 +    for (int i = 0; i < hosts_netpoints.size(); i++) {
 +        hosts_netpoints[i]->ipv4_address_ = transformIpv4Address(addresses.GetAddress(i));
 +    }
 +
 +    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 clusterCreation_cb(simgrid::kernel::routing::ClusterCreationArgs const& cluster)
  {
@@@ -300,7 -271,6 +300,7 @@@ NetworkNS3Model::NetworkNS3Model() : Ne
    });
    routing::on_cluster_creation.connect(&clusterCreation_cb);
    s4u::NetZone::on_route_creation.connect(&routeCreation_cb);
 +  s4u::NetZone::on_seal.connect(&zoneCreation_cb);
  }
  
  LinkImpl* NetworkNS3Model::create_link(const std::string& name, const std::vector<double>& bandwidths, double latency,
@@@ -414,6 -384,57 +414,6 @@@ LinkNS3::LinkNS3(NetworkNS3Model* model
    bandwidth_.peak = bandwidth;
    latency_.peak   = latency;
  
 -  /* If wifi, create the wifizone now. If not, don't do anything: the links will be created in routeCreate_cb */
 -
 -  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 != nullptr, "Link name '%s' does not match the 'wifi_link' property of a host.", name.c_str());
 -    auto* 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",
 -                    "Ssid", ns3::SsidValue(name));
 -
 -    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(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());
  }
  
@@@ -439,6 -460,20 +439,20 @@@ void LinkNS3::set_latency_profile(profi
  NetworkNS3Action::NetworkNS3Action(Model* model, double totalBytes, s4u::Host* src, s4u::Host* dst)
      : NetworkAction(model, *src, *dst, totalBytes, false)
  {
+   // ns-3 fails when src = dst, so avoid the problem by considering that communications are infinitely fast on the
+   // loopback that does not exists
+   if (src == dst) {
+     static bool warned = false;
+     if (not warned) {
+       XBT_WARN("Sending from a host %s to itself is not supported by ns-3. Every such communication finishes "
+                "immediately upon startup.",
+                src->get_cname());
+       warned = true;
+     }
+     finish(Action::State::FINISHED);
+     return;
+   }
    // If there is no other started actions, we need to move NS-3 forward to be sync with SimGrid
    if (model->get_started_action_set()->size()==1){
      while(double_positive(surf_get_clock() - ns3::Simulator::Now().GetSeconds(), sg_surf_precision)){
@@@ -529,7 -564,46 +543,7 @@@ void ns3_add_direct_route(simgrid::kern
    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) {
 -    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;
 -
 -    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())));
 -
 -    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",
 -                     "Ssid", ns3::SsidValue(link_name),
 -                     "ActiveProbing", ns3::BooleanValue(false));
 -
 -    netA.Add(wifi.Install(wifiPhy, wifiMac, staNode));
 -
 -    ns3::Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", ns3::UintegerValue(40));
 -
 -    simgrid::kernel::routing::NetPoint* sta_netpoint = WifiZone::is_ap(host_src->ns3_node_) ? dst : src;
 -    const char* wifi_distance    = simgrid::s4u::Host::by_name(sta_netpoint->get_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());
 -    auto addresses          = address.Assign(netA);
 -    host_dst->ipv4_address_ = transformIpv4Address(addresses.GetAddress(1));
 +      xbt_die("The wifi sharing policy is not supported for links. You want to use a wifi zone (see documentation).");
    } else {
      ns3::PointToPointHelper pointToPoint;
  
      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);
  
      host_src->ipv4_address_ = transformIpv4Address(addresses.GetAddress(0));