Skip to content

Commit

Permalink
[code sync] Merge code from sonic-net/sonic-sairedis:202411 to 202412 (
Browse files Browse the repository at this point in the history
…#24)

```<br>* f83634d - (HEAD -> 202412) Merge branch '202411' of https://github.com/sonic-net/sonic-sairedis into 202412 (2025-02-27) [Sonic Automation]
* 8c17d4b - (origin/202411) Revert "Do not enter vendor SAI critical section for counter polling/clearing operations (#1450)" (#1541) (2025-02-27) [mssonicbld]
* 3df03e1 - Optimize counter polling interval by making it more accurate (#1457) (#1534) (2025-02-26) [Stephen Sun]
* d884ff9 - [syncd] Move logSet logGet under mutex to prevent race condition (#1520) (#1538) (2025-02-20) [Kamil Cudnik]
* ec8b3c3 - Fix pipeline errors related to rsyslogd and libswsscommon installation (#1535) (2025-02-19) [mssonicbld]
* 6b263b8 - [FC] Support Policer Counter (#1533) (2025-02-19) [mssonicbld]
* e53489e - [syncd] Update log level for bulk api (#1532) (2025-02-18) [Jianyue Wu]
* 7ae00e5 - Define bulk chunk size and bulk chunk size per counter ID (#1528) (2025-02-11) [mssonicbld]
* f35e743 - [nvidia] Skip SAI discovery on ports (#1524) (2025-02-07) [mssonicbld]
* bf049ed - Use sonictest pool instead of sonic-common and fix arm64 issue. (#1516) (2025-02-05) [mssonicbld]
* ffe371d - [syncd] Support bulk set in INIT_VIEW mode (#1517) (2025-02-05) [mssonicbld]<br>```
  • Loading branch information
mssonicbld authored Feb 27, 2025
1 parent 9fbe10d commit 5ee5610
Show file tree
Hide file tree
Showing 7 changed files with 694 additions and 49 deletions.
2 changes: 2 additions & 0 deletions lib/RedisRemoteSaiInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,8 @@ sai_status_t RedisRemoteSaiInterface::notifyCounterGroupOperations(
std::string key((const char*)flexCounterGroupParam->counter_group_name.list, flexCounterGroupParam->counter_group_name.count);

emplaceStrings(POLL_INTERVAL_FIELD, flexCounterGroupParam->poll_interval, entries);
emplaceStrings(BULK_CHUNK_SIZE_FIELD, flexCounterGroupParam->bulk_chunk_size, entries);
emplaceStrings(BULK_CHUNK_SIZE_PER_PREFIX_FIELD, flexCounterGroupParam->bulk_chunk_size_per_prefix, entries);
emplaceStrings(STATS_MODE_FIELD, flexCounterGroupParam->stats_mode, entries);
emplaceStrings(flexCounterGroupParam->plugin_name, flexCounterGroupParam->plugins, entries);
emplaceStrings(FLEX_COUNTER_STATUS_FIELD, flexCounterGroupParam->operation, entries);
Expand Down
468 changes: 423 additions & 45 deletions syncd/FlexCounter.cpp

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions syncd/FlexCounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@ namespace syncd
class BaseCounterContext
{
public:
BaseCounterContext(const std::string &name);
BaseCounterContext(const std::string &name, const std::string &instance);
void addPlugins(
_In_ const std::vector<std::string>& shaStrings);

void setNoDoubleCheckBulkCapability(
_In_ bool);

virtual void setBulkChunkSize(
_In_ uint32_t bulkChunkSize);

virtual void setBulkChunkSizePerPrefix(
_In_ const std::string& bulkChunkSizePerPrefix);

bool hasPlugin() const {return !m_plugins.empty();}

void removePlugins() {m_plugins.clear();}
Expand All @@ -51,7 +57,9 @@ namespace syncd

protected:
std::string m_name;
std::string m_instanceId;
std::set<std::string> m_plugins;
std::string m_bulkChunkSizePerPrefix;

public:
bool always_check_supported_counters = false;
Expand All @@ -60,6 +68,7 @@ namespace syncd
bool double_confirm_supported_counters = false;
bool no_double_check_bulk_capability = false;
bool dont_clear_support_counter = false;
uint32_t default_bulk_chunk_size;
};
class FlexCounter
{
Expand Down Expand Up @@ -119,7 +128,8 @@ namespace syncd
_In_ const std::string &name);

std::shared_ptr<BaseCounterContext> createCounterContext(
_In_ const std::string &name);
_In_ const std::string &name,
_In_ const std::string &instance);

void removeCounterContext(
_In_ const std::string &name);
Expand Down
5 changes: 5 additions & 0 deletions syncd/VendorSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ sai_status_t VendorSai::getStats(
_In_ const sai_stat_id_t *counter_ids,
_Out_ uint64_t *counters)
{
MUTEX();
SWSS_LOG_ENTER();
VENDOR_CHECK_API_INITIALIZED();

Expand Down Expand Up @@ -350,6 +351,7 @@ sai_status_t VendorSai::getStatsExt(
_In_ sai_stats_mode_t mode,
_Out_ uint64_t *counters)
{
MUTEX();
SWSS_LOG_ENTER();
VENDOR_CHECK_API_INITIALIZED();

Expand All @@ -364,6 +366,7 @@ sai_status_t VendorSai::clearStats(
_In_ uint32_t number_of_counters,
_In_ const sai_stat_id_t *counter_ids)
{
MUTEX();
SWSS_LOG_ENTER();
VENDOR_CHECK_API_INITIALIZED();

Expand All @@ -383,6 +386,7 @@ sai_status_t VendorSai::bulkGetStats(
_Inout_ sai_status_t *object_statuses,
_Out_ uint64_t *counters)
{
MUTEX();
SWSS_LOG_ENTER();
VENDOR_CHECK_API_INITIALIZED();

Expand Down Expand Up @@ -410,6 +414,7 @@ sai_status_t VendorSai::bulkClearStats(
_In_ sai_stats_mode_t mode,
_Inout_ sai_status_t *object_statuses)
{
MUTEX();
SWSS_LOG_ENTER();
VENDOR_CHECK_API_INITIALIZED();

Expand Down
1 change: 1 addition & 0 deletions tests/aspell.en.pws
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ ecmp
ECMP
FDB
FDBs
FEC
FIXME
FlexCounter
gbsyncd
Expand Down
231 changes: 229 additions & 2 deletions unittest/syncd/TestFlexCounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ void testAddRemoveCounter(
const std::vector<std::string>& expectedValues,
VerifyStatsFunc verifyFunc,
bool autoRemoveDbEntry,
const std::string statsMode = STATS_MODE_READ)
const std::string statsMode = STATS_MODE_READ,
const std::string bulkChunkSize = "",
const std::string bulkChunkSizePerCounter = "",
bool bulkChunkSizeAfterPort = true,
const std::string pluginName = "",
bool immediatelyRemoveBulkChunkSizePerCounter = false)
{
SWSS_LOG_ENTER();

Expand All @@ -100,6 +105,20 @@ void testAddRemoveCounter(
values.emplace_back(POLL_INTERVAL_FIELD, "1000");
values.emplace_back(FLEX_COUNTER_STATUS_FIELD, "enable");
values.emplace_back(STATS_MODE_FIELD, statsMode);
std::vector<swss::FieldValueTuple> fcValues = values;
auto &bulkChunkSizeValues = bulkChunkSizeAfterPort ? fcValues : values;
if (!bulkChunkSize.empty())
{
bulkChunkSizeValues.emplace_back(BULK_CHUNK_SIZE_FIELD, bulkChunkSize);
}
if (!bulkChunkSizePerCounter.empty())
{
bulkChunkSizeValues.emplace_back(BULK_CHUNK_SIZE_PER_PREFIX_FIELD, bulkChunkSizePerCounter);
}
if (!pluginName.empty())
{
values.emplace_back(pluginName, "");
}
fc.addCounterPlugin(values);

values.clear();
Expand All @@ -109,6 +128,17 @@ void testAddRemoveCounter(
fc.addCounter(object_id, object_id, values);
}

if (bulkChunkSizeAfterPort)
{
fc.addCounterPlugin(bulkChunkSizeValues);
if (immediatelyRemoveBulkChunkSizePerCounter)
{
bulkChunkSizeValues.clear();
bulkChunkSizeValues.emplace_back(BULK_CHUNK_SIZE_PER_PREFIX_FIELD, "");
fc.addCounterPlugin(bulkChunkSizeValues);
}
}

EXPECT_EQ(fc.isEmpty(), false);

usleep(1000*1050);
Expand Down Expand Up @@ -761,6 +791,204 @@ TEST(FlexCounter, bulkCounter)
EXPECT_EQ(false, clearCalled);
}

TEST(FlexCounter, bulkChunksize)
{
/*
* Test logic
* 1. Generate counter values and store them whenever the bulk get stat is called after initialization
* 2. Convert stored counter values to string when the verify function is called
* and verify whether the database content aligns with the stored values
* 3. Verify whether values of all counter IDs of all objects have been generated
* 4. Verify whether the bulk chunk size is correct
*/
sai->mock_getStatsExt = [&](sai_object_type_t, sai_object_id_t, uint32_t number_of_counters, const sai_stat_id_t *, sai_stats_mode_t, uint64_t *counters) {
return SAI_STATUS_SUCCESS;
};
sai->mock_getStats = [&](sai_object_type_t, sai_object_id_t, uint32_t number_of_counters, const sai_stat_id_t *, uint64_t *counters) {
return SAI_STATUS_SUCCESS;
};
sai->mock_queryStatsCapability = [&](sai_object_id_t switch_id, sai_object_type_t object_type, sai_stat_capability_list_t *stats_capability) {
// For now, just return failure to make test simple, will write a singe test to cover querySupportedCounters
return SAI_STATUS_FAILURE;
};

// Map of number from {oid: {counter_id: counter value}}
std::map<sai_object_id_t, std::map<sai_stat_id_t, sai_uint64_t>> counterValuesMap;
// Map of string from {oid: {counter_id: counter value}}
std::map<std::string, std::map<std::string, std::string>> expectedValuesMap;

std::set<std::string> allCounterIds = {
"SAI_PORT_STAT_IF_IN_OCTETS",
"SAI_PORT_STAT_IF_IN_UCAST_PKTS",
"SAI_PORT_STAT_IF_OUT_QLEN",
"SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES",
"SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES"
};
std::set<std::string> allObjectIds;
auto generateExpectedValues = [&]()
{
std::set<sai_uint64_t> allCounterValueSet;
for (const auto &oidRef : counterValuesMap)
{
auto &expected = expectedValuesMap[toOid(oidRef.first)];
std::set<std::string> localAllCounterIds = allCounterIds;
for (const auto &counters : oidRef.second)
{
// No duplicate counter value
EXPECT_EQ(allCounterValueSet.find(counters.second), allCounterValueSet.end());
allCounterValueSet.insert(counters.second);

// For each object, no unexpected counter ID
const auto &counterId = sai_serialize_port_stat((sai_port_stat_t)counters.first);
EXPECT_TRUE(localAllCounterIds.find(counterId) != localAllCounterIds.end());
localAllCounterIds.erase(counterId);

expected[counterId] = to_string(counters.second);
}

// For each object, all expected counters are generated
EXPECT_TRUE(localAllCounterIds.empty());
}
};

std::vector<std::vector<sai_stat_id_t>> counterRecord;
std::vector<std::vector<uint64_t>> valueRecord;
sai_uint64_t counterSeed = 0;
uint32_t unifiedBulkChunkSize = 0;
sai->mock_bulkGetStats = [&](sai_object_id_t,
sai_object_type_t,
uint32_t object_count,
const sai_object_key_t *object_keys,
uint32_t number_of_counters,
const sai_stat_id_t *counter_ids,
sai_stats_mode_t mode,
sai_status_t *object_status,
uint64_t *counters)
{
EXPECT_TRUE(mode == SAI_STATS_MODE_BULK_READ);
std::vector<sai_stat_id_t> record;
std::vector<uint64_t> value;
if (number_of_counters >= 5 && object_count == 1)
{
allObjectIds.insert(toOid(object_keys[0].key.object_id));
// This call is to check whether bulk counter polling is supported during initialization
return SAI_STATUS_SUCCESS;
}
for (uint32_t i = 0; i < object_count; i++)
{
object_status[i] = SAI_STATUS_SUCCESS;
auto &counterMap = counterValuesMap[object_keys[i].key.object_id];
for (uint32_t j = 0; j < number_of_counters; j++)
{
const auto &searchRef = counterMap.find(counter_ids[j]);
if (searchRef == counterMap.end())
{
counterMap[counter_ids[j]] = ++counterSeed;
}
counters[i * number_of_counters + j] = counterMap[counter_ids[j]];
record.emplace_back(counter_ids[j]);
value.emplace_back(counterSeed);
if (unifiedBulkChunkSize > 0)
{
if (object_count != unifiedBulkChunkSize)
{
EXPECT_EQ(object_count, unifiedBulkChunkSize);
}
continue;
}
switch (counter_ids[j])
{
case SAI_PORT_STAT_IF_IN_OCTETS:
case SAI_PORT_STAT_IF_IN_UCAST_PKTS:
// default chunk size 2, object number 6, object count 6 / 2 = 3
EXPECT_EQ(object_count, 3);
break;
case SAI_PORT_STAT_IF_OUT_QLEN:
// queue length chunk size 0, object number 6, object count 6
EXPECT_EQ(object_count, 6);
break;
case SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES:
case SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES:
// FEC chunk size 2, object number 6, object count 6 / 3 = 2
EXPECT_EQ(object_count, 2);
default:
break;
}
}
}
return SAI_STATUS_SUCCESS;
};

auto counterVerifyFunc = [&] (swss::Table &countersTable, const std::string& key, const std::vector<std::string>& counterIdNames, const std::vector<std::string>&)
{
std::string value;
if (expectedValuesMap.empty())
{
generateExpectedValues();
}
auto const &searchRef = expectedValuesMap.find(key);
ASSERT_TRUE(searchRef != expectedValuesMap.end());
auto &oidCounters = searchRef->second;

for (auto const &counter : counterIdNames)
{
countersTable.hget(key, counter, value);
EXPECT_EQ(value, oidCounters[counter]);
oidCounters.erase(counter);
}

EXPECT_TRUE(oidCounters.empty());
expectedValuesMap.erase(searchRef);

allObjectIds.erase(key);
};

testAddRemoveCounter(
6,
SAI_OBJECT_TYPE_PORT,
PORT_COUNTER_ID_LIST,
{"SAI_PORT_STAT_IF_IN_OCTETS", "SAI_PORT_STAT_IF_IN_UCAST_PKTS", "SAI_PORT_STAT_IF_OUT_QLEN", "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES", "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES"},
{},
counterVerifyFunc,
false,
STATS_MODE_READ,
"3",
"SAI_PORT_STAT_IF_OUT_QLEN:0;SAI_PORT_STAT_IF_IN_FEC:2");
EXPECT_TRUE(allObjectIds.empty());

testAddRemoveCounter(
6,
SAI_OBJECT_TYPE_PORT,
PORT_COUNTER_ID_LIST,
{"SAI_PORT_STAT_IF_IN_OCTETS", "SAI_PORT_STAT_IF_IN_UCAST_PKTS", "SAI_PORT_STAT_IF_OUT_QLEN", "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES", "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES"},
{},
counterVerifyFunc,
false,
STATS_MODE_READ,
"3",
"SAI_PORT_STAT_IF_OUT_QLEN:0;SAI_PORT_STAT_IF_IN_FEC:2",
false,
PORT_PLUGIN_FIELD);
EXPECT_TRUE(allObjectIds.empty());

unifiedBulkChunkSize = 3;
testAddRemoveCounter(
6,
SAI_OBJECT_TYPE_PORT,
PORT_COUNTER_ID_LIST,
{"SAI_PORT_STAT_IF_IN_OCTETS", "SAI_PORT_STAT_IF_IN_UCAST_PKTS", "SAI_PORT_STAT_IF_OUT_QLEN", "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES", "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES"},
{},
counterVerifyFunc,
false,
STATS_MODE_READ,
"3",
"SAI_PORT_STAT_IF_OUT_QLEN:0;SAI_PORT_STAT_IF_IN_FEC:2",
true,
"",
true);
EXPECT_TRUE(allObjectIds.empty());
}

TEST(FlexCounter, counterIdChange)
{
sai->mock_getStats = [&](sai_object_type_t, sai_object_id_t, uint32_t number_of_counters, const sai_stat_id_t *, uint64_t *counters) {
Expand Down Expand Up @@ -1152,4 +1380,3 @@ TEST(FlexCounter, noEniDashMeterCounter)
counterVerifyFunc,
false);
}

22 changes: 22 additions & 0 deletions unittest/syncd/TestVendorSai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,28 @@ TEST(VendorSai, bulkGetStats)
nullptr));
}

TEST(VendorSai, getStatsExt)
{
VendorSai sai;
sai.apiInitialize(0, &test_services);
ASSERT_EQ(SAI_STATUS_NOT_SUPPORTED, sai.getStatsExt(SAI_OBJECT_TYPE_NULL,
SAI_NULL_OBJECT_ID,
0,
nullptr,
SAI_STATS_MODE_READ,
nullptr));
}

TEST(VendorSai, clearStats)
{
VendorSai sai;
sai.apiInitialize(0, &test_services);
ASSERT_EQ(SAI_STATUS_NOT_SUPPORTED, sai.clearStats(SAI_OBJECT_TYPE_NULL,
SAI_NULL_OBJECT_ID,
0,
nullptr));
}

sai_object_id_t create_port(
_In_ VendorSai& sai,
_In_ sai_object_id_t switch_id)
Expand Down

0 comments on commit 5ee5610

Please sign in to comment.