OLD | NEW |
| (Empty) |
1 /***************************************************************************** | |
2 Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. | |
3 All rights reserved. | |
4 | |
5 Redistribution and use in source and binary forms, with or without | |
6 modification, are permitted provided that the following conditions are | |
7 met: | |
8 | |
9 * Redistributions of source code must retain the above | |
10 copyright notice, this list of conditions and the | |
11 following disclaimer. | |
12 | |
13 * Redistributions in binary form must reproduce the | |
14 above copyright notice, this list of conditions | |
15 and the following disclaimer in the documentation | |
16 and/or other materials provided with the distribution. | |
17 | |
18 * Neither the name of the University of Illinois | |
19 nor the names of its contributors may be used to | |
20 endorse or promote products derived from this | |
21 software without specific prior written permission. | |
22 | |
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
24 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
25 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
26 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 *****************************************************************************/ | |
35 | |
36 /***************************************************************************** | |
37 written by | |
38 Yunhong Gu, last updated 07/09/2009 | |
39 *****************************************************************************/ | |
40 | |
41 | |
42 #include "core.h" | |
43 #include "ccc.h" | |
44 #include <cmath> | |
45 #include <cstring> | |
46 | |
47 CCC::CCC(): | |
48 m_iSYNInterval(CUDT::m_iSYNInterval), | |
49 m_dPktSndPeriod(1.0), | |
50 m_dCWndSize(16.0), | |
51 m_iBandwidth(), | |
52 m_dMaxCWndSize(), | |
53 m_iMSS(), | |
54 m_iSndCurrSeqNo(), | |
55 m_iRcvRate(), | |
56 m_iRTT(), | |
57 m_pcParam(NULL), | |
58 m_iPSize(0), | |
59 m_UDT(), | |
60 m_iACKPeriod(0), | |
61 m_iACKInterval(0), | |
62 m_bUserDefinedRTO(false), | |
63 m_iRTO(-1), | |
64 m_PerfInfo() | |
65 { | |
66 } | |
67 | |
68 CCC::~CCC() | |
69 { | |
70 delete [] m_pcParam; | |
71 } | |
72 | |
73 void CCC::setACKTimer(const int& msINT) | |
74 { | |
75 m_iACKPeriod = msINT; | |
76 | |
77 if (m_iACKPeriod > m_iSYNInterval) | |
78 m_iACKPeriod = m_iSYNInterval; | |
79 } | |
80 | |
81 void CCC::setACKInterval(const int& pktINT) | |
82 { | |
83 m_iACKInterval = pktINT; | |
84 } | |
85 | |
86 void CCC::setRTO(const int& usRTO) | |
87 { | |
88 m_bUserDefinedRTO = true; | |
89 m_iRTO = usRTO; | |
90 } | |
91 | |
92 void CCC::sendCustomMsg(CPacket& pkt) const | |
93 { | |
94 CUDT* u = CUDT::getUDTHandle(m_UDT); | |
95 | |
96 if (NULL != u) | |
97 { | |
98 pkt.m_iID = u->m_PeerID; | |
99 u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt); | |
100 } | |
101 } | |
102 | |
103 const CPerfMon* CCC::getPerfInfo() | |
104 { | |
105 CUDT* u = CUDT::getUDTHandle(m_UDT); | |
106 if (NULL != u) | |
107 u->sample(&m_PerfInfo, false); | |
108 | |
109 return &m_PerfInfo; | |
110 } | |
111 | |
112 void CCC::setMSS(const int& mss) | |
113 { | |
114 m_iMSS = mss; | |
115 } | |
116 | |
117 void CCC::setBandwidth(const int& bw) | |
118 { | |
119 m_iBandwidth = bw; | |
120 } | |
121 | |
122 void CCC::setSndCurrSeqNo(const int32_t& seqno) | |
123 { | |
124 m_iSndCurrSeqNo = seqno; | |
125 } | |
126 | |
127 void CCC::setRcvRate(const int& rcvrate) | |
128 { | |
129 m_iRcvRate = rcvrate; | |
130 } | |
131 | |
132 void CCC::setMaxCWndSize(const int& cwnd) | |
133 { | |
134 m_dMaxCWndSize = cwnd; | |
135 } | |
136 | |
137 void CCC::setRTT(const int& rtt) | |
138 { | |
139 m_iRTT = rtt; | |
140 } | |
141 | |
142 void CCC::setUserParam(const char* param, const int& size) | |
143 { | |
144 delete [] m_pcParam; | |
145 m_pcParam = new char[size]; | |
146 memcpy(m_pcParam, param, size); | |
147 m_iPSize = size; | |
148 } | |
149 | |
150 // | |
151 CUDTCC::CUDTCC(): | |
152 m_iRCInterval(), | |
153 m_LastRCTime(), | |
154 m_bSlowStart(), | |
155 m_iLastAck(), | |
156 m_bLoss(), | |
157 m_iLastDecSeq(), | |
158 m_dLastDecPeriod(), | |
159 m_iNAKCount(), | |
160 m_iDecRandom(), | |
161 m_iAvgNAKNum(), | |
162 m_iDecCount() | |
163 { | |
164 } | |
165 | |
166 void CUDTCC::init() | |
167 { | |
168 m_iRCInterval = m_iSYNInterval; | |
169 m_LastRCTime = CTimer::getTime(); | |
170 setACKTimer(m_iRCInterval); | |
171 | |
172 m_bSlowStart = true; | |
173 m_iLastAck = m_iSndCurrSeqNo; | |
174 m_bLoss = false; | |
175 m_iLastDecSeq = CSeqNo::decseq(m_iLastAck); | |
176 m_dLastDecPeriod = 1; | |
177 m_iAvgNAKNum = 0; | |
178 m_iNAKCount = 0; | |
179 m_iDecRandom = 1; | |
180 | |
181 m_dCWndSize = 16; | |
182 m_dPktSndPeriod = 1; | |
183 } | |
184 | |
185 void CUDTCC::onACK(const int32_t& ack) | |
186 { | |
187 uint64_t currtime = CTimer::getTime(); | |
188 if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval) | |
189 return; | |
190 | |
191 m_LastRCTime = currtime; | |
192 | |
193 if (m_bSlowStart) | |
194 { | |
195 m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack); | |
196 m_iLastAck = ack; | |
197 | |
198 if (m_dCWndSize > m_dMaxCWndSize) | |
199 { | |
200 m_bSlowStart = false; | |
201 if (m_iRcvRate > 0) | |
202 m_dPktSndPeriod = 1000000.0 / m_iRcvRate; | |
203 else | |
204 m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); | |
205 } | |
206 } | |
207 else | |
208 m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16; | |
209 | |
210 // During Slow Start, no rate increase | |
211 if (m_bSlowStart) | |
212 return; | |
213 | |
214 if (m_bLoss) | |
215 { | |
216 m_bLoss = false; | |
217 return; | |
218 } | |
219 | |
220 int64_t B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod); | |
221 if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B)) | |
222 B = m_iBandwidth / 9; | |
223 | |
224 double inc; | |
225 | |
226 if (B <= 0) | |
227 inc = 1.0 / m_iMSS; | |
228 else | |
229 { | |
230 // inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS) | |
231 // Beta = 1.5 * 10^(-6) | |
232 | |
233 inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS; | |
234 | |
235 if (inc < 1.0/m_iMSS) | |
236 inc = 1.0/m_iMSS; | |
237 } | |
238 | |
239 m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc
+ m_iRCInterval); | |
240 | |
241 //set maximum transfer rate | |
242 if ((NULL != m_pcParam) && (m_iPSize == 8)) | |
243 { | |
244 int64_t maxSR = *(int64_t*)m_pcParam; | |
245 if (maxSR <= 0) | |
246 return; | |
247 | |
248 double minSP = 1000000.0 / (double(maxSR) / m_iMSS); | |
249 if (m_dPktSndPeriod < minSP) | |
250 m_dPktSndPeriod = minSP; | |
251 } | |
252 } | |
253 | |
254 void CUDTCC::onLoss(const int32_t* losslist, const int&) | |
255 { | |
256 //Slow Start stopped, if it hasn't yet | |
257 if (m_bSlowStart) | |
258 { | |
259 m_bSlowStart = false; | |
260 if (m_iRcvRate > 0) | |
261 m_dPktSndPeriod = 1000000.0 / m_iRcvRate; | |
262 else | |
263 m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); | |
264 } | |
265 | |
266 m_bLoss = true; | |
267 | |
268 if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0) | |
269 { | |
270 m_dLastDecPeriod = m_dPktSndPeriod; | |
271 m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); | |
272 | |
273 m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125); | |
274 m_iNAKCount = 1; | |
275 m_iDecCount = 1; | |
276 | |
277 m_iLastDecSeq = m_iSndCurrSeqNo; | |
278 | |
279 // remove global synchronization using randomization | |
280 srand(m_iLastDecSeq); | |
281 m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX)); | |
282 if (m_iDecRandom < 1) | |
283 m_iDecRandom = 1; | |
284 } | |
285 else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom))) | |
286 { | |
287 // 0.875^5 = 0.51, rate should not be decreased by more than half within a
congestion period | |
288 m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); | |
289 m_iLastDecSeq = m_iSndCurrSeqNo; | |
290 } | |
291 } | |
292 | |
293 void CUDTCC::onTimeout() | |
294 { | |
295 if (m_bSlowStart) | |
296 { | |
297 m_bSlowStart = false; | |
298 if (m_iRcvRate > 0) | |
299 m_dPktSndPeriod = 1000000.0 / m_iRcvRate; | |
300 else | |
301 m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); | |
302 } | |
303 else | |
304 { | |
305 /* | |
306 m_dLastDecPeriod = m_dPktSndPeriod; | |
307 m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2); | |
308 m_iLastDecSeq = m_iLastAck; | |
309 */ | |
310 } | |
311 } | |
OLD | NEW |