🎄

SRv6 on SONiC を設定してみる (End.DT46, H.Encaps.Red)

2022/12/06に公開3

SONiC Advent Calendar 2022 Day 6

SONiC の "Segment Routing over IPv6 (SRv6)" 機能について、 End.DT46 H.Encaps.Red SRv6 behvaior を中心に解説します。

  • SRv6 on SONiC の歴史
  • SRv6 on SONiC のデザイン(SONiC.202111)
  • 試してみる:設定方法とパケット変換動作
  • SAI Object と ASIC_DB エントリ
  • APPL_DB, ASIC_DB エントリの変換フロー

SRv6 on SONiC の歴史

SONiC での SRv6 対応の歴史をまとめた表です。

実は SONiC(SAI) における SRv6 の歴史は古く、2017年頃(SAI 1.2)に初めて実装されました。
しかし、その後の SRv6 標準化進展に伴う変化や、 SAI Pipeline Model の Tunnel (VxLAN) や MPLS との整合性を確保するため、2021年に大幅に更新されました。

最初の実装は Cavium XPliant ASIC 向けに実装されましたが、2018年に Cavium が Marvell に買収され、XPliant ASIC がディスコン(製品ライン打ち切り)となり現在では入手できません。

そのため、これから SRv6 on SONiC を学びたい人は、上記HLD(High Level Design)文書とその実装である SONiC.202111 リリース以降の SONiC だけ学べば十分です。

また、SONiC.202211 リリースでは uSID がサポートされました。
まだ SONiC.202211 のプリビルドイメージはありませんが、sonic-buildimage の 202211 ブランチを自分でビルドすれば試す事が可能と思われます。

なお、 2022年12月5日 現在では SRv6 on SONiC は Tofino ASIC (Intel/Barefoot) でしか動作していないようです。もし Broadcom など、他の ASIC 搭載のスイッチで動作した場合は、ぜひ情報をお寄せください。

SRv6 on SONiC のデザイン(SONiC.202111)

図は、前述の SRv6 HLD に記載されたデザインに情報を追加し整理したものです。

このようにHLDが作成された段階で CONFIG_DB や FRR (BGP Container) との連携が考慮されていましたが、実装されませんでした。よって、現在は Controller App や Script 等で APPL_DB を直接操作する必要があります。

なお FRR との連携(fpmsyncd への機能追加)は関連PRを見ると開発はほぼ完了し、レビューやマージを待っている状況のようです。FRR + SONiC で SRv6 を利用できる日が楽しみですね!

試してみる:設定方法とパケット変換動作の確認

では、早速 SRv6 を設定してみましょう。
今回利用した環境は以下の通りです。

  • Wedge100BF-32 (Tofino ASIC 搭載)
  • SONiC-OS-master.143513-dirty-20220903.195418

最新のリリースである SONiC.202205 ブランチでは H.Encaps.Red が動かない[1]ため、master ブランチのビルドを利用しました。

[1] SAI_NEXT_HOP_TYPE_SRV6_SIDLIST を SET する際に SAI_STATUS_INVALID_PARAMETER となり設定できない。(Tofino ASIC の P4 Table に Entry が作成されない)

構成と設定

SRv6 を試すには パケット送信 -> 変換 -> 受信 が必要なため、SONiC に接続された Server に netns を利用して仮想的に2台のホストを作成し、その間で通信しました。
また、 End.DT46 では Lookup するテーブル(VRF)を指定するため、分かりやすいように vrf: <default>vrf: Vrf_srv6 の2つのVRFを設定しました。

基本設定

SRv6 ではない基本設定は以下の通りです。こちらはCLI等から設定してください。

"INTERFACE": {
    "Ethernet0": {},
    "Ethernet0|10.0.0.1/24": {},
    "Ethernet0|2001:db8::1/64": {},
    "Ethernet4": {
        "vrf_name": "Vrf_srv6"
    },
    "Ethernet4|10.0.4.1/24": {},
    "Ethernet4|2001:db8:4::1/64": {}
},
"VRF": {
    "Vrf_srv6": {}
}

