Skip to content

Commit

Permalink
[sonic-snmpagent] SONiC physical entity mib extension (sonic-net#168)
Browse files Browse the repository at this point in the history
Implement all mib objects defined in EntPhysicalEntry of RFC 2737.

**- How I did it**

Refactor rfc2737.py to have different mib updater for different physical entity: XcvrCacheUpdater, FanCacheUpdater, FanDrawerCacheUpdater, PsuCacheUpdater, ThermalCacheUpdater.

**- How to verify it**

Manual test on MSN2410
  • Loading branch information
Junchao-Mellanox authored Nov 12, 2020
1 parent 6b94ec3 commit b8f19ee
Show file tree
Hide file tree
Showing 8 changed files with 1,311 additions and 260 deletions.
89 changes: 34 additions & 55 deletions src/sonic_ax_impl/mibs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,6 @@
TABLE_NAME_SEPARATOR_COLON = ':'
TABLE_NAME_SEPARATOR_VBAR = '|'

# This is used in both rfc2737 and rfc3433
SENSOR_PART_ID_MAP = {
"temperature": 1,
"voltage": 2,
"rx1power": 11,
"rx2power": 21,
"rx3power": 31,
"rx4power": 41,
"tx1bias": 12,
"tx2bias": 22,
"tx3bias": 32,
"tx4bias": 42,
"tx1power": 13,
"tx2power": 23,
"tx3power": 33,
"tx4power": 43,
}

# IfIndex to OID multiplier for transceiver
IFINDEX_SUB_ID_MULTIPLIER = 1000

redis_kwargs = {'unix_socket_path': '/var/run/redis/redis.sock'}


Expand All @@ -65,6 +44,22 @@ def chassis_info_table(chassis_name):

return "CHASSIS_INFO" + TABLE_NAME_SEPARATOR_VBAR + chassis_name

def fan_info_table(fan_name):
"""
:param: fan_name: fan name
:return: fan info entry for this fan
"""
return 'FAN_INFO' + TABLE_NAME_SEPARATOR_VBAR + fan_name


def fan_drawer_info_table(drawer_name):
"""
:param: drawer_name: fan drawer name
:return: fan drawer info entry for this fan
"""
return 'FAN_DRAWER_INFO' + TABLE_NAME_SEPARATOR_VBAR + drawer_name


def psu_info_table(psu_name):
"""
:param: psu_name: psu name
Expand All @@ -73,6 +68,15 @@ def psu_info_table(psu_name):

return "PSU_INFO" + TABLE_NAME_SEPARATOR_VBAR + psu_name


def physical_entity_info_table(name):
"""
:param: name: object name
:return: entity info entry for this object
"""
return 'PHYSICAL_ENTITY_INFO' + TABLE_NAME_SEPARATOR_VBAR + name


def counter_table(sai_id):
"""
:param if_name: given sai_id to cast.
Expand Down Expand Up @@ -106,6 +110,14 @@ def transceiver_dom_table(port_name):

return "TRANSCEIVER_DOM_SENSOR" + TABLE_NAME_SEPARATOR_VBAR + port_name

def thermal_info_table(thermal_name):
"""
:param: port_name: port name
:return: transceiver dom entry for this port
"""

return "TEMPERATURE_INFO" + TABLE_NAME_SEPARATOR_VBAR + thermal_name

def lldp_entry_table(if_name):
"""
:param if_name: given interface to cast.
Expand Down Expand Up @@ -386,40 +398,6 @@ def get_device_metadata(db_conn):
device_metadata = db_conn.get_all(db_conn.STATE_DB, DEVICE_METADATA)
return device_metadata

def get_transceiver_sub_id(ifindex):
"""
Returns sub OID for transceiver. Sub OID is calculated as folows:
+------------+------------+
|Interface |Index |
+------------+------------+
|Ethernet[X] |X * 1000 |
+------------+------------+
()
:param ifindex: interface index
:return: sub OID of a port calculated as sub OID = {{index}} * 1000
"""

return (ifindex * IFINDEX_SUB_ID_MULTIPLIER, )

def get_transceiver_sensor_sub_id(ifindex, sensor):
"""
Returns sub OID for transceiver sensor. Sub OID is calculated as folows:
+-------------------------------------+------------------------------+
|Sensor |Index |
+-------------------------------------+------------------------------+
|RX Power for Ethernet[X]/[LANEID] |X * 1000 + LANEID * 10 + 1 |
|TX Bias for Ethernet[X]/[LANEID] |X * 1000 + LANEID * 10 + 2 |
|Temperature for Ethernet[X] |X * 1000 + 1 |
|Voltage for Ethernet[X]/[LANEID] |X * 1000 + 2 |
+-------------------------------------+------------------------------+
()
:param ifindex: interface index
:param sensor: sensor key
:return: sub OID = {{index}} * 1000 + {{lane}} * 10 + sensor id
"""

transceiver_oid, = get_transceiver_sub_id(ifindex)
return (transceiver_oid + SENSOR_PART_ID_MAP[sensor], )

def get_redis_pubsub(db_conn, db_name, pattern):
redis_client = db_conn.get_redis_client(db_name)
Expand All @@ -428,6 +406,7 @@ def get_redis_pubsub(db_conn, db_name, pattern):
pubsub.psubscribe("__keyspace@{}__:{}".format(db, pattern))
return pubsub


class RedisOidTreeUpdater(MIBUpdater):
def __init__(self, prefix_str):
super().__init__()
Expand Down
188 changes: 188 additions & 0 deletions src/sonic_ax_impl/mibs/ietf/physical_entity_sub_oid_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
"""
For non-port entity, the rule to generate entPhysicalIndex describes below:
The entPhysicalIndex is divided into 3 layers:
1. Module layer which includes modules located on system (e.g. fan drawer, PSU)
2. Device layer which includes system devices (e.g. fan )
3. Sensor layer which includes system sensors (e.g. temperature sensor, fan sensor)
The entPhysicalIndex is a 9 digits number, and each digit describes below:
Digit 1: Module Type
Digit 2~3: Module Index
Digit 4~5: Device Type
Digit 6~7: Device Index
Digit 8: Sensor Type
Digit 9: Sensor Index
Module Type describes below:
2 - Management
5 - Fan Drawer
6 - PSU
Device Type describes below:
01 - PS
02 - Fan
24 - Power Monitor (temperature, power, current, voltage...)
99 - Chassis Thermals
Sensor Type describes below:
1 - Temperature
2 - Fan Tachometers
3 - Power
4 - Current
5 - Voltage
e.g. 501000000 means the first fan drawer, 502020100 means the first fan of the second fan drawer
As we are using ifindex to generate port entPhysicalIndex and ifindex might be a valur larger
than 99, we uses a different way to generate port entPhysicalIndex.
For port entity, the entPhysicalIndex is a 10 digits number, and each digit describes below:
Digit 1: 1
Digit 2~8: ifindex
Digit 9: Sensor Type
Digit 10: Sensor Index
Port Sensor Type describes below:
1 - Temperature
2 - TX Power
3 - RX Power
4 - TX BIAS
5 - Voltage
"""

# Moduel Type Definition
MODULE_TYPE_MULTIPLE = 100000000
MODULE_INDEX_MULTIPLE = 1000000
MODULE_TYPE_MGMT = 2 * MODULE_TYPE_MULTIPLE
MODULE_TYPE_FAN_DRAWER = 5 * MODULE_TYPE_MULTIPLE
MODULE_TYPE_PSU = 6 * MODULE_TYPE_MULTIPLE
MODULE_TYPE_PORT = 1000000000

# Device Type Definition
DEVICE_TYPE_MULTIPLE = 10000
DEVICE_INDEX_MULTIPLE = 100
DEVICE_TYPE_PS = 1 * DEVICE_TYPE_MULTIPLE
DEVICE_TYPE_FAN = 2 * DEVICE_TYPE_MULTIPLE
DEVICE_TYPE_CHASSIS_THERMAL = 99 * DEVICE_TYPE_MULTIPLE
DEVICE_TYPE_POWER_MONITOR = 24 * DEVICE_TYPE_MULTIPLE

# Sensor Type Definition
SENSOR_TYPE_MULTIPLE = 10
SENSOR_TYPE_TEMP = 1 * SENSOR_TYPE_MULTIPLE
SENSOR_TYPE_FAN = 2 * SENSOR_TYPE_MULTIPLE
SENSOR_TYPE_POWER = 3 * SENSOR_TYPE_MULTIPLE
SENSOR_TYPE_CURRENT = 4 * SENSOR_TYPE_MULTIPLE
SENSOR_TYPE_VOLTAGE = 5 * SENSOR_TYPE_MULTIPLE

# Port entPhysicalIndex Definition
PORT_IFINDEX_MULTIPLE = 100
SENSOR_TYPE_PORT_TX_POWER = 2 * SENSOR_TYPE_MULTIPLE
SENSOR_TYPE_PORT_RX_POWER = 3 * SENSOR_TYPE_MULTIPLE
SENSOR_TYPE_PORT_TX_BIAS = 4 * SENSOR_TYPE_MULTIPLE

CHASSIS_SUB_ID = 1
CHASSIS_MGMT_SUB_ID = MODULE_TYPE_MGMT

# This is used in both rfc2737 and rfc3433
XCVR_SENSOR_PART_ID_MAP = {
"temperature": SENSOR_TYPE_TEMP,
"tx1power": SENSOR_TYPE_PORT_TX_POWER + 1,
"tx2power": SENSOR_TYPE_PORT_TX_POWER + 2,
"tx3power": SENSOR_TYPE_PORT_TX_POWER + 3,
"tx4power": SENSOR_TYPE_PORT_TX_POWER + 4,
"rx1power": SENSOR_TYPE_PORT_RX_POWER + 1,
"rx2power": SENSOR_TYPE_PORT_RX_POWER + 2,
"rx3power": SENSOR_TYPE_PORT_RX_POWER + 3,
"rx4power": SENSOR_TYPE_PORT_RX_POWER + 4,
"tx1bias": SENSOR_TYPE_PORT_TX_BIAS + 1,
"tx2bias": SENSOR_TYPE_PORT_TX_BIAS + 2,
"tx3bias": SENSOR_TYPE_PORT_TX_BIAS + 3,
"tx4bias": SENSOR_TYPE_PORT_TX_BIAS + 4,
"voltage": SENSOR_TYPE_VOLTAGE,
}

PSU_SENSOR_PART_ID_MAP = {
'temperature': SENSOR_TYPE_TEMP,
'power': SENSOR_TYPE_POWER,
'current': SENSOR_TYPE_CURRENT,
'voltage': SENSOR_TYPE_VOLTAGE
}

def get_chassis_thermal_sub_id(position):
"""
Returns sub OID for thermals that belong to chassis. Sub OID is calculated as follows:
sub OID = CHASSIS_MGMT_SUB_ID + DEVICE_TYPE_CHASSIS_THERMAL + position * DEVICE_INDEX_MULTIPLE + SENSOR_TYPE_TEMP,
:param position: thermal position
:return: sub OID of the thermal
"""
return (CHASSIS_MGMT_SUB_ID + DEVICE_TYPE_CHASSIS_THERMAL + position * DEVICE_INDEX_MULTIPLE + SENSOR_TYPE_TEMP, )

def get_fan_sub_id(parent_id, position):
"""
Returns sub OID for fan. Sub OID is calculated as follows:
sub OID = parent_id[0] + DEVICE_TYPE_FAN + position * DEVICE_INDEX_MULTIPLE
If parent_id is chassis OID, will use a "virtual" fan drawer OID as its parent_id
:param parent_id: parent device sub OID
:param position: fan position
:return: sub OID of the fan
"""
if parent_id[0] == CHASSIS_SUB_ID:
parent_id = MODULE_TYPE_FAN_DRAWER + position * MODULE_INDEX_MULTIPLE
else:
parent_id = parent_id[0]
return (parent_id + DEVICE_TYPE_FAN + position * DEVICE_INDEX_MULTIPLE, )

def get_fan_drawer_sub_id(position):
"""
Returns sub OID for fan drawer. Sub OID is calculated as follows:
sub OID = MODULE_TYPE_FAN_DRAWER + position * MODULE_INDEX_MULTIPLE
:param position: fan drawer position
:return: sub OID of the fan drawer
"""
return (MODULE_TYPE_FAN_DRAWER + position * MODULE_INDEX_MULTIPLE, )

def get_fan_tachometers_sub_id(parent_id):
"""
Returns sub OID for fan tachometers. Sub OID is calculated as follows:
sub OID = parent_id[0] + SENSOR_TYPE_FAN
:param parent_id: parent device sub OID
:return: sub OID of the fan tachometers
"""
return (parent_id[0] + SENSOR_TYPE_FAN, )

def get_psu_sub_id(position):
"""
Returns sub OID for PSU. Sub OID is calculated as follows:
sub OID = MODULE_TYPE_PSU + position * MODULE_INDEX_MULTIPLE
:param position: PSU position
:return: sub OID of PSU
"""
return (MODULE_TYPE_PSU + position * MODULE_INDEX_MULTIPLE, )

def get_psu_sensor_sub_id(parent_id, sensor):
"""
Returns sub OID for PSU sensor. Sub OID is calculated as follows:
sub OID = parent_id[0] + DEVICE_TYPE_POWER_MONITOR + PSU_SENSOR_PART_ID_MAP[sensor]
:param parent_id: PSU oid
:param sensor: PSU sensor name
:return: sub OID of PSU sensor
"""
return (parent_id[0] + DEVICE_TYPE_POWER_MONITOR + PSU_SENSOR_PART_ID_MAP[sensor], )

def get_transceiver_sub_id(ifindex):
"""
Returns sub OID for transceiver. Sub OID is calculated as folows:
sub OID = MODULE_TYPE_PORT + ifindex * PORT_IFINDEX_MULTIPLE
:param ifindex: interface index
:return: sub OID of a port
"""
return (MODULE_TYPE_PORT + ifindex * PORT_IFINDEX_MULTIPLE, )

def get_transceiver_sensor_sub_id(ifindex, sensor):
"""
Returns sub OID for transceiver sensor. Sub OID is calculated as folows:
sub OID = transceiver_oid + XCVR_SENSOR_PART_ID_MAP[sensor]
:param ifindex: interface index
:param sensor: sensor key
:return: sub OID = {{index}} * 1000 + {{lane}} * 10 + sensor id
"""

transceiver_oid, = get_transceiver_sub_id(ifindex)
return (transceiver_oid + XCVR_SENSOR_PART_ID_MAP[sensor],)
Loading

0 comments on commit b8f19ee

Please sign in to comment.