internet: Added TCP Bic

This commit is contained in:
Natale Patriciello
2016-04-18 17:21:45 +02:00
parent e1d2bd27e1
commit 5aaeb0103c
6 changed files with 430 additions and 1 deletions

View File

@@ -25,6 +25,7 @@ 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
- (internet) Added TCP Bic congestion control algorithm
Bugs fixed
----------

View File

@@ -179,7 +179,7 @@ int main (int argc, char *argv[])
CommandLine cmd;
cmd.AddValue ("transport_prot", "Transport protocol to use: TcpNewReno, "
"TcpHybla, TcpHighSpeed, TcpVegas, TcpScalable, TcpVeno, "
"TcpWestwood, TcpWestwoodPlus ", transport_prot);
"TcpBic, 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);
@@ -250,6 +250,10 @@ int main (int argc, char *argv[])
{
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpVeno::GetTypeId ()));
}
else if (transport_prot.compare ("TcpBic") == 0)
{
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpBic::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 ()));
@@ -368,6 +372,7 @@ int main (int argc, char *argv[])
|| transport_prot.compare ("TcpHighSpeed") == 0
|| transport_prot.compare ("TcpVegas") == 0
|| transport_prot.compare ("TcpVeno") == 0
|| transport_prot.compare ("TcpBic") == 0
|| transport_prot.compare ("TcpScalable") == 0)
{
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (tcp_adu_size));

View File

@@ -306,6 +306,29 @@ rate as in Reno.
More informations at: http://dx.doi.org/10.1109/JSAC.2002.807336
Bic
^^^
In TCP Bic the congestion control problem is viewed as a search
problem. Taking as a starting point the current window value
and as a target point the last maximum window value
(i.e. the cWnd value just before the loss event) a binary search
technique can be used to update the cWnd value at the midpoint between
the two, directly or using an additive increase strategy if the distance from
the current window is too large.
This way, assuming a no-loss period, the congestion window logarithmically
approaches the maximum value of cWnd until the difference between it and cWnd
falls below a preset threshold. After reaching such a value (or the maximum
window is unknown, i.e. the binary search does not start at all) the algorithm
switches to probing the new maximum window with a 'slow start' strategy.
If a loss occur in either these phases, the current window (before the loss)
can be treated as the new maximum, and the reduced (with a multiplicative
decrease factor Beta) window size can be used as the new minimum.
More informations at: http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1354672
Validation
++++++++++

View File

