コンテンツにスキップ

Topics で読み物として読む

この HLD は実装詳細を含みます。機能の概念・設定・運用を読み物として読みたい場合は Topics 10 章: gNMI / OpenConfig / 管理プレーン を参照。

裏取りステータス: Code-verified(命名差分あり)

sonic-pins/p4rt_app/p4runtime/p4runtime_impl.cc および p4runtime_read.cc で実装を確認。HLD の table_entry_cache_ は実装では entity_cache_(type は absl::flat_hash_map<pdpi::EntityKey, p4::v1::Entity>)に汎化されており、TableEntry に加え PacketReplicationEngineEntry も保持する。Write 連動更新は UpdateCacheAndUtilizationState(INSERT/MODIFY 反映 + DELETE で erase)、Read は entity_cache_ 走査で AppDb を見ない経路 (p4runtime_read.cc AppendTableEntryReads)、検証ロジックは P4RuntimeImpl::VerifyState()VerifyP4rtTableWithCacheEntities を呼ぶ実装を確認。warm boot は warm_boot_state_adapter_ でフレームワーク化済み(HLD 記載の事前充填案を踏まえた基盤)(verified at: 2026-05-09)。

P4RT App の Read キャッシュ(PI 形式の table_entry_cache_)

概要

P4 Runtime (P4RT) サーバはコントローラから 3 種の操作(Stream / Write / Read)を受ける。SONiC の P4RT App は 1 リクエスト同時実行 モデルで動くため、Read が遅いと Write を含む他リクエストが詰まる1

実測では 16,000 フローの Read で 約 1.30s を要し、その大半(1.28s)が AppDb (Redis) の HGETALL を 16,000 回叩く時間で消える。さらに Redis の生データを Platform Independent (PI) 形式へ変換する処理にも一定時間がかかる1

本機能は P4RT App プロセス内に PI 形式そのままを保持するキャッシュ を持たせ、Read 時には Redis にアクセスせずキャッシュから直接返す。実測では同等のフロー数で Read が 40ms(約 40 倍高速化)に短縮される1

動作仕様

キャッシュ実体

absl::flat_hash_map<TableEntryKey, p4::v1::TableEntry> table_entry_cache_;

Key は TableEntryKey(テーブル + match key の合成)、値は PI 形式の p4::v1::TableEntry。Read リクエスト時の翻訳コストをゼロにするため、書き込み時点で PI に変換した状態で持つ1

Write 連動

P4Orch から成功応答が返ったら、Write 種別に応じてキャッシュを更新する1:

Write 種別 結果 キャッシュ操作
any FAIL 何もしない
INSERT SUCCESS 新規 PI エントリ追加
MODIFY SUCCESS 既存 PI エントリ更新
DELETE SUCCESS 既存 PI エントリ削除
sequenceDiagram
  participant Ctrl as Controller
  participant P4RT as P4RT App
  participant P4O as P4Orch
  participant DB as AppDB (Redis)
  Ctrl->>P4RT: Write(INSERT|MODIFY|DELETE)
  P4RT->>P4O: 反映依頼
  P4O->>DB: P4RT_TABLE 更新
  P4O-->>P4RT: SUCCESS
  P4RT->>P4RT: table_entry_cache_ を更新
  Ctrl->>P4RT: Read
  P4RT-->>Ctrl: cache から PI を直接返却 (40ms)

Read

Read リクエストは Redis を見ずキャッシュを直接走査して返す。これにより KEYS P4RT_TABLE:* + HGETALL ループの O(N) Redis 往復が消える1

キャッシュと AppDb の同期検証

P4Orch は P4 エントリを 独自に書き換えない 想定なので、定常的なポーリングは不要1。ただし「2 つの Source of Truth」が原理的に存在するため、HLD は明示的に 検証ロジック を組み込むと述べる1:

  1. Redis の全 P4RT_TABLE エントリを読む
  2. 各エントリを PI 形式に変換
  3. キャッシュと比較
  4. 差分(片方にしかない / 値違い)をレポート

実行頻度はオペレータが設定する。

Warm boot

P4RT App は現時点で warm boot 未対応だが、対応する際は 既存の Redis 読み出し経路を再利用してキャッシュを事前充填 する設計を HLD は提示している1

