internet: Added TCP Bic
This commit is contained in:
@@ -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
|
||||
----------
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
++++++++++
|
||||
|
||||
|
||||
275
src/internet/model/tcp-bic.cc
Normal file
275
src/internet/model/tcp-bic.cc
Normal 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
|
||||
123
src/internet/model/tcp-bic.h
Normal file
123
src/internet/model/tcp-bic.h
Normal 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
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user