對RLC重排序窗口大小的一點討論


在LTE協議棧的PDCP層和RLC層,都有一個重排序窗口(reordering window),主要用來保證數據的可靠傳輸,PDCP層的重排序窗口主要用於handover時保證數據的可靠傳輸,這里暫且不表,只討論RLC層的重排序窗口。

對RLC層,在AM接收模式和UM接收模式下,UM接收實體/AM實體接收端有一個重排序窗口,當接收到的RLC PDU位於重排序窗口內,且之前沒有被接收過時,接收端才會對該RLC PDU進行處理,重排序窗口大小無論是在UM模式還是AM模塊下都是序列號(SN)取值范圍的一半。例如,在AM模式下,假如SN長度為10bit,那么SN取值范圍為0 ~ 2^10-1,即0 ~ 1023,則重排序窗口大小為512。

剛開始的時候,我一直不太明白,為什么重排序窗口要選擇這么一個數?不能取大點或者取小點嗎?我想了一下,沒想明白,就囫圇吞棗地默認了這個事實,直到有一天,我在Andrew S. Tanenbaum寫的Computer Networks一書中才偶然發現了答案。As an aside,這里推薦一下Tanenbaum寫的另外一本書——Modern operating systems,這本書對現代操作系統里面基本的元素和概念都進行了比較詳細的闡述,雖然有些地方略有晦澀,並且似乎有點far-fetched之嫌,但是不深究里面的code snippet,僅從其對操作系統一些思想的論述來理解操作系統的設計的話,仍然大有裨益。

回到前面的討論,在AM模式下,RLC PDU不一定要按序接收,假如收到的RLC PDU不是期望接收到的下一幀RLC PDU(i.e. 其SN不等於VR(R)變量的值),但是卻位於重排序窗口內,那么接收端仍然會將該RLC PDU緩存下來,這種非順序接收(Nonsequential receive)方法相比只能按序接收的協議會引入一個問題,而這個問題恰好可以通過對重排序窗口大小的設置來優雅地解決掉。這里我直接引用Tanenbaum的Computer Networks一書中3.4.3節的例子來闡述這個問題。

假設現在RLC PDU的SN號長度為3bit,初始時刻,發送端和接收端的窗口如圖所示。圖中,a圖是初始時刻發送端和接收端窗口的情況。發送端發送窗口為0~6,假設發送端將發送窗口內的RLC PDU全都發送出去了,接收端成功地接收到了SN0~6 RLC PDU,那么接收端就會將窗口往右挪,並將VR(MS)更新為7,此時接收窗口變為7、0~5,如b圖所示。同時,接收端會給發送端發ACK,通知發送端它已經接收到了SN0 ~6 RLC PDU,發送端可以發送新的RLC PDU了。不幸的是,接收端給發送端回復的ACK全都丟失了,發送端一個都沒收着,其發送窗口仍然保持不動,這種情況被稱為window stalling(窗口停滯)。就這樣,一段時間過后,發送端的t-Pol 大專欄  對RLC重排序窗口大小的一點討論lRetransmit timer將會超時,此時發送端還沒有收到0~6 RLC PDU的ACK,它會認為對方可能沒有收到這7個RLC PDU,於是又重傳SN0 RLC PDU,並且將該RLC PDU header里的Poll位置1,詢問對方是不是沒有收着它剛發出去的7個RLC PDU。當SN0 RLC PDU到達接收端時,接收端檢查其是否位於接收窗口內,此時接收窗口為7、0~5,如b圖所示。很不幸,SN0 RLC PDU正好位於其中,接收端認為這是一幀新的RLC PDU,於是很愉快地接收下這幀RLC PDU,然后回了一幀status report(因為它收到的RLC PDU的P位為1),ACK_SN為7,告訴發送端SN 0~6 RLC PDU都已經接收到了。發送端這會終於收到ACK了(i.e. status report),知道SN 0~6 RLC PDU已經被對方成功接收了,於是很愉快地把發送窗口往前移動,發送窗口變為7、0~5。發送端繼續發送SN7、0 ~ 5 RLC PDU給對方,接收端收到SN7、0~5RLC PDU后,發現接收buffer里面已經有SN0 RLC PDU了,就認為新接收到的SN0 RLC PDU是duplicate packet,於是就把新接收到的SN0 RLC PDU給丟棄了,然后對接收buffer里的舊的SN0 RLC PDU連同新接收到的SN7、SN1~5 RLC PDU一起解析,再向上提交給PDCP層。顯然,PDCP會得到錯誤的packet,原因就在於RLC層把舊的SN0 RLC PDU當成了新的RLC PDU,而把真正的新的RLC PDU當成了duplicate packet給丟棄了,通信就此出錯。

image

解決這個問題的方法就是要確保接收窗口在往右移動的過程中,不會把原來的窗口給覆蓋掉(即窗口移進來的部分不會與窗口移出去的部分發生重疊),上面的例子之所以會出錯,就是因為接收窗口往右移動的過程中,新的窗口右邊緣為SN5,剛好落入到舊的窗口里面(SN0~6),新的窗口把舊的窗口的一部分給覆蓋掉了(覆蓋了SN0 ~ 5)。為了保證新的窗口不會覆蓋到舊的窗口,窗口的大小最大不能超過序列號范圍的一半。以圖c和圖d為例,序列號的范圍仍然為0~7,發送窗口大小變為4,任何時刻最多只能有4幀沒有被確認的RLC PDU。這種情況下,當接收端接收到SN0 ~ 3 RLC PDU之后,將會往右移動接收窗口,允許接收SN 4 ~ 7 RLC PDU,這時候,接收端可以明確地區分出發送端發過來的是重傳的RLC PDU(SN0 ~ 3)還是新的RLC PDU(SN4 ~ 7)。一般來說,接收窗口和發送窗口的大小為(MAX_SEQ+1)/2,MAX_SEQ為SN的最大取值。上面的例子中,MAX_SEQ為7,因此窗口大小應該設置為4。當然了,窗口大小也可以取小一點,(MAX_SEQ+1)/2只是一個上界,極端一點的話,甚至可以把窗口大小設為1,但是沒人會這么干,因為這樣的話每次發送都只能發送一幀RLC PDU,然后又要等上老半天,等接收到對方的回復的確認才能發下一幀,采用這種通信方式效率會非常低。所以,這就是為什么RLC層窗口的大小要設置為序列號一半的原因。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM