in simulation/src/dsr/model/dsr-options.cc [495:959]
uint8_t DsrOptionRreq::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc, Ipv4Address promiscSource)
{
NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
// Fields from IP header
Ipv4Address srcAddress = ipv4Header.GetSource ();
/*
* \ when the ip source address is equal to the address of our own, this is request packet originated
* \ by the node itself, discard it
*/
if (source == ipv4Address)
{
NS_LOG_DEBUG ("Discard the packet since it was originated from same source address");
m_dropTrace (packet); // call the drop trace to show in the tracing
return 0;
}
/*
* Get the node associated with the ipv4 address and get several objects from the node and leave for further use
*/
Ptr<Node> node = GetNodeWithAddress (ipv4Address);
Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
Ptr<Packet> p = packet->Copy (); // Note: The packet here doesn't contain the fixed size dsr header
/*
* \brief Get the number of routers' address field before removing the header
* \peek the packet and get the value
*/
uint8_t buf[2];
p->CopyData (buf, sizeof(buf));
uint8_t numberAddress = (buf[1] - 6) / 4;
NS_LOG_DEBUG ("The number of Ip addresses " << (uint32_t)numberAddress);
if (numberAddress >= 255)
{
NS_LOG_DEBUG ("Discard the packet, malformed header since two many ip addresses in route");
m_dropTrace (packet); // call the drop trace to show in the tracing
return 0;
}
/*
* Create the dsr rreq header
*/
DsrOptionRreqHeader rreq;
/*
* Set the number of addresses with the value from peek data and remove the rreq header
*/
rreq.SetNumberAddress (numberAddress);
// Remove the route request header
p->RemoveHeader (rreq);
// Verify the option length
uint8_t length = rreq.GetLength ();
if (length % 2 != 0)
{
NS_LOG_LOGIC ("Malformed header. Drop!");
m_dropTrace (packet); // call drop trace
return 0;
}
// Check the rreq id for verifying the request id
uint16_t requestId = rreq.GetId ();
// The target address is where we want to send the data packets
Ipv4Address targetAddress = rreq.GetTarget ();
// Get the node list and source address from the route request header
std::vector<Ipv4Address> mainVector = rreq.GetNodesAddresses ();
std::vector<Ipv4Address> nodeList (mainVector);
// Get the real source address of this request, it will be used when checking if we have received the save
// route request before or not
Ipv4Address sourceAddress = nodeList.front ();
PrintVector (nodeList);
/*
* Construct the dsr routing header for later use
*/
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
dsrRoutingHeader.SetDestId (255);
// check whether we have received this request or not, if not, it will save the request in the table for
// later use, if not found, return false, and push the newly received source request entry in the cache
// Get the TTL value, this is used to test if the packet will be forwarded or not
uint8_t ttl = ipv4Header.GetTtl ();
bool dupRequest = false; // initialize the duplicate request check value
if (ttl)
{
// if the ttl value is not 0, then this request will be forwarded, then we need to
// save it in the source entry
dupRequest = dsr->FindSourceEntry (sourceAddress, targetAddress, requestId);
}
/*
* Before processing the route request, we need to check two things
* 1. if this is the exact same request we have just received, ignore it
* 2. if our address is already in the path list, ignore it
* 3. otherwise process further
*/
if (dupRequest)
{
// We have received this same route request before, not forwarding it now
NS_LOG_LOGIC ("Duplicate request. Drop!");
m_dropTrace (packet); // call drop trace
return 0;
}
else if (CheckDuplicates (ipv4Address, nodeList))
{
/*
* if the route contains the node address already, drop the request packet
*/
m_dropTrace (packet); // call drop trace
NS_LOG_DEBUG ("Our node address is already seen in the route, drop the request");
return 0;
}
else
{
// A node ignores all RREQs received from any node in its blacklist
DsrRouteCacheEntry toPrev;
bool isRouteInCache = dsr->LookupRoute (targetAddress,
toPrev);
DsrRouteCacheEntry::IP_VECTOR ip = toPrev.GetVector (); // The route from our own route cache to dst
PrintVector (ip);
std::vector<Ipv4Address> saveRoute (nodeList);
PrintVector (saveRoute);
bool areThereDuplicates = IfDuplicates (ip,
saveRoute);
/*
* When the reverse route is created or updated, the following actions on the route are also carried out:
* 3. the next hop in the routing table becomes the node from which the RREQ was received
* 4. the hop count is copied from the Hop Count in the RREQ message;
*/
// A node generates a RREP if either:
// (i) it is itself the destination,
/*
* The target address equal to our own ip address
*/
NS_LOG_DEBUG ("The target address over here " << targetAddress << " and the ip address " << ipv4Address << " and the source address " << mainVector[0]);
if (targetAddress == ipv4Address)
{
Ipv4Address nextHop; // Declare the next hop address to use
if (nodeList.size () == 1)
{
NS_LOG_DEBUG ("These two nodes are neighbors");
m_finalRoute.clear ();
/// TODO has changed the srcAddress to source, should not matter either way, check later
m_finalRoute.push_back (source); // push back the request originator's address
m_finalRoute.push_back (ipv4Address); // push back our own address
nextHop = srcAddress;
}
else
{
std::vector<Ipv4Address> changeRoute (nodeList);
changeRoute.push_back (ipv4Address); // push back our own address
m_finalRoute.clear (); // get a clear route vector
for (std::vector<Ipv4Address>::iterator i = changeRoute.begin (); i != changeRoute.end (); ++i)
{
m_finalRoute.push_back (*i); // Get the full route from source to destination
}
PrintVector (m_finalRoute);
nextHop = ReverseSearchNextHop (ipv4Address, m_finalRoute); // get the next hop
}
DsrOptionRrepHeader rrep;
rrep.SetNodesAddress (m_finalRoute); // Set the node addresses in the route reply header
NS_LOG_DEBUG ("The nextHop address " << nextHop);
Ipv4Address replyDst = m_finalRoute.front ();
/*
* This part add dsr header to the packet and send route reply packet
*/
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (ipv4Address));
dsrRoutingHeader.SetDestId (GetIDfromIP (replyDst));
// Set the route for route reply
SetRoute (nextHop, ipv4Address);
uint8_t length = rrep.GetLength (); // Get the length of the rrep header excluding the type header
dsrRoutingHeader.SetPayloadLength (length + 2);
dsrRoutingHeader.AddDsrOption (rrep);
Ptr<Packet> newPacket = Create<Packet> ();
newPacket->AddHeader (dsrRoutingHeader);
dsr->ScheduleInitialReply (newPacket, ipv4Address, nextHop, m_ipv4Route);
/*
* Create the route entry to the rreq originator and save it to route cache, also need to reverse the route
*/
PrintVector (m_finalRoute);
if (ReverseRoutes (m_finalRoute))
{
PrintVector (m_finalRoute);
Ipv4Address dst = m_finalRoute.back ();
bool addRoute = false;
if (numberAddress > 0)
{
DsrRouteCacheEntry toSource (/*IP_VECTOR=*/ m_finalRoute, /*dst=*/
dst, /*expire time=*/ ActiveRouteTimeout);
if (dsr->IsLinkCache ())
{
addRoute = dsr->AddRoute_Link (m_finalRoute, ipv4Address);
}
else
{
addRoute = dsr->AddRoute (toSource);
}
}
else
{
NS_LOG_DEBUG ("Abnormal RouteRequest");
return 0;
}
if (addRoute)
{
/*
* Found a route to the dst, construct the source route option header
*/
DsrOptionSRHeader sourceRoute;
NS_LOG_DEBUG ("The route length " << m_finalRoute.size ());
sourceRoute.SetNodesAddress (m_finalRoute);
/// TODO !!!!!!!!!!!!!!
/// Think about this part, we just added the route,
/// probability no need to increase stability now?????
// if (dsr->IsLinkCache ())
// {
// dsr->UseExtends (m_finalRoute);
// }
sourceRoute.SetSegmentsLeft ((m_finalRoute.size () - 2));
// The salvage value here is 0
sourceRoute.SetSalvage (0);
Ipv4Address nextHop = SearchNextHop (ipv4Address, m_finalRoute); // Get the next hop address
NS_LOG_DEBUG ("The nextHop address " << nextHop);
if (nextHop == "0.0.0.0")
{
dsr->PacketNewRoute (dsrP, ipv4Address, dst, protocol);
return 0;
}
SetRoute (nextHop, ipv4Address);
/*
* Send the data packet from the send buffer
*/
dsr->SendPacketFromBuffer (sourceRoute, nextHop, protocol);
// Cancel the route request timer for destination after sending the data packet
dsr->CancelRreqTimer (dst, true);
}
else
{
NS_LOG_DEBUG ("The route is failed to add in cache");
return 0;
}
}
else
{
NS_LOG_DEBUG ("Unable to reverse route");
return 0;
}
isPromisc = false;
return rreq.GetSerializedSize ();
}
/*
* (ii) or it has an active route to the destination, send reply based on request header and route cache,
* need to delay based on a random value from d = H * (h - 1 + r), which can avoid possible route
* reply storm. Also, verify if two vectors do not contain duplicates (part of the route to the
* destination from route cache and route collected so far). If so, do not use the route found
* and forward the route request.
*/
else if (isRouteInCache && !areThereDuplicates)
{
m_finalRoute.clear (); // Clear the final route vector
/**
* push back the intermediate node address from the source to this node
*/
for (std::vector<Ipv4Address>::iterator i = saveRoute.begin (); i != saveRoute.end (); ++i)
{
m_finalRoute.push_back (*i);
}
/**
* push back the route vector we found in our route cache to destination, including this node's address
*/
for (std::vector<Ipv4Address>::iterator j = ip.begin (); j != ip.end (); ++j)
{
m_finalRoute.push_back (*j);
}
/*
* Create the route entry to the rreq originator and save it to route cache, also need to reverse the route
*/
bool addRoute = false;
std::vector<Ipv4Address> reverseRoute (m_finalRoute);
if (ReverseRoutes (reverseRoute))
{
saveRoute.push_back (ipv4Address);
ReverseRoutes (saveRoute);
Ipv4Address dst = saveRoute.back ();
NS_LOG_DEBUG ("This is the route save in route cache");
PrintVector (saveRoute);
DsrRouteCacheEntry toSource (/*IP_VECTOR=*/ saveRoute, /*dst=*/ dst, /*expire time=*/ ActiveRouteTimeout);
NS_ASSERT (saveRoute.front () == ipv4Address);
// Add the route entry in the route cache
if (dsr->IsLinkCache ())
{
addRoute = dsr->AddRoute_Link (saveRoute, ipv4Address);
}
else
{
addRoute = dsr->AddRoute (toSource);
}
if (addRoute)
{
NS_LOG_LOGIC ("We have added the route and search send buffer for packet with destination " << dst);
/*
* Found a route the dst, construct the source route option header
*/
DsrOptionSRHeader sourceRoute;
PrintVector (saveRoute);
sourceRoute.SetNodesAddress (saveRoute);
// if (dsr->IsLinkCache ())
// {
// dsr->UseExtends (saveRoute);
// }
sourceRoute.SetSegmentsLeft ((saveRoute.size () - 2));
uint8_t salvage = 0;
sourceRoute.SetSalvage (salvage);
Ipv4Address nextHop = SearchNextHop (ipv4Address, saveRoute); // Get the next hop address
NS_LOG_DEBUG ("The nextHop address " << nextHop);
if (nextHop == "0.0.0.0")
{
dsr->PacketNewRoute (dsrP, ipv4Address, dst, protocol);
return 0;
}
SetRoute (nextHop, ipv4Address);
/*
* Schedule the packet retry
*/
dsr->SendPacketFromBuffer (sourceRoute, nextHop, protocol);
// Cancel the route request timer for destination
dsr->CancelRreqTimer (dst, true);
}
else
{
NS_LOG_DEBUG ("The route is failed to add in cache");
return 0;
}
}
else
{
NS_LOG_DEBUG ("Unable to reverse the route");
return 0;
}
/*
* Need to first pin down the next hop address before removing duplicates
*/
Ipv4Address nextHop = ReverseSearchNextHop (ipv4Address, m_finalRoute);
/*
* First remove the duplicate ip address to automatically shorten the route, and then reversely
* search the next hop address
*/
// Set the route
SetRoute (nextHop, ipv4Address);
uint16_t hops = m_finalRoute.size ();
DsrOptionRrepHeader rrep;
rrep.SetNodesAddress (m_finalRoute); // Set the node addresses in the route reply header
// Get the real source of the reply
Ipv4Address realSource = m_finalRoute.back ();
PrintVector (m_finalRoute);
NS_LOG_DEBUG ("This is the full route from " << realSource << " to " << m_finalRoute.front ());
/*
* This part add dsr header to the packet and send route reply packet
*/
DsrRoutingHeader dsrRoutingHeader;
dsrRoutingHeader.SetNextHeader (protocol);
dsrRoutingHeader.SetMessageType (1);
dsrRoutingHeader.SetSourceId (GetIDfromIP (realSource));
dsrRoutingHeader.SetDestId (255);
uint8_t length = rrep.GetLength (); // Get the length of the rrep header excluding the type header
dsrRoutingHeader.SetPayloadLength (length + 2);
dsrRoutingHeader.AddDsrOption (rrep);
Ptr<Packet> newPacket = Create<Packet> ();
newPacket->AddHeader (dsrRoutingHeader);
dsr->ScheduleCachedReply (newPacket, ipv4Address, nextHop, m_ipv4Route, hops);
isPromisc = false;
return rreq.GetSerializedSize ();
}
/*
* (iii) no route in any type has been found
*/
else
{
mainVector.push_back (ipv4Address);
NS_ASSERT (mainVector.front () == source);
NS_LOG_DEBUG ("Print out the main vector");
PrintVector (mainVector);
rreq.SetNodesAddress (mainVector);
Ptr<Packet> errP = p->Copy ();
if (errP->GetSize ())
{
NS_LOG_DEBUG ("Error header included");
DsrOptionRerrUnreachHeader rerr;
p->RemoveHeader (rerr);
Ipv4Address errorSrc = rerr.GetErrorSrc ();
Ipv4Address unreachNode = rerr.GetUnreachNode ();
Ipv4Address errorDst = rerr.GetErrorDst ();
if ((errorSrc == srcAddress) && (unreachNode == ipv4Address))
{
NS_LOG_DEBUG ("The error link back to work again");
uint16_t length = rreq.GetLength ();
NS_LOG_DEBUG ("The RREQ header length " << length);
dsrRoutingHeader.AddDsrOption (rreq);
dsrRoutingHeader.SetPayloadLength (length + 2);
}
else
{
dsr->DeleteAllRoutesIncludeLink (errorSrc, unreachNode, ipv4Address);
DsrOptionRerrUnreachHeader newUnreach;
newUnreach.SetErrorType (1);
newUnreach.SetErrorSrc (errorSrc);
newUnreach.SetUnreachNode (unreachNode);
newUnreach.SetErrorDst (errorDst);
newUnreach.SetSalvage (rerr.GetSalvage ()); // Set the value about whether to salvage a packet or not
uint16_t length = rreq.GetLength () + newUnreach.GetLength ();
NS_LOG_DEBUG ("The RREQ and newUnreach header length " << length);
dsrRoutingHeader.SetPayloadLength (length + 4);
dsrRoutingHeader.AddDsrOption (rreq);
dsrRoutingHeader.AddDsrOption (newUnreach);
}
}
else
{
uint16_t length = rreq.GetLength ();
NS_LOG_DEBUG ("The RREQ header length " << length);
dsrRoutingHeader.AddDsrOption (rreq);
dsrRoutingHeader.SetPayloadLength (length + 2);
}
// Get the TTL value
uint8_t ttl = ipv4Header.GetTtl ();
/*
* Decrease the TTL value in the packet tag by one, this tag will go to ip layer 3 send function
* and drop packet when TTL value equals to 0
*/
NS_LOG_DEBUG ("The ttl value here " << (uint32_t)ttl);
if (ttl)
{
Ptr<Packet> interP = Create<Packet> ();
SocketIpTtlTag tag;
tag.SetTtl (ttl - 1);
interP->AddPacketTag (tag);
interP->AddHeader (dsrRoutingHeader);
dsr->ScheduleInterRequest (interP);
isPromisc = false;
}
return rreq.GetSerializedSize ();
}
}
//unreachable: return rreq.GetSerializedSize ();
}