uint8_t DsrOptionRreq::Process()

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 ();
}