Skip to content

Commit

Permalink
Add libsai RedisInterface for link event damping.
Browse files Browse the repository at this point in the history
- This supports the link event damping config and algorithm set API.
- Sends the link event damping config from libsai to syncd main thread.

HLD: sonic-net/SONiC#1071
  • Loading branch information
Ashish Singh committed Dec 6, 2023
1 parent cd41369 commit bbd506e
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/ClientSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ sai_status_t ClientSai::set(
SWSS_LOG_ENTER();
REDIS_CHECK_API_INITIALIZED();

if (RedisRemoteSaiInterface::isRedisAttribute(objectType, attr))
if (RedisRemoteSaiInterface::isRedisAttribute(objectType, attr) ||
RedisRemoteSaiInterface::isRedisPortAttribute(objectType, attr))
{
SWSS_LOG_ERROR("sairedis extension attributes are not supported in CLIENT mode");

Expand Down
96 changes: 96 additions & 0 deletions lib/RedisRemoteSaiInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,83 @@ sai_status_t RedisRemoteSaiInterface::setRedisExtensionAttribute(
return SAI_STATUS_FAILURE;
}

sai_status_t RedisRemoteSaiInterface::setLinkEventDampingConfig(
_In_ sai_object_type_t objectType,
_In_ sai_object_id_t objectId,
_In_ const std::vector<swss::FieldValueTuple> &values)
{
SWSS_LOG_ENTER();

std::string key = sai_serialize_object_type(objectType) + ":" + sai_serialize_object_id(objectId);

m_communicationChannel->set(key, values, REDIS_ASIC_STATE_COMMAND_DAMPING_CONFIG_SET);

if (m_syncMode)
{
swss::KeyOpFieldsValuesTuple kco;
auto status = m_communicationChannel->wait(REDIS_ASIC_STATE_COMMAND_DAMPING_CONFIG_SET, kco);

m_recorder->recordGenericSetResponse(status);

return status;
}

return SAI_STATUS_SUCCESS;
}

sai_status_t RedisRemoteSaiInterface::setRedisPortExtensionAttribute(
_In_ sai_object_type_t objectType,
_In_ sai_object_id_t objectId,
_In_ const sai_attribute_t *attr)
{
SWSS_LOG_ENTER();

if (attr == nullptr)
{
SWSS_LOG_ERROR("attr pointer is null");

return SAI_STATUS_INVALID_PARAMETER;
}

std::string str_attr_id = sai_serialize_redis_port_attr_id(
static_cast<sai_redis_port_attr_t>(attr->id));

switch (attr->id)
{
case SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGORITHM:
{
std::string str_attr_value = sai_serialize_redis_link_event_damping_algorithm(
static_cast<sai_redis_link_event_damping_algorithm_t>(attr->value.s32));

return setLinkEventDampingConfig(
objectType, objectId, {swss::FieldValueTuple(str_attr_id, str_attr_value)});
}
case SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG:
{
sai_redis_link_event_damping_algo_aied_config_t *config =
(sai_redis_link_event_damping_algo_aied_config_t *)attr->value.ptr;

if (config == NULL)
{
SWSS_LOG_ERROR("invalid link damping config attr value NULL");

return SAI_STATUS_INVALID_PARAMETER;
}

std::string str_attr_value = sai_serialize_redis_link_event_damping_aied_config(*config);

return setLinkEventDampingConfig(
objectType, objectId, {swss::FieldValueTuple(str_attr_id, str_attr_value)});
}
default:
break;
}

SWSS_LOG_ERROR("unknown redis port extension attribute: %d", attr->id);

return SAI_STATUS_INVALID_PARAMETER;
}

sai_status_t RedisRemoteSaiInterface::set(
_In_ sai_object_type_t objectType,
_In_ sai_object_id_t objectId,
Expand All @@ -497,6 +574,11 @@ sai_status_t RedisRemoteSaiInterface::set(
return setRedisExtensionAttribute(objectType, objectId, attr);
}

if (RedisRemoteSaiInterface::isRedisPortAttribute(objectType, attr))
{
return setRedisPortExtensionAttribute(objectType, objectId, attr);
}

auto status = set(
objectType,
sai_serialize_object_id(objectId),
Expand Down Expand Up @@ -1664,6 +1746,20 @@ bool RedisRemoteSaiInterface::isRedisAttribute(
return true;
}

bool RedisRemoteSaiInterface::isRedisPortAttribute(
_In_ sai_object_id_t objectType,
_In_ const sai_attribute_t* attr)
{
SWSS_LOG_ENTER();

if ((objectType != SAI_OBJECT_TYPE_PORT) || (attr == nullptr) || (attr->id < SAI_PORT_ATTR_CUSTOM_RANGE_START))
{
return false;
}

return true;
}

void RedisRemoteSaiInterface::handleNotification(
_In_ const std::string &name,
_In_ const std::string &serializedNotification,
Expand Down
19 changes: 19 additions & 0 deletions lib/RedisRemoteSaiInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ namespace sairedis
_In_ sai_object_id_t switchId,
_In_ const sai_attribute_t* attr);

/**
* @brief Checks whether attribute is custom SAI_REDIS_PORT attribute.
*
* This function should only be used on port_api set function.
*/
static bool isRedisPortAttribute(
_In_ sai_object_id_t obejctType,
_In_ const sai_attribute_t* attr);

void setMeta(
_In_ std::weak_ptr<saimeta::Meta> meta);

Expand Down Expand Up @@ -343,12 +352,22 @@ namespace sairedis
_In_ sai_object_id_t objectId,
_In_ const sai_attribute_t *attr);

sai_status_t setRedisPortExtensionAttribute(
_In_ sai_object_type_t objectType,
_In_ sai_object_id_t objectId,
_In_ const sai_attribute_t *attr);

private:

sai_status_t sai_redis_notify_syncd(
_In_ sai_object_id_t switchId,
_In_ const sai_attribute_t *attr);

sai_status_t setLinkEventDampingConfig(
_In_ sai_object_type_t objectType,
_In_ sai_object_id_t objectId,
_In_ const std::vector<swss::FieldValueTuple> &values);

void clear_local_state();

sai_switch_notifications_t processNotification(
Expand Down
6 changes: 6 additions & 0 deletions lib/Sai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ sai_status_t Sai::set(

REDIS_CHECK_CONTEXT(objectId);

if (RedisRemoteSaiInterface::isRedisPortAttribute(objectType, attr))
{
// skip metadata if attribute is redis extension port attribute.
return context->m_redisSai->set(objectType, objectId, attr);
}

return context->m_meta->set(objectType, objectId, attr);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/sairediscommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
#define REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_QUERY "object_type_get_availability_query"
#define REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_RESPONSE "object_type_get_availability_response"

#define REDIS_ASIC_STATE_COMMAND_DAMPING_CONFIG_SET "link_event_damping_config_set"

/**
* @brief Redis virtual object id counter key name.
*
Expand Down
27 changes: 27 additions & 0 deletions syncd/Syncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,9 @@ sai_status_t Syncd::processSingleEvent(
if (op == REDIS_ASIC_STATE_COMMAND_OBJECT_TYPE_GET_AVAILABILITY_QUERY)
return processObjectTypeGetAvailabilityQuery(kco);

if (op == REDIS_ASIC_STATE_COMMAND_DAMPING_CONFIG_SET)
return processLinkEventDampingConfigSet(kco);

SWSS_LOG_THROW("event op '%s' is not implemented, FIXME", op.c_str());
}

Expand Down Expand Up @@ -563,6 +566,30 @@ sai_status_t Syncd::processObjectTypeGetAvailabilityQuery(
return status;
}

sai_status_t Syncd::processLinkEventDampingConfigSet(
_In_ const swss::KeyOpFieldsValuesTuple &kco)
{
SWSS_LOG_ENTER();

sendLinkEventDampingConfigResponse(SAI_STATUS_NOT_IMPLEMENTED);

return SAI_STATUS_NOT_IMPLEMENTED;
}

void Syncd::sendLinkEventDampingConfigResponse(
_In_ sai_status_t status)
{
SWSS_LOG_ENTER();

std::string strStatus = sai_serialize_status(status);

std::vector<swss::FieldValueTuple> entry;

SWSS_LOG_INFO("sending link event damping config response: %s", strStatus.c_str());

m_selectableChannel->set(strStatus, entry, REDIS_ASIC_STATE_COMMAND_DAMPING_CONFIG_SET);
}

sai_status_t Syncd::processFdbFlush(
_In_ const swss::KeyOpFieldsValuesTuple &kco)
{
Expand Down
6 changes: 6 additions & 0 deletions syncd/Syncd.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ namespace syncd
_In_ uint32_t attr_count,
_In_ sai_attribute_t *attr_list);

sai_status_t processLinkEventDampingConfigSet(
_In_ const swss::KeyOpFieldsValuesTuple &kco);

private: // process quad oid

sai_status_t processOidCreate(
Expand Down Expand Up @@ -347,6 +350,9 @@ namespace syncd
void sendNotifyResponse(
_In_ sai_status_t status);

void sendLinkEventDampingConfigResponse(
_In_ sai_status_t status);

private: // snoop get response oids

void snoopGetResponse(
Expand Down
68 changes: 68 additions & 0 deletions unittest/lib/TestClientServerSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,74 @@ TEST(ClientServerSai, logSet)
EXPECT_EQ(SAI_STATUS_SUCCESS, css->logSet(SAI_API_PORT, SAI_LOG_LEVEL_NOTICE));
}

TEST(ClientServerSai, VerifySaiRedisPortAttrNotSupportedInClientMode)
{
auto css = std::make_shared<ClientServerSai>();

// Initialize as sairedis client.
EXPECT_EQ(SAI_STATUS_SUCCESS, css->initialize(0, &test_client_services));

sai_attribute_t attr;
attr.id = SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGORITHM;
attr.value.s32 = SAI_LINK_EVENT_DAMPING_ALGORITHM_AIED;

EXPECT_EQ(SAI_STATUS_FAILURE, css->set(SAI_OBJECT_TYPE_PORT, SAI_NULL_OBJECT_ID, &attr));
}

TEST(ClientServerSai, SetLinkEventDampingAlgorithm)
{
auto css = std::make_shared<ClientServerSai>();

// Initialize as sairedis server.
EXPECT_EQ(SAI_STATUS_SUCCESS, css->initialize(0, &test_services));

sai_attribute_t attr;
attr.id = SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGORITHM;
attr.value.s32 = SAI_LINK_EVENT_DAMPING_ALGORITHM_AIED;

EXPECT_EQ(SAI_STATUS_SUCCESS, css->set(SAI_OBJECT_TYPE_PORT, SAI_NULL_OBJECT_ID, &attr));
}

TEST(ClientServerSai, SetLinkEventDampingConfig)
{
auto css = std::make_shared<ClientServerSai>();

// Initialize as sairedis server.
EXPECT_EQ(SAI_STATUS_SUCCESS, css->initialize(0, &test_services));

// Failure when config is NULL.
sai_attribute_t attr;
attr.id = SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG;
attr.value.ptr = nullptr;

EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, css->set(SAI_OBJECT_TYPE_PORT, SAI_NULL_OBJECT_ID, &attr));

sai_redis_link_event_damping_algo_aied_config_t config = {
.max_suppress_time = 5000,
.suppress_threshold = 1500,
.reuse_threshold = 1200,
.decay_half_life = 3000,
.flap_penalty = 1000};

attr.value.ptr = (void *) &config;

EXPECT_EQ(SAI_STATUS_SUCCESS, css->set(SAI_OBJECT_TYPE_PORT, SAI_NULL_OBJECT_ID, &attr));
}

TEST(ClientServerSai, SetInvalidSaiRedisPortAttribute)
{
auto css = std::make_shared<ClientServerSai>();

// Initialize as sairedis server.
EXPECT_EQ(SAI_STATUS_SUCCESS, css->initialize(0, &test_services));

sai_attribute_t attr;
// Set an id that is not supported yet.
attr.id = SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG + 100;

EXPECT_EQ(SAI_STATUS_INVALID_PARAMETER, css->set(SAI_OBJECT_TYPE_PORT, SAI_NULL_OBJECT_ID, &attr));
}

TEST(ClientServerSai, bulkGetClearStats)
{
auto css = std::make_shared<ClientServerSai>();
Expand Down

0 comments on commit bbd506e

Please sign in to comment.