Exemple #1
0
def verify_lag_in_asic_db(asics, lag_id, deleted=False):
    """
    Verifies LAG in ASIC DB
    Args:
        asics<list>: asic
        lag_id<int>: lag id
        deleted<bool>: True if lag is deleted
    """
    for asic in asics:
        asicdb = AsicDbCli(asic)
        asic_db_lag_list = asicdb.get_asic_db_lag_list()
        if deleted:
            for lag in asic_db_lag_list:
                if asicdb.hget_key_value(lag, "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id:
                    pytest.fail('LAG id {} for LAG {} exist in ASIC DB,'
                                ' Expected was should not be present'.format(lag_id, TMP_PC))

            logging.info('LAG id {} for LAG {} does not exist in ASIC DB'.format(lag_id, TMP_PC))

        else:
            for lag in asic_db_lag_list:
                if asicdb.hget_key_value(lag, "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id:
                    logging.info('LAG id {} for LAG {} exist in ASIC DB'.format(lag_id, TMP_PC))
                    return
            pytest.fail('LAG id {} for LAG {} does not exist in ASIC DB'.format(lag_id, TMP_PC))
Exemple #2
0
def check_local_neighbor_asicdb(asic, neighbor_ip, neighbor_mac):
    """
    Verifies the neighbor information of a sonic host in the asicdb for a locally attached neighbor.

    Args:
        asic: The SonicAsic instance to be checked.
        neighbor_ip: The IP address of the neighbor.
        neighbor_mac: The MAC address of the neighbor.

    Returns:
        A dictionary with the encap ID from the ASIC neighbor table.

    Raises:
        Pytest Failed exception when assertions fail.

    """
    asicdb = AsicDbCli(asic)
    neighbor_key = asicdb.get_neighbor_key_by_ip(neighbor_ip)
    pytest_assert(
        neighbor_key is not None,
        "Did not find neighbor in asictable for IP: %s" % neighbor_ip)
    asic_mac = asicdb.get_neighbor_value(
        neighbor_key, 'SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS')
    pytest_assert(
        asic_mac.lower() == neighbor_mac.lower(),
        "MAC does not match in asicDB, asic %s, device %s" %
        (asic_mac.lower(), neighbor_mac.lower()))
    encap_idx = asicdb.get_neighbor_value(
        neighbor_key, 'SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX')
    return {"encap_index": encap_idx}
Exemple #3
0
def test_voq_system_port_create(duthosts):
    """Compare the config facts with the asic db for system ports

    * Verify ASIC_DB get all system ports referenced in configDB created on all hosts and ASICs.
    * Verify object creation and values of port attributes.

    """

    for per_host in duthosts.frontend_nodes:

        for asic in per_host.asics:
            logger.info("Checking system ports on host: %s, asic: %s", per_host.hostname, asic.asic_index)
            cfg_facts = asic.config_facts(source="persistent")['ansible_facts']
            dev_ports = get_device_system_ports(cfg_facts)
            asicdb = AsicDbCli(asic)
            keylist = asicdb.get_system_port_key_list()
            pytest_assert(len(keylist) == len(dev_ports.keys()),
                          "Found %d system port keys, %d entries in cfg_facts, not matching" % (
                              len(keylist), len(dev_ports.keys())))
            logger.info("Found %d system port keys, %d entries in cfg_facts, checking each.",
                        len(keylist), len(dev_ports.keys()))
            for portkey in keylist:
                try:
                    port_output = asicdb.hget_key_value(portkey, field="SAI_SYSTEM_PORT_ATTR_CONFIG_INFO")
                except RedisKeyNotFound:
                    # TODO: Need to check on behavior here.
                    logger.warning("System port: %s had no SAI_SYSTEM_PORT_ATTR_CONFIG_INFO", portkey)
                    continue
                port_data = json.loads(port_output)
                for cfg_port in dev_ports:
                    if dev_ports[cfg_port]['system_port_id'] == port_data['port_id']:
                        #             "switch_id": "0",
                        #             "core_index": "1",
                        #             "core_port_index": "6",
                        #             "speed": "400000"
                        pytest_assert(dev_ports[cfg_port]['switch_id'] == port_data[
                            'attached_switch_id'], "switch IDs do not match for port: %s" % portkey)
                        pytest_assert(dev_ports[cfg_port]['core_index'] == port_data[
                            'attached_core_index'], "switch IDs do not match for port: %s" % portkey)
                        pytest_assert(dev_ports[cfg_port]['core_port_index'] == port_data[
                            'attached_core_port_index'], "switch IDs do not match for port: %s" % portkey)
                        pytest_assert(dev_ports[cfg_port]['speed'] == port_data[
                            'speed'], "switch IDs do not match for port: %s" % portkey)
                        break
                else:
                    logger.error("Could not find config entry for portkey: %s" % portkey)

            logger.info("Host: %s, Asic: %s all ports match all parameters", per_host.hostname, asic.asic_index)
def test_voq_switch_create(duthosts):
    """Compare the config facts with the asic db for switch:
    * Verify ASIC_DB get all system ports referenced in configDB created on all hosts and ASICs.
    * Verify object creation and values of port attributes.
    """

    switch_id_list = []
    for per_host in duthosts.frontend_nodes:

        for asic in per_host.asics:
            cfg_facts = asic.config_facts(source="persistent")['ansible_facts']
            dev_facts = cfg_facts['DEVICE_METADATA']['localhost']
            asicdb = AsicDbCli(asic)

            switchkey = asicdb.get_switch_key()
            logger.info("Checking switch %s", switchkey)
            check_list = {
                "max_cores": "SAI_SWITCH_ATTR_MAX_SYSTEM_CORES",
                "switch_id": "SAI_SWITCH_ATTR_SWITCH_ID"
            }
            for k in check_list:
                asicdb.get_and_check_key_value(switchkey,
                                               dev_facts[k],
                                               field=check_list[k])

            pytest_assert(
                dev_facts["switch_id"] not in switch_id_list,
                "Switch ID: %s has been used more than once" %
                dev_facts["switch_id"])
            switch_id_list.append(dev_facts["switch_id"])

            asicdb.get_and_check_key_value(switchkey,
                                           "SAI_SWITCH_TYPE_VOQ",
                                           field="SAI_SWITCH_ATTR_TYPE")
Exemple #5
0
    def test_voq_switch_create(self, duthosts, enum_frontend_dut_hostname,
                               enum_asic_index, all_cfg_facts):
        """Compare the config facts with the asic db for switch:
        * Verify ASIC_DB get all system ports referenced in configDB created on all hosts and ASICs.
        * Verify object creation and values of port attributes.
        """
        per_host = duthosts[enum_frontend_dut_hostname]
        asic = per_host.asics[
            enum_asic_index if enum_asic_index is not None else 0]
        cfg_facts = all_cfg_facts[per_host.hostname][
            asic.asic_index]['ansible_facts']

        dev_facts = cfg_facts['DEVICE_METADATA']['localhost']
        asicdb = AsicDbCli(asic)

        switchkey = asicdb.get_switch_key()
        logger.info("Checking switch %s", switchkey)
        check_list = {
            "max_cores": "SAI_SWITCH_ATTR_MAX_SYSTEM_CORES",
            "switch_id": "SAI_SWITCH_ATTR_SWITCH_ID"
        }
        for k in check_list:
            asicdb.get_and_check_key_value(switchkey,
                                           dev_facts[k],
                                           field=check_list[k])

        pytest_assert(
            dev_facts["switch_id"] not in TestVoqSwitch.SWITCH_ID_LIST,
            "Switch ID: %s has been used more than once" %
            dev_facts["switch_id"])
        TestVoqSwitch.SWITCH_ID_LIST.append(dev_facts["switch_id"])

        asicdb.get_and_check_key_value(switchkey,
                                       "SAI_SWITCH_TYPE_VOQ",
                                       field="SAI_SWITCH_ATTR_TYPE")
Exemple #6
0
def check_voq_remote_neighbor(host, asic, neighbor_ip, neighbor_mac, interface, encap_idx, inband_mac):
    """
    Verifies the neighbor information of a neighbor learned on a different host.

    The ASIC DB, APP DB, and host ARP table are checked. The host kernal route is verified.  The encap ID from the
    local neighbor is provided as a parameter and verified that it is imposed.

    Args:
        host: Instance of SonicHost to check.
        asic: Instance of SonicAsic to check.
        neighbor_ip: IP address if the neighbor to check.
        neighbor_mac: Expected ethernet MAC address of the neighbor.
        interface: Expected interface the neighbor was learned on.
        encap_idx: The encap index from the SONIC host the neighbor is directly attached to.
        inband_mac: The MAC of the inband port of the remote host.

    Raises:
        Pytest Failed exception when assertions fail.
    """
    logger.info("Check remote neighbor on host %s, asic: %s for %s/%s via port: %s", host.hostname,
                str(asic.asic_index), neighbor_ip, neighbor_mac, interface)

    # asic db
    asicdb = AsicDbCli(asic)
    neighbor_key = asicdb.get_neighbor_key_by_ip(neighbor_ip)
    pytest_assert(neighbor_key is not None, "Did not find neighbor in asic table for IP: %s" % neighbor_ip)
    pytest_assert(asicdb.get_neighbor_value(neighbor_key,
                                            'SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS').lower() == neighbor_mac.lower(),
                  "MAC does not match in asicDB")
    pytest_assert(asicdb.get_neighbor_value(neighbor_key,
                                            'SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX') == encap_idx,
                  "Encap index does not match in asicDB")
    pytest_assert(asicdb.get_neighbor_value(neighbor_key,
                                            'SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_IMPOSE_INDEX') == "true",
                  "Encap impose is not true in asicDB")
    pytest_assert(asicdb.get_neighbor_value(neighbor_key,
                                            'SAI_NEIGHBOR_ENTRY_ATTR_IS_LOCAL') == "false",
                  "is local is not false in asicDB")

    # LC app db
    appdb = AppDbCli(asic)
    neighbor_key = appdb.get_neighbor_key_by_ip(neighbor_ip)
    pytest_assert(":{}:".format(interface) in neighbor_key, "Port for %s does not match" % neighbor_key)
    appdb.get_and_check_key_value(neighbor_key, inband_mac, field="neigh")

    # verify linux arp table
    check_host_arp_table(host, neighbor_ip, inband_mac, interface, 'PERMANENT')

    # verify linux route entry
    check_neighbor_kernel_route(host, asic.asic_index, neighbor_ip, interface)
Exemple #7
0
def verify_lag_member_in_asic_db(asics, lag_id, pc_members, deleted=False):
    """
       Verifies lag member in ASIC DB
       It runs the command e.g.
    """
    for asic in asics:
        asicdb = AsicDbCli(asic)
        asic_lag_list = asicdb.get_asic_db_lag_list()
        asic_db_lag_member_list = asicdb.get_asic_db_lag_member_list()
        lag_oid = None
        if deleted:
            for lag in asic_lag_list:
                if asicdb.hget_key_value(
                        lag,
                        "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id:
                    lag_oid = ":".join(lag for lag in lag.split(':')[-1:-3:-1])

            for lag_member in asic_db_lag_member_list:
                if asicdb.hget_key_value(
                        lag_member, "SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_oid:
                    pytest.fail(
                        "lag members {} still exist in lag member table on {},"
                        " Expected was should be deleted".format(
                            pc_members, asic.sonichost.hostname))
            logging.info('Lag members are deleted from {} on {}'.format(
                asic.asic_index, asic.sonichost.hostname))

        else:
            for lag in asic_lag_list:
                if asicdb.hget_key_value(
                        lag,
                        "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id:
                    lag_oid = ":".join(lag for lag in lag.split(':')[-2::1])
                    break

            for lag_member in asic_db_lag_member_list:
                if asicdb.hget_key_value(
                        lag_member, "SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_oid:
                    logging.info('Lag members exist in {} on {}'.format(
                        asic.asic_index, asic.sonichost.hostname))
                    return

            pytest.fail('Lag members {} does not exist in {} on {}'.format(
                pc_members, asic.asic_index, asic.sonichost.hostname))
Exemple #8
0
def test_voq_local_port_create(duthosts):
    """Compare the config facts with the asic db for local ports

    * Verify ASIC_DB has host interface information for all local ports on all cards and ASICs.
    * Verify host interfaces exist on host CLI (ifconfig).
    * Verify interfaces exist in show interfaces on the linecard.
    """

    for per_host in duthosts.frontend_nodes:

        for asic in per_host.asics:
            cfg_facts = asic.config_facts(source="persistent")['ansible_facts']
            dev_ports = cfg_facts['PORT']

            asicdb = AsicDbCli(asic)

            keylist = asicdb.get_hostif_list()
            pytest_assert(len(keylist) == len(dev_ports.keys()),
                          "Found %d hostif keys, %d entries in cfg_facts" % (len(keylist), len(dev_ports.keys())))
            logger.info("Found %s ports to check on host:%s, asic: %s.", len(dev_ports.keys()), per_host.hostname,
                        asic.asic_index)

            show_intf = asic.show_interface(command="status")['ansible_facts']
            for portkey in keylist:
                port_name = asicdb.hget_key_value(portkey, "SAI_HOSTIF_ATTR_NAME")
                port_state = asicdb.hget_key_value(portkey, "SAI_HOSTIF_ATTR_OPER_STATUS")
                port_type = asicdb.hget_key_value(portkey, "SAI_HOSTIF_ATTR_TYPE")
                logger.info("Checking port: %s, state: %s", port_name, port_state)
                # "SAI_HOSTIF_ATTR_NAME": "Ethernet0",
                # "SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x1000000000002",
                # "SAI_HOSTIF_ATTR_OPER_STATUS": "false",
                # "SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV"
                pytest_assert(port_type == "SAI_HOSTIF_TYPE_NETDEV", "Port %s is not type netdev" % portkey)
                if port_state == "true":
                    pytest_assert(show_intf['int_status'][port_name]['oper_state'] == "up",
                                  "Show interface state is down when it should be up")
                if port_state == "false":
                    pytest_assert(show_intf['int_status'][port_name]['oper_state'] == "down",
                                  "Show interface state is up when it should be down")

                if asic.namespace is None:
                    cmd = "sudo ifconfig %s" % port_name
                else:
                    cmd = "sudo ip netns exec %s ifconfig %s" % (asic.namespace, port_name)
                ifout = per_host.command(cmd)
                assert "not found" not in ifout['stdout_lines'][0], "Interface %s not found" % port_name
                if port_state == "true" and "RUNNING" in ifout['stdout_lines'][0]:
                    logger.debug("Interface state is up and matches")
                elif port_state == "false" and "RUNNING" not in ifout['stdout_lines'][0]:
                    logger.debug("Interface state is down and matches")
                else:
                    raise AssertionError("Interface state does not match: %s %s", port_state, ifout['stdout_lines'][0])
def test_voq_interface_create(duthosts):
    """
    Verify router interfaces are created on all line cards and present in Chassis App Db.

    * Verify router interface creation on local ports in ASIC DB.
    * PORT_ID should match system port table and traced back to config_db.json, mac and MTU should match as well.
    * Verify SYSTEM_INTERFACE table in Chassis AppDb (redis-dump -h <ip> -p 6380 -d 12 on supervisor).
    * Verify creation interfaces with different MTUs in configdb.json.
    * Verify creation of different subnet masks in configdb.json.
    * Repeat with IPv4, IPv6, dual-stack.

    """
    for per_host in duthosts.frontend_nodes:
        logger.info("Check router interfaces on node: %s", per_host.hostname)

        for asic in per_host.asics:
            cfg_facts = asic.config_facts(source="persistent")['ansible_facts']
            dev_intfs = cfg_facts['INTERFACE']
            dev_sysports = get_device_system_ports(cfg_facts)

            slot = per_host.facts['slot_num']
            rif_ports_in_asicdb = []

            # intf_list = get_router_interface_list(dev_intfs)
            asicdb = AsicDbCli(asic)

            asicdb_intf_key_list = asicdb.get_router_if_list()
            # Check each rif in the asicdb, if it is local port, check VOQ DB for correct RIF.
            # If it is on system port, verify slot/asic/port and OID match a RIF in VoQDB
            for rif in asicdb_intf_key_list:
                rif_type = asicdb.hget_key_value(
                    rif, "SAI_ROUTER_INTERFACE_ATTR_TYPE")
                if rif_type != "SAI_ROUTER_INTERFACE_TYPE_PORT":
                    logger.info("Skip this rif: %s, it is not on a port: %s",
                                rif, rif_type)
                    continue
                else:
                    portid = asicdb.hget_key_value(
                        rif, "SAI_ROUTER_INTERFACE_ATTR_PORT_ID")
                    logger.info("Process RIF %s, Find port with ID: %s", rif,
                                portid)

                porttype = asicdb.get_rif_porttype(portid)
                logger.info("RIF: %s is of type: %s", rif, porttype)
                if porttype == 'hostif':
                    # find the hostif entry to get the physical port the router interface is on.
                    hostifkey = asicdb.find_hostif_by_portid(portid)
                    hostif = asicdb.hget_key_value(hostifkey,
                                                   'SAI_HOSTIF_ATTR_NAME')
                    logger.info("RIF: %s is on local port: %s", rif, hostif)
                    rif_ports_in_asicdb.append(hostif)
                    if hostif not in dev_intfs:
                        pytest.fail(
                            "Port: %s has a router interface, but it isn't in configdb."
                            % portid)

                    # check MTU and ethernet address
                    asicdb.get_and_check_key_value(
                        rif,
                        cfg_facts['PORT'][hostif]['mtu'],
                        field="SAI_ROUTER_INTERFACE_ATTR_MTU")
                    intf_mac = get_sonic_mac(per_host, asic.asic_index, hostif)
                    asicdb.get_and_check_key_value(
                        rif,
                        intf_mac,
                        field="SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS")

                    sup_rif = asicdb.hget_key_value("VIDTORID",
                                                    "oid:" + rif.split(":")[3])
                    sysport_info = find_system_port(dev_sysports, slot,
                                                    asic.asic_index, hostif)
                    for sup in duthosts.supervisor_nodes:
                        check_rif_on_sup(sup, sup_rif, sysport_info['slot'],
                                         sysport_info['asic'], hostif)

                elif porttype == 'sysport':
                    try:
                        port_output = asicdb.hget_key_value(
                            "ASIC_STATE:SAI_OBJECT_TYPE_SYSTEM_PORT:" + portid,
                            field="SAI_SYSTEM_PORT_ATTR_CONFIG_INFO")
                    except RedisKeyNotFound:
                        # not a hostif or system port, log error and continue
                        logger.error(
                            "Did not find OID %s in local or system tables" %
                            portid)
                        continue
                    port_data = json.loads(port_output)
                    for cfg_port in dev_sysports:
                        if dev_sysports[cfg_port][
                                'system_port_id'] == port_data['port_id']:
                            logger.info("RIF: %s is on remote port: %s", rif,
                                        cfg_port)
                            break
                    else:
                        raise AssertionError(
                            "Did not find OID %s in local or system tables" %
                            portid)

                    sys_slot, sys_asic, sys_port = cfg_port.split("|")
                    sup_rif = asicdb.hget_key_value("VIDTORID",
                                                    "oid:" + rif.split(":")[3])
                    for sup in duthosts.supervisor_nodes:
                        check_rif_on_sup(sup, sup_rif, sys_slot, sys_asic,
                                         sys_port)

                elif porttype == 'port':
                    # this is the RIF on the inband port.
                    inband = get_inband_info(cfg_facts)
                    logger.info("RIF: %s is on local port: %s", rif,
                                inband['port'])

                    # check MTU and ethernet address
                    asicdb.get_and_check_key_value(
                        rif,
                        cfg_facts['PORT'][inband['port']]['mtu'],
                        field="SAI_ROUTER_INTERFACE_ATTR_MTU")
                    intf_mac = get_sonic_mac(per_host, asic.asic_index,
                                             inband['port'])
                    asicdb.get_and_check_key_value(
                        rif,
                        intf_mac,
                        field="SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS")

                    sup_rif = asicdb.hget_key_value("VIDTORID",
                                                    "oid:" + rif.split(":")[3])
                    sysport_info = find_system_port(dev_sysports, slot,
                                                    asic.asic_index,
                                                    inband['port'])
                    for sup in duthosts.supervisor_nodes:
                        check_rif_on_sup(sup, sup_rif, sysport_info['slot'],
                                         sysport_info['asic'], inband['port'])

            # Verify each RIF in config had a corresponding local port RIF in the asicDB.
            for rif in dev_intfs:
                pytest_assert(
                    rif in rif_ports_in_asicdb,
                    "Interface %s is in configdb.json but not in asicdb" % rif)
            logger.info(
                "Interfaces %s are present in configdb.json and asicdb" %
                str(dev_intfs.keys()))
Exemple #10
0
def test_voq_system_port_create(duthosts, enum_frontend_dut_hostname,
                                enum_asic_index, all_cfg_facts):
    """Compare the config facts with the asic db for system ports

    * Verify ASIC_DB get all system ports referenced in configDB created on all hosts and ASICs.
    * Verify object creation and values of port attributes.

    """
    per_host = duthosts[enum_frontend_dut_hostname]
    asic = per_host.asics[
        enum_asic_index if enum_asic_index is not None else 0]
    cfg_facts = all_cfg_facts[per_host.hostname][
        asic.asic_index]['ansible_facts']

    logger.info("Checking system ports on host: %s, asic: %s",
                per_host.hostname, asic.asic_index)

    dev_ports = get_device_system_ports(cfg_facts)
    asicdb = AsicDbCli(asic)
    sys_port_table = asicdb.dump(asicdb.ASIC_SYSPORT_TABLE)
    keylist = sys_port_table.keys()
    pytest_assert(
        len(keylist) == len(dev_ports.keys()),
        "Found %d system port keys, %d entries in cfg_facts, not matching" %
        (len(keylist), len(dev_ports.keys())))
    logger.info(
        "Found %d system port keys, %d entries in cfg_facts, checking each.",
        len(keylist), len(dev_ports.keys()))
    for portkey in keylist:
        try:
            port_config_info = sys_port_table[portkey]['value'][
                'SAI_SYSTEM_PORT_ATTR_CONFIG_INFO']
        except KeyError:
            # TODO: Need to check on behavior here.
            logger.warning(
                "System port: %s had no SAI_SYSTEM_PORT_ATTR_CONFIG_INFO",
                portkey)
            continue

        port_data = json.loads(port_config_info)
        for cfg_port in dev_ports:
            if dev_ports[cfg_port]['system_port_id'] == port_data['port_id']:
                #             "switch_id": "0",
                #             "core_index": "1",
                #             "core_port_index": "6",
                #             "speed": "400000"
                pytest_assert(
                    dev_ports[cfg_port]['switch_id'] ==
                    port_data['attached_switch_id'],
                    "switch IDs do not match for port: %s" % portkey)
                pytest_assert(
                    dev_ports[cfg_port]['core_index'] ==
                    port_data['attached_core_index'],
                    "switch IDs do not match for port: %s" % portkey)
                pytest_assert(
                    dev_ports[cfg_port]['core_port_index'] ==
                    port_data['attached_core_port_index'],
                    "switch IDs do not match for port: %s" % portkey)
                pytest_assert(
                    dev_ports[cfg_port]['speed'] == port_data['speed'],
                    "switch IDs do not match for port: %s" % portkey)
                break
        else:
            logger.error("Could not find config entry for portkey: %s" %
                         portkey)

    logger.info("Host: %s, Asic: %s all ports match all parameters",
                per_host.hostname, asic.asic_index)
Exemple #11
0
def check_voq_interfaces(duthosts, per_host, asic, cfg_facts):
    """
    Checks router interfaces on a dut.

    Args:
        duthosts: The duthosts fixture
        per_host: Instance of MultiAsicSonic host to check.
        asic: Instance of SonicAsic to check,
        cfg_facts: Config facts for the frontend duthost/asic under test

    """
    logger.info("Check router interfaces on node: %s, asic: %d",
                per_host.hostname, asic.asic_index)

    dev_intfs = cfg_facts.get('INTERFACE', {})
    voq_intfs = cfg_facts.get('VOQ_INBAND_INTERFACE', [])
    dev_sysports = get_device_system_ports(cfg_facts)

    rif_ports_in_asicdb = []

    # intf_list = get_router_interface_list(dev_intfs)
    asicdb = AsicDbCli(asic)
    asicdb_rif_table = asicdb.dump(asicdb.ASIC_ROUTERINTF_TABLE)
    sys_port_table = asicdb.dump(asicdb.ASIC_SYSPORT_TABLE)

    # asicdb_intf_key_list = asicdb.get_router_if_list()
    # Check each rif in the asicdb, if it is local port, check VOQ DB for correct RIF.
    # If it is on system port, verify slot/asic/port and OID match a RIF in VoQDB
    for rif in asicdb_rif_table.keys():
        rif_type = asicdb_rif_table[rif]['value'][
            "SAI_ROUTER_INTERFACE_ATTR_TYPE"]
        if rif_type != "SAI_ROUTER_INTERFACE_TYPE_PORT":
            logger.info("Skip this rif: %s, it is not on a port: %s", rif,
                        rif_type)
            continue
        else:
            portid = asicdb_rif_table[rif]['value'][
                "SAI_ROUTER_INTERFACE_ATTR_PORT_ID"]
            logger.info("Process RIF %s, Find port with ID: %s", rif, portid)

        porttype = asicdb.get_rif_porttype(portid)
        logger.info("RIF: %s is of type: %s", rif, porttype)
        if porttype == 'hostif':
            # find the hostif entry to get the physical port the router interface is on.
            hostifkey = asicdb.find_hostif_by_portid(portid)
            hostif = asicdb.hget_key_value(hostifkey, 'SAI_HOSTIF_ATTR_NAME')
            logger.info("RIF: %s is on local port: %s", rif, hostif)
            rif_ports_in_asicdb.append(hostif)
            if hostif not in dev_intfs and hostif not in voq_intfs:
                pytest.fail(
                    "Port: %s has a router interface, but it isn't in configdb."
                    % portid)

            # check MTU and ethernet address
            pytest_assert(
                asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_MTU"]
                == cfg_facts['PORT'][hostif]['mtu'],
                "MTU for rif %s is not %s" %
                (rif, cfg_facts['PORT'][hostif]['mtu']))
            intf_mac = get_sonic_mac(per_host, asic.asic_index, hostif)
            pytest_assert(
                asicdb_rif_table[rif]['value']
                ["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"].lower() ==
                intf_mac.lower(), "MAC for rif %s is not %s" % (rif, intf_mac))

            sysport_info = {
                'slot': cfg_facts['DEVICE_METADATA']['localhost']['hostname'],
                'asic': cfg_facts['DEVICE_METADATA']['localhost']['asic_name']
            }

            if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0:
                check_rif_on_sup(per_host, sysport_info['slot'],
                                 sysport_info['asic'], hostif)
            else:
                for sup in duthosts.supervisor_nodes:
                    check_rif_on_sup(sup, sysport_info['slot'],
                                     sysport_info['asic'], hostif)

        elif porttype == 'sysport':
            try:
                port_output = sys_port_table[
                    "ASIC_STATE:SAI_OBJECT_TYPE_SYSTEM_PORT:" +
                    portid]['value']['SAI_SYSTEM_PORT_ATTR_CONFIG_INFO']
            except KeyError:
                # not a hostif or system port, log error and continue
                logger.error("Did not find OID %s in local or system tables" %
                             portid)
                continue
            port_data = json.loads(port_output)
            for cfg_port in dev_sysports:
                if dev_sysports[cfg_port]['system_port_id'] == port_data[
                        'port_id']:
                    logger.info("RIF: %s is on remote port: %s", rif, cfg_port)
                    break
            else:
                raise AssertionError(
                    "Did not find OID %s in local or system tables" % portid)

            sys_slot, sys_asic, sys_port = cfg_port.split("|")
            if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0:
                check_rif_on_sup(per_host, sys_slot, sys_asic, sys_port)
            else:
                for sup in duthosts.supervisor_nodes:
                    check_rif_on_sup(sup, sys_slot, sys_asic, sys_port)

        elif porttype == 'port':
            # this is the RIF on the inband port.
            inband = get_inband_info(cfg_facts)
            logger.info("RIF: %s is on local port: %s", rif, inband['port'])

            # check MTU and ethernet address
            pytest_assert(
                asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_MTU"]
                == cfg_facts['PORT'][inband['port']]['mtu'],
                "MTU for rif %s is not %s" %
                (rif, cfg_facts['PORT'][inband['port']]['mtu']))
            intf_mac = get_sonic_mac(per_host, asic.asic_index, inband['port'])
            pytest_assert(
                asicdb_rif_table[rif]['value']
                ["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"].lower() ==
                intf_mac.lower(), "MAC for rif %s is not %s" % (rif, intf_mac))

            sysport_info = {
                'slot': cfg_facts['DEVICE_METADATA']['localhost']['hostname'],
                'asic': cfg_facts['DEVICE_METADATA']['localhost']['asic_name']
            }

            if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0:
                check_rif_on_sup(per_host, sysport_info['slot'],
                                 sysport_info['asic'], inband['port'])
            else:
                for sup in duthosts.supervisor_nodes:
                    check_rif_on_sup(sup, sysport_info['slot'],
                                     sysport_info['asic'], inband['port'])

        # TODO: Could be on a LAG
        elif porttype == 'lag':
            lagid = asicdb.hget_key_value(
                "%s:%s" % (AsicDbCli.ASIC_LAG_TABLE, portid),
                'SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID')
            logger.info("RIF: %s is on system LAG: %s", rif, lagid)

            if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0:
                voqdb = VoqDbCli(per_host)
            else:
                voqdb = VoqDbCli(duthosts.supervisor_nodes[0])

            systemlagtable = voqdb.dump("SYSTEM_LAG_ID_TABLE")
            for lag, sysid in systemlagtable['SYSTEM_LAG_ID_TABLE'][
                    'value'].iteritems():
                if sysid == lagid:
                    logger.info("System LAG ID %s is portchannel: %s", lagid,
                                lag)
                    break

            myslot = cfg_facts['DEVICE_METADATA']['localhost']['hostname']
            myasic = cfg_facts['DEVICE_METADATA']['localhost']['asic_name']
            if lag.startswith("%s|%s" % (myslot, myasic)):
                logger.info(
                    "Lag: %s is a local portchannel with a router interface.",
                    lag)
                (s, a, lagname) = lag.split("|")
                pytest_assert(
                    lagname in cfg_facts['PORTCHANNEL_INTERFACE'],
                    "RIF Interface %s is in configdb.json but not in asicdb" %
                    rif)

                if per_host.is_multi_asic and len(
                        duthosts.supervisor_nodes) == 0:
                    check_rif_on_sup(per_host, myslot, myasic, lagname)
                else:
                    for sup in duthosts.supervisor_nodes:
                        check_rif_on_sup(sup, myslot, myasic, lagname)

            else:
                logger.info(
                    "Lag: %s is a remote portchannel with a router interface.",
                    lag)

    # Verify each RIF in config had a corresponding local port RIF in the asicDB.
    for rif in dev_intfs:
        if rif not in rif_ports_in_asicdb:
            raise AssertionError(
                "Interface %s is in configdb.json but not in asicdb" % rif)

    logger.info("Interfaces %s are present in configdb.json and asicdb" %
                str(dev_intfs.keys()))
Exemple #12
0
def test_voq_local_port_create(duthosts, enum_frontend_dut_hostname,
                               enum_asic_index, all_cfg_facts):
    """Compare the config facts with the asic db for local ports

    * Verify ASIC_DB has host interface information for all local ports on all cards and ASICs.
    * Verify host interfaces exist on host CLI (ifconfig).
    * Verify interfaces exist in show interfaces on the linecard.
    """

    per_host = duthosts[enum_frontend_dut_hostname]
    asic = per_host.asics[
        enum_asic_index if enum_asic_index is not None else 0]
    cfg_facts = all_cfg_facts[per_host.hostname][
        asic.asic_index]['ansible_facts']

    dev_ports = cfg_facts['PORT']

    asicdb = AsicDbCli(asic)
    hostif_table = asicdb.get_hostif_table(refresh=True)

    keylist = hostif_table.keys()
    pytest_assert(
        len(keylist) == len(dev_ports.keys()),
        "Found %d hostif keys, %d entries in cfg_facts" %
        (len(keylist), len(dev_ports.keys())))
    logger.info("Found %s ports to check on host:%s, asic: %s.",
                len(dev_ports.keys()), per_host.hostname, asic.asic_index)

    show_intf = asic.show_interface(
        command="status", include_internal_intfs=True)['ansible_facts']
    for portkey in keylist:
        portkey = portkey.decode(
            'unicode-escape'
        )  # need to handle the hyphen in the inband port name
        port_name = hostif_table[portkey]['value'][
            "SAI_HOSTIF_ATTR_NAME"].decode('unicode-escape')
        port_state = hostif_table[portkey]['value'][
            "SAI_HOSTIF_ATTR_OPER_STATUS"]
        port_type = hostif_table[portkey]['value']["SAI_HOSTIF_ATTR_TYPE"]

        logger.info("Checking port: %s, state: %s", port_name, port_state)
        # "SAI_HOSTIF_ATTR_NAME": "Ethernet0",
        # "SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x1000000000002",
        # "SAI_HOSTIF_ATTR_OPER_STATUS": "false",
        # "SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV"
        pytest_assert(port_type == "SAI_HOSTIF_TYPE_NETDEV",
                      "Port %s is not type netdev" % portkey)
        if port_state == "true":
            pytest_assert(
                show_intf['int_status'][port_name]['oper_state'] == "up",
                "Show interface state is down when it should be up")
        if port_state == "false":
            pytest_assert(
                show_intf['int_status'][port_name]['oper_state'] == "down",
                "Show interface state is up when it should be down")

        if asic.namespace is None:
            cmd = "sudo ifconfig %s" % port_name
        else:
            cmd = "sudo ip netns exec %s ifconfig %s" % (asic.namespace,
                                                         port_name)
        ifout = per_host.command(cmd)
        assert "not found" not in ifout['stdout_lines'][
            0], "Interface %s not found" % port_name
        if port_state == "true" and "RUNNING" in ifout['stdout_lines'][0]:
            logger.debug("Interface state is up and matches")
        elif port_state == "false" and "RUNNING" not in ifout['stdout_lines'][
                0]:
            logger.debug("Interface state is down and matches")
        else:
            raise AssertionError("Interface state does not match: %s %s",
                                 port_state, ifout['stdout_lines'][0])
def test_voq_interface_create(duthosts, enum_frontend_dut_hostname,
                              enum_asic_index, all_cfg_facts):
    """
    Verify router interfaces are created on all line cards and present in Chassis App Db.

    * Verify router interface creation on local ports in ASIC DB.
    * PORT_ID should match system port table and traced back to config_db.json, mac and MTU should match as well.
    * Verify SYSTEM_INTERFACE table in Chassis AppDb (redis-dump -h <ip> -p 6380 -d 12 on supervisor).
    * Verify creation interfaces with different MTUs in configdb.json.
    * Verify creation of different subnet masks in configdb.json.
    * Repeat with IPv4, IPv6, dual-stack.

    """
    per_host = duthosts[enum_frontend_dut_hostname]
    asic = per_host.asics[
        enum_asic_index if enum_asic_index is not None else 0]
    cfg_facts = all_cfg_facts[per_host.hostname][
        asic.asic_index]['ansible_facts']
    logger.info("Check router interfaces on node: %s, asic: %d",
                per_host.hostname, asic.asic_index)

    dev_intfs = cfg_facts['INTERFACE']
    voq_intfs = cfg_facts['VOQ_INBAND_INTERFACE']
    dev_sysports = get_device_system_ports(cfg_facts)

    slot = per_host.facts['slot_num']

    rif_ports_in_asicdb = []

    # intf_list = get_router_interface_list(dev_intfs)
    asicdb = AsicDbCli(asic)
    asicdb_rif_table = asicdb.dump(asicdb.ASIC_ROUTERINTF_TABLE)
    sys_port_table = asicdb.dump(asicdb.ASIC_SYSPORT_TABLE)

    # asicdb_intf_key_list = asicdb.get_router_if_list()
    # Check each rif in the asicdb, if it is local port, check VOQ DB for correct RIF.
    # If it is on system port, verify slot/asic/port and OID match a RIF in VoQDB
    for rif in asicdb_rif_table.keys():
        rif_type = asicdb_rif_table[rif]['value'][
            "SAI_ROUTER_INTERFACE_ATTR_TYPE"]
        if rif_type != "SAI_ROUTER_INTERFACE_TYPE_PORT":
            logger.info("Skip this rif: %s, it is not on a port: %s", rif,
                        rif_type)
            continue
        else:
            portid = asicdb_rif_table[rif]['value'][
                "SAI_ROUTER_INTERFACE_ATTR_PORT_ID"]
            logger.info("Process RIF %s, Find port with ID: %s", rif, portid)

        porttype = asicdb.get_rif_porttype(portid)
        logger.info("RIF: %s is of type: %s", rif, porttype)
        if porttype == 'hostif':
            # find the hostif entry to get the physical port the router interface is on.
            hostifkey = asicdb.find_hostif_by_portid(portid)
            hostif = asicdb.hget_key_value(hostifkey, 'SAI_HOSTIF_ATTR_NAME')
            logger.info("RIF: %s is on local port: %s", rif, hostif)
            rif_ports_in_asicdb.append(hostif)
            if hostif not in dev_intfs and hostif not in voq_intfs:
                pytest.fail(
                    "Port: %s has a router interface, but it isn't in configdb."
                    % portid)

            # check MTU and ethernet address
            pytest_assert(
                asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_MTU"]
                == cfg_facts['PORT'][hostif]['mtu'],
                "MTU for rif %s is not %s" %
                (rif, cfg_facts['PORT'][hostif]['mtu']))
            intf_mac = get_sonic_mac(per_host, asic.asic_index, hostif)
            pytest_assert(
                asicdb_rif_table[rif]['value']
                ["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"].lower() ==
                intf_mac.lower(), "MAC for rif %s is not %s" % (rif, intf_mac))

            sysport_info = find_system_port(dev_sysports, slot,
                                            asic.asic_index, hostif)
            for sup in duthosts.supervisor_nodes:
                check_rif_on_sup(sup, sysport_info['slot'],
                                 sysport_info['asic'], hostif)

        elif porttype == 'sysport':
            try:
                port_output = sys_port_table[
                    "ASIC_STATE:SAI_OBJECT_TYPE_SYSTEM_PORT:" +
                    portid]['value']['SAI_SYSTEM_PORT_ATTR_CONFIG_INFO']
            except KeyError:
                # not a hostif or system port, log error and continue
                logger.error("Did not find OID %s in local or system tables" %
                             portid)
                continue
            port_data = json.loads(port_output)
            for cfg_port in dev_sysports:
                if dev_sysports[cfg_port]['system_port_id'] == port_data[
                        'port_id']:
                    logger.info("RIF: %s is on remote port: %s", rif, cfg_port)
                    break
            else:
                raise AssertionError(
                    "Did not find OID %s in local or system tables" % portid)

            sys_slot, sys_asic, sys_port = cfg_port.split("|")
            for sup in duthosts.supervisor_nodes:
                check_rif_on_sup(sup, sys_slot, sys_asic, sys_port)

        elif porttype == 'port':
            # this is the RIF on the inband port.
            inband = get_inband_info(cfg_facts)
            logger.info("RIF: %s is on local port: %s", rif, inband['port'])

            # check MTU and ethernet address
            pytest_assert(
                asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_MTU"]
                == cfg_facts['PORT'][inband['port']]['mtu'],
                "MTU for rif %s is not %s" %
                (rif, cfg_facts['PORT'][inband['port']]['mtu']))
            intf_mac = get_sonic_mac(per_host, asic.asic_index, inband['port'])
            pytest_assert(
                asicdb_rif_table[rif]['value']
                ["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"].lower() ==
                intf_mac.lower(), "MAC for rif %s is not %s" % (rif, intf_mac))

            sysport_info = find_system_port(dev_sysports, slot,
                                            asic.asic_index, inband['port'])

            for sup in duthosts.supervisor_nodes:
                check_rif_on_sup(sup, sysport_info['slot'],
                                 sysport_info['asic'], inband['port'])

        # TODO: Could be on a LAG

    # Verify each RIF in config had a corresponding local port RIF in the asicDB.
    for rif in dev_intfs:
        pytest_assert(
            rif in rif_ports_in_asicdb,
            "Interface %s is in configdb.json but not in asicdb" % rif)

    logger.info("Interfaces %s are present in configdb.json and asicdb" %
                str(dev_intfs.keys()))