internet-apps: add TracerouteV4 application

This commit is contained in:
Jack Higgins
2019-12-01 15:48:58 +01:00
committed by Tommaso Pecorella
7 changed files with 1070 additions and 2 deletions

View File

@@ -0,0 +1,248 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*
*
* TraceRoute application example using AODV routing protocol.
*
*
*/
#include "ns3/aodv-module.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/wifi-module.h"
#include "ns3/v4traceroute-helper.h"
#include <iostream>
#include <cmath>
using namespace ns3;
/**
* \ingroup aodv-examples
* \ingroup examples
* \brief Test script.
*
* This script creates 1-dimensional grid topology and Traceroute the last node from the first one:
*
* [10.0.0.1] <-- step --> [10.0.0.2] <-- step --> [10.0.0.3] <-- step --> [10.0.0.4]
*
* The results should be all the intermediate hops all the way to 10.0.0.10
*
* Usage:
*
* traceroute 10.0.0.10
*/
class TracerouteExample
{
public:
TracerouteExample ();
/**
* \brief Configure script parameters
* \param argc is the command line argument count
* \param argv is the command line arguments
* \return true on successful configuration
*/
bool Configure (int argc, char **argv);
/// Run simulation
void Run ();
/**
* Report results
* \param os the output stream
*/
void Report (std::ostream & os);
private:
// parameters
/// Number of nodes
uint32_t size;
/// Distance between nodes, meters
double step;
/// Simulation time, seconds
double totalTime;
/// Write per-device PCAP traces if true
bool pcap;
/// Print aodv routes if true
bool printRoutes;
/// nodes used in the example
NodeContainer nodes;
/// devices used in the example
NetDeviceContainer devices;
/// interfaces used in the example
Ipv4InterfaceContainer interfaces;
private:
/// Create the nodes
void CreateNodes ();
/// Create the devices
void CreateDevices ();
/// Create the network
void InstallInternetStack ();
/// Create the simulation applications
void InstallApplications ();
};
int main (int argc, char **argv)
{
TracerouteExample test;
if (!test.Configure (argc, argv))
{
NS_FATAL_ERROR ("Configuration failed. Aborted.");
}
test.Run ();
test.Report (std::cout);
return 0;
}
//-----------------------------------------------------------------------------
TracerouteExample::TracerouteExample ()
: size (10),
step (50),
totalTime (100),
pcap (false),
printRoutes (false)
{
}
bool
TracerouteExample::Configure (int argc, char **argv)
{
// Enable AODV logs by default. Comment this if too noisy
// LogComponentEnable("AodvRoutingProtocol", LOG_LEVEL_ALL);
SeedManager::SetSeed (12345);
CommandLine cmd;
cmd.AddValue ("pcap", "Write PCAP traces.", pcap);
cmd.AddValue ("printRoutes", "Print routing table dumps.", printRoutes);
cmd.AddValue ("size", "Number of nodes.", size);
cmd.AddValue ("time", "Simulation time, s.", totalTime);
cmd.AddValue ("step", "Grid step, m", step);
cmd.Parse (argc, argv);
return true;
}
void
TracerouteExample::Run ()
{
CreateNodes ();
CreateDevices ();
InstallInternetStack ();
InstallApplications ();
std::cout << "Starting simulation for " << totalTime << " s ...\n";
Simulator::Stop (Seconds (totalTime));
Simulator::Run ();
Simulator::Destroy ();
}
void
TracerouteExample::Report (std::ostream &)
{
}
void
TracerouteExample::CreateNodes ()
{
std::cout << "Creating " << (unsigned)size << " nodes " << step << " m apart.\n";
nodes.Create (size);
// Name nodes
for (uint32_t i = 0; i < size; ++i)
{
std::ostringstream os;
os << "node-" << i;
Names::Add (os.str (), nodes.Get (i));
}
// Create static grid
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (step),
"DeltaY", DoubleValue (0),
"GridWidth", UintegerValue (size),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (nodes);
}
void
TracerouteExample::CreateDevices ()
{
WifiMacHelper wifiMac;
wifiMac.SetType ("ns3::AdhocWifiMac");
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
wifiPhy.SetChannel (wifiChannel.Create ());
WifiHelper wifi;
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("OfdmRate6Mbps"), "RtsCtsThreshold", UintegerValue (0));
devices = wifi.Install (wifiPhy, wifiMac, nodes);
if (pcap)
{
wifiPhy.EnablePcapAll (std::string ("aodv"));
}
}
void
TracerouteExample::InstallInternetStack ()
{
AodvHelper aodv;
// you can configure AODV attributes here using aodv.Set(name, value)
InternetStackHelper stack;
stack.SetRoutingHelper (aodv); // has effect on the next Install ()
stack.Install (nodes);
Ipv4AddressHelper address;
address.SetBase ("10.0.0.0", "255.0.0.0");
interfaces = address.Assign (devices);
if (printRoutes)
{
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("aodv.routes", std::ios::out);
aodv.PrintRoutingTableAllAt (Seconds (8), routingStream);
}
}
void
TracerouteExample::InstallApplications ()
{
V4TraceRouteHelper traceroute (Ipv4Address ("10.0.0.10")); //size - 1
traceroute.SetAttribute ("Verbose", BooleanValue (true));
ApplicationContainer p = traceroute.Install (nodes.Get (0));
// Used when we wish to dump the traceroute results into a file
//Ptr<OutputStreamWrapper> printstrm = Create<OutputStreamWrapper> ("mytrace", std::ios::out);
//traceroute.PrintTraceRouteAt(nodes.Get(0),printstrm);
p.Start (Seconds (0));
p.Stop (Seconds (totalTime) - Seconds (0.001));
}

