static sai_status_t refresh_vlan_member_list(
        _In_ const sai_attr_metadata_t *meta,
        _In_ sai_object_id_t vlan_id,
        _In_ sai_object_id_t switch_id)
{
    SWSS_LOG_ENTER();

    auto &all_vlan_members = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_VLAN_MEMBER);

    auto m_member_list = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_VLAN, SAI_VLAN_ATTR_MEMBER_LIST);
    auto md_vlan_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_VLAN_MEMBER, SAI_VLAN_MEMBER_ATTR_VLAN_ID);
    //auto md_brportid = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_VLAN_MEMBER, SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID);

    std::vector<sai_object_id_t> vlan_member_list;

    /*
     * We want order as bridge port order (so port order)
     */

    sai_attribute_t attr;

    auto me = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_VLAN).at(sai_serialize_object_id(vlan_id));

    for (auto vm: all_vlan_members)
    {
        if (vm.second.at(md_vlan_id->attridname)->getAttr()->value.oid != vlan_id)
        {
            /*
             * Only interested in our vlan
             */

            continue;
        }

        // TODO we need order as bridge ports, but we need bridge id!

        {
            sai_object_id_t vlan_member_id;

            sai_deserialize_object_id(vm.first, vlan_member_id);

            vlan_member_list.push_back(vlan_member_id);
        }
    }

    uint32_t vlan_member_list_count = (uint32_t)vlan_member_list.size();

    SWSS_LOG_NOTICE("recalculated %s: %u", m_member_list->attridname, vlan_member_list_count);

    attr.id = SAI_VLAN_ATTR_MEMBER_LIST;
    attr.value.objlist.count = vlan_member_list_count;
    attr.value.objlist.list = vlan_member_list.data();

    return vs_generic_set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr);
}
Пример #2
0
void WatermarkOrch::init_pg_ids()
{
    SWSS_LOG_ENTER();
    std::vector<FieldValueTuple> values;
    Table pg_index_table(m_countersDb.get(), COUNTERS_PG_INDEX_MAP);
    pg_index_table.get("", values);
    for (auto fv: values)
    {
        sai_object_id_t id;
        sai_deserialize_object_id(fv.first, id);
        m_pg_ids.push_back(id);
    }
}
Пример #3
0
void WatermarkOrch::init_queue_ids()
{
    SWSS_LOG_ENTER();
    std::vector<FieldValueTuple> values;
    Table m_queue_type_table(m_countersDb.get(), COUNTERS_QUEUE_TYPE_MAP);
    m_queue_type_table.get("", values);
    for (auto fv: values)
    {
        sai_object_id_t id;
        sai_deserialize_object_id(fv.first, id);
        if (fv.second == "SAI_QUEUE_TYPE_UNICAST")
        {
            m_unicast_queue_ids.push_back(id);
        }
        else
        {
            m_multicast_queue_ids.push_back(id);
        }
    }
}
Пример #4
0
sai_status_t handle_generic(
        _In_ sai_object_type_t object_type,
        _In_ const std::string &str_object_id,
        _In_ sai_common_api_t api,
        _In_ uint32_t attr_count,
        _In_ sai_attribute_t *attr_list)
{
    SWSS_LOG_ENTER();

    sai_object_id_t local_id;
    sai_deserialize_object_id(str_object_id, local_id);

    SWSS_LOG_DEBUG("generic %s for %s:%s",
            sai_serialize_common_api(api).c_str(),
            sai_serialize_object_type(object_type).c_str(),
            str_object_id.c_str());

    auto info = sai_metadata_get_object_type_info(object_type);

    sai_object_meta_key_t meta_key;

    meta_key.objecttype = object_type;

    switch (api)
    {
        case SAI_COMMON_API_CREATE:

            {
                sai_object_id_t switch_id = sai_switch_id_query(local_id);

                if (switch_id == SAI_NULL_OBJECT_ID)
                {
                    SWSS_LOG_THROW("invalid switch_id translated from VID %s",
                            sai_serialize_object_id(local_id).c_str());
                }

                if (object_type == SAI_OBJECT_TYPE_SWITCH)
                {
                    update_notifications_pointers(attr_count, attr_list);

                    /*
                     * We are creating switch, in both cases local and redis
                     * switch id is deterministic and should be the same.
                     */
                }
                else
                {
                    /*
                     * When we creating switch, then switch_id parameter is
                     * ignored, but we can't convert it using vid to rid map,
                     * since rid don't exist yet, so skip translate for switch,
                     * but use translate for all other objects.
                     */

                     switch_id = translate_local_to_redis(switch_id);
                }

                sai_status_t status = info->create(&meta_key, switch_id, attr_count, attr_list);

                if (status == SAI_STATUS_SUCCESS)
                {
                    sai_object_id_t rid = meta_key.objectkey.key.object_id;

                    match_redis_with_rec(rid, local_id);

                    SWSS_LOG_INFO("saved VID %s to RID %s",
                            sai_serialize_object_id(local_id).c_str(),
                            sai_serialize_object_id(rid).c_str());
                }
                else
                {
                    SWSS_LOG_ERROR("failed to create %s",
                            sai_serialize_status(status).c_str());
                }

                return status;
            }

        case SAI_COMMON_API_REMOVE:

            {
                meta_key.objectkey.key.object_id = translate_local_to_redis(local_id);

                return info->remove(&meta_key);
            }

        case SAI_COMMON_API_SET:

            {
                if (object_type == SAI_OBJECT_TYPE_SWITCH)
                {
                    update_notifications_pointers(1, attr_list);
                }

                meta_key.objectkey.key.object_id = translate_local_to_redis(local_id);

                return info->set(&meta_key, attr_list);
            }

        case SAI_COMMON_API_GET:

            {
                meta_key.objectkey.key.object_id = translate_local_to_redis(local_id);

                return info->get(&meta_key, attr_count, attr_list);
            }

        default:
            SWSS_LOG_THROW("generic other apis not implemented");
    }
}
void channelOpSetReadOnlyAttribute(
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    SWSS_LOG_ENTER();

    for (const auto &v: values)
    {
        SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
    }

    if (values.size() != 1)
    {
        SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size());
        return;
    }

    const std::string &str_object_type = key.substr(0, key.find(":"));
    const std::string &str_object_id = key.substr(key.find(":") + 1);

    sai_object_type_t object_type;
    sai_deserialize_object_type(str_object_type, object_type);

    if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX)
    {
        SWSS_LOG_ERROR("invalid object type: %d", object_type);
        return;
    }

    auto info = sai_metadata_get_object_type_info(object_type);

    if (info->isnonobjectid)
    {
        SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str());
        return;
    }

    sai_object_id_t object_id;

    sai_deserialize_object_id(str_object_id, object_id);

    sai_object_type_t ot = sai_object_type_query(object_id);

    if (ot != object_type)
    {
        SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s",
                str_object_type.c_str(), sai_serialize_object_type(ot).c_str());
        return;
    }

    sai_object_id_t switch_id = sai_switch_id_query(object_id);

    if (switch_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str());
        return;
    }

    // oid is validated and we got switch id

    const std::string &str_attr_id = fvField(values.at(0));
    const std::string &str_attr_value = fvValue(values.at(0));

    auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str());

    if (meta == NULL)
    {
        SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str());
        return;
    }

    if (meta->objecttype != ot)
    {
        SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s",
                str_attr_id.c_str(), sai_serialize_object_type(ot).c_str());
        return;
    }

    // we got attr metadata

    sai_attribute_t attr;

    attr.id = meta->attrid;

    sai_deserialize_attr_value(str_attr_value, *meta, attr);

    SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str());

    sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid);

    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str());
        return;
    }

    sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } };

    status = info->set(&meta_key, &attr);

    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("failed to set %s to %s on %s",
                str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
    }
    else
    {
        SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s",
                str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
    }

    sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
}
void channelOpSetStats(
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    SWSS_LOG_ENTER();

    // NOTE: we need to find stats for specific object, later SAI already have
    // this feature and this search could be optimized here:
    // https://github.com/opencomputeproject/SAI/commit/acc83933ff21c68e8ef10c9826de45807fdc0438

    sai_object_id_t oid;

    sai_deserialize_object_id(key, oid);

    sai_object_type_t ot = sai_object_type_query(oid);

    if (ot == SAI_OBJECT_TYPE_NULL)
    {
        SWSS_LOG_ERROR("invalid object id: %s", key.c_str());
        return;
    }

    sai_object_id_t switch_id = sai_switch_id_query(oid);

    if (switch_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("unable to get switch_id from oid: %s", key.c_str());
        return;
    }

    /*
     * Check if object for statistics was created and exists on switch.
     */

    auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(ot);

    auto it = objectHash.find(key.c_str());

    if (it == objectHash.end())
    {
        SWSS_LOG_ERROR("object not found: %s", key.c_str());
        return;
    }

    /*
     * Check if object for statistics have statistic map created, if not
     * create empty map.
     */

    auto &countersMap = g_switch_state_map.at(switch_id)->countersMap;

    auto mapit = countersMap.find(key);

    if (mapit == countersMap.end())
        countersMap[key] = std::map<int,uint64_t>();

    /*
     * Find stats enum based on object type.  In new metadata we have enum on
     * object type, but here we need to find it manually enum is in format
     * "sai_" + object_type + "_stat_t"
     */

    std::string lower_ot = sai_serialize_object_type(ot).substr(16);  // 16 = skip "SAI_OBJECT_TYPE_"

    std::transform(lower_ot.begin(), lower_ot.end(), lower_ot.begin(), ::tolower);

    std::string stat_enum_name = "sai_" + lower_ot + "_stat_t";

    const sai_enum_metadata_t* statenum = NULL;

    for (size_t i = 0; i < sai_metadata_all_enums_count; ++i)
    {
        if (sai_metadata_all_enums[i]->name == stat_enum_name)
        {
            SWSS_LOG_INFO("found enum %s", stat_enum_name.c_str());
            // found
            statenum = sai_metadata_all_enums[i];
            break;
        }
    }

    if (statenum == NULL)
    {
        SWSS_LOG_ERROR("failed to find stat enum: %s", stat_enum_name.c_str());
        return;
    }

    for (auto v: values)
    {
        // value format: stat_enum_name:uint64

        auto name = fvField(v);

        uint64_t value;

        if (sscanf(fvValue(v).c_str(), "%lu", &value) != 1)
        {
            SWSS_LOG_ERROR("failed to deserialize %s as couner value uint64_t", fvValue(v).c_str());
        }

        // linear search

        int enumvalue = -1;

        for (size_t i = 0; i < statenum->valuescount; ++i)
        {
            if (statenum->valuesnames[i] == name)
            {
                enumvalue = statenum->values[i];
                break;
            }
        }

        if (enumvalue == -1)
        {
            SWSS_LOG_ERROR("failed to find enum value: %s", name.c_str());
            continue;
        }

        SWSS_LOG_DEBUG("writting %s = %lu on %s", name.c_str(), value, key.c_str());

        countersMap.at(key)[enumvalue] = value;
    }
}
void handleUnittestChannelOp(
        _In_ const std::string &op,
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    /*
     * Since we will access and modify DB we need to be under mutex.
     *
     * NOTE: since this unittest channel is handled in thread, then that means
     * there is a DELAY from producer and consumer thread in VS, so if user
     * will set value on the specific READ_ONLY value he should wait for some
     * time until that value will be propagated to virtual switch.
     */

    MUTEX();

    SWSS_LOG_ENTER();

    SWSS_LOG_NOTICE("read only SET: op = %s, key = %s", op.c_str(), key.c_str());

    if (op == SAI_VS_UNITTEST_ENABLE_UNITTESTS)
    {
        bool enable = (key == "true");

        meta_unittests_enable(enable);
    }
    else if (op == SAI_VS_UNITTEST_SET_RO_OP)
    {
        for (const auto &v: values)
        {
            SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
        }

        if (values.size() != 1)
        {
            SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size());
            return;
        }

        const std::string &str_object_type = key.substr(0, key.find(":"));
        const std::string &str_object_id = key.substr(key.find(":") + 1);

        sai_object_type_t object_type;
        sai_deserialize_object_type(str_object_type, object_type);

        if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_MAX)
        {
            SWSS_LOG_ERROR("invalid object type: %d", object_type);
            return;
        }

        auto info = sai_metadata_get_object_type_info(object_type);

        if (info->isnonobjectid)
        {
            SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str());
            return;
        }

        sai_object_id_t object_id;

        sai_deserialize_object_id(str_object_id, object_id);

        sai_object_type_t ot = sai_object_type_query(object_id);

        if (ot != object_type)
        {
            SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s",
                    str_object_type.c_str(), sai_serialize_object_type(ot).c_str());
            return;
        }

        sai_object_id_t switch_id = sai_switch_id_query(object_id);

        if (switch_id == SAI_NULL_OBJECT_ID)
        {
            SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str());
            return;
        }

        // oid is validated and we got switch id

        const std::string &str_attr_id = fvField(values.at(0));
        const std::string &str_attr_value = fvValue(values.at(0));

        auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str());

        if (meta == NULL)
        {
            SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str());
            return;
        }

        if (meta->objecttype != ot)
        {
            SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s",
                    str_attr_id.c_str(), sai_serialize_object_type(ot).c_str());
            return;
        }

        // we got attr metadata

        sai_attribute_t attr;

        attr.id = meta->attrid;

        sai_deserialize_attr_value(str_attr_value, *meta, attr);

        SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str());

        sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid);

        if (status != SAI_STATUS_SUCCESS)
        {
            SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str());
            return;
        }

        sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } };

        status = info->set(&meta_key, &attr);

        if (status != SAI_STATUS_SUCCESS)
        {
            SWSS_LOG_ERROR("failed to set %s to %s on %s",
                    str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
        }
        else
        {
            SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s",
                    str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
        }

        sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
    }
    else
    {
Пример #8
0
sai_status_t internal_vs_generic_get(
        _In_ sai_object_type_t object_type,
        _In_ const std::string &serialized_object_id,
        _In_ sai_object_id_t switch_id,
        _In_ uint32_t attr_count,
        _Out_ sai_attribute_t *attr_list)
{
    SWSS_LOG_ENTER();

    auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(object_type);

    auto it = objectHash.find(serialized_object_id);

    if (it == objectHash.end())
    {
        SWSS_LOG_ERROR("not found %s:%s",
                sai_serialize_object_type(object_type).c_str(),
                serialized_object_id.c_str());

        return SAI_STATUS_ITEM_NOT_FOUND;
    }

    /*
     * We need reference here since we can potentially update attr hash for RO
     * object.
     */

    AttrHash& attrHash = it->second;

    /*
     * Some of the list query maybe for length, so we can't do
     * normal serialize, maybe with count only.
     */

    sai_status_t final_status = SAI_STATUS_SUCCESS;

    for (uint32_t idx = 0; idx < attr_count; ++idx)
    {
        sai_attr_id_t id = attr_list[idx].id;

        auto meta = sai_metadata_get_attr_metadata(object_type, id);

        if (meta == NULL)
        {
            SWSS_LOG_ERROR("failed to find attribute %d for %s:%s", id,
                    sai_serialize_object_type(object_type).c_str(),
                    serialized_object_id.c_str());

            return SAI_STATUS_FAILURE;
        }

        sai_status_t status;

        if (HAS_FLAG_READ_ONLY(meta->flags))
        {
            /*
             * Read only attributes may require recalculation.
             * Metadata makes sure that non object id's can't have
             * read only attributes. So here is defenetly OID.
             */

            sai_object_id_t oid;
            sai_deserialize_object_id(serialized_object_id, oid);

            status = refresh_read_only(meta, oid, switch_id);

            if (status != SAI_STATUS_SUCCESS)
            {
                SWSS_LOG_ERROR("%s read only not implemented on %s",
                        meta->attridname,
                        serialized_object_id.c_str());

                return status;
            }
        }

        auto ait = attrHash.find(meta->attridname);

        if (ait == attrHash.end())
        {
            SWSS_LOG_ERROR("%s not implemented on %s",
                    meta->attridname,
                    serialized_object_id.c_str());

            return SAI_STATUS_NOT_IMPLEMENTED;
        }

        auto attr = ait->second->getAttr();

        status = transfer_attributes(object_type, 1, attr, &attr_list[idx], false);

        if (status == SAI_STATUS_BUFFER_OVERFLOW)
        {
            /*
             * This is considered partial success, since we get correct list
             * length.  Note that other items ARE processes on the list.
             */

            SWSS_LOG_NOTICE("BUFFER_OVERFLOW %s: %s",
                    serialized_object_id.c_str(),
                    meta->attridname);

            /*
             * We still continue processing other attributes for get as long as
             * we only will be getting buffer overflow error.
             */

            final_status = status;
            continue;
        }

        if (status != SAI_STATUS_SUCCESS)
        {
            // all other errors

            SWSS_LOG_ERROR("get failed %s: %s: %s",
                    serialized_object_id.c_str(),
                    meta->attridname,
                    sai_serialize_status(status).c_str());

            return status;
        }
    }

    return final_status;
}
static sai_status_t refresh_bridge_port_list(
        _In_ const sai_attr_metadata_t *meta,
        _In_ sai_object_id_t bridge_id,
        _In_ sai_object_id_t switch_id)
{
    SWSS_LOG_ENTER();

    /*
     * TODO possible issues with vxlan and lag.
     */

    auto &all_bridge_ports = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT);

    sai_attribute_t attr;

    auto m_port_list = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE, SAI_BRIDGE_ATTR_PORT_LIST);
    auto m_port_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID);
    auto m_bridge_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_BRIDGE_ID);

    /*
     * First get all port's that belong to this bridge id.
     */

    std::map<sai_object_id_t, AttrHash> bridge_port_list_on_bridge_id;

    for (const auto &bp: all_bridge_ports)
    {
        auto it = bp.second.find(m_bridge_id->attridname);

        if (it == bp.second.end())
        {
            continue;
        }

        if (bridge_id == it->second->getAttr()->value.oid)
        {
            /*
             * This bridge port belongs to currently processing bridge ID.
             */

            sai_object_id_t bridge_port;

            sai_deserialize_object_id(bp.first, bridge_port);

            bridge_port_list_on_bridge_id[bridge_port] = bp.second;
        }
    }

    /*
     * Now sort those bridge port id's by port id to be consistent.
     */

    std::vector<sai_object_id_t> bridge_port_list;

    for (const auto &p: port_list)
    {
        for (const auto &bp: bridge_port_list_on_bridge_id)
        {
            auto it = bp.second.find(m_port_id->attridname);

            if (it == bp.second.end())
            {
                SWSS_LOG_THROW("bridge port is missing %s, not supported yet, FIXME", m_port_id->attridname);
            }

            if (p == it->second->getAttr()->value.oid)
            {
                bridge_port_list.push_back(bp.first);
            }
        }
    }

    if (bridge_port_list_on_bridge_id.size() != bridge_port_list.size())
    {
        SWSS_LOG_THROW("filter by port id failed size on lists is different: %zu vs %zu",
                bridge_port_list_on_bridge_id.size(),
                bridge_port_list.size());
    }

    uint32_t bridge_port_list_count = (uint32_t)bridge_port_list.size();

    SWSS_LOG_NOTICE("recalculated %s: %u", m_port_list->attridname, bridge_port_list_count);

    attr.id = SAI_BRIDGE_ATTR_PORT_LIST;
    attr.value.objlist.count = bridge_port_list_count;
    attr.value.objlist.list = bridge_port_list.data();

    return vs_generic_set(SAI_OBJECT_TYPE_BRIDGE, bridge_id, &attr);
}