Skip to content

Commit a03f779

Browse files
committed
Added ciscoPfcExtMIB, ciscoSwitchQosMIB MIBs
Squashed commit of the following: commit 6c58080 Author: Qi Luo <[email protected]> Date: Fri Jan 26 15:08:53 2018 -0800 Fix queue counter value type, and wrap queue index (#4) * Fix queue counter value type * Wrap queue index commit 66d738c Author: Qi Luo <[email protected]> Date: Fri Jan 26 02:44:32 2018 +0000 Added ciscoPfcExtMIB, ciscoSwitchQosMIB MIBs Squashed commit of the following: commit 0b68d9e Author: Qi Luo <[email protected]> Date: Thu Jan 25 18:27:53 2018 -0800 Fix PFC queue index base and value type (#3) * Fix PFC queue index base * Fix pfc counter64 commit e84d1d8 Author: Qi Luo <[email protected]> Date: Tue Jan 23 23:59:51 2018 +0000 Added ciscoPfcExtMIB, ciscoSwitchQosMIB MIBs Squashed commit of the following: commit f0cbfff Author: Qi Luo <[email protected]> Date: Tue Jan 23 23:20:02 2018 +0000 Fix Pfc/Qos counter integer range commit c954e4e Author: AndriiS <[email protected]> Date: Thu Jan 11 21:51:35 2018 +0200 Added ciscoPfcExtMIB, ciscoSwitchQosMIB MIBs (#1) Remove lag from csqIfQosGroupStatsTable (#5)
1 parent 67050bb commit a03f779

File tree

8 files changed

+1968
-34
lines changed

8 files changed

+1968
-34
lines changed

src/sonic_ax_impl/main.py

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class SonicMIB(
3131
ieee802_1ab.LLDPLocPortTable,
3232
ieee802_1ab.LLDPRemTable,
3333
dell.force10.SSeriesMIB,
34+
cisco.ciscoPfcExtMIB.cpfcIfTable,
35+
cisco.ciscoPfcExtMIB.cpfcIfPriorityTable,
36+
cisco.ciscoSwitchQosMIB.csqIfQosGroupStatsTable,
3437
cisco.ciscoEntityFruControlMIB.cefcFruPowerStatusTable,
3538
):
3639
"""

src/sonic_ax_impl/mibs/__init__.py

+66
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from sonic_ax_impl import logger, _if_alias_map
88

99
COUNTERS_PORT_NAME_MAP = b'COUNTERS_PORT_NAME_MAP'
10+
COUNTERS_QUEUE_NAME_MAP = b'COUNTERS_QUEUE_NAME_MAP'
1011
LAG_TABLE = b'LAG_TABLE'
1112
LAG_MEMBER_TABLE = b'LAG_MEMBER_TABLE'
1213
APPL_DB = 'APPL_DB'
@@ -22,6 +23,16 @@ def counter_table(sai_id):
2223
"""
2324
return b'COUNTERS:oid:0x' + sai_id
2425

26+
def queue_table(sai_id):
27+
"""
28+
:param sai_id: given sai_id to cast.
29+
:return: COUNTERS table key.
30+
"""
31+
return b'COUNTERS:' + sai_id
32+
33+
def queue_key(port_index, queue_index):
34+
return str(port_index) + ':' + str(queue_index)
35+
2536

2637
def lldp_entry_table(if_name):
2738
"""
@@ -158,3 +169,58 @@ def member_name_str(val, lag_name):
158169
oid_lag_name_map[idx] = if_name
159170

160171
return lag_name_if_name_map, if_name_lag_name_map, oid_lag_name_map
172+
173+
def init_sync_d_queue_tables(db_conn):
174+
"""
175+
Initializes queue maps for SyncD-connected MIB(s).
176+
:return: tuple(port_queues_map, queue_stat_map)
177+
"""
178+
179+
# Make sure we're connected to COUNTERS_DB
180+
db_conn.connect(COUNTERS_DB)
181+
182+
# { Port index : Queue index (SONiC) -> sai_id }
183+
# ex: { "1:2" : "1000000000023" }
184+
queue_name_map = db_conn.get_all(COUNTERS_DB, COUNTERS_QUEUE_NAME_MAP, blocking=True)
185+
logger.debug("Queue name map:\n" + pprint.pformat(queue_name_map, indent=2))
186+
187+
# Parse the queue_name_map and create the following maps:
188+
# port_queues_map -> {"if_index : queue_index" : sai_oid}
189+
# queue_stat_map -> {queue stat table name : {counter name : value}}
190+
# port_queue_list_map -> {if_index: [sorted queue list]}
191+
port_queues_map = {}
192+
queue_stat_map = {}
193+
port_queue_list_map = {}
194+
195+
for queue_name, sai_id in queue_name_map.items():
196+
port_name, queue_index = queue_name.decode().split(':')
197+
queue_index = ''.join(i for i in queue_index if i.isdigit())
198+
port_index = get_index_from_str(port_name)
199+
key = queue_key(port_index, queue_index)
200+
port_queues_map[key] = sai_id
201+
202+
queue_stat_name = queue_table(sai_id)
203+
queue_stat = db_conn.get_all(COUNTERS_DB, queue_stat_name, blocking=False)
204+
if queue_stat is not None:
205+
queue_stat_map[queue_stat_name] = queue_stat
206+
207+
if not port_queue_list_map.get(int(port_index)):
208+
port_queue_list_map[int(port_index)] = [int(queue_index)]
209+
else:
210+
port_queue_list_map[int(port_index)].append(int(queue_index))
211+
212+
# SyncD consistency checks.
213+
if not port_queues_map:
214+
# In the event no queue exists that follows the SONiC pattern, no OIDs are able to be registered.
215+
# A RuntimeError here will prevent the 'main' module from loading. (This is desirable.)
216+
logger.error("No queues found in the Counter DB. SyncD database is incoherent.")
217+
raise RuntimeError('The port_queues_map is not defined')
218+
elif not queue_stat_map:
219+
logger.error("No queue stat counters found in the Counter DB. SyncD database is incoherent.")
220+
raise RuntimeError('The queue_stat_map is not defined')
221+
222+
for queues in port_queue_list_map.values():
223+
queues.sort()
224+
225+
return port_queues_map, queue_stat_map, port_queue_list_map
226+
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
from . import ciscoPfcExtMIB
2+
from . import ciscoSwitchQosMIB
13
from . import ciscoEntityFruControlMIB
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
from enum import unique, Enum
2+
from bisect import bisect_right
3+
4+
from sonic_ax_impl import mibs
5+
from ax_interface import MIBMeta, ValueType, MIBUpdater, MIBEntry, SubtreeMIBEntry
6+
from ax_interface.encodings import ObjectIdentifier
7+
8+
class PfcUpdater(MIBUpdater):
9+
"""
10+
Class to update the info from Counter DB and to handle the SNMP request
11+
"""
12+
def __init__(self):
13+
super().__init__()
14+
self.db_conn = mibs.init_db()
15+
16+
self.if_name_map = {}
17+
self.if_alias_map = {}
18+
self.if_id_map = {}
19+
self.oid_sai_map = {}
20+
self.oid_name_map = {}
21+
22+
self.lag_name_if_name_map = {}
23+
self.if_name_lag_name_map = {}
24+
self.oid_lag_name_map = {}
25+
26+
# cache of interface counters
27+
self.if_counters = {}
28+
self.if_range = []
29+
30+
def reinit_data(self):
31+
"""
32+
Subclass update interface information
33+
"""
34+
self.if_name_map, \
35+
self.if_alias_map, \
36+
self.if_id_map, \
37+
self.oid_sai_map, \
38+
self.oid_name_map = mibs.init_sync_d_interface_tables(self.db_conn)
39+
40+
self.update_data()
41+
42+
def update_data(self):
43+
"""
44+
Update redis (caches config)
45+
Pulls the table references for each interface.
46+
"""
47+
self.if_counters = \
48+
{sai_id: self.db_conn.get_all(mibs.COUNTERS_DB, mibs.counter_table(sai_id), blocking=True)
49+
for sai_id in self.if_id_map}
50+
51+
self.lag_name_if_name_map, \
52+
self.if_name_lag_name_map, \
53+
self.oid_lag_name_map = mibs.init_sync_d_lag_tables(self.db_conn)
54+
55+
self.if_range = sorted(list(self.oid_sai_map.keys()) + list(self.oid_lag_name_map.keys()))
56+
self.if_range = [(i,) for i in self.if_range]
57+
58+
def get_next(self, sub_id):
59+
"""
60+
:param sub_id: The 1-based sub-identifier query.
61+
:return: the next sub id.
62+
"""
63+
try:
64+
if not sub_id:
65+
return self.if_range[0]
66+
67+
right = bisect_right(self.if_range, sub_id)
68+
if right >= len(self.if_range):
69+
return None
70+
return self.if_range[right]
71+
except (IndexError, KeyError) as e:
72+
mibs.logger.error("failed to get next oid with error = {}".format(str(e)))
73+
74+
def get_oid(self, sub_id):
75+
"""
76+
:param sub_id: The 1-based sub-identifier query.
77+
:return: the interface OID.
78+
"""
79+
if sub_id is None or sub_id not in self.if_range:
80+
return None
81+
82+
return sub_id[0]
83+
84+
def _get_counter(self, oid, counter_name):
85+
"""
86+
:param sub_id: The interface OID.
87+
:param counter_name: the redis table (either IntEnum or string literal) to query.
88+
:return: the counter for the respective sub_id/table.
89+
"""
90+
sai_id = self.oid_sai_map[oid]
91+
92+
# Enum.name or counter_name = 'name_of_the_table'
93+
_counter_name = bytes(getattr(counter_name, 'name', counter_name), 'utf-8')
94+
95+
try:
96+
counter_value = self.if_counters[sai_id][_counter_name]
97+
counter_value = int(counter_value) & 0xffffffffffffffff
98+
# done!
99+
return counter_value
100+
except KeyError as e:
101+
mibs.logger.warning("SyncD 'COUNTERS_DB' missing attribute '{}'.".format(e))
102+
return None
103+
104+
def cpfc_if_requests(self, sub_id):
105+
"""
106+
:param sub_id: The 1-based sub-identifier query.
107+
:return: the counter for the respective sub_id/table.
108+
"""
109+
oid = self.get_oid(sub_id)
110+
if oid is None:
111+
return None
112+
113+
counter_name = 'SAI_PORT_STAT_PFC_3_RX_PKTS'
114+
115+
if oid in self.oid_lag_name_map:
116+
counter_value = 0
117+
for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[oid]]:
118+
counter_value += self._get_counter(mibs.get_index(lag_member), counter_name)
119+
120+
return counter_value
121+
else:
122+
return self._get_counter(oid, counter_name)
123+
124+
125+
def cpfc_if_indications(self, sub_id):
126+
"""
127+
:param sub_id: The 1-based sub-identifier query.
128+
:return: the counter for the respective sub_id/table.
129+
"""
130+
oid = self.get_oid(sub_id)
131+
if oid is None:
132+
return None
133+
134+
counter_name = 'SAI_PORT_STAT_PFC_3_TX_PKTS'
135+
136+
if oid in self.oid_lag_name_map:
137+
counter_value = 0
138+
for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[oid]]:
139+
counter_value += self._get_counter(mibs.get_index(lag_member), counter_name)
140+
141+
return counter_value
142+
else:
143+
return self._get_counter(oid, counter_name)
144+
145+
146+
class PfcPrioUpdater(PfcUpdater):
147+
def __init__(self):
148+
super().__init__()
149+
self.min_prio = 0
150+
self.max_prio = 7
151+
152+
def queue_index(self, sub_id):
153+
"""
154+
:param sub_id: The 0-based sub-identifier query.
155+
:return: the 0-based interface ID.
156+
"""
157+
if len(sub_id) >= 2:
158+
return sub_id[1]
159+
return None
160+
161+
def get_next(self, sub_id):
162+
"""
163+
:param sub_id: The 1-based sub-identifier query.
164+
:return: the next sub id.
165+
"""
166+
try:
167+
if not sub_id:
168+
return self.if_range[0][0], self.min_prio
169+
170+
if len(sub_id) < 2:
171+
return sub_id[0], self.min_prio
172+
173+
if sub_id[1] >= self.max_prio:
174+
idx = self.if_range.index((sub_id[0],))
175+
return self.if_range[idx + 1][0], self.min_prio
176+
177+
right = sub_id[1] + 1
178+
179+
return sub_id[0], right
180+
except IndexError:
181+
# Reached the last element. Return None to notify caller
182+
return None
183+
except Exception as e:
184+
mibs.logger.error("failed to get next oid with error = {}".format(str(e)))
185+
return None
186+
187+
def requests_per_priority(self, sub_id):
188+
"""
189+
:param sub_id: The 0-based sub-identifier query.
190+
:return: the counter for the respective sub_id/table.
191+
"""
192+
port_oid = ''
193+
queue_index = ''
194+
try:
195+
if not sub_id:
196+
return None
197+
198+
port_oid = self.get_oid((sub_id[0],))
199+
queue_index = self.queue_index(sub_id)
200+
if port_oid is None or queue_index is None:
201+
return None
202+
except Exception as e:
203+
mibs.logger.warning("requestsPerPriority: incorrect sub_id = {} error: {}".format(str(sub_id), e))
204+
return None
205+
206+
counter_name = 'SAI_PORT_STAT_PFC_' + str(queue_index) + '_RX_PKTS'
207+
208+
if port_oid in self.oid_lag_name_map:
209+
counter_value = 0
210+
for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[port_oid]]:
211+
counter_value += self._get_counter(mibs.get_index(lag_member), counter_name)
212+
213+
return counter_value
214+
else:
215+
return self._get_counter(port_oid, counter_name)
216+
217+
def indications_per_priority(self, sub_id):
218+
"""
219+
:param sub_id: The 0-based sub-identifier query.
220+
:return: the counter for the respective sub_id/table.
221+
"""
222+
port_oid = ''
223+
queue_index = ''
224+
try:
225+
if not sub_id:
226+
return None
227+
228+
port_oid = self.get_oid((sub_id[0],))
229+
queue_index = self.queue_index(sub_id)
230+
if port_oid is None or queue_index is None:
231+
return None
232+
except IndexError:
233+
mibs.logger.warning("indicationsPerPriority: incorrect sub_id = {}".format(str(sub_id)))
234+
return None
235+
236+
counter_name = 'SAI_PORT_STAT_PFC_' + str(queue_index) + '_TX_PKTS'
237+
238+
if port_oid in self.oid_lag_name_map:
239+
counter_value = 0
240+
for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[port_oid]]:
241+
counter_value += self._get_counter(mibs.get_index(lag_member), counter_name)
242+
243+
return counter_value
244+
else:
245+
return self._get_counter(port_oid, counter_name)
246+
247+
248+
# cpfcIfTable = '1.1'
249+
# cpfcIfEntry = '1.1.1.x'
250+
class cpfcIfTable(metaclass=MIBMeta, prefix='.1.3.6.1.4.1.9.9.813.1.1'):
251+
"""
252+
'ciscoPfcExtMIB' http://oidref.com/1.3.6.1.4.1.9.9.813.1.1
253+
"""
254+
pfc_updater = PfcUpdater()
255+
256+
ifRequests = \
257+
SubtreeMIBEntry('1.1', pfc_updater, ValueType.COUNTER_64, pfc_updater.cpfc_if_requests)
258+
259+
ifIndications = \
260+
SubtreeMIBEntry('1.2', pfc_updater, ValueType.COUNTER_64, pfc_updater.cpfc_if_indications)
261+
262+
263+
# cpfcIfPriorityTable = '1.2'
264+
# cpfcIfPriorityEntry = '1.2.x'
265+
class cpfcIfPriorityTable(metaclass=MIBMeta, prefix='.1.3.6.1.4.1.9.9.813.1.2'):
266+
"""
267+
'ciscoPfcExtMIB' http://oidref.com/1.3.6.1.4.1.9.9.813
268+
"""
269+
pfc_updater = PfcPrioUpdater()
270+
271+
prioRequests = \
272+
SubtreeMIBEntry('1.2', pfc_updater, ValueType.COUNTER_64, pfc_updater.requests_per_priority)
273+
274+
prioIndications = \
275+
SubtreeMIBEntry('1.3', pfc_updater, ValueType.COUNTER_64, pfc_updater.indications_per_priority)

0 commit comments

Comments
 (0)