View | Details | Raw Unified | Return to bug 647
Collapse All | Expand All

(-)a/src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc (-9 / +211 lines)
 Lines 27-32    Link Here 
27
#include "ns3/inet-socket-address.h"
27
#include "ns3/inet-socket-address.h"
28
#include "ns3/point-to-point-helper.h"
28
#include "ns3/point-to-point-helper.h"
29
#include "ns3/internet-stack-helper.h"
29
#include "ns3/internet-stack-helper.h"
30
#include "ns3/ipv4-global-routing-helper.h"
30
#include "ns3/ipv4-address-helper.h"
31
#include "ns3/ipv4-address-helper.h"
31
#include "ns3/packet-sink-helper.h"
32
#include "ns3/packet-sink-helper.h"
32
#include "ns3/tcp-socket-factory.h"
33
#include "ns3/tcp-socket-factory.h"
 Lines 172-182   SimpleSource::ScheduleTx (void) Link Here 
172
    }
173
    }
173
}
174
}
174
175
175
class Ns3TcpCwndTestCase : public TestCase
176
class Ns3TcpCwndTestCase1 : public TestCase
176
{
177
{
177
public:
178
public:
178
  Ns3TcpCwndTestCase ();
179
  Ns3TcpCwndTestCase1 ();
179
  virtual ~Ns3TcpCwndTestCase ();
180
  virtual ~Ns3TcpCwndTestCase1 ();
180
181
181
private:
182
private:
182
  virtual bool DoRun (void);
183
  virtual bool DoRun (void);
 Lines 193-210   private: Link Here 
193
  void CwndChange (uint32_t oldCwnd, uint32_t newCwnd);
194
  void CwndChange (uint32_t oldCwnd, uint32_t newCwnd);
194
};
195
};
195
196
196
Ns3TcpCwndTestCase::Ns3TcpCwndTestCase ()
197
Ns3TcpCwndTestCase1::Ns3TcpCwndTestCase1 ()
197
  : TestCase ("Check to see that the ns-3 TCP congestion window works as expected against liblinux2.6.26.so"),
198
  : TestCase ("Check to see that the ns-3 TCP congestion window works as expected against liblinux2.6.26.so"),
198
    m_writeResults (false)
199
    m_writeResults (false)
199
{
200
{
200
}
201
}
201
202
202
Ns3TcpCwndTestCase::~Ns3TcpCwndTestCase ()
203
Ns3TcpCwndTestCase1::~Ns3TcpCwndTestCase1 ()
203
{
204
{
204
}
205
}
205
206
206
void
207
void
207
Ns3TcpCwndTestCase::CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
208
Ns3TcpCwndTestCase1::CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
208
{
209
{
209
  CwndEvent event;
210
  CwndEvent event;
210
211
 Lines 215-221   Ns3TcpCwndTestCase::CwndChange (uint32_t Link Here 
215
}
216
}
216
217
217
bool
218
bool
218
Ns3TcpCwndTestCase::DoRun (void)
219
Ns3TcpCwndTestCase1::DoRun (void)
219
{
220
{
220
  //
221
  //
221
  // Just create two nodes.  One (node zero) will be the node with the TCP
222
  // Just create two nodes.  One (node zero) will be the node with the TCP
 Lines 297-303   Ns3TcpCwndTestCase::DoRun (void) Link Here 
297
  // in the node with the ns-3 TCP.
298
  // in the node with the ns-3 TCP.
298
  //
299
  //
299
  Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
300
  Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
300
  ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&Ns3TcpCwndTestCase::CwndChange, this));
301
  ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&Ns3TcpCwndTestCase1::CwndChange, this));
301
302
302
  Ptr<SimpleSource> app = CreateObject<SimpleSource> ();
303
  Ptr<SimpleSource> app = CreateObject<SimpleSource> ();
303
  app->Setup (ns3TcpSocket, sinkAddress, 1040, 10, DataRate ("5Mbps"));
304
  app->Setup (ns3TcpSocket, sinkAddress, 1040, 10, DataRate ("5Mbps"));
 Lines 366-371   Ns3TcpCwndTestCase::DoRun (void) Link Here 
366
  return GetErrorStatus ();
367
  return GetErrorStatus ();
