Emane模型调研

Emane开发文档

Emane维基

Emane仿真架构:

Emane仿真流程

​ 当仿真器实例化模型插件(即读取模型配置文件platform.xml),emane仿真器会将每个无线模型插件与仿真器物理层的专用实例一起封装在网络仿真模块 组成网络仿真中的最小单元Network Emulation Module(NEM)。

​ 一个容器可以有多个NEM,一个NEM映射一个无线网卡(通过向 /dev/net/tun 写数据实现)。而网络接口部署在 platform (容器节点 或执行仿真的主机)上,底层原始数据在平台的网络接口 通过组播通道传输仿真数据。即所有 OTA(over the air multicast channel) 消息封装后的多播数据包都由使用同一 OTA 多播通道的每个模拟器实例platform进行处理。

​ 这些无线仿真节点的物理层数据通过emane进程转发到主、辅控制网络的多播通道互连(两种网络都使用多播传输数据包)。

​ 这就是仿真器物理层在异构无线电模型中考虑信号传播、天线效应和干扰源的方式,都在emane进程中处理。

​ Emane计算信噪比后通过设定规则的pcr曲线计算物理层是否可接收数据,路径损耗,gps位置 天线角度 通信损耗 等可以通过 emane事件触发。

transport layer

transport layer 是应用程序/模拟传输边界的程序,负责在模拟器实例和一个或多个应用程序空间进程之间传递消息的模拟组件。

传输程序为模拟器和应用程序空间消息提供入口点和出口点。

传输插件既可以作为模拟器进程的一部分在内部实例化,也可以作为其他应用程序的一部分在外部实例化。Transport Daemon EMANE应用程序处理配置XML,以确定要实例化的外部传输插件的类型、应该如何配置插件以及应用什么通用的应用程序级别设置。

Emane 包含两种传输模式:

  • Raw Transport

    应用程序/模拟边界不限于由模拟器内部加载或由Transport Daemon外部加载的插件。在将软件定义无线电(SDR)波形连接到EMANE时,应开发自定义传输接口,并将其嵌入到Modem硬件抽象层(MHAL)的SDR中。SRSlte-emane模型就是如此,将sdr替换为emane物理层嵌入srslte中通信,上行mac层架构不变。

  • Virtual Transport

    ​ 默认使用的就是虚拟传输通道,容器节点中,虚拟传输使用 TUN/TAP 接口(一一映射到NEM)创建虚拟接口 (vif) 作为应用程序/仿真边界入口/出口点。在下行方向(发送端处理过程),内核将路由到 vif 的以太网帧被打包成emane消息转发至控制网接口即各个NEM实际相接网络接口中,发送到相应的 NEM 进行处理。在上行方向(接受端处理过程),直接接收到不需要转发至虚拟vif 处理,NEM 消息被解包并作为以太网帧写入 TUN/TAP 接口。

Emane NEM layer 处理流程

上层组件结构:

组件大致功能
TimerServiceUseremane定时器后台服务
EventServiceUseremane事件后台服务
Component用于配置和控制所有组件的通用接口
UpstreamTransportUpstreamTransport允许处理上游数据和控制消息。上游数据包和控制消息被放置在NEMQueuedLayer函数队列中进行处理。
DownstreamTransportDownstreamTransport允许处理下游数据和控制消息
PlatformServiceUser仿真平台服务的接口,提供对nem layer服务的访问
Buildable使用应用程序范围构建唯一的Id标记对象的接口。构建器操作可构建对象来注册它们与其他应用程序对象的关联,并执行组合规则
RunningStateMutableRunningStateMutable接口用于允许在运行状态下对配置进行更改。配置被放置在NEMQueuedLayer函数队列中进行处理。
NEMQueuedLayerNEM数据层堆栈,每层之间有一个处理队列,以解耦到节点内部处理
NEMStatefulLayer组件状态强制转换规则的层堆栈。有状态层并不是一个功能完整的层,它封装了只允许正确的转换和状态操作的NEM层。
PHYLayerImplementor用于创建PHY层插件实现的接口
MACLayerImplementor用于创建MAC层插件实现的接口
ShimLayerImplementor用于创建Shim层插件实现的接口
Transport传输边界程序的基类

使用emane版本为1.2.5 系统Ubuntu 18.04

# emane 编译 安装教程
cd emane
sudo apt install -y gcc g++ automake libtool libxml2-dev libprotobuf-dev libpcap-dev libpcre3-dev uuid-dev pkg-config protobuf-compiler git python3-protobuf python3-setuptools

./autogen.sh
PYTHON=python3 ./configure --prefix=/usr
make check 		 # 检测编译
make -j$(nproc)
sudo make install # 复制动态库 emane二进制程序 头文件 pcr模型xml 解析器 到对应系统目录

# 安装core内的python工具绑定
cd ../core/daemon
poetry run pip install ~/emane/src/python

注意: emane使用动态库链接各模块 写好了对应模块的代码 不必每次都在总目录下编译生成,只要在对应目录 make 并 install 即可。

模型介绍及架构:

各无线模型均采用 通用物理层,无线模型主要设计其mac层。

PHY layer

物理层大部分细节由 libemane include文件夹 内的otamanger commonphyheader downstreampacket 等等组件构成,其处理流程类似mac layer 处理上下游数据。可以构建自定义的物理层组件 phylayer 或者改造添加其细节。官方的建议是为了兼容性是不要自己构建新的phyapi 直接使用原生的进行改造或使用。 其间的物理层 OTA流量 (原始数据包) 是采用 src/libemane/otaheader.proto 定义 proto 序列化反序列化传输数据。

无线电模型可以使用 Spectrum Service 频谱服务访问仿真器物理层跟踪的每个频率的噪声信息。

  • 传播模型:2-Ray、Freespace、事件触发预计算

  • 接收功率计算

  • 天线增益的支持

  • 噪声处理

  • 频率分集

  • 协作传输

​ 物理层接口主要使用这些 控制消息

ControlMessage功能
FrequencyControlMessage在 transport layer 中上下游消息 (UpstreamPacket DownstreamPacket) 的频率
TransmitterControlMessage发送 下游 DownstreamPacket 控制消息
ReceivePropertiesControlMessage接收 上游 UpstreamPacket 控制消息
TimeStampControlMessage指定该无线信息开始传输时刻的传输时间戳
AntennaProfileControlMessage配置接收下游数据时的天线参数

Radio Models (Mac layer)

绝大多模型库生成动态库由主程序加载的形式链接调用。

  1. RF Pipe

  2. IEEE802.11abg

  3. TDMA

  4. LTE/srsRAN-emane (嵌入型 emane 与srsRAN配套使用,与此处介绍的其他模型不同)

Utility Models

使用shim类派生完成下列功能:

Comm Effect : Comm Effect 不是无线电模型。它使用模拟器接口将仿真效果应用于流量,而无需相关无线网络的特定概念 (构建虚拟shim layer实现,猜测是开发人员测试成功后将这些具体实现添加到无线模型中)

​ Comm Effect 提供了定义以下无线网络传播的损失效果模拟:

  • Loss: 使用均匀损失分布模型将被丢弃的包的百分比。
  • Latency: 数据包通过网络的延迟由一个固定的和可变的部分组成。固定的延迟量是通过一个延迟配置参数定义的,可变的量是通过一个抖动配置参数定义的。抖动是使用一个关于+/-抖动的均匀随机分布模型随机确定的。然后将随机生成的抖动值添加到固定的延迟中,以确定总延迟。
  • Duplicates: 在接收端复制接收的数据包的百分比。
  • Unicast Bitrate: 发送到NEM或以混杂模式处理的数据包的比特率。
  • Broadcast Bitrate: 发送到NEM广播地址的报文的比特率。

除此之外还有pathloss 天线 TDMA特有的时隙等影响无线传播的事件。这些统称为emane事件 交由定时器 查询检索 触发。

PHYAPITest

  • 构建虚拟mac ShimLayer 来进行 phy api 的测试

TimingAnalysis

