A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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
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
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
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.
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
Fast test.
Definition: test.h:1152
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.
This test suite implements a Unit Test.
Definition: test.h:1343
#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.