TL

CoDel と FQ-CoDel:遅延を直接狙うAQMの原理

ダウンロード中でも通話やSSHが固まらない、その裏側が腑に落ちる。CoDelがキュー長でなく滞留時間で輻輳を見抜く原理と、FQ-CoDelのフロー分離、target/intervalの正しい意味を内部から解説。

応用CoDelFQ-CoDelAQMバッファブロート輻輳制御最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.CoDel はキュー長ではなくパケットの滞留時間(sojourn time)を測り、target が interval の間継続して超え続けたときだけドロップに入る。
  • 2.target はバースト用の一時キューを許す下限、interval は最悪 RTT 相当の観測窓で、両者は時間の量なのでリンク速度に依存しない。
  • 3.FQ-CoDel は 5-タプルのハッシュでフローを別キューに分け、新規・低レートのフローを先回しすることで、エレファントフローの裏でも対話的応答性を保つ。

CoDel が解こうとした問題

CoDel(Controlled Delay, RFC 8289)は Kathleen Nichols と Van Jacobson が設計した AQM(Active Queue Management)です。出発点は、過大なバッファに定常的なキューが居座って遅延が肥大するバッファブロートを、現場ごとの再調整なしで潰すことでした。

従来の RED(Random Early Detection)は平均キュー長をしきい値と比べて確率的に落とす方式ですが、適切なしきい値がリンク速度・RTT・フロー数に依存し、固定値で当てるのが事実上不可能でした。CoDel の核心はここを発想転換した点にあります。問題はキューが長いことではなく、キューが長く居座ることです。バーストを吸収する一時的なキュー(good queue)は有益で落としてはならず、いつまでも掃けない定常キュー(bad queue)だけを崩したい。この両者を見分ける指標が、キュー長ではなくパケットの**滞留時間(sojourn time)**だ、というのが CoDel の土台です。

滞留時間はデキュー時にしか分からない

滞留時間とは、あるパケットがキューに入ってから取り出されるまでの実時間です。CoDel はエンキュー時刻をパケットに刻み、デキュー(取り出し)の瞬間に now - enqueue_time で実測します。キュー長(バイト数)と違い、これはボトルネックの実際の送出レートを織り込んだ「本物の遅延」です。だからリンク速度がいくらでも、同じ閾値判定がそのまま通用します。

target と interval の正確な意味

CoDel のパラメータは実質 2 つだけで、どちらも時間で表されます。ここを取り違えると挙動が読めません。

  • target(目標遅延, 既定 5ms): 許容するキュー遅延の下限。滞留時間がこれ未満なら一時バーストとみなし、絶対に落としません。設計上の目安は interval の 5〜10%(既定なら 100ms に対して 5ms)で、小さくしすぎるとバースト吸収力を失ってスループットが落ちます。
  • interval(観測窓, 既定 100ms): 滞留時間が target を超え続けてよい猶予時間。おおむね典型的な最悪 RTT に相当します。1 回の RTT 内では、送信側が減速シグナルに反応する時間を与えるため、超過しても即座には落としません。

重要なのは、CoDel が見るのは「targetinterval の間、継続して超えたか」という一点だということです。瞬間的に target を超えても、interval 内にキューが捌けて滞留時間が target を下回れば、それは健全なバーストであり何もしません。interval の全期間にわたって滞留時間が target 以上であり続けたときに初めて「これは掃けない定常キューだ」と判断し、ドロップ状態に入ります。

target はキュー遅延、interval は反応待ち時間

よくある誤解は両者を「上限と下限のしきい値ペア」と捉えることです。正しくは、target は許容遅延の水準、interval はその超過がどれだけ続いたら本物とみなすかの時間窓です。target を下げれば遅延は浅くなるがバーストに弱くなり、interval を縮めれば反応は速くなるが偽陽性(健全バーストの誤ドロップ)が増えます。

ドロップ間隔がなぜ逆数平方根なのか

ドロップ状態に入ると、CoDel は 1 個落とすたびに次のドロップまでの間隔を詰めていきます。その縮め方が interval / sqrt(count) です(count は連続ドロップ回数)。

# CoDel デキュー時の擬似コード(要点)
sojourn = now - packet.enqueue_time
if sojourn < target or queue_bytes < MTU:
    dropping = false            # 健全。一時バーストは許す。first_above_time をリセット
else:
    if first_above_time == 0:
        first_above_time = now + interval   # 超過の開始を記録
    else if now >= first_above_time and not dropping:
        dropping = true                     # interval だけ継続した。ドロップ開始
        count = 1
        drop_next = now + interval / sqrt(count)
    while dropping and now >= drop_next:
        drop(packet); packet = dequeue()
        count += 1
        drop_next = drop_next + interval / sqrt(count)

count が増えるほど次のドロップまでの間隔が逆数平方根で短くなり、輻輳が続くほどドロップ頻度が上がります。なぜ平方根なのか。これは TCP のスループットが損失率 p の平方根に反比例する(いわゆる 1/sqrt(p) 則)ことへの整合です。送信側のレートを一定割合だけ下げるには、ドロップ確率を二乗のペースで上げる必要があり、裏返せばドロップ間隔を平方根のペースで詰めれば送信側の cwnd が線形に下がります。線形制御の応答を AQM 側が時間軸で実現する仕組みです(AIMD と輻輳制御の数理 参照)。

