diff --git a/src/internet/model/ipv4-l3-protocol.cc b/src/internet/model/ipv4-l3-protocol.cc index ef112c317..e18256446 100644 --- a/src/internet/model/ipv4-l3-protocol.cc +++ b/src/internet/model/ipv4-l3-protocol.cc @@ -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, 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, 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 key; + FragmentKey_t key; bool ret = false; Ptr p = packet->Copy (); @@ -1538,9 +1534,9 @@ Ipv4L3Protocol::ProcessFragment (Ptr& packet, Ipv4Header& ipHeader, uint { fragments = Create (); 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, 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 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 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 diff --git a/src/internet/model/ipv4-l3-protocol.h b/src/internet/model/ipv4-l3-protocol.h index fd0cc76ae..00f15ae8d 100644 --- a/src/internet/model/ipv4-l3-protocol.h +++ b/src/internet/model/ipv4-l3-protocol.h @@ -230,8 +230,8 @@ public: * \param [in] interface */ typedef void (* SentTracedCallback) - (const Ipv4Header & header, Ptr packet, uint32_t interface); - + (const Ipv4Header & header, Ptr packet, uint32_t interface); + /** * TracedCallback signature for packet transmission or reception events. * @@ -243,7 +243,7 @@ public: * and will be changed to \c Ptr in a future release. */ typedef void (* TxRxTracedCallback) - (Ptr packet, Ptr ipv4, uint32_t interface); + (Ptr packet, Ptr ipv4, uint32_t interface); /** * TracedCallback signature for packet drop events. @@ -257,10 +257,10 @@ public: * and will be changed to \c Ptr in a future release. */ typedef void (* DropTracedCallback) - (const Ipv4Header & header, Ptr packet, - DropReason reason, Ptr ipv4, - uint32_t interface); - + (const Ipv4Header & header, Ptr packet, + DropReason reason, Ptr 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, 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 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 FragmentKey_t; + + /// Container for fragment timeouts. + typedef std::list< std::tuple > FragmentsTimeoutsList_t; + /// Container Iterator for fragment timeouts.. + typedef std::list< std::tuple >::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 { -public: + public: /** * \brief Constructor. */ @@ -535,7 +561,19 @@ public: */ Ptr 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, 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, Ptr > MapFragments_t; - /// Container of fragment timeout event, stored as pairs(src+dst addr, src+dst port) / EventId - typedef std::map< std::pair, EventId > MapFragmentsTimers_t; + typedef std::map< FragmentKey_t, Ptr > 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} diff --git a/src/internet/model/ipv6-extension.cc b/src/internet/model/ipv6-extension.cc index 9df8df2ae..b3bea6185 100644 --- a/src/internet/model/ipv6-extension.cc +++ b/src/internet/model/ipv6-extension.cc @@ -315,6 +315,12 @@ TypeId Ipv6ExtensionFragment::GetTypeId () .SetParent () .SetGroupName ("Internet") .AddConstructor () + .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, uint32_t identification = fragmentHeader.GetIdentification (); Ipv6Address src = ipv6Header.GetSourceAddress (); - std::pair fragmentsId = std::pair (src, identification); + FragmentKey_t fragmentsId = FragmentKey_t (src, identification); Ptr fragments; Ipv6Header ipHeader = ipv6Header; @@ -387,10 +398,8 @@ uint8_t Ipv6ExtensionFragment::Process (Ptr& packet, { fragments = Create (); 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, 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, Ipv6Header ipv6Hea hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION); } - unfragmentablePart.push_back (std::pair (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, Ipv6Header ipv6Hea routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION); } - unfragmentablePart.push_back (std::pair (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, Ipv6Header ipv6Hea destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION); } - unfragmentablePart.push_back (std::pair (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION)); + unfragmentablePart.emplace_back (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION); unfragmentablePartSize += extensionHeaderLength; } } @@ -581,7 +591,7 @@ void Ipv6ExtensionFragment::GetFragments (Ptr 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, Ipv6Header ipv6Hea } -void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair fragmentsId, +void Ipv6ExtensionFragment::HandleFragmentsTimeout (FragmentKey_t fragmentsId, Ipv6Header ipHeader) { Ptr fragments; @@ -621,6 +631,44 @@ void Ipv6ExtensionFragment::HandleFragmentsTimeout (std::pair (*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 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; } diff --git a/src/internet/model/ipv6-extension.h b/src/internet/model/ipv6-extension.h index 73d2052ae..caa1034c1 100644 --- a/src/internet/model/ipv6-extension.h +++ b/src/internet/model/ipv6-extension.h @@ -23,6 +23,7 @@ #include #include +#include #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 FragmentKey_t; + + /** + * Container for fragment timeouts. + */ + typedef std::list< std::tuple > FragmentsTimeoutsList_t; + /** + * Container Iterator for fragment timeouts. + */ + typedef std::list< std::tuple >::iterator FragmentsTimeoutsListI_t; + /** * \ingroup ipv6HeaderExt * @@ -367,15 +383,16 @@ public: Ptr 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 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 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, Ptr > MapFragments_t; + typedef std::map > 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 }; /** diff --git a/src/sixlowpan/model/sixlowpan-net-device.cc b/src/sixlowpan/model/sixlowpan-net-device.cc index aff27bba3..dac892117 100644 --- a/src/sixlowpan/model/sixlowpan-net-device.cc +++ b/src/sixlowpan/model/sixlowpan-net-device.cc @@ -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, Address const &sr NS_LOG_FUNCTION ( this << *packet ); SixLowPanFrag1 frag1Header; SixLowPanFragN fragNHeader; - FragmentKey key; + FragmentKey_t key; uint16_t packetSize; key.first = std::pair (src, dst); @@ -2028,16 +2028,8 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr& 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 > storedFragments = m_fragments[oldestKey]->GetFraments (); for (std::list< Ptr >::iterator fragIter = storedFragments.begin (); @@ -2046,8 +2038,7 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr& packet, Address const &sr m_dropTrace (DROP_FRAGMENT_BUFFER_FULL, *fragIter, m_node->GetObject (), 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, 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, 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 > 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 diff --git a/src/sixlowpan/model/sixlowpan-net-device.h b/src/sixlowpan/model/sixlowpan-net-device.h index 3a40f2c92..dccb19ac2 100644 --- a/src/sixlowpan/model/sixlowpan-net-device.h +++ b/src/sixlowpan/model/sixlowpan-net-device.h @@ -25,10 +25,12 @@ #include #include #include +#include #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, std::pair > FragmentKey; + typedef std::pair< std::pair, std::pair > FragmentKey_t; + + /// Container for fragment timeouts. + typedef std::list< std::tuple > FragmentsTimeoutsList_t; + /// Container Iterator for fragment timeouts. + typedef std::list< std::tuple >::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 > 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 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 > MapFragments_t; + typedef std::map< FragmentKey_t, Ptr > MapFragments_t; /** * Container Iterator for fragment key -> fragments. */ - typedef std::map< FragmentKey, Ptr >::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 >::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. /**