Dynamic Port Breakoutを試してみる[追記あり]

# はじめに

ある機能について、SONiC自体はサポートしていても、それぞれの機種がその機能をサポートしているとは限りません。そんな機能の一つ、Dynamic Port Breakout (DPB) について実機で試してみました。

確認したのは2022年12月8日にビルドしたmasterブランチのイメージになります。

# DPB?

リンク速度100Gのポートを持つスイッチがあるとします。
このポートを25G×4に分割して使うのがPort Breakoutです。

もちろん物理的に分割できないと意味がないのですが、[こんなかんじのケーブル](https://www.dell.com/ja-jp/shop/%E3%83%87%E3%83%AB-40gbe-qsfp-to-4-x-10gbe-sfp-passive-copper-breakout-cable-%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B1%E3%83%BC%E3%83%96%E3%83%AB-2-%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%BC/apd/470-abxo/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AD%E3%83%B3%E3%82%B0)を使います。

SONiCでは長らく、`port_config.ini`を編集して再起動することでこのPort Breakout設定することが可能でしたが、2019年に動的な変更実現する仕組みが検討され始め、2020年以降いくつかのハードウェアで利用可能になっています。これがDynamic Port Braekeout(DPB)です。

# DPBのやりかた

CLIで `config interface breakout` を実行します。

```shell-session
admin@sonic:~$ sudo config interface breakout
Usage: config interface breakout [OPTIONS] <interface_name> MODE
Try "config interface breakout -h" for help.

Error: Missing argument "<interface_name>".
```

`<interface_name>`には`Ethernet0`などを指定します。`MODE`には`1x100G[40G]`とか`4x25G[10G]`とか書きます。ポート速度は`config interface speed`で設定します。

# さわれる実機では対応していないんじゃが?

自分が触ることのできるSONiC対応スイッチに [DELTA AG9032V2A](https://ecin.ca/agema-delta-ag9032-v2a-100gbe-tor-spine-switch-broadcom-trident-3/) というのがあります。Broadcom Trident3を搭載した100G×32ポートのスイッチなのですが、このスイッチ用のSONiCはどうもDPBに対応していないようです。

```shell-session
admin@sonic:~$ sudo config interface breakout Ethernet0 4x25G[10G]
Do you want to Breakout the port, continue? [y/N]: y
[ERROR] Breakout feature is not available without platform.json file
Aborted!
```

むう。エラーメッセージを見る限り、なんかJSONファイルを書けばいけそうな感じがしますが。

# 調べてみた

## DPB対応機種

`rg -i breakout_modes` で出てきたうちスクリプトやテスト用ファイルを覗いたものを整形しました。

- Accton
  - WEDGE100BF-32QS
  - AS7816-64X
- Alphanetworks
  - SNJ60D0_320F
- Arista
  - 7050-QX32
  - 7060PX4-32
  - 7170B-64C
  - 7060DX4-32
  - 720DT-48S
  - 7050CX3-32S
  - 7260CX3-64
  - 7050-QX32S
  - 7060-CX32S
  - 7060DX5-64S
- DELL
  - Z9332F-D1508
- Barefoot
  - AS9516-32D
  - WEDGE100BF-65X
  - WEDGE100BF-32X
- Celestica
  - Seastone
- Mellanox
  - MSN3700C
  - MSN4600C
  - MSN2740
  - MSN4410
  - MSN2010
  - SN2201
  - MSN2410
  - MSN4700
  - MSN2100
  - MSN3420
  - MSN4600
  - MSN3800
  - MSN3700
  - MSN2700
  - SN5600
- Netberg
  - AURORA-610
- Quanta
  - IX9-BWDE


## `platform.json`のフォーマット

[設計ドキュメント](https://github.com/sonic-net/SONiC/blob/master/doc/dynamic-port-breakout/sonic-dynamic-port-breakout-HLD.md)が見つかりました。それによると、ざっくり下記のように書けばよさそうです。

```json:platform.json
{
  "interfaces": {
    "Ethernet0": {
      "index": "0,0,0,0",
      "lanes": "1,2,3,4",
      "breakout_modes": {
        "1x100G[40G]": ["Ethernet0"],
        "4x25G[10G]": ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"]
      }
    },
    "Ethernet4": {
      (以下略)
    }
  }
}
```

`breakout_modes`のところは書きを設定可能パターンに合わせて並べます。

```
"本数x速度[別の速度]: [本数分インタフェース名をカンマ区切りで並べる]"
```

`index`と`lanes`は`port_config.ini`の値をそのまま書けばよさそうです。

# 書いてみた

これを実機のディレクトリ(`/usr/share/sonic/device/x86_64-delta-ag9032v2a-r0/`)に置けば完了かな?

よし設定してみよう！

```shell-session
admin@sonic:~$ sudo config interface breakout Ethernet0 4x25G
Do you want to Breakout the port, continue? [y/N]: y
[ERROR] Breakout feature is not available without platform.json file
Aborted!
```

あれ?

# 調査結果

コードを追いかけた結果わかったこと

1. `hwsku.json`と`platform.json`の両方が必要
1. `platform.json`の中は前述のものが必要
1. `hwsku.json`の中に`interfaces`キーが必要
1. `hwsku.json`の`interfaces`の中にデフォルトのモードを書いておくこと

`hwsku.json`の中身は、デフォルトをどうするか記述するようです。

```json:hwsku.json
{ 
   "interfaces": {
        "Ethernet0": {
            "default_brkout_mode": "1x100G[40G]"
        },

        "Ethernet4": {
            "default_brkout_mode": "1x100G[40G]"
        },
        (以下略)
}
```

`/usr/share/sonic/device/x86_64-delta-ag9032v2a-r0/Delta-ag9932v2a/`に置きます。

ではいざ実行！

```shell-session
admin@sonic:~$ sudo config interface breakout Ethernet0 4x25G[10G]
Do you want to Breakout the port, continue? [y/N]: y
[ERROR] BREAKOUT_CFG table is NOT present in CONFIG DB
Aborted!
```

ぐぬぬ。

# CONFIG_DBの`BREAKOUT_CFG`を設定する

探したところ、[SONiC Configuration Database Manual](https://github.com/sonic-net/sonic-buildimage/blob/master/src/sonic-yang-models/doc/Configuration.md)に記載がありました。

```
"BREAKOUT_CFG": {
    "Ethernet0": {
        "brkout_mode": "4x25G[10G]"
    },
    "Ethernet4": {
        "brkout_mode": "4x25G[10G]"
    },
```

というふうに書くとのこと。`"1x100G[40G]"でずらっと`/etc/sonic/config_db.json`に書き加えて、`sudo config load -y`します。

さあ、試してみましょう。

```
admin@sonic:~$ sudo config interface breakout Ethernet0 4x25G[10G]
Do you want to Breakout the port, continue? [y/N]: y

Running Breakout Mode : 1x100G[40G] 
Target Breakout Mode : 4x25G[10G]

Ports to be deleted : 
 {
    "Ethernet0": "100000"
}
Ports to be added : 
 {
    "Ethernet0": "25000",
    "Ethernet1": "25000",
    "Ethernet2": "25000",
    "Ethernet3": "25000"
}
sonic_yang(6):Note: Below table(s) have no YANG models: CONTAINER_FEATURE, XCVRD_LOG
sonic_yang(3):All Keys are not parsed in FEATURE
dict_keys(['sflow', 'telemetry'])
sonic_yang(3):exceptionList:["'status'", "'status'"]
sonic_yang(3):Data Loading Failed:All Keys are not parsed in FEATURE
dict_keys(['sflow', 'telemetry'])
exceptionList:["'status'", "'status'"]
Data Loading Failed
All Keys are not parsed in FEATURE
dict_keys(['sflow', 'telemetry'])
exceptionList:["'status'", "'status'"]
ConfigMgmt Class creation failed
```

**YANG model**の罠!

CONFIG_DBの中身がYANG modelのお気に召さなかったようでうまくいきませんでしたが、DPB自体は動かせそうでした。本日はここまで。

# おわりに

思ったよりも簡単に対応できそうでホッとしました。

YANG modelもう少しわかるようにエラーを出していただきたいです。。

# [追記] 動きました!

YANG model的にはおそらく`FEATURE`テーブルの中の`"status`"がお気に召さないんだろうと思い、`"status"`キーのある部分を2箇所削除してみました。すると、

```
$ $ sudo config interface breakout Ethernet0 4x25G[10G]
Do you want to Breakout the port, continue? [y/N]: y

Running Breakout Mode : 1x100G[40G] 
Target Breakout Mode : 4x25G[10G]

Ports to be deleted : 
 {
    "Ethernet0": "100000"
}
Ports to be added : 
 {
    "Ethernet0": "25000",
    "Ethernet1": "25000",
    "Ethernet2": "25000",
    "Ethernet3": "25000"
}
sonic_yang(6):Note: Below table(s) have no YANG models: CONTAINER_FEATURE, XCVRD_LOG
libyang[0]: Leafref "/sonic-mgmt_port:sonic-mgmt_port/sonic-mgmt_port:MGMT_PORT/sonic-mgmt_port:MGMT_PORT_LIST/sonic-mgmt_port:name" of value "eth0" points to a non-existing leaf. (path: /sonic-mgmt_interface:sonic-mgmt_interface/MGMT_INTERFACE/MGMT_INTERFACE_LIST[name='eth0'][ip_prefix='10.207.9.135/24']/name)
sonic_yang(3):Data Loading Failed:Leafref "/sonic-mgmt_port:sonic-mgmt_port/sonic-mgmt_port:MGMT_PORT/sonic-mgmt_port:MGMT_PORT_LIST/sonic-mgmt_port:name" of value "eth0" points to a non-existing leaf.
Data Loading Failed
Leafref "/sonic-mgmt_port:sonic-mgmt_port/sonic-mgmt_port:MGMT_PORT/sonic-mgmt_port:MGMT_PORT_LIST/sonic-mgmt_port:name" of value "eth0" points to a non-existing leaf.
ConfigMgmt Class creation failed
```

ああ、これはYANG modelで怒られるありがちな`MGMT_PORT`関連かな。追加してみます。

```
    "MGMT_PORT": {
        "eth0": {
          "admin_status": "up"
        }
    },
```

追記して、`config load -y`でCONFIG_DBに反映して、もう一度。

```
admin@sonic:~$ sudo config interface breakout Ethernet0 4x25G[10G]
Do you want to Breakout the port, continue? [y/N]: y

Running Breakout Mode : 1x100G[40G] 
Target Breakout Mode : 4x25G[10G]

Ports to be deleted : 
 {
    "Ethernet0": "100000"
}
Ports to be added : 
 {
    "Ethernet0": "25000",
    "Ethernet1": "25000",
    "Ethernet2": "25000",
    "Ethernet3": "25000"
}
sonic_yang(6):Note: Below table(s) have no YANG models: CONTAINER_FEATURE, XCVRD_LOG
Below Config can not be verified, It may cause harm to the system
 {}
Do you wish to Continue? [y/N]: y
Breakout process got successfully completed.
Please note loaded setting will be lost after system reboot. To preserve setting, run `config save`.
```

**動きました!!**

よかった。おしまい。