void Rip::HandleResponses()

in simulation/src/internet/model/rip.cc [951:1089]


void Rip::HandleResponses (RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
{
  NS_LOG_FUNCTION (this << senderAddress << incomingInterface << int (hopLimit) << hdr);

  if (m_interfaceExclusions.find (incomingInterface) != m_interfaceExclusions.end ())
    {
      NS_LOG_LOGIC ("Ignoring an update message from an excluded interface: " << incomingInterface);
      return;
    }

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

  // validate the RTEs before processing
  for (std::list<RipRte>::iterator iter = rtes.begin ();
      iter != rtes.end (); iter++)
    {
      if (iter->GetRouteMetric () == 0 || iter->GetRouteMetric () > m_linkDown)
        {
          NS_LOG_LOGIC ("Ignoring an update message with malformed metric: " << int (iter->GetRouteMetric ()));
          return;
        }
      if (iter->GetPrefix ().IsLocalhost () ||
          iter->GetPrefix ().IsBroadcast () ||
          iter->GetPrefix ().IsMulticast ())
        {
          NS_LOG_LOGIC ("Ignoring an update message with wrong prefixes: " << iter->GetPrefix ());
          return;
        }
    }

  bool changed = false;

  for (std::list<RipRte>::iterator iter = rtes.begin ();
      iter != rtes.end (); iter++)
    {
      Ipv4Mask rtePrefixMask = iter->GetSubnetMask ();
      Ipv4Address rteAddr = iter->GetPrefix ().CombineMask (rtePrefixMask);

      NS_LOG_LOGIC ("Processing RTE " << *iter);

      uint32_t interfaceMetric = 1;
      if (m_interfaceMetrics.find (incomingInterface) != m_interfaceMetrics.end ())
        {
          interfaceMetric = m_interfaceMetrics[incomingInterface];
        }
      uint64_t rteMetric = iter->GetRouteMetric () + interfaceMetric;
      if (rteMetric > m_linkDown)
        {
          rteMetric = m_linkDown;
        }

      RoutesI it;
      bool found = false;
      for (it = m_routes.begin (); it != m_routes.end (); it++)
        {
          if (it->first->GetDestNetwork () == rteAddr &&
              it->first->GetDestNetworkMask () == rtePrefixMask)
            {
              found = true;
              if (rteMetric < it->first->GetRouteMetric ())
                {
                  if (senderAddress != it->first->GetGateway ())
                    {
                      RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
                      delete it->first;
                      it->first = route;
                    }
                  it->first->SetRouteMetric (rteMetric);
                  it->first->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
                  it->first->SetRouteTag (iter->GetRouteTag ());
                  it->first->SetRouteChanged (true);
                  it->second.Cancel ();
                  it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
                  changed = true;
                }
              else if (rteMetric == it->first->GetRouteMetric ())
                {
                  if (senderAddress == it->first->GetGateway ())
                    {
                      it->second.Cancel ();
                      it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
                    }
                  else
                    {
                      if (Simulator::GetDelayLeft (it->second) < m_timeoutDelay/2)
                        {
                          RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
                          route->SetRouteMetric (rteMetric);
                          route->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
                          route->SetRouteTag (iter->GetRouteTag ());
                          route->SetRouteChanged (true);
                          delete it->first;
                          it->first = route;
                          it->second.Cancel ();
                          it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, route);
                          changed = true;
                        }
                    }
                }
              else if (rteMetric > it->first->GetRouteMetric () && senderAddress == it->first->GetGateway ())
                {
                  it->second.Cancel ();
                  if (rteMetric < m_linkDown)
                    {
                      it->first->SetRouteMetric (rteMetric);
                      it->first->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
                      it->first->SetRouteTag (iter->GetRouteTag ());
                      it->first->SetRouteChanged (true);
                      it->second.Cancel ();
                      it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
                    }
                  else
                    {
                      InvalidateRoute (it->first);
                    }
                  changed = true;
                }
            }
        }
      if (!found && rteMetric != m_linkDown)
        {
          NS_LOG_LOGIC ("Received a RTE with new route, adding.");

          RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
          route->SetRouteMetric (rteMetric);
          route->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
          route->SetRouteChanged (true);
          m_routes.push_front (std::make_pair (route, EventId ()));
          EventId invalidateEvent = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, route);
          (m_routes.begin ())->second = invalidateEvent;
          changed = true;
        }
    }

  if (changed)
    {
      SendTriggeredRouteUpdate ();
    }
}