View File

@@ -5,4 +5,7 @@ def build(bld):
return;
obj = bld.create_ns3_program('dhcp-example', ['internet', 'internet-apps', 'csma', 'point-to-point', 'applications'])
obj.source = 'dhcp-example.cc'
obj.source = 'dhcp-example.cc'
obj = bld.create_ns3_program('traceroute-example', ['aodv', 'core', 'network', 'internet', 'point-to-point', 'wifi','internet-apps'])
obj.source = 'traceroute-example.cc'

View File

@@ -0,0 +1,94 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*
*/
#include "v4traceroute-helper.h"
#include "ns3/v4traceroute.h"
#include "ns3/names.h"
namespace ns3 {
V4TraceRouteHelper::V4TraceRouteHelper (Ipv4Address remote)
{
m_factory.SetTypeId ("ns3::V4TraceRoute");
m_factory.Set ("Remote", Ipv4AddressValue (remote));
}
void
V4TraceRouteHelper::SetAttribute (std::string name, const AttributeValue &value)
{
m_factory.Set (name, value);
}
ApplicationContainer
V4TraceRouteHelper::Install (Ptr<Node> node) const
{
return ApplicationContainer (InstallPriv (node));
}
ApplicationContainer
V4TraceRouteHelper::Install (std::string nodeName) const
{
Ptr<Node> node = Names::Find<Node> (nodeName);
return ApplicationContainer (InstallPriv (node));
}
ApplicationContainer
V4TraceRouteHelper::Install (NodeContainer c) const
{
ApplicationContainer apps;
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
{
apps.Add (InstallPriv (*i));
}
return apps;
}
Ptr<Application>
V4TraceRouteHelper::InstallPriv (Ptr<Node> node) const
{
Ptr<V4TraceRoute> app = m_factory.Create<V4TraceRoute> ();
node->AddApplication (app);
return app;
}
void
V4TraceRouteHelper::PrintTraceRouteAt (Ptr<Node> node, Ptr<OutputStreamWrapper> stream)
{
Ptr<V4TraceRoute> trace;
for (uint32_t i = 0; i < node->GetNApplications (); ++i)
{
trace = node->GetApplication (i)->GetObject <V4TraceRoute> ();
if (trace != NULL)
{
*stream->GetStream () << "Tracing Route from Node " << node->GetId () << "\n";
trace->Print (stream);
return;
}
}
NS_ASSERT_MSG (false, "No V4TraceRoute application found in node " << node->GetId ());
}
} // namespace ns3

