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;
}