
2026/03/20 4:18
オシロスコープからWiresharkへ:UDPの物語(2022年)
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
要約
この記事は、Oxide VSC7448ラックスイッチ(VSC8504 PHYを使用)から取得した生のQSGMII波形をEthernetパケットトレース(.pcapファイル)に変換する完全なパイプラインを文書化しています。スイッチに差し込まれた高速デジタルプローブがTektronixオシロスコープに接続され、1 TSPSでサンプリングされた191 MBの波形が記録されました。このデータセットは約100 µsのトラフィックを含み、数千ではなく1〜3個のUDPパケット(≈33 µs/パケット)しか生成しません。
コンパクトなRustパーサー(約400行)は .wfm ファイルを読み込み、カンマシンボルとゼロクロッシングを検出して8b/10b符号化されたストリームをデコードし、4つの交差したポートストリームを抽出します。パーサーは
TryFrom<u16> を介してコードグループを検索テーブルにマッピングし、その後PCS制御マーカー(Configuration, Idle, CarrierExtend, StartOfPacket, EndOfPacket, ErrorPropagation, LinkPartnerIdle)を解釈します。Port 0 に固有の K28.5/K28.1 交差パターンを使用して、ツールは各ポートのデータストリームを回復します。
デコードされたEthernetフレームは7バイトのプレアンブルから始まり、宛先MAC
33:33:00:00:00:01(IPv6全ノードマルチキャスト)、送信元MAC 0e:1d:f3:5c:9d:24、EtherType 0x86DD を持ちます。各ポートで2つのUDPパケットが生成され(tshark で確認済み)、それぞれ8バイトペイロード 01 02 03 04 05 06 07 08 を送信元 fe80::c1d:f3ff:fe5c:9d24 から宛先 ff02::1 に、ポート 997→8 の間で転送します。
Rustツールは4つの .pcap ファイル(各ポートごと)を出力し、パケット数をログに記録します。波形から pcap までの全作業フローは著者のマシンで約 410 ms で実行されます。
今後の課題として、より長いキャプチャや高スループットデバイス用にパイプラインをスケールし、リアルタイム監視統合を探求することが挙げられます。Rustパーサーをオープンソースとして公開することで、このアプローチは物理層でのデータセンターネットワークハードウェアのトラブルシューティングと認証を加速させることを目指しています。
本文
UDP – 生電圧波形から復号されたパケットへ
UDP の概要
UDP は IP ネットワーク上でメッセージを送受信するためのトランスポート層プロトコルです。
OSI 参照モデルではレベル 4 に位置します。
7 アプリケーション 6 プレゼンテーション 5 セッション 4 トランスポート ← UDP 3 ネットワーク 2 データリンク 1 物理層
動機
デスク上には UDP パケットを連続で送信するハードウェアがあります。
「tcpdump を使って生パケットを見る」といった一般的なチュートリアルではなく、
より詳細に解析したいと考えています。
対象は、Oxide Computer Company のラックスイッチの金属層まで接続された アクティブ差動プローブ です。
(プローブはエリックによって丁寧にハンダ付けされています。)
アナログトレースから波形へ
オシロスコープで線路上の信号を取得しました。
目的は、これらのアナログトレースを読みやすい UDP パケットへ変換することです。
-
キャプチャサイズ – デバイスは約 30 k UDP パケット/秒(≈33 µs/パケット)を放出します。
スコープは 100 M サンプル、1 TSPS で設定 → 100 µs のデータ量で 1〜3 パケット分が取得できます。 -
ファイル形式 – スコープは
ファイルを出力します。.wfm
Tektronix はこのフォーマットを公開しており、私は Rust と
を使って解析しました。nom
簡易テスト用に:import numpy as np data = open('udp-spam.wfm', 'rb').read() pts = np.frombuffer(data[904:-1], dtype=np.int16) -
結果 – スコープが表示した波形と一致する生電圧トレースを取得しました。
QSGMII のデコード
VSC7448 スイッチと VSC8504 PHY を接続するリンクは QSGMII(Quad Serial Gigabit Media‑Independent Interface)です。
四つの SGMII チャネルを 1 本の Tx/Rx ペアに統合し、5 Gbps で動作します。
8b/10b エンコーディング
SGMII と QSGMII は共に 8b/10b エンコーディングを使用します。
フレーミングを復元するためには コンマ文字(
1100000 または 0011111)を探します – 連続した同一ビットが五つ並ぶ唯一のコードグループです。
let pts: Vec<bool> = t.pts.iter().map(|p| *p < 0).collect();
遷移を検出し、約 900 サンプルほど一定レベルが続く領域を検索してコンマを見つけます。
同期したら、5 GHz のクロックレート(1 ビットあたり 200 サンプル)で 10‑bit コードグループを読み取ります。
コードグループからストリームへ
QSGMII は四つの SGMII ストリームを交互に配置します。
特別な K28.5 → K28.1 スワッパーが Port 0 を識別し、以降は
port0, port1, port2, port3… の順で並びます。
let mut channel: Option<usize> = None; for (i, mut cg) in cgs.iter().cloned().enumerate() { if cg == Codegroup::K28_1 { channel = Some(0); cg = Codegroup::K28_5; // スワップ解除 } if let Some(c) = channel.as_mut() { streams[*c].push(cg); *c = (*c + 1) % 4; } }
このステップの後、各ポートごとにコードグループ列が得られます。
コードグループからパケットへ
IEEE 802.3‑2015 の表を参照し、コードグループは Ordered Set にマッピングされます:
| Ordered Set | 意味 |
|---|---|
→ config pair | 設定 |
| キャリア拡張 |
| パケット開始 |
| パケット終了 |
| エラー伝搬 |
データグループ() | ペイロード |
デコーダは
Pcs アイテムのストリーム(OrderedSet か生データバイト)を生成します。
fn decode(cgs: &[Codegroup]) -> Vec<Pcs> { … }
パケット再構築
デコード後、慣れ親しんだイーサネットフレーミングが見えてきます:
- アイドル(
) – 連続した/I/55 - パケット開始(
)/S/ - パケットデータ –
で始まる列55 55 55… - パケット終了(
)/T/ - キャリア拡張(
)/R/
リンクは 100 Mbit で動作し、QSGMII はギガビットなので各バイトが十回繰り返されます。
10 回ごとに一つだけ取り出せばクリーンなイーサネットフレームが得られます:
55 55 55 55 55 55 55 d5 33 33 00 00 00 01 ← 宛先 MAC(IPv6 全ノード) 0e 1d f3 5c 9d 24 ← 送信元 MAC 86 DD ← イーサタイプ(IPv6)
IPv6 ペイロードは UDP パケットで、宛先
ff02::1、送信元 fe80::… です。
PCAP への書き出し
pcap クレートを使用して、.wfm ファイル全体を四つの .pcap ファイル(ポートごと)へ変換します。典型的なログ出力は以下の通りです:
[2022-08-08T13:22:35Z INFO qsgmii] Opening udp-spam.wfm … [2022-08-08T13:22:36Z INFO qsgmii] Wrote 2 packets from port 0 to out.pcap.0 ...
処理は標準的なマシンで約 410 ms です。
Wireshark での検証
tshark -r out.pcap.0
同一の UDP パケットが二つ表示されます:
1 0.000000 fe80::c1d:f3ff:fe5c:9d24 → ff02::1 UDP 82 997 → 8 Len=8 2 0.000000 fe80::c1d:f3ff:fe5c:9d24 → ff02::1 UDP 82 997 → 8 Len=8
-V を付けて詳細ダンプすると、イーサネット・IPv6・UDP の各層が確認できます。
結論
生電圧トレースから始めて、以下の手順で物理層からアプリケーションデータまでを完全に解析できました:
- Tektronix
ファイルをパース.wfm - QSGMII のコンマ文字で同期取得
- 8b/10b コードグループをポートごとのストリームへ変換
- コードグループをイーサネットフレームにマッピング
- パケットを PCAP としてエクスポートし、標準解析ツールで確認
これにより、物理層からアプリケーション層までの完全な低レベル検査パイプラインが実現しました。