opnet物联网仿真2.5 陈敏 包交换网络全解----比较详细

我在网上看到了很多讲解包交换网络的这一教程,但是或多或少里面抄英文讲解的太多,或者里面有一些细节的地方没有说清楚,导致很多地方都一知半解或者就差了一点点你就对了,所以这里力求做一个完整的全解

当然本人暑假的时候做过了陈敏2004年出版的那本书上的包交换网络,但是陈敏用的是opnet10.0,现在我的版本是opnet14.5.

请注意安装opnet的时候参考https://blog.csdn.net/qq_31285709/article/details/87873709 这篇文章,其他地方的文章普遍有问题,我的老师给我的opnet安装包我一开始用的就是vs2019,但是opnet14.5在vs2013之后可能就会出一点问题,尤其是在链接和基本库这一块,里面的环境变量建议使用vs2010的东西,不然问题很多很多,感谢上文作者,因为他的文章和资源应该是全网目前看来最靠谱的opnet安装教程。

下面我们开始 对陈敏的这本物联网仿真里面包交换网络进行全解

首先我们搭建包格式 packet_format

首先这里就是一个大坑,陈敏这本书里面有明显错误,在他2006年的那本书里面,他用的是32位(4字节)的包,但是这本书里面他建议使用4位的包,这里是大错,因为在后面我们会用到一个写32位的函数,这里是第一个坑

这里还是建议使用32位的陈敏2004/2006版的书里面的包格式

 

然后我们开始搭建链路模型,这里可以完全按照陈敏书里面来,请注意我的截图,这里我的链路错误用的是error_zero_err

 

下面我们就能搭建节点的node模型,这里我们在陈敏那本2006年的书里面写的是4个节点,这里我们用了8个节点,不过node的模型是一样的,但是hub的模型不一样

 

请注意了,我们这里一定要更改收发机channel属性,来匹配我们的链路

当然还有src模块的更改,我们要把src模块变成一个产生包的一个模块,所以要这么改

这里我们注意了,除了你要改包格式之外,我们要把packet interarrival time这个东西提升属性变成promoted,什么叫提升属性,也就是你仿真的时候可以指定这个属性值为多个值,这样的话你就能够进行仿真对比

这里我们包交换网络就是要考察包生成速率不同的时候,信道利用率怎么样,所以要把它提升属性

然后我们跳到node interfaces界面,去更改我们的一些界面属性,按照陈敏他的教程,我们这里可以重命名那个interarrival time,然后哦我们对此做出初值进行修改,这里建议看书

 

下面是hub的模型,同样我们要更改收发机的channel属性,这里我就不放截图了,反而这里其实比较简单,注意收发信机不要配错了,我有一次没有用固定节点,用的可变节点,结果就一直出不来结果2333.

下面我们就能配两个进程模型了,分别是hub的和node的

我们先看hub的,这里我们必须明确一下opnet进程模型的一些概念,PK_ARRVL这种就是条件,而route_pk()是满足这个条件触发的函数,而触发函数之后,转移到的状态仍然是idle,我们这里idle的状态是红的,也就是所谓的非强制,也就说,进程在这个状态是可以中断的!!!这个非常重要,我们进程状态转换就是牵扯到这种概念

 

 

 我们进入FB模块看一下我们的代码

static void route_pk(void)
{
       int dest_address;
    Packet* pkptr;
    FIN(route_pk());
    pkptr = op_pk_get(op_intrpt_strm());//从中断流编号之中找到包的指针
    op_pk_nfd_get(pkptr,"dest_address",&dest_address);//找到包的目的地址
    op_pk_send(pkptr,dest_address);//转发到目标流中
    FOUT;
}

建议看一下陈敏2015版物联网仿真的第二章,熟读,里面的代码你就明白了,这里就是一个简单的提取目标地址然后转发的代码。

然后我们进入HB看一下我们对于PK_ARRVL的定义

#define PK_ARRVL (op_intrpt_type()==OPC_INTRPT_STRM)

显然,我们只要认为中断是流中断的时候,我们就说,有包流到达了,这样我们要转发,这是显而易见的,但是还是建议先读一下书,看一下中断的概念

然后我们到了node模块的代码,node模块中我们要干什么?就是node是一个双工的模块,我们既要产生包把它送出去,又要接受从hub转发来的包,所以说让我们先看一下代码和有限状态机

看我们的有限状态机,这里我们看init状态,变成了绿色,这就是所谓的强制状态,也就是说,我们这个状态是绝对不会中断的,进程绝对不会停留在强制状态,一定要让他顺序执行,所以说,强制状态我们一般不写出口代码,因为本质上他的进口代码和出口代码应该是一样的。

我们先看看init的进口代码里面写了什么东西

address_dist = op_dist_load("uniform_int",0,7);//产生随机分布,应该是平均分布的0-7
ete_gsh = op_stat_reg("ETE Delay",OPC_STAT_INDEX_NONE,OPC_STAT_GLOBAL);//得到统计量的句柄

这时候我们奇怪了,我们并没有定义address_dist和ete_gsh啊,但是很简单,这两个东西定义在SV(状态变量)里面

我们进入SV看一看状态变量的定义,请注意,状态变量就是相当于这个模型自己拥有的变量,所以我们在SV里面定义了一遍,然后就不用再定义了

 

