コンテンツにスキップ

Topics で読み物として読む

この HLD は実装詳細を含みます。機能の概念・設定・運用を読み物として読みたい場合は Topics 04 章: VRF / ECMP / 経路選択 を参照。

裏取りステータス: code-verified

Verifier 2026-05-09: sonic-swss/orchagent/fgnhgorch.{cpp,h} の現行実装、sonic-buildimage/src/sonic-yang-models/yang-models/sonic-fine-grained-ecmp.yangmatch_modeprefix-based を含む Rev 1.5 後の追加分も収容)、sonic-sairedis/vslib/SwitchStateBase.cpp:4165SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP capability 列挙を確認し HLD と整合。

Fine Grained ECMP(FG_NHG / fgnhgorch)

読者が知りたいこと

  • 通常 ECMP と何が違うのか、いつ FG ECMP を選ぶ べきか
  • 3 つの match_mode(route-based / nexthop-based / prefix-based)の違い
  • CONFIG_DB のキーbucket_size の決め方
  • 内部で どの orch / SAI 属性 が動くか、warm boot で何が残るか
  • スケールと既知の落とし穴

1. いつ FG ECMP を使うか

通常 ECMP は next-hop が増減するたびに hash redistribution が全 flow に波及 する。loadbalanced VM / firewall 群のように next-hop 単位で flow stickiness と bank(共有状態グループ)を保つ必要があるトポロジ では、これが致命的になる。

FG ECMP は ASIC 上に hash bucket(SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX)を明示的に作り、消えた next-hop が占めていたバケットだけを同 bank 内の生存 next-hop で埋め直す ことで bank 内 consistent hashing を実現する1

2. match_mode 3 種

match_mode FG ECMP の発火条件
route-based route prefix が FG_NHG_PREFIX と一致 かつ next-hop が FG_NHG_MEMBER に含まれる
nexthop-based next-hop IP が FG_NHG_MEMBER のサブセット
prefix-based route prefix が FG_NHG_PREFIX に一致(next-hop は route 学習で動的)

prefix-based は Rev 1.5 で追加され、FG_NHG.max_next_hops を持つ。FG_NHG_MEMBER は使わない1

3. CONFIG_DB と CLI

FG_NHG|<group>:
    bucket_size      = <int>
    match_mode       = route-based | nexthop-based | prefix-based
    max_next_hops    = <int>   # prefix-based のみ

FG_NHG_PREFIX|<v4|v6 prefix>:
    FG_NHG = <group>

FG_NHG_MEMBER|<nexthop-ip>:
    FG_NHG = <group>
    bank   = <int>          # bank 内で再分配
    link   = <ifname>       # OPTIONAL: link down で nh withdraw

bucket_size の決め方: 「想定する次ホップ数の組み合わせの最小公倍数」。例: 2 bank × 各 3 NH → LCM(1,2,3) * 2 = 121

Command 用途
config fg-nhg add/del <group> --match-mode --bucket-size --max-next-hops グループ作成/削除
config fg-nhg-prefix add/del <prefix> --fg-nhg <group> プレフィックス紐付け
config fg-nhg-member add/del <nh-ip> --fg-nhg <group> メンバー追加/削除(route/nexthop モード)
show fgnhg hash-view [<group>] bucket → NH のマッピング表示
show fgnhg active-hops [<group>] bank ごとの active NH 表示

設定例(route-based, 2 bank × 3 NH)

{
  "FG_NHG":  { "2-VM-Sets": { "bucket_size": 12, "match_mode": "route-based" } },
  "FG_NHG_PREFIX": { "10.10.10.10/32": { "FG_NHG": "2-VM-Sets" } },
  "FG_NHG_MEMBER": {
    "1.1.1.1": { "FG_NHG": "2-VM-Sets", "bank": 0, "link": "Ethernet4" },
    "1.1.1.4": { "FG_NHG": "2-VM-Sets", "bank": 1, "link": "Ethernet16" }
  }
}

4. データフローと bank 動作

flowchart LR
    USER[(CONFIG_DB\nFG_NHG /\nFG_NHG_PREFIX /\nFG_NHG_MEMBER)] --> FGORCH[fgnhgorch]
    BGP[FRR / bgpd] --> APP[(APPL_DB\nROUTE_TABLE)]
    APP --> ROUTEORCH[routeorch]
    ROUTEORCH -- match した route を委譲 --> FGORCH
    PORTS[portsorch] -- SUBJECT_TYPE_PORT_OPER_STATE_CHANGE --> FGORCH
    FGORCH -->|hash bucket 配置決定| SAI[(SAI NHG\nFINE_GRAIN_ECMP)]
    FGORCH -->|hash バケット ↔ NH| STATE[(STATE_DB\nFG_ROUTE_TABLE)]
    STATE --> CLI[show fgnhg hash-view / active-hops]

