Skip to content

Commit

Permalink
sonic-snmpagent: fixed interface speeds (sonic-net#73)
Browse files Browse the repository at this point in the history
* sonic-snmpagent: fixed interface speeds
* ifSpeed now reports speed under 2^32 bps
* ifSpeed returns 2^32 is speed is above
* ifHighSpeed reports the interface speed in Mbps
* ifHighSpeed defaults to 40000 if speed not available in APPL_DB
* unit tests for rfc1213 and rfc2863
* appl_db.json modified to provide variety of speeds
  • Loading branch information
MichelMoriniaux authored and qiluo-msft committed Aug 7, 2018
1 parent 10528ee commit 9d113dc
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 20 deletions.
31 changes: 20 additions & 11 deletions src/sonic_ax_impl/mibs/ietf/rfc1213.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ class IpMib(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.4'):
SubtreeMIBEntry('22.1.2', arp_updater, ValueType.OCTET_STRING, arp_updater.arp_dest)

class InterfacesUpdater(MIBUpdater):

RFC1213_MAX_SPEED = 4294967295

def __init__(self):
super().__init__()
self.db_conn = mibs.init_db()
Expand Down Expand Up @@ -282,13 +285,13 @@ def _get_if_entry(self, sub_id):
if not oid:
return

table = ""
if_table = ""
if oid in self.oid_lag_name_map:
table = mibs.lag_entry_table(self.oid_lag_name_map[oid])
if_table = mibs.lag_entry_table(self.oid_lag_name_map[oid])
else:
table = mibs.if_entry_table(self.oid_name_map[oid])
if_table = mibs.if_entry_table(self.oid_name_map[oid])

return self.db_conn.get_all(mibs.APPL_DB, table, blocking=True)
return self.db_conn.get_all(mibs.APPL_DB, if_table, blocking=True)

def _get_status(self, sub_id, key):
"""
Expand Down Expand Up @@ -336,6 +339,18 @@ def get_mtu(self, sub_id):

return int(entry.get(b"mtu", 0))

def get_speed_bps(self, sub_id):
"""
:param sub_id: The 1-based sub-identifier query.
:return: min of RFC1213_MAX_SPEED or speed value for the respective sub_id.
"""
entry = self._get_if_entry(sub_id)
if not entry:
return

speed = int(entry.get(b"speed", 0))
# speed is reported in Mbps in the db
return min(RFC1213_MAX_SPEED, speed * 1000000)

class InterfacesMIB(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.2'):
"""
Expand Down Expand Up @@ -365,14 +380,8 @@ class InterfacesMIB(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.2'):
ifMtu = \
SubtreeMIBEntry('2.1.4', if_updater, ValueType.INTEGER, if_updater.get_mtu)

# FIXME Placeholder.
# "If the bandwidth of the interface is greater
# than the maximum value reportable by this object,
# then this object should report its maximum value
# (4.294,967,295) and ifHighSpeed must be used to
# report the interface's speed."
ifSpeed = \
SubtreeMIBEntry('2.1.5', if_updater, ValueType.GAUGE_32, lambda sub_id: 4294967295)
SubtreeMIBEntry('2.1.5', if_updater, ValueType.GAUGE_32, if_updater.get_speed_bps)

# FIXME Placeholder.
ifPhysAddress = \
Expand Down
31 changes: 29 additions & 2 deletions src/sonic_ax_impl/mibs/ietf/rfc2863.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,34 @@ def _get_counter(self, oid, table_name, mask):
mibs.logger.warning("SyncD 'COUNTERS_DB' missing attribute '{}'.".format(e))
return None

def _get_if_entry(self, sub_id):
"""
:param oid: The 1-based sub-identifier query.
:return: the DB entry for the respective sub_id.
"""
oid = self.get_oid(sub_id)
if not oid:
return

if_table = ""
if oid in self.oid_lag_name_map:
if_table = mibs.lag_entry_table(self.oid_lag_name_map[oid])
else:
if_table = mibs.if_entry_table(self.oid_name_map[oid])

return self.db_conn.get_all(mibs.APPL_DB, if_table, blocking=True)

def get_high_speed(self, sub_id):
"""
:param sub_id: The 1-based sub-identifier query.
:return: speed value for the respective sub_id or 40000 if not defined.
"""
entry = self._get_if_entry(sub_id)
if not entry:
return

return int(entry.get(b"speed", 40000))


class InterfaceMIBObjects(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.31.1'):
"""
Expand Down Expand Up @@ -259,8 +287,7 @@ class InterfaceMIBObjects(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.31.1'):
""" # FIXME: Placeholder (original impl reported 0)
ifLinkUpDownTrapEnable = SubtreeMIBEntry('1.1.14', if_updater, ValueType.INTEGER, lambda sub_id: 2)

# FIXME: Placeholder
ifHighSpeed = SubtreeMIBEntry('1.1.15', if_updater, ValueType.GAUGE_32, lambda sub_id: 40000)
ifHighSpeed = SubtreeMIBEntry('1.1.15', if_updater, ValueType.GAUGE_32, if_updater.get_high_speed)

"""
ifPromiscuousMode OBJECT-TYPE
Expand Down
10 changes: 4 additions & 6 deletions tests/mock_tables/appl_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -572,11 +572,10 @@
},
"PORT_TABLE:Ethernet116": {
"description": "snowflake",
"speed": 100000
"speed": 1000
},
"PORT_TABLE:Ethernet120": {
"description": "snowflake",
"speed": 100000
"description": "snowflake"
},
"PORT_TABLE:Ethernet124": {
"description": "snowflake",
Expand Down Expand Up @@ -700,11 +699,10 @@
},
"PORT_TABLE:Ethernet116": {
"description": "snowflake",
"speed": 100000
"speed": 1000
},
"PORT_TABLE:Ethernet120": {
"description": "snowflake",
"speed": 100000
"description": "snowflake"
},
"PORT_TABLE:Ethernet124": {
"description": "snowflake",
Expand Down
59 changes: 58 additions & 1 deletion tests/test_hc_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,61 @@ def test_get_next3(self):
payload = b'\x01\x06\x10\x00\x00\x00\x00\x17\x00\x00\x01V\x00\x00\x01W\x00\x00\x00,\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x03\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x02\x01\x06\x10\x00\x00\x00\x00\x17\x00\x00\x01\\\x00\x00\x01]\x00\x00\x00,\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x03\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x02\x01\x06\x10\x00\x00\x00\x00\x17\x00\x00\x01b\x00\x00\x01c\x00\x00\x00,\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x03\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x02\x01\x06\x10\x00\x00\x00\x00\x17\x00\x00\x01h\x00\x00\x01i\x00\x00\x00,\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x03\x02\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1f\x00\x00\x00\x02'
pdu = PDU.decode(payload)
resp = pdu.make_response(self.lut)
print(resp)
print(resp)

def test_low_speed(self):
"""
For an interface with a speed inside the 32 bit counter returns the speed of the interface in Mbps
"""
oid = ObjectIdentifier(12, 0, 0, 0, (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15, 113))
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.GAUGE_32)
self.assertEqual(str(value0.name), str(ObjectIdentifier(12, 0, 1, 0, (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15, 117))))
self.assertEqual(value0.data, 1000)

def test_high_speed(self):
"""
should return the speed of the interface
"""
oid = ObjectIdentifier(12, 0, 0, 0, (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15, 1))
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.GAUGE_32)
self.assertEqual(str(value0.name), str(ObjectIdentifier(12, 0, 1, 0, (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15, 5))))
self.assertEqual(value0.data, 100000)

def test_no_speed(self):
"""
For a port with no speed in the db the result should be 40000
"""
oid = ObjectIdentifier(12, 0, 0, 0, (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15, 117))
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.GAUGE_32)
self.assertEqual(str(value0.name), str(ObjectIdentifier(12, 0, 1, 0, (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15, 121))))
self.assertEqual(value0.data, 40000)
57 changes: 57 additions & 0 deletions tests/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,60 @@ def test_missing_counter(self):
pdu = PDU.decode(resp)
resp = pdu.make_response(self.lut)
print(resp)

def test_low_speed(self):
"""
For an interface with a speed inside the 32 bit counter returns the speed of the interface in bps
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 5, 113))
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.GAUGE_32)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 5, 117))))
self.assertEqual(value0.data, 1000000000)

def test_high_speed(self):
"""
For a speed higher than 4,294,967,295 the retrun should be 4294967295
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 5, 1))
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.GAUGE_32)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 5, 5))))
self.assertEqual(value0.data, 4294967295)

def test_no_speed(self):
"""
For a port with no speed in the db the result should be 0
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 5, 117))
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.GAUGE_32)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 5, 121))))
self.assertEqual(value0.data, 0)

0 comments on commit 9d113dc

Please sign in to comment.