Added TCP HighSpeed

This commit is contained in:
Natale Patriciello
2015-10-28 11:21:29 +01:00
parent 0aee9d9712
commit 2903ebda5c
3 changed files with 862 additions and 0 deletions

View File

@@ -0,0 +1,758 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 Natale Patriciello, <natale.patriciello@gmail.com>
*
* 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
*
*/
#include "tcp-highspeed.h"
#include "ns3/tcp-socket-base.h"
#include "ns3/log.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("TcpHighSpeed");
NS_OBJECT_ENSURE_REGISTERED (TcpHighSpeed);
TypeId
TcpHighSpeed::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpHighSpeed")
.SetParent<TcpNewReno> ()
.AddConstructor<TcpHighSpeed> ()
.SetGroupName ("Internet")
;
return tid;
}
TcpHighSpeed::TcpHighSpeed (void)
: TcpNewReno (),
m_ackCnt (0)
{
NS_LOG_FUNCTION (this);
}
TcpHighSpeed::TcpHighSpeed (const TcpHighSpeed& sock)
: TcpNewReno (sock),
m_ackCnt (sock.m_ackCnt)
{
NS_LOG_FUNCTION (this);
}
TcpHighSpeed::~TcpHighSpeed (void)
{
NS_LOG_FUNCTION (this);
}
Ptr<TcpCongestionOps>
TcpHighSpeed::Fork (void)
{
return CopyObject<TcpHighSpeed> (this);
}
/**
* \brief Congestion avoidance of TcpHighSpeed
*
* As implementation choice, we increment cWnd only by MSS, when the right
* number of ACK has been received. At this point, the important question is:
* what is the "right number of ACK" ?
*
* As you can recall from RFC, Highspeed works this way:
*
* w = w + a(w)/w
*
* Let's start when a(w) is 1 (so it is classical NewReno). The formula then is
* the classical text-book version for NewReno:
*
* w = w + 1 / w
*
* So, for each segment acked, we increase the window by the quantity 1/w. Or,
* instead of adding the 1/w quantity for each segment acked, we can track the
* number of segments acked (m_ackCnt) and increment by 1 MSS when m_ackCnt
* reaches w.
*
* When a(w) > 1, it means that each segment acked has a different "weight".
* For instance, when it is equal to 2, we need to increase the window by the
* quantity 2/w. But, this means that one segment acked is equivalent (from
* the point of view of incrementing cWnd) to two segments acked in NewReno
* (1/w + 1/w). That a coefficent is, in other word, the weight of each segment
* acked. More weight, less ACK are necessary to increment cWnd, which is
* exactly the Highspeed principle.
*
* \param tcb internal congestion state
* \param segmentsAcked count of segments acked
*/
void
TcpHighSpeed::CongestionAvoidance (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{
NS_LOG_FUNCTION (this << tcb << segmentsAcked);
uint32_t segCwnd = tcb->GetCwndInSegments ();
uint32_t oldCwnd = segCwnd;
if (segmentsAcked > 0)
{
uint32_t coeffA = TableLookupA (segCwnd);
m_ackCnt += segmentsAcked * coeffA;
}
while (m_ackCnt >= segCwnd)
{
m_ackCnt -= segCwnd;
segCwnd += 1;
}
if (segCwnd != oldCwnd)
{
tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
NS_LOG_INFO ("In CongAvoid, updated to cwnd " << tcb->m_cWnd <<
" ssthresh " << tcb->m_ssThresh);
}
}
std::string
TcpHighSpeed::GetName () const
{
return "TcpHighSpeed";
}
/**
* \brief Get slow start threshold following HighSpeed principles
*
* \param tcb internal congestion state
* \param bytesInFlight Bytes in flight
*
* \return the slow start threshold value
*/
uint32_t
TcpHighSpeed::GetSsThresh (Ptr<const TcpSocketState> tcb,
uint32_t bytesInFlight)
{
NS_LOG_FUNCTION (this << tcb << bytesInFlight);
uint32_t segCwnd = bytesInFlight / tcb->m_segmentSize;
double b = 1.0 - TableLookupB (segCwnd);
uint32_t ssThresh = std::max (2.0, segCwnd * b);
NS_LOG_DEBUG ("Calculated b(w) = " << b <<
" resulting (in segment) ssThresh=" << ssThresh);
return ssThresh * tcb->m_segmentSize;
}
uint32_t
TcpHighSpeed::TableLookupA (uint32_t w)
{
if (w <= 38)
{
return 1;
}
else if (w <= 118)
{
return 2;
}
else if (w <= 221)
{
return 3;
}
else if (w <= 347)
{
return 4;
}
else if (w <= 495)
{
return 5;
}
else if (w <= 663)
{
return 6;
}
else if (w <= 851)
{
return 7;
}
else if (w <= 1058)
{
return 8;
}
else if (w <= 1284)
{
return 9;
}
else if (w <= 1529)
{
return 10;
}
else if (w <= 1793)
{
return 11;
}
else if (w <= 2076)
{
return 12;
}
else if (w <= 2378)
{
return 13;
}
else if (w <= 2699)
{
return 14;
}
else if (w <= 3039)
{
return 15;
}
else if (w <= 3399)
{
return 16;
}
else if (w <= 3778)
{
return 17;
}
else if (w <= 4177)
{
return 18;
}
else if (w <= 4596)
{
return 19;
}
else if (w <= 5036)
{
return 20;
}
else if (w <= 5497)
{
return 21;
}
else if (w <= 5979)
{
return 22;
}
else if (w <= 6483)
{
return 23;
}
else if (w <= 7009)
{
return 24;
}
else if (w <= 7558)
{
return 25;
}
else if (w <= 8130)
{
return 26;
}
else if (w <= 8726)
{
return 27;
}
else if (w <= 9346)
{
return 28;
}
else if (w <= 9991)
{
return 29;
}
else if (w <= 10661)
{
return 30;
}
else if (w <= 11358)
{
return 31;
}
else if (w <= 12082)
{
return 32;
}
else if (w <= 12834)
{
return 33;
}
else if (w <= 13614)
{
return 34;
}
else if (w <= 14424)
{
return 35;
}
else if (w <= 15265)
{
return 36;
}
else if (w <= 16137)
{
return 37;
}
else if (w <= 17042)
{
return 38;
}
else if (w <= 17981)
{
return 39;
}
else if (w <= 18955)
{
return 40;
}
else if (w <= 19965)
{
return 41;
}
else if (w <= 21013)
{
return 42;
}
else if (w <= 22101)
{
return 43;
}
else if (w <= 23230)
{
return 44;
}
else if (w <= 24402)
{
return 45;
}
else if (w <= 25618)
{
return 46;
}
else if (w <= 26881)
{
return 47;
}
else if (w <= 28193)
{
return 48;
}
else if (w <= 29557)
{
return 49;
}
else if (w <= 30975)
{
return 50;
}
else if (w <= 32450)
{
return 51;
}
else if (w <= 33986)
{
return 52;
}
else if (w <= 35586)
{
return 53;
}
else if (w <= 37253)
{
return 54;
}
else if (w <= 38992)
{
return 55;
}
else if (w <= 40808)
{
return 56;
}
else if (w <= 42707)
{
return 57;
}
else if (w <= 44694)
{
return 58;
}
else if (w <= 46776)
{
return 59;
}
else if (w <= 48961)
{
return 60;
}
else if (w <= 51258)
{
return 61;
}
else if (w <= 53667)
{
return 62;
}
else if (w <= 56230)
{
return 63;
}
else if (w <= 58932)
{
return 64;
}
else if (w <= 61799)
{
return 65;
}
else if (w <= 64851)
{
return 66;
}
else if (w <= 68113)
{
return 67;
}
else if (w <= 71617)
{
return 68;
}
else if (w <= 75401)
{
return 69;
}
else if (w <= 79517)
{
return 70;
}
else if (w <= 84035)
{
return 71;
}
else if (w <= 89053)
{
return 72;
}
else if (w <= 94717)
{
return 73;
}
else
{
return 73;
}
}
double
TcpHighSpeed::TableLookupB (uint32_t w)
{
if (w <= 38)
{
return 0.50;
}
else if (w <= 118)
{
return 0.44;
}
else if (w <= 221)
{
return 0.41;
}
else if (w <= 347)
{
return 0.38;
}
else if (w <= 495)
{
return 0.37;
}
else if (w <= 663)
{
return 0.35;
}
else if (w <= 851)
{
return 0.34;
}
else if (w <= 1058)
{
return 0.33;
}
else if (w <= 1284)
{
return 0.32;
}
else if (w <= 1529)
{
return 0.31;
}
else if (w <= 1793)
{
return 0.30;
}
else if (w <= 2076)
{
return 0.29;
}
else if (w <= 2378)
{
return 0.28;
}
else if (w <= 2699)
{
return 0.28;
}
else if (w <= 3039)
{
return 0.27;
}
else if (w <= 3399)
{
return 0.27;
}
else if (w <= 3778)
{
return 0.26;
}
else if (w <= 4177)
{
return 0.26;
}
else if (w <= 4596)
{
return 0.25;
}
else if (w <= 5036)
{
return 0.25;
}
else if (w <= 5497)
{
return 0.24;
}
else if (w <= 5979)
{
return 0.24;
}
else if (w <= 6483)
{
return 0.23;
}
else if (w <= 7009)
{
return 0.23;
}
else if (w <= 7558)
{
return 0.22;
}
else if (w <= 8130)
{
return 0.22;
}
else if (w <= 8726)
{
return 0.22;
}
else if (w <= 9346)
{
return 0.21;
}
else if (w <= 9991)
{
return 0.21;
}
else if (w <= 10661)
{
return 0.21;
}
else if (w <= 11358)
{
return 0.20;
}
else if (w <= 12082)
{
return 0.20;
}
else if (w <= 12834)
{
return 0.20;
}
else if (w <= 13614)
{
return 0.19;
}
else if (w <= 14424)
{
return 0.19;
}
else if (w <= 15265)
{
return 0.19;
}
else if (w <= 16137)
{
return 0.19;
}
else if (w <= 17042)
{
return 0.18;
}
else if (w <= 17981)
{
return 0.18;
}
else if (w <= 18955)
{
return 0.18;
}
else if (w <= 19965)
{
return 0.17;
}
else if (w <= 21013)
{
return 0.17;
}
else if (w <= 22101)
{
return 0.17;
}
else if (w <= 23230)
{
return 0.17;
}
else if (w <= 24402)
{
return 0.16;
}
else if (w <= 25618)
{
return 0.16;
}
else if (w <= 26881)
{
return 0.16;
}
else if (w <= 28193)
{
return 0.16;
}
else if (w <= 29557)
{
return 0.15;
}
else if (w <= 30975)
{
return 0.15;
}
else if (w <= 32450)
{
return 0.15;
}
else if (w <= 33986)
{
return 0.15;
}
else if (w <= 35586)
{
return 0.14;
}
else if (w <= 37253)
{
return 0.14;
}
else if (w <= 38992)
{
return 0.14;
}
else if (w <= 40808)
{
return 0.14;
}
else if (w <= 42707)
{
return 0.13;
}
else if (w <= 44694)
{
return 0.13;
}
else if (w <= 46776)
{
return 0.13;
}
else if (w <= 48961)
{
return 0.13;
}
else if (w <= 51258)
{
return 0.13;
}
else if (w <= 53667)
{
return 0.12;
}
else if (w <= 56230)
{
return 0.12;
}
else if (w <= 58932)
{
return 0.12;
}
else if (w <= 61799)
{
return 0.12;
}
else if (w <= 64851)
{
return 0.11;
}
else if (w <= 68113)
{
return 0.11;
}
else if (w <= 71617)
{
return 0.11;
}
else if (w <= 75401)
{
return 0.10;
}
else if (w <= 79517)
{
return 0.10;
}
else if (w <= 84035)
{
return 0.10;
}
else if (w <= 89053)
{
return 0.10;
}
else if (w <= 94717)
{
return 0.09;
}
else
{
return 0.09;
}
}
} // namespace ns3

