1 trace 变量
- 作用:追踪记录某些网络行为(如数据分组发送、接受、丢失事件)或网络指标(如TCP cwnd)。
- 本质:C++类的成员变量,变量类型为函数指针。
- 使用:用户先预定义回调函数callback,再通过tracing系统将回调函数与C++对象内部的函数指针(trace变量)相关联。发生特定网络事件时,ns-3调用对应trace变量,从而触发回调函数,模拟数据通过回调函数参数列表形式传递给脚本
2 trace 变量配置
总体原则:不要自己凭空写,先找例子,在其基础上微调。
例子查找方法:
# /home/ns-allinone-3.34_v1/ns-3.34 下
find . -name '*.cc' | xargs grep CongestionWindow
2.1 Tracing Sources
生产者
例如
"/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacTx" // Config Path
-
如何确定Tracing Sources变量?
方法一:看对应类的GetTraceSource()函数里面的.AddTraceSource。
方法二:在Doxygen主页中找对应类的TraceSource内容。 -
如何确定Config Path?
API文档 -> 找到类 -> Config Path
2.2 Tracing Sinks
消费者,一个函数。
看系统中已经写好的例子的回调函数。
2.3 Config::Connect()
- 函数作用:将用户定义的回调函数指针与trace变量关联一起。
- 参数1:trace变量绝对路径
- 参数2:回调函数指针
- 例子:每当PointToPointNetDevice对象发分组时,回调函数就打印分组的发送时间和大小。
void MacTxCallback (std::string context, Ptr<const packet>) //参数列表,context固定,用于存储trace变量命名空间路径。其他通过查看PointToPointNetDevice::GetTypeId()查看
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << " " << packet->GetSize () << " " << context);
}
Config::Connet ("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacTx", MakeCallback (&MacTxCallback));
Config::ConnectWithoutContext ()函数与Config::Connect()函数唯一区别是有无context参数
3 Helper类
- 本质:对Config::ConnectWithoutContext ()函数与Config::Connect()函数的封装。将回调函数与trace变量连接好,用户只需要调用相关函数就可以直接生成pcap或ASCII格式的trace记录。
3.1 NetDeviceHelper
3.2 InternetStackHelper
4 例子
ns3.xx/examples/tutorial/fourth.cc
#include "ns3/object.h"
#include "ns3/uinteger.h"
#include "ns3/traced-value.h"
#include "ns3/trace-source-accessor.h"
#include <iostream>
using namespace ns3;
class MyObject : public Object
{
public:
/**
* Register this type.
* \return The TypeId.
*/
static TypeId GetTypeId (void)
{
static TypeId tid = TypeId ("MyObject")
.SetParent<Object> ()
.SetGroupName ("Tutorial")
.AddConstructor<MyObject> ()
.AddTraceSource ("MyInteger",
"An integer value to trace.",
MakeTraceSourceAccessor (&MyObject::m_myInt),
"ns3::TracedValueCallback::Int32")
;
return tid;
}
MyObject () {}
TracedValue<int32_t> m_myInt;
};
void
IntTrace (int32_t oldValue, int32_t newValue)
{
std::cout << "Traced " << oldValue << " to " << newValue << std::endl;
}
int
main (int argc, char *argv[])
{
Ptr<MyObject> myObject = CreateObject<MyObject> ();
myObject->TraceConnectWithoutContext ("MyInteger", MakeCallback (&IntTrace));
myObject->m_myInt = 1234;
}
fifth.cc
static void
CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
}
static void
RxDrop (Ptr<const Packet> p)
{
NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
}
// main()内
// trace1
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndChange));
// trace2
devices.Get (1)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&RxDrop));
5 数据绘图
以fifth.cc为例:可参考
./waf --run fifth > cwnd.dat 2>&1 # 将程序输出的所有信息,放入文件cwnd.dat中
gnuplot # 进入gnuplot命令行,根据提示设置生成文件的格式
# set terminal png size 640, 480
# set output "cwnd.png"
# plot "cwnd.dat" using 1:2 title "Congestion Window" with linespoints
# exit