View File

@@ -0,0 +1,109 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*
*/
#ifndef V4TRACEROUTE_HELPER_H
#define V4TRACEROUTE_HELPER_H
#include "ns3/node-container.h"
#include "ns3/application-container.h"
#include "ns3/object-factory.h"
#include "ns3/output-stream-wrapper.h"
namespace ns3 {
/**
* \ingroup v4traceroute
* \brief Create a IPv4 traceroute application and associate it to a node
*
* This class creates one or multiple instances of ns3::V4TraceRoute and associates
* it/them to one/multiple node(s).
*/
class V4TraceRouteHelper
{
public:
/**
* Create a V4TraceRouteHelper which is used to make life easier for people wanting
* to use TraceRoute
*
* \param remote The address which should be traced
*/
V4TraceRouteHelper (Ipv4Address remote);
/**
* Install a TraceRoute application on each Node in the provided NodeContainer.
*
* \param nodes The NodeContainer containing all of the nodes to get a V4TraceRoute
* application.
*
* \returns A list of TraceRoute applications, one for each input node
*/
ApplicationContainer Install (NodeContainer nodes) const;
/**
* Install a TraceRoute application on the provided Node. The Node is specified
* directly by a Ptr<Node>
*
* \param node The node to install the V4TraceRouteApplication on.
*
* \returns An ApplicationContainer holding the TraceRoute application created.
*/
ApplicationContainer Install (Ptr<Node> node) const;
/**
* Install a TraceRoute application on the provided Node. The Node is specified
* by a string that must have previously been associated with a Node using the
* Object Name Service.
*
* \param nodeName The node to install the V4TraceRouteApplication on.
*
* \returns An ApplicationContainer holding the TraceRoute application created.
*/
ApplicationContainer Install (std::string nodeName) const;
/**
* \brief Configure traceRoute applications attribute
* \param name attribute's name
* \param value attribute's value
*/
void SetAttribute (std::string name, const AttributeValue &value);
/**
* \brief Print the resulting trace routes from given node.
* \param node The origin node where the traceroute is initiated.
* \param stream The outputstream used to print the resulting traced routes.
*/
static void PrintTraceRouteAt (Ptr<Node> node, Ptr<OutputStreamWrapper> stream);
private:
/**
* \brief Do the actual application installation in the node
* \param node the node
* \returns a Smart pointer to the installed application
*/
Ptr<Application> InstallPriv (Ptr<Node> node) const;
/// Object factory
ObjectFactory m_factory;
};
} // namespace ns3
#endif /* V4TRACEROUTE_HELPER_H */

View File

