void Rip::HandleRequests()

in simulation/src/internet/model/rip.cc [789:949]


void Rip::HandleRequests (RipHeader requestHdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
{
  NS_LOG_FUNCTION (this << senderAddress << int (senderPort) << incomingInterface << int (hopLimit) << requestHdr);

  std::list<RipRte> rtes = requestHdr.GetRteList ();

  if (rtes.empty ())
    {
      return;
    }

  // check if it's a request for the full table from a neighbor
  if (rtes.size () == 1)
    {
      if (rtes.begin ()->GetPrefix () == Ipv4Address::GetAny () &&
          rtes.begin ()->GetSubnetMask ().GetPrefixLength () == 0 &&
          rtes.begin ()->GetRouteMetric () == m_linkDown)
        {
          // Output whole thing. Use Split Horizon
          if (m_interfaceExclusions.find (incomingInterface) == m_interfaceExclusions.end ())
            {
              // we use one of the sending sockets, as they're bound to the right interface
              // and the local address might be used on different interfaces.
              Ptr<Socket> sendingSocket;
              for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
                {
                  if (iter->second == incomingInterface)
                    {
                      sendingSocket = iter->first;
                    }
                }
              NS_ASSERT_MSG (sendingSocket, "HandleRequest - Impossible to find a socket to send the reply");

              uint16_t mtu = m_ipv4->GetMtu (incomingInterface);
              uint16_t maxRte = (mtu - Ipv4Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipHeader ().GetSerializedSize ()) / RipRte ().GetSerializedSize ();

              Ptr<Packet> p = Create<Packet> ();
              SocketIpTtlTag tag;
              p->RemovePacketTag (tag);
              if (senderAddress == Ipv4Address(RIP_ALL_NODE))
                {
                  tag.SetTtl (1);
                }
              else
                {
                  tag.SetTtl (255);
                }
              p->AddPacketTag (tag);

              RipHeader hdr;
              hdr.SetCommand (RipHeader::RESPONSE);

              for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
                {
                  bool splitHorizoning = (rtIter->first->GetInterface () == incomingInterface);

                  Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress(rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());

                  bool isGlobal = (rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL);
                  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv4Address::GetAny ()) &&
                      (rtIter->first->GetDestNetworkMask () == Ipv4Mask::GetZero ()) &&
                      (rtIter->first->GetInterface () != incomingInterface));

                  if ((isGlobal || isDefaultRoute) &&
                      (rtIter->first->GetRouteStatus () == RipRoutingTableEntry::RIP_VALID) )
                    {
                      RipRte rte;
                      rte.SetPrefix (rtIter->first->GetDestNetwork ());
                      rte.SetSubnetMask (rtIter->first->GetDestNetworkMask ());
                      if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
                        {
                          rte.SetRouteMetric (m_linkDown);
                        }
                      else
                        {
                          rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
                        }
                      rte.SetRouteTag (rtIter->first->GetRouteTag ());
                      if ((m_splitHorizonStrategy != SPLIT_HORIZON) ||
                          (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
                        {
                          hdr.AddRte (rte);
                        }
                    }
                  if (hdr.GetRteNumber () == maxRte)
                    {
                      p->AddHeader (hdr);
                      NS_LOG_DEBUG ("SendTo: " << *p);
                      sendingSocket->SendTo (p, 0, InetSocketAddress (senderAddress, RIP_PORT));
                      p->RemoveHeader (hdr);
                      hdr.ClearRtes ();
                    }
                }
              if (hdr.GetRteNumber () > 0)
                {
                  p->AddHeader (hdr);
                  NS_LOG_DEBUG ("SendTo: " << *p);
                  sendingSocket->SendTo (p, 0, InetSocketAddress (senderAddress, RIP_PORT));
                }
            }
        }
    }
  else
    {
      // note: we got the request as a single packet, so no check is necessary for MTU limit

      Ptr<Packet> p = Create<Packet> ();
      SocketIpTtlTag tag;
      p->RemovePacketTag (tag);
      if (senderAddress == Ipv4Address(RIP_ALL_NODE))
        {
          tag.SetTtl (1);
        }
      else
        {
          tag.SetTtl (255);
        }
      p->AddPacketTag (tag);

      RipHeader hdr;
      hdr.SetCommand (RipHeader::RESPONSE);

      for (std::list<RipRte>::iterator iter = rtes.begin ();
          iter != rtes.end (); iter++)
        {
          bool found = false;
          for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
            {

              Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress (rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());
              if ((rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL) &&
                  (rtIter->first->GetRouteStatus () == RipRoutingTableEntry::RIP_VALID))
                {
                  Ipv4Address requestedAddress = iter->GetPrefix ();
                  requestedAddress.CombineMask (iter->GetSubnetMask ());
                  Ipv4Address rtAddress = rtIter->first->GetDestNetwork ();
                  rtAddress.CombineMask (rtIter->first->GetDestNetworkMask ());

                  if (requestedAddress == rtAddress)
                    {
                      iter->SetRouteMetric (rtIter->first->GetRouteMetric ());
                      iter->SetRouteTag (rtIter->first->GetRouteTag ());
                      hdr.AddRte (*iter);
                      found = true;
                      break;
                    }
                }
            }
          if (!found)
            {
              iter->SetRouteMetric (m_linkDown);
              iter->SetRouteTag (0);
              hdr.AddRte (*iter);
            }
        }
      p->AddHeader (hdr);
      NS_LOG_DEBUG ("SendTo: " << *p);
      m_multicastRecvSocket->SendTo (p, 0, InetSocketAddress (senderAddress, senderPort));
    }

}