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 で状態が即時更新されていることが確認できます。