View File

@@ -0,0 +1,102 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 Natale Patriciello, <natale.patriciello@gmail.com>
*
* 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
*
*/
#ifndef TCPHIGHSPEED_H
#define TCPHIGHSPEED_H
#include "ns3/tcp-congestion-ops.h"
namespace ns3 {
/**
* \ingroup tcp
*
* \brief An implementation of TCP HighSpeed
*
* TCP HighSpeed is designed for high-capacity channels or, in general, for
* TCP connections with large congestion windows.
* Conceptually, with respect to the standard TCP, HighSpeed makes the
* cWnd grow faster during the probing phases and accelerates the
* cWnd recovery from losses.
* This behavior is executed only when the window grows beyond a
* certain threshold, which allows TCP Highspeed to be friendly with standard
* TCP in environments with heavy congestion, without introducing new dangers
* of congestion collapse.
* At the core of TCP HighSpeed there are two functions, a(w) and b(w), which respectively
* specify the cWnd growth addendum and the cWnd reduction factor when
* given an actual cWnd value w.
*
* More information: http://dl.acm.org/citation.cfm?id=2756518
*/
class TcpHighSpeed : public TcpNewReno
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
/**
* Create an unbound tcp socket.
*/
TcpHighSpeed (void);
/**
* \brief Copy constructor
* \param sock the object to copy
*/
TcpHighSpeed (const TcpHighSpeed& sock);
virtual ~TcpHighSpeed (void);
virtual std::string GetName () const;
virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb,
uint32_t bytesInFlight);
virtual Ptr<TcpCongestionOps> Fork ();
/**
* \brief Lookup table for the coefficent a (from RFC 3649)
*
* \param w Window value (in packets)
*
* \return the coefficent a
*/
static uint32_t TableLookupA (uint32_t w);
/**
* \brief Lookup table for the coefficent b (from RFC 3649)
*
* \param w Window value (in packets)
*
* \return the coefficent b
*/
static double TableLookupB (uint32_t w);
protected:
virtual void CongestionAvoidance (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked);
private:
uint32_t m_ackCnt; //!< Number of received ACK, corrected with the coefficent a
};
} // namespace ns3
#endif // TCPHIGHSPEED_H

View File

@@ -145,6 +145,7 @@ def build(bld):
'model/ipv6-option-demux.cc',
'model/icmpv6-l4-protocol.cc',
'model/tcp-socket-base.cc',
'model/tcp-highspeed.cc',
'model/tcp-congestion-ops.cc',
'model/tcp-westwood.cc',
'model/tcp-rx-buffer.cc',
@@ -327,6 +328,7 @@ def build(bld):
'helper/ipv6-interface-container.h',
'helper/ipv6-routing-helper.h',
'model/ipv6-address-generator.h',
'model/tcp-highspeed.h',
'model/tcp-congestion-ops.h',
'model/tcp-westwood.h',
'model/tcp-socket-base.h',