def aggregate_counters(self): """ For ports with l3 router interfaces l3 drops may be counted separately (RIF counters) add l3 drops to l2 drop counters cache according to mapping For l3vlan map l3 counters to l2 counters """ for rif_sai_id, port_sai_id in self.rif_port_map.items(): if port_sai_id in self.if_id_map: port_idx = mibs.get_index_from_str(self.if_id_map[port_sai_id]) for port_counter_name, rif_counter_name in mibs.RIF_DROPS_AGGR_MAP.items( ): self.if_counters[port_idx][port_counter_name] = \ self.if_counters[port_idx][port_counter_name] + \ self.rif_counters[rif_sai_id][rif_counter_name] for vlan_sai_id, vlan_name in self.vlan_name_map.items(): for port_counter_name, rif_counter_name in mibs.RIF_COUNTERS_AGGR_MAP.items( ): vlan_idx = mibs.get_index_from_str(vlan_name) vlan_rif_counters = self.rif_counters[vlan_sai_id] if rif_counter_name in vlan_rif_counters: self.if_counters.setdefault(vlan_idx, {}) self.if_counters[vlan_idx][port_counter_name] = \ vlan_rif_counters[rif_counter_name]
def update_data(self): """ Update redis (caches config) Pulls the table references for each interface. """ self.vlanmac_ifindex_map = {} self.vlanmac_ifindex_list = [] fdb_strings = Namespace.dbs_keys( self.db_conn, mibs.ASIC_DB, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY:*") if not fdb_strings: return for s in fdb_strings: fdb_str = s try: fdb = json.loads(fdb_str.split(":", maxsplit=2)[-1]) except ValueError as e: # includes simplejson.decoder.JSONDecodeError mibs.logger.error( "SyncD 'ASIC_DB' includes invalid FDB_ENTRY '{}': {}.". format(fdb_str, e)) continue ent = Namespace.dbs_get_all(self.db_conn, mibs.ASIC_DB, s, blocking=True) # Example output: oid:0x3a000000000608 bridge_port_id = ent["SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID"][6:] if bridge_port_id not in self.if_bpid_map: continue port_id = self.if_bpid_map[bridge_port_id] if port_id in self.if_id_map: port_name = self.if_id_map[port_id] port_index = mibs.get_index_from_str(port_name) elif port_id in self.sai_lag_map: port_name = self.sai_lag_map[port_id] port_index = mibs.get_index_from_str(port_name) else: continue vlanmac = self.fdb_vlanmac(fdb) if not vlanmac: mibs.logger.error( "SyncD 'ASIC_DB' includes invalid FDB_ENTRY '{}': failed in fdb_vlanmac()." .format(fdb_str)) continue self.vlanmac_ifindex_map[vlanmac] = port_index self.vlanmac_ifindex_list.append(vlanmac) self.vlanmac_ifindex_list.sort()
def get_counter(self, sub_id, table_name): """ :param sub_id: The 1-based sub-identifier query. :param table_name: the redis table (either IntEnum or string literal) to query. :return: the counter for the respective sub_id/table. """ oid = self.get_oid(sub_id) if not oid: return if oid in self.mgmt_oid_name_map: # TODO: mgmt counters not available through SNMP right now # COUNTERS DB does not have support for generic linux (mgmt) interface counters return 0 elif oid in self.oid_lag_name_map: counter_value = 0 for lag_member in self.lag_name_if_name_map[ self.oid_lag_name_map[oid]]: counter_value += self._get_counter( mibs.get_index_from_str(lag_member), table_name) # truncate to 32-bit counter return counter_value & 0x00000000ffffffff else: return self._get_counter(oid, table_name)
def indications_per_priority(self, sub_id): """ :param sub_id: The 0-based sub-identifier query. :return: the counter for the respective sub_id/table. """ port_oid = '' queue_index = '' try: if not sub_id: return None port_oid = self.get_oid((sub_id[0],)) queue_index = self.queue_index(sub_id) if port_oid is None or queue_index is None: return None except IndexError: mibs.logger.warning("indicationsPerPriority: incorrect sub_id = {}".format(str(sub_id))) return None counter_name = 'SAI_PORT_STAT_PFC_' + str(queue_index) + '_RX_PKTS' if port_oid in self.oid_lag_name_map: counter_value = 0 for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[port_oid]]: counter_value += self._get_counter(mibs.get_index_from_str(lag_member), counter_name) return counter_value else: return self._get_counter(port_oid, counter_name)
def _get_counter(self, oid, table_name, mask): """ :param oid: The 1-based sub-identifier query. :param table_name: the redis table (either IntEnum or string literal) to query. :param mask: mask to apply to counter :return: the counter for the respective sub_id/table. """ if oid in self.mgmt_oid_name_map: # TODO: mgmt counters not available through SNMP right now # COUNTERS DB does not have support for generic linux (mgmt) interface counters return 0 if oid in self.oid_lag_name_map: counter_value = 0 for lag_member in self.lag_name_if_name_map[ self.oid_lag_name_map[oid]]: counter_value += self._get_counter( mibs.get_index_from_str(lag_member), table_name, mask) return counter_value & mask # Enum.name or table_name = 'name_of_the_table' _table_name = getattr(table_name, 'name', table_name) try: counter_value = self.if_counters[oid][_table_name] # truncate to 32-bit counter (database implements 64-bit counters) counter_value = int(counter_value) & mask # done! return counter_value except KeyError as e: mibs.logger.warning( "SyncD 'COUNTERS_DB' missing attribute '{}'.".format(e)) return None
def get_counter(self, sub_id, table_name): """ :param sub_id: The 1-based sub-identifier query. :param table_name: the redis table (either IntEnum or string literal) to query. :return: the counter for the respective sub_id/table. """ oid = self.get_oid(sub_id) if not oid: return if oid in self.mgmt_oid_name_map: # TODO: mgmt counters not available through SNMP right now # COUNTERS DB does not have support for generic linux (mgmt) interface counters return 0 elif oid in self.oid_lag_name_map: counter_value = 0 for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[oid]]: counter_value += self._get_counter(mibs.get_index_from_str(lag_member), table_name) sai_lag_id = self.lag_sai_map[self.oid_lag_name_map[oid]] sai_lag_rif_id = self.port_rif_map[sai_lag_id] if sai_lag_rif_id in self.rif_port_map: table_name = getattr(table_name, 'name', table_name) if table_name in mibs.RIF_DROPS_AGGR_MAP: rif_table_name = mibs.RIF_DROPS_AGGR_MAP[table_name] counter_value += int(self.rif_counters[sai_lag_rif_id].get(rif_table_name, 0)) # truncate to 32-bit counter return counter_value & 0x00000000ffffffff else: return self._get_counter(oid, table_name)
def get_counter(self, sub_id, table_name): """ :param sub_id: The 1-based sub-identifier query. :param table_name: the redis table (either IntEnum or string literal) to query. :return: the counter for the respective sub_id/table. """ oid = self.get_oid(sub_id) if not oid: return if oid in self.mgmt_oid_name_map: # TODO: mgmt counters not available through SNMP right now # COUNTERS DB does not have support for generic linux (mgmt) interface counters return 0 elif oid in self.oid_lag_name_map: counter_value = 0 # Sum the values of this counter for all ports in the LAG. # Example: # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20> # oid = 1001 # self.oid_lag_name_map = {1001: 'PortChannel01', 1002: 'PortChannel02', 1003: 'PortChannel03'} # self.oid_lag_name_map[oid] = 'PortChannel01' # self.lag_name_if_name_map = {'PortChannel01': ['Ethernet112'], 'PortChannel02': ['Ethernet116'], 'PortChannel03': ['Ethernet120']} # self.lag_name_if_name_map['PortChannel01'] = ['Ethernet112'] # mibs.get_index_from_str('Ethernet112') = 113 (because Ethernet N = N + 1) # self._get_counter retrieves the counter per oid and table. for lag_member in self.lag_name_if_name_map[ self.oid_lag_name_map[oid]]: counter_value += self._get_counter( mibs.get_index_from_str(lag_member), table_name) # Check if we need to add a router interface count. # Example: # self.lag_sai_map = {'PortChannel01': '2000000000006', 'PortChannel02': '2000000000005', 'PortChannel03': '2000000000004'} # self.port_rif_map = {'2000000000006': '6000000000006', '2000000000005': '6000000000005', '2000000000004': '6000000000004'} # self.rif_port_map = {'6000000000006': '2000000000006', '6000000000005': '2000000000005', '6000000000004': '2000000000004'} # self.lag_sai_map['PortChannel01'] = '2000000000006' # self.port_rif_map['2000000000006'] = '6000000000006' sai_lag_id = self.lag_sai_map[self.oid_lag_name_map[oid]] sai_lag_rif_id = self.port_rif_map[sai_lag_id] if sai_lag_rif_id in self.rif_port_map: # Extract the 'name' part of 'table_name'. # Example: # table_name = <DbTables.SAI_PORT_STAT_IF_OUT_ERRORS: 20> # _table_name = 'SAI_PORT_STAT_IF_OUT_ERRORS' table_name = getattr(table_name, 'name', table_name) # Find rif counter table if applicable and add the count for this table. # Example: # 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'} # self.rif_counters['6000000000006'] = {'SAI_ROUTER_INTERFACE_STAT_IN_PACKETS': 6, ... 'SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS': 6, ...} if table_name in mibs.RIF_DROPS_AGGR_MAP: rif_table_name = mibs.RIF_DROPS_AGGR_MAP[table_name] counter_value += self.rif_counters[sai_lag_rif_id].get( rif_table_name, 0) # truncate to 32-bit counter return counter_value & 0x00000000ffffffff else: return self._get_counter(oid, table_name)
def update_if_counters(self): for sai_id_key in self.if_id_map: namespace, sai_id = mibs.split_sai_id_key(sai_id_key) if_idx = mibs.get_index_from_str(self.if_id_map[sai_id_key]) counters_db_data = self.namespace_db_map[namespace].get_all( mibs.COUNTERS_DB, mibs.counter_table(sai_id), blocking=True) self.if_counters[if_idx] = { counter: int(value) for counter, value in counters_db_data.items() }
def update_data(self): """ Update redis (caches config) Pulls the table references for each interface. """ for sai_id_key in self.if_id_map: namespace, sai_id = mibs.split_sai_id_key(sai_id_key) if_idx = mibs.get_index_from_str(self.if_id_map[sai_id_key]) self.if_counters[if_idx] = self.namespace_db_map[namespace].get_all(mibs.COUNTERS_DB, \ mibs.counter_table(sai_id), blocking=True)
def _update_arp_info(self, dev, mac, ip): if_index = mibs.get_index_from_str(dev) if if_index is None: return mactuple = mac_decimals(mac) machex = ''.join(chr(b) for b in mactuple) # if MAC is all zero #if not any(mac): continue iptuple = ip2tuple_v4(ip) subid = (if_index, ) + iptuple self.arp_dest_map[subid] = machex self.arp_dest_list.append(subid)
def update_data(self): """ Update redis (caches config) Pulls the table references for each interface. """ for sai_id_key in self.if_id_map: namespace, sai_id = mibs.split_sai_id_key(sai_id_key) if_idx = mibs.get_index_from_str(self.if_id_map[sai_id_key]) self.if_counters[if_idx] = self.namespace_db_map[namespace].get_all(mibs.COUNTERS_DB, \ mibs.counter_table(sai_id), blocking=True) self.lag_name_if_name_map, \ self.if_name_lag_name_map, \ self.oid_lag_name_map, _ = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_lag_tables, self.db_conn) self.if_range = sorted(list(self.oid_name_map.keys()) + list(self.oid_lag_name_map.keys())) self.if_range = [(i,) for i in self.if_range]
def reinit_data(self): """ Subclass update interface information """ self.if_name_map, \ self.if_alias_map, \ self.if_id_map, \ self.oid_name_map = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_interface_tables, self.db_conn) for sai_id_key in self.if_id_map: namespace, sai_id = mibs.split_sai_id_key(sai_id_key) if_idx = mibs.get_index_from_str(self.if_id_map[sai_id_key]) self.port_index_namespace[if_idx] = namespace self.port_queues_map, self.queue_stat_map, self.port_queue_list_map = \ Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_queue_tables, self.db_conn) for db_conn in Namespace.get_non_host_dbs(self.db_conn): self.queue_type_map[db_conn.namespace] = db_conn.get_all(mibs.COUNTERS_DB, "COUNTERS_QUEUE_TYPE_MAP", blocking=False)
def cpfc_if_indications(self, sub_id): """ :param sub_id: The 1-based sub-identifier query. :return: the counter for the respective sub_id/table. """ oid = self.get_oid(sub_id) if oid is None: return None # BUG: need the sum of all the priorities counter_name = 'SAI_PORT_STAT_PFC_3_RX_PKTS' if oid in self.oid_lag_name_map: counter_value = 0 for lag_member in self.lag_name_if_name_map[self.oid_lag_name_map[oid]]: counter_value += self._get_counter(mibs.get_index_from_str(lag_member), counter_name) return counter_value else: return self._get_counter(oid, counter_name)
def update_data(self): self.arp_dest_map = {} self.arp_dest_list = [] for entry in python_arptable.get_arp_table(): dev = entry['Device'] mac = entry['HW address'] ip = entry['IP address'] if_index = mibs.get_index_from_str(dev) if if_index is None: continue mactuple = mac_decimals(mac) machex = ''.join(chr(b) for b in mactuple) # if MAC is all zero #if not any(mac): continue iptuple = ip2tuple_v4(ip) subid = (if_index, ) + iptuple self.arp_dest_map[subid] = machex self.arp_dest_list.append(subid) self.arp_dest_list.sort()
def update_data(self): self.arp_dest_map = {} self.arp_dest_list = [] for entry in python_arptable.get_arp_table(): dev = entry['Device'] mac = entry['HW address'] ip = entry['IP address'] if_index = mibs.get_index_from_str(dev) if if_index is None: continue mactuple = mac_decimals(mac) machex = ''.join(chr(b) for b in mactuple) # if MAC is all zero #if not any(mac): continue iptuple = ip2tuple_v4(ip) subid = (if_index,) + iptuple self.arp_dest_map[subid] = machex self.arp_dest_list.append(subid) self.arp_dest_list.sort()
def update_if_counters(self): for sai_id_key in self.if_id_map: namespace, sai_id = mibs.split_sai_id_key(sai_id_key) if_idx = mibs.get_index_from_str(self.if_id_map[sai_id_key]) self.if_counters[if_idx] = self.namespace_db_map[namespace].get_all(mibs.COUNTERS_DB, \ mibs.counter_table(sai_id), blocking=True)