如何在NS3中定期统计网络各链路的带宽利用率?
在NS3中获取链路带宽利用率的实现方法
NS3的FlowMonitor确实聚焦于流级统计,要获取单条链路的带宽使用情况,得借助NetDevice层的TraceSource或者协议栈的流量跟踪,下面是几种可行的实现方式:
方法1:利用NetDevice的Tx/Rx Trace统计流量
每个NetDevice都提供了PhyTxBegin、PhyRxEnd等TraceSource,可以通过绑定这些Trace来统计某段时间内链路的收发字节数,进而计算带宽利用率。
实现步骤:
- 定义统计类,存储链路的累计流量、时间戳并定期计算利用率:
#include "ns3/core-module.h" #include "ns3/network-module.h" #include "ns3/internet-module.h" class LinkBandwidthMonitor { public: // 初始化:传入链路两端NetDevice、链路总带宽(Mbps) LinkBandwidthMonitor(Ptr<NetDevice> devA, Ptr<NetDevice> devB, double linkBandwidthMbps) : m_devA(devA), m_devB(devB), m_totalBandwidth(linkBandwidthMbps * 1e6 / 8) { // 转换为字节/秒 // 绑定发送、接收Trace m_txTrace = devA->TraceConnectWithoutContext("PhyTxBegin", MakeCallback(&LinkBandwidthMonitor::OnTx, this)); m_rxTrace = devB->TraceConnectWithoutContext("PhyRxEnd", MakeCallback(&LinkBandwidthMonitor::OnRx, this)); // 启动1秒周期的利用率计算 m_calcEvent = Simulator::Schedule(Seconds(1.0), &LinkBandwidthMonitor::CalculateUtilization, this); } ~LinkBandwidthMonitor() { m_txTrace.Disconnect(); m_rxTrace.Disconnect(); m_calcEvent.Cancel(); } private: Ptr<NetDevice> m_devA; Ptr<NetDevice> m_devB; double m_totalBandwidth; // 链路总带宽(字节/秒) uint64_t m_txBytes = 0; uint64_t m_rxBytes = 0; EventId m_calcEvent; TracedCallbackPtr m_txTrace; TracedCallbackPtr m_rxTrace; // 发送回调:累加发送字节数 void OnTx(Ptr<const Packet> pkt) { m_txBytes += pkt->GetSize(); } // 接收回调:累加接收字节数 void OnRx(Ptr<const Packet> pkt) { m_rxBytes += pkt->GetSize(); } // 定期计算并输出带宽利用率 void CalculateUtilization() { const double duration = 1.0; // 统计周期(秒) // 转换为Mbps并计算利用率百分比 double txUtil = (m_txBytes * 8) / (m_totalBandwidth * duration) * 100; double rxUtil = (m_rxBytes * 8) / (m_totalBandwidth * duration) * 100; std::cout << Simulator::Now().GetSeconds() << "s: Link (" << m_devA->GetAddress() << " -> " << m_devB->GetAddress() << ") Tx Utilization: " << txUtil << "%, Rx Utilization: " << rxUtil << "%" << std::endl; // 重置计数器 m_txBytes = 0; m_rxBytes = 0; // 调度下一次计算 m_calcEvent = Simulator::Schedule(Seconds(1.0), &LinkBandwidthMonitor::CalculateUtilization, this); } };
- 在仿真脚本中为目标链路实例化监控类:
int main(int argc, char* argv[]) { // ... 省略节点创建、链路搭建(如PointToPointHelper)等代码 ... // 假设nodeA和nodeB之间有一条10Mbps链路 Ptr<NetDevice> devA = nodeA->GetDevice(0); Ptr<NetDevice> devB = nodeB->GetDevice(0); Ptr<LinkBandwidthMonitor> linkMonitor = CreateObject<LinkBandwidthMonitor>(devA, devB, 10.0); Simulator::Run(); Simulator::Destroy(); return 0; }
方法2:利用Ipv4L3Protocol的Trace统计IP层流量
如果只关注IP层的业务流量(过滤链路层控制帧),可以绑定Ipv4L3Protocol的Tx和Rx Trace:
// 在统计类中添加IP层跟踪逻辑 void BindIpTrace(Ptr<Node> node) { Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>(); ipv4->TraceConnectWithoutContext("Tx", MakeCallback(&LinkBandwidthMonitor::OnIpTx, this)); } void OnIpTx(Ptr<const Packet> pkt, Ipv4Header const& header, uint32_t interface) { m_ipTxBytes += pkt->GetSize(); }
方法3:结合Queue Trace分析拥塞情况
若需要评估链路拥塞状态,可绑定NetDevice队列的Enqueue、Dequeue、Drop Trace,补充流量统计维度:
Ptr<Queue<Packet>> queue = DynamicCast<PointToPointNetDevice>(devA)->GetQueue(); queue->TraceConnectWithoutContext("Drop", MakeCallback(&LinkBandwidthMonitor::OnQueueDrop, this));
注意事项:
- 不同类型NetDevice(如WiFi、PointToPoint)的TraceSource略有差异,需参考对应设备的NS3文档
- 统计周期可根据需求调整(如0.1秒或5秒)
- 批量监控所有链路时,可遍历拓扑中的NetDevice对,自动实例化监控类
内容的提问来源于stack exchange,提问作者LucasB
相关产品推荐
相关产品推荐

