This commit is contained in:
Sebastien Vincent
2009-11-24 20:38:21 +01:00
66 changed files with 6335 additions and 511 deletions

View File

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

View File

@@ -56,9 +56,15 @@ us a note on ns-developers mailing list. </p>
'context' (a 32bit integer which, by convention identifies a node by its id). Simulator::GetContext
returns the context of the currently-executing event while Simulator::ScheduleWithContext creates an
event with a context different from the execution context of the caller. This API is used
by the ns-3 logging system to report the execution context of each log line.
by the ns-3 logging system to report the execution context of each log line.</li>
<li><b>Object::DoStart</b>: 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.
can override this virtual method, perform their adhoc setup, and then, must chain up to their parent.</li>
<li><b>Aod hoc On-Demand Distance Vector (AODV)</b> routing model,
<a href=http://www.ietf.org/rfc/rfc3561.txt>RFC 3561</a> </li>
<li><b>IPv6 extension support</b></li>
</ul>
<h2>Changes to existing API:</h2>
@@ -122,6 +128,9 @@ sched.SetTypeId ("ns3::ListScheduler");
Simulator::SetScheduler (sched);
</pre>
<li> Extensions to IPv4 <b>Ping</b> application: verbose output and the ability to configure different ping
sizes and time intervals (via new attributes)</li>
</ul>
<h2>Changed behavior:</h2>

View File

@@ -31,10 +31,14 @@ 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.
c) IPv6 extensions support and two new examples for fragmentation and loose routing.
API changes from ns-3.6
-----------------------
API changes for this release are documented in the file CHANGES.html.

View File

@@ -45,26 +45,25 @@ NS_LOG_COMPONENT_DEFINE ("FragmentationIpv6Example");
*/
class StackHelper
{
public:
/**
* \brief Add an address to a IPv6 node.
* \param n node
* \param interface interface index
* \param address IPv6 address to add
*/
inline void AddAddress (Ptr<Node>& n, uint32_t interface, Ipv6Address address)
{
public:
/**
* \brief Add an address to a IPv6 node.
* \param n node
* \param interface interface index
* \param address IPv6 address to add
*/
inline void AddAddress (Ptr<Node>& n, uint32_t interface, Ipv6Address address)
{
Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
ipv6->AddAddress (interface, address);
}
/**
* \brief Print the routing table.
* \param n the node
*/
inline void PrintRoutingTable (Ptr<Node>& n)
{
/**
* \brief Print the routing table.
* \param n the node
*/
inline void PrintRoutingTable (Ptr<Node>& n)
{
Ptr<Ipv6StaticRouting> routing = 0;
Ipv6StaticRoutingHelper routingHelper;
Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
@@ -78,15 +77,15 @@ class StackHelper
nbRoutes = routing->GetNRoutes ();
for (uint32_t i = 0 ; i < nbRoutes ; i++)
{
route = routing->GetRoute (i);
std::cout << route.GetDest () << "\t"
<< route.GetGateway () << "\t"
<< route.GetInterface () << "\t"
<< route.GetPrefixToUse () << "\t"
<< std::endl;
}
}
{
route = routing->GetRoute (i);
std::cout << route.GetDest () << "\t"
<< route.GetGateway () << "\t"
<< route.GetInterface () << "\t"
<< route.GetPrefixToUse () << "\t"
<< std::endl;
}
}
};
int main (int argc, char** argv)

214
examples/routing/aodv.cc Normal file
View File

@@ -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 <boyko@iitp.ru>
*/
#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 <iostream>
#include <cmath>
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> node = nodes.Get (size/2);
Ptr<MobilityModel> mob = node->GetObject<MobilityModel> ();
Simulator::Schedule (Seconds (totalTime/3), &MobilityModel::SetPosition, mob, Vector (1e5, 1e5, 1e5));
}

View File

@@ -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'

View File

@@ -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<uint32_t> (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> 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> socket)
{
Icmpv4Echo echo;
p->RemoveHeader (echo);
if (echo.GetSequenceNumber () == (m_seq - 1) &&
echo.GetIdentifier () == 0)
std::map<uint16_t, Time>::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> 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<Packet> p = Create<Packet> ();
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<Packet> dataPacket = Create<Packet> ((uint8_t *) &data, 16);
Ptr<Packet> dataPacket = Create<Packet> ((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();
}
}

View File

@@ -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 <map>
namespace ns3 {
@@ -35,11 +53,32 @@ private:
virtual void DoDispose (void);
uint32_t GetApplicationId (void) const;
void Receive (Ptr<Socket> 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<Socket> m_socket;
uint16_t m_seq;
TracedCallback<Time> m_traceRtt;
/// produce ping-style output if true
bool m_verbose;
/// received packets counter
uint32_t m_recv;
/// Start time to report total ping time
Time m_started;
/// Average rtt is ms
Average<double> m_avgRtt;
/// Next packet will be sent
EventId m_next;
/// All sent but not answered packets. Map icmp seqno -> when sent
std::map<uint16_t, Time> m_sent;
};
} // namespace ns3

82
src/contrib/average.h Normal file
View File

@@ -0,0 +1,82 @@
/* -*- 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
*
* Authors: Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AVERAGE_H
#define AVERAGE_H
#include <cmath>
#include <iostream>
#include <limits>
/// Simple average, min, max and std. deviation calculator
template <typename T = double>
class Average
{
public:
Average () :
size (0), min (std::numeric_limits<T>::max ()), max (0), avg (0), avg2 (0)
{
}
/// Add new value
void Update (T const & x)
{
min = std::min (x, min);
max = std::max (x, max);
avg = (size * avg + x) / (size + 1);
avg2 = (size * avg2 + x * x) / (size + 1);
size++;
}
/// Reset statistics
void Reset ()
{
size = 0;
min = std::numeric_limits<T>::max ();
max = 0;
avg = 0;
avg2 = 0;
}
///\name Access results
//\{
uint32_t Count () const { return size; }
T Min () const { return min; }
T Max () const { return max; }
double Avg () const { return avg; }
double Err () const { return sqrt ((avg2 - avg*avg)/(size - 1)); }
//\}
private:
uint32_t size;
T min, max;
double avg, avg2;
};
/// Print avg (err) [min, max]
template <typename T>
std::ostream & operator<< (std::ostream & os, Average<T> const & x)
{
if (x.Count () != 0)
os << x.Avg () << " (" << x.Err () << ") [" << x.Min () << ", " << x.Max () << "]";
else
os << "NA"; // not avaliable
return os;
}
#endif /* AVERAGE_H */

View File

@@ -43,6 +43,7 @@ def build(bld):
'file-config.h',
'config-store.h',
'flow-id-tag.h',
'average.h',
]
if bld.env['ENABLE_GTK_CONFIG_STORE']:

View File

@@ -56,7 +56,20 @@ PppHeader::GetInstanceTypeId (void) const
void
PppHeader::Print (std::ostream &os) const
{
os << "Point-to-Point Protocol: " << m_protocol;
std::string proto;
switch(m_protocol)
{
case 0x0021: /* IPv4 */
proto = "IP (0x0021)";
break;
case 0x0057: /* IPv6 */
proto = "IPv6 (0x0057)";
break;
default:
NS_ASSERT_MSG(false, "PPP Protocol number not defined!");
}
os << "Point-to-Point Protocol: " << proto;
}
uint32_t

View File

@@ -28,6 +28,7 @@
#include "ns3/pointer.h"
#include "ns3/packet.h"
#include "ns3/log.h"
#include "ns3/trace-source-accessor.h"
NS_LOG_COMPONENT_DEFINE ("AdhocWifiMac");
@@ -48,6 +49,16 @@ AdhocWifiMac::GetTypeId (void)
PointerValue (),
MakePointerAccessor (&AdhocWifiMac::GetDcaTxop),
MakePointerChecker<DcaTxop> ())
.AddTraceSource ( "TxOkHeader",
"The header of successfully transmitted packet",
MakeTraceSourceAccessor (
&AdhocWifiMac::m_txOkCallback)
)
.AddTraceSource ( "TxErrHeader",
"The header of unsuccessfully transmitted packet",
MakeTraceSourceAccessor (
&AdhocWifiMac::m_txErrCallback)
)
;
return tid;
}
@@ -67,6 +78,7 @@ AdhocWifiMac::AdhocWifiMac ()
m_dca = CreateObject<DcaTxop> ();
m_dca->SetLow (m_low);
m_dca->SetManager (m_dcfManager);
m_dca->SetTxFailedCallback (MakeCallback (&AdhocWifiMac::TxFailed, this));
}
AdhocWifiMac::~AdhocWifiMac ()
{}
@@ -276,6 +288,14 @@ AdhocWifiMac::FinishConfigureStandard (enum WifiPhyStandard standard)
break;
}
}
void
AdhocWifiMac::TxOk (const WifiMacHeader &hdr)
{
m_txOkCallback (hdr);
}
void
AdhocWifiMac::TxFailed (const WifiMacHeader &hdr)
{
m_txErrCallback (hdr);
}
} // namespace ns3

View File

@@ -87,8 +87,9 @@ private:
AdhocWifiMac (const AdhocWifiMac & ctor_arg);
AdhocWifiMac &operator = (const AdhocWifiMac &o);
Ptr<DcaTxop> GetDcaTxop(void) const;
void TxOk (WifiMacHeader const &hdr);
void TxFailed (WifiMacHeader const &hdr);
virtual void FinishConfigureStandard (enum WifiPhyStandard standard);
Ptr<DcaTxop> m_dca;
Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> m_upCallback;
Ptr<WifiRemoteStationManager> m_stationManager;
@@ -97,6 +98,8 @@ private:
MacRxMiddle *m_rxMiddle;
Ptr<MacLow> m_low;
Ssid m_ssid;
TracedCallback<WifiMacHeader const &> m_txOkCallback;
TracedCallback<WifiMacHeader const &> m_txErrCallback;
};
} // namespace ns3

View File

@@ -91,6 +91,15 @@ WifiNetDevice::DoDispose (void)
NetDevice::DoDispose ();
}
void
WifiNetDevice::DoStart (void)
{
m_phy->Start ();
m_mac->Start ();
m_stationManager->Start ();
NetDevice::DoStart ();
}
void
WifiNetDevice::CompleteConfig (void)
{

View File

@@ -104,6 +104,7 @@ public:
private:
virtual void DoDispose (void);
virtual void DoStart (void);
void ForwardUp (Ptr<Packet> packet, Mac48Address from, Mac48Address to);
void LinkUp (void);
void LinkDown (void);

55
src/helper/aodv-helper.cc Normal file
View File

@@ -0,0 +1,55 @@
/* -*- 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
*
* Authors: Pavel Boyko <boyko@iitp.ru>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "aodv-helper.h"
#include "ns3/aodv-routing-protocol.h"
#include "ns3/node-list.h"
#include "ns3/names.h"
#include "ns3/ipv4-list-routing.h"
namespace ns3
{
AodvHelper::AodvHelper() :
Ipv4RoutingHelper ()
{
m_agentFactory.SetTypeId ("ns3::aodv::RoutingProtocol");
}
AodvHelper*
AodvHelper::Copy (void) const
{
return new AodvHelper (*this);
}
Ptr<Ipv4RoutingProtocol>
AodvHelper::Create (Ptr<Node> node) const
{
Ptr<aodv::RoutingProtocol> agent = m_agentFactory.Create<aodv::RoutingProtocol> ();
node->AggregateObject (agent);
return agent;
}
void
AodvHelper::Set (std::string name, const AttributeValue &value)
{
m_agentFactory.Set (name, value);
}
}

70
src/helper/aodv-helper.h Normal file
View File

@@ -0,0 +1,70 @@
/* -*- 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
*
* Authors: Pavel Boyko <boyko@iitp.ru>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef AODVHELPER_H_
#define AODVHELPER_H_
#include "ns3/object-factory.h"
#include "ns3/node.h"
#include "node-container.h"
#include "ipv4-routing-helper.h"
namespace ns3
{
/**
* \ingroup aodv
* \brief Helper class that adds AODV routing to nodes.
*/
class AodvHelper : public Ipv4RoutingHelper
{
public:
AodvHelper();
/**
* \internal
* \returns pointer to clone of this OlsrHelper
*
* This method is mainly for internal use by the other helpers;
* clients are expected to free the dynamic memory allocated by this method
*/
AodvHelper* Copy (void) const;
/**
* \param node the node on which the routing protocol will run
* \returns a newly-created routing protocol
*
* This method will be called by ns3::InternetStackHelper::Install
*
* TODO: support installing AODV on the subset of all available IP interfaces
*/
virtual Ptr<Ipv4RoutingProtocol> Create (Ptr<Node> node) const;
/**
* \param name the name of the attribute to set
* \param value the value of the attribute to set.
*
* This method controls the attributes of ns3::aodv::RoutingProtocol
*/
void Set (std::string name, const AttributeValue &value);
private:
ObjectFactory m_agentFactory;
};
}
#endif /* AODVHELPER_H_ */

View File

@@ -30,6 +30,12 @@ V4PingHelper::V4PingHelper (Ipv4Address remote)
m_factory.Set ("Remote", Ipv4AddressValue (remote));
}
void
V4PingHelper::SetAttribute (std::string name, const AttributeValue &value)
{
m_factory.Set (name, value);
}
ApplicationContainer
V4PingHelper::Install (Ptr<Node> node) const
{

View File

@@ -55,6 +55,12 @@ public:
*/
ApplicationContainer Install (std::string nodeName) const;
/**
* \brief Configure ping applications attribute
* \param name attribute's name
* \param value attribute's value
*/
void SetAttribute (std::string name, const AttributeValue &value);
private:
/**
* \internal

View File

@@ -1,7 +1,7 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'nix-vector-routing', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
helper.source = [
'node-container.cc',
'net-device-container.cc',
@@ -29,6 +29,7 @@ def build(bld):
'ipv4-global-routing-helper.cc',
'ipv4-list-routing-helper.cc',
'ipv4-routing-helper.cc',
'aodv-helper.cc',
'mesh-helper.cc',
'dot11s-installer.cc',
'flame-installer.cc',
@@ -68,9 +69,10 @@ def build(bld):
'nqos-wifi-mac-helper.h',
'qos-wifi-mac-helper.h',
'ipv4-nix-vector-helper.h',
'ipv4-global-routing-helper.h',
'ipv4-global-routing-helper.h',
'ipv4-list-routing-helper.h',
'ipv4-routing-helper.h',
'aodv-helper.h',
'mesh-helper.h',
'mesh-stack-installer.h',
'dot11s-installer.h',

View File

@@ -86,6 +86,7 @@ Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t typ
NS_ASSERT (ipv4 != 0 && ipv4->GetRoutingProtocol () != 0);
Ipv4Header header;
header.SetDestination (dest);
header.SetProtocol (PROT_NUMBER);
Socket::SocketErrno errno_;
Ptr<Ipv4Route> route;
uint32_t oif = 0; //specify non-zero if bound to a source address

View File

@@ -42,7 +42,8 @@ Ipv4Interface::GetTypeId (void)
.AddAttribute ("ArpCache",
"The arp cache for this ipv4 interface",
PointerValue (0),
MakePointerAccessor (&Ipv4Interface::m_cache),
MakePointerAccessor (&Ipv4Interface::SetArpCache,
&Ipv4Interface::GetArpCache),
MakePointerChecker<ArpCache> ())
;
;
@@ -128,6 +129,18 @@ Ipv4Interface::GetMetric (void) const
return m_metric;
}
void
Ipv4Interface::SetArpCache (Ptr<ArpCache> a)
{
m_cache = a;
}
Ptr<ArpCache>
Ipv4Interface::GetArpCache () const
{
return m_cache;
}
/**
* These are IP interface states and may be distinct from
* NetDevice states, such as found in real implementations

View File

@@ -56,12 +56,17 @@ public:
void SetNode (Ptr<Node> node);
void SetDevice (Ptr<NetDevice> device);
void SetArpCache (Ptr<ArpCache>);
/**
* \returns the underlying NetDevice. This method cannot return zero.
*/
Ptr<NetDevice> GetDevice (void) const;
/**
* \return ARP cache used by this interface
*/
Ptr<ArpCache> GetArpCache () const;
/**
* \param metric configured routing metric (cost) of this interface
*

View File

@@ -241,7 +241,6 @@ private:
bool m_ipForward;
L4List_t m_protocols;
Ipv4InterfaceList m_interfaces;
uint32_t m_nInterfaces;
uint8_t m_defaultTtl;
uint16_t m_identification;
Ptr<Node> m_node;

View File

@@ -174,6 +174,7 @@ Ipv4RawSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags,
{
Ipv4Header header;
header.SetDestination (dst);
header.SetProtocol (m_protocol);
SocketErrno errno_ = ERROR_NOTERROR;//do not use errno as it is the standard C last error number
Ptr<Ipv4Route> route;
uint32_t oif = 0; //specify non-zero if bound to a source address
@@ -247,6 +248,7 @@ Ipv4RawSocketImpl::ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<NetD
{
return false;
}
NS_LOG_LOGIC ("src = " << m_src << " dst = " << m_dst);
if ((m_src == Ipv4Address::GetAny () || ipHeader.GetDestination () == m_src) &&
(m_dst == Ipv4Address::GetAny () || ipHeader.GetSource () == m_dst) &&
ipHeader.GetProtocol () == m_protocol)

View File

@@ -35,9 +35,9 @@ TypeId Ipv6ExtensionDemux::GetTypeId ()
static TypeId tid = TypeId ("ns3::Ipv6ExtensionDemux")
.SetParent<Object> ()
.AddAttribute ("Extensions", "The set of IPv6 extensions registered with this demux.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Ipv6ExtensionDemux::m_extensions),
MakeObjectVectorChecker<Ipv6Extension> ())
ObjectVectorValue (),
MakeObjectVectorAccessor (&Ipv6ExtensionDemux::m_extensions),
MakeObjectVectorChecker<Ipv6Extension> ())
;
return tid;
}
@@ -53,10 +53,10 @@ Ipv6ExtensionDemux::~Ipv6ExtensionDemux ()
void Ipv6ExtensionDemux::DoDispose ()
{
for (Ipv6ExtensionList_t::iterator it = m_extensions.begin (); it != m_extensions.end (); it++)
{
(*it)->Dispose ();
*it = 0;
}
{
(*it)->Dispose ();
*it = 0;
}
m_extensions.clear ();
m_node = 0;
Object::DoDispose ();
@@ -75,12 +75,12 @@ void Ipv6ExtensionDemux::Insert (Ptr<Ipv6Extension> extension)
Ptr<Ipv6Extension> Ipv6ExtensionDemux::GetExtension (uint8_t extensionNumber)
{
for (Ipv6ExtensionList_t::iterator i = m_extensions.begin (); i != m_extensions.end (); ++i)
{
if ((*i)->GetExtensionNumber () == extensionNumber)
{
return *i;
if ((*i)->GetExtensionNumber () == extensionNumber)
{
return *i;
}
}
}
return 0;
}

View File

@@ -37,66 +37,66 @@ class Node;
*/
class Ipv6ExtensionDemux : public Object
{
public:
/**
* \brief The interface ID.
* \return type ID
*/
static TypeId GetTypeId (void);
public:
/**
* \brief The interface ID.
* \return type ID
*/
static TypeId GetTypeId (void);
/**
* \brief Constructor.
*/
Ipv6ExtensionDemux ();
/**
* \brief Constructor.
*/
Ipv6ExtensionDemux ();
/**
* \brief Destructor.
*/
virtual ~Ipv6ExtensionDemux ();
/**
* \brief Destructor.
*/
virtual ~Ipv6ExtensionDemux ();
/**
* \brief Set the node.
* \param node the node to set
*/
void SetNode (Ptr<Node> node);
/**
* \brief Set the node.
* \param node the node to set
*/
void SetNode (Ptr<Node> node);
/**
* \brief Insert a new IPv6 Extension.
* \param extension the extension to insert
*/
void Insert (Ptr<Ipv6Extension> extension);
/**
* \brief Insert a new IPv6 Extension.
* \param extension the extension to insert
*/
void Insert (Ptr<Ipv6Extension> extension);
/**
* \brief Get the extension corresponding to extensionNumber.
* \param extensionNumber extension number of the extension to retrieve
* \return a matching IPv6 extension
*/
Ptr<Ipv6Extension> GetExtension (uint8_t extensionNumber);
/**
* \brief Get the extension corresponding to extensionNumber.
* \param extensionNumber extension number of the extension to retrieve
* \return a matching IPv6 extension
*/
Ptr<Ipv6Extension> GetExtension (uint8_t extensionNumber);
/**
* \brief Remove an extension from this demux.
* \param extension pointer on the extension to remove
*/
void Remove (Ptr<Ipv6Extension> extension);
/**
* \brief Remove an extension from this demux.
* \param extension pointer on the extension to remove
*/
void Remove (Ptr<Ipv6Extension> extension);
protected:
/**
* \brief Dispose object.
*/
virtual void DoDispose ();
protected:
/**
* \brief Dispose object.
*/
virtual void DoDispose ();
private:
typedef std::list<Ptr<Ipv6Extension> > Ipv6ExtensionList_t;
private:
typedef std::list<Ptr<Ipv6Extension> > Ipv6ExtensionList_t;
/**
* \brief List of IPv6 Extensions supported.
*/
Ipv6ExtensionList_t m_extensions;
/**
* \brief List of IPv6 Extensions supported.
*/
Ipv6ExtensionList_t m_extensions;
/**
* \brief The node.
*/
Ptr<Node> m_node;
/**
* \brief The node.
*/
Ptr<Node> m_node;
};
} /* namespace ns3 */