要点:

  • routeorch は通常通り APP_DB route 更新を処理しつつ、FG ECMP 設定にマッチする route を fgnhgorch に redirect1
  • fgnhgorch は portsorch の SUBJECT_TYPE_PORT_OPER_STATE_CHANGE を購読し、FG_NHG_MEMBER.link 紐付き link down/up で NH を出し入れ1
  • ASIC 上の bucket 配置は STATE_DB.FG_ROUTE_TABLE にミラー(warm reboot 復元と show CLI 用)1

bank 内 consistent hashing:

  • next-hop down: 同 bank 内の生存 NH に「down した NH のバケットだけ」を均等再配布。bank 内ゼロのときのみ対向 bank に流す("entire VM set down" シナリオ)1
  • next-hop add: bank 内に生存 NH があれば新規 NH に均等にバケットを返す。ゼロ → 1 復活時は対向 bank から戻す
  • prefix-based: BGP 学習で動的に取得した NH のうち先着 max_next_hops までを対象1

5. SAI とのインタフェース

SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP
SAI_NEXT_HOP_GROUP_ATTR_CONFIGURED_SIZE
SAI_NEXT_HOP_GROUP_ATTR_REAL_SIZE
SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID
SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX     # bucket index

通常 ECMP NHG 型ではなく FINE_GRAIN_ECMP を使い、member に INDEX を明示 する点が SAI 上の差分1

6. Warm boot

STATE_DB.FG_ROUTE_TABLE を fast-reboot dump に含めて保存し、起動後に 同一の bucket → NH マッピング で ECMP group を再構築する1。これが無いと NH 追加順序の非決定性で bucket index がぶれ、flow が乱れる。

7. 制限事項

  • スケール: グループ数 8、bucket size は HW 依存(最大 4k)1
  • 全 prefix に consistent ECMP を効かせる「動的有効化」は HLD スコープ外1
  • route/nexthop モードでは FG_NHG_MEMBER 未定義の NH は 黙って ASIC に伝播されない(syslog エラーのみ)1

8. 干渉する機能

  • routeorch / NHG: 通常 ECMP NHG 型と排他。同一 prefix を両方で扱おうとすると FG 側が優先
  • portsorch: link 付き member は port oper state に従って NH を出し入れ
  • warm reboot: FG_ROUTE_TABLE 永続化が前提

9. トラブルシューティング

  • 期待する NH が ASIC に出ていない → show fgnhg active-hopsFG_NHG_MEMBER 定義と一致するか確認。route/nexthop モードでは未定義 NH は無視
  • bucket がぶれる → STATE_DB.FG_ROUTE_TABLE を直接確認。warm reboot 後に空ならダンプ経路の不整合

コマンド例

Fine-grained ECMP (FG NHG) の bucket 配分を確認する。

show fgnhg active-hops
show fgnhg hash-view
redis-cli -n 4 keys 'FG_NHG*'

10. 次に読む

制限事項

  • FG-ECMP は per-prefix の hash bucket 制御を SAI 経由で行うため、ASIC が SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP を未サポートだと有効化できない。
  • bucket 数は platform 依存 (典型的に 16 / 64 / 256) で、FG_NHG テーブルで指定したサイズと一致しない場合は flap 時の影響範囲が変わる。
  • inactive nexthop の bucket 入れ替え動作は実装/HLD 間で差異が報告されており、saidump で実際の bucket 配列を検証することを推奨。

引用元

📋 検証エビデンス: sonic-net/SONiC/doc/ecmp/fine_grained_next_hop_hld.md#L344-L352 (sha: 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06)

出典:

sonic-net/SONiC/doc/ecmp/fine_grained_next_hop_hld.md#L344-L352 (sha: 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06)

抜粋:

A key idea ... is the creation of many hash buckets ... having a next-hop repeated multiple times within it.
... in the route/nexthop match modes, by pushing configuration with next-hop bank membership, we can ensure
that we only refill the affected hash buckets with those next-hops within the same bank.

判断根拠: bank 内 consistent hashing と「同 bank 内のみで refill」原則の根拠。

関連 Topics


  1. sonic-net/SONiC doc/ecmp/fine_grained_next_hop_hld.md @ 49bab5b5ff0e924f1ea52b3d9db0dfa4191a7c06