Skip to content

Commit c467dc8

Browse files
Revert "Revert "[rfc1213] Interface MIB add l3 vlan interfaces & aggregate rif counters (sonic-net#169)" (sonic-net#191)"
This reverts commit dfde06e.
1 parent 28b9dfd commit c467dc8

15 files changed

+1528
-49
lines changed

src/sonic_ax_impl/mibs/__init__.py

+69-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@
2727

2828
HOST_NAMESPACE_DB_IDX = 0
2929

30+
RIF_COUNTERS_AGGR_MAP = {
31+
"SAI_PORT_STAT_IF_IN_OCTETS": "SAI_ROUTER_INTERFACE_STAT_IN_OCTETS",
32+
"SAI_PORT_STAT_IF_IN_UCAST_PKTS": "SAI_ROUTER_INTERFACE_STAT_IN_PACKETS",
33+
"SAI_PORT_STAT_IF_IN_ERRORS": "SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS",
34+
"SAI_PORT_STAT_IF_OUT_OCTETS": "SAI_ROUTER_INTERFACE_STAT_OUT_OCTETS",
35+
"SAI_PORT_STAT_IF_OUT_UCAST_PKTS": "SAI_ROUTER_INTERFACE_STAT_OUT_PACKETS",
36+
"SAI_PORT_STAT_IF_OUT_ERRORS": "SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS"
37+
}
38+
39+
RIF_DROPS_AGGR_MAP = {
40+
"SAI_PORT_STAT_IF_IN_ERRORS": "SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS",
41+
"SAI_PORT_STAT_IF_OUT_ERRORS": "SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS"
42+
}
43+
44+
# IfIndex to OID multiplier for transceiver
45+
IFINDEX_SUB_ID_MULTIPLIER = 1000
46+
3047
redis_kwargs = {'unix_socket_path': '/var/run/redis/redis.sock'}
3148

3249

@@ -136,6 +153,14 @@ def if_entry_table(if_name):
136153
return 'PORT_TABLE:' + if_name
137154

138155

156+
def vlan_entry_table(if_name):
157+
"""
158+
:param if_name: given interface to cast.
159+
:return: VLAN_TABLE key.
160+
"""
161+
return 'VLAN_TABLE:' + if_name
162+
163+
139164
def lag_entry_table(lag_name):
140165
"""
141166
:param lag_name: given lag to cast.
@@ -292,6 +317,46 @@ def init_sync_d_interface_tables(db_conn):
292317

293318
return if_name_map, if_alias_map, if_id_map, oid_name_map
294319

320+
321+
def init_sync_d_rif_tables(db_conn):
322+
"""
323+
Initializes map of RIF SAI oids to port SAI oid.
324+
:return: dict
325+
"""
326+
rif_port_map = {get_sai_id_key(db_conn.namespace, rif): get_sai_id_key(db_conn.namespace, port)
327+
for rif, port in port_util.get_rif_port_map(db_conn).items()}
328+
port_rif_map = {port: rif for rif, port in rif_port_map.items()}
329+
logger.debug("Rif port map:\n" + pprint.pformat(rif_port_map, indent=2))
330+
331+
return rif_port_map, port_rif_map
332+
333+
334+
def init_sync_d_vlan_tables(db_conn):
335+
"""
336+
Initializes vlan interface maps for SyncD-connected MIB(s).
337+
:return: tuple(vlan_name_map, oid_sai_map, oid_name_map)
338+
"""
339+
340+
vlan_name_map = port_util.get_vlan_interface_oid_map(db_conn)
341+
342+
logger.debug("Vlan oid map:\n" + pprint.pformat(vlan_name_map, indent=2))
343+
344+
# { OID -> sai_id }
345+
oid_sai_map = {get_index_from_str(if_name): sai_id for sai_id, if_name in vlan_name_map.items()
346+
# only map the interface if it's a style understood to be a SONiC interface.
347+
if get_index_from_str(if_name) is not None}
348+
logger.debug("OID sai map:\n" + pprint.pformat(oid_sai_map, indent=2))
349+
350+
# { OID -> if_name (SONiC) }
351+
oid_name_map = {get_index_from_str(if_name): if_name for sai_id, if_name in vlan_name_map.items()
352+
# only map the interface if it's a style understood to be a SONiC interface.
353+
if get_index_from_str(if_name) is not None}
354+
355+
logger.debug("OID name map:\n" + pprint.pformat(oid_name_map, indent=2))
356+
357+
return vlan_name_map, oid_sai_map, oid_name_map
358+
359+
295360
def init_sync_d_lag_tables(db_conn):
296361
"""
297362
Helper method. Connects to and initializes LAG interface maps for SyncD-connected MIB(s).
@@ -345,7 +410,7 @@ def member_name_str(val, lag_name):
345410
if idx:
346411
oid_lag_name_map[idx] = if_name
347412

348-
return lag_name_if_name_map, if_name_lag_name_map, oid_lag_name_map, sai_lag_map
413+
return lag_name_if_name_map, if_name_lag_name_map, oid_lag_name_map, lag_sai_map, sai_lag_map
349414

350415
def init_sync_d_queue_tables(db_conn):
351416
"""
@@ -360,7 +425,7 @@ def init_sync_d_queue_tables(db_conn):
360425

361426
# Parse the queue_name_map and create the following maps:
362427
# port_queues_map -> {"port_index : queue_index" : sai_oid}
363-
# queue_stat_map -> {"port_index : queue stat table name" : {counter name : value}}
428+
# queue_stat_map -> {"port_index : queue stat table name" : {counter name : value}}
364429
# port_queue_list_map -> {port_index: [sorted queue list]}
365430
port_queues_map = {}
366431
queue_stat_map = {}
@@ -424,7 +489,7 @@ class RedisOidTreeUpdater(MIBUpdater):
424489
def __init__(self, prefix_str):
425490
super().__init__()
426491

427-
self.db_conn = Namespace.init_namespace_dbs()
492+
self.db_conn = Namespace.init_namespace_dbs()
428493
if prefix_str.startswith('.'):
429494
prefix_str = prefix_str[1:]
430495
self.prefix_str = prefix_str
@@ -537,7 +602,7 @@ def dbs_get_all(dbs, db_name, _hash, *args, **kwargs):
537602
db get_all function executed on global and all namespace DBs.
538603
"""
539604
result = {}
540-
# If there are multiple namespaces, _hash might not be
605+
# If there are multiple namespaces, _hash might not be
541606
# present in all namespace, ignore if not present in a
542607
# specfic namespace.
543608
if len(dbs) > 1:

src/sonic_ax_impl/mibs/ietf/rfc1213.py

+86-10
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ class DbTables(int, Enum):
5050
class IfTypes(int, Enum):
5151
""" IANA ifTypes """
5252
ethernetCsmacd = 6
53-
ieee8023adLag = 161
53+
l3ipvlan = 136
54+
ieee8023adLag = 161
5455

5556
class ArpUpdater(MIBUpdater):
5657
def __init__(self):
@@ -192,8 +193,13 @@ def __init__(self):
192193
self.lag_name_if_name_map = {}
193194
self.if_name_lag_name_map = {}
194195
self.oid_lag_name_map = {}
196+
self.lag_sai_map = {}
195197
self.mgmt_oid_name_map = {}
196198
self.mgmt_alias_map = {}
199+
self.vlan_oid_name_map = {}
200+
self.vlan_name_map = {}
201+
self.rif_port_map = {}
202+
self.port_rif_map = {}
197203

198204
# cache of interface counters
199205
self.if_counters = {}
@@ -202,6 +208,8 @@ def __init__(self):
202208
self.if_alias_map = {}
203209
self.if_id_map = {}
204210
self.oid_name_map = {}
211+
self.rif_counters = {}
212+
205213
self.namespace_db_map = Namespace.get_namespace_db_map(self.db_conn)
206214

207215
def reinit_data(self):
@@ -220,26 +228,56 @@ def reinit_data(self):
220228
self.mgmt_oid_name_map, \
221229
self.mgmt_alias_map = mibs.init_mgmt_interface_tables(self.db_conn[0])
222230

231+
self.vlan_name_map, \
232+
self.vlan_oid_sai_map, \
233+
self.vlan_oid_name_map = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_vlan_tables, self.db_conn)
234+
235+
self.rif_port_map, \
236+
self.port_rif_map = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_rif_tables, self.db_conn)
237+
223238
def update_data(self):
224239
"""
225240
Update redis (caches config)
226241
Pulls the table references for each interface.
227242
"""
228-
for sai_id_key in self.if_id_map:
229-
namespace, sai_id = mibs.split_sai_id_key(sai_id_key)
230-
if_idx = mibs.get_index_from_str(self.if_id_map[sai_id_key])
231-
self.if_counters[if_idx] = self.namespace_db_map[namespace].get_all(mibs.COUNTERS_DB, \
232-
mibs.counter_table(sai_id), blocking=True)
243+
244+
self.update_if_counters()
245+
self.update_rif_counters()
246+
247+
self.aggregate_counters()
233248

