diff --git a/AUTHORS b/AUTHORS index 7ade1a3d3..f016de8f2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,6 +6,7 @@ Mehdi Benamor (mehdi.benamor@telecom-bretagne.eu) Raj Bhattacharjea (raj.b@gatech.edu) Timo Bingmann (timo.bingmann@student.kit.edu) Pavel Boyko (boyko@iitp.ru) +Elena Buchatskaia (borovkovaes@iitp.ru) Gustavo Carneiro (gjc@inescporto.pt, gjcarneiro@gmail.com) Angelos Chatzipapas (chatzipa@ceid.upatras.gr) Luis Cortes (cortes@gatech.edu) diff --git a/CHANGES.html b/CHANGES.html index 1beecb862..eb469ebb7 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -59,6 +59,10 @@ event with a context different from the execution context of the caller. This AP by the ns-3 logging system to report the execution context of each log line.
  • Object::DoStart: Users who need to complete their object setup at the start of a simulation can override this virtual method, perform their adhoc setup, and then, must chain up to their parent. + +
  • Aod hoc On-Demand Distance Vector (AODV) routing model, +RFC 3561
  • +

    Changes to existing API:

    @@ -122,6 +126,9 @@ sched.SetTypeId ("ns3::ListScheduler"); Simulator::SetScheduler (sched); +
  • Extensions to IPv4 Ping application: verbose output and the ability to configure different ping +sizes and time intervals (via new attributes)
  • +

    Changed behavior:

    diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 94ee6d58b..de91a904e 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -31,10 +31,12 @@ http://www.nsnam.org/wiki/index.php/Installation New user-visible features ------------------------- - * The ns-3 logging macros (NS_LOG_*) now report automatically the node id - of the event which called the macro. + a) The ns-3 logging macros (NS_LOG_*) now report automatically the node id + of the event which called the macro. -API changes from ns-3.5 + b) Ad hoc On-Demand Distance Vector (AODV) routing model according to RFC 3561. + +API changes from ns-3.6 ----------------------- API changes for this release are documented in the file CHANGES.html. diff --git a/examples/routing/aodv.cc b/examples/routing/aodv.cc new file mode 100644 index 000000000..de1de85cd --- /dev/null +++ b/examples/routing/aodv.cc @@ -0,0 +1,214 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * 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 + * + * This is an example script for AODV manet routing protocol. + * + * Authors: Pavel Boyko + */ + +#include "ns3/aodv-module.h" +#include "ns3/core-module.h" +#include "ns3/common-module.h" +#include "ns3/node-module.h" +#include "ns3/helper-module.h" +#include "ns3/mobility-module.h" +#include "ns3/contrib-module.h" +#include "ns3/wifi-module.h" +#include "ns3/v4ping-helper.h" +#include +#include + +using namespace ns3; + +/** + * \brief Test script. + * + * This script creates 1-dimensional grid topology and then ping last node from the first one: + * + * [10.0.0.1] <-- step --> [10.0.0.2] <-- step --> [10.0.0.3] <-- step --> [10.0.04] + * + * ping 10.0.0.4 + */ +class AodvExample +{ +public: + AodvExample (); + /// Configure script parameters, \return true on successful configuration + bool Configure (int argc, char **argv); + /// Run simulation + void Run (); + /// Report results + void Report (std::ostream & os); + +private: + ///\name 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; + //\} + + ///\name network + //\{ + NodeContainer nodes; + NetDeviceContainer devices; + Ipv4InterfaceContainer interfaces; + //\} + +private: + void CreateNodes (); + void CreateDevices (); + void InstallInternetStack (); + void InstallApplications (); +}; + +int main (int argc, char **argv) +{ + AodvExample test; + if (! test.Configure(argc, argv)) + NS_FATAL_ERROR ("Configuration failed. Aborted."); + + test.Run (); + test.Report (std::cout); + return 0; +} + +//----------------------------------------------------------------------------- +AodvExample::AodvExample () : + size (10), + step (120), + totalTime (10), + pcap (true) +{ +} + +bool +AodvExample::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 ("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 +AodvExample::Run () +{ +// Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue (1)); // enable rts cts all the time. + CreateNodes (); + CreateDevices (); + InstallInternetStack (); + InstallApplications (); + + std::cout << "Starting simulation for " << totalTime << " s ...\n"; + + Simulator::Stop (Seconds (totalTime)); + Simulator::Run (); + Simulator::Destroy (); +} + +void +AodvExample::Report (std::ostream &) +{ +} + +void +AodvExample::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 +AodvExample::CreateDevices () +{ + NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default (); + wifiMac.SetType ("ns3::AdhocWifiMac"); + YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); + YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); + wifiPhy.SetChannel (wifiChannel.Create ()); + WifiHelper wifi = WifiHelper::Default (); + wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("wifia-6mbs"), "RtsCtsThreshold", UintegerValue (0)); + devices = wifi.Install (wifiPhy, wifiMac, nodes); + + if (pcap) + { + wifiPhy.EnablePcapAll (std::string ("aodv")); + } +} + +void +AodvExample::InstallInternetStack () +{ + AodvHelper aodv; + // you can configure AODV attributes here using aodv.Set(name, value) + InternetStackHelper stack; + stack.SetRoutingHelper (aodv); + stack.Install (nodes); + Ipv4AddressHelper address; + address.SetBase ("10.0.0.0", "255.0.0.0"); + interfaces = address.Assign (devices); +} + +void +AodvExample::InstallApplications () +{ + V4PingHelper ping (interfaces.GetAddress (size - 1)); + ping.SetAttribute ("Verbose", BooleanValue (true)); + + ApplicationContainer p = ping.Install (nodes.Get (0)); + p.Start (Seconds (0)); + p.Stop (Seconds (totalTime)); + + // move node away + Ptr node = nodes.Get (size/2); + Ptr mob = node->GetObject (); + Simulator::Schedule (Seconds (totalTime/3), &MobilityModel::SetPosition, mob, Vector (1e5, 1e5, 1e5)); +} + diff --git a/examples/routing/wscript b/examples/routing/wscript index bff2f8b0e..c3404d2c7 100644 --- a/examples/routing/wscript +++ b/examples/routing/wscript @@ -44,3 +44,7 @@ def build(bld): obj = bld.create_ns3_program('simple-routing-ping6', ['csma', 'internet-stack']) obj.source = 'simple-routing-ping6.cc' + + obj = bld.create_ns3_program('aodv', + ['wifi', 'internet-stack', 'aodv']) + obj.source = 'aodv.cc' diff --git a/src/applications/v4ping/v4ping.cc b/src/applications/v4ping/v4ping.cc index 8523439f5..b23f45484 100644 --- a/src/applications/v4ping/v4ping.cc +++ b/src/applications/v4ping/v4ping.cc @@ -20,10 +20,10 @@ #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" -#include "ns3/simulator.h" namespace ns3 { @@ -41,6 +41,19 @@ V4Ping::GetTypeId (void) Ipv4AddressValue (), MakeIpv4AddressAccessor (&V4Ping::m_remote), MakeIpv4AddressChecker ()) + .AddAttribute ("Verbose", + "Produce usual output.", + BooleanValue (false), + MakeBooleanAccessor (&V4Ping::m_verbose), + MakeBooleanChecker ()) + .AddAttribute ("Interval", "Wait interval seconds between sending each packet.", + TimeValue (Seconds (1)), + MakeTimeAccessor (&V4Ping::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 (&V4Ping::m_size), + MakeUintegerChecker (16)) .AddTraceSource ("Rtt", "The rtt calculated by the ping.", MakeTraceSourceAccessor (&V4Ping::m_traceRtt)); @@ -49,9 +62,14 @@ V4Ping::GetTypeId (void) } V4Ping::V4Ping () - : m_socket (0), - m_seq (0) -{} + : m_interval (Seconds (1)), + m_size (56), + m_socket (0), + m_seq (0), + m_verbose (false), + m_recv (0) +{ +} V4Ping::~V4Ping () {} @@ -92,6 +110,7 @@ V4Ping::Receive (Ptr socket) NS_ASSERT (realFrom.GetPort () == 1); // protocol should be icmp. Ipv4Header ipv4; p->RemoveHeader (ipv4); + uint32_t recvSize = p->GetSize (); NS_ASSERT (ipv4.GetProtocol () == 1); // protocol should be icmp. Icmpv4Header icmp; p->RemoveHeader (icmp); @@ -99,10 +118,11 @@ V4Ping::Receive (Ptr socket) { Icmpv4Echo echo; p->RemoveHeader (echo); - if (echo.GetSequenceNumber () == (m_seq - 1) && - echo.GetIdentifier () == 0) + std::map::iterator i = m_sent.find(echo.GetSequenceNumber()); + + if (i != m_sent.end () && echo.GetIdentifier () == 0) { - uint32_t buf[4]; + uint32_t buf[m_size / 4]; uint32_t dataSize = echo.GetDataSize (); if (dataSize == sizeof(buf)) { @@ -111,13 +131,22 @@ V4Ping::Receive (Ptr socket) if (buf[0] == GetNode ()->GetId () && buf[1] == GetApplicationId ()) { - int64_t ts = buf[3]; - ts <<= 32; - ts |= buf[2]; - Time sendTime = TimeStep (ts); + Time sendTime = i->second; NS_ASSERT (Simulator::Now () > sendTime); Time delta = Simulator::Now () - sendTime; + + m_sent.erase (i); + m_avgRtt.Update (delta.GetMilliSeconds()); + m_recv++; m_traceRtt (delta); + + if (m_verbose) + { + std::cout << recvSize << " bytes from " << realFrom.GetIpv4() << ":" + << " icmp_seq=" << echo.GetSequenceNumber () + << " ttl=" << (unsigned)ipv4.GetTtl () + << " time=" << delta.GetMilliSeconds() << " ms\n"; + } } } } @@ -135,20 +164,8 @@ V4Ping::Write32 (uint8_t *buffer, uint32_t data) } void -V4Ping::StartApplication (void) +V4Ping::Send () { - NS_LOG_FUNCTION (this); - m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory")); - NS_ASSERT (m_socket != 0); - m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp - m_socket->SetRecvCallback (MakeCallback (&V4Ping::Receive, this)); - InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0); - int status; - status = m_socket->Bind (src); - NS_ASSERT (status != -1); - InetSocketAddress dst = InetSocketAddress (m_remote, 0); - status = m_socket->Connect (dst); - NS_ASSERT (status != -1); Ptr p = Create (); Icmpv4Echo echo; echo.SetSequenceNumber (m_seq); @@ -161,22 +178,17 @@ V4Ping::StartApplication (void) // (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[4 * sizeof(uint32_t)]; + uint8_t data[m_size]; + for (uint32_t i = 0; i < m_size; ++i) data[i] = 0; + NS_ASSERT (m_size >= 16); + uint32_t tmp = GetNode ()->GetId (); Write32 (&data[0 * sizeof(uint32_t)], tmp); tmp = GetApplicationId (); Write32 (&data[1 * sizeof(uint32_t)], tmp); - int64_t now = Simulator::Now ().GetTimeStep (); - tmp = now & 0xffffffff; - Write32 (&data[2 * sizeof(uint32_t)], tmp); - - now >>= 32; - tmp = now & 0xffffffff; - Write32 (&data[3 * sizeof(uint32_t)], tmp); - - Ptr dataPacket = Create ((uint8_t *) &data, 16); + Ptr dataPacket = Create ((uint8_t *) &data, m_size); echo.SetData (dataPacket); p->AddHeader (echo); Icmpv4Header header; @@ -184,13 +196,57 @@ V4Ping::StartApplication (void) header.SetCode (0); p->AddHeader (header); m_socket->Send (p, 0); + m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now())); + m_next = Simulator::Schedule (m_interval, & V4Ping::Send, this); +} + +void +V4Ping::StartApplication (void) +{ + NS_LOG_FUNCTION (this); + m_started = Simulator::Now (); + if (m_verbose) + { + std::cout << "PING " << m_remote << " 56(84) bytes of data.\n"; + } + + m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory")); + NS_ASSERT (m_socket != 0); + m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp + m_socket->SetRecvCallback (MakeCallback (&V4Ping::Receive, this)); + InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0); + int status; + status = m_socket->Bind (src); + NS_ASSERT (status != -1); + InetSocketAddress dst = InetSocketAddress (m_remote, 0); + status = m_socket->Connect (dst); + NS_ASSERT (status != -1); + + Send (); } void V4Ping::StopApplication (void) { NS_LOG_FUNCTION (this); + m_next.Cancel(); m_socket->Close (); + + if (m_verbose) + { + std::ostringstream os; + os.precision (4); + os << "--- " << m_remote << " ping statistics ---\n" + << m_seq << " packets transmitted, " << m_recv << " received, " + << ((m_seq - m_recv) * 100 / m_seq) << "% packet loss, " + << "time " << (Simulator::Now () - m_started).GetMilliSeconds () << "ms\n"; + + if (m_avgRtt.Count () > 0) + os << "rtt min/avg/max/mdev = " << m_avgRtt.Min() << "/" << m_avgRtt.Avg() << "/" + << m_avgRtt.Max() << "/" << m_avgRtt.Err() + << " ms\n"; + std::cout << os.str(); + } } diff --git a/src/applications/v4ping/v4ping.h b/src/applications/v4ping/v4ping.h index ec7ed3820..3eb3e64b3 100644 --- a/src/applications/v4ping/v4ping.h +++ b/src/applications/v4ping/v4ping.h @@ -1,9 +1,27 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * 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 + */ #ifndef V4PING_H #define V4PING_H #include "ns3/application.h" #include "ns3/traced-callback.h" #include "ns3/nstime.h" +#include "ns3/average.h" +#include "ns3/simulator.h" +#include namespace ns3 { @@ -35,11 +53,32 @@ private: virtual void DoDispose (void); uint32_t GetApplicationId (void) const; void Receive (Ptr socket); + void Send (); + /// 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; Ptr m_socket; uint16_t m_seq; TracedCallback