147#include "ns3/applications-module.h"
148#include "ns3/core-module.h"
149#include "ns3/internet-apps-module.h"
150#include "ns3/internet-module.h"
151#include "ns3/network-module.h"
152#include "ns3/point-to-point-module.h"
153#include "ns3/traffic-control-module.h"
193 double cwnd =
static_cast<double>(newCwnd) / 1448;
194 if ((now > 5.43) && (now < 5.465) && (cwnd < 500))
199 else if ((now > 5.795) && (now < 6) && (cwnd > 190))
204 else if ((now > 14) && (now < 14.197) && (cwnd < 224))
209 else if ((now > 17) && (now < 18.026) && (cwnd < 212))
236 if ((now < 7.5) && (alpha < 0.1))
241 else if ((now > 11) && (now < 30) && (alpha > 0.01))
246 else if ((now > 34) && (alpha < 0.015) && (alpha > 0.025))
249 <<
" (expected 0.015 <= alpha <= 0.025)");
256 if ((now > 5.6) && (alpha > 0.1))
261 if ((now > 7) && ((alpha > 0.09) || (alpha < 0.055)))
264 <<
" (expected 0.09 <= alpha <= 0.055)");
427 <<
static_cast<double>(newVal * 8) / (queueLinkRate.
GetBitRate() / 1000)
449 marksSamplingInterval);
471 if ((now < 14) && (throughput > 20))
474 <<
" (expected <= 20)");
477 if ((now < 30) && (throughput > 48))
480 <<
" (expected <= 48)");
483 if ((now > 32) && ((throughput < 47.5) || (throughput > 48.5)))
486 <<
" (expected 47.5 <= throughput <= 48.5)");
493 if ((now > 5.6) && ((throughput < 48) || (throughput > 49)))
496 <<
" (expected 48 <= throughput <= 49)");
529 "/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
554 "CongestionOps/$ns3::TcpDctcp/CongestionEstimate",
567 "CongestionOps/$ns3::TcpDctcp/CongestionEstimate",
616main(
int argc,
char* argv[])
622 bool enableSecondTcp =
false;
623 bool enableLogging =
false;
627 std::string pingTraceFile =
"tcp-validation-ping.dat";
628 std::string firstTcpRttTraceFile =
"tcp-validation-first-tcp-rtt.dat";
629 std::string firstTcpCwndTraceFile =
"tcp-validation-first-tcp-cwnd.dat";
630 std::string firstDctcpTraceFile =
"tcp-validation-first-dctcp-alpha.dat";
631 std::string firstTcpThroughputTraceFile =
"tcp-validation-first-tcp-throughput.dat";
632 std::string secondTcpRttTraceFile =
"tcp-validation-second-tcp-rtt.dat";
633 std::string secondTcpCwndTraceFile =
"tcp-validation-second-tcp-cwnd.dat";
634 std::string secondTcpThroughputTraceFile =
"tcp-validation-second-tcp-throughput.dat";
635 std::string secondDctcpTraceFile =
"tcp-validation-second-dctcp-alpha.dat";
636 std::string queueMarkTraceFile =
"tcp-validation-queue-mark.dat";
637 std::string queueDropTraceFile =
"tcp-validation-queue-drop.dat";
638 std::string queueMarksFrequencyTraceFile =
"tcp-validation-queue-marks-frequency.dat";
639 std::string queueLengthTraceFile =
"tcp-validation-queue-length.dat";
644 std::string firstTcpType =
"cubic";
645 std::string secondTcpType =
"";
646 std::string queueType =
"codel";
650 bool queueUseEcn =
false;
652 bool enablePcap =
false;
671 cmd.AddValue(
"firstTcpType",
"first TCP type (cubic, dctcp, or reno)", firstTcpType);
672 cmd.AddValue(
"secondTcpType",
"second TCP type (cubic, dctcp, or reno)", secondTcpType);
673 cmd.AddValue(
"queueType",
"bottleneck queue type (fq, codel, pie, or red)", queueType);
674 cmd.AddValue(
"baseRtt",
"base RTT", baseRtt);
675 cmd.AddValue(
"ceThreshold",
"CoDel CE threshold (for DCTCP)", ceThreshold);
676 cmd.AddValue(
"linkRate",
"data rate of bottleneck link", linkRate);
677 cmd.AddValue(
"stopTime",
"simulation stop time",
stopTime);
678 cmd.AddValue(
"queueUseEcn",
"use ECN on queue", queueUseEcn);
679 cmd.AddValue(
"enablePcap",
"enable Pcap", enablePcap);
680 cmd.AddValue(
"validate",
"validation case to run",
g_validate);
681 cmd.Parse(argc, argv);
733 Time oneWayDelay = baseRtt / 2;
736 if (firstTcpType ==
"reno")
740 else if (firstTcpType ==
"cubic")
744 else if (firstTcpType ==
"dctcp")
751 std::cout <<
"Warning: using DCTCP with queue ECN disabled" << std::endl;
759 if (secondTcpType ==
"reno")
761 enableSecondTcp =
true;
764 else if (secondTcpType ==
"cubic")
766 enableSecondTcp =
true;
769 else if (secondTcpType ==
"dctcp")
771 enableSecondTcp =
true;
774 else if (secondTcpType.empty())
776 enableSecondTcp =
false;
784 if (queueType ==
"fq")
788 else if (queueType ==
"codel")
792 else if (queueType ==
"pie")
796 else if (queueType ==
"red")
819 <<
"; second TCP: " << secondTcpTypeId.
GetName()
820 <<
"; queue: " << queueTypeId.
GetName()
821 <<
"; ceThreshold: " << ceThreshold.
GetSeconds() * 1000 <<
"ms");
826 <<
"; queue: " << queueTypeId.
GetName()
827 <<
"; ceThreshold: " << ceThreshold.
GetSeconds() * 1000 <<
"ms");
831 std::ofstream pingOfStream;
832 std::ofstream firstTcpRttOfStream;
833 std::ofstream firstTcpCwndOfStream;
834 std::ofstream firstTcpThroughputOfStream;
835 std::ofstream firstTcpDctcpOfStream;
836 std::ofstream secondTcpRttOfStream;
837 std::ofstream secondTcpCwndOfStream;
838 std::ofstream secondTcpThroughputOfStream;
839 std::ofstream secondTcpDctcpOfStream;
840 std::ofstream queueDropOfStream;
841 std::ofstream queueMarkOfStream;
842 std::ofstream queueMarksFrequencyOfStream;
843 std::ofstream queueLengthOfStream;
846 pingOfStream.open(pingTraceFile, std::ofstream::out);
847 firstTcpRttOfStream.open(firstTcpRttTraceFile, std::ofstream::out);
848 firstTcpCwndOfStream.open(firstTcpCwndTraceFile, std::ofstream::out);
849 firstTcpThroughputOfStream.open(firstTcpThroughputTraceFile, std::ofstream::out);
850 if (firstTcpType ==
"dctcp")
852 firstTcpDctcpOfStream.open(firstDctcpTraceFile, std::ofstream::out);
856 secondTcpRttOfStream.open(secondTcpRttTraceFile, std::ofstream::out);
857 secondTcpCwndOfStream.open(secondTcpCwndTraceFile, std::ofstream::out);
858 secondTcpThroughputOfStream.open(secondTcpThroughputTraceFile, std::ofstream::out);
859 if (secondTcpType ==
"dctcp")
861 secondTcpDctcpOfStream.open(secondDctcpTraceFile, std::ofstream::out);
864 queueDropOfStream.open(queueDropTraceFile, std::ofstream::out);
865 queueMarkOfStream.open(queueMarkTraceFile, std::ofstream::out);
866 queueMarksFrequencyOfStream.open(queueMarksFrequencyTraceFile, std::ofstream::out);
867 queueLengthOfStream.open(queueLengthTraceFile, std::ofstream::out);
873 Ptr<Node> pingServer = CreateObject<Node>();
874 Ptr<Node> firstServer = CreateObject<Node>();
875 Ptr<Node> secondServer = CreateObject<Node>();
876 Ptr<Node> wanRouter = CreateObject<Node>();
877 Ptr<Node> lanRouter = CreateObject<Node>();
878 Ptr<Node> pingClient = CreateObject<Node>();
879 Ptr<Node> firstClient = CreateObject<Node>();
880 Ptr<Node> secondClient = CreateObject<Node>();
896 pingServerDevices =
p2p.Install(wanRouter, pingServer);
897 firstServerDevices =
p2p.Install(wanRouter, firstServer);
898 secondServerDevices =
p2p.Install(wanRouter, secondServer);
899 p2p.SetChannelAttribute(
"Delay",
TimeValue(oneWayDelay));
900 wanLanDevices =
p2p.Install(wanRouter, lanRouter);
903 pingClientDevices =
p2p.Install(lanRouter, pingClient);
904 firstClientDevices =
p2p.Install(lanRouter, firstClient);
905 secondClientDevices =
p2p.Install(lanRouter, secondClient);
912 stackHelper.
Install(pingServer);
914 stackHelper.
Install(firstServer);
916 proto->SetAttribute(
"SocketType",
TypeIdValue(firstTcpTypeId));
917 stackHelper.
Install(secondServer);
918 stackHelper.
Install(wanRouter);
919 stackHelper.
Install(lanRouter);
920 stackHelper.
Install(pingClient);
922 stackHelper.
Install(firstClient);
925 proto->SetAttribute(
"SocketType",
TypeIdValue(firstTcpTypeId));
926 stackHelper.
Install(secondClient);
931 proto->SetAttribute(
"SocketType",
TypeIdValue(secondTcpTypeId));
933 proto->SetAttribute(
"SocketType",
TypeIdValue(secondTcpTypeId));
944 tchFq.
Install(pingServerDevices);
945 tchFq.
Install(firstServerDevices);
946 tchFq.
Install(secondServerDevices);
948 tchFq.
Install(pingClientDevices);
949 tchFq.
Install(firstClientDevices);
950 tchFq.
Install(secondClientDevices);
958 ipv4.SetBase(
"10.1.1.0",
"255.255.255.0");
960 ipv4.SetBase(
"10.1.2.0",
"255.255.255.0");
962 ipv4.SetBase(
"10.1.3.0",
"255.255.255.0");
964 ipv4.SetBase(
"172.16.1.0",
"255.255.255.0");
966 ipv4.SetBase(
"192.168.1.0",
"255.255.255.0");
968 ipv4.SetBase(
"192.168.2.0",
"255.255.255.0");
970 ipv4.SetBase(
"192.168.3.0",
"255.255.255.0");
979 pingHelper.SetAttribute(
"Interval",
TimeValue(pingInterval));
981 pingHelper.SetAttribute(
"VerboseMode",
EnumValue(Ping::VerboseMode::SILENT));
989 uint16_t firstPort = 5000;
995 tcp.SetAttribute(
"Remote",
AddressValue(firstDestAddress));
996 firstApp = tcp.Install(firstServer);
1002 PacketSinkHelper firstSinkHelper(
"ns3::TcpSocketFactory", firstSinkAddress);
1003 firstSinkApp = firstSinkHelper.Install(firstClient);
1008 if (enableSecondTcp)
1011 uint16_t secondPort = 5000;
1014 tcp.SetAttribute(
"Remote",
AddressValue(secondDestAddress));
1015 secondApp = tcp.Install(secondServer);
1020 PacketSinkHelper secondSinkHelper(
"ns3::TcpSocketFactory", secondSinkAddress);
1022 secondSinkApp = secondSinkHelper.Install(secondClient);
1032 qd = tc->GetRootQueueDiscOnDevice(wanLanDevices.
Get(0));
1042 &firstTcpRttOfStream);
1045 &firstTcpCwndOfStream);
1047 if (firstTcpType ==
"dctcp")
1051 &firstTcpDctcpOfStream);
1055 &firstTcpThroughputOfStream,
1056 throughputSamplingInterval);
1057 if (enableSecondTcp)
1062 &secondTcpRttOfStream);
1065 &secondTcpCwndOfStream);
1069 &secondTcpThroughputOfStream,
1070 throughputSamplingInterval);
1071 if (secondTcpType ==
"dctcp")
1075 &secondTcpDctcpOfStream);
1080 &queueMarksFrequencyOfStream,
1081 marksSamplingInterval);
1085 p2p.EnablePcapAll(
"tcp-validation",
false);
1094 pingOfStream.close();
1095 firstTcpCwndOfStream.close();
1096 firstTcpRttOfStream.close();
1097 if (firstTcpType ==
"dctcp")
1099 firstTcpDctcpOfStream.close();
1101 firstTcpThroughputOfStream.close();
1102 if (enableSecondTcp)
1104 secondTcpCwndOfStream.close();
1105 secondTcpRttOfStream.close();
1106 secondTcpThroughputOfStream.close();
1107 if (secondTcpType ==
"dctcp")
1109 secondTcpDctcpOfStream.close();
1112 queueDropOfStream.close();
1113 queueMarkOfStream.close();
1114 queueMarksFrequencyOfStream.close();
1115 queueLengthOfStream.close();
a polymophic address class
AttributeValue implementation for Address.
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
AttributeValue implementation for Boolean.
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
static TypeId GetTypeId()
Get the type ID.
Parse command-line arguments.
Class for representing data rates.
uint64_t GetBitRate() const
Get the underlying bitrate.
AttributeValue implementation for DataRate.
Hold variables of type enum.
static TypeId GetTypeId()
Get the type ID.
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.
Ipv4 addresses are stored in host order in this class.
static Ipv4Address GetAny()
static void PopulateRoutingTables()
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
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
static TypeId GetTypeId()
Get the type ID.
Create a ping application and associate it to a node.
This application behaves similarly to the Unix ping application, although with fewer options supporte...
Build a set of PointToPointNetDevice objects.
A Device for a Point to Point Network Link.
Smart pointer class similar to boost::intrusive_ptr.
Class for representing queue sizes.
AttributeValue implementation for QueueSize.
static TypeId GetTypeId()
Get the type ID.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
static Time Now()
Return the current simulation virtual time.
static void Run()
Run the simulation.
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Hold variables of type string.
static TypeId GetTypeId()
Get the type ID.
static TypeId GetTypeId()
Get the type ID.
TCP socket creation and multiplexing/demultiplexing.
static TypeId GetTypeId()
Get the type ID.
static TypeId GetTypeId()
Get the type ID.
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
AttributeValue implementation for Time.
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.
The Traffic Control layer aims at introducing an equivalent of the Linux Traffic Control infrastructu...
a unique identifier for an interface.
std::string GetName() const
Get the name.
AttributeValue implementation for TypeId.
Hold an unsigned integer type.
void SetDefault(std::string name, const AttributeValue &value)
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Time Now()
create an ns3::Time instance which contains the current simulation time.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
LogLevel
Logging severity classes and levels.
@ LOG_LEVEL_ALL
Print everything.
@ LOG_PREFIX_FUNC
Prefix all trace prints with function.
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
@ LOG_PREFIX_NODE
Prefix all trace prints with simulation node.
void TracePingRtt(std::ofstream *ofStream, uint16_t, Time rtt)
Trace ping RTT.
void ScheduleSecondDctcpTraceConnection(std::ofstream *ofStream)
Schedule trace connection.
void TraceMarksFrequency(std::ofstream *ofStream, Time marksSamplingInterval)
Trace marks frequency.
void ScheduleSecondTcpRttTraceConnection(std::ofstream *ofStream)
Schedule trace connection.
void TraceSecondRtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
Trace second RTT.
void TraceSecondDctcp(std::ofstream *ofStream, uint32_t bytesMarked, uint32_t bytesAcked, double alpha)
Trace second TcpDctcp.
void TraceSecondThroughput(std::ofstream *ofStream, Time throughputInterval)
Trace the second throughput.
void TraceFirstThroughput(std::ofstream *ofStream, Time throughputInterval)
Trace the first throughput.
void ScheduleFirstDctcpTraceConnection(std::ofstream *ofStream)
Schedule trace connection.
void TraceSecondCwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
Trace second congestion window.
void TraceQueueMark(std::ofstream *ofStream, Ptr< const QueueDiscItem > item, const char *reason)
Trace queue marks.
bool g_validationFailed
True if validation failed.
void ScheduleFirstPacketSinkConnection()
Schedule trace connection.
void TraceQueueLength(std::ofstream *ofStream, DataRate queueLinkRate, uint32_t oldVal, uint32_t newVal)
Trace queue length.
void TraceFirstRx(Ptr< const Packet > packet, const Address &address)
Trace first Rx.
void TraceFirstCwnd(std::ofstream *ofStream, uint32_t oldCwnd, uint32_t newCwnd)
Trace first congestion window.
void TraceQueueDrop(std::ofstream *ofStream, Ptr< const QueueDiscItem > item)
Trace queue drop.
uint32_t g_marksObserved
Number of marked packets observed.
void ScheduleSecondPacketSinkConnection()
Schedule trace connection.
void ScheduleSecondTcpCwndTraceConnection(std::ofstream *ofStream)
Schedule trace connection.
void TraceSecondRx(Ptr< const Packet > packet, const Address &address)
Trace second Rx.
void TraceFirstRtt(std::ofstream *ofStream, Time oldRtt, Time newRtt)
Trace first RTT.
uint32_t g_firstBytesReceived
First received packet size.
std::string g_validate
Empty string disables validation.
uint32_t g_secondBytesReceived
Second received packet size.
uint32_t g_dropsObserved
Number of dropped packets observed.
void TraceFirstDctcp(std::ofstream *ofStream, uint32_t bytesMarked, uint32_t bytesAcked, double alpha)
Trace first TcpDctcp.
void ScheduleFirstTcpRttTraceConnection(std::ofstream *ofStream)
Schedule trace connection.
void ScheduleFirstTcpCwndTraceConnection(std::ofstream *ofStream)
Schedule trace connection.