View File

@@ -45,7 +45,7 @@ TypeId Ipv6ExtensionHeader::GetInstanceTypeId () const
}
Ipv6ExtensionHeader::Ipv6ExtensionHeader ()
: m_nextHeader (0),
: m_nextHeader (0),
m_length (0),
m_data (0)
{
@@ -106,13 +106,13 @@ uint32_t Ipv6ExtensionHeader::Deserialize (Buffer::Iterator start)
i.Read (data, dataLength);
if (dataLength > m_data.GetSize ())
{
m_data.AddAtEnd (dataLength - m_data.GetSize ());
}
{
m_data.AddAtEnd (dataLength - m_data.GetSize ());
}
else
{
m_data.RemoveAtEnd (m_data.GetSize () - dataLength);
}
{
m_data.RemoveAtEnd (m_data.GetSize () - dataLength);
}
i = m_data.Begin ();
i.Write (data, dataLength);
@@ -121,7 +121,7 @@ uint32_t Ipv6ExtensionHeader::Deserialize (Buffer::Iterator start)
}
OptionField::OptionField (uint32_t optionsOffset)
: m_optionData (0),
: m_optionData (0),
m_optionsOffset (optionsOffset)
{
}
@@ -141,13 +141,13 @@ void OptionField::Serialize (Buffer::Iterator start) const
uint32_t fill = CalculatePad ((Ipv6OptionHeader::Alignment) {8,0});
NS_LOG_LOGIC ("fill with " << fill << " bytes padding");
switch (fill)
{
{
case 0: return;
case 1: Ipv6OptionPad1Header ().Serialize (start);
return;
default: Ipv6OptionPadnHeader (fill).Serialize (start);
return;
}
}
}
uint32_t OptionField::Deserialize (Buffer::Iterator start, uint32_t length)
@@ -167,13 +167,13 @@ void OptionField::AddOption (Ipv6OptionHeader const& option)
uint32_t pad = CalculatePad (option.GetAlignment ());
NS_LOG_LOGIC ("need " << pad << " bytes padding");
switch (pad)
{
{
case 0: break; //no padding needed
case 1: AddOption (Ipv6OptionPad1Header ());
break;
break;
default: AddOption (Ipv6OptionPadnHeader (pad));
break;
}
break;
}
m_optionData.AddAtEnd (option.GetSerializedSize ());
Buffer::Iterator it = m_optionData.End ();
@@ -214,7 +214,7 @@ TypeId Ipv6ExtensionHopByHopHeader::GetInstanceTypeId () const
}
Ipv6ExtensionHopByHopHeader::Ipv6ExtensionHopByHopHeader ()
: OptionField (2)
: OptionField (2)
{
}
@@ -269,7 +269,7 @@ TypeId Ipv6ExtensionDestinationHeader::GetInstanceTypeId () const
}
Ipv6ExtensionDestinationHeader::Ipv6ExtensionDestinationHeader ()
: OptionField (2)
: OptionField (2)
{
}
@@ -325,7 +325,7 @@ TypeId Ipv6ExtensionFragmentHeader::GetInstanceTypeId () const
}
Ipv6ExtensionFragmentHeader::Ipv6ExtensionFragmentHeader ()
: m_offset (0),
: m_offset (0),
m_identification (0)
{
}
@@ -416,7 +416,7 @@ TypeId Ipv6ExtensionRoutingHeader::GetInstanceTypeId () const
}
Ipv6ExtensionRoutingHeader::Ipv6ExtensionRoutingHeader ()
: m_typeRouting (0),
: m_typeRouting (0),
m_segmentsLeft (0)
{
}
@@ -495,7 +495,7 @@ TypeId Ipv6ExtensionLooseRoutingHeader::GetInstanceTypeId () const
}
Ipv6ExtensionLooseRoutingHeader::Ipv6ExtensionLooseRoutingHeader ()
: m_routersAddress (0)
: m_routersAddress (0)
{
}
@@ -535,9 +535,9 @@ void Ipv6ExtensionLooseRoutingHeader::Print (std::ostream &os) const
<< " typeRouting = " << (uint32_t)GetTypeRouting () << " segmentsLeft = " << (uint32_t)GetSegmentsLeft () << " ";
for (std::vector<Ipv6Address>::const_iterator it = m_routersAddress.begin (); it != m_routersAddress.end (); it++)
{
os << *it << " ";
}
{
os << *it << " ";
}
os << " )";
}
@@ -559,10 +559,10 @@ void Ipv6ExtensionLooseRoutingHeader::Serialize (Buffer::Iterator start) const
i.WriteU32 (0);
for (VectorIpv6Address_t::const_iterator it = m_routersAddress.begin (); it != m_routersAddress.end () ; it++)
{
it->Serialize (buff);
i.Write (buff, 16);
}
{
it->Serialize (buff);
i.Write (buff, 16);
}
}
uint32_t Ipv6ExtensionLooseRoutingHeader::Deserialize (Buffer::Iterator start)
@@ -577,10 +577,10 @@ uint32_t Ipv6ExtensionLooseRoutingHeader::Deserialize (Buffer::Iterator start)
i.ReadU32 ();
for (std::vector<Ipv6Address>::iterator it = m_routersAddress.begin (); it != m_routersAddress.end (); it++)
{
i.Read (buff, 16);
it->Set (buff);
}
{
i.Read (buff, 16);
it->Set (buff);
}
return GetSerializedSize ();
}

View File

