# 通知設計書 43-RCTLルールマッチ通知

## 概要

本ドキュメントは、FreeBSD カーネルの RCTL（リソース制御）サブシステムが、プロセスのリソース使用量がリソース制御ルールの閾値を超過した際に発行する devctl 通知「RCTL / rule / matched」の設計を記述する。

### 本通知の処理概要

RCTL サブシステムにおいて、プロセスのリソース消費がルールで定義された上限を超えた際に、アクションとして devctl 通知を発行する。これにより、ユーザーランドでリソース超過イベントを検知し、適切な対応を自動化できる。

**業務上の目的・背景**：マルチテナント環境やサーバー運用において、プロセスやユーザー、jail のリソース使用量を監視・制御する必要がある。RCTL の「devctl」アクションは、リソース超過をリアルタイムに外部システムへ通知し、アラート発報やログ記録、自動対処を可能にする。deny（拒否）や signal（シグナル送信）と異なり、プロセスの動作を妨げずに監視できる非侵入的な手段を提供する。

**通知の送信タイミング**：rctl_enforce() 関数内で、プロセスのリソース使用量がルールの rr_amount を超過した際に、アクションが RCTL_ACTION_DEVCTL であるルールについて送信される。同一ルールに対しては、プロセスごとに 1 回のみ送信される（rrl_exceeded フラグにより重複抑止）。

**通知の受信者**：devd(8) デーモンを経由して、リソース監視ツールやアラートシステムが受信する。

**通知内容の概要**：マッチしたルール定義文字列、プロセスID、実効UID、jail 名が含まれる。

**期待されるアクション**：受信者はリソース超過を検知し、管理者への通知、ログ記録、自動スケーリング、プロセス優先度調整などのアクションを実行する。

## 通知種別

devctl カーネル通知（devd(8) 経由のシステムイベント通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（カーネル内 devctl_notify） |
| 優先度 | 中 |
| リトライ | 無（同一ルール・プロセスの組み合わせに対し 1 回のみ） |

### 送信先決定ロジック

devctl_notify() によりカーネルの devctl キューに投入される。devd(8) が受信する。

## 通知テンプレート

### devctl 通知フォーマット

| 項目 | 内容 |
|-----|------|
| system | RCTL |
| subsystem | rule |
| type | matched |
| data | rule=... pid=... ruid=... jail=... |

### 本文テンプレート

```
!system=RCTL subsystem=rule type=matched
rule=user:1001:vmemoryuse:devctl=1073741824/user pid=12345 ruid=1001 jail=default
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| rule | マッチしたルールの文字列表現 | rctl_rule_to_sbuf() | Yes |
| pid | プロセスID | p->p_pid | Yes |
| ruid | 実効UID | p->p_ucred->cr_ruid | Yes |
| jail | jail 名 | p->p_ucred->cr_prison->pr_prison_racct->prr_name | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| リソース制御 | rctl_enforce() でルール超過検知 | rr_action == RCTL_ACTION_DEVCTL かつ available < amount | リソース使用量がルール上限を超過 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| rrl_exceeded != 0 | 同一ルール・プロセスの組み合わせで既に通知済み |
| p->p_state != PRS_NORMAL | プロセス状態が正常でない場合（fork 中など） |
| ppsratecheck 失敗 | devctl_rate_limit（デフォルト 10 回/秒）を超過した場合 |
| メモリ割り当て失敗 | RCTL_LOG_BUFSIZE のバッファ確保に失敗 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[rctl_enforce 呼び出し] --> B[ルールリスト走査]
    B --> C{リソース超過?}
    C -->|No| B
    C -->|Yes| D{アクション = DEVCTL?}
    D -->|No| E[他のアクション処理]
    D -->|Yes| F{rrl_exceeded != 0?}
    F -->|Yes| B
    F -->|No| G{p_state == PRS_NORMAL?}
    G -->|No| B
    G -->|Yes| H{ppsratecheck OK?}
    H -->|No| B
    H -->|Yes| I[バッファ割り当て]
    I --> J{割り当て成功?}
    J -->|No| B
    J -->|Yes| K[sbuf にルール・PID・UID・jail を構築]
    K --> L[devctl_notify 発行]
    L --> M[rrl_exceeded = 1 に設定]
    M --> B
```

## データベース参照・更新仕様

### 参照テーブル一覧

カーネル内データ構造を参照する。

| 構造体 | 用途 | 備考 |
|-----------|------|------|
| struct rctl_rule | ルール定義（subject, resource, action, amount, per） | racct 経由で参照 |
| struct proc | プロセス情報 | p_pid, p_ucred |
| struct ucred | 認証情報 | cr_ruid, cr_prison |
| struct rctl_rule_link | ルールとracctの関連 | rrl_exceeded フラグ |

