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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback), | 89 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback), |
90 MakeCallbackChecker ()) | 90 MakeCallbackChecker ()) |
91 .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.", |
92 CallbackValue (), | 92 CallbackValue (), |
93 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback6), | 93 MakeCallbackAccessor (&TcpSocketBase::m_icmpCallback6), |
94 MakeCallbackChecker ()) | 94 MakeCallbackChecker ()) |
95 .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option", | 95 .AddAttribute ("WindowScaling", "Enable or disable Window Scaling option", |
96 BooleanValue (true), | 96 BooleanValue (true), |
97 MakeBooleanAccessor (&TcpSocketBase::m_winScalingEnabled), | 97 MakeBooleanAccessor (&TcpSocketBase::m_winScalingEnabled), |
98 MakeBooleanChecker ()) | 98 MakeBooleanChecker ()) |
99 .AddAttribute ("SACK", "Enable or disable Window Scaling option", | 99 .AddAttribute ("Sack", "Enable or disable Sack option", |
100 BooleanValue (false), | 100 BooleanValue (false), |
101 MakeBooleanAccessor (&TcpSocketBase::m_sackEnabled), | 101 MakeBooleanAccessor (&TcpSocketBase::m_sackEnabled), |
102 MakeBooleanChecker ()) | 102 MakeBooleanChecker ()) |
103 .AddAttribute ("Timestamp", "Enable or disable Timestamp option", | 103 .AddAttribute ("Timestamp", "Enable or disable Timestamp option", |
104 BooleanValue (true), | 104 BooleanValue (true), |
105 MakeBooleanAccessor (&TcpSocketBase::m_timestampEnabled), | 105 MakeBooleanAccessor (&TcpSocketBase::m_timestampEnabled), |
106 MakeBooleanChecker ()) | 106 MakeBooleanChecker ()) |
107 .AddAttribute ("MinRto", | 107 .AddAttribute ("MinRto", |
108 "Minimum retransmit timeout value", | 108 "Minimum retransmit timeout value", |
109 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. |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 ok = m_tcb->TraceConnectWithoutContext ("CongState", | 439 ok = m_tcb->TraceConnectWithoutContext ("CongState", |
440 MakeCallback (&TcpSocketBase::UpdateCo
ngState, this)); | 440 MakeCallback (&TcpSocketBase::UpdateCo
ngState, this)); |
441 NS_ASSERT (ok == true); | 441 NS_ASSERT (ok == true); |
442 | 442 |
443 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence", | 443 ok = m_tcb->TraceConnectWithoutContext ("NextTxSequence", |
444 MakeCallback (&TcpSocketBase::UpdateNe
xtTxSequence, this)); | 444 MakeCallback (&TcpSocketBase::UpdateNe
xtTxSequence, this)); |
445 NS_ASSERT (ok == true); | 445 NS_ASSERT (ok == true); |
446 | 446 |
447 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence", | 447 ok = m_tcb->TraceConnectWithoutContext ("HighestSequence", |
448 MakeCallback (&TcpSocketBase::UpdateHi
ghTxMark, this)); | 448 MakeCallback (&TcpSocketBase::UpdateHi
ghTxMark, this)); |
| 449 NS_ASSERT (ok == true); |
449 } | 450 } |
450 | 451 |
451 TcpSocketBase::~TcpSocketBase (void) | 452 TcpSocketBase::~TcpSocketBase (void) |
452 { | 453 { |
453 NS_LOG_FUNCTION (this); | 454 NS_LOG_FUNCTION (this); |
454 m_node = 0; | 455 m_node = 0; |
455 if (m_endPoint != 0) | 456 if (m_endPoint != 0) |
456 { | 457 { |
457 NS_ASSERT (m_tcp != 0); | 458 NS_ASSERT (m_tcp != 0); |
458 /* | 459 /* |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 /* Inherit from Socket class: Bind socket (with specific address) to an end-poin
t in TcpL4Protocol */ | 557 /* Inherit from Socket class: Bind socket (with specific address) to an end-poin
t in TcpL4Protocol */ |
557 int | 558 int |
558 TcpSocketBase::Bind (const Address &address) | 559 TcpSocketBase::Bind (const Address &address) |
559 { | 560 { |
560 NS_LOG_FUNCTION (this << address); | 561 NS_LOG_FUNCTION (this << address); |
561 if (InetSocketAddress::IsMatchingType (address)) | 562 if (InetSocketAddress::IsMatchingType (address)) |
562 { | 563 { |
563 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); | 564 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); |
564 Ipv4Address ipv4 = transport.GetIpv4 (); | 565 Ipv4Address ipv4 = transport.GetIpv4 (); |
565 uint16_t port = transport.GetPort (); | 566 uint16_t port = transport.GetPort (); |
| 567 SetIpTos (transport.GetTos ()); |
566 if (ipv4 == Ipv4Address::GetAny () && port == 0) | 568 if (ipv4 == Ipv4Address::GetAny () && port == 0) |
567 { | 569 { |
568 m_endPoint = m_tcp->Allocate (); | 570 m_endPoint = m_tcp->Allocate (); |
569 } | 571 } |
570 else if (ipv4 == Ipv4Address::GetAny () && port != 0) | 572 else if (ipv4 == Ipv4Address::GetAny () && port != 0) |
571 { | 573 { |
572 m_endPoint = m_tcp->Allocate (port); | 574 m_endPoint = m_tcp->Allocate (port); |
573 } | 575 } |
574 else if (ipv4 != Ipv4Address::GetAny () && port == 0) | 576 else if (ipv4 != Ipv4Address::GetAny () && port == 0) |
575 { | 577 { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 return m_tcb->m_initialCWnd; | 657 return m_tcb->m_initialCWnd; |
656 } | 658 } |
657 | 659 |
658 /* Inherit from Socket class: Initiate connection to a remote address:port */ | 660 /* Inherit from Socket class: Initiate connection to a remote address:port */ |
659 int | 661 int |
660 TcpSocketBase::Connect (const Address & address) | 662 TcpSocketBase::Connect (const Address & address) |
661 { | 663 { |
662 NS_LOG_FUNCTION (this << address); | 664 NS_LOG_FUNCTION (this << address); |
663 | 665 |
664 // If haven't do so, Bind() this socket first | 666 // If haven't do so, Bind() this socket first |
665 if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0) | 667 if (InetSocketAddress::IsMatchingType (address)) |
666 { | 668 { |
667 if (m_endPoint == 0) | 669 if (m_endPoint == 0) |
668 { | 670 { |
669 if (Bind () == -1) | 671 if (Bind () == -1) |
670 { | 672 { |
671 NS_ASSERT (m_endPoint == 0); | 673 NS_ASSERT (m_endPoint == 0); |
672 return -1; // Bind() failed | 674 return -1; // Bind() failed |
673 } | 675 } |
674 NS_ASSERT (m_endPoint != 0); | 676 NS_ASSERT (m_endPoint != 0); |
675 } | 677 } |
676 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); | 678 InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); |
677 m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ()); | 679 m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ()); |
| 680 SetIpTos (transport.GetTos ()); |
678 m_endPoint6 = 0; | 681 m_endPoint6 = 0; |
679 | 682 |
680 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint | 683 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint |
681 if (SetupEndpoint () != 0) | 684 if (SetupEndpoint () != 0) |
682 { | 685 { |
683 NS_LOG_ERROR ("Route to destination does not exist ?!"); | 686 NS_LOG_ERROR ("Route to destination does not exist ?!"); |
684 return -1; | 687 return -1; |
685 } | 688 } |
686 } | 689 } |
687 else if (Inet6SocketAddress::IsMatchingType (address) && m_endPoint == 0) | 690 else if (Inet6SocketAddress::IsMatchingType (address)) |
688 { | 691 { |
689 // If we are operating on a v4-mapped address, translate the address to | 692 // If we are operating on a v4-mapped address, translate the address to |
690 // a v4 address and re-call this function | 693 // a v4 address and re-call this function |
691 Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address); | 694 Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address); |
692 Ipv6Address v6Addr = transport.GetIpv6 (); | 695 Ipv6Address v6Addr = transport.GetIpv6 (); |
693 if (v6Addr.IsIpv4MappedAddress () == true) | 696 if (v6Addr.IsIpv4MappedAddress () == true) |
694 { | 697 { |
695 Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress (); | 698 Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress (); |
696 return Connect (InetSocketAddress (v4Addr, transport.GetPort ())); | 699 return Connect (InetSocketAddress (v4Addr, transport.GetPort ())); |
697 } | 700 } |
698 | 701 |
699 if (m_endPoint6 == 0) | 702 if (m_endPoint6 == 0) |
700 { | 703 { |
701 if (Bind6 () == -1) | 704 if (Bind6 () == -1) |
702 { | 705 { |
703 NS_ASSERT (m_endPoint6 == 0); | 706 NS_ASSERT (m_endPoint6 == 0); |
704 return -1; // Bind() failed | 707 return -1; // Bind() failed |
705 } | 708 } |
706 NS_ASSERT (m_endPoint6 != 0); | 709 NS_ASSERT (m_endPoint6 != 0); |
707 } | 710 } |
708 m_endPoint6->SetPeer (v6Addr, transport.GetPort ()); | 711 m_endPoint6->SetPeer (v6Addr, transport.GetPort ()); |
709 m_endPoint = 0; | 712 m_endPoint = 0; |
710 | 713 |
711 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint | 714 // Get the appropriate local address and port number from the routing prot
ocol and set up endpoint |
712 if (SetupEndpoint6 () != 0) | 715 if (SetupEndpoint6 () != 0) |
713 { // Route to destination does not exist | 716 { |
| 717 NS_LOG_ERROR ("Route to destination does not exist ?!"); |
714 return -1; | 718 return -1; |
715 } | 719 } |
716 } | 720 } |
717 else | 721 else |
718 { | 722 { |
719 m_errno = ERROR_INVAL; | 723 m_errno = ERROR_INVAL; |
720 return -1; | 724 return -1; |
721 } | 725 } |
722 | 726 |
723 // Re-initialize parameters in case this socket is being reused after CLOSE | 727 // Re-initialize parameters in case this socket is being reused after CLOSE |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1192 if (!m_icmpCallback6.IsNull ()) | 1196 if (!m_icmpCallback6.IsNull ()) |
1193 { | 1197 { |
1194 m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo); | 1198 m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo); |
1195 } | 1199 } |
1196 } | 1200 } |
1197 | 1201 |
1198 void | 1202 void |
1199 TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress, | 1203 TcpSocketBase::DoForwardUp (Ptr<Packet> packet, const Address &fromAddress, |
1200 const Address &toAddress) | 1204 const Address &toAddress) |
1201 { | 1205 { |
| 1206 // in case the packet still has a priority tag attached, remove it |
| 1207 SocketPriorityTag priorityTag; |
| 1208 packet->RemovePacketTag (priorityTag); |
| 1209 |
1202 // Peel off TCP header and do validity checking | 1210 // Peel off TCP header and do validity checking |
1203 TcpHeader tcpHeader; | 1211 TcpHeader tcpHeader; |
1204 uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader); | 1212 uint32_t bytesRemoved = packet->RemoveHeader (tcpHeader); |
1205 SequenceNumber32 seq = tcpHeader.GetSequenceNumber (); | 1213 SequenceNumber32 seq = tcpHeader.GetSequenceNumber (); |
1206 if (bytesRemoved == 0 || bytesRemoved > 60) | 1214 if (bytesRemoved == 0 || bytesRemoved > 60) |
1207 { | 1215 { |
1208 NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid"); | 1216 NS_LOG_ERROR ("Bytes removed: " << bytesRemoved << " invalid"); |
1209 return; // Discard invalid packet | 1217 return; // Discard invalid packet |
1210 } | 1218 } |
1211 else if (packet->GetSize () > 0 && OutOfRange (seq, seq + packet->GetSize ())) | 1219 else if (packet->GetSize () > 0 && OutOfRange (seq, seq + packet->GetSize ())) |
(...skipping 26 matching lines...) Expand all Loading... |
1238 { | 1246 { |
1239 ProcessOptionWScale (tcpHeader.GetOption (TcpOption::WINSCALE)); | 1247 ProcessOptionWScale (tcpHeader.GetOption (TcpOption::WINSCALE)); |
1240 } | 1248 } |
1241 else | 1249 else |
1242 { | 1250 { |
1243 m_winScalingEnabled = false; | 1251 m_winScalingEnabled = false; |
1244 } | 1252 } |
1245 | 1253 |
1246 if (tcpHeader.HasOption (TcpOption::SACKPERMITTED) && m_sackEnabled) | 1254 if (tcpHeader.HasOption (TcpOption::SACKPERMITTED) && m_sackEnabled) |
1247 { | 1255 { |
1248 ProcessOptionSACKPermitted (tcpHeader.GetOption (TcpOption::SACKPERMIT
TED)); | 1256 ProcessOptionSackPermitted (tcpHeader.GetOption (TcpOption::SACKPERMIT
TED)); |
1249 } | 1257 } |
1250 else | 1258 else |
1251 { | 1259 { |
1252 m_sackEnabled = false; | 1260 m_sackEnabled = false; |
1253 } | 1261 } |
1254 | 1262 |
1255 // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end | 1263 // When receiving a <SYN> or <SYN-ACK> we should adapt TS to the other end |
1256 if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled) | 1264 if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled) |
1257 { | 1265 { |
1258 ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), | 1266 ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 } | 1302 } |
1295 } | 1303 } |
1296 | 1304 |
1297 EstimateRtt (tcpHeader); | 1305 EstimateRtt (tcpHeader); |
1298 UpdateWindowSize (tcpHeader); | 1306 UpdateWindowSize (tcpHeader); |
1299 | 1307 |
1300 if (!m_sackEnabled | 1308 if (!m_sackEnabled |
1301 && m_tcb->m_congState != TcpSocketState::CA_LOSS | 1309 && m_tcb->m_congState != TcpSocketState::CA_LOSS |
1302 && !m_persistEvent.IsRunning ()) | 1310 && !m_persistEvent.IsRunning ()) |
1303 { | 1311 { |
1304 // Emulate SACK for (old) dupack definition. | 1312 // Emulate sack for (old) dupack definition. |
1305 // Don't generate block for the persistent window probe | 1313 // Don't generate block for the persistent window probe |
1306 // Don't include the ACK number in any SACK block | 1314 // Don't include the ACK number in any sack block |
1307 if (tcpHeader.GetAckNumber () == m_txBuffer->HeadSequence () | 1315 if (tcpHeader.GetAckNumber () == m_txBuffer->HeadSequence () |
1308 && tcpHeader.GetAckNumber () < m_tcb->m_nextTxSequence) | 1316 && tcpHeader.GetAckNumber () < m_tcb->m_nextTxSequence) |
1309 { | 1317 { |
1310 // Dupack following old ns-3 behavior. Craft a special SACK option
. | 1318 // Dupack following old ns-3 behavior. Craft a special sack option
. |
1311 uint8_t available = tcpHeader.GetMaxOptionLength () - tcpHeader.Ge
tOptionLength (); | 1319 uint8_t available = tcpHeader.GetMaxOptionLength () - tcpHeader.Ge
tOptionLength (); |
1312 Ptr<const TcpOptionSack> sackBlock = m_txBuffer->CraftSackOption (
tcpHeader.GetAckNumber (), available); | 1320 Ptr<const TcpOptionSack> sackBlock = m_txBuffer->CraftSackOption (
tcpHeader.GetAckNumber (), available); |
1313 if (sackBlock != 0) | 1321 if (sackBlock != 0) |
1314 { | 1322 { |
1315 tcpHeader.AppendOption (sackBlock); | 1323 tcpHeader.AppendOption (sackBlock); |
1316 } | 1324 } |
1317 } | 1325 } |
1318 } | 1326 } |
1319 } | 1327 } |
1320 | 1328 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1491 const TcpHeader::TcpOptionList options = tcpHeader.GetOptionList (); | 1499 const TcpHeader::TcpOptionList options = tcpHeader.GetOptionList (); |
1492 | 1500 |
1493 for (it = options.begin (); it != options.end (); ++it) | 1501 for (it = options.begin (); it != options.end (); ++it) |
1494 { | 1502 { |
1495 const Ptr<const TcpOption> option = (*it); | 1503 const Ptr<const TcpOption> option = (*it); |
1496 | 1504 |
1497 // Check only for ACK options here | 1505 // Check only for ACK options here |
1498 switch (option->GetKind ()) | 1506 switch (option->GetKind ()) |
1499 { | 1507 { |
1500 case TcpOption::SACK: | 1508 case TcpOption::SACK: |
1501 scoreboardUpdated = ProcessOptionSACK (option); | 1509 scoreboardUpdated = ProcessOptionSack (option); |
1502 break; | 1510 break; |
1503 default: | 1511 default: |
1504 continue; | 1512 continue; |
1505 } | 1513 } |
1506 } | 1514 } |
1507 } | 1515 } |
1508 | 1516 |
1509 void | 1517 void |
1510 TcpSocketBase::LimitedTransmit () | 1518 TcpSocketBase::LimitedTransmit () |
1511 { | 1519 { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1621 /* Process the newly received ACK */ | 1629 /* Process the newly received ACK */ |
1622 void | 1630 void |
1623 TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader) | 1631 TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader) |
1624 { | 1632 { |
1625 NS_LOG_FUNCTION (this << tcpHeader); | 1633 NS_LOG_FUNCTION (this << tcpHeader); |
1626 | 1634 |
1627 NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK)); | 1635 NS_ASSERT (0 != (tcpHeader.GetFlags () & TcpHeader::ACK)); |
1628 NS_ASSERT (m_tcb->m_segmentSize > 0); | 1636 NS_ASSERT (m_tcb->m_segmentSize > 0); |
1629 | 1637 |
1630 // RFC 6675, Section 5, 1st paragraph: | 1638 // RFC 6675, Section 5, 1st paragraph: |
1631 // Upon the receipt of any ACK containing SACK information, the | 1639 // Upon the receipt of any ACK containing sack information, the |
1632 // scoreboard MUST be updated via the Update () routine (done in ReadOptions) | 1640 // scoreboard MUST be updated via the Update () routine (done in ReadOptions) |
1633 bool scoreboardUpdated = false; | 1641 bool scoreboardUpdated = false; |
1634 ReadOptions (tcpHeader, scoreboardUpdated); | 1642 ReadOptions (tcpHeader, scoreboardUpdated); |
1635 | 1643 |
1636 SequenceNumber32 ackNumber = tcpHeader.GetAckNumber (); | 1644 SequenceNumber32 ackNumber = tcpHeader.GetAckNumber (); |
1637 | 1645 |
1638 // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation | 1646 // RFC 6675 Section 5: 2nd, 3rd paragraph and point (A), (B) implementation |
1639 // are inside the function ProcessAck | 1647 // are inside the function ProcessAck |
1640 ProcessAck (ackNumber, scoreboardUpdated); | 1648 ProcessAck (ackNumber, scoreboardUpdated); |
1641 | 1649 |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2297 Ptr<Packet> p = Create<Packet> (); | 2305 Ptr<Packet> p = Create<Packet> (); |
2298 TcpHeader header; | 2306 TcpHeader header; |
2299 SequenceNumber32 s = m_tcb->m_nextTxSequence; | 2307 SequenceNumber32 s = m_tcb->m_nextTxSequence; |
2300 | 2308 |
2301 /* | 2309 /* |
2302 * Add tags for each socket option. | 2310 * Add tags for each socket option. |
2303 * Note that currently the socket adds both IPv4 tag and IPv6 tag | 2311 * Note that currently the socket adds both IPv4 tag and IPv6 tag |
2304 * if both options are set. Once the packet got to layer three, only | 2312 * if both options are set. Once the packet got to layer three, only |
2305 * the corresponding tags will be read. | 2313 * the corresponding tags will be read. |
2306 */ | 2314 */ |
2307 if (IsManualIpTos ()) | 2315 if (GetIpTos ()) |
2308 { | 2316 { |
2309 SocketIpTosTag ipTosTag; | 2317 SocketIpTosTag ipTosTag; |
2310 ipTosTag.SetTos (GetIpTos ()); | 2318 ipTosTag.SetTos (GetIpTos ()); |
2311 p->AddPacketTag (ipTosTag); | 2319 p->AddPacketTag (ipTosTag); |
2312 } | 2320 } |
2313 | 2321 |
2314 if (IsManualIpv6Tclass ()) | 2322 if (IsManualIpv6Tclass ()) |
2315 { | 2323 { |
2316 SocketIpv6TclassTag ipTclassTag; | 2324 SocketIpv6TclassTag ipTclassTag; |
2317 ipTclassTag.SetTclass (GetIpv6Tclass ()); | 2325 ipTclassTag.SetTclass (GetIpv6Tclass ()); |
2318 p->AddPacketTag (ipTclassTag); | 2326 p->AddPacketTag (ipTclassTag); |
2319 } | 2327 } |
2320 | 2328 |
2321 if (IsManualIpTtl ()) | 2329 if (IsManualIpTtl ()) |
2322 { | 2330 { |
2323 SocketIpTtlTag ipTtlTag; | 2331 SocketIpTtlTag ipTtlTag; |
2324 ipTtlTag.SetTtl (GetIpTtl ()); | 2332 ipTtlTag.SetTtl (GetIpTtl ()); |
2325 p->AddPacketTag (ipTtlTag); | 2333 p->AddPacketTag (ipTtlTag); |
2326 } | 2334 } |
2327 | 2335 |
2328 if (IsManualIpv6HopLimit ()) | 2336 if (IsManualIpv6HopLimit ()) |
2329 { | 2337 { |
2330 SocketIpv6HopLimitTag ipHopLimitTag; | 2338 SocketIpv6HopLimitTag ipHopLimitTag; |
2331 ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ()); | 2339 ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ()); |
2332 p->AddPacketTag (ipHopLimitTag); | 2340 p->AddPacketTag (ipHopLimitTag); |
| 2341 } |
| 2342 |
| 2343 uint8_t priority = GetPriority (); |
| 2344 if (priority) |
| 2345 { |
| 2346 SocketPriorityTag priorityTag; |
| 2347 priorityTag.SetPriority (priority); |
| 2348 p->ReplacePacketTag (priorityTag); |
2333 } | 2349 } |
2334 | 2350 |
2335 if (m_endPoint == 0 && m_endPoint6 == 0) | 2351 if (m_endPoint == 0 && m_endPoint6 == 0) |
2336 { | 2352 { |
2337 NS_LOG_WARN ("Failed to send empty packet due to null endpoint"); | 2353 NS_LOG_WARN ("Failed to send empty packet due to null endpoint"); |
2338 return; | 2354 return; |
2339 } | 2355 } |
2340 if (flags & TcpHeader::FIN) | 2356 if (flags & TcpHeader::FIN) |
2341 { | 2357 { |
2342 flags |= TcpHeader::ACK; | 2358 flags |= TcpHeader::ACK; |
(...skipping 27 matching lines...) Expand all Loading... |
2370 bool isAck = flags == TcpHeader::ACK; | 2386 bool isAck = flags == TcpHeader::ACK; |
2371 if (hasSyn) | 2387 if (hasSyn) |
2372 { | 2388 { |
2373 if (m_winScalingEnabled) | 2389 if (m_winScalingEnabled) |
2374 { // The window scaling option is set only on SYN packets | 2390 { // The window scaling option is set only on SYN packets |
2375 AddOptionWScale (header); | 2391 AddOptionWScale (header); |
2376 } | 2392 } |
2377 | 2393 |
2378 if (m_sackEnabled) | 2394 if (m_sackEnabled) |
2379 { | 2395 { |
2380 AddOptionSACKPermitted (header); | 2396 AddOptionSackPermitted (header); |
2381 } | 2397 } |
2382 | 2398 |
2383 if (m_synCount == 0) | 2399 if (m_synCount == 0) |
2384 { // No more connection retries, give up | 2400 { // No more connection retries, give up |
2385 NS_LOG_LOGIC ("Connection failed."); | 2401 NS_LOG_LOGIC ("Connection failed."); |
2386 m_rtt->Reset (); //According to recommendation -> RFC 6298 | 2402 m_rtt->Reset (); //According to recommendation -> RFC 6298 |
2387 CloseAndNotify (); | 2403 CloseAndNotify (); |
2388 return; | 2404 return; |
2389 } | 2405 } |
2390 else | 2406 else |
(...skipping 21 matching lines...) Expand all Loading... |
2412 m_delAckEvent.Cancel (); | 2428 m_delAckEvent.Cancel (); |
2413 m_delAckCount = 0; | 2429 m_delAckCount = 0; |
2414 if (m_highTxAck < header.GetAckNumber ()) | 2430 if (m_highTxAck < header.GetAckNumber ()) |
2415 { | 2431 { |
2416 m_highTxAck = header.GetAckNumber (); | 2432 m_highTxAck = header.GetAckNumber (); |
2417 } | 2433 } |
2418 else | 2434 else |
2419 { | 2435 { |
2420 if (m_sackEnabled) | 2436 if (m_sackEnabled) |
2421 { | 2437 { |
2422 AddOptionSACK (header); | 2438 AddOptionSack (header); |
2423 } | 2439 } |
2424 } | 2440 } |
2425 } | 2441 } |
2426 | 2442 |
2427 m_txTrace (p, header, this); | 2443 m_txTrace (p, header, this); |
2428 | 2444 |
2429 if (m_endPoint != 0) | 2445 if (m_endPoint != 0) |
2430 { | 2446 { |
2431 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), | 2447 m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), |
2432 m_endPoint->GetPeerAddress (), m_boundnetdevice); | 2448 m_endPoint->GetPeerAddress (), m_boundnetdevice); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2615 m_delAckEvent.Cancel (); | 2631 m_delAckEvent.Cancel (); |
2616 m_delAckCount = 0; | 2632 m_delAckCount = 0; |
2617 } | 2633 } |
2618 | 2634 |
2619 /* | 2635 /* |
2620 * Add tags for each socket option. | 2636 * Add tags for each socket option. |
2621 * Note that currently the socket adds both IPv4 tag and IPv6 tag | 2637 * Note that currently the socket adds both IPv4 tag and IPv6 tag |
2622 * if both options are set. Once the packet got to layer three, only | 2638 * if both options are set. Once the packet got to layer three, only |
2623 * the corresponding tags will be read. | 2639 * the corresponding tags will be read. |
2624 */ | 2640 */ |
2625 if (IsManualIpTos ()) | 2641 if (GetIpTos ()) |
2626 { | 2642 { |
2627 SocketIpTosTag ipTosTag; | 2643 SocketIpTosTag ipTosTag; |
2628 ipTosTag.SetTos (GetIpTos ()); | 2644 ipTosTag.SetTos (GetIpTos ()); |
2629 p->AddPacketTag (ipTosTag); | 2645 p->AddPacketTag (ipTosTag); |
2630 } | 2646 } |
2631 | 2647 |
2632 if (IsManualIpv6Tclass ()) | 2648 if (IsManualIpv6Tclass ()) |
2633 { | 2649 { |
2634 SocketIpv6TclassTag ipTclassTag; | 2650 SocketIpv6TclassTag ipTclassTag; |
2635 ipTclassTag.SetTclass (GetIpv6Tclass ()); | 2651 ipTclassTag.SetTclass (GetIpv6Tclass ()); |
2636 p->AddPacketTag (ipTclassTag); | 2652 p->AddPacketTag (ipTclassTag); |
2637 } | 2653 } |
2638 | 2654 |
2639 if (IsManualIpTtl ()) | 2655 if (IsManualIpTtl ()) |
2640 { | 2656 { |
2641 SocketIpTtlTag ipTtlTag; | 2657 SocketIpTtlTag ipTtlTag; |
2642 ipTtlTag.SetTtl (GetIpTtl ()); | 2658 ipTtlTag.SetTtl (GetIpTtl ()); |
2643 p->AddPacketTag (ipTtlTag); | 2659 p->AddPacketTag (ipTtlTag); |
2644 } | 2660 } |
2645 | 2661 |
2646 if (IsManualIpv6HopLimit ()) | 2662 if (IsManualIpv6HopLimit ()) |
2647 { | 2663 { |
2648 SocketIpv6HopLimitTag ipHopLimitTag; | 2664 SocketIpv6HopLimitTag ipHopLimitTag; |
2649 ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ()); | 2665 ipHopLimitTag.SetHopLimit (GetIpv6HopLimit ()); |
2650 p->AddPacketTag (ipHopLimitTag); | 2666 p->AddPacketTag (ipHopLimitTag); |
| 2667 } |
| 2668 |
| 2669 uint8_t priority = GetPriority (); |
| 2670 if (priority) |
| 2671 { |
| 2672 SocketPriorityTag priorityTag; |
| 2673 priorityTag.SetPriority (priority); |
| 2674 p->ReplacePacketTag (priorityTag); |
2651 } | 2675 } |
2652 | 2676 |
2653 if (m_closeOnEmpty && (remainingData == 0)) | 2677 if (m_closeOnEmpty && (remainingData == 0)) |
2654 { | 2678 { |
2655 flags |= TcpHeader::FIN; | 2679 flags |= TcpHeader::FIN; |
2656 if (m_state == ESTABLISHED) | 2680 if (m_state == ESTABLISHED) |
2657 { // On active close: I am the first one to send FIN | 2681 { // On active close: I am the first one to send FIN |
2658 NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1"); | 2682 NS_LOG_DEBUG ("ESTABLISHED -> FIN_WAIT_1"); |
2659 m_state = FIN_WAIT_1; | 2683 m_state = FIN_WAIT_1; |
2660 } | 2684 } |
(...skipping 15 matching lines...) Expand all Loading... |
2676 else | 2700 else |
2677 { | 2701 { |
2678 header.SetSourcePort (m_endPoint6->GetLocalPort ()); | 2702 header.SetSourcePort (m_endPoint6->GetLocalPort ()); |
2679 header.SetDestinationPort (m_endPoint6->GetPeerPort ()); | 2703 header.SetDestinationPort (m_endPoint6->GetPeerPort ()); |
2680 } | 2704 } |
2681 header.SetWindowSize (AdvertisedWindowSize ()); | 2705 header.SetWindowSize (AdvertisedWindowSize ()); |
2682 AddOptions (header); | 2706 AddOptions (header); |
2683 | 2707 |
2684 if (m_retxEvent.IsExpired ()) | 2708 if (m_retxEvent.IsExpired ()) |
2685 { | 2709 { |
2686 // Schedules retransmit timeout. | 2710 // Schedules retransmit timeout. m_rto should be already doubled. |
2687 | 2711 |
2688 NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " << | 2712 NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " << |
2689 Simulator::Now ().GetSeconds () << " to expire at time " << | 2713 Simulator::Now ().GetSeconds () << " to expire at time " << |
2690 (Simulator::Now () + m_rto.Get ()).GetSeconds () ); | 2714 (Simulator::Now () + m_rto.Get ()).GetSeconds () ); |
2691 m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::ReTxTimeout, thi
s); | 2715 m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::ReTxTimeout, thi
s); |
2692 } | 2716 } |
2693 | 2717 |
2694 m_txTrace (p, header, this); | 2718 m_txTrace (p, header, this); |
2695 | 2719 |
2696 if (m_endPoint) | 2720 if (m_endPoint) |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2778 { | 2802 { |
2779 NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit"); | 2803 NS_LOG_INFO ("FIN_WAIT and OPEN state; no data to transmit"); |
2780 break; | 2804 break; |
2781 } | 2805 } |
2782 // (C.1) The scoreboard MUST be queried via NextSeg () for the | 2806 // (C.1) The scoreboard MUST be queried via NextSeg () for the |
2783 // sequence number range of the next segment to transmit (if | 2807 // sequence number range of the next segment to transmit (if |
2784 // any), and the given segment sent. If NextSeg () returns | 2808 // any), and the given segment sent. If NextSeg () returns |
2785 // failure (no data to send), return without sending anything | 2809 // failure (no data to send), return without sending anything |
2786 // (i.e., terminate steps C.1 -- C.5). | 2810 // (i.e., terminate steps C.1 -- C.5). |
2787 SequenceNumber32 next; | 2811 SequenceNumber32 next; |
2788 if (!m_txBuffer->NextSeg (&next, m_retxThresh, m_tcb->m_segmentSize)) | 2812 if (!m_txBuffer->NextSeg (&next, m_retxThresh, m_tcb->m_segmentSize, |
2789 { | 2813 m_tcb->m_congState == TcpSocketState::CA_RECOVER
Y)) |
2790 return nPacketsSent; | 2814 { |
| 2815 NS_LOG_INFO ("no valid seq to transmit, or no data available"); |
| 2816 break; |
2791 } | 2817 } |
2792 else | 2818 else |
2793 { | 2819 { |
2794 // It's time to transmit, but before do silly window and Nagle's check | 2820 // It's time to transmit, but before do silly window and Nagle's check |
2795 uint32_t availableData = m_txBuffer->SizeFromSequence (next); | 2821 uint32_t availableData = m_txBuffer->SizeFromSequence (next); |
2796 | 2822 |
2797 // Stop sending if we need to wait for a larger Tx window (prevent sil
ly window syndrome) | 2823 // Stop sending if we need to wait for a larger Tx window (prevent sil
ly window syndrome) |
2798 if (availableWindow < m_tcb->m_segmentSize && availableData > availab
leWindow) | 2824 if (availableWindow < m_tcb->m_segmentSize && availableData > availab
leWindow) |
2799 { | 2825 { |
2800 NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send."); | 2826 NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send."); |
2801 break; // No more | 2827 break; // No more |
2802 } | 2828 } |
2803 // Nagle's algorithm (RFC896): Hold off sending if there is unacked da
ta | 2829 // Nagle's algorithm (RFC896): Hold off sending if there is unacked da
ta |
2804 // in the buffer and the amount of data to send is less than one segme
nt | 2830 // in the buffer and the amount of data to send is less than one segme
nt |
2805 if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_se
gmentSize) | 2831 if (!m_noDelay && UnAckDataCount () > 0 && availableData < m_tcb->m_se
gmentSize) |
2806 { | 2832 { |
2807 NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next << | 2833 NS_LOG_DEBUG ("Invoking Nagle's algorithm for seq " << next << |
2808 ", SFS: " << m_txBuffer->SizeFromSequence (next) << | 2834 ", SFS: " << m_txBuffer->SizeFromSequence (next) << |
2809 ". Wait to send."); | 2835 ". Wait to send."); |
2810 break; | 2836 break; |
2811 } | 2837 } |
2812 | 2838 |
2813 m_tcb->m_nextTxSequence = next; | |
2814 uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize); | 2839 uint32_t s = std::min (availableWindow, m_tcb->m_segmentSize); |
2815 | 2840 |
2816 // (C.2) If any of the data octets sent in (C.1) are below HighData, | 2841 // (C.2) If any of the data octets sent in (C.1) are below HighData, |
2817 // HighRxt MUST be set to the highest sequence number of the | 2842 // HighRxt MUST be set to the highest sequence number of the |
2818 // retransmitted segment unless NextSeg () rule (4) was | 2843 // retransmitted segment unless NextSeg () rule (4) was |
2819 // invoked for this retransmission. | 2844 // invoked for this retransmission. |
2820 // (C.3) If any of the data octets sent in (C.1) are above HighData, | 2845 // (C.3) If any of the data octets sent in (C.1) are above HighData, |
2821 // HighData must be updated to reflect the transmission of | 2846 // HighData must be updated to reflect the transmission of |
2822 // previously unsent data. | 2847 // previously unsent data. |
2823 // | 2848 // |
2824 // These steps are done in m_txBuffer with the tags. | 2849 // These steps are done in m_txBuffer with the tags. |
| 2850 if (m_tcb->m_nextTxSequence != next) |
| 2851 { |
| 2852 m_tcb->m_nextTxSequence = next; |
| 2853 } |
| 2854 |
2825 uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck); | 2855 uint32_t sz = SendDataPacket (m_tcb->m_nextTxSequence, s, withAck); |
| 2856 m_tcb->m_nextTxSequence += sz; |
2826 | 2857 |
2827 NS_LOG_LOGIC (" rxwin " << m_rWnd << | 2858 NS_LOG_LOGIC (" rxwin " << m_rWnd << |
2828 " segsize " << m_tcb->m_segmentSize << | 2859 " segsize " << m_tcb->m_segmentSize << |
2829 " highestRxAck " << m_txBuffer->HeadSequence () << | 2860 " highestRxAck " << m_txBuffer->HeadSequence () << |
2830 " pd->Size " << m_txBuffer->Size () << | 2861 " pd->Size " << m_txBuffer->Size () << |
2831 " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_ne
xtTxSequence)); | 2862 " pd->SFS " << m_txBuffer->SizeFromSequence (m_tcb->m_ne
xtTxSequence)); |
2832 | 2863 |
2833 NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd << | 2864 NS_LOG_DEBUG ("cWnd: " << m_tcb->m_cWnd << |
2834 " total unAck: " << UnAckDataCount () << | 2865 " total unAck: " << UnAckDataCount () << |
2835 " sent seq " << m_tcb->m_nextTxSequence << | 2866 " sent seq " << m_tcb->m_nextTxSequence << |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2900 NS_LOG_FUNCTION_NOARGS (); | 2931 NS_LOG_FUNCTION_NOARGS (); |
2901 uint32_t inflight = BytesInFlight (); // Number of outstanding bytes | 2932 uint32_t inflight = BytesInFlight (); // Number of outstanding bytes |
2902 uint32_t win = Window (); // Number of bytes allowed to be outstan
ding | 2933 uint32_t win = Window (); // Number of bytes allowed to be outstan
ding |
2903 | 2934 |
2904 if (inflight > win) | 2935 if (inflight > win) |
2905 { | 2936 { |
2906 NS_LOG_DEBUG ("InFlight=" << inflight << ", Win=" << win << " availWin=0")
; | 2937 NS_LOG_DEBUG ("InFlight=" << inflight << ", Win=" << win << " availWin=0")
; |
2907 return 0; | 2938 return 0; |
2908 } | 2939 } |
2909 | 2940 |
2910 NS_LOG_DEBUG ("InFlight=" << inflight << ", Win=" << win << " availWin=" << wi
n-inflight); | 2941 NS_LOG_DEBUG ("InFlight=" << inflight << ", Win=" << win << " availWin=" << wi
n - inflight); |
2911 return win - inflight; | 2942 return win - inflight; |
2912 } | 2943 } |
2913 | 2944 |
2914 uint16_t | 2945 uint16_t |
2915 TcpSocketBase::AdvertisedWindowSize (bool scale) const | 2946 TcpSocketBase::AdvertisedWindowSize (bool scale) const |
2916 { | 2947 { |
2917 NS_LOG_FUNCTION (this << scale); | 2948 NS_LOG_FUNCTION (this << scale); |
2918 uint32_t w = m_rxBuffer->MaxBufferSize (); | 2949 uint32_t w = m_rxBuffer->MaxBufferSize (); |
2919 | 2950 |
2920 if (scale) | 2951 if (scale) |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3069 } | 3100 } |
3070 | 3101 |
3071 // Note the highest ACK and tell app to send more | 3102 // Note the highest ACK and tell app to send more |
3072 NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack << | 3103 NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack << |
3073 " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number
bytes ack'ed | 3104 " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number
bytes ack'ed |
3074 m_txBuffer->DiscardUpTo (ack); | 3105 m_txBuffer->DiscardUpTo (ack); |
3075 if (GetTxAvailable () > 0) | 3106 if (GetTxAvailable () > 0) |
3076 { | 3107 { |
3077 NotifySend (GetTxAvailable ()); | 3108 NotifySend (GetTxAvailable ()); |
3078 } | 3109 } |
| 3110 if (ack > m_tcb->m_nextTxSequence) |
| 3111 { |
| 3112 m_tcb->m_nextTxSequence = ack; // If advanced |
| 3113 } |
3079 if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING) | 3114 if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING) |
3080 { // No retransmit timer if no data to retransmit | 3115 { // No retransmit timer if no data to retransmit |
3081 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir
e at " << | 3116 NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expir
e at " << |
3082 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).
GetSeconds ()); | 3117 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).
GetSeconds ()); |
3083 m_retxEvent.Cancel (); | 3118 m_retxEvent.Cancel (); |
3084 } | 3119 } |
3085 } | 3120 } |
3086 | 3121 |
3087 // Retransmit timeout | 3122 // Retransmit timeout |
3088 void | 3123 void |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3546 m_rcvWindShift = CalculateWScale (); | 3581 m_rcvWindShift = CalculateWScale (); |
3547 option->SetScale (m_rcvWindShift); | 3582 option->SetScale (m_rcvWindShift); |
3548 | 3583 |
3549 header.AppendOption (option); | 3584 header.AppendOption (option); |
3550 | 3585 |
3551 NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " << | 3586 NS_LOG_INFO (m_node->GetId () << " Send a scaling factor of " << |
3552 static_cast<int> (m_rcvWindShift)); | 3587 static_cast<int> (m_rcvWindShift)); |
3553 } | 3588 } |
3554 | 3589 |
3555 bool | 3590 bool |
3556 TcpSocketBase::ProcessOptionSACK (const Ptr<const TcpOption> option) | 3591 TcpSocketBase::ProcessOptionSack (const Ptr<const TcpOption> option) |
3557 { | 3592 { |
3558 NS_LOG_FUNCTION (this << option); | 3593 NS_LOG_FUNCTION (this << option); |
3559 | 3594 |
3560 Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option); | 3595 Ptr<const TcpOptionSack> s = DynamicCast<const TcpOptionSack> (option); |
3561 TcpOptionSack::SackList list = s->GetSackList (); | 3596 TcpOptionSack::SackList list = s->GetSackList (); |
3562 return m_txBuffer->Update (list); | 3597 return m_txBuffer->Update (list); |
3563 } | 3598 } |
3564 | 3599 |
3565 void | 3600 void |
3566 TcpSocketBase::ProcessOptionSACKPermitted (const Ptr<const TcpOption> option) | 3601 TcpSocketBase::ProcessOptionSackPermitted (const Ptr<const TcpOption> option) |
3567 { | 3602 { |
3568 NS_LOG_FUNCTION (this << option); | 3603 NS_LOG_FUNCTION (this << option); |
3569 | 3604 |
3570 Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted
> (option); | 3605 Ptr<const TcpOptionSackPermitted> s = DynamicCast<const TcpOptionSackPermitted
> (option); |
3571 | 3606 |
3572 NS_ASSERT (m_sackEnabled == true); | 3607 NS_ASSERT (m_sackEnabled == true); |
3573 NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s); | 3608 NS_LOG_INFO (m_node->GetId () << " Received a SACK_PERMITTED option " << s); |
3574 } | 3609 } |
3575 | 3610 |
3576 void | 3611 void |
3577 TcpSocketBase::AddOptionSACKPermitted (TcpHeader &header) | 3612 TcpSocketBase::AddOptionSackPermitted (TcpHeader &header) |
3578 { | 3613 { |
3579 NS_LOG_FUNCTION (this << header); | 3614 NS_LOG_FUNCTION (this << header); |
3580 NS_ASSERT (header.GetFlags () & TcpHeader::SYN); | 3615 NS_ASSERT (header.GetFlags () & TcpHeader::SYN); |
3581 | 3616 |
3582 Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> (); | 3617 Ptr<TcpOptionSackPermitted> option = CreateObject<TcpOptionSackPermitted> (); |
3583 header.AppendOption (option); | 3618 header.AppendOption (option); |
3584 NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED"); | 3619 NS_LOG_INFO (m_node->GetId () << " Add option SACK-PERMITTED"); |
3585 } | 3620 } |
3586 | 3621 |
3587 void | 3622 void |
3588 TcpSocketBase::AddOptionSACK (TcpHeader& header) | 3623 TcpSocketBase::AddOptionSack (TcpHeader& header) |
3589 { | 3624 { |
3590 NS_LOG_FUNCTION (this << header); | 3625 NS_LOG_FUNCTION (this << header); |
3591 | 3626 |
3592 // Calculate the number of SACK blocks allowed in this packet | 3627 // Calculate the number of sack blocks allowed in this packet |
3593 uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength
(); | 3628 uint8_t optionLenAvail = header.GetMaxOptionLength () - header.GetOptionLength
(); |
3594 uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8; | 3629 uint8_t allowedSackBlocks = (optionLenAvail - 2) / 8; |
3595 | 3630 |
3596 TcpOptionSack::SackList sackList = m_rxBuffer->GetSackList (); | 3631 TcpOptionSack::SackList sackList = m_rxBuffer->GetSackList (); |
3597 if (allowedSackBlocks == 0 || sackList.empty ()) | 3632 if (allowedSackBlocks == 0 || sackList.empty ()) |
3598 { | 3633 { |
3599 NS_LOG_LOGIC ("No space available or sack list empty, not adding sack bloc
ks"); | 3634 NS_LOG_LOGIC ("No space available or sack list empty, not adding sack bloc
ks"); |
3600 return; | 3635 return; |
3601 } | 3636 } |
3602 | 3637 |
3603 // Append the allowed number of SACK blocks | 3638 // Append the allowed number of sack blocks |
3604 Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> (); | 3639 Ptr<TcpOptionSack> option = CreateObject<TcpOptionSack> (); |
3605 TcpOptionSack::SackList::iterator i; | 3640 TcpOptionSack::SackList::iterator i; |
3606 for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i
) | 3641 for (i = sackList.begin (); allowedSackBlocks > 0 && i != sackList.end (); ++i
) |
3607 { | 3642 { |
3608 NS_LOG_LOGIC ("Left edge of the block: " << (*i).first << "Right edge of t
he block: " << (*i).second); | 3643 NS_LOG_LOGIC ("Left edge of the block: " << (*i).first << "Right edge of t
he block: " << (*i).second); |
3609 option->AddSackBlock (*i); | 3644 option->AddSackBlock (*i); |
3610 allowedSackBlocks--; | 3645 allowedSackBlocks--; |
3611 } | 3646 } |
3612 | 3647 |
3613 header.AppendOption (option); | 3648 header.AppendOption (option); |
3614 NS_LOG_INFO (m_node->GetId () << " Add option SACK"); | 3649 NS_LOG_INFO (m_node->GetId () << " Add option sack"); |
3615 } | 3650 } |
3616 | 3651 |
3617 void | 3652 void |
3618 TcpSocketBase::ProcessOptionTimestamp (const Ptr<const TcpOption> option, | 3653 TcpSocketBase::ProcessOptionTimestamp (const Ptr<const TcpOption> option, |
3619 const SequenceNumber32 &seq) | 3654 const SequenceNumber32 &seq) |
3620 { | 3655 { |
3621 NS_LOG_FUNCTION (this << option); | 3656 NS_LOG_FUNCTION (this << option); |
3622 | 3657 |
3623 Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option); | 3658 Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option); |
3624 | 3659 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3772 TcpSocketBase::Fork (void) | 3807 TcpSocketBase::Fork (void) |
3773 { | 3808 { |
3774 return CopyObject<TcpSocketBase> (this); | 3809 return CopyObject<TcpSocketBase> (this); |
3775 } | 3810 } |
3776 | 3811 |
3777 uint32_t | 3812 uint32_t |
3778 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b) | 3813 TcpSocketBase::SafeSubtraction (uint32_t a, uint32_t b) |
3779 { | 3814 { |
3780 if (a > b) | 3815 if (a > b) |
3781 { | 3816 { |
3782 return a-b; | 3817 return a - b; |
3783 } | 3818 } |
3784 | 3819 |
3785 return 0; | 3820 return 0; |
3786 } | 3821 } |
3787 | 3822 |
3788 //RttHistory methods | 3823 //RttHistory methods |
3789 RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t) | 3824 RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t) |
3790 : seq (s), | 3825 : seq (s), |
3791 count (c), | 3826 count (c), |
3792 time (t), | 3827 time (t), |
3793 retx (false) | 3828 retx (false) |
3794 { | 3829 { |
3795 } | 3830 } |
3796 | 3831 |
3797 RttHistory::RttHistory (const RttHistory& h) | 3832 RttHistory::RttHistory (const RttHistory& h) |
3798 : seq (h.seq), | 3833 : seq (h.seq), |
3799 count (h.count), | 3834 count (h.count), |
3800 time (h.time), | 3835 time (h.time), |
3801 retx (h.retx) | 3836 retx (h.retx) |
3802 { | 3837 { |
3803 } | 3838 } |
3804 | 3839 |
3805 } // namespace ns3 | 3840 } // namespace ns3 |
LEFT | RIGHT |