@@ -53,11 +53,11 @@ TypeId Ipv6Extension::GetTypeId ()
static TypeId tid = TypeId ("ns3::Ipv6Extension")
.SetParent<Object> ()
.AddAttribute ("ExtensionNumber", "The IPv6 extension number.",
UintegerValue (0),
MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber),
MakeUintegerChecker<uint8_t> ())
UintegerValue (0),
MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber),
MakeUintegerChecker<uint8_t> ())
.AddTraceSource ("Drop", "Drop ipv6 packet",
MakeTraceSourceAccessor (&Ipv6Extension::m_dropTrace))
MakeTraceSourceAccessor (&Ipv6Extension::m_dropTrace))
;
return tid;
}
@@ -102,64 +102,64 @@ uint8_t Ipv6Extension::ProcessOptions (Ptr<Packet>& packet, uint8_t offset, uint
uint8_t optionLength = 0;
while (length > processedSize && !isDropped)
{
optionType = *(data + processedSize);
ipv6Option = ipv6OptionDemux->GetOption (optionType);
if (ipv6Option == 0)
{
optionType >>= 6;
switch (optionType)
{
case 0:
optionLength = *(data + processedSize + 1);
break;
optionType = *(data + processedSize);
ipv6Option = ipv6OptionDemux->GetOption (optionType);
case 1:
NS_LOG_LOGIC ("Unknown Option. Drop!");
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
if (ipv6Option == 0)
{
optionType >>= 6;
switch (optionType)
{
case 0:
optionLength = *(data + processedSize + 1);
break;
case 2:
NS_LOG_LOGIC ("Unknown Option. Drop!");
icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
case 1:
NS_LOG_LOGIC ("Unknown Option. Drop!");
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
case 3:
NS_LOG_LOGIC ("Unknown Option. Drop!");
case 2:
NS_LOG_LOGIC ("Unknown Option. Drop!");
icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
{
icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
}
case 3:
NS_LOG_LOGIC ("Unknown Option. Drop!");
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
{
icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
}
default:
break;
}
m_dropTrace (packet);
optionLength = 0;
isDropped = true;
break;
default:
break;
}
}
else
{
optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
}
processedSize += optionLength;
p->RemoveAtStart (optionLength);
}
else
{
optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
}
processedSize += optionLength;
p->RemoveAtStart (optionLength);
}
return processedSize;
}
@@ -203,9 +203,9 @@ uint8_t Ipv6ExtensionHopByHop::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
Ipv6ExtensionHopByHopHeader hopbyhopHeader;
p->RemoveHeader (hopbyhopHeader);
if (nextHeader)
{
*nextHeader = hopbyhopHeader.GetNextHeader ();
}
{
*nextHeader = hopbyhopHeader.GetNextHeader ();
}
uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
offset += processedSize;
@@ -255,9 +255,9 @@ uint8_t Ipv6ExtensionDestination::Process (Ptr<Packet>& packet, uint8_t offset,
Ipv6ExtensionDestinationHeader destinationHeader;
p->RemoveHeader (destinationHeader);
if (nextHeader)
{
*nextHeader = destinationHeader.GetNextHeader ();
}
{
*nextHeader = destinationHeader.GetNextHeader ();
}
uint8_t processedSize = destinationHeader.GetOptionsOffset ();
offset += processedSize;
@@ -295,9 +295,9 @@ void Ipv6ExtensionFragment::DoDispose ()
NS_LOG_FUNCTION_NOARGS ();
for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
{
it->second = 0;
}
{
it->second = 0;
}
m_fragments.clear ();
Ipv6Extension::DoDispose ();
@@ -321,9 +321,9 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
p->RemoveHeader (fragmentHeader);
if (nextHeader)
{
*nextHeader = fragmentHeader.GetNextHeader ();
}
{
*nextHeader = fragmentHeader.GetNextHeader ();
}
bool moreFragment = fragmentHeader.GetMoreFragment ();
uint16_t fragmentOffset = fragmentHeader.GetOffset ();
@@ -335,35 +335,35 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
MapFragments_t::iterator it = m_fragments.find (fragmentsId);
if (it == m_fragments.end ())
{
fragments = Create<Fragments> ();
m_fragments.insert (std::make_pair (fragmentsId, fragments));
}
{
fragments = Create<Fragments> ();
m_fragments.insert (std::make_pair (fragmentsId, fragments));
}
else
{
fragments = it->second;
}
{
fragments = it->second;
}
if (fragmentOffset == 0)
{
Ptr<Packet> unfragmentablePart = packet->Copy ();
unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
fragments->SetUnfragmentablePart (unfragmentablePart);
}
{
Ptr<Packet> unfragmentablePart = packet->Copy ();
unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
fragments->SetUnfragmentablePart (unfragmentablePart);
}
fragments->AddFragment (p, fragmentOffset, moreFragment);
if (fragments->IsEntire ())
{
packet = fragments->GetPacket ();
isDropped = false;
}
{
packet = fragments->GetPacket ();
isDropped = false;
}
else
{
NS_LOG_LOGIC ("Fragment. Drop!");
m_dropTrace (packet);
isDropped = true;
}
{
NS_LOG_LOGIC ("Fragment. Drop!");
m_dropTrace (packet);
isDropped = true;
}
return 0;
}
@@ -381,10 +381,10 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
bool moreHeader = true;
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
ipv6Header.SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
{
moreHeader = false;
ipv6Header.SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
uint32_t unfragmentablePartSize = 0;
@@ -394,64 +394,64 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
uint8_t extensionHeaderLength;
while (moreHeader)
{
if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
Ipv6ExtensionHopByHopHeader *hopbyhopHeader = new Ipv6ExtensionHopByHopHeader ();
p->RemoveHeader (*hopbyhopHeader);
if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
Ipv6ExtensionHopByHopHeader *hopbyhopHeader = new Ipv6ExtensionHopByHopHeader ();
p->RemoveHeader (*hopbyhopHeader);
nextHeader = hopbyhopHeader->GetNextHeader ();
extensionHeaderLength = hopbyhopHeader->GetLength ();
nextHeader = hopbyhopHeader->GetNextHeader ();
extensionHeaderLength = hopbyhopHeader->GetLength ();
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
unfragmentablePartSize += extensionHeaderLength;
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
unfragmentablePartSize += extensionHeaderLength;
}
else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
{
uint8_t numberAddress = (*(p->PeekData () + 1)) / 2;
Ipv6ExtensionLooseRoutingHeader *routingHeader = new Ipv6ExtensionLooseRoutingHeader ();
routingHeader->SetNumberAddress (numberAddress);
p->RemoveHeader (*routingHeader);
nextHeader = routingHeader->GetNextHeader ();
extensionHeaderLength = routingHeader->GetLength ();
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
unfragmentablePartSize += extensionHeaderLength;
}
else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
{
Ipv6ExtensionDestinationHeader *destinationHeader = new Ipv6ExtensionDestinationHeader ();
p->RemoveHeader (*destinationHeader);
nextHeader = destinationHeader->GetNextHeader ();
extensionHeaderLength = destinationHeader->GetLength ();
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
unfragmentablePartSize += extensionHeaderLength;
}
}
else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
{
uint8_t numberAddress = (*(p->PeekData () + 1)) / 2;
Ipv6ExtensionLooseRoutingHeader *routingHeader = new Ipv6ExtensionLooseRoutingHeader ();
routingHeader->SetNumberAddress (numberAddress);
p->RemoveHeader (*routingHeader);
nextHeader = routingHeader->GetNextHeader ();
extensionHeaderLength = routingHeader->GetLength ();
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
unfragmentablePartSize += extensionHeaderLength;
}
else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
{
Ipv6ExtensionDestinationHeader *destinationHeader = new Ipv6ExtensionDestinationHeader ();
p->RemoveHeader (*destinationHeader);
nextHeader = destinationHeader->GetNextHeader ();
extensionHeaderLength = destinationHeader->GetLength ();
if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
|| (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
{
moreHeader = false;
destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
}
unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
unfragmentablePartSize += extensionHeaderLength;
}
}
Ipv6ExtensionFragmentHeader fragmentHeader;
uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize ();
@@ -465,65 +465,65 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
uint16_t offset = 0;
do
{
if (p->GetSize () > offset + maxFragmentablePartSize)
{
moreFragment = true;
currentFragmentablePartSize = maxFragmentablePartSize;
}
else
{
moreFragment = false;
currentFragmentablePartSize = p->GetSize () - offset;
}
if (p->GetSize () > offset + maxFragmentablePartSize)
{
moreFragment = true;
currentFragmentablePartSize = maxFragmentablePartSize;
}
else
{
moreFragment = false;
currentFragmentablePartSize = p->GetSize () - offset;
}
currentFragmentablePartSize -= currentFragmentablePartSize % 8;
currentFragmentablePartSize -= currentFragmentablePartSize % 8;
fragmentHeader.SetNextHeader (nextHeader);
fragmentHeader.SetLength (currentFragmentablePartSize);
fragmentHeader.SetOffset (offset);
fragmentHeader.SetMoreFragment (moreFragment);
fragmentHeader.SetIdentification (identification);
fragmentHeader.SetNextHeader (nextHeader);
fragmentHeader.SetLength (currentFragmentablePartSize);
fragmentHeader.SetOffset (offset);
fragmentHeader.SetMoreFragment (moreFragment);
fragmentHeader.SetIdentification (identification);
Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
offset += currentFragmentablePartSize;
Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
offset += currentFragmentablePartSize;
fragment->AddHeader (fragmentHeader);
fragment->AddHeader (fragmentHeader);
for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
{
if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *>(it->first));
}
else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *>(it->first));
}
else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *>(it->first));
}
}
for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
{
if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *>(it->first));
}
else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *>(it->first));
}
else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
{
fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *>(it->first));
}
}
ipv6Header.SetPayloadLength (fragment->GetSize ());
fragment->AddHeader (ipv6Header);
ipv6Header.SetPayloadLength (fragment->GetSize ());
fragment->AddHeader (ipv6Header);
std::ostringstream oss;
fragment->Print (oss);
listFragments.push_back (fragment);
} while (moreFragment);
std::ostringstream oss;
fragment->Print (oss);
listFragments.push_back (fragment);
} while (moreFragment);
for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
{
delete it->first;
}
{
delete it->first;
}
unfragmentablePart.clear ();
}
Ipv6ExtensionFragment::Fragments::Fragments ()
: m_moreFragment (0)
: m_moreFragment (0)
{
}
@@ -536,17 +536,17 @@ void Ipv6ExtensionFragment::Fragments::AddFragment (Ptr<Packet> fragment, uint16
std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
for (it = m_fragments.begin (); it != m_fragments.end (); it++)
{
if (it->second > fragmentOffset)
{
break;
if (it->second > fragmentOffset)
{
break;
}
}
}
if (it == m_fragments.end ())
{
m_moreFragment = moreFragment;
}
{
m_moreFragment = moreFragment;
}
m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
}
@@ -561,20 +561,20 @@ bool Ipv6ExtensionFragment::Fragments::IsEntire () const
bool ret = !m_moreFragment && m_fragments.size () > 0;
if (ret)
{
uint16_t lastEndOffset = 0;
for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
{
if (lastEndOffset != it->second)
{
ret = false;
break;
}
uint16_t lastEndOffset = 0;
lastEndOffset += it->first->GetSize ();
for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
{
if (lastEndOffset != it->second)
{
ret = false;
break;
}
lastEndOffset += it->first->GetSize ();
}
}
}
return ret;
}
@@ -584,9 +584,9 @@ Ptr<Packet> Ipv6ExtensionFragment::Fragments::GetPacket () const
Ptr<Packet> p = m_unfragmentable->Copy ();
for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
{
p->AddAtEnd (it->first);
}
{
p->AddAtEnd (it->first);
}
return p;
}
@@ -640,14 +640,14 @@ uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6
const uint8_t *buff = packet->PeekData ();
uint8_t routingNextHeader = *buff;
uint8_t routingLength = *(buff+1);
uint8_t routingTypeRouting = *(buff+2);
uint8_t routingSegmentsLeft = *(buff+3);
uint8_t routingLength = *(buff + 1);
uint8_t routingTypeRouting = *(buff + 2);
uint8_t routingSegmentsLeft = *(buff + 3);
if (nextHeader)
{
*nextHeader = routingNextHeader;
}
{
*nextHeader = routingNextHeader;
}
Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
@@ -655,22 +655,22 @@ uint8_t Ipv6ExtensionRouting::Process (Ptr<Packet>& packet, uint8_t offset, Ipv6
Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
if (ipv6ExtensionRouting == 0)
{
if (routingSegmentsLeft == 0)
{
isDropped = false;
}
else
{
NS_LOG_LOGIC ("Malformed header. Drop!");
if (routingSegmentsLeft == 0)
{
isDropped = false;
}
else
{
NS_LOG_LOGIC ("Malformed header. Drop!");
icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
m_dropTrace (packet);
isDropped = true;
}
icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
m_dropTrace (packet);
isDropped = true;
}
return routingLength;
}
return routingLength;
}
return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
}
@@ -683,9 +683,9 @@ TypeId Ipv6ExtensionRoutingDemux::GetTypeId ()
static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
.SetParent<Object> ()
.AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Ipv6ExtensionRoutingDemux::m_extensionsRouting),
MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
ObjectVectorValue (),
MakeObjectVectorAccessor (&Ipv6ExtensionRoutingDemux::m_extensionsRouting),
MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
;
return tid;
}
@@ -701,10 +701,10 @@ Ipv6ExtensionRoutingDemux::~Ipv6ExtensionRoutingDemux ()
void Ipv6ExtensionRoutingDemux::DoDispose ()
{
for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
{
(*it)->Dispose ();
*it = 0;
}
{
(*it)->Dispose ();
*it = 0;
}
m_extensionsRouting.clear ();
m_node = 0;
Object::DoDispose ();
@@ -723,12 +723,12 @@ void Ipv6ExtensionRoutingDemux::Insert (Ptr<Ipv6ExtensionRouting> extensionRouti
Ptr<Ipv6ExtensionRouting> Ipv6ExtensionRoutingDemux::GetExtensionRouting (uint8_t typeRouting)
{
for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
{
if ((*i)->GetTypeRouting () == typeRouting)
{
return *i;
if ((*i)->GetTypeRouting () == typeRouting)
{
return *i;
}
}
}
return 0;
}
@@ -792,9 +792,9 @@ uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset,
p->RemoveHeader (routingHeader);
if (nextHeader)
{
*nextHeader = routingHeader.GetNextHeader ();
}
{
*nextHeader = routingHeader.GetNextHeader ();
}
Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
@@ -808,51 +808,51 @@ uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset,
Ipv6Address nextAddress;
if (segmentsLeft == 0)
{
isDropped = false;
return routingHeader.GetSerializedSize ();
}
{
isDropped = false;
return routingHeader.GetSerializedSize ();
}
if (length % 2 != 0)
{
NS_LOG_LOGIC ("Malformed header. Drop!");
icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
{
NS_LOG_LOGIC ("Malformed header. Drop!");
icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
if (segmentsLeft > nbAddress)
{
NS_LOG_LOGIC ("Malformed header. Drop!");
icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
{
NS_LOG_LOGIC ("Malformed header. Drop!");
icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
routingHeader.SetSegmentsLeft (segmentsLeft - 1);
nextAddressIndex = nbAddress - segmentsLeft;
nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
{
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
{
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
ipv6header.SetDestinationAddress (nextAddress);
if (hopLimit <= 1)
{
NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
{
NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
m_dropTrace (packet);
isDropped = true;
return routingHeader.GetSerializedSize ();
}
routingHeader.SetLength (88);
ipv6header.SetHopLimit (hopLimit - 1);
@@ -873,14 +873,14 @@ uint8_t Ipv6ExtensionLooseRouting::Process (Ptr<Packet>& packet, uint8_t offset,
Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
if (rtentry)
{
/* we know a route exists so send packet now */
ipv6->SendRealOut (rtentry, p, ipv6header);
}
{
/* we know a route exists so send packet now */
ipv6->SendRealOut (rtentry, p, ipv6header);
}
else
{
NS_LOG_INFO ("No route for next router");
}
{
NS_LOG_INFO ("No route for next router");
}
/* as we directly send packet, mark it as dropped */
isDropped = true;

View File

@@ -35,9 +35,9 @@ TypeId Ipv6OptionDemux::GetTypeId ()
static TypeId tid = TypeId ("ns3::Ipv6OptionDemux")
.SetParent<Object> ()
.AddAttribute ("Options", "The set of IPv6 options registered with this demux.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Ipv6OptionDemux::m_options),
MakeObjectVectorChecker<Ipv6Option> ())
ObjectVectorValue (),
MakeObjectVectorAccessor (&Ipv6OptionDemux::m_options),
MakeObjectVectorChecker<Ipv6Option> ())
;
return tid;
}
@@ -53,10 +53,10 @@ Ipv6OptionDemux::~Ipv6OptionDemux ()
void Ipv6OptionDemux::DoDispose ()
{
for (Ipv6OptionList_t::iterator it = m_options.begin (); it != m_options.end (); it++)
{
(*it)->Dispose ();
*it = 0;
}
{
(*it)->Dispose ();
*it = 0;
}
m_options.clear ();
m_node = 0;
Object::DoDispose ();
@@ -75,12 +75,12 @@ void Ipv6OptionDemux::Insert (Ptr<Ipv6Option> option)
Ptr<Ipv6Option> Ipv6OptionDemux::GetOption (int optionNumber)
{
for (Ipv6OptionList_t::iterator i = m_options.begin (); i != m_options.end (); ++i)
{
if ((*i)->GetOptionNumber () == optionNumber)
{
return *i;
if ((*i)->GetOptionNumber () == optionNumber)
{
return *i;
}
}
}
return 0;
}

View File

@@ -37,66 +37,66 @@ class Node;
*/
class Ipv6OptionDemux : public Object
{
public:
/**
* \brief The interface ID.
* \return type ID
*/
static TypeId GetTypeId (void);
public:
/**
* \brief The interface ID.
* \return type ID
*/
static TypeId GetTypeId (void);
/**
* \brief Constructor.
*/
Ipv6OptionDemux ();
/**
* \brief Constructor.
*/
Ipv6OptionDemux ();
/**
* \brief Destructor.
*/
virtual ~Ipv6OptionDemux ();
/**
* \brief Destructor.
*/
virtual ~Ipv6OptionDemux ();
/**
* \brief Set the node.
* \param node the node to set
*/
void SetNode (Ptr<Node> node);
/**
* \brief Set the node.
* \param node the node to set
*/
void SetNode (Ptr<Node> node);
/**
* \brief Insert a new IPv6 Option.
* \param option the option to insert
*/
void Insert (Ptr<Ipv6Option> option);
/**
* \brief Insert a new IPv6 Option.
* \param option the option to insert
*/
void Insert (Ptr<Ipv6Option> option);
/**
* \brief Get the option corresponding to optionNumber.
* \param optionNumber the option number of the option to retrieve
* \return a matching IPv6 option
*/
Ptr<Ipv6Option> GetOption (int optionNumber);
/**
* \brief Get the option corresponding to optionNumber.
* \param optionNumber the option number of the option to retrieve
* \return a matching IPv6 option
*/
Ptr<Ipv6Option> GetOption (int optionNumber);
/**
* \brief Remove an option from this demux.
* \param option pointer on the option to remove
*/
void Remove (Ptr<Ipv6Option> option);
/**
* \brief Remove an option from this demux.
* \param option pointer on the option to remove
*/
void Remove (Ptr<Ipv6Option> option);
protected:
/**
* \brief Dispose this object.
*/
virtual void DoDispose();
protected:
/**
* \brief Dispose this object.
*/
virtual void DoDispose();
private:
typedef std::list<Ptr<Ipv6Option> > Ipv6OptionList_t;
private:
typedef std::list<Ptr<Ipv6Option> > Ipv6OptionList_t;
/**
* \brief List of IPv6 Options supported.
*/
Ipv6OptionList_t m_options;
/**
* \brief List of IPv6 Options supported.
*/
Ipv6OptionList_t m_options;
/**
* \brief The node.
*/
Ptr<Node> m_node;
/**
* \brief The node.
*/
Ptr<Node> m_node;
};
} /* namespace ns3 */

View File

@@ -45,7 +45,7 @@ TypeId Ipv6OptionHeader::GetInstanceTypeId () const
}
Ipv6OptionHeader::Ipv6OptionHeader ()
: m_type (0),
: m_type (0),
m_length (0)
{
}
@@ -212,9 +212,9 @@ void Ipv6OptionPadnHeader::Serialize (Buffer::Iterator start) const
i.WriteU8 (GetLength ());
for (int padding = 0; padding < GetLength (); padding++)
{
i.WriteU8 (0);
}
{
i.WriteU8 (0);
}
}
uint32_t Ipv6OptionPadnHeader::Deserialize (Buffer::Iterator start)
@@ -315,7 +315,7 @@ TypeId Ipv6OptionRouterAlertHeader::GetInstanceTypeId () const
}
Ipv6OptionRouterAlertHeader::Ipv6OptionRouterAlertHeader ()
: m_value (0)
: m_value (0)
{
SetLength (2);
}

View File

@@ -36,9 +36,9 @@ TypeId Ipv6Option::GetTypeId ()
static TypeId tid = TypeId ("ns3::Ipv6Option")
.SetParent<Object> ()
.AddAttribute ("OptionNumber", "The IPv6 option number.",
UintegerValue (0),
MakeUintegerAccessor (&Ipv6Option::GetOptionNumber),
MakeUintegerChecker<uint8_t> ())
UintegerValue (0),
MakeUintegerAccessor (&Ipv6Option::GetOptionNumber),
MakeUintegerChecker<uint8_t> ())
;
return tid;
}

View File

@@ -576,6 +576,7 @@ TcpL4Protocol::Send (Ptr<Packet> packet,
// should be cached.
Ipv4Header header;
header.SetDestination (daddr);
header.SetProtocol (PROT_NUMBER);
Socket::SocketErrno errno_;
Ptr<Ipv4Route> route;
uint32_t oif = 0; //specify non-zero if bound to a source address
@@ -615,6 +616,7 @@ TcpL4Protocol::SendPacket (Ptr<Packet> packet, const TcpHeader &outgoing,
// should be cached.
Ipv4Header header;
header.SetDestination (daddr);
header.SetProtocol (PROT_NUMBER);
Socket::SocketErrno errno_;
Ptr<Ipv4Route> route;
uint32_t oif = 0; //specify non-zero if bound to a source address

View File

@@ -373,6 +373,8 @@ UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
// Get the primary address
Ipv4InterfaceAddress iaddr = ipv4->GetAddress (i, 0);
Ipv4Address addri = iaddr.GetLocal ();
if (addri == Ipv4Address ("127.0.0.1"))
continue;
Ipv4Mask maski = iaddr.GetMask ();
if (maski == Ipv4Mask::GetOnes ())
{
@@ -403,6 +405,7 @@ UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
{
Ipv4Header header;
header.SetDestination (dest);
header.SetProtocol (UdpL4Protocol::PROT_NUMBER);
Socket::SocketErrno errno_;
Ptr<Ipv4Route> route;
uint32_t oif = 0; //specify non-zero if bound to a source address

View File

@@ -128,6 +128,8 @@ def build(bld):
'sequence-number.h',
'icmpv4.h',
'icmpv6-header.h',
# used by routing
'ipv4-interface.h',
'ipv4-l3-protocol.h',
'ipv6-l3-protocol.h',
'ipv6-extension-header.h',

View File

@@ -45,7 +45,9 @@ Ptr<Socket>
Socket::CreateSocket (Ptr<Node> node, TypeId tid)
{
Ptr<Socket> s;
NS_ASSERT (node != 0);
Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
NS_ASSERT (socketFactory != 0);
s = socketFactory->CreateSocket ();
NS_ASSERT (s != 0);
return s;

View File

@@ -0,0 +1,173 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#include "aodv-neighbor.h"
#include "ns3/log.h"
#include <algorithm>
NS_LOG_COMPONENT_DEFINE ("AodvNeighbors");
namespace ns3
{
namespace aodv
{
Neighbors::Neighbors (Time delay) :
m_ntimer (Timer::CANCEL_ON_DESTROY)
{
m_ntimer.SetDelay(delay);
m_ntimer.SetFunction(&Neighbors::Purge, this);
m_txErrorCallback = MakeCallback (& Neighbors::ProcessTxError, this);
}
bool
Neighbors::IsNeighbor (Ipv4Address addr)
{
Purge ();
for (std::vector<Neighbor>::const_iterator i = m_nb.begin ();
i != m_nb.end (); ++i)
{
if (i->m_neighborAddress == addr)
return true;
}
return false;
}
Time
Neighbors::GetExpireTime (Ipv4Address addr)
{
Purge ();
for (std::vector<Neighbor>::const_iterator i = m_nb.begin (); i
!= m_nb.end (); ++i)
{
if (i->m_neighborAddress == addr)
return (i->m_expireTime - Simulator::Now ());
}
return Seconds (0);
}
void
Neighbors::Update (Ipv4Address addr, Time expire)
{
for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i)
if (i->m_neighborAddress == addr)
{
i->m_expireTime
= std::max (expire + Simulator::Now (), i->m_expireTime);
if (i->m_hardwareAddress == Mac48Address ())
i->m_hardwareAddress = LookupMacAddress (i->m_neighborAddress);
return;
}
NS_LOG_LOGIC ("Open link to " << addr);
Neighbor neighbor (addr, LookupMacAddress (addr), expire + Simulator::Now ());
m_nb.push_back (neighbor);
Purge ();
}
struct CloseNeighbor
{
bool operator() (const Neighbors::Neighbor & nb) const
{
return ((nb.m_expireTime < Simulator::Now ()) || nb.close);
}
};
void
Neighbors::Purge ()
{
if (m_nb.empty ())
return;
CloseNeighbor pred;
if (!m_handleLinkFailure.IsNull ())
{
for (std::vector<Neighbor>::iterator j = m_nb.begin (); j != m_nb.end (); ++j)
{
if (pred (*j))
{
NS_LOG_LOGIC ("Close link to " << j->m_neighborAddress);
m_handleLinkFailure (j->m_neighborAddress);
}
}
}
m_nb.erase (std::remove_if (m_nb.begin (), m_nb.end (), pred), m_nb.end ());
m_ntimer.Cancel ();
m_ntimer.Schedule ();
}
void
Neighbors::ScheduleTimer ()
{
m_ntimer.Cancel ();
m_ntimer.Schedule ();
}
void
Neighbors::AddArpCache (Ptr<ArpCache> a)
{
m_arp.push_back (a);
}
void
Neighbors::DelArpCache (Ptr<ArpCache> a)
{
m_arp.erase (std::remove (m_arp.begin (), m_arp.end (), a), m_arp.end ());
}
Mac48Address
Neighbors::LookupMacAddress (Ipv4Address addr)
{
Mac48Address hwaddr;
for (std::vector<Ptr<ArpCache> >::const_iterator i = m_arp.begin ();
i != m_arp.end (); ++i)
{
ArpCache::Entry * entry = (*i)->Lookup (addr);
if (entry != 0 && entry->IsAlive () && !entry->IsExpired ())
{
hwaddr = Mac48Address::ConvertFrom (entry->GetMacAddress ());
break;
}
}
return hwaddr;
}
void
Neighbors::ProcessTxError (WifiMacHeader const & hdr)
{
Mac48Address addr = hdr.GetAddr1 ();
for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i)
{
if (i->m_hardwareAddress == addr)
i->close = true;
}
Purge ();
}
}
}

View File

@@ -0,0 +1,114 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AODVNEIGHBOR_H
#define AODVNEIGHBOR_H
#include "ns3/simulator.h"
#include "ns3/timer.h"
#include "ns3/ipv4-address.h"
#include "ns3/callback.h"
#include "ns3/wifi-mac-header.h"
#include "ns3/arp-cache.h"
#include <vector>
namespace ns3
{
namespace aodv
{
class RoutingProtocol;
/**
* \ingroup aodv
* \brief maintain list of active neighbors
*/
class Neighbors
{
public:
/// c-tor
Neighbors (Time delay);
/// Neighbor description
struct Neighbor
{
Ipv4Address m_neighborAddress;
Mac48Address m_hardwareAddress;
Time m_expireTime;
bool close;
Neighbor (Ipv4Address ip, Mac48Address mac, Time t) :
m_neighborAddress (ip), m_hardwareAddress (mac), m_expireTime (t),
close (false)
{
}
};
/// Return expire time for neighbor node with address addr, if exists, else return 0.
Time GetExpireTime (Ipv4Address addr);
/// Check that node with address addr is neighbor
bool IsNeighbor (Ipv4Address addr);
/// Update expire time for entry with address addr, if it exists, else add new entry
void Update (Ipv4Address addr, Time expire);
/// Remove all expired entries
void Purge ();
/// Schedule m_ntimer.
void ScheduleTimer ();
/// Remove all entries
void Clear () { m_nb.clear (); }
/// Add ARP cache to be used to allow layer 2 notifications processing
void AddArpCache (Ptr<ArpCache>);
/// Don't use given ARP cache any more (interface is down)
void DelArpCache (Ptr<ArpCache>);
/// Get callback to ProcessTxError
Callback<void, WifiMacHeader const &> GetTxErrorCallback () const { return m_txErrorCallback; }
///\name Handle link failure callback
//\{
void SetCallback (Callback<void, Ipv4Address> cb) { m_handleLinkFailure = cb;}
Callback<void, Ipv4Address> GetCallback () const { return m_handleLinkFailure; }
//\}
private:
/// link failure callback
Callback<void, Ipv4Address> m_handleLinkFailure;
/// TX error callback
Callback<void, WifiMacHeader const &> m_txErrorCallback;
/// Timer for neighbor's list. Schedule Purge().
Timer m_ntimer;
/// vector of entries
std::vector<Neighbor> m_nb;
/// list of ARP cached to be used for layer 2 notifications processing
std::vector<Ptr<ArpCache> > m_arp;
/// Find MAC address by IP using list of ARP caches
Mac48Address LookupMacAddress (Ipv4Address);
/// Process layer 2 TX error notification
void ProcessTxError (WifiMacHeader const &);
};
}
}
#endif /* AODVNEIGHBOR_H */

View File

@@ -0,0 +1,580 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#include "aodv-packet.h"
#include "ns3/address-utils.h"
#include "ns3/packet.h"
namespace ns3
{
namespace aodv
{
TypeHeader::TypeHeader (MessageType t) :
m_type (t), m_valid (true)
{
}
TypeId
TypeHeader::GetInstanceTypeId () const
{
return TypeId ();
}
uint32_t
TypeHeader::GetSerializedSize () const
{
return 1;
}
void
TypeHeader::Serialize (Buffer::Iterator i) const
{
i.WriteU8 ((uint8_t) m_type);
}
uint32_t
TypeHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
uint8_t type = i.ReadU8 ();
m_valid = true;
switch (type)
{
case AODVTYPE_RREQ:
case AODVTYPE_RREP:
case AODVTYPE_RERR:
case AODVTYPE_RREP_ACK:
{
m_type = (MessageType) type;
break;
}
default:
m_valid = false;
}
uint32_t dist = i.GetDistanceFrom (start);
NS_ASSERT (dist == GetSerializedSize ());
return dist;
}
void
TypeHeader::Print (std::ostream &os) const
{
switch (m_type)
{
case AODVTYPE_RREQ:
{
os << "RREQ" << "\n";
break;
}
case AODVTYPE_RREP:
{
os << "RREP" << "\n";
break;
}
case AODVTYPE_RERR:
{
os << "RERR" << "\n";
break;
}
case AODVTYPE_RREP_ACK:
{
os << "RREP_ACK" << "\n";
break;
}
default:
os << "UNKNOWN_TYPE";
}
}
bool
TypeHeader::operator== (TypeHeader const & o) const
{
return (m_type == o.m_type && m_valid == o.m_valid);
}
std::ostream &
operator<< (std::ostream & os, TypeHeader const & h)
{
h.Print (os);
return os;
}
//-----------------------------------------------------------------------------
// RREQ
//-----------------------------------------------------------------------------
RreqHeader::RreqHeader (uint8_t flags, uint8_t reserved, uint8_t hopCount, uint32_t requestID, Ipv4Address dst,
uint32_t dstSeqNo, Ipv4Address origin, uint32_t originSeqNo) :
m_flags (flags), m_reserved (reserved), m_hopCount (hopCount), m_requestID (requestID), m_dst(dst),
m_dstSeqNo (dstSeqNo), m_origin(origin), m_originSeqNo (originSeqNo)
{
}
TypeId
RreqHeader::GetInstanceTypeId () const
{
return TypeId ();
}
uint32_t
RreqHeader::GetSerializedSize () const
{
return 23;
}
void
RreqHeader::Serialize (Buffer::Iterator i) const
{
i.WriteU8 (m_flags);
i.WriteU8 (m_reserved);
i.WriteU8 (m_hopCount);
i.WriteHtonU32 (m_requestID);
WriteTo (i, m_dst);
i.WriteHtonU32 (m_dstSeqNo);
WriteTo (i, m_origin);
i.WriteHtonU32 (m_originSeqNo);
}
uint32_t
RreqHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
m_flags = i.ReadU8 ();
m_reserved = i.ReadU8 ();
m_hopCount = i.ReadU8 ();
m_requestID = i.ReadNtohU32 ();
ReadFrom (i, m_dst);
m_dstSeqNo = i.ReadNtohU32 ();
ReadFrom (i, m_origin);
m_originSeqNo = i.ReadNtohU32 ();
uint32_t dist = i.GetDistanceFrom (start);
NS_ASSERT (dist == GetSerializedSize ());
return dist;
}
void
RreqHeader::Print (std::ostream &os) const
{
os << "RREQ ID " << m_requestID << "\n" << "destination: ipv4 " << m_dst
<< " " << "sequence number " << m_dstSeqNo << "\n" << "source: ipv4 "
<< m_origin << " " << "sequence number " << m_originSeqNo << "\n"
<< "flags:\n" << "Gratuitous RREP " << (*this).GetGratiousRrep () << "\n"
<< "Destination only " << (*this).GetDestinationOnly () << "\n"
<< "Unknown sequence number " << (*this).GetUnknownSeqno () << "\n";
}
std::ostream &
operator<< (std::ostream & os, RreqHeader const & h)
{
h.Print (os);
return os;
}
void
RreqHeader::SetGratiousRrep (bool f)
{
if (f)
m_flags |= (1 << 5);
else
m_flags &= ~(1 << 5);
}
bool
RreqHeader::GetGratiousRrep () const
{
return (m_flags & (1 << 5));
}
void
RreqHeader::SetDestinationOnly (bool f)
{
if (f)
m_flags |= (1 << 4);
else
m_flags &= ~(1 << 4);
}
bool
RreqHeader::GetDestinationOnly () const
{
return (m_flags & (1 << 4));
}
void
RreqHeader::SetUnknownSeqno (bool f)
{
if (f)
m_flags |= (1 << 3);
else
m_flags &= ~(1 << 3);
}
bool
RreqHeader::GetUnknownSeqno () const
{
return (m_flags & (1 << 3));
}
bool
RreqHeader::operator== (RreqHeader const & o) const
{
return (m_flags == o.m_flags && m_reserved == o.m_reserved &&
m_hopCount == o.m_hopCount && m_requestID == o.m_requestID &&
m_dst == o.m_dst && m_dstSeqNo == o.m_dstSeqNo &&
m_origin == o.m_origin && m_originSeqNo == o.m_originSeqNo);
}
//-----------------------------------------------------------------------------
// RREP
//-----------------------------------------------------------------------------
RrepHeader::RrepHeader (uint8_t prefixSize, uint8_t hopCount, Ipv4Address dst,
uint32_t dstSeqNo, Ipv4Address origin, Time lifeTime) :
m_flags (0), m_prefixSize (prefixSize), m_hopCount (hopCount),
m_dst (dst), m_dstSeqNo (dstSeqNo), m_origin (origin)
{
m_lifeTime = uint32_t (lifeTime.GetMilliSeconds ());
}
TypeId
RrepHeader::GetInstanceTypeId () const
{
return TypeId ();
}
uint32_t
RrepHeader::GetSerializedSize () const
{
return 19;
}
void
RrepHeader::Serialize (Buffer::Iterator i) const
{
i.WriteU8 (m_flags);
i.WriteU8 (m_prefixSize);
i.WriteU8 (m_hopCount);
WriteTo (i, m_dst);
i.WriteHtonU32 (m_dstSeqNo);
WriteTo (i, m_origin);
i.WriteHtonU32 (m_lifeTime);
}
uint32_t
RrepHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
m_flags = i.ReadU8 ();
m_prefixSize = i.ReadU8 ();
m_hopCount = i.ReadU8 ();
ReadFrom (i, m_dst);
m_dstSeqNo = i.ReadNtohU32 ();
ReadFrom (i, m_origin);
m_lifeTime = i.ReadNtohU32 ();
uint32_t dist = i.GetDistanceFrom (start);
NS_ASSERT (dist == GetSerializedSize ());
return dist;
}
void
RrepHeader::Print (std::ostream &os) const
{
os << "destination: ipv4 " << m_dst << "sequence number " << m_dstSeqNo;
if (m_prefixSize != 0)
os << "prefix size " << m_prefixSize << "\n";
else
os << "\n";
os << "source ipv4 " << m_origin << "\n" << "life time " << m_lifeTime
<< "\n" << "acknowledgment required flag " << (*this).GetAckRequired ()
<< "\n";
}
void
RrepHeader::SetLifeTime (Time t)
{
m_lifeTime = t.GetMilliSeconds ();
}
Time
RrepHeader::GetLifeTime () const
{
Time t (MilliSeconds (m_lifeTime));
return t;
}
void
RrepHeader::SetAckRequired (bool f)
{
if (f)
m_flags |= (1 << 6);
else
m_flags &= ~(1 << 6);
}
bool
RrepHeader::GetAckRequired () const
{
return (m_flags & (1 << 6));
}
void
RrepHeader::SetPrefixSize (uint8_t sz)
{
m_prefixSize = sz;
}
uint8_t
RrepHeader::GetPrefixSize () const
{
return m_prefixSize;
}
bool
RrepHeader::operator== (RrepHeader const & o) const
{
return (m_flags == o.m_flags && m_prefixSize == o.m_prefixSize &&
m_hopCount == o.m_hopCount && m_dst == o.m_dst && m_dstSeqNo == o.m_dstSeqNo &&
m_origin == o.m_origin && m_lifeTime == o.m_lifeTime);
}
void
RrepHeader::SetHello (Ipv4Address origin, uint32_t srcSeqNo, Time lifetime)
{
m_flags = 0;
m_prefixSize = 0;
m_hopCount = 0;
m_dst = origin;
m_dstSeqNo = srcSeqNo;
m_origin = origin;
m_lifeTime = lifetime.GetMilliSeconds ();
}
std::ostream &
operator<< (std::ostream & os, RrepHeader const & h)
{
h.Print (os);
return os;
}
//-----------------------------------------------------------------------------
// RREP-ACK
//-----------------------------------------------------------------------------
RrepAckHeader::RrepAckHeader () :
m_reserved (0)
{
}
TypeId
RrepAckHeader::GetInstanceTypeId () const
{
return TypeId ();
}
uint32_t
RrepAckHeader::GetSerializedSize () const
{
return 1;
}
void
RrepAckHeader::Serialize (Buffer::Iterator i ) const
{
i.WriteU8 (m_reserved);
}
uint32_t
RrepAckHeader::Deserialize (Buffer::Iterator start )
{
Buffer::Iterator i = start;
m_reserved = i.ReadU8 ();
uint32_t dist = i.GetDistanceFrom (start);
NS_ASSERT (dist == GetSerializedSize ());
return dist;
}
void
RrepAckHeader::Print (std::ostream &os ) const
{
}
bool
RrepAckHeader::operator== (RrepAckHeader const & o ) const
{
return m_reserved == o.m_reserved;
}
std::ostream &
operator<< (std::ostream & os, RrepAckHeader const & h )
{
h.Print (os);
return os;
}
//-----------------------------------------------------------------------------
// RERR
//-----------------------------------------------------------------------------
RerrHeader::RerrHeader () :
m_flag (0), m_reserved (0)
{
}
TypeId
RerrHeader::GetInstanceTypeId () const
{
return TypeId ();
}
uint32_t
RerrHeader::GetSerializedSize () const
{
return (3 + 8 * GetDestCount ());
}
void
RerrHeader::Serialize (Buffer::Iterator i ) const
{
i.WriteU8 (m_flag);
i.WriteU8 (m_reserved);
i.WriteU8 (GetDestCount ());
std::map<Ipv4Address, uint32_t>::const_iterator j;
for (j = m_unreachableDstSeqNo.begin (); j != m_unreachableDstSeqNo.end (); ++j)
{
WriteTo (i, (*j).first);
i.WriteHtonU32 ((*j).second);
}
}
uint32_t
RerrHeader::Deserialize (Buffer::Iterator start )
{
Buffer::Iterator i = start;
m_flag = i.ReadU8 ();
m_reserved = i.ReadU8 ();
uint8_t dest = i.ReadU8 ();
m_unreachableDstSeqNo.clear ();
Ipv4Address address;
uint32_t seqNo;
for (uint8_t k = 0; k < dest; ++k)
{
ReadFrom (i, address);
seqNo = i.ReadNtohU32 ();
m_unreachableDstSeqNo.insert (std::make_pair (address, seqNo));
}
uint32_t dist = i.GetDistanceFrom (start);
NS_ASSERT (dist == GetSerializedSize ());
return dist;
}
void
RerrHeader::Print (std::ostream &os ) const
{
os << "Unreachable destination (ipv4 address, seq. number):\n";
std::map<Ipv4Address, uint32_t>::const_iterator j;
for (j = m_unreachableDstSeqNo.begin (); j != m_unreachableDstSeqNo.end (); ++j)
{
os << (*j).first << ", " << (*j).second << "\n";
}
os << "No delete flag " << (*this).GetNoDelete () << "\n";
}
void
RerrHeader::SetNoDelete (bool f )
{
if (f)
m_flag |= (1 << 0);
else
m_flag &= ~(1 << 0);
}
bool
RerrHeader::GetNoDelete () const
{
return (m_flag & (1 << 0));
}
bool
RerrHeader::AddUnDestination (Ipv4Address dst, uint32_t seqNo )
{
if (m_unreachableDstSeqNo.find (dst) != m_unreachableDstSeqNo.end ())
return true;
NS_ASSERT (GetDestCount() < 255); // can't support more than 255 destinations in single RERR
m_unreachableDstSeqNo.insert (std::make_pair (dst, seqNo));
return true;
}
bool
RerrHeader::RemoveUnDestination (std::pair<Ipv4Address, uint32_t> & un )
{
if (m_unreachableDstSeqNo.empty ())
return false;
std::map<Ipv4Address, uint32_t>::iterator i = m_unreachableDstSeqNo.begin ();
un = *i;
m_unreachableDstSeqNo.erase (i);
return true;
}
void
RerrHeader::Clear ()
{
m_unreachableDstSeqNo.clear ();
m_flag = 0;
m_reserved = 0;
}
bool
RerrHeader::operator== (RerrHeader const & o ) const
{
if (m_flag != o.m_flag || m_reserved != o.m_reserved || GetDestCount () != o.GetDestCount ())
return false;
std::map<Ipv4Address, uint32_t>::const_iterator j = m_unreachableDstSeqNo.begin ();
std::map<Ipv4Address, uint32_t>::const_iterator k = o.m_unreachableDstSeqNo.begin ();
for (uint8_t i = 0; i < GetDestCount (); ++i)
{
if ((j->first != k->first) || (j->second != k->second))
return false;
j++;
k++;
}
return true;
}
std::ostream &
operator<< (std::ostream & os, RerrHeader const & h )
{
h.Print (os);
return os;
}
}
}

View File

@@ -0,0 +1,330 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AODVPACKET_H
#define AODVPACKET_H
#include <iostream>
#include "ns3/header.h"
#include "ns3/enum.h"
#include "ns3/ipv4-address.h"
#include <map>
#include "ns3/nstime.h"
namespace ns3 {
namespace aodv {
enum MessageType
{
AODVTYPE_RREQ = 1, //!< AODVTYPE_RREQ
AODVTYPE_RREP = 2, //!< AODVTYPE_RREP
AODVTYPE_RERR = 3, //!< AODVTYPE_RERR
AODVTYPE_RREP_ACK = 4 //!< AODVTYPE_RREP_ACK
};
/**
* \ingroup aodv
* \brief AODV types
*/
class TypeHeader : public Header
{
public:
/// c-tor
TypeHeader (MessageType t);
///\name Header serialization/deserialization
//\{
TypeId GetInstanceTypeId () const;
uint32_t GetSerializedSize () const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
//\}
/// Return type
MessageType Get () const { return m_type; }
/// Check that type if valid
bool IsValid () const { return m_valid; }
bool operator== (TypeHeader const & o) const;
private:
MessageType m_type;
bool m_valid;
};
std::ostream & operator<< (std::ostream & os, TypeHeader const & h);
/**
* \ingroup aodv
* \brief Route Request (RREQ) Message Format
\verbatim
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type |J|R|G|D|U| Reserved | Hop Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RREQ ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Originator IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Originator Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\endverbatim
*/
class RreqHeader : public Header
{
public:
/// c-tor
RreqHeader (uint8_t flags = 0, uint8_t reserved = 0, uint8_t hopCount = 0,
uint32_t requestID = 0, Ipv4Address dst = Ipv4Address (),
uint32_t dstSeqNo = 0, Ipv4Address origin = Ipv4Address (),
uint32_t originSeqNo = 0);
///\name Header serialization/deserialization
//\{
TypeId GetInstanceTypeId () const;
uint32_t GetSerializedSize () const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
//\}
///\name Fields
//\{
void SetHopCount (uint8_t count) { m_hopCount = count; }
uint8_t GetHopCount () const { return m_hopCount; }
void SetId (uint32_t id) { m_requestID = id; }
uint8_t GetId () const { return m_requestID; }
void SetDst (Ipv4Address a) { m_dst = a; }
Ipv4Address GetDst () const { return m_dst; }
void SetDstSeqno (uint32_t s) { m_dstSeqNo = s; }
uint32_t GetDstSeqno () const { return m_dstSeqNo; }
void SetOrigin (Ipv4Address a) { m_origin = a; }
Ipv4Address GetOrigin () const { return m_origin; }
void SetOriginSeqno (uint32_t s) { m_originSeqNo = s; }
uint32_t GetOriginSeqno () const { return m_originSeqNo; }
//\}
///\name Flags
//\{
void SetGratiousRrep (bool f);
bool GetGratiousRrep () const;
void SetDestinationOnly (bool f);
bool GetDestinationOnly () const;
void SetUnknownSeqno (bool f);
bool GetUnknownSeqno () const;
//\}
bool operator== (RreqHeader const & o) const;
private:
uint8_t m_flags; ///< |J|R|G|D|U| bit flags, see RFC
uint8_t m_reserved; ///< Not used
uint8_t m_hopCount; ///< Hop Count
uint32_t m_requestID; ///< RREQ ID
Ipv4Address m_dst; ///< Destination IP Address
uint32_t m_dstSeqNo; ///< Destination Sequence Number
Ipv4Address m_origin; ///< Originator IP Address
uint32_t m_originSeqNo; ///< Source Sequence Number
};
std::ostream & operator<< (std::ostream & os, RreqHeader const &);
/**
* \ingroup aodv
* \brief Route Reply (RREP) Message Format
\verbatim
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type |R|A| Reserved |Prefix Sz| Hop Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Originator IP address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Lifetime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\endverbatim
*/
class RrepHeader : public Header
{
public:
/// c-tor
RrepHeader (uint8_t prefixSize = 0, uint8_t hopCount = 0, Ipv4Address dst =
Ipv4Address (), uint32_t dstSeqNo = 0, Ipv4Address origin =
Ipv4Address (), Time lifetime = MilliSeconds (0));
///\name Header serialization/deserialization
//\{
TypeId GetInstanceTypeId () const;
uint32_t GetSerializedSize () const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
//\}
///\name Fields
//\{
void SetHopCount (uint8_t count) { m_hopCount = count; }
uint8_t GetHopCount () const { return m_hopCount; }
void SetDst (Ipv4Address a) { m_dst = a; }
Ipv4Address GetDst () const { return m_dst; }
void SetDstSeqno (uint32_t s) { m_dstSeqNo = s; }
uint32_t GetDstSeqno () const { return m_dstSeqNo; }
void SetOrigin (Ipv4Address a) { m_origin = a; }
Ipv4Address GetOrigin () const { return m_origin; }
void SetLifeTime (Time t);
Time GetLifeTime () const;
//\}
///\name Flags
//\{
void SetAckRequired (bool f);
bool GetAckRequired () const;
void SetPrefixSize (uint8_t sz);
uint8_t GetPrefixSize () const;
//\}
/// Configure RREP to be a Hello message
void SetHello (Ipv4Address src, uint32_t srcSeqNo, Time lifetime);
bool operator== (RrepHeader const & o) const;
private:
uint8_t m_flags; ///< A - acknowledgment required flag
uint8_t m_prefixSize; ///< Prefix Size
uint8_t m_hopCount; ///< Hop Count
Ipv4Address m_dst; ///< Destination IP Address
uint32_t m_dstSeqNo; ///< Destination Sequence Number
Ipv4Address m_origin; ///< Source IP Address
uint32_t m_lifeTime; ///< Lifetime (in milliseconds)
};
std::ostream & operator<< (std::ostream & os, RrepHeader const &);
/**
* \ingroup aodv
* \brief Route Reply Acknowledgment (RREP-ACK) Message Format
\verbatim
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\endverbatim
*/
class RrepAckHeader : public Header
{
public:
/// c-tor
RrepAckHeader ();
///\name Header serialization/deserialization
//\{
TypeId GetInstanceTypeId () const;
uint32_t GetSerializedSize () const;
void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
//\}
bool operator== (RrepAckHeader const & o) const;
private:
uint8_t m_reserved;
};
std::ostream & operator<< (std::ostream & os, RrepAckHeader const &);
/**
* \ingroup aodv
* \brief Route Error (RERR) Message Format
\verbatim
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type |N| Reserved | DestCount |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unreachable Destination IP Address (1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unreachable Destination Sequence Number (1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
| Additional Unreachable Destination IP Addresses (if needed) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Additional Unreachable Destination Sequence Numbers (if needed)|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\endverbatim
*/
class RerrHeader : public Header
{
public:
/// c-tor
RerrHeader ();
///\name Header serialization/deserialization
//\{
TypeId GetInstanceTypeId () const;
uint32_t GetSerializedSize () const;
void Serialize (Buffer::Iterator i) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
//\}
///\name No delete flag
//\{
void SetNoDelete (bool f);
bool GetNoDelete () const;
//\}
/**
* Add unreachable node address and its sequence number in RERR header
*\return false if we already added maximum possible number of unreachable destinations
*/
bool AddUnDestination (Ipv4Address dst, uint32_t seqNo);
/** Delete pair (address + sequence number) from REER header, if the number of unreachable destinations > 0
* \return true on success
*/
bool RemoveUnDestination (std::pair<Ipv4Address, uint32_t> & un);
/// Clear header
void Clear();
/// Return number of unreachable destinations in RERR message
uint8_t GetDestCount () const { return (uint8_t)m_unreachableDstSeqNo.size(); }
bool operator== (RerrHeader const & o) const;
private:
uint8_t m_flag; ///< No delete flag
uint8_t m_reserved; ///< Not used
/// List of Unreachable destination: IP addresses and sequence numbers
std::map<Ipv4Address, uint32_t> m_unreachableDstSeqNo;
};
std::ostream & operator<< (std::ostream & os, RerrHeader const &);
}
}
#endif /* AODVPACKET_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,254 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AODVROUTINGPROTOCOL_H
#define AODVROUTINGPROTOCOL_H
#include "aodv-rtable.h"
#include "aodv-rqueue.h"
#include "aodv-packet.h"
#include "aodv-neighbor.h"
#include "ns3/dpd.h"
#include "ns3/node.h"
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/ipv4-interface.h"
#include "ns3/ipv4-l3-protocol.h"
#include <map>
namespace ns3
{
namespace aodv
{
/**
* \ingroup aodv
*
* \brief AODV routing protocol
*/
class RoutingProtocol : public Ipv4RoutingProtocol
{
public:
static TypeId GetTypeId (void);
static const uint32_t AODV_PORT;
/// c-tor
RoutingProtocol ();
virtual ~RoutingProtocol();
virtual void DoDispose ();
///\name From Ipv4RoutingProtocol
//\{
Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
LocalDeliverCallback lcb, ErrorCallback ecb);
virtual void NotifyInterfaceUp (uint32_t interface);
virtual void NotifyInterfaceDown (uint32_t interface);
virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
virtual void SetIpv4 (Ptr<Ipv4> ipv4);
//\}
///\name Handle protocol parameters
//\{
bool GetDesinationOnlyFlag () const { return DestinationOnly; }
void SetDesinationOnlyFlag (bool f) { DestinationOnly = f; }
bool GetGratuitousReplyFlag () const { return GratuitousReply; }
void SetGratuitousReplyFlag (bool f) { GratuitousReply = f; }
void SetHelloEnable (bool f) { EnableHello = f; }
bool GetHelloEnable () const { return EnableHello; }
void SetBroadcastEnable (bool f) { EnableBroadcast = f; }
bool GetBroadcastEnable () const { return EnableBroadcast; }
//\}
private:
///\name Protocol parameters.
//\{
uint32_t RreqRetries; ///< Maximum number of retransmissions of RREQ with TTL = NetDiameter to discover a route
uint16_t RreqRateLimit; ///< Maximum number of RREQ per second.
Time ActiveRouteTimeout; ///< Period of time during which the route is considered to be valid.
uint32_t NetDiameter; ///< Net diameter measures the maximum possible number of hops between two nodes in the network
/**
* NodeTraversalTime is a conservative estimate of the average one hop traversal time for packets
* and should include queuing delays, interrupt processing times and transfer times.
*/
Time NodeTraversalTime;
Time NetTraversalTime; ///< Estimate of the average net traversal time.
Time PathDiscoveryTime; ///< Estimate of maximum time needed to find route in network.
Time MyRouteTimeout; ///< Value of lifetime field in RREP generating by this node.
/**
* Every HelloInterval the node checks whether it has sent a broadcast within the last HelloInterval.
* If it has not, it MAY broadcast a Hello message
*/
Time HelloInterval;
uint32_t AllowedHelloLoss; ///< Number of hello messages which may be loss for valid link
/**
* DeletePeriod is intended to provide an upper bound on the time for which an upstream node A
* can have a neighbor B as an active next hop for destination D, while B has invalidated the route to D.
*/
Time DeletePeriod;
Time NextHopWait; ///< Period of our waiting for the neighbour's RREP_ACK
/**
* The TimeoutBuffer is configurable. Its purpose is to provide a buffer for the timeout so that if the RREP is delayed
* due to congestion, a timeout is less likely to occur while the RREP is still en route back to the source.
*/
uint16_t TimeoutBuffer;
Time BlackListTimeout; ///< Time for which the node is put into the blacklist
uint32_t MaxQueueLen; ///< The maximum number of packets that we allow a routing protocol to buffer.
Time MaxQueueTime; ///< The maximum period of time that a routing protocol is allowed to buffer a packet for.
bool DestinationOnly; ///< Indicates only the destination may respond to this RREQ.
bool GratuitousReply; ///< Indicates whether a gratuitous RREP should be unicast to the node originated route discovery.
bool EnableHello; ///< Indicates whether a hello messages enable
bool EnableBroadcast; ///< Indicates whether a a broadcast data packets forwarding enable
//\}
/// IP protocol
Ptr<Ipv4> m_ipv4;
/// Raw socket per each IP interface, map socket -> iface address (IP + mask)
std::map< Ptr<Socket>, Ipv4InterfaceAddress > m_socketAddresses;
/// Routing table
RoutingTable m_routingTable;
/// A "drop-front" queue used by the routing layer to buffer packets to which it does not have a route.
RequestQueue m_queue;
/// Broadcast ID
uint32_t m_requestId;
/// Request sequence number
uint32_t m_seqNo;
/// Handle duplicated RREQ
dpd::IdCache m_rreqIdCache;
/// Handle duplicated broadcast/multicast packets
dpd::DuplicatePacketDetection m_dpd;
/// Handle neighbors
Neighbors m_nb;
/// Number of RREQs used for RREQ rate control
uint16_t m_rreqCount;
/// Unicast callback for own packets
UnicastForwardCallback m_scb;
/// Error callback for own packets
ErrorCallback m_ecb;
private:
/// Start protocol operation
void Start ();
/// If route exists and valid, forward packet.
bool Forwarding (Ptr<const Packet> p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb);
/**
* To reduce congestion in a network, repeated attempts by a source node at route discovery
* for a single destination MUST utilize a binary exponential backoff.
*/
void ScheduleRreqRetry (Ipv4Address dst);
/**
* Set lifetime field in routing table entry to the maximum of existing lifetime and lt, if the entry exists
* \param addr - destination address
* \param lt - proposed time for lifetime field in routing table entry for destination with address addr.
* \return true if route to destination address addr exist
*/
bool UpdateRouteLifeTime (Ipv4Address addr, Time lt);
/**
* Update neighbor record.
* \param receiver is supposed to be my interface
* \param sender is supposed to be IP address of my neighbor.
*/
void UpdateRouteToNeighbor (Ipv4Address sender, Ipv4Address receiver);
/// Check that packet is send from own interface
bool IsMyOwnAddress (Ipv4Address src);
/// Find socket with local interface address iface
Ptr<Socket> FindSocketWithInterfaceAddress (Ipv4InterfaceAddress iface) const;
/// Process hello message
void ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiverIfaceAddr);
///\name Receive control packets
//\{
/// Receive and process control packet
void RecvAodv (Ptr<Socket> socket);
/// Receive RREQ
void RecvRequest (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src);
/// Receive RREP
void RecvReply (Ptr<Packet> p, Ipv4Address my ,Ipv4Address src);
/// Receive RREP_ACK
void RecvReplyAck (Ipv4Address neighbor);
/// Receive RERR from node with address src
void RecvError (Ptr<Packet> p, Ipv4Address src);
//\}
///\name Send
//\{
/// Forward packet from route request queue
void SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route);
/// Aux. send helper
void Send (Ptr<Ipv4Route>, Ptr<const Packet>, const Ipv4Header &);
/// Send hello
void SendHello ();
/// Send RREQ
void SendRequest (Ipv4Address dst);
/// Send RREP
void SendReply (RreqHeader const & rreqHeader, RoutingTableEntry const & toOrigin);
/** Send RREP by intermediate node
* \param toDst routing table entry to destination
* \param toOrigin routing table entry to originator
* \param gratRep indicates whether a gratuitous RREP should be unicast to destination
*/
void SendReplyByIntermediateNode (RoutingTableEntry & toDst, RoutingTableEntry & toOrigin, bool gratRep);
/// Send RREP_ACK
void SendReplyAck (Ipv4Address neighbor);
/// Initiate RERR
void SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop);
/// Forward RERR
void SendRerrMessage(Ptr<Packet> packet, std::vector<Ipv4Address> precursors);
/**
* Send RERR message when no route to forward input packet. Unicast if there is reverse route to originating node, broadcast otherwise.
* \param dst - destination node IP address
* \param dstSeqNo - destination node sequence number
* \param origin - originating node IP address
*/
void SendRerrWhenNoRouteToForward (Ipv4Address dst, uint32_t dstSeqNo, Ipv4Address origin);
//\}
/// Notify that packet is dropped for some reason
void Drop(Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno);
/// Hello timer
Timer m_htimer;
/// Schedule next send of hello message
void HelloTimerExpire ();
/// RREQ rate limit timer
Timer m_rreqRateLimitTimer;
/// Reset RREQ count and schedule RREQ rate limit timer with delay 1 sec.
void RreqRateLimitTimerExpire ();
/// Map IP address + RREQ timer.
std::map<Ipv4Address, Timer> m_addressReqTimer;
/// Handle route discovery process
void RouteRequestTimerExpire (Ipv4Address dst);
/// Mark link to neighbor node as unidirectional for blacklistTimeout
void AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout);
};
}
}
#endif /* AODVROUTINGPROTOCOL_H */

