internet: added tcp-rtt-estimation test

This commit is contained in:
Natale Patriciello
2016-02-22 10:07:19 +01:00
parent 85c64c4d03
commit 932033c7a3
4 changed files with 253 additions and 19 deletions

View File

@@ -164,6 +164,7 @@ TcpGeneralTest::DoRun (void)
m_receiverSocket->SetProcessedAckCb (MakeCallback (&TcpGeneralTest::ProcessedAckCb, this));
m_receiverSocket->SetRetransmitCb (MakeCallback (&TcpGeneralTest::RtoExpiredCb, this));
m_receiverSocket->SetForkCb (MakeCallback (&TcpGeneralTest::ForkCb, this));
m_receiverSocket->SetUpdateRttHistoryCb (MakeCallback (&TcpGeneralTest::UpdateRttHistoryCb, this));
m_receiverSocket->TraceConnectWithoutContext ("Tx",
MakeCallback (&TcpGeneralTest::TxPacketCb, this));
m_receiverSocket->TraceConnectWithoutContext ("Rx",
@@ -181,6 +182,7 @@ TcpGeneralTest::DoRun (void)
m_senderSocket->SetProcessedAckCb (MakeCallback (&TcpGeneralTest::ProcessedAckCb, this));
m_senderSocket->SetRetransmitCb (MakeCallback (&TcpGeneralTest::RtoExpiredCb, this));
m_senderSocket->SetDataSentCallback (MakeCallback (&TcpGeneralTest::DataSentCb, this));
m_senderSocket->SetUpdateRttHistoryCb (MakeCallback (&TcpGeneralTest::UpdateRttHistoryCb, this));
m_senderSocket->TraceConnectWithoutContext ("CongestionWindow",
MakeCallback (&TcpGeneralTest::CWndTrace, this));
m_senderSocket->TraceConnectWithoutContext ("CongState",
@@ -334,6 +336,25 @@ TcpGeneralTest::NormalCloseCb (Ptr<Socket> socket)
}
}
void
TcpGeneralTest::UpdateRttHistoryCb (Ptr<const TcpSocketBase> tcp,
const SequenceNumber32 & seq, uint32_t sz,
bool isRetransmission)
{
if (tcp->GetNode () == m_receiverSocket->GetNode ())
{
UpdatedRttHistory (seq, sz, isRetransmission, RECEIVER);
}
else if (tcp->GetNode () == m_senderSocket->GetNode ())
{
UpdatedRttHistory (seq, sz, isRetransmission, SENDER);
}
else
{
NS_FATAL_ERROR ("Closed socket, but not recognized");
}
}
void
TcpGeneralTest::RtoExpiredCb (const Ptr<const TcpSocketState> tcb,
const Ptr<const TcpSocketBase> tcp)
@@ -775,21 +796,21 @@ TcpSocketMsgBase::Fork (void)
}
void
TcpSocketMsgBase::SetRcvAckCb (AckManagementCallback cb)
TcpSocketMsgBase::SetRcvAckCb (AckManagementCb cb)
{
NS_ASSERT (!cb.IsNull ());
m_rcvAckCb = cb;
}
void
TcpSocketMsgBase::SetProcessedAckCb (AckManagementCallback cb)
TcpSocketMsgBase::SetProcessedAckCb (AckManagementCb cb)
{
NS_ASSERT (!cb.IsNull ());
m_processedAckCb = cb;
}
void
TcpSocketMsgBase::SetRetransmitCb (RetrCallback cb)
TcpSocketMsgBase::SetRetransmitCb (RetrCb cb)
{
NS_ASSERT (!cb.IsNull ());
m_retrCallback = cb;
@@ -821,6 +842,24 @@ TcpSocketMsgBase::SetForkCb (Callback<void, Ptr<TcpSocketMsgBase> > cb)
m_forkCb = cb;
}
void
TcpSocketMsgBase::SetUpdateRttHistoryCb (UpdateRttCallback cb)
{
NS_ASSERT (!cb.IsNull ());
m_updateRttCb = cb;
}
void
TcpSocketMsgBase::UpdateRttHistory (const SequenceNumber32 &seq, uint32_t sz,
bool isRetransmission)
{
TcpSocketBase::UpdateRttHistory (seq, sz, isRetransmission);
if (!m_updateRttCb.IsNull ())
{
m_updateRttCb (this, seq, sz, isRetransmission);
}
}
void
TcpSocketMsgBase::CompleteFork (Ptr<Packet> p, const TcpHeader &tcpHeader,
const Address &fromAddress, const Address &toAddress)

View File

