Skip to content
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
41 changes: 26 additions & 15 deletions syncd/FlexCounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "swss/redisapi.h"
#include "swss/tokenize.h"
#include "swss/dbconnector.h"

using namespace syncd;
using namespace std;
Expand Down Expand Up @@ -1762,9 +1763,11 @@ class PortPhyAttrContext : public AttrContext<sai_port_attr_t, PortPhyAttributeD
_In_ sai_object_type_t object_type,
_In_ sairedis::SaiInterface *vendor_sai,
_In_ sai_stats_mode_t &stats_mode,
_In_ const std::string &dbCounters):
_In_ const std::string &dbCounters,
_In_ bool isTcpConn):
Base(name, instance, object_type, vendor_sai, stats_mode),
m_dbCounters(dbCounters)
m_dbCounters(dbCounters),
m_isTcpConn(isTcpConn)
{
SWSS_LOG_ENTER();
}
Expand Down Expand Up @@ -1965,7 +1968,7 @@ class PortPhyAttrContext : public AttrContext<sai_port_attr_t, PortPhyAttributeD
SWSS_LOG_ENTER();

// Create dedicated PORT_PHY_ATTR table
swss::DBConnector db(m_dbCounters, 0);
swss::DBConnector db(m_dbCounters, 0, m_isTcpConn);
swss::RedisPipeline pipeline(&db);
swss::Table portPhyAttrTable(&pipeline, PORT_PHY_ATTR_TABLE, true);

Expand Down Expand Up @@ -2165,6 +2168,7 @@ class PortPhyAttrContext : public AttrContext<sai_port_attr_t, PortPhyAttributeD
};

std::string m_dbCounters;
bool m_isTcpConn;
std::map<sai_object_id_t, std::map<sai_port_attr_t, uint32_t>> m_portLaneCountMap;
// Map: [VID][attr_id][lane_number] -> metadata
std::map<sai_object_id_t, std::map<sai_port_attr_t, std::map<uint32_t, LaneMetadata>>> m_laneMetadata;
Expand Down Expand Up @@ -2192,9 +2196,11 @@ class PortPhySerdesAttrContext : public AttrContext<sai_port_serdes_attr_t, Port
_In_ sai_object_type_t object_type,
_In_ sairedis::SaiInterface *vendor_sai,
_In_ sai_stats_mode_t &stats_mode,
_In_ const std::string &dbCounters):
_In_ const std::string &dbCounters,
_In_ bool isTcpConn):
Base(name, instance, object_type, vendor_sai, stats_mode),
m_dbCounters(dbCounters)
m_dbCounters(dbCounters),
m_isTcpConn(isTcpConn)
{
SWSS_LOG_ENTER();
}
Expand Down Expand Up @@ -2224,7 +2230,7 @@ class PortPhySerdesAttrContext : public AttrContext<sai_port_serdes_attr_t, Port

try
{
swss::DBConnector db(m_dbCounters, 0);
swss::DBConnector db(m_dbCounters, 0, m_isTcpConn);
swss::Table portSerdesIdToPortIdTable(&db, "COUNTERS_PORT_SERDES_ID_TO_PORT_ID_MAP");

std::string port_serdes_vid_str = sai_serialize_object_id(port_serdes_vid);
Expand Down Expand Up @@ -2499,7 +2505,7 @@ class PortPhySerdesAttrContext : public AttrContext<sai_port_serdes_attr_t, Port
SWSS_LOG_ENTER();

// Collected port phy serdes attrs data will be written to PORT_PHY_ATTR_TABLE (shared with port phy attrs)
swss::DBConnector db(m_dbCounters, 0);
swss::DBConnector db(m_dbCounters, 0, m_isTcpConn);
swss::RedisPipeline pipeline(&db);
swss::Table portPhyAttrTable(&pipeline, PORT_PHY_ATTR_TABLE, true);

Expand Down Expand Up @@ -2605,6 +2611,7 @@ class PortPhySerdesAttrContext : public AttrContext<sai_port_serdes_attr_t, Port
static const std::unordered_map<sai_port_serdes_attr_t, std::string> m_attrAliases;

std::string m_dbCounters;
bool m_isTcpConn;
std::map<sai_object_id_t, PortIdInfo> m_portSerdesIdToPortIdMap;
std::map<sai_object_id_t, uint32_t> m_portSerdesIdToLaneCountMap;
std::map<sai_object_id_t, std::map<sai_port_serdes_attr_t, uint32_t>> m_portSerdesTapsCountMap;
Expand All @@ -2623,8 +2630,9 @@ class DashMeterCounterContext : public BaseCounterContext
_In_ const std::string &name,
_In_ const std::string &instance,
_In_ sairedis::SaiInterface *vendor_sai,
_In_ std::string dbCounters):
BaseCounterContext(name, instance), m_dbCounters(dbCounters), m_vendorSai(vendor_sai)
_In_ std::string dbCounters,
_In_ bool isTcpConn):
BaseCounterContext(name, instance), m_dbCounters(dbCounters), m_isTcpConn(isTcpConn), m_vendorSai(vendor_sai)
{
SWSS_LOG_ENTER();
}
Expand Down Expand Up @@ -2698,7 +2706,7 @@ class DashMeterCounterContext : public BaseCounterContext
return;
}
// delete all meter bucket stats for this object from counters DB
swss::DBConnector db(m_dbCounters, 0);
swss::DBConnector db(m_dbCounters, 0, m_isTcpConn);
swss::RedisPipeline pipeline(&db);
swss::Table countersTable(&pipeline, COUNTERS_TABLE, true);
for (const auto& object_key: it->second.object_keys) {
Expand Down Expand Up @@ -2993,6 +3001,7 @@ class DashMeterCounterContext : public BaseCounterContext
std::vector<sai_meter_bucket_entry_stat_t> m_supportedMeterCounters;
sai_object_type_t m_objectType = (sai_object_type_t) SAI_OBJECT_TYPE_METER_BUCKET_ENTRY;
std::string m_dbCounters;
bool m_isTcpConn;
sairedis::SaiInterface *m_vendorSai;
sai_stats_mode_t m_groupStatsMode = SAI_STATS_MODE_READ;
sai_object_id_t m_switchId = 0UL;
Expand All @@ -3018,6 +3027,8 @@ FlexCounter::FlexCounter(
m_enable = false;
m_isDiscarded = false;

m_isTcpConn = swss::SonicDBConfig::getDbSock(dbCounters).empty();

startFlexCounterThread();
}

Expand Down Expand Up @@ -3089,7 +3100,7 @@ void FlexCounter::removeDataFromCountersDB(
_In_ const std::string &ratePrefix)
{
SWSS_LOG_ENTER();
swss::DBConnector db(m_dbCounters, 0);
swss::DBConnector db(m_dbCounters, 0, m_isTcpConn);
swss::RedisPipeline pipeline(&db);
swss::Table countersTable(&pipeline, COUNTERS_TABLE, false);

Expand Down Expand Up @@ -3361,15 +3372,15 @@ std::shared_ptr<BaseCounterContext> FlexCounter::createCounterContext(
}
else if (context_name == COUNTER_TYPE_METER_BUCKET)
{
return std::make_shared<DashMeterCounterContext>(context_name, instance, m_vendorSai.get(), m_dbCounters);
return std::make_shared<DashMeterCounterContext>(context_name, instance, m_vendorSai.get(), m_dbCounters, m_isTcpConn);
}
else if (context_name == ATTR_TYPE_PORT_PHY_ATTR)
{
return std::make_shared<PortPhyAttrContext>(context_name, instance, SAI_OBJECT_TYPE_PORT, m_vendorSai.get(), m_statsMode, m_dbCounters);
return std::make_shared<PortPhyAttrContext>(context_name, instance, SAI_OBJECT_TYPE_PORT, m_vendorSai.get(), m_statsMode, m_dbCounters, m_isTcpConn);
}
else if (context_name == ATTR_TYPE_PORT_PHY_SERDES_ATTR)
{
return std::make_shared<PortPhySerdesAttrContext>(context_name, instance, SAI_OBJECT_TYPE_PORT_SERDES, m_vendorSai.get(), m_statsMode, m_dbCounters);
return std::make_shared<PortPhySerdesAttrContext>(context_name, instance, SAI_OBJECT_TYPE_PORT_SERDES, m_vendorSai.get(), m_statsMode, m_dbCounters, m_isTcpConn);
}
else if (context_name == ATTR_TYPE_QUEUE)
{
Expand Down Expand Up @@ -3492,7 +3503,7 @@ void FlexCounter::flexCounterThreadRunFunction()
{
SWSS_LOG_ENTER();

swss::DBConnector db(m_dbCounters, 0);
swss::DBConnector db(m_dbCounters, 0, m_isTcpConn);
swss::RedisPipeline pipeline(&db);
swss::Table countersTable(&pipeline, COUNTERS_TABLE, true);

Expand Down
2 changes: 2 additions & 0 deletions syncd/FlexCounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ namespace syncd

std::string m_dbCounters;

bool m_isTcpConn;

bool m_isDiscarded;

std::map<std::string, std::shared_ptr<BaseCounterContext>> m_counterContext;
Expand Down
114 changes: 111 additions & 3 deletions unittest/syncd/TestFlexCounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include "NumberOidIndexGenerator.h"
#include <string>
#include <chrono>
#include <fstream>
#include <gtest/gtest.h>
#include "swss/dbconnector.h"

using namespace saimeta;
using namespace sairedis;
Expand Down Expand Up @@ -1550,11 +1552,15 @@ TEST(FlexCounter, bulkChunksize)
// addCounterPlugin calls that set and then remove per-prefix
// chunk sizes, the polling thread can poll with per-prefix
// partitions that have fewer counters and different chunk
// sizes. Those polls should fall through to the per-counter
// switch below.
// sizes. After the merge-back, FlexCounter also re-probes
// bulk capability with single-object calls (object_count=1)
// that have all counters. Skip the assertion for both
// per-prefix polls and re-probe polls.
if (unifiedBulkChunkSize > 0)
{
if (object_count != unifiedBulkChunkSize && number_of_counters == allCounters.size())
if (object_count != unifiedBulkChunkSize
&& number_of_counters == allCounters.size()
&& object_count > 1)
{
EXPECT_EQ(object_count, unifiedBulkChunkSize);
}
Expand Down Expand Up @@ -2309,3 +2315,105 @@ TEST(FlexCounter, noEniDashMeterCounter)
counterVerifyFunc,
false);
}

class FlexCounterTcpFallback : public ::testing::Test
{
protected:
static constexpr const char *configPath = "/tmp/test_tcp_fallback_db_config.json";

void SetUp() override
{
const std::string configContent = R"({
"INSTANCES": {
"redis": {
"hostname": "127.0.0.1",
"port": 6379,
"unix_socket_path": ""
}
},
"DATABASES": {
"COUNTERS_DB": {
"id": 2,
"separator": ":",
"instance": "redis"
}
},
"VERSION": "1.0"
})";

std::ofstream ofs(configPath);
ofs << configContent;
ofs.close();

swss::SonicDBConfig::reset();
swss::SonicDBConfig::initialize(configPath);
}

void TearDown() override
{
std::remove(configPath);
swss::SonicDBConfig::reset();
swss::SonicDBConfig::initialize();
}
};

TEST_F(FlexCounterTcpFallback, tcpFallbackWhenNoUnixSocket)
{
EXPECT_TRUE(swss::SonicDBConfig::getDbSock("COUNTERS_DB").empty());

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) {
for (uint32_t i = 0; i < number_of_counters; i++)
{
counters[i] = (i + 1) * 100;
}
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) {
for (uint32_t i = 0; i < number_of_counters; i++)
{
counters[i] = (i + 1) * 100;
}
return SAI_STATUS_SUCCESS;
};
sai->mock_queryStatsCapability = [](sai_object_id_t, sai_object_type_t, sai_stat_capability_list_t *) {
return SAI_STATUS_FAILURE;
};
sai->mock_bulkGetStats = [](sai_object_id_t, sai_object_type_t, uint32_t, const sai_object_key_t *, uint32_t, const sai_stat_id_t *, sai_stats_mode_t, sai_status_t *, uint64_t *) {
return SAI_STATUS_FAILURE;
};

// FlexCounter should detect empty socket path and use TCP
FlexCounter fc("test_tcp", sai, "COUNTERS_DB");

test_syncd::mockVidManagerObjectTypeQuery(SAI_OBJECT_TYPE_PORT);

std::vector<swss::FieldValueTuple> values;
values.emplace_back(POLL_INTERVAL_FIELD, "1000");
values.emplace_back(FLEX_COUNTER_STATUS_FIELD, "enable");
values.emplace_back(STATS_MODE_FIELD, STATS_MODE_READ);
fc.addCounterPlugin(values);

values.clear();
values.emplace_back(PORT_COUNTER_ID_LIST, "SAI_PORT_STAT_IF_IN_OCTETS,SAI_PORT_STAT_IF_IN_UCAST_PKTS");

auto object_ids = generateOids(1, SAI_OBJECT_TYPE_PORT);
fc.addCounter(object_ids[0], object_ids[0], values);
EXPECT_FALSE(fc.isEmpty());

// Use TCP to connect and verify counters were written
swss::DBConnector db("COUNTERS_DB", 0, true);
swss::RedisPipeline pipeline(&db);
swss::Table countersTable(&pipeline, COUNTERS_TABLE, false);

waitForCounterKeys(countersTable, 1);

std::string key = toOid(object_ids[0]);
waitForCounterValues(countersTable, key,
{"SAI_PORT_STAT_IF_IN_OCTETS", "SAI_PORT_STAT_IF_IN_UCAST_PKTS"},
{"100", "200"});

fc.removeCounter(object_ids[0]);
EXPECT_TRUE(fc.isEmpty());

countersTable.del(key);
}
Loading