tcp: Add H-TCP model

This commit is contained in:
Amir Modarresi
2016-08-18 16:22:57 -07:00
parent c657724294
commit 531955a8fe
8 changed files with 544 additions and 1 deletions

View File

@@ -110,6 +110,7 @@ Jens Mittag (jens.mittag@kit.edu)
Marco Miozzo (mmiozzo@cttc.es)
Faker Moatamri (faker.moatamri@inria.fr)
Edvin Močibob (edvin.mocibob@gmail.com)
Amir Modarresi (amodarresi@ittc.ku.edu)
Mike Moreton (mjvm_ns@hotmail.com)
Michele Muccio (michelemuccio@virgilio.it)
Esteban Municio (esteban.municio@urjc.es)

View File

@@ -34,6 +34,7 @@ New user-visible features
- (internet) Added TCP Veno congestion control algorithm
- (internet) Added TCP Bic congestion control algorithm
- (internet) Added TCP YeAH congestion control algorithm
- (internet) Added H-TCP congestion control algorithm
- (network) SocketAddressTag has been removed from the codebase.
Users can use RecvFrom (for UDP) or GetPeerName (for TCP) instead.
- (wifi) A new SpectrumWifiPhy physical layer model, making use of the

View File

@@ -178,7 +178,7 @@ int main (int argc, char *argv[])
CommandLine cmd;
cmd.AddValue ("transport_prot", "Transport protocol to use: TcpNewReno, "
"TcpHybla, TcpHighSpeed, TcpVegas, TcpScalable, TcpVeno, "
"TcpHybla, TcpHighSpeed, TcpHtcp, TcpVegas, TcpScalable, TcpVeno, "
"TcpBic, TcpYeah, TcpIllinois, TcpWestwood, TcpWestwoodPlus ", transport_prot);
cmd.AddValue ("error_p", "Packet error rate", error_p);
cmd.AddValue ("bandwidth", "Bottleneck bandwidth", bandwidth);
@@ -246,6 +246,10 @@ int main (int argc, char *argv[])
{
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpScalable::GetTypeId ()));
}
else if (transport_prot.compare ("TcpHtcp") == 0)
{
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpHtcp::GetTypeId ()));
}
else if (transport_prot.compare ("TcpVeno") == 0)
{
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpVeno::GetTypeId ()));
@@ -377,6 +381,7 @@ int main (int argc, char *argv[])
|| transport_prot.compare ("TcpWestwoodPlus") == 0
|| transport_prot.compare ("TcpHybla") == 0
|| transport_prot.compare ("TcpHighSpeed") == 0
|| transport_prot.compare ("TcpHtcp") == 0
|| transport_prot.compare ("TcpVegas") == 0
|| transport_prot.compare ("TcpVeno") == 0
|| transport_prot.compare ("TcpBic") == 0

View File

@@ -636,6 +636,39 @@ default parameter settings:
More information: http://www.doi.org/10.1145/1190095.1190166
H-TCP
^^^^^
H-TCP has been designed for high BDP (Bandwidth-Delay Product) paths. It is
a dual mode protocol. In normal conditions, it works like traditional TCP
with the same rate of increment and decrement for the congestion window.
However, in high BDP networks, when it finds no congestion on the path
after ``deltal`` seconds, it increases the window size based on the alpha
function in the following:
.. math::
alpha(delta)=1+10(delta-deltal)+0.5(delta-deltal)^2
where ``deltal`` is a threshold in seconds for switching between the modes and
``delta`` is the elapsed time from the last congestion. During congestion,
it reduces the window size by multiplying by beta function provided
in the reference paper. The calculated throughput between the last two
consecutive congestion events is considered for beta calculation.
The transport ``TcpHtcp`` can be selected in the program
``examples/tcp/tcp-variants/comparison`` to perform an experiment with H-TCP,
although it is useful to increase the bandwidth in this example (e.g.
to 20 Mb/s) to create a higher BDP link, such as
::
./waf --run "tcp-variants-comparison --transport_prot=TcpHtcp --bandwidth=20Mbps --duration=10"
More information (paper): http://www.hamilton.ie/net/htcp3.pdf
More information (Internet Draft): https://tools.ietf.org/html/draft-leith-tcp-htcp-06
Validation
++++++++++
@@ -653,6 +686,7 @@ section below on :ref:`Writing-tcp-tests`.
* **tcp-fast-retr-test:** Fast Retransmit testing
* **tcp-header:** Unit tests on the TCP header
* **tcp-highspeed-test:** Unit tests on the Highspeed congestion control
* **tcp-htcp-test:** Unit tests on the H-TCP congestion control
* **tcp-hybla-test:** Unit tests on the Hybla congestion control
* **tcp-vegas-test:** Unit tests on the Vegas congestion control
* **tcp-veno-test:** Unit tests on the Veno congestion control

