sai_object_id_t SingleReiniter::processSingleVid()

in syncd/SingleReiniter.cpp [644:862]


sai_object_id_t SingleReiniter::processSingleVid(
        _In_ sai_object_id_t vid)
{
    SWSS_LOG_ENTER();

    if (vid == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_DEBUG("processed VID 0 to RID 0");

        return SAI_NULL_OBJECT_ID;
    }

    auto it = m_translatedV2R.find(vid);

    if (it != m_translatedV2R.end())
    {
        /*
         * This object was already processed, just return real object id.
         */

        SWSS_LOG_DEBUG("processed VID %s to RID %s",
                sai_serialize_object_id(vid).c_str(),
                sai_serialize_object_id(it->second).c_str());

        return it->second;
    }

    sai_object_type_t objectType = VidManager::objectTypeQuery(vid);

    std::string strVid = sai_serialize_object_id(vid);

    auto oit = m_oids.find(strVid);

    if (oit == m_oids.end())
    {
        SWSS_LOG_THROW("failed to find VID %s in OIDs map", strVid.c_str());
    }

    std::string asicKey = oit->second;;

    std::shared_ptr<SaiAttributeList> list = m_attributesLists[asicKey];

    sai_attribute_t *attrList = list->get_attr_list();

    uint32_t attrCount = list->get_attr_count();

    processAttributesForOids(objectType, attrCount, attrList);

    bool createObject = true;

    /*
     * Now let's determine whether this object need to be created.  Default
     * objects like default virtual router, queues or cpu can't be created.
     * When object exists on the switch (even VLAN member) it will not be
     * created, but matched. We just need to watch for RO/CO attributes.
     *
     * NOTE: this also should be per switch.
     */

    auto v2rMapIt = m_vidToRidMap.find(vid);

    if (v2rMapIt == m_vidToRidMap.end())
    {
        SWSS_LOG_THROW("failed to find VID %s in VIDTORID map",
                sai_serialize_object_id(vid).c_str());
    }

    sai_object_id_t rid;

    if (m_sw->isDiscoveredRid(v2rMapIt->second))
    {
        rid = v2rMapIt->second;

        createObject = false;

        SWSS_LOG_DEBUG("object %s will not be created, processed VID %s to RID %s",
                sai_serialize_object_type(objectType).c_str(),
                sai_serialize_object_id(vid).c_str(),
                sai_serialize_object_id(rid).c_str());
    }

    if (objectType == SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP)
    {
        /*
         * We need special case for trap group, look inside for details.
         */

        trapGroupWorkaround(vid, rid, createObject, attrCount, attrList);
    }

    if (createObject)
    {
        sai_object_meta_key_t meta_key;

        meta_key.objecttype = objectType;

        /*
         * Since we have only one switch, we can get away using m_switch_rid here.
         */

#ifdef ENABLE_PERF
        auto start = std::chrono::high_resolution_clock::now();
#endif

        sai_status_t status = m_vendorSai->create(meta_key.objecttype, &meta_key.objectkey.key.object_id, m_switch_rid, attrCount, attrList);

#ifdef ENABLE_PERF
        auto end = std::chrono::high_resolution_clock::now();

        typedef std::chrono::duration<double, std::ratio<1>> second_t;

        double duration = std::chrono::duration_cast<second_t>(end - start).count();

        std::get<0>(m_perf_create[objectType])++;
        std::get<1>(m_perf_create[objectType]) += duration;
#endif

        if (status != SAI_STATUS_SUCCESS)
        {
            listFailedAttributes(objectType, attrCount, attrList);

            SWSS_LOG_THROW("failed to create object %s: %s",
                    sai_serialize_object_type(objectType).c_str(),
                    sai_serialize_status(status).c_str());
        }

        rid = meta_key.objectkey.key.object_id;

        SWSS_LOG_DEBUG("created object of type %s, processed VID %s to RID %s",
                sai_serialize_object_type(objectType).c_str(),
                sai_serialize_object_id(vid).c_str(),
                sai_serialize_object_id(rid).c_str());
    }
    else
    {
        SWSS_LOG_DEBUG("setting attributes on object of type %x, processed VID 0x%" PRIx64 " to RID 0x%" PRIx64 " ", objectType, vid, rid);

        for (uint32_t idx = 0; idx < attrCount; idx++)
        {
            sai_attribute_t *attr = &attrList[idx];

            sai_object_meta_key_t meta_key;

            meta_key.objecttype = objectType;
            meta_key.objectkey.key.object_id = rid;

            auto meta = sai_metadata_get_attr_metadata(objectType, attr->id);

            if (meta == NULL)
            {
                SWSS_LOG_THROW("failed to get attribute metadata %s: %d",
                        sai_serialize_object_type(objectType).c_str(),
                        attr->id);
            }

            // XXX workaround
            if (meta->objecttype == SAI_OBJECT_TYPE_SWITCH &&
                    attr->id == SAI_SWITCH_ATTR_SRC_MAC_ADDRESS)
            {
                SWSS_LOG_WARN("skipping to set MAC address since not supported on Mellanox platforms");
                continue;
            }

            if (SAI_HAS_FLAG_CREATE_ONLY(meta->flags))
            {
                /*
                 * If we will be performing this on default existing created
                 * object then it may happen that during snoop in previous
                 * iteration we put some attribute that is create only, then
                 * this set will fail and we need to skip this set.
                 *
                 * NOTE: We could do get here to see if it actually matches.
                 */

                if (m_sw->isDiscoveredRid(rid))
                {
                    continue;
                }

                SWSS_LOG_WARN("skipping create only attr %s: %s",
                        meta->attridname,
                        sai_serialize_attr_value(*meta, *attr).c_str());

                continue;
            }

#ifdef ENABLE_PERF
            auto start = std::chrono::high_resolution_clock::now();
#endif

            sai_status_t status = m_vendorSai->set(meta_key.objecttype, meta_key.objectkey.key.object_id, attr);

#ifdef ENABLE_PERF
            auto end = std::chrono::high_resolution_clock::now();

            typedef std::chrono::duration<double, std::ratio<1>> second_t;

            double duration = std::chrono::duration_cast<second_t>(end - start).count();

            std::get<0>(m_perf_set[objectType])++;
            std::get<1>(m_perf_set[objectType]) += duration;
#endif

            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_THROW(
                        "failed to set %s value %s: %s",
                        meta->attridname,
                        sai_serialize_attr_value(*meta, *attr).c_str(),
                        sai_serialize_status(status).c_str());
            }
        }
    }

    m_translatedV2R[vid] = rid;
    m_translatedR2V[rid] = vid;

    return rid;
}