​ 定时器分析模块,计算shimlayer接收数据到发送给另一个shimlayer的延迟时间和定时采集事件信息。

  • ShimHeaderMessage

    包含模型的事件 及定时器事件的触发消息的序列化 反序列化

  • ShimLayer

无线模型MAC开发流程:

创建 Radio Model 插件所需的实现的API清单。

  1. 派生创建自定义的 mac实现 MACLayerImplementor

    MACLayerImplementor 父类的 公共成员函数

    void 	setBuildId (BuildId bid)
    NEMId 	getNEMId () const
    BuildId getBuildId () const
    
    virtual void 	setUpstreamTransport (UpstreamTransport *pUpstreamTransport)
    virtual void 	setDownstreamTransport (DownstreamTransport *pDownstreamTransport)
    
    virtual 		~MACLayerImplementor ()
    virtual void 	initialize (Registrar &registrar)=0
    virtual void 	configure (const ConfigurationUpdate &update)=0
    virtual void 	start ()=0
    virtual void 	postStart ()
    virtual void 	stop ()=0
    virtual void 	destroy ()=0 throw ()
    
    void 	sendDownstreamControl (const ControlMessages &msgs)
    void 	sendUpstreamControl (const ControlMessages &msgs)
    void 	sendUpstreamPacket (UpstreamPacket &pkt, const ControlMessages &msgs=empty)
    void 	sendDownstreamPacket (const CommonMACHeader &hdr, DownstreamPacket &pkt, const ControlMessages &msgs=DownstreamTransport::empty)    
    virtual void 	processUpstreamPacket (const CommonMACHeader &hdr, UpstreamPacket &pkt, const ControlMessages &msgs=UpstreamTransport::empty)=0
    virtual void 	processUpstreamControl (const ControlMessages &msgs)=0
    virtual void 	processDownstreamPacket (DownstreamPacket &pkt, const ControlMessages &msgs=empty)=0
    virtual void 	processDownstreamControl (const ControlMessages &msgs)=0
    
    virtual void 	processEvent (const EventId &eventId, const Serialization &serialization)
    virtual void 	processTimedEvent (TimerEventId eventId, const TimePoint &expireTime, const TimePoint &scheduleTime, const TimePoint &fireTime, const void *arg)
    virtual void 	processConfiguration (const ConfigurationUpdate &update)
    
  2. 重写(覆盖)所有组件状态的转换方法:

    • initialize
      • 注册插件配置项和一个可选的配置验证器
      • 注册无线模型的统计信息和统计表
      • 注册无线模型需要的emane事件
    • configure
      • 处理所有已加载的配置
    • start
      • 仿真从该方法开始,启动无线模型仿真内定时器等。
    • postStart
      • NEM层堆栈中的所有组件现在都处于“启动”状态。跟踪或配置相邻层的组件。
    • stop
      • 与 start 相反,执行停止行为
    • destroy
      • 与 initialize 相反,执行清理销毁操作。
  3. 重写(覆盖)所有处理数据包和控制消息的方法:

  4. 如果你的插件要处理Emane事件,也需要重写覆盖下面函数:

  5. 如果你的插件要调度Emane定时器事件,也需要重写覆盖下面函数:

  6. 如果你的插件允许运行状态下的进行配置修改,需要重写该api:

  7. 使用 DECLARE_MAC_LAYER 宏函数 来完成mac模型 Implementor 的声明与实例化

可以看看 基础模型 bypass 的搭建流程

phylayer

bypass 是 类似 hello world 的无线模型来介绍 emane无线模型 的开发流程 其具有处理步骤为空的 未对无线数据包做处理的 phy mac 库

Emane 新模型开发示例:

