Installation

this part will be supplemented soon.

Build and setup

this part will be supplemented soon.

Simulation study first part

build our own script “first.cc”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#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("FirstScriptExample");
int main(int argc, char *argv[])
{
Time::SetResolution(Time::NS);
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
NodeContainer nodes;
nodes.Create(2);

PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
pointToPoint.SetChannelAttribute("Delay", StringValue("2ms"));

NetDeviceContainer devices;//devices are on the nodes.
devices = pointToPoint.Install(nodes);//也就是点对点连接两个节点,就成了网络节点,因为有了网络链路,称为了net devices
//信道为pointToPoint在上面有所定义,其性质也是。
InternetStackHelper stack;//protocol stacks installed on our nodes.
stack.Install(nodes);//install an internet stack on each of the nodes.

Ipv4AddressHelper address;
address.SetBase("10.1.1.0", "255.255.255.0");

Ipv4InterfaceContainer interfaces = address.Assign(devices);//actual address assignment
//Now we have a point-to-point network built, with stacks installed and IP addresses assigned

UdpEchoServerHelper echoServer(9);//UdpEchoServerHelper. As usual, this isn’t the application itself,
// it is an object used to help us create the actual applications.
//9 is the port number.

ApplicationContainer serverApps = echoServer.Install(nodes.Get(1));//nodes.Get(1), index number one of the NodeContainer
// which returns a smart pointer to a node object — Ptr<Node>)
serverApps.Start(Seconds(1.0));//app requires a time to start generating the traffic and an optional time to stop.
serverApps.Stop(Seconds(10.0));//end at ten seconds into the simulation.

UdpEchoClientHelper echoClient(interfaces.GetAddress(1), 9);//也就是确认发送源,是1号node的9端口
echoClient.SetAttribute("MaxPackets", UintegerValue(1));//maximum number of packets we allow it to send during the simulation
echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0)));//tells the client how long to wait between packets
echoClient.SetAttribute("PacketSize", UintegerValue(1024));//how large its packet payloads should be.

ApplicationContainer clientApps = echoClient.Install(nodes.Get(0));
clientApps.Start(Seconds(2.0));
clientApps.Stop(Seconds(10.0));

//Now at this point we can run the simulation.
Simulator::Stop(Seconds(11.0));
//important to call Simulator::Stop before calling Simulator::Run;
// otherwise, Simulator::Run may never return control to the main program to execute the stop
Simulator::Run();
Simulator::Destroy();
return 0;
}

then we run the build command, in the terminal

1
./ns3 build

then run the exec file

1
./ns3 run scratch/first

or we can also use the clion to build and run the script, more convenient.

There are two ways starting our logging modules.

In our script we can see

1
2
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);

this will give the log of the class “UdpEchoClientHelper” and “UdpEchoServerApplication”.

Other than this method, we can also use environment variable settings, to set

1
export 'NS_LOG=UdpEchoClientApplication=level_all'

In the output we can see all the logs, but there is a question, like this

image-20240702154617693

what can we determine the source of the log, where is it from?

so we should improve the form of the log printed, using

1
export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'

this time, shell is the only way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
UdpEchoServerApplication:UdpEchoServer(0x60000215ebc0)
UdpEchoClientApplication:UdpEchoClient(0x13870af60)
UdpEchoClientApplication:SetDataSize(0x13870af60, 1024)
UdpEchoServerApplication:StartApplication(0x60000215ebc0)
UdpEchoClientApplication:StartApplication(0x13870af60)
UdpEchoClientApplication:ScheduleTransmit(0x13870af60, +0ns)
UdpEchoClientApplication:Send(0x13870af60)
UdpEchoClientApplication:Send(): At time +2s client sent 1024 bytes to 10.1.1.2 port 9
UdpEchoServerApplication:HandleRead(0x60000215ebc0, 0x13a004bc0)
At time +2.00369s server received 1024 bytes from 10.1.1.1 port 49153
Echoing packet
At time +2.00369s server sent 1024 bytes to 10.1.1.1 port 49153
UdpEchoClientApplication:HandleRead(0x13870af60, 0x138706560)
UdpEchoClientApplication:HandleRead(): At time +2.00737s client received 1024 bytes from 10.1.1.2 port 9
UdpEchoClientApplication:StopApplication(0x13870af60)
UdpEchoServerApplication:StopApplication(0x60000215ebc0)
UdpEchoClientApplication:~UdpEchoClient(0x13870af60)
UdpEchoServerApplication:~UdpEchoServer(0x60000215ebc0)

we can also add the log of server functions, like this

1
export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:UdpEchoServerApplication=level_all|prefix_func'

using single colon to seperate the two parts.

It is also sometimes useful to be able to see the simulation time at which a log message is generated. You can do this by ORing in the prefix_time bit.

1
2
export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time:
UdpEchoServerApplication=level_all|prefix_func|prefix_time'

then the output would be

image-20240702155024434

