Edited at

Raspberry Pi2で、E-VPN / VXLAN動作を試してみる

More than 3 years have passed since last update.

従来、ネットワーク機器の内部機能は、ベンダプロプライエタリな領域であり、私たち利用者自らが、カスタマイズを行うことができませんでした。

ただ、最近は、SDN技術によって、ネットワーク機器のオープン化/ホワイトボックス化も着実に浸透しつつあります。

そんな折に、次のようなWeb記事

「機能がないなら作れば良い? SDN研究者から見た「ホワイトボックススイッチ」の現状と未来」

が公開されました。

とても興味深い内容なので、自分自身でも、Web記事で語られているE-VPNを試してみたいと思います。ただ、個人でCumulus Linuxを購入するのは、金銭面で敷居が高いので、今回は、Raspberry Pi2をホワイトボッックスと見立てて動作確認しております。


◼︎ E-VPN / VXLANとは、、

EVPN と VXLAN は、次世代データセンタでのスケール性/拡張性を兼ね備えた新たなネットワークアーキテクチャ技術です。技術の詳細については、ここでは触れません。

ただ、個人的な所感としては、IoT分野においても活用が期待される技術だと思います。

さらに、E-VPNの実装事例として、Github: osrg/goBGP にてオープンソースとして技術公開されているという点は、とても興味深いです。


◼︎ Raspberry Pi2環境整備

早速、E-VPN / VXLAN動作を試すRaspberry Pi2環境を取り掛かります。


(1) Ubuntu導入

基本的に、"ARM/RaspberryPi - Ubuntu Wiki"の記載どおり、作業を進めていきます。

https://wiki.ubuntu.com/ARM/RaspberryPi


  • SDフォーマッターなどを活用して、microSDHCカードをフォーマットする


  • Raspberry Pi2用Ubuntu 14.04 LTSイメージをダウンロードする


  • microSDHCカードが、どこにマウントされてるかを確認する


$ df

Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1 487849984 431973088 55364896 89% 54060634 6920612 89% /
devfs 659 659 0 100% 1140 0 100% /dev
map -hosts 0 0 0 100% 0 0 100% /net
map auto_home 0 0 0 100% 0 0 100% /home
/dev/disk2s1 30852096 4928 30847168 1% 0 0 100% /Volumes/NO NAME

 今回は、/dev/disk2s1にマウントされているようでした。


  • microSDHCカードをアンマウントする

$ diskutil unmount /dev/disk2s1

Volume NO NAME on disk2s1 unmounted
$ df
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1 487849984 431975632 55362352 89% 54060952 6920294 89% /
devfs 659 659 0 100% 1141 0 100% /dev
map -hosts 0 0 0 100% 0 0 100% /net
map auto_home 0 0 0 100% 0 0 100% /home


  • microSDHCカードに、Ubuntu 14.04 LTSイメージを書き込む

$ sudo dd bs=1m if=2015-04-06-ubuntu-trusty.img of=/dev/rdisk2

Password:
1792+0 records in
1792+0 records out
1879048192 bytes transferred in 201.154983 secs (9341296 bytes/sec)

 ddで書き込むときはdisk2s1の先頭にrをつけて、s1を削る必要があります。


  • Ubuntuを起動して、最新にアップグレードする(ユーザ名、パスワードは、デフォルト"ubuntu"と設定されている)

$ sudo apt-get upgrade

...

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"


  • SSHアクセス環境を整える

$ sudo apt-get update

$ sudo apt-get install openssh-server


  • rootディスク領域を拡張する

$ df -k

Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 1707856 563264 1039788 36% /
devtmpfs 468776 4 468772 1% /dev
none 4 0 4 0% /sys/fs/cgroup
none 94612 288 94324 1% /run
none 5120 0 5120 0% /run/lock
none 473056 0 473056 0% /run/shm
none 102400 0 102400 0% /run/user
/dev/mmcblk0p1 65390 19794 45596 31% /boot/firmware

$ sudo fdisk /dev/mmcblk0
[sudo] password for ubuntu:

