それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

macvtap でできた仮想マシンとホストと通信してみる。macvlan/macvtap

macvtap でできた仮想マシンとホストと通信してみる。

macvtap でできた仮想マシンとホストと通信してみる。

macvtap を使った場合、ホスト・ゲスト間の通信ができない。

しかたないので、ホストに別にNICをmacvlan で定義して、そこを経由して通信するとしてみる。

sudo ip link add dev macvlan1 link eth1 type macvlan mode bridge
sudo ip addr add 192.168.11.112/24 dev macvlan1
sudo ip link set macvlan1 up

macvtap に向けてパケットを送ってみる、応答がきて通信がができることがわかる。

ping 192.168.11.103 -I macvlan1

削除するには

sudo ip link set macvlan0 down
sudo ip addr del 192.168.11.112/24 dev macvlan0
sudo ip link del dev macvlan0 

ちゃんと macvlan 経由で出ていくことがわかる。

takuya@ubuntu:~$ ip route get 192.168.11.103
192.168.11.103 dev macvlan1 src 192.168.11.101 uid 1001
    cache
    

ちょっと理解が追いつかず怖いなと思った箇所が次の通り。

パケットはごちゃまぜ(?)になって eth0から出たはずのパケットは、内部でeth1 へ到達している。

ホストに [eth1,eth0] の2物理NICがあって、macvlan1@eth1として設定。ゲストでは macvtap はmacvtap@eth0 に割り当てたのだが、

ゲスト側のネットワークは次の通り

root@OpenWrt:/# ip a
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
    link/ether 52:54:00:ab:ff:35 brd ff:ff:ff:ff:ff:ff
    inet 192.168.11.12/24 brd 192.168.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:feab:ff35/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
    link/ether 52:54:00:3a:09:af brd ff:ff:ff:ff:ff:ff
    inet 192.168.11.107/24 brd 192.168.11.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe3a:9af/64 scope link
       valid_lft forever preferred_lft forever

ホスト側のネットワークは次の通り。

takuya@ubuntu:~$ ip a
### もともとの物理NIC
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether dc:a6:32:dd:23:c4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.11.111/24 brd 192.168.11.255 scope global dynamic eth0
       valid_lft 42628sec preferred_lft 42628sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether e8:fc:af:c7:aa:21 brd ff:ff:ff:ff:ff:ff
### ここが macvlan
5: macvlan1@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether aa:85:1b:0e:e4:59 brd ff:ff:ff:ff:ff:ff
    inet 192.168.11.101/24 brd 192.168.11.255 scope global dynamic macvlan1
       valid_lft 42623sec preferred_lft 42623sec
### ゲストの eth0
10: macvtap0@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 500
    link/ether 52:54:00:ab:ff:35 brd ff:ff:ff:ff:ff:ff
### ゲストの eth1
11: macvtap1@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 500
    link/ether 52:54:00:3a:09:af brd ff:ff:ff:ff:ff:ff

[ホスト macvtap0@eth0 , ゲスト側eth0]、[ホスト macvtap1@eth1 , ゲスト側eth1]、がそれぞれペアとなる割当にしてある。

ここで、ホストの macvlan1@eth1 から ゲストの eth0 へ向かってping を投げると・・・到達するんですよね。ホスト外部には出ません。これがちょっと気持ち悪いと思った点。

macvlan はホスト内部で処理されてしまう。つまりホスト内部のvlan という扱いなのですかね。ちょっとモヤっとする。

ホスト・ゲストで通信ができた。

これで無事に macvtap と疎通する事ができるとわかる。

ただし、これを起動時に最初からやるのはしんどいのです。if-up / if-down スクリプトをこのご時世に書いて管理するのもちょっと。

そこでnetworkd が動いているなら、それを使うと、macvlan を起動時にと来ることができるはずです。

3つのファイルを作ります。

ぱぱっとファイルを作ります。

touch /etc/systemd/network/{eth1.network,macvlan1.netdev,macvlan1.network}

つくった。

takuya@ubuntu:~$ ll  /etc/systemd/network/*
-rw-r--r-- 1 root root 46  3月 24 22:25 /etc/systemd/network/eth1.network
-rw-r--r-- 1 root root 60  3月 24 22:22 /etc/systemd/network/macvlan1.netdev
-rw-r--r-- 1 root root 44  3月 24 22:18 /etc/systemd/network/macvlan1.network

eth1 に macvlan1 をbridge定義する 設定 macvlan1 をネットワークデバイスとする 設定 macvlan1 にIPアドレスを割り当てる 設定

ですかね

/etc/systemd/network/eth1.network

[Match]
Name=eth1

[Network]
MACVLAN=macvlan1

/etc/systemd/network/macvlan1.netdev

[NetDev]
Name=macvlan1
Kind=macvlan

[MACVLAN]
Mode=bridge

/etc/systemd/network/macvlan1.network

[Match]
Name=macvlan1

[Network]
DHCP=ipv4

再起動

sudo systemctl restart systemd-networkd.service

結果を確認

takuya@ubuntu:~$ sudo systemctl status systemd-networkd.service
● systemd-networkd.service - Network Service
     Loaded: loaded (/lib/systemd/system/systemd-networkd.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2021-03-24 22:48:36 JST; 7s ago
TriggeredBy: ● systemd-networkd.socket
       Docs: man:systemd-networkd.service(8)
   Main PID: 3526 (systemd-network)
     Status: "Processing requests..."
      Tasks: 1 (limit: 9257)
     CGroup: /system.slice/systemd-networkd.service
             └─3526 /lib/systemd/systemd-networkd

 3月 24 22:48:36 ubuntu systemd-networkd[3526]: macvlan1: Gained IPv6LL
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: eth1: Gained IPv6LL
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: eth0: Gained IPv6LL
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: Enumeration completed
 3月 24 22:48:36 ubuntu systemd[1]: Started Network Service.
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: macvlan1: IPv6 successfully enabled
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: eth1: IPv6 successfully enabled
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: eth0: IPv6 successfully enabled
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: macvlan1: DHCPv4 address 192.168.11.101/24 via 192.168.11.1
 3月 24 22:48:36 ubuntu systemd-networkd[3526]: eth0: DHCPv4 address 192.168.11.111/24 via 192.168.11.1

これで、networkd でも macvlan が作成されるとわかる。

netplan は非対応

raspi 4 に ubuntu を入れているので、ubuntu だしnetplan で設定しようかと思ったが、netplan は macvlan を作れないらしい。

なので if-up/if-down を書くか、/etc/network/interfacesを書くか、networkd を書く必要がある。今回は networkd に書くことで対応した。

参考資料

https://tenforward.hatenablog.com/entry/20111221/1324466720

https://major.io/2015/10/26/systemd-networkd-and-macvlan-interfaces/