@@ -0,0 +1,469 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet
*
* Traceroute uses ICMPV4 echo messages to trace all the middle hops to a given destination.
* It also shows the delay time it takes for a round trip to complete for each
* set probe (default 3).
*
*/
#include "v4traceroute.h"
#include "ns3/icmpv4.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/assert.h"
#include "ns3/log.h"
#include "ns3/ipv4-address.h"
#include "ns3/socket.h"
#include "ns3/uinteger.h"
#include "ns3/boolean.h"
#include "ns3/inet-socket-address.h"
#include "ns3/packet.h"
#include "ns3/trace-source-accessor.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("V4TraceRoute");
NS_OBJECT_ENSURE_REGISTERED (V4TraceRoute);
TypeId
V4TraceRoute::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::V4TraceRoute")
.SetParent<Application> ()
.SetGroupName ("Internet-Apps")
.AddConstructor<V4TraceRoute> ()
.AddAttribute ("Remote",
"The address of the machine we want to trace.",
Ipv4AddressValue (),
MakeIpv4AddressAccessor (&V4TraceRoute::m_remote),
MakeIpv4AddressChecker ())
.AddAttribute ("Verbose",
"Produce usual output.",
BooleanValue (true),
MakeBooleanAccessor (&V4TraceRoute::m_verbose),
MakeBooleanChecker ())
.AddAttribute ("Interval", "Wait interval between sent packets.",
TimeValue (Seconds (0)),
MakeTimeAccessor (&V4TraceRoute::m_interval),
MakeTimeChecker ())
.AddAttribute ("Size", "The number of data bytes to be sent, real packet will be 8 (ICMP) + 20 (IP) bytes longer.",
UintegerValue (56),
MakeUintegerAccessor (&V4TraceRoute::m_size),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("MaxHop", "The maximum number of hops to trace.",
UintegerValue (30),
MakeUintegerAccessor (&V4TraceRoute::m_maxTtl),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("ProbeNum", "The number of packets send to each hop.",
UintegerValue (3),
MakeUintegerAccessor (&V4TraceRoute::m_maxProbes),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("Timeout", "The waiting time for a route response before a timeout.",
TimeValue (Seconds (5)),
MakeTimeAccessor (&V4TraceRoute::m_waitIcmpReplyTimeout),
MakeTimeChecker ())
;
return tid;
}
V4TraceRoute::V4TraceRoute ()
: m_interval (Seconds (0)),
m_size (56),
m_socket (0),
m_seq (0),
m_verbose (true),
m_probeCount (0),
m_maxProbes (3),
m_ttl (1),
m_maxTtl (30),
m_waitIcmpReplyTimeout (Seconds (5))
{
osRoute.clear ();
routeIpv4.clear ();
}
V4TraceRoute::~V4TraceRoute ()
{
}
void
V4TraceRoute::Print (Ptr<OutputStreamWrapper> stream)
{
printStream = stream;
}
void
V4TraceRoute::StartApplication (void)
{
NS_LOG_FUNCTION (this);
NS_LOG_LOGIC ("Application started");
m_started = Simulator::Now ();
if (m_verbose)
{
NS_LOG_UNCOND("Traceroute to " << m_remote << ", "
<< m_maxTtl << " hops Max, "
<< m_size << " bytes of data.");
}
if (printStream != NULL)
{
*printStream->GetStream () << "Traceroute to " << m_remote << ", "
<< m_maxTtl << " hops Max, "
<< m_size << " bytes of data.\n";
}
m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
m_socket->SetAttribute ("Protocol", UintegerValue (Icmpv4L4Protocol::PROT_NUMBER));
NS_ASSERT (m_socket != 0);
m_socket->SetRecvCallback (MakeCallback (&V4TraceRoute::Receive, this));
InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0);
int status;
status = m_socket->Bind (src);
NS_ASSERT (status != -1);
m_next = Simulator::ScheduleNow (&V4TraceRoute::StartWaitReplyTimer, this);
}
void
V4TraceRoute::StopApplication (void)
{
NS_LOG_FUNCTION (this);
if (m_next.IsRunning ())
{
m_next.Cancel ();
}
if (m_waitIcmpReplyTimer.IsRunning ())
{
m_waitIcmpReplyTimer.Cancel ();
}
if (m_socket)
{
m_socket->Close ();
}
if (m_verbose)
{
NS_LOG_UNCOND("\nTrace Complete");
}
if (printStream != NULL)
{
*printStream->GetStream () << "Trace Complete\n" << std::endl;
}
}
void
V4TraceRoute::DoDispose (void)
{
NS_LOG_FUNCTION (this);
if (m_next.IsRunning () || m_waitIcmpReplyTimer.IsRunning ())
{
StopApplication ();
}
m_socket = 0;
Application::DoDispose ();
}
uint32_t
V4TraceRoute::GetApplicationId (void) const
{
NS_LOG_FUNCTION (this);
Ptr<Node> node = GetNode ();
for (uint32_t i = 0; i < node->GetNApplications (); ++i)
{
if (node->GetApplication (i) == this)
{
return i;
}
}
NS_ASSERT_MSG (false, "forgot to add application to node");
return 0;
}
void
V4TraceRoute::Receive (Ptr<Socket> socket)
{
NS_LOG_FUNCTION (this << socket);
while (m_socket->GetRxAvailable () > 0)
{
Address from;
Ptr<Packet> p = m_socket->RecvFrom (0xffffffff, 0, from);
NS_LOG_DEBUG ("recv " << p->GetSize () << " bytes");
NS_ASSERT (InetSocketAddress::IsMatchingType (from));
InetSocketAddress realFrom = InetSocketAddress::ConvertFrom (from);
NS_ASSERT (realFrom.GetPort () == 1);
Ipv4Header ipv4;
p->RemoveHeader (ipv4);
NS_ASSERT (ipv4.GetProtocol () == Icmpv4L4Protocol::PROT_NUMBER);
Icmpv4Header icmp;
p->RemoveHeader (icmp);
if (icmp.GetType () == Icmpv4Header::ICMPV4_TIME_EXCEEDED)
{
Icmpv4TimeExceeded timeoutResp;
p->RemoveHeader (timeoutResp);
// GetData () gets 64 bits of data, but the received packet
// only contains 32 bits of data.
uint8_t data [8];
timeoutResp.GetData (data);
// Get the 7th and 8th Octect to obtain the Sequence number from
// the original packet.
uint16_t recvSeq;
recvSeq = (uint16_t) data[7] << 0;
recvSeq |= (uint16_t) data [6] << 8;
std::map<uint16_t, Time>::iterator i = m_sent.find (recvSeq);
if (i != m_sent.end ())
{
Time sendTime = i->second;
NS_ASSERT (Simulator::Now () >= sendTime);
Time delta = Simulator::Now () - sendTime;
routeIpv4.str ("");
routeIpv4.clear ();
routeIpv4 << realFrom.GetIpv4 ();
osRoute << delta.GetMilliSeconds () << " ms ";
if (m_probeCount == m_maxProbes)
{
if (m_verbose)
{
NS_LOG_UNCOND(m_ttl << " " << routeIpv4.str () << " " << osRoute.str ());
}
if (printStream != NULL)
{
*printStream->GetStream () << m_ttl << " "
<< routeIpv4.str () << " "
<< osRoute.str () << "\n";
}
osRoute.str ("");
osRoute.clear ();
routeIpv4.str ("");
routeIpv4.clear ();
}
m_waitIcmpReplyTimer.Cancel ();
if (m_ttl < m_maxTtl + 1)
{
m_next = Simulator::Schedule (m_interval, &V4TraceRoute::StartWaitReplyTimer, this);
}
}
}
else if (icmp.GetType () == Icmpv4Header::ICMPV4_ECHO_REPLY && m_remote == realFrom.GetIpv4 ())
{
// When UDP is used, TraceRoute should stop until ICMPV4_DEST_UNREACH
// (with code (3) PORT_UNREACH) is received, however, the current
// ns-3 implementation does not include the UDP version of traceroute.
// The traceroute ICMP version (the current version) stops until max_ttl is reached
// or until an ICMP ECHO REPLY is received m_maxProbes times.
Icmpv4Echo echo;
p->RemoveHeader (echo);
std::map<uint16_t, Time>::iterator i = m_sent.find (echo.GetSequenceNumber ());
if (i != m_sent.end () && echo.GetIdentifier () == 0)
{
uint32_t * buf = new uint32_t [m_size];
uint32_t dataSize = echo.GetDataSize ();
if (dataSize == m_size)
{
echo.GetData ((uint8_t *)buf);
Time sendTime = i->second;
NS_ASSERT (Simulator::Now () >= sendTime);
Time delta = Simulator::Now () - sendTime;
m_sent.erase (i);
if (m_verbose)
{
routeIpv4.str ("");
routeIpv4.clear ();
routeIpv4 << realFrom.GetIpv4 ();
osRoute << delta.GetMilliSeconds () << " ms ";
if (m_probeCount == m_maxProbes)
{
NS_LOG_UNCOND(m_ttl << " " << routeIpv4.str () << " " << osRoute.str ());
if (printStream != NULL)
{
*printStream->GetStream () << m_ttl << " "
<< routeIpv4.str () << " "
<< osRoute.str () << "\n";
}
osRoute.clear ();
routeIpv4.clear ();
}
}
}
delete[] buf;
}
m_waitIcmpReplyTimer.Cancel ();
if (m_probeCount == m_maxProbes)
{
StopApplication ();
}
else if (m_ttl < m_maxTtl + 1)
{
m_next = Simulator::Schedule (m_interval, &V4TraceRoute::StartWaitReplyTimer, this);
}
}
}
}
void
V4TraceRoute::Send ()
{
NS_LOG_INFO ("m_seq=" << m_seq);
Ptr<Packet> p = Create<Packet> ();
Icmpv4Echo echo;
echo.SetSequenceNumber (m_seq);
m_seq++;
echo.SetIdentifier (0);
//
// We must write quantities out in some form of network order. Since there
// isn't an htonl to work with we just follow the convention in pcap traces
// (where any difference would show up anyway) and borrow that code. Don't
// be too surprised when you see that this is a little endian convention.
//
uint8_t* data = new uint8_t[m_size];
for (uint32_t i = 0; i < m_size; ++i)
{
data[i] = 0;
}
NS_ASSERT (m_size >= 16);
Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) data, m_size);
echo.SetData (dataPacket);
p->AddHeader (echo);
Icmpv4Header header;
header.SetType (Icmpv4Header::ICMPV4_ECHO);
header.SetCode (0);
if (Node::ChecksumEnabled ())
{
header.EnableChecksum ();
}
p->AddHeader (header);
if (m_probeCount < m_maxProbes)
{
m_probeCount++;
}
else
{
m_probeCount = 1;
m_ttl++;
}
m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now ()));
m_socket->SetIpTtl (m_ttl);
InetSocketAddress dst = InetSocketAddress (m_remote, 0);
m_socket->SendTo (p, 0, dst);
delete[] data;
}
void
V4TraceRoute::StartWaitReplyTimer (void)
{
NS_LOG_FUNCTION (this);
if (!m_waitIcmpReplyTimer.IsRunning ())
{
NS_LOG_LOGIC ("Starting WaitIcmpReplyTimer at " << Simulator::Now () << " for " <<
m_waitIcmpReplyTimeout);
m_waitIcmpReplyTimer = Simulator::Schedule (m_waitIcmpReplyTimeout,
&V4TraceRoute::HandleWaitReplyTimeout, this);
Send ();
}
}
void
V4TraceRoute::HandleWaitReplyTimeout (void)
{
if (m_ttl < m_maxTtl + 1)
{
m_next = Simulator::Schedule (m_interval, &V4TraceRoute::StartWaitReplyTimer, this);
}
osRoute << "* ";
if (m_probeCount == m_maxProbes)
{
if (m_verbose)
{
NS_LOG_UNCOND(m_ttl << " " << routeIpv4.str () << " " << osRoute.str ());
}
if (printStream != NULL)
{
*printStream->GetStream () << m_ttl
<< " " << routeIpv4.str () << " "
<< osRoute.str () << "\n";
}
osRoute.str ("");
osRoute.clear ();
routeIpv4.str ("");
routeIpv4.clear ();
}
}
} // ns3 namespace

