/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 Yufei Cheng
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Yufei Cheng <yfcheng@ittc.ku.edu>
*
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
* Information and Telecommunication Technology Center (ITTC)
* and Department of Electrical Engineering and Computer Science
* The University of Kansas Lawrence, KS USA.
*
* Work supported in part by NSF FIND (Future Internet Design) Program
* under grant CNS-0626918 (Postmodern Internet Architecture),
* NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
* US Department of Defense (DoD), and ITTC at The University of Kansas.
*/
#define NS_LOG_APPEND_CONTEXT \
if (GetObject<Node> ()) { std::clog << "[node " << GetObject<Node> ()->GetId () << "] "; }
#include <list>
#include <ctime>
#include <map>
#include <limits>
#include <algorithm>
#include <iostream>
#include "ns3/enum.h"
#include "ns3/string.h"
#include "ns3/ptr.h"
#include "ns3/log.h"
#include "ns3/assert.h"
#include "ns3/uinteger.h"
#include "ns3/packet.h"
#include "ns3/boolean.h"
#include "ns3/node-list.h"
#include "ns3/double.h"
#include "ns3/pointer.h"
#include "ns3/object-vector.h"
#include "ns3/ipv4-address.h"
#include "ns3/ipv4-header.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/ipv4-l4-protocol.h"
#include "ns3/ipv4-route.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/random-variable.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/adhoc-wifi-mac.h"
#include "ns3/wifi-net-device.h"
#include "ns3/inet-socket-address.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/udp-socket-factory.h"
#include "ns3/tcp-socket-factory.h"
#include "dsr-rreq-table.h"
#include "dsr-rcache.h"
#include "dsr-routing.h"
#include "dsr-fs-header.h"
#include "dsr-options.h"
NS_LOG_COMPONENT_DEFINE ("DsrRouting");
namespace ns3 {
namespace dsr {
NS_OBJECT_ENSURE_REGISTERED (DsrRouting);
/* see http://www.iana.org/assignments/protocol-numbers */
const uint8_t DsrRouting::PROT_NUMBER = 48;
/*
* The extension header is the fixed size dsr header, it is response for recognizing DSR option types
* and demux to right options to process the packet.
*
* The header format with neighboring layers is as follows:
*
+-+-+-+-+-+-+-+-+-+-+-
| Application Header |
+-+-+-+-+-+-+-+-+-+-+-+
| Transport Header |
+-+-+-+-+-+-+-+-+-+-+-+
| Fixed DSR Header |
+---------------------+
| DSR Options |
+-+-+-+-+-+-+-+-+-+-+-+
| IP Header |
+-+-+-+-+-+-+-+-+-+-+-+
*/
TypeId DsrRouting::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::dsr::DsrRouting")
.SetParent<Ipv4L4Protocol> ()
.AddConstructor<DsrRouting> ()
.AddAttribute ("RouteCache", "The route cache for saving routes from route discovery process.",
PointerValue (0),
MakePointerAccessor (&DsrRouting::SetRouteCache,
&DsrRouting::GetRouteCache),
MakePointerChecker<RouteCache> ())
.AddAttribute ("RreqTable", "The request table to manage route requests.",
PointerValue (0),
MakePointerAccessor (&DsrRouting::SetRequestTable,
&DsrRouting::GetRequestTable),
MakePointerChecker<RreqTable> ())
.AddAttribute ("MaxSendBuffLen","Maximum number of packets that can be stored in send buffer.",
UintegerValue (64),
MakeUintegerAccessor (&DsrRouting::m_maxSendBuffLen),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("MaxSendBuffTime","Maximum time packets can be queued in the send buffer .",
TimeValue (Seconds (30)),
MakeTimeAccessor (&DsrRouting::m_sendBufferTimeout),
MakeTimeChecker ())
.AddAttribute ("MaxMaintLen","Maximum number of packets that can be stored in maintenance buffer.",
UintegerValue (50),
MakeUintegerAccessor (&DsrRouting::m_maxMaintainLen),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("MaxMaintTime","Maximum time packets can be queued in maintenance buffer.",
TimeValue (Seconds (30)),
MakeTimeAccessor (&DsrRouting::m_maxMaintainTime),
MakeTimeChecker ())
.AddAttribute ("MaxCacheLen","Maximum number of route entries that can be stored in route cache.",
UintegerValue (64),
MakeUintegerAccessor (&DsrRouting::m_maxCacheLen),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("RouteCacheTimeout","Maximum time the route cache can be queued in route cache.",
TimeValue (Seconds (300)),
MakeTimeAccessor (&DsrRouting::m_maxCacheTime),
MakeTimeChecker ())
.AddAttribute ("MaxEntriesEachDst","Maximum number of route entries for a single destination to respond.",
UintegerValue (20),
MakeUintegerAccessor (&DsrRouting::m_maxEntriesEachDst),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("SendBuffInterval","How often to check send buffer for packet with route.",
TimeValue (Seconds (500)),
MakeTimeAccessor (&DsrRouting::m_sendBuffInterval),
MakeTimeChecker ())
.AddAttribute ("NodeTraversalTime","The time it takes to traverse two neighboring nodes.",
TimeValue (MilliSeconds (40)),
MakeTimeAccessor (&DsrRouting::m_nodeTraversalTime),
MakeTimeChecker ())
.AddAttribute ("RreqRetries","Maximum number of retransmissions for request discovery of a route.",
UintegerValue (16),
MakeUintegerAccessor (&DsrRouting::m_rreqRetries),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("MaintenanceRetries","Maximum number of retransmissions for data packets from maintenance buffer.",
DoubleValue (2),
MakeDoubleAccessor (&DsrRouting::m_maxMaintRexmt),
MakeDoubleChecker<uint32_t> ())
.AddAttribute ("RequestTableSize","Maximum number of request entries in the request table.",
UintegerValue (64),
MakeUintegerAccessor (&DsrRouting::m_requestTableSize),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("RequestIdSize","Maximum number of request source Ids in the request table.",
UintegerValue (16),
MakeUintegerAccessor (&DsrRouting::m_requestTableIds),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("UniqueRequestIdSize","Maximum number of request Ids in the request table for a single destination.",
UintegerValue (256),
MakeUintegerAccessor (&DsrRouting::m_maxRreqId),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("NonPropRequestTimeout","The timeout value for non-propagation request.",
TimeValue (MilliSeconds (30)),
MakeTimeAccessor (&DsrRouting::m_nonpropRequestTimeout),
MakeTimeChecker ())
.AddAttribute ("DiscoveryHopLimit","The max discovery hop limit for route requests.",
DoubleValue (255),
MakeDoubleAccessor (&DsrRouting::m_discoveryHopLimit),
MakeDoubleChecker<uint32_t> ())
.AddAttribute ("MaxSalvageCount","The max salvage count for a single data packet.",
UintegerValue (15),
MakeUintegerAccessor (&DsrRouting::m_maxSalvageCount),
MakeUintegerChecker<uint8_t> ())
.AddAttribute ("BlacklistTimeout","The time for a neighbor to stay in blacklist.",
TimeValue (Seconds (3)),
MakeTimeAccessor (&DsrRouting::m_blacklistTimeout),
MakeTimeChecker ())
.AddAttribute ("GratReplyHoldoff","The time for gratuitous reply entry to expire.",
TimeValue (Seconds (1)),
MakeTimeAccessor (&DsrRouting::m_gratReplyHoldoff),
MakeTimeChecker ())
.AddAttribute ("BroadcastJitter","The jitter time to avoid collision for broadcast packets.",
UintegerValue (10),
MakeUintegerAccessor (&DsrRouting::m_broadcastJitter),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("PassiveAckTimeout","The time a packet in maintenance buffer wait for passive acknowledgment.",
TimeValue (MilliSeconds (100)),
MakeTimeAccessor (&DsrRouting::m_passiveAckTimeout),
MakeTimeChecker ())
.AddAttribute ("TryPassiveAcks","The number of passive acknowledgment to use.",
UintegerValue (1),
MakeUintegerAccessor (&DsrRouting::m_tryPassiveAcks),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("RequestPeriod","The base time interval between route requests.",
TimeValue (MilliSeconds (500)),
MakeTimeAccessor (&DsrRouting::m_requestPeriod),
MakeTimeChecker ())
.AddAttribute ("MaxRequestPeriod","The max time interval between route requests.",
TimeValue (Seconds (10)),
MakeTimeAccessor (&DsrRouting::m_maxRequestPeriod),
MakeTimeChecker ())
.AddAttribute ("GraReplyTableSize","The gratuitous reply table size.",
UintegerValue (64),
MakeUintegerAccessor (&DsrRouting::m_graReplyTableSize),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("CacheType","Use Link Cache or use Path Cache",
StringValue ("LinkCache"),
MakeStringAccessor (&DsrRouting::m_cacheType),
MakeStringChecker ())
.AddAttribute ("StabilityDecrFactor","The stability decrease factor for link cache",
UintegerValue (2),
MakeUintegerAccessor (&DsrRouting::m_stabilityDecrFactor),
MakeUintegerChecker<uint64_t> ())
.AddAttribute ("StabilityIncrFactor","The stability increase factor for link cache",
UintegerValue (4),
MakeUintegerAccessor (&DsrRouting::m_stabilityIncrFactor),
MakeUintegerChecker<uint64_t> ())
.AddAttribute ("InitStability","The initial stability factor for link cache",
TimeValue (Seconds (25)),
MakeTimeAccessor (&DsrRouting::m_initStability),
MakeTimeChecker ())
.AddAttribute ("MinLifeTime","The minimal life time for link cache",
TimeValue (Seconds (1)),
MakeTimeAccessor (&DsrRouting::m_minLifeTime),
MakeTimeChecker ())
.AddAttribute ("UseExtends","The extension time for link cache",
TimeValue (Seconds (120)),
MakeTimeAccessor (&DsrRouting::m_useExtends),
MakeTimeChecker ())
.AddAttribute ("EnableSubRoute","Enables saving of sub route when receiving route error messages, only available when using path route cache",
BooleanValue (true),
MakeBooleanAccessor (&DsrRouting::m_subRoute),
MakeBooleanChecker ())
.AddAttribute ("RetransIncr","The increase time for retransmission timer when facing network congestion",
TimeValue (MilliSeconds (20)),
MakeTimeAccessor (&DsrRouting::m_retransIncr),
MakeTimeChecker ())
.AddAttribute ("MaxNetworkQueueSize","The max number of packet to save in the network queue.",
UintegerValue (400),
MakeUintegerAccessor (&DsrRouting::m_maxNetworkSize),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("MaxNetworkQueueDelay","The max time for a packet to stay in the network queue.",
TimeValue (Seconds (30.0)),
MakeTimeAccessor (&DsrRouting::m_maxNetworkDelay),
MakeTimeChecker ())
.AddAttribute ("NumPriorityQueues","The max number of packet to save in the network queue.",
UintegerValue (2),
MakeUintegerAccessor (&DsrRouting::m_numPriorityQueues),
MakeUintegerChecker<uint32_t> ())
.AddTraceSource ("Tx", "Send DSR packet.",
MakeTraceSourceAccessor (&DsrRouting::m_txPacketTrace))
.AddTraceSource ("Drop", "Drop DSR packet",
MakeTraceSourceAccessor (&DsrRouting::m_dropTrace))
;
return tid;
}
DsrRouting::DsrRouting ()
{
NS_LOG_FUNCTION_NOARGS ();
/*
* The following Ptr statements created objects for all the options header for DSR, and each of them have
* distinct option number assigned, when DSR Routing received a packet from higher layer, it will find
* the following options based on the option number, and pass the packet to the appropriate option to
* process it. After the option processing, it will pass the packet back to DSR Routing to send down layer.
*/
Ptr<dsr::DsrOptionPad1> pad1Option = CreateObject<dsr::DsrOptionPad1> ();
Ptr<dsr::DsrOptionPadn> padnOption = CreateObject<dsr::DsrOptionPadn> ();
Ptr<dsr::DsrOptionRreq> rreqOption = CreateObject<dsr::DsrOptionRreq> ();
Ptr<dsr::DsrOptionRrep> rrepOption = CreateObject<dsr::DsrOptionRrep> ();
Ptr<dsr::DsrOptionSR> srOption = CreateObject<dsr::DsrOptionSR> ();
Ptr<dsr::DsrOptionRerr> rerrOption = CreateObject<dsr::DsrOptionRerr> ();
Ptr<dsr::DsrOptionAckReq> ackReq = CreateObject<dsr::DsrOptionAckReq> ();
Ptr<dsr::DsrOptionAck> ack = CreateObject<dsr::DsrOptionAck> ();
Insert (pad1Option);
Insert (padnOption);
Insert (rreqOption);
Insert (rrepOption);
Insert (srOption);
Insert (rerrOption);
Insert (ackReq);
Insert (ack);
// Check the send buffer for sending packets
m_sendBuffTimer.SetFunction (&DsrRouting::SendBuffTimerExpire, this);
m_sendBuffTimer.Schedule (Seconds (100));
}
DsrRouting::~DsrRouting ()
{
NS_LOG_FUNCTION_NOARGS ();
}
void
DsrRouting::NotifyNewAggregate ()
{
NS_LOG_FUNCTION (this << "NotifyNewAggregate");
if (m_node == 0)
{
Ptr<Node> node = this->GetObject<Node> ();
if (node != 0)
{
m_ipv4 = this->GetObject<Ipv4L3Protocol> ();
if (m_ipv4 != 0)
{
this->SetNode (node);
m_ipv4->Insert (this);
this->SetDownTarget (MakeCallback (&Ipv4L3Protocol::Send, m_ipv4));
}
m_ip = node->GetObject<Ipv4> ();
if (m_ip != 0)
{
NS_LOG_DEBUG ("Ipv4 started");
}
}
}
Object::NotifyNewAggregate ();
Simulator::ScheduleNow (&DsrRouting::Start, this);
}
void DsrRouting::Start ()
{
NS_LOG_FUNCTION (this << "Start DSR Routing protocol");
Ptr<dsr::RouteCache> routeCache = CreateObject<dsr::RouteCache> ();
// Configure the path cache parameters
routeCache->SetCacheType (m_cacheType);
routeCache->SetSubRoute (m_subRoute);
routeCache->SetMaxCacheLen (m_maxCacheLen);
routeCache->SetCacheTimeout (m_maxCacheTime);
routeCache->SetMaxEntriesEachDst (m_maxEntriesEachDst);
// Parameters for link cache
routeCache->SetStabilityDecrFactor (m_stabilityDecrFactor);
routeCache->SetStabilityIncrFactor (m_stabilityIncrFactor);
routeCache->SetInitStability (m_initStability);
routeCache->SetMinLifeTime (m_minLifeTime);
routeCache->SetUseExtends (m_useExtends);
routeCache->ScheduleTimer ();
// The call back to handle link error and send error message to appropriate nodes
routeCache->SetCallback (MakeCallback (&DsrRouting::SendRerrWhenBreaksLinkToNextHop, this));
SetRouteCache (routeCache);
if (m_mainAddress == Ipv4Address ())
{
Ipv4Address loopback ("127.0.0.1");
for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
{
// Use primary address, if multiple
Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
m_broadcast = m_ipv4->GetAddress (i, 0).GetBroadcast();
NS_LOG_DEBUG ("The addr " << addr);
if (addr != loopback)
{
m_mainAddress = addr;
NS_LOG_DEBUG ("The node Address " << m_mainAddress);
m_ipv4->GetNetDevice (1)->SetPromiscReceiveCallback (MakeCallback (&DsrRouting::PromiscReceive, this));
// Allow neighbor manager use this interface for layer 2 feedback if possible
Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (addr));
Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
if (wifi == 0)
{
break;
}
Ptr<WifiMac> mac = wifi->GetMac ();
if (mac == 0)
{
break;
}
// trace back to link mac drop event to process tx error call back
mac->TraceConnectWithoutContext ("TxErrHeader", routeCache->GetTxErrorCallback ());
routeCache->AddArpCache (m_ipv4->GetInterface (i)->GetArpCache ());
break;
}
}
NS_ASSERT (m_mainAddress != Ipv4Address () && m_broadcast != Ipv4Address());
}
NS_LOG_DEBUG ("The number queues " << m_numPriorityQueues);
for (uint32_t i = 0; i < m_numPriorityQueues; i++)
{
// Set the network queue max size and the delay
NS_LOG_DEBUG ("The network size " << m_maxNetworkSize << " and the network delay " << m_maxNetworkDelay.GetSeconds());
Ptr<dsr::DsrNetworkQueue> queue_i = CreateObject<dsr::DsrNetworkQueue> (m_maxNetworkSize,m_maxNetworkDelay);
std::pair<std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator, bool> result_i = m_priorityQueue.insert (std::make_pair (i, queue_i));
NS_ASSERT_MSG (result_i.second, "Error in creating queues");
}
Ptr<dsr::RreqTable> rreqTable = CreateObject<dsr::RreqTable> ();
// Set the initial hop limit
rreqTable->SetInitHopLimit (m_discoveryHopLimit);
// Configure the request table parameters
rreqTable->SetRreqTableSize (m_requestTableSize);
rreqTable->SetRreqIdSize (m_requestTableIds);
rreqTable->SetUniqueRreqIdSize (m_maxRreqId);
SetRequestTable (rreqTable);
// Set the send buffer parameters
m_sendBuffer.SetMaxQueueLen (m_maxSendBuffLen);
m_sendBuffer.SetSendBufferTimeout (m_sendBufferTimeout);
// Set the error buffer parameters using just the send buffer parameters
m_errorBuffer.SetMaxQueueLen (m_maxSendBuffLen);
m_errorBuffer.SetErrorBufferTimeout (m_sendBufferTimeout);
// Set the maintenance buffer parameters
m_maintainBuffer.SetMaxQueueLen (m_maxMaintainLen);
m_maintainBuffer.SetMaintainBufferTimeout (m_maxMaintainTime);
// Set the gratuitous reply table size
m_graReply.SetGraTableSize (m_graReplyTableSize);
NS_LOG_DEBUG ("Starting DSR on node " << m_mainAddress);
}
void
DsrRouting::DoDispose (void)
{
NS_LOG_FUNCTION_NOARGS ();
m_node = 0;
for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
{
// Disable layer 2 link state monitoring (if possible)
Ptr<NetDevice> dev = m_ipv4->GetNetDevice (i);
Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
if (wifi != 0)
{
Ptr<WifiMac> mac = wifi->GetMac ()->GetObject<AdhocWifiMac> ();
if (mac != 0)
{
mac->TraceDisconnectWithoutContext ("TxErrHeader",
m_routeCache->GetTxErrorCallback ());
m_routeCache->DelArpCache (m_ipv4->GetInterface (i)->GetArpCache ());
}
}
}
Ipv4L4Protocol::DoDispose ();
}
void
DsrRouting::SetNode (Ptr<Node> node)
{
m_node = node;
}
Ptr<Node>
DsrRouting::GetNode () const
{
NS_LOG_FUNCTION_NOARGS ();
return m_node;
}
void DsrRouting::SetRouteCache (Ptr<dsr::RouteCache> r)
{
// / Set the route cache to use
m_routeCache = r;
}
Ptr<dsr::RouteCache>
DsrRouting::GetRouteCache () const
{
// / Get the route cache to use
return m_routeCache;
}
void DsrRouting::SetRequestTable (Ptr<dsr::RreqTable> q)
{
// / Set the request table to use
m_rreqTable = q;
}
Ptr<dsr::RreqTable>
DsrRouting::GetRequestTable () const
{
// / Get the request table to use
return m_rreqTable;
}
bool DsrRouting::IsLinkCache ()
{
return m_routeCache->IsLinkCache ();
}
void DsrRouting::UseExtends (RouteCacheEntry::IP_VECTOR rt)
{
m_routeCache->UseExtends (rt);
}
bool DsrRouting::LookupRoute (Ipv4Address id, RouteCacheEntry & rt)
{
return m_routeCache->LookupRoute (id, rt);
}
bool DsrRouting::AddRoute_Link (RouteCacheEntry::IP_VECTOR nodelist, Ipv4Address source)
{
Ipv4Address nextHop = SearchNextHop (source, nodelist);
m_errorBuffer.DropPacketForErrLink (source, nextHop);
return m_routeCache->AddRoute_Link (nodelist, source);
}
bool DsrRouting::AddRoute (RouteCacheEntry & rt)
{
std::vector<Ipv4Address> nodelist = rt.GetVector ();
Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodelist);
m_errorBuffer.DropPacketForErrLink (m_mainAddress, nextHop);
return m_routeCache->AddRoute (rt);
}
void DsrRouting::DeleteAllRoutesIncludeLink (Ipv4Address errorSrc, Ipv4Address unreachNode, Ipv4Address node)
{
m_routeCache->DeleteAllRoutesIncludeLink (errorSrc, unreachNode, node);
}
bool DsrRouting::UpdateRouteEntry (Ipv4Address dst)
{
return m_routeCache->UpdateRouteEntry (dst);
}
Ipv4Address
DsrRouting::GetIPfromMAC (Mac48Address address)
{
NS_LOG_FUNCTION (this << address);
int32_t nNodes = NodeList::GetNNodes ();
for (int32_t i = 0; i < nNodes; ++i)
{
Ptr<Node> node = NodeList::GetNode (i);
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
Ptr<NetDevice> netDevice = ipv4->GetNetDevice (1);
if (netDevice->GetAddress () == address)
{
return ipv4->GetAddress (1, 0).GetLocal ();
}
}
return 0;
}
void DsrRouting::PrintVector (std::vector<Ipv4Address>& vec)
{
NS_LOG_FUNCTION (this);
/*
* Check elements in a route vector
*/
if (!vec.size ())
{
NS_LOG_DEBUG ("The vector is empty");
}
else
{
NS_LOG_DEBUG ("Print all the elements in a vector");
for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
{
NS_LOG_DEBUG ("The ip address " << *i);
}
}
}
Ipv4Address DsrRouting::SearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec)
{
NS_LOG_FUNCTION (this << ipv4Address);
Ipv4Address nextHop;
NS_LOG_DEBUG ("the vector size " << vec.size ());
if (vec.size () == 2)
{
NS_LOG_DEBUG ("The two nodes are neighbors");
nextHop = vec[1];
return nextHop;
}
else
{
if (ipv4Address == vec.back ())
{
NS_LOG_DEBUG ("We have reached to the final destination " << ipv4Address << " " << vec.back ());
return ipv4Address;
}
for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
{
if (ipv4Address == (*i))
{
NS_LOG_DEBUG (ipv4Address << " and " << *i);
nextHop = *(++i);
return nextHop;
}
}
}
NS_LOG_DEBUG ("Next hop address not found");
Ipv4Address none = "0.0.0.0";
return none;
}
Ptr<Ipv4Route>
DsrRouting::SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress)
{
NS_LOG_FUNCTION (this << nextHop << srcAddress);
m_ipv4Route = Create<Ipv4Route> ();
m_ipv4Route->SetDestination (nextHop);
m_ipv4Route->SetGateway (nextHop);
m_ipv4Route->SetSource (srcAddress);
return m_ipv4Route;
}
int
DsrRouting::GetProtocolNumber (void) const
{
// / This is the protocol number for DSR which is 48
return PROT_NUMBER;
}
uint16_t
DsrRouting::GetIDfromIP (Ipv4Address address)
{
int32_t nNodes = NodeList::GetNNodes ();
for (int32_t i = 0; i < nNodes; ++i)
{
Ptr<Node> node = NodeList::GetNode (i);
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
if (ipv4->GetAddress (1, 0).GetLocal () == address)
{
return uint16_t(i);
}
}
return 256;
}
Ipv4Address
DsrRouting::GetIPfromID (uint16_t id)
{
if (id >= 256)
{
NS_LOG_DEBUG ("Exceed the node range");
return "0.0.0.0";
}
else
{
Ptr<Node> node = NodeList::GetNode (uint32_t (id));
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
return ipv4->GetAddress (1, 0).GetLocal ();
}
}
uint32_t
DsrRouting::GetPriority (DsrMessageType messageType)
{
if (messageType == DSR_CONTROL_PACKET)
{
return 0;
}
else
{
return 1;
}
}
void DsrRouting::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop, uint8_t protocol)
{
NS_LOG_FUNCTION (this << nextHop << (uint32_t)protocol);
MaintainBuffEntry entry;
// Find the packet in send buffer
if (m_maintainBuffer.Find (nextHop))
{
NS_LOG_DEBUG ("Trying to dequeue");
if (m_maintainBuffer.Dequeue (nextHop, entry))
{
NS_LOG_DEBUG ("creating new packet");
/*
* Copy the packet and save a copy to the send buffer.
* if only queue the original packet to the buffer,
* when dequeue the packet, it turns to be empty.
*/
Ptr<Packet> dequeP = ConstCast<Packet> (entry.GetPacket ());
Ptr<Packet> newPacket = dequeP->Copy ();
Ptr<Packet> p = dequeP->Copy ();
Ipv4Address source = entry.GetSrc ();
Ipv4Address destination = entry.GetDst ();
// Send the data packet out before schedule the next packet transmission
SendPacket (dequeP, source, nextHop, protocol);
DsrRoutingHeader dsrRoutingHeader;
p->RemoveHeader (dsrRoutingHeader);
Ptr<Packet> cleanP = p->Copy ();
uint8_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
newPacket->RemoveAtStart (offset);
// Get the number of routers' address field
uint8_t buf[2];
newPacket->CopyData (buf, sizeof(buf));
uint8_t numberAddress = (buf[1] - 2) / 4;
DsrOptionSRHeader sourceRoute;
sourceRoute.SetNumberAddress (numberAddress);
newPacket->RemoveHeader (sourceRoute);
uint8_t salvage = sourceRoute.GetSalvage ();
// TODO
DsrOptionAckReqHeader ackReq;
newPacket->RemoveHeader (ackReq);
/*
* Get the node list address
*/
std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
Ipv4Address address1 = nodeList[1];
Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);
NS_LOG_DEBUG ("The next hop address" << nextHop);
if (nextHop == "0.0.0.0")
{
PacketNewRoute (cleanP, m_mainAddress, destination, protocol);
return;
}
RouteCacheEntry salvageRoute;
bool findRoute = m_routeCache->LookupRoute (destination, salvageRoute);
// Check the salvage value in header, if salvage is needed, we should find alternative route
if (findRoute && (salvage < m_maxSalvageCount))
{
// Need to salvage the packet instead of discard it
Ipv4Address source = nodeList.front ();
std::vector<Ipv4Address> nodeList = salvageRoute.GetVector ();
DsrOptionSRHeader newSR;
newSR.SetNodesAddress (nodeList);
newSR.SetSegmentsLeft ((nodeList.size () - 2));
newSR.SetSalvage (salvage + 1);
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (nodeList);
}
NetworkKey networkKey;
networkKey.m_ackId = entry.GetAckId ();
networkKey.m_ourAdd = entry.GetOurAdd ();
networkKey.m_nextHop = entry.GetNextHop ();
networkKey.m_source = entry.GetSrc ();
networkKey.m_destination = entry.GetDst ();
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = entry.GetSrc ();
passiveKey.m_destination = entry.GetDst ();
passiveKey.m_segsLeft = entry.GetSegsLeft ();
m_addressForwardCnt[networkKey] = 0;
m_passiveCnt[passiveKey] = 0;
if (nextHop != destination)
{
SchedulePassivePacketRetry (entry, false, protocol);
}
else
{
// This is the first network retry
ScheduleNetworkPacketRetry (entry, true, protocol);
}
}
else
{
/*
* This code block create a packet and attach a route error option to it
*/
m_routeCache->DeleteAllRoutesIncludeLink (source, nextHop, m_mainAddress);
/*
* If the salvage is not 0, use the first address in the route as the error dst in error header
* otherwise use the source of packet as the error destination
*/
Ipv4Address errorDst;
if (salvage)
{
errorDst = address1;
}
else
{
errorDst = source;
}
SendUnreachError (nextHop, errorDst, destination, salvage, protocol);
/*
* here we cancel the packet retransmission time for all the packets have next hop address
* as nextHop
*/
}
if (m_maintainBuffer.GetSize () != 0 && m_maintainBuffer.Find (nextHop))
{
Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
&DsrRouting::SendRerrWhenBreaksLinkToNextHop,this,nextHop,protocol);
}
}
}
}
void DsrRouting::SendBuffTimerExpire ()
{
if (m_sendBuffTimer.IsRunning ())
{
m_sendBuffTimer.Cancel ();
}
m_sendBuffTimer.Schedule (m_sendBuffInterval);
CheckSendBuffer ();
}
void DsrRouting::CheckSendBuffer ()
{
NS_LOG_INFO (Simulator::Now ().GetSeconds ()
<< " Checking send buffer at " << m_mainAddress << " with size " << m_sendBuffer.GetSize ());
for (std::vector<SendBuffEntry>::iterator i = m_sendBuffer.GetBuffer ().begin (); i != m_sendBuffer.GetBuffer ().end (); )
{
NS_LOG_DEBUG ("Here we try to find the data packet in the send buffer");
Ipv4Address destination = i->GetDestination ();
RouteCacheEntry toDst;
bool findRoute = m_routeCache->LookupRoute (destination, toDst);
if (findRoute)
{
NS_LOG_INFO ("We have found a route for the packet");
Ptr<const Packet> packet = i->GetPacket ();
Ptr<Packet> cleanP = packet->Copy ();
uint8_t protocol = i->GetProtocol ();
m_sendBuffer.GetBuffer ().erase (i);
DsrRoutingHeader dsrRoutingHeader;
Ptr<Packet> copyP = packet->Copy ();
Ptr<Packet> dsrPacket = packet->Copy ();
dsrPacket->RemoveHeader (dsrRoutingHeader);
uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
copyP->RemoveAtStart (offset); // Here the processed size is 8 bytes, which is the fixed sized extension header
// The packet to get ipv4 header
Ptr<Packet> ipv4P = copyP->Copy ();
/*
* Peek data to get the option type as well as length and segmentsLeft field
*/
uint32_t size = copyP->GetSize ();
uint8_t *data = new uint8_t[size];
copyP->CopyData (data, size);
uint8_t optionType = 0;
optionType = *(data);
if (optionType == 3)
{
Ptr<dsr::DsrOptions> dsrOption;
DsrOptionHeader dsrOptionHeader;
uint8_t errorType = *(data + 2);
if (errorType == 1) // This is the Route Error Option
{
DsrOptionRerrUnreachHeader rerr;
copyP->RemoveHeader (rerr);
NS_ASSERT (copyP->GetSize () == 0);
DsrOptionRerrUnreachHeader newUnreach;
newUnreach.SetErrorType (1);
newUnreach.SetErrorSrc (rerr.GetErrorSrc ());
newUnreach.SetUnreachNode (rerr.GetUnreachNode ());
newUnreach.SetErrorDst (rerr.GetErrorDst ());
newUnreach.SetSalvage (rerr.GetSalvage ()); // Set the value about whether to salvage a packet or not
DsrOptionSRHeader sourceRoute;
std::vector<Ipv4Address> errorRoute = toDst.GetVector ();
sourceRoute.SetNodesAddress (errorRoute);
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (errorRoute);
}
sourceRoute.SetSegmentsLeft ((errorRoute.size () - 2));
uint8_t salvage = 0;
sourceRoute.SetSalvage (salvage);
Ipv4Address nextHop = SearchNextHop (m_mainAddress, errorRoute); // Get the next hop address
if (nextHop == "0.0.0.0")
{
PacketNewRoute (dsrPacket, m_mainAddress, destination, protocol);
return;
}
SetRoute (nextHop, m_mainAddress);
uint8_t length = (sourceRoute.GetLength () + newUnreach.GetLength ());
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
dsrRoutingHeader.SetDestId (255);
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
dsrRoutingHeader.AddDsrOption (newUnreach);
dsrRoutingHeader.AddDsrOption (sourceRoute);
Ptr<Packet> newPacket = Create<Packet> ();
newPacket->AddHeader (dsrRoutingHeader); // Add the routing header with rerr and sourceRoute attached to it
Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
m_ipv4Route->SetOutputDevice (dev);
uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (newPacket, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
}
else
{
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (2);
dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
DsrOptionSRHeader sourceRoute;
std::vector<Ipv4Address> nodeList = toDst.GetVector (); // Get the route from the route entry we found
Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList); // Get the next hop address for the route
if (nextHop == "0.0.0.0")
{
PacketNewRoute (dsrPacket, m_mainAddress, destination, protocol);
return;
}
uint8_t salvage = 0;
sourceRoute.SetNodesAddress (nodeList); // Save the whole route in the source route header of the packet
sourceRoute.SetSegmentsLeft ((nodeList.size () - 2)); // The segmentsLeft field will indicate the hops to go
sourceRoute.SetSalvage (salvage);
uint8_t length = sourceRoute.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
dsrRoutingHeader.AddDsrOption (sourceRoute);
cleanP->AddHeader (dsrRoutingHeader);
// Send the data packet out before schedule the next packet transmission
SendPacket (cleanP, m_mainAddress, nextHop, protocol);
Ptr<const Packet> mtP = cleanP->Copy ();
// Put the data packet in the maintenance queue for data packet retransmission
MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*Ipv4Address=*/ m_mainAddress, /*nextHop=*/ nextHop,
/*source=*/ m_mainAddress, /*destination=*/ destination, /*ackId=*/ 0,
/*SegsLeft=*/nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
bool result = m_maintainBuffer.Enqueue (newEntry); // Enqueue the packet the the maintenance buffer
if (result)
{
NetworkKey networkKey;
networkKey.m_ackId = newEntry.GetAckId ();
networkKey.m_ourAdd = newEntry.GetOurAdd ();
networkKey.m_nextHop = newEntry.GetNextHop ();
networkKey.m_source = newEntry.GetSrc ();
networkKey.m_destination = newEntry.GetDst ();
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = newEntry.GetSrc ();
passiveKey.m_destination = newEntry.GetDst ();
passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
m_addressForwardCnt[networkKey] = 0;
m_passiveCnt[passiveKey] = 0;
if (nextHop != destination)
{
SchedulePassivePacketRetry (newEntry, false, protocol);
}
else
{
// This is the first network retry
ScheduleNetworkPacketRetry (newEntry, true, protocol);
}
}
// we need to suspend the normal timer that checks the send buffer
// until we are done sending packets
if (!m_sendBuffTimer.IsSuspended ())
{
m_sendBuffTimer.Suspend ();
}
Simulator::Schedule (m_sendBuffInterval, &DsrRouting::SendBuffTimerExpire, this);
return;
}
}
else
{
++i;
}
}
//after going through the entire send buffer and send all packets found route,
//we need to resume the timer if it has been suspended
if (m_sendBuffTimer.IsSuspended ())
{
NS_LOG_DEBUG ("Resume the send buffer timer");
m_sendBuffTimer.Resume ();
}
}
bool DsrRouting::PromiscReceive (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType)
{
// Receive only IP packets and packets destined for other hosts
if (protocol == Ipv4L3Protocol::PROT_NUMBER && packetType == NetDevice::PACKET_OTHERHOST)
{
Ptr<Packet> p = packet->Copy ();
//pull off IP header
Ipv4Header ipv4Header;
p->RemoveHeader (ipv4Header);
// Process only data packets with DSR header
if (ipv4Header.GetProtocol () == DsrRouting::PROT_NUMBER)
{
//just to minimize debug output
NS_LOG_INFO (this << from << to << packetType << *p);
DsrRoutingHeader dsrRoutingHeader;
//pull of DSR header to check option type
Ptr<Packet> dsrPacket = p->Copy ();
dsrPacket->RemoveHeader (dsrRoutingHeader);
uint8_t offset = dsrRoutingHeader.GetDsrOptionsOffset (); // Get the offset for option header, 4 bytes in this case
uint8_t nextHeader = dsrRoutingHeader.GetNextHeader ();
uint32_t sourceId = dsrRoutingHeader.GetSourceId ();
Ipv4Address source = GetIPfromID (sourceId);
// This packet is used to peek option type
p->RemoveAtStart (offset);
/*
* Peek data to get the option type as well as length and segmentsLeft field
*/
uint32_t size = p->GetSize ();
uint8_t *data = new uint8_t[size];
p->CopyData (data, size);
uint8_t optionType = 0;
uint8_t optionLength = 0;
optionType = *(data);
Ptr<dsr::DsrOptions> dsrOption;
if (optionType == 96) // This is the source route option
{
dsrOption = GetOption (optionType); // Get the relative DSR option and demux to the process function
Ipv4Address fromAddr = GetIPfromMAC (Mac48Address::ConvertFrom (from));
Ipv4Address toAddr = GetIPfromMAC (Mac48Address::ConvertFrom (to));
NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
<< " DSR node " << m_mainAddress <<
" overhearing packet PID: " << p->GetUid () << " from " << fromAddr << " to " << toAddr <<
" with source IP " << ipv4Header.GetSource () <<
" and destination IP " << ipv4Header.GetDestination () <<
" and packet : " << *dsrPacket);
bool isPromisc = true; // Set the boolean value isPromisc as true
optionLength = dsrOption->Process (p, dsrPacket, m_mainAddress, source, ipv4Header, nextHeader, isPromisc);
return true;
}
}
}
return false;
}
void
DsrRouting::PacketNewRoute (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address destination,
uint8_t protocol)
{
NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol);
// Look up routes for the specific destination
RouteCacheEntry toDst;
bool findRoute = m_routeCache->LookupRoute (destination, toDst);
// Queue the packet if there is no route pre-existing
if (!findRoute)
{
NS_LOG_INFO (Simulator::Now ().GetSeconds ()
<< "s " << m_mainAddress << " there is no route for this packet, queue the packet");
Ptr<Packet> p = packet->Copy ();
SendBuffEntry newEntry (p, destination, m_sendBufferTimeout, protocol); // Create a new entry for send buffer
bool result = m_sendBuffer.Enqueue (newEntry); // Enqueue the packet in send buffer
if (result)
{
NS_LOG_INFO (Simulator::Now ().GetSeconds ()
<< "s Add packet PID: " << packet->GetUid () << " to queue. Packet: " << *packet);
NS_LOG_LOGIC ("Send RREQ to" << destination);
if ((m_addressReqTimer.find (destination) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (destination) == m_nonPropReqTimer.end ()))
{
/*
* Call the send request function, it will update the request table entry and ttl there
*/
SendInitialRequest (source, destination, protocol);
}
}
}
else
{
Ptr<Packet> cleanP = packet->Copy ();
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (2);
dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
DsrOptionSRHeader sourceRoute;
std::vector<Ipv4Address> nodeList = toDst.GetVector (); // Get the route from the route entry we found
Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList); // Get the next hop address for the route
if (nextHop == "0.0.0.0")
{
PacketNewRoute (cleanP, source, destination, protocol);
return;
}
uint8_t salvage = 0;
sourceRoute.SetNodesAddress (nodeList); // Save the whole route in the source route header of the packet
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (nodeList);
}
sourceRoute.SetSegmentsLeft ((nodeList.size () - 2)); // The segmentsLeft field will indicate the hops to go
sourceRoute.SetSalvage (salvage);
uint8_t length = sourceRoute.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
dsrRoutingHeader.AddDsrOption (sourceRoute);
cleanP->AddHeader (dsrRoutingHeader);
// Send the data packet out before schedule the next packet transmission
SendPacket (cleanP, source, nextHop, protocol);
Ptr<const Packet> mtP = cleanP->Copy ();
SetRoute (nextHop, m_mainAddress);
// Put the data packet in the maintenance queue for data packet retransmission
MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*Ipv4Address=*/ m_mainAddress, /*nextHop=*/ nextHop,
/*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
/*SegsLeft=*/nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
bool result = m_maintainBuffer.Enqueue (newEntry); // Enqueue the packet the the maintenance buffer
if (result)
{
NetworkKey networkKey;
networkKey.m_ackId = newEntry.GetAckId ();
networkKey.m_ourAdd = newEntry.GetOurAdd ();
networkKey.m_nextHop = newEntry.GetNextHop ();
networkKey.m_source = newEntry.GetSrc ();
networkKey.m_destination = newEntry.GetDst ();
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = newEntry.GetSrc ();
passiveKey.m_destination = newEntry.GetDst ();
passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
m_addressForwardCnt[networkKey] = 0;
m_passiveCnt[passiveKey] = 0;
if (nextHop != destination)
{
SchedulePassivePacketRetry (newEntry, false, protocol);
}
else
{
// This is the first network retry
ScheduleNetworkPacketRetry (newEntry, true, protocol);
}
}
}
}
void
DsrRouting::SendUnreachError (Ipv4Address errorHop, Ipv4Address destination, Ipv4Address originalDst, uint8_t salvage, uint8_t protocol)
{
NS_LOG_FUNCTION (this << errorHop << destination << originalDst << (uint32_t)salvage << (uint32_t)protocol);
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
DsrOptionRerrUnreachHeader rerrUnreachHeader;
rerrUnreachHeader.SetErrorType (1);
rerrUnreachHeader.SetErrorSrc (m_mainAddress);
rerrUnreachHeader.SetUnreachNode (errorHop);
rerrUnreachHeader.SetErrorDst (destination);
rerrUnreachHeader.SetOriginalDst (originalDst);
rerrUnreachHeader.SetSalvage (salvage); // Set the value about whether to salvage a packet or not
uint8_t rerrLength = rerrUnreachHeader.GetLength ();
RouteCacheEntry toDst;
bool findRoute = m_routeCache->LookupRoute (destination, toDst);
// Queue the packet if there is no route pre-existing
Ptr<Packet> newPacket = Create<Packet> ();
if (!findRoute)
{
NS_LOG_INFO (Simulator::Now ().GetSeconds ()
<< "s " << m_mainAddress << " there is no route for this packet, queue the packet");
dsrRoutingHeader.SetPayloadLength (rerrLength + 2);
dsrRoutingHeader.AddDsrOption (rerrUnreachHeader);
newPacket->AddHeader (dsrRoutingHeader);
Ptr<Packet> p = newPacket->Copy ();
// Save the error packet in the error buffer
ErrorBuffEntry newEntry (p, destination, m_mainAddress, errorHop, m_sendBufferTimeout, protocol);
bool result = m_errorBuffer.Enqueue (newEntry); // Enqueue the packet in send buffer
if (result)
{
NS_LOG_INFO (Simulator::Now ().GetSeconds ()
<< "s Add packet PID: " << p->GetUid () << " to queue. Packet: " << *p);
NS_LOG_LOGIC ("Send RREQ to" << destination);
if ((m_addressReqTimer.find (destination) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (destination) == m_nonPropReqTimer.end ()))
{
NS_LOG_DEBUG ("When there is no existing route request for " << destination << ", initialize one");
/*
* Call the send request function, it will update the request table entry and ttl there
*/
SendInitialRequest (m_mainAddress, destination, protocol);
}
}
}
else
{
std::vector<Ipv4Address> nodeList = toDst.GetVector ();
Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);
if (nextHop == "0.0.0.0")
{
NS_LOG_DEBUG ("The route is not right");
PacketNewRoute (newPacket, m_mainAddress, destination, protocol);
return;
}
DsrOptionSRHeader sourceRoute;
sourceRoute.SetNodesAddress (nodeList);
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (nodeList);
}
sourceRoute.SetSegmentsLeft ((nodeList.size () - 2));
uint8_t srLength = sourceRoute.GetLength ();
uint8_t length = (srLength + rerrLength);
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
dsrRoutingHeader.AddDsrOption (rerrUnreachHeader);
dsrRoutingHeader.AddDsrOption (sourceRoute);
newPacket->AddHeader (dsrRoutingHeader);
SetRoute (nextHop, m_mainAddress);
Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
m_ipv4Route->SetOutputDevice (dev);
NS_LOG_INFO ("Send the packet to the next hop address " << nextHop << " from " << m_mainAddress << " with the size " << newPacket->GetSize());
uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (newPacket, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
}
void
DsrRouting::ForwardErrPacket (DsrOptionRerrUnreachHeader &rerr,
DsrOptionSRHeader &sourceRoute,
Ipv4Address nextHop,
uint8_t protocol,
Ptr<Ipv4Route> route)
{
NS_LOG_FUNCTION (this << rerr << sourceRoute << nextHop << (uint32_t)protocol << route);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (rerr.GetErrorSrc ()));
dsrRoutingHeader.SetDestId (GetIDfromIP (rerr.GetErrorDst ()));
uint8_t length = (sourceRoute.GetLength () + rerr.GetLength ());
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
dsrRoutingHeader.AddDsrOption (rerr);
dsrRoutingHeader.AddDsrOption (sourceRoute);
Ptr<Packet> packet = Create<Packet> ();
packet->AddHeader (dsrRoutingHeader);
Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
route->SetOutputDevice (dev);
uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (packet, m_mainAddress, nextHop, Simulator::Now (), route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
void
DsrRouting::Send (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address destination,
uint8_t protocol,
Ptr<Ipv4Route> route)
{
NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol << route);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
if (protocol == 1)
{
NS_LOG_INFO ("Drop packet. Not handling ICMP packet for now");
}
else
{
// Look up routes for the specific destination
RouteCacheEntry toDst;
bool findRoute = m_routeCache->LookupRoute (destination, toDst);
// Queue the packet if there is no route pre-existing
if (!findRoute)
{
NS_LOG_INFO (Simulator::Now ().GetSeconds ()
<< "s " << m_mainAddress << " there is no route for this packet, queue the packet");
Ptr<Packet> p = packet->Copy ();
SendBuffEntry newEntry (p, destination, m_sendBufferTimeout, protocol); // Create a new entry for send buffer
bool result = m_sendBuffer.Enqueue (newEntry); // Enqueue the packet in send buffer
if (result)
{
NS_LOG_INFO (Simulator::Now ().GetSeconds ()
<< "s Add packet PID: " << packet->GetUid () << " to queue. Packet: " << *packet);
NS_LOG_LOGIC ("Send RREQ to " << destination);
// Only when there is no existing route request timer when new route request is scheduled
if ((m_addressReqTimer.find (destination) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (destination) == m_nonPropReqTimer.end ()))
{
NS_LOG_DEBUG ("When there is no existing route request for " << destination << ", initialize one");
/*
* Call the send request function, it will update the request table entry and ttl there
*/
SendInitialRequest (source, destination, protocol);
}
else
{
NS_LOG_DEBUG ("There is existing route request timer and the request count here " << m_rreqTable->GetRreqCnt (destination));
}
}
}
else
{
Ptr<Packet> cleanP = packet->Copy ();
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (2);
dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
DsrOptionSRHeader sourceRoute;
std::vector<Ipv4Address> nodeList = toDst.GetVector (); // Get the route from the route entry we found
Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList); // Get the next hop address for the route
if (nextHop == "0.0.0.0")
{
PacketNewRoute (cleanP, source, destination, protocol);
return;
}
uint8_t salvage = 0;
sourceRoute.SetNodesAddress (nodeList); // Save the whole route in the source route header of the packet
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (nodeList);
}
sourceRoute.SetSegmentsLeft ((nodeList.size () - 2)); // The segmentsLeft field will indicate the hops to go
sourceRoute.SetSalvage (salvage);
uint8_t length = sourceRoute.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
dsrRoutingHeader.AddDsrOption (sourceRoute);
cleanP->AddHeader (dsrRoutingHeader);
// Send the data packet out before schedule the next packet transmission
SendPacket (cleanP, source, nextHop, protocol);
Ptr<const Packet> mtP = cleanP->Copy ();
NS_LOG_DEBUG ("maintain packet size " << cleanP->GetSize());
// Put the data packet in the maintenance queue for data packet retransmission
MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
/*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
/*SegsLeft=*/nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
bool result = m_maintainBuffer.Enqueue (newEntry); // Enqueue the packet the the maintenance buffer
if (result)
{
NetworkKey networkKey;
networkKey.m_ackId = newEntry.GetAckId ();
networkKey.m_ourAdd = newEntry.GetOurAdd ();
networkKey.m_nextHop = newEntry.GetNextHop ();
networkKey.m_source = newEntry.GetSrc ();
networkKey.m_destination = newEntry.GetDst ();
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = newEntry.GetSrc ();
passiveKey.m_destination = newEntry.GetDst ();
passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
m_addressForwardCnt[networkKey] = 0;
m_passiveCnt[passiveKey] = 0;
if (nextHop != destination)
{
SchedulePassivePacketRetry (newEntry, false, protocol);
}
else
{
// This is the first network retry
ScheduleNetworkPacketRetry (newEntry, true, protocol);
}
}
// Try to send packet from *previously* queued entries from send buffer if any
Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
&DsrRouting::SendPacketFromBuffer,this,sourceRoute,nextHop,protocol);
}
}
}
uint16_t
DsrRouting::AddAckReqHeader (Ptr<Packet>& packet, Ipv4Address nextHop)
{
NS_LOG_FUNCTION (this << packet << nextHop);
// This packet is used to peek option type
Ptr<Packet> dsrP = packet->Copy ();
Ptr<Packet> tmpP = packet->Copy ();
DsrRoutingHeader dsrRoutingHeader;
dsrP->RemoveHeader (dsrRoutingHeader); // Remove the DSR header in whole
uint8_t protocol = dsrRoutingHeader.GetNextHeader ();
uint32_t sourceId = dsrRoutingHeader.GetSourceId ();
uint32_t destinationId = dsrRoutingHeader.GetDestId ();
uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
tmpP->RemoveAtStart (offset); // Here the processed size is 8 bytes, which is the fixed sized extension header
// Get the number of routers' address field
uint8_t buf[2];
tmpP->CopyData (buf, sizeof(buf));
uint8_t numberAddress = (buf[1] - 2) / 4;
DsrOptionSRHeader sourceRoute;
sourceRoute.SetNumberAddress (numberAddress);
tmpP->RemoveHeader (sourceRoute); // this is a clean packet without any dsr involved headers
DsrOptionAckReqHeader ackReq;
m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
ackReq.SetAckId (m_ackId);
uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
DsrRoutingHeader newDsrRoutingHeader;
newDsrRoutingHeader.SetNextHeader (protocol);
newDsrRoutingHeader.SetMessageType (2);
newDsrRoutingHeader.SetSourceId (sourceId);
newDsrRoutingHeader.SetDestId (destinationId);
newDsrRoutingHeader.SetPayloadLength (length + 4);
newDsrRoutingHeader.AddDsrOption (sourceRoute);
newDsrRoutingHeader.AddDsrOption (ackReq);
dsrP->AddHeader (newDsrRoutingHeader);
// give the dsrP value to packet and then return
packet = dsrP;
return m_ackId;
}
void
DsrRouting::SendPacket (Ptr<Packet> packet, Ipv4Address source, Ipv4Address nextHop, uint8_t protocol)
{
NS_LOG_FUNCTION (this << packet << source << nextHop << (uint32_t)protocol);
// Send out the data packet
m_ipv4Route = SetRoute (nextHop, m_mainAddress);
Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
m_ipv4Route->SetOutputDevice (dev);
uint32_t priority = GetPriority (DSR_DATA_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (packet, source, nextHop, Simulator::Now (), m_ipv4Route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
void
DsrRouting::Scheduler (uint32_t priority)
{
NS_LOG_FUNCTION (this);
PriorityScheduler (priority, true);
}
void
DsrRouting::PriorityScheduler (uint32_t priority, bool continueWithFirst)
{
NS_LOG_FUNCTION (this << priority << continueWithFirst);
NS_LOG_DEBUG ("Scheduler looking for packets in network queue");
uint32_t numPriorities;
if (continueWithFirst)
{
numPriorities = 0;
}
else
{
numPriorities = priority;
}
// priorities range from 0 to m_numPriorityQueues, with 0 as the highest priority
for (uint32_t i = priority; numPriorities < m_numPriorityQueues; numPriorities++)
{
std::map<uint32_t, Ptr<DsrNetworkQueue> >::iterator q = m_priorityQueue.find (i);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = q->second;
uint32_t queueSize = dsrNetworkQueue->GetSize ();
if (queueSize == 0)
{
if ((i == (m_numPriorityQueues - 1)) && continueWithFirst)
{
i = 0;
}
else
{
i++;
}
}
else
{
uint32_t totalQueueSize;
for (std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator j = m_priorityQueue.begin (); j != m_priorityQueue.end (); j++)
{
NS_LOG_DEBUG ("The size of the network queue for " << j->first << " is " << j->second->GetSize());
totalQueueSize += j->second->GetSize ();
NS_LOG_DEBUG ("And the total size is " << totalQueueSize);
}
if (totalQueueSize > 5)
{
// Here the queue size is larger than 5, we need to increase the retransmission timer for each packet in the network queue
IncreaseRetransTimer ();
}
DsrNetworkQueueEntry newEntry;
dsrNetworkQueue->Dequeue (newEntry);
if (SendRealDown (newEntry))
{
NS_LOG_DEBUG("Packet sent by Dsr. Calling PriorityScheduler after some time");
//packet was successfully sent down. call scheduler after some time
Simulator::Schedule (MicroSeconds (UniformVariable ().GetInteger (0, 1000)),
&DsrRouting::PriorityScheduler,this, i, false);
}
else
{
// packet was dropped by Dsr. Call scheduler immediately so that we can
// send another packet immediately.
NS_LOG_DEBUG("Packet dropped by Dsr. Calling PriorityScheduler immediately");
Simulator::Schedule (Seconds (0), &DsrRouting::PriorityScheduler, this, i, false);
}
if ((i == (m_numPriorityQueues - 1)) && continueWithFirst)
{
i = 0;
}
else
{
i++;
}
}
}
}
void
DsrRouting::IncreaseRetransTimer ()
{
NS_LOG_FUNCTION (this);
// We may want to get the queue first and then we need to save a vector of the entries here and then find
uint32_t priority = GetPriority (DSR_DATA_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
std::vector<DsrNetworkQueueEntry> newNetworkQueue = dsrNetworkQueue->GetQueue ();
for (std::vector<DsrNetworkQueueEntry>::iterator i = newNetworkQueue.begin (); i != newNetworkQueue.end (); i++)
{
Ipv4Address nextHop = i->GetNextHopAddress ();
for (std::map<NetworkKey, Timer>::iterator j = m_addressForwardTimer.begin (); j != m_addressForwardTimer.end (); j++)
{
if (nextHop == j->first.m_nextHop)
{
NS_LOG_DEBUG ("The network delay left is " << j->second.GetDelayLeft());
j->second.SetDelay (j->second.GetDelayLeft () + m_retransIncr);
NS_LOG_DEBUG ("The new network delay time is " << j->second.GetDelayLeft ());
}
}
}
}
bool
DsrRouting::SendRealDown (DsrNetworkQueueEntry & newEntry)
{
NS_LOG_FUNCTION (this);
Ipv4Address source = newEntry.GetSourceAddress ();
Ipv4Address nextHop = newEntry.GetNextHopAddress ();
Ptr<Packet> packet = newEntry.GetPacket ()->Copy ();
Ptr<Ipv4Route> route = newEntry.GetIpv4Route ();
m_downTarget (packet, source, nextHop, GetProtocolNumber(), route);
return true;
}
void
DsrRouting::SendPacketFromBuffer (DsrOptionSRHeader const &sourceRoute, Ipv4Address nextHop, uint8_t protocol)
{
NS_LOG_FUNCTION (this << nextHop << (uint32_t)protocol);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
// Reconstruct the route and Retransmit the data packet
std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
Ipv4Address destination = nodeList.back ();
Ipv4Address source = nodeList.front (); // Get the source address
NS_LOG_INFO ("The nexthop address " << nextHop << " the source " << source << " the destination " << destination);
/*
* Here we try to find data packet from send buffer, if packet with this destiantion found, send it out
*/
if (m_sendBuffer.Find (destination))
{
SendBuffEntry entry;
if (m_sendBuffer.Dequeue (destination, entry))
{
Ptr<Packet> packet = entry.GetPacket ()->Copy ();
NS_LOG_DEBUG ("The queued packet size " << packet->GetSize ());
NS_LOG_DEBUG ("This is the data packet");
Ptr<Packet> p = packet->Copy (); // get a copy of the packet
// Set the source route option
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (2);
dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
uint8_t length = sourceRoute.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
dsrRoutingHeader.AddDsrOption (sourceRoute);
p->AddHeader (dsrRoutingHeader);
// Send the data packet out before schedule the next packet transmission
NS_LOG_DEBUG ("Send out the data packet");
SendPacket (p, source, nextHop, protocol);
Ptr<const Packet> mtP = p->Copy ();
// Put the data packet in the maintenance queue for data packet retransmission
MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
/*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
/*SegsLeft=*/nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
bool result = m_maintainBuffer.Enqueue (newEntry); // Enqueue the packet the the maintenance buffer
if (result)
{
NetworkKey networkKey;
networkKey.m_ackId = newEntry.GetAckId ();
networkKey.m_ourAdd = newEntry.GetOurAdd ();
networkKey.m_nextHop = newEntry.GetNextHop ();
networkKey.m_source = newEntry.GetSrc ();
networkKey.m_destination = newEntry.GetDst ();
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = newEntry.GetSrc ();
passiveKey.m_destination = newEntry.GetDst ();
passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
m_addressForwardCnt[networkKey] = 0;
m_passiveCnt[passiveKey] = 0;
if (nextHop != destination)
{
SchedulePassivePacketRetry (newEntry, false, protocol);
}
else
{
// This is the first network retry
ScheduleNetworkPacketRetry (newEntry, true, protocol);
}
}
if (m_sendBuffer.GetSize () != 0 && m_sendBuffer.Find (destination))
{
NS_LOG_DEBUG ("Schedule sending the next packet in send buffer");
Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
&DsrRouting::SendPacketFromBuffer,this,sourceRoute,nextHop,protocol);
}
}
else
{
NS_LOG_DEBUG ("All queued packets are out-dated for the destination in send buffer");
}
}
/*
* Here we try to find data packet from send buffer, if packet with this destiantion found, send it out
*/
else if (m_errorBuffer.Find (destination))
{
ErrorBuffEntry entry;
if (m_errorBuffer.Dequeue (destination, entry))
{
Ptr<Packet> packet = entry.GetPacket ()->Copy ();
NS_LOG_DEBUG ("The queued packet size " << packet->GetSize ());
DsrRoutingHeader dsrRoutingHeader;
Ptr<Packet> copyP = packet->Copy ();
Ptr<Packet> dsrPacket = packet->Copy ();
dsrPacket->RemoveHeader (dsrRoutingHeader);
uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
copyP->RemoveAtStart (offset); // Here the processed size is 8 bytes, which is the fixed sized extension header
/*
* Peek data to get the option type as well as length and segmentsLeft field
*/
uint32_t size = copyP->GetSize ();
uint8_t *data = new uint8_t[size];
copyP->CopyData (data, size);
uint8_t optionType = 0;
optionType = *(data);
NS_LOG_DEBUG ("The option type value in send packet " << (uint32_t)optionType);
if (optionType == 3)
{
NS_LOG_DEBUG ("The packet is error packet");
Ptr<dsr::DsrOptions> dsrOption;
DsrOptionHeader dsrOptionHeader;
uint8_t errorType = *(data + 2);
NS_LOG_DEBUG ("The error type");
if (errorType == 1)
{
NS_LOG_DEBUG ("The packet is route error unreach packet");
DsrOptionRerrUnreachHeader rerr;
copyP->RemoveHeader (rerr);
NS_ASSERT (copyP->GetSize () == 0);
uint8_t length = (sourceRoute.GetLength () + rerr.GetLength ());
DsrOptionRerrUnreachHeader newUnreach;
newUnreach.SetErrorType (1);
newUnreach.SetErrorSrc (rerr.GetErrorSrc ());
newUnreach.SetUnreachNode (rerr.GetUnreachNode ());
newUnreach.SetErrorDst (rerr.GetErrorDst ());
newUnreach.SetOriginalDst (rerr.GetOriginalDst ());
newUnreach.SetSalvage (rerr.GetSalvage ()); // Set the value about whether to salvage a packet or not
std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
DsrRoutingHeader newRoutingHeader;
newRoutingHeader.SetNextHeader (protocol);
newRoutingHeader.SetMessageType (1);
newRoutingHeader.SetSourceId (GetIDfromIP (rerr.GetErrorSrc ()));
newRoutingHeader.SetDestId (GetIDfromIP (rerr.GetErrorDst ()));
newRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
newRoutingHeader.AddDsrOption (newUnreach);
newRoutingHeader.AddDsrOption (sourceRoute);
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (nodeList);
}
SetRoute (nextHop, m_mainAddress);
Ptr<Packet> newPacket = Create<Packet> ();
newPacket->AddHeader (newRoutingHeader); // Add the extension header with rerr and sourceRoute attached to it
Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
m_ipv4Route->SetOutputDevice (dev);
uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (newPacket, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
}
if (m_errorBuffer.GetSize () != 0 && m_errorBuffer.Find (destination))
{
NS_LOG_DEBUG ("Schedule sending the next packet in send buffer");
Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
&DsrRouting::SendPacketFromBuffer,this,sourceRoute,nextHop,protocol);
}
}
}
else
{
NS_LOG_DEBUG ("Packet not found in either the send or error buffer");
}
}
bool
DsrRouting::FindSamePackets (Ptr<Packet> packet, Ipv4Address source, Ipv4Address destination,
uint8_t segsLeft)
{
NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)segsLeft);
Ptr<Packet> p = packet->Copy ();
// Here the segments left value need to plus one to check the earlier hop maintain buffer entry
MaintainBuffEntry newEntry;
newEntry.SetPacket (p);
newEntry.SetSrc (source);
newEntry.SetDst (destination);
newEntry.SetAckId (0);
newEntry.SetSegsLeft (segsLeft + 1);
if (m_maintainBuffer.PromiscEqual (newEntry))
{
// The PromiscEqual function will remove the maintain buffer entry if equal value found
// It only compares the source and destination address, ackId, and the segments left value
CancelPassivePacketTimer (newEntry);
return true;
}
return false;
}
void
DsrRouting::CallCancelPacketTimer (uint16_t ackId, Ipv4Header const& ipv4Header, Ipv4Address realSrc, Ipv4Address realDst)
{
NS_LOG_FUNCTION (this << (uint32_t)ackId << ipv4Header << realSrc << realDst);
Ipv4Address sender = ipv4Header.GetDestination ();
Ipv4Address receiver = ipv4Header.GetSource ();
/*
* Create a packet to fill maintenance buffer, not used to compare
* The reason is ack header doesn't have the original packet copy
*/
Ptr<Packet> mainP = Create<Packet> ();
MaintainBuffEntry newEntry (/*Packet=*/ mainP, /*ourAddress=*/ sender, /*nextHop=*/ receiver,
/*source=*/ realSrc, /*destination=*/ realDst, /*ackId=*/ ackId,
/*SegsLeft=*/0, /*expire time=*/ Simulator::Now ());
CancelNetworkPacketTimer (newEntry);
}
void
DsrRouting::CancelNetworkPacketTimer (MaintainBuffEntry & mb)
{
NS_LOG_FUNCTION (this);
NetworkKey networkKey;
networkKey.m_ackId = mb.GetAckId ();
networkKey.m_ourAdd = mb.GetOurAdd ();
networkKey.m_nextHop = mb.GetNextHop ();
networkKey.m_source = mb.GetSrc ();
networkKey.m_destination = mb.GetDst ();
/*
* Here we have found the entry for send retries, so we get the value and increase it by one
*/
m_addressForwardCnt[networkKey] = 0;
m_addressForwardCnt.erase (networkKey);
NS_LOG_INFO ("ackId " << mb.GetAckId () << " ourAdd " << mb.GetOurAdd () << " nextHop " << mb.GetNextHop ()
<< " source " << mb.GetSrc () << " destination " << mb.GetDst ()
<< " segsLeft " << (uint32_t)mb.GetSegsLeft ()
);
// Find the network acknowledgment timer
std::map<NetworkKey, Timer>::const_iterator i =
m_addressForwardTimer.find (networkKey);
if (i == m_addressForwardTimer.end ())
{
NS_LOG_INFO ("did not find the packet timer");
}
else
{
NS_LOG_INFO ("did find the packet timer");
/*
* Schedule the packet retry
* Push back the nextHop, source, destination address
*/
m_addressForwardTimer[networkKey].Cancel ();
m_addressForwardTimer[networkKey].Remove ();
if (m_addressForwardTimer[networkKey].IsRunning ())
{
NS_LOG_INFO ("Timer not canceled");
}
m_addressForwardTimer.erase (networkKey);
}
// Erase the maintenance entry
// yet this does not check the segments left value here
if (m_maintainBuffer.NetworkEqual (mb))
{
NS_LOG_INFO ("Remove same maintenance buffer entry based on network acknowledgment");
}
}
void
DsrRouting::CancelPassivePacketTimer (MaintainBuffEntry & mb)
{
NS_LOG_FUNCTION (this);
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = mb.GetSrc ();
passiveKey.m_destination = mb.GetDst ();
passiveKey.m_segsLeft = mb.GetSegsLeft ();
m_passiveCnt[passiveKey] = 0;
m_passiveCnt.erase (passiveKey);
// Find the passive acknowledgment timer
std::map<PassiveKey, Timer>::const_iterator j =
m_passiveAckTimer.find (passiveKey);
if (j == m_passiveAckTimer.end ())
{
NS_LOG_INFO ("did not find the passive timer");
}
else
{
NS_LOG_INFO ("find the passive timer");
/*
* Cancel passive acknowledgment timer
*/
m_passiveAckTimer[passiveKey].Cancel ();
m_passiveAckTimer[passiveKey].Remove ();
if (m_passiveAckTimer[passiveKey].IsRunning ())
{
NS_LOG_INFO ("Timer not canceled");
}
m_passiveAckTimer.erase (passiveKey);
}
}
void
DsrRouting::CancelPacketTimerNextHop (Ipv4Address nextHop, uint8_t protocol)
{
NS_LOG_FUNCTION (this << nextHop << (uint32_t)protocol);
MaintainBuffEntry entry;
if (m_maintainBuffer.Dequeue (nextHop, entry))
{
Ptr<const Packet> packet = entry.GetPacket ()->Copy ();
Ipv4Address source = entry.GetSrc ();
Ipv4Address destination = entry.GetDst ();
/*
* Cancel the packet timer and then salvage the data packet
*/
CancelNetworkPacketTimer (entry);
SalvagePacket (packet, source, destination, protocol);
if (m_maintainBuffer.GetSize () && m_maintainBuffer.Find (nextHop))
{
NS_LOG_INFO ("Cancel the packet timer for next maintenance entry");
Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
&DsrRouting::CancelPacketTimerNextHop,this,nextHop,protocol);
}
}
else
{
NS_LOG_INFO ("Maintenance buffer entry not found");
}
}
void
DsrRouting::SalvagePacket (Ptr<const Packet> packet, Ipv4Address source, Ipv4Address dst, uint8_t protocol)
{
NS_LOG_FUNCTION (this << packet << source << dst << (uint32_t)protocol);
// Create two copies of packet
Ptr<Packet> p = packet->Copy ();
Ptr<Packet> newPacket = packet->Copy ();
// Remove the routing header in a whole to get a clean packet
DsrRoutingHeader dsrRoutingHeader;
p->RemoveHeader (dsrRoutingHeader);
// Remove offset of dsr routing header
uint8_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
newPacket->RemoveAtStart (offset);
// Get the number of routers' address field
uint8_t buf[2];
newPacket->CopyData (buf, sizeof(buf));
uint8_t numberAddress = (buf[1] - 2) / 4;
DsrOptionSRHeader sourceRoute;
sourceRoute.SetNumberAddress (numberAddress);
newPacket->RemoveHeader (sourceRoute);
uint8_t salvage = sourceRoute.GetSalvage ();
/*
* Look in the route cache for other routes for this destination
*/
RouteCacheEntry toDst;
bool findRoute = m_routeCache->LookupRoute (dst, toDst);
if (findRoute && (salvage < m_maxSalvageCount))
{
NS_LOG_DEBUG ("We have found a route for the packet");
DsrRoutingHeader newDsrRoutingHeader;
newDsrRoutingHeader.SetNextHeader (protocol);
newDsrRoutingHeader.SetMessageType (2);
newDsrRoutingHeader.SetSourceId (GetIDfromIP (source));
newDsrRoutingHeader.SetDestId (GetIDfromIP (dst));
std::vector<Ipv4Address> nodeList = toDst.GetVector (); // Get the route from the route entry we found
Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList); // Get the next hop address for the route
if (nextHop == "0.0.0.0")
{
PacketNewRoute (p, source, dst, protocol);
return;
}
// Increase the salvage count by 1
salvage++;
DsrOptionSRHeader sourceRoute;
sourceRoute.SetSalvage (salvage);
sourceRoute.SetNodesAddress (nodeList); // Save the whole route in the source route header of the packet
sourceRoute.SetSegmentsLeft ((nodeList.size () - 2)); // The segmentsLeft field will indicate the hops to go
DsrOptionAckReqHeader ackReq;
m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
ackReq.SetAckId (m_ackId);
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (nodeList);
}
uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
NS_LOG_INFO ("length of source route header " << (uint32_t)(sourceRoute.GetLength ())
<< " length of ack request header " << (uint32_t)(ackReq.GetLength ()));
newDsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
newDsrRoutingHeader.AddDsrOption (sourceRoute);
newDsrRoutingHeader.AddDsrOption (ackReq);
p->AddHeader (newDsrRoutingHeader);
SetRoute (nextHop, m_mainAddress);
Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
m_ipv4Route->SetOutputDevice (dev);
// Send out the data packet
uint32_t priority = GetPriority (DSR_DATA_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (p, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
/*
* Mark the next hop address in blacklist
*/
// NS_LOG_DEBUG ("Save the next hop node in blacklist");
// m_rreqTable->MarkLinkAsUnidirectional (nextHop, m_blacklistTimeout);
}
else
{
NS_LOG_DEBUG ("Will not salvage this packet, silently drop");
}
}
void
DsrRouting::SchedulePassivePacketRetry (MaintainBuffEntry & mb,
bool onlyPassive,
uint8_t protocol)
{
NS_LOG_FUNCTION (this << onlyPassive << (uint32_t)protocol);
Ipv4Address nextHop = mb.GetNextHop ();
Ipv4Address source = mb.GetSrc ();
Ipv4Address dst = mb.GetDst ();
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = mb.GetSrc ();
passiveKey.m_destination = mb.GetDst ();
passiveKey.m_segsLeft = mb.GetSegsLeft ();
if (m_passiveAckTimer.find (passiveKey) == m_passiveAckTimer.end ())
{
Timer timer (Timer::CANCEL_ON_DESTROY);
m_passiveAckTimer[passiveKey] = timer;
}
NS_LOG_DEBUG ("The passive acknowledgment option for data packet");
m_passiveAckTimer[passiveKey].SetFunction (&DsrRouting::PassiveScheduleTimerExpire, this);
m_passiveAckTimer[passiveKey].Remove ();
m_passiveAckTimer[passiveKey].SetArguments (mb, onlyPassive, protocol);
m_passiveAckTimer[passiveKey].Schedule (m_passiveAckTimeout);
}
void
DsrRouting::ScheduleNetworkPacketRetry (MaintainBuffEntry & mb,
bool isFirst,
uint8_t protocol)
{
Ptr<Packet> p = Create<Packet> ();
Ptr<Packet> dsrP = Create<Packet> ();
// The new entry will be used for retransmission
NetworkKey networkKey;
Ipv4Address nextHop = mb.GetNextHop ();
Ipv4Address source = mb.GetSrc ();
Ipv4Address dst = mb.GetDst ();
NS_LOG_DEBUG ("is the first retry or not " << isFirst);
if (isFirst)
{
// This is the very first network packet retry
p = mb.GetPacket ()->Copy ();
// Here we add the ack request header to the data packet for network acknowledgement
uint16_t ackId = AddAckReqHeader (p, nextHop);
dsrP = p->Copy ();
MaintainBuffEntry newEntry = mb;
// The function AllEqual will find the exact entry and delete it if found
m_maintainBuffer.AllEqual (mb);
newEntry.SetPacket (dsrP);
newEntry.SetAckId (ackId);
newEntry.SetExpireTime (m_maxMaintainTime);
networkKey.m_ackId = newEntry.GetAckId ();
networkKey.m_ourAdd = newEntry.GetOurAdd ();
networkKey.m_nextHop = newEntry.GetNextHop ();
networkKey.m_source = newEntry.GetSrc ();
networkKey.m_destination = newEntry.GetDst ();
m_addressForwardCnt[networkKey] = 0;
m_maintainBuffer.Enqueue (newEntry);
if (m_addressForwardTimer.find (networkKey) == m_addressForwardTimer.end ())
{
Timer timer (Timer::CANCEL_ON_DESTROY);
m_addressForwardTimer[networkKey] = timer;
}
// After m_tryPassiveAcks, schedule the packet retransmission using network acknowledgment option
m_addressForwardTimer[networkKey].SetFunction (&DsrRouting::NetworkScheduleTimerExpire, this);
m_addressForwardTimer[networkKey].Remove ();
m_addressForwardTimer[networkKey].SetArguments (newEntry, protocol);
NS_LOG_DEBUG ("The packet retries time for " << newEntry.GetAckId() << " is " << m_sendRetries
<< " and the delay time is " << Time (2 * m_nodeTraversalTime));
// Back-off mechanism
m_addressForwardTimer[networkKey].Schedule (Time (2 * m_nodeTraversalTime));
}
else
{
networkKey.m_ackId = mb.GetAckId ();
networkKey.m_ourAdd = mb.GetOurAdd ();
networkKey.m_nextHop = mb.GetNextHop ();
networkKey.m_source = mb.GetSrc ();
networkKey.m_destination = mb.GetDst ();
/*
* Here we have found the entry for send retries, so we get the value and increase it by one
*/
m_sendRetries = m_addressForwardCnt[networkKey];
NS_LOG_DEBUG ("The packet retry we have done " << m_sendRetries);
p = mb.GetPacket ()->Copy ();
dsrP = mb.GetPacket ()->Copy ();
NS_LOG_DEBUG ("The packet with dsr header " << dsrP->GetSize());
networkKey.m_ackId = mb.GetAckId ();
networkKey.m_ourAdd = mb.GetOurAdd ();
networkKey.m_nextHop = mb.GetNextHop ();
networkKey.m_source = mb.GetSrc ();
networkKey.m_destination = mb.GetDst ();
/*
* If a data packet has been attempted SendRetries times at the maximum TTL without
* receiving any ACK, all data packets destined for the corresponding destination SHOULD be
* dropped from the send buffer
*
* The maxMaintRexmt also needs to decrease one for the passive ack packet
*/
/*
* Check if the send retry time for a certain packet has already passed max maintenance retransmission
* time or not
*/
// After m_tryPassiveAcks, schedule the packet retransmission using network acknowledgment option
m_addressForwardTimer[networkKey].SetFunction (&DsrRouting::NetworkScheduleTimerExpire, this);
m_addressForwardTimer[networkKey].Remove ();
m_addressForwardTimer[networkKey].SetArguments (mb, protocol);
NS_LOG_DEBUG ("The packet retries time for " << mb.GetAckId() << " is " << m_sendRetries
<< " and the delay time is " << Time (2 * m_sendRetries * m_nodeTraversalTime));
// Back-off mechanism
m_addressForwardTimer[networkKey].Schedule (Time (2 * m_sendRetries * m_nodeTraversalTime));
}
}
void
DsrRouting::PassiveScheduleTimerExpire (MaintainBuffEntry & mb,
bool onlyPassive,
uint8_t protocol)
{
NS_LOG_FUNCTION (this << onlyPassive << (uint32_t)protocol);
Ipv4Address nextHop = mb.GetNextHop ();
Ipv4Address source = mb.GetSrc ();
Ipv4Address dst = mb.GetDst ();
Ptr<const Packet> packet = mb.GetPacket ();
SetRoute (nextHop, m_mainAddress);
Ptr<Packet> p = packet->Copy ();
PassiveKey pk;
pk.m_ackId = 0;
pk.m_source = mb.GetSrc ();
pk.m_destination = mb.GetDst ();
pk.m_segsLeft = mb.GetSegsLeft ();
// Cancel passive ack timer
m_passiveAckTimer[pk].Cancel ();
m_passiveAckTimer[pk].Remove ();
if (m_passiveAckTimer[pk].IsRunning ())
{
NS_LOG_DEBUG ("Timer not canceled");
}
m_passiveAckTimer.erase (pk);
// Send the data packet out before schedule the next packet transmission
SendPacket (p, source, nextHop, protocol);
// Increase the send retry times
m_passiveRetries = m_passiveCnt[pk];
if (m_passiveRetries < m_tryPassiveAcks)
{
m_passiveCnt[pk] = ++m_passiveRetries;
SchedulePassivePacketRetry (mb, onlyPassive, protocol);
}
else if (!onlyPassive)
{
// This is the first network acknowledgement retry
// Cancel the passive packet timer now and remove maintenance buffer entry for it
CancelPassivePacketTimer (mb);
ScheduleNetworkPacketRetry (mb, true, protocol);
}
else
{
// This is the end of the data retransmission retries
CancelPassivePacketTimer (mb);
// The function AllEqual will find the exact entry and delete it if found
m_maintainBuffer.AllEqual (mb);
}
}
void
DsrRouting::NetworkScheduleTimerExpire (MaintainBuffEntry & mb,
uint8_t protocol)
{
Ptr<Packet> p = mb.GetPacket ()->Copy ();
Ipv4Address source = mb.GetSrc ();
Ipv4Address nextHop = mb.GetNextHop ();
Ipv4Address dst = mb.GetDst ();
NetworkKey networkKey;
networkKey.m_ackId = mb.GetAckId ();
networkKey.m_ourAdd = mb.GetOurAdd ();
networkKey.m_nextHop = nextHop;
networkKey.m_source = source;
networkKey.m_destination = dst;
// Send the data packet out before schedule the next packet transmission
SendPacket (p, source, nextHop, protocol);
// Increase the send retry times
m_sendRetries = m_addressForwardCnt[networkKey];
NS_LOG_DEBUG ("The send retry time is " << m_sendRetries);
if (m_sendRetries >= m_maxMaintRexmt)
{
Ptr<Packet> dsrP = mb.GetPacket ()->Copy ();
// The packet retries time has exceed the max maintenance retransmission times
NS_LOG_LOGIC ("Packet transmissions to " << nextHop << " has been attempted SendRetries times for " << networkKey.m_ackId);
DsrRoutingHeader dsrRoutingHeader;
dsrP->RemoveHeader (dsrRoutingHeader); // Remove the dsr header in whole
uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
p->RemoveAtStart (offset);
// Get the number of routers' address field
uint8_t buf[2];
p->CopyData (buf, sizeof(buf));
uint8_t numberAddress = (buf[1] - 2) / 4;
NS_LOG_DEBUG ("The number of addresses " << (uint32_t)numberAddress);
DsrOptionSRHeader sourceRoute;
sourceRoute.SetNumberAddress (numberAddress);
p->RemoveHeader (sourceRoute);
std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
uint8_t salvage = sourceRoute.GetSalvage ();
Ipv4Address address1 = nodeList[1];
NS_LOG_DEBUG ("address1 " << address1);
PrintVector (nodeList);
// Delete all the routes including the links
m_routeCache->DeleteAllRoutesIncludeLink (m_mainAddress, nextHop, m_mainAddress);
/*
* If the salvage is not 0, use the first address in the route as the error dst in error header
* otherwise use the source of packet as the error destination
*/
Ipv4Address errorDst;
if (salvage)
{
errorDst = address1;
}
else
{
errorDst = source;
}
SendUnreachError (nextHop, errorDst, dst, salvage, protocol);
/*
* here we cancel the packet retransmission time for all the packets have next hop address as nextHop
* Also salvage the packet for the all the packet destined for the nextHop address
*/
CancelPacketTimerNextHop (nextHop, protocol);
}
else
{
m_addressForwardCnt[networkKey] = ++m_sendRetries;
ScheduleNetworkPacketRetry (mb, false, protocol);
}
}
void
DsrRouting::ForwardPacket (Ptr<const Packet> packet,
DsrOptionSRHeader &sourceRoute,
Ipv4Header const& ipv4Header,
Ipv4Address source,
Ipv4Address nextHop,
Ipv4Address targetAddress,
uint8_t protocol,
Ptr<Ipv4Route> route)
{
NS_LOG_FUNCTION (this << packet << sourceRoute << source << nextHop << targetAddress << (uint32_t)protocol << route);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (2);
dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
dsrRoutingHeader.SetDestId (GetIDfromIP (targetAddress));
// We get the salvage value in sourceRoute header and set it to route error header if triggered error
Ptr<Packet> p = packet->Copy ();
uint8_t length = sourceRoute.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
dsrRoutingHeader.AddDsrOption (sourceRoute);
p->AddHeader (dsrRoutingHeader);
// Send the data packet out before schedule the next packet transmission
SendPacket (p, source, nextHop, protocol);
Ptr<const Packet> mtP = p->Copy ();
MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
/*source=*/ source, /*destination=*/ targetAddress,
/*ackId=*/ m_ackId, /*SegsLeft=*/sourceRoute.GetSegmentsLeft(), /*expire time=*/ m_maxMaintainTime);
bool result = m_maintainBuffer.Enqueue (newEntry);
if (result)
{
NetworkKey networkKey;
networkKey.m_ackId = newEntry.GetAckId ();
networkKey.m_ourAdd = newEntry.GetOurAdd ();
networkKey.m_nextHop = newEntry.GetNextHop ();
networkKey.m_source = newEntry.GetSrc ();
networkKey.m_destination = newEntry.GetDst ();
PassiveKey passiveKey;
passiveKey.m_ackId = 0;
passiveKey.m_source = newEntry.GetSrc ();
passiveKey.m_destination = newEntry.GetDst ();
passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
m_addressForwardCnt[networkKey] = 0;
m_passiveCnt[passiveKey] = 0;
if (nextHop != targetAddress)
{
SchedulePassivePacketRetry (newEntry, false, protocol);
}
else
{
// This is the first network retry
ScheduleNetworkPacketRetry (newEntry, true, protocol);
}
}
}
void
DsrRouting::SendInitialRequest (Ipv4Address source,
Ipv4Address destination,
uint8_t protocol)
{
NS_LOG_FUNCTION (this << source << destination << (uint32_t)protocol);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
Ptr<Packet> packet = Create<Packet> ();
// Create an empty Ipv4 route ptr
Ptr<Ipv4Route> route;
/*
* Construct the route request option header
*/
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
dsrRoutingHeader.SetDestId (255);
DsrOptionRreqHeader rreqHeader; // has an alignment of 4n+0
rreqHeader.AddNodeAddress (m_mainAddress); // Add our own address in the header
rreqHeader.SetTarget (destination);
m_requestId = m_rreqTable->CheckUniqueRreqId (destination); // Check the Id cache for duplicate ones
rreqHeader.SetId (m_requestId);
dsrRoutingHeader.AddDsrOption (rreqHeader); // Add the rreqHeader to the dsr extension header
uint8_t length = rreqHeader.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
packet->AddHeader (dsrRoutingHeader);
// Schedule the route requests retry with non-propagation set true
bool nonProp = true;
std::vector<Ipv4Address> address;
address.push_back (source);
address.push_back (destination);
/*
* Add the socket ip ttl tag to the packet to limit the scope of route requests
*/
SocketIpTtlTag tag;
tag.SetTtl (0);
Ptr<Packet> nonPropPacket = packet->Copy ();
nonPropPacket->AddPacketTag (tag);
SendRequest (nonPropPacket, source);
// Schedule the next route request
ScheduleRreqRetry (packet, address, nonProp, m_requestId, protocol);
}
void
DsrRouting::SendErrorRequest (DsrOptionRerrUnreachHeader &rerr, uint8_t protocol)
{
NS_LOG_FUNCTION (this << (uint32_t)protocol);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
uint8_t salvage = rerr.GetSalvage ();
Ipv4Address dst = rerr.GetOriginalDst ();
NS_LOG_DEBUG ("our own address here " << m_mainAddress << " error source " << rerr.GetErrorSrc () << " error destination " << rerr.GetErrorDst ()
<< " error next hop " << rerr.GetUnreachNode () << " original dst " << rerr.GetOriginalDst ()
);
RouteCacheEntry toDst;
if (m_routeCache->LookupRoute (dst, toDst))
{
/*
* Found a route the dst, construct the source route option header
*/
DsrOptionSRHeader sourceRoute;
std::vector<Ipv4Address> ip = toDst.GetVector ();
sourceRoute.SetNodesAddress (ip);
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (ip);
}
sourceRoute.SetSegmentsLeft ((ip.size () - 2));
sourceRoute.SetSalvage (salvage);
Ipv4Address nextHop = SearchNextHop (m_mainAddress, ip); // Get the next hop address
NS_LOG_DEBUG ("The nextHop address " << nextHop);
Ptr<Packet> packet = Create<Packet> ();
if (nextHop == "0.0.0.0")
{
NS_LOG_DEBUG ("Error next hop address");
PacketNewRoute (packet, m_mainAddress, dst, protocol);
return;
}
SetRoute (nextHop, m_mainAddress);
CancelRreqTimer (dst, true);
SendPacketFromBuffer (sourceRoute, nextHop, protocol);
NS_LOG_LOGIC ("Route to " << dst << " found");
return;
}
else
{
NS_LOG_INFO ("No route found, initiate route error request");
Ptr<Packet> packet = Create<Packet> ();
Ipv4Address unreachAddress = rerr.GetUnreachNode ();
Ipv4Address originalDst = rerr.GetOriginalDst ();
// Create an empty route ptr
Ptr<Ipv4Route> route = 0;
/*
* Construct the route request option header
*/
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
dsrRoutingHeader.SetDestId (255);
Ptr<Packet> dstP = Create<Packet> ();
DsrOptionRreqHeader rreqHeader; // has an alignment of 4n+0
rreqHeader.AddNodeAddress (m_mainAddress); // Add our own address in the header
rreqHeader.SetTarget (originalDst);
m_requestId = m_rreqTable->CheckUniqueRreqId (originalDst); // Check the Id cache for duplicate ones
rreqHeader.SetId (m_requestId);
dsrRoutingHeader.AddDsrOption (rreqHeader); // Add the rreqHeader to the dsr extension header
dsrRoutingHeader.AddDsrOption (rerr);
uint8_t length = rreqHeader.GetLength () + rerr.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
dstP->AddHeader (dsrRoutingHeader);
// Schedule the route requests retry, propagate the route request message as it contains error
bool nonProp = false;
std::vector<Ipv4Address> address;
address.push_back (m_mainAddress);
address.push_back (originalDst);
/*
* Add the socket ip ttl tag to the packet to limit the scope of route requests
*/
SocketIpTtlTag tag;
tag.SetTtl ((uint8_t)m_discoveryHopLimit);
Ptr<Packet> propPacket = dstP->Copy ();
propPacket->AddPacketTag (tag);
if ((m_addressReqTimer.find (originalDst) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (originalDst) == m_nonPropReqTimer.end ()))
{
NS_LOG_INFO ("Only when there is no existing route request time when the initial route request is scheduled");
SendRequest (propPacket, m_mainAddress);
ScheduleRreqRetry (dstP, address, nonProp, m_requestId, protocol);
}
else
{
NS_LOG_INFO ("There is existing route request, find the existing route request entry");
/*
* Cancel the route request timer first before scheduling the route request
* in this case, we do not want to remove the route request entry, so the isRemove value is false
*/
CancelRreqTimer (originalDst, false);
ScheduleRreqRetry (dstP, address, nonProp, m_requestId, protocol);
}
}
}
void
DsrRouting::CancelRreqTimer (Ipv4Address dst, bool isRemove)
{
NS_LOG_FUNCTION (this << dst << isRemove);
// Cancel the non propagation request timer if found
if (m_nonPropReqTimer.find (dst) == m_nonPropReqTimer.end ())
{
NS_LOG_DEBUG ("Did not find the non-propagation timer");
}
else
{
NS_LOG_DEBUG ("did find the non-propagation timer");
}
m_nonPropReqTimer[dst].Cancel ();
m_nonPropReqTimer[dst].Remove ();
if (m_nonPropReqTimer[dst].IsRunning ())
{
NS_LOG_DEBUG ("Timer not canceled");
}
m_nonPropReqTimer.erase (dst);
// Cancel the address request timer if found
if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ())
{
NS_LOG_DEBUG ("Did not find the propagation timer");
}
else
{
NS_LOG_DEBUG ("did find the propagation timer");
}
m_addressReqTimer[dst].Cancel ();
m_addressReqTimer[dst].Remove ();
if (m_addressReqTimer[dst].IsRunning ())
{
NS_LOG_DEBUG ("Timer not canceled");
}
m_addressReqTimer.erase (dst);
/*
* If the route request is scheduled to remove the route request entry
* Remove the route request entry with the route retry times done for certain destination
*/
if (isRemove)
{
// remove the route request entry from route request table
m_rreqTable->RemoveRreqEntry (dst);
}
}
void
DsrRouting::ScheduleRreqRetry (Ptr<Packet> packet, std::vector<Ipv4Address> address, bool nonProp, uint32_t requestId, uint8_t protocol)
{
NS_LOG_FUNCTION (this << packet << nonProp << requestId << (uint32_t)protocol);
Ipv4Address source = address[0];
Ipv4Address dst = address[1];
if (nonProp)
{
// The nonProp route request is only sent out only and is already used
if (m_nonPropReqTimer.find (dst) == m_nonPropReqTimer.end ())
{
Timer timer (Timer::CANCEL_ON_DESTROY);
m_nonPropReqTimer[dst] = timer;
}
std::vector<Ipv4Address> address;
address.push_back (source);
address.push_back (dst);
m_nonPropReqTimer[dst].SetFunction (&DsrRouting::RouteRequestTimerExpire, this);
m_nonPropReqTimer[dst].Remove ();
m_nonPropReqTimer[dst].SetArguments (packet, address, requestId, protocol);
m_nonPropReqTimer[dst].Schedule (m_nonpropRequestTimeout);
}
else
{
// Cancel the non propagation request timer if found
m_nonPropReqTimer[dst].Cancel ();
m_nonPropReqTimer[dst].Remove ();
if (m_nonPropReqTimer[dst].IsRunning ())
{
NS_LOG_DEBUG ("Timer not canceled");
}
m_nonPropReqTimer.erase (dst);
if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ())
{
Timer timer (Timer::CANCEL_ON_DESTROY);
m_addressReqTimer[dst] = timer;
}
std::vector<Ipv4Address> address;
address.push_back (source);
address.push_back (dst);
m_addressReqTimer[dst].SetFunction (&DsrRouting::RouteRequestTimerExpire, this);
m_addressReqTimer[dst].Remove ();
m_addressReqTimer[dst].SetArguments (packet, address, requestId, protocol);
Time rreqDelay;
// back off mechanism for sending route requests
if (m_rreqTable->GetRreqCnt (dst))
{
// When the route request count is larger than 0
rreqDelay = Time (pow (m_rreqTable->GetRreqCnt (dst), 2) * m_requestPeriod);
}
else
{
// This is the first route request retry
rreqDelay = m_requestPeriod;
}
NS_LOG_DEBUG ("The request count for the destination " << dst << " " << m_rreqTable->GetRreqCnt (dst) << " with time value " << rreqDelay);
if (rreqDelay > m_maxRequestPeriod)
{
// use the max request period
NS_LOG_DEBUG ("The max request delay time " << m_maxRequestPeriod.GetSeconds());
m_addressReqTimer[dst].Schedule (m_maxRequestPeriod);
}
else
{
NS_LOG_DEBUG ("The request delay time " << rreqDelay.GetSeconds());
m_addressReqTimer[dst].Schedule (rreqDelay);
}
}
}
void
DsrRouting::RouteRequestTimerExpire (Ptr<Packet> packet, std::vector<Ipv4Address> address, uint32_t requestId, uint8_t protocol)
{
NS_LOG_FUNCTION (this << packet << requestId << (uint32_t)protocol);
// Get a clean packet without dsr header
Ptr<Packet> dsrP = packet->Copy ();
DsrRoutingHeader dsrRoutingHeader;
dsrP->RemoveHeader (dsrRoutingHeader); // Remove the dsr header in whole
Ipv4Address source = address[0];
Ipv4Address dst = address[1];
RouteCacheEntry toDst;
if (m_routeCache->LookupRoute (dst, toDst))
{
/*
* Found a route the dst, construct the source route option header
*/
DsrOptionSRHeader sourceRoute;
std::vector<Ipv4Address> ip = toDst.GetVector ();
sourceRoute.SetNodesAddress (ip);
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (ip);
}
sourceRoute.SetSegmentsLeft ((ip.size () - 2));
uint8_t salvage = 0;
sourceRoute.SetSalvage (salvage);
Ipv4Address nextHop = SearchNextHop (m_mainAddress, ip); // Get the next hop address
NS_LOG_DEBUG ("The nextHop address " << nextHop);
if (nextHop == "0.0.0.0")
{
NS_LOG_DEBUG ("Error next hop address");
PacketNewRoute (dsrP, source, dst, protocol);
return;
}
SetRoute (nextHop, m_mainAddress);
CancelRreqTimer (dst, true);
SendPacketFromBuffer (sourceRoute, nextHop, protocol);
NS_LOG_LOGIC ("Route to " << dst << " found");
return;
}
/*
* If a route discovery has been attempted m_rreqRetries times at the maximum TTL without
* receiving any RREP, all data packets destined for the corresponding destination SHOULD be
* dropped from the buffer and a Destination Unreachable message SHOULD be delivered to the application.
*/
NS_LOG_DEBUG ("The new request count for " << dst << " is " << m_rreqTable->GetRreqCnt (dst) << " the max " << m_rreqRetries);
if (m_rreqTable->GetRreqCnt (dst) >= m_rreqRetries)
{
NS_LOG_LOGIC ("Route discovery to " << dst << " has been attempted " << m_rreqRetries << " times");
CancelRreqTimer (dst, true);
NS_LOG_DEBUG ("Route not found. Drop packet with dst " << dst);
m_sendBuffer.DropPacketWithDst (dst);
}
else
{
SocketIpTtlTag tag;
tag.SetTtl ((uint8_t)m_discoveryHopLimit);
Ptr<Packet> propPacket = packet->Copy ();
propPacket->AddPacketTag (tag);
// Increase the request count
m_rreqTable->FindAndUpdate (dst);
SendRequest (propPacket, source);
NS_LOG_DEBUG ("Check the route request entry " << source << " " << dst);
ScheduleRreqRetry (packet, address, false, requestId, protocol);
}
return;
}
void
DsrRouting::SendRequest (Ptr<Packet> packet,
Ipv4Address source)
{
NS_LOG_FUNCTION (this << packet << source);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
/*
* The destination address here is directed broadcast address
*/
uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (packet, source, m_broadcast, Simulator::Now (), 0);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
void
DsrRouting::ScheduleInterRequest (Ptr<Packet> packet)
{
NS_LOG_FUNCTION (this << packet);
/*
* This is a forwarding case when sending route requests, a random delay time [0, m_broadcastJitter]
* used before forwarding as link-layer broadcast
*/
Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0, m_broadcastJitter)), &DsrRouting::SendRequest, this,
packet, m_mainAddress);
}
void
DsrRouting::SendGratuitousReply (Ipv4Address source, Ipv4Address srcAddress, std::vector<Ipv4Address> &nodeList, uint8_t protocol)
{
NS_LOG_FUNCTION (this << source << srcAddress << (uint32_t)protocol);
if (!(m_graReply.FindAndUpdate (source, srcAddress, m_gratReplyHoldoff))) // Find the gratuitous reply entry
{
NS_LOG_LOGIC ("Update gratuitous reply " << source);
GraReplyEntry graReplyEntry (source, srcAddress, m_gratReplyHoldoff + Simulator::Now ());
m_graReply.AddEntry (graReplyEntry);
/*
* Automatic route shortening
*/
m_finalRoute.clear (); // Clear the final route vector
/**
* Push back the node addresses other than those between srcAddress and our own ip address
*/
std::vector<Ipv4Address>::iterator before = find (nodeList.begin (), nodeList.end (), srcAddress);
for (std::vector<Ipv4Address>::iterator i = nodeList.begin (); i != before; ++i)
{
m_finalRoute.push_back (*i);
}
m_finalRoute.push_back (srcAddress);
std::vector<Ipv4Address>::iterator after = find (nodeList.begin (), nodeList.end (), m_mainAddress);
for (std::vector<Ipv4Address>::iterator j = after; j != nodeList.end (); ++j)
{
m_finalRoute.push_back (*j);
}
DsrOptionRrepHeader rrep;
rrep.SetNodesAddress (m_finalRoute); // Set the node addresses in the route reply header
// Get the real reply source and destination
Ipv4Address replySrc = m_finalRoute.back ();
Ipv4Address replyDst = m_finalRoute.front ();
/*
* Set the route and use it in send back route reply
*/
m_ipv4Route = SetRoute (srcAddress, m_mainAddress);
/*
* This part adds DSR header to the packet and send reply
*/
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (replySrc));
dsrRoutingHeader.SetDestId (GetIDfromIP (replyDst));
uint8_t length = rrep.GetLength (); // Get the length of the rrep header excluding the type header
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
dsrRoutingHeader.AddDsrOption (rrep);
Ptr<Packet> newPacket = Create<Packet> ();
newPacket->AddHeader (dsrRoutingHeader);
/*
* Send gratuitous reply
*/
NS_LOG_INFO ("Send back gratuitous route reply");
SendReply (newPacket, m_mainAddress, srcAddress, m_ipv4Route);
}
else
{
NS_LOG_INFO ("The same gratuitous route reply has already sent");
}
}
void
DsrRouting::SendReply (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address nextHop,
Ptr<Ipv4Route> route)
{
NS_LOG_FUNCTION (this << packet << source << nextHop);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (m_mainAddress));
route->SetOutputDevice (dev);
NS_LOG_INFO ("The output device " << dev << " packet is: " << *packet);
uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (packet, source, nextHop, Simulator::Now (), route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
void
DsrRouting::ScheduleInitialReply (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address nextHop,
Ptr<Ipv4Route> route)
{
NS_LOG_FUNCTION (this << packet << source << nextHop);
Simulator::ScheduleNow (&DsrRouting::SendReply, this,
packet, source, nextHop, route);
}
void
DsrRouting::ScheduleCachedReply (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address destination,
Ptr<Ipv4Route> route,
double hops)
{
NS_LOG_FUNCTION (this << packet << source << destination);
Simulator::Schedule (Time (2 * m_nodeTraversalTime * (hops - 1 + UniformVariable ().GetValue (0,1))), &DsrRouting::SendReply, this, packet, source, destination, route);
}
void
DsrRouting::SendAck (uint16_t ackId,
Ipv4Address destination,
Ipv4Address realSrc,
Ipv4Address realDst,
uint8_t protocol,
Ptr<Ipv4Route> route)
{
NS_LOG_FUNCTION (this << ackId << destination << realSrc << realDst << (uint32_t)protocol << route);
NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
// This is a route reply option header
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
DsrOptionAckHeader ack;
/*
* Set the ack Id and set the ack source address and destination address
*/
ack.SetAckId (ackId);
ack.SetRealSrc (realSrc);
ack.SetRealDst (realDst);
uint8_t length = ack.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
dsrRoutingHeader.AddDsrOption (ack);
Ptr<Packet> packet = Create<Packet> ();
packet->AddHeader (dsrRoutingHeader);
Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
route->SetOutputDevice (dev);
NS_LOG_DEBUG ("Send out the ACK");
uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
DsrNetworkQueueEntry newEntry (packet, m_mainAddress, destination, Simulator::Now (), route);
if (dsrNetworkQueue->Enqueue (newEntry))
{
Scheduler (priority);
}
else
{
NS_LOG_INFO ("Packet dropped as dsr network queue is full");
}
}
enum Ipv4L4Protocol::RxStatus
DsrRouting::Receive (Ptr<Packet> p,
Ipv4Header const &ip,
Ptr<Ipv4Interface> incomingInterface)
{
NS_LOG_FUNCTION (this << p << ip << incomingInterface);
NS_LOG_INFO ("Our own IP address " << m_mainAddress << " The incoming interface address " << incomingInterface);
m_node = GetNode (); // Get the node
Ptr<Packet> packet = p->Copy (); // Save a copy of the received packet
/*
* When forwarding or local deliver packets, this one should be used always!!
*/
DsrRoutingHeader dsrRoutingHeader;
packet->RemoveHeader (dsrRoutingHeader); // Remove the DSR header in whole
Ptr<Packet> copy = packet->Copy ();
uint8_t protocol = dsrRoutingHeader.GetNextHeader ();
uint32_t sourceId = dsrRoutingHeader.GetSourceId ();
Ipv4Address source = GetIPfromID (sourceId);
NS_LOG_DEBUG ("The source address " << source << " with source id " << sourceId);
/*
* Get the IP source and destination address
*/
Ipv4Address src = ip.GetSource ();
bool isPromisc = false;
uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset (); // Get the offset for option header, 8 bytes in this case
// This packet is used to peek option type
p->RemoveAtStart (offset);
Ptr<dsr::DsrOptions> dsrOption;
DsrOptionHeader dsrOptionHeader;
/*
* Peek data to get the option type as well as length and segmentsLeft field
*/
uint32_t size = p->GetSize ();
uint8_t *data = new uint8_t[size];
p->CopyData (data, size);
uint8_t optionType = 0;
uint8_t optionLength = 0;
uint8_t segmentsLeft = 0;
optionType = *(data);
NS_LOG_LOGIC ("The option type value " << (uint32_t)optionType << " with packet size " << p->GetSize());
dsrOption = GetOption (optionType); // Get the relative dsr option and demux to the process function
if (optionType == 1) // This is the request option
{
BlackList *blackList = m_rreqTable->FindUnidirectional (src);
if (blackList)
{
NS_LOG_DEBUG ("Discard this packet due to unidirectional link");
m_dropTrace (p);
}
dsrOption = GetOption (optionType);
optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
if (optionLength == 0)
{
NS_LOG_DEBUG ("Discard this packet");
m_dropTrace (p);
}
}
else if (optionType == 2)
{
dsrOption = GetOption (optionType);
optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
if (optionLength == 0)
{
NS_LOG_DEBUG ("Discard this packet");
m_dropTrace (p);
}
}
else if (optionType == 32) // This is the ACK option
{
NS_LOG_DEBUG ("This is the ack option");
dsrOption = GetOption (optionType);
optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
if (optionLength == 0)
{
NS_LOG_DEBUG ("Discard this packet");
m_dropTrace (p);
}
}
else if (optionType == 3) // This is a route error header
{
// populate this route error
NS_LOG_DEBUG ("The option type value " << (uint32_t)optionType);
dsrOption = GetOption (optionType);
optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
if (optionLength == 0)
{
NS_LOG_DEBUG ("Discard this packet");
m_dropTrace (p);
}
NS_LOG_DEBUG ("The option Length " << (uint32_t)optionLength);
}
else if (optionType == 96) // This is the source route option
{
NS_LOG_DEBUG ("This is the source route option " << (uint32_t)optionType);
dsrOption = GetOption (optionType);
optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
segmentsLeft = *(data + 3);
NS_LOG_DEBUG ("The segments left in source route header " << (uint32_t)segmentsLeft);
if (optionLength == 0)
{
NS_LOG_DEBUG ("Discard this packet");
m_dropTrace (p);
}
else
{
if (segmentsLeft == 0)
{
// / Get the next header
uint8_t nextHeader = dsrRoutingHeader.GetNextHeader ();
Ptr<Ipv4L3Protocol> l3proto = m_node->GetObject<Ipv4L3Protocol> ();
Ptr<Ipv4L4Protocol> nextProto = l3proto->GetProtocol (nextHeader);
if (nextProto != 0)
{
// we need to make a copy in the unlikely event we hit the
// RX_ENDPOINT_UNREACH code path
// Here we can use the packet that has been get off whole DSR header
NS_LOG_DEBUG ("The packet size here " << copy->GetSize());
NS_LOG_DEBUG ("The packet received " << *copy);
enum Ipv4L4Protocol::RxStatus status =
nextProto->Receive (copy, ip, incomingInterface);
NS_LOG_DEBUG ("The receive status " << status);
switch (status)
{
case Ipv4L4Protocol::RX_OK:
// fall through
case Ipv4L4Protocol::RX_ENDPOINT_CLOSED:
// fall through
case Ipv4L4Protocol::RX_CSUM_FAILED:
break;
case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
if (ip.GetDestination ().IsBroadcast () == true
|| ip.GetDestination ().IsMulticast () == true)
{
break; // Do not reply to broadcast or multicast
}
// Another case to suppress ICMP is a subnet-directed broadcast
}
return status;
}
}
else
{
NS_LOG_INFO ("This is not the final destination, the packet has already been forward to next hop");
}
}
}
else
{
NS_LOG_LOGIC ("Unknown Option. Drop!");
/*
* Initialize the salvage value to 0
*/
uint8_t salvage = 0;
DsrOptionRerrUnsupportHeader rerrUnsupportHeader;
rerrUnsupportHeader.SetErrorType (3); // The error type 3 means Option not supported
rerrUnsupportHeader.SetErrorSrc (m_mainAddress); // The error source address is our own address
rerrUnsupportHeader.SetUnsupported (optionType); // The unsupported option type number
rerrUnsupportHeader.SetErrorDst (src); // Error destination address is the destination of the data packet
rerrUnsupportHeader.SetSalvage (salvage); // Set the value about whether to salvage a packet or not
/*
* The unknow option error is not supported currently in this implementation, and it's also not likely to
* happen in simulations
*/
// SendError (rerrUnsupportHeader, 0, protocol); // Send the error packet
}
return Ipv4L4Protocol::RX_OK;
}
void
DsrRouting::SetDownTarget (DownTargetCallback callback)
{
m_downTarget = callback;
}
Ipv4L4Protocol::DownTargetCallback
DsrRouting::GetDownTarget (void) const
{
return m_downTarget;
}
void DsrRouting::Insert (Ptr<dsr::DsrOptions> option)
{
m_options.push_back (option);
}
Ptr<dsr::DsrOptions> DsrRouting::GetOption (int optionNumber)
{
for (DsrOptionList_t::iterator i = m_options.begin (); i != m_options.end (); ++i)
{
if ((*i)->GetOptionNumber () == optionNumber)
{
return *i;
}
}
return 0;
}
} /* namespace dsr */
} /* namespace ns3 */