View File

@@ -0,0 +1,151 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#include "aodv-rqueue.h"
#include <algorithm>
#include <functional>
#include "ns3/ipv4-route.h"
#include "ns3/socket.h"
#include "ns3/log.h"
NS_LOG_COMPONENT_DEFINE ("AodvRequestQueue");
namespace ns3
{
namespace aodv
{
uint32_t
RequestQueue::GetSize ()
{
Purge ();
return m_queue.size ();
}
bool
RequestQueue::Enqueue (QueueEntry & entry)
{
Purge ();
for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i
!= m_queue.end (); ++i)
{
if ((i->GetPacket ()->GetUid () == entry.GetPacket ()->GetUid ())
&& (i->GetIpv4Header ().GetDestination ()
== entry.GetIpv4Header ().GetDestination ()))
return false;
}
entry.SetExpireTime (m_queueTimeout);
if (m_queue.size () == m_maxLen)
{
Drop (m_queue.front (), "Drop the most aged packet"); // Drop the most aged packet
m_queue.erase (m_queue.begin ());
}
m_queue.push_back (entry);
return true;
}
void
RequestQueue::DropPacketWithDst (Ipv4Address dst)
{
NS_LOG_FUNCTION (this << dst);
Purge ();
const Ipv4Address addr = dst;
for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i
!= m_queue.end (); ++i)
{
if (IsEqual (*i, dst))
{
Drop (*i, "DropPacketWithDst ");
}
}
m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (),
std::bind2nd (std::ptr_fun (RequestQueue::IsEqual), dst)), m_queue.end ());
}
bool
RequestQueue::Dequeue (Ipv4Address dst, QueueEntry & entry)
{
Purge ();
for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i != m_queue.end (); ++i)
{
if (i->GetIpv4Header ().GetDestination () == dst)
{
entry = *i;
m_queue.erase (i);
return true;
}
}
return false;
}
bool
RequestQueue::Find (Ipv4Address dst)
{
for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i
!= m_queue.end (); ++i)
{
if (i->GetIpv4Header ().GetDestination () == dst)
return true;
}
return false;
}
struct IsExpired
{
bool
operator() (QueueEntry const & e) const
{
return (e.GetExpireTime () < Seconds (0));
}
};
void
RequestQueue::Purge ()
{
IsExpired pred;
for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i
!= m_queue.end (); ++i)
{
if (pred (*i))
{
Drop (*i, "Drop outdated packet ");
}
}
m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (), pred),
m_queue.end ());
}
void
RequestQueue::Drop (QueueEntry en, std::string reason)
{
NS_LOG_LOGIC (reason << en.GetPacket ()->GetUid () << " " << en.GetIpv4Header ().GetDestination ());
en.GetErrorCallback () (en.GetPacket (), en.GetIpv4Header (),
Socket::ERROR_NOROUTETOHOST);
return;
}
}
}

