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

[action] [PR:13940] show macsec: add --profile option, include profile name in show command output #15127

Merged
merged 1 commit into from
May 18, 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
75 changes: 75 additions & 0 deletions dockers/docker-macsec/cli-plugin-tests/config_db.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
4 changes: 4 additions & 0 deletions dockers/docker-macsec/cli-plugin-tests/test_show_macsec.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ def test_show_one_port(self):
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)

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)
104 changes: 89 additions & 15 deletions dockers/docker-macsec/cli/show/plugins/show_macsec.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@
DB_CONNECTOR = 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):
def __init__(self, *args) -> None:
Expand Down Expand Up @@ -126,23 +137,55 @@ def get_header(self):
return "MACsec Egress SC ({})\n".format(self.sci)


class MACsecPort(MACsecAppMeta):
class MACsecPort(MACsecAppMeta, MACsecCfgMeta):
def __init__(self, port_name: str) -> None:
self.port_name = port_name
super(MACsecPort, self).__init__(port_name)
MACsecAppMeta.__init__(self, port_name)
MACsecCfgMeta.__init__(self, port_name)

@classmethod
def get_appl_table_name(cls) -> str:
return "MACSEC_PORT_TABLE"

@classmethod
def get_cfg_table_name(cls) -> str:
return "PORT"

def dump_str(self, cache = None) -> str:
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]))
return buffer

def get_header(self) -> str:
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:
attr = key.split(":")
Expand All @@ -161,6 +204,14 @@ def create_macsec_obj(key: str) -> MACsecAppMeta:
except ValueError as e:
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]:
objs = []
Expand Down Expand Up @@ -192,6 +243,12 @@ def create_macsec_objs(interface_name: str) -> typing.List[MACsecAppMeta]:
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:
if not cache or not cache["objs"]:
return None
Expand All @@ -207,34 +264,51 @@ def cache_find(cache: dict, target: MACsecAppMeta) -> MACsecAppMeta:

@click.command()
@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
def macsec(interface_name, dump_file, namespace, display):
MacsecContext(namespace, display).show(interface_name, dump_file)
def macsec(interface_name, dump_file, namespace, display, profile):
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):

def __init__(self, namespace_option, display_option):
self.db = None
self.multi_asic = multi_asic_util.MultiAsic(
display_option, namespace_option)
self.macsec_profiles = []

@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 COUNTER_TABLE
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 interface_name is not None:
if interface_name not in interface_names:
return
interface_names = [interface_name]
objs = []
if not profile:
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 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)
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 = {}
if os.path.isfile(CACHE_FILE.format(self.multi_asic.current_namespace)):
Expand Down