mtp: Change the code style of examples
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2017-20 NITK Surathkal
|
||||
* Copyright (c) 2020 Tom Henderson (better alignment with experiment)
|
||||
@@ -91,16 +90,16 @@
|
||||
// utilization and low queueing delay and fairness across competing flows
|
||||
// sharing the same path.
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
#include "ns3/mtp-interface.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
@@ -117,451 +116,481 @@ std::vector<uint64_t> rxS2R2Bytes;
|
||||
std::vector<uint64_t> rxS3R1Bytes;
|
||||
|
||||
void
|
||||
PrintProgress (Time interval)
|
||||
PrintProgress(Time interval)
|
||||
{
|
||||
std::cout << "Progress to " << std::fixed << std::setprecision (1) << Simulator::Now ().GetSeconds () << " seconds simulation time" << std::endl;
|
||||
Simulator::Schedule (interval, &PrintProgress, interval);
|
||||
std::cout << "Progress to " << std::fixed << std::setprecision(1)
|
||||
<< Simulator::Now().GetSeconds() << " seconds simulation time" << std::endl;
|
||||
Simulator::Schedule(interval, &PrintProgress, interval);
|
||||
}
|
||||
|
||||
void
|
||||
TraceS1R1Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
|
||||
TraceS1R1Sink(std::size_t index, Ptr<const Packet> p, const Address& a)
|
||||
{
|
||||
rxS1R1Bytes[index] += p->GetSize ();
|
||||
rxS1R1Bytes[index] += p->GetSize();
|
||||
}
|
||||
|
||||
void
|
||||
TraceS2R2Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
|
||||
TraceS2R2Sink(std::size_t index, Ptr<const Packet> p, const Address& a)
|
||||
{
|
||||
rxS2R2Bytes[index] += p->GetSize ();
|
||||
rxS2R2Bytes[index] += p->GetSize();
|
||||
}
|
||||
|
||||
void
|
||||
TraceS3R1Sink (std::size_t index, Ptr<const Packet> p, const Address& a)
|
||||
TraceS3R1Sink(std::size_t index, Ptr<const Packet> p, const Address& a)
|
||||
{
|
||||
rxS3R1Bytes[index] += p->GetSize ();
|
||||
rxS3R1Bytes[index] += p->GetSize();
|
||||
}
|
||||
|
||||
void
|
||||
InitializeCounters (void)
|
||||
InitializeCounters()
|
||||
{
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
rxS1R1Bytes[i] = 0;
|
||||
rxS1R1Bytes[i] = 0;
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
rxS2R2Bytes[i] = 0;
|
||||
rxS2R2Bytes[i] = 0;
|
||||
}
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
rxS3R1Bytes[i] = 0;
|
||||
rxS3R1Bytes[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintThroughput (Time measurementWindow)
|
||||
PrintThroughput(Time measurementWindow)
|
||||
{
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
rxS1R1Throughput << measurementWindow.GetSeconds () << "s " << i << " " << (rxS1R1Bytes[i] * 8) / (measurementWindow.GetSeconds ()) / 1e6 << std::endl;
|
||||
rxS1R1Throughput << measurementWindow.GetSeconds() << "s " << i << " "
|
||||
<< (rxS1R1Bytes[i] * 8) / (measurementWindow.GetSeconds()) / 1e6
|
||||
<< std::endl;
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
rxS2R2Throughput << Simulator::Now ().GetSeconds () << "s " << i << " " << (rxS2R2Bytes[i] * 8) / (measurementWindow.GetSeconds ()) / 1e6 << std::endl;
|
||||
rxS2R2Throughput << Simulator::Now().GetSeconds() << "s " << i << " "
|
||||
<< (rxS2R2Bytes[i] * 8) / (measurementWindow.GetSeconds()) / 1e6
|
||||
<< std::endl;
|
||||
}
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
rxS3R1Throughput << Simulator::Now ().GetSeconds () << "s " << i << " " << (rxS3R1Bytes[i] * 8) / (measurementWindow.GetSeconds ()) / 1e6 << std::endl;
|
||||
rxS3R1Throughput << Simulator::Now().GetSeconds() << "s " << i << " "
|
||||
<< (rxS3R1Bytes[i] * 8) / (measurementWindow.GetSeconds()) / 1e6
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Jain's fairness index: https://en.wikipedia.org/wiki/Fairness_measure
|
||||
void
|
||||
PrintFairness (Time measurementWindow)
|
||||
PrintFairness(Time measurementWindow)
|
||||
{
|
||||
double average = 0;
|
||||
uint64_t sumSquares = 0;
|
||||
uint64_t sum = 0;
|
||||
double fairness = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
double average = 0;
|
||||
uint64_t sumSquares = 0;
|
||||
uint64_t sum = 0;
|
||||
double fairness = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
sum += rxS1R1Bytes[i];
|
||||
sumSquares += (rxS1R1Bytes[i] * rxS1R1Bytes[i]);
|
||||
sum += rxS1R1Bytes[i];
|
||||
sumSquares += (rxS1R1Bytes[i] * rxS1R1Bytes[i]);
|
||||
}
|
||||
average = ((sum / 10) * 8 / measurementWindow.GetSeconds ()) / 1e6;
|
||||
fairness = static_cast<double> (sum * sum) / (10 * sumSquares);
|
||||
fairnessIndex << "Average throughput for S1-R1 flows: "
|
||||
<< std::fixed << std::setprecision (2) << average << " Mbps; fairness: "
|
||||
<< std::fixed << std::setprecision (3) << fairness << std::endl;
|
||||
average = 0;
|
||||
sumSquares = 0;
|
||||
sum = 0;
|
||||
fairness = 0;
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
average = ((sum / 10) * 8 / measurementWindow.GetSeconds()) / 1e6;
|
||||
fairness = static_cast<double>(sum * sum) / (10 * sumSquares);
|
||||
fairnessIndex << "Average throughput for S1-R1 flows: " << std::fixed << std::setprecision(2)
|
||||
<< average << " Mbps; fairness: " << std::fixed << std::setprecision(3)
|
||||
<< fairness << std::endl;
|
||||
average = 0;
|
||||
sumSquares = 0;
|
||||
sum = 0;
|
||||
fairness = 0;
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
sum += rxS2R2Bytes[i];
|
||||
sumSquares += (rxS2R2Bytes[i] * rxS2R2Bytes[i]);
|
||||
sum += rxS2R2Bytes[i];
|
||||
sumSquares += (rxS2R2Bytes[i] * rxS2R2Bytes[i]);
|
||||
}
|
||||
average = ((sum / 20) * 8 / measurementWindow.GetSeconds ()) / 1e6;
|
||||
fairness = static_cast<double> (sum * sum) / (20 * sumSquares);
|
||||
fairnessIndex << "Average throughput for S2-R2 flows: "
|
||||
<< std::fixed << std::setprecision (2) << average << " Mbps; fairness: "
|
||||
<< std::fixed << std::setprecision (3) << fairness << std::endl;
|
||||
average = 0;
|
||||
sumSquares = 0;
|
||||
sum = 0;
|
||||
fairness = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
average = ((sum / 20) * 8 / measurementWindow.GetSeconds()) / 1e6;
|
||||
fairness = static_cast<double>(sum * sum) / (20 * sumSquares);
|
||||
fairnessIndex << "Average throughput for S2-R2 flows: " << std::fixed << std::setprecision(2)
|
||||
<< average << " Mbps; fairness: " << std::fixed << std::setprecision(3)
|
||||
<< fairness << std::endl;
|
||||
average = 0;
|
||||
sumSquares = 0;
|
||||
sum = 0;
|
||||
fairness = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
sum += rxS3R1Bytes[i];
|
||||
sumSquares += (rxS3R1Bytes[i] * rxS3R1Bytes[i]);
|
||||
sum += rxS3R1Bytes[i];
|
||||
sumSquares += (rxS3R1Bytes[i] * rxS3R1Bytes[i]);
|
||||
}
|
||||
average = ((sum / 10) * 8 / measurementWindow.GetSeconds ()) / 1e6;
|
||||
fairness = static_cast<double> (sum * sum) / (10 * sumSquares);
|
||||
fairnessIndex << "Average throughput for S3-R1 flows: "
|
||||
<< std::fixed << std::setprecision (2) << average << " Mbps; fairness: "
|
||||
<< std::fixed << std::setprecision (3) << fairness << std::endl;
|
||||
sum = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
average = ((sum / 10) * 8 / measurementWindow.GetSeconds()) / 1e6;
|
||||
fairness = static_cast<double>(sum * sum) / (10 * sumSquares);
|
||||
fairnessIndex << "Average throughput for S3-R1 flows: " << std::fixed << std::setprecision(2)
|
||||
<< average << " Mbps; fairness: " << std::fixed << std::setprecision(3)
|
||||
<< fairness << std::endl;
|
||||
sum = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
sum += rxS1R1Bytes[i];
|
||||
sum += rxS1R1Bytes[i];
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
sum += rxS2R2Bytes[i];
|
||||
sum += rxS2R2Bytes[i];
|
||||
}
|
||||
fairnessIndex << "Aggregate user-level throughput for flows through T1: " << static_cast<double> (sum * 8) / 1e9 << " Gbps" << std::endl;
|
||||
sum = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
fairnessIndex << "Aggregate user-level throughput for flows through T1: "
|
||||
<< static_cast<double>(sum * 8) / 1e9 << " Gbps" << std::endl;
|
||||
sum = 0;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
sum += rxS3R1Bytes[i];
|
||||
sum += rxS3R1Bytes[i];
|
||||
}
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
sum += rxS1R1Bytes[i];
|
||||
sum += rxS1R1Bytes[i];
|
||||
}
|
||||
fairnessIndex << "Aggregate user-level throughput for flows to R1: " << static_cast<double> (sum * 8) / 1e9 << " Gbps" << std::endl;
|
||||
fairnessIndex << "Aggregate user-level throughput for flows to R1: "
|
||||
<< static_cast<double>(sum * 8) / 1e9 << " Gbps" << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
CheckT1QueueSize (Ptr<QueueDisc> queue)
|
||||
CheckT1QueueSize(Ptr<QueueDisc> queue)
|
||||
{
|
||||
// 1500 byte packets
|
||||
uint32_t qSize = queue->GetNPackets ();
|
||||
Time backlog = Seconds (static_cast<double> (qSize * 1500 * 8) / 1e10); // 10 Gb/s
|
||||
// report size in units of packets and ms
|
||||
t1QueueLength << std::fixed << std::setprecision (2) << Simulator::Now ().GetSeconds () << " " << qSize << " " << backlog.GetMicroSeconds () << std::endl;
|
||||
// check queue size every 1/100 of a second
|
||||
Simulator::Schedule (MilliSeconds (10), &CheckT1QueueSize, queue);
|
||||
// 1500 byte packets
|
||||
uint32_t qSize = queue->GetNPackets();
|
||||
Time backlog = Seconds(static_cast<double>(qSize * 1500 * 8) / 1e10); // 10 Gb/s
|
||||
// report size in units of packets and ms
|
||||
t1QueueLength << std::fixed << std::setprecision(2) << Simulator::Now().GetSeconds() << " "
|
||||
<< qSize << " " << backlog.GetMicroSeconds() << std::endl;
|
||||
// check queue size every 1/100 of a second
|
||||
Simulator::Schedule(MilliSeconds(10), &CheckT1QueueSize, queue);
|
||||
}
|
||||
|
||||
void
|
||||
CheckT2QueueSize (Ptr<QueueDisc> queue)
|
||||
CheckT2QueueSize(Ptr<QueueDisc> queue)
|
||||
{
|
||||
uint32_t qSize = queue->GetNPackets ();
|
||||
Time backlog = Seconds (static_cast<double> (qSize * 1500 * 8) / 1e9); // 1 Gb/s
|
||||
// report size in units of packets and ms
|
||||
t2QueueLength << std::fixed << std::setprecision (2) << Simulator::Now ().GetSeconds () << " " << qSize << " " << backlog.GetMicroSeconds () << std::endl;
|
||||
// check queue size every 1/100 of a second
|
||||
Simulator::Schedule (MilliSeconds (10), &CheckT2QueueSize, queue);
|
||||
uint32_t qSize = queue->GetNPackets();
|
||||
Time backlog = Seconds(static_cast<double>(qSize * 1500 * 8) / 1e9); // 1 Gb/s
|
||||
// report size in units of packets and ms
|
||||
t2QueueLength << std::fixed << std::setprecision(2) << Simulator::Now().GetSeconds() << " "
|
||||
<< qSize << " " << backlog.GetMicroSeconds() << std::endl;
|
||||
// check queue size every 1/100 of a second
|
||||
Simulator::Schedule(MilliSeconds(10), &CheckT2QueueSize, queue);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable (4);
|
||||
MtpInterface::Enable (4);
|
||||
std::string outputFilePath = ".";
|
||||
std::string tcpTypeId = "TcpDctcp";
|
||||
Time flowStartupWindow = Seconds(1);
|
||||
Time convergenceTime = Seconds(3);
|
||||
Time measurementWindow = Seconds(1);
|
||||
bool enableSwitchEcn = true;
|
||||
Time progressInterval = MilliSeconds(100);
|
||||
|
||||
std::string outputFilePath = ".";
|
||||
std::string tcpTypeId = "TcpDctcp";
|
||||
Time flowStartupWindow = Seconds (1);
|
||||
Time convergenceTime = Seconds (3);
|
||||
Time measurementWindow = Seconds (1);
|
||||
bool enableSwitchEcn = true;
|
||||
Time progressInterval = MilliSeconds (100);
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.AddValue("tcpTypeId", "ns-3 TCP TypeId", tcpTypeId);
|
||||
cmd.AddValue("flowStartupWindow",
|
||||
"startup time window (TCP staggered starts)",
|
||||
flowStartupWindow);
|
||||
cmd.AddValue("convergenceTime", "convergence time", convergenceTime);
|
||||
cmd.AddValue("measurementWindow", "measurement window", measurementWindow);
|
||||
cmd.AddValue("enableSwitchEcn", "enable ECN at switches", enableSwitchEcn);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("tcpTypeId", "ns-3 TCP TypeId", tcpTypeId);
|
||||
cmd.AddValue ("flowStartupWindow", "startup time window (TCP staggered starts)", flowStartupWindow);
|
||||
cmd.AddValue ("convergenceTime", "convergence time", convergenceTime);
|
||||
cmd.AddValue ("measurementWindow", "measurement window", measurementWindow);
|
||||
cmd.AddValue ("enableSwitchEcn", "enable ECN at switches", enableSwitchEcn);
|
||||
cmd.Parse (argc, argv);
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::" + tcpTypeId));
|
||||
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue ("ns3::" + tcpTypeId));
|
||||
Time startTime = Seconds(0);
|
||||
Time stopTime = flowStartupWindow + convergenceTime + measurementWindow;
|
||||
|
||||
Time startTime = Seconds (0);
|
||||
Time stopTime = flowStartupWindow + convergenceTime + measurementWindow;
|
||||
Time clientStartTime = startTime;
|
||||
|
||||
Time clientStartTime = startTime;
|
||||
rxS1R1Bytes.reserve(10);
|
||||
rxS2R2Bytes.reserve(20);
|
||||
rxS3R1Bytes.reserve(10);
|
||||
|
||||
rxS1R1Bytes.reserve (10);
|
||||
rxS2R2Bytes.reserve (20);
|
||||
rxS3R1Bytes.reserve (10);
|
||||
NodeContainer S1;
|
||||
NodeContainer S2;
|
||||
NodeContainer S3;
|
||||
NodeContainer R2;
|
||||
Ptr<Node> T1 = CreateObject<Node>();
|
||||
Ptr<Node> T2 = CreateObject<Node>();
|
||||
Ptr<Node> R1 = CreateObject<Node>();
|
||||
S1.Create(10);
|
||||
S2.Create(20);
|
||||
S3.Create(10);
|
||||
R2.Create(20);
|
||||
|
||||
NodeContainer S1, S2, S3, R2;
|
||||
Ptr<Node> T1 = CreateObject<Node> ();
|
||||
Ptr<Node> T2 = CreateObject<Node> ();
|
||||
Ptr<Node> R1 = CreateObject<Node> ();
|
||||
S1.Create (10);
|
||||
S2.Create (20);
|
||||
S3.Create (10);
|
||||
R2.Create (20);
|
||||
Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1448));
|
||||
Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(2));
|
||||
GlobalValue::Bind("ChecksumEnabled", BooleanValue(false));
|
||||
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1448));
|
||||
Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (2));
|
||||
GlobalValue::Bind ("ChecksumEnabled", BooleanValue (false));
|
||||
// Set default parameters for RED queue disc
|
||||
Config::SetDefault("ns3::RedQueueDisc::UseEcn", BooleanValue(enableSwitchEcn));
|
||||
// ARED may be used but the queueing delays will increase; it is disabled
|
||||
// here because the SIGCOMM paper did not mention it
|
||||
// Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
// Config::SetDefault ("ns3::RedQueueDisc::Gentle", BooleanValue (true));
|
||||
Config::SetDefault("ns3::RedQueueDisc::UseHardDrop", BooleanValue(false));
|
||||
Config::SetDefault("ns3::RedQueueDisc::MeanPktSize", UintegerValue(1500));
|
||||
// Triumph and Scorpion switches used in DCTCP Paper have 4 MB of buffer
|
||||
// If every packet is 1500 bytes, 2666 packets can be stored in 4 MB
|
||||
Config::SetDefault("ns3::RedQueueDisc::MaxSize", QueueSizeValue(QueueSize("2666p")));
|
||||
// DCTCP tracks instantaneous queue length only; so set QW = 1
|
||||
Config::SetDefault("ns3::RedQueueDisc::QW", DoubleValue(1));
|
||||
Config::SetDefault("ns3::RedQueueDisc::MinTh", DoubleValue(20));
|
||||
Config::SetDefault("ns3::RedQueueDisc::MaxTh", DoubleValue(60));
|
||||
|
||||
// Set default parameters for RED queue disc
|
||||
Config::SetDefault ("ns3::RedQueueDisc::UseEcn", BooleanValue (enableSwitchEcn));
|
||||
// ARED may be used but the queueing delays will increase; it is disabled
|
||||
// here because the SIGCOMM paper did not mention it
|
||||
// Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
// Config::SetDefault ("ns3::RedQueueDisc::Gentle", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::UseHardDrop", BooleanValue (false));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MeanPktSize", UintegerValue (1500));
|
||||
// Triumph and Scorpion switches used in DCTCP Paper have 4 MB of buffer
|
||||
// If every packet is 1500 bytes, 2666 packets can be stored in 4 MB
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MaxSize", QueueSizeValue (QueueSize ("2666p")));
|
||||
// DCTCP tracks instantaneous queue length only; so set QW = 1
|
||||
Config::SetDefault ("ns3::RedQueueDisc::QW", DoubleValue (1));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MinTh", DoubleValue (20));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MaxTh", DoubleValue (60));
|
||||
PointToPointHelper pointToPointSR;
|
||||
pointToPointSR.SetDeviceAttribute("DataRate", StringValue("1Gbps"));
|
||||
pointToPointSR.SetChannelAttribute("Delay", StringValue("10us"));
|
||||
|
||||
PointToPointHelper pointToPointSR;
|
||||
pointToPointSR.SetDeviceAttribute ("DataRate", StringValue ("1Gbps"));
|
||||
pointToPointSR.SetChannelAttribute ("Delay", StringValue ("10us"));
|
||||
PointToPointHelper pointToPointT;
|
||||
pointToPointT.SetDeviceAttribute("DataRate", StringValue("10Gbps"));
|
||||
pointToPointT.SetChannelAttribute("Delay", StringValue("10us"));
|
||||
|
||||
PointToPointHelper pointToPointT;
|
||||
pointToPointT.SetDeviceAttribute ("DataRate", StringValue ("10Gbps"));
|
||||
pointToPointT.SetChannelAttribute ("Delay", StringValue ("10us"));
|
||||
// Create a total of 62 links.
|
||||
std::vector<NetDeviceContainer> S1T1;
|
||||
S1T1.reserve(10);
|
||||
std::vector<NetDeviceContainer> S2T1;
|
||||
S2T1.reserve(20);
|
||||
std::vector<NetDeviceContainer> S3T2;
|
||||
S3T2.reserve(10);
|
||||
std::vector<NetDeviceContainer> R2T2;
|
||||
R2T2.reserve(20);
|
||||
NetDeviceContainer T1T2 = pointToPointT.Install(T1, T2);
|
||||
NetDeviceContainer R1T2 = pointToPointSR.Install(R1, T2);
|
||||
|
||||
|
||||
// Create a total of 62 links.
|
||||
std::vector<NetDeviceContainer> S1T1;
|
||||
S1T1.reserve (10);
|
||||
std::vector<NetDeviceContainer> S2T1;
|
||||
S2T1.reserve (20);
|
||||
std::vector<NetDeviceContainer> S3T2;
|
||||
S3T2.reserve (10);
|
||||
std::vector<NetDeviceContainer> R2T2;
|
||||
R2T2.reserve (20);
|
||||
NetDeviceContainer T1T2 = pointToPointT.Install (T1, T2);
|
||||
NetDeviceContainer R1T2 = pointToPointSR.Install (R1, T2);
|
||||
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
Ptr<Node> n = S1.Get (i);
|
||||
S1T1.push_back (pointToPointSR.Install (n, T1));
|
||||
Ptr<Node> n = S1.Get(i);
|
||||
S1T1.push_back(pointToPointSR.Install(n, T1));
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
Ptr<Node> n = S2.Get (i);
|
||||
S2T1.push_back (pointToPointSR.Install (n, T1));
|
||||
Ptr<Node> n = S2.Get(i);
|
||||
S2T1.push_back(pointToPointSR.Install(n, T1));
|
||||
}
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
Ptr<Node> n = S3.Get (i);
|
||||
S3T2.push_back (pointToPointSR.Install (n, T2));
|
||||
Ptr<Node> n = S3.Get(i);
|
||||
S3T2.push_back(pointToPointSR.Install(n, T2));
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
Ptr<Node> n = R2.Get (i);
|
||||
R2T2.push_back (pointToPointSR.Install (n, T2));
|
||||
Ptr<Node> n = R2.Get(i);
|
||||
R2T2.push_back(pointToPointSR.Install(n, T2));
|
||||
}
|
||||
|
||||
InternetStackHelper stack;
|
||||
stack.InstallAll ();
|
||||
InternetStackHelper stack;
|
||||
stack.InstallAll();
|
||||
|
||||
TrafficControlHelper tchRed10;
|
||||
// MinTh = 50, MaxTh = 150 recommended in ACM SIGCOMM 2010 DCTCP Paper
|
||||
// This yields a target (MinTh) queue depth of 60us at 10 Gb/s
|
||||
tchRed10.SetRootQueueDisc ("ns3::RedQueueDisc",
|
||||
"LinkBandwidth", StringValue ("10Gbps"),
|
||||
"LinkDelay", StringValue ("10us"),
|
||||
"MinTh", DoubleValue (50),
|
||||
"MaxTh", DoubleValue (150));
|
||||
QueueDiscContainer queueDiscs1 = tchRed10.Install (T1T2);
|
||||
TrafficControlHelper tchRed10;
|
||||
// MinTh = 50, MaxTh = 150 recommended in ACM SIGCOMM 2010 DCTCP Paper
|
||||
// This yields a target (MinTh) queue depth of 60us at 10 Gb/s
|
||||
tchRed10.SetRootQueueDisc("ns3::RedQueueDisc",
|
||||
"LinkBandwidth",
|
||||
StringValue("10Gbps"),
|
||||
"LinkDelay",
|
||||
StringValue("10us"),
|
||||
"MinTh",
|
||||
DoubleValue(50),
|
||||
"MaxTh",
|
||||
DoubleValue(150));
|
||||
QueueDiscContainer queueDiscs1 = tchRed10.Install(T1T2);
|
||||
|
||||
TrafficControlHelper tchRed1;
|
||||
// MinTh = 20, MaxTh = 60 recommended in ACM SIGCOMM 2010 DCTCP Paper
|
||||
// This yields a target queue depth of 250us at 1 Gb/s
|
||||
tchRed1.SetRootQueueDisc ("ns3::RedQueueDisc",
|
||||
"LinkBandwidth", StringValue ("1Gbps"),
|
||||
"LinkDelay", StringValue ("10us"),
|
||||
"MinTh", DoubleValue (20),
|
||||
"MaxTh", DoubleValue (60));
|
||||
QueueDiscContainer queueDiscs2 = tchRed1.Install (R1T2.Get (1));
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
TrafficControlHelper tchRed1;
|
||||
// MinTh = 20, MaxTh = 60 recommended in ACM SIGCOMM 2010 DCTCP Paper
|
||||
// This yields a target queue depth of 250us at 1 Gb/s
|
||||
tchRed1.SetRootQueueDisc("ns3::RedQueueDisc",
|
||||
"LinkBandwidth",
|
||||
StringValue("1Gbps"),
|
||||
"LinkDelay",
|
||||
StringValue("10us"),
|
||||
"MinTh",
|
||||
DoubleValue(20),
|
||||
"MaxTh",
|
||||
DoubleValue(60));
|
||||
QueueDiscContainer queueDiscs2 = tchRed1.Install(R1T2.Get(1));
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
tchRed1.Install (S1T1[i].Get (1));
|
||||
tchRed1.Install(S1T1[i].Get(1));
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
tchRed1.Install (S2T1[i].Get (1));
|
||||
tchRed1.Install(S2T1[i].Get(1));
|
||||
}
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
tchRed1.Install (S3T2[i].Get (1));
|
||||
tchRed1.Install(S3T2[i].Get(1));
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
tchRed1.Install (R2T2[i].Get (1));
|
||||
tchRed1.Install(R2T2[i].Get(1));
|
||||
}
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
std::vector<Ipv4InterfaceContainer> ipS1T1;
|
||||
ipS1T1.reserve (10);
|
||||
std::vector<Ipv4InterfaceContainer> ipS2T1;
|
||||
ipS2T1.reserve (20);
|
||||
std::vector<Ipv4InterfaceContainer> ipS3T2;
|
||||
ipS3T2.reserve (10);
|
||||
std::vector<Ipv4InterfaceContainer> ipR2T2;
|
||||
ipR2T2.reserve (20);
|
||||
address.SetBase ("172.16.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer ipT1T2 = address.Assign (T1T2);
|
||||
address.SetBase ("192.168.0.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer ipR1T2 = address.Assign (R1T2);
|
||||
address.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
Ipv4AddressHelper address;
|
||||
std::vector<Ipv4InterfaceContainer> ipS1T1;
|
||||
ipS1T1.reserve(10);
|
||||
std::vector<Ipv4InterfaceContainer> ipS2T1;
|
||||
ipS2T1.reserve(20);
|
||||
std::vector<Ipv4InterfaceContainer> ipS3T2;
|
||||
ipS3T2.reserve(10);
|
||||
std::vector<Ipv4InterfaceContainer> ipR2T2;
|
||||
ipR2T2.reserve(20);
|
||||
address.SetBase("172.16.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer ipT1T2 = address.Assign(T1T2);
|
||||
address.SetBase("192.168.0.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer ipR1T2 = address.Assign(R1T2);
|
||||
address.SetBase("10.1.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
ipS1T1.push_back (address.Assign (S1T1[i]));
|
||||
address.NewNetwork ();
|
||||
ipS1T1.push_back(address.Assign(S1T1[i]));
|
||||
address.NewNetwork();
|
||||
}
|
||||
address.SetBase ("10.2.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
address.SetBase("10.2.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
ipS2T1.push_back (address.Assign (S2T1[i]));
|
||||
address.NewNetwork ();
|
||||
ipS2T1.push_back(address.Assign(S2T1[i]));
|
||||
address.NewNetwork();
|
||||
}
|
||||
address.SetBase ("10.3.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
address.SetBase("10.3.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
ipS3T2.push_back (address.Assign (S3T2[i]));
|
||||
address.NewNetwork ();
|
||||
ipS3T2.push_back(address.Assign(S3T2[i]));
|
||||
address.NewNetwork();
|
||||
}
|
||||
address.SetBase ("10.4.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
address.SetBase("10.4.1.0", "255.255.255.0");
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
ipR2T2.push_back (address.Assign (R2T2[i]));
|
||||
address.NewNetwork ();
|
||||
ipR2T2.push_back(address.Assign(R2T2[i]));
|
||||
address.NewNetwork();
|
||||
}
|
||||
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
|
||||
|
||||
// Each sender in S2 sends to a receiver in R2
|
||||
std::vector<Ptr<PacketSink> > r2Sinks;
|
||||
r2Sinks.reserve (20);
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
// Each sender in S2 sends to a receiver in R2
|
||||
std::vector<Ptr<PacketSink>> r2Sinks;
|
||||
r2Sinks.reserve(20);
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
uint16_t port = 50000 + i;
|
||||
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (R2.Get (i));
|
||||
Ptr<PacketSink> packetSink = sinkApp.Get (0)->GetObject<PacketSink> ();
|
||||
r2Sinks.push_back (packetSink);
|
||||
sinkApp.Start (startTime);
|
||||
sinkApp.Stop (stopTime);
|
||||
uint16_t port = 50000 + i;
|
||||
Address sinkLocalAddress(InetSocketAddress(Ipv4Address::GetAny(), port));
|
||||
PacketSinkHelper sinkHelper("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp = sinkHelper.Install(R2.Get(i));
|
||||
Ptr<PacketSink> packetSink = sinkApp.Get(0)->GetObject<PacketSink>();
|
||||
r2Sinks.push_back(packetSink);
|
||||
sinkApp.Start(startTime);
|
||||
sinkApp.Stop(stopTime);
|
||||
|
||||
OnOffHelper clientHelper1 ("ns3::TcpSocketFactory", Address ());
|
||||
clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("1Gbps")));
|
||||
clientHelper1.SetAttribute ("PacketSize", UintegerValue (1000));
|
||||
OnOffHelper clientHelper1("ns3::TcpSocketFactory", Address());
|
||||
clientHelper1.SetAttribute("OnTime",
|
||||
StringValue("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper1.SetAttribute("OffTime",
|
||||
StringValue("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
clientHelper1.SetAttribute("DataRate", DataRateValue(DataRate("1Gbps")));
|
||||
clientHelper1.SetAttribute("PacketSize", UintegerValue(1000));
|
||||
|
||||
ApplicationContainer clientApps1;
|
||||
AddressValue remoteAddress (InetSocketAddress (ipR2T2[i].GetAddress (0), port));
|
||||
clientHelper1.SetAttribute ("Remote", remoteAddress);
|
||||
clientApps1.Add (clientHelper1.Install (S2.Get (i)));
|
||||
clientApps1.Start (i * flowStartupWindow / 20 + clientStartTime + MilliSeconds (i * 5));
|
||||
clientApps1.Stop (stopTime);
|
||||
ApplicationContainer clientApps1;
|
||||
AddressValue remoteAddress(InetSocketAddress(ipR2T2[i].GetAddress(0), port));
|
||||
clientHelper1.SetAttribute("Remote", remoteAddress);
|
||||
clientApps1.Add(clientHelper1.Install(S2.Get(i)));
|
||||
clientApps1.Start(i * flowStartupWindow / 20 + clientStartTime + MilliSeconds(i * 5));
|
||||
clientApps1.Stop(stopTime);
|
||||
}
|
||||
|
||||
// Each sender in S1 and S3 sends to R1
|
||||
std::vector<Ptr<PacketSink> > s1r1Sinks;
|
||||
std::vector<Ptr<PacketSink> > s3r1Sinks;
|
||||
s1r1Sinks.reserve (10);
|
||||
s3r1Sinks.reserve (10);
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
// Each sender in S1 and S3 sends to R1
|
||||
std::vector<Ptr<PacketSink>> s1r1Sinks;
|
||||
std::vector<Ptr<PacketSink>> s3r1Sinks;
|
||||
s1r1Sinks.reserve(10);
|
||||
s3r1Sinks.reserve(10);
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
uint16_t port = 50000 + i;
|
||||
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (R1);
|
||||
Ptr<PacketSink> packetSink = sinkApp.Get (0)->GetObject<PacketSink> ();
|
||||
if (i < 10)
|
||||
uint16_t port = 50000 + i;
|
||||
Address sinkLocalAddress(InetSocketAddress(Ipv4Address::GetAny(), port));
|
||||
PacketSinkHelper sinkHelper("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp = sinkHelper.Install(R1);
|
||||
Ptr<PacketSink> packetSink = sinkApp.Get(0)->GetObject<PacketSink>();
|
||||
if (i < 10)
|
||||
{
|
||||
s1r1Sinks.push_back (packetSink);
|
||||
s1r1Sinks.push_back(packetSink);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
s3r1Sinks.push_back (packetSink);
|
||||
s3r1Sinks.push_back(packetSink);
|
||||
}
|
||||
sinkApp.Start (startTime);
|
||||
sinkApp.Stop (stopTime);
|
||||
sinkApp.Start(startTime);
|
||||
sinkApp.Stop(stopTime);
|
||||
|
||||
OnOffHelper clientHelper1 ("ns3::TcpSocketFactory", Address ());
|
||||
clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("1Gbps")));
|
||||
clientHelper1.SetAttribute ("PacketSize", UintegerValue (1000));
|
||||
OnOffHelper clientHelper1("ns3::TcpSocketFactory", Address());
|
||||
clientHelper1.SetAttribute("OnTime",
|
||||
StringValue("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper1.SetAttribute("OffTime",
|
||||
StringValue("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
clientHelper1.SetAttribute("DataRate", DataRateValue(DataRate("1Gbps")));
|
||||
clientHelper1.SetAttribute("PacketSize", UintegerValue(1000));
|
||||
|
||||
ApplicationContainer clientApps1;
|
||||
AddressValue remoteAddress (InetSocketAddress (ipR1T2.GetAddress (0), port));
|
||||
clientHelper1.SetAttribute ("Remote", remoteAddress);
|
||||
if (i < 10)
|
||||
ApplicationContainer clientApps1;
|
||||
AddressValue remoteAddress(InetSocketAddress(ipR1T2.GetAddress(0), port));
|
||||
clientHelper1.SetAttribute("Remote", remoteAddress);
|
||||
if (i < 10)
|
||||
{
|
||||
clientApps1.Add (clientHelper1.Install (S1.Get (i)));
|
||||
clientApps1.Start (i * flowStartupWindow / 10 + clientStartTime + MilliSeconds (i * 5));
|
||||
clientApps1.Add(clientHelper1.Install(S1.Get(i)));
|
||||
clientApps1.Start(i * flowStartupWindow / 10 + clientStartTime + MilliSeconds(i * 5));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
clientApps1.Add (clientHelper1.Install (S3.Get (i - 10)));
|
||||
clientApps1.Start ((i - 10) * flowStartupWindow / 10 + clientStartTime + MilliSeconds (i * 5));
|
||||
clientApps1.Add(clientHelper1.Install(S3.Get(i - 10)));
|
||||
clientApps1.Start((i - 10) * flowStartupWindow / 10 + clientStartTime +
|
||||
MilliSeconds(i * 5));
|
||||
}
|
||||
|
||||
clientApps1.Stop (stopTime);
|
||||
clientApps1.Stop(stopTime);
|
||||
}
|
||||
|
||||
rxS1R1Throughput.open ("dctcp-example-s1-r1-throughput.dat", std::ios::out);
|
||||
rxS1R1Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
|
||||
rxS2R2Throughput.open ("dctcp-example-s2-r2-throughput.dat", std::ios::out);
|
||||
rxS2R2Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
|
||||
rxS3R1Throughput.open ("dctcp-example-s3-r1-throughput.dat", std::ios::out);
|
||||
rxS3R1Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
|
||||
fairnessIndex.open ("dctcp-example-fairness.dat", std::ios::out);
|
||||
t1QueueLength.open ("dctcp-example-t1-length.dat", std::ios::out);
|
||||
t1QueueLength << "#Time(s) qlen(pkts) qlen(us)" << std::endl;
|
||||
t2QueueLength.open ("dctcp-example-t2-length.dat", std::ios::out);
|
||||
t2QueueLength << "#Time(s) qlen(pkts) qlen(us)" << std::endl;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
rxS1R1Throughput.open("dctcp-example-s1-r1-throughput.dat", std::ios::out);
|
||||
rxS1R1Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
|
||||
rxS2R2Throughput.open("dctcp-example-s2-r2-throughput.dat", std::ios::out);
|
||||
rxS2R2Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
|
||||
rxS3R1Throughput.open("dctcp-example-s3-r1-throughput.dat", std::ios::out);
|
||||
rxS3R1Throughput << "#Time(s) flow thruput(Mb/s)" << std::endl;
|
||||
fairnessIndex.open("dctcp-example-fairness.dat", std::ios::out);
|
||||
t1QueueLength.open("dctcp-example-t1-length.dat", std::ios::out);
|
||||
t1QueueLength << "#Time(s) qlen(pkts) qlen(us)" << std::endl;
|
||||
t2QueueLength.open("dctcp-example-t2-length.dat", std::ios::out);
|
||||
t2QueueLength << "#Time(s) qlen(pkts) qlen(us)" << std::endl;
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
s1r1Sinks[i]->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&TraceS1R1Sink, i));
|
||||
s1r1Sinks[i]->TraceConnectWithoutContext("Rx", MakeBoundCallback(&TraceS1R1Sink, i));
|
||||
}
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
for (std::size_t i = 0; i < 20; i++)
|
||||
{
|
||||
r2Sinks[i]->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&TraceS2R2Sink, i));
|
||||
r2Sinks[i]->TraceConnectWithoutContext("Rx", MakeBoundCallback(&TraceS2R2Sink, i));
|
||||
}
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
for (std::size_t i = 0; i < 10; i++)
|
||||
{
|
||||
s3r1Sinks[i]->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&TraceS3R1Sink, i));
|
||||
s3r1Sinks[i]->TraceConnectWithoutContext("Rx", MakeBoundCallback(&TraceS3R1Sink, i));
|
||||
}
|
||||
Simulator::Schedule (flowStartupWindow + convergenceTime, &InitializeCounters);
|
||||
Simulator::Schedule (flowStartupWindow + convergenceTime + measurementWindow, &PrintThroughput, measurementWindow);
|
||||
Simulator::Schedule (flowStartupWindow + convergenceTime + measurementWindow, &PrintFairness, measurementWindow);
|
||||
Simulator::Schedule (progressInterval, &PrintProgress, progressInterval);
|
||||
Simulator::Schedule (flowStartupWindow + convergenceTime, &CheckT1QueueSize, queueDiscs1.Get (0));
|
||||
Simulator::Schedule (flowStartupWindow + convergenceTime, &CheckT2QueueSize, queueDiscs2.Get (0));
|
||||
Simulator::Stop (stopTime + TimeStep (1));
|
||||
Simulator::Schedule(flowStartupWindow + convergenceTime, &InitializeCounters);
|
||||
Simulator::Schedule(flowStartupWindow + convergenceTime + measurementWindow,
|
||||
&PrintThroughput,
|
||||
measurementWindow);
|
||||
Simulator::Schedule(flowStartupWindow + convergenceTime + measurementWindow,
|
||||
&PrintFairness,
|
||||
measurementWindow);
|
||||
Simulator::Schedule(progressInterval, &PrintProgress, progressInterval);
|
||||
Simulator::Schedule(flowStartupWindow + convergenceTime, &CheckT1QueueSize, queueDiscs1.Get(0));
|
||||
Simulator::Schedule(flowStartupWindow + convergenceTime, &CheckT2QueueSize, queueDiscs2.Get(0));
|
||||
Simulator::Stop(stopTime + TimeStep(1));
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Run();
|
||||
|
||||
rxS1R1Throughput.close ();
|
||||
rxS2R2Throughput.close ();
|
||||
rxS3R1Throughput.close ();
|
||||
fairnessIndex.close ();
|
||||
t1QueueLength.close ();
|
||||
t2QueueLength.close ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
rxS1R1Throughput.close();
|
||||
rxS2R2Throughput.close();
|
||||
rxS3R1Throughput.close();
|
||||
fairnessIndex.close();
|
||||
t1QueueLength.close();
|
||||
t2QueueLength.close();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -16,7 +15,6 @@
|
||||
* Contributed by: Luis Cortes (cortes@gatech.edu)
|
||||
*/
|
||||
|
||||
|
||||
// This script exercises global routing code in a mixed point-to-point
|
||||
// and csma/cd environment. We bring up and down interfaces and observe
|
||||
// the effect on global routing. We explicitly enable the attribute
|
||||
@@ -29,7 +27,7 @@
|
||||
// \ p-p
|
||||
// \ (shared csma/cd)
|
||||
// n2 -------------------------n3
|
||||
// / | |
|
||||
// / | |
|
||||
// / p-p n4 n5 ---------- n6
|
||||
// n1 p-p
|
||||
// | |
|
||||
@@ -55,177 +53,174 @@
|
||||
// on the n1/n6 p2p link)
|
||||
// At time 12s, bring the n1 interface down between n1 and n6. Packets
|
||||
// will be diverted to the alternate path
|
||||
// At time 14s, re-enable the n1/n6 interface to up. This will change
|
||||
// At time 14s, re-enable the n1/n6 interface to up. This will change
|
||||
// routing back to n1-n6 since the interface up notification will cause
|
||||
// a new local interface route, at higher priority than global routing
|
||||
// At time 16s, stop the second flow.
|
||||
|
||||
// - Tracing of queues and packet receptions to file "dynamic-global-routing.tr"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/csma-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/ipv4-global-routing-helper.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DynamicGlobalRoutingExample");
|
||||
NS_LOG_COMPONENT_DEFINE("DynamicGlobalRoutingExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
// The below value configures the default behavior of global routing.
|
||||
// By default, it is disabled. To respond to interface events, set to true
|
||||
Config::SetDefault("ns3::Ipv4GlobalRouting::RespondToInterfaceEvents", BooleanValue(true));
|
||||
|
||||
// The below value configures the default behavior of global routing.
|
||||
// By default, it is disabled. To respond to interface events, set to true
|
||||
Config::SetDefault ("ns3::Ipv4GlobalRouting::RespondToInterfaceEvents", BooleanValue (true));
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind ()s at run-time, via command-line arguments
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind ()s at run-time, via command-line arguments
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.Parse (argc, argv);
|
||||
NS_LOG_INFO("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create(7);
|
||||
NodeContainer n0n2 = NodeContainer(c.Get(0), c.Get(2));
|
||||
NodeContainer n1n2 = NodeContainer(c.Get(1), c.Get(2));
|
||||
NodeContainer n5n6 = NodeContainer(c.Get(5), c.Get(6));
|
||||
NodeContainer n1n6 = NodeContainer(c.Get(1), c.Get(6));
|
||||
NodeContainer n2345 = NodeContainer(c.Get(2), c.Get(3), c.Get(4), c.Get(5));
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (7);
|
||||
NodeContainer n0n2 = NodeContainer (c.Get (0), c.Get (2));
|
||||
NodeContainer n1n2 = NodeContainer (c.Get (1), c.Get (2));
|
||||
NodeContainer n5n6 = NodeContainer (c.Get (5), c.Get (6));
|
||||
NodeContainer n1n6 = NodeContainer (c.Get (1), c.Get (6));
|
||||
NodeContainer n2345 = NodeContainer (c.Get (2), c.Get (3), c.Get (4), c.Get (5));
|
||||
InternetStackHelper internet;
|
||||
internet.Install(c);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
|
||||
p2p.SetChannelAttribute("Delay", StringValue("2ms"));
|
||||
NetDeviceContainer d0d2 = p2p.Install(n0n2);
|
||||
NetDeviceContainer d1d6 = p2p.Install(n1n6);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer d0d2 = p2p.Install (n0n2);
|
||||
NetDeviceContainer d1d6 = p2p.Install (n1n6);
|
||||
NetDeviceContainer d1d2 = p2p.Install(n1n2);
|
||||
|
||||
NetDeviceContainer d1d2 = p2p.Install (n1n2);
|
||||
p2p.SetDeviceAttribute("DataRate", StringValue("1500kbps"));
|
||||
p2p.SetChannelAttribute("Delay", StringValue("10ms"));
|
||||
NetDeviceContainer d5d6 = p2p.Install(n5n6);
|
||||
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("1500kbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("10ms"));
|
||||
NetDeviceContainer d5d6 = p2p.Install (n5n6);
|
||||
// We create the channels first without any IP addressing information
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelAttribute("DataRate", StringValue("5Mbps"));
|
||||
csma.SetChannelAttribute("Delay", StringValue("2ms"));
|
||||
NetDeviceContainer d2345 = csma.Install(n2345);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
csma.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer d2345 = csma.Install (n2345);
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase("10.1.1.0", "255.255.255.0");
|
||||
ipv4.Assign(d0d2);
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
ipv4.Assign (d0d2);
|
||||
ipv4.SetBase("10.1.2.0", "255.255.255.0");
|
||||
ipv4.Assign(d1d2);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
ipv4.Assign (d1d2);
|
||||
ipv4.SetBase("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i5i6 = ipv4.Assign(d5d6);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i5i6 = ipv4.Assign (d5d6);
|
||||
ipv4.SetBase("10.250.1.0", "255.255.255.0");
|
||||
ipv4.Assign(d2345);
|
||||
|
||||
ipv4.SetBase ("10.250.1.0", "255.255.255.0");
|
||||
ipv4.Assign (d2345);
|
||||
ipv4.SetBase("172.16.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i1i6 = ipv4.Assign(d1d6);
|
||||
|
||||
ipv4.SetBase ("172.16.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i1i6 = ipv4.Assign (d1d6);
|
||||
// Create router nodes, initialize routing database and set up the routing
|
||||
// tables in the nodes.
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
|
||||
|
||||
// Create router nodes, initialize routing database and set up the routing
|
||||
// tables in the nodes.
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
OnOffHelper onoff("ns3::UdpSocketFactory", InetSocketAddress(i5i6.GetAddress(1), port));
|
||||
onoff.SetConstantRate(DataRate("2kbps"));
|
||||
onoff.SetAttribute("PacketSize", UintegerValue(50));
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (i5i6.GetAddress (1), port));
|
||||
onoff.SetConstantRate (DataRate ("2kbps"));
|
||||
onoff.SetAttribute ("PacketSize", UintegerValue (50));
|
||||
ApplicationContainer apps = onoff.Install(c.Get(1));
|
||||
apps.Start(Seconds(1.0));
|
||||
apps.Stop(Seconds(10.0));
|
||||
|
||||
ApplicationContainer apps = onoff.Install (c.Get (1));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
// Create a second OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
OnOffHelper onoff2("ns3::UdpSocketFactory", InetSocketAddress(i1i6.GetAddress(1), port));
|
||||
onoff2.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onoff2.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onoff2.SetAttribute("DataRate", StringValue("2kbps"));
|
||||
onoff2.SetAttribute("PacketSize", UintegerValue(50));
|
||||
|
||||
// Create a second OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
OnOffHelper onoff2 ("ns3::UdpSocketFactory",
|
||||
InetSocketAddress (i1i6.GetAddress (1), port));
|
||||
onoff2.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onoff2.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onoff2.SetAttribute ("DataRate", StringValue ("2kbps"));
|
||||
onoff2.SetAttribute ("PacketSize", UintegerValue (50));
|
||||
ApplicationContainer apps2 = onoff2.Install(c.Get(1));
|
||||
apps2.Start(Seconds(11.0));
|
||||
apps2.Stop(Seconds(16.0));
|
||||
|
||||
ApplicationContainer apps2 = onoff2.Install (c.Get (1));
|
||||
apps2.Start (Seconds (11.0));
|
||||
apps2.Stop (Seconds (16.0));
|
||||
// Create an optional packet sink to receive these packets
|
||||
PacketSinkHelper sink("ns3::UdpSocketFactory",
|
||||
Address(InetSocketAddress(Ipv4Address::GetAny(), port)));
|
||||
apps = sink.Install(c.Get(6));
|
||||
apps.Start(Seconds(1.0));
|
||||
apps.Stop(Seconds(10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
apps = sink.Install (c.Get (6));
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
PacketSinkHelper sink2("ns3::UdpSocketFactory",
|
||||
Address(InetSocketAddress(Ipv4Address::GetAny(), port)));
|
||||
apps2 = sink2.Install(c.Get(6));
|
||||
apps2.Start(Seconds(11.0));
|
||||
apps2.Stop(Seconds(16.0));
|
||||
|
||||
PacketSinkHelper sink2 ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
apps2 = sink2.Install (c.Get (6));
|
||||
apps2.Start (Seconds (11.0));
|
||||
apps2.Stop (Seconds (16.0));
|
||||
AsciiTraceHelper ascii;
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream("dynamic-global-routing.tr");
|
||||
p2p.EnableAsciiAll(stream);
|
||||
csma.EnableAsciiAll(stream);
|
||||
internet.EnableAsciiIpv4All(stream);
|
||||
|
||||
p2p.EnablePcapAll("dynamic-global-routing");
|
||||
csma.EnablePcapAll("dynamic-global-routing", false);
|
||||
|
||||
AsciiTraceHelper ascii;
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream ("dynamic-global-routing.tr");
|
||||
p2p.EnableAsciiAll (stream);
|
||||
csma.EnableAsciiAll (stream);
|
||||
internet.EnableAsciiIpv4All (stream);
|
||||
Ptr<Node> n1 = c.Get(1);
|
||||
Ptr<Ipv4> ipv41 = n1->GetObject<Ipv4>();
|
||||
// The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
|
||||
// then the next p2p is numbered 2
|
||||
uint32_t ipv4ifIndex1 = 2;
|
||||
|
||||
p2p.EnablePcapAll ("dynamic-global-routing");
|
||||
csma.EnablePcapAll ("dynamic-global-routing", false);
|
||||
|
||||
Ptr<Node> n1 = c.Get (1);
|
||||
Ptr<Ipv4> ipv41 = n1->GetObject<Ipv4> ();
|
||||
// The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
|
||||
// then the next p2p is numbered 2
|
||||
uint32_t ipv4ifIndex1 = 2;
|
||||
Simulator::Schedule(Seconds(2), &Ipv4::SetDown, ipv41, ipv4ifIndex1);
|
||||
Simulator::Schedule(Seconds(4), &Ipv4::SetUp, ipv41, ipv4ifIndex1);
|
||||
|
||||
Simulator::Schedule (Seconds (2),&Ipv4::SetDown,ipv41, ipv4ifIndex1);
|
||||
Simulator::Schedule (Seconds (4),&Ipv4::SetUp,ipv41, ipv4ifIndex1);
|
||||
Ptr<Node> n6 = c.Get(6);
|
||||
Ptr<Ipv4> ipv46 = n6->GetObject<Ipv4>();
|
||||
// The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
|
||||
// then the next p2p is numbered 2
|
||||
uint32_t ipv4ifIndex6 = 2;
|
||||
Simulator::Schedule(Seconds(6), &Ipv4::SetDown, ipv46, ipv4ifIndex6);
|
||||
Simulator::Schedule(Seconds(8), &Ipv4::SetUp, ipv46, ipv4ifIndex6);
|
||||
|
||||
Ptr<Node> n6 = c.Get (6);
|
||||
Ptr<Ipv4> ipv46 = n6->GetObject<Ipv4> ();
|
||||
// The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
|
||||
// then the next p2p is numbered 2
|
||||
uint32_t ipv4ifIndex6 = 2;
|
||||
Simulator::Schedule (Seconds (6),&Ipv4::SetDown,ipv46, ipv4ifIndex6);
|
||||
Simulator::Schedule (Seconds (8),&Ipv4::SetUp,ipv46, ipv4ifIndex6);
|
||||
Simulator::Schedule(Seconds(12), &Ipv4::SetDown, ipv41, ipv4ifIndex1);
|
||||
Simulator::Schedule(Seconds(14), &Ipv4::SetUp, ipv41, ipv4ifIndex1);
|
||||
|
||||
Simulator::Schedule (Seconds (12),&Ipv4::SetDown,ipv41, ipv4ifIndex1);
|
||||
Simulator::Schedule (Seconds (14),&Ipv4::SetUp,ipv41, ipv4ifIndex1);
|
||||
// Trace routing tables
|
||||
Ipv4GlobalRoutingHelper g;
|
||||
Ptr<OutputStreamWrapper> routingStream =
|
||||
Create<OutputStreamWrapper>("dynamic-global-routing.routes", std::ios::out);
|
||||
g.PrintRoutingTableAllAt(Seconds(12), routingStream);
|
||||
|
||||
// Trace routing tables
|
||||
Ipv4GlobalRoutingHelper g;
|
||||
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("dynamic-global-routing.routes", std::ios::out);
|
||||
g.PrintRoutingTableAllAt (Seconds (12), routingStream);
|
||||
NS_LOG_INFO("Run Simulation.");
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
NS_LOG_INFO("Done.");
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 Universita' degli Studi di Napoli Federico II
|
||||
*
|
||||
@@ -27,10 +26,11 @@
|
||||
// n1 ------------------------------------ n2 ----------------------------------- n3
|
||||
// point-to-point (access link) point-to-point (bottleneck link)
|
||||
// 100 Mbps, 0.1 ms bandwidth [10 Mbps], delay [5 ms]
|
||||
// qdiscs PfifoFast with capacity qdiscs queueDiscType in {PfifoFast, ARED, CoDel, FqCoDel, PIE} [PfifoFast]
|
||||
// of 1000 packets with capacity of queueDiscSize packets [1000]
|
||||
// netdevices queues with size of 100 packets netdevices queues with size of netdevicesQueueSize packets [100]
|
||||
// without BQL bql BQL [false]
|
||||
// qdiscs PfifoFast with capacity qdiscs queueDiscType in {PfifoFast, ARED, CoDel,
|
||||
// FqCoDel, PIE} [PfifoFast] of 1000 packets with capacity of
|
||||
// queueDiscSize packets [1000] netdevices queues with size of 100 packets netdevices queues with
|
||||
// size of netdevicesQueueSize packets [100] without BQL bql BQL
|
||||
// [false]
|
||||
// *** fixed configuration ***
|
||||
//
|
||||
// Two TCP flows are generated: one from n1 to n3 and the other from n3 to n1.
|
||||
@@ -53,263 +53,319 @@
|
||||
// If you use an AQM as queue disc on the bottleneck netdevices, you can observe that the ping Rtt
|
||||
// decrease. A further decrease can be observed when you enable BQL.
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/internet-apps-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/flow-monitor-module.h"
|
||||
#include "ns3/mtp-interface.h"
|
||||
#include "ns3/internet-apps-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("BenchmarkQueueDiscs");
|
||||
NS_LOG_COMPONENT_DEFINE("BenchmarkQueueDiscs");
|
||||
|
||||
/**
|
||||
* Print the queue limitis.
|
||||
*
|
||||
* \param stream The ouput stream.
|
||||
* \param oldVal Old value.
|
||||
* \param newVal New value.
|
||||
*/
|
||||
void
|
||||
LimitsTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
|
||||
LimitsTrace(Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
|
||||
{
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
|
||||
*stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the bytes in the queue.
|
||||
*
|
||||
* \param stream The ouput stream.
|
||||
* \param oldVal Old value.
|
||||
* \param newVal New value.
|
||||
*/
|
||||
void
|
||||
BytesInQueueTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
|
||||
BytesInQueueTrace(Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
|
||||
{
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
|
||||
*stream->GetStream() << Simulator::Now().GetSeconds() << " " << newVal << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample and print the queue goodput.
|
||||
*
|
||||
* \param app The Tx app.
|
||||
* \param stream The ouput stream.
|
||||
* \param period The sampling period.
|
||||
*/
|
||||
static void
|
||||
GoodputSampling (std::string fileName, ApplicationContainer app, Ptr<OutputStreamWrapper> stream, float period)
|
||||
GoodputSampling(ApplicationContainer app, Ptr<OutputStreamWrapper> stream, float period)
|
||||
{
|
||||
Simulator::Schedule (Seconds (period), &GoodputSampling, fileName, app, stream, period);
|
||||
double goodput;
|
||||
uint64_t totalPackets = DynamicCast<PacketSink> (app.Get (0))->GetTotalRx ();
|
||||
goodput = totalPackets * 8 / (Simulator::Now ().GetSeconds () * 1024); // Kbit/s
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << goodput << std::endl;
|
||||
Simulator::Schedule(Seconds(period), &GoodputSampling, app, stream, period);
|
||||
double goodput;
|
||||
uint64_t totalPackets = DynamicCast<PacketSink>(app.Get(0))->GetTotalRx();
|
||||
goodput = totalPackets * 8 / (Simulator::Now().GetSeconds() * 1024); // Kbit/s
|
||||
*stream->GetStream() << Simulator::Now().GetSeconds() << " " << goodput << std::endl;
|
||||
}
|
||||
|
||||
static void PingRtt (std::string context, Time rtt)
|
||||
/**
|
||||
* Print the ping RTT.
|
||||
*
|
||||
* \param context The context.
|
||||
* \param rtt The RTT.
|
||||
*/
|
||||
static void
|
||||
PingRtt(std::string context, Time rtt)
|
||||
{
|
||||
std::cout << context << "=" << rtt.GetMilliSeconds () << " ms" << std::endl;
|
||||
std::cout << context << "=" << rtt.GetMilliSeconds() << " ms" << std::endl;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
std::string bandwidth = "10Mbps";
|
||||
std::string delay = "5ms";
|
||||
std::string queueDiscType = "PfifoFast";
|
||||
uint32_t queueDiscSize = 1000;
|
||||
uint32_t netdevicesQueueSize = 50;
|
||||
bool bql = false;
|
||||
|
||||
std::string bandwidth = "10Mbps";
|
||||
std::string delay = "5ms";
|
||||
std::string queueDiscType = "PfifoFast";
|
||||
uint32_t queueDiscSize = 1000;
|
||||
uint32_t netdevicesQueueSize = 50;
|
||||
bool bql = false;
|
||||
std::string flowsDatarate = "20Mbps";
|
||||
uint32_t flowsPacketsSize = 1000;
|
||||
|
||||
std::string flowsDatarate = "20Mbps";
|
||||
uint32_t flowsPacketsSize = 1000;
|
||||
float startTime = 0.1F; // in s
|
||||
float simDuration = 60;
|
||||
float samplingPeriod = 1;
|
||||
|
||||
float startTime = 0.1f; // in s
|
||||
float simDuration = 60;
|
||||
float samplingPeriod = 1;
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.AddValue("bandwidth", "Bottleneck bandwidth", bandwidth);
|
||||
cmd.AddValue("delay", "Bottleneck delay", delay);
|
||||
cmd.AddValue("queueDiscType",
|
||||
"Bottleneck queue disc type in {PfifoFast, ARED, CoDel, FqCoDel, PIE, prio}",
|
||||
queueDiscType);
|
||||
cmd.AddValue("queueDiscSize", "Bottleneck queue disc size in packets", queueDiscSize);
|
||||
cmd.AddValue("netdevicesQueueSize",
|
||||
"Bottleneck netdevices queue size in packets",
|
||||
netdevicesQueueSize);
|
||||
cmd.AddValue("bql", "Enable byte queue limits on bottleneck netdevices", bql);
|
||||
cmd.AddValue("flowsDatarate", "Upload and download flows datarate", flowsDatarate);
|
||||
cmd.AddValue("flowsPacketsSize", "Upload and download flows packets sizes", flowsPacketsSize);
|
||||
cmd.AddValue("startTime", "Simulation start time", startTime);
|
||||
cmd.AddValue("simDuration", "Simulation duration in seconds", simDuration);
|
||||
cmd.AddValue("samplingPeriod", "Goodput sampling period in seconds", samplingPeriod);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("bandwidth", "Bottleneck bandwidth", bandwidth);
|
||||
cmd.AddValue ("delay", "Bottleneck delay", delay);
|
||||
cmd.AddValue ("queueDiscType", "Bottleneck queue disc type in {PfifoFast, ARED, CoDel, FqCoDel, PIE, prio}", queueDiscType);
|
||||
cmd.AddValue ("queueDiscSize", "Bottleneck queue disc size in packets", queueDiscSize);
|
||||
cmd.AddValue ("netdevicesQueueSize", "Bottleneck netdevices queue size in packets", netdevicesQueueSize);
|
||||
cmd.AddValue ("bql", "Enable byte queue limits on bottleneck netdevices", bql);
|
||||
cmd.AddValue ("flowsDatarate", "Upload and download flows datarate", flowsDatarate);
|
||||
cmd.AddValue ("flowsPacketsSize", "Upload and download flows packets sizes", flowsPacketsSize);
|
||||
cmd.AddValue ("startTime", "Simulation start time", startTime);
|
||||
cmd.AddValue ("simDuration", "Simulation duration in seconds", simDuration);
|
||||
cmd.AddValue ("samplingPeriod", "Goodput sampling period in seconds", samplingPeriod);
|
||||
cmd.Parse (argc, argv);
|
||||
float stopTime = startTime + simDuration;
|
||||
|
||||
float stopTime = startTime + simDuration;
|
||||
// Create nodes
|
||||
NodeContainer n1;
|
||||
NodeContainer n2;
|
||||
NodeContainer n3;
|
||||
n1.Create(1);
|
||||
n2.Create(1);
|
||||
n3.Create(1);
|
||||
|
||||
// Create nodes
|
||||
NodeContainer n1, n2, n3;
|
||||
n1.Create (1);
|
||||
n2.Create (1);
|
||||
n3.Create (1);
|
||||
// Create and configure access link and bottleneck link
|
||||
PointToPointHelper accessLink;
|
||||
accessLink.SetDeviceAttribute("DataRate", StringValue("100Mbps"));
|
||||
accessLink.SetChannelAttribute("Delay", StringValue("0.1ms"));
|
||||
accessLink.SetQueue("ns3::DropTailQueue", "MaxSize", StringValue("100p"));
|
||||
|
||||
// Create and configure access link and bottleneck link
|
||||
PointToPointHelper accessLink;
|
||||
accessLink.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
|
||||
accessLink.SetChannelAttribute ("Delay", StringValue ("0.1ms"));
|
||||
accessLink.SetQueue ("ns3::DropTailQueue", "MaxSize", StringValue ("100p"));
|
||||
PointToPointHelper bottleneckLink;
|
||||
bottleneckLink.SetDeviceAttribute("DataRate", StringValue(bandwidth));
|
||||
bottleneckLink.SetChannelAttribute("Delay", StringValue(delay));
|
||||
bottleneckLink.SetQueue("ns3::DropTailQueue",
|
||||
"MaxSize",
|
||||
StringValue(std::to_string(netdevicesQueueSize) + "p"));
|
||||
|
||||
PointToPointHelper bottleneckLink;
|
||||
bottleneckLink.SetDeviceAttribute ("DataRate", StringValue (bandwidth));
|
||||
bottleneckLink.SetChannelAttribute ("Delay", StringValue (delay));
|
||||
bottleneckLink.SetQueue ("ns3::DropTailQueue", "MaxSize", StringValue (std::to_string (netdevicesQueueSize) + "p"));
|
||||
InternetStackHelper stack;
|
||||
stack.InstallAll();
|
||||
|
||||
InternetStackHelper stack;
|
||||
stack.InstallAll ();
|
||||
// Access link traffic control configuration
|
||||
TrafficControlHelper tchPfifoFastAccess;
|
||||
tchPfifoFastAccess.SetRootQueueDisc("ns3::PfifoFastQueueDisc", "MaxSize", StringValue("1000p"));
|
||||
|
||||
// Access link traffic control configuration
|
||||
TrafficControlHelper tchPfifoFastAccess;
|
||||
tchPfifoFastAccess.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "MaxSize", StringValue ("1000p"));
|
||||
// Bottleneck link traffic control configuration
|
||||
TrafficControlHelper tchBottleneck;
|
||||
|
||||
// Bottleneck link traffic control configuration
|
||||
TrafficControlHelper tchBottleneck;
|
||||
|
||||
if (queueDiscType.compare ("PfifoFast") == 0)
|
||||
if (queueDiscType == "PfifoFast")
|
||||
{
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "MaxSize",
|
||||
QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
tchBottleneck.SetRootQueueDisc(
|
||||
"ns3::PfifoFastQueueDisc",
|
||||
"MaxSize",
|
||||
QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
}
|
||||
else if (queueDiscType.compare ("ARED") == 0)
|
||||
else if (queueDiscType == "ARED")
|
||||
{
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
|
||||
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::RedQueueDisc::MaxSize",
|
||||
QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
tchBottleneck.SetRootQueueDisc("ns3::RedQueueDisc");
|
||||
Config::SetDefault("ns3::RedQueueDisc::ARED", BooleanValue(true));
|
||||
Config::SetDefault("ns3::RedQueueDisc::MaxSize",
|
||||
QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
}
|
||||
else if (queueDiscType.compare ("CoDel") == 0)
|
||||
else if (queueDiscType == "CoDel")
|
||||
{
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::CoDelQueueDisc");
|
||||
Config::SetDefault ("ns3::CoDelQueueDisc::MaxSize",
|
||||
QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
tchBottleneck.SetRootQueueDisc("ns3::CoDelQueueDisc");
|
||||
Config::SetDefault("ns3::CoDelQueueDisc::MaxSize",
|
||||
QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
}
|
||||
else if (queueDiscType.compare ("FqCoDel") == 0)
|
||||
else if (queueDiscType == "FqCoDel")
|
||||
{
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
|
||||
Config::SetDefault ("ns3::FqCoDelQueueDisc::MaxSize",
|
||||
QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
tchBottleneck.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
|
||||
Config::SetDefault("ns3::FqCoDelQueueDisc::MaxSize",
|
||||
QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
}
|
||||
else if (queueDiscType.compare ("PIE") == 0)
|
||||
else if (queueDiscType == "PIE")
|
||||
{
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::PieQueueDisc");
|
||||
Config::SetDefault ("ns3::PieQueueDisc::MaxSize",
|
||||
QueueSizeValue (QueueSize (QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
tchBottleneck.SetRootQueueDisc("ns3::PieQueueDisc");
|
||||
Config::SetDefault("ns3::PieQueueDisc::MaxSize",
|
||||
QueueSizeValue(QueueSize(QueueSizeUnit::PACKETS, queueDiscSize)));
|
||||
}
|
||||
else if (queueDiscType.compare ("prio") == 0)
|
||||
else if (queueDiscType == "prio")
|
||||
{
|
||||
uint16_t handle = tchBottleneck.SetRootQueueDisc ("ns3::PrioQueueDisc", "Priomap",
|
||||
StringValue ("0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1"));
|
||||
TrafficControlHelper::ClassIdList cid = tchBottleneck.AddQueueDiscClasses (handle, 2, "ns3::QueueDiscClass");
|
||||
tchBottleneck.AddChildQueueDisc (handle, cid[0], "ns3::FifoQueueDisc");
|
||||
tchBottleneck.AddChildQueueDisc (handle, cid[1], "ns3::RedQueueDisc");
|
||||
uint16_t handle =
|
||||
tchBottleneck.SetRootQueueDisc("ns3::PrioQueueDisc",
|
||||
"Priomap",
|
||||
StringValue("0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1"));
|
||||
TrafficControlHelper::ClassIdList cid =
|
||||
tchBottleneck.AddQueueDiscClasses(handle, 2, "ns3::QueueDiscClass");
|
||||
tchBottleneck.AddChildQueueDisc(handle, cid[0], "ns3::FifoQueueDisc");
|
||||
tchBottleneck.AddChildQueueDisc(handle, cid[1], "ns3::RedQueueDisc");
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("--queueDiscType not valid");
|
||||
NS_ABORT_MSG("--queueDiscType not valid");
|
||||
}
|
||||
|
||||
if (bql)
|
||||
if (bql)
|
||||
{
|
||||
tchBottleneck.SetQueueLimits ("ns3::DynamicQueueLimits");
|
||||
tchBottleneck.SetQueueLimits("ns3::DynamicQueueLimits");
|
||||
}
|
||||
|
||||
NetDeviceContainer devicesAccessLink = accessLink.Install (n1.Get (0), n2.Get (0));
|
||||
tchPfifoFastAccess.Install (devicesAccessLink);
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase ("192.168.0.0", "255.255.255.0");
|
||||
address.NewNetwork ();
|
||||
Ipv4InterfaceContainer interfacesAccess = address.Assign (devicesAccessLink);
|
||||
NetDeviceContainer devicesAccessLink = accessLink.Install(n1.Get(0), n2.Get(0));
|
||||
tchPfifoFastAccess.Install(devicesAccessLink);
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase("192.168.0.0", "255.255.255.0");
|
||||
address.NewNetwork();
|
||||
Ipv4InterfaceContainer interfacesAccess = address.Assign(devicesAccessLink);
|
||||
|
||||
NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install (n2.Get (0), n3.Get (0));
|
||||
QueueDiscContainer qdiscs;
|
||||
qdiscs = tchBottleneck.Install (devicesBottleneckLink);
|
||||
NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install(n2.Get(0), n3.Get(0));
|
||||
QueueDiscContainer qdiscs;
|
||||
qdiscs = tchBottleneck.Install(devicesBottleneckLink);
|
||||
|
||||
address.NewNetwork ();
|
||||
Ipv4InterfaceContainer interfacesBottleneck = address.Assign (devicesBottleneckLink);
|
||||
address.NewNetwork();
|
||||
Ipv4InterfaceContainer interfacesBottleneck = address.Assign(devicesBottleneckLink);
|
||||
|
||||
Ptr<NetDeviceQueueInterface> interface = devicesBottleneckLink.Get (0)->GetObject<NetDeviceQueueInterface> ();
|
||||
Ptr<NetDeviceQueue> queueInterface = interface->GetTxQueue (0);
|
||||
Ptr<DynamicQueueLimits> queueLimits = StaticCast<DynamicQueueLimits> (queueInterface->GetQueueLimits ());
|
||||
Ptr<NetDeviceQueueInterface> interface =
|
||||
devicesBottleneckLink.Get(0)->GetObject<NetDeviceQueueInterface>();
|
||||
Ptr<NetDeviceQueue> queueInterface = interface->GetTxQueue(0);
|
||||
Ptr<DynamicQueueLimits> queueLimits =
|
||||
StaticCast<DynamicQueueLimits>(queueInterface->GetQueueLimits());
|
||||
|
||||
AsciiTraceHelper ascii;
|
||||
if (bql)
|
||||
AsciiTraceHelper ascii;
|
||||
if (bql)
|
||||
{
|
||||
queueDiscType = queueDiscType + "-bql";
|
||||
Ptr<OutputStreamWrapper> streamLimits = ascii.CreateFileStream (queueDiscType + "-limits.txt");
|
||||
queueLimits->TraceConnectWithoutContext ("Limit",MakeBoundCallback (&LimitsTrace, streamLimits));
|
||||
queueDiscType = queueDiscType + "-bql";
|
||||
Ptr<OutputStreamWrapper> streamLimits =
|
||||
ascii.CreateFileStream(queueDiscType + "-limits.txt");
|
||||
queueLimits->TraceConnectWithoutContext("Limit",
|
||||
MakeBoundCallback(&LimitsTrace, streamLimits));
|
||||
}
|
||||
Ptr<Queue<Packet> > queue = StaticCast<PointToPointNetDevice> (devicesBottleneckLink.Get (0))->GetQueue ();
|
||||
Ptr<OutputStreamWrapper> streamBytesInQueue = ascii.CreateFileStream (queueDiscType + "-bytesInQueue.txt");
|
||||
queue->TraceConnectWithoutContext ("BytesInQueue",MakeBoundCallback (&BytesInQueueTrace, streamBytesInQueue));
|
||||
Ptr<Queue<Packet>> queue =
|
||||
StaticCast<PointToPointNetDevice>(devicesBottleneckLink.Get(0))->GetQueue();
|
||||
Ptr<OutputStreamWrapper> streamBytesInQueue =
|
||||
ascii.CreateFileStream(queueDiscType + "-bytesInQueue.txt");
|
||||
queue->TraceConnectWithoutContext("BytesInQueue",
|
||||
MakeBoundCallback(&BytesInQueueTrace, streamBytesInQueue));
|
||||
|
||||
Ipv4InterfaceContainer n1Interface;
|
||||
n1Interface.Add (interfacesAccess.Get (0));
|
||||
Ipv4InterfaceContainer n1Interface;
|
||||
n1Interface.Add(interfacesAccess.Get(0));
|
||||
|
||||
Ipv4InterfaceContainer n3Interface;
|
||||
n3Interface.Add (interfacesBottleneck.Get (1));
|
||||
Ipv4InterfaceContainer n3Interface;
|
||||
n3Interface.Add(interfacesBottleneck.Get(1));
|
||||
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
|
||||
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (flowsPacketsSize));
|
||||
Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(flowsPacketsSize));
|
||||
|
||||
// Flows configuration
|
||||
// Bidirectional TCP streams with ping like flent tcp_bidirectional test.
|
||||
uint16_t port = 7;
|
||||
ApplicationContainer uploadApp, downloadApp, sourceApps;
|
||||
// Configure and install upload flow
|
||||
Address addUp (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelperUp ("ns3::TcpSocketFactory", addUp);
|
||||
sinkHelperUp.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
|
||||
uploadApp.Add (sinkHelperUp.Install (n3));
|
||||
// Flows configuration
|
||||
// Bidirectional TCP streams with ping like flent tcp_bidirectional test.
|
||||
uint16_t port = 7;
|
||||
ApplicationContainer uploadApp;
|
||||
ApplicationContainer downloadApp;
|
||||
ApplicationContainer sourceApps;
|
||||
// Configure and install upload flow
|
||||
Address addUp(InetSocketAddress(Ipv4Address::GetAny(), port));
|
||||
PacketSinkHelper sinkHelperUp("ns3::TcpSocketFactory", addUp);
|
||||
sinkHelperUp.SetAttribute("Protocol", TypeIdValue(TcpSocketFactory::GetTypeId()));
|
||||
uploadApp.Add(sinkHelperUp.Install(n3));
|
||||
|
||||
InetSocketAddress socketAddressUp = InetSocketAddress (n3Interface.GetAddress (0), port);
|
||||
OnOffHelper onOffHelperUp ("ns3::TcpSocketFactory", Address ());
|
||||
onOffHelperUp.SetAttribute ("Remote", AddressValue (socketAddressUp));
|
||||
onOffHelperUp.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onOffHelperUp.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onOffHelperUp.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
|
||||
onOffHelperUp.SetAttribute ("DataRate", StringValue (flowsDatarate));
|
||||
sourceApps.Add (onOffHelperUp.Install (n1));
|
||||
InetSocketAddress socketAddressUp = InetSocketAddress(n3Interface.GetAddress(0), port);
|
||||
OnOffHelper onOffHelperUp("ns3::TcpSocketFactory", Address());
|
||||
onOffHelperUp.SetAttribute("Remote", AddressValue(socketAddressUp));
|
||||
onOffHelperUp.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onOffHelperUp.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onOffHelperUp.SetAttribute("PacketSize", UintegerValue(flowsPacketsSize));
|
||||
onOffHelperUp.SetAttribute("DataRate", StringValue(flowsDatarate));
|
||||
sourceApps.Add(onOffHelperUp.Install(n1));
|
||||
|
||||
port = 8;
|
||||
// Configure and install download flow
|
||||
Address addDown (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelperDown ("ns3::TcpSocketFactory", addDown);
|
||||
sinkHelperDown.SetAttribute ("Protocol", TypeIdValue (TcpSocketFactory::GetTypeId ()));
|
||||
downloadApp.Add (sinkHelperDown.Install (n1));
|
||||
port = 8;
|
||||
// Configure and install download flow
|
||||
Address addDown(InetSocketAddress(Ipv4Address::GetAny(), port));
|
||||
PacketSinkHelper sinkHelperDown("ns3::TcpSocketFactory", addDown);
|
||||
sinkHelperDown.SetAttribute("Protocol", TypeIdValue(TcpSocketFactory::GetTypeId()));
|
||||
downloadApp.Add(sinkHelperDown.Install(n1));
|
||||
|
||||
InetSocketAddress socketAddressDown = InetSocketAddress (n1Interface.GetAddress (0), port);
|
||||
OnOffHelper onOffHelperDown ("ns3::TcpSocketFactory", Address ());
|
||||
onOffHelperDown.SetAttribute ("Remote", AddressValue (socketAddressDown));
|
||||
onOffHelperDown.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onOffHelperDown.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onOffHelperDown.SetAttribute ("PacketSize", UintegerValue (flowsPacketsSize));
|
||||
onOffHelperDown.SetAttribute ("DataRate", StringValue (flowsDatarate));
|
||||
sourceApps.Add (onOffHelperDown.Install (n3));
|
||||
InetSocketAddress socketAddressDown = InetSocketAddress(n1Interface.GetAddress(0), port);
|
||||
OnOffHelper onOffHelperDown("ns3::TcpSocketFactory", Address());
|
||||
onOffHelperDown.SetAttribute("Remote", AddressValue(socketAddressDown));
|
||||
onOffHelperDown.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
onOffHelperDown.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
onOffHelperDown.SetAttribute("PacketSize", UintegerValue(flowsPacketsSize));
|
||||
onOffHelperDown.SetAttribute("DataRate", StringValue(flowsDatarate));
|
||||
sourceApps.Add(onOffHelperDown.Install(n3));
|
||||
|
||||
// Configure and install ping
|
||||
V4PingHelper ping = V4PingHelper (n3Interface.GetAddress (0));
|
||||
ping.Install (n1);
|
||||
// Configure and install ping
|
||||
V4PingHelper ping = V4PingHelper(n3Interface.GetAddress(0));
|
||||
ping.Install(n1);
|
||||
|
||||
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", MakeCallback (&PingRtt));
|
||||
Config::Connect("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", MakeCallback(&PingRtt));
|
||||
|
||||
uploadApp.Start (Seconds (0));
|
||||
uploadApp.Stop (Seconds (stopTime));
|
||||
downloadApp.Start (Seconds (0));
|
||||
downloadApp.Stop (Seconds (stopTime));
|
||||
uploadApp.Start(Seconds(0));
|
||||
uploadApp.Stop(Seconds(stopTime));
|
||||
downloadApp.Start(Seconds(0));
|
||||
downloadApp.Stop(Seconds(stopTime));
|
||||
|
||||
sourceApps.Start (Seconds (0 + 0.1));
|
||||
sourceApps.Stop (Seconds (stopTime - 0.1));
|
||||
sourceApps.Start(Seconds(0 + 0.1));
|
||||
sourceApps.Stop(Seconds(stopTime - 0.1));
|
||||
|
||||
Ptr<OutputStreamWrapper> uploadGoodputStream = ascii.CreateFileStream (queueDiscType + "-upGoodput.txt");
|
||||
Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-upGoodput.txt", uploadApp,
|
||||
uploadGoodputStream, samplingPeriod);
|
||||
Ptr<OutputStreamWrapper> downloadGoodputStream = ascii.CreateFileStream (queueDiscType + "-downGoodput.txt");
|
||||
Simulator::Schedule (Seconds (samplingPeriod), &GoodputSampling, queueDiscType + "-downGoodput.txt", downloadApp,
|
||||
downloadGoodputStream, samplingPeriod);
|
||||
Ptr<OutputStreamWrapper> uploadGoodputStream =
|
||||
ascii.CreateFileStream(queueDiscType + "-upGoodput.txt");
|
||||
Simulator::Schedule(Seconds(samplingPeriod),
|
||||
&GoodputSampling,
|
||||
uploadApp,
|
||||
uploadGoodputStream,
|
||||
samplingPeriod);
|
||||
Ptr<OutputStreamWrapper> downloadGoodputStream =
|
||||
ascii.CreateFileStream(queueDiscType + "-downGoodput.txt");
|
||||
Simulator::Schedule(Seconds(samplingPeriod),
|
||||
&GoodputSampling,
|
||||
downloadApp,
|
||||
downloadGoodputStream,
|
||||
samplingPeriod);
|
||||
|
||||
// Flow monitor
|
||||
Ptr<FlowMonitor> flowMonitor;
|
||||
FlowMonitorHelper flowHelper;
|
||||
flowMonitor = flowHelper.InstallAll();
|
||||
// Flow monitor
|
||||
Ptr<FlowMonitor> flowMonitor;
|
||||
FlowMonitorHelper flowHelper;
|
||||
flowMonitor = flowHelper.InstallAll();
|
||||
|
||||
Simulator::Stop (Seconds (stopTime));
|
||||
Simulator::Run ();
|
||||
Simulator::Stop(Seconds(stopTime));
|
||||
Simulator::Run();
|
||||
|
||||
flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
|
||||
flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
|
||||
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014 Universita' di Firenze, Italy
|
||||
*
|
||||
@@ -50,225 +49,229 @@
|
||||
// the Echo Reply is unable to reach the sender.
|
||||
// Examining the .pcap files with Wireshark can confirm this effect.
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/internet-apps-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/ipv6-routing-table-entry.h"
|
||||
#include "ns3/ipv6-static-routing-helper.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/internet-apps-module.h"
|
||||
#include "ns3/ipv6-static-routing-helper.h"
|
||||
#include "ns3/ipv6-routing-table-entry.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("RipNgSimpleRouting");
|
||||
NS_LOG_COMPONENT_DEFINE("RipNgSimpleRouting");
|
||||
|
||||
void TearDownLink (Ptr<Node> nodeA, Ptr<Node> nodeB, uint32_t interfaceA, uint32_t interfaceB)
|
||||
void
|
||||
TearDownLink(Ptr<Node> nodeA, Ptr<Node> nodeB, uint32_t interfaceA, uint32_t interfaceB)
|
||||
{
|
||||
nodeA->GetObject<Ipv6> ()->SetDown (interfaceA);
|
||||
nodeB->GetObject<Ipv6> ()->SetDown (interfaceB);
|
||||
nodeA->GetObject<Ipv6>()->SetDown(interfaceA);
|
||||
nodeB->GetObject<Ipv6>()->SetDown(interfaceB);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
bool verbose = false;
|
||||
bool printRoutingTables = false;
|
||||
bool showPings = false;
|
||||
std::string SplitHorizon("PoisonReverse");
|
||||
|
||||
bool verbose = false;
|
||||
bool printRoutingTables = false;
|
||||
bool showPings = false;
|
||||
std::string SplitHorizon ("PoisonReverse");
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.AddValue("verbose", "turn on log components", verbose);
|
||||
cmd.AddValue("printRoutingTables",
|
||||
"Print routing tables at 30, 60 and 90 seconds",
|
||||
printRoutingTables);
|
||||
cmd.AddValue("showPings", "Show Ping6 reception", showPings);
|
||||
cmd.AddValue("splitHorizonStrategy",
|
||||
"Split Horizon strategy to use (NoSplitHorizon, SplitHorizon, PoisonReverse)",
|
||||
SplitHorizon);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("verbose", "turn on log components", verbose);
|
||||
cmd.AddValue ("printRoutingTables", "Print routing tables at 30, 60 and 90 seconds", printRoutingTables);
|
||||
cmd.AddValue ("showPings", "Show Ping6 reception", showPings);
|
||||
cmd.AddValue ("splitHorizonStrategy", "Split Horizon strategy to use (NoSplitHorizon, SplitHorizon, PoisonReverse)", SplitHorizon);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
{
|
||||
LogComponentEnable ("RipNgSimpleRouting", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("RipNg", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("NdiscCache", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("RipNgSimpleRouting", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("RipNg", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Icmpv6L4Protocol", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("Ipv6Interface", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Icmpv6L4Protocol", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("NdiscCache", LOG_LEVEL_ALL);
|
||||
LogComponentEnable("Ping6Application", LOG_LEVEL_ALL);
|
||||
}
|
||||
|
||||
if (showPings)
|
||||
if (showPings)
|
||||
{
|
||||
LogComponentEnable ("Ping6Application", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("Ping6Application", LOG_LEVEL_INFO);
|
||||
}
|
||||
|
||||
if (SplitHorizon == "NoSplitHorizon")
|
||||
if (SplitHorizon == "NoSplitHorizon")
|
||||
{
|
||||
Config::SetDefault ("ns3::RipNg::SplitHorizon", EnumValue (RipNg::NO_SPLIT_HORIZON));
|
||||
Config::SetDefault("ns3::RipNg::SplitHorizon", EnumValue(RipNg::NO_SPLIT_HORIZON));
|
||||
}
|
||||
else if (SplitHorizon == "SplitHorizon")
|
||||
else if (SplitHorizon == "SplitHorizon")
|
||||
{
|
||||
Config::SetDefault ("ns3::RipNg::SplitHorizon", EnumValue (RipNg::SPLIT_HORIZON));
|
||||
Config::SetDefault("ns3::RipNg::SplitHorizon", EnumValue(RipNg::SPLIT_HORIZON));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
Config::SetDefault ("ns3::RipNg::SplitHorizon", EnumValue (RipNg::POISON_REVERSE));
|
||||
Config::SetDefault("ns3::RipNg::SplitHorizon", EnumValue(RipNg::POISON_REVERSE));
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> src = CreateObject<Node> ();
|
||||
Names::Add ("SrcNode", src);
|
||||
Ptr<Node> dst = CreateObject<Node> ();
|
||||
Names::Add ("DstNode", dst);
|
||||
Ptr<Node> a = CreateObject<Node> ();
|
||||
Names::Add ("RouterA", a);
|
||||
Ptr<Node> b = CreateObject<Node> ();
|
||||
Names::Add ("RouterB", b);
|
||||
Ptr<Node> c = CreateObject<Node> ();
|
||||
Names::Add ("RouterC", c);
|
||||
Ptr<Node> d = CreateObject<Node> ();
|
||||
Names::Add ("RouterD", d);
|
||||
NodeContainer net1 (src, a);
|
||||
NodeContainer net2 (a, b);
|
||||
NodeContainer net3 (a, c);
|
||||
NodeContainer net4 (b, c);
|
||||
NodeContainer net5 (c, d);
|
||||
NodeContainer net6 (b, d);
|
||||
NodeContainer net7 (d, dst);
|
||||
NodeContainer routers (a, b, c, d);
|
||||
NodeContainer nodes (src, dst);
|
||||
NS_LOG_INFO("Create nodes.");
|
||||
Ptr<Node> src = CreateObject<Node>();
|
||||
Names::Add("SrcNode", src);
|
||||
Ptr<Node> dst = CreateObject<Node>();
|
||||
Names::Add("DstNode", dst);
|
||||
Ptr<Node> a = CreateObject<Node>();
|
||||
Names::Add("RouterA", a);
|
||||
Ptr<Node> b = CreateObject<Node>();
|
||||
Names::Add("RouterB", b);
|
||||
Ptr<Node> c = CreateObject<Node>();
|
||||
Names::Add("RouterC", c);
|
||||
Ptr<Node> d = CreateObject<Node>();
|
||||
Names::Add("RouterD", d);
|
||||
NodeContainer net1(src, a);
|
||||
NodeContainer net2(a, b);
|
||||
NodeContainer net3(a, c);
|
||||
NodeContainer net4(b, c);
|
||||
NodeContainer net5(c, d);
|
||||
NodeContainer net6(b, d);
|
||||
NodeContainer net7(d, dst);
|
||||
NodeContainer routers(a, b, c, d);
|
||||
NodeContainer nodes(src, dst);
|
||||
|
||||
NS_LOG_INFO("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute("DataRate", DataRateValue(5000000));
|
||||
p2p.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2)));
|
||||
NetDeviceContainer ndc1 = p2p.Install(net1);
|
||||
NetDeviceContainer ndc2 = p2p.Install(net2);
|
||||
NetDeviceContainer ndc3 = p2p.Install(net3);
|
||||
NetDeviceContainer ndc4 = p2p.Install(net4);
|
||||
NetDeviceContainer ndc5 = p2p.Install(net5);
|
||||
NetDeviceContainer ndc6 = p2p.Install(net6);
|
||||
NetDeviceContainer ndc7 = p2p.Install(net7);
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute ("DataRate", DataRateValue (5000000));
|
||||
p2p.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
|
||||
NetDeviceContainer ndc1 = p2p.Install (net1);
|
||||
NetDeviceContainer ndc2 = p2p.Install (net2);
|
||||
NetDeviceContainer ndc3 = p2p.Install (net3);
|
||||
NetDeviceContainer ndc4 = p2p.Install (net4);
|
||||
NetDeviceContainer ndc5 = p2p.Install (net5);
|
||||
NetDeviceContainer ndc6 = p2p.Install (net6);
|
||||
NetDeviceContainer ndc7 = p2p.Install (net7);
|
||||
NS_LOG_INFO("Create IPv6 and routing");
|
||||
RipNgHelper ripNgRouting;
|
||||
|
||||
NS_LOG_INFO ("Create IPv6 and routing");
|
||||
RipNgHelper ripNgRouting;
|
||||
// Rule of thumb:
|
||||
// Interfaces are added sequentially, starting from 0
|
||||
// However, interface 0 is always the loopback...
|
||||
ripNgRouting.ExcludeInterface(a, 1);
|
||||
ripNgRouting.ExcludeInterface(d, 3);
|
||||
|
||||
// Rule of thumb:
|
||||
// Interfaces are added sequentially, starting from 0
|
||||
// However, interface 0 is always the loopback...
|
||||
ripNgRouting.ExcludeInterface (a, 1);
|
||||
ripNgRouting.ExcludeInterface (d, 3);
|
||||
ripNgRouting.SetInterfaceMetric(c, 3, 10);
|
||||
ripNgRouting.SetInterfaceMetric(d, 1, 10);
|
||||
|
||||
ripNgRouting.SetInterfaceMetric (c, 3, 10);
|
||||
ripNgRouting.SetInterfaceMetric (d, 1, 10);
|
||||
Ipv6ListRoutingHelper listRH;
|
||||
listRH.Add(ripNgRouting, 0);
|
||||
Ipv6StaticRoutingHelper staticRh;
|
||||
listRH.Add(staticRh, 5);
|
||||
|
||||
Ipv6ListRoutingHelper listRH;
|
||||
listRH.Add (ripNgRouting, 0);
|
||||
Ipv6StaticRoutingHelper staticRh;
|
||||
listRH.Add (staticRh, 5);
|
||||
InternetStackHelper internetv6;
|
||||
internetv6.SetIpv4StackInstall(false);
|
||||
internetv6.SetRoutingHelper(listRH);
|
||||
internetv6.Install(routers);
|
||||
|
||||
InternetStackHelper internetv6;
|
||||
internetv6.SetIpv4StackInstall (false);
|
||||
internetv6.SetRoutingHelper (listRH);
|
||||
internetv6.Install (routers);
|
||||
InternetStackHelper internetv6Nodes;
|
||||
internetv6Nodes.SetIpv4StackInstall(false);
|
||||
internetv6Nodes.Install(nodes);
|
||||
|
||||
InternetStackHelper internetv6Nodes;
|
||||
internetv6Nodes.SetIpv4StackInstall (false);
|
||||
internetv6Nodes.Install (nodes);
|
||||
// Assign addresses.
|
||||
// The source and destination networks have global addresses
|
||||
// The "core" network just needs link-local addresses for routing.
|
||||
// We assign global addresses to the routers as well to receive
|
||||
// ICMPv6 errors.
|
||||
NS_LOG_INFO("Assign IPv6 Addresses.");
|
||||
Ipv6AddressHelper ipv6;
|
||||
|
||||
// Assign addresses.
|
||||
// The source and destination networks have global addresses
|
||||
// The "core" network just needs link-local addresses for routing.
|
||||
// We assign global addresses to the routers as well to receive
|
||||
// ICMPv6 errors.
|
||||
NS_LOG_INFO ("Assign IPv6 Addresses.");
|
||||
Ipv6AddressHelper ipv6;
|
||||
ipv6.SetBase(Ipv6Address("2001:1::"), Ipv6Prefix(64));
|
||||
Ipv6InterfaceContainer iic1 = ipv6.Assign(ndc1);
|
||||
iic1.SetForwarding(1, true);
|
||||
iic1.SetDefaultRouteInAllNodes(1);
|
||||
|
||||
ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer iic1 = ipv6.Assign (ndc1);
|
||||
iic1.SetForwarding (1, true);
|
||||
iic1.SetDefaultRouteInAllNodes (1);
|
||||
ipv6.SetBase(Ipv6Address("2001:0:1::"), Ipv6Prefix(64));
|
||||
Ipv6InterfaceContainer iic2 = ipv6.Assign(ndc2);
|
||||
iic2.SetForwarding(0, true);
|
||||
iic2.SetForwarding(1, true);
|
||||
|
||||
ipv6.SetBase (Ipv6Address ("2001:0:1::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer iic2 = ipv6.Assign (ndc2);
|
||||
iic2.SetForwarding (0, true);
|
||||
iic2.SetForwarding (1, true);
|
||||
ipv6.SetBase(Ipv6Address("2001:0:2::"), Ipv6Prefix(64));
|
||||
Ipv6InterfaceContainer iic3 = ipv6.Assign(ndc3);
|
||||
iic3.SetForwarding(0, true);
|
||||
iic3.SetForwarding(1, true);
|
||||
|
||||
ipv6.SetBase (Ipv6Address ("2001:0:2::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer iic3 = ipv6.Assign (ndc3);
|
||||
iic3.SetForwarding (0, true);
|
||||
iic3.SetForwarding (1, true);
|
||||
ipv6.SetBase(Ipv6Address("2001:0:3::"), Ipv6Prefix(64));
|
||||
Ipv6InterfaceContainer iic4 = ipv6.Assign(ndc4);
|
||||
iic4.SetForwarding(0, true);
|
||||
iic4.SetForwarding(1, true);
|
||||
|
||||
ipv6.SetBase (Ipv6Address ("2001:0:3::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer iic4 = ipv6.Assign (ndc4);
|
||||
iic4.SetForwarding (0, true);
|
||||
iic4.SetForwarding (1, true);
|
||||
ipv6.SetBase(Ipv6Address("2001:0:4::"), Ipv6Prefix(64));
|
||||
Ipv6InterfaceContainer iic5 = ipv6.Assign(ndc5);
|
||||
iic5.SetForwarding(0, true);
|
||||
iic5.SetForwarding(1, true);
|
||||
|
||||
ipv6.SetBase (Ipv6Address ("2001:0:4::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer iic5 = ipv6.Assign (ndc5);
|
||||
iic5.SetForwarding (0, true);
|
||||
iic5.SetForwarding (1, true);
|
||||
ipv6.SetBase(Ipv6Address("2001:0:5::"), Ipv6Prefix(64));
|
||||
Ipv6InterfaceContainer iic6 = ipv6.Assign(ndc6);
|
||||
iic6.SetForwarding(0, true);
|
||||
iic6.SetForwarding(1, true);
|
||||
|
||||
ipv6.SetBase (Ipv6Address ("2001:0:5::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer iic6 = ipv6.Assign (ndc6);
|
||||
iic6.SetForwarding (0, true);
|
||||
iic6.SetForwarding (1, true);
|
||||
ipv6.SetBase(Ipv6Address("2001:2::"), Ipv6Prefix(64));
|
||||
Ipv6InterfaceContainer iic7 = ipv6.Assign(ndc7);
|
||||
iic7.SetForwarding(0, true);
|
||||
iic7.SetDefaultRouteInAllNodes(0);
|
||||
|
||||
ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer iic7 = ipv6.Assign (ndc7);
|
||||
iic7.SetForwarding (0, true);
|
||||
iic7.SetDefaultRouteInAllNodes (0);
|
||||
|
||||
if (printRoutingTables)
|
||||
if (printRoutingTables)
|
||||
{
|
||||
RipNgHelper routingHelper;
|
||||
RipNgHelper routingHelper;
|
||||
|
||||
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> (&std::cout);
|
||||
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>(&std::cout);
|
||||
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), d, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(30.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(30.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(30.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(30.0), d, routingStream);
|
||||
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), d, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(60.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(60.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(60.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(60.0), d, routingStream);
|
||||
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), d, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(90.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(90.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(90.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt(Seconds(90.0), d, routingStream);
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint32_t packetSize = 1024;
|
||||
uint32_t maxPacketCount = 100;
|
||||
Time interPacketInterval = Seconds (1.0);
|
||||
Ping6Helper ping6;
|
||||
NS_LOG_INFO("Create Applications.");
|
||||
uint32_t packetSize = 1024;
|
||||
uint32_t maxPacketCount = 100;
|
||||
Time interPacketInterval = Seconds(1.0);
|
||||
Ping6Helper ping6;
|
||||
|
||||
ping6.SetLocal (iic1.GetAddress (0, 1));
|
||||
ping6.SetRemote (iic7.GetAddress (1, 1));
|
||||
ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
|
||||
ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
|
||||
ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
|
||||
ApplicationContainer apps = ping6.Install (src);
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (110.0));
|
||||
ping6.SetLocal(iic1.GetAddress(0, 1));
|
||||
ping6.SetRemote(iic7.GetAddress(1, 1));
|
||||
ping6.SetAttribute("MaxPackets", UintegerValue(maxPacketCount));
|
||||
ping6.SetAttribute("Interval", TimeValue(interPacketInterval));
|
||||
ping6.SetAttribute("PacketSize", UintegerValue(packetSize));
|
||||
ApplicationContainer apps = ping6.Install(src);
|
||||
apps.Start(Seconds(1.0));
|
||||
apps.Stop(Seconds(110.0));
|
||||
|
||||
AsciiTraceHelper ascii;
|
||||
p2p.EnableAsciiAll (ascii.CreateFileStream ("ripng-simple-routing.tr"));
|
||||
p2p.EnablePcapAll ("ripng-simple-routing", true);
|
||||
AsciiTraceHelper ascii;
|
||||
p2p.EnableAsciiAll(ascii.CreateFileStream("ripng-simple-routing.tr"));
|
||||
p2p.EnablePcapAll("ripng-simple-routing", true);
|
||||
|
||||
Simulator::Schedule (Seconds (40), &TearDownLink, b, d, 3, 2);
|
||||
Simulator::Schedule(Seconds(40), &TearDownLink, b, d, 3, 2);
|
||||
|
||||
/* Now, do the actual simulation. */
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Stop (Seconds (120));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
/* Now, do the actual simulation. */
|
||||
NS_LOG_INFO("Run Simulation.");
|
||||
Simulator::Stop(Seconds(120));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
NS_LOG_INFO("Done.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2013 Universita' di Firenze
|
||||
* Copyright (c) 2019 Caliola Engineering, LLC : RFC 6621 multicast packet de-duplication
|
||||
@@ -22,45 +21,41 @@
|
||||
* network to all nodes over multiple hops.
|
||||
*/
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/simple-channel.h"
|
||||
#include "ns3/simple-net-device.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/data-rate.h"
|
||||
#include "ns3/uinteger.h"
|
||||
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
|
||||
#include "ns3/ipv4-l3-protocol.h"
|
||||
#include "ns3/ipv4-static-routing.h"
|
||||
#include "ns3/udp-socket-factory.h"
|
||||
#include "ns3/udp-socket.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
|
||||
#include "ns3/internet-stack-helper.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/ipv4-l3-protocol.h"
|
||||
#include "ns3/ipv4-list-routing-helper.h"
|
||||
#include "ns3/ipv4-static-routing-helper.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/simple-net-device-helper.h"
|
||||
#include "ns3/packet-sink-helper.h"
|
||||
#include "ns3/ipv4-static-routing.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/mtp-interface.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/on-off-helper.h"
|
||||
#include "ns3/packet-sink-helper.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/simple-channel.h"
|
||||
#include "ns3/simple-net-device-helper.h"
|
||||
#include "ns3/simple-net-device.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/trace-helper.h"
|
||||
|
||||
#include "ns3/traffic-control-layer.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/udp-socket-factory.h"
|
||||
#include "ns3/udp-socket.h"
|
||||
#include "ns3/uinteger.h"
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
@@ -73,139 +68,148 @@ using namespace ns3;
|
||||
*
|
||||
* This example demonstrates configuration of
|
||||
* static routing to realize broadcast-like
|
||||
* flooding of packets from node A
|
||||
* flooding of packets from node A
|
||||
* across the illustrated topology.
|
||||
*/
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
// multicast target
|
||||
const std::string targetAddr = "239.192.100.1";
|
||||
Config::SetDefault("ns3::Ipv4L3Protocol::EnableDuplicatePacketDetection", BooleanValue(true));
|
||||
Config::SetDefault("ns3::Ipv4L3Protocol::DuplicateExpire", TimeValue(Seconds(10)));
|
||||
|
||||
// multicast target
|
||||
const std::string targetAddr = "239.192.100.1";
|
||||
Config::SetDefault ("ns3::Ipv4L3Protocol::EnableDuplicatePacketDetection", BooleanValue (true));
|
||||
Config::SetDefault ("ns3::Ipv4L3Protocol::DuplicateExpire", TimeValue (Seconds (10)));
|
||||
// Create topology
|
||||
|
||||
// Create topology
|
||||
// Create nodes
|
||||
auto nodes = NodeContainer();
|
||||
nodes.Create(5);
|
||||
|
||||
// Create nodes
|
||||
auto nodes = NodeContainer ();
|
||||
nodes.Create (5);
|
||||
// Name nodes
|
||||
Names::Add("A", nodes.Get(0));
|
||||
Names::Add("B", nodes.Get(1));
|
||||
Names::Add("C", nodes.Get(2));
|
||||
Names::Add("D", nodes.Get(3));
|
||||
Names::Add("E", nodes.Get(4));
|
||||
|
||||
// Name nodes
|
||||
Names::Add ("A", nodes.Get (0));
|
||||
Names::Add ("B", nodes.Get (1));
|
||||
Names::Add ("C", nodes.Get (2));
|
||||
Names::Add ("D", nodes.Get (3));
|
||||
Names::Add ("E", nodes.Get (4));
|
||||
SimpleNetDeviceHelper simplenet;
|
||||
auto devices = simplenet.Install(nodes);
|
||||
// name devices
|
||||
Names::Add("A/dev", devices.Get(0));
|
||||
Names::Add("B/dev", devices.Get(1));
|
||||
Names::Add("C/dev", devices.Get(2));
|
||||
Names::Add("D/dev", devices.Get(3));
|
||||
Names::Add("E/dev", devices.Get(4));
|
||||
|
||||
SimpleNetDeviceHelper simplenet;
|
||||
auto devices = simplenet.Install (nodes);
|
||||
// name devices
|
||||
Names::Add ("A/dev", devices.Get (0));
|
||||
Names::Add ("B/dev", devices.Get (1));
|
||||
Names::Add ("C/dev", devices.Get (2));
|
||||
Names::Add ("D/dev", devices.Get (3));
|
||||
Names::Add ("E/dev", devices.Get (4));
|
||||
// setup static routes to facilitate multicast flood
|
||||
Ipv4ListRoutingHelper listRouting;
|
||||
Ipv4StaticRoutingHelper staticRouting;
|
||||
listRouting.Add(staticRouting, 0);
|
||||
|
||||
// setup static routes to facilitate multicast flood
|
||||
Ipv4ListRoutingHelper listRouting;
|
||||
Ipv4StaticRoutingHelper staticRouting;
|
||||
listRouting.Add (staticRouting, 0);
|
||||
InternetStackHelper internet;
|
||||
internet.SetIpv6StackInstall(false);
|
||||
internet.SetIpv4ArpJitter(true);
|
||||
internet.SetRoutingHelper(listRouting);
|
||||
internet.Install(nodes);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.SetIpv6StackInstall (false);
|
||||
internet.SetIpv4ArpJitter (true);
|
||||
internet.SetRoutingHelper (listRouting);
|
||||
internet.Install (nodes);
|
||||
Ipv4AddressHelper ipv4address;
|
||||
ipv4address.SetBase("10.0.0.0", "255.255.255.0");
|
||||
ipv4address.Assign(devices);
|
||||
|
||||
Ipv4AddressHelper ipv4address;
|
||||
ipv4address.SetBase ("10.0.0.0", "255.255.255.0");
|
||||
ipv4address.Assign (devices);
|
||||
|
||||
// add static routes for each node / device
|
||||
for (auto diter = devices.Begin (); diter != devices.End (); ++diter)
|
||||
// add static routes for each node / device
|
||||
for (auto diter = devices.Begin(); diter != devices.End(); ++diter)
|
||||
{
|
||||
Ptr<Node> node = (*diter)->GetNode ();
|
||||
Ptr<Node> node = (*diter)->GetNode();
|
||||
|
||||
if (Names::FindName (node) == "A")
|
||||
if (Names::FindName(node) == "A")
|
||||
{
|
||||
// route for host
|
||||
// Use host routing entry according to note in Ipv4StaticRouting::RouteOutput:
|
||||
//// Note: Multicast routes for outbound packets are stored in the
|
||||
//// normal unicast table. An implication of this is that it is not
|
||||
//// possible to source multicast datagrams on multiple interfaces.
|
||||
//// This is a well-known property of sockets implementation on
|
||||
//// many Unix variants.
|
||||
//// So, we just log it and fall through to LookupStatic ()
|
||||
auto ipv4 = node->GetObject <Ipv4> ();
|
||||
NS_ASSERT_MSG ((bool) ipv4, "Node " << Names::FindName (node) << " does not have Ipv4 aggregate");
|
||||
auto routing = staticRouting.GetStaticRouting (ipv4);
|
||||
routing->AddHostRouteTo (targetAddr.c_str (), ipv4->GetInterfaceForDevice (*diter), 0);
|
||||
// route for host
|
||||
// Use host routing entry according to note in Ipv4StaticRouting::RouteOutput:
|
||||
//// Note: Multicast routes for outbound packets are stored in the
|
||||
//// normal unicast table. An implication of this is that it is not
|
||||
//// possible to source multicast datagrams on multiple interfaces.
|
||||
//// This is a well-known property of sockets implementation on
|
||||
//// many Unix variants.
|
||||
//// So, we just log it and fall through to LookupStatic ()
|
||||
auto ipv4 = node->GetObject<Ipv4>();
|
||||
NS_ASSERT_MSG((bool)ipv4,
|
||||
"Node " << Names::FindName(node) << " does not have Ipv4 aggregate");
|
||||
auto routing = staticRouting.GetStaticRouting(ipv4);
|
||||
routing->AddHostRouteTo(targetAddr.c_str(), ipv4->GetInterfaceForDevice(*diter), 0);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// route for forwarding
|
||||
staticRouting.AddMulticastRoute (node, Ipv4Address::GetAny (), targetAddr.c_str (), *diter, NetDeviceContainer (*diter));
|
||||
// route for forwarding
|
||||
staticRouting.AddMulticastRoute(node,
|
||||
Ipv4Address::GetAny(),
|
||||
targetAddr.c_str(),
|
||||
*diter,
|
||||
NetDeviceContainer(*diter));
|
||||
}
|
||||
}
|
||||
|
||||
// set the topology, by default fully-connected
|
||||
auto channel = devices.Get (0)->GetChannel ();
|
||||
auto simplechannel = channel->GetObject <SimpleChannel> ();
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("A/dev"), Names::Find <SimpleNetDevice> ("D/dev"));
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("D/dev"), Names::Find <SimpleNetDevice> ("A/dev"));
|
||||
// set the topology, by default fully-connected
|
||||
auto channel = devices.Get(0)->GetChannel();
|
||||
auto simplechannel = channel->GetObject<SimpleChannel>();
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("A/dev"),
|
||||
Names::Find<SimpleNetDevice>("D/dev"));
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("D/dev"),
|
||||
Names::Find<SimpleNetDevice>("A/dev"));
|
||||
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("A/dev"), Names::Find <SimpleNetDevice> ("E/dev"));
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("E/dev"), Names::Find <SimpleNetDevice> ("A/dev"));
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("A/dev"),
|
||||
Names::Find<SimpleNetDevice>("E/dev"));
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("E/dev"),
|
||||
Names::Find<SimpleNetDevice>("A/dev"));
|
||||
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("B/dev"), Names::Find <SimpleNetDevice> ("E/dev"));
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("E/dev"), Names::Find <SimpleNetDevice> ("B/dev"));
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("B/dev"),
|
||||
Names::Find<SimpleNetDevice>("E/dev"));
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("E/dev"),
|
||||
Names::Find<SimpleNetDevice>("B/dev"));
|
||||
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("C/dev"), Names::Find <SimpleNetDevice> ("E/dev"));
|
||||
simplechannel->BlackList (Names::Find <SimpleNetDevice> ("E/dev"), Names::Find <SimpleNetDevice> ("C/dev"));
|
||||
// ensure some time progress between re-transmissions
|
||||
simplechannel->SetAttribute ("Delay", TimeValue (MilliSeconds (1)));
|
||||
|
||||
// sinks
|
||||
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 9));
|
||||
auto sinks = sinkHelper.Install ("B");
|
||||
sinks.Add (sinkHelper.Install ("C"));
|
||||
sinks.Add (sinkHelper.Install ("D"));
|
||||
sinks.Add (sinkHelper.Install ("E"));
|
||||
sinks.Start (Seconds (1));
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("C/dev"),
|
||||
Names::Find<SimpleNetDevice>("E/dev"));
|
||||
simplechannel->BlackList(Names::Find<SimpleNetDevice>("E/dev"),
|
||||
Names::Find<SimpleNetDevice>("C/dev"));
|
||||
// ensure some time progress between re-transmissions
|
||||
simplechannel->SetAttribute("Delay", TimeValue(MilliSeconds(1)));
|
||||
|
||||
// source
|
||||
OnOffHelper onoffHelper ("ns3::UdpSocketFactory", InetSocketAddress (targetAddr.c_str (), 9));
|
||||
onoffHelper.SetAttribute ("DataRate", DataRateValue (DataRate ("8Mbps")));
|
||||
onoffHelper.SetAttribute ("MaxBytes", UintegerValue (10 * 1024));
|
||||
auto source = onoffHelper.Install ("A");
|
||||
source.Start (Seconds (1.1));
|
||||
// sinks
|
||||
PacketSinkHelper sinkHelper("ns3::UdpSocketFactory",
|
||||
InetSocketAddress(Ipv4Address::GetAny(), 9));
|
||||
auto sinks = sinkHelper.Install("B");
|
||||
sinks.Add(sinkHelper.Install("C"));
|
||||
sinks.Add(sinkHelper.Install("D"));
|
||||
sinks.Add(sinkHelper.Install("E"));
|
||||
sinks.Start(Seconds(1));
|
||||
|
||||
// pcap traces
|
||||
for (auto end = nodes.End (),
|
||||
iter = nodes.Begin (); iter != end; ++iter)
|
||||
// source
|
||||
OnOffHelper onoffHelper("ns3::UdpSocketFactory", InetSocketAddress(targetAddr.c_str(), 9));
|
||||
onoffHelper.SetAttribute("DataRate", DataRateValue(DataRate("8Mbps")));
|
||||
onoffHelper.SetAttribute("MaxBytes", UintegerValue(10 * 1024));
|
||||
auto source = onoffHelper.Install("A");
|
||||
source.Start(Seconds(1.1));
|
||||
|
||||
// pcap traces
|
||||
for (auto end = nodes.End(), iter = nodes.Begin(); iter != end; ++iter)
|
||||
{
|
||||
internet.EnablePcapIpv4 ("smf-trace", (*iter)->GetId (), 1, false);
|
||||
internet.EnablePcapIpv4("smf-trace", (*iter)->GetId(), 1, false);
|
||||
}
|
||||
|
||||
// run simulation
|
||||
Simulator::Run ();
|
||||
|
||||
std::cout << "Node A sent " << 10 * 1024 << " bytes" << std::endl;
|
||||
for (auto end = sinks.End (),
|
||||
iter = sinks.Begin (); iter != end; ++iter)
|
||||
// run simulation
|
||||
Simulator::Run();
|
||||
|
||||
std::cout << "Node A sent " << 10 * 1024 << " bytes" << std::endl;
|
||||
for (auto end = sinks.End(), iter = sinks.Begin(); iter != end; ++iter)
|
||||
{
|
||||
auto node = (*iter)->GetNode ();
|
||||
auto sink = (*iter)->GetObject <PacketSink> ();
|
||||
std::cout << "Node " << Names::FindName (node)
|
||||
<< " received " << sink->GetTotalRx () << " bytes" << std::endl;
|
||||
auto node = (*iter)->GetNode();
|
||||
auto sink = (*iter)->GetObject<PacketSink>();
|
||||
std::cout << "Node " << Names::FindName(node) << " received " << sink->GetTotalRx()
|
||||
<< " bytes" << std::endl;
|
||||
}
|
||||
|
||||
Simulator::Destroy ();
|
||||
Simulator::Destroy();
|
||||
|
||||
Names::Clear ();
|
||||
return 0;
|
||||
Names::Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -20,7 +19,7 @@
|
||||
Destination host (10.20.1.2)
|
||||
|
|
||||
| 10.20.1.0/24
|
||||
DSTRTR
|
||||
DSTRTR
|
||||
10.10.1.0/24 / \ 10.10.2.0/24
|
||||
/ \
|
||||
Rtr1 Rtr2
|
||||
@@ -30,206 +29,206 @@
|
||||
Source
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/ipv4-static-routing-helper.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/ipv4-list-routing-helper.h"
|
||||
#include "ns3/ipv4-static-routing-helper.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SocketBoundTcpRoutingExample");
|
||||
NS_LOG_COMPONENT_DEFINE("SocketBoundTcpRoutingExample");
|
||||
|
||||
static const uint32_t totalTxBytes = 20000;
|
||||
static uint32_t currentTxBytes = 0;
|
||||
static const uint32_t writeSize = 1040;
|
||||
uint8_t data[writeSize];
|
||||
|
||||
void StartFlow(Ptr<Socket>, Ipv4Address, uint16_t);
|
||||
void WriteUntilBufferFull(Ptr<Socket>, uint32_t);
|
||||
|
||||
void StartFlow (Ptr<Socket>, Ipv4Address, uint16_t);
|
||||
void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
|
||||
void SendStuff(Ptr<Socket> sock, Ipv4Address dstaddr, uint16_t port);
|
||||
void BindSock(Ptr<Socket> sock, Ptr<NetDevice> netdev);
|
||||
void srcSocketRecv(Ptr<Socket> socket);
|
||||
void dstSocketRecv(Ptr<Socket> socket);
|
||||
|
||||
void SendStuff (Ptr<Socket> sock, Ipv4Address dstaddr, uint16_t port);
|
||||
void BindSock (Ptr<Socket> sock, Ptr<NetDevice> netdev);
|
||||
void srcSocketRecv (Ptr<Socket> socket);
|
||||
void dstSocketRecv (Ptr<Socket> socket);
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// DefaultValue::Bind ()s at run-time, via command-line arguments
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// DefaultValue::Bind ()s at run-time, via command-line arguments
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.Parse (argc, argv);
|
||||
Ptr<Node> nSrc = CreateObject<Node>();
|
||||
Ptr<Node> nDst = CreateObject<Node>();
|
||||
Ptr<Node> nRtr1 = CreateObject<Node>();
|
||||
Ptr<Node> nRtr2 = CreateObject<Node>();
|
||||
Ptr<Node> nDstRtr = CreateObject<Node>();
|
||||
|
||||
Ptr<Node> nSrc = CreateObject<Node> ();
|
||||
Ptr<Node> nDst = CreateObject<Node> ();
|
||||
Ptr<Node> nRtr1 = CreateObject<Node> ();
|
||||
Ptr<Node> nRtr2 = CreateObject<Node> ();
|
||||
Ptr<Node> nDstRtr = CreateObject<Node> ();
|
||||
NodeContainer c = NodeContainer(nSrc, nDst, nRtr1, nRtr2, nDstRtr);
|
||||
|
||||
NodeContainer c = NodeContainer (nSrc, nDst, nRtr1, nRtr2, nDstRtr);
|
||||
InternetStackHelper internet;
|
||||
internet.Install(c);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.Install (c);
|
||||
// Point-to-point links
|
||||
NodeContainer nSrcnRtr1 = NodeContainer(nSrc, nRtr1);
|
||||
NodeContainer nSrcnRtr2 = NodeContainer(nSrc, nRtr2);
|
||||
NodeContainer nRtr1nDstRtr = NodeContainer(nRtr1, nDstRtr);
|
||||
NodeContainer nRtr2nDstRtr = NodeContainer(nRtr2, nDstRtr);
|
||||
NodeContainer nDstRtrnDst = NodeContainer(nDstRtr, nDst);
|
||||
|
||||
// Point-to-point links
|
||||
NodeContainer nSrcnRtr1 = NodeContainer (nSrc, nRtr1);
|
||||
NodeContainer nSrcnRtr2 = NodeContainer (nSrc, nRtr2);
|
||||
NodeContainer nRtr1nDstRtr = NodeContainer (nRtr1, nDstRtr);
|
||||
NodeContainer nRtr2nDstRtr = NodeContainer (nRtr2, nDstRtr);
|
||||
NodeContainer nDstRtrnDst = NodeContainer (nDstRtr, nDst);
|
||||
// We create the channels first without any IP addressing information
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
|
||||
p2p.SetChannelAttribute("Delay", StringValue("2ms"));
|
||||
NetDeviceContainer dSrcdRtr1 = p2p.Install(nSrcnRtr1);
|
||||
NetDeviceContainer dSrcdRtr2 = p2p.Install(nSrcnRtr2);
|
||||
NetDeviceContainer dRtr1dDstRtr = p2p.Install(nRtr1nDstRtr);
|
||||
NetDeviceContainer dRtr2dDstRtr = p2p.Install(nRtr2nDstRtr);
|
||||
NetDeviceContainer dDstRtrdDst = p2p.Install(nDstRtrnDst);
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
NetDeviceContainer dSrcdRtr1 = p2p.Install (nSrcnRtr1);
|
||||
NetDeviceContainer dSrcdRtr2 = p2p.Install (nSrcnRtr2);
|
||||
NetDeviceContainer dRtr1dDstRtr = p2p.Install (nRtr1nDstRtr);
|
||||
NetDeviceContainer dRtr2dDstRtr = p2p.Install (nRtr2nDstRtr);
|
||||
NetDeviceContainer dDstRtrdDst = p2p.Install (nDstRtrnDst);
|
||||
Ptr<NetDevice> SrcToRtr1 = dSrcdRtr1.Get(0);
|
||||
Ptr<NetDevice> SrcToRtr2 = dSrcdRtr2.Get(0);
|
||||
|
||||
Ptr<NetDevice> SrcToRtr1=dSrcdRtr1.Get (0);
|
||||
Ptr<NetDevice> SrcToRtr2=dSrcdRtr2.Get (0);
|
||||
// Later, we add IP addresses.
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iSrciRtr1 = ipv4.Assign(dSrcdRtr1);
|
||||
ipv4.SetBase("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iSrciRtr2 = ipv4.Assign(dSrcdRtr2);
|
||||
ipv4.SetBase("10.10.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iRtr1iDstRtr = ipv4.Assign(dRtr1dDstRtr);
|
||||
ipv4.SetBase("10.10.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iRtr2iDstRtr = ipv4.Assign(dRtr2dDstRtr);
|
||||
ipv4.SetBase("10.20.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iDstRtrDst = ipv4.Assign(dDstRtrdDst);
|
||||
|
||||
// Later, we add IP addresses.
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iSrciRtr1 = ipv4.Assign (dSrcdRtr1);
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iSrciRtr2 = ipv4.Assign (dSrcdRtr2);
|
||||
ipv4.SetBase ("10.10.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iRtr1iDstRtr = ipv4.Assign (dRtr1dDstRtr);
|
||||
ipv4.SetBase ("10.10.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iRtr2iDstRtr = ipv4.Assign (dRtr2dDstRtr);
|
||||
ipv4.SetBase ("10.20.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer iDstRtrDst = ipv4.Assign (dDstRtrdDst);
|
||||
Ptr<Ipv4> ipv4Src = nSrc->GetObject<Ipv4>();
|
||||
Ptr<Ipv4> ipv4Rtr1 = nRtr1->GetObject<Ipv4>();
|
||||
Ptr<Ipv4> ipv4Rtr2 = nRtr2->GetObject<Ipv4>();
|
||||
Ptr<Ipv4> ipv4DstRtr = nDstRtr->GetObject<Ipv4>();
|
||||
Ptr<Ipv4> ipv4Dst = nDst->GetObject<Ipv4>();
|
||||
|
||||
Ptr<Ipv4> ipv4Src = nSrc->GetObject<Ipv4> ();
|
||||
Ptr<Ipv4> ipv4Rtr1 = nRtr1->GetObject<Ipv4> ();
|
||||
Ptr<Ipv4> ipv4Rtr2 = nRtr2->GetObject<Ipv4> ();
|
||||
Ptr<Ipv4> ipv4DstRtr = nDstRtr->GetObject<Ipv4> ();
|
||||
Ptr<Ipv4> ipv4Dst = nDst->GetObject<Ipv4> ();
|
||||
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
||||
Ptr<Ipv4StaticRouting> staticRoutingSrc = ipv4RoutingHelper.GetStaticRouting(ipv4Src);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingRtr1 = ipv4RoutingHelper.GetStaticRouting(ipv4Rtr1);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingRtr2 = ipv4RoutingHelper.GetStaticRouting(ipv4Rtr2);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingDstRtr = ipv4RoutingHelper.GetStaticRouting(ipv4DstRtr);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingDst = ipv4RoutingHelper.GetStaticRouting(ipv4Dst);
|
||||
|
||||
Ipv4StaticRoutingHelper ipv4RoutingHelper;
|
||||
Ptr<Ipv4StaticRouting> staticRoutingSrc = ipv4RoutingHelper.GetStaticRouting (ipv4Src);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingRtr1 = ipv4RoutingHelper.GetStaticRouting (ipv4Rtr1);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingRtr2 = ipv4RoutingHelper.GetStaticRouting (ipv4Rtr2);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingDstRtr = ipv4RoutingHelper.GetStaticRouting (ipv4DstRtr);
|
||||
Ptr<Ipv4StaticRouting> staticRoutingDst = ipv4RoutingHelper.GetStaticRouting (ipv4Dst);
|
||||
// Create static routes from Src to Dst
|
||||
staticRoutingRtr1->AddHostRouteTo(Ipv4Address("10.20.1.2"), Ipv4Address("10.10.1.2"), 2);
|
||||
staticRoutingRtr2->AddHostRouteTo(Ipv4Address("10.20.1.2"), Ipv4Address("10.10.2.2"), 2);
|
||||
|
||||
// Create static routes from Src to Dst
|
||||
staticRoutingRtr1->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.10.1.2"), 2);
|
||||
staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.10.2.2"), 2);
|
||||
// Two routes to same destination - setting separate metrics.
|
||||
// You can switch these to see how traffic gets diverted via different routes
|
||||
staticRoutingSrc->AddHostRouteTo(Ipv4Address("10.20.1.2"), Ipv4Address("10.1.1.2"), 1, 5);
|
||||
staticRoutingSrc->AddHostRouteTo(Ipv4Address("10.20.1.2"), Ipv4Address("10.1.2.2"), 2, 10);
|
||||
|
||||
// Two routes to same destination - setting separate metrics.
|
||||
// You can switch these to see how traffic gets diverted via different routes
|
||||
staticRoutingSrc->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.1.1.2"), 1,5);
|
||||
staticRoutingSrc->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.1.2.2"), 2,10);
|
||||
// Creating static routes from DST to Source pointing to Rtr1 VIA Rtr2(!)
|
||||
staticRoutingDst->AddHostRouteTo(Ipv4Address("10.1.1.1"), Ipv4Address("10.20.1.1"), 1);
|
||||
staticRoutingDstRtr->AddHostRouteTo(Ipv4Address("10.1.1.1"), Ipv4Address("10.10.2.1"), 2);
|
||||
staticRoutingRtr2->AddHostRouteTo(Ipv4Address("10.1.1.1"), Ipv4Address("10.1.2.1"), 1);
|
||||
|
||||
// Creating static routes from DST to Source pointing to Rtr1 VIA Rtr2(!)
|
||||
staticRoutingDst->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.20.1.1"), 1);
|
||||
staticRoutingDstRtr->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.10.2.1"), 2);
|
||||
staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.2.1"), 1);
|
||||
staticRoutingDst->AddHostRouteTo(Ipv4Address("10.1.2.1"), Ipv4Address("10.20.1.1"), 1);
|
||||
staticRoutingDstRtr->AddHostRouteTo(Ipv4Address("10.1.2.1"), Ipv4Address("10.10.2.1"), 2);
|
||||
staticRoutingRtr2->AddHostRouteTo(Ipv4Address("10.1.2.1"), Ipv4Address("10.1.2.1"), 1);
|
||||
|
||||
staticRoutingDst->AddHostRouteTo (Ipv4Address ("10.1.2.1"), Ipv4Address ("10.20.1.1"), 1);
|
||||
staticRoutingDstRtr->AddHostRouteTo (Ipv4Address ("10.1.2.1"), Ipv4Address ("10.10.2.1"), 2);
|
||||
staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.1.2.1"), Ipv4Address ("10.1.2.1"), 1);
|
||||
// There are no apps that can utilize the Socket Option so doing the work directly..
|
||||
// Taken from tcp-large-transfer example
|
||||
|
||||
// There are no apps that can utilize the Socket Option so doing the work directly..
|
||||
// Taken from tcp-large-transfer example
|
||||
Ptr<Socket> srcSocket1 =
|
||||
Socket::CreateSocket(nSrc, TypeId::LookupByName("ns3::TcpSocketFactory"));
|
||||
Ptr<Socket> srcSocket2 =
|
||||
Socket::CreateSocket(nSrc, TypeId::LookupByName("ns3::TcpSocketFactory"));
|
||||
Ptr<Socket> srcSocket3 =
|
||||
Socket::CreateSocket(nSrc, TypeId::LookupByName("ns3::TcpSocketFactory"));
|
||||
Ptr<Socket> srcSocket4 =
|
||||
Socket::CreateSocket(nSrc, TypeId::LookupByName("ns3::TcpSocketFactory"));
|
||||
|
||||
Ptr<Socket> srcSocket1 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory"));
|
||||
Ptr<Socket> srcSocket2 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory"));
|
||||
Ptr<Socket> srcSocket3 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory"));
|
||||
Ptr<Socket> srcSocket4 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory"));
|
||||
uint16_t dstport = 12345;
|
||||
Ipv4Address dstaddr("10.20.1.2");
|
||||
|
||||
PacketSinkHelper sink("ns3::TcpSocketFactory",
|
||||
InetSocketAddress(Ipv4Address::GetAny(), dstport));
|
||||
ApplicationContainer apps = sink.Install(nDst);
|
||||
apps.Start(Seconds(0.0));
|
||||
apps.Stop(Seconds(10.0));
|
||||
|
||||
uint16_t dstport = 12345;
|
||||
Ipv4Address dstaddr ("10.20.1.2");
|
||||
AsciiTraceHelper ascii;
|
||||
p2p.EnableAsciiAll(ascii.CreateFileStream("socket-bound-tcp-static-routing.tr"));
|
||||
p2p.EnablePcapAll("socket-bound-tcp-static-routing");
|
||||
|
||||
PacketSinkHelper sink ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), dstport));
|
||||
ApplicationContainer apps = sink.Install (nDst);
|
||||
apps.Start (Seconds (0.0));
|
||||
apps.Stop (Seconds (10.0));
|
||||
LogComponentEnableAll(LOG_PREFIX_TIME);
|
||||
LogComponentEnable("SocketBoundTcpRoutingExample", LOG_LEVEL_INFO);
|
||||
|
||||
AsciiTraceHelper ascii;
|
||||
p2p.EnableAsciiAll (ascii.CreateFileStream ("socket-bound-tcp-static-routing.tr"));
|
||||
p2p.EnablePcapAll ("socket-bound-tcp-static-routing");
|
||||
// First packet as normal (goes via Rtr1)
|
||||
Simulator::Schedule(Seconds(0.1), &StartFlow, srcSocket1, dstaddr, dstport);
|
||||
// Second via Rtr1 explicitly
|
||||
Simulator::Schedule(Seconds(1.0), &BindSock, srcSocket2, SrcToRtr1);
|
||||
Simulator::Schedule(Seconds(1.1), &StartFlow, srcSocket2, dstaddr, dstport);
|
||||
// Third via Rtr2 explicitly
|
||||
Simulator::Schedule(Seconds(2.0), &BindSock, srcSocket3, SrcToRtr2);
|
||||
Simulator::Schedule(Seconds(2.1), &StartFlow, srcSocket3, dstaddr, dstport);
|
||||
// Fourth again as normal (goes via Rtr1)
|
||||
Simulator::Schedule(Seconds(3.0), &BindSock, srcSocket4, Ptr<NetDevice>(nullptr));
|
||||
Simulator::Schedule(Seconds(3.1), &StartFlow, srcSocket4, dstaddr, dstport);
|
||||
// If you uncomment what's below, it results in ASSERT failing since you can't
|
||||
// bind to a socket not existing on a node
|
||||
// Simulator::Schedule(Seconds(4.0),&BindSock, srcSocket, dDstRtrdDst.Get(0));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
|
||||
LogComponentEnableAll (LOG_PREFIX_TIME);
|
||||
LogComponentEnable ("SocketBoundTcpRoutingExample", LOG_LEVEL_INFO);
|
||||
|
||||
// First packet as normal (goes via Rtr1)
|
||||
Simulator::Schedule (Seconds (0.1),&StartFlow, srcSocket1, dstaddr, dstport);
|
||||
// Second via Rtr1 explicitly
|
||||
Simulator::Schedule (Seconds (1.0),&BindSock, srcSocket2, SrcToRtr1);
|
||||
Simulator::Schedule (Seconds (1.1),&StartFlow, srcSocket2, dstaddr, dstport);
|
||||
// Third via Rtr2 explicitly
|
||||
Simulator::Schedule (Seconds (2.0),&BindSock, srcSocket3, SrcToRtr2);
|
||||
Simulator::Schedule (Seconds (2.1),&StartFlow, srcSocket3, dstaddr, dstport);
|
||||
// Fourth again as normal (goes via Rtr1)
|
||||
Simulator::Schedule (Seconds (3.0),&BindSock, srcSocket4, Ptr<NetDevice>(0));
|
||||
Simulator::Schedule (Seconds (3.1),&StartFlow, srcSocket4, dstaddr, dstport);
|
||||
// If you uncomment what's below, it results in ASSERT failing since you can't
|
||||
// bind to a socket not existing on a node
|
||||
// Simulator::Schedule(Seconds(4.0),&BindSock, srcSocket, dDstRtrdDst.Get(0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BindSock (Ptr<Socket> sock, Ptr<NetDevice> netdev)
|
||||
void
|
||||
BindSock(Ptr<Socket> sock, Ptr<NetDevice> netdev)
|
||||
{
|
||||
sock->BindToNetDevice (netdev);
|
||||
return;
|
||||
sock->BindToNetDevice(netdev);
|
||||
}
|
||||
|
||||
void StartFlow (Ptr<Socket> localSocket,
|
||||
Ipv4Address servAddress,
|
||||
uint16_t servPort)
|
||||
void
|
||||
StartFlow(Ptr<Socket> localSocket, Ipv4Address servAddress, uint16_t servPort)
|
||||
{
|
||||
NS_LOG_INFO ("Starting flow at time " << Simulator::Now ().GetSeconds ());
|
||||
currentTxBytes = 0;
|
||||
localSocket->Bind ();
|
||||
localSocket->Connect (InetSocketAddress (servAddress, servPort)); //connect
|
||||
NS_LOG_INFO("Starting flow at time " << Simulator::Now().GetSeconds());
|
||||
currentTxBytes = 0;
|
||||
localSocket->Bind();
|
||||
localSocket->Connect(InetSocketAddress(servAddress, servPort)); // connect
|
||||
|
||||
// tell the tcp implementation to call WriteUntilBufferFull again
|
||||
// if we blocked and new tx buffer space becomes available
|
||||
localSocket->SetSendCallback (MakeCallback (&WriteUntilBufferFull));
|
||||
WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ());
|
||||
// tell the tcp implementation to call WriteUntilBufferFull again
|
||||
// if we blocked and new tx buffer space becomes available
|
||||
localSocket->SetSendCallback(MakeCallback(&WriteUntilBufferFull));
|
||||
WriteUntilBufferFull(localSocket, localSocket->GetTxAvailable());
|
||||
}
|
||||
|
||||
void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace)
|
||||
void
|
||||
WriteUntilBufferFull(Ptr<Socket> localSocket, uint32_t txSpace)
|
||||
{
|
||||
while (currentTxBytes < totalTxBytes && localSocket->GetTxAvailable () > 0)
|
||||
while (currentTxBytes < totalTxBytes && localSocket->GetTxAvailable() > 0)
|
||||
{
|
||||
uint32_t left = totalTxBytes - currentTxBytes;
|
||||
uint32_t dataOffset = currentTxBytes % writeSize;
|
||||
uint32_t toWrite = writeSize - dataOffset;
|
||||
toWrite = std::min (toWrite, left);
|
||||
toWrite = std::min (toWrite, localSocket->GetTxAvailable ());
|
||||
int amountSent = localSocket->Send (&data[dataOffset], toWrite, 0);
|
||||
if(amountSent < 0)
|
||||
uint32_t left = totalTxBytes - currentTxBytes;
|
||||
uint32_t dataOffset = currentTxBytes % writeSize;
|
||||
uint32_t toWrite = writeSize - dataOffset;
|
||||
toWrite = std::min(toWrite, left);
|
||||
toWrite = std::min(toWrite, localSocket->GetTxAvailable());
|
||||
int amountSent = localSocket->Send(&data[dataOffset], toWrite, 0);
|
||||
if (amountSent < 0)
|
||||
{
|
||||
// we will be called again when new tx space becomes available.
|
||||
return;
|
||||
// we will be called again when new tx space becomes available.
|
||||
return;
|
||||
}
|
||||
currentTxBytes += amountSent;
|
||||
currentTxBytes += amountSent;
|
||||
}
|
||||
localSocket->Close ();
|
||||
localSocket->Close();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2018-20 NITK Surathkal
|
||||
*
|
||||
@@ -53,213 +52,223 @@
|
||||
// The congestion window and queue occupancy traces output by this program show
|
||||
// periodic drops every 10 seconds when BBR algorithm is in PROBE_RTT phase.
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/flow-monitor-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
std::string dir;
|
||||
uint32_t prev = 0;
|
||||
Time prevTime = Seconds (0);
|
||||
Time prevTime = Seconds(0);
|
||||
|
||||
// Calculate throughput
|
||||
static void
|
||||
TraceThroughput (Ptr<FlowMonitor> monitor)
|
||||
TraceThroughput(Ptr<FlowMonitor> monitor)
|
||||
{
|
||||
FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats ();
|
||||
auto itr = stats.begin ();
|
||||
Time curTime = Now ();
|
||||
std::ofstream thr (dir + "/throughput.dat", std::ios::out | std::ios::app);
|
||||
thr << curTime << " " << 8 * (itr->second.txBytes - prev) / (1000 * 1000 * (curTime.GetSeconds () - prevTime.GetSeconds ())) << std::endl;
|
||||
prevTime = curTime;
|
||||
prev = itr->second.txBytes;
|
||||
Simulator::Schedule (Seconds (0.2), &TraceThroughput, monitor);
|
||||
FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
|
||||
auto itr = stats.begin();
|
||||
Time curTime = Now();
|
||||
std::ofstream thr(dir + "/throughput.dat", std::ios::out | std::ios::app);
|
||||
thr << curTime << " "
|
||||
<< 8 * (itr->second.txBytes - prev) /
|
||||
(1000 * 1000 * (curTime.GetSeconds() - prevTime.GetSeconds()))
|
||||
<< std::endl;
|
||||
prevTime = curTime;
|
||||
prev = itr->second.txBytes;
|
||||
Simulator::Schedule(Seconds(0.2), &TraceThroughput, monitor);
|
||||
}
|
||||
|
||||
// Check the queue size
|
||||
void CheckQueueSize (Ptr<QueueDisc> qd)
|
||||
void
|
||||
CheckQueueSize(Ptr<QueueDisc> qd)
|
||||
{
|
||||
uint32_t qsize = qd->GetCurrentSize ().GetValue ();
|
||||
Simulator::Schedule (Seconds (0.2), &CheckQueueSize, qd);
|
||||
std::ofstream q (dir + "/queueSize.dat", std::ios::out | std::ios::app);
|
||||
q << Simulator::Now ().GetSeconds () << " " << qsize << std::endl;
|
||||
q.close ();
|
||||
uint32_t qsize = qd->GetCurrentSize().GetValue();
|
||||
Simulator::Schedule(Seconds(0.2), &CheckQueueSize, qd);
|
||||
std::ofstream q(dir + "/queueSize.dat", std::ios::out | std::ios::app);
|
||||
q << Simulator::Now().GetSeconds() << " " << qsize << std::endl;
|
||||
q.close();
|
||||
}
|
||||
|
||||
// Trace congestion window
|
||||
static void CwndTracer (Ptr<OutputStreamWrapper> stream, uint32_t oldval, uint32_t newval)
|
||||
static void
|
||||
CwndTracer(Ptr<OutputStreamWrapper> stream, uint32_t oldval, uint32_t newval)
|
||||
{
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newval / 1448.0 << std::endl;
|
||||
*stream->GetStream() << Simulator::Now().GetSeconds() << " " << newval / 1448.0 << std::endl;
|
||||
}
|
||||
|
||||
void TraceCwnd (uint32_t nodeId, uint32_t socketId)
|
||||
void
|
||||
TraceCwnd(uint32_t nodeId, uint32_t socketId)
|
||||
{
|
||||
AsciiTraceHelper ascii;
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream (dir + "/cwnd.dat");
|
||||
Config::ConnectWithoutContext ("/NodeList/" + std::to_string (nodeId) + "/$ns3::TcpL4Protocol/SocketList/" + std::to_string (socketId) + "/CongestionWindow", MakeBoundCallback (&CwndTracer, stream));
|
||||
AsciiTraceHelper ascii;
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream(dir + "/cwnd.dat");
|
||||
Config::ConnectWithoutContext("/NodeList/" + std::to_string(nodeId) +
|
||||
"/$ns3::TcpL4Protocol/SocketList/" +
|
||||
std::to_string(socketId) + "/CongestionWindow",
|
||||
MakeBoundCallback(&CwndTracer, stream));
|
||||
}
|
||||
|
||||
int main (int argc, char *argv [])
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
// Naming the output directory using local system time
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[80];
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
strftime(buffer, sizeof(buffer), "%d-%m-%Y-%I-%M-%S", timeinfo);
|
||||
std::string currentTime(buffer);
|
||||
|
||||
// Naming the output directory using local system time
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
char buffer [80];
|
||||
time (&rawtime);
|
||||
timeinfo = localtime (&rawtime);
|
||||
strftime (buffer, sizeof (buffer), "%d-%m-%Y-%I-%M-%S", timeinfo);
|
||||
std::string currentTime (buffer);
|
||||
std::string tcpTypeId = "TcpBbr";
|
||||
std::string queueDisc = "FifoQueueDisc";
|
||||
uint32_t delAckCount = 2;
|
||||
bool bql = true;
|
||||
bool enablePcap = false;
|
||||
Time stopTime = Seconds(100);
|
||||
|
||||
std::string tcpTypeId = "TcpBbr";
|
||||
std::string queueDisc = "FifoQueueDisc";
|
||||
uint32_t delAckCount = 2;
|
||||
bool bql = true;
|
||||
bool enablePcap = false;
|
||||
Time stopTime = Seconds (100);
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.AddValue("tcpTypeId", "Transport protocol to use: TcpNewReno, TcpBbr", tcpTypeId);
|
||||
cmd.AddValue("delAckCount", "Delayed ACK count", delAckCount);
|
||||
cmd.AddValue("enablePcap", "Enable/Disable pcap file generation", enablePcap);
|
||||
cmd.AddValue("stopTime",
|
||||
"Stop time for applications / simulation time will be stopTime + 1",
|
||||
stopTime);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("tcpTypeId", "Transport protocol to use: TcpNewReno, TcpBbr", tcpTypeId);
|
||||
cmd.AddValue ("delAckCount", "Delayed ACK count", delAckCount);
|
||||
cmd.AddValue ("enablePcap", "Enable/Disable pcap file generation", enablePcap);
|
||||
cmd.AddValue ("stopTime", "Stop time for applications / simulation time will be stopTime + 1", stopTime);
|
||||
cmd.Parse (argc, argv);
|
||||
queueDisc = std::string("ns3::") + queueDisc;
|
||||
|
||||
queueDisc = std::string ("ns3::") + queueDisc;
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::" + tcpTypeId));
|
||||
Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue(4194304));
|
||||
Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue(6291456));
|
||||
Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(10));
|
||||
Config::SetDefault("ns3::TcpSocket::DelAckCount", UintegerValue(delAckCount));
|
||||
Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1448));
|
||||
Config::SetDefault("ns3::DropTailQueue<Packet>::MaxSize", QueueSizeValue(QueueSize("1p")));
|
||||
Config::SetDefault(queueDisc + "::MaxSize", QueueSizeValue(QueueSize("100p")));
|
||||
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue ("ns3::" + tcpTypeId));
|
||||
Config::SetDefault ("ns3::TcpSocket::SndBufSize", UintegerValue (4194304));
|
||||
Config::SetDefault ("ns3::TcpSocket::RcvBufSize", UintegerValue (6291456));
|
||||
Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (10));
|
||||
Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (delAckCount));
|
||||
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1448));
|
||||
Config::SetDefault ("ns3::DropTailQueue<Packet>::MaxSize", QueueSizeValue (QueueSize ("1p")));
|
||||
Config::SetDefault (queueDisc + "::MaxSize", QueueSizeValue (QueueSize ("100p")));
|
||||
NodeContainer sender;
|
||||
NodeContainer receiver;
|
||||
NodeContainer routers;
|
||||
sender.Create(1);
|
||||
receiver.Create(1);
|
||||
routers.Create(2);
|
||||
|
||||
NodeContainer sender, receiver;
|
||||
NodeContainer routers;
|
||||
sender.Create (1);
|
||||
receiver.Create (1);
|
||||
routers.Create (2);
|
||||
// Create the point-to-point link helpers
|
||||
PointToPointHelper bottleneckLink;
|
||||
bottleneckLink.SetDeviceAttribute("DataRate", StringValue("10Mbps"));
|
||||
bottleneckLink.SetChannelAttribute("Delay", StringValue("10ms"));
|
||||
|
||||
// Create the point-to-point link helpers
|
||||
PointToPointHelper bottleneckLink;
|
||||
bottleneckLink.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
|
||||
bottleneckLink.SetChannelAttribute ("Delay", StringValue ("10ms"));
|
||||
PointToPointHelper edgeLink;
|
||||
edgeLink.SetDeviceAttribute("DataRate", StringValue("1000Mbps"));
|
||||
edgeLink.SetChannelAttribute("Delay", StringValue("5ms"));
|
||||
|
||||
PointToPointHelper edgeLink;
|
||||
edgeLink.SetDeviceAttribute ("DataRate", StringValue ("1000Mbps"));
|
||||
edgeLink.SetChannelAttribute ("Delay", StringValue ("5ms"));
|
||||
// Create NetDevice containers
|
||||
NetDeviceContainer senderEdge = edgeLink.Install(sender.Get(0), routers.Get(0));
|
||||
NetDeviceContainer r1r2 = bottleneckLink.Install(routers.Get(0), routers.Get(1));
|
||||
NetDeviceContainer receiverEdge = edgeLink.Install(routers.Get(1), receiver.Get(0));
|
||||
|
||||
// Create NetDevice containers
|
||||
NetDeviceContainer senderEdge = edgeLink.Install (sender.Get (0), routers.Get (0));
|
||||
NetDeviceContainer r1r2 = bottleneckLink.Install (routers.Get (0), routers.Get (1));
|
||||
NetDeviceContainer receiverEdge = edgeLink.Install (routers.Get (1), receiver.Get (0));
|
||||
// Install Stack
|
||||
InternetStackHelper internet;
|
||||
internet.Install(sender);
|
||||
internet.Install(receiver);
|
||||
internet.Install(routers);
|
||||
|
||||
// Install Stack
|
||||
InternetStackHelper internet;
|
||||
internet.Install (sender);
|
||||
internet.Install (receiver);
|
||||
internet.Install (routers);
|
||||
// Configure the root queue discipline
|
||||
TrafficControlHelper tch;
|
||||
tch.SetRootQueueDisc(queueDisc);
|
||||
|
||||
// Configure the root queue discipline
|
||||
TrafficControlHelper tch;
|
||||
tch.SetRootQueueDisc (queueDisc);
|
||||
|
||||
if (bql)
|
||||
if (bql)
|
||||
{
|
||||
tch.SetQueueLimits ("ns3::DynamicQueueLimits", "HoldTime", StringValue ("1000ms"));
|
||||
tch.SetQueueLimits("ns3::DynamicQueueLimits", "HoldTime", StringValue("1000ms"));
|
||||
}
|
||||
|
||||
tch.Install (senderEdge);
|
||||
tch.Install (receiverEdge);
|
||||
tch.Install(senderEdge);
|
||||
tch.Install(receiverEdge);
|
||||
|
||||
// Assign IP addresses
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.0.0.0", "255.255.255.0");
|
||||
// Assign IP addresses
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase("10.0.0.0", "255.255.255.0");
|
||||
|
||||
Ipv4InterfaceContainer i1i2 = ipv4.Assign (r1r2);
|
||||
Ipv4InterfaceContainer i1i2 = ipv4.Assign(r1r2);
|
||||
|
||||
ipv4.NewNetwork ();
|
||||
Ipv4InterfaceContainer is1 = ipv4.Assign (senderEdge);
|
||||
ipv4.NewNetwork();
|
||||
Ipv4InterfaceContainer is1 = ipv4.Assign(senderEdge);
|
||||
|
||||
ipv4.NewNetwork ();
|
||||
Ipv4InterfaceContainer ir1 = ipv4.Assign (receiverEdge);
|
||||
ipv4.NewNetwork();
|
||||
Ipv4InterfaceContainer ir1 = ipv4.Assign(receiverEdge);
|
||||
|
||||
// Populate routing tables
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
// Populate routing tables
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
|
||||
|
||||
// Select sender side port
|
||||
uint16_t port = 50001;
|
||||
// Select sender side port
|
||||
uint16_t port = 50001;
|
||||
|
||||
// Install application on the sender
|
||||
BulkSendHelper source ("ns3::TcpSocketFactory", InetSocketAddress (ir1.GetAddress (1), port));
|
||||
source.SetAttribute ("MaxBytes", UintegerValue (0));
|
||||
ApplicationContainer sourceApps = source.Install (sender.Get (0));
|
||||
sourceApps.Start (Seconds (0.1));
|
||||
// Hook trace source after application starts
|
||||
Simulator::Schedule (Seconds (0.1) + MilliSeconds (1), &TraceCwnd, 0, 0);
|
||||
sourceApps.Stop (stopTime);
|
||||
// Install application on the sender
|
||||
BulkSendHelper source("ns3::TcpSocketFactory", InetSocketAddress(ir1.GetAddress(1), port));
|
||||
source.SetAttribute("MaxBytes", UintegerValue(0));
|
||||
ApplicationContainer sourceApps = source.Install(sender.Get(0));
|
||||
sourceApps.Start(Seconds(0.1));
|
||||
// Hook trace source after application starts
|
||||
Simulator::Schedule(Seconds(0.1) + MilliSeconds(1), &TraceCwnd, 0, 0);
|
||||
sourceApps.Stop(stopTime);
|
||||
|
||||
// Install application on the receiver
|
||||
PacketSinkHelper sink ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
ApplicationContainer sinkApps = sink.Install (receiver.Get (0));
|
||||
sinkApps.Start (Seconds (0.0));
|
||||
sinkApps.Stop (stopTime);
|
||||
// Install application on the receiver
|
||||
PacketSinkHelper sink("ns3::TcpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), port));
|
||||
ApplicationContainer sinkApps = sink.Install(receiver.Get(0));
|
||||
sinkApps.Start(Seconds(0.0));
|
||||
sinkApps.Stop(stopTime);
|
||||
|
||||
// Create a new directory to store the output of the program
|
||||
dir = "bbr-results/" + currentTime + "/";
|
||||
std::string dirToSave = "mkdir -p " + dir;
|
||||
if (system (dirToSave.c_str ()) == -1)
|
||||
// Create a new directory to store the output of the program
|
||||
dir = "bbr-results/" + currentTime + "/";
|
||||
std::string dirToSave = "mkdir -p " + dir;
|
||||
if (system(dirToSave.c_str()) == -1)
|
||||
{
|
||||
exit (1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// The plotting scripts are provided in the following repository, if needed:
|
||||
// https://github.com/mohittahiliani/BBR-Validation/
|
||||
//
|
||||
// Download 'PlotScripts' directory (which is inside ns-3 scripts directory)
|
||||
// from the link given above and place it in the ns-3 root directory.
|
||||
// Uncomment the following three lines to generate plots for Congestion
|
||||
// Window, sender side throughput and queue occupancy on the bottleneck link.
|
||||
//
|
||||
// system (("cp -R PlotScripts/gnuplotScriptCwnd " + dir).c_str ());
|
||||
// system (("cp -R PlotScripts/gnuplotScriptThroughput " + dir).c_str ());
|
||||
// system (("cp -R PlotScripts/gnuplotScriptQueueSize " + dir).c_str ());
|
||||
// The plotting scripts are provided in the following repository, if needed:
|
||||
// https://github.com/mohittahiliani/BBR-Validation/
|
||||
//
|
||||
// Download 'PlotScripts' directory (which is inside ns-3 scripts directory)
|
||||
// from the link given above and place it in the ns-3 root directory.
|
||||
// Uncomment the following three lines to generate plots for Congestion
|
||||
// Window, sender side throughput and queue occupancy on the bottleneck link.
|
||||
//
|
||||
// system (("cp -R PlotScripts/gnuplotScriptCwnd " + dir).c_str ());
|
||||
// system (("cp -R PlotScripts/gnuplotScriptThroughput " + dir).c_str ());
|
||||
// system (("cp -R PlotScripts/gnuplotScriptQueueSize " + dir).c_str ());
|
||||
|
||||
// Trace the queue occupancy on the second interface of R1
|
||||
tch.Uninstall (routers.Get (0)->GetDevice (1));
|
||||
QueueDiscContainer qd;
|
||||
qd = tch.Install (routers.Get (0)->GetDevice (1));
|
||||
Simulator::ScheduleNow (&CheckQueueSize, qd.Get (0));
|
||||
// Trace the queue occupancy on the second interface of R1
|
||||
tch.Uninstall(routers.Get(0)->GetDevice(1));
|
||||
QueueDiscContainer qd;
|
||||
qd = tch.Install(routers.Get(0)->GetDevice(1));
|
||||
Simulator::ScheduleNow(&CheckQueueSize, qd.Get(0));
|
||||
|
||||
// Generate PCAP traces if it is enabled
|
||||
if (enablePcap)
|
||||
// Generate PCAP traces if it is enabled
|
||||
if (enablePcap)
|
||||
{
|
||||
if (system ((dirToSave + "/pcap/").c_str ()) == -1)
|
||||
if (system((dirToSave + "/pcap/").c_str()) == -1)
|
||||
{
|
||||
exit (1);
|
||||
exit(1);
|
||||
}
|
||||
bottleneckLink.EnablePcapAll (dir + "/pcap/bbr", true);
|
||||
bottleneckLink.EnablePcapAll(dir + "/pcap/bbr", true);
|
||||
}
|
||||
|
||||
// Check for dropped packets using Flow Monitor
|
||||
FlowMonitorHelper flowmon;
|
||||
Ptr<FlowMonitor> monitor = flowmon.InstallAll ();
|
||||
Simulator::Schedule (Seconds (0 + 0.000001), &TraceThroughput, monitor);
|
||||
// Check for dropped packets using Flow Monitor
|
||||
FlowMonitorHelper flowmon;
|
||||
Ptr<FlowMonitor> monitor = flowmon.InstallAll();
|
||||
Simulator::Schedule(Seconds(0 + 0.000001), &TraceThroughput, monitor);
|
||||
|
||||
Simulator::Stop (stopTime + TimeStep (1));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
Simulator::Stop(stopTime + TimeStep(1));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 NITK Surathkal
|
||||
*
|
||||
@@ -79,24 +78,25 @@
|
||||
// TCP Prague and ACK-filtering, which may show a stronger performance
|
||||
// impact for TCP pacing.
|
||||
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/flow-monitor-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/ipv4-global-routing-helper.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/flow-monitor-module.h"
|
||||
#include "ns3/ipv4-global-routing-helper.h"
|
||||
#include "ns3/traffic-control-module.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpPacingExample");
|
||||
NS_LOG_COMPONENT_DEFINE("TcpPacingExample");
|
||||
|
||||
std::ofstream cwndStream;
|
||||
std::ofstream pacingRateStream;
|
||||
@@ -104,231 +104,252 @@ std::ofstream ssThreshStream;
|
||||
std::ofstream packetTraceStream;
|
||||
|
||||
static void
|
||||
CwndTracer (uint32_t oldval, uint32_t newval)
|
||||
CwndTracer(uint32_t oldval, uint32_t newval)
|
||||
{
|
||||
cwndStream << std::fixed << std::setprecision (6) << Simulator::Now ().GetSeconds () << std::setw (12) << newval << std::endl;
|
||||
cwndStream << std::fixed << std::setprecision(6) << Simulator::Now().GetSeconds()
|
||||
<< std::setw(12) << newval << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
PacingRateTracer (DataRate oldval, DataRate newval)
|
||||
PacingRateTracer(DataRate oldval, DataRate newval)
|
||||
{
|
||||
pacingRateStream << std::fixed << std::setprecision (6) << Simulator::Now ().GetSeconds () << std::setw (12) << newval.GetBitRate () / 1e6 << std::endl;
|
||||
pacingRateStream << std::fixed << std::setprecision(6) << Simulator::Now().GetSeconds()
|
||||
<< std::setw(12) << newval.GetBitRate() / 1e6 << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
SsThreshTracer (uint32_t oldval, uint32_t newval)
|
||||
SsThreshTracer(uint32_t oldval, uint32_t newval)
|
||||
{
|
||||
ssThreshStream << std::fixed << std::setprecision (6) << Simulator::Now ().GetSeconds () << std::setw (12) << newval << std::endl;
|
||||
ssThreshStream << std::fixed << std::setprecision(6) << Simulator::Now().GetSeconds()
|
||||
<< std::setw(12) << newval << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
TxTracer (Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface)
|
||||
TxTracer(Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface)
|
||||
{
|
||||
packetTraceStream << std::fixed << std::setprecision (6) << Simulator::Now ().GetSeconds () << " tx " << p->GetSize () << std::endl;
|
||||
packetTraceStream << std::fixed << std::setprecision(6) << Simulator::Now().GetSeconds()
|
||||
<< " tx " << p->GetSize() << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
RxTracer (Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface)
|
||||
RxTracer(Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface)
|
||||
{
|
||||
packetTraceStream << std::fixed << std::setprecision (6) << Simulator::Now ().GetSeconds () << " rx " << p->GetSize () << std::endl;
|
||||
packetTraceStream << std::fixed << std::setprecision(6) << Simulator::Now().GetSeconds()
|
||||
<< " rx " << p->GetSize() << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
ConnectSocketTraces (void)
|
||||
ConnectSocketTraces()
|
||||
{
|
||||
Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeCallback (&CwndTracer));
|
||||
Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/PacingRate", MakeCallback (&PacingRateTracer));
|
||||
Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/SlowStartThreshold", MakeCallback (&SsThreshTracer));
|
||||
Config::ConnectWithoutContext ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx", MakeCallback (&TxTracer));
|
||||
Config::ConnectWithoutContext ("/NodeList/0/$ns3::Ipv4L3Protocol/Rx", MakeCallback (&RxTracer));
|
||||
Config::ConnectWithoutContext("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
|
||||
MakeCallback(&CwndTracer));
|
||||
Config::ConnectWithoutContext("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/PacingRate",
|
||||
MakeCallback(&PacingRateTracer));
|
||||
Config::ConnectWithoutContext("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/SlowStartThreshold",
|
||||
MakeCallback(&SsThreshTracer));
|
||||
Config::ConnectWithoutContext("/NodeList/0/$ns3::Ipv4L3Protocol/Tx", MakeCallback(&TxTracer));
|
||||
Config::ConnectWithoutContext("/NodeList/0/$ns3::Ipv4L3Protocol/Rx", MakeCallback(&RxTracer));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
bool tracing = false;
|
||||
|
||||
bool tracing = false;
|
||||
uint32_t maxBytes = 0; // value of zero corresponds to unlimited send
|
||||
std::string transportProtocol = "ns3::TcpCubic";
|
||||
|
||||
uint32_t maxBytes = 0; // value of zero corresponds to unlimited send
|
||||
std::string transportProtocol = "ns3::TcpCubic";
|
||||
Time simulationEndTime = Seconds(5);
|
||||
DataRate bottleneckBandwidth("10Mbps"); // value of x as shown in the above network topology
|
||||
Time bottleneckDelay = MilliSeconds(40);
|
||||
DataRate regLinkBandwidth = DataRate(4 * bottleneckBandwidth.GetBitRate());
|
||||
Time regLinkDelay = MilliSeconds(5);
|
||||
DataRate maxPacingRate("4Gbps");
|
||||
|
||||
Time simulationEndTime = Seconds (5);
|
||||
DataRate bottleneckBandwidth ("10Mbps"); // value of x as shown in the above network topology
|
||||
Time bottleneckDelay = MilliSeconds (40);
|
||||
DataRate regLinkBandwidth = DataRate (4 * bottleneckBandwidth.GetBitRate ());
|
||||
Time regLinkDelay = MilliSeconds (5);
|
||||
DataRate maxPacingRate ("4Gbps");
|
||||
bool isPacingEnabled = true;
|
||||
bool useEcn = true;
|
||||
bool useQueueDisc = true;
|
||||
bool shouldPaceInitialWindow = true;
|
||||
|
||||
bool isPacingEnabled = true;
|
||||
bool useEcn = true;
|
||||
bool useQueueDisc = true;
|
||||
bool shouldPaceInitialWindow = true;
|
||||
// Configure defaults that are not based on explicit command-line arguments
|
||||
// They may be overridden by general attribute configuration of command line
|
||||
Config::SetDefault("ns3::TcpL4Protocol::SocketType",
|
||||
TypeIdValue(TypeId::LookupByName(transportProtocol)));
|
||||
Config::SetDefault("ns3::TcpSocket::InitialCwnd", UintegerValue(10));
|
||||
|
||||
// Configure defaults that are not based on explicit command-line arguments
|
||||
// They may be overridden by general attribute configuration of command line
|
||||
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TypeId::LookupByName (transportProtocol)));
|
||||
Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (10));
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.AddValue("tracing", "Flag to enable/disable Ascii and Pcap tracing", tracing);
|
||||
cmd.AddValue("maxBytes", "Total number of bytes for application to send", maxBytes);
|
||||
cmd.AddValue("isPacingEnabled", "Flag to enable/disable pacing in TCP", isPacingEnabled);
|
||||
cmd.AddValue("maxPacingRate", "Max Pacing Rate", maxPacingRate);
|
||||
cmd.AddValue("useEcn", "Flag to enable/disable ECN", useEcn);
|
||||
cmd.AddValue("useQueueDisc", "Flag to enable/disable queue disc on bottleneck", useQueueDisc);
|
||||
cmd.AddValue("shouldPaceInitialWindow",
|
||||
"Flag to enable/disable pacing of TCP initial window",
|
||||
shouldPaceInitialWindow);
|
||||
cmd.AddValue("simulationEndTime", "Simulation end time", simulationEndTime);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("tracing", "Flag to enable/disable Ascii and Pcap tracing", tracing);
|
||||
cmd.AddValue ("maxBytes", "Total number of bytes for application to send", maxBytes);
|
||||
cmd.AddValue ("isPacingEnabled", "Flag to enable/disable pacing in TCP", isPacingEnabled);
|
||||
cmd.AddValue ("maxPacingRate", "Max Pacing Rate", maxPacingRate);
|
||||
cmd.AddValue ("useEcn", "Flag to enable/disable ECN", useEcn);
|
||||
cmd.AddValue ("useQueueDisc", "Flag to enable/disable queue disc on bottleneck", useQueueDisc);
|
||||
cmd.AddValue ("shouldPaceInitialWindow", "Flag to enable/disable pacing of TCP initial window", shouldPaceInitialWindow);
|
||||
cmd.AddValue ("simulationEndTime", "Simulation end time", simulationEndTime);
|
||||
cmd.Parse (argc, argv);
|
||||
// Configure defaults based on command-line arguments
|
||||
Config::SetDefault("ns3::TcpSocketState::EnablePacing", BooleanValue(isPacingEnabled));
|
||||
Config::SetDefault("ns3::TcpSocketState::PaceInitialWindow",
|
||||
BooleanValue(shouldPaceInitialWindow));
|
||||
Config::SetDefault("ns3::TcpSocketBase::UseEcn",
|
||||
(useEcn ? EnumValue(TcpSocketState::On) : EnumValue(TcpSocketState::Off)));
|
||||
Config::SetDefault("ns3::TcpSocketState::MaxPacingRate", DataRateValue(maxPacingRate));
|
||||
|
||||
// Configure defaults based on command-line arguments
|
||||
Config::SetDefault ("ns3::TcpSocketState::EnablePacing", BooleanValue (isPacingEnabled));
|
||||
Config::SetDefault ("ns3::TcpSocketState::PaceInitialWindow", BooleanValue (shouldPaceInitialWindow));
|
||||
Config::SetDefault ("ns3::TcpSocketBase::UseEcn", (useEcn ? EnumValue (TcpSocketState::On) : EnumValue (TcpSocketState::Off)));
|
||||
Config::SetDefault ("ns3::TcpSocketState::MaxPacingRate", DataRateValue (maxPacingRate));
|
||||
NS_LOG_INFO("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create(6);
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer c;
|
||||
c.Create (6);
|
||||
NS_LOG_INFO("Create channels.");
|
||||
NodeContainer n0n2 = NodeContainer(c.Get(0), c.Get(2));
|
||||
NodeContainer n1n2 = NodeContainer(c.Get(1), c.Get(2));
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
NodeContainer n0n2 = NodeContainer (c.Get (0), c.Get (2));
|
||||
NodeContainer n1n2 = NodeContainer (c.Get (1), c.Get (2));
|
||||
NodeContainer n2n3 = NodeContainer(c.Get(2), c.Get(3));
|
||||
|
||||
NodeContainer n2n3 = NodeContainer (c.Get (2), c.Get (3));
|
||||
NodeContainer n3n4 = NodeContainer(c.Get(3), c.Get(4));
|
||||
NodeContainer n3n5 = NodeContainer(c.Get(3), c.Get(5));
|
||||
|
||||
NodeContainer n3n4 = NodeContainer (c.Get (3), c.Get (4));
|
||||
NodeContainer n3n5 = NodeContainer (c.Get (3), c.Get (5));
|
||||
// Define Node link properties
|
||||
PointToPointHelper regLink;
|
||||
regLink.SetDeviceAttribute("DataRate", DataRateValue(regLinkBandwidth));
|
||||
regLink.SetChannelAttribute("Delay", TimeValue(regLinkDelay));
|
||||
|
||||
//Define Node link properties
|
||||
PointToPointHelper regLink;
|
||||
regLink.SetDeviceAttribute ("DataRate", DataRateValue (regLinkBandwidth));
|
||||
regLink.SetChannelAttribute ("Delay", TimeValue (regLinkDelay));
|
||||
NetDeviceContainer d0d2 = regLink.Install(n0n2);
|
||||
NetDeviceContainer d1d2 = regLink.Install(n1n2);
|
||||
NetDeviceContainer d3d4 = regLink.Install(n3n4);
|
||||
NetDeviceContainer d3d5 = regLink.Install(n3n5);
|
||||
|
||||
NetDeviceContainer d0d2 = regLink.Install (n0n2);
|
||||
NetDeviceContainer d1d2 = regLink.Install (n1n2);
|
||||
NetDeviceContainer d3d4 = regLink.Install (n3n4);
|
||||
NetDeviceContainer d3d5 = regLink.Install (n3n5);
|
||||
PointToPointHelper bottleNeckLink;
|
||||
bottleNeckLink.SetDeviceAttribute("DataRate", DataRateValue(bottleneckBandwidth));
|
||||
bottleNeckLink.SetChannelAttribute("Delay", TimeValue(bottleneckDelay));
|
||||
|
||||
PointToPointHelper bottleNeckLink;
|
||||
bottleNeckLink.SetDeviceAttribute ("DataRate", DataRateValue (bottleneckBandwidth));
|
||||
bottleNeckLink.SetChannelAttribute ("Delay", TimeValue (bottleneckDelay));
|
||||
NetDeviceContainer d2d3 = bottleNeckLink.Install(n2n3);
|
||||
|
||||
NetDeviceContainer d2d3 = bottleNeckLink.Install (n2n3);
|
||||
// Install Internet stack
|
||||
InternetStackHelper stack;
|
||||
stack.Install(c);
|
||||
|
||||
//Install Internet stack
|
||||
InternetStackHelper stack;
|
||||
stack.Install (c);
|
||||
|
||||
// Install traffic control
|
||||
if (useQueueDisc)
|
||||
// Install traffic control
|
||||
if (useQueueDisc)
|
||||
{
|
||||
TrafficControlHelper tchBottleneck;
|
||||
tchBottleneck.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
|
||||
tchBottleneck.Install (d2d3);
|
||||
TrafficControlHelper tchBottleneck;
|
||||
tchBottleneck.SetRootQueueDisc("ns3::FqCoDelQueueDisc");
|
||||
tchBottleneck.Install(d2d3);
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface0 = ipv4.Assign (d0d2);
|
||||
NS_LOG_INFO("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface0 = ipv4.Assign(d0d2);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface1 = ipv4.Assign (d1d2);
|
||||
ipv4.SetBase("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface1 = ipv4.Assign(d1d2);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer bottleneckInterface = ipv4.Assign (d2d3);
|
||||
ipv4.SetBase("10.1.3.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer bottleneckInterface = ipv4.Assign(d2d3);
|
||||
|
||||
ipv4.SetBase ("10.1.4.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface4 = ipv4.Assign (d3d4);
|
||||
ipv4.SetBase("10.1.4.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface4 = ipv4.Assign(d3d4);
|
||||
|
||||
ipv4.SetBase ("10.1.5.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface5 = ipv4.Assign (d3d5);
|
||||
ipv4.SetBase("10.1.5.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer regLinkInterface5 = ipv4.Assign(d3d5);
|
||||
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
|
||||
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
NS_LOG_INFO("Create Applications.");
|
||||
|
||||
// Two Sink Applications at n4 and n5
|
||||
uint16_t sinkPort = 8080;
|
||||
Address sinkAddress4 (InetSocketAddress (regLinkInterface4.GetAddress (1), sinkPort)); // interface of n4
|
||||
Address sinkAddress5 (InetSocketAddress (regLinkInterface5.GetAddress (1), sinkPort)); // interface of n5
|
||||
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
|
||||
ApplicationContainer sinkApps4 = packetSinkHelper.Install (c.Get (4)); //n4 as sink
|
||||
ApplicationContainer sinkApps5 = packetSinkHelper.Install (c.Get (5)); //n5 as sink
|
||||
// Two Sink Applications at n4 and n5
|
||||
uint16_t sinkPort = 8080;
|
||||
Address sinkAddress4(
|
||||
InetSocketAddress(regLinkInterface4.GetAddress(1), sinkPort)); // interface of n4
|
||||
Address sinkAddress5(
|
||||
InetSocketAddress(regLinkInterface5.GetAddress(1), sinkPort)); // interface of n5
|
||||
PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory",
|
||||
InetSocketAddress(Ipv4Address::GetAny(), sinkPort));
|
||||
ApplicationContainer sinkApps4 = packetSinkHelper.Install(c.Get(4)); // n4 as sink
|
||||
ApplicationContainer sinkApps5 = packetSinkHelper.Install(c.Get(5)); // n5 as sink
|
||||
|
||||
sinkApps4.Start (Seconds (0));
|
||||
sinkApps4.Stop (simulationEndTime);
|
||||
sinkApps5.Start (Seconds (0));
|
||||
sinkApps5.Stop (simulationEndTime);
|
||||
sinkApps4.Start(Seconds(0));
|
||||
sinkApps4.Stop(simulationEndTime);
|
||||
sinkApps5.Start(Seconds(0));
|
||||
sinkApps5.Stop(simulationEndTime);
|
||||
|
||||
// Randomize the start time between 0 and 1ms
|
||||
Ptr<UniformRandomVariable> uniformRv = CreateObject<UniformRandomVariable> ();
|
||||
uniformRv->SetStream (0);
|
||||
// Randomize the start time between 0 and 1ms
|
||||
Ptr<UniformRandomVariable> uniformRv = CreateObject<UniformRandomVariable>();
|
||||
uniformRv->SetStream(0);
|
||||
|
||||
// Two Source Applications at n0 and n1
|
||||
BulkSendHelper source0 ("ns3::TcpSocketFactory", sinkAddress4);
|
||||
BulkSendHelper source1 ("ns3::TcpSocketFactory", sinkAddress5);
|
||||
// Set the amount of data to send in bytes. Zero is unlimited.
|
||||
source0.SetAttribute ("MaxBytes", UintegerValue (maxBytes));
|
||||
source1.SetAttribute ("MaxBytes", UintegerValue (maxBytes));
|
||||
ApplicationContainer sourceApps0 = source0.Install (c.Get (0));
|
||||
ApplicationContainer sourceApps1 = source1.Install (c.Get (1));
|
||||
// Two Source Applications at n0 and n1
|
||||
BulkSendHelper source0("ns3::TcpSocketFactory", sinkAddress4);
|
||||
BulkSendHelper source1("ns3::TcpSocketFactory", sinkAddress5);
|
||||
// Set the amount of data to send in bytes. Zero is unlimited.
|
||||
source0.SetAttribute("MaxBytes", UintegerValue(maxBytes));
|
||||
source1.SetAttribute("MaxBytes", UintegerValue(maxBytes));
|
||||
ApplicationContainer sourceApps0 = source0.Install(c.Get(0));
|
||||
ApplicationContainer sourceApps1 = source1.Install(c.Get(1));
|
||||
|
||||
sourceApps0.Start (MicroSeconds (uniformRv->GetInteger (0, 1000)));
|
||||
sourceApps0.Stop (simulationEndTime);
|
||||
sourceApps1.Start (MicroSeconds (uniformRv->GetInteger (0, 1000)));
|
||||
sourceApps1.Stop (simulationEndTime);
|
||||
sourceApps0.Start(MicroSeconds(uniformRv->GetInteger(0, 1000)));
|
||||
sourceApps0.Stop(simulationEndTime);
|
||||
sourceApps1.Start(MicroSeconds(uniformRv->GetInteger(0, 1000)));
|
||||
sourceApps1.Stop(simulationEndTime);
|
||||
|
||||
if (tracing)
|
||||
if (tracing)
|
||||
{
|
||||
AsciiTraceHelper ascii;
|
||||
regLink.EnableAsciiAll (ascii.CreateFileStream ("tcp-dynamic-pacing.tr"));
|
||||
regLink.EnablePcapAll ("tcp-dynamic-pacing", false);
|
||||
AsciiTraceHelper ascii;
|
||||
regLink.EnableAsciiAll(ascii.CreateFileStream("tcp-dynamic-pacing.tr"));
|
||||
regLink.EnablePcapAll("tcp-dynamic-pacing", false);
|
||||
}
|
||||
|
||||
cwndStream.open ("tcp-dynamic-pacing-cwnd.dat", std::ios::out);
|
||||
cwndStream << "#Time(s) Congestion Window (B)" << std::endl;
|
||||
cwndStream.open("tcp-dynamic-pacing-cwnd.dat", std::ios::out);
|
||||
cwndStream << "#Time(s) Congestion Window (B)" << std::endl;
|
||||
|
||||
pacingRateStream.open ("tcp-dynamic-pacing-pacing-rate.dat", std::ios::out);
|
||||
pacingRateStream << "#Time(s) Pacing Rate (Mb/s)" << std::endl;
|
||||
pacingRateStream.open("tcp-dynamic-pacing-pacing-rate.dat", std::ios::out);
|
||||
pacingRateStream << "#Time(s) Pacing Rate (Mb/s)" << std::endl;
|
||||
|
||||
ssThreshStream.open ("tcp-dynamic-pacing-ssthresh.dat", std::ios::out);
|
||||
ssThreshStream << "#Time(s) Slow Start threshold (B)" << std::endl;
|
||||
ssThreshStream.open("tcp-dynamic-pacing-ssthresh.dat", std::ios::out);
|
||||
ssThreshStream << "#Time(s) Slow Start threshold (B)" << std::endl;
|
||||
|
||||
packetTraceStream.open ("tcp-dynamic-pacing-packet-trace.dat", std::ios::out);
|
||||
packetTraceStream << "#Time(s) tx/rx size (B)" << std::endl;
|
||||
packetTraceStream.open("tcp-dynamic-pacing-packet-trace.dat", std::ios::out);
|
||||
packetTraceStream << "#Time(s) tx/rx size (B)" << std::endl;
|
||||
|
||||
Simulator::Schedule (MicroSeconds (1001), &ConnectSocketTraces);
|
||||
Simulator::Schedule(MicroSeconds(1001), &ConnectSocketTraces);
|
||||
|
||||
FlowMonitorHelper flowmon;
|
||||
Ptr<FlowMonitor> monitor = flowmon.InstallAll ();
|
||||
FlowMonitorHelper flowmon;
|
||||
Ptr<FlowMonitor> monitor = flowmon.InstallAll();
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Stop (simulationEndTime);
|
||||
Simulator::Run ();
|
||||
NS_LOG_INFO("Run Simulation.");
|
||||
Simulator::Stop(simulationEndTime);
|
||||
Simulator::Run();
|
||||
|
||||
monitor->CheckForLostPackets ();
|
||||
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier> (flowmon.GetClassifier ());
|
||||
FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats ();
|
||||
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin (); i != stats.end (); ++i)
|
||||
monitor->CheckForLostPackets();
|
||||
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier());
|
||||
FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats();
|
||||
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
|
||||
i != stats.end();
|
||||
++i)
|
||||
{
|
||||
Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow (i->first);
|
||||
Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
|
||||
|
||||
std::cout << "Flow " << i->first << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")\n";
|
||||
std::cout << " Tx Packets: " << i->second.txPackets << "\n";
|
||||
std::cout << " Tx Bytes: " << i->second.txBytes << "\n";
|
||||
std::cout << " TxOffered: " << i->second.txBytes * 8.0 / simulationEndTime.GetSeconds () / 1000 / 1000 << " Mbps\n";
|
||||
std::cout << " Rx Packets: " << i->second.rxPackets << "\n";
|
||||
std::cout << " Rx Bytes: " << i->second.rxBytes << "\n";
|
||||
std::cout << " Throughput: " << i->second.rxBytes * 8.0 / simulationEndTime.GetSeconds () / 1000 / 1000 << " Mbps\n";
|
||||
std::cout << "Flow " << i->first << " (" << t.sourceAddress << " -> "
|
||||
<< t.destinationAddress << ")\n";
|
||||
std::cout << " Tx Packets: " << i->second.txPackets << "\n";
|
||||
std::cout << " Tx Bytes: " << i->second.txBytes << "\n";
|
||||
std::cout << " TxOffered: "
|
||||
<< i->second.txBytes * 8.0 / simulationEndTime.GetSeconds() / 1000 / 1000
|
||||
<< " Mbps\n";
|
||||
std::cout << " Rx Packets: " << i->second.rxPackets << "\n";
|
||||
std::cout << " Rx Bytes: " << i->second.rxBytes << "\n";
|
||||
std::cout << " Throughput: "
|
||||
<< i->second.rxBytes * 8.0 / simulationEndTime.GetSeconds() / 1000 / 1000
|
||||
<< " Mbps\n";
|
||||
}
|
||||
|
||||
cwndStream.close();
|
||||
pacingRateStream.close();
|
||||
ssThreshStream.close();
|
||||
Simulator::Destroy();
|
||||
|
||||
cwndStream.close ();
|
||||
pacingRateStream.close ();
|
||||
ssThreshStream.close ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -15,7 +14,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Default Network topology, 9 nodes in a star
|
||||
/*
|
||||
n2 n3 n4
|
||||
@@ -33,140 +31,133 @@
|
||||
// "tcp-star-server-$n-$i.pcap" where n and i represent node and interface
|
||||
// numbers respectively
|
||||
// Usage examples for things you might want to tweak:
|
||||
// ./ns3 run="tcp-star-server"
|
||||
// ./ns3 run="tcp-star-server --nNodes=25"
|
||||
// ./ns3 run="tcp-star-server --ns3::OnOffApplication::DataRate=10000"
|
||||
// ./ns3 run="tcp-star-server --ns3::OnOffApplication::PacketSize=500"
|
||||
// See the ns-3 tutorial for more info on the command line:
|
||||
// ./ns3 run "tcp-star-server"
|
||||
// ./ns3 run "tcp-star-server --nNodes=25"
|
||||
// ./ns3 run "tcp-star-server --ns3::OnOffApplication::DataRate=10000"
|
||||
// ./ns3 run "tcp-star-server --ns3::OnOffApplication::PacketSize=500"
|
||||
// See the ns-3 tutorial for more info on the command line:
|
||||
// http://www.nsnam.org/tutorials.html
|
||||
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/ipv4-global-routing-helper.h"
|
||||
#include "ns3/mtp-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TcpServer");
|
||||
NS_LOG_COMPONENT_DEFINE("TcpServer");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);
|
||||
MtpInterface::Enable ();
|
||||
MtpInterface::Enable();
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
// LogComponentEnable ("TcpServer", LOG_LEVEL_INFO);
|
||||
// LogComponentEnable ("TcpL4Protocol", LOG_LEVEL_ALL);
|
||||
// LogComponentEnable ("TcpSocketImpl", LOG_LEVEL_ALL);
|
||||
// LogComponentEnable ("PacketSink", LOG_LEVEL_ALL);
|
||||
|
||||
//LogComponentEnable ("TcpServer", LOG_LEVEL_INFO);
|
||||
//LogComponentEnable ("TcpL4Protocol", LOG_LEVEL_ALL);
|
||||
//LogComponentEnable ("TcpSocketImpl", LOG_LEVEL_ALL);
|
||||
//LogComponentEnable ("PacketSink", LOG_LEVEL_ALL);
|
||||
// Set up some default values for the simulation.
|
||||
Config::SetDefault("ns3::OnOffApplication::PacketSize", UintegerValue(250));
|
||||
Config::SetDefault("ns3::OnOffApplication::DataRate", StringValue("5kb/s"));
|
||||
uint32_t N = 9; // number of nodes in the star
|
||||
|
||||
// Set up some default values for the simulation.
|
||||
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (250));
|
||||
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("5kb/s"));
|
||||
uint32_t N = 9; //number of nodes in the star
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Config::SetDefault()s at run-time, via command-line arguments
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.AddValue("nNodes", "Number of nodes to place in the star", N);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Config::SetDefault()s at run-time, via command-line arguments
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("nNodes", "Number of nodes to place in the star", N);
|
||||
cmd.Parse (argc, argv);
|
||||
// Here, we will create N nodes in a star.
|
||||
NS_LOG_INFO("Create nodes.");
|
||||
NodeContainer serverNode;
|
||||
NodeContainer clientNodes;
|
||||
serverNode.Create(1);
|
||||
clientNodes.Create(N - 1);
|
||||
NodeContainer allNodes = NodeContainer(serverNode, clientNodes);
|
||||
|
||||
// Here, we will create N nodes in a star.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
NodeContainer serverNode;
|
||||
NodeContainer clientNodes;
|
||||
serverNode.Create (1);
|
||||
clientNodes.Create (N-1);
|
||||
NodeContainer allNodes = NodeContainer (serverNode, clientNodes);
|
||||
// Install network stacks on the nodes
|
||||
InternetStackHelper internet;
|
||||
internet.Install(allNodes);
|
||||
|
||||
// Install network stacks on the nodes
|
||||
InternetStackHelper internet;
|
||||
internet.Install (allNodes);
|
||||
|
||||
//Collect an adjacency list of nodes for the p2p topology
|
||||
std::vector<NodeContainer> nodeAdjacencyList (N-1);
|
||||
for(uint32_t i=0; i<nodeAdjacencyList.size (); ++i)
|
||||
// Collect an adjacency list of nodes for the p2p topology
|
||||
std::vector<NodeContainer> nodeAdjacencyList(N - 1);
|
||||
for (uint32_t i = 0; i < nodeAdjacencyList.size(); ++i)
|
||||
{
|
||||
nodeAdjacencyList[i] = NodeContainer (serverNode, clientNodes.Get (i));
|
||||
nodeAdjacencyList[i] = NodeContainer(serverNode, clientNodes.Get(i));
|
||||
}
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
std::vector<NetDeviceContainer> deviceAdjacencyList (N-1);
|
||||
for(uint32_t i=0; i<deviceAdjacencyList.size (); ++i)
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO("Create channels.");
|
||||
PointToPointHelper p2p;
|
||||
p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
|
||||
p2p.SetChannelAttribute("Delay", StringValue("2ms"));
|
||||
std::vector<NetDeviceContainer> deviceAdjacencyList(N - 1);
|
||||
for (uint32_t i = 0; i < deviceAdjacencyList.size(); ++i)
|
||||
{
|
||||
deviceAdjacencyList[i] = p2p.Install (nodeAdjacencyList[i]);
|
||||
deviceAdjacencyList[i] = p2p.Install(nodeAdjacencyList[i]);
|
||||
}
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
std::vector<Ipv4InterfaceContainer> interfaceAdjacencyList (N-1);
|
||||
for(uint32_t i=0; i<interfaceAdjacencyList.size (); ++i)
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO("Assign IP Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
std::vector<Ipv4InterfaceContainer> interfaceAdjacencyList(N - 1);
|
||||
for (uint32_t i = 0; i < interfaceAdjacencyList.size(); ++i)
|
||||
{
|
||||
std::ostringstream subnet;
|
||||
subnet<<"10.1."<<i+1<<".0";
|
||||
ipv4.SetBase (subnet.str ().c_str (), "255.255.255.0");
|
||||
interfaceAdjacencyList[i] = ipv4.Assign (deviceAdjacencyList[i]);
|
||||
std::ostringstream subnet;
|
||||
subnet << "10.1." << i + 1 << ".0";
|
||||
ipv4.SetBase(subnet.str().c_str(), "255.255.255.0");
|
||||
interfaceAdjacencyList[i] = ipv4.Assign(deviceAdjacencyList[i]);
|
||||
}
|
||||
|
||||
//Turn on global static routing
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
||||
// Turn on global static routing
|
||||
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
|
||||
|
||||
// Create a packet sink on the star "hub" to receive these packets
|
||||
uint16_t port = 50000;
|
||||
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
|
||||
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp = sinkHelper.Install (serverNode);
|
||||
sinkApp.Start (Seconds (1.0));
|
||||
sinkApp.Stop (Seconds (10.0));
|
||||
// Create a packet sink on the star "hub" to receive these packets
|
||||
uint16_t port = 50000;
|
||||
Address sinkLocalAddress(InetSocketAddress(Ipv4Address::GetAny(), port));
|
||||
PacketSinkHelper sinkHelper("ns3::TcpSocketFactory", sinkLocalAddress);
|
||||
ApplicationContainer sinkApp = sinkHelper.Install(serverNode);
|
||||
sinkApp.Start(Seconds(1.0));
|
||||
sinkApp.Stop(Seconds(10.0));
|
||||
|
||||
// Create the OnOff applications to send TCP to the server
|
||||
OnOffHelper clientHelper ("ns3::TcpSocketFactory", Address ());
|
||||
clientHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
// Create the OnOff applications to send TCP to the server
|
||||
OnOffHelper clientHelper("ns3::TcpSocketFactory", Address());
|
||||
clientHelper.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
|
||||
clientHelper.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
|
||||
|
||||
//normally wouldn't need a loop here but the server IP address is different
|
||||
//on each p2p subnet
|
||||
ApplicationContainer clientApps;
|
||||
for(uint32_t i=0; i<clientNodes.GetN (); ++i)
|
||||
// normally wouldn't need a loop here but the server IP address is different
|
||||
// on each p2p subnet
|
||||
ApplicationContainer clientApps;
|
||||
for (uint32_t i = 0; i < clientNodes.GetN(); ++i)
|
||||
{
|
||||
AddressValue remoteAddress
|
||||
(InetSocketAddress (interfaceAdjacencyList[i].GetAddress (0), port));
|
||||
clientHelper.SetAttribute ("Remote", remoteAddress);
|
||||
clientApps.Add (clientHelper.Install (clientNodes.Get (i)));
|
||||
AddressValue remoteAddress(
|
||||
InetSocketAddress(interfaceAdjacencyList[i].GetAddress(0), port));
|
||||
clientHelper.SetAttribute("Remote", remoteAddress);
|
||||
clientApps.Add(clientHelper.Install(clientNodes.Get(i)));
|
||||
}
|
||||
clientApps.Start (Seconds (1.0));
|
||||
clientApps.Stop (Seconds (10.0));
|
||||
clientApps.Start(Seconds(1.0));
|
||||
clientApps.Stop(Seconds(10.0));
|
||||
|
||||
// configure tracing
|
||||
AsciiTraceHelper ascii;
|
||||
p2p.EnableAsciiAll(ascii.CreateFileStream("tcp-star-server.tr"));
|
||||
p2p.EnablePcapAll("tcp-star-server");
|
||||
|
||||
//configure tracing
|
||||
AsciiTraceHelper ascii;
|
||||
p2p.EnableAsciiAll (ascii.CreateFileStream ("tcp-star-server.tr"));
|
||||
p2p.EnablePcapAll ("tcp-star-server");
|
||||
NS_LOG_INFO("Run Simulation.");
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
NS_LOG_INFO("Done.");
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user