From 5469367a6b24ff48096a07e98569c7c858614df6 Mon Sep 17 00:00:00 2001 From: junchao Date: Wed, 12 Jan 2022 18:48:25 +0800 Subject: [PATCH 01/10] Add route flow counter related test cases Change-Id: I4b9b1dd1c5372645c67511ddcc667b99f427d556 --- tests/bgp/test_bgp_speaker.py | 28 +-- tests/flow_counter/__init__.py | 0 tests/flow_counter/flow_counter_utils.py | 278 +++++++++++++++++++++++ tests/route/__init__.py | 0 tests/route/test_route_flow_counter.py | 158 +++++++++++++ tests/route/test_static_route.py | 7 +- tests/vxlan/test_vnet_vxlan.py | 31 ++- 7 files changed, 478 insertions(+), 24 deletions(-) create mode 100644 tests/flow_counter/__init__.py create mode 100644 tests/flow_counter/flow_counter_utils.py create mode 100644 tests/route/__init__.py create mode 100644 tests/route/test_route_flow_counter.py diff --git a/tests/bgp/test_bgp_speaker.py b/tests/bgp/test_bgp_speaker.py index 1d063ac2e8..0f595181a2 100644 --- a/tests/bgp/test_bgp_speaker.py +++ b/tests/bgp/test_bgp_speaker.py @@ -15,6 +15,7 @@ from tests.common.utilities import wait_tcp_connection from tests.common.helpers.assertions import pytest_require from tests.common.utilities import wait_until +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext pytestmark = [ @@ -311,19 +312,20 @@ def bgp_speaker_announce_routes_common(common_setup_teardown, logger.info("run ptf test") - ptf_runner(ptfhost, - "ptftests", - "fib_test.FibTest", - platform_dir="ptftests", - params={"router_macs": [duthost.facts['router_mac']], - "ptf_test_port_map": PTF_TEST_PORT_MAP, - "fib_info_files": ["/root/bgp_speaker_route_%s.txt" % family], - "ipv4": ipv4, - "ipv6": ipv6, - "testbed_mtu": mtu, - "test_balancing": False}, - log_file="/tmp/bgp_speaker_test.FibTest.log", - socket_recv_size=16384) + with RouteFlowCounterTestContext(duthost, [prefix], {prefix : {'packets': 3, 'bytes': 4554}}): + ptf_runner(ptfhost, + "ptftests", + "fib_test.FibTest", + platform_dir="ptftests", + params={"router_macs": [duthost.facts['router_mac']], + "ptf_test_port_map": PTF_TEST_PORT_MAP, + "fib_info_files": ["/root/bgp_speaker_route_%s.txt" % family], + "ipv4": ipv4, + "ipv6": ipv6, + "testbed_mtu": mtu, + "test_balancing": False}, + log_file="/tmp/bgp_speaker_test.FibTest.log", + socket_recv_size=16384) logger.info("Withdraw routes") withdraw_route(ptfip, lo_addr, prefix, nexthop_ips[1].ip, port_num[0]) diff --git a/tests/flow_counter/__init__.py b/tests/flow_counter/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/flow_counter/flow_counter_utils.py b/tests/flow_counter/flow_counter_utils.py new file mode 100644 index 0000000000..6fa0e36ad1 --- /dev/null +++ b/tests/flow_counter/flow_counter_utils.py @@ -0,0 +1,278 @@ +import logging +import random +from tests.common.helpers.assertions import pytest_assert +from tests.common.utilities import wait_until, check_skip_release + +logger = logging.getLogger(__name__) + +support_route_flow_counter = None +skip_versions = ['201811', '201911', '202012', '202106', '202111'] +CAPABILITY_WAIT_TIME_IN_SEC = 180 +CAPABILITY_CHECK_INTERVAL_IN_SEC = 5 + + +class RouteFlowCounterTestContext: + """Allow caller to use "with" key words to run router flow counter test. + """ + def __init__(self, dut, route_pattern_list, expected_stats, interval=1000): + """Init RouteFlowCounterTestContext + + Args: + dut (object): DUT object + route_pattern_list (list): a list of route pattern, e.g. ['1.1.1.0/24', 'Vrf1|1.1.1.0/24', 'Vnet1|2.2.2.0/24'] + expected_stats (dict): Expected result value. e.g. {'1.1.1.0/24': {'packets': '5', 'bytes': '4500'}} + interval (int, optional): Route flow counter query interval. Defaults to 1000. + """ + self.dut = dut + self.route_pattern_list = route_pattern_list + self.expected_stats = expected_stats + self.interval = interval + + def __enter__(self): + """Enable route flow counter and configure route pattern + """ + if not is_route_flow_counter_supported(self.dut): + return + set_route_flow_counter_interval(self.dut, self.interval) + set_route_flow_counter_status(self.dut, True) + for route_pattern in self.route_pattern_list: + set_route_flow_counter_pattern(self.dut, route_pattern) + + def __exit__(self, exc_type, exc_val, exc_tb): + """Do following tasks: + 1. Verify route flow counter stats agaist expected value + 2. Disable route flow coutern and remove route pattern + + Args: + exc_type (object): not used + exc_val (object): not used + exc_tb (object): not used + """ + if not is_route_flow_counter_supported(self.dut): + return + + try: + result, message = self.check_stats() + pytest_assert(result, message) + finally: + set_route_flow_counter_status(self.dut, False) + for route_pattern in self.route_pattern_list: + remove_route_flow_counter_pattern(self.dut, route_pattern) + + + def check_stats(self): + """Verify route flow counter statistic + + Returns: + tuple: (status, error message) + """ + logger.info('Checking route flow counter stats') + actual_stats = parse_route_flow_counter_stats(self.dut) + result, message = verify_route_flow_counter_stats(self.expected_stats, actual_stats) + if not result: + return result, message + + if len(self.expected_stats) > 0: + logger.info('Checking route flow counter stats after clearing by route') + to_clear = random.sample(list(self.expected_stats.keys()), 1)[0] + clear_route_flow_counter_by_route(self.dut, to_clear) + for key in self.expected_stats[to_clear]: + self.expected_stats[to_clear][key] = '0' + actual_stats = parse_route_flow_counter_stats(self.dut) + result, message = verify_route_flow_counter_stats(self.expected_stats, actual_stats) + if not result: + return result, message + + if len(self.expected_stats) == 1 and len(self.route_pattern_list) == 1: + logger.info('Checking route flow counter stats after clearing by pattern') + clear_route_flow_counter_by_pattern(self.dut, self.route_pattern_list[0]) + else: + logger.info('Checking route flow counter stats after clearing all routes') + clear_route_flow_counter(self.dut) + for prefix, value in self.expected_stats.items(): + for key in value: + self.expected_stats[prefix][key] = '0' + + actual_stats = parse_route_flow_counter_stats(self.dut) + return verify_route_flow_counter_stats(self.expected_stats, actual_stats) + + +def is_route_flow_counter_supported(dut): + """Check if route flow counter is supported on this platform + + Args: + dut (object): DUT object + + Returns: + bool: True if supported + """ + skip, _ = check_skip_release(dut, skip_versions) + if skip: + return False + + global support_route_flow_counter + if support_route_flow_counter is None: + if not wait_until(CAPABILITY_WAIT_TIME_IN_SEC, CAPABILITY_CHECK_INTERVAL_IN_SEC, 0, get_route_flow_counter_capability, dut): + support_route_flow_counter = False + pytest_assert(False, 'Failed to get route flow counter capability') + if not support_route_flow_counter: + logger.info('Route flow counter is not supported on this platform') + return support_route_flow_counter + + +def get_route_flow_counter_capability(dut): + """Get route flow counter capability from STATE DB + + Args: + dut (object): DUT object + + Returns: + bool: True if capability is successfully retrieved from STATE DB + """ + global support_route_flow_counter + support = dut.shell('sudo sonic-db-cli STATE_DB HGET "FLOW_COUNTER_CAPABILITY_TABLE|route" support')['stdout'].strip() + if support == 'true': + support_route_flow_counter = True + elif support == 'false': + support_route_flow_counter = False + return support_route_flow_counter is not None + + +def set_route_flow_counter_status(dut, status): + """Set route flow counter status + + Args: + dut (object): DUT object + status (bool): Enable if True else disable + """ + dut.command('counterpoll flowcnt-route {}'.format('enable' if status else 'disable')) + + +def set_route_flow_counter_interval(dut, interval): + """Set route flow counter interval + + Args: + dut (object): DUT object + interval (int): Query interval value in ms + """ + dut.command('counterpoll flowcnt-route interval {}'.format(interval)) + + +def set_route_flow_counter_pattern(dut, route_pattern, max_match_count=30): + """Set route pattern for route flow counter + + Args: + dut (object): DUT object + route_pattern (str): Route pattern. e.g. "1.1.1.0/24", "2000::/64", "Vrf1|2.2.2.0/24" + max_match_count (int, optional): Max allowed match count. Defaults to 30. + """ + items = route_pattern.split('|') + if len(items) == 2: + dut.command('sudo config flowcnt-route pattern add {} --vrf {} --max {} -y'.format(items[1], items[0], max_match_count)) + elif len(items) == 1: + dut.command('sudo config flowcnt-route pattern add {} --max {} -y'.format(items[0], max_match_count)) + else: + logger.error('Invalid route pattern {}'.format(route_pattern)) + + +def remove_route_flow_counter_pattern(dut, route_pattern): + """Remove route pattern for route flow counter + + Args: + dut (object): DUT object + route_pattern (str): Route pattern. e.g. "1.1.1.0/24", "2000::/64", "Vrf1|2.2.2.0/24" + """ + items = route_pattern.split('|') + if len(items) == 2: + dut.command('sudo config flowcnt-route pattern remove {} --vrf {}'.format(items[1], items[0])) + elif len(items) == 1: + dut.command('sudo config flowcnt-route pattern remove {}'.format(items[0])) + else: + logger.error('Invalid route pattern {}'.format(route_pattern)) + + +def clear_route_flow_counter(dut): + """Clear all route flow counter statistics + + Args: + dut (object): DUT object + """ + dut.command('sonic-clear flowcnt-route') + + +def clear_route_flow_counter_by_pattern(dut, route_pattern): + """Clear route flow counter statistics by pattern + + Args: + dut (object): DUT object + route_pattern (str): Route pattern. e.g. "1.1.1.0/24", "2000::/64", "Vrf1|2.2.2.0/24" + """ + items = route_pattern.split('|') + if len(items) == 2: + dut.command('sonic-clear flowcnt-route pattern {} --vrf {}'.format(items[1], items[0])) + elif len(items) == 1: + dut.command('sonic-clear flowcnt-route pattern {}'.format(items[0])) + else: + logger.error('Invalid route pattern {}'.format(route_pattern)) + + +def clear_route_flow_counter_by_route(dut, prefix): + """Clear route flow counter statistics by route + + Args: + dut (object): DUT object + prefix (str): Prefix pattern. e.g. "1.1.1.0/24", "2000::/64", "Vrf1|2.2.2.0/24" + """ + items = prefix.split('|') + if len(items) == 2: + dut.command('sonic-clear flowcnt-route route {} --vrf {}'.format(items[1], items[0])) + elif len(items) == 1: + dut.command('sonic-clear flowcnt-route route {}'.format(items[0])) + else: + logger.error('Invalid prefix pattern {}'.format(prefix)) + + +def parse_route_flow_counter_stats(dut): + """Parse command output of "show flowcnt-route stats" + + Args: + dut (object): DUT object + + Returns: + dict: Parsed result. e.g. {'1.1.1.0/24': {'packets': '5', 'bytes': '4500'}} + """ + stats_list = dut.show_and_parse('show flowcnt-route stats') + parse_result = {} + for stats in stats_list: + if stats['vrf'] == 'default': + key = stats['matched routes'] + else: + key = '|'.join([stats['vrf'], stats['matched routes']]) + parse_result[key] = { + 'packets': stats['packets'], + 'bytes': stats['bytes'] + } + return parse_result + + +def verify_route_flow_counter_stats(expect_stats, actual_stats): + """Verify actual statistic with expected statistic + + Args: + expect_stats (dict): Expected stats. e.g. {'1.1.1.0/24': {'packets': '5', 'bytes': '4500'}} + actual_stats (dict): Actual stats. e.g. {'1.1.1.0/24': {'packets': '5', 'bytes': '4500'}} + + Returns: + bool: Match if True. + """ + logger.info('Expected stats: {}'.format(expect_stats)) + logger.info('Actual stats: {}'.format(actual_stats)) + for key, value in expect_stats.items(): + if key not in actual_stats: + return False, 'Failed to find {} in result'.format(key) + + for stats_type, expect_value in value.items(): + if int(expect_value) != int(actual_stats[key][stats_type].replace(',', '')): + return False, 'Expected {} value of {} is {}, but got {}'.format(stats_type, key, expect_value, actual_stats[key][stats_type]) + + return True, None diff --git a/tests/route/__init__.py b/tests/route/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/route/test_route_flow_counter.py b/tests/route/test_route_flow_counter.py new file mode 100644 index 0000000000..ee51b79183 --- /dev/null +++ b/tests/route/test_route_flow_counter.py @@ -0,0 +1,158 @@ +import logging +import pytest +from tests.common.helpers.assertions import pytest_assert, pytest_require +from tests.flow_counter import flow_counter_utils + +logger = logging.getLogger(__name__) + + +@pytest.fixture(scope='function', autouse=True) +def skip_if_not_supported(rand_selected_dut): + """Skip the test if route flow counter is not supported on this platform + + Args: + rand_selected_dut (object): DUT object + """ + pytest_require(flow_counter_utils.is_route_flow_counter_supported(rand_selected_dut)) + + +class TestRouteCounter: + @pytest.mark.parametrize("route_flow_counter_params", [(False, '1.1.0.0/16', '1.1.1.0/24'), + (True, '1234::/64', '1234::/64')]) + def test_add_remove_route(self, rand_selected_dut, route_flow_counter_params): + """Test steps: + 1. Add route and verify the route flow counter is created. + 2. Remove route and verify the route flow counter is removed. + + Args: + rand_selected_dut (object): DUT object + route_flow_counter_params (list): A list contains the test parameter. [ipv6, route_pattern, prefix] + """ + duthost = rand_selected_dut + ipv6 = route_flow_counter_params[0] + route_pattern = route_flow_counter_params[1] + prefix = route_flow_counter_params[2] + flow_counter_utils.set_route_flow_counter_status(duthost, True) + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern) + nexthop_addr = self._get_nexthop(duthost, ipv6=ipv6) + + logger.info('Adding static route {} {}, check route flow counter is created'.format(prefix, nexthop_addr)) + duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix, nexthop_addr)) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(prefix in stats, 'Route flow counter is not created') + + logger.info('Removing static route {} {}, check route flow counter is removed'.format(prefix, nexthop_addr)) + duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix), module_ignore_errors=True) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(prefix not in stats, 'Route flow counter is not removed') + + flow_counter_utils.set_route_flow_counter_status(duthost, False) + flow_counter_utils.remove_route_flow_counter_pattern(duthost, route_pattern) + + @pytest.mark.parametrize("route_flow_counter_params", [(False, '1.1.0.0/16', '1.2.0.0/16', '1.1.1.0/24', '1.2.1.0/24'), + (True, '1234:0:0:1::/64', '1234:0:0:2::/64', '1234:0:0:1::/64', '1234:0:0:2::/64')]) + def test_update_route_pattern(self, rand_selected_dut, route_flow_counter_params): + """Test steps: + 1. Add two routes a and b, configure route pattern match a + 2. Verify only route flow counter for a is created + 3. Update route pattern to match b + 4. Verify only route flow counter for b is created + + Args: + rand_selected_dut (object): DUT object + route_flow_counter_params (list): A list contains the test parameter. [ipv6, pattern_a, pattern_b, prefix_a, prefix_b] + """ + duthost = rand_selected_dut + ipv6 = route_flow_counter_params[0] + route_pattern_a = route_flow_counter_params[1] + route_pattern_b = route_flow_counter_params[2] + prefix_a = route_flow_counter_params[3] + prefix_b = route_flow_counter_params[4] + flow_counter_utils.set_route_flow_counter_status(duthost, True) + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern_a) + nexthop_addr = self._get_nexthop(duthost, ipv6=ipv6) + + logger.info('Adding static route {} and {}'.format(prefix_a, prefix_b)) + duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix_a, nexthop_addr)) + duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix_b, nexthop_addr)) + + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(prefix_a in stats, 'Route flow counter for {} is not created'.format(prefix_a)) + pytest_assert(prefix_b not in stats, 'Route flow counter for {} should not be created'.format(prefix_b)) + + + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern_b) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(prefix_a not in stats, 'Route flow counter for {} is not removed'.format(prefix_a)) + pytest_assert(prefix_b in stats, 'Route flow counter for {} is not created'.format(prefix_b)) + + duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix_a), module_ignore_errors=True) + duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix_b), module_ignore_errors=True) + + flow_counter_utils.set_route_flow_counter_status(duthost, False) + flow_counter_utils.remove_route_flow_counter_pattern(duthost, route_pattern_b) + + def test_max_match_count(self, rand_selected_dut): + """Test steps: + 1. Add 3 routes, set max allowed match to 2, verify only 2 route flow counters are created + 2. Remove 1 routes, verify that there are still 2 route flow counters as it should automatically fill the room + 3. Set max_allowed_match to 1, verify that there is 1 route flow counter + 4. Set max_allowed match to 2 again, verify that there are two route flow counter as it should automatically fill the room + + Args: + rand_selected_dut ([type]): [description] + """ + duthost = rand_selected_dut + route_pattern = '1.1.0.0/16' + prefix_list = ['1.1.1.0/24', '1.1.2.0/24', '1.1.3.0/24'] + nexthop_addr = self._get_nexthop(duthost, False) + flow_counter_utils.set_route_flow_counter_status(duthost, True) + expect_route_flow_counter = len(prefix_list) - 1 + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) + logger.info('Adding {} static routes while max allowed match count is {}'.format(len(prefix_list), expect_route_flow_counter)) + for prefix in prefix_list: + duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix, nexthop_addr)) + + logger.info('Verify there are {} route flow counters'.format(expect_route_flow_counter)) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + + pytest_assert(len(stats) == expect_route_flow_counter, 'Expecetd {} route flow counters, but got {} counters'.format(expect_route_flow_counter, len(stats))) + + logger.info('Removing a route, verify there are still {} route flow counters'.format(expect_route_flow_counter)) + duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix_list[0]), module_ignore_errors=True) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) + + expect_route_flow_counter -= 1 + logger.info('Set max_match_count to {}, verify there is {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)) + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) + + expect_route_flow_counter += 1 + logger.info('Set max_match_count to {}, verify there is {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)) + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) + + for prefix in prefix_list: + duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix), module_ignore_errors=True) + flow_counter_utils.set_route_flow_counter_status(duthost, False) + flow_counter_utils.remove_route_flow_counter_pattern(duthost, route_pattern) + + def _get_nexthop(self, duthost, ipv6): + """Get next hop from BGP neighbors + + Args: + duthost (object): DUT object + ipv6 (bool): True if getting IPv6 nexthop + + Returns: + str: Nexthop IP + """ + if ipv6: + cmd = 'show ipv6 bgp summary' + else: + cmd = 'show ip bgp summary' + parse_result = duthost.show_and_parse(cmd) + return parse_result[0]['neighbhor'] diff --git a/tests/route/test_static_route.py b/tests/route/test_static_route.py index a3226e9c5c..00496b592b 100644 --- a/tests/route/test_static_route.py +++ b/tests/route/test_static_route.py @@ -19,6 +19,7 @@ import ptf.packet as packet from pkg_resources import parse_version from tests.common import constants +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext pytestmark = [ @@ -165,7 +166,8 @@ def run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, prefix, nexthop_ # Check traffic get forwarded to the nexthop ip_dst = str(ipaddress.ip_network(unicode(prefix))[1]) - generate_and_verify_traffic(duthost, ptfadapter, tbinfo, ip_dst, nexthop_devs, ipv6=ipv6) + with RouteFlowCounterTestContext(duthost, [prefix], {prefix: {'packets': '1'}}): + generate_and_verify_traffic(duthost, ptfadapter, tbinfo, ip_dst, nexthop_devs, ipv6=ipv6) # Check the route is advertised to the neighbors check_route_redistribution(duthost, prefix, ipv6) @@ -177,7 +179,8 @@ def run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, prefix, nexthop_ #FIXME: We saw re-establishing BGP sessions can takes around 7 minutes # on some devices (like 4600) after config reload, so we need below patch wait_all_bgp_up(duthost) - generate_and_verify_traffic(duthost, ptfadapter, tbinfo, ip_dst, nexthop_devs, ipv6=ipv6) + with RouteFlowCounterTestContext(duthost, [prefix], {prefix: {'packets': '1'}}): + generate_and_verify_traffic(duthost, ptfadapter, tbinfo, ip_dst, nexthop_devs, ipv6=ipv6) check_route_redistribution(duthost, prefix, ipv6) finally: diff --git a/tests/vxlan/test_vnet_vxlan.py b/tests/vxlan/test_vnet_vxlan.py index 129f3a696f..d6a0b01a47 100644 --- a/tests/vxlan/test_vnet_vxlan.py +++ b/tests/vxlan/test_vnet_vxlan.py @@ -1,6 +1,7 @@ import json import logging import pytest +import random from datetime import datetime from tests.ptf_runner import ptf_runner @@ -11,7 +12,7 @@ from tests.common.fixtures.ptfhost_utils import remove_ip_addresses, change_mac_addresses, \ copy_arp_responder_py, copy_ptftests_directory - +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext import tests.arp.test_wr_arp as test_wr_arp logger = logging.getLogger(__name__) @@ -133,7 +134,7 @@ def vxlan_status(setup, request, duthosts, rand_one_dut_hostname, ptfhost, vnet_ return vxlan_enabled, request.param -def test_vnet_vxlan(setup, vxlan_status, duthosts, rand_one_dut_hostname, ptfhost, vnet_test_params, creds): +def test_vnet_vxlan(setup, vxlan_status, duthosts, rand_one_dut_hostname, ptfhost, vnet_test_params, vnet_config, creds): """ Test case for VNET VxLAN @@ -169,10 +170,22 @@ def test_vnet_vxlan(setup, vxlan_status, duthosts, rand_one_dut_hostname, ptfhos pytest.skip("Skip cleanup specified") logger.debug("Starting PTF runner") - ptf_runner(ptfhost, - "ptftests", - "vnet_vxlan.VNET", - platform_dir="ptftests", - params=ptf_params, - qlen=1000, - log_file=log_file) + if scenario == 'Enabled' and vxlan_enabled: + route_pattern = 'Vnet1|100.1.1.1/32' + with RouteFlowCounterTestContext(duthost, [route_pattern], {route_pattern: {'packets': '3'}}): + ptf_runner(ptfhost, + "ptftests", + "vnet_vxlan.VNET", + platform_dir="ptftests", + params=ptf_params, + qlen=1000, + log_file=log_file) + else: + ptf_runner(ptfhost, + "ptftests", + "vnet_vxlan.VNET", + platform_dir="ptftests", + params=ptf_params, + qlen=1000, + log_file=log_file) + From dac195d370af306504906b2c34b4e4023eaa0cf0 Mon Sep 17 00:00:00 2001 From: junchao Date: Mon, 14 Feb 2022 18:01:53 +0800 Subject: [PATCH 02/10] Fix LGTM warning Change-Id: I70d4fdd3160e7a31dfca66d829491b19630adc92 --- tests/vxlan/test_vnet_vxlan.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/vxlan/test_vnet_vxlan.py b/tests/vxlan/test_vnet_vxlan.py index d6a0b01a47..23d471d57b 100644 --- a/tests/vxlan/test_vnet_vxlan.py +++ b/tests/vxlan/test_vnet_vxlan.py @@ -1,7 +1,6 @@ import json import logging import pytest -import random from datetime import datetime from tests.ptf_runner import ptf_runner From 6238b27f4ca28baf6e6ac350063b73512ee8c282 Mon Sep 17 00:00:00 2001 From: junchao Date: Wed, 27 Apr 2022 14:10:45 +0800 Subject: [PATCH 03/10] Fix review comment Change-Id: Iad925eaf3c605780e9d41802240ba89b8a4dce2f --- tests/bgp/test_bgp_speaker.py | 5 +- tests/flow_counter/flow_counter_utils.py | 81 ++++++---- tests/route/test_route_flow_counter.py | 196 +++++++++++++---------- 3 files changed, 167 insertions(+), 115 deletions(-) diff --git a/tests/bgp/test_bgp_speaker.py b/tests/bgp/test_bgp_speaker.py index 9565267371..e5166a7c5e 100644 --- a/tests/bgp/test_bgp_speaker.py +++ b/tests/bgp/test_bgp_speaker.py @@ -308,8 +308,9 @@ def bgp_speaker_announce_routes_common(common_setup_teardown, ptfhost.copy(content=json.dumps(ptf_test_port_map), dest=PTF_TEST_PORT_MAP) logger.info("run ptf test") - - with RouteFlowCounterTestContext(duthost, [prefix], {prefix : {'packets': 3, 'bytes': 4554}}): + expecte_packet_num = 3 + packet_size = 1518 + with RouteFlowCounterTestContext(duthost, [prefix], {prefix : {'packets': expecte_packet_num, 'bytes': packet_size * expecte_packet_num}}): ptf_runner(ptfhost, "ptftests", "fib_test.FibTest", diff --git a/tests/flow_counter/flow_counter_utils.py b/tests/flow_counter/flow_counter_utils.py index 6fa0e36ad1..e73017ddbe 100644 --- a/tests/flow_counter/flow_counter_utils.py +++ b/tests/flow_counter/flow_counter_utils.py @@ -1,3 +1,4 @@ +import allure import logging import random from tests.common.helpers.assertions import pytest_assert @@ -27,16 +28,18 @@ def __init__(self, dut, route_pattern_list, expected_stats, interval=1000): self.route_pattern_list = route_pattern_list self.expected_stats = expected_stats self.interval = interval + self.is_route_flow_counter_supported = is_route_flow_counter_supported(dut) def __enter__(self): """Enable route flow counter and configure route pattern """ - if not is_route_flow_counter_supported(self.dut): + if not self.is_route_flow_counter_supported: return - set_route_flow_counter_interval(self.dut, self.interval) - set_route_flow_counter_status(self.dut, True) - for route_pattern in self.route_pattern_list: - set_route_flow_counter_pattern(self.dut, route_pattern) + with allure.step('Enable route flow counter and config route flow pattern: {}'.format(','.join(self.route_pattern_list))): + set_route_flow_counter_interval(self.dut, self.interval) + set_route_flow_counter_status(self.dut, True) + for route_pattern in self.route_pattern_list: + set_route_flow_counter_pattern(self.dut, route_pattern) def __exit__(self, exc_type, exc_val, exc_tb): """Do following tasks: @@ -48,7 +51,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): exc_val (object): not used exc_tb (object): not used """ - if not is_route_flow_counter_supported(self.dut): + if not self.is_route_flow_counter_supported: return try: @@ -67,34 +70,37 @@ def check_stats(self): tuple: (status, error message) """ logger.info('Checking route flow counter stats') - actual_stats = parse_route_flow_counter_stats(self.dut) - result, message = verify_route_flow_counter_stats(self.expected_stats, actual_stats) - if not result: - return result, message - - if len(self.expected_stats) > 0: - logger.info('Checking route flow counter stats after clearing by route') - to_clear = random.sample(list(self.expected_stats.keys()), 1)[0] - clear_route_flow_counter_by_route(self.dut, to_clear) - for key in self.expected_stats[to_clear]: - self.expected_stats[to_clear][key] = '0' + with allure.step('Checking route flow counter stats'): actual_stats = parse_route_flow_counter_stats(self.dut) result, message = verify_route_flow_counter_stats(self.expected_stats, actual_stats) if not result: return result, message - if len(self.expected_stats) == 1 and len(self.route_pattern_list) == 1: - logger.info('Checking route flow counter stats after clearing by pattern') - clear_route_flow_counter_by_pattern(self.dut, self.route_pattern_list[0]) - else: - logger.info('Checking route flow counter stats after clearing all routes') - clear_route_flow_counter(self.dut) - for prefix, value in self.expected_stats.items(): - for key in value: - self.expected_stats[prefix][key] = '0' + if len(self.expected_stats) > 0: + logger.info('Checking route flow counter stats after clearing by route') + with allure.step('Checking route flow counter stats after clearing by route'): + to_clear = random.sample(list(self.expected_stats.keys()), 1)[0] + clear_route_flow_counter_by_route(self.dut, to_clear) + for key in self.expected_stats[to_clear]: + self.expected_stats[to_clear][key] = '0' + actual_stats = parse_route_flow_counter_stats(self.dut) + result, message = verify_route_flow_counter_stats(self.expected_stats, actual_stats) + if not result: + return result, message + + with allure.step('Checking route flow counter stats after clearing by pattern or clearing all'): + if len(self.expected_stats) == 1 and len(self.route_pattern_list) == 1: + logger.info('Checking route flow counter stats after clearing by pattern') + clear_route_flow_counter_by_pattern(self.dut, self.route_pattern_list[0]) + else: + logger.info('Checking route flow counter stats after clearing all routes') + clear_route_flow_counter(self.dut) + for prefix, value in self.expected_stats.items(): + for key in value: + self.expected_stats[prefix][key] = '0' - actual_stats = parse_route_flow_counter_stats(self.dut) - return verify_route_flow_counter_stats(self.expected_stats, actual_stats) + actual_stats = parse_route_flow_counter_stats(self.dut) + return verify_route_flow_counter_stats(self.expected_stats, actual_stats) def is_route_flow_counter_supported(dut): @@ -108,6 +114,7 @@ def is_route_flow_counter_supported(dut): """ skip, _ = check_skip_release(dut, skip_versions) if skip: + logger.info('Route flow counter is not supported on these versions: {}'.format(skip_versions)) return False global support_route_flow_counter @@ -135,6 +142,9 @@ def get_route_flow_counter_capability(dut): support_route_flow_counter = True elif support == 'false': support_route_flow_counter = False + elif support: + # Impossible branch, just incase + pytest_assert(False, 'support field of FLOW_COUNTER_CAPABILITY_TABLE|route has invalid value {}'.format(support)) return support_route_flow_counter is not None @@ -190,6 +200,21 @@ def remove_route_flow_counter_pattern(dut, route_pattern): else: logger.error('Invalid route pattern {}'.format(route_pattern)) +def remove_all_route_flow_counter_patterns(dut): + """Remove all route patterns + + Args: + dut (object): DUT object + """ + data = dut.show_and_parse('show flowcnt-route config') + for item in data: + prefix = item['route pattern'] + vrf = item['vrf'] + if vrf != 'default': + dut.command('sudo config flowcnt-route pattern remove {} --vrf {}'.format(prefix, vrf)) + else: + dut.command('sudo config flowcnt-route pattern remove {}'.format(prefix)) + def clear_route_flow_counter(dut): """Clear all route flow counter statistics diff --git a/tests/route/test_route_flow_counter.py b/tests/route/test_route_flow_counter.py index ee51b79183..cb6c59bf76 100644 --- a/tests/route/test_route_flow_counter.py +++ b/tests/route/test_route_flow_counter.py @@ -1,3 +1,4 @@ +import allure import logging import pytest from tests.common.helpers.assertions import pytest_assert, pytest_require @@ -5,6 +6,25 @@ logger = logging.getLogger(__name__) +test_update_route_pattern_para = [ + { + 'is_ipv6': False, + 'route_pattern_a': '1.1.0.0/16', + 'route_pattern_b': '1.2.0.0/16', + 'prefix_a': '1.1.1.0/24', + 'prefix_b': '1.2.1.0/24', + }, + { + 'is_ipv6': True, + 'route_pattern_a': '1234:0:0:1::/64', + 'route_pattern_b': '1234:0:0:2::/64', + 'prefix_a': '1234:0:0:1::/64', + 'prefix_b': '1234:0:0:2::/64', + } +] + +added_routes = set() + @pytest.fixture(scope='function', autouse=True) def skip_if_not_supported(rand_selected_dut): @@ -16,41 +36,48 @@ def skip_if_not_supported(rand_selected_dut): pytest_require(flow_counter_utils.is_route_flow_counter_supported(rand_selected_dut)) -class TestRouteCounter: - @pytest.mark.parametrize("route_flow_counter_params", [(False, '1.1.0.0/16', '1.1.1.0/24'), - (True, '1234::/64', '1234::/64')]) - def test_add_remove_route(self, rand_selected_dut, route_flow_counter_params): - """Test steps: - 1. Add route and verify the route flow counter is created. - 2. Remove route and verify the route flow counter is removed. +@pytest.fixture(scope='function', autouse=True) +def clear_route_flow_counter(rand_selected_dut): + """Clear route flow counter configuration - Args: - rand_selected_dut (object): DUT object - route_flow_counter_params (list): A list contains the test parameter. [ipv6, route_pattern, prefix] - """ - duthost = rand_selected_dut - ipv6 = route_flow_counter_params[0] - route_pattern = route_flow_counter_params[1] - prefix = route_flow_counter_params[2] - flow_counter_utils.set_route_flow_counter_status(duthost, True) - flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern) - nexthop_addr = self._get_nexthop(duthost, ipv6=ipv6) - - logger.info('Adding static route {} {}, check route flow counter is created'.format(prefix, nexthop_addr)) - duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix, nexthop_addr)) - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - pytest_assert(prefix in stats, 'Route flow counter is not created') - - logger.info('Removing static route {} {}, check route flow counter is removed'.format(prefix, nexthop_addr)) - duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix), module_ignore_errors=True) - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - pytest_assert(prefix not in stats, 'Route flow counter is not removed') - - flow_counter_utils.set_route_flow_counter_status(duthost, False) - flow_counter_utils.remove_route_flow_counter_pattern(duthost, route_pattern) - - @pytest.mark.parametrize("route_flow_counter_params", [(False, '1.1.0.0/16', '1.2.0.0/16', '1.1.1.0/24', '1.2.1.0/24'), - (True, '1234:0:0:1::/64', '1234:0:0:2::/64', '1234:0:0:1::/64', '1234:0:0:2::/64')]) + Args: + rand_selected_dut (object): DUT object + """ + yield + + flow_counter_utils.set_route_flow_counter_status(rand_selected_dut, False) + flow_counter_utils.remove_all_route_flow_counter_patterns(rand_selected_dut) + for route in added_routes: + rand_selected_dut.shell('config route del prefix {} nexthop {}'.format(route[0], route[1]), module_ignore_errors=True) + added_routes.clear() + + +def add_route(duthost, prefix, nexthop): + """Add static route + + Args: + duthost (object): DUT object + prefix (str): Route prefix + nexthop (str): Route nexthop + """ + duthost.shell('config route add prefix {} nexthop {}'.format(prefix, nexthop)) + added_routes.add((prefix, nexthop)) + + +def del_route(duthost, prefix, nexthop): + """Remove static route + + Args: + duthost (object): DUT object + prefix (str): Route prefix + nexthop (str): Route nexthop + """ + duthost.shell('config route del prefix {} nexthop {}'.format(prefix, nexthop), module_ignore_errors=True) + added_routes.remove((prefix, nexthop)) + + +class TestRouteCounter: + @pytest.mark.parametrize("route_flow_counter_params", test_update_route_pattern_para) def test_update_route_pattern(self, rand_selected_dut, route_flow_counter_params): """Test steps: 1. Add two routes a and b, configure route pattern match a @@ -63,34 +90,31 @@ def test_update_route_pattern(self, rand_selected_dut, route_flow_counter_params route_flow_counter_params (list): A list contains the test parameter. [ipv6, pattern_a, pattern_b, prefix_a, prefix_b] """ duthost = rand_selected_dut - ipv6 = route_flow_counter_params[0] - route_pattern_a = route_flow_counter_params[1] - route_pattern_b = route_flow_counter_params[2] - prefix_a = route_flow_counter_params[3] - prefix_b = route_flow_counter_params[4] - flow_counter_utils.set_route_flow_counter_status(duthost, True) - flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern_a) - nexthop_addr = self._get_nexthop(duthost, ipv6=ipv6) + ipv6 = route_flow_counter_params['is_ipv6'] + route_pattern_a = route_flow_counter_params['route_pattern_a'] + route_pattern_b = route_flow_counter_params['route_pattern_b'] + prefix_a = route_flow_counter_params['prefix_a'] + prefix_b = route_flow_counter_params['prefix_b'] + with allure.step('Enable route flow counter and config route pattern to {}'.format(route_pattern_a)): + flow_counter_utils.set_route_flow_counter_status(duthost, True) + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern_a) logger.info('Adding static route {} and {}'.format(prefix_a, prefix_b)) - duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix_a, nexthop_addr)) - duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix_b, nexthop_addr)) - - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - pytest_assert(prefix_a in stats, 'Route flow counter for {} is not created'.format(prefix_a)) - pytest_assert(prefix_b not in stats, 'Route flow counter for {} should not be created'.format(prefix_b)) - - - flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern_b) - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - pytest_assert(prefix_a not in stats, 'Route flow counter for {} is not removed'.format(prefix_a)) - pytest_assert(prefix_b in stats, 'Route flow counter for {} is not created'.format(prefix_b)) - - duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix_a), module_ignore_errors=True) - duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix_b), module_ignore_errors=True) - - flow_counter_utils.set_route_flow_counter_status(duthost, False) - flow_counter_utils.remove_route_flow_counter_pattern(duthost, route_pattern_b) + with allure.step('Adding static route {} and {}'.format(prefix_a, prefix_b)): + nexthop_addr = self._get_nexthop(duthost, ipv6=ipv6) + add_route(rand_selected_dut, prefix_a, nexthop_addr) + add_route(rand_selected_dut, prefix_b, nexthop_addr) + + with allure.step('Route pattern is {}, verify route flow counter is bound to {}'.format(route_pattern_a, prefix_a)): + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(prefix_a in stats, 'Route flow counter for {} is not created'.format(prefix_a)) + pytest_assert(prefix_b not in stats, 'Route flow counter for {} should not be created'.format(prefix_b)) + + with allure.step('Change route flow pattern to {}, verify route flow counter is bound to {}'.format(route_pattern_b, prefix_b)): + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern_b) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(prefix_a not in stats, 'Route flow counter for {} is not removed'.format(prefix_a)) + pytest_assert(prefix_b in stats, 'Route flow counter for {} is not created'.format(prefix_b)) def test_max_match_count(self, rand_selected_dut): """Test steps: @@ -100,45 +124,47 @@ def test_max_match_count(self, rand_selected_dut): 4. Set max_allowed match to 2 again, verify that there are two route flow counter as it should automatically fill the room Args: - rand_selected_dut ([type]): [description] + rand_selected_dut (object): DUT object """ duthost = rand_selected_dut route_pattern = '1.1.0.0/16' prefix_list = ['1.1.1.0/24', '1.1.2.0/24', '1.1.3.0/24'] - nexthop_addr = self._get_nexthop(duthost, False) - flow_counter_utils.set_route_flow_counter_status(duthost, True) expect_route_flow_counter = len(prefix_list) - 1 - flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) + nexthop_addr = self._get_nexthop(duthost, False) + + with allure.step('Enable route flow counter and config route pattern to {} with max allowed {}'.format(route_pattern, expect_route_flow_counter)): + flow_counter_utils.set_route_flow_counter_status(duthost, True) + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) + logger.info('Adding {} static routes while max allowed match count is {}'.format(len(prefix_list), expect_route_flow_counter)) - for prefix in prefix_list: - duthost.shell("sonic-db-cli CONFIG_DB hmset 'STATIC_ROUTE|{}' nexthop {}".format(prefix, nexthop_addr)) + with allure.step('Adding static routes'): + for prefix in prefix_list: + add_route(rand_selected_dut, prefix, nexthop_addr) logger.info('Verify there are {} route flow counters'.format(expect_route_flow_counter)) - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - - pytest_assert(len(stats) == expect_route_flow_counter, 'Expecetd {} route flow counters, but got {} counters'.format(expect_route_flow_counter, len(stats))) + with allure.step('Verify there are {} route flow counters'.format(expect_route_flow_counter)): + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(len(stats) == expect_route_flow_counter, 'Expecetd {} route flow counters, but got {} counters'.format(expect_route_flow_counter, len(stats))) logger.info('Removing a route, verify there are still {} route flow counters'.format(expect_route_flow_counter)) - duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix_list[0]), module_ignore_errors=True) - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) + with allure.step('Removing a route, verify there are still {} route flow counters'.format(expect_route_flow_counter)): + del_route(rand_selected_dut, prefix_list[0], nexthop_addr) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) expect_route_flow_counter -= 1 - logger.info('Set max_match_count to {}, verify there is {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)) - flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) + logger.info('Set max_match_count to {}, verify there are {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)) + with allure.step('Set max_match_count to {}, verify there are {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)): + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) expect_route_flow_counter += 1 - logger.info('Set max_match_count to {}, verify there is {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)) - flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) - stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) - pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) - - for prefix in prefix_list: - duthost.shell("sonic-db-cli CONFIG_DB del 'STATIC_ROUTE|{}'".format(prefix), module_ignore_errors=True) - flow_counter_utils.set_route_flow_counter_status(duthost, False) - flow_counter_utils.remove_route_flow_counter_pattern(duthost, route_pattern) + logger.info('Set max_match_count to {}, verify there are {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)) + with allure.step('Set max_match_count to {}, verify there are {} route flow counters'.format(expect_route_flow_counter, expect_route_flow_counter)): + flow_counter_utils.set_route_flow_counter_pattern(duthost, route_pattern, max_match_count=expect_route_flow_counter) + stats = flow_counter_utils.parse_route_flow_counter_stats(duthost) + pytest_assert(len(stats) == expect_route_flow_counter, 'Max allowed match counter is {}, but got {} counters'.format(expect_route_flow_counter, len(stats))) def _get_nexthop(self, duthost, ipv6): """Get next hop from BGP neighbors From 5d6cc25d74ee6798ba7b9f3fd2a8ffdcd1937a29 Mon Sep 17 00:00:00 2001 From: junchao Date: Tue, 10 May 2022 10:55:22 +0800 Subject: [PATCH 04/10] Fix review comment Change-Id: I75d88cdd90244de99f832f154716ca6ad001c1b2 --- tests/bgp/test_bgp_speaker.py | 14 +++++----- tests/flow_counter/flow_counter_utils.py | 34 +++++++++++------------- tests/route/test_route_flow_counter.py | 5 ++-- tests/route/test_static_route.py | 16 +++++------ tests/vxlan/test_vnet_vxlan.py | 6 ++--- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/tests/bgp/test_bgp_speaker.py b/tests/bgp/test_bgp_speaker.py index e5166a7c5e..81902b1262 100644 --- a/tests/bgp/test_bgp_speaker.py +++ b/tests/bgp/test_bgp_speaker.py @@ -15,7 +15,7 @@ from tests.common.utilities import wait_tcp_connection from tests.common.helpers.assertions import pytest_require from tests.common.utilities import wait_until -from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext, is_route_flow_counter_supported pytestmark = [ @@ -252,7 +252,7 @@ def is_all_neighbors_learned(duthost, speaker_ips): def bgp_speaker_announce_routes_common(common_setup_teardown, tbinfo, duthost, ptfhost, ipv4, ipv6, mtu, - family, prefix, nexthop_ips, vlan_mac): + family, prefix, nexthop_ips, vlan_mac, is_route_flow_counter_supported): """Setup bgp speaker on T0 topology and verify routes advertised by bgp speaker is received by T0 TOR """ @@ -310,7 +310,7 @@ def bgp_speaker_announce_routes_common(common_setup_teardown, logger.info("run ptf test") expecte_packet_num = 3 packet_size = 1518 - with RouteFlowCounterTestContext(duthost, [prefix], {prefix : {'packets': expecte_packet_num, 'bytes': packet_size * expecte_packet_num}}): + with RouteFlowCounterTestContext(is_route_flow_counter_supported, duthost, [prefix], {prefix : {'packets': expecte_packet_num, 'bytes': packet_size * expecte_packet_num}}): ptf_runner(ptfhost, "ptftests", "fib_test.FibTest", @@ -334,20 +334,20 @@ def bgp_speaker_announce_routes_common(common_setup_teardown, @pytest.mark.parametrize("ipv4, ipv6, mtu", [pytest.param(True, False, 9114)]) -def test_bgp_speaker_announce_routes(common_setup_teardown, tbinfo, duthosts, rand_one_dut_hostname, ptfhost, ipv4, ipv6, mtu, vlan_mac): +def test_bgp_speaker_announce_routes(common_setup_teardown, tbinfo, duthosts, rand_one_dut_hostname, ptfhost, ipv4, ipv6, mtu, vlan_mac, is_route_flow_counter_supported): """Setup bgp speaker on T0 topology and verify routes advertised by bgp speaker is received by T0 TOR """ duthost = duthosts[rand_one_dut_hostname] nexthops = common_setup_teardown[3] - bgp_speaker_announce_routes_common(common_setup_teardown, tbinfo, duthost, ptfhost, ipv4, ipv6, mtu, "v4", "10.10.10.0/26", nexthops, vlan_mac) + bgp_speaker_announce_routes_common(common_setup_teardown, tbinfo, duthost, ptfhost, ipv4, ipv6, mtu, "v4", "10.10.10.0/26", nexthops, vlan_mac, is_route_flow_counter_supported) @pytest.mark.parametrize("ipv4, ipv6, mtu", [pytest.param(False, True, 9114)]) -def test_bgp_speaker_announce_routes_v6(common_setup_teardown, tbinfo, duthosts, rand_one_dut_hostname, ptfhost, ipv4, ipv6, mtu, vlan_mac): +def test_bgp_speaker_announce_routes_v6(common_setup_teardown, tbinfo, duthosts, rand_one_dut_hostname, ptfhost, ipv4, ipv6, mtu, vlan_mac, is_route_flow_counter_supported): """Setup bgp speaker on T0 topology and verify routes advertised by bgp speaker is received by T0 TOR """ duthost = duthosts[rand_one_dut_hostname] nexthops = common_setup_teardown[4] - bgp_speaker_announce_routes_common(common_setup_teardown, tbinfo, duthost, ptfhost, ipv4, ipv6, mtu, "v6", "fc00:10::/64", nexthops, vlan_mac) + bgp_speaker_announce_routes_common(common_setup_teardown, tbinfo, duthost, ptfhost, ipv4, ipv6, mtu, "v6", "fc00:10::/64", nexthops, vlan_mac, is_route_flow_counter_supported) diff --git a/tests/flow_counter/flow_counter_utils.py b/tests/flow_counter/flow_counter_utils.py index e73017ddbe..f7c647f3c1 100644 --- a/tests/flow_counter/flow_counter_utils.py +++ b/tests/flow_counter/flow_counter_utils.py @@ -1,12 +1,12 @@ import allure import logging +import pytest import random from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import wait_until, check_skip_release logger = logging.getLogger(__name__) -support_route_flow_counter = None skip_versions = ['201811', '201911', '202012', '202106', '202111'] CAPABILITY_WAIT_TIME_IN_SEC = 180 CAPABILITY_CHECK_INTERVAL_IN_SEC = 5 @@ -15,7 +15,7 @@ class RouteFlowCounterTestContext: """Allow caller to use "with" key words to run router flow counter test. """ - def __init__(self, dut, route_pattern_list, expected_stats, interval=1000): + def __init__(self, support, dut, route_pattern_list, expected_stats, interval=1000): """Init RouteFlowCounterTestContext Args: @@ -28,7 +28,7 @@ def __init__(self, dut, route_pattern_list, expected_stats, interval=1000): self.route_pattern_list = route_pattern_list self.expected_stats = expected_stats self.interval = interval - self.is_route_flow_counter_supported = is_route_flow_counter_supported(dut) + self.is_route_flow_counter_supported = support def __enter__(self): """Enable route flow counter and configure route pattern @@ -103,7 +103,8 @@ def check_stats(self): return verify_route_flow_counter_stats(self.expected_stats, actual_stats) -def is_route_flow_counter_supported(dut): +@pytest.fixture(scope = "session") +def is_route_flow_counter_supported(rand_selected_dut): """Check if route flow counter is supported on this platform Args: @@ -112,22 +113,20 @@ def is_route_flow_counter_supported(dut): Returns: bool: True if supported """ - skip, _ = check_skip_release(dut, skip_versions) + skip, _ = check_skip_release(rand_selected_dut, skip_versions) if skip: logger.info('Route flow counter is not supported on these versions: {}'.format(skip_versions)) return False - global support_route_flow_counter - if support_route_flow_counter is None: - if not wait_until(CAPABILITY_WAIT_TIME_IN_SEC, CAPABILITY_CHECK_INTERVAL_IN_SEC, 0, get_route_flow_counter_capability, dut): - support_route_flow_counter = False - pytest_assert(False, 'Failed to get route flow counter capability') - if not support_route_flow_counter: - logger.info('Route flow counter is not supported on this platform') - return support_route_flow_counter + route_flow_counter_capability = [] # Use a list to store the capability + if not wait_until(CAPABILITY_WAIT_TIME_IN_SEC, CAPABILITY_CHECK_INTERVAL_IN_SEC, 0, get_route_flow_counter_capability, rand_selected_dut, route_flow_counter_capability): + pytest_assert(False, 'Failed to get route flow counter capability') + if not route_flow_counter_capability[0]: + logger.info('Route flow counter is not supported on this platform') + return route_flow_counter_capability[0] -def get_route_flow_counter_capability(dut): +def get_route_flow_counter_capability(dut, route_flow_counter_capability): """Get route flow counter capability from STATE DB Args: @@ -136,16 +135,15 @@ def get_route_flow_counter_capability(dut): Returns: bool: True if capability is successfully retrieved from STATE DB """ - global support_route_flow_counter support = dut.shell('sudo sonic-db-cli STATE_DB HGET "FLOW_COUNTER_CAPABILITY_TABLE|route" support')['stdout'].strip() if support == 'true': - support_route_flow_counter = True + route_flow_counter_capability.append(True) elif support == 'false': - support_route_flow_counter = False + route_flow_counter_capability.append(False) elif support: # Impossible branch, just incase pytest_assert(False, 'support field of FLOW_COUNTER_CAPABILITY_TABLE|route has invalid value {}'.format(support)) - return support_route_flow_counter is not None + return len(route_flow_counter_capability) > 0 def set_route_flow_counter_status(dut, status): diff --git a/tests/route/test_route_flow_counter.py b/tests/route/test_route_flow_counter.py index cb6c59bf76..abb2a473a0 100644 --- a/tests/route/test_route_flow_counter.py +++ b/tests/route/test_route_flow_counter.py @@ -3,6 +3,7 @@ import pytest from tests.common.helpers.assertions import pytest_assert, pytest_require from tests.flow_counter import flow_counter_utils +from tests.flow_counter.flow_counter_utils import check_route_flow_counter_supported logger = logging.getLogger(__name__) @@ -27,13 +28,13 @@ @pytest.fixture(scope='function', autouse=True) -def skip_if_not_supported(rand_selected_dut): +def skip_if_not_supported(check_route_flow_counter_supported): """Skip the test if route flow counter is not supported on this platform Args: rand_selected_dut (object): DUT object """ - pytest_require(flow_counter_utils.is_route_flow_counter_supported(rand_selected_dut)) + pytest_require(check_route_flow_counter_supported, 'route flow counter is not supported') @pytest.fixture(scope='function', autouse=True) diff --git a/tests/route/test_static_route.py b/tests/route/test_static_route.py index 00496b592b..fc84e82644 100644 --- a/tests/route/test_static_route.py +++ b/tests/route/test_static_route.py @@ -19,7 +19,7 @@ import ptf.packet as packet from pkg_resources import parse_version from tests.common import constants -from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext, is_route_flow_counter_supported pytestmark = [ @@ -152,7 +152,7 @@ def _check_routes(): assert(wait_until(60, 15, 0, _check_routes)) -def run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, prefix, nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, ipv6=False, config_reload_test=False): +def run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, prefix, nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, is_route_flow_counter_supported, ipv6=False, config_reload_test=False): # Clean up arp or ndp clear_arp_ndp(duthost, ipv6=ipv6) @@ -166,7 +166,7 @@ def run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, prefix, nexthop_ # Check traffic get forwarded to the nexthop ip_dst = str(ipaddress.ip_network(unicode(prefix))[1]) - with RouteFlowCounterTestContext(duthost, [prefix], {prefix: {'packets': '1'}}): + with RouteFlowCounterTestContext(is_route_flow_counter_supported, duthost, [prefix], {prefix: {'packets': '1'}}): generate_and_verify_traffic(duthost, ptfadapter, tbinfo, ip_dst, nexthop_devs, ipv6=ipv6) # Check the route is advertised to the neighbors @@ -179,7 +179,7 @@ def run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, prefix, nexthop_ #FIXME: We saw re-establishing BGP sessions can takes around 7 minutes # on some devices (like 4600) after config reload, so we need below patch wait_all_bgp_up(duthost) - with RouteFlowCounterTestContext(duthost, [prefix], {prefix: {'packets': '1'}}): + with RouteFlowCounterTestContext(is_route_flow_counter_supported, duthost, [prefix], {prefix: {'packets': '1'}}): generate_and_verify_traffic(duthost, ptfadapter, tbinfo, ip_dst, nexthop_devs, ipv6=ipv6) check_route_redistribution(duthost, prefix, ipv6) @@ -239,7 +239,7 @@ def test_static_route(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo) run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, "1.1.1.0/24", - nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces) + nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, is_route_flow_counter_supported) def test_static_route_ecmp(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m): @@ -247,7 +247,7 @@ def test_static_route_ecmp(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggl skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo, count=3) run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, "2.2.2.0/24", - nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, config_reload_test=True) + nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, is_route_flow_counter_supported, config_reload_test=True) def test_static_route_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m): @@ -255,7 +255,7 @@ def test_static_route_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggl skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo, ipv6=True) run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, "2000:1::/64", - nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, ipv6=True) + nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, is_route_flow_counter_supported, ipv6=True) def test_static_route_ecmp_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m): @@ -263,4 +263,4 @@ def test_static_route_ecmp_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo, ipv6=True, count=3) run_static_route_test(duthost, ptfadapter, ptfhost, tbinfo, "2000:2::/64", - nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, ipv6=True, config_reload_test=True) + nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, is_route_flow_counter_supported, ipv6=True, config_reload_test=True) diff --git a/tests/vxlan/test_vnet_vxlan.py b/tests/vxlan/test_vnet_vxlan.py index 0cb5224c36..92568d3359 100644 --- a/tests/vxlan/test_vnet_vxlan.py +++ b/tests/vxlan/test_vnet_vxlan.py @@ -14,7 +14,7 @@ from tests.common.fixtures.ptfhost_utils import remove_ip_addresses, change_mac_addresses, \ copy_arp_responder_py, copy_ptftests_directory -from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext, is_route_flow_counter_supported import tests.arp.test_wr_arp as test_wr_arp from tests.common.config_reload import config_reload @@ -169,7 +169,7 @@ def is_neigh_reachable(duthost, vnet_config): return True -def test_vnet_vxlan(setup, vxlan_status, duthosts, rand_one_dut_hostname, ptfhost, vnet_test_params, creds): +def test_vnet_vxlan(setup, vxlan_status, duthosts, rand_one_dut_hostname, ptfhost, vnet_test_params, creds, is_route_flow_counter_supported): """ Test case for VNET VxLAN @@ -207,7 +207,7 @@ def test_vnet_vxlan(setup, vxlan_status, duthosts, rand_one_dut_hostname, ptfhos logger.debug("Starting PTF runner") if scenario == 'Enabled' and vxlan_enabled: route_pattern = 'Vnet1|100.1.1.1/32' - with RouteFlowCounterTestContext(duthost, [route_pattern], {route_pattern: {'packets': '3'}}): + with RouteFlowCounterTestContext(is_route_flow_counter_supported, duthost, [route_pattern], {route_pattern: {'packets': '3'}}): ptf_runner(ptfhost, "ptftests", "vnet_vxlan.VNET", From 0d7cd5f175982f74ad52f76fbaa441ea690cf270 Mon Sep 17 00:00:00 2001 From: junchao Date: Tue, 10 May 2022 11:24:12 +0800 Subject: [PATCH 05/10] express invalid LGTM warning Change-Id: If6e571d803b7ba8702164f000ac7a0a10919f175 --- tests/bgp/test_bgp_speaker.py | 2 +- tests/route/test_route_flow_counter.py | 2 +- tests/vxlan/test_vnet_vxlan.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bgp/test_bgp_speaker.py b/tests/bgp/test_bgp_speaker.py index 81902b1262..bbb1e2c41c 100644 --- a/tests/bgp/test_bgp_speaker.py +++ b/tests/bgp/test_bgp_speaker.py @@ -15,7 +15,7 @@ from tests.common.utilities import wait_tcp_connection from tests.common.helpers.assertions import pytest_require from tests.common.utilities import wait_until -from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext, is_route_flow_counter_supported +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext, is_route_flow_counter_supported # lgtm[py/unused-import] pytestmark = [ diff --git a/tests/route/test_route_flow_counter.py b/tests/route/test_route_flow_counter.py index abb2a473a0..448331d80e 100644 --- a/tests/route/test_route_flow_counter.py +++ b/tests/route/test_route_flow_counter.py @@ -3,7 +3,7 @@ import pytest from tests.common.helpers.assertions import pytest_assert, pytest_require from tests.flow_counter import flow_counter_utils -from tests.flow_counter.flow_counter_utils import check_route_flow_counter_supported +from tests.flow_counter.flow_counter_utils import check_route_flow_counter_supported # lgtm[py/unused-import] logger = logging.getLogger(__name__) diff --git a/tests/vxlan/test_vnet_vxlan.py b/tests/vxlan/test_vnet_vxlan.py index 92568d3359..87f3b0e6ad 100644 --- a/tests/vxlan/test_vnet_vxlan.py +++ b/tests/vxlan/test_vnet_vxlan.py @@ -14,7 +14,7 @@ from tests.common.fixtures.ptfhost_utils import remove_ip_addresses, change_mac_addresses, \ copy_arp_responder_py, copy_ptftests_directory -from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext, is_route_flow_counter_supported +from tests.flow_counter.flow_counter_utils import RouteFlowCounterTestContext, is_route_flow_counter_supported # lgtm[py/unused-import] import tests.arp.test_wr_arp as test_wr_arp from tests.common.config_reload import config_reload From 6f2fe3ef62024fcc1a5507427cf86179cfc2a4eb Mon Sep 17 00:00:00 2001 From: junchao Date: Thu, 12 May 2022 18:01:12 +0800 Subject: [PATCH 06/10] Fix typo Change-Id: Ia784fc3ad19483fbc84ebd657066c0bce218c273 --- tests/route/test_route_flow_counter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/route/test_route_flow_counter.py b/tests/route/test_route_flow_counter.py index 448331d80e..fb0f0051c0 100644 --- a/tests/route/test_route_flow_counter.py +++ b/tests/route/test_route_flow_counter.py @@ -3,7 +3,7 @@ import pytest from tests.common.helpers.assertions import pytest_assert, pytest_require from tests.flow_counter import flow_counter_utils -from tests.flow_counter.flow_counter_utils import check_route_flow_counter_supported # lgtm[py/unused-import] +from tests.flow_counter.flow_counter_utils import is_route_flow_counter_supported # lgtm[py/unused-import] logger = logging.getLogger(__name__) @@ -28,13 +28,13 @@ @pytest.fixture(scope='function', autouse=True) -def skip_if_not_supported(check_route_flow_counter_supported): +def skip_if_not_supported(is_route_flow_counter_supported): """Skip the test if route flow counter is not supported on this platform Args: rand_selected_dut (object): DUT object """ - pytest_require(check_route_flow_counter_supported, 'route flow counter is not supported') + pytest_require(is_route_flow_counter_supported, 'route flow counter is not supported') @pytest.fixture(scope='function', autouse=True) From f9278f7e12827c5202b2f0dbe197e8ef3d7e84d2 Mon Sep 17 00:00:00 2001 From: junchao Date: Fri, 13 May 2022 09:35:28 +0800 Subject: [PATCH 07/10] Fix fixture issue Change-Id: I89c90deabd38720136ab2dea5b1eb38283f1bcf2 --- tests/flow_counter/flow_counter_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/flow_counter/flow_counter_utils.py b/tests/flow_counter/flow_counter_utils.py index f7c647f3c1..cd16b12b9c 100644 --- a/tests/flow_counter/flow_counter_utils.py +++ b/tests/flow_counter/flow_counter_utils.py @@ -104,7 +104,7 @@ def check_stats(self): @pytest.fixture(scope = "session") -def is_route_flow_counter_supported(rand_selected_dut): +def is_route_flow_counter_supported(duthosts, enum_rand_one_per_hwsku_hostname): """Check if route flow counter is supported on this platform Args: @@ -113,6 +113,7 @@ def is_route_flow_counter_supported(rand_selected_dut): Returns: bool: True if supported """ + rand_selected_dut = duthosts[enum_rand_one_per_hwsku_hostname] skip, _ = check_skip_release(rand_selected_dut, skip_versions) if skip: logger.info('Route flow counter is not supported on these versions: {}'.format(skip_versions)) From e2fe2d8074c0d5029971299e5a83977ba051cd1b Mon Sep 17 00:00:00 2001 From: junchao Date: Fri, 13 May 2022 14:56:08 +0800 Subject: [PATCH 08/10] Change fixture scope from session to module Change-Id: I7b304d40004ea699c29d61d88b7bd1f64ec63a53 --- tests/flow_counter/flow_counter_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/flow_counter/flow_counter_utils.py b/tests/flow_counter/flow_counter_utils.py index cd16b12b9c..8d7817d797 100644 --- a/tests/flow_counter/flow_counter_utils.py +++ b/tests/flow_counter/flow_counter_utils.py @@ -103,7 +103,7 @@ def check_stats(self): return verify_route_flow_counter_stats(self.expected_stats, actual_stats) -@pytest.fixture(scope = "session") +@pytest.fixture(scope = "module") def is_route_flow_counter_supported(duthosts, enum_rand_one_per_hwsku_hostname): """Check if route flow counter is supported on this platform From 007f21e02be79e44a1012e4827719ea12eb6eab0 Mon Sep 17 00:00:00 2001 From: junchao Date: Thu, 2 Jun 2022 17:20:30 +0800 Subject: [PATCH 09/10] Disable route flow counter test on vs platform Change-Id: I095c6c9be9f1fe9aef4d6e13307981fae5a481e8 --- tests/bgp/test_bgp_speaker.py | 2 +- tests/flow_counter/flow_counter_utils.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/bgp/test_bgp_speaker.py b/tests/bgp/test_bgp_speaker.py index 0294c2ca06..77b8e04567 100644 --- a/tests/bgp/test_bgp_speaker.py +++ b/tests/bgp/test_bgp_speaker.py @@ -310,7 +310,7 @@ def bgp_speaker_announce_routes_common(common_setup_teardown, logger.info("run ptf test") expecte_packet_num = 3 - packet_size = 1518 + packet_size = mtu + 4 with RouteFlowCounterTestContext(is_route_flow_counter_supported, duthost, [prefix], {prefix : {'packets': expecte_packet_num, 'bytes': packet_size * expecte_packet_num}}): ptf_runner(ptfhost, "ptftests", diff --git a/tests/flow_counter/flow_counter_utils.py b/tests/flow_counter/flow_counter_utils.py index 8d7817d797..8c02c67162 100644 --- a/tests/flow_counter/flow_counter_utils.py +++ b/tests/flow_counter/flow_counter_utils.py @@ -114,6 +114,10 @@ def is_route_flow_counter_supported(duthosts, enum_rand_one_per_hwsku_hostname): bool: True if supported """ rand_selected_dut = duthosts[enum_rand_one_per_hwsku_hostname] + if rand_selected_dut.facts['asic_type'] == 'vs': + # vs platform always set SAI capability to enabled, however, it does not really support all SAI atrributes. + # Currently, vs platform does not support route flow counter. + return False skip, _ = check_skip_release(rand_selected_dut, skip_versions) if skip: logger.info('Route flow counter is not supported on these versions: {}'.format(skip_versions)) From 9daf6d1adc88598c7fded170da0bc106cc59f0eb Mon Sep 17 00:00:00 2001 From: junchao Date: Mon, 6 Jun 2022 09:54:07 +0800 Subject: [PATCH 10/10] Fix test failure on static route test Change-Id: I7cdd6151d5fdf258f6d04ca1e0c897488900de97 --- tests/route/test_static_route.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/route/test_static_route.py b/tests/route/test_static_route.py index 55f9316b1e..34516322fd 100644 --- a/tests/route/test_static_route.py +++ b/tests/route/test_static_route.py @@ -234,7 +234,7 @@ def get_nexthops(duthost, tbinfo, ipv6=False, count=1): return prefix_len, [nexthop_addrs[_] for _ in indices], [nexthop_devs[_] for _ in indices], [nexthop_interfaces[_] for _ in indices] -def test_static_route(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m): +def test_static_route(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m, is_route_flow_counter_supported): duthost = rand_selected_dut skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo) @@ -243,7 +243,7 @@ def test_static_route(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all @pytest.mark.disable_loganalyzer -def test_static_route_ecmp(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m): +def test_static_route_ecmp(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m, is_route_flow_counter_supported): duthost = rand_selected_dut skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo, count=3) @@ -251,7 +251,7 @@ def test_static_route_ecmp(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggl nexthop_addrs, prefix_len, nexthop_devs, nexthop_interfaces, is_route_flow_counter_supported, config_reload_test=True) -def test_static_route_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m): +def test_static_route_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m, is_route_flow_counter_supported): duthost = rand_selected_dut skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo, ipv6=True) @@ -260,7 +260,7 @@ def test_static_route_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggl @pytest.mark.disable_loganalyzer -def test_static_route_ecmp_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m): +def test_static_route_ecmp_ipv6(rand_selected_dut, ptfadapter, ptfhost, tbinfo, toggle_all_simulator_ports_to_rand_selected_tor_m, is_route_flow_counter_supported): duthost = rand_selected_dut skip_201911_and_older(duthost) prefix_len, nexthop_addrs, nexthop_devs, nexthop_interfaces = get_nexthops(duthost, tbinfo, ipv6=True, count=3)