モチベーション
Brocade vRouter(vyatta)がAT&Tにより買収され、今後サポートしないと無慈悲に通知されてしまったので、vyattaの代替となりそうな仮想ルーターを探していました。
vyattaは仮想アプライアンスになっていて、OSとソフトウェア製品群さらに管理インターフェースが一体となった製品です。これはこれでコンフィグに集中できて良いのだけど、バージョンアップが難しかったり、他のソフトウェアを同居させたりツールをインストールするといった事ができず、使い始めてからの維持管理が難しい製品でした。
よって仮想アプライアンスではなくソフトウェアとして扱えるFD.io vppを試してみました。
FD.io vppについて
FD.ioは、Linux Foundationのオープンソース(OSS)のプロジェクトであり、vppはその中核的な存在のサブプロジェクトにあたります。
特徴としては、DPDKによる兎に角速いパケットフォワーディング。そしてPluginによる機能の柔軟さがあり、vRouterやvSwitchとしてだけでなく、LoadBalancerやFirewallとしても利用可能です。
なお、vppはCisco社から寄贈されたものであり、商用で鍛えられた技術がベースになっているそうです。
今回やってみること
vppの使い勝手を確認するために、手元のMacbook ProのVirtualBox上にubuntu16.04をインストールし、vppをインストールしてみます。
vppは、開発のスパンが短く3ヶ月単位でリリースされています。現在のバージョンは17.7と数日前にリリースされた新しいものです。
仮想マシン
ネットワークの準備
ホストオンリーネットワークをいくつか作成しておきます。Macのターミナルで実行してください。
vboxnet0を一旦削除し、再作成します。このネットワークをMacbookからアクセスするための管理ネットワークとします。
$ VBoxManage dhcpserver remove --ifname vboxnet0
$ VBoxManage hostonlyif remove vboxnet0
$ VBoxManage hostonlyif create
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Interface 'vboxnet0' was successfully created
$ VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.0.1
$ VBoxManage dhcpserver add --ifname vboxnet0 --ip 192.168.0.1 --netmask 255.255.255.0 --lowerip 192.168.0.100 --upperip 192.168.0.200
$ VBoxManage dhcpserver modify --ifname vboxnet0 --enable
vboxnet1を作成します。仮想ルーターのインターフェース用です。
$ VBoxManage hostonlyif create
vboxnet2を作成します。仮想ルーターのインターフェース用です。
$ VBoxManage hostonlyif create
ifconfigで確認してください。
$ ifconfig
・・・・
vboxnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 0a:00:27:00:00:00
inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255
vboxnet1: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 0a:00:27:00:00:01
vboxnet2: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 0a:00:27:00:00:02
仮想マシンの作成
VirtualBoxで仮想マシンを作成します。
私が試した構成は以下のとおりです。メモリが少なすぎるとvppインストール後にOSが起動しなくなりますので注意してください。
- CPU: 2コア
- メモリ: 4GB
- NICは4枚
- 1杖目: vppインストールのために、インターネット接続用。NATを割り当て
- 2,3枚目: vppのインターフェース用。ホストオンリーアダプラーを割り当て。アダプタタイプはIntel PRO/1000 MT Server (82545EM) を選択。
- 4枚目: 管理用。Macから接続できるようにしました。
OSインストール
Ubuntu Server 16.04LTSをISOからインストールします。特別なことはありません。
ネットワークI/F設定
大事な所なのですが、インターネット接続用と、管理ネットワーク用のインターフェースのみをアップしてください。vppのインターフェースはダウンしたままで良いです。どうせ見えなくなります。
vppはDPDKを利用しています。DPDKで利用するインターフェースはOS側からは見えず、専用のコマンドで確認する事になります。
4つのインターフェースのうち、enp0s8とenp0s9がダウンのままであることを確認してください。これは後ほどvppのインターフェースとなります。
$ vi /etc/network/interfaces
$ cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto enp0s17
iface enp0s17 inet dhcp
auto enp0s10
iface enp0s10 inet dhcp
hirofumimatsu@ubuntu:~$ sudo ifup enp0s10
[sudo] hirofumimatsu のパスワード:
$ sudo ifup enp0s10
Internet Systems Consortium DHCP Client 4.3.3
Copyright 2004-2015 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Listening on LPF/enp0s10/08:00:27:3d:ea:63
Sending on LPF/enp0s10/08:00:27:3d:ea:63
Sending on Socket/fallback
DHCPDISCOVER on enp0s10 to 255.255.255.255 port 67 interval 3 (xid=0xdfd2bc71)
DHCPREQUEST of 192.168.0.1 on enp0s10 to 255.255.255.255 port 67 (xid=0x71bcd2df)
DHCPOFFER of 192.168.0.100 from 192.168.0.1
DHCPACK of 192.168.0.100 from 192.168.0.1
bound to 192.168.0.100 -- renewal in 36321 seconds.
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s8: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 08:00:27:e9:ef:48 brd ff:ff:ff:ff:ff:ff
3: enp0s9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 08:00:27:f6:07:c8 brd ff:ff:ff:ff:ff:ff
4: enp0s10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:0c:fa:7a brd ff:ff:ff:ff:ff:ff
inet 192.168.0.100/24 brd 192.168.0.255 scope global enp0s10
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe0c:fa7a/64 scope link
valid_lft forever preferred_lft forever
5: enp0s17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:3d:ea:63 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s17
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe3d:ea63/64 scope link
valid_lft forever preferred_lft forever
$
vppのインストール
Quick Start Guideが用意されていますので、これに従いインストールできます。
$ sudo vi /etc/apt/sources.list.d/99fd.io.list
$ cat /etc/apt/sources.list.d/99fd.io.list
deb [trusted=yes] https://nexus.fd.io/content/repositories/fd.io.stable.1707.ubuntu.xenial.main/ ./
# apt-get update
ヒット:1 http://jp.archive.ubuntu.com/ubuntu xenial InRelease
ヒット:2 http://jp.archive.ubuntu.com/ubuntu xenial-updates InRelease
ヒット:3 http://jp.archive.ubuntu.com/ubuntu xenial-backports InRelease
取得:4 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
無視:5 https://nexus.fd.io/content/repositories/fd.io.stable.1707.ubuntu.xenial.main ./ InRelease
無視:7 https://nexus.fd.io/content/repositories/fd.io.stable.1707.ubuntu.xenial.main ./ Release.gpg
178 kB を 3秒 で取得しました (53.8 kB/s)
パッケージリストを読み込んでいます... 完了
$ sudo apt-get install vpp-lib vpp vpp-plugins
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
libapr1 libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python python-minimal python2.7 python2.7-minimal
提案パッケージ:
python-doc python-tk python2.7-doc binutils binfmt-support
以下のパッケージが新たにインストールされます:
libapr1 libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python python-minimal python2.7 python2.7-minimal
vpp vpp-lib vpp-plugins
アップグレード: 0 個、新規インストール: 11 個、削除: 0 個、保留: 119 個。
7,616 kB のアーカイブを取得する必要があります。
この操作後に追加で 31.9 MB のディスク容量が消費されます。
続行しますか? [Y/n] Y
取得:1 http://jp.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpython2.7-minimal amd64 2.7.12-1ubuntu0~16.04.1 [339 kB]
取得:2 http://jp.archive.ubuntu.com/ubuntu xenial-updates/main amd64 python2.7-minimal amd64 2.7.12-1ubuntu0~16.04.1 [1,295 kB]
取得:3 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 python-minimal amd64 2.7.11-1 [28.2 kB]
取得:4 http://jp.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpython2.7-stdlib amd64 2.7.12-1ubuntu0~16.04.1 [1,884 kB]
取得:5 http://jp.archive.ubuntu.com/ubuntu xenial-updates/main amd64 python2.7 amd64 2.7.12-1ubuntu0~16.04.1 [224 kB]
取得:6 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 libpython-stdlib amd64 2.7.11-1 [7,656 B]
取得:7 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 python amd64 2.7.11-1 [137 kB]
取得:8 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 libapr1 amd64 1.5.2-3 [86.0 kB]
取得:9 https://nexus.fd.io/content/repositories/fd.io.stable.1707.ubuntu.xenial.main ./ vpp-lib 17.07-rc2~20-gf302825~b37 [1,682 kB]
取得:10 https://nexus.fd.io/content/repositories/fd.io.stable.1707.ubuntu.xenial.main ./ vpp 17.07-rc2~20-gf302825~b37 [270 kB]
取得:11 https://nexus.fd.io/content/repositories/fd.io.stable.1707.ubuntu.xenial.main ./ vpp-plugins 17.07-rc2~20-gf302825~b37 [1,663 kB]
7,616 kB を 9秒 で取得しました (807 kB/s)
以前に未選択のパッケージ libpython2.7-minimal:amd64 を選択しています。
(データベースを読み込んでいます ... 現在 59867 個のファイルとディレクトリがインストールされています。)
.../libpython2.7-minimal_2.7.12-1ubuntu0~16.04.1_amd64.deb を展開する準備をしています ...
libpython2.7-minimal:amd64 (2.7.12-1ubuntu0~16.04.1) を展開しています...
以前に未選択のパッケージ python2.7-minimal を選択しています。
.../python2.7-minimal_2.7.12-1ubuntu0~16.04.1_amd64.deb を展開する準備をしています ...
python2.7-minimal (2.7.12-1ubuntu0~16.04.1) を展開しています...
以前に未選択のパッケージ python-minimal を選択しています。
.../python-minimal_2.7.11-1_amd64.deb を展開する準備をしています ...
python-minimal (2.7.11-1) を展開しています...
以前に未選択のパッケージ libpython2.7-stdlib:amd64 を選択しています。
.../libpython2.7-stdlib_2.7.12-1ubuntu0~16.04.1_amd64.deb を展開する準備をしています ...
libpython2.7-stdlib:amd64 (2.7.12-1ubuntu0~16.04.1) を展開しています...
以前に未選択のパッケージ python2.7 を選択しています。
.../python2.7_2.7.12-1ubuntu0~16.04.1_amd64.deb を展開する準備をしています ...
python2.7 (2.7.12-1ubuntu0~16.04.1) を展開しています...
以前に未選択のパッケージ libpython-stdlib:amd64 を選択しています。
.../libpython-stdlib_2.7.11-1_amd64.deb を展開する準備をしています ...
libpython-stdlib:amd64 (2.7.11-1) を展開しています...
man-db (2.7.5-1) のトリガを処理しています ...
mime-support (3.59ubuntu1) のトリガを処理しています ...
libpython2.7-minimal:amd64 (2.7.12-1ubuntu0~16.04.1) を設定しています ...
python2.7-minimal (2.7.12-1ubuntu0~16.04.1) を設定しています ...
Linking and byte-compiling packages for runtime python2.7...
python-minimal (2.7.11-1) を設定しています ...
以前に未選択のパッケージ python を選択しています。
(データベースを読み込んでいます ... 現在 60613 個のファイルとディレクトリがインストールされています。)
.../python_2.7.11-1_amd64.deb を展開する準備をしています ...
python (2.7.11-1) を展開しています...
以前に未選択のパッケージ libapr1:amd64 を選択しています。
.../libapr1_1.5.2-3_amd64.deb を展開する準備をしています ...
libapr1:amd64 (1.5.2-3) を展開しています...
以前に未選択のパッケージ vpp-lib を選択しています。
.../vpp-lib_17.07-rc2~20-gf302825~b37_amd64.deb を展開する準備をしています ...
vpp-lib (17.07-rc2~20-gf302825~b37) を展開しています...
以前に未選択のパッケージ vpp を選択しています。
.../vpp_17.07-rc2~20-gf302825~b37_amd64.deb を展開する準備をしています ...
vpp (17.07-rc2~20-gf302825~b37) を展開しています...
以前に未選択のパッケージ vpp-plugins を選択しています。
.../vpp-plugins_17.07-rc2~20-gf302825~b37_amd64.deb を展開する準備をしています ...
vpp-plugins (17.07-rc2~20-gf302825~b37) を展開しています...
man-db (2.7.5-1) のトリガを処理しています ...
libc-bin (2.23-0ubuntu5) のトリガを処理しています ...
ureadahead (0.100.0-19) のトリガを処理しています ...
libpython2.7-stdlib:amd64 (2.7.12-1ubuntu0~16.04.1) を設定しています ...
python2.7 (2.7.12-1ubuntu0~16.04.1) を設定しています ...
libpython-stdlib:amd64 (2.7.11-1) を設定しています ...
python (2.7.11-1) を設定しています ...
libapr1:amd64 (1.5.2-3) を設定しています ...
vpp-lib (17.07-rc2~20-gf302825~b37) を設定しています ...
vpp (17.07-rc2~20-gf302825~b37) を設定しています ...
* Applying /etc/sysctl.d/10-console-messages.conf ...
kernel.printk = 4 4 1 7
* Applying /etc/sysctl.d/10-ipv6-privacy.conf ...
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2
* Applying /etc/sysctl.d/10-kernel-hardening.conf ...
kernel.kptr_restrict = 1
* Applying /etc/sysctl.d/10-link-restrictions.conf ...
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
* Applying /etc/sysctl.d/10-magic-sysrq.conf ...
kernel.sysrq = 176
* Applying /etc/sysctl.d/10-network-security.conf ...
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1
* Applying /etc/sysctl.d/10-ptrace.conf ...
kernel.yama.ptrace_scope = 1
* Applying /etc/sysctl.d/10-zeropage.conf ...
vm.mmap_min_addr = 65536
* Applying /etc/sysctl.d/80-vpp.conf ...
vm.nr_hugepages = 1024
vm.max_map_count = 3096
vm.hugetlb_shm_group = 0
kernel.shmmax = 2147483648
* Applying /etc/sysctl.d/99-sysctl.conf ...
* Applying /etc/sysctl.conf ...
vpp-plugins (17.07-rc2~20-gf302825~b37) を設定しています ...
libc-bin (2.23-0ubuntu5) のトリガを処理しています ...
ureadahead (0.100.0-19) のトリガを処理しています ...
vppの起動と確認
$ ps auxw|grep vpp
root 2572 99.4 1.1 3528040 47952 ? Rsl 18:00 1:04 /usr/bin/vpp -c /etc/vpp/startup.conf
hirofum+ 2627 0.0 0.0 15256 980 pts/0 S+ 18:01 0:00 grep --color=auto vpp
$ systemctl status vpp
● vpp.service - vector packet processing engine
Loaded: loaded (/lib/systemd/system/vpp.service; enabled; vendor preset: enabled)
Active: active (running) since 土 2017-07-22 18:00:25 JST; 1min 19s ago
Process: 2567 ExecStartPre=/sbin/modprobe uio_pci_generic (code=exited, status=0/SUCCESS)
Process: 2564 ExecStartPre=/bin/rm -f /dev/shm/db /dev/shm/global_vm /dev/shm/vpe-api (code=exited, status=0/SUCCESS)
Main PID: 2572 (vpp_main)
Tasks: 3
Memory: 39.2M
CPU: 1min 19.628s
CGroup: /system.slice/vpp.service
└─2572 /usr/bin/vpp -c /etc/vpp/startup.conf
7月 22 18:00:25 ubuntu vpp[2572]: load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_export_test_plugi
7月 22 18:00:25 ubuntu vpp[2572]: load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/acl_test_plugin.so
7月 22 18:00:25 ubuntu vpp[2572]: load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/gtpu_test_plugin.so
7月 22 18:00:25 ubuntu vpp[2572]: load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/dpdk_test_plugin.so
7月 22 18:00:25 ubuntu vpp[2572]: load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/lb_test_plugin.so
7月 22 18:00:25 ubuntu vpp[2572]: load_one_plugin:63: Loaded plugin: /usr/lib/vpp_api_test_plugins/ioam_trace_test_plugin
7月 22 18:00:25 ubuntu vpp[2572]: vlib_pci_bind_to_uio: Skipping PCI device 0000:00:11.0 as host interface enp0s17 is up
7月 22 18:00:25 ubuntu vpp[2572]: vlib_pci_bind_to_uio: Skipping PCI device 0000:00:0a.0 as host interface enp0s10 is up
7月 22 18:00:27 ubuntu vpp[2572]: /usr/bin/vpp[2572]: dpdk_ipsec_process:239: not enough Cryptodevs, default to OpenSSL I
7月 22 18:00:27 ubuntu /usr/bin/vpp[2572]: dpdk_ipsec_process:239: not enough Cryptodevs, default to OpenSSL IPsec
$
vppのインターフェースが2つ確認できます。先ほどダウンのままとしたenp0s8(pci@0000:00:08.0)とenp0s9(pci@0000:00:09.0)のデバイスはvpp側のインターフェースとして自動的に設定されました。
$ sudo vppctl show int
Name Idx State Counter Count
GigabitEthernet0/8/0 1 down
GigabitEthernet0/9/0 2 down
local0 0 down
ここでOSのプロンプトからip aコマンドで確認してみると、OS側からはenp0s8とenp0s9は見えなくなっています。
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
4: enp0s10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:0c:fa:7a brd ff:ff:ff:ff:ff:ff
inet 192.168.0.100/24 brd 192.168.0.255 scope global enp0s10
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe0c:fa7a/64 scope link
valid_lft forever preferred_lft forever
5: enp0s17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:3d:ea:63 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s17
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe3d:ea63/64 scope link
valid_lft forever preferred_lft forever
$
vppのインターフェース設定
IPアドレスを設定します。
$ sudo vppctl set int ip address GigabitEthernet0/8/0 192.168.10.10/24
$ sudo vppctl set int state GigabitEthernet0/8/0 up
$ sudo vppctl set int ip address GigabitEthernet0/9/0 192.168.20.10/24
$ sudo vppctl set int state GigabitEthernet0/9/0 up
IPアドレスが設定されたことを確認します。
$ sudo vppctl show interface address
GigabitEthernet0/8/0 (up):
192.168.10.10/24
GigabitEthernet0/9/0 (up):
192.168.20.10/24
local0 (dn):
I/F設定の保存
インターフェース設定の保存はできないようです。
rebootしたあとインターフェースのアドレスはクリアされています。
$ sudo vppctl show int address
GigabitEthernet0/8/0 (dn):
GigabitEthernet0/9/0 (dn):
local0 (dn):
再起動しても設定内容が消えないようにするには、起動時に設定を書き込むようにしなければいけないようです。
$ sudo vi setupinterface
$ cat setupinterface
set int ip address GigabitEthernet0/8/0 192.168.10.10/24
set int state GigabitEthernet0/8/0 up
set int ip address GigabitEthernet0/9/0 192.168.20.10/24
set int state GigabitEthernet0/9/0 up
ip route add 0.0.0.0/0 via 192.168.10.1
$ sudo cp -p startup.conf startup.conf_orig
$ sudo vi startup.conf
$ diff -u startup.conf_orig startup.conf
--- startup.conf_orig 2017-07-16 00:53:02.000000000 +0900
+++ startup.conf 2017-07-22 18:38:32.017656802 +0900
@@ -3,6 +3,7 @@
nodaemon
log /tmp/vpp.log
full-coredump
+ exec /etc/vpp/setupinterface
}
api-trace {
$
ルーティングのテスト
2つのインターフェースにテスト用のVMを接続し、ルーターとして動作していることを確認しました。
コマンドライン
一部のコマンドは、Command-line Interface (CLI) Guideに書かれているようです。あとはお好きなように。
冗長化
無さそうですね。pacemakerを使えばいけるかもしれません。