• NS3 日志(Logging)、命令行参数、Tracing系统概述(转载)


    NS-3日志子系统的提供了各种查看仿真结果的渠道:


    一、使用Logging Module


    1 【预备知识】日志级别及其对应的宏

    NS-3 提供了若干个日志级别来满足不同的 Debug 需求,每一级的日志内容都涵盖了低一级的内容。这些级别对应的宏从低到高排列为:

    • LOG_ERROR — Log error messages (associated macro: NS_LOG_ERROR);
    • LOG_WARN — Log warning messages (associated macro: NS_LOG_WARN);
    • LOG_DEBUG — Log relatively rare, ad-hoc debugging messages (associated macro: NS_LOG_DEBUG);
    • LOG_INFO — Log informational messages about program progress (associated macro: NS_LOG_INFO);
    • LOG_FUNCTION — Log a message describing each function called (two associated macros: NS_LOG_FUNCTION, used for member functions, and NS_LOG_FUNCTION_NOARGS, used for static functions);
    • LOG_LOGIC – Log messages describing logical flow within a function (associated macro: NS_LOG_LOGIC);
    • LOG_ALL — Log everything mentioned above (no associated macro).

     

    方式1、通过设置shell环境变量NS_LOG使用日志系统
     

    1.1)首先,定义好一个日志模块:


      可以在脚本中使用宏 NS_LOG_COMPONENT_DEFINE(name) 定义一个日志模块。(注意,为了使用宏 NS_LOG(name, level) 来输出这个模块所定义的内容,这个定义语句必须写在每个脚本文件的开始。宏 NS_LOG 将在方式 2 中进行介绍。)


      也有一些日志模块是内置的,比如上文的名为 “UdpEchoClientApplication” 、“UdpEchoServerApplication” 的模块就是 UdpEcho 应用程序内置的日志模块,只要使用了相应的类,就可以启用相应的日志模块。


    1.2)在 shell 中通过设置环境变量 NS_LOG,来控制仿真输出级别:

    $~/ns-3.2.1 > export NS_LOG = '<日志模块名称> =level_all | prefix_func | prefix_time' 

        

    • level_all 表示启用所有级别(=error | warn | debug | info | function | logic)
    • prefix_func 表示记录输出该消息的函数
    • prefix_time 表示加上时间前缀
    $~/ns-3.2.1 > export NS_LOG = '<日志模块名称1>=level_all : <日志模块名称2>=info'

      

    • 符号 : 表示隔开两个不同的日志模块
    $~/ns-3.2.1 > export NS_LOG = * = level_all
    • 符号 * 作为通配符。上行命令表示启用所有可用模块的所有日志级别。
    • 这一般会形成大量的数据,此时可以使用 shell 的输出重定向保存日志到文件里面:

        

    $~/ns-3.2.1 > ./waf --run scratch/example >& log.out

    方式2、通过在脚本里使用宏NS_LOG调用日志模块
     

    2.0)宏 NS_LOG(level, msg) 用于定义对应 level 的输出内容;为了方便使用,系统预定义了各个级别的 NS_LOGNS_LOG_ERROR等(参见【预备知识】):
      

    #define NS_LOG_ERROR(msg)   NS_LOG(ns3::LOG_ERROR, msg) 


    2.1)如上文,在脚本里使用宏 NS_LOG_COMPONENT_DEFINE(name) 定义一个日志模块;


    2.2)使用宏 LogComponentEnable(name, level) 启用日志(对应地,有宏 LogComponentDisable(name, level) 用于禁用日志);


    2.3)使用【预备知识】里定义的各种级别的宏输出内容,注意程序只会输出低于等于已经启用的 level 的宏内容

     

     NS_LOG_COMPONENT_DEFINE("Example");
     LogComponentEnable("Example", LOG_LEVEL_INFO);   //等价于shell中:export NS_LOG = 'Example=info'
      //运行时显示程序中用语句NS_LOG_INFO(“字符串”)定义的字符串,便于检查错误。
     NS_LOG_WARN("Message:level_warn");
     NS_LOG_INFO("Message:level_info");
     NS_LOG_LOGIC("Message:level_logic");
     //由于我们启用的日志level是INFO,因此编译运行后,程序会输出低于和等于INFO级别的内容,而高于INFO级别的宏内容不会被输出
     //即,Message:level_warn和Message:level_info会被输出,而Message:level_logic不会被输出

    ===============================================================================================================

    二、使用Command Line(命令行)参数


    仿真一般是为了收集各种不同条件下的数据,常常需要改变一些变量。NS-3 提供了Command Line 参数接口,可以在运行时对脚本中的变量进行设置,免去了每次更改变量后要重新编译的麻烦。(相当于在运行前进行变量的 scanf/cin 操作,但因为有默认值,CLI 更灵活一些。)


    1、在脚本中添加语句

    int main (int argc, char *argv[])
    {
      ...
      CommandLine cmd;
      cmd.Parse (argc, argv);  //将命令行输入的参数作为类CommandLine的参数进行分析
      ...
    }

    这样可以在 shell 中使用某些附加参数如 PrintHelp:

    $~/ns-3.2.1 > ./waf --run "scratch/example --PrintHelp"

    这条命令将会列出 example 当前可用的命令参数:

    Entering directory '/home/craigdo/repos/ns-3-dev/build'
    Compilation finished successfully
    --PrintHelp: Print this help message.
    --PrintGroups: Print the list of groups.
    --PrintTypeIds: Print all TypeIds.
    --PrintGroup=[group]: Print all TypeIds of group.
    --PrintAttributes=[typeid]: Print all attributes of typeid.
    --PrintGlobals: Print the list of globals.

      

    从输出中(倒数第二行)我们知道可以打印某些类的属性:

    $~/ns-3.2.1 > ./waf --run "scratch/example --PrintAttributes=ns3::PointToPointNetDevice"

    这条命令将会列出类型为 PointToPointNetDevice 的设备的属性:
       

    --ns3::PointToPointNetDevice::DataRate=[32768bps]:
       The default data rate for point to point links

    知道了属性名称,我们也可以使用命令更改这个属性:

     

    $~/ns-3.2.1 > ./waf --run "scratch/example --ns3::PointToPointNetDevice::DataRate=5Mbps"

    2、使用 CommandLine::AddValue 添加自己的变量,使之成为 CommandLine 可以使用的参数:

    CommandLine cmd;
    cmd.AddValue("nPackets", "Number of packets to echo", nPackets);   //(属性名称,属性说明,变量)
    cmd.Parse(argc, argv);

    这样在 shell 中我们可以在命令中更改这个属性:

    $~/ns-3.2.1 > ./waf --run "scratch/example --nPackets=2"

    ===============================================================================================================

    三、使用Tracing System

    Ns-3 tracing 系统的基本目标:

    • 基本任务,tracing 系统允许用户生成标准 tracing,且自定义哪些对象生成 tracing;
    • 中级用户必须能扩展 tracing 系统来修改输出的生成格式,或者插入新的 tracing sources ,而不用修改仿真器的核心;
    • 高级用户可以修改仿真器的核心来添加 tracing sources 和 tracing  sinks。

     

    Ns-3 tracing 系统建立在独立的 tracing sources 和 tracing sinks 概念之上,有一个统一的机制连接 sources 和 sinks  。Trace sources 是仿真过程中标识事件发生的实体,可以对内部数据进行访问,为感兴趣的潜在数据提供接口。例如,trace sources 可以指示网络设备什么时候接收到数据包,并能对感兴趣的 trace sinks 的数据包内容提供访问。

    Traces sources 本身无用,它们必须连接到其他的代码上才行,这些代码会利用 sinks 提供的信息做些有用的事。Trace sinks 是 traces sources 提供的事件和数据的消费者。例如,一个 trace sink 连接到一个 trace source 上,trace sink 会显示接收到的数据包中感兴趣的部分。只有将 trace sink 与 trace source 连接起来才可以对仿真过程中感兴趣的事件或数据进行处理。

    明确的划分 trace source 和 trace sink目的是允许用户连接新类型的输出到已有的tracing source 上,而不用编辑和重新编译仿真器的核心。因此,如上述例子,用户只需编辑用户脚本就可以在其脚本上定义新的 tracing sink 并把它连接到仿真核心中。

    Tracing 系统的设计遵循两个思想:即 trace source 与 trace sink 相互独立和采用标准的输出格式。

    在trace 输出格式上,ns-3 既考虑了标准化的要求,也考虑了前后延续的要求,提供了两种输出格式:ASCII 格式和 PCAP 格式。ASCII 格式类似于 ns-2 中使用的 .tr 文件格式,采用以行为单位的字符串来表示网络事件;PCAP 格式是一种标准的网络抓包文件格式,可以采用多种工具进行分析,如 tcpdumpwireshark

    1 启用 ASCII Tracing


    Ns-3 提供 helper 功能(封装底层 tracing 系统)来帮助你理解配置数据包 traces 的细节。如果启用该功能,你会看到输出为ASCII 的文件。

    在我们的脚本 scratch/myfirst.cc 中添加一些 ASCII tracing 输出,在调用 Simulator::Run () 之前添加下列代码:

    AsciiTraceHelper ascii;
    pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));

    上述代码的第二行包含两个嵌套的方法调用。第一个是“内部”方法,CreateFileStream() 使用未命名的对象习语在堆栈上创建文件流对象,并把它传递给调用的方法。需要明确的是,你正在创建一个对象,文件名为 “myfirst.tr”,然后你把它传递给 ns3。

    第二个方法是外部调用,EnableAsciiAll() 告诉 helper 你想要在仿真中对所有的点对点设备使能 ASCII tracing,想要 trace sinks 以 ASCII 格式写出数据包运动的信息。

    现在可以 build 脚本并在命令行运行。

    运行时会创建文件 myfirst.tr,默认创建在资源库的 top-level 路径。若想控制 traces 保存的地方,可以使用 Waf 的 --cwd 选项指定。然后以最喜欢的编辑器打开 ASCII trace 文件 myfirst.tr。(在ns-3.22目录下)

    2 解析 ASCII Tracing

    myfirst.tr 文件中有很多信息以密集的形式出现,但是我们首先注意到的事情是文本中出现链路很多独特的行。

    文件中的每一行都与一个trace event 相关。我们在每个点对点网络设备的传输队列上tracing events 。

    注意,Trace 文件每一行开始都有一个单独的字符,其含义为:

      +:设备队列入队操作;

      -:设备队列出对操作;

      d:丢弃数据包;

      r:网络设备接收数据包。

    例如我们可以看到文件中的第一行(为了说明方便,这里分段编号显示),显示了一个入队操作:

    00 +
    01 2
    02 /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
    03 ns3::PppHeader (
    04  Point-to-Point Protocol: IP (0x0021))
    05  ns3::Ipv4Header (
    06   tos 0x0 ttl 64 id 0 offset 0 flags [none]
    07   length: 1052 10.1.1.1 > 10.1.1.2)
    08   ns3::UdpHeader (
    09    length: 1032 49153 > 9)
    10    Payload (size=1024)

    其中编号为 02 的部分显示了发生操作的路径:根 /NodeList 是 NS-3 维护的所有节点列表,因此 /NodeList/0 表示编号为 0 的节点;随后的 /DeviceList/0 表示在该节点上的编号为 0 的 NetDivece(比如网卡);接下来的$ns3::PointToPointNetDevice 指明了该 NetDivece 的类型;最后的 TxQueue/Enqueue 表示在传送队列上发生了入队操作,也就是行开头的 + 所表现的意义。

    3 启用 PCAP Tracing

    Ns-3设备 helpers 也可以用来创建 .pcap 格式的 trace 文件。首字母缩略词 pcap 表示 packet capture(数据包捕获),通常是包含定义 .pcap 文件格式的 API 。可以显示和读取这种格式的最受欢迎的编程工具是 Wireshark。然而,有很多业务 trace 分析器使用该数据包格式。我们鼓励用户利用多种可用的工具来分析 pcap traces。

    (1)使用 tcpdump 来查看 pcap traces。

    启用 pcap tracing的代码:

    pointToPoint.EnablePcapAll  ("myfirst");

    在之前 scratch/myfirst.cc 中添加过的 ASCII tracing 代码的后面插入这行代码。

    注意,我们只是传递字符串 "myfirst" 而不是 “myfirst.pcap” 或其他相似的。这是因为该参数是一个前缀,而不是一个完整的文件名。helper 会为每个 point-to-point 设备创建 trace 文件,文件名格式会使用前缀、节点编号、设备编号和 .pcap 后缀,例如 “myfirst-0-0.pcap”

    在我们运行完脚本后,我们最终会看到文件 “myfirst-0-0.pcap” “myfirst-1-0.pcap”,分别对应节点0-设备0和节点1-设备0。

    一旦添加完这行代码使能 pcap tracing 后,可以按照通常的方式运行脚本:

    $ ./waf --run scratch/myfirst

    结果显示为:

    (2)使用 Wireshark 读取输出

    Wireshark 是一款图形用户界面,可以用来显示 trace 文件。

    例如,myfirst-0-0.pcap 文件用 Wireshark 打开显示如下:

    =======End===================================================================

     

    参考文献:

    [1] http://www.cnblogs.com/lovemo1314/archive/2011/12/21/2295969.html

    [2] https://www.nsnam.org/docs/tutorial/singlehtml/index.html#document-index

  • 相关阅读:
    explain详解与索引最佳实践
    MySQL的配置文件
    MySQL索引数据结构红黑树,Hash,B+树详解
    elasticsearch 进阶
    淘宝服务端高并发分布式架构演进之路
    http请求的header的一个小细节
    一次解决idea maven settings.xml文件不生效
    SpringBoot dev-tools vjtools dozer热启动类加载器不相同问题
    spring boot eclipse 远程调试
    vscode 同步配置
  • 原文地址:https://www.cnblogs.com/alice123/p/5467936.html
Copyright © 2020-2023  润新知