SONiCでVXLANを使ってみた

# はじめに

以前、[使うのをあきらめたという記事](https://qiita.com/masru0714/items/71f2d8e0efa4c28f991d)を書いたのですが、実装が進んだのか先程試してみたら通信できたので、設定をざっと書きます。

# 基本

- 今回は1:1でトンネルをつくります
- トンネルの中に複数のVNIのパケットがL2分離されて通るイメージになります
- VNIはSONiCのVLANと1:1でマッピングされます

# 設定

SONiC-VS(仮想マシン版SONiC)を使います。2021年８月２日にビルドしたものを使いました。環境構築はGNS3でやりました。2台のSONiC仮想マシンの`Ethernet0`どうしが接続されている前提になります。

`config vxlan`コマンドが実装されていました。よかった。

## 1台目 (sonic1)

```
sudo config hostname sonic1
sudo config interface ip add Ethernet0 192.168.0.1/24
sudo config vxlan add Vxlan0 192.168.0.1
sudo config vlan add 10
sudo config vxlan map add Vxlan0 10 1001
sudo config interface ip add Vlan10 172.21.0.1/24
```

- VXLANのパケットを運ぶ外側(outer)のIPアドレスは`192.168.0.1/24`、`Ethernet0`につけます。
- VXLANを定義します。source IPに先程つけた`192.168.0.1`を指定します。
- マッピング用のVLANを作成します。VLAN IDはここでは10とします。
- 内側(innner)はVLANとマッピングします。先程作ったVLAN ID 10と、VXLANのVNI 1001を対応させます。
- VLANにIPアドレスを割り振ります。`172.21.0.1/24`をつけます。

## 2台目 (sonic2)

```
sudo config hostname sonic2
sudo config interface ip add Ethernet0 192.168.0.2/24
sudo config vxlan add Vxlan0 192.168.0.2
sudo config vlan add 20
sudo config vxlan map add Vxlan0 20 1001
sudo config interface ip add Vlan10 172.21.0.2/24
```

- VXLANのパケットを運ぶ外側(outer)のIPアドレスは`192.168.0.2/24`、`Ethernet0`につけます。
- VXLANを定義します。source IPに先程つけた`192.168.0.2`を指定します。
- マッピング用のVLANを作成します。VLAN IDはここでは20とします。
- 内側(innner)はVLANとマッピングします。先程作ったVLAN ID 20と、VXLANのVNIはsonic1と同じ1001を対応させます。
- VLANにIPアドレスを割り振ります。`172.21.0.2/24`をつけます。

# 動作検証

1. outerの疎通確認。sonic1から `ping 192.168.0.2` - OK
1. innerの疎通確認。sonic1から `ping 172.21.0.2` - **NG**

あれ?

# 状況確認

`show vxlan interface` してみました。

```
admin@sonic1:~$ show vxlan interface 
VTEP Information:

	VTEP Name : Vxlan0, SIP  : 192.168.0.1
	Source interface  : Not Configured
admin@sonic1:~$ 
```

ん? どういうこと?

# 調査

親切なドキュメントは見当たらないようなのでソースコードを見てみました。どうやら`show vxlan interface`で表示される`Source interface`はループバックインタフェースのようでした。つまりouterのIPアドレスをループバックインタフェースにつけておく(BGPのように)ということ? 冗長化を考えたらたしかに合理的かも。

と思って`Ethernet0`につけてたのを`Loopback0`とか用意してつけてみるもやっぱり動かず。これについてはいったん忘れることにします。

接続点をパケットキャプチャしてもLLDPのパケットしか流れてない。うーん。

ソースコード内を探索していたらテストコードがしっかり書かれていることに気づきました。`src/sonic-swss/tests/test_vxlan_tunnel.py` を眺めてみます。すると、下記の記述が目に留まりました。

```json
    attrs = [
            ("src_ip", src_ip),
    ]

    if not skip_dst_ip:
        attrs.append(("dst_ip", dst_ip))

    # create the VXLAN tunnel Term entry in Config DB
    create_entry_tbl(
        conf_db,
        "VXLAN_TUNNEL", '|', name,
        attrs,
    )
```

ん? `dst_ip`?

# dst_ipを追加する

上記の設定をした上で、dst_ipの設定を加えます。が、実は現在`config vxlan add` ではdst_ipを指定することができません。なので、ひとまず双方、`sudo config save`で設定を保存。そのあと保存した`/etc/sonic/config_db.json`を編集して再起動。編集内容は下記で、`"src_ip"`だけだったところに`"dst_ip"`の行を加えました。JSONなので`"src_ip"`行の末尾にカンマを忘れずに。

```json:sonic1
    "VXLAN_TUNNEL": {
        "Vxlan0": {
            "src_ip": "192.168.0.1",
            "dst_ip": "192.168.0.2"
        }
    },
```

```json:sonic2
    "VXLAN_TUNNEL": {
        "Vxlan0": {
            "src_ip": "192.168.0.2",
            "dst_ip": "192.168.0.1"
        }
    },
```

# 再検証

1. outerの疎通確認。sonic1から `ping 192.168.0.2` - OK
1. innerの疎通確認。sonic1から `ping 172.21.0.2` - **OK**
1. innerの疎通確認。sonic2から `ping 172.21.0.1` - **OK**

念のためパケットキャプチャして確認しました。下記はsonic2から`ping`を送ったときのものです。

```
Frame 137: 148 bytes on wire (1184 bits), 148 bytes captured (1184 bits) on interface -, id 0
Ethernet II, Src: 0c:d0:50:39:86:00 (0c:d0:50:39:86:00), Dst: 0c:d0:50:1a:7e:00 (0c:d0:50:1a:7e:00)
Internet Protocol Version 4, Src: 192.168.0.2, Dst: 192.168.0.1
User Datagram Protocol, Src Port: 55988, Dst Port: 4789
Virtual eXtensible Local Area Network
Ethernet II, Src: 0c:d0:50:39:86:00 (0c:d0:50:39:86:00), Dst: 0c:d0:50:1a:7e:00 (0c:d0:50:1a:7e:00)
Internet Protocol Version 4, Src: 172.21.0.2, Dst: 172.21.0.1
Internet Control Message Protocol
```

いけました。よかった。

# まとめ

- 1.1でVXLAN tunnelを作り、SONiCどうしで通信できました
- outerのIPはふつうに足につけました
- VNIはVLAN IDにマッピングします
- dst_ipを省略するとmulticastで相手を探すはずですがパケットは送信されてませんでした
- dst_ipを指定すると無事相手と繋がりました。ただしCLIで設定できない点に注意
- ループバックのIPを使う方法は後で試してみます

# 感想

dst_ipをCLIで設定できないのは罠。もうひとつ、VNETっていったいなんだったんだ? (ご存知の方教えてください)