- 1 Installation and usage instructions
- 2 Further Reading
- 3 Protocol Stack
- 4 Additive/modified files & folders from the original fork, maintainer must keep those files & folders
- 5 Potential Problems
This repository is vessal of the IEEE802.11ah (Wi-Fi HaLow) protocol for the NS-3 network simulator, which comes from LeTian and his associates. Its NS-3 version is 3.23 with multiple modules updated to 3.25 to incorporate congestion control fixes for TCP traffic.
- This module includes support for:
- Restricted Access Window (RAW) with interface for dynamic configuration
- Traffic Indication Map (TIM) segmentation
- Energy consumption model
- Adaptive Modulation and Coding Scheme (MCS)
After installing Anaconda, we need to create two environments.
ns3
This environment is used to compilens3.
conda create -n ns3 python=2.7ai
This environment is used to run scripts relying onns3-ai
conda create -n ai python=3.9
# activate ai
conda activate ai
# pandas
pip install pandas
# tensorflow
conda install -c conda-forge cudatoolkit=11.2 cudnn=8.1.0
pip install tensorflow- train SNN (in
ai)
python Components/AI_SNN_Train.py- train RNN (in
ai)
python Components/AI_RNN_Train.py# switch to ai
conda activate ai
# add interfaces
cd src/ns3-ai/py_interface
pip install . --user1.5 Follow the instructions on https://www.nsnam.org/wiki/Installation to prepare all dependencies.
For Ubuntu 18.04, those are:
(please note that sudo apt-get -y install gsl-bin libgsl2 libgsl2:i386 is changed into sudo apt-get -y install gsl-bin because the other two packets are missing in Ubuntu 18.04)
sudo apt-get update
sudo apt-get -y install gcc g++ python-dev
sudo apt-get -y install qt4-dev-tools libqt4-dev
sudo apt-get -y install mercurial
sudo apt-get -y install bzr
sudo apt-get -y install cmake libc6-dev libc6-dev-i386 g++-multilib
sudo apt-get -y install gdb valgrind
sudo apt-get -y install gsl-bin
sudo apt-get -y install flex bison libfl-dev
sudo apt-get -y install tcpdump
sudo apt-get -y install sqlite sqlite3 libsqlite3-dev
sudo apt-get -y install libxml2 libxml2-dev
sudo apt-get -y install libgtk2.0-0 libgtk2.0-dev
sudo apt-get -y install vtun lxcThis step is to clean dynamic libraries (*.so files) in build . If you haven't built this project, you can jump this step.
./waf cleanIf you have already created RAW configuration files, you should jump this step and use them in run the simulation
# Contentions 2 (static)
./waf --run "RAW-generate --NRawSta=128 --NGroup=32 --NumSlot=1 --RAWConfigPath='./OptimalRawGroup/RawConfig-rca-contention-2.txt' --beaconinterval=1000000 --pageSliceCount=2 --pageSliceLen=1"If you use ahVisualizer start it first
- For rate control
- For Minstrel
__SDN_LAB_RA_MINSTREL_SNN_VINCENTto activateSNNin Vincent version (where the overhead of SNN is not considered)__SDN_LAB_RA_MINSTREL_SNNto activateSNN__SDN_LAB_RA_MINSTREL_SNN_PLUSto activateSNN_PLUS__SDN_LAB_RA_MINSTREL_AI_DISTto activateMINSTREL_AI_DIST(where AI is implemented in STAs and DIST means distributes).
- For Minstrel
__SDN_LAB_DEBUGto activate debug mode
rate control is set to__SDN_LAB_RA_MINSTREL
src\wifi\ap-wifi-mac:ApWifiMac(),SendOneBeacon(),Receive()src\wifi\yans-wifi-phy:EndReceive()-D__SDN_LAB_PHY_PACKET_SIZE_DATA=to track physical layer data packet size-D__SDN_LAB_PHY_PACKET_SIZE_BEACON=to additively track physical beacon packet size
The macro definition is added in
CXXFLAGS. For example,CXXFLAGS="-Dxxx=yy",xxxis the macro definition andyyis the replacement ofxxx. Please note that the replacement is not necessary especially in the conditional compilation.
RAW configuration must be in line with TIM and page configuration. If a RAW group is reserved for a station in beacon interval that does not correspond to its TIM, station will be asleep during that RAW.
-
File
projectname: the project name (default atrca)
-
Hardware
hwNoiseFigure: the noise figure (because the amplifier in the circuit increases the noise), by default at6.8(dB)
-
Rate Adaption Algorithm
isRAoptimal: when the AP receives a packet, it will chose the best rate based on the relative distance from the sender.raOptimalBERThreshold: the BER to decide the rate, by default at10e-8
isRAconstantDataMode: the MCS we use, by default atMCS2_0
isRAidealisRAaarfisRAamrrisRAMinstrelraMinstrelLookAroundRate: Minstrel lookaround rate, by default at10(%)
-
Location
- The shape of the boundary
isLocRectangularisLocCircle
rho: Maximal distance between AP and stations in m- How stations are scattered
isLocRandomisLocUniformlocUniformXlocUniformY
- The shape of the boundary
-
Mobility
- Mobility models
isMobStaticisMobConstantisMobRandomWaypointisMobRandomWalk
speedHoldTime: the time to hold the speed- Speed Range
speedMin: the minimal speed in m/sspeedMax: the maximal speed in m/s
- The fixed speed
speedConstantXspeedConstantY
- Mobility models
-
RAW related parameters
-
NRawSta: Number of stations supporting RAW. NRawSta equals the largest AID specified in RAWConfigFile. -
RAWConfigFile: RAW configuration is stored in this file.
The default RAWConfigFile "./OptimalRawGroup/RawConfig-32-2-2.txt" sets 2 RPSs (RAW Parameter Sets) to be broadcasted with beacons in cycles (e.g. Beacon1: RPS1, Beacon2: RPS2, Beacon3: RPS1, Beacon4: RPS2, ...). The first RPS contains 2 RAW groups for 63 stations, each RAW group contains 2 RAW slots. The second RPS contains 1 RAW group for 4 stations (64-67), where the RAW group contains 3 slots. This file consists of 6 lines:2 2 0 1 1 200 2 0 1 29 0 1 1 200 2 0 30 63 1 0 1 1 220 3 0 64 67line 1: NRPS = number of RPS elements line x: NRAW_k = number of RAW Groups in the RPS k; x = (NRAW_0 + NRAW_1 + ... + NRAW_(k-1)) + 1 + k; NRAW_0 = 0
for RPS number k=1, line x=0+1+1=2 contains information on number of RAW groups in the RPS
for RPS number k=2 and NRAW_1=2 (from line 2), line x=0+2+1+2=5 contains information on number of RAW groups in the RPS
line 3, line 4 and line 6: configuration of each individual RAW group, including
RawControl: Whether RAW can be accessed by any stations within the RAW group or only the paged stations within the RAW group.CrossSlotBoundary: Whether STAs are allowed to transmit after the assigned RAW slot boundary.SlotFormat: Format of RAW slot count.NRawSlotCount: Used for calculation of RAW slot duration.NRawSlotNum: Number of slots per RAW group.Page: Page index of the subset of AIDs.Aid_start: Station with the lowest AID allocated in the RAW.Aid_end: Station with the highest AID allocated in the RAW. Notes:RawControl: currently set to 0, RAW can be accessed by any stations within the RAW group.CrossSlotBoundary: currenty set to 1, only cross slot boundary are supported.- RAW slot duration = 500 us +
NRawSlotCount* 120 us,NRawSlotCountis y = 11(8) bits length whenSlotFormatis set to 1(0), andNRawSlotNumis (14 - y) bits length. - The above RAWConfigFile assumes BeaconInterval is 102400 us. Users can adjust the parameters based on their own needs.
-
-
Wi-Fi mode parameters
DataMode: Data mode.datarate: Data rate of data mode.bandWidth: BandWidth of data mode.
Relation between the above 3 parameters and MCS is described in file "MCStoWifiMode".
-
Other parameters
SimulationTime: Simulatiom time in seconds after all stations get associated with AP.payloadSize: Size of payload.BeaconInterval: Beacon interval time in us.UdpInterval: Traffic mode, station send one packet every UdpInterval seconds.Nsta: Number of total stations.seed: Seed of RandomVariableStream.TrafficPath: Include traffic of each stations, packet sending interval can be automatically calcualted based on payloadSize. The above TrafficPath "./OptimalRawGroup/traffic/data-32-0.82.txt" contains traffic of 32 stations, and the total traffic is 0.82 Mbps.S1g1MfieldEnabled: Packet using 1 Mhz bandwidth if set to "true".
-
TIM and page slice parameters
pagePeriod: Number of Beacon Intervals between DTIM beacons that carry Page Slice element for the associated pagepageIndex: Index of the page (0-3) whose slices are served during beacon intervals within a page period, default value is 0pageSliceLength: Number of blocks in each TIM for the associated page except for the last TIM (1-31)pageSliceCount: Number of TIMs in a single page period (0-31), value 0 has special meaningblockOffset: The 1st page slice starts with the block with blockOffset number, default value is 0timOffset: Offset in number of Beacon Intervals from the DTIM that carries the first page slice of the page, default value is 0 For example,./waf --run "test --pagePeriod=4 --pageSliceLength=8 --pageSliceCount=4"
pagePeriod=4: every 4th beacon is DTIM beacon that carries Page Slice element for pageIndex=0
pageSliceLength=8: each page slice cosists of 8 blocks, meaning that each page slice (PS) accomodates up to 512 stations (8 blocks * 8 subblocks * 8 stations)
(slice0: 1-512, slice1: 513-1024, slice2: 1025-1536, slice3: 1537-2048)
The last page slice can have different length.
pageSliceCount=4: 4 TIMs are scheduled in one page period.
To configure a single page slice (whole page encoded in a single page slice), it is neccessary to set
pageSliceCountto 0 andpageSliceLengthto 1.
- Compile
- Testing the protocol stack & other RA algorithms
CXXFLAGS="-std=c++11 -D__SDN_LAB_DEBUG -D__SDN_LAB_PHY_PACKET_SIZE_DATA=166 -D__SDN_LAB_PHY_PACKET_SIZE_BEACON=71" ./waf configure --disable-examples --disable-tests - Minstrel-SNN (Vincent)
CXXFLAGS="-std=c++11 -D__SDN_LAB_DEBUG -D__SDN_LAB_RA_MINSTREL_SNN_VINCENT" ./waf configure --disable-examples --disable-tests - Minstrel-SNN
CXXFLAGS="-std=c++11 -D__SDN_LAB_DEBUG -D__SDN_LAB_RA_MINSTREL_SNN" ./waf configure --disable-examples --disable-tests - Minstrel-SNN+
CXXFLAGS="-std=c++11 -D__SDN_LAB_RA_MINSTREL_SNN_PLUS -D__SDN_LAB_DEBUG -D__SDN_LAB_PHY_PACKET_SIZE_DATA=166 -D__SDN_LAB_DEBUG_NN" ./waf configure --disable-examples --disable-tests
- Testing the protocol stack & other RA algorithms
- Run
Use 1 STA and simulate for 20 seconds
./waf --run "rca --seed=1 --isRAMinstrel --simulationTime=20 --payloadSize=100 --pagePeriod=1 --pageSliceLength=1 --pageSliceCount=0 --isLocRectangular --rho=250 --isLocRandom --isMobRandomWalk --speedHoldTime=2 --speedMin=83.3333 --speedMax=127.778"
- Vincent SNN & others rates
This recovers the simulation results inImproving The Minstrel Rate Adaptation Algorithm using Shallow Neural Networks in IEEE 802.11ahOpen another terminal to activate./Scripts/vincent_scenario.sh
SNNpython Components/AI_SNN.py
- RSNN
python ./Components/AI_RSNN_TimeLSTM1.py
- Generate data useful for Neural Network
Not using MAC address shift, i.e.,macAddrShift=0. Seeds should be treated differently. This can be used to trainbatch size=124or take each station file as an individual input.Using MAC address shift, i.e.,./Scripts/generate_nn_data.sh
macAddrShift=224. Therefore, you can merge all seeds into one folder to support differentbatch size../Scripts/generate_nn_data.sh 1
Before running any matlab code, you need to initiate the environment first by using init.
- Throughput vs Time
@foldername: the folername
@seeds: the seed range (a number vector)
@jumptime: the time we jump
@duration: the durition we take records
@ColNumTime: the column number for time
@ColNumTransient: the column number for transient power
@ColNumAverage: the column number for average power
@PlotTransient: plot the transient power (default: true)
@PlotAverage: plot the average power (default: false)DrawThroughputVsTime("STA128_C00_rec_human_2"); - Average Throughput (end) vs hold time
@projectnameprefix: the project name prefix
@holdtime: the holdtime range(a number vector)
@seeds: the seed range (a number vector)
@endtime: the endtime point (a scalar)
@ColNumTime: the column number for time
@ColNumAverage: the column number for average powerDrawThroughputVsHoldTime("STA128_C00_rec_human_");
For more information on the implementation of the IEEE 802.11ah module for ns-3, check recent WNS3 paper on ResearchGate.
Le Tian, Amina Sljivo, Serena Santi, Eli De Poorter, Jeroen Hoebeke, Jeroen Famaey. Extension of the IEEE 802.11ah NS-3 Simulation Module. Workshop on ns-3 (WNS3), 2018.
-
Type&SubtypeType Type Value Subtype Subtype Value Management 00 (0) Control 01(1) Control Wrapper 0111(7) Control 01(1) Block Ack Request 1000(8) Control 01(1) Block Ack 1001(9) Control 01(1) PS-Poll 1010(10) Control 01(1) RTC 1011(11) Control 01(1) CTS 1100(12) Control 01(1) ACK 1101(13) Data 10(2) Data 0000(0) Data 10(2) QoS Data 1000(8) Data 10(2) QoS Data + CF-ACK 1001(9) Data 10(2) QoS Data + QoS Data + CF-Poll 1010(10) Data 10(2) QoS Data + CF-ACK + CF-Poll 1011(11) Data 10(2) QoS Null (no data) 1100(12) Data 10(2) QoS CF-Poll (no data) 1110(14) Data 10(2) QoS CF-ACK + CF-Poll (no data) 1111(8) Extension 11(3) PS-Poll
ThePS-POLL Mechanismis the Legacy Power save mechanism. As the name suggestsPS-POLLstands for Power Save Polling. The Access point uses the TIM information element to indicate to the station that there is unicast data buffered for the WLAN station at the Access Point.
The station wakes up at Listen Interval/DTIM time to receive the beacon from the Access Point.
It then checks the TIM Information element to check whether its Association ID is set in The TIM Information element.
If the Association ID of the Station is set – then it sends a specific frame to retrieve data from the AP. This Frame is termed as a PS-Poll frame.
On receiving aPS-POLLframe from the 802.11 station, the AP would ACK the PS-Poll frame and then sends a single data packet to the Station. If there are more data packets queued for the 802.11 Station at the Access Point, the Access Point sets theMore Data bitin the frame control to true.
The WLAN (802.11) station processes the received data frame and on processing the frame control field realizes that it has more data queued at the Access point. The WLAN (802.11) station will send anotherPS-Pollframe to retrieve another data packet. When theMore Data bitis set to zero – the Access Point has no more data uffered for the WLAN station and the station can go to sleep.
In legacy Power save devices, for transmitting eachPS-Pollframe the 802.11 station has to contend for the medium.
-
ToDS&FromDS
There are 5 Mac address:SA: source addressDA: destination addressTA: transmitter addressRA: receiver addressBSSID: basic service set identifier.
BSSID is a Layer 2 identifier of the BSS
- To DS = 0 and From DS = 0
A simple beacon frame, which is originated from the AP radio MAC address (BSSID, transmitter and source addresses) to all mobile clients (receiver and destination addresses). Management, control and IBSS(ad-hoc) frames are dedicated to wireless networking only.
Address 1 – RA=DA, ff:ff:ff:ff:ff:ff – broadcast to all mobile clients
Address 2 – TA=SA, 84:24:8d:c1:24:20 – AP BSSID
Address 3 – BSSID, 84:24:8d:c1:24:20 – AP BSSID - To DS = 1 and From DS = 0
A wireless data frame is being sent from a mobile client to wired network. For example, ICMP echo request ping test from the mobile client via the AP to the default gateway.
Address 1 – RA=BSSID, 84:24:8d:c1:24:20 – AP BSSID
Address 2 – TA=SA, cc:44:63:1b:2d:fa – mobile client’s MAC address
Address 3 – DA, 74:8e:f8:4f:02:76 - To DS = 0 and From DS = 1
A wireless data frame is being sent from the wired network to the mobile client associated to the AP.
Address 1 – RA=DA, cc:44:63:1b:2d:fa – mobile client’s MAC address
Address 2 – TA=BSSID, 84:24:8d:c1:24:20 – AP BSSID
Address 3 – SA, 74:8e:f8:4f:02:76 - To DS = 1 and From DS = 1
Typical mesh environment (AP to AP).
Address 1 – RA, f0:5c:19:65:64:30 – AP BSSID
Address 2 – TA, f0:5c:19:65:60:f1 – AP BSSID
Address 3 – DA, cc:44:63:1b:2d:fa – mobile client’s MAC address
Address 4 – SA, 74:8e:f8:4f:02:76
In Figure, AP is static at a coordinate,
; STAs are randomly scattered around the AP within a circle at a radius of r with an arbitrary speed vector. The speed vector for each STA changes for each second: its absolute value is from 0.75 m/s to 1.5 m/s and its direction is from 0 to 2π. Please note that this vector is limited inside the circle boundary and so is STAs' moving trajectory. Through tracking the trajectory of a STA,
, at a time point. The distance between the STA and the AP is,
.
When a STA is able to moving out of the range, we should limit the moving angle range. To achieve this goal, we need to calculate the angle from STA to AP first. The detail is given in the figure below.

