Skip to content

Commit

Permalink
Add port counters collector thread (sonic-net#12)
Browse files Browse the repository at this point in the history
* Add port counters collector thread

* Use VID for port ID counter statistics

* Get only supported counters, allow tune interval
  • Loading branch information
kcudnik committed Apr 29, 2016
1 parent 8aca74a commit 58870d9
Show file tree
Hide file tree
Showing 6 changed files with 289 additions and 4 deletions.
119 changes: 119 additions & 0 deletions common/saiserialize.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "saiserialize.h"

#include <vector>

sai_serialization_map_t g_serialization_map = sai_get_serialization_map();
sai_object_type_to_string_map_t g_object_type_map = sai_get_object_type_map();

Expand Down Expand Up @@ -128,6 +130,123 @@ sai_status_t sai_get_object_type_string(sai_object_type_t object_type, std::stri
return SAI_STATUS_SUCCESS;
}

static std::vector<std::string> sai_get_port_stat_counter_names()
{
SWSS_LOG_ENTER();

std::vector<std::string> v;

v.resize(SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS + 1);

#define ENTRY(x) v[x] = std::string( #x )

ENTRY(SAI_PORT_STAT_IF_IN_OCTETS);
ENTRY(SAI_PORT_STAT_IF_IN_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IF_IN_DISCARDS);
ENTRY(SAI_PORT_STAT_IF_IN_ERRORS);
ENTRY(SAI_PORT_STAT_IF_IN_UNKNOWN_PROTOS);
ENTRY(SAI_PORT_STAT_IF_IN_BROADCAST_PKTS);
ENTRY(SAI_PORT_STAT_IF_IN_MULTICAST_PKTS);
ENTRY(SAI_PORT_STAT_IF_IN_VLAN_DISCARDS);
ENTRY(SAI_PORT_STAT_IF_OUT_OCTETS);
ENTRY(SAI_PORT_STAT_IF_OUT_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IF_OUT_DISCARDS);
ENTRY(SAI_PORT_STAT_IF_OUT_ERRORS);
ENTRY(SAI_PORT_STAT_IF_OUT_QLEN);
ENTRY(SAI_PORT_STAT_IF_OUT_BROADCAST_PKTS);
ENTRY(SAI_PORT_STAT_IF_OUT_MULTICAST_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_DROP_EVENTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_MULTICAST_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_BROADCAST_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_FRAGMENTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_64_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_65_TO_127_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_128_TO_255_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_256_TO_511_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_512_TO_1023_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_1024_TO_1518_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_1519_TO_2047_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_2048_TO_4095_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_4096_TO_9216_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS_9217_TO_16383_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_OVERSIZE_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_RX_OVERSIZE_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_TX_OVERSIZE_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_JABBERS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_PKTS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_COLLISIONS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_CRC_ALIGN_ERRORS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_TX_NO_ERRORS);
ENTRY(SAI_PORT_STAT_ETHER_STATS_RX_NO_ERRORS);
ENTRY(SAI_PORT_STAT_IP_IN_RECEIVES);
ENTRY(SAI_PORT_STAT_IP_IN_OCTETS);
ENTRY(SAI_PORT_STAT_IP_IN_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IP_IN_NON_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IP_IN_DISCARDS);
ENTRY(SAI_PORT_STAT_IP_OUT_OCTETS);
ENTRY(SAI_PORT_STAT_IP_OUT_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IP_OUT_NON_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IP_OUT_DISCARDS);
ENTRY(SAI_PORT_STAT_IPV6_IN_RECEIVES);
ENTRY(SAI_PORT_STAT_IPV6_IN_OCTETS);
ENTRY(SAI_PORT_STAT_IPV6_IN_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IPV6_IN_NON_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IPV6_IN_MCAST_PKTS);
ENTRY(SAI_PORT_STAT_IPV6_IN_DISCARDS);
ENTRY(SAI_PORT_STAT_IPV6_OUT_OCTETS);
ENTRY(SAI_PORT_STAT_IPV6_OUT_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IPV6_OUT_NON_UCAST_PKTS);
ENTRY(SAI_PORT_STAT_IPV6_OUT_MCAST_PKTS);
ENTRY(SAI_PORT_STAT_IPV6_OUT_DISCARDS);
ENTRY(SAI_PORT_STAT_GREEN_DISCARD_DROPPED_PACKETS);
ENTRY(SAI_PORT_STAT_GREEN_DISCARD_DROPPED_BYTES);
ENTRY(SAI_PORT_STAT_YELLOW_DISCARD_DROPPED_PACKETS);
ENTRY(SAI_PORT_STAT_YELLOW_DISCARD_DROPPED_BYTES);
ENTRY(SAI_PORT_STAT_RED_DISCARD_DROPPED_PACKETS);
ENTRY(SAI_PORT_STAT_RED_DISCARD_DROPPED_BYTES);
ENTRY(SAI_PORT_STAT_DISCARD_DROPPED_PACKETS);
ENTRY(SAI_PORT_STAT_DISCARD_DROPPED_BYTES);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_64_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_65_TO_127_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_128_TO_255_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_256_TO_511_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_512_TO_1023_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_1024_TO_1518_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_1519_TO_2047_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_2048_TO_4095_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_4096_TO_9216_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_IN_PKTS_9217_TO_16383_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_64_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_65_TO_127_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_128_TO_255_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_256_TO_511_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_512_TO_1023_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_1024_TO_1518_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_1519_TO_2047_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_2048_TO_4095_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_4096_TO_9216_OCTETS);
ENTRY(SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS);

return std::move(v);
}