### 更新テーブル一覧

| 構造体フィールド | 操作 | 概要 |
|-----------|------|------|
| rrl_exceeded | UPDATE (= 1) | 通知済みフラグの設定 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| メモリ不足 | malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT) が NULL | printf でエラー出力し、通知をスキップ |
| レート制限 | rctl_devctl_rate_limit を超過 | 通知をスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1秒あたり上限 | kern.racct.rctl.devctl_rate_limit（デフォルト 10） |
| 重複抑止 | 同一ルール・プロセスの組み合わせに対し rrl_exceeded フラグで 1 回のみ |

### 配信時間帯

制限なし

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

- 通知にはプロセスID、UID、jail 名が含まれ、プロセスの識別情報が外部に公開される
- /dev/devctl の読み取りには root 権限が必要
- RCTL ルールの追加・削除には PRIV_RCTL_ADD_RULE / PRIV_RCTL_REMOVE_RULE 権限が必要
- カーネルに RACCT および RCTL オプションが有効であることが前提条件

## 備考

- RCTL_LOG_BUFSIZE は 128 バイトに定義されている。長いルール文字列の場合に切り詰めが発生する可能性がある
- rrl_exceeded フラグはリソース使用量が閾値以下に戻った場合にリセットされる（次回超過時に再度通知される）
- sysctl kern.racct.rctl.devctl_rate_limit でレート制限を動的に変更可能

---

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

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

### 推奨読解順序

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

RCTL のルール構造体と関連データ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rctl.h | `sys/sys/rctl.h` | struct rctl_rule の定義。rr_subject_type, rr_resource, rr_action, rr_amount, rr_per フィールド |
| 1-2 | kern_rctl.c | `sys/kern/kern_rctl.c` | struct rctl_rule_link（行128-132）。rrl_exceeded フラグの役割 |

**読解のコツ**: RCTL は subject（対象）, resource（リソース種別）, action（アクション）, amount（閾値）, per（単位）の 5 要素でルールが構成される。actionnames 配列（行174-210）で全アクション種別を確認できる。

#### Step 2: エントリーポイントを理解する

リソース超過チェックと通知発行の流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kern_rctl.c | `sys/kern/kern_rctl.c` | rctl_enforce()（行494-695）がリソース超過チェックのメイン関数 |

**主要処理フロー**:
1. **行513**: プロセスの racct ルールリストを走査開始
2. **行518-522**: リソース使用量と閾値の比較
3. **行566-594**: RCTL_ACTION_DEVCTL の処理ブロック
4. **行577-578**: バッファ割り当て（M_NOWAIT）
5. **行582-590**: sbuf にルール文字列、PID、UID、jail 名を構築
6. **行589-590**: devctl_notify("RCTL", "rule", "matched", ...) 発行
7. **行593**: rrl_exceeded = 1 に設定

#### Step 3: ルール文字列の構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kern_rctl.c | `sys/kern/kern_rctl.c` | rctl_rule_to_sbuf()（行1476-1530）がルールの文字列表現を構築 |

**主要処理フロー**:
- **行1482**: subject_type 名の出力
- **行1484-1516**: subject_type に応じた ID の出力
- **行1523-1526**: resource名:action名=amount の出力
- **行1528-1529**: per が subject_type と異なる場合のみ per を出力

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

```
rctl_enforce()                             [行494: リソース超過チェック]
    |
    +-- rctl_available_resource()           [行357: 利用可能リソース計算]
    |
    +-- [RCTL_ACTION_DEVCTL の場合]
            |
            +-- rctl_rule_to_sbuf()        [行1476: ルール文字列構築]
            +-- devctl_notify()            [行589: 通知発行]
```

### データフロー図

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

リソース割り当て要求 ---> rctl_enforce()               ---> devctl キュー
                              |                               |
struct rctl_rule --------> available = amount - used      devd(8) 受信
struct proc             -> sbuf: rule, pid, ruid, jail
struct racct
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kern_rctl.c | `sys/kern/kern_rctl.c` | ソース | RCTL サブシステム実装。通知発行元 |
| rctl.h | `sys/sys/rctl.h` | ヘッダー | RCTL ルール構造体定義 |
| racct.h | `sys/sys/racct.h` | ヘッダー | リソースアカウンティング定義 |
| subr_bus.c | `sys/kern/subr_bus.c` | ソース | devctl_notify() 実装 |
