OLD | NEW |
| (Empty) |
1 /***************************************************************************** | |
2 Copyright (c) 2001 - 2011, 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 01/22/2011 | |
39 *****************************************************************************/ | |
40 | |
41 #include <cmath> | |
42 #include "common.h" | |
43 #include "window.h" | |
44 #include <algorithm> | |
45 | |
46 using namespace std; | |
47 | |
48 CACKWindow::CACKWindow(const int& size): | |
49 m_piACKSeqNo(NULL), | |
50 m_piACK(NULL), | |
51 m_pTimeStamp(NULL), | |
52 m_iSize(size), | |
53 m_iHead(0), | |
54 m_iTail(0) | |
55 { | |
56 m_piACKSeqNo = new int32_t[m_iSize]; | |
57 m_piACK = new int32_t[m_iSize]; | |
58 m_pTimeStamp = new uint64_t[m_iSize]; | |
59 | |
60 m_piACKSeqNo[0] = -1; | |
61 } | |
62 | |
63 CACKWindow::~CACKWindow() | |
64 { | |
65 delete [] m_piACKSeqNo; | |
66 delete [] m_piACK; | |
67 delete [] m_pTimeStamp; | |
68 } | |
69 | |
70 void CACKWindow::store(const int32_t& seq, const int32_t& ack) | |
71 { | |
72 m_piACKSeqNo[m_iHead] = seq; | |
73 m_piACK[m_iHead] = ack; | |
74 m_pTimeStamp[m_iHead] = CTimer::getTime(); | |
75 | |
76 m_iHead = (m_iHead + 1) % m_iSize; | |
77 | |
78 // overwrite the oldest ACK since it is not likely to be acknowledged | |
79 if (m_iHead == m_iTail) | |
80 m_iTail = (m_iTail + 1) % m_iSize; | |
81 } | |
82 | |
83 int CACKWindow::acknowledge(const int32_t& seq, int32_t& ack) | |
84 { | |
85 if (m_iHead >= m_iTail) | |
86 { | |
87 // Head has not exceeded the physical boundary of the window | |
88 | |
89 for (int i = m_iTail, n = m_iHead; i < n; ++ i) | |
90 { | |
91 // looking for indentical ACK Seq. No. | |
92 if (seq == m_piACKSeqNo[i]) | |
93 { | |
94 // return the Data ACK it carried | |
95 ack = m_piACK[i]; | |
96 | |
97 // calculate RTT | |
98 int rtt = int(CTimer::getTime() - m_pTimeStamp[i]); | |
99 | |
100 if (i + 1 == m_iHead) | |
101 { | |
102 m_iTail = m_iHead = 0; | |
103 m_piACKSeqNo[0] = -1; | |
104 } | |
105 else | |
106 m_iTail = (i + 1) % m_iSize; | |
107 | |
108 return rtt; | |
109 } | |
110 } | |
111 | |
112 // Bad input, the ACK node has been overwritten | |
113 return -1; | |
114 } | |
115 | |
116 // Head has exceeded the physical window boundary, so it is behind tail | |
117 for (int j = m_iTail, n = m_iHead + m_iSize; j < n; ++ j) | |
118 { | |
119 // looking for indentical ACK seq. no. | |
120 if (seq == m_piACKSeqNo[j % m_iSize]) | |
121 { | |
122 // return Data ACK | |
123 j %= m_iSize; | |
124 ack = m_piACK[j]; | |
125 | |
126 // calculate RTT | |
127 int rtt = int(CTimer::getTime() - m_pTimeStamp[j]); | |
128 | |
129 if (j == m_iHead) | |
130 { | |
131 m_iTail = m_iHead = 0; | |
132 m_piACKSeqNo[0] = -1; | |
133 } | |
134 else | |
135 m_iTail = (j + 1) % m_iSize; | |
136 | |
137 return rtt; | |
138 } | |
139 } | |
140 | |
141 // bad input, the ACK node has been overwritten | |
142 return -1; | |
143 } | |
144 | |
145 //////////////////////////////////////////////////////////////////////////////// | |
146 | |
147 CPktTimeWindow::CPktTimeWindow(const int& asize, const int& psize): | |
148 m_iAWSize(asize), | |
149 m_piPktWindow(NULL), | |
150 m_iPktWindowPtr(0), | |
151 m_iPWSize(psize), | |
152 m_piProbeWindow(NULL), | |
153 m_iProbeWindowPtr(0), | |
154 m_iLastSentTime(0), | |
155 m_iMinPktSndInt(1000000), | |
156 m_LastArrTime(), | |
157 m_CurrArrTime(), | |
158 m_ProbeTime() | |
159 { | |
160 m_piPktWindow = new int[m_iAWSize]; | |
161 m_piPktReplica = new int[m_iAWSize]; | |
162 m_piProbeWindow = new int[m_iPWSize]; | |
163 m_piProbeReplica = new int[m_iPWSize]; | |
164 | |
165 m_LastArrTime = CTimer::getTime(); | |
166 | |
167 for (int i = 0; i < m_iAWSize; ++ i) | |
168 m_piPktWindow[i] = 1000000; | |
169 | |
170 for (int k = 0; k < m_iPWSize; ++ k) | |
171 m_piProbeWindow[k] = 1000; | |
172 } | |
173 | |
174 CPktTimeWindow::~CPktTimeWindow() | |
175 { | |
176 delete [] m_piPktWindow; | |
177 delete [] m_piPktReplica; | |
178 delete [] m_piProbeWindow; | |
179 delete [] m_piProbeReplica; | |
180 } | |
181 | |
182 int CPktTimeWindow::getMinPktSndInt() const | |
183 { | |
184 return m_iMinPktSndInt; | |
185 } | |
186 | |
187 int CPktTimeWindow::getPktRcvSpeed() const | |
188 { | |
189 // get median value, but cannot change the original value order in the window | |
190 std::copy(m_piPktWindow, m_piPktWindow + m_iAWSize - 1, m_piPktReplica); | |
191 std::nth_element(m_piPktReplica, m_piPktReplica + (m_iAWSize / 2), m_piPktRep
lica + m_iAWSize - 1); | |
192 int median = m_piPktReplica[m_iAWSize / 2]; | |
193 | |
194 int count = 0; | |
195 int sum = 0; | |
196 int upper = median << 3; | |
197 int lower = median >> 3; | |
198 | |
199 // median filtering | |
200 int* p = m_piPktWindow; | |
201 for (int i = 0, n = m_iAWSize; i < n; ++ i) | |
202 { | |
203 if ((*p < upper) && (*p > lower)) | |
204 { | |
205 ++ count; | |
206 sum += *p; | |
207 } | |
208 ++ p; | |
209 } | |
210 | |
211 // claculate speed, or return 0 if not enough valid value | |
212 if (count > (m_iAWSize >> 1)) | |
213 return (int)ceil(1000000.0 / (sum / count)); | |
214 else | |
215 return 0; | |
216 } | |
217 | |
218 int CPktTimeWindow::getBandwidth() const | |
219 { | |
220 // get median value, but cannot change the original value order in the window | |
221 std::copy(m_piProbeWindow, m_piProbeWindow + m_iPWSize - 1, m_piProbeReplica)
; | |
222 std::nth_element(m_piProbeReplica, m_piProbeReplica + (m_iPWSize / 2), m_piPr
obeReplica + m_iPWSize - 1); | |
223 int median = m_piProbeReplica[m_iPWSize / 2]; | |
224 | |
225 int count = 1; | |
226 int sum = median; | |
227 int upper = median << 3; | |
228 int lower = median >> 3; | |
229 | |
230 // median filtering | |
231 int* p = m_piProbeWindow; | |
232 for (int i = 0, n = m_iPWSize; i < n; ++ i) | |
233 { | |
234 if ((*p < upper) && (*p > lower)) | |
235 { | |
236 ++ count; | |
237 sum += *p; | |
238 } | |
239 ++ p; | |
240 } | |
241 | |
242 return (int)ceil(1000000.0 / (double(sum) / double(count))); | |
243 } | |
244 | |
245 void CPktTimeWindow::onPktSent(const int& currtime) | |
246 { | |
247 int interval = currtime - m_iLastSentTime; | |
248 | |
249 if ((interval < m_iMinPktSndInt) && (interval > 0)) | |
250 m_iMinPktSndInt = interval; | |
251 | |
252 m_iLastSentTime = currtime; | |
253 } | |
254 | |
255 void CPktTimeWindow::onPktArrival() | |
256 { | |
257 m_CurrArrTime = CTimer::getTime(); | |
258 | |
259 // record the packet interval between the current and the last one | |
260 *(m_piPktWindow + m_iPktWindowPtr) = int(m_CurrArrTime - m_LastArrTime); | |
261 | |
262 // the window is logically circular | |
263 ++ m_iPktWindowPtr; | |
264 if (m_iPktWindowPtr == m_iAWSize) | |
265 m_iPktWindowPtr = 0; | |
266 | |
267 // remember last packet arrival time | |
268 m_LastArrTime = m_CurrArrTime; | |
269 } | |
270 | |
271 void CPktTimeWindow::probe1Arrival() | |
272 { | |
273 m_ProbeTime = CTimer::getTime(); | |
274 } | |
275 | |
276 void CPktTimeWindow::probe2Arrival() | |
277 { | |
278 m_CurrArrTime = CTimer::getTime(); | |
279 | |
280 // record the probing packets interval | |
281 *(m_piProbeWindow + m_iProbeWindowPtr) = int(m_CurrArrTime - m_ProbeTime); | |
282 // the window is logically circular | |
283 ++ m_iProbeWindowPtr; | |
284 if (m_iProbeWindowPtr == m_iPWSize) | |
285 m_iProbeWindowPtr = 0; | |
286 } | |
OLD | NEW |