-
Notifications
You must be signed in to change notification settings - Fork 745
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update IP decap testing for dualtor (#3702)
Fixes sonic-net/sonic-buildimage#8098 What is the motivation for this PR? The IP decap testing was only designed for single ToR. This PR is to adapt the IP decap testing for dualtor testbed as well. How did you do it? Changes: * Add common fib_utils.py script for FIB related helper functions. * Updated the fib testing to use the tools in common fib_utils.py file. * Update the IP decap testing scripts to support dualtor. Signed-off-by: Xin Wang <[email protected]>
- Loading branch information
Showing
7 changed files
with
657 additions
and
664 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
import json | ||
import logging | ||
import tempfile | ||
|
||
from datetime import datetime | ||
|
||
import pytest | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def get_t2_fib_info(duthosts, duts_cfg_facts, duts_mg_facts): | ||
"""Get parsed FIB information from redis DB for T2 topology. | ||
Args: | ||
duthosts (DutHosts): Instance of DutHosts for interacting with DUT hosts | ||
duts_cfg_facts (dict): Running config facts of all DUT hosts. | ||
duts_mg_facts (dict): Minigraph facts of all DUT hosts. | ||
Returns: | ||
dict: Map of prefix to PTF ports that are connected to DUT output ports. | ||
{ | ||
'192.168.0.0/21': [], | ||
'192.168.8.0/25': [[58 59] [62 63] [66 67] [70 71]], | ||
'192.168.16.0/25': [[58 59] [62 63] [66 67] [70 71]], | ||
... | ||
'20c0:c2e8:0:80::/64': [[58 59] [62 63] [66 67] [70 71]], | ||
'20c1:998::/64': [[58 59] [62 63] [66 67] [70 71]], | ||
... | ||
} | ||
""" | ||
timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S') | ||
fib_info = {} | ||
for duthost in duthosts.frontend_nodes: | ||
cfg_facts = duts_cfg_facts[duthost.hostname] | ||
mg_facts = duts_mg_facts[duthost.hostname] | ||
for asic_index, asic_cfg_facts in enumerate(cfg_facts): | ||
asic = duthost.asic_instance(asic_index) | ||
|
||
asic.shell("{} redis-dump -d 0 -k 'ROUTE*' -y > /tmp/fib.{}.txt".format(asic.ns_arg, timestamp)) | ||
duthost.fetch(src="/tmp/fib.{}.txt".format(timestamp), dest="/tmp/fib") | ||
|
||
po = asic_cfg_facts.get('PORTCHANNEL', {}) | ||
ports = asic_cfg_facts.get('PORT', {}) | ||
|
||
with open("/tmp/fib/{}/tmp/fib.{}.txt".format(duthost.hostname, timestamp)) as fp: | ||
fib = json.load(fp) | ||
for k, v in fib.items(): | ||
skip = False | ||
|
||
prefix = k.split(':', 1)[1] | ||
ifnames = v['value']['ifname'].split(',') | ||
nh = v['value']['nexthop'] | ||
|
||
oports = [] | ||
for ifname in ifnames: | ||
if po.has_key(ifname): | ||
# ignore the prefix, if the prefix nexthop is not a frontend port | ||
if 'members' in po[ifname]: | ||
if 'role' in ports[po[ifname]['members'][0]] and ports[po[ifname]['members'][0]]['role'] == 'Int': | ||
skip = True | ||
else: | ||
oports.append([str(mg_facts['minigraph_ptf_indices'][x]) for x in po[ifname]['members']]) | ||
else: | ||
if ports.has_key(ifname): | ||
if 'role' in ports[ifname] and ports[ifname]['role'] == 'Int': | ||
skip = True | ||
else: | ||
oports.append([str(mg_facts['minigraph_ptf_indices'][ifname])]) | ||
else: | ||
logger.info("Route point to non front panel port {}:{}".format(k, v)) | ||
skip = True | ||
|
||
# skip direct attached subnet | ||
if nh == '0.0.0.0' or nh == '::' or nh == "": | ||
skip = True | ||
|
||
if not skip: | ||
if prefix in fib_info: | ||
fib_info[prefix] += oports | ||
else: | ||
fib_info[prefix] = oports | ||
|
||
return fib_info | ||
|
||
|
||
def get_fib_info(duthost, dut_cfg_facts, duts_mg_facts): | ||
"""Get parsed FIB information from redis DB. | ||
Args: | ||
duthost (SonicHost): Object for interacting with DUT. | ||
duts_cfg_facts (dict): Running config facts of all DUT hosts. | ||
duts_mg_facts (dict): Minigraph facts of all DUT hosts. | ||
Returns: | ||
dict: Map of prefix to PTF ports that are connected to DUT output ports. | ||
{ | ||
'192.168.0.0/21': [], | ||
'192.168.8.0/25': [[58 59] [62 63] [66 67] [70 71]], | ||
'192.168.16.0/25': [[58 59] [62 63] [66 67] [70 71]], | ||
... | ||
'20c0:c2e8:0:80::/64': [[58 59] [62 63] [66 67] [70 71]], | ||
'20c1:998::/64': [[58 59] [62 63] [66 67] [70 71]], | ||
... | ||
} | ||
""" | ||
timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S') | ||
fib_info = {} | ||
for asic_index, asic_cfg_facts in enumerate(dut_cfg_facts): | ||
|
||
asic = duthost.asic_instance(asic_index) | ||
|
||
asic.shell("{} redis-dump -d 0 -k 'ROUTE*' -y > /tmp/fib.{}.txt".format(asic.ns_arg, timestamp)) | ||
duthost.fetch(src="/tmp/fib.{}.txt".format(timestamp), dest="/tmp/fib") | ||
|
||
po = asic_cfg_facts.get('PORTCHANNEL', {}) | ||
ports = asic_cfg_facts.get('PORT', {}) | ||
|
||
with open("/tmp/fib/{}/tmp/fib.{}.txt".format(duthost.hostname, timestamp)) as fp: | ||
fib = json.load(fp) | ||
for k, v in fib.items(): | ||
skip = False | ||
|
||
prefix = k.split(':', 1)[1] | ||
ifnames = v['value']['ifname'].split(',') | ||
nh = v['value']['nexthop'] | ||
|
||
oports = [] | ||
for ifname in ifnames: | ||
if po.has_key(ifname): | ||
# ignore the prefix, if the prefix nexthop is not a frontend port | ||
if 'members' in po[ifname]: | ||
if 'role' in ports[po[ifname]['members'][0]] and ports[po[ifname]['members'][0]]['role'] == 'Int': | ||
skip = True | ||
else: | ||
oports.append([str(duts_mg_facts['minigraph_ptf_indices'][x]) for x in po[ifname]['members']]) | ||
else: | ||
if ports.has_key(ifname): | ||
if 'role' in ports[ifname] and ports[ifname]['role'] == 'Int': | ||
skip = True | ||
else: | ||
oports.append([str(duts_mg_facts['minigraph_ptf_indices'][ifname])]) | ||
else: | ||
logger.info("Route point to non front panel port {}:{}".format(k, v)) | ||
skip = True | ||
|
||
# skip direct attached subnet | ||
if nh == '0.0.0.0' or nh == '::' or nh == "": | ||
skip = True | ||
|
||
if not skip: | ||
if prefix in fib_info: | ||
fib_info[prefix] += oports | ||
else: | ||
fib_info[prefix] = oports | ||
# For single_asic device, add empty list for directly connected subnets | ||
elif skip and not duthost.is_multi_asic: | ||
fib_info[prefix] = [] | ||
|
||
return fib_info | ||
|
||
|
||
def gen_fib_info_file(ptfhost, fib_info, filename): | ||
"""Store FIB info dumped & parsed from database to temporary file, then copy the file to PTF host. | ||
Args: | ||
ptfhost (PTFHost): Instance of PTFHost for interacting with the PTF host. | ||
fib_info (dict): FIB info dumped and parsed from database. | ||
filename (str): Name of the target FIB info file on PTF host. | ||
""" | ||
tmp_fib_info = tempfile.NamedTemporaryFile() | ||
for prefix, oports in fib_info.items(): | ||
tmp_fib_info.write(prefix) | ||
if oports: | ||
for op in oports: | ||
tmp_fib_info.write(' [{}]'.format(' '.join(op))) | ||
else: | ||
tmp_fib_info.write(' []') | ||
tmp_fib_info.write('\n') | ||
tmp_fib_info.flush() | ||
ptfhost.copy(src=tmp_fib_info.name, dest=filename) | ||
|
||
|
||
@pytest.fixture(scope='module') | ||
def fib_info_files(duthosts, ptfhost, duts_running_config_facts, duts_minigraph_facts, tbinfo): | ||
"""Get FIB info from database and store to text files on PTF host. | ||
For T2 topology, generate a single file to /root/fib_info_all_duts.txt to PTF host. | ||
For other topologies, generate one file for each duthost. File name pattern: | ||
/root/fib_info_dut<dut_index>.txt | ||
Args: | ||
duthosts (DutHosts): Instance of DutHosts for interacting with DUT hosts. | ||
ptfhost (PTFHost): Instance of PTFHost for interacting with the PTF host. | ||
duts_running_config_facts (dict): Running config facts of all DUT hosts. | ||
duts_minigraph_facts (dict): Minigraph facts of all DUT hosts. | ||
tbinfo (object): Instance of TestbedInfo. | ||
Returns: | ||
list: List of FIB info file names on PTF host. | ||
""" | ||
duts_config_facts = duts_running_config_facts | ||
files = [] | ||
if tbinfo['topo']['type'] != "t2": | ||
for dut_index, duthost in enumerate(duthosts): | ||
fib_info = get_fib_info(duthost, duts_config_facts[duthost.hostname], duts_minigraph_facts[duthost.hostname]) | ||
filename = '/root/fib_info_dut{}.txt'.format(dut_index) | ||
gen_fib_info_file(ptfhost, fib_info, filename) | ||
files.append(filename) | ||
else: | ||
fib_info = get_t2_fib_info(duthosts, duts_config_facts, duts_minigraph_facts) | ||
filename = '/root/fib_info_all_duts.txt' | ||
gen_fib_info_file(ptfhost, fib_info, filename) | ||
files.append(filename) | ||
|
||
return files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.