Skip to content

Session 1

Point-to-point topology and UDP echo

Updated View as Markdown

The first session builds the smallest possible network in NS-3, two nodes on a point-to-point link, and runs a UDP client and server over it. Every later topology is this pattern repeated.

Objectives

Do not copy. Read for understanding and the viva
  • Complete questions 1 to 2 of the manual: point-to-point topology and udp echo
  • 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
QuestionRequirementStatus
Q1Create a simple point to point network topology using two nodesComplete
Q2Create a UdpClient and UdpServer nodes and communicate at a fixed data rateComplete

Preparation

Do not copy. Read for understanding and the viva
  • Read first.cc in the NS-3 tutorial; it is the answer to question 1 with different parameters.
  • Know the helper sequence: NodeContainer, PointToPointHelper (DataRate, Delay), InternetStackHelper, Ipv4AddressHelper, UdpEchoServerHelper and UdpEchoClientHelper.
  • Fixed data rate for the client means setting MaxPackets, Interval and PacketSize attributes; compute the rate with the CBR formula below.

Question 1

Problem Statement

Write in lab record

Create a simple point to point network topology using two nodes.

Solution

Write in lab record

Steps

  1. Install ns-3 (3.36 or later) and build it once: ./ns3 configure --enable-examples && ./ns3 build.
  2. Save the program below as scratch/p2p_two_nodes.cc. Anything in scratch/ is compiled automatically.
  3. Run ./ns3 run scratch/p2p_two_nodes. The first run compiles the file; later runs start at once.
  4. Draw the topology in the record: two boxes, one line, the link parameters and the two addresses.
  5. List the pcap files with ls session1-*.pcap. They are empty here (no traffic) and fill up in question 2.

Program

The five helper calls are the skeleton of every NS-3 script: nodes, channel plus devices, protocol stack, addresses, then run.

p2p_two_nodes.cccpp
/*
 * MCSL-223 Section 1, Session 1, Question 1
 * Point-to-point topology with two nodes.
 *
 * Build: copy to ns-3.36+/scratch/ and run
 *   ./ns3 run scratch/p2p_two_nodes
 *
 * Topology:
 *   n0 ---------- n1
 *      5 Mbps, 2 ms
 *   10.1.1.1      10.1.1.2
 */
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE("P2PTwoNodes");

/*
 * main: creates two nodes, joins them with one point-to-point link,
 * installs the IP stack, assigns 10.1.1.0/24 and prints what was built.
 * No traffic is sent; question 2 adds the applications.
 */
int
main(int argc, char* argv[])
{
    std::string dataRate = "5Mbps";
    std::string delay = "2ms";

    CommandLine cmd(__FILE__);
    cmd.AddValue("dataRate", "Link data rate", dataRate);
    cmd.AddValue("delay", "Link propagation delay", delay);
    cmd.Parse(argc, argv);

    // 1. Nodes: the two end hosts.
    NodeContainer nodes;
    nodes.Create(2);

    // 2. Channel and net devices: one full-duplex point-to-point link.
    PointToPointHelper p2p;
    p2p.SetDeviceAttribute("DataRate", StringValue(dataRate));
    p2p.SetChannelAttribute("Delay", StringValue(delay));
    NetDeviceContainer devices = p2p.Install(nodes);

    // 3. Protocol stack: IPv4, UDP, TCP on both nodes.
    InternetStackHelper stack;
    stack.Install(nodes);

    // 4. Addresses: one /24 subnet for the link.
    Ipv4AddressHelper address;
    address.SetBase("10.1.1.0", "255.255.255.0");
    Ipv4InterfaceContainer interfaces = address.Assign(devices);

    // Report the topology so the lab record has something to show.
    std::cout << "Nodes created      : " << nodes.GetN() << std::endl;
    std::cout << "Link               : " << dataRate << ", delay " << delay << std::endl;
    for (uint32_t i = 0; i < nodes.GetN(); ++i)
    {
        std::cout << "n" << i << " address        : " << interfaces.GetAddress(i) << std::endl;
    }

    // Write a pcap per device (session1-0-0.pcap, session1-1-0.pcap).
    p2p.EnablePcapAll("session1");

    Simulator::Stop(Seconds(10.0));
    Simulator::Run();
    std::cout << "Simulation finished at " << Simulator::Now().GetSeconds() << " s" << std::endl;
    Simulator::Destroy();
    return 0;
}

