This documentation is not the Latest Release.
A Discrete-Event Network Simulator
API
tcp-rto-test.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  */
19 #include "tcp-rto-test.h"
20 #include "tcp-error-model.h"
21 
22 #include "ns3/node.h"
23 #include "ns3/log.h"
24 #include "ns3/tcp-westwood.h"
25 
26 namespace ns3 {
27 
28 NS_LOG_COMPONENT_DEFINE ("TcpRtoTest");
29 
30 TcpRtoTest::TcpRtoTest (TypeId &congControl, const std::string &desc)
31  : TcpGeneralTest (desc, 500, 100, Seconds (0.01), Seconds (0.5),
32  Seconds (10), 0, 1, 500, congControl, 1500),
33  m_rtoExpired (false),
34  m_segmentReceived (false)
35 {
36 }
37 
40 {
41  // Get a really low RTO, and let them fire as soon as possible since
42  // we are interested only in what happen after it expires
44  socket->SetAttribute ("MinRto", TimeValue (Seconds (0.5)));
45 
46  return socket;
47 }
48 
49 void
51 {
52  // In this test, the RTO fires for the first segment (and no more).
53  // This function is called after the management of the RTO expiration,
54  // and because of this we must check all the involved variables.
56  "Second RTO expired");
58  "Ack state machine not in LOSS state after a loss");
59 
60  m_rtoExpired = true;
61 }
62 
63 void
65  SocketWho who)
66 {
67  // Called after the first ack is received (the lost segment has been
68  // successfully retransmitted. We must check on the sender that variables
69  // are in the same state as they where after RTOExpired if it is the first
70  // ACK after the loss; in every other case, all must be OPEN and the counter
71  // set to 0.
72 
73  if (m_rtoExpired && who == SENDER)
74  {
76  "Ack state machine not in LOSS state after a loss");
77  }
78  else
79  {
81  "Ack state machine not in OPEN state after recovering "
82  "from loss");
83  }
84 }
85 
86 void
88  SocketWho who)
89 {
90  // Called after the ACK processing. Every time we should be in OPEN state,
91  // without any packet lost or marked as retransmitted, in both the sockets
92 
94  "Ack state machine not in OPEN state after recovering "
95  "from loss");
96 
97  if (who == SENDER)
98  {
99  m_rtoExpired = false;
100  m_segmentReceived = true;
101  }
102 }
103 
104 void
106 {
107  // At least one time we should process an ACK; otherwise, the segment
108  // has not been retransmitted, and this is bad
109 
111  "Retransmission has not been done");
112 }
113 
114 // TcpTimeRtoTest
115 
116 TcpTimeRtoTest::TcpTimeRtoTest (TypeId &congControl, const std::string &desc)
117  : TcpGeneralTest (desc, 500, 100, Seconds (0.01), Seconds (0.5),
118  Seconds (10), 0xffff, 1, 500, congControl, 1500),
119  m_senderSentSegments (0),
120  m_closed (false)
121 {
122 
123 }
124 
127 {
129  s->SetAttribute ("DataRetries", UintegerValue (6));
130 
131  return s;
132 }
133 
136 {
137  Ptr<TcpSeqErrorModel> errorModel = CreateObject<TcpSeqErrorModel> ();
138 
139  // Drop packet for 7 times. At the 7th, the connection should be dropped.
140  for (uint32_t i = 0; i<7; ++i)
141  {
142  errorModel->AddSeqToKill (SequenceNumber32 (1));
143  }
144 
145  errorModel->SetDropCallback (MakeCallback (&TcpTimeRtoTest::PktDropped, this));
146 
147  return errorModel;
148 }
149 
150 void
152 {
153  NS_LOG_FUNCTION (this << p << h << who);
154 
155  if (who == SENDER)
156  {
158  NS_LOG_INFO (Simulator::Now ().GetSeconds () << "\tMeasured RTO:" <<
159  GetRto (SENDER).GetSeconds ());
160 
161  if (h.GetFlags () & TcpHeader::SYN)
162  {
164 
165  Time s_rto = GetRto (SENDER);
167  "SYN packet sent without respecting "
168  "ConnTimeout attribute");
169  }
170  else
171  {
172  NS_LOG_INFO (Simulator::Now ().GetSeconds () << "\tTX: " << h <<
174 
176  "First packet has been correctly sent");
177 
178  // Remember, from RFC:
179  // m_rto = Max (m_rtt->GetEstimate () +
180  // Max (m_clockGranularity, m_rtt->GetVariation ()*4), m_minRto);
181 
182  if (m_senderSentSegments == 2)
183  { // ACK of SYN-ACK, rto set for the first time, since now we have
184  // an estimation of RTT
185 
186  Ptr<RttEstimator> rttEstimator = GetRttEstimator (SENDER);
187  Time clockGranularity = GetClockGranularity (SENDER);
188  m_previousRTO = rttEstimator->GetEstimate ();
189 
190  if (clockGranularity > rttEstimator->GetVariation ()*4)
191  {
192  m_previousRTO += clockGranularity;
193  }
194  else
195  {
196  m_previousRTO += rttEstimator->GetVariation ()*4;
197  }
198 
200 
202  "RTO value differs from calculation");
203  }
204  else if (m_senderSentSegments == 3)
205  { // First data packet. RTO should be the same as before
206 
208  "RTO value has changed unexpectedly");
209 
210  }
211  }
212  }
213  else if (who == RECEIVER)
214  {
215 
216  }
217 }
218 
219 void
221 {
222  m_closed = true;
223 }
224 
225 void
227 {
228  NS_TEST_ASSERT_MSG_EQ (who, SENDER, "RTO in Receiver. That's unexpected");
229 
230  Time actualRto = GetRto (SENDER);
231 
232  if (actualRto < Seconds (60))
233  {
235  "RTO has not doubled after an expiration");
237  }
238  else
239  {
240  NS_TEST_ASSERT_MSG_EQ (actualRto, Seconds (60),
241  "RTO goes beyond 60 second limit");
242  }
243 }
244 
245 void
247 {
248  NS_LOG_INFO (Simulator::Now ().GetSeconds () << "\tDROPPED! " << tcpH);
249 }
250 
251 void
253 {
255  "Socket has not been closed after retrying data retransmissions");
256 }
257 
258 //-----------------------------------------------------------------------------
259 
260 static class TcpRtoTestSuite : public TestSuite
261 {
262 public:
263  TcpRtoTestSuite () : TestSuite ("tcp-rto-test", UNIT)
264  {
265  std::list<TypeId> types;
266  types.insert (types.begin (), TcpNewReno::GetTypeId ());
267  types.insert (types.begin (), TcpWestwood::GetTypeId ());
268 
269  for (std::list<TypeId>::iterator it = types.begin (); it != types.end (); ++it)
270  {
271  AddTestCase (new TcpRtoTest ((*it), "RTO retransmit testing"), TestCase::QUICK);
272  AddTestCase (new TcpTimeRtoTest ((*it), "RTO timing testing"), TestCase::QUICK);
273  }
274  }
276 
277 } // namespace ns3
Time GetMinRto(SocketWho who)
Get the minimun RTO attribute.
virtual void ErrorClose(SocketWho who)
Socket closed with an error.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Normal state, no dubious events.
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:161
uint32_t m_senderSentSegments
Definition: tcp-rto-test.h:77
ns3::TcpRtoTestSuite g_TcpRtoTestSuite
Fast test.
Definition: test.h:1152
A suite of tests to run.
Definition: test.h:1333
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
This test suite implements a Unit Test.
Definition: test.h:1343
static TcpSocketState::TcpCongState_t GetCongStateFrom(Ptr< const TcpSocketState > tcb)
Convenience function to retrieve the ACK state from a TCB.
virtual void Tx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who)
Packet transmitted down to IP layer.
virtual void ProcessedAck(const Ptr< const TcpSocketState > tcb, const TcpHeader &h, SocketWho who)
Processed ack.
Definition: tcp-rto-test.cc:87
Packet header for IPv4.
Definition: ipv4-header.h:31
static TypeId GetTypeId(void)
Get the type ID.
virtual Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node)
Create and install the socket to install on the sender.
bool m_segmentReceived
Definition: tcp-rto-test.h:53
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:297
AttributeValue implementation for Time.
Definition: nstime.h:957
TcpTimeRtoTest(TypeId &congControl, const std::string &msg)
Testing the moments after an RTO expiration.
Definition: tcp-rto-test.h:36
virtual void FinalChecks()
Performs the (eventual) final checks through test asserts.
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:161
virtual Ptr< ErrorModel > CreateReceiverErrorModel()
Create and return the error model to install in the receiver node.
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
Definition: int64x64.h:209
Time GetConnTimeout(SocketWho who)
Get the retransmission time for the SYN segments.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1480
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition: test.h:373
virtual Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node)
Create and install the socket to install on the sender.
Definition: tcp-rto-test.cc:39
Time GetRto(SocketWho who)
Get the retransmission time.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
virtual void RTOExpired(const Ptr< const TcpSocketState > tcb, SocketWho who)
Rto has expired.
virtual Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node)
Create and install the socket to install on the sender.
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-westwood.cc:47
virtual void RcvAck(const Ptr< const TcpSocketState > tcb, const TcpHeader &h, SocketWho who)
Received ack.
Definition: tcp-rto-test.cc:64
void PktDropped(const Ipv4Header &ipH, const TcpHeader &tcpH)
Time GetClockGranularity(SocketWho who)
Get the clock granularity attribute.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
TcpRtoTest(TypeId &congControl, const std::string &msg)
Definition: tcp-rto-test.cc:30
virtual void RTOExpired(const Ptr< const TcpSocketState > tcb, SocketWho who)
Rto has expired.
Definition: tcp-rto-test.cc:50
SocketWho
Used as parameter of methods, specifies on what node the caller is interested (e.g.
Ptr< RttEstimator > GetRttEstimator(SocketWho who)
Get the Rtt estimator of the socket.
General infrastructure for TCP testing.
CWND was reduced due to RTO timeout or SACK reneging.
virtual void FinalChecks()
Performs the (eventual) final checks through test asserts.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:895
a unique identifier for an interface.
Definition: type-id.h:58
Testing the timing of RTO.
Definition: tcp-rto-test.h:61