|
|
| 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); |
|
|
| 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 |
NodeContainer n0n1; |
| 434 |
n0n1.Create (2); |
| 435 |
|
| 436 |
NodeContainer n1n2; |
| 437 |
n1n2.Add (n0n1.Get (1)); |
| 438 |
n1n2.Create (1); |
| 439 |
|
| 440 |
NodeContainer n2n3; |
| 441 |
n2n3.Add (n1n2.Get (1)); |
| 442 |
n2n3.Create (1); |
| 443 |
|
| 444 |
PointToPointHelper p2p1; |
| 445 |
p2p1.SetDeviceAttribute ("DataRate", DataRateValue (DataRate(1000000))); |
| 446 |
p2p1.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(10))); |
| 447 |
PointToPointHelper p2p2; |
| 448 |
p2p2.SetDeviceAttribute ("DataRate", DataRateValue (DataRate(100000))); |
| 449 |
p2p2.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(10))); |
| 450 |
|
| 451 |
// And then install devices and channels connecting our topology. |
| 452 |
NetDeviceContainer dev0 = p2p1.Install (n0n1); |
| 453 |
NetDeviceContainer dev1 = p2p2.Install (n1n2); |
| 454 |
NetDeviceContainer dev2 = p2p1.Install (n2n3); |
| 455 |
|
| 456 |
// Now add ip/tcp stack to all nodes. |
| 457 |
InternetStackHelper internet; |
| 458 |
internet.InstallAll (); |
| 459 |
|
| 460 |
// Later, we add IP addresses. |
| 461 |
Ipv4AddressHelper ipv4; |
| 462 |
ipv4.SetBase ("10.1.3.0", "255.255.255.0"); |
| 463 |
ipv4.Assign (dev0); |
| 464 |
ipv4.SetBase ("10.1.2.0", "255.255.255.0"); |
| 465 |
ipv4.Assign (dev1); |
| 466 |
ipv4.SetBase ("10.1.1.0", "255.255.255.0"); |
| 467 |
Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev2); |
| 468 |
|
| 469 |
// and setup ip routing tables to get total ip-level connectivity. |
| 470 |
Ipv4GlobalRoutingHelper::PopulateRoutingTables (); |
| 471 |
|
| 472 |
// Set up the apps |
| 473 |
uint16_t servPort = 50000; |
| 474 |
|
| 475 |
// Create a packet sink to receive these packets on n3 |
| 476 |
PacketSinkHelper sink ("ns3::TcpSocketFactory", |
| 477 |
InetSocketAddress (Ipv4Address::GetAny (), servPort)); |
| 478 |
|
| 479 |
ApplicationContainer apps = sink.Install (n2n3.Get (1)); |
| 480 |
apps.Start (Seconds (0.0)); |
| 481 |
apps.Stop (Seconds (5.4)); |
| 482 |
|
| 483 |
// Create the socket for n0 |
| 484 |
Address sinkAddress (InetSocketAddress(ipInterfs.GetAddress (1), servPort)); |
| 485 |
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (n0n1.Get (0), TcpSocketFactory::GetTypeId ()); |
| 486 |
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&Ns3TcpCwndTestCase2::CwndChange, this)); |
| 487 |
|
| 488 |
// Create and start the app for n0 |
| 489 |
Ptr<SimpleSource> app = CreateObject<SimpleSource> (); |
| 490 |
app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps")); |
| 491 |
n0n1.Get (0)->AddApplication (app); |
| 492 |
app->Start (Seconds (1.0)); |
| 493 |
app->Stop (Seconds (5.4)); |
| 494 |
|
| 495 |
if (m_writeResults) |
| 496 |
{ |
| 497 |
// Write a pcap for tcp cwnd testcase with out-of-order delivery |
| 498 |
PointToPointHelper::EnablePcapAll ("tcp-cwnd-ood"); |
| 499 |
} |
| 500 |
|
| 501 |
// Finally, set up the simulator to run. |
| 502 |
Simulator::Stop (Seconds(5.4)); |
| 503 |
Simulator::Run (); |
| 504 |
Simulator::Destroy (); |
| 505 |
|
| 506 |
// |
| 507 |
// As new acks are received by the TCP under test, the congestion window |
| 508 |
// should be opened up by one segment (MSS bytes) each time. This should |
| 509 |
// trigger a congestion window change event which we hooked and saved above. |
| 510 |
// We should now be able to look through the saved response vectors and follow |
| 511 |
// the congestion window as it opens up when the ns-3 TCP under test |
| 512 |
// transmits its bits |
| 513 |
// |
| 514 |
// From inspecting the results, we know that we should see 31 congestion |
| 515 |
// window change events. On the tenth change event, the window should go back |
| 516 |
// to one segment due to 3 dup acks. It should then slow start again for |
| 517 |
// 4 events and then enter congestion avoidance. On change event 30 |
| 518 |
// (29 zero-based indexing), it should go back to one segment, because of triple dup ack. |
| 519 |
// |
| 520 |
const uint32_t MSS = 536; |
| 521 |
|
| 522 |
CwndEvent event; |
| 523 |
|
| 524 |
NS_TEST_ASSERT_MSG_EQ (m_responses.GetN (), 31, "Unexpected number of cwnd change events"); |
| 525 |
|
| 526 |
for (uint32_t i = 0, from = 536, to = 1072; i < 9; ++i, from += 536, to += 536) |
| 527 |
{ |
| 528 |
event = m_responses.Get (i); |
| 529 |
NS_TEST_ASSERT_MSG_EQ (event.m_oldCwnd, from, "Wrong old cwnd value in cwnd change event " << i); |
| 530 |
NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, to, "Wrong new cwnd value in cwnd change event " << i); |
| 531 |
} |
| 532 |
|
| 533 |
// Cwnd should be back to 536 |
| 534 |
event = m_responses.Get (9); |
| 535 |
NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, MSS, "Wrong new cwnd value in cwnd change event " << 9); |
| 536 |
|
| 537 |
// Another round of slow start |
| 538 |
for (uint32_t i = 10, from = 536, to = 1072; i < 14; ++i, from += 536, to += 536) |
| 539 |
{ |
| 540 |
event = m_responses.Get (i); |
| 541 |
NS_TEST_ASSERT_MSG_EQ (event.m_oldCwnd, from, "Wrong old cwnd value in cwnd change event " << i); |
| 542 |
NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, to, "Wrong new cwnd value in cwnd change event " << i); |
| 543 |
} |
| 544 |
|
| 545 |
// Congestion Avoidance |
| 546 |
double adder; |
| 547 |
uint32_t from = 2680; |
| 548 |
for (uint32_t i = 14; i < 29; ++i) |
| 549 |
{ |
| 550 |
event = m_responses.Get (i); |
| 551 |
NS_TEST_ASSERT_MSG_EQ (event.m_oldCwnd, from, "Wrong old cwnd value in cwnd change event " << i); |
| 552 |
adder = ((double) MSS * MSS) / event.m_oldCwnd; |
| 553 |
adder += event.m_oldCwnd; |
| 554 |
from = adder; |
| 555 |
NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, (uint32_t)adder, "Wrong new cwnd value in cwnd change event " << i); |
| 556 |
} |
| 557 |
|
| 558 |
// Cwnd should be back to 536 |
| 559 |
event = m_responses.Get (29); |
| 560 |
NS_TEST_ASSERT_MSG_EQ (event.m_newCwnd, MSS, "Wrong new cwnd value in cwnd change event " << 29); |
| 561 |
|
| 562 |
return GetErrorStatus (); |
| 563 |
} |
| 564 |
|
| 369 |
class Ns3TcpCwndTestSuite : public TestSuite |
565 |
class Ns3TcpCwndTestSuite : public TestSuite |
| 370 |
{ |
566 |
{ |
| 371 |
public: |
567 |
public: |
|
Lines 375-381
Ns3TcpCwndTestSuite::Ns3TcpCwndTestSuite
|
Link Here
|
|---|
|
| 375 |
Ns3TcpCwndTestSuite::Ns3TcpCwndTestSuite () |
571 |
Ns3TcpCwndTestSuite::Ns3TcpCwndTestSuite () |
| 376 |
: TestSuite ("ns3-tcp-cwnd", SYSTEM) |
572 |
: TestSuite ("ns3-tcp-cwnd", SYSTEM) |
| 377 |
{ |
573 |
{ |
| 378 |
AddTestCase (new Ns3TcpCwndTestCase); |
574 |
AddTestCase (new Ns3TcpCwndTestCase1); |
|
|
575 |
AddTestCase (new Ns3TcpCwndTestCase2); |
| 379 |
} |
576 |
} |
| 380 |
|
577 |
|
| 381 |
Ns3TcpCwndTestSuite ns3TcpCwndTestSuite; |
578 |
Ns3TcpCwndTestSuite ns3TcpCwndTestSuite; |