A Discrete-Event Network Simulator
API
tcp-validation.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2019 Cable Television Laboratories, Inc.
4 * Copyright (c) 2020 Tom Henderson (adapted for DCTCP testing)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer,
11 * without modification.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The names of the authors may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * Alternatively, provided that this notice is retained in full, this
19 * software may be distributed under the terms of the GNU General
20 * Public License ("GPL") version 2, in which case the provisions of the
21 * GPL apply INSTEAD OF those given above.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36// This program is designed to observe long-running TCP congestion control
37// behavior over a configurable bottleneck link. The program is also
38// instrumented to check progam data against validated results, when
39// the validation option is enabled.
40//
41// ---> downstream (primary data transfer from servers to clients)
42// <--- upstream (return acks and ICMP echo response)
43//
44// ---- bottleneck link ----
45// servers ---| WR |--------------------| LR |--- clients
46// ---- ----
47// ns-3 node IDs:
48// nodes 0-2 3 4 5-7
49//
50// - The box WR is notionally a WAN router, aggregating all server links
51// - The box LR is notionally a LAN router, aggregating all client links
52// - Three servers are connected to WR, three clients are connected to LR
53//
54// clients and servers are configured for ICMP measurements and TCP throughput
55// and latency measurements in the downstream direction
56//
57// All link rates are enforced by a point-to-point (P2P) ns-3 model with full
58// duplex operation. Dynamic queue limits
59// (BQL) are enabled to allow for queueing to occur at the priority queue layer;
60// the notional P2P hardware device queue is limited to three packets.
61//
62// One-way link delays and link rates
63// -----------------------------------
64// (1) server to WR links, 1000 Mbps, 1us delay
65// (2) bottleneck link: configurable rate, configurable delay
66// (3) client to LR links, 1000 Mbps, 1us delay
67//
68// By default, ns-3 FQ-CoDel model is installed on all interfaces, but
69// the bottleneck queue uses CoDel by default and is configurable.
70//
71// The ns-3 FQ-CoDel model uses ns-3 defaults:
72// - 100ms interval
73// - 5ms target
74// - drop batch size of 64 packets
75// - minbytes of 1500
76//
77// Default simulation time is 70 sec. For single flow experiments, the flow is
78// started at simulation time 5 sec; if a second flow is used, it starts
79// at 15 sec.
80//
81// ping frequency is set at 100ms.
82//
83// A command-line option to enable a step-threshold CE threshold
84// from the CoDel queue model is provided.
85//
86// Measure:
87// - ping RTT
88// - TCP RTT estimate
89// - TCP throughput
90//
91// IPv4 addressing
92// ----------------------------
93// pingServer 10.1.1.2 (ping source)
94// firstServer 10.1.2.2 (data sender)
95// secondServer 10.1.3.2 (data sender)
96// pingClient 192.168.1.2
97// firstClient 192.168.2.2
98// secondClient 192.168.3.2
99//
100// Program Options:
101// ---------------
102// --firstTcpType: first TCP type (cubic, dctcp, or reno) [cubic]
103// --secondTcpType: second TCP type (cubic, dctcp, or reno) []
104// --queueType: bottleneck queue type (fq, codel, pie, or red) [codel]
105// --baseRtt: base RTT [+80ms]
106// --ceThreshold: CoDel CE threshold (for DCTCP) [+1ms]
107// --linkRate: data rate of bottleneck link [50000000bps]
108// --stopTime: simulation stop time [+1.16667min]
109// --queueUseEcn: use ECN on queue [false]
110// --enablePcap: enable Pcap [false]
111// --validate: validation case to run []
112//
113// validation cases (and syntax of how to run):
114// ------------
115// Case 'dctcp-10ms': DCTCP single flow, 10ms base RTT, 50 Mbps link, ECN enabled, CoDel:
116// ./ns3 run 'tcp-validation --firstTcpType=dctcp --linkRate=50Mbps --baseRtt=10ms --queueUseEcn=1 --stopTime=15s --validate=1 --validation=dctcp-10ms'
117// - Throughput between 48 Mbps and 49 Mbps for time greater than 5.6s
118// - DCTCP alpha below 0.1 for time greater than 5.4s
119// - DCTCP alpha between 0.06 and 0.085 for time greater than 7s
120//
121// Case 'dctcp-80ms': DCTCP single flow, 80ms base RTT, 50 Mbps link, ECN enabled, CoDel:
122// ./ns3 run 'tcp-validation --firstTcpType=dctcp --linkRate=50Mbps --baseRtt=80ms --queueUseEcn=1 --stopTime=40s --validate=1 --validation=dctcp-80ms'
123// - Throughput less than 20 Mbps for time less than 14s
124// - Throughput less than 48 Mbps for time less than 30s
125// - Throughput between 47.5 Mbps and 48.5 for time greater than 32s
126// - DCTCP alpha above 0.1 for time less than 7.5
127// - DCTCP alpha below 0.01 for time greater than 11 and less than 30
128// - DCTCP alpha between 0.015 and 0.025 for time greater than 34
129//
130// Case 'cubic-50ms-no-ecn': CUBIC single flow, 50ms base RTT, 50 Mbps link, ECN disabled, CoDel:
131// ./ns3 run 'tcp-validation --firstTcpType=cubic --linkRate=50Mbps --baseRtt=50ms --queueUseEcn=0 --stopTime=20s --validate=1 --validation=cubic-50ms-no-ecn'
132// - Maximum value of cwnd is 511 segments at 5.4593 seconds
133// - cwnd decreases to 173 segments at 5.80304 seconds
134// - cwnd reaches another local maxima around 14.2815 seconds of 236 segments
135// - cwnd reaches a second maximum around 18.048 seconds of 234 segments
136//
137// Case 'cubic-50ms-ecn': CUBIC single flow, 50ms base RTT, 50 Mbps link, ECN enabled, CoDel:
138// ./ns3 run 'tcp-validation --firstTcpType=cubic --linkRate=50Mbps --baseRtt=50ms --queueUseEcn=0 --stopTime=20s --validate=1 --validation=cubic-50ms-no-ecn'
139// - Maximum value of cwnd is 511 segments at 5.4593 seconds
140// - cwnd decreases to 173 segments at 5.7939 seconds
141// - cwnd reaches another local maxima around 14.3477 seconds of 236 segments
142// - cwnd reaches a second maximum around 18.064 seconds of 234 segments
143
144#include <iostream>
145#include <fstream>
146#include <string>
147#include "ns3/core-module.h"
148#include "ns3/network-module.h"
149#include "ns3/applications-module.h"
150#include "ns3/traffic-control-module.h"
151#include "ns3/internet-module.h"
152#include "ns3/internet-apps-module.h"
153#include "ns3/point-to-point-module.h"
154
155using namespace ns3;
156
157NS_LOG_COMPONENT_DEFINE ("TcpValidation");
158
159// These variables are declared outside of main() so that they can
160// be used in trace sinks.
165std::string g_validate = ""; // Empty string disables this mode
167
168void
169TraceFirstCwnd (std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
170{
171 // TCP segment size is configured below to be 1448 bytes
172 // so that we can report cwnd in units of segments
173 if (g_validate == "")
174 {
175 *ofStream << Simulator::Now ().GetSeconds () << " " << static_cast<double> (newCwnd) / 1448 << std::endl;
176 }
177 // Validation checks; both the ECN enabled and disabled cases are similar
178 if (g_validate == "cubic-50ms-no-ecn" || g_validate == "cubic-50ms-ecn")
179 {
180 double now = Simulator::Now ().GetSeconds ();
181 double cwnd = static_cast<double> (newCwnd) / 1448;
182 if ((now > 5.43) && (now < 5.465) && (cwnd < 500))
183 {
184 NS_LOG_WARN ("now " << Now ().As (Time::S) << " cwnd " << cwnd << " (expected >= 500)");
185 g_validationFailed = true;
186 }
187 else if ((now > 5.795) && (now < 6) && (cwnd > 190))
188 {
189 NS_LOG_WARN ("now " << Now ().As (Time::S) << " cwnd " << cwnd << " (expected <= 190)");
190 g_validationFailed = true;
191 }
192 else if ((now > 14) && (now < 14.197) && (cwnd < 224))
193 {
194 NS_LOG_WARN ("now " << Now ().As (Time::S) << " cwnd " << cwnd << " (expected >= 224)");
195 g_validationFailed = true;
196 }
197 else if ((now > 17) && (now < 18.026) && (cwnd < 212))
198 {
199 NS_LOG_WARN ("now " << Now ().As (Time::S) << " cwnd " << cwnd << " (expected >= 212)");
200 g_validationFailed = true;
201 }
202 }
203}
204
205void
206TraceFirstDctcp (std::ofstream* ofStream, uint32_t bytesMarked, uint32_t bytesAcked, double alpha)
207{
208 if (g_validate == "")
209 {
210 *ofStream << Simulator::Now ().GetSeconds () << " " << alpha << std::endl;
211 }
212 // Validation checks
213 if (g_validate == "dctcp-80ms")
214 {
215 double now = Simulator::Now ().GetSeconds ();
216 if ((now < 7.5) && (alpha < 0.1))
217 {
218 NS_LOG_WARN ("now " << Now ().As (Time::S) << " alpha " << alpha << " (expected >= 0.1)");
219 g_validationFailed = true;
220 }
221 else if ((now > 11) && (now < 30) && (alpha > 0.01))
222 {
223 NS_LOG_WARN ("now " << Now ().As (Time::S) << " alpha " << alpha << " (expected <= 0.01)");
224 g_validationFailed = true;
225 }
226 else if ((now > 34) && (alpha < 0.015) && (alpha > 0.025))
227 {
228 NS_LOG_WARN ("now " << Now ().As (Time::S) << " alpha " << alpha << " (expected 0.015 <= alpha <= 0.025)");
229 g_validationFailed = true;
230 }
231 }
232 else if (g_validate == "dctcp-10ms")
233 {
234 double now = Simulator::Now ().GetSeconds ();
235 if ((now > 5.6) && (alpha > 0.1))
236 {
237 NS_LOG_WARN ("now " << Now ().As (Time::S) << " alpha " << alpha << " (expected <= 0.1)");
238 g_validationFailed = true;
239 }
240 if ((now > 7) && ((alpha > 0.09) || (alpha < 0.055)))
241 {
242 NS_LOG_WARN ("now " << Now ().As (Time::S) << " alpha " << alpha << " (expected 0.09 <= alpha <= 0.055)");
243 g_validationFailed = true;
244 }
245 }
246}
247
248void
249TraceFirstRtt (std::ofstream* ofStream, Time oldRtt, Time newRtt)
250{
251 if (g_validate == "")
252 {
253 *ofStream << Simulator::Now ().GetSeconds () << " " << newRtt.GetSeconds () * 1000 << std::endl;
254 }
255}
256
257void
258TraceSecondCwnd (std::ofstream* ofStream, uint32_t oldCwnd, uint32_t newCwnd)
259{
260 // TCP segment size is configured below to be 1448 bytes
261 // so that we can report cwnd in units of segments
262 if (g_validate == "")
263 {
264 *ofStream << Simulator::Now ().GetSeconds () << " " << static_cast<double> (newCwnd) / 1448 << std::endl;
265 }
266}
267
268void
269TraceSecondRtt (std::ofstream* ofStream, Time oldRtt, Time newRtt)
270{
271 if (g_validate == "")
272 {
273 *ofStream << Simulator::Now ().GetSeconds () << " " << newRtt.GetSeconds () * 1000 << std::endl;
274 }
275}
276
277void
278TraceSecondDctcp (std::ofstream* ofStream, uint32_t bytesMarked, uint32_t bytesAcked, double alpha)
279{
280 if (g_validate == "")
281 {
282 *ofStream << Simulator::Now ().GetSeconds () << " " << alpha << std::endl;
283 }
284}
285
286void
287TracePingRtt (std::ofstream* ofStream, Time rtt)
288{
289 if (g_validate == "")
290 {
291 *ofStream << Simulator::Now ().GetSeconds () << " " << rtt.GetSeconds () * 1000 << std::endl;
292 }
293}
294
295void
297{
298 g_firstBytesReceived += packet->GetSize ();
299}
300
301void
303{
304 g_secondBytesReceived += packet->GetSize ();
305}
306
307void
308TraceQueueDrop (std::ofstream* ofStream, Ptr<const QueueDiscItem> item)
309{
310 if (g_validate == "")
311 {
312 *ofStream << Simulator::Now ().GetSeconds () << " " << std::hex << item->Hash () << std::endl;
313 }
315}
316
317void
318TraceQueueMark (std::ofstream* ofStream, Ptr<const QueueDiscItem> item, const char* reason)
319{
320 if (g_validate == "")
321 {
322 *ofStream << Simulator::Now ().GetSeconds () << " " << std::hex << item->Hash () << std::endl;
323 }
325}
326
327void
328TraceQueueLength (std::ofstream* ofStream, DataRate queueLinkRate, uint32_t oldVal, uint32_t newVal)
329{
330 // output in units of ms
331 if (g_validate == "")
332 {
333 *ofStream << Simulator::Now ().GetSeconds () << " " << std::fixed << static_cast<double> (newVal * 8) / (queueLinkRate.GetBitRate () / 1000) << std::endl;
334 }
335}
336
337void
338TraceMarksFrequency (std::ofstream* ofStream, Time marksSamplingInterval)
339{
340 if (g_validate == "")
341 {
342 *ofStream << Simulator::Now ().GetSeconds () << " " << g_marksObserved << std::endl;
343 }
344 g_marksObserved = 0;
345 Simulator::Schedule (marksSamplingInterval, &TraceMarksFrequency, ofStream, marksSamplingInterval);
346}
347
348void
349TraceFirstThroughput (std::ofstream* ofStream, Time throughputInterval)
350{
351 double throughput = g_firstBytesReceived * 8 / throughputInterval.GetSeconds () / 1e6;
352 if (g_validate == "")
353 {
354 *ofStream << Simulator::Now ().GetSeconds () << " " << throughput << std::endl;
355 }
357 Simulator::Schedule (throughputInterval, &TraceFirstThroughput, ofStream, throughputInterval);
358 if (g_validate == "dctcp-80ms")
359 {
360 double now = Simulator::Now ().GetSeconds ();
361 if ((now < 14) && (throughput > 20))
362 {
363 NS_LOG_WARN ("now " << Now ().As (Time::S) << " throughput " << throughput << " (expected <= 20)");
364 g_validationFailed = true;
365 }
366 if ((now < 30) && (throughput > 48))
367 {
368 NS_LOG_WARN ("now " << Now ().As (Time::S) << " throughput " << throughput << " (expected <= 48)");
369 g_validationFailed = true;
370 }
371 if ((now > 32) && ((throughput < 47.5) || (throughput > 48.5)))
372 {
373 NS_LOG_WARN ("now " << Now ().As (Time::S) << " throughput " << throughput << " (expected 47.5 <= throughput <= 48.5)");
374 g_validationFailed = true;
375 }
376 }
377 else if (g_validate == "dctcp-10ms")
378 {
379 double now = Simulator::Now ().GetSeconds ();
380 if ((now > 5.6) && ((throughput < 48) || (throughput > 49)))
381 {
382 NS_LOG_WARN ("now " << Now ().As (Time::S) << " throughput " << throughput << " (expected 48 <= throughput <= 49)");
383 g_validationFailed = true;
384 }
385 }
386}
387
388void
389TraceSecondThroughput (std::ofstream* ofStream, Time throughputInterval)
390{
391 if (g_validate == "")
392 {
393 *ofStream << Simulator::Now ().GetSeconds () << " " << g_secondBytesReceived * 8 / throughputInterval.GetSeconds () / 1e6 << std::endl;
394 }
396 Simulator::Schedule (throughputInterval, &TraceSecondThroughput, ofStream, throughputInterval);
397}
398
399void
400ScheduleFirstTcpCwndTraceConnection (std::ofstream* ofStream)
401{
402 Config::ConnectWithoutContextFailSafe ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeBoundCallback (&TraceFirstCwnd, ofStream));
403}
404
405void
406ScheduleFirstTcpRttTraceConnection (std::ofstream* ofStream)
407{
408 Config::ConnectWithoutContextFailSafe ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/RTT", MakeBoundCallback (&TraceFirstRtt, ofStream));
409}
410
411void
412ScheduleFirstDctcpTraceConnection (std::ofstream* ofStream)
413{
414 Config::ConnectWithoutContextFailSafe ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionOps/$ns3::TcpDctcp/CongestionEstimate", MakeBoundCallback (&TraceFirstDctcp, ofStream));
415}
416
417void
418ScheduleSecondDctcpTraceConnection (std::ofstream* ofStream)
419{
420 Config::ConnectWithoutContextFailSafe ("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/CongestionOps/$ns3::TcpDctcp/CongestionEstimate", MakeBoundCallback (&TraceSecondDctcp, ofStream));
421}
422
423void
425{
426 Config::ConnectWithoutContextFailSafe ("/NodeList/6/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&TraceFirstRx));
427}
428
429void
431{
432 Config::ConnectWithoutContext ("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeBoundCallback (&TraceSecondCwnd, ofStream));
433}
434
435void
436ScheduleSecondTcpRttTraceConnection (std::ofstream* ofStream)
437{
438 Config::ConnectWithoutContext ("/NodeList/2/$ns3::TcpL4Protocol/SocketList/0/RTT", MakeBoundCallback (&TraceSecondRtt, ofStream));
439}
440
441void
443{
444 Config::ConnectWithoutContext ("/NodeList/7/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback (&TraceSecondRx));
445}
446
447int
448main (int argc, char *argv[])
449{
451 // variables not configured at command line //
453 uint32_t pingSize = 100; // bytes
454 bool enableSecondTcp = false;
455 bool enableLogging = false;
456 Time pingInterval = MilliSeconds (100);
457 Time marksSamplingInterval = MilliSeconds (100);
458 Time throughputSamplingInterval = MilliSeconds (200);
459 std::string pingTraceFile = "tcp-validation-ping.dat";
460 std::string firstTcpRttTraceFile = "tcp-validation-first-tcp-rtt.dat";
461 std::string firstTcpCwndTraceFile = "tcp-validation-first-tcp-cwnd.dat";
462 std::string firstDctcpTraceFile = "tcp-validation-first-dctcp-alpha.dat";
463 std::string firstTcpThroughputTraceFile = "tcp-validation-first-tcp-throughput.dat";
464 std::string secondTcpRttTraceFile = "tcp-validation-second-tcp-rtt.dat";
465 std::string secondTcpCwndTraceFile = "tcp-validation-second-tcp-cwnd.dat";
466 std::string secondTcpThroughputTraceFile = "tcp-validation-second-tcp-throughput.dat";
467 std::string secondDctcpTraceFile = "tcp-validation-second-dctcp-alpha.dat";
468 std::string queueMarkTraceFile = "tcp-validation-queue-mark.dat";
469 std::string queueDropTraceFile = "tcp-validation-queue-drop.dat";
470 std::string queueMarksFrequencyTraceFile = "tcp-validation-queue-marks-frequency.dat";
471 std::string queueLengthTraceFile = "tcp-validation-queue-length.dat";
472
474 // variables configured at command line //
476 std::string firstTcpType = "cubic";
477 std::string secondTcpType = "";
478 std::string queueType = "codel";
479 Time stopTime = Seconds (70);
480 Time baseRtt = MilliSeconds (80);
481 DataRate linkRate ("50Mbps");
482 bool queueUseEcn = false;
483 Time ceThreshold = MilliSeconds (1);
484 bool enablePcap = false;
485
487 // Override ns-3 defaults //
489 Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1448));
490 // Increase default buffer sizes to improve throughput over long delay paths
491 //Config::SetDefault ("ns3::TcpSocket::SndBufSize",UintegerValue (8192000));
492 //Config::SetDefault ("ns3::TcpSocket::RcvBufSize",UintegerValue (8192000));
493 Config::SetDefault ("ns3::TcpSocket::SndBufSize",UintegerValue (32768000));
494 Config::SetDefault ("ns3::TcpSocket::RcvBufSize",UintegerValue (32768000));
495 Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (10));
496 Config::SetDefault ("ns3::TcpL4Protocol::RecoveryType", TypeIdValue (TcpPrrRecovery::GetTypeId ()));
497
499 // command-line argument parsing //
501 CommandLine cmd (__FILE__);
502 cmd.AddValue ("firstTcpType", "first TCP type (cubic, dctcp, or reno)", firstTcpType);
503 cmd.AddValue ("secondTcpType", "second TCP type (cubic, dctcp, or reno)", secondTcpType);
504 cmd.AddValue ("queueType", "bottleneck queue type (fq, codel, pie, or red)", queueType);
505 cmd.AddValue ("baseRtt", "base RTT", baseRtt);
506 cmd.AddValue ("ceThreshold", "CoDel CE threshold (for DCTCP)", ceThreshold);
507 cmd.AddValue ("linkRate", "data rate of bottleneck link", linkRate);
508 cmd.AddValue ("stopTime", "simulation stop time", stopTime);
509 cmd.AddValue ("queueUseEcn", "use ECN on queue", queueUseEcn);
510 cmd.AddValue ("enablePcap", "enable Pcap", enablePcap);
511 cmd.AddValue ("validate", "validation case to run", g_validate);
512 cmd.Parse (argc, argv);
513
514 // If validation is selected, perform some configuration checks
515 if (g_validate != "")
516 {
517 NS_ABORT_MSG_UNLESS (g_validate == "dctcp-10ms"
518 || g_validate == "dctcp-80ms"
519 || g_validate == "cubic-50ms-no-ecn"
520 || g_validate == "cubic-50ms-ecn", "Unknown test");
521 if (g_validate == "dctcp-10ms" || g_validate == "dctcp-80ms")
522 {
523 NS_ABORT_MSG_UNLESS (firstTcpType == "dctcp", "Incorrect TCP");
524 NS_ABORT_MSG_UNLESS (secondTcpType == "", "Incorrect TCP");
525 NS_ABORT_MSG_UNLESS (linkRate == DataRate ("50Mbps"), "Incorrect data rate");
526 NS_ABORT_MSG_UNLESS (queueUseEcn == true, "Incorrect ECN configuration");
527 NS_ABORT_MSG_UNLESS (stopTime >= Seconds (15), "Incorrect stopTime");
528 if (g_validate == "dctcp-10ms")
529 {
530 NS_ABORT_MSG_UNLESS (baseRtt == MilliSeconds (10), "Incorrect RTT");
531 }
532 else if (g_validate == "dctcp-80ms")
533 {
534 NS_ABORT_MSG_UNLESS (baseRtt == MilliSeconds (80), "Incorrect RTT");
535 }
536 }
537 else if (g_validate == "cubic-50ms-no-ecn" || g_validate == "cubic-50ms-ecn")
538 {
539 NS_ABORT_MSG_UNLESS (firstTcpType == "cubic", "Incorrect TCP");
540 NS_ABORT_MSG_UNLESS (secondTcpType == "", "Incorrect TCP");
541 NS_ABORT_MSG_UNLESS (baseRtt == MilliSeconds (50), "Incorrect RTT");
542 NS_ABORT_MSG_UNLESS (linkRate == DataRate ("50Mbps"), "Incorrect data rate");
543 NS_ABORT_MSG_UNLESS (stopTime >= Seconds (20), "Incorrect stopTime");
544 if (g_validate == "cubic-50ms-no-ecn")
545 {
546 NS_ABORT_MSG_UNLESS (queueUseEcn == false, "Incorrect ECN configuration");
547 }
548 else if (g_validate == "cubic-50ms-ecn")
549 {
550 NS_ABORT_MSG_UNLESS (queueUseEcn == true, "Incorrect ECN configuration");
551 }
552 }
553 }
554
555 if (enableLogging)
556 {
559 }
560
561 Time oneWayDelay = baseRtt / 2;
562
563 TypeId firstTcpTypeId;
564 if (firstTcpType == "reno")
565 {
566 firstTcpTypeId = TcpLinuxReno::GetTypeId ();
567 }
568 else if (firstTcpType == "cubic")
569 {
570 firstTcpTypeId = TcpCubic::GetTypeId ();
571 }
572 else if (firstTcpType == "dctcp")
573 {
574 firstTcpTypeId = TcpDctcp::GetTypeId ();
575 Config::SetDefault ("ns3::CoDelQueueDisc::CeThreshold", TimeValue (ceThreshold));
576 Config::SetDefault ("ns3::FqCoDelQueueDisc::CeThreshold", TimeValue (ceThreshold));
577 if (queueUseEcn == false)
578 {
579 std::cout << "Warning: using DCTCP with queue ECN disabled" << std::endl;
580 }
581 }
582 else
583 {
584 NS_FATAL_ERROR ("Fatal error: tcp unsupported");
585 }
586 TypeId secondTcpTypeId;
587 if (secondTcpType == "reno")
588 {
589 enableSecondTcp = true;
590 secondTcpTypeId = TcpLinuxReno::GetTypeId ();
591 }
592 else if (secondTcpType == "cubic")
593 {
594 enableSecondTcp = true;
595 secondTcpTypeId = TcpCubic::GetTypeId ();
596 }
597 else if (secondTcpType == "dctcp")
598 {
599 enableSecondTcp = true;
600 secondTcpTypeId = TcpDctcp::GetTypeId ();
601 }
602 else if (secondTcpType == "")
603 {
604 enableSecondTcp = false;
605 NS_LOG_DEBUG ("No second TCP selected");
606 }
607 else
608 {
609 NS_FATAL_ERROR ("Fatal error: tcp unsupported");
610 }
611 TypeId queueTypeId;
612 if (queueType == "fq")
613 {
614 queueTypeId = FqCoDelQueueDisc::GetTypeId ();
615 }
616 else if (queueType == "codel")
617 {
618 queueTypeId = CoDelQueueDisc::GetTypeId ();
619 }
620 else if (queueType == "pie")
621 {
622 queueTypeId = PieQueueDisc::GetTypeId ();
623 }
624 else if (queueType == "red")
625 {
626 queueTypeId = RedQueueDisc::GetTypeId ();
627 }
628 else
629 {
630 NS_FATAL_ERROR ("Fatal error: queueType unsupported");
631 }
632
633 if (queueUseEcn)
634 {
635 Config::SetDefault ("ns3::CoDelQueueDisc::UseEcn", BooleanValue (true));
636 Config::SetDefault ("ns3::FqCoDelQueueDisc::UseEcn", BooleanValue (true));
637 Config::SetDefault ("ns3::PieQueueDisc::UseEcn", BooleanValue (true));
638 Config::SetDefault ("ns3::RedQueueDisc::UseEcn", BooleanValue (true));
639 }
640 // Enable TCP to use ECN regardless
641 Config::SetDefault ("ns3::TcpSocketBase::UseEcn", StringValue ("On"));
642
643 // Report on configuration
644 if (enableSecondTcp)
645 {
646 NS_LOG_DEBUG ("first TCP: " << firstTcpTypeId.GetName () << "; second TCP: " << secondTcpTypeId.GetName () << "; queue: " << queueTypeId.GetName () << "; ceThreshold: " << ceThreshold.GetSeconds () * 1000 << "ms");
647 }
648 else
649 {
650 NS_LOG_DEBUG ("first TCP: " << firstTcpTypeId.GetName () << "; queue: " << queueTypeId.GetName () << "; ceThreshold: " << ceThreshold.GetSeconds () * 1000 << "ms");
651 }
652
653 // Write traces only if we are not in validation mode (g_validate == "")
654 std::ofstream pingOfStream;
655 std::ofstream firstTcpRttOfStream;
656 std::ofstream firstTcpCwndOfStream;
657 std::ofstream firstTcpThroughputOfStream;
658 std::ofstream firstTcpDctcpOfStream;
659 std::ofstream secondTcpRttOfStream;
660 std::ofstream secondTcpCwndOfStream;
661 std::ofstream secondTcpThroughputOfStream;
662 std::ofstream secondTcpDctcpOfStream;
663 std::ofstream queueDropOfStream;
664 std::ofstream queueMarkOfStream;
665 std::ofstream queueMarksFrequencyOfStream;
666 std::ofstream queueLengthOfStream;
667 if (g_validate == "")
668 {
669 pingOfStream.open (pingTraceFile.c_str (), std::ofstream::out);
670 firstTcpRttOfStream.open (firstTcpRttTraceFile.c_str (), std::ofstream::out);
671 firstTcpCwndOfStream.open (firstTcpCwndTraceFile.c_str (), std::ofstream::out);
672 firstTcpThroughputOfStream.open (firstTcpThroughputTraceFile.c_str (), std::ofstream::out);
673 if (firstTcpType == "dctcp")
674 {
675 firstTcpDctcpOfStream.open (firstDctcpTraceFile.c_str (), std::ofstream::out);
676 }
677 if (enableSecondTcp)
678 {
679 secondTcpRttOfStream.open (secondTcpRttTraceFile.c_str (), std::ofstream::out);
680 secondTcpCwndOfStream.open (secondTcpCwndTraceFile.c_str (), std::ofstream::out);
681 secondTcpThroughputOfStream.open (secondTcpThroughputTraceFile.c_str (), std::ofstream::out);
682 if (secondTcpType == "dctcp")
683 {
684 secondTcpDctcpOfStream.open (secondDctcpTraceFile.c_str (), std::ofstream::out);
685 }
686 }
687 queueDropOfStream.open (queueDropTraceFile.c_str (), std::ofstream::out);
688 queueMarkOfStream.open (queueMarkTraceFile.c_str (), std::ofstream::out);
689 queueMarksFrequencyOfStream.open (queueMarksFrequencyTraceFile.c_str (), std::ofstream::out);
690 queueLengthOfStream.open (queueLengthTraceFile.c_str (), std::ofstream::out);
691 }
692
694 // scenario setup //
696 Ptr<Node> pingServer = CreateObject<Node> ();
697 Ptr<Node> firstServer = CreateObject<Node> ();
698 Ptr<Node> secondServer = CreateObject<Node> ();
699 Ptr<Node> wanRouter = CreateObject<Node> ();
700 Ptr<Node> lanRouter = CreateObject<Node> ();
701 Ptr<Node> pingClient = CreateObject<Node> ();
702 Ptr<Node> firstClient = CreateObject<Node> ();
703 Ptr<Node> secondClient = CreateObject<Node> ();
704
705 // Device containers
706 NetDeviceContainer pingServerDevices;
707 NetDeviceContainer firstServerDevices;
708 NetDeviceContainer secondServerDevices;
709 NetDeviceContainer wanLanDevices;
710 NetDeviceContainer pingClientDevices;
711 NetDeviceContainer firstClientDevices;
712 NetDeviceContainer secondClientDevices;
713
715 p2p.SetQueue ("ns3::DropTailQueue", "MaxSize", QueueSizeValue (QueueSize ("3p")));
716 p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("1000Mbps")));
717 // Add delay only on the WAN links
718 p2p.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));
719 pingServerDevices = p2p.Install (wanRouter, pingServer);
720 firstServerDevices = p2p.Install (wanRouter, firstServer);
721 secondServerDevices = p2p.Install (wanRouter, secondServer);
722 p2p.SetChannelAttribute ("Delay", TimeValue (oneWayDelay));
723 wanLanDevices = p2p.Install (wanRouter, lanRouter);
724 p2p.SetQueue ("ns3::DropTailQueue", "MaxSize", QueueSizeValue (QueueSize ("3p")));
725 p2p.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));
726 pingClientDevices = p2p.Install (lanRouter, pingClient);
727 firstClientDevices = p2p.Install (lanRouter, firstClient);
728 secondClientDevices = p2p.Install (lanRouter, secondClient);
729
730 // Limit the bandwidth on the wanRouter->lanRouter interface
732 p->SetAttribute ("DataRate", DataRateValue (linkRate));
733
734 InternetStackHelper stackHelper;
735 stackHelper.Install (pingServer);
736 Ptr<TcpL4Protocol> proto;
737 stackHelper.Install (firstServer);
738 proto = firstServer->GetObject<TcpL4Protocol> ();
739 proto->SetAttribute ("SocketType", TypeIdValue (firstTcpTypeId));
740 stackHelper.Install (secondServer);
741 stackHelper.Install (wanRouter);
742 stackHelper.Install (lanRouter);
743 stackHelper.Install (pingClient);
744
745 stackHelper.Install (firstClient);
746 // Set the per-node TCP type here
747 proto = firstClient->GetObject<TcpL4Protocol> ();
748 proto->SetAttribute ("SocketType", TypeIdValue (firstTcpTypeId));
749 stackHelper.Install (secondClient);
750
751 if (enableSecondTcp)
752 {
753 proto = secondClient->GetObject<TcpL4Protocol> ();
754 proto->SetAttribute ("SocketType", TypeIdValue (secondTcpTypeId));
755 proto = secondServer->GetObject<TcpL4Protocol> ();
756 proto->SetAttribute ("SocketType", TypeIdValue (secondTcpTypeId));
757 }
758
759 // InternetStackHelper will install a base TrafficControLayer on the node,
760 // but the Ipv4AddressHelper below will install the default FqCoDelQueueDisc
761 // on all single device nodes. The below code overrides the configuration
762 // that is normally done by the Ipv4AddressHelper::Install() method by
763 // instead explicitly configuring the queue discs we want on each device.
765 tchFq.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
766 tchFq.SetQueueLimits ("ns3::DynamicQueueLimits", "HoldTime", StringValue ("1ms"));
767 tchFq.Install (pingServerDevices);
768 tchFq.Install (firstServerDevices);
769 tchFq.Install (secondServerDevices);
770 tchFq.Install (wanLanDevices.Get (1));
771 tchFq.Install (pingClientDevices);
772 tchFq.Install (firstClientDevices);
773 tchFq.Install (secondClientDevices);
774 // Install queue for bottleneck link
775 TrafficControlHelper tchBottleneck;
776 tchBottleneck.SetRootQueueDisc (queueTypeId.GetName ());
777 tchBottleneck.SetQueueLimits ("ns3::DynamicQueueLimits", "HoldTime", StringValue ("1ms"));
778 tchBottleneck.Install (wanLanDevices.Get (0));
779
781 ipv4.SetBase ("10.1.1.0", "255.255.255.0");
782 Ipv4InterfaceContainer pingServerIfaces = ipv4.Assign (pingServerDevices);
783 ipv4.SetBase ("10.1.2.0", "255.255.255.0");
784 Ipv4InterfaceContainer firstServerIfaces = ipv4.Assign (firstServerDevices);
785 ipv4.SetBase ("10.1.3.0", "255.255.255.0");
786 Ipv4InterfaceContainer secondServerIfaces = ipv4.Assign (secondServerDevices);
787 ipv4.SetBase ("172.16.1.0", "255.255.255.0");
788 Ipv4InterfaceContainer wanLanIfaces = ipv4.Assign (wanLanDevices);
789 ipv4.SetBase ("192.168.1.0", "255.255.255.0");
790 Ipv4InterfaceContainer pingClientIfaces = ipv4.Assign (pingClientDevices);
791 ipv4.SetBase ("192.168.2.0", "255.255.255.0");
792 Ipv4InterfaceContainer firstClientIfaces = ipv4.Assign (firstClientDevices);
793 ipv4.SetBase ("192.168.3.0", "255.255.255.0");
794 Ipv4InterfaceContainer secondClientIfaces = ipv4.Assign (secondClientDevices);
795
796 Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
797
799 // application setup //
801 V4PingHelper pingHelper ("192.168.1.2");
802 pingHelper.SetAttribute ("Interval", TimeValue (pingInterval));
803 pingHelper.SetAttribute ("Size", UintegerValue (pingSize));
804 ApplicationContainer pingContainer = pingHelper.Install (pingServer);
805 Ptr<V4Ping> v4Ping = pingContainer.Get (0)->GetObject<V4Ping> ();
806 v4Ping->TraceConnectWithoutContext ("Rtt", MakeBoundCallback (&TracePingRtt, &pingOfStream));
807 pingContainer.Start (Seconds (1));
808 pingContainer.Stop (stopTime - Seconds (1));
809
810 ApplicationContainer firstApp;
811 uint16_t firstPort = 5000;
812 BulkSendHelper tcp ("ns3::TcpSocketFactory", Address ());
813 // set to large value: e.g. 1000 Mb/s for 60 seconds = 7500000000 bytes
814 tcp.SetAttribute ("MaxBytes", UintegerValue (7500000000));
815 // Configure first TCP client/server pair
816 InetSocketAddress firstDestAddress (firstClientIfaces.GetAddress (1), firstPort);
817 tcp.SetAttribute ("Remote", AddressValue (firstDestAddress));
818 firstApp = tcp.Install (firstServer);
819 firstApp.Start (Seconds (5));
820 firstApp.Stop (stopTime - Seconds (1));
821
822 Address firstSinkAddress (InetSocketAddress (Ipv4Address::GetAny (), firstPort));
823 ApplicationContainer firstSinkApp;
824 PacketSinkHelper firstSinkHelper ("ns3::TcpSocketFactory", firstSinkAddress);
825 firstSinkApp = firstSinkHelper.Install (firstClient);
826 firstSinkApp.Start (Seconds (5));
827 firstSinkApp.Stop (stopTime - MilliSeconds (500));
828
829 // Configure second TCP client/server pair
830 if (enableSecondTcp)
831 {
832 BulkSendHelper tcp ("ns3::TcpSocketFactory", Address ());
833 uint16_t secondPort = 5000;
834 ApplicationContainer secondApp;
835 InetSocketAddress secondDestAddress (secondClientIfaces.GetAddress (1), secondPort);
836 tcp.SetAttribute ("Remote", AddressValue (secondDestAddress));
837 secondApp = tcp.Install (secondServer);
838 secondApp.Start (Seconds (15));
839 secondApp.Stop (stopTime - Seconds (1));
840
841 Address secondSinkAddress (InetSocketAddress (Ipv4Address::GetAny (), secondPort));
842 PacketSinkHelper secondSinkHelper ("ns3::TcpSocketFactory", secondSinkAddress);
843 ApplicationContainer secondSinkApp;
844 secondSinkApp = secondSinkHelper.Install (secondClient);
845 secondSinkApp.Start (Seconds (15));
846 secondSinkApp.Stop (stopTime - MilliSeconds (500));
847 }
848
849 // Setup traces that can be hooked now
852 // Trace drops and marks for bottleneck
853 tc = wanLanDevices.Get (0)->GetNode ()->GetObject<TrafficControlLayer> ();
854 qd = tc->GetRootQueueDiscOnDevice (wanLanDevices.Get (0));
855 qd->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&TraceQueueDrop, &queueDropOfStream));
856 qd->TraceConnectWithoutContext ("Mark", MakeBoundCallback (&TraceQueueMark, &queueMarkOfStream));
857 qd->TraceConnectWithoutContext ("BytesInQueue", MakeBoundCallback (&TraceQueueLength, &queueLengthOfStream, linkRate));
858
859 // Setup scheduled traces; TCP traces must be hooked after socket creation
860 Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleFirstTcpRttTraceConnection, &firstTcpRttOfStream);
861 Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleFirstTcpCwndTraceConnection, &firstTcpCwndOfStream);
862 Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleFirstPacketSinkConnection);
863 if (firstTcpType == "dctcp")
864 {
865 Simulator::Schedule (Seconds (5) + MilliSeconds (100), &ScheduleFirstDctcpTraceConnection, &firstTcpDctcpOfStream);
866 }
867 Simulator::Schedule (throughputSamplingInterval, &TraceFirstThroughput, &firstTcpThroughputOfStream, throughputSamplingInterval);
868 if (enableSecondTcp)
869 {
870 // Setup scheduled traces; TCP traces must be hooked after socket creation
871 Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleSecondTcpRttTraceConnection, &secondTcpRttOfStream);
872 Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleSecondTcpCwndTraceConnection, &secondTcpCwndOfStream);
873 Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleSecondPacketSinkConnection);
874 Simulator::Schedule (throughputSamplingInterval, &TraceSecondThroughput, &secondTcpThroughputOfStream, throughputSamplingInterval);
875 if (secondTcpType == "dctcp")
876 {
877 Simulator::Schedule (Seconds (15) + MilliSeconds (100), &ScheduleSecondDctcpTraceConnection, &secondTcpDctcpOfStream);
878 }
879 }
880 Simulator::Schedule (marksSamplingInterval, &TraceMarksFrequency, &queueMarksFrequencyOfStream, marksSamplingInterval);
881
882 if (enablePcap)
883 {
884 p2p.EnablePcapAll ("tcp-validation", false);
885 }
886
887 Simulator::Stop (stopTime);
888 Simulator::Run ();
889 Simulator::Destroy ();
890
891 if (g_validate == "")
892 {
893 pingOfStream.close ();
894 firstTcpCwndOfStream.close ();
895 firstTcpRttOfStream.close ();
896 if (firstTcpType == "dctcp")
897 {
898 firstTcpDctcpOfStream.close ();
899 }
900 firstTcpThroughputOfStream.close ();
901 if (enableSecondTcp)
902 {
903 secondTcpCwndOfStream.close ();
904 secondTcpRttOfStream.close ();
905 secondTcpThroughputOfStream.close ();
906 if (secondTcpType == "dctcp")
907 {
908 secondTcpDctcpOfStream.close ();
909 }
910 }
911 queueDropOfStream.close ();
912 queueMarkOfStream.close ();
913 queueMarksFrequencyOfStream.close ();
914 queueLengthOfStream.close ();
915 }
916
918 {
919 NS_FATAL_ERROR ("Validation failed");
920 }
921}
922
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Address.
holds a vector of ns3::Application pointers.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
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.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
Parse command-line arguments.
Definition: command-line.h:229
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:287
AttributeValue implementation for DataRate.
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
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...
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
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
virtual Ptr< Node > GetNode(void) const =0
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
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 SetQueue(std::string type, std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue())
Each point to point net device must have a queue to pass packets through.
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)
A Device for a Point to Point Network Link.
Class for representing queue sizes.
Definition: queue-size.h:95
AttributeValue implementation for QueueSize.
Hold variables of type string.
Definition: string.h:41
TCP socket creation and multiplexing/demultiplexing.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
AttributeValue implementation for Time.
Definition: nstime.h:1308
Build a set of QueueDisc objects.
QueueDiscContainer Install(NetDeviceContainer c)
uint16_t SetRootQueueDisc(const std::string &type, Args &&... args)
Helper function used to set a root queue disc of the given type and with the given attributes.
void SetQueueLimits(std::string type, Args &&... args)
Helper function used to add a queue limits object to the transmission queues of the devices.
Introspection did not find any typical Config paths.
a unique identifier for an interface.
Definition: type-id.h:59
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Hold an unsigned integer type.
Definition: uinteger.h:44
Create a IPv4 ping application and associate it to a node.
Definition: v4ping-helper.h:38
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT.
Definition: v4ping.h:42
Time stopTime
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:901
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:909
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1709
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
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
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
LogLevel
Logging severity classes and levels.
Definition: log.h:94
@ LOG_LEVEL_ALL
Print everything.
Definition: log.h:116
@ LOG_PREFIX_FUNC
Prefix all trace prints with function.
Definition: log.h:118
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition: log.h:119
@ LOG_PREFIX_NODE
Prefix all trace prints with simulation node.
Definition: log.h:120
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:361
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
float alpha
Plot alpha value (transparency)
cmd
Definition: second.py:35
void ScheduleSecondDctcpTraceConnection(std::ofstream *ofStream)
void TraceMarksFrequency(std::ofstream *ofStream, Time marksSamplingInterval)
void ScheduleFirstPacketSinkConnection(void)
void ScheduleSecondTcpRttTraceConnection(std::ofstream *ofStream)
void TraceSecondRtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
void TraceSecondDctcp(std::ofstream *ofStream, uint32_t bytesMarked, uint32_t bytesAcked, double alpha)
void TraceSecondThroughput(std::ofstream *ofStream, Time throughputInterval)
void TraceFirstThroughput(std::ofstream *ofStream, Time throughputInterval)
void ScheduleFirstDctcpTraceConnection(std::ofstream *ofStream)
void TraceSecondCwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
void TraceQueueMark(std::ofstream *ofStream, Ptr< const QueueDiscItem > item, const char *reason)
bool g_validationFailed
void TraceQueueLength(std::ofstream *ofStream, DataRate queueLinkRate, uint32_t oldVal, uint32_t newVal)
void TracePingRtt(std::ofstream *ofStream, Time rtt)
void TraceFirstRx(Ptr< const Packet > packet, const Address &address)
void TraceFirstCwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
void TraceQueueDrop(std::ofstream *ofStream, Ptr< const QueueDiscItem > item)
uint32_t g_marksObserved
void ScheduleSecondPacketSinkConnection(void)
void ScheduleSecondTcpCwndTraceConnection(std::ofstream *ofStream)
void TraceSecondRx(Ptr< const Packet > packet, const Address &address)
void TraceFirstRtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
uint32_t g_firstBytesReceived
std::string g_validate
uint32_t g_secondBytesReceived
uint32_t g_dropsObserved
void TraceFirstDctcp(std::ofstream *ofStream, uint32_t bytesMarked, uint32_t bytesAcked, double alpha)
void ScheduleFirstTcpRttTraceConnection(std::ofstream *ofStream)
void ScheduleFirstTcpCwndTraceConnection(std::ofstream *ofStream)