LinuxにおけるBufferbloat対策ソリューションの比較
SSHで快適に作業していたところ、同僚がトレントをダウンロードし始めたり、クラウドへ50GBのバックアップをアップロードした途端、pingが15msから一気に450msまで跳ね上がる――これはBufferbloat(バッファブロート)の典型的な症状です。ネットワーク機器がTCPパケットの破棄を抑えようとして過剰にパケットをバッファリングするため、キューが肥大化してしまいます。その結果、DNSルックアップ、SSHのキーストローク、VoIP通話といった低遅延が求められるパケットが後ろに詰まり、応答しなくなってしまいます。
Linuxでは、この問題を解決するために主に3つのキューイング規則(qdisc)が提供されています。
- Default FIFO (pfifo_fast): 古典的な先入れ先出し(FIFO)キューです。先に到着したパケットから順に送信されます。1つのフローが帯域を使い果たすとバッファが満杯になり、他のすべての接続でラグが発生します。
- FQ-CoDel (Fair Queuing Controlled Delay): トラフィックを1024個の独立したサブキューに分散させます。キューが滞留し始めると、CoDelアルゴリズムが自動的にパケットをドロップするかECNフラグを付与します。FQ-CoDelはLinuxカーネル3.5以降に標準搭載されています。
- CAKE (Common Applications Kept Enhanced): エッジルーター向けにFQ-CoDelを全面的にアップグレードした仕組みです。帯域シェーパーが組み込まれており、物理層のオーバーヘッド(PPPoE、Ethernetフレーミング)を自動補正し、ホストごとにトラフィックを公平に配分します。
技術的なメリット・デメリットの比較分析:FQ-CoDel vs CAKE
各アルゴリズムは、ネットワークインフラ内の異なる箇所のボトルネックを解消するように設計されています。
1. FQ-CoDel
メリット:
- CPU負荷が極めて低く、1 vCPUのVPSから数十Gbpsの高負荷を処理するLinuxスイッチまで軽快に動作します。
- 煩雑なパラメータ調整が不要です。実際のネットワークRTTに応じてアルゴリズムが自動適応します。
- 外部モジュールを追加インストールすることなく、主要なLinuxディストリビューションですぐに利用できます。
デメリット:
- トラフィックシェーパーが内蔵されていません。WANポートの帯域を絞ってLinux側に意図的にバッファを形成させるには、非常に冗長な
tc構文を使ってHTBとFQ-CoDelを組み合わせる必要があります。 - 5-tuple(送信元/宛先IP・ポート、プロトコル)に基づいて均等配分するだけなので、1台のマシンがマルチスレッドで40本の接続を張ると、1セッションしか開いていないマシンを依然として圧迫してしまいます。
2. CAKE (qdisc_cake)
メリット:
- 極めて安定した帯域シェーパーが組み込まれています。複雑なHTBツリーを構築することなく、わずか1行のコマンドで設定できます。
triple-isolateモードをサポートしており、フロー単位ではなくホスト単位で均等に帯域を配分します。単一のIPがオフィスネットワーク全体を占有することを防止できます。- 物理層のオーバーヘッド(FTTH PPPoE、VLAN、DOCSISなど)を自動計算・補正します。プロバイダーのモデム側でパケットが不意に滞留するのを防ぎます。
- iptables/nftablesで手動設定しなくても、DiffServ(DSCP)フィールドに基づいてパケットを自動認識・優先順位付けします。
デメリット:
- オーバーヘッドの計算や多段ハッシュ処理を行うため、FQ-CoDelに比べてCPU使用率が15〜25%程度高くなります。
- Linuxカーネル4.19以降が必要です(Ubuntu 20.04以降やDebian 10以降であれば標準で対応しています)。
ネットワーク構成ごとの最適な選定基準
すべての環境で一律にCAKEを採用すればよいわけではありません。
- FQ-CoDelが適しているケース: スタンドアロンのサービスサーバー、Kubernetesクラスタ、または10Gbps/40Gbpsの内部ネットワークポート。インターフェース自体がボトルネックにならない環境では、FQ-CoDelにより計算コストをほぼゼロに抑えつつ超低遅延を維持できます。
- CAKEが適しているケース: エッジルーター、オフィスのLinuxゲートウェイ、PPPoEでインターネットに接続するホームラボ。1GbpsのNICに200Mbpsの回線を接続しているような環境では、CAKEの内蔵シェーパーによってキューの制御権をLinux側へ引き戻すことで最大の効果を発揮します。
Linuxでの具体的な設定手順
ステップ1:現在のqdiscを確認しBufferbloatを計測する
まず、プライマリネットワークカードで現在どのキューイング機構が稼働しているかを確認します。
# eth0 インターフェースのキューイング規則(qdisc)を確認
tc qdisc show dev eth0
ターミナルにpfifo_fastや単なるmqと出力された場合、アクティブなキュー管理アルゴリズムはまだ有効になっていません。
遅延の簡易測定は、ターミナルを2つ開くことで行えます。一方のウィンドウでping 1.1.1.1を実行し、もう一方でcurl -Oで大きなファイルをダウンロードするかiperf3を実行します。もしpingが20msから200〜300msに跳ね上がるようであれば、深刻なBufferbloatが発生しています。
ステップ2:スタンドアロンサーバーでFQ-CoDelを有効化する
Webサーバーやデータベースノード、一般的なVMの場合は、ネットワークカードにFQ-CoDelを割り当てるだけで完了します。
# eth0 のデフォルト qdisc を fq_codel に変更
sudo tc qdisc replace dev eth0 root fq_codel
# パケットの統計情報とステータスを確認
tc -s qdisc show dev eth0
出力結果には、drops(ドロップ数)、ecn_mark、およびアクティブなフロー数が表示されます。FQ-CoDelがトラフィックを自動調停し、特定のフローがキューを長時間占有しないように制御します。
ステップ3:Linuxルーター / ゲートウェイでCAKEを設定する
輻輳防止の鉄則は、シェーパーの帯域を実効回線速度の90%〜95%に設定することです。これにより、パケットの滞留がISPのモデム側ではなく、常にLinux側で制御されるようになります。
内部ネットワークの各セグメントにルールを分割する前に、サブネットマスクの設定ミスを防ぐため、toolcraft.app/ja/tools/developer/ip-subnet-calculatorなどでネットワーク範囲とホスト数を確認しておくと便利です。
インターネット向けのWANポートがeth0で、回線契約が100Mbps(実測値で安定して95Mbps出ている)環境を想定します。
# CAKE シェーパーを90Mbpsに設定、Ethernetオーバーヘッドを補正しホスト単位で均等配分:
sudo tc qdisc replace dev eth0 root cake bandwidth 90mbit ethernet triple-isolate nonat
# このインターフェースで外部へのNATを行っている場合、natフラグを有効にしてCAKEでconntrackを追跡:
sudo tc qdisc replace dev eth0 root cake bandwidth 90mbit ethernet nat dual-srchost
適用後すぐに動作ステータスを確認します。
tc -s qdisc show dev eth0
出力にはターゲット遅延(通常5ms前後)、使用中バッファサイズ、ドロップされたパケット数、ECNマーク率が明確に表示されます。
ステップ4:再起動後も設定が自動適用されるように永続化する
tcコマンドで設定した内容はマシンの再起動時に失われます。恒久的にルールを保持するには、systemdサービスを作成するのが最も確実な方法です。
/etc/systemd/system/cake-sqm.serviceファイルを作成・編集します。
sudo nano /etc/systemd/system/cake-sqm.service
以下の内容を記述します(インターフェース名と帯域幅は環境に合わせて変更してください)。
[Unit]
Description=Apply CAKE SQM to eth0
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/sbin/tc qdisc replace dev eth0 root cake bandwidth 90mbit ethernet nat dual-srchost
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
サービスを有効化します。
sudo systemctl daemon-reload
sudo systemctl enable --now cake-sqm.service
これで、回線の負荷テストを再度実施してみてください。帯域を100%フルに使用している状態でも、pingの増加はアイドル時と比べてわずか1ms〜5ms程度に抑えられているはずです。

