std::shared_ptr BestCandidateFinder::findCurrentBestMatchForAclCounter()

in syncd/BestCandidateFinder.cpp [217:363]


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

    /*
     * For acl counter we use SAI_ACL_COUNTER_ATTR_TABLE_ID to match exact
     * counter since if set, then table id will be matched previously.
     */

    std::vector<std::shared_ptr<SaiObj>> objs;

    const auto tmpAclTables = m_temporaryView.getObjectsByObjectType(SAI_OBJECT_TYPE_ACL_TABLE);

    for (auto& tmpAclTable: tmpAclTables)
    {
        auto tmpAclCounterTableIdAttr = temporaryObj->tryGetSaiAttr(SAI_ACL_COUNTER_ATTR_TABLE_ID);

        if (tmpAclCounterTableIdAttr == nullptr)
            continue;

        if (tmpAclCounterTableIdAttr->getOid() == SAI_NULL_OBJECT_ID)
            continue;

        if (tmpAclTable->getVid() != tmpAclCounterTableIdAttr->getOid())
            continue; // not this table

        if (tmpAclTable->getObjectStatus() != SAI_OBJECT_STATUS_FINAL)
            continue; // not processed

        sai_object_id_t aclTableRid = m_temporaryView.m_vidToRid.at(tmpAclTable->getVid());

        sai_object_id_t curAclTableVid = m_currentView.m_ridToVid.at(aclTableRid);

        for (auto c: candidateObjects)
        {
            auto curAclCounterTableIdAttr = c.obj->tryGetSaiAttr(SAI_ACL_COUNTER_ATTR_TABLE_ID);

            if (curAclCounterTableIdAttr == nullptr)
                continue;

            if (curAclCounterTableIdAttr->getOid() != curAclTableVid)
                continue;

            objs.push_back(c.obj);
            continue;
        }
    }

    if (objs.size() > 1)
    {
        // in this case more than 1 acl counters has the same acl table associated,
        // try to find best acl counter matching same acl entry field

        SWSS_LOG_INFO("more than 1 (%zu) best match on acl counter using acl table", objs.size());

        const auto tmpAclEntries = m_temporaryView.getObjectsByObjectType(SAI_OBJECT_TYPE_ACL_ENTRY);

        for (auto& tmpAclEntry: tmpAclEntries)
        {
            auto tmpAclEntryActionCounterAttr = tmpAclEntry->tryGetSaiAttr(SAI_ACL_ENTRY_ATTR_ACTION_COUNTER);

            if (tmpAclEntryActionCounterAttr == nullptr)
                continue; // skip acl entries with no counter

            if (tmpAclEntryActionCounterAttr->getOid() != temporaryObj->getVid())
                continue; // not the counter we are looking for

            // try use priority attribute first since it should be unique
            // TODO we should use HASH from all non OID attribute here to have
            // better chance for finding best candidate, this could be also
            // used in pre match logic

            std::vector<std::shared_ptr<const SaiAttr>> values;

            if (tmpAclEntry->hasAttr(SAI_ACL_ENTRY_ATTR_PRIORITY))
            {
                values.push_back(tmpAclEntry->getSaiAttr(SAI_ACL_ENTRY_ATTR_PRIORITY));
            }

            for (auto&attr: tmpAclEntry->getAllAttributes())
            {
                values.push_back(attr.second);
            }

            for (auto&attr: values)
            {
                auto*meta = attr->getAttrMetadata();

                if (!meta->isaclfield && meta->attrid != SAI_ACL_ENTRY_ATTR_PRIORITY)
                    continue; // looking only for acl fields

                if (meta->isoidattribute)
                    continue; // only non oid fields

                auto tmpValue = attr->getStrAttrValue();

                const auto curAclEntries = m_currentView.getObjectsByObjectType(SAI_OBJECT_TYPE_ACL_ENTRY);

                for (auto& curAclEntry: curAclEntries)
                {
                    auto curAclEntryAclFieldAttr = curAclEntry->tryGetSaiAttr(meta->attrid);

                    if (curAclEntryAclFieldAttr == nullptr)
                        continue; // this field is missing from current view

                    if (curAclEntryAclFieldAttr->getStrAttrValue() != tmpValue)
                        continue; // values are different, keep looking

                    auto curAclEntryActionCounterAttr = curAclEntry->tryGetSaiAttr(SAI_ACL_ENTRY_ATTR_ACTION_COUNTER);

                    if (curAclEntryActionCounterAttr == nullptr)
                        continue; // no counter

                    auto curAclCounter = m_currentView.m_oOids.at(curAclEntryActionCounterAttr->getOid());

                    if (curAclCounter->getObjectStatus() != SAI_OBJECT_STATUS_NOT_PROCESSED)
                        continue;

                    for (auto c: candidateObjects)
                    {
                        if (c.obj->getVid() == curAclCounter->getVid())
                        {
                            SWSS_LOG_NOTICE("found best ACL counter match based on ACL entry field: %s, %s",
                                    c.obj->m_str_object_id.c_str(),
                                    meta->attridname);
                            return c.obj;
                        }
                    }
                }
            }
        }

    }

    if (objs.size())
    {
        SWSS_LOG_NOTICE("found best ACL counter match based on ACL table: %s", objs.at(0)->m_str_object_id.c_str());

        return objs.at(0);
    }

    SWSS_LOG_NOTICE("failed to find best candidate for ACL_COUNTER using ACL table");

    return nullptr;
}