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