WIFI on NS-3

written by Junseok KIM, last updated Apr 8, 2011

Ns-3 is a discrete-event network simulator, developed as a replacement for the ns-2. Of course, it's a free software and you can edit any codes and implement your network protocols on ns-3. Ns-3 provides more realistic 802.11 module than ns-2. The 802.11 module of ns-3 supports the medium access control (MAC) and physical (PHY) layers of IEEE 802.11a/b/e/n/p. (IEEE 802.11e/n/p are not available in basic ns-2) The 802.11 module of ns-3 also supports several rate-adaptation algorithms such as the auto rate fallback (ARF), and the adaptive ARF (AARF). It's really good but it also means that understanding and editting the codes are not easy. I was analyzing and editing the 802.11 module of ns-2 when I was a junior undergraduate student. There are only two C++ files related to 802.11. It was not that difficult. :) But the 802.11 module of ns-3 consists of 50 C++ files. You should look at six C++ files thoroughly to understand the basic transmission procedure of the ns-3's 802.11 module. It's NOT THAT EASY for beginners. Its more headache for instructors either. In this web-page, I'm enumerating the basic procedure of the 802.11 module of ns-3 when transmission and reception occurs. I hope this web-page could be helpful. If you have questions "about this web-page", email me. I'm not the person who made this 802.11 module. You can get more information from ns-3 official site. If you have questions of NS-3 or 802.11 module, ask Google. It knows everything. :)

A data packet, from upper layer, should be inserted into the queue (i.e., temporary storage for data packets). In ns-3, the IEEE 802.11 MAC protocol is implemented with several C++ classes. Five classes are most important to understand the basic procedure of the transmission and reception: DcaTxop, DcfManager, MacLow, YansWifiPhy, and YansWifiChannel. DCA and DCF mean the dynamic channel assignment and the discrete contention function, respectively. When a data packet is inserted into the queue, DCA and DCF check whether another packet transmission or reception is processing. If there is no other packet, or when the packet transmission is finished, one data packet is extracted from the queue and forwarded to MacLow class. MacLow checks whether this data packet is multicast packet, or requires the ready to send (RTS) or the fragmentation. After estimating the duration of the transmission, MacLow forwards the data packet to YansWifiPhy and YansWifiPhy forwards it to YansWifiChannel. The backoff procedure -- selecing a random number and waiting for a contention -- is required only if channel was busy just before. This means that if there was no transmission or reception (i.e., channel is idle) for a specific time (i.e., during DIFS), MAC protocol sends a data packet immediately upon getting a data packet from an upper layer.

Here is an example of WiFi infrastructure network. One nodes is transmitting UDP packets to another node. One node is overhearing packets.

#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
#include "ns3/wifi-module.h"
#include "ns3/mobility-module.h"

using namespace ns3;

int main (int argc, char *argv[])
{
NodeContainer wifiNodes;
wifiNodes.Create (3);

YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
wifiPhy.SetChannel (wifiChannel.Create ());
WifiHelper wifi = WifiHelper::Default ();
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager");
wifiMac.SetType("ns3::AdhocWifiMac");
NetDeviceContainer wifiDevices = wifi.Install( wifiPhy, wifiMac, wifiNodes );

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::ConstantPositionMobilityModel");
mobility.Install (wifiNodes);

InternetStackHelper internet;
internet.Install (wifiNodes);
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer wifiInterfaces;
wifiInterfaces = address.Assign( wifiDevices );

UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (wifiNodes.Get( 0 ));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));

UdpEchoClientHelper echoClient (wifiInterfaces.GetAddress (0), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (2));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install ( wifiNodes.Get( 2 ) );
clientApps.Start( Seconds (2.0) );
clientApps.Stop( Seconds (10.0) );

Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

Simulator::Stop (Seconds (5.05));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}

 

The basic procedure of transmission is as follows:

Uppder Layer → WifiNetDevice::Send() # Convert IP address to MAC address; Add LLC header.
→ AdhocWifiMac::Enqueue()                    # Set Wifi MAC header; Estimate PHY modes (i.e., data rate) supported by destination node.
→ DcaTxop::Queue()                                 # Insert new packet into queue through WifiMacQueue::Enqueue().
→ DcaTxop::StartAccessIfNeeded()        # Request Access to DCF manager if there is no packet pending (i.e., if m_accessRequested  == true).
→ DcfManager::RequestAccess()           # If there is another packet pending, signal a collision through DcaTxop::NotifyCollision() which will select a random back-off number and try to access again.
→ DcfManager::DoGrantAccess()           # Check the internal collision among four different queues (for EDCA of IEEE 802.11e).
→ DcfState::NotifyAccessGranted()        # Set m_accessRequested as false; Notify that channel access is granted.
→ DcaTxop::NotifyAccessGranted()        # Extract one packet from queue; Set new sequence; Check whether this packet is multicast message, or requiring fragment or RTS.
→ MacLow::StartTransmission()              # If RTS is required, call SendRtsForPacket(). If not, call SendDataPacket().
→ MacLow::SendDataPacket()               # Estimate the duration of sum of transmission, ACK reception, and/or next transmission (for Block ACK or fragmentation).
→ MacLow::ForwardDown()                    # Toss the packet to PHY layer.
→ YansWifiPhy::SendPacket()                # Change current PHY state to TX (this command will eventually inform DCF that a transmission is starting); Toss the packet to CHANNEL layer.
→ YansWifiChannel::Send()                     # Estimate receive power; Set the propagation delay to trigger YansWifiChannel::Receive() of neighbors after a short period.

The basic procedure of reception is as follows:

YansWifiChannel::Receive()                    # Triggered after the propagation delay (set by sender through YansWifiChannel::Receive()).
→ YansWifiPhy::StartReceivePacket()  # Calculate the current interference level; Drop the received packet if the state of PHY is not idle or the receive power is below than a threshold; Set the delay to trigger YansWifiPhy::EndSync() after the packet transmission.
→ YansWifiPhy::EndSync()                     # Estimate the packet error rate (PER) from the signal to noise ratio (SNR) (i.e., signal power / (noise + interference power)); If a random value is smaller than the PER value, the packet is dropped.
→ MacLow::ReceiveOk()                        # If the packet is the RTS packet, schedule MacLow::SendCtsAfterRts(); If it is CTS, schedule MacLow::SendDataAfterCts(); If it is DATA, forward it to the upper; If the destination is me, schedule MacLow::SendAckAfterData().
→ MacRxMiddle::Receive()                    # Check whether the received packet is a duplicated one with a sequence number.
→ AdhocWifiMac::ForwardUp()             # Just forward the received packet to the upper.
→ WifiNetDevice::ForwardUp() → Upper Layer  # Unless the destination is other node, forward the received packet to the upper layer.

Some functions are triggered by callback functions. Some classes link to other classes via Pointers. These make difficult to understand ns-3's 802.11 module especially for who are not familiar to the C++ language. But when you get familiar, it's more easy to develop different versions of idea. For example, the 802.11 module has several rate adaptation algorithms: ARF,  AARF, the robust rate adaptation algorithm (RRAA), and etc. You can switch a rate adaptation algorithm by editing a simulation scenario file. You can also switch 802.11 modes (such as 802.11a/b/g/e/p/n/s) in the same way. For example, you can change a node from an ad hoc device to an access point (AP) by replacing AdhocWifiMac with QapWifiMac.

Following figure helps you more to understand function flows.