トラフィックシェーピング入門:原理・アルゴリズム・実装とベストプラクティス

はじめに — トラフィックシェーピングとは何か

トラフィックシェーピング(traffic shaping)は、ネットワーク上のパケット送信タイミングやレートを制御して帯域の利用を平滑化(スムージング)し、遅延・ジッタ・輻輳の管理やサービス品質(QoS)の担保を行う技術です。単に帯域を制限するポリシング(policing)とは異なり、超過パケットを即座に破棄するのではなく、バッファリングして送信を遅らせることでパケット損失を抑え、突発的なバーストを整形します。

なぜ重要か — ユースケースと効果

  • VoIPやリアルタイムストリーミングの遅延・ジッタ低減で音声・映像品質を確保する。
  • バックアップや大容量転送の帯域を調整し、重要トラフィックの優先度を保つ。
  • ISPやクラウド事業者でアクセス回線における不公平利用を抑え、総合的なユーザ体験を向上させる。
  • バッファブロート(bufferbloat)対策として遅延を抑える設計と併用する。

基本原理 — アルゴリズムと動作

代表的なアルゴリズムには、トークンバケット(Token Bucket)とリ―キーバケット(Leaky Bucket)があります。どちらもバースト管理と平均レート制御を目的としますが挙動が異なります。

  • トークンバケット:一定速度でトークン(許可)を生成しバケットに蓄える。パケットを送信する際にパケットサイズ分のトークンを消費し、トークンが足りなければ送信を待機(または遅延)する。バーストを許容しつつ平均レートを維持するのに適している。
  • リ―キーバケット:内部的には一定レートで出力を行うキューと見なせる。到着パケットはバッファに溜められ、出力は一定の「漏出」速度で行われる。バーストを滑らかにするが、実装によっては遅延が増える。

ネットワーク機器では、これらの基本を拡張した実装(例:単一/階層トークンバケット、HTB:Hierarchical Token Bucket、TBF:Token Bucket Filter 等)が用いられます。

ポリシング(policing)との違い

ポリシングは規定帯域を超過したパケットを即座に破棄したりマーク(DSCPなど)する処理で、シンプルかつ速いですが損失が発生します。一方シェーピングは送信タイミングを調整して損失を回避するため、リアルタイムアプリケーションに有利です。実運用では、シェーピングとポリシングを組み合わせることが多いです(例えば、顧客側でシェーピングして余剰を吸収し、送信先側でポリシングを行う)。

QoSとの連携 — クラス分類とキューイング

シェーピングは分類(classification)とキューイング(queuing)とセットで運用されます。代表的なキューイング戦略には以下があります。

  • FIFO(First-In First-Out): 最も単純。
  • PQ(Priority Queueing): 高優先度トラフィックを常に先出し。
  • WRR / WFQ(Weighted Round Robin / Weighted Fair Queuing): 帯域を重み付けして公平に分配。
  • CBQ(Class-Based Queuing) / HTB: 階層的にクラス分けして帯域を配分。
  • CoDel / fq_codel: バッファブロート対策に有効な遅延制御アルゴリズム。

さらに、DiffServ の DSCP マークを用いてパケットに優先度を付け、ネットワーク全体のポリシーと連携することが一般的です(RFC 2474/2475 等)。

実装例 — Linux の tc と代表的 qdisc

Linux では tc コマンドを用いて qdisc(queueing discipline)を設定します。代表的なもの:

  • TBF(Token Bucket Filter):単純で低オーバーヘッドなレート制御。
  • HTB(Hierarchical Token Bucket):クラス階層を持ち、柔軟に帯域を配分可能で ISP や企業のアクセス制御に多用。
  • fq_codel:公平なキューイングと遅延短縮を両立する現代的 qdisc。
  • pfifo_fast:デフォルトのシンプルキュー。

実運用では、端末側/顧客ゲートウェイで TBF/HTB によるシェーピングを行い、ルータやプロバイダ側で優先制御(DSCP→キュー)と CoDel 系 qdisc を併用する構成が多いです。

どこでシェーピングするか — 出入口の考え方

シェーピングは原則として「エグレス(出力)」で行うのが効果的です。パケットの送出を制御できるタイミングがエグレス側だからです。インバウンド(受信)トラフィックの整形が必要な場合は、顧客側で ACK を遅延させるなどの間接的手法や、プロバイダ側でポリシングを併用する方法があります。

設計とチューニングのポイント

  • 目標指標を明確に:帯域、最大遅延、許容ジッタ、損失率など。
  • バーストサイズ(バケットサイズ)の設定:小さすぎればアプリケーションの短期バーストを潰す、 大きすぎれば遅延が増える。
  • バッファブロート対策:CoDel/fq_codel を検討し、キュー長を適切に制御する。
  • 測定と監視:sFlow、NetFlow、tcpdump、iperf、ping、ホスト側の QoS モニタを活用する。
  • エンドツーエンドの観点:経路にある中間ノードのキューイング特性も品質に影響するため、単一箇所でのチューニングでは限界がある。

トラブルシューティングの例

  • 高遅延・ジッタが増加:バッファが大きすぎる(バッファブロート)か、シェーピングのバースト許容が不適切。
  • パケット損失が多い:ポリシングによるドロップや、過度なキューオーバーフロー。シェーピングでバッファを調整するか、優先度設定を見直す。
  • ユーザからの不満(速度不足):過度に厳しい帯域制限、または他トラフィックの優先度が高すぎる可能性。

ベストプラクティスまとめ

  • エッジでのシェーピング + コアでの優先制御という分担を基本にする。
  • リアルタイムトラフィックは優先かつ最小遅延、バルクトラフィックはバーストを許容してバックグラウンドで処理する。
  • CoDel / fq_codel 等の遅延制御アルゴリズムを導入しバッファブロートを防ぐ。
  • 変更ごとに性能試験(iperf、実トラフィックの観測)を行い、ユーザ体験に与える影響を測定する。

まとめ

トラフィックシェーピングは単なる帯域制限ではなく、ネットワーク品質を守るための重要な手段です。適切なアルゴリズム選択、階層的なクラス設計、遅延制御(CoDel 等)の併用、そして継続的な監視とチューニングが成功の鍵です。事前に目標を明確に定め、実測ベースでパラメータを最適化しましょう。

参考文献