367
}
368
}
368
369
370
371
// ===========================================================================
372
// Test case for cwnd changes due to out-of-order packets. A bottleneck 
373
// link is created, and a limited droptail queue is used in order to 
374
// force dropped packets, resulting in out-of-order packet delivery. 
375
// This out-of-order delivery will result in a different congestion 
376
// window behavior than testcase 1.  Specifically, duplicate ACKs
377
// are encountered.
378
//
379
// Network topology
380
//
381
//        1Mb/s, 10ms      100kb/s, 10ms     1Mb/s, 10ms
382
//    n0--------------n1-----------------n2---------------n3
383
//
384
// ===========================================================================
385
class Ns3TcpCwndTestCase2 : public TestCase
386
{
387
public:
388
  Ns3TcpCwndTestCase2 ();
389
  virtual ~Ns3TcpCwndTestCase2 ();
390
391
private:
392
  virtual bool DoRun (void);
393
  bool m_writeResults;
394
395
  class  CwndEvent {
396
  public:
397
    uint32_t m_oldCwnd;
398
    uint32_t m_newCwnd;
399
  };
400
401
  TestVectors<CwndEvent> m_responses;
402
403
  void CwndChange (uint32_t oldCwnd, uint32_t newCwnd);
404
};
405
406
Ns3TcpCwndTestCase2::Ns3TcpCwndTestCase2 ()
407
  : TestCase ("Check to see that the ns-3 TCP congestion window works as expected for out-of-order packet delivery"),
408
    m_writeResults (false)
409
{
410
}
411
412
Ns3TcpCwndTestCase2::~Ns3TcpCwndTestCase2 ()
413
{
414
}
415
416
void
417
Ns3TcpCwndTestCase2::CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
418
{
419
  CwndEvent event;
420
421
  event.m_oldCwnd = oldCwnd;
422
  event.m_newCwnd = newCwnd;
423
424
  m_responses.Add (event);
425
}
426
427
bool
428
Ns3TcpCwndTestCase2::DoRun (void)
429
{
430
  // Set up some default values for the simulation.
431
  Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (4));
432
433
  // Here, we will explicitly create three nodes.  The first container contains
434
  // nodes 0 and 1 from the diagram above, and the second one contains nodes
435
  // 1 and 2.  This reflects the channel connectivity, and will be used to
436
  // install the network interfaces and connect them with a channel.
437
  NodeContainer n0n1;
438
  n0n1.Create (2);
439
440
  NodeContainer n1n2;
441
  n1n2.Add (n0n1.Get (1));
442
  n1n2.Create (1);
443
444
  NodeContainer n2n3;
445
  n2n3.Add (n1n2.Get (1));
446
  n2n3.Create (1);
447
448
  // We create the channels first without any IP addressing information
449
  // First make and configure the helper, so that it will put the appropriate
450
  // attributes on the network interfaces and channels we are about to install.
451
  PointToPointHelper p2p1;
452
  p2p1.SetDeviceAttribute ("DataRate", DataRateValue (DataRate(1000000)));
453
  p2p1.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(10)));
454
  PointToPointHelper p2p2;
455
  p2p2.SetDeviceAttribute ("DataRate", DataRateValue (DataRate(100000)));
456
  p2p2.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(10)));
457
458
  // And then install devices and channels connecting our topology.
459
  NetDeviceContainer dev0 = p2p1.Install (n0n1);
460
  NetDeviceContainer dev1 = p2p2.Install (n1n2);
461
  NetDeviceContainer dev2 = p2p1.Install (n2n3);
462
463
  // Now add ip/tcp stack to all nodes.
464
  InternetStackHelper internet;
465
  internet.InstallAll ();
466
467
  // Later, we add IP addresses.
468
  Ipv4AddressHelper ipv4;
469
  ipv4.SetBase ("10.1.3.0", "255.255.255.0");
470
  ipv4.Assign (dev0);
471
  ipv4.SetBase ("10.1.2.0", "255.255.255.0");
472
  ipv4.Assign (dev1);
473
  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
474
  Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev2);
475
476
  // and setup ip routing tables to get total ip-level connectivity.
477
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
478
479
  // Set up the apps
480
  uint16_t servPort = 50000;
481
482
  // Create a packet sink to receive these packets on n3
483
  PacketSinkHelper sink ("ns3::TcpSocketFactory",
484
                         InetSocketAddress (Ipv4Address::GetAny (), servPort));
485
486
  ApplicationContainer apps = sink.Install (n2n3.Get (1));
487
  apps.Start (Seconds (0.0));
488
  apps.Stop (Seconds (5.4));
489
490
  Address sinkAddress (InetSocketAddress(ipInterfs.GetAddress (1), servPort));
491
  Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (n0n1.Get (0), TcpSocketFactory::GetTypeId ());
492
  ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&Ns3TcpCwndTestCase2::CwndChange, this));