@@ -0,0 +1,275 @@
/* -*- 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-bic.h"
#include "ns3/log.h"
#include "ns3/tcp-socket-base.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("TcpBic");
NS_OBJECT_ENSURE_REGISTERED (TcpBic);
TypeId
TcpBic::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::TcpBic")
.SetParent<TcpCongestionOps> ()
.AddConstructor<TcpBic> ()
.SetGroupName ("Internet")
.AddAttribute ("FastConvergence", "Turn on/off fast convergence.",
BooleanValue (true),
MakeBooleanAccessor (&TcpBic::m_fastConvergence),
MakeBooleanChecker ())
.AddAttribute ("Beta", "Beta for multiplicative decrease",
DoubleValue (0.8),
MakeDoubleAccessor (&TcpBic::m_beta),
MakeDoubleChecker <double> (0.0))
.AddAttribute ("MaxIncr", "Limit on increment allowed during binary search",
UintegerValue (16),
MakeUintegerAccessor (&TcpBic::m_maxIncr),
MakeUintegerChecker <uint32_t> (1))
.AddAttribute ("LowWnd", "Threshold window size (in segments) for engaging BIC response",
UintegerValue (14),
MakeUintegerAccessor (&TcpBic::m_lowWnd),
MakeUintegerChecker <uint32_t> ())
.AddAttribute ("SmoothPart", "Number of RTT needed to approach cWnd_max from "
"cWnd_max-BinarySearchCoefficient. It can be viewed as the gradient "
"of the slow start AIM phase: less this value is, "
"more steep the increment will be.",
IntegerValue (5),
MakeIntegerAccessor (&TcpBic::m_smoothPart),
MakeIntegerChecker <int> (1))
.AddAttribute ("BinarySearchCoefficient", "Inverse of the coefficient for the "
"binary search. Default 4, as in Linux",
UintegerValue (4),
MakeUintegerAccessor (&TcpBic::m_b),
MakeUintegerChecker <uint8_t> (2))
;
return tid;
}
TcpBic::TcpBic ()
: TcpCongestionOps (),
m_cWndCnt (0),
m_lastMaxCwnd (0),
m_lastCwnd (0),
m_epochStart (Time::Min ())
{
NS_LOG_FUNCTION (this);
}
TcpBic::TcpBic (const TcpBic &sock)
: TcpCongestionOps (sock),
m_cWndCnt (sock.m_cWndCnt),
m_lastMaxCwnd (sock.m_lastMaxCwnd),
m_lastCwnd (sock.m_lastCwnd),
m_epochStart (sock.m_epochStart)
{
NS_LOG_FUNCTION (this);
}
void
TcpBic::IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{
NS_LOG_FUNCTION (this << tcb << segmentsAcked);
if (tcb->m_cWnd < tcb->m_ssThresh)
{
tcb->m_cWnd += tcb->m_segmentSize;
segmentsAcked -= 1;
NS_LOG_INFO ("In SlowStart, updated to cwnd " << tcb->m_cWnd <<
" ssthresh " << tcb->m_ssThresh);
}
if (tcb->m_cWnd >= tcb->m_ssThresh && segmentsAcked > 0)
{
m_cWndCnt += segmentsAcked;
uint32_t cnt = Update (tcb);
/* According to the BIC paper and RFC 6356 even once the new cwnd is
* calculated you must compare this to the number of ACKs received since
* the last cwnd update. If not enough ACKs have been received then cwnd
* cannot be updated.
*/
if (m_cWndCnt > cnt)
{
tcb->m_cWnd += tcb->m_segmentSize;
m_cWndCnt = 0;
NS_LOG_INFO ("In CongAvoid, updated to cwnd " << tcb->m_cWnd);
}
else
{
NS_LOG_INFO ("Not enough segments have been ACKed to increment cwnd."
"Until now " << m_cWndCnt);
}
}
}
uint32_t
TcpBic::Update (Ptr<TcpSocketState> tcb)
{
NS_LOG_FUNCTION (this << tcb);
uint32_t segCwnd = tcb->GetCwndInSegments ();
uint32_t cnt;
m_lastCwnd = segCwnd;
if (m_epochStart == Time::Min ())
{
m_epochStart = Simulator::Now (); /* record the beginning of an epoch */
}
if (segCwnd < m_lowWnd)
{
NS_LOG_INFO ("Under lowWnd, compatibility mode. Behaving as NewReno");
cnt = segCwnd;
return cnt;
}
if (segCwnd < m_lastMaxCwnd)
{
double dist = (m_lastMaxCwnd - segCwnd) / m_b;
NS_LOG_INFO ("cWnd = " << segCwnd << " under lastMax, " <<
m_lastMaxCwnd << " and dist=" << dist);
if (dist > m_maxIncr)
{
/* Linear increase */
cnt = segCwnd / m_maxIncr;
NS_LOG_INFO ("Linear increase (maxIncr=" << m_maxIncr << "), cnt=" << cnt);
}
else if (dist <= 1)
{
/* smoothed binary search increase: when our window is really
* close to the last maximum, we parameterize in m_smoothPart the number
* of RTT needed to reach that window.
*/
cnt = (segCwnd * m_smoothPart) / m_b;
NS_LOG_INFO ("Binary search increase (smoothPart=" << m_smoothPart <<
"), cnt=" << cnt);
}
else
{
/* binary search increase */
cnt = segCwnd / dist;
NS_LOG_INFO ("Binary search increase, cnt=" << cnt);
}
}
else
{
NS_LOG_INFO ("cWnd = " << segCwnd << " above last max, " <<
m_lastMaxCwnd);
if (segCwnd < m_lastMaxCwnd + m_b)
{
/* slow start AMD linear increase */
cnt = (segCwnd * m_smoothPart) / m_b;
NS_LOG_INFO ("Slow start AMD, cnt=" << cnt);
}
else if (segCwnd < m_lastMaxCwnd + m_maxIncr * (m_b - 1))
{
/* slow start */
cnt = (segCwnd * (m_b - 1)) / (segCwnd - m_lastMaxCwnd);
NS_LOG_INFO ("Slow start, cnt=" << cnt);
}
else
{
/* linear increase */
cnt = segCwnd / m_maxIncr;
NS_LOG_INFO ("Linear, cnt=" << cnt);
}
}
/* if in slow start or link utilization is very low. Code taken from Linux
* kernel, not sure of the source they take it. Usually, it is not reached,
* since if m_lastMaxCwnd is 0, we are (hopefully) in slow start.
*/
if (m_lastMaxCwnd == 0)
{
if (cnt > 20) /* increase cwnd 5% per RTT */
{
cnt = 20;
}
}
if (cnt == 0)
{
cnt = 1;
}
return cnt;
}
std::string
TcpBic::GetName () const
{
return "TcpBic";
}
uint32_t
TcpBic::GetSsThresh (Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight)
{
NS_LOG_FUNCTION (this);
uint32_t segCwnd = tcb->GetCwndInSegments ();
uint32_t ssThresh = 0;
m_epochStart = Time::Min ();
/* Wmax and fast convergence */
if (segCwnd < m_lastMaxCwnd && m_fastConvergence)
{
NS_LOG_INFO ("Fast Convergence. Last max cwnd: " << m_lastMaxCwnd <<
" updated to " << (uint32_t) m_beta * segCwnd);
m_lastMaxCwnd = m_beta * segCwnd;
}
else
{
NS_LOG_INFO ("Last max cwnd: " << m_lastMaxCwnd << " updated to " <<
segCwnd);
m_lastMaxCwnd = segCwnd;
}
if (segCwnd < m_lowWnd)
{
ssThresh = std::max (2 * tcb->m_segmentSize, bytesInFlight / 2);
NS_LOG_INFO ("Less than lowWindow, ssTh= " << ssThresh);
}
else
{
ssThresh = std::max (segCwnd * m_beta, 2.0) * tcb->m_segmentSize;
NS_LOG_INFO ("More than lowWindow, ssTh= " << ssThresh);
}
return ssThresh;
}
Ptr<TcpCongestionOps>
TcpBic::Fork (void)
{
return CopyObject<TcpBic> (this);
}
} // namespace ns3

