#include "ns3/core-module.
h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/flow-monitor-module.h"
/**
The network looks like this
n0--| |--n2
|--n4---n5--|
n1--| |--n3
LAN1 LAN2
We install UdpEchoClient on node 0
We install UdpEchoServer on node 2.
Run the program with
./waf --run LayerTracing --ip
to enable IP-level logging. You will notice that the packet will be printed as it travels from node 0, to node 4, to node 5, to node 2.
Then node 2 will reply to node 0. The packet will be printed, starting from the IPv4 header
To enable data-link layer tracing, and print MAC headers, run it with --mac
./waf --run LayerTracing --mac
You will notice that the packet has its data-link layer header replaced as it traverses different links.
It will have an Ethernet header going from node 0, to node 4
Node 4 removes the ethernet header, and attaches a PPP header when it passes it to node 5. This is because the link between node 4 & node 5 is
of type PPP.
In addition, before packets are sent, nodes will make ARP messages to obtain the MAC address corresponding to IPv4 Addresses before messages
are sent.
*/
NS_LOG_COMPONENT_DEFINE ("TracingExample");
using namespace ns3;
//For printing in color
#define GREEN_CODE "\033[32m"
#define PURPLE_CODE "\033[95m"
#define BOLD_CODE "\033[1m"
#define END_CODE "\033[0m"
bool mac_logging = false;
bool ip_logging = false;
void MacTxTrace (std::string context, Ptr<const Packet> packet)
{
if (mac_logging)
{
NS_LOG_UNCOND (PURPLE_CODE << "Time: " << Now().GetSeconds() << "\t" << BOLD_CODE << context << END_CODE);
NS_LOG_UNCOND (packet->ToString ());
}
}
void MacRxTrace (std::string context, Ptr<const Packet> packet)
{
if (mac_logging)
{
NS_LOG_UNCOND (GREEN_CODE << "Time: " << Now().GetSeconds() << "\t" << BOLD_CODE << context << END_CODE);
NS_LOG_UNCOND (packet->ToString ());
}
}
void IpRx (std::string context, Ptr< const Packet > packet, Ptr< Ipv4 > ipv4, uint32_t interface)
{
if (ip_logging)
{
NS_LOG_UNCOND (GREEN_CODE << "Time: " << Now().GetSeconds() << "\t" << BOLD_CODE << context << END_CODE);
NS_LOG_UNCOND (packet->ToString ());
}
}
void IpTx (std::string context, Ptr< const Packet > packet, Ptr< Ipv4 > ipv4, uint32_t interface)
{
if (ip_logging)
{
NS_LOG_UNCOND (PURPLE_CODE << "Time: " << Now().GetSeconds() << "\t"<< BOLD_CODE << context << END_CODE);
NS_LOG_UNCOND (packet->ToString ());
}
}
int main (int argc, char *argv[])
{
CommandLine cmd;
uint32_t n = 2; //Number of nodes per LAN
double number_of_packets = 1;
double interval = 1;
double simulation_time = 10; // Simulation time
[Link] ("n", "Number of nodes per LAN", n);
[Link] ("i", "Number of nodes per LAN", interval);
[Link] ("t", "Simulation Time (seconds)", simulation_time);
[Link] ("p", "number of packets", number_of_packets);
[Link] ("mac", "Enable MAC layer logging", mac_logging);
[Link] ("ip", "Enable IP-level logging", ip_logging);
[Link] (argc, argv);
LogComponentEnable ("TracingExample", LOG_LEVEL_DEBUG);
NodeContainer lan1_nodes;
NodeContainer lan2_nodes;
NodeContainer routers;
lan1_nodes.Create (n);
lan2_nodes.Create (n);
[Link] (2);
/*
Setup the connection between the middle router nodes
*/
PointToPointHelper p2p;
[Link] ("Delay", TimeValue (MilliSeconds (2)));
[Link] ("DataRate", DataRateValue(DataRate ("10Mbps")));
NetDeviceContainer router_devs = [Link] (routers);
lan1_nodes.Add ([Link](0)); //first router is also in LAN 1
CsmaHelper csma1;
[Link] ("Delay", StringValue ("10us"));
[Link] ("DataRate", StringValue ("1Gbps"));
NetDeviceContainer lan1_devs = [Link] (lan1_nodes);
lan2_nodes.Add ([Link](1)); //Second router is also in LAN 2
CsmaHelper csma2;
[Link] ("Delay", StringValue ("10us"));
[Link] ("DataRate", StringValue ("1Gbps"));
NetDeviceContainer lan2_devs = [Link] (lan2_nodes);
//Setup IPs
InternetStackHelper stack;
[Link] ();
Ipv4AddressHelper address;
[Link] ("[Link]", "[Link]");
Ipv4InterfaceContainer lan1_interface = [Link] (lan1_devs);
[Link] ("[Link]", "[Link]");
Ipv4InterfaceContainer lan2_interface = [Link] (lan2_devs);
[Link] ("[Link]", "[Link]");
Ipv4InterfaceContainer router_interface = [Link] (router_devs);
uint16_t port_number = 9999;
//A UdpEchoServer is installed at node 0 in lan2_nodes
UdpEchoServerHelper server_helper (port_number);
ApplicationContainer serverApps = server_helper.Install (lan2_nodes.Get (0));
[Link] (Seconds (0.5));
[Link] (Seconds (simulation_time));
UdpEchoClientHelper client_helper (lan2_interface.GetAddress(0));
client_helper.SetAttribute ("Interval", TimeValue (Seconds (interval)));
client_helper.SetAttribute ("MaxPackets", UintegerValue (number_of_packets));
client_helper.SetAttribute ("RemotePort", UintegerValue (port_number));
client_helper.SetAttribute ("PacketSize", UintegerValue (1400));
//We will install a UdpEchoClient at node 0 in lan1_nodes
ApplicationContainer clientApps = client_helper.Install (lan1_nodes.Get (0));
[Link] (Seconds (0.5));
[Link] (Seconds (simulation_time));
//This step is needed so that routers know how to forward packets
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
//Let us trace packets on MAC-level. We can connect to these trace sources.
//Incoming packets on CsmaNetDevice on data-link layer level (MAC). They will have Ethernet header.
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacTx", MakeCallback (&MacTxTrace));
//Incoming packet on a PointToPointNetDevice on data-link layer level (MAC). They will have PPP header.
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacTx", MakeCallback (&MacTxTrace));
//MAC Reception traces.
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacRx", MakeCallback (&MacRxTrace));
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacRx", MakeCallback (&MacRxTrace));
//Let's trace packets on IP-level
Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Tx", MakeCallback (&IpTx));
Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Rx", MakeCallback (&IpRx));
Packet::EnablePrinting ();
Ptr<FlowMonitor> flowMonitor;
FlowMonitorHelper flowHelper;
flowMonitor = [Link]();
Simulator::Stop ( Seconds (simulation_time));
Simulator::Run ();
flowMonitor->SerializeToXmlFile ("[Link]", true, true);
//This code executes after simulation is completed.
Simulator::Destroy ();
return 0;