internet: added TCP Veno
This commit is contained in:
@@ -24,11 +24,13 @@ New user-visible features
|
||||
-------------------------
|
||||
- (internet) Added TCP Vegas congestion control algorithm
|
||||
- (internet) Added TCP Scalable congestion control algorithm
|
||||
- (internet) Added TCP Veno congestion control algorithm
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
- Bug 2057 - ARP and Ndisc caches should be updated by receiving valid L3 packets
|
||||
- Bug 2346 - SixLowPan ConpressionThreshold can be violated.
|
||||
- Bug 2329 - TCP Veno implementation
|
||||
- Bug 2333 - TCP Scalable implementation
|
||||
- Bug 2347 - LrWpan Ascii traces are hooked to the wrong traces.
|
||||
- Bug 2353 - TCP Vegas implementation
|
||||
|
||||
@@ -178,8 +178,8 @@ int main (int argc, char *argv[])
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("transport_prot", "Transport protocol to use: TcpNewReno, "
|
||||
"TcpHybla, TcpHighSpeed, TcpVegas, TcpScalable, TcpWestwood, "
|
||||
"TcpWestwoodPlus ", transport_prot);
|
||||
"TcpHybla, TcpHighSpeed, TcpVegas, TcpScalable, TcpVeno, "
|
||||
"TcpWestwood, TcpWestwoodPlus ", transport_prot);
|
||||
cmd.AddValue ("error_p", "Packet error rate", error_p);
|
||||
cmd.AddValue ("bandwidth", "Bottleneck bandwidth", bandwidth);
|
||||
cmd.AddValue ("delay", "Bottleneck delay", delay);
|
||||
@@ -246,6 +246,10 @@ int main (int argc, char *argv[])
|
||||
{
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpScalable::GetTypeId ()));
|
||||
}
|
||||
else if (transport_prot.compare ("TcpVeno") == 0)
|
||||
{
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpVeno::GetTypeId ()));
|
||||
}
|
||||
else if (transport_prot.compare ("TcpWestwood") == 0)
|
||||
{ // the default protocol type in ns3::TcpWestwood is WESTWOOD
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpWestwood::GetTypeId ()));
|
||||
@@ -363,6 +367,7 @@ int main (int argc, char *argv[])
|
||||
|| transport_prot.compare ("TcpHybla") == 0
|
||||
|| transport_prot.compare ("TcpHighSpeed") == 0
|
||||
|| transport_prot.compare ("TcpVegas") == 0
|
||||
|| transport_prot.compare ("TcpVeno") == 0
|
||||
|| transport_prot.compare ("TcpScalable") == 0)
|
||||
{
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (tcp_adu_size));
|
||||
|
||||
@@ -275,6 +275,37 @@ the following equation:
|
||||
|
||||
More informations at: http://dl.acm.org/citation.cfm?id=956989
|
||||
|
||||
Veno
|
||||
^^^^
|
||||
|
||||
TCP Veno enhances Reno algorithm for more effectively dealing with random
|
||||
packet loss in wireless access networks by employing Vegas's method in
|
||||
estimating the backlog at the bottleneck queue to distinguish between
|
||||
congestive and non-congestive states.
|
||||
|
||||
The backlog (the number of packets accumulated at the bottleneck queue) is
|
||||
calculated using Equation (1):
|
||||
N = Actual * (RTT - BaseRTT) = Diff * BaseRTT (1)
|
||||
where
|
||||
Diff = Expected - Actual = cwnd/BaseRTT - cwnd/RTT
|
||||
|
||||
Veno makes decision on cwnd modification based on the calculated N and its
|
||||
predefined threshold beta.
|
||||
|
||||
Specifically, it refines the additive increase algorithm of Reno so that the
|
||||
connection can stay longer in the stable state by incrementing cwnd by
|
||||
1/cwnd for every other new ACK received after the available bandwidth has
|
||||
been fully utilized, i.e. when N exceeds beta. Otherwise, Veno increases
|
||||
its cwnd by 1/cwnd upon every new ACK receipt as in Reno.
|
||||
|
||||
In the multiplicative decrease algorithm, when Veno is in the non-congestive
|
||||
state, i.e. when N is less than beta, Veno decrements its cwnd by only 1/5
|
||||
because the loss encountered is more likely a corruption-based loss than a
|
||||
congestion-based. Only when N is greater than beta, Veno halves its sending
|
||||
rate as in Reno.
|
||||
|
||||
More informations at: http://dx.doi.org/10.1109/JSAC.2002.807336
|
||||
|
||||
Validation
|
||||
++++++++++
|
||||
|
||||
|
||||
253
src/internet/model/tcp-veno.cc
Normal file
253
src/internet/model/tcp-veno.cc
Normal file
@@ -0,0 +1,253 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
|
||||
*
|
||||
* 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: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
|
||||
*
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* Information and Telecommunication Technology Center (ITTC)
|
||||
* and Department of Electrical Engineering and Computer Science
|
||||
* The University of Kansas Lawrence, KS USA.
|
||||
*/
|
||||
|
||||
#include "tcp-veno.h"
|
||||
#include "ns3/tcp-socket-base.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpVeno");
|
||||
NS_OBJECT_ENSURE_REGISTERED (TcpVeno);
|
||||
|
||||
TypeId
|
||||
TcpVeno::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::TcpVeno")
|
||||
.SetParent<TcpNewReno> ()
|
||||
.AddConstructor<TcpVeno> ()
|
||||
.SetGroupName ("Internet")
|
||||
.AddAttribute ("Beta", "Threshold for congestion detection",
|
||||
UintegerValue (6),
|
||||
MakeUintegerAccessor (&TcpVeno::m_beta),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TcpVeno::TcpVeno (void)
|
||||
: TcpNewReno (),
|
||||
m_baseRtt (Time::Max ()),
|
||||
m_minRtt (Time::Max ()),
|
||||
m_cntRtt (0),
|
||||
m_doingVenoNow (true),
|
||||
m_diff (0),
|
||||
m_inc (true),
|
||||
m_ackCnt (0),
|
||||
m_beta (6)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
TcpVeno::TcpVeno (const TcpVeno& sock)
|
||||
: TcpNewReno (sock),
|
||||
m_baseRtt (sock.m_baseRtt),
|
||||
m_minRtt (sock.m_minRtt),
|
||||
m_cntRtt (sock.m_cntRtt),
|
||||
m_doingVenoNow (true),
|
||||
m_diff (0),
|
||||
m_inc (true),
|
||||
m_ackCnt (sock.m_ackCnt),
|
||||
m_beta (sock.m_beta)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
TcpVeno::~TcpVeno (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
Ptr<TcpCongestionOps>
|
||||
TcpVeno::Fork (void)
|
||||
{
|
||||
return CopyObject<TcpVeno> (this);
|
||||
}
|
||||
|
||||
void
|
||||
TcpVeno::PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
|
||||
const Time& rtt)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << segmentsAcked << rtt);
|
||||
|
||||
if (rtt.IsZero ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_minRtt = std::min (m_minRtt, rtt);
|
||||
NS_LOG_DEBUG ("Updated m_minRtt= " << m_minRtt);
|
||||
|
||||
|
||||
m_baseRtt = std::min (m_baseRtt, rtt);
|
||||
NS_LOG_DEBUG ("Updated m_baseRtt= " << m_baseRtt);
|
||||
|
||||
// Update RTT counter
|
||||
m_cntRtt++;
|
||||
NS_LOG_DEBUG ("Updated m_cntRtt= " << m_cntRtt);
|
||||
}
|
||||
|
||||
void
|
||||
TcpVeno::EnableVeno (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
|
||||
m_doingVenoNow = true;
|
||||
m_minRtt = Time::Max ();
|
||||
}
|
||||
|
||||
void
|
||||
TcpVeno::DisableVeno ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
m_doingVenoNow = false;
|
||||
}
|
||||
|
||||
void
|
||||
TcpVeno::CongestionStateSet (Ptr<TcpSocketState> tcb,
|
||||
const TcpSocketState::TcpCongState_t newState)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << newState);
|
||||
if (newState == TcpSocketState::CA_OPEN)
|
||||
{
|
||||
EnableVeno (tcb);
|
||||
NS_LOG_LOGIC ("Veno is now on.");
|
||||
}
|
||||
else
|
||||
{
|
||||
DisableVeno ();
|
||||
NS_LOG_LOGIC ("Veno is turned off.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpVeno::IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << segmentsAcked);
|
||||
|
||||
if (!m_doingVenoNow)
|
||||
{
|
||||
// If Veno is not on, we follow NewReno algorithm
|
||||
NS_LOG_LOGIC ("Veno is not turned on, we follow NewReno algorithm.");
|
||||
TcpNewReno::IncreaseWindow (tcb, segmentsAcked);
|
||||
return;
|
||||
}
|
||||
|
||||
// We do the Veno calculations only if we got enough RTT samples
|
||||
if (m_cntRtt <= 2)
|
||||
{ // We do not have enough RTT samples, so we should behave like NewReno
|
||||
NS_LOG_LOGIC ("We do not have enough RTT samples to perform Veno "
|
||||
"calculations, we behave like NewReno.");
|
||||
TcpNewReno::IncreaseWindow (tcb, segmentsAcked);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("We have enough RTT samples to perform Veno calculations.");
|
||||
|
||||
uint64_t targetCwnd;
|
||||
uint32_t segCwnd = tcb->GetCwndInSegments ();
|
||||
|
||||
// Calculate the cwnd we should have
|
||||
targetCwnd = (uint64_t) segCwnd * (double) m_baseRtt.GetMilliSeconds () * 2;
|
||||
targetCwnd = targetCwnd / (double) m_minRtt.GetMilliSeconds ();
|
||||
NS_LOG_DEBUG ("Calculated targetCwnd = " << targetCwnd);
|
||||
|
||||
// Calculate the difference between actual and target cwnd
|
||||
m_diff = (segCwnd * 2) - targetCwnd;
|
||||
NS_LOG_DEBUG ("Calculated m_diff = " << m_diff);
|
||||
|
||||
if (tcb->m_cWnd < tcb->m_ssThresh)
|
||||
{ // Slow start mode. Veno employs same slow start algorithm as NewReno's.
|
||||
NS_LOG_LOGIC ("We are in slow start, behave like NewReno.");
|
||||
segmentsAcked = TcpNewReno::SlowStart (tcb, segmentsAcked);
|
||||
}
|
||||
else
|
||||
{ // Congestion avoidance mode
|
||||
NS_LOG_LOGIC ("We are in congestion avoidance, execute Veno additive "
|
||||
"increase algo.");
|
||||
if (m_diff < m_beta)
|
||||
{
|
||||
// Available bandwidth is not fully utilized,
|
||||
// increase cwnd by 1 every RTT
|
||||
NS_LOG_LOGIC ("Available bandwidth not fully utilized, increase "
|
||||
"cwnd by 1 every RTT");
|
||||
TcpNewReno::CongestionAvoidance (tcb, segmentsAcked);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Available bandwidth is fully utilized,
|
||||
// increase cwnd by 1 every other RTT
|
||||
NS_LOG_LOGIC ("Available bandwidth fully utilized, increase cwnd "
|
||||
"by 1 every other RTT");
|
||||
if (m_inc)
|
||||
{
|
||||
TcpNewReno::CongestionAvoidance (tcb, segmentsAcked);
|
||||
m_inc = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset minRtt
|
||||
m_minRtt = Time::Max ();
|
||||
}
|
||||
|
||||
std::string
|
||||
TcpVeno::GetName () const
|
||||
{
|
||||
return "TcpVeno";
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpVeno::GetSsThresh (Ptr<const TcpSocketState> tcb,
|
||||
uint32_t bytesInFlight)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << bytesInFlight);
|
||||
|
||||
if (m_diff < m_beta)
|
||||
{
|
||||
// random loss due to bit errors is most likely to have occurred,
|
||||
// we cut cwnd by 1/5
|
||||
NS_LOG_LOGIC ("Random loss is most likely to have occurred, "
|
||||
"cwnd is reduced by 1/5");
|
||||
return std::max (bytesInFlight * 4 / 5, 2 * tcb->m_segmentSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// congestion-based loss is most likely to have occurred,
|
||||
// we reduce cwnd by 1/2 as in NewReno
|
||||
NS_LOG_LOGIC ("Congestive loss is most likely to have occurred, "
|
||||
"cwnd is halved");
|
||||
return std::max (bytesInFlight / 2, 2 * tcb->m_segmentSize);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
175
src/internet/model/tcp-veno.h
Normal file
175
src/internet/model/tcp-veno.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
|
||||
*
|
||||
* 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: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
|
||||
*
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* Information and Telecommunication Technology Center (ITTC)
|
||||
* and Department of Electrical Engineering and Computer Science
|
||||
* The University of Kansas Lawrence, KS USA.
|
||||
*/
|
||||
|
||||
#ifndef TCPVENO_H
|
||||
#define TCPVENO_H
|
||||
|
||||
#include "ns3/tcp-congestion-ops.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup tcp
|
||||
*
|
||||
* \brief An implementation of TCP Veno
|
||||
*
|
||||
* TCP Veno enhances Reno algorithm for more effectively dealing with random
|
||||
* packet loss in wireless access networks by employing Vegas's method in
|
||||
* estimating the backlog at the bottleneck queue to distinguish between
|
||||
* congestive and non-congestive states.
|
||||
*
|
||||
* The backlog (the number of packets accumulated at the bottleneck queue) is
|
||||
* calculated using Equation (1):
|
||||
*
|
||||
* N = Actual * (RTT - BaseRTT) = Diff * BaseRTT (1)
|
||||
* where
|
||||
* Diff = Expected - Actual = cwnd/BaseRTT - cwnd/RTT
|
||||
*
|
||||
* Veno makes decision on cwnd modification based on the calculated N and its
|
||||
* predefined threshold beta.
|
||||
*
|
||||
* Specifically, it refines the additive increase algorithm of Reno so that the
|
||||
* connection can stay longer in the stable state by incrementing cwnd by
|
||||
* 1/cwnd for every other new ACK received after the available bandwidth has
|
||||
* been fully utilized, i.e. when N exceeds beta. Otherwise, Veno increases
|
||||
* its cwnd by 1/cwnd upon every new ACK receipt as in Reno.
|
||||
*
|
||||
* In the multiplicative decrease algorithm, when Veno is in the non-congestive
|
||||
* state, i.e. when N is less than beta, Veno decrements its cwnd by only 1/5
|
||||
* because the loss encountered is more likely a corruption-based loss than a
|
||||
* congestion-based. Only when N is greater than beta, Veno halves its sending
|
||||
* rate as in Reno.
|
||||
*
|
||||
* More information: http://dx.doi.org/10.1109/JSAC.2002.807336
|
||||
*/
|
||||
|
||||
class TcpVeno : public TcpNewReno
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Create an unbound tcp socket.
|
||||
*/
|
||||
TcpVeno (void);
|
||||
|
||||
/**
|
||||
* \brief Copy constructor
|
||||
* \param sock the object to copy
|
||||
*/
|
||||
TcpVeno (const TcpVeno& sock);
|
||||
virtual ~TcpVeno (void);
|
||||
|
||||
virtual std::string GetName () const;
|
||||
|
||||
/**
|
||||
* \brief Perform RTT sampling needed to execute Veno algorithm
|
||||
*
|
||||
* The function filters RTT samples from the last RTT to find
|
||||
* the current smallest propagation delay + queueing delay (m_minRtt).
|
||||
* We take the minimum to avoid the effects of delayed ACKs.
|
||||
*
|
||||
* The function also min-filters all RTT measurements seen to find the
|
||||
* propagation delay (m_baseRtt).
|
||||
*
|
||||
* \param tcb internal congestion state
|
||||
* \param segementsAcked count of segments ACKed
|
||||
* \param rtt last RTT
|
||||
*
|
||||
*/
|
||||
virtual void PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
|
||||
const Time& rtt);
|
||||
|
||||
/**
|
||||
* \brief Enable/disable Veno depending on the congestion state
|
||||
*
|
||||
* We only start a Veno when we are in normal congestion state (CA_OPEN state).
|
||||
*
|
||||
* \param tcb internal congestion state
|
||||
* \param newState new congestion state to which the TCP is going to switch
|
||||
*/
|
||||
virtual void CongestionStateSet (Ptr<TcpSocketState> tcb,
|
||||
const TcpSocketState::TcpCongState_t newState);
|
||||
|
||||
/**
|
||||
* \brief Adjust cwnd following Veno additive increase algorithm
|
||||
*
|
||||
* \param tcb internal congestion state
|
||||
* \param segmentsAcked count of segments ACKed
|
||||
*/
|
||||
virtual void IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
|
||||
|
||||
/**
|
||||
* \brief Get slow start threshold during Veno multiplicative-decrease phase
|
||||
*
|
||||
* \param tcb internal congestion state
|
||||
* \param bytesInFlight bytes in flight
|
||||
*
|
||||
* \return the slow start threshold value
|
||||
*/
|
||||
virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb,
|
||||
uint32_t bytesInFlight);
|
||||
|
||||
virtual Ptr<TcpCongestionOps> Fork ();
|
||||
|
||||
protected:
|
||||
private:
|
||||
/**
|
||||
* \brief Enable Veno algorithm to start Veno sampling
|
||||
*
|
||||
* Veno algorithm is enabled in the following situations:
|
||||
* 1. at the establishment of a connection
|
||||
* 2. after an RTO
|
||||
* 3. after fast recovery
|
||||
* 4. when an idle connection is restarted
|
||||
*
|
||||
* \param tcb internal congestion state
|
||||
*/
|
||||
void EnableVeno (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Turn off Veno
|
||||
*/
|
||||
void DisableVeno ();
|
||||
|
||||
private:
|
||||
Time m_baseRtt; //!< Minimum of all RTT measurements seen during connection
|
||||
Time m_minRtt; //!< Minimum of RTTs measured within last RTT
|
||||
uint32_t m_cntRtt; //!< # of RTT measurements during last RTT
|
||||
bool m_doingVenoNow; //!< If true, do Veno for this RTT
|
||||
uint32_t m_diff; //!< Difference between expected and actual throughput
|
||||
bool m_inc; //!< If true, cwnd needs to be incremented
|
||||
uint32_t m_ackCnt; //!< Number of received ACK
|
||||
uint32_t m_beta; //!< Threshold for congestion detection
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // TCPVENO_H
|
||||
220
src/internet/test/tcp-veno-test.cc
Normal file
220
src/internet/test/tcp-veno-test.cc
Normal file
@@ -0,0 +1,220 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
|
||||
*
|
||||
* 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: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
|
||||
*
|
||||
* James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
|
||||
* ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
|
||||
* Information and Telecommunication Technology Center (ITTC)
|
||||
* and Department of Electrical Engineering and Computer Science
|
||||
* The University of Kansas Lawrence, KS USA.
|
||||
*/
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/tcp-congestion-ops.h"
|
||||
#include "ns3/tcp-socket-base.h"
|
||||
#include "ns3/tcp-veno.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpVenoTestSuite");
|
||||
|
||||
/**
|
||||
* \brief Testing the additive increase and multiplicative decrease of TcpVeno
|
||||
*/
|
||||
class TcpVenoTest : public TestCase
|
||||
{
|
||||
public:
|
||||
TcpVenoTest (uint32_t cWnd,
|
||||
uint32_t segmentSize,
|
||||
uint32_t ssThresh,
|
||||
Time rtt,
|
||||
uint32_t segmentsAcked,
|
||||
uint32_t numRtt,
|
||||
const std::string &name);
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
uint32_t AdditiveIncrease (Ptr<TcpVeno> cong, uint32_t diff, UintegerValue beta);
|
||||
uint32_t MultiplicativeDecrease (uint32_t diff, UintegerValue beta);
|
||||
|
||||
uint32_t m_cWnd;
|
||||
uint32_t m_segmentSize;
|
||||
uint32_t m_ssThresh;
|
||||
Time m_rtt;
|
||||
uint32_t m_segmentsAcked;
|
||||
uint32_t m_numRtt;
|
||||
bool m_inc;
|
||||
Ptr<TcpSocketState> m_state;
|
||||
};
|
||||
|
||||
TcpVenoTest::TcpVenoTest (uint32_t cWnd,
|
||||
uint32_t segmentSize,
|
||||
uint32_t ssThresh,
|
||||
Time rtt,
|
||||
uint32_t segmentsAcked,
|
||||
uint32_t numRtt,
|
||||
const std::string &name)
|
||||
: TestCase (name),
|
||||
m_cWnd (cWnd),
|
||||
m_segmentSize (segmentSize),
|
||||
m_ssThresh (ssThresh),
|
||||
m_rtt (rtt),
|
||||
m_segmentsAcked (segmentsAcked),
|
||||
m_numRtt (numRtt),
|
||||
m_inc (true)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TcpVenoTest::DoRun ()
|
||||
{
|
||||
m_state = CreateObject<TcpSocketState> ();
|
||||
|
||||
m_state->m_cWnd = m_cWnd;
|
||||
m_state->m_segmentSize = m_segmentSize;
|
||||
m_state->m_ssThresh = m_ssThresh;
|
||||
|
||||
Ptr<TcpVeno> cong = CreateObject <TcpVeno> ();
|
||||
|
||||
// Set baseRtt to 100 ms
|
||||
cong->PktsAcked (m_state, m_segmentsAcked, MilliSeconds (100));
|
||||
|
||||
// Re-set Veno to assign a new value of minRtt
|
||||
cong->CongestionStateSet (m_state, TcpSocketState::CA_OPEN);
|
||||
cong->PktsAcked (m_state, m_segmentsAcked, m_rtt);
|
||||
|
||||
// Another call to PktsAcked to increment cntRtt beyond 2
|
||||
cong->PktsAcked (m_state, m_segmentsAcked, m_rtt);
|
||||
|
||||
Time baseRtt = MilliSeconds (100);
|
||||
uint32_t segCwnd = m_cWnd / m_segmentSize;
|
||||
|
||||
// Calculate expected throughput
|
||||
uint64_t expectedCwnd;
|
||||
expectedCwnd = (uint64_t) segCwnd * (double) baseRtt.GetMilliSeconds () * 2 / (double) m_rtt.GetMilliSeconds ();
|
||||
|
||||
// Calculate the difference between actual and expected throughput
|
||||
uint32_t diff;
|
||||
diff = (segCwnd * 2) - expectedCwnd;
|
||||
|
||||
// Get the beta attribute
|
||||
UintegerValue beta;
|
||||
cong->GetAttribute ("Beta", beta);
|
||||
|
||||
while (m_numRtt != 0)
|
||||
{
|
||||
// Update cwnd using Veno's additive increase algorithm
|
||||
cong->IncreaseWindow (m_state, m_segmentsAcked);
|
||||
|
||||
// Our calculation of cwnd
|
||||
uint32_t calculatedCwnd = AdditiveIncrease (cong, diff, beta);
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (m_state->m_cWnd.Get (), calculatedCwnd,
|
||||
"CWnd has not updated correctly based on Veno linear increase algorithm");
|
||||
m_numRtt--;
|
||||
}
|
||||
|
||||
// Update ssthresh using Veno's multiplicative decrease algorithm
|
||||
uint32_t ssThresh = cong->GetSsThresh (m_state, m_state->m_cWnd);
|
||||
|
||||
// Our calculation of ssthresh
|
||||
uint32_t calculatedSsThresh = MultiplicativeDecrease (diff, beta);
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (ssThresh, calculatedSsThresh,
|
||||
"Veno has not decremented cWnd correctly based on its multiplicative decrease algo.");
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpVenoTest::AdditiveIncrease (Ptr<TcpVeno> cong, uint32_t diff, UintegerValue beta)
|
||||
{
|
||||
if (m_cWnd < m_ssThresh)
|
||||
{ // Slow start
|
||||
if (m_segmentsAcked >= 1)
|
||||
{
|
||||
m_cWnd += m_segmentSize;
|
||||
m_segmentsAcked--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Congestion avoidance
|
||||
if (diff < beta.Get ())
|
||||
{ // Increase cwnd by 1 every RTT when bandwidth is not fully utilized
|
||||
if (m_segmentsAcked > 0)
|
||||
{
|
||||
double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd;
|
||||
adder = std::max (1.0, adder);
|
||||
m_cWnd += static_cast<uint32_t> (adder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Increase cwnd by 1 every other RTT when bandwidth is fully utilized
|
||||
if (m_inc)
|
||||
{
|
||||
if (m_segmentsAcked > 0)
|
||||
{
|
||||
double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd;
|
||||
adder = std::max (1.0, adder);
|
||||
m_cWnd += static_cast<uint32_t> (adder);
|
||||
}
|
||||
m_inc = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_cWnd;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpVenoTest::MultiplicativeDecrease (uint32_t diff, UintegerValue beta)
|
||||
{
|
||||
uint32_t calculatedSsThresh;
|
||||
if (diff < beta.Get ())
|
||||
{
|
||||
calculatedSsThresh = std::max (2 * m_segmentSize, m_cWnd * 4 / 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
calculatedSsThresh = std::max (2 * m_segmentSize, m_cWnd / 2);
|
||||
}
|
||||
return calculatedSsThresh;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
static class TcpVenoTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
TcpVenoTestSuite () : TestSuite ("tcp-veno-test", UNIT)
|
||||
{
|
||||
AddTestCase (new TcpVenoTest (38 * 1446, 1446, 40 * 1446, MilliSeconds (100), 1, 1,
|
||||
"Veno test on cWnd in slow start and non-congestive loss"),
|
||||
TestCase::QUICK);
|
||||
AddTestCase (new TcpVenoTest (30 * 536, 536, 20 * 536, MilliSeconds (106), 1, 1,
|
||||
"Veno test on cWnd with diff < beta"),
|
||||
TestCase::QUICK);
|
||||
AddTestCase (new TcpVenoTest (60 * 536, 536, 40 * 536, MilliSeconds (106), 1, 3,
|
||||
"Veno increment test on cWnd with diff > beta"),
|
||||
TestCase::QUICK);
|
||||
}
|
||||
} g_tcpVenoTest;
|
||||
|
||||
} // namespace ns3
|
||||
@@ -151,6 +151,7 @@ def build(bld):
|
||||
'model/tcp-congestion-ops.cc',
|
||||
'model/tcp-westwood.cc',
|
||||
'model/tcp-scalable.cc',
|
||||
'model/tcp-veno.cc',
|
||||
'model/tcp-rx-buffer.cc',
|
||||
'model/tcp-tx-buffer.cc',
|
||||
'model/tcp-option.cc',
|
||||
@@ -252,6 +253,7 @@ def build(bld):
|
||||
'test/tcp-hybla-test.cc',
|
||||
'test/tcp-vegas-test.cc',
|
||||
'test/tcp-scalable-test.cc',
|
||||
'test/tcp-veno-test.cc',
|
||||
'test/tcp-zero-window-test.cc',
|
||||
'test/tcp-pkts-acked-test.cc',
|
||||
'test/tcp-rtt-estimation.cc',
|
||||
@@ -358,6 +360,7 @@ def build(bld):
|
||||
'model/tcp-congestion-ops.h',
|
||||
'model/tcp-westwood.h',
|
||||
'model/tcp-scalable.h',
|
||||
'model/tcp-veno.h',
|
||||
'model/tcp-socket-base.h',
|
||||
'model/tcp-tx-buffer.h',
|
||||
'model/tcp-rx-buffer.h',
|
||||
|
||||
Reference in New Issue
Block a user