internet: (fixes #579) remove TcpWestwood model

This commit is contained in:
Tommaso Pecorella
2022-11-13 11:21:42 +01:00
committed by Tommaso Pecorella
parent 33b9f5fe7a
commit 0077121649
11 changed files with 72 additions and 148 deletions

View File

@@ -23,6 +23,7 @@ Changes from ns-3.37 to ns-3.38
### Changes to existing API
* (network) **Ipv4Address** and **Ipv6Address** now do not raise an exception if built from an invalid string. Instead the address is marked as not initialized.
* (internet) TCP Westwood model has been removed due to a bug in BW estimation documented in https://gitlab.com/nsnam/ns-3-dev/-/issues/579. The TCP Westwood+ model is now named **TcpWestwoodPlus** and can be instantiated like all the other TCP flavors.
### Changes to build system

View File

@@ -20,6 +20,7 @@ Release 3-dev
- (network) !938 - Add class `TimestampTag` for associating a timestamp with a packet.
- (network) !1163 Initializing an Ipv[4,6]Address from an invalid string do not raise an exception anymore. Instead the address is marked as not initialized.
- (internet) !1186 `TcpWestwood` model has been removed, and the class has been renamed `TcpWestwoodPlus`.
### Bugs fixed

View File

@@ -152,21 +152,11 @@ main(int argc, char* argv[])
// Set recovery algorithm and TCP variant
Config::SetDefault("ns3::TcpL4Protocol::RecoveryType",
TypeIdValue(TypeId::LookupByName(recovery)));
if (tcpTypeId == "ns3::TcpWestwoodPlus")
{
// TcpWestwoodPlus is not an actual TypeId name; we need TcpWestwood here
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue(TcpWestwood::GetTypeId()));
// the default protocol type in ns3::TcpWestwood is WESTWOOD
Config::SetDefault("ns3::TcpWestwood::ProtocolType", EnumValue(TcpWestwood::WESTWOODPLUS));
}
else
{
TypeId tcpTid;
NS_ABORT_MSG_UNLESS(TypeId::LookupByNameFailSafe(tcpTypeId, &tcpTid),
"TypeId " << tcpTypeId << " not found");
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TypeId::LookupByName(tcpTypeId)));
}
TypeId tcpTid;
NS_ABORT_MSG_UNLESS(TypeId::LookupByNameFailSafe(tcpTypeId, &tcpTid),
"TypeId " << tcpTypeId << " not found");
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TypeId::LookupByName(tcpTypeId)));
// Create nodes
NodeContainer leftNodes;

View File

@@ -342,7 +342,7 @@ TraceNextRx(std::string& next_rx_seq_file_name, uint32_t nodeId)
int
main(int argc, char* argv[])
{
std::string transport_prot = "TcpWestwood";
std::string transport_prot = "TcpWestwoodPlus";
double error_p = 0.0;
std::string bandwidth = "2Mbps";
std::string delay = "0.01ms";
@@ -365,7 +365,7 @@ main(int argc, char* argv[])
cmd.AddValue("transport_prot",
"Transport protocol to use: TcpNewReno, TcpLinuxReno, "
"TcpHybla, TcpHighSpeed, TcpHtcp, TcpVegas, TcpScalable, TcpVeno, "
"TcpBic, TcpYeah, TcpIllinois, TcpWestwood, TcpWestwoodPlus, TcpLedbat, "
"TcpBic, TcpYeah, TcpIllinois, TcpWestwoodPlus, TcpLedbat, "
"TcpLp, TcpDctcp, TcpCubic, TcpBbr",
transport_prot);
cmd.AddValue("error_p", "Packet error rate", error_p);
@@ -423,21 +423,11 @@ main(int argc, char* argv[])
Config::SetDefault("ns3::TcpL4Protocol::RecoveryType",
TypeIdValue(TypeId::LookupByName(recovery)));
// Select TCP variant
if (transport_prot == "ns3::TcpWestwoodPlus")
{
// TcpWestwoodPlus is not an actual TypeId name; we need TcpWestwood here
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue(TcpWestwood::GetTypeId()));
// the default protocol type in ns3::TcpWestwood is WESTWOOD
Config::SetDefault("ns3::TcpWestwood::ProtocolType", EnumValue(TcpWestwood::WESTWOODPLUS));
}
else
{
TypeId tcpTid;
NS_ABORT_MSG_UNLESS(TypeId::LookupByNameFailSafe(transport_prot, &tcpTid),
"TypeId " << transport_prot << " not found");
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TypeId::LookupByName(transport_prot)));
}
TypeId tcpTid;
NS_ABORT_MSG_UNLESS(TypeId::LookupByNameFailSafe(transport_prot, &tcpTid),
"TypeId " << transport_prot << " not found");
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TypeId::LookupByName(transport_prot)));
// Create gateways, sources, and sinks
NodeContainer gateways;

