SONiC と FRR -- sonic-frr-mgmt-framework 編

## はじめに

SONiC では、sonic-frr-mgmt-framework が FRR configの初期状態を制御する手法の一つとして使用されています。このフレームワークは、BGP はもちろん、OSPF、STATIC、IGMP、PIM、VRFs、BGP EVPN もサポートするようです。デフォルトの sonic-bgpcfgd よりも対応範囲が広く、FRR 関連の設定を `config_db.json` で一括管理できるようになると認識しています。

https://github.com/sonic-net/SONiC/blob/master/doc/mgmt/SONiC_Design_Doc_Unified_FRR_Mgmt_Interface.md

実際の使用方法、例えばどのように JSON の Key-Value の記述方法で FRR を設定するかという詳細なドキュメントがまだないと思われますが、[SONiC — Don’t use split-mode, use frr-mgmt-framework!!!](https://medium.com/sonic-nos/sonic-dont-use-split-mode-use-frr-mgmt-framework-a67ad76ec1a6)という記事の設定例を参考に、FRR config が frr-mgmt-frameworkでどのように生成されるかを確認し、軽く検証を行います。

## routing mode in sonic-frr-mgmt-framework

frr-mgmt-framework 上の routing mode について、もし DEVICE_METADATA.local に指定しなかった場合、routing mode は `separated` になっています。
``` python
        if 'docker_routing_config_mode' in db_entry:
            self.config_mode = db_entry['docker_routing_config_mode']
        else:
            self.config_mode = "separated"
```
（ソースコード：https://github.com/sonic-net/sonic-buildimage/blob/master/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py#L2091）

それぞれの routing mode について、前回の記事 [SONiC と FRR -- sonic-bgpcfgd 編](https://qiita.com/cyo-chang/items/d82de5fbe1887000da96#routing-mode-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6) にご参考ください。

## sonic-frr-mgmt-framework で シンプルな BGP セッションの構築を試す
### 環境
- version: Community 202311 VS（イメージの入手について、[SONiC VS 仮想スイッチを使ってみよう [Community/Edgecore]](https://qiita.com/cyo-chang/items/3f987d1b3e8303e40988)に参考）
- GNS3
- Topology
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/28a808c9-d18a-a600-b0b2-fb95a53f6384.png)

## 手順
### 1．sonic-vs の初期 config を削除
sonic-vs 202311 版の初期 `config_db.json` には、IP インターフェースと BGP の設定が含まれています。それは不要のため、jp コマンドの小技を使って `config_db.json` の `BGP_NEIGHBOR`、`INTERFACE`、および `LOOPBACK_INTERFACE`と `DEVICE_METADATA.localhost.bgp_asn`* のキーを削除します。その後、config reload を実行すれば、不要な IP インターフェースと BGP の設定をすべてリムーブできます。

*frr-mgmt-framework 有効の場合、Local AS number の 参照先は `DEVICE_METADATA.localhost.bgp_asn` じゃなくなります。key `bgp_asn` を削除したほうが紛らわしくないと思います。
（参考：https://github.com/sonic-net/sonic-buildimage/blob/master/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py#L2099）

``` bash:
admin@sonic:~$ sudo jq 'del(.DEVICE_METADATA.localhost.bgp_asn ,.BGP_NEIGHBOR, .INTERFACE, .LOOPBACK_INTERFACE)' \
                        /etc/sonic/config_db.json > \
                        /tmp/temp_config_db.json && \
                        sudo mv /tmp/temp_config_db.json \
                        /etc/sonic/config_db.json
admin@sonic:~$ sudo config reload -y
```

### 2．IP interface を追加
Topology に合わせ、BGP session のためのIP interface を設定します。
（hostname の変更を省略）
``` bash:vs-1
admin@vs-1:~$ sudo config interface ip add Ethernet0 10.0.0.0/31
admin@vs-1:~$ sudo config interface ip add Loopback0 1.1.1.1/32
```
``` bash:vs-2
admin@vs-2:~$ sudo config interface ip add Ethernet0 10.0.0.1/31
admin@vs-2:~$ sudo config interface ip add Loopback0 2.2.2.2/32
```
### 3．config_db.json を編集
- `"frr_mgmt_framework_config": "true"`を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/c1863f42-96f8-0431-36a1-3828ab60b478.png)

- BGP 設定をそれぞれの config_db.json に入れます
  ``` json:vs-1:/etc/sonic/config_db.json
  {
  ...(省略)...
	"BGP_GLOBALS": {
		"default": {
			"local_asn": "65000",
			"router_id": "1.1.1.1"
		}
	},
	"ROUTE_REDISTRIBUTE": {
		"default|connected|bgp|ipv4": {}
	},
	"BGP_NEIGHBOR": {
		"default|10.0.0.1": {
			"local_asn":  "65000",
			"asn": "65000"
		}
	},
	"BGP_NEIGHBOR_AF": {
		"default|10.0.0.1|ipv4_unicast": {
			"admin_status": "true"
		}
	}
  }
  ```
  ``` json:vs-2:/etc/sonic/config_json
  {
  ...(省略)...
      "BGP_GLOBALS": {
        "default": {
            "local_asn": "65000",
            "router_id": "2.2.2.2"
        }
    },
    "ROUTE_REDISTRIBUTE": {
        "default|connected|bgp|ipv4": {}
    },
    "BGP_NEIGHBOR": {
        "default|10.0.0.0": {
            "local_asn":  "65000",
            "asn": "65000"
        }
    },
    "BGP_NEIGHBOR_AF": {
        "default|10.0.0.0|ipv4_unicast": {
            "admin_status": "true"
        }
    }
  }
  ```

最後、`config save`, `config reload` すれば、設定終了です。

## 結果確認
### FRR config
config_db.json で生成された FRR 設定内容です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/2b3a29bb-ee8c-ec02-5502-13865d83538a.png)

