NS3中TypeId设置属性以及追踪方法

TypeId介绍

每一个模块类都有TypeId属性
TypeId将每一个模块类的属性和跟踪源集合在一起,非常方便的进行属性值的设定和跟踪源的回调函数的设定

TypeId
WifiPhy::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::WifiPhy")
    .SetParent<Object> ()
    .SetGroupName ("Wifi")
    .AddAttribute ("Frequency",
                   "The operating center frequency (MHz)",
                   UintegerValue (0),
                   MakeUintegerAccessor (&WifiPhy::GetFrequency,
                                         &WifiPhy::SetFrequency),
                   MakeUintegerChecker<uint32_t> ())
    .AddTraceSource ("PhyTxBegin",
                     "Trace source indicating a packet "
                     "has begun transmitting over the channel medium",
                     MakeTraceSourceAccessor (&WifiPhy::m_phyTxBeginTrace),
                     "ns3::Packet::TracedCallback")
  ;
  return tid;
}

方法说明

SetParent:设置WifiPhy类的父类
SetGroupName :设置WifiPhy类所在模块组
AddAttribute :添加属性
AddTraceSource :添加跟踪源
AddConstructor:添加构造器

用法

//设置属性
m_wifiphy->SetAttribute ("Frequency", TimeValue (m_frequency));
//设置属性,返回bool值说明是否成功
m_wifiphy->SetAttributeFailSafe("Frequency", DoubleValue (m_lookAroundRate));
//设置跟踪源回调
m_wifiphy->TraceConnectWithoutContext ("PhyTxBegin",
                                          MakeCallback (&TcpSocketBase::UpdateCwnd, this));
//解除跟踪源回调
m_wifiphy->TraceDisconnectWithoutContext ("PhyTxBegin", 
                                          MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));

NS3中很少使用上面的方式设置属性值的,最常用的是通过Config类完成:

Config::Set ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/ChannelNumber", UintegerValue(40));

*是通配符
NodeList是一个类,每创建一个Node对象,都会保存NodeList中
DeviceList也是一个类,每创建一个NetDevice对象都会保存在DeviceList
*表示全部,0 1 2 3这些数字表示第几个Node对象或者NetDevice对象
ns3::WifiNetDevice表示对象类型
Phy表示ns3::WifiNetDevice这个对象的属性。这个属性在类WifiNetDevice或者其父类里面的TypeId中有定义
ns3::YansWifiPhy]表示Phy这个属性的类型值
ChannelNumber表示ns3::YansWifiPhy这个对象的属性。这个属性可以在类YansWifiPhy或者其父类里面的TypeId里面有定义

样例

NS3的Tracing系统大体分为3个部分:Tracing SourcesTracing Sinks,以及将Tracing SourcesTracing Sinks关联起来的方法,以basic-energy-source.cc为例

#include "basic-energy-source.h"
#include "ns3/log.h"
#include "ns3/assert.h"
#include "ns3/double.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/simulator.h"
using namespace ns3;
class MyObject : public Object
{
public:
  /**
   * Register this type.
   * \return The TypeId.
   */
  static TypeId GetTypeId (void)
  {
    static TypeId tid = TypeId ("ns3::BasicEnergySource")
      .SetParent<EnergySource> ()
      .SetGroupName ("Energy")
      .AddConstructor<BasicEnergySource> ()
	  .AddTraceSource ("RemainingEnergy",
                     "Remaining energy at BasicEnergySource.",
                     MakeTraceSourceAccessor (&BasicEnergySource::m_remainingEnergyJ),
                     "ns3::TracedValueCallback::Double")
   	;
    return tid;
};

TracedValue定义在basici-energy-source.h

TracedValue<double> m_remainingEnergyJ; // remaining energy, in Joules

回调函数=Trace Sink

void
RemainingEnergy (double oldValue, double remainingEnergy)
{
  NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
                 << "s Current remaining energy = " << remainingEnergy << "J");
}

主函数

完整主函数地址

int
main (int argc, char *argv[])
{
  Ptr<BasicEnergySource> basicSourcePtr = DynamicCast<BasicEnergySource> (sources.Get (1));
  basicSourcePtr->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback (&RemainingEnergy));
}

运行结果

99.5094s Current remaining energy = 918.771J

