[BUG 2068] Timestamp option conforms to RFC 7323

This commit is contained in:
Natale Patriciello
2016-01-22 16:15:58 +01:00
parent d3198a5795
commit d17168bc7e
5 changed files with 49 additions and 13 deletions

View File

@@ -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

View File

@@ -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> packet, const Address &fromAddress,
*/
m_rWnd = tcpHeader.GetWindowSize ();
// When receiving a <SYN> or <SYN-ACK> 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<const TcpOption> option)
TcpSocketBase::ProcessOptionTimestamp (const Ptr<const TcpOption> option,
const SequenceNumber32 &seq)
{
NS_LOG_FUNCTION (this << option);
Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (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 ());

View File

@@ -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<const TcpOption> option);
void ProcessOptionTimestamp (const Ptr<const TcpOption> 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<uint32_t> m_rWnd; //!< Receiver window (RCV.WND in RFC793)
TracedValue<SequenceNumber32> m_highRxMark; //!< Highest seqno received
SequenceNumber32 m_highTxAck; //!< Highest ack sent
TracedValue<SequenceNumber32> m_highRxAckMark; //!< Highest ack received
uint32_t m_bytesAckedNotProcessed; //!< Bytes acked, but not processed