234249
self.lag_name_if_name_map, \
235250
self.if_name_lag_name_map, \
236-
self.oid_lag_name_map, _ = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_lag_tables, self.db_conn)
251+
self.oid_lag_name_map, \
252+
self.lag_sai_map = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_lag_tables, self.db_conn)
237253

238254
self.if_range = sorted(list(self.oid_name_map.keys()) +
239255
list(self.oid_lag_name_map.keys()) +
240-
list(self.mgmt_oid_name_map.keys()))
256+
list(self.mgmt_oid_name_map.keys()) +
257+
list(self.vlan_oid_name_map.keys()))
241258
self.if_range = [(i,) for i in self.if_range]
242259

260+
def update_if_counters(self):
261+
for sai_id_key in self.if_id_map:
262+
namespace, sai_id = mibs.split_sai_id_key(sai_id_key)
263+
if_idx = mibs.get_index_from_str(self.if_id_map[sai_id_key])
264+
counters_db_data = self.namespace_db_map[namespace].get_all(mibs.COUNTERS_DB,
265+
mibs.counter_table(sai_id),
266+
blocking=True)
267+
self.if_counters[if_idx] = {
268+
counter: int(value) for counter, value in counters_db_data.items()
269+
}
270+
271+
def update_rif_counters(self):
272+
rif_sai_ids = list(self.rif_port_map) + list(self.vlan_name_map)
273+
for sai_id in rif_sai_ids:
274+
counters_db_data = Namespace.dbs_get_all(self.db_conn, mibs.COUNTERS_DB,
275+
mibs.counter_table(mibs.split_sai_id_key(sai_id)[1]),
276+
blocking=False)
277+
self.rif_counters[sai_id] = {
278+
counter: int(value) for counter, value in counters_db_data.items()
279+
}
280+
243281
def get_next(self, sub_id):
244282
"""
245283
:param sub_id: The 1-based sub-identifier query.
@@ -281,6 +319,8 @@ def interface_description(self, sub_id):
281319
return self.oid_lag_name_map[oid]
282320
elif oid in self.mgmt_oid_name_map:
283321
return self.mgmt_alias_map[self.mgmt_oid_name_map[oid]]
322+
elif oid in self.vlan_oid_name_map:
323+
return self.vlan_oid_name_map[oid]
284324

285325
return self.if_alias_map[self.oid_name_map[oid]]
286326

@@ -296,13 +336,38 @@ def _get_counter(self, oid, table_name):
296336
try:
297337
counter_value = self.if_counters[oid][_table_name]
298338
# truncate to 32-bit counter (database implements 64-bit counters)
299-
counter_value = int(counter_value) & 0x00000000ffffffff
339+
counter_value = counter_value & 0x00000000ffffffff
300340
# done!
301341
return counter_value
302342
except KeyError as e:
303343
mibs.logger.warning("SyncD 'COUNTERS_DB' missing attribute '{}'.".format(e))
304344
return None
305345

346+
def aggregate_counters(self):
347+
"""
348+
For ports with l3 router interfaces l3 drops may be counted separately (RIF counters)
349+
add l3 drops to l2 drop counters cache according to mapping
350+
351+
For l3vlan map l3 counters to l2 counters
352+
"""
353+
for rif_sai_id, port_sai_id in self.rif_port_map.items():
354+
if port_sai_id in self.if_id_map:
355+
port_idx = mibs.get_index_from_str(self.if_id_map[port_sai_id])
356+
for port_counter_name, rif_counter_name in mibs.RIF_DROPS_AGGR_MAP.items():
357+
self.if_counters[port_idx][port_counter_name] = \
358+
self.if_counters[port_idx][port_counter_name] + \
359+
self.rif_counters[rif_sai_id][rif_counter_name]
360+
361+
for vlan_sai_id, vlan_name in self.vlan_name_map.items():
362+
for port_counter_name, rif_counter_name in mibs.RIF_COUNTERS_AGGR_MAP.items():
363+
vlan_idx = mibs.get_index_from_str(vlan_name)
364+
vlan_rif_counters = self.rif_counters[vlan_sai_id]
365+
if rif_counter_name in vlan_rif_counters:
366+
self.if_counters.setdefault(vlan_idx, {})
367+
self.if_counters[vlan_idx][port_counter_name] = \
368+
vlan_rif_counters[rif_counter_name]
369+
370+
306371
def get_counter(self, sub_id, table_name):
307372
"""
308373
:param sub_id: The 1-based sub-identifier query.
@@ -322,7 +387,13 @@ def get_counter(self, sub_id, table_name):
322387
counter_value = 0
323388
for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[oid]]:
324389
counter_value += self._get_counter(mibs.get_index_from_str(lag_member), table_name)
325-
390+
sai_lag_id = self.lag_sai_map[self.oid_lag_name_map[oid]]
391+
sai_lag_rif_id = self.port_rif_map[sai_lag_id]
392+
if sai_lag_rif_id in self.rif_port_map:
393+
table_name = getattr(table_name, 'name', table_name)
394+
if table_name in mibs.RIF_DROPS_AGGR_MAP:
395+
rif_table_name = mibs.RIF_DROPS_AGGR_MAP[table_name]
396+
counter_value += self.rif_counters[sai_lag_rif_id].get(rif_table_name, 0)
326397
# truncate to 32-bit counter
327398
return counter_value & 0x00000000ffffffff
328399
else:
@@ -352,6 +423,8 @@ def _get_if_entry(self, sub_id):
352423
elif oid in self.mgmt_oid_name_map:
353424
if_table = mibs.mgmt_if_entry_table(self.mgmt_oid_name_map[oid])
354425
db = mibs.CONFIG_DB
426+
elif oid in self.vlan_oid_name_map:
427+
if_table = mibs.vlan_entry_table(self.vlan_oid_name_map[oid])
355428
elif oid in self.oid_name_map:
356429
if_table = mibs.if_entry_table(self.oid_name_map[oid])
357430
else:
@@ -456,6 +529,7 @@ def get_if_type(self, sub_id):
456529
457530
ethernetCsmacd(6), -- for all ethernet-like interfaces,
458531
-- regardless of speed, as per RFC3635
532+
l3ipvlan(136) -- Layer 3 Virtual LAN using IP
459533
ieee8023adLag(161) -- IEEE 802.3ad Link Aggregate
460534
"""
461535
oid = self.get_oid(sub_id)
@@ -464,6 +538,8 @@ def get_if_type(self, sub_id):
464538

465539
if oid in self.oid_lag_name_map:
466540
return IfTypes.ieee8023adLag
541+
elif oid in self.vlan_oid_name_map:
542+
return IfTypes.l3ipvlan
467543
else:
468544
return IfTypes.ethernetCsmacd
469545

src/sonic_ax_impl/mibs/vendor/cisco/ciscoPfcExtMIB.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def _get_counter(self, oid, counter_name):
9494
_counter_name = getattr(counter_name, 'name', counter_name)
9595

9696
try:
97-
counter_value = self.if_counters[oid][_counter_name]
97+
counter_value = self.if_counters[oid][_counter_name]
9898
counter_value = int(counter_value) & 0xffffffffffffffff
9999
# done!
100100
return counter_value

tests/mock_tables/asic0/asic_db.json

+7
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,12 @@
2323
"SAI_BRIDGE_PORT_ATTR_TYPE": "SAI_BRIDGE_PORT_TYPE_PORT",
2424
"SAI_BRIDGE_PORT_ATTR_PORT_ID": "oid:0x1000000000005",
2525
"SAI_BRIDGE_PORT_ATTR_ADMIN_STATE": "true"
26+
},
27+
"ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x6000000000006": {
28+
"SAI_ROUTER_INTERFACE_ATTR_TYPE": "SAI_ROUTER_INTERFACE_TYPE_PORT",
29+
"SAI_ROUTER_INTERFACE_ATTR_PORT_ID": "oid:0x1000000000007"
30+
},
31+
"ASIC_STATE:SAI_OBJECT_TYPE_LAG:oid:0x1000000000007": {
32+
"NULL": "NULL"
2633
}
2734
}

0 commit comments

Comments
 (0)