|
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.pcap-$n-$i" where n and i represent node and interface numbers respectively |
|
29 // Usage (e.g.): ./waf --run tcp-large-transfer |
|
30 |
|
31 #include <ctype.h> |
|
32 #include <iostream> |
|
33 #include <fstream> |
|
34 #include <string> |
|
35 #include <cassert> |
|
36 |
|
37 #include "ns3/command-line.h" |
|
38 #include "ns3/default-value.h" |
|
39 #include "ns3/ptr.h" |
|
40 #include "ns3/random-variable.h" |
|
41 #include "ns3/log.h" |
|
42 |
|
43 #include "ns3/simulator.h" |
|
44 #include "ns3/nstime.h" |
|
45 #include "ns3/data-rate.h" |
|
46 |
|
47 #include "ns3/ascii-trace.h" |
|
48 #include "ns3/pcap-trace.h" |
|
49 #include "ns3/internet-node.h" |
|
50 #include "ns3/point-to-point-channel.h" |
|
51 #include "ns3/point-to-point-net-device.h" |
|
52 #include "ns3/ipv4-address.h" |
|
53 #include "ns3/inet-socket-address.h" |
|
54 #include "ns3/ipv4.h" |
|
55 #include "ns3/socket.h" |
|
56 #include "ns3/ipv4-route.h" |
|
57 #include "ns3/point-to-point-topology.h" |
|
58 #include "ns3/onoff-application.h" |
|
59 #include "ns3/packet-sink.h" |
|
60 #include "ns3/error-model.h" |
|
61 #include "ns3/node-list.h" |
|
62 |
|
63 #include "ns3/tcp.h" |
|
64 |
|
65 using namespace ns3; |
|
66 |
|
67 NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer"); |
|
68 |
|
69 void |
|
70 ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet, |
|
71 const Address &addr) |
|
72 { |
|
73 // g_log is not declared in optimized builds |
|
74 // should convert this to use of some other flag than the logging system |
|
75 #ifdef NS3_LOG_ENABLE |
|
76 if (!g_log.IsNoneEnabled ()) { |
|
77 if (InetSocketAddress::IsMatchingType (addr) ) |
|
78 { |
|
79 InetSocketAddress address = InetSocketAddress::ConvertFrom (addr); |
|
80 std::cout << "PacketSink received size " << |
|
81 packet->GetSize () << " at time " << |
|
82 Simulator::Now ().GetSeconds () << " from address: " << |
|
83 address.GetIpv4 () << std::endl; |
|
84 char buf[2000]; |
|
85 memcpy(buf, packet->PeekData (), packet->GetSize ()); |
|
86 for (uint32_t i=0; i < packet->GetSize (); i++) |
|
87 { |
|
88 std::cout << buf[i]; |
|
89 if (i && i % 60 == 0) |
|
90 std::cout << std::endl; |
|
91 } |
|
92 std::cout << std::endl << std::endl; |
|
93 } |
|
94 } |
|
95 #endif |
|
96 } |
|
97 |
|
98 void CloseConnection (Ptr<Socket> localSocket) |
|
99 { |
|
100 //localSocket->Close (); |
|
101 } |
|
102 |
|
103 void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes, |
|
104 uint16_t servPort) |
|
105 { |
|
106 // NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ()); |
|
107 localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect |
|
108 localSocket->SetConnectCallback (MakeCallback (&CloseConnection), |
|
109 Callback<void, Ptr<Socket> > (), |
|
110 Callback<void, Ptr<Socket> > ()); |
|
111 //we want to close as soon as the connection is established |
|
112 //the tcp state machine and outgoing buffer will assure that |
|
113 //all of the data is delivered |
|
114 |
|
115 // Perform series of 1040 byte writes (this is a multiple of 26 since |
|
116 // we want to detect data splicing in the output stream) |
|
117 uint32_t writeSize = 1040; |
|
118 uint8_t data[writeSize]; |
|
119 while (nBytes > 0) { |
|
120 uint32_t curSize= nBytes > writeSize ? writeSize : nBytes; |
|
121 for(uint32_t i = 0; i < curSize; ++i) |
|
122 { |
|
123 char m = toascii (97 + i % 26); |
|
124 data[i] = m; |
|
125 } |
|
126 localSocket->Send (data, curSize); |
|
127 nBytes -= curSize; |
|
128 } |
|
129 } |
|
130 |
|
131 int main (int argc, char *argv[]) |
|
132 { |
|
133 |
|
134 // Users may find it convenient to turn on explicit debugging |
|
135 // for selected modules; the below lines suggest how to do this |
|
136 // LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL); |
|
137 // LogComponentEnable("TcpSocket", LOG_LEVEL_ALL); |
|
138 // LogComponentEnable("PacketSink", LOG_LEVEL_ALL); |
|
139 //LogComponentEnable("TcpLargeTransfer", LOG_LEVEL_ALL); |
|
140 |
|
141 // Allow the user to override any of the defaults and the above |
|
142 // Bind()s at run-time, via command-line arguments |
|
143 CommandLine::Parse (argc, argv); |
|
144 |
|
145 // Here, we will explicitly create three nodes. In more sophisticated |
|
146 // topologies, we could configure a node factory. |
|
147 Ptr<Node> n0 = Create<InternetNode> (); |
|
148 Ptr<Node> n1 = Create<InternetNode> (); |
|
149 Ptr<Node> n2 = Create<InternetNode> (); |
|
150 |
|
151 // We create the channels first without any IP addressing information |
|
152 Ptr<PointToPointChannel> channel0 = |
|
153 PointToPointTopology::AddPointToPointLink ( |
|
154 n0, n1, DataRate(10000000), MilliSeconds(10)); |
|
155 |
|
156 // Later, we add IP addresses. |
|
157 PointToPointTopology::AddIpv4Addresses ( |
|
158 channel0, n0, Ipv4Address("10.1.3.1"), |
|
159 n1, Ipv4Address("10.1.3.2")); |
|
160 |
|
161 Ptr<PointToPointChannel> channel1 = |
|
162 PointToPointTopology::AddPointToPointLink ( |
|
163 n1, n2, DataRate(10000000), MilliSeconds(10)); |
|
164 |
|
165 PointToPointTopology::AddIpv4Addresses ( |
|
166 channel1, n1, Ipv4Address("10.1.2.1"), |
|
167 n2, Ipv4Address("10.1.2.2")); |
|
168 |
|
169 // Finally, we add static routes. These three steps (Channel and |
|
170 // NetDevice creation, IP Address assignment, and routing) are |
|
171 // separated because there may be a need to postpone IP Address |
|
172 // assignment (emulation) or modify to use dynamic routing |
|
173 PointToPointTopology::AddIpv4Routes(n0, n1, channel0); |
|
174 PointToPointTopology::AddIpv4Routes(n1, n2, channel1); |
|
175 Ptr<Ipv4> ipv4; |
|
176 ipv4 = n0->QueryInterface<Ipv4> (); |
|
177 ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1); |
|
178 ipv4 = n2->QueryInterface<Ipv4> (); |
|
179 ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1); |
|
180 |
|
181 |
|
182 /////////////////////////////////////////////////////////////////////////// |
|
183 // Simulation 1 |
|
184 // |
|
185 // Send 2000000 bytes over a connection to server port 50000 at time 0 |
|
186 // Should observe SYN exchange, a lot of data segments, and FIN exchange |
|
187 // |
|
188 /////////////////////////////////////////////////////////////////////////// |
|
189 |
|
190 int nBytes = 2000000; |
|
191 uint16_t servPort = 50000; |
|
192 |
|
193 Ptr<SocketFactory> socketFactory = |
|
194 n0->QueryInterface<SocketFactory> (); |
|
195 Ptr<Socket> localSocket = socketFactory->CreateSocket (); |
|
196 localSocket->Bind (); |
|
197 |
|
198 // Create a packet sink to receive these packets |
|
199 Ptr<PacketSink> sink = Create<PacketSink> ( |
|
200 n2, |
|
201 InetSocketAddress (Ipv4Address::GetAny (), servPort), |
|
202 "Tcp"); |
|
203 sink->Start (Seconds (0.0)); |
|
204 sink->Stop (Seconds (100.0)); |
|
205 |
|
206 Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes, |
|
207 servPort); |
|
208 |
|
209 // Configure tracing of all enqueue, dequeue, and NetDevice receive events |
|
210 // Trace output will be sent to the simple-examples.tr file |
|
211 AsciiTrace asciitrace ("tcp-large-transfer.tr"); |
|
212 asciitrace.TraceAllQueues (); |
|
213 asciitrace.TraceAllNetDeviceRx (); |
|
214 |
|
215 |
|
216 // Also configure some tcpdump traces; each interface will be traced |
|
217 // The output files will be named |
|
218 // simple-examples.pcap-<nodeId>-<interfaceId> |
|
219 // and can be read by the "tcpdump -r" command (use "-tt" option to |
|
220 // display timestamps correctly) |
|
221 PcapTrace pcaptrace ("tcp-large-transfer.pcap"); |
|
222 pcaptrace.TraceAllIp (); |
|
223 |
|
224 NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink)); |
|
225 |
|
226 Simulator::StopAt (Seconds(1000)); |
|
227 Simulator::Run (); |
|
228 Simulator::Destroy (); |
|
229 } |