EC2でOpenFlowを動かしてみる on VPC

基本情報

  • 同じサブネット上に構築
  • Amazon Linux AMI 2012.03 (64bit / m1.small) × 3台

サーバ構成


  • source-01 (10.0.10.1)
  • switch-01 (10.0.10.2)
    • 『net.ipv4.ip_forward = 1』
    • 『net.ipv4.conf.default.rp_filter = 0』
    • Source Dest. Checkはdisabled
  • dest-01 (10.0.10.3)

下準備

ICMPのリダイレクトはしない


shell> tail /etc/sysctl.conf
...
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
shell> sudo sysctl -p
どうも再起動しないと有効にならないような、、ネットワークだけ再起動すればいいのかな、、、、

IPv6は無効にする


shell> cat /etc/modprobe.d/disable-ipv6.conf
options ipv6 disable=1
shell> sudo /sbin/shutdown -r now

ルーティングテーブル


[ec2-user@source-01 ~]$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 10.0.0.1 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 10.0.10.2 255.255.0.0 UG 0 0 0 eth0
10.0.10.2 * 255.255.255.255 UH 0 0 0 eth0

[ec2-user@switch-01 ~]$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 10.0.0.1 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 * 255.255.0.0 U 0 0 0 eth0

[ec2-user@dest-01 ~]$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 10.0.0.1 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 10.0.10.2 255.255.0.0 UG 0 0 0 eth0
10.0.10.2 * 255.255.255.255 UH 0 0 0 eth0

一応、パケットがswitch-01を通ることを確認。


[ec2-user@switch-01 ~]$ sudo tcpdump -i any icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
10:51:19.163751 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 48388, seq 1, length 64
10:51:19.163786 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 48388, seq 1, length 64
10:51:19.164116 IP 10.0.10.3 > 10.0.10.1: ICMP echo reply, id 48388, seq 1, length 64
10:51:19.164121 IP 10.0.10.3 > 10.0.10.1: ICMP echo reply, id 48388, seq 1, length 64
10:51:20.164668 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 48388, seq 2, length 64
10:51:20.164691 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 48388, seq 2, length 64
10:51:20.165047 IP 10.0.10.3 > 10.0.10.1: ICMP echo reply, id 48388, seq 2, length 64
10:51:20.165054 IP 10.0.10.3 > 10.0.10.1: ICMP echo reply, id 48388, seq 2, length 64
10:51:21.165626 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 48388, seq 3, length 64
10:51:21.165648 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 48388, seq 3, length 64
10:51:21.166052 IP 10.0.10.3 > 10.0.10.1: ICMP echo reply, id 48388, seq 3, length 64
10:51:21.166059 IP 10.0.10.3 > 10.0.10.1: ICMP echo reply, id 48388, seq 3, length 64

Trema/OpenFlowのインストール

OpenFlowのインストール

switch-01にOpenFlowをインストールする。


sudo yum install -y git automake pkgconfig libtool gcc make
git clone git://openflow.org/openflow.git
cd openflow
./boot.sh
./configure
make
sudo make install

Tremaのインストール

switch-01にTremaをインストールする。


sudo yum install -y ruby ruby-devel ruby-irb libpcap-devel sqlite-devel
git clone git://github.com/trema/trema.git
cd trema
./build.rb

NOXよりインストールはらくですな。

一応、動作確認。


[ec2-user@switch-01 trema]$ ./trema run ./src/examples/hello_trema/hello_trema.rb -c src/examples/hello_trema/hello_trema.conf
Hello 0xabc from ./src/examples/hello_trema/hello_trema.rb!

Trema/OpenFlowの起動

最初にtrema を起動。とりあえずexamplesのdumper.rbを使ってみる。ドラえもん化はしない


[ec2-user@switch-01 trema]$ ./trema run ./src/examples/dumper/dumper.rb

次にofdatapath を起動。ドラえもん化しないので別のsshセッションで起動。


[ec2-user@switch-01 ~]$ sudo /usr/local/bin/ofdatapath punix:/var/run/dp0.sock -i eth0
Apr 22 11:08:42|00001|datapath|ERR|eth0 device has assigned IP address 10.0.10.2
RTNETLINK answers: No such file or directory
エラーはとりあえず無視で、、、

最後に、ofprotocolを起動。『connected』って出たら成功。


