nix-vector-routing: Handle Multiple Wifi connections with same channel object

Signed-off-by: Ameya Deshpande <ameyanrd@outlook.com>
This commit is contained in:
Ameya Deshpande
2021-08-13 21:17:20 +02:00
committed by Tommaso Pecorella
parent 2d512ad14b
commit 7be87100a9
9 changed files with 406 additions and 14 deletions

View File

@@ -125,6 +125,16 @@ Ipv4InterfaceAddress::GetScope (void) const
return m_scope;
}
bool Ipv4InterfaceAddress::IsInSameSubnet (const Ipv4Address b) const
{
Ipv4Address aAddr = m_local;
aAddr = aAddr.CombineMask(m_mask);
Ipv4Address bAddr = b;
bAddr = bAddr.CombineMask(m_mask);
return (aAddr == bAddr);
}
bool
Ipv4InterfaceAddress::IsSecondary (void) const
{

View File

@@ -138,6 +138,13 @@ public:
*/
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope (void) const;
/**
* \brief Checks if the address is in the same subnet.
* \param b the address to check
* \return true if the address is in the same subnet.
*/
bool IsInSameSubnet (const Ipv4Address b) const;
/**
* \brief Check if the address is a secondary address
*

View File

@@ -60,15 +60,14 @@ Scope and Limitations
=====================
Currently, the |ns3| model of nix-vector routing supports IPv4 and IPv6
p2p links as well as CSMA links. It does not (yet) provide support for
efficient adaptation to link failures. It simply flushes all nix-vector
routing caches.
p2p links, CSMA links and multiple WiFi networks with the same channel object.
It does not (yet) provide support for efficient adaptation to link failures.
It simply flushes all nix-vector routing caches.
NixVectorRouting bases its routing decisions on the nodes' interface
addresses and does **not** check whether the nodes are in the proper
subnets or the addresses have been appropriately assigned. In other
terms, using Nix-Vector routing, it is possible to have a working
network that violates every good practice in IP address assignments.
NixVectorRouting performs a subnet matching check, but it does **not** check
entirely if the addresses have been appropriately assigned. In other terms,
using Nix-Vector routing, it is possible to have a working network that
violates some good practices in IP address assignments.
In case of IPv6, Nix assumes the link-local addresses assigned are **unique**.
When using the IPv6 stack, the link-local address allocation is unique by
@@ -177,7 +176,7 @@ Thus, the nix-vector for the path from n0 to n3 is 101.
#. Using IPv6:
.. code-block:: bash
# Set ip as "v6" explicity
# Use the --useIPv6 flag
./waf --run "src/nix-vector-routing/examples/nix-simple --useIPv6"
* nms-p2p-nix.cc
@@ -197,7 +196,7 @@ performs source-based routing (BFS) to have faster routing.
#. Using IPv6:
.. code-block:: bash
# Set ip as "v6" explicity
# Use the --useIPv6 flag
./waf --run "src/nix-vector-routing/examples/nms-p2p-nix --useIPv6"
* nix-simple-multi-address.cc
@@ -210,3 +209,25 @@ the all the route caches and Nix caches to flush.
# By default IPv4 network is selected
./waf --run src/nix-vector-routing/examples/nix-simple-multi-address
* nix-double-wifi.cc
This example demonstrates the working of Nix with two Wifi networks
operating on the same Wifi channel object. The example uses ``ns3::YansWifiChannel``
for both the wifi networks.
#. Using IPv4:
.. code-block:: bash
# By default IPv4 network is selected
./waf --run src/nix-vector-routing/examples/nix-double-wifi
# Use the --enableNixLog to enable NixVectorRouting logging.
./waf --run "src/nix-vector-routing/examples/nix-double-wifi --enableNixLog"
#. Using IPv6:
.. code-block:: bash
# Use the --useIPv6 flag
./waf --run "src/nix-vector-routing/examples/nix-double-wifi --useIPv6"
# Use the --enableNixLog to enable NixVectorRouting logging.
./waf --run "src/nix-vector-routing/examples/nix-double-wifi --useIPv6 --enableNixLog"

View File

@@ -0,0 +1,262 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2021 NITK Surathkal
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This example is inspired from examples/tutorial/third.cc by
* substituting the CSMA network with another WiFi network.
*
* Author: Ameya Deshpande <ameyanrd@outlook.com>
*/
#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/wifi-module.h"
#include "ns3/ssid.h"
#include "ns3/nix-vector-routing-module.h"
/**
* This example demonstrates how Nix works with
* two Wifi networks on the same channel.
*
* IPv4 Network Topology
* \verbatim
Wifi 10.1.1.0/24
AP
* * * *
| | | | 10.1.2.0/24
n5 n6 n7 n0 -------------- n1 n2 n3 n4
point-to-point | | | |
* * * *
AP
Wifi 10.1.3.0/24
\endverbatim
*
* \verbatim
Wifi 2001:1::/64
AP
* * * *
| | | | 2001:2::/64
n5 n6 n7 n0 -------------- n1 n2 n3 n4
point-to-point | | | |
* * * *
AP
Wifi 2001:3::/64
\endverbatim
*
* Expected Outputs:
* IPv4:
* \verbatim
Time: +7s, Nix Routing
Route Path: (Node 4 to Node 7, Nix Vector: 100011)
10.1.1.3 (Node 4) ----> 10.1.1.4 (Node 0)
10.1.2.1 (Node 0) ----> 10.1.2.2 (Node 1)
10.1.3.4 (Node 1) ----> 10.1.3.3 (Node 7)
\endverbatim
*
* IPv6:
* \verbatim
Time: +7s, Nix Routing
Route Path: (Node 4 to Node 7, Nix Vector: 100011)
2001:1::200:ff:fe00:5 (Node 4) ----> fe80::200:ff:fe00:6 (Node 0)
fe80::200:ff:fe00:1 (Node 0) ----> fe80::200:ff:fe00:2 (Node 1)
fe80::200:ff:fe00:a (Node 1) ----> 2001:3::200:ff:fe00:9 (Node 7)
\endverbatim
*/
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("NixDoubleWifiExample");
int
main (int argc, char *argv[])
{
bool useIpv6 = false;
bool enableNixLog = false;
CommandLine cmd (__FILE__);
cmd.AddValue ("useIPv6", "Use IPv6 instead of IPv4", useIpv6);
cmd.AddValue ("enableNixLog", "Enable NixVectorRouting logging", enableNixLog);
cmd.Parse (argc,argv);
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
if (enableNixLog)
{
LogComponentEnable ("NixVectorRouting", LOG_LEVEL_LOGIC);
}
NodeContainer p2pNodes;
p2pNodes.Create (2);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
NodeContainer wifiStaNodes1;
wifiStaNodes1.Create (3);
NodeContainer wifiApNode1 = p2pNodes.Get (0);
NodeContainer wifiStaNodes2;
wifiStaNodes2.Create (3);
NodeContainer wifiApNode2 = p2pNodes.Get (1);
YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
YansWifiPhyHelper phy;
phy.SetChannel (channel.Create ());
WifiHelper wifi;
wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
WifiMacHelper mac;
Ssid ssid = Ssid ("ns-3-ssid-first");
mac.SetType ("ns3::StaWifiMac",
"Ssid", SsidValue (ssid),
"ActiveProbing", BooleanValue (false));
NetDeviceContainer staDevices1;
staDevices1 = wifi.Install (phy, mac, wifiStaNodes1);
mac.SetType ("ns3::ApWifiMac",
"Ssid", SsidValue (ssid));
NetDeviceContainer apDevices1;
apDevices1 = wifi.Install (phy, mac, wifiApNode1);
ssid = Ssid ("ns-3-ssid-second");
mac.SetType ("ns3::StaWifiMac",
"Ssid", SsidValue (ssid),
"ActiveProbing", BooleanValue (false));
NetDeviceContainer staDevices2;
staDevices2 = wifi.Install (phy, mac, wifiStaNodes2);
mac.SetType ("ns3::ApWifiMac",
"Ssid", SsidValue (ssid));
NetDeviceContainer apDevices2;
apDevices2 = wifi.Install (phy, mac, wifiApNode2);
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (5.0),
"DeltaY", DoubleValue (10.0),
"GridWidth", UintegerValue (3),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
"Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
mobility.Install (wifiStaNodes1);
mobility.Install (wifiStaNodes2);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (wifiApNode1);
mobility.Install (wifiApNode2);
Address udpServerAddress;
if (!useIpv6)
{
InternetStackHelper stack;
Ipv4NixVectorHelper nixRouting;
stack.SetRoutingHelper (nixRouting);
stack.Install (wifiApNode1);
stack.Install (wifiStaNodes1);
stack.Install (wifiApNode2);
stack.Install (wifiStaNodes2);
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
address.Assign (staDevices1);
address.Assign (apDevices1);
address.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
address.SetBase ("10.1.3.0", "255.255.255.0");
Ipv4InterfaceContainer staDevicesInterfaces2;
staDevicesInterfaces2 = address.Assign (staDevices2);
address.Assign (apDevices2);
udpServerAddress = staDevicesInterfaces2.GetAddress (2);
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("nix-double-wifi-ipv4.routes", std::ios::out);
nixRouting.PrintRoutingPathAt (Seconds (7), wifiStaNodes1.Get (2), staDevicesInterfaces2.GetAddress (2), routingStream);
}
else
{
InternetStackHelper stack;
Ipv6NixVectorHelper nixRouting;
stack.SetRoutingHelper (nixRouting);
stack.Install (wifiApNode1);
stack.Install (wifiStaNodes1);
stack.Install (wifiApNode2);
stack.Install (wifiStaNodes2);
Ipv6AddressHelper address;
address.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
address.Assign (staDevices1);
address.Assign (apDevices1);
address.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64));
Ipv6InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
address.SetBase (Ipv6Address ("2001:3::"), Ipv6Prefix (64));
Ipv6InterfaceContainer staDevicesInterfaces2;
staDevicesInterfaces2 = address.Assign (staDevices2);
address.Assign (apDevices2);
udpServerAddress = staDevicesInterfaces2.GetAddress (2, 1);
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("nix-double-wifi-ipv6.routes", std::ios::out);
nixRouting.PrintRoutingPathAt (Seconds (7), wifiStaNodes1.Get (2), staDevicesInterfaces2.GetAddress (2, 1), routingStream);
}
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (wifiStaNodes2.Get (2));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (udpServerAddress, 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (wifiStaNodes1.Get (2));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Simulator::Stop (Seconds (10.0));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}

