internet and sixlowpan: optimization to fragment timeout processing
This commit is contained in:
@@ -324,16 +324,12 @@ Ipv4L3Protocol::DoDispose (void)
|
||||
it->second = 0;
|
||||
}
|
||||
|
||||
for (MapFragmentsTimers_t::iterator it = m_fragmentsTimers.begin (); it != m_fragmentsTimers.end (); it++)
|
||||
{
|
||||
if (it->second.IsRunning ())
|
||||
{
|
||||
it->second.Cancel ();
|
||||
}
|
||||
}
|
||||
|
||||
m_fragments.clear ();
|
||||
m_fragmentsTimers.clear ();
|
||||
m_timeoutEventList.clear ();
|
||||
if (m_timeoutEvent.IsRunning ())
|
||||
{
|
||||
m_timeoutEvent.Cancel ();
|
||||
}
|
||||
|
||||
if (m_cleanDpd.IsRunning ())
|
||||
{
|
||||
@@ -1507,7 +1503,7 @@ Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, const Ipv4Header & ipv4Head
|
||||
|
||||
NS_LOG_LOGIC ("New fragment " << *fragment);
|
||||
|
||||
listFragments.push_back (Ipv4PayloadHeaderPair (fragment, fragmentHeader));
|
||||
listFragments.emplace_back (fragment, fragmentHeader);
|
||||
|
||||
offset += currentFragmentablePartSize;
|
||||
|
||||
@@ -1524,7 +1520,7 @@ Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint
|
||||
|
||||
uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 | uint64_t (ipHeader.GetDestination ().Get ());
|
||||
uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 | uint32_t (ipHeader.GetProtocol ());
|
||||
std::pair<uint64_t, uint32_t> key;
|
||||
FragmentKey_t key;
|
||||
bool ret = false;
|
||||
Ptr<Packet> p = packet->Copy ();
|
||||
|
||||
@@ -1538,9 +1534,9 @@ Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint
|
||||
{
|
||||
fragments = Create<Fragments> ();
|
||||
m_fragments.insert (std::make_pair (key, fragments));
|
||||
m_fragmentsTimers[key] = Simulator::Schedule (m_fragmentExpirationTimeout,
|
||||
&Ipv4L3Protocol::HandleFragmentsTimeout, this,
|
||||
key, ipHeader, iif);
|
||||
|
||||
FragmentsTimeoutsListI_t iter = SetTimeout (key, ipHeader, iif);
|
||||
fragments->SetTimeoutIter (iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1554,14 +1550,9 @@ Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint
|
||||
if ( fragments->IsEntire () )
|
||||
{
|
||||
packet = fragments->GetPacket ();
|
||||
m_timeoutEventList.erase (fragments->GetTimeoutIter ());
|
||||
fragments = 0;
|
||||
m_fragments.erase (key);
|
||||
if (m_fragmentsTimers[key].IsRunning ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Stopping WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
|
||||
m_fragmentsTimers[key].Cancel ();
|
||||
}
|
||||
m_fragmentsTimers.erase (key);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
@@ -1706,7 +1697,21 @@ Ipv4L3Protocol::Fragments::GetPartialPacket () const
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4Header & ipHeader, uint32_t iif)
|
||||
Ipv4L3Protocol::Fragments::SetTimeoutIter (FragmentsTimeoutsListI_t iter)
|
||||
{
|
||||
m_timeoutIter = iter;
|
||||
return;
|
||||
}
|
||||
|
||||
Ipv4L3Protocol::FragmentsTimeoutsListI_t
|
||||
Ipv4L3Protocol::Fragments::GetTimeoutIter ()
|
||||
{
|
||||
return m_timeoutIter;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Ipv4L3Protocol::HandleFragmentsTimeout (FragmentKey_t key, Ipv4Header & ipHeader, uint32_t iif)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
|
||||
|
||||
@@ -1725,7 +1730,6 @@ Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4H
|
||||
it->second = 0;
|
||||
|
||||
m_fragments.erase (key);
|
||||
m_fragmentsTimers.erase (key);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1834,5 +1838,44 @@ Ipv4L3Protocol::RemoveDuplicates (void)
|
||||
}
|
||||
}
|
||||
|
||||
Ipv4L3Protocol::FragmentsTimeoutsListI_t
|
||||
Ipv4L3Protocol::SetTimeout (FragmentKey_t key, Ipv4Header ipHeader, uint32_t iif)
|
||||
{
|
||||
Time now = Simulator::Now () + m_fragmentExpirationTimeout;
|
||||
|
||||
if (m_timeoutEventList.empty ())
|
||||
{
|
||||
m_timeoutEvent = Simulator::Schedule (m_fragmentExpirationTimeout, &Ipv4L3Protocol::HandleTimeout, this);
|
||||
}
|
||||
m_timeoutEventList.emplace_back (now, key, ipHeader, iif);
|
||||
|
||||
Ipv4L3Protocol::FragmentsTimeoutsListI_t iter = --m_timeoutEventList.end();
|
||||
|
||||
return (iter);
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4L3Protocol::HandleTimeout (void)
|
||||
{
|
||||
Time now = Simulator::Now ();
|
||||
|
||||
while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
|
||||
{
|
||||
HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
|
||||
std::get<2> (*m_timeoutEventList.begin ()),
|
||||
std::get<3> (*m_timeoutEventList.begin ()));
|
||||
m_timeoutEventList.pop_front ();
|
||||
}
|
||||
|
||||
if (m_timeoutEventList.empty ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
|
||||
m_timeoutEvent = Simulator::Schedule (difference, &Ipv4L3Protocol::HandleTimeout, this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -230,8 +230,8 @@ public:
|
||||
* \param [in] interface
|
||||
*/
|
||||
typedef void (* SentTracedCallback)
|
||||
(const Ipv4Header & header, Ptr<const Packet> packet, uint32_t interface);
|
||||
|
||||
(const Ipv4Header & header, Ptr<const Packet> packet, uint32_t interface);
|
||||
|
||||
/**
|
||||
* TracedCallback signature for packet transmission or reception events.
|
||||
*
|
||||
@@ -243,7 +243,7 @@ public:
|
||||
* and will be changed to \c Ptr<const Ipv4> in a future release.
|
||||
*/
|
||||
typedef void (* TxRxTracedCallback)
|
||||
(Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
|
||||
(Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
|
||||
|
||||
/**
|
||||
* TracedCallback signature for packet drop events.
|
||||
@@ -257,10 +257,10 @@ public:
|
||||
* and will be changed to \c Ptr<const Ipv4> in a future release.
|
||||
*/
|
||||
typedef void (* DropTracedCallback)
|
||||
(const Ipv4Header & header, Ptr<const Packet> packet,
|
||||
DropReason reason, Ptr<Ipv4> ipv4,
|
||||
uint32_t interface);
|
||||
|
||||
(const Ipv4Header & header, Ptr<const Packet> packet,
|
||||
DropReason reason, Ptr<Ipv4> ipv4,
|
||||
uint32_t interface);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void DoDispose (void);
|
||||
@@ -309,13 +309,13 @@ private:
|
||||
* \return newly created IPv4 header
|
||||
*/
|
||||
Ipv4Header BuildHeader (
|
||||
Ipv4Address source,
|
||||
Ipv4Address destination,
|
||||
uint8_t protocol,
|
||||
uint16_t payloadSize,
|
||||
uint8_t ttl,
|
||||
uint8_t tos,
|
||||
bool mayFragment);
|
||||
Ipv4Address source,
|
||||
Ipv4Address destination,
|
||||
uint8_t protocol,
|
||||
uint16_t payloadSize,
|
||||
uint8_t ttl,
|
||||
uint8_t tos,
|
||||
bool mayFragment);
|
||||
|
||||
/**
|
||||
* \brief Send packet with route.
|
||||
@@ -415,14 +415,6 @@ private:
|
||||
*/
|
||||
bool ProcessFragment (Ptr<Packet>& packet, Ipv4Header & ipHeader, uint32_t iif);
|
||||
|
||||
/**
|
||||
* \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<uint64_t, uint32_t> key, Ipv4Header & ipHeader, uint32_t iif);
|
||||
|
||||
/**
|
||||
* \brief Make a copy of the packet, add the header and invoke the TX trace callback
|
||||
* \param ipHeader the IP header that will be added to the packet
|
||||
@@ -493,12 +485,46 @@ private:
|
||||
|
||||
SocketList m_sockets; //!< List of IPv4 raw sockets.
|
||||
|
||||
/// Key identifying a fragmented packet
|
||||
typedef std::pair<uint64_t, uint32_t> FragmentKey_t;
|
||||
|
||||
/// Container for fragment timeouts.
|
||||
typedef std::list< std::tuple <Time, FragmentKey_t, Ipv4Header, uint32_t > > FragmentsTimeoutsList_t;
|
||||
/// Container Iterator for fragment timeouts..
|
||||
typedef std::list< std::tuple <Time, FragmentKey_t, Ipv4Header, uint32_t > >::iterator FragmentsTimeoutsListI_t;
|
||||
|
||||
/**
|
||||
* \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 (FragmentKey_t key, Ipv4Header & ipHeader, uint32_t iif);
|
||||
|
||||
/**
|
||||
* \brief Set a new timeout "event" for a fragmented packet
|
||||
* \param key the fragment identification
|
||||
* \param ipHeader the IPv4 header of the fragmented packet
|
||||
* \param iif input interface of the packet
|
||||
* \return an iterator to the inserted "event"
|
||||
*/
|
||||
FragmentsTimeoutsListI_t SetTimeout (FragmentKey_t key, Ipv4Header ipHeader, uint32_t iif);
|
||||
|
||||
/**
|
||||
* \brief Handles a fragmented packet timeout
|
||||
*/
|
||||
void HandleTimeout (void);
|
||||
|
||||
FragmentsTimeoutsList_t m_timeoutEventList; //!< Timeout "events" container
|
||||
|
||||
EventId m_timeoutEvent; //!< Event for the next scheduled timeout
|
||||
|
||||
/**
|
||||
* \brief A Set of Fragment belonging to the same packet (src, dst, identification and proto)
|
||||
*/
|
||||
class Fragments : public SimpleRefCount<Fragments>
|
||||
{
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* \brief Constructor.
|
||||
*/
|
||||
@@ -535,7 +561,19 @@ public:
|
||||
*/
|
||||
Ptr<Packet> GetPartialPacket () const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Set the Timeout iterator.
|
||||
* \param iter The iterator.
|
||||
*/
|
||||
void SetTimeoutIter (FragmentsTimeoutsListI_t iter);
|
||||
|
||||
/**
|
||||
* \brief Get the Timeout iterator.
|
||||
* \returns The iterator.
|
||||
*/
|
||||
FragmentsTimeoutsListI_t GetTimeoutIter ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief True if other fragments will be sent.
|
||||
*/
|
||||
@@ -546,16 +584,17 @@ private:
|
||||
*/
|
||||
std::list<std::pair<Ptr<Packet>, uint16_t> > m_fragments;
|
||||
|
||||
/**
|
||||
* \brief Timeout iterator to "event" handler
|
||||
*/
|
||||
FragmentsTimeoutsListI_t m_timeoutIter;
|
||||
};
|
||||
|
||||
/// Container of fragments, stored as pairs(src+dst addr, src+dst port) / fragment
|
||||
typedef std::map< std::pair<uint64_t, uint32_t>, Ptr<Fragments> > MapFragments_t;
|
||||
/// Container of fragment timeout event, stored as pairs(src+dst addr, src+dst port) / EventId
|
||||
typedef std::map< std::pair<uint64_t, uint32_t>, EventId > MapFragmentsTimers_t;
|
||||
typedef std::map< FragmentKey_t, Ptr<Fragments> > MapFragments_t;
|
||||
|
||||
MapFragments_t m_fragments; //!< Fragmented packets.
|
||||
Time m_fragmentExpirationTimeout; //!< Expiration timeout
|
||||
MapFragmentsTimers_t m_fragmentsTimers; //!< Expiration events.
|
||||
|
||||
/// IETF RFC 6621, Section 6.2 de-duplication w/o IPSec
|
||||
/// RFC 6621 recommended duplicate packet tuple: {IPV hash, IP protocol, IP source address, IP destination address}
|
||||
|
||||
@@ -315,6 +315,12 @@ TypeId Ipv6ExtensionFragment::GetTypeId ()
|
||||
.SetParent<Ipv6Extension> ()
|
||||
.SetGroupName ("Internet")
|
||||
.AddConstructor<Ipv6ExtensionFragment> ()
|
||||
.AddAttribute ("FragmentExpirationTimeout",
|
||||
"When this timeout expires, the fragments "
|
||||
"will be cleared from the buffer.",
|
||||
TimeValue (Seconds (60)),
|
||||
MakeTimeAccessor (&Ipv6ExtensionFragment::m_fragmentExpirationTimeout),
|
||||
MakeTimeChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@@ -339,6 +345,11 @@ void Ipv6ExtensionFragment::DoDispose ()
|
||||
}
|
||||
|
||||
m_fragments.clear ();
|
||||
m_timeoutEventList.clear ();
|
||||
if (m_timeoutEvent.IsRunning ())
|
||||
{
|
||||
m_timeoutEvent.Cancel ();
|
||||
}
|
||||
Ipv6Extension::DoDispose ();
|
||||
}
|
||||
|
||||
@@ -376,7 +387,7 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet,
|
||||
uint32_t identification = fragmentHeader.GetIdentification ();
|
||||
Ipv6Address src = ipv6Header.GetSourceAddress ();
|
||||
|
||||
std::pair<Ipv6Address, uint32_t> fragmentsId = std::pair<Ipv6Address, uint32_t> (src, identification);
|
||||
FragmentKey_t fragmentsId = FragmentKey_t (src, identification);
|
||||
Ptr<Fragments> fragments;
|
||||
|
||||
Ipv6Header ipHeader = ipv6Header;
|
||||
@@ -387,10 +398,8 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet,
|
||||
{
|
||||
fragments = Create<Fragments> ();
|
||||
m_fragments.insert (std::make_pair (fragmentsId, fragments));
|
||||
EventId timeout = Simulator::Schedule (Seconds (60),
|
||||
&Ipv6ExtensionFragment::HandleFragmentsTimeout, this,
|
||||
fragmentsId, ipHeader);
|
||||
fragments->SetTimeoutEventId (timeout);
|
||||
FragmentsTimeoutsListI_t iter = SetTimeout (fragmentsId, ipHeader);
|
||||
fragments->SetTimeoutIter (iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -409,7 +418,8 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr<Packet>& packet,
|
||||
if (fragments->IsEntire ())
|
||||
{
|
||||
packet = fragments->GetPacket ();
|
||||
fragments->CancelTimeout ();
|
||||
|
||||
m_timeoutEventList.erase (fragments->GetTimeoutIter ());
|
||||
m_fragments.erase (fragmentsId);
|
||||
stopProcessing = false;
|
||||
}
|
||||
@@ -466,7 +476,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, Ipv6Header ipv6Hea
|
||||
hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
|
||||
}
|
||||
|
||||
unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
|
||||
unfragmentablePart.emplace_back (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP);
|
||||
unfragmentablePartSize += extensionHeaderLength;
|
||||
}
|
||||
else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
|
||||
@@ -490,7 +500,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, Ipv6Header ipv6Hea
|
||||
routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
|
||||
}
|
||||
|
||||
unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
|
||||
unfragmentablePart.emplace_back (routingHeader, Ipv6Header::IPV6_EXT_ROUTING);
|
||||
unfragmentablePartSize += extensionHeaderLength;
|
||||
}
|
||||
else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
|
||||
@@ -510,7 +520,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, Ipv6Header ipv6Hea
|
||||
destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
|
||||
}
|
||||
|
||||
unfragmentablePart.push_back (std::pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
|
||||
unfragmentablePart.emplace_back (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION);
|
||||
unfragmentablePartSize += extensionHeaderLength;
|
||||
}
|
||||
}
|
||||
@@ -581,7 +591,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, Ipv6Header ipv6Hea
|
||||
oss << ipv6Header;
|
||||
fragment->Print (oss);
|
||||
|
||||
listFragments.push_back (Ipv6PayloadHeaderPair (fragment, ipv6Header));
|
||||
listFragments.emplace_back (fragment, ipv6Header);
|
||||
}
|
||||
while (moreFragment);
|
||||
|
||||
@@ -594,7 +604,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr<Packet> packet, Ipv6Header ipv6Hea
|
||||
}
|
||||
|
||||
|
||||
void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> fragmentsId,
|
||||
void Ipv6ExtensionFragment::HandleFragmentsTimeout (FragmentKey_t fragmentsId,
|
||||
Ipv6Header ipHeader)
|
||||
{
|
||||
Ptr<Fragments> fragments;
|
||||
@@ -621,6 +631,44 @@ void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair<Ipv6Address, uint3
|
||||
m_fragments.erase (fragmentsId);
|
||||
}
|
||||
|
||||
|
||||
Ipv6ExtensionFragment::FragmentsTimeoutsListI_t Ipv6ExtensionFragment::SetTimeout (FragmentKey_t key, Ipv6Header ipHeader)
|
||||
{
|
||||
if (m_timeoutEventList.empty ())
|
||||
{
|
||||
m_timeoutEvent = Simulator::Schedule (m_fragmentExpirationTimeout, &Ipv6ExtensionFragment::HandleTimeout, this);
|
||||
}
|
||||
m_timeoutEventList.emplace_back (Simulator::Now () + m_fragmentExpirationTimeout, key, ipHeader);
|
||||
|
||||
Ipv6ExtensionFragment::FragmentsTimeoutsListI_t iter = --m_timeoutEventList.end();
|
||||
|
||||
return (iter);
|
||||
}
|
||||
|
||||
void Ipv6ExtensionFragment::HandleTimeout (void)
|
||||
{
|
||||
Time now = Simulator::Now ();
|
||||
|
||||
while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
|
||||
{
|
||||
HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
|
||||
std::get<2> (*m_timeoutEventList.begin ()));
|
||||
m_timeoutEventList.pop_front ();
|
||||
}
|
||||
|
||||
if (m_timeoutEventList.empty ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
|
||||
m_timeoutEvent = Simulator::Schedule (difference, &Ipv6ExtensionFragment::HandleTimeout, this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ipv6ExtensionFragment::Fragments::Fragments ()
|
||||
: m_moreFragment (0)
|
||||
{
|
||||
@@ -718,16 +766,15 @@ Ptr<Packet> Ipv6ExtensionFragment::Fragments::GetPartialPacket () const
|
||||
return p;
|
||||
}
|
||||
|
||||
void Ipv6ExtensionFragment::Fragments::SetTimeoutEventId (EventId event)
|
||||
void Ipv6ExtensionFragment::Fragments::SetTimeoutIter (FragmentsTimeoutsListI_t iter)
|
||||
{
|
||||
m_timeoutEventId = event;
|
||||
m_timeoutIter = iter;
|
||||
return;
|
||||
}
|
||||
|
||||
void Ipv6ExtensionFragment::Fragments::CancelTimeout ()
|
||||
Ipv6ExtensionFragment::FragmentsTimeoutsListI_t Ipv6ExtensionFragment::Fragments::GetTimeoutIter ()
|
||||
{
|
||||
m_timeoutEventId.Cancel ();
|
||||
return;
|
||||
return m_timeoutIter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <tuple>
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/node.h"
|
||||
@@ -316,6 +317,21 @@ protected:
|
||||
virtual void DoDispose ();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Key identifying a fragmented packet
|
||||
*/
|
||||
typedef std::pair<Ipv6Address, uint32_t> FragmentKey_t;
|
||||
|
||||
/**
|
||||
* Container for fragment timeouts.
|
||||
*/
|
||||
typedef std::list< std::tuple <Time, FragmentKey_t, Ipv6Header > > FragmentsTimeoutsList_t;
|
||||
/**
|
||||
* Container Iterator for fragment timeouts.
|
||||
*/
|
||||
typedef std::list< std::tuple <Time, FragmentKey_t, Ipv6Header > >::iterator FragmentsTimeoutsListI_t;
|
||||
|
||||
/**
|
||||
* \ingroup ipv6HeaderExt
|
||||
*
|
||||
@@ -367,15 +383,16 @@ public:
|
||||
Ptr<Packet> GetPartialPacket () const;
|
||||
|
||||
/**
|
||||
* \brief Set the Timeout EventId.
|
||||
* \param event The event.
|
||||
* \brief Set the Timeout iterator.
|
||||
* \param iter The iterator.
|
||||
*/
|
||||
void SetTimeoutEventId (EventId event);
|
||||
void SetTimeoutIter (FragmentsTimeoutsListI_t iter);
|
||||
|
||||
/**
|
||||
* \brief Cancel the timeout event
|
||||
* \brief Get the Timeout iterator.
|
||||
* \returns The iterator.
|
||||
*/
|
||||
void CancelTimeout ();
|
||||
FragmentsTimeoutsListI_t GetTimeoutIter ();
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -394,9 +411,9 @@ private:
|
||||
Ptr<Packet> m_unfragmentable;
|
||||
|
||||
/**
|
||||
* \brief Timeout handler event
|
||||
* \brief Timeout iterator to "event" handler
|
||||
*/
|
||||
EventId m_timeoutEventId;
|
||||
FragmentsTimeoutsListI_t m_timeoutIter;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -404,7 +421,7 @@ private:
|
||||
* \param key representing the packet fragments
|
||||
* \param ipHeader the IP header of the original packet
|
||||
*/
|
||||
void HandleFragmentsTimeout (std::pair<Ipv6Address, uint32_t> key, Ipv6Header ipHeader);
|
||||
void HandleFragmentsTimeout (FragmentKey_t key, Ipv6Header ipHeader);
|
||||
|
||||
/**
|
||||
* \brief Get the packet parts so far received.
|
||||
@@ -426,12 +443,29 @@ private:
|
||||
/**
|
||||
* \brief Container for the packet fragments.
|
||||
*/
|
||||
typedef std::map<std::pair<Ipv6Address, uint32_t>, Ptr<Fragments> > MapFragments_t;
|
||||
typedef std::map<FragmentKey_t, Ptr<Fragments> > MapFragments_t;
|
||||
|
||||
/**
|
||||
* \brief The hash of fragmented packets.
|
||||
*/
|
||||
MapFragments_t m_fragments;
|
||||
|
||||
/**
|
||||
* \brief Set a new timeout "event" for a fragmented packet
|
||||
* \param key the fragment identification
|
||||
* \param ipHeader the IPv6 header of the fragmented packet
|
||||
* \return an iterator to the inserted "event"
|
||||
*/
|
||||
FragmentsTimeoutsListI_t SetTimeout (FragmentKey_t key, Ipv6Header ipHeader);
|
||||
|
||||
/**
|
||||
* \brief Handles a fragmented packet timeout
|
||||
*/
|
||||
void HandleTimeout (void);
|
||||
|
||||
FragmentsTimeoutsList_t m_timeoutEventList; //!< Timeout "events" container
|
||||
EventId m_timeoutEvent; //!< Event for the next scheduled timeout
|
||||
Time m_fragmentExpirationTimeout; //!< Expiration timeout
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -173,11 +173,11 @@ void SixLowPanNetDevice::DoDispose ()
|
||||
m_netDevice = 0;
|
||||
m_node = 0;
|
||||
|
||||
for (MapFragmentsTimersI_t iter = m_fragmentsTimers.begin (); iter != m_fragmentsTimers.end (); iter++)
|
||||
m_timeoutEventList.clear ();
|
||||
if (m_timeoutEvent.IsRunning ())
|
||||
{
|
||||
iter->second.Cancel ();
|
||||
m_timeoutEvent.Cancel ();
|
||||
}
|
||||
m_fragmentsTimers.clear ();
|
||||
|
||||
for (MapFragmentsI_t iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
|
||||
{
|
||||
@@ -1962,7 +1962,7 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &sr
|
||||
NS_LOG_FUNCTION ( this << *packet );
|
||||
SixLowPanFrag1 frag1Header;
|
||||
SixLowPanFragN fragNHeader;
|
||||
FragmentKey key;
|
||||
FragmentKey_t key;
|
||||
uint16_t packetSize;
|
||||
key.first = std::pair<Address, Address> (src, dst);
|
||||
|
||||
@@ -2028,16 +2028,8 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &sr
|
||||
// erase the oldest packet.
|
||||
if ( m_fragmentReassemblyListSize && (m_fragments.size () >= m_fragmentReassemblyListSize) )
|
||||
{
|
||||
MapFragmentsTimers_t::iterator iter;
|
||||
MapFragmentsTimers_t::iterator iterFound = m_fragmentsTimers.begin ();
|
||||
for ( iter = m_fragmentsTimers.begin (); iter != m_fragmentsTimers.end (); iter++)
|
||||
{
|
||||
if ( iter->second.GetTs () < iterFound->second.GetTs () )
|
||||
{
|
||||
iterFound = iter;
|
||||
}
|
||||
}
|
||||
FragmentKey oldestKey = iterFound->first;
|
||||
FragmentsTimeoutsListI_t iter = m_timeoutEventList.begin ();
|
||||
FragmentKey_t oldestKey = std::get<1> (*iter);
|
||||
|
||||
std::list< Ptr<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
|
||||
for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
|
||||
@@ -2046,8 +2038,7 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &sr
|
||||
m_dropTrace (DROP_FRAGMENT_BUFFER_FULL, *fragIter, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
|
||||
}
|
||||
|
||||
m_fragmentsTimers[oldestKey].Cancel ();
|
||||
m_fragmentsTimers.erase (oldestKey);
|
||||
m_timeoutEventList.erase (m_fragments[oldestKey]->GetTimeoutIter ());
|
||||
m_fragments[oldestKey] = 0;
|
||||
m_fragments.erase (oldestKey);
|
||||
|
||||
@@ -2056,9 +2047,9 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &sr
|
||||
fragments->SetPacketSize (packetSize);
|
||||
m_fragments.insert (std::make_pair (key, fragments));
|
||||
uint32_t ifIndex = GetIfIndex ();
|
||||
m_fragmentsTimers[key] = Simulator::Schedule (m_fragmentExpirationTimeout,
|
||||
&SixLowPanNetDevice::HandleFragmentsTimeout, this,
|
||||
key, ifIndex);
|
||||
|
||||
FragmentsTimeoutsListI_t iter = SetTimeout (key, ifIndex);
|
||||
fragments->SetTimeoutIter (iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2083,14 +2074,9 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &sr
|
||||
packet->RemoveHeader (frag1Header);
|
||||
|
||||
NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
|
||||
m_timeoutEventList.erase (fragments->GetTimeoutIter ());
|
||||
fragments = 0;
|
||||
m_fragments.erase (key);
|
||||
if (m_fragmentsTimers[key].IsRunning ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Stopping 6LoWPAN WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
|
||||
m_fragmentsTimers[key].Cancel ();
|
||||
}
|
||||
m_fragmentsTimers.erase (key);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2220,7 +2206,20 @@ std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
|
||||
return fragments;
|
||||
}
|
||||
|
||||
void SixLowPanNetDevice::HandleFragmentsTimeout (FragmentKey key, uint32_t iif)
|
||||
void
|
||||
SixLowPanNetDevice::Fragments::SetTimeoutIter (FragmentsTimeoutsListI_t iter)
|
||||
{
|
||||
m_timeoutIter = iter;
|
||||
return;
|
||||
}
|
||||
|
||||
SixLowPanNetDevice::FragmentsTimeoutsListI_t
|
||||
SixLowPanNetDevice::Fragments::GetTimeoutIter ()
|
||||
{
|
||||
return m_timeoutIter;
|
||||
}
|
||||
|
||||
void SixLowPanNetDevice::HandleFragmentsTimeout (FragmentKey_t key, uint32_t iif)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
@@ -2235,7 +2234,6 @@ void SixLowPanNetDevice::HandleFragmentsTimeout (FragmentKey key, uint32_t iif)
|
||||
it->second = 0;
|
||||
|
||||
m_fragments.erase (key);
|
||||
m_fragmentsTimers.erase (key);
|
||||
}
|
||||
|
||||
Address SixLowPanNetDevice::Get16MacFrom48Mac (Address addr)
|
||||
@@ -2251,6 +2249,41 @@ Address SixLowPanNetDevice::Get16MacFrom48Mac (Address addr)
|
||||
return shortAddr;
|
||||
}
|
||||
|
||||
SixLowPanNetDevice::FragmentsTimeoutsListI_t SixLowPanNetDevice::SetTimeout (FragmentKey_t key, uint32_t iif)
|
||||
{
|
||||
if (m_timeoutEventList.empty ())
|
||||
{
|
||||
m_timeoutEvent = Simulator::Schedule (m_fragmentExpirationTimeout, &SixLowPanNetDevice::HandleTimeout, this);
|
||||
}
|
||||
m_timeoutEventList.emplace_back (Simulator::Now () + m_fragmentExpirationTimeout, key, iif);
|
||||
|
||||
SixLowPanNetDevice::FragmentsTimeoutsListI_t iter = --m_timeoutEventList.end();
|
||||
|
||||
return (iter);
|
||||
}
|
||||
|
||||
void SixLowPanNetDevice::HandleTimeout (void)
|
||||
{
|
||||
Time now = Simulator::Now ();
|
||||
|
||||
while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
|
||||
{
|
||||
HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
|
||||
std::get<2> (*m_timeoutEventList.begin ()));
|
||||
m_timeoutEventList.pop_front ();
|
||||
}
|
||||
|
||||
if (m_timeoutEventList.empty ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
|
||||
m_timeoutEvent = Simulator::Schedule (difference, &SixLowPanNetDevice::HandleTimeout, this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// namespace ns3
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -352,7 +354,29 @@ private:
|
||||
/**
|
||||
* Fragment identifier type: src/dst address src/dst port.
|
||||
*/
|
||||
typedef std::pair< std::pair<Address, Address>, std::pair<uint16_t, uint16_t> > FragmentKey;
|
||||
typedef std::pair< std::pair<Address, Address>, std::pair<uint16_t, uint16_t> > FragmentKey_t;
|
||||
|
||||
/// Container for fragment timeouts.
|
||||
typedef std::list< std::tuple <Time, FragmentKey_t, uint32_t > > FragmentsTimeoutsList_t;
|
||||
/// Container Iterator for fragment timeouts.
|
||||
typedef std::list< std::tuple <Time, FragmentKey_t, uint32_t > >::iterator FragmentsTimeoutsListI_t;
|
||||
|
||||
/**
|
||||
* \brief Set a new timeout "event" for a fragmented packet
|
||||
* \param key the fragment identification
|
||||
* \param iif input interface of the packet
|
||||
* \return an iterator to the inserted "event"
|
||||
*/
|
||||
FragmentsTimeoutsListI_t SetTimeout (FragmentKey_t key, uint32_t iif);
|
||||
|
||||
/**
|
||||
* \brief Handles a fragmented packet timeout
|
||||
*/
|
||||
void HandleTimeout (void);
|
||||
|
||||
FragmentsTimeoutsList_t m_timeoutEventList; //!< Timeout "events" container
|
||||
|
||||
EventId m_timeoutEvent; //!< Event for the next scheduled timeout
|
||||
|
||||
/**
|
||||
* \brief A Set of Fragments.
|
||||
@@ -408,6 +432,18 @@ public:
|
||||
*/
|
||||
std::list< Ptr<Packet> > GetFraments () const;
|
||||
|
||||
/**
|
||||
* \brief Set the Timeout iterator.
|
||||
* \param iter The iterator.
|
||||
*/
|
||||
void SetTimeoutIter (FragmentsTimeoutsListI_t iter);
|
||||
|
||||
/**
|
||||
* \brief Get the Timeout iterator.
|
||||
* \returns The iterator.
|
||||
*/
|
||||
FragmentsTimeoutsListI_t GetTimeoutIter ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief The size of the reconstructed packet (bytes).
|
||||
@@ -424,6 +460,10 @@ private:
|
||||
*/
|
||||
Ptr<Packet> m_firstFragment;
|
||||
|
||||
/**
|
||||
* \brief Timeout iterator to "event" handler
|
||||
*/
|
||||
FragmentsTimeoutsListI_t m_timeoutIter;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -451,7 +491,7 @@ private:
|
||||
* \param [in] key A key representing the packet fragments.
|
||||
* \param [in] iif Input Interface.
|
||||
*/
|
||||
void HandleFragmentsTimeout ( FragmentKey key, uint32_t iif);
|
||||
void HandleFragmentsTimeout (FragmentKey_t key, uint32_t iif);
|
||||
|
||||
/**
|
||||
* \brief Drops the oldest fragment set.
|
||||
@@ -460,7 +500,7 @@ private:
|
||||
|
||||
/**
|
||||
* Get a Mac16 from its Mac48 pseudo-MAC
|
||||
* \param addr the PseudoMac adddress
|
||||
* \param addr the PseudoMac address
|
||||
* \return the Mac16Address
|
||||
*/
|
||||
Address Get16MacFrom48Mac (Address addr);
|
||||
@@ -468,22 +508,13 @@ private:
|
||||
/**
|
||||
* Container for fragment key -> fragments.
|
||||
*/
|
||||
typedef std::map< FragmentKey, Ptr<Fragments> > MapFragments_t;
|
||||
typedef std::map< FragmentKey_t, Ptr<Fragments> > MapFragments_t;
|
||||
/**
|
||||
* Container Iterator for fragment key -> fragments.
|
||||
*/
|
||||
typedef std::map< FragmentKey, Ptr<Fragments> >::iterator MapFragmentsI_t;
|
||||
/**
|
||||
* Container for fragment key -> expiration event.
|
||||
*/
|
||||
typedef std::map< FragmentKey, EventId > MapFragmentsTimers_t;
|
||||
/**
|
||||
* Container Iterator for fragment key -> expiration event.
|
||||
*/
|
||||
typedef std::map< FragmentKey, EventId >::iterator MapFragmentsTimersI_t;
|
||||
typedef std::map< FragmentKey_t, Ptr<Fragments> >::iterator MapFragmentsI_t;
|
||||
|
||||
MapFragments_t m_fragments; //!< Fragments hold to be rebuilt.
|
||||
MapFragmentsTimers_t m_fragmentsTimers; //!< Timers related to fragment rebuilding.
|
||||
Time m_fragmentExpirationTimeout; //!< Time limit for fragment rebuilding.
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user