uint8_t DsrOptionSR::Process()

in simulation/src/dsr/model/dsr-options.cc [1195:1402]


uint8_t DsrOptionSR::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 << ipv4Address << ipv4Header << (uint32_t)protocol << isPromisc);
  Ptr<Packet> p = packet->Copy ();
  // Get the number of routers' address field
  uint8_t buf[2];
  p->CopyData (buf, sizeof(buf));
  uint8_t numberAddress = (buf[1] - 2) / 4;
  DsrOptionSRHeader sourceRoute;
  sourceRoute.SetNumberAddress (numberAddress);
  p->RemoveHeader (sourceRoute);

  // The route size saved in the source route
  std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
  uint8_t segsLeft = sourceRoute.GetSegmentsLeft ();
  uint8_t salvage = sourceRoute.GetSalvage ();
  /*
   * Get the node from IP address and get the DSR extension object
   */
  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
  /*
   * Get the source and destination address from ipv4 header
   */
  Ipv4Address srcAddress = ipv4Header.GetSource ();
  Ipv4Address destAddress = ipv4Header.GetDestination ();

  // Get the node list destination
  Ipv4Address destination = nodeList.back ();
  /*
   * If it's a promiscuous receive data packet,
   * 1. see if automatic route shortening possible or not
   * 2. see if it is a passive acknowledgment
   */
  if (isPromisc)
    {
      NS_LOG_LOGIC ("We process promiscuous receipt data packet");
      if (ContainAddressAfter (ipv4Address, destAddress, nodeList))
        {
          NS_LOG_LOGIC ("Send back the gratuitous reply");
          dsr->SendGratuitousReply (source, srcAddress, nodeList, protocol);
        }

      uint16_t fragmentOffset = ipv4Header.GetFragmentOffset ();
      uint16_t identification = ipv4Header.GetIdentification ();

      if (destAddress != destination)
        {
          NS_LOG_DEBUG ("Process the promiscuously received packet");
          bool findPassive = false;
          int32_t nNodes = NodeList::GetNNodes ();
          for (int32_t i = 0; i < nNodes; ++i)
            {
              NS_LOG_DEBUG ("Working with node " << i);

              Ptr<Node> node = NodeList::GetNode (i);
              Ptr<dsr::DsrRouting> dsrNode = node->GetObject<dsr::DsrRouting> ();
              // The source and destination addresses here are the real source and destination for the packet
              findPassive = dsrNode->PassiveEntryCheck (packet, source, destination, segsLeft, fragmentOffset, identification, false);
              if (findPassive)
                {
                  break;
                }
            }

          if (findPassive)
            {
              NS_LOG_DEBUG ("We find one previously received passive entry");
              /*
               * Get the node from IP address and get the DSR extension object
               * the srcAddress would be the source address from ip header
               */
              PrintVector (nodeList);

              NS_LOG_DEBUG ("promisc source " << promiscSource);
              Ptr<Node> node = GetNodeWithAddress (promiscSource);
              Ptr<dsr::DsrRouting> dsrSrc = node->GetObject<dsr::DsrRouting> ();
              dsrSrc->CancelPassiveTimer (packet, source, destination, segsLeft);
            }
          else
            {
              NS_LOG_DEBUG ("Saved the entry for further use");
              dsr->PassiveEntryCheck (packet, source, destination, segsLeft, fragmentOffset, identification, true);
            }
        }
      /// Safely terminate promiscuously received packet
      return 0;
    }
  else
    {
      /*
       * Get the number of address from the source route header
       */
      uint8_t length = sourceRoute.GetLength ();
      uint8_t nextAddressIndex;
      Ipv4Address nextAddress;

      // Get the option type value
      uint32_t size = p->GetSize ();
      uint8_t *data = new uint8_t[size];
      p->CopyData (data, size);
      uint8_t optionType = 0;
      optionType = *(data);
      /// When the option type is 160, means there is ACK request header after the source route, we need
      /// to send back acknowledgment
      if (optionType == 160)
        {
          NS_LOG_LOGIC ("Remove the ack request header and add ack header to the packet");
          // Here we remove the ack packet to the previous hop
          DsrOptionAckReqHeader ackReq;
          p->RemoveHeader (ackReq);
          uint16_t ackId = ackReq.GetAckId ();
          /*
           * Send back acknowledgment packet to the earlier hop
           * If the node list is not empty, find the previous hop from the node list,
           * otherwise, use srcAddress
           */
          Ipv4Address ackAddress = srcAddress;
          if (!nodeList.empty ())
            {
              if (segsLeft > numberAddress)   // The segmentsLeft field should not be larger than the total number of ip addresses
                {
                  NS_LOG_LOGIC ("Malformed header. Drop!");
                  m_dropTrace (packet);
                  return 0;
                }
              // -fstrict-overflow sensitive, see bug 1868
              if (numberAddress - segsLeft < 2)   // The index is invalid
                {
                  NS_LOG_LOGIC ("Malformed header. Drop!");
                  m_dropTrace (packet);
                  return 0;
                }
              ackAddress = nodeList[numberAddress - segsLeft - 2];
            }
          m_ipv4Route = SetRoute (ackAddress, ipv4Address);
          NS_LOG_DEBUG ("Send back ACK to the earlier hop " << ackAddress << " from us " << ipv4Address);
          dsr->SendAck (ackId, ackAddress, source, destination, protocol, m_ipv4Route);
        }
      /*
       * After send back ACK, check if the segments left value has turned to 0 or not, if yes, update the route entry
       * and return header length
       */
      if (segsLeft == 0)
        {
          NS_LOG_DEBUG ("This is the final destination");
          isPromisc = false;
          return sourceRoute.GetSerializedSize ();
        }

      if (length % 2 != 0)
        {
          NS_LOG_LOGIC ("Malformed header. Drop!");
          m_dropTrace (packet);
          return 0;
        }

      if (segsLeft > numberAddress) // The segmentsLeft field should not be larger than the total number of ip addresses
        {
          NS_LOG_LOGIC ("Malformed header. Drop!");
          m_dropTrace (packet);
          return 0;
        }

      DsrOptionSRHeader newSourceRoute;
      newSourceRoute.SetSegmentsLeft (segsLeft - 1);
      newSourceRoute.SetSalvage (salvage);
      newSourceRoute.SetNodesAddress (nodeList);
      nextAddressIndex = numberAddress - segsLeft;
      nextAddress = newSourceRoute.GetNodeAddress (nextAddressIndex);
      NS_LOG_DEBUG ("The next address of source route option " << nextAddress << " and the nextAddressIndex: " << (uint32_t)nextAddressIndex << " and the segments left : " << (uint32_t)segsLeft);
      /*
       * Get the target Address in the node list
       */
      Ipv4Address targetAddress = nodeList.back ();
      Ipv4Address realSource = nodeList.front ();
      /*
       * Search the vector for next hop address
       */
      Ipv4Address nextHop = SearchNextHop (ipv4Address, nodeList);
      PrintVector (nodeList);

      if (nextHop == "0.0.0.0")
        {
          NS_LOG_DEBUG ("Before new packet " << *dsrP);
          dsr->PacketNewRoute (dsrP, realSource, targetAddress, protocol);
          return 0;
        }

      if (ipv4Address == nextHop)
        {
          NS_LOG_DEBUG ("We have reached the destination");
          newSourceRoute.SetSegmentsLeft (0);
          return newSourceRoute.GetSerializedSize ();
        }
      // Verify the multicast address, leave it here for now
      if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
        {
          m_dropTrace (packet);
          return 0;
        }
      // Set the route and forward the data packet
      SetRoute (nextAddress, ipv4Address);
      NS_LOG_DEBUG ("dsr packet size " << dsrP->GetSize ());
      dsr->ForwardPacket (dsrP, newSourceRoute, ipv4Header, realSource, nextAddress, targetAddress, protocol, m_ipv4Route);
    }
  return sourceRoute.GetSerializedSize ();
}