A Discrete-Event Network Simulator
API
tcp-wscaling-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 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 
20 #include "ns3/test.h"
21 
22 #define private public
23 #define protected public
24 
25 #include "ns3/socket-factory.h"
26 #include "ns3/tcp-socket-factory.h"
27 #include "ns3/simulator.h"
28 #include "ns3/simple-channel.h"
29 #include "ns3/simple-net-device.h"
30 #include "ns3/drop-tail-queue.h"
31 #include "ns3/config.h"
32 #include "ns3/ipv4-static-routing.h"
33 #include "ns3/ipv4-list-routing.h"
34 #include "ns3/ipv6-static-routing.h"
35 #include "ns3/ipv6-list-routing.h"
36 #include "ns3/node.h"
37 #include "ns3/inet-socket-address.h"
38 #include "ns3/inet6-socket-address.h"
39 #include "ns3/uinteger.h"
40 #include "ns3/log.h"
41 
42 #include "ns3/arp-l3-protocol.h"
43 #include "ns3/ipv4-l3-protocol.h"
44 #include "ns3/ipv6-l3-protocol.h"
45 #include "ns3/icmpv4-l4-protocol.h"
46 #include "ns3/icmpv6-l4-protocol.h"
47 #include "ns3/udp-l4-protocol.h"
48 #include "ns3/tcp-l4-protocol.h"
49 
50 #include "ns3/tcp-socket-base.h"
51 
52 namespace ns3 {
53 
54 NS_LOG_COMPONENT_DEFINE ("WScalingTestSuite");
55 
56 class WScalingTestCase : public TestCase
57 {
58 public:
60  {
65  };
66 
68  uint32_t maxServerBufferSize,
69  uint32_t maxSourceBufferSize, std::string name);
70 
71 private:
72  virtual void DoRun (void);
73  virtual void DoTeardown (void);
74 
75  void SetupDefaultSim (void);
76  //void SetupDefaultSim6 (void);
77 
80 
81  Ptr<SimpleNetDevice> AddSimpleNetDevice (Ptr<Node> node, const char* ipaddr, const char* netmask);
83 
84  void ServerHandleConnectionCreated (Ptr<Socket> s, const Address & addr);
86  void ServerHandleRecv (Ptr<Socket> sock);
87  void ServerHandleSend (Ptr<Socket> sock, uint32_t sendB);
88  void SourceHandleSend (Ptr<Socket> sock, uint32_t available);
89  void SourceHandleRecv (Ptr<Socket> sock);
90 
92 
93  uint32_t m_totalBytes;
95  uint32_t m_sourceReadSize;
97  uint32_t m_serverReadSize;
102 
105 
108 };
109 
111  uint32_t maxServerBufferSize,
112  uint32_t maxSourceBufferSize, std::string name)
113  : TestCase (name)
114 {
115  m_configuration = conf;
116  m_totalBytes = 2000;
117  m_sourceWriteSize = 500;
118  m_sourceReadSize = 500;
119  m_serverWriteSize = 500;
120  m_serverReadSize = 500;
121 
122  m_maxServerBufferSize = maxServerBufferSize;
123  m_maxSourceBufferSize = maxSourceBufferSize;
124 }
125 
126 void
128 {
133 
134 
135 // if (m_useIpv6 == true)
136 // {
137 // SetupDefaultSim6 ();
138 // }
139 // else
140 // {
141  SetupDefaultSim ();
142 // }
143 
144  Simulator::Run ();
145 
147  m_totalBytes,
148  "Source sent all bytes");
149 
151  m_totalBytes,
152  "Server received all bytes");
153 
155  m_totalBytes,
156  "Source received all bytes");
157 }
158 
159 void
161 {
163 }
164 
165 void
167  const Address & addr)
168 {
171 
172  Ptr<TcpSocketBase> b = DynamicCast <TcpSocketBase> (s);
173 
174  if (m_configuration == ENABLED)
175  {
176  NS_TEST_EXPECT_MSG_EQ ((b->m_rWnd.Get ()), m_maxSourceBufferSize,
177  "Miscalculating source window");
178 
179  NS_TEST_EXPECT_MSG_LT_OR_EQ ((b->m_rWnd.Get () >> b->m_rcvScaleFactor),
180  b->m_maxWinSize, "Violating maximum adv window");
181 
182  NS_TEST_EXPECT_MSG_LT_OR_EQ (b->m_rcvScaleFactor, 14,
183  "Violating RFC for max value of the scale factor");
184  }
185  else
186  {
187  NS_TEST_EXPECT_MSG_EQ (b->m_rcvScaleFactor, 0, "Using Window scale while disabled");
188  NS_TEST_EXPECT_MSG_EQ (b->m_sndScaleFactor, 0, "Using Window scale while disabled");
189  NS_TEST_EXPECT_MSG_LT_OR_EQ (b->m_rWnd.Get (), m_source->m_maxWinSize, "Violating max adv window");
190  }
191 }
192 
193 void
195 {
196  while (sock->GetRxAvailable () > 0)
197  {
198  uint32_t toRead = std::min (m_serverReadSize, sock->GetRxAvailable ());
199  Ptr<Packet> p = sock->Recv (toRead, 0);
200 
201  if (p == 0 && sock->GetErrno () != Socket::ERROR_NOTERROR)
202  {
203  NS_FATAL_ERROR ("Server could not read stream at byte " << m_currentServerRxBytes);
204  }
205 
206  m_currentServerRxBytes += p->GetSize ();
207 
208  ServerHandleSend (sock, sock->GetTxAvailable ());
209  }
210 }
211 
212 void
214 {
215  Ptr<TcpSocketBase> b = DynamicCast <TcpSocketBase> (sock);
216 
217  if (m_configuration == ENABLED)
218  {
219  NS_TEST_EXPECT_MSG_EQ ((b->m_rWnd.Get ()), m_maxServerBufferSize,
220  "Miscalculating server window " << (int)b->m_rcvScaleFactor);
221 
222  NS_TEST_EXPECT_MSG_LT_OR_EQ ((b->m_rWnd.Get () >> b->m_rcvScaleFactor),
223  b->m_maxWinSize, "Violating maximum adv window");
224 
225  NS_TEST_EXPECT_MSG_LT_OR_EQ (b->m_rcvScaleFactor, 14,
226  "Violating RFC for max value of the scale factor");
227  }
228  else
229  {
230  NS_TEST_EXPECT_MSG_EQ (b->m_rcvScaleFactor, 0, "Using Window scale while disabled");
231  NS_TEST_EXPECT_MSG_EQ (b->m_sndScaleFactor, 0, "Using Window scale while disabled");
232  NS_TEST_EXPECT_MSG_LT_OR_EQ (b->m_rWnd.Get (), m_server->m_maxWinSize, "Violating max adv window");
233  }
234 }
235 
236 void
238 {
240  {
242  uint32_t toSend = std::min (left, sock->GetTxAvailable ());
243  toSend = std::min (toSend, m_serverWriteSize);
244 
245  Ptr<Packet> p = Create<Packet> (toSend);
246 
247  int sent = sock->Send (p);
248 
249  NS_TEST_EXPECT_MSG_EQ ((sent != -1), true, "Server error during send ?");
250 
251  m_currentServerTxBytes += sent;
252  }
253 
255  {
256  sock->Close ();
257  }
258 }
259 
260 void
262 {
263  while (sock->GetTxAvailable () > 0 && m_currentSourceTxBytes < m_totalBytes)
264  {
265  uint32_t left = m_totalBytes - m_currentSourceTxBytes;
266  uint32_t toSend = std::min (left, sock->GetTxAvailable ());
267  toSend = std::min (toSend, m_sourceWriteSize);
268 
269  Ptr<Packet> p = Create<Packet> (toSend);
270 
271  int sent = sock->Send (p);
272  NS_TEST_EXPECT_MSG_EQ ((sent != -1), true, "Error during send ?");
273  m_currentSourceTxBytes += sent;
274  }
275 }
276 
277 void
279 {
280  while (sock->GetRxAvailable () > 0 && m_currentSourceRxBytes < m_totalBytes)
281  {
282  uint32_t toRead = std::min (m_sourceReadSize, sock->GetRxAvailable ());
283  Ptr<Packet> p = sock->Recv (toRead, 0);
284 
285  if (p == 0 && sock->GetErrno () != Socket::ERROR_NOTERROR)
286  {
287  NS_FATAL_ERROR ("Source could not read stream at byte " << m_currentSourceRxBytes);
288  }
289 
290  m_currentSourceRxBytes += p->GetSize ();
291  }
292 
294  {
295  sock->Close ();
296  }
297 }
298 
299 Ptr<Node>
301 {
302  Ptr<Node> node = CreateObject<Node> ();
303  //ARP
304  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
305  node->AggregateObject (arp);
306  //IPV4
307  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
308  //Routing for Ipv4
309  Ptr<Ipv4ListRouting> ipv4Routing = CreateObject<Ipv4ListRouting> ();
310  ipv4->SetRoutingProtocol (ipv4Routing);
311  Ptr<Ipv4StaticRouting> ipv4staticRouting = CreateObject<Ipv4StaticRouting> ();
312  ipv4Routing->AddRoutingProtocol (ipv4staticRouting, 0);
313  node->AggregateObject (ipv4);
314  //ICMP
315  Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
316  node->AggregateObject (icmp);
317  //UDP
318  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
319  node->AggregateObject (udp);
320  //TCP
321  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
322  node->AggregateObject (tcp);
323  return node;
324 }
325 
327 WScalingTestCase::AddSimpleNetDevice (Ptr<Node> node, const char* ipaddr, const char* netmask)
328 {
329  Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
330  dev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
331  node->AddDevice (dev);
332  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
333  uint32_t ndid = ipv4->AddInterface (dev);
334  Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address (ipaddr), Ipv4Mask (netmask));
335  ipv4->AddAddress (ndid, ipv4Addr);
336  ipv4->SetUp (ndid);
337  return dev;
338 }
339 
340 void
342 {
343  const char* netmask = "255.255.255.0";
344  const char* ipaddr0 = "192.168.1.1";
345  const char* ipaddr1 = "192.168.1.2";
346  Ptr<Node> node0 = CreateInternetNode ();
347  Ptr<Node> node1 = CreateInternetNode ();
348  Ptr<SimpleNetDevice> dev0 = AddSimpleNetDevice (node0, ipaddr0, netmask);
349  Ptr<SimpleNetDevice> dev1 = AddSimpleNetDevice (node1, ipaddr1, netmask);
350 
351  Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
352  dev0->SetChannel (channel);
353  dev1->SetChannel (channel);
354 
355  Ptr<SocketFactory> sockFactory0 = node0->GetObject<TcpSocketFactory> ();
356  Ptr<SocketFactory> sockFactory1 = node1->GetObject<TcpSocketFactory> ();
357 
358  m_server = DynamicCast<TcpSocketBase> (sockFactory0->CreateSocket ());
359  m_source = DynamicCast<TcpSocketBase> (sockFactory1->CreateSocket ());
360 
361  NS_ASSERT (m_server != 0);
362  NS_ASSERT (m_source != 0);
363 
364  switch (m_configuration)
365  {
366  case DISABLED:
367  m_server->SetAttribute ("WindowScaling", BooleanValue (false));
368  m_source->SetAttribute ("WindowScaling", BooleanValue (false));
369  break;
370 
371  case ENABLED_CLIENT:
372  m_server->SetAttribute ("WindowScaling", BooleanValue (false));
373  m_source->SetAttribute ("WindowScaling", BooleanValue (true));
374  break;
375 
376  case ENABLED_SERVER:
377  m_server->SetAttribute ("WindowScaling", BooleanValue (true));
378  m_source->SetAttribute ("WindowScaling", BooleanValue (false));
379  break;
380 
381  case ENABLED:
382  m_server->SetAttribute ("WindowScaling", BooleanValue (true));
383  m_source->SetAttribute ("WindowScaling", BooleanValue (true));
384  break;
385  }
386 
387  m_server->m_rxBuffer->SetMaxBufferSize (m_maxServerBufferSize);
388  m_source->m_rxBuffer->SetMaxBufferSize (m_maxSourceBufferSize);
389 
390  uint16_t port = 50000;
391  InetSocketAddress serverlocaladdr (Ipv4Address::GetAny (), port);
392  InetSocketAddress serverremoteaddr (Ipv4Address (ipaddr0), port);
393 
394  m_server->Bind (serverlocaladdr);
395  m_server->Listen ();
396  m_server->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
398 
399  m_source->SetRecvCallback (MakeCallback (&WScalingTestCase::SourceHandleRecv, this));
400  m_source->SetSendCallback (MakeCallback (&WScalingTestCase::SourceHandleSend, this));
401  m_source->SetConnectCallback (MakeCallback (&WScalingTestCase::SourceHandleConnectionCreated, this),
402  MakeNullCallback<void, Ptr<Socket> > ());
403 
404  m_source->Connect (serverremoteaddr);
405 }
406 
407 static class TcpWScalingTestSuite : public TestSuite
408 {
409 public:
411  : TestSuite ("tcp-wscaling", UNIT)
412  {
413  AddTestCase (new WScalingTestCase (WScalingTestCase::ENABLED, 200000, 65535, "WS only server"), TestCase::QUICK);
414  AddTestCase (new WScalingTestCase (WScalingTestCase::ENABLED, 65535, 65535, "Window scaling not used, all enabled"), TestCase::QUICK);
415  AddTestCase (new WScalingTestCase (WScalingTestCase::DISABLED, 65535, 65535, "WS disabled"), TestCase::QUICK);
416  AddTestCase (new WScalingTestCase (WScalingTestCase::ENABLED_CLIENT, 65535, 65535, "WS enabled client"), TestCase::QUICK);
417  AddTestCase (new WScalingTestCase (WScalingTestCase::ENABLED_SERVER, 65535, 65535, "WS disabled client"), TestCase::QUICK);
418 
419  AddTestCase (new WScalingTestCase (WScalingTestCase::ENABLED, 65535, 200000, "WS only client"), TestCase::QUICK);
420  AddTestCase (new WScalingTestCase (WScalingTestCase::ENABLED, 131072, 65535, "WS only server"), TestCase::QUICK);
421  AddTestCase (new WScalingTestCase (WScalingTestCase::ENABLED, 65535, 131072, "WS only client"), TestCase::QUICK);
422  }
423 
425 
426 } // namespace ns3
427 
tuple channel
Definition: third.py:85
Ptr< TcpSocketBase > m_server
an Inet address class
static Ipv4Address GetAny(void)
AttributeValue implementation for Boolean.
Definition: boolean.h:34
void ServerHandleConnectionCreated(Ptr< Socket > s, const Address &addr)
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:455
API to create TCP socket instances.
void SourceHandleSend(Ptr< Socket > sock, uint32_t available)
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:226
Fast test.
Definition: test.h:1152
A suite of tests to run.
Definition: test.h:1333
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:246
Ptr< SimpleNetDevice > AddSimpleNetDevice6(Ptr< Node > node, Ipv6Address ipaddr, Ipv6Prefix prefix)
#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
static void Run(void)
Run the simulation.
Definition: simulator.cc:200
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
ns3::TcpWScalingTestSuite g_tcpWScalingTestSuite
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:278
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:145
Callback< R > MakeNullCallback(void)
Definition: callback.h:1626
Definition: conf.py:1
encapsulates test code
Definition: test.h:1147
This test suite implements a Unit Test.
Definition: test.h:1343
virtual enum Socket::SocketErrno GetErrno(void) const =0
Get last error number.
uint16_t port
Definition: dsdv-manet.cc:44
a polymophic address class
Definition: address.h:90
Configuration m_configuration
static Mac48Address Allocate(void)
Allocate a new Mac48Address.
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:297
Ptr< Node > CreateInternetNode6(void)
Ptr< Node > CreateInternetNode(void)
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1480
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
void SourceHandleConnectionCreated(Ptr< Socket > sock)
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:164
static Mac48Address ConvertFrom(const Address &address)
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
Ptr< TcpSocketBase > m_source
Ptr< SimpleNetDevice > AddSimpleNetDevice(Ptr< Node > node, const char *ipaddr, const char *netmask)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
void ServerHandleSend(Ptr< Socket > sock, uint32_t sendB)
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:121
Describes an IPv6 address.
Definition: ipv6-address.h:47
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:121
a class to store IPv4 address information on an interface
virtual void DoRun(void)
Implementation to actually run this TestCase.
WScalingTestCase(WScalingTestCase::Configuration conf, uint32_t maxServerBufferSize, uint32_t maxSourceBufferSize, std::string name)
Describes an IPv6 prefix.
Definition: ipv6-address.h:389
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual int Close(void)=0
Close a socket.
virtual uint32_t GetTxAvailable(void) const =0
Returns the number of bytes which can be sent in a single call to Send.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:191
void SourceHandleRecv(Ptr< Socket > sock)
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report if not.
Definition: test.h:917
void ServerHandleRecv(Ptr< Socket > sock)
virtual uint32_t GetRxAvailable(void) const =0
Return number of bytes which can be returned from one or multiple calls to Recv.