Next Hop Group on SONiC
SONiC Advent Calendar 2022 Day 5
SONiC.202111 で追加された "Better route scalability with multiple next-hops" 機能を解説します。
- High Level Design (HLD): Routing and Next Hop Table Enhancement
- PR (SONiC): Next hop group split HLD #712
- PR (sonic-swss): [orchagent] Add separate next hop table and orch #1702
Next Hop Group とは?
ホスト(Linux等)や Switch/Router によらず、パケットを送信・転送する場合は通常 FIB (Forwarding Information Base) や Routing Table と呼ばれるテーブルを参照し、パケットの宛先アドレスを Key として次に到達すべき宛先を Lookup します。
この "次に到達すべき宛先" が nexthop と呼ばれます。
FIB エントリ(route object)は Lookup 対象となるプレフィックス/長さ(Prefix/Len)と、nexthop のアドレス、送信インターフェース(デバイス)、等の情報を保持します。
この route object のフォーマットは実装により様々であり、例えば Linux Kernel の場合は v5.2 以前は nexthop 情報を route object の一部として保持していますが、v5.3 からは route object と nexthop object を分離しています。
ある宛先(Prefix/Len)の nexthop が複数ある場合は Multipath とも呼ばれます。
Multipath の場合、 route object と nexthop object を分離して保持しする事により、nexthop を複数の route で共有(参照)する事が可能となるため、以下メリットがあります。
- メモリ消費量の削減
- 追加・更新に必要な時間の短縮
- Prefix/Len と nexthop で異なるアドレスファミリーを利用(e.g. IPv4, IPv6)
特に、エントリの更新コスト(Network OS -> ASIC の通信コスト)が大きい Switch/Router 等のハードウェア機器では、route と nexthop を分離し別々のテーブルで管理する事によりパフォーマンスやリソース(SRAM/TCAM)消費量の節約といった大きなメリットがあるため、多くの実装で分離して管理されています。
SONiC の Multipath 設定方法は2種類
SONiC における Multipath の設定方法は、 "CLIの有無" や "APPL_DB形式" が異なる2種類の方式あります。どちらの設定方法でも ASIC_DB は同じエントリとなります。
従来の方法(図・左)
設定方法:CLIから config コマンドを使用して設定可能です。
config route add prefix 10.99.0.0/24 nexthop 10.0.0.100
config route add prefix 10.99.0.0/24 nexthop 10.0.0.101
APPL_DB には、 ROUTE_TABLE エントリに nexthop に関する情報を "列挙" します。(CLIで設定すると自動的に生成されます)
Next Hop Group を用いる方法(図・右)
設定方法:CLIから設定はできず、直接 APPL_DB にエントリを追加する必要があります。
APPL_DB には、 NEXT_HOP_GROUP_TABLE エントリを作成し、ROUTE_TABLE からそのエントリ(ID)を参照します。具体的には、 ROUTE_TABLE エントリの nexthop_group
に NEXT_HOP_GROUP_TABLE エントリの Key (e.g. nhg1
)を ID として指定します。
Next Hop Group: APPL_DB エントリ追加方法
APPL_DB へのエントリ追加方法を3種類ご紹介します。
-
swssconfig
コマンド(swssコンテナ) -
sonic-db-cli
コマンド(ホスト) - Python スクリプト(ホスト)
例として、NEXT_HOP_GROUP_TABLE エントリを追加しています。
パケット転送を試す際には、NEXT_HOP_GROUP_TABLE に加えて、ROUTE_TABLE に ROUTE_TABLE:10.99.0.0/24 {'nexthop_group': 'nhg1'}
エントリを追加しましょう。
(sonic-db-cli
コマンドに例示しています)
swssconfig
コマンド(swssコンテナ)
APPL_DB へのエントリの追加は swss コンテナ上で swssconfig <xxxx.json>
コマンドを実行する事で可能です。(JSONファイルを docker cp
で swss コンテナにコピーして実行)
admin@sonic:~$ cat nhg88.json
[
{
"NEXTHOP_GROUP_TABLE:nhg88": {
"nexthop": "10.0.0.100,10.0.0.101", "ifname": "Ethernet0,Ethernet0"
},
"OP": "SET"
}
]
admin@sonic:~$ docker cp nhg88.json swss:.
admin@sonic:~$ docker exec -it swss swssconfig nhg88.json
admin@sonic:~$ sonic-db-cli APPL_DB HGETALL NEXTHOP_GROUP_TABLE:nhg88
{'ifname': 'Ethernet0,Ethernet0', 'nexthop': '10.0.0.100,10.0.0.101'}
sonic-db-cli
コマンド(ホスト)
sonic-db-cli
コマンドを利用して追加する事も可能です。
admin@sonic:~$ sonic-db-cli APPL_DB HSET NEXTHOP_GROUP_TABLE:nhg99 \
'nexthop' '10.0.0.100,10.0.0.101' \
'ifname' 'Ethernet0,Ethernet0'
2
admin@sonic:~$ sonic-db-cli APPL_DB HGETALL NEXTHOP_GROUP_TABLE:nhg99
{'nexthop': '10.0.0.100,10.0.0.101', 'ifname': 'Ethernet0,Ethernet0'}
Route Object の追加方法も例示します。
admin@sonic:~/script$ sonic-db-cli APPL_DB HSET \
ROUTE_TABLE:10.99.0.0/24 'nexthop_group' 'nhg99'
1
admin@sonic:~/script$ sonic-db-cli APPL_DB HGETALL ROUTE_TABLE:10.99.0.0/24
{'nexthop_group': 'nhg99'}
Python スクリプト(ホスト)
admin@sonic:~$ cat nhg_push_appldb.py
#!/usr/bin/python3
from swsscommon import swsscommon
db = swsscommon.DBConnector("APPL_DB", 0, True)
table = swsscommon.ProducerStateTable(db, "NEXTHOP_GROUP_TABLE")
key = "nhg1"
fieldValues = {"nexthop": "10.0.0.100,10.0.0.101", "ifname": "Ethernet0,Ethernet0"}
fvs = swsscommon.FieldValuePairs(list(fieldValues.items()))
table.set(key, fvs)
admin@sonic:~$ ./nhg_push_appldb.py
admin@sonic:~$ sonic-db-cli APPL_DB HGETALL NEXTHOP_GROUP_TABLE:nhg1
{'nexthop': '10.0.0.100,10.0.0.101', 'ifname': 'Ethernet0,Ethernet0'}
Next Hop Group: ASIC_DB エントリ
APPL_DB に nexthop, route object のエントリを追加すると、swss/orchagent により ASIC_DB にエントリが追加されます。
例として、以下 APPL_DB エントリを追加した際の ASIC_DB エントリを図示します。
> APPL_DB entry
ROUTE_TABLE:10.99.0.0/24 {'nexthop_group': 'nhg1'}
NEXTHOP_GROUP_TABLE:nhg1 {'nexthop': '10.0.0.100,10.0.0.101', 'ifname': 'Ethernet0,Ethernet0'}
図のように、APPL_DB の NEXT_HOP_GROUP エントリは、ASIC_DB では NEXT_HOP, NEXT_HOP_GROUP_MEMBER, NEXT_HOP_GROUP の3種類のエントリになります。
Next Hop や Next Hop Group の object id (oid) は自動的に採番されます。
図中では簡略化のために1桁の数字で記載していますが、実際は後述の通り 0x2d0000000003a9 といった数値となります。
ASIC_DBのエントリは sonic-db-cli
コマンドを利用して確認できます。
admin@sonic:~/script$ sonic-db-cli APPL_DB HGETALL NEXTHOP_GROUP_TABLE:nhg1
{'nexthop': '10.0.0.100,10.0.0.101', 'ifname': 'Ethernet0,Ethernet0'}
admin@sonic:~/script$ sonic-db-cli ASIC_DB keys \* | grep NEXT
ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d0000000003a9
ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP:oid:0x50000000003a8
ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d0000000003aa
ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000003a7
ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000003a5
admin@sonic:~/script$ sonic-db-cli ASIC_DB HGETALL ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP:oid:0x50000000003a8
{'SAI_NEXT_HOP_GROUP_ATTR_TYPE': 'SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP'}
admin@sonic:~/script$ sonic-db-cli ASIC_DB HGETALL ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d0000000003a9
{'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID': 'oid:0x50000000003a8', 'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID': 'oid:0x40000000003a5'}
admin@sonic:~/script$ sonic-db-cli ASIC_DB HGETALL ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:oid:0x2d0000000003aa
{'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID': 'oid:0x50000000003a8', 'SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID': 'oid:0x40000000003a7'}
admin@sonic:~/script$ sonic-db-cli ASIC_DB HGETALL ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000003a5
{'SAI_NEXT_HOP_ATTR_TYPE': 'SAI_NEXT_HOP_TYPE_IP', 'SAI_NEXT_HOP_ATTR_IP': '10.0.0.100', 'SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID': 'oid:0x60000000003a1'}
admin@sonic:~/script$ sonic-db-cli ASIC_DB HGETALL ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x40000000003a7
{'SAI_NEXT_HOP_ATTR_TYPE': 'SAI_NEXT_HOP_TYPE_IP', 'SAI_NEXT_HOP_ATTR_IP': '10.0.0.101', 'SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID': 'oid:0x60000000003a1'}
Next Hop Group の利用方法(まとめ)
SONiC の Next Hop Group について、APPL_DB へのエントリ追加方法を含めて解説しました。
今回はコマンドや Python Script により手動で追加しましたが、実際には BGPコンテナの FRR ( GoBGP) や Juniperが提供するcRPDのような商用ルーティングデーモンが APPL_DB にエントリを追加する事が想定されます。
コミュニティ版(オープンソース) SONiCでは fpmsyncd が Next Hop Group に未対応なためBGPコンテナ(FRR)で Next Hop Group を利用できませんが、将来的な拡張が期待されます。
Discussion