首秀按我们要知道Distriction*这个东西是一个函数指针,他指向一个随机分布函数,请注意,我们这里陈敏书里又有一个错误,也就是他的随机分布是0-3,事实上这是他2004年那本书里面写的,在2015版这本书里面应该使用0-7对应我们的八个收发信机

而stathandle指向我们的统计量,请注意,我们的统计量应该是全局统计量,但是这个全局统计量我们需要先声明一下(这里,ETE delay代表每一个包的输入到输出的延迟,也就是transmission delay(我们前面忽略了传播时延,只计入传输时延),自然这应该是一个全局变量,毕竟我们要统计全局的包的delay)

终于,我们可以看一下我们的HB的定义和FB里面的函数了,这里建议一定要理解陈敏那本书的第二章

让我们看看HB里面写了什么

#define RCV_IN_STRM 0 
#define SRC_IN_STRM 1 
#define XMT_OUT_STRM 0 

#define SRC_ARRVL (op_intrpt_type () == OPC_INTRPT_STRM && op_intrpt_strm () == SRC_IN_STRM) 
#define RCV_ARRVL (op_intrpt_type () == OPC_INTRPT_STRM && op_intrpt_strm () == RCV_IN_STRM)

什么意思,这里我们定义输入的包流0代表RCV,也就是从hub输入进来的,而输入包流1代表SRC,表示这个node他自己产生的包流

而输出包流显然只有一个,那么我们直接编号0就行,代表输出出去的包流

而SRC_ARRVL要求是流中断,而且中断号应该就是1

RCV_ARRVL要求是流中断,中断号显然就是0

这里就好解释了,然后我们进入最重要的FB里面,看一下我们的核心函数

static void xmt(void)
    {
        Packet* pkptr;
        FIN(xmt());
        pkptr = op_pk_get(SRC_IN_STRM);//根据包流编号得到包,这种包应该是src产生的包
        op_pk_nfd_set_int32(pkptr,"dest_address",(int)op_dist_outcome(address_dist));//填入dest_address
        op_pk_send(pkptr,XMT_OUT_STRM);//输出,输出包流号为0
        FOUT;
    }

static void rcv(void)
    {
        Packet* pkptr;
        double ete_delay;
        FIN(rcv());
        pkptr = op_pk_get(RCV_IN_STRM);//根据包流编号得到包,这种包是hub转发的包
        ete_delay = op_sim_time()-op_pk_creation_time_get(pkptr);//计算时延
        op_stat_write(ete_gsh,ete_delay);//填入ete_gsh所指代的时延,也就是全局变量ETE Delay
        op_pk_destroy(pkptr);//释放内存
        FOUT;
    }

我在里面还是添加了一些注释,应该能够帮助理解,但是具体请一定要参考陈敏的书,其实理解起来很简单

每一个node都是两种作用,产生包把它发出去,或者接受从hub转发过来的包,这里我说道了之前说的陈敏这本书里面的坑

也就是这里op_pk_nfd_set_int32这个函数本应该是写一个32位的数据,如果你在第一步设置包格式的时候写了4位必定出大错

最后我们一定要激活仿真中断,这在前一个进程模型(hub那一步)也要做的,所以两个模型都用这一步

注意把begsm intrpt改成enabled

好了,现在我们只要把两个进程模型编译一下,然后edit attribute把它们放进该有的模块里面就行了

 

最后,我们终于可以进行网络层的建模了,而这里面也有大坑,稍后会提到

我们new一个project出来,按照陈敏那本书的指示,在你的所有模型里面就能用到这样的集合

按照如图所示摆好

也就是一个hub,8个node

好了,现在我们点ctrl + L,或者在拓扑里面点verify links,检查我们的链路是否合理

本人在暑假里面做的四交换的网络很快就合理,但是这一次8交换的网络,一开始都是failed,链路居然连不上,请注意,这里是一个大坑,因为正常来说如果你的格式设置正确的话,opnet可能会根据你链接的顺序自动找收发信机,但如果你摆的顺序不是那么准确的话,请手动设置,这里我卡了半天,这也是陈敏这本书里面没有提到的,注意,我们右击每一个链路

这样

点edit attributes,这样设置

如果你的链路失败,很可能是你的收发信道都是none,注意手动设置

这样,我们的拓扑就搭好了,最后就是仿真了,找到

 

 

进入configure run(advanced)进入仿真页面,我们最重要的是设置之前我们promoted的那个interarrival time

这里我们两个仿真,一个设置的4,一个是40

 

在你run之前先设置一下你要记录的仿真量

最后,run吧

得到结果,我们终于完成了这个包交换网络

 

其实我们这里一个是ete delay(端到端的时延),其实这时延的表示还不够精确,如果我们用离散图,就可以看到每一个包的时延了,还有一个是信道利用率,显然,单位时间内发包越多,信道利用率肯定越大。

 

最后,我们终于完成了,这篇博文希望能对opnet的初学者能有一点启发和一些问题进行解决,当然答主本人也只是一个准大三学生,如果有学长或者其他高手来探讨一下自然是最好了

 

posted @ 2020-09-01 13:51  coolwx  阅读(1744)  评论(3编辑  收藏  举报