From d17168bc7e38ead174f2da3f2dfb1071fa338d9c Mon Sep 17 00:00:00 2001 From: Natale Patriciello Date: Fri, 22 Jan 2016 16:15:58 +0100 Subject: [PATCH] [BUG 2068] Timestamp option conforms to RFC 7323 --- RELEASE_NOTES | 1 + src/aodv/test/tcp-chain-test-0-0.pcap | Bin 53374 -> 53374 bytes src/aodv/test/tcp-chain-test-9-0.pcap | Bin 28956 -> 28956 bytes src/internet/model/tcp-socket-base.cc | 54 ++++++++++++++++++++------ src/internet/model/tcp-socket-base.h | 7 +++- 5 files changed, 49 insertions(+), 13 deletions(-) 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 95974dccaeddc2442f1f1644c1051fb52c6e64b3..777179bee2e21aad30feb98a2bb1ec43941f5f32 100644 GIT binary patch delta 164 zcmeyjfcf77<_!xZ`I$d4fB_?rc}BKBFJtiL7ZpG*`-RN~t(`oKzMFqdY~$hQI0Z422}rH_$U1o; tv-sv^^OAWO-8XZs2Fi0DLCCWl+$?p(j)#eB-{hzZDgg3*Gc5oB delta 164 zcmeyjfcf77<_!xZ`B_pKz$HT;JJvr)v3IJ@>G64Vp diff --git a/src/aodv/test/tcp-chain-test-9-0.pcap b/src/aodv/test/tcp-chain-test-9-0.pcap index 28d26d6088c85d211dc1ab968b870092e75b9d67..a95bccf4176dd435fc21e7ee33168edfd2bf15d1 100644 GIT binary patch delta 285 zcmbR9h;hy%#tnKxOw6Aq8wh;@QkzwT-|+CWJYoO?Mj**|n{~3Fr1WGfg%~E5N1JCT zOlM_`pKPGk${4?So7yy1Ce}NX{d8JD)D@jHAhp>>7pNq1@)e_2AQ@#0BsV`Wu3%+i zyEZw>vIRsvuuKC|n?0<63WFy^KGI=fhT>B8_ZEWWSn|CTNhzS6V)?N_+ delta 285 zcmbR9h;hy%#tnKxOf0FB4TL@csm&_FZ+Q4w;~Bt!5lHggW}Pf3DLvUrA%=-He)9~4 z>8y-*CL5@=GTzy|O>G)06IE8~&LQPHi8M>ao*20Dt%adJgs y3yAucm 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