std::shared_ptr BestCandidateFinder::findCurrentBestMatchForRouterInterface()

in syncd/BestCandidateFinder.cpp [652:844]


std::shared_ptr<SaiObj> BestCandidateFinder::findCurrentBestMatchForRouterInterface(
        _In_ const std::shared_ptr<const SaiObj> &temporaryObj,
        _In_ const std::vector<sai_object_compare_info_t> &candidateObjects)
{
    SWSS_LOG_ENTER();

    /*
     * For router interface which is LOOPBACK, we could trace them to TUNNEL
     * object on which they are used. It could be not obvious, when multiple
     * tunnels will be used.
     */

    const auto typeAttr = temporaryObj->getSaiAttr(SAI_ROUTER_INTERFACE_ATTR_TYPE);

    if (typeAttr->getSaiAttr()->value.s32 != SAI_ROUTER_INTERFACE_TYPE_LOOPBACK)
    {
        SWSS_LOG_WARN("RIF %s is not LOOPBACK", temporaryObj->m_str_object_id.c_str());

        return nullptr;
    }

    const auto tmpTunnels = m_temporaryView.getNotProcessedObjectsByObjectType(SAI_OBJECT_TYPE_TUNNEL);

    for (auto tmpTunnel: tmpTunnels)
    {
        /*
         * Try match tunnel by src encap IP address.
         */

        if (!tmpTunnel->hasAttr(SAI_TUNNEL_ATTR_ENCAP_SRC_IP))
        {
            // not encap src attribute, skip
            continue;
        }

        const std::string tmpSrcIP = tmpTunnel->getSaiAttr(SAI_TUNNEL_ATTR_ENCAP_SRC_IP)->getStrAttrValue();

        const auto curTunnels = m_currentView.getNotProcessedObjectsByObjectType(SAI_OBJECT_TYPE_TUNNEL);

        for (auto curTunnel: curTunnels)
        {
            if (!tmpTunnel->hasAttr(SAI_TUNNEL_ATTR_ENCAP_SRC_IP))
            {
                // not encap src attribute, skip
                continue;
            }

            const std::string curSrcIP = tmpTunnel->getSaiAttr(SAI_TUNNEL_ATTR_ENCAP_SRC_IP)->getStrAttrValue();

            if (curSrcIP != tmpSrcIP)
            {
                continue;
            }

            /*
             * At this point we have both tunnels which ip matches.
             */

            if (tmpTunnel->hasAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE) &&
                curTunnel->hasAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE))
            {
                auto tmpRif = tmpTunnel->getSaiAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE);
                auto curRif = curTunnel->getSaiAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE);

                if (tmpRif->getSaiAttr()->value.oid == temporaryObj->getVid())
                {
                    for (auto c: candidateObjects)
                    {
                        if (c.obj->getVid() != curRif->getSaiAttr()->value.oid)
                            continue;

                        SWSS_LOG_INFO("found best ROUTER_INTERFACE based on TUNNEL underlay interface %s", c.obj->m_str_object_id.c_str());

                        return c.obj;
                    }
                }
            }

            if (tmpTunnel->hasAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE) &&
                curTunnel->hasAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE))
            {
                auto tmpRif = tmpTunnel->getSaiAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE);
                auto curRif = curTunnel->getSaiAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE);

                if (tmpRif->getSaiAttr()->value.oid == temporaryObj->getVid())
                {
                    for (auto c: candidateObjects)
                    {
                        if (c.obj->getVid() != curRif->getSaiAttr()->value.oid)
                            continue;

                        SWSS_LOG_INFO("found best ROUTER_INTERFACE based on TUNNEL overlay interface %s", c.obj->m_str_object_id.c_str());

                        return c.obj;
                    }
                }
            }
        }
    }

    // try find tunnel by TUNNEL_TERM_TABLE_ENTRY using SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP

    for (auto tmpTunnel: tmpTunnels)
    {
        const auto curTunnels = m_currentView.getNotProcessedObjectsByObjectType(SAI_OBJECT_TYPE_TUNNEL);

        for (auto curTunnel: curTunnels)
        {
            const auto tmpTunnelTermTableEtnries = m_temporaryView.getNotProcessedObjectsByObjectType(SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY);

            for (auto tmpTunnelTermTableEntry: tmpTunnelTermTableEtnries)
            {
                auto tmpTunnelId = tmpTunnelTermTableEntry->tryGetSaiAttr(SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID);

                if (tmpTunnelId == nullptr)
                    continue;

                auto tmpDstIp = tmpTunnelTermTableEntry->tryGetSaiAttr(SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP);

                if (tmpDstIp == nullptr)
                    continue;

                if (tmpTunnelId->getOid() != tmpTunnel->getVid())   // not this tunnel
                    continue;

                const auto curTunnelTermTableEtnries = m_currentView.getNotProcessedObjectsByObjectType(SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY);

                for (auto curTunnelTermTableEntry: curTunnelTermTableEtnries)
                {
                    auto curTunnelId = curTunnelTermTableEntry->tryGetSaiAttr(SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID);

                    if (curTunnelId == nullptr)
                        continue;

                    auto curDstIp = curTunnelTermTableEntry->tryGetSaiAttr(SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP);

                    if (curDstIp == nullptr)
                        continue;

                    if (curTunnelId->getOid() != curTunnel->getVid())   // not this tunnel
                        continue;

                    if (curDstIp->getStrAttrValue() != tmpDstIp->getStrAttrValue())
                        continue;

                    if (tmpTunnel->hasAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE) &&
                            curTunnel->hasAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE))
                    {
                        auto tmpRif = tmpTunnel->getSaiAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE);
                        auto curRif = curTunnel->getSaiAttr(SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE);

                        if (tmpRif->getSaiAttr()->value.oid == temporaryObj->getVid())
                        {
                            for (auto c: candidateObjects)
                            {
                                if (c.obj->getVid() != curRif->getSaiAttr()->value.oid)
                                    continue;

                                SWSS_LOG_INFO("found best ROUTER_INTERFACE based on TUNNEL underlay interface %s", c.obj->m_str_object_id.c_str());

                                return c.obj;
                            }
                        }
                    }

                    if (tmpTunnel->hasAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE) &&
                            curTunnel->hasAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE))
                    {
                        auto tmpRif = tmpTunnel->getSaiAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE);
                        auto curRif = curTunnel->getSaiAttr(SAI_TUNNEL_ATTR_OVERLAY_INTERFACE);

                        if (tmpRif->getSaiAttr()->value.oid == temporaryObj->getVid())
                        {
                            for (auto c: candidateObjects)
                            {
                                if (c.obj->getVid() != curRif->getSaiAttr()->value.oid)
                                    continue;

                                SWSS_LOG_INFO("found best ROUTER_INTERFACE based on TUNNEL overlay interface %s", c.obj->m_str_object_id.c_str());

                                return c.obj;
                            }
                        }
                    }
                }
            }
        }
    }

    SWSS_LOG_NOTICE("failed to find best candidate for LOOPBACK ROUTER_INTERFACE using tunnel");

    return nullptr;
}