View File

@@ -44,7 +44,7 @@
#include "ns3/packet-sink.h"
#include "ns3/ssid.h"
#include "ns3/string.h"
#include "ns3/tcp-westwood.h"
#include "ns3/tcp-westwood-plus.h"
#include "ns3/yans-wifi-channel.h"
#include "ns3/yans-wifi-helper.h"
@@ -95,21 +95,11 @@ main(int argc, char* argv[])
tcpVariant = std::string("ns3::") + tcpVariant;
// Select TCP variant
if (tcpVariant == "ns3::TcpWestwoodPlus")
{
// TcpWestwoodPlus is not an actual TypeId name; we need TcpWestwood here
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue(TcpWestwood::GetTypeId()));
// the default protocol type in ns3::TcpWestwood is WESTWOOD
Config::SetDefault("ns3::TcpWestwood::ProtocolType", EnumValue(TcpWestwood::WESTWOODPLUS));
}
else
{
TypeId tcpTid;
NS_ABORT_MSG_UNLESS(TypeId::LookupByNameFailSafe(tcpVariant, &tcpTid),
"TypeId " << tcpVariant << " not found");
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TypeId::LookupByName(tcpVariant)));
}
TypeId tcpTid;
NS_ABORT_MSG_UNLESS(TypeId::LookupByNameFailSafe(tcpVariant, &tcpTid),
"TypeId " << tcpVariant << " not found");
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
TypeIdValue(TypeId::LookupByName(tcpVariant)));
/* Configure TCP Options */
Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(payloadSize));

View File

