static int discover()

in saidiscovery/saidiscovery.cpp [74:327]


static int discover(
        _In_ std::shared_ptr<sairedis::SaiInterface> sai,
        _In_ sai_object_id_t id,
        _Inout_ std::map<sai_object_id_t, std::map<std::string, std::string>> &discovered)
{
    SWSS_LOG_ENTER();

    int callCount = 0;

    if (id == SAI_NULL_OBJECT_ID)
    {
        return callCount;
    }

    if (discovered.find(id) != discovered.end())
    {
        return callCount;
    }

    sai_object_type_t ot = sai->objectTypeQuery(id);

    if (ot == SAI_OBJECT_TYPE_NULL)
    {
        SWSS_LOG_ERROR("oid %s returned NULL object type",
                sai_serialize_object_id(id).c_str());

        return callCount;
    }

    SWSS_LOG_INFO("processing %s: %s",
            sai_serialize_object_type(ot).c_str(),
            sai_serialize_object_id(id).c_str());

    discovered[id] = {};

    const sai_object_type_info_t *info = sai_metadata_all_object_type_infos[ot];

    for (int idx = 0; info->attrmetadata[idx] != NULL; ++idx)
    {
        const sai_attr_metadata_t *md = info->attrmetadata[idx];

        if (md->objecttype == SAI_OBJECT_TYPE_PORT &&
                md->attrid == SAI_PORT_ATTR_HW_LANE_LIST)
        {
            // XXX workaround for brcm
            continue;
        }

        /*
         * Note that we don't care about ACL object id's since we assume that
         * there are no ACLs on switch after init.
         */

        sai_attribute_t attr;

        attr.id = md->attrid;

        if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID)
        {
            if (md->objecttype == SAI_OBJECT_TYPE_STP &&
                    md->attrid == SAI_STP_ATTR_BRIDGE_ID)
            {
                SWSS_LOG_WARN("skipping %s since it causes crash", md->attridname);
                continue;
            }

            SWSS_LOG_DEBUG("getting %s for %s", md->attridname,
                    sai_serialize_object_id(id).c_str());

            callCount++;

            sai_status_t status = sai->get(ot, id, 1, &attr);

            if (status != SAI_STATUS_SUCCESS)
            {
                if (gOptions.logWarnings)
                {
                    SWSS_LOG_WARN("%s: %s",
                            md->attridname,
                            sai_serialize_status(status).c_str());
                }

                continue;
            }

            if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_CONST
                    && attr.value.oid != SAI_NULL_OBJECT_ID)
            {
                if (gOptions.logWarnings)
                {
                    SWSS_LOG_WARN("const null, but got value %s on %s",
                            sai_serialize_object_id(attr.value.oid).c_str(),
                            md->attridname);
                }
            }

            if (!md->allownullobjectid && attr.value.oid == SAI_NULL_OBJECT_ID)
            {
                if (gOptions.logWarnings)
                {
                    SWSS_LOG_WARN("dont allow null, but got null on %s", md->attridname);
                }
            }

            discovered[id][md->attridname] = sai_serialize_attr_value(*md, attr);

            SWSS_LOG_DEBUG("result on %s: %s: %s",
                    sai_serialize_object_id(id).c_str(),
                    md->attridname,
                    discovered[id][md->attridname].c_str());

            callCount += discover(sai, attr.value.oid, discovered); // recursion
        }
        else if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_LIST)
        {
            SWSS_LOG_DEBUG("getting %s for %s", md->attridname,
                    sai_serialize_object_id(id).c_str());

            sai_object_id_t list[MAX_ELEMENTS];

            attr.value.objlist.count = MAX_ELEMENTS;
            attr.value.objlist.list = list;

            callCount++;

            sai_status_t status = sai->get(ot, id, 1, &attr);

            if (status != SAI_STATUS_SUCCESS)
            {
                if (gOptions.logWarnings)
                {
                    SWSS_LOG_WARN("%s: %s",
                            md->attridname,
                            sai_serialize_status(status).c_str());
                }

                continue;
            }

            if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_EMPTY_LIST
                    && attr.value.objlist.count != 0)
            {
                if (gOptions.logWarnings)
                {
                    SWSS_LOG_WARN("default is empty list, but got count %u on %s",
                            attr.value.objlist.count,
                            md->attridname);
                }
            }

            discovered[id][md->attridname] = sai_serialize_attr_value(*md, attr);

            SWSS_LOG_INFO("list count %s: %u", md->attridname, attr.value.objlist.count);

            SWSS_LOG_DEBUG("result on %s: %s: %s",
                    sai_serialize_object_id(id).c_str(),
                    md->attridname,
                    discovered[id][md->attridname].c_str());

            for (uint32_t i = 0; i < attr.value.objlist.count; ++i)
            {
                callCount += discover(sai, attr.value.objlist.list[i], discovered); // recursion
            }
        }
        else
        {
            if (!gOptions.fullDiscovery)
            {
                continue;
            }

            if ((md->objecttype == SAI_OBJECT_TYPE_PORT && md->attrid == SAI_PORT_ATTR_FEC_MODE) ||
                (md->objecttype == SAI_OBJECT_TYPE_PORT && md->attrid == SAI_PORT_ATTR_GLOBAL_FLOW_CONTROL_MODE) ||
                (md->objecttype == SAI_OBJECT_TYPE_SWITCH && md->attrid == SAI_SWITCH_ATTR_INIT_SWITCH))
            {
                // workaround since return invalid values
                continue;
            }

            /*
             * Discover non oid attributes as well.
             *
             * TODO lists!
             */

            sai_object_id_t list[MAX_ELEMENTS];

            switch (md->attrvaluetype)
            {
                case SAI_ATTR_VALUE_TYPE_INT8:
                case SAI_ATTR_VALUE_TYPE_INT16:
                case SAI_ATTR_VALUE_TYPE_INT32:
                case SAI_ATTR_VALUE_TYPE_INT64:
                case SAI_ATTR_VALUE_TYPE_UINT8:
                case SAI_ATTR_VALUE_TYPE_UINT16:
                case SAI_ATTR_VALUE_TYPE_UINT32:
                case SAI_ATTR_VALUE_TYPE_UINT64:
                case SAI_ATTR_VALUE_TYPE_POINTER:
                case SAI_ATTR_VALUE_TYPE_BOOL:
                case SAI_ATTR_VALUE_TYPE_UINT32_RANGE:
                case SAI_ATTR_VALUE_TYPE_MAC:
                    break;

                case SAI_ATTR_VALUE_TYPE_INT8_LIST:
                case SAI_ATTR_VALUE_TYPE_INT32_LIST:
                case SAI_ATTR_VALUE_TYPE_UINT32_LIST:
                case SAI_ATTR_VALUE_TYPE_VLAN_LIST:

                    attr.value.objlist.count = MAX_ELEMENTS;
                    attr.value.objlist.list = list;
                    break;

                case SAI_ATTR_VALUE_TYPE_ACL_CAPABILITY:

                    attr.value.aclcapability.action_list.count = MAX_ELEMENTS;
                    attr.value.aclcapability.action_list.list = (int32_t*)list;
                    break;

                default:

                    SWSS_LOG_WARN("attr value: %s not supported",
                             sai_serialize_attr_value_type(md->attrvaluetype).c_str());

                    continue;
            }

            SWSS_LOG_DEBUG("getting %s for %s", md->attridname,
                    sai_serialize_object_id(id).c_str());

            callCount++;

            sai_status_t status = sai->get(ot, id, 1, &attr);

            if (status == SAI_STATUS_SUCCESS)
            {
                discovered[id][md->attridname] = sai_serialize_attr_value(*md, attr);

                SWSS_LOG_DEBUG("result on %s: %s: %s",
                        sai_serialize_object_id(id).c_str(),
                        md->attridname,
                        discovered[id][md->attridname].c_str());
            }
            else
            {
                if (gOptions.logWarnings)
                {
                    SWSS_LOG_WARN("%s: %s", md->attridname, sai_serialize_status(status).c_str());
                }
            }
        }
    }

    return callCount;
}