Placing nodes at exact 3D coordinates lets you study how distance affects a wireless link. A constant bit rate source then gives a steady, predictable load to measure.
Objectives
Do not copy. Read for understanding and the viva- Complete questions 13 to 15 of the manual: fixed-distance ad-hoc nodes and cbr traffic
- Prepare the deliverable before the lab and finish it during the session
- Be ready to explain every step in the viva
Questions Covered
Do not copy. Read for understanding and the viva| Question | Requirement | Status |
|---|---|---|
| Q13 | Use 2 nodes to setup a wireless ad-hoc network where nodes are placed at a fixed… | Complete |
| Q14 | Install UDP server and Client at these two nodes | Complete |
| Q15 | Setup a CBR transmission between these nodes | Complete |
Preparation
Do not copy. Read for understanding and the viva- Use
ConstantPositionMobilityModelwith aListPositionAllocatorandVector(x, y, z)for each node. - CBR is an OnOffHelper with
OnTimeconstant 1 andOffTimeconstant 0, plus DataRate and PacketSize. - Repeat at two or three distances and record delivered bytes; relate the drop to the propagation loss model.
Question 13
Problem Statement
Write in lab recordUse 2 nodes to setup a wireless ad-hoc network where nodes are placed at a fixed distance in a 3D plane.
Solution
Write in lab recordOne script, adhoc-cbr.cc, answers questions 13 to 15. Question 13 is the topology and position part; 14 and 15 add the applications. The whole listing is given here once and referred to from the next two questions.
Steps
- Copy the listing below into
scratch/adhoc-cbr.ccinside your ns-3 directory (cp adhoc-cbr.cc scratch/). - Positions: a
ListPositionAllocatorreceives oneVector(x, y, z)per node, node 0 at (0, 0, 1.5) m and node 1 at (distance, 0, 1.5) m. The z value is the antenna height, so both nodes have full 3D coordinates. MobilityHelpertakes that allocator, setsns3::ConstantPositionMobilityModel(the nodes never move) and is installed on theNodeContainer.- Wi-Fi:
WifiHelperwith standard 802.11a andConstantRateWifiManagerfixed atOfdmRate6Mbps;YansWifiChannelHelper::Default()gives the log-distance loss model;WifiMacHelpertypens3::AdhocWifiMacmakes it an ad-hoc network with no access point. InternetStackHelperandIpv4AddressHelper(10.1.1.0/24) give the two interfaces addresses 10.1.1.1 and 10.1.1.2.- Build and run:
./ns3 run "scratch/adhoc-cbr --distance=50". The first line printed comes from the mobility models and confirms the positions and the distance.
Program
/*
* adhoc-cbr.cc -- MCSL-223 Session 6, questions 13 to 15
*
* Purpose of the program:
* Two 802.11a ad-hoc nodes are placed at fixed 3D coordinates
* (ConstantPositionMobilityModel fed by a ListPositionAllocator).
* Node 0 runs a UdpClient (Q14) and a constant bit rate OnOff source (Q15);
* node 1 runs the matching UdpServer and a PacketSink. At the end the
* program prints the positions, the distance, the packets the UdpServer
* counted and the bytes the CBR sink delivered.
*
* Topology:
* n0 (0, 0, 1.5) m ~~~~ 802.11a ad-hoc, 6 Mbit/s ~~~~ n1 (d, 0, 1.5) m
* UdpClient --> port 9 --> UdpServer
* OnOff CBR --> port 10 --> PacketSink
*
* Build and run (ns-3.36 or later):
* cp adhoc-cbr.cc scratch/
* ./ns3 run "scratch/adhoc-cbr --distance=50"
* ./ns3 run "scratch/adhoc-cbr --distance=100"
* ./ns3 run "scratch/adhoc-cbr --distance=150"
*/
#include "ns3/applications-module.h"
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/network-module.h"
#include "ns3/wifi-module.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("AdhocCbr");
/*
* main: builds the two-node ad-hoc network, installs the applications,
* runs for simTime seconds and prints the delivery figures.
*/
int
main(int argc, char* argv[])
{
double distance = 50.0; // metres between the nodes along x
double height = 1.5; // antenna height, the z coordinate
double simTime = 10.0; // seconds
std::string cbrRate = "500kb/s";
uint32_t cbrPacketSize = 500; // bytes, so 500 kb/s is one packet every 8 ms
bool verbose = false;
CommandLine cmd(__FILE__);
cmd.AddValue("distance", "Distance between the two nodes in metres", distance);
cmd.AddValue("height", "Antenna height (z coordinate) in metres", height);
cmd.AddValue("cbrRate", "Constant bit rate of the OnOff source", cbrRate);
cmd.AddValue("simTime", "Simulation time in seconds", simTime);
cmd.AddValue("verbose", "Print UdpClient and UdpServer log lines", verbose);
cmd.Parse(argc, argv);
if (verbose)
{
LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
}
// ---- Q13: two nodes at fixed 3D positions --------------------------
NodeContainer nodes;
nodes.Create(2);
Ptr<ListPositionAllocator> positions = CreateObject<ListPositionAllocator>();
positions->Add(Vector(0.0, 0.0, height)); // node 0
positions->Add(Vector(distance, 0.0, height)); // node 1
MobilityHelper mobility;
mobility.SetPositionAllocator(positions);
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
mobility.Install(nodes);
// ---- Q13: 802.11a ad-hoc Wi-Fi at a fixed 6 Mbit/s ------------------
WifiHelper wifi;
wifi.SetStandard(WIFI_STANDARD_80211a);
wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
"DataMode", StringValue("OfdmRate6Mbps"),
"ControlMode", StringValue("OfdmRate6Mbps"));
YansWifiChannelHelper channel = YansWifiChannelHelper::Default();
YansWifiPhyHelper phy;
phy.SetChannel(channel.Create());
WifiMacHelper mac;
mac.SetType("ns3::AdhocWifiMac");
NetDeviceContainer devices = wifi.Install(phy, mac, nodes);
InternetStackHelper stack;
stack.Install(nodes);
Ipv4AddressHelper address;
address.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer ifaces = address.Assign(devices);
// ---- Q14: UdpServer on node 1, UdpClient on node 0 -------------------
uint16_t udpPort = 9;
uint32_t clientPackets = 900;
UdpServerHelper server(udpPort);
ApplicationContainer serverApp = server.Install(nodes.Get(1));
serverApp.Start(Seconds(0.0));
serverApp.Stop(Seconds(simTime));
UdpClientHelper client(ifaces.GetAddress(1), udpPort);
client.SetAttribute("MaxPackets", UintegerValue(clientPackets));
client.SetAttribute("Interval", TimeValue(MilliSeconds(10)));
client.SetAttribute("PacketSize", UintegerValue(1024));
ApplicationContainer clientApp = client.Install(nodes.Get(0));
clientApp.Start(Seconds(1.0));
clientApp.Stop(Seconds(simTime));
// ---- Q15: constant bit rate flow node 0 -> node 1 --------------------
uint16_t cbrPort = 10;
OnOffHelper onoff("ns3::UdpSocketFactory",
InetSocketAddress(ifaces.GetAddress(1), cbrPort));
onoff.SetConstantRate(DataRate(cbrRate), cbrPacketSize); // OnTime 1, OffTime 0
ApplicationContainer cbrApp = onoff.Install(nodes.Get(0));
cbrApp.Start(Seconds(1.0));
cbrApp.Stop(Seconds(simTime));
PacketSinkHelper sinkHelper("ns3::UdpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), cbrPort));
ApplicationContainer sinkApp = sinkHelper.Install(nodes.Get(1));
sinkApp.Start(Seconds(0.0));
sinkApp.Stop(Seconds(simTime));
// pcap of node 1's Wi-Fi interface, for Wireshark
phy.EnablePcap("adhoc-cbr", devices.Get(1));
Simulator::Stop(Seconds(simTime));
Simulator::Run();
// ---- report ---------------------------------------------------------
Ptr<MobilityModel> m0 = nodes.Get(0)->GetObject<MobilityModel>();
Ptr<MobilityModel> m1 = nodes.Get(1)->GetObject<MobilityModel>();
Vector p0 = m0->GetPosition();
Vector p1 = m1->GetPosition();
Ptr<UdpServer> udpServer = DynamicCast<UdpServer>(serverApp.Get(0));
Ptr<PacketSink> sink = DynamicCast<PacketSink>(sinkApp.Get(0));
double active = simTime - 1.0; // both sources run from 1 s to simTime
std::cout << "Node 0 at (" << p0.x << ", " << p0.y << ", " << p0.z << ") m, "
<< "node 1 at (" << p1.x << ", " << p1.y << ", " << p1.z << ") m, "
<< "distance " << m0->GetDistanceFrom(m1) << " m" << std::endl;
std::cout << "UdpClient : sent " << clientPackets << " packets of 1024 bytes" << std::endl;
std::cout << "UdpServer : received " << udpServer->GetReceived() << " packets, lost "
<< udpServer->GetLost() << std::endl;
std::cout << "CBR sink : received " << sink->GetTotalRx() << " bytes in " << active
<< " s = " << sink->GetTotalRx() * 8.0 / active / 1000.0 << " kbit/s"
<< std::endl;
Simulator::Destroy();
return 0;
}Diagram
z = 1.5 m z = 1.5 m
n0 (0, 0, 1.5) ~~~~ 802.11a ad-hoc, 6 Mbit/s ~~~~ n1 (d, 0, 1.5)
10.1.1.1 10.1.1.2
UdpClient ---- port 9 ----> UdpServer
OnOff CBR ---- port 10 ----> PacketSinkOutput
Expected output for the default run (ns-3 is not installed here; the listing was checked by reading against the ns-3.36 helper API):
$ ./ns3 run "scratch/adhoc-cbr --distance=50"
Node 0 at (0, 0, 1.5) m, node 1 at (50, 0, 1.5) m, distance 50 m
UdpClient : sent 900 packets of 1024 bytes
UdpServer : received 900 packets, lost 0
CBR sink : received 562500 bytes in 9 s = 500 kbit/sThe file adhoc-cbr-1-0.pcap (node 1, device 0) is also written and opens in Wireshark.
Explanation
GetDistanceFrom computes the straight-line distance between the two position vectors:
With node 0 at (0, 0, 1.5) and node 1 at (50, 0, 1.5) the y and z terms cancel and d is 50 m. If you set the nodes at different heights the z term counts too, which is why the manual says “3D plane”.
Ad-hoc mode means both stations talk directly; there is no association with an access point and no routing protocol is needed because both nodes are on the same subnet. Fixing the rate at 6 Mbit/s removes rate adaptation from the experiment, so the only thing that changes with distance is whether a frame is decoded or not.
Question 14
Problem Statement
Write in lab recordInstall UDP server and Client at these two nodes.
Solution
Write in lab recordSteps
- In the same script,
UdpServerHelper server(9)installed on node 1 runs from 0 s to 10 s.UdpServercounts packets and, because the client adds aSeqTsHeader, also counts lost packets from gaps in the sequence numbers. UdpClientHelper client(10.1.1.2, 9)installed on node 0 with attributesMaxPackets900,Interval10 ms andPacketSize1024 bytes; it runs from 1 s to 10 s, so exactly 900 packets are offered.- Run with
--verboseto see the per-packet log lines from both applications:./ns3 run "scratch/adhoc-cbr --distance=50 --verbose=1". - Read
GetReceived()andGetLost()on theUdpServerafterSimulator::Run()and write both in the record.
Output
Expected log lines with --verbose=1 (two of 900 shown; ns-3 prints times in nanoseconds):
TraceDelay TX 1024 bytes to 10.1.1.2 Uid: 4 Time: +1s
TraceDelay: RX 1024 bytes from 10.1.1.1 Sequence Number: 0 Uid: 4 TXtime: +1e+09ns RXtime: +1.00163e+09ns Delay: +1.63e+06ns
TraceDelay TX 1024 bytes to 10.1.1.2 Uid: 6 Time: +1.01s
TraceDelay: RX 1024 bytes from 10.1.1.1 Sequence Number: 1 Uid: 6 TXtime: +1.01e+09ns RXtime: +1.01163e+09ns Delay: +1.63e+06ns
...
UdpServer : received 900 packets, lost 0Explanation
The client offers 1024 bytes every 10 ms, which is
well under the 6 Mbit/s link, so at 50 m nothing is lost. The 1.63 ms delay is almost all transmission time: 1024 bytes of payload plus 8 bytes UDP, 20 bytes IP, 8 bytes LLC/SNAP and 34 bytes MAC header and FCS is 1094 bytes, and
plus the OFDM preamble (20 microseconds), DIFS and one backoff slot. Propagation over 50 m is 0.17 microseconds and does not show at this precision. UdpServer and UdpClient are the right pair here (rather than the echo pair from Session 1) because the server keeps the received and lost counters that the record needs.
Question 15
Problem Statement
Write in lab recordSetup a CBR transmission between these nodes.
Solution
Write in lab recordSteps
OnOffHelper onoff("ns3::UdpSocketFactory", InetSocketAddress(10.1.1.2, 10))on node 0.SetConstantRate(DataRate("500kb/s"), 500)setsOnTimeto a constant 1,OffTimeto a constant 0,DataRate500 kb/s andPacketSize500 bytes, which is exactly a constant bit rate source.PacketSinkHelperon node 1 at port 10 receives it;GetTotalRx()gives the bytes delivered.- Both run from 1 s to 10 s. Run the script three times, at 50 m, 100 m and 150 m, and fill the table below.
- Optional:
--cbrRate=1Mb/sto see the effect of a heavier load.
Output
Expected values at the three distances (rows 2 and 3 depend on the random error model and will vary a little between runs; label them “approximate” in the record):
| Distance | UdpServer received / sent | UdpServer lost | CBR bytes received | CBR throughput |
|---|---|---|---|---|
| 50 m | 900 / 900 | 0 | 562500 | 500 kbit/s |
| 100 m | about 610 / 900 | about 290 | about 380000 | about 338 kbit/s |
| 150 m | 0 / 900 | 900 | 0 | 0 |
$ ./ns3 run "scratch/adhoc-cbr --distance=150"
Node 0 at (0, 0, 1.5) m, node 1 at (150, 0, 1.5) m, distance 150 m
UdpClient : sent 900 packets of 1024 bytes
UdpServer : received 0 packets, lost 0
CBR sink : received 0 bytes in 9 s = 0 kbit/sAt 150 m UdpServer reports lost 0 because it never saw a single sequence number; the loss is the 900 packets that never arrived, which you compute yourself.
Explanation
Packet interval from the formula sheet:
so in 9 s the source sends 1125 packets of 500 bytes, which is 562500 bytes, and the sink throughput is 8 times that over 9 s, exactly 500 kbit/s when nothing is lost.
Why distance matters: the default channel uses the log-distance propagation loss model with exponent 3 and a reference loss of 46.7 dB at 1 m, and the PHY transmits at 16 dBm. The received power is
The noise floor of a 20 MHz 802.11a receiver with the default 7 dB noise figure is about -94 dBm, so the signal-to-noise ratio is
| Distance | Received power | SNR | Result at 6 Mbit/s BPSK |
|---|---|---|---|
| 50 m | -81.7 dBm | 12.3 dB | every frame decoded |
| 100 m | -90.7 dBm | 3.3 dB | frame error rate large; part of the traffic lost |
| 150 m | -96.0 dBm | below 0 dB | nothing decoded |
Every 10 dB more path loss needs 2.15 times the distance with exponent 3, so the link goes from perfect to dead in a narrow band around 100 m. Put these three rows in the record next to the measured table.
Formula Sheet
Do not copy. Read for understanding and the vivaThroughput
Bytes received at the sink divided by the time the flow was active, converted to bits per second:
Bandwidth-delay product
The amount of data in flight on a link of capacity and round-trip time . A TCP window smaller than this cannot fill the link:
For the Session 10 defaults, and one-way delay give and .
Transmission and propagation delay
where is packet size in bits, link rate, distance and signal speed (about in copper or fibre).
Constant bit rate traffic
An OnOff application with packet size bytes and rate bit/s sends one packet every
TCP congestion window
Slow start doubles the window every RTT until the threshold; congestion avoidance adds one segment per RTT; a loss halves it (TCP NewReno):
The maximum throughput of one TCP flow is bounded by
Packet loss
Viva Questions
Do not copy. Read for understanding and the viva- Q: Why
ConstantPositionMobilityModelwhen nothing moves? A: Every Wi-Fi node needs aMobilityModelobject so the channel can ask for its position; the constant model is the one that stores a fixed position and never updates it. - Q: What does
ListPositionAllocatordo thatSetPositionAllocatorwith a grid does not? A: It lets you give an explicitVector(x, y, z)for each node in install order, so you control the exact 3D coordinates. - Q: What makes the network ad-hoc? A:
WifiMacHelper::SetType("ns3::AdhocWifiMac"). There is no access point and no association; frames go station to station. - Q: Why fix the rate with
ConstantRateWifiManager? A: So the PHY rate does not adapt with distance. The measured loss then comes only from the propagation model, which is what the question studies. - Q: How does an
OnOffHelperbecome CBR? A:SetConstantRatesetsOnTimeto a constant 1 andOffTimeto a constant 0, so the source is always on and sends one packet every 8L/R seconds. - Q: Why does
UdpServerreport lost 0 at 150 m when nothing arrived? A: It counts gaps in the sequence numbers it sees; with no packets seen there are no gaps. The real loss is sent minus received. - Q: Which model decides that 150 m is out of range? A:
LogDistancePropagationLossModelwith exponent 3; at 150 m the received power falls below the noise floor and the error-rate model rejects every frame. - Q: Why is the delay about 1.6 ms for a 1024-byte packet? A: Transmission time at 6 Mbit/s for the 1094-byte frame (1.46 ms) plus preamble, DIFS and backoff; propagation over 50 m is negligible.
Common Mistakes
Do not copy. Read for understanding and the viva- Leaving the default Wi-Fi standard (802.11ax in ns-3.36 and later) and asking for
OfdmRate6Mbps; the run aborts because that mode does not exist for the standard. CallSetStandard(WIFI_STANDARD_80211a)first. - Installing the mobility model after the Wi-Fi devices are used, or not at all; the channel then cannot compute a distance and the simulation asserts.
- Calling
GetReceived()on theApplicationContainerentry withoutDynamicCast<UdpServer>; the baseApplicationclass has no such method. - Reading the CBR figure as packets per second instead of bytes;
GetTotalRx()returns bytes, so multiply by 8 and divide by the active time to get bit/s. - Running only one distance. The question is about the effect of distance; the record needs at least three rows.
- Forgetting that the client starts at 1 s while the server starts at 0 s, then dividing by 10 s instead of 9 s in the throughput.
Session Summary
Write in lab record- Source listing of
adhoc-cbr.ccwith the header comment and the ASCII topology diagram (two nodes with their 3D coordinates) - The distance formula with the two position vectors substituted
- Run output at 50 m with the
UdpServerreceived and lost counts and the CBR bytes - Two log lines from
--verbose=1showing the UDP client TX and server RX with the delay - The three-distance table (50, 100, 150 m) with received bytes, throughput and the received-power and SNR columns
- The 8 ms packet interval calculation and the 562500-byte check