# 機能設計書 37-ブリッジング

## 概要

本ドキュメントは、FreeBSDカーネルにおけるイーサネットブリッジ機能（L2スイッチング）の機能設計書である。if_bridge.cおよびbridgestp.cで実装されるネットワークブリッジドライバの設計を記述する。

### 本機能の処理概要

FreeBSDのブリッジ機能は、複数のイーサネットインタフェースをレイヤ2（データリンク層）で接続し、MACアドレス学習とフレーム転送を行うカーネルモジュールである。IEEE 802.1D Spanning Tree Protocol (STP)もサポートする。

**業務上の目的・背景**：物理的に分離された複数のイーサネットセグメントを論理的に1つのブロードキャストドメインに統合するために使用される。仮想マシンのネットワーク接続、ネットワークの冗長化、トランスペアレントファイアウォールの構築などで必要となる。

**機能の利用シーン**：bhyve仮想マシンのネットワーク接続、jail環境のネットワーク構成、物理セグメント間のブリッジング、STPによるループ防止構成、SPAN（ポートミラーリング）によるパケットキャプチャで利用される。

**主要な処理内容**：
1. ブリッジインタフェースの作成・削除（ifconfig bridgeN create/destroy）
2. メンバーインタフェースの追加・削除
3. MACアドレス学習テーブル（フォワーディングデータベース）の管理
4. イーサネットフレームの受信・学習・転送・フラッディング
5. IEEE 802.1D Spanning Tree Protocol (STP)
6. Rapid STP (RSTP) - IEEE 802.1w
7. SPANポート（ミラーリング）
8. インタフェースフラグ制御（learning, discover, stp, edge等）
9. IPv4/IPv6フィルタリング（pfil連携）

**関連システム・外部連携**：ifconfig（ブリッジ管理）、pfil（パケットフィルタ連携）、IPFW/PF（ファイアウォール）、VLAN

**権限による制御**：ブリッジの作成・設定にはroot権限（PRIV_NET_BRIDGE）が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | カーネルモジュールのため該当する画面なし |

## 機能種別

カーネルネットワーク機能（L2フレーム転送 / MACアドレス学習 / STP）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ioctl コマンド | int | Yes | BRDGADD/BRDGDEL/BRDGFLUSH等 | 有効なioctl番号 |
| メンバーIF名 | string | 条件付 | 追加/削除するインタフェース名 | 存在するイーサネット系IF |
| STPパラメータ | struct | No | priority, hello time, forward delay等 | 有効な範囲 |

### 入力データソース

ifconfigコマンド（ioctl経由）、受信イーサネットフレーム

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 転送フレーム | mbuf | 宛先インタフェースへの転送データ |
| フラッディング | mbuf | 全メンバーIFへのブロードキャスト/不明宛先フレーム |
| SPANコピー | mbuf | SPANポートへのミラーリングコピー |

### 出力先

メンバーインタフェース（フレーム転送）

## 処理フロー

### 処理シーケンス

```
1. ブリッジメンバーIFでフレーム受信
   └─ bridge_input() がNICドライバから呼ばれる
2. 送信元MACアドレスの学習
   └─ フォワーディングテーブルにエントリ追加/更新
3. 宛先MACアドレスの検索
   ├─ ユニキャスト: フォワーディングテーブルで出力IF特定
   └─ ブロードキャスト/不明: 全メンバーIFにフラッディング
4. STPチェック
   └─ ポート状態（forwarding/blocking/learning等）に基づく転送判定
5. pfil（パケットフィルタ）フック
   └─ IPFW/PF等のファイアウォールルール適用
6. フレーム転送/フラッディング
   └─ bridge_enqueue() でメンバーIFに送信
```

### フローチャート

