A Discrete-Event Network Simulator
API
tcp-fast-retr-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 "ns3/log.h"
20 #include "tcp-fast-retr-test.h"
21 #include "ns3/tcp-westwood.h"
22 #include "ns3/node.h"
23 
24 namespace ns3 {
25 
26 NS_LOG_COMPONENT_DEFINE ("TcpFastRetrTest");
27 
28 TcpFastRetrTest::TcpFastRetrTest (TypeId typeId, uint32_t seqToKill,
29  const std::string &msg)
30  : TcpGeneralTest (msg),
31  m_pktDropped (false),
32  m_pktWasDropped (false),
33  m_seqToKill (seqToKill),
34  m_dupAckReceived (0),
35  m_sndNextExpSeq (0),
36  m_rcvNextExpAck (1),
37  m_countRetr (0),
38  m_bytesRcvButNotAcked (0)
39 {
40  m_congControlTypeId = typeId;
41 }
42 
43 void
45 {
48 }
49 
50 void
52 {
54  SetAppPktCount (100);
55 }
56 
59 {
60  return 0;
61 }
62 
65 {
66  m_errorModel = CreateObject<TcpSeqErrorModel> ();
67  m_errorModel->AddSeqToKill (SequenceNumber32 (m_seqToKill));
68  m_errorModel->SetDropCallback (MakeCallback (&TcpFastRetrTest::PktDropped, this));
69 
70  return m_errorModel;
71 }
72 
73 
76 {
78  socket->SetAttribute ("MinRto", TimeValue (Seconds (10.0)));
79 
80  return socket;
81 }
82 
83 void
85 {
86  if (who == SENDER)
87  {
88  // Nothing to check
89  NS_LOG_INFO ("\tSENDER Rx " << h);
90  }
91  else if (who == RECEIVER)
92  {
93  NS_LOG_INFO ("\tRECEIVER Rx " << h);
94 
95  // Receiver has received the missing segment
96  if (h.GetSequenceNumber ().GetValue () == m_seqToKill)
97  {
98  m_pktDropped = false;
99  if (m_bytesRcvButNotAcked > 0)
100  {
103  }
104  }
105 
106  // Count all the received bytes not acked
107  if (m_pktDropped)
108  {
110  }
111  }
112 }
113 
114 void
116 {
117  if (who == SENDER)
118  {
119  NS_LOG_INFO ("\tSENDER Tx " << h << " size=" << p->GetSize ());
120 
122  {
123  // Spotted the retransmission!
124  m_countRetr++;
126  "Segment retransmitted too many times");
127  }
128  else
129  {
130  // No delayed ACK involved here.
131  while (h.GetSequenceNumber () < m_sndNextExpSeq)
132  {
134  }
135 
136  if (h.GetSequenceNumber ().GetValue () != 50002)
137  {
139  "Sequence number expected differs");
140  }
141  }
142 
143  if (m_sndNextExpSeq.GetValue () == 0)
144  {
145  // SYN
147  }
148  else if (m_sndNextExpSeq.GetValue () == 1 && p->GetSize () == 32)
149  {
150  // Pure ACK in three-way handshake, then we expect data
152  }
153  else
154  {
155  // Data segments
157  }
158  }
159  else if (who == RECEIVER)
160  {
161  NS_LOG_INFO ("\tRECEIVER Tx, " << h << " size=" << p->GetSize ());
162 
163  if (h.GetFlags () == (TcpHeader::SYN | TcpHeader::ACK))
164  {
166  "SYN pkt has not 0 as initial sequence number."
167  "Probably, random sqn number has been implemented."
168  "Check this test");
169  }
170  else
171  {
173  "ACK pkt has not 1 as sequence number."
174  "Probably, random sqn number has been implemented."
175  "Check this test");
176  }
177 
178  // Accounted for delayed ACK, but not received.
179  while (h.GetAckNumber () < m_rcvNextExpAck)
180  {
182  }
183 
184  if (m_rcvNextExpAck.GetValue () >= 50001)
185  {
186  m_rcvNextExpAck = 50002;
187  }
188 
190  "ACKing something not considered");
191 
192  if (m_pktDropped)
193  {
195  }
196  else
197  {
198  switch (m_rcvNextExpAck.GetValue ())
199  {
200  case 0:
202  break;
203  case 1:
205  break;
206  case 50002:
207  break;
208  default:
210  }
211  }
212  }
213 }
214 
215 void
217  SocketWho who)
218 {
219  NS_LOG_FUNCTION (this << tcb << h << who);
220 
221  if (who == SENDER)
222  {
223  if (h.GetAckNumber ().GetValue () < m_seqToKill)
224  {
226  "Not in OPEN state to respond to a loss");
228  "Dupack different than 0 but no loss detected");
229  }
230  else if (h.GetAckNumber ().GetValue () == m_seqToKill)
231  {
233  "Dupack count differs");
234 
235  if (GetDupAckCount (SENDER) == 0 &&
237  {
239  "Not in OPEN state for processing dupack");
240  }
241  else if (GetDupAckCount (SENDER) > 0 &&
243  {
245  "Not in DISORDER state after receiving dupacks");
246  }
248  {
250  "Not in RECOVERY state after reaching retxthresh");
251  }
252  }
253  }
254  else if (who == RECEIVER)
255  {
257  "Receiver not in OPEN state");
258  }
259 }
260 
261 void
263  SocketWho who)
264 {
265  NS_LOG_FUNCTION (this << tcb << h << who);
266 
267  if (who == SENDER)
268  {
269  if (m_previousAck == h.GetAckNumber () && h.GetAckNumber ().GetValue () < 50002)
270  {
272 
274  "Count of dupAck differs");
275 
277  {
279  "DupAck less than ReTxThreshold but not "
280  "in DISORDER state");
281  }
282  else
283  {
285  "DupAck greater than ReTxThreshold but not "
286  "in RECOVERY or LOSS state");
287  m_pktWasDropped = true;
288  }
289  }
290  else if (m_previousAck < h.GetAckNumber ())
291  {
292  m_dupAckReceived = 0;
293  }
294 
296  }
297  else if (who == RECEIVER)
298  {
300  "Different state than OPEN in the receiver");
301  }
302 }
303 
304 void
306 {
307  NS_ASSERT_MSG (true == false, "RTO isn't expected here");
308 }
309 
310 void
312  const TcpSocketState::TcpCongState_t newValue)
313 {
314  NS_LOG_FUNCTION (this << oldValue << newValue);
315 
316  if (oldValue == TcpSocketState::CA_OPEN && newValue == TcpSocketState::CA_DISORDER)
317  {
318  }
319  else if (oldValue == TcpSocketState::CA_OPEN
320  && newValue == TcpSocketState::CA_RECOVERY
321  && GetReTxThreshold (SENDER) > 1)
322  {
323  NS_TEST_ASSERT_MSG_EQ (true, false,
324  "Invalid OPEN to RECOVERY state change");
325  }
326  else if (oldValue == TcpSocketState::CA_DISORDER
327  && newValue == TcpSocketState::CA_RECOVERY)
328  {
330  "DISORDER to RECOVERY state change but not reached "
331  "the ReTxThreshold");
332  }
333 }
334 
335 
336 void
338 {
339  NS_LOG_FUNCTION (this << ipH << tcpH);
340 
341  m_pktDropped = true;
343 
345  "Packet dropped but sequence number differs");
346 }
347 
348 void
350 {
352  "Packet was not dropped at all");
354  "Segment was not retransmitted at all");
356  "Not all data have been transmitted");
357 }
358 
359 //-----------------------------------------------------------------------------
360 
361 static class TcpFastRetrTestSuite : public TestSuite
362 {
363 public:
364  TcpFastRetrTestSuite () : TestSuite ("tcp-fast-retr-test", UNIT)
365  {
366  std::list<TypeId> types;
367  types.insert (types.begin (), TcpWestwood::GetTypeId ());
368  types.insert (types.begin (), TcpNewReno::GetTypeId ());
369 
370  for (std::list<TypeId>::iterator it = types.begin (); it != types.end (); ++it)
371  {
372  AddTestCase (new TcpFastRetrTest ((*it), 5001, "Fast Retransmit testing"), TestCase::QUICK);
373  }
374  }
376 
377 } // namespace ns3
virtual void FinalChecks()
Performs the (eventual) final checks through test asserts.
SequenceNumber32 m_sndNextExpSeq
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
uint32_t GetDelAckCount(SocketWho who)
Get the number of delayed ack (if present)
uint32_t GetSegSize(SocketWho who)
Get the segment size of the node specified.
CWND was reduced, we are fast-retransmitting.
In all the respects it is "Open", but requires a bit more attention.
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
Fast test.
Definition: test.h:1152
A suite of tests to run.
Definition: test.h:1333
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
virtual void RTOExpired(const Ptr< const TcpSocketState > tcb, SocketWho who)
Rto has expired.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
void PktDropped(const Ipv4Header &ipH, const TcpHeader &tcpH, Ptr< const Packet > p)
#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 Ptr< ErrorModel > CreateSenderErrorModel()
Create and return the error model to install in the sender node.
virtual void RcvAck(const Ptr< const TcpSocketState > tcb, const TcpHeader &h, SocketWho who)
Received ack.
Packet header for IPv4.
Definition: ipv4-header.h:33
virtual void Tx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who)
Packet transmitted down to IP layer.
static TypeId GetTypeId(void)
Get the type ID.
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:298
virtual Ptr< ErrorModel > CreateReceiverErrorModel()
Create and return the error model to install in the receiver node.
AttributeValue implementation for Time.
Definition: nstime.h:957
uint32_t GetDupAckCount(SocketWho who)
Get the number of dupack received.
SequenceNumber32 m_previousAck
virtual void ConfigureProperties(void)
Change the configuration of the socket properties.
Test the fast retransmission.
#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
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
TcpFastRetrTest(TypeId congControl, uint32_t seqToKill, const std::string &msg)
SequenceNumber32 m_rcvNextExpAck
virtual void ProcessedAck(const Ptr< const TcpSocketState > tcb, const TcpHeader &h, SocketWho who)
Processed ack.
ns3::TcpFastRetrTestSuite g_TcpFastRetrTestSuite
TcpCongState_t
Definition of the Congestion state machine.
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 Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node)
Create and install the socket to install on the sender.
void SetAppPktCount(uint32_t pktCount)
Set app packet count.
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
uint32_t GetReTxThreshold(SocketWho who)
Get the retransmission threshold.
virtual void ConfigureProperties()
Change the configuration of the socket properties.
void SetInitialSsThresh(SocketWho who, uint32_t initialSsThresh)
Forcefully set the initial ssth.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
SocketWho
Used as parameter of methods, specifies on what node the caller is interested (e.g.
virtual void ConfigureEnvironment()
Change the configuration of the evironment.
General infrastructure for TCP testing.
Ptr< TcpSeqErrorModel > m_errorModel
virtual void ConfigureEnvironment(void)
Change the configuration of the evironment.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:895
virtual void Rx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who)
Packet received from IP layer.
virtual void CongStateTrace(const TcpSocketState::TcpCongState_t oldValue, const TcpSocketState::TcpCongState_t newValue)
State on Ack state machine changes.
#define NS_TEST_ASSERT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to a limit and report and abort if not...
Definition: test.h:1011
a unique identifier for an interface.
Definition: type-id.h:58
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
TypeId m_congControlTypeId
Congestion control.