P4 の simple_switch を使って Docker コンテナ間で ping する

Docker コンテナ間で P4 をデバッグできれば色々デバッグが捗るのでできるようにする(今回は mininet は使わない)。

今回使う P4 プログラムは https://github.com/p4lang/tutorials/tree/master/exercises/basic

(Optional) iptables, masq, forward を無効化する

ハマらないために、 `/etc/docker/daemon.json` で設定しても良い。

{
  "ip-forward": true,
  "ip-masq": true,
  "iptables":true
}

お互いに通信できないコンテナを作る

Docker network を別々にすれば(`simple_switch` がなければ)お互いに通信できない。

 $ docker network create network1 --subnet=172.18.100.0/24
 $ docker network create network2 --subnet=172.18.200.0/24

コンテナをたてる

IP とネットワークを指定する。

 $ docker run --rm -it --ip=172.18.100.2 --network=network1 --name=container1 busybox sh
 $ docker run --rm -it --ip=172.18.200.2 --network=network2 --name=container2 busybox sh  

simple_switch をたてる

コンテナの veth にアタッチする。Bridge interface でも良い。

 $ sudo simple_switch build/basic.json -i 1@veth65e0b28 -i 2@veth79593d4 --log-console

仮想スイッチにエントリを入れる

MAC アドレスは Docker コンテナ側から見た MAC アドレスであることに注意。

$ simple_switch_CLI
 Obtaining JSON from switch…
 Done
 Control utility for runtime P4 table manipulation
 RuntimeCmd: table_add MyIngress.ipv4_lpm MyIngress.ipv4_forward 172.18.200.2/32 => 02:42:d1:d2:6b:16 2
 Adding entry to lpm match table MyIngress.ipv4_lpm
 match key:           LPM-ac:12:c8:02/32
 action:              MyIngress.ipv4_forward
 runtime data:        02:42:d1:d2:6b:16  00:02
 Entry has been added with handle 0
 RuntimeCmd: table_add MyIngress.ipv4_lpm MyIngress.ipv4_forward 172.18.100.2/32 => 02:42:d3:9d:be:4f 1
 Adding entry to lpm match table MyIngress.ipv4_lpm
 match key:           LPM-ac:12:64:02/32
 action:              MyIngress.ipv4_forward
 runtime data:        02:42:d3:9d:be:4f  00:01
 Entry has been added with handle 12

これで ping が相互に届き、返事もできるようになる。

なお、MAC アドレスを(外から見たものにする等して)間違えていた場合、宛先インターフェースまでは届くものの返事はしない。