逆にキューが捌けて滞留時間が target を下回ると dropping を解除します。ただし count は完全には捨てず控えめに減らして引き継ぐため、輻輳が短時間で再発したときに前回のペースから素早く反応できます。これにより、断続的な輻輳でゼロから立ち上げ直す無駄を避けています。

観点REDCoDel
制御変数平均キュー長(バイト/パケット数)デキュー時の実測滞留時間
設定パラメータmin_th / max_th / max_p の手調整target と interval(時間の量)
速度依存あり(環境ごとに再調整)なし(時間基準で不変)
バースト吸収やや苦手(平均で鈍る)得意(interval 内の一時キューは許容)
反応の起点しきい値超過で確率ドロップtarget を interval 継続超過で開始

FQ-CoDel — フロー分離との合わせ技

CoDel 単体は 1 本のキューを制御するだけで、フロー間の不公平には手を出しません。実運用で事実上の標準になっているのは FQ-CoDel(Flow Queueing + CoDel, RFC 8290)です。これは入ってきたパケットを 5-タプル(送信元/宛先 IP・ポート・プロトコル)のハッシュで多数のサブキュー(既定 1024 本)に振り分け、各サブキューを独立した CoDel インスタンスで管理したうえで、サブキュー間を**改良版 DRR(Deficit Round Robin)**で取り出します。基盤となるスケジューリングはパケットスケジューリングの DRR と同じ仕組みです。

効果は二重です。第一に、各フローが自前の CoDel と自前のキューを持つため、1 本の大量転送(エレファントフロー)が埋めるのは自分のサブキューだけで、他のフローの遅延を巻き込みません。CoDel 単体ではすべてのフローが同じキューを共有するので、この分離が決定的に効きます。

第二に、FQ-CoDel はサブキューを**新規(new)継続(old)**の 2 グループに分け、新規フローを優先して取り出します。新しく現れた、あるいはしばらく無音だったフロー(DNS 問い合わせ、対話的な ACK、Web 接続の最初の数パケット)は、まだ自分の quantum を使い切っておらず new リストに入るため、継続中の大量転送より先に送られます。送り終えて quantum を使い切ると old へ移ります。

なぜダウンロード中でも通話が固まらないのか

大量転送は自分のサブキューに長い CoDel キューを作りますが、それは他フローに波及しません。さらに音声パケットや SSH のキーストロークは低レートの new フローとして先回しされるため、たとえ回線が飽和していても対話的な応答性が保たれます。これが FQ-CoDel が家庭用ルータや Linux の既定キューイング規律として広く採用された理由です。

ECN との連携と設計上の含意

CoDel・FQ-CoDel とも、パケットを落とす代わりに ECN(明示的輻輳通知) でマークする変種を持ちます。ECN 対応フローには、ドロップと同じ判定タイミングで CE マークだけを付けられるため、再送遅延ゼロでキューを浅く保てます(ECN と L4S 参照)。ドロップとマークの判定ロジックは共通で、違いは「捨てるか合図するか」だけです。

設計上の急所は、CoDel がフローのレートを直接制御しない点です。CoDel はあくまでボトルネックの滞留時間を浅く保ち、ドロップ(またはマーク)という形で輻輳シグナルを早く返すだけで、減速するのはエンド間の輻輳制御側です。AQM とエンド輻輳制御は役割分担の関係にあり、片方だけでは完結しません。逆に言えば、CoDel が偽陽性で健全バーストを落とすとスループットを無駄に削るため、interval を最悪 RTT に合わせて余裕を持たせる設計が効いてきます。

試験・面接で問われる急所

「CoDel が RED と決定的に違う点は」と聞かれたら、「RED は環境依存のキュー長を見て調整が破綻したが、CoDel はリンク速度に依存しない滞留時間を見て、target を interval の間継続超過したときだけ落とすため実質無調整で動く」と即答できること。あわせて、ドロップ間隔が interval / sqrt(count) と逆数平方根で詰まるのは TCP スループットが損失率の平方根に反比例することへの整合である点、FQ-CoDel の優位はフロー分離(エレファント隔離)と new フロー優先(対話的応答性)の二点である点が頻出です。

ネットワーク Article

CoDel と FQ-CoDel:遅延を直接狙うAQMの原理を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

CoDel

比較で見る軸

難易度: advanced / カテゴリ: ネットワーク / タグ数: 5

導入後に効く点

target はバースト用の一時キューを許す下限、interval は最悪 RTT 相当の観測窓で、両者は時間の量なのでリンク速度に依存しない。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
ネットワーク
タグ数
5

判断チェックリスト

  • 自社の用途が「CoDel / FQ-CoDel」に近いか確認する。
  • 強みである「CoDel はキュー長ではなくパケットの滞留時間(sojourn time)を測り、target が interval の間継続して超え続けたときだけドロップに入る。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

CoDelFQ-CoDelAQMバッファブロート輻輳制御CoDelFQ-CoDelAQM
参考: 公式情報