IPv6 fragmentation enhancements

Tommaso Pecorella 2011-07-09 03:22:59 +02:00
parent 6e08749a57
commit bca1786023
2 changed files with 110 additions and 2 deletions

View File

@ -343,6 +343,10 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
{
fragments = Create<Fragments> ();
m_fragments.insert (std::make_pair (fragmentsId, fragments));
EventId timeout = Simulator::Schedule (Seconds(60),
&Ipv6ExtensionFragment::HandleFragmentsTimeout, this,
fragmentsId, fragments, ipv6Header);
fragments->SetTimeoutEventId (timeout);
}
else
{
@ -361,12 +365,13 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet, uint8_t offset, Ipv
if (fragments->IsEntire ())
{
packet = fragments->GetPacket ();
fragments->CancelTimeout();
m_fragments.erase(fragmentsId);
isDropped = false;
}
else
{
NS_LOG_LOGIC ("Fragment. Drop!");
m_dropTrace (packet);
// the fragment is not "dropped", but Ipv6L3Protocol::LocalDeliver must stop processing it.
isDropped = true;
}
@ -539,6 +544,24 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, uint32_t maxFragme
unfragmentablePart.clear ();
}
void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId, Ptr<Fragments> fragments, Ipv6Header & ipHeader)
{
Ptr<Packet> packet = fragments->GetPartialPacket ();
// if we have at least 8 bytes, we can send an ICMP.
if ( packet->GetSize () > 8 )
{
Ptr<Icmpv6L4Protocol> icmp = GetNode()->GetObject<Icmpv6L4Protocol> ();
icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
}
m_dropTrace (packet);
// clear the buffers
m_fragments.erase(fragmentsId);
}
Ipv6ExtensionFragment::Fragments::Fragments ()
: m_moreFragment (0)
{
@ -608,6 +631,46 @@ Ptr<Packet> Ipv6ExtensionFragment::Fragments::GetPacket () const
return p;
}
Ptr<Packet> Ipv6ExtensionFragment::Fragments::GetPartialPacket () const
{
Ptr<Packet> p;
if ( m_unfragmentable )
{
p = m_unfragmentable->Copy ();
}
else
{
return p;
}
uint16_t lastEndOffset = 0;
for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
{
if (lastEndOffset != it->second)
{
break;
}
p->AddAtEnd (it->first);
lastEndOffset += it->first->GetSize ();
}
return p;
}
void Ipv6ExtensionFragment::Fragments::SetTimeoutEventId (EventId event)
{
m_timeoutEventId = event;
return;
}
void Ipv6ExtensionFragment::Fragments::CancelTimeout()
{
m_timeoutEventId.Cancel ();
return;
}
NS_OBJECT_ENSURE_REGISTERED (Ipv6ExtensionRouting);

View File

@ -319,6 +319,22 @@ public:
*/
Ptr<Packet> GetPacket () const;
/**
* \brief Get the packet parts so far received.
* \return the partial packet
*/
Ptr<Packet> GetPartialPacket () const;
/**
* \brief Set the Timeout EventId.
*/
void SetTimeoutEventId (EventId event);
/**
* \brief Cancel the timeout event
*/
void CancelTimeout ();
private:
/**
* \brief If other fragments will be sent.
@ -339,8 +355,37 @@ private:
* \brief Number of references.
*/
mutable uint32_t m_refCount;
/**
* \brief Timeout handler event
*/
EventId m_timeoutEventId;
};
/**
* \brief Process the timeout for packet fragments
* \param key representing the packet fragments
* \param ipHeader the IP header of the original packet
* \param iif Input Interface
*/
void HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> key, Ptr<Fragments> fragments, Ipv6Header & ipHeader);
/**
* \brief Get the packet parts so far received.
* \return the partial packet
*/
Ptr<Packet> GetPartialPacket () const;
/**
* \brief Set the Timeout EventId.
*/
void SetTimeoutEventId (EventId event);
/**
* \brief Cancel the timeout event
*/
void CancelTimeout ();
typedef std::map<std::pair<Ipv6Address, uint32_t>, Ptr<Fragments> > MapFragments_t;
/**