議狀態(tài)機與定時器:LTE可靠傳輸?shù)牡讓舆壿? alt=)
簡介面向LTE無線接入網(wǎng)研發(fā)、協(xié)議棧實現(xiàn)與測試崗位工程師的學(xué)習(xí)資料聚焦TD-LTE數(shù)字蜂窩移動通信網(wǎng)Uu接口中的RLC協(xié)議。內(nèi)容依據(jù)中國通信標(biāo)準(zhǔn)化協(xié)會技術(shù)報告系統(tǒng)規(guī)定E-UTRA RLC子層結(jié)構(gòu)、RLC實體、上下層業(yè)務(wù)關(guān)系、功能劃分以及與對等層通信的協(xié)議數(shù)據(jù)元、格式和參數(shù)并說明未知或錯誤協(xié)議數(shù)據(jù)的處理方式同時覆蓋確認(rèn)模式等關(guān)鍵機制可幫助讀者理解RLC在數(shù)據(jù)傳輸與差錯校正中的職責(zé)邊界。資源包共1個doc文件約1.74MB為中文協(xié)議文本適合作為協(xié)議查閱與實現(xiàn)對照的案頭文檔。目前已有493人學(xué)習(xí)適合需要梳理Uu接口協(xié)議分層、準(zhǔn)備協(xié)議棧開發(fā)或測試用例設(shè)計的讀者參考使用。1. RLC 協(xié)議為什么 LTE 的“可靠傳輸”不靠重傳次數(shù)堆出來很多人第一次翻 LTE 協(xié)議棧會覺得 RLC 這一層“沒什么存在感”——上有 PDCP 做加密和頭壓縮下有 MAC 做調(diào)度和 HARQRLC 夾在中間好像只是把數(shù)據(jù)切一切、編個號。但真正在鏈路層調(diào)過參數(shù)的人會告訴你掉話、速率上不去、切換后業(yè)務(wù)卡頓最后追下去十有八九落在 RLC 的狀態(tài)變量和定時器上。RLC 協(xié)議真正解決的問題不是“重傳”而是在一個底層 HARQ 已經(jīng)會重傳、上層又要求按序交付的環(huán)境里如何用最少的反饋把“哪些收到了、哪些沒收到、什么時候該等、什么時候該放棄”講清楚。這份 TD-LTE Uu 接口技術(shù)要求第 7 部分把 TM、UM、AM 三種實體、發(fā)送/接收窗口、t_Reordering、t_PollRetransmit、t_StatusProhibit 這些機制一條條寫成了可實現(xiàn)的規(guī)范。搞懂它你才能明白為什么 LTE 的可靠傳輸不是靠“多傳幾遍”堆出來的而是靠窗口和定時器把不確定性收斂掉。2. 三種模式的分工TM、UM、AM 到底在取舍什么2.1 TM 實體為什么它連 RLC 頭都不給透明模式是三種模式里最“反直覺”的一個。按規(guī)范描述發(fā)送 TM RLC 實體從上層收到 RLC SDU 后不做分段、不做級聯(lián)也不在 TMD PDU 里加任何 RLC 頭直接往下層交。接收側(cè)同樣收到 TMD PDU 就原樣往上分發(fā)。這意味著 TM 實體根本不提供序列號也就沒有重排序、沒有重復(fù)檢測、沒有重傳。那它存在的意義是什么看它綁定的邏輯信道就明白了BCCH、DL/UL CCCH、PCCH。這些信道傳的是廣播信息、公共控制信息和尋呼信息特點是“一次性、面向小區(qū)內(nèi)所有終端、對時延敏感但對個別丟失不敏感”。如果給尋呼消息加一個 RLC 頭再編個 SN接收側(cè)還得維護窗口狀態(tài)純屬給終端增加無謂的狀態(tài)機負擔(dān)。TM 的設(shè)計動機就是當(dāng)上層業(yè)務(wù)本身不需要 RLC 級別的可靠性保證時把這一層的開銷壓到零。這里有個容易踩的細節(jié)TM 不分段意味著上層交下來的 SDU 必須能塞進下層通知的傳輸機會里。實際實現(xiàn)中TM 實體通常只處理固定或受控大小的消息不會出現(xiàn)“SDU 太大塞不下”的情況。如果你在實現(xiàn)里給 TM 加了分段邏輯那已經(jīng)不是規(guī)范里的 TM 了。2.2 UM 實體單向可靠性的邊界在哪里UM 實體綁定在 DL/UL DTCH 上做分段、級聯(lián)、加 RLC 頭、編 SN接收側(cè)做重復(fù)檢測、重排序、丟失檢測但不請求重傳。這是它和 AM 最本質(zhì)的區(qū)別UM 承認(rèn)“有些 PDU 就是會丟”它只負責(zé)把收到的按序整理好、把等不到的東西在合理時間內(nèi)放過去而不是死等。規(guī)范里 UM 接收側(cè)維護一個以 VR(UH) 為基準(zhǔn)的重排序窗口窗口范圍是(VR(UH) – UM_Window_Size) SN VR(UH)。收到一個 UMD PDU 時先判斷它是否落在窗口內(nèi)、是否重復(fù)再決定丟棄還是放進接收緩存。放進去之后如果這個 SN 落在窗口外就推進 VR(UH)把窗口外能重組的 SDU 按 SN 升序往上交如果 VR(UR) 落在窗口外就把 VR(UR) 拉回VR(UH) – UM_Window_Size。這一套狀態(tài)推進的邏輯核心目的只有一個不讓一個丟失的 PDU 把整個接收緩存無限期卡住。t_Reordering 就是那個“后悔藥”。當(dāng) VR(UH) VR(UR)說明有空洞啟動定時器超時后直接把 VR(UR) 推到 VR(UX)的第一個未收到 SN把空洞之前能交的都交上去。這樣即使中間丟了一個包后續(xù)數(shù)據(jù)也不會被永久阻塞。UM 的取舍很清晰用“可能丟一點”換“不會因為一個包卡死整條鏈路”適合語音、流媒體這類對時延敏感、對少量丟包可容忍的業(yè)務(wù)。2.3 AM 實體ARQ 和 HARQ 為什么要疊兩層AM 實體是三種模式里狀態(tài)最復(fù)雜的發(fā)送部分和接收部分各自維護窗口和一組狀態(tài)變量。發(fā)送側(cè)窗口由 VT(A) 和 VT(MS) 界定VT(A) SN VT(MS)內(nèi)的 PDU 才允許下發(fā)接收側(cè)窗口由 VR(R) 和 VR(MR) 界定。AM 同時支持分段、級聯(lián)、重分段、ARQ 重傳、輪詢和狀態(tài)報告。一個常見疑問是MAC 層已經(jīng)有 HARQ 了為什么 RLC 還要做 ARQ因為兩者解決的問題不在一個時間尺度上。HARQ 是快速反饋、基于傳輸塊的重傳次數(shù)有限失敗后就把“這個塊沒救回來”的事實往上報RLC ARQ 是慢速反饋、基于 PDU 序列號的它負責(zé)把 HARQ 漏掉的那些洞補上。規(guī)范里 AM 發(fā)送部分明確寫了“傳輸 RLC 控制 PDU 優(yōu)先于數(shù)據(jù) PDU重傳數(shù)據(jù) PDU 優(yōu)先于新數(shù)據(jù) PDU”這個優(yōu)先級順序就是為 ARQ 服務(wù)的狀態(tài)報告先走欠的賬先還新數(shù)據(jù)往后排。AM 的重分段能力也值得單獨說。當(dāng)一個待重傳的 AMD PDU 塞不進當(dāng)前傳輸機會時發(fā)送部分可以把它重新分段成多個 AMD PDU 段而且規(guī)范明確寫了“重分段的分段數(shù)量沒有限制”。這給了實現(xiàn)很大的靈活性底層給的授權(quán)忽大忽小RLC 不用死等一個剛好合適的傳輸機會而是把大 PDU 拆小分批送。代價是接收側(cè)要按“字節(jié)段序號”來管理重復(fù)檢測比 UM 的整 PDU 粒度復(fù)雜得多。3. 狀態(tài)變量與窗口RLC 的“賬本”是怎么記的3.1 UM 接收側(cè)的四個變量和一次收包決策UM 接收側(cè)的核心狀態(tài)變量是 VR(UR)、VR(UH)、VR(UX)。VR(UR) 是“下一個期望按序收到的 SN”VR(UH) 是“已收到的最高 SN 加一”VR(UX) 是 t_Reordering 啟動時記下的快照。收到 SN x 的 UMD PDU 時決策順序大致如下收到 SN x 的 UMD PDU 若 VR(UR) x VR(UH) 且 x 之前已收到 - 丟棄重復(fù) 若 (VR(UH) - UM_Window_Size) x VR(UR) - 丟棄窗口外舊包 否則 - 放入接收緩存 放入緩存后 若 x 落在重排序窗口之外 VR(UH) x 1 重組并向上分發(fā)窗口外可交付的 SDU 若 VR(UR) 落在窗口之外 VR(UR) VR(UH) - UM_Window_Size 若緩存中存在 SN VR(UR) 的 PDU VR(UR) 推進到下一個未收到的 SN 重組并分發(fā) SN 新 VR(UR) 的 SDU 若 t_Reordering 在運行且滿足停止條件 停止并重置 t_Reordering 若 t_Reordering 未運行且 VR(UH) VR(UR) 啟動 t_ReorderingVR(UX) VR(UH)這段偽代碼對應(yīng)規(guī)范 5.1.2.2.2 和 5.1.2.2.3 兩節(jié)。幾個參數(shù)的含義需要說清楚UM_Window_Size決定了接收側(cè)最多能容忍多大的亂序范圍窗口越大抗亂序能力越強但接收緩存和狀態(tài)維護成本越高VR(UX)的作用是給 t_Reordering 超時后的推進設(shè)一個下界避免超時后把還沒等到的包直接跳過太多。t_Reordering 超時時VR(UR) 被推到“SN VR(UX) 的第一個未收到 PDU”然后如果還有空洞就重啟定時器。這套邏輯的本質(zhì)是用定時器把“等”這件事量化等多久由 VR(UX) 和窗口共同決定而不是無限等。3.2 AM 發(fā)送窗口VT(A)、VT(S)、VT(MS) 三者的關(guān)系A(chǔ)M 發(fā)送側(cè)的狀態(tài)變量更多但核心就三個VT(A) 是“最早未被肯定應(yīng)答的 SN”VT(S) 是“下一個新 PDU 要用的 SN”VT(MS) 是“發(fā)送窗口上界”滿足VT(MS) VT(A) AM_Window_Size。發(fā)送窗口的有效范圍是VT(A) SN VT(MS)任何 SN 落在窗口外的數(shù)據(jù) PDU 都不允許下發(fā)。這個窗口機制解決的是“發(fā)送方不能無限往前跑”的問題。如果沒有窗口發(fā)送方可以一直發(fā)新數(shù)據(jù)接收方的緩存和狀態(tài)變量會無限增長而且一旦某個早期 PDU 丟了后面所有 PDU 都得在接收側(cè)等著重排序壓力全壓在接收端。窗口把“在途未確認(rèn)數(shù)據(jù)”的數(shù)量限制住讓收發(fā)雙方的狀態(tài)空間有界。收到肯定應(yīng)答時如果應(yīng)答的 SN 等于 VT(A)發(fā)送部分就把 VT(A) 推進到“VT(A) 到 VT(S) 范圍內(nèi)最小的未被肯定應(yīng)答的 SN”。這里有個容易忽略的點規(guī)范說的是“最小的未被肯定應(yīng)答的 SN”不是簡單地 VT(A)1。因為 STATUS PDU 可能一次性確認(rèn)多個 PDU也可能有空洞VT(A) 必須跳到第一個真正沒被確認(rèn)的位置。如果某個 RLC SDU 的所有相關(guān) AMD PDU 都被確認(rèn)了還要向上層發(fā)“發(fā)送成功指示”——這就是 AM 模式對 PDCP 的交付保證。3.3 AM 接收窗口與字節(jié)段粒度AM 接收側(cè)的窗口由 VR(R) 和 VR(MR) 界定VR(R) SN VR(MR)為窗口內(nèi)。和 UM 不同的是AM 的重復(fù)檢測粒度是字節(jié)段一個 AMD PDU 可能被重分段成多個段接收側(cè)要記錄每個 SN 下哪些字節(jié)段已經(jīng)收到。規(guī)范 5.1.3.2.2 寫得很明確收到包含 SNx 的 AMD PDU 字節(jié)段 y 到 z 的 PDU 時如果 x 在窗口外或 y 到 z 之前已收到丟棄否則放入緩存并把其中重復(fù)的字節(jié)段丟掉。這個設(shè)計直接來自 AM 的重分段能力。如果只按整 PDU 做重復(fù)檢測重分段后的段就沒法正確合并。字節(jié)段粒度讓接收側(cè)可以“拼圖”同一個 SN 下不同段可能從不同傳輸機會到達只要所有字節(jié)段湊齊這個 AMD PDU 就算完整收到。VR(MS) 就是用來跟蹤“哪些 SN 還沒湊齊所有字節(jié)段”的t_Reordering 超時后 VR(MS) 被更新為“SN VR(X) 的第一個未湊齊的 PDU”觸發(fā)狀態(tài)報告把缺口告訴發(fā)送方。4. ARQ 與輪詢STATUS 報告什么時候發(fā)、發(fā)給誰4.1 輪詢的觸發(fā)條件不是想發(fā)就發(fā)AM 發(fā)送部分通過 P 域poll 位觸發(fā)對等實體回 STATUS 報告。規(guī)范給了幾類觸發(fā)條件PDU_WITHOUT_POLL pollPDU、BYTE_WITHOUT_POLL pollByte、發(fā)送后發(fā)送緩存和重傳緩存都空、或者沒有新數(shù)據(jù)能發(fā)窗口延遲。這幾個條件覆蓋了不同場景前兩個是“發(fā)夠了就問問”后兩個是“沒得發(fā)了趕緊確認(rèn)一下好推進窗口”。輪詢不是免費的。每發(fā)一個帶 P 域的 PDU就要啟動或重啟 t_PollRetransmit如果對等實體沒回 STATUS定時器超時后要重傳并再次輪詢。所以 pollPDU 和 pollByte 設(shè)得太小STATUS 報告會過于頻繁反向鏈路開銷上去設(shè)得太大窗口推進慢吞吐受影響。這是典型的參數(shù)調(diào)優(yōu)取舍沒有放之四海皆準(zhǔn)的值。4.2 STATUS 報告的觸發(fā)與禁止接收側(cè)觸發(fā) STATUS 報告的來源有三類收到 P 域為 1 的 PDU、t_Reordering 超時檢測到接收失敗、以及規(guī)范里提到的其他觸發(fā)。但觸發(fā)不等于立刻發(fā)還要過 t_StatusProhibit 這一關(guān)如果 t_StatusProhibit 沒在運行就在下一個傳輸機會構(gòu)造并下發(fā) STATUS PDU如果在運行就等它超時后的第一個傳輸機會再發(fā)而且期間多次觸發(fā)也只發(fā)一個。這個“狀態(tài)禁止定時器”的設(shè)計動機是防止 STATUS 風(fēng)暴。設(shè)想接收側(cè)連續(xù)收到多個帶 P 域的 PDU如果每個都立刻回一個 STATUS反向鏈路會被狀態(tài)報告淹沒而且這些報告內(nèi)容高度重疊。t_StatusProhibit 把反饋合并、限頻用一點反饋延遲換反向鏈路效率。規(guī)范里還特別注了一句P 域為 1 的 PDU 如果 x VR(MS) 或 x VR(MR)觸發(fā) STATUS否則延遲觸發(fā)直到條件滿足——這是為了保證狀態(tài)報告在 HARQ 重排序之后發(fā)避免基于亂序到達的中間狀態(tài)做出錯誤判斷。4.3 重傳計數(shù)與 maxRetxThresholdAM 發(fā)送部分對每個 AMD PDU 維護 RETX_COUNT。首次重傳時置 0之后每次“該 PDU 或它的部分不再等待重傳”時加一。當(dāng) RETX_COUNT 達到 maxRetxThreshold向上層指示“已達到最大重傳”。這個機制是 RLC 的“止損線”ARQ 不能無限重傳否則一個永遠收不到的 PDU 會把整個承載卡死。達到閾值后往上報告由上層決定是重建、釋放還是別的處理。這里有個實現(xiàn)上的坑RETX_COUNT 的加一條件是“不再等待重傳”而不是“每次重傳就加一”。因為一個 PDU 可能被重分段成多個段分多次發(fā)送規(guī)范用“不再等待重傳”這個狀態(tài)來界定一次完整的重傳嘗試避免分段導(dǎo)致計數(shù)虛高。5. 避坑與排查RLC 實現(xiàn)里最容易翻車的幾件事5.1 現(xiàn)象切換后業(yè)務(wù)卡住STATUS 報告一直不發(fā)原因通常是 t_StatusProhibit 配置過大或者狀態(tài)報告觸發(fā)條件判斷有誤。切換過程中接收側(cè)可能積壓了多個觸發(fā)事件如果 t_StatusProhibit 沒超時這些觸發(fā)會被合并延遲。排查時先看接收側(cè)是否在 t_StatusProhibit 運行期間持續(xù)觸發(fā)但從未下發(fā) STATUS PDU再看 VR(MS) 是否長時間不更新。解決方式是核對 t_StatusProhibit 的配置值和觸發(fā)邏輯確認(rèn)“延遲觸發(fā)直到 x VR(MS) 或 x VR(MR)”這個條件沒有被實現(xiàn)成永久等待。5.2 現(xiàn)象UM 業(yè)務(wù)偶發(fā)大面積亂序交付原因多半是 t_Reordering 超時處理里 VR(UR) 推進邏輯寫錯。規(guī)范要求超時后 VR(UR) 更新為“SN VR(UX) 的第一個未收到 PDU 的 SN”如果實現(xiàn)里誤寫成“VR(UX) 本身”或“VR(UH)”就會把還沒等到的包直接跳過造成上層看到空洞。排查時抓接收側(cè)狀態(tài)變量日志對比超時前后 VR(UR)、VR(UX)、VR(UH) 的變化是否符合規(guī)范 5.1.2.2.4 節(jié)。解決是按規(guī)范逐條核對狀態(tài)推進順序特別注意“先更新 VR(UR)再重組分發(fā)再判斷是否重啟定時器”這個次序。5.3 現(xiàn)象AM 重傳次數(shù)異常增長RETX_COUNT 很快打滿常見原因是重分段后 RETX_COUNT 的加一條件判斷錯誤。如果實現(xiàn)里每發(fā)一個分段就加一一個 PDU 被拆成多段重傳幾次就會虛高到閾值。規(guī)范說的是“該 PDU 或它的部分不再等待重傳”時才加一。排查時看 RETX_COUNT 的增長是否和“完整重傳嘗試次數(shù)”一致而不是和“分段發(fā)送次數(shù)”一致。解決是把計數(shù)點放在“一次重傳嘗試結(jié)束”的位置而不是每次下發(fā)分段時。5.4 現(xiàn)象窗口延遲導(dǎo)致吞吐上不去發(fā)送側(cè) VT(MS) 長時間不推進新數(shù)據(jù)發(fā)不出去表現(xiàn)為“有數(shù)據(jù)但發(fā)不了”。根因可能是 STATUS 報告丟失或輪詢沒觸發(fā)。檢查 pollPDU、pollByte 是否設(shè)得過大導(dǎo)致長時間不輪詢以及 t_PollRetransmit 超時后是否正確重傳并重新輪詢。另一個可能是接收側(cè) VR(MS) 更新邏輯有誤導(dǎo)致狀態(tài)報告里漏報缺口。排查時同時看發(fā)送側(cè) VT(A)/VT(S)/VT(MS) 和接收側(cè) VR(R)/VR(MS) 的日志確認(rèn)缺口是否被正確報告和確認(rèn)。5.5 現(xiàn)象TM 承載上出現(xiàn)“SDU 太大塞不下”TM 不分段如果上層交下來的 SDU 超過下層傳輸機會能承載的大小實現(xiàn)里沒有合法處理路徑。這通常不是 RLC 本身的問題而是上層對 TM 承載的使用方式不對或者傳輸機會通知的大小計算有誤。排查時確認(rèn)該承載是否真的應(yīng)該用 TM以及下層通知的 RLC PDU 總大小是否包含了必要的開銷。解決要么調(diào)整上層數(shù)據(jù)大小要么重新評估該業(yè)務(wù)是否適合 TM。6. 設(shè)計取舍RLC 為什么把復(fù)雜度放在狀態(tài)機上回頭看這份規(guī)范RLC 最值得琢磨的地方不是某個具體過程而是它把“可靠性”拆成了幾層不同時間尺度的機制HARQ 管快速重傳RLC ARQ 管慢速補洞t_Reordering 管亂序容忍t_StatusProhibit 管反饋限頻窗口管狀態(tài)有界。每一層都在做一個取舍——用多少狀態(tài)、多少延遲、多少反饋開銷換多少可靠性。一個有意思的對比是 UM 和 AM 的接收側(cè)。UM 只有 VR(UR)、VR(UH)、VR(UX) 三個變量重復(fù)檢測是整 PDU 粒度AM 多了 VR(R)、VR(MR)、VR(MS)、VR(H)、VR(X)重復(fù)檢測細到字節(jié)段。這個復(fù)雜度差異不是隨意的而是由“是否支持重傳和重分段”決定的一旦允許重傳和重分段接收側(cè)就必須能表達“這個 SN 下哪些字節(jié)收到了、哪些沒收到”狀態(tài)空間自然膨脹。規(guī)范沒有試圖用一套統(tǒng)一的狀態(tài)機覆蓋三種模式而是讓 TM 極簡、UM 中等、AM 完整各取所需。另一個取舍是定時器的角色。t_Reordering、t_PollRetransmit、t_StatusProhibit 三個定時器分別對應(yīng)“等亂序”“等狀態(tài)”“限反饋”它們都不是為了“保證正確”而存在而是為了“在不確定的情況下做出可接受的決策”。協(xié)議不能假設(shè)底層永遠不丟包、不能假設(shè)對等實體永遠及時回復(fù)所以用定時器把“等多久”變成一個可配置、可驗證的量。這也解釋了為什么 RLC 的參數(shù)調(diào)優(yōu)這么依賴場景定時器值本質(zhì)上是把業(yè)務(wù)特征時延容忍度、丟包率、往返時間編碼進協(xié)議行為里。我自己的習(xí)慣是每次碰到 RLC 相關(guān)的異常先把收發(fā)兩側(cè)的狀態(tài)變量按時間軸拉出來對照規(guī)范里狀態(tài)推進的條件逐條核對而不是先去調(diào)定時器參數(shù)。因為大多數(shù)“玄學(xué)”問題最后都能在某個狀態(tài)變量的推進條件里找到根因——定時器只是把問題暴露出來的那個觸發(fā)器。希望這份規(guī)范里的狀態(tài)機和過程描述能幫你在下次排查鏈路層問題時少走一點彎路。本文還有配套的精品資源點擊獲取