internet and sixlowpan: optimization to fragment timeout processing

This commit is contained in:
Tommaso Pecorella
2020-03-24 21:24:21 +00:00
parent 5e59a9e7b2
commit a594f16550
6 changed files with 343 additions and 116 deletions

View File

@@ -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

View File

@@ -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}

View File

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

View File

@@ -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
};
/**

View File

@@ -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

View File

@@ -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.
/**