View File

@@ -0,0 +1,230 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2015 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
*
* by: Amir Modarresi <amodarresi@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-htcp.h"
#include "ns3/log.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/simulator.h"
#include "ns3/abort.h"
#include "ns3/node.h"
#include "math.h"
#include "ns3/tcp-socket-base.h"
#include "ns3/sequence-number.h"
#include "ns3/double.h"
#include "ns3/nstime.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("TcpHtcp");
NS_OBJECT_ENSURE_REGISTERED (TcpHtcp);
TypeId TcpHtcp::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpHtcp")
.SetParent<TcpNewReno> ()
.AddConstructor<TcpHtcp> ()
.SetGroupName ("Internet")
.AddAttribute ("DefaultBackoff",
"The default AIMD backoff factor",
DoubleValue (0.5),
MakeDoubleAccessor (&TcpHtcp::m_defaultBackoff),
MakeDoubleChecker<double> (0,1))
.AddAttribute ("ThroughputRatio",
"Threshold value for updating beta",
DoubleValue (0.2),
MakeDoubleAccessor (&TcpHtcp::m_throughputRatio),
MakeDoubleChecker<double> ())
.AddAttribute ("DeltaL",
"Delta_L parameter in increase function",
TimeValue (Seconds (1)),
MakeTimeAccessor (&TcpHtcp::m_deltaL),
MakeTimeChecker ())
;
return tid;
}
std::string TcpHtcp::GetName () const
{
return "TcpHtcp";
}
TcpHtcp::TcpHtcp (void)
: TcpNewReno (),
m_alpha (0),
m_beta (0),
m_delta (0),
m_lastCon (0),
m_minRtt (Time::Max ()),
m_maxRtt (Time::Min ()),
m_throughput (0),
m_lastThroughput (0),
m_dataSent (0)
{
NS_LOG_FUNCTION (this);
}
TcpHtcp::TcpHtcp (const TcpHtcp& sock)
: TcpNewReno (sock),
m_alpha (sock.m_alpha),
m_beta (sock.m_beta),
m_defaultBackoff (sock.m_defaultBackoff),
m_throughputRatio (sock.m_throughputRatio),
m_delta (sock.m_delta),
m_deltaL (sock.m_deltaL),
m_lastCon (sock.m_lastCon),
m_minRtt (sock.m_minRtt),
m_maxRtt (sock.m_maxRtt),
m_throughput (sock.m_throughput),
m_lastThroughput (sock.m_lastThroughput),
m_dataSent (sock.m_dataSent)
{
NS_LOG_FUNCTION (this);
}
TcpHtcp::~TcpHtcp (void)
{
NS_LOG_FUNCTION (this);
}
Ptr<TcpCongestionOps> TcpHtcp::Fork (void)
{
NS_LOG_FUNCTION (this);
return CopyObject<TcpHtcp> (this);
}
void TcpHtcp::CongestionAvoidance (Ptr<TcpSocketState> tcb,
uint32_t segmentsAcked)
{
NS_LOG_FUNCTION (this << tcb << segmentsAcked);
if (segmentsAcked > 0)
{
double adder = static_cast<double> (((tcb->m_segmentSize
* tcb->m_segmentSize) + (tcb->m_cWnd * m_alpha)) / tcb->m_cWnd);
adder = std::max (1.0, adder);
tcb->m_cWnd += static_cast<uint32_t> (adder);
NS_LOG_INFO ("In CongAvoid, updated to cwnd " << tcb->m_cWnd
<< " ssthresh " << tcb->m_ssThresh);
}
}
void TcpHtcp::UpdateAlpha (void)
{
NS_LOG_FUNCTION (this);
m_delta = (Simulator::Now () - m_lastCon);
if (m_delta <= m_deltaL)
{
m_alpha = 1;
}
else
{
Time diff = m_delta - m_deltaL;
double diffSec = diff.GetSeconds ();
// alpha=1+10(Delta-Delta_L)+[0.5(Delta-Delta_L)]^2 (seconds)
// from Leith and Shorten H-TCP paper
m_alpha = (1 + 10 * diffSec + 0.25 * (diffSec * diffSec));
}
m_alpha = 2 * (1 - m_beta) * m_alpha;
if (m_alpha < 1)
{
m_alpha = 1;
}
NS_LOG_DEBUG ("Updated m_alpha: " << m_alpha);
}
void TcpHtcp::UpdateBeta (void)
{
NS_LOG_FUNCTION (this);
if (m_lastThroughput > 0)
{
if (((m_throughput - m_lastThroughput) / m_lastThroughput) > m_throughputRatio)
{
m_beta = m_defaultBackoff;
}
else
{
m_beta = m_minRtt.GetDouble () / m_maxRtt.GetDouble ();
}
}
else
{
m_beta = m_defaultBackoff;
}
NS_LOG_DEBUG ("Updated m_beta: " << m_beta);
}
uint32_t TcpHtcp::GetSsThresh (Ptr<const TcpSocketState> tcb,
uint32_t bytesInFlight)
{
NS_LOG_FUNCTION (this << tcb << bytesInFlight);
m_lastCon = Simulator::Now ();
UpdateBeta ();
UpdateAlpha ();
uint32_t segWin = 2 * tcb->m_segmentSize;
uint32_t bFlight = bytesInFlight * m_beta;
uint32_t ssThresh = std::max (segWin, bFlight);
m_minRtt = Time::Max ();
m_maxRtt = Time::Min ();
m_lastThroughput = m_throughput;
m_throughput = 0;
m_dataSent = 0;
NS_LOG_DEBUG (this << " ssThresh: " << ssThresh << " m_beta: " << m_beta);
return ssThresh;
}
void TcpHtcp::PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
const Time &rtt)
{
NS_LOG_FUNCTION (this << tcb << segmentsAcked << rtt);
NS_LOG_DEBUG ("TcpSocketState: " << tcb->m_congState);
if (tcb->m_congState == TcpSocketState::CA_OPEN)
{
m_dataSent += segmentsAcked * tcb->m_segmentSize;
}
m_throughput = m_dataSent
/ (Simulator::Now ().GetSeconds () - m_lastCon.GetSeconds ());
UpdateAlpha ();
if (rtt < m_minRtt)
{
m_minRtt = rtt;
NS_LOG_DEBUG ("Updated m_minRtt=" << m_minRtt);
}
if (rtt > m_maxRtt)
{
m_maxRtt = rtt;
NS_LOG_DEBUG ("Updated m_maxRtt=" << m_maxRtt);
}
}
} // namespace ns3

