diff --git a/show/plugins/sonic-hash.py b/show/plugins/sonic-hash.py index 5069c070ff..3744067744 100644 --- a/show/plugins/sonic-hash.py +++ b/show/plugins/sonic-hash.py @@ -4,6 +4,7 @@ import click import tabulate +import json import utilities_common.cli as clicommon from utilities_common.switch_hash import ( @@ -57,30 +58,50 @@ def SWITCH_HASH(): @SWITCH_HASH.command( name="global" ) +@click.option( + "-j", "--json", "json_format", + help="Display in JSON format", + is_flag=True, + default=False +) @clicommon.pass_db -def SWITCH_HASH_GLOBAL(db): +@click.pass_context +def SWITCH_HASH_GLOBAL(ctx, db, json_format): """ Show switch hash global configuration """ - ecmp_header = [ - "ECMP HASH", - "ECMP HASH ALGORITHM", + header = [ + "Hash", + "Configuration", ] - ecmp_body = [] + body = [] - lag_header = [ - "LAG HASH", - "LAG HASH ALGORITHM", + sub_header = [ + "Hash Field", + "Algorithm" ] + ecmp_body = [] lag_body = [] table = db.cfgdb.get_table(CFG_SWITCH_HASH) entry = table.get(SW_HASH_KEY, {}) if not entry: - click.echo(tabulate.tabulate(ecmp_body, ecmp_header)) - click.echo() - click.echo(tabulate.tabulate(lag_body, lag_header)) - return + click.echo("No configuration is present in CONFIG DB") + ctx.exit(0) + + if json_format: + json_dict = { + "ecmp": { + "hash_field": entry["ecmp_hash"] if "ecmp_hash" in entry else "N/A", + "algorithm": entry["ecmp_hash_algorithm"] if "ecmp_hash_algorithm" in entry else "N/A" + }, + "lag": { + "hash_field": entry["lag_hash"] if "lag_hash" in entry else "N/A", + "algorithm": entry["lag_hash_algorithm"] if "lag_hash_algorithm" in entry else "N/A" + } + } + click.echo(json.dumps(json_dict, indent=4)) + ctx.exit(0) ecmp_row = [ format_attr_value( @@ -118,37 +139,43 @@ def SWITCH_HASH_GLOBAL(db): ] lag_body.append(lag_row) - click.echo(tabulate.tabulate(ecmp_body, ecmp_header)) - click.echo() - click.echo(tabulate.tabulate(lag_body, lag_header)) + body.append(["ECMP", tabulate.tabulate(ecmp_body, sub_header, "psql")]) + body.append(["LAG", tabulate.tabulate(lag_body, sub_header, "psql")]) + + click.echo(tabulate.tabulate(body, header, "grid")) @SWITCH_HASH.command( name="capabilities" ) +@click.option( + "-j", "--json", "json_format", + help="Display in JSON format", + is_flag=True, + default=False +) @clicommon.pass_db -def SWITCH_HASH_CAPABILITIES(db): +@click.pass_context +def SWITCH_HASH_CAPABILITIES(ctx, db, json_format): """ Show switch hash capabilities """ - ecmp_header = [ - "ECMP HASH", - "ECMP HASH ALGORITHM", + header = [ + "Hash", + "Capabilities", ] - ecmp_body = [] + body = [] - lag_header = [ - "LAG HASH", - "LAG HASH ALGORITHM", + sub_header = [ + "Hash Field", + "Algorithm" ] + ecmp_body = [] lag_body = [] entry = db.db.get_all(db.db.STATE_DB, "{}|{}".format(STATE_SWITCH_CAPABILITY, SW_CAP_KEY)) if not entry: - click.echo(tabulate.tabulate(ecmp_body, ecmp_header)) - click.echo() - click.echo(tabulate.tabulate(lag_body, lag_header)) - return + ctx.fail("No data is present in STATE DB") entry.setdefault(SW_CAP_HASH_FIELD_LIST_KEY, 'N/A') entry.setdefault(SW_CAP_ECMP_HASH_ALGORITHM_KEY, 'N/A') @@ -167,6 +194,29 @@ def SWITCH_HASH_CAPABILITIES(db): if not entry[SW_CAP_LAG_HASH_ALGORITHM_KEY]: entry[SW_CAP_LAG_HASH_ALGORITHM_KEY] = "no capabilities" + if json_format: + if entry[SW_CAP_HASH_FIELD_LIST_KEY] not in ["N/A", "no capabilities"]: + entry[SW_CAP_HASH_FIELD_LIST_KEY] = entry[SW_CAP_HASH_FIELD_LIST_KEY].split(',') + + if entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY] not in ["N/A", "no capabilities"]: + entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY] = entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY].split(',') + + if entry[SW_CAP_LAG_HASH_ALGORITHM_KEY] not in ["N/A", "no capabilities"]: + entry[SW_CAP_LAG_HASH_ALGORITHM_KEY] = entry[SW_CAP_LAG_HASH_ALGORITHM_KEY].split(',') + + json_dict = { + "ecmp": { + "hash_field": entry[SW_CAP_HASH_FIELD_LIST_KEY] if entry[SW_CAP_ECMP_HASH_CAPABLE_KEY] == 'true' else 'not supported', + "algorithm": entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY] if entry[SW_CAP_ECMP_HASH_ALGORITHM_CAPABLE_KEY] == 'true' else 'not supported' + }, + "lag": { + "hash_field": entry[SW_CAP_HASH_FIELD_LIST_KEY] if entry[SW_CAP_LAG_HASH_CAPABLE_KEY] == 'true' else 'not supported', + "algorithm": entry[SW_CAP_LAG_HASH_ALGORITHM_KEY] if entry[SW_CAP_LAG_HASH_ALGORITHM_CAPABLE_KEY] == 'true' else 'not supported' + } + } + click.echo(json.dumps(json_dict, indent=4)) + ctx.exit(0) + entry[SW_CAP_HASH_FIELD_LIST_KEY] = entry[SW_CAP_HASH_FIELD_LIST_KEY].split(',') entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY] = entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY].split(',') entry[SW_CAP_LAG_HASH_ALGORITHM_KEY] = entry[SW_CAP_LAG_HASH_ALGORITHM_KEY].split(',') @@ -207,9 +257,10 @@ def SWITCH_HASH_CAPABILITIES(db): ] lag_body.append(lag_row) - click.echo(tabulate.tabulate(ecmp_body, ecmp_header)) - click.echo() - click.echo(tabulate.tabulate(lag_body, lag_header)) + body.append(["ECMP", tabulate.tabulate(ecmp_body, sub_header, "psql")]) + body.append(["LAG", tabulate.tabulate(lag_body, sub_header, "psql")]) + + click.echo(tabulate.tabulate(body, header, "grid")) def register(cli): diff --git a/tests/hash_input/assert_show_output.py b/tests/hash_input/assert_show_output.py index eb87632ef9..8a1e1fa2dc 100644 --- a/tests/hash_input/assert_show_output.py +++ b/tests/hash_input/assert_show_output.py @@ -3,227 +3,579 @@ """ show_hash_empty="""\ -ECMP HASH ECMP HASH ALGORITHM ------------ --------------------- - -LAG HASH LAG HASH ALGORITHM ----------- -------------------- +No configuration is present in CONFIG DB """ show_hash_ecmp="""\ -ECMP HASH ECMP HASH ALGORITHM ------------------ --------------------- -DST_MAC CRC -SRC_MAC -ETHERTYPE -IP_PROTOCOL -DST_IP -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT - -LAG HASH LAG HASH ALGORITHM ----------- -------------------- -N/A N/A ++--------+-------------------------------------+ +| Hash | Configuration | ++========+=====================================+ +| ECMP | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | DST_MAC | CRC | | +| | | SRC_MAC | | | +| | | ETHERTYPE | | | +| | | IP_PROTOCOL | | | +| | | DST_IP | | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +| LAG | +--------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |--------------+-------------| | +| | | N/A | N/A | | +| | +--------------+-------------+ | ++--------+-------------------------------------+ +""" +show_hash_ecmp_json="""\ +{ + "ecmp": { + "hash_field": [ + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": "CRC" + }, + "lag": { + "hash_field": "N/A", + "algorithm": "N/A" + } +} """ show_hash_lag="""\ -ECMP HASH ECMP HASH ALGORITHM ------------ --------------------- -N/A N/A - -LAG HASH LAG HASH ALGORITHM ------------------ -------------------- -DST_MAC XOR -SRC_MAC -ETHERTYPE -IP_PROTOCOL -DST_IP -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT ++--------+-------------------------------------+ +| Hash | Configuration | ++========+=====================================+ +| ECMP | +--------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |--------------+-------------| | +| | | N/A | N/A | | +| | +--------------+-------------+ | ++--------+-------------------------------------+ +| LAG | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | DST_MAC | XOR | | +| | | SRC_MAC | | | +| | | ETHERTYPE | | | +| | | IP_PROTOCOL | | | +| | | DST_IP | | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +""" +show_hash_lag_json="""\ +{ + "ecmp": { + "hash_field": "N/A", + "algorithm": "N/A" + }, + "lag": { + "hash_field": [ + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": "XOR" + } +} """ show_hash_ecmp_and_lag="""\ -ECMP HASH ECMP HASH ALGORITHM ------------------ --------------------- -DST_MAC CRC -SRC_MAC -ETHERTYPE -IP_PROTOCOL -DST_IP -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT - -LAG HASH LAG HASH ALGORITHM ------------------ -------------------- -DST_MAC XOR -SRC_MAC -ETHERTYPE -IP_PROTOCOL -DST_IP -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT ++--------+-------------------------------------+ +| Hash | Configuration | ++========+=====================================+ +| ECMP | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | DST_MAC | CRC | | +| | | SRC_MAC | | | +| | | ETHERTYPE | | | +| | | IP_PROTOCOL | | | +| | | DST_IP | | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +| LAG | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | DST_MAC | XOR | | +| | | SRC_MAC | | | +| | | ETHERTYPE | | | +| | | IP_PROTOCOL | | | +| | | DST_IP | | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +""" +show_hash_ecmp_and_lag_json="""\ +{ + "ecmp": { + "hash_field": [ + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": "CRC" + }, + "lag": { + "hash_field": [ + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": "XOR" + } +} """ show_hash_capabilities_no="""\ -ECMP HASH ECMP HASH ALGORITHM ---------------- --------------------- -no capabilities no capabilities - -LAG HASH LAG HASH ALGORITHM ---------------- -------------------- -no capabilities no capabilities ++--------+---------------------------------------+ +| Hash | Capabilities | ++========+=======================================+ +| ECMP | +-----------------+-----------------+ | +| | | Hash Field | Algorithm | | +| | |-----------------+-----------------| | +| | | no capabilities | no capabilities | | +| | +-----------------+-----------------+ | ++--------+---------------------------------------+ +| LAG | +-----------------+-----------------+ | +| | | Hash Field | Algorithm | | +| | |-----------------+-----------------| | +| | | no capabilities | no capabilities | | +| | +-----------------+-----------------+ | ++--------+---------------------------------------+ +""" +show_hash_capabilities_no_json="""\ +{ + "ecmp": { + "hash_field": "no capabilities", + "algorithm": "no capabilities" + }, + "lag": { + "hash_field": "no capabilities", + "algorithm": "no capabilities" + } +} """ show_hash_capabilities_na="""\ -ECMP HASH ECMP HASH ALGORITHM ------------ --------------------- -N/A N/A - -LAG HASH LAG HASH ALGORITHM ----------- -------------------- -N/A N/A ++--------+--------------------------------+ +| Hash | Capabilities | ++========+================================+ +| ECMP | +--------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |--------------+-------------| | +| | | N/A | N/A | | +| | +--------------+-------------+ | ++--------+--------------------------------+ +| LAG | +--------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |--------------+-------------| | +| | | N/A | N/A | | +| | +--------------+-------------+ | ++--------+--------------------------------+ +""" +show_hash_capabilities_na_json="""\ +{ + "ecmp": { + "hash_field": "N/A", + "algorithm": "N/A" + }, + "lag": { + "hash_field": "N/A", + "algorithm": "N/A" + } +} """ show_hash_capabilities_empty="""\ -ECMP HASH ECMP HASH ALGORITHM -------------- --------------------- -not supported not supported - -LAG HASH LAG HASH ALGORITHM -------------- -------------------- -not supported not supported ++--------+-----------------------------------+ +| Hash | Capabilities | ++========+===================================+ +| ECMP | +---------------+---------------+ | +| | | Hash Field | Algorithm | | +| | |---------------+---------------| | +| | | not supported | not supported | | +| | +---------------+---------------+ | ++--------+-----------------------------------+ +| LAG | +---------------+---------------+ | +| | | Hash Field | Algorithm | | +| | |---------------+---------------| | +| | | not supported | not supported | | +| | +---------------+---------------+ | ++--------+-----------------------------------+ +""" +show_hash_capabilities_empty_json="""\ +{ + "ecmp": { + "hash_field": "not supported", + "algorithm": "not supported" + }, + "lag": { + "hash_field": "not supported", + "algorithm": "not supported" + } +} """ show_hash_capabilities_ecmp="""\ -ECMP HASH ECMP HASH ALGORITHM ------------------ --------------------- -IN_PORT CRC -DST_MAC XOR -SRC_MAC RANDOM -ETHERTYPE CRC_32LO -VLAN_ID CRC_32HI -IP_PROTOCOL CRC_CCITT -DST_IP CRC_XOR -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT - -LAG HASH LAG HASH ALGORITHM -------------- -------------------- -not supported not supported ++--------+-------------------------------------+ +| Hash | Capabilities | ++========+=====================================+ +| ECMP | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | IN_PORT | CRC | | +| | | DST_MAC | XOR | | +| | | SRC_MAC | RANDOM | | +| | | ETHERTYPE | CRC_32LO | | +| | | VLAN_ID | CRC_32HI | | +| | | IP_PROTOCOL | CRC_CCITT | | +| | | DST_IP | CRC_XOR | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +| LAG | +---------------+---------------+ | +| | | Hash Field | Algorithm | | +| | |---------------+---------------| | +| | | not supported | not supported | | +| | +---------------+---------------+ | ++--------+-------------------------------------+ +""" +show_hash_capabilities_ecmp_json="""\ +{ + "ecmp": { + "hash_field": [ + "IN_PORT", + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "VLAN_ID", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": [ + "CRC", + "XOR", + "RANDOM", + "CRC_32LO", + "CRC_32HI", + "CRC_CCITT", + "CRC_XOR" + ] + }, + "lag": { + "hash_field": "not supported", + "algorithm": "not supported" + } +} """ show_hash_capabilities_lag="""\ -ECMP HASH ECMP HASH ALGORITHM -------------- --------------------- -not supported not supported - -LAG HASH LAG HASH ALGORITHM ------------------ -------------------- -IN_PORT CRC -DST_MAC XOR -SRC_MAC RANDOM -ETHERTYPE CRC_32LO -VLAN_ID CRC_32HI -IP_PROTOCOL CRC_CCITT -DST_IP CRC_XOR -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT ++--------+-------------------------------------+ +| Hash | Capabilities | ++========+=====================================+ +| ECMP | +---------------+---------------+ | +| | | Hash Field | Algorithm | | +| | |---------------+---------------| | +| | | not supported | not supported | | +| | +---------------+---------------+ | ++--------+-------------------------------------+ +| LAG | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | IN_PORT | CRC | | +| | | DST_MAC | XOR | | +| | | SRC_MAC | RANDOM | | +| | | ETHERTYPE | CRC_32LO | | +| | | VLAN_ID | CRC_32HI | | +| | | IP_PROTOCOL | CRC_CCITT | | +| | | DST_IP | CRC_XOR | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +""" +show_hash_capabilities_lag_json="""\ +{ + "ecmp": { + "hash_field": "not supported", + "algorithm": "not supported" + }, + "lag": { + "hash_field": [ + "IN_PORT", + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "VLAN_ID", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": [ + "CRC", + "XOR", + "RANDOM", + "CRC_32LO", + "CRC_32HI", + "CRC_CCITT", + "CRC_XOR" + ] + } +} """ show_hash_capabilities_ecmp_and_lag="""\ -ECMP HASH ECMP HASH ALGORITHM ------------------ --------------------- -IN_PORT CRC -DST_MAC XOR -SRC_MAC RANDOM -ETHERTYPE CRC_32LO -VLAN_ID CRC_32HI -IP_PROTOCOL CRC_CCITT -DST_IP CRC_XOR -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT - -LAG HASH LAG HASH ALGORITHM ------------------ -------------------- -IN_PORT CRC -DST_MAC XOR -SRC_MAC RANDOM -ETHERTYPE CRC_32LO -VLAN_ID CRC_32HI -IP_PROTOCOL CRC_CCITT -DST_IP CRC_XOR -SRC_IP -L4_DST_PORT -L4_SRC_PORT -INNER_DST_MAC -INNER_SRC_MAC -INNER_ETHERTYPE -INNER_IP_PROTOCOL -INNER_DST_IP -INNER_SRC_IP -INNER_L4_DST_PORT -INNER_L4_SRC_PORT ++--------+-------------------------------------+ +| Hash | Capabilities | ++========+=====================================+ +| ECMP | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | IN_PORT | CRC | | +| | | DST_MAC | XOR | | +| | | SRC_MAC | RANDOM | | +| | | ETHERTYPE | CRC_32LO | | +| | | VLAN_ID | CRC_32HI | | +| | | IP_PROTOCOL | CRC_CCITT | | +| | | DST_IP | CRC_XOR | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +| LAG | +-------------------+-------------+ | +| | | Hash Field | Algorithm | | +| | |-------------------+-------------| | +| | | IN_PORT | CRC | | +| | | DST_MAC | XOR | | +| | | SRC_MAC | RANDOM | | +| | | ETHERTYPE | CRC_32LO | | +| | | VLAN_ID | CRC_32HI | | +| | | IP_PROTOCOL | CRC_CCITT | | +| | | DST_IP | CRC_XOR | | +| | | SRC_IP | | | +| | | L4_DST_PORT | | | +| | | L4_SRC_PORT | | | +| | | INNER_DST_MAC | | | +| | | INNER_SRC_MAC | | | +| | | INNER_ETHERTYPE | | | +| | | INNER_IP_PROTOCOL | | | +| | | INNER_DST_IP | | | +| | | INNER_SRC_IP | | | +| | | INNER_L4_DST_PORT | | | +| | | INNER_L4_SRC_PORT | | | +| | +-------------------+-------------+ | ++--------+-------------------------------------+ +""" +show_hash_capabilities_ecmp_and_lag_json="""\ +{ + "ecmp": { + "hash_field": [ + "IN_PORT", + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "VLAN_ID", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": [ + "CRC", + "XOR", + "RANDOM", + "CRC_32LO", + "CRC_32HI", + "CRC_CCITT", + "CRC_XOR" + ] + }, + "lag": { + "hash_field": [ + "IN_PORT", + "DST_MAC", + "SRC_MAC", + "ETHERTYPE", + "VLAN_ID", + "IP_PROTOCOL", + "DST_IP", + "SRC_IP", + "L4_DST_PORT", + "L4_SRC_PORT", + "INNER_DST_MAC", + "INNER_SRC_MAC", + "INNER_ETHERTYPE", + "INNER_IP_PROTOCOL", + "INNER_DST_IP", + "INNER_SRC_IP", + "INNER_L4_DST_PORT", + "INNER_L4_SRC_PORT" + ], + "algorithm": [ + "CRC", + "XOR", + "RANDOM", + "CRC_32LO", + "CRC_32HI", + "CRC_CCITT", + "CRC_XOR" + ] + } +} """ diff --git a/tests/hash_test.py b/tests/hash_test.py index d700907b55..f9de27e999 100644 --- a/tests/hash_test.py +++ b/tests/hash_test.py @@ -218,90 +218,132 @@ def test_config_hash_algorithm_neg(self, hash, arg, pattern): "cfgdb,output", [ pytest.param( os.path.join(mock_config_path, "empty"), - assert_show_output.show_hash_empty, + { + "plain": assert_show_output.show_hash_empty, + "json": assert_show_output.show_hash_empty + }, id="empty" ), pytest.param( os.path.join(mock_config_path, "ecmp"), - assert_show_output.show_hash_ecmp, + { + "plain": assert_show_output.show_hash_ecmp, + "json": assert_show_output.show_hash_ecmp_json + }, id="ecmp" ), pytest.param( os.path.join(mock_config_path, "lag"), - assert_show_output.show_hash_lag, + { + "plain": assert_show_output.show_hash_lag, + "json": assert_show_output.show_hash_lag_json + }, id="lag" ), pytest.param( os.path.join(mock_config_path, "ecmp_and_lag"), - assert_show_output.show_hash_ecmp_and_lag, + { + "plain": assert_show_output.show_hash_ecmp_and_lag, + "json": assert_show_output.show_hash_ecmp_and_lag_json + }, id="all" ) ] ) - def test_show_hash(self, cfgdb, output): + @pytest.mark.parametrize( + "format", [ + "plain", + "json", + ] + ) + def test_show_hash(self, cfgdb, output, format): dbconnector.dedicated_dbs["CONFIG_DB"] = cfgdb db = Db() runner = CliRunner() result = runner.invoke( - show.cli.commands["switch-hash"]. - commands["global"], [], obj=db + show.cli.commands["switch-hash"].commands["global"], + [] if format == "plain" else ["--json"], obj=db ) logger.debug("\n" + result.output) logger.debug(result.exit_code) - assert result.output == output + assert result.output == output[format] assert result.exit_code == SUCCESS @pytest.mark.parametrize( "statedb,output", [ pytest.param( os.path.join(mock_state_path, "no_capabilities"), - assert_show_output.show_hash_capabilities_no, + { + "plain": assert_show_output.show_hash_capabilities_no, + "json": assert_show_output.show_hash_capabilities_no_json + }, id="no" ), pytest.param( os.path.join(mock_state_path, "not_applicable"), - assert_show_output.show_hash_capabilities_na, + { + "plain": assert_show_output.show_hash_capabilities_na, + "json": assert_show_output.show_hash_capabilities_na_json + }, id="na" ), pytest.param( os.path.join(mock_state_path, "empty"), - assert_show_output.show_hash_capabilities_empty, + { + "plain": assert_show_output.show_hash_capabilities_empty, + "json": assert_show_output.show_hash_capabilities_empty_json + }, id="empty" ), pytest.param( os.path.join(mock_state_path, "ecmp"), - assert_show_output.show_hash_capabilities_ecmp, + { + "plain": assert_show_output.show_hash_capabilities_ecmp, + "json": assert_show_output.show_hash_capabilities_ecmp_json + }, id="ecmp" ), pytest.param( os.path.join(mock_state_path, "lag"), - assert_show_output.show_hash_capabilities_lag, + { + "plain": assert_show_output.show_hash_capabilities_lag, + "json": assert_show_output.show_hash_capabilities_lag_json + }, id="lag" ), pytest.param( os.path.join(mock_state_path, "ecmp_and_lag"), - assert_show_output.show_hash_capabilities_ecmp_and_lag, + { + "plain": assert_show_output.show_hash_capabilities_ecmp_and_lag, + "json": assert_show_output.show_hash_capabilities_ecmp_and_lag_json + }, id="all" ) ] ) - def test_show_hash_capabilities(self, statedb, output): + @pytest.mark.parametrize( + "format", [ + "plain", + "json", + ] + ) + def test_show_hash_capabilities(self, statedb, output, format): dbconnector.dedicated_dbs["STATE_DB"] = statedb db = Db() runner = CliRunner() result = runner.invoke( - show.cli.commands["switch-hash"]. - commands["capabilities"], [], obj=db + show.cli.commands["switch-hash"].commands["capabilities"], + [] if format == "plain" else ["--json"], obj=db ) logger.debug("\n" + result.output) logger.debug(result.exit_code) - assert result.output == output + assert result.output == output[format] assert result.exit_code == SUCCESS