View File

@@ -0,0 +1,137 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AODV_RQUEUE_H
#define AODV_RQUEUE_H
#include <vector>
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/simulator.h"
namespace ns3 {
namespace aodv {
/**
* \ingroup aodv
* \brief AODV Queue Entry
*/
class QueueEntry
{
public:
typedef Ipv4RoutingProtocol::UnicastForwardCallback UnicastForwardCallback;
typedef Ipv4RoutingProtocol::ErrorCallback ErrorCallback;
/// c-tor
QueueEntry (Ptr<const Packet> pa = 0, Ipv4Header const & h = Ipv4Header (),
UnicastForwardCallback ucb = UnicastForwardCallback (),
ErrorCallback ecb = ErrorCallback (), Time exp = Simulator::Now ()) :
m_packet (pa), m_header (h), m_ucb (ucb), m_ecb (ecb),
m_expire (exp + Simulator::Now ())
{}
/**
* Compare queue entries
* \return true if equal
*/
bool operator== (QueueEntry const & o) const
{
return ((m_packet == o.m_packet) && (m_header.GetDestination () == o.m_header.GetDestination ()) && (m_expire == o.m_expire));
}
///\name Fields
//\{
UnicastForwardCallback GetUnicastForwardCallback () const { return m_ucb; }
void SetUnicastForwardCallback (UnicastForwardCallback ucb) { m_ucb = ucb; }
ErrorCallback GetErrorCallback () const { return m_ecb; }
void SetErrorCallback (ErrorCallback ecb) { m_ecb = ecb; }
Ptr<const Packet> GetPacket () const { return m_packet; }
void SetPacket (Ptr<const Packet> p) { m_packet = p; }
Ipv4Header GetIpv4Header() const { return m_header; }
void SetIpv4Header (Ipv4Header h) { m_header = h; }
void SetExpireTime (Time exp) { m_expire = exp + Simulator::Now(); }
Time GetExpireTime () const { return m_expire - Simulator::Now(); }
//\}
private:
/// Data packet
Ptr<const Packet> m_packet;
/// IP header
Ipv4Header m_header;
/// Unicast forward callback
UnicastForwardCallback m_ucb;
/// Error callback
ErrorCallback m_ecb;
/// Expire time for queue entry
Time m_expire;
};
/**
* \ingroup aodv
* \brief AODV route request queue
*
* Since AODV is an on demand routing we queue requests while looking for route.
*/
class RequestQueue
{
public:
/// Default c-tor
RequestQueue (uint32_t maxLen, Time routeToQueueTimeout) :
m_maxLen (maxLen), m_queueTimeout (routeToQueueTimeout)
{
}
/// Push entry in queue, if there is no entry with the same packet and destination address in queue.
bool Enqueue (QueueEntry & entry);
/// Return first found (the earliest) entry for given destination
bool Dequeue (Ipv4Address dst, QueueEntry & entry);
/// Remove all packets with destination IP address dst
void DropPacketWithDst (Ipv4Address dst);
/// Finds whether a packet with destination dst exists in the queue
bool Find (Ipv4Address dst);
/// Number of entries
uint32_t GetSize ();
///\name Fields
//\{
uint32_t GetMaxQueueLen () const { return m_maxLen; }
void SetMaxQueueLen (uint32_t len) { m_maxLen = len; }
Time GetQueueTimeout () const { return m_queueTimeout; }
void SetQueueTimeout (Time t) { m_queueTimeout = t; }
//\}
private:
std::vector<QueueEntry> m_queue;
/// Remove all expired entries
void Purge ();
/// Notify that packet is dropped from queue by timeout
void Drop (QueueEntry en, std::string reason);
/// The maximum number of packets that we allow a routing protocol to buffer.
uint32_t m_maxLen;
/// The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
Time m_queueTimeout;
static bool IsEqual (QueueEntry en, const Ipv4Address dst) { return (en.GetIpv4Header ().GetDestination () == dst); }
};
}}
#endif /* AODV_RQUEUE_H */

View File

@@ -0,0 +1,344 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#include "aodv-rtable.h"
#include <algorithm>
#include "ns3/simulator.h"
#include "ns3/log.h"
NS_LOG_COMPONENT_DEFINE ("AodvRoutingTable");
namespace ns3
{
namespace aodv
{
/*
The Routing Table
*/
RoutingTableEntry::RoutingTableEntry (Ptr<NetDevice> dev, Ipv4Address dst, bool vSeqNo, u_int32_t seqNo,
Ipv4InterfaceAddress iface, u_int16_t hops, Ipv4Address nextHop, Time lifetime) :
m_ackTimer (Timer::CANCEL_ON_DESTROY),
m_validSeqNo (vSeqNo), m_seqNo (seqNo), m_hops (hops),
m_lifeTime (lifetime + Simulator::Now ()), m_iface (iface), m_flag (VALID),
m_reqCount (0), m_blackListState (false), m_blackListTimeout (Simulator::Now ())
{
m_ipv4Route = Create<Ipv4Route> ();
m_ipv4Route->SetDestination (dst);
m_ipv4Route->SetGateway (nextHop);
m_ipv4Route->SetSource (m_iface.GetLocal ());
m_ipv4Route->SetOutputDevice (dev);
}
RoutingTableEntry::~RoutingTableEntry ()
{
}
bool
RoutingTableEntry::InsertPrecursor (Ipv4Address id)
{
if (!LookupPrecursor (id))
{
m_precursorList.push_back (id);
return true;
}
else
return false;
}
bool
RoutingTableEntry::LookupPrecursor (Ipv4Address id)
{
for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i
!= m_precursorList.end (); ++i)
{
if (*i == id)
return true;
}
return false;
}
bool
RoutingTableEntry::DeletePrecursor (Ipv4Address id)
{
std::vector<Ipv4Address>::iterator i = std::remove (m_precursorList.begin (),
m_precursorList.end (), id);
if (i == m_precursorList.end ())
return false;
else
m_precursorList.erase (i, m_precursorList.end ());
return true;
}
void
RoutingTableEntry::DeleteAllPrecursors ()
{
m_precursorList.clear ();
}
bool
RoutingTableEntry::IsPrecursorListEmpty () const
{
return m_precursorList.empty ();
}
void
RoutingTableEntry::GetPrecursors (std::vector<Ipv4Address> & prec) const
{
if (IsPrecursorListEmpty ())
return;
for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i
!= m_precursorList.end (); ++i)
{
bool result = true;
for (std::vector<Ipv4Address>::const_iterator j = prec.begin (); j
!= prec.end (); ++j)
{
if (*j == *i)
result = false;
}
if (result)
prec.push_back (*i);
}
}
void
RoutingTableEntry::Invalidate (Time badLinkLifetime)
{
if (m_flag == INVALID)
return;
m_flag = INVALID;
m_reqCount = 0;
m_lifeTime = badLinkLifetime + Simulator::Now ();
}
void
RoutingTableEntry::Print (std::ostream & os) const
{
os << m_ipv4Route->GetDestination () << "\t" << m_ipv4Route->GetGateway ()
<< "\t" << m_iface.GetLocal () << "\t";
switch (m_flag)
{
case VALID:
{
os << "UP";
break;
}
case INVALID:
{
os << "DOWN";
break;
}
case IN_SEARCH:
{
os << "IN_SEARCH";
break;
}
}
os << "\t" << (m_lifeTime - Simulator::Now ()).GetSeconds () << "\t"
<< m_hops << "\n";
}
/*
The Routing Table
*/
RoutingTable::RoutingTable (Time t) :
m_badLinkLifetime (t)
{
}
bool
RoutingTable::LookupRoute (Ipv4Address id, RoutingTableEntry & rt)
{
Purge ();
if (m_ipv4AddressEntry.empty ())
return false;
std::map<Ipv4Address, RoutingTableEntry>::const_iterator i =
m_ipv4AddressEntry.find (id);
if (i == m_ipv4AddressEntry.end ())
return false;
rt = i->second;
return true;
}
bool
RoutingTable::DeleteRoute (Ipv4Address dst)
{
Purge ();
if (m_ipv4AddressEntry.erase (dst) != 0)
return true;
return false;
}
bool
RoutingTable::AddRoute (RoutingTableEntry & rt)
{
if (rt.GetFlag () != IN_SEARCH)
rt.SetRreqCnt (0);
std::pair<std::map<Ipv4Address, RoutingTableEntry>::iterator, bool> result =
m_ipv4AddressEntry.insert (std::make_pair (rt.GetDestination (), rt));
return result.second;
}
bool
RoutingTable::Update (RoutingTableEntry & rt)
{
std::map<Ipv4Address, RoutingTableEntry>::iterator i =
m_ipv4AddressEntry.find (rt.GetDestination ());
if (i == m_ipv4AddressEntry.end ())
return false;
i->second = rt;
if (i->second.GetFlag () != IN_SEARCH)
i->second.SetRreqCnt (0);
return true;
}
bool
RoutingTable::SetEntryState (Ipv4Address id, RouteFlags state)
{
std::map<Ipv4Address, RoutingTableEntry>::iterator i =
m_ipv4AddressEntry.find (id);
if (i == m_ipv4AddressEntry.end ())
return false;
i->second.SetFlag (state);
i->second.SetRreqCnt (0);
return true;
}
void
RoutingTable::GetListOfDestinationWithNextHop (Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> & unreachable )
{
Purge ();
unreachable.clear ();
for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i =
m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
{
if (i->second.GetNextHop () == nextHop)
{
unreachable.insert (std::make_pair (i->first, i->second.GetSeqNo ()));
}
}
}
void
RoutingTable::InvalidateRoutesWithDst (const std::map<Ipv4Address, uint32_t> & unreachable)
{
Purge ();
for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
{
for (std::map<Ipv4Address, uint32_t>::const_iterator j =
unreachable.begin (); j != unreachable.end (); ++j)
{
if ((i->first == j->first) && (i->second.GetFlag () == VALID))
{
NS_LOG_LOGIC ("Invalidate route with destination address " << i->first);
i->second.Invalidate (m_badLinkLifetime);
}
}
}
}
void
RoutingTable::DeleteAllRoutesFromInterface (Ipv4InterfaceAddress iface)
{
if (m_ipv4AddressEntry.empty ())
return;
for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end ();)
{
if (i->second.GetInterface () == iface)
{
std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
++i;
m_ipv4AddressEntry.erase (tmp);
}
else
++i;
}
}
void
RoutingTable::Purge ()
{
if (m_ipv4AddressEntry.empty ())
return;
for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end ();)
{
if (i->second.GetLifeTime () < Seconds (0))
{
if (i->second.GetFlag () == INVALID)
{
std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
++i;
m_ipv4AddressEntry.erase (tmp);
}
else if (i->second.GetFlag () == VALID)
{
NS_LOG_LOGIC ("Invalidate route with destination address " << i->first);
i->second.Invalidate (m_badLinkLifetime);
++i;
}
else
++i;
}
++i;
}
}
bool
RoutingTable::MarkLinkAsUnidirectional (Ipv4Address neighbor, Time blacklistTimeout)
{
std::map<Ipv4Address, RoutingTableEntry>::iterator i =
m_ipv4AddressEntry.find (neighbor);
if (i == m_ipv4AddressEntry.end ())
return false;
i->second.SetUnidirectional (true);
i->second.SetBalcklistTimeout (blacklistTimeout);
i->second.SetRreqCnt (0);
return true;
}
void
RoutingTable::Print (std::ostream &os)
{
Purge ();
os << "\nAODV Routing table\n"
<< "Destination\tGateway\t\tInterface\tFlag\tExpire\tHops\n";
for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i =
m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
{
i->second.Print (os);
}
os << "\n";
}
}
}

