in simulation/src/internet/model/ipv6-l3-protocol.cc [934:1085]
void Ipv6L3Protocol::Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
{
NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
NS_ASSERT_MSG (GetInterfaceForDevice(device) != -1, "Received a packet from an interface that is not known to IPv6");
uint32_t interface = GetInterfaceForDevice(device);
Ptr<Ipv6Interface> ipv6Interface = m_interfaces[interface];
Ptr<Packet> packet = p->Copy ();
if (ipv6Interface->IsUp ())
{
m_rxTrace (packet, this, interface);
}
else
{
NS_LOG_LOGIC ("Dropping received packet-- interface is down");
Ipv6Header hdr;
packet->RemoveHeader (hdr);
m_dropTrace (hdr, packet, DROP_INTERFACE_DOWN, this, interface);
return;
}
Ipv6Header hdr;
packet->RemoveHeader (hdr);
// Trim any residual frame padding from underlying devices
if (hdr.GetPayloadLength () < packet->GetSize ())
{
packet->RemoveAtEnd (packet->GetSize () - hdr.GetPayloadLength ());
}
// the packet is valid, we update the NDISC cache entry (if present)
Ptr<NdiscCache> ndiscCache = ipv6Interface->GetNdiscCache ();
if (ndiscCache)
{
// case one, it's a a direct routing.
NdiscCache::Entry *entry = ndiscCache->Lookup (hdr.GetSource ());
if (entry)
{
entry->UpdateReachableTimer ();
}
else
{
// It's not in the direct routing, so it's the router, and it could have multiple IP addresses.
// In doubt, update all of them.
// Note: it's a confirmed behavior for Linux routers.
std::list<NdiscCache::Entry *> entryList = ndiscCache->LookupInverse (from);
std::list<NdiscCache::Entry *>::iterator iter;
for (iter = entryList.begin (); iter != entryList.end (); iter ++)
{
(*iter)->UpdateReachableTimer ();
}
}
}
/* forward up to IPv6 raw sockets */
for (SocketList::iterator it = m_sockets.begin (); it != m_sockets.end (); ++it)
{
Ptr<Ipv6RawSocketImpl> socket = *it;
socket->ForwardUp (packet, hdr, device);
}
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
Ptr<Ipv6Extension> ipv6Extension = 0;
uint8_t nextHeader = hdr.GetNextHeader ();
bool stopProcessing = false;
bool isDropped = false;
DropReason dropReason;
if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
{
ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
if (ipv6Extension)
{
ipv6Extension->Process (packet, 0, hdr, hdr.GetDestination (), (uint8_t *)0, stopProcessing, isDropped, dropReason);
}
if (isDropped)
{
m_dropTrace (hdr, packet, dropReason, this, interface);
}
if (stopProcessing)
{
return;
}
}
if (hdr.GetDestination ().IsAllNodesMulticast ())
{
LocalDeliver (packet, hdr, interface);
return;
}
else if (hdr.GetDestination ().IsAllRoutersMulticast() && ipv6Interface->IsForwarding ())
{
LocalDeliver (packet, hdr, interface);
return;
}
else if (hdr.GetDestination ().IsMulticast ())
{
bool isSolicited = ipv6Interface->IsSolicitedMulticastAddress (hdr.GetDestination ());
bool isRegisteredOnInterface = IsRegisteredMulticastAddress (hdr.GetDestination (), interface);
bool isRegisteredGlobally = IsRegisteredMulticastAddress (hdr.GetDestination ());
if (isSolicited || isRegisteredGlobally || isRegisteredOnInterface)
{
LocalDeliver (packet, hdr, interface);
// do not return, the packet could be handled by a routing protocol
}
}
for (uint32_t j = 0; j < GetNInterfaces (); j++)
{
if (j == interface || !m_strongEndSystemModel)
{
for (uint32_t i = 0; i < GetNAddresses (j); i++)
{
Ipv6InterfaceAddress iaddr = GetAddress (j, i);
Ipv6Address addr = iaddr.GetAddress ();
if (addr == hdr.GetDestination ())
{
if (j == interface)
{
NS_LOG_LOGIC ("For me (destination " << addr << " match)");
}
else
{
NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << hdr.GetDestination ());
}
LocalDeliver (packet, hdr, interface);
return;
}
NS_LOG_LOGIC ("Address " << addr << " not a match");
}
}
}
if (!m_routingProtocol->RouteInput (packet, hdr, device,
MakeCallback (&Ipv6L3Protocol::IpForward, this),
MakeCallback (&Ipv6L3Protocol::IpMulticastForward, this),
MakeCallback (&Ipv6L3Protocol::LocalDeliver, this),
MakeCallback (&Ipv6L3Protocol::RouteInputError, this)))
{
NS_LOG_WARN ("No route found for forwarding packet. Drop.");
// Drop trace and ICMPs are courtesy of RouteInputError
}
}