はじめに
SONiCのtelemetryですが、dial-in (server) と dial-out (client) があります。ここではdial-inについて解説します。簡単に言えば、外からSONiCに対して情報取得を要求し、SONiCが応答するという動作になります。動かしながら説明していきたいと思います。
なお、環境はSONiC-VS on GNS3です。
準備
何も設定していなくても標準でtelemetry serviceが動作しています。何も設定してなければどこからでも情報取得ができます。がばがばです。証明書を用意してクライアント認証を有効にすることでセキュアにできますが、今回は情報取得の解説がメインなので省略します。
よってSONiC側は設定不要ですが、情報取得のためのクライアントプログラムが必要です。
クライアントプログラム gnmi_get
のインストール
SONiCのtelemetry機能はgRPCによって情報取得するものですが、公式ドキュメントでも言及されている下記のプログラムを使って情報取得します。(検索するとGoogle謹製のgnmi_getが見つかりますが、コマンドラインパラメータが異なるようで使えません、ご注意ください)
$ go get github.com/jipanyang/gnxi/gnmi_get
gnmi_get
の動作確認
以降のサンプル出力において、192.168.1.34
はターゲットのSONiCのマネジメントポートにつけられたIPアドレスです。8080
は無指定時のポート番号になります。
$ gnmi_get -xpath_target COUNTERS_DB -xpath COUNTERS_PORT_NAME_MAP -target_addr 192.168.1.34:8080 -insecure true
== getRequest:
prefix: <
target: "COUNTERS_DB"
>
path: <
elem: <
name: "COUNTERS_PORT_NAME_MAP"
>
>
encoding: JSON_IETF
== getResponse:
notification: <
timestamp: 1610990669317028240
prefix: <
target: "COUNTERS_DB"
>
update: <
path: <
elem: <
name: "COUNTERS_PORT_NAME_MAP"
>
>
val: <
json_ietf_val: "{\"Ethernet0\":\"oid:0x1000000000002\",\"Ethernet100\":\"oid:0x100000000001b\",\"Ethernet104\":\"oid:0x100000000001c\",\"Ethernet108\":\"oid:0x100000000001d\",\"Ethernet112\":\"oid:0x100000000001e\",\"Ethernet116\":\"oid:0x100000000001f\",\"Ethernet12\":\"oid:0x1000000000005\",\"Ethernet120\":\"oid:0x1000000000020\",\"Ethernet124\":\"oid:0x1000000000021\",\"Ethernet16\":\"oid:0x1000000000006\",\"Ethernet20\":\"oid:0x1000000000007\",\"Ethernet24\":\"oid:0x1000000000008\",\"Ethernet28\":\"oid:0x1000000000009\",\"Ethernet32\":\"oid:0x100000000000a\",\"Ethernet36\":\"oid:0x100000000000b\",\"Ethernet4\":\"oid:0x1000000000003\",\"Ethernet40\":\"oid:0x100000000000c\",\"Ethernet44\":\"oid:0x100000000000d\",\"Ethernet48\":\"oid:0x100000000000e\",\"Ethernet52\":\"oid:0x100000000000f\",\"Ethernet56\":\"oid:0x1000000000010\",\"Ethernet60\":\"oid:0x1000000000011\",\"Ethernet64\":\"oid:0x1000000000012\",\"Ethernet68\":\"oid:0x1000000000013\",\"Ethernet72\":\"oid:0x1000000000014\",\"Ethernet76\":\"oid:0x1000000000015\",\"Ethernet8\":\"oid:0x1000000000004\",\"Ethernet80\":\"oid:0x1000000000016\",\"Ethernet84\":\"oid:0x1000000000017\",\"Ethernet88\":\"oid:0x1000000000018\",\"Ethernet92\":\"oid:0x1000000000019\",\"Ethernet96\":\"oid:0x100000000001a\"}"
>
>
>
$
取得できる情報
gnmi_get
の-xpath_target
と-xpath
を使って取得する情報を指定します。
-xpath_target
に何が指定できるのか
動作確認の例を見ていただければわかると思いますが、SONiCが抱えているRedisデータベース名です。src/sonic-swss-common/common/schema.h
から引っ張り出してます。
APPL_DB
ASIC_DB
COUNTERS_DB
LOGLEVEL_DB
CONFIG_DB
PFC_WD_DB
FLEX_COUNTER_DB
STATE_DB
DB定義には下記もありますが、テーブル内容が不明のため以降では言及しません。
SNMP_OVERLAY_DB
RESTAPI_DB
GB_ASIC_DB
GB_COUNTERS_DB
GB_FLEX_COUNTER_DB
CHASSIS_APP_DB
CHASSIS_STATE_DB
-xpath
なにが指定できるのか
DBのテーブル名以降を指定できます。テーブル名は下記です。めちゃくちゃ多いので折りたたんであります。テーブル名のみを指定するとテーブル全体を、個別の項目を指定すればそこだけ取得できます。
APPL_DB
PORT_TABLE
GEARBOX_TABLE
VLAN_TABLE
VLAN_MEMBER_TABLE
LAG_TABLE
LAG_MEMBER_TABLE
INTF_TABLE
NEIGH_TABLE
ROUTE_TABLE
TUNNEL_DECAP_TABLE
FDB_TABLE
PFC_WD_TABLE
SWITCH_TABLE
COPP_TABLE
VRF_TABLE
VNET_TABLE
VNET_ROUTE_TABLE
VNET_ROUTE_TUNNEL_TABLE
VXLAN_VRF_TABLE
VXLAN_TUNNEL_MAP_TABLE
VXLAN_TUNNEL_TABLE
VXLAN_FDB_TABLE
VXLAN_REMOTE_VNI_TABLE
VXLAN_EVPN_NVO_TABLE
SUPPRESS_VLAN_NEIGH_TABLE
PASS_THROUGH_ROUTE_TABLE
ACL_TABLE_TABLE
ACL_RULE_TABLE
SFLOW_TABLE
SFLOW_SESSION_TABLE
SFLOW_SAMPLE_RATE_TABLE
NAT_TABLE
NAPT_TABLE
NAT_TWICE_TABLE
NAPT_TWICE_TABLE
NAT_GLOBAL_TABLE
NAPT_POOL_IP_TABLE
NAT_DNAT_POOL_TABLE
STP_VLAN_TABLE
STP_VLAN_PORT_TABLE
STP_VLAN_INSTANCE_TABLE
STP_PORT_TABLE
STP_PORT_STATE_TABLE
STP_FASTAGEING_FLUSH_TABLE
STP_BPDU_GUARD_TABLE
MCLAG_FDB_TABLE
ISOLATION_GROUP_TABLE
ASIC_DB
- ASIC_TEMPERATURE_INFO
COUNTER_DB
COUNTERS_PORT_NAME_MAP
COUNTERS_LAG_NAME_MAP
COUNTERS
COUNTERS_QUEUE_NAME_MAP
COUNTERS_QUEUE_PORT_MAP
COUNTERS_QUEUE_INDEX_MAP
COUNTERS_QUEUE_TYPE_MAP
COUNTERS_PG_NAME_MAP
COUNTERS_PG_PORT_MAP
COUNTERS_PG_INDEX_MAP
COUNTERS_RIF_TYPE_MAP
COUNTERS_RIF_NAME_MAP
CRM
COUNTERS_BUFFER_POOL_NAME_MAP
COUNTERS_SWITCH_NAME_MAP
COUNTERS_MACSEC_NAME_MAP
COUNTERS_DEBUG_NAME_PORT_STAT_MAP
COUNTERS_DEBUG_NAME_SWITCH_STAT_MAP
COUNTERS_NAT
COUNTERS_NAPT
COUNTERS_TWICE_NAT
COUNTERS_TWICE_NAPT
COUNTERS_GLOBAL_NAT
PERIODIC_WATERMARKS
PERSISTENT_WATERMARKS
USER_WATERMARKS
RATES
LOGLEVEL_DB
スキーマには記述がありましたが、SONiC-VSでは情報取得できませんでした。
DAEMON_TABLE
LOGLEVEL
LOGOUTPUT
FLEX_COUNTER_DB
FLEX_COUNTER_TABLE
PORT_COUNTER_ID_LIST
PORT_DEBUG_COUNTER_ID_LIST
QUEUE_COUNTER_ID_LIST
QUEUE_ATTR_ID_LIST
BUFFER_POOL_COUNTER_ID_LIST
PFC_WD_STATE_TABLE
PORT_COUNTER_ID_LIST
QUEUE_COUNTER_ID_LIST
QUEUE_ATTR_ID_LIST
PG_COUNTER_ID_LIST
PG_ATTR_ID_LIST
RIF_COUNTER_ID_LIST
SWITCH_DEBUG_COUNTER_ID_LIST
MACSEC_SA_ATTR_ID_LIST
PLUGIN_TABLE
LUA_PLUGIN_TYPE
SAI_OBJECT_TYPE
POLL_INTERVAL
STATS_MODE
STATS_MODE_READ
STATS_MODE_READ_AND_CLEAR
QUEUE_PLUGIN_LIST
PORT_PLUGIN_LIST
RIF_PLUGIN_LIST
PG_PLUGIN_LIST
BUFFER_POOL_PLUGIN_LIST
FLEX_COUNTER_STATUS
FLEX_COUNTER_GROUP_TABLE
CONFIG_DB
PORT
CABLE_LENGTH
GEARBOX
INTERFACE
LOOPBACK_INTERFACE
MGMT_INTERFACE
PORTCHANNEL_INTERFACE
VLAN_INTERFACE
VLAN_SUB_INTERFACE
ASIC_SENSORS
PORTCHANNEL
PORTCHANNEL_MEMBER
VLAN
VLAN_MEMBER
FDB
SWITCH
VRF
CRM
DHCP_SERVER
NTP_SERVER
SYSLOG_SERVER
BGP_NEIGHBOR
BGP_INTERNAL_NEIGHBOR
BGP_MONITORS
BGP_PEER_RANGE
DEVICE_METADATA
DEVICE_NEIGHBOR
DEVICE_NEIGHBOR_METADATA
MIRROR_SESSION
ACL_TABLE
ACL_RULE
PFC_WD
FLEX_COUNTER_TABLE
WATERMARK_TABLE
PFC_PRIORITY_TO_PRIORITY_GROUP_MAP
TC_TO_PRIORITY_GROUP_MAP
MAP_PFC_PRIORITY_TO_QUEUE
TC_TO_QUEUE_MAP
DSCP_TO_TC_MAP
SCHEDULER
PORT_QOS_MAP
WRED_PROFILE
QUEUE
DOT1P_TO_TC_MAP
BUFFER_POOL
BUFFER_PROFILE
BUFFER_QUEUE
BUFFER_PG
BUFFER_PORT_INGRESS_PROFILE_LIST
BUFFER_PORT_EGRESS_PROFILE_LIST
DEFAULT_LOSSLESS_BUFFER_PARAMETER
POLICER
WARM_RESTART
VXLAN_TUNNEL
VXLAN_TUNNEL_MAP
VXLAN_EVPN_NVO
VNET
NEIGH
SUPPRESS_VLAN_NEIGH
VNET_ROUTE
VNET_ROUTE_TUNNEL
PASS_THROUGH_ROUTE_TABLE
SFLOW
SFLOW_SESSION
DEBUG_COUNTER
DEBUG_COUNTER_DROP_REASON
STATIC_NAT
STATIC_NAPT
NAT_POOL
NAT_BINDINGS
NAT_GLOBAL
STP
STP_VLAN
STP_VLAN_PORT
STP_PORT
MCLAG_DOMAIN
MCLAG_INTERFACE
MCLAG_UNIQUE_IP
PORT_STORM_CONTROL
RATES
FEATURE
COPP_TRAP
COPP_GROUP
FG_NHG
FG_NHG_PREFIX
FG_NHG_MEMBER
MUX_CABLE
PEER_SWITCH
TUNNEL
SYSTEM_PORT
VOQ_INBAND_INTERFACE
MACSEC_PROFILE
SYSTEM_INTERFACE
SYSTEM_NEIGH
CHASSIS_MODULE
STATE_DB
SWITCH_CAPABILITY_TABLE
PORT_TABLE
LAG_TABLE
VLAN_TABLE
VLAN_MEMBER_TABLE
INTERFACE_TABLE
FDB_TABLE
WARM_RESTART_TABLE
WARM_RESTART_ENABLE_TABLE
VRF_TABLE
VRF_OBJECT_TABLE
MGMT_PORT_TABLE
NEIGH_RESTORE_TABLE
MIRROR_SESSION_TABLE
VXLAN_TABLE
VXLAN_TUNNEL_TABLE
SUPPRESS_VLAN_NEIGH_TABLE
BGP_STATE_TABLE
DEBUG_COUNTER_CAPABILITIES
NAT_RESTORE_TABLE
MCLAG_TABLE
MCLAG_LOCAL_INTF_TABLE
MCLAG_REMOTE_INTF_TABLE
MCLAG_REMOTE_FDB_TABLE
STP_TABLE
COPP_GROUP_TABLE
COPP_TRAP_TABLE
FG_ROUTE_TABLE
MUX_CABLE_TABLE
HW_MUX_CABLE_TABLE
SYSTEM_NEIGH_TABLE
MACSEC_PORT_TABLE
MACSEC_INGRESS_SC_TABLE
MACSEC_INGRESS_SA_TABLE
MACSEC_EGRESS_SC_TABLE
MACSEC_EGRESS_SA_TABLE
ASIC_TABLE
BUFFER_MAX_PARAM_TABLE
PERIPHERAL_TABLE
PORT_PERIPHERAL_TABLE
BUFFER_POOL_TABLE
BUFFER_PROFILE_TABLE
取得例
CONFIG_DBからPORT
テーブルのEthernet0
の内容を取得してみます。
さすがにgnmi_get
の出力のままでは見づらいので、スクリプトで必要な部分を取り出して整形することにします。
実行すると、下記のようになります。
$ ./telemetry_get.sh 192.168.1.34:8080 CONFIG_DB PORT/Ethernet0
{
"admin_status": "up",
"alias": "fortyGigE0/0",
"index": "0",
"lanes": "25,26,27,28",
"mtu": "9100",
"speed": "40000"
}
$
なお、テーブルが存在しない場合取得に失敗します。たとえばVLANを設定していない場合、下記のようになります。(設定すれば取得できます)
$ ./telemetry_get.sh 192.168.1.34:8080 CONFIG_DB VLAN
F0118 14:15:20.090200 48481 gnmi_get.go:137] Get Failed: rpc error: code = Not Found desc = Failed to find CONFIG_DB VLAN <nil> []
$
OpenConfig?
サポートしているようです。確認のため、gnmi_capabilities
を使ってみます。
$ go get github.com/google/gnxi/gnmi_capabilities
実行結果は下記。
$ gnmi_capabilities -target_addr 192.168.1.34:8080 -target_name sonic -insecure
== CapabilitiesResponse:
supported_models: <
name: "openconfig-acl"
organization: "OpenConfig working group"
version: "1.0.2"
>
supported_models: <
name: "openconfig-interfaces"
organization: "OpenConfig working group"
version: "1.0.2"
>
supported_models: <
name: "openconfig-lldp"
organization: "OpenConfig working group"
version: "1.0.2"
>
supported_models: <
name: "openconfig-platform"
organization: "OpenConfig working group"
version: "1.0.2"
>
supported_models: <
name: "openconfig-system"
organization: "OpenConfig working group"
version: "1.0.2"
>
supported_encodings: JSON
supported_encodings: JSON_IETF
gNMI_version: "0.7.0"
$
実際に取得してみます。-xpath_target
にopenconfig
を指定し、-xpath
にOpenConfigのpathを書きます。
$ ./telemetry_get.sh 192.168.1.34:8080 openconfig /openconfig-interfaces:interfaces/interface[name=Ethernet0]
{
"openconfig-interfaces:interface": [
{
"config": {
"description": "",
"mtu": 9100,
"name": "Ethernet0"
},
"name": "Ethernet0",
"openconfig-if-ethernet:ethernet": {
"config": {
"port-speed": "openconfig-if-ethernet:SPEED_40GB"
},
"state": {
"port-speed": "openconfig-if-ethernet:SPEED_40GB"
}
},
"state": {
"admin-status": "UP",
"counters": {
"in-broadcast-pkts": "0",
"in-discards": "0",
"in-errors": "0",
"in-multicast-pkts": "0",
"in-octets": "0",
"in-pkts": "0",
"in-unicast-pkts": "0",
"out-broadcast-pkts": "0",
"out-discards": "0",
"out-errors": "0",
"out-multicast-pkts": "0",
"out-octets": "0",
"out-pkts": "0",
"out-unicast-pkts": "0"
},
"description": "",
"ifindex": 0,
"mtu": 9100,
"name": "Ethernet0",
"oper-status": "DOWN"
},
"subinterfaces": {
"subinterface": [
{
"index": 0
}
]
}
}
]
}
$
標準に則った(OSが違っても同じフォーマットの)出力が得られますので、情報量に不足がなければOpenConfigフォーマットを使ったほうがいいと思います。が、capabilitiesの結果からわかるとおりいろいろ足りないので、今後に期待というところです。
おわりに
設定もできると思いますが、今回は割愛しました。いつか試してみたいと思います。