ns-3_ Day 8
对象模型
ns-3对象模型通过3个基类Object、ObjectBase、SimpleRefCount定义了ns-3中绝大部分C++类的行为和关系。
- SimpleRefCount解决针对单个类的动态内存管理问题。这在前面的Ptr已经讲了。
- ObjectBase解决配置属性和trace变量的问题。它定义了对这些变量进行配置的方法和存储数据结构。
- Object解决多个类的动态关联问题,解决的方法是对象聚合(Object Aggregation)。可以让一个Object对象在运行时关联其他对象。
Object:理解对象聚合
对象聚合就是对象关联,这些对象都是Object的派生类。
看一段Object的代码:
class Object : public SimpleRefCount<Object, ObjectBase, ObjectDeleter> { public: //添加聚合对象 void AggregateObject(Ptr<Object> other); //依据类名查找对应对象 template <typename T> inline Ptr<T> GetObject(void) const; private: //聚合数组 struct Aggregates { uint32_t n; //聚合数组元素数量 Object *buffer[1]; //聚合数组起始指针 }; struct Aggregates *m_aggregates; //聚合数组 }
一个Object的派生类持有一个聚合数组m_aggregates,包含其所有的关联对象。这些关联对象彼此地位平等,持有的聚合数组也是完全一样的。
创建Object
- 创建ObjectFactory对象
ObjectFactory pppF;
- 设置对象属性
pppF.SetTypeId(); pppF.Set();
pppF.Create<>();
GetObject
查找关联对象,用法如下:
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>(); Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol>();
上面两行是等价的,只是查找到的指针类型不同(Ipv4是Ipv4L3Protocol的基类)。因此GetObject的另一个用法是指针上下行转换:
Ptr<Ipv4L3Protocol> ipv4L3Prot = ipv4->GetObject<Ipv4L3Protocol>();
查找失败则返回空指针。
元信息
GetObject的技术原理是元信息(meta information)。元信息是关于ObjectBase及其派生类的辅助信息,每一个派生类具有唯一的一组元信息。
所有元信息被存储在一个vector中,类名作为查找关键字,实体类是IidManager。
ObjectBase的派生类会保存其元信息的索引值,保存在TypeId之中。可以把元信息的结构理解成:
查找的实现思路:
- 获取模板中类的TypeId tid;
- 把tid和聚合数组中的每个元素的TypeId进行比较;
- 把tid和聚合数组中的每个元素的基类TypeId进行比较;
举例:GetObject[ipv6L3Protocol, ipv4L3Protocol]
的搜索路径
ObjectBase:实现配置功能
前面已经看到,属性和trace信息保存在元信息之中。实际上属性系统和trace系统就是元信息以及对应的函数。
属性
属性值类型不可以互转,但都可以转换成StringValue。
- ConfigStore可以用于保存脚本中用过的属性集为一个文件,并在下一次模拟中加载。
- 全局属性不属于任何一个类,都是一些影响模拟器行为或者性能的变量。ns-3支持的全局属性有限。
举例:PointToPointNetDevice的传输速率属性
class PointToPointNetDevice : public NetDevice { private: DataRate m_bps; }; TypeId PointToPointDevice::GetTypeId(void) { static TypeId tid = TypeId("ns3::PointToPointNetDevice") .AddAttribute( "DataRate", //属性名 DataRateValue(DataRate("32768b/s")), //默认值 MakeDataRateAccessor(&PointToPointNetDevice::m_bps));//创建了一个属性访问函数并将函数指针存放在属性辅助信息中 return tid; }
trace
trace变量本质上是一个函数指针的成员变量,trace系统的作用就是把函数指针变成一个可以配置的变量。
举例:一个PointToPointDevice的分组接收trace
class PointToPointNetDevice : public NetDevice { private: TracedCallback<Ptr<const Packet>> m_macRxTrace; }; TypeId PointToPointDevice::GetTypeId(void) { static TypeId tid = TypeId("ns3::PointToPointNetDevice") .AddTraceSource( "MacRx", //trace名 MakeTraceSourceAccessor(&PointToPointNetDevice::m_macRxTrace), //创建了一个trace访问函数并将其函数指针存放在trace辅助信息中 "ns3::Packet::TracedCallback"); //指定回调函数的签名是Packet类的TracedCallback函数指针 return tid; } void PointToPointNetDevice::Receive(Ptr<Packet> packet) { m_macRxTrace(originalPacket); //使用回调的方法 }
当m_macRxTrace作为一个TracedCallback被声明后,它就成为了一个可以在脚本中配置的trace变量。
和属性辅助信息一样,trace变量的辅助信息也在初始化TypeId的时候指定。
ns-3的trace变量的签名格式主要有两种:
- TracedCallback类型 主要用于和分组相关的行为事件(如分组收发、丢失)
- 返回值为void(因为这些trace变量只用作提供数据,不需要返回),形参最多8个
- 签名格式命名习惯为
ns3::类名或命名空间::typedef名
,举例:- Ipv4L3Protocol类的分组发送trace变量Tx的签名格式:
ns3::Ipv4L3Protocol::TxRxTracedCallback
; - 使用最广泛的签名格式是
ns3::Packet::TracedCallback
- Ipv4L3Protocol类的分组发送trace变量Tx的签名格式:
- trace变量对应的函数指针都是TracedCallback类的对象
- TracedValue类型 主要用于一个数值变量的大小变化事件(如TCP拥塞窗口大小变化、一个队列中分组数目变化)
- 其内部就是只有两个形参的TracedValueCallback对象
- 只需要记录旧数值和新数值两个变量即可
posted on 2023-01-10 09:49 LeewayTang 阅读(115) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)