「Wi-Fiが遅い」という言葉の裏には、単なるスループット(帯域幅)の不足だけでなく、パケットが空中で渋滞し、順番待ちに疲弊しているという残酷な現実が隠されています。
現場で数々のパケットロスと格闘してきたエンジニアの皆さんなら、ビデオ会議の音声が途切れたり、APIのレスポンスがスパイクしたりする現象がいかに致命的か、身に染みて理解しているはずです。今回は、家庭用ルーターのスペック表で「QoS対応」と一言で片付けられがちな技術の深淵、WMM(Wi-Fi Multimedia)とトラフィック制御の実践的なメカニズムについて、現場の視点で解き明かしていきます。
—
1. WMMの正体:Wi-Fiの空中で行われる「優先順位」の選別
Wi-Fiは本質的に「早い者勝ち(CSMA/CA)」の世界です。しかし、すべてのパケットを平等に扱うと、巨大なOSアップデートのダウンロードパケットのせいで、数ミリ秒の遅延も許されないVoIPパケットが死蔵してしまいます。
これを解決するのが、IEEE 802.11eで規定されたEDCA(Enhanced Distributed Channel Access)、通称「WMM」です。WMMは、パケットを以下の4つのAC(Access Category)に分類し、送信待機時間(バックオフ制御)に差をつけます。
| カテゴリ | 略称 | 用途 | 特徴 |
| :— | :— | :— | :— |
| Voice | AC_VO | 音声 (VoIP) | 最優先。待機時間が極めて短く、割り込みに近い挙動。 |
| Video | AC_VI | 動画ストリーミング | 高優先。バースト転送を許容しつつ遅延を抑制。 |
| Best Effort | AC_BE | 一般的なWeb、API | 標準。従来のWi-Fiと同じ扱い。 |
| Background | AC_BK | ファイル同期、更新 | 低優先。空いている時だけ流す。 |
なぜWMMで優先度が変わるのか
WMMは、各カテゴリに対して「送信権を得るまでの待ち時間(AIFS)」と「衝突時に再送を待つウィンドウ(CWmin/CWmax)」のパラメータを個別に設定します。
例えば、AC_VOはAC_BEよりも「ジャンケン(バックオフ)」を開始するまでの時間が短く、かつ負けた時のペナルティ(待ち時間)も小さく設定されています。これにより、物理レイヤで統計的にパケットが「先に飛び出す」仕組みになっているのです。
—
2. 実務でのマッピング:DSCPからWMMへの橋渡し
インフラ運用やWeb API設計に携わるエンジニアにとって重要なのは、「自分のアプリケーションのパケットを、どうやってルーターに『重要だ』と認識させるか」という点です。
Wi-Fiルーターは通常、IPヘッダー内のDSCP(Differentiated Services Code Point)フィールドを見て、WMMのカテゴリを決定します。RFC 8325では、このマッピングの推奨指針が示されています。
DSCPとWMMの対応例(RFC 8325準拠)
- EF (Expedited Forwarding / 46) →
AC_VO - AF41 (34) / CS4 (32) →
AC_VI - BE (0) →
AC_BE
これをコードレベルでどう制御するか。例えば、Pythonで書かれたリアルタイム信号通信のクライアント側で、特定のパケットにDSCP値をセットする方法を見てみましょう。
import socket
# ソケットの作成(UDPを想定)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# DSCP値を設定(EF: 46)
# DSCPはIP_TOS(Type of Service)フィールドの上位6ビットを使用する
# 46を6ビット左シフト(46 << 2)して 184 (0xB8) をセットする
IPTOS_PREC_EF = 0xB8
try:
# IPレベルのソケットオプションでTOS(DSCP)を指定
sock.setsockopt(socket.IPPROTO_IP, socket.IP_TOS, IPTOS_PREC_EF)
# 送信先
server_address = ('192.168.1.10', 5000)
message = b'Priority Packet: High Urgency'
# 送信
sock.sendto(message, server_address)
print(f"Successfully sent packet with DSCP EF (0xB8)")
except Exception as e:
print(f"Failed to set DSCP: {e}")
finally:
sock.close()
このように、アプリケーション層からソケットオプション(IP_TOS)を叩くことで、OSのネットワークスタックを経由してWi-Fiチップセットに対し、「これはAC_VOで飛ばしてくれ」というヒントを与えることができます。
—
3. ルーター内部のキューイングと帯域制限のロジック
パケットが無線に飛び出す前、ルーターのCPUとメモリ内ではキューイング(Queuing)が行われます。安価なルーターでは単なるFIFO(First-In, First-Out)ですが、高機能なモデルやOpenWrtなどのカスタムファームウェアでは、より高度なアルゴリズムが動いています。
主なキューイングアルゴリズム
1. FQ_CoDel (Fair Queuing Controlled Delay):
現代のLinuxカーネルや高性能ルーターのデファクトです。パケットをフローごとに細かく分け、巨大なフローが小さなフローをブロックする「Bufferbloat」を防ぎます。
2. HTB (Hierarchical Token Bucket):
「このデバイスには最大100Mbps、ただし余っていたら200Mbpsまで貸して良い」といった、階層的な帯域制限を実現します。
設定例:トラフィックシェーピング(疑似コード)
もしあなたがLinuxベースのゲートウェイを構築しているなら、tc(traffic control)コマンドで以下のような制御を行うことになります。
# eth0(WAN側)に対してFQ_CoDelを適用し、バッファ詰まりを防止
tc qdisc add dev eth0 root fq_codel
# 特定のIP(IoTデバイス等)の帯域を制限する設定例
# 1. クラスベースのキュー(HTB)を作成
tc qdisc add dev eth0 root handle 1: htb default 12
# 2. 親クラス(全体の帯域 1Gbps)
tc class add dev eth0 parent 1: classid 1:1 htb rate 1000mbit
# 3. 特定デバイス用の制限クラス(10Mbps保証、最大20Mbps)
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10mbit ceil 20mbit
# 4. フィルターを適用(IPアドレス 192.168.1.50 の通信を上記クラスへ)
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 192.168.1.50 flowid 1:10
—
4. 現場でのデバッグ:パケットは本当に優先されているか?
QoSの設定をしたつもりでも、実際に効果が出ているかはWiresharkやtsharkでの検証が欠かせません。
特に、Wi-Fiの「空中の優先度」を確認するには、通常のEthernetキャプチャではなく、Monitor Modeでのキャプチャが必要です。802.11 QoS Dataフレーム内のPriorityフィールドを確認してください。
# tsharkを使用して、QoSデータフレームの優先度を表示する例
tshark -i wlan0mon -Y "wlan.fc.type_subtype == 0x0028" -T fields -e wlan.qos.priority -e ip.src -e ip.dst
ここで出力されるwlan.qos.priorityが、WMMの各AC(0〜7の値)に対応します。もしここがすべて0(Best Effort)のままであれば、OSのスタックかNICのドライバがDSCP値を無視して落としてしまっている可能性があります。
—
5. シニアエンジニアからのアドバイス:メッシュWi-Fiの罠
最近流行のメッシュWi-Fiを導入する場合、一つ注意点があります。
バックホール(ルーター間の通信)が無線の場合、QoSの効果が減衰することがあります。親機で優先制御を行っても、子機から親機への転送(中継)時に再度コンテンション(競合)が発生するためです。
実務で「絶対に遅延を許さない」環境を作るなら、以下の3点を徹底してください。
1. 可能な限り有線バックホール(Ethernet Backhaul)を使う。
2. DSCPを正しく付与し、WMMが有効であることを確認する。
3. ルーターの「ゲームモード」や「優先制御」を過信せず、FQ_CoDelのようなモダンなアルゴリズムが採用されている機種を選ぶ。
ネットワークは、目に見えないパケットの譲り合いで成り立っています。QoSを正しく理解し制御することは、単なる高速化ではなく、通信という「対話」の品質を守ることに他なりません。
この記事が、皆さんの構築するインフラやアプリケーションの信頼性を一段階引き上げる一助となれば幸いです。
コメント