Emane源码修改:

  1. 仿照 rfpipe 创建一个 新的自定义模型:

    将要发送的 downstream 封装至使用通用物理层的原始数据包 downstreamqueue 需要自己设计发送形式来触发 sendDownstreamPacket,而upstream的数据 直接 sendUpstreamPacket 不需要设计数据队列。

    需要完成如下5个类:

    1. Downstreamqueue 下游数据的定义

    2. DownstreamQueueEntry 队列数据入队定义

    3. MACHeaderMessage Mac head数据结构及成员定义,mac数据对象大部分都是使用 Google Protocol Buffers 来进行序列化 如下是 rfpipemacheader.proto,对应上下游数据有两类构造函数。

      数据类型虽然为string 但是内部是二进制的 非打印数据流 Protobuf简易教程

      syntax = "proto2";
      
      package EMANEMessage;
      
      option optimize_for = SPEED;
      
      message RFPipeMACHeader
      {
        required uint64 dataRate = 1;
      }
      
    4. Maclayer 进行实例化的对象

    5. pcrmanager: 基础射频模型 对物理层 PCR 的管理, 其中xml数据由DTD (document type definition) 定义结构。简易教程: DTD的编写

      platform.xml 定义了全局的emane 组播地址 事件 及nem映射设备等,具体配置依赖nem.xml。 一般情况下,nem.xml定义了 transport phy mac 层的配置。platform 的 dtd 如下所示

      <?xml encoding="UTF-8"?>
      
      <!ELEMENT platform ((param|paramlist)*, nem+)>
      <!ATTLIST platform 
                name CDATA #IMPLIED>
      
      <!ENTITY % nemcontents SYSTEM "nemcontents.dtd">
      %nemcontents;
      
      <!ELEMENT nem (%alllayers;)>
      <!ATTLIST nem 
                name CDATA #IMPLIED
                id CDATA #REQUIRED
                definition NMTOKEN #REQUIRED
                transport (external | internal) "internal">
      
      <!ENTITY % param SYSTEM "param.dtd">
      %param;
      
      <!ELEMENT shim (param|paramlist)*>
      <!ATTLIST shim 
                definition NMTOKEN #REQUIRED>
      
      <!ELEMENT mac (param|paramlist)*>
      <!ATTLIST mac 
                definition NMTOKEN #REQUIRED>
      
      <!ELEMENT phy (param|paramlist)*>
      <!ATTLIST phy 
                definition NMTOKEN #IMPLIED>
      
      <!ELEMENT transport (param|paramlist)*>
      <!ATTLIST transport 
                definition NMTOKEN #REQUIRED
                group CDATA #IMPLIED
      

      整个 基础的rfpipe模型构建的必要文件大致如下所示:

      
      lk233@vm-5gc:~/emane/src/models/mac/myrfpipe$ tree
      .
      ├── downstreamqueue.cc	# 定义了 downstream queue 的数据格式 及 插入弹出数据队列类
      ├── downstreamqueue.h	# 
      ├── maclayer.cc			# 整个无线模型的实例化 启动 销毁的流程定义
      ├── maclayer.h			# mac layer 类的 api 必须 重写
      ├── Makefile.am			# 编译配置文件 项目使用 autoconfig 完成编译
      ├── pcrmanager.cc		# pcr配置文件的读取与设定
      ├── pcrmanager.h		#
      ├── rfpipemacheadermessage.cc	# 调用下面 probuf 的api进行序列化 反序列化  这里只有一个参数 daterate
      ├── rfpipemacheadermessage.h	# 
      ├── rfpipemacheader.proto		# 定义mac head消息数据结构。使用protoc *.proto --cpp_out=./ 生成 对应数据序列化、反序列化的pb.cc pb.h
      ├── myrfpipemac.xml.in	# mac库参数 以及 在源码dtd/中加入 DOCTYPE 解析   (注意 library 最好与 pzLayerName 小写名统一)
      ├── myrfpipenem.xml.in	# nem配置的参数示例 以及 在源码dtd/中加入 DOCTYPE 解析  (此处nem中的mac 依赖rfpipemac rfpipemac依赖pcr)
      └── myrfpipepcr.xml.in	# 默认pcr曲线配置示例 以及 在源码dtd/中加入 DOCTYPE 解析
      

      Mac layer 使用 Virtual Transport 的数据大致处理过程

      此处的Rfpipe模型就是通过定时器控制队列入队出队 来限制无线数据dataRate

  2. automake 和 autoconf 使用简明教程,下面介绍 myrfpipe 的 autoconfig 配置实例 (以下相对目录皆是emane源码路径的相对目录)

    • 添加新模型一般需要修改 autoconfig 的 configure.ac, 在该文件的 AC_OUTPUT 添加如下路径 来在构建过程指定输出文件

      AC_OUTPUT(
       ***
       src/models/mac/rfpipe/Makefile
       src/models/mac/myrfpipe/Makefile
       ***
      )
      
    • 编写并修改 makefile.am Makefile.am 中指明当前目录如何编译。

      修改 Makefile.am 安装 卸载的hook (可选)

      src/models/mac/Makefile.am 添加 myrfpipe 子目录

      在 /dtd/ 中定义dtd的数据格式,并在 /dtd/Makefile.am 添加 myrfpipepcr.dtd

      在 /scripts/emanegenmanifests.sh 中添加 需要生成的库名 myrfpipemaclayer。其原理是调用 emaneinfo -m 导出插件或模型的类内注册 配置和统计信息 的参数。生成的xml给core解析就可以得到模型的所有参数。

    • 编写 src/models/mac/myrfpipe/Makefile.am

      lib_LTLIBRARIES = libmyrfpipemaclayer.la
      
      # cpp 编译的选项 -I指定头文件目录等等
      libmyrfpipemaclayer_la_CPPFLAGS=   \
       -I@top_srcdir@/include          \
       $(AM_CPPFLAGS)                  \
       $(libemane_CFLAGS)
      
      libmyrfpipemaclayer_la_LIBADD=                  \
       $(libuuid_LIBS)                              \
       $(libxml2_LIBS)                              \
       $(protobuf_LIBS)                             \
       @top_srcdir@/src/libemane/.libs/libemane.la
      
      libmyrfpipemaclayer_la_LDFLAGS=    \
       $(AM_LDFLAGS)                   \
       -avoid-version
      
      # 源码监听文件
      libmyrfpipemaclayer_la_SOURCES =   \
       maclayer.cc                     \
       downstreamqueue.cc              \
       pcrmanager.cc                   \
       rfpipemacheadermessage.cc       \
       maclayer.h                      \
       downstreamqueue.h               \
       pcrmanager.h                    \
       rfpipemacheadermessage.h
      
      nodist_libmyrfpipemaclayer_la_SOURCES =   \
       rfpipemacheader.pb.cc           \
       rfpipemacheader.pb.h
      
      # 定义非动态库编译的其他文件
      EXTRA_DIST=                      \
       myrfpipenem.xml.in                \
       myrfpipemac.xml.in                \
       myrfpipepcr.xml.in                \
       rfpipemacheader.proto           
      
      BUILT_SOURCES =                  \
       myrfpipenem.xml                   \
       myrfpipemac.xml                   \
       myrfpipepcr.xml                   \
       $(nodist_libmyrfpipemaclayer_la_SOURCES)
      
      edit = sed                                \
             -e 's|@datadir[@]|$(pkgdatadir)|g'  
      
      # 定义模板xml的生成 sed 加 文本重定向
      myrfpipenem.xml: myrfpipenem.xml.in
      	$(edit) $< > $@
      
      myrfpipemac.xml: myrfpipemac.xml.in
      	$(edit) $< > $@
      
      myrfpipepcr.xml: myrfpipepcr.xml.in
      	$(edit) $< > $@
      
      # 定义proto 的生成
      rfpipemacheader.pb.cc rfpipemacheader.pb.h: rfpipemacheader.proto
      	protoc -I=. --cpp_out=. $<
      
      clean-local:
      	rm -f $(BUILT_SOURCES)
      
      # 创建 相应模型目录, 并定义 make install 复制的模板xml
      install-exec-hook:	
      	$(mkinstalldirs) $(DESTDIR)$(datadir)/$(PACKAGE)/xml/models/mac/myrfpipe
      	cp -f myrfpipenem.xml $(SCHEMAS) $(DESTDIR)$(datadir)/$(PACKAGE)/xml/models/mac/myrfpipe
      	cp -f myrfpipemac.xml $(SCHEMAS) $(DESTDIR)$(datadir)/$(PACKAGE)/xml/models/mac/myrfpipe
      	cp -f myrfpipepcr.xml $(SCHEMAS) $(DESTDIR)$(datadir)/$(PACKAGE)/xml/models/mac/myrfpipe
      
      uninstall-local:
      	rm -f $(DESTDIR)$(datadir)/$(PACKAGE)/xml/models/mac/myrfpipe/myrfpipenem.xml
      	rm -f $(DESTDIR)$(datadir)/$(PACKAGE)/xml/models/mac/myrfpipe/myrfpipemac.xml
      	rm -f $(DESTDIR)$(datadir)/$(PACKAGE)/xml/models/mac/myrfpipe/myrfpipepcr.xml
      
    • makefile 编写完成后

      ./autogen.sh # 或者  autoreconf --install 生成相应makefile
      PYTHON=python3 ./configure --prefix=/usr
      make check 		 # 检测编译
      make -j$(nproc)  # 按照核心数多线程编译
      sudo make install # 复制动态库 emane二进制程序 头文件 pcr模型xml 解析器 到对应系统目录
      
  3. 关于 emane 的xml配置路径:

    /usr/share/emane$ tree -L 1
    .
    ├── dtd		# Document Type Definition路径 
    ├── manifest # 所有无线模型 mac phy 和其他插件的参数类型定义xml
    ├── schema	# tdma 时隙专用
    └── xml		# 无线模型插件pcr与其他插件的默认xml
    

    core中一般命名mac library 都是mac层上级文件夹与该文件名 (小写),在 makefile.am 的 lib_LTLIBRARIES 定义 (需要加上前缀 lib)

    mac library相对路径DECLARE_MAC_LAYER
    bypassmaclayersrc/models/mac/bypass/maclayer.ccEMANE::Models::Bypass::MACLayer
    ieee80211abgmaclayersrc/models/mac/ieee80211abg/maclayer.ccEMANE::Models::IEEE80211ABG::MACLayer
    rfpipemaclayersrc/models/mac/rfpipe/maclayer.ccEMANE::Models::RFPipe::MACLayer
    tdmaeventschedulerradiomodelsrc/models/mac/tdma/eventscheduler/radiomodel.ccTDMAEventSchedulerRadioModel

    如果 core 安装时使用 虚拟环境 (默认),则emane make install 生成的脚本包默认使用真实环境的python,需要修改或者这些py脚本的解析器路径,否则无法运行。 这里分享一个简易指令:

    py_path=$(cat $(which core-python) | awk 'NR==2 {print $2}')
    py_path='#!'${py_path:1:-1}
    old_path='#!.*'
    files=("emaneevent-fadingselection" "emanecommand-eel" "emaneevent-location" \
    "emaneota-publisher" "emaneevent-antennaprofile" "emaneevent-pathloss" \
    "emanesh" "emaneevent-commeffect" "emaneevent-tdmaschedule"\ 
    "emaneevent-dump ""emanegentransportxml")
    for f in ${files[@]}
    do
    	a=$(which $f)
    	sudo sed -i "1s|$old_path|$py_path|" $a
    done
    