493
494
  Ptr<SimpleSource> app = CreateObject<SimpleSource> ();
495
  app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
496
  n0n1.Get (0)->AddApplication (app);
497
  app->Start (Seconds (1.0));
498
  app->Stop (Seconds (5.4));
499
500
  if (m_writeResults)
501
    {
502
      // Write a pcap for tcp cwnd testcase with out-of-order delivery
503
      PointToPointHelper::EnablePcapAll ("tcp-cwnd-ood");
504
    }
505
506
  // Finally, set up the simulator to run.
507
  Simulator::Stop (Seconds(5.4));
508
  Simulator::Run ();
509
  Simulator::Destroy ();
510
511
  //
512
  // As new acks are received by the TCP under test, the congestion window 
513
  // should be opened up by one segment (MSS bytes) each time.  This should
514
  // trigger a congestion window change event which we hooked and saved above.
515
  // We should now be able to look through the saved response vectors and follow
516
  // the congestion window as it opens up when the ns-3 TCP under test 
517
  // transmits its bits
518
  //
519
  // From inspecting the results, we know that we should see 31 congestion
520
  // window change events. On the tenth change event, the window should go back 
521
  // to one segment due to 3 dup acks.  It should then slow start again for 
522
  // 4 events and then enter congestion avoidance.  On change event 30 
523
  // (29 zero-based indexing), it should go back to one segment, because of triple dup ack.
524
  //
525
  const uint32_t MSS = 536;
526
527
  CwndEvent event;
528
529
  NS_TEST_ASSERT_MSG_EQ (m_responses.GetN (), 31, "Unexpected number of cwnd change events");
530
531
  for (uint32_t i = 0, from = 536, to = 1072; i < 9; ++i, from += 536, to += 536)
532
    {
533
      event = m_responses.Get (i);
534
      NS_TEST_ASSERT_MSG_EQ (event.m_oldCwnd, from, "Wrong old cwnd value in cwnd change event " << i);
535
      NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, to, "Wrong new cwnd value in cwnd change event " << i);
536
    }
537
538
  // Cwnd should be back to 536
539
  event = m_responses.Get (9);
540
  NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, MSS, "Wrong new cwnd value in cwnd change event " << 9);
541
542
  // Another round of slow start
543
  for (uint32_t i = 10, from = 536, to = 1072; i < 14; ++i, from += 536, to += 536)
544
    {
545
      event = m_responses.Get (i);
546
      NS_TEST_ASSERT_MSG_EQ (event.m_oldCwnd, from, "Wrong old cwnd value in cwnd change event " << i);
547
      NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, to, "Wrong new cwnd value in cwnd change event " << i);
548
    }
549
550
  // Congestion Avoidance
551
  double adder; 
552
  uint32_t from = 2680;
553
  for (uint32_t i = 14;  i < 29; ++i)
554
    {
555
      event = m_responses.Get (i);
556
      NS_TEST_ASSERT_MSG_EQ (event.m_oldCwnd, from, "Wrong old cwnd value in cwnd change event " << i);
557
      adder = ((double) MSS * MSS) / event.m_oldCwnd;
558
      adder += event.m_oldCwnd;
559
      from = adder;
560
      NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, (uint32_t)adder, "Wrong new cwnd value in cwnd change event " << i);
561
    }
562
563
  // Cwnd should be back to 536
564
  event = m_responses.Get (29);
565
  NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, MSS, "Wrong new cwnd value in cwnd change event " << 29);
566
567
  return GetErrorStatus ();
568
}
569
369
class Ns3TcpCwndTestSuite : public TestSuite
570
class Ns3TcpCwndTestSuite : public TestSuite
370
{
571
{
371
public:
572
public:
 Lines 375-381   Ns3TcpCwndTestSuite::Ns3TcpCwndTestSuite Link Here 
375
Ns3TcpCwndTestSuite::Ns3TcpCwndTestSuite ()
576
Ns3TcpCwndTestSuite::Ns3TcpCwndTestSuite ()
376
  : TestSuite ("ns3-tcp-cwnd", SYSTEM)
577
  : TestSuite ("ns3-tcp-cwnd", SYSTEM)
377
{
578
{
378
  AddTestCase (new Ns3TcpCwndTestCase);
579
  AddTestCase (new Ns3TcpCwndTestCase1);
580
  AddTestCase (new Ns3TcpCwndTestCase2);
379
}
581
}
380
582
381
Ns3TcpCwndTestSuite ns3TcpCwndTestSuite;
583
Ns3TcpCwndTestSuite ns3TcpCwndTestSuite;

Return to bug 647