View File

@@ -0,0 +1,142 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#ifndef V4TRACEROUTE_H
#define V4TRACEROUTE_H
#include "ns3/application.h"
#include "ns3/traced-callback.h"
#include "ns3/nstime.h"
#include "ns3/average.h"
#include "ns3/simulator.h"
#include "ns3/output-stream-wrapper.h"
#include <map>
namespace ns3 {
class Socket;
/**
* \ingroup internet-apps
* \defgroup v4traceroute V4Traceroute
*/
/**
* \ingroup v4traceroute
* \brief Traceroute application sends one ICMP ECHO request with TTL=1,
* and after receiving an ICMP TIME EXCEED reply, it increases the
* TTL and repeat the process to reveal all the intermediate hops to
* the destination.
*
*/
class V4TraceRoute : public Application
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
V4TraceRoute ();
virtual ~V4TraceRoute ();
/**
* \brief Prints the application traced routes into a given OutputStream.
*/
void Print (Ptr<OutputStreamWrapper> stream);
private:
virtual void StartApplication (void);
virtual void StopApplication (void);
virtual void DoDispose (void);
/**
* \brief Return the application ID in the node.
* \returns the application id
*/
uint32_t GetApplicationId (void) const;
/**
* \brief Receive an ICMP Echo
* \param socket the receiving socket
*
* This function is called by lower layers through a callback.
*/
void Receive (Ptr<Socket> socket);
/** \brief Send one (ICMP ECHO) to the destination.*/
void Send ();
/** \brief Starts a timer after sending an ICMP ECHO.*/
void StartWaitReplyTimer ();
/** \brief Triggers an action if an ICMP TIME EXCEED have not being received
* in the time defined by StartWaitReplyTimer.
*/
void HandleWaitReplyTimeout ();
/// Remote address
Ipv4Address m_remote;
/// Wait interval seconds between sending each packet
Time m_interval;
/**
* Specifies the number of data bytes to be sent.
* The default is 56, which translates into 64 ICMP data bytes when
* combined with the 8 bytes of ICMP header data.
*/
uint32_t m_size;
/// The socket we send packets from
Ptr<Socket> m_socket;
/// ICMP ECHO sequence number
uint16_t m_seq;
/// produce traceroute style output if true
bool m_verbose;
/// Start time to report total ping time
Time m_started;
/// Next packet will be sent
EventId m_next;
/// The Current probe value
uint32_t m_probeCount;
/// The maximum number of probe packets per hop
u_int16_t m_maxProbes;
/// The current TTL value
uint16_t m_ttl;
/// The maximium Ttl (Max number of hops to trace)
uint32_t m_maxTtl;
/// The wait time until the response is considered lost.
Time m_waitIcmpReplyTimeout;
/// The timer used to wait for the probes ICMP replies
EventId m_waitIcmpReplyTimer;
/// All sent but not answered packets. Map icmp seqno -> when sent
std::map<uint16_t, Time> m_sent;
/// Stream of characters used for printing the traceroute results
std::ostringstream os;
/// Stream of characters used for printing a single route
std::ostringstream osRoute;
/// The Ipv4 address of the latest hop found
std::ostringstream routeIpv4;
/// Stream of the traceroute used for the output file
Ptr<OutputStreamWrapper> printStream;
};
} //ns3 namespace
#endif /*V4TRACEROUTE_H*/

View File

@@ -14,12 +14,14 @@ def build(bld):
'model/radvd-prefix.cc',
'model/radvd.cc',
'model/v4ping.cc',
'model/v4traceroute.cc',
'model/dhcp-header.cc',
'model/dhcp-server.cc',
'model/dhcp-client.cc',
'helper/ping6-helper.cc',
'helper/radvd-helper.cc',
'helper/v4ping-helper.cc',
'helper/v4traceroute-helper.cc',
'helper/dhcp-helper.cc',
]
@@ -36,11 +38,13 @@ def build(bld):
'model/radvd-interface.h',
'model/radvd-prefix.h',
'model/v4ping.h',
'model/v4traceroute.h',
'model/dhcp-header.h',
'model/dhcp-server.h',
'model/dhcp-client.h',
'helper/ping6-helper.h',
'helper/v4ping-helper.h',
'helper/v4traceroute-helper.h',
'helper/radvd-helper.h',
'helper/dhcp-helper.h',
]
@@ -49,4 +53,3 @@ def build(bld):
bld.recurse('examples')
bld.ns3_python_bindings()