Then we calculate the half moving range α and the whole range based on the angle from STA to AP. Then we calculate the range based on the relationship between the start and the end, and arbitarily choose an angle from the range to be the new moving direction. The detail is given in the figure below.
/scatch/rca/s1g-rca.ccIn the main function, we setMac Layer nameandother parametersand transfer this parameter toWifiHelper::Install
S1gWifiMacHelperinheritsQosWifiMacHelper;QosWifiMacHelperhas a memeberObjectFactory m_macthat acceptsMac Layer nameandother parameters.... int main(int argc, char *argv[]){ ... WifiHelper wifi = WifiHelper::Default(); S1gWifiMacHelper mac = S1gWifiMacHelper::Default(); // set the configuration of this mac mac.SetType ("ns3::ApWifiMac", "Ssid", SsidValue (ssid), "BeaconInterval", TimeValue (MicroSeconds(config.BeaconInterval)), "NRawStations", UintegerValue (config.NRawSta), "RPSsetup", RPSVectorValue (config.rps), "PageSliceSet", pageSliceValue (config.pageS), "TIMSet", TIMValue (config.tim)); NetDeviceContainer apDevice = wifi.Install(phy, mac, wifiApNode); // set Sta Mac & Phy mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid), "ActiveProbing", BooleanValue(false)); NetDeviceContainer staDevice = wifi.Install(phy, mac, wifiStaNode); ... }
/src/wifi/helper/wifi-helper.ccmacHelper.Create ()useObjectFactory m_macto create the actual Mac objectNetDeviceContainer WifiHelper::Install (const WifiPhyHelper &phyHelper, const WifiMacHelper &macHelper, NodeContainer c) const{ NetDeviceContainer devices; for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) { Ptr<Node> node = *i; Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> (); Ptr<WifiRemoteStationManager> manager = m_stationManager.Create<WifiRemoteStationManager> (); Ptr<WifiMac> mac = macHelper.Create (); Ptr<WifiPhy> phy = phyHelper.Create (node, device); mac->SetAddress (Mac48Address::Allocate ()); mac->ConfigureStandard (m_standard); phy->ConfigureStandard (m_standard); device->SetMac (mac); device->SetPhy (phy); device->SetRemoteStationManager (manager); node->AddDevice (device); devices.Add (device); NS_LOG_DEBUG ("node=" << node << ", mob=" << node->GetObject<MobilityModel> ()); } return devices; }
/src/wifi/helper/qos-wifi-mac-helper.ccPtr<WifiMac> QosWifiMacHelper::Create (void) const{ Ptr<WifiMac> mac = m_mac.Create<WifiMac> (); Setup (mac, AC_VO, "VO_EdcaTxopN"); Setup (mac, AC_VI, "VI_EdcaTxopN"); Setup (mac, AC_BE, "BE_EdcaTxopN"); Setup (mac, AC_BK, "BK_EdcaTxopN"); return mac; }
In src/wifi/model/regular-wifi-mac.cc
When ApWifiMac and StaWifiMac initialise themselves, they will call their parent constructor at m_rxMiddle->SetForwardCallback (MakeCallback (&RegularWifiMac::Receive, this));. Here this points at the instances of ApWifiMac and StaWifiMac even in their parent constructor.
class ApWifiMac : public RegularWifiMac;
...
class StaWifiMac : public RegularWifiMac;
...
RegularWifiMac::RegularWifiMac ()
{
...
m_rxMiddle = new MacRxMiddle ();
m_rxMiddle->SetForwardCallback (MakeCallback (&RegularWifiMac::Receive, this));
m_txMiddle = new MacTxMiddle ();
m_low = CreateObject<MacLow> ();
m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
m_dcfManager = new DcfManager ();
m_dcfManager->SetupLowListener (m_low);
m_dca = CreateObject<DcaTxop> ();
m_dca->SetLow (m_low);
m_dca->SetManager (m_dcfManager);
m_dca->SetTxMiddle (m_txMiddle);
m_dca->SetTxOkCallback (MakeCallback (&RegularWifiMac::TxOk, this));
m_dca->SetTxFailedCallback (MakeCallback (&RegularWifiMac::TxFailed, this));
m_dca->GetQueue()->TraceConnect("PacketDropped", "", MakeCallback(&RegularWifiMac::OnQueuePacketDropped, this));
m_dca->TraceConnect("Collision", "", MakeCallback(&RegularWifiMac::OnCollision, this));
m_dca->TraceConnect("TransmissionWillCrossRAWBoundary", "", MakeCallback(&RegularWifiMac::OnTransmissionWillCrossRAWBoundary, this));
...
}4 Additive/modified files & folders from the original fork, maintainer must keep those files & folders
.gitignoreREADME.mdLICENSE
optimal-RAW-algorithm-fixedraw.sh, README, RELEASE_NOTES, run.pbs
Mac.h: define the broadcast mac addressMcs.h: define the MCS we use and the index we use. (Also, Vincent's index format is preserved)Setting.h: set the configuration across all layers and componentsPacketContext.h: the context of a packet across the physical layer to the MAC layerStation.h: store the data associated with station andStationList.h: combine all stations into a list to manageNNData.h: the data structure shared betweenPythonandC/C++
scatch/rca/s1g-rca
s1g-rca.h// extra headers #include "Modules/Toolbox/FileManager.h" #include "Components/Settings.h" #include "Components/StationList.h" #include "Components/Station.h" ... // extra namespaces using namespace Toolbox; using namespace SdnLab; ... /*** self-defined varables ***/ FileManager fm; Settings settings; /*** self-defined functions ***/ void PrintStatistics(double pastTime, unsigned int pastSentPackets, unsigned int pastSuccessfulPackets);
s1g-rca.cc... /*** self-defined marcos ***/ // look around rate #ifndef __SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE #define __SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE 10 #endif // __SDN_LAB_SET_WIFIMANAGER(dr): define the wifimanager // __SDN_LAB_SET_STATISTIC_PATH(sets): define the file path to storage statistics #ifdef __SDN_LAB_DEBUG #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::MinstrelWifiManager") #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_MINSTREL #else #if defined(__SDN_LAB_RA_CONST_RATE) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", "DataMode", dr, "ControlMode", dr) #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_CONSTRATE #elif defined(__SDN_LAB_RA_AMRR) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::AmrrWifiManager") #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_AMRR #elif defined(__SDN_LAB_RA_AARF) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::AarfWifiManager") #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_AARF #elif defined(__SDN_LAB_RA_MINSTREL) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::MinstrelWifiManager"); #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_MINSTREL + sets.__SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE + sets.REPORT_THROUGHPUT_SUFFIX; #elif defined(__SDN_LAB_RA_MINSTREL_SNN) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::MinstrelWifiManager"); #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_MINSTREL_SNN + sets.__SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE + sets.REPORT_THROUGHPUT_SUFFIX; #elif defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::MinstrelWifiManager"); #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_MINSTREL_SNN_VINCENT + sets.__SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE + sets.REPORT_THROUGHPUT_SUFFIX; #elif defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::MinstrelWifiManager"); #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_MINSTREL_SNN_PLUS + sets.__SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE + sets.REPORT_THROUGHPUT_SUFFIX; #elif defined(__SDN_LAB_RA_MINSTREL_AI_DIST) #define __SDN_LAB_SET_WIFIMANAGER(dr) wifi.SetRemoteStationManager("ns3::MinstrelWifiManager"); #define __SDN_LAB_SET_STATISTIC_PATH(sets) sets.PathProjectReport() + sets.REPORT_THROUGHPUT_MINSTREL_AI_DIST + sets.__SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE + sets.REPORT_THROUGHPUT_SUFFIX; #else #define __SDN_LAB_SET_WIFIMANAGER(dr) \ cout << settings.ERR_WIFI_MANAGER_UNDEFINED << endl; \ NS_ASSERT(false); #define __SDN_LAB_SET_STATISTIC_PATH(sets) "" #endif #endif ... // print the throughput void PrintStatistics(double pastTime, unsigned int pastSentPackets, unsigned int pastSuccessfulPackets){ // set the throughput file path based on the wifi manager string path = __SDN_LAB_SET_STATISTIC_PATH(settings); // do next when the path is not empty if(!path.empty()){ // get the current time double curTime = Simulator::Now().GetSeconds(); // calculate statistics // calculate statistics - total unsigned int totalSentPackets = 0; unsigned int totalSuccessfulPackets = 0; double totalThroughput = 0; for (int i = 0; i < config.Nsta; i++){ totalSentPackets += stats.get(i).NumberOfSentPackets; totalSuccessfulPackets += stats.get(i).NumberOfSuccessfulPackets; } totalThroughput = totalSuccessfulPackets * config.payloadSize * 8 / (curTime * 1000000.0); // calculate statistics - transient unsigned int curSentPackets = totalSentPackets - pastSentPackets; unsigned int curSuccessfulPackets = totalSuccessfulPackets - pastSuccessfulPackets; double curThroughput = curSuccessfulPackets * config.payloadSize * 8 / ((curTime - pastTime) * 1000000.0); // write to file if(fm.Open(path) == 200){ fm.AddCSVItem(curTime); // additive fm.AddCSVItem(curSentPackets); fm.AddCSVItem(curSuccessfulPackets); fm.AddCSVItem(curThroughput); // Mbits/s // total fm.AddCSVItem(totalSentPackets); fm.AddCSVItem(totalSuccessfulPackets); fm.AddCSVItem(totalThroughput, true); // Mbits/s fm.Close(); } // schedule the next Simulator::Schedule(Seconds(1), &PrintStatistics, curTime, totalSentPackets, totalSuccessfulPackets); } } ... int main(int argc, char *argv[]) { // config settings.SetProjectName("rca"); FileManager::CreatePath(settings.PathProject()); // config - create folders NS_ASSERT(FileManager::CreatePath(settings.PathProjectDebug()) == 200); // debug NS_ASSERT(FileManager::CreatePath(settings.PathProjectTmp()) == 200); // tmp NS_ASSERT(FileManager::CreatePath(settings.PathProjectReport()) == 200); // report // reset NSSFile location config.NSSFile = settings.PathProjectTmp() + config.trafficType + "_" + std::to_string(config.Nsta) + "sta_" + std::to_string(config.NGroup) + "Group_" + std::to_string(config.NRawSlotNum) + "slots_" + std::to_string(config.payloadSize) + "payload_" + std::to_string(config.totaltraffic) + "Mbps_" + std::to_string(config.BeaconInterval) + "BI" + ".nss"; ... // set the rate adaption __SDN_LAB_SET_WIFIMANAGER(DataRate); ... // schedule the througput Simulator::Schedule(Seconds(1), &PrintStatistics, 0, 0, 0); }
scatch/rca/Configuration
Configuration.h// 3rd party headers #include <cmath> // support abs ... struct Configuration { /** self-defined parameters **/ // locations in x and y axis // any -1 of these two location parameters means the location is given randomly (in the radius of `rho`) double locX = -1; double locY = -1; // the speed configuration double mobilitySpeedMin = 0; double mobilitySpeedMax = 0; double mobilityAcceleration = 0; ... }
Configuration.ccConfiguration::Configuration(int argc, char *argv[]) { ... /** self-defined parameters **/ cmd.AddValue("locX", "location in X", locX); cmd.AddValue("locY", "location in Y", locY); cmd.AddValue("mobilitySpeedMin", "the minimal speed", mobilitySpeedMin); cmd.AddValue("mobilitySpeedMax", "the maximal speed", mobilitySpeedMax); cmd.AddValue("mobilityAcceleration", "the speed acceleration", mobilityAcceleration); ... // parse input cmd.Parse(argc, argv); // format input this->mobilityAcceleration = abs(this->mobilityAcceleration); }
/src/wifi/model/wifi-remote-station-manager
wifi-remote-station-manager.hclass WifiRemoteStationManager : public Object{ ... // NN based methods #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) // set a MCS candidate as the initial (calling `DoSetMcsPredict` of its child's method) void SetMcsPredict(unsigned int mcs); // actually set a mcs to a station virtual void DoSetMcsPredict(WifiRemoteStation *station, unsigned int mcs); #endif ... }
wifi-remote-station-manager.cc... #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) // set a MCS candidate as the initial (calling `DoSetMcsPredict` of its child's method) void SetMcsPredict(Mac48Address address, const WifiMacHeader *header, unsigned int mcs){ WifiRemoteStation *station = Lookup(address, header); DoSetMcsPredict(station, mcs); } // the father method does nothing void WifiRemoteStationManager::DoSetMcsPredict(WifiRemoteStation *station, unsigned int mcs){}; #endif ...
/src/wifi/model/wifi-remote-station-manager
wifi-remote-station-manager.hclass MinstrelWifiManager : public WifiRemoteStationManager { /*** NN based methods ***/ #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) // set a MCS candidate as the initial virtual void DoSetMcsPredict(WifiRemoteStation *station, unsigned int mcs); #endif }
wifi-remote-station-manager.cc// extra headers #include "Components/Mcs.h" // extra namespace using namespace SdnLab; ... // extra macro // look around rate #ifndef __SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE #define __SDN_LAB_RA_MINSTREL_LOOK_AROUND_RATE 10 #endif // find mcs #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) #define __SDN_LAB_MINSTREL_WIFI_MANAGER_FIND_MCS_IDX(idx, station) \ size_t i; \ for(i = 0; i < station->m_state->m_operationalRateSet.size(); ++i){ \ if(Mcs::FromModeName(station->m_state->m_operationalRateSet[i].GetUniqueName()) == station->mcs){ \ break; \ } \ } \ idx = i #else #define __SDN_LAB_MINSTREL_WIFI_MANAGER_FIND_MCS_IDX(idx, station) idx=GetNextSample (station) #endif ... struct MinstrelWifiRemoteStation : public WifiRemoteStation { ... unsigned int mcs; // MCS predicted by NN } /*** NN based methods ***/ #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) // set a MCS candidate as the initial void MinstrelWifiManager::DoSetMcsPredict(WifiRemoteStation *station, unsigned int mcs){ MinstrelWifiRemoteStation * curStation = (MinstrelWifiRemoteStation *) station; curStation->mcs = mcs; } #endif ... uint32_t MinstrelWifiManager::FindRate (MinstrelWifiRemoteStation *station){ if ( (((100 * station->m_sampleCount) / (station->m_sampleCount + station->m_packetCount )) < m_lookAroundRate) && (coinFlip == 1) ){ ... __SDN_LAB_MINSTREL_WIFI_MANAGER_FIND_MCS_IDX(idx, station); ... } }
src/wifi/model/regular-wifi-mac
regular-wifi-mac.h#pragma once ... // extra headers #include "Components/PacketContext.h" ... // add packet context as an extra parameter virtual void Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, SdnLab::PacketContext context = SdnLab::PacketContext());
regular-wifi-mac.c// 3rd party namespaces using namespace SdnLab; ... void RegularWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, PacketContext packetContext){ ... }
src/wifi/model/ap-wifi-mac
ap-wifi-mac.h// extra headers #include "Modules/Toolbox/FileManager.h" #include "Components/Settings.h" #include "Components/PacketContext.h" #include "Components/StationList.h" #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) #include "Components/NNData.h" #include "Components/OverheadSNN.h" #endif ... // add PacketContext as an extra parameter virtual void Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, SdnLab::PacketContext context); ... // self-defined parameters #ifdef __SDN_LAB_DEBUG Toolbox::FileManager fm; // FileManger SdnLab::Settings settings; // Settings SdnLab::StationList stationList = SdnLab::StationListFactory::Create(4424, 5); #else SdnLab::StationList stationList = SdnLab::StationListFactory::Create(4259344, 8191); #endif #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) SdnLab::NNData nnData; #endif SdnLab::PacketContext context = SdnLab::PacketContext();
ap-wifi-mac.c// extra headers #include "Modules/Toolbox/FileManager.h" #include "Components/Settings.h" #include "Components/Mac.h" // extra namespaces using namespace Toolbox; using namespace SdnLab; /*** self defined macros ***/ // debug #ifdef __SDN_LAB_DEBUG #define __SDN_LAB_AP_WIFI_MAC_REPROT_MEMORY_COST(stalist, set) \ string path = set.PathProjectReport() + set.REPORT_MEMORY_COST; \ StationListFactory::Summary(path); \ cout << "Memory size for each station = " << stalist->GetStaMemSize() << " (bytes)" << '\n'; #define __SDN_LAB_AP_WIFI_MAC_PRINT_STATIONLIST(stalist, set) \ if(stalist){ \ Time time = Simulator::Now(); \ string path = set.PathProjectDebug() + set.TRACK_FILE_AP_WIFI_MAC_STALIST + to_string(time.GetSeconds()) + set.TRACK_FILE_FORM_SUFFIX; \ stalist->Summary2File(path); \ } #define __SDN_LAB_AP_WIFI_MAC_PRINT_DATA_TO_STATIONLIST(stalist, set) \ if(stalist){ \ Time time = Simulator::Now(); \ string path = set.PathProjectDebug() + set.TRACK_FILE_AP_WIFI_MAC_NN_INPUT + to_string(time.GetSeconds()) + set.TRACK_FILE_FORM_SUFFIX; \ stalist->Summary2File(path, __SDN_LAB_NNDATA_LEN); \ } #define __SDN_LAB_AP_WIFI_MAC_PRINT_DATA_FROM_STATIONLIST(stalist, set) \ if(stalist){ \ Time time = Simulator::Now(); \ string path = set.PathProjectDebug() + set.TRACK_FILE_AP_WIFI_MAC_NN_OUTPUT + to_string(time.GetSeconds()) + set.TRACK_FILE_FORM_SUFFIX; \ stalist->Summary2File(path, __SDN_LAB_NNDATA_LEN, true); \ } #define __SDN_LAB_AP_WIFI_MAC_PRINT_RECE(fm, set) \ if(fm.Open((set.PathProjectDebug() + set.TRACK_FILE_AP_WIFI_MAC_RECE))==200){ \ fm.AddCSVItem(context.IsEmpty()); \ fm.AddCSVItem(macPacketSize); \ fm.AddCSVItem(phyPacketSize); \ fm.AddCSVItem(context.GetStartTime()); \ fm.AddCSVItem(context.GetEndTime()); \ fm.AddCSVItem(context.GetSnr()); \ fm.AddCSVItem(context.GetRxPower()); \ fm.AddCSVItem(context.GetMCSIn()); \ fm.AddCSVItem(context.IsReceived(), true); \ fm.Close(); \ } #define __SDN_LAB_AP_WIFI_MAC_PRINT_RECE_MAC_ADDR(set, macPacketSize, context) \ std::fstream file; \ file.open(set.PathProjectDebug() + set.TRACK_FILE_AP_WIFI_MAC_RECE_ADDR, std::fstream::in | std::fstream::app); \ file << macPacketSize << ','; \ file << context.GetSourMacAddr() << ','; \ file << context.GetDestMacAddr() << ','; \ file << context.GetTxMacAddr() << ','; \ file << context.GetRxMacAddr() << ','; \ file << context.GetStartTime() << ','; \ file << context.GetEndTime() << ','; \ file << context.GetMCSIn() << ','; \ file << '\n'; \ file.close(); #else #define __SDN_LAB_AP_WIFI_MAC_REPROT_MEMORY_COST(stalist, set) #define __SDN_LAB_AP_WIFI_MAC_PRINT_STATIONLIST(stalist, set) #define __SDN_LAB_AP_WIFI_MAC_PRINT_DATA_TO_STATIONLIST(stalist, set) #define __SDN_LAB_AP_WIFI_MAC_PRINT_DATA_FROM_STATIONLIST(stalist, set) #define __SDN_LAB_AP_WIFI_MAC_PRINT_RECE(fm, set) #define __SDN_LAB_AP_WIFI_MAC_PRINT_RECE_MAC_ADDR(set, macPacketSize, context) #endif #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) #define __SDN_LAB_PREDICT_AT_AP(stalist, context) \ stalist->PredictMCS(); \ context.Clear(); \ context.SetOverhead(OverheadSNN::Create(stalist)); #else #define __SDN_LAB_PREDICT_AT_AP(stalist, context) #endif // clear the station list ApWifiMac::ApWifiMac (){ ... // debug __SDN_LAB_AP_WIFI_MAC_REPROT_MEMORY_COST(this->stationList, this->settings); } ApWifiMac::~ApWifiMac{ ... // clear the station list StationList::Destory(this->stationList); } ... // ApWifiMac::Receive: add PacketContext as an extra parameter void ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, PacketContext context){ ... uint32_t macPacketSize = packet->GetSize(); uint32_t phyPacketSize = 0; Mac48Address sourMacAddr = __SDN_LAB_MAC_BROADCAST_ADDR; // set the source Mac default address is broadcast if (!context.isEmpty()){ context.SetMacPacketSize(macPacketSize); context.SetAllMacAddr(hdr); phyPacketSize = context.GetPhyPacketSize(); sourMacAddr = context.GetSourMacAddr(); } // add context to StationList this->stationList->AddStationOrContext(context); // debug - print the packet information __SDN_LAB_AP_WIFI_MAC_PRINT_RECE(this->filemanager, this->settings); __SDN_LAB_AP_WIFI_MAC_PRINT_RECE_MAC_ADDR(this->settings, macPacketSize, context); ... } // transpond the station list to the lower layer void ApWifiMac::SendOneBeacon (void){ // predict the MCS for each station __SDN_LAB_PREDICT_AT_AP(this->stationList, this->context); // debug - print __SDN_LAB_AP_WIFI_MAC_PRINT_STATIONLIST(this->stationList, this->settings); __SDN_LAB_AP_WIFI_MAC_PRINT_DATA_TO_STATIONLIST(this->stationList, this->settings); __SDN_LAB_AP_WIFI_MAC_PRINT_DATA_FROM_STATIONLIST(this->stationList, this->settings); ... if (m_s1gSupported){ ... m_beaconDca->Queue (packet, hdr, context); ... } else{ ... m_beaconDca->Queue (packet, hdr, context); } ... }
src/wifi/model/sta-wifi-mac
sta-wifi-mac.h// extra headers #include "Components/PacketContext.h" // add PacketContext header for its C/C++ file #if defined(__SDN_LAB_DEBUG) || defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) || defined(__SDN_LAB_RA_MINSTREL_AI_DIST) #include "Components/NNData.h" #include "Components/OverheadSNN.h" #endif ... // add PacketContext as an extra parameter virtual void Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, SdnLab::PacketContext context);
sta-wifi-mac.cc// extra headers #include "Modules/Toolbox/FileManager.h" #include "Components/Settings.h" #include "Components/Mac.h" // extra namespaces using namespace Toolbox; using namespace SdnLab; // extra macros #if defined(__SDN_LAB_RA_MINSTREL_SNN_VINCENT) || defined(__SDN_LAB_RA_MINSTREL_SNN) || defined(__SDN_LAB_RA_MINSTREL_SNN_PLUS) #define __SDN_LAB_STA_MAC_ACCEPT_MCS_PREDICT(context) \ OverheadSNN * overhead = (OverheadSNN *)(context.GetOverhead()); \ if(overhead){ \ if(overhead->Begin()){ \ for(auto overheadData = overhead->Begin(); overheadData!= overhead->End(); ++overheadData){ \ if(overheadData && overheadData->Match(GetAddress())){ \ break; \ } \ } \ if(overhead->End()->Match(GetAddress())){ \ }\ } \ } #else #define __SDN_LAB_STA_MAC_ACCEPT_MCS_PREDICT(context) #endif ... // StaWifiMac::Receive: add PacketContext as an extra parameter void StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, PacketContext context){ // accept the MCS prediction from a beacon __SDN_LAB_STA_MAC_ACCEPT_MCS_PREDICT(context); }
src/wifi/model/dca-txop
dca-txop.h#pragma once ... // self-defined headers #include "Components/StationList.h" ... // add PacketContext as an extra parameter void Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr, SdnLab::PacketContext context = SdnLab::PacketContext());
dca-txop.cc// 3rd party namespaces using namespace SdnLab; ... // add PacketContext as an extra parameter void DcaTxop::Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr, PacketContext context){ ... m_queue->Enqueue (packet, hdr, context); ... } ... // send the PacketContext to MacLow void DcaTxop::NotifyAccessGranted (void){ // init variables PacketContext context; ... if (m_currentPacket == 0){ ... m_currentPacket = m_queue->Dequeue (&m_currentHdr, context); ... } ... if (m_currentHdr.GetAddr1 ().IsGroup () || m_currentHdr.IsPsPoll ()){ ... Low ()->StartTransmission (m_currentPacket, &m_currentHdr, params, m_transmissionListener, context); ... }else{ if (NeedFragmentation ()){ ... Low ()->StartTransmission (m_currentPacket, &m_currentHdr, params, m_transmissionListener, context); }else{ ... Low ()->StartTransmission (m_currentPacket, &m_currentHdr, params, m_transmissionListener, context); } } } // send the empty context DcaTxop::StartNext (void){ ... Low ()->StartTransmission (fragment, &hdr, params, m_transmissionListener); }
src/wifi/model/mac-rx-middle.h
mac-rx-middle.h// extra headers #include "Components/PacketContext.h" ... // add PacketContext as extra parameters typedef Callback<void, Ptr<Packet>, const WifiMacHeader*, SdnLab::PacketContext> ForwardUpCallback; ... // add PacketContext as extra parameters void Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, SdnLab::PacketContext);
mac-rx-middle.c// 3rd party headers #include "Modules/Toolbox/FileManager.h" // self-defined headers #include "Components/Settings.h" // 3rd party namespaces using namespace Toolbox; using namespace SdnLab; ... // MacRxMiddle::Receive: add PacketContext as an extra parameter // m_callback: add PacketContext as an extra parameter void MacRxMiddle::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr, PacketContext context){ ... m_callback (agregate, hdr, context); }
src/wifi/model/wifi-mac-queue
wifi-mac-queue.hxt#pragma once ... // self-defined headers #include "Components/PacketContext.h" ... // add PacketContext as an extra parameter struct Item{ Item (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tstamp); Item (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tstamp, SdnLab::PacketContext context); Ptr<const Packet> packet; WifiMacHeader hdr; Time tstamp; SdnLab::PacketContext context; }; ... // add PacketContext as an extra parameter void Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr); void Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr, SdnLab::PacketContext context); // add PacketContext as an extra parameter Ptr<const Packet> Dequeue (WifiMacHeader *hdr); Ptr<const Packet> Dequeue (WifiMacHeader *hdr, SdnLab::PacketContext &context);
wifi-mac-queue.cc// 3rd party namespaces using namespace SdnLab; ... WifiMacQueue::Item::Item (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tstamp){ this->packet = packet; this->hdr = hdr; this->tstamp = tstamp; } WifiMacQueue::Item::Item (Ptr<const Packet> packet, const WifiMacHeader &hdr, Time tstamp, PacketContext context){ Item(packet, hdr, tstamp); this->context = context; } ... // add PacketContext as an extra parameter void Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr, PacketContext context){ ... m_queue.push_back (Item (packet, hdr, now, context)); ... } void WifiMacQueue::Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr){ Enqueue(packet, hdr, PacketContext()); } ... // add PacketContext as an extra parameter Ptr<const Packet> WifiMacQueue::Dequeue (WifiMacHeader *hdr){ ... } Ptr<const Packet> Dequeue (WifiMacHeader *hdr, SdnLab::PacketContext &context){ ... if (!m_queue.empty (){ ... context = i.context; ... } ... }
src/wifi/model/mac-low
mac-low.h// extra headers #include "Components/PacketContext.h" ... // add PacketContext as extra parameters typedef Callback<void, Ptr<Packet>, const WifiMacHeader*, SdnLab::PacketContext> MacLowRxCallback; ... void SendDataPacket (SdnLab::PacketContext context); ... void ForwardDown (Ptr<const Packet> packet, const WifiMacHeader *hdr, WifiTxVector txVector, WifiPreamble preamble, SdnLab::PacketContext context=SdnLab::PacketContext()); void SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, SdnLab::PacketContext context); ... virtual void StartTransmission (Ptr<const Packet> packet, const WifiMacHeader* hdr, MacLowTransmissionParameters parameters, MacLowTransmissionListener *listener, SdnLab::PacketContext context=SdnLab::PacketContext()); ... void SetRxCallback (Callback<void,Ptr<Packet>,const WifiMacHeader *, SdnLab::PacketContext> callback); ... void DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, SdnLab::PacketContext context); ... void ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, bool ampduSubframe, SdnLab::PacketContext context);
mac-low.cc// extra headers #include "Modules/Toolbox/FileManager.h" #include "Components/Settings.h" #include "Components/PacketContext.h" // extra namespaces using namespace Toolbox; using namespace SdnLab; ... void MacLow::StartTransmission (Ptr<const Packet> packet, const WifiMacHeader* hdr, MacLowTransmissionParameters parameters, MacLowTransmissionListener *listener, PacketContext context){ ... if (m_txParams.MustSendRts ()){ ... } else{ if (NeedCtsToSelf () && m_ctsToSelfSupported) { ... } else{ SendDataPacket (context); } } } ... void MacLow::SendDataPacket (PacketContext context){ ... ForwardDown (m_currentPacket, &m_currentHdr, dataTxVector, preamble, context); ... } ... void MacLow::ForwardDown (Ptr<const Packet> packet, const WifiMacHeader* hdr, WifiTxVector txVector, WifiPreamble preamble, PacketContext context){ ... if (!m_ampdu || hdr->IsRts () || hdr->IsRts ()){ m_phy->SendPacket (packet, txVector, preamble, 0, context); }else{ ... for (; queueSize > 0; queueSize--){ ... if (delay == Seconds (0)){ ... m_phy->SendPacket (newPacket, txVector, preamble, packetType, context); }else{ Simulator::Schedule (delay, &MacLow::SendPacket, this, newPacket, txVector, preamble, packetType, context); } ... } } } void MacLow::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, SdnLab::PacketContext context){ NS_LOG_DEBUG ("Sending MPDU as part of A-MPDU"); m_phy->SendPacket (packet, txVector, preamble, packetType, context); } ... // MacLow::DeaggregateAmpduAndReceive: add PacketContext as an extra parameter // ReceiveOk: add PacketContext as an extra parameter void MacLow::DeaggregateAmpduAndReceive (Ptr<Packet> aggregatedPacket, double rxSnr, WifiTxVector txVector, WifiPreamble preamble, PacketContext context){ ... if (aggregatedPacket->RemovePacketTag (ampdu)){ ... if (firsthdr.GetAddr1 () == m_self){ ... if (firsthdr.IsAck () || firsthdr.IsBlockAck () || firsthdr.IsBlockAckReq ()){ ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe, context); }else if (firsthdr.IsData () || firsthdr.IsQosData ()){ ... ReceiveOk ((*n).first, rxSnr, txVector, preamble, ampduSubframe, context); ... } ... } ... } else{ ReceiveOk (aggregatedPacket, rxSnr, txVector, preamble, ampduSubframe, context); } } ... // m_rxCallback: add a NULL Packet Context (not being called in the current version) void MacLow::RxCompleteBufferedPacketsWithSmallerSequence (uint16_t seq, Mac48Address originator, uint8_t tid) { ... if (it != m_bAckAgreements.end ()) { ... for (; i != (*it).second.second.end ()&& QosUtilsMapSeqControlToUniqueInteger ((*i).second.GetSequenceNumber (), endSequence) < mappedStart; ) { if (guard == (*i).second.GetSequenceControl ()) { if (!(*i).second.IsMoreFragments ()) { while (last != i) { m_rxCallback ((*last).first, &(*last).second, PacketContext()); last++; } m_rxCallback ((*last).first, &(*last).second, PacketContext()); ... } ... } ... } ... } } // m_rxCallback: add a NULL Packet Context (not being called in the current version) void MacLow::RxCompleteBufferedPacketsUntilFirstLost (Mac48Address originator, uint8_t tid) { ... if (it != m_bAckAgreements.end ()) { ... for (; i != (*it).second.second.end () && guard == (*i).second.GetSequenceControl (); i++) { if (!(*i).second.IsMoreFragments ()) { while (lastComplete != i) { m_rxCallback ((*lastComplete).first, &(*lastComplete).second, PacketContext()); lastComplete++; } m_rxCallback ((*lastComplete).first, &(*lastComplete).second, PacketContext()); lastComplete++; } guard = (*i).second.IsMoreFragments () ? (guard + 1) : ((guard + 16) & 0xfff0); } ... } }
src/wifi/model/wifi-phy.h
#include "Components/PacketContext.h" // RxOkCallback:: add PacketContext as an extra parameter typedef Callback<void, Ptr<Packet>, double, WifiTxVector, enum WifiPreamble, SdnLab::PacketContext> RxOkCallback; ... virtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble, uint8_t packetType, SdnLab::PacketContext context) = 0;
src/wifi/model/wifi-phy-state-helper
wifi-phy-state-helper.h#include "Components/PacketContext.h" // add PacketContext header for its C/C++ file ... // add PacketContext as an extra parameter void SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiTxVector txVector, enum WifiPreamble preamble, SdnLab::PacketContext context);
wifi-phy-state-helper.cc// 3rd party namespaces using namespace SdnLab; ... // SwitchFromRxEndOk: add PacketContext as an extra parameter // WifiPhy::RxOkCallback m_rxOkCallback: add PacketContext as an extra input void WifiPhyStateHelper::SwitchFromRxEndOk (Ptr<Packet> packet, double snr, WifiTxVector txVector, enum WifiPreamble preamble, PacketContext context){ ... if (!m_rxOkCallback.IsNull ()){ m_rxOkCallback (packet, snr, txVector, preamble, context); } }
src/wifi/model/yans-wifi-phy
yans-wifi-phy.hvirtual void SendPacket (Ptr<const Packet> packet, WifiTxVector txvector, enum WifiPreamble preamble, uint8_t packetType, SdnLab::PacketContext context); ... void EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, uint8_t packetType, Ptr<InterferenceHelper::Event> event, SdnLab::PacketContext context); ... void StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerDbm, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, Time rxDuration, SdnLab::PacketContext context = SdnLab::PacketContext()); ... // debug #ifdef __SDN_LAB_DEBUG SdnLab::Settings settings; #endif
yans-wifi-phy.cc// extra headers #include "Modules/Toolbox/FileManager.h" #include "Components/Settings.h" #include "Components/PacketContext.h" // extra namespaces using namespace Toolbox; using namespace SdnLab; // extra macros #ifdef __SDN_LAB_DEBUG #define __SDN_LAB_YANS_WIFI_PHY_PRINT(path, filemanager) \ if(filemanager.Open(path) == 200){ \ filemanager.AddCSVItem(packetSize); \ filemanager.AddCSVItem(startTime); \ filemanager.AddCSVItem(endTime); \ filemanager.AddCSVItem(snr); \ filemanager.AddCSVItem(per); \ filemanager.AddCSVItem(rxPower); \ filemanager.AddCSVItem(interferePower); \ filemanager.AddCSVItem(modeName); \ filemanager.AddCSVItem(mcs_in); \ filemanager.AddCSVItem(isReceived, true); \ filemanager.Close(); \ }\ #define __SDN_LAB_YANS_WIFI_PHY_RECE_ALL_FILEPATH(set) (set.PathProjectDebug() + set.TRACK_FILE_YANS_WIFI_PHY) #else #define __SDN_LAB_YANS_WIFI_PHY_PRINT(path, filemanager) #define __SDN_LAB_YANS_WIFI_PHY_RECE_ALL_FILEPATH(set) "" #endif #ifdef __SDN_LAB_PHY_PACKET_SIZE_DATA #define __SDN_LAB_YANS_WIFI_PHY_RECE_DATA_FILEPATH(set) (set.PathProjectDebug() + set.TRACK_FILE_YANS_WIFI_PHY_DATA) #else #define __SDN_LAB_YANS_WIFI_PHY_RECE_DATA_FILEPATH(set) "" #define __SDN_LAB_PHY_PACKET_SIZE_DATA 0 #endif #ifdef __SDN_LAB_PHY_PACKET_SIZE_BEACON #define __SDN_LAB_YANS_WIFI_PHY_RECE_DATA_BEACON_FILEPATH(set) (set.PathProjectDebug() + set.TRACK_FILE_YANS_WIFI_PHY_DATA_BEACON) #else #define __SDN_LAB_YANS_WIFI_PHY_RECE_DATA_BEACON_FILEPATH(set) "" #define __SDN_LAB_PHY_PACKET_SIZE_BEACON 0 #endif ... StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerDbm, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, Time rxDuration, PacketContext context){ ... switch (m_state->GetState ()){ ... case YansWifiPhy::IDLE: if (rxPowerW > m_edThresholdW){ ... m_endRxEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndReceive, this, packet, preamble, packetType, event, context); } } } ... // YansWifiPhy::EndReceive: create the PacketContext // SwitchFromRxEndOk: transfer the packet to the upper layer // <DEBUG>: DEBUG_SDN, DEBUG_SDN_PHY_PACKET_SIZE_DATA, DEBUG_SDN_PHY_PACKET_SIZE_BEACON control printing void YansWifiPhy::EndReceive (Ptr<Packet> packet, enum WifiPreamble preamble, uint8_t packetType, Ptr<InterferenceHelper::Event> event, PacketContext context) { ... // packet context // calculate the packet size uint32_t packetSize = packet->GetSize(); // calculate the start time and end time of this packet double startTime = event->GetStartTime().GetSeconds(); double endTime = event->GetEndTime().GetSeconds(); // calculate SNR & PER struct InterferenceHelper::SnrPer snrPer; snrPer = m_interference.CalculatePlcpPayloadSnrPer (event); double snr = snrPer.snr; double per = snrPer.per; // calculate the Rx power in Watt double rxPower = event->GetRxPowerW(); // calculate the interference power (currently we suppose we don't know the interference power) double interferePower = -1; // get the mode name std::string modeName = event->GetPayloadMode().GetUniqueName(); // MCS unsigned int mcs_in = ContextFactory::ModeName2MCS(modeName); // whether is received bool isReceived = false; // create the context context.SetPhyPacketSize(packetSize); context.SetStartTime(startTime); context.SetEndTime(endTime); context.SetPer(per); context.SetSnr(snr); context.SetRxPower(rxPower); context.SetMcsInAndBandwidth(modeName); ... // decide whether this packet is received or not if (m_plcpSuccess == true){ ... if (m_random->GetValue () > snrPer.per){ ... // set packetContext to be received isReceived = true; packetContext.SetIsReceived(true); // notify the upper layer that this packet is received m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetTxVector (), event->GetPreambleType (), packetContext); } else{ ... } // record data __SDN_LAB_YANS_WIFI_PHY_PRINT(__SDN_LAB_YANS_WIFI_PHY_RECE_ALL_FILEPATH(this->settings), fm); if (packetSize == __SDN_LAB_PHY_PACKET_SIZE_DATA){ __SDN_LAB_YANS_WIFI_PHY_PRINT(__SDN_LAB_YANS_WIFI_PHY_RECE_DATA_FILEPATH(this->settings), fm); } if (packetSize == __SDN_LAB_PHY_PACKET_SIZE_BEACON){ __SDN_LAB_YANS_WIFI_PHY_PRINT(__SDN_LAB_YANS_WIFI_PHY_RECE_DATA_BEACON_FILEPATH(this->settings), fm); } } else{ ... } ... } ... void YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, PacketContext context){ ... m_channel->Send (this, packet, GetPowerDbm (txVector.GetTxPowerLevel ()) + m_txGainDb, txVector, preamble, packetType, txDuration, context); }
src/wifi/model/yans-wifi-channl
src/wifi/model/.h// extra headers #include "Components/PacketContext.h" ... // add PacketContext as the extra parameter void Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, Time duration, SdnLab::PacketContext context) const; ... // add PacketContext as the extra parameter void Receive (uint32_t i, Ptr<Packet> packet, double *atts, WifiTxVector txVector, WifiPreamble preamble) const; void Receive (SdnLab::PacketContext context, Ptr<Packet> packet, double *atts, WifiTxVector txVector, WifiPreamble preamble) const;
yans-wifi-channl.cc// extra headers #include "Modules/Toolbox/FileManager.h" #include "Components/Settings.h" #include "Components/PacketContext.h" // extra namespaces using namespace Toolbox; using namespace SdnLab; ... void Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm, WifiTxVector txVector, WifiPreamble preamble, uint8_t packetType, Time duration, PacketContext context) const{ ... for (PhyList::const_iterator i = m_phyList.begin (); i != m_phyList.end (); i++, j++){ if (sender != (*i)){ ... if(context.isEmpty()){ void (YansWifiChannel::*callback)(uint32_t, Ptr<Packet>, double *, WifiTxVector, WifiPreamble) const = NULL; callback = &YansWifiChannel::Receive; Simulator::ScheduleWithContext (dstNode, delay, callback, this, j, copy, atts, txVector, preamble); }else{ context.SetNodeIndex(j); void (YansWifiChannel::*callback)(PacketContext, Ptr<Packet>, double *, WifiTxVector, WifiPreamble) const = NULL; callback = &YansWifiChannel::Receive; Simulator::ScheduleWithContext (dstNode, delay, callback, this, context, copy, atts, txVector, preamble); } } } } void YansWifiChannel::Receive (uint32_t i, Ptr<Packet> packet, double *atts, WifiTxVector txVector, WifiPreamble preamble) const {...} void YansWifiChannel::Receive (SdnLab::PacketContext context, Ptr<Packet> packet, double *atts, WifiTxVector txVector, WifiPreamble preamble) const{ m_phyList[context.GetNodeIndex()]->StartReceivePreambleAndHeader (packet, *atts, txVector, preamble, *(atts + 1), NanoSeconds (*(atts + 2)), context); delete[] atts; }
MacLow::RxCompleteBufferedPacketsWithSmallerSequenceunknow when to be called and why it is not calledMacLow::RxCompleteBufferedPacketsUntilFirstLostunkown when to be called and why it is not calledApWifiMac::Receivewhy does A-MSDU must be QoS?MacLow -> MacRxMiddle -> RegularWifiMac::ReceiveinAdhocWifiMac&OcbWifiMac
src/wifi/model/adhoc-wifi-mac.cc
This change should not be remove whenRegularWifiMac::Receivesupports defaultNULLPacketContext// RegularWifiMac::Receive:: add a NULL PacketContext void AdhocWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr){ ... RegularWifiMac::Receive (packet, hdr, NULL); }
src/wave/model/ocb-wifi-mac.cc
This change should not be remove whenRegularWifiMac::Receivesupports defaultNULLPacketContext
// RegularWifiMac::Receive: add a NULL PacketContext void OcbWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr){ ... RegularWifiMac::Receive (packet, hdr, NULL); }




