44from bisect import bisect_right
55
66from sonic_ax_impl import mibs
7+ from sonic_ax_impl import logger
78from sonic_ax_impl .mibs import Namespace
89from ax_interface .mib import MIBMeta , ValueType , MIBUpdater , MIBEntry , SubtreeMIBEntry , OverlayAdpaterMIBEntry , OidMIBEntry
910from ax_interface .encodings import ObjectIdentifier
@@ -49,7 +50,8 @@ class DbTables(int, Enum):
4950class IfTypes (int , Enum ):
5051 """ IANA ifTypes """
5152 ethernetCsmacd = 6
52- ieee8023adLag = 161
53+ l3ipvlan = 136
54+ ieee8023adLag = 161
5355
5456class ArpUpdater (MIBUpdater ):
5557 def __init__ (self ):
@@ -157,8 +159,13 @@ def __init__(self):
157159 self .lag_name_if_name_map = {}
158160 self .if_name_lag_name_map = {}
159161 self .oid_lag_name_map = {}
162+ self .lag_sai_map = {}
160163 self .mgmt_oid_name_map = {}
161164 self .mgmt_alias_map = {}
165+ self .vlan_oid_name_map = {}
166+ self .vlan_name_map = {}
167+ self .rif_port_map = {}
168+ self .port_rif_map = {}
162169
163170 # cache of interface counters
164171 self .if_counters = {}
@@ -168,6 +175,7 @@ def __init__(self):
168175 self .if_id_map = {}
169176 self .oid_sai_map = {}
170177 self .oid_name_map = {}
178+ self .rif_counters = {}
171179
172180 def reinit_data (self ):
173181 """
@@ -186,6 +194,13 @@ def reinit_data(self):
186194 self .mgmt_oid_name_map , \
187195 self .mgmt_alias_map = mibs .init_mgmt_interface_tables (self .db_conn [0 ])
188196
197+ self .vlan_name_map , \
198+ self .vlan_oid_sai_map , \
199+ self .vlan_oid_name_map = Namespace .init_namespace_sync_d_vlan_tables (self .db_conn )
200+
201+ self .rif_port_map , \
202+ self .port_rif_map = Namespace .init_namespace_sync_d_rif_tables (self .db_conn )
203+
189204 def update_data (self ):
190205 """
191206 Update redis (caches config)
@@ -195,13 +210,24 @@ def update_data(self):
195210 {sai_id : Namespace .dbs_get_all (self .db_conn , mibs .COUNTERS_DB , mibs .counter_table (sai_id ), blocking = True )
196211 for sai_id in self .if_id_map }
197212
213+ rif_sai_ids = list (self .rif_port_map ) + list (self .vlan_name_map )
214+
215+ self .rif_counters = \
216+ {sai_id : Namespace .dbs_get_all (self .db_conn , mibs .COUNTERS_DB , mibs .counter_table (sai_id ), blocking = True )
217+ for sai_id in rif_sai_ids }
218+
219+ if self .rif_counters :
220+ self .aggregate_counters ()
221+
198222 self .lag_name_if_name_map , \
199223 self .if_name_lag_name_map , \
200- self .oid_lag_name_map = Namespace .init_namespace_sync_d_lag_tables (self .db_conn )
224+ self .oid_lag_name_map , \
225+ self .lag_sai_map = Namespace .init_namespace_sync_d_lag_tables (self .db_conn )
201226
202227 self .if_range = sorted (list (self .oid_sai_map .keys ()) +
203228 list (self .oid_lag_name_map .keys ()) +
204- list (self .mgmt_oid_name_map .keys ()))
229+ list (self .mgmt_oid_name_map .keys ()) +
230+ list (self .vlan_oid_name_map .keys ()))
205231 self .if_range = [(i ,) for i in self .if_range ]
206232
207233 def get_next (self , sub_id ):
@@ -245,6 +271,8 @@ def interface_description(self, sub_id):
245271 return self .oid_lag_name_map [oid ]
246272 elif oid in self .mgmt_oid_name_map :
247273 return self .mgmt_alias_map [self .mgmt_oid_name_map [oid ]]
274+ elif oid in self .vlan_oid_name_map :
275+ return self .vlan_oid_name_map [oid ]
248276
249277 return self .if_alias_map [self .oid_name_map [oid ]]
250278
@@ -254,7 +282,13 @@ def _get_counter(self, oid, table_name):
254282 :param table_name: the redis table (either IntEnum or string literal) to query.
255283 :return: the counter for the respective sub_id/table.
256284 """
257- sai_id = self .oid_sai_map [oid ]
285+ sai_id = ''
286+ if oid in self .oid_sai_map :
287+ sai_id = self .oid_sai_map [oid ]
288+ elif oid in self .vlan_oid_sai_map :
289+ sai_id = self .vlan_oid_sai_map [oid ]
290+ else :
291+ logger .warning ("Unexpected oid {}" .format (oid ))
258292 # Enum.name or table_name = 'name_of_the_table'
259293 _table_name = bytes (getattr (table_name , 'name' , table_name ), 'utf-8' )
260294
@@ -268,6 +302,29 @@ def _get_counter(self, oid, table_name):
268302 mibs .logger .warning ("SyncD 'COUNTERS_DB' missing attribute '{}'." .format (e ))
269303 return None
270304
305+ def aggregate_counters (self ):
306+ """
307+ For ports with l3 router interfaces l3 drops may be counted separately (RIF counters)
308+ add l3 drops to l2 drop counters cache according to mapping
309+
310+ For l3vlan map l3 counters to l2 counters
311+ """
312+ for rif_sai_id , port_sai_id in self .rif_port_map .items ():
313+ if port_sai_id in self .if_id_map :
314+ for port_counter_name , rif_counter_name in mibs .RIF_DROPS_AGGR_MAP .items ():
315+ self .if_counters [port_sai_id ][port_counter_name ] = \
316+ int (self .if_counters [port_sai_id ][port_counter_name ]) + \
317+ int (self .rif_counters [rif_sai_id ][rif_counter_name ])
318+
319+ for vlan_sai_id in self .vlan_name_map :
320+ for port_counter_name , rif_counter_name in mibs .RIF_COUNTERS_AGGR_MAP .items ():
321+ try :
322+ self .if_counters .setdefault (vlan_sai_id , {})
323+ self .if_counters [vlan_sai_id ][port_counter_name ] = \
324+ int (self .rif_counters [vlan_sai_id ][rif_counter_name ])
325+ except KeyError as e :
326+ logger .warning ("Not able to aggregate counters for {}: {}\n {}" .format (vlan_sai_id , rif_counter_name , e ))
327+
271328 def get_counter (self , sub_id , table_name ):
272329 """
273330 :param sub_id: The 1-based sub-identifier query.
@@ -287,7 +344,13 @@ def get_counter(self, sub_id, table_name):
287344 counter_value = 0
288345 for lag_member in self .lag_name_if_name_map [self .oid_lag_name_map [oid ]]:
289346 counter_value += self ._get_counter (mibs .get_index (lag_member ), table_name )
290-
347+ sai_lag_id = self .lag_sai_map [self .oid_lag_name_map [oid ]]
348+ sai_lag_rif_id = self .port_rif_map [sai_lag_id ]
349+ if sai_lag_rif_id in self .rif_port_map :
350+ table_name = bytes (getattr (table_name , 'name' , table_name ), 'utf-8' )
351+ if table_name in mibs .RIF_DROPS_AGGR_MAP :
352+ rif_table_name = mibs .RIF_DROPS_AGGR_MAP [table_name ]
353+ counter_value += int (self .rif_counters [sai_lag_rif_id ][rif_table_name ])
291354 # truncate to 32-bit counter
292355 return counter_value & 0x00000000ffffffff
293356 else :
@@ -317,6 +380,8 @@ def _get_if_entry(self, sub_id):
317380 elif oid in self .mgmt_oid_name_map :
318381 if_table = mibs .mgmt_if_entry_table (self .mgmt_oid_name_map [oid ])
319382 db = mibs .CONFIG_DB
383+ elif oid in self .vlan_oid_name_map :
384+ if_table = mibs .vlan_entry_table (self .vlan_oid_name_map [oid ])
320385 elif oid in self .oid_name_map :
321386 if_table = mibs .if_entry_table (self .oid_name_map [oid ])
322387 else :
@@ -421,6 +486,7 @@ def get_if_type(self, sub_id):
421486
422487 ethernetCsmacd(6), -- for all ethernet-like interfaces,
423488 -- regardless of speed, as per RFC3635
489+ l3ipvlan(136) -- Layer 3 Virtual LAN using IP
424490 ieee8023adLag(161) -- IEEE 802.3ad Link Aggregate
425491 """
426492 oid = self .get_oid (sub_id )
@@ -429,6 +495,8 @@ def get_if_type(self, sub_id):
429495
430496 if oid in self .oid_lag_name_map :
431497 return IfTypes .ieee8023adLag
498+ elif oid in self .vlan_oid_name_map :
499+ return IfTypes .l3ipvlan
432500 else :
433501 return IfTypes .ethernetCsmacd
434502
0 commit comments