33 #define NS_LOG_APPEND_CONTEXT \
34 if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
36 #include "tcp-westwood.h"
38 #include "ns3/trace-source-accessor.h"
39 #include "ns3/simulator.h"
40 #include "ns3/abort.h"
42 #include "ns3/sequence-number.h"
43 #include "rtt-estimator.h"
49 NS_OBJECT_ENSURE_REGISTERED(TcpWestwood);
52 TcpWestwood::GetTypeId (
void)
54 static TypeId tid = TypeId(
"ns3::TcpWestwood")
56 .AddConstructor<TcpWestwood>()
57 .AddTraceSource(
"CongestionWindow",
"The TCP connection's congestion window",
59 .AddAttribute(
"FilterType",
"Use this to choose no filter or Tustin's approximation filter",
60 EnumValue(TcpWestwood::TUSTIN), MakeEnumAccessor(&TcpWestwood::m_fType),
61 MakeEnumChecker(TcpWestwood::NONE,
"None", TcpWestwood::TUSTIN,
"Tustin"))
62 .AddAttribute(
"ProtocolType",
"Use this to let the code run as Westwood or WestwoodPlus",
63 EnumValue(TcpWestwood::WESTWOOD),
64 MakeEnumAccessor(&TcpWestwood::m_pType),
65 MakeEnumChecker(TcpWestwood::WESTWOOD,
"Westwood",TcpWestwood::WESTWOODPLUS,
"WestwoodPlus"))
66 .AddTraceSource(
"EstimatedBW",
"The estimated bandwidth",
71 TcpWestwood::TcpWestwood (
void) :
86 TcpWestwood::TcpWestwood (
const TcpWestwood& sock) :
89 m_ssThresh(sock.m_ssThresh),
90 m_initialCWnd(sock.m_initialCWnd),
92 m_currentBW(sock.m_currentBW),
93 m_lastSampleBW(sock.m_lastSampleBW),
94 m_lastBW(sock.m_lastBW),
95 m_minRtt(sock.m_minRtt),
96 m_lastAck(sock.m_lastAck),
97 m_prevAckNo(sock.m_prevAckNo),
98 m_accountedFor(sock.m_accountedFor),
99 m_pType(sock.m_pType),
100 m_fType(sock.m_fType),
101 m_IsCount(sock.m_IsCount)
105 NS_LOG_INFO (
"m_minRtt at copy constructor" << m_minRtt);
108 TcpWestwood::~TcpWestwood (
void)
132 return std::min (m_rWnd.Get (), m_cWnd.Get ());
139 return CopyObject<TcpWestwood>(
this);
146 NS_LOG_LOGIC (
"TcpWestwood receieved ACK for seq " << seq <<
147 " cwnd " << m_cWnd <<
148 " ssthresh " << m_ssThresh);
159 if (m_cWnd < m_ssThresh)
161 m_cWnd += m_segmentSize;
162 NS_LOG_INFO (
"In SlowStart, updated to cwnd " << m_cWnd <<
" ssthresh " << m_ssThresh);
166 double adder =
static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get();
167 adder = std::max(1.0, adder);
168 m_cWnd +=
static_cast<uint32_t
>(adder);
169 NS_LOG_INFO (
"In CongAvoid, updated to cwnd " << m_cWnd <<
" ssthresh " << m_ssThresh);
173 TcpSocketBase::NewAck(seq);
183 if (m_pType == TcpWestwood::WESTWOOD)
188 else if (m_pType == TcpWestwood::WESTWOODPLUS)
205 if (m_pType == TcpWestwood::WESTWOOD)
210 m_currentBW = acked * m_segmentSize / (currentAck - m_lastAck);
212 m_lastAck = currentAck;
214 else if (m_pType == TcpWestwood::WESTWOODPLUS)
217 m_currentBW = m_ackedSegments * m_segmentSize / rtt.
GetSeconds();
233 int cumul_ack = (tcpHeader.
GetAckNumber() - m_prevAckNo) / m_segmentSize;
243 if (m_accountedFor >= cumul_ack)
245 m_accountedFor -= cumul_ack;
248 else if (m_accountedFor < cumul_ack)
250 cumul_ack -= m_accountedFor;
264 m_ackedSegments += acked;
272 if (count == 3 && !m_inFastRec)
275 m_ssThresh = m_currentBW *
static_cast<double> (m_minRtt.
GetSeconds());
276 if (m_cWnd > m_ssThresh)
281 NS_LOG_INFO (
"Triple dupack. Enter fast recovery mode. Reset cwnd to " << m_cWnd <<
", ssthresh to " << m_ssThresh);
284 else if (m_inFastRec)
286 m_cWnd += m_segmentSize;
287 NS_LOG_INFO (
"Dupack in fast recovery mode. Increase cwnd to " << m_cWnd);
300 if (m_state == CLOSED || m_state == TIME_WAIT)
307 m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get() *
static_cast<double> (m_minRtt.
GetSeconds()));
308 m_cWnd = m_segmentSize;
313 ", ssthresh to " << m_ssThresh <<
", restart from seqnum " << m_nextTxSequence);
316 m_rtt->IncreaseMultiplier();
333 m_minRtt = m_lastRtt;
337 if (m_lastRtt < m_minRtt)
339 m_minRtt = m_lastRtt;
345 if (m_pType == TcpWestwood::WESTWOODPLUS)
347 if(m_lastRtt != 0 && m_state == ESTABLISHED && !m_IsCount)
350 m_bwEstimateEvent.
Cancel();
363 if (m_fType == TcpWestwood::NONE)
366 else if (m_fType == TcpWestwood::TUSTIN)
368 double sample_bwe = m_currentBW;
369 m_currentBW = (alpha * m_lastBW) + ((1 - alpha) * ((sample_bwe + m_lastSampleBW) / 2));
370 m_lastSampleBW = sample_bwe;
371 m_lastBW = m_currentBW;
378 NS_ABORT_MSG_UNLESS(m_state == CLOSED,
"TcpWestwood::SetSegSize() cannot change segment size after connection started.");
379 m_segmentSize = size;
386 m_ssThresh = threshold;
399 NS_ABORT_MSG_UNLESS(m_state == CLOSED,
"TcpWestwood::SetInitialCwnd() cannot change initial cwnd after connection started.");
400 m_initialCWnd = cwnd;
407 return m_initialCWnd;
419 m_cWnd = m_initialCWnd * m_segmentSize;
void InitializeCwnd(void)
int CountAck(const TcpHeader &tcpHeader)
smart pointer class similar to boost::intrusive_ptr
virtual void EstimateRtt(const TcpHeader &)
#define NS_LOG_FUNCTION(parameters)
virtual void ReceivedAck(Ptr< Packet >, const TcpHeader &)
SequenceNumber32 HeadSequence(void) const
virtual void NewAck(SequenceNumber32 const &seq)
#define NS_LOG_COMPONENT_DEFINE(name)
#define NS_LOG_FUNCTION_NOARGS()
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
virtual uint32_t Window(void)
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if cond is false.
virtual void Retransmit(void)
a polymophic address class
double GetSeconds(void) const
virtual uint32_t GetInitialCwnd(void) const
virtual void SetSSThresh(uint32_t threshold)
virtual void DupAck(const TcpHeader &header, uint32_t count)
#define NS_LOG_LOGIC(msg)
void UpdateAckedSegments(int acked)
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
virtual int Connect(const Address &address)
virtual void SetSegSize(uint32_t size)
virtual void ReceivedAck(Ptr< Packet > packet, const TcpHeader &tcpHeader)
virtual void SetInitialCwnd(uint32_t cwnd)
virtual Ptr< TcpSocketBase > Fork(void)
void EstimateBW(int acked, const TcpHeader &tcpHeader, Time rtt)
virtual uint32_t GetSSThresh(void) const
virtual int Connect(const Address &address)
virtual void EstimateRtt(const TcpHeader &header)
bool SendPendingData(bool withAck=false)