A Discrete-Event Network Simulator
API
tcp-zero-window-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  */
18 
19 #include "tcp-error-model.h"
20 #include "tcp-general-test.h"
21 
22 #include "ns3/log.h"
23 #include "ns3/node.h"
24 
25 using namespace ns3;
26 
27 NS_LOG_COMPONENT_DEFINE("TcpZeroWindowTestSuite");
28 
35 {
36  public:
41  TcpZeroWindowTest(const std::string& desc);
42 
43  protected:
44  // virtual void ReceivePacket (Ptr<Socket> socket);
45  Ptr<TcpSocketMsgBase> CreateReceiverSocket(Ptr<Node> node) override;
46 
47  void Tx(const Ptr<const Packet> p, const TcpHeader& h, SocketWho who) override;
48  void Rx(const Ptr<const Packet> p, const TcpHeader& h, SocketWho who) override;
49  void ProcessedAck(const Ptr<const TcpSocketState> tcb,
50  const TcpHeader& h,
51  SocketWho who) override;
52  void NormalClose(SocketWho who) override;
53  void FinalChecks() override;
54 
55  void ConfigureEnvironment() override;
56  void ConfigureProperties() override;
57 
61  void IncreaseBufSize();
62 
63  protected:
69 };
70 
71 TcpZeroWindowTest::TcpZeroWindowTest(const std::string& desc)
72  : TcpGeneralTest(desc),
73  m_zeroWindowProbe(false),
74  m_windowUpdated(false),
75  m_senderFinished(false),
76  m_receiverFinished(false)
77 {
78 }
79 
80 void
82 {
83  TcpGeneralTest::ConfigureEnvironment();
84  SetAppPktCount(20);
85  SetMTU(500);
88 }
89 
90 void
92 {
93  TcpGeneralTest::ConfigureProperties();
95 }
96 
97 void
99 {
100  SetRcvBufSize(RECEIVER, 2500);
101 }
102 
105 {
106  Ptr<TcpSocketMsgBase> socket = TcpGeneralTest::CreateReceiverSocket(node);
107 
108  socket->SetAttribute("RcvBufSize", UintegerValue(0));
109  Simulator::Schedule(Seconds(10.0), &TcpZeroWindowTest::IncreaseBufSize, this);
110 
111  return socket;
112 }
113 
114 void
116 {
117  if (who == SENDER)
118  {
119  NS_LOG_INFO("\tSENDER TX " << h << " size " << p->GetSize());
120 
121  if (Simulator::Now().GetSeconds() <= 6.0)
122  {
123  NS_TEST_ASSERT_MSG_EQ(p->GetSize(), 0, "Data packet sent anyway");
124  }
125  else if (Simulator::Now().GetSeconds() > 6.0 && Simulator::Now().GetSeconds() <= 7.0)
126  {
127  NS_TEST_ASSERT_MSG_EQ(m_zeroWindowProbe, false, "Sent another probe");
128 
129  if (!m_zeroWindowProbe)
130  {
131  NS_TEST_ASSERT_MSG_EQ(p->GetSize(), 1, "Data packet sent instead of window probe");
133  SequenceNumber32(1),
134  "Data packet sent instead of window probe");
135  m_zeroWindowProbe = true;
136  }
137  }
138  else if (Simulator::Now().GetSeconds() > 7.0 && Simulator::Now().GetSeconds() < 10.0)
139  {
140  NS_FATAL_ERROR("No packets should be sent before the window update");
141  }
142  }
143  else if (who == RECEIVER)
144  {
145  NS_LOG_INFO("\tRECEIVER TX " << h << " size " << p->GetSize());
146 
147  if (h.GetFlags() & TcpHeader::SYN)
148  {
150  0,
151  "RECEIVER window size is not 0 in the SYN-ACK");
152  }
153 
154  if (Simulator::Now().GetSeconds() > 6.0 && Simulator::Now().GetSeconds() <= 7.0)
155  {
157  SequenceNumber32(1),
158  "Data packet sent instead of window probe");
159  NS_TEST_ASSERT_MSG_EQ(h.GetWindowSize(), 0, "No zero window advertised by RECEIVER");
160  }
161  else if (Simulator::Now().GetSeconds() > 7.0 && Simulator::Now().GetSeconds() < 10.0)
162  {
163  NS_FATAL_ERROR("No packets should be sent before the window update");
164  }
165  else if (Simulator::Now().GetSeconds() >= 10.0)
166  {
167  NS_TEST_ASSERT_MSG_EQ(h.GetWindowSize(), 2500, "Receiver window not updated");
168  }
169  }
170 
171  NS_TEST_ASSERT_MSG_EQ(GetTcb(SENDER)->m_congState.Get(),
172  TcpSocketState::CA_OPEN,
173  "Sender State is not OPEN");
174  NS_TEST_ASSERT_MSG_EQ(GetTcb(RECEIVER)->m_congState.Get(),
175  TcpSocketState::CA_OPEN,
176  "Receiver State is not OPEN");
177 }
178 
179 void
181 {
182  if (who == SENDER)
183  {
184  NS_LOG_INFO("\tSENDER RX " << h << " size " << p->GetSize());
185 
186  if (h.GetFlags() & TcpHeader::SYN)
187  {
189  0,
190  "RECEIVER window size is not 0 in the SYN-ACK");
191  }
192 
193  if (Simulator::Now().GetSeconds() >= 10.0)
194  {
195  NS_TEST_ASSERT_MSG_EQ(h.GetWindowSize(), 2500, "Receiver window not updated");
196  m_windowUpdated = true;
197  }
198  }
199  else if (who == RECEIVER)
200  {
201  NS_LOG_INFO("\tRECEIVER RX " << h << " size " << p->GetSize());
202  }
203 }
204 
205 void
207 {
208  if (who == SENDER)
209  {
210  m_senderFinished = true;
211  }
212  else if (who == RECEIVER)
213  {
214  m_receiverFinished = true;
215  }
216 }
217 
218 void
220 {
221  NS_TEST_ASSERT_MSG_EQ(m_zeroWindowProbe, true, "Zero window probe not sent");
222  NS_TEST_ASSERT_MSG_EQ(m_windowUpdated, true, "Window has not updated during the connection");
223  NS_TEST_ASSERT_MSG_EQ(m_senderFinished, true, "Connection not closed successfully (SENDER)");
225  true,
226  "Connection not closed successfully (RECEIVER)");
227 }
228 
229 void
231  const TcpHeader& h,
232  SocketWho who)
233 {
234  if (who == SENDER)
235  {
236  if (h.GetFlags() & TcpHeader::SYN)
237  {
238  EventId persistentEvent = GetPersistentEvent(SENDER);
239  NS_TEST_ASSERT_MSG_EQ(persistentEvent.IsRunning(),
240  true,
241  "Persistent event not started");
242  }
243  }
244  else if (who == RECEIVER)
245  {
246  }
247 }
248 
255 {
256  public:
258  : TestSuite("tcp-zero-window-test", UNIT)
259  {
260  AddTestCase(new TcpZeroWindowTest("zero window test"), TestCase::QUICK);
261  }
262 };
263 
Testing the congestion avoidance increment on TCP ZeroWindow.
void ConfigureEnvironment() override
Change the configuration of the environment.
void FinalChecks() override
Performs the (eventual) final checks through test asserts.
void NormalClose(SocketWho who) override
bool m_windowUpdated
Window updated.
void ProcessedAck(const Ptr< const TcpSocketState > tcb, const TcpHeader &h, SocketWho who) override
bool m_senderFinished
Send finished.
bool m_receiverFinished
Receiver finished.
Ptr< TcpSocketMsgBase > CreateReceiverSocket(Ptr< Node > node) override
Create and install the socket to install on the receiver.
void IncreaseBufSize()
Increase the receiver buffer size.
void Rx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who) override
Packet received from IP layer.
void Tx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who) override
Packet transmitted down to IP layer.
bool m_zeroWindowProbe
ZeroWindow probe.
TcpZeroWindowTest(const std::string &desc)
Constructor.
EventId m_receivePktEvent
Receive packet event.
void ConfigureProperties() override
Change the configuration of the socket properties.
TCP ZeroWindow TestSuite.
An identifier for simulation events.
Definition: event-id.h:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
General infrastructure for TCP testing.
void SetPropagationDelay(Time propDelay)
Propagation delay of the bottleneck link.
void SetAppPktCount(uint32_t pktCount)
Set app packet count.
SocketWho
Used as parameter of methods, specifies on what node the caller is interested (e.g.
@ RECEIVER
Receiver node.
Ptr< TcpSocketState > GetTcb(SocketWho who)
Get the TCB from selected socket.
void SetRcvBufSize(SocketWho who, uint32_t size)
Forcefully set a defined size for rx buffer.
EventId GetPersistentEvent(SocketWho who)
Get the persistent event of the selected socket.
void SetInitialCwnd(SocketWho who, uint32_t initialCwnd)
Forcefully set the initial cwnd.
void SetMTU(uint32_t mtu)
MTU of the bottleneck link.
void SetTransmitStart(Time startTime)
Set the initial time at which the application sends the first data packet.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:47
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:118
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:154
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:148
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
@ UNIT
This test suite implements a Unit Test.
Definition: test.h:1265
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
#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:144
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static TcpZeroWindowTestSuite g_tcpZeroWindowTestSuite
Static variable for test initialization.