Command (m for help): d
Partition number (1-4): 2

Command (m for help): n
Partition type:
p primary (1 primary, 0 extended, 3 free)
e extended
Select (default p): p
Partition number (1-4, default 2): 2
First sector (133120-30868479, default 133120):
Using default value 133120
Last sector, +sectors or +size{K,M,G} (133120-30868479, default 30868479):
Using default value 30868479

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

$ sudo reboot
...

$ sudo resize2fs /dev/mmcblk0p2
[sudo] password for ubuntu:
resize2fs 1.42.9 (4-Feb-2014)
Filesystem at /dev/mmcblk0p2 is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/mmcblk0p2 is now 3841920 blocks long.

ubuntu@ubuntu:~$ df -k
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 15100720 565128 13889496 4% /
devtmpfs 468776 4 468772 1% /dev
none 4 0 4 0% /sys/fs/cgroup
none 94612 288 94324 1% /run
none 5120 0 5120 0% /run/lock
none 473056 0 473056 0% /run/shm
none 102400 0 102400 0% /run/user
/dev/mmcblk0p1 65390 19794 45596 31% /boot/firmware


  • swap領域を確保する

$ sudo apt-get install dphys-swapfile

...

$ cat /proc/swaps
Filename Type Size Used Priority
/var/swap file 1910780 0 -1


  • Raspberry Pi2のUSBポートに、USB Ethernetアダプタを装着し、ネットワーク設定を行う

$ sudo vi /etc/network/interfaces 

...
auto eth0
iface eth0 inet static
address 192.168.100.101
netmask 255.255.255.0
gateway 192.168.100.1

auto eth1
iface eth1 inet static
address 192.168.0.1
netmask 255.255.255.0

auto eth2
iface eth2 inet manual
up ifconfig $IFACE 0.0.0.0 up
up ip link set $IFACE promisc on
down ip link set $IFACE promisc off
down ifconfig $IFACE down

 ちなみに、今回は、uplink側に"eth1"を、downlink側に"eth2"を割り当てる予定です。


  • DNS解決の設定を反映する

sudo vi /etc/resolvconf/resolv.conf.d/base

...
nameserver 192.168.100.1

$ sudo reboot
$ sudo apt-get update


(2) E-VPNルータ(通称:gobgp/goplane)の環境整備

次のようなE-VPN / VXLAN動作環境を作成します。

         (eth2) +---------+ (eth1)         mp-BGP               +--------+

... ----------+ | gobgp | +---------------------------------+ | BGP | +---- ...
|/goplane | 192.168.0.1/30 192.168.0.2/30 | Router |
+---------+ +--------+
< AS65000 > < AS65000 >

<----------- Target ----------> <-- out of scope -->


  • golangをインストールし、golang動作環境をセットアップする

$ wget https://storage.googleapis.com/golang/go1.6.2.linux-armv6l.tar.gz

$ sudo tar -C /usr/local -xzf go1.6.2.linux-armv6l.tar.gz
$ mkdir $HOME/golang
$ vi $HOME/.profile

...(snip)
export GOPATH=$HOME/golang
export PATH=$PATH:$GOPATH/bin:/usr/local/go/bin

$ source .profile
$ go version
go version go1.6.2 linux/arm


  • glideをインストールする

$ sudo apt-get install git

$ sudo apt-get install gcc
$ go get github.com/Masterminds/glide


  • glide活用により、goplaneをインストールする

$ cd $GOPATH/src/github.com

$ mkdir osrg
$ cd osrg
$ git clone https://github.com/osrg/goplane.git
$ cd goplane
$ glide install
$ glide up
$ cd goplaned
$ go install .

$ cd $GOPATH/bin
$ ls -l
total 25604
-rwxrwxr-x 1 ubuntu ubuntu 10504584 Jul 13 11:09 glide
-rwxrwxr-x 1 ubuntu ubuntu 15708831 Jul 13 11:22 goplaned


  • gobgpをインストールする

$ cd $GOPATH/src/github.com/osrg/goplane