@@ -60,9 +60,11 @@ public:
}
typedef Callback<void, Ptr<const Packet>, const TcpHeader&,
Ptr<const TcpSocketBase> > AckManagementCallback;
Ptr<const TcpSocketBase> > AckManagementCb;
typedef Callback<void, Ptr<const TcpSocketState>,
Ptr<const TcpSocketBase> > RetrCallback;
Ptr<const TcpSocketBase> > RetrCb;
typedef Callback<void, Ptr<const TcpSocketBase>, const SequenceNumber32&,
uint32_t, bool> UpdateRttCallback;
/**
* \brief Set the callback invoked when an ACK is received (at the beginning
@@ -70,7 +72,7 @@ public:
*
* \param cb callback
*/
void SetRcvAckCb (AckManagementCallback cb);
void SetRcvAckCb (AckManagementCb cb);
/**
* \brief Set the callback invoked when an ACK is received and processed
@@ -78,14 +80,14 @@ public:
*
* \param cb callback
*/
void SetProcessedAckCb (AckManagementCallback cb);
void SetProcessedAckCb (AckManagementCb cb);
/**
* \brief Set the callback invoked after the processing of a retransmit timeout
*
* \param cb callback
*/
void SetRetransmitCb (RetrCallback cb);
void SetRetransmitCb (RetrCb cb);
/**
* \brief Set the callback invoked after the forking
@@ -93,18 +95,28 @@ public:
*/
void SetForkCb (Callback<void, Ptr<TcpSocketMsgBase> > cb);
/**
* \brief Set the callback invoked when we update rtt history
*
* \param cb callback
*/
void SetUpdateRttHistoryCb (UpdateRttCallback cb);
protected:
virtual void ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader);
virtual void Retransmit (void);
virtual Ptr<TcpSocketBase> Fork (void);
virtual void CompleteFork (Ptr<Packet> p, const TcpHeader& tcpHeader,
const Address& fromAddress, const Address& toAddress);
virtual void UpdateRttHistory (const SequenceNumber32 &seq, uint32_t sz,
bool isRetransmission);
private:
AckManagementCallback m_rcvAckCb;
AckManagementCallback m_processedAckCb;
RetrCallback m_retrCallback;
AckManagementCb m_rcvAckCb;
AckManagementCb m_processedAckCb;
RetrCb m_retrCallback;
Callback<void, Ptr<TcpSocketMsgBase> > m_forkCb;
UpdateRttCallback m_updateRttCb;
};
@@ -129,16 +141,17 @@ public:
TcpSocketSmallAcks ()
: TcpSocketMsgBase (),
m_bytesToAck (125),
m_bytesLeftToBeAcked (0),
m_lastAckedSeq (1)
m_bytesToAck (125),
m_bytesLeftToBeAcked (0),
m_lastAckedSeq (1)
{
}
TcpSocketSmallAcks (const TcpSocketSmallAcks &other) : TcpSocketMsgBase (other),
m_bytesToAck (other.m_bytesToAck),
m_bytesLeftToBeAcked (other.m_bytesLeftToBeAcked),
m_lastAckedSeq (other.m_lastAckedSeq)
TcpSocketSmallAcks (const TcpSocketSmallAcks &other)
: TcpSocketMsgBase (other),
m_bytesToAck (other.m_bytesToAck),
m_bytesLeftToBeAcked (other.m_bytesLeftToBeAcked),
m_lastAckedSeq (other.m_lastAckedSeq)
{
}
@@ -464,7 +477,7 @@ protected:
* \param newValue new value
*/
virtual void CongStateTrace (const TcpSocketState::TcpCongState_t oldValue,
const TcpSocketState::TcpCongState_t newValue)
const TcpSocketState::TcpCongState_t newValue)
{
}
@@ -580,6 +593,18 @@ protected:
{
}
/**
* \brief Updated the Rtt history
* \param seq Sequence inserted
* \param sz size
* \param isRetransmission self-explanatory
* \param who where the rtt history was updated
*/
virtual void UpdatedRttHistory (const SequenceNumber32 & seq, uint32_t sz,
bool isRetransmission, SocketWho who)
{
}
/**
* \brief Notifying application for sent data
*
@@ -709,6 +734,8 @@ private:
const Ptr<const TcpSocketBase> tcp);
void RtoExpiredCb (const Ptr<const TcpSocketState> tcb,
const Ptr<const TcpSocketBase> tcp);
void UpdateRttHistoryCb (Ptr<const TcpSocketBase> tcp, const SequenceNumber32&seq,
uint32_t sz, bool isRetransmission);
void DataSentCb (Ptr<Socket> socket, uint32_t size);
void ForkCb (Ptr<TcpSocketMsgBase> tcp);
void HandleAccept (Ptr<Socket> socket, const Address& from);

View File

@@ -0,0 +1,167 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016 Natale Patriciello <natale.patriciello@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "tcp-general-test.h"
#include "ns3/node.h"
#include "ns3/log.h"
#include "tcp-error-model.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("TcpRttEstimationTestSuite");
/**
* \brief Check Rtt calculations
*
* First check is that, for each ACK, we have a valid estimation of the RTT.
* The second check is that, when updating RTT history, we should consider
* retransmission only segments which sequence number is lower than the highest
* already transmitted.
*/
class TcpRttEstimationTest : public TcpGeneralTest
{
public:
TcpRttEstimationTest (const std::string &desc, bool enableTs, uint32_t dataPkt);
protected:
virtual Ptr<TcpSocketMsgBase> CreateReceiverSocket (Ptr<Node> node);
virtual Ptr<TcpSocketMsgBase> CreateSenderSocket (Ptr<Node> node);
virtual void Rx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who);
virtual void Tx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who);
virtual void UpdatedRttHistory (const SequenceNumber32 & seq, uint32_t sz,
bool isRetransmission, SocketWho who);
virtual void RttTrace (Time oldTime, Time newTime);
void FinalChecks ();
private:
bool m_enableTs;
bool m_rttChanged;
SequenceNumber32 m_highestTxSeq;
};
TcpRttEstimationTest::TcpRttEstimationTest (const std::string &desc, bool enableTs, uint32_t dataPkt)
: TcpGeneralTest (desc, 500, dataPkt, Seconds (0.01), Seconds (0.05), Seconds (2.0),
0xffffffff,1, 500),
m_enableTs (enableTs),
m_rttChanged (false),
m_highestTxSeq (0)
{
}
Ptr<TcpSocketMsgBase>
TcpRttEstimationTest::CreateReceiverSocket (Ptr<Node> node)
{
Ptr<TcpSocketMsgBase> s = TcpGeneralTest::CreateReceiverSocket (node);
if (!m_enableTs)
{
s->SetAttribute ("Timestamp", BooleanValue (false));
}
return s;
}
Ptr<TcpSocketMsgBase>
TcpRttEstimationTest::CreateSenderSocket (Ptr<Node> node)
{
Ptr<TcpSocketMsgBase> s = TcpGeneralTest::CreateSenderSocket (node);
if (!m_enableTs)
{
s->SetAttribute ("Timestamp", BooleanValue (false));
}
return s;
}
void
TcpRttEstimationTest::Tx (const Ptr<const Packet> p, const TcpHeader &h, SocketWho who)
{
if (who == SENDER && h.GetFlags () != TcpHeader::SYN)
{
if (m_highestTxSeq < h.GetSequenceNumber ())
{
m_highestTxSeq = h.GetSequenceNumber ();
}
Ptr<RttEstimator> rttEstimator = GetRttEstimator (SENDER);
NS_ASSERT (rttEstimator != 0);
NS_LOG_DEBUG ("S Rx: seq=" << h.GetSequenceNumber () << " ack=" << h.GetAckNumber ());
NS_TEST_ASSERT_MSG_NE (rttEstimator->GetEstimate (), Seconds (1),
"Default Estimate for the RTT");
}
}
void
TcpRttEstimationTest::Rx (const Ptr<const Packet> p, const TcpHeader &h, SocketWho who)
{
if (who == RECEIVER)
{
NS_LOG_DEBUG ("R Rx: seq=" << h.GetSequenceNumber () << " ack=" << h.GetAckNumber ());
}
}
void
TcpRttEstimationTest::UpdatedRttHistory (const SequenceNumber32 & seq, uint32_t sz,
bool isRetransmission, SocketWho who)
{
if (seq < m_highestTxSeq)
{
NS_TEST_ASSERT_MSG_EQ (isRetransmission, true,
"A retransmission is not flagged as such");
}
else
{
NS_TEST_ASSERT_MSG_EQ (isRetransmission, false,
"Incorrectly flagging seq as retransmission");
}
}
void
TcpRttEstimationTest::RttTrace (Time oldTime, Time newTime)
{
NS_LOG_DEBUG ("Rtt changed to " << newTime);
m_rttChanged = true;
}
void
TcpRttEstimationTest::FinalChecks ()
{
NS_TEST_ASSERT_MSG_EQ (m_rttChanged, true, "Rtt was not updated");
}
//-----------------------------------------------------------------------------
static class TcpRttEstimationTestSuite : public TestSuite
{
public:
TcpRttEstimationTestSuite () : TestSuite ("tcp-rtt-estimation-test", UNIT)
{
AddTestCase (new TcpRttEstimationTest ("RTT estimation, ts, no data", true, 0),
TestCase::QUICK);
AddTestCase (new TcpRttEstimationTest ("RTT estimation, no ts, no data", false, 0),
TestCase::QUICK);
AddTestCase (new TcpRttEstimationTest ("RTT estimation, ts, some data", true, 10),
TestCase::QUICK);
AddTestCase (new TcpRttEstimationTest ("RTT estimation, no ts, some data", false, 10),
TestCase::QUICK);
}
} g_tcpRttEstimationTestSuite;
} // namespace ns3

View File

@@ -243,6 +243,7 @@ def build(bld):
'test/tcp-hybla-test.cc',
'test/tcp-zero-window-test.cc',
'test/tcp-pkts-acked-test.cc',
'test/tcp-rtt-estimation.cc',
'test/udp-test.cc',
'test/ipv6-address-generator-test-suite.cc',
'test/ipv6-dual-stack-test-suite.cc',