2020-06-18 18:26:09 -05:00
|
|
|
try:
|
|
|
|
import ast
|
2020-11-20 12:58:48 -06:00
|
|
|
import json
|
|
|
|
import os
|
2020-06-18 18:26:09 -05:00
|
|
|
import re
|
2020-11-20 12:58:48 -06:00
|
|
|
import sys
|
|
|
|
|
2021-06-07 14:34:23 -05:00
|
|
|
from swsscommon import swsscommon
|
2020-09-04 12:19:12 -05:00
|
|
|
from sonic_py_common import device_info
|
2021-06-07 14:34:23 -05:00
|
|
|
from sonic_py_common.multi_asic import get_asic_id_from_name
|
2020-06-18 18:26:09 -05:00
|
|
|
except ImportError as e:
|
|
|
|
raise ImportError("%s - required module not found" % str(e))
|
2017-10-24 12:56:09 -05:00
|
|
|
|
2021-06-07 14:34:23 -05:00
|
|
|
try:
|
|
|
|
if os.environ["CFGGEN_UNIT_TESTING"] == "2":
|
|
|
|
modules_path = os.path.join(os.path.dirname(__file__), ".")
|
|
|
|
tests_path = os.path.join(modules_path, "tests")
|
|
|
|
sys.path.insert(0, modules_path)
|
|
|
|
sys.path.insert(0, tests_path)
|
|
|
|
import mock_tables.dbconnector
|
|
|
|
mock_tables.dbconnector.load_namespace_config()
|
|
|
|
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
|
2020-06-18 18:26:09 -05:00
|
|
|
# Global Variable
|
|
|
|
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
|
|
|
|
PLATFORM_ROOT_PATH_DOCKER = '/usr/share/sonic/platform'
|
|
|
|
SONIC_ROOT_PATH = '/usr/share/sonic'
|
|
|
|
HWSKU_ROOT_PATH = '/usr/share/sonic/hwsku'
|
|
|
|
|
|
|
|
PLATFORM_JSON = 'platform.json'
|
|
|
|
PORT_CONFIG_INI = 'port_config.ini'
|
|
|
|
HWSKU_JSON = 'hwsku.json'
|
|
|
|
|
|
|
|
PORT_STR = "Ethernet"
|
|
|
|
BRKOUT_MODE = "default_brkout_mode"
|
|
|
|
CUR_BRKOUT_MODE = "brkout_mode"
|
|
|
|
INTF_KEY = "interfaces"
|
[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
```
2021-01-24 19:46:33 -06:00
|
|
|
OPTIONAL_HWSKU_ATTRIBUTES = ["fec", "autoneg"]
|
2020-06-18 18:26:09 -05:00
|
|
|
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
BRKOUT_PATTERN = r'(\d{1,3})x(\d{1,3}G)(\[(\d{1,3}G,?)*\])?(\((\d{1,3})\))?'
|
2020-06-18 18:26:09 -05:00
|
|
|
|
|
|
|
#
|
|
|
|
# Helper Functions
|
|
|
|
#
|
|
|
|
def readJson(filename):
|
|
|
|
# Read 'platform.json' or 'hwsku.json' file
|
|
|
|
try:
|
|
|
|
with open(filename) as fp:
|
|
|
|
try:
|
|
|
|
data = json.load(fp)
|
|
|
|
except json.JSONDecodeError:
|
|
|
|
print("Json file does not exist")
|
|
|
|
data_dict = ast.literal_eval(json.dumps(data))
|
|
|
|
return data_dict
|
|
|
|
except Exception as e:
|
2020-08-19 11:29:40 -05:00
|
|
|
print("error occurred while parsing json: {}".format(sys.exc_info()[1]))
|
2020-06-18 18:26:09 -05:00
|
|
|
return None
|
|
|
|
|
2021-06-07 14:34:23 -05:00
|
|
|
def db_connect_configdb(namespace=None):
|
2020-06-18 18:26:09 -05:00
|
|
|
"""
|
|
|
|
Connect to configdb
|
|
|
|
"""
|
2021-06-07 14:34:23 -05:00
|
|
|
try:
|
|
|
|
if namespace is not None:
|
|
|
|
swsscommon.SonicDBConfig.load_sonic_global_db_config(namespace=namespace)
|
|
|
|
config_db = swsscommon.ConfigDBConnector(use_unix_socket_path=True, namespace=namespace)
|
|
|
|
except Exception as e:
|
|
|
|
return None
|
2020-06-18 18:26:09 -05:00
|
|
|
if config_db is None:
|
|
|
|
return None
|
|
|
|
try:
|
|
|
|
"""
|
|
|
|
This could be blocking during the config load_minigraph phase,
|
|
|
|
as the CONFIG_DB_INITIALIZED is not yet set in the configDB.
|
|
|
|
We can ignore the check by using config_db.db_connect('CONFIG_DB') instead
|
|
|
|
"""
|
|
|
|
# Connect only if available & initialized
|
|
|
|
config_db.connect(wait_for_init=False)
|
|
|
|
except Exception as e:
|
|
|
|
config_db = None
|
|
|
|
return config_db
|
2017-10-24 12:56:09 -05:00
|
|
|
|
2020-06-18 18:26:09 -05:00
|
|
|
def get_hwsku_file_name(hwsku=None, platform=None):
|
|
|
|
hwsku_candidates_Json = []
|
|
|
|
hwsku_candidates_Json.append(os.path.join(HWSKU_ROOT_PATH, HWSKU_JSON))
|
|
|
|
if hwsku:
|
|
|
|
if platform:
|
|
|
|
hwsku_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH, platform, hwsku, HWSKU_JSON))
|
|
|
|
hwsku_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH_DOCKER, hwsku, HWSKU_JSON))
|
|
|
|
hwsku_candidates_Json.append(os.path.join(SONIC_ROOT_PATH, hwsku, HWSKU_JSON))
|
|
|
|
for candidate in hwsku_candidates_Json:
|
2017-10-24 12:56:09 -05:00
|
|
|
if os.path.isfile(candidate):
|
|
|
|
return candidate
|
|
|
|
return None
|
|
|
|
|
2021-06-07 14:34:23 -05:00
|
|
|
def get_port_config(hwsku=None, platform=None, port_config_file=None, hwsku_config_file=None, asic_name=None):
|
|
|
|
config_db = db_connect_configdb(asic_name)
|
2020-06-18 18:26:09 -05:00
|
|
|
# If available, Read from CONFIG DB first
|
|
|
|
if config_db is not None and port_config_file is None:
|
|
|
|
|
|
|
|
port_data = config_db.get_table("PORT")
|
|
|
|
if bool(port_data):
|
|
|
|
ports = ast.literal_eval(json.dumps(port_data))
|
|
|
|
port_alias_map = {}
|
|
|
|
port_alias_asic_map = {}
|
|
|
|
for intf_name in ports.keys():
|
2021-06-07 14:34:23 -05:00
|
|
|
if "alias" in ports[intf_name]:
|
|
|
|
port_alias_map[ports[intf_name]["alias"]] = intf_name
|
2020-06-18 18:26:09 -05:00
|
|
|
return (ports, port_alias_map, port_alias_asic_map)
|
2020-05-04 18:15:15 -05:00
|
|
|
|
2021-06-07 14:34:23 -05:00
|
|
|
if asic_name is not None:
|
|
|
|
asic_id = str(get_asic_id_from_name(asic_name))
|
|
|
|
else:
|
|
|
|
asic_id = None
|
|
|
|
|
2017-10-24 12:56:09 -05:00
|
|
|
if not port_config_file:
|
2021-06-07 14:34:23 -05:00
|
|
|
port_config_file = device_info.get_path_to_port_config_file(hwsku, asic_id)
|
|
|
|
|
2017-10-24 12:56:09 -05:00
|
|
|
if not port_config_file:
|
2020-05-04 18:15:15 -05:00
|
|
|
return ({}, {}, {})
|
2017-10-24 12:56:09 -05:00
|
|
|
|
|
|
|
|
2020-06-18 18:26:09 -05:00
|
|
|
# Read from 'platform.json' file
|
|
|
|
if port_config_file.endswith('.json'):
|
|
|
|
if not hwsku_config_file:
|
|
|
|
hwsku_json_file = get_hwsku_file_name(hwsku, platform)
|
|
|
|
if not hwsku_json_file:
|
|
|
|
return ({}, {}, {})
|
|
|
|
else:
|
|
|
|
hwsku_json_file = hwsku_config_file
|
|
|
|
|
|
|
|
return parse_platform_json_file(hwsku_json_file, port_config_file)
|
|
|
|
|
|
|
|
# If 'platform.json' file is not available, read from 'port_config.ini'
|
|
|
|
else:
|
|
|
|
return parse_port_config_file(port_config_file)
|
|
|
|
|
2017-10-24 12:56:09 -05:00
|
|
|
def parse_port_config_file(port_config_file):
|
|
|
|
ports = {}
|
|
|
|
port_alias_map = {}
|
2020-05-04 18:15:15 -05:00
|
|
|
port_alias_asic_map = {}
|
2017-10-24 12:56:09 -05:00
|
|
|
# Default column definition
|
|
|
|
titles = ['name', 'lanes', 'alias', 'index']
|
|
|
|
with open(port_config_file) as data:
|
|
|
|
for line in data:
|
|
|
|
if line.startswith('#'):
|
|
|
|
if "name" in line:
|
|
|
|
titles = line.strip('#').split()
|
|
|
|
continue;
|
|
|
|
tokens = line.split()
|
|
|
|
if len(tokens) < 2:
|
|
|
|
continue
|
|
|
|
name_index = titles.index('name')
|
|
|
|
name = tokens[name_index]
|
|
|
|
data = {}
|
|
|
|
for i, item in enumerate(tokens):
|
|
|
|
if i == name_index:
|
|
|
|
continue
|
|
|
|
data[titles[i]] = item
|
|
|
|
data.setdefault('alias', name)
|
|
|
|
ports[name] = data
|
|
|
|
port_alias_map[data['alias']] = name
|
2020-05-04 18:15:15 -05:00
|
|
|
# asic_port_name to sonic_name mapping also included in
|
|
|
|
# port_alias_map
|
|
|
|
if (('asic_port_name' in data) and
|
|
|
|
(data['asic_port_name'] != name)):
|
|
|
|
port_alias_map[data['asic_port_name']] = name
|
|
|
|
# alias to asic_port_name mapping
|
|
|
|
if 'asic_port_name' in data:
|
|
|
|
port_alias_asic_map[data['alias']] = data['asic_port_name'].strip()
|
|
|
|
return (ports, port_alias_map, port_alias_asic_map)
|
2017-10-24 12:56:09 -05:00
|
|
|
|
2020-06-18 18:26:09 -05:00
|
|
|
# Generate configs (i.e. alias, lanes, speed, index) for port
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
def gen_port_config(ports, parent_intf_id, index, alias_list, lanes, k, offset):
|
2020-06-18 18:26:09 -05:00
|
|
|
if k is not None:
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
num_lane_used, speed, alt_speed, _, _ , assigned_lane = k[0], k[1], k[2], k[3], k[4], k[5]
|
2020-06-18 18:26:09 -05:00
|
|
|
|
|
|
|
# In case of symmetric mode
|
|
|
|
if assigned_lane is None:
|
|
|
|
assigned_lane = len(lanes.split(","))
|
|
|
|
|
|
|
|
parent_intf_id = int(offset)+int(parent_intf_id)
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
alias_position = 0 + int(offset)//int(num_lane_used)
|
|
|
|
lanes_start = 0 + int(offset)
|
2020-06-18 18:26:09 -05:00
|
|
|
|
|
|
|
step = int(assigned_lane)//int(num_lane_used)
|
|
|
|
for i in range(0,int(assigned_lane), step):
|
|
|
|
intf_name = PORT_STR + str(parent_intf_id)
|
|
|
|
ports[intf_name] = {}
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
ports[intf_name]['alias'] = alias_list[alias_position]
|
|
|
|
ports[intf_name]['lanes'] = ','.join(lanes.split(",")[lanes_start:lanes_start+step])
|
2020-06-18 18:26:09 -05:00
|
|
|
if speed:
|
|
|
|
speed_pat = re.search("^((\d+)G|\d+)$", speed.upper())
|
|
|
|
if speed_pat is None:
|
|
|
|
raise Exception('{} speed is not Supported...'.format(speed))
|
|
|
|
speed_G, speed_orig = speed_pat.group(2), speed_pat.group(1)
|
|
|
|
if speed_G:
|
|
|
|
conv_speed = int(speed_G)*1000
|
|
|
|
else:
|
|
|
|
conv_speed = int(speed_orig)
|
|
|
|
ports[intf_name]['speed'] = str(conv_speed)
|
|
|
|
else:
|
|
|
|
raise Exception('Regex return for speed is None...')
|
|
|
|
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
ports[intf_name]['index'] = index.split(",")[alias_position]
|
2020-06-18 18:26:09 -05:00
|
|
|
|
|
|
|
parent_intf_id += step
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
alias_position += 1
|
|
|
|
lanes_start += step
|
2020-06-18 18:26:09 -05:00
|
|
|
|
|
|
|
offset = int(assigned_lane) + int(offset)
|
|
|
|
return offset
|
|
|
|
else:
|
|
|
|
raise Exception('Regex return for k is None...')
|
|
|
|
|
|
|
|
"""
|
|
|
|
Given a port and breakout mode, this method returns
|
|
|
|
the list of child ports using platform_json file
|
|
|
|
"""
|
|
|
|
def get_child_ports(interface, breakout_mode, platform_json_file):
|
|
|
|
child_ports = {}
|
|
|
|
|
|
|
|
port_dict = readJson(platform_json_file)
|
|
|
|
|
|
|
|
index = port_dict[INTF_KEY][interface]['index']
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
alias_list = port_dict[INTF_KEY][interface]['breakout_modes'][breakout_mode]
|
2020-06-18 18:26:09 -05:00
|
|
|
lanes = port_dict[INTF_KEY][interface]['lanes']
|
|
|
|
|
|
|
|
"""
|
|
|
|
Example of match_list for some breakout_mode using regex
|
|
|
|
Breakout Mode -------> Match_list
|
|
|
|
-----------------------------
|
|
|
|
2x25G(2)+1x50G(2) ---> [('2', '25G', None, '(2)', '2'), ('1', '50G', None, '(2)', '2')]
|
|
|
|
1x50G(2)+2x25G(2) ---> [('1', '50G', None, '(2)', '2'), ('2', '25G', None, '(2)', '2')]
|
|
|
|
1x100G[40G] ---------> [('1', '100G', '[40G]', None, None)]
|
|
|
|
2x50G ---------------> [('2', '50G', None, None, None)]
|
|
|
|
"""
|
|
|
|
# Asymmetric breakout mode
|
|
|
|
if re.search("\+",breakout_mode) is not None:
|
|
|
|
breakout_parts = breakout_mode.split("+")
|
|
|
|
match_list = [re.match(BRKOUT_PATTERN, i).groups() for i in breakout_parts]
|
|
|
|
|
|
|
|
# Symmetric breakout mode
|
|
|
|
else:
|
|
|
|
match_list = [re.match(BRKOUT_PATTERN, breakout_mode).groups()]
|
|
|
|
|
|
|
|
offset = 0
|
|
|
|
parent_intf_id = int(re.search("Ethernet(\d+)", interface).group(1))
|
|
|
|
for k in match_list:
|
[DPB|master] Update Dynamic Port Breakout Logic for flexible alias support a… (#6831)
To fix [DPB| wrong aliases for interfaces](https://github.com/Azure/sonic-buildimage/issues/6024) issue, implimented flexible alias support [design doc](https://github.com/Azure/SONiC/pull/749)
> [[dpb|config] Fix the validation logic of breakout mode](https://github.com/Azure/sonic-utilities/pull/1440) depends on this
#### How I did it
1. Removed `"alias_at_lanes"` from port-configuration file(i.e. platfrom.json)
2. Added dictionary to "breakout_modes" values. This defines the breakout modes available on the platform for this parent port, and it maps to the alias list. The alias list presents the alias names for individual ports in order under this breakout mode.
```
{
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",
"lanes": "0,1,2,3",
"breakout_modes": {
"1x100G[40G]": ["Eth1"],
"2x50G": ["Eth1/1", "Eth1/2"],
"4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"],
"2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"],
"1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"]
}
}
}
```
#### How to verify it
`config interface breakout`
Signed-off-by: Sangita Maity <samaity@linkedin.com>
2021-02-26 02:13:33 -06:00
|
|
|
offset = gen_port_config(child_ports, parent_intf_id, index, alias_list, lanes, k, offset)
|
2020-06-18 18:26:09 -05:00
|
|
|
return child_ports
|
|
|
|
|
|
|
|
def parse_platform_json_file(hwsku_json_file, platform_json_file):
|
|
|
|
ports = {}
|
|
|
|
port_alias_map = {}
|
|
|
|
port_alias_asic_map = {}
|
|
|
|
|
|
|
|
port_dict = readJson(platform_json_file)
|
|
|
|
hwsku_dict = readJson(hwsku_json_file)
|
|
|
|
|
2021-08-23 05:28:59 -05:00
|
|
|
if port_dict is None:
|
2020-06-18 18:26:09 -05:00
|
|
|
raise Exception("port_dict is none")
|
2021-08-23 05:28:59 -05:00
|
|
|
if hwsku_dict is None:
|
2020-06-18 18:26:09 -05:00
|
|
|
raise Exception("hwsku_dict is none")
|
|
|
|
|
|
|
|
if INTF_KEY not in port_dict or INTF_KEY not in hwsku_dict:
|
|
|
|
raise Exception("INTF_KEY is not present in appropriate file")
|
|
|
|
|
|
|
|
for intf in port_dict[INTF_KEY]:
|
|
|
|
if intf not in hwsku_dict[INTF_KEY]:
|
|
|
|
raise Exception("{} is not available in hwsku_dict".format(intf))
|
|
|
|
|
|
|
|
# take default_brkout_mode from hwsku.json
|
|
|
|
brkout_mode = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE]
|
|
|
|
|
|
|
|
child_ports = get_child_ports(intf, brkout_mode, platform_json_file)
|
[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
```
2021-01-24 19:46:33 -06:00
|
|
|
|
|
|
|
# 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
|
|
|
|
|
2020-06-18 18:26:09 -05:00
|
|
|
ports.update(child_ports)
|
|
|
|
|
2021-08-23 05:28:59 -05:00
|
|
|
if ports is None:
|
|
|
|
raise Exception("Ports dictionary is None")
|
2020-06-18 18:26:09 -05:00
|
|
|
|
|
|
|
for i in ports.keys():
|
|
|
|
port_alias_map[ports[i]["alias"]]= i
|
|
|
|
return (ports, port_alias_map, port_alias_asic_map)
|
|
|
|
|
|
|
|
|
|
|
|
def get_breakout_mode(hwsku=None, platform=None, port_config_file=None):
|
|
|
|
if not port_config_file:
|
2020-09-04 12:19:12 -05:00
|
|
|
port_config_file = device_info.get_path_to_port_config_file(hwsku)
|
2020-06-18 18:26:09 -05:00
|
|
|
if not port_config_file:
|
|
|
|
return None
|
|
|
|
if port_config_file.endswith('.json'):
|
|
|
|
hwsku_json_file = get_hwsku_file_name(hwsku, platform)
|
|
|
|
if not hwsku_json_file:
|
|
|
|
raise Exception("'hwsku_json' file does not exist!!! This file is necessary to proceed forward.")
|
|
|
|
|
|
|
|
return parse_breakout_mode(hwsku_json_file)
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
def parse_breakout_mode(hwsku_json_file):
|
|
|
|
brkout_table = {}
|
|
|
|
hwsku_dict = readJson(hwsku_json_file)
|
|
|
|
if not hwsku_dict:
|
|
|
|
raise Exception("hwsku_dict is empty")
|
|
|
|
if INTF_KEY not in hwsku_dict:
|
|
|
|
raise Exception("INTF_KEY is not present in hwsku_dict")
|
2017-10-24 12:56:09 -05:00
|
|
|
|
2020-06-18 18:26:09 -05:00
|
|
|
for intf in hwsku_dict[INTF_KEY]:
|
|
|
|
brkout_table[intf] = {}
|
|
|
|
brkout_table[intf][CUR_BRKOUT_MODE] = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE]
|
|
|
|
return brkout_table
|