From c15de37706c8d913921b87ad74642ea3e1d16e19 Mon Sep 17 00:00:00 2001 From: yaqiangz Date: Sat, 8 Oct 2022 04:12:55 +0000 Subject: [PATCH 1/2] [m0] Add support for m0 in test_vlan_interface/test_vlan_ping --- .../tests_mark_conditions.yaml | 6 + .../test_vlan_interface.py | 151 ++++++++++++++---- tests/vlan/test_vlan_ping.py | 19 ++- 3 files changed, 140 insertions(+), 36 deletions(-) diff --git a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml index b14686f0aea..12a38ff54cb 100644 --- a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml +++ b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml @@ -271,6 +271,12 @@ generic_config_updater: conditions: - "'t2' in topo_name" +generic_config_updater/test_bgp_speaker.py: + skip: + reason: "M0 topo does not support test_bgp_speaker" + conditions: + - "topo_name in ['m0']" + generic_config_updater/test_eth_interface.py::test_replace_fec: skip: reason: 'replace_fec ethernet test is not supported on virtual switch' diff --git a/tests/generic_config_updater/test_vlan_interface.py b/tests/generic_config_updater/test_vlan_interface.py index 398c2b2534a..537a092f2a6 100644 --- a/tests/generic_config_updater/test_vlan_interface.py +++ b/tests/generic_config_updater/test_vlan_interface.py @@ -1,6 +1,10 @@ +import ipaddress import logging +import sys +import re import pytest +from tests.common.helpers.assertions import pytest_assert from tests.generic_config_updater.gu_utils import apply_patch, expect_op_success, expect_op_failure from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile from tests.generic_config_updater.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload @@ -12,6 +16,12 @@ # "Vlan1000|192.168.0.1/21": {}, # "Vlan1000|fc02:1000::1/64": {} # } +# Test on m0 topo to verify functionality and to choose predefined variable +# "VLAN_INTERFACE": { +# "Vlan1000": {}, +# "Vlan1000|192.168.0.1/24": {}, +# "Vlan1000|fc02:1000::1/64": {} +# } pytestmark = [ pytest.mark.topology('t0', 'm0'), @@ -19,9 +29,70 @@ logger = logging.getLogger(__name__) +if sys.version_info.major == 3: + UNICODE_TYPE = str +else: + UNICODE_TYPE = unicode + + +def get_vlan_info(intf): + """ + Sample output + { + "name": "Vlan1000", + "prefix": "192.168.0.1/24" + } + """ + info = { + "name": intf["attachto"], + "prefix": "{}/{}".format(intf["addr"], intf["prefixlen"]) + } + return info + + +@pytest.fixture() +def vlan_info(duthost, tbinfo): + """ + Fixture of getting ipv4/ipv6 vlan info + Args: + duthost: DUT host + tbinfo: fixture provides information about testbed + Return: + Name and prefix of ipv4/ipv6 vlans + Sample output + { + "v4": { + "name": "Vlan1000", + "prefix": "192.168.0.1/24" + }, + "v6": { + "name": "Vlan1000", + "prefix": "fc02:1000::1/64" + } + } + """ + mg_facts = duthost.get_extended_minigraph_facts(tbinfo) + vlan_intf = mg_facts['minigraph_vlan_interfaces'] + vlan_v4_info = None + vlan_v6_info = None + for intf in vlan_intf: + if vlan_v4_info is None and ipaddress.ip_address(intf["addr"]).version == 4: + vlan_v4_info = get_vlan_info(intf) + + if vlan_v6_info is None and ipaddress.ip_address(intf["addr"]).version == 6: + vlan_v6_info = get_vlan_info(intf) + + pytest_assert(vlan_v4_info is not None, "Not ipv4 vlan") + pytest_assert(vlan_v6_info is not None, "Not ipv6 vlan") + + yield { + "v4": vlan_v4_info, + "v6": vlan_v6_info + } + @pytest.fixture(autouse=True) -def cleanup_test_env(duthosts, rand_one_dut_hostname): +def cleanup_test_env(duthosts, rand_one_dut_hostname, vlan_info): """ Setup/teardown fixture for VLAN interface config Args: @@ -36,15 +107,15 @@ def cleanup_test_env(duthosts, rand_one_dut_hostname): try: logger.info("Rolled back to original checkpoint") rollback_or_reload(duthost) - check_show_ip_intf(duthost, "Vlan1000", ["192.168.0.1/21"], + check_show_ip_intf(duthost, vlan_info["v4"]["name"], [vlan_info["v4"]["prefix"]], [], is_ipv4=True) - check_show_ip_intf(duthost, "Vlan1000", ["fc02:1000::1/64"], + check_show_ip_intf(duthost, vlan_info["v6"]["name"], [vlan_info["v6"]["prefix"]], [], is_ipv4=False) finally: delete_checkpoint(duthost) -def vlan_interface_tc1_add_duplicate(duthost): +def vlan_interface_tc1_add_duplicate(duthost, vlan_info): """ Add duplicate v4 and v6 lo intf to config Sample output @@ -58,13 +129,13 @@ def vlan_interface_tc1_add_duplicate(duthost): { "op": "add", "path": create_path(["VLAN_INTERFACE", - "Vlan1000|192.168.0.1/21"]), + "{}|{}".format(vlan_info["v4"]["name"], vlan_info["v4"]["prefix"])]), "value": {} }, { "op": "add", "path": create_path(["VLAN_INTERFACE", - "Vlan1000|fc02:1000::1/64"]), + "{}|{}".format(vlan_info["v6"]["name"], vlan_info["v6"]["prefix"])]), "value": {} } ] @@ -78,15 +149,23 @@ def vlan_interface_tc1_add_duplicate(duthost): output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) expect_op_success(duthost, output) - check_show_ip_intf(duthost, "Vlan1000", ["192.168.0.1/21"], + check_show_ip_intf(duthost, vlan_info["v4"]["name"], [vlan_info["v4"]["prefix"]], [], is_ipv4=True) - check_show_ip_intf(duthost, "Vlan1000", ["fc02:1000::1/64"], + check_show_ip_intf(duthost, vlan_info["v6"]["name"], [vlan_info["v6"]["prefix"]], [], is_ipv4=False) finally: delete_tmpfile(duthost, tmpfile) -def vlan_interface_tc1_xfail(duthost): +def reg_replace(str, reg, replace_str): + """ + Replace str by regex + """ + regex = re.compile(reg) + return regex.sub(replace_str, str) + + +def vlan_interface_tc1_xfail(duthost, vlan_info): """ Test expect fail testcase ("add", "Vlan1000", "587.168.0.1/21", "fc02:1000::1/64"), ADD Invalid IPv4 address @@ -95,10 +174,10 @@ def vlan_interface_tc1_xfail(duthost): ("remove", "Vlan1000", "192.168.0.1/21", "fc02:1000::2/64") REMOVE Unexist IPv6 address """ xfail_input = [ - ("add", "Vlan1000", "587.168.0.1/21", "fc02:1000::1/64"), - ("add", "Vlan1000", "192.168.0.1/21", "fc02:1000::xyz/64"), - ("remove", "Vlan1000", "192.168.0.2/21", "fc02:1000::1/64"), - ("remove", "Vlan1000", "192.168.0.1/21", "fc02:1000::2/64") + ("add", vlan_info["v4"]["name"], reg_replace(vlan_info["v4"]["prefix"], r"^\d*", "587"), vlan_info["v6"]["prefix"]), + ("add", vlan_info["v4"]["name"], vlan_info["v4"]["prefix"], reg_replace(vlan_info["v6"]["prefix"], r":\d*/", ":xyz/")), + ("remove", vlan_info["v4"]["name"], ipaddr_plus(vlan_info["v4"]["prefix"]), vlan_info["v6"]["prefix"]), + ("remove", vlan_info["v4"]["name"], vlan_info["v4"]["prefix"], ipaddr_plus(vlan_info["v6"]["prefix"])) ] for op, name, ip, ipv6 in xfail_input: dummy_vlan_interface_v4 = name + "|" + ip @@ -205,7 +284,15 @@ def vlan_interface_tc1_add_new(duthost): delete_tmpfile(duthost, tmpfile) -def vlan_interface_tc1_replace(duthost): +def ipaddr_plus(ipaddr): + """ + Get next ip address of ipaddr + """ + splits = ipaddr.split("/") + return "{}/{}".format(ipaddress.ip_address(UNICODE_TYPE(splits[0])) + 1, splits[1]) + + +def vlan_interface_tc1_replace(duthost, vlan_info): """ Test replace testcase Expected output @@ -219,23 +306,23 @@ def vlan_interface_tc1_replace(duthost): { "op": "remove", "path": create_path(["VLAN_INTERFACE", - "Vlan1000|fc02:1000::1/64"]), + "{}|{}".format(vlan_info["v6"]["name"], vlan_info["v6"]["prefix"])]), }, { "op": "remove", "path": create_path(["VLAN_INTERFACE", - "Vlan1000|192.168.0.1/21"]), + "{}|{}".format(vlan_info["v4"]["name"], vlan_info["v4"]["prefix"])]), }, { "op": "add", "path": create_path(["VLAN_INTERFACE", - "Vlan1000|192.168.0.2/21"]), + "{}|{}".format(vlan_info["v4"]["name"], ipaddr_plus(vlan_info["v4"]["prefix"]))]), "value": {} }, { "op": "add", "path": create_path(["VLAN_INTERFACE", - "Vlan1000|fc02:1000::2/64"]), + "{}|{}".format(vlan_info["v6"]["name"], ipaddr_plus(vlan_info["v6"]["prefix"]))]), "value": {} } ] @@ -247,15 +334,15 @@ def vlan_interface_tc1_replace(duthost): output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) expect_op_success(duthost, output) - check_show_ip_intf(duthost, "Vlan1000", ["192.168.0.2/21"], - ["192.168.0.1/21"], is_ipv4=True) - check_show_ip_intf(duthost, "Vlan1000", ["fc02:1000::2/64"], - ["fc02:1000::1/64"], is_ipv4=False) + check_show_ip_intf(duthost, vlan_info["v4"]["name"], [ipaddr_plus(vlan_info["v4"]["prefix"])], + [], is_ipv4=True) + check_show_ip_intf(duthost, vlan_info["v6"]["name"], [ipaddr_plus(vlan_info["v6"]["prefix"])], + [], is_ipv4=False) finally: delete_tmpfile(duthost, tmpfile) -def vlan_interface_tc1_remove(duthost): +def vlan_interface_tc1_remove(duthost, vlan_info): """ Remove all VLAN intf """ json_patch = [ @@ -272,10 +359,10 @@ def vlan_interface_tc1_remove(duthost): output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) expect_op_success(duthost, output) - check_show_ip_intf(duthost, "Vlan1000", [], - ["192.168.0.2/21", ], is_ipv4=True) - check_show_ip_intf(duthost, "Vlan1000", [], - ["fc02:1000::2/64"], is_ipv4=False) + check_show_ip_intf(duthost, vlan_info["v4"]["name"], [], + [ipaddr_plus(vlan_info["v4"]["prefix"])], is_ipv4=True) + check_show_ip_intf(duthost, vlan_info["v6"]["name"], [], + [ipaddr_plus(vlan_info["v6"]["prefix"])], is_ipv4=False) check_show_ip_intf(duthost, "Vlan2000", [], ["192.168.8.1/21"], is_ipv4=True) check_show_ip_intf(duthost, "Vlan2000", [], @@ -284,12 +371,12 @@ def vlan_interface_tc1_remove(duthost): delete_tmpfile(duthost, tmpfile) -def test_vlan_interface_tc1_suite(rand_selected_dut): - vlan_interface_tc1_add_duplicate(rand_selected_dut) - vlan_interface_tc1_xfail(rand_selected_dut) +def test_vlan_interface_tc1_suite(rand_selected_dut, vlan_info): + vlan_interface_tc1_add_duplicate(rand_selected_dut, vlan_info) + vlan_interface_tc1_xfail(rand_selected_dut, vlan_info) vlan_interface_tc1_add_new(rand_selected_dut) - vlan_interface_tc1_replace(rand_selected_dut) - vlan_interface_tc1_remove(rand_selected_dut) + vlan_interface_tc1_replace(rand_selected_dut, vlan_info) + vlan_interface_tc1_remove(rand_selected_dut, vlan_info) def test_vlan_interface_tc2_incremental_change(rand_selected_dut): diff --git a/tests/vlan/test_vlan_ping.py b/tests/vlan/test_vlan_ping.py index 891f001abd0..039efaba3ce 100644 --- a/tests/vlan/test_vlan_ping.py +++ b/tests/vlan/test_vlan_ping.py @@ -3,6 +3,7 @@ import ipaddress import logging import ptf.testutils as testutils +from tests.common.helpers.assertions import pytest_assert as py_assert from tests.common.plugins import ptfadapter logger = logging.getLogger(__name__) @@ -52,7 +53,16 @@ def vlan_ping_setup(duthosts, rand_one_dut_hostname, ptfhost, nbrhosts, tbinfo): Teardown: deletes ipv4 and ipv6 address on ptf hosts and removes routes to VM. Also removes residual static arp entries from tests """ vm_host_info = {} - vm_name, vm_info = random.choice(nbrhosts.items()) + + vm_name, vm_info = None, None + topo_name = tbinfo["topo"]["name"] + for nbr_name, nbr_info in nbrhosts.items(): + if topo_name != "m0" or (topo_name == "m0" and "M1" in nbr_name): + vm_name = nbr_name + vm_info = nbr_info + break + + py_assert(vm_name is not None, "Can't get neighbor vm") vm_ip_with_prefix = (vm_info['conf']['interfaces']['Port-Channel1']['ipv4']).decode('utf-8') output = vm_info['host'].command("ip addr show dev po1") vm_host_info["mac"] = output['stdout_lines'][1].split()[1] @@ -101,15 +111,16 @@ def vlan_ping_setup(duthosts, rand_one_dut_hostname, ptfhost, nbrhosts, tbinfo): ) # getting port index, mac, ipv4 and ipv6 of ptf ports into a dict - for member in rand_vlan_member_list: - random_ip_in_vlan = random.choice([x for x in vlan_ip_network_v4 if x not in exclude_ip]) + for index in range(len(rand_vlan_member_list)): + member = rand_vlan_member_list[index] + ip_in_vlan = [x for x in vlan_ip_network_v4 if x not in exclude_ip][index] ptfhost_info[member] = {} ptfhost_info[member]["Vlanid"] = vlanid ptfhost_info[member]["port_index"] = mg_facts['minigraph_ptf_indices'][member] ptfhost_info[member]["mac"] = (ptfhost.shell( "ifconfig eth%d | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'" % ptfhost_info[member][ "port_index"]))['stdout'] - ptfhost_info[member]["ipv4"] = str(random_ip_in_vlan) + ptfhost_info[member]["ipv4"] = str(ip_in_vlan) ptfhost_info[member]["ipv6"] = str( ipaddress.IPv6Interface(ip6).network[ptfhost_info[member]["port_index"]]) From 479c7b25225ef19a269bcfd27a3b70426f1fb769 Mon Sep 17 00:00:00 2001 From: yaqiangz Date: Mon, 10 Oct 2022 06:57:34 +0000 Subject: [PATCH 2/2] Fix comments --- .../tests_mark_conditions.yaml | 6 --- .../test_vlan_interface.py | 47 +++++++++++++++---- tests/vlan/test_vlan_ping.py | 19 ++------ 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml index 12a38ff54cb..b14686f0aea 100644 --- a/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml +++ b/tests/common/plugins/conditional_mark/tests_mark_conditions.yaml @@ -271,12 +271,6 @@ generic_config_updater: conditions: - "'t2' in topo_name" -generic_config_updater/test_bgp_speaker.py: - skip: - reason: "M0 topo does not support test_bgp_speaker" - conditions: - - "topo_name in ['m0']" - generic_config_updater/test_eth_interface.py::test_replace_fec: skip: reason: 'replace_fec ethernet test is not supported on virtual switch' diff --git a/tests/generic_config_updater/test_vlan_interface.py b/tests/generic_config_updater/test_vlan_interface.py index 537a092f2a6..538b8c4b160 100644 --- a/tests/generic_config_updater/test_vlan_interface.py +++ b/tests/generic_config_updater/test_vlan_interface.py @@ -166,18 +166,45 @@ def reg_replace(str, reg, replace_str): def vlan_interface_tc1_xfail(duthost, vlan_info): - """ Test expect fail testcase - - ("add", "Vlan1000", "587.168.0.1/21", "fc02:1000::1/64"), ADD Invalid IPv4 address - ("add", "Vlan1000", "192.168.0.1/21", "fc02:1000::xyz/64"), ADD Invalid IPv6 address - ("remove", "Vlan1000", "192.168.0.2/21", "fc02:1000::1/64"), REMOVE Unexist IPv4 address - ("remove", "Vlan1000", "192.168.0.1/21", "fc02:1000::2/64") REMOVE Unexist IPv6 address """ + Get invalid IPv4/IPv6 address and unexist IPv4/IPv6 address by vlan_info and then add/remove them. + + For example: + vlan_info = { + "v4": { + "name": "Vlan1000", + "prefix": "192.168.0.1/24" + }, + "v6": { + "name": "Vlan1000", + "prefix": "fc02:1000::1/64" + } + } + + then we can get: + invalid_ipv4_address = "587.168.0.1/24" (Replace "192" with "587" in "192.168.0.1/24") + invalid_ipv6_address = "fc02:1000::xyz/64" (Replace last "1" with "xyz" in "fc02:1000::1/64") + unexist_ipv4_address = "192.168.0.2/24" (Next ip address behind 192.168.0.1/24) + unexist_ipv6_address = "fc02:1000::2/64" (Next ip address behind fc02:1000::1/64) + + and then construct xfail_input: + xfail_input = [ + ("add", "Vlan1000", "587.168.0.1/24", "fc02:1000::1/64"), # Add invalid IPv4 address + ("add", "Vlan1000", "192.168.0.1/24", "fc02:1000::xyz/64"), # Add invalid IPv6 address + ("remove", "Vlan1000", "192.168.0.2/24", "fc02:1000::1/64"), # Remove unexist IPv4 address + ("remove", "Vlan1000", "192.168.0.1/24", "fc02:1000::2/64") # Remove unexist IPv6 address + ] + """ + invalid_ipv4_address = reg_replace(vlan_info["v4"]["prefix"], r"^\d*", "587") + invalid_ipv6_address = reg_replace(vlan_info["v6"]["prefix"], r":\d*/", ":xyz/") + unexist_ipv4_address = ipaddr_plus(vlan_info["v4"]["prefix"]) + unexist_ipv6_address = ipaddr_plus(vlan_info["v6"]["prefix"]) + xfail_input = [ - ("add", vlan_info["v4"]["name"], reg_replace(vlan_info["v4"]["prefix"], r"^\d*", "587"), vlan_info["v6"]["prefix"]), - ("add", vlan_info["v4"]["name"], vlan_info["v4"]["prefix"], reg_replace(vlan_info["v6"]["prefix"], r":\d*/", ":xyz/")), - ("remove", vlan_info["v4"]["name"], ipaddr_plus(vlan_info["v4"]["prefix"]), vlan_info["v6"]["prefix"]), - ("remove", vlan_info["v4"]["name"], vlan_info["v4"]["prefix"], ipaddr_plus(vlan_info["v6"]["prefix"])) + ("add", vlan_info["v4"]["name"], invalid_ipv4_address, vlan_info["v6"]["prefix"]), + ("add", vlan_info["v4"]["name"], vlan_info["v4"]["prefix"], invalid_ipv6_address), + ("remove", vlan_info["v4"]["name"], unexist_ipv4_address, vlan_info["v6"]["prefix"]), + ("remove", vlan_info["v4"]["name"], vlan_info["v4"]["prefix"], unexist_ipv6_address) ] for op, name, ip, ipv6 in xfail_input: dummy_vlan_interface_v4 = name + "|" + ip diff --git a/tests/vlan/test_vlan_ping.py b/tests/vlan/test_vlan_ping.py index 039efaba3ce..891f001abd0 100644 --- a/tests/vlan/test_vlan_ping.py +++ b/tests/vlan/test_vlan_ping.py @@ -3,7 +3,6 @@ import ipaddress import logging import ptf.testutils as testutils -from tests.common.helpers.assertions import pytest_assert as py_assert from tests.common.plugins import ptfadapter logger = logging.getLogger(__name__) @@ -53,16 +52,7 @@ def vlan_ping_setup(duthosts, rand_one_dut_hostname, ptfhost, nbrhosts, tbinfo): Teardown: deletes ipv4 and ipv6 address on ptf hosts and removes routes to VM. Also removes residual static arp entries from tests """ vm_host_info = {} - - vm_name, vm_info = None, None - topo_name = tbinfo["topo"]["name"] - for nbr_name, nbr_info in nbrhosts.items(): - if topo_name != "m0" or (topo_name == "m0" and "M1" in nbr_name): - vm_name = nbr_name - vm_info = nbr_info - break - - py_assert(vm_name is not None, "Can't get neighbor vm") + vm_name, vm_info = random.choice(nbrhosts.items()) vm_ip_with_prefix = (vm_info['conf']['interfaces']['Port-Channel1']['ipv4']).decode('utf-8') output = vm_info['host'].command("ip addr show dev po1") vm_host_info["mac"] = output['stdout_lines'][1].split()[1] @@ -111,16 +101,15 @@ def vlan_ping_setup(duthosts, rand_one_dut_hostname, ptfhost, nbrhosts, tbinfo): ) # getting port index, mac, ipv4 and ipv6 of ptf ports into a dict - for index in range(len(rand_vlan_member_list)): - member = rand_vlan_member_list[index] - ip_in_vlan = [x for x in vlan_ip_network_v4 if x not in exclude_ip][index] + for member in rand_vlan_member_list: + random_ip_in_vlan = random.choice([x for x in vlan_ip_network_v4 if x not in exclude_ip]) ptfhost_info[member] = {} ptfhost_info[member]["Vlanid"] = vlanid ptfhost_info[member]["port_index"] = mg_facts['minigraph_ptf_indices'][member] ptfhost_info[member]["mac"] = (ptfhost.shell( "ifconfig eth%d | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'" % ptfhost_info[member][ "port_index"]))['stdout'] - ptfhost_info[member]["ipv4"] = str(ip_in_vlan) + ptfhost_info[member]["ipv4"] = str(random_ip_in_vlan) ptfhost_info[member]["ipv6"] = str( ipaddress.IPv6Interface(ip6).network[ptfhost_info[member]["port_index"]])