View File

@@ -0,0 +1,123 @@
/* -*- 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 TCPBIC_H
#define TCPBIC_H
#include "ns3/tcp-congestion-ops.h"
#include "ns3/traced-value.h"
namespace ns3 {
/** \brief BIC congestion control algorithm
*
* In TCP Bic the congestion control problem is viewed as a search
* problem. Taking as a starting point the current window value
* and as a target point the last maximum window value
* (i.e. the cWnd value just before the loss event) a binary search
* technique can be used to update the cWnd value at the midpoint between
* the two, directly or using an additive increase strategy if the distance from
* the current window is too large.
*
* This way, assuming a no-loss period, the congestion window logarithmically
* approaches the maximum value of cWnd until the difference between it and cWnd
* falls below a preset threshold. After reaching such a value (or the maximum
* window is unknown, i.e. the binary search does not start at all) the algorithm
* switches to probing the new maximum window with a 'slow start' strategy.
*
* If a loss occur in either these phases, the current window (before the loss)
* can be treated as the new maximum, and the reduced (with a multiplicative
* decrease factor Beta) window size can be used as the new minimum.
*
* To maintain the performance of TCP Bic as close as possible with the Linux
* implementation, and at the same time maintain the friendliness with other TCP
* flavors, the cWnd is increased only after a certain number of ACKs
* are received, following RFC 6356. After the slow start phase, and after each
* new ACK, a value is calculated by the method Update. This number
* (m_cnt in the code) represents the ACK packets that should be received
* before increasing the cWnd by one segment. After a trivial check on the
* arrived ACKs (represented by m_cWndCnt in the code), the
* cWnd can be increased and m_cWndCnt can be set to zero, or
* otherwise m_cWndCnt can be increased by one and the
* cWnd can be left untouched.
*
* The binary search on the cWnd size space is done by varying the returned
* cnt, depending on the internal state of the class (e.g. the last maximum
* and the current cWnd size).
*
* The reference paper for BIC can be found in:
* http://an.kaist.ac.kr/courses/2006/cs540/reading/bic-tcp.pdf
*
* This model has a number of configurable parameters that are exposed as
* attributes of the TcpBic TypeId. This model also exports trace sources,
* for tracking the congestion window, slow start threshold, and the internal
* state of the protocol.
*
* More information on this implementation: http://dl.acm.org/citation.cfm?id=2756518
*/
class TcpBic : public TcpCongestionOps
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
/**
* \brief Constructor
*/
TcpBic ();
TcpBic (const TcpBic &sock);
virtual std::string GetName () const;
virtual void IncreaseWindow (Ptr<TcpSocketState> tcb,
uint32_t segmentsAcked);
virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb,
uint32_t bytesInFlight);
virtual Ptr<TcpCongestionOps> Fork ();
protected:
/**
* \brief Bic window update after a new ack received
*/
virtual uint32_t Update (Ptr<TcpSocketState> tcb);
private:
friend class TcpBicIncrementTest;
friend class TcpBicDecrementTest;
// User parameters
bool m_fastConvergence; //!< Enable or disable fast convergence algorithm
double m_beta; //!< Beta for cubic multiplicative increase
uint32_t m_maxIncr; //!< Maximum window increment
uint32_t m_lowWnd; //!< Lower bound on congestion window
int m_smoothPart; //!< Number of RTT needed to reach Wmax from Wmax-B
// Bic parameters
uint32_t m_cWndCnt; //!< cWnd integer-to-float counter
uint32_t m_lastMaxCwnd; //!< Last maximum cWnd
uint32_t m_lastCwnd; //!< Last cWnd
Time m_epochStart; //!< Beginning of an epoch
uint8_t m_b; //!< Binary search coefficient
};
} // namespace ns3
#endif // TCPBIC_H

View File

@@ -152,6 +152,7 @@ def build(bld):
'model/tcp-westwood.cc',
'model/tcp-scalable.cc',
'model/tcp-veno.cc',
'model/tcp-bic.cc',
'model/tcp-rx-buffer.cc',
'model/tcp-tx-buffer.cc',
'model/tcp-option.cc',
@@ -361,6 +362,7 @@ def build(bld):
'model/tcp-westwood.h',
'model/tcp-scalable.h',
'model/tcp-veno.h',
'model/tcp-bic.h',
'model/tcp-socket-base.h',
'model/tcp-tx-buffer.h',
'model/tcp-rx-buffer.h',