FRR の コンフィグファイルは、frr-mgmt-framework によって`/etc/sonic/frr/bgpd.conf` に自動的に出力されています。その内容をのぞいてみると
 ``` bash:vs-1:/etc/sonic/frr/bgpd.conf
 admin@vs-1:~$ sudo cat /etc/sonic/frr/bgpd.conf
    ! =========== Managed by sonic-cfggen DO NOT edit manually! ====================
! generated by templates/quagga/bgpd.conf.j2 with config DB data
! file: bgpd.conf
!
!
! template: common/daemons.common.conf.j2
!
hostname vs-1
password zebra
enable password zebra
!
log syslog informational
log facility local4
!
! end of template: common/daemons.common.conf.j2!
agentx
!
! template: bgpd/bgpd.conf.db.j2
!
! BGP configuration using config DB BGP instance tables
!
!
router bgp 65000
 bgp router-id 1.1.1.1
 no bgp default ipv4-unicast
 neighbor 10.0.0.1 remote-as 65000
 neighbor 10.0.0.1 local-as 65000
 !
 address-family ipv4 unicast
  redistribute connected
  neighbor 10.0.0.1 activate
 exit-address-family
 !
 address-family ipv6 unicast
 exit-address-family
 !
 address-family l2vpn evpn
 exit-address-family
!
! end of template: bgpd/bgpd.conf.j2
!
admin@vs-1:~$ 

 ```

 ``` bash:vs-2:/etc/sonic/frr/bgpd.conf
 admin@vs-2:~$ sudo cat /etc/sonic/frr/bgpd.conf
    ! =========== Managed by sonic-cfggen DO NOT edit manually! ====================
! generated by templates/quagga/bgpd.conf.j2 with config DB data
! file: bgpd.conf
!
!
! template: common/daemons.common.conf.j2
!
hostname vs-2
password zebra
enable password zebra
!
log syslog informational
log facility local4
!
! end of template: common/daemons.common.conf.j2!
agentx
!
! template: bgpd/bgpd.conf.db.j2
!
! BGP configuration using config DB BGP instance tables
!
!
router bgp 65000
 bgp router-id 2.2.2.2
 no bgp default ipv4-unicast
 neighbor 10.0.0.0 remote-as 65000
 neighbor 10.0.0.0 local-as 65000
 !
 address-family ipv4 unicast
  redistribute connected
  neighbor 10.0.0.0 activate
 exit-address-family
 !
 address-family ipv6 unicast
 exit-address-family
 !
 address-family l2vpn evpn
 exit-address-family
!
! end of template: bgpd/bgpd.conf.j2
!
admin@vs-2:~$ 
 ``` 
<font color="Red"><b>Managed by sonic-cfggen DO NOT edit manually!<b></font> という警告メッセージが表示されているのをわかりました。

それは split mode と一番大きな違いだと考えられます。直接に FRR config ファイルを修正しないことは、frr-mgmt-framework の目的の一つでしょう。

### BGP session summary
BGP session うまく生成されたと確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/87dd663c-1a05-6e8b-873e-a1e93e51f0e7.png)

### 不具合
だが、`show ip interface` を確認してみると、バグを踏んだようです。
おそらく Community 版の SONiC CLI の方は、frr-mgmt-framework との統合まだ終わっていないと見えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3307184/eec88bac-f9ac-8460-3dc1-aa246f9bbe86.png)

## 最後に
sonic-frr-mgmt-framework を軽く検証後、直接 FRR config をいじる必要はないというメリットを感じましたが、今の時点ならかなり不便だという事実もあります。一番大きな理由は、config_db.json でのJSONのキーと値の記述方法で FRR を設定する方法がわかりませんでした。具体的なリファレンスがないため、設定のハードルが高いと感じます。（しかも不具合まだ存在します..）

ネットワークオペレータの目線からみると、FRR の設定ファイルを直接に設定することで、詳細なルーティングの制御が柔軟に調整できるというのは一番大事です。そのため、基本的には sonic-frr-mgmt-framework を使わず、split modeは主流になったでしょう。

## 参考
[SONiC — Don’t use split-mode, use frr-mgmt-framework!!!](https://medium.com/sonic-nos/sonic-dont-use-split-mode-use-frr-mgmt-framework-a67ad76ec1a6)
[sonic-vsの初期configを見てみる](https://zenn.dev/nanakanok/articles/32d0ff44fec4ce)