This documentation is not the Latest Release.
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, 500, 100, Seconds (0.01), Seconds (0.5), Seconds (10),
31  0, 1, 500, typeId, 1500),
32  m_pktDropped (false),
33  m_pktWasDropped (false),
34  m_seqToKill (seqToKill),
35  m_dupAckReceived (0),
36  m_sndNextExpSeq (0),
37  m_rcvNextExpAck (1),
38  m_countRetr (0),
39  m_bytesRcvButNotAcked (0)
40 {
41 }
42 
45 {
46  return 0;
47 }
48 
51 {
52  m_errorModel = CreateObject<TcpSeqErrorModel> ();
53  m_errorModel->AddSeqToKill (SequenceNumber32 (m_seqToKill));
54  m_errorModel->SetDropCallback (MakeCallback (&TcpFastRetrTest::PktDropped, this));
55 
56  return m_errorModel;
57 }
58 
59 
62 {
64  socket->SetAttribute ("MinRto", TimeValue (Seconds (10.0)));
65 
66  return socket;
67 }
68 
69 void
71 {
72  if (who == SENDER)
73  {
74  // Nothing to check
75  NS_LOG_INFO ("\tSENDER Rx " << h);
76  }
77  else if (who == RECEIVER)
78  {
79  NS_LOG_INFO ("\tRECEIVER Rx " << h);
80 
81  // Receiver has received the missing segment
82  if (h.GetSequenceNumber ().GetValue () == m_seqToKill)
83  {
84  m_pktDropped = false;
85  if (m_bytesRcvButNotAcked > 0)
86  {
89  }
90  }
91 
92  // Count all the received bytes not acked
93  if (m_pktDropped)
94  {
96  }
97  }
98 }
99 
100 void
102 {
103  if (who == SENDER)
104  {
105  NS_LOG_INFO ("\tSENDER Tx " << h << " size=" << p->GetSize ());
106 
108  {
109  // Spotted the retransmission!
110  m_countRetr++;
112  "Segment retransmitted too many times");
113  }
114  else
115  {
116  // No delayed ACK involved here.
117  while (h.GetSequenceNumber () < m_sndNextExpSeq)
118  {
120  }
121 
122  if (h.GetSequenceNumber ().GetValue () != 50002)
123  {
125  "Sequence number expected differs");
126  }
127  }
128 
129  if (m_sndNextExpSeq.GetValue () == 0)
130  {
131  // SYN
133  }
134  else if (m_sndNextExpSeq.GetValue () == 1 && p->GetSize () == 32)
135  {
136  // Pure ACK in three-way handshake, then we expect data
138  }
139  else
140  {
141  // Data segments
143  }
144  }
145  else if (who == RECEIVER)
146  {
147  NS_LOG_INFO ("\tRECEIVER Tx, " << h << " size=" << p->GetSize ());
148 
149  if (h.GetFlags () == (TcpHeader::SYN | TcpHeader::ACK))
150  {
152  "SYN pkt has not 0 as initial sequence number."
153  "Probably, random sqn number has been implemented."
154  "Check this test");
155  }
156  else
157  {
159  "ACK pkt has not 1 as sequence number."
160  "Probably, random sqn number has been implemented."
161  "Check this test");
162  }
163 
164  // Accounted for delayed ACK, but not received.
165  while (h.GetAckNumber () < m_rcvNextExpAck)
166  {
168  }
169 
170  if (m_rcvNextExpAck.GetValue () == 50001)
171  {
172  m_rcvNextExpAck += 1;
173  }
174 
176  "ACKing something not considered");
177 
178  if (m_pktDropped)
179  {
181  }
182  else
183  {
184  switch (m_rcvNextExpAck.GetValue ())
185  {
186  case 0:
188  break;
189  case 1:
191  break;
192  default:
194 
195  // FIN seq
196  if (m_rcvNextExpAck.GetValue () == 50001)
197  {
198  m_rcvNextExpAck += 1;
199  }
200  else if (m_rcvNextExpAck.GetValue () > 50002)
201  {
202  m_rcvNextExpAck = 50002;
203  }
204  }
205  }
206  }
207 }
208 
209 void
211  SocketWho who)
212 {
213  NS_LOG_FUNCTION (this << tcb << h << who);
214 
215  if (who == SENDER)
216  {
217  if (h.GetAckNumber ().GetValue () < m_seqToKill)
218  {
220  "Not in OPEN state to respond to a loss");
222  "Dupack different than 0 but no loss detected");
223  }
224  else if (h.GetAckNumber ().GetValue () == m_seqToKill)
225  {
227  "Dupack count differs");
228 
229  if (GetDupAckCount(SENDER) == 0 &&
231  {
233  "Not in OPEN state for processing dupack");
234  }
235  else if (GetDupAckCount (SENDER) > 0 &&
237  {
239  "Not in DISORDER state after receiving dupacks");
240  }
242  {
244  "Not in RECOVERY state after reaching retxthresh");
245  }
246  }
247  }
248  else if (who == RECEIVER)
249  {
251  "Receiver not in OPEN state");
252  }
253 }
254 
255 void
257  SocketWho who)
258 {
259  NS_LOG_FUNCTION (this << tcb << h << who);
260 
261  if (who == SENDER)
262  {
263  if (m_previousAck == h.GetAckNumber () && h.GetAckNumber ().GetValue () < 50002)
264  {
266 
268  "Count of dupAck differs");
269 
271  {
273  "DupAck less than ReTxThreshold but not "
274  "in DISORDER state");
275  }
276  else
277  {
279  "DupAck greater than ReTxThreshold but not "
280  "in RECOVERY or LOSS state");
281  m_pktWasDropped = true;
282  }
283  }
284  else if (m_previousAck < h.GetAckNumber ())
285  {
286  m_dupAckReceived = 0;
287  }
288 
290  }
291  else if (who == RECEIVER)
292  {
294  "Different state than OPEN in the receiver");
295  }
296 }
297 
298 void
300 {
301  NS_ASSERT_MSG (true == false, "RTO isn't expected here");
302 }
303 
304 void
306  const TcpSocketState::TcpCongState_t newValue)
307 {
308  NS_LOG_FUNCTION (this << oldValue << newValue);
309 
310  if (oldValue == TcpSocketState::CA_OPEN && newValue == TcpSocketState::CA_DISORDER)
311  {
312  }
313  else if (oldValue == TcpSocketState::CA_OPEN
314  && newValue == TcpSocketState::CA_RECOVERY
315  && GetReTxThreshold (SENDER) > 1)
316  {
317  NS_TEST_ASSERT_MSG_EQ (true, false,
318  "Invalid OPEN to RECOVERY state change");
319  }
320  else if (oldValue == TcpSocketState::CA_DISORDER
321  && newValue == TcpSocketState::CA_RECOVERY)
322  {
324  "DISORDER to RECOVERY state change but not reached "
325  "the ReTxThreshold");
326  }
327 }
328 
329 
330 void
332 {
333  NS_LOG_FUNCTION (this << ipH << tcpH);
334 
335  m_pktDropped = true;
337 
339  "Packet dropped but sequence number differs");
340 }
341 
342 void
344 {
346  "Packet was not dropped at all");
348  "Segment was not retransmitted at all");
350  "Not all data have been transmitted");
351 }
352 
353 //-----------------------------------------------------------------------------
354 
355 static class TcpFastRetrTestSuite : public TestSuite
356 {
357 public:
358  TcpFastRetrTestSuite () : TestSuite ("tcp-fast-retr-test", UNIT)
359  {
360  std::list<TypeId> types;
361  types.insert (types.begin (), TcpWestwood::GetTypeId ());
362  types.insert (types.begin (), TcpNewReno::GetTypeId ());
363 
364  for (std::list<TypeId>::iterator it = types.begin (); it != types.end (); ++it)
365  {
366  AddTestCase (new TcpFastRetrTest ((*it), 5001, "Fast Retransmit testing"), TestCase::QUICK);
367  }
368  }
370 
371 } // namespace ns3
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:161
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:786
void PktDropped(const Ipv4Header &ipH, const TcpHeader &tcpH)
#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:31
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:297
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
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:1480
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.
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.
#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.
General infrastructure for TCP testing.
Ptr< TcpSeqErrorModel > m_errorModel
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.