📋 検証エビデンス: sonic-net/SONiC/doc/pins/p4rt_app_read_cache_hld.md#L40-L58 (sha: 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06)

出典:

sonic-net/SONiC/doc/pins/p4rt_app_read_cache_hld.md#L40-L58 (sha: 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06)

抜粋:

The cache will be updated for each P4RT App write request based on the P4Orch agents response.
... INSERT/SUCCESS -> Create a new PI entry; MODIFY/SUCCESS -> Update; DELETE/SUCCESS -> Remove
... we will also implement verification logic that ensures the cache and AppDb entries are in sync.

判断根拠: Write 連動更新ルールと検証ロジックの根拠。

性能測定(HLD 添付)

実験 内容 Read 時間
Exp.1 (cache 無し) 16,000 フロー end-to-end Read ~1.30s(うち 1.28s が Redis 読み)
Exp.2 (cache 無し) 22,152 フロー、種別混在。Redis 読み 1.27s + PI 変換 0.29s ~1.60s
Exp.3 (cache 有り) 22,152 フロー(VRF 64, RIF 64, Neighbor 512, Nexthop 512, IPv4 10000, IPv6 10000, WCMP 1000×2) 40ms

PI 形式キャッシュのメモリ占有1:

エントリ種別 1 件あたり 合計(Exp.3 の規模)
VRF ~29 B ~1.8 KB
RIF ~61 B ~4 KB
Neighbor ~79 B ~40 KB
Nexthop ~91 B ~47 KB
IPv4 ~68 B ~685 KB
IPv6 ~80 B ~805 KB
WCMP ~100 B ~100 KB

数十万エントリ規模でも MB オーダの追加メモリで済む見積。

設定

関連する CONFIG_DB / CLI / YANG

本機能はプロセス内最適化であり、CONFIG_DB / CLI / YANG への外部表面は持たない。設定項目は HLD 上では言及されていない(オン/オフのフラグや検証頻度の設定有無は実装依存)。

設定例

該当なし(コードビルド時の機能)。

制限事項

  • 2 つの Source of Truth リスク: cache と AppDb がずれる可能性は構造上ゼロにできない。HLD は検証ロジックでの突合を必須としている1
  • Warm boot は未対応: 現時点で P4RT App が warm boot 未対応のため、再起動でキャッシュは消える。前述の事前充填策は将来の対応案1
  • メモリ消費: PI 形式の保持で常駐メモリが増える。HLD の見積では数十万エントリで数 MB だが、ACL 等で大規模化するとさらに増える。

干渉する機能

  • P4Orch / SWSS: P4Orch が P4RT App を経由せずに P4RT_TABLE を書き換えると cache が古くなる。HLD は P4Orch が独自書き換えしない前提を置く1
  • P4RT 同時 1 リクエスト制約: cache 化は本質的に「1 リクエスト直列処理ゆえに Read 遅延が他を阻害する」ことへの対症療法。同時実行モデルへの移行は別議論。
  • ACL counters: 既存実装は ACL エントリの counter を CountersDb から読みに行く。cache がこれをどうカバーするか HLD は明記していない(counter は別経路で取得する想定と読める)。

トラブルシューティング

  • 検証ロジックが差分を報告する: P4Orch 側が独自に AppDb を書き換えていないか確認。または cache 更新タイミングの race を疑う。
  • Read が依然遅い: cache 自体が無効化されている、または初回起動時で cache 未充填の可能性。
  • メモリ増加が想定外: エントリ種別ごとの 1 件サイズ(前掲表)を参考に、実際のフロー数と突き合わせる。

確認コマンド例:

# P4RT controller 接続/cache 状態
docker ps | grep p4rt
docker logs p4rt 2>&1 | tail
redis-cli -n 4 hgetall 'P4RT_TABLE|*'

引用元

関連 Topics

運用入口

この HLD に対応する運用面の入口(CLI / CONFIG_DB / YANG / Runbook)を以下にまとめる。

関連 Runbook


  1. sonic-net/SONiC doc/pins/p4rt_app_read_cache_hld.md @ 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06