Dev Study
← ネットワークの仕組み
レッスン 2 / 13·約 15 分·第2期 ネットワークの仕組み

信号からフレームへ — ビット列をどこで区切るか

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択今ここ
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理
  7. DB保存

前回、通信を層に分けて考える理由を見ました。今回はその一番下、電気信号として届いたビット列を「1通のまとまり」に切り出す段階を扱います。ここが決まって初めて、上の層はIPアドレスやポート番号を読めるようになります。

まず結論

ケーブルを流れてくるのは、切れ目のない0と1の連なりです。受信側は「どこからが1通のデータか」を自力で見つけなければなりません。

Ethernetはこれを2段階で解いています。プリアンブルで相手の刻みに同期し(古典的な10Mb/sのEthernetでの説明)、その直後のSFD(スタートフレームデリミタ)で「ここから本体」と区切りを確定させます。同期と区切りは別の仕事で、これを混同するとフレーム構造の話が最後まで噛み合いません。

? 読む前に予測

ケーブルには0と1が途切れなく流れてきます。受信側は「1つのフレームがどこから始まるか」を、何を手がかりに判断しているでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

切れ目のない信号に、区切りは書かれていない

前回、通信を層に分けて考える理由を見ました。今回はその一番下、ケーブルの中で起きていることから始めます。

ケーブルを流れているのは、電圧の変化として表された0と1の連なりです。ここで見落とされやすい問題が出てきます。この連なりには、区切りが書かれていません。 紙の文章なら単語の間に空白があり、文の終わりに句点があります。しかし受信側に届くのは ...0101101000110101... という、ひたすら続くビットの列だけです。

しかも厄介なことが2つ重なります。そもそも1ビットの幅が分からないこと(送信側の刻みと合っていないと、同じ信号から違うビット列を読んでしまう)。そして仕切り専用の記号が使えないこと(0と1しか流せない以上、区切りもまた0と1の並びで表すしかない)。

Ethernetはこの2つを、別々の仕組みで順番に解決しています。この「別々である」という点が、本レッスンの要点です。

具体実物

Ethernetフレームの先頭8オクテットを見る

実際のEthernetフレームの構造を、先頭から並べます。

Ethernetフレームの構造(オクテット数)表
フィールド オクテット 役割
プリアンブル 7 受信側を送信側の刻みに同期させる
SFD 1 区切りの確定「次から本体」
宛先MACアドレス 6 ここからが「フレーム」
送信元MACアドレス 6
(802.1Qタグ) (4) VLAN使用時のみ
タイプ/長さ 2 中身のプロトコル種別
ペイロード 46-1500 運ばれるデータ(タグ付き時 42-1500)
FCS 4 伝送誤りの検査
フレーム間ギャップ 12 次のフレームとの間隔

注目してほしいのは先頭の2つ、プリアンブルとSFDです。この8オクテットが、先ほどの2つの問題に順番に答えています。

プリアンブルの7オクテットは 10101010 の繰り返しです。0と1が規則正しく交互に現れるので、受信側は「相手は今このくらいの速さで刻んでいる」と読み取りタイミングを合わせ込めます。これが同期(クロック回復)です。ただしこれは古典的な10Mb/sのEthernetでの説明です。より高速な規格の物理層で、同期をどこまでプリアンブルに頼っているかは、本教材は IEEE 802.3 本文で確認できていません。

ただし同期はできても、区切りはまだ決まりません。 10101010 を7回繰り返した信号は、どの周期も全く同じ見た目だからです。「交番している最中だ」とは分かっても、「その何番目にいるのか」は判別できません。区切りが決まるのは、次の1オクテットを見た瞬間です。

プリアンブルからSFDへ(ビット列)コマンド出力
10101010 10101010 10101010 10101010 10101010 10101010 10101010 ← プリアンブル(7オクテット)
10101011 ← SFD(1オクテット)
^
ここだけ 0 ではなく 1。交番パターンが破れる
→ 「次のビットから宛先MACアドレス」と確定

SFDのパターンは 10101011 で、プリアンブルと違うのは末尾の1ビットだけです。ずっと ...0 で終わっていた並びが、ここで初めて ...1 で終わる。この「期待が裏切られる瞬間」が合図になります。

✓ ここまでの確認

プリアンブルとSFD(スタートフレームデリミタ)の役割の違いとして、正しいのはどれですか。

抽象原理

同期と区切りは、別の仕事

ここで一般化しておきます。ビット列から意味のあるまとまりを切り出すには、2つの異なる仕事が必要です。

