From d909a48f5e5e012f7eac081122b25b92dd0f4261 Mon Sep 17 00:00:00 2001 From: "Nazeer, Mohammed" Date: Wed, 3 Aug 2022 22:24:19 +0530 Subject: [PATCH] sync from broadcom_sonic_4.x_share to dell_sonic_4.x_share - 0803 (#157) * [JIRA SONIC-54751] Flex-DPB UMF changes - Rejecting config when max ports per pipe-line is reached. - Support some new modes in different formats - 1x50G-PAM and 1x50G-NRZ Signed-off-by: Prasanth Kunjum Veettil Change-Id: I1305e237f000434f7c837d11b9977246df30efec * [JIRA SONIC-54751] FlexDPB - modifying the show interface breakout modes command to display the pipe. Signed-off-by: Prasanth Kunjum Veettil Change-Id: Icadd5afd3729f65180a99cb8133fae47e090849c * [JIRA SONIC-54751] FlexDPB - Making the CLI output better when there are too many breakout modes. Signed-off-by: Prasanth Kunjum Veettil Change-Id: I38ec87ef6025978dbd88d7d5a2fa9ff7209ac969 * [JIRA SONIC-54751] Flex-DPB UM Adding CLI "show interface breakout resources" Signed-off-by: Prasanth Kunjum Veettil Change-Id: I8b9658b289557e0c708fa02f65e392b112c11609 * [JIRA SONIC-59502] User name field in not applicable cases should be displayed as Not Applicable instead of empty. Change-Id: Ie96be7eacf13a9ebe4c9e95abbd6a88f1e47533f * [JIRA SONIC-60245] Field to display the operational value of the session timeout in the output of the show authentication clients. Change-Id: Ieddba8ac30568d55197fe1ce172b8cc208ffdc30 * [JIRA SONIC-56405] Added support for pac configuration over range of interfaces. Change-Id: I0ce68fc2497fcc45fcd0c15d6113542967d974c2 * [JIRA SONIC-61478] KLISH: add 50G AN support Signed-off-by: Dante Su Change-Id: If6c05a49f18469858b66c58cd456e7b4f6a3c0e0 * [JIRA SONIC-61803] GetTablePattern ExistKeysPattern API in DB Layer - Added Statistics Change-Id: I3732e78e13881842e9394a571788abe3ab1ac337 * [JIRA SONIC-61314] go.sum update Change-Id: I7576ffc6933f9727747d3463b022c23ad7def609 * [JIRA SONIC-61807] - Model Identity as enumeration Used Enum to represent identities This will allow swagger ui to show drop-down in case of parameters. Change-Id: I8e438545d0b28c9c2ee545a2704366da512b5c74 * [JIRA SONIC-60508]: ospf neighbor details template fix Change-Id: Iee1dbdc72e02a6d23e0dfac71220843be3730ddd * [JIRA SONIC-61879] PAC - Added required changes for config knobs dymanic_vlan_enable, vlan_assign_enable. Change-Id: Ib38db8f2e9917b4261fc709e1548ea78f0196453 * [JIRA SONIC-61168] Klish support for ND config commands Change-Id: I7227cb99ecf82bddac169c3b544bd28758f40c3b * [JIRA SONIC-61223] With user added explicit snooping configuration on Vlan, actioner has called PATCH with default value for the no form of the user configuration, this has resulted in running configuration showing default value when there is no explicit configuration for the default - Fixed actioner script to trigger DELETE for the snooping configuration instead of PATCH with the default values. - Fix added in l2mcmgrd to fill snooping configuration IPC message by reading redisDB update instead of keeping separate local cache for snooping configurations which comes before snooping enable. Change-Id: I3ace4e6eca5cb7608d48bb9e3a11bb1c4976e4d9 * [JIRA SONIC-61948] - Using oc-yang for dhcp snooping trusted port configuration in Klish Change-Id: I33c811e9316b552b08cdbc12489c73806f4e3e95 * [JIRA SONIC-54751] Flex DPB - PAM/NRZ generic lane count approach - System level max ports - Lane count notation translation, display, config display Signed-off-by: Prasanth Kunjum Veettil Change-Id: If8b5429e732fce5342d960b0980a250f75a5ff8c * [JIRA SONIC-54751] Flex DPB - 20G speed support Signed-off-by: Prasanth Kunjum Veettil Change-Id: I8a0f581c70c0aa6b30e76a64fe4262d44f828568 * [JIRA SONIC-62134] - Corrected the sag xml order to come after vrf config Change-Id: I0d463d9d16e014d39b343d14d36ff801019017d4 * [JIRA SONIC-61997] using escap_chars option to skip '\' for special chars Change-Id: I3b654ea105931c0e3605b84ed5db560cb5e13e95 * [JIRA SONIC-62061] validating tag field of SNMP_SERVER_TARGET entry, before using it Change-Id: I504812121a85e83693d00dae76d5321583b1b7a0 * [JIRA SONIC-61168] Klish support for show command Change-Id: Ia2e6d4d8b8ae598af3cdcdbbb051bcddc8625bbc * [JIRA SONIC-62420] Added changes to not format debug logs until its enabled to speed up execuction of actioners for ACL and FBS Change-Id: Ibbad404d7f6890d03b99d63f26f9ddd36eab728d * [JIRA SONIC-54751] Flex DPB - rename lane-count to total-lane-count Signed-off-by: Prasanth Kunjum Veettil Change-Id: I2ecb8e0a5e6ca0ced86bb795ef2a98a155c25fdc * [JIRA SONIC-60841] The NTP client must support the "prefer" option and provide CLI for enabling it Change-Id: I724543e858a256032fa9d45a5982a4124266a859 * [JIRA SONIC-61168] Klish support for modifying help string associated with config commands to make it more descriptive Change-Id: I9377ef77a093c3b0ed5269a1df874965ae6a3298 * [JIRA SONIC-61879] PAC - Added required UI changes for Auth Fail Retry config command. Change-Id: Id66b4d31e6a509816f4d5b598c005b109397856e * [JIRA SONIC-60945] Show redirect ACL binding in show access-group CLI Change-Id: I56a2f7bce3a34eec51c4371210a4379ee8730589 * [JIRA SONIC-62672] Fix exception when per interface acl mode is enabled Change-Id: If924f71bc4e614ff948351a94a3a26b9ef18df6b * [JIRA SONIC-62110] SONIC_4.1.0 - media_autoconf: initial commit Signed-off-by: Dante Su Change-Id: Id799deb252c489102d9efcc3b3280d32ff86dce4 * [JIRA SONIC-62796] SONIC_4.1.0 - KLISH CLI: Add 200G support to 'show interface advertise' Signed-off-by: Dante Su Change-Id: Ic66c272a8bc8826480365eb5780ef4db2aa4f1ca * [JIRA SONIC-62847] Clish pre-exec hook * Added a new pre-exec hook, which gets called before executing the ACTION or CONFIG handlers * Hook function receives the current command context * Command execution is aborted if hook returns non-zero value * Added a skeleton implementation in clish plugin * Few utility functions for the future pre-hook implementation char *get_uname(clish_context_t *c) char *get_masked_line(clish_context_t *c) Change-Id: I44a0a5df4419fb51ad90ff9898db6b9534ef5eb1 * [JIRA SONIC-62732] [JIRA SONIC-62730] : 1.Fix jinja template to show proper state for helper strict lsa checking Change-Id: I313baac45137b46eab821fb5e17234ca365270a5 * [JIRA SONIC-62280] Added COA klish CLI changes. Change-Id: Ie7498ad7451763256641862da4d5ba12efdc750a * [JIRA SONIC-61879] Modified authentication fail retry default value to 1, made minor corrections in authmgr appl. Change-Id: I1cef51a96991d22a54e407c0b6dd60d0edef055c * [JIRA SONIC-62875] Fix processing of dynamic acls and redirect acls when per interface acl counter mode is enabled Change-Id: Ic8d3e0c8b16ac9785b8f9c687e603c3f8659cd77 * [JIRA SONIC-61950]: Dot1x/MAB timers config support Change-Id: I022b1d75b183e3028db5c083b1d70a971616a597 * [JIRA SONIC-62911] PTP 1-step and TH3 support - UMF changes Signed-off-by: Prasanth Kunjum Veettil Change-Id: Ib46e89a9f82c73b8e8af5b53d479258f424a51f5 * [JIRA SONIC-63025] SONIC_4.1.0 - KLISH: add the missing link-training status support Signed-off-by: Dante Su Change-Id: Icb05d69abd3a9042d5d2838868fcbde7871caf09 * [JIRA SONIC-63081] SONIC_4.1.0 - KLISH/YANG: Reverting SONIC-51042 to use float with precision 2 in DOM values Signed-off-by: Dante Su Change-Id: I200df89d1dcc234965eb87a27b5c6df8e28c3f0a * [JIRA SONIC-62637] : 1. Added support for -:show ip ospf database opaque-link 2.Support opaque-link lsa summary for -:show ip ospf database Change-Id: I631ca9918bb90630420a94caed1603d673923e81 * [JIRA SONIC-62953] added check for security-nme key before accessing it. Change-Id: I5ff72ed7a4b183cf939455e2afba97d0f964d618 * [JIRA SONIC-63000] Portchannel min-links related changes Change-Id: I3ab9f27c8b6fe5266eddfc60295d0fa3bb806557 * [JIRA SONIC-63158] Kernel 5.10 does not support l3mdev cgroups, instead cgroups with BPF programs are used to achieve this. Since kernel vrf support now adds CGROUPS with BPF which iproute2 utils uses in ip vrf exec commands. Update SONiC scripts to "ip vrf exec" from cgexec. Change-Id: I8df96902b4d933462fa23cb14100caf5f432de6f * [JIRA SONIC-62104] SONIC_4.1.0 - EVPN Multihoming Task - KLISH system-mac and evpn ethernet segment Change-Id: Iad4153e21c9f67b0326aced909f7c9d07ef67429 * [JIRA SONIC-63064] SONIC_4.1.0 - EVPN Multihoming Task - mclag domain config checking Change-Id: I8bc1619034e37fd99fdbac8a096fbe51de0d85b3 * [JIRA SONIC-62780] SONIC_4.1.0 - Add interface Portchannel range support for system-mac configuration Change-Id: I10bec6d70e1eaff6af16de33c12f3dbc1aa47433 * [JIRA SONIC-63320] Added UI support for multi-vrf functionality of TAM collectors. Change-Id: Ie44af58c8aab48b54b43aa843ccf5ea7870db479 * [JIRA SONIC-63333] bgp clis - disable-ead-evi-rx, disable-ead-evi-tx, use-es-l3nhg Change-Id: I12470dbf82495e14cc3638e9b329897d5d9156f5 * [JIRA SONIC-63377] TCAM Keyprofile CLI Changes Few key-profile names are missing in TCAM CLI. Code changes has been done to add the missing key-profile names in TCAM CLI. Change-Id: I249cd34b6266e6c35e79b77d5fb9d95a0dccaf04 * [JIRA SONIC-63000] Portchannel fallback config updated related changes Change-Id: I9fb8885f8f055ffe7a8556788f1e8b50ac5fb73f * [JIRA SONIC-63408] - Fix CLI docgen issue Re-Enaled cli docgen made it to execute with python3 always Fixed unicode issues. Change-Id: I611133abbf0d389172768153e6e3fc2fa2f1b996 * [JIRA SONIC-63053] : 1.Add ospf gr prepartion status to ospf global state info 2.Fixed a template issue Change-Id: I0a875f2b7b520b535f564061eb92427be8db26dd * [JIRA SONIC-62082] Support for clearing evpn duplicate address based on IP address. Change-Id: I3f0ab0428cca4e37285ffa12416d7755cc4ce020 * [JIRA SONIC-63000] Portchannel fast-rate config updated related changes Change-Id: If154af9ada867067aee3b631170e1a7c815d9f05 * [JIRA SONIC-62800] Invoking new statistics detail URLs. Change-Id: I29290a17cc85223c6ba5f23f4d64cb9c29c08380 * [JIRA SONIC-63378] Fix ACL description update to not include double quotes, ACL subintf binding to use subintf index, added exception handling to prevent exception in 1 show running callback to impact other callbacks Change-Id: Ib796610c3fe4bfb1dee090518c564f2069e95d5c * [JIRA SONIC-62913] Unable to remove tacacs-server host and observing "% Error: Client is not authorized to perform this operation" Change-Id: I972174c64374ab198678e7722bcf8822cced1830 * [JIRA SONIC-63479] WFB: "speed auto 400000" throwing Error " Speed 400000 is not supported on Ethernet56" on z9332 Signed-off-by: Dante Su Change-Id: I3f06248c2f5a3d5b82058753dfc16256d99cb40a * [JIRA SONIC-63000] Fixing the show-configuration and show-running-configuration for the config updated related changes Change-Id: I2c4e4a5a02a3508e86d8111b7dd1a66db4caf548 * [JIRA SONIC-63303] [JIRA SONIC-63459] Neighbor Discovery fixes for alias mode and reboot case for ra-lifetime Change-Id: I98f8d738e9d4196debe12323931306004caecf0c * [JIRA SONIC-63000] Fallback value is showing incorrect in the command 'show interface portchannel' as it is not picking the value from DB correctly. Fixing the issue by picking the correct value from CONFIG_DB. Change-Id: I58db4bcde4f9af7e8dae79151b1b5768189ff8e3 * [JIRA SONIC-62130] Tpcm Enhancements Along with previous enhancements, added support for "tpcm update disk-limit " Change-Id: I8ee3058f1d69d39c19d8c06d96c5faf60843db9b * [JIRA SONIC-63601] checking presence of target-params and udp in the dictionary before accession them Change-Id: Ia147b385087449487e2c91ac2ed8de3adb37e540 * Fixing merge conflict Co-authored-by: sonicmergeuser Co-authored-by: Prasanth Kunjum Veettil Co-authored-by: Sravani Maddukuri Co-authored-by: Shiva Kumar Boddula Co-authored-by: Dante Su Co-authored-by: Sonic Build Co-authored-by: Arun Barboza Co-authored-by: Sachin Holla Co-authored-by: Faraaz Co-authored-by: Ramachandran Sathianandan Co-authored-by: sudhanshukumar22 Co-authored-by: Ashok Krishnegowda Co-authored-by: Akhilesh Samineni Co-authored-by: suresh-rupanagudi Co-authored-by: Lakshmi Sruthy Co-authored-by: Abhishek Dharwadkar Co-authored-by: Asha Behera Co-authored-by: Rama Chandra Reddy Gaddam Co-authored-by: madhukar-kamarapu Co-authored-by: Preetham Singh Co-authored-by: leeprecy Co-authored-by: Mayank Maheshwari Co-authored-by: karthik raj Co-authored-by: Ashok Narayanasamy Co-authored-by: Kishore Kunal Co-authored-by: Phanindra TV Co-authored-by: Prabhu Sreenivasan Co-authored-by: sg893052 Co-authored-by: SONiC Syncbot --- CLI/actioner/show_config_data.py | 1 + CLI/actioner/show_config_interface.py | 18 +- CLI/actioner/show_running_config_nd.py | 4 +- CLI/actioner/sonic-cli-neighbors.py | 9 +- CLI/actioner/sonic_cli_if.py | 3 +- CLI/actioner/sonic_cli_if_autoneg.py | 126 ++--- CLI/actioner/sonic_cli_if_eth.py | 441 ++++++++++++++++++ CLI/actioner/sonic_cli_if_range.py | 3 +- CLI/actioner/sonic_cli_if_status.py | 116 +++++ CLI/actioner/sonic_cli_network_tools.py | 2 +- CLI/actioner/sonic_cli_snmp.py | 8 +- CLI/actioner/sonic_cli_tpcm.py | 217 ++++++--- CLI/clitree/cli-xml/interface.xml | 95 +++- CLI/clitree/cli-xml/sonic_types.xml | 9 +- CLI/clitree/cli-xml/tpcm.xml | 103 +++- .../templates/show_interface_advertise_one.j2 | 4 +- CLI/renderer/templates/show_interface_fec.j2 | 51 ++ CLI/renderer/templates/show_interface_id.j2 | 4 +- .../templates/show_interface_portchannel.j2 | 2 + .../templates/show_interface_unlos.j2 | 49 ++ 20 files changed, 1054 insertions(+), 211 deletions(-) create mode 100644 CLI/actioner/sonic_cli_if_eth.py create mode 100644 CLI/actioner/sonic_cli_if_status.py create mode 100644 CLI/renderer/templates/show_interface_fec.j2 create mode 100644 CLI/renderer/templates/show_interface_unlos.j2 diff --git a/CLI/actioner/show_config_data.py b/CLI/actioner/show_config_data.py index 98ff7d5f59..750875f77f 100644 --- a/CLI/actioner/show_config_data.py +++ b/CLI/actioner/show_config_data.py @@ -231,6 +231,7 @@ "if_autoneg": show_if_autoneg, "if_fec": show_if_fec, "if_speed": show_if_speed, + "if_unlos": show_if_unlos, "tacacs_server_source_if": show_tacacs_source_if, "dns_server_source_if": show_dns_source_if, "ntp_server_source_if": show_ntp_source_if, diff --git a/CLI/actioner/show_config_interface.py b/CLI/actioner/show_config_interface.py index fa1870486e..ee0b65193c 100644 --- a/CLI/actioner/show_config_interface.py +++ b/CLI/actioner/show_config_interface.py @@ -312,12 +312,28 @@ def show_if_fec(render_tables): if port.get("ifname") != ifname_key: continue fec = port.get("fec") - if fec not in ['rs', 'RS', 'fc', 'FC']: + if fec not in ['rs', 'RS', 'fc', 'FC', 'auto', 'AUTO']: continue cmd_str = "fec {}".format(fec.upper()) return "CB_SUCCESS", cmd_str +def show_if_unlos(render_tables): + cmd_str = "" + + if "name" in render_tables: + ifname_key = render_tables["name"] + if "sonic-port:sonic-port/PORT/PORT_LIST" in render_tables: + for port in render_tables["sonic-port:sonic-port/PORT/PORT_LIST"]: + if port.get("ifname") != ifname_key: + continue + mode = port.get("unreliable_los") + if mode not in ['off', 'OFF', 'on', 'ON']: + continue + cmd_str = "unreliable-los {}".format(mode) + + return "CB_SUCCESS", cmd_str + def show_if_loopback(render_tables): cmd_str = "" diff --git a/CLI/actioner/show_running_config_nd.py b/CLI/actioner/show_running_config_nd.py index 1e586d4074..c3506d2635 100644 --- a/CLI/actioner/show_running_config_nd.py +++ b/CLI/actioner/show_running_config_nd.py @@ -62,9 +62,9 @@ def show_nd_running_intf_config(render_tables): elif "interval" in nd_cfg_intf: cmd_str += (nd_base_cmd + "ra-interval {}".format( nd_cfg_intf["interval"]) + cmd_end) - if "ra-lifetime" in nd_cfg_intf: + if "lifetime" in nd_cfg_intf: cmd_str += (nd_base_cmd + "ra-lifetime {}".format( - nd_cfg_intf["ra-lifetime"]) + cmd_end) + nd_cfg_intf["lifetime"]) + cmd_end) if "ra-retrans-interval" in nd_cfg_intf: cmd_str += (nd_base_cmd + "ra-retrans-interval {}".format( nd_cfg_intf["ra-retrans-interval"]) + cmd_end) diff --git a/CLI/actioner/sonic-cli-neighbors.py b/CLI/actioner/sonic-cli-neighbors.py index 5784b28b15..0dcc58ace3 100644 --- a/CLI/actioner/sonic-cli-neighbors.py +++ b/CLI/actioner/sonic-cli-neighbors.py @@ -19,6 +19,7 @@ from rpipe_utils import pipestr from collections import OrderedDict from scripts.render_cli import show_cli_output +from six.moves.urllib.parse import quote import json import socket import syslog as log @@ -198,7 +199,7 @@ def get_nd_intf_keypath(intf_name, config_add, param_name): sub_intf_index = 0 intf_name, sub_intf_index = get_nd_if_and_subif(intf_name) if 'Eth' in intf_name or 'Po' in intf_name: - keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(intf_name, sub_intf_index) + \ + keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(quote(intf_name, safe=""), sub_intf_index) + \ "openconfig-if-ip:ipv6/router-advertisement/" elif 'Vlan' in intf_name: keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/openconfig-vlan:routed-vlan/".format(intf_name) + \ @@ -214,7 +215,7 @@ def fill_nd_prefix_info(intf_name, output): api = cc.ApiClient() intf_name, sub_intf_index = get_nd_if_and_subif(intf_name) if 'Eth' in intf_name or 'Po' in intf_name: - keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(intf_name, sub_intf_index) + \ + keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(quote(intf_name, safe=""), sub_intf_index) + \ "openconfig-if-ip:ipv6/router-advertisement/openconfig-interfaces-ext:ra-prefixes" elif 'Vlan' in intf_name: keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/openconfig-vlan:routed-vlan/".format(intf_name) + \ @@ -235,7 +236,7 @@ def fill_nd_rdnss_info(intf_name, output): api = cc.ApiClient() intf_name, sub_intf_index = get_nd_if_and_subif(intf_name) if 'Eth' in intf_name or 'Po' in intf_name: - keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(intf_name, sub_intf_index) + \ + keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(quote(intf_name, safe=""), sub_intf_index) + \ "openconfig-if-ip:ipv6/router-advertisement/openconfig-interfaces-ext:rdnss-addresses" elif 'Vlan' in intf_name: keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/openconfig-vlan:routed-vlan/".format(intf_name) + \ @@ -256,7 +257,7 @@ def fill_nd_dnssl_info(intf_name, output): api = cc.ApiClient() intf_name, sub_intf_index = get_nd_if_and_subif(intf_name) if 'Eth' in intf_name or 'Po' in intf_name: - keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(intf_name, sub_intf_index) + \ + keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/subinterfaces/subinterface={}/".format(quote(intf_name, safe=""), sub_intf_index) + \ "openconfig-if-ip:ipv6/router-advertisement/openconfig-interfaces-ext:dns-search-names" elif 'Vlan' in intf_name: keypath = "/restconf/data/openconfig-interfaces:interfaces/interface={}/openconfig-vlan:routed-vlan/".format(intf_name) + \ diff --git a/CLI/actioner/sonic_cli_if.py b/CLI/actioner/sonic_cli_if.py index 9c77b48cba..46a0a6b33d 100644 --- a/CLI/actioner/sonic_cli_if.py +++ b/CLI/actioner/sonic_cli_if.py @@ -369,7 +369,8 @@ def invoke_api(func, args=[]): "RS": "FEC_RS", "FC": "FEC_FC", "none": "FEC_DISABLED", - "default": "FEC_AUTO", + "default": "FEC_DEFAULT", + "AUTO": "FEC_AUTO" } fec = args[1] diff --git a/CLI/actioner/sonic_cli_if_autoneg.py b/CLI/actioner/sonic_cli_if_autoneg.py index 3a56f3d320..55fecc2aac 100644 --- a/CLI/actioner/sonic_cli_if_autoneg.py +++ b/CLI/actioner/sonic_cli_if_autoneg.py @@ -37,67 +37,8 @@ aa = cc.ApiClient() -platform_dict = {} -def initPlatformDict(): - global platform_dict - if len(platform_dict) != 0: - return - - file = "/usr/share/sonic/hwsku/platform-def.json" - if os.path.exists(file): - with open(file) as json_file: - platform_dict = json.load(json_file) - for id in platform_dict['native-port-supported-speeds'].keys(): - ports = getRangedPortList(id) - lanes = platform_dict['native-port-supported-speeds'][id].keys() - for lane in lanes: - num = int(lane) - iii = 0 - while iii < len(ports): - intf = ports[iii] - spds = platform_dict['native-port-supported-speeds'][id][lane] - platform_dict[intf] = spds - iii += num - - file = "/usr/share/sonic/hwsku/platform.json" - if os.path.exists(file): - with open(file) as json_file: - platform_dict['brkout'] = json.load(json_file) - - # alias map - if 'brkout' in platform_dict: - platform_dict['alias_map'] = {} - for phys, info in platform_dict['brkout'].items(): - alias_list = info['alias_at_lanes'].replace(' ', '').split(',') - if len(alias_list) == 1: - a = alias_list[0] - platform_dict['alias_map'][a] = phys - elif len(alias_list) > 1: - a = alias_list[0] - p = a[:len(a) - 2] - b = int(phys[8:]) - platform_dict['alias_map'][p] = phys - i = 0 - for a in alias_list: - platform_dict['alias_map'][a] = "Ethernet{}".format(b + i) - i += 1 - -def getPortPhysicalName(port): - if port is None: - return port - if '/' not in port: - return port - if 'alias_map' not in platform_dict: - return port - if port not in platform_dict['alias_map']: - return port - return platform_dict['alias_map'][port] - asic_id = 0 def hasAutoNegSupport(port=None): - if port is not None: - port_cfg = getPortConfig(port) - port = getPortPhysicalName(port) # Check for switch chip id global asic_id @@ -119,23 +60,25 @@ def hasAutoNegSupport(port=None): except: asic_id = 0 - # TH, TH2 are not supported + # Abort if it's not a supported chip (e.g. TH, TH+, TH2) if (asic_id & 0xfff0) in [0xb930, 0xb960, 0xb970]: return False - # TH3, TD4: 1-lane mode is not supported, as they're non-official port mode - if ((asic_id & 0xfff0) in [0xb980, 0xb880, 0xb780]) and (port is not None): - lanes = port_cfg.get('lanes', '0').replace(' ', '').split(',') - if len(lanes) == 1: - return False + # Skip if this is not a per-port capability check + if port is None: + return True - # TD3: merlin port is not supported - if ((asic_id & 0xfff0) in [0xb870]) and (port is not None): - brkout = platform_dict.get('brkout') - if (brkout is not None) and (port in brkout): - lanes = brkout[port].get('lanes', '0').replace(' ', '').split(',') - if (len(lanes) == 1) and (lanes[0] in ['128', '129']): - return False + # Skip if it's a mgmt. port + port_cfg = getPortConfig(port) + lanes = port_cfg.get('lanes', '0').replace(' ', '').split(',') + if len(lanes) == 0: + return False + if len(lanes) == 1: + # TD3 + if (asic_id & 0xfff0) in [0xb870]: + return int(lanes[0]) in range(1, 128) + # HR4, MV2, HX5, TH2, TH3, TD4 + return int(lanes[0]) in range(1, 257) return True @@ -242,41 +185,28 @@ def getPortInfo(if_list): def getPortValidSpeeds(port): port_cfg = getPortConfig(port) - - # Is a breakout port? - is_brkout = False - cur_lanes = port_cfg.get('lanes', '0').replace(' ', '').split(',') - cur_speed = port_cfg.get('speed', '0') - if 'brkout' in platform_dict: - phys = getPortPhysicalName(port) - if phys in platform_dict['brkout']: - def_lanes = platform_dict['brkout'][phys].get('lanes', '0').replace(' ', '').split(',') - is_brkout = (len(cur_lanes) < len(def_lanes)) - else: - is_brkout = True - if is_brkout: - return [cur_speed] - - # Return current speed or the valid speed list in the platform-def.json - val_speed = platform_dict.get(getPortPhysicalName(port)) - if val_speed is None: + lanes = port_cfg.get('lanes', '0').replace(' ', '').split(',') + speed = port_cfg.get('speed', '0') + valid_speeds = port_cfg.get('valid_speeds', speed).replace(' ', '').split(',') + if valid_speeds is None or len(valid_speeds) == 0: # TD3-X7: Valid speed list could be unavailable if it's a member of port-group - if ((asic_id & 0xfff0) in [0xb870]) and (len(cur_lanes) == 1): - if int(cur_speed) == 25000: + if ((asic_id & 0xfff0) in [0xb870]) and (len(lanes) == 1): + if int(speed) == 25000: return ['25000'] - elif int(cur_speed) in [10000, 1000]: + elif int(speed) in [10000, 1000]: return ['10000', '1000'] - return [cur_speed] - return val_speed + return [speed] + return valid_speeds def getPortConfig(port): port = port.replace("/", "%2F") link = "/restconf/data/sonic-port:sonic-port/PORT/PORT_LIST={}".format(port) path = cc.Path(link) resp = aa.get(path) + conf = None if resp.ok() and (resp.content is not None): - return resp.content.get('sonic-port:PORT_LIST', [{}])[0] - return {} + conf = resp.content.get('sonic-port:PORT_LIST', [{}])[0] + return {} if conf is None else conf def run(func, args): path = None @@ -284,8 +214,6 @@ def run(func, args): if_list = [] if_dict = OrderedDict() - initPlatformDict() - if not hasAutoNegSupport(): print("Error: This feature is not available on the current platform") return diff --git a/CLI/actioner/sonic_cli_if_eth.py b/CLI/actioner/sonic_cli_if_eth.py new file mode 100644 index 0000000000..47928c7670 --- /dev/null +++ b/CLI/actioner/sonic_cli_if_eth.py @@ -0,0 +1,441 @@ +#!/usr/bin/python3 +########################################################################### +# +# Copyright 2021 Broadcom. The term Broadcom refers to Broadcom Inc. and/or +# its subsidiaries. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + +try: + import os + import sys + import json + import subprocess + + from natsort import natsorted + from collections import OrderedDict + from rpipe_utils import pipestr + from scripts.render_cli import show_cli_output + from sonic_cli_if_range import eth_intf_range_expand + + import cli_client as cc + import sonic_intf_utils as ifutils +except Exception as ex: + print(("Ex: {}".format(ex))) + +aa = cc.ApiClient() + +platform_dict = {} +def initPlatformDict(): + global platform_dict + if len(platform_dict) != 0: + return + + file = "/usr/share/sonic/hwsku/platform-def.json" + if os.path.exists(file): + with open(file) as json_file: + platform_dict = json.load(json_file) + for id in platform_dict['native-port-supported-speeds'].keys(): + ports = getRangedPortList(id) + lanes = platform_dict['native-port-supported-speeds'][id].keys() + for lane in lanes: + num = int(lane) + iii = 0 + while iii < len(ports): + intf = ports[iii] + spds = platform_dict['native-port-supported-speeds'][id][lane] + platform_dict[intf] = spds + iii += num + + file = "/usr/share/sonic/hwsku/platform.json" + if os.path.exists(file): + with open(file) as json_file: + platform_dict['brkout'] = json.load(json_file) + + # alias map + if 'brkout' in platform_dict: + platform_dict['alias_map'] = {} + for phys, info in platform_dict['brkout'].items(): + alias_list = info['alias_at_lanes'].replace(' ', '').split(',') + if len(alias_list) == 1: + a = alias_list[0] + platform_dict['alias_map'][a] = phys + elif len(alias_list) > 1: + a = alias_list[0] + p = a[:len(a) - 2] + b = int(phys[8:]) + platform_dict['alias_map'][p] = phys + i = 0 + for a in alias_list: + platform_dict['alias_map'][a] = "Ethernet{}".format(b + i) + i += 1 + +def getPortPhysicalName(port): + if port is None: + return port + if '/' not in port: + return port + if 'alias_map' not in platform_dict: + return port + if port not in platform_dict['alias_map']: + return port + return platform_dict['alias_map'][port] + +asic_id = 0 +def hasAutoNegSupport(port=None): + if port is not None: + port_cfg = getPortConfig(port) + port = getPortPhysicalName(port) + + # Check for switch chip id + global asic_id + if asic_id == 0: + try: + if os.path.exists("/sys/bus/pci/drivers/linux-kernel-bde"): + mm = subprocess.check_output( + "cat /sys/bus/pci/drivers/linux-kernel-bde/*/device | head -1", + shell=True, + ) + elif os.path.exists("/sys/bus/pci/drivers/linux_ngbde"): + mm = subprocess.check_output( + "cat /sys/bus/pci/drivers/linux_ngbde/*/device | head -1", + shell=True, + ) + else: + mm = "0" + asic_id = int(mm.strip(), 16) + except: + asic_id = 0 + + # TH, TH2 are not supported + if (asic_id & 0xfff0) in [0xb930, 0xb960, 0xb970]: + return False + + # TH3, TD4: 1-lane mode is not supported, as they're non-official port mode + if ((asic_id & 0xfff0) in [0xb980, 0xb880, 0xb780]) and (port is not None): + lanes = port_cfg.get('lanes', '0').replace(' ', '').split(',') + if len(lanes) == 1: + return False + + # TD3: merlin port is not supported + if ((asic_id & 0xfff0) in [0xb870]) and (port is not None): + brkout = platform_dict.get('brkout') + if (brkout is not None) and (port in brkout): + lanes = brkout[port].get('lanes', '0').replace(' ', '').split(',') + if (len(lanes) == 1) and (lanes[0] in ['128', '129']): + return False + + return True + + +def getRangedPortList(name): + if name is None: + return [] + + if (not name.startswith("Eth")) or (("-" not in name) and + ("," not in name)): + return [name] + + if name.startswith("Ethernet"): + prefix = "Ethernet" + else: + prefix = "Eth" + + list = [] + try: + for tok in name[len(prefix):].split(","): + if "-" in tok: + ids = tok.split("-") + if len(ids) < 2: + continue + if prefix == "Eth": + a = int(ids[0][2:], 10) + else: + a = int(ids[0], 10) + if prefix == "Eth": + b = int(ids[1][2:], 10) + else: + b = int(ids[1], 10) + if a > b: + c = a + a = b + b = c + for id in range(a, b + 1, 1): + if prefix == "Eth": + port = "{0}1/{1}".format(prefix, id) + else: + port = "{0}{1}".format(prefix, id) + if port not in list: + list.append(port) + else: + port = "{0}{1}".format(prefix, tok) + if port not in list: + list.append("{0}{1}".format(prefix, tok)) + except: + pass + + # print("list: '{}'".format(list)) + return list + + +def getFilteredPortList(if_name=None): + list = [] + head = "sonic-port:PORT_LIST" + path = cc.Path("/restconf/data/sonic-port:sonic-port/PORT/PORT_LIST") + resp = aa.get(path) + if resp.ok() and (resp.content is not None) and (head in resp.content): + if if_name is None: + filter = [] + else: + filter = eth_intf_range_expand(if_name) + for port in resp.content[head]: + name = port.get("ifname") + if (name is None) or (not name.startswith("Eth")): + continue + if len(filter) > 0: + if name in filter: + list.append(name) + else: + list.append(name) + return list + + +def getPortInfo(if_list): + if_dict = OrderedDict() + for intf in natsorted(if_list): + if_dict[intf] = {} + + link = "/restconf/data/openconfig-interfaces:interfaces/interface={0}/state".format( + intf.replace("/", "%2F")) + resp = aa.get(cc.Path(link)) + if resp is None or not resp.ok(): + continue + if_dict[intf].update(resp.content) + + link = "/restconf/data/openconfig-interfaces:interfaces/interface={0}/openconfig-if-ethernet:ethernet/state".format( + intf.replace("/", "%2F")) + resp = aa.get(cc.Path(link)) + if resp is None or not resp.ok(): + continue + if_dict[intf].update(resp.content) + + link = "/restconf/data/openconfig-platform:components/component={0}/openconfig-platform-transceiver:transceiver/state".format( + intf.replace("/", "%2F")) + resp = aa.get(cc.Path(link)) + if resp is None or not resp.ok() or resp.content is None: + continue + if_dict[intf].update(resp.content) + + return if_dict + +def getPortValidSpeeds(port): + port_cfg = getPortConfig(port) + + # Is a breakout port? + is_brkout = False + cur_lanes = port_cfg.get('lanes', '0').replace(' ', '').split(',') + cur_speed = port_cfg.get('speed', '0') + if 'brkout' in platform_dict: + phys = getPortPhysicalName(port) + if phys in platform_dict['brkout']: + def_lanes = platform_dict['brkout'][phys].get('lanes', '0').replace(' ', '').split(',') + is_brkout = (len(cur_lanes) < len(def_lanes)) + else: + is_brkout = True + if is_brkout: + return [cur_speed] + + # Return current speed or the valid speed list in the platform-def.json + val_speed = platform_dict.get(getPortPhysicalName(port)) + if val_speed is None: + # TD3-X7: Valid speed list could be unavailable if it's a member of port-group + if ((asic_id & 0xfff0) in [0xb870]) and (len(cur_lanes) == 1): + if int(cur_speed) == 25000: + return ['25000'] + elif int(cur_speed) in [10000, 1000]: + return ['10000', '1000'] + return [cur_speed] + return val_speed + +def getPortConfig(port): + port = port.replace("/", "%2F") + link = "/restconf/data/sonic-port:sonic-port/PORT/PORT_LIST={}".format(port) + path = cc.Path(link) + resp = aa.get(path) + if resp.ok() and (resp.content is not None): + return resp.content.get('sonic-port:PORT_LIST', [{}])[0] + return {} + +def run(func, args): + path = None + if_name = None if len(args) < 1 else args[0] + if_list = [] + if_dict = OrderedDict() + + initPlatformDict() + + if not hasAutoNegSupport(): + print("Error: This feature is not available on the current platform") + return + + if func == "show_ocif_ethernet_advertise": + if_list = getFilteredPortList(if_name) + if len(if_list) < 1: + return + if_dict = getPortInfo(if_list) + if len(if_list) > 1: + show_cli_output("show_interface_advertise.j2", if_dict) + else: + show_cli_output("show_interface_advertise_one.j2", if_dict) + + elif func == "show_ocif_ethernet_link_training": + if_list = getFilteredPortList(if_name) + if len(if_list) < 1: + return + if_dict = getPortInfo(if_list) + show_cli_output("show_interface_link_training.j2", if_dict) + + elif func == "patch_ocif_eth_autoneg": + if if_name is not None: + if_list = if_name.split(",") + else: + if_list = [] + autoneg = True if len(args) > 1 and args[1] == "on" else False + advspds_admin = ("" if len(args) < 3 or args[2] is None or args[2] == "null" + else args[2]) + advspds_admin = advspds_admin.replace(' ', '') + + info = [] + for port in if_list: + advspds = advspds_admin + if autoneg and not hasAutoNegSupport(port): + print( + ("%Error: AutoNeg is not supported on {}".format(port))) + return + if autoneg: + valid_speeds = getPortValidSpeeds(port) + if len(advspds) == 0: + advspds = ",".join(valid_speeds) + advspds_list = list(dict.fromkeys(advspds.split(','))) + bailout = False + for speed in advspds_list: + if not speed.isdigit(): + print("%Error: Invalid speed detected in '{}'".format(advspds)) + break + if speed not in valid_speeds: + print("%Error: Speed {} is not supported on {}, valid speeds={}".format(speed, port, ",".join(valid_speeds))) + bailout = True + break + if bailout: + return + advspds = ",".join(advspds_list) + data = { + "name": port, + "openconfig-if-ethernet:ethernet": { + "config": { + "auto-negotiate": autoneg, + "openconfig-if-ethernet-ext2:advertised-speed": + advspds, + } + }, + } + info.append(data) + + if len(info) == 0: + return + + body = {"openconfig-interfaces:interfaces": {"interface": info}} + path = cc.Path("/restconf/data/openconfig-interfaces:interfaces") + response = {} + response = aa.patch(path, body) + if response.ok(): + return + else: + print((response.error_message())) + return + + elif func == "patch_ocif_eth_link_training": + if if_name is not None: + if_list = if_name.split(",") + else: + if_list = [] + mode = True if len(args) > 1 and args[1] == "on" else False + + info = [] + for port in if_list: + if mode and not hasAutoNegSupport(port): + print( + ("%Error: Link-Training is not supported on {}".format(port))) + continue + data = { + "name": port, + "openconfig-if-ethernet:ethernet": { + "config": { + "openconfig-if-ethernet-ext2:standalone-link-training": + mode + } + }, + } + info.append(data) + + if len(info) == 0: + return + + body = {"openconfig-interfaces:interfaces": {"interface": info}} + path = cc.Path("/restconf/data/openconfig-interfaces:interfaces") + aa.patch(path, body) + + elif func == "patch_ocif_eth_unlos": + if if_name is not None: + if_list = if_name.split(",") + else: + if_list = [] + mode = args[1] if len(args) > 1 else "auto" + mmap = { + 'auto': 'UNRELIABLE_LOS_MODE_AUTO', + 'off': 'UNRELIABLE_LOS_MODE_OFF', + 'on': 'UNRELIABLE_LOS_MODE_ON' + } + + if mode not in mmap: + return + + info = [] + for port in if_list: + data = { + "name": port, + "openconfig-if-ethernet:ethernet": { + "config": { + "openconfig-if-ethernet-ext2:unreliable-los": + mmap[mode] + } + }, + } + info.append(data) + + if len(info) == 0: + return + + body = {"openconfig-interfaces:interfaces": {"interface": info}} + path = cc.Path("/restconf/data/openconfig-interfaces:interfaces") + aa.patch(path, body) + + return + + +if __name__ == "__main__": + pipestr().write(sys.argv) + # pdb.set_trace() + run(sys.argv[1], sys.argv[2:]) diff --git a/CLI/actioner/sonic_cli_if_range.py b/CLI/actioner/sonic_cli_if_range.py index ef6348608d..f5a9863328 100755 --- a/CLI/actioner/sonic_cli_if_range.py +++ b/CLI/actioner/sonic_cli_if_range.py @@ -396,7 +396,8 @@ def generate_body(func, args=[]): "RS": "FEC_RS", "FC": "FEC_FC", "none": "FEC_DISABLED", - "default": "FEC_AUTO", + "default": "FEC_DEFAULT", + "AUTO": "FEC_AUTO" } fec = args[1] if fec not in list(fec_map.keys()): diff --git a/CLI/actioner/sonic_cli_if_status.py b/CLI/actioner/sonic_cli_if_status.py new file mode 100644 index 0000000000..9d777610d0 --- /dev/null +++ b/CLI/actioner/sonic_cli_if_status.py @@ -0,0 +1,116 @@ +#!/usr/bin/python3 +########################################################################### +# +# Copyright 2022 Broadcom. The term Broadcom refers to Broadcom Inc. and/or +# its subsidiaries. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + +try: + import os + import sys + import json + import subprocess + + from natsort import natsorted + from collections import OrderedDict + from rpipe_utils import pipestr + from scripts.render_cli import show_cli_output + from sonic_cli_if_range import eth_intf_range_expand + + import cli_client as cc + import sonic_intf_utils as ifutils +except Exception as ex: + print(("Ex: {}".format(ex))) + +aa = cc.ApiClient() + +def getFilteredPortList(if_name=None): + list = [] + head = "sonic-port:PORT_LIST" + path = cc.Path("/restconf/data/sonic-port:sonic-port/PORT/PORT_LIST") + resp = aa.get(path) + if resp.ok() and (resp.content is not None) and (head in resp.content): + if if_name is None: + filter = [] + else: + filter = eth_intf_range_expand(if_name) + for port in resp.content[head]: + name = port.get("ifname") + if (name is None) or (not name.startswith("Eth")): + continue + if len(filter) > 0: + if name in filter: + list.append(name) + else: + list.append(name) + return list + + +def getPortInfo(if_list): + if_dict = OrderedDict() + for intf in natsorted(if_list): + if_dict[intf] = {} + + link = "/restconf/data/openconfig-interfaces:interfaces/interface={0}/state".format( + intf.replace("/", "%2F")) + resp = aa.get(cc.Path(link)) + if resp is None or not resp.ok(): + continue + if_dict[intf].update(resp.content) + + link = "/restconf/data/openconfig-interfaces:interfaces/interface={0}/openconfig-if-ethernet:ethernet/state".format( + intf.replace("/", "%2F")) + resp = aa.get(cc.Path(link)) + if resp is None or not resp.ok(): + continue + if_dict[intf].update(resp.content) + + link = "/restconf/data/openconfig-platform:components/component={0}/openconfig-platform-transceiver:transceiver/state".format( + intf.replace("/", "%2F")) + resp = aa.get(cc.Path(link)) + if resp is None or not resp.ok() or resp.content is None: + continue + if_dict[intf].update(resp.content) + + return if_dict + +def run(func, args): + path = None + if_name = None if len(args) < 1 else args[0] + if_list = [] + if_dict = OrderedDict() + + if func == "show_ocif_ethernet_fec": + if_list = getFilteredPortList(if_name) + if len(if_list) < 1: + return + if_dict = getPortInfo(if_list) + show_cli_output("show_interface_fec.j2", if_dict) + + elif func == "show_ocif_ethernet_unlos": + if_list = getFilteredPortList(if_name) + if len(if_list) < 1: + return + if_dict = getPortInfo(if_list) + show_cli_output("show_interface_unlos.j2", if_dict) + + return + + +if __name__ == "__main__": + pipestr().write(sys.argv) + # pdb.set_trace() + run(sys.argv[1], sys.argv[2:]) diff --git a/CLI/actioner/sonic_cli_network_tools.py b/CLI/actioner/sonic_cli_network_tools.py index 91a0460621..de78b83f2e 100644 --- a/CLI/actioner/sonic_cli_network_tools.py +++ b/CLI/actioner/sonic_cli_network_tools.py @@ -32,7 +32,7 @@ def do_cmd(args, func, vrfName): if len(vrfName) > 0: if vrfName.lower() == "mgmt": - cmd = "sudo /bin/ip vrf exec " + vrfName + " " + func + " " + args + cmd = "sudo /usr/bin/ip vrf exec " + vrfName + " " + func + " " + args else: cmd = func + " " + intfSwitch + " " + vrfName + " " + args else: diff --git a/CLI/actioner/sonic_cli_snmp.py b/CLI/actioner/sonic_cli_snmp.py index 662cc554f5..43339ea4d5 100755 --- a/CLI/actioner/sonic_cli_snmp.py +++ b/CLI/actioner/sonic_cli_snmp.py @@ -233,6 +233,8 @@ def findKeyForTargetEntry(ipAddr): for key, table in list(response.content.items()): while len(table) > 0: data = table.pop(0) + if 'udp' not in data: + return "None" udp = data["udp"] if udp["ip"] == ipAddr: return data["name"] @@ -1131,8 +1133,12 @@ def invoke(func, args): [] for i in range(4)) while len(table) > 0: data = table.pop(0) + if 'udp' not in data: + continue h = {} - h["target"] = data["target-params"] + if "target-params" in data: + h["target"] = data["target-params"] + h["security-name"] = " " udp = data["udp"] h["ipaddr"] = udp["ip"] h["port"] = udp["port"] diff --git a/CLI/actioner/sonic_cli_tpcm.py b/CLI/actioner/sonic_cli_tpcm.py index 44fa53d3af..1fa1ff5dad 100644 --- a/CLI/actioner/sonic_cli_tpcm.py +++ b/CLI/actioner/sonic_cli_tpcm.py @@ -2,52 +2,102 @@ import cli_client as cc from scripts.render_cli import show_cli_output - -def run_tpcm_list(argv): +def run_tpcm_list(func, argv): aa = cc.ApiClient() + keypath = cc.Path('/restconf/operations/openconfig-tpcm:tpcm-list') templ = argv[0] - path = cc.Path("/restconf/data/openconfig-tpcm:tpcm/state/tpcm-image-list") - api_response = aa.get(path) + + body = build_body(func, None, argv) + + api_response = aa.post(keypath, body) + if api_response.ok(): if api_response.content is not None: response = api_response.content show_cli_output(templ, response) + else: + print(api_response.error_message()) +def convert_list_to_str(args_list): + args_str = "" + for el in args_list: + if el == '"': + args_str += '\\"' + else: + args_str += el + return (args_str) def build_body(func, method, argv): - body = "" - args_list = [] - parameters = { - "args": "string", - "skip": "string", - "docker-name": "string", - "image-name": "string", - "remote-server": "string", - "username": "string", - "password": "string", - } - if func == "tpcm_uninstall": - if argv[2] != "null": + body="" + args_list=[] + cargs_list=[] + parameters = { "args" : "string", + "cargs" : "string", + "vrf-name" : "string", + "mem-limit" : "string", + "start-after-system-ready" : "string", + "skip" : "string", + "docker-name" : "string", + "image-name" : "string", + "remote-server" : "string", + "username" : "string", + "type-name" : "string", + "key-name" : "string", + "field-value" : "string", + "password" : "string", + "disk-limit" : "string"} + if func == 'tpcm_uninstall': + if argv[2] != 'null': parameters["skip"] = argv[2] parameters["docker-name"] = argv[0] + elif func == 'tpcm_show': + parameters["docker-name"] = argv[0] + elif func == 'tpcm_update': + if argv[2] == "name": + parameters["docker-name"] = argv[3] + elif argv[2] == "disk-limit": + parameters["disk-limit"] = argv[3] + if 'vrf-name' in argv: + value_index = argv.index('vrf-name')+1 + parameters["vrf-name"] = argv[value_index] + if 'memory' in argv: + value_index = argv.index('memory')+1 + parameters["mem-limit"] = argv[value_index] + if 'start-after-system-ready' in argv: + value_index = argv.index('start-after-system-ready')+1 + parameters["start-after-system-ready"] = argv[value_index] + elif func == 'tpcm_list': + if 'vrf-name' in argv: + value_index = argv.index('vrf-name')+1 + parameters["vrf-name"] = argv[value_index] else: - if func == "tpcm_install": + if func == 'tpcm_install': parameters["docker-name"] = argv[4] - if "args" in argv: - value_index = argv.index("args") + 1 - args_list = argv[value_index:] - - if func == "tpcm_upgrade": + if 'vrf-name' in argv: + value_index = argv.index('vrf-name')+1 + parameters["vrf-name"] = argv[value_index] + if 'args' in argv: + value_index = argv.index('args')+1 + args_list = argv[value_index] + if 'cargs' in argv: + value_index = argv.index('cargs')+1 + cargs_list = argv[value_index] + if 'start-after-system-ready' in argv: + value_index = argv.index('start-after-system-ready')+1 + parameters["start-after-system-ready"] = argv[value_index] + + if func == 'tpcm_upgrade': parameters["docker-name"] = argv[4] - if "skip_data_migration" in argv: - value_index = argv.index("skip_data_migration") + 1 + if 'skip-data-migration' in argv: + value_index = argv.index('skip-data-migration') + 1 parameters["skip"] = argv[value_index] - if "args" in argv: - value_index = argv.index("args") + 1 - if '"' in argv[value_index]: - args_list = argv[value_index:] - else: - args_list = argv[value_index] + if 'args' in argv: + value_index = argv.index('args') + 1 + args_list = argv[value_index] + if 'cargs' in argv: + value_index = argv.index('cargs')+1 + cargs_list = argv[value_index] + if method == "scp" or method == "sftp": parameters["remote-server"] = argv[6] @@ -58,47 +108,28 @@ def build_body(func, method, argv): parameters["image-name"] = argv[6] if args_list: - parameters["args"] = " ".join(args_list) - - if func == "tpcm_install": - body = { - "openconfig-tpcm:input": { - "docker-name": parameters["docker-name"], - "image-source": method, - "image-name": parameters["image-name"], - "remote-server": parameters["remote-server"], - "username": parameters["username"], - "password": parameters["password"], - "args": parameters["args"], - } - } - - elif func == "tpcm_upgrade": - body = { - "openconfig-tpcm:input": { - "docker-name": parameters["docker-name"], - "image-source": method, - "image-name": parameters["image-name"], - "remote-server": parameters["remote-server"], - "username": parameters["username"], - "password": parameters["password"], - "skip-data-migration": parameters["skip"], - "args": parameters["args"], - } - } - elif func == "tpcm_uninstall": - body = { - "openconfig-tpcm:input": { - "docker-name": parameters["docker-name"], - "clean-data": parameters["skip"], - } - } + parameters['args'] = convert_list_to_str(args_list) + if cargs_list: + parameters['cargs'] = convert_list_to_str(cargs_list) + + if func == 'tpcm_install': + body = {"openconfig-tpcm:input":{"docker-name":parameters['docker-name'],"image-source":method,"image-name":parameters['image-name'],"remote-server":parameters['remote-server'],"username":parameters['username'],"password":parameters['password'],"args":parameters['args'], "cargs":parameters['cargs'], "vrf-name":parameters['vrf-name'], "start-after-system-ready":parameters['start-after-system-ready']}} + elif func == 'tpcm_upgrade': + body = {"openconfig-tpcm:input":{"docker-name":parameters['docker-name'],"image-source":method,"image-name":parameters['image-name'],"remote-server":parameters['remote-server'],"username":parameters['username'],"password":parameters['password'],"skip-data-migration":parameters['skip'], "args":parameters['args'], "cargs":parameters['cargs']}} + elif func == 'tpcm_uninstall': + body = {"openconfig-tpcm:input":{"docker-name":parameters['docker-name'],"clean-data":parameters['skip']}} + elif func == 'tpcm_show': + body = {"openconfig-tpcm:input":{"docker-name":parameters['docker-name']}} + elif func == 'tpcm_update': + body = {"openconfig-tpcm:input":{"docker-name":parameters['docker-name'], "disk-limit":parameters['disk-limit'], "vrf-name":parameters['vrf-name'], "mem-limit":parameters['mem-limit'], "start-after-system-ready":parameters['start-after-system-ready']}} + elif func == 'tpcm_list': + body = {"openconfig-tpcm:input":{"vrf-name":parameters['vrf-name']}} return body def run_tpcm_install(func, method, argv): aa = cc.ApiClient() - keypath = cc.Path("/restconf/operations/openconfig-tpcm:tpcm-install") + keypath = cc.Path('/restconf/operations/openconfig-tpcm:tpcm-install') templ = argv[0] body = build_body(func, method, argv) @@ -117,7 +148,7 @@ def run_tpcm_install(func, method, argv): def run_tpcm_upgrade(func, method, argv): aa = cc.ApiClient() - keypath = cc.Path("/restconf/operations/openconfig-tpcm:tpcm-upgrade") + keypath = cc.Path('/restconf/operations/openconfig-tpcm:tpcm-upgrade') templ = argv[0] body = build_body(func, method, argv) @@ -136,7 +167,7 @@ def run_tpcm_upgrade(func, method, argv): def run_tpcm_uninstall(func, method, argv): aa = cc.ApiClient() - keypath = cc.Path("/restconf/operations/openconfig-tpcm:tpcm-uninstall") + keypath = cc.Path('/restconf/operations/openconfig-tpcm:tpcm-uninstall') templ = argv[1] body = build_body(func, method, argv) @@ -150,16 +181,52 @@ def run_tpcm_uninstall(func, method, argv): response = api_response.content show_cli_output(templ, response) else: - print((api_response.error_message())) + print(api_response.error_message()) + +def run_tpcm_show(func, argv): + aa = cc.ApiClient() + keypath = cc.Path('/restconf/operations/openconfig-tpcm:tpcm-show') + templ = argv[0] + + body = build_body(func, None, argv[1:]) + + api_response = aa.post(keypath, body) + + if api_response.ok(): + if api_response.content is not None: + response = api_response.content + show_cli_output(templ, response) + else: + print(api_response.error_message()) + +def run_tpcm_update(func, argv): + aa = cc.ApiClient() + keypath = cc.Path('/restconf/operations/openconfig-tpcm:tpcm-update') + templ = argv[0] + + body = build_body(func, None, argv[1:]) + + api_response = aa.post(keypath, body) + + if api_response.ok(): + if api_response.content is not None: + response = api_response.content + show_cli_output(templ, response) + else: + print(api_response.error_message()) def run(func, args): - if func == "tpcm_list": - run_tpcm_list(args) - if func == "tpcm_install": + if func == 'tpcm_list': + run_tpcm_list(func, args) + if func == 'tpcm_install': run_tpcm_install(func, args[5], args[0:]) - if func == "tpcm_uninstall": + if func == 'tpcm_uninstall': run_tpcm_uninstall(func, args[0], args[1:]) - if func == "tpcm_upgrade": + if func == 'tpcm_upgrade': run_tpcm_upgrade(func, args[5], args[0:]) + if func == 'tpcm_show': + run_tpcm_show(func, args) + if func == 'tpcm_update': + run_tpcm_update(func, args) return diff --git a/CLI/clitree/cli-xml/interface.xml b/CLI/clitree/cli-xml/interface.xml index f75e812b07..9acbeac95d 100644 --- a/CLI/clitree/cli-xml/interface.xml +++ b/CLI/clitree/cli-xml/interface.xml @@ -212,10 +212,28 @@ limitations under the License. optional="true" /> + + + + + @@ -226,6 +244,25 @@ limitations under the License. optional="true" /> + + + + + + - sonic_cli_if_autoneg patch_ocif_eth_autoneg ${iface} "on" ${admin_advertise} + sonic_cli_if_eth patch_ocif_eth_autoneg ${iface} "on" ${admin_advertise} - sonic_cli_if_autoneg patch_ocif_eth_autoneg ${iface} "off" "" + sonic_cli_if_eth patch_ocif_eth_autoneg ${iface} "off" "" - sonic_cli_if_autoneg patch_ocif_eth_link_training ${iface} "on" + sonic_cli_if_eth patch_ocif_eth_link_training ${iface} "on" - sonic_cli_if_autoneg patch_ocif_eth_link_training ${iface} "off" + sonic_cli_if_eth patch_ocif_eth_link_training ${iface} "off" + + + + + sonic_cli_if_eth patch_ocif_eth_unlos ${iface} ${unlos} + + + sonic_cli_if_eth patch_ocif_eth_unlos ${iface} "auto" - sonic_cli_if_autoneg patch_ocif_eth_link_training ${iflist} "on" + sonic_cli_if_eth patch_ocif_eth_link_training ${iflist} "on" - sonic_cli_if_autoneg patch_ocif_eth_link_training ${iflist} "off" + sonic_cli_if_eth patch_ocif_eth_link_training ${iflist} "off" + + + + + sonic_cli_if_eth patch_ocif_eth_unlos ${iflist} ${unlos} + + + sonic_cli_if_eth patch_ocif_eth_unlos ${iflist} "auto" - sonic_cli_if_autoneg patch_ocif_eth_autoneg ${iflist} "on" ${admin_advertise} + sonic_cli_if_eth patch_ocif_eth_autoneg ${iflist} "on" ${admin_advertise} - sonic_cli_if_autoneg patch_ocif_eth_autoneg ${iflist} "off" "" + sonic_cli_if_eth patch_ocif_eth_autoneg ${iflist} "off" "" diff --git a/CLI/clitree/cli-xml/sonic_types.xml b/CLI/clitree/cli-xml/sonic_types.xml index cc7adc547e..890ec04a1a 100644 --- a/CLI/clitree/cli-xml/sonic_types.xml +++ b/CLI/clitree/cli-xml/sonic_types.xml @@ -936,10 +936,17 @@ limitations under the License. + + + + + + - - + + + + + sonic_cli_tpcm tpcm_show tpcm.j2 ${container_name} + + + + + + + sonic_cli_tpcm tpcm_list tpcm.j2 + builtin="clish_pyobj">sonic_cli_tpcm tpcm_list tpcm.j2 ${__full_line} @@ -103,11 +129,61 @@ ptype="STRING"> + + + + + + + + + + + + sonic_cli_tpcm tpcm_install tpcm.j2 ${__full_line} + + + + + + + + + + + + + + + + + + + + + + + + + + sonic_cli_tpcm tpcm_update tpcm.j2 ${__full_line} + + + - + + + + + sonic_cli_tpcm tpcm_upgrade tpcm.j2 ${__full_line} @@ -199,8 +282,8 @@ ptype="BOOL_SELECT"> - sonic_cli_tpcm tpcm_uninstall default ${container_name} tpcm.j2 ${skip} + + sonic_cli_tpcm tpcm_uninstall default ${container_name} tpcm.j2 ${skip} diff --git a/CLI/renderer/templates/show_interface_advertise_one.j2 b/CLI/renderer/templates/show_interface_advertise_one.j2 index b336f84dce..76b60d3630 100644 --- a/CLI/renderer/templates/show_interface_advertise_one.j2 +++ b/CLI/renderer/templates/show_interface_advertise_one.j2 @@ -32,8 +32,8 @@ {% set autoneg = "on" %} {% endif %} {% endif %} -{% if 'openconfig-if-ethernet-ext2:negotiated-port-fec' in data %} -{% set oper_fec = data['openconfig-if-ethernet-ext2:negotiated-port-fec'] %} +{% if 'openconfig-if-ethernet-ext2:oper-fec' in data %} +{% set oper_fec = data['openconfig-if-ethernet-ext2:oper-fec'] %} {% if 'FEC_RS' in oper_fec %} {% set oper_fec = 'RS' %} {% elif 'FEC_FC' in oper_fec %} diff --git a/CLI/renderer/templates/show_interface_fec.j2 b/CLI/renderer/templates/show_interface_fec.j2 new file mode 100644 index 0000000000..fc54e55d19 --- /dev/null +++ b/CLI/renderer/templates/show_interface_fec.j2 @@ -0,0 +1,51 @@ +{% if json_output -%} + +{{'Interface Type Oper Admin If-State'}} +{{'-------------- ---------------------------------------- ----- ----- -----------'}} + +{% for ifName in json_output %} + +{% set info = json_output[ifName] %} + +{% set present = '' %} +{% set type = '' %} +{% if 'openconfig-platform-transceiver:state' in info %} +{% set data = info['openconfig-platform-transceiver:state'] %} +{% if 'present' in data %} +{% set present = data['present'] %} +{% endif %} +{% if present == 'PRESENT' and 'display-name' in data %} +{% set type = data['display-name'] %} +{% endif %} +{% endif %} + +{% set port_fec = "" %} +{% set oper_fec = "none" %} + +{% if 'openconfig-if-ethernet:state' in info %} +{% set data = info['openconfig-if-ethernet:state'] %} + +{% if 'openconfig-if-ethernet-ext2:port-fec' in data %} +{% set fec = data['openconfig-if-ethernet-ext2:port-fec'] %} +{% set port_fec = fec|replace('openconfig-platform-types:FEC_','')|replace('openconfig-platform-ext:FEC_','')|replace('DISABLED','none')|lower() %} +{% endif %} + +{% if 'openconfig-if-ethernet-ext2:oper-fec' in data %} +{% set fec = data['openconfig-if-ethernet-ext2:oper-fec'] %} +{% set oper_fec = fec|replace('openconfig-platform-types:FEC_','')|replace('openconfig-platform-ext:FEC_','')|replace('DISABLED','none')|lower() %} +{% endif %} + +{% set reason = "" %} +{% if 'openconfig-if-ethernet:state' in info %} +{% set data = info['openconfig-if-ethernet:state'] %} +{% if 'openconfig-interfaces-ext:reason' in data %} +{% set reason = data['openconfig-interfaces-ext:reason']|lower()|replace('_','-') %} +{% endif %} +{% endif %} + +{% endif %} + +{{ifName.ljust(16)}}{{type[:40].ljust(42)}}{{oper_fec.ljust(7)}}{{port_fec.ljust(7)}}{{reason}} + +{% endfor %} +{% endif %} diff --git a/CLI/renderer/templates/show_interface_id.j2 b/CLI/renderer/templates/show_interface_id.j2 index ab1bbe9813..bc9000440d 100644 --- a/CLI/renderer/templates/show_interface_id.j2 +++ b/CLI/renderer/templates/show_interface_id.j2 @@ -67,7 +67,7 @@ {% if vars.update({'autoneg':'on'}) %}{% endif %} {% if interface['state']['oper-status'] == 'UP' and 'negotiated-port-speed' in interface[key]['state'] %} {% if vars.update({'speed':interface[key]['state']['negotiated-port-speed']|replace("openconfig-if-ethernet:SPEED_", "")}) %}{% endif %} - {% if vars.update({'fec':interface[key]["state"]["openconfig-if-ethernet-ext2:negotiated-port-fec"]|replace("openconfig-platform-types:FEC_", "")|replace("openconfig-platform-ext:FEC_", "")}) %}{% endif %} + {% if vars.update({'fec':interface[key]["state"]["openconfig-if-ethernet-ext2:oper-fec"]|replace("openconfig-platform-types:FEC_", "")|replace("openconfig-platform-ext:FEC_", "")}) %}{% endif %} {% else %} {% if vars.update({'speed':'auto'}) %}{% endif %} {% if vars.update({'fec':'auto'}) %}{% endif %} @@ -75,7 +75,7 @@ {% else %} {% if vars.update({'autoneg':'off'}) %}{% endif %} {% if vars.update({'speed':interface[key]["state"]["port-speed"]|replace("openconfig-if-ethernet:SPEED_", "")}) %}{% endif %} - {% if vars.update({'fec':interface[key]["state"]["openconfig-if-ethernet-ext2:port-fec"]|replace("openconfig-platform-types:FEC_", "")|replace("openconfig-platform-ext:FEC_", "")}) %}{% endif %} + {% if vars.update({'fec':interface[key]["state"]["openconfig-if-ethernet-ext2:oper-fec"]|replace("openconfig-platform-types:FEC_", "")|replace("openconfig-platform-ext:FEC_", "")}) %}{% endif %} {% endif %} {% if "openconfig-interfaces-ext:reason" in interface[key]["state"] %} {% if vars.update({'reason':interface[key]["state"]["openconfig-interfaces-ext:reason"]}) %}{% endif %} diff --git a/CLI/renderer/templates/show_interface_portchannel.j2 b/CLI/renderer/templates/show_interface_portchannel.j2 index 8beb050b55..6d2fe50203 100644 --- a/CLI/renderer/templates/show_interface_portchannel.j2 +++ b/CLI/renderer/templates/show_interface_portchannel.j2 @@ -43,8 +43,10 @@ {% if po_conf_intf['name'] == po_intf['lagname'] and 'fallback' in po_conf_intf %} +{% if po_conf_intf['fallback'] == True %} {% set fallback = "Enabled" %} {% endif %} +{% endif %} {{po_intf['lagname']}} is {{po_intf['admin_status']}}, line protocol is {{po_intf['oper_status']}}, reason {{po_intf['reason']|lower()|replace('_','-') }}, mode {{mode}} Hardware is PortChannel, address is {{vars.mac_address}} diff --git a/CLI/renderer/templates/show_interface_unlos.j2 b/CLI/renderer/templates/show_interface_unlos.j2 new file mode 100644 index 0000000000..8d7e4471e3 --- /dev/null +++ b/CLI/renderer/templates/show_interface_unlos.j2 @@ -0,0 +1,49 @@ +{% if json_output -%} + +{{'Interface Type Oper Admin If-State'}} +{{'-------------- ---------------------------------------- ----- ----- -----------'}} + +{% for ifName in json_output %} + +{% set info = json_output[ifName] %} + +{% set present = '' %} +{% set type = '' %} +{% if 'openconfig-platform-transceiver:state' in info %} +{% set data = info['openconfig-platform-transceiver:state'] %} +{% if 'present' in data %} +{% set present = data['present'] %} +{% endif %} +{% if present == 'PRESENT' and 'display-name' in data %} +{% set type = data['display-name'] %} +{% endif %} +{% endif %} + +{% set unlos = "auto" %} +{% if 'openconfig-if-ethernet:state' in info %} +{% set data = info['openconfig-if-ethernet:state'] %} +{% if 'openconfig-if-ethernet-ext2:unreliable-los' in data %} +{% set unlos = data['openconfig-if-ethernet-ext2:unreliable-los']|replace('openconfig-if-ethernet-ext2:UNRELIABLE_LOS_MODE_','')|lower() %} +{% endif %} +{% endif %} + +{% set oper_unlos = "off" %} +{% if 'openconfig-if-ethernet:state' in info %} +{% set data = info['openconfig-if-ethernet:state'] %} +{% if 'openconfig-if-ethernet-ext2:oper-unreliable-los' in data %} +{% set oper_unlos = "on" if 'MODE_ON' in data['openconfig-if-ethernet-ext2:oper-unreliable-los'] else "off" %} +{% endif %} +{% endif %} + +{% set reason = "" %} +{% if 'openconfig-if-ethernet:state' in info %} +{% set data = info['openconfig-if-ethernet:state'] %} +{% if 'openconfig-interfaces-ext:reason' in data %} +{% set reason = data['openconfig-interfaces-ext:reason']|lower()|replace('_','-') %} +{% endif %} +{% endif %} + +{{ifName.ljust(16)}}{{type[:40].ljust(42)}}{{oper_unlos.ljust(7)}}{{unlos.ljust(7)}}{{reason}} + +{% endfor %} +{% endif %}