diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 1891632fc..c7863fa2e 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -57,6 +57,7 @@ Bugs fixed - Bug 1999 - PointToPointRemoteChannel invokes PointToPointChannel constructor - Bug 2003 - Missing DSSS short PLCP preamble - Bug 2041 - TCP RTO needs unit tests +- Bug 2068 - Timestamp option conforms to RFC 7323 - Bug 2141 - TCP DataSent callback now correctly notifies sent data, without missing bytes in particular conditions - Bug 2150 - The TCP sender keeps retransmitting and does not terminate the connection after some retries. - Bug 2159 - TCP advertises wrong receive window diff --git a/src/aodv/test/tcp-chain-test-0-0.pcap b/src/aodv/test/tcp-chain-test-0-0.pcap index 95974dcca..777179bee 100644 Binary files a/src/aodv/test/tcp-chain-test-0-0.pcap and b/src/aodv/test/tcp-chain-test-0-0.pcap differ diff --git a/src/aodv/test/tcp-chain-test-9-0.pcap b/src/aodv/test/tcp-chain-test-9-0.pcap index 28d26d608..a95bccf41 100644 Binary files a/src/aodv/test/tcp-chain-test-9-0.pcap and b/src/aodv/test/tcp-chain-test-9-0.pcap differ diff --git a/src/internet/model/tcp-socket-base.cc b/src/internet/model/tcp-socket-base.cc index 64ef4d910..fc1805253 100644 --- a/src/internet/model/tcp-socket-base.cc +++ b/src/internet/model/tcp-socket-base.cc @@ -283,6 +283,7 @@ TcpSocketBase::TcpSocketBase (void) m_maxWinSize (0), m_rWnd (0), m_highRxMark (0), + m_highTxAck (0), m_highRxAckMark (0), m_bytesAckedNotProcessed (0), m_winScalingEnabled (false), @@ -1175,11 +1176,42 @@ TcpSocketBase::DoForwardUp (Ptr packet, const Address &fromAddress, */ m_rWnd = tcpHeader.GetWindowSize (); + // When receiving a or we should adapt TS to the other end + if (tcpHeader.HasOption (TcpOption::TS) && m_timestampEnabled) + { + ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), + tcpHeader.GetSequenceNumber ()); + } + else + { + m_timestampEnabled = false; + } + + // Initialize cWnd and ssThresh m_tcb->m_cWnd = GetInitialCwnd () * GetSegSize (); m_tcb->m_ssThresh = GetInitialSSThresh (); } else if (tcpHeader.GetFlags () & TcpHeader::ACK) { + NS_ASSERT (!(tcpHeader.GetFlags () & TcpHeader::SYN)); + if (m_timestampEnabled) + { + if (!tcpHeader.HasOption (TcpOption::TS)) + { + // Ignoring segment without TS, RFC 7323 + NS_LOG_LOGIC ("At state " << TcpStateName[m_state] << + " received packet of seq [" << seq << + ":" << seq + packet->GetSize () << + ") without TS option. Silently discard it"); + return; + } + else + { + ProcessOptionTimestamp (tcpHeader.GetOption (TcpOption::TS), + tcpHeader.GetSequenceNumber ()); + } + } + EstimateRtt (tcpHeader); UpdateWindowSize (tcpHeader); } @@ -2121,6 +2153,10 @@ TcpSocketBase::SendEmptyPacket (uint8_t flags) { // If sending an ACK, cancel the delay ACK as well m_delAckEvent.Cancel (); m_delAckCount = 0; + if (m_highTxAck < header.GetAckNumber ()) + { + m_highTxAck = header.GetAckNumber (); + } } if (m_retxEvent.IsExpired () && (hasSyn || hasFin) && !isAck ) { // Retransmit SYN / SYN+ACK / FIN / FIN+ACK to guard against lost @@ -3086,15 +3122,6 @@ TcpSocketBase::ReadOptions (const TcpHeader& header) } } } - - bool timestampAttribute = m_timestampEnabled; - m_timestampEnabled = false; - - if (header.HasOption (TcpOption::TS) && timestampAttribute) - { - m_timestampEnabled = true; - ProcessOptionTimestamp (header.GetOption (TcpOption::TS)); - } } void @@ -3180,12 +3207,17 @@ TcpSocketBase::AddOptionWScale (TcpHeader &header) } void -TcpSocketBase::ProcessOptionTimestamp (const Ptr option) +TcpSocketBase::ProcessOptionTimestamp (const Ptr option, + const SequenceNumber32 &seq) { NS_LOG_FUNCTION (this << option); Ptr ts = DynamicCast (option); - m_timestampToEcho = ts->GetTimestamp (); + + if (seq == m_rxBuffer->NextRxSequence () && seq <= m_highTxAck) + { + m_timestampToEcho = ts->GetTimestamp (); + } NS_LOG_INFO (m_node->GetId () << " Got timestamp=" << m_timestampToEcho << " and Echo=" << ts->GetEcho ()); diff --git a/src/internet/model/tcp-socket-base.h b/src/internet/model/tcp-socket-base.h index f0a31f3c9..d5ae8b8fd 100644 --- a/src/internet/model/tcp-socket-base.h +++ b/src/internet/model/tcp-socket-base.h @@ -882,9 +882,11 @@ protected: * to utilize later to calculate RTT. * * \see EstimateRtt - * \param option Option from the packet + * \param option Option from the segment + * \param seq Sequence number of the segment */ - void ProcessOptionTimestamp (const Ptr option); + void ProcessOptionTimestamp (const Ptr option, + const SequenceNumber32 &seq); /** * \brief Add the timestamp option to the header * @@ -949,6 +951,7 @@ protected: uint16_t m_maxWinSize; //!< Maximum window size to advertise TracedValue m_rWnd; //!< Receiver window (RCV.WND in RFC793) TracedValue m_highRxMark; //!< Highest seqno received + SequenceNumber32 m_highTxAck; //!< Highest ack sent TracedValue m_highRxAckMark; //!< Highest ack received uint32_t m_bytesAckedNotProcessed; //!< Bytes acked, but not processed