some things may also be covered that you can not see, so you can enable all of the logging components,

1
export 'NS_LOG=*=level_all|prefix_func|prefix_time'

And you can write logs generated into a file

1
./ns3 run scratch/first > log.out 2>&1

Notice: shell environment’s level is higher than the Log level set in the script. For example, if you use

1
NS_LOG_COMPONENT_DEFINE("FirstScriptExample");

in the script, and also add

1
NS_LOG_INFO("Creating Topology");

before

1
2
NodeContainer nodes;
nodes.Create(2);

and at the same time use

1
export NS_LOG=""

then you will not see the “Creating Topology”. But if you use

1
export NS_LOG=FirstScriptExample=info

to emphasize the FirstSctiptExample and “info”, you will see

image-20240702161409934

in the log.

Command line arguments

Overriding default attributes

We can change the behavior of the script by “command line arguments“. There is a method parsing command line arguments and automatically set local and global variables based on those arguments.

1
2
3
4
5
6
7
8
9
10
int
main(int argc, char *argv[])
{
...

CommandLine cmd;
cmd.Parse(argc, argv);

...
}

For example,

1
./ns3 run "scratch/first --PrintHelp"

will print the help content like

image-20240703021426070

Recall the attributes we set previously

1
2
3
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
pointToPoint.SetChannelAttribute("Delay", StringValue("2ms"));

So we can use parsing command line to print these attributes, by

1
./ns3 run "scratch/first --PrintAttributes=ns3::PointToPointNetDevice"

Namely point at the “PointToPointNetDevice”. Seeing the output, you will find

image-20240703021900146

This is the default value that will be used when a PointToPointNetDevice is created in the system. We override the default using SetDeviceAttribute and SetChannelAttribute. So if we want to use the default value, we should delete the SetDeviceAttribute and SetChannelAttribute, just

1
2
3
4
5
6
7
NodeContainer nodes;
nodes.Create(2);

PointToPointHelper pointToPoint;

NetDeviceContainer devices;
devices = pointToPoint.Install(nodes);

We can also set these attributes through the command line.

1
2
3
./ns3 run "scratch/first
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms"

However if we desire to set the speed-of-light delay of the channel, we can run

1
./ns3 run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"

You will see the output caused by 2ms delay comes from

1
2
3
4
5
6
7
8
9
10
11
+0.000000000s UdpEchoServerApplication:UdpEchoServer(0x1df20f0)
+1.000000000s UdpEchoServerApplication:StartApplication(0x1df20f0)
At time +2s client sent 1024 bytes to 10.1.1.2 port 9
+2.003686400s UdpEchoServerApplication:HandleRead(0x1df20f0, 0x1de0250)
+2.003686400s At time +2.00369s server received 1024 bytes from 10.1.1.1 port 49153
+2.003686400s Echoing packet
+2.003686400s 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
+10.000000000s UdpEchoServerApplication:StopApplication(0x1df20f0)
UdpEchoServerApplication:DoDispose(0x1df20f0)
UdpEchoServerApplication:~UdpEchoServer(0x1df20f0)

from 2s to 2.00369s

We can complete the whole settings,

1
2
3
4
./ns3 run "scratch/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms
--ns3::UdpEchoClient::MaxPackets=2"

A question is how to learn about all of these attributes, we can use “PrintGroups” to list the attributes of the corresponding module.

1
2
3
4
5
./ns3 run "scratch/myfirst --PrintGroup=PointToPoint"
TypeIds in group PointToPoint:
ns3::PointToPointChannel
ns3::PointToPointNetDevice
ns3::PppHeader

Another way to find the attributes’ names is to search in the NS3-Doxygen.

Hooking Your Own Values

We can add our own hooks to the command line system, using the Addvalue method to the command line parser.

Let’s add a local variable called nPackets to the main function.

1
2
3
4
5
6
7
8
9
10
int
main(int argc, char *argv[])
{
uint32_t nPackets = 1;

CommandLine cmd;
cmd.AddValue("nPackets", "Number of packets to echo", nPackets);
cmd.Parse(argc, argv);

...

Because previously we set 1 of the number of packets.

1
echoClient.SetAttribute("MaxPackets", UintegerValue(nPackets));

then

1
2
./ns3 build
./ns3 run "scratch/myfirst --PrintHelp"

In the output, you should see your new User Argument listed in the help display.

1
2
3
4
5
6
7
8
9
10
11
Program Options:
--nPackets: Number of packets to echo [1]

General Arguments:
--PrintGlobals: Print the list of globals.
--PrintGroups: Print the list of groups.
--PrintGroup=[group]: Print all TypeIds of group.
--PrintTypeIds: Print all TypeIds.
--PrintAttributes=[typeid]: Print all attributes of typeid.
--PrintVersion: Print the ns-3 version.
--PrintHelp: Print this help message.

If you want to specify the number of packets to do, now you can do so by setting the —nPackets in the command line.

1
./ns3 run "scratch/myfirst --nPackets=2"