[ECMP][Multi-ASIC] Have different ECMP seed value on each ASIC (#5357)

* Calculate ECMP hash seed based on ASIC ID on multi ASIC platform. Each ASIC will have a unique ECMP hash seed value.
This commit is contained in:
Mahesh Maddikayala 2020-10-08 09:05:37 -07:00 committed by GitHub
parent 895f4e0bf7
commit 744612d269
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 120 additions and 8 deletions

View File

@ -1,20 +1,25 @@
{# the range of hash_seed is 0-15 #}
{# set default hash seed to 0 #}
{% set hash_seed = 0 %}
{% set hash_seed_offset = 0 %}
{% if DEVICE_METADATA.localhost.type %}
{% if DEVICE_METADATA.localhost.type == "ToRRouter" %}
{% set hash_seed = 0 %}
{% elif DEVICE_METADATA.localhost.type == "LeafRouter" %}
{% set hash_seed = 10 %}
{% elif DEVICE_METADATA.localhost.type == "SpineRouter" %}
{% set hash_seed = 15 %}
{% set hash_seed = 25 %}
{% endif %}
{% endif %}
{% if DEVICE_METADATA.localhost.namespace_id %}
{% set hash_seed_offset = DEVICE_METADATA.localhost.namespace_id | int %}
{% endif %}
{% set hash_seed_value = hash_seed_offset + hash_seed %}
[
{
"SWITCH_TABLE:switch": {
"ecmp_hash_seed": "{{ hash_seed }}",
"lag_hash_seed": "{{ hash_seed }}",
"ecmp_hash_seed": "{{ hash_seed_value }}",
"lag_hash_seed": "{{ hash_seed_value }}",
"fdb_aging_time": "600"
},
"OP": "SET"

View File

@ -31,7 +31,7 @@ import contextlib
import jinja2
import json
import netaddr
import os.path
import os
import sys
import yaml
@ -61,7 +61,7 @@ def sort_by_port_index(value):
if not value:
return
if isinstance(value, list):
# In multi-ASIC platforms backend ethernet ports are identified as
# In multi-ASIC platforms backend ethernet ports are identified as
# 'Ethernet-BPxy'. Add 1024 to sort backend ports to the end.
value.sort(
key = lambda k: int(k[8:]) if "BP" not in k else int(k[11:]) + 1024
@ -296,8 +296,14 @@ def main():
asic_id = None
if asic_name is not None:
asic_id = get_asic_id_from_name(asic_name)
# get the namespace ID
namespace_id = os.getenv("NAMESPACE_ID")
if namespace_id:
deep_update(data, {
'DEVICE_METADATA': {
'localhost': {'namespace_id': namespace_id}
}
})
# Load the database config for the namespace from global database json
if args.namespace is not None:
SonicDBConfig.load_sonic_global_db_config(namespace=args.namespace)

View File

@ -0,0 +1,10 @@
[
{
"SWITCH_TABLE:switch": {
"ecmp_hash_seed": "11",
"lag_hash_seed": "11",
"fdb_aging_time": "600"
},
"OP": "SET"
}
]

View File

@ -0,0 +1,10 @@
[
{
"SWITCH_TABLE:switch": {
"ecmp_hash_seed": "13",
"lag_hash_seed": "13",
"fdb_aging_time": "600"
},
"OP": "SET"
}
]

View File

@ -0,0 +1,10 @@
[
{
"SWITCH_TABLE:switch": {
"ecmp_hash_seed": "0",
"lag_hash_seed": "0",
"fdb_aging_time": "600"
},
"OP": "SET"
}
]

View File

@ -0,0 +1,10 @@
[
{
"SWITCH_TABLE:switch": {
"ecmp_hash_seed": "10",
"lag_hash_seed": "10",
"fdb_aging_time": "600"
},
"OP": "SET"
}
]

View File

@ -171,6 +171,68 @@ class TestJ2Files(TestCase):
sample_output_file = os.path.join(self.test_dir, 'multi_npu_data', utils.PYvX_DIR, 'ipinip.json')
assert filecmp.cmp(sample_output_file, self.output_file)
def test_swss_switch_render_template(self):
switch_template = os.path.join(
self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent',
'switch.json.j2'
)
constants_yml = os.path.join(
self.test_dir, '..', '..', '..', 'files', 'image_config',
'constants', 'constants.yml'
)
test_list = {
"t1": {
"graph": self.t1_mlnx_minigraph,
"output": "t1-switch.json"
},
"t0": {
"graph": self.t0_minigraph,
"output": "t0-switch.json"
},
}
for _, v in test_list.items():
argument = " -m {} -y {} -t {} > {}".format(
v["graph"], constants_yml, switch_template, self.output_file
)
sample_output_file = os.path.join(
self.test_dir, 'sample_output', v["output"]
)
self.run_script(argument)
assert filecmp.cmp(sample_output_file, self.output_file)
def test_swss_switch_render_template_multi_asic(self):
# verify the ECMP hash seed changes per namespace
switch_template = os.path.join(
self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent',
'switch.json.j2'
)
constants_yml = os.path.join(
self.test_dir, '..', '..', '..', 'files', 'image_config',
'constants', 'constants.yml'
)
test_list = {
"0": {
"namespace_id": "1",
"output": "t0-switch-masic1.json"
},
"1": {
"namespace_id": "3",
"output": "t0-switch-masic3.json"
},
}
for _, v in test_list.items():
os.environ["NAMESPACE_ID"] = v["namespace_id"]
argument = " -m {} -y {} -t {} > {}".format(
self.t1_mlnx_minigraph, constants_yml, switch_template,
self.output_file
)
sample_output_file = os.path.join(
self.test_dir, 'sample_output', v["output"]
)
self.run_script(argument)
assert filecmp.cmp(sample_output_file, self.output_file)
os.environ["NAMESPACE_ID"] = ""
def test_ndppd_conf(self):
conf_template = os.path.join(self.test_dir, "ndppd.conf.j2")
vlan_interfaces_json = os.path.join(self.test_dir, "data", "ndppd", "vlan_interfaces.json")
@ -180,7 +242,6 @@ class TestJ2Files(TestCase):
self.run_script(argument)
assert filecmp.cmp(expected, self.output_file), self.run_diff(expected, self.output_file)
def tearDown(self):
try:
os.remove(self.output_file)