in simulation/src/internet/model/ipv6-l3-protocol.cc [1099:1224]
void Ipv6L3Protocol::SendRealOut (Ptr<Ipv6Route> route, Ptr<Packet> packet, Ipv6Header const& ipHeader)
{
NS_LOG_FUNCTION (this << route << packet << ipHeader);
if (!route)
{
NS_LOG_LOGIC ("No route to host, drop!.");
return;
}
Ptr<NetDevice> dev = route->GetOutputDevice ();
int32_t interface = GetInterfaceForDevice (dev);
NS_ASSERT (interface >= 0);
Ptr<Ipv6Interface> outInterface = GetInterface (interface);
NS_LOG_LOGIC ("Send via NetDevice ifIndex " << dev->GetIfIndex () << " Ipv6InterfaceIndex " << interface);
// Check packet size
std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair> fragments;
// Check if this is the source of the packet
bool fromMe = false;
for (uint32_t i = 0; i < GetNInterfaces (); i++ )
{
for (uint32_t j = 0; j < GetNAddresses (i); j++ )
{
if (GetAddress (i,j).GetAddress () == ipHeader.GetSource ())
{
fromMe = true;
break;
}
}
}
size_t targetMtu = 0;
// Check if we have a Path MTU stored. If so, use it. Else, use the link MTU.
// Note: PMTU must not be cached in intermediate nodes, and must be checked only by the source node
if (fromMe)
{
targetMtu = (size_t)(m_pmtuCache->GetPmtu (ipHeader.GetDestination ()));
}
if (targetMtu == 0)
{
targetMtu = dev->GetMtu ();
}
if (packet->GetSize () + ipHeader.GetSerializedSize () > targetMtu)
{
// Router => drop
if (!fromMe)
{
Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
if ( icmpv6 )
{
packet->AddHeader (ipHeader);
icmpv6->SendErrorTooBig (packet, ipHeader.GetSource (), dev->GetMtu ());
}
return;
}
Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
// To get specific method GetFragments from Ipv6ExtensionFragmentation
Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *> (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
NS_ASSERT (ipv6Fragment != 0);
ipv6Fragment->GetFragments (packet, ipHeader, targetMtu, fragments);
}
if (route->GetGateway () != Ipv6Address::GetAny ())
{
if (outInterface->IsUp ())
{
NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
if (fragments.size () != 0)
{
std::ostringstream oss;
for (std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair>::const_iterator it = fragments.begin (); it != fragments.end (); it++)
{
CallTxTrace (it->second, it->first, this, interface);
outInterface->Send (it->first, it->second, route->GetGateway ());
}
}
else
{
CallTxTrace (ipHeader, packet, this, interface);
outInterface->Send (packet, ipHeader, route->GetGateway ());
}
}
else
{
NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, this, interface);
}
}
else
{
if (outInterface->IsUp ())
{
NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
if (fragments.size () != 0)
{
std::ostringstream oss;
for (std::list<Ipv6ExtensionFragment::Ipv6PayloadHeaderPair>::const_iterator it = fragments.begin (); it != fragments.end (); it++)
{
CallTxTrace (it->second, it->first, this, interface);
outInterface->Send (it->first, it->second, ipHeader.GetDestination ());
}
}
else
{
CallTxTrace (ipHeader, packet, this, interface);
outInterface->Send (packet, ipHeader, ipHeader.GetDestination ());
}
}
else
{
NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ());
m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, this, interface);
}
}
}