View File

@@ -0,0 +1,252 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AODV_RTABLE_H
#define AODV_RTABLE_H
#include <cassert>
#include <map>
#include <sys/types.h>
#include "ns3/ipv4.h"
#include "ns3/ipv4-route.h"
#include "ns3/timer.h"
#include "ns3/net-device.h"
namespace ns3 {
namespace aodv {
/**
* \ingroup aodv
* \brief Route record states
*/
enum RouteFlags
{
VALID = 0, //!< VALID
INVALID = 1, //!< INVALID
IN_SEARCH = 2, //!< IN_SEARCH
};
/**
* \ingroup aodv
* \brief Routing table entry
*/
class RoutingTableEntry
{
public:
/// c-to
RoutingTableEntry (Ptr<NetDevice> dev = 0,Ipv4Address dst = Ipv4Address(), bool vSeqNo = false, u_int32_t m_seqNo = 0,
Ipv4InterfaceAddress iface = Ipv4InterfaceAddress(), u_int16_t hops = 0,
Ipv4Address nextHop = Ipv4Address(), Time lifetime = Simulator::Now());
~RoutingTableEntry ();
///\name Precursors management
//\{
/**
* Insert precursor in precursor list if it doesn't yet exist in the list
* \param id precursor address
* \return true on success
*/
bool InsertPrecursor (Ipv4Address id);
/**
* Lookup precursor by address
* \param id precursor address
* \return true on success
*/
bool LookupPrecursor (Ipv4Address id);
/**
* \brief Delete precursor
* \param id precursor address
* \return true on success
*/
bool DeletePrecursor (Ipv4Address id);
/// Delete all precursors
void DeleteAllPrecursors ();
/**
* Check that precursor list empty
* \return true if precursor list empty
*/
bool IsPrecursorListEmpty () const;
/**
* Inserts precursors in vector prec if they does not yet exist in vector
*/
void GetPrecursors (std::vector<Ipv4Address> & prec) const;
//\}
/// Mark entry as "down" (i.e. disable it)
void Invalidate (Time badLinkLifetime);
///\name Fields
//\{
Ipv4Address GetDestination () const { return m_ipv4Route->GetDestination(); }
Ptr<Ipv4Route> GetRoute () const { return m_ipv4Route; }
void SetRoute (Ptr<Ipv4Route> r) { m_ipv4Route = r; }
void SetNextHop (Ipv4Address nextHop) { m_ipv4Route->SetGateway(nextHop); }
Ipv4Address GetNextHop () const { return m_ipv4Route->GetGateway(); }
void SetOutputDevice (Ptr<NetDevice> dev) { m_ipv4Route->SetOutputDevice(dev); }
Ptr<NetDevice> GetOutputDevice () const { return m_ipv4Route->GetOutputDevice(); }
Ipv4InterfaceAddress GetInterface () const { return m_iface;}
void SetInterface (Ipv4InterfaceAddress iface) { m_iface = iface; }
void SetValidSeqNo (bool s) { m_validSeqNo = s; }
bool GetValidSeqNo () const { return m_validSeqNo; }
void SetSeqNo (uint32_t sn) { m_seqNo = sn; }
uint32_t GetSeqNo () const { return m_seqNo; }
void SetHop (uint16_t hop) { m_hops = hop; }
uint16_t GetHop () const {return m_hops; }
void SetLifeTime (Time lt) { m_lifeTime = lt + Simulator::Now(); }
Time GetLifeTime () const { return m_lifeTime - Simulator::Now(); }
void SetFlag (RouteFlags flag) { m_flag = flag; }
RouteFlags GetFlag () const { return m_flag; }
void SetRreqCnt (uint8_t n) { m_reqCount = n; }
uint8_t GetRreqCnt () const { return m_reqCount; }
void IncrementRreqCnt () { m_reqCount++; }
void SetUnidirectional (bool u) { m_blackListState = u; }
bool IsUnidirectional () const { return m_blackListState; }
void SetBalcklistTimeout (Time t) { m_blackListTimeout = t; }
Time GetBlacklistTimeout () const { return m_blackListTimeout; }
/// RREP_ACK timer
Timer m_ackTimer;
//\}
/**
* \brief Compare destination address
* \return true if equal
*/
bool operator== (Ipv4Address const dst) const
{
return (m_ipv4Route->GetDestination () == dst);
}
void Print(std::ostream & os) const;
private:
/// Valid Destination Sequence Number flag
bool m_validSeqNo;
/// Destination Sequence Number, if m_validSeqNo = true
uint32_t m_seqNo;
/// Hop Count (number of hops needed to reach destination)
uint16_t m_hops;
/**
* \brief Expiration or deletion time of the route
* Lifetime field in the routing table plays dual role --
* for an active route it is the expiration time, and for an invalid route
* it is the deletion time.
*/
Time m_lifeTime;
/** Ip route, include
* - destination address
* - source address
* - next hop address (gateway)
* - output device
*/
Ptr<Ipv4Route> m_ipv4Route;
/// Output interface address
Ipv4InterfaceAddress m_iface;
/// Routing flags: valid, invalid or in search
RouteFlags m_flag;
/// List of precursors
std::vector<Ipv4Address> m_precursorList;
/// When I can send another request
Time m_routeRequestTimout;
/// Number of route requests
uint8_t m_reqCount;
/// Indicate if this entry is in "blacklist"
bool m_blackListState;
/// Time for which the node is put into the blacklist
Time m_blackListTimeout;
};
/**
* \ingroup aodv
* \brief The Routing table used by AODV protocol
*/
class RoutingTable
{
public:
/// c-tor
RoutingTable (Time t);
///\name Handle life time of invalid route
//\{
Time GetBadLinkLifetime () const { return m_badLinkLifetime; }
void SetBadLinkLifetime (Time t) { m_badLinkLifetime = t; }
//\}
/**
* Add routing table entry if it doesn't yet exist in routing table
* \param r routing table entry
* \return true in success
*/
bool AddRoute (RoutingTableEntry & r);
/**
* Delete routing table entry with destination address dst, if it exists.
* \param dst destination address
* \return true on success
*/
bool DeleteRoute (Ipv4Address dst);
/**
* Lookup routing table entry with destination address dst
* \param dst destination address
* \param rt entry with destination address dst, if exists
* \return true on success
*/
bool LookupRoute (Ipv4Address dst, RoutingTableEntry & rt);
/// Update routing table
bool Update (RoutingTableEntry & rt);
/// Set routing table entry flags
bool SetEntryState (Ipv4Address dst, RouteFlags state);
/// Lookup routing entries with next hop Address dst and not empty list of precursors.
void GetListOfDestinationWithNextHop (Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> & unreachable);
/**
* Update routing entries with this destinations as follows:
* 1. The destination sequence number of this routing entry, if it
* exists and is valid, is incremented.
* 2. The entry is invalidated by marking the route entry as invalid
* 3. The Lifetime field is updated to current time plus DELETE_PERIOD.
*/
void InvalidateRoutesWithDst (std::map<Ipv4Address, uint32_t> const & unreachable);
/// Delete all route from interface with address iface
void DeleteAllRoutesFromInterface (Ipv4InterfaceAddress iface);
/// Delete all entries from routing table
void Clear () { m_ipv4AddressEntry.clear (); }
/// Delete all outdated entries and invalidate valid entry if Lifetime is expired
void Purge ();
/** Mark entry as unidirectional (e.g. add this neighbor to "blacklist" for blacklistTimeout period)
* \param neighbor - neighbor address link to which assumed to be unidirectional
* \param blacklistTimeout - time for which the neighboring node is put into the blacklist
* \return true on success
*/
bool MarkLinkAsUnidirectional(Ipv4Address neighbor, Time blacklistTimeout);
/// Print routing table
void Print(std::ostream &os);
private:
std::map<Ipv4Address, RoutingTableEntry> m_ipv4AddressEntry;
/// Deletion time for invalid routes
Time m_badLinkLifetime;
};
}}
#endif /* AODV_RTABLE_H */

View File

