【ns3】Debug技巧(GDB、ns3日志系统、ns3抓包)

5. 调试

5.1. GDB调试

启用GDB:gdb --args ./ns3 run

  1. –command-template=“gdb %s” 启动调试,
    1. 在里面可以用help查看一系列命令
    2. help running 输出运行相关的命令
  2. –command-template=“%s --help”
  3. General Arguments:
    • –PrintGlobals: Print the list of globals.
    • –PrintGroups: Print the list of groups.
    • –PrintGroup=[group]: Print all TypeIds of group.
    • –PrintTypeIds: Print all TypeIds.
    • –PrintAttributes=[typeid]: Print all attributes of typeid.
    • –PrintVersion: Print the ns-3 version.
    • –PrintHelp: Print this help message.

直接在终端使用下面命令:(先run一遍才能用这些命令好像)
./ns3 run scratch/wificsma_quic.cc --command-template="gdb %s"

常用 GDB 命令

  1. break 在指定函数设置断点(如 break main)
  2. break(b) <file:line/> 在指定文件的某一行设置断点
  3. b 文件名:行号
  4. b 函数名:行号
  5. b 函数名
  6. i loc 命令:当程序因观察点触发而暂停时,可以通过此命令查看局部变量的值
  7. info locals 显示所有局部变量及其值
  8. info args 显示函数参数及其值
  9. 或者断点后直接print变量即可;
  10. run® 启动程序
  11. finish 运行到函数结束
  12. next (n) 单步执行(不进入函数)
  13. step (s) 单步执行(进入函数)
  14. continue © 继续运行直到下一个断点
  15. backtrace (bt) 查看调用堆栈
  16. print§ 打印变量值
  17. info(ii) breakpoints 查看所有断点
  18. watch 监控变量变化
  19. quit 退出 GDB

.调试 ns-3 特有场景

  1. 调试事件调度

  2. 通过断点观察事件执行:break Simulator::Schedule

  3. 跟踪数据包生命周期

  4. 发送函数设置断点:break UdpSocketImpl::Send

  5. 条件断点

  6. 仅在特定条件下触发断点(例如某个节点发送数据包)

  7. break UdpSocketImpl::Send if node->GetId() == 1

  8. 监控变量或内存地址的变化:watch m_count

  9. 调试崩溃问题

5.2. 日志系统

ns-3提供了一种可选的、多等级的消息记录功能—Logging系统。Logging功能可以被完全禁用,可以逐个组件启用,也可以全局启用。Logging系统还可以选择所记录消息的详细程度(verbosity level)或严重程度(severity level),以及为消息添加不同的前缀(prefix)。因此,Logging系统提供了一种非常灵活且功能强大,但使用相对简单的消息记录功能

5.3. 日志组件

一个日志组件就是指一个C++源代码文件。通过日志组件,Logging系统就可以把信息输出控制精确到某一个C++文件

C++文件添加为日志组件:只要在C++文件开头在ns3名字空间范围内使用NS_LOG_COMPONENT_DEFINE宏注册即可。日志组件名必须是全局唯一的(通常基于文件名或文件中定义的类的名)
image.png
如果需要使用某个日志,就在文件里引用即可,如下:
image.png

