-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add state to install criteo sonic-utilities
Note: currently these scripts are in criteo-sonic-utilities repository. They will be removed from it.
- Loading branch information
1 parent
7f00ae2
commit a15026f
Showing
5 changed files
with
802 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
#!/usr/bin/python | ||
""" | ||
This file is a modified version fdbshow in https://github.com/sonic-net/sonic-utilities | ||
It adds JSON output support. | ||
Script to show MAC/FDB entries learnt in Hardware / fixed from fdbshow in 201911 | ||
In long term, this will be replaced by the official sonic-utilies version (in python3). | ||
usage: criteo_fdbshow [-p PORT] [-v VLAN] | ||
optional arguments: | ||
-p, --port FDB learned on specific port: Ethernet0 | ||
-v, --vlan FDB learned on specific Vlan: 1000 | ||
Examples of the output: | ||
$ ./criteo_fdbshow -v 1234 | ||
[{"MacAddress": "00:53:00:01:02:03", "No.": 1, "Vlan": 1234, "Type": "Dynamic", "Port": "Ethernet0"}, 000] | ||
$ ./criteo_fdbshow -p Ethernet0 | ||
[{"MacAddress": "00:53:00:01:02:03", "No.": 1, "Vlan": 1234, "Type": "Dynamic", "Port": "Ethernet0"}, ...] | ||
""" | ||
import argparse | ||
import json | ||
import sys | ||
|
||
from natsort import natsorted | ||
from swsssdk import SonicV2Connector, port_util | ||
|
||
class FdbShow(object): | ||
|
||
HEADER = ['No.', 'Vlan', 'MacAddress', 'Port', 'Type'] | ||
FDB_COUNT = 0 | ||
|
||
def __init__(self): | ||
super(FdbShow,self).__init__() | ||
self.db = SonicV2Connector(host="127.0.0.1") | ||
self.if_name_map, \ | ||
self.if_oid_map = port_util.get_interface_oid_map(self.db) | ||
self.if_br_oid_map = port_util.get_bridge_port_map(self.db) | ||
self.fetch_fdb_data() | ||
return | ||
|
||
def fetch_fdb_data(self): | ||
""" | ||
Fetch FDB entries from ASIC DB. | ||
FDB entries are sorted on "VlanID" and stored as a list of tuples | ||
""" | ||
self.db.connect(self.db.ASIC_DB) | ||
self.bridge_mac_list = [] | ||
|
||
fdb_str = self.db.keys('ASIC_DB', "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY:*") | ||
if not fdb_str: | ||
return | ||
|
||
if self.if_br_oid_map is None: | ||
return | ||
|
||
oid_pfx = len("oid:0x") | ||
for s in fdb_str: | ||
fdb_entry = s.decode() | ||
fdb = json.loads(fdb_entry .split(":", 2)[-1]) | ||
if not fdb: | ||
continue | ||
|
||
ent = self.db.get_all('ASIC_DB', s, blocking=True) | ||
br_port_id = ent[b"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID"][oid_pfx:] | ||
ent_type = ent[b"SAI_FDB_ENTRY_ATTR_TYPE"] | ||
fdb_type = ['Dynamic','Static'][ent_type == "SAI_FDB_ENTRY_TYPE_STATIC"] | ||
if br_port_id not in self.if_br_oid_map: | ||
continue | ||
port_id = self.if_br_oid_map[br_port_id] | ||
if port_id in self.if_oid_map: | ||
if_name = self.if_oid_map[port_id] | ||
else: | ||
if_name = port_id | ||
if 'vlan' in fdb: | ||
vlan_id = fdb["vlan"] | ||
elif 'bvid' in fdb: | ||
try: | ||
vlan_id = port_util.get_vlan_id_from_bvid(self.db, fdb["bvid"]) | ||
if vlan_id is None: | ||
# the situation could be faced if the system has an FDB entries, | ||
# which are linked to default Vlan(caused by untagged trafic) | ||
continue | ||
except: | ||
vlan_id = fdb["bvid"] | ||
# print "Failed to get Vlan id for bvid {}\n".format(fdb["bvid"]) | ||
|
||
try: | ||
self.bridge_mac_list.append((int(vlan_id),) + (fdb["mac"],) + (if_name,) + (fdb_type,)) | ||
except ValueError: | ||
continue | ||
|
||
self.bridge_mac_list.sort(key = lambda x: x[0]) | ||
return | ||
|
||
|
||
def get_iter_index(self, key_value=0, pos=0): | ||
""" | ||
Get the starting index of matched entry | ||
""" | ||
if pos != 0: | ||
self.bridge_mac_list = natsorted(self.bridge_mac_list, key = lambda x: x[pos]) | ||
|
||
if key_value == 0: | ||
return 0 | ||
|
||
keys = [r[pos] for r in self.bridge_mac_list] | ||
return keys.index(key_value) | ||
|
||
|
||
def display(self, vlan, port): | ||
""" | ||
Display the FDB entries for specified vlan/port. | ||
@todo: - PortChannel support | ||
""" | ||
output = [] | ||
|
||
if vlan is not None: | ||
vlan = int(vlan) | ||
s_index = self.get_iter_index(vlan) | ||
self.bridge_mac_list = [fdb for fdb in self.bridge_mac_list[s_index:] | ||
if fdb[0] == vlan] | ||
if port is not None: | ||
s_index = self.get_iter_index(port, 2) | ||
self.bridge_mac_list = [fdb for fdb in self.bridge_mac_list[s_index:] | ||
if fdb[2] == port] | ||
|
||
for fdb in self.bridge_mac_list: | ||
self.FDB_COUNT += 1 | ||
entry = [self.FDB_COUNT, fdb[0], fdb[1], fdb[2], fdb[3]] | ||
zipped_entry = dict(zip(self.HEADER, entry)) | ||
output.append(zipped_entry) | ||
|
||
print json.dumps(output) | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='Display ASIC FDB entries', | ||
formatter_class=argparse.RawTextHelpFormatter) | ||
parser.add_argument('-p', '--port', type=str, help='FDB learned on specific port: Ethernet0', default=None) | ||
parser.add_argument('-v', '--vlan', type=str, help='FDB learned on specific Vlan: 1001', default=None) | ||
# the -j arg is not used, it is just here to ensure compatibility with the >= 202205 script version | ||
parser.add_argument('-j', '--json', action='store_true', help='JSON output') | ||
args = parser.parse_args() | ||
|
||
try: | ||
fdb = FdbShow() | ||
fdb.display(args.vlan, args.port) | ||
except Exception as e: | ||
print e.message | ||
sys.exit(1) | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
#!/usr/bin/python | ||
""" | ||
This file is derivated from scripts in https://github.com/sonic-net/sonic-utilities | ||
It merges several interface information into a single command. | ||
""" | ||
|
||
import json | ||
import swsssdk | ||
import sys | ||
import re | ||
from swsssdk import ConfigDBConnector | ||
|
||
|
||
PORT_STATUS_TABLE_PREFIX = "PORT_TABLE:" | ||
PORT_TRANSCEIVER_TABLE_PREFIX = "TRANSCEIVER_INFO|" | ||
PORT_TRANSCEIVER_DOM_TABLE_PREFIX = "TRANSCEIVER_DOM_SENSOR|" | ||
PORT_LANES_STATUS = "lanes" | ||
PORT_ALIAS = "alias" | ||
PORT_OPER_STATUS = "oper_status" | ||
PORT_ADMIN_STATUS = "admin_status" | ||
PORT_SPEED = "speed" | ||
PORT_MTU_STATUS = "mtu" | ||
PORT_DESCRIPTION = "description" | ||
PORT_OPTICS_TYPE = "type" | ||
PORT_OPTICS_MODEL = "modelname" | ||
PORT_OPTICS_MANUFACTURER = "manufacturename" | ||
PORT_OPTICS_SENSOR_RX = "rx{}power" | ||
PORT_OPTICS_SENSOR_TX = "tx{}power" | ||
PORT_PFC_ASYM_STATUS = "pfc_asym" | ||
|
||
|
||
def db_connect_configdb(): | ||
""" | ||
Connect to configdb | ||
""" | ||
config_db = ConfigDBConnector() | ||
if config_db is None: | ||
return None | ||
config_db.connect() | ||
return config_db | ||
|
||
|
||
def get_frontpanel_port_list(config_db): | ||
ports_dict = config_db.get_table('PORT') | ||
front_panel_ports_list = [] | ||
for port in ports_dict.iterkeys(): | ||
front_panel_ports_list.append(port) | ||
return front_panel_ports_list | ||
|
||
|
||
def db_connect_appl(): | ||
appl_db = swsssdk.SonicV2Connector(host='127.0.0.1') | ||
if appl_db is None: | ||
return None | ||
appl_db.connect(appl_db.APPL_DB) | ||
return appl_db | ||
|
||
|
||
def appl_db_keys_get(appl_db, front_panel_ports_list, intf_name): | ||
""" | ||
Get APPL_DB Keys | ||
""" | ||
if intf_name is None: | ||
appl_db_keys = appl_db.keys(appl_db.APPL_DB, "PORT_TABLE:*") | ||
elif intf_name in front_panel_ports_list: | ||
appl_db_keys = appl_db.keys(appl_db.APPL_DB, "PORT_TABLE:%s" % intf_name) | ||
else: | ||
return None | ||
return appl_db_keys | ||
|
||
|
||
def appl_db_port_status_get(appl_db, intf_name, status_type): | ||
""" | ||
Get the port status | ||
""" | ||
full_table_id = PORT_STATUS_TABLE_PREFIX + intf_name | ||
status = appl_db.get(appl_db.APPL_DB, full_table_id, status_type) | ||
if status is None: | ||
return "N/A" | ||
if status_type == PORT_SPEED and status != "N/A": | ||
status = '{}G'.format(status[:-3]) | ||
return status | ||
|
||
|
||
def db_connect_state(): | ||
""" | ||
Connect to REDIS STATE DB and get optics info | ||
""" | ||
state_db = swsssdk.SonicV2Connector(host='127.0.0.1') | ||
if state_db is None: | ||
return None | ||
state_db.connect(state_db.STATE_DB, False) # Make one attempt only | ||
return state_db | ||
|
||
|
||
def state_db_port_optics_get(state_db, intf_name, field): | ||
""" | ||
Get optic info for port | ||
""" | ||
full_table_id = PORT_TRANSCEIVER_TABLE_PREFIX + intf_name | ||
info = state_db.get(state_db.STATE_DB, full_table_id, field) | ||
if info is None: | ||
return "N/A" | ||
return info | ||
|
||
|
||
def state_db_port_optics_sensors_get(state_db, intf_name, field): | ||
""" | ||
Get optic sensor info for port | ||
""" | ||
full_table_id = PORT_TRANSCEIVER_DOM_TABLE_PREFIX + intf_name | ||
info = state_db.get(state_db.STATE_DB, full_table_id, field) | ||
if info is None: | ||
return "N/A" | ||
return info | ||
|
||
|
||
class IntfInformation(object): | ||
|
||
def display_intf_information(self, appl_db_keys, front_panel_ports_list): | ||
""" | ||
Get information related to an interface | ||
""" | ||
|
||
i = {} | ||
key = [] | ||
interfaces = {} | ||
|
||
# | ||
# Iterate through all the keys and append port's associated state to | ||
# the result table. | ||
# | ||
for i in appl_db_keys: | ||
key = re.split(':', i, maxsplit=1)[-1].strip() | ||
|
||
if key in front_panel_ports_list: | ||
lanes = appl_db_port_status_get(self.appl_db, key, PORT_LANES_STATUS) | ||
nb_lanes = len(lanes.split(",")) | ||
|
||
interfaces[key] = { | ||
"alias": appl_db_port_status_get(self.appl_db, key, PORT_ALIAS), | ||
"description": appl_db_port_status_get(self.appl_db, key, PORT_DESCRIPTION), | ||
"admin_status": appl_db_port_status_get(self.appl_db, key, PORT_ADMIN_STATUS), | ||
"oper_status": appl_db_port_status_get(self.appl_db, key, PORT_OPER_STATUS), | ||
"lanes": lanes, | ||
"speed": appl_db_port_status_get(self.appl_db, key, PORT_SPEED), | ||
"mtu": appl_db_port_status_get(self.appl_db, key, PORT_MTU_STATUS), | ||
"optic_type": state_db_port_optics_get(self.state_db, key, PORT_OPTICS_TYPE), | ||
"optic_model": state_db_port_optics_get(self.state_db, key, PORT_OPTICS_MODEL), | ||
"optic_manufacturer": state_db_port_optics_get(self.state_db, key, PORT_OPTICS_MANUFACTURER), | ||
} | ||
|
||
for i in range(1, nb_lanes + 1): | ||
interfaces[key]["rx{}_power".format(i)] = state_db_port_optics_sensors_get(self.state_db, key, PORT_OPTICS_SENSOR_RX.format(i)) | ||
interfaces[key]["tx{}_power".format(i)] = state_db_port_optics_sensors_get(self.state_db, key, PORT_OPTICS_SENSOR_TX.format(i)) | ||
|
||
|
||
print json.dumps(interfaces) | ||
|
||
def __init__(self, intf_name): | ||
|
||
self.config_db = db_connect_configdb() | ||
self.state_db = db_connect_state() | ||
self.appl_db = db_connect_appl() | ||
if self.appl_db is None: | ||
return | ||
if self.config_db is None: | ||
return | ||
self.front_panel_ports_list = get_frontpanel_port_list(self.config_db) | ||
appl_db_keys = appl_db_keys_get(self.appl_db, self.front_panel_ports_list, intf_name) | ||
if appl_db_keys is None: | ||
return | ||
|
||
self.display_intf_information(appl_db_keys, self.front_panel_ports_list) | ||
|
||
|
||
def main(args): | ||
if len(args) == 0: | ||
print "No valid arguments provided" | ||
return | ||
|
||
intf_name = args[1] if len(args) == 2 else None | ||
|
||
IntfInformation(intf_name) | ||
|
||
sys.exit(0) | ||
|
||
if __name__ == "__main__": | ||
main(sys.argv) |
Oops, something went wrong.