H.Encaps.Red (APPL_DB), vrf: Vrf_srv6

SRv6 の設定は APPL_DB にエントリを作成します。

{
    "SRV6_SID_LIST_TABLE:seg3": {
        "path": "2001:db8::100,2001:db8::103"
    },
},
{
    "ROUTE_TABLE:Vrf_srv6:10.3.0.0/24": {
        "segment": "seg3",
        "seg_src": "2001:db8:ffff::3"
    },
}

End.DT46 (APPL_DB), vrf: default

{
    "SRV6_MY_SID_TABLE:32:32:16:0:2001:db8:ffff:1:14::": {
        "action": "end.dt46", "vrf": "Vrf_srv6"
    },
}

swssconfig を用いた APPL_DB エントリ作成方法

APPL_DB にエントリを作成する方法は色々ありますが、今回は swssconfig を利用した方法を解説します。

swssconfig は swss container 上で実行できる、APPL_DB に対してエントリをセットしたり消したりできるツールです。
以下のように、作成するエントリと操作内容(OP)を記述した json ファイルを用意し swssconfig <*.json> を実行する事でエントリを作成できます。

End.DT46 : end-dt46.json

[
    {
        "SRV6_MY_SID_TABLE:32:32:16:0:2001:db8:ffff:1:14::": {
            "action": "end.dt46", "vrf": "Vrf_srv6"
        },
        "OP": "SET"
    }
]

H.Encaps.Red : encaps-red-3.json

[
    {
        "SRV6_SID_LIST_TABLE:seg3": {
            "path": "2001:db8::100,2001:db8::103"
        },
        "OP": "SET"
    },
    {
        "ROUTE_TABLE:Vrf_srv6:10.3.0.0/24": {
            "segment": "seg3",
            "seg_src": "2001:db8:ffff::3"
        },
        "OP": "SET"
    }
]

swssconfig 実行方法

  1. swss container に入る
admin@sonic:~$ docker exec -it swss bash
  1. JSON ファイルの作成
root@sonic:/# vi encaps-red-3.json
root@sonic:/# vi end-dt46.json
  1. swssconfig コマンドを実行
root@sonic:/# swssconfig end-dt46.json
root@sonic:/# swssconfig encaps-red-3.json

パケット変換動作の確認(End.DT46)

End.DT46 は SRv6 パケットを送信し、Decap された Inner パケットを受信する動作になります。

注目は IPv6 Hop Limit (hlim) と IPv4 TTL (ttl) で、End.DT46 を実行した場合、Inner Packet の TTL を1減らして送信している事がわかります。

(1) 送信パケット:SRv6 Packet from ens1f0 to End.DT46 SID

(2)(3) 受信パケット:Decap, Lookup Vrf_srv6, Send to ens1f1

パケット変換動作の確認(H.Encaps.Red)

H.Encaps.Red はオリジナルパケット(IPv4)を送信し、Encap された SRv6 パケットを受信する動作になります。

Encap されたパケットは vrf: default に渡され、SRv6 パケットの宛先アドレスを Lookup して転送されます。

H.Encaps.Red を実行した場合、Inner Packet の TTL を1減らし、かつ TTL の値を IPv6 Hop Limit の値として利用し送信している事がわかります。

(1) 送信パケット:IPv4 Packet from ens1f1@sonic04

(2)(3) 受信パケット:Encap, Lookup vrf:default, Send to ens1f0

SAI Object と ASIC_DB エントリ

SAI Object の定義

SONiC の ASIC_DB エントリは、実は SAI Object と等価です。
SAI Object は SAI レポジトリの inc/sai*.h に定義されていますので、そちらを参照すると ASIC_DB のエントリについても理解が深まります。

SRv6 に関しては saisrv6.h を中心に定義されています。
例えば My SID に関連する箇所を以下に抜き出しました。見やすいようにコメントは一部省略しています。

  • SAI Object は Entry + Attribute の組合せであり、*_entry_t が取りうる Attribute は *_entry_attr_t で定義されています。(例: sai_my_sid_entry_t の Attribute は sai_my_sid_entry_attr_t で定義)
  • また、Attribute の利用可能な状況に制約がある場合、コメントで制約条件( @validonly )が記載されています。