View File

@@ -12,3 +12,7 @@ def build(bld):
obj = bld.create_ns3_program('nix-simple-multi-address',
['point-to-point', 'applications', 'internet', 'nix-vector-routing'])
obj.source = 'nix-simple-multi-address.cc'
obj = bld.create_ns3_program('nix-double-wifi',
['point-to-point', 'wifi', 'applications', 'internet', 'nix-vector-routing'])
obj.source = 'nix-double-wifi.cc'

View File

@@ -34,6 +34,17 @@
#include "nix-vector-routing.h"
/* RunIf code is a candidate for ns-3 core module */
template <class F, class...Ts>
void RunIf (std::true_type, F&& f, Ts&&... ts )
{
f (std::forward<Ts>(ts)...);
}
template <class...Xs>
void RunIf (std::false_type, Xs&&...)
{
}
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("NixVectorRouting");
@@ -149,6 +160,7 @@ NixVectorRouting<T>::FlushGlobalNixRoutingCache (void) const
NS_LOG_LOGIC ("Flushing Nix caches.");
rp->FlushNixCache ();
rp->FlushIpRouteCache ();
rp->m_totalNeighbors = 0;
}
// IP address to node mapping is potentially invalid so clear it.
@@ -372,11 +384,84 @@ NixVectorRouting<T>::GetAdjacentNetDevices (Ptr<NetDevice> netDevice, Ptr<Channe
{
NS_LOG_FUNCTION (this << netDevice << channel);
Ptr<Ip> netDeviceIp = netDevice->GetNode ()->GetObject<Ip> ();
if (!netDeviceIp)
{
return;
}
int32_t netDeviceInterface = netDeviceIp->GetInterfaceForDevice (netDevice);
if (netDeviceInterface == -1)
{
return;
}
if (!netDeviceIp->IsUp (netDeviceInterface))
{
return;
}
uint32_t netDeviceAddresses = netDeviceIp->GetNAddresses (netDeviceInterface);
for (std::size_t i = 0; i < channel->GetNDevices (); i++)
{
Ptr<NetDevice> remoteDevice = channel->GetDevice (i);
if (remoteDevice != netDevice)
{
// Compare if the remoteDevice shares a common subnet with remoteDevice
Ptr<Ip> remoteDeviceIp = remoteDevice->GetNode ()->GetObject<Ip> ();
if (!remoteDeviceIp)
{
continue;
}
int32_t remoteDeviceInterface = remoteDeviceIp->GetInterfaceForDevice (remoteDevice);
if (remoteDeviceInterface == -1)
{
continue;
}
if (!remoteDeviceIp->IsUp (remoteDeviceInterface))
{
continue;
}
uint32_t remoteDeviceAddresses = remoteDeviceIp->GetNAddresses (remoteDeviceInterface);
bool commonSubnetFound = false;
for (uint32_t j = 0; j < netDeviceAddresses; ++j)
{
IpInterfaceAddress netDeviceIfAddr = netDeviceIp->GetAddress (netDeviceInterface, j);
bool isNetDeviceAddrLinkLocal = false;
RunIf (std::is_same<Ipv6RoutingProtocol,T>{}, [&](Ipv6InterfaceAddress IfAddr, bool &isNetDeviceAddrLinkLocal)
{
if (IfAddr.GetScope () == Ipv6InterfaceAddress::LINKLOCAL)
{
isNetDeviceAddrLinkLocal = true;
}
},
netDeviceIfAddr, isNetDeviceAddrLinkLocal);
if (isNetDeviceAddrLinkLocal)
{
continue;
}
for (uint32_t k = 0; k < remoteDeviceAddresses; ++k)
{
IpInterfaceAddress remoteDeviceIfAddr = remoteDeviceIp->GetAddress (remoteDeviceInterface, k);
if (netDeviceIfAddr.IsInSameSubnet (remoteDeviceIfAddr.GetAddress ()))
{
commonSubnetFound = true;
break;
}
}
if (commonSubnetFound)
{
break;
}
}
if (!commonSubnetFound)
{
continue;
}
Ptr<BridgeNetDevice> bd = NetDeviceIsBridged (remoteDevice);
// we have a bridged device, we need to add all
// bridged devices

View File

@@ -328,7 +328,7 @@ NixVectorRoutingTest::DoRun (void)
NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), p_nSrcnAnCnDstv6, "Routing Path is incorrect.");
const std::string p_nSrcnAnBnCnDstv4 = "Time: +9s, Nix Routing\n"
"Route Path: (Node 0 to Node 4, Nix Vector: 001101)\n"
"Route Path: (Node 0 to Node 4, Nix Vector: 0111)\n"
"10.1.0.1 (Node 0) ----> 10.1.0.2 (Node 1)\n"
"10.1.1.1 (Node 1) ----> 10.1.1.2 (Node 2)\n"
"10.1.2.1 (Node 2) ----> 10.1.2.2 (Node 3)\n"
@@ -336,7 +336,7 @@ NixVectorRoutingTest::DoRun (void)
NS_TEST_EXPECT_MSG_EQ (stringStream3v4.str (), p_nSrcnAnBnCnDstv4, "Routing Path is incorrect.");
const std::string p_nSrcnAnBnCnDstv6 = "Time: +9s, Nix Routing\n"
"Route Path: (Node 0 to Node 4, Nix Vector: 001101)\n"
"Route Path: (Node 0 to Node 4, Nix Vector: 0111)\n"
"2001::200:ff:fe00:1 (Node 0) ----> fe80::200:ff:fe00:2 (Node 1)\n"
"fe80::200:ff:fe00:3 (Node 1) ----> fe80::200:ff:fe00:4 (Node 2)\n"
"fe80::200:ff:fe00:5 (Node 2) ----> fe80::200:ff:fe00:6 (Node 3)\n"