Output

Topology drawn for the record:

        5 Mbit/s, 2 ms
  n0 ------------------- n1
  10.1.1.1           10.1.1.2
  (10.1.1.0/24, one point-to-point channel)

Expected console output (NS-3 is not installed on the machine that wrote this page, so values come from the parameters, not from a run):

Nodes created      : 2
Link               : 5Mbps, delay 2ms
n0 address        : 10.1.1.1
n1 address        : 10.1.1.2
Simulation finished at 10 s

Change the link from the command line without editing the file: ./ns3 run "scratch/p2p_two_nodes --dataRate=10Mbps --delay=5ms".

Explanation

What each helper call creates, for the viva:

CallObjects createdKey attributes
NodeContainer::Create(2)two Node objects, ids 0 and 1none
PointToPointHelper::Installtwo PointToPointNetDevice, one PointToPointChannel, two DropTailQueueDataRate (device), Delay (channel), MaxSize (queue, 100 packets)
InternetStackHelper::InstallIpv4L3Protocol, ArpL3Protocol, UdpL4Protocol, TcpL4Protocol, loopback device, list routingIpForward true
Ipv4AddressHelper::Assignone Ipv4Interface per device with an address and maskbase 10.1.1.0, mask /24
EnablePcapAllone pcap file per deviceprefix session1

NodeContainer::Create(2) makes two empty nodes. PointToPointHelper::Install creates one PointToPointNetDevice on each node and a PointToPointChannel between them; DataRate lives on the device (it decides how long a packet takes to serialise) and Delay on the channel (propagation time). InternetStackHelper adds IPv4, ARP, UDP and TCP to both nodes. Ipv4AddressHelper::Assign hands out 10.1.1.1 and 10.1.1.2 in device order. Nothing is scheduled, so Simulator::Run returns as soon as the stop event at 10 s fires. From the formula sheet, one 1024-byte packet on this link takes ttrans=8×1054/5×106=1.686ms to serialise (1024 bytes payload plus 8 UDP, 20 IP and 2 PPP header bytes) and tprop=2ms to propagate, so ttotal=3.686ms; question 2 shows exactly that number in the log.

Question 2

Problem Statement

Write in lab record

Create a UdpClient and UdpServer nodes and communicate at a fixed data rate.

Solution

Write in lab record

Steps

  1. Pick the fixed rate: packet size L = 1024 bytes and rate R = 1 Mbit/s. From the formula sheet the client interval is Δt=8L/R=8192/106=8.192ms.
  2. Save the program as scratch/udp_echo_fixed_rate.cc and run ./ns3 run scratch/udp_echo_fixed_rate.
  3. Read the client and server log lines; NS-3 prints them because the script enables LOG_LEVEL_INFO on both applications.
  4. Open session1-echo-1-0.pcap in Wireshark (n1’s device) and confirm 10 UDP packets in each direction with the filter udp.port == 9.
  5. Try another rate: ./ns3 run "scratch/udp_echo_fixed_rate --rate=2000000 --maxPackets=20" halves the interval to 4.096 ms.

Intervals for other fixed rates with a 1024-byte packet, from the same formula:

Rate RInterval 8L/RCommand line
500 kbit/s16.384 ms--rate=500000
1 Mbit/s8.192 msdefault
2 Mbit/s4.096 ms--rate=2000000
4 Mbit/s2.048 ms--rate=4000000 (80 percent of the 5 Mbit/s link)

Program

udp_echo_fixed_rate.cccpp
/*
 * MCSL-223 Section 1, Session 1, Question 2
 * UDP echo client and server on the two-node link, sending at a fixed rate.
 *
 * Build: copy to ns-3.36+/scratch/ and run
 *   ./ns3 run scratch/udp_echo_fixed_rate
 *
 * Fixed data rate: packet size L = 1024 bytes, rate R = 1 Mbit/s,
 * so the client interval is 8L/R = 8192 / 1e6 = 8.192 ms.
 *
 *   n0 (client) ---------- n1 (server, port 9)
 *   10.1.1.1   5 Mbps, 2 ms   10.1.1.2
 */
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE("UdpEchoFixedRate");

/*
 * main: builds the Session 1 link, puts a UdpEchoServer on n1 and a
 * UdpEchoClient on n0 that sends maxPackets packets of packetSize bytes
 * every 8*packetSize/rate seconds, then runs for 10 s.
 */
