Skip to content

Commit

Permalink
[sai_redis_interface_query] Add sairedis support for sai_query_attrib…
Browse files Browse the repository at this point in the history
…ute_enum_values_capability (#525)

* [sai_redis_interface_query] Add sairedis support for sai_query_attribute_enum_values_capability
* Add sai_query_attribute_enum_values_capability to libsairedis
* Add handler for sai_query_attribute_enum_values_capability to syncd
* Add sai_query_attribute_enum_values_capability implementation to virtual switch

Signed-off-by: Danny Allen <daall@microsoft.com>
  • Loading branch information
daall authored and lguohan committed Oct 28, 2019
1 parent d9faa58 commit ff5306e
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/inc/sairedis.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ extern "C" {
#define ASIC_STATE_TABLE "ASIC_STATE"
#define TEMP_PREFIX "TEMP_"

const std::string attrEnumValuesCapabilityQuery("attr_enum_values_capability_query");
const std::string attrEnumValuesCapabilityResponse("attr_enum_values_capability_response");

typedef enum _sai_redis_notify_syncd_t
{
SAI_REDIS_NOTIFY_SYNCD_INIT_VIEW,
Expand Down
152 changes: 152 additions & 0 deletions lib/src/sai_redis_interfacequery.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "sai_redis.h"
#include "sairedis.h"

#include "meta/sai_serialize.h"

#include "swss/selectableevent.h"
#include <string.h>

Expand Down Expand Up @@ -258,3 +260,153 @@ sai_status_t sai_api_query(
return SAI_STATUS_INVALID_PARAMETER;
}
}

sai_status_t sai_query_attribute_enum_values_capability(
_In_ sai_object_id_t switch_id,
_In_ sai_object_type_t object_type,
_In_ sai_attr_id_t attr_id,
_Inout_ sai_s32_list_t *enum_values_capability)
{
MUTEX();

SWSS_LOG_ENTER();

const std::string switch_id_str = sai_serialize_object_id(switch_id);
const std::string object_type_str = sai_serialize_object_type(object_type);

auto meta = sai_metadata_get_attr_metadata(object_type, attr_id);
if (meta == NULL)
{
SWSS_LOG_ERROR("Failed to find attribute metadata: object type %s, attr id %d", object_type_str.c_str(), attr_id);
return SAI_STATUS_INVALID_PARAMETER;
}

const std::string attr_id_str = sai_serialize_attr_id(*meta);
const std::string list_size = std::to_string(enum_values_capability->count);

const std::vector<swss::FieldValueTuple> query_arguments =
{
swss::FieldValueTuple("OBJECT_TYPE", object_type_str),
swss::FieldValueTuple("ATTR_ID", attr_id_str),
swss::FieldValueTuple("LIST_SIZE", list_size)
};

SWSS_LOG_DEBUG(
"Query arguments: switch %s, object type: %s, attribute: %s, count: %s",
switch_id_str.c_str(),
object_type_str.c_str(),
attr_id_str.c_str(),
list_size.c_str()
);

if (g_record)
{
recordLine("q|attribute_enum_values_capability|" + switch_id_str + "|" + joinFieldValues(query_arguments));
}

// This query will not put any data into the ASIC view, just into the
// message queue
g_asicState->set(switch_id_str, query_arguments, attrEnumValuesCapabilityQuery);

swss::Select callback;
callback.addSelectable(g_redisGetConsumer.get());

while (true)
{
SWSS_LOG_DEBUG("Waiting for a response");

swss::Selectable *sel;

auto result = callback.select(&sel, GET_RESPONSE_TIMEOUT);

if (result == swss::Select::OBJECT)
{
swss::KeyOpFieldsValuesTuple kco;

g_redisGetConsumer->pop(kco);

const std::string &message_type = kfvOp(kco);
const std::string &status_str = kfvKey(kco);

SWSS_LOG_DEBUG("Received response: op = %s, key = %s", message_type.c_str(), status_str.c_str());

// Ignore messages that are not in response to our query
if (message_type != attrEnumValuesCapabilityResponse)
{
continue;
}

sai_status_t status;
sai_deserialize_status(status_str, status);

if (status == SAI_STATUS_SUCCESS)
{
const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues(kco);

if (values.size() != 2)
{
if (g_record)
{
recordLine("Q|attribute_enum_values_capability|SAI_STATUS_FAILURE");
}

SWSS_LOG_ERROR("Invalid response from syncd: expected 2 values, received %d", values.size());
return SAI_STATUS_FAILURE;
}

const std::string &capability_str = fvValue(values[0]);
const uint32_t num_capabilities = std::stoi(fvValue(values[1]));

SWSS_LOG_DEBUG("Received payload: capabilites = '%s', count = %d", capability_str.c_str(), num_capabilities);

enum_values_capability->count = num_capabilities;

size_t position = 0;
for (uint32_t i = 0; i < num_capabilities; i++)
{
size_t old_position = position;
position = capability_str.find(",", old_position);
std::string capability = capability_str.substr(old_position, position - old_position);
enum_values_capability->list[i] = std::stoi(capability);

// We have run out of values to add to our list
if (position == std::string::npos)
{
if (num_capabilities != i + 1)
{
SWSS_LOG_WARN("Query returned less attributes than expected: expected %d, recieved %d");
}

break;
}

// Skip the commas
position++;
}

if (g_record)
{
recordLine("Q|attribute_enum_values_capability|" + status_str + "|" + joinFieldValues(values));
}
}
else
{
if (g_record)
{
recordLine("Q|attribute_enum_values_capability|" + status_str);
}
}

SWSS_LOG_DEBUG("Status: %s", status_str.c_str());
return status;
}
}

if (g_record)
{
recordLine("Q|attribute_enum_values_capability|SAI_STATUS_FAILURE");
}

SWSS_LOG_ERROR("Failed to receive a response from syncd");
return SAI_STATUS_FAILURE;
}
5 changes: 5 additions & 0 deletions saiplayer/saiplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,11 @@ int replay(int argc, char **argv)
case 'g':
api = SAI_COMMON_API_GET;
break;
case 'q':
// TODO: implement SAI player support for query commands
continue;
case 'Q':
continue; // skip over query responses
case '#':
case 'n':
continue; // skip comment and notification
Expand Down
70 changes: 70 additions & 0 deletions syncd/syncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,72 @@ sai_status_t processFdbFlush(
return status;
}

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

const std::string &switch_str_id = kfvKey(kco);

sai_object_id_t switch_vid;
sai_deserialize_object_id(switch_str_id, switch_vid);

const sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid);

const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues(kco);

if (values.size() != 3)
{
SWSS_LOG_ERROR("Invalid input: expected 3 arguments, received %d", values.size());
getResponse->set(sai_serialize_status(SAI_STATUS_INVALID_PARAMETER), {}, attrEnumValuesCapabilityResponse);
return SAI_STATUS_INVALID_PARAMETER;
}

sai_object_type_t object_type;
sai_deserialize_object_type(fvValue(values[0]), object_type);

sai_attr_id_t attr_id;
sai_deserialize_attr_id(fvValue(values[1]), attr_id);

const uint32_t list_size = std::stoi(fvValue(values[2]));
std::vector<int32_t> enum_capabilities_list(list_size);

sai_s32_list_t enum_values_capability;
enum_values_capability.count = list_size;
enum_values_capability.list = enum_capabilities_list.data();

sai_status_t status = sai_query_attribute_enum_values_capability(switch_rid, object_type, attr_id, &enum_values_capability);

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

if (status == SAI_STATUS_SUCCESS)
{
std::string serialized_enum_capabilities;
for (uint32_t i = 0; i < enum_values_capability.count; i++)
{
// We will remove the leading comma before sending the response
serialized_enum_capabilities += ',';
serialized_enum_capabilities += std::to_string(enum_capabilities_list[i]);
}

if (!serialized_enum_capabilities.empty())
{
serialized_enum_capabilities = serialized_enum_capabilities.substr(1);
}

response_payload =
{
swss::FieldValueTuple("ENUM_CAPABILITIES", serialized_enum_capabilities),
swss::FieldValueTuple("ENUM_COUNT", std::to_string(enum_values_capability.count))
};

SWSS_LOG_DEBUG("Sending response: capabilities = '%s', count = %d", serialized_enum_capabilities.substr(1).c_str(), enum_values_capability.count);
}

getResponse->set(sai_serialize_status(status), response_payload, attrEnumValuesCapabilityResponse);
return status;
}

sai_status_t processEvent(
_In_ swss::ConsumerTable &consumer)
{
Expand Down Expand Up @@ -2959,6 +3025,10 @@ sai_status_t processEvent(
{
return processFdbFlush(kco);
}
else if (op == attrEnumValuesCapabilityQuery)
{
return processAttrEnumValuesCapabilityQuery(kco);
}
else
{
SWSS_LOG_THROW("api '%s' is not implemented", op.c_str());
Expand Down
8 changes: 8 additions & 0 deletions tests/brcm.pl
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,13 @@ sub test_brcm_warm_boot_port_create
request_warm_shutdown;
}

sub test_brcm_query_attr_enum_values_capability
{
fresh_start;

play "query_attr_enum_values_capability.rec";
}

# RUN TESTS

test_brcm_warm_boot_port_remove;
Expand Down Expand Up @@ -568,5 +575,6 @@ sub test_brcm_warm_boot_port_create
test_brcm_full_to_empty_no_queue_no_ipg;
test_brcm_full_to_empty_hostif_remove_segfault;
test_brcm_full_to_empty_no_queue_no_ipg_no_buffer_profile;
test_brcm_query_attr_enum_values_capability;

kill_syncd;
9 changes: 9 additions & 0 deletions tests/brcm/query_attr_enum_values_capability.rec
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
2019-10-25.04:21:31.884173|a|INIT_VIEW
2019-10-25.04:21:31.884636|A|SAI_STATUS_SUCCESS
2019-10-25.04:21:31.884882|c|SAI_OBJECT_TYPE_SWITCH:oid:0x21000000000000|SAI_SWITCH_ATTR_INIT_SWITCH=true|SAI_SWITCH_ATTR_SRC_MAC_ADDRESS=02:42:AC:11:00:02
2019-10-25.04:21:32.853334|q|attribute_enum_values_capability|oid:0x21000000000000|OBJECT_TYPE=SAI_OBJECT_TYPE_DEBUG_COUNTER|ATTR_ID=SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST|LIST_SIZE=100
2019-10-25.04:21:32.854651|Q|attribute_enum_values_capability|SAI_STATUS_SUCCESS|ENUM_CAPABILITIES=0,11,41|ENUM_COUNT=3
2019-10-25.04:21:32.854730|q|attribute_enum_values_capability|oid:0x21000000000000|OBJECT_TYPE=SAI_OBJECT_TYPE_DEBUG_COUNTER|ATTR_ID=SAI_DEBUG_COUNTER_ATTR_OUT_DROP_REASON_LIST|LIST_SIZE=100
2019-10-25.04:21:32.855398|Q|attribute_enum_values_capability|SAI_STATUS_SUCCESS|ENUM_CAPABILITIES=0,2|ENUM_COUNT=2
2019-10-25.04:21:32.862373|a|APPLY_VIEW
2019-10-25.04:21:32.863487|A|SAI_STATUS_SUCCESS
42 changes: 42 additions & 0 deletions vslib/src/sai_vs_interfacequery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,3 +921,45 @@ sai_status_t sai_api_query(
return SAI_STATUS_INVALID_PARAMETER;
}
}

sai_status_t sai_query_attribute_enum_values_capability(
_In_ sai_object_id_t switch_id,
_In_ sai_object_type_t object_type,
_In_ sai_attr_id_t attr_id,
_Inout_ sai_s32_list_t *enum_values_capability)
{
SWSS_LOG_ENTER();

// TODO: We should generate this metadata for the virtual switch rather than hard-coding it here.
if (object_type == SAI_OBJECT_TYPE_DEBUG_COUNTER && attr_id == SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST)
{
if (enum_values_capability->count < 3)
{
return SAI_STATUS_BUFFER_OVERFLOW;
}

enum_values_capability->count = 3;
enum_values_capability->list[0] = SAI_IN_DROP_REASON_L2_ANY;
enum_values_capability->list[1] = SAI_IN_DROP_REASON_L3_ANY;
enum_values_capability->list[2] = SAI_IN_DROP_REASON_ACL_ANY;

return SAI_STATUS_SUCCESS;
}
else if (object_type == SAI_OBJECT_TYPE_DEBUG_COUNTER && attr_id == SAI_DEBUG_COUNTER_ATTR_OUT_DROP_REASON_LIST)
{
if (enum_values_capability->count < 2)
{
return SAI_STATUS_BUFFER_OVERFLOW;
}

enum_values_capability->count = 2;
enum_values_capability->list[0] = SAI_OUT_DROP_REASON_L2_ANY;
enum_values_capability->list[1] = SAI_OUT_DROP_REASON_L3_ANY;

return SAI_STATUS_SUCCESS;
}
else
{
return SAI_STATUS_NOT_SUPPORTED;
}
}

0 comments on commit ff5306e

Please sign in to comment.