RESTCONF APIを使ってフローを書き換えてみる

※記事内で一部のソースコードが突き抜けて表示されている箇所があります。マウスオーバーするとSyntaxHighlighterというツールがポップアップされますので、別ウィンドウで表示させたりクリップボードにコピーしたりしてご活用ください。
OpenDaylightの特徴の一つとして、多くのNorthbound Inrerface(NBI)が用意されている点があげられます。MD-SALがインターフェースを抽象化することで、OpenDaylightを利用するさまざまなアプリケーションからのAPI呼び出しを容易にできるようになっています。第2回と第3回ではOpenDaylightとOpenStackを連携させた環境の構築を行いましたが、OpenStackにおいてもNeutronプラグイン経由でOpenDaylightに用意されているAPIを呼び出すことで、ネットワークに関する様々なコントロールができるようになっています。
そこで、今回はOpenDaylightのRESTCONF APIに注目します。RESTCONF APIを利用して、OpenDaylightのデータストアに登録されているフローの取得と更新を行ってみます。
RESTCONF API
そもそもRESTCONF APIとは、NETCONFデータストア内のYANGで定義されたデータにアクセスするためのHTTPを使ったRESTライクなプロトコルのことです。OpenDaylightでもRESTCONF APIを使えば、OpenDaylightのデータストアに登録されたフローをコントロールできます。
OpenDaylight RESTCONF API Documentation
OpenDaylightを起動すると、RESTCONF API ExplorerがOSGi bundleとして実行されるようになっています。RESTCONF API ExplorerはAPIドキュメントなのですが、Swaggerの仕様に基づいており、レンダリングされてSwagger UIとして表示されます。OpenDaylightを実行しているノードに対して、ブラウザから以下の様にアクセスすると、APIの一覧を表示したり、テストリクエストを投げたりすることができます。
http://192.168.0.10:8181/apidoc/explorer/index.html
RESTCONF APIを使ってみる
それでは、RESTCONF APIを試してみます。環境は第2回で構築したOpenDaylight+OpenStack環境を使います。
フローの取得
RESTCONFのHTTPリクエストとレスポンスの内容は、非常に長くなる場合があり記述するのが面倒です。そこで、ここではクライアントコマンドでオペレーションしていきます。まず、python-odlclientをインストールします。
1 | ~$ sudo pip install python-odlclient |
フローを取得するためには、取得したいノードのノードIDを知る必要があります。そこで、まず最初にノード一覧を取得してコンピュートノードのノードIDを確認します。
1 | ~$ export ODL_HOST=192.168.0.10 |
2 | ~$ odl node list |
3 | +--------------------------+--------------+-----------------+-------------+--------------+----------+ |
4 | | id | ip_address | connector_count | table_count | hardware | software | |
5 | +--------------------------+--------------+-----------------+-------------+--------------+----------+ |
6 | | openflow:267140174830659 | 192.168.0.11 | 4 | 11 | Open vSwitch | 2.0.2 | # コンピュートノード |
7 | | openflow:235547676672585 | 192.168.0.10 | 5 | 11 | Open vSwitch | 2.0.2 | # コントローラノード |
8 | +--------------------------+--------------+-----------------+-------------+--------------+----------+ |
ちなみに、ノード一覧を取得するためにcurlコマンドを使ってリクエストすると、以下の様に膨大な量のレスポンスが返ってくるため、うまく加工しない限り人間が読めたものではありません。
1 | ~$ curl -s -H "Accept: application/json" -u "admin:admin" -X GET http://192.168.0.10:8181/restconf/operational/opendaylight-inventory:nodes |
2 | {"nodes":{"node":[{"id":"openflow:267140174830659","node-connector":[{"id":"openflow:267140174830659:1","flow-node-inventory:hardware-address":"76:6B:A2:F5:73:75",‥‥‥‥} |
ノードごとのノードIDがわかったので、コンピュートノードのフローを取得してみます。
01 | ~/devstack$ odl flow list openflow:267140174830659 |
02 | +---------------------------------------------------+----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
03 | | id | table_id | priority | match | instructions | |
04 | +---------------------------------------------------+----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
05 | | LLDP | 0 | 32768 | ethernet-match: {"ethernet-type": {"type": 35020}} | output-action: {"max-length": 65535, "output-node-connector": "CONTROLLER"} | |
06 | | LocalMac_1056_7_fa:16:3e:db:c3:fd | 0 | 32768 | in-port: "openflow:267140174830659:7", ethernet-match: {"ethernet-source": {"address": "FA:16:3E:DB:C3:FD"}} | set-field: {"tunnel": {"tunnel-id": 1056}}, openflowplugin-extension-nicira-action:nx-reg-load: {"dst": {"start": 0, "end": 31, "nx-reg": "nicira-match:nxm-nx-reg0"}, "value": 1}, go-to-table: {"table_id": 20} | |
07 | | LocalMac_1056_6_fa:16:3e:c5:8b:b9 | 0 | 32768 | in-port: "openflow:267140174830659:6", ethernet-match: {"ethernet-source": {"address": "FA:16:3E:C5:8B:B9"}} | set-field: {"tunnel": {"tunnel-id": 1056}}, openflowplugin-extension-nicira-action:nx-reg-load: {"dst": {"start": 0, "end": 31, "nx-reg": "nicira-match:nxm-nx-reg0"}, "value": 1}, go-to-table: {"table_id": 20} | |
08 | | TunnelIn_1056_1 | 0 | 32768 | tunnel: {"tunnel-id": 1056}, in-port: "openflow:267140174830659:1" | openflowplugin-extension-nicira-action:nx-reg-load: {"dst": {"start": 0, "end": 31, "nx-reg": "nicira-match:nxm-nx-reg0"}, "value": 2}, go-to-table: {"table_id": 20} | |
09 | | DropFilter_7 | 0 | 8192 | in-port: "openflow:267140174830659:7" | Drop | |
10 | | DropFilter_6 | 0 | 8192 | in-port: "openflow:267140174830659:6" | Drop | |
11 | | DEFAULT_PIPELINE_FLOW_0 | 0 | 0 | | go-to-table: {"table_id": 20} | |
12 | | DEFAULT_PIPELINE_FLOW_20 | 20 | 0 | | go-to-table: {"table_id": 30} | |
13 | | DEFAULT_PIPELINE_FLOW_30 | 30 | 0 | | go-to-table: {"table_id": 40} | |
14 | | Egress_DHCP_Client_Permit_ | 40 | 61012 | udp-destination-port: 67, ip-match: {"ip-protocol": 17}, udp-source-port: 68, ethernet-match: {"ethernet-type": {"type": 2048}} | go-to-table: {"table_id": 50} | |
15 | | Egress_DHCP_Server_7_DROP_ | 40 | 61011 | in-port: "openflow:267140174830659:7", udp-destination-port: 68, ethernet-match: {"ethernet-type": {"type": 2048}}, udp-source-port: 67, ip-match: {"ip-protocol": 17} | Drop | |
16 | | Egress_DHCP_Server_6_DROP_ | 40 | 61011 | in-port: "openflow:267140174830659:6", udp-destination-port: 68, ethernet-match: {"ethernet-type": {"type": 2048}}, udp-source-port: 67, ip-match: {"ip-protocol": 17} | Drop | |
17 | | #UF$TABLE*40-9 | 40 | 61010 | arp-source-hardware-address: {"address": "FA:16:3E:C5:8B:B9"}, ethernet-match: {"ethernet-type": {"type": 2054}} | go-to-table: {"table_id": 50} | |
18 | | #UF$TABLE*40-11 | 40 | 61010 | arp-source-hardware-address: {"address": "FA:16:3E:DB:C3:FD"}, ethernet-match: {"ethernet-type": {"type": 2054}} | go-to-table: {"table_id": 50} | |
19 | | Egress_IP1056_fa:16:3e:c5:8b:b9_Permit_ | 40 | 61007 | ethernet-match: {"ethernet-source": {"address": "FA:16:3E:C5:8B:B9"}, "ethernet-type": {"type": 2048}} | go-to-table: {"table_id": 50} | |
20 | | Egress_IP1056_fa:16:3e:db:c3:fd_Permit_ | 40 | 61007 | ethernet-match: {"ethernet-source": {"address": "FA:16:3E:DB:C3:FD"}, "ethernet-type": {"type": 2048}} | go-to-table: {"table_id": 50} | |
21 | | Egress_Allow_VM_IP_MAC_6fa:16:3e:c5:8b:b9_Permit_ | 40 | 36001 | in-port: "openflow:267140174830659:6", ipv4-source: "10.11.12.7/32", ethernet-match: {"ethernet-source": {"address": "FA:16:3E:C5:8B:B9"}, "ethernet-type": {"type": 2048}} | go-to-table: {"table_id": 50} | |
22 | | Egress_Allow_VM_IP_MAC_7fa:16:3e:db:c3:fd_Permit_ | 40 | 36001 | in-port: "openflow:267140174830659:7", ipv4-source: "10.11.12.8/32", ethernet-match: {"ethernet-source": {"address": "FA:16:3E:DB:C3:FD"}, "ethernet-type": {"type": 2048}} | go-to-table: {"table_id": 50} | |
23 | | DEFAULT_PIPELINE_FLOW_40 | 40 | 0 | | go-to-table: {"table_id": 50} | |
24 | | DEFAULT_PIPELINE_FLOW_50 | 50 | 0 | | go-to-table: {"table_id": 60} | |
25 | | DEFAULT_PIPELINE_FLOW_60 | 60 | 0 | | go-to-table: {"table_id": 70} | |
26 | | DEFAULT_PIPELINE_FLOW_70 | 70 | 0 | | go-to-table: {"table_id": 80} | |
27 | | DEFAULT_PIPELINE_FLOW_80 | 80 | 0 | | go-to-table: {"table_id": 90} | |
28 | | #UF$TABLE*90-10 | 90 | 61010 | arp-target-hardware-address: {"address": "FA:16:3E:C5:8B:B9"}, ethernet-match: {"ethernet-type": {"type": 2054}} | go-to-table: {"table_id": 100} | |
29 | | #UF$TABLE*90-12 | 90 | 61010 | arp-target-hardware-address: {"address": "FA:16:3E:DB:C3:FD"}, ethernet-match: {"ethernet-type": {"type": 2054}} | go-to-table: {"table_id": 100} | |
30 | | Ingress_IP1056_fa:16:3e:c5:8b:b9_Permit_ | 90 | 61007 | ethernet-match: {"ethernet-type": {"type": 2048}, "ethernet-destination": {"address": "FA:16:3E:C5:8B:B9"}} | go-to-table: {"table_id": 100} | |
31 | | Ingress_IP1056_fa:16:3e:db:c3:fd_Permit_ | 90 | 61007 | ethernet-match: {"ethernet-type": {"type": 2048}, "ethernet-destination": {"address": "FA:16:3E:DB:C3:FD"}} | go-to-table: {"table_id": 100} | |
32 | | Ingress_DHCP_Server1056_fa:16:3e:57:9e:07_Permit_ | 90 | 61006 | udp-destination-port: 68, ip-match: {"ip-protocol": 17}, udp-source-port: 67, ethernet-match: {"ethernet-source": {"address": "FA:16:3E:57:9E:07"}, "ethernet-type": {"type": 2048}} | go-to-table: {"table_id": 100} | |
33 | | DEFAULT_PIPELINE_FLOW_90 | 90 | 0 | | go-to-table: {"table_id": 100} | |
34 | | DEFAULT_PIPELINE_FLOW_100 | 100 | 0 | | go-to-table: {"table_id": 110} | |
35 | | UcastOut_1056_7_fa:16:3e:db:c3:fd | 110 | 32768 | tunnel: {"tunnel-id": 1056}, ethernet-match: {"ethernet-destination": {"address": "FA:16:3E:DB:C3:FD"}} | output-action: {"max-length": 0, "output-node-connector": "7"} | |
36 | | UcastOut_1056_6_fa:16:3e:c5:8b:b9 | 110 | 32768 | tunnel: {"tunnel-id": 1056}, ethernet-match: {"ethernet-destination": {"address": "FA:16:3E:C5:8B:B9"}} | output-action: {"max-length": 0, "output-node-connector": "6"} | |
37 | | TunnelOut_1056_1_fa:16:3e:57:9e:07 | 110 | 32768 | tunnel: {"tunnel-id": 1056}, ethernet-match: {"ethernet-destination": {"address": "FA:16:3E:57:9E:07"}} | output-action: {"max-length": 0, "output-node-connector": "1"} | |
38 | | TunnelOut_1056_1_fa:16:3e:da:ac:59 | 110 | 32768 | tunnel: {"tunnel-id": 1056}, ethernet-match: {"ethernet-destination": {"address": "FA:16:3E:DA:AC:59"}} | output-action: {"max-length": 0, "output-node-connector": "1"} | |
39 | | BcastOut_1056 | 110 | 16384 | tunnel: {"tunnel-id": 1056}, ethernet-match: {"ethernet-destination": {"mask": "01:00:00:00:00:00", "address": "01:00:00:00:00:00"}}, openflowplugin-extension-general:extension-list: [{"extension-key": "openflowplugin-extension-nicira-match:nxm-nx-reg0-key", "extension": {"openflowplugin-extension-nicira-match:nxm-nx-reg": {"reg": "nicira-match:nxm-nx-reg0", "value": 2}}}] | output-action: {"max-length": 0, "output-node-connector": "6"}, output-action: {"max-length": 0, "output-node-connector": "7"} | |
40 | | TunnelFloodOut_1056 | 110 | 16383 | tunnel: {"tunnel-id": 1056}, ethernet-match: {"ethernet-destination": {"mask": "01:00:00:00:00:00", "address": "01:00:00:00:00:00"}}, openflowplugin-extension-general:extension-list: [{"extension-key": "openflowplugin-extension-nicira-match:nxm-nx-reg0-key", "extension": {"openflowplugin-extension-nicira-match:nxm-nx-reg": {"reg": "nicira-match:nxm-nx-reg0", "value": 1}}}] | output-action: {"max-length": 0, "output-node-connector": "6"}, output-action: {"max-length": 0, "output-node-connector": "1"}, output-action: {"max-length": 0, "output-node-connector": "7"} | |
41 | | LocalTableMiss_1056 | 110 | 8192 | tunnel: {"tunnel-id": 1056} | Drop | |
42 | | DEFAULT_PIPELINE_FLOW_110 | 110 | 0 | | Drop | |
43 | +---------------------------------------------------+----------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |
フローの変更
今回は2台のインスタンス(vm01、vm-mirror)を使って、パケットのミラーリングをRESTCONF APIから行ってみます。インスタンスvm01宛のパケットをインスタンスvm-mirrorにミラーリングするためフローの設定をします。
まず、外部ネットワークとテナントネットワークを作成します。
01 | ~/devstack$ source openrc admin admin |
02 | ~/devstack$ neutron net-create ext-net --router:external |
03 | ~/devstack$ neutron subnet-create ext-net 172.16.1.0/24 |
04 | ~/devstack$ sudo ip addr add 172.16.1.1/24 dev br-ex |
05 | ~/devstack$ source openrc demo demo |
06 | ~/devstack$ neutron net-create net01 |
07 | ~/devstack$ neutron subnet-create net01 10.11.12.0/24 --name net01-subnet |
08 | ~/devstack$ neutron router-create router1 |
09 | ~/devstack$ neutron router-interface-add router1 net01-subnet |
10 | ~/devstack$ neutron router-gateway-set router1 ext-net |
ネットワーク上のパケットをキャプチャーするツールとしてtcpdumpをよく利用すると思います。今回もtcpdumpを利用しますが、現在Glanceイメージとして登録されているcirrosは非常にミニマムなクラウドOSであるためtcpdumpコマンドがインストールされていません。そこで、Ubuntuのイメージを新規に登録することにします。
1 | ~/devstack$ wget https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img # Ubuntuのイメージをダウンロード |
2 | ~/devstack$ source openrc admin admin |
3 | ~/devstack$ glance image-create --name ubuntu --disk-format=qcow2 --container-format=bare \ |
4 | --visibility public --file ./trusty-server-cloudimg-amd64-disk1.img # Ubuntuイメージの登録 |
Ubuntuのインスタンスを起動し、Floating IPを割り当てます。
01 | ~/devstack$ source openrc demo demo |
02 | ~/devstack$ nova keypair-add mykey > mykey # インスタンスへのSSH用のキーペアの作成と公開鍵の登録 |
03 | ~/devstack$ nova boot --image ubuntu --flavor m1.small --key mykey vm01 # vm01を作成 |
04 | ~/devstack$ nova boot --image ubuntu --flavor m1.small --key mykey vm-mirror # vm-mirrorを作成 |
05 | ~/devstack$ neutron floatingip-create ext-net # フローティングIPの作成 |
06 | Created a new floatingip: |
07 | +---------------------+--------------------------------------+ |
08 | | Field | Value | |
09 | +---------------------+--------------------------------------+ |
10 | | fixed_ip_address | | |
11 | | floating_ip_address | 172.16.1.4 | |
12 | | floating_network_id | ad490f39-82b9-4164-8526-d47ae379dd49 | |
13 | | id | 101351bd-3044-4da2-bf36-72a193adc976 | |
14 | | port_id | | |
15 | | router_id | | |
16 | | status | DOWN | |
17 | | tenant_id | 48e3c8d0688c4ccfac7126060ec550c0 | |
18 | +---------------------+--------------------------------------+ |
19 | ~/devstack$ neutron floatingip-create ext-net # フローティングIPの作成 |
20 | Created a new floatingip: |
21 | +---------------------+--------------------------------------+ |
22 | | Field | Value | |
23 | +---------------------+--------------------------------------+ |
24 | | fixed_ip_address | | |
25 | | floating_ip_address | 172.16.1.5 | |
26 | | floating_network_id | ad490f39-82b9-4164-8526-d47ae379dd49 | |
27 | | id | f75ba7ed-3796-4f97-a0b9-e39d77baafca | |
28 | | port_id | | |
29 | | router_id | | |
30 | | status | DOWN | |
31 | | tenant_id | 48e3c8d0688c4ccfac7126060ec550c0 | |
32 | +---------------------+--------------------------------------+ |
33 | ~/devstack$ neutron port-list # インスタンスのポートを確認 |
34 | +--------------------------------------+------+-------------------+-----------------------------------------------------------------------------------+ |
35 | | id | name | mac_address | fixed_ips | |
36 | +--------------------------------------+------+-------------------+-----------------------------------------------------------------------------------+ |
37 | | 18173079-b4b1-44f8-85cc-a8bdd2a9ebe4 | | fa:16:3e:db:c3:fd | {"subnet_id": "565fdfc0-d215-46c1-88da-fdd938c3aebd", "ip_address": "10.11.12.8"} | |
38 | | 470bbdfe-4be4-49c0-8a0b-71a75f664e9c | | fa:16:3e:57:9e:07 | {"subnet_id": "565fdfc0-d215-46c1-88da-fdd938c3aebd", "ip_address": "10.11.12.2"} | |
39 | | c22dc6bc-d575-4100-a825-c64ef3a2fac4 | | fa:16:3e:da:ac:59 | {"subnet_id": "565fdfc0-d215-46c1-88da-fdd938c3aebd", "ip_address": "10.11.12.1"} | |
40 | | d151ef5d-5954-4c35-ac88-b047f6bda2b1 | | fa:16:3e:c5:8b:b9 | {"subnet_id": "565fdfc0-d215-46c1-88da-fdd938c3aebd", "ip_address": "10.11.12.7"} | |
41 | +--------------------------------------+------+-------------------+-----------------------------------------------------------------------------------+ |
42 | ~/devstack$ neutron floatingip-associate 101351bd-3044-4da2-bf36-72a193adc976 d151ef5d-5954-4c35-ac88-b047f6bda2b1 # vm01へフローティングIPを割り当てる |
43 | ~/devstack$ neutron floatingip-associate f75ba7ed-3796-4f97-a0b9-e39d77baafca 18173079-b4b1-44f8-85cc-a8bdd2a9ebe4 # vm-mirrorへフローティングIPを割り当てる |
コンピュートノードのCLIを2つ開き、Floating IPでvm01とvm-mirrorにSSHログインします。各インスタンスでeth0へのICMPパケットをtcpdumpで監視します。
[vm01]
01 | ~/devstack$ ssh 172.16.1.4 -i mykey |
02 | Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-85-generic x86_64) |
03 |
04 | * Documentation: https://help.ubuntu.com/ |
05 |
06 | System information disabled due to load higher than 1.0 |
07 |
08 | Get cloud support with Ubuntu Advantage Cloud Guest: |
10 |
11 | 0 packages can be updated. |
12 | 0 updates are security updates. |
13 |
14 |
15 |
16 | The programs included with the Ubuntu system are free software; |
17 | the exact distribution terms for each program are described in the |
18 | individual files in /usr/share/doc/*/copyright. |
19 |
20 | Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by |
21 | applicable law. |
22 |
23 | ubuntu@vm01:~$ sudo tcpdump -i eth0 icmp |
24 | tcpdump: verbose output suppressed, use -v or -vv for full protocol decode |
25 | listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes |
[vm-mirror]
01 | ~/devstack$ ssh 172.16.1.5 -i mykey |
02 | Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-85-generic x86_64) |
03 |
04 | * Documentation: https://help.ubuntu.com/ |
05 |
06 | System information disabled due to load higher than 1.0 |
07 |
08 | Get cloud support with Ubuntu Advantage Cloud Guest: |
10 |
11 | 0 packages can be updated. |
12 | 0 updates are security updates. |
13 |
14 |
15 |
16 | The programs included with the Ubuntu system are free software; |
17 | the exact distribution terms for each program are described in the |
18 | individual files in /usr/share/doc/*/copyright. |
19 |
20 | Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by |
21 | applicable law. |
22 |
23 | ubuntu@vm-mirror:~$ sudo tcpdump -i eth0 icmp |
24 | tcpdump: verbose output suppressed, use -v or -vv for full protocol decode |
25 | listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes |
コントローラノードからvm01のFloating IPに対してpingを実行します。
1 | ~/devstack$ ping 172.16.1.4 |
2 | PING 172.16.1.4 (172.16.1.4) 56(84) bytes of data. |
3 | 64 bytes from 172.16.1.4: icmp_seq=1 ttl=63 time=4.01 ms |
4 | 64 bytes from 172.16.1.4: icmp_seq=2 ttl=63 time=5.66 ms |
5 | 64 bytes from 172.16.1.4: icmp_seq=3 ttl=63 time=1.04 ms |
6 | 64 bytes from 172.16.1.4: icmp_seq=4 ttl=63 time=1.00 ms |
7 | : |
vm01のtcpdumpでicmpリクエストが届いている事がわかると思います。
01 | ubuntu@vm01:~$ sudo tcpdump -i eth0 icmp |
02 | tcpdump: verbose output suppressed, use -v or -vv for full protocol decode |
03 | listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes |
04 | 08:58:25.002574 IP 172.16.1.1 > host-10-11-12-3.openstacklocal: ICMP echo request, id 9565, seq 1, length 64 |
05 | 08:58:25.004569 IP host-10-11-12-3.openstacklocal > 172.16.1.1: ICMP echo reply, id 9565, seq 1, length 64 |
06 | 08:58:26.018485 IP 172.16.1.1 > host-10-11-12-3.openstacklocal: ICMP echo request, id 9565, seq 2, length 64 |
07 | 08:58:26.018673 IP host-10-11-12-3.openstacklocal > 172.16.1.1: ICMP echo reply, id 9565, seq 2, length 64 |
08 | 08:58:27.017110 IP 172.16.1.1 > host-10-11-12-3.openstacklocal: ICMP echo request, id 9565, seq 3, length 64 |
09 | 08:58:27.017286 IP host-10-11-12-3.openstacklocal > 172.16.1.1: ICMP echo reply, id 9565, seq 3, length 64 |
10 | 08:58:28.018369 IP 172.16.1.1 > host-10-11-12-3.openstacklocal: ICMP echo request, id 9565, seq 4, length 64 |
11 | 08:58:28.018548 IP host-10-11-12-3.openstacklocal > 172.16.1.1: ICMP echo reply, id 9565, seq 4, length 64 |
12 | : |
それでは、vm01宛のパケットをvm-mirrorへミラーリングためのフローを設定します。
1 | ~/devstack$ odl flow create openflow:267140174830659 110 flow_mirror --tun-id 0x420 --dl-dst fa:16:3e:c5:8b:b9 --instructions output:2,output:3 |
2 | True |
curlでリクエストを投げると以下の様になります。
1 | ~/devstack$ curl -i -H "Content-Type: application/xml" -H "Accept: application/json" -u "admin:admin" -X PUT "http://192.168.0.11:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:267140174830659/flow-node-inventory:table/110/flow/flow_mirror" -d '<?xml version="1.0" encoding="utf-8"?><flow xmlns="urn:opendaylight:flow:inventory"><table_id>110</table_id><id>flow_mirror</id><match><tunnel><tunnel-id>0x420</tunnel-id></tunnel><ethernet-match><ethernet-destination><mask>ff:ff:ff:ff:ff:ff</mask><address>fa:16:3e:c5:8b:b9</address></ethernet-destination></ethernet-match></match><instructions><instruction><order>0</order><apply-actions><action><output-action><output-node-connector>2</output-node-connector></output-action><order>0</order></action><action><output-action><output-node-connector>3</output-node-connector></output-action><order>1</order></action></apply-actions></instruction></instructions></flow>' |
vm-mirrorのtcpdumpを見てみるとミラーリングされたパケットが届くようになったことが確認できます。
[vm-mirror]
1 | ubuntu@vm-mirror:~$ sudo tcpdump -i eth0 icmp |
2 | tcpdump: verbose output suppressed, use -v or -vv for full protocol decode |
3 | listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes |
4 | 09:07:04.530341 IP 172.16.1.1 > 10.11.12.3: ICMP echo request, id 9788, seq 1, length 64 |
5 | 09:07:05.533755 IP 172.16.1.1 > 10.11.12.3: ICMP echo request, id 9788, seq 2, length 64 |
6 | 09:07:06.531791 IP 172.16.1.1 > 10.11.12.3: ICMP echo request, id 9788, seq 3, length 64 |
7 | : |
RESTCONF APIを使ってミラーリングのフローを設定する例を紹介しました。OpenDaylightがMD-SALという抽象化レイヤーを採用していることによって、OpenDaylightを利用する様々なアプリケーションからのリクエストをNBIから受け取れる仕組みになっています。今回はRESTCONF APIをご紹介しましたが、この他にも様々なNBIが用意されているので、ぜひ使ってみてください。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- OpenStack with OpenDaylight(DevStack編)
- OpenStack with OpenDaylight (手動構築編)
- MidoNetのパケット処理をDVRと比較してみる
- OpenDaylightでクラスタを組んでみよう
- OpenStack Kilo(RDO版)でのMidoNet構築手順(1)
- IPアドレスを管理する「DHCPサーバ」と通信の橋渡し「NATルータ」
- IPアドレスを管理する「DHCPサーバ」と通信の橋渡し「NATルータ」
- CentOS 7のネットワーク管理基礎(前編)
- Neutron DVR環境でのパケット処理を探る
- OpenStack TackerによるNFVオーケストレーション