1. 程式人生 > >TI CC2530 CC2538 zigbee source routing機制的有效利用(加快單播指令的傳送,解決單播丟包問題)

TI CC2530 CC2538 zigbee source routing機制的有效利用(加快單播指令的傳送,解決單播丟包問題)

  • 很多人開始對於source routing是十分迷惑的,加之TI的FAE很多時候人力有限,所以會產生很多疑問,既然都有路由表了,怎麼還會有個叫做source routing,這些東西不是憑空產生的,都是有產生的歷史背景的。
  • 通過對Z-Stack 3.0 Developer’s Guide.pdf文件的閱讀,我們發現,source routing作為zigbee PRO協議棧的一個新特性,是many-to-one路由機制的一部分,source routing的唯一作用就是協調器(在這裡也可以稱為concentrator,中文叫閘道器,或者英文名coordinator)能以最優路徑傳送資料給其他router或者end device。
  • 即使你按照swra427c.pdf(AN123)文件Z-Stack Knobs配置使能了many to one,但是預設也不會使用到source routing。
  • 一般情況下,coordinator和其他router一樣,也有一張路由表,記錄了到達多個router的路由資訊,而且會AODV動態變化,協議棧自帶的所有sample工程,都是在zcl.c裡面呼叫zcl_SendCommand傳送控制指令,最終都會呼叫AF_DataRequest傳送控制指令給其他節點,但此時根本沒有利用到source routing,不信可以用ubiqua分析一下資料包,就會發現Source Route Included是No,而不是Yes,這就解釋了為什麼很多人提到coordinator給多個節點單播發送控制指令的時候,雖然有間隔傳送,但有時候也會出現莫名奇妙丟包的問題,因為協議棧此時可能沒有路由路徑,所以發了AODV,等路由路徑建立了,此時控制指令也不會再次重發,自然就產生了丟包。
  • 一般網路建立之後物理位置就固定下來了,能否利用source routing來發送資料呢,這樣就不存在路由表超時無效的問題,可以加快傳送資料。即使在協調器上電不久,不需要重建路由表,都可以利用上層閘道器已儲存的source route加快資料的傳送。

下圖可以看出,並沒有利用source routing
沒有用到source routing

對於many to one路由機制有兩個點需要注意,無非就是:
1. coordinator傳送資料給其他節點,類似於通過閘道器傳送控制指令控制LED燈或者窗簾;
2. 其他節點發送資料給coordinator,類似於做為zigbee感測器資料採集節點。

  • 這就是所謂的many to one,多對一,或者說一對多,前提他們是如何知道到達彼此的路徑的呢?
  • 首先,其他節點是如何知道到達coordinator的路徑?不是一般意義上的大家都死命在那傳送AODV路由請求,這樣就會導致網路嚴重擁塞,嚴重丟包,最後誰也發現不了誰。為了解決這個問題,coordinator會定時傳送route request(RREQ)廣播,這個時間由CONCENTRATOR_DISCOVERY_TIME這個巨集來控制,其他節點收到這個廣播包後,就知道自己到達coordinator的路徑了,當然也可以傳送單播,只給某一個節點發送route request,請參考 5.4.2 Many-to-One Route Discovery 。例如下圖,0x1234和0x5678節點收到route request之後就知道到達coordinator(0x0000)的路由路徑了。
    many to one route discovery

  • 其次,coordinator是如何知道到達其他節點的路由路徑呢? 肯定是讓其他節點主動報告自己的位置,不能是人家coordinator主動問你在哪裡,對吧。協議棧裡面也是這麼幹的,我們接下來往下看,參考 5.4.3 Route Record Command

  • 其他節點會不定時的給coordinator傳送route record(RREC)指令,這個指令裡面就包含了自己到達coordinator的relay轉發路徑,這樣,coordinator一旦收到route record之後,就知道自己到達這個節點的最優路徑了。

  • 例如下圖,0x9DF5節點給0x0000傳送了一條route record指令,就包含了兩個負責relay的節點,最終coordinator就知道這樣的路由路徑:0x9DF5->0x1828->0x5E89->0x0000
    route record

  • 很多人會以為協議棧會自己管理source routing,在你需要傳送控制指令給某個節點的時候,協議棧會自動幫你加上relay列表,以實現最優路徑傳送給某個節點。

  • 遺憾的是,協議棧並不會這樣做,這一點guide文件並沒有提及。 coordinator自己收到了route record,也只是把短地址、路由列表relayList和路由數量relayCount解析出來,最後呼叫ZDO_SrcRtgIndCB函式把這三個引數丟給上層APP,自己就不管了( 具體傳遞引數請參考ZDO_SrcRtgIndCB的程式碼,這個函式在非公開的程式碼AllDevice.a庫裡面被呼叫 )。
  • 既然協議棧自己並不會管理source routing,那麼只能上層APP自己管理收到的relayList,並在傳送控制指令的時候根據目的節點的短地址,要不要給出relayList了,如果給出,那麼就按照relayList的路徑去傳送,否則就按照協議棧自己的一般路由表去找目的節點。
  • AF_DataRequestSrcRtg這個函式就是負責在傳送控制指令前,新增relayList的,該函式最終也會呼叫AF_DataRequest實現控制指令的傳送,但是在這之前,它還有一個動作就是呼叫RTG_AddSrcRtgEntry_Guaranteed把relayList加入到source routing table裡面,讓協議棧按照這個relay路徑去傳送,指令就能很快到達目的節點,只有不能到達的時候才會AODV。
  • 我們自己在上層APP裡面使用了資料庫,一旦收到route record,則把短地址和對應的relayList以及relayCount都插入到資料庫中,在需要單播發送控制指令的時候,再用短地址去資料庫中查詢是否有source routing,如果有則呼叫AF_DataRequestSrcRtg,否則呼叫AF_DataRequest進行傳送。

結語

  • 測試On/Off:Off關燈指令,是否通過了source routing傳送,我們看到,的確是通過了source routing提供的路徑傳送的,且沒有提示source route failure,說明發送成功,中間經過了0x42B3、0x1828、0x5E89三個節點進行了轉發,由於我們沒有在0x42B3附近進行抓包,所以左邊Traffic View裡面的On/Off:Off只能顯示了2行,否則一定顯示的是3行轉發資訊。
    這裡寫圖片描述

  • 通過使用source routing,協調器能夠快速傳送單播指令給其他節點,效率很高,再也不會出現單播控制指令有時候能控制成功,有時候總是控制失敗的問題

注意事項

  • 需要注意的是,在收到route record以及傳送單播的時候,要原封不動的給出relayList,不要做逆序。比如收到0x8836發來的route record的時候,relayList方向是這樣的:0x42B3->0x1828->0x5E89,那麼傳送單播控制指令的時候,也要同樣給出0x42B3->0x1828->0x5E89,而不是0x5E89->0x1828->0x42B3,否則就會提示source route failure錯誤。