我在網上看到了很多講解包交換網絡的這一教程,但是或多或少里面抄英文講解的太多,或者里面有一些細節的地方沒有說清楚,導致很多地方都一知半解或者就差了一點點你就對了,所以這里力求做一個完整的全解
當然本人暑假的時候做過了陳敏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的初學者能有一點啟發和一些問題進行解決,當然答主本人也只是一個准大三學生,如果有學長或者其他高手來探討一下自然是最好了