@@ -50,7 +50,8 @@ class DbTables(int, Enum):
50
50
class IfTypes (int , Enum ):
51
51
""" IANA ifTypes """
52
52
ethernetCsmacd = 6
53
- ieee8023adLag = 161
53
+ l3ipvlan = 136
54
+ ieee8023adLag = 161
54
55
55
56
class ArpUpdater (MIBUpdater ):
56
57
def __init__ (self ):
@@ -192,8 +193,13 @@ def __init__(self):
192
193
self .lag_name_if_name_map = {}
193
194
self .if_name_lag_name_map = {}
194
195
self .oid_lag_name_map = {}
196
+ self .lag_sai_map = {}
195
197
self .mgmt_oid_name_map = {}
196
198
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 = {}
197
203
198
204
# cache of interface counters
199
205
self .if_counters = {}
@@ -202,6 +208,8 @@ def __init__(self):
202
208
self .if_alias_map = {}
203
209
self .if_id_map = {}
204
210
self .oid_name_map = {}
211
+ self .rif_counters = {}
212
+
205
213
self .namespace_db_map = Namespace .get_namespace_db_map (self .db_conn )
206
214
207
215
def reinit_data (self ):
@@ -220,26 +228,56 @@ def reinit_data(self):
220
228
self .mgmt_oid_name_map , \
221
229
self .mgmt_alias_map = mibs .init_mgmt_interface_tables (self .db_conn [0 ])
222
230
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
+
223
238
def update_data (self ):
224
239
"""
225
240
Update redis (caches config)
226
241
Pulls the table references for each interface.
227
242
"""
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 ( )
233
248
234
249
self .lag_name_if_name_map , \
235
250
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 , self .sai_lag_map = Namespace .get_sync_d_from_all_namespace (mibs .init_sync_d_lag_tables , self .db_conn )
237
253
238
254
self .if_range = sorted (list (self .oid_name_map .keys ()) +
239
255
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 ()))
241
258
self .if_range = [(i ,) for i in self .if_range ]
242
259
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
+
243
281
def get_next (self , sub_id ):
244
282
"""
245
283
:param sub_id: The 1-based sub-identifier query.
@@ -281,6 +319,8 @@ def interface_description(self, sub_id):
281
319
return self .oid_lag_name_map [oid ]
282
320
elif oid in self .mgmt_oid_name_map :
283
321
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 ]
284
324
285
325
return self .if_alias_map [self .oid_name_map [oid ]]
286
326
@@ -291,18 +331,46 @@ def _get_counter(self, oid, table_name):
291
331
:return: the counter for the respective sub_id/table.
292
332
"""
293
333
# Enum.name or table_name = 'name_of_the_table'
334
+ # Example:
335
+ # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20>
336
+ # _table_name = 'SAI_PORT_STAT_IF_OUT_ERRORS'
294
337
_table_name = getattr (table_name , 'name' , table_name )
295
338
296
339
try :
297
340
counter_value = self .if_counters [oid ][_table_name ]
298
341
# truncate to 32-bit counter (database implements 64-bit counters)
299
- counter_value = int ( counter_value ) & 0x00000000ffffffff
342
+ counter_value = counter_value & 0x00000000ffffffff
300
343
# done!
301
344
return counter_value
302
345
except KeyError as e :
303
346
mibs .logger .warning ("SyncD 'COUNTERS_DB' missing attribute '{}'." .format (e ))
304
347
return None
305
348
349
+ def aggregate_counters (self ):
350
+ """
351
+ For ports with l3 router interfaces l3 drops may be counted separately (RIF counters)
352
+ add l3 drops to l2 drop counters cache according to mapping
353
+
354
+ For l3vlan map l3 counters to l2 counters
355
+ """
356
+ for rif_sai_id , port_sai_id in self .rif_port_map .items ():
357
+ if port_sai_id in self .if_id_map :
358
+ port_idx = mibs .get_index_from_str (self .if_id_map [port_sai_id ])
359
+ for port_counter_name , rif_counter_name in mibs .RIF_DROPS_AGGR_MAP .items ():
360
+ self .if_counters [port_idx ][port_counter_name ] = \
361
+ self .if_counters [port_idx ][port_counter_name ] + \
362
+ self .rif_counters [rif_sai_id ][rif_counter_name ]
363
+
364
+ for vlan_sai_id , vlan_name in self .vlan_name_map .items ():
365
+ for port_counter_name , rif_counter_name in mibs .RIF_COUNTERS_AGGR_MAP .items ():
366
+ vlan_idx = mibs .get_index_from_str (vlan_name )
367
+ vlan_rif_counters = self .rif_counters [vlan_sai_id ]
368
+ if rif_counter_name in vlan_rif_counters :
369
+ self .if_counters .setdefault (vlan_idx , {})
370
+ self .if_counters [vlan_idx ][port_counter_name ] = \
371
+ vlan_rif_counters [rif_counter_name ]
372
+
373
+
306
374
def get_counter (self , sub_id , table_name ):
307
375
"""
308
376
:param sub_id: The 1-based sub-identifier query.
@@ -320,9 +388,40 @@ def get_counter(self, sub_id, table_name):
320
388
return 0
321
389
elif oid in self .oid_lag_name_map :
322
390
counter_value = 0
391
+ # Sum the values of this counter for all ports in the LAG.
392
+ # Example:
393
+ # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20>
394
+ # oid = 1001
395
+ # self.oid_lag_name_map = {1001: 'PortChannel01', 1002: 'PortChannel02', 1003: 'PortChannel03'}
396
+ # self.oid_lag_name_map[oid] = 'PortChannel01'
397
+ # self.lag_name_if_name_map = {'PortChannel01': ['Ethernet112'], 'PortChannel02': ['Ethernet116'], 'PortChannel03': ['Ethernet120']}
398
+ # self.lag_name_if_name_map['PortChannel01'] = ['Ethernet112']
399
+ # mibs.get_index_from_str('Ethernet112') = 113 (because Ethernet N = N + 1)
400
+ # self._get_counter retrieves the counter per oid and table.
323
401
for lag_member in self .lag_name_if_name_map [self .oid_lag_name_map [oid ]]:
324
402
counter_value += self ._get_counter (mibs .get_index_from_str (lag_member ), table_name )
325
-
403
+ # Check if we need to add a router interface count.
404
+ # Example:
405
+ # self.lag_sai_map = {'PortChannel01': '2000000000006', 'PortChannel02': '2000000000005', 'PortChannel03': '2000000000004'}
406
+ # self.port_rif_map = {'2000000000006': '6000000000006', '2000000000005': '6000000000005', '2000000000004': '6000000000004'}
407
+ # self.rif_port_map = {'6000000000006': '2000000000006', '6000000000005': '2000000000005', '6000000000004': '2000000000004'}
408
+ # self.lag_sai_map['PortChannel01'] = '2000000000006'
409
+ # self.port_rif_map['2000000000006'] = '6000000000006'
410
+ sai_lag_id = self .lag_sai_map [self .oid_lag_name_map [oid ]]
411
+ sai_lag_rif_id = self .port_rif_map [sai_lag_id ]
412
+ if sai_lag_rif_id in self .rif_port_map :
413
+ # Extract the 'name' part of 'table_name'.
414
+ # Example:
415
+ # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20>
416
+ # _table_name = 'SAI_PORT_STAT_IF_OUT_ERRORS'
417
+ table_name = getattr (table_name , 'name' , table_name )
418
+ # Find rif counter table if applicable and add the count for this table.
419
+ # Example:
420
+ # mibs.RIF_DROPS_AGGR_MAP = {'SAI_PORT_STAT_IF_IN_ERRORS': 'SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS', 'SAI_PORT_STAT_IF_OUT_ERRORS': 'SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS'}
421
+ # self.rif_counters['6000000000006'] = {'SAI_ROUTER_INTERFACE_STAT_IN_PACKETS': 6, ... 'SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS': 6, ...}
422
+ if table_name in mibs .RIF_DROPS_AGGR_MAP :
423
+ rif_table_name = mibs .RIF_DROPS_AGGR_MAP [table_name ]
424
+ counter_value += self .rif_counters [sai_lag_rif_id ].get (rif_table_name , 0 )
326
425
# truncate to 32-bit counter
327
426
return counter_value & 0x00000000ffffffff
328
427
else :
@@ -352,6 +451,8 @@ def _get_if_entry(self, sub_id):
352
451
elif oid in self .mgmt_oid_name_map :
353
452
if_table = mibs .mgmt_if_entry_table (self .mgmt_oid_name_map [oid ])
354
453
db = mibs .CONFIG_DB
454
+ elif oid in self .vlan_oid_name_map :
455
+ if_table = mibs .vlan_entry_table (self .vlan_oid_name_map [oid ])
355
456
elif oid in self .oid_name_map :
356
457
if_table = mibs .if_entry_table (self .oid_name_map [oid ])
357
458
else :
@@ -456,6 +557,7 @@ def get_if_type(self, sub_id):
456
557
457
558
ethernetCsmacd(6), -- for all ethernet-like interfaces,
458
559
-- regardless of speed, as per RFC3635
560
+ l3ipvlan(136) -- Layer 3 Virtual LAN using IP
459
561
ieee8023adLag(161) -- IEEE 802.3ad Link Aggregate
460
562
"""
461
563
oid = self .get_oid (sub_id )
@@ -464,6 +566,8 @@ def get_if_type(self, sub_id):
464
566
465
567
if oid in self .oid_lag_name_map :
466
568
return IfTypes .ieee8023adLag
569
+ elif oid in self .vlan_oid_name_map :
570
+ return IfTypes .l3ipvlan
467
571
else :
468
572
return IfTypes .ethernetCsmacd
469
573
0 commit comments