@@ -118,7 +118,7 @@ set(source_files
model/tcp-tx-item.cc
model/tcp-vegas.cc
model/tcp-veno.cc
model/tcp-westwood.cc
model/tcp-westwood-plus.cc
model/tcp-yeah.cc
model/udp-header.cc
model/udp-l4-protocol.cc
@@ -243,7 +243,7 @@ set(header_files
model/tcp-tx-item.h
model/tcp-vegas.h
model/tcp-veno.h
model/tcp-westwood.h
model/tcp-westwood-plus.h
model/tcp-yeah.h
model/udp-header.h
model/udp-l4-protocol.h

View File

@@ -554,6 +554,12 @@ bandwidth and use the estimated value to adjust the cwnd.
While Westwood performs the bandwidth sampling every ACK reception,
Westwood+ samples the bandwidth every RTT.
The TCP Westwood model has been removed in ns-3.38 due to bugs that are impossible
to fix without modifying the original Westwood model as presented in the published papers.
For further info refer to https://gitlab.com/nsnam/ns-3-dev/-/issues/579
The Westwood+ model does not have such issues, and is still available.
WARNING: this TCP model lacks validation and regression tests; use with caution.
More information at: http://dl.acm.org/citation.cfm?id=381704 and

View File

@@ -30,7 +30,7 @@
* US Department of Defense (DoD), and ITTC at The University of Kansas.
*/
#include "tcp-westwood.h"
#include "tcp-westwood-plus.h"
#include "rtt-estimator.h"
#include "tcp-socket-base.h"
@@ -38,42 +38,35 @@
#include "ns3/log.h"
#include "ns3/simulator.h"
NS_LOG_COMPONENT_DEFINE("TcpWestwood");
NS_LOG_COMPONENT_DEFINE("TcpWestwoodPlus");
namespace ns3
{
NS_OBJECT_ENSURE_REGISTERED(TcpWestwood);
NS_OBJECT_ENSURE_REGISTERED(TcpWestwoodPlus);
TypeId
TcpWestwood::GetTypeId()
TcpWestwoodPlus::GetTypeId()
{
static TypeId tid =
TypeId("ns3::TcpWestwood")
TypeId("ns3::TcpWestwoodPlus")
.SetParent<TcpNewReno>()
.SetGroupName("Internet")
.AddConstructor<TcpWestwood>()
.AddAttribute("FilterType",
"Use this to choose no filter or Tustin's approximation filter",
EnumValue(TcpWestwood::TUSTIN),
MakeEnumAccessor(&TcpWestwood::m_fType),
MakeEnumChecker(TcpWestwood::NONE, "None", TcpWestwood::TUSTIN, "Tustin"))
.AddAttribute("ProtocolType",
"Use this to let the code run as Westwood or WestwoodPlus",
EnumValue(TcpWestwood::WESTWOOD),
MakeEnumAccessor(&TcpWestwood::m_pType),
MakeEnumChecker(TcpWestwood::WESTWOOD,
"Westwood",
TcpWestwood::WESTWOODPLUS,
"WestwoodPlus"))
.AddConstructor<TcpWestwoodPlus>()
.AddAttribute(
"FilterType",
"Use this to choose no filter or Tustin's approximation filter",
EnumValue(TcpWestwoodPlus::TUSTIN),
MakeEnumAccessor(&TcpWestwoodPlus::m_fType),
MakeEnumChecker(TcpWestwoodPlus::NONE, "None", TcpWestwoodPlus::TUSTIN, "Tustin"))
.AddTraceSource("EstimatedBW",
"The estimated bandwidth",
MakeTraceSourceAccessor(&TcpWestwood::m_currentBW),
MakeTraceSourceAccessor(&TcpWestwoodPlus::m_currentBW),
"ns3::TracedValueCallback::DataRate");
return tid;
}
TcpWestwood::TcpWestwood()
TcpWestwoodPlus::TcpWestwoodPlus()
: TcpNewReno(),
m_currentBW(0),
m_lastSampleBW(0),
@@ -85,12 +78,11 @@ TcpWestwood::TcpWestwood()
NS_LOG_FUNCTION(this);
}
TcpWestwood::TcpWestwood(const TcpWestwood& sock)
TcpWestwoodPlus::TcpWestwoodPlus(const TcpWestwoodPlus& sock)
: TcpNewReno(sock),
m_currentBW(sock.m_currentBW),
m_lastSampleBW(sock.m_lastSampleBW),
m_lastBW(sock.m_lastBW),
m_pType(sock.m_pType),
m_fType(sock.m_fType),
m_IsCount(sock.m_IsCount)
{
@@ -98,12 +90,12 @@ TcpWestwood::TcpWestwood(const TcpWestwood& sock)
NS_LOG_LOGIC("Invoked the copy constructor");
}
TcpWestwood::~TcpWestwood()
TcpWestwoodPlus::~TcpWestwoodPlus()
{
}
void
TcpWestwood::PktsAcked(Ptr<TcpSocketState> tcb, uint32_t packetsAcked, const Time& rtt)
TcpWestwoodPlus::PktsAcked(Ptr<TcpSocketState> tcb, uint32_t packetsAcked, const Time& rtt)
{
NS_LOG_FUNCTION(this << tcb << packetsAcked << rtt);
@@ -115,45 +107,23 @@ TcpWestwood::PktsAcked(Ptr<TcpSocketState> tcb, uint32_t packetsAcked, const Tim
m_ackedSegments += packetsAcked;
if (m_pType == TcpWestwood::WESTWOOD)
if (!(rtt.IsZero() || m_IsCount))
{
EstimateBW(rtt, tcb);
}
else if (m_pType == TcpWestwood::WESTWOODPLUS)
{
if (!(rtt.IsZero() || m_IsCount))
{
m_IsCount = true;
m_bwEstimateEvent.Cancel();
m_bwEstimateEvent = Simulator::Schedule(rtt, &TcpWestwood::EstimateBW, this, rtt, tcb);
}
m_IsCount = true;
m_bwEstimateEvent.Cancel();
m_bwEstimateEvent = Simulator::Schedule(rtt, &TcpWestwoodPlus::EstimateBW, this, rtt, tcb);
}
}
void
TcpWestwood::EstimateBW(const Time& rtt, Ptr<TcpSocketState> tcb)
TcpWestwoodPlus::EstimateBW(const Time& rtt, Ptr<TcpSocketState> tcb)
{
NS_LOG_FUNCTION(this);
NS_ASSERT(!rtt.IsZero());
if (m_pType == TcpWestwood::WESTWOOD)
{
Time currentAck = Simulator::Now();
NS_ABORT_MSG_IF(currentAck == m_lastAck,
"This violates a model assumption and would lead to divide-by-zero; please "
"report to ns-3 maintainers if this occurs.");
m_currentBW = DataRate(m_ackedSegments * tcb->m_segmentSize * 8.0 /
(currentAck - m_lastAck).GetSeconds());
m_lastAck = currentAck;
}
else if (m_pType == TcpWestwood::WESTWOODPLUS)
{
m_currentBW = DataRate(m_ackedSegments * tcb->m_segmentSize * 8.0 / rtt.GetSeconds());
m_IsCount = false;
}
m_currentBW = DataRate(m_ackedSegments * tcb->m_segmentSize * 8.0 / rtt.GetSeconds());
m_IsCount = false;
m_ackedSegments = 0;
@@ -161,12 +131,12 @@ TcpWestwood::EstimateBW(const Time& rtt, Ptr<TcpSocketState> tcb)
// Filter the BW sample
constexpr double alpha = 0.9;
constexpr double ALPHA = 0.9;
if (m_fType == TcpWestwood::TUSTIN)
if (m_fType == TcpWestwoodPlus::TUSTIN)
{
DataRate sample_bwe = m_currentBW;
m_currentBW = (m_lastBW * alpha) + (((sample_bwe + m_lastSampleBW) * 0.5) * (1 - alpha));
m_currentBW = (m_lastBW * ALPHA) + (((sample_bwe + m_lastSampleBW) * 0.5) * (1 - ALPHA));
m_lastSampleBW = sample_bwe;
m_lastBW = m_currentBW;
}
@@ -175,7 +145,7 @@ TcpWestwood::EstimateBW(const Time& rtt, Ptr<TcpSocketState> tcb)
}
uint32_t
TcpWestwood::GetSsThresh(Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight [[maybe_unused]])
TcpWestwoodPlus::GetSsThresh(Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight [[maybe_unused]])
{
uint32_t ssThresh = static_cast<uint32_t>((m_currentBW * tcb->m_minRtt) / 8.0);
@@ -186,9 +156,9 @@ TcpWestwood::GetSsThresh(Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight [
}
Ptr<TcpCongestionOps>
TcpWestwood::Fork()
TcpWestwoodPlus::Fork()
{
return CreateObject<TcpWestwood>(*this);
return CreateObject<TcpWestwoodPlus>(*this);
}
} // namespace ns3

View File

@@ -47,9 +47,9 @@ class Time;
/**
* \ingroup congestionOps
*
* \brief An implementation of TCP Westwood and Westwood+.
* \brief An implementation of TCP Westwood+.
*
* Westwood and Westwood+ employ the AIAD (Additive Increase/Adaptive Decrease)
* Westwood+ employ the AIAD (Additive Increase/Adaptive Decrease)
* congestion control paradigm. When a congestion episode happens,
* instead of halving the cwnd, these protocols try to estimate the network's
* bandwidth and use the estimated value to adjust the cwnd.
@@ -60,11 +60,11 @@ class Time;
* and the EstimateBW (int, const, Time). The CountAck method calculates
* the number of acknowledged segments on the receipt of an ACK.
* The EstimateBW estimates the bandwidth based on the value returned by CountAck
* and the sampling interval (last ACK inter-arrival time for Westwood and last RTT for Westwood+).
* and the sampling interval (last RTT).
*
* WARNING: this TCP model lacks validation and regression tests; use with caution.
*/
class TcpWestwood : public TcpNewReno
class TcpWestwoodPlus : public TcpNewReno
{
public:
/**
@@ -73,22 +73,13 @@ class TcpWestwood : public TcpNewReno
*/
static TypeId GetTypeId();
TcpWestwood();
TcpWestwoodPlus();
/**
* \brief Copy constructor
* \param sock the object to copy
*/
TcpWestwood(const TcpWestwood& sock);
~TcpWestwood() override;
/**
* \brief Protocol variant (Westwood or Westwood+)
*/
enum ProtocolType
{
WESTWOOD,
WESTWOODPLUS
};
TcpWestwoodPlus(const TcpWestwoodPlus& sock);
~TcpWestwoodPlus() override;
/**
* \brief Filter type (None or Tustin)
@@ -125,8 +116,7 @@ class TcpWestwood : public TcpNewReno
TracedValue<DataRate> m_currentBW; //!< Current value of the estimated BW
DataRate m_lastSampleBW; //!< Last bandwidth sample
DataRate m_lastBW; //!< Last bandwidth sample after being filtered
enum ProtocolType m_pType; //!< 0 for Westwood, 1 for Westwood+
enum FilterType m_fType; //!< 0 for none, 1 for Tustin
FilterType m_fType; //!< 0 for none, 1 for Tustin
uint32_t m_ackedSegments; //!< The number of segments ACKed between RTTs
bool m_IsCount; //!< Start keeping track of m_ackedSegments for Westwood+ if TRUE

View File

@@ -21,7 +21,7 @@
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/simple-channel.h"
#include "ns3/tcp-westwood.h"
#include "ns3/tcp-westwood-plus.h"
using namespace ns3;
@@ -442,7 +442,7 @@ class TcpFastRetrTestSuite : public TestSuite
: TestSuite("tcp-fast-retr-test", UNIT)
{
std::list<TypeId> types;
types.insert(types.begin(), TcpWestwood::GetTypeId());
types.insert(types.begin(), TcpWestwoodPlus::GetTypeId());
types.insert(types.begin(), TcpNewReno::GetTypeId());
for (std::list<TypeId>::iterator it = types.begin(); it != types.end(); ++it)

View File

@@ -35,7 +35,7 @@
#include "ns3/string.h"
#include "ns3/tcp-header.h"
#include "ns3/tcp-socket-factory.h"
#include "ns3/tcp-westwood.h"
#include "ns3/tcp-westwood-plus.h"
#include "ns3/test.h"
#include "ns3/uinteger.h"
@@ -146,7 +146,7 @@ Ns3TcpLossTestCase::Ns3TcpLossTestCase()
m_writeResults(WRITE_PCAP),
m_writeLogging(WRITE_LOGGING),
m_needToClose(true),
m_tcpModel("ns3::TcpWestwood")
m_tcpModel("ns3::TcpWestwoodPlus")
{
}
@@ -351,15 +351,7 @@ Ns3TcpLossTestCase::DoRun()
std::ostringstream tcpModel;
tcpModel << "ns3::Tcp" << m_tcpModel;
if (m_tcpModel == "WestwoodPlus")
{
Config::SetDefault("ns3::TcpL4Protocol::SocketType", TypeIdValue(TcpWestwood::GetTypeId()));
Config::SetDefault("ns3::TcpWestwood::ProtocolType", EnumValue(TcpWestwood::WESTWOODPLUS));
}
else
{
Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue(tcpModel.str()));
}
Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue(tcpModel.str()));
Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1000));
Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(1));
@@ -370,7 +362,7 @@ Ns3TcpLossTestCase::DoRun()
LogComponentEnableAll(LOG_PREFIX_FUNC);
LogComponentEnable("Ns3TcpLossTest", LOG_LEVEL_ALL);
LogComponentEnable("ErrorModel", LOG_LEVEL_DEBUG);
LogComponentEnable("TcpWestwood", LOG_LEVEL_ALL);
LogComponentEnable("TcpWestwoodPlus", LOG_LEVEL_ALL);
LogComponentEnable("TcpCongestionOps", LOG_LEVEL_INFO);
LogComponentEnable("TcpSocketBase", LOG_LEVEL_INFO);
}
@@ -530,12 +522,6 @@ Ns3TcpLossTestSuite::Ns3TcpLossTestSuite()
AddTestCase(new Ns3TcpLossTestCase("NewReno", 3), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("NewReno", 4), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("Westwood", 0), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("Westwood", 1), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("Westwood", 2), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("Westwood", 3), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("Westwood", 4), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("WestwoodPlus", 0), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("WestwoodPlus", 1), TestCase::QUICK);
AddTestCase(new Ns3TcpLossTestCase("WestwoodPlus", 2), TestCase::QUICK);