1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015 ResiliNets, ITTC, University of Kansas
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * by: Amir Modarresi <amodarresi@ittc.ku.edu>
19  *
20  * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
21  * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
22  * Information and Telecommunication Technology Center (ITTC)
23  * and Department of Electrical Engineering and Computer Science
24  * The University of Kansas Lawrence, KS USA.
25  */
26 
27 #include "tcp-htcp.h"
28 #include "ns3/log.h"
29 #include "ns3/simulator.h"
30 
31 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("TcpHtcp");
34 
35 NS_OBJECT_ENSURE_REGISTERED (TcpHtcp);
36 
GetTypeId(void)37 TypeId TcpHtcp::GetTypeId (void)
38 {
39   static TypeId tid = TypeId ("ns3::TcpHtcp")
40     .SetParent<TcpNewReno> ()
41     .AddConstructor<TcpHtcp> ()
42     .SetGroupName ("Internet")
43     .AddAttribute ("DefaultBackoff",
44                    "The default AIMD backoff factor",
45                    DoubleValue (0.5),
46                    MakeDoubleAccessor (&TcpHtcp::m_defaultBackoff),
47                    MakeDoubleChecker<double> (0,1))
48     .AddAttribute ("ThroughputRatio",
49                    "Threshold value for updating beta",
50                    DoubleValue (0.2),
51                    MakeDoubleAccessor (&TcpHtcp::m_throughputRatio),
52                    MakeDoubleChecker<double> ())
53     .AddAttribute ("DeltaL",
54                    "Delta_L parameter in increase function",
55                    TimeValue (Seconds (1)),
56                    MakeTimeAccessor (&TcpHtcp::m_deltaL),
57                    MakeTimeChecker ())
58   ;
59   return tid;
60 }
61 
GetName() const62 std::string TcpHtcp::GetName () const
63 {
64   return "TcpHtcp";
65 }
66 
TcpHtcp(void)67 TcpHtcp::TcpHtcp (void)
68   : TcpNewReno (),
69     m_alpha (0),
70     m_beta (0),
71     m_delta (0),
72     m_lastCon (0),
73     m_minRtt (Time::Max ()),
74     m_maxRtt (Time::Min ()),
75     m_throughput (0),
76     m_lastThroughput (0),
77     m_dataSent (0)
78 {
79   NS_LOG_FUNCTION (this);
80 }
81 
TcpHtcp(const TcpHtcp & sock)82 TcpHtcp::TcpHtcp (const TcpHtcp& sock)
83   : TcpNewReno (sock),
84     m_alpha (sock.m_alpha),
85     m_beta (sock.m_beta),
86     m_defaultBackoff (sock.m_defaultBackoff),
87     m_throughputRatio (sock.m_throughputRatio),
88     m_delta (sock.m_delta),
89     m_deltaL (sock.m_deltaL),
90     m_lastCon (sock.m_lastCon),
91     m_minRtt (sock.m_minRtt),
92     m_maxRtt (sock.m_maxRtt),
93     m_throughput (sock.m_throughput),
94     m_lastThroughput (sock.m_lastThroughput),
95     m_dataSent (sock.m_dataSent)
96 {
97   NS_LOG_FUNCTION (this);
98 }
99 
~TcpHtcp(void)100 TcpHtcp::~TcpHtcp (void)
101 {
102   NS_LOG_FUNCTION (this);
103 }
104 
Fork(void)105 Ptr<TcpCongestionOps> TcpHtcp::Fork (void)
106 {
107   NS_LOG_FUNCTION (this);
108   return CopyObject<TcpHtcp> (this);
109 }
110 
CongestionAvoidance(Ptr<TcpSocketState> tcb,uint32_t segmentsAcked)111 void TcpHtcp::CongestionAvoidance (Ptr<TcpSocketState> tcb,
112                                    uint32_t segmentsAcked)
113 {
114   NS_LOG_FUNCTION (this << tcb << segmentsAcked);
115   if (segmentsAcked > 0)
116     {
117       double adder = static_cast<double> (((tcb->m_segmentSize
118                                             * tcb->m_segmentSize) + (tcb->m_cWnd * m_alpha)) / tcb->m_cWnd);
119       adder = std::max (1.0, adder);
120       tcb->m_cWnd += static_cast<uint32_t> (adder);
121       NS_LOG_INFO ("In CongAvoid, updated to cwnd " << tcb->m_cWnd
122                                                     << " ssthresh " << tcb->m_ssThresh);
123     }
124 }
125 
UpdateAlpha(void)126 void TcpHtcp::UpdateAlpha (void)
127 {
128   NS_LOG_FUNCTION (this);
129 
130   m_delta = (Simulator::Now () - m_lastCon);
131   if (m_delta <= m_deltaL)
132     {
133       m_alpha = 1;
134     }
135   else
136     {
137       Time diff = m_delta - m_deltaL;
138       double diffSec = diff.GetSeconds ();
139       // alpha=1+10(Delta-Delta_L)+[0.5(Delta-Delta_L)]^2  (seconds)
140       // from Leith and Shorten H-TCP paper
141       m_alpha = (1 + 10 * diffSec + 0.25 * (diffSec * diffSec));
142     }
143   m_alpha = 2 * (1 - m_beta) * m_alpha;
144   if (m_alpha < 1)
145     {
146       m_alpha = 1;
147     }
148   NS_LOG_DEBUG ("Updated m_alpha: " << m_alpha);
149 }
150 
UpdateBeta(void)151 void TcpHtcp::UpdateBeta (void)
152 {
153   NS_LOG_FUNCTION (this);
154 
155   // Default value for m_beta
156   m_beta = m_defaultBackoff;
157 
158   if (m_throughput > m_lastThroughput && m_lastThroughput > 0)
159     {
160       uint32_t diff = m_throughput - m_lastThroughput;
161       if (diff / m_lastThroughput <= m_throughputRatio)
162         {
163           m_beta = m_minRtt.GetDouble () / m_maxRtt.GetDouble ();
164         }
165     }
166   NS_LOG_DEBUG ("Updated m_beta: " << m_beta);
167 }
168 
GetSsThresh(Ptr<const TcpSocketState> tcb,uint32_t bytesInFlight)169 uint32_t TcpHtcp::GetSsThresh (Ptr<const TcpSocketState> tcb,
170                                uint32_t bytesInFlight)
171 {
172   NS_LOG_FUNCTION (this << tcb << bytesInFlight);
173 
174   m_lastCon = Simulator::Now ();
175 
176   UpdateBeta ();
177   UpdateAlpha ();
178 
179   uint32_t segWin = 2 * tcb->m_segmentSize;
180   uint32_t bFlight = static_cast<uint32_t> (bytesInFlight * m_beta);
181   uint32_t ssThresh = std::max (segWin, bFlight);
182   m_minRtt = Time::Max ();
183   m_maxRtt = Time::Min ();
184   m_lastThroughput = m_throughput;
185   m_throughput = 0;
186   m_dataSent = 0;
187   NS_LOG_DEBUG (this << " ssThresh: " << ssThresh << " m_beta: "  << m_beta);
188   return ssThresh;
189 }
190 
PktsAcked(Ptr<TcpSocketState> tcb,uint32_t segmentsAcked,const Time & rtt)191 void TcpHtcp::PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
192                          const Time &rtt)
193 {
194 
195   NS_LOG_FUNCTION (this << tcb << segmentsAcked << rtt);
196   NS_LOG_DEBUG ("TcpSocketState: " << tcb->m_congState);
197   if (tcb->m_congState == TcpSocketState::CA_OPEN)
198     {
199       m_dataSent += segmentsAcked * tcb->m_segmentSize;
200     }
201 
202   m_throughput = static_cast<uint32_t> (m_dataSent
203                                         / (Simulator::Now ().GetSeconds () - m_lastCon.GetSeconds ()));
204 
205   UpdateAlpha ();
206   if (rtt < m_minRtt)
207     {
208       m_minRtt = rtt;
209       NS_LOG_DEBUG ("Updated m_minRtt=" << m_minRtt);
210     }
211   if (rtt > m_maxRtt)
212     {
213       m_maxRtt = rtt;
214       NS_LOG_DEBUG ("Updated m_maxRtt=" << m_maxRtt);
215     }
216 }
217 
218 } // namespace ns3
219