@@ -0,0 +1,554 @@
/* -*- 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
*
* Authors: Pavel Boyko <boyko@iitp.ru>
*/
#include "ns3/test.h"
#include "aodv-neighbor.h"
#include "aodv-packet.h"
#include "aodv-rqueue.h"
#include "aodv-rtable.h"
#include "ns3/ipv4-route.h"
namespace ns3
{
namespace aodv
{
/// Unit test for neighbors
struct NeighborTest : public TestCase
{
NeighborTest () : TestCase ("Neighbor"), neighbor (0) { }
virtual bool DoRun ();
void Handler (Ipv4Address addr);
void CheckTimeout1 ();
void CheckTimeout2 ();
void CheckTimeout3 ();
Neighbors * neighbor;
};
void
NeighborTest::Handler (Ipv4Address addr)
{
}
void
NeighborTest::CheckTimeout1 ()
{
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), true, "Neighbor exists");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), true, "Neighbor exists");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), true, "Neighbor exists");
}
void
NeighborTest::CheckTimeout2 ()
{
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), false, "Neighbor doesn't exist");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), false, "Neighbor doesn't exist");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), false, "Neighbor doesn't exist");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), true, "Neighbor exists");
}
void
NeighborTest::CheckTimeout3 ()
{
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), false, "Neighbor doesn't exist");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), false, "Neighbor doesn't exist");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), false, "Neighbor doesn't exist");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), false, "Neighbor doesn't exist");
}
bool
NeighborTest::DoRun ()
{
Neighbors nb (Seconds (1));
neighbor = &nb;
neighbor->SetCallback (MakeCallback (&NeighborTest::Handler, this));
neighbor->Update (Ipv4Address ("1.2.3.4"), Seconds (1));
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists");
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("4.3.2.1")), false, "Neighbor doesn't exist");
neighbor->Update (Ipv4Address ("1.2.3.4"), Seconds (10));
NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists");
NS_TEST_EXPECT_MSG_EQ (neighbor->GetExpireTime (Ipv4Address ("1.2.3.4")), Seconds (10), "Known expire time");
NS_TEST_EXPECT_MSG_EQ (neighbor->GetExpireTime (Ipv4Address ("4.3.2.1")), Seconds (0), "Known expire time");
neighbor->Update (Ipv4Address ("1.1.1.1"), Seconds (5));
neighbor->Update (Ipv4Address ("2.2.2.2"), Seconds (10));
neighbor->Update (Ipv4Address ("3.3.3.3"), Seconds (20));
Simulator::Schedule (Seconds (2), &NeighborTest::CheckTimeout1, this);
Simulator::Schedule (Seconds (15), &NeighborTest::CheckTimeout2, this);
Simulator::Schedule (Seconds (30), &NeighborTest::CheckTimeout3, this);
Simulator::Run ();
Simulator::Destroy ();
return GetErrorStatus ();
}
//-----------------------------------------------------------------------------
struct TypeHeaderTest : public TestCase
{
TypeHeaderTest () : TestCase ("AODV TypeHeader")
{
}
virtual bool DoRun ()
{
TypeHeader h (AODVTYPE_RREQ);
NS_TEST_EXPECT_MSG_EQ (h.IsValid (), true, "Default header is valid");
NS_TEST_EXPECT_MSG_EQ (h.Get (), AODVTYPE_RREQ, "Default header is RREQ");
Ptr<Packet> p = Create<Packet> ();
p->AddHeader (h);
TypeHeader h2 (AODVTYPE_RREP);
uint32_t bytes = p->RemoveHeader (h2);
NS_TEST_EXPECT_MSG_EQ (bytes, 1, "Type header is 1 byte long");
NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
return GetErrorStatus ();
}
};
//-----------------------------------------------------------------------------
/// Unit test for RREQ
struct RreqHeaderTest : public TestCase
{
RreqHeaderTest () : TestCase ("AODV RREQ")
{
}
virtual bool DoRun ()
{
RreqHeader h (/*flags*/0, /*reserved*/0, /*hopCount*/6, /*requestID*/1, /*dst*/Ipv4Address ("1.2.3.4"),
/*dstSeqNo*/40, /*origin*/Ipv4Address ("4.3.2.1"), /*originSeqNo*/10);
NS_TEST_EXPECT_MSG_EQ (h.GetGratiousRrep (), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetDestinationOnly (), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 6, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetId (), 1, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.2.3.4"), "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 40, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.3.2.1"), "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetOriginSeqno (), 10, "trivial");
h.SetGratiousRrep (true);
NS_TEST_EXPECT_MSG_EQ (h.GetGratiousRrep (), true, "trivial");
h.SetDestinationOnly (true);
NS_TEST_EXPECT_MSG_EQ (h.GetDestinationOnly (), true, "trivial");
h.SetUnknownSeqno (true);
NS_TEST_EXPECT_MSG_EQ (h.GetUnknownSeqno (), true, "trivial");
h.SetDst (Ipv4Address ("1.1.1.1"));
NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.1.1.1"), "trivial");
h.SetDstSeqno (5);
NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 5, "trivial");
h.SetHopCount (7);
NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 7, "trivial");
h.SetId (55);
NS_TEST_EXPECT_MSG_EQ (h.GetId (), 55, "trivial");
h.SetOrigin (Ipv4Address ("4.4.4.4"));
NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.4.4.4"), "trivial");
h.SetOriginSeqno (23);
NS_TEST_EXPECT_MSG_EQ (h.GetOriginSeqno (), 23, "trivial");
Ptr<Packet> p = Create<Packet> ();
p->AddHeader (h);
RreqHeader h2;
uint32_t bytes = p->RemoveHeader (h2);
NS_TEST_EXPECT_MSG_EQ (bytes, 23, "RREP is 23 bytes long");
NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
return GetErrorStatus ();
}
};
//-----------------------------------------------------------------------------
/// Unit test for RREP
struct RrepHeaderTest : public TestCase
{
RrepHeaderTest () : TestCase ("AODV RREP") {}
virtual bool DoRun ()
{
RrepHeader h (/*prefixSize*/0, /*hopCount*/12, /*dst*/Ipv4Address ("1.2.3.4"), /*dstSeqNo*/2,
/*origin*/Ipv4Address ("4.3.2.1"), /*lifetime*/Seconds (3));
NS_TEST_EXPECT_MSG_EQ (h.GetPrefixSize (), 0, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 12, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.2.3.4"), "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 2, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.3.2.1"), "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), Seconds (3), "trivial");
h.SetDst (Ipv4Address ("1.1.1.1"));
NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.1.1.1"), "trivial");
h.SetDstSeqno (123);
NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 123, "trivial");
h.SetOrigin (Ipv4Address ("4.4.4.4"));
NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.4.4.4"), "trivial");
h.SetLifeTime (MilliSeconds (1200));
NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), MilliSeconds (1200), "trivial");
h.SetAckRequired (true);
NS_TEST_EXPECT_MSG_EQ (h.GetAckRequired (), true, "trivial");
h.SetAckRequired (false);
NS_TEST_EXPECT_MSG_EQ (h.GetAckRequired (), false, "trivial");
h.SetPrefixSize (2);
NS_TEST_EXPECT_MSG_EQ (h.GetPrefixSize (), 2, "trivial");
h.SetHopCount (15);
NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 15, "trivial");
h.SetHello (Ipv4Address ("10.0.0.2"), 9, Seconds (15));
NS_TEST_EXPECT_MSG_EQ (h.GetDst (), h.GetOrigin (), "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 9, "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), Seconds (15), "trivial");
Ptr<Packet> p = Create<Packet> ();
p->AddHeader (h);
RrepHeader h2;
uint32_t bytes = p->RemoveHeader (h2);
NS_TEST_EXPECT_MSG_EQ (bytes, 19, "RREP is 19 bytes long");
NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
return GetErrorStatus ();
}
};
//-----------------------------------------------------------------------------
/// Unit test for RREP-ACK
struct RrepAckHeaderTest : public TestCase
{
RrepAckHeaderTest () : TestCase ("AODV RREP-ACK")
{
}
virtual bool DoRun()
{
RrepAckHeader h;
Ptr<Packet> p = Create<Packet> ();
p->AddHeader (h);
RrepAckHeader h2;
uint32_t bytes = p->RemoveHeader(h2);
NS_TEST_EXPECT_MSG_EQ (bytes, 1, "ACK is 1 byte long");
NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
return GetErrorStatus ();
}
};
//-----------------------------------------------------------------------------
/// Unit test for RERR
struct RerrHeaderTest : public TestCase
{
RerrHeaderTest () : TestCase ("AODV RERR")
{
}
virtual bool DoRun()
{
RerrHeader h;
h.SetNoDelete(true);
NS_TEST_EXPECT_MSG_EQ(h.GetNoDelete(), true, "trivial");
Ipv4Address dst = Ipv4Address("1.2.3.4");
NS_TEST_EXPECT_MSG_EQ(h.AddUnDestination(dst, 12), true, "trivial");
NS_TEST_EXPECT_MSG_EQ(h.GetDestCount(), 1, "trivial");
NS_TEST_EXPECT_MSG_EQ(h.AddUnDestination(dst, 13), true, "trivial");
Ipv4Address dst2 = Ipv4Address("4.3.2.1");
NS_TEST_EXPECT_MSG_EQ(h.AddUnDestination(dst2, 12), true, "trivial");
NS_TEST_EXPECT_MSG_EQ(h.GetDestCount(), 2, "trivial");
Ptr<Packet> p = Create<Packet> ();
p->AddHeader (h);
RerrHeader h2;
uint32_t bytes = p->RemoveHeader(h2);
NS_TEST_EXPECT_MSG_EQ (bytes, h.GetSerializedSize(), "(De)Serialized size match");
NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
return GetErrorStatus ();
}
};
//-----------------------------------------------------------------------------
/// Unit test for AODV routing table entry
struct QueueEntryTest : public TestCase
{
QueueEntryTest () : TestCase ("QueueEntry") {}
void Unicast (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) {}
void Error (Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno) {}
void Unicast2 (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) {}
void Error2 (Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno) {}
virtual bool DoRun()
{
Ptr<const Packet> packet = Create<Packet> ();
Ipv4Header h;
h.SetDestination (Ipv4Address ("1.2.3.4"));
h.SetSource (Ipv4Address ("4.3.2.1"));
Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&QueueEntryTest::Unicast, this);
Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&QueueEntryTest::Error, this);
QueueEntry entry (packet, h, ucb, ecb, Seconds (1));
NS_TEST_EXPECT_MSG_EQ (h.GetDestination (), entry.GetIpv4Header ().GetDestination (), "trivial");
NS_TEST_EXPECT_MSG_EQ (h.GetSource (), entry.GetIpv4Header ().GetSource (), "trivial");
NS_TEST_EXPECT_MSG_EQ (ucb.IsEqual(entry.GetUnicastForwardCallback ()), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (ecb.IsEqual(entry.GetErrorCallback ()), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (1), "trivial");
NS_TEST_EXPECT_MSG_EQ (entry.GetPacket (), packet, "trivial");
entry.SetExpireTime (Seconds (3));
NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (3), "trivial");
Ipv4Header h2;
h2.SetDestination(Ipv4Address ("1.1.1.1"));
entry.SetIpv4Header (h2);
NS_TEST_EXPECT_MSG_EQ (entry.GetIpv4Header ().GetDestination (), Ipv4Address ("1.1.1.1"), "trivial");
Ipv4RoutingProtocol::UnicastForwardCallback ucb2 = MakeCallback (&QueueEntryTest::Unicast2, this);
Ipv4RoutingProtocol::ErrorCallback ecb2 = MakeCallback (&QueueEntryTest::Error2, this);
entry.SetErrorCallback (ecb2);
NS_TEST_EXPECT_MSG_EQ (ecb2.IsEqual (entry.GetErrorCallback ()), true, "trivial");
entry.SetUnicastForwardCallback (ucb2);
NS_TEST_EXPECT_MSG_EQ (ucb2.IsEqual (entry.GetUnicastForwardCallback ()), true, "trivial");
return GetErrorStatus();
}
};
//-----------------------------------------------------------------------------
/// Unit test for RequestQueue
struct AodvRqueueTest : public TestCase
{
AodvRqueueTest () : TestCase ("Rqueue"), q (64, Seconds (30)) {}
virtual bool DoRun ();
void Unicast (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) {}
void Error (Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno) {}
void CheckSizeLimit ();
void CheckTimeout ();
RequestQueue q;
};
bool
AodvRqueueTest::DoRun ()
{
NS_TEST_EXPECT_MSG_EQ (q.GetMaxQueueLen (), 64, "trivial");
q.SetMaxQueueLen (32);
NS_TEST_EXPECT_MSG_EQ (q.GetMaxQueueLen (), 32, "trivial");
NS_TEST_EXPECT_MSG_EQ (q.GetQueueTimeout (), Seconds (30), "trivial");
q.SetQueueTimeout (Seconds(10));
NS_TEST_EXPECT_MSG_EQ (q.GetQueueTimeout (), Seconds (10), "trivial");
Ptr<const Packet> packet = Create<Packet> ();
Ipv4Header h;
h.SetDestination (Ipv4Address ("1.2.3.4"));
h.SetSource (Ipv4Address ("4.3.2.1"));
Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&AodvRqueueTest::Unicast, this);
Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&AodvRqueueTest::Error, this);
QueueEntry e1 (packet, h, ucb, ecb, Seconds (1));
q.Enqueue (e1);
q.Enqueue (e1);
q.Enqueue (e1);
NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.2.3.4")), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.1.1.1")), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 1, "trivial");
q.DropPacketWithDst (Ipv4Address ("1.2.3.4"));
NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.2.3.4")), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "trivial");
h.SetDestination (Ipv4Address ("2.2.2.2"));
QueueEntry e2 (packet, h, ucb, ecb, Seconds (1));
q.Enqueue (e1);
q.Enqueue (e2);
Ptr<Packet> packet2 = Create<Packet> ();
QueueEntry e3 (packet2, h, ucb, ecb, Seconds (1));
NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address("3.3.3.3"), e3), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address ("2.2.2.2"), e3), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("2.2.2.2")), false, "trivial");
q.Enqueue (e2);
q.Enqueue (e3);
NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
Ptr<Packet> packet4 = Create<Packet> ();
h.SetDestination (Ipv4Address ("1.2.3.4"));
QueueEntry e4 (packet4, h, ucb, ecb, Seconds (20));
q.Enqueue (e4);
NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 3, "trivial");
q.DropPacketWithDst (Ipv4Address ("1.2.3.4"));
NS_TEST_EXPECT_MSG_EQ (q.GetSize(), 1, "trivial");
CheckSizeLimit ();
Ipv4Header header2;
Ipv4Address dst2 ("1.2.3.4");
header2.SetDestination (dst2);
Simulator::Schedule (q.GetQueueTimeout () + Seconds (1), &AodvRqueueTest::CheckTimeout, this);
Simulator::Run ();
Simulator::Destroy ();
return GetErrorStatus ();
}
void
AodvRqueueTest::CheckSizeLimit ()
{
Ptr<Packet> packet = Create<Packet> ();
Ipv4Header header;
Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&AodvRqueueTest::Unicast, this);
Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&AodvRqueueTest::Error, this);
QueueEntry e1 (packet, header, ucb, ecb, Seconds (1));
for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i)
q.Enqueue (e1);
NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i)
q.Enqueue (e1);
NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
}
void
AodvRqueueTest::CheckTimeout ()
{
NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "Must be empty now");
}
//-----------------------------------------------------------------------------
/// Unit test for AODV routing table entry
struct AodvRtableEntryTest : public TestCase
{
AodvRtableEntryTest () : TestCase ("RtableEntry") {}
virtual bool DoRun()
{
Ptr<NetDevice> dev;
Ipv4InterfaceAddress iface;
RoutingTableEntry rt (/*output device*/dev, /*dst*/Ipv4Address("1.2.3.4"), /*validSeqNo*/true, /*seqNo*/10,
/*interface*/iface, /*hop*/5, /*next hop*/Ipv4Address("3.3.3.3"), /*lifetime*/Seconds(10));
NS_TEST_EXPECT_MSG_EQ (rt.GetOutputDevice (), dev, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetDestination (), Ipv4Address ("1.2.3.4"), "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetValidSeqNo (), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetSeqNo (), 10, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetInterface (), iface, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetHop (), 5, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetNextHop (), Ipv4Address ("3.3.3.3"), "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (10), "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), VALID, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 0, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), true, "trivial");
Ptr<NetDevice> dev2;
Ipv4InterfaceAddress iface2;
rt.SetOutputDevice (dev2);
NS_TEST_EXPECT_MSG_EQ (rt.GetOutputDevice (), dev2, "trivial");
rt.SetInterface (iface2);
NS_TEST_EXPECT_MSG_EQ (rt.GetInterface (), iface2, "trivial");
rt.SetValidSeqNo (false);
NS_TEST_EXPECT_MSG_EQ (rt.GetValidSeqNo (), false, "trivial");
rt.SetFlag (INVALID);
NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial");
rt.SetFlag (IN_SEARCH);
NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), IN_SEARCH, "trivial");
rt.SetHop (12);
NS_TEST_EXPECT_MSG_EQ (rt.GetHop (), 12, "trivial");
rt.SetLifeTime (Seconds (1));
NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (1), "trivial");
rt.SetNextHop (Ipv4Address ("1.1.1.1"));
NS_TEST_EXPECT_MSG_EQ (rt.GetNextHop (), Ipv4Address ("1.1.1.1"), "trivial");
rt.SetUnidirectional (true);
NS_TEST_EXPECT_MSG_EQ (rt.IsUnidirectional (), true, "trivial");
rt.SetBalcklistTimeout (Seconds (7));
NS_TEST_EXPECT_MSG_EQ (rt.GetBlacklistTimeout (), Seconds (7), "trivial");
rt.SetRreqCnt (2);
NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 2, "trivial");
rt.IncrementRreqCnt ();
NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 3, "trivial");
rt.Invalidate (Seconds (13));
NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (13), "trivial");
rt.SetLifeTime (Seconds (0.1));
NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (0.1), "trivial");
Ptr<Ipv4Route> route = rt.GetRoute ();
NS_TEST_EXPECT_MSG_EQ (route->GetDestination (), Ipv4Address ("1.2.3.4"), "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.1")), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.2")), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.2")), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.3")), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.1")), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.DeletePrecursor (Ipv4Address ("10.0.0.2")), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.2")), false, "trivial");
std::vector<Ipv4Address> prec;
rt.GetPrecursors (prec);
NS_TEST_EXPECT_MSG_EQ (prec.size (), 1, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.4")), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.DeletePrecursor (Ipv4Address ("10.0.0.5")), false, "trivial");
rt.GetPrecursors (prec);
NS_TEST_EXPECT_MSG_EQ (prec.size (), 2, "trivial");
rt.DeleteAllPrecursors ();
NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), true, "trivial");
rt.GetPrecursors (prec);
NS_TEST_EXPECT_MSG_EQ (prec.size (), 2, "trivial");
return GetErrorStatus ();
}
};
//-----------------------------------------------------------------------------
/// Unit test for AODV routing table
struct AodvRtableTest : public TestCase
{
AodvRtableTest () : TestCase ("Rtable") {}
virtual bool DoRun()
{
RoutingTable rtable (Seconds (2));
NS_TEST_EXPECT_MSG_EQ (rtable.GetBadLinkLifetime (), Seconds (2), "trivial");
rtable.SetBadLinkLifetime (Seconds (1));
NS_TEST_EXPECT_MSG_EQ (rtable.GetBadLinkLifetime (), Seconds (1), "trivial");
Ptr<NetDevice> dev;
Ipv4InterfaceAddress iface;
RoutingTableEntry rt (/*output device*/dev, /*dst*/Ipv4Address("1.2.3.4"), /*validSeqNo*/true, /*seqNo*/10,
/*interface*/iface, /*hop*/5, /*next hop*/Ipv4Address("1.1.1.1"), /*lifetime*/Seconds(10));
NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt), false, "trivial");
RoutingTableEntry rt2 (/*output device*/dev, /*dst*/Ipv4Address("4.3.2.1"), /*validSeqNo*/false, /*seqNo*/0,
/*interface*/iface, /*hop*/15, /*next hop*/Ipv4Address("1.1.1.1"), /*lifetime*/Seconds(1));
NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt2), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (rt2.GetDestination (), rt), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt2.GetDestination (), rt.GetDestination (), "trivial");
rt.SetHop (20);
rt.InsertPrecursor (Ipv4Address ("10.0.0.3"));
NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt), true, "trivial");
RoutingTableEntry rt3;
NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("10.0.0.1"), rt), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt3), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("10.0.0.1"), INVALID), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("1.2.3.4"), IN_SEARCH), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("5.5.5.5")), false, "trivial");
RoutingTableEntry rt4 (/*output device*/dev, /*dst*/Ipv4Address ("5.5.5.5"), /*validSeqNo*/false, /*seqNo*/0,
/*interface*/iface, /*hop*/15, /*next hop*/Ipv4Address ("1.1.1.1"), /*lifetime*/Seconds (-10));
NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt4), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("5.5.5.5"), INVALID), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("5.5.5.5"), rt), false, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.MarkLinkAsUnidirectional (Ipv4Address ("1.2.3.4"), Seconds (2)), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("1.2.3.4"), rt), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.IsUnidirectional (), true, "trivial");
rt.SetLifeTime (Seconds (-5));
NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt), true, "trivial");
std::map<Ipv4Address, uint32_t> unreachable;
rtable.GetListOfDestinationWithNextHop (Ipv4Address ("1.1.1.1"), unreachable);
NS_TEST_EXPECT_MSG_EQ (unreachable.size (), 2, "trivial");
unreachable.insert (std::make_pair (Ipv4Address ("4.3.2.1"), 3));
rtable.InvalidateRoutesWithDst (unreachable);
NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("4.3.2.1"), rt), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("1.2.3.4")), true, "trivial");
NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("1.2.3.4")), false, "trivial");
return GetErrorStatus ();
}
};
//-----------------------------------------------------------------------------
class AodvTestSuite : public TestSuite
{
public:
AodvTestSuite () : TestSuite ("routing-aodv", UNIT)
{
AddTestCase (new NeighborTest);
AddTestCase (new TypeHeaderTest);
AddTestCase (new RreqHeaderTest);
AddTestCase (new RrepHeaderTest);
AddTestCase (new RrepAckHeaderTest);
AddTestCase (new RerrHeaderTest);
AddTestCase (new QueueEntryTest);
AddTestCase (new AodvRqueueTest);
AddTestCase (new AodvRtableEntryTest);
AddTestCase (new AodvRtableTest);
}
} g_aodvTestSuite;
}}

View File

@@ -0,0 +1,86 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AODV_H
#define AODV_H
/**
* \ingroup routing
* \defgroup aodv AODV
*
* This model implements the base specification of the Ad hoc on demand distance vector (AODV)
* protocol. Implementation is based on RFC3561.
*
* Class aodv::RoutingProtocol implements all functionality of service packet exchange and inherits Ipv4RoutingProtocol.
* Base class defines two virtual functions for packet routing and forwarding. The first one,
* RouteOutput(), is used for locally originated packets, and the second one, RouteInput(), is used for forwarding
* and/or delivering received packets.
*
* Protocol operation depends on the many adjustable parameters. Parameters for this functionality are attributes of
* aodv::RoutingProtocol. We support parameters, with their default values, from RFC and parameters that enable/disable
* protocol features, such as broadcasting HELLO messages, broadcasting data packets and so on.
*
* AODV discovers routes on demand. Therefore, our AODV model buffer all packets, while a route request packet (RREQ)
* is disseminated. We implement a packet queue in aodv-rqueue.cc. Smart pointer to packet, Ipv4RoutingProtocol::ErrorCallback,
* Ipv4RoutingProtocol::UnicastForwardCallback and IP header are stored in this queue. The packet queue implements garbage collection of old
* packets and a queue size limit.
*
* Routing table implementation support garbage collection of old entries and state machine, defined in standard.
* It implements as a STL map container. The key is a destination IP address.
*
* Some moments of protocol operation aren't described in RFC. This moments generally concern cooperation of different OSI model layers.
* We use following heuristics:
*
* 1) This AODV implementation can detect the presence of unidirectional links and avoid them if necessary.
* If the node we received a RREQ for is a neighbor we are probably facing a unidirectional link...
* This heuristic is taken from AODV-UU implementation and can be disabled.
*
* 2) Protocol operation strongly depends on broken link detection mechanism. We implements two such heuristics.
* First, this implementation support HELLO messages. However HELLO messages are not a good way to do neighbor sensing
* in a wireless environment (at least not over 802.11). Therefore, you may experience bad performance when running over wireless.
* There are several reasons for this:
* -# HELLO messages are broadcasted. In 802.11, broadcasting is done at a lower bit rate than unicasting,
* thus HELLO messages travel further than data.
* -# HELLO messages are small, thus less prone to bit errors than data transmissions.
* -# Broadcast transmissions are not guaranteed to be bidirectional, unlike unicast transmissions.
* Second, we use layer 2 feedback when possible. Link considered to be broken, if frame transmission results in a transmission
* failure for all retries. This mechanism meant for active links and work much more faster, than first method.
* Layer 2 feedback implementation relies on TxErrHeader trace source, currently it is supported in AdhocWifiMac only.
*
* 3) Duplicate packet detection. We use special class dpd::DuplicatePacketDetection for this purpose.
*
* Following optional protocol optimizations aren't implemented:
* - Expanding ring search.
* - Local link repair.
* - RREP, RREQ and HELLO message extensions.
* This techniques require direct access to IP header, which contradict assertion from AODV RFC that AODV works over UDP. Our model use UDP
* for simplicity, but this disable us to implement protocol optimizations. We don't use low layer raw socket, because they are not portable.
*
*/
#endif /* AODV_H */

View File

