in simulation/src/internet/model/ripng.cc [925:1079]
void RipNg::HandleResponses (RipNgHeader hdr, Ipv6Address 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;
}
if (!senderAddress.IsLinkLocal ())
{
NS_LOG_LOGIC ("Ignoring an update message from a non-link-local source: " << senderAddress);
return;
}
if (hopLimit != 255)
{
NS_LOG_LOGIC ("Ignoring an update message with suspicious hop count: " << int (hopLimit));
return;
}
std::list<RipNgRte> rtes = hdr.GetRteList ();
// validate the RTEs before processing
for (std::list<RipNgRte>::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->GetPrefixLen () > 128)
{
NS_LOG_LOGIC ("Ignoring an update message with malformed prefix length: " << int (iter->GetPrefixLen ()));
return;
}
if (iter->GetPrefix ().IsLocalhost () ||
iter->GetPrefix ().IsLinkLocal () ||
iter->GetPrefix ().IsMulticast ())
{
NS_LOG_LOGIC ("Ignoring an update message with wrong prefixes: " << iter->GetPrefix ());
return;
}
}
bool changed = false;
for (std::list<RipNgRte>::iterator iter = rtes.begin ();
iter != rtes.end (); iter++)
{
Ipv6Prefix rtePrefix = Ipv6Prefix (iter->GetPrefixLen ());
Ipv6Address rteAddr = iter->GetPrefix ().CombinePrefix (rtePrefix);
NS_LOG_LOGIC ("Processing RTE " << *iter);
uint8_t interfaceMetric = 1;
if (m_interfaceMetrics.find (incomingInterface) != m_interfaceMetrics.end ())
{
interfaceMetric = m_interfaceMetrics[incomingInterface];
}
uint16_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->GetDestNetworkPrefix () == rtePrefix)
{
found = true;
if (rteMetric < it->first->GetRouteMetric ())
{
if (senderAddress != it->first->GetGateway ())
{
RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
delete it->first;
it->first = route;
}
it->first->SetRouteMetric (rteMetric);
it->first->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID);
it->first->SetRouteTag (iter->GetRouteTag ());
it->first->SetRouteChanged (true);
it->second.Cancel ();
it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::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, &RipNg::InvalidateRoute, this, it->first);
}
else
{
if (Simulator::GetDelayLeft (it->second) < m_timeoutDelay/2)
{
RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
route->SetRouteMetric (rteMetric);
route->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID);
route->SetRouteTag (iter->GetRouteTag ());
route->SetRouteChanged (true);
delete it->first;
it->first = route;
it->second.Cancel ();
it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::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 (RipNgRoutingTableEntry::RIPNG_VALID);
it->first->SetRouteTag (iter->GetRouteTag ());
it->first->SetRouteChanged (true);
it->second.Cancel ();
it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::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.");
RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
route->SetRouteMetric (rteMetric);
route->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID);
route->SetRouteChanged (true);
m_routes.push_front (std::make_pair (route, EventId ()));
EventId invalidateEvent = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, route);
(m_routes.begin ())->second = invalidateEvent;
changed = true;
}
}
if (changed)
{
SendTriggeredRouteUpdate ();
}
}