#show interfaces Te1/49 transceiver !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Optical Optical Temperature Voltage Tx Power Rx Power Port (Celsius) (Volts) (dBm) (dBm) --------- ----------- ------- -------- -------- Te1/49 53.3 3.25 -4.3 -2.8
Кому-то (у кого нет соответствующего доступа) приходится ждать этой минуты целую вечность. Например, когда канал упал в пиковые часы и на резервном линке какие-то потери, которые обнаружились только при загрузке линка трафиком. Или когда новый канал нужно было сдать вчера, а ничего не работает, потому что поставщик неправильно подписал оптику на CWDM-мультиплексоре, и требуется методом тыка отыскать «правильную волну». И все это происходит в условиях дефицита верховных сетевых инженеров и времени.
В статье рассматривается вариант того, как проверить сигнал, имея лишь read-only доступ по SNMP. Ждать при этом приходится не более 10 минут (обычный период обновления соответвтующей переменной). Выделение такого доступа кажется более
Дано
- хост с IP-адресом, который имеет read-only доступ по SNMP к нескольким Cisco (7604, 7609, 4948-10GE)
- IP-адрес устройства Cisco (например, 10.0.7.35)
- номер порта (например, Te1/49)
Найти
- уровень сигнала трансивера, установленного в заданный порт
Решение
Для начала найдем нужный OID. Он будет состоять из ID «entSensorValue» и «индекса» самого сенсора. Последний можно найти, выполнив следующий запрос с хоста, который имеет доступ по snmp к сетевому устройству с management IP 10.0.7.35:
$ snmpwalk -v 2c -c community 10.0.7.35 1.3.6.1.2.1.47.1.1.1.1.7 | grep Te1/49 SNMPv2-SMI::mib-2.47.1.1.1.1.7.1107 = STRING: "Te1/49 Module Temperature Sensor" SNMPv2-SMI::mib-2.47.1.1.1.1.7.1157 = STRING: "Te1/49 Supply Voltage Sensor" SNMPv2-SMI::mib-2.47.1.1.1.1.7.1207 = STRING: "Te1/49 Bias Current Sensor" SNMPv2-SMI::mib-2.47.1.1.1.1.7.1257 = STRING: "Te1/49 Transmit Power Sensor" SNMPv2-SMI::mib-2.47.1.1.1.1.7.1307 = STRING: "Te1/49 Receive Power Sensor"
Воспользуемся последним числом в OID для «Te1/49 Transmit Power Sensor» и «Te1/49 Receive Power Sensor». Это соответственно 1257 и 1307. Используя эти числа, мы сразу можем получить уровень исходящего и входящего оптического сигнала (value):
$ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.4.1257 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.4.1257 = INTEGER: -28 $ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.4.1307 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.4.1307 = INTEGER: -35
Комбинируя аналогичным образом «entSensorPrecision» и «индекс» сенсора, находим точность измерения (количество знаков после запятой):
$ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.3.1257 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.3.1257 = INTEGER: 1 $ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.3.1307 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.3.1307 = INTEGER: 1
Цифра «1» в этом случае означает, что нужно поставить запятую перед одной цифрой справа в значении соответствующего сенсора.
Te1/49 Transmit Power = -2,8
Te1/49 Receive Power = -3,5
Чтобы определить единицы измерения, воспользуемся «entSensorType» в комбинации с «индексом» сенсора:
$ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.1.1257 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.1.1257 = INTEGER: 14 $ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.1.1307 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.1.1307 = INTEGER: 14
Значение 14 соответсвует единицам «dBm». Список значений дается в описании «entSensorType».
К единицам измерения может быть добавлена десятичная приставка. Какая именно — покажет «entSensorScale»:
$ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.2.1257 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.2.1257 = INTEGER: 9 $ snmpget -v 2c -c community 10.0.7.35 1.3.6.1.4.1.9.9.91.1.1.1.1.2.1307 SNMPv2-SMI::enterprises.9.9.91.1.1.1.1.2.1307 = INTEGER: 9
В данном случае приставка «Units» (которая соответствует числу 9) фактически означает отсутствие приставки.
Таким образом, мы получили уровень сигнала трансивера, установленного в порту Te1/49, на свиче с IP 10.0.7.35
Te1/49 Transmit Power = -2,8 dBm
Te1/49 Receive Power = -3,5 dBm
Составим ответ по учебнику:
#!/bin/bash E_OPTERROR=65 verbose=0 get_type () { if [ -z "$1" ] # Length of argument is 0? then exit $E_OPTERROR elif [ "$1" -eq "1" ] then truetype=other elif [ "$1" -eq "2" ] then truetype=unknown elif [ "$1" -eq "3" ] then truetype=voltsAC elif [ "$1" -eq "4" ] then truetype=voltsDC elif [ "$1" -eq "5" ] then truetype=amperes elif [ "$1" -eq "6" ] then truetype=watts elif [ "$1" -eq "7" ] then truetype=hertz elif [ "$1" -eq "8" ] then truetype=celsius elif [ "$1" -eq "9" ] then truetype=percentRH elif [ "$1" -eq "10" ] then truetype="rpm" elif [ "$1" -eq "11" ] then truetype=cmm elif [ "$1" -eq "12" ] then truetype=truthvalue elif [ "$1" -eq "13" ] then truetype=specialEnum elif [ "$1" -eq "14" ] then truetype=dBm else echo type=$1,error; exit $E_OPTERROR fi return 0 } get_scale () { if [ -z "$1" ] # Length of argument is 0? then exit $E_OPTERROR elif [ "$1" -eq "1" ] then truescale=yocto elif [ "$1" -eq "2" ] then truescale=zepto elif [ "$1" -eq "3" ] then truescale=atto elif [ "$1" -eq "4" ] then truescale=femto elif [ "$1" -eq "5" ] then truescale=pico elif [ "$1" -eq "6" ] then truescale=nano elif [ "$1" -eq "7" ] then truescale=micro elif [ "$1" -eq "8" ] then truescale=milli elif [ "$1" -eq "9" ] then truescale="" elif [ "$1" -eq "10" ] then truescale=kilo elif [ "$1" -eq "11" ] then truescale=mega elif [ "$1" -eq "12" ] then truescale=giga elif [ "$1" -eq "13" ] then truescale=tera elif [ "$1" -eq "14" ] then truescale=exa elif [ "$1" -eq "15" ] then truescale=peta elif [ "$1" -eq "16" ] then truescale=zetta elif [ "$1" -eq "17" ] then truescale=yotta else echo scale=$1,error; exit $E_OPTERROR fi return 0 } #reading the options while getopts ":c:h:i:v" Option do #echo $OPTIND case $Option in c ) community=$OPTARG;; h ) host=$OPTARG;; i ) interface=$OPTARG;; v ) echo "Verbose mode is set";verbose=1;; * ) echo "Usage: `basename $0` -c community -h host -i interface"; exit $E_OPTERROR;; # default options esac done shift $(($OPTIND - 1)) #moving on to the next provided option if [ -z "$community" ] || [ -z $host ] || [ -z $interface ] # if some of options is not submitted then echo "Usage: `basename $0` -c community -h host -i interface" exit $E_OPTERROR fi if [ $verbose -eq 1 ] then echo "community is \"$community\"" echo "host is \"$host\"" echo "interface is \"$interface\"" fi #looking for the index of sensor if [ $verbose -eq 1 ] then echo "executing \"snmpwalk -v 2c -OX -c $community $host 1.3.6.1.2.1.47.1.1.1.1.7 | grep $interface\"" fi # step1: getiing information about device #snmpwalk -v 2c -OX -c $community $host 1.3.6.1.2.1.47.1.1.1.1.7 | grep $interface > index=0 while read line; do string[$index]="$line" index=$(($index+1)) # done < <(cat tempcache) done < <(snmpwalk -v 2c -OX -c $community $host 1.3.6.1.2.1.47.1.1.1.1.7 | grep $interface) if [ $verbose -eq 1 ] then for ((a=0; a < ${#string[*]}; a++)) do echo "have a string#$a as ${string[$a]}" done fi # step2: parse/cut received strings if [ $verbose -eq 1 ] then echo "parsing/cuting snmpwalk result" fi for ((a=0; a < ${#string[*]}; a++)) do rx_string=`echo ${string[$a]} | grep Receive`; tx_string=`echo ${string[$a]} | grep Transmit`; if [ -n "$rx_string" ] then rx_sensor=`echo ${string[$a]}| cut -d "[" -f2 | cut -d "]" -f1` elif [ -n "$tx_string" ] then tx_sensor=`echo ${string[$a]}| cut -d "[" -f2 | cut -d "]" -f1` fi done if [ $verbose -eq 1 ] then echo "index of rx_sensor parsed to $rx_sensor" echo "index of tx_sensor parsed to $tx_sensor" fi #getting the sensor value if [ $verbose -eq 1 ] then echo "getting the sensor value" fi rx_value=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.4.$rx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` rx_precision=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.3.$rx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` rx_type=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.1.$rx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` get_type $rx_type rx_type=$truetype rx_scale=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.2.$rx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` get_scale $rx_scale rx_scale=$truescale tx_value=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.4.$tx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` tx_precision=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.3.$tx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` tx_type=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.1.$tx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` get_type $tx_type tx_type=$truetype tx_scale=`snmpget -v 2c -c $community $host 1.3.6.1.4.1.9.9.91.1.1.1.1.2.$rx_sensor | grep -o -e "INTEGER: [-+0-9]*" | cut -f2 -d" "` get_scale $tx_scale tx_scale=$truescale let lengthrx=${#rx_value}-$rx_precision let lengthtx=${#tx_value}-$tx_precision echo RX=${rx_value:0:$lengthrx}.${rx_value:$lengthrx} $rx_scale$rx_type echo TX=${tx_value:0:$lengthtx}.${tx_value:$lengthtx} $tx_scale$tx_type exit 0