oldValue是改变之前的值,newValue是改变之后的值,如果想打印oldValue可以直接在回调函数处改变输出

实战

追踪某路由协议的控制开销

***-routing-protocol.h定义接收追踪和发出追踪

  /// Traced Callback: transmitted packets.
  TracedCallback<Ptr<const Packet> > m_txTrace; // trace
  /// Traced Callback: received packets.
  TracedCallback<Ptr<const Packet> > m_rxTrace; // trace

***-routing-protocol.cc添加TraceSource

 .AddTraceSource ("Tx", "A new routing protocol packet is created and is sent or retransmitted", // trace
                     MakeTraceSourceAccessor (&RoutingProtocol::m_txTrace),
                     "ns3::Packet::TracedCallback")    
 .AddTraceSource ("Rx", "A new routing protocol packet is received", // trace
                     MakeTraceSourceAccessor (&RoutingProtocol::m_rxTrace),
                     "ns3::Packet::TracedCallback")

TraceCallback是在network/packet.h定义的
这里就是个函数指针嘛,typedef下的话 取的名字叫TracedCallback
所以addTraceSource的时候TraceCallback需要绑定,用到的变量也要绑定,TX/RX是名字 也要绑定,三者绑定在一起;就可以用下面的方式调用了
在这里插入图片描述

 typedef void (* TracedCallback) (Ptr<const Packet> packet);

在自己的仿真场景里追踪

// Tracing
  Config::Connect ("/NodeList/*/$ns3::aodv::RoutingProtocol/Tx", MakeCallback (&AodvPacketTrace));
// Function for capturing overhead statistics
void
AodvPacketTrace (std::string context, Ptr<const Packet> packet)
{
  std::string packetType;
  std::ostringstream description;
  aodv::TypeHeader tHeader;
  Ptr<Packet> p = packet->Copy ();
  p->RemoveHeader (tHeader);
  if (!tHeader.IsValid ())
    {
      NS_LOG_DEBUG ("AODV message " << packet->GetUid () << " with unknown type received: " << tHeader.Get () << ". Drop");
      return; // drop
    }
  switch (tHeader.Get ())
    {
    case aodv::MessageType::AODVTYPE_RREQ:
      {
        packetType = "RREQ";
        aodv::RreqHeader rreqHeader;
        p->RemoveHeader (rreqHeader);
        description << "O:" << rreqHeader.GetOrigin () << " D:" << rreqHeader.GetDst () << " Hop:" << (int)rreqHeader.GetHopCount (); 
        countRreq++;
        break;
      }
    case aodv::MessageType::AODVTYPE_RREP:
      {
        packetType = "RREP";
        aodv::RrepHeader rrepHeader;
        p->RemoveHeader (rrepHeader);
        description << "O:" << rrepHeader.GetOrigin () << " D:" << rrepHeader.GetDst () << " Hop:" << (int)rrepHeader.GetHopCount (); 
        countRrep++;
        break;
      }
    case aodv::MessageType::AODVTYPE_RERR:
      {
        packetType = "RERR";
        countRerr++;
        break;
      }
    case aodv::MessageType::AODVTYPE_RREP_ACK:
      {
        packetType = "RREP_ACK";
        countRrepAck++;
        break;
      }
    }

  countAodv++;
  if (countAodv==1)
  {
    firstAodv = Simulator::Now ();
  }
  lastAodv = Simulator::Now ();
  uint64_t packetSize = packet->GetSize ();
  bytesAodv += packetSize;

  // Write packet data to file
  std::ofstream out (overheadFileName.c_str (), std::ios::app);
  // Time [us], Packet Type, Length [B], Description, Context
  out << lastAodv.GetDouble () / 1000.0 << ","
      << packetType << ","
      << packetSize << ","
      << description.str () << "," // currently Description field is used for RREQ and RREP only
      << context << std::endl;
  out.close ();
  NS_LOG_INFO ("AODV stats: " << lastAodv << ", #" << countAodv << ", bytes: " << bytesAodv);
}

routing-protocol.cc中需要追踪的地方添加m_txTrace(packet->copy());
在这里插入图片描述
看过的几篇文章,写得很清楚
改变值追踪的数据追踪与采集样例
trace回调与first例子的修改

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值