--- a/examples/tcp/tcp-loss-response.cc Wed Jan 19 16:23:13 2011 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,292 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-//
-// Network topology
-//
-// 8Mb/s, 0.1ms 0.8Mb/s, 100ms
-// s1-----------------r1-----------------k1
-//
-// Example corresponding to simulations in the paper "Simulation-based
-// Comparisons of Tahoe, Reno, and SACK TCP"
-//
-// To look at the time-sequence plots corresponding to the packet traces,
-// the tcptrace tool (www.tcptrace.org) with the -S option can produce
-// xplot plots (a2b.xpl, b2a.xpl) which can be viewed using xplot
-//
-// - Tracing of queues and packet receptions to file
-// "tcp-loss-response.tr
-// - pcap traces also generated in the following files
-// "tcp-loss-response-s1-0.pcap" and "tcp-loss-response-k1-0.pcap"
-//
-// Usage (e.g.): ./waf --run tcp-loss-response
-//
-
-
-#include <ctype.h>
-#include <iostream>
-#include <iomanip>
-#include <fstream>
-#include <string>
-#include <cassert>
-
-#include "ns3/core-module.h"
-#include "ns3/common-module.h"
-#include "ns3/helper-module.h"
-#include "ns3/node-module.h"
-#include "ns3/simulator-module.h"
-#include "ns3/ipv4-global-routing-helper.h"
-
-using namespace ns3;
-
-NS_LOG_COMPONENT_DEFINE ("TcpLossResponse");
-
-// The number of bytes to send in this simulation.
-static const uint32_t totalTxBytes = 200000;
-static uint32_t currentTxBytes = 0;
-// Perform series of 26*40=1040 byte writes (this is a multiple of 26 since
-// we want to detect data splicing in the output stream)
-static const uint32_t writeSize = 1040;
-uint8_t data[writeSize];
-// Need to invoke Socket::Close() on sender?
-bool needToClose = true;
-
-// These are for starting the writing process, and handling the sending
-// socket's notification upcalls (events). These two together more or less
-// implement a sending "Application", although not a proper ns3::Application
-// subclass.
-
-void StartFlow (Ptr<Socket>, Ipv4Address, uint16_t);
-void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
-
-static void
-CwndTracer (uint32_t oldval, uint32_t newval)
-{
- NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval << " at time " << Simulator::Now ().GetSeconds () << " seconds");
-}
-
-int main (int argc, char *argv[])
-{
- std::string tcpModel ("ns3::TcpNewReno");
- uint32_t losses = 1;
- bool verbose = false;
- bool tracing = true;
-
- // Configuration and command line parameter parsing
- CommandLine cmd;
- cmd.AddValue ("tcpModel", "Tcp congestion control model", tcpModel);
- cmd.AddValue ("losses", "number of packet losses", losses);
- cmd.AddValue ("verbose", "turn on selected log components", verbose);
- cmd.AddValue ("tracing", "turn on ascii and pcap tracing", tracing);
- cmd.Parse (argc, argv);
-
- Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue (tcpModel));
- Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000)); // 1000-byte packet for easier reading
- Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1));
-
- LogComponentEnableAll (LOG_PREFIX_FUNC);
- LogComponentEnable ("TcpLossResponse", LOG_LEVEL_ALL);
- if (verbose)
- {
- //LogComponentEnableAll (LOG_PREFIX_TIME);
- LogComponentEnable ("ErrorModel", LOG_LEVEL_DEBUG);
- LogComponentEnable ("TcpLossResponse", LOG_LEVEL_ALL);
- LogComponentEnable ("TcpNewReno", LOG_LEVEL_INFO);
- LogComponentEnable ("TcpReno", LOG_LEVEL_INFO);
- LogComponentEnable ("TcpTahoe", LOG_LEVEL_INFO);
- LogComponentEnable ("TcpSocketBase", LOG_LEVEL_INFO);
- }
-
- // initialize the tx buffer (fill with lowercase a to z)
- for (uint32_t i = 0; i < writeSize; ++i)
- {
- char m = toascii (97 + i % 26);
- data[i] = m;
- }
-
- ////////////////////////////////////////////////////////
- // Topology construction
- //
-
- // Create three nodes: s1, r1, and k1
- NodeContainer s1r1;
- s1r1.Create (2);
- Names::Add ("s1", s1r1.Get (0));
- Names::Add ("r1", s1r1.Get (1));
-
- NodeContainer r1k1;
- r1k1.Add (s1r1.Get (1));
- r1k1.Create (1);
- Names::Add ("k1", r1k1.Get (1));
-
- // Set up TCP/IP stack to all nodes (and create loopback device at device 0)
- InternetStackHelper internet;
- internet.InstallAll ();
-
- // Connect the nodes
- PointToPointHelper p2p;
- p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate (8000000)));
- p2p.SetChannelAttribute ("Delay", TimeValue (Seconds (0.0001)));
- NetDeviceContainer dev0 = p2p.Install (s1r1);
- p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate (800000)));
- p2p.SetChannelAttribute ("Delay", TimeValue (Seconds (0.1)));
- NetDeviceContainer dev1 = p2p.Install (r1k1);
-
- // Add IP addresses to each network interfaces
- Ipv4AddressHelper ipv4;
- ipv4.SetBase ("10.1.3.0", "255.255.255.0");
- ipv4.Assign (dev0);
- ipv4.SetBase ("10.1.2.0", "255.255.255.0");
- Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev1);
-
- // Set up routes to all nodes
- Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
-
- ////////////////////////////////////////////////////////
- // Send 20000 (totalTxBytes) bytes from node s1 to node k1
- //
-
- // Create a packet sink to receive packets on node k1
- uint16_t servPort = 50000; // Destination port number
- PacketSinkHelper sink ("ns3::TcpSocketFactory",
- InetSocketAddress (Ipv4Address::GetAny (), servPort));
- ApplicationContainer apps = sink.Install (r1k1.Get (1));
- apps.Start (Seconds (0.0));
- apps.Stop (Seconds (100.0));
-
- // Create a data source to send packets on node s0.
- // Instead of full application, here use the socket directly by
- // registering callbacks in function StarFlow().
- Ptr<Socket> localSocket = Socket::CreateSocket (s1r1.Get (0), TcpSocketFactory::GetTypeId ());
- localSocket->Bind ();
- Simulator::ScheduleNow (&StartFlow, localSocket, ipInterfs.GetAddress (1), servPort);
-
- // Trace changes to the congestion window (available in Tahoe and descendents)
- Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeCallback (&CwndTracer));
-
- ////////////////////////////////////////////////////////
- // Set up loss model at node k1
- //
-
- std::list<uint32_t> sampleList;
- switch (losses)
- {
- case 0:
- break;
- case 1:
- // Force a loss for 15th data packet. TCP cwnd will be at 14 segments
- // (14000 bytes) when duplicate acknowledgments start to come.
- sampleList.push_back (16);
- break;
- case 2:
- sampleList.push_back (16);
- sampleList.push_back (17);
- break;
- case 3:
- sampleList.push_back (16);
- sampleList.push_back (17);
- sampleList.push_back (18);
- break;
- case 4:
- sampleList.push_back (16);
- sampleList.push_back (17);
- sampleList.push_back (18);
- sampleList.push_back (19);
- break;
- default:
- NS_FATAL_ERROR ("Program fatal error: loss value " << losses << " not supported.");
- break;
- }
-
- Ptr<ReceiveListErrorModel> pem = CreateObject<ReceiveListErrorModel> ();
- pem->SetList (sampleList);
- dev1.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (pem));
-
- // One can toggle the comment for the following line on or off to see the
- // effects of finite send buffer modelling. One can also change the size of
- // that buffer.
- // localSocket->SetAttribute("SndBufSize", UintegerValue(4096));
-
- /////////////////////////////////////////////////////////
- // Set up trace and run the simulation
- //
-
- if (tracing)
- {
- // Ask for ASCII and pcap traces of network traffic
- AsciiTraceHelper ascii;
- //Ptr<OutputStreamWrapper> osw = ascii.CreateFileStream ("tcp-loss-response.tr");
- Ptr<OutputStreamWrapper> osw = Create<OutputStreamWrapper> (&std::clog);
- *(osw->GetStream ()) << std::setprecision(9) << std::fixed;
- p2p.EnableAsciiAll (osw);
-// p2p.EnablePcap ("tcp-loss-response", 0, 0);
-// p2p.EnablePcap ("tcp-loss-response", 2, 0);
- }
-
- // Finally, set up the simulator to run. The 1000 second hard limit is a
- // failsafe in case some change above causes the simulation to never end
- Simulator::Stop (Seconds (1000));
- Simulator::Run ();
- Simulator::Destroy ();
-}
-
-
-// -----------------------------------------------------------------------------
-// -----------------------------------------------------------------------------
-// -----------------------------------------------------------------------------
-// begin implementation of sending "Application"
-void StartFlow (Ptr<Socket> localSocket,
- Ipv4Address servAddress,
- uint16_t servPort)
-{
- NS_LOG_LOGIC ("Starting flow at time " << Simulator::Now ().GetSeconds ());
- localSocket->Connect (InetSocketAddress (servAddress, servPort)); // connect
-
- // tell the tcp implementation to call WriteUntilBufferFull again
- // if we blocked and new tx buffer space becomes available
- localSocket->SetSendCallback (MakeCallback (&WriteUntilBufferFull));
- WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ());
-}
-
-void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace)
-{
- while (currentTxBytes < totalTxBytes)
- {
- uint32_t left = totalTxBytes - currentTxBytes;
- uint32_t dataOffset = currentTxBytes % writeSize;
- uint32_t toWrite = writeSize - dataOffset;
- uint32_t txAvail = localSocket->GetTxAvailable ();
- toWrite = std::min (toWrite, left);
- toWrite = std::min (toWrite, txAvail);
- if (txAvail == 0)
- {
- NS_LOG_LOGIC ("TCP socket buffer full at " << Simulator::Now ().GetSeconds ());
- return;
- };
- NS_LOG_LOGIC ("Submitting " << toWrite << " bytes to TCP socket");
- int amountSent = localSocket->Send (&data[dataOffset], toWrite, 0);
- NS_ASSERT (amountSent > 0); // Given GetTxAvailable() non-zero, amountSent should not be zero
- currentTxBytes += amountSent;
- }
- if (needToClose)
- {
- NS_LOG_LOGIC ("Close socket at " << Simulator::Now ().GetSeconds ());
- localSocket->Close ();
- needToClose = false;
- }
-}
-
--- a/examples/tcp/wscript Wed Jan 19 16:23:13 2011 -0500
+++ b/examples/tcp/wscript Thu Jan 20 14:18:12 2011 -0500
@@ -21,10 +21,6 @@
['point-to-point', 'internet-stack'])
obj.source = 'star.cc'
- obj = bld.create_ns3_program('tcp-loss-response',
- ['point-to-point', 'internet-stack'])
- obj.source = 'tcp-loss-response.cc'
-
obj = bld.create_ns3_program('tcp-bulk-send',
['point-to-point', 'internet-stack'])
obj.source = 'tcp-bulk-send.cc'
Binary file src/test/ns3tcp/ns3tcp-loss-NewReno0-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-NewReno1-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-NewReno2-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-NewReno3-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-NewReno4-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Reno0-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Reno1-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Reno2-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Reno3-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Reno4-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Tahoe0-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Tahoe1-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Tahoe2-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Tahoe3-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss-Tahoe4-response-vectors.pcap has changed
--- a/src/test/ns3tcp/ns3tcp-loss-test-suite.cc Wed Jan 19 16:23:13 2011 -0500
+++ b/src/test/ns3tcp/ns3tcp-loss-test-suite.cc Thu Jan 20 14:18:12 2011 -0500
@@ -42,7 +42,7 @@
NS_LOG_COMPONENT_DEFINE ("Ns3TcpLossTest");
const bool WRITE_VECTORS = false; // set to true to write response vectors
-const uint32_t PCAP_LINK_TYPE = 1187373553; // Some large random number -- we use to verify data was written by this program
+const uint32_t PCAP_LINK_TYPE = 1187373557; // Some large random number -- we use to verify data was written by this program
const uint32_t PCAP_SNAPLEN = 64; // Don't bother to save much data
// ===========================================================================
@@ -50,11 +50,12 @@
// ===========================================================================
//
-class Ns3TcpLossTestCase1 : public TestCase
+class Ns3TcpLossTestCase : public TestCase
{
public:
- Ns3TcpLossTestCase1 ();
- virtual ~Ns3TcpLossTestCase1 () {}
+ Ns3TcpLossTestCase ();
+ Ns3TcpLossTestCase (std::string tcpModel, uint32_t testCase);
+ virtual ~Ns3TcpLossTestCase () {}
private:
virtual void DoSetup (void);
@@ -63,28 +64,56 @@
std::string m_pcapFilename;
PcapFile m_pcapFile;
+ uint32_t m_testCase;
+ uint32_t m_totalTxBytes;
+ uint32_t m_currentTxBytes;
bool m_writeVectors;
bool m_writeResults;
+ bool m_needToClose;
+ std::string m_tcpModel;
void Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
+ void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace);
+ void StartFlow (Ptr<Socket> localSocket,
+ Ipv4Address servAddress,
+ uint16_t servPort);
};
-Ns3TcpLossTestCase1::Ns3TcpLossTestCase1 ()
- : TestCase ("Check that ns-3 TCP survives loss of first two SYNs"),
+Ns3TcpLossTestCase::Ns3TcpLossTestCase ()
+ : TestCase ("Check the operation of the TCP state machine for several cases"),
+ m_testCase (0),
+ m_totalTxBytes (200000),
+ m_currentTxBytes (0),
m_writeVectors (WRITE_VECTORS),
- m_writeResults (false)
+ m_writeResults (false),
+ m_needToClose (true),
+ m_tcpModel ("ns3::TcpTahoe")
+{
+}
+
+Ns3TcpLossTestCase::Ns3TcpLossTestCase (std::string tcpModel, uint32_t testCase)
+ : TestCase ("Check the behaviour of TCP upon packet losses"),
+ m_testCase (testCase),
+ m_totalTxBytes (200000),
+ m_currentTxBytes (0),
+ m_writeVectors (WRITE_VECTORS),
+ m_writeResults (false),
+ m_needToClose (true),
+ m_tcpModel (tcpModel)
{
}
void
-Ns3TcpLossTestCase1::DoSetup (void)
+Ns3TcpLossTestCase::DoSetup (void)
{
//
- // We expect there to be a file called ns3tcp-loss1-response-vectors.pcap" in
+ // We expect there to be a file called ns3tcp-state-response-vectors.pcap in
// the source directory of this file.
//
- m_pcapFilename = NS_TEST_SOURCEDIR + "ns3tcp-loss1-response-vectors.pcap";
+ std::ostringstream oss;
+ oss << "ns3tcp-loss-" << m_tcpModel << m_testCase << "-response-vectors.pcap";
+ m_pcapFilename = NS_TEST_SOURCEDIR + oss.str ();
if (m_writeVectors)
{
@@ -99,13 +128,13 @@
}
void
-Ns3TcpLossTestCase1::DoTeardown (void)
+Ns3TcpLossTestCase::DoTeardown (void)
{
m_pcapFile.Close ();
}
void
-Ns3TcpLossTestCase1::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface)
+Ns3TcpLossTestCase::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface)
{
//
// We're not testing IP so remove and toss the header. In order to do this,
@@ -165,251 +194,184 @@
}
}
-void
-Ns3TcpLossTestCase1::DoRun (void)
+////////////////////////////////////////////////////////////////////
+// Implementing an "application" to send bytes over a TCP connection
+void
+Ns3TcpLossTestCase::WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace)
{
- uint16_t sinkPort = 50000;
- double sinkStopTime = 40; // sec; will trigger Socket::Close
- double writerStopTime = 30; // sec; will trigger Socket::Close
- double simStopTime = 60; // sec
- Time sinkStopTimeObj = Seconds (sinkStopTime);
- Time writerStopTimeObj = Seconds (writerStopTime);
- Time simStopTimeObj= Seconds (simStopTime);
-
- Ptr<Node> n0 = CreateObject<Node> ();
- Ptr<Node> n1 = CreateObject<Node> ();
-
- PointToPointHelper pointToPoint;
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("200ms"));
-
- NetDeviceContainer devices;
- devices = pointToPoint.Install (n0, n1);
-
- InternetStackHelper internet;
- internet.InstallAll ();
-
- Ipv4AddressHelper address;
- address.SetBase ("10.1.1.0", "255.255.255.252");
- Ipv4InterfaceContainer ifContainer = address.Assign (devices);
-
- Ptr<SocketWriter> socketWriter = CreateObject<SocketWriter> ();
- Address sinkAddress (InetSocketAddress (ifContainer.GetAddress (1), sinkPort));
- socketWriter->Setup (n0, sinkAddress);
- n0->AddApplication (socketWriter);
- socketWriter->SetStartTime (Seconds (0.));
- socketWriter->SetStopTime (writerStopTimeObj);
-
- PacketSinkHelper sink ("ns3::TcpSocketFactory",
- InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
- ApplicationContainer apps = sink.Install (n1);
- // Start the sink application at time zero, and stop it at sinkStopTime
- apps.Start (Seconds (0.0));
- apps.Stop (sinkStopTimeObj);
-
- Config::Connect ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx",
- MakeCallback (&Ns3TcpLossTestCase1::Ipv4L3Tx, this));
-
- Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter);
- Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 500);
- Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter);
-
- std::list<uint32_t> sampleList;
- // Lose first two SYNs
- sampleList.push_back (0);
- sampleList.push_back (1);
- // This time, we'll explicitly create the error model we want
- Ptr<ReceiveListErrorModel> pem = CreateObject<ReceiveListErrorModel> ();
- pem->SetList (sampleList);
- devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (pem));
-
- if (m_writeResults)
+ while (m_currentTxBytes < m_totalTxBytes)
{
- pointToPoint.EnablePcapAll ("tcp-loss-test-case-1");
- pointToPoint.EnableAsciiAll ("tcp-loss-test-case-1");
+ uint32_t left = m_totalTxBytes - m_currentTxBytes;
+ uint32_t dataOffset = m_currentTxBytes % 1040;
+ uint32_t toWrite = 1040 - dataOffset;
+ uint32_t txAvail = localSocket->GetTxAvailable ();
+ toWrite = std::min (toWrite, left);
+ toWrite = std::min (toWrite, txAvail);
+ if (txAvail == 0)
+ {
+ return;
+ };
+ NS_LOG_LOGIC ("Submitting " << toWrite << " bytes to TCP socket");
+ int amountSent = localSocket->Send (0, toWrite, 0);
+ NS_ASSERT (amountSent > 0); // Given GetTxAvailable() non-zero, amountSent should not be zero
+ m_currentTxBytes += amountSent;
}
-
- Simulator::Stop (simStopTimeObj);
- Simulator::Run ();
- Simulator::Destroy ();
+ if (m_needToClose)
+ {
+ NS_LOG_LOGIC ("Close socket at " << Simulator::Now ().GetSeconds ());
+ localSocket->Close ();
+ m_needToClose = false;
+ }
}
-class Ns3TcpLossTestCase2 : public TestCase
+void
+Ns3TcpLossTestCase::StartFlow (Ptr<Socket> localSocket,
+ Ipv4Address servAddress,
+ uint16_t servPort)
{
-public:
- Ns3TcpLossTestCase2 ();
- virtual ~Ns3TcpLossTestCase2 () {}
-
-private:
- virtual void DoSetup (void);
- virtual void DoRun (void);
- virtual void DoTeardown (void);
-
- std::string m_pcapFilename;
- PcapFile m_pcapFile;
- bool m_writeVectors;
- bool m_writeResults;
-
- void Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
-};
-
-Ns3TcpLossTestCase2::Ns3TcpLossTestCase2 ()
- : TestCase ("Check that ns-3 TCP survives loss of first data packet"),
- m_writeVectors (WRITE_VECTORS),
- m_writeResults (false)
-{
-}
+ NS_LOG_LOGIC ("Starting flow at time " << Simulator::Now ().GetSeconds ());
+ localSocket->Connect (InetSocketAddress (servAddress, servPort)); // connect
-void
-Ns3TcpLossTestCase2::DoSetup (void)
-{
- //
- // We expect there to be a file called ns3tcp-loss1-response-vectors.pcap" in
- // the source directory of this file.
- //
- m_pcapFilename = NS_TEST_SOURCEDIR + "ns3tcp-loss2-response-vectors.pcap";
-
- if (m_writeVectors)
- {
- m_pcapFile.Open (m_pcapFilename, std::ios::out|std::ios::binary);
- m_pcapFile.Init(PCAP_LINK_TYPE, PCAP_SNAPLEN);
- }
- else
- {
- m_pcapFile.Open (m_pcapFilename, std::ios::in|std::ios::binary);
- NS_ABORT_MSG_UNLESS (m_pcapFile.GetDataLinkType () == PCAP_LINK_TYPE, "Wrong response vectors in directory");
- }
-}
-
-void
-Ns3TcpLossTestCase2::DoTeardown (void)
-{
- m_pcapFile.Close ();
+ // tell the tcp implementation to call WriteUntilBufferFull again
+ // if we blocked and new tx buffer space becomes available
+ localSocket->SetSendCallback (MakeCallback
+ (&Ns3TcpLossTestCase::WriteUntilBufferFull,
+ this));
+ WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ());
}
void
-Ns3TcpLossTestCase2::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface)
+Ns3TcpLossTestCase::DoRun (void)
{
- //
- // We're not testing IP so remove and toss the header. In order to do this,
- // though, we need to copy the packet since we have a const version.
- //
- Ptr<Packet> p = packet->Copy ();
- Ipv4Header ipHeader;
- p->RemoveHeader (ipHeader);
-
+ // Network topology
//
- // What is left is the TCP header and any data that may be sent. We aren't
- // sending any TCP data, so we expect what remains is only TCP header, which
- // is a small thing to save.
+ // 8Mb/s, 0.1ms 0.8Mb/s, 100ms
+ // s1-----------------r1-----------------k1
//
- if (m_writeVectors)
- {
- //
- // Save the TCP under test response for later testing.
- //
- Time tNow = Simulator::Now ();
- int64_t tMicroSeconds = tNow.GetMicroSeconds ();
- uint32_t size = p->GetSize ();
- uint8_t *buf = new uint8_t[size];
- p->CopyData (buf, size);
+ // Example corresponding to simulations in the paper "Simulation-based
+ // Comparisons of Tahoe, Reno, and SACK TCP"
- m_pcapFile.Write (uint32_t (tMicroSeconds / 1000000),
- uint32_t (tMicroSeconds % 1000000),
- buf,
- size);
- }
- else
- {
- //
- // Read the TCP under test expected response from the expected vector
- // file and see if it still does the right thing.
- //
- uint8_t expected[PCAP_SNAPLEN];
- uint32_t tsSec, tsUsec, inclLen, origLen, readLen;
- m_pcapFile.Read (expected, sizeof(expected), tsSec, tsUsec, inclLen, origLen, readLen);
-
- uint8_t *actual = new uint8_t[readLen];
- p->CopyData (actual, readLen);
-
- uint32_t result = memcmp(actual, expected, readLen);
-
- delete [] actual;
+ std::ostringstream tcpModel;
+ tcpModel << "ns3::Tcp" << m_tcpModel;
+ Config::SetDefault ("ns3::TcpL4Protocol::SocketType",
+ StringValue (tcpModel.str ()));
+ Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000));
+ Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1));
- //
- // Avoid streams of errors -- only report the first.
- //
- if (GetErrorStatus () == false)
- {
- NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error");
- }
- }
-}
+ ////////////////////////////////////////////////////////
+ // Topology construction
+ //
+
+ // Create three nodes: s1, r1, and k1
+ NodeContainer s1r1;
+ s1r1.Create (2);
-void
-Ns3TcpLossTestCase2::DoRun (void)
-{
- uint16_t sinkPort = 50000;
- double sinkStopTime = 40; // sec; will trigger Socket::Close
- double writerStopTime = 12; // sec; will trigger Socket::Close
- double simStopTime = 60; // sec
- Time sinkStopTimeObj = Seconds (sinkStopTime);
- Time writerStopTimeObj = Seconds (writerStopTime);
- Time simStopTimeObj= Seconds (simStopTime);
+ NodeContainer r1k1;
+ r1k1.Add (s1r1.Get (1));
+ r1k1.Create (1);
- Ptr<Node> n0 = CreateObject<Node> ();
- Ptr<Node> n1 = CreateObject<Node> ();
-
- PointToPointHelper pointToPoint;
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("200ms"));
-
- NetDeviceContainer devices;
- devices = pointToPoint.Install (n0, n1);
-
+ // Set up TCP/IP stack to all nodes (and create loopback device at device 0)
InternetStackHelper internet;
internet.InstallAll ();
- Ipv4AddressHelper address;
- address.SetBase ("10.1.1.0", "255.255.255.252");
- Ipv4InterfaceContainer ifContainer = address.Assign (devices);
+ // Connect the nodes
+ PointToPointHelper p2p;
+ p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate (8000000)));
+ p2p.SetChannelAttribute ("Delay", TimeValue (Seconds (0.0001)));
+ NetDeviceContainer dev0 = p2p.Install (s1r1);
+ p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate (800000)));
+ p2p.SetChannelAttribute ("Delay", TimeValue (Seconds (0.1)));
+ NetDeviceContainer dev1 = p2p.Install (r1k1);
+
+ // Add IP addresses to each network interfaces
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.3.0", "255.255.255.0");
+ ipv4.Assign (dev0);
+ ipv4.SetBase ("10.1.2.0", "255.255.255.0");
+ Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev1);
+
+ // Set up routes to all nodes
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
- Ptr<SocketWriter> socketWriter = CreateObject<SocketWriter> ();
- Address sinkAddress (InetSocketAddress (ifContainer.GetAddress (1), sinkPort));
- socketWriter->Setup (n0, sinkAddress);
- n0->AddApplication (socketWriter);
- socketWriter->SetStartTime (Seconds (0.));
- socketWriter->SetStopTime (writerStopTimeObj);
+ ////////////////////////////////////////////////////////
+ // Send 20000 (totalTxBytes) bytes from node s1 to node k1
+ //
+ // Create a packet sink to receive packets on node k1
+ uint16_t servPort = 50000; // Destination port number
PacketSinkHelper sink ("ns3::TcpSocketFactory",
- InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
- ApplicationContainer apps = sink.Install (n1);
- // Start the sink application at time zero, and stop it at sinkStopTime
+ InetSocketAddress (Ipv4Address::GetAny (), servPort));
+ ApplicationContainer apps = sink.Install (r1k1.Get (1));
apps.Start (Seconds (0.0));
- apps.Stop (sinkStopTimeObj);
+ apps.Stop (Seconds (100.0));
+
+ // Create a data source to send packets on node s0.
+ // Instead of full application, here use the socket directly by
+ // registering callbacks in function StarFlow().
+ Ptr<Socket> localSocket = Socket::CreateSocket (s1r1.Get (0), TcpSocketFactory::GetTypeId ());
+ localSocket->Bind ();
+ Simulator::ScheduleNow (&Ns3TcpLossTestCase::StartFlow,
+ this,
+ localSocket,
+ ipInterfs.GetAddress (1),
+ servPort);
Config::Connect ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx",
- MakeCallback (&Ns3TcpLossTestCase2::Ipv4L3Tx, this));
+ MakeCallback (&Ns3TcpLossTestCase::Ipv4L3Tx, this));
- Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter);
- Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 500);
- Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter);
+ ////////////////////////////////////////////////////////
+ // Set up loss model at node k1
+ //
+ std::list<uint32_t> sampleList;
+ switch (m_testCase)
+ {
+ case 0:
+ break;
+ case 1:
+ // Force a loss for 15th data packet. TCP cwnd will be at 14 segments
+ // (14000 bytes) when duplicate acknowledgments start to come.
+ sampleList.push_back (16);
+ break;
+ case 2:
+ sampleList.push_back (16);
+ sampleList.push_back (17);
+ break;
+ case 3:
+ sampleList.push_back (16);
+ sampleList.push_back (17);
+ sampleList.push_back (18);
+ break;
+ case 4:
+ sampleList.push_back (16);
+ sampleList.push_back (17);
+ sampleList.push_back (18);
+ sampleList.push_back (19);
+ break;
+ default:
+ NS_FATAL_ERROR ("Program fatal error: loss value " << m_testCase << " not supported.");
+ break;
+ }
- std::list<uint32_t> sampleList;
- // Lose first data segment
- sampleList.push_back (2);
- // This time, we'll explicitly create the error model we want
Ptr<ReceiveListErrorModel> pem = CreateObject<ReceiveListErrorModel> ();
pem->SetList (sampleList);
- devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (pem));
+ dev1.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (pem));
+ // One can toggle the comment for the following line on or off to see the
+ // effects of finite send buffer modelling. One can also change the size of
+ // that buffer.
+ // localSocket->SetAttribute("SndBufSize", UintegerValue(4096));
+
+ std::ostringstream oss;
+ oss << "tcp-loss-" << m_tcpModel << m_testCase << "-test-case";
if (m_writeResults)
{
- pointToPoint.EnablePcapAll ("tcp-loss-test-case-2");
- pointToPoint.EnableAsciiAll ("tcp-loss-test-case-2");
+ p2p.EnablePcapAll (oss.str ());
+ p2p.EnableAsciiAll (oss.str ());
}
-
- Simulator::Stop (simStopTimeObj);
+
+ // Finally, set up the simulator to run. The 1000 second hard limit is a
+ // failsafe in case some change above causes the simulation to never end
+ Simulator::Stop (Seconds (1000));
Simulator::Run ();
Simulator::Destroy ();
}
@@ -424,8 +386,23 @@
: TestSuite ("ns3-tcp-loss", SYSTEM)
{
Packet::EnablePrinting (); // Enable packet metadata for all test cases
- AddTestCase (new Ns3TcpLossTestCase1);
- AddTestCase (new Ns3TcpLossTestCase2);
+ AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 0));
+ AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 1));
+ AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 2));
+ AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 3));
+ AddTestCase (new Ns3TcpLossTestCase ("Tahoe", 4));
+
+ AddTestCase (new Ns3TcpLossTestCase ("Reno", 0));
+ AddTestCase (new Ns3TcpLossTestCase ("Reno", 1));
+ AddTestCase (new Ns3TcpLossTestCase ("Reno", 2));
+ AddTestCase (new Ns3TcpLossTestCase ("Reno", 3));
+ AddTestCase (new Ns3TcpLossTestCase ("Reno", 4));
+
+ AddTestCase (new Ns3TcpLossTestCase ("NewReno", 0));
+ AddTestCase (new Ns3TcpLossTestCase ("NewReno", 1));
+ AddTestCase (new Ns3TcpLossTestCase ("NewReno", 2));
+ AddTestCase (new Ns3TcpLossTestCase ("NewReno", 3));
+ AddTestCase (new Ns3TcpLossTestCase ("NewReno", 4));
}
static Ns3TcpLossTestSuite ns3TcpLossTestSuite;
Binary file src/test/ns3tcp/ns3tcp-loss1-response-vectors.pcap has changed
Binary file src/test/ns3tcp/ns3tcp-loss2-response-vectors.pcap has changed