sai_status_t Meta::flushFdbEntries()

in meta/Meta.cpp [387:564]


sai_status_t Meta::flushFdbEntries(
        _In_ sai_object_id_t switch_id,
        _In_ uint32_t attr_count,
        _In_ const sai_attribute_t *attr_list)
{
    SWSS_LOG_ENTER();

    if (attr_count > MAX_LIST_COUNT)
    {
        SWSS_LOG_ERROR("create attribute count %u > max list count %u", attr_count, MAX_LIST_COUNT);

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (attr_count != 0 && attr_list == NULL)
    {
        SWSS_LOG_ERROR("attribute list is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    sai_object_type_t swot = objectTypeQuery(switch_id);

    if (swot != SAI_OBJECT_TYPE_SWITCH)
    {
        SWSS_LOG_ERROR("object type for switch_id %s is %s",
                sai_serialize_object_id(switch_id).c_str(),
                sai_serialize_object_type(swot).c_str());

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (!m_oids.objectReferenceExists(switch_id))
    {
        SWSS_LOG_ERROR("switch id %s doesn't exist",
                sai_serialize_object_id(switch_id).c_str());

        return SAI_STATUS_INVALID_PARAMETER;
    }

    // validate attributes
    // - attribute list can be empty
    // - validation is similar to "create" action but there is no
    //   post create step and no references are updated
    // - fdb entries are updated in fdb notification

    std::unordered_map<sai_attr_id_t, const sai_attribute_t*> attrs;

    SWSS_LOG_DEBUG("attr count = %u", attr_count);

    for (uint32_t idx = 0; idx < attr_count; ++idx)
    {
        const sai_attribute_t* attr = &attr_list[idx];

        auto mdp = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_FDB_FLUSH, attr->id);

        if (mdp == NULL)
        {
            SWSS_LOG_ERROR("unable to find attribute metadata SAI_OBJECT_TYPE_FDB_FLUSH:%d", attr->id);

            return SAI_STATUS_INVALID_PARAMETER;
        }

        const sai_attribute_value_t& value = attr->value;

        const sai_attr_metadata_t& md = *mdp;

        META_LOG_DEBUG(md, "(fdbflush)");

        if (attrs.find(attr->id) != attrs.end())
        {
            META_LOG_ERROR(md, "attribute id (%u) is defined on attr list multiple times", attr->id);

            return SAI_STATUS_INVALID_PARAMETER;
        }

        attrs[attr->id] = attr;

        // SAI metadata checks if
        // - attribute is create only
        // - is not conditional
        // - is not valid only

        switch (md.attrvaluetype)
        {
            case SAI_ATTR_VALUE_TYPE_INT32:

                if (md.isenum && !sai_metadata_is_allowed_enum_value(&md, value.s32))
                {
                    META_LOG_ERROR(md, "is enum, but value %d not found on allowed values list", value.s32);

                    return SAI_STATUS_INVALID_PARAMETER;
                }

                break;

            case SAI_ATTR_VALUE_TYPE_OBJECT_ID:

                {
                    sai_status_t status = meta_generic_validation_objlist(md, switch_id, 1, &value.oid);

                    CHECK_STATUS_SUCCESS(status)

                    break;
                }

            default:

                META_LOG_THROW(md, "value type %s is not supported yet, FIXME",
                        sai_serialize_attr_value_type(md.attrvaluetype).c_str());
        }
    }

    // there are no mandatory attributes
    // there are no conditional attributes

    auto status = m_implementation->flushFdbEntries(switch_id, attr_count, attr_list);

    if (status == SAI_STATUS_SUCCESS)
    {
        // use same logic as notification, so create notification event

        std::vector<int32_t> types;

        auto *et = sai_metadata_get_attr_by_id(SAI_FDB_FLUSH_ATTR_ENTRY_TYPE, attr_count, attr_list);

        if (et)
        {
            switch (et->value.s32)
            {
                case SAI_FDB_FLUSH_ENTRY_TYPE_DYNAMIC:
                    types.push_back(SAI_FDB_ENTRY_TYPE_DYNAMIC);
                    break;

                case SAI_FDB_FLUSH_ENTRY_TYPE_STATIC:
                    types.push_back(SAI_FDB_ENTRY_TYPE_STATIC);
                    break;

                default:
                    types.push_back(SAI_FDB_ENTRY_TYPE_DYNAMIC);
                    types.push_back(SAI_FDB_ENTRY_TYPE_STATIC);
                    break;
            }
        }
        else
        {
            // no type specified so we need to flush dynamic only

            types.push_back(SAI_FDB_ENTRY_TYPE_DYNAMIC);
        }

        for (auto type: types)
        {
            sai_fdb_event_notification_data_t data = {};

            auto *bv_id = sai_metadata_get_attr_by_id(SAI_FDB_FLUSH_ATTR_BV_ID, attr_count, attr_list);
            auto *bp_id = sai_metadata_get_attr_by_id(SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID, attr_count, attr_list);

            sai_attribute_t list[2];

            list[0].id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID;
            list[0].value.oid = bp_id ? bp_id->value.oid : SAI_NULL_OBJECT_ID;

            list[1].id = SAI_FDB_ENTRY_ATTR_TYPE;
            list[1].value.s32 = type;

            data.event_type = SAI_FDB_EVENT_FLUSHED;
            data.fdb_entry.switch_id = switch_id;
            data.fdb_entry.bv_id = (bv_id) ? bv_id->value.oid : SAI_NULL_OBJECT_ID;
            data.attr_count = 2;
            data.attr = list;

            meta_sai_on_fdb_flush_event_consolidated(data);
        }
    }

    return status;
}