[Из песочницы] Уровень сигнала трансивера через SNMP в Cisco
Иногда нужно узнать уровень сигнала в трансивере. Причины бывают разные: внезапное падение канала связи, подключение новых оптических кроссировок, мониторинг. Инженер с необходимым уровнем доступа решает этот вопрос меньше чем за одну минуту с помощью команды: #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 минут (обычный период обновления соответвтующей переменной). Выделение такого доступа кажется более безопаным логичным для ряда сотрудников, которые по тем или иным причинам не имеют CCNA или CCNP (инженеры мониторинга, операционисты, технические менеджеры). Так же информация может быть полезна при настройке систем мониторинга.
Дано
- хост с 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,8Te1/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 dBmTe1/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» fi # step1: getiing information from device walksnmp=`snmpwalk -v 2c -c $community $host 1.3.6.1.2.1.47.1.1.1.1.7 | grep $interface` # step2: parse received string if [ $verbose -eq 1 ] then echo «parsing snmpwalk result» fi rx_string=`echo $walksnmp | grep -o -e »[0–9]* = STRING: \»[ 0–9\/a-zA-Z]*Receive[ 0–9\/a-zA-Z]*\»` rx_sensor=`echo $walksnmp | grep -o -e »[0–9]* = STRING: \»[ 0–9\/a-zA-Z]*Receive[ 0–9\/a-zA-Z]*\» | cut -f1 -d » »` tx_string=`echo $walksnmp | grep -o -e »[0–9]* = STRING: \»[ 0–9\/a-zA-Z]*Transmit[ 0–9\/a-zA-Z]*\»` tx_sensor=`echo $walksnmp | grep -o -e »[0–9]* = STRING: \»[ 0–9\/a-zA-Z]*Transmit[ 0–9\/a-zA-Z]*\» | cut -f1 -d » »` if [ $verbose -eq 1 ] then echo «index of rx_sensor parsed to $rx_sensor» echo «index of tx_sensor parsed to $tx_sensor» echo »$rx_string» echo »$tx_string» 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