in simulation/src/dsr/model/dsr-routing.cc [835:1045]
void DsrRouting::CheckSendBuffer ()
{
NS_LOG_INFO (Simulator::Now ().As (Time::S)
<< " Checking send buffer at " << m_mainAddress << " with size " << m_sendBuffer.GetSize ());
for (std::vector<DsrSendBuffEntry>::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 ();
DsrRouteCacheEntry 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 ();
i = 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);
/// When found a route and use it, UseExtends to the link cache
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); /// This will be priority 0
std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
NS_LOG_LOGIC ("Will be inserting into priority queue number: " << priority);
//m_downTarget (newPacket, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route);
/// \todo New DsrNetworkQueueEntry
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);
/// When found a route and use it, UseExtends to the link cache
if (m_routeCache->IsLinkCache ())
{
m_routeCache->UseExtends (nodeList);
}
uint8_t length = sourceRoute.GetLength ();
dsrRoutingHeader.SetPayloadLength (uint16_t (length) + 2);
dsrRoutingHeader.AddDsrOption (sourceRoute);
cleanP->AddHeader (dsrRoutingHeader);
Ptr<const Packet> mtP = cleanP->Copy ();
// Put the data packet in the maintenance queue for data packet retransmission
DsrMaintainBuffEntry 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 ();
LinkKey linkKey;
linkKey.m_source = newEntry.GetSrc ();
linkKey.m_destination = newEntry.GetDst ();
linkKey.m_ourAdd = newEntry.GetOurAdd ();
linkKey.m_nextHop = newEntry.GetNextHop ();
m_addressForwardCnt[networkKey] = 0;
m_passiveCnt[passiveKey] = 0;
m_linkCnt[linkKey] = 0;
if (m_linkAck)
{
ScheduleLinkPacketRetry (newEntry, protocol);
}
else
{
NS_LOG_LOGIC ("Not using link acknowledgment");
if (nextHop != destination)
{
SchedulePassivePacketRetry (newEntry, 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 ();
}
}