View File

@@ -0,0 +1,120 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2015 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
*
* by: Amir Modarresi <amodarresi@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 TCP_HTCP_H
#define TCP_HTCP_H
#include "ns3/tcp-congestion-ops.h"
#include "ns3/traced-value.h"
#include "ns3/sequence-number.h"
namespace ns3 {
/**
* \ingroup socket
* \ingroup tcp
*
* \brief An implementation of the H-TCP variant of TCP.
*
* This class contains the H-TCP implementation of TCP, according to
* Internet-Draft draft-leith-tcp-htcp-03 and its related paper,
* "H-TCP: TCP for high-speed and long-distance networks"
* H-TCP is a congestion control protocol suitable for high bandwidth-delay
* product networks. It is fair to similar flows present in the network and
* also friendly with conventional TCP. It also makes use of free
* bandwidth when it is available.
*/
class TcpHtcp : public TcpNewReno
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
/**
* Create an unbound tcp socket.
*/
TcpHtcp (void);
/**
* \brief Copy constructor
* \param sock the object to copy
*/
TcpHtcp (const TcpHtcp& sock);
virtual ~TcpHtcp (void);
virtual std::string GetName () const;
virtual Ptr<TcpCongestionOps> Fork ();
virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb,
uint32_t bytesInFlight);
virtual void PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
const Time &rtt);
protected:
virtual void CongestionAvoidance (Ptr<TcpSocketState> tcb,
uint32_t segmentsAcked);
private:
/**
* \brief calculates alpha as an increment parameter for HTCP
*
* \param tcb as TcpSocketState
*
* \return updated value of alpha as the increment factor
*/
void UpdateAlpha (void);
/**
* \brief calculates beta as the decrement parameter for HTCP
*
* \param tcb as TcpSocketState
*
* \return updated value of beta as the decrement factor
*/
void UpdateBeta (void);
// h-tcp varaibles
double m_alpha; //!< Adjusting the AMID increase parameter by
//f_alpha(m_delta) function
double m_beta; //!< AMID decrease parameter
double m_defaultBackoff; //!< default value when throughput ratio less than default
double m_throughputRatio; //!< ratio of two consequence throughput
Time m_delta; //!< Time in second that has elapsed since the
//last congestion event experienced by a flow
Time m_deltaL; //!< Threshold for switching between standard
//and new increase function
Time m_lastCon; //!< Time of the last congestion for the flow
Time m_minRtt; //!< Minimum RTT in each congestion period
Time m_maxRtt; //!< Maximum RTT in each congestion period
uint32_t m_throughput; //!< Current throughput since last congestion
uint32_t m_lastThroughput; //!< Throughput in last congestion period
uint32_t m_dataSent; //!< Current amount of data sent since last congestion
};
} // namespace ns3
#endif /* TCP_HTCP_H */

