Commit 365bf66b authored by Adam Wujek's avatar Adam Wujek 💬

userspace/snmpd: transpose wrsPstats and move it to different branch in MIB

--transpose wrsPstats, now ports are in rows, counters in columns
--counters descriptions from pstats info file are not used anymore
--move pstats from wrsPstats.c to wrsPstatsTable.c
--use tableTemplate.h for wrsPstatsTable.c
--move in MIB from .1.3.6.1.4.1.96.100.2.1 to .1.3.6.1.4.1.96.100.6.4.1
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parent 8baa63de
......@@ -28,7 +28,7 @@ SOURCES = \
init.c \
snmp_shmem.c \
wrsScalar.c \
wrsPstats.c \
wrsPstatsTable.c \
wrsVersion.c \
wrsDate.c \
shmem.c \
......
This diff is collapsed.
......@@ -8,6 +8,7 @@
/* The sub-init functions */
#include "wrsSnmp.h"
#include "snmp_shmem.h"
#include "wrsPstatsTable.h"
#include "wrsPtpDataTable.h"
#include "wrsTemperature.h"
#include "wrsOSStatus.h"
......@@ -19,7 +20,7 @@ void init_wrsSnmp(void)
{
init_shm();
init_wrsScalar();
init_wrsPstats();
init_wrsPstatsTable();
init_wrsVersion();
init_wrsDate();
init_wrsPtpDataTable();
......
/*
* White Rabbit Switch pstats table
* Using the netsnmp iterator, like in tcpTable
* Alessandro Rubini for CERN, 2014
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/auto_nlist.h>
#include "wrsSnmp.h"
#define PSTATS_CACHE_TIMEOUT 5 /* seconds */
/* Our structure for caching data */
#define PSTATS_MAX_N_COUNTERS 50 /* Maximum number of counters */
#define PSTATS_N_PORTS 18 /* this hardwired in the mib too */
#define PSTATS_MAX_COUNTERS_NAME_LEN 35 /* maximum length of counter's name */
#define PSTATS_SYSCTL_PATH "/proc/sys/pstats/" /* Path to sysclt entries */
#define PSTATS_SYSCTL_DESCRIPTION_FILE "description" /* file with counters' descriptions */
struct pstats_per_port {
uint32_t val[PSTATS_MAX_N_COUNTERS];
};
static struct pstats_global_data {
struct pstats_per_port port[PSTATS_N_PORTS];
char counter_name[PSTATS_MAX_N_COUNTERS][PSTATS_MAX_COUNTERS_NAME_LEN];
int n_counters;
} pstats_global_data;
/* FIXME: build error if ARRAY_SIZE(pstats_names) != PSTATS_N_COUNTERS */
static int
wrsPstats_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
netsnmp_request_info *request;
netsnmp_variable_list *requestvb;
netsnmp_table_request_info *table_info;
struct pstats_global_data *data = &pstats_global_data; /* a shorter name */
int counter;
int wrport;
uint32_t *c;
logmsg("%s: %i\n", __func__, __LINE__);
switch (reqinfo->mode) {
case MODE_GET:
for (request = requests; request; request = request->next) {
requestvb = request->requestvb;
logmsg("%s: %i\n", __func__, __LINE__);
/* our "context" is the counter number; "subid" the column i.e. the port */
counter = (intptr_t)netsnmp_extract_iterator_context(request);
if (!counter)
/* NULL returned from
* netsnmp_extract_iterator_context shuld be
* interpreted as end of table */
continue;
/* change range of counter (1..39 (snmp is 1 based) ->
* 0..38 (pstats_global_data array is 0 based)) */
counter--;
table_info = netsnmp_extract_table_info(request);
/* port is 0-based and position 1 is the string */
wrport = table_info->colnum - 2;
logmsg("counter %i, port %i\n", counter, wrport);
if (wrport < 0) {
char *s = pstats_global_data.counter_name[counter];
snmp_set_var_typed_value(requestvb, ASN_OCTET_STR, s, strlen(s));
continue;
}
/* While most tables do "switch(subid)" we'd better just index */
c = &data->port[wrport].val[counter];
snmp_set_var_typed_value(requestvb, ASN_COUNTER,
(u_char *)c, sizeof(*c));
}
break;
case MODE_GETNEXT:
case MODE_GETBULK:
case MODE_SET_RESERVE1:
case MODE_SET_RESERVE2:
case MODE_SET_ACTION:
case MODE_SET_COMMIT:
case MODE_SET_FREE:
case MODE_SET_UNDO:
/* unsupported mode */
break;
default:
/* unknown mode */
break;
}
return SNMP_ERR_NOERROR;
}
static netsnmp_variable_list *
wrsPstats_next_entry(void **loop_context,
void **data_context,
netsnmp_variable_list *index,
netsnmp_iterator_info *data)
{
intptr_t i;
/* create the line ID from counter number */
i = (intptr_t)*loop_context;
//logmsg("%s: %i (i = %i)\n", __func__, __LINE__, i);
if (i >= pstats_global_data.n_counters)
return NULL; /* no more */
i++;
/* Create the row OID: only the counter index */
snmp_set_var_value(index, (u_char *)&i, sizeof(i));
/* Set the data context (1..39)
* Cannot be set to 0, because netsnmp_extract_iterator_context returns
* NULL in function wrsPstats_handler when table is over */
*data_context = (void *)i;
/* and set the loop context for the next iteration */
*loop_context = (void *)i;
return index;
}
static netsnmp_variable_list *
wrsPstats_first_entry(void **loop_context,
void **data_context,
netsnmp_variable_list *index,
netsnmp_iterator_info *data)
{
logmsg("%s: %i\n", __func__, __LINE__);
/* reset internal position, so "next" is "first" */
*loop_context = (void *)0; /* first counter */
return wrsPstats_next_entry(loop_context, data_context, index, data);
}
static int
wrsPstats_load(netsnmp_cache *cache, void *vmagic)
{
FILE *f;
char fname[32];
int wrport, counter;
struct pstats_per_port *stat;
char *p;
/* fill names of counters */
f = fopen(PSTATS_SYSCTL_PATH PSTATS_SYSCTL_DESCRIPTION_FILE, "r");
if (f) {
for (counter = 0; counter < PSTATS_MAX_N_COUNTERS; counter++) {
/* parse new line delimited file */
p = fgets(pstats_global_data.counter_name[counter],
PSTATS_MAX_COUNTERS_NAME_LEN, f);
if (p == NULL)
break;
/* fgets usualy returns strings with newline, return
string shall contain maximum one newline character */
p = strchr(pstats_global_data.counter_name[counter],
'\n');
if (p != NULL)
*p = '\0';
}
pstats_global_data.n_counters = counter;
fclose(f);
} else {
/* use PSTATS_MAX_N_COUNTERS as number of counters */
pstats_global_data.n_counters = PSTATS_MAX_N_COUNTERS;
/* fill counters' names */
for (counter = 0; counter < PSTATS_MAX_N_COUNTERS; counter++) {
snprintf(pstats_global_data.counter_name[counter],
PSTATS_MAX_COUNTERS_NAME_LEN,
"pstats counter %d", counter);
}
}
for (wrport = 0; wrport < PSTATS_N_PORTS; wrport++) {
sprintf(fname, PSTATS_SYSCTL_PATH"port%i", wrport);
stat = pstats_global_data.port + wrport;
f = fopen(fname, "r");
if (!f) {
memset(stat, 0x7f, sizeof(*stat));
continue;
}
for (counter = 0;
counter < pstats_global_data.n_counters;
counter++) {
if (fscanf(f, "%u", stat->val + counter) != 1)
stat->val[counter] = 0xffffffff;
}
fclose(f);
}
return 0;
}
void
init_wrsPstats(void)
{
const oid wrsPstats_oid[] = { WRS_OID, 2 };
netsnmp_table_registration_info *table_info;
netsnmp_iterator_info *iinfo;
netsnmp_handler_registration *reginfo;
table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
if (!table_info)
return;
/* Add indexes: we only use one integer OID member as line identifier */
netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, 0);
table_info->min_column = 1;
table_info->max_column = 1 + PSTATS_N_PORTS;
/* Iterator info */
iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
if (!iinfo)
return; /* free table_info? */
iinfo->get_first_data_point = wrsPstats_first_entry;
iinfo->get_next_data_point = wrsPstats_next_entry;
iinfo->table_reginfo = table_info;
/* register the table */
reginfo = netsnmp_create_handler_registration("wrsPstats",
wrsPstats_handler,
wrsPstats_oid, OID_LENGTH(wrsPstats_oid),
HANDLER_CAN_RONLY);
netsnmp_register_table_iterator(reginfo, iinfo);
/* and create a local cache */
netsnmp_inject_handler(reginfo,
netsnmp_get_cache_handler(PSTATS_CACHE_TIMEOUT,
wrsPstats_load, NULL,
wrsPstats_oid, OID_LENGTH(wrsPstats_oid)));
}
#include "wrsSnmp.h"
#include "wrsPstatsTable.h"
struct wrsPstatsTable_s pstats_array[WRS_N_PORTS];
static struct pickinfo wrsPstatsTable_pickinfo[] = {
/* Warning: strings are a special case for snmp format */
FIELD(wrsPstatsTable_s, ASN_UNSIGNED, index), /* not reported */
FIELD(wrsPstatsTable_s, ASN_OCTET_STR, port_name),
FIELD(wrsPstatsTable_s, ASN_COUNTER, TXUnderrun),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXOverrun),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXInvalidCode),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXSyncLost),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPauseFrames),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPfilterDropped),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPCSErrors),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXGiantFrames),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXRuntFrames),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXCRCErrors),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass0),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass1),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass2),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass3),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass4),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass5),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass6),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPclass7),
FIELD(wrsPstatsTable_s, ASN_COUNTER, TXFrames),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXFrames),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXDropRTUFull),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio0),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio1),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio2),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio3),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio4),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio5),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio6),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RXPrio7),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RTUValid),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RTUResponses),
FIELD(wrsPstatsTable_s, ASN_COUNTER, RTUDropped),
FIELD(wrsPstatsTable_s, ASN_COUNTER, FastMatchPriority),
FIELD(wrsPstatsTable_s, ASN_COUNTER, FastMatchFastForward),
FIELD(wrsPstatsTable_s, ASN_COUNTER, FastMatchNonForward),
FIELD(wrsPstatsTable_s, ASN_COUNTER, FastMatchRespValid),
FIELD(wrsPstatsTable_s, ASN_COUNTER, FullMatchRespValid),
FIELD(wrsPstatsTable_s, ASN_COUNTER, Forwarded),
FIELD(wrsPstatsTable_s, ASN_COUNTER, TRURespValid),
};
time_t
wrsPstatsTable_data_fill(unsigned int *n_rows)
{
FILE *f;
char fname[32];
int wrport;
uint32_t i;
uint32_t counters[PSTATS_MAX_N_COUNTERS];
static time_t time_update;
time_t time_cur;
uint32_t n_counters_in_fpga;
uint32_t counters_version;
uint32_t tmp;
if (n_rows)
*n_rows = WRS_N_PORTS;
time_cur = time(NULL);
if (time_update
&& time_cur - time_update < WRSPSTATSTABLE_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
return time_update;
}
time_update = time_cur;
/* fill array with 0xff, buy this it will be easy visible in case
* some counters are invalid */
memset(&pstats_array, 0xff, sizeof(pstats_array));
/* read counters version and number of counters */
f = fopen(PSTATS_SYSCTL_PATH PSTATS_SYSCTL_INFO_FILE, "r");
if (f) {
if (fscanf(f, "%u", &counters_version) != 1) {
/* not able to read valid counters version,
* assign invalid version number */
counters_version = 0;
}
/* read number of counters per word, not used */
fscanf(f, "%u", &tmp);
if (fscanf(f, "%u", &n_counters_in_fpga) != 1) {
/* not able to read valid number of counters,
* use maximum possible */
n_counters_in_fpga = PSTATS_MAX_N_COUNTERS;
}
if (n_counters_in_fpga > PSTATS_MAX_N_COUNTERS) {
/* n_counters_in_fpga cannot be bigger than
* PSTATS_MAX_N_COUNTERS */
n_counters_in_fpga = PSTATS_MAX_N_COUNTERS;
}
fclose(f);
} else {
/* unable to open info file */
/* use PSTATS_MAX_N_COUNTERS as number of counters */
n_counters_in_fpga = PSTATS_MAX_N_COUNTERS;
counters_version = 0; /* invalid version */
}
/* read pstats for each port */
for (wrport = 0; wrport < WRS_N_PORTS; wrport++) {
snprintf(pstats_array[wrport].port_name, 10,
"wr%d", wrport);
sprintf(fname, PSTATS_SYSCTL_PATH"port%i", wrport);
f = fopen(fname, "r");
if (!f) {
snmp_log(LOG_ERR,
"SNMP: wrsPstatsTable filed to open file %s\n", fname);
continue;
}
for (i = 0; i < n_counters_in_fpga; i++) {
if (fscanf(f, "%u", &counters[i]) != 1)
counters[i] = 0xffffffff;
}
fclose(f);
/* copy counters */
switch (counters_version) {
case 1:
/* copy counters to array */
pstats_array[wrport].TXUnderrun = counters[0];
pstats_array[wrport].RXOverrun = counters[1];
pstats_array[wrport].RXInvalidCode = counters[2];
pstats_array[wrport].RXSyncLost = counters[3];
pstats_array[wrport].RXPauseFrames = counters[4];
pstats_array[wrport].RXPfilterDropped = counters[5];
pstats_array[wrport].RXPCSErrors = counters[6];
pstats_array[wrport].RXGiantFrames = counters[7];
pstats_array[wrport].RXRuntFrames = counters[8];
pstats_array[wrport].RXCRCErrors = counters[9];
pstats_array[wrport].RXPclass0 = counters[10];
pstats_array[wrport].RXPclass1 = counters[11];
pstats_array[wrport].RXPclass2 = counters[12];
pstats_array[wrport].RXPclass3 = counters[13];
pstats_array[wrport].RXPclass4 = counters[14];
pstats_array[wrport].RXPclass5 = counters[15];
pstats_array[wrport].RXPclass6 = counters[16];
pstats_array[wrport].RXPclass7 = counters[17];
pstats_array[wrport].TXFrames = counters[18];
pstats_array[wrport].RXFrames = counters[19];
pstats_array[wrport].RXDropRTUFull = counters[20];
pstats_array[wrport].RXPrio0 = counters[21];
pstats_array[wrport].RXPrio1 = counters[22];
pstats_array[wrport].RXPrio2 = counters[23];
pstats_array[wrport].RXPrio3 = counters[24];
pstats_array[wrport].RXPrio4 = counters[25];
pstats_array[wrport].RXPrio5 = counters[26];
pstats_array[wrport].RXPrio6 = counters[27];
pstats_array[wrport].RXPrio7 = counters[28];
pstats_array[wrport].RTUValid = counters[29];
pstats_array[wrport].RTUResponses = counters[30];
pstats_array[wrport].RTUDropped = counters[31];
pstats_array[wrport].FastMatchPriority = counters[32];
pstats_array[wrport].FastMatchFastForward = counters[33];
pstats_array[wrport].FastMatchNonForward = counters[34];
pstats_array[wrport].FastMatchRespValid = counters[35];
pstats_array[wrport].FullMatchRespValid = counters[36];
pstats_array[wrport].Forwarded = counters[37];
pstats_array[wrport].TRURespValid = counters[38];
break;
case 2:
default:
break;
}
}
/* there was an update, return current time */
return time_update;
}
#define TT_OID WRSPSTATSTABLE_OID
#define TT_PICKINFO wrsPstatsTable_pickinfo
#define TT_DATA_FILL_FUNC wrsPstatsTable_data_fill
#define TT_DATA_ARRAY pstats_array
#define TT_GROUP_NAME "wrsPstatsTable"
#define TT_INIT_FUNC init_wrsPstatsTable
#define TT_CACHE_TIMEOUT WRSPSTATSTABLE_CACHE_TIMEOUT
#include "wrsTableTemplate.h"
#ifndef WRS_PSTATS_TABLE_H
#define WRS_PSTATS_TABLE_H
#define WRSPSTATSTABLE_CACHE_TIMEOUT 5
#define WRSPSTATSTABLE_OID WRS_OID, 6, 4
#define PSTATS_MAX_N_COUNTERS 39 /* maximum number of counters */
#define PSTATS_SYSCTL_PATH "/proc/sys/pstats/" /* Path to sysclt entries */
#define PSTATS_SYSCTL_INFO_FILE "info" /* file with version of pstats counters
* and number of counters */
struct wrsPstatsTable_s {
uint32_t index; /* not reported, index fields has to be marked
* as not-accessible in MIB */
char port_name[12]; /* port name of counters */
uint32_t TXUnderrun;
uint32_t RXOverrun;
uint32_t RXInvalidCode;
uint32_t RXSyncLost;
uint32_t RXPauseFrames;
uint32_t RXPfilterDropped;
uint32_t RXPCSErrors;
uint32_t RXGiantFrames;
uint32_t RXRuntFrames;
uint32_t RXCRCErrors;
uint32_t RXPclass0;
uint32_t RXPclass1;
uint32_t RXPclass2;
uint32_t RXPclass3;
uint32_t RXPclass4;
uint32_t RXPclass5;
uint32_t RXPclass6;
uint32_t RXPclass7;
uint32_t TXFrames;
uint32_t RXFrames;
uint32_t RXDropRTUFull;
uint32_t RXPrio0;
uint32_t RXPrio1;
uint32_t RXPrio2;
uint32_t RXPrio3;
uint32_t RXPrio4;
uint32_t RXPrio5;
uint32_t RXPrio6;
uint32_t RXPrio7;
uint32_t RTUValid;
uint32_t RTUResponses;
uint32_t RTUDropped;
uint32_t FastMatchPriority;
uint32_t FastMatchFastForward;
uint32_t FastMatchNonForward;
uint32_t FastMatchRespValid;
uint32_t FullMatchRespValid;
uint32_t Forwarded;
uint32_t TRURespValid;
};
extern struct wrsPstatsTable_s pstats_array[WRS_N_PORTS];
time_t wrsPstatsTable_data_fill(unsigned int *rows);
void init_wrsPstatsTable(void);
#endif /* WRS_PSTATS_TABLE_H */
......@@ -102,7 +102,6 @@ static inline int dumpstruct(FILE *dest, char *name, void *ptr, int size)
extern void init_wrsScalar(void);
/* Real stuff follows */
extern void init_wrsPstats(void);
extern void init_wrsVersion(void);
extern void init_wrsDate(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment