Lab 1: NS-3 Simulator
EE597 — Wireless Networks, USC Spring 2026
Welcome to the NS-3 Lab! In this lab, you will learn to use the NS-3 network simulator to model and analyze IEEE 802.11 wireless networks. You'll write C++ simulation scripts, run experiments, and collect performance data.
Learning Goals
Lab Experiments
Single BSS Throughput
Measure throughput of a single BSS with varying number of stations and data rates using IEEE 802.11a.
OBSS & Hidden Node
Analyze the impact of overlapping BSSs and hidden node problems on network performance.
Getting Started
Environment setup and first steps
Set up your development environment using the provided virtual machine image, then explore the example scripts to get familiar with NS-3 before starting the lab.
Virtual Machine Setup
Use VirtualBox to run the provided Ubuntu 18.04 VM image, which has NS-3 preinstalled.
ee597
ee597
~/ns-3-allinone/ns-3-dev/
The VM image just works with VirtualBox on Windows — download VirtualBox, import the image, and you are ready to go. No extra configuration needed.
VirtualBox works on Intel Macs. For Apple Silicon (M1/M2/M3), use UTM or another ARM-compatible virtualizer to run the VM image.
If you prefer coding in your native environment, that is fine — but make sure to test in the VM before final submission.
Example Files to Study
Before writing your own script, study these example files to understand how NS-3 wireless simulations are structured:
~/ns-3-allinone/ns-3-dev/examples/wireless/wifi-pcf.ccWiFi PCF (Point Coordination Function) example
~/ns-3-allinone/ns-3-dev/examples/wireless/wireless-ad-hoc.ccWireless ad-hoc network example
~/ns-3-allinone/ns-3-dev/examples/tutorial/third.ccWiFi + P2P mixed topology tutorial
Compiling & Running
Run these commands from the NS-3 root directory. You may need to enable examples if working in your native environment.
1# Run example with different RSS values
2./waf --run "wifi-simple-adhoc --rss=-97 --numPackets=20"
3./waf --run "wifi-simple-adhoc --rss=-98 --numPackets=20"
4./waf --run "wifi-simple-adhoc --rss=-99 --numPackets=20"
5
6# Drop your script into scratch/ and run it
7./waf --run yourscriptDrop your script into the scratch/ directory and it will automatically build and run with Waf. No need to modify any build files.
Documentation & References
What is NS-3?
NS-3 (Network Simulator 3) is a discrete-event network simulator primarily used for research and education. It provides realistic models of network protocols and is widely used to simulate wired/wireless networks, test new protocols, and analyze network behavior before real deployment.
Discrete-Event Simulation
Events are processed in chronological order. The simulator jumps from event to event — no wasted computation on idle time.
C++ & Python
Core is written in C++ for performance. Python bindings are available for scripting. Simulation scripts are typically in C++.
Modular Architecture
Protocol stacks are modular — swap WiFi for LTE, change routing protocols, or add new modules easily.
Realistic Models
Includes detailed models for WiFi (802.11a/b/g/n/ac/ax), LTE, propagation loss, mobility patterns, and more.
Open Source
Free and open-source (GPLv2). Large community with extensive documentation and active development.
Scalable
Can simulate large networks with hundreds of nodes. Supports distributed simulation for even larger scenarios.
NS-3 Architecture Stack
IEEE 802.11 DCF — CSMA/CA
Distributed Coordination Function
The Distributed Coordination Function (DCF) is the fundamental MAC protocol in IEEE 802.11. It uses CSMA/CA — Carrier Sense Multiple Access with Collision Avoidance — to manage channel access among competing stations.
How DCF Works
A station wanting to transmit listens to the medium. If the channel is busy, it waits until the channel becomes idle.
If the channel is free, the station waits for a specific duration called the Distributed Inter-Frame Space (DIFS = 50 µs for 802.11a).
To avoid collisions, the station selects a random backoff time from [0, CW] (Contention Window, initially 15). The timer decrements only while the channel is idle. If the channel becomes busy, the timer pauses (freezes).
Once the backoff timer reaches zero, the station sends an RTS frame. The receiver replies with a CTS frame. Neighboring stations hear the CTS and set their NAV to defer.
The station sends its data frame. The receiver responds with an ACK to confirm successful reception. The channel is then released.
If a collision occurs (no ACK received), the Contention Window doubles (Binary Exponential Backoff): CW goes 15 → 31 → 63 → 127 → 255 → 511 → 1023. A larger CW means a wider random range, reducing future collision probability.
CSMA/CA with RTS/CTS — Interactive Scenario
3 Laptops + 1 Access Point
Initial State
Three laptops (A, B, C) are associated with one Access Point (AP). Laptops A and B both have data to send at the same time. Laptop C is idle.
The Hidden Node Problem
The hidden node problem occurs when two stations (A and C) are out of range of each other but both within range of a common station (B). Since A cannot sense C's transmission, they may transmit simultaneously, causing a collision at B.
A and C cannot hear each other — hidden from one another!
RTS/CTS Mechanism
RTS/CTS (Request to Send / Clear to Send) solves the hidden node problem by reserving the channel before data transmission.
Test Your Knowledge: CSMA/CA
What does CSMA/CA stand for?
Key NS-3 Concepts
Core building blocks for simulations
Every NS-3 simulation is built from five fundamental abstractions: Node, NetDevice, Channel, Helpers, and Applications.
Node
A computing device in the simulation. Think of it as a bare computer — no network stack until you add one. Created via NodeContainer.
1NodeContainer nodes;
2nodes.Create(2); // Create 2 nodesNetDevice
A network interface card (NIC). Connects a Node to a Channel. Different types: CsmaNetDevice, WifiNetDevice, PointToPointNetDevice.
1PointToPointHelper p2p;
2p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
3NetDeviceContainer devices = p2p.Install(nodes);Channel
The communication medium (wire or wireless). Connects NetDevices together. Channels model propagation delay and loss.
1p2p.SetChannelAttribute("Delay", StringValue("2ms"));Helpers
Helper classes simplify configuration. They follow the "factory" pattern — create and configure complex objects with a few lines.
1InternetStackHelper stack;
2stack.Install(nodes); // Adds TCP/IP stack
3
4Ipv4AddressHelper address;
5address.SetBase("10.1.1.0", "255.255.255.0");
6Ipv4InterfaceContainer interfaces = address.Assign(devices);Application
Traffic generators installed on nodes. NS-3 provides UdpEchoServer, UdpEchoClient, OnOffApplication, PacketSink, and more.
1UdpEchoServerHelper echoServer(9); // Port 9
2ApplicationContainer serverApps = echoServer.Install(nodes.Get(1));
3serverApps.Start(Seconds(1.0));
4serverApps.Stop(Seconds(10.0));Example 1: UDP Echo (Point-to-Point)
first.cc — Your first NS-3 script
This example creates two nodes connected by a point-to-point link. A UDP Echo Client on Node 0 sends a packet to the UDP Echo Server on Node 1, which echoes it back.
UDP Echo Client — sends 1024-byte packet to 10.1.1.2:9
IP: 10.1.1.1UDP Echo Server — listens on port 9, echoes packets back
IP: 10.1.1.2Code Walkthrough
Include the necessary NS-3 modules (core, network, internet, point-to-point, applications). Define a logging component and enable logging for the echo applications.
#include "ns3/core-module.h"
#include "ns3/network-module.h"
NS_LOG_COMPONENT_DEFINE("FirstScriptExample");Complete Code
1#include "ns3/core-module.h"
2#include "ns3/network-module.h"
3#include "ns3/internet-module.h"
4#include "ns3/point-to-point-module.h"
5#include "ns3/applications-module.h"
6
7using namespace ns3;
8
9NS_LOG_COMPONENT_DEFINE("FirstScriptExample");
10
11int main(int argc, char *argv[]) {
12 CommandLine cmd;
13 cmd.Parse(argc, argv);
14
15 Time::SetResolution(Time::NS);
16 LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
17 LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
18
19 // Create 2 nodes
20 NodeContainer nodes;
21 nodes.Create(2);
22
23 // Configure point-to-point link
24 PointToPointHelper pointToPoint;
25 pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
26 pointToPoint.SetChannelAttribute("Delay", StringValue("2ms"));
27
28 // Install devices
29 NetDeviceContainer devices;
30 devices = pointToPoint.Install(nodes);
31
32 // Install Internet stack
33 InternetStackHelper stack;
34 stack.Install(nodes);
35
36 // Assign IP addresses
37 Ipv4AddressHelper address;
38 address.SetBase("10.1.1.0", "255.255.255.0");
39 Ipv4InterfaceContainer interfaces = address.Assign(devices);
40
41 // Setup UDP Echo Server on Node 1
42 UdpEchoServerHelper echoServer(9);
43 ApplicationContainer serverApps = echoServer.Install(nodes.Get(1));
44 serverApps.Start(Seconds(1.0));
45 serverApps.Stop(Seconds(10.0));
46
47 // Setup UDP Echo Client on Node 0
48 UdpEchoClientHelper echoClient(interfaces.GetAddress(1), 9);
49 echoClient.SetAttribute("MaxPackets", UintegerValue(1));
50 echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0)));
51 echoClient.SetAttribute("PacketSize", UintegerValue(1024));
52
53 ApplicationContainer clientApps = echoClient.Install(nodes.Get(0));
54 clientApps.Start(Seconds(2.0));
55 clientApps.Stop(Seconds(10.0));
56
57 Simulator::Run();
58 Simulator::Destroy();
59 return 0;
60}Expected Output
1At time +2s client sent 1024 bytes to 10.1.1.2 port 9
2At time +2.00369s server received 1024 bytes from 10.1.1.1 port 49153
3At time +2.00369s server sent 1024 bytes to 10.1.1.1 port 49153
4At time +2.00737s client received 1024 bytes from 10.1.1.2 port 9Example 2: Wireless Topology
third.cc — WiFi + Point-to-Point
This example creates a mixed wired-wireless topology: WiFi stations communicate through an Access Point (AP) that is also connected to a wired server via a Point-to-Point link.
3 mobile stations with RandomWalk2d mobility
Subnet: 10.1.2.0/24Bridges WiFi and wired network, stationary
SSID: ns-3-ssidUDP Echo Server on port 9
Subnet: 10.1.1.0/24Code Walkthrough
Create 2 nodes connected by a 5 Mbps, 2ms point-to-point link. This forms the wired backbone. Node 0 will also serve as the WiFi AP.
NodeContainer p2pNodes;
p2pNodes.Create(2);
PointToPointHelper p2p;
p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
p2p.Install(p2pNodes);Complete Code
1#include "ns3/core-module.h"
2#include "ns3/network-module.h"
3#include "ns3/internet-module.h"
4#include "ns3/wifi-module.h"
5#include "ns3/mobility-module.h"
6#include "ns3/applications-module.h"
7#include "ns3/point-to-point-module.h"
8
9using namespace ns3;
10
11NS_LOG_COMPONENT_DEFINE("WirelessExample");
12
13int main(int argc, char *argv[]) {
14 uint32_t nWifi = 3;
15 CommandLine cmd;
16 cmd.AddValue("nWifi", "Number of wifi STA devices", nWifi);
17 cmd.Parse(argc, argv);
18
19 // Create P2P nodes (wired backbone)
20 NodeContainer p2pNodes;
21 p2pNodes.Create(2);
22
23 PointToPointHelper pointToPoint;
24 pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
25 pointToPoint.SetChannelAttribute("Delay", StringValue("2ms"));
26 NetDeviceContainer p2pDevices = pointToPoint.Install(p2pNodes);
27
28 // Create WiFi station nodes
29 NodeContainer wifiStaNodes;
30 wifiStaNodes.Create(nWifi);
31 NodeContainer wifiApNode = p2pNodes.Get(0); // AP is P2P node 0
32
33 // Configure WiFi channel and PHY
34 YansWifiChannelHelper channel = YansWifiChannelHelper::Default();
35 YansWifiPhyHelper phy;
36 phy.SetChannel(channel.Create());
37
38 // Configure WiFi MAC
39 WifiHelper wifi;
40 WifiMacHelper mac;
41 Ssid ssid = Ssid("ns-3-ssid");
42
43 // STA devices
44 mac.SetType("ns3::StaWifiMac",
45 "Ssid", SsidValue(ssid),
46 "ActiveProbing", BooleanValue(false));
47 NetDeviceContainer staDevices = wifi.Install(phy, mac, wifiStaNodes);
48
49 // AP device
50 mac.SetType("ns3::ApWifiMac",
51 "Ssid", SsidValue(ssid));
52 NetDeviceContainer apDevices = wifi.Install(phy, mac, wifiApNode);
53
54 // Mobility
55 MobilityHelper mobility;
56 mobility.SetPositionAllocator("ns3::GridPositionAllocator",
57 "MinX", DoubleValue(0.0),
58 "MinY", DoubleValue(0.0),
59 "DeltaX", DoubleValue(5.0),
60 "DeltaY", DoubleValue(10.0),
61 "GridWidth", UintegerValue(3),
62 "LayoutType", StringValue("RowFirst"));
63
64 mobility.SetMobilityModel("ns3::RandomWalk2dMobilityModel",
65 "Bounds", RectangleValue(Rectangle(-50, 50, -50, 50)));
66 mobility.Install(wifiStaNodes);
67
68 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
69 mobility.Install(wifiApNode);
70
71 // Internet stack
72 InternetStackHelper stack;
73 stack.Install(p2pNodes.Get(1));
74 stack.Install(wifiStaNodes);
75 stack.Install(wifiApNode);
76
77 // IP addresses
78 Ipv4AddressHelper address;
79 address.SetBase("10.1.1.0", "255.255.255.0");
80 address.Assign(p2pDevices);
81
82 address.SetBase("10.1.2.0", "255.255.255.0");
83 Ipv4InterfaceContainer wifiInterfaces;
84 wifiInterfaces = address.Assign(staDevices);
85 address.Assign(apDevices);
86
87 // Applications (similar to Example 1)
88 UdpEchoServerHelper echoServer(9);
89 ApplicationContainer serverApps = echoServer.Install(p2pNodes.Get(1));
90 serverApps.Start(Seconds(1.0));
91 serverApps.Stop(Seconds(10.0));
92
93 UdpEchoClientHelper echoClient(
94 p2pNodes.Get(1)->GetObject<Ipv4>()->GetAddress(1, 0).GetLocal(), 9);
95 echoClient.SetAttribute("MaxPackets", UintegerValue(1));
96 echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0)));
97 echoClient.SetAttribute("PacketSize", UintegerValue(1024));
98
99 ApplicationContainer clientApps = echoClient.Install(wifiStaNodes.Get(nWifi - 1));
100 clientApps.Start(Seconds(2.0));
101 clientApps.Stop(Seconds(10.0));
102
103 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
104
105 Simulator::Stop(Seconds(10.0));
106 Simulator::Run();
107 Simulator::Destroy();
108 return 0;
109}Building & Running Scripts
NS-3 build system and workflow
NS-3 uses a CMake-based build system accessed via the ./ns3 command. Place your simulation scripts in the scratch/ directory, build, and run.
Directory Structure
1ns-3-dev/
2├── src/ # NS-3 modules (wifi, internet, etc.)
3│ ├── wifi/
4│ ├── internet/
5│ ├── network/
6│ └── ...
7├── scratch/ # YOUR simulation scripts go here
8│ ├── first.cc
9│ ├── third.cc
10│ └── my-script.cc
11├── examples/ # Example scripts (read-only reference)
12├── build/ # Compiled output
13└── ns3 # Build/run tool (replaces old waf)Key Commands
Configure NS-3 (First Time)
Run once to configure the build system with examples and tests enabled.
1./ns3 configure --enable-examples --enable-testsBuild NS-3
Compile all NS-3 modules. Run after configuration or code changes.
1./ns3 buildRun a Script
Execute an NS-3 simulation script from the scratch/ directory.
1./ns3 run scratch/firstRun with Arguments
Pass command-line arguments to your simulation script.
1./ns3 run "scratch/third --nWifi=5"Workflow Tip
Copy example scripts to scratch/ before modifying:
cp examples/tutorial/first.cc scratch/my-first.ccCommands & Debugging
Logging, tracing, and debugging tools
NS-3 provides powerful tools for logging, data collection, and debugging. Master these to efficiently develop and analyze your simulations.
Logging
NS-3 has a built-in logging system with multiple verbosity levels.
1LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);1export NS_LOG="UdpEchoClientApplication=level_all|prefix_func|prefix_time"1LOG_LEVEL_ALL // Everything
2LOG_LEVEL_DEBUG // Debug messages
3LOG_LEVEL_INFO // Informational messages
4LOG_LEVEL_WARN // Warnings
5LOG_LEVEL_ERROR // Errors only
6LOG_LEVEL_FUNCTION // Function entry/exit tracesCommand Line Arguments
Pass runtime parameters to your simulation scripts.
1CommandLine cmd;
2uint32_t nWifi = 3;
3bool verbose = true;
4cmd.AddValue("nWifi", "Number of wifi stations", nWifi);
5cmd.AddValue("verbose", "Enable logging", verbose);
6cmd.Parse(argc, argv);1./ns3 run "scratch/my-script --nWifi=5 --verbose=true"1./ns3 run "scratch/my-script --PrintHelp"Tracing & Data Collection
Collect simulation data using ASCII/PCAP tracing or FlowMonitor.
1AsciiTraceHelper ascii;
2pointToPoint.EnableAsciiAll(ascii.CreateFileStream("first.tr"));1pointToPoint.EnablePcapAll("first");
2// Creates first-0-0.pcap, first-1-0.pcap1tcpdump -nn -tt -r first-0-0.pcap1FlowMonitorHelper flowmon;
2Ptr<FlowMonitor> monitor = flowmon.InstallAll();
3// After simulation:
4monitor->SerializeToXmlFile("results.xml", true, true);Debugging
Debug your NS-3 scripts with GDB or Valgrind.
1./ns3 run scratch/first --command-template="gdb %s"1./ns3 run scratch/first --command-template="valgrind %s"1./ns3 configure --build-profile=debug --enable-examplesResources
Useful links and references for NS-3 development and IEEE 802.11 learning.
Official Documentation
Source Code & Downloads
Learning Resources
Quick Tips
Always check examples/ directory for reference implementations before writing from scratch.
Use NS_LOG environment variable to debug without recompiling.
Start with simple topologies and gradually add complexity.
Lab Experiment
NS-3 Simulation of 802.11 CSMA/CA MAC
Investigate how CSMA/CA with binary exponential backoff behaves under saturation. You will measure throughput while varying the number of transmitting nodes and the offered data rate under two different contention window configurations.
Network Topology
Default NS-3 WiFi PHY
IEEE 802.11 DCF (CSMA/CA)
OnOffApplication — CBR
512 bytes
PacketSink on central node
Two Contention Window Configurations
Standard Backoff
Wide range (1 → 1023). After each collision the CW doubles: 1 → 3 → 7 → 15 → 31 → 63 → 127 → 255 → 511 → 1023. Standard binary exponential backoff with a large spread.
CW growth after each collision
Narrow Window
Narrow range (63 → 127). Only one doubling step possible. Higher initial backoff reduces collisions at low load, but the small CW_max limits adaptation at high load.
CW growth after collision (only 1 step)
Experiments
Vary Number of Nodes (N)
Increase offered load by adding more transmitters
Keep data rate R fixed at a reasonable value. Vary N and measure throughput at the receiver for each N.
Measure: Aggregate throughput & per-node throughput for each N
Vary Data Rate (R)
Increase offered load by raising data rate
Fix number of nodes at N = 20. Vary the offered data rate R in fine granularity and measure throughput.
Measure: Aggregate throughput & per-node throughput for each R value
Evaluation Matrix
| Case A CW: 1 → 1023 | Case B CW: 63 → 127 | |
|---|---|---|
| E1Vary N Throughput vs. N (22 pts) | Aggregate: 10 pts Per-node: 10 pts | Aggregate: 10 pts Per-node: 10 pts |
| E2Vary R Throughput vs. R (22 pts) | Aggregate: 10 pts Per-node: 10 pts | Aggregate: 10 pts Per-node: 10 pts |
| Discussion — 12 pts Compare Case A vs B, explain saturation behavior, visualize data | ||
| Bonus (10 pts) Mean & variance of backoff slots per TX vs. N/R (+5 pts) • Collision rate vs. N/R (+5 pts) | ||
Implementation Tips
Modify NS-3 source files: wifi-phy.cc, txop.cc, wifi-helper.h in ~/ns-3-allinone/ns-3-dev/src/wifi/. Reading the source is the easiest way.
Create one lab1.cc file with command-line arguments for case/experiment selection. Use a Lab1Run.sh bash script to run all configurations.
Run the simulation long enough to reach saturation. Use FlowMonitor to collect throughput metrics. Average over multiple runs for reliable estimates.
Place all N transmitters uniformly in the terrain, ensuring every node is within radio range of every other node and the receiver.
Submission Requirements
Submit via Brightspace
All code files and the electronic report should be submitted online. Make sure your code works with the NS-3 installation on the provided VM.
All evaluation plots, throughput data, and discussion of results. Code (including comments) does not count as description — do not include code files in the report.
Include a readme file explaining how to run your code. One common lab1.cc file for all simulations is recommended.
Create one lab1.cc that accepts command-line arguments for Case (A/B) and Experiment (E1/E2), then use a bash script to run everything:
1#!/bin/bash
2# Lab1Run.sh — runs all 4 experiment configurations
3
4# Case A, Experiment 1: vary N
5for N in 5 10 15 20 25 30 35 40; do
6 ./waf --run "scratch/lab1 --case=A --experiment=E1 --nNodes=$N --dataRate=2"
7done
8
9# Case A, Experiment 2: vary R (N=20)
10for R in 0.5 1 2 4 6 8 10 12 14 16; do
11 ./waf --run "scratch/lab1 --case=A --experiment=E2 --nNodes=20 --dataRate=$R"
12done
13
14# Case B, Experiment 1: vary N
15for N in 5 10 15 20 25 30 35 40; do
16 ./waf --run "scratch/lab1 --case=B --experiment=E1 --nNodes=$N --dataRate=2"
17done
18
19# Case B, Experiment 2: vary R (N=20)
20for R in 0.5 1 2 4 6 8 10 12 14 16; do
21 ./waf --run "scratch/lab1 --case=B --experiment=E2 --nNodes=20 --dataRate=$R"
22doneDiscuss results with respect to different case configurations. Use MATLAB, Python, R, or any visualization tool to plot throughput data. Visualization makes saturation patterns visible — but explaining your CSV data is also accepted.