@@ -0,0 +1,171 @@
/* -*- 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
*
* Authors: Pavel Boyko <boyko@iitp.ru>
*/
#include "aodv-regression.h"
#include "ns3/mesh-helper.h"
#include "ns3/simulator.h"
#include "ns3/random-variable.h"
#include "ns3/mobility-helper.h"
#include "ns3/double.h"
#include "ns3/uinteger.h"
#include "ns3/string.h"
#include "ns3/boolean.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/abort.h"
#include "ns3/udp-echo-helper.h"
#include "ns3/mobility-model.h"
#include "ns3/pcap-file.h"
#include "ns3/aodv-helper.h"
#include "ns3/v4ping-helper.h"
#include "ns3/nqos-wifi-mac-helper.h"
#include <sstream>
/// Set to true to rewrite reference traces, leave false to run regression tests
const bool WRITE_VECTORS = false;
namespace ns3 {
namespace aodv {
//-----------------------------------------------------------------------------
// Test suite
//-----------------------------------------------------------------------------
class AodvRegressionTestSuite : public TestSuite
{
public:
AodvRegressionTestSuite () : TestSuite ("routing-aodv-regression", SYSTEM)
{
AddTestCase (new ChainRegressionTest);
}
} g_aodvRegressionTestSuite;
//-----------------------------------------------------------------------------
// ChainRegressionTest
//-----------------------------------------------------------------------------
/// Unique PCAP files prefix for this test
const char * const ChainRegressionTest::PREFIX = "aodv-chain-regression-test";
ChainRegressionTest::ChainRegressionTest () : TestCase ("AODV chain regression test"),
m_nodes (0),
m_time (Seconds (10)),
m_size (5),
m_step (120)
{
}
ChainRegressionTest::~ChainRegressionTest ()
{
delete m_nodes;
}
bool
ChainRegressionTest::DoRun ()
{
SeedManager::SetSeed(12345);
CreateNodes ();
CreateDevices ();
// At m_time / 3 move central node away and see what will happen
Ptr<Node> node = m_nodes->Get (m_size / 2);
Ptr<MobilityModel> mob = node->GetObject<MobilityModel> ();
Simulator::Schedule (m_time / Scalar(3.0), &MobilityModel::SetPosition, mob, Vector (1e5, 1e5, 1e5));
Simulator::Stop (m_time);
Simulator::Run ();
Simulator::Destroy ();
if (!WRITE_VECTORS) CheckResults ();
delete m_nodes, m_nodes = 0;
return GetErrorStatus ();
}
void
ChainRegressionTest::CreateNodes ()
{
m_nodes = new NodeContainer;
m_nodes->Create (m_size);
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (m_step),
"DeltaY", DoubleValue (0),
"GridWidth", UintegerValue (m_size),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (*m_nodes);
}
void
ChainRegressionTest::CreateDevices ()
{
// 1. Setup WiFi
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", StringValue ("2200"));
NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, *m_nodes);
// 2. Setup TCP/IP & AODV
AodvHelper aodv; // Use default parameters here
InternetStackHelper internetStack;
internetStack.SetRoutingHelper (aodv);
internetStack.Install (*m_nodes);
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = address.Assign (devices);
// 3. Setup ping
V4PingHelper ping (interfaces.GetAddress (m_size - 1));
ping.SetAttribute ("Verbose", BooleanValue (false)); // don't need verbose ping in regression test
ApplicationContainer p = ping.Install (m_nodes->Get (0));
p.Start (Seconds (0));
p.Stop (m_time);
// 4. write PCAP
std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + PREFIX;
wifiPhy.EnablePcapAll (prefix);
}
void
ChainRegressionTest::CheckResults ()
{
for (uint32_t i = 0; i < m_size; ++i)
{
std::ostringstream os1, os2;
// File naming conventions are hard-coded here.
os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-0.pcap";
os2 << GetTempDir () << PREFIX << "-" << i << "-0.pcap";
uint32_t sec(0), usec(0);
bool diff = PcapFile::Diff (os1.str(), os2.str(), sec, usec);
NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str() << " and " << os2.str()
<< " differ starting from " << sec << " s " << usec << " us");
}
}
}
}

View File

@@ -0,0 +1,184 @@
/* -*- 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
*
* Authors: Pavel Boyko <boyko@iitp.ru>
*/
#ifndef AODVREGRESSION_H_
#define AODVREGRESSION_H_
#include "ns3/test.h"
#include "ns3/nstime.h"
#include "ns3/node-container.h"
namespace ns3 {
namespace aodv {
/**
* \ingroup aodv
*
* \brief AODV chain regression test
*
* This script creates 1-dimensional grid topology and then ping last node from the first one:
*
* [10.1.1.1] <-- step --> [10.1.1.2] <-- step --> [10.1.1.3] <-- step --> [10.1.1.4] <-- step --> [10.1.1.5]
*
* Each node can hear only his right and his left neighbor, if they exist. When one third of total time expired,
* central node moves away. After this, node 3 doesn't hear any packets from other nodes and nobody hears his packets.
* We want to demonstrate in this script
* 1) route establishing
* 2) broken link detection both from layer 2 information and hello messages.
*
* \verbatim
Expected packets time diagram.
1 2 3 4 5
<------|------>| | | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=0, ID=1, org_seqno=1) src = 10.1.1.1
|<------|------>| | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=1, ID=1, org_seqno=1) src = 10.1.1.2
| |<------|------>| | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=2, ID=1, org_seqno=1) src = 10.1.1.3
| | |<------|------>| RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=3, ID=1, org_seqno=1) src = 10.1.1.4
| | | |<------|------> ARP request. Who has 10.1.1.4? Tell 10.1.1.5
| | | |======>| ARP reply
| | | |<======| RREP (orig 10.1.1.1, dst 10.1.1.5, hop=0, dst_seqno=0) src=10.1.1.5
| | |<------|------>| ARP request. Who has 10.1.1.3? Tell 10.1.1.4
| | |======>| | ARP reply
| | |<======| | RREP (orig 10.1.1.1, dst 10.1.1.5, hop=1, dst_seqno=0) src=10.1.1.4
| |<------|------>| | ARP request. Who has 10.1.1.2? Tell 10.1.1.3
| |======>| | | ARP reply
| |<======| | | RREP (orig 10.1.1.1, dst 10.1.1.5, hop=2, dst_seqno=0) src=10.1.1.3
|<------|------>| | | ARP request. Who has 10.1.1.1? Tell 10.1.1.2
|======>| | | | ARP reply
|<======| | | | RREP (orig 10.1.1.1, dst 10.1.1.5, hop=3, dst_seqno=0) src=10.1.1.2
<-------|------>| | | | ARP request. Who has 10.1.1.2? Tell 10.1.1.1
|<======| | | |
|======>| | | | ICMP (ping) request 0 from 10.1.1.1 to 10.1.1.5; src=10.1.1.1 next_hop=10.1.1.2
|<------|------>| | | ARP request. Who has 10.1.1.3? Tell 10.1.1.2
| |<======| | | ARP reply
| |======>| | | ICMP (ping) request 0 from 10.1.1.1 to 10.1.1.5; src=10.1.1.2 next_hop=10.1.1.3
| |<------|------>| | ARP request. Who has 10.1.1.4? Tell 10.1.1.3
| | |<======| | ARP reply
| | |======>| | ICMP (ping) request 0 from 10.1.1.1 to 10.1.1.5; src=10.1.1.3 next_hop=10.1.1.4
| | |<------|------>| ARP request. Who has 10.1.1.5? Tell 10.1.1.4
| | | |<======| ARP reply
| | | |======>| ICMP (ping) request 0; src=10.1.1.4 next_hop=10.1.1.5
| | | |<======| ICMP (ping) reply 0; src=10.1.1.5 next_hop=10.1.1.4
| | |<======| | ICMP (ping) reply 0; src=10.1.1.4 next_hop=10.1.1.3
| |<======| | | ICMP (ping) reply 0; src=10.1.1.3 next_hop=10.1.1.2
|<======| | | | ICMP (ping) reply 0; src=10.1.1.2 next_hop=10.1.1.1
| | | |<------|------> Hello
|<------|------>| | | Hello
<------|------>| | | | Hello
| |<------|------>| | Hello
|======>| | | | ICMP (ping) request 1; src=10.1.1.1 next_hop=10.1.1.2
| | |<------|------>| Hello
| |======>| | | ICMP (ping) request 1; src=10.1.1.2 next_hop=10.1.1.3
| | |======>| | ICMP (ping) request 1; src=10.1.1.3 next_hop=10.1.1.4
| | | |======>| ICMP (ping) request 1; src=10.1.1.4 next_hop=10.1.1.5
| | | |<======| ICMP (ping) reply 1; src=10.1.1.5 next_hop=10.1.1.4
| | |<======| | ICMP (ping) reply 1; src=10.1.1.4 next_hop=10.1.1.3
| |<======| | | ICMP (ping) reply 11; src=10.1.1.3 next_hop=10.1.1.2
|<======| | | | ICMP (ping) reply 1; src=10.1.1.2 next_hop=10.1.1.1
| | | |<------|------> Hello
|<------|------>| | | Hello
<------|------>| | | | Hello
| | |<------|------>| Hello
| |<------|------>| | Hello
|======>| | | | ICMP (ping) request 2; src=10.1.1.1 next_hop=10.1.1.2
| |======>| | | ICMP (ping) request 2; src=10.1.1.2 next_hop=10.1.1.3
| | |======>| | ICMP (ping) request 2; src=10.1.1.3 next_hop=10.1.1.4
| | | |======>| ICMP (ping) request 2; src=10.1.1.4 next_hop=10.1.1.5
| | | |<======| ICMP (ping) reply 2; src=10.1.1.5 next_hop=10.1.1.4
| | |<======| | ICMP (ping) reply 2; src=10.1.1.4 next_hop=10.1.1.3
| |<======| | | ICMP (ping) reply 2; src=10.1.1.3 next_hop=10.1.1.2
|<======| | | | ICMP (ping) reply 2; src=10.1.1.2 next_hop=10.1.1.1
| | | |<------|------> Hello
<------|------>| | | | Hello
| |<------|------>| | Hello
|<------|------>| | | Hello
| | |<------|------>| Hello
|======>| | | | ICMP (ping) request 3; src=10.1.1.1 next_hop=10.1.1.2
| |======>| | | ICMP (ping) request 3; src=10.1.1.2 next_hop=10.1.1.3
| | |======>| | ICMP (ping) request 3; src=10.1.1.3 next_hop=10.1.1.4
| | | |======>| ICMP (ping) request 3; src=10.1.1.4 next_hop=10.1.1.5
| | | |<======| ICMP (ping) reply 3; src=10.1.1.5 next_hop=10.1.1.4
| | |<======| | ICMP (ping) reply 3; src=10.1.1.4 next_hop=10.1.1.3
| |<======| | | ICMP (ping) reply 3; src=10.1.1.3 next_hop=10.1.1.2
|<======| | | | ICMP (ping) reply 3; src=10.1.1.2 next_hop=10.1.1.1
| | | |<------|------> Hello
<------|------>| | | | Hello
|<------|--> | | | Hello |
| | <--|--> | | Hello |Node 3 move away => nobody hear his packets and node 3 doesn't hear anything !
| | | <--|------>| Hello |
|======>| | | | ICMP (ping) request 4; src=10.1.1.1 next_hop=10.1.1.2
| |==> | | | ICMP (ping) request 4; src=10.1.1.2 next_hop=10.1.1.3. 7 retries.
|<======| | | | RERR (unreachable dst 10.1.1.3 & 10.1.1.5) src=10.1.1.2
| | | |<------|------> Hello
<------|------>| | | | Hello
|<------|--> | | | Hello
| | <--|--> | | Hello
| | | <--|------>| Hello
<------|------>| | | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=0, ID=2, org_seqno=2) src = 10.1.1.1
|<------|--> | | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=1, ID=2, org_seqno=1) src = 10.1.1.2
| | | |<------|------> Hello
| | | <--|------>| Hello
| | <--|--> | | Hello
<------|------>| | | | Hello
<------|------>| | | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=0, ID=3, org_seqno=3) src = 10.1.1.1
|<------|--> | | | Hello
|<------|--> | | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=1, ID=3, org_seqno=3) src = 10.1.1.2
| | | |======>| RERR (unreachable dst 10.1.1.1 & 10.1.1.3) src=10.1.1.4
| | | |<------|------> Hello
| | | <--|------>| Hello
| | <--|--> | | Hello
|<------|--> | | | Hello
<------|------>| | | | Hello
<------|------>| | | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=0, ID=4, org_seqno=4) src = 10.1.1.1
|<------|--> | | | RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=1, ID=4, org_seqno=4) src = 10.1.1.2
..................................................................
* \endverbatim
*/
class ChainRegressionTest : public TestCase
{
public:
ChainRegressionTest ();
~ChainRegressionTest ();
private:
/// Unique PCAP files prefix for this test
static const char * const PREFIX;
/// XXX It is important to have pointers here
NodeContainer * m_nodes;
/// Total simulation time
const Time m_time;
/// Chain size
const uint32_t m_size;
/// Chain step, meters
const double m_step;
/// Create test topology
void CreateNodes ();
/// Create devices, install TCP/IP stack and applications
void CreateDevices ();
/// Compare traces with reference ones
void CheckResults ();
/// Go
bool DoRun ();
};
}
}
#endif /* AODVREGRESSION_H_ */

1
src/routing/manet/aodv/waf vendored Executable file
View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../../../waf "$@"

View File

@@ -0,0 +1,25 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
module = bld.create_ns3_module('aodv', ['internet-stack', 'contrib'])
module.includes = '.'
module.source = [
'aodv-rtable.cc',
'aodv-rqueue.cc',
'aodv-packet.cc',
'aodv-neighbor.cc',
'aodv-routing-protocol.cc',
'aodv-test-suite.cc',
'test/aodv-regression.cc',
]
headers = bld.new_task_gen('ns3header')
headers.module = 'aodv'
headers.source = [
'aodv-rtable.h',
'aodv-rqueue.h',
'aodv-packet.h',
'aodv-neighbor.h',
'aodv-routing-protocol.h',
]

View File

@@ -0,0 +1,50 @@
/* -*- 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
*
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#include "dpd.h"
namespace ns3
{
namespace dpd
{
bool
DuplicatePacketDetection::IsDuplicate (Ptr<const Packet> p, const Ipv4Header & header)
{
return m_idCache.IsDuplicate (header.GetSource (), p->GetUid() );
}
void
DuplicatePacketDetection::SetLifetime (Time lifetime)
{
m_idCache.SetLifetime(lifetime);
}
Time
DuplicatePacketDetection::GetLifetime () const
{
return m_idCache.GetLifeTime();
}
}
}

View File

@@ -0,0 +1,59 @@
/* -*- 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
*
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef DUPLICATEPACKETDETECTION_H_
#define DUPLICATEPACKETDETECTION_H_
#include "id-cache.h"
#include "ns3/nstime.h"
#include "ns3/packet.h"
#include "ns3/ipv4-header.h"
namespace ns3
{
namespace dpd
{
/**
* \ingroup dpd
*
* \brief Helper class used to remember already seen packets and detect duplicates.
*/
class DuplicatePacketDetection
{
public:
/// C-tor
DuplicatePacketDetection (Time lifetime) : m_idCache(lifetime) {}
/// Check that the packet is duplicated. If not, save information about this packet.
bool IsDuplicate (Ptr<const Packet> p, const Ipv4Header & header);
/// Set duplicate records lifetimes
void SetLifetime (Time lifetime);
/// Get duplicate records lifetimes
Time GetLifetime () const;
private:
/// Impl
IdCache m_idCache;
};
}
}
#endif

View File

@@ -0,0 +1,131 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#include "id-cache.h"
#include "ns3/test.h"
#include <algorithm>
namespace ns3
{
namespace dpd
{
bool
IdCache::IsDuplicate (Ipv4Address addr, uint32_t id)
{
Purge ();
for (std::vector<UniqueId>::const_iterator i = m_idCache.begin ();
i != m_idCache.end (); ++i)
if (i->m_context == addr && i->m_id == id)
return true;
struct UniqueId uniqueId =
{ addr, id, m_lifetime + Simulator::Now () };
m_idCache.push_back (uniqueId);
return false;
}
void
IdCache::Purge ()
{
m_idCache.erase (remove_if (m_idCache.begin (), m_idCache.end (),
IsExpired ()), m_idCache.end ());
}
uint32_t
IdCache::GetSize ()
{
Purge ();
return m_idCache.size ();
}
//-----------------------------------------------------------------------------
// Tests
//-----------------------------------------------------------------------------
/// Unit test for id cache
struct IdCacheTest : public TestCase
{
IdCacheTest () : TestCase ("Id Cache"), cache (Seconds(10))
{}
virtual bool DoRun();
void CheckTimeout1 ();
void CheckTimeout2 ();
void CheckTimeout3 ();
IdCache cache;
};
bool
IdCacheTest::DoRun ()
{
NS_TEST_EXPECT_MSG_EQ (cache.GetLifeTime(), Seconds(10), "Lifetime");
NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 3), false, "Unknown ID & address");
NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 4), false, "Unknown ID");
NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("4.3.2.1"), 3), false, "Unknown address");
NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 3), true, "Known address & ID");
cache.SetLifetime(Seconds(15));
NS_TEST_EXPECT_MSG_EQ (cache.GetLifeTime(), Seconds(15), "New lifetime");
cache.IsDuplicate (Ipv4Address ("1.1.1.1"), 4);
cache.IsDuplicate (Ipv4Address ("1.1.1.1"), 4);
cache.IsDuplicate (Ipv4Address ("2.2.2.2"), 5);
cache.IsDuplicate (Ipv4Address ("3.3.3.3"), 6);
NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 6, "trivial");
Simulator::Schedule (Seconds(5), &IdCacheTest::CheckTimeout1, this);
Simulator::Schedule (Seconds(11), &IdCacheTest::CheckTimeout2, this);
Simulator::Schedule (Seconds(30), &IdCacheTest::CheckTimeout3, this);
Simulator::Run ();
Simulator::Destroy ();
return GetErrorStatus ();
}
void
IdCacheTest::CheckTimeout1 ()
{
NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 6, "Nothing expire");
}
void
IdCacheTest::CheckTimeout2 ()
{
NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 3, "3 records left");
}
void
IdCacheTest::CheckTimeout3 ()
{
NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 0, "All records expire");
}
//-----------------------------------------------------------------------------
class IdCacheTestSuite : public TestSuite
{
public:
IdCacheTestSuite () : TestSuite ("routing-id-cache", UNIT)
{
AddTestCase (new IdCacheTest);
}
} g_idCacheTestSuite;
}}

View File

@@ -0,0 +1,86 @@
/* -*- 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
*
* Based on
* NS-2 AODV model developed by the CMU/MONARCH group and optimized and
* tuned by Samir Das and Mahesh Marina, University of Cincinnati;
*
* AODV-UU implementation by Erik Nordström of Uppsala University
* http://core.it.uu.se/core/index.php/AODV-UU
*
* Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
* Pavel Boyko <boyko@iitp.ru>
*/
#ifndef IDCACHE_H_
#define IDCACHE_H_
#include "ns3/ipv4-address.h"
#include "ns3/simulator.h"
#include <vector>
namespace ns3
{
namespace dpd
{
/**
* \ingroup dpd
*
* \brief Unique packets identification cache used for simple duplicate detection.
*/
class IdCache
{
public:
/// c-tor
IdCache (Time lifetime): m_lifetime (lifetime) {}
/// Check that entry (addr, id) exists in cache. Add entry, if it doesn't exist.
bool IsDuplicate (Ipv4Address addr, uint32_t id);
/// Remove all expired entries
void Purge ();
/// Return number of entries in cache
uint32_t GetSize ();
/// Set lifetime for future added entries.
void SetLifetime (Time lifetime) { m_lifetime = lifetime; }
/// Return lifetime for existing entries in cache
Time GetLifeTime () const { return m_lifetime; }
private:
/// Unique packet ID
struct UniqueId
{
/// ID is supposed to be unique in single address context (e.g. sender address)
Ipv4Address m_context;
/// The id
uint32_t m_id;
/// When record will expire
Time m_expire;
};
struct IsExpired
{
bool operator() (const struct UniqueId & u) const
{
return (u.m_expire < Simulator::Now ());
}
};
/// Already seen IDs
std::vector<UniqueId> m_idCache;
/// Default lifetime for ID records
Time m_lifetime;
};
}
}
#endif /* IDCACHE_H_ */

1
src/routing/manet/dpd/waf vendored Executable file
View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../../../waf "$@"

View File

@@ -0,0 +1,17 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
module = bld.create_ns3_module('dpd', ['contrib'])
module.includes = '.'
module.source = [
'id-cache.cc',
'dpd.cc'
]
headers = bld.new_task_gen('ns3header')
headers.module = 'dpd'
headers.source = [
'dpd.h',
'id-cache.h',
]

View File

@@ -32,6 +32,8 @@ all_modules = (
'routing/global-routing',
'routing/static-routing',
'routing/list-routing',
'routing/manet/aodv',
'routing/manet/dpd',
'mobility',
'devices/wifi',
'helper',

View File

@@ -114,6 +114,7 @@ example_tests = [
("routing/simple-point-to-point-olsr", "True", "True"),
("routing/simple-routing-ping6", "True", "True"),
("routing/static-routing-slash32", "True", "True"),
("routing/aodv", "True", "True"),
("stats/wifi-example-sim", "True", "True"),