LEFT | RIGHT |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
2 /* | 2 /* |
3 * Copyright (c) 2007 Georgia Tech Research Corporation | 3 * Copyright (c) 2007 Georgia Tech Research Corporation |
4 * Copyright (c) 2010 Adrian Sai-wah Tam | 4 * Copyright (c) 2010 Adrian Sai-wah Tam |
5 * | 5 * |
6 * This program is free software; you can redistribute it and/or modify | 6 * This program is free software; you can redistribute it and/or modify |
7 * it under the terms of the GNU General Public License version 2 as | 7 * it under the terms of the GNU General Public License version 2 as |
8 * published by the Free Software Foundation; | 8 * published by the Free Software Foundation; |
9 * | 9 * |
10 * This program is distributed in the hope that it will be useful, | 10 * This program is distributed in the hope that it will be useful, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 #include "ns3/pointer.h" | 42 #include "ns3/pointer.h" |
43 #include "ns3/trace-source-accessor.h" | 43 #include "ns3/trace-source-accessor.h" |
44 #include "tcp-socket-base.h" | 44 #include "tcp-socket-base.h" |
45 #include "tcp-l4-protocol.h" | 45 #include "tcp-l4-protocol.h" |
46 #include "ipv4-end-point.h" | 46 #include "ipv4-end-point.h" |
47 #include "ipv6-end-point.h" | 47 #include "ipv6-end-point.h" |
48 #include "ipv6-l3-protocol.h" | 48 #include "ipv6-l3-protocol.h" |
49 #include "tcp-header.h" | 49 #include "tcp-header.h" |
50 #include "tcp-option-winscale.h" | 50 #include "tcp-option-winscale.h" |
51 #include "tcp-option-ts.h" | 51 #include "tcp-option-ts.h" |
| 52 #include "tcp-option-sack-permitted.h" |
| 53 #include "tcp-option-sack.h" |
52 #include "rtt-estimator.h" | 54 #include "rtt-estimator.h" |
53 #include "tcp-congestion-ops.h" | 55 #include "tcp-congestion-ops.h" |
54 | 56 |
55 #include <math.h> | 57 #include <math.h> |
56 #include <algorithm> | 58 #include <algorithm> |
57 | 59 |
58 namespace ns3 { | 60 namespace ns3 { |
59 | 61 |
60 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase"); | 62 NS_LOG_COMPONENT_DEFINE ("TcpSocketBase"); |
61 | 63 |
(...skipping 24 matching lines...) Expand all Loading... |
86 CallbackValue (), | 88 CallbackValue (), |
87 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback), | 89 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback), |
88 MakeCallbackChecker ()) | 90 MakeCallbackChecker ()) |
89 .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error i
s received on this socket.", | 91 .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error i
s received on this socket.", |
90 CallbackValue (), | 92 CallbackValue (), |
91 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback6), | 93 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback6), |
92 MakeCallbackChecker ()) | 94 MakeCallbackChecker ()) |
93 .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option", | 95 .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option", |
94 BooleanValue (true), | 96 BooleanValue (true), |
95 MakeBooleanAccessor (&TcpSocketBase::m_winScalingEnabled), | 97 MakeBooleanAccessor (&TcpSocketBase::m_winScalingEnabled), |
| 98 MakeBooleanChecker ()) |
| 99 .AddAttribute ("Sack", "Enable or disable Sack option", |
| 100 BooleanValue (true), |
| 101 MakeBooleanAccessor (&TcpSocketBase::m_sackEnabled), |
96 MakeBooleanChecker ()) | 102 MakeBooleanChecker ()) |
97 .AddAttribute ("Timestamp", "Enable or disable Timestamp option", | 103 .AddAttribute ("Timestamp", "Enable or disable Timestamp option", |
98 BooleanValue (true), | 104 BooleanValue (true), |
99 MakeBooleanAccessor (&TcpSocketBase::m_timestampEnabled), | 105 MakeBooleanAccessor (&TcpSocketBase::m_timestampEnabled), |
100 MakeBooleanChecker ()) | 106 MakeBooleanChecker ()) |
101 .AddAttribute ("MinRto", | 107 .AddAttribute ("MinRto", |
102 "Minimum retransmit timeout value", | 108 "Minimum retransmit timeout value", |
103 TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, bu
t Linux uses 200ms. | 109 TimeValue (Seconds (1.0)), // RFC 6298 says min RTO=1 sec, bu
t Linux uses 200ms. |
104 // See http://www.postel.org/pipermail/end2end-interest/2004-
November/004402.html | 110 // See http://www.postel.org/pipermail/end2end-interest/2004-
November/004402.html |
105 MakeTimeAccessor (&TcpSocketBase::SetMinRto, | 111 MakeTimeAccessor (&TcpSocketBase::SetMinRto, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 MakeTraceSourceAccessor (&TcpSocketBase::m_highTxMarkTrace)
, | 156 MakeTraceSourceAccessor (&TcpSocketBase::m_highTxMarkTrace)
, |
151 "ns3::SequenceNumber32TracedValueCallback") | 157 "ns3::SequenceNumber32TracedValueCallback") |
152 .AddTraceSource ("State", | 158 .AddTraceSource ("State", |
153 "TCP state", | 159 "TCP state", |
154 MakeTraceSourceAccessor (&TcpSocketBase::m_state), | 160 MakeTraceSourceAccessor (&TcpSocketBase::m_state), |
155 "ns3::TcpStatesTracedValueCallback") | 161 "ns3::TcpStatesTracedValueCallback") |
156 .AddTraceSource ("CongState", | 162 .AddTraceSource ("CongState", |
157 "TCP Congestion machine state", | 163 "TCP Congestion machine state", |
158 MakeTraceSourceAccessor (&TcpSocketBase::m_congStateTrace), | 164 MakeTraceSourceAccessor (&TcpSocketBase::m_congStateTrace), |
159 "ns3::TcpSocketState::TcpCongStatesTracedValueCallback") | 165 "ns3::TcpSocketState::TcpCongStatesTracedValueCallback") |
| 166 .AddTraceSource ("EcnState", |
| 167 "Current ECN State of TCP Socket", |
| 168 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnStateTrace), |
| 169 "ns3::TcpSocketState::EcnStatesTracedValueCallback") |
| 170 .AddTraceSource ("AdvWND", |
| 171 "Advertised Window Size", |
| 172 MakeTraceSourceAccessor (&TcpSocketBase::m_advWnd), |
| 173 "ns3::TracedValueCallback::Uint32") |
160 .AddTraceSource ("RWND", | 174 .AddTraceSource ("RWND", |
161 "Remote side's flow control window", | 175 "Remote side's flow control window", |
162 MakeTraceSourceAccessor (&TcpSocketBase::m_rWnd), | 176 MakeTraceSourceAccessor (&TcpSocketBase::m_rWnd), |
163 "ns3::TracedValueCallback::Uint32") | 177 "ns3::TracedValueCallback::Uint32") |
164 .AddTraceSource ("BytesInFlight", | 178 .AddTraceSource ("BytesInFlight", |
165 "Socket estimation of bytes in flight", | 179 "Socket estimation of bytes in flight", |
166 MakeTraceSourceAccessor (&TcpSocketBase::m_bytesInFlight), | 180 MakeTraceSourceAccessor (&TcpSocketBase::m_bytesInFlight), |
167 "ns3::TracedValueCallback::Uint32") | 181 "ns3::TracedValueCallback::Uint32") |
168 .AddTraceSource ("HighestRxSequence", | 182 .AddTraceSource ("HighestRxSequence", |
169 "Highest sequence number received from peer", | 183 "Highest sequence number received from peer", |
(...skipping 12 matching lines...) Expand all Loading... |
182 MakeTraceSourceAccessor (&TcpSocketBase::m_ssThTrace), | 196 MakeTraceSourceAccessor (&TcpSocketBase::m_ssThTrace), |
183 "ns3::TracedValueCallback::Uint32") | 197 "ns3::TracedValueCallback::Uint32") |
184 .AddTraceSource ("Tx", | 198 .AddTraceSource ("Tx", |
185 "Send tcp packet to IP protocol", | 199 "Send tcp packet to IP protocol", |
186 MakeTraceSourceAccessor (&TcpSocketBase::m_txTrace), | 200 MakeTraceSourceAccessor (&TcpSocketBase::m_txTrace), |
187 "ns3::TcpSocketBase::TcpTxRxTracedCallback") | 201 "ns3::TcpSocketBase::TcpTxRxTracedCallback") |
188 .AddTraceSource ("Rx", | 202 .AddTraceSource ("Rx", |
189 "Receive tcp packet from IP protocol", | 203 "Receive tcp packet from IP protocol", |
190 MakeTraceSourceAccessor (&TcpSocketBase::m_rxTrace), | 204 MakeTraceSourceAccessor (&TcpSocketBase::m_rxTrace), |
191 "ns3::TcpSocketBase::TcpTxRxTracedCallback") | 205 "ns3::TcpSocketBase::TcpTxRxTracedCallback") |
192 .AddTraceSource ("ECNState", | 206 .AddTraceSource ("EcnEchoSeq", |
193 "Current ECN State of TCP Socket", | |
194 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnState), | |
195 "ns3::EcnStatesTracedValueCallback") | |
196 .AddTraceSource ("ECNEchoSeq", | |
197 "Sequence of last received ECN Echo", | 207 "Sequence of last received ECN Echo", |
198 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnEchoSeq), | 208 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnEchoSeq), |
199 "ns3::SequenceNumber32TracedValueCallback") | 209 "ns3::SequenceNumber32TracedValueCallback") |
200 .AddTraceSource ("ECNCESeq", | 210 .AddTraceSource ("EcnCESeq", |
201 "Sequence of last received CE ", | 211 "Sequence of last received CE ", |
202 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnCESeq), | 212 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnCESeq), |
203 "ns3::SequenceNumber32TracedValueCallback") | 213 "ns3::SequenceNumber32TracedValueCallback") |
204 .AddTraceSource ("ECNCWRSeq", | 214 .AddTraceSource ("EcnCWRSeq", |
205 "Sequence of last received CWR", | 215 "Sequence of last received CWR", |
206 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnCWRSeq), | 216 MakeTraceSourceAccessor (&TcpSocketBase::m_ecnCWRSeq), |
207 "ns3::SequenceNumber32TracedValueCallback") | 217 "ns3::SequenceNumber32TracedValueCallback") |
208 ; | 218 ; |
209 return tid; | 219 return tid; |
210 } | 220 } |
211 | 221 |
212 TypeId | 222 TypeId |
213 TcpSocketBase::GetInstanceTypeId () const | 223 TcpSocketBase::GetInstanceTypeId () const |
214 { | 224 { |
(...skipping 13 matching lines...) Expand all Loading... |
228 MakeTraceSourceAccessor (&TcpSocketState::m_cWnd), | 238 MakeTraceSourceAccessor (&TcpSocketState::m_cWnd), |
229 "ns3::TracedValue::Uint32Callback") | 239 "ns3::TracedValue::Uint32Callback") |
230 .AddTraceSource ("SlowStartThreshold", | 240 .AddTraceSource ("SlowStartThreshold", |
231 "TCP slow start threshold (bytes)", | 241 "TCP slow start threshold (bytes)", |
232 MakeTraceSourceAccessor (&TcpSocketState::m_ssThresh), | 242 MakeTraceSourceAccessor (&TcpSocketState::m_ssThresh), |
233 "ns3::TracedValue::Uint32Callback") | 243 "ns3::TracedValue::Uint32Callback") |
234 .AddTraceSource ("CongState", | 244 .AddTraceSource ("CongState", |
235 "TCP Congestion machine state", | 245 "TCP Congestion machine state", |
236 MakeTraceSourceAccessor (&TcpSocketState::m_congState), | 246 MakeTraceSourceAccessor (&TcpSocketState::m_congState), |
237 "ns3::TracedValue::TcpCongStatesTracedValueCallback") | 247 "ns3::TracedValue::TcpCongStatesTracedValueCallback") |
| 248 .AddTraceSource ("EcnState", |
| 249 "Current ECN State of TCP Socket", |
| 250 MakeTraceSourceAccessor (&TcpSocketState::m_ecnState), |
| 251 "ns3::TracedValue::EcnStatesTracedValueCallback") |
238 .AddTraceSource ("HighestSequence", | 252 .AddTraceSource ("HighestSequence", |
239 "Highest sequence number received from peer", | 253 "Highest sequence number received from peer", |
240 MakeTraceSourceAccessor (&TcpSocketState::m_highTxMark), | 254 MakeTraceSourceAccessor (&TcpSocketState::m_highTxMark), |
241 "ns3::SequenceNumber32TracedValueCallback") | 255 "ns3::SequenceNumber32TracedValueCallback") |
242 .AddTraceSource ("NextTxSequence", | 256 .AddTraceSource ("NextTxSequence", |
243 "Next sequence number to send (SND.NXT)", | 257 "Next sequence number to send (SND.NXT)", |
244 MakeTraceSourceAccessor (&TcpSocketState::m_nextTxSequence)
, | 258 MakeTraceSourceAccessor (&TcpSocketState::m_nextTxSequence)
, |
245 "ns3::SequenceNumber32TracedValueCallback") | 259 "ns3::SequenceNumber32TracedValueCallback") |
246 ; | 260 ; |
247 return tid; | 261 return tid; |
248 } | 262 } |
249 | 263 |
250 TcpSocketState::TcpSocketState (void) | 264 TcpSocketState::TcpSocketState (void) |
251 : Object (), | 265 : Object (), |
252 m_cWnd (0), | 266 m_cWnd (0), |
253 m_ssThresh (0), | 267 m_ssThresh (0), |
254 m_initialCWnd (0), | 268 m_initialCWnd (0), |
255 m_initialSsThresh (0), | 269 m_initialSsThresh (0), |
256 m_segmentSize (0), | 270 m_segmentSize (0), |
257 m_lastAckedSeq (0), | 271 m_lastAckedSeq (0), |
258 m_congState (CA_OPEN), | 272 m_congState (CA_OPEN), |
| 273 m_ecnState (ECN_DISABLED), |
259 m_highTxMark (0), | 274 m_highTxMark (0), |
260 // Change m_nextTxSequence for non-zero initial sequence number | 275 // Change m_nextTxSequence for non-zero initial sequence number |
261 m_nextTxSequence (0) | 276 m_nextTxSequence (0), |
| 277 m_rcvTimestampValue (0), |
| 278 m_rcvTimestampEchoReply (0) |
262 { | 279 { |
263 } | 280 } |
264 | 281 |
265 TcpSocketState::TcpSocketState (const TcpSocketState &other) | 282 TcpSocketState::TcpSocketState (const TcpSocketState &other) |
266 : Object (other), | 283 : Object (other), |
267 m_cWnd (other.m_cWnd), | 284 m_cWnd (other.m_cWnd), |
268 m_ssThresh (other.m_ssThresh), | 285 m_ssThresh (other.m_ssThresh), |
269 m_initialCWnd (other.m_initialCWnd), | 286 m_initialCWnd (other.m_initialCWnd), |
270 m_initialSsThresh (other.m_initialSsThresh), | 287 m_initialSsThresh (other.m_initialSsThresh), |
271 m_segmentSize (other.m_segmentSize), | 288 m_segmentSize (other.m_segmentSize), |
272 m_lastAckedSeq (other.m_lastAckedSeq), | 289 m_lastAckedSeq (other.m_lastAckedSeq), |
273 m_congState (other.m_congState), | 290 m_congState (other.m_congState), |
| 291 m_ecnState (other.m_ecnState), |
274 m_highTxMark (other.m_highTxMark), | 292 m_highTxMark (other.m_highTxMark), |
275 m_nextTxSequence (other.m_nextTxSequence) | 293 m_nextTxSequence (other.m_nextTxSequence), |
| 294 m_rcvTimestampValue (other.m_rcvTimestampValue), |
| 295 m_rcvTimestampEchoReply (other.m_rcvTimestampEchoReply) |
276 { | 296 { |
277 } | 297 } |
278 | 298 |
279 const char* const | 299 const char* const |
280 TcpSocketState::TcpCongStateName[TcpSocketState::CA_LAST_STATE] = | 300 TcpSocketState::TcpCongStateName[TcpSocketState::CA_LAST_STATE] = |
281 { | 301 { |
282 "CA_OPEN", "CA_DISORDER", "CA_CWR", "CA_RECOVERY", "CA_LOSS" | 302 "CA_OPEN", "CA_DISORDER", "CA_CWR", "CA_RECOVERY", "CA_LOSS" |
283 }; | 303 }; |
| 304 |
| 305 const char* const |
| 306 TcpSocketState::EcnStateName[TcpSocketState::ECN_CWR_SENT+1] =· |
| 307 {· |
| 308 "ECN_DISABLED", "ECN_IDLE", "ECN_CE_RCVD", "ECN_ECE_SENT", "ECN_ECE_RCVD", "EC
N_CWR_SENT" |
| 309 }; |
| 310 |
284 | 311 |
285 TcpSocketBase::TcpSocketBase (void) | 312 TcpSocketBase::TcpSocketBase (void) |
286 : TcpSocket (), | 313 : TcpSocket (), |
287 m_retxEvent (), | 314 m_retxEvent (), |
288 m_lastAckEvent (), | 315 m_lastAckEvent (), |
289 m_delAckEvent (), | 316 m_delAckEvent (), |
290 m_persistEvent (), | 317 m_persistEvent (), |
291 m_timewaitEvent (), | 318 m_timewaitEvent (), |
292 m_dupAckCount (0), | 319 m_dupAckCount (0), |
293 m_delAckCount (0), | 320 m_delAckCount (0), |
(...skipping 25 matching lines...) Expand all Loading... |
319 m_shutdownRecv (false), | 346 m_shutdownRecv (false), |
320 m_connected (false), | 347 m_connected (false), |
321 m_msl (0), | 348 m_msl (0), |
322 m_maxWinSize (0), | 349 m_maxWinSize (0), |
323 m_rWnd (0), | 350 m_rWnd (0), |
324 m_highRxMark (0), | 351 m_highRxMark (0), |
325 m_highTxAck (0), | 352 m_highTxAck (0), |
326 m_highRxAckMark (0), | 353 m_highRxAckMark (0), |
327 m_bytesAckedNotProcessed (0), | 354 m_bytesAckedNotProcessed (0), |
328 m_bytesInFlight (0), | 355 m_bytesInFlight (0), |
| 356 m_sackEnabled (false), |
329 m_winScalingEnabled (false), | 357 m_winScalingEnabled (false), |
330 m_rcvWindShift (0), | 358 m_rcvWindShift (0), |
331 m_sndWindShift (0), | 359 m_sndWindShift (0), |
332 m_timestampEnabled (true), | 360 m_timestampEnabled (true), |
333 m_timestampToEcho (0), | 361 m_timestampToEcho (0), |
334 m_sendPendingDataEvent (), | 362 m_sendPendingDataEvent (), |
335 // Set m_recover to the initial sequence number | 363 // Set m_recover to the initial sequence number |
336 m_recover (0), | 364 m_recover (0), |
337 m_retxThresh (3), | 365 m_retxThresh (3), |
338 m_limitedTx (false), | 366 m_limitedTx (false), |
339 m_retransOut (0), | |
340 m_congestionControl (0), | 367 m_congestionControl (0), |
341 m_isFirstPartialAck (true), | 368 m_isFirstPartialAck (true), |
342 m_ecn(false), | 369 m_ecn(false), |
343 m_ecnState (ECN_DISABLED), | |
344 m_ecnEchoSeq (0), | 370 m_ecnEchoSeq (0), |
345 m_ecnCESeq (0), | 371 m_ecnCESeq (0), |
346 m_ecnCWRSeq (0) | 372 m_ecnCWRSeq (0) |
347 { | 373 { |
348 NS_LOG_FUNCTION (this); | 374 NS_LOG_FUNCTION (this); |
349 m_rxBuffer = CreateObject<TcpRxBuffer> (); | 375 m_rxBuffer = CreateObject<TcpRxBuffer> (); |
350 m_txBuffer = CreateObject<TcpTxBuffer> (); | 376 m_txBuffer = CreateObject<TcpTxBuffer> (); |
351 m_tcb = CreateObject<TcpSocketState> (); | 377 m_tcb = CreateObject<TcpSocketState> (); |
352 | 378 |
353 bool ok; | 379 bool ok; |
354 | 380 |
355 ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow", | 381 ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow", |
356 MakeCallback (&TcpSocketBase::UpdateCw
nd, this)); | 382 MakeCallback (&TcpSocketBase::UpdateCw
nd, this)); |
357 NS_ASSERT (ok == true); | 383 NS_ASSERT (ok == true); |
358 | 384 |
359 ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold", | 385 ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold", |
360 MakeCallback (&TcpSocketBase::UpdateSs
Thresh, this)); | 386 MakeCallback (&TcpSocketBase::UpdateSs
Thresh, this)); |
361 NS_ASSERT (ok == true); | 387 NS_ASSERT (ok == true); |
362 | 388 |
363 ok = m_tcb->TraceConnectWithoutContext ("CongState", | 389 ok = m_tcb->TraceConnectWithoutContext ("CongState", |
364 MakeCallback (&TcpSocketBase::UpdateCo
ngState, this)); | 390 MakeCallback (&TcpSocketBase::UpdateCo
ngState, this)); |
| 391 NS_ASSERT (ok == true); |
| 392 |
| 393 ok = m_tcb->TraceConnectWithoutContext ("EcnState", |
| 394 MakeCallback (&TcpSocketBase::UpdateEc
nState, this)); |
365 NS_ASSERT (ok == true); | 395 NS_ASSERT (ok == true); |
366 | 396 |
367 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence", | 397 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence", |
368 MakeCallback (&TcpSocketBase::UpdateNe
xtTxSequence, this)); | 398 MakeCallback (&TcpSocketBase::UpdateNe
xtTxSequence, this)); |
369 NS_ASSERT (ok == true); | 399 NS_ASSERT (ok == true); |
370 | 400 |
371 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence", | 401 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence", |
372 MakeCallback (&TcpSocketBase::UpdateHi
ghTxMark, this)); | 402 MakeCallback (&TcpSocketBase::UpdateHi
ghTxMark, this)); |
373 NS_ASSERT (ok == true); | 403 NS_ASSERT (ok == true); |
374 } | 404 } |
(...skipping 27 matching lines...) Expand all Loading... |
402 m_shutdownSend (sock.m_shutdownSend), | 432 m_shutdownSend (sock.m_shutdownSend), |
403 m_shutdownRecv (sock.m_shutdownRecv), | 433 m_shutdownRecv (sock.m_shutdownRecv), |
404 m_connected (sock.m_connected), | 434 m_connected (sock.m_connected), |
405 m_msl (sock.m_msl), | 435 m_msl (sock.m_msl), |
406 m_maxWinSize (sock.m_maxWinSize), | 436 m_maxWinSize (sock.m_maxWinSize), |
407 m_rWnd (sock.m_rWnd), | 437 m_rWnd (sock.m_rWnd), |
408 m_highRxMark (sock.m_highRxMark), | 438 m_highRxMark (sock.m_highRxMark), |
409 m_highRxAckMark (sock.m_highRxAckMark), | 439 m_highRxAckMark (sock.m_highRxAckMark), |
410 m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed), | 440 m_bytesAckedNotProcessed (sock.m_bytesAckedNotProcessed), |
411 m_bytesInFlight (sock.m_bytesInFlight), | 441 m_bytesInFlight (sock.m_bytesInFlight), |
| 442 m_sackEnabled (sock.m_sackEnabled), |
412 m_winScalingEnabled (sock.m_winScalingEnabled), | 443 m_winScalingEnabled (sock.m_winScalingEnabled), |
413 m_rcvWindShift (sock.m_rcvWindShift), | 444 m_rcvWindShift (sock.m_rcvWindShift), |
414 m_sndWindShift (sock.m_sndWindShift), | 445 m_sndWindShift (sock.m_sndWindShift), |
415 m_timestampEnabled (sock.m_timestampEnabled), | 446 m_timestampEnabled (sock.m_timestampEnabled), |
416 m_timestampToEcho (sock.m_timestampToEcho), | 447 m_timestampToEcho (sock.m_timestampToEcho), |
417 m_recover (sock.m_recover), | 448 m_recover (sock.m_recover), |
418 m_retxThresh (sock.m_retxThresh), | 449 m_retxThresh (sock.m_retxThresh), |
419 m_limitedTx (sock.m_limitedTx), | 450 m_limitedTx (sock.m_limitedTx), |
420 m_retransOut (sock.m_retransOut), | |
421 m_isFirstPartialAck (sock.m_isFirstPartialAck), | 451 m_isFirstPartialAck (sock.m_isFirstPartialAck), |
422 m_txTrace (sock.m_txTrace), | 452 m_txTrace (sock.m_txTrace), |
423 m_rxTrace (sock.m_rxTrace), | 453 m_rxTrace (sock.m_rxTrace), |
424 m_ecn (sock.m_ecn), | 454 m_ecn (sock.m_ecn), |
425 m_ecnState (sock.m_ecnState), | |
426 m_ecnEchoSeq (sock.m_ecnEchoSeq), | 455 m_ecnEchoSeq (sock.m_ecnEchoSeq), |
427 m_ecnCWRSeq (sock.m_ecnCWRSeq)···· | 456 m_ecnCWRSeq (sock.m_ecnCWRSeq)···· |
428 { | 457 { |
429 NS_LOG_FUNCTION (this); | 458 NS_LOG_FUNCTION (this); |
430 NS_LOG_LOGIC ("Invoked the copy constructor"); | 459 NS_LOG_LOGIC ("Invoked the copy constructor"); |
431 // Copy the rtt estimator if it is set | 460 // Copy the rtt estimator if it is set |
432 if (sock.m_rtt) | 461 if (sock.m_rtt) |
433 { | 462 { |
434 m_rtt = sock.m_rtt->Copy (); | 463 m_rtt = sock.m_rtt->Copy (); |
435 } | 464 } |
(...skipping 20 matching lines...) Expand all Loading... |
456 NS_ASSERT (ok == true); | 485 NS_ASSERT (ok == true); |
457 | 486 |
458 ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold", | 487 ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold", |
459 MakeCallback (&TcpSocketBase::UpdateSs
Thresh, this)); | 488 MakeCallback (&TcpSocketBase::UpdateSs
Thresh, this)); |
460 NS_ASSERT (ok == true); | 489 NS_ASSERT (ok == true); |
461 | 490 |
462 ok = m_tcb->TraceConnectWithoutContext ("CongState", | 491 ok = m_tcb->TraceConnectWithoutContext ("CongState", |
463 MakeCallback (&TcpSocketBase::UpdateCo
ngState, this)); | 492 MakeCallback (&TcpSocketBase::UpdateCo
ngState, this)); |
464 NS_ASSERT (ok == true); | 493 NS_ASSERT (ok == true); |
465 | 494 |
| 495 ok = m_tcb->TraceConnectWithoutContext ("EcnState", |
| 496 MakeCallback (&TcpSocketBase::UpdateEc
nState, this)); |
| 497 NS_ASSERT (ok == true); |
| 498 |
466 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence", | 499 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence", |
467 MakeCallback (&TcpSocketBase::UpdateNe
xtTxSequence, this)); | 500 MakeCallback (&TcpSocketBase::UpdateNe
xtTxSequence, this)); |
468 NS_ASSERT (ok == true); | 501 NS_ASSERT (ok == true); |
469 | 502 |
470 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence", | 503 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence", |
471 MakeCallback (&TcpSocketBase::UpdateHi
ghTxMark, this)); | 504 MakeCallback (&TcpSocketBase::UpdateHi
ghTxMark, this)); |
| 505 NS_ASSERT (ok == true); |
472 } | 506 } |
473 | 507 |
474 TcpSocketBase::~TcpSocketBase (void) | 508 TcpSocketBase::~TcpSocketBase (void) |
475 { | 509 { |
476 NS_LOG_FUNCTION (this); | 510 NS_LOG_FUNCTION (this); |
477 m_node = 0; | 511 m_node = 0; |
478 if (m_endPoint != 0) | 512 if (m_endPoint != 0) |
479 { | 513 { |
480 NS_ASSERT (m_tcp != 0); | 514 NS_ASSERT (m_tcp != 0); |
481 /* | 515 /* |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 return m_tcb->m_initialCWnd; | 713 return m_tcb->m_initialCWnd; |
680 } | 714 } |
681 | 715 |
682 /* Inherit from Socket class: Initiate connection to a remote address:port */ | 716 /* Inherit from Socket class: Initiate connection to a remote address:port */ |
683 int | 717 int |
684 TcpSocketBase::Connect (const Address & address) | 718 TcpSocketBase::Connect (const Address & address) |
685 { | 719 { |
686 NS_LOG_FUNCTION (this << address); | 720 NS_LOG_FUNCTION (this << address); |
687 | 721 |
688 // If haven't do so, Bind() this socket first | 722 // If haven't do so, Bind() this socket first |
689 if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0) | 723 if (InetSocketAddress::IsMatchingType (address)) |
690 { | 724 { |
691 if (m_endPoint == 0) | 725 if (m_endPoint == 0) |
692 { | 726 { |
693 if (Bind () == -1) | 727 if (Bind () == -1) |
694 { | 728 { |
695 NS_ASSERT (m_endPoint == 0); | 729 NS_ASSERT (m_endPoint == 0); |
696 return -1; // Bind() failed | 730 return -1; // Bind() failed |
697 } | 731 } |
698 NS_ASSERT (m_endPoint != 0); | 732 NS_ASSERT (m_endPoint != 0); |
699 } | 733 } |
700 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); | 734 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); |
701 m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ()); | 735 m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ()); |
702 SetIpTos (transport.GetTos ()); | 736 SetIpTos (transport.GetTos ()); |
703 m_endPoint6 = 0; | 737 m_endPoint6 = 0; |
704 | 738 |
705 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint | 739 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint |
706 if (SetupEndpoint () != 0) | 740 if (SetupEndpoint () != 0) |
707 { | 741 { |
708 NS_LOG_ERROR ("Route to destination does not exist ?!"); | 742 NS_LOG_ERROR ("Route to destination does not exist ?!"); |
709 return -1; | 743 return -1; |
710 } | 744 } |
711 } | 745 } |
712 else if (Inet6SocketAddress::IsMatchingType (address) && m_endPoint == 0) | 746 else if (Inet6SocketAddress::IsMatchingType (address)) |
713 { | 747 { |
714 // If we are operating on a v4-mapped address, translate the address to | 748 // If we are operating on a v4-mapped address, translate the address to |
715 // a v4 address and re-call this function | 749 // a v4 address and re-call this function |
716 Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address); | 750 Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address); |
717 Ipv6Address v6Addr = transport.GetIpv6 (); | 751 Ipv6Address v6Addr = transport.GetIpv6 (); |
718 if (v6Addr.IsIpv4MappedAddress () == true) | 752 if (v6Addr.IsIpv4MappedAddress () == true) |
719 { | 753 { |
720 Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress (); | 754 Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress (); |
721 return Connect (InetSocketAddress (v4Addr, transport.GetPort ())); | 755 return Connect (InetSocketAddress (v4Addr, transport.GetPort ())); |
722 } | 756 } |
723 | 757 |
724 if (m_endPoint6 == 0) | 758 if (m_endPoint6 == 0) |
725 { | 759 { |
726 if (Bind6 () == -1) | 760 if (Bind6 () == -1) |
727 { | 761 { |
728 NS_ASSERT (m_endPoint6 == 0); | 762 NS_ASSERT (m_endPoint6 == 0); |
729 return -1; // Bind() failed | 763 return -1; // Bind() failed |
730 } | 764 } |
731 NS_ASSERT (m_endPoint6 != 0); | 765 NS_ASSERT (m_endPoint6 != 0); |
732 } | 766 } |
733 m_endPoint6->SetPeer (v6Addr, transport.GetPort ()); | 767 m_endPoint6->SetPeer (v6Addr, transport.GetPort ()); |
734 m_endPoint = 0; | 768 m_endPoint = 0; |
735 | 769 |
736 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint | 770 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint |
737 if (SetupEndpoint6 () != 0) | 771 if (SetupEndpoint6 () != 0) |
738 { // Route to destination does not exist | 772 { |
| 773 NS_LOG_ERROR ("Route to destination does not exist ?!"); |
739 return -1; | 774 return -1; |
740 } | 775 } |
741 } | 776 } |
742 else | 777 else |
743 { | 778 { |
744 m_errno = ERROR_INVAL; | 779 m_errno = ERROR_INVAL; |
745 return -1; | 780 return -1; |
746 } | 781 } |
747 | 782 |
748 // Re-initialize parameters in case this socket is being reused after CLOSE | 783 // Re-initialize parameters in case this socket is being reused after CLOSE |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 m_errno = ERROR_MSGSIZE; | 893 m_errno = ERROR_MSGSIZE; |
859 return -1; | 894 return -1; |
860 } | 895 } |
861 if (m_shutdownSend) | 896 if (m_shutdownSend) |
862 { | 897 { |
863 m_errno = ERROR_SHUTDOWN; | 898 m_errno = ERROR_SHUTDOWN; |
864 return -1; | 899 return -1; |
865 } | 900 } |
866 // Submit the data to lower layers | 901 // Submit the data to lower layers |
867 NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpState
Name[m_state]); | 902 NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpState
Name[m_state]); |
868 if (m_state == ESTABLISHED || m_state == CLOSE_WAIT) | 903 if ((m_state == ESTABLISHED || m_state == CLOSE_WAIT) && AvailableWindow (
) > 0) |
869 { // Try to send the data out | 904 { // Try to send the data out: Add a little step to allow the applicatio
n |
| 905 // to fill the buffer |
870 if (!m_sendPendingDataEvent.IsRunning ()) | 906 if (!m_sendPendingDataEvent.IsRunning ()) |
871 { | 907 { |
872 m_sendPendingDataEvent = Simulator::Schedule (TimeStep (1), | 908 m_sendPendingDataEvent = Simulator::Schedule (TimeStep (1), |
873 &TcpSocketBase::Send
PendingData, | 909 &TcpSocketBase::Send
PendingData, |
874 this, m_connected); | 910 this, m_connected); |
875 } | 911 } |
876 } | 912 } |
877 return p->GetSize (); | 913 return p->GetSize (); |
878 } | 914 } |
879 else | 915 else |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1067 if (m_ecn) | 1103 if (m_ecn) |
1068 { | 1104 { |
1069 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ECE | TcpHeader::CWR); | 1105 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ECE | TcpHeader::CWR); |
1070 } | 1106 } |
1071 else | 1107 else |
1072 { | 1108 { |
1073 SendEmptyPacket (TcpHeader::SYN); | 1109 SendEmptyPacket (TcpHeader::SYN); |
1074 } | 1110 } |
1075 NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT"); | 1111 NS_LOG_DEBUG (TcpStateName[m_state] << " -> SYN_SENT"); |
1076 m_state = SYN_SENT; | 1112 m_state = SYN_SENT; |
1077 m_ecnState = ECN_DISABLED; // because sender is not yet aware about rec
eiver's ECN capability· | 1113 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; // because sender is
not yet aware about receiver's ECN capability· |
1078 } | 1114 } |
1079 else if (m_state != TIME_WAIT) | 1115 else if (m_state != TIME_WAIT) |
1080 { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, a
n connection | 1116 { // In states SYN_RCVD, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, and CLOSING, a
n connection |
1081 // exists. We send RST, tear down everything, and close this socket. | 1117 // exists. We send RST, tear down everything, and close this socket. |
1082 SendRST (); | 1118 SendRST (); |
1083 CloseAndNotify (); | 1119 CloseAndNotify (); |
1084 } | 1120 } |
1085 return 0; | 1121 return 0; |
1086 } | 1122 } |
1087 | 1123 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 ":" << m_endPoint->GetLocalPort ()); | 1215 ":" << m_endPoint->GetLocalPort ()); |
1180 | 1216 |
1181 Address fromAddress = InetSocketAddress (header.GetSource (), port); | 1217 Address fromAddress = InetSocketAddress (header.GetSource (), port); |
1182 Address toAddress = InetSocketAddress (header.GetDestination (), | 1218 Address toAddress = InetSocketAddress (header.GetDestination (), |
1183 m_endPoint->GetLocalPort ()); | 1219 m_endPoint->GetLocalPort ()); |
1184 TcpHeader tcpHeader; | 1220 TcpHeader tcpHeader; |
1185 packet->PeekHeader (tcpHeader); | 1221 packet->PeekHeader (tcpHeader); |
1186 if (header.GetEcn() == Ipv4Header::ECN_CE && m_ecnCESeq < tcpHeader.GetAckNumb
er ()) | 1222 if (header.GetEcn() == Ipv4Header::ECN_CE && m_ecnCESeq < tcpHeader.GetAckNumb
er ()) |
1187 { | 1223 { |
1188 NS_LOG_INFO ("Received CE flag is valid"); | 1224 NS_LOG_INFO ("Received CE flag is valid"); |
1189 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_CE_RCVD"); | 1225 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_
CE_RCVD"); |
1190 m_ecnCESeq = tcpHeader.GetAckNumber (); | 1226 m_ecnCESeq = tcpHeader.GetAckNumber (); |
1191 m_ecnState = ECN_CE_RCVD;· | 1227 m_tcb->m_ecnState = TcpSocketState::ECN_CE_RCVD;· |
1192 } | 1228 } |
1193 DoForwardUp (packet, fromAddress, toAddress); | 1229 DoForwardUp (packet, fromAddress, toAddress); |
1194 } | 1230 } |
1195 | 1231 |
1196 void | 1232 void |
1197 TcpSocketBase::ForwardUp6 (Ptr<Packet> packet, Ipv6Header header, uint16_t port, | 1233 TcpSocketBase::ForwardUp6 (Ptr<Packet> packet, Ipv6Header header, uint16_t port, |
1198 Ptr<Ipv6Interface> incomingInterface) | 1234 Ptr<Ipv6Interface> incomingInterface) |
1199 { | 1235 { |
1200 NS_LOG_LOGIC ("Socket " << this << " forward up " << | 1236 NS_LOG_LOGIC ("Socket " << this << " forward up " << |
1201 m_endPoint6->GetPeerAddress () << | 1237 m_endPoint6->GetPeerAddress () << |
1202 ":" << m_endPoint6->GetPeerPort () << | 1238 ":" << m_endPoint6->GetPeerPort () << |
1203 " to " << m_endPoint6->GetLocalAddress () << | 1239 " to " << m_endPoint6->GetLocalAddress () << |
1204 ":" << m_endPoint6->GetLocalPort ()); | 1240 ":" << m_endPoint6->GetLocalPort ()); |
1205 | 1241 |
1206 Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port); | 1242 Address fromAddress = Inet6SocketAddress (header.GetSourceAddress (), port); |
1207 Address toAddress = Inet6SocketAddress (header.GetDestinationAddress (), | 1243 Address toAddress = Inet6SocketAddress (header.GetDestinationAddress (), |
1208 m_endPoint6->GetLocalPort ()); | 1244 m_endPoint6->GetLocalPort ()); |
1209 | 1245 |
1210 TcpHeader tcpHeader; | 1246 TcpHeader tcpHeader; |
1211 packet->PeekHeader (tcpHeader); | 1247 packet->PeekHeader (tcpHeader); |
1212 if (header.GetEcn() == Ipv6Header::ECN_CE && m_ecnCESeq < tcpHeader.GetAckNumb
er ()) | 1248 if (header.GetEcn() == Ipv6Header::ECN_CE && m_ecnCESeq < tcpHeader.GetAckNumb
er ()) |
1213 { | 1249 { |
1214 NS_LOG_INFO ("Received CE flag is valid"); | 1250 NS_LOG_INFO ("Received CE flag is valid"); |
1215 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_CE_RCVD"); | 1251 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_
CE_RCVD"); |
1216 m_ecnCESeq = tcpHeader.GetAckNumber (); | 1252 m_ecnCESeq = tcpHeader.GetAckNumber (); |
1217 m_ecnState = ECN_CE_RCVD;·· | 1253 m_tcb->m_ecnState = TcpSocketState::ECN_CE_RCVD;·· |
1218 } | 1254 } |
1219 DoForwardUp (packet, fromAddress, toAddress); | 1255 DoForwardUp (packet, fromAddress, toAddress); |
1220 } | 1256 } |
1221 | 1257 |
1222 void | 1258 void |
1223 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, | 1259 TcpSocketBase::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, |
1224 uint8_t icmpType, uint8_t icmpCode, | 1260 uint8_t icmpType, uint8_t icmpCode, |
1225 uint32_t icmpInfo) | 1261 uint32_t icmpInfo) |
1226 { | 1262 { |
1227 NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType
<< | 1263 NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType
<< |
(...skipping 30 matching lines...) Expand all Loading... |
1258 uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader); | 1294 uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader); |
1259 SequenceNumber32 seq = tcpHeader.GetSequenceNumber (); | 1295 SequenceNumber32 seq = tcpHeader.GetSequenceNumber (); |
1260 if (bytesRemoved == 0 || bytesRemoved > 60) | 1296 if (bytesRemoved == 0 || bytesRemoved > 60) |
1261 { | 1297 { |
1262 NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid"); | 1298 NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid"); |
1263 return; // Discard invalid packet | 1299 return; // Discard invalid packet |
1264 } | 1300 } |
1265 else if (packet->GetSize () > 0 && OutOfRange (seq, seq + packet->GetSize ())) | 1301 else if (packet->GetSize () > 0 && OutOfRange (seq, seq + packet->GetSize ())) |
1266 { | 1302 { |
1267 // Discard fully out of range data packets | 1303 // Discard fully out of range data packets |
1268 NS_LOG_LOGIC ("At state " << TcpStateName[m_state] << | 1304 NS_LOG_WARN ("At state " << TcpStateName[m_state] << |
1269 " received packet of seq [" << seq << | 1305 " received packet of seq [" << seq << |
1270 ":" << seq + packet->GetSize () << | 1306 ":" << seq + packet->GetSize () << |
1271 ") out of range [" << m_rxBuffer->NextRxSequence () << ":" <
< | 1307 ") out of range [" << m_rxBuffer->NextRxSequence () << ":" << |
1272 m_rxBuffer->MaxRxSequence () << ")"); | 1308 m_rxBuffer->MaxRxSequence () << ")"); |
1273 // Acknowledgement should be sent for all unacceptable packets (RFC793, p.
69) | 1309 // Acknowledgement should be sent for all unacceptable packets (RFC793, p.
69) |
1274 if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST)) | 1310 if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST)) |
1275 { | 1311 { |
1276 // Check if the sender has responded to ECN echo by reducing the Conge
stion Window | 1312 // Check if the sender has responded to ECN echo by reducing the Conge
stion Window |
1277 if (tcpHeader.GetFlags () & TcpHeader::CWR ) | 1313 if (tcpHeader.GetFlags () & TcpHeader::CWR ) |
1278 { | 1314 { |
1279 // Check if a packet with CE bit set is received. If there is no C
E bit set, then change the state to ECN_IDLE to· | 1315 // Check if a packet with CE bit set is received. If there is no C
E bit set, then change the state to ECN_IDLE to· |
1280 // stop sending ECN Echo messages. If there is CE bit set, the pac
ket should continue sending ECN Echo messages | 1316 // stop sending ECN Echo messages. If there is CE bit set, the pac
ket should continue sending ECN Echo messages |
1281 // | 1317 // |
1282 if (m_ecnState != ECN_CE_RCVD)· | 1318 if (m_tcb->m_ecnState != TcpSocketState::ECN_CE_RCVD)· |
1283 { | 1319 { |
1284 m_ecnState = ECN_IDLE; | 1320 m_tcb->m_ecnState = TcpSocketState::ECN_IDLE; |
1285 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_IDLE"); | 1321 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState]
<< " -> ECN_IDLE"); |
1286 } | 1322 } |
1287 } | 1323 } |
1288 if (m_ecnState == ECN_CE_RCVD || m_ecnState == ECN_ECE_SENT) | 1324 if (m_tcb->m_ecnState == TcpSocketState::ECN_CE_RCVD || m_tcb->m_ecnSt
ate == TcpSocketState::ECN_ECE_SENT) |
1289 { | 1325 { |
1290 // Receiver sets ECE flags when it receives a packet with CE bit o
n or sender hasn’t responded to ECN echo sent by receiver | 1326 // Receiver sets ECE flags when it receives a packet with CE bit o
n or sender hasn’t responded to ECN echo sent by receiver |
1291 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); | 1327 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); |
1292 m_ecnState = ECN_ECE_SENT;·· | 1328 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_SENT;·· |
1293 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_ECE_SENT"); | 1329 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << "
-> ECN_ECE_SENT"); |
1294 } | 1330 } |
1295 else | 1331 else |
1296 { | 1332 { |
1297 SendEmptyPacket (TcpHeader::ACK); | 1333 SendEmptyPacket (TcpHeader::ACK); |
1298 } | 1334 } |
1299 } | 1335 } |
1300 return; | 1336 return; |
1301 } | 1337 } |
1302 | 1338 |
1303 m_rxTrace (packet, tcpHeader, this); | 1339 m_rxTrace (packet, tcpHeader, this); |
1304 | 1340 |
1305 if (tcpHeader.GetFlags () & TcpHeader::SYN) | 1341 if (tcpHeader.GetFlags () & TcpHeader::SYN) |
1306 { | 1342 { |
1307 /* The window field in a segment where the SYN bit is set (i.e., a <SYN> | 1343 /* The window field in a segment where the SYN bit is set (i.e., a <SYN> |
1308 * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be | 1344 * or <SYN,ACK>) MUST NOT be scaled (from RFC 7323 page 9). But should be |
1309 * saved anyway.. | 1345 * saved anyway.. |
1310 */ | 1346 */ |
1311 m_rWnd = tcpHeader.GetWindowSize (); | 1347 m_rWnd = tcpHeader.GetWindowSize (); |
1312 | 1348 |
1313 if (tcpHeader.HasOption (TcpOption::WINSCALE) && m_winScalingEnabled) | 1349 if (tcpHeader.HasOption (TcpOption::WINSCALE) && m_winScalingEnabled) |
1314 { | 1350 { |
1315 ProcessOptionWScale (tcpHeader.GetOption (TcpOption::WINSCALE)); | 1351 ProcessOptionWScale (tcpHeader.GetOption (TcpOption::WINSCALE)); |
1316 } | 1352 } |
1317 else | 1353 else |
1318 { | 1354 { |
1319 m_winScalingEnabled = false; | 1355 m_winScalingEnabled = false; |
| 1356 } |
| 1357 |
| 1358 if (tcpHeader.HasOption (TcpOption::SACKPERMITTED) && m_sackEnabled) |
| 1359 { |
| 1360 ProcessOptionSackPermitted (tcpHeader.GetOption (TcpOption::SACKPERMIT
TED)); |
| 1361 } |
| 1362 else |
| 1363 { |
| 1364 m_sackEnabled = false; |
1320 } | 1365 } |
1321 | 1366 |
1322 // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end | 1367 // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end |
1323 if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled) | 1368 if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled) |
1324 { | 1369 { |
1325 ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), | 1370 ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), |
1326 tcpHeader.GetSequenceNumber ()); | 1371 tcpHeader.GetSequenceNumber ()); |
1327 } | 1372 } |
1328 else | 1373 else |
1329 { | 1374 { |
(...skipping 26 matching lines...) Expand all Loading... |
1356 } | 1401 } |
1357 else | 1402 else |
1358 { | 1403 { |
1359 ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), | 1404 ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), |
1360 tcpHeader.GetSequenceNumber ()); | 1405 tcpHeader.GetSequenceNumber ()); |
1361 } | 1406 } |
1362 } | 1407 } |
1363 | 1408 |
1364 EstimateRtt (tcpHeader); | 1409 EstimateRtt (tcpHeader); |
1365 UpdateWindowSize (tcpHeader); | 1410 UpdateWindowSize (tcpHeader); |
| 1411 |
| 1412 if (!m_sackEnabled |
| 1413 && m_tcb->m_congState != TcpSocketState::CA_LOSS |
| 1414 && !m_persistEvent.IsRunning ()) |
| 1415 { |
| 1416 // Emulate SACK for (old) dupack definition. |
| 1417 // Don't generate block for the persistent window probe |
| 1418 // Don't include the ACK number in any SACK block |
| 1419 if (tcpHeader.GetAckNumber () == m_txBuffer->HeadSequence () |
| 1420 && tcpHeader.GetAckNumber () < m_tcb->m_nextTxSequence) |
| 1421 { |
| 1422 // Dupack following old ns-3 behavior. Craft a special SACK option
. |
| 1423 uint8_t available = tcpHeader.GetMaxOptionLength () - tcpHeader.Ge
tOptionLength (); |
| 1424 Ptr<const TcpOptionSack> sackBlock = m_txBuffer->CraftSackOption (
tcpHeader.GetAckNumber (), available); |
| 1425 if (sackBlock != 0) |
| 1426 { |
| 1427 tcpHeader.AppendOption (sackBlock); |
| 1428 } |
| 1429 } |
| 1430 } |
1366 } | 1431 } |
1367 | 1432 |
1368 | 1433 |
1369 if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ()) | 1434 if (m_rWnd.Get () == 0 && m_persistEvent.IsExpired ()) |
1370 { // Zero window: Enter persist state to send 1 byte to probe | 1435 { // Zero window: Enter persist state to send 1 byte to probe |
1371 NS_LOG_LOGIC (this << " Enter zerowindow persist state"); | 1436 NS_LOG_LOGIC (this << " Enter zerowindow persist state"); |
1372 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir
e at " << | 1437 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir
e at " << |
1373 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).
GetSeconds ()); | 1438 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).
GetSeconds ()); |
1374 m_retxEvent.Cancel (); | 1439 m_retxEvent.Cancel (); |
1375 NS_LOG_LOGIC ("Schedule persist timeout at time " << | 1440 NS_LOG_LOGIC ("Schedule persist timeout at time " << |
(...skipping 16 matching lines...) Expand all Loading... |
1392 case TIME_WAIT: | 1457 case TIME_WAIT: |
1393 // Do nothing | 1458 // Do nothing |
1394 break; | 1459 break; |
1395 case CLOSED: | 1460 case CLOSED: |
1396 // Send RST if the incoming packet is not a RST | 1461 // Send RST if the incoming packet is not a RST |
1397 if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHea
der::RST) | 1462 if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHea
der::RST) |
1398 { // Since m_endPoint is not configured yet, we cannot use SendRST here | 1463 { // Since m_endPoint is not configured yet, we cannot use SendRST here |
1399 TcpHeader h; | 1464 TcpHeader h; |
1400 Ptr<Packet> p = Create<Packet> (); | 1465 Ptr<Packet> p = Create<Packet> (); |
1401 // Send a packet tag for setting ECT bits in IP header | 1466 // Send a packet tag for setting ECT bits in IP header |
1402 if (m_ecnState != ECN_DISABLED ) | 1467 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED ) |
1403 { | 1468 { |
1404 SocketIpTosTag ipTosTag; | 1469 SocketIpTosTag ipTosTag; |
1405 ipTosTag.SetTos (0x02); | 1470 ipTosTag.SetTos (0x02); |
1406 p->AddPacketTag (ipTosTag); | 1471 p->AddPacketTag (ipTosTag); |
1407 ················ | |
1408 SocketIpv6TclassTag ipTclassTag; | 1472 SocketIpv6TclassTag ipTclassTag; |
1409 ipTclassTag.SetTclass (0x02); | 1473 ipTclassTag.SetTclass (0x02); |
1410 p->AddPacketTag (ipTclassTag); | 1474 p->AddPacketTag (ipTclassTag); |
1411 } | 1475 } |
1412 h.SetFlags (TcpHeader::RST); | 1476 h.SetFlags (TcpHeader::RST); |
1413 h.SetSequenceNumber (m_tcb->m_nextTxSequence); | 1477 h.SetSequenceNumber (m_tcb->m_nextTxSequence); |
1414 h.SetAckNumber (m_rxBuffer->NextRxSequence ()); | 1478 h.SetAckNumber (m_rxBuffer->NextRxSequence ()); |
1415 h.SetSourcePort (tcpHeader.GetDestinationPort ()); | 1479 h.SetSourcePort (tcpHeader.GetDestinationPort ()); |
1416 h.SetDestinationPort (tcpHeader.GetSourcePort ()); | 1480 h.SetDestinationPort (tcpHeader.GetSourcePort ()); |
1417 h.SetWindowSize (AdvertisedWindowSize ()); | 1481 h.SetWindowSize (AdvertisedWindowSize ()); |
1418 AddOptions (h); | 1482 AddOptions (h); |
1419 m_txTrace (p, h, this); | 1483 m_txTrace (p, h, this); |
1420 m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice); | 1484 m_tcp->SendPacket (p, h, toAddress, fromAddress, m_boundnetdevice); |
1421 } | 1485 } |
(...skipping 18 matching lines...) Expand all Loading... |
1440 default: // mute compiler | 1504 default: // mute compiler |
1441 break; | 1505 break; |
1442 } | 1506 } |
1443 | 1507 |
1444 if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ()) | 1508 if (m_rWnd.Get () != 0 && m_persistEvent.IsRunning ()) |
1445 { // persist probes end, the other end has increased the window | 1509 { // persist probes end, the other end has increased the window |
1446 NS_ASSERT (m_connected); | 1510 NS_ASSERT (m_connected); |
1447 NS_LOG_LOGIC (this << " Leaving zerowindow persist state"); | 1511 NS_LOG_LOGIC (this << " Leaving zerowindow persist state"); |
1448 m_persistEvent.Cancel (); | 1512 m_persistEvent.Cancel (); |
1449 | 1513 |
1450 // Try to send more data, since window has been updated | 1514 SendPendingData (m_connected); |
1451 if (!m_sendPendingDataEvent.IsRunning ()) | |
1452 { | |
1453 m_sendPendingDataEvent = Simulator::Schedule (TimeStep (1), | |
1454 &TcpSocketBase::SendPend
ingData, | |
1455 this, m_connected); | |
1456 } | |
1457 } | 1515 } |
1458 } | 1516 } |
1459 | 1517 |
1460 /* Received a packet upon ESTABLISHED state. This function is mimicking the | 1518 /* Received a packet upon ESTABLISHED state. This function is mimicking the |
1461 role of tcp_rcv_established() in tcp_input.c in Linux kernel. */ | 1519 role of tcp_rcv_established() in tcp_input.c in Linux kernel. */ |
1462 void | 1520 void |
1463 TcpSocketBase::ProcessEstablished (Ptr<Packet> packet, const TcpHeader& tcpHeade
r) | 1521 TcpSocketBase::ProcessEstablished (Ptr<Packet> packet, const TcpHeader& tcpHeade
r) |
1464 { | 1522 { |
1465 NS_LOG_FUNCTION (this << tcpHeader); | 1523 NS_LOG_FUNCTION (this << tcpHeader); |
1466 | 1524 |
1467 // Extract the flags. PSH, URG, CWR and ECE are not honoured. | 1525 // Extract the flags. PSH, URG, CWR and ECE are not honoured. |
1468 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG |
TcpHeader::CWR | TcpHeader::ECE); | 1526 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG |
TcpHeader::CWR | TcpHeader::ECE); |
1469 | 1527 |
1470 // Different flags are different events | 1528 // Different flags are different events |
1471 if (tcpflags == TcpHeader::ACK) | 1529 if (tcpflags == TcpHeader::ACK) |
1472 { | 1530 { |
1473 if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ()) | 1531 if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ()) |
1474 { | 1532 { |
1475 // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be i
gnored. | 1533 // Case 1: If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be i
gnored. |
1476 // Pag. 72 RFC 793 | 1534 // Pag. 72 RFC 793 |
1477 NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber () << | 1535 NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () << |
1478 " SND.UNA = " << m_txBuffer->HeadSequence ()); | 1536 " SND.UNA = " << m_txBuffer->HeadSequence ()); |
1479 | 1537 |
1480 // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] | 1538 // TODO: RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] |
1481 } | 1539 } |
1482 else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark) | 1540 else if (tcpHeader.GetAckNumber () > m_tcb->m_highTxMark) |
1483 { | 1541 { |
1484 // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then | 1542 // If the ACK acks something not yet sent (SEG.ACK > HighTxMark) then |
1485 // send an ACK, drop the segment, and return. | 1543 // send an ACK, drop the segment, and return. |
1486 // Pag. 72 RFC 793 | 1544 // Pag. 72 RFC 793 |
1487 NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber () << | 1545 NS_LOG_WARN ("Ignored ack of " << tcpHeader.GetAckNumber () << |
1488 " HighTxMark = " << m_tcb->m_highTxMark); | 1546 " HighTxMark = " << m_tcb->m_highTxMark); |
1489 | 1547 |
1490 // Receiver sets ECE flags when it receives a packet with CE bit on or
sender hasn’t responded to ECN echo sent by receiver | 1548 // Receiver sets ECE flags when it receives a packet with CE bit on or
sender hasn’t responded to ECN echo sent by receiver |
1491 if (m_ecnState == ECN_CE_RCVD || m_ecnState == ECN_ECE_SENT) | 1549 if (m_tcb->m_ecnState == TcpSocketState::ECN_CE_RCVD || m_tcb->m_ecnSt
ate == TcpSocketState::ECN_ECE_SENT) |
1492 { | 1550 { |
1493 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); | 1551 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); |
1494 m_ecnState = ECN_ECE_SENT; | 1552 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_SENT; |
1495 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_ECE_SENT"); | 1553 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << "
-> ECN_ECE_SENT"); |
1496 } | 1554 } |
1497 else | 1555 else |
1498 { | 1556 { |
1499 SendEmptyPacket (TcpHeader::ACK); | 1557 SendEmptyPacket (TcpHeader::ACK); |
1500 } | 1558 } |
1501 } | 1559 } |
1502 else | 1560 else |
1503 { | 1561 { |
1504 // SND.UNA < SEG.ACK =< HighTxMark | 1562 // SND.UNA < SEG.ACK =< HighTxMark |
1505 // Pag. 72 RFC 793 | 1563 // Pag. 72 RFC 793 |
1506 ReceivedAck (packet, tcpHeader); | 1564 ReceivedAck (packet, tcpHeader); |
1507 } | 1565 } |
1508 } | 1566 } |
1509 else if (tcpflags == TcpHeader::SYN) | 1567 else if (tcpflags == TcpHeader::SYN) |
(...skipping 20 matching lines...) Expand all Loading... |
1530 { // Received RST or the TCP flags is invalid, in either case, terminate thi
s socket | 1588 { // Received RST or the TCP flags is invalid, in either case, terminate thi
s socket |
1531 if (tcpflags != TcpHeader::RST) | 1589 if (tcpflags != TcpHeader::RST) |
1532 { // this must be an invalid flag, send reset | 1590 { // this must be an invalid flag, send reset |
1533 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <
< " received. Reset packet is sent."); | 1591 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <
< " received. Reset packet is sent."); |
1534 SendRST (); | 1592 SendRST (); |
1535 } | 1593 } |
1536 CloseAndNotify (); | 1594 CloseAndNotify (); |
1537 } | 1595 } |
1538 } | 1596 } |
1539 | 1597 |
| 1598 bool |
| 1599 TcpSocketBase::IsTcpOptionEnabled (uint8_t kind) const |
| 1600 { |
| 1601 NS_LOG_FUNCTION (this << (int)kind); |
| 1602 |
| 1603 switch (kind) |
| 1604 { |
| 1605 case TcpOption::TS: |
| 1606 return m_timestampEnabled; |
| 1607 case TcpOption::WINSCALE: |
| 1608 return m_winScalingEnabled; |
| 1609 case TcpOption::SACKPERMITTED: |
| 1610 case TcpOption::SACK: |
| 1611 return m_sackEnabled; |
| 1612 default: |
| 1613 break; |
| 1614 } |
| 1615 return false; |
| 1616 } |
| 1617 |
| 1618 void |
| 1619 TcpSocketBase::ReadOptions (const TcpHeader &tcpHeader, bool &scoreboardUpdated) |
| 1620 { |
| 1621 NS_LOG_FUNCTION (this << tcpHeader); |
| 1622 TcpHeader::TcpOptionList::const_iterator it; |
| 1623 const TcpHeader::TcpOptionList options = tcpHeader.GetOptionList (); |
| 1624 |
| 1625 for (it = options.begin (); it != options.end (); ++it) |
| 1626 { |
| 1627 const Ptr<const TcpOption> option = (*it); |
| 1628 |
| 1629 // Check only for ACK options here |
| 1630 switch (option->GetKind ()) |
| 1631 { |
| 1632 case TcpOption::SACK: |
| 1633 scoreboardUpdated = ProcessOptionSack (option); |
| 1634 break; |
| 1635 default: |
| 1636 continue; |
| 1637 } |
| 1638 } |
| 1639 } |
| 1640 |
1540 void | 1641 void |
1541 TcpSocketBase::LimitedTransmit () | 1642 TcpSocketBase::LimitedTransmit () |
1542 { | 1643 { |
1543 NS_LOG_FUNCTION (this); | 1644 NS_LOG_FUNCTION (this); |
1544 NS_ASSERT (m_limitedTx); | 1645 NS_ASSERT (m_limitedTx); |
1545 NS_ASSERT (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) > 0); | |
1546 | 1646 |
1547 NS_LOG_INFO ("Limited transmit"); | 1647 NS_LOG_INFO ("Limited transmit"); |
1548 uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, m_tcb->m_segmentSize, t
rue); | 1648 // RFC 6675, Section 5, point 3, continuing : |
1549 m_tcb->m_nextTxSequence += sz; | 1649 // (3.2) Run SetPipe (). |
1550 } | 1650 // (3.3) If (cwnd - pipe) >= 1 SMSS, there exists previously unsent |
1551 | 1651 // data, and the receiver's advertised window allows, transmit |
1552 void | 1652 // up to 1 SMSS of data starting with the octet HighData+1 and |
1553 TcpSocketBase::FastRetransmit () | 1653 // update HighData to reflect this transmission, then return |
| 1654 // to (3.2). |
| 1655 // (3.2) and (3.1) done in SendPendingData |
| 1656 SendPendingData (m_connected); |
| 1657 } |
| 1658 |
| 1659 void |
| 1660 TcpSocketBase::EnterRecovery () |
1554 { | 1661 { |
1555 NS_LOG_FUNCTION (this); | 1662 NS_LOG_FUNCTION (this); |
1556 NS_ASSERT (m_tcb->m_congState != TcpSocketState::CA_RECOVERY); | 1663 NS_ASSERT (m_tcb->m_congState != TcpSocketState::CA_RECOVERY); |
1557 | 1664 |
| 1665 NS_LOG_DEBUG (TcpSocketState::TcpCongStateName[m_tcb->m_congState] << |
| 1666 " -> CA_RECOVERY"); |
| 1667 |
| 1668 // RFC 6675, point (4): |
| 1669 // (4) Invoke fast retransmit and enter loss recovery as follows: |
| 1670 // (4.1) RecoveryPoint = HighData |
1558 m_recover = m_tcb->m_highTxMark; | 1671 m_recover = m_tcb->m_highTxMark; |
| 1672 |
1559 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY); | 1673 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_RECOVERY); |
1560 m_tcb->m_congState = TcpSocketState::CA_RECOVERY; | 1674 m_tcb->m_congState = TcpSocketState::CA_RECOVERY; |
1561 | 1675 |
| 1676 // (4.2) ssthresh = cwnd = (FlightSize / 2) |
1562 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, | 1677 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, |
1563 BytesInFlight ()); | 1678 BytesInFlight ()); |
1564 m_tcb->m_cWnd = m_tcb->m_ssThresh + m_dupAckCount * m_tcb->m_segmentSize; | 1679 m_tcb->m_cWnd = m_tcb->m_ssThresh; |
1565 | 1680 |
1566 NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." << | 1681 NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." << |
1567 "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " << | 1682 "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " << |
1568 m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover); | 1683 m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover); |
| 1684 |
| 1685 // (4.3) Retransmit the first data segment presumed dropped |
1569 DoRetransmit (); | 1686 DoRetransmit (); |
| 1687 // (4.4) Run SetPipe () |
| 1688 // (4.5) Proceed to step (C) |
| 1689 // the step C is done after the ProcessAck function (SendPendingData) |
1570 } | 1690 } |
1571 | 1691 |
1572 void | 1692 void |
1573 TcpSocketBase::DupAck () | 1693 TcpSocketBase::DupAck () |
1574 { | 1694 { |
1575 NS_LOG_FUNCTION (this); | 1695 NS_LOG_FUNCTION (this); |
| 1696 // RFC 6675, Section 5: |
| 1697 // the TCP MUST increase DupAcks by one ... |
| 1698 // NOTE: We count also the dupAcks received in CA_RECOVERY |
1576 ++m_dupAckCount; | 1699 ++m_dupAckCount; |
1577 | 1700 |
1578 if (m_tcb->m_congState == TcpSocketState::CA_OPEN) | 1701 if (m_tcb->m_congState == TcpSocketState::CA_OPEN) |
1579 { | 1702 { |
1580 // From Open we go Disorder | 1703 // From Open we go Disorder |
1581 NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " << | 1704 NS_ASSERT_MSG (m_dupAckCount == 1, "From OPEN->DISORDER but with " << |
1582 m_dupAckCount << " dup ACKs"); | 1705 m_dupAckCount << " dup ACKs"); |
1583 | 1706 |
1584 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_DISORDE
R); | 1707 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_DISORDE
R); |
1585 m_tcb->m_congState = TcpSocketState::CA_DISORDER; | 1708 m_tcb->m_congState = TcpSocketState::CA_DISORDER; |
1586 | 1709 |
1587 NS_LOG_DEBUG ("OPEN -> DISORDER"); | 1710 NS_LOG_DEBUG ("OPEN -> DISORDER"); |
1588 } | 1711 } |
1589 | 1712 |
1590 if (m_tcb->m_congState == TcpSocketState::CA_DISORDER) | 1713 if (m_tcb->m_congState == TcpSocketState::CA_DISORDER) |
1591 { | 1714 { |
| 1715 // RFC 6675, Section 5, continuing: |
| 1716 // ... and take the following steps: |
| 1717 // (1) If DupAcks >= DupThresh, go to step (4). |
1592 if ((m_dupAckCount == m_retxThresh) && (m_highRxAckMark >= m_recover)) | 1718 if ((m_dupAckCount == m_retxThresh) && (m_highRxAckMark >= m_recover)) |
1593 { | 1719 { |
1594 // triple duplicate ack triggers fast retransmit (RFC2582 sec.3 bullet
#1) | 1720 EnterRecovery (); |
1595 NS_LOG_DEBUG (TcpSocketState::TcpCongStateName[m_tcb->m_congState] << | 1721 NS_ASSERT (m_tcb->m_congState == TcpSocketState::CA_RECOVERY); |
1596 " -> RECOVERY"); | 1722 } |
1597 FastRetransmit (); | 1723 // (2) If DupAcks < DupThresh but IsLost (HighACK + 1) returns true |
1598 } | 1724 // (indicating at least three segments have arrived above the current |
1599 else if (m_limitedTx && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSeque
nce) > 0) | 1725 // cumulative acknowledgment point, which is taken to indicate loss) |
1600 { | 1726 // go to step (4). |
1601 // RFC3042 Limited transmit: Send a new packet for each duplicated ACK
before fast retransmit | 1727 else if (m_txBuffer->IsLost (m_highRxAckMark + 1, m_retxThresh, m_tcb->m_s
egmentSize)) |
1602 LimitedTransmit (); | 1728 { |
1603 } | 1729 EnterRecovery (); |
1604 } | 1730 NS_ASSERT (m_tcb->m_congState == TcpSocketState::CA_RECOVERY); |
1605 else if (m_tcb->m_congState == TcpSocketState::CA_RECOVERY) | 1731 } |
1606 { // Increase cwnd for every additional dupack (RFC2582, sec.3 bullet #3) | 1732 else |
1607 m_tcb->m_cWnd += m_tcb->m_segmentSize; | 1733 { |
1608 NS_LOG_INFO (m_dupAckCount << " Dupack received in fast recovery mode." | 1734 // (3) The TCP MAY transmit previously unsent data segments as per |
1609 "Increase cwnd to " << m_tcb->m_cWnd); | 1735 // Limited Transmit [RFC5681] ...except that the number of octets |
1610 SendPendingData (m_connected); | 1736 // which may be sent is governed by pipe and cwnd as follows: |
1611 } | 1737 // |
1612 | 1738 // (3.1) Set HighRxt to HighACK. |
1613 // Artificially call PktsAcked. After all, one segment has been ACKed. | 1739 // Not clear in RFC. We don't do this here, since we still have |
1614 m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt); | 1740 // to retransmit the segment. |
| 1741 |
| 1742 NS_ASSERT (m_dupAckCount < m_retxThresh); |
| 1743 if (m_limitedTx) |
| 1744 { |
| 1745 // (3.2) and (3.3) are performed in the following: |
| 1746 LimitedTransmit (); |
| 1747 } |
| 1748 // (3.4) Terminate processing of this ACK. |
| 1749 } |
| 1750 } |
| 1751 |
| 1752 if (m_dupAckCount > 0) |
| 1753 { |
| 1754 NS_ASSERT (m_tcb->m_congState > TcpSocketState::CA_OPEN); |
| 1755 } |
1615 } | 1756 } |
1616 | 1757 |
1617 /* Process the newly received ACK */ | 1758 /* Process the newly received ACK */ |
1618 void | 1759 void |
1619 TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader) | 1760 TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader) |
1620 { | 1761 { |
1621 NS_LOG_FUNCTION (this << tcpHeader); | 1762 NS_LOG_FUNCTION (this << tcpHeader); |
1622 | 1763 |
1623 NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK)); | 1764 NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK)); |
1624 NS_ASSERT (m_tcb->m_segmentSize > 0); | 1765 NS_ASSERT (m_tcb->m_segmentSize > 0); |
1625 | 1766 |
| 1767 // RFC 6675, Section 5, 1st paragraph: |
| 1768 // Upon the receipt of any ACK containing SACK information, the |
| 1769 // scoreboard MUST be updated via the Update () routine (done in ReadOptions) |
| 1770 bool scoreboardUpdated = false; |
| 1771 ReadOptions (tcpHeader, scoreboardUpdated); |
| 1772 |
1626 SequenceNumber32 ackNumber = tcpHeader.GetAckNumber (); | 1773 SequenceNumber32 ackNumber = tcpHeader.GetAckNumber (); |
1627 | 1774 |
1628 NS_LOG_DEBUG ("ACK of " << ackNumber << | 1775 if (ackNumber > m_txBuffer->HeadSequence () && (m_tcb->m_ecnState != TcpSocket
State::ECN_DISABLED) && (tcpHeader.GetFlags () & TcpHeader::ECE)) |
1629 " SND.UNA=" << m_txBuffer->HeadSequence () << | |
1630 " SND.NXT=" << m_tcb->m_nextTxSequence); | |
1631 | |
1632 m_tcb->m_lastAckedSeq = ackNumber; | |
1633 | |
1634 if (ackNumber == m_txBuffer->HeadSequence () | |
1635 && ackNumber < m_tcb->m_nextTxSequence | |
1636 && packet->GetSize () == 0) | |
1637 { | |
1638 // There is a DupAck | |
1639 DupAck (); | |
1640 } | |
1641 else if (ackNumber == m_txBuffer->HeadSequence () | |
1642 && ackNumber == m_tcb->m_nextTxSequence) | |
1643 { | |
1644 // Dupack, but the ACK is precisely equal to the nextTxSequence | |
1645 } | |
1646 else if (ackNumber > m_txBuffer->HeadSequence ()) | |
1647 { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer | |
1648 bool callCongestionControl = true; | |
1649 bool resetRTO = true; | |
1650 uint32_t bytesAcked = ackNumber - m_txBuffer->HeadSequence (); | |
1651 uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize; | |
1652 m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize; | |
1653 | |
1654 if (m_bytesAckedNotProcessed >= m_tcb->m_segmentSize) | |
1655 { | |
1656 segsAcked += 1; | |
1657 m_bytesAckedNotProcessed -= m_tcb->m_segmentSize; | |
1658 } | |
1659 | |
1660 NS_LOG_LOGIC (" Bytes acked: " << bytesAcked << | |
1661 " Segments acked: " << segsAcked << | |
1662 " bytes left: " << m_bytesAckedNotProcessed); | |
1663 | |
1664 if ((m_ecnState != ECN_DISABLED) && (tcpHeader.GetFlags () & TcpHeader::EC
E)) | |
1665 { | 1776 { |
1666 if (m_ecnEchoSeq < tcpHeader.GetAckNumber ()) | 1777 if (m_ecnEchoSeq < tcpHeader.GetAckNumber ()) |
1667 { | 1778 { |
1668 NS_LOG_INFO ("Received ECN Echo is valid"); | 1779 NS_LOG_INFO ("Received ECN Echo is valid"); |
1669 m_ecnEchoSeq = tcpHeader.GetAckNumber (); | 1780 m_ecnEchoSeq = tcpHeader.GetAckNumber (); |
1670 m_ecnState = ECN_ECE_RCVD; | 1781 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_RCVD; |
1671 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_ECE_RCVD"); | 1782 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << "
-> ECN_ECE_RCVD"); |
1672 } | 1783 } |
1673 } | 1784 } |
1674 | 1785 |
1675 /* The following switch is made because m_dupAckCount can be | 1786 // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation |
1676 * "inflated" through out-of-order segments (e.g. from retransmission, | 1787 // are inside the function ProcessAck |
1677 * while segments have not been lost but are network-reordered). At | 1788 ProcessAck (ackNumber, scoreboardUpdated); |
1678 * least one segment has been acked; in the luckiest case, an amount | 1789 |
1679 * equals to segsAcked-m_dupAckCount has not been processed. | 1790 // RFC 6675, Section 5, point (C), try to send more data. NB: (C) is implement
ed |
1680 * | 1791 // inside SendPendingData |
1681 * To be clear: segsAcked will be passed to PktsAcked, and it should take | 1792 SendPendingData (m_connected); |
1682 * in considerations the times that it has been already called, while newS
egsAcked | 1793 |
1683 * will be passed to IncreaseCwnd, and it represents the amount of | 1794 // If there is any data piggybacked, store it into m_rxBuffer |
1684 * segments that are allowed to increase the cWnd value. | 1795 if (packet->GetSize () > 0) |
1685 */ | 1796 { |
1686 uint32_t newSegsAcked = segsAcked; | 1797 ReceivedData (packet, tcpHeader); |
1687 if (segsAcked > m_dupAckCount) | 1798 } |
1688 { | 1799 } |
1689 segsAcked -= m_dupAckCount; | 1800 |
| 1801 void |
| 1802 TcpSocketBase::ProcessAck (const SequenceNumber32 &ackNumber, bool scoreboardUpd
ated) |
| 1803 { |
| 1804 NS_LOG_FUNCTION (this << ackNumber << scoreboardUpdated); |
| 1805 // RFC 6675, Section 5, 2nd paragraph: |
| 1806 // If the incoming ACK is a cumulative acknowledgment, the TCP MUST |
| 1807 // reset DupAcks to zero. |
| 1808 uint32_t oldDupAckCount = m_dupAckCount; // remember the old value |
| 1809 if (ackNumber > m_txBuffer->HeadSequence ()) |
| 1810 { |
| 1811 m_dupAckCount = 0; |
| 1812 } |
| 1813 |
| 1814 m_tcb->m_lastAckedSeq = ackNumber; // Update lastAckedSeq |
| 1815 |
| 1816 /* In RFC 5681 the definition of duplicate acknowledgment was strict: |
| 1817 * |
| 1818 * (a) the receiver of the ACK has outstanding data, |
| 1819 * (b) the incoming acknowledgment carries no data, |
| 1820 * (c) the SYN and FIN bits are both off, |
| 1821 * (d) the acknowledgment number is equal to the greatest acknowledgment |
| 1822 * received on the given connection (TCP.UNA from [RFC793]), |
| 1823 * (e) the advertised window in the incoming acknowledgment equals the |
| 1824 * advertised window in the last incoming acknowledgment. |
| 1825 * |
| 1826 * With RFC 6675, this definition has been reduced: |
| 1827 * |
| 1828 * (a) the ACK is carrying a SACK block that identifies previously |
| 1829 * unacknowledged and un-SACKed octets between HighACK (TCP.UNA) and |
| 1830 * HighData (m_highTxMark) |
| 1831 */ |
| 1832 // RFC 6675, Section 5, 3rd paragraph: |
| 1833 // If the incoming ACK is a duplicate acknowledgment per the definition |
| 1834 // in Section 2 (regardless of its status as a cumulative |
| 1835 // acknowledgment), and the TCP is not currently in loss recovery |
| 1836 if (scoreboardUpdated) |
| 1837 { |
| 1838 NS_LOG_DEBUG ("ACK of " << ackNumber << |
| 1839 " SND.UNA=" << m_txBuffer->HeadSequence () << |
| 1840 " SND.NXT=" << m_tcb->m_nextTxSequence << |
| 1841 " we are ready to process the dupAck"); |
| 1842 // loss recovery check is done inside this function thanks to |
| 1843 // the congestion state machine |
| 1844 DupAck (); |
| 1845 } |
| 1846 |
| 1847 if (ackNumber == m_txBuffer->HeadSequence () |
| 1848 && ackNumber == m_tcb->m_nextTxSequence) |
| 1849 { |
| 1850 NS_LOG_INFO ("ACK of " << ackNumber << |
| 1851 ", there is no need to process (we haven't data to transmit)"
); |
| 1852 // Dupack, but the ACK is precisely equal to the nextTxSequence |
| 1853 return; |
| 1854 } |
| 1855 else if (ackNumber == m_txBuffer->HeadSequence () |
| 1856 && ackNumber > m_tcb->m_nextTxSequence) |
| 1857 { |
| 1858 // ACK of the FIN bit ... nextTxSequence is not updated since we |
| 1859 // don't have anything to transmit |
| 1860 NS_LOG_DEBUG ("Update nextTxSequence manually to " << ackNumber); |
| 1861 m_tcb->m_nextTxSequence = ackNumber; |
| 1862 } |
| 1863 else if (ackNumber == m_txBuffer->HeadSequence ()) |
| 1864 { |
| 1865 // DupAck. Artificially call PktsAcked: after all, one segment has been AC
Ked. |
| 1866 NS_LOG_INFO ("ACK of " << ackNumber << ", PktsAcked called (ACK already ma
naged in DupAck)"); |
| 1867 m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt); |
| 1868 } |
| 1869 else if (ackNumber > m_txBuffer->HeadSequence ()) |
| 1870 { |
| 1871 uint32_t bytesAcked = ackNumber - m_txBuffer->HeadSequence (); |
| 1872 uint32_t segsAcked = bytesAcked / m_tcb->m_segmentSize; |
| 1873 m_bytesAckedNotProcessed += bytesAcked % m_tcb->m_segmentSize; |
| 1874 |
| 1875 if (m_bytesAckedNotProcessed >= m_tcb->m_segmentSize) |
| 1876 { |
| 1877 segsAcked += 1; |
| 1878 m_bytesAckedNotProcessed -= m_tcb->m_segmentSize; |
| 1879 } |
| 1880 |
| 1881 // RFC 6675, Section 5, part (B) |
| 1882 // (B) Upon receipt of an ACK that does not cover RecoveryPoint, the |
| 1883 // following actions MUST be taken: |
| 1884 // |
| 1885 // (B.1) Use Update () to record the new SACK information conveyed |
| 1886 // by the incoming ACK. |
| 1887 // (B.2) Use SetPipe () to re-calculate the number of octets still |
| 1888 // in the network. |
| 1889 // |
| 1890 // (B.1) is done at the beginning, while (B.2) is delayed to part (C) whil
e |
| 1891 // trying to transmit with SendPendingData. We are not allowed to exit |
| 1892 // the CA_RECOVERY phase. Just process this partial ack (RFC 5681) |
| 1893 if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA_RECO
VERY) |
| 1894 { |
| 1895 m_txBuffer->DiscardUpTo (ackNumber); |
| 1896 DoRetransmit (); // Assume the next seq is lost. Retransmit lost packe
t |
| 1897 |
| 1898 // This partial ACK acknowledge the fact that one segment has been |
| 1899 // previously lost and now successfully received. All others have |
| 1900 // been processed when they come under the form of dupACKs |
| 1901 m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt); |
| 1902 NewAck (ackNumber, m_isFirstPartialAck); |
| 1903 |
| 1904 if (m_isFirstPartialAck) |
| 1905 { |
| 1906 NS_LOG_DEBUG ("Partial ACK of " << ackNumber << |
| 1907 " and this is the first (RTO will be reset)"); |
| 1908 m_isFirstPartialAck = false; |
| 1909 } |
| 1910 else |
| 1911 { |
| 1912 NS_LOG_DEBUG ("Partial ACK of " << ackNumber << |
| 1913 " and this is NOT the first (RTO will not be reset)"
); |
| 1914 } |
| 1915 } |
| 1916 // From RFC 6675 section 5.1 |
| 1917 // In addition, a new recovery phase (as described in Section 5) MUST NOT |
| 1918 // be initiated until HighACK is greater than or equal to the new value |
| 1919 // of RecoveryPoint. |
| 1920 else if (ackNumber < m_recover && m_tcb->m_congState == TcpSocketState::CA
_LOSS) |
| 1921 { |
| 1922 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); |
| 1923 |
| 1924 m_congestionControl->IncreaseWindow (m_tcb, segsAcked); |
| 1925 |
| 1926 NS_LOG_DEBUG ("Ack of " << ackNumber << ", equivalent of " << segsAcke
d << |
| 1927 " segments in CA_LOSS. Cong Control Called, cWnd=" << m_
tcb->m_cWnd << |
| 1928 " ssTh=" << m_tcb->m_ssThresh); |
| 1929 |
| 1930 NewAck (ackNumber, true); |
1690 } | 1931 } |
1691 else | 1932 else |
1692 { | 1933 { |
1693 segsAcked = 1; | 1934 if (m_tcb->m_congState == TcpSocketState::CA_OPEN) |
1694 } | |
1695 | |
1696 if (m_tcb->m_congState == TcpSocketState::CA_OPEN) | |
1697 { | |
1698 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); | |
1699 } | |
1700 else if (m_tcb->m_congState == TcpSocketState::CA_DISORDER) | |
1701 { | |
1702 // The network reorder packets. Linux changes the counting lost | |
1703 // packet algorithm from FACK to NewReno. We simply go back in Open. | |
1704 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPE
N); | |
1705 m_tcb->m_congState = TcpSocketState::CA_OPEN; | |
1706 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); | |
1707 m_dupAckCount = 0; | |
1708 m_retransOut = 0; | |
1709 | |
1710 NS_LOG_DEBUG ("DISORDER -> OPEN"); | |
1711 } | |
1712 else if (m_tcb->m_congState == TcpSocketState::CA_RECOVERY) | |
1713 { | |
1714 if (ackNumber < m_recover) | |
1715 { | 1935 { |
1716 /* Partial ACK. | 1936 NS_LOG_DEBUG (segsAcked << " segments acked in CA_OPEN, ack of " <
< |
1717 * In case of partial ACK, retransmit the first unacknowledged | 1937 ackNumber); |
1718 * segment. Deflate the congestion window by the amount of new | 1938 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); |
1719 * data acknowledged by the Cumulative Acknowledgment field. | 1939 } |
1720 * If the partial ACK acknowledges at least one SMSS of new data, | 1940 else if (m_tcb->m_congState == TcpSocketState::CA_DISORDER) |
1721 * then add back SMSS bytes to the congestion window. | 1941 { |
1722 * This artificially inflates the congestion window in order to | 1942 // The network reorder packets. Linux changes the counting lost |
1723 * reflect the additional segment that has left the network. | 1943 // packet algorithm from FACK to NewReno. We simply go back in Ope
n. |
1724 * Send a new segment if permitted by the new value of cwnd. | 1944 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA
_OPEN); |
1725 * This "partial window deflation" attempts to ensure that, when | 1945 m_tcb->m_congState = TcpSocketState::CA_OPEN; |
1726 * fast recovery eventually ends, approximately ssthresh amount | 1946 if (segsAcked >= oldDupAckCount) |
1727 * of data will be outstanding in the network. Do not exit the | |
1728 * fast recovery procedure (i.e., if any duplicate ACKs subsequent
ly | |
1729 * arrive, execute step 4 of Section 3.2 of [RFC5681]). | |
1730 */ | |
1731 m_tcb->m_cWnd = SafeSubtraction (m_tcb->m_cWnd, bytesAcked); | |
1732 | |
1733 if (segsAcked >= 1) | |
1734 { | 1947 { |
1735 m_tcb->m_cWnd += m_tcb->m_segmentSize; | 1948 m_congestionControl->PktsAcked (m_tcb, segsAcked - oldDupAckCo
unt, m_lastRtt); |
1736 } | |
1737 | |
1738 callCongestionControl = false; // No congestion control on cWnd sh
ow be invoked | |
1739 m_dupAckCount = SafeSubtraction (m_dupAckCount, segsAcked); // Upd
ate the dupAckCount | |
1740 m_retransOut = SafeSubtraction (m_retransOut, 1); // at least on
e retransmission | |
1741 // has reached
the other side | |
1742 m_txBuffer->DiscardUpTo (ackNumber); //Bug 1850: retransmit befo
re newack | |
1743 DoRetransmit (); // Assume the next seq is lost. Retransmit lost p
acket | |
1744 | |
1745 if (m_isFirstPartialAck) | |
1746 { | |
1747 m_isFirstPartialAck = false; | |
1748 } | 1949 } |
1749 else | 1950 else |
1750 { | 1951 { |
1751 resetRTO = false; | 1952 NS_ASSERT (oldDupAckCount - segsAcked == 1); |
1752 } | 1953 } |
1753 | 1954 NS_LOG_DEBUG (segsAcked << " segments acked in CA_DISORDER, ack of
" << |
1754 /* This partial ACK acknowledge the fact that one segment has been | 1955 ackNumber << " exiting CA_DISORDER -> CA_OPEN"); |
1755 * previously lost and now successfully received. All others have | |
1756 * been processed when they come under the form of dupACKs | |
1757 */ | |
1758 m_congestionControl->PktsAcked (m_tcb, 1, m_lastRtt); | |
1759 | |
1760 NS_LOG_INFO ("Partial ACK for seq " << ackNumber << | |
1761 " in fast recovery: cwnd set to " << m_tcb->m_cWnd << | |
1762 " recover seq: " << m_recover << | |
1763 " dupAck count: " << m_dupAckCount); | |
1764 } | 1956 } |
1765 else if (ackNumber >= m_recover) | 1957 // RFC 6675, Section 5: |
1766 { // Full ACK (RFC2582 sec.3 bullet #5 paragraph 2, option 1) | 1958 // Once a TCP is in the loss recovery phase, the following procedure |
1767 m_tcb->m_cWnd = std::min (m_tcb->m_ssThresh.Get (), | 1959 // MUST be used for each arriving ACK: |
1768 BytesInFlight () + m_tcb->m_segmentSize)
; | 1960 // (A) An incoming cumulative ACK for a sequence number greater than |
| 1961 // RecoveryPoint signals the end of loss recovery, and the loss |
| 1962 // recovery phase MUST be terminated. Any information contained in |
| 1963 // the scoreboard for sequence numbers greater than the new value of |
| 1964 // HighACK SHOULD NOT be cleared when leaving the loss recovery |
| 1965 // phase. |
| 1966 else if (m_tcb->m_congState == TcpSocketState::CA_RECOVERY) |
| 1967 { |
1769 m_isFirstPartialAck = true; | 1968 m_isFirstPartialAck = true; |
1770 m_dupAckCount = 0; | 1969 |
1771 m_retransOut = 0; | 1970 // Recalculate the segs acked, that are from m_recover to ackNumbe
r |
1772 | 1971 // (which are the ones we have not passed to PktsAcked and that |
1773 /* This FULL ACK acknowledge the fact that one segment has been | 1972 // can increase cWnd) |
1774 * previously lost and now successfully received. All others have | 1973 segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize; |
1775 * been processed when they come under the form of dupACKs, | |
1776 * except the (maybe) new ACKs which come from a new window | |
1777 */ | |
1778 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); | 1974 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); |
1779 newSegsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize; | 1975 |
1780 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA
_OPEN); | 1976 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA
_OPEN); |
1781 m_tcb->m_congState = TcpSocketState::CA_OPEN; | 1977 m_tcb->m_congState = TcpSocketState::CA_OPEN; |
1782 | 1978 |
1783 NS_LOG_INFO ("Received full ACK for seq " << ackNumber << | 1979 NS_LOG_DEBUG (segsAcked << " segments acked in CA_RECOVER, ack of
" << |
1784 ". Leaving fast recovery with cwnd set to " << m_tcb-
>m_cWnd); | 1980 ackNumber << ", exiting CA_RECOVERY -> CA_OPEN"); |
1785 NS_LOG_DEBUG ("RECOVERY -> OPEN"); | |
1786 } | 1981 } |
1787 } | 1982 else if (m_tcb->m_congState == TcpSocketState::CA_LOSS) |
1788 else if (m_tcb->m_congState == TcpSocketState::CA_LOSS) | |
1789 { | |
1790 // Go back in OPEN state | |
1791 m_isFirstPartialAck = true; | |
1792 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); | |
1793 m_dupAckCount = 0; | |
1794 m_retransOut = 0; | |
1795 if(ackNumber >= m_recover + 1) | |
1796 { | 1983 { |
| 1984 m_isFirstPartialAck = true; |
| 1985 |
| 1986 // Recalculate the segs acked, that are from m_recover to ackNumbe
r |
| 1987 // (which are the ones we have not passed to PktsAcked and that |
| 1988 // can increase cWnd) |
| 1989 segsAcked = (ackNumber - m_recover) / m_tcb->m_segmentSize; |
| 1990 |
| 1991 m_congestionControl->PktsAcked (m_tcb, segsAcked, m_lastRtt); |
| 1992 |
1797 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA
_OPEN); | 1993 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA
_OPEN); |
1798 m_tcb->m_congState = TcpSocketState::CA_OPEN; | 1994 m_tcb->m_congState = TcpSocketState::CA_OPEN; |
1799 NS_LOG_DEBUG ("LOSS -> OPEN"); | 1995 NS_LOG_DEBUG (segsAcked << " segments acked in CA_LOSS, ack of" << |
| 1996 ackNumber << ", exiting CA_LOSS -> CA_OPEN"); |
1800 } | 1997 } |
1801 } | 1998 |
1802 | 1999 m_congestionControl->IncreaseWindow (m_tcb, segsAcked); |
1803 if (callCongestionControl) | 2000 m_dupAckCount = 0; |
1804 { | |
1805 m_congestionControl->IncreaseWindow (m_tcb, newSegsAcked); | |
1806 | 2001 |
1807 NS_LOG_LOGIC ("Congestion control called: " << | 2002 NS_LOG_LOGIC ("Congestion control called: " << |
1808 " cWnd: " << m_tcb->m_cWnd << | 2003 " cWnd: " << m_tcb->m_cWnd << |
1809 " ssTh: " << m_tcb->m_ssThresh); | 2004 " ssTh: " << m_tcb->m_ssThresh); |
1810 } | 2005 |
1811 | 2006 NewAck (ackNumber, true); |
1812 // Reset the data retransmission count. We got a new ACK! | 2007 } |
1813 m_dataRetrCount = m_dataRetries; | |
1814 | |
1815 if (m_isFirstPartialAck == false) | |
1816 { | |
1817 NS_ASSERT (m_tcb->m_congState == TcpSocketState::CA_RECOVERY); | |
1818 } | |
1819 | |
1820 NewAck (ackNumber, resetRTO); | |
1821 | |
1822 // Try to send more data | |
1823 if (!m_sendPendingDataEvent.IsRunning ()) | |
1824 { | |
1825 m_sendPendingDataEvent = Simulator::Schedule (TimeStep (1), | |
1826 &TcpSocketBase::SendPend
ingData, | |
1827 this, m_connected); | |
1828 } | |
1829 } | |
1830 | |
1831 // If there is any data piggybacked, store it into m_rxBuffer | |
1832 if (packet->GetSize () > 0) | |
1833 { | |
1834 ReceivedData (packet, tcpHeader); | |
1835 } | 2008 } |
1836 } | 2009 } |
1837 | 2010 |
1838 /* Received a packet upon LISTEN state. */ | 2011 /* Received a packet upon LISTEN state. */ |
1839 void | 2012 void |
1840 TcpSocketBase::ProcessListen (Ptr<Packet> packet, const TcpHeader& tcpHeader, | 2013 TcpSocketBase::ProcessListen (Ptr<Packet> packet, const TcpHeader& tcpHeader, |
1841 const Address& fromAddress, const Address& toAddre
ss) | 2014 const Address& fromAddress, const Address& toAddre
ss) |
1842 { | 2015 { |
1843 NS_LOG_FUNCTION (this << tcpHeader); | 2016 NS_LOG_FUNCTION (this << tcpHeader); |
1844 | 2017 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 m_synCount = m_synRetries; | 2068 m_synCount = m_synRetries; |
1896 m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNu
mber32 (1)); | 2069 m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNu
mber32 (1)); |
1897 | 2070 |
1898 /* Check if we recieved an ECN SYN packet. Change the ECN state of receive
r to ECN_IDLE if the traffic is ECN capable and· | 2071 /* Check if we recieved an ECN SYN packet. Change the ECN state of receive
r to ECN_IDLE if the traffic is ECN capable and· |
1899 * sender has sent ECN SYN packet | 2072 * sender has sent ECN SYN packet |
1900 */ | 2073 */ |
1901 if (m_ecn && (tcpHeader.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) =
= (TcpHeader::CWR | TcpHeader::ECE)) | 2074 if (m_ecn && (tcpHeader.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) =
= (TcpHeader::CWR | TcpHeader::ECE)) |
1902 { | 2075 { |
1903 NS_LOG_INFO ("Received ECN SYN packet"); | 2076 NS_LOG_INFO ("Received ECN SYN packet"); |
1904 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK | TcpHeader::ECE); | 2077 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK | TcpHeader::ECE); |
1905 m_ecnState = ECN_IDLE; | 2078 m_tcb->m_ecnState = TcpSocketState::ECN_IDLE; |
1906 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_IDLE"); | 2079 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " ->
ECN_IDLE"); |
1907 } | 2080 } |
1908 else | 2081 else |
1909 { | 2082 { |
1910 m_ecnState = ECN_DISABLED; | 2083 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; |
1911 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);···· | 2084 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);···· |
1912 } | 2085 } |
1913 } | 2086 } |
1914 else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK) | 2087 else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK) |
1915 && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAck
Number ()) | 2088 && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAck
Number ()) |
1916 { // Handshake completed | 2089 { // Handshake completed |
1917 NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED"); | 2090 NS_LOG_DEBUG ("SYN_SENT -> ESTABLISHED"); |
1918 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN); | 2091 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN); |
1919 m_state = ESTABLISHED; | 2092 m_state = ESTABLISHED; |
1920 m_connected = true; | 2093 m_connected = true; |
1921 m_retxEvent.Cancel (); | 2094 m_retxEvent.Cancel (); |
1922 m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNu
mber32 (1)); | 2095 m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNu
mber32 (1)); |
1923 m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence; | 2096 m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence; |
1924 m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence); | 2097 m_txBuffer->SetHeadSequence (m_tcb->m_nextTxSequence); |
1925 SendEmptyPacket (TcpHeader::ACK); | 2098 SendEmptyPacket (TcpHeader::ACK); |
1926 | 2099 |
1927 /* Check if we received an ECN SYN-ACK packet. Change the ECN state of sen
der to ECN_IDLE if receiver has sent an ECN SYN-ACK· | 2100 /* Check if we received an ECN SYN-ACK packet. Change the ECN state of sen
der to ECN_IDLE if receiver has sent an ECN SYN-ACK· |
1928 * packet and the traffic is ECN Capable | 2101 * packet and the traffic is ECN Capable |
1929 */ | 2102 */ |
1930 if (m_ecn && (tcpHeader.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) =
= (TcpHeader::ECE)) | 2103 if (m_ecn && (tcpHeader.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) =
= (TcpHeader::ECE)) |
1931 { | 2104 { |
1932 NS_LOG_INFO ("Received ECN SYN-ACK packet."); | 2105 NS_LOG_INFO ("Received ECN SYN-ACK packet."); |
1933 m_ecnState = ECN_IDLE; | 2106 m_tcb->m_ecnState = TcpSocketState::ECN_IDLE; |
1934 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_IDLE"); | 2107 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " ->
ECN_IDLE"); |
1935 } | 2108 } |
1936 else | 2109 else |
1937 { | 2110 { |
1938 m_ecnState = ECN_DISABLED; | 2111 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; |
1939 } | 2112 } |
1940 | 2113 |
1941 SendPendingData (m_connected); | 2114 SendPendingData (m_connected); |
1942 Simulator::ScheduleNow (&TcpSocketBase::ConnectionSucceeded, this); | 2115 Simulator::ScheduleNow (&TcpSocketBase::ConnectionSucceeded, this); |
1943 // Always respond to first data packet to speed up the connection. | 2116 // Always respond to first data packet to speed up the connection. |
1944 // Remove to get the behaviour of old NS-3 code. | 2117 // Remove to get the behaviour of old NS-3 code. |
1945 m_delAckCount = m_delAckMaxCount; | 2118 m_delAckCount = m_delAckMaxCount; |
1946 } | 2119 } |
1947 else | 2120 else |
1948 { // Other in-sequence input | 2121 { // Other in-sequence input |
1949 if (tcpflags != TcpHeader::RST) | 2122 if (tcpflags != TcpHeader::RST) |
1950 { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags | 2123 { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags |
1951 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <
< | 2124 NS_LOG_LOGIC ("Illegal flag " << TcpHeader::FlagsToString (tcpflags) <
< |
1952 " received. Reset packet is sent."); | 2125 " received. Reset packet is sent."); |
1953 SendRST (); | 2126 SendRST (); |
1954 } | 2127 } |
1955 CloseAndNotify (); | 2128 CloseAndNotify (); |
1956 } | 2129 } |
1957 } | 2130 } |
1958 | 2131 |
1959 /* Received a packet upon SYN_RCVD */ | 2132 /* Received a packet upon SYN_RCVD */ |
1960 void | 2133 void |
1961 TcpSocketBase::ProcessSynRcvd (Ptr<Packet> packet, const TcpHeader& tcpHeader, | 2134 TcpSocketBase::ProcessSynRcvd (Ptr<Packet> packet, const TcpHeader& tcpHeader, |
1962 const Address& fromAddress, const Address& toAddr
ess) | 2135 const Address& fromAddress, const Address& toAddr
ess) |
1963 { | 2136 { |
1964 NS_LOG_FUNCTION (this << tcpHeader); | 2137 NS_LOG_FUNCTION (this << tcpHeader); |
1965 | 2138 |
1966 // Extract the flags. PSH, URG, CWR and ECE are not honoured. | 2139 // Extract the flags. PSH, URG, CWR and ECE are not honoured. |
1967 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG |
TcpHeader::CWR | TcpHeader::ECE ); | 2140 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG |
TcpHeader::CWR | TcpHeader::ECE); |
1968 | 2141 |
1969 if (tcpflags == 0 | 2142 if (tcpflags == 0 |
1970 || (tcpflags == TcpHeader::ACK | 2143 || (tcpflags == TcpHeader::ACK |
1971 && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckN
umber ())) | 2144 && m_tcb->m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckN
umber ())) |
1972 { // If it is bare data, accept it and move to ESTABLISHED state. This is | 2145 { // If it is bare data, accept it and move to ESTABLISHED state. This is |
1973 // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the | 2146 // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the |
1974 // handshake is completed nicely. | 2147 // handshake is completed nicely. |
1975 NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED"); | 2148 NS_LOG_DEBUG ("SYN_RCVD -> ESTABLISHED"); |
1976 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN); | 2149 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_OPEN); |
1977 m_state = ESTABLISHED; | 2150 m_state = ESTABLISHED; |
(...skipping 26 matching lines...) Expand all Loading... |
2004 { // Probably the peer lost my SYN+ACK | 2177 { // Probably the peer lost my SYN+ACK |
2005 m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNu
mber32 (1)); | 2178 m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNu
mber32 (1)); |
2006 | 2179 |
2007 /* Check if we received an ECN SYN packet. Change the ECN state of receive
r to ECN_IDLE if sender has sent an ECN SYN· | 2180 /* Check if we received an ECN SYN packet. Change the ECN state of receive
r to ECN_IDLE if sender has sent an ECN SYN· |
2008 * packet and the traffic is ECN Capable | 2181 * packet and the traffic is ECN Capable |
2009 */ | 2182 */ |
2010 if (m_ecn && (tcpHeader.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) =
= (TcpHeader::CWR | TcpHeader::ECE)) | 2183 if (m_ecn && (tcpHeader.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) =
= (TcpHeader::CWR | TcpHeader::ECE)) |
2011 { | 2184 { |
2012 NS_LOG_INFO ("Received ECN SYN packet"); | 2185 NS_LOG_INFO ("Received ECN SYN packet"); |
2013 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK |TcpHeader::ECE); | 2186 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK |TcpHeader::ECE); |
2014 m_ecnState = ECN_IDLE; | 2187 m_tcb->m_ecnState = TcpSocketState::ECN_IDLE; |
2015 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_IDLE"); | 2188 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " ->
ECN_IDLE"); |
2016 } | 2189 } |
2017 else | 2190 else |
2018 { | 2191 { |
2019 m_ecnState = ECN_DISABLED; | 2192 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; |
2020 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); | 2193 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); |
2021 } | 2194 } |
2022 } | 2195 } |
2023 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK)) | 2196 else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK)) |
2024 { | 2197 { |
2025 if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ()) | 2198 if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ()) |
2026 { // In-sequence FIN before connection complete. Set up connection and c
lose. | 2199 { // In-sequence FIN before connection complete. Set up connection and c
lose. |
2027 m_connected = true; | 2200 m_connected = true; |
2028 m_retxEvent.Cancel (); | 2201 m_retxEvent.Cancel (); |
2029 m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence; | 2202 m_tcb->m_highTxMark = ++m_tcb->m_nextTxSequence; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2134 } | 2307 } |
2135 } | 2308 } |
2136 } | 2309 } |
2137 | 2310 |
2138 /* Received a packet upon CLOSING */ | 2311 /* Received a packet upon CLOSING */ |
2139 void | 2312 void |
2140 TcpSocketBase::ProcessClosing (Ptr<Packet> packet, const TcpHeader& tcpHeader) | 2313 TcpSocketBase::ProcessClosing (Ptr<Packet> packet, const TcpHeader& tcpHeader) |
2141 { | 2314 { |
2142 NS_LOG_FUNCTION (this << tcpHeader); | 2315 NS_LOG_FUNCTION (this << tcpHeader); |
2143 | 2316 |
2144 // Extract the flags. PSH , URG , CWR and ECE are not honoured. | 2317 // Extract the flags. PSH, URG, CWR and ECE are not honoured. |
2145 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG |
TcpHeader::CWR | TcpHeader::ECE); | 2318 uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG |
TcpHeader::CWR | TcpHeader::ECE); |
2146 | 2319 |
2147 if (tcpflags == TcpHeader::ACK) | 2320 if (tcpflags == TcpHeader::ACK) |
2148 { | 2321 { |
2149 if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ()) | 2322 if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ()) |
2150 { // This ACK corresponds to the FIN sent | 2323 { // This ACK corresponds to the FIN sent |
2151 TimeWait (); | 2324 TimeWait (); |
2152 } | 2325 } |
2153 } | 2326 } |
2154 else | 2327 else |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2397 bool hasSyn = flags & TcpHeader::SYN; | 2570 bool hasSyn = flags & TcpHeader::SYN; |
2398 bool hasFin = flags & TcpHeader::FIN; | 2571 bool hasFin = flags & TcpHeader::FIN; |
2399 bool isAck = flags == TcpHeader::ACK; | 2572 bool isAck = flags == TcpHeader::ACK; |
2400 if (hasSyn) | 2573 if (hasSyn) |
2401 { | 2574 { |
2402 if (m_winScalingEnabled) | 2575 if (m_winScalingEnabled) |
2403 { // The window scaling option is set only on SYN packets | 2576 { // The window scaling option is set only on SYN packets |
2404 AddOptionWScale (header); | 2577 AddOptionWScale (header); |
2405 } | 2578 } |
2406 | 2579 |
| 2580 if (m_sackEnabled) |
| 2581 { |
| 2582 AddOptionSackPermitted (header); |
| 2583 } |
| 2584 |
2407 if (m_synCount == 0) | 2585 if (m_synCount == 0) |
2408 { // No more connection retries, give up | 2586 { // No more connection retries, give up |
2409 NS_LOG_LOGIC ("Connection failed."); | 2587 NS_LOG_LOGIC ("Connection failed."); |
2410 m_rtt->Reset (); //According to recommendation -> RFC 6298 | 2588 m_rtt->Reset (); //According to recommendation -> RFC 6298 |
2411 CloseAndNotify (); | 2589 CloseAndNotify (); |
2412 return; | 2590 return; |
2413 } | 2591 } |
2414 else | 2592 else |
2415 { // Exponential backoff of connection time out | 2593 { // Exponential backoff of connection time out |
2416 int backoffCount = 0x1 << (m_synRetries - m_synCount); | 2594 int backoffCount = 0x1 << (m_synRetries - m_synCount); |
2417 m_rto = m_cnTimeout * backoffCount; | 2595 m_rto = m_cnTimeout * backoffCount; |
2418 m_synCount--; | 2596 m_synCount--; |
2419 } | 2597 } |
2420 | 2598 |
2421 if (m_synRetries - 1 == m_synCount) | 2599 if (m_synRetries - 1 == m_synCount) |
2422 { | 2600 { |
2423 UpdateRttHistory (s, 0, false); | 2601 UpdateRttHistory (s, 0, false); |
2424 } | 2602 } |
2425 else | 2603 else |
2426 { // This is SYN retransmission | 2604 { // This is SYN retransmission |
2427 UpdateRttHistory (s, 0, true); | 2605 UpdateRttHistory (s, 0, true); |
2428 } | 2606 } |
2429 | 2607 |
2430 windowSize = AdvertisedWindowSize (false); | 2608 windowSize = AdvertisedWindowSize (false); |
2431 } | 2609 } |
2432 header.SetWindowSize (windowSize); | 2610 header.SetWindowSize (windowSize); |
2433 | 2611 |
2434 m_txTrace (p, header, this); | |
2435 | |
2436 if (m_endPoint != 0) | |
2437 { | |
2438 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), | |
2439 m_endPoint->GetPeerAddress (), m_boundnetdevice); | |
2440 } | |
2441 else | |
2442 { | |
2443 m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (), | |
2444 m_endPoint6->GetPeerAddress (), m_boundnetdevice); | |
2445 } | |
2446 | |
2447 if (flags & TcpHeader::ACK) | 2612 if (flags & TcpHeader::ACK) |
2448 { // If sending an ACK, cancel the delay ACK as well | 2613 { // If sending an ACK, cancel the delay ACK as well |
2449 m_delAckEvent.Cancel (); | 2614 m_delAckEvent.Cancel (); |
2450 m_delAckCount = 0; | 2615 m_delAckCount = 0; |
2451 if (m_highTxAck < header.GetAckNumber ()) | 2616 if (m_highTxAck < header.GetAckNumber ()) |
2452 { | 2617 { |
2453 m_highTxAck = header.GetAckNumber (); | 2618 m_highTxAck = header.GetAckNumber (); |
2454 } | 2619 } |
2455 } | 2620 if (m_sackEnabled && m_rxBuffer->GetSackListSize () > 0) |
| 2621 { |
| 2622 AddOptionSack (header); |
| 2623 } |
| 2624 } |
| 2625 |
| 2626 m_txTrace (p, header, this); |
| 2627 |
| 2628 if (m_endPoint != 0) |
| 2629 { |
| 2630 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), |
| 2631 m_endPoint->GetPeerAddress (), m_boundnetdevice); |
| 2632 } |
| 2633 else |
| 2634 { |
| 2635 m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (), |
| 2636 m_endPoint6->GetPeerAddress (), m_boundnetdevice); |
| 2637 } |
| 2638 |
| 2639 |
2456 if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck ) | 2640 if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck ) |
2457 { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost | 2641 { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost |
2458 NS_LOG_LOGIC ("Schedule retransmission timeout at time " | 2642 NS_LOG_LOGIC ("Schedule retransmission timeout at time " |
2459 << Simulator::Now ().GetSeconds () << " to expire at time " | 2643 << Simulator::Now ().GetSeconds () << " to expire at time " |
2460 << (Simulator::Now () + m_rto.Get ()).GetSeconds ()); | 2644 << (Simulator::Now () + m_rto.Get ()).GetSeconds ()); |
2461 m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::SendEmptyPacket,
this, flags); | 2645 m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::SendEmptyPacket,
this, flags); |
2462 } | 2646 } |
2463 } | 2647 } |
2464 | 2648 |
2465 /* This function closes the endpoint completely. Called upon RST_TX action. */ | 2649 /* This function closes the endpoint completely. Called upon RST_TX action. */ |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 SetupCallback (); | 2773 SetupCallback (); |
2590 // Set the sequence number and send SYN+ACK | 2774 // Set the sequence number and send SYN+ACK |
2591 m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1)); | 2775 m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1)); |
2592 | 2776 |
2593 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to
ECN_IDLE if sender has sent an ECN SYN· | 2777 /* Check if we received an ECN SYN packet. Change the ECN state of receiver to
ECN_IDLE if sender has sent an ECN SYN· |
2594 * packet and the traffic is ECN Capable | 2778 * packet and the traffic is ECN Capable |
2595 */ | 2779 */ |
2596 if (m_ecn && (h.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) == (TcpHeader
::CWR | TcpHeader::ECE)) | 2780 if (m_ecn && (h.GetFlags () & (TcpHeader::CWR | TcpHeader::ECE)) == (TcpHeader
::CWR | TcpHeader::ECE)) |
2597 { | 2781 { |
2598 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK | TcpHeader::ECE); | 2782 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK | TcpHeader::ECE); |
2599 m_ecnState = ECN_IDLE; | 2783 m_tcb->m_ecnState = TcpSocketState::ECN_IDLE; |
2600 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_IDLE"); | 2784 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_
IDLE"); |
2601 } | 2785 } |
2602 else | 2786 else |
2603 { | 2787 { |
2604 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); | 2788 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); |
2605 m_ecnState = ECN_DISABLED; | 2789 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; |
2606 }·· | 2790 }·· |
2607 } | 2791 } |
2608 | 2792 |
2609 void | 2793 void |
2610 TcpSocketBase::ConnectionSucceeded () | 2794 TcpSocketBase::ConnectionSucceeded () |
2611 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can | 2795 { // Wrapper to protected function NotifyConnectionSucceeded() so that it can |
2612 // be called as a scheduled event | 2796 // be called as a scheduled event |
2613 NotifyConnectionSucceeded (); | 2797 NotifyConnectionSucceeded (); |
2614 // The if-block below was moved from ProcessSynSent() to here because we need | 2798 // The if-block below was moved from ProcessSynSent() to here because we need |
2615 // to invoke the NotifySend() only after NotifyConnectionSucceeded() to | 2799 // to invoke the NotifySend() only after NotifyConnectionSucceeded() to |
(...skipping 22 matching lines...) Expand all Loading... |
2638 uint8_t flags = withAck ? TcpHeader::ACK : 0; | 2822 uint8_t flags = withAck ? TcpHeader::ACK : 0; |
2639 uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32
(sz)); | 2823 uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32
(sz)); |
2640 | 2824 |
2641 if (withAck) | 2825 if (withAck) |
2642 { | 2826 { |
2643 m_delAckEvent.Cancel (); | 2827 m_delAckEvent.Cancel (); |
2644 m_delAckCount = 0; | 2828 m_delAckCount = 0; |
2645 } | 2829 } |
2646 | 2830 |
2647 // Sender should reduce the Congestion Window as a response to receiver's ECN
Echo notification only once per window· | 2831 // Sender should reduce the Congestion Window as a response to receiver's ECN
Echo notification only once per window· |
2648 if (m_ecnState == ECN_ECE_RCVD && m_ecnEchoSeq.Get() > m_ecnCWRSeq.Get())· | 2832 if (m_tcb->m_ecnState == TcpSocketState::ECN_ECE_RCVD && m_ecnEchoSeq.Get() >
m_ecnCWRSeq.Get() && !isRetransmission )· |
2649 { | 2833 { |
2650 NS_LOG_INFO ("Backoff mechanism by reducing CWND by half because we've re
ceived ECN Echo"); | 2834 NS_LOG_INFO ("Backoff mechanism by reducing CWND by half because we've re
ceived ECN Echo"); |
2651 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, BytesInFlight
());·· | 2835 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, BytesInFlight
());·· |
2652 m_tcb->m_cWnd = std::max ((uint32_t)m_tcb->m_cWnd/2, m_tcb->m_segmentSize)
; | 2836 m_tcb->m_cWnd = std::max ((uint32_t)m_tcb->m_cWnd/2, m_tcb->m_segmentSize)
; |
2653 flags |= TcpHeader::CWR;· | 2837 flags |= TcpHeader::CWR;· |
2654 m_ecnCWRSeq = seq; | 2838 m_ecnCWRSeq = seq; |
2655 m_ecnState = ECN_CWR_SENT; | 2839 m_tcb->m_ecnState = TcpSocketState::ECN_CWR_SENT; |
2656 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_CWR_SENT"); | 2840 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " -> ECN_
CWR_SENT"); |
2657 NS_LOG_INFO ("CWR flags set"); | 2841 NS_LOG_INFO ("CWR flags set"); |
2658 NS_LOG_DEBUG (TcpSocketState::TcpCongStateName[m_tcb->m_congState] << " ->
CA_CWR"); | 2842 NS_LOG_DEBUG (TcpSocketState::TcpCongStateName[m_tcb->m_congState] << " ->
CA_CWR"); |
2659 if (m_tcb->m_congState == TcpSocketState::CA_OPEN) | 2843 if (m_tcb->m_congState == TcpSocketState::CA_OPEN) |
2660 { | 2844 { |
2661 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_CWR
); | 2845 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_CWR
); |
2662 m_tcb->m_congState = TcpSocketState::CA_CWR; | 2846 m_tcb->m_congState = TcpSocketState::CA_CWR; |
2663 } | 2847 } |
2664 } | 2848 } |
2665 | 2849 |
2666 /* | 2850 /* |
2667 * Add tags for each socket option. | 2851 * Add tags for each socket option. |
2668 * Note that currently the socket adds both IPv4 tag and IPv6 tag | 2852 * Note that currently the socket adds both IPv4 tag and IPv6 tag |
2669 * if both options are set. Once the packet got to layer three, only | 2853 * if both options are set. Once the packet got to layer three, only |
2670 * the corresponding tags will be read. | 2854 * the corresponding tags will be read. |
2671 */ | 2855 */ |
2672 if (GetIpTos ()) | 2856 if (GetIpTos ()) |
2673 { | 2857 { |
2674 SocketIpTosTag ipTosTag; | 2858 SocketIpTosTag ipTosTag; |
2675 NS_LOG_LOGIC (" ECT bits should not be set on retransmitted packets "); | 2859 NS_LOG_LOGIC (" ECT bits should not be set on retransmitted packets "); |
2676 if (m_ecnState != ECN_DISABLED && (GetIpTos () & 0x3) == 0 && !isRetransmi
ssion) | 2860 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && (GetIpTos () & 0x
3) == 0 && !isRetransmission) |
2677 {· | 2861 {· |
2678 ipTosTag.SetTos (GetIpTos () | 0x2); | 2862 ipTosTag.SetTos (GetIpTos () | 0x2); |
2679 } | 2863 } |
2680 else | 2864 else |
2681 { | 2865 { |
2682 ipTosTag.SetTos (GetIpTos ()); | 2866 ipTosTag.SetTos (GetIpTos ()); |
2683 } | 2867 } |
2684 p->AddPacketTag (ipTosTag); | 2868 p->AddPacketTag (ipTosTag); |
2685 } | 2869 } |
2686 else | 2870 else |
2687 { | 2871 { |
2688 if (m_ecnState != ECN_DISABLED && !isRetransmission) | 2872 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && !isRetransmission
) |
2689 { | 2873 { |
2690 SocketIpTosTag ipTosTag; | 2874 SocketIpTosTag ipTosTag; |
2691 ipTosTag.SetTos (0x02); | 2875 ipTosTag.SetTos (0x02); |
2692 p->AddPacketTag (ipTosTag); | 2876 p->AddPacketTag (ipTosTag); |
2693 } | 2877 } |
2694 } | 2878 } |
2695 | 2879 |
2696 if (IsManualIpv6Tclass ()) | 2880 if (IsManualIpv6Tclass ()) |
2697 { | 2881 { |
2698 SocketIpv6TclassTag ipTclassTag; | 2882 SocketIpv6TclassTag ipTclassTag; |
2699 if (m_ecnState != ECN_DISABLED && (GetIpv6Tclass () & 0x3) == 0 && !isRetr
ansmission) | 2883 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && (GetIpv6Tclass ()
& 0x3) == 0 && !isRetransmission) |
2700 { | 2884 { |
2701 ipTclassTag.SetTclass (GetIpv6Tclass () | 0x2); | 2885 ipTclassTag.SetTclass (GetIpv6Tclass () | 0x2); |
2702 } | 2886 } |
2703 else | 2887 else |
2704 { | 2888 { |
2705 ipTclassTag.SetTclass (GetIpv6Tclass ()); | 2889 ipTclassTag.SetTclass (GetIpv6Tclass ()); |
2706 } | 2890 } |
2707 p->AddPacketTag (ipTclassTag); | 2891 p->AddPacketTag (ipTclassTag); |
2708 } | 2892 } |
2709 else | 2893 else |
2710 { | 2894 { |
2711 if (m_ecnState != ECN_DISABLED && !isRetransmission) | 2895 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED && !isRetransmission
) |
2712 { | 2896 { |
2713 SocketIpv6TclassTag ipTclassTag; | 2897 SocketIpv6TclassTag ipTclassTag; |
2714 ipTclassTag.SetTclass (0x02); | 2898 ipTclassTag.SetTclass (0x02); |
2715 p->AddPacketTag (ipTclassTag); | 2899 p->AddPacketTag (ipTclassTag); |
2716 } | 2900 } |
2717 } | 2901 } |
2718 | 2902 |
2719 if (IsManualIpTtl ()) | 2903 if (IsManualIpTtl ()) |
2720 { | 2904 { |
2721 SocketIpTtlTag ipTtlTag; | 2905 SocketIpTtlTag ipTtlTag; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2764 else | 2948 else |
2765 { | 2949 { |
2766 header.SetSourcePort (m_endPoint6->GetLocalPort ()); | 2950 header.SetSourcePort (m_endPoint6->GetLocalPort ()); |
2767 header.SetDestinationPort (m_endPoint6->GetPeerPort ()); | 2951 header.SetDestinationPort (m_endPoint6->GetPeerPort ()); |
2768 } | 2952 } |
2769 header.SetWindowSize (AdvertisedWindowSize ()); | 2953 header.SetWindowSize (AdvertisedWindowSize ()); |
2770 AddOptions (header); | 2954 AddOptions (header); |
2771 | 2955 |
2772 if (m_retxEvent.IsExpired ()) | 2956 if (m_retxEvent.IsExpired ()) |
2773 { | 2957 { |
2774 // Schedules retransmit timeout. If this is a retransmission, double the t
imer | 2958 // Schedules retransmit timeout. m_rto should be already doubled. |
2775 | |
2776 if (isRetransmission) | |
2777 { // This is a retransmit | |
2778 // RFC 6298, clause 2.5 | |
2779 Time doubledRto = m_rto + m_rto; | |
2780 m_rto = Min (doubledRto, Time::FromDouble (60, Time::S)); | |
2781 } | |
2782 | 2959 |
2783 NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " << | 2960 NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " << |
2784 Simulator::Now ().GetSeconds () << " to expire at time " << | 2961 Simulator::Now ().GetSeconds () << " to expire at time " << |
2785 (Simulator::Now () + m_rto.Get ()).GetSeconds () ); | 2962 (Simulator::Now () + m_rto.Get ()).GetSeconds () ); |
2786 m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::ReTxTimeout, thi
s); | 2963 m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::ReTxTimeout, thi
s); |
2787 } | 2964 } |
2788 | 2965 |
2789 m_txTrace (p, header, this); | 2966 m_txTrace (p, header, this); |
2790 | 2967 |
2791 if (m_endPoint) | 2968 if (m_endPoint) |
(...skipping 12 matching lines...) Expand all Loading... |
2804 remainingData << " via TcpL4Protocol to " << m_endPoint6->G
etPeerAddress () << | 2981 remainingData << " via TcpL4Protocol to " << m_endPoint6->G
etPeerAddress () << |
2805 ". Header " << header); | 2982 ". Header " << header); |
2806 } | 2983 } |
2807 | 2984 |
2808 UpdateRttHistory (seq, sz, isRetransmission); | 2985 UpdateRttHistory (seq, sz, isRetransmission); |
2809 | 2986 |
2810 // Notify the application of the data being sent unless this is a retransmit | 2987 // Notify the application of the data being sent unless this is a retransmit |
2811 if (seq + sz > m_tcb->m_highTxMark) | 2988 if (seq + sz > m_tcb->m_highTxMark) |
2812 { | 2989 { |
2813 Simulator::ScheduleNow (&TcpSocketBase::NotifyDataSent, this, | 2990 Simulator::ScheduleNow (&TcpSocketBase::NotifyDataSent, this, |
2814 (seq + sz - m_tcb->m_highTxMark.Get ())); | 2991 (seq + sz - m_tcb->m_highTxMark.Get ())); |
2815 } | 2992 } |
2816 // Update highTxMark | 2993 // Update highTxMark |
2817 m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ()); | 2994 m_tcb->m_highTxMark = std::max (seq + sz, m_tcb->m_highTxMark.Get ()); |
2818 return sz; | 2995 return sz; |
2819 } | 2996 } |
2820 | 2997 |
2821 void | 2998 void |
2822 TcpSocketBase::UpdateRttHistory (const SequenceNumber32 &seq, uint32_t sz, | 2999 TcpSocketBase::UpdateRttHistory (const SequenceNumber32 &seq, uint32_t sz, |
2823 bool isRetransmission) | 3000 bool isRetransmission) |
2824 { | 3001 { |
(...skipping 11 matching lines...) Expand all Loading... |
2836 if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count)))) | 3013 if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count)))) |
2837 { // Found it | 3014 { // Found it |
2838 i->retx = true; | 3015 i->retx = true; |
2839 i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update
count in hist | 3016 i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update
count in hist |
2840 break; | 3017 break; |
2841 } | 3018 } |
2842 } | 3019 } |
2843 } | 3020 } |
2844 } | 3021 } |
2845 | 3022 |
2846 /* Send as much pending data as possible according to the Tx window. Note that | 3023 // Note that this function did not implement the PSH flag |
2847 * this function did not implement the PSH flag | 3024 uint32_t |
2848 */ | |
2849 bool | |
2850 TcpSocketBase::SendPendingData (bool withAck) | 3025 TcpSocketBase::SendPendingData (bool withAck) |
2851 { | 3026 { |
2852 NS_LOG_FUNCTION (this << withAck); | 3027 NS_LOG_FUNCTION (this << withAck); |
2853 if (m_txBuffer->Size () == 0) | 3028 if (m_txBuffer->Size () == 0) |
2854 { | 3029 { |
2855 return false; // Nothing to send | 3030 return false; // Nothing to send |
2856 } | 3031 } |
2857 if (m_endPoint == 0 && m_endPoint6 == 0) | 3032 if (m_endPoint == 0 && m_endPoint6 == 0) |
2858 { | 3033 { |
2859 NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=
" << m_shutdownSend); | 3034 NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=
" << m_shutdownSend); |
2860 return false; // Is this the right way to handle this condition? | 3035 return false; // Is this the right way to handle this condition? |
2861 } | 3036 } |
| 3037 |
2862 uint32_t nPacketsSent = 0; | 3038 uint32_t nPacketsSent = 0; |
2863 while (m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence)) | 3039 uint32_t availableWindow = AvailableWindow (); |
2864 { | 3040 |
2865 uint32_t w = AvailableWindow (); // Get available window size | 3041 // RFC 6675, Section (C) |
2866 // Stop sending if we need to wait for a larger Tx window (prevent silly w
indow syndrome) | 3042 // If cwnd - pipe >= 1 SMSS, the sender SHOULD transmit one or more |
2867 if (w < m_tcb->m_segmentSize && m_txBuffer->SizeFromSequence (m_tcb->m_nex
tTxSequence) > w) | 3043 // segments as follows: |
2868 { | 3044 // (NOTE: We check > 0, and do the checks for segmentSize in the following |
2869 NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send."); | 3045 // else branch to control silly window syndrome and Nagle) |
2870 break; // No more | 3046 while (availableWindow > 0) |
2871 } | 3047 { |
2872 // Nagle's algorithm (RFC896): Hold off sending if there is unacked data | 3048 if (m_tcb->m_congState == TcpSocketState::CA_OPEN |
2873 // in the buffer and the amount of data to send is less than one segment | 3049 && m_state == TcpSocket::FIN_WAIT_1) |
2874 if (!m_noDelay && UnAckDataCount () > 0 | 3050 { |
2875 && m_txBuffer->SizeFromSequence (m_tcb->m_nextTxSequence) < m_tcb->m_s
egmentSize) | 3051 NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit"); |
2876 { | |
2877 NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send."); | |
2878 break; | 3052 break; |
2879 } | 3053 } |
2880 NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" << | 3054 // (C.1) The scoreboard MUST be queried via NextSeg () for the |
2881 " w " << w << | 3055 // sequence number range of the next segment to transmit (if |
2882 " rxwin " << m_rWnd << | 3056 // any), and the given segment sent. If NextSeg () returns |
2883 " segsize " << m_tcb->m_segmentSize << | 3057 // failure (no data to send), return without sending anything |
2884 " nextTxSeq " << m_tcb->m_nextTxSequence << | 3058 // (i.e., terminate steps C.1 -- C.5). |
2885 " highestRxAck " << m_txBuffer->HeadSequence () << | 3059 SequenceNumber32 next; |
2886 " pd->Size " << m_txBuffer->Size () << | 3060 if (!m_txBuffer->NextSeg (&next, m_retxThresh, m_tcb->m_segmentSize, |
2887 " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_nextTx
Sequence)); | 3061 m_tcb->m_congState == TcpSocketState::CA_RECOVER
Y)) |
2888 | 3062 { |
2889 NS_LOG_DEBUG ("Window: " << w << | 3063 NS_LOG_INFO ("no valid seq to transmit, or no data available"); |
2890 " cWnd: " << m_tcb->m_cWnd << | 3064 break; |
2891 " unAck: " << UnAckDataCount ()); | 3065 } |
2892 | 3066 else |
2893 uint32_t s = std::min (w, m_tcb->m_segmentSize); // Send no more than win
dow | 3067 { |
2894 uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck); | 3068 // It's time to transmit, but before do silly window and Nagle's check |
2895 nPacketsSent++; // Count sent this loop | 3069 uint32_t availableData = m_txBuffer->SizeFromSequence (next); |
2896 m_tcb->m_nextTxSequence += sz; // Advance next tx sequ
ence | 3070 |
2897 } | 3071 // Stop sending if we need to wait for a larger Tx window (prevent sil
ly window syndrome) |
| 3072 if (availableWindow < m_tcb->m_segmentSize && availableData > availab
leWindow) |
| 3073 { |
| 3074 NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send."); |
| 3075 break; // No more |
| 3076 } |
| 3077 // Nagle's algorithm (RFC896): Hold off sending if there is unacked da
ta |
| 3078 // in the buffer and the amount of data to send is less than one segme
nt |
| 3079 if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_se
gmentSize) |
| 3080 { |
| 3081 NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next << |
| 3082 ", SFS: " << m_txBuffer->SizeFromSequence (next) << |
| 3083 ". Wait to send."); |
| 3084 break; |
| 3085 } |
| 3086 |
| 3087 uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize); |
| 3088 |
| 3089 // (C.2) If any of the data octets sent in (C.1) are below HighData, |
| 3090 // HighRxt MUST be set to the highest sequence number of the |
| 3091 // retransmitted segment unless NextSeg () rule (4) was |
| 3092 // invoked for this retransmission. |
| 3093 // (C.3) If any of the data octets sent in (C.1) are above HighData, |
| 3094 // HighData must be updated to reflect the transmission of |
| 3095 // previously unsent data. |
| 3096 // |
| 3097 // These steps are done in m_txBuffer with the tags. |
| 3098 if (m_tcb->m_nextTxSequence != next) |
| 3099 { |
| 3100 m_tcb->m_nextTxSequence = next; |
| 3101 } |
| 3102 |
| 3103 uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck); |
| 3104 m_tcb->m_nextTxSequence += sz; |
| 3105 |
| 3106 NS_LOG_LOGIC (" rxwin " << m_rWnd << |
| 3107 " segsize " << m_tcb->m_segmentSize << |
| 3108 " highestRxAck " << m_txBuffer->HeadSequence () << |
| 3109 " pd->Size " << m_txBuffer->Size () << |
| 3110 " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_ne
xtTxSequence)); |
| 3111 |
| 3112 NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd << |
| 3113 " total unAck: " << UnAckDataCount () << |
| 3114 " sent seq " << m_tcb->m_nextTxSequence << |
| 3115 " size " << sz); |
| 3116 |
| 3117 ++nPacketsSent; |
| 3118 } |
| 3119 |
| 3120 // (C.4) The estimate of the amount of data outstanding in the |
| 3121 // network must be updated by incrementing pipe by the number |
| 3122 // of octets transmitted in (C.1). |
| 3123 // |
| 3124 // Done in BytesInFlight, inside AvailableWindow. |
| 3125 availableWindow = AvailableWindow (); |
| 3126 |
| 3127 // (C.5) If cwnd - pipe >= 1 SMSS, return to (C.1) |
| 3128 // loop again! |
| 3129 } |
| 3130 |
2898 if (nPacketsSent > 0) | 3131 if (nPacketsSent > 0) |
2899 { | 3132 { |
2900 NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments"); | 3133 NS_LOG_DEBUG ("SendPendingData sent " << nPacketsSent << " segments"); |
2901 } | 3134 } |
2902 return (nPacketsSent > 0); | 3135 return nPacketsSent; |
2903 } | 3136 } |
2904 | 3137 |
2905 uint32_t | 3138 uint32_t |
2906 TcpSocketBase::UnAckDataCount () const | 3139 TcpSocketBase::UnAckDataCount () const |
2907 { | 3140 { |
2908 NS_LOG_FUNCTION (this); | 3141 NS_LOG_FUNCTION (this); |
2909 return m_tcb->m_nextTxSequence.Get () - m_txBuffer->HeadSequence (); | 3142 return m_tcb->m_highTxMark.Get () - m_txBuffer->HeadSequence (); |
2910 } | 3143 } |
2911 | 3144 |
2912 uint32_t | 3145 uint32_t |
2913 TcpSocketBase::BytesInFlight () | 3146 TcpSocketBase::BytesInFlight () const |
2914 { | 3147 { |
2915 NS_LOG_FUNCTION (this); | 3148 NS_LOG_FUNCTION (this); |
2916 // Previous (see bug 1783): | 3149 // Previous (see bug 1783): |
2917 // uint32_t bytesInFlight = m_highTxMark.Get () - m_txBuffer->HeadSequence (); | 3150 // uint32_t bytesInFlight = m_highTxMark.Get () - m_txBuffer->HeadSequence (); |
2918 // RFC 4898 page 23 | 3151 // RFC 4898 page 23 |
2919 // PipeSize=SND.NXT-SND.UNA+(retransmits-dupacks)*CurMSS | 3152 // PipeSize=SND.NXT-SND.UNA+(retransmits-dupacks)*CurMSS |
2920 | 3153 |
2921 // flightSize == UnAckDataCount (), but we avoid the call to save log lines | 3154 // flightSize == UnAckDataCount (), but we avoid the call to save log lines |
2922 uint32_t flightSize = m_tcb->m_nextTxSequence.Get () - m_txBuffer->HeadSequenc
e (); | 3155 uint32_t bytesInFlight = m_txBuffer->BytesInFlight (m_retxThresh, m_tcb->m_seg
mentSize); |
2923 uint32_t duplicatedSize; | |
2924 uint32_t bytesInFlight; | |
2925 | |
2926 if (m_retransOut > m_dupAckCount) | |
2927 { | |
2928 duplicatedSize = (m_retransOut - m_dupAckCount)*m_tcb->m_segmentSize; | |
2929 bytesInFlight = flightSize + duplicatedSize; | |
2930 } | |
2931 else | |
2932 { | |
2933 duplicatedSize = (m_dupAckCount - m_retransOut)*m_tcb->m_segmentSize; | |
2934 bytesInFlight = duplicatedSize > flightSize ? 0 : flightSize - duplicatedS
ize; | |
2935 } | |
2936 | 3156 |
2937 // m_bytesInFlight is traced; avoid useless assignments which would fire | 3157 // m_bytesInFlight is traced; avoid useless assignments which would fire |
2938 // fruitlessly the callback | 3158 // fruitlessly the callback |
2939 if (m_bytesInFlight != bytesInFlight) | 3159 if (m_bytesInFlight != bytesInFlight) |
2940 { | 3160 { |
2941 m_bytesInFlight = bytesInFlight; | 3161 // Ugly, but we are not modifying the state; m_bytesInFlight is used |
| 3162 // only for tracing purpose. |
| 3163 const_cast<TcpSocketBase*> (this)->m_bytesInFlight = bytesInFlight; |
2942 } | 3164 } |
2943 | 3165 |
2944 return bytesInFlight; | 3166 return bytesInFlight; |
2945 } | 3167 } |
2946 | 3168 |
2947 uint32_t | 3169 uint32_t |
2948 TcpSocketBase::Window (void) const | 3170 TcpSocketBase::Window (void) const |
2949 { | 3171 { |
2950 NS_LOG_FUNCTION (this); | 3172 NS_LOG_FUNCTION (this); |
2951 return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ()); | 3173 return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ()); |
2952 } | 3174 } |
2953 | 3175 |
2954 uint32_t | 3176 uint32_t |
2955 TcpSocketBase::AvailableWindow () const | 3177 TcpSocketBase::AvailableWindow () const |
2956 { | 3178 { |
2957 NS_LOG_FUNCTION_NOARGS (); | 3179 NS_LOG_FUNCTION_NOARGS (); |
2958 uint32_t unack = UnAckDataCount (); // Number of outstanding bytes | 3180 uint32_t inflight = BytesInFlight (); // Number of outstanding bytes |
2959 uint32_t win = Window (); // Number of bytes allowed to be outstandi
ng | 3181 uint32_t win = Window (); // Number of bytes allowed to be outstan
ding |
2960 | 3182 |
2961 NS_LOG_DEBUG ("UnAckCount=" << unack << ", Win=" << win); | 3183 if (inflight > win) |
2962 return (win < unack) ? 0 : (win - unack); | 3184 { |
| 3185 NS_LOG_DEBUG ("InFlight=" << inflight << ", Win=" << win << " availWin=0")
; |
| 3186 return 0; |
| 3187 } |
| 3188 |
| 3189 NS_LOG_DEBUG ("InFlight=" << inflight << ", Win=" << win << " availWin=" << wi
n-inflight); |
| 3190 return win - inflight; |
2963 } | 3191 } |
2964 | 3192 |
2965 uint16_t | 3193 uint16_t |
2966 TcpSocketBase::AdvertisedWindowSize (bool scale) const | 3194 TcpSocketBase::AdvertisedWindowSize (bool scale) const |
2967 { | 3195 { |
2968 NS_LOG_FUNCTION (this << scale); | 3196 NS_LOG_FUNCTION (this << scale); |
2969 uint32_t w = m_rxBuffer->MaxBufferSize (); | 3197 uint32_t w = (m_rxBuffer->MaxRxSequence () > m_rxBuffer->NextRxSequence ()) ? |
2970 | 3198 m_rxBuffer->MaxRxSequence () - m_rxBuffer->NextRxSequence () : 0; |
| 3199 |
| 3200 // We don't want to advertise 0 after a FIN is received. So, we just use |
| 3201 // the previous value of the advWnd. |
| 3202 if (m_rxBuffer->Finished ()) |
| 3203 { |
| 3204 w = m_advWnd; |
| 3205 } |
| 3206 |
| 3207 // Ugly, but we are not modifying the state, that variable |
| 3208 // is used only for tracing purpose. |
| 3209 if (w != m_advWnd) |
| 3210 { |
| 3211 const_cast<TcpSocketBase*> (this)->m_advWnd = w; |
| 3212 } |
2971 if (scale) | 3213 if (scale) |
2972 { | 3214 { |
2973 w >>= m_rcvWindShift; | 3215 w >>= m_rcvWindShift; |
2974 } | 3216 } |
2975 if (w > m_maxWinSize) | 3217 if (w > m_maxWinSize) |
2976 { | 3218 { |
2977 w = m_maxWinSize; | 3219 w = m_maxWinSize; |
2978 NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibl
y to avoid overflow of the 16-bit integer"); | 3220 NS_LOG_WARN ("Adv window size truncated to " << m_maxWinSize << "; possibl
y to avoid overflow of the 16-bit integer"); |
2979 } | 3221 } |
2980 NS_LOG_DEBUG ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w
)); | 3222 NS_LOG_INFO ("Returning AdvertisedWindowSize of " << static_cast<uint16_t> (w)
); |
2981 return static_cast<uint16_t> (w); | 3223 return static_cast<uint16_t> (w); |
2982 } | 3224 } |
2983 | 3225 |
2984 // Receipt of new packet, put into Rx buffer | 3226 // Receipt of new packet, put into Rx buffer |
2985 void | 3227 void |
2986 TcpSocketBase::ReceivedData (Ptr<Packet> p, const TcpHeader& tcpHeader) | 3228 TcpSocketBase::ReceivedData (Ptr<Packet> p, const TcpHeader& tcpHeader) |
2987 { | 3229 { |
2988 NS_LOG_FUNCTION (this << tcpHeader); | 3230 NS_LOG_FUNCTION (this << tcpHeader); |
2989 NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () << | 3231 NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () << |
2990 " pkt size=" << p->GetSize () ); | 3232 " pkt size=" << p->GetSize () ); |
2991 | 3233 |
2992 // Put into Rx buffer | 3234 // Put into Rx buffer |
2993 SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence (); | 3235 SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence (); |
2994 if (!m_rxBuffer->Add (p, tcpHeader)) | 3236 if (!m_rxBuffer->Add (p, tcpHeader)) |
2995 { // Insert failed: No data or RX buffer full | 3237 { // Insert failed: No data or RX buffer full |
2996 if (m_ecnState == ECN_CE_RCVD || m_ecnState == ECN_ECE_SENT) | 3238 if (m_tcb->m_ecnState == TcpSocketState::ECN_CE_RCVD || m_tcb->m_ecnState
== TcpSocketState::ECN_ECE_SENT) |
2997 { | 3239 { |
2998 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); | 3240 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); |
2999 m_ecnState = ECN_ECE_SENT; | 3241 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_SENT; |
3000 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_ECE_SENT"); | 3242 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " ->
ECN_ECE_SENT"); |
3001 } | 3243 } |
3002 else | 3244 else |
3003 { | 3245 { |
3004 SendEmptyPacket (TcpHeader::ACK); | 3246 SendEmptyPacket (TcpHeader::ACK); |
3005 }· | 3247 }· |
3006 return; | 3248 return; |
3007 } | 3249 } |
| 3250 // Notify app to receive if necessary |
| 3251 if (expectedSeq < m_rxBuffer->NextRxSequence ()) |
| 3252 { // NextRxSeq advanced, we have something to send to the app |
| 3253 if (!m_shutdownRecv) |
| 3254 { |
| 3255 NotifyDataRecv (); |
| 3256 } |
| 3257 // Handle exceptions |
| 3258 if (m_closeNotified) |
| 3259 { |
| 3260 NS_LOG_WARN ("Why TCP " << this << " got data after close notification
?"); |
| 3261 } |
| 3262 // If we received FIN before and now completed all "holes" in rx buffer, |
| 3263 // invoke peer close procedure |
| 3264 if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) ==
0) |
| 3265 { |
| 3266 DoPeerClose (); |
| 3267 return; |
| 3268 } |
| 3269 } |
3008 // Now send a new ACK packet acknowledging all received and delivered data | 3270 // Now send a new ACK packet acknowledging all received and delivered data |
3009 if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequen
ce () > expectedSeq + p->GetSize ()) | 3271 if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequen
ce () > expectedSeq + p->GetSize ()) |
3010 { // A gap exists in the buffer, or we filled a gap: Always ACK | 3272 { // A gap exists in the buffer, or we filled a gap: Always ACK |
3011 if (m_ecnState == ECN_CE_RCVD || m_ecnState == ECN_ECE_SENT) | 3273 if (m_tcb->m_ecnState == TcpSocketState::ECN_CE_RCVD || m_tcb->m_ecnState
== TcpSocketState::ECN_ECE_SENT) |
3012 { | 3274 { |
3013 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); | 3275 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); |
3014 m_ecnState = ECN_ECE_SENT; | 3276 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_SENT; |
3015 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_ECE_SENT"); | 3277 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " ->
ECN_ECE_SENT"); |
3016 } | 3278 } |
3017 else | 3279 else |
3018 { | 3280 { |
3019 SendEmptyPacket (TcpHeader::ACK); | 3281 SendEmptyPacket (TcpHeader::ACK); |
3020 } | 3282 } |
3021 } | 3283 } |
3022 else | 3284 else |
3023 { // In-sequence packet: ACK if delayed ack count allows | 3285 { // In-sequence packet: ACK if delayed ack count allows |
3024 if (++m_delAckCount >= m_delAckMaxCount) | 3286 if (++m_delAckCount >= m_delAckMaxCount) |
3025 { | 3287 { |
3026 m_delAckEvent.Cancel (); | 3288 m_delAckEvent.Cancel (); |
3027 m_delAckCount = 0; | 3289 m_delAckCount = 0; |
3028 if (m_ecnState == ECN_CE_RCVD || m_ecnState == ECN_ECE_SENT) | 3290 if (m_tcb->m_ecnState == TcpSocketState::ECN_CE_RCVD || m_tcb->m_ecnSt
ate == TcpSocketState::ECN_ECE_SENT) |
3029 { | 3291 { |
3030 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); | 3292 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); |
3031 m_ecnState = ECN_ECE_SENT; | 3293 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_SENT; |
3032 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_ECE_SENT"); | 3294 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << "
-> ECN_ECE_SENT"); |
3033 } | 3295 } |
3034 else | 3296 else |
3035 { | 3297 { |
3036 SendEmptyPacket (TcpHeader::ACK); | 3298 SendEmptyPacket (TcpHeader::ACK); |
3037 } | 3299 } |
3038 } | 3300 } |
3039 else if (m_delAckEvent.IsExpired ()) | 3301 else if (m_delAckEvent.IsExpired ()) |
3040 { | 3302 { |
3041 m_delAckEvent = Simulator::Schedule (m_delAckTimeout, | 3303 m_delAckEvent = Simulator::Schedule (m_delAckTimeout, |
3042 &TcpSocketBase::DelAckTimeout, th
is); | 3304 &TcpSocketBase::DelAckTimeout, th
is); |
3043 NS_LOG_LOGIC (this << " scheduled delayed ACK at " << | 3305 NS_LOG_LOGIC (this << " scheduled delayed ACK at " << |
3044 (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEv
ent)).GetSeconds ()); | 3306 (Simulator::Now () + Simulator::GetDelayLeft (m_delAckEv
ent)).GetSeconds ()); |
3045 } | |
3046 } | |
3047 // Notify app to receive if necessary | |
3048 if (expectedSeq < m_rxBuffer->NextRxSequence ()) | |
3049 { // NextRxSeq advanced, we have something to send to the app | |
3050 if (!m_shutdownRecv) | |
3051 { | |
3052 NotifyDataRecv (); | |
3053 } | |
3054 // Handle exceptions | |
3055 if (m_closeNotified) | |
3056 { | |
3057 NS_LOG_WARN ("Why TCP " << this << " got data after close notification
?"); | |
3058 } | |
3059 // If we received FIN before and now completed all "holes" in rx buffer, | |
3060 // invoke peer close procedure | |
3061 if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) ==
0) | |
3062 { | |
3063 DoPeerClose (); | |
3064 } | 3307 } |
3065 } | 3308 } |
3066 } | 3309 } |
3067 | 3310 |
3068 /** | 3311 /** |
3069 * \brief Estimate the RTT | 3312 * \brief Estimate the RTT |
3070 * | 3313 * |
3071 * Called by ForwardUp() to estimate RTT. | 3314 * Called by ForwardUp() to estimate RTT. |
3072 * | 3315 * |
3073 * \param tcpHeader TCP header for the incoming packet | 3316 * \param tcpHeader TCP header for the incoming packet |
3074 */ | 3317 */ |
3075 void | 3318 void |
3076 TcpSocketBase::EstimateRtt (const TcpHeader& tcpHeader) | 3319 TcpSocketBase::EstimateRtt (const TcpHeader& tcpHeader) |
3077 { | 3320 { |
3078 SequenceNumber32 ackSeq = tcpHeader.GetAckNumber (); | 3321 SequenceNumber32 ackSeq = tcpHeader.GetAckNumber (); |
3079 Time m = Time (0.0); | 3322 Time m = Time (0.0); |
3080 | 3323 |
3081 // An ack has been received, calculate rtt and log this measurement | 3324 // An ack has been received, calculate rtt and log this measurement |
3082 // Note we use a linear search (O(n)) for this since for the common | 3325 // Note we use a linear search (O(n)) for this since for the common |
3083 // case the ack'ed packet will be at the head of the list | 3326 // case the ack'ed packet will be at the head of the list |
3084 if (!m_history.empty ()) | 3327 if (!m_history.empty ()) |
3085 { | 3328 { |
3086 RttHistory& h = m_history.front (); | 3329 RttHistory& h = m_history.front (); |
3087 if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count))) | 3330 if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count))) |
3088 { // Ok to use this sample | 3331 { // Ok to use this sample |
3089 if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS)) | 3332 if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS)) |
3090 { | 3333 { |
3091 Ptr<TcpOptionTS> ts; | 3334 Ptr<const TcpOptionTS> ts; |
3092 ts = DynamicCast<TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS)
); | 3335 ts = DynamicCast<const TcpOptionTS> (tcpHeader.GetOption (TcpOptio
n::TS)); |
3093 m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ()); | 3336 m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ()); |
3094 } | 3337 } |
3095 else | 3338 else |
3096 { | 3339 { |
3097 m = Simulator::Now () - h.time; // Elapsed time | 3340 m = Simulator::Now () - h.time; // Elapsed time |
3098 } | 3341 } |
3099 } | 3342 } |
3100 } | 3343 } |
3101 | 3344 |
3102 // Now delete all ack history with seq <= ack | 3345 // Now delete all ack history with seq <= ack |
(...skipping 17 matching lines...) Expand all Loading... |
3120 } | 3363 } |
3121 } | 3364 } |
3122 | 3365 |
3123 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd() | 3366 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd() |
3124 // when the three-way handshake completed. This cancels retransmission timer | 3367 // when the three-way handshake completed. This cancels retransmission timer |
3125 // and advances Tx window | 3368 // and advances Tx window |
3126 void | 3369 void |
3127 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO) | 3370 TcpSocketBase::NewAck (SequenceNumber32 const& ack, bool resetRTO) |
3128 { | 3371 { |
3129 NS_LOG_FUNCTION (this << ack); | 3372 NS_LOG_FUNCTION (this << ack); |
| 3373 |
| 3374 // Reset the data retransmission count. We got a new ACK! |
| 3375 m_dataRetrCount = m_dataRetries; |
3130 | 3376 |
3131 if (m_state != SYN_RCVD && resetRTO) | 3377 if (m_state != SYN_RCVD && resetRTO) |
3132 { // Set RTO unless the ACK is received in SYN_RCVD state | 3378 { // Set RTO unless the ACK is received in SYN_RCVD state |
3133 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir
e at " << | 3379 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir
e at " << |
3134 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).
GetSeconds ()); | 3380 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).
GetSeconds ()); |
3135 m_retxEvent.Cancel (); | 3381 m_retxEvent.Cancel (); |
3136 // On receiving a "New" ack we restart retransmission timer .. RFC 6298 | 3382 // On receiving a "New" ack we restart retransmission timer .. RFC 6298 |
3137 // RFC 6298, clause 2.4 | 3383 // RFC 6298, clause 2.4 |
3138 m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVa
riation () * 4), m_minRto); | 3384 m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVa
riation () * 4), m_minRto); |
3139 | 3385 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3173 if (m_state == CLOSED || m_state == TIME_WAIT) | 3419 if (m_state == CLOSED || m_state == TIME_WAIT) |
3174 { | 3420 { |
3175 return; | 3421 return; |
3176 } | 3422 } |
3177 // If all data are received (non-closing socket and nothing to send), just ret
urn | 3423 // If all data are received (non-closing socket and nothing to send), just ret
urn |
3178 if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMa
rk) | 3424 if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMa
rk) |
3179 { | 3425 { |
3180 return; | 3426 return; |
3181 } | 3427 } |
3182 | 3428 |
| 3429 // From RFC 6675, Section 5.1 |
| 3430 // [RFC2018] suggests that a TCP sender SHOULD expunge the SACK |
| 3431 // information gathered from a receiver upon a retransmission timeout |
| 3432 // (RTO) "since the timeout might indicate that the data receiver has |
| 3433 // reneged." Additionally, a TCP sender MUST "ignore prior SACK |
| 3434 // information in determining which data to retransmit." |
| 3435 if (!m_sackEnabled) |
| 3436 { |
| 3437 // If SACK is not enabled, give up with all sack blocks we crafted |
| 3438 // m_txBuffer->ResetScoreboard (); |
| 3439 // And move all the sent packet into the unsent, again. (ResetScoreboard |
| 3440 // is done inside that function) |
| 3441 m_txBuffer->ResetSentList (); |
| 3442 } |
| 3443 else |
| 3444 { |
| 3445 // Continuing from RFC 6675, Section 5.1 |
| 3446 // It has been suggested that, as long as robust tests for |
| 3447 // reneging are present, an implementation can retain and use SACK |
| 3448 // information across a timeout event [Errata1610] |
| 3449 |
| 3450 // Please note that BytesInFlight should reflect the fact that all our |
| 3451 // sent list is considered lost. The following line could be a start, |
| 3452 // but we miss tests for reneging right now. So, be safe. |
| 3453 // m_txBuffer->SetSentListLost (); |
| 3454 m_txBuffer->ResetSentList (); |
| 3455 } |
| 3456 |
| 3457 // From RFC 6675, Section 5.1 |
| 3458 // If an RTO occurs during loss recovery as specified in this document, |
| 3459 // RecoveryPoint MUST be set to HighData. Further, the new value of |
| 3460 // RecoveryPoint MUST be preserved and the loss recovery algorithm |
| 3461 // outlined in this document MUST be terminated. |
3183 m_recover = m_tcb->m_highTxMark; | 3462 m_recover = m_tcb->m_highTxMark; |
3184 Retransmit (); | 3463 |
| 3464 // RFC 6298, clause 2.5, double the timer |
| 3465 Time doubledRto = m_rto + m_rto; |
| 3466 m_rto = Min (doubledRto, Time::FromDouble (60, Time::S)); |
| 3467 |
| 3468 // Empty RTT history |
| 3469 m_history.clear (); |
| 3470 |
| 3471 // Reset dupAckCount |
| 3472 m_dupAckCount = 0; |
| 3473 |
| 3474 // Please don't reset highTxMark, it is used for retransmission detection |
| 3475 |
| 3476 // When a TCP sender detects segment loss using the retransmission timer |
| 3477 // and the given segment has not yet been resent by way of the |
| 3478 // retransmission timer, decrease ssThresh |
| 3479 if (m_tcb->m_congState != TcpSocketState::CA_LOSS || !m_txBuffer->IsHeadRetran
smitted ()) |
| 3480 { |
| 3481 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, BytesInFlight
()); |
| 3482 } |
| 3483 |
| 3484 // Cwnd set to 1 MSS |
| 3485 m_tcb->m_cWnd = m_tcb->m_segmentSize; |
| 3486 |
| 3487 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS); |
| 3488 m_tcb->m_congState = TcpSocketState::CA_LOSS; |
| 3489 |
| 3490 NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " << |
| 3491 m_tcb->m_ssThresh << ", restart from seqnum " << |
| 3492 m_txBuffer->HeadSequence () << " doubled rto to " << |
| 3493 m_rto.Get ().GetSeconds () << " s"); |
| 3494 |
| 3495 NS_ASSERT_MSG (BytesInFlight () == 0, "There are some bytes in flight after an
RTO: " << |
| 3496 BytesInFlight ()); |
| 3497 |
| 3498 // Retransmit the packet |
| 3499 DoRetransmit (); |
| 3500 |
| 3501 NS_ASSERT_MSG (BytesInFlight () <= m_tcb->m_segmentSize, |
| 3502 "In flight there is more than one segment"); |
3185 } | 3503 } |
3186 | 3504 |
3187 void | 3505 void |
3188 TcpSocketBase::DelAckTimeout (void) | 3506 TcpSocketBase::DelAckTimeout (void) |
3189 { | 3507 { |
3190 m_delAckCount = 0; | 3508 m_delAckCount = 0; |
3191 if (m_ecnState == ECN_CE_RCVD || m_ecnState == ECN_ECE_SENT) | 3509 if (m_tcb->m_ecnState == TcpSocketState::ECN_CE_RCVD || m_tcb->m_ecnState == T
cpSocketState::ECN_ECE_SENT) |
3192 { | 3510 { |
3193 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); | 3511 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); |
3194 m_ecnState = ECN_ECE_SENT; | 3512 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_SENT; |
3195 } | 3513 } |
3196 else | 3514 else |
3197 { | 3515 { |
3198 SendEmptyPacket (TcpHeader::ACK); | 3516 SendEmptyPacket (TcpHeader::ACK); |
3199 } | 3517 } |
3200 } | 3518 } |
3201 | 3519 |
3202 void | 3520 void |
3203 TcpSocketBase::LastAckTimeout (void) | 3521 TcpSocketBase::LastAckTimeout (void) |
3204 { | 3522 { |
(...skipping 12 matching lines...) Expand all Loading... |
3217 | 3535 |
3218 // Send 1-byte data to probe for the window size at the receiver when | 3536 // Send 1-byte data to probe for the window size at the receiver when |
3219 // the local knowledge tells that the receiver has zero window size | 3537 // the local knowledge tells that the receiver has zero window size |
3220 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17 | 3538 // C.f.: RFC793 p.42, RFC1112 sec.4.2.2.17 |
3221 void | 3539 void |
3222 TcpSocketBase::PersistTimeout () | 3540 TcpSocketBase::PersistTimeout () |
3223 { | 3541 { |
3224 NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ())
; | 3542 NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ())
; |
3225 m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // ma
x persist timeout = 60s | 3543 m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // ma
x persist timeout = 60s |
3226 Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence); | 3544 Ptr<Packet> p = m_txBuffer->CopyFromSequence (1, m_tcb->m_nextTxSequence); |
| 3545 m_txBuffer->ResetLastSegmentSent (); |
3227 TcpHeader tcpHeader; | 3546 TcpHeader tcpHeader; |
3228 tcpHeader.SetSequenceNumber (m_tcb->m_nextTxSequence); | 3547 tcpHeader.SetSequenceNumber (m_tcb->m_nextTxSequence); |
3229 tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ()); | 3548 tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ()); |
3230 tcpHeader.SetWindowSize (AdvertisedWindowSize ()); | 3549 tcpHeader.SetWindowSize (AdvertisedWindowSize ()); |
3231 if (m_endPoint != 0) | 3550 if (m_endPoint != 0) |
3232 { | 3551 { |
3233 tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ()); | 3552 tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ()); |
3234 tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ()); | 3553 tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ()); |
3235 } | 3554 } |
3236 else | 3555 else |
3237 { | 3556 { |
3238 tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ()); | 3557 tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ()); |
3239 tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ()); | 3558 tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ()); |
3240 } | 3559 } |
3241 AddOptions (tcpHeader); | 3560 AddOptions (tcpHeader); |
3242 //Send a packet tag for setting ECT bits in IP header | 3561 //Send a packet tag for setting ECT bits in IP header |
3243 if (m_ecnState != ECN_DISABLED) | 3562 if (m_tcb->m_ecnState != TcpSocketState::ECN_DISABLED) |
3244 { | 3563 { |
3245 SocketIpTosTag ipTosTag; | 3564 SocketIpTosTag ipTosTag; |
3246 ipTosTag.SetTos (0x02); | 3565 ipTosTag.SetTos (0x02); |
3247 p->AddPacketTag (ipTosTag); | 3566 p->AddPacketTag (ipTosTag); |
3248 · | 3567 · |
3249 SocketIpv6TclassTag ipTclassTag; | 3568 SocketIpv6TclassTag ipTclassTag; |
3250 ipTclassTag.SetTclass (0x02); | 3569 ipTclassTag.SetTclass (0x02); |
3251 p->AddPacketTag (ipTclassTag); | 3570 p->AddPacketTag (ipTclassTag); |
3252 } | 3571 } |
3253 m_txTrace (p, tcpHeader, this); | 3572 m_txTrace (p, tcpHeader, this); |
3254 | 3573 |
3255 if (m_endPoint != 0) | 3574 if (m_endPoint != 0) |
3256 { | 3575 { |
3257 m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (), | 3576 m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (), |
3258 m_endPoint->GetPeerAddress (), m_boundnetdevice); | 3577 m_endPoint->GetPeerAddress (), m_boundnetdevice); |
3259 } | 3578 } |
3260 else | 3579 else |
3261 { | 3580 { |
3262 m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (), | 3581 m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (), |
3263 m_endPoint6->GetPeerAddress (), m_boundnetdevice); | 3582 m_endPoint6->GetPeerAddress (), m_boundnetdevice); |
3264 } | 3583 } |
3265 | 3584 |
3266 NS_LOG_LOGIC ("Schedule persist timeout at time " | 3585 NS_LOG_LOGIC ("Schedule persist timeout at time " |
3267 << Simulator::Now ().GetSeconds () << " to expire at time " | 3586 << Simulator::Now ().GetSeconds () << " to expire at time " |
3268 << (Simulator::Now () + m_persistTimeout).GetSeconds ()); | 3587 << (Simulator::Now () + m_persistTimeout).GetSeconds ()); |
3269 m_persistEvent = Simulator::Schedule (m_persistTimeout, &TcpSocketBase::Persis
tTimeout, this); | 3588 m_persistEvent = Simulator::Schedule (m_persistTimeout, &TcpSocketBase::Persis
tTimeout, this); |
3270 } | |
3271 | |
3272 void | |
3273 TcpSocketBase::Retransmit () | |
3274 { | |
3275 // If erroneous timeout in closed/timed-wait state, just return | |
3276 if (m_state == CLOSED || m_state == TIME_WAIT) | |
3277 { | |
3278 return; | |
3279 } | |
3280 // If all data are received (non-closing socket and nothing to send), just ret
urn | |
3281 if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_tcb->m_highTxMa
rk) | |
3282 { | |
3283 return; | |
3284 } | |
3285 | |
3286 /* | |
3287 * When a TCP sender detects segment loss using the retransmission timer | |
3288 * and the given segment has not yet been resent by way of the | |
3289 * retransmission timer, the value of ssthresh MUST be set to no more | |
3290 * than the value given in equation (4): | |
3291 * | |
3292 * ssthresh = max (FlightSize / 2, 2*SMSS) (4) | |
3293 * | |
3294 * where, as discussed above, FlightSize is the amount of outstanding | |
3295 * data in the network. | |
3296 * | |
3297 * On the other hand, when a TCP sender detects segment loss using the | |
3298 * retransmission timer and the given segment has already been | |
3299 * retransmitted by way of the retransmission timer at least once, the | |
3300 * value of ssthresh is held constant. | |
3301 * | |
3302 * Conditions to decrement slow - start threshold are as follows: | |
3303 * | |
3304 * *) The TCP state should be less than disorder, which is nothing but open. | |
3305 * If we are entering into the loss state from the open state, we have not yet | |
3306 * reduced the slow - start threshold for the window of data. (Nat: Recovery?) | |
3307 * *) If we have entered the loss state with all the data pointed to by high_s
eq | |
3308 * acknowledged. Once again it means that in whatever state we are (other than | |
3309 * open state), all the data from the window that got us into the state, prior
to | |
3310 * retransmission timer expiry, has been acknowledged. (Nat: How this can happ
en?) | |
3311 * *) If the above two conditions fail, we still have one more condition that
can | |
3312 * demand reducing the slow - start threshold: If we are already in the loss s
tate | |
3313 * and have not yet retransmitted anything. The condition may arise in case we | |
3314 * are not able to retransmit anything because of local congestion. | |
3315 */ | |
3316 | |
3317 if (m_tcb->m_congState != TcpSocketState::CA_LOSS) | |
3318 { | |
3319 m_congestionControl->CongestionStateSet (m_tcb, TcpSocketState::CA_LOSS); | |
3320 m_tcb->m_congState = TcpSocketState::CA_LOSS; | |
3321 m_tcb->m_ssThresh = m_congestionControl->GetSsThresh (m_tcb, BytesInFlight
()); | |
3322 m_tcb->m_cWnd = m_tcb->m_segmentSize; | |
3323 } | |
3324 | |
3325 m_tcb->m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest
Ack | |
3326 m_dupAckCount = 0; | |
3327 | |
3328 NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " << | |
3329 m_tcb->m_ssThresh << ", restart from seqnum " << m_tcb->m_nextTx
Sequence); | |
3330 DoRetransmit (); // Retransmit the packet | |
3331 } | 3589 } |
3332 | 3590 |
3333 void | 3591 void |
3334 TcpSocketBase::DoRetransmit () | 3592 TcpSocketBase::DoRetransmit () |
3335 { | 3593 { |
3336 NS_LOG_FUNCTION (this); | 3594 NS_LOG_FUNCTION (this); |
3337 // Retransmit SYN packet | 3595 // Retransmit SYN packet |
3338 if (m_state == SYN_SENT) | 3596 if (m_state == SYN_SENT) |
3339 { | 3597 { |
3340 if (m_synCount > 0) | 3598 if (m_synCount > 0) |
3341 { | 3599 { |
3342 if (m_ecn) | 3600 if (m_ecn) |
3343 { | 3601 { |
3344 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ECE | TcpHeader::CWR)
; | 3602 SendEmptyPacket (TcpHeader::SYN | TcpHeader::ECE | TcpHeader::CWR)
; |
3345 } | 3603 } |
3346 else | 3604 else |
3347 { | 3605 { |
3348 SendEmptyPacket (TcpHeader::SYN); | 3606 SendEmptyPacket (TcpHeader::SYN); |
3349 } | 3607 } |
3350 m_ecnState = ECN_DISABLED; | 3608 m_tcb->m_ecnState = TcpSocketState::ECN_DISABLED; |
3351 } | 3609 } |
3352 else | 3610 else |
3353 { | 3611 { |
3354 NotifyConnectionFailed (); | 3612 NotifyConnectionFailed (); |
3355 } | 3613 } |
3356 return; | 3614 return; |
3357 } | 3615 } |
3358 | 3616 |
3359 if (m_dataRetrCount == 0) | 3617 if (m_dataRetrCount == 0) |
3360 { | 3618 { |
(...skipping 11 matching lines...) Expand all Loading... |
3372 if (m_txBuffer->Size () == 0) | 3630 if (m_txBuffer->Size () == 0) |
3373 { | 3631 { |
3374 if (m_state == FIN_WAIT_1 || m_state == CLOSING) | 3632 if (m_state == FIN_WAIT_1 || m_state == CLOSING) |
3375 { // Must have lost FIN, re-send | 3633 { // Must have lost FIN, re-send |
3376 SendEmptyPacket (TcpHeader::FIN); | 3634 SendEmptyPacket (TcpHeader::FIN); |
3377 } | 3635 } |
3378 return; | 3636 return; |
3379 } | 3637 } |
3380 | 3638 |
3381 // Retransmit a data packet: Call SendDataPacket | 3639 // Retransmit a data packet: Call SendDataPacket |
| 3640 SequenceNumber32 oldSequence = m_tcb->m_nextTxSequence; |
| 3641 m_tcb->m_nextTxSequence = m_txBuffer->HeadSequence (); |
3382 uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_tcb->m_segmentSiz
e, true); | 3642 uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_tcb->m_segmentSiz
e, true); |
3383 ++m_retransOut; | |
3384 | 3643 |
3385 // In case of RTO, advance m_tcb->m_nextTxSequence | 3644 // In case of RTO, advance m_tcb->m_nextTxSequence |
3386 m_tcb->m_nextTxSequence = std::max (m_tcb->m_nextTxSequence.Get (), m_txBuffer
->HeadSequence () + sz); | 3645 if (oldSequence == m_tcb->m_nextTxSequence.Get ()) |
| 3646 { |
| 3647 m_tcb->m_nextTxSequence = std::max (m_tcb->m_nextTxSequence.Get (), m_txBu
ffer->HeadSequence () + sz); |
| 3648 } |
| 3649 else |
| 3650 { |
| 3651 m_tcb->m_nextTxSequence = oldSequence; |
| 3652 } |
3387 | 3653 |
3388 NS_LOG_DEBUG ("retxing seq " << m_txBuffer->HeadSequence ()); | 3654 NS_LOG_DEBUG ("retxing seq " << m_txBuffer->HeadSequence ()); |
3389 } | 3655 } |
3390 | 3656 |
3391 void | 3657 void |
3392 TcpSocketBase::CancelAllTimers () | 3658 TcpSocketBase::CancelAllTimers () |
3393 { | 3659 { |
3394 m_retxEvent.Cancel (); | 3660 m_retxEvent.Cancel (); |
3395 m_persistEvent.Cancel (); | 3661 m_persistEvent.Cancel (); |
3396 m_delAckEvent.Cancel (); | 3662 m_delAckEvent.Cancel (); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3433 NS_LOG_FUNCTION (this << size); | 3699 NS_LOG_FUNCTION (this << size); |
3434 uint32_t oldSize = GetRcvBufSize (); | 3700 uint32_t oldSize = GetRcvBufSize (); |
3435 | 3701 |
3436 m_rxBuffer->SetMaxBufferSize (size); | 3702 m_rxBuffer->SetMaxBufferSize (size); |
3437 | 3703 |
3438 /* The size has (manually) increased. Actively inform the other end to prevent | 3704 /* The size has (manually) increased. Actively inform the other end to prevent |
3439 * stale zero-window states. | 3705 * stale zero-window states. |
3440 */ | 3706 */ |
3441 if (oldSize < size && m_connected) | 3707 if (oldSize < size && m_connected) |
3442 { | 3708 { |
3443 if (m_ecnState == ECN_CE_RCVD || m_ecnState == ECN_ECE_SENT) | 3709 if (m_tcb->m_ecnState == TcpSocketState::ECN_CE_RCVD || m_tcb->m_ecnState
== TcpSocketState::ECN_ECE_SENT) |
3444 { | 3710 { |
3445 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); | 3711 SendEmptyPacket (TcpHeader::ACK | TcpHeader::ECE); |
3446 m_ecnState = ECN_ECE_SENT; | 3712 m_tcb->m_ecnState = TcpSocketState::ECN_ECE_SENT; |
3447 NS_LOG_DEBUG (EcnStateName[m_ecnState] << " -> ECN_ECE_SENT"); | 3713 NS_LOG_DEBUG (TcpSocketState::EcnStateName[m_tcb->m_ecnState] << " ->
ECN_ECE_SENT"); |
3448 } | 3714 } |
3449 else | 3715 else |
3450 { | 3716 { |
3451 SendEmptyPacket (TcpHeader::ACK); | 3717 SendEmptyPacket (TcpHeader::ACK); |
3452 } | 3718 } |
3453 } | 3719 } |
3454 } | 3720 } |
3455 | 3721 |
3456 uint32_t | 3722 uint32_t |
3457 TcpSocketBase::GetRcvBufSize (void) const | 3723 TcpSocketBase::GetRcvBufSize (void) const |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3648 | 3914 |
3649 m_rcvWindShift = CalculateWScale (); | 3915 m_rcvWindShift = CalculateWScale (); |
3650 option->SetScale (m_rcvWindShift); | 3916 option->SetScale (m_rcvWindShift); |
3651 | 3917 |
3652 header.AppendOption (option); | 3918 header.AppendOption (option); |
3653 | 3919 |
3654 NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " << | 3920 NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " << |
3655 static_cast<int> (m_rcvWindShift)); | 3921 static_cast<int> (m_rcvWindShift)); |
3656 } | 3922 } |
3657 | 3923 |
| 3924 bool |
| 3925 TcpSocketBase::ProcessOptionSack (const Ptr<const TcpOption> option) |
| 3926 { |
| 3927 NS_LOG_FUNCTION (this << option); |
| 3928 |
| 3929 Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option); |
| 3930 TcpOptionSack::SackList list = s->GetSackList (); |
| 3931 return m_txBuffer->Update (list); |
| 3932 } |
| 3933 |
| 3934 void |
| 3935 TcpSocketBase::ProcessOptionSackPermitted (const Ptr<const TcpOption> option) |
| 3936 { |
| 3937 NS_LOG_FUNCTION (this << option); |
| 3938 |
| 3939 Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted
> (option); |
| 3940 |
| 3941 NS_ASSERT (m_sackEnabled == true); |
| 3942 NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s); |
| 3943 } |
| 3944 |
| 3945 void |
| 3946 TcpSocketBase::AddOptionSackPermitted (TcpHeader &header) |
| 3947 { |
| 3948 NS_LOG_FUNCTION (this << header); |
| 3949 NS_ASSERT (header.GetFlags () & TcpHeader::SYN); |
| 3950 |
| 3951 Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> (); |
| 3952 header.AppendOption (option); |
| 3953 NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED"); |
| 3954 } |
| 3955 |
| 3956 void |
| 3957 TcpSocketBase::AddOptionSack (TcpHeader& header) |
| 3958 { |
| 3959 NS_LOG_FUNCTION (this << header); |
| 3960 |
| 3961 // Calculate the number of SACK blocks allowed in this packet |
| 3962 uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength
(); |
| 3963 uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8; |
| 3964 |
| 3965 TcpOptionSack::SackList sackList = m_rxBuffer->GetSackList (); |
| 3966 if (allowedSackBlocks == 0 || sackList.empty ()) |
| 3967 { |
| 3968 NS_LOG_LOGIC ("No space available or sack list empty, not adding sack bloc
ks"); |
| 3969 return; |
| 3970 } |
| 3971 |
| 3972 // Append the allowed number of SACK blocks |
| 3973 Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> (); |
| 3974 TcpOptionSack::SackList::iterator i; |
| 3975 for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i
) |
| 3976 { |
| 3977 NS_LOG_LOGIC ("Left edge of the block: " << (*i).first << " Right edge of
the block: " << (*i).second); |
| 3978 option->AddSackBlock (*i); |
| 3979 allowedSackBlocks--; |
| 3980 } |
| 3981 |
| 3982 header.AppendOption (option); |
| 3983 NS_LOG_INFO (m_node->GetId () << " Add option SACK"); |
| 3984 } |
| 3985 |
3658 void | 3986 void |
3659 TcpSocketBase::ProcessOptionTimestamp (const Ptr<const TcpOption> option, | 3987 TcpSocketBase::ProcessOptionTimestamp (const Ptr<const TcpOption> option, |
3660 const SequenceNumber32 &seq) | 3988 const SequenceNumber32 &seq) |
3661 { | 3989 { |
3662 NS_LOG_FUNCTION (this << option); | 3990 NS_LOG_FUNCTION (this << option); |
3663 | 3991 |
3664 Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option); | 3992 Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option); |
| 3993 |
| 3994 m_tcb->m_rcvTimestampValue = ts->GetTimestamp (); |
| 3995 m_tcb->m_rcvTimestampEchoReply = ts->GetEcho(); |
3665 | 3996 |
3666 if (seq == m_rxBuffer->NextRxSequence () && seq <= m_highTxAck) | 3997 if (seq == m_rxBuffer->NextRxSequence () && seq <= m_highTxAck) |
3667 { | 3998 { |
3668 m_timestampToEcho = ts->GetTimestamp (); | 3999 m_timestampToEcho = ts->GetTimestamp (); |
3669 } | 4000 } |
3670 | 4001 |
3671 NS_LOG_INFO (m_node->GetId () << " Got timestamp=" << | 4002 NS_LOG_INFO (m_node->GetId () << " Got timestamp=" << |
3672 m_timestampToEcho << " and Echo=" << ts->GetEcho ()); | 4003 m_timestampToEcho << " and Echo=" << ts->GetEcho ()); |
3673 } | 4004 } |
3674 | 4005 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3782 } | 4113 } |
3783 | 4114 |
3784 void | 4115 void |
3785 TcpSocketBase::UpdateCongState (TcpSocketState::TcpCongState_t oldValue, | 4116 TcpSocketBase::UpdateCongState (TcpSocketState::TcpCongState_t oldValue, |
3786 TcpSocketState::TcpCongState_t newValue) | 4117 TcpSocketState::TcpCongState_t newValue) |
3787 { | 4118 { |
3788 m_congStateTrace (oldValue, newValue); | 4119 m_congStateTrace (oldValue, newValue); |
3789 } | 4120 } |
3790 | 4121 |
3791 void | 4122 void |
| 4123 TcpSocketBase::UpdateEcnState (TcpSocketState::EcnState_t oldValue, |
| 4124 TcpSocketState::EcnState_t newValue) |
| 4125 { |
| 4126 m_ecnStateTrace (oldValue, newValue); |
| 4127 } |
| 4128 |
| 4129 void |
3792 TcpSocketBase::UpdateNextTxSequence (SequenceNumber32 oldValue, | 4130 TcpSocketBase::UpdateNextTxSequence (SequenceNumber32 oldValue, |
3793 SequenceNumber32 newValue) | 4131 SequenceNumber32 newValue) |
3794 | 4132 |
3795 { | 4133 { |
3796 m_nextTxSequenceTrace (oldValue, newValue); | 4134 m_nextTxSequenceTrace (oldValue, newValue); |
3797 } | 4135 } |
3798 | 4136 |
3799 void | 4137 void |
3800 TcpSocketBase::UpdateHighTxMark (SequenceNumber32 oldValue, SequenceNumber32 new
Value) | 4138 TcpSocketBase::UpdateHighTxMark (SequenceNumber32 oldValue, SequenceNumber32 new
Value) |
3801 { | 4139 { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3843 | 4181 |
3844 RttHistory::RttHistory (const RttHistory& h) | 4182 RttHistory::RttHistory (const RttHistory& h) |
3845 : seq (h.seq), | 4183 : seq (h.seq), |
3846 count (h.count), | 4184 count (h.count), |
3847 time (h.time), | 4185 time (h.time), |
3848 retx (h.retx) | 4186 retx (h.retx) |
3849 { | 4187 { |
3850 } | 4188 } |
3851 | 4189 |
3852 } // namespace ns3 | 4190 } // namespace ns3 |
LEFT | RIGHT |