[ec2-user@switch-01 ~]$ sudo /usr/local/bin/ofprotocol unix:/var/run/dp0.sock tcp:127.0.0.1
Apr 22 11:13:51|00001|secchan|INFO|OpenFlow reference implementation version 1.0.0
Apr 22 11:13:51|00002|secchan|INFO|OpenFlow protocol version 0x01
Apr 22 11:13:51|00003|secchan|WARN|new management connection will receive asynchronous messages
Apr 22 11:13:51|00004|rconn|INFO|unix:/var/run/dp0.sock: connecting...
Apr 22 11:13:51|00005|rconn|INFO|tcp:127.0.0.1: connecting...
Apr 22 11:13:51|00006|rconn|INFO|unix:/var/run/dp0.sock: connected
Apr 22 11:13:51|00007|port_watcher|INFO|Datapath id is 002320fc2d1a
Apr 22 11:13:51|00008|port_watcher|INFO|Identified data path local port as "tap0".
Apr 22 11:13:51|00009|rconn|INFO|tcp:127.0.0.1: connected

dumper.rbの実行結果

tremaのコンソールに大量のダンプが出力される。


[packet_in]
datapath_id: 0x2320fc2d1a
transaction_id: 0x0
buffer_id: 0xffffffff
total_len: 60
in_port: 1
reason: 0x0
data: 0266c5386fa60266c50000010800450000284d4040007706151bd204bb6e0a000a02c22f001685e6bcae523ff763501073f04bf10000000000000000
[packet_in]
datapath_id: 0x2320fc2d1a
transaction_id: 0x0
buffer_id: 0xffffffff
total_len: 60
in_port: 1
reason: 0x0
data: 0266c5386fa60266c50000010800450000284d4140007706151ad204bb6e0a000a02c22f001685e6bcae523ff7db501073d24b970000000000000000
[packet_in]
datapath_id: 0x2320fc2d1a
transaction_id: 0x0
buffer_id: 0xffffffff

dumper.rbに手を加える

source-01からdest-01にicmpを飛ばす。


[ec2-user@source-01 ~]$ ping 10.0.10.3

icmpのパケットはこんな感じなので、


11:22:43.309981 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 31037, seq 112, length 64
0x0000: 4500 0054 0000 4000 3f01 13a6 0a00 0a01 E..T..@.?.......
0x0010: 0a00 0a03 0800 a6b6 793d 0070 03ea 934f ........y=.p...O
0x0020: 0000 0000 7d8f 0400 0000 0000 1011 1213 ....}...........
0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
0x0050: 3435 3637 4567
すごくてきとーにフィルタリングしてみる。

修正はこんなかんじ。

--- ./src/examples/dumper/dumper.rb.orig        2012-04-22 11:00:55.139038131 +0000
+++ ./src/examples/dumper/dumper.rb     2012-04-22 11:29:57.794697464 +0000
@@ -76,6 +76,9 @@


   def packet_in datapath_id, message
+    data = message.data.unpack("H*").join
+    return unless data =~ /45000054/
+
     info "[packet_in]"
     info "  datapath_id: #{ datapath_id.to_hex }"
     info "  transaction_id: #{ message.transaction_id.to_hex }"


tcpdumpの出力とdumper.rbの出力を横に並べてみると、キャプチャされている様子がわかる

tcpdump


11:35:05.439661 IP 10.0.10.1 > 10.0.10.3: ICMP echo request, id 26187, seq 1, length 64
0x0000: 4500 0054 0000 4000 3f01 13a6 0a00 0a01 E..T..@.?.......
0x0010: 0a00 0a03 0800 4926 664b 0001 e9ec 934f ......I&fK.....O
0x0020: 0000 0000 067e 0600 0000 0000 1011 1213 .....~..........
0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
0x0050: 3435 3637 4567
11:35:05.439706 IP 10.0.10.3 > 10.0.10.1: ICMP echo reply, id 26187, seq 1, length 64
0x0000: 4500 0054 7b81 0000 4001 d724 0a00 0a03 E..T{...@..$....
0x0010: 0a00 0a01 0000 5126 664b 0001 e9ec 934f ......Q&fK.....O
0x0020: 0000 0000 067e 0600 0000 0000 1011 1213 .....~..........
0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
0x0050: 3435 3637 4567

dumper.rb


[packet_in]
datapath_id: 0x232079b7c3
transaction_id: 0x0
buffer_id: 0xcdd
total_len: 98
in_port: 1
reason: 0x0
data: 0266c5386fa60266c530940a08004500005400004000400112a60a000a010a000a0308004926664b0001e9ec934f00000000067e060000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
[packet_in]
datapath_id: 0x232079b7c3
transaction_id: 0x0
buffer_id: 0xcde
total_len: 98
in_port: 1
reason: 0x0
data: 0266c5386fa60266c534821b0800450000547b8100004001d7240a000a030a000a0100005126664b0001e9ec934f00000000067e060000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637

所感

  • 性能はともかくキャプチャ代わりに使うことはできた
  • パケットの書き換えはまだ試していない
  • ofdatapathのエラーは対応方法あるのかなぁ…