[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:
Dmytro Shevchuk 2021-01-25 03:46:33 +02:00 committed by GitHub
parent 24df482e0e
commit dd0e1100a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 0 deletions

View File

@ -24,6 +24,7 @@ PORT_STR = "Ethernet"
BRKOUT_MODE = "default_brkout_mode"
CUR_BRKOUT_MODE = "brkout_mode"
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})\))?'
@ -250,6 +251,12 @@ def parse_platform_json_file(hwsku_json_file, platform_json_file):
brkout_mode = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE]
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)
if not ports:

View File

@ -14,4 +14,7 @@ test:
for f in $$(find ../../../device -name platform.json); do
./platform_json_checker $$f
done
for f in $$(find ../../../device -name hwsku.json); do
./hwsku_json_checker $$f
done
popd

View 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:])