#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/flow-monitor-module.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("BenchmarkQueueDiscs");
void
LimitsTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
{
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
}
void
BytesInQueueTrace (Ptr<OutputStreamWrapper> stream, uint32_t oldVal, uint32_t newVal)
{
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << newVal << std::endl;
}
static void
GoodputSampling (std::string fileName, ApplicationContainer app, Ptr<OutputStreamWrapper> stream, float period)
{
Simulator::Schedule (Seconds (period), &GoodputSampling, fileName, app, stream, period);
double goodput;
uint32_t totalPackets = DynamicCast<PacketSink> (app.Get (0))->GetTotalRx ();
goodput = totalPackets * 8 / (Simulator::Now ().GetSeconds () * 1024);
*stream->GetStream () << Simulator::Now ().GetSeconds () << " " << goodput << std::endl;
}
static void PingRtt (std::string context, Time rtt)
{
std::cout << context << "=" << rtt.GetMilliSeconds () << " ms" << std::endl;
}
int main (int argc, char *argv[])
{
std::string bandwidth = "10Mbps";
std::string delay = "5ms";
std::string queueDiscType = "PfifoFast";
uint32_t queueDiscSize = 1000;
uint32_t netdevicesQueueSize = 100;
bool bql = false;
std::string flowsDatarate = "20Mbps";
uint32_t flowsPacketsSize = 1000;
float startTime = 0.1;
float simDuration = 60;
float samplingPeriod = 1;
CommandLine cmd;
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}", 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;
NodeContainer n1, n2, n3;
n1.Create (1);
n2.Create (1);
n3.Create (1);
PointToPointHelper accessLink;
accessLink.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
accessLink.SetChannelAttribute ("Delay", StringValue ("0.1ms"));
PointToPointHelper bottleneckLink;
bottleneckLink.SetDeviceAttribute ("DataRate", StringValue (bandwidth));
bottleneckLink.SetChannelAttribute ("Delay", StringValue (delay));
InternetStackHelper stack;
stack.InstallAll ();
TrafficControlHelper tchPfifoFastAccess;
uint32_t handle = tchPfifoFastAccess.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (1000));
TrafficControlHelper tchBottleneck;
if (queueDiscType.compare ("PfifoFast") == 0)
{
tchBottleneck.SetRootQueueDisc ("ns3::PfifoFastQueueDisc", "Limit", UintegerValue (queueDiscSize));
}
else if (queueDiscType.compare ("ARED") == 0)
{
handle = tchBottleneck.SetRootQueueDisc ("ns3::RedQueueDisc");
Config::SetDefault ("ns3::RedQueueDisc::ARED", BooleanValue (true));
Config::SetDefault ("ns3::RedQueueDisc::Mode", EnumValue (Queue::QUEUE_MODE_PACKETS));
Config::SetDefault ("ns3::RedQueueDisc::QueueLimit", UintegerValue (queueDiscSize));
}
else if (queueDiscType.compare ("CoDel") == 0)
{
handle = tchBottleneck.SetRootQueueDisc ("ns3::CoDelQueueDisc");
Config::SetDefault ("ns3::CoDelQueueDisc::Mode", EnumValue (Queue::QUEUE_MODE_PACKETS));
Config::SetDefault ("ns3::CoDelQueueDisc::MaxPackets", UintegerValue (queueDiscSize));
}
else if (queueDiscType.compare ("FqCoDel") == 0)
{
handle = tchBottleneck.SetRootQueueDisc ("ns3::FqCoDelQueueDisc");
Config::SetDefault ("ns3::FqCoDelQueueDisc::Packet limit", UintegerValue (queueDiscSize));
tchBottleneck.AddPacketFilter (handle, "ns3::FqCoDelIpv4PacketFilter");
tchBottleneck.AddPacketFilter (handle, "ns3::FqCoDelIpv6PacketFilter");
}
else if (queueDiscType.compare ("PIE") == 0)
{
handle = tchBottleneck.SetRootQueueDisc ("ns3::PieQueueDisc");
Config::SetDefault ("ns3::PieQueueDisc::Mode", EnumValue (Queue::QUEUE_MODE_PACKETS));
Config::SetDefault ("ns3::PieQueueDisc::QueueLimit", UintegerValue (queueDiscSize));
}
else
{
NS_ABORT_MSG ("--queueDiscType not valid");
}
if (bql)
{
tchBottleneck.SetQueueLimits ("ns3::DynamicQueueLimits");
}
Config::SetDefault ("ns3::Queue::Mode", StringValue ("QUEUE_MODE_PACKETS"));
Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (100));
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);
Config::SetDefault ("ns3::Queue::MaxPackets", UintegerValue (netdevicesQueueSize));
NetDeviceContainer devicesBottleneckLink = bottleneckLink.Install (n2.Get (0), n3.Get (0));
QueueDiscContainer qdiscs;
qdiscs = tchBottleneck.Install (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 ());
AsciiTraceHelper ascii;
if (bql)
{
queueDiscType = queueDiscType + "-bql";
Ptr<OutputStreamWrapper> streamLimits = ascii.CreateFileStream (queueDiscType + "-limits.txt");
queueLimits.TraceConnectWithoutContext ("Limit",MakeBoundCallback (&LimitsTrace, streamLimits));
}
Ptr<Queue> 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 n3Interface;
n3Interface.Add (interfacesBottleneck.Get (1));
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (flowsPacketsSize));
uint16_t port = 7;
ApplicationContainer uploadApp, downloadApp, sourceApps;
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));
port = 8;
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));
V4PingHelper ping = V4PingHelper (n3Interface.GetAddress (0));
ping.Install (n1);
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));
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<FlowMonitor> flowMonitor;
FlowMonitorHelper flowHelper;
flowMonitor = flowHelper.InstallAll();
Simulator::Stop (Seconds (stopTime));
Simulator::Run ();
flowMonitor->SerializeToXmlFile(queueDiscType + "-flowMonitor.xml", true, true);
Simulator::Destroy ();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通