void RipNg::HandleRequests()

in simulation/src/internet/model/ripng.cc [760:923]


void RipNg::HandleRequests (RipNgHeader requestHdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
{
  NS_LOG_FUNCTION (this << senderAddress << int (senderPort) << incomingInterface << int (hopLimit) << requestHdr);

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

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

  // check if it's a request for the full table from a neighbor
  if (rtes.size () == 1 && senderAddress.IsLinkLocal ())
    {
      if (rtes.begin ()->GetPrefix () == Ipv6Address::GetAny () &&
          rtes.begin ()->GetPrefixLen () == 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_ipv6->GetMtu (incomingInterface);
              uint16_t maxRte = (mtu - Ipv6Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipNgHeader ().GetSerializedSize ()) / RipNgRte ().GetSerializedSize ();

              Ptr<Packet> p = Create<Packet> ();
              SocketIpv6HopLimitTag tag;
              p->RemovePacketTag (tag);
              tag.SetHopLimit (255);
              p->AddPacketTag (tag);

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

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

                  Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress (rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkPrefix ());

                  bool isGlobal = (rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL);
                  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv6Address::GetAny ()) &&
                      (rtIter->first->GetDestNetworkPrefix () == Ipv6Prefix::GetZero ()) &&
                      (rtIter->first->GetInterface () != incomingInterface));

                  if ((isGlobal || isDefaultRoute) &&
                      (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID) )
                    {
                      RipNgRte rte;
                      rte.SetPrefix (rtIter->first->GetDestNetwork ());
                      rte.SetPrefixLen (rtIter->first->GetDestNetworkPrefix ().GetPrefixLength ());
                      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, Inet6SocketAddress (senderAddress, RIPNG_PORT));
                      p->RemoveHeader (hdr);
                      hdr.ClearRtes ();
                    }
                }
              if (hdr.GetRteNumber () > 0)
                {
                  p->AddHeader (hdr);
                  NS_LOG_DEBUG ("SendTo: " << *p);
                  sendingSocket->SendTo (p, 0, Inet6SocketAddress (senderAddress, RIPNG_PORT));
                }
            }
        }
    }
  else
    {
      // note: we got the request as a single packet, so no check is necessary for MTU limit

      // 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;
      if (senderAddress.IsLinkLocal ())
        {
          for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
            {
              if (iter->second == incomingInterface)
                {
                  sendingSocket = iter->first;
                }
            }
        }
      else
        {
          sendingSocket = m_multicastRecvSocket;
        }

      Ptr<Packet> p = Create<Packet> ();
      SocketIpv6HopLimitTag tag;
      p->RemovePacketTag (tag);
      tag.SetHopLimit (255);
      p->AddPacketTag (tag);

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

      for (std::list<RipNgRte>::iterator iter = rtes.begin ();
          iter != rtes.end (); iter++)
        {
          bool found = false;
          for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
            {
              Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkPrefix ());
              if ((rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL) &&
                  (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID))
                {
                  Ipv6Address requestedAddress = iter->GetPrefix ();
                  requestedAddress.CombinePrefix (Ipv6Prefix (iter->GetPrefixLen ()));
                  Ipv6Address rtAddress = rtIter->first->GetDestNetwork ();
                  rtAddress.CombinePrefix (rtIter->first->GetDestNetworkPrefix ());

                  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);
      sendingSocket->SendTo (p, 0, Inet6SocketAddress (senderAddress, senderPort));
    }

}