void Ipv6L3Protocol::SendRealOut()

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