区切りを見つけるまでの2段階
①刻みを合わせる規則的なパターンを送り続ける○ 1ビットの幅と読み取り位置が合う
②位置を確定するそのパターンを意図的に破る○ 「ここが境目」と分かる
↓
①だけでは「読めるが、どこにいるか分からない」状態にとどまる
  • ・①がプリアンブル、②がSFD
  • ・規則性を作るのが①、その規則性を壊すのが②。壊すためには、まず作る必要がある

②が成立するために①が要るという関係に注目してください。パターンを破って合図にする方法は、破られる前の「当たり前のパターン」が共有されていて初めて働きます。何も規則が無いところに急に 1 が来ても、合図にはなりません。だから順番は入れ替えられず、片方だけでも足りません。

具体実物

「フレーム」はどこから数えるのか

もう1つ、区切りの話に直結する数え方の問題があります。Ethernetには最小フレームサイズ64オクテットという制約がありますが、この64がどこからどこまでなのかは、意外と取り違えられています。

答えは宛先MACアドレスからFCSまでです。プリアンブルとSFDの8オクテットは含みません。

64オクテットの範囲表
プリアンブル(7) + SFD(1) 含まない ← 本体を読むための「助走」
宛先MAC(6) + 送信元MAC(6) 含む
タイプ/長さ(2) 含む
ペイロード(最小46) 含む
FCS(4) 含む
─────
6+6+2+46+4 = 64

Linuxカーネルの定数がこの数え方を裏づけています。include/uapi/linux/if_ether.h の ETH_ZLEN は60(FCSを除いた最小)で、FCSの4オクテットを足すと64です。RFC 2544 が挙げるベンチマーク用のサイズ列 64, 128, 256, 512, 1024, 1280, 1518 も同じ数え方です。

つまりプリアンブルとSFDはフレームの一部として数えられていません。区切りを見つけるための仕掛けは、区切られた中身そのものには含まれない、という線引きです。

抽象原理

なぜ今も64オクテットなのか

ここで1つ、注意して扱うべき話があります。

この下限について「衝突検出のために必要だから」という説明が広く流通しています。1本のケーブルを共有していた半二重の環境で衝突が起こり得た、その名残であること自体は事実です。

しかし**「現代のスイッチ環境でも衝突検出のために必要だ」は成り立ちません。** 全二重では送信と受信が独立した経路を通るため、衝突が原理的に発生しないからです。RFC 3635 は衝突に関するカウンタすべてについて、全二重動作時にはインクリメントしないと明記しています。数えられていないのは、起きていないからです。

残っている理由はフレームの形式を変えないためです。最小サイズを変えることはフレームの形を変えることで、その利点より、既存の膨大な実装と話が通じなくなる不利益の方がはるかに大きい。由来となった事情が消えた後も、形だけが保存されています。

なお、この下限がもともとどういう計算から導かれたのか(最大ケーブル長と信号の往復時間の関係)については、方向性としては語られているものの、具体的な数値の導出はIEEE 802.3 の原典を確認する必要があります。本レッスンでは踏み込まず、「今なぜ残っているか」は後方互換性であるという点だけを確かなものとして扱います。

具体実物

上限の方 — MTU 1500

上限も見ておきます。1つのフレームで運べるペイロードの最大長が 1500オクテット、これをMTU(最大転送単位)と呼びます。近い数字が複数あって混乱しやすいので整理します。

1500 / 1514 / 1518 の違い表
値 範囲 カーネル定数
1500 ペイロードのみ ETH_DATA_LEN
1514 ヘッダ14 + ペイロード(FCS除く) ETH_FRAME_LEN
1518 上記 + FCS 4

「MTU 1500にヘッダが含まれる」という誤解がありますが、1500はペイロードだけです。どこで規定されているかははっきり辿れ、RFC 894 は「the maximum length of an IP datagram sent over an Ethernet is 1500 octets」と述べ、RFC 3635 も「The defined standard MTU for ethernet-like interfaces is 1500 octets」としています。

ただし条件が変わると数字も変わります。802.3 の LLC/SNAP を使う構成では上限が 1492 になり、RFC 1042 はこの値が1500と等しくないことをわざわざ注意しています。規格文書が念を押すほど取り違えられやすい箇所です。

なお1500を超えるジャンボフレーム(9000オクテットが多い)はIEEE 802.3 の標準に含まれません。対応機器は珍しくありませんが、9000という値も業界の慣行です。「規格で決まっているのだから経路途中の機器も対応しているはず」と考えると、1台の非対応機器で通信が成立しなくなります。

