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) 2014 Natale Patriciello <natale.patriciello@gmail.com> | 3 * Copyright (c) 2014 Natale Patriciello <natale.patriciello@gmail.com> |
4 * | 4 * |
5 * This program is free software; you can redistribute it and/or modify | 5 * This program is free software; you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 2 as | 6 * it under the terms of the GNU General Public License version 2 as |
7 * published by the Free Software Foundation; | 7 * published by the Free Software Foundation; |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 17 matching lines...) Expand all Loading... |
28 namespace ns3 { | 28 namespace ns3 { |
29 | 29 |
30 NS_OBJECT_ENSURE_REGISTERED (TcpCubic); | 30 NS_OBJECT_ENSURE_REGISTERED (TcpCubic); |
31 | 31 |
32 TypeId | 32 TypeId |
33 TcpCubic::GetTypeId (void) | 33 TcpCubic::GetTypeId (void) |
34 { | 34 { |
35 static TypeId tid = TypeId ("ns3::TcpCubic") | 35 static TypeId tid = TypeId ("ns3::TcpCubic") |
36 .SetParent<TcpSocketBase> () | 36 .SetParent<TcpSocketBase> () |
37 .AddConstructor<TcpCubic> () | 37 .AddConstructor<TcpCubic> () |
| 38 .SetGroupName ("Internet") |
38 .AddAttribute ("FastConvergence", "Enable (true) or disable (false) fast con
vergence", | 39 .AddAttribute ("FastConvergence", "Enable (true) or disable (false) fast con
vergence", |
39 BooleanValue (true), | 40 BooleanValue (true), |
40 MakeBooleanAccessor (&TcpCubic::m_fastConvergence), | 41 MakeBooleanAccessor (&TcpCubic::m_fastConvergence), |
41 MakeBooleanChecker ()) | 42 MakeBooleanChecker ()) |
42 .AddAttribute ("Beta", "Beta for multiplicative increase", | 43 .AddAttribute ("Beta", "Beta for multiplicative decrease", |
43 DoubleValue (0.8), | 44 DoubleValue (0.8), |
44 MakeDoubleAccessor (&TcpCubic::m_beta), | 45 MakeDoubleAccessor (&TcpCubic::m_beta), |
45 MakeDoubleChecker <double> (0.0)) | 46 MakeDoubleChecker <double> (0.0)) |
46 .AddAttribute ("HyStart", "Enable (true) or disable (false) hybrid slow star
t algorithm", | 47 .AddAttribute ("HyStart", "Enable (true) or disable (false) hybrid slow star
t algorithm", |
47 BooleanValue (false), | 48 BooleanValue (false), |
48 MakeBooleanAccessor (&TcpCubic::m_hystart), | 49 MakeBooleanAccessor (&TcpCubic::m_hystart), |
49 MakeBooleanChecker ()) | 50 MakeBooleanChecker ()) |
50 .AddAttribute ("HyStartLowWindow", "Lower bound cWnd for hybrid slow start (
segments)", | 51 .AddAttribute ("HyStartLowWindow", "Lower bound cWnd for hybrid slow start (
segments)", |
51 UintegerValue (16), | 52 UintegerValue (16), |
52 MakeUintegerAccessor (&TcpCubic::m_hystartLowWindow), | 53 MakeUintegerAccessor (&TcpCubic::m_hystartLowWindow), |
53 MakeUintegerChecker <uint32_t> ()) | 54 MakeUintegerChecker <uint32_t> ()) |
54 .AddAttribute ("HyStartDetect", "Hybrid Slow Start detection mechanisms:" \ | 55 .AddAttribute ("HyStartDetect", "Hybrid Slow Start detection mechanisms:" \ |
55 "1: packet train, 2: delay, 3: both", | 56 "1: packet train, 2: delay, 3: both", |
56 IntegerValue (3), | 57 IntegerValue (3), |
57 MakeIntegerAccessor (&TcpCubic::m_hystartDetect), | 58 MakeIntegerAccessor (&TcpCubic::m_hystartDetect), |
58 MakeIntegerChecker <int> ()) | 59 MakeIntegerChecker <int> (1,3)) |
59 .AddAttribute ("HyStartMinSamples", "Number of delay samples for detecting t
he increase of delay", | 60 .AddAttribute ("HyStartMinSamples", "Number of delay samples for detecting t
he increase of delay", |
60 UintegerValue (8), | 61 UintegerValue (8), |
61 MakeUintegerAccessor (&TcpCubic::m_hystartMinSamples), | 62 MakeUintegerAccessor (&TcpCubic::m_hystartMinSamples), |
62 MakeUintegerChecker <uint8_t> ()) | 63 MakeUintegerChecker <uint8_t> ()) |
63 .AddAttribute ("HyStartAckDelta", "Spacing between ack's indicating train", | 64 .AddAttribute ("HyStartAckDelta", "Spacing between ack's indicating train", |
64 TimeValue (MilliSeconds (2)), | 65 TimeValue (MilliSeconds (2)), |
65 MakeTimeAccessor (&TcpCubic::m_hystartAckDelta), | 66 MakeTimeAccessor (&TcpCubic::m_hystartAckDelta), |
66 MakeTimeChecker ()) | 67 MakeTimeChecker ()) |
67 .AddAttribute ("HyStartDelayMin", "Minimum time for hystart algorithm", | 68 .AddAttribute ("HyStartDelayMin", "Minimum time for hystart algorithm", |
68 TimeValue (MilliSeconds (4)), | 69 TimeValue (MilliSeconds (4)), |
(...skipping 19 matching lines...) Expand all Loading... |
88 MakeDoubleAccessor (&TcpCubic::m_c), | 89 MakeDoubleAccessor (&TcpCubic::m_c), |
89 MakeDoubleChecker <double> (0.0)) | 90 MakeDoubleChecker <double> (0.0)) |
90 .AddTraceSource ("CongestionWindow", | 91 .AddTraceSource ("CongestionWindow", |
91 "The TCP connection's congestion window", | 92 "The TCP connection's congestion window", |
92 MakeTraceSourceAccessor (&TcpCubic::m_cWnd), | 93 MakeTraceSourceAccessor (&TcpCubic::m_cWnd), |
93 "ns3::TracedValue::Uint32Callback") | 94 "ns3::TracedValue::Uint32Callback") |
94 .AddTraceSource ("SlowStartThreshold", | 95 .AddTraceSource ("SlowStartThreshold", |
95 "TCP slow start threshold (bytes)", | 96 "TCP slow start threshold (bytes)", |
96 MakeTraceSourceAccessor (&TcpCubic::m_ssThresh), | 97 MakeTraceSourceAccessor (&TcpCubic::m_ssThresh), |
97 "ns3::TracedValue::Uint32Callback") | 98 "ns3::TracedValue::Uint32Callback") |
| 99 .AddTraceSource ("CubicState", |
| 100 "State of TCP Cubic", |
| 101 MakeTraceSourceAccessor (&TcpCubic::m_cubicState), |
| 102 "ns3::TracedValue::Uint8Callback") |
98 ; | 103 ; |
99 return tid; | 104 return tid; |
100 } | 105 } |
101 | 106 |
102 TcpCubic::TcpCubic () : TcpSocketBase () | 107 TcpCubic::TcpCubic () : TcpSocketBase () |
103 { | 108 { |
104 NS_LOG_FUNCTION_NOARGS (); | 109 NS_LOG_FUNCTION_NOARGS (); |
105 m_cWndCnt = 0; | 110 m_cWndCnt = 0; |
106 } | 111 } |
107 | 112 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 m_bicOriginPoint = m_lastMaxCwnd; | 246 m_bicOriginPoint = m_lastMaxCwnd; |
242 NS_LOG_DEBUG ("Wow K=" << m_bicK << " and origin=" << m_lastMaxCwnd); | 247 NS_LOG_DEBUG ("Wow K=" << m_bicK << " and origin=" << m_lastMaxCwnd); |
243 } | 248 } |
244 } | 249 } |
245 | 250 |
246 t = Simulator::Now () + m_delayMin - m_epochStart; | 251 t = Simulator::Now () + m_delayMin - m_epochStart; |
247 | 252 |
248 if (t.GetSeconds () < m_bicK) /* t - K */ | 253 if (t.GetSeconds () < m_bicK) /* t - K */ |
249 { | 254 { |
250 offs = m_bicK - t.GetSeconds (); | 255 offs = m_bicK - t.GetSeconds (); |
251 NS_LOG_DEBUG ("t=" << t.GetSeconds() << " <k: offs=" << offs); | 256 NS_LOG_DEBUG ("t=" << t.GetSeconds () << " <k: offs=" << offs); |
252 } | 257 } |
253 else | 258 else |
254 { | 259 { |
255 offs = t.GetSeconds () - m_bicK; | 260 offs = t.GetSeconds () - m_bicK; |
256 NS_LOG_DEBUG ("t=" << t.GetSeconds() << " >= k: offs=" << offs); | 261 NS_LOG_DEBUG ("t=" << t.GetSeconds () << " >= k: offs=" << offs); |
257 } | 262 } |
258 | 263 |
259 | 264 |
260 /* Constant value taken from Experimental Evaluation of Cubic Tcp, available a
t | 265 /* Constant value taken from Experimental Evaluation of Cubic Tcp, available a
t |
261 * eprints.nuim.ie/1716/1/Hamiltonpfldnet2007_cubic_final.pdf */ | 266 * eprints.nuim.ie/1716/1/Hamiltonpfldnet2007_cubic_final.pdf */ |
262 delta = m_c * std::pow (offs, 3); | 267 delta = m_c * std::pow (offs, 3); |
263 | 268 |
264 NS_LOG_DEBUG ("delta: " << delta); | 269 NS_LOG_DEBUG ("delta: " << delta); |
265 | 270 |
266 if (t.GetSeconds () < m_bicK) /* below origin*/ | 271 if (t.GetSeconds () < m_bicK) /* below origin*/ |
267 { | 272 { |
268 bicTarget = m_bicOriginPoint - delta; | 273 bicTarget = m_bicOriginPoint - delta; |
269 NS_LOG_DEBUG ("t < k: Bic Target: " << bicTarget); | 274 NS_LOG_DEBUG ("t < k: Bic Target: " << bicTarget); |
270 } | 275 } |
271 else /* above origin*/ | 276 else /* above origin*/ |
272 { | 277 { |
273 bicTarget = m_bicOriginPoint + delta; | 278 bicTarget = m_bicOriginPoint + delta; |
274 NS_LOG_DEBUG ("t >= k: Bic Target: " << bicTarget); | 279 NS_LOG_DEBUG ("t >= k: Bic Target: " << bicTarget); |
275 } | 280 } |
276 | 281 |
277 // Next the window target is converted into a cnt or count value. CUBIC will | 282 // Next the window target is converted into a cnt or count value. CUBIC will |
278 // wait until enough new ACKs have arrived that a counter meets or exceeds | 283 // wait until enough new ACKs have arrived that a counter meets or exceeds |
279 // this cnt value. This is how the CUBIC implementation simulates growing | 284 // this cnt value. This is how the CUBIC implementation simulates growing |
280 // cwnd by values other than 1 segment size. | 285 // cwnd by values other than 1 segment size. |
281 if (bicTarget > segCwnd) | 286 if (bicTarget > segCwnd) |
282 { | 287 { |
283 cnt = segCwnd / (bicTarget - segCwnd); | 288 cnt = segCwnd / (bicTarget - segCwnd); |
284 NS_LOG_DEBUG ("target>cwnd. cnt=" << cnt); | 289 NS_LOG_DEBUG ("target>cwnd. cnt=" << cnt); |
285 } | 290 } |
286 else | 291 else |
287 { | 292 { |
288 cnt = 100 * segCwnd; | 293 cnt = 100 * segCwnd; |
289 } | 294 } |
290 | 295 |
291 if (m_lastMaxCwnd == 0 && cnt > m_cntClamp) | 296 if (m_lastMaxCwnd == 0 && cnt > m_cntClamp) |
292 { | 297 { |
293 cnt = m_cntClamp; | 298 cnt = m_cntClamp; |
294 } | 299 } |
295 | 300 |
296 if (cnt == 0) | 301 if (cnt == 0) |
297 { | 302 { |
298 cnt = 1; | 303 cnt = 1; |
299 } | 304 } |
300 | 305 |
301 NS_LOG_DEBUG ("After all, cnt=" << cnt); | 306 NS_LOG_DEBUG ("After all, cnt=" << cnt); |
302 | 307 |
303 return cnt; | 308 return cnt; |
304 } | 309 } |
305 | 310 |
306 void | 311 void |
307 TcpCubic::CongAvoid (const SequenceNumber32& seq) | 312 TcpCubic::CongAvoid (const SequenceNumber32& seq) |
308 { | 313 { |
309 NS_LOG_FUNCTION (this); | 314 NS_LOG_FUNCTION (this); |
310 if (m_cWnd.Get () < m_ssThresh) | 315 if (m_cWnd.Get () < m_ssThresh) |
311 { | 316 { |
(...skipping 11 matching lines...) Expand all Loading... |
323 uint32_t cnt = WindowUpdate (); | 328 uint32_t cnt = WindowUpdate (); |
324 | 329 |
325 // According to the CUBIC paper and RFC 6356 even once the new cwnd is | 330 // According to the CUBIC paper and RFC 6356 even once the new cwnd is |
326 // calculated you must compare this to the number of ACKs received since | 331 // calculated you must compare this to the number of ACKs received since |
327 // the last cwnd update. If not enough ACKs have been received then cwnd | 332 // the last cwnd update. If not enough ACKs have been received then cwnd |
328 // cannot be updated. | 333 // cannot be updated. |
329 if (m_cWndCnt > cnt) | 334 if (m_cWndCnt > cnt) |
330 { | 335 { |
331 m_cWnd += m_segmentSize; | 336 m_cWnd += m_segmentSize; |
332 m_cWndCnt = 0; | 337 m_cWndCnt = 0; |
333 NS_LOG_DEBUG("Increment cwnd to " << m_cWnd); | 338 NS_LOG_DEBUG ("Increment cwnd to " << m_cWnd); |
334 } | 339 } |
335 else | 340 else |
336 { | 341 { |
337 NS_LOG_DEBUG("Not enough segments have been ACKed to increment cwnd. U
ntil now " << m_cWndCnt); | 342 NS_LOG_DEBUG ("Not enough segments have been ACKed to increment cwnd.
Until now " << m_cWndCnt); |
338 } | 343 } |
339 } | 344 } |
340 } | 345 } |
341 | 346 |
342 void | 347 void |
343 TcpCubic::PktsAcked () | 348 TcpCubic::PktsAcked () |
344 { | 349 { |
345 NS_LOG_FUNCTION (this); | 350 NS_LOG_FUNCTION (this); |
346 | 351 |
347 /* Discard delay samples right after fast recovery */ | 352 /* Discard delay samples right after fast recovery */ |
(...skipping 11 matching lines...) Expand all Loading... |
359 delay = Time (MilliSeconds (10)); | 364 delay = Time (MilliSeconds (10)); |
360 } | 365 } |
361 | 366 |
362 /* first time call or link delay decreases */ | 367 /* first time call or link delay decreases */ |
363 if (m_delayMin == Time::Min () || m_delayMin > delay) | 368 if (m_delayMin == Time::Min () || m_delayMin > delay) |
364 { | 369 { |
365 m_delayMin = delay; | 370 m_delayMin = delay; |
366 } | 371 } |
367 | 372 |
368 /* hystart triggers when cwnd is larger than some threshold */ | 373 /* hystart triggers when cwnd is larger than some threshold */ |
369 if (m_hystart && | 374 if (m_hystart |
370 m_cWnd.Get () <= m_ssThresh && | 375 && m_cWnd.Get () <= m_ssThresh |
371 m_cWnd.Get () >= m_hystartLowWindow * m_segmentSize) | 376 && m_cWnd.Get () >= m_hystartLowWindow * m_segmentSize) |
372 { | 377 { |
373 HystartUpdate (delay); | 378 HystartUpdate (delay); |
374 } | 379 } |
375 } | 380 } |
376 | 381 |
377 void | 382 void |
378 TcpCubic::HystartUpdate (const Time& delay) | 383 TcpCubic::HystartUpdate (const Time& delay) |
379 { | 384 { |
380 NS_LOG_FUNCTION (this); | 385 NS_LOG_FUNCTION (this << delay); |
381 | 386 |
382 if (!(m_found & m_hystartDetect)) | 387 if (!(m_found & m_hystartDetect)) |
383 { | 388 { |
384 Time now = Simulator::Now (); | 389 Time now = Simulator::Now (); |
385 | 390 |
386 /* first detection parameter - ack-train detection */ | 391 /* first detection parameter - ack-train detection */ |
387 if ((now - m_lastAck) <= m_hystartAckDelta) | 392 if ((now - m_lastAck) <= m_hystartAckDelta) |
388 { | 393 { |
389 m_lastAck = now; | 394 m_lastAck = now; |
390 | 395 |
(...skipping 27 matching lines...) Expand all Loading... |
418 */ | 423 */ |
419 if (m_found & m_hystartDetect) | 424 if (m_found & m_hystartDetect) |
420 { | 425 { |
421 NS_LOG_DEBUG ("Exit from SS, immediately :-)"); | 426 NS_LOG_DEBUG ("Exit from SS, immediately :-)"); |
422 m_ssThresh = m_cWnd.Get (); | 427 m_ssThresh = m_cWnd.Get (); |
423 } | 428 } |
424 } | 429 } |
425 } | 430 } |
426 | 431 |
427 Time | 432 Time |
428 TcpCubic::HystartDelayThresh (Time t) const | 433 TcpCubic::HystartDelayThresh (const Time& t) const |
429 { | 434 { |
430 NS_LOG_FUNCTION (this); | 435 NS_LOG_FUNCTION (this << t); |
431 | 436 |
432 Time ret = t; | 437 Time ret = t; |
433 if (t > m_hystartDelayMax) | 438 if (t > m_hystartDelayMax) |
434 { | 439 { |
435 ret = m_hystartDelayMax; | 440 ret = m_hystartDelayMax; |
436 } | 441 } |
437 else if (t < m_hystartDelayMin) | 442 else if (t < m_hystartDelayMin) |
438 { | 443 { |
439 ret = m_hystartDelayMin; | 444 ret = m_hystartDelayMin; |
440 } | 445 } |
(...skipping 27 matching lines...) Expand all Loading... |
468 else | 473 else |
469 { | 474 { |
470 m_lastMaxCwnd = segCwnd; | 475 m_lastMaxCwnd = segCwnd; |
471 } | 476 } |
472 | 477 |
473 /* Formula taken from the Linux kernel */ | 478 /* Formula taken from the Linux kernel */ |
474 m_ssThresh = std::max (static_cast<uint32_t> (segCwnd * m_beta * m_segmentSize
), | 479 m_ssThresh = std::max (static_cast<uint32_t> (segCwnd * m_beta * m_segmentSize
), |
475 2U * m_segmentSize); | 480 2U * m_segmentSize); |
476 m_cWnd = m_ssThresh; | 481 m_cWnd = m_ssThresh; |
477 | 482 |
478 NS_LOG_DEBUG ("Imposing cwnd and ssth=" << m_cWnd/m_segmentSize); | 483 NS_LOG_DEBUG ("Imposing cwnd and ssth=" << m_cWnd / m_segmentSize); |
479 } | 484 } |
480 | 485 |
481 void | 486 void |
482 TcpCubic::DupAck (const TcpHeader& t, uint32_t count) | 487 TcpCubic::DupAck (const TcpHeader& t, uint32_t count) |
483 { | 488 { |
484 NS_LOG_FUNCTION (this); | 489 NS_LOG_FUNCTION (this << t << count); |
485 (void) t; | 490 (void) t; |
486 | 491 |
487 /* Keep the timing information */ | 492 /* Keep the timing information */ |
488 PktsAcked (); | 493 PktsAcked (); |
489 | 494 |
490 /* After 3 DUPAcks, there is a Loss. */ | 495 /* After 3 DUPAcks, there is a Loss. */ |
491 if (count == 3) | 496 if (count == 3) |
492 { | 497 { |
493 RecalcSsthresh (); | 498 RecalcSsthresh (); |
494 m_cubicState = LOSS; | 499 m_cubicState = LOSS; |
495 DoRetransmit (); | 500 DoRetransmit (); |
496 } | 501 } |
497 else if (count > 3) | 502 else if (count > 3) |
498 { | 503 { |
499 CongAvoid(SequenceNumber32 (0)); | 504 CongAvoid (SequenceNumber32 (0)); |
500 SendPendingData (m_connected); | 505 SendPendingData (m_connected); |
501 } | 506 } |
502 } | 507 } |
503 | 508 |
504 void | 509 void |
505 TcpCubic::Retransmit (void) | 510 TcpCubic::Retransmit (void) |
506 { | 511 { |
507 NS_LOG_FUNCTION (this); | 512 NS_LOG_FUNCTION (this); |
508 | 513 |
509 RecalcSsthresh (); | 514 RecalcSsthresh (); |
(...skipping 12 matching lines...) Expand all Loading... |
522 | 527 |
523 uint32_t | 528 uint32_t |
524 TcpCubic::Window (void) | 529 TcpCubic::Window (void) |
525 { | 530 { |
526 NS_LOG_FUNCTION (this); | 531 NS_LOG_FUNCTION (this); |
527 | 532 |
528 /* Limit the size of in-flight data by cwnd and receiver's rxwin */ | 533 /* Limit the size of in-flight data by cwnd and receiver's rxwin */ |
529 return std::min (m_rWnd.Get (), m_cWnd.Get ()); | 534 return std::min (m_rWnd.Get (), m_cWnd.Get ()); |
530 } | 535 } |
531 | 536 |
532 } | 537 void |
| 538 TcpCubic::ScaleSsThresh (uint8_t scaleFactor) |
| 539 { |
| 540 NS_LOG_FUNCTION (this << scaleFactor); |
| 541 |
| 542 m_ssThresh <<= scaleFactor; |
| 543 } |
| 544 |
| 545 } |
LEFT | RIGHT |