本文共 3448 字,大约阅读时间需要 11 分钟。
(以下都是个人理解!有更好见解可以提出,共同学习,共同进步!)
MACA协议主要详细规则大家可以查看相关书籍。
我直接记录我自己的思路如下:设计节点,构建网络
一、节点模型
1.首先节点的设计,因为我主要想仿真MACA协议(MAC协议),因此简单将节点模型设计为如下图所示:
整个节点模型只有一个MAC层,数据包处理模块和接收机发射机。数据包处理模块和接收机发射机模块具体参数设置到后面调试再说。
虚线表示一个接收机的数据包收集线。
2.节点模型设置
A\interfaces-->node interfaces-->打开如下:
这里值得注意的是:因为需要接受数据包,一定需要设置altitude(天线)的高度,其单位是最初建立环境时的单位。我这里建立的是100KM*100KM的office环境,天线高度的单位因此是KM。
B\各个模块的包的传输速率需要统一,例如接收机和发射机
二、进程模型
然后就主要设计了MAC层的模块。此模块的进程模型如下图所示:
状态转移过程如下:
此协议主要有五个状态:空闲、竞争、等待数据、等待CTS、静默。(一般红色的非强制转移状态才是主要考虑的)
每个状态的执行过程应该是:入口代码、等待中断、中断到达、出口代码、执行转移条件的判断
A.当节点处于空闲状态时。
入口代码,需要初始化一些参数,比如需要将数据到达和CTS到达的事件重新重新初始化为未发生。因为当再一次回到空闲状态时,某些参数可能被改变,再一次从空闲状态转移便会出错。
有三种需要转移的情况:第一是当此节点有包发送并且没有接收到其他帧时,转移到竞争状态,准备发送数据。;第二是接收到发送给我自己的RTS,需要回CTS,然后发送数据;第三是接收到别人的RTS或者CTS,转移到退避状态; (这里是流中断)
出口代码主要执行一些需要在这个状态执行的操作,为状态转移条件做准备。 (展示空闲状态出口代码)
if(ARV_UP) { queue_pk();//如果从src来的包,则将需要发送的包压入队列 }if(ARV_DOWN) { rcv_pk_type();//如果是接收到的流,判断其包类型并执行一些操作 }//上述两个函数都是自己写的NO_FRAME=!(RCV_RTS||RCV_OTHER_RTS||RCV_OTHER_CTS);//判断转移条件
B.当节点处于竞争状态时。
入口代码。需要设置竞争等待时间(超过这个时间,则发生状态转移)
有三种种需要转移的情况。第一种等待时间超过并且信道空闲,那么发送RTS,转移到等待CTS状态。第二种在等待时间内接收到发送给自己的RTS,那么回一个CTS,转移到等待数据状态。第三种在等待时间内接收到其他的RTS和CTS,那么转移到静默状态。(这里等待时间是自中断、接收到其他数据包是流中断)
出口代码主要执行一些需要在这个状态执行的操作,为状态转移条件做准备。
C.当节点处于等待CTS状态时。
入口代码。需要设置等待CTS时间(超过这个时间,还没有等到CTS,则发生转移)
有一种需要转移的情况。当等待时间超过还没有接收到CTS,或者在等待过程中接收到CTS,则转移到空闲状态(这里等待时间是自中断,接收到CTS数据包是流中断。但这里不太可能接收到别人的CTS或者RTS,因为信道被占用)
出口代码。当流中断来临时,取消自中断。
D.当节点处于等待数据状态时。
入口代码。同理设置等待时间,等待时间超过,便抛出一个自中断。
有一种需要转移的情况。当等待时间超过还没有接收到数据时,或者在等待过程中接收到数据,则发生转移到空闲状态。(情况和等待CTS类似)
E.当节点处于静默状态。(这个状态我原本写错了)
(错误思路:当转移到这个状态时,设置静默时间作为一个自中断;当接收到其他RTS或者CTS流中断时,取消这个自中断///但是问题是,我已经收到其他RTS或者CTS才能转移到静默状态,我转移到这个状态可能接收不到其他RTS或者CTS了)
正确思路是:我在上一个状态收到RTS或者CTS流中断,转移到静默状态,并且设置一个静默时间。
此时有两种情况需要转移,第一是静默时间完毕,判断条件,转移到空闲状态;第二是接收到发送给自己的RTS,执行出口代码(发送CTS),判断条件,转移到等待数据状态。
F.每个节点都有默认转移。
当满足不了其他转移条件时,便执行默认转移。如果不写,容易发生意想不到的错误。因此每个状态都有默认转移。
如果不想默认转移项一直执行,在入口代码出限制即可。
如此,我的MAC协议进程模块便写好了。此刻注意一些参数的设置(为你的进程模块添加一些属性)。
比较重要的是如下图所示:
Interfaces--->process interfaces--->begsim intrpt 一般其改为enabled。(我之前忘记改了,就一直错)
begsim intrpt影响init状态的enter代码何时执行,如果是enabled,那么仿真一开始,即仿真0时刻,可以对process进行初始化,process被触发后,即执行init的enter代码。endsim intrpt如果仿真结束时,需要进行一些工作(如变量的收集,内存的释放等),则需要enable endsim intrpt。
三、中断及函数(只提及我用过的)
A.中断
1.流中断(直接给出用法)
#define UP_STREAM 0#define DOWN_STREAM 1//define break for strm#define ARV_UP (op_intrpt_type()==OPC_INTRPT_STRM&&op_intrpt_strm()==UP_STREAM)#define ARV_DOWN (op_intrpt_type()==OPC_INTRPT_STRM&&op_intrpt_strm()==DOWN_STREAM)
2.自中断
#define CONTEND_T (op_intrpt_type()==OPC_INTRPT_SELF&&op_intrpt_code()==CONTEND_TIMEOUT)
op_intrpt_code()返回中断号,即第几个自中断。
B、函数(由于时间问题,只列出来并稍微解释,详细看OPNET自带文档)
op_pk_create()//创建一个包op_ici_attr_set(iciptr,"frame_type",rts_frame);//为ici接口绑定属性
(不写了,用的时候查吧)
四、在调试过程中,产生的一些问题,以及一些解答和解决方案。
1.op_intrpt_code()和op_intrpt_strm()在同时都用于获取流中断的序号时,有什么区别?
2.opnet里面的执行过程为(事件----->触发中断----->进程执行)
比如:一般对于一个节点,收发数据包:触发流中断
等待超时 :触发自中断,进程内部状态转移,执行某些操作
3.ICI
将指定的ICI指针存储在数据包中,在数据包和ICI之间建立关联。(隐含就是一个数据包在不同时候可以绑定不同的ICI)
4.op_subq_pk_remove()
获得指向存储在指定位置的指定子队列中的数据包的指针,并从子队列中删除该数据包。
5.需要产生队列,mac层不能使用进程模块
6.写完后,运行,没有产生包??
写的时候上下包流没有匹配正确
7.产生包,但是很奇怪,只是发生了RTS,然后永远停留在CONTEND状态?
8.ODB调试经验
9.OPNET无线发送时,只有自己能收到自己的包,其他节点都收不到,可能是什么原因?
传输速率修改了
接收地址和目的地址也改了
传输功率也改了
最后发现是接收天线没设置。
10.<<< Program Abort >>>
Packet pointer is NIL. T (0.00873242), EV (207), MOD (top.Office Network.node_2.mac_f), KP (op_pk_ici_set)???不知道为啥,将begin intrpt设置为enable即可,然后就没有报错。(只是在0.03s)
当我换成0.1时,又报同样的错误
然后将产生包的时间间隔改成(0.001),就可以
跑出来,结果不对
然后是静默状态写错了。
转载地址:https://blog.csdn.net/weixin_40599276/article/details/86031411 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!