上一篇学习了如何新建一个omnet++的工程,这篇来学习下INET框架以及如何使用INET框架来新建一个工程。
INET框架是什么
- INET框架是一个开源模型库,用于OMNeT++仿真环境。它为研究者和学生在使用通信网络时提供协议、代理和其他模型。当设计和验证新协议或探索新的场景时,INET尤其有用。
- INET支持广泛的通信网络类别,包括有线、无线、移动、自组织和传感器网络。它包含了互联网协议栈(TCP、UDP、IPv4、IPv6、OSPF、BGP等)、链路层协议(以太网、PPP、IEEE 802.11、各种传感器MAC协议等)、无线物理层的精细支持、MANET路由协议、区分服务(DiffServ)、MPLS与LDP和RSVP-TE信令、多个应用模型以及许多其他协议和组件。它还提供了对节点移动性、高级可视化、网络仿真等的支持。
- 有几个其他的仿真框架以INET为基础,并将其扩展到特定方向,如车联网、覆盖/对等网络和LTE。
INET框架的安装
- 在新建自己工程的时候,可以在omnet++解压后的那个文件夹里新建一个存储自己工程文件的文件夹
- 然后启动omnet++的时候,会弹出来设置启动路径的窗口,这个时候将启动路径设置为自己新建的文件夹的路径
- 对于新建的工作空间,启动后进入到IDE界面,会自动弹出来安装INET框架的提示,然后直接点击安装就好了,十分方便!
新建一个INET框架的工程
参考资料:新建一个基于INET框架的工程
新建一个OMNeT++的工程
选择File---->OMNeT++ Project
输入自己的工程名称,点击next
选择Empty project with ‘src’ and ‘simulations’ folders,然后点击finish
这样,我们就完成了新建omnet++工程的步骤,到这里是和我们创建普通的omnet++工程是一样的,接下来开始配置INET框架。
配置INET框架
右击刚刚新建的omnet++工程的文件夹,选择Properties
在下面的窗口中,选择Project References,然后给inet4.5打钩
然后选择上面OMNeT++下面的Makemake选项,然后选择下面图中蓝色的选项,再点击Build选项栏里面的Options选项
然后在下面的窗口中选择Compile选项,将下面的三个选项全部勾上。
再点击Link选项,将其中的两项也全部勾选上。
然后点击OK,之后再原来的窗口点击Apply,然后Apply and Close,就完成了该工程和INET框架的连接。
在工程中新建仿真文件进行仿真运行
我给的参考资料中用的是AODV那个仿真程序,我按照资料里给的方法试了一下,发现报错:
具体错误信息如下:
<!> Enum "inet::NodeStatus" not found -- its declaration may be missing from .msg files, or the code was not linked in -- in module (inet::NodeStatus) AODVNetwork.host[0].status (id=31), during network initialization
然后试图解决一下,但是也没搞定,后续还得好好研究一下INET框架的源码,如果有哪个友友解决了这个问题,可以交流一下,感谢!!!
于是,我从官网上找了INET的教程,重新新建了一个仿真程序来进行INET框架的仿真验证,跑成功了!
参考资料:Two hosts communicating wirelessly
目标
首先,我们想要创建一个包含两个主机的网络,其中一台主机通过无线给另一台主机发送UDP数据流,我们的目的是想要物理层和更底层的协议尽可能的简单。
建立的模型如下图所示:
该模型的NED源码如下所示:
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
package learn_2.simulations.test;
// 定义网络模型所在的路径
import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator; // 从inet框架导入IP 网络配置器模块
import inet.node.contract.INetworkNode; // 从inet框架导入网络节点接口模块
import inet.physicallayer.wireless.common.medium.RadioMedium; // 从inet框架中导入无线介质接口模块
import inet.visualizer.contract.IIntegratedVisualizer; //从inet框架中导入集成可视化接口模块network WirelessA // 定义一个WirelessA的网络模型
{// 参数定义parameters: @display("bgb=650,500;bgg=100,1,grey95"); @figure[title](type=label; pos=0,-1; anchor=sw; color=darkblue);@figure[rcvdPkText](type=indicatorText; pos=380,20; anchor=w; font=,18; textFormat="packets received: %g"; initialValue=0);@statistic[packetReceived](source=hostB.app[0].packetReceived; record=figure(count); targetFigure=rcvdPkText);submodules:visualizer: <default(firstAvailableOrEmpty("IntegratedCanvasVisualizer"))> like IIntegratedVisualizer if typename != "" {@display("p=580,125");}configurator: Ipv4NetworkConfigurator {@display("p=580,200");}// 无线介质,使用 RadioMedium 作为无线通信的物理介质radioMedium: RadioMedium {@display("p=580,275");}// 主机 A,使用 WirelessHost 作为无线网络节点hostA: <default("WirelessHost")> like INetworkNode {@display("p=50,325"); // 主机 A 在画布上的位置}// 主机 B,使用 WirelessHost 作为无线网络节点hostB: <default("WirelessHost")> like INetworkNode {@display("p=450,325"); // 主机 B 在画布上的位置}
}
对于该仿真模型的描述
仿真背景
- 该模型包含一个500x650米的运动场,两个主机相隔400米。(这个距离将在后面的步骤中变得相关。)这些数字是通过显示字符串设置的。
- 除了主机之外,网络中存在的模块负责诸如可视化、配置IP层和模拟物理无线电信道等任务。
主机
- 在INET框架中,主机通常是由StandardHost的NED类型来表示,这是一个用于TCP/IP主机的通用模板。它包含了像TCP、UDP和IP这样的协议组件,用于插入应用模型的插槽,以及各种网络接口(NICs)。
- 在INET中,StandardHost有一些变体,例如,WirelessHost基本上是一个为无线场景预配置的StandardHost。
- 在这个NED文件中,主机的类型是参数化的(通过hostType参数和INetworkNode模块接口定义)。这样做是为了在后面的步骤中我们可以用不同的NED类型替换主机。这里的实际NED类型是WirelessHost(在NED文件顶部附近给出),后面的步骤将使用omnetpp.ini覆盖这个设置。
地址分配
- IP地址由一个Ipv4NetworkConfigurator模块分配给主机,该模块在网络中显示为配置器子模块。主机还需要知道彼此的MAC地址才能通信,在这个模型中,这是通过为每个主机使用GlobalArp模块而不是真实的ARP来处理的。
流量模型
- 在这个模型中,主机A生成UDP数据包,由主机B接收。为此,主机A被配置为包含一个UdpBasicApp模块,该模块以平均12毫秒的指数分布随机间隔生成1000字节的UDP消息,因此该应用程序将生成100千字节/秒(800千比特/秒)的UDP流量,不包括协议开销。主机B包含一个UdpSink应用程序,它只丢弃接收到的数据包。
- 该模型还显示了主机B接收的数据包数量,文本由@figure[rcvdPkText]行添加,随后的行会在仿真期间更新该数字。
物理层模型
- INET中的所有无线仿真都需要一个无线介质模块。这个模块代表了通信发生的共享物理介质。它负责信号传播、衰减、干扰和其他物理现象。
- INET能够以不同的细节层次模拟无线物理层,通过不同的无线介质模块实现。在这个步骤中,使用了UnitDiskRadioMedium,这是最简单的模型。它实现了一种单元磁盘无线电的变体,意味着像信号衰减这样的物理现象被忽略了,通信范围简单地以米为单位指定。在范围内的传输总是正确接收,除非发生碰撞。可选模拟碰撞(重叠传输导致接收失败)和干扰范围(一个范围,信号不能正确接收,但仍然与其他信号发生冲突导致它们的接收失败)。
注意:这种物理层的模型与现实几乎没有对应关系。但是,它在仿真中有其用途。它的简单性和可预测性在物理层现实建模不是主要关注点的场景中是一种优势,例如在模拟自组织路由协议时。使用UnitDiskRadioMedium的仿真也比更现实的模型运行得更快,因为计算成本低。
- 在主机中,网络接口卡由NIC模块表示。无线电是无线NIC模块的一部分。有各种无线电模块,必须始终使用与介质模块兼容的一个。在这个步骤中,主机包含的GenericUnitDiskRadio是AckingWirelessInterface中的一部分。
- 在这个模型中,我们如下配置所选的物理层模型(UnitDiskRadioMedium和GenericUnitDiskRadio),通信范围设置为500米,将由于碰撞导致的分组丢失(在这个模型中称为“干扰”)的模拟功能关闭,形成独立的双向通信信道。无线电数据速率设置为1 Mbps,这些值在omnetpp.ini中通过适当的模块的communicationRange、ignoreInterference和bitrate参数进行设置。
MAC层
- 网络接口卡的模块也包含L2层的协议,比如数据链路层的协议。AckingWirelessInterface中的MAC协议是可配置的,默认选择是MultipleAccessMac。MultipleAccessMac实现了一个简单的MAC层,它只提供封装/解封装,但没有真正的介质访问协议。实际上几乎没有介质访问控制:只要前一个数据包完成了传输,数据包就会立即传输。MultipleAccessMac还包含一个可选的带外确认机制,我们这里将其关闭。
网络模型配置
[Config Wireless01]
description = Two hosts communicating wirelessly
network = WirelessA
#record-eventlog = true
sim-time-limit = 20s
record-eventlog = true*.radioMedium.signalAnalogRepresentation = "unitDisk"
*.host*.ipv4.arp.typename = "GlobalArp"*.hostA.numApps = 1
*.hostA.app[0].typename = "UdpBasicApp"
*.hostA.app[0].destAddresses = "hostB"
*.hostA.app[0].destPort = 5000
*.hostA.app[0].messageLength = 1000B
*.hostA.app[0].sendInterval = exponential(12ms)
*.hostA.app[0].packetName = "UDPData"*.hostB.numApps = 1
*.hostB.app[0].typename = "UdpSink"
*.hostB.app[0].localPort = 5000*.host*.wlan[0].typename = "AckingWirelessInterface"
*.host*.wlan[0].mac.useAck = false
*.host*.wlan[0].mac.fullDuplex = false
*.host*.wlan[0].radio.signalAnalogRepresentation = "unitDisk"
*.host*.wlan[0].radio.transmitter.analogModel.communicationRange = 500m
*.host*.wlan[0].radio.receiver.ignoreInterference = true
*.host*.wlan[0].mac.headerLength = 23B*.host*.**.bitrate = 1Mbps
仿真运行
当我们运行仿真时,主机A的UdpBasicApp在随机间隔生成UDP数据包。这些数据包通过UDP和IPv4发送到网络接口进行传输。网络接口将数据包存储在缓冲区队列中,并在可以时立即传输它们。只要网络接口的发送队列中有数据包,数据包就会连续进行传输。
这些事件可以在OMNeT++的Qtenv仿真GUI中进行跟踪。以下图片是从Qtenv捕获的,显示了仿真期间主机A的内部。可以看到一个UDP数据包从udpApp子模块发送下来,穿过中间的协议层,并由wlan接口传输。
下面这个仿真显示了两台主机通过omnet++默认的消息进行通信的动画
当仿真在t=25s时结束时,数据包计数器显示大约发送了2000个数据包。一个包含开销的数据包是1028字节,这意味着传输速率大约是660 kbps。