无线模型绑定至core

  1. 设定自定义模型路径

    ​ CORE 通过动态加载用户创建的模型的 python 来支持自定义开发的 EMANE 模型。自定义 EMANE 模型应放置在 CORE 配置文件 /etc/core/core.conf 中 emane_models_dir 定义的路径中。例如 emane_models_dir = /home/lk233/core/mytools/myemane_modules 此路径不能以 /emane 结尾。

  2. 设定emane参数 对应core配置界面

    ​ 该路径下应当设置为一个模块,类似如下结构

    ├── CRradio.py
    ├── mybypass.py
    └── __init__.py
    

    ​ 其中 一个调用emane模型的模板 如下所示,具体选项由自定义模型决定:

    """
    自定义 emane model 示例
    """
    from pathlib import Path
    from typing import Dict, Optional, Set, List
    
    from core.config import Configuration
    from core.emane import emanemanifest, emanemodel
    
    
    class ExampleModel(emanemodel.EmaneModel):
        """
        :参数 name: 定义将显示在GUI中的emane模型名称,必须加上前缀 emane_
    	:参数 config_ignore: 忽略 mac phy 参数的列表,添加至此列表的参数将不会序列化至emane配置xml中,这些配置一般是core的界面或其他额外设定
    
        Mac 定义:
        :参数 mac_library: 定义模型将引用的 emane MAC库
        :参数 mac_xml: 定义将被解析以获得默认配置选项的MAC清单xml,将显示在GUI中
        :参数 mac_defaults: 覆盖上述的mac层默认值
        :参数 mac_config: 解析xml并转换生成的core支持的列表
    
        Phy 定义:
        phy一般配置为通用模型,如下所示,下面的参数都是可选的。
        :参数 phy_library: 定义模型将引用的phy库,也可使用自定义phy
        :参数 phy_xml: 定义将被解析以获得配置选项的phy清单xml,将显示在GUI中
        :参数 phy_defaults: 覆盖上述的phy层默认值
        :参数 phy_config: 解析xml并转换生成的core支持的列表
        """
    
        # 一定为emane_前缀
        name: str = "emane_myrfpipe" 
        # 设置mac库模型
        mac_library: str = "myrfpipemaclayer" 
        # 解析获取模型所有配置
        mac_xml: str = "/usr/share/emane/manifest/myrfpipemaclayer.xml" 
        # 覆盖默认值
        mac_defaults: Dict[str, str] = { 
            "pcrcurveuri": "/usr/share/emane/xml/models/mac/myrfpipe/myrfpipepcr.xml"
        }
        mac_config: List[Configuration] = []
    
        # phy 类似mac配置,使用默认phy模型 无需设置library
        phy_library: Optional[str] = None
        phy_xml: str = "/usr/share/emane/manifest/emanephy.xml"
        phy_defaults: Dict[str, str] = {
            "subid": "1",
            "propagationmodel": "2ray",
            "noisemode": "none",
        }
        phy_config: List[Configuration] = []
        config_ignore: Set[str] = set()
    
        @classmethod
        def load(cls, emane_prefix: Path) -> None:
            """
            Called after being loaded within the EmaneManager. Provides configured
            emane_prefix for parsing xml files.
    
            :param emane_prefix: configured emane prefix path
            :return: nothing
            """
            # load mac configuration
            cls.mac_config = emanemanifest.parse(cls.mac_xml, cls.mac_defaults)
            # load phy configuration
            cls.phy_config = emanemanifest.parse(cls.phy_xml, cls.phy_defaults)
    

