You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NS3中定期统计网络各链路的带宽利用率?

在NS3中获取链路带宽利用率的实现方法

NS3的FlowMonitor确实聚焦于流级统计,要获取单条链路的带宽使用情况,得借助NetDevice层的TraceSource或者协议栈的流量跟踪,下面是几种可行的实现方式:

方法1:利用NetDevice的Tx/Rx Trace统计流量

每个NetDevice都提供了PhyTxBegin、PhyRxEnd等TraceSource,可以通过绑定这些Trace来统计某段时间内链路的收发字节数,进而计算带宽利用率。

实现步骤:

  1. 定义统计类,存储链路的累计流量、时间戳并定期计算利用率:
#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);
  }
};
  1. 在仿真脚本中为目标链路实例化监控类:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 19:22:51