$ cd vendor/github.com/osrg/gobgp/gobgp
$ go install .

$ cd $GOPATH/bin
$ ls -l|grep gobgp
-rwxrwxr-x 1 ubuntu ubuntu 15643728 Jul 13 11:27 gobgp


  • gobgpdをインストールする

$ cd $GOPATH/src/github.com/osrg/goplane

$ cd vendor/github.com/osrg/gobgp/gobgpd
$ go install .

$ cd $GOPATH/bin
$ ls -l|grep gobgpd
-rwxrwxr-x 1 ubuntu ubuntu 18679584 Jul 13 11:31 gobgpd


  • gobgp設定ファイルを作成する


$HOME/golang/bin/gobgpd.conf

[[neighbors]]

[[neighbors.afi-safis]]
[neighbors.afi-safis.config]
afi-safi-name = "ipv4-unicast"
[[neighbors.afi-safis]]
[neighbors.afi-safis.config]
afi-safi-name = "l2vpn-evpn"

[neighbors.config]
neighbor-address = "192.168.0.2"
peer-as = 65000
local-as = 65000

[global.config]
as = 65000
router-id = "192.168.0.1"



  • goplane設定ファイルを作成する


$HOME/golang/bin/goplaned.conf

[dataplane]

type = "netlink"
[[dataplane.virtual-network-list]]
member-interfaces = [ "eth2",]
vni = 10
vxlan-port = 8472
rd = "65000:10"
vtep-interface = "vtep10"
etag = 10
sniff-interfaces = [ "eth2",]


◼︎ 実際、gobgp/goplane起動して、E-VPNを試してみる


(1) gobgp/goplaneを起動する

それでは、実際に、gobgp/goplaneを起動して、E-VPN / VXLANが動作させてみます。


  • gobgpdを起動する

$ cd $HOME/golang/bin

$ sudo ./gobgpd -f gobgpd.conf
[sudo] password for ubuntu:
{"level":"info","msg":"gobgpd started","time":"2016-07-13T12:30:47Z"}
{"level":"info","msg":"finished reading the config file","time":"2016-07-13T12:30:47Z"}
{"level":"info","msg":"Peer 192.168.0.2 is added","time":"2016-07-13T12:30:47Z"}
{"level":"info","msg":"Add a peer configuration for 192.168.0.2","time":"2016-07-13T12:30:47Z"}
{"Key":"192.168.0.2","State":"BGP_FSM_OPENCONFIRM","Topic":"Peer","level":"info","msg":"Peer Up","time":"2016-07-13T12:33:58Z"}


  • goplanedを起動する

$ cd $HOME/golang/bin

$ sudo ./goplaned -f goplaned.conf
[sudo] password for ubuntu:
{"level":"info","msg":"VirtualNetwork 65000:10 is added","time":"2016-07-13T12:31:27Z"}

 対抗側でも同様に、gobgp/goplaneを起動することにより、BGPピアが開設されました。


(2) gobgp/goplane動作状態を確認する

別ターミナルより、gobgpコマンドを用いてgobgp/goplane動作状態を、いろいろと確認してみます。


  • BGPピア状態を確認する

$ gobgp neighbor 192.168.0.2

BGP neighbor is 192.168.0.2, remote AS 65000
BGP version 4, remote router ID 192.168.0.2
BGP state = BGP_FSM_ESTABLISHED, up for 00:21:22
BGP OutQ = 0, Flops = 0
Hold time is 90, keepalive interval is 30 seconds
Configured hold time is 90, keepalive interval is 30 seconds
Neighbor capabilities:
BGP_CAP_MULTIPROTOCOL:
ipv4-unicast: advertised and received
l2vpn-evpn: advertised and received
BGP_CAP_ROUTE_REFRESH: advertised and received
BGP_CAP_FOUR_OCTET_AS_NUMBER: advertised and received
Message statistics:
Sent Rcvd
Opens: 2 2
Notifications: 0 0
Updates: 6 13
Keepalives: 49 49
Route Refesh: 0 0
Discarded: 0 0
Total: 57 64
Route statistics:
Advertised: 3
Received: 2
Accepted: 2


  • VTEP状態を確認する

