tcp: Added BBR Congestion control
This commit is contained in:
committed by
Tom Henderson
parent
b8ba1b70cb
commit
86755f4175
674
src/internet/model/tcp-bbr.cc
Normal file
674
src/internet/model/tcp-bbr.cc
Normal file
@@ -0,0 +1,674 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2018 NITK Surathkal
|
||||
*
|
||||
* 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: Vivek Jain <jain.vivek.anand@gmail.com>
|
||||
* Viyom Mittal <viyommittal@gmail.com>
|
||||
* Mohit P. Tahiliani <tahiliani@nitk.edu.in>
|
||||
*/
|
||||
|
||||
#include "tcp-bbr.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/tcp-socket-base.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpBbr");
|
||||
NS_OBJECT_ENSURE_REGISTERED (TcpBbr);
|
||||
|
||||
const double TcpBbr::PACING_GAIN_CYCLE [] = {5.0 / 4, 3.0 / 4, 1, 1, 1, 1, 1, 1};
|
||||
|
||||
TypeId
|
||||
TcpBbr::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::TcpBbr")
|
||||
.SetParent<TcpCongestionOps> ()
|
||||
.AddConstructor<TcpBbr> ()
|
||||
.SetGroupName ("Internet")
|
||||
.AddAttribute ("HighGain",
|
||||
"Value of high gain",
|
||||
DoubleValue (2.89),
|
||||
MakeDoubleAccessor (&TcpBbr::m_highGain),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("BwWindowLength",
|
||||
"Length of bandwidth windowed filter",
|
||||
UintegerValue (10),
|
||||
MakeUintegerAccessor (&TcpBbr::m_bandwidthWindowLength),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("RttWindowLength",
|
||||
"Length of bandwidth windowed filter",
|
||||
TimeValue (Seconds (10)),
|
||||
MakeTimeAccessor (&TcpBbr::m_rtPropFilterLen),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("ProbeRttDuration",
|
||||
"Length of bandwidth windowed filter",
|
||||
TimeValue (MilliSeconds (200)),
|
||||
MakeTimeAccessor (&TcpBbr::m_probeRttDuration),
|
||||
MakeTimeChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TcpBbr::TcpBbr ()
|
||||
: TcpCongestionOps ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_uv = CreateObject<UniformRandomVariable> ();
|
||||
}
|
||||
|
||||
TcpBbr::TcpBbr (const TcpBbr &sock)
|
||||
: TcpCongestionOps (sock),
|
||||
m_bandwidthWindowLength (sock.m_bandwidthWindowLength),
|
||||
m_pacingGain (sock.m_pacingGain),
|
||||
m_cWndGain (sock.m_cWndGain),
|
||||
m_highGain (sock.m_highGain),
|
||||
m_isPipeFilled (sock.m_isPipeFilled),
|
||||
m_minPipeCwnd (sock.m_minPipeCwnd),
|
||||
m_roundCount (sock.m_roundCount),
|
||||
m_roundStart (sock.m_roundStart),
|
||||
m_nextRoundDelivered (sock.m_nextRoundDelivered),
|
||||
m_probeRttDuration (sock.m_probeRttDuration),
|
||||
m_probeRtPropStamp (sock.m_probeRtPropStamp),
|
||||
m_probeRttDoneStamp (sock.m_probeRttDoneStamp),
|
||||
m_probeRttRoundDone (sock.m_probeRttRoundDone),
|
||||
m_packetConservation (sock.m_packetConservation),
|
||||
m_priorCwnd (sock.m_priorCwnd),
|
||||
m_idleRestart (sock.m_idleRestart),
|
||||
m_targetCWnd (sock.m_targetCWnd),
|
||||
m_fullBandwidth (sock.m_fullBandwidth),
|
||||
m_fullBandwidthCount (sock.m_fullBandwidthCount),
|
||||
m_rtProp (Time::Max ()),
|
||||
m_sendQuantum (sock.m_sendQuantum),
|
||||
m_cycleStamp (sock.m_cycleStamp),
|
||||
m_cycleIndex (sock.m_cycleIndex),
|
||||
m_rtPropExpired (sock.m_rtPropExpired),
|
||||
m_rtPropFilterLen (sock.m_rtPropFilterLen),
|
||||
m_rtPropStamp (sock.m_rtPropStamp),
|
||||
m_isInitialized (sock.m_isInitialized),
|
||||
m_delivered (sock.m_delivered),
|
||||
m_appLimited (sock.m_appLimited), // TODO
|
||||
m_txItemDelivered (sock.m_txItemDelivered) // TODO
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_uv = CreateObject<UniformRandomVariable> ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
TcpBbr::AssignStreams (int64_t stream)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << stream);
|
||||
m_uv->SetStream (stream);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::InitRoundCounting ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_nextRoundDelivered = 0;
|
||||
m_roundStart = false;
|
||||
m_roundCount = 0;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::InitFullPipe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_isPipeFilled = false;
|
||||
m_fullBandwidth = 0;
|
||||
m_fullBandwidthCount = 0;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::InitPacingRate (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
|
||||
if (!tcb->m_pacing)
|
||||
{
|
||||
NS_LOG_WARN ("BBR must use pacing");
|
||||
tcb->m_pacing = true;
|
||||
}
|
||||
Time rtt = tcb->m_lastRtt != Time::Max () ? tcb->m_lastRtt.Get () : MilliSeconds (1);
|
||||
DataRate nominalBandwidth (tcb->m_initialCWnd * tcb->m_segmentSize * 8 / rtt.GetSeconds ());
|
||||
tcb->m_currentPacingRate = DataRate (m_pacingGain * nominalBandwidth.GetBitRate ());
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::EnterStartup ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
SetBbrState (BbrMode_t::BBR_STARTUP);
|
||||
m_pacingGain = m_highGain;
|
||||
m_cWndGain = m_highGain;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::HandleRestartFromIdle (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
if (tcb->m_bytesInFlight.Get () == 0U && rs.m_isAppLimited)
|
||||
{
|
||||
m_idleRestart = true;
|
||||
if (m_state == BbrMode_t::BBR_PROBE_BW)
|
||||
{
|
||||
SetPacingRate (tcb, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::SetPacingRate (Ptr<TcpSocketState> tcb, double gain)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << gain);
|
||||
DataRate rate (gain * m_maxBwFilter.GetBest ().GetBitRate ());
|
||||
rate = std::min (rate, tcb->m_maxPacingRate);
|
||||
if (m_isPipeFilled || rate > tcb->m_currentPacingRate)
|
||||
{
|
||||
tcb->m_currentPacingRate = rate;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpBbr::InFlight (Ptr<TcpSocketState> tcb, double gain)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << gain);
|
||||
if (m_rtProp == Time::Max ())
|
||||
{
|
||||
return tcb->m_initialCWnd * tcb->m_segmentSize;
|
||||
}
|
||||
double quanta = 3 * m_sendQuantum;
|
||||
double estimatedBdp = m_maxBwFilter.GetBest () * m_rtProp / 8.0;
|
||||
return gain * estimatedBdp + quanta;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::AdvanceCyclePhase ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_cycleStamp = Simulator::Now ();
|
||||
m_cycleIndex = (m_cycleIndex + 1) % GAIN_CYCLE_LENGTH;
|
||||
m_pacingGain = PACING_GAIN_CYCLE [m_cycleIndex];
|
||||
}
|
||||
|
||||
bool
|
||||
TcpBbr::IsNextCyclePhase (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
bool isFullLength = (Simulator::Now () - m_cycleStamp) > m_rtProp;
|
||||
if (m_pacingGain == 1)
|
||||
{
|
||||
return isFullLength;
|
||||
}
|
||||
else if (m_pacingGain > 1)
|
||||
{
|
||||
return isFullLength && (rs.m_bytesLoss > 0 || rs.m_priorInFlight >= InFlight (tcb, m_pacingGain));
|
||||
}
|
||||
else
|
||||
{
|
||||
return isFullLength || rs.m_priorInFlight <= InFlight (tcb, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::CheckCyclePhase (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
if (m_state == BbrMode_t::BBR_PROBE_BW && IsNextCyclePhase (tcb, rs))
|
||||
{
|
||||
AdvanceCyclePhase ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::CheckFullPipe (const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << rs);
|
||||
if (m_isPipeFilled || !m_roundStart || rs.m_isAppLimited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if Bottleneck bandwidth is still growing*/
|
||||
if (m_maxBwFilter.GetBest ().GetBitRate () >= m_fullBandwidth.GetBitRate () * 1.25)
|
||||
{
|
||||
m_fullBandwidth = m_maxBwFilter.GetBest ();
|
||||
m_fullBandwidthCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_fullBandwidthCount++;
|
||||
if (m_fullBandwidthCount >= 3)
|
||||
{
|
||||
NS_LOG_DEBUG ("Pipe filled");
|
||||
m_isPipeFilled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::EnterDrain ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
SetBbrState (BbrMode_t::BBR_DRAIN);
|
||||
m_pacingGain = 1.0 / m_highGain;
|
||||
m_cWndGain = m_highGain;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::EnterProbeBW ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
SetBbrState (BbrMode_t::BBR_PROBE_BW);
|
||||
m_pacingGain = 1;
|
||||
m_cWndGain = 2;
|
||||
m_cycleIndex = GAIN_CYCLE_LENGTH - 1 - (int) m_uv->GetValue (0, 6);
|
||||
AdvanceCyclePhase ();
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::CheckDrain (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
if (m_state == BbrMode_t::BBR_STARTUP && m_isPipeFilled)
|
||||
{
|
||||
EnterDrain ();
|
||||
}
|
||||
|
||||
if (m_state == BbrMode_t::BBR_DRAIN && tcb->m_bytesInFlight <= InFlight (tcb, 1))
|
||||
{
|
||||
EnterProbeBW ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::UpdateRTprop (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
m_rtPropExpired = Simulator::Now () > (m_rtPropStamp + m_rtPropFilterLen);
|
||||
if (tcb->m_lastRtt >= Seconds (0) && (tcb->m_lastRtt <= m_rtProp || m_rtPropExpired))
|
||||
{
|
||||
m_rtProp = tcb->m_lastRtt;
|
||||
m_rtPropStamp = Simulator::Now ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::EnterProbeRTT ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
SetBbrState (BbrMode_t::BBR_PROBE_RTT);
|
||||
m_pacingGain = 1;
|
||||
m_cWndGain = 1;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::SaveCwnd (Ptr<const TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
if (tcb->m_congState != TcpSocketState::CA_RECOVERY && m_state != BbrMode_t::BBR_PROBE_RTT)
|
||||
{
|
||||
m_priorCwnd = tcb->m_cWnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_priorCwnd = std::max (m_priorCwnd, tcb->m_cWnd.Get ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::RestoreCwnd (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
tcb->m_cWnd = std::max (m_priorCwnd, tcb->m_cWnd.Get ());
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::ExitProbeRTT ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_isPipeFilled)
|
||||
{
|
||||
EnterProbeBW ();
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterStartup ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::HandleProbeRTT (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
m_appLimited = (m_delivered + tcb->m_bytesInFlight.Get ()) ? : 1;
|
||||
|
||||
if (m_probeRttDoneStamp == Seconds (0) && tcb->m_bytesInFlight <= m_minPipeCwnd)
|
||||
{
|
||||
m_probeRttDoneStamp = Simulator::Now () + m_probeRttDuration;
|
||||
m_probeRttRoundDone = false;
|
||||
m_nextRoundDelivered = m_delivered;
|
||||
}
|
||||
else if (m_probeRttDoneStamp != Seconds (0))
|
||||
{
|
||||
if (m_roundStart)
|
||||
{
|
||||
m_probeRttRoundDone = true;
|
||||
}
|
||||
if (m_probeRttRoundDone && Simulator::Now () > m_probeRttDoneStamp)
|
||||
{
|
||||
m_rtPropStamp = Simulator::Now ();
|
||||
RestoreCwnd (tcb);
|
||||
ExitProbeRTT ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::CheckProbeRTT (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
if (m_state != BbrMode_t::BBR_PROBE_RTT && m_rtPropExpired && !m_idleRestart)
|
||||
{
|
||||
EnterProbeRTT ();
|
||||
SaveCwnd (tcb);
|
||||
m_probeRttDoneStamp = Seconds (0);
|
||||
}
|
||||
|
||||
if (m_state == BbrMode_t::BBR_PROBE_RTT)
|
||||
{
|
||||
HandleProbeRTT (tcb);
|
||||
}
|
||||
|
||||
m_idleRestart = false;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::SetSendQuantum (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
m_sendQuantum = 1 * tcb->m_segmentSize;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::UpdateTargetCwnd (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
m_targetCWnd = InFlight (tcb, m_cWndGain);
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::ModulateCwndForRecovery (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
if ( rs.m_bytesLoss > 0)
|
||||
{
|
||||
tcb->m_cWnd = std::max ((int) tcb->m_cWnd.Get () - (int) rs.m_bytesLoss, (int) tcb->m_segmentSize);
|
||||
}
|
||||
|
||||
if (m_packetConservation)
|
||||
{
|
||||
tcb->m_cWnd = std::max (tcb->m_cWnd.Get (), tcb->m_bytesInFlight.Get () + rs.m_ackedSacked);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::ModulateCwndForProbeRTT (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
if (m_state == BbrMode_t::BBR_PROBE_RTT)
|
||||
{
|
||||
tcb->m_cWnd = std::min (tcb->m_cWnd.Get (), m_minPipeCwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::SetCwnd (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
UpdateTargetCwnd (tcb);
|
||||
|
||||
if (tcb->m_congState == TcpSocketState::CA_RECOVERY)
|
||||
{
|
||||
ModulateCwndForRecovery (tcb, rs);
|
||||
}
|
||||
|
||||
if (!m_packetConservation)
|
||||
{
|
||||
if (m_isPipeFilled)
|
||||
{
|
||||
tcb->m_cWnd = std::min (tcb->m_cWnd.Get () + (uint32_t) rs.m_ackedSacked, m_targetCWnd);
|
||||
}
|
||||
else if (tcb->m_cWnd < m_targetCWnd || m_delivered < tcb->m_initialCWnd * tcb->m_segmentSize)
|
||||
{
|
||||
tcb->m_cWnd = tcb->m_cWnd.Get () + rs.m_ackedSacked;
|
||||
}
|
||||
tcb->m_cWnd = std::max (tcb->m_cWnd.Get (), m_minPipeCwnd);
|
||||
}
|
||||
ModulateCwndForProbeRTT (tcb);
|
||||
if (tcb->m_congState == TcpSocketState::CA_RECOVERY)
|
||||
{
|
||||
m_packetConservation = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::UpdateRound (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
if (m_txItemDelivered >= m_nextRoundDelivered)
|
||||
{
|
||||
m_nextRoundDelivered = m_delivered;
|
||||
m_roundCount++;
|
||||
m_roundStart = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_roundStart = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::UpdateBtlBw (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
if (rs.m_deliveryRate == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateRound (tcb, rs);
|
||||
|
||||
if (rs.m_deliveryRate >= m_maxBwFilter.GetBest () || !rs.m_isAppLimited)
|
||||
{
|
||||
m_maxBwFilter.Update (rs.m_deliveryRate, m_roundCount);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::UpdateModelAndState (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
UpdateBtlBw (tcb, rs);
|
||||
CheckCyclePhase (tcb, rs);
|
||||
CheckFullPipe (rs);
|
||||
CheckDrain (tcb);
|
||||
UpdateRTprop (tcb);
|
||||
CheckProbeRTT (tcb);
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::UpdateControlParameters (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
SetPacingRate (tcb, m_pacingGain);
|
||||
SetSendQuantum (tcb);
|
||||
SetCwnd (tcb, rs);
|
||||
}
|
||||
|
||||
std::string
|
||||
TcpBbr::WhichState (BbrMode_t mode) const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case 0:
|
||||
return "BBR_STARTUP";
|
||||
case 1:
|
||||
return "BBR_DRAIN";
|
||||
case 2:
|
||||
return "BBR_PROBE_BW";
|
||||
case 3:
|
||||
return "BBR_PROBE_RTT";
|
||||
}
|
||||
NS_ASSERT (false);
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::SetBbrState (BbrMode_t mode)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << mode);
|
||||
NS_LOG_DEBUG (Simulator::Now () << " Changing from " << WhichState (m_state) << " to " << WhichState (mode));
|
||||
m_state = mode;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpBbr::GetBbrState ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_state;
|
||||
}
|
||||
|
||||
double
|
||||
TcpBbr::GetCwndGain ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_cWndGain;
|
||||
}
|
||||
|
||||
double
|
||||
TcpBbr::GetPacingGain ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_pacingGain;
|
||||
}
|
||||
|
||||
std::string
|
||||
TcpBbr::GetName () const
|
||||
{
|
||||
return "TcpBbr";
|
||||
}
|
||||
|
||||
bool
|
||||
TcpBbr::HasCongControl () const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::CongControl(Ptr<TcpSocketState> tcb,
|
||||
const TcpRateOps::TcpRateConnection &rc,
|
||||
const TcpRateOps::TcpRateSample &rs)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << rs);
|
||||
m_delivered = rc.m_delivered;
|
||||
m_txItemDelivered = rc.m_txItemDelivered;
|
||||
UpdateModelAndState (tcb, rs);
|
||||
UpdateControlParameters (tcb, rs);
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::CongestionStateSet (Ptr<TcpSocketState> tcb,
|
||||
const TcpSocketState::TcpCongState_t newState)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << newState);
|
||||
if (newState == TcpSocketState::CA_OPEN && !m_isInitialized)
|
||||
{
|
||||
NS_LOG_DEBUG ("CongestionStateSet triggered to CA_OPEN :: " << newState);
|
||||
m_rtProp = tcb->m_lastRtt.Get () != Time::Max () ? tcb->m_lastRtt.Get () : Time::Max ();
|
||||
m_rtPropStamp = Simulator::Now ();
|
||||
m_priorCwnd = tcb->m_initialCWnd * tcb->m_segmentSize;
|
||||
m_targetCWnd = tcb->m_initialCWnd * tcb->m_segmentSize;
|
||||
m_minPipeCwnd = 4 * tcb->m_segmentSize;
|
||||
m_sendQuantum = 1 * tcb->m_segmentSize;
|
||||
m_maxBwFilter = MaxBandwidthFilter_t (m_bandwidthWindowLength,
|
||||
DataRate (tcb->m_initialCWnd * tcb->m_segmentSize * 8 / m_rtProp.GetSeconds ())
|
||||
, 0);
|
||||
InitRoundCounting ();
|
||||
InitFullPipe ();
|
||||
InitPacingRate (tcb);
|
||||
EnterStartup ();
|
||||
m_isInitialized = true;
|
||||
}
|
||||
else if (newState == TcpSocketState::CA_LOSS)
|
||||
{
|
||||
NS_LOG_DEBUG ("CongestionStateSet triggered to CA_LOSS :: " << newState);
|
||||
SaveCwnd (tcb);
|
||||
m_roundStart = true;
|
||||
}
|
||||
else if (newState == TcpSocketState::CA_RECOVERY)
|
||||
{
|
||||
NS_LOG_DEBUG ("CongestionStateSet triggered to CA_RECOVERY :: " << newState);
|
||||
SaveCwnd (tcb);
|
||||
tcb->m_cWnd = tcb->m_bytesInFlight.Get () + std::max (tcb->m_lastAckedSackedBytes, tcb->m_segmentSize);
|
||||
m_packetConservation = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TcpBbr::CwndEvent (Ptr<TcpSocketState> tcb,
|
||||
const TcpSocketState::TcpCAEvent_t event)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << event);
|
||||
if (event == TcpSocketState::CA_EVENT_COMPLETE_CWR)
|
||||
{
|
||||
NS_LOG_DEBUG ("CwndEvent triggered to CA_EVENT_COMPLETE_CWR :: " << event);
|
||||
m_packetConservation = false;
|
||||
RestoreCwnd (tcb);
|
||||
}
|
||||
else if (event == TcpSocketState::CA_EVENT_TX_START)
|
||||
{
|
||||
NS_LOG_DEBUG ("CwndEvent triggered to CA_EVENT_TX_START :: " << event);
|
||||
if (tcb->m_bytesInFlight.Get () == 0 && m_appLimited)
|
||||
{
|
||||
m_idleRestart = true;
|
||||
if (m_state == BbrMode_t::BBR_PROBE_BW && m_appLimited)
|
||||
{
|
||||
SetPacingRate (tcb, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TcpBbr::GetSsThresh (Ptr<const TcpSocketState> tcb, uint32_t bytesInFlight)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb << bytesInFlight);
|
||||
SaveCwnd (tcb);
|
||||
return tcb->m_initialSsThresh;
|
||||
}
|
||||
void
|
||||
TcpBbr::ReduceCwnd (Ptr<TcpSocketState> tcb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tcb);
|
||||
}
|
||||
|
||||
Ptr<TcpCongestionOps>
|
||||
TcpBbr::Fork (void)
|
||||
{
|
||||
return CopyObject<TcpBbr> (this);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
365
src/internet/model/tcp-bbr.h
Normal file
365
src/internet/model/tcp-bbr.h
Normal file
@@ -0,0 +1,365 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2018 NITK Surathkal
|
||||
*
|
||||
* 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: Vivek Jain <jain.vivek.anand@gmail.com>
|
||||
* Viyom Mittal <viyommittal@gmail.com>
|
||||
* Mohit P. Tahiliani <tahiliani@nitk.edu.in>
|
||||
*/
|
||||
|
||||
#ifndef TCPBBR_H
|
||||
#define TCPBBR_H
|
||||
|
||||
#include "ns3/tcp-congestion-ops.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/windowed-filter.h"
|
||||
|
||||
class TcpBbrCheckGainValuesTest;
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class TcpBbr : public TcpCongestionOps
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief The number of phases in the BBR ProbeBW gain cycle.
|
||||
*/
|
||||
static const uint8_t GAIN_CYCLE_LENGTH = 8;
|
||||
|
||||
/**
|
||||
* \brief BBR uses an eight-phase cycle with the given pacing_gain value
|
||||
* in the BBR ProbeBW gain cycle.
|
||||
*/
|
||||
const static double PACING_GAIN_CYCLE [];
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
*/
|
||||
TcpBbr ();
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
* \param sock The socket to copy from.
|
||||
*/
|
||||
TcpBbr (const TcpBbr &sock);
|
||||
|
||||
/* BBR has the following modes for deciding how fast to send: */
|
||||
typedef enum
|
||||
{
|
||||
BBR_STARTUP, /* ramp up sending rate rapidly to fill pipe */
|
||||
BBR_DRAIN, /* drain any queue created during startup */
|
||||
BBR_PROBE_BW, /* discover, share bw: pace around estimated bw */
|
||||
BBR_PROBE_RTT, /* cut inflight to min to probe min_rtt */
|
||||
} BbrMode_t;
|
||||
|
||||
typedef WindowedFilter<DataRate,
|
||||
MaxFilter<DataRate>,
|
||||
uint32_t,
|
||||
uint32_t>
|
||||
MaxBandwidthFilter_t;
|
||||
|
||||
/**
|
||||
* Assign a fixed random variable stream number to the random variables
|
||||
* used by this model. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream first stream index to use
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
virtual int64_t AssignStreams (int64_t stream);
|
||||
|
||||
virtual std::string GetName () const;
|
||||
virtual bool HasCongControl () const;
|
||||
virtual void CongControl (Ptr<TcpSocketState> tcb,
|
||||
const TcpRateOps::TcpRateConnection &rc,
|
||||
const TcpRateOps::TcpRateSample &rs);
|
||||
virtual void CongestionStateSet (Ptr<TcpSocketState> tcb,
|
||||
const TcpSocketState::TcpCongState_t newState);
|
||||
virtual void CwndEvent (Ptr<TcpSocketState> tcb,
|
||||
const TcpSocketState::TcpCAEvent_t event);
|
||||
virtual uint32_t GetSsThresh (Ptr<const TcpSocketState> tcb,
|
||||
uint32_t bytesInFlight);
|
||||
virtual void ReduceCwnd (Ptr<TcpSocketState> tcb);
|
||||
virtual Ptr<TcpCongestionOps> Fork ();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief TcpBbrCheckGainValuesTest friend class (for tests).
|
||||
* \relates TcpBbrCheckGainValuesTest
|
||||
*/
|
||||
friend class TcpBbrCheckGainValuesTest;
|
||||
|
||||
/**
|
||||
* \brief Advances pacing gain using cycle gain algorithm, while in BBR_PROBE_BW state
|
||||
*/
|
||||
void AdvanceCyclePhase ();
|
||||
|
||||
/**
|
||||
* \brief Checks whether to advance pacing gain in BBR_PROBE_BW state,
|
||||
* and if allowed calls AdvanceCyclePhase ()
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void CheckCyclePhase (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Checks whether its time to enter BBR_DRAIN or BBR_PROBE_BW state
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void CheckDrain (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Identifies whether pipe or BDP is already full
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void CheckFullPipe (const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief This method handles the steps related to the ProbeRTT state
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void CheckProbeRTT (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Updates variables specific to BBR_DRAIN state
|
||||
*/
|
||||
void EnterDrain ();
|
||||
|
||||
/**
|
||||
* \brief Updates variables specific to BBR_PROBE_BW state
|
||||
*/
|
||||
void EnterProbeBW ();
|
||||
|
||||
/**
|
||||
* \brief Updates variables specific to BBR_PROBE_RTT state
|
||||
*/
|
||||
void EnterProbeRTT ();
|
||||
|
||||
/**
|
||||
* \brief Updates variables specific to BBR_STARTUP state
|
||||
*/
|
||||
void EnterStartup ();
|
||||
|
||||
/**
|
||||
* \brief Called on exiting from BBR_PROBE_RTT state, it eithers invoke EnterProbeBW () or EnterStartup ()
|
||||
*/
|
||||
void ExitProbeRTT ();
|
||||
|
||||
/**
|
||||
* \brief Gets BBR state.
|
||||
* \return returns BBR state.
|
||||
*/
|
||||
uint32_t GetBbrState ();
|
||||
|
||||
/**
|
||||
* \brief Gets current pacing gain.
|
||||
* \return returns current pacing gain.
|
||||
*/
|
||||
double GetPacingGain ();
|
||||
|
||||
/**
|
||||
* \brief Gets current cwnd gain.
|
||||
* \return returns current cwnd gain.
|
||||
*/
|
||||
double GetCwndGain ();
|
||||
|
||||
/**
|
||||
* \brief Handles the steps for BBR_PROBE_RTT state.
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void HandleProbeRTT (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Updates pacing rate if socket is restarting from idle state.
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void HandleRestartFromIdle (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Estimates the target value for congestion window
|
||||
* \param tcb the socket state.
|
||||
* \param gain cwnd gain
|
||||
*/
|
||||
uint32_t InFlight (Ptr<TcpSocketState> tcb, double gain);
|
||||
|
||||
/**
|
||||
* \brief Intializes the full pipe estimator.
|
||||
*/
|
||||
void InitFullPipe ();
|
||||
|
||||
/**
|
||||
* \brief Intializes the pacing rate.
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void InitPacingRate (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Intializes the round counting related variables.
|
||||
*/
|
||||
void InitRoundCounting ();
|
||||
|
||||
/**
|
||||
* \brief Checks whether to move to next value of pacing gain while in BBR_PROBE_BW.
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
* \returns true if want to move to next value otherwise false.
|
||||
*/
|
||||
bool IsNextCyclePhase (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Modulates congestion window in BBR_PROBE_RTT.
|
||||
* \param tcb the socket state
|
||||
*/
|
||||
void ModulateCwndForProbeRTT (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Modulates congestion window in CA_RECOVERY.
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void ModulateCwndForRecovery (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Helper to restore the last-known good congestion window
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void RestoreCwnd (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Helper to remember the last-known good congestion window or
|
||||
* the latest congestion window unmodulated by loss recovery or ProbeRTT.
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void SaveCwnd (Ptr<const TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Updates congestion window based on the network model.
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void SetCwnd (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Updates pacing rate based on network model.
|
||||
* \param tcb the socket state.
|
||||
* \param gain pacing gain
|
||||
*/
|
||||
void SetPacingRate (Ptr<TcpSocketState> tcb, double gain);
|
||||
|
||||
/**
|
||||
* \brief Updates send quantum based on the network model.
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void SetSendQuantum (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Updates maximum bottleneck.
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void UpdateBtlBw (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Updates control parameters congestion windowm, pacing rate, send quantum.
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void UpdateControlParameters (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Updates BBR network model (Maximum bandwidth and minimum RTT).
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void UpdateModelAndState (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Updates round counting related variables.
|
||||
* \param tcb the socket state.
|
||||
* \param rs rate sample
|
||||
*/
|
||||
void UpdateRound (Ptr<TcpSocketState> tcb, const TcpRateOps::TcpRateSample &rs);
|
||||
|
||||
/**
|
||||
* \brief Updates minimum RTT.
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void UpdateRTprop (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Updates target congestion window.
|
||||
* \param tcb the socket state.
|
||||
*/
|
||||
void UpdateTargetCwnd (Ptr<TcpSocketState> tcb);
|
||||
|
||||
/**
|
||||
* \brief Sets BBR state.
|
||||
* \param state BBR state.
|
||||
*/
|
||||
void SetBbrState (BbrMode_t state);
|
||||
|
||||
/**
|
||||
* \brief Maps mode into string.
|
||||
* \return string translation of mode value.
|
||||
*/
|
||||
std::string WhichState (BbrMode_t state) const;
|
||||
|
||||
private:
|
||||
BbrMode_t m_state {BbrMode_t::BBR_STARTUP}; //!< Current state of BBR state machine
|
||||
MaxBandwidthFilter_t m_maxBwFilter; //!< Maximum bandwidth filter
|
||||
uint32_t m_bandwidthWindowLength {0}; //!< A constant specifying the length of the BBR.BtlBw max filter window, default 10 packet-timed round trips.
|
||||
double m_pacingGain {0}; //!< The dynamic pacing gain factor
|
||||
double m_cWndGain {0}; //!< The dynamic congestion window gain factor
|
||||
double m_highGain {0}; //!< A constant specifying highest gain factor, default is 2.89
|
||||
bool m_isPipeFilled {false}; //!< A boolean that records whether BBR has filled the pipe
|
||||
uint32_t m_minPipeCwnd {0}; //!< The minimal congestion window value BBR tries to target, default 4 Segment size
|
||||
uint32_t m_roundCount {0}; //!< Count of packet-timed round trips
|
||||
bool m_roundStart {false}; //!< A boolean that BBR sets to true once per packet-timed round trip
|
||||
uint32_t m_nextRoundDelivered {0}; //!< Denotes the end of a packet-timed round trip
|
||||
Time m_probeRttDuration {MilliSeconds (200)};//!< A constant specifying the minimum duration for which ProbeRTT state, default 200 millisecs
|
||||
Time m_probeRtPropStamp {Seconds (0)}; //!< The wall clock time at which the current BBR.RTProp sample was obtained.
|
||||
Time m_probeRttDoneStamp {Seconds (0)}; //!< Time to exit from BBR_PROBE_RTT state
|
||||
bool m_probeRttRoundDone {false}; //!< True when it is time to exit BBR_PROBE_RTT
|
||||
bool m_packetConservation {false}; //!<
|
||||
uint32_t m_priorCwnd {0}; //!< The last-known good congestion window
|
||||
bool m_idleRestart {false}; //!< When restarting from idle, set it true
|
||||
uint32_t m_targetCWnd {0}; //!< Target value for congestion window, adapted to the estimated BDP
|
||||
DataRate m_fullBandwidth {0}; //!< Value of full bandwidth recorded
|
||||
uint32_t m_fullBandwidthCount {0}; //!< Count of full bandwidth recorded consistently
|
||||
Time m_rtProp {Time::Max ()}; //!< Estimated two-way round-trip propagation delay of the path, estimated from the windowed minimum recent round-trip delay sample.
|
||||
uint32_t m_sendQuantum {0}; //!< The maximum size of a data aggregate scheduled and transmitted together
|
||||
Time m_cycleStamp {Seconds (0)}; //!< Last time gain cycle updated
|
||||
uint32_t m_cycleIndex {0}; //!< Current index of gain cycle
|
||||
bool m_rtPropExpired {false}; //!< A boolean recording whether the BBR.RTprop has expired
|
||||
Time m_rtPropFilterLen {Seconds (10)}; //!< A constant specifying the length of the RTProp min filter window, default 10 secs.
|
||||
Time m_rtPropStamp {Seconds (0)}; //!< The wall clock time at which the current BBR.RTProp sample was obtained
|
||||
bool m_isInitialized {false}; //!< Set to true after first time initializtion variables
|
||||
Ptr<UniformRandomVariable> m_uv {nullptr}; //!< Uniform Random Variable
|
||||
uint64_t m_delivered {0}; //!< The total amount of data in bytes delivered so far
|
||||
uint32_t m_appLimited {0}; //!< The index of the last transmitted packet marked as application-limited
|
||||
uint32_t m_txItemDelivered {0};
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
#endif // TCPBBR_H
|
||||
@@ -1811,6 +1811,7 @@ TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
|
||||
m_txBuffer->DiscardUpTo (ackNumber, MakeCallback (&TcpRateOps::SkbDelivered, m_rateOps));
|
||||
|
||||
uint32_t currentDelivered = static_cast<uint32_t> (m_rateOps->GetConnectionRate ().m_delivered - previousDelivered);
|
||||
m_tcb->m_lastAckedSackedBytes = currentDelivered;
|
||||
|
||||
if (m_tcb->m_congState == TcpSocketState::CA_CWR && (ackNumber > m_recover))
|
||||
{
|
||||
|
||||
@@ -116,7 +116,10 @@ TcpSocketState::TcpSocketState (const TcpSocketState &other)
|
||||
m_bytesInFlight (other.m_bytesInFlight),
|
||||
m_lastRtt (other.m_lastRtt),
|
||||
m_ecnMode (other.m_ecnMode),
|
||||
m_useEcn (other.m_useEcn)
|
||||
m_useEcn (other.m_useEcn),
|
||||
m_ectCodePoint (other.m_ectCodePoint),
|
||||
m_lastAckedSackedBytes (other.m_lastAckedSackedBytes)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -207,6 +207,8 @@ public:
|
||||
|
||||
EcnCodePoint_t m_ectCodePoint {Ect0}; //!< ECT code point to use
|
||||
|
||||
uint32_t m_lastAckedSackedBytes {0}; //!< Last acked and sacked recorded upon receiving last acknowledgment
|
||||
|
||||
/**
|
||||
* \brief Get cwnd in segments rather than bytes
|
||||
*
|
||||
|
||||
@@ -163,6 +163,7 @@ def build(bld):
|
||||
'model/tcp-htcp.cc',
|
||||
'model/tcp-lp.cc',
|
||||
'model/tcp-dctcp.cc',
|
||||
'model/tcp-bbr.cc',
|
||||
'model/tcp-rx-buffer.cc',
|
||||
'model/tcp-tx-buffer.cc',
|
||||
'model/tcp-tx-item.cc',
|
||||
@@ -421,6 +422,7 @@ def build(bld):
|
||||
'model/tcp-lp.h',
|
||||
'model/tcp-dctcp.h',
|
||||
'model/windowed-filter.h',
|
||||
'model/tcp-bbr.h',
|
||||
'model/tcp-ledbat.h',
|
||||
'model/tcp-socket-base.h',
|
||||
'model/tcp-socket-state.h',
|
||||
|
||||
Reference in New Issue
Block a user