int
main(int argc, char* argv[])
{
    uint32_t packetSize = 1024;   // bytes
    uint32_t maxPackets = 10;
    double rateBps = 1e6;         // bit/s, the fixed data rate

    CommandLine cmd(__FILE__);
    cmd.AddValue("packetSize", "UDP payload in bytes", packetSize);
    cmd.AddValue("maxPackets", "Packets the client sends", maxPackets);
    cmd.AddValue("rate", "Client data rate in bit/s", rateBps);
    cmd.Parse(argc, argv);

    // Print the client and server log lines (the expected output).
    LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
    LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);

    NodeContainer nodes;
    nodes.Create(2);

    PointToPointHelper p2p;
    p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
    p2p.SetChannelAttribute("Delay", StringValue("2ms"));
    NetDeviceContainer devices = p2p.Install(nodes);

    InternetStackHelper stack;
    stack.Install(nodes);

    Ipv4AddressHelper address;
    address.SetBase("10.1.1.0", "255.255.255.0");
    Ipv4InterfaceContainer interfaces = address.Assign(devices);

    // Server on n1, listening on UDP port 9.
    UdpEchoServerHelper echoServer(9);
    ApplicationContainer serverApps = echoServer.Install(nodes.Get(1));
    serverApps.Start(Seconds(1.0));
    serverApps.Stop(Seconds(10.0));

    // Client on n0. Interval = 8L/R seconds gives the fixed rate.
    double intervalUs = 8.0 * packetSize / rateBps * 1e6;
    UdpEchoClientHelper echoClient(interfaces.GetAddress(1), 9);
    echoClient.SetAttribute("MaxPackets", UintegerValue(maxPackets));
    echoClient.SetAttribute("Interval", TimeValue(MicroSeconds(static_cast<uint64_t>(intervalUs))));
    echoClient.SetAttribute("PacketSize", UintegerValue(packetSize));
    ApplicationContainer clientApps = echoClient.Install(nodes.Get(0));
    clientApps.Start(Seconds(2.0));
    clientApps.Stop(Seconds(10.0));

    std::cout << "Client rate " << rateBps / 1e6 << " Mbit/s, packet " << packetSize
              << " B, interval " << intervalUs / 1000.0 << " ms, packets " << maxPackets
              << std::endl;

    p2p.EnablePcapAll("session1-echo");

    Simulator::Run();
    Simulator::Destroy();
    return 0;
}

Output

Expected output (first three and last exchanges shown; the remaining lines follow the same 8.192 ms spacing). Time stamps are computed from the link parameters: one-way delay is 1.686 ms serialisation plus 2 ms propagation, 3.686 ms.

Client rate 1 Mbit/s, packet 1024 B, interval 8.192 ms, packets 10
At time +2s client sent 1024 bytes to 10.1.1.2 port 9
At time +2.00369s server received 1024 bytes from 10.1.1.1 port 49153
At time +2.00369s server sent 1024 bytes to 10.1.1.1 port 49153
At time +2.00737s client received 1024 bytes from 10.1.1.2 port 9
At time +2.00819s client sent 1024 bytes to 10.1.1.2 port 9
At time +2.01188s server received 1024 bytes from 10.1.1.1 port 49153
At time +2.01188s server sent 1024 bytes to 10.1.1.1 port 49153
At time +2.01556s client received 1024 bytes from 10.1.1.2 port 9
At time +2.01638s client sent 1024 bytes to 10.1.1.2 port 9
At time +2.02007s server received 1024 bytes from 10.1.1.1 port 49153
At time +2.02007s server sent 1024 bytes to 10.1.1.1 port 49153
At time +2.02376s client received 1024 bytes from 10.1.1.2 port 9
...
At time +2.07373s client sent 1024 bytes to 10.1.1.2 port 9
At time +2.07741s server received 1024 bytes from 10.1.1.1 port 49153
At time +2.07741s server sent 1024 bytes to 10.1.1.1 port 49153
At time +2.0811s client received 1024 bytes from 10.1.1.2 port 9

Calculation to show in the record:

QuantityValue
Packet size L1024 bytes = 8192 bits
Fixed rate R1 Mbit/s
Interval Δt=8L/R8.192 ms
One-way delay per packet1.686 ms + 2 ms = 3.686 ms
Round trip seen by the client7.37 ms
Bytes received at server10 x 1024 = 10240
Server receive window2.00369 s to 2.07741 s = 73.7 ms
Measured throughput 8×10240/0.07371.11 Mbit/s

