diff --git a/meta/SaiSerialize.cpp b/meta/SaiSerialize.cpp index bd482c3e..ce7048c0 100644 --- a/meta/SaiSerialize.cpp +++ b/meta/SaiSerialize.cpp @@ -822,6 +822,46 @@ std::string sai_serialize_number( return std::to_string(number); } +// internal +static std::string sai_serialize_flags( + _In_ int32_t value, + _In_ const sai_enum_metadata_t* meta) +{ + SWSS_LOG_ENTER(); + + if (value == 0) + return meta->values[0] ? "0x0" : meta->valuesnames[0]; + + std::string s; + + s.reserve(1024); + + for (size_t i = 0; i < meta->valuescount; ++i) + { + if (value & meta->values[i]) + { + if (s.size()) + s.append("|"); + + s += meta->valuesnames[i]; + + value &= ~meta->values[i]; + } + } + + if (value) + { + SWSS_LOG_WARN("unrecognized flags: 0x%x in enum %s", value, meta->name); + + if (s.size()) + s.append("|"); + + s += sai_serialize_number(value, true); + } + + return s; +} + std::string sai_serialize_enum( _In_ const int32_t value, _In_ const sai_enum_metadata_t* meta) @@ -833,6 +873,11 @@ std::string sai_serialize_enum( return sai_serialize_number(value); } + if (meta->flagstype == SAI_ENUM_FLAGS_TYPE_STRICT) + { + return sai_serialize_flags(value, meta); + } + for (size_t i = 0; i < meta->valuescount; ++i) { if (meta->values[i] == value) @@ -3615,6 +3660,47 @@ void sai_deserialize_number( sai_deserialize_number(s, number, hex); } + +// internal +static void sai_deserialize_flags( + _In_ const std::string& s, + _In_ const sai_enum_metadata_t *meta, + _Out_ int32_t& value) +{ + SWSS_LOG_ENTER(); + + value = 0; + + const auto tokens = swss::tokenize(s, '|'); + + for (auto& v: tokens) + { + if (v[0] == '0') + { + uint32_t val; + sai_deserialize_number(v, val, true); + + value |= val; + continue; + } + + size_t i; + for (i = 0; i < meta->valuescount; ++i) + { + if (v == meta->valuesnames[i]) + { + value |= meta->values[i]; + break; + } + } + if (i == meta->valuescount) + { + // v is empty or doesn't match any enum + SWSS_LOG_WARN("%s in %s has invalid enum for %s", v.c_str(), s.c_str(), meta->name); + } + } +} + void sai_deserialize_enum( _In_ const std::string& s, _In_ const sai_enum_metadata_t *meta, @@ -3627,6 +3713,11 @@ void sai_deserialize_enum( return sai_deserialize_number(s, value); } + if (meta->flagstype == SAI_ENUM_FLAGS_TYPE_STRICT) + { + return sai_deserialize_flags(s, meta, value); + } + for (size_t i = 0; i < meta->valuescount; ++i) { if (strcmp(s.c_str(), meta->valuesnames[i]) == 0) diff --git a/unittest/meta/TestSaiSerialize.cpp b/unittest/meta/TestSaiSerialize.cpp index c16cede0..c16322d7 100644 --- a/unittest/meta/TestSaiSerialize.cpp +++ b/unittest/meta/TestSaiSerialize.cpp @@ -1488,7 +1488,7 @@ TEST(SaiSerialize, serialize_stat_capability_list) { SWSS_LOG_ENTER(); - extern const sai_enum_metadata_t sai_metadata_enum_sai_stats_mode_t; + auto meta = sai_metadata_get_object_type_info(SAI_OBJECT_TYPE_QUEUE); sai_stat_capability_list_t queue_stats_capability; sai_stat_capability_t stat_initializer; stat_initializer.stat_enum = 0; @@ -1501,13 +1501,13 @@ TEST(SaiSerialize, serialize_stat_capability_list) queue_stats_capability.list[1].stat_enum = SAI_QUEUE_STAT_PACKETS; queue_stats_capability.list[1].stat_modes = SAI_STATS_MODE_READ; - std::string capab_count = sai_serialize_stats_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, true); - std::string capab_str = sai_serialize_stats_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, false); + std::string capab_count = sai_serialize_stats_capability_list(queue_stats_capability, meta->statenum, true); + std::string capab_str = sai_serialize_stats_capability_list(queue_stats_capability, meta->statenum, false); std::string exp_count_str = "{\"count\":2,\"list\":null}"; EXPECT_EQ(capab_count, exp_count_str); - std::string exp_capab_str = "{\"count\":2,\"list\":[{\"stat_enum\":\"34\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]},{\"stat_enum\":\"0\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]}]}"; + std::string exp_capab_str = "{\"count\":2,\"list\":[{\"stat_enum\":\"SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]},{\"stat_enum\":\"SAI_QUEUE_STAT_PACKETS\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]}]}"; EXPECT_EQ(capab_str, exp_capab_str); std::vector vec_stat_enum; @@ -1557,7 +1557,8 @@ TEST(SaiSerialize, serialize_stat_st_capability_list) { SWSS_LOG_ENTER(); - extern const sai_enum_metadata_t sai_metadata_enum_sai_stats_mode_t; + auto meta = sai_metadata_get_object_type_info(SAI_OBJECT_TYPE_QUEUE); + sai_stat_st_capability_list_t queue_stats_capability; sai_stat_st_capability_t stat_initializer; stat_initializer.capability.stat_enum = 0; @@ -1574,13 +1575,13 @@ TEST(SaiSerialize, serialize_stat_st_capability_list) queue_stats_capability.list[1].capability.stat_modes = SAI_STATS_MODE_READ; queue_stats_capability.list[1].minimal_polling_interval = 200; - std::string capab_count = sai_serialize_stats_st_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, true); - std::string capab_str = sai_serialize_stats_st_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, false); + std::string capab_count = sai_serialize_stats_st_capability_list(queue_stats_capability, meta->statenum, true); + std::string capab_str = sai_serialize_stats_st_capability_list(queue_stats_capability, meta->statenum, false); std::string exp_count_str = "{\"count\":2,\"list\":null}"; EXPECT_EQ(capab_count, exp_count_str); - std::string exp_capab_str = "{\"count\":2,\"list\":[{\"minimal_polling_interval\":\"100\",\"stat_enum\":\"34\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]},{\"minimal_polling_interval\":\"200\",\"stat_enum\":\"0\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]}]}"; + std::string exp_capab_str = "{\"count\":2,\"list\":[{\"minimal_polling_interval\":\"100\",\"stat_enum\":\"SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]},{\"minimal_polling_interval\":\"200\",\"stat_enum\":\"SAI_QUEUE_STAT_PACKETS\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]}]}"; EXPECT_EQ(capab_str, exp_capab_str); std::vector vec_stat_enum; @@ -1853,3 +1854,110 @@ TEST(SaiSerialize, sai_deserialize_taps_list) sai_deserialize_taps_list(count_str, taps_list, true); EXPECT_EQ(taps_list.count, 5); } + +TEST(SaiSerialize, sai_serialize_enum) +{ + auto *emd = &sai_metadata_enum_sai_port_error_status_t; + + int flags = 0; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_PORT_ERROR_STATUS_CLEAR"); + + flags = SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT"); + + flags = SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT| SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE"); + + flags = SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT| SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE | 0x80000; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|0x80000"); + + flags = SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT| SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE | 0xe0000; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|0xe0000"); + + flags = SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT| 0x67100 | 0xff000000; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|" + "SAI_PORT_ERROR_STATUS_NO_RX_REACHABILITY|SAI_PORT_ERROR_STATUS_LLR_TX_FLUSH|0xff064000"); + + flags = 0xff000000; + EXPECT_EQ(sai_serialize_enum(flags, emd), "0xff000000"); + + emd = &sai_metadata_enum_sai_stats_mode_t; + + flags = 0; + + // has zero flag + if (emd->values[0] == 0) + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_STATS_MODE_NONE"); + else + EXPECT_EQ(sai_serialize_enum(flags, emd), "0x0"); + + flags = SAI_STATS_MODE_READ; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_STATS_MODE_READ"); + + flags = SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR"); + + flags = SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR|0xff00; + EXPECT_EQ(sai_serialize_enum(flags, emd), "SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR|0xff00"); + + flags = 0xf1230000; + EXPECT_EQ(sai_serialize_enum(flags, emd), "0xf1230000"); +} + +TEST(SaiDeserialize, sai_deserialize_enum) +{ + auto *emd = &sai_metadata_enum_sai_port_error_status_t; + + int32_t value; + sai_deserialize_enum("SAI_PORT_ERROR_STATUS_CLEAR", emd, value); + EXPECT_EQ(value, 0); + + sai_deserialize_enum("SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT", emd, value); + EXPECT_EQ(value, SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT); + + sai_deserialize_enum("SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE", emd, value); + EXPECT_EQ(value, SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT| SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE); + + sai_deserialize_enum("SAI_PORT_ERROR_STATUS_MAC_REMOTE_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|0x80000", emd, value); + EXPECT_EQ(value, SAI_PORT_ERROR_STATUS_MAC_REMOTE_FAULT| SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|0x80000); + + sai_deserialize_enum("SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|0xe0000", emd, value); + EXPECT_EQ(value, SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT| SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|0xe0000); + + sai_deserialize_enum("SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE|" + "SAI_PORT_ERROR_STATUS_NO_RX_REACHABILITY|SAI_PORT_ERROR_STATUS_LLR_TX_FLUSH|0xff064000", emd, value); + EXPECT_EQ(value, SAI_PORT_ERROR_STATUS_MAC_LOCAL_FAULT|SAI_PORT_ERROR_STATUS_DATA_UNIT_SIZE| + SAI_PORT_ERROR_STATUS_NO_RX_REACHABILITY|SAI_PORT_ERROR_STATUS_LLR_TX_FLUSH|0xff064000); + + sai_deserialize_enum("0xff000000", emd, value); + EXPECT_EQ(value, 0xff000000); + + emd = &sai_metadata_enum_sai_stats_mode_t; + + + // has zero flag + if (emd->values[0] == 0) + sai_deserialize_enum("SAI_STATS_MODE_NONE", emd, value); + else + sai_deserialize_enum("0x0", emd, value); + EXPECT_EQ(value, 0); + + sai_deserialize_enum("SAI_STATS_MODE_READ", emd, value); + EXPECT_EQ(value, SAI_STATS_MODE_READ); + + sai_deserialize_enum("SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR", emd, value); + EXPECT_EQ(value, SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR); + + sai_deserialize_enum("SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR|0xff00", emd, value); + EXPECT_EQ(value, SAI_STATS_MODE_READ|SAI_STATS_MODE_BULK_CLEAR|0xff00); + + sai_deserialize_enum("0xf1230000", emd, value); + EXPECT_EQ(value, 0xf1230000); + + sai_deserialize_enum("SAI_STATS_MODE_READ|", emd, value); + EXPECT_EQ(value, SAI_STATS_MODE_READ); + + // Not checking the syslog warning + sai_deserialize_enum("SAI_STATS_MODE_READ|SAI_STATS_MODE_WRITE", emd, value); + EXPECT_EQ(value, SAI_STATS_MODE_READ); +}