802.1Qau QCN 筆記

Posted by summer on January 26, 2024

建議搭配 QCN Pseudo Code

QCN 是運用在 L2 環境下的壅塞控制

QCN大致分為 3 部分

  • Reaction Point
  • Congestion Point
  • Reflection Point

對應發送方、中間節點、接收方

Congestion Point

Congestion Point 會在收到封包後計算 $F_b$,$F_b$ 被用來量化壅塞程度

$F_b = (Q_{eq} - q{len}) - W * (q{len} - q{len}_{old})$

$Q_{eq}$ 是 Queue 的參考點,QCN 會將 Queue 長度維持在這裡

W 是控制參數,模擬時取 2

$F_b$ 會被限制在

\[-Q_{eq}*(2*W+1) \le F_b \le 0\]

區間內

接下來根據所使用的位元數將 $F_b$ 量化成一個正數稱為 $qntz{F_b}$, 等於 0 時代表沒有壅塞發生。

Congestion Point 會在 Time_to_mark byte counter 小於 0 ,且 $qntz{F_b} > 0$ 時送出 feedback frame

Time_to_mark byte counter小於 0 時還會更新 $q{len}_{old}$ 並更新byte counter

fb_frame 中有

  • destination address 送方 MAC
  • source address 壅塞點的 MAC
  • flow id
  • $qntz{F_b}$
  • $q_{off}$ $Q_{eq} - q{len}$
  • $q_{delta}$ $q{len} - q{len}_{old}$

Reaction Point

在 Reaction Point 第一次收到 feedback 後,會為流啟用一個 rate limiter, rate limiter 中有

  • state 區分是否啟用
  • flow id
  • Crate current rate
  • Trate taget rate
  • tx_bcount byte counter 用於改變 stage
  • si_count 紀錄 byte counter 的 stage
  • timer
  • timer_scount 紀錄 timer 的 stage
  • qlen

如果 fb 不為 0,重設 byte counter 與 timer 的 stage ,並 Multiplicative decrease current rate

\[decfactor = (1 - GD * fb)\] \[Crate = Crate * decfactor\]

發送 frame 時,若 Crate 到達速度上限且 qlen 為 0 ,停用 rate limiter。 若不滿足條件,則會讓 tx_bcount 減去 frame 大小。 tx_bcount 倒數結束後,si_count加一,重設 tx_bcount 進入 self_increase 函式


timer 在到期時會將 timer_scount 加一,進入 self_increase 函式,重設timer

byte counter 與 time counter 重設時都是參考 fast recovery threshold,在 stage 大於 threshold 時,expire period 都是原來的一半。

self_increase

首先判斷兩個 timer 的 stage 是否大於 fast recovery threshold,如果其中之一大於 threshold 代表進入 active increase 階段 \(R_i = R_{ai}\)

若兩個都大於,則進入 hyperactive increase 階段

\[R_i = R_{hai} * (min(si\_count,tx\_bcount) - fast recovery threshold)\]

若兩個都不大於

\[R_i = 0\]

$R_{ai}$ 與 $R_{hai}$ 為控制參數,而 $R_i$ 並不會直接加在 Crate 上,而是加在 Trate 上,而 Crate 最後為

\[Crate = (Crate+Trate)/2\]

總結

QCN 有兩個 counter 計算 stage,stage 影響 QCN 所屬階段,Reaction Point 流程圖如下

    flowchart TD
        s[收到 feedback] --> r["reset(si_count timer_count)"]
        r --> w[等待 counter expire]
        w -- byte counter expire --> si[self_increase]
        w -- timer expire --> si
        si --> sis{"max(si ti)>FRT"}
        sis --yes-->siss{"min(si ti)>FRT"}
        sis -- no -->ai[active increase]-->w
        siss -- yes --> hai[hyperactive increase]
        siss -- no --> fas[fast recovery]
        hai --> w
        fas --> w