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