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))
196 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" cwnd " << cwnd <<
" (expected >= 500)");
199 else if ((now > 5.795) && (now < 6) && (cwnd > 190))
201 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" cwnd " << cwnd <<
" (expected <= 190)");
204 else if ((now > 14) && (now < 14.197) && (cwnd < 224))
206 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" cwnd " << cwnd <<
" (expected >= 224)");
209 else if ((now > 17) && (now < 18.026) && (cwnd < 212))
211 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" cwnd " << cwnd <<
" (expected >= 212)");
236 if ((now < 7.5) && (alpha < 0.1))
238 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" alpha " << alpha <<
" (expected >= 0.1)");
241 else if ((now > 11) && (now < 30) && (alpha > 0.01))
243 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" alpha " << alpha <<
" (expected <= 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))
258 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" alpha " << alpha <<
" (expected <= 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)
446 Simulator::Schedule(marksSamplingInterval,
449 marksSamplingInterval);
471 if ((now < 14) && (throughput > 20))
473 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" throughput " << throughput
474 <<
" (expected <= 20)");
477 if ((now < 30) && (throughput > 48))
479 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" throughput " << throughput
480 <<
" (expected <= 48)");
483 if ((now > 32) && ((throughput < 47.5) || (throughput > 48.5)))
485 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" throughput " << throughput
486 <<
" (expected 47.5 <= throughput <= 48.5)");
493 if ((now > 5.6) && ((throughput < 48) || (throughput > 49)))
495 NS_LOG_WARN(
"now " <<
Now().As(Time::S) <<
" throughput " << throughput
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")
738 firstTcpTypeId = TcpLinuxReno::GetTypeId();
740 else if (firstTcpType ==
"cubic")
742 firstTcpTypeId = TcpCubic::GetTypeId();
744 else if (firstTcpType ==
"dctcp")
746 firstTcpTypeId = TcpDctcp::GetTypeId();
749 if (queueUseEcn ==
false)
751 std::cout <<
"Warning: using DCTCP with queue ECN disabled" << std::endl;
759 if (secondTcpType ==
"reno")
761 enableSecondTcp =
true;
762 secondTcpTypeId = TcpLinuxReno::GetTypeId();
764 else if (secondTcpType ==
"cubic")
766 enableSecondTcp =
true;
767 secondTcpTypeId = TcpCubic::GetTypeId();
769 else if (secondTcpType ==
"dctcp")
771 enableSecondTcp =
true;
772 secondTcpTypeId = TcpDctcp::GetTypeId();
774 else if (secondTcpType ==
"")
776 enableSecondTcp =
false;
784 if (queueType ==
"fq")
786 queueTypeId = FqCoDelQueueDisc::GetTypeId();
788 else if (queueType ==
"codel")
790 queueTypeId = CoDelQueueDisc::GetTypeId();
792 else if (queueType ==
"pie")
794 queueTypeId = PieQueueDisc::GetTypeId();
796 else if (queueType ==
"red")
798 queueTypeId = RedQueueDisc::GetTypeId();
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);
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");
973 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
979 pingHelper.SetAttribute(
"Interval",
TimeValue(pingInterval));
988 uint16_t firstPort = 5000;
994 tcp.SetAttribute(
"Remote",
AddressValue(firstDestAddress));
995 firstApp = tcp.Install(firstServer);
1001 PacketSinkHelper firstSinkHelper(
"ns3::TcpSocketFactory", firstSinkAddress);
1002 firstSinkApp = firstSinkHelper.Install(firstClient);
1007 if (enableSecondTcp)
1010 uint16_t secondPort = 5000;
1013 tcp.SetAttribute(
"Remote",
AddressValue(secondDestAddress));
1014 secondApp = tcp.Install(secondServer);
1019 PacketSinkHelper secondSinkHelper(
"ns3::TcpSocketFactory", secondSinkAddress);
1021 secondSinkApp = secondSinkHelper.Install(secondClient);
1031 qd = tc->GetRootQueueDiscOnDevice(wanLanDevices.
Get(0));
1041 &firstTcpRttOfStream);
1044 &firstTcpCwndOfStream);
1046 if (firstTcpType ==
"dctcp")
1050 &firstTcpDctcpOfStream);
1052 Simulator::Schedule(throughputSamplingInterval,
1054 &firstTcpThroughputOfStream,
1055 throughputSamplingInterval);
1056 if (enableSecondTcp)
1061 &secondTcpRttOfStream);
1064 &secondTcpCwndOfStream);
1066 Simulator::Schedule(throughputSamplingInterval,
1068 &secondTcpThroughputOfStream,
1069 throughputSamplingInterval);
1070 if (secondTcpType ==
"dctcp")
1074 &secondTcpDctcpOfStream);
1077 Simulator::Schedule(marksSamplingInterval,
1079 &queueMarksFrequencyOfStream,
1080 marksSamplingInterval);
1089 Simulator::Destroy();
1093 pingOfStream.close();
1094 firstTcpCwndOfStream.close();
1095 firstTcpRttOfStream.close();
1096 if (firstTcpType ==
"dctcp")
1098 firstTcpDctcpOfStream.close();
1100 firstTcpThroughputOfStream.close();
1101 if (enableSecondTcp)
1103 secondTcpCwndOfStream.close();
1104 secondTcpRttOfStream.close();
1105 secondTcpThroughputOfStream.close();
1106 if (secondTcpType ==
"dctcp")
1108 secondTcpDctcpOfStream.close();
1111 queueDropOfStream.close();
1112 queueMarkOfStream.close();
1113 queueMarksFrequencyOfStream.close();
1114 queueLengthOfStream.close();
a polymophic address class
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.
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
Parse command-line arguments.
Class for representing data rates.
uint64_t GetBitRate() const
Get the underlying bitrate.
AttributeValue implementation for DataRate.
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.
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.
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
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.
void SetQueue(std::string type, Ts &&... args)
Each point to point net device must have a queue to pass packets through.
NetDeviceContainer Install(NodeContainer c)
A Device for a Point to Point Network Link.
Class for representing queue sizes.
AttributeValue implementation for QueueSize.
Hold variables of type string.
TCP socket creation and multiplexing/demultiplexing.
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.
Introspection did not find any typical Config paths.
a unique identifier for an interface.
std::string GetName() const
Get the name.
AttributeValue implementation for TypeId.
Hold an unsigned integer type.
Create a IPv4 ping application and associate it to a node.
an application which sends one ICMP ECHO request, waits for a REPLYs and reports the calculated RTT.
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.
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
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.
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 LogComponentEnable(const char *name, enum LogLevel level)
Enable the logging output associated with that log component.
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 TracePingRtt(std::ofstream *ofStream, Time rtt)
Trace ping RTT.
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.