1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2014 Natale Patriciello <natale.patriciello@gmail.com>
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 */
19
20 #include "tcp-hybla.h"
21 #include "tcp-socket-state.h"
22
23 #include "ns3/log.h"
24
25 namespace ns3 {
26
27 NS_LOG_COMPONENT_DEFINE ("TcpHybla");
28 NS_OBJECT_ENSURE_REGISTERED (TcpHybla);
29
30 TypeId
GetTypeId(void)31 TcpHybla::GetTypeId (void)
32 {
33 static TypeId tid = TypeId ("ns3::TcpHybla")
34 .SetParent<TcpNewReno> ()
35 .AddConstructor<TcpHybla> ()
36 .SetGroupName ("Internet")
37 .AddAttribute ("RRTT", "Reference RTT",
38 TimeValue (MilliSeconds (50)),
39 MakeTimeAccessor (&TcpHybla::m_rRtt),
40 MakeTimeChecker ())
41 .AddTraceSource ("Rho",
42 "Rho parameter of Hybla",
43 MakeTraceSourceAccessor (&TcpHybla::m_rho),
44 "ns3::TracedValueCallback::Double")
45 ;
46 return tid;
47 }
48
TcpHybla()49 TcpHybla::TcpHybla ()
50 : TcpNewReno (),
51 m_rho (1.0),
52 m_cWndCnt (0)
53 {
54 NS_LOG_FUNCTION (this);
55 }
56
TcpHybla(const TcpHybla & sock)57 TcpHybla::TcpHybla (const TcpHybla &sock)
58 : TcpNewReno (sock),
59 m_rho (sock.m_rho),
60 m_cWndCnt (sock.m_cWndCnt)
61 {
62 NS_LOG_FUNCTION (this);
63 }
64
~TcpHybla()65 TcpHybla::~TcpHybla ()
66 {
67 NS_LOG_FUNCTION (this);
68 }
69
70 void
RecalcParam(const Ptr<TcpSocketState> & tcb)71 TcpHybla::RecalcParam (const Ptr<TcpSocketState> &tcb)
72 {
73 NS_LOG_FUNCTION (this);
74
75 m_rho = std::max ((double) tcb->m_minRtt.GetMilliSeconds () / m_rRtt.GetMilliSeconds (), 1.0);
76
77 NS_ASSERT (m_rho > 0.0);
78 NS_LOG_DEBUG ("Calculated rho=" << m_rho);
79 }
80
81 void
PktsAcked(Ptr<TcpSocketState> tcb,uint32_t segmentsAcked,const Time & rtt)82 TcpHybla::PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
83 const Time &rtt)
84 {
85 NS_LOG_FUNCTION (this << tcb << segmentsAcked << rtt);
86
87 if (rtt == tcb->m_minRtt)
88 {
89 RecalcParam (tcb);
90 NS_LOG_DEBUG ("min rtt seen: " << rtt);
91 }
92 }
93
94 uint32_t
SlowStart(Ptr<TcpSocketState> tcb,uint32_t segmentsAcked)95 TcpHybla::SlowStart (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
96 {
97 NS_LOG_FUNCTION (this << tcb << segmentsAcked);
98
99 NS_ASSERT (tcb->m_cWnd <= tcb->m_ssThresh);
100
101 if (segmentsAcked >= 1)
102 {
103 /*
104 * slow start
105 * INC = 2^RHO - 1
106 */
107
108 double increment = std::pow (2, m_rho) - 1.0;
109 uint32_t incr = static_cast<uint32_t> (increment * tcb->m_segmentSize);
110 NS_LOG_INFO ("Slow start: inc=" << increment);
111
112 tcb->m_cWnd = std::min (tcb->m_cWnd + incr, tcb->m_ssThresh);
113
114 NS_LOG_INFO ("In SlowStart, updated to cwnd " << tcb->m_cWnd <<
115 " ssthresh " << tcb->m_ssThresh <<
116 " with an increment of " << increment * tcb->m_segmentSize);
117
118 return segmentsAcked - 1;
119 }
120
121 return 0;
122 }
123
124 void
CongestionAvoidance(Ptr<TcpSocketState> tcb,uint32_t segmentsAcked)125 TcpHybla::CongestionAvoidance (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
126 {
127 NS_LOG_FUNCTION (this << tcb << segmentsAcked);
128
129 uint32_t segCwnd;
130 double increment;
131
132 while (segmentsAcked > 0)
133 {
134 /*
135 * congestion avoidance
136 * INC = RHO^2 / W
137 */
138 segCwnd = tcb->GetCwndInSegments ();
139 increment = std::pow (m_rho, 2) / static_cast<double> (segCwnd);
140
141 m_cWndCnt += increment;
142 segmentsAcked -= 1;
143 }
144
145 if (m_cWndCnt >= 1.0)
146 {
147 // double to int truncates every time.
148 uint32_t inc = static_cast<uint32_t> (m_cWndCnt);
149 m_cWndCnt -= inc;
150
151 NS_ASSERT (m_cWndCnt >= 0.0);
152
153 /* This leaves space for a tcp pacing implementation; it would be easy
154 to setup a limit on the maximum increment of the cWnd per ACK received.
155 The remaining increment is leaved for the next ACK. */
156
157 tcb->m_cWnd += inc * tcb->m_segmentSize;
158
159
160 NS_LOG_INFO ("In CongAvoid, updated to cwnd " << tcb->m_cWnd <<
161 " ssthresh " << tcb->m_ssThresh <<
162 " with an increment of " << inc * tcb->m_segmentSize);
163 }
164 }
165
166 Ptr<TcpCongestionOps>
Fork(void)167 TcpHybla::Fork (void)
168 {
169 return CopyObject<TcpHybla> (this);
170 }
171
172 std::string
GetName() const173 TcpHybla::GetName () const
174 {
175 return "TcpHybla";
176 }
177
178
179 } // namespace ns3
180