From d29760f934eb6e0cb623b2fb94520b10ef410fde Mon Sep 17 00:00:00 2001 From: Danny Allen Date: Mon, 28 Oct 2019 11:52:50 -0700 Subject: [PATCH] [sai_redis_interface_query] Add sairedis support for sai_object_type_get_availability (#528) * Add sai_object_type_get_availability to libsairedis * Add handler for sai_object_type_get_availability to syncd * Add sai_object_type_get_availability implementation to virtual switch Signed-off-by: Danny Allen --- lib/inc/sairedis.h | 3 + lib/src/sai_redis_interfacequery.cpp | 117 ++++++++++++++++++ syncd/syncd.cpp | 55 ++++++++ tests/brcm.pl | 8 ++ .../query_object_type_get_availability.rec | 13 ++ vslib/src/sai_vs_interfacequery.cpp | 19 +++ 6 files changed, 215 insertions(+) create mode 100644 tests/brcm/query_object_type_get_availability.rec diff --git a/lib/inc/sairedis.h b/lib/inc/sairedis.h index 369fe0121a0e..a971a3e61d56 100644 --- a/lib/inc/sairedis.h +++ b/lib/inc/sairedis.h @@ -11,8 +11,11 @@ extern "C" { #define ASIC_STATE_TABLE "ASIC_STATE" #define TEMP_PREFIX "TEMP_" +// Messages for processing queries from libsairedis to syncd const std::string attrEnumValuesCapabilityQuery("attr_enum_values_capability_query"); const std::string attrEnumValuesCapabilityResponse("attr_enum_values_capability_response"); +const std::string objectTypeGetAvailabilityQuery("object_type_get_availability_query"); +const std::string objectTypeGetAvailabilityResponse("object_type_get_availability_response"); typedef enum _sai_redis_notify_syncd_t { diff --git a/lib/src/sai_redis_interfacequery.cpp b/lib/src/sai_redis_interfacequery.cpp index 1647ac0f18b8..04407bc61ab8 100644 --- a/lib/src/sai_redis_interfacequery.cpp +++ b/lib/src/sai_redis_interfacequery.cpp @@ -2,6 +2,7 @@ #include "sairedis.h" #include "meta/sai_serialize.h" +#include "meta/saiattributelist.h" #include "swss/selectableevent.h" #include @@ -410,3 +411,119 @@ sai_status_t sai_query_attribute_enum_values_capability( SWSS_LOG_ERROR("Failed to receive a response from syncd"); return SAI_STATUS_FAILURE; } + +sai_status_t sai_object_type_get_availability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list, + _Out_ uint64_t *count) +{ + 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); + std::vector query_arguments = SaiAttributeList::serialize_attr_list( + object_type, + attr_count, + attr_list, + false); + + SWSS_LOG_DEBUG( + "Query arguments: switch: %s, object type: %s, attributes: %s", + switch_id_str.c_str(), + object_type_str.c_str(), + joinFieldValues(query_arguments).c_str() + ); + + // Syncd will pop this argument off before trying to deserialize the attribute list + query_arguments.push_back(swss::FieldValueTuple("OBJECT_TYPE", object_type_str)); + + if (g_record) + { + recordLine("q|object_type_get_availability|" + 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, objectTypeGetAvailabilityQuery); + + 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 != objectTypeGetAvailabilityResponse) + { + continue; + } + + sai_status_t status; + sai_deserialize_status(status_str, status); + + if (status == SAI_STATUS_SUCCESS) + { + const std::vector &values = kfvFieldsValues(kco); + + if (values.size() != 1) + { + if (g_record) + { + recordLine("Q|object_type_get_availability|SAI_STATUS_FAILURE"); + } + + SWSS_LOG_ERROR("Invalid response from syncd: expected 1 value, received %d", values.size()); + return SAI_STATUS_FAILURE; + } + + const std::string &availability_str = fvValue(values[0]); + *count = std::stol(availability_str); + + SWSS_LOG_DEBUG("Received payload: count = %lu", *count); + + if (g_record) + { + recordLine("Q|object_type_get_availability|" + status_str + "|" + joinFieldValues(values)); + } + } + else + { + if (g_record) + { + recordLine("Q|object_type_get_availability|" + status_str); + } + } + + SWSS_LOG_DEBUG("Status: %s", status_str.c_str()); + return status; + } + } + + if (g_record) + { + recordLine("Q|object_type_get_availability|SAI_STATUS_FAILURE"); + } + + SWSS_LOG_ERROR("Failed to receive a response from syncd"); + return SAI_STATUS_FAILURE; +} diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 752e113ee84f..1892d950bf65 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -2933,6 +2933,57 @@ sai_status_t processAttrEnumValuesCapabilityQuery( return status; } +sai_status_t processObjectTypeGetAvailabilityQuery( + _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); + + std::vector values = kfvFieldsValues(kco); + + // Syncd needs to pop the object type off the end of the list in order to + // retrieve the attribute list + sai_object_type_t object_type; + sai_deserialize_object_type(fvValue(values.back()), object_type); + values.pop_back(); + + SaiAttributeList attr_list(object_type, values, false); + + sai_attribute_t *sai_attr_list = attr_list.get_attr_list(); + uint32_t attr_count = attr_list.get_attr_count(); + + translate_vid_to_rid_list(object_type, attr_count, sai_attr_list); + + uint64_t count; + sai_status_t status = sai_object_type_get_availability( + switch_rid, + object_type, + attr_count, + sai_attr_list, + &count); + + std::vector response_payload; + + if (status == SAI_STATUS_SUCCESS) + { + response_payload = + { + swss::FieldValueTuple("OBJECT_COUNT", std::to_string(count)) + }; + + SWSS_LOG_DEBUG("Sending response: count = %lu", count); + } + + getResponse->set(sai_serialize_status(status), response_payload, objectTypeGetAvailabilityResponse); + return status; +} + sai_status_t processEvent( _In_ swss::ConsumerTable &consumer) { @@ -3029,6 +3080,10 @@ sai_status_t processEvent( { return processAttrEnumValuesCapabilityQuery(kco); } + else if (op == objectTypeGetAvailabilityQuery) + { + return processObjectTypeGetAvailabilityQuery(kco); + } else { SWSS_LOG_THROW("api '%s' is not implemented", op.c_str()); diff --git a/tests/brcm.pl b/tests/brcm.pl index 12de57e3d467..ea56deab14fd 100755 --- a/tests/brcm.pl +++ b/tests/brcm.pl @@ -525,6 +525,13 @@ sub test_brcm_query_attr_enum_values_capability play "query_attr_enum_values_capability.rec"; } +sub test_brcm_query_object_type_get_availability +{ + fresh_start; + + play "query_object_type_get_availability.rec"; +} + # RUN TESTS test_brcm_warm_boot_port_remove; @@ -576,5 +583,6 @@ sub test_brcm_query_attr_enum_values_capability 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; +test_brcm_query_object_type_get_availability; kill_syncd; diff --git a/tests/brcm/query_object_type_get_availability.rec b/tests/brcm/query_object_type_get_availability.rec new file mode 100644 index 000000000000..cf8c7ebc8cf6 --- /dev/null +++ b/tests/brcm/query_object_type_get_availability.rec @@ -0,0 +1,13 @@ +2019-10-25.17:56:23.794105|a|INIT_VIEW +2019-10-25.17:56:23.795120|A|SAI_STATUS_SUCCESS +2019-10-25.17:56:23.795362|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.17:56:24.786816|q|object_type_get_availability|oid:0x21000000000000|SAI_DEBUG_COUNTER_ATTR_TYPE=SAI_DEBUG_COUNTER_TYPE_SWITCH_IN_DROP_REASONS|OBJECT_TYPE=SAI_OBJECT_TYPE_DEBUG_COUNTER +2019-10-25.17:56:24.789781|Q|object_type_get_availability|SAI_STATUS_SUCCESS|OBJECT_COUNT=3 +2019-10-25.17:56:24.792839|q|object_type_get_availability|oid:0x21000000000000|SAI_DEBUG_COUNTER_ATTR_TYPE=SAI_DEBUG_COUNTER_TYPE_PORT_OUT_DROP_REASONS|OBJECT_TYPE=SAI_OBJECT_TYPE_DEBUG_COUNTER +2019-10-25.17:56:24.794665|Q|object_type_get_availability|SAI_STATUS_SUCCESS|OBJECT_COUNT=3 +2019-10-25.17:56:24.795255|q|object_type_get_availability|oid:0x21000000000000|SAI_DEBUG_COUNTER_ATTR_TYPE=SAI_DEBUG_COUNTER_TYPE_SWITCH_OUT_DROP_REASONS|OBJECT_TYPE=SAI_OBJECT_TYPE_DEBUG_COUNTER +2019-10-25.17:56:24.796390|Q|object_type_get_availability|SAI_STATUS_SUCCESS|OBJECT_COUNT=3 +2019-10-25.17:56:24.796704|q|object_type_get_availability|oid:0x21000000000000|SAI_DEBUG_COUNTER_ATTR_TYPE=SAI_DEBUG_COUNTER_TYPE_PORT_IN_DROP_REASONS|OBJECT_TYPE=SAI_OBJECT_TYPE_DEBUG_COUNTER +2019-10-25.17:56:24.797838|Q|object_type_get_availability|SAI_STATUS_SUCCESS|OBJECT_COUNT=3 +2019-10-25.17:56:24.807699|a|APPLY_VIEW +2019-10-25.17:56:24.808521|A|SAI_STATUS_SUCCESS diff --git a/vslib/src/sai_vs_interfacequery.cpp b/vslib/src/sai_vs_interfacequery.cpp index 2d1a0c30c339..eb3b0968dcf6 100644 --- a/vslib/src/sai_vs_interfacequery.cpp +++ b/vslib/src/sai_vs_interfacequery.cpp @@ -963,3 +963,22 @@ sai_status_t sai_query_attribute_enum_values_capability( return SAI_STATUS_NOT_SUPPORTED; } } + +sai_status_t sai_object_type_get_availability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list, + _Out_ uint64_t *count) +{ + 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) + { + *count = 3; + return SAI_STATUS_SUCCESS; + } + + return SAI_STATUS_NOT_SUPPORTED; +}