Additional modifications: ported to ns-3.36.1
Password to ZIP is 1234
-
TSN-enabled switch and nodes connected to Wi-Fi 6 AP and stations with its own switch.
-
The simulation uses PerfectClockModel for time sync
- Different clocks but synchronized by design
- An additional goal is to implement Fine Time Measurement (FTM) to obtain timestamps
- QoS allows setting of priority of transmissions in a multimodal, bidirectional system, and is built into the WiFi model.
- The specified topology has 3 STAs, 1 AP, 2 switches for the wireless and wired ends, and 3 wired nodes.
- I implemented applications running on all nodes, transferring data back and forth to simulate traffic.
- QoS allows deterministic transmission for high-priority real-time applications, minimizing the impact of concurrent best-effort traffic.
- Additionally, I installed the time-aware shaper on to the switches, as well as a porting process to ns-3.36 to utilize the new build system and enable newer features of the ns-3 stack to be used.
- Setup process of ns-3.34 (I used bake) and ns-3.36.
- Ubuntu 20.04 containerized instance using Distrobox over Arch Linux
-
sudo apt install g++ python3 python3-dev pkg-config sqlite3 cmake python3-setuptools git qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools gir1.2-goocanvas-2.0 python3-gi python3-gi-cairo python3-pygraphviz gir1.2-gtk-3.0 ipython3 openmpi-bin openmpi-common openmpi-doc libopenmpi-dev autoconf cvs bzr unrar gsl-bin libgsl-dev libgslcblas0 wireshark tcpdump sqlite libxml2 libxml2-dev libc6-dev libc6-dev-i386 libclang-dev llvm-dev automake python3-pip libxml2 libxml2-dev libboost-all-dev
-
git clone [https://gitlab.com/nsnam/ns-3-dev.git](https://gitlab.com/nsnam/ns-3-dev.git) && cd ns-3-dev
-
git checkout -b ns-3.36.1-branch ns-3.36.1
-
Extract the ZIP, paste it over the ns-3-dev/src folder, and accept any replacements of pre-existing files.
-
I have VS Code running on the same instance to utilize the Distrobox container’s libraries
-
The porting process resolves the non-termination issue in ns-3.34 since 3.36 supports concurrent execution of applications and Flowmon displays statistics after the execution is over. Additionally, CMake allows easier debugging through IDEs.
- launch.json for debugging ns-3.36
"version": "0.2.0", "configurations": [ { "name": "(gdb) Launch from scratch", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/build/scratch/TSNWifi/ns3.36.1-${fileBasenameNoExtension}-default", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "preLaunchTask": "Build", "environment": [ { "name": "LD_LIBRARY_PATH", "value": "${workspaceFolder}/build/lib/" } ],
- Pipe Launching for ns-3.34
{ "name": "(gdb) Pipe Launch", "type": "cppdbg", "request": "launch", //"program": "${workspaceFolder}/build/utils/ns3-dev-test-runner-debug", "program": "${workspaceFolder}/build/scratch/TSNWifi/${fileBasenameNoExtension}", //"args": ["--nWifi=12"], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "pipeTransport": { "debuggerPath": "", // leave blank "pipeProgram": "${workspaceFolder}/waf", // pipeArgs is essentially the entire waf command line arguments "pipeArgs": [ "--command-template", "\"", // opening double quote for command template "${debuggerCommand}", // gdb path and --interpreter arg already in debuggerCommand "--args", "%s", // Need to add --args %s to the gdb call "\"", // closing quote for command template "--run", "${fileBasenameNoExtension}", // Run call with the filename ], "quoteArgs":false, "pipeCwd": "" },
-
- Ubuntu 20.04 containerized instance using Distrobox over Arch Linux
The first step after configuration is enabling QosSupported in src/tsnwifi/wifi-setup.cc
mac.SetType ("ns3::ApWifiMac",
"EnableBeaconJitter", BooleanValue (false), "QosSupported", BooleanValue (true),
"Ssid", SsidValue (ssid));
Create InetSocketAddress objects for QoS tagging, based on AC Matrix followed in ns-3.34+
Ipv4Address apIp = APWifiInterfaces.GetAddress (0);
Ipv4Address staIP1 = staInterfaces.GetAddress (0);
Ipv4Address staIP2 = staInterfaces.GetAddress (1);
Ipv4Address staIP3 = staInterfaces.GetAddress (2);
InetSocketAddress apAddress (apIp, 10);
apAddress.SetTos (0x0);
InetSocketAddress sta1Address (staIP1, 10);
sta1Address.SetTos (0x2e);
InetSocketAddress sta2Address (staIP2, 10);
sta2Address.SetTos (0x18);
InetSocketAddress sta3Address (staIP3, 11);
sta3Address.SetTos (0x14);
TOS Matrix, ns-3.34 docs
- A topology is implemented to enable cross-communication between nodes on the network using UDP to generate traffic.
ApplicationContainer serverApp1
UdpServerHelper server1 (9);
serverApp1 = server1.Install (wireStaNodeContainer.Get (0));
serverApp1.Start (Seconds (0.0));
serverApp1.Stop (Seconds (simulationTime + 1));
UdpClientHelper client1 (wireInterfaces.GetAddress (0), 9);
client1.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
client1.SetAttribute ("Interval", TimeValue (Time ("0.002"))); // packet interval
client1.SetAttribute ("PacketSize", UintegerValue (200)); // packet size in bytes
ApplicationContainer clientApp1 = client1.Install (wifiStaNodeContainer.Get (nWifi - 3)); // 0 -> STA1
clientApp1.Start (Seconds (0.2));
clientApp1.Stop (Seconds (simulationTime + 1.2));
ApplicationContainer serverAppSTA2;
UdpServerHelper server2 (10);
serverAppSTA2 = server2.Install (wifiStaNodeContainer.Get (nWifi - 2)); // 1 -> STA2
serverAppSTA2.Start (Seconds (0));
serverAppSTA2.Stop (Seconds (simulationTime + 1));
UdpClientHelper clientAPforSTA2 (sta2Address, 10);
clientAPforSTA2.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
clientAPforSTA2.SetAttribute ("Interval", TimeValue (Time ("0.002"))); // packet interval
clientAPforSTA2.SetAttribute ("PacketSize", UintegerValue (100)); // packet size in bytes
ApplicationContainer clientApp2 = clientAPforSTA2.Install (APNodeContainer.Get(0)); // AP
clientApp2.Start (Seconds (0.2));
clientApp2.Stop (Seconds (simulationTime + 1.2));
ApplicationContainer serverAppAP;
UdpServerHelper server3 (10);
serverAppAP = server3.Install (APNodeContainer.Get(0));
serverAppAP.Start (Seconds (0.0));
serverAppAP.Stop (Seconds (simulationTime + 1));
UdpClientHelper clientSTA3forAP (apAddress, 10);
clientSTA3forAP.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
clientSTA3forAP.SetAttribute ("Interval", TimeValue (Time ("0.002"))); // packet interval
clientSTA3forAP.SetAttribute ("PacketSize", UintegerValue (100)); // packet size in bytes
ApplicationContainer clientApp3 = clientSTA3forAP.Install (wifiStaNodeContainer.Get (nWifi - 1));
clientApp3.Start (Seconds (0.2));
clientApp3.Stop (Seconds (simulationTime + 1.2));
ApplicationContainer serverAppSTA3;
UdpServerHelper server4(11);
serverAppSTA3 = server4.Install (wifiStaNodeContainer.Get (nWifi - 1)); // 2 -> STA3
serverAppSTA3.Start (Seconds (0.0));
serverAppSTA3.Stop (Seconds (simulationTime + 1));
UdpClientHelper clientAPforSTA3 (sta3Address, 11);
clientAPforSTA3.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
clientAPforSTA3.SetAttribute ("Interval", TimeValue (Time ("0.002"))); // packet interval
clientAPforSTA3.SetAttribute ("PacketSize", UintegerValue (100)); // packet size in bytes
ApplicationContainer clientApp4 = clientAPforSTA3.Install (APNodeContainer.Get(0)); // AP
clientApp4.Start (Seconds (0.2));
clientApp4.Stop (Seconds (simulationTime + 1.2));
UdpClientHelper clientSTA2forAP (apAddress, 10);
clientSTA2forAP.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
clientSTA2forAP.SetAttribute ("Interval", TimeValue (Time ("0.002"))); // packet interval
clientSTA2forAP.SetAttribute ("PacketSize", UintegerValue (100)); // packet size in bytes
ApplicationContainer clientApp5= clientSTA2forAP.Install (wifiStaNodeContainer.Get (nWifi - 2));
clientApp5.Start (Seconds (0.2));
clientApp5.Stop (Seconds (simulationTime + 1.2));
UdpClientHelper clientwireSTA2forSTA2 (sta2Address, 10);
clientwireSTA2forSTA2.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
clientwireSTA2forSTA2.SetAttribute ("Interval", TimeValue (Time ("0.002"))); // packet interval
clientwireSTA2forSTA2.SetAttribute ("PacketSize", UintegerValue (100)); // packet size in bytes
ApplicationContainer clientApp6= clientwireSTA2forSTA2.Install (wireStaNodeContainer.Get(1));
clientApp6.Start (Seconds (0.2));
clientApp6.Stop (Seconds (simulationTime + 1.2));
ApplicationContainer serverAppSTA1;
UdpServerHelper server5 (10);
serverAppSTA1 = server5.Install (wifiStaNodeContainer.Get (nWifi - 3));
serverAppSTA1.Start (Seconds (0.0));
serverAppSTA1.Stop (Seconds (simulationTime + 1));
UdpClientHelper clientwireSTA3forSTA1 (sta1Address, 10);
clientwireSTA3forSTA1.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
clientwireSTA3forSTA1.SetAttribute ("Interval", TimeValue (Time ("0.002"))); // packet interval
clientwireSTA3forSTA1.SetAttribute ("PacketSize", UintegerValue (100)); // packet size in bytes
ApplicationContainer clientApp7= clientwireSTA3forSTA1.Install (wireStaNodeContainer.Get(2));
clientApp7.Start (Seconds (0.2));
clientApp7.Stop (Seconds (simulationTime + 1.2));
-
Flowmon
- ns3::FlowMonitorHelper
- ns3::Ipv4HelperClassifier - statistics segregation per flow
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator iter = stats.begin (); iter != stats.end (); ++iter) { Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow (iter->first); NS_LOG_UNCOND("\n----Flow ID:" <<iter->first); NS_LOG_UNCOND("Src Addr " <<t.sourceAddress << " Dst Addr "<< t.destinationAddress); NS_LOG_UNCOND("Sent Packets=" <<iter->second.txPackets); NS_LOG_UNCOND("Received Packets =" <<iter->second.rxPackets); //NS_LOG_UNCOND("Lost Packets =" <<iter->second.txPackets-iter->second.rxPackets); NS_LOG_UNCOND("Packet delivery ratio =" <<iter->second.rxPackets*100/iter->second.txPackets << "%"); //NS_LOG_UNCOND("Packet loss ratio =" << (iter->second.txPackets-iter->second.rxPackets)*100/iter->second.txPackets << "%"); NS_LOG_UNCOND("Packet loss percentage =" << iter->second.txPackets-iter->second.rxPackets << "/" << iter->second.txPackets << "(" << (iter->second.txPackets-iter->second.rxPackets)*100/iter->second.txPackets << "%)"); NS_LOG_UNCOND("Avg. Delay =" << NanoSeconds(((iter->second.delaySum).GetInteger())/iter->second.rxPackets)); NS_LOG_UNCOND("Sum. Delay =" << iter->second.delaySum); NS_LOG_UNCOND("Avg. Jitter =" << NanoSeconds(((iter->second.jitterSum).GetInteger())/iter->second.rxPackets)); NS_LOG_UNCOND("Sum. Jitter =" <<iter->second.jitterSum); }
Dataset QoS ns-3 measurements.xlsx
- For a more accurate picture, a manual measurement using PCAP files is required.
// in TSNWifi.cc csma.EnablePcap ("TSNWifi-wire.pcap", APDevices.Get (0), true); csma.EnablePcap ("TSNWifi-wire", wireDevices.Get (0), true); csma.EnablePcap ("TSNWifi-Switch1-AP", switchFullLink.Get (1), true); csma.EnablePcap ("TSNWifi-Switch1-Node0", switch1Link.Get (0), true); csma.EnablePcap ("TSNWifi-Switch1-Switch0", switch1Link.Get (3), true); csma.EnablePcap ("TSNWifi-Switch0-Switch1", switchFullLink.Get (0), false); // in wifi-setup.cc phy.EnablePcap ("AccessPoint", m_netDeviceContainerAP.Get (0)); phy.EnablePcap ("StationBG", m_netDeviceContainerSTA.Get (0)); // STA1 (BG) phy.EnablePcap ("StationFG", m_netDeviceContainerSTA.Get (1)); // STA2 (FG)
I am using Wireshark to analyze traffic.