Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add state to install criteo sonic-utilities #11

Merged
merged 1 commit into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions states/utilities/201911/criteo_fdbshow
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()
189 changes: 189 additions & 0 deletions states/utilities/201911/criteo_intf_information
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)
Loading
Loading