/**
 * @brief My SID Entry
 */
typedef struct _sai_my_sid_entry_t
{
    sai_object_id_t switch_id; // SAI_OBJECT_TYPE_SWITCH
    sai_object_id_t vr_id;     // SAI_OBJECT_TYPE_VIRTUAL_ROUTER

    sai_uint8_t locator_block_len;
    sai_uint8_t locator_node_len;
    sai_uint8_t function_len;
    sai_uint8_t args_len;
    sai_ip6_t sid; // IPv6 Address for My SID

} sai_my_sid_entry_t;
/**
 * @brief Attribute list for My SID
 */
typedef enum _sai_my_sid_entry_attr_t
{
    SAI_MY_SID_ENTRY_ATTR_START,

    /**
     * @brief Endpoint Function
     * @type sai_my_sid_entry_endpoint_behavior_t
     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
     */
    SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR = SAI_MY_SID_ENTRY_ATTR_START,

    /**
     * @brief Flavor for End, End.X and End.T functions
     *
     * @type sai_my_sid_entry_endpoint_behavior_flavor_t
     * @flags CREATE_AND_SET
     * @default SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_FLAVOR_NONE
     * @validonly SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR == SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_E or SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR == SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_X or SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR == SAI_MY_SID_ENTRY_ENDPOINT_BEHAVIOR_T
     */
    SAI_MY_SID_ENTRY_ATTR_ENDPOINT_BEHAVIOR_FLAVOR,

... snip ...

} sai_my_sid_entry_attr_t;

SAI Object & ASIC_DB エントリ

End.DT46, H.Encaps.Red について、SAI Object == ASIC_DB エントリを図示すると以下のようになります。

End.DT46

H.Encaps.Red

APPL_DB, ASIC_DB エントリの変換フロー

APPL_DB から ASIC_DB への変換は swss/orchagent の役割となります。
SRv6 H.Encaps.Red の場合、以下のように IP Route を管理する RouteOrch と SRv6 の Srv6Orch が協調して動作します。

まとめ

SRv6 の設定方法から APPL_DB, ASIC_DB のエントリについて説明してきました。
SRv6 on SONiC は uSID のサポートなど、現在もアクティブに開発が行われています。
今後の機能追加も楽しみですね!!

Discussion

huihui

Hi, ebiken_sdn!

I'm new to SONiC. I encountered the SAI_STATUS_ITEM_NOT_FOUND error on x86_64-accton_wedge100bf_32x-r0 with SONiC.master.298183-dirty-20230620.123137 version. Do you have the same problem?
Do you have a solution?
Thanks.

swss log :
Jul 14 11:36:02.327180 sonic ERR swss#orchagent: :- create: create status: SAI_STATUS_ITEM_NOT_FOUND
Jul 14 11:36:02.327208 sonic ERR swss#orchagent: :- createUpdateMysidEntry: Failed to create my_sid entry 32:32:16:0:2001:db8:ffff:1:14::, rv -7
Jul 14 11:36:02.327208 sonic ERR swss#orchagent: :- doTaskMySidTable: Failed to create/update my_sid entry for sid 32:32:16:0:2001:db8:ffff:1:14::

syncd log:
Jul 14 11:36:02.326294 sonic INFO syncd#supervisord: syncd 2023-07-14 11:36:02.325851 BF_SAI ERROR - sai_get_my_sid_entry_attribute:285: Failed to get my_sid_entry: object not found my_sid: vrf 0x40000000000001, ip: 2001:db8:ffff:1:14::: SAI_STATUS_ITEM_NOT_FOUND

ebiken_sdnebiken_sdn

Hi Hui. No, I havent. But it can be because I haven't tryed with the version you are running.
Only specific build of SONiC is supported on Tofino, which requires to be used with corresponding version of the P4 program and Intel SDE. Thus you might want to try with the SONiC build which is listed in the latest SDE release notes.

huihui

Thank you for your advice.I'll give it a try as you suggested.