FITELnet F220のLXCでSRv6 MUPをやってみた

こちらは [エーピーコミュニケーションズ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ap-com) の 19日目の記事です。

#目次
[1.はじめに](#1-はじめに)
[2.FITELnet](#2-fitelnet)
[3.検証構成](#3-検証構成)
[4.F220上のLXC](#4-f220上のlxc)
[5.GoBGP](#5-gobgp)
[6.FRR](#6-frr)
[7.SRv6設定可否を調査](#7-srv6設定可否を調査)
[8.SRv6 MUPに挑戦](#8-srv6-mupに挑戦)
[9.おわりに](#9-おわりに)

### 1. はじめに
こんにちは！やすお(@chimay_wh)です。
普段「はてなブログ」で技術を中心にブログを投稿しております。
良かったら見てください。
https://chimay-wh.hatenablog.com/archive

手のひらネットワーク機器のミニチュアセット第一弾のラインナップに古河電工「FITELnet FX2」があります。欲しいけど懐事情が厳しいのでFX2は諦めました。代わりにヤフオクで手に入れた別のFITELnetシリーズ「FITELnet F220：以後F220と省略します」を使って~~ルータ上でLXCを有効化してGoBGPとFRRを動かして、LXCを使った筐体間通信を検証する~~SRv6 MUPの検証に挑戦した話を書きます。

### 2. FITELnet
FITELnet にはFシリーズ、FXシリーズ、Vシリーズがあります。  
FXシリーズは、大規模センタ・キャリアサービス設備向けの製品です。  
Fシリーズは、拠点～中規模センタ向けの製品です。  
Vシリーズは、NFV（Network Functions Virtualization）です。  

詳しくは、古河電工さんの[ルータ製品総合カタログ](https://www.furukawa.co.jp/product/catalogue/pdf/fitelnet_j458.pdf)をご参照ください。
製品の位置づけは以下の通りです。
![01_FITELnet_F_FX.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/501e5b29-6242-d587-2acf-8682a5ad7a26.png)
![02_FITELnet_V.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/a2700ada-52b3-f052-fc76-fec3c7f40447.png)
F220 とFITELnet F220 EX 外観はほぼ同じです。  
![03_F220_vs_F220-EX.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/4755c66a-ea84-fc4e-88c1-6972f75e7472.png)
F220はカタログ記載のとおりSRv6はサポートされていません。  
コマンドは実装済みなのですが、残念なことに使えないのです。  
![F220_not_support_SRv6_but_command_is_visible.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/6a25504f-77d1-96bc-6e39-423fd0f1260b.png)
しかし、F220には素晴らしい機能があります。
![04_c_d_bunri.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/f474790b-d0a8-eb2f-cb30-429ad54b0754.png)
今回は、F220上のLinux Containers:LXCを主に使って検証します。  

### 3. 検証構成
■物理構成
![物理構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/0bcd42c3-4f0e-beaf-f2b0-9ae9fcae619d.png)
■論理構成（GoBGP、FRR構築時：インターネット接続が必要）
![論理構成_インターネット接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/16b1aeb7-1051-5491-b787-5f8b60dedf8c.png)
■論理構成
![論理構成_final.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/6cf63e4b-01b1-5cb1-bb7f-b98d4b6dccce.png)

~~F220上でLXCを有効化し、経路交換をGoBGPで行う。  
LXCのカーネルFIBに経路を反映させるためにFRRを使う。  
ここまでが元々の予定でした。~~  
しかし、思っていた以上にあっさり出来てしまい、もう少し特別なことをしたいという欲が出て、SRv6 MUPを検証してみよう！という流れになりました。

### 4. F220上のLXC
F220にCONSOLE接続して、設定します。
■初期値■
operator(パスワード無）、enable(パスワード無)
```
F220 (console)
login: operator

<WARNING> weak login password: set the password
>
>enable

password:
<WARNING> weak enable password: set the password



#configure terminal

(config)#
```
F220＃1のインターフェース設定を例として示します。
F220＃2は構成図のとおりに設定します。
```
! Enter configuration mode
#conf t
! Port-channel interface 2 (default 1) 
(config)#interface Port-channel 2
! Port-channel 2 IPv4 setting
(config-if-ch 2)#ip address 192.168.2.23 255.255.255.0
! Exit from current configuration mode
(config-if-ch 2)#exit
! GigabitEthernet interface 1/1
(config)#interface Gigaethernet 1/1
! Belong to vlan id (default 1) 
(config-if-ge 1/1)#vlan-id 2
! Belong to bridge group (default 1) 
(config-if-ge 1/1)#bridge-group 2
! Belong to port-channel group (default 1) 
(config-if-ge 1/1)#channel-group 2
! Use container interface
(config-if-ge 1/1)#container-use
! Copy from candidate-config to running-config and hot start
(config-if-ge 1/1)#commit
...........................Done
! Exit from configuration mode
(config-if-ge 1/1)#end

#
```
F220＃1のコンテナ設定を例として示します。
F220＃2は構成図のとおりに設定します。
```
! Enter configuration mode
#conf t
! Set container
(config)#container enable
! Enter Container configuration mode
(config)#container configuration
! Set DNS Addresses
(config-container)#dns 8.8.8.8
! Set hostname
(config-container)#hostname RTA
! Enter Container interface mode (number 1 - 1 - 16777215)
(config-container)#interface 1
! Belong to bridge group 
(config-container-if 1)#bridge-group 2
! Set the IP address
(config-container-if 1)#ip address 192.168.2.25 255.255.255.0
! Set gateway
(config-container-if 1)#ip gateway 192.168.2.1
! Set the IPv6 address
(config-container-if 1)#ipv6 address 2001:df8::1/64
! Copy from candidate-config to running-config and hot start
(config-container-if 1)#commit
...........................Done
! Exit from configuration mode
(config-container-if 1)#end

#
```
:::note warn
時刻同期がなされていないと、LXCのパッケージ更新などでエラーとなるので、NTPサーバを必ず指定してください。
:::
自宅にはNTPサーバが無いので、NICT公開NTPサービスを利用することにしました。
```
! Enter configuration mode
#conf t
! ntp client setup (ntp.nict.jp:61.205.120.130)
(config)#ntp server 61.205.120.130
! Copy from candidate-config to running-config and hot start
(config)#commit
..................Dec 18 13:53:43  ntpd[15903]: sendto(61.205.120.130): No route to host
..........Done
! Exit from configuration mode
(config)#end

#
```
F220を再起動しても設定が失われないように保存します。
```
#save
save ok?[y/N]:yes

% saving working-config
100% |*************************************************|    95 /    95 ( Lines)

#
```
以後、F220を起動すればコンテナは自動起動します。
しかし、初回コンテナ作成直は停止しています。
コンテナの状態を確認します。
```
#show container list

+-----------+------------+---------------------+---------+------+------+
|   NAME    | BASE IMAGE |    IMAGE VERSION    |  STATE  | IPV4 | IPV6 |
+-----------+------------+---------------------+---------+------+------+
| container | a58b2c065a | 3.13 20210422_15:00 | STOPPED |      |      |
+-----------+------------+---------------------+---------+------+------+
#
```
コンテナを起動します。start ok?[y/N]: に y を入力すると起動します。
```
#container ?
attach   Attach container
backup   Export container backups
delete   Delete container
exec     Execute commands in containers
image    Manage image
init     Create container from image
push     Push files into containers
restart  Restart containers
restore  Restore container
start    Start containers
stop     Stop containers

#container start
start ok?[y/N]:yes

#
```
コンテナの状態を確認します。
```
#show container list

+-----------+------------+---------------------+---------+---------------------+--------------------+
|   NAME    | BASE IMAGE |    IMAGE VERSION    |  STATE  |        IPV4         |        IPV6        |
+-----------+------------+---------------------+---------+---------------------+--------------------+
| container | a58b2c065a | 3.13 20210422_15:00 | RUNNING | 192.168.2.25 (eth2) | 2001:df8::1 (eth2) |
+-----------+------------+---------------------+---------+---------------------+--------------------+
#
```
STATEが`RUNNING`になり、IPv4,IPv6の値が確認できます。
コンテナにログインします。（container attach)
```
#container attach
~ #
~ # uname -n
RTA
~ # ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
sit0@NONE        DOWN
loop0            DOWN
loop1            DOWN
eth2@if2         UP             192.168.2.25/24 2001:df8::1/64 fe80::280:bdff:fe51:11c5/64
~ #
```
コンテナからF220 OSのCLIに戻ります。
exitと入力するか、<Ctrl><D>同時押下します。
```
#! F220 OS CLI
#
#container attach
~ #
~ # uname -n
RTA
~ #! Exit from execute mode
~ # exit

#! F220 OS CLI
#
#container attach
~ #! <Ctrl><D>同時押下

#! F220 OS CLI
```
コンテナを停止します。stop ok?[y/N]: に y を入力すると停止します。
```
#container stop
stop ok?[y/N]:yes

#show container list

+-----------+------------+---------------------+---------+------+------+
|   NAME    | BASE IMAGE |    IMAGE VERSION    |  STATE  | IPV4 | IPV6 |
+-----------+------------+---------------------+---------+------+------+
| container | a58b2c065a | 3.13 20210422_15:00 | STOPPED |      |      |
+-----------+------------+---------------------+---------+------+------+
#
```
コンテナの再起動も同じ要領でできます。
起動状態からの再起動のようです。停止していたら勝手に起動し直すというものではありませんでした。
```
#container restart
restart ok?[y/N]:yes

The container is already stopped.

#show container list

+-----------+------------+---------------------+---------+------+------+
|   NAME    | BASE IMAGE |    IMAGE VERSION    |  STATE  | IPV4 | IPV6 |
+-----------+------------+---------------------+---------+------+------+
| container | a58b2c065a | 3.13 20210422_15:00 | STOPPED |      |      |
+-----------+------------+---------------------+---------+------+------+
#
```
コンテナの起動/停止、F220 OS CLIと行ったり来たりする操作も簡単です。コンテナ起動したら、apk update しましょう。
```
~ # apk update
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/aarch64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/aarch64/APKINDEX.tar.gz
v3.13.12-96-ga50b7c1ba58 [https://dl-cdn.alpinelinux.org/alpine/v3.13/main]
v3.13.12-94-g0551adbecc [https://dl-cdn.alpinelinux.org/alpine/v3.13/community]
OK: 13801 distinct packages available
~ #
```
### 5. GoBGP
GoBGPとはNTT発のOSSのBGP（Control-Plane)のことです。  
Control-Planeだけではパケットを転送できません。Data-Planeと連携する必要があります。  
今回は、以下の記事を参考に致しました。
[GoBGPコトハジメ@yas-nyan](https://qiita.com/yas-nyan/items/efd6c587b88678878da6)
違う点と言えば、「aarch64 Linux」である点とGoBGPはv3.31.0を使用した点だけです。
```
（参考）実行したものだけを羅列します。
!
mkdir /opt/gobgp
cd /opt/gobgp
wget https://github.com/osrg/gobgp/releases/download/v3.31.0/gobgp_3.31.0_linux_arm64.tar.gz
tar xvf gobgp_3.31.0_linux_arm64.tar.gz
ln -s /opt/gobgp/gobgpd /usr/local/bin/gobgpd
ln -s /opt/gobgp/gobgp /usr/local/bin/gobgp
gobgp --version
```
[/opt/gobgpディレクトリ]にGoBGPの.confファイルを保存します。
```
RTA
!
rta_gobgp_only.conf
!
[global.config]
  as = 64512
  router-id = "192.0.0.1"

[[neighbors]]
  [neighbors.config]
    peer-as = 64512
    neighbor-address = "2001:df8::2"
    local-as = 64512

    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
        afi-safi-name = "ipv6-unicast"
```
```
RTB
!
rtb_gobgp_only.conf
!
[global.config]
  as = 64512
  router-id = "192.0.0.2"

[[neighbors]]
  [neighbors.config]
    peer-as = 64512
    neighbor-address = "2001:df8::1"
    local-as = 64512

    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
        afi-safi-name = "ipv6-unicast"
```
GoBGPのデーモンをそれぞれ起動します。
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgpd -f rta_gobgp_only.conf &
/opt/gobgp # {"level":"info","msg":"gobgpd started","time":"2024-12-18T09:44:16+09:00"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2024-12-18T09:44:16+09:00"}
{"Key":"2001:df8::2","Topic":"config","level":"info","msg":"Add Peer","time":"2024-12-18T09:44:16+09:00"}
{"Key":"2001:df8::2","Topic":"Peer","level":"info","msg":"Add a peer configuration","time":"2024-12-18T09:44:16+09:00"}
{"Key":"2001:df8::2","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2024-12-18T09:44:41+09:00"}

/opt/gobgp #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgpd -f rtb_gobgp_only.conf &
/opt/gobgp # {"level":"info","msg":"gobgpd started","time":"2024-12-18T09:44:32+09:00"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2024-12-18T09:44:32+09:00"}
{"Key":"2001:df8::1","Topic":"config","level":"info","msg":"Add Peer","time":"2024-12-18T09:44:32+09:00"}
{"Key":"2001:df8::1","Topic":"Peer","level":"info","msg":"Add a peer configuration","time":"2024-12-18T09:44:32+09:00"}
{"Key":"2001:df8::1","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2024-12-18T09:44:40+09:00"}

/opt/gobgp #
```

RTAとRTBのBGP neighborがEstablishとなります。  
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
2001:df8::2 64512 00:01:25 Establ      |        0         0
/opt/gobgp #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
2001:df8::1 64512 00:01:36 Establ      |        0         0
/opt/gobgp #
```
Received 0の表示から見て明らかですが、双方何も受信していません。  
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgp global rib -a ipv6
Network not in table
/opt/gobgp #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgp global rib -a ipv6
Network not in table
/opt/gobgp #
```
RTAからRTBへ経路を追加します。
prefix：`2001:df8:1111:2222::/64`
nexthop：`2001:df8::1`
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgp global rib add -a ipv6 2001:df8:1111:2222::/64 nexthop 2001:df8::1
/opt/gobgp #
```
RTBで経路を受信していることが確認できます。
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgp global rib -a ipv6
   Network                 Next Hop             AS_PATH              Age        Attrs
*> 2001:df8:1111:2222::/64 2001:df8::1                               00:00:34   [{Origin: ?} {LocalPref: 100}]
/opt/gobgp #
```
GoBGP(Control-Plane)では学習していますが、カーネルのFIBには連携していないため疎通することができません。
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # ip -6 r
2001:df8::/64 dev eth2 proto kernel metric 256 pref medium
fe80::/64 dev eth2 proto kernel metric 256 pref medium
/opt/gobgp # ping 2001:df8:1111:2222::
ping: connect: Network unreachable
/opt/gobgp #
```
ここでFRRの登場です。
### 6. FRR
今回は、以下の記事を参考に致しました。
[Ubuntu 20.04LTSでGoBGPを動かしてみた@masru0714](https://qiita.com/masru0714/items/b468ebcd4919b1589ecd)
  
apkコマンドで追加できるかを確認します。
最近見つけた[Alpine Linuxの公式パッケージリポジトリサイト](https://pkgs.alpinelinux.org/packages)を使うと簡単に調べられます。
![Alpine_v3.13_aarch64_frr_7.5.1-r0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/1d1295f1-21ec-4cbe-a69f-591ad64caa1b.png)
```
apk add frr
```
FRRのデーモンも動くことが確認できました。
```
~ # uname -n
RTA
~ # rc-service frr status
Status of watchfrr: running
Status of zebra: running
Status of staticd: running
~ #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # rc-service frr status
Status of watchfrr: running
Status of zebra: running
Status of isisd: running
Status of staticd: running
/opt/gobgp #
```
[/opt/gobgpディレクトリ]にGoBGPとFRRを記述した.confファイルを保存します。
```
RTA
!
rta_frr_and_gobgp.conf
!
[global.config]
  as = 64512
  router-id = "192.0.0.1"

[[neighbors]]
  [neighbors.config]
    peer-as = 64512
    neighbor-address = "2001:df8::2"
    local-as = 64512

    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
        afi-safi-name = "ipv6-unicast"

[zebra]
[zebra.config]
  enabled = true
  url = "unix:/var/run/frr/zserv.api"
  redistribute-route-type-list = ["connect"]
  software-name = "frr7.5.1"
  version = 6
```
```
RTB
!
rtb_frr_and_gobgp.conf
!
[global.config]
  as = 64512
  router-id = "192.0.0.2"

[[neighbors]]
  [neighbors.config]
    peer-as = 64512
    neighbor-address = "2001:df8::1"
    local-as = 64512

    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
        afi-safi-name = "ipv6-unicast"

[zebra]
[zebra.config]
  enabled = true
  url = "unix:/var/run/frr/zserv.api"
  redistribute-route-type-list = ["connect"]
  software-name = "frr7.5.1"
  version = 6
```
GoBGPのデーモンを起動します。
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgpd -f rta_frr_and_gobgp.conf &
/opt/gobgp # {"level":"info","msg":"gobgpd started","time":"2024-12-18T10:13:43+09:00"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2024-12-18T10:13:43+09:00"}
{"Topic":"Zebra","Version":6,"level":"info","msg":"success to connect to Zebra","time":"2024-12-18T10:13:43+09:00"}
{"Key":"2001:df8::2","Topic":"config","level":"info","msg":"Add Peer","time":"2024-12-18T10:13:43+09:00"}
{"Key":"2001:df8::2","Topic":"Peer","level":"info","msg":"Add a peer configuration","time":"2024-12-18T10:13:43+09:00"}
{"Key":"2001:df8::2","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2024-12-18T10:14:09+09:00"}

/opt/gobgp #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgpd -f rtb_frr_and_gobgp.conf &
/opt/gobgp # {"level":"info","msg":"gobgpd started","time":"2024-12-18T10:14:02+09:00"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2024-12-18T10:14:02+09:00"}
{"Topic":"Zebra","Version":6,"level":"info","msg":"success to connect to Zebra","time":"2024-12-18T10:14:02+09:00"}
{"Key":"2001:df8::1","Topic":"config","level":"info","msg":"Add Peer","time":"2024-12-18T10:14:02+09:00"}
{"Key":"2001:df8::1","Topic":"Peer","level":"info","msg":"Add a peer configuration","time":"2024-12-18T10:14:02+09:00"}
{"Key":"2001:df8::1","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2024-12-18T10:14:09+09:00"}

/opt/gobgp #
```
Establish
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
2001:df8::2 64512 00:00:39 Establ      |        1         1
/opt/gobgp #
/opt/gobgp # gobgp global rib -a ipv6
   Network              Next Hop             AS_PATH              Age        Attrs
*> 2001:df8::/64        ::                                        00:02:59   [{Origin: i} {Med: 0}]
*  2001:df8::/64        2001:df8::2                               00:02:33   [{Origin: i} {Med: 0} {LocalPref: 100}]
/opt/gobgp #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
2001:df8::1 64512 00:04:42 Establ      |        1         1
/opt/gobgp #
/opt/gobgp # gobgp global rib -a ipv6
   Network              Next Hop             AS_PATH              Age        Attrs
*> 2001:df8::/64        ::                                        00:05:00   [{Origin: i} {Med: 0}]
*  2001:df8::/64        2001:df8::1                               00:04:53   [{Origin: i} {Med: 0} {LocalPref: 100}]
/opt/gobgp #
```
RTAから経路情報を流します。
prefix：`2001:df8:1111:2222::/64`
nexthop：`2001:df8::1`
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgp global rib add -a ipv6 2001:df8:1111:2222::/64 nexthop 2001:df8::1
/opt/gobgp #
```
RTBで経路を受信していることが確認できます。
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
2001:df8::1 64512 00:07:24 Establ      |        2         2
/opt/gobgp #
/opt/gobgp # gobgp global rib -a ipv6
   Network                 Next Hop             AS_PATH              Age        Attrs
*> 2001:df8::/64           ::                                        00:07:37   [{Origin: i} {Med: 0}]
*  2001:df8::/64           2001:df8::1                               00:07:30   [{Origin: i} {Med: 0} {LocalPref: 100}]
*> 2001:df8:1111:2222::/64 2001:df8::1                               00:00:43   [{Origin: ?} {Med: 0} {LocalPref: 100}]
/opt/gobgp #
```


GoBGPから受け取った経路情報をRTBのカーネルFIBに連携できていることが確認できます。
`2001:df8:1111:2222::/64 via 2001:df8::1 dev eth2 proto bgp metric 20 pref medium`
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # ip -6 r
2001:df8::/64 dev eth2 proto kernel metric 256 pref medium
2001:df8:1111:2222::/64 via 2001:df8::1 dev eth2 proto bgp metric 20 pref medium
fe80::/64 dev eth2 proto kernel metric 256 pref medium
/opt/gobgp #
```
当然疎通確認も問題ないはずです。
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # ping -c 5 2001:df8:1111:2222::
PING 2001:df8:1111:2222::(2001:df8:1111:2222::) 56 data bytes
From 2001:df8::1 icmp_seq=1 Destination unreachable: No route
From 2001:df8::1 icmp_seq=2 Destination unreachable: No route
From 2001:df8::1 icmp_seq=3 Destination unreachable: No route
From 2001:df8::1 icmp_seq=4 Destination unreachable: No route
From 2001:df8::1 icmp_seq=5 Destination unreachable: No route

--- 2001:df8:1111:2222:: ping statistics ---
5 packets transmitted, 0 received, +5 errors, 100% packet loss, time 4104ms

/opt/gobgp #
```
すみません。RTAでIPv6を付与し忘れていました。
GoBGPの場合は、自身のルーティングテーブルに経路情報が無くてもpeerに広報することが出来るということが分かったので良しとします。
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # ip -br -6 a
lo               UNKNOWN        ::1/128
eth2@sit0        UP             2001:df8::1/64 fe80::280:bdff:fe51:11c5/64
/opt/gobgp #
```
一時的にIPv6を設定しておきます。
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # ip -6 addr add 2001:df8:1111:2222::/64 dev lo
/opt/gobgp #
/opt/gobgp # ip -br -6 a
lo               UNKNOWN        2001:df8:1111:2222::/64 ::1/128
eth2@sit0        UP             2001:df8::1/64 fe80::280:bdff:fe51:11c5/64
/opt/gobgp #
```
RTBからの疎通確認を再度実施します。
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # ip -6 r
2001:df8::/64 dev eth2 proto kernel metric 256 pref medium
2001:df8:1111:2222::/64 via 2001:df8::1 dev eth2 proto bgp metric 20 pref medium
fe80::/64 dev eth2 proto kernel metric 256 pref medium
/opt/gobgp #
/opt/gobgp # ping -c 5 2001:df8:1111:2222::
PING 2001:df8:1111:2222::(2001:df8:1111:2222::) 56 data bytes
64 bytes from 2001:df8:1111:2222::: icmp_seq=1 ttl=64 time=0.289 ms
64 bytes from 2001:df8:1111:2222::: icmp_seq=2 ttl=64 time=0.304 ms
64 bytes from 2001:df8:1111:2222::: icmp_seq=3 ttl=64 time=0.298 ms
64 bytes from 2001:df8:1111:2222::: icmp_seq=4 ttl=64 time=0.297 ms
64 bytes from 2001:df8:1111:2222::: icmp_seq=5 ttl=64 time=0.298 ms

--- 2001:df8:1111:2222:: ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4069ms
rtt min/avg/max/mdev = 0.289/0.297/0.304/0.004 ms
/opt/gobgp #
```
LXCのカーネルFIBに経路情報を渡すことができたので、コンテナ間で疎通できるようになることが分かりました。
また、GoBGPはControl-Planeであるということが良く分かりました。
### 7. SRv6設定可否を調査
FRRを調べていると通常のルータ感覚で簡単に設定できるようです。
残念ながら、最新のFRRではSRv6が設定できるのですが、F220のLXCではSRv6が設定できませんでした。
以下は、VirtualBoxで構築したAlpine 3.20 x86_64です。
FRR v10.0はSRv6が設定できます。
![Alpine_v_3.20_support_SRv6_on_FRR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/44772c8e-ffed-17a8-e067-61fb9ac0796c.png)
しかし、F220のLXCは、Alpine 3.13 aarch64です。
FRR v7.5.1はSRv6が設定できません。
![Alpine_v3.13_not_support_SRv6_on_FRR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/875fbc64-52e6-a7ad-576b-541119fe353c.png)

F220は筐体でSRv6をサポートしていないし、仕方ないかと...半ば諦めていました。  
偶然見つけたある記事「[GoBGPにBGP Extensions for the Mobile User Plane (MUP) SAFIを実装した話](https://blog.bbsakura.net/posts/implement-bgp-mup-to-gobgp)」のおかげでF220でもSRv6のパケットを見ることができるのではと思いました。
### 8. SRv6 MUPに挑戦
モバイルユーザープレーンでパフォーマンスと効率を向上させるために設計されたBGPの拡張機能が、BGP Extensions for the Mobile User Plane (MUP) だ！  
文字通りと言ってしまえばそれまでなのですが．．．。
F220のLXCで動かしているGoBGP`v3.31.0`が比較的新しいので、SRv6のパケットを見ることができるのではないかと淡い期待を抱き検証しました。

まだまだ勉強不足で自分の言葉で説明できない状態なので、先ずは「BGP-MUP SAFI：`85`、SRv6 MUP Extended Community：`0x0c`」これを目視するに挑戦します。

[/opt/gobgpディレクトリ]にGoBGPの.confファイルを保存します。
```
RTA
!
rta_srv6_mup_frr_and_gobgp.conf
!
[global.config]
  as = 64512
  router-id = "192.0.0.1"

[[neighbors]]
  [neighbors.config]
    peer-as = 64512
    neighbor-address = "2001:df8::2"
    local-as = 64512

    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
        afi-safi-name = "ipv6-mup"

[zebra]
[zebra.config]
  enabled = true
  url = "unix:/var/run/frr/zserv.api"
  redistribute-route-type-list = ["connect"]
  software-name = "frr7.5.1"
  version = 6
```
```
RTB
!
rtb_srv6_mup_frr_and_gobgp.conf
!
[global.config]
  as = 64512
  router-id = "192.0.0.2"

[[neighbors]]
  [neighbors.config]
    peer-as = 64512
    neighbor-address = "2001:df8::1"
    local-as = 64512

    [[neighbors.afi-safis]]
        [neighbors.afi-safis.config]
        afi-safi-name = "ipv6-mup"

[zebra]
[zebra.config]
  enabled = true
  url = "unix:/var/run/frr/zserv.api"
  redistribute-route-type-list = ["connect"]
  software-name = "frr7.5.1"
  version = 6
```
GoBGPデーモンを起動します。
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgpd -f rta_srv6_mup_frr_and_gobgp.conf &
/opt/gobgp # {"level":"info","msg":"gobgpd started","time":"2024-12-18T16:22:58+09:00"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2024-12-18T16:22:58+09:00"}
{"Topic":"Zebra","Version":6,"level":"info","msg":"success to connect to Zebra","time":"2024-12-18T16:22:58+09:00"}
{"Key":"2001:df8::2","Topic":"config","level":"info","msg":"Add Peer","time":"2024-12-18T16:22:58+09:00"}
{"Key":"2001:df8::2","Topic":"Peer","level":"info","msg":"Add a peer configuration","time":"2024-12-18T16:22:58+09:00"}
{"Key":"2001:df8::2","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2024-12-18T16:23:37+09:00"}

/opt/gobgp # gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
2001:df8::2 64512 00:00:32 Establ      |        0         0
/opt/gobgp #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgpd -f rtb_srv6_mup_frr_and_gobgp.conf &
/opt/gobgp # {"level":"info","msg":"gobgpd started","time":"2024-12-18T16:23:28+09:00"}
{"Topic":"Config","level":"info","msg":"Finished reading the config file","time":"2024-12-18T16:23:28+09:00"}
{"Topic":"Zebra","Version":6,"level":"info","msg":"success to connect to Zebra","time":"2024-12-18T16:23:28+09:00"}
{"Key":"2001:df8::1","Topic":"config","level":"info","msg":"Add Peer","time":"2024-12-18T16:23:28+09:00"}
{"Key":"2001:df8::1","Topic":"Peer","level":"info","msg":"Add a peer configuration","time":"2024-12-18T16:23:28+09:00"}
{"Key":"2001:df8::1","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2024-12-18T16:23:37+09:00"}

/opt/gobgp # gobgp neighbor
Peer           AS  Up/Down State       |#Received  Accepted
2001:df8::1 64512 00:00:43 Establ      |        0         0
/opt/gobgp #
```
BGP Establishになりました。まだ何も流していないので経路情報はありません。
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgp global rib -a ipv6-mup
Network not in table
/opt/gobgp #
```
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgp global rib -a ipv6-mup
Network not in table
/opt/gobgp #
```
RTAから経路情報を流します。
SRv6 locator Prefix：`2001:db8:a:b::/64`
DSD(Direct Segment Discovery)：`fc:00:1::`
RD(Route Distinguisher)：`100:100`
SRv6 behavior：`END_DT4`
RT(Route Target)：`10:10`
MUP：`10:10`
Nexthop：`2001:df8::1`
```
/opt/gobgp # uname -n
RTA
/opt/gobgp # gobgp global rib add -a ipv6-mup dsd fc:00:1:: rd 100:100 prefix 2001:db8:a:b::/64 locator-node-length 24 function-length 16 behavior
 END_DT4 rt 10:10 mup 10:10 nexthop 2001:df8::1
/opt/gobgp #
/opt/gobgp # gobgp global rib -a ipv6-mup
   Network                                 Next Hop             AS_PATH              Age        Attrs
*> [type:dsd][rd:100:100][prefix:fc:0:1::] 2001:df8::1                               00:01:26   [{Origin: ?} {Extcomms: [10:10], [10:10]} {Prefix SID attributes: {SRv6 L3 Service Attribute: {SRv6 Information Sub TLV: SID: 2001:db8:a:b:: Flag: 0 Endpoint Behavior: 19 {SRv6 Structure Sub Sub TLV: [ Locator Block Length: 64, Locator Node Length: 24, Function Length: 16, Argument Length: 0, Transposition Length: 0, Transposition Offset: 0] } } } }]
/opt/gobgp #
```
RTBで経路を受信しています。
```
/opt/gobgp # uname -n
RTB
/opt/gobgp # gobgp global rib -a ipv6-mup
   Network                                 Next Hop             AS_PATH              Age        Attrs
*> [type:dsd][rd:100:100][prefix:fc:0:1::] 2001:df8::1                               00:00:45   [{Origin: ?} {LocalPref: 100} {Extcomms: [10:10], [10:10]} {Prefix SID attributes: {SRv6 L3 Service Attribute: {SRv6 Information Sub TLV: SID: 2001:db8:a:b:: Flag: 0 Endpoint Behavior: 19 {SRv6 Structure Sub Sub TLV: [ Locator Block Length: 64, Locator Node Length: 24, Function Length: 16, Argument Length: 0, Transposition Length: 0, Transposition Offset: 0] } } } }]
/opt/gobgp #
```
横に長いので若干分かりにくいのですが、**SRv6**の情報が見えています。
`{Extcomms: [10:10], [10:10]} {Prefix SID attributes: {SRv6 L3 Service Attribute: {SRv6 Information Sub TLV: SID: 2001:db8:a:b:: Flag: 0 Endpoint Behavior: 19 {SRv6 Structure Sub Sub TLV: [ Locator Block Length: 64, Locator Node Length: 24, Function Length: 16, Argument Length: 0, Transposition Length: 0, Transposition Offset: 0] } } } }`

**SRv6 L3 Service Attribute**の中に`Endpoint Behavior: 19 `と見えます。
RTAからRTBへ流した経路情報で「SRv6 behavior：`END_DT4`」としているのが正しく反映されています。今のところ動作良好です。
[RFC8986 - 10.2.2. Initial Registrations](https://www.rfc-editor.org/rfc/rfc8986.html#name-initial-registrations)
![RFC8986_End.DT4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/278e948c-451d-6d19-8a09-82654e881390.png)





Wiresharkを使ってパケットを観察します。
![F220_wireshark_phisical_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/1328ab6a-8b07-9b04-4643-f19502f77060.png)
![F220_wireshark_phisical_photo.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/2708b05e-8989-67ca-4822-cffe2fdb5279.jpeg)
2022年12月時点では開発版のWiresharkが必要だったのですが、新しいバージョンを使用していれば通常版のWiresharkで`BGP-MUPのパケット`を見ることが出来ます。ちなみに当方の環境は、`Version 4.4.2`です。
![FITELnet_F220___SRv6_MUP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698685/43a04f9b-cae9-3298-c2d5-68d493ed7032.png)

BGP-MUPのパケットで、以下が確認できました。
Subsequent address family identifier (SAFI): BGP-MUP (`85`)
Type: Transitive MUP (`0x0c`)

■Internet Assigned Numbers Authority:IANA
[Subsequent Address Family Identifiers (SAFI) Parameters](https://www.iana.org/assignments/safi-namespace/safi-namespace.xhtml)
`Value:85` `Description:BGP-MUP SAFI`
[BGP Transitive Extended Community Types](https://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xml#transitive)
`Type Value:0x0c` `Name:SRv6 MUP Extended Community`

### 9. おわりに
F220で`(config)#segment-routing srv6`これが見えて喜び、commitしたら`ERROR: SR function is disabled by license.`と表示され悲しくなった9月末。GoBGPを使えば、F220でサポートしていないSRv6も「技術的には可能」と言えた（BGP-MUPパケットを見て喜んでいた）のが11月半ば。ギリギリアドカレに間に合って一安心しました。

高価なハードウェアが無くてもSRv6が使えるのは良い時代になりましたね。

SRv6をもっと勉強して自分の言葉で説明できるようになったら、続きを書きます。
最後までお読みいただきありがとうございました。