OCI VCN上にVXLAN Overlay Networkを構築してブロードキャスト通信をやってみた

パブリッククラウド上の仮想ネットワークでは、ブロードキャストやマルチキャストといった1:多の通信は利用できないケースに遭遇することがあります。
Oracle Linuxのipコマンドを利用してVXLANを構築し、OCI VCN上でブロードキャスト通信を実現してみました。

# 検証環境
Oracle Linux 8が稼働するE5 Computeインスタンスを利用して検証を行いました。

```
[opc@instance01 ~]$ uname -r
5.15.0-205.149.5.1.el8uek.x86_64
```

OCIに構築した環境は下記の図のようになっています。
![Pasted Graphic 66.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/18586d81-a900-1a6c-d787-6ddd9aecd431.png)

構築したインスタンスのVCN上のPrivate IPアドレスと、VXLAN上のPrivate IPアドレスの対応は下記のようになっています。
|Instance Name|Private IP on VCN|Private IP on VXLAN|
|---|---|---|
|instance01|192.168.0.254|171.16.1.1|
|instance02|192.168.0.180|172.16.1.2|
|instance03|192.168.0.110|172.16.1.3|


# UDP通信で利用するポートの開放

VXLANの通信には、UDP 8472番ポートが利用されます。
また、ブロードキャストの検証で利用するアプリケーション用にUDP 50001番ポートを解放しました。

```
[opc@instance01 ~]$ sudo firewall-cmd --add-port=8472/udp --zone=public --permanent
success
[opc@instance01 ~]$ sudo firewall-cmd --add-port=50001/udp --zone=public --permanent
success
[opc@instance01 ~]$ sudo systemctl restart firewalld
```


# VXLANの構築

事前準備が終わりしたので各インスタンスにてVXLANの構築作業を行います。

### instance01
ユニキャストモードでvxlan0を構築します。
```
[opc@instance01 ~]$ sudo ip link add vxlan0 type vxlan id 10 remote 192.168.0.254 dstport 8472 dev enp0s5
```

設定したvxlan0の情報を確認します。
```
[opc@instance01 ~]$ ip -d link show vxlan0
3: vxlan0: <BROADCAST,MULTICAST> mtu 8950 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether c2:74:8e:a8:42:e2 brd ff:ff:ff:ff:ff:ff promiscuity 0  allmulti 0 minmtu 68 maxmtu 65535 
    vxlan id 10 remote 192.168.0.254 dev enp0s5 srcport 0 0 dstport 8472 ttl auto ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 
```

vxlan01をUPします。
```
[opc@instance01 ~]$ sudo ip link set vxlan0 up
```

Instance01にPrivate IPを割当てます。
```
[opc@instance01 ~]$ sudo ip addr add 172.16.1.1/24 broadcast 172.16.1.255 dev vxlan0
```
他のインスタンスと通信ができるようにネットワークブリッジを設定を行います。
```
[opc@instance01 ~]$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 192.168.0.180
[opc@instance01 ~]$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 192.168.0.110
```


### instance02
下記の設定を投入します。
```
[opc@instance02 ~]$ sudo ip link add vxlan0 type vxlan id 10 remote 192.168.0.180 dstport 8472 dev enp0s5
[opc@instance02 ~]$ sudo ip link set vxlan0 up
[opc@instance02 ~]$ sudo ip addr add 172.16.1.2/24 broadcast 172.16.1.255 dev vxlan0
[opc@instance02 ~]$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 192.168.0.254
[opc@instance02 ~]$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 192.168.0.110
```


### instance03
下記の設定を投入します。
```
[opc@instance03 ~]$ sudo ip link add vxlan0 type vxlan id 10 remote 192.168.0.110 dstport 8472 dev enp0s5
[opc@instance03 ~]$ sudo ip link set vxlan0 up
[opc@instance03 ~]$ sudo ip addr add 172.16.1.3/24 broadcast 172.16.1.255 dev vxlan0
[opc@instance03 ~]$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 192.168.0.254
[opc@instance03 ~]$ sudo bridge fdb append 00:00:00:00:00:00 dev vxlan0 dst 192.168.0.110
```

# ブロードキャスト通信の疎通確認
Pythonで作成したブロードキャストアプリケーションを利用してVXLAN（172.16.1.0/24）の疎通確認を行います。

### 送信プログラム（Instance01から実行）
```sender.py
from socket import socket, AF_INET, SOCK_DGRAM,SOL_SOCKET, SO_BROADCAST
import sys

HOST = ''
PORT = 50001
ADDRESS = "172.16.1.255"  # 送信先にVXLANのBroadcastアドレスを指定

s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
#s.bind((HOST, PORT))

while True:
    msg = input("> ")
    s.sendto(msg.encode(), (ADDRESS, PORT))
    if msg == "\q":
        break

s.close()
sys.exit
```

### 受信プログラム（Instance01, Instance02, Instance03から実行）

```receiver.py
from socket import socket, AF_INET, SOCK_DGRAM
import sys

HOST = ""
PORT = 50001

s = socket(AF_INET, SOCK_DGRAM)
s.bind((HOST, PORT))

while True:
    msg, address = s.recvfrom(8192)
    if msg.decode("utf-8") == "\q":
        print("Sender is closed")
        break

    print("message:", msg.decode("utf-8"), "\nfrom:", address[0])

s.close()
sys.exit()
```

# 実行結果
![Broadcat.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/03a56245-790b-b521-26c7-6975219470eb.gif)


# 参考情報
https://tech-mmmm.blogspot.com/2017/10/vxlancentos-7vxlan.html
https://ameblo.jp/oyasai10/entry-10590541669.html