The measured value is 10/9 of the nominal 1 Mbit/s because ten packets span only nine intervals; with 1000 packets the ratio drops to 1.001.

Explanation

UdpEchoServerHelper(9) binds a UDP socket on port 9 of n1 and echoes every datagram back. UdpEchoClientHelper on n0 has three attributes that set the rate: PacketSize (bytes per datagram), Interval (time between datagrams) and MaxPackets (how many). Holding the size fixed and choosing the interval as 8L/R gives a constant bit rate of exactly R; that is the same idea OnOffHelper uses internally in later sessions. The server starts at 1 s and the client at 2 s so the socket is listening before the first datagram arrives. Every log line carries the simulator time, which is why the record can show the transmission and propagation delay from the formula sheet appearing in the output.

Viva Questions

Do not copy. Read for understanding and the viva
  • Q: What is the difference between a Node, a NetDevice and a Channel? A: A Node is the computer, a NetDevice is its network card plus driver, a Channel is the wire between two devices.
  • Q: Where is DataRate set and where is Delay set, and why? A: DataRate on the device because serialisation happens in the card; Delay on the channel because propagation happens on the wire.
  • Q: Why does the server receive the first packet at 2.00369 s and not at 2.002 s? A: 2 ms is propagation only; 1054 bytes at 5 Mbit/s add 1.686 ms of serialisation.
  • Q: How do you send at a fixed rate with UdpEchoClient? A: Fix PacketSize and set Interval to 8L/R seconds.
  • Q: What does Ipv4AddressHelper::Assign return? A: An Ipv4InterfaceContainer; GetAddress(i) gives the address of the i-th device in the container.
  • Q: Why start the server before the client? A: A datagram that arrives before the server socket is bound is dropped.
  • Q: What is in session1-echo-0-0.pcap? A: Every frame that entered or left device 0 of node 0, in libpcap format readable by Wireshark.
  • Q: Why does the client use port 49153? A: It is the first ephemeral port NS-3 allocates when a socket is bound without a port.

Common Mistakes

Do not copy. Read for understanding and the viva
  • Passing 8.192 to MilliSeconds(); it takes an integer and silently rounds to 8 ms. Use MicroSeconds(8192).
  • Starting the client before or at the same time as the server, so the first datagram is lost.
  • Forgetting LogComponentEnable, then reporting that “nothing happens” because the run prints nothing.
  • Reading the pcap of the wrong node; the file name is prefix-nodeId-deviceId.
  • Editing files under examples/ instead of scratch/; only scratch/ picks up new files without touching the build files.
  • Omitting the topology diagram from the record; the manual requires it with every program.

Formula Sheet

Do not copy. Read for understanding and the viva

Throughput

Bytes received at the sink divided by the time the flow was active, converted to bits per second:

Throughput=8×bytes receivedtend−tstartbit/s

Bandwidth-delay product

The amount of data in flight on a link of capacity B and round-trip time RTT. A TCP window smaller than this cannot fill the link:

BDP=B×RTT

For the Session 10 defaults, B=5Mbit/s and one-way delay 5ms give RTT=10ms and BDP=5×106×0.010=50,000bits≈6.25kB.

Transmission and propagation delay

ttrans=LB,tprop=dv,ttotal=ttrans+tprop+tqueue+tproc

where L is packet size in bits, B link rate, d distance and v signal speed (about 2×108m/s in copper or fibre).

Constant bit rate traffic

An OnOff application with packet size L bytes and rate R bit/s sends one packet every

Δt=8LR seconds

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):

cwndss(n)=2nMSS,cwndca←cwnd+MSS2cwnd,cwndloss←cwnd2

The maximum throughput of one TCP flow is bounded by

Throughputmax⁡=cwndmax⁡RTT

Packet loss

Loss rate=packets sent−packets receivedpackets sent

Session Summary

Write in lab record
  • p2p_two_nodes.cc listing with the header comment, the topology diagram and the address printout
  • udp_echo_fixed_rate.cc listing, the 40 echo log lines and the rate table (interval 8.192 ms for 1 Mbit/s, throughput 1.11 Mbit/s)
  • Wireshark screenshot of session1-echo-1-0.pcap filtered on udp.port == 9
Navigation

Type to search…

↑↓ navigate↵ selectEsc close