diff --git a/tests/snmp/test_snmp_interfaces.py b/tests/snmp/test_snmp_interfaces.py index 956e13237d2..0ba95885632 100644 --- a/tests/snmp/test_snmp_interfaces.py +++ b/tests/snmp/test_snmp_interfaces.py @@ -2,6 +2,9 @@ import pytest from tests.common.helpers.assertions import pytest_assert from tests.common.helpers.snmp_helpers import get_snmp_facts +from tests.platform_tests.counterpoll.counterpoll_helper import ConterpollHelper +from tests.platform_tests.counterpoll.counterpoll_constants import CounterpollConstants +from tests.ip.ip_util import parse_rif_counters pytestmark = [ pytest.mark.topology('any'), @@ -10,6 +13,86 @@ logger = logging.getLogger(__name__) +SAI_PORT_STAT_IF_IN_ERRORS = 'SAI_PORT_STAT_IF_IN_ERRORS' +SAI_PORT_STAT_IF_OUT_ERRORS = 'SAI_PORT_STAT_IF_OUT_ERRORS' +SAI_PORT_STAT_IF_IN_DISCARDS = 'SAI_PORT_STAT_IF_IN_DISCARDS' +SAI_PORT_STAT_IF_OUT_DISCARDS = 'SAI_PORT_STAT_IF_OUT_DISCARDS' +SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS = 'SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS' +SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS = 'SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS' + +COUNTERS_PORT_NAME_MAP = 'COUNTERS_PORT_NAME_MAP' +COUNTERS_RIF_NAME_MAP = 'COUNTERS_RIF_NAME_MAP' +COUNTER_VALUE = 5000 + + +@pytest.fixture() +def disable_conterpoll(duthost): + """ + Disable conterpoll for RIF and PORT and re-enable it when TC finished + :param duthost: DUT host object + :return: dict with data collected from DUT per each port + """ + ConterpollHelper.disable_counterpoll(duthost, counter_type_list=[CounterpollConstants.PORT, + CounterpollConstants.RIF]) + yield + ConterpollHelper.enable_counterpoll(duthost, counter_type_list=[CounterpollConstants.PORT, + CounterpollConstants.RIF]) + + +def get_interfaces(duthost, tbinfo): + """ + Method to get interfaces for testing + :param duthost: DUT host object + :return: RIF interface name in case available in topo. If not - return Port Channel name and interface in Port + Channel + """ + rif_counters = parse_rif_counters(duthost.command("show interfaces counters rif")["stdout_lines"]) + for interface in rif_counters: + if 'Eth' in interface: + return interface, interface + else: + mg_facts = duthost.get_extended_minigraph_facts(tbinfo) + return mg_facts["minigraph_portchannels"][interface]['members'][0], interface + + +def get_oid_for_interface(duthost, table_name, interface_name): + """ + Method to get interface oid from Counters DB + :param duthost: DUT host object + :param table_name: table name + :param interface_name: interface name + :return: oid for specific interface + """ + return duthost.command(f"docker exec -i database redis-cli --raw -n 2 HMGET " + f"{table_name} {interface_name}")["stdout"] + + +def set_counters_value(duthost, interface_oid, counter_name, counter_value): + """ + Method to set interface counter value in Counters DB + :param duthost: DUT host object + :param interface_oid: oid value + :param counter_name: counter name + :param counter_value: counter value + """ + duthost.command(f"sudo redis-cli -n 2 hset COUNTERS:{interface_oid} {counter_name} {counter_value}") + + +def get_port_interface_counter(duthost, interface_name): + """ + Method to set interface counter value in Counters DB + :param duthost: DUT host object + :param interface_name: name of interface to collect counters + :return : dict with counters + """ + port_counters = duthost.show_and_parse("show interfaces counters") + for port_counter in port_counters: + if port_counter['iface'] == interface_name: + for key, value in port_counter.items(): + if ',' in value: + port_counter[key] = value.replace(',', '') + return port_counter + def collect_all_facts(duthost, ports_list, namespace=None): """ @@ -242,3 +325,69 @@ def test_snmp_interfaces_mibs(duthosts, enum_rand_one_per_hwsku_hostname, localh result = verify_port_ifindex(snmp_facts, speed_snmp) pytest_assert( not result, "Unexpected comparsion of SNMP: {}".format(result)) + + +def test_snmp_interfaces_error_discard(duthosts, enum_rand_one_per_hwsku_hostname, localhost, creds_all_duts, + enum_asic_index, disable_conterpoll, tbinfo, mg_facts): + """Verify correct behaviour of port MIBs ifInError, ifOutError, IfInDiscards, IfOutDiscards """ + duthost = duthosts[enum_rand_one_per_hwsku_hostname] + hostip = duthost.host.options['inventory_manager'].get_host( + duthost.hostname).vars['ansible_host'] + port_interface, rif_interface = get_interfaces(duthost, tbinfo) + logger.info(f'Selected interfaces: port {port_interface}, rif {rif_interface}') + # Get interfaces oid + port_oid = get_oid_for_interface(duthost, COUNTERS_PORT_NAME_MAP, port_interface) + rif_oid = get_oid_for_interface(duthost, COUNTERS_RIF_NAME_MAP, rif_interface) + + logger.info('Set port and rif counters in COUNTERS DB') + logger.info(f'Set port {port_interface} {SAI_PORT_STAT_IF_IN_ERRORS} counter to {COUNTER_VALUE}') + set_counters_value(duthost, port_oid, SAI_PORT_STAT_IF_IN_ERRORS, COUNTER_VALUE) + logger.info(f'Set port {port_interface} {SAI_PORT_STAT_IF_IN_DISCARDS} counter to {COUNTER_VALUE}') + set_counters_value(duthost, port_oid, SAI_PORT_STAT_IF_IN_DISCARDS, COUNTER_VALUE) + logger.info(f'Set port {rif_interface} {SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS} counter to {COUNTER_VALUE}') + set_counters_value(duthost, rif_oid, SAI_ROUTER_INTERFACE_STAT_IN_ERROR_PACKETS, COUNTER_VALUE) + logger.info(f'Set port {port_interface} {SAI_PORT_STAT_IF_OUT_DISCARDS} counter to {COUNTER_VALUE}') + set_counters_value(duthost, port_oid, SAI_PORT_STAT_IF_OUT_DISCARDS, COUNTER_VALUE) + logger.info(f'Set port {rif_interface} {SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS} counter to {COUNTER_VALUE}') + set_counters_value(duthost, rif_oid, SAI_ROUTER_INTERFACE_STAT_OUT_ERROR_PACKETS, COUNTER_VALUE) + logger.info(f'Set port {port_interface} {SAI_PORT_STAT_IF_OUT_ERRORS} counter to {COUNTER_VALUE}') + set_counters_value(duthost, port_oid, SAI_PORT_STAT_IF_OUT_ERRORS, COUNTER_VALUE) + + rif_counters = parse_rif_counters(duthost.command("show interfaces counters rif")["stdout_lines"]) + port_counters = get_port_interface_counter(duthost, port_interface) + + logger.info('Compare rif counters in COUNTERS DB and counters get from SONiC CLI') + assert int(rif_counters[rif_interface]['tx_err']) == COUNTER_VALUE, \ + f"tx_err value is {rif_counters[rif_interface]['tx_err']} not set to {COUNTER_VALUE}" + assert int(rif_counters[rif_interface]['rx_err']) == COUNTER_VALUE, \ + f"rx_err value is {rif_counters[rif_interface]['tx_err']} not set to {COUNTER_VALUE}" + + logger.info('Compare port counters in COUNTERS DB and counters get from SONiC CLI') + assert int(port_counters['tx_err']) == COUNTER_VALUE, \ + f"tx_err value is {port_counters['tx_err']} not set to {COUNTER_VALUE}" + assert int(port_counters['rx_err']) == COUNTER_VALUE, \ + f"rx_err value is {port_counters['rx_err']} not set to {COUNTER_VALUE}" + assert int(port_counters['tx_drp']) == COUNTER_VALUE, \ + f"tx_drp value is {port_counters['tx_drp']} not set to {COUNTER_VALUE}" + assert int(port_counters['rx_drp']) == COUNTER_VALUE, \ + f"rx_drp value is {port_counters['rx_drp']} not set to {COUNTER_VALUE}" + + snmp_facts = get_snmp_facts( + localhost, host=hostip, version="v2c", + community=creds_all_duts[duthost.hostname]["snmp_rocommunity"], wait=True)['ansible_facts'] + minigraph_port_name_to_alias_map = mg_facts['minigraph_port_name_to_alias_map'] + snmp_port_map = {snmp_facts['snmp_interfaces'][idx]['name']: idx for idx in snmp_facts['snmp_interfaces']} + rif_snmp_facts = snmp_facts['snmp_interfaces'][snmp_port_map[minigraph_port_name_to_alias_map[rif_interface]]] + + assert (int(rif_snmp_facts['ifInDiscards']) == int(rif_counters[rif_interface]['rx_err']) + + int(port_counters['rx_drp'])), \ + (f"ifInDiscards value is {rif_snmp_facts['ifInDiscards']} but must be " + f"{int(rif_counters[rif_interface]['rx_err']) + int(port_counters['rx_drp'])}") + assert (int(rif_snmp_facts['ifOutDiscards']) == int(rif_counters[rif_interface]['tx_err']) + + int(port_counters['tx_drp'])), \ + (f"ifOutDiscards value is {rif_snmp_facts['ifOutDiscards']} but must be " + f"{int(rif_counters[rif_interface]['tx_err']) + int(port_counters['tx_drp'])}") + assert int(rif_snmp_facts['ifInErrors']) == COUNTER_VALUE, \ + f"ifInErrors value is {rif_snmp_facts['ifInErrors']} but must be {COUNTER_VALUE}" + assert int(rif_snmp_facts['ifOutErrors']) == COUNTER_VALUE, \ + f"ifOutErrors value is {rif_snmp_facts['ifOutErrors']} but must be {COUNTER_VALUE}"