✓ ここまでの確認

Ethernetの最小フレームサイズ64オクテットには、どこからどこまでが含まれますか。

⇄ 2つを見比べる
具体例 A

Ethernet — 先頭の目印で区切る

流れてくるビット列に対し、先頭のパターン(プリアンブル+SFD)で「ここから」を示します。終わりの位置は、タイプ/長さフィールドやFCSの位置から決まります。区切りの情報は、データの外側に付けられた「枠」として存在します。

先頭に目印を置く方式コマンド出力
[10101010 x7][10101011][宛先MAC][送信元MAC][型][データ...][FCS]
└─ 同期 ──┘ └─ 区切り ┘ └──────── ここからが中身 ────────┘
 
・区切りの情報は中身の「外」にある
・中身にどんなビット列が現れても、区切りの判断は揺るがない
具体例 B

ファイルのレコード区切り — 中身に混ぜて区切る

テキストファイルでは改行文字が1行の終わりを表し、CSVではカンマが列を区切ります。区切りの情報はデータの流れの中に、中身と同じ文字として置かれます。そのため「中身にカンマが含まれていたら?」という問題が必ず発生し、引用符やエスケープという追加の規則が要ります。

中身に混ぜる方式コマンド出力
田中,営業部,東京
佐藤,"開発部,第2課",大阪
└──────────┘ ← 引用符が無いと、ここのカンマが区切りに見えてしまう
 
・区切り文字が中身にも現れ得るため、追加の規則(引用符・エスケープ)が必要
・その規則の解釈を1箇所間違えると、以降の列が全部ずれる

この2つは、どちらも「切れ目の無い連なりから1件分を切り出す」という同じ問題を解いています。それぞれ区切りの情報をどこに置いており、その違いは何を生んでいるでしょうか。

「区切りを表すものが、中身としても現れ得るかどうか」に注目してください。

この章のまとめ

  • ケーブルを流れるビット列には区切りが書かれていない。受信側が自力で「1通の始まり」を見つける必要がある。
  • Ethernetはこれを2段階で解く。プリアンブル(10101010 × 7オクテット)で同期し(古典的な10Mb/sのEthernetでの説明)、SFD(10101011)で区切りを確定させる。2つは別の仕事で、プリアンブルは開始位置を示さない。
  • SFDが合図になるのは、それまでの交番パターンを末尾の1ビットで破るから。規則を破って合図にするには、まず規則が共有されている必要がある。
  • 最小フレーム64オクテットは宛先MACからFCSまで。プリアンブルとSFDの8オクテットは含まれない(ETH_ZLEN 60 + FCS 4)。
  • 64オクテットが今も残る理由は後方互換性であって、衝突検出のためではない。全二重に衝突は発生しない(RFC 3635)。
  • MTU 1500はペイロードのみ。ヘッダ込み1514、FCS込み1518。LLC/SNAP構成では1492になる。ジャンボフレームは規格外。
  • 区切りの情報を中身の外に置くか(Ethernet)、中身に混ぜるか(CSVの改行やカンマ)は設計判断で、後者は必ずエスケープの問題を抱え込む。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 4正解: 0

SFD(スタートフレームデリミタ)のビットパターンはどれですか。

用語集(6語)
プリアンブル
フレーム本体の前に置かれる7オクテット。`10101010` の繰り返しで、受信側が送信側のクロックに同期する(クロック回復)ために使う。開始位置を示すものではない。
SFD (スタートフレームデリミタ)
プリアンブルの直後に置かれる1オクテット。`10101011` で、末尾の `1` が交番パターンを破ることにより「次のビットから宛先MACアドレス」と区切りを確定させる。
FCS (フレームチェックシーケンス)
フレーム末尾の4オクテット。伝送中にビットが化けていないかを検査するための値。最小フレーム64オクテットにはこのFCSまでが含まれる。
MTU (最大転送単位)
1つのフレームで運べるペイロードの最大長。Ethernetでは1500オクテット。ヘッダ14を足すと1514、さらにFCS 4を足すと1518になる。
フレーム間ギャップ (IPG)
フレームとフレームの間に置かれる12オクテット分の間隔。連続するフレームの境目に余白を設けるためのもの。
タイプ/長さフィールド
送信元MACアドレスの次に置かれる2オクテット。0x0600以上ならEtherType(中身のプロトコル種別)、0x05DC(1500)以下、つまり0x5DD未満なら長さとして解釈される(RFC 9542)。