$ gobgp global rib -a evpn

Network Next Hop AS_PATH Age Attrs
*> [type:macadv][rd:65000:10][esi:single-homed][etag:10][mac:40:6c:8f:59:31:af][ip:<nil>][labels:[10]]0.0.0.0 00:04:50 [{Origin: i} {Extcomms: [VXLAN], [65000:10]}]
*> [type:macadv][rd:65000:10][esi:single-homed][etag:10][mac:8e:7d:29:85:e9:c6][ip:<nil>][labels:[10]]192.168.0.2 00:02:03 [{Origin: i} {LocalPref: 100} {Extcomms: [VXLAN], [65000:10]}]
*> [type:multicast][rd:65000:10][etag:10][ip:192.168.0.1] 0.0.0.0 00:04:52 [{Origin: i} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 192.168.0.1} {Extcomms: [65000:10]}]
*> [type:multicast][rd:65000:10][etag:10][ip:192.168.0.2] 192.168.0.2 00:02:21 [{Origin: i} {LocalPref: 100} {Extcomms: [65000:10]} {Pmsi: type: ingress-repl, label: 0, tunnel-id: 192.168.0.2}]

問題なく、E-VPN / VXLANは、動作しているようです。


(3) エンド端末から、DataPlane通信を確認してみる

いよいよ、E-VPN / VXLANを用いて作成されたDataPlane通信路を用いて、実際にデータ流通を確認してみたいと思います。


  • 事前準備として、自側インタフェスのネットワーク設定を確認しておく

$ ifconfig

...(snip)

en5: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV>
ether 40:6c:8f:59:31:af
inet6 fe80::426c:8fff:fe59:31af%en5 prefixlen 64 scopeid 0x1c
inet 192.168.3.2 netmask 0xffffff00 broadcast 192.168.3.255
nd6 options=1<PERFORMNUD>
media: autoselect (100baseTX <full-duplex,flow-control>)
status: active


  • いよいよ、Pingコマンドをうってみる

$ ping 192.168.3.1

PING 192.168.3.1 (192.168.3.1): 56 data bytes
64 bytes from 192.168.3.1: icmp_seq=0 ttl=64 time=2.917 ms
64 bytes from 192.168.3.1: icmp_seq=1 ttl=64 time=1.327 ms
64 bytes from 192.168.3.1: icmp_seq=2 ttl=64 time=1.354 ms
64 bytes from 192.168.3.1: icmp_seq=3 ttl=64 time=1.311 ms
64 bytes from 192.168.3.1: icmp_seq=4 ttl=64 time=1.283 ms
^C
--- 192.168.3.1 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.283/1.638/2.917/0.640 ms


  • さらに、MACアドレスの学習のようすを確認してみる

$ arp -a

? (192.168.3.1) at 8e:7d:29:85:e9:c6 on en5 ifscope [ethernet]

E-VPN / VXLANにより作成されたDataPlane通信路を用いて、ICMP ECHO Request / Replyが期待どおり動作しました。


(4) DataPlane通信のようすを、パケットキャプチャで確認してみる


  • TCPDUMPによるVXLANパケット内部を確認する

![tcpdump.png](vxlan.png

VXLANによって、ICMP ECHO Request / Replyが転送されているようすが確認できました!


◼︎ 終わりに...

今回は、あくまでも、Raspberry Pi2というホワイトボックスを活用して、E-VPNを動作させたに過ぎません。もちろん、DataPlane通信におけるパフォーマンス面は、全く期待できるものではありません。単に、pingが通信できただけです。

しかしながら、従来、ネットワーク機器の内部機能として、ベンダプロプライエタリな領域に、オープンソースなソフトウェアと、ホワイトボックスを組み合わせれば、私たち利用者自らが自由なネットワーク機能ブロックを構築できる将来への可能性を確認できたと思います。

そして、将来は、IoT時代にも、ホワイトボックス製品は、浸透していくものだと思います。


◼︎ 参照元