View File

@@ -0,0 +1,149 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2015 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
*
* Authors: Amir Modarresi <amodarresi@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-htcp.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("TcpHtcpTestSuite");
/**
* \brief Testing the congestion avoidance increment on TcpHtcp
*/
class TcpHtcpIncrementTest : public TestCase
{
public:
TcpHtcpIncrementTest (uint32_t cWnd, uint32_t segmentSize,
uint32_t segmentsAcked, Time lastCongestion, Time firstAck,
Time secondAck, uint32_t expectedCwnd, const std::string &name);
private:
virtual void DoRun (void);
uint32_t m_cWnd;
uint32_t m_segmentSize;
uint32_t m_segmentsAcked;
Time m_lastCongestion;
Time m_firstAck;
Time m_secondAck;
uint32_t m_expectedCwnd;
Ptr<TcpSocketState> m_state;
};
TcpHtcpIncrementTest::TcpHtcpIncrementTest (uint32_t cWnd, uint32_t segmentSize,
uint32_t segmentsAcked, Time lastCongestion, Time firstAck,
Time secondAck, uint32_t expectedCwnd, const std::string &name)
: TestCase (name),
m_cWnd (cWnd),
m_segmentSize (segmentSize),
m_segmentsAcked (segmentsAcked),
m_lastCongestion (lastCongestion),
m_firstAck (firstAck),
m_secondAck (secondAck),
m_expectedCwnd (expectedCwnd)
{
}
/**
* \brief Since the calculation depends on the throughput and its associated
* timing, we schedule a few exact events. We get the value from HTCP methods
* during the simulation and compare them with their associated expected
* values calculated from the algorithm by hand.
*/
void
TcpHtcpIncrementTest::DoRun ()
{
NS_LOG_FUNCTION (this);
m_state = CreateObject<TcpSocketState> ();
m_state->m_cWnd = m_cWnd;
m_state->m_segmentSize = m_segmentSize;
Ptr<TcpHtcp> cong = CreateObject<TcpHtcp> ();
Time lastCongestion;
NS_LOG_DEBUG ("m_cWnd: " << m_cWnd << " m_segmentSize: " << m_segmentSize <<
" m_segmentsAcked: " << m_segmentsAcked << " m_lastCongestion" << m_lastCongestion);
Simulator::Schedule (Time (m_lastCongestion), &TcpHtcp::GetSsThresh, cong,
m_state, m_state->m_cWnd);
lastCongestion = m_lastCongestion;
Simulator::Schedule (Time (m_firstAck), &TcpHtcp::PktsAcked, cong, m_state,
m_segmentsAcked, Time (ns3::MilliSeconds (80)));
Simulator::Schedule (Time (m_secondAck), &TcpHtcp::PktsAcked, cong, m_state,
m_segmentsAcked, Time (ns3::MilliSeconds (100)));
Simulator::Run ();
NS_LOG_DEBUG ("Simulation ran for the scheduled events");
cong->IncreaseWindow (m_state, m_segmentsAcked);
NS_LOG_DEBUG ( "m_cwnd from function: " << m_state->m_cWnd << " expected cWnd calculated: " << m_expectedCwnd);
NS_TEST_ASSERT_MSG_EQ (m_state->m_cWnd.Get (), m_expectedCwnd,
"CWnd has not updated correctly");
Simulator::Destroy ();
}
/* The following tests simulate conditions after a congestion event and
* return to 1/2 ssthresh. After that, two acks are scheduled and the
* value of the cWnd is compared at the end of the event.
* The values in each test have been chosen randomly. The first test
* simulates receiving acks for 38 packets with segmentSize=536,
* the second one receives ack for 100 packets with segmentSize=1 and
* the third one receives ack for 50 segment with segmentSize=1446.
* The resulting cWnd values of 20383, 40 and 76671 have been
* calculated by hand from the algorithm for their expected values.
*/
static class TcpHtcpTestSuite : public TestSuite
{
public:
TcpHtcpTestSuite ()
: TestSuite ("tcp-htcp-test", UNIT)
{
AddTestCase (
new TcpHtcpIncrementTest (38 * 536, 536, 38, ns3::MilliSeconds (1),
ns3::MilliSeconds (900), ns3::MilliSeconds (1000),
20383,"TcpHtcp increment test on cWnd "), TestCase::QUICK);
AddTestCase (
new TcpHtcpIncrementTest (38, 1, 100, ns3::MilliSeconds (1),
ns3::MilliSeconds (900), ns3::MilliSeconds (1100),
40,"TcpHtcp increment test on cWnd "), TestCase::QUICK);
AddTestCase (
new TcpHtcpIncrementTest (53 * 1446, 1446, 50, ns3::MilliSeconds (1),
ns3::MilliSeconds (900), ns3::MilliSeconds (1500),
76671,"TcpHtcp increment test on cWnd "), TestCase::QUICK);
}
} g_TcpHtcpTest;
} // namespace ns3

View File

@@ -155,6 +155,7 @@ def build(bld):
'model/tcp-bic.cc',
'model/tcp-yeah.cc',
'model/tcp-illinois.cc',
'model/tcp-htcp.cc',
'model/tcp-rx-buffer.cc',
'model/tcp-tx-buffer.cc',
'model/tcp-option.cc',
@@ -259,6 +260,7 @@ def build(bld):
'test/tcp-bic-test.cc',
'test/tcp-yeah-test.cc',
'test/tcp-illinois-test.cc',
'test/tcp-htcp-test.cc',
'test/tcp-zero-window-test.cc',
'test/tcp-pkts-acked-test.cc',
'test/tcp-rtt-estimation.cc',
@@ -369,6 +371,7 @@ def build(bld):
'model/tcp-bic.h',
'model/tcp-yeah.h',
'model/tcp-illinois.h',
'model/tcp-htcp.h',
'model/tcp-socket-base.h',
'model/tcp-tx-buffer.h',
'model/tcp-rx-buffer.h',