@@ -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 ):
@@ -196,8 +197,13 @@ def __init__(self):
196
197
self .lag_name_if_name_map = {}
197
198
self .if_name_lag_name_map = {}
198
199
self .oid_lag_name_map = {}
200
+ self .lag_sai_map = {}
199
201
self .mgmt_oid_name_map = {}
200
202
self .mgmt_alias_map = {}
203
+ self .vlan_oid_name_map = {}
204
+ self .vlan_name_map = {}
205
+ self .rif_port_map = {}
206
+ self .port_rif_map = {}
201
207
202
208
# cache of interface counters
203
209
self .if_counters = {}
@@ -206,6 +212,8 @@ def __init__(self):
206
212
self .if_alias_map = {}
207
213
self .if_id_map = {}
208
214
self .oid_name_map = {}
215
+ self .rif_counters = {}
216
+
209
217
self .namespace_db_map = Namespace .get_namespace_db_map (self .db_conn )
210
218
211
219
def reinit_data (self ):
@@ -228,6 +236,13 @@ def reinit_data(self):
228
236
self .if_name_lag_name_map , \
229
237
self .oid_lag_name_map , _ = Namespace .get_sync_d_from_all_namespace (mibs .init_sync_d_lag_tables , self .db_conn )
230
238
239
+ self .vlan_name_map , \
240
+ self .vlan_oid_sai_map , \
241
+ self .vlan_oid_name_map = Namespace .get_sync_d_from_all_namespace (mibs .init_sync_d_vlan_tables , self .db_conn )
242
+
243
+ self .rif_port_map , \
244
+ self .port_rif_map = Namespace .get_sync_d_from_all_namespace (mibs .init_sync_d_rif_tables , self .db_conn )
245
+
231
246
def update_data (self ):
232
247
"""
233
248
Update redis (caches config)
@@ -242,11 +257,43 @@ def update_data(self):
242
257
counter_table = {}
243
258
self .if_counters [if_idx ] = counter_table
244
259
260
+ self .update_if_counters ()
261
+ self .update_rif_counters ()
262
+
263
+ self .aggregate_counters ()
264
+
265
+ self .lag_name_if_name_map , \
266
+ self .if_name_lag_name_map , \
267
+ self .oid_lag_name_map , \
268
+ self .lag_sai_map , self .sai_lag_map = Namespace .get_sync_d_from_all_namespace (mibs .init_sync_d_lag_tables , self .db_conn )
269
+
245
270
self .if_range = sorted (list (self .oid_name_map .keys ()) +
246
271
list (self .oid_lag_name_map .keys ()) +
247
- list (self .mgmt_oid_name_map .keys ()))
272
+ list (self .mgmt_oid_name_map .keys ()) +
273
+ list (self .vlan_oid_name_map .keys ()))
248
274
self .if_range = [(i ,) for i in self .if_range ]
249
275
276
+ def update_if_counters (self ):
277
+ for sai_id_key in self .if_id_map :
278
+ namespace , sai_id = mibs .split_sai_id_key (sai_id_key )
279
+ if_idx = mibs .get_index_from_str (self .if_id_map [sai_id_key ])
280
+ counters_db_data = self .namespace_db_map [namespace ].get_all (mibs .COUNTERS_DB ,
281
+ mibs .counter_table (sai_id ),
282
+ blocking = True )
283
+ self .if_counters [if_idx ] = {
284
+ counter : int (value ) for counter , value in counters_db_data .items ()
285
+ }
286
+
287
+ def update_rif_counters (self ):
288
+ rif_sai_ids = list (self .rif_port_map ) + list (self .vlan_name_map )
289
+ for sai_id in rif_sai_ids :
290
+ counters_db_data = Namespace .dbs_get_all (self .db_conn , mibs .COUNTERS_DB ,
291
+ mibs .counter_table (mibs .split_sai_id_key (sai_id )[1 ]),
292
+ blocking = False )
293
+ self .rif_counters [sai_id ] = {
294
+ counter : int (value ) for counter , value in counters_db_data .items ()
295
+ }
296
+
250
297
def get_next (self , sub_id ):
251
298
"""
252
299
:param sub_id: The 1-based sub-identifier query.
@@ -288,6 +335,8 @@ def interface_description(self, sub_id):
288
335
return self .oid_lag_name_map [oid ]
289
336
elif oid in self .mgmt_oid_name_map :
290
337
return self .mgmt_alias_map [self .mgmt_oid_name_map [oid ]]
338
+ elif oid in self .vlan_oid_name_map :
339
+ return self .vlan_oid_name_map [oid ]
291
340
292
341
return self .if_alias_map [self .oid_name_map [oid ]]
293
342
@@ -298,18 +347,46 @@ def _get_counter(self, oid, table_name):
298
347
:return: the counter for the respective sub_id/table.
299
348
"""
300
349
# Enum.name or table_name = 'name_of_the_table'
350
+ # Example:
351
+ # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20>
352
+ # _table_name = 'SAI_PORT_STAT_IF_OUT_ERRORS'
301
353
_table_name = getattr (table_name , 'name' , table_name )
302
354
303
355
try :
304
356
counter_value = self .if_counters [oid ][_table_name ]
305
357
# truncate to 32-bit counter (database implements 64-bit counters)
306
- counter_value = int ( counter_value ) & 0x00000000ffffffff
358
+ counter_value = counter_value & 0x00000000ffffffff
307
359
# done!
308
360
return counter_value
309
361
except KeyError as e :
310
362
mibs .logger .warning ("SyncD 'COUNTERS_DB' missing attribute '{}'." .format (e ))
311
363
return None
312
364
365
+ def aggregate_counters (self ):
366
+ """
367
+ For ports with l3 router interfaces l3 drops may be counted separately (RIF counters)
368
+ add l3 drops to l2 drop counters cache according to mapping
369
+
370
+ For l3vlan map l3 counters to l2 counters
371
+ """
372
+ for rif_sai_id , port_sai_id in self .rif_port_map .items ():
373
+ if port_sai_id in self .if_id_map :
374
+ port_idx = mibs .get_index_from_str (self .if_id_map [port_sai_id ])
375
+ for port_counter_name , rif_counter_name in mibs .RIF_DROPS_AGGR_MAP .items ():
376
+ self .if_counters [port_idx ][port_counter_name ] = \
377
+ self .if_counters [port_idx ][port_counter_name ] + \
378
+ self .rif_counters [rif_sai_id ][rif_counter_name ]
379
+
380
+ for vlan_sai_id , vlan_name in self .vlan_name_map .items ():
381
+ for port_counter_name , rif_counter_name in mibs .RIF_COUNTERS_AGGR_MAP .items ():
382
+ vlan_idx = mibs .get_index_from_str (vlan_name )
383
+ vlan_rif_counters = self .rif_counters [vlan_sai_id ]
384
+ if rif_counter_name in vlan_rif_counters :
385
+ self .if_counters .setdefault (vlan_idx , {})
386
+ self .if_counters [vlan_idx ][port_counter_name ] = \
387
+ vlan_rif_counters [rif_counter_name ]
388
+
389
+
313
390
def get_counter (self , sub_id , table_name ):
314
391
"""
315
392
:param sub_id: The 1-based sub-identifier query.
@@ -327,9 +404,40 @@ def get_counter(self, sub_id, table_name):
327
404
return 0
328
405
elif oid in self .oid_lag_name_map :
329
406
counter_value = 0
407
+ # Sum the values of this counter for all ports in the LAG.
408
+ # Example:
409
+ # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20>
410
+ # oid = 1001
411
+ # self.oid_lag_name_map = {1001: 'PortChannel01', 1002: 'PortChannel02', 1003: 'PortChannel03'}
412
+ # self.oid_lag_name_map[oid] = 'PortChannel01'
413
+ # self.lag_name_if_name_map = {'PortChannel01': ['Ethernet112'], 'PortChannel02': ['Ethernet116'], 'PortChannel03': ['Ethernet120']}
414
+ # self.lag_name_if_name_map['PortChannel01'] = ['Ethernet112']
415
+ # mibs.get_index_from_str('Ethernet112') = 113 (because Ethernet N = N + 1)
416
+ # self._get_counter retrieves the counter per oid and table.
330
417
for lag_member in self .lag_name_if_name_map [self .oid_lag_name_map [oid ]]:
331
418
counter_value += self ._get_counter (mibs .get_index_from_str (lag_member ), table_name )
332
-
419
+ # Check if we need to add a router interface count.
420
+ # Example:
421
+ # self.lag_sai_map = {'PortChannel01': '2000000000006', 'PortChannel02': '2000000000005', 'PortChannel03': '2000000000004'}
422
+ # self.port_rif_map = {'2000000000006': '6000000000006', '2000000000005': '6000000000005', '2000000000004': '6000000000004'}
423
+ # self.rif_port_map = {'6000000000006': '2000000000006', '6000000000005': '2000000000005', '6000000000004': '2000000000004'}
424
+ # self.lag_sai_map['PortChannel01'] = '2000000000006'
425
+ # self.port_rif_map['2000000000006'] = '6000000000006'
426
+ sai_lag_id = self .lag_sai_map [self .oid_lag_name_map [oid ]]
427
+ sai_lag_rif_id = self .port_rif_map [sai_lag_id ]
428
+ if sai_lag_rif_id in self .rif_port_map :
429
+ # Extract the 'name' part of 'table_name'.
430
+ # Example:
431
+ # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20>
432
+ # _table_name = 'SAI_PORT_STAT_IF_OUT_ERRORS'
433
+ table_name = getattr (table_name , 'name' , table_name )
434
+ # Find rif counter table if applicable and add the count for this table.
435
+ # Example:
436
+ # 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'}
437
+ # self.rif_counters['6000000000006'] = {'SAI_ROUTER_INTERFACE_STAT_IN_PACKETS': 6, ... 'SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS': 6, ...}
438
+ if table_name in mibs .RIF_DROPS_AGGR_MAP :
439
+ rif_table_name = mibs .RIF_DROPS_AGGR_MAP [table_name ]
440
+ counter_value += self .rif_counters [sai_lag_rif_id ].get (rif_table_name , 0 )
333
441
# truncate to 32-bit counter
334
442
return counter_value & 0x00000000ffffffff
335
443
else :
@@ -359,6 +467,8 @@ def _get_if_entry(self, sub_id):
359
467
elif oid in self .mgmt_oid_name_map :
360
468
if_table = mibs .mgmt_if_entry_table (self .mgmt_oid_name_map [oid ])
361
469
db = mibs .CONFIG_DB
470
+ elif oid in self .vlan_oid_name_map :
471
+ if_table = mibs .vlan_entry_table (self .vlan_oid_name_map [oid ])
362
472
elif oid in self .oid_name_map :
363
473
if_table = mibs .if_entry_table (self .oid_name_map [oid ])
364
474
else :
@@ -463,6 +573,7 @@ def get_if_type(self, sub_id):
463
573
464
574
ethernetCsmacd(6), -- for all ethernet-like interfaces,
465
575
-- regardless of speed, as per RFC3635
576
+ l3ipvlan(136) -- Layer 3 Virtual LAN using IP
466
577
ieee8023adLag(161) -- IEEE 802.3ad Link Aggregate
467
578
"""
468
579
oid = self .get_oid (sub_id )
@@ -471,6 +582,8 @@ def get_if_type(self, sub_id):
471
582
472
583
if oid in self .oid_lag_name_map :
473
584
return IfTypes .ieee8023adLag
585
+ elif oid in self .vlan_oid_name_map :
586
+ return IfTypes .l3ipvlan
474
587
else :
475
588
return IfTypes .ethernetCsmacd
476
589
0 commit comments