A Discrete-Event Network Simulator
API
tcp-large-transfer.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  */
17 
18 //
19 // Network topology
20 //
21 // 10Mb/s, 10ms 10Mb/s, 10ms
22 // n0-----------------n1-----------------n2
23 //
24 //
25 // - Tracing of queues and packet receptions to file
26 // "tcp-large-transfer.tr"
27 // - pcap traces also generated in the following files
28 // "tcp-large-transfer-$n-$i.pcap" where n and i represent node and interface
29 // numbers respectively
30 // Usage (e.g.): ./waf --run tcp-large-transfer
31 
32 #include <iostream>
33 #include <fstream>
34 #include <string>
35 
36 #include "ns3/core-module.h"
37 #include "ns3/applications-module.h"
38 #include "ns3/network-module.h"
39 #include "ns3/internet-module.h"
40 #include "ns3/point-to-point-module.h"
41 #include "ns3/ipv4-global-routing-helper.h"
42 
43 using namespace ns3;
44 
45 NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
46 
47 // The number of bytes to send in this simulation.
48 static const uint32_t totalTxBytes = 2000000;
49 static uint32_t currentTxBytes = 0;
50 // Perform series of 1040 byte writes (this is a multiple of 26 since
51 // we want to detect data splicing in the output stream)
52 static const uint32_t writeSize = 1040;
53 uint8_t data[writeSize];
54 
55 // These are for starting the writing process, and handling the sending
56 // socket's notification upcalls (events). These two together more or less
57 // implement a sending "Application", although not a proper ns3::Application
58 // subclass.
59 
60 void StartFlow (Ptr<Socket>, Ipv4Address, uint16_t);
61 void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
62 
63 static void
64 CwndTracer (uint32_t oldval, uint32_t newval)
65 {
66  NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
67 }
68 
69 int main (int argc, char *argv[])
70 {
71  // Users may find it convenient to turn on explicit debugging
72  // for selected modules; the below lines suggest how to do this
73  // LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
74  // LogComponentEnable("TcpSocketImpl", LOG_LEVEL_ALL);
75  // LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
76  // LogComponentEnable("TcpLargeTransfer", LOG_LEVEL_ALL);
77 
78  CommandLine cmd (__FILE__);
79  cmd.Parse (argc, argv);
80 
81  // initialize the tx buffer.
82  for(uint32_t i = 0; i < writeSize; ++i)
83  {
84  char m = toascii (97 + i % 26);
85  data[i] = m;
86  }
87 
88  // Here, we will explicitly create three nodes. The first container contains
89  // nodes 0 and 1 from the diagram above, and the second one contains nodes
90  // 1 and 2. This reflects the channel connectivity, and will be used to
91  // install the network interfaces and connect them with a channel.
92  NodeContainer n0n1;
93  n0n1.Create (2);
94 
96  n1n2.Add (n0n1.Get (1));
97  n1n2.Create (1);
98 
99  // We create the channels first without any IP addressing information
100  // First make and configure the helper, so that it will put the appropriate
101  // attributes on the network interfaces and channels we are about to install.
102  PointToPointHelper p2p;
103  p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate (10000000)));
104  p2p.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (10)));
105 
106  // And then install devices and channels connecting our topology.
107  NetDeviceContainer dev0 = p2p.Install (n0n1);
108  NetDeviceContainer dev1 = p2p.Install (n1n2);
109 
110  // Now add ip/tcp stack to all nodes.
111  InternetStackHelper internet;
112  internet.InstallAll ();
113 
114  // Later, we add IP addresses.
115  Ipv4AddressHelper ipv4;
116  ipv4.SetBase ("10.1.3.0", "255.255.255.0");
117  ipv4.Assign (dev0);
118  ipv4.SetBase ("10.1.2.0", "255.255.255.0");
119  Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev1);
120 
121  // and setup ip routing tables to get total ip-level connectivity.
123 
125  // Simulation 1
126  //
127  // Send 2000000 bytes over a connection to server port 50000 at time 0
128  // Should observe SYN exchange, a lot of data segments and ACKS, and FIN
129  // exchange. FIN exchange isn't quite compliant with TCP spec (see release
130  // notes for more info)
131  //
133 
134  uint16_t servPort = 50000;
135 
136  // Create a packet sink to receive these packets on n2...
137  PacketSinkHelper sink ("ns3::TcpSocketFactory",
138  InetSocketAddress (Ipv4Address::GetAny (), servPort));
139 
140  ApplicationContainer apps = sink.Install (n1n2.Get (1));
141  apps.Start (Seconds (0.0));
142  apps.Stop (Seconds (3.0));
143 
144  // Create a source to send packets from n0. Instead of a full Application
145  // and the helper APIs you might see in other example files, this example
146  // will use sockets directly and register some socket callbacks as a sending
147  // "Application".
148 
149  // Create and bind the socket...
150  Ptr<Socket> localSocket =
152  localSocket->Bind ();
153 
154  // Trace changes to the congestion window
155  Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeCallback (&CwndTracer));
156 
157  // ...and schedule the sending "Application"; This is similar to what an
158  // ns3::Application subclass would do internally.
159  Simulator::ScheduleNow (&StartFlow, localSocket,
160  ipInterfs.GetAddress (1), servPort);
161 
162  // One can toggle the comment for the following line on or off to see the
163  // effects of finite send buffer modelling. One can also change the size of
164  // said buffer.
165 
166  //localSocket->SetAttribute("SndBufSize", UintegerValue(4096));
167 
168  //Ask for ASCII and pcap traces of network traffic
169  AsciiTraceHelper ascii;
170  p2p.EnableAsciiAll (ascii.CreateFileStream ("tcp-large-transfer.tr"));
171  p2p.EnablePcapAll ("tcp-large-transfer");
172 
173  // Finally, set up the simulator to run. The 1000 second hard limit is a
174  // failsafe in case some change above causes the simulation to never end
175  Simulator::Stop (Seconds (1000));
176  Simulator::Run ();
178 }
179 
180 
181 //-----------------------------------------------------------------------------
182 //-----------------------------------------------------------------------------
183 //-----------------------------------------------------------------------------
184 //begin implementation of sending "Application"
185 void StartFlow (Ptr<Socket> localSocket,
186  Ipv4Address servAddress,
187  uint16_t servPort)
188 {
189  NS_LOG_LOGIC ("Starting flow at time " << Simulator::Now ().GetSeconds ());
190  localSocket->Connect (InetSocketAddress (servAddress, servPort)); //connect
191 
192  // tell the tcp implementation to call WriteUntilBufferFull again
193  // if we blocked and new tx buffer space becomes available
195  WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ());
196 }
197 
198 void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace)
199 {
200  while (currentTxBytes < totalTxBytes && localSocket->GetTxAvailable () > 0)
201  {
202  uint32_t left = totalTxBytes - currentTxBytes;
203  uint32_t dataOffset = currentTxBytes % writeSize;
204  uint32_t toWrite = writeSize - dataOffset;
205  toWrite = std::min (toWrite, left);
206  toWrite = std::min (toWrite, localSocket->GetTxAvailable ());
207  int amountSent = localSocket->Send (&data[dataOffset], toWrite, 0);
208  if(amountSent < 0)
209  {
210  // we will be called again when new tx space becomes available.
211  return;
212  }
213  currentTxBytes += amountSent;
214  }
216  {
217  localSocket->Close ();
218  }
219 }
#define min(a, b)
Definition: 80211b.c:42
NodeContainer n1n2
holds a vector of ns3::Application pointers.
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
void EnableAsciiAll(std::string prefix)
Enable ascii trace output on each device (which is of the appropriate type) in the set of all nodes c...
Manage ASCII trace files for device models.
Definition: trace-helper.h:163
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
Parse command-line arguments.
Definition: command-line.h:229
Class for representing data rates.
Definition: data-rate.h:89
AttributeValue implementation for DataRate.
Definition: data-rate.h:298
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void InstallAll(void) const
Aggregate IPv4, IPv6, UDP, and TCP stacks to all nodes in the simulation.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
static Ipv4Address GetAny(void)
static void PopulateRoutingTables(void)
Build a routing database and initialize the routing tables of the nodes in the simulation.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
void Add(NodeContainer other)
Append the contents of another NodeContainer to the end of this container.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
void EnablePcapAll(std::string prefix, bool promiscuous=false)
Enable pcap output on each device (which is of the appropriate type) in the set of all nodes created ...
Build a set of PointToPointNetDevice objects.
void SetDeviceAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each NetDevice created by the helper.
void SetChannelAttribute(std::string name, const AttributeValue &value)
Set an attribute value to be propagated to each Channel created by the helper.
NetDeviceContainer Install(NodeContainer c)
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:587
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:121
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual int Close(void)=0
Close a socket.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual uint32_t GetTxAvailable(void) const =0
Returns the number of bytes which can be sent in a single call to Send.
static TypeId GetTypeId(void)
Get the type ID.
AttributeValue implementation for Time.
Definition: nstime.h:1308
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:901
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
cmd
Definition: second.py:35
static const uint32_t totalTxBytes
static const uint32_t writeSize
void WriteUntilBufferFull(Ptr< Socket >, uint32_t)
static uint32_t currentTxBytes
static void CwndTracer(uint32_t oldval, uint32_t newval)
uint8_t data[writeSize]
void StartFlow(Ptr< Socket >, Ipv4Address, uint16_t)
Ptr< PacketSink > sink
Definition: wifi-tcp.cc:56