[macsec]: show macsec: add --profile option, include profile name in show command output (#13940)
This PR is to add the following Add a new options "--profile" to the show macsec command, to show all profiles in device Update the currentl show macsec command, to show profile in each interface o/p. This will tell which macsec profile the interface is attached to.
This commit is contained in:
parent
80aba31433
commit
4b30d09903
75
dockers/docker-macsec/cli-plugin-tests/config_db.json
Normal file
75
dockers/docker-macsec/cli-plugin-tests/config_db.json
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"MACSEC_PROFILE|macsec_profile": {
|
||||||
|
"cipher_suite": "GCM-AES-XPN-256",
|
||||||
|
"policy": "security",
|
||||||
|
"primary_cak": "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
|
||||||
|
"primary_ckn": "6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435",
|
||||||
|
"priority": "0",
|
||||||
|
"rekey_period": "900",
|
||||||
|
"send_sci": "true"
|
||||||
|
},
|
||||||
|
"PORT|Ethernet0": {
|
||||||
|
"alias": "Ethernet1/1",
|
||||||
|
"asic_port_name": "Eth0-ASIC0",
|
||||||
|
"coreid": "1",
|
||||||
|
"coreportid": "1",
|
||||||
|
"description": "Ethernet1/1",
|
||||||
|
"index": "1",
|
||||||
|
"lanes": "72,73,74,75,76,77,78,79",
|
||||||
|
"macsec": "macsec_profile",
|
||||||
|
"mtu": "9100",
|
||||||
|
"numvoq": "8",
|
||||||
|
"pfc_asym": "off",
|
||||||
|
"role": "Ext",
|
||||||
|
"speed": "400000",
|
||||||
|
"tpid": "0x8100"
|
||||||
|
},
|
||||||
|
"PORT|Ethernet1": {
|
||||||
|
"alias": "Ethernet2/1",
|
||||||
|
"asic_port_name": "Eth0-ASIC0",
|
||||||
|
"coreid": "1",
|
||||||
|
"coreportid": "1",
|
||||||
|
"description": "Ethernet2/1",
|
||||||
|
"index": "1",
|
||||||
|
"lanes": "72,73,74,75,76,77,78,79",
|
||||||
|
"macsec": "macsec_profile",
|
||||||
|
"mtu": "9100",
|
||||||
|
"numvoq": "8",
|
||||||
|
"pfc_asym": "off",
|
||||||
|
"role": "Ext",
|
||||||
|
"speed": "400000",
|
||||||
|
"tpid": "0x8100"
|
||||||
|
},
|
||||||
|
"PORT|Ethernet4": {
|
||||||
|
"alias": "Ethernet5/1",
|
||||||
|
"asic_port_name": "Eth0-ASIC0",
|
||||||
|
"coreid": "1",
|
||||||
|
"coreportid": "1",
|
||||||
|
"description": "Ethernet5/1",
|
||||||
|
"index": "1",
|
||||||
|
"lanes": "72,73,74,75,76,77,78,79",
|
||||||
|
"macsec": "macsec_profile",
|
||||||
|
"mtu": "9100",
|
||||||
|
"numvoq": "8",
|
||||||
|
"pfc_asym": "off",
|
||||||
|
"role": "Ext",
|
||||||
|
"speed": "400000",
|
||||||
|
"tpid": "0x8100"
|
||||||
|
},
|
||||||
|
"PORT|Ethernet5": {
|
||||||
|
"alias": "Ethernet6/1",
|
||||||
|
"asic_port_name": "Eth0-ASIC0",
|
||||||
|
"coreid": "1",
|
||||||
|
"coreportid": "1",
|
||||||
|
"description": "Ethernet6/1",
|
||||||
|
"index": "1",
|
||||||
|
"lanes": "72,73,74,75,76,77,78,79",
|
||||||
|
"macsec": "macsec_profile",
|
||||||
|
"mtu": "9100",
|
||||||
|
"numvoq": "8",
|
||||||
|
"pfc_asym": "off",
|
||||||
|
"role": "Ext",
|
||||||
|
"speed": "400000",
|
||||||
|
"tpid": "0x8100"
|
||||||
|
}
|
||||||
|
}
|
@ -23,3 +23,7 @@ class TestShowMACsec(object):
|
|||||||
result = runner.invoke(show_macsec.macsec,["Ethernet1"])
|
result = runner.invoke(show_macsec.macsec,["Ethernet1"])
|
||||||
assert result.exit_code == 0, "exit code: {}, Exception: {}, Traceback: {}".format(result.exit_code, result.exception, result.exc_info)
|
assert result.exit_code == 0, "exit code: {}, Exception: {}, Traceback: {}".format(result.exit_code, result.exception, result.exc_info)
|
||||||
|
|
||||||
|
def test_show_profile(self):
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(show_macsec.macsec,["--profile"])
|
||||||
|
assert result.exit_code == 0, "exit code: {}, Exception: {}, Traceback: {}".format(result.exit_code, result.exception, result.exc_info)
|
||||||
|
@ -18,6 +18,17 @@ CACHE_FILE = os.path.join(CACHE_MANAGER.get_directory(), "macsecstats{}")
|
|||||||
DB_CONNECTOR = None
|
DB_CONNECTOR = None
|
||||||
COUNTER_TABLE = None
|
COUNTER_TABLE = None
|
||||||
|
|
||||||
|
class MACsecCfgMeta(object):
|
||||||
|
def __init__(self, *args) -> None:
|
||||||
|
SEPARATOR = DB_CONNECTOR.get_db_separator(DB_CONNECTOR.CONFIG_DB)
|
||||||
|
self.key = self.__class__.get_cfg_table_name() + SEPARATOR + \
|
||||||
|
SEPARATOR.join(args)
|
||||||
|
self.cfgMeta = DB_CONNECTOR.get_all(
|
||||||
|
DB_CONNECTOR.CONFIG_DB, self.key)
|
||||||
|
if len(self.cfgMeta) == 0:
|
||||||
|
raise ValueError("No such MACsecCfgMeta: {}".format(self.key))
|
||||||
|
for k, v in self.cfgMeta.items():
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
class MACsecAppMeta(object):
|
class MACsecAppMeta(object):
|
||||||
def __init__(self, *args) -> None:
|
def __init__(self, *args) -> None:
|
||||||
@ -126,23 +137,55 @@ class MACsecEgressSC(MACsecSC):
|
|||||||
return "MACsec Egress SC ({})\n".format(self.sci)
|
return "MACsec Egress SC ({})\n".format(self.sci)
|
||||||
|
|
||||||
|
|
||||||
class MACsecPort(MACsecAppMeta):
|
class MACsecPort(MACsecAppMeta, MACsecCfgMeta):
|
||||||
def __init__(self, port_name: str) -> None:
|
def __init__(self, port_name: str) -> None:
|
||||||
self.port_name = port_name
|
self.port_name = port_name
|
||||||
super(MACsecPort, self).__init__(port_name)
|
MACsecAppMeta.__init__(self, port_name)
|
||||||
|
MACsecCfgMeta.__init__(self, port_name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_appl_table_name(cls) -> str:
|
def get_appl_table_name(cls) -> str:
|
||||||
return "MACSEC_PORT_TABLE"
|
return "MACSEC_PORT_TABLE"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_cfg_table_name(cls) -> str:
|
||||||
|
return "PORT"
|
||||||
|
|
||||||
def dump_str(self, cache = None) -> str:
|
def dump_str(self, cache = None) -> str:
|
||||||
buffer = self.get_header()
|
buffer = self.get_header()
|
||||||
|
|
||||||
|
# Add the profile information to the meta dict from config meta dict
|
||||||
|
self.meta["profile"] = self.cfgMeta["macsec"]
|
||||||
|
|
||||||
buffer += tabulate(sorted(self.meta.items(), key=lambda x: x[0]))
|
buffer += tabulate(sorted(self.meta.items(), key=lambda x: x[0]))
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
def get_header(self) -> str:
|
def get_header(self) -> str:
|
||||||
return "MACsec port({})\n".format(self.port_name)
|
return "MACsec port({})\n".format(self.port_name)
|
||||||
|
|
||||||
|
class MACsecProfile(MACsecCfgMeta):
|
||||||
|
def __init__(self, profile_name: str) -> None:
|
||||||
|
self.profile_name = profile_name
|
||||||
|
super(MACsecProfile, self).__init__(profile_name)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_cfg_table_name(cls) -> str:
|
||||||
|
return "MACSEC_PROFILE"
|
||||||
|
|
||||||
|
def dump_str(self, cache = None) -> str:
|
||||||
|
buffer = self.get_header()
|
||||||
|
|
||||||
|
# Don't display the primary and fallback CAK
|
||||||
|
if 'primary_cak' in self.cfgMeta: del self.cfgMeta['primary_cak']
|
||||||
|
if 'fallback_cak' in self.cfgMeta: del self.cfgMeta['fallback_cak']
|
||||||
|
|
||||||
|
t_buffer = tabulate(sorted(self.cfgMeta.items(), key=lambda x: x[0]))
|
||||||
|
t_buffer = "\n".join(["\t" + line for line in t_buffer.splitlines()])
|
||||||
|
buffer += t_buffer
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
def get_header(self) -> str:
|
||||||
|
return "MACsec profile : {}\n".format(self.profile_name)
|
||||||
|
|
||||||
def create_macsec_obj(key: str) -> MACsecAppMeta:
|
def create_macsec_obj(key: str) -> MACsecAppMeta:
|
||||||
attr = key.split(":")
|
attr = key.split(":")
|
||||||
@ -161,6 +204,14 @@ def create_macsec_obj(key: str) -> MACsecAppMeta:
|
|||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def create_macsec_profile_obj(key: str) -> MACsecCfgMeta:
|
||||||
|
attr = key.split("|")
|
||||||
|
try:
|
||||||
|
if attr[0] == MACsecProfile.get_cfg_table_name():
|
||||||
|
return MACsecProfile(attr[1])
|
||||||
|
raise TypeError("Unknown MACsec object type")
|
||||||
|
except ValueError as e:
|
||||||
|
return None
|
||||||
|
|
||||||
def create_macsec_objs(interface_name: str) -> typing.List[MACsecAppMeta]:
|
def create_macsec_objs(interface_name: str) -> typing.List[MACsecAppMeta]:
|
||||||
objs = []
|
objs = []
|
||||||
@ -192,6 +243,12 @@ def create_macsec_objs(interface_name: str) -> typing.List[MACsecAppMeta]:
|
|||||||
return objs
|
return objs
|
||||||
|
|
||||||
|
|
||||||
|
def create_macsec_profiles_objs(profile_name: str) -> typing.List[MACsecCfgMeta]:
|
||||||
|
objs = []
|
||||||
|
objs.append(create_macsec_profile_obj(MACsecProfile.get_cfg_table_name() + "|" + profile_name))
|
||||||
|
return objs
|
||||||
|
|
||||||
|
|
||||||
def cache_find(cache: dict, target: MACsecAppMeta) -> MACsecAppMeta:
|
def cache_find(cache: dict, target: MACsecAppMeta) -> MACsecAppMeta:
|
||||||
if not cache or not cache["objs"]:
|
if not cache or not cache["objs"]:
|
||||||
return None
|
return None
|
||||||
@ -207,10 +264,14 @@ def cache_find(cache: dict, target: MACsecAppMeta) -> MACsecAppMeta:
|
|||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.argument('interface_name', required=False)
|
@click.argument('interface_name', required=False)
|
||||||
@click.option('--dump-file', is_flag=True, required=False, default=False)
|
@click.option('--profile', is_flag=True, required=False, default=False, help="show all macsec profiles")
|
||||||
|
@click.option('--dump-file', is_flag=True, required=False, default=False, help="store show output to a file")
|
||||||
@multi_asic_util.multi_asic_click_options
|
@multi_asic_util.multi_asic_click_options
|
||||||
def macsec(interface_name, dump_file, namespace, display):
|
def macsec(interface_name, dump_file, namespace, display, profile):
|
||||||
MacsecContext(namespace, display).show(interface_name, dump_file)
|
if interface_name is not None and profile:
|
||||||
|
click.echo('Interface name is not valid with profile option')
|
||||||
|
return
|
||||||
|
MacsecContext(namespace, display).show(interface_name, dump_file, profile)
|
||||||
|
|
||||||
class MacsecContext(object):
|
class MacsecContext(object):
|
||||||
|
|
||||||
@ -218,23 +279,36 @@ class MacsecContext(object):
|
|||||||
self.db = None
|
self.db = None
|
||||||
self.multi_asic = multi_asic_util.MultiAsic(
|
self.multi_asic = multi_asic_util.MultiAsic(
|
||||||
display_option, namespace_option)
|
display_option, namespace_option)
|
||||||
|
self.macsec_profiles = []
|
||||||
|
|
||||||
@multi_asic_util.run_on_multi_asic
|
@multi_asic_util.run_on_multi_asic
|
||||||
def show(self, interface_name, dump_file):
|
def show(self, interface_name, dump_file, profile):
|
||||||
global DB_CONNECTOR
|
global DB_CONNECTOR
|
||||||
global COUNTER_TABLE
|
global COUNTER_TABLE
|
||||||
DB_CONNECTOR = self.db
|
DB_CONNECTOR = self.db
|
||||||
COUNTER_TABLE = CounterTable(self.db.get_redis_client(self.db.COUNTERS_DB))
|
|
||||||
|
|
||||||
interface_names = [name.split(":")[1] for name in self.db.keys(self.db.APPL_DB, "MACSEC_PORT*")]
|
if not profile:
|
||||||
if interface_name is not None:
|
COUNTER_TABLE = CounterTable(self.db.get_redis_client(self.db.COUNTERS_DB))
|
||||||
if interface_name not in interface_names:
|
|
||||||
return
|
|
||||||
interface_names = [interface_name]
|
|
||||||
objs = []
|
|
||||||
|
|
||||||
for interface_name in natsorted(interface_names):
|
interface_names = [name.split(":")[1] for name in self.db.keys(self.db.APPL_DB, "MACSEC_PORT*")]
|
||||||
objs += create_macsec_objs(interface_name)
|
if interface_name is not None:
|
||||||
|
if interface_name not in interface_names:
|
||||||
|
return
|
||||||
|
interface_names = [interface_name]
|
||||||
|
objs = []
|
||||||
|
|
||||||
|
for interface_name in natsorted(interface_names):
|
||||||
|
objs += create_macsec_objs(interface_name)
|
||||||
|
else:
|
||||||
|
profile_names = [name.split("|")[1] for name in self.db.keys(self.db.CONFIG_DB, "MACSEC_PROFILE*")]
|
||||||
|
objs = []
|
||||||
|
|
||||||
|
for profile_name in natsorted(profile_names):
|
||||||
|
# Check if this macsec profile is already added to profile list. This is in case of
|
||||||
|
# multi-asic devices where all namespaces will have the same macsec profile defined.
|
||||||
|
if profile_name not in self.macsec_profiles and not dump_file:
|
||||||
|
self.macsec_profiles.append(profile_name)
|
||||||
|
objs += create_macsec_profiles_objs(profile_name)
|
||||||
|
|
||||||
cache = {}
|
cache = {}
|
||||||
if os.path.isfile(CACHE_FILE.format(self.multi_asic.current_namespace)):
|
if os.path.isfile(CACHE_FILE.format(self.multi_asic.current_namespace)):
|
||||||
|
Loading…
Reference in New Issue
Block a user