diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/AUTHORS ns-3.30.1/AUTHORS
--- ns-3.30/AUTHORS 2019-08-12 19:42:05.000000000 -0700
+++ ns-3.30.1/AUTHORS 2019-09-18 10:36:11.000000000 -0700
@@ -83,6 +83,7 @@
Christopher Hepner (hepner@hs-ulm.de)
Budiarto Herman (budiarto.herman@magister.fi)
Tom Hewer (tomhewer@mac.com)
+Jack Higgins (shattered.feelings@gmail.com)
Kristian A. Hiorth (kristahi@ifi.uio.no)
Kim Højgaard-Hansen (kimrhh@gmail.com)
Chris Hood (chood8@gatech.edu)
@@ -179,6 +180,7 @@
Michele Polese (michele.polese@gmail.com)
Ovidiu Poncea (ovidiu.poncea@cs.pub.ro)
Vikas Pushkar (vikaskupushkar@gmail.com)
+Alberto Gallegos Ramonet (ramonet@fc.ritsumei.ac.jp)
Manoj Kumar Rana (manoj24.rana@gmail.com)
Andrea Ranieri (andreran@uno.it)
Bruno Ranieri (Yrrsinn@googlemail.com)
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/CHANGES.html ns-3.30.1/CHANGES.html
--- ns-3.30/CHANGES.html 2019-08-13 10:50:16.000000000 -0700
+++ ns-3.30.1/CHANGES.html 2019-09-18 10:36:11.000000000 -0700
@@ -51,6 +51,21 @@
us a note on ns-developers mailing list.
+Changes from ns-3.30 to ns-3.31
+New API:
+
+Changes to existing API:
+
+Changes to build system:
+
+Changed behavior:
+
+
+
Changes from ns-3.29 to ns-3.30
New API:
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/doc/manual/source/conf.py ns-3.30.1/doc/manual/source/conf.py
--- ns-3.30/doc/manual/source/conf.py 2019-08-12 16:30:33.000000000 -0700
+++ ns-3.30.1/doc/manual/source/conf.py 2019-09-18 11:07:48.000000000 -0700
@@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
-version = 'ns-3-dev'
+version = 'ns-3.30'
# The full version, including alpha/beta/rc tags.
-release = 'ns-3-dev'
+release = 'ns-3.30'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/doc/models/source/conf.py ns-3.30.1/doc/models/source/conf.py
--- ns-3.30/doc/models/source/conf.py 2019-08-12 16:30:33.000000000 -0700
+++ ns-3.30.1/doc/models/source/conf.py 2019-09-18 11:07:48.000000000 -0700
@@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
-version = 'ns-3-dev'
+version = 'ns-3.30'
# The full version, including alpha/beta/rc tags.
-release = 'ns-3-dev'
+release = 'ns-3.30'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/doc/tutorial/source/conf.py ns-3.30.1/doc/tutorial/source/conf.py
--- ns-3.30/doc/tutorial/source/conf.py 2019-08-12 16:30:33.000000000 -0700
+++ ns-3.30.1/doc/tutorial/source/conf.py 2019-09-18 11:07:48.000000000 -0700
@@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
-version = 'ns-3-dev'
+version = 'ns-3.30'
# The full version, including alpha/beta/rc tags.
-release = 'ns-3-dev'
+release = 'ns-3.30'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/doc/tutorial/source/tracing.rst ns-3.30.1/doc/tutorial/source/tracing.rst
--- ns-3.30/doc/tutorial/source/tracing.rst 2019-08-12 16:30:33.000000000 -0700
+++ ns-3.30.1/doc/tutorial/source/tracing.rst 2019-09-18 10:36:11.000000000 -0700
@@ -2097,7 +2097,7 @@
system! You would be correct. But, bear with us. We're not done
yet.
-One of the most important things we want to do is to is to have the
+One of the most important things we want to do is to have the
ability to easily control the amount of output coming out of the
simulation; and we also want to save those data to a file so we can
refer back to it later. We can use the mid-level trace helpers
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/doc/tutorial-pt-br/source/conf.py ns-3.30.1/doc/tutorial-pt-br/source/conf.py
--- ns-3.30/doc/tutorial-pt-br/source/conf.py 2019-08-12 16:30:33.000000000 -0700
+++ ns-3.30.1/doc/tutorial-pt-br/source/conf.py 2019-09-18 11:07:48.000000000 -0700
@@ -50,9 +50,9 @@
# built documents.
#
# The short X.Y version.
-version = 'ns-3-dev'
+version = 'ns-3.30'
# The full version, including alpha/beta/rc tags.
-release = 'ns-3-dev'
+release = 'ns-3.30'
# The language for content autogenerated by . Refer to babel documentation
# for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/RELEASE_NOTES ns-3.30.1/RELEASE_NOTES
--- ns-3.30/RELEASE_NOTES 2019-08-13 10:38:27.000000000 -0700
+++ ns-3.30.1/RELEASE_NOTES 2019-09-18 10:41:27.000000000 -0700
@@ -9,6 +9,61 @@
Consult the file CHANGES.html for more detailed information about changed
API and behavior across ns-3 releases.
+Release 3-dev
+=============
+
+Availability
+------------
+This release is not yet available.
+
+Supported platforms
+-------------------
+To be determined.
+
+New user-visible features
+-------------------------
+
+Bugs fixed
+----------
+
+Known issues
+------------
+In general, known issues are tracked on the project tracker available
+at https://gitlab.com/nsnam/ns-3-dev/issues
+
+Release 3.30.1
+==============
+Release 3.30.1 is a maintenance release that fixes the following issues from
+the ns-3.30 release:
+
+- fix issue with Block Ack transmit window leading to low throughput or
+ connection dropping
+- fix invalid restriction on Wi-Fi VHT Capabilities MaxMpduLength field
+- support for Apple clang version 11.0.0 (macOS Catalina preview release)
+- fix the handling of ICMP time exceeded responses
+- fix syntax error in Wi-Fi-based Tap Bridge Python example
+
+Availability
+------------
+This release is available from:
+https://www.nsnam.org/release/ns-allinone-3.30.1.tar.bz2
+
+Supported platforms
+-------------------
+The list of supported platforms includes those listed for ns-3.30 plus
+- macOS 10.15 preview (Catalina) with Apple clang version 11.0.0
+
+New user-visible features
+-------------------------
+Features are identical to release 3.30.
+
+Bugs fixed
+----------
+- Issue #62 - ICMP does not handle ICMPv4 TIME_EXCEEDED responses
+- Issue #77 - Wi-Fi VHT capabilities MaxMpduLength had invalid restriction
+- Issue #79 - Wi-Fi connection drop or low throughput due to Block Ack transmit window
+- Example program tap-wifi-virtual-machine.py had a syntax error
+
Release 3.30
============
@@ -130,7 +185,7 @@
Known issues
------------
In general, known issues are tracked on the project tracker available
-at http://www.nsnam.org/bugzilla/
+at https://gitlab.com/nsnam/ns-3-dev/issues
Release 3.29
============
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/aodv/model/aodv-rqueue.cc ns-3.30.1/src/aodv/model/aodv-rqueue.cc
--- ns-3.30/src/aodv/model/aodv-rqueue.cc 2019-08-12 16:30:33.000000000 -0700
+++ ns-3.30.1/src/aodv/model/aodv-rqueue.cc 2019-09-18 10:36:11.000000000 -0700
@@ -76,13 +76,14 @@
for (std::vector::iterator i = m_queue.begin (); i
!= m_queue.end (); ++i)
{
- if (IsEqual (*i, dst))
+ if (i->GetIpv4Header ().GetDestination () == dst)
{
Drop (*i, "DropPacketWithDst ");
}
}
- m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (),
- std::bind2nd (std::ptr_fun (RequestQueue::IsEqual), dst)), m_queue.end ());
+ auto new_end = std::remove_if (m_queue.begin (), m_queue.end (),
+ [&](const QueueEntry& en) { return en.GetIpv4Header ().GetDestination () == dst; });
+ m_queue.erase (new_end, m_queue.end ());
}
bool
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/aodv/model/aodv-rqueue.h ns-3.30.1/src/aodv/model/aodv-rqueue.h
--- ns-3.30/src/aodv/model/aodv-rqueue.h 2019-08-12 16:30:33.000000000 -0700
+++ ns-3.30.1/src/aodv/model/aodv-rqueue.h 2019-09-18 10:36:11.000000000 -0700
@@ -271,16 +271,6 @@
uint32_t m_maxLen;
/// The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
Time m_queueTimeout;
- /**
- * Determine if queue matches a destination address
- * \param en The queue entry
- * \param dst The destination IPv4 address
- * \returns true if the queue entry matches the destination address
- */
- static bool IsEqual (QueueEntry en, const Ipv4Address dst)
- {
- return (en.GetIpv4Header ().GetDestination () == dst);
- }
};
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/applications/model/bulk-send-application.cc ns-3.30.1/src/applications/model/bulk-send-application.cc
--- ns-3.30/src/applications/model/bulk-send-application.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/applications/model/bulk-send-application.cc 2019-09-18 10:36:11.000000000 -0700
@@ -202,7 +202,7 @@
}
// We exit this loop when actual < toSend as the send side
// buffer is full. The "DataSent" callback will pop when
- // some buffer space has freed ip.
+ // some buffer space has freed up.
if ((unsigned)actual != toSend)
{
break;
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/applications/model/onoff-application.cc ns-3.30.1/src/applications/model/onoff-application.cc
--- ns-3.30/src/applications/model/onoff-application.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/applications/model/onoff-application.cc 2019-09-18 10:36:11.000000000 -0700
@@ -142,6 +142,7 @@
{
NS_LOG_FUNCTION (this);
+ CancelEvents ();
m_socket = 0;
// chain up
Application::DoDispose ();
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsdv/model/dsdv-packet-queue.cc ns-3.30.1/src/dsdv/model/dsdv-packet-queue.cc
--- ns-3.30/src/dsdv/model/dsdv-packet-queue.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsdv/model/dsdv-packet-queue.cc 2019-09-18 10:36:11.000000000 -0700
@@ -88,13 +88,14 @@
for (std::vector::iterator i = m_queue.begin (); i
!= m_queue.end (); ++i)
{
- if (IsEqual (*i, dst))
+ if (i->GetIpv4Header ().GetDestination () == dst)
{
Drop (*i, "DropPacketWithDst ");
}
}
- m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (),
- std::bind2nd (std::ptr_fun (PacketQueue::IsEqual), dst)), m_queue.end ());
+ auto new_end = std::remove_if (m_queue.begin (), m_queue.end (), [&](const QueueEntry& en)
+ { return en.GetIpv4Header ().GetDestination () == dst; });
+ m_queue.erase (new_end, m_queue.end ());
}
bool
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsdv/model/dsdv-packet-queue.h ns-3.30.1/src/dsdv/model/dsdv-packet-queue.h
--- ns-3.30/src/dsdv/model/dsdv-packet-queue.h 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsdv/model/dsdv-packet-queue.h 2019-09-18 10:36:11.000000000 -0700
@@ -291,16 +291,6 @@
uint32_t m_maxLenPerDst;
/// The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
Time m_queueTimeout;
- /**
- * Determine if queue entries are equal
- * \param en the queue entry
- * \param dst the IPv4 destination address
- * \returns true if the entry is for the destination address
- */
- static bool IsEqual (QueueEntry en, const Ipv4Address dst)
- {
- return (en.GetIpv4Header ().GetDestination () == dst);
- }
};
}
}
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsr/model/dsr-errorbuff.cc ns-3.30.1/src/dsr/model/dsr-errorbuff.cc
--- ns-3.30/src/dsr/model/dsr-errorbuff.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsr/model/dsr-errorbuff.cc 2019-09-18 10:36:11.000000000 -0700
@@ -96,13 +96,15 @@
for (std::vector::iterator i = m_errorBuffer.begin (); i
!= m_errorBuffer.end (); ++i)
{
- if (LinkEqual (*i, link))
+ if ((i->GetSource () == link[0]) && (i->GetNextHop () == link[1]))
{
DropLink (*i, "DropPacketForErrLink");
}
}
- m_errorBuffer.erase (std::remove_if (m_errorBuffer.begin (), m_errorBuffer.end (),
- std::bind2nd (std::ptr_fun (DsrErrorBuffer::LinkEqual), link)), m_errorBuffer.end ());
+
+ auto new_end = std::remove_if (m_errorBuffer.begin (), m_errorBuffer.end (), [&](const DsrErrorBuffEntry& en)
+ { return (en.GetSource () == link[0]) && (en.GetNextHop () == link[1]); });
+ m_errorBuffer.erase (new_end, m_errorBuffer.end ());
}
bool
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsr/model/dsr-errorbuff.h ns-3.30.1/src/dsr/model/dsr-errorbuff.h
--- ns-3.30/src/dsr/model/dsr-errorbuff.h 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsr/model/dsr-errorbuff.h 2019-09-18 10:36:11.000000000 -0700
@@ -298,17 +298,6 @@
uint32_t m_maxLen;
/// The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
Time m_errorBufferTimeout;
- /**
- * Check if the send buffer entry is the same or not
- * \param en Buffer Entry
- * \param link Link description.
- * \return true if the entry is compatible with the link description (source and next hop)
- */
- ///
- static bool LinkEqual (DsrErrorBuffEntry en, const std::vector link)
- {
- return ((en.GetSource () == link[0]) && (en.GetNextHop () == link[1]));
- }
};
/*******************************************************************************************************************************/
} // namespace dsr
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsr/model/dsr-maintain-buff.cc ns-3.30.1/src/dsr/model/dsr-maintain-buff.cc
--- ns-3.30/src/dsr/model/dsr-maintain-buff.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsr/model/dsr-maintain-buff.cc 2019-09-18 10:36:11.000000000 -0700
@@ -85,8 +85,10 @@
NS_LOG_FUNCTION (this << nextHop);
Purge ();
NS_LOG_INFO ("Drop Packet With next hop " << nextHop);
- m_maintainBuffer.erase (std::remove_if (m_maintainBuffer.begin (), m_maintainBuffer.end (),
- std::bind2nd (std::ptr_fun (DsrMaintainBuffer::IsEqual), nextHop)), m_maintainBuffer.end ());
+
+ auto new_end = std::remove_if (m_maintainBuffer.begin (), m_maintainBuffer.end (), [&](const DsrMaintainBuffEntry& en)
+ { return en.GetNextHop () == nextHop; });
+ m_maintainBuffer.erase (new_end, m_maintainBuffer.end ());
}
bool
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsr/model/dsr-maintain-buff.h ns-3.30.1/src/dsr/model/dsr-maintain-buff.h
--- ns-3.30/src/dsr/model/dsr-maintain-buff.h 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsr/model/dsr-maintain-buff.h 2019-09-18 10:36:11.000000000 -0700
@@ -483,14 +483,6 @@
uint32_t m_maxLen;
/// The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
Time m_maintainBufferTimeout;
- /// Verify if the maintain buffer is equal or not
- /// \param en The Entry to check
- /// \param nextHop The next hop to check
- /// \return true if an Entry next hop is equal to the function second parameter
- static bool IsEqual (DsrMaintainBuffEntry en, const Ipv4Address nextHop)
- {
- return (en.GetNextHop () == nextHop);
- }
};
/*******************************************************************************************************************************/
} // namespace dsr
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsr/model/dsr-rsendbuff.cc ns-3.30.1/src/dsr/model/dsr-rsendbuff.cc
--- ns-3.30/src/dsr/model/dsr-rsendbuff.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsr/model/dsr-rsendbuff.cc 2019-09-18 10:36:11.000000000 -0700
@@ -91,13 +91,14 @@
for (std::vector::iterator i = m_sendBuffer.begin (); i
!= m_sendBuffer.end (); ++i)
{
- if (IsEqual (*i, dst))
+ if (i->GetDestination () == dst)
{
Drop (*i, "DropPacketWithDst");
}
}
- m_sendBuffer.erase (std::remove_if (m_sendBuffer.begin (), m_sendBuffer.end (),
- std::bind2nd (std::ptr_fun (DsrSendBuffer::IsEqual), dst)), m_sendBuffer.end ());
+ auto new_end = std::remove_if (m_sendBuffer.begin (), m_sendBuffer.end (), [&](const DsrSendBuffEntry& en)
+ { return en.GetDestination () == dst; });
+ m_sendBuffer.erase (new_end, m_sendBuffer.end ());
}
bool
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/dsr/model/dsr-rsendbuff.h ns-3.30.1/src/dsr/model/dsr-rsendbuff.h
--- ns-3.30/src/dsr/model/dsr-rsendbuff.h 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/dsr/model/dsr-rsendbuff.h 2019-09-18 10:36:11.000000000 -0700
@@ -259,18 +259,6 @@
uint32_t m_maxLen; ///< The maximum number of packets that we allow a routing protocol to buffer.
Time m_sendBufferTimeout; ///< The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
- /**
- * Check if the send buffer entry is the same or not
- *
- * \param en SendBufferEntry
- * \param dst IPv4 address to check
- * \return true if the SendBufferEntry destination is the same,
- * false otherwise
- */
- static bool IsEqual (DsrSendBuffEntry en, const Ipv4Address dst)
- {
- return (en.GetDestination () == dst);
- }
};
/*******************************************************************************************************************************/
} // namespace dsr
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/internet/model/ipv4-l3-protocol.cc ns-3.30.1/src/internet/model/ipv4-l3-protocol.cc
--- ns-3.30/src/internet/model/ipv4-l3-protocol.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/internet/model/ipv4-l3-protocol.cc 2019-09-18 10:36:11.000000000 -0700
@@ -1029,9 +1029,8 @@
ipHeader.SetTtl (ipHeader.GetTtl () - 1);
if (ipHeader.GetTtl () == 0)
{
- // Do not reply to ICMP or to multicast/broadcast IP address
- if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER &&
- ipHeader.GetDestination ().IsBroadcast () == false &&
+ // Do not reply to multicast/broadcast IP address
+ if (ipHeader.GetDestination ().IsBroadcast () == false &&
ipHeader.GetDestination ().IsMulticast () == false)
{
Ptr icmp = GetIcmp ();
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/internet/test/icmp-test.cc ns-3.30.1/src/internet/test/icmp-test.cc
--- ns-3.30/src/internet/test/icmp-test.cc 1969-12-31 16:00:00.000000000 -0800
+++ ns-3.30.1/src/internet/test/icmp-test.cc 2019-09-18 10:36:11.000000000 -0700
@@ -0,0 +1,692 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2019 Ritsumeikan University, Shiga, Japan.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Alberto Gallegos Ramonet
+ */
+
+// Test program for the Internet Control Message Protocol (ICMP) responses.
+//
+// IcmpEchoReplyTestCase scenario:
+//
+// n0 <------------------> n1
+// i(0,0) i(1,0)
+//
+// Test that sends a single ICMP echo packet with TTL = 1 from n0 to n1,
+// n1 receives the packet and send an ICMP echo reply.
+//
+//
+// IcmpTimeExceedTestCase scenario:
+//
+// channel1 channel2
+// n0 <------------------> n1 <---------------------> n2
+// i(0,0) i(1,0) i2(1,0)
+// i2(0,0)
+//
+// Test that sends a single ICMP echo packet with TTL = 1 from n0 to n4,
+// however, the TTL is not enough and n1 reply to n0 with an ICMP time exceed.
+//
+//
+// IcmpV6EchoReplyTestCase scenario:
+//
+// n0 <-------------------> n1
+// i(0,1) i(1,1)
+//
+// Test that sends a single ICMPV6 ECHO request with hopLimit = 1 from n0 to n1,
+// n1 receives the packet and send an ICMPV6 echo reply.
+//
+// IcmpV6TimeExceedTestCase scenario:
+//
+// channel1 channel2
+// n0 <------------------> n1 <---------------------> n2
+// i(0,0) i(1,0) i2(1,0)
+// i2(0,0)
+//
+// Test that sends a single ICMPV6 echo packet with hopLimit = 1 from n0 to n4,
+// however, the hopLimit is not enough and n1 reply to n0 with an ICMPV6 time exceed error.
+
+
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/ipv6-address-helper.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/simple-net-device-helper.h"
+#include "ns3/simulator.h"
+#include "ns3/icmpv6-header.h"
+#include "ns3/icmpv4.h"
+#include "ns3/socket.h"
+#include "ns3/socket-factory.h"
+#include "ns3/uinteger.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/ipv4-global-routing-helper.h"
+#include "ns3/ipv6-static-routing-helper.h"
+#include "ns3/ipv6-routing-helper.h"
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/internet-stack-helper.h"
+
+#include "ns3/test.h"
+
+using namespace ns3;
+
+/**
+ * \ingroup internet-apps
+ * \defgroup icmp-test ICMP protocol tests
+ */
+
+
+/**
+ * \ingroup icmp-test
+ * \ingroup tests
+ *
+ * \brief ICMP Echo Reply Test
+ */
+class IcmpEchoReplyTestCase : public TestCase
+{
+public:
+ IcmpEchoReplyTestCase ();
+ virtual ~IcmpEchoReplyTestCase ();
+
+ void SendData (Ptr socket, Ipv4Address dst);
+ void DoSendData (Ptr socket, Ipv4Address dst);
+ void ReceivePkt (Ptr socket);
+
+private:
+ virtual void DoRun (void);
+ Ptr m_receivedPacket;
+
+};
+
+
+IcmpEchoReplyTestCase::IcmpEchoReplyTestCase ()
+ : TestCase ("ICMP:EchoReply test case")
+{
+
+}
+
+
+IcmpEchoReplyTestCase::~IcmpEchoReplyTestCase ()
+{
+
+}
+
+
+void
+IcmpEchoReplyTestCase::DoSendData (Ptr socket, Ipv4Address dst)
+{
+ Ptr p = Create ();
+ Icmpv4Echo echo;
+ echo.SetSequenceNumber (1);
+ echo.SetIdentifier (0);
+ p->AddHeader (echo);
+
+ Icmpv4Header header;
+ header.SetType (Icmpv4Header::ICMPV4_ECHO);
+ header.SetCode (0);
+ p->AddHeader (header);
+
+ Address realTo = InetSocketAddress (dst, 1234);
+
+ NS_TEST_EXPECT_MSG_EQ (socket->SendTo (p, 0, realTo),
+ (int) p->GetSize (), " Unable to send ICMP Echo Packet");
+
+}
+
+
+void
+IcmpEchoReplyTestCase::SendData (Ptr socket, Ipv4Address dst)
+{
+ m_receivedPacket = Create ();
+ Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+ &IcmpEchoReplyTestCase::DoSendData, this, socket, dst);
+ Simulator::Run ();
+}
+
+void
+IcmpEchoReplyTestCase::ReceivePkt (Ptr socket)
+{
+ Address from;
+ Ptr p = socket->RecvFrom (0xffffffff, 0, from);
+ m_receivedPacket = p->Copy ();
+
+ Ipv4Header ipv4;
+ p->RemoveHeader (ipv4);
+ NS_TEST_EXPECT_MSG_EQ (ipv4.GetProtocol (), 1," The received Packet is not an ICMP packet");
+
+ Icmpv4Header icmp;
+ p->RemoveHeader (icmp);
+
+ NS_TEST_EXPECT_MSG_EQ (icmp.GetType (), Icmpv4Header::ICMPV4_ECHO_REPLY,
+ " The received Packet is not a ICMPV4_ECHO_REPLY");
+}
+
+
+void
+IcmpEchoReplyTestCase::DoRun ()
+{
+ NodeContainer n;
+ n.Create (2);
+
+ InternetStackHelper internet;
+ internet.Install (n);
+
+ // link the two nodes
+ Ptr txDev = CreateObject ();
+ Ptr rxDev = CreateObject ();
+ n.Get (0)->AddDevice (txDev);
+ n.Get (1)->AddDevice (rxDev);
+ Ptr channel1 = CreateObject ();
+ rxDev->SetChannel (channel1);
+ txDev->SetChannel (channel1);
+ NetDeviceContainer d;
+ d.Add (txDev);
+ d.Add (rxDev);
+
+ Ipv4AddressHelper ipv4;
+
+ ipv4.SetBase ("10.0.0.0", "255.255.255.252");
+ Ipv4InterfaceContainer i = ipv4.Assign (d);
+
+ Ptr socket;
+ socket = Socket::CreateSocket (n.Get (0), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
+ socket->SetAttribute ("Protocol", UintegerValue (1)); // ICMP protocol
+ socket->SetRecvCallback (MakeCallback (&IcmpEchoReplyTestCase::ReceivePkt, this));
+
+ InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0);
+ NS_TEST_EXPECT_MSG_EQ (socket->Bind (src),0," Socket Binding failed");
+
+ // Set a TTL big enough
+ socket->SetIpTtl (1);
+ SendData (socket, i.GetAddress (1,0));
+
+ NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 28, " Unexpected ICMPV4_ECHO_REPLY packet size");
+
+
+ Simulator::Destroy ();
+}
+
+
+/**
+ * \ingroup icmp-test
+ * \ingroup tests
+ *
+ * \brief ICMP Time Exceed Reply Test
+ */
+class IcmpTimeExceedTestCase : public TestCase
+{
+public:
+ IcmpTimeExceedTestCase ();
+ virtual ~IcmpTimeExceedTestCase ();
+
+ void SendData (Ptr socket, Ipv4Address dst);
+ void DoSendData (Ptr socket, Ipv4Address dst);
+ void ReceivePkt (Ptr socket);
+
+private:
+ virtual void DoRun (void);
+ Ptr m_receivedPacket;
+
+};
+
+
+IcmpTimeExceedTestCase::IcmpTimeExceedTestCase ()
+ : TestCase ("ICMP:TimeExceedReply test case")
+{
+
+}
+
+
+IcmpTimeExceedTestCase::~IcmpTimeExceedTestCase ()
+{
+
+}
+
+
+void
+IcmpTimeExceedTestCase::DoSendData (Ptr socket, Ipv4Address dst)
+{
+ Ptr p = Create ();
+ Icmpv4Echo echo;
+ echo.SetSequenceNumber (1);
+ echo.SetIdentifier (0);
+ p->AddHeader (echo);
+
+ Icmpv4Header header;
+ header.SetType (Icmpv4Header::ICMPV4_ECHO);
+ header.SetCode (0);
+ p->AddHeader (header);
+
+ Address realTo = InetSocketAddress (dst, 1234);
+
+ NS_TEST_EXPECT_MSG_EQ (socket->SendTo (p, 0, realTo),
+ (int) p->GetSize (), " Unable to send ICMP Echo Packet");
+}
+
+
+void
+IcmpTimeExceedTestCase::SendData (Ptr socket, Ipv4Address dst)
+{
+ m_receivedPacket = Create ();
+ Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+ &IcmpTimeExceedTestCase::DoSendData, this, socket, dst);
+ Simulator::Run ();
+}
+
+
+void
+IcmpTimeExceedTestCase::ReceivePkt (Ptr socket)
+{
+ Address from;
+ Ptr p = socket->RecvFrom (0xffffffff, 0, from);
+ m_receivedPacket = p->Copy ();
+
+ Ipv4Header ipv4;
+ p->RemoveHeader (ipv4);
+ NS_TEST_EXPECT_MSG_EQ (ipv4.GetProtocol (), 1,"The received packet is not an ICMP packet");
+
+ NS_TEST_EXPECT_MSG_EQ (ipv4.GetSource (),Ipv4Address ("10.0.0.2"),
+ "ICMP Time Exceed Response should come from 10.0.0.2");
+
+ Icmpv4Header icmp;
+ p->RemoveHeader (icmp);
+
+ NS_TEST_EXPECT_MSG_EQ (icmp.GetType (), Icmpv4Header::ICMPV4_TIME_EXCEEDED,
+ "The received packet is not a ICMPV4_TIME_EXCEEDED packet ");
+}
+
+
+void
+IcmpTimeExceedTestCase::DoRun ()
+{
+ NodeContainer n, n0n1,n1n2;
+ n.Create (3);
+ n0n1.Add (n.Get (0));
+ n0n1.Add (n.Get (1));
+ n1n2.Add (n.Get (1));
+ n1n2.Add (n.Get (2));
+
+ Ptr channel = CreateObject ();
+ Ptr channel2 = CreateObject ();
+
+ SimpleNetDeviceHelper simpleHelper;
+ simpleHelper.SetNetDevicePointToPointMode (true);
+
+ SimpleNetDeviceHelper simpleHelper2;
+ simpleHelper2.SetNetDevicePointToPointMode (true);
+
+ NetDeviceContainer devices;
+ devices = simpleHelper.Install (n0n1,channel);
+ NetDeviceContainer devices2;
+ devices2 = simpleHelper2.Install (n1n2,channel2);
+
+ InternetStackHelper internet;
+ internet.Install (n);
+
+ Ipv4AddressHelper address;
+ address.SetBase ("10.0.0.0","255.255.255.255");
+ Ipv4InterfaceContainer i = address.Assign (devices);
+
+ address.SetBase ("10.0.1.0","255.255.255.255");
+ Ipv4InterfaceContainer i2 = address.Assign (devices2);
+
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+ Ptr socket;
+ socket = Socket::CreateSocket (n.Get (0), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
+ socket->SetAttribute ("Protocol", UintegerValue (1)); // ICMP protocol
+ socket->SetRecvCallback (MakeCallback (&IcmpTimeExceedTestCase::ReceivePkt, this));
+
+ InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0);
+ NS_TEST_EXPECT_MSG_EQ (socket->Bind (src),0," Socket Binding failed");
+
+
+ // The ttl is not big enough , causing an ICMP Time Exceeded response
+ socket->SetIpTtl (1);
+ SendData (socket, i2.GetAddress (1,0));
+
+ NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 56, " Unexpected ICMP Time Exceed Response packet size");
+
+ Simulator::Destroy ();
+}
+
+
+/**
+ * \ingroup icmp-test
+ * \ingroup tests
+ *
+ * \brief ICMPV6 Echo Reply Test
+ */
+class IcmpV6EchoReplyTestCase : public TestCase
+{
+public:
+ IcmpV6EchoReplyTestCase ();
+ virtual ~IcmpV6EchoReplyTestCase ();
+
+ void SendData (Ptr socket, Ipv6Address dst);
+ void DoSendData (Ptr socket, Ipv6Address dst);
+ void ReceivePkt (Ptr socket);
+
+private:
+ virtual void DoRun (void);
+ Ptr m_receivedPacket;
+
+};
+
+
+IcmpV6EchoReplyTestCase::IcmpV6EchoReplyTestCase ()
+ : TestCase ("ICMPV6:EchoReply test case")
+{
+
+}
+
+
+IcmpV6EchoReplyTestCase::~IcmpV6EchoReplyTestCase ()
+{
+
+}
+
+
+void
+IcmpV6EchoReplyTestCase::DoSendData (Ptr socket, Ipv6Address dst)
+{
+ Ptr p = Create ();
+ Icmpv6Echo echo (1);
+ echo.SetSeq (1);
+ echo.SetId (0XB1ED);
+ p->AddHeader (echo);
+
+ Icmpv6Header header;
+ header.SetType (Icmpv6Header::ICMPV6_ECHO_REQUEST);
+ header.SetCode (0);
+ p->AddHeader (header);
+
+ Address realTo = Inet6SocketAddress (dst, 1234);
+
+ NS_TEST_EXPECT_MSG_EQ (socket->SendTo (p, 0, realTo),
+ (int) p->GetSize (), " Unable to send ICMP Echo Packet");
+
+}
+
+
+void
+IcmpV6EchoReplyTestCase::SendData (Ptr socket, Ipv6Address dst)
+{
+ m_receivedPacket = Create ();
+ Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+ &IcmpV6EchoReplyTestCase::DoSendData, this, socket, dst);
+ Simulator::Run ();
+}
+
+void
+IcmpV6EchoReplyTestCase::ReceivePkt (Ptr socket)
+{
+ Address from;
+ Ptr p = socket->RecvFrom (from);
+ m_receivedPacket = p->Copy ();
+
+ if (Inet6SocketAddress::IsMatchingType (from))
+ {
+ Ipv6Header ipv6;
+ p->RemoveHeader (ipv6);
+
+ NS_TEST_EXPECT_MSG_EQ (ipv6.GetNextHeader (),
+ Ipv6Header::IPV6_ICMPV6,
+ "The received Packet is not an ICMPV6 packet");
+ Icmpv6Header icmpv6;
+ p->RemoveHeader (icmpv6);
+
+ // Ignore the neighbor discovery (ICMPV6_ND) packets
+ if (!(((int)icmpv6.GetType () >= 133) && ((int)icmpv6.GetType () <= 137)))
+ {
+ NS_TEST_EXPECT_MSG_EQ ((int) icmpv6.GetType (),
+ Icmpv6Header::ICMPV6_ECHO_REPLY,
+ "The received Packet is not a ICMPV6_ECHO_REPLY");
+ }
+ }
+}
+
+
+void
+IcmpV6EchoReplyTestCase::DoRun ()
+{
+ NodeContainer n;
+ n.Create (2);
+
+ InternetStackHelper internet;
+ internet.Install (n);
+
+ // link the two nodes
+ Ptr txDev = CreateObject ();
+ Ptr rxDev = CreateObject ();
+ txDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
+ rxDev->SetAddress (Mac48Address ("00:00:00:00:00:02"));
+ n.Get (0)->AddDevice (txDev);
+ n.Get (1)->AddDevice (rxDev);
+ Ptr channel1 = CreateObject ();
+ rxDev->SetChannel (channel1);
+ txDev->SetChannel (channel1);
+ NetDeviceContainer d;
+ d.Add (txDev);
+ d.Add (rxDev);
+
+ Ipv6AddressHelper ipv6;
+
+ ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
+ Ipv6InterfaceContainer i = ipv6.Assign (d);
+
+ Ptr socket;
+ socket = Socket::CreateSocket (n.Get (0), TypeId::LookupByName ("ns3::Ipv6RawSocketFactory"));
+ socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
+ socket->SetRecvCallback (MakeCallback (&IcmpV6EchoReplyTestCase::ReceivePkt, this));
+
+ Inet6SocketAddress src = Inet6SocketAddress (Ipv6Address::GetAny (), 0);
+ NS_TEST_EXPECT_MSG_EQ (socket->Bind (src),0," SocketV6 Binding failed");
+
+ // Set a TTL big enough
+ socket->SetIpTtl (1);
+
+ SendData (socket, i.GetAddress (1,1));
+
+ NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 72, " Unexpected ICMPV6_ECHO_REPLY packet size");
+
+ Simulator::Destroy ();
+}
+
+
+/**
+ * \ingroup icmp-test
+ * \ingroup tests
+ *
+ * \brief ICMPV6 Time Exceed response test
+ */
+class IcmpV6TimeExceedTestCase : public TestCase
+{
+public:
+ IcmpV6TimeExceedTestCase ();
+ virtual ~IcmpV6TimeExceedTestCase ();
+
+ void SendData (Ptr socket, Ipv6Address dst);
+ void DoSendData (Ptr socket, Ipv6Address dst);
+ void ReceivePkt (Ptr socket);
+
+private:
+ virtual void DoRun (void);
+ Ptr m_receivedPacket;
+
+};
+
+
+IcmpV6TimeExceedTestCase::IcmpV6TimeExceedTestCase ()
+ : TestCase ("ICMPV6:TimeExceed test case")
+{
+
+}
+
+
+IcmpV6TimeExceedTestCase::~IcmpV6TimeExceedTestCase ()
+{
+
+}
+
+
+void
+IcmpV6TimeExceedTestCase::DoSendData (Ptr socket, Ipv6Address dst)
+{
+ Ptr p = Create ();
+ Icmpv6Echo echo (1);
+ echo.SetSeq (1);
+ echo.SetId (0XB1ED);
+ p->AddHeader (echo);
+
+ Icmpv6Header header;
+ header.SetType (Icmpv6Header::ICMPV6_ECHO_REQUEST);
+ header.SetCode (0);
+ p->AddHeader (header);
+
+ Address realTo = Inet6SocketAddress (dst, 1234);
+
+
+ socket->SendTo (p, 0, realTo);
+
+}
+
+
+void
+IcmpV6TimeExceedTestCase::SendData (Ptr socket, Ipv6Address dst)
+{
+ m_receivedPacket = Create ();
+ Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+ &IcmpV6TimeExceedTestCase::DoSendData, this, socket, dst);
+ Simulator::Run ();
+}
+
+void
+IcmpV6TimeExceedTestCase::ReceivePkt (Ptr socket)
+{
+ Address from;
+ Ptr p = socket->RecvFrom (from);
+ m_receivedPacket = p->Copy ();
+
+ if (Inet6SocketAddress::IsMatchingType (from))
+ {
+ Ipv6Header ipv6;
+ p->RemoveHeader (ipv6);
+
+
+ NS_TEST_EXPECT_MSG_EQ (ipv6.GetNextHeader (),
+ Ipv6Header::IPV6_ICMPV6,
+ "The received Packet is not an ICMPV6 packet");
+
+ Icmpv6Header icmpv6;
+ p->RemoveHeader (icmpv6);
+
+ // Ignore the neighbor discovery (ICMPV6_ND) packets
+ if (!(((int)icmpv6.GetType () >= 133) && ((int)icmpv6.GetType () <= 137)))
+ {
+ NS_TEST_EXPECT_MSG_EQ ((int) icmpv6.GetType (),
+ Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED,
+ "The received Packet is not a ICMPV6_ERROR_TIME_EXCEEDED");
+ }
+ }
+}
+
+
+void
+IcmpV6TimeExceedTestCase::DoRun ()
+{
+ NodeContainer n, n0n1,n1n2;
+ n.Create (3);
+ n0n1.Add (n.Get (0));
+ n0n1.Add (n.Get (1));
+ n1n2.Add (n.Get (1));
+ n1n2.Add (n.Get (2));
+
+ Ptr channel = CreateObject ();
+ Ptr channel2 = CreateObject ();
+
+ SimpleNetDeviceHelper simpleHelper;
+ simpleHelper.SetNetDevicePointToPointMode (true);
+
+ SimpleNetDeviceHelper simpleHelper2;
+ simpleHelper2.SetNetDevicePointToPointMode (true);
+
+ NetDeviceContainer devices;
+ devices = simpleHelper.Install (n0n1,channel);
+
+ NetDeviceContainer devices2;
+ devices2 = simpleHelper2.Install (n1n2,channel2);
+
+ InternetStackHelper internet;
+ internet.Install (n);
+
+ Ipv6AddressHelper address;
+
+ address.NewNetwork ();
+ address.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
+
+ Ipv6InterfaceContainer interfaces = address.Assign (devices);
+ interfaces.SetForwarding (1,true);
+ interfaces.SetDefaultRouteInAllNodes (1);
+ address.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64));
+ Ipv6InterfaceContainer interfaces2 = address.Assign (devices2);
+
+ interfaces2.SetForwarding (0,true);
+ interfaces2.SetDefaultRouteInAllNodes (0);
+
+ Ptr socket;
+ socket = Socket::CreateSocket (n.Get (0), TypeId::LookupByName ("ns3::Ipv6RawSocketFactory"));
+ socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6));
+ socket->SetRecvCallback (MakeCallback (&IcmpV6TimeExceedTestCase::ReceivePkt, this));
+
+ Inet6SocketAddress src = Inet6SocketAddress (Ipv6Address::GetAny (), 0);
+ NS_TEST_EXPECT_MSG_EQ (socket->Bind (src),0," SocketV6 Binding failed");
+
+ // In Ipv6 TTL is renamed hop limit in IPV6.
+ // The hop limit is not big enough , causing an ICMPV6 Time Exceeded error
+ socket->SetIpv6HopLimit (1);
+
+ SendData (socket, interfaces2.GetAddress (1,1));
+
+ NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 72, " Unexpected ICMPV6_ECHO_REPLY packet size");
+
+ Simulator::Destroy ();
+}
+
+
+/**
+ * \ingroup icmp-test
+ * \ingroup tests
+ *
+ * \brief ICMP TestSuite
+ */
+
+class IcmpTestSuite : public TestSuite
+{
+public:
+ IcmpTestSuite ();
+};
+
+IcmpTestSuite::IcmpTestSuite ()
+ : TestSuite ("icmp", UNIT)
+{
+ AddTestCase (new IcmpEchoReplyTestCase, TestCase::QUICK);
+ AddTestCase (new IcmpTimeExceedTestCase, TestCase::QUICK);
+ AddTestCase (new IcmpV6EchoReplyTestCase, TestCase::QUICK);
+ AddTestCase (new IcmpV6TimeExceedTestCase, TestCase::QUICK);
+}
+
+static IcmpTestSuite icmpTestSuite; //!< Static variable for test initialization
+
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/internet/wscript ns-3.30.1/src/internet/wscript
--- ns-3.30/src/internet/wscript 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/internet/wscript 2019-09-18 10:36:11.000000000 -0700
@@ -293,6 +293,7 @@
'test/tcp-datasentcb-test.cc',
'test/ipv4-rip-test.cc',
'test/tcp-close-test.cc',
+ 'test/icmp-test.cc',
]
privateheaders = bld(features='ns3privateheader')
privateheaders.module = 'internet'
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/internet-apps/examples/wscript ns-3.30.1/src/internet-apps/examples/wscript
--- ns-3.30/src/internet-apps/examples/wscript 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/internet-apps/examples/wscript 2019-09-18 10:36:11.000000000 -0700
@@ -5,4 +5,4 @@
return;
obj = bld.create_ns3_program('dhcp-example', ['internet', 'internet-apps', 'csma', 'point-to-point', 'applications'])
- obj.source = 'dhcp-example.cc'
+ obj.source = 'dhcp-example.cc'
\ No newline at end of file
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/tap-bridge/examples/tap-wifi-virtual-machine.py ns-3.30.1/src/tap-bridge/examples/tap-wifi-virtual-machine.py
--- ns-3.30/src/tap-bridge/examples/tap-wifi-virtual-machine.py 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/tap-bridge/examples/tap-wifi-virtual-machine.py 2019-09-18 10:36:11.000000000 -0700
@@ -54,7 +54,7 @@
#
# No reason for pesky access points, so we'll use an ad-hoc network.
#
- wifiMac = ns.wifi.WifiMacHelper
+ wifiMac = ns.wifi.WifiMacHelper()
wifiMac.SetType ("ns3::AdhocWifiMac");
#
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/block-ack-manager.cc ns-3.30.1/src/wifi/model/block-ack-manager.cc
--- ns-3.30/src/wifi/model/block-ack-manager.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/wifi/model/block-ack-manager.cc 2019-09-18 10:36:11.000000000 -0700
@@ -198,6 +198,7 @@
// update the starting sequence number because some frames may have been sent
// under Normal Ack policy after the transmission of the ADDBA Request frame
agreement.SetStartingSequence (m_txMiddle->GetNextSeqNumberByTidAndAddress (tid, recipient));
+ agreement.InitTxWindow ();
if (respHdr->IsImmediateBlockAck ())
{
agreement.SetImmediateBlockAck ();
@@ -241,8 +242,7 @@
AgreementsI agreementIt = m_agreements.find (std::make_pair (recipient, tid));
NS_ASSERT (agreementIt != m_agreements.end ());
- uint16_t startingSeq = agreementIt->second.first.GetStartingSequence ();
- uint16_t mpduDist = (mpdu->GetHeader ().GetSequenceNumber () - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE;
+ uint16_t mpduDist = agreementIt->second.first.GetDistance (mpdu->GetHeader ().GetSequenceNumber ());
if (mpduDist >= SEQNO_SPACE_HALF_SIZE)
{
@@ -261,7 +261,7 @@
return;
}
- uint16_t dist = ((*it)->GetHeader ().GetSequenceNumber () - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE;
+ uint16_t dist = agreementIt->second.first.GetDistance ((*it)->GetHeader ().GetSequenceNumber ());
if (mpduDist < dist ||
(mpduDist == dist && mpdu->GetHeader ().GetFragmentNumber () < (*it)->GetHeader ().GetFragmentNumber ()))
@@ -272,6 +272,7 @@
it++;
}
agreementIt->second.second.insert (it, mpdu);
+ agreementIt->second.first.NotifyTransmittedMpdu (mpdu);
}
bool
@@ -361,12 +362,7 @@
}
}
- uint16_t startingSeq = it->second.first.GetStartingSequence ();
- if (mpdu->GetHeader ().GetSequenceNumber () == startingSeq)
- {
- // make the transmit window advance
- it->second.first.SetStartingSequence ((startingSeq + 1) % SEQNO_SPACE_SIZE);
- }
+ it->second.first.NotifyAckedMpdu (mpdu);
}
void
@@ -447,7 +443,7 @@
if (!foundFirstLost)
{
foundFirstLost = true;
- SetStartingSequence (recipient, tid, currentSeq);
+ RemoveOldPackets (recipient, tid, currentSeq);
}
nFailedMpdus++;
InsertInRetryQueue (*queueIt);
@@ -458,7 +454,7 @@
// If all frames were acknowledged, move the transmit window past the last one
if (!foundFirstLost && currentSeq != SEQNO_SPACE_SIZE)
{
- SetStartingSequence (recipient, tid, (currentSeq + 1) % SEQNO_SPACE_SIZE);
+ RemoveOldPackets (recipient, tid, (currentSeq + 1) % SEQNO_SPACE_SIZE);
}
}
else if (blockAck->IsCompressed () || blockAck->IsExtendedCompressed ())
@@ -468,6 +464,7 @@
currentSeq = (*queueIt)->GetHeader ().GetSequenceNumber ();
if (blockAck->IsPacketReceived (currentSeq))
{
+ it->second.first.NotifyAckedMpdu (*queueIt);
nSuccessfulMpdus++;
if (!m_txOkCallback.IsNull ())
{
@@ -476,11 +473,6 @@
}
else if (!QosUtilsIsOldPacket (currentStartingSeq, currentSeq))
{
- if (!foundFirstLost)
- {
- foundFirstLost = true;
- SetStartingSequence (recipient, tid, currentSeq);
- }
nFailedMpdus++;
if (!m_txFailedCallback.IsNull ())
{
@@ -491,11 +483,6 @@
// in any case, this packet is no longer outstanding
queueIt = it->second.second.erase (queueIt);
}
- // If all frames were acknowledged, move the transmit window past the last one
- if (!foundFirstLost && currentSeq != SEQNO_SPACE_SIZE)
- {
- SetStartingSequence (recipient, tid, (currentSeq + 1) % SEQNO_SPACE_SIZE);
- }
}
m_stationManager->ReportAmpduTxStatus (recipient, tid, nSuccessfulMpdus, nFailedMpdus, rxSnr, dataSnr);
}
@@ -532,7 +519,19 @@
if (ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::ESTABLISHED))
{
AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
- it->second.second.clear ();
+ while (!it->second.second.empty ())
+ {
+ Ptr mpdu = it->second.second.front ();
+ if (it->second.first.GetDistance (mpdu->GetHeader ().GetSequenceNumber ()) >= SEQNO_SPACE_HALF_SIZE)
+ {
+ // old packet
+ it->second.second.pop_front ();
+ }
+ else
+ {
+ NotifyDiscardedMpdu (mpdu);
+ }
+ }
}
}
@@ -570,8 +569,11 @@
return;
}
- // advance the transmit window past the discarded mpdu
- SetStartingSequence (recipient, tid, (mpdu->GetHeader ().GetSequenceNumber () + 1) % SEQNO_SPACE_SIZE);
+ // remove outstanding frames and frames in the retransmit queue with a sequence
+ // number less than or equal to the discarded MPDU
+ RemoveOldPackets (recipient, tid, (mpdu->GetHeader ().GetSequenceNumber () + 1) % SEQNO_SPACE_SIZE);
+ // actually advance the transmit window
+ it->second.first.NotifyDiscardedMpdu (mpdu);
// schedule a block ack request
NS_LOG_DEBUG ("Schedule a Block Ack Request for agreement (" << recipient << ", " << +tid << ")");
@@ -749,7 +751,6 @@
AgreementsI agreementIt = m_agreements.find (std::make_pair (address, tid));
NS_ASSERT (agreementIt != m_agreements.end ());
- uint16_t startingSeq = agreementIt->second.first.GetStartingSequence ();
/* remove retry packet iterators if they are present in retry queue */
WifiMacQueue::ConstIterator it = m_retryPackets->PeekByTidAndAddress (tid, address);
@@ -758,10 +759,8 @@
{
uint16_t itSeq = (*it)->GetHeader ().GetSequenceNumber ();
- if ((itSeq - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE
- >= (startSeq - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE
- && (itSeq - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE
- <= (endSeq - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE)
+ if (agreementIt->second.first.GetDistance (itSeq) >= agreementIt->second.first.GetDistance (startSeq)
+ && agreementIt->second.first.GetDistance (itSeq) <= agreementIt->second.first.GetDistance (endSeq))
{
NS_LOG_DEBUG ("Removing frame with seqnum = " << itSeq);
it = m_retryPackets->Remove (it);
@@ -775,7 +774,7 @@
}
void
-BlockAckManager::SetStartingSequence (Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
+BlockAckManager::RemoveOldPackets (Mac48Address recipient, uint8_t tid, uint16_t startingSeq)
{
NS_LOG_FUNCTION (this << recipient << +tid << startingSeq);
@@ -783,7 +782,7 @@
NS_ASSERT (agreementIt != m_agreements.end ());
uint16_t currStartingSeq = agreementIt->second.first.GetStartingSequence ();
- NS_ABORT_MSG_IF ((startingSeq - currStartingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE >= SEQNO_SPACE_HALF_SIZE,
+ NS_ABORT_MSG_IF (agreementIt->second.first.GetDistance (startingSeq) >= SEQNO_SPACE_HALF_SIZE,
"The new starting sequence number is an old sequence number");
if (startingSeq == currStartingSeq)
@@ -801,8 +800,7 @@
{
uint16_t itSeq = (*it)->GetHeader ().GetSequenceNumber ();
- if ((itSeq - currStartingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE
- <= (lastRemovedSeq - currStartingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE)
+ if (agreementIt->second.first.GetDistance (itSeq) <= agreementIt->second.first.GetDistance (lastRemovedSeq))
{
NS_LOG_DEBUG ("Removing frame with seqnum = " << itSeq);
it = agreementIt->second.second.erase (it);
@@ -812,9 +810,6 @@
it++;
}
}
-
- // update the starting sequence number
- agreementIt->second.first.SetStartingSequence (startingSeq);
}
void
@@ -869,8 +864,7 @@
AgreementsI agreementIt = m_agreements.find (std::make_pair (recipient, tid));
NS_ASSERT (agreementIt != m_agreements.end ());
- uint16_t startingSeq = agreementIt->second.first.GetStartingSequence ();
- uint16_t mpduDist = (mpdu->GetHeader ().GetSequenceNumber () - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE;
+ uint16_t mpduDist = agreementIt->second.first.GetDistance (mpdu->GetHeader ().GetSequenceNumber ());
if (mpduDist >= SEQNO_SPACE_HALF_SIZE)
{
@@ -888,7 +882,7 @@
return;
}
- uint16_t dist = ((*it)->GetHeader ().GetSequenceNumber () - startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE;
+ uint16_t dist = agreementIt->second.first.GetDistance ((*it)->GetHeader ().GetSequenceNumber ());
if (mpduDist < dist ||
(mpduDist == dist && mpdu->GetHeader ().GetFragmentNumber () < (*it)->GetHeader ().GetFragmentNumber ()))
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/block-ack-manager.h ns-3.30.1/src/wifi/model/block-ack-manager.h
--- ns-3.30/src/wifi/model/block-ack-manager.h 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/wifi/model/block-ack-manager.h 2019-09-18 10:36:11.000000000 -0700
@@ -430,16 +430,16 @@
void InactivityTimeout (Mac48Address recipient, uint8_t tid);
/**
- * Set the starting sequence number for the agreement with recipient equal to
- * recipient and TID equal to tid to the given startingSeq.
- * Also, remove packets that became old from the retransmit queue and from the
- * queue of outstanding packets.
+ * Remove packets from the retransmit queue and from the queue of outstanding
+ * packets that become old after setting the starting sequence number for the
+ * agreement with recipient equal to recipient and TID equal to tid
+ * to the given startingSeq.
*
* \param recipient the recipient MAC address
* \param tid Traffic ID
* \param startingSeq the new starting sequence number
*/
- void SetStartingSequence (Mac48Address recipient, uint8_t tid, uint16_t startingSeq);
+ void RemoveOldPackets (Mac48Address recipient, uint8_t tid, uint16_t startingSeq);
/**
* typedef for a list of WifiMacQueueItem.
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/block-ack-window.cc ns-3.30.1/src/wifi/model/block-ack-window.cc
--- ns-3.30/src/wifi/model/block-ack-window.cc 1969-12-31 16:00:00.000000000 -0800
+++ ns-3.30.1/src/wifi/model/block-ack-window.cc 2019-09-18 10:36:11.000000000 -0700
@@ -0,0 +1,95 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2019 Universita' degli Studi di Napoli Federico II
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Stefano Avallone
+ */
+
+#include "ns3/log.h"
+#include "block-ack-window.h"
+#include "wifi-utils.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("BlockAckWindow");
+
+BlockAckWindow::BlockAckWindow ()
+ : m_winStart (0),
+ m_head (0)
+{
+}
+
+void
+BlockAckWindow::Init (uint16_t winStart, uint16_t winSize)
+{
+ NS_LOG_FUNCTION (this << winStart << winSize);
+ m_winStart = winStart;
+ m_window.assign (winSize, false);
+ m_head = 0;
+}
+
+void
+BlockAckWindow::Reset (uint16_t winStart)
+{
+ Init (winStart, m_window.size ());
+}
+
+uint16_t
+BlockAckWindow::GetWinStart (void) const
+{
+ return m_winStart;
+}
+
+uint16_t
+BlockAckWindow::GetWinEnd (void) const
+{
+ return (m_winStart + m_window.size () - 1) % SEQNO_SPACE_SIZE;
+}
+
+std::size_t
+BlockAckWindow::GetWinSize (void) const
+{
+ return m_window.size ();
+}
+
+std::vector::reference
+BlockAckWindow::At (std::size_t distance)
+{
+ NS_ASSERT (distance < m_window.size ());
+
+ return m_window.at ((m_head + distance) % m_window.size ());
+}
+
+void
+BlockAckWindow::Advance (std::size_t count)
+{
+ NS_LOG_FUNCTION (this << count);
+
+ if (count >= m_window.size ())
+ {
+ Reset ((m_winStart + count) % SEQNO_SPACE_SIZE);
+ return;
+ }
+
+ for (std::size_t i = 0; i < count; i++)
+ {
+ m_window[m_head] = false;
+ m_head = (m_head + 1) % m_window.size ();
+ }
+ m_winStart = (m_winStart + count) % SEQNO_SPACE_SIZE;
+}
+
+} //namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/block-ack-window.h ns-3.30.1/src/wifi/model/block-ack-window.h
--- ns-3.30/src/wifi/model/block-ack-window.h 1969-12-31 16:00:00.000000000 -0800
+++ ns-3.30.1/src/wifi/model/block-ack-window.h 2019-09-18 10:36:11.000000000 -0700
@@ -0,0 +1,120 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2019 Universita' degli Studi di Napoli Federico II
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Stefano Avallone
+ */
+
+#ifndef BLOCK_ACK_WINDOW_H
+#define BLOCK_ACK_WINDOW_H
+
+#include
+
+namespace ns3 {
+
+/**
+ * \ingroup wifi
+ * \brief Block Ack window
+ *
+ * This class provides the basic functionalities of a window sliding over a
+ * bitmap: accessing any element in the bitmap and moving the window forward
+ * a given number of positions. This class can be used to implement both
+ * an originator's window and a recipient's window.
+ *
+ * The window is implemented as a vector of bool and managed as a circular
+ * queue. The window is moved forward by advancing the head of the queue and
+ * clearing the elements that become part of the tail of the queue. Hence,
+ * no element is required to be shifted when the window moves forward.
+ *
+ * Example:
+ *
+ * |0|1|1|0|1|1|1|0|1|1|1|1|1|1|1|0|
+ * ^
+ * |
+ * HEAD
+ *
+ * After moving the window forward three positions:
+ *
+ * |0|1|1|0|1|1|1|0|1|1|0|0|0|1|1|0|
+ * ^
+ * |
+ * HEAD
+ */
+class BlockAckWindow
+{
+public:
+ /**
+ * Constructor
+ */
+ BlockAckWindow ();
+ /**
+ * Initialize the window with the given starting sequence number and size
+ *
+ * \param winStart the window start
+ * \param winSize the window size
+ */
+ void Init (uint16_t winStart, uint16_t winSize);
+ /**
+ * Reset the window by clearing all the elements and setting winstart to the
+ * given value.
+ *
+ * \param winStart the window start
+ */
+ void Reset (uint16_t winStart);
+ /**
+ * Get the current winstart value.
+ *
+ * \return the current winstart value
+ */
+ uint16_t GetWinStart (void) const;
+ /**
+ * Get the current winend value.
+ *
+ * \return the current winend value
+ */
+ uint16_t GetWinEnd (void) const;
+ /**
+ * Get the window size.
+ *
+ * \return the window size
+ */
+ std::size_t GetWinSize (void) const;
+ /**
+ * Get a reference to the element in the window having the given distance from
+ * the current winstart. Note that the given distance must be less than the
+ * window size.
+ *
+ * \param distance the given distance
+ * \return a reference to the element in the window having the given distance
+ * from the current winstart
+ */
+ std::vector::reference At (std::size_t distance);
+ /**
+ * Advance the current winstart by the given number of positions.
+ *
+ * \param count the number of positions the current winstart must be advanced by
+ */
+ void Advance (std::size_t count);
+
+private:
+ uint16_t m_winStart; ///< window start (sequence number)
+ std::vector m_window; ///< window
+ std::size_t m_head; ///< index of winstart in the vector
+};
+
+} //namespace ns3
+
+#endif /* BLOCK_ACK_WINDOW_H */
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/originator-block-ack-agreement.cc ns-3.30.1/src/wifi/model/originator-block-ack-agreement.cc
--- ns-3.30/src/wifi/model/originator-block-ack-agreement.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/wifi/model/originator-block-ack-agreement.cc 2019-09-18 10:36:11.000000000 -0700
@@ -19,10 +19,15 @@
* Tommaso Pecorella
*/
+#include "ns3/log.h"
#include "originator-block-ack-agreement.h"
+#include "wifi-mac-queue-item.h"
+#include "wifi-utils.h"
namespace ns3 {
+NS_LOG_COMPONENT_DEFINE ("OriginatorBlockAckAgreement");
+
OriginatorBlockAckAgreement::OriginatorBlockAckAgreement (Mac48Address recipient, uint8_t tid)
: BlockAckAgreement (recipient, tid),
m_state (PENDING)
@@ -69,4 +74,104 @@
return (m_state == RESET) ? true : false;
}
+uint16_t
+OriginatorBlockAckAgreement::GetStartingSequence (void) const
+{
+ if (m_txWindow.GetWinSize () == 0)
+ {
+ // the TX window has not been initialized yet
+ return m_startingSeq;
+ }
+ return m_txWindow.GetWinStart ();
+}
+
+std::size_t
+OriginatorBlockAckAgreement::GetDistance (uint16_t seqNumber) const
+{
+ NS_ASSERT (seqNumber < SEQNO_SPACE_SIZE);
+ return (seqNumber - GetStartingSequence () + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE;
+}
+
+void
+OriginatorBlockAckAgreement::InitTxWindow (void)
+{
+ m_txWindow.Init (m_startingSeq, m_bufferSize);
+}
+
+void
+OriginatorBlockAckAgreement::AdvanceTxWindow (void)
+{
+ while (m_txWindow.At (0))
+ {
+ m_txWindow.Advance (1); // reset the current head -- ensures loop termination
+ }
+}
+
+void
+OriginatorBlockAckAgreement::NotifyTransmittedMpdu (Ptr mpdu)
+{
+ uint16_t mpduSeqNumber = mpdu->GetHeader ().GetSequenceNumber ();
+ uint16_t distance = GetDistance (mpduSeqNumber);
+
+ if (distance >= SEQNO_SPACE_HALF_SIZE)
+ {
+ NS_LOG_DEBUG ("Transmitted an old MPDU, do nothing.");
+ return;
+ }
+
+ // advance the transmit window if an MPDU beyond the current transmit window
+ // is transmitted (see Section 10.24.7.7 of 802.11-2016)
+ if (distance >= m_txWindow.GetWinSize ())
+ {
+ std::size_t count = distance - m_txWindow.GetWinSize () + 1;
+ m_txWindow.Advance (count);
+ // transmit window may advance further
+ AdvanceTxWindow ();
+ NS_LOG_DEBUG ("Transmitted MPDU beyond current transmit window. New starting sequence number: "
+ << m_txWindow.GetWinStart ());
+ }
+}
+
+void
+OriginatorBlockAckAgreement::NotifyAckedMpdu (Ptr mpdu)
+{
+ uint16_t mpduSeqNumber = mpdu->GetHeader ().GetSequenceNumber ();
+ uint16_t distance = GetDistance (mpduSeqNumber);
+
+ if (distance >= SEQNO_SPACE_HALF_SIZE)
+ {
+ NS_LOG_DEBUG ("Acked an old MPDU, do nothing.");
+ return;
+ }
+
+ // when an MPDU is transmitted, the transmit window is updated such that the
+ // transmitted MPDU is in the window, hence we cannot be notified of the
+ // acknowledgment of an MPDU which is beyond the transmit window
+ m_txWindow.At (distance) = true;
+
+ // the starting sequence number can be advanced to the sequence number of
+ // the nearest unacknowledged MPDU
+ AdvanceTxWindow ();
+ NS_LOG_DEBUG ("Starting sequence number: " << m_txWindow.GetWinStart ());
+}
+
+void
+OriginatorBlockAckAgreement::NotifyDiscardedMpdu (Ptr mpdu)
+{
+ uint16_t mpduSeqNumber = mpdu->GetHeader ().GetSequenceNumber ();
+ uint16_t distance = GetDistance (mpduSeqNumber);
+
+ if (distance >= SEQNO_SPACE_HALF_SIZE)
+ {
+ NS_LOG_DEBUG ("Discarded an old MPDU, do nothing.");
+ return;
+ }
+
+ m_txWindow.Advance (distance + 1);
+ // transmit window may advance further
+ AdvanceTxWindow ();
+ NS_LOG_DEBUG ("Discarded MPDU within current transmit window. New starting sequence number: "
+ << m_txWindow.GetWinStart ());
+}
+
} //namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/originator-block-ack-agreement.h ns-3.30.1/src/wifi/model/originator-block-ack-agreement.h
--- ns-3.30/src/wifi/model/originator-block-ack-agreement.h 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/wifi/model/originator-block-ack-agreement.h 2019-09-18 10:36:11.000000000 -0700
@@ -22,9 +22,14 @@
#define ORIGINATOR_BLOCK_ACK_AGREEMENT_H
#include "block-ack-agreement.h"
+#include "block-ack-window.h"
+
+class OriginatorBlockAckWindowTest;
namespace ns3 {
+class WifiMacQueueItem;
+
/**
* \ingroup wifi
* Maintains the state and information about transmitted MPDUs with ack policy block ack
@@ -54,6 +59,7 @@
{
/// allow BlockAckManager class access
friend class BlockAckManager;
+ friend class ::OriginatorBlockAckWindowTest;
public:
@@ -141,8 +147,64 @@
*/
bool IsRejected (void) const;
+ /**
+ * Return the starting sequence number of the transmit window, if a transmit
+ * window has been initialized. Otherwise, return the starting sequence number
+ * stored by the BlockAckAgreement base class.
+ *
+ * \return the starting sequence number.
+ */
+ uint16_t GetStartingSequence (void) const;
+
+ /**
+ * Get the distance between the current starting sequence number and the
+ * given sequence number.
+ *
+ * \param seqNumber the given sequence number
+ * \return the distance of the given sequence number from the current winstart
+ */
+ std::size_t GetDistance (uint16_t seqNumber) const;
+
+ /**
+ * Initialize the originator's transmit window by setting its size and starting
+ * sequence number equal to the values stored by the BlockAckAgreement base class.
+ */
+ void InitTxWindow (void);
+
+ /**
+ * Advance the transmit window so as to include the transmitted MPDU, if the
+ * latter is not an old packet and is beyond the current transmit window.
+ *
+ * \param mpdu the transmitted MPDU
+ */
+ void NotifyTransmittedMpdu (Ptr mpdu);
+ /**
+ * Record that the given MPDU has been acknowledged and advance the transmit
+ * window if possible.
+ *
+ * \param mpdu the acknowledged MPDU
+ */
+ void NotifyAckedMpdu (Ptr mpdu);
+ /**
+ * Advance the transmit window beyond the MPDU that has been reported to
+ * be discarded.
+ *
+ * \param mpdu the discarded MPDU
+ */
+ void NotifyDiscardedMpdu (Ptr mpdu);
+
+
private:
- State m_state; ///< state
+ /**
+ * Advance the transmit window so that the starting sequence number is the
+ * nearest unacknowledged MPDU.
+ *
+ * \param newStartingSeq the new starting sequence number
+ */
+ void AdvanceTxWindow (void);
+
+ State m_state; ///< state
+ BlockAckWindow m_txWindow; ///< originator's transmit window
};
} //namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/qos-txop.cc ns-3.30.1/src/wifi/model/qos-txop.cc
--- ns-3.30/src/wifi/model/qos-txop.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/wifi/model/qos-txop.cc 2019-09-18 10:36:11.000000000 -0700
@@ -941,7 +941,10 @@
{
NS_LOG_FUNCTION (this);
if ((m_currentPacket != 0
- || !m_queue->IsEmpty () || m_baManager->HasPackets ())
+ // check first if the BA manager retransmit queue is empty, so that expired
+ // frames (if any) are removed and a Block Ack Request is scheduled to advance
+ // the starting sequence number of the transmit (and receiver) window
+ || m_baManager->HasPackets () || !m_queue->IsEmpty ())
&& !IsAccessRequested ())
{
Ptr packet;
@@ -978,7 +981,10 @@
{
NS_LOG_FUNCTION (this);
if (m_currentPacket == 0
- && (!m_queue->IsEmpty () || m_baManager->HasPackets ())
+ // check first if the BA manager retransmit queue is empty, so that expired
+ // frames (if any) are removed and a Block Ack Request is scheduled to advance
+ // the starting sequence number of the transmit (and receiver) window
+ && (m_baManager->HasPackets () || !m_queue->IsEmpty ())
&& !IsAccessRequested ())
{
Ptr packet;
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/model/vht-capabilities.cc ns-3.30.1/src/wifi/model/vht-capabilities.cc
--- ns-3.30/src/wifi/model/vht-capabilities.cc 2019-08-12 16:30:34.000000000 -0700
+++ ns-3.30.1/src/wifi/model/vht-capabilities.cc 2019-09-18 10:36:11.000000000 -0700
@@ -210,7 +210,7 @@
void
VhtCapabilities::SetMaxMpduLength (uint16_t length)
{
- NS_ABORT_MSG_IF (length != 3895 && length != 7991 && length == 11454,
+ NS_ABORT_MSG_IF (length != 3895 && length != 7991 && length != 11454,
"Invalid MPDU Max Length value");
if (length == 11454)
{
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/test/block-ack-test-suite.cc ns-3.30.1/src/wifi/test/block-ack-test-suite.cc
--- ns-3.30/src/wifi/test/block-ack-test-suite.cc 2019-08-12 16:30:35.000000000 -0700
+++ ns-3.30.1/src/wifi/test/block-ack-test-suite.cc 2019-09-18 10:36:11.000000000 -0700
@@ -251,6 +251,298 @@
}
}
+/**
+ * \ingroup wifi-test
+ * \ingroup tests
+ *
+ * \brief Test for the originator block ack window
+ */
+class OriginatorBlockAckWindowTest : public TestCase
+{
+public:
+ OriginatorBlockAckWindowTest ();
+private:
+ virtual void DoRun ();
+};
+
+OriginatorBlockAckWindowTest::OriginatorBlockAckWindowTest ()
+ : TestCase ("Check the correctness of the originator block ack window")
+{
+}
+
+void
+OriginatorBlockAckWindowTest::DoRun (void)
+{
+ uint16_t winSize = 16;
+ uint16_t startingSeq = 4090;
+
+ OriginatorBlockAckAgreement agreement (Mac48Address ("00:00:00:00:00:01"), 0);
+ agreement.SetBufferSize (winSize);
+ agreement.SetStartingSequence (startingSeq);
+ agreement.InitTxWindow ();
+
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.GetWinSize (), winSize, "Incorrect window size");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.GetWinStart (), startingSeq, "Incorrect winStart");
+ // check that all the elements in the window are cleared
+ for (uint16_t i = 0; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after initialization");
+ }
+
+ // Notify the acknowledgment of 5 packets
+ Ptr mpdu = Create (Create (), WifiMacHeader ());
+ uint16_t seqNumber = startingSeq;
+ mpdu->GetHeader ().SetSequenceNumber (seqNumber);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+ // ^
+ // |
+ // HEAD
+
+ startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 5 acknowledgments");
+ for (uint16_t i = 0; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after 5 acknowledgments");
+ }
+
+ // the next MPDU is not acknowledged, hence the window is blocked while the
+ // subsequent 4 MPDUs are acknowledged
+ ++seqNumber %= SEQNO_SPACE_SIZE;
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |0|0|0|0|0|0|1|1|1|1|0|0|0|0|0|0|
+ // ^
+ // |
+ // HEAD
+
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 1 unacknowledged MPDU");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after 1 unacknowledged MPDU");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), true, "Incorrect flag after 1 unacknowledged MPDU");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after 1 unacknowledged MPDU");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after 1 unacknowledged MPDU");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after 1 unacknowledged MPDU");
+ for (uint16_t i = 5; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after 1 unacknowledged MPDU");
+ }
+
+ // the missing MPDU is now acknowledged; the window moves forward and the starting
+ // sequence number is the one of the first unacknowledged MPDU
+ mpdu->GetHeader ().SetSequenceNumber (startingSeq);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+ // ^
+ // |
+ // HEAD
+
+ startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after acknowledgment of missing MPDU");
+ for (uint16_t i = 0; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after acknowledgment of missing MPDU");
+ }
+
+ // Now, create a hole of 3 MPDUs before 4 acknowledged MPDUs, another hole of 2 MPDUs before 3 acknowledged MPDUs
+ seqNumber = (seqNumber + 4) % SEQNO_SPACE_SIZE;
+ mpdu->GetHeader ().SetSequenceNumber (seqNumber);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ seqNumber = (seqNumber + 3) % SEQNO_SPACE_SIZE;
+ mpdu->GetHeader ().SetSequenceNumber (seqNumber);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
+ // ^
+ // |
+ // HEAD
+
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), false, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), false, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (5), true, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (6), true, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (7), false, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (8), false, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (9), true, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (10), true, "Incorrect flag after 3 unacknowledged MPDUs");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (11), true, "Incorrect flag after 3 unacknowledged MPDUs");
+ for (uint16_t i = 12; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after 3 unacknowledged MPDUs");
+ }
+
+ // the transmission of an MPDU beyond the current window (by 2 positions) is
+ // notified, hence the window moves forward 2 positions
+ seqNumber = (agreement.m_txWindow.GetWinEnd () + 2) % SEQNO_SPACE_SIZE;
+ mpdu->GetHeader ().SetSequenceNumber (seqNumber);
+ agreement.NotifyTransmittedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
+ // ^
+ // |
+ // HEAD
+
+ startingSeq = (startingSeq + 2) % SEQNO_SPACE_SIZE;
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
+ "Incorrect starting sequence after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), true, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (5), false, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (6), false, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (7), true, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (8), true, "Incorrect flag after transmitting an MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (9), true, "Incorrect flag after transmitting an MPDU beyond the current window");
+ for (uint16_t i = 10; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after transmitting an MPDU beyond the current window");
+ }
+
+ // another MPDU is transmitted beyond the current window. Now, the window advances
+ // until the first unacknowledged MPDU
+ seqNumber = (agreement.m_txWindow.GetWinEnd () + 1) % SEQNO_SPACE_SIZE;
+ mpdu->GetHeader ().SetSequenceNumber (seqNumber);
+ agreement.NotifyTransmittedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |0|0|0|1|1|1|0|0|0|0|0|0|0|0|0|0|
+ // ^
+ // |
+ // HEAD
+
+ startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
+ "Incorrect starting sequence after transmitting another MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after transmitting another MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), false, "Incorrect flag after transmitting another MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after transmitting another MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after transmitting another MPDU beyond the current window");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after transmitting another MPDU beyond the current window");
+ for (uint16_t i = 5; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after transmitting another MPDU beyond the current window");
+ }
+
+ // the MPDU next to winStart is discarded, hence the window advances to make it an old packet.
+ // Since the subsequent MPDUs have been acknowledged, the window advances further.
+ seqNumber = (startingSeq + 1) % SEQNO_SPACE_SIZE;
+ mpdu->GetHeader ().SetSequenceNumber (seqNumber);
+ agreement.NotifyDiscardedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+ // ^
+ // |
+ // HEAD
+
+ startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
+ "Incorrect starting sequence after discarding an MPDU");
+ for (uint16_t i = 0; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after discarding an MPDU");
+ }
+
+ // Finally, check that the window correctly advances when the MPDU with the starting sequence number
+ // is acknowledged after being the only unacknowledged MPDU
+ for (uint16_t i = 1; i < winSize; i++)
+ {
+ mpdu->GetHeader ().SetSequenceNumber ((startingSeq + i) % SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+ }
+
+ // the current window must look like this:
+ //
+ // |1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|
+ // ^
+ // |
+ // HEAD
+
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
+ "Incorrect starting sequence after acknowledging all but the first MPDU");
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after acknowledging all but the first MPDU");
+ for (uint16_t i = 1; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), true, "Incorrect flag after acknowledging all but the first MPDU");
+ }
+
+ // acknowledge the first MPDU
+ mpdu->GetHeader ().SetSequenceNumber (startingSeq % SEQNO_SPACE_SIZE);
+ agreement.NotifyAckedMpdu (mpdu);
+
+ // the current window must look like this:
+ //
+ // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+ // ^
+ // |
+ // HEAD
+
+ startingSeq = (startingSeq + winSize) % SEQNO_SPACE_SIZE;
+ NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
+ "Incorrect starting sequence after acknowledging the first MPDU");
+ for (uint16_t i = 0; i < winSize; i++)
+ {
+ NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after acknowledging the first MPDU");
+ }
+}
+
/**
* \ingroup wifi-test
@@ -554,6 +846,7 @@
{
AddTestCase (new PacketBufferingCaseA, TestCase::QUICK);
AddTestCase (new PacketBufferingCaseB, TestCase::QUICK);
+ AddTestCase (new OriginatorBlockAckWindowTest, TestCase::QUICK);
AddTestCase (new CtrlBAckResponseHeaderTest, TestCase::QUICK);
AddTestCase (new BlockAckAggregationDisabledTest, TestCase::QUICK);
}
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/src/wifi/wscript ns-3.30.1/src/wifi/wscript
--- ns-3.30/src/wifi/wscript 2019-08-12 16:30:35.000000000 -0700
+++ ns-3.30.1/src/wifi/wscript 2019-09-18 10:36:11.000000000 -0700
@@ -66,6 +66,7 @@
'model/block-ack-agreement.cc',
'model/block-ack-manager.cc',
'model/block-ack-cache.cc',
+ 'model/block-ack-window.cc',
'model/snr-tag.cc',
'model/ht-capabilities.cc',
'model/wifi-tx-vector.cc',
@@ -189,6 +190,7 @@
'model/block-ack-agreement.h',
'model/block-ack-manager.h',
'model/block-ack-cache.h',
+ 'model/block-ack-window.h',
'model/snr-tag.h',
'model/ht-capabilities.h',
'model/parf-wifi-manager.h',
diff -Naur -x '*.dia' -x '*.pcap' ns-3.30/VERSION ns-3.30.1/VERSION
--- ns-3.30/VERSION 2019-08-20 23:05:26.000000000 -0700
+++ ns-3.30.1/VERSION 2019-09-18 11:47:30.203118783 -0700
@@ -1 +1 @@
-3.30
+3.30.1