TDMA 模型 添加注意项

TDMA无线模型 实现了专门的时隙调度器和消息队列管理器模块 来对的TDMA模型开发。

除了引用 include/emane/ 下的基础的计算邻居节点等头文件定义 (类似 #include “emane/models/tdma/basemodel.h”)

包含了 通过解析emane事件用于调度时隙 的事件消息结构定义 (类似"emane/events/slotstructure.h")

还包含了 include/emane/models/tdma/ 的tdma模型独有变种文件 (类似 #include “emane/maclayerimpl.h”)

TDMA 与其他模型不同 并非在 maclayer.cc 中创建mac层 Implementor, 而是通过 MACLayerImplementor SchedulerUser 派生出 tdma 包含时隙通信的。TDMA 模型(radiomodel) 从逻辑上可以分为

  1. 基础tdma无线模型 basemodel

  2. 动态更新时隙模块 eventscheduler 和其处理 时隙切割报文队列管理模块 queuemangager

大致结构如下所示:

查看文件结构

include/emane/events 部分内容
emane/include/emane/events
├── slotinfo.h
├── slotinfo.inl
├── slotstructure.h
├── slotstructure.inl
└── tdmascheduleevent.h
# tdma 时隙事件可以用 emane 安装后生成的 emaneevent-tdmaschedule 来触发新时隙更新调度, 其组件与emane进程通信的数据也是通过 protobuf 序列化生成的。

emane/include/emane/models/tdma
├── radiomodel.h                # TDMA 动态时隙无线模型 的头文件 include basemodel.h
├── basemodel.h                 # maclayerimpl 的变种 包含 TDMA 的 scheduler.h 和 queuemanager.h
├── basicqueuemanager.h         # QueueManager 的变种 包含 queuemanager.h
├── Makefile.am
├── messagecomponent.h         # 消息缓存组件,其内容根据是否启用了聚合 来确定 data 或 control message 是否完整或部分传输 无线模型每次传输将传输一个或多个组件。在时隙和消息数据大小上的消息组件可以是一个或多个包的组合。
├── messagecomponent.inl
├── packetstatuspublisher.h
├── packetstatuspublisheruser.h
├── queuemanager.h              # 包含上述包处理的消息队列变种处理的头文件
├── scheduler.h                 # BaseModel用于通信的调度器接口与调度器(Scheduler)模块 包含 scheduleruser.h
├── scheduleruser.h
└── types.h                     # 包含了mac的基础消息类似 还包含的时隙 SlotInfo TxSlotInfo RxSlotInfo 相关的定义

一个tdma示例的实现
emane/src/models/mac/mytdma
├── eventscheduler
│   ├── radiomodel.cc           # 最终打包的动态库实例,生成动态时隙模型
│   ├── eventscheduler.cc       # 时隙调度器实例
│   ├── eventscheduler.h
│   ├── eventtablepublisher.cc  # 通过emane tdma事件 来进行 动态调度的实例
│   ├── eventtablepublisher.h
│   ├── Makefile.am
│   ├── slotter.h               # 时隙成员声明
│   ├── slotter.inl
│   ├── tdmanem.xml.in          # 初始时隙表 模板示例
│   └── tdmaradiomodel.xml.in   # 基础无线参数 模板示例
├── aggregationstatuspublisher.cc   # 消息片段聚合状态 统计实例
├── aggregationstatuspublisher.h
├── basemodel.cc                # 包含了 根据时隙来处理上下游关系的基础无线tdma模型
├── basemodelimpl.cc
├── basemodelimpl.h
├── basemodelmessage.h
├── basemodelmessage.inl
├── basicqueuemanager.cc
├── Makefile.am
├── packetstatuspublisherimpl.cc    # 报文状态发布实例
├── packetstatuspublisherimpl.h
├── pormanager.cc
├── pormanager.h
├── priority.h                  # 下游数据入队列的优先级声明
├── queue.cc
├── queue.h
├── queuestatuspublisher.cc
├── queuestatuspublisher.h
├── receivemanager.cc           # 将分离的时隙的数据重新聚合
├── receivemanager.h
├── slotstatustablepublisher.cc  # 时隙表统计实例
├── slotstatustablepublisher.h
├── tdmabasemodelmessage.proto  # 模型mac层消息的数据结构定义 可以使用 文件夹内make 更新,也可调用 protoc -I=. --cpp_out=. *.proto
├── tdmabasemodelpcr.xml        # 默认无线模型的pcr曲线定义,其解析与 其他模型交由emane组件解析不同,由模型自己做解析处理
├── txslotinfosformatter.cc     # 格式化 发送消息时隙的对象
└── txslotinfosformatter.h

修改 configure.ac AC_OUTPUT 添加这两行 生成 makefile 选项

 src/models/mac/mytdma/Makefile
 src/models/mac/mytdma/eventscheduler/Makefile

其余 makefile.am 的修改类似 之前 myrfpipe 的创建过程

注意

  • xml解析由模型自己模块的 pormanager.cc 实现, 无需添加dtd

  • 为了后面可能需要的定制修改, 将 emane/models/mytdma/ 复制一份放入 header 中, 并修改其中的调用路径

  • emane/src/models/mac/mytdma/eventscheduler/Makefile.am 里的动态库包含的上级目录的 libtdmabase 需要修改 libmytdmabase