```mermaid
flowchart TD
    A[フレーム受信] --> B[bridge_input]
    B --> C[送信元MAC学習]
    C --> D{宛先MAC検索}
    D -->|既知ユニキャスト| E[特定IFへ転送]
    D -->|ブロードキャスト/不明| F[全IFへフラッディング]
    E --> G{STPポート状態}
    F --> G
    G -->|forwarding| H[pfil フック]
    G -->|blocking| I[破棄]
    H --> J{フィルタ結果}
    J -->|許可| K[bridge_enqueue]
    J -->|拒否| I
    K --> L[IF出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | MAC学習 | 受信フレームの送信元MACアドレスとポートの対応を学習テーブルに記録 | フレーム受信時 |
| BR-37-02 | エージング | 学習テーブルエントリは一定時間後にタイムアウト削除 | タイマー満了時 |
| BR-37-03 | STP状態遷移 | disabled→blocking→listening→learning→forwardingの状態遷移 | STP有効時 |
| BR-37-04 | SPANポート | SPANポートには全フレームのコピーが送信されるが、受信は無視 | SPAN設定時 |

### 計算ロジック

STPのブリッジIDはプライオリティ(16bit)+MACアドレス(48bit)で構成。ルートブリッジ選出はブリッジIDの比較による。

## データベース操作仕様

該当なし（カーネル内メモリ上のフォワーディングテーブル）

### 操作別データベース影響一覧

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOENT | メンバーなし | 存在しないインタフェースの追加 | IF名確認 |
| EBUSY | 使用中 | 既に他のブリッジのメンバー | メンバーシップ確認 |
| ELOOP | ループ | ブリッジのブリッジへのネスト | 構成変更 |
| EPERM | 権限不足 | 非root権限での設定変更 | root権限で実行 |

### リトライ仕様

なし

## トランザクション仕様

各ioctl操作はアトミック。STPの状態遷移はタイマーに基づく非同期処理。

## パフォーマンス要件

フォワーディングテーブル参照はハッシュテーブルで実装され、O(1)の検索性能を提供する。

## セキュリティ考慮事項

- ブリッジ設定変更にはPRIV_NET_BRIDGE権限が必要
- pfil連携によりブリッジフレームにファイアウォールルールを適用可能
- STPのBPDU処理により不正なトポロジー変更を防止

## 備考

FreeBSDのブリッジ実装はNetBSD由来であり、if_bridge.cが主要な処理を、bridgestp.cがSTP/RSTP処理を担当する。Ethernet系インタフェースのみサポートする。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | if_bridgevar.h | `sys/net/if_bridgevar.h` | struct bridge_softc（ブリッジ全体）、struct bridge_iflist（メンバーIF）、struct bridge_rtnode（学習テーブルエントリ） |
| 1-2 | if_bridge.c | `sys/net/if_bridge.c` | ヘッダincludeと定数定義 |

**読解のコツ**: bridge_softcがブリッジインスタンスの全情報を保持し、bridge_iflistがメンバーIFのリスト、bridge_rtnodeがMACアドレス学習テーブルのエントリである。

#### Step 2: フレーム受信・転送処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | if_bridge.c | `sys/net/if_bridge.c` | bridge_input()（受信処理）、bridge_forward()（転送処理）、bridge_broadcast()（フラッディング） |

**主要処理フロー**:
- bridge_input(): メンバーIFからのフレーム受信、送信元MAC学習、宛先判定
- bridge_forward(): ユニキャストフレームの特定IFへの転送
- bridge_broadcast(): ブロードキャスト/マルチキャスト/不明宛先のフラッディング

#### Step 3: STP処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | bridgestp.c | `sys/net/bridgestp.c` | STP/RSTPの状態遷移、BPDU処理、タイマー管理 |

### プログラム呼び出し階層図

```
[受信パス]
NICドライバ → bridge_input() [if_bridge.c]
    +-- bridge_rtupdate() - 送信元MAC学習
    +-- bridge_rtlookup() - 宛先MAC検索
    |
    +-- [ユニキャスト]
    |   +-- bridge_forward()
    |       +-- pfil_bridge_*() - フィルタリング
    |       +-- bridge_enqueue() - IF出力
    |
    +-- [ブロードキャスト/不明]
        +-- bridge_broadcast()
            +-- 各メンバーIFへbridge_enqueue()

[STP]
bstp_received_bpdu() [bridgestp.c]
    +-- bstp_update_info()
    +-- bstp_set_port_state()
    +-- bstp_timer_*() - タイマー管理
```

### データフロー図

```
[入力]                     [処理]                          [出力]

受信フレーム ──────> bridge_input()
                         |
                    MAC学習テーブル更新
                         |
                    宛先MAC検索
                         |
                    +----+----+
                    |         |
               ユニキャスト   B/Mキャスト
                    |         |
              bridge_forward  bridge_broadcast
                    |         |
               pfil フック    pfil フック
                    |         |
               特定IF出力    全IF出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| if_bridge.c | `sys/net/if_bridge.c` | ソース | ブリッジドライバ主処理 |
| bridgestp.c | `sys/net/bridgestp.c` | ソース | STP/RSTP処理 |
| if_bridgevar.h | `sys/net/if_bridgevar.h` | ヘッダ | ブリッジ構造体定義 |
| ifbridge.c | `sbin/ifconfig/ifbridge.c` | ソース | ifconfigブリッジ設定モジュール |