5.4. 日志前缀

  1. **LOG_PREFIX_TIME
    **功能:在日志前添加时间戳。
    输出示例:
    +0.003s This is a log message
    使用场景:分析仿真事件的时间顺序。
  2. LOG_PREFIX_FUNC
    功能:在日志前添加函数名。
    输出示例:
    void MyClass::MyMethod() This is a log message
    使用场景:快速定位日志输出的代码位置。
  3. LOG_PREFIX_NODE
    功能:在日志前添加节点 ID。
    输出示例:
    Node 1: This is a log message
    使用场景:在多节点仿真中区分不同节点的日志。
  4. LOG_PREFIX_LEVEL
    功能:在日志前添加日志级别。
    输出示例:
    [INFO] This is a log message
    使用场景:快速识别日志的严重程度。
  5. LOG_PREFIX_ALL
    功能:在日志前添加所有可用的前缀(时间、函数、节点、级别)。
    输出示例:
    +0.003s Node 1 [INFO] void MyClass::MyMethod() This is a log message
    使用场景:需要完整的上下文信息时使用。
  6. LOG_PREFIX_CONTEXT
    功能:在日志前添加上下文信息(如模块名称)。
    输出示例:
    [QuicEchoClientApplication] This is a log message
    使用场景:区分不同模块或组件的日志。
  7. LOG_PREFIX_SYSLOG
    功能:将日志格式化为系统日志(syslog)格式。
    输出示例:
    <6> This is a log message
    使用场景:与系统日志工具集成时使用。
  8. LOG_PREFIX_THREAD
    功能:在日志前添加线程 ID。
    输出示例:
    Thread 0x7f8b2b5a1700: This is a log message
    使用场景:在多线程仿真中区分不同线程的日志。
  9. LOG_PREFIX_CALLBACK
    功能:在日志前添加回调信息(如事件类型)。
    输出示例:
    Callback: This is a log message
    使用场景:调试事件回调机制时使用。
  10. LOG_PREFIX_NONE
    功能:禁用所有日志前缀。
    输出示例:
    This is a log message
    使用场景:需要简洁日志输出时使用。
  11. 组合使用前缀
    可以通过按位或操作符(|)组合多个前缀。例如
  12. 默认前缀
    如果没有显式启用前缀,ns-3 默认会启用 LOG_PREFIX_TIME 和 LOG_PREFIX_NODE

eg:
LogComponentEnableAll(LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_PREFIX_FUNC);
输出示例:
+0.003s Node 1 void MyClass::MyMethod() This is a log message
使用场景:根据需要自定义日志输出的上下文信息。

5.5. 日志详细程度(严重程度)选项

通过日志详细程度(或严重程度)选项,Logging系统可以进一步把信息输出控制精确到某一个C++文件的某一层级。

ns-3中,Logging系统通常提供了7个日志详细程度(或严重程度)选项,输出信息的详细程度由低到高(即输出信息由少到多)或者说信息的严重程度由高到低依次为 [1]:

  • LOG_ERROR:记录错误信息(关联的宏为:NS_LOG_ERROR)
  • LOG_WARN:记录警告信息(关联的宏为:NS_LOG_WARN)
  • LOG_DEBUG:记录相对罕见、特别的调试消息(关联的宏为:NS_LOG_DEBUG)
  • LOG_INFO:记录程序进程相关的信息(关联的宏为:NS_LOG_INFO)
  • LOG_FUNCTION:记录描述每个调用函数的消息(关联的宏为:NS_LOG_FUNCTION和NS_LOG_FUNCTION_NOARGS)
  • LOG_LOGIC:记录函数内部逻辑流信息(关联的宏为:NS_LOG_LOGIC)
  • LOG_ALL:记录上述所有信息(无关联的宏)

eg:以first.cc为例,LogComponentEnable()中的第二个参数是日志详细程度(严重程度)选项,如下图所示

需要注意的是,除了LOG_ALL之外,其余6个日志详细程度(或严重程度)选项只能控制其所关联的宏中所输出的信息的输出。例如,LOG_INFO等级只能控制指定日志组件中所有NS_LOG_INFO宏所输出的信息的输出

如果我们希望同时输出NS_LOG_INFO宏和NS_LOG_DEBUG宏中的信息,那么我们可以这样:

eg:
在终端中通过NS_LOG环境变量控制日志输出:

5.7. 抓包调试

生成 .pcap 文件分析网络行为

  1. PointToPointHelper::EnablePcapAll(“udp-echo”);
   // 添加IP层抓包 包括传输层的包
    internet.EnablePcapIpv4All("ip-trace");
    // 添加设备级别的抓包  链路层
    for (uint32_t i = 0; i < devices.GetN(); ++i) {
        std::string filename = "device-" + std::to_string(i);
        wifiPhy.EnablePcap(filename, devices.Get(i));
    }

此时会在目录下生成.pcap文件,然后导入到wireshark中查看即可:
image.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值