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