APRESIA Technical Blog

Stratum on BMv2をGNS3上で動かしてみた(第二弾)

はじめに

前回に続き、Stratum on BMv2 を触っていきます。 前回は、P4 で定義したテーブルを P4Runtime 経由で操作しました。今回は、gNMI 経由でデバイスの状態取得や設定変更等を実施します。
前回同様、ONF Connect ’19 にて開催されていたチュートリアル(EXERCISE 2)をベースに進めていきます。

構成

前回と同様に、Stratum スイッチ 1 台、クライアント 2 台を接続して、お互い通信可能なように P4Runtime 経由でテーブルを登録した状態にします。

gNMI に関して

gNMI (gRPC Network Management Interface)は、名前の通り gRPC をベースにした、ネットワークを管理/操作するためのプロトコルです。ネットワーク装置の状態取得や、設定変更等が可能です。
Stratum では、OpenConfig で定義されたモデルの一部を利用しており、チュートリアル用に用意された Docker コンテナ(bocon/yang-tools:latest)内部で以下のコマンドにより Tree 形式で表示させることが出来ます。
bash-4.4# pyang -f tree \ -p ietf \ -p openconfig \ -p hercules \ openconfig/interfaces/openconfig-interfaces.yang \ openconfig/interfaces/openconfig-if-ethernet.yang \ openconfig/platform/* \ openconfig/qos/* \ openconfig/system/openconfig-system.yang \ hercules/openconfig-hercules-*.yang | less

gNMI 送信

チュートリアルで用意されている gNMI client を使って装置に接続してみます。
以下のコマンドで Get リクエストを送信できます。Path は/を指定しているため config tree の root を取得する命令となります。
util/gnmi-cli --grpc-addr 192.168.122.51:50001 get /
成功すると、以下のような結果が返ってきます。
*************************** REQUEST path { } type: CONFIG encoding: PROTO *************************** *************************** RESPONSE notification { update { path { } val { any_val { type_url: "type.googleapis.com/openconfig.Device" value: "\252\221\231\304\001&\n\022... // 省略
1 番目のパートは送信したリクエストに関する情報であり、2 番目のパートはレスポンスの情報となっています。 gNMI の生の情報は、Protobuf でバイナリエンコーディングされているため、デコーダーも準備されています。
以下のようにパイプでリクエストとつなげることでデコードされた情報を確認できます。
util/gnmi-cli --grpc-addr 192.168.122.51:50001 get / | util/oc-pb-decoder | less
成功すると、以下のような結果が返ってきます。
今度は人間が読める形式で Device の情報(インタフェースの情報)が取得出来ていることが分かります。
*************************** REQUEST path { } type: CONFIG encoding: PROTO *************************** *************************** RESPONSE notification { update { path { } val { any_val { type_url: "type.googleapis.com/openconfig.Device" value: component { name: "bmv2-simple_switch" component { chassis { platform: OPENCONFIGHERCULESPLATFORMPLATFORMTYPE_GENERIC } } } component { name: ":lc-1" component { linecard { slot_id { value: "1" } } id { value: "1" } } } component { name: "eth1" component { linecard { slot_id { value: "1" } } transceiver { channel { index: 1 } } integrated_circuit { node_id { value: 1 } } subcomponent { name: "eth1" } port { port_id { value: 1 } } } } // 省略

Interface の情報取得

パケットカウンタの情報を取得するために、以下の gNMI リクエストを送信します。
util/gnmi-cli --grpc-addr 192.168.122.51:50001 \ --interval 1000 sub-sample \ /interfaces/interface[name=eth3]/state/counters/in-unicast-pkts
/interfaces/interface[name=eth3]/state/counters/in-unicast-pktsは、受信ユニキャストのパケット数を示すリソースへの Path を指定しています。
Path は、先述した YANG ツリーを辿っていくと確認できます。
sub-sampleは gNMI の STREAM Subscriptions における SAMPLE モードの要求であり、interval 時間毎(今回は 1 秒)にレスポンスを返すモードとなっています。
成功すると、以下のような結果が返ってきて、1 秒毎に結果が更新されていることが確認できます。
*************************** REQUEST subscribe { subscription { path { elem { name: "interfaces" } elem { name: "interface" key { key: "name" value: "eth3" } } elem { name: "state" } elem { name: "counters" } elem { name: "in-unicast-pkts" } } mode: SAMPLE sample_interval: 1000 } updates_only: true } *************************** *************************** RESPONSE update { timestamp: 1571898597675982684 update { path { elem { name: "interfaces" } elem { name: "interface" key { key: "name" value: "eth3" } } elem { name: "state" } elem { name: "counters" } elem { name: "in-unicast-pkts" } } val { uint_val: 44 } } } ***************************

Interface の状態制御

次は、Interface の状態を制御して、gNMI でどのように確認できるかを見ていきます。
以下のコマンドを発行することで、Interface の運用状態(oper-status)が確認できます。sub-onchangeを用いて、ON_CHANGE モードの Subscription リクエストを発行しています。
util/gnmi-cli --grpc-addr 192.168.122.51:50001 sub-onchange /interfaces/interface[name=eth3]/state/oper-status
成功すると、以下のような結果が返ってきて、変更待ち受け状態となります。
現在は、インタフェースはアップ状態のため、string_val: "UP"と表示されていることを確認してください。
*************************** REQUEST subscribe { subscription { path { elem { name: "interfaces" } elem { name: "interface" key { key: "name" value: "eth3" } } elem { name: "state" } elem { name: "oper-status" } } mode: ON_CHANGE } updates_only: true } *************************** *************************** RESPONSE update { timestamp: 1571901432581865924 update { path { elem { name: "interfaces" } elem { name: "interface" key { key: "name" value: "eth3" } } elem { name: "state" } elem { name: "oper-status" } } val { string_val: "UP" } } } *************************** *************************** RESPONSE sync_response: true ***************************
スイッチにコンソール接続し、以下のコマンドを発行して、インタフェースをダウンさせてみます。
ifconfig eth3 down
変更するとすぐに、string_val: "DOWN"となることが確認できます。ON_CHANGE のモードで Subscription 発行しているため、変更検知で即時通知されます。
また、以下のコマンドでアップ状態に戻すと、状態が即時更新されます。
ifconfig eth3 up
続いて、インタフェースのアップ/ダウンも gNMI 経由で制御してみます。
別ターミナルを開いて、以下のように Set リクエストを発行してみます。
util/gnmi-cli --grpc-addr 192.168.122.51:50001 set \ /interfaces/interface[name=eth3]/config/enabled \ --bool-val false
コンソールからインタフェースダウンさせた場合と同様に、gNMI で状態が即時更新されていることが確認できます。

最後に

今回は、Stratum の gNMI を用いて、装置情報の取得や装置制御を実施しました。P4Runtime や gNMI はすべて gRPC での通信であり、コントローラーからの制御を前提としています。そのため、Stratum を制御するための SDN コントローラーが重要になってきます。次回以降は、ONF が開発している SDN コントローラー(ONOS)を用いて Stratum の制御を実際に動かしていきたいと思います。

参考