Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sai_redis_interface_query] Add sairedis support for sai_query_attribute_enum_values_capability #525

Merged
merged 4 commits into from
Oct 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 += ',';
daall marked this conversation as resolved.
Show resolved Hide resolved
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;
daall marked this conversation as resolved.
Show resolved Hide resolved
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;
}
}