[sonic-cfggen] parse optional fec and autoneg fields from hwsku.json (#6155)
**- Why I did it** For now `hwsku.json` and `platform.json` dont support optional fields. For example no way to add `fec` or `autoneg` field using `platform.json` and `hwsku.json`. **- How I did it** Added parsing of optional fields from hwsku.json. **- How to verify it** Add optional field to `hwsku.json`. After first boot will be generated new `config_db.json` or you can generate it using `sonic-cfggen` command. In this file must be optional field from `hwsku.json` or check using command `redis-cli hgetall PORT_TABLE:Ethernet0` Example of `hwsku.json`, that must be parsed: ``` { "interfaces": { "Ethernet0": { "default_brkout_mode": "1x100G[40G]", "fec": "rs", "autoneg": "0" }, ... } ``` Example of generated `config_db.json`: ``` "PORT": { "Ethernet0": { "alias": "Ethernet0", "lanes": "0,1,2,3", "speed": "100000", "index": "1", "admin_status": "up", "fec": "rs", "autoneg": "0", "mtu": "9100" }, ``` So, we can see this entries in redis db: ``` admin@sonic:~$ redis-cli hgetall PORT_TABLE:Ethernet0 1) "alias" 2) "Ethernet0" 3) "lanes" 4) "0,1,2,3" 5) "speed" 6) "100000" 7) "index" 8) "1" 9) "admin_status" 10) "up" 11) "fec" 12) "rs" 13) "autoneg" 14) "0" 15) "mtu" 16) "9100" 17) "description" 18) "" 19) "oper_status" 20) "up" ``` Also its way to fix `show interface status`, `FEC` field but also need add `FEC` field to `hwsku.json`. Before: ``` admin@sonic:~$ show interfaces status Interface Lanes Speed MTU FEC Alias Vlan Oper Admin Type Asym PFC ----------- --------------- ------- ----- ----- ----------- ------ ------ ------- --------------- ---------- Ethernet0 0,1,2,3 100G 9100 N/A Ethernet0 routed up up QSFP28 or later N/A ``` After: ``` admin@sonic:~$ show interfaces status Interface Lanes Speed MTU FEC Alias Vlan Oper Admin Type Asym PFC ----------- --------------- ------- ----- ----- ----------- ------ ------ ------- --------------- ---------- Ethernet0 0,1,2,3 100G 9100 rs Ethernet0 routed up up QSFP28 or later N/A ```
This commit is contained in:
parent
24df482e0e
commit
dd0e1100a5
@ -24,6 +24,7 @@ PORT_STR = "Ethernet"
|
|||||||
BRKOUT_MODE = "default_brkout_mode"
|
BRKOUT_MODE = "default_brkout_mode"
|
||||||
CUR_BRKOUT_MODE = "brkout_mode"
|
CUR_BRKOUT_MODE = "brkout_mode"
|
||||||
INTF_KEY = "interfaces"
|
INTF_KEY = "interfaces"
|
||||||
|
OPTIONAL_HWSKU_ATTRIBUTES = ["fec", "autoneg"]
|
||||||
|
|
||||||
BRKOUT_PATTERN = r'(\d{1,3})x(\d{1,3}G)(\[\d{1,3}G\])?(\((\d{1,3})\))?'
|
BRKOUT_PATTERN = r'(\d{1,3})x(\d{1,3}G)(\[\d{1,3}G\])?(\((\d{1,3})\))?'
|
||||||
|
|
||||||
@ -250,6 +251,12 @@ def parse_platform_json_file(hwsku_json_file, platform_json_file):
|
|||||||
brkout_mode = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE]
|
brkout_mode = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE]
|
||||||
|
|
||||||
child_ports = get_child_ports(intf, brkout_mode, platform_json_file)
|
child_ports = get_child_ports(intf, brkout_mode, platform_json_file)
|
||||||
|
|
||||||
|
# take optional fields from hwsku.json
|
||||||
|
for key, item in hwsku_dict[INTF_KEY][intf].items():
|
||||||
|
if key in OPTIONAL_HWSKU_ATTRIBUTES:
|
||||||
|
child_ports.get(intf)[key] = item
|
||||||
|
|
||||||
ports.update(child_ports)
|
ports.update(child_ports)
|
||||||
|
|
||||||
if not ports:
|
if not ports:
|
||||||
|
@ -14,4 +14,7 @@ test:
|
|||||||
for f in $$(find ../../../device -name platform.json); do
|
for f in $$(find ../../../device -name platform.json); do
|
||||||
./platform_json_checker $$f
|
./platform_json_checker $$f
|
||||||
done
|
done
|
||||||
|
for f in $$(find ../../../device -name hwsku.json); do
|
||||||
|
./hwsku_json_checker $$f
|
||||||
|
done
|
||||||
popd
|
popd
|
||||||
|
91
src/sonic-device-data/tests/hwsku_json_checker
Executable file
91
src/sonic-device-data/tests/hwsku_json_checker
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Global variable
|
||||||
|
PORT_ATTRIBUTES = ["default_brkout_mode"]
|
||||||
|
OPTIONAL_PORT_ATTRIBUTES = ["fec", "autoneg"]
|
||||||
|
PORT_REG = "Ethernet(\d+)"
|
||||||
|
HWSKU_JSON = '*hwsku.json'
|
||||||
|
INTF_KEY = "interfaces"
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print("Usage: " + sys.argv[0] + " <hwsku_json_file>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def check_port_attr(port_attr):
|
||||||
|
for each_key in port_attr:
|
||||||
|
if each_key not in PORT_ATTRIBUTES and each_key not in OPTIONAL_PORT_ATTRIBUTES:
|
||||||
|
print("Error: " + each_key + " is not the correct Port attribute.")
|
||||||
|
return False
|
||||||
|
if not port_attr[each_key]:
|
||||||
|
print("Error: " + each_key + " has no value.")
|
||||||
|
return False
|
||||||
|
if not isinstance(port_attr[each_key], str):
|
||||||
|
print("Error:value type of " + each_key + " must be string.")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def check_file(hwsku_json_file):
|
||||||
|
try:
|
||||||
|
hwsku_cap_file = open(hwsku_json_file,"r")
|
||||||
|
hwsku_data_data = hwsku_cap_file.read()
|
||||||
|
hwsku_dict = json.loads(hwsku_data_data)
|
||||||
|
|
||||||
|
for each_port in hwsku_dict[INTF_KEY]:
|
||||||
|
# Validate port at top level
|
||||||
|
port_id = re.search(PORT_REG, each_port)
|
||||||
|
if port_id is None:
|
||||||
|
print("Error: Unknown Interface " + str(each_port) + " at top level")
|
||||||
|
return False
|
||||||
|
|
||||||
|
port_attr = hwsku_dict[INTF_KEY][each_port]
|
||||||
|
|
||||||
|
# Check mandatory attributes
|
||||||
|
for each_key in PORT_ATTRIBUTES:
|
||||||
|
if each_key not in port_attr:
|
||||||
|
print("Error: " + each_key + " of " + each_port + " is/are missing")
|
||||||
|
return False
|
||||||
|
|
||||||
|
#Validate port attributes for each port
|
||||||
|
if not check_port_attr(port_attr):
|
||||||
|
return False
|
||||||
|
except IOError:
|
||||||
|
print("Error: Cannot open file " + hwsku_json_file)
|
||||||
|
return False
|
||||||
|
except ValueError as e:
|
||||||
|
print("Error in parsing json file " + hwsku_json_file + " ")
|
||||||
|
print(str(e))
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
if len(argv) > 0 and argv[0] == "-h":
|
||||||
|
usage()
|
||||||
|
|
||||||
|
# Load target file
|
||||||
|
if len(argv) == 0:
|
||||||
|
files = glob.glob(HWSKU_JSON)
|
||||||
|
else:
|
||||||
|
files = argv
|
||||||
|
|
||||||
|
all_good = True
|
||||||
|
|
||||||
|
for f in files:
|
||||||
|
good = check_file(f)
|
||||||
|
if good:
|
||||||
|
print("File " + f + " passed validity check")
|
||||||
|
else:
|
||||||
|
print("File " + f + " failed validity check")
|
||||||
|
|
||||||
|
all_good = all_good and good
|
||||||
|
|
||||||
|
if not all_good:
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv[1:])
|
Reference in New Issue
Block a user