static std::vector<std::string> g_port_stat_counter_names = sai_get_port_stat_counter_names();

std::string sai_get_port_stat_counter_name(sai_port_stat_counter_t counter)
{
if (counter < g_port_stat_counter_names.size())
return g_port_stat_counter_names[counter];

SWSS_LOG_WARN("unable to find counter name: %d", counter);

// TODO exit here ?
return std::to_string(counter);
}

sai_status_t sai_get_serialization_type(
_In_ const sai_object_type_t object_type,
_In_ const sai_attr_id_t attr_id,
Expand Down
2 changes: 2 additions & 0 deletions common/saiserialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,6 @@ void transfer_attributes(
_In_ sai_attribute_t *dst_attr_list,
_In_ bool countOnly);

std::string sai_get_port_stat_counter_name(sai_port_stat_counter_t counter);

#endif // __SAI_SERIALIZE__
1 change: 1 addition & 0 deletions syncd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ syncd_SOURCES = syncd.cpp \
syncd_reinit.cpp \
syncd_hard_reinit.cpp \
syncd_notifications.cpp \
syncd_counters.cpp \
../common/redisclient.cpp \
../common/saiserialize.cpp \
../common/saiattribute.cpp \
Expand Down
36 changes: 32 additions & 4 deletions syncd/syncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,9 @@ void notifySyncd(swss::NotificationConsumer &consumer)

struct cmdOptions
{
int countersThreadIntervalInSeconds;
bool diagShell;
bool disableCountersThread;
std::string profileMapFile;
};

Expand All @@ -912,24 +914,35 @@ cmdOptions handleCmdLine(int argc, char **argv)

cmdOptions options = {};

const int defaultCountersThreadIntervalInSeconds = 1;

options.countersThreadIntervalInSeconds = defaultCountersThreadIntervalInSeconds;

while(true)
{
static struct option long_options[] =
{
{"diag", no_argument, 0, 'd' },
{"profile", required_argument, 0, 'p' },
{0, 0, 0, 0}
{ "diag", no_argument, 0, 'd' },
{ "nocounters", no_argument, 0, 'N' },
{ "profile", required_argument, 0, 'p' },
{ "countersInterval", required_argument, 0, 'i' },
{ 0, 0, 0, 0 }
};

int option_index = 0;

int c = getopt_long(argc, argv, "dp:", long_options, &option_index);
int c = getopt_long(argc, argv, "dNp:i:", long_options, &option_index);

if (c == -1)
break;

switch (c)
{
case 'N':
SWSS_LOG_INFO("disable counters thread");
options.disableCountersThread = true;
break;

case 'd':
SWSS_LOG_INFO("enable diag shell");
options.diagShell = true;
Expand All @@ -940,6 +953,12 @@ cmdOptions handleCmdLine(int argc, char **argv)
options.profileMapFile = std::string(optarg);
break;

case 'i':
SWSS_LOG_INFO("counters thread interval: %s", optarg);
options.countersThreadIntervalInSeconds =
std::max(defaultCountersThreadIntervalInSeconds, std::stoi(std::string(optarg)));
break;

case '?':
SWSS_LOG_WARN("unknown get opti option %c", optopt);
exit(EXIT_FAILURE);
Expand Down Expand Up @@ -1057,6 +1076,13 @@ int main(int argc, char **argv)

SWSS_LOG_INFO("syncd listening for events");

if (options.disableCountersThread == false)
{
SWSS_LOG_INFO("starting counters thread");

startCountersThread(options.countersThreadIntervalInSeconds);
}

swss::Select s;

s.addSelectable(getRequest);
Expand Down Expand Up @@ -1088,5 +1114,7 @@ int main(int argc, char **argv)
SWSS_LOG_ERROR("Runtime error: %s", e.what());
}

endCountersThread();

sai_api_uninitialize();
}
5 changes: 5 additions & 0 deletions syncd/syncd.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,9 @@ extern swss::DBConnector *db;
void initialize_common_api_pointers();
void populate_sai_apis();

void startCountersThread(int intervalInSeconds);
void endCountersThread();

std::vector<sai_object_id_t> saiGetPortList();

#endif // __SYNCD_H__
130 changes: 130 additions & 0 deletions syncd/syncd_counters.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include "syncd.h"

void collectCounters(swss::Table &countersTable,
const std::vector<sai_port_stat_counter_t> &supportedCounters)
{
// collect counters should be under mutex
// sice configuration can change and we
// don't want that during counters collection
std::lock_guard<std::mutex> lock(g_mutex);

SWSS_LOG_ENTER();

SWSS_LOG_TIMER("get counters");

uint32_t countersSize = supportedCounters.size();

std::vector<uint64_t> counters;

counters.resize(countersSize);

auto ports = saiGetPortList();

for (auto &portId: ports)
{
sai_status_t status = sai_port_api->get_port_stats(portId, supportedCounters.data(), countersSize, counters.data());

if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("failed to collect counters for port %llx: %d", portId, status);
return;
}

sai_object_id_t vid = translate_rid_to_vid(portId);

std::string strPortId;
sai_serialize_primitive(vid, strPortId);

std::vector<swss::FieldValueTuple> values;

for (size_t idx = 0; idx < counters.size(); idx++)
{
std::string field = sai_get_port_stat_counter_name(supportedCounters[idx]);
std::string value = std::to_string(counters[idx]);

swss::FieldValueTuple fvt(field, value);

values.push_back(fvt);
}

countersTable.set(strPortId, values, "");
}
}

std::vector<sai_port_stat_counter_t> getSupportedCounters(sai_object_id_t portId)
{
SWSS_LOG_ENTER();

std::vector<sai_port_stat_counter_t> supportedCounters;

for (int idx = SAI_PORT_STAT_IF_IN_OCTETS;
idx <= SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS;
++idx)
{
sai_port_stat_counter_t counter = (sai_port_stat_counter_t)idx;

uint64_t value;

sai_status_t status = sai_port_api->get_port_stats(portId, &counter, 1, &value);

if (status != SAI_STATUS_SUCCESS)
{
const std::string &name = sai_get_port_stat_counter_name(counter);

SWSS_LOG_WARN("counter %s is not supported on port RID %llx: %d", name.c_str(), portId, status);
continue;
}

supportedCounters.push_back(counter);
}

return std::move(supportedCounters);
}

static volatile bool g_runCountersThread = false;
static std::shared_ptr<std::thread> g_countersThread = NULL;

void collectCountersThread(int intervalInSeconds)
{
SWSS_LOG_ENTER();

swss::DBConnector db(COUNTERS_DB, "localhost", 6379, 0);
swss::Table countersTable(&db, "COUNTERS");

auto ports = saiGetPortList();

// get supported counters on first port
// we assume that all ports will support those counters
const auto &supportedCounters = getSupportedCounters(ports.at(0));

SWSS_LOG_INFO("supported counters count: %ld", supportedCounters.size());

while(g_runCountersThread)
{
collectCounters(countersTable, supportedCounters);

// collect counters every second
sleep(intervalInSeconds);
}
}

void startCountersThread(int intervalInSeconds)
{
SWSS_LOG_ENTER();

g_runCountersThread = true;

g_countersThread = std::shared_ptr<std::thread>(new std::thread(collectCountersThread, intervalInSeconds));
}

void endCountersThread()
{
SWSS_LOG_ENTER();

g_runCountersThread = false;

if (g_countersThread != NULL)
{
g_countersThread->join();
}
}

0 comments on commit 58870d9

Please sign in to comment.