Commit 7d04c427 authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch 'adam-snmp_template' into proposed_master

Branch include SNMP related work
parents 2fa02f9f a20e15e6
......@@ -367,28 +367,53 @@ config SNMP_TEMP_THOLD_FPGA
default "0"
help
Threshold level for FPGA temperature, when exceeded warning is
notified by WR-SWITCH-MIB::tempWarning
notified by SNMP via WR-SWITCH-MIB::wrsTemperatureWarning
Require hal restart after change
config SNMP_TEMP_THOLD_PLL
int "Threshold level for PLL temperature"
default "0"
help
Threshold level for PLL temperature, when exceeded warning is
notified by WR-SWITCH-MIB::tempWarning
notified by SNMP via WR-SWITCH-MIB::wrsTemperatureWarning
Require hal restart after change
config SNMP_TEMP_THOLD_PSL
int "Threshold level for Power Supply Left (PSL) temperature"
default "0"
help
Threshold level for Power Supply Left (PSL) temperature, when
exceeded warning is notified by WR-SWITCH-MIB::tempWarning
exceeded warning is notified by SNMP via
WR-SWITCH-MIB::wrsTemperatureWarning
Require hal restart after change
config SNMP_TEMP_THOLD_PSR
int "Threshold level for Power Supply Right (PSR) temperature"
default "0"
help
Threshold level for Power Supply Right (PSR) temperature, when
exceeded warning is notified by WR-SWITCH-MIB::tempWarning
exceeded warning is notified by SNMP via
WR-SWITCH-MIB::wrsTemperatureWarning
Require hal restart after change
config SNMP_SWCORESTATUS_HP_FRAME_RATE
int "Maximum allowed rate of HP frames on a port"
default "0"
help
Error via SNMP if rate of HP frames on any port exceed given value.
config SNMP_SWCORESTATUS_RX_FRAME_RATE
int "Maximum allowed rate of RX frames on a port"
default "0"
help
Error via SNMP if rate of RX frames on any port exceed given value.
config SNMP_SWCORESTATUS_RX_PRIO_FRAME_RATE
int "Maximum allowed rate of any RX priority"
default "0"
help
Error if frame rate of any RX priority exceed given value.
endmenu
......
......@@ -1360,6 +1360,63 @@ If everything goes well, you'll get a window like the following one:
@center @image{show-pstats, 10cm,, show-pstats}
Command @t{snmptable} can also be used to get simillar results:
@smallexample
snmptable -Cw 80 -c public -v 2c 192.168.1.10 -m all \
-M $WRS_OUTPUT_DIR/build/buildroot-2011.11/output/build/netsnmp-5.6.1.1/mibs/\
:userspace/snmpd/ WR-SWITCH-MIB::wrsPstatsTable
@end smallexample
Output is in text form and looks like:
@smallexample
SNMP table: WR-SWITCH-MIB::wrsPstatsTable
wrsPstatsPortName wrsPstatsTXUnderrun wrsPstatsRXOverrun wrsPstatsRXInvalidCode
wr0 0 0 0
wr1 0 0 0
wr2 0 0 0
wr3 0 0 0
wr4 0 0 0
wr5 0 0 0
wr6 0 0 0
wr7 0 0 0
wr8 0 0 0
wr9 0 0 0
wr10 0 0 0
wr11 0 0 0
wr12 0 0 0
wr13 0 0 0
wr14 0 0 0
wr15 0 0 0
wr16 0 0 0
wr17 0 0 0
SNMP table WR-SWITCH-MIB::wrsPstatsTable, part 2
wrsPstatsRXSyncLost wrsPstatsRXPauseFrames wrsPstatsRXPfilterDropped
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
(...)
@end smallexample
Unfortunately output due to the number of counters is very wide. Number of
characters per line can be limited by switch @t{Cw}, in example was set to 80.
@c ##########################################################################
@node Bugs and Troubleshooting
......
......@@ -8,9 +8,16 @@
# First, read dot-config to get the new location, if any.
dotconfig=/wr/etc/dot-config
tmpconfig=/tmp/dot-config
tmpdir=/tmp
if [ -f $dotconfig ]; then
. $dotconfig
echo "local" > "$tmpdir"/dot-config_proto
#assume that local config is always ok
echo "config_ok" > "$tmpdir"/dot-config_status
else
echo "no_config" > "$tmpdir"/dot-config_proto
echo "config_error" > "$tmpdir"/dot-config_status
fi
# Create /etc/resolv.conf, so we can use it. /etc is ramdisk anyways
......@@ -33,6 +40,11 @@ if [ -n "$CONFIG_DOTCONF_URL" ]; then
host=$(echo $URL | cut -d/ -f 3)
filename=$(echo $URL | cut -d/ -f 4-)
# save proto, host and filename of dot-config, to be used by SNMPd
echo "$proto" > "$tmpdir"/dot-config_proto
echo "$host" > "$tmpdir"/dot-config_host
echo "$filename" > "$tmpdir"/dot-config_filename
rm -f $tmpconfig
case $proto in
http|ftp)
......@@ -45,13 +57,20 @@ if [ -n "$CONFIG_DOTCONF_URL" ]; then
echo "Invalid URL for dot-config: \"$URL\"" >& 2
;;
esac
# If it exists, it is not empty or too small, and the checker is happy..
if [ -f $tmpconfig ] &&
[ $(cat $tmpconfig | wc -c) -gt 200 ] &&
/wr/bin/wrs_checkcfg $tmpconfig /wr/etc/Kconfig; then
echo "Using newly-downloaded dot-config from $URL"
# copy it in place to use the new file (unless it is identical)
cmp -s $tmpconfig $dotconfig || cp $tmpconfig $dotconfig
if [ -f $tmpconfig ]; then
# If it exists, it is not empty or too small, and the checker is happy
if [ $(cat $tmpconfig | wc -c) -gt 200 ] &&
/wr/bin/wrs_checkcfg $tmpconfig /wr/etc/Kconfig; then
echo "Using newly-downloaded dot-config from $URL"
# copy it in place to use the new file (unless it is identical)
cmp -s $tmpconfig $dotconfig || cp $tmpconfig $dotconfig
# info for SNMP that downloading was successful and checker is happy
echo "config_ok" > "$tmpdir"/dot-config_status
else
echo "check_error" > "$tmpdir"/dot-config_status
fi
else
echo "download_error" > "$tmpdir"/dot-config_status
fi
fi
......
......@@ -6,6 +6,18 @@
# Make sure the dropbearkey progam exists
[ -f /usr/bin/dropbearkey ] || exit 0
start_counter() {
# increase boot counter
COUNTER_FILE="/tmp/start_cnt_sshd"
START_COUNTER=1
if [ -f "$COUNTER_FILE" ];
then
read -r START_COUNTER < $COUNTER_FILE
START_COUNTER=$((START_COUNTER+1))
fi
echo "$START_COUNTER" > $COUNTER_FILE
}
start() {
echo -n "Starting dropbear sshd: "
# Make sure dropbear directory exists
......@@ -28,6 +40,7 @@ start() {
fi
umask 077
start-stop-daemon -S -q -p /var/run/dropbear.pid --exec /usr/sbin/dropbear
start_counter
echo "OK"
}
stop() {
......
#!/bin/sh
COUNTER_FILE="/tmp/start_cnt_syslogd"
start_counter() {
# increase boot counter
START_COUNTER=1
if [ -f "$COUNTER_FILE" ];
then
read -r START_COUNTER < $COUNTER_FILE
START_COUNTER=$((START_COUNTER+1))
fi
echo "$START_COUNTER" > $COUNTER_FILE
}
start() {
# Check the configuration file: if there's no target, don't run the thing.
if ! grep -q '^##.*remote-host' /etc/rsyslog.conf; then
echo -n "Starting rsyslog: "
/usr/sbin/rsyslogd
start_counter
echo "OK"
else
echo "Not starting rsyslog: no target host selected"
# avoid SNMPd complaints about lack of start counter file
echo "0" > $COUNTER_FILE
fi
}
......
......@@ -3,9 +3,22 @@
SNMP_PID=/var/run/snmpd.pid
SNMP_CONF=/wr/etc/snmpd.conf
start_counter() {
# increase boot counter
COUNTER_FILE="/tmp/start_cnt_snmpd"
START_COUNTER=1
if [ -f "$COUNTER_FILE" ];
then
read -r START_COUNTER < $COUNTER_FILE
START_COUNTER=$((START_COUNTER+1))
fi
echo "$START_COUNTER" > $COUNTER_FILE
}
start() {
# Log to syslog at daemon level. And log source address (-a)
snmpd -Lsd -p $SNMP_PID -a -c $SNMP_CONF
start_counter
}
stop() {
......
......@@ -13,11 +13,22 @@ if [ -n "$WRS_VERBOSE" ]; then
set -x
fi
# will be changed later if successful
echo "hwinfo_error" > /tmp/hwinfo_read_status
# This kernel has no hwinfo partition (strange...)
if ! grep -q hwinfo /proc/mtd; then exit 0; fi
if ! grep -q hwinfo /proc/mtd; then
# probably not an error, save script result for snmp
echo "hwinfo_warning" > /tmp/hwinfo_read_status
exit 0;
fi
# Is there sdb in there? If so, nothing to do.
if /wr/bin/sdb-read /dev/mtd5ro > /dev/null; then exit 0; fi
if /wr/bin/sdb-read /dev/mtd5ro > /dev/null; then
# save script result for snmp
echo "hwinfo_ok" > /tmp/hwinfo_read_status
exit 0;
fi
echo "Creating SDB filesystem in /dev/mtd5"
......@@ -47,3 +58,6 @@ test -c /dev/mtd5 || mknod /dev/mtd5 c 90 10
flash_erase /dev/mtd5 0 0
cat /tmp/sdb-for-dataflash > /dev/mtd5
rm /dev/mtd5
# save script result for snmp
echo "hwinfo_ok" > /tmp/hwinfo_read_status
......@@ -2,9 +2,23 @@
#
# Starts lighttpd daemon.
#
start_counter() {
# increase boot counter
COUNTER_FILE="/tmp/start_cnt_httpd"
START_COUNTER=1
if [ -f "$COUNTER_FILE" ];
then
read -r START_COUNTER < $COUNTER_FILE
START_COUNTER=$((START_COUNTER+1))
fi
echo "$START_COUNTER" > $COUNTER_FILE
}
start() {
echo -n "Starting lighttpd daemon: "
/usr/sbin/lighttpd -f /var/www/lighttpd.config
start_counter
echo "OK"
}
stop() {
......
......@@ -1282,7 +1282,8 @@ function safefilerewrite($dotconfig, $tmpdotconfig){
function apply_kconfig(){
$dotconfigapp = "/usr/wr/bin/apply_dot-config";
shell_exec($dotconfigapp. " > /dev/null 2>&1 &");
/* So far all changes via web-interface are on local file. Notify apply_dot-config that changes are on local file */
shell_exec($dotconfigapp. " local_config > /dev/null 2>&1 &");
}
......
......@@ -6,6 +6,9 @@
# require restarting running processes). The script is called at
# every boot by /etc/init.d/S20dot-config
# When called with "local_config" parameter, files with information about
# dotconfig source are removed (used by SNMP)
# We create a temporary file in /tmp, to avoid wearing flash if not
# needed. Then we replace the real file if different.
......@@ -18,6 +21,16 @@ copy_conf() {
done
}
#check if config is local
if [ "$1" == "local_config" ]; then
# remove source information in case previous config was received from
# network
rm /tmp/dot-config_*
echo "local" > /tmp/dot-config_proto
#assume that local config is always ok
echo "config_ok" > /tmp/dot-config_status
fi
# Check and complain, but we need to edit some files even if unconfigured.
if [ -f /wr/etc/dot-config ]; then
. /wr/etc/dot-config
......
#!/bin/ash
export WR_HOME="/wr"
LOAD_FPGA_STATUS_FILE="/tmp/load_fpga_status"
LOAD_LM32_STATUS_FILE="/tmp/load_lm32_status"
# Get parameter from kernel commandline
for arg in $(cat /proc/cmdline); do
......@@ -26,15 +28,33 @@ LM_FILE="$WR_HOME/lib/firmware/rt_cpu.elf"
if ! [ -f "$FP_FILE" ]; then
echo "Fatal: can't find \"$FP_FILE\"" >& 2
echo "load_file_not_found" > $LOAD_FPGA_STATUS_FILE
exit 1;
fi
if ! [ -f "$LM_FILE" ]; then
echo "Fatal: can't find \"$LM_FILE\"" >& 2
echo "load_file_not_found" > $LOAD_LM32_STATUS_FILE
exit 1;
fi
$WR_HOME/bin/load-virtex $FP_FILE
if [ $? -eq 0 ];
then
echo "load_ok" > $LOAD_FPGA_STATUS_FILE
else
echo "Fatal: load FPGA failed" >& 2
echo "load_error" > $LOAD_FPGA_STATUS_FILE
fi
$WR_HOME/bin/load-lm32 $LM_FILE scb_ver=${scb_ver}
if [ $? -eq 0 ];
then
echo "load_ok" > $LOAD_LM32_STATUS_FILE
else
echo "Fatal: load LM32 failed" >& 2
echo "load_error" > $LOAD_LM32_STATUS_FILE
fi
insmod $WR_HOME/lib/modules/at91_softpwm.ko
insmod $WR_HOME/lib/modules/wr_vic.ko
insmod $WR_HOME/lib/modules/wr-nic.ko macaddr=$val
......
......@@ -24,7 +24,26 @@ CFLAGS += -I../include -I../libwr/include -I../ppsi/include -I../ppsi/arch-wrs/i
CFLAGS += -DWRS_WITH_SNMP_HACKISH_LOG=0
SHLIB = wrsSnmp.so
SOURCES = init.c wrsScalar.c wrsPstats.c wrsPpsi.c wrsVersion.c wrsDate.c shmem.c
SOURCES = \
shmem.c \
dot-config.c \
snmp_shmem.c \
snmp_mmap.c \
wrsScalar.c \
wrsGeneralStatusGroup.c \
wrsOSStatusGroup.c \
wrsNetworkingStatusGroup.c \
wrsVersionGroup.c \
wrsCurrentTimeGroup.c \
wrsBootStatusGroup.c \
wrsTemperatureGroup.c \
wrsStartCntGroup.c \
wrsSpllStatusGroup.c \
wrsPstatsTable.c \
wrsPtpDataTable.c \
wrsPortStatusTable.c \
init.c \
OBJECTS = $(SOURCES:.c=.o)
all: $(SHLIB)
......
This diff is collapsed.
../libwr/dot-config.c
\ No newline at end of file
......@@ -7,14 +7,45 @@
/* The sub-init functions */
#include "wrsSnmp.h"
#include "snmp_shmem.h"
#include "libwr/config.h"
#include "wrsGeneralStatusGroup.h"
#include "wrsOSStatusGroup.h"
#include "wrsNetworkingStatusGroup.h"
#include "wrsVersionGroup.h"
#include "wrsCurrentTimeGroup.h"
#include "wrsBootStatusGroup.h"
#include "wrsTemperatureGroup.h"
#include "wrsStartCntGroup.h"
#include "wrsSpllStatusGroup.h"
#include "wrsPstatsTable.h"
#include "wrsPtpDataTable.h"
#include "wrsPortStatusTable.h"
#define DOTCONFIG_FILE "/wr/etc/dot-config"
FILE *wrs_logf; /* for the local-hack messages */
void init_wrsSnmp(void)
{
init_shm();
if (libwr_cfg_read_file(DOTCONFIG_FILE)) {
/* unable to read dot-config,
* don't crash SNMPd, it will be reported in SNMP objects */
snmp_log(LOG_ERR, "SNMP: unable to read dot-config file %s\n",
DOTCONFIG_FILE);
}
init_wrsScalar();
init_wrsPstats();
init_wrsPpsi();
init_wrsVersion();
init_wrsDate();
init_wrsGeneralStatusGroup();
init_wrsOSStatusGroup();
init_wrsNetworkingStatusGroup();
init_wrsVersionGroup();
init_wrsCurrentTimeGroup();
init_wrsBootStatusGroup();
init_wrsTemperatureGroup();
init_wrsStartCntGroup();
init_wrsSpllStatusGroup();
init_wrsPstatsTable();
init_wrsPtpDataTable();
init_wrsPortStatusTable();
}
......@@ -2,7 +2,7 @@
# Allow user override
if [catch "set cmd \"\$env(SHOWPS_CMD)\""] {
set cmd "snmpwalk -c public -v 2c -On -Oq HOST .1.3.6.1.4.1.96.100.2.1"
set cmd "snmpwalk -c public -v 2c -On -Oq HOST .1.3.6.1.4.1.96.100.6.4.1"
}
if ![llength $argv] {
......@@ -21,13 +21,53 @@ proc updatew {wname} {
grid [label $wname.wr$i -text "WR$i" -fg blue] -row 0 -column $c
}
}
set labels {wrsPstatsPortName
wrsPstatsTXUnderrun
wrsPstatsRXOverrun
wrsPstatsRXInvalidCode
wrsPstatsRXSyncLost
wrsPstatsRXPauseFrames
wrsPstatsRXPfilterDropped
wrsPstatsRXPCSErrors
wrsPstatsRXGiantFrames
wrsPstatsRXRuntFrames
wrsPstatsRXCRCErrors
wrsPstatsRXPclass0
wrsPstatsRXPclass1
wrsPstatsRXPclass2
wrsPstatsRXPclass3
wrsPstatsRXPclass4
wrsPstatsRXPclass5
wrsPstatsRXPclass6
wrsPstatsRXPclass7
wrsPstatsTXFrames
wrsPstatsRXFrames
wrsPstatsRXDropRTUFull
wrsPstatsRXPrio0
wrsPstatsRXPrio1
wrsPstatsRXPrio2
wrsPstatsRXPrio3
wrsPstatsRXPrio4
wrsPstatsRXPrio5
wrsPstatsRXPrio6
wrsPstatsRXPrio7
wrsPstatsRTUValid
wrsPstatsRTUResponses
wrsPstatsRTUDropped
wrsPstatsFastMatchPriority
wrsPstatsFastMatchFastForward
wrsPstatsFastMatchNonForward
wrsPstatsFastMatchRespValid
wrsPstatsFullMatchRespValid
wrsPstatsForwarded
wrsPstatsTRURespValid
}
# open a file according to the command given
set F [open "| $w($wname:cmd)" r]
while {[gets $F str] > 0} {
foreach {oid value} $str {
# remove the leading part
regsub ".1.3.6.1.4.1.96.100.2.1." $oid "" oid
regsub ".1.3.6.1.4.1.96.100.6.4.1." $oid "" oid
# extract column and row
foreach {col row} [split $oid .] {
if ![string length $row] break
......@@ -38,10 +78,24 @@ proc updatew {wname} {
set width "-width 8"
if {$col == 1} {set width ""}
eval $name config -text \"$value\" $width
grid $name -row $row -column $col
set row1 [expr $row +1]
grid $name -row $col -column $row1
}
}
}
}
set n [llength $labels]
set row 0
while {$row < $n} {
set name $wname.1_${row}
if $new {
label $name
}
set counter_name [lindex $labels $row]
eval $name config -text \"$counter_name\"
set row1 [expr $row +2]
grid $name -row $row1 -column 1
incr row
}
if [catch "close $F" message] {
puts stderr "Error in snmpwalk for host $w($wname:host)"
puts stderr $message
......
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include "snmp_mmap.h"
/* FIXME: this is copied from wr_date, should be librarized */
void *create_map(unsigned long address, unsigned long size)
{
unsigned long ps = getpagesize();
unsigned long offset, fragment, len;
void *mapaddr;
int fd;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0)
return NULL;
offset = address & ~(ps - 1);
fragment = address & (ps - 1);
len = address + size - offset;
mapaddr = mmap(0, len, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, offset);
close(fd);
if (mapaddr == MAP_FAILED)
return NULL;
return mapaddr + fragment;
}
void *create_map(unsigned long address, unsigned long size);
#include "wrsSnmp.h"
#include "snmp_shmem.h"
/* HAL */
struct wrs_shm_head *hal_head;
struct hal_shmem_header *hal_shmem;
struct hal_port_state *hal_ports;
int hal_nports_local;
/* PPSI */
struct wrs_shm_head *ppsi_head;
static struct pp_globals *ppg;
struct wr_servo_state_t *ppsi_servo;
/* RTUd */
struct wrs_shm_head *rtud_head;
static void init_shm_hal(void)
{
hal_head = wrs_shm_get(wrs_shm_hal, "", WRS_SHM_READ);
if (!hal_head) {
snmp_log(LOG_ERR, "unable to open shm for HAL!\n");
exit(-1);
}
/* check hal's shm version */
if (hal_head->version != HAL_SHMEM_VERSION) {
snmp_log(LOG_ERR, "unknown hal's shm version %i "
"(known is %i)\n", hal_head->version,
HAL_SHMEM_VERSION);
exit(-1);
}
hal_shmem = (void *)hal_head + hal_head->data_off;
/* Assume number of ports does not change in runtime */
hal_nports_local = hal_shmem->nports;
if (hal_nports_local > WRS_N_PORTS) {
snmp_log(LOG_ERR, "Too many ports reported by HAL. "
"%d vs %d supported\n",
hal_nports_local, WRS_N_PORTS);
exit(-1);
}
/* Even after HAL restart, HAL will place structures at the same
* addresses. No need to re-dereference pointer at each read. */
hal_ports = wrs_shm_follow(hal_head, hal_shmem->ports);
if (!hal_ports) {
snmp_log(LOG_ERR, "Unalbe to follow hal_ports pointer in HAL's"
" shmem");
exit(-1);
}
}
static void init_shm_ppsi(void)
{
ppsi_head = wrs_shm_get(wrs_shm_ptp, "", WRS_SHM_READ);
if (!ppsi_head) {
snmp_log(LOG_ERR, "unable to open shm for PPSI!\n");
exit(-1);
}
/* check ppsi's shm version */
if (ppsi_head->version != WRS_PPSI_SHMEM_VERSION) {
snmp_log(LOG_ERR, "unknown PPSI's shm version %i "
"(known is %i)\n",
ppsi_head->version, WRS_PPSI_SHMEM_VERSION);
exit(-1);
}
ppg = (void *)ppsi_head + ppsi_head->data_off;
ppsi_servo = wrs_shm_follow(ppsi_head, ppg->global_ext_data);
if (!ppsi_servo) {
snmp_log(LOG_ERR, "Cannot follow ppsi_servo in shmem.\n");
exit(-1);
}
}
static void init_shm_rtud(void)
{
/* open RTUd's shm */
rtud_head = wrs_shm_get(wrs_shm_rtu, "", WRS_SHM_READ);
if (!rtud_head) {
snmp_log(LOG_ERR, "unable to open shm for RTUd!\n");
exit(-1);
}
/* check rtud's shm version */
if (rtud_head->version != RTU_SHMEM_VERSION) {
snmp_log(LOG_ERR, "unknown RTUd's shm version %i "
"(known is %i)\n", rtud_head->version,
RTU_SHMEM_VERSION);
exit(-1);
}
}
void init_shm(void){
init_shm_hal();
init_shm_ppsi();
init_shm_rtud();
}
#ifndef WRS_SNMP_SHMEM_H
#define WRS_SNMP_SHMEM_H
#include <libwr/shmem.h>
#include <libwr/hal_shmem.h>
#include <ppsi/ppsi.h>
#include <libwr/hal_shmem.h>
#include <libwr/rtu_shmem.h>
/* HAL */
extern struct wrs_shm_head *hal_head;
extern struct hal_shmem_header *hal_shmem;
extern struct hal_port_state *hal_ports;
extern int hal_nports_local;
/* PPSI */
extern struct wrs_shm_head *ppsi_head;
extern struct wr_servo_state_t *ppsi_servo;
/* RTUd */
struct wrs_shm_head *rtud_head;
void init_shm();
#endif /* WRS_SNMP_SHMEM_H */
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2010 - 2013 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/* softpll_ng.h: public SoftPLL API header */
#ifndef __SOFTPLL_NG_H
#define __SOFTPLL_NG_H
#include <stdint.h>
/* SoftPLL operating modes, for mode parameter of spll_init(). */
/* Grand Master - lock to 10 MHz external reference */
#define SPLL_MODE_GRAND_MASTER 1
/* Free running master - 125 MHz refrence free running, DDMTD locked to it */
#define SPLL_MODE_FREE_RUNNING_MASTER 2
/* Slave mode - 125 MHz reference locked to one of the input clocks */
#define SPLL_MODE_SLAVE 3
/* Disabled mode: SoftPLL inactive */
#define SPLL_MODE_DISABLED 4
/* Shortcut for 'channels' parameter in various API functions to perform operation on all channels */
#define SPLL_ALL_CHANNELS 0xffffffff
/* Aux clock flags */
#define SPLL_AUX_ENABLED (1<<0) /* Locking the particular aux channel to the WR reference is enabled */
#define SPLL_AUX_LOCKED (1<<1) /* The particular aux clock is already locked to WR reference */
/* Phase detector types */
#define SPLL_PD_DDMTD 0
#define SPLL_PD_BANGBANG 1
/* Channels for spll_measure_frequency() */
#define SPLL_OSC_REF 0
#define SPLL_OSC_DMTD 1
#define SPLL_OSC_EXT 2
/* Note on channel naming:
- ref_channel means a PHY recovered clock input. There can be one (as in WR core) or more (WR switch).
- out_channel means an output channel, which represents PLL feedback signal from a local, tunable oscillator. Every SPLL implementation
has at least one output channel, connected to the 125 / 62.5 MHz transceiver (WR) reference. This channel has always
index 0 and is compared against all reference channels by the phase tracking mechanism.
*/
/* PUBLIC API */
/*
Initializes the SoftPLL to work in mode (mode). Extra parameters depend on choice of the mode:
- for SPLL_MODE_GRAND_MASTER: non-zero (align_pps) value enables realignment of the WR reference rising edge to the
rising edge of 10 MHz external clock that comes immediately after a PPS pulse
- for SPLL_MODE_SLAVE: (ref_channel) indicates the reference channel to which we are locking our PLL.
*/
void spll_init(int mode, int ref_channel, int align_pps);
/* Disables the SoftPLL and cleans up stuff */
void spll_shutdown();
/* Returns number of reference and output channels implemented in HW. */
void spll_get_num_channels(int *n_ref, int *n_out);
/* Starts locking output channel (out_channel) */
void spll_start_channel(int out_channel);
/* Stops locking output channel (out_channel) */
void spll_stop_channel(int out_channel);
/* Returns non-zero if output channel (out_channel) is locked to a WR reference */
int spll_check_lock(int out_channel);
/* Sets phase setpoint for given output channel. */
void spll_set_phase_shift(int out_channel, int32_t value_picoseconds);
/* Retreives the current phase shift and desired setpoint for given output channel */
void spll_get_phase_shift(int out_channel, int32_t *current, int32_t *target);
/* Returns non-zero if the given output channel is busy phase shifting to a new preset */
int spll_shifter_busy(int out_channel);
/* Returns phase detector type used by particular output channel. There are two phase detectors available:
- DDMTD: locks only 62.5 / 125 MHz. Provides independent phase shift control for each output.
- Bang-Bang: locks to any frequency that is a result of rational (M/N) multiplication of the reference frequency.
The frequency can be set by spll_set_aux_frequency(). BB detector follows phase setpoint of channel 0 (WR reference),
there is no per-output shift control.
*/
int spll_get_phase_detector_type(int out_channel);
/* Sets the aux clock freuency when a BB detector is in use.
Must be called prior to spll_start_channel(). If the frequency is out of available range,
returns negative value */
int spll_set_aux_frequency(int out_channel, int32_t frequency);
/* Enables/disables phase tracking on channel (ref_channel). Phase is always measured between
the WR local reference (out_channel 0) and ref_channel */
void spll_enable_ptracker(int ref_channel, int enable);
/* Reads tracked phase shift value for given reference channel */
int spll_read_ptracker(int ref_channel, int32_t *phase_ps, int *enabled);
/* Calls non-realtime update state machine. Must be called regularly (although
* it is not time-critical) in the main loop of the program if aux clocks or
* external reference are used in the design. */
void spll_update();
/* Returns the status of given aux clock output (SPLL_AUX_) */
int spll_get_aux_status(int out_channel);
const char *spll_get_aux_status_string(int channel);
/* Debug/testing functions */
/* Returns how many time the PLL has de-locked since last call of spll_init() */
int spll_get_delock_count();
void spll_show_stats(void);
/* Sets VCXO tuning DAC corresponding to output (out_channel) to a given value */
void spll_set_dac(int out_channel, int value);
/* Returns current DAC sample value for output (out_channel) */
int spll_get_dac(int out_channel);
void check_vco_frequencies();
/* info reported through .stat section */
struct spll_stats {
int magic; /* 0x5b1157a7 = SPLLSTAT ?;)*/
int ver; /* version of the structure */
int sequence; /* sequence number, so the host can retry */
int mode;
int irq_cnt;
int seq_state;
int align_state;
int H_lock;
int M_lock;
int H_y, M_y;
int del_cnt;
};
/* This only exists in wr-switch, but we should use it always */
extern struct spll_stats stats;
#endif // __SOFTPLL_NG_H
This diff is collapsed.
#ifndef WRS_BOOT_STATUS_GROUP_H
#define WRS_BOOT_STATUS_GROUP_H
#define WRSBOOTSTATUS_CACHE_TIMEOUT 5
#define WRSBOOTSTATUS_OID WRS_OID, 7, 1, 2
#define WRS_RESTART_REASON_ERROR 1 /* error */
#define WRS_CONFIG_SOURCE_HOST_LEN 64
#define WRS_CONFIG_SOURCE_FILENAME_LEN 128
#define WRS_CONFIG_SOURCE_PROTO_ERROR 1 /* error */
#define WRS_CONFIG_SOURCE_PROTO_ERROR_MINOR 2 /* warning */
#define WRS_CONFIG_SOURCE_PROTO_LOCAL 3 /* ok */
/* below proto are ok, if host and filename not empty */
#define WRS_CONFIG_SOURCE_PROTO_TFTP 4
#define WRS_CONFIG_SOURCE_PROTO_HTTP 5
#define WRS_CONFIG_SOURCE_PROTO_FTP 6
#define WRS_CONFIG_STATUS_OK 1 /* ok */
#define WRS_CONFIG_STATUS_ERROR 2 /* error */
#define WRS_CONFIG_STATUS_DL_ERROR 3 /* error */
#define WRS_CONFIG_STATUS_CHECK_ERROR 4 /* error */
#define WRS_CONFIG_STATUS_ERROR_MINOR 5 /* warning */
#define WRS_BOOT_HWINFO_OK 1 /* ok */
#define WRS_BOOT_HWINFO_ERROR 2 /* error */
#define WRS_BOOT_HWINFO_ERROR_MINOR 3 /* warning */
#define WRS_BOOT_HWINFO_WARNING 4 /* warning */
#define WRS_BOOT_LOAD_FPGA_OK 1 /* ok */
#define WRS_BOOT_LOAD_FPGA_ERROR 2 /* error */
#define WRS_BOOT_LOAD_FPGA_ERROR_MINOR 3 /* warning */
#define WRS_BOOT_LOAD_FPGA_FILE_NOT_FOUND 4 /* error */
#define WRS_BOOT_LOAD_LM32_OK 1 /* ok */
#define WRS_BOOT_LOAD_LM32_ERROR 2 /* error */
#define WRS_BOOT_LOAD_LM32_ERROR_MINOR 3 /* warning */
#define WRS_BOOT_LOAD_LM32_FILE_NOT_FOUND 4 /* error */
struct wrsBootStatus_s {
uint32_t wrsBootCnt; /* boots since power-on must be != 0 */
uint32_t wrsRebootCnt; /* soft reboots since hard reboot
* (i.e. caused by reset button) */
int32_t wrsRestartReason; /* reason of last restart */
char wrsFaultIP[11]; /* faulty instruction pointer as string */
char wrsFaultLR[11]; /* link register at fault as string */
int32_t wrsConfigSource;
char wrsConfigSourceHost[WRS_CONFIG_SOURCE_HOST_LEN+1];
char wrsConfigSourceFilename[WRS_CONFIG_SOURCE_FILENAME_LEN+1];
int32_t wrsBootConfigStatus;
int32_t wrsBootHwinfoReadout;
int32_t wrsBootLoadFPGA;
int32_t wrsBootLoadLM32;
int32_t wrsBootKernelModulesMissing;
int32_t wrsBootUserspaceDaemonsMissing;
};
extern struct wrsBootStatus_s wrsBootStatus_s;
time_t wrsBootStatus_data_fill(void);
void init_wrsBootStatusGroup(void);
#endif /* WRS_BOOT_STATUS_GROUP_H */
#include "wrsSnmp.h"
#include "wrsCurrentTimeGroup.h"
#include "snmp_mmap.h"
/* defines for nic-hardware.h */
#define WR_SWITCH
#define WR_IS_NODE 0
#define WR_IS_SWITCH 1
#include "../../kernel/wr_nic/nic-hardware.h"
#include "../../kernel/wbgen-regs/ppsg-regs.h"
static struct PPSG_WB *pps;
static struct pickinfo wrsCurrentTime_pickinfo[] = {
FIELD(wrsCurrentTime_s, ASN_COUNTER64, wrsDateTAI),
FIELD(wrsCurrentTime_s, ASN_OCTET_STR, wrsDateTAIString),
};
struct wrsCurrentTime_s wrsCurrentTime_s;
time_t wrsCurrentTime_data_fill(void)
{
static time_t time_update;
time_t time_cur;
unsigned long utch, utcl, tmp1, tmp2;
time_t t;
struct tm tm;
uint64_t wrs_d_current_64;
time_cur = time(NULL);
if (time_update
&& time_cur - time_update < WRSCURRENTTIME_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
return time_update;
}
time_update = time_cur;
memset(&wrsCurrentTime_s, 0, sizeof(wrsCurrentTime_s));
/* get TAI time from FPGA */
if (!pps) /* first time, map the fpga space */
pps = create_map(FPGA_BASE_PPSG, sizeof(*pps));
if (!pps) {
wrs_d_current_64 = 0;
strcpy(wrsCurrentTime_s.wrsDateTAIString,
"0000-00-00-00:00:00 (failed)");
return time_update;
}
do {
utch = pps->CNTR_UTCHI;
utcl = pps->CNTR_UTCLO;
tmp1 = pps->CNTR_UTCHI;
tmp2 = pps->CNTR_UTCLO;
} while ((tmp1 != utch) || (tmp2 != utcl));
wrs_d_current_64 = (uint64_t)(utch) << 32 | utcl;
/*
* WARNING: the current snmpd is bugged: it has
* endianness problems with 64 bit, and the two
* halves are swapped. So pre-swap them here
*/
wrsCurrentTime_s.wrsDateTAI =
(wrs_d_current_64 << 32) | (wrs_d_current_64 >> 32);
t = wrs_d_current_64;
localtime_r(&t, &tm);
strftime(wrsCurrentTime_s.wrsDateTAIString,
sizeof(wrsCurrentTime_s.wrsDateTAIString),
"%Y-%m-%d-%H:%M:%S", &tm);
/* there was an update, return current time */
return time_update;
}
#define GT_OID WRSCURRENTTIME_OID
#define GT_PICKINFO wrsCurrentTime_pickinfo
#define GT_DATA_FILL_FUNC wrsCurrentTime_data_fill
#define GT_DATA_STRUCT wrsCurrentTime_s
#define GT_GROUP_NAME "wrsCurrentTimeGroup"
#define GT_INIT_FUNC init_wrsCurrentTimeGroup
#include "wrsGroupTemplate.h"
#ifndef WRS_CURRENT_TIME_GROUP_H
#define WRS_CURRENT_TIME_GROUP_H
#define WRSCURRENTTIME_CACHE_TIMEOUT 5
#define WRSCURRENTTIME_OID WRS_OID, 7, 1, 1
struct wrsCurrentTime_s {
uint64_t wrsDateTAI; /* current time in TAI */
char wrsDateTAIString[32]; /* current time in TAI as string */
};
extern struct wrsCurrentTime_s wrsCurrentTime_s;
time_t wrsCurrentTime_data_fill(void);
void init_wrsCurrentTimeGroup(void);
#endif /* WRS_CURRENT_TIME_GROUP_H */
/*
* White Rabbit Switch date. This is two changing values
*
* 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 <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "wrsSnmp.h"
/* defines for nic-hardware.h */
#define WR_SWITCH
#define WR_IS_NODE 0
#define WR_IS_SWITCH 1
#include "../../kernel/wr_nic/nic-hardware.h"
#include "../../kernel/wbgen-regs/ppsg-regs.h"
static struct PPSG_WB *pps;
static uint64_t wrs_d_current_64;
static char wrs_d_current_string[32];
/* FIXME: this is copied from wr_date, should be librarized */
void *create_map(unsigned long address, unsigned long size)
{
unsigned long ps = getpagesize();
unsigned long offset, fragment, len;
void *mapaddr;
int fd;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0)
return NULL;
offset = address & ~(ps - 1);
fragment = address & (ps - 1);
len = address + size - offset;
mapaddr = mmap(0, len, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, offset);
close(fd);
if (mapaddr == MAP_FAILED)
return NULL;
return mapaddr + fragment;
}
static void wrs_d_get(void)
{
unsigned long utch, utcl, tmp1, tmp2;
time_t t;
struct tm tm;
if (!pps) /* first time, map the fpga space */
pps = create_map(FPGA_BASE_PPSG, sizeof(*pps));
if (!pps) {
wrs_d_current_64 = 0;
strcpy(wrs_d_current_string, "0000-00-00-00:00:00 (failed)");
return;
}
do {
utch = pps->CNTR_UTCHI;
utcl = pps->CNTR_UTCLO;
tmp1 = pps->CNTR_UTCHI;
tmp2 = pps->CNTR_UTCLO;
} while ((tmp1 != utch) || (tmp2 != utcl));
wrs_d_current_64 = (uint64_t)(utch) << 32 | utcl;
t = wrs_d_current_64;
localtime_r(&t, &tm);
strftime(wrs_d_current_string,
sizeof(wrs_d_current_string), "%Y-%m-%d-%H:%M:%S", &tm);
}
static int date_group(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
oid obj; /* actually, an integer, i.e. the final index */
switch (reqinfo->mode) {
case MODE_GET:
wrs_d_get();
/*
* WARNING: the current snmpd is bugged: it has
* endianness problems with 64 bit, and the two
* halves are swapped. So pre-swap them here
*/
wrs_d_current_64 =
(wrs_d_current_64 << 32) | (wrs_d_current_64 >> 32);
/* "- 2" because last is 0 for all scalars, I suppose */
obj = requests->requestvb->name[
requests->requestvb->name_length - 2
];
if (obj == 1) /* number */
snmp_set_var_typed_value(requests->requestvb,
ASN_COUNTER64,
&wrs_d_current_64,
sizeof(wrs_d_current_64));
else /* string */
snmp_set_var_typed_value(requests->requestvb,
ASN_OCTET_STR,
wrs_d_current_string,
strlen(wrs_d_current_string));
break;
default:
snmp_log(LOG_ERR, "unknown mode (%d) in wrs date group\n",
reqinfo->mode);
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
void
init_wrsDate(void)
{
const oid wrsDate_oid[] = { WRS_OID, 5 };
netsnmp_handler_registration *hreg;
/* do the registration */
hreg = netsnmp_create_handler_registration(
"wrsDate", date_group,
wrsDate_oid, OID_LENGTH(wrsDate_oid),
HANDLER_CAN_RONLY);
netsnmp_register_scalar_group(
hreg, 1 /* min */, 2 /* max */);
}
#include "wrsSnmp.h"
#include "wrsOSStatusGroup.h"
#include "wrsNetworkingStatusGroup.h"
#include "wrsGeneralStatusGroup.h"
static struct pickinfo wrsGeneralStatus_pickinfo[] = {
FIELD(wrsGeneralStatus_s, ASN_INTEGER, wrsMainSystemStatus),
FIELD(wrsGeneralStatus_s, ASN_INTEGER, wrsOSStatus),
FIELD(wrsGeneralStatus_s, ASN_INTEGER, wrsTimingStatus),
FIELD(wrsGeneralStatus_s, ASN_INTEGER, wrsNetworkingStatus),
};
struct wrsGeneralStatus_s wrsGeneralStatus_s;
time_t wrsGeneralStatus_data_fill(void)
{
static time_t time_update; /* time of last update */
time_t time_osstatus; /* time when wrsOSStatus data was updated */
time_t time_networking_status; /* time when wrsNetworkingStatus data
* was updated */
struct wrsOSStatus_s *o;
struct wrsNetworkingStatus_s *n;
struct wrsGeneralStatus_s *g;
time_osstatus = wrsOSStatus_data_fill();
time_networking_status = wrsNetworkingStatus_data_fill();
if (time_osstatus <= time_update
&& time_networking_status <= time_update) {
/* cache not updated, return last update time */
snmp_log(LOG_ERR,
"SNMP: wrsGeneralStatusGroup cache\n");
return time_update;
}
memset(&wrsGeneralStatus_s, 0, sizeof(wrsGeneralStatus_s));
/*********************************************************************\
|**************************** wrsOSStatus ****************************|
\*********************************************************************/
o = &wrsOSStatus_s;
if ( /* check if error */
o->wrsBootSuccessful == WRS_BOOT_SUCCESSFUL_ERROR
) {
wrsGeneralStatus_s.wrsOSStatus = WRS_OS_STATUS_ERROR;
} else if ( /* check if warning */
o->wrsBootSuccessful == WRS_BOOT_SUCCESSFUL_WARNING
|| o->wrsTemperatureWarning == WRS_TEMPERATURE_WARNING_THOLD_NOT_SET
|| o->wrsTemperatureWarning == WRS_TEMPERATURE_WARNING_TOO_HIGH
) { /* warning */
wrsGeneralStatus_s.wrsOSStatus = WRS_OS_STATUS_WARNING;
} else if ( /* check if any of fields equal to 0 or WARNING_NA */
o->wrsBootSuccessful == WRS_BOOT_SUCCESSFUL_WARNING_NA
|| o->wrsBootSuccessful == 0
|| o->wrsTemperatureWarning == 0
) { /* warning NA */
wrsGeneralStatus_s.wrsOSStatus = WRS_OS_STATUS_WARNING_NA;
} else if ( /* check if OK */
o->wrsBootSuccessful == WRS_BOOT_SUCCESSFUL_OK
&& o->wrsTemperatureWarning == WRS_TEMPERATURE_WARNING_OK
) { /* OK */
wrsGeneralStatus_s.wrsOSStatus = WRS_OS_STATUS_OK;
} else { /* probably bug in previous conditions,
* this should never happen */
wrsGeneralStatus_s.wrsOSStatus = WRS_OS_STATUS_BUG;
}
/*********************************************************************\
|************************** wrsTimingStatus **************************|
\*********************************************************************/
/* not implemented, always return OK */
wrsGeneralStatus_s.wrsTimingStatus = WRS_TIMING_STATUS_OK;
/*********************************************************************\
|************************ wrsNetworkingStatus ************************|
\*********************************************************************/
n = &wrsNetworkingStatus_s;
if ( /* check if error */
n->wrsSFPsStatus == WRS_SFPS_STATUS_ERROR
|| n->wrsEndpointStatus == WRS_ENDPOINT_STATUS_ERROR
|| n->wrsSwcoreStatus == WRS_SWCORE_STATUS_ERROR
|| n->wrsRTUStatus == WRS_RTU_STATUS_ERROR
) {
wrsGeneralStatus_s.wrsNetworkingStatus =
WRS_NETWORKING_STATUS_ERROR;
} else if ( /* check if warning */
n->wrsSFPsStatus == WRS_SFPS_STATUS_WARNING
) { /* warning */
wrsGeneralStatus_s.wrsNetworkingStatus =
WRS_NETWORKING_STATUS_WARNING;
} else if ( /* check if any of fields equal to 0 or WARNING_NA */
n->wrsSFPsStatus == WRS_SFPS_STATUS_WARNING_NA
|| n->wrsSFPsStatus == 0
|| n->wrsEndpointStatus == 0
|| n->wrsSwcoreStatus == 0
|| n->wrsRTUStatus == 0
) { /* warning NA */
wrsGeneralStatus_s.wrsNetworkingStatus =
WRS_NETWORKING_STATUS_WARNING_NA;
} else if ( /* check if OK, FR (first read) is also ok */
n->wrsSFPsStatus == WRS_SFPS_STATUS_OK
&& (n->wrsEndpointStatus == WRS_ENDPOINT_STATUS_OK
|| n->wrsEndpointStatus == WRS_ENDPOINT_STATUS_FR) /* FR*/
&& (n->wrsSwcoreStatus == WRS_SWCORE_STATUS_OK
|| n->wrsSwcoreStatus == WRS_SWCORE_STATUS_FR) /* FR */
&& (n->wrsRTUStatus == WRS_RTU_STATUS_OK
|| n->wrsRTUStatus == WRS_RTU_STATUS_FR) /* FR */
) { /* OK */
wrsGeneralStatus_s.wrsNetworkingStatus =
WRS_NETWORKING_STATUS_OK;
} else { /* probably bug in previous conditions,
* this should never happen */
wrsGeneralStatus_s.wrsNetworkingStatus =
WRS_NETWORKING_STATUS_BUG;
}
/*********************************************************************\
|************************ wrsMainSystemStatus ************************|
\*********************************************************************/
/* update at the end of this group to have latest results of other
* statuses */
g = &wrsGeneralStatus_s;
if ( /* check if error */
g->wrsOSStatus == WRS_OS_STATUS_ERROR
|| g->wrsTimingStatus == WRS_TIMING_STATUS_ERROR
|| g->wrsNetworkingStatus == WRS_NETWORKING_STATUS_ERROR
) {
wrsGeneralStatus_s.wrsMainSystemStatus =
WRS_MAIN_SYSTEM_STATUS_ERROR;
} else if ( /* check if warning */
g->wrsOSStatus == WRS_OS_STATUS_WARNING
|| g->wrsTimingStatus == WRS_TIMING_STATUS_WARNING
|| g->wrsNetworkingStatus == WRS_NETWORKING_STATUS_WARNING
) { /* warning */
wrsGeneralStatus_s.wrsMainSystemStatus =
WRS_MAIN_SYSTEM_STATUS_WARNING;
} else if ( /* check if any of fields equal to 0 or WARNING_NA */
g->wrsOSStatus == WRS_OS_STATUS_WARNING_NA
|| g->wrsOSStatus == 0
|| g->wrsTimingStatus == WRS_TIMING_STATUS_WARNING_NA
|| g->wrsTimingStatus == 0
|| g->wrsNetworkingStatus == WRS_NETWORKING_STATUS_WARNING_NA
|| g->wrsNetworkingStatus == 0
) { /* warning NA */
wrsGeneralStatus_s.wrsMainSystemStatus =
WRS_MAIN_SYSTEM_STATUS_WARNING_NA;
} else if ( /* check if OK */
g->wrsOSStatus == WRS_OS_STATUS_OK
&& g->wrsTimingStatus == WRS_TIMING_STATUS_OK
&& g->wrsNetworkingStatus == WRS_NETWORKING_STATUS_OK
) { /* OK */
wrsGeneralStatus_s.wrsMainSystemStatus =
WRS_MAIN_SYSTEM_STATUS_OK;
} else { /* probably bug in previous conditions,
* this should never happen */
wrsGeneralStatus_s.wrsMainSystemStatus =
WRS_MAIN_SYSTEM_STATUS_BUG;
}
time_update = time(NULL);
/* there was an update, return current time */
return time_update;
}
#define GT_OID WRSGENERALSTATUS_OID
#define GT_PICKINFO wrsGeneralStatus_pickinfo
#define GT_DATA_FILL_FUNC wrsGeneralStatus_data_fill
#define GT_DATA_STRUCT wrsGeneralStatus_s
#define GT_GROUP_NAME "wrsGeneralStatusGroup"
#define GT_INIT_FUNC init_wrsGeneralStatusGroup
#include "wrsGroupTemplate.h"
#ifndef WRS_GENERAL_STATUS_GROUP_H
#define WRS_GENERAL_STATUS_GROUP_H
#define WRSGENERALSTATUS_OID WRS_OID, 6, 1
#define WRS_MAIN_SYSTEM_STATUS_OK 1 /* ok */
#define WRS_MAIN_SYSTEM_STATUS_ERROR 2 /* error */
#define WRS_MAIN_SYSTEM_STATUS_WARNING 3 /* warning */
#define WRS_MAIN_SYSTEM_STATUS_WARNING_NA 4 /* warning, at least one field is
* equal to 0 (NA),shouldn't happen in
* normal operation */
#define WRS_MAIN_SYSTEM_STATUS_BUG 5 /* warning */
#define WRS_OS_STATUS_OK 1 /* ok */
#define WRS_OS_STATUS_ERROR 2 /* error */
#define WRS_OS_STATUS_WARNING 3 /* warning */
#define WRS_OS_STATUS_WARNING_NA 4 /* warning, at least one field is
* equal to 0 (NA),shouldn't happen in
* normal operation */
#define WRS_OS_STATUS_BUG 5 /* warning */
#define WRS_TIMING_STATUS_OK 1 /* ok */
#define WRS_TIMING_STATUS_ERROR 2 /* error */
#define WRS_TIMING_STATUS_WARNING 3 /* warning */
#define WRS_TIMING_STATUS_WARNING_NA 4 /* warning, at least one field is
* equal to 0 (NA),shouldn't happen in
* normal operation */
#define WRS_TIMING_STATUS_BUG 5 /* warning */
#define WRS_NETWORKING_STATUS_OK 1 /* ok */
#define WRS_NETWORKING_STATUS_ERROR 2 /* error */
#define WRS_NETWORKING_STATUS_WARNING 3 /* warning */
#define WRS_NETWORKING_STATUS_WARNING_NA 4 /* warning, at least one field is
* equal to 0 (NA),shouldn't happen in
* normal operation */
#define WRS_NETWORKING_STATUS_BUG 5 /* warning */
struct wrsGeneralStatus_s {
int wrsMainSystemStatus;
int wrsOSStatus;
int wrsTimingStatus;
int wrsNetworkingStatus;
};
extern struct wrsGeneralStatus_s wrsGeneralStatus_s;
time_t wrsGeneralStatus_data_fill(void);
void init_wrsGeneralStatusGroup(void);
#endif /* WRS_GENERAL_STATUS_GROUP_H */
static int group_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
int obj; /* the final index */
struct pickinfo *pi;
void *ptr;
int len;
/*
* Retrieve information from ppsi itself. But this function
* is called once for every item, so only query the whole set
* once every 2 seconds.
*/
GT_DATA_FILL_FUNC();
switch (reqinfo->mode) {
case MODE_GET:
/* "- 2" because last is 0 for all scalars, I suppose */
obj = requests->requestvb->name[
requests->requestvb->name_length - 2];
obj--; /* we are 0-based */
if (obj < 0 || obj >= ARRAY_SIZE(GT_PICKINFO)) {
snmp_log(LOG_ERR,
"wrong index (%d) in "GT_GROUP_NAME"\n",
obj + 1);
return SNMP_ERR_GENERR;
}
pi = GT_PICKINFO + obj;
ptr = (void *)&GT_DATA_STRUCT + pi->offset;
len = pi->len;
if (len > 8) /* special case for strings */
len = strnlen(ptr, len);
snmp_set_var_typed_value(requests->requestvb,
pi->type, ptr, len);
break;
default:
snmp_log(LOG_ERR, "unknown mode (%d) in "GT_GROUP_NAME"\n",
reqinfo->mode);
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
/* init function */
void GT_INIT_FUNC(void)
{
const oid wrsGT_oid[] = { GT_OID };
netsnmp_handler_registration *hreg;
/* do the registration for the scalars/globals */
hreg = netsnmp_create_handler_registration(
GT_GROUP_NAME, group_handler,
wrsGT_oid, OID_LENGTH(wrsGT_oid),
HANDLER_CAN_RONLY);
netsnmp_register_scalar_group(
hreg, 1 /* min */, ARRAY_SIZE(GT_PICKINFO) /* max */);
}
This diff is collapsed.
#ifndef WRS_NETWORKING_STATUS_GROUP_H
#define WRS_NETWORKING_STATUS_GROUP_H
#define WRSNETWORKINGSTATUS_OID WRS_OID, 6, 2, 3
#define FORWARD_DELTA 5
#define WRS_SFPS_STATUS_OK 1 /* ok */
#define WRS_SFPS_STATUS_ERROR 2 /* error */
#define WRS_SFPS_STATUS_WARNING 3 /* warning, not used */
#define WRS_SFPS_STATUS_WARNING_NA 4 /* warning, at least one field is
* equal to 0 (NA),shouldn't happen in
* normal operation */
#define WRS_SFPS_STATUS_BUG 5 /* warning */
#define WRS_ENDPOINT_STATUS_FR 1 /* ok, first read */
#define WRS_ENDPOINT_STATUS_OK 2 /* ok */
#define WRS_ENDPOINT_STATUS_ERROR 3 /* error */
#define WRS_SWCORE_STATUS_FR 1 /* ok, first read */
#define WRS_SWCORE_STATUS_OK 2 /* ok */
#define WRS_SWCORE_STATUS_ERROR 3 /* error */
#define WRS_RTU_STATUS_FR 1 /* ok, first read */
#define WRS_RTU_STATUS_OK 2 /* ok */
#define WRS_RTU_STATUS_ERROR 3 /* error */
struct wrsNetworkingStatus_s {
int wrsSFPsStatus;
int wrsEndpointStatus;
int wrsSwcoreStatus;
int wrsRTUStatus;
};
extern struct wrsNetworkingStatus_s wrsNetworkingStatus_s;
time_t wrsNetworkingStatus_data_fill(void);
void init_wrsNetworkingStatusGroup(void);
struct ns_pstats {
/* wrsEndpointStatus */
uint32_t TXUnderrun; /* 1 */
uint32_t RXOverrun; /* 2 */
uint32_t RXInvalidCode; /* 3 */
uint32_t RXSyncLost; /* 4 */
uint32_t RXPfilterDropped; /* 6 */
uint32_t RXPCSErrors; /* 7 */
uint32_t RXCRCErrors; /* 10 */
/* wrsSwcoreStatus */
/* Too much HP traffic / Per-priority queue full */
uint32_t RXFrames; /* 20 */
uint32_t RXPrio0; /* 22 */
uint32_t RXPrio1; /* 23 */
uint32_t RXPrio2; /* 24 */
uint32_t RXPrio3; /* 25 */
uint32_t RXPrio4; /* 26 */
uint32_t RXPrio5; /* 27 */
uint32_t RXPrio6; /* 28 */
uint32_t RXPrio7; /* 29 */
uint32_t FastMatchPriority; /* 33 */
/* wrsRTUStatus */
uint32_t RXDropRTUFull; /* 21 */
};
/* parameters read from dot-config */
struct wrsNetworkingStatus_config {
int hp_frame_rate;
int rx_frame_rate;
int rx_prio_frame_rate;
};
#endif /* WRS_NETWORKING_STATUS_GROUP_H */
#include "wrsSnmp.h"
#include "wrsBootStatusGroup.h"
#include "wrsTemperatureGroup.h"
#include "wrsOSStatusGroup.h"
static struct pickinfo wrsOSStatus_pickinfo[] = {
FIELD(wrsOSStatus_s, ASN_INTEGER, wrsBootSuccessful),
FIELD(wrsOSStatus_s, ASN_INTEGER, wrsTemperatureWarning),
};
struct wrsOSStatus_s wrsOSStatus_s;
time_t wrsOSStatus_data_fill(void)
{
static time_t time_update; /* time of last update */
time_t time_temp; /* time when temperature data was updated */
time_t time_boot; /* time when boot data was updated */
struct wrsBootStatus_s *b;
time_boot = wrsBootStatus_data_fill();
time_temp = wrsTemperature_data_fill();
if (time_boot <= time_update
&& time_temp <= time_update) {
/* cache not updated, return last update time */
return time_update;
}
time_update = time(NULL);
memset(&wrsOSStatus_s, 0, sizeof(wrsOSStatus_s));
/*********************************************************************\
|************************* wrsBootSuccessful *************************|
\*********************************************************************/
b = &wrsBootStatus_s;
if ( /* check if error */
b->wrsBootCnt == 0
|| b->wrsRestartReason == WRS_RESTART_REASON_ERROR
|| b->wrsConfigSource == WRS_CONFIG_SOURCE_PROTO_ERROR
|| b->wrsBootConfigStatus == WRS_CONFIG_STATUS_ERROR
|| b->wrsBootConfigStatus == WRS_CONFIG_STATUS_DL_ERROR
|| b->wrsBootConfigStatus == WRS_CONFIG_STATUS_CHECK_ERROR
|| b->wrsBootHwinfoReadout == WRS_BOOT_HWINFO_ERROR
|| b->wrsBootLoadFPGA == WRS_BOOT_LOAD_FPGA_ERROR
|| b->wrsBootLoadFPGA == WRS_BOOT_LOAD_FPGA_FILE_NOT_FOUND
|| b->wrsBootLoadLM32 == WRS_BOOT_LOAD_LM32_ERROR
|| b->wrsBootLoadLM32 == WRS_BOOT_LOAD_LM32_FILE_NOT_FOUND
|| b->wrsBootKernelModulesMissing > 0 /* contain number of missing modules */
|| b->wrsBootUserspaceDaemonsMissing > 0 /* contain number of missing deamons */
) {
wrsOSStatus_s.wrsBootSuccessful = WRS_BOOT_SUCCESSFUL_ERROR;
} else if ( /* check if warning */
b->wrsConfigSource == WRS_CONFIG_SOURCE_PROTO_ERROR_MINOR
|| b->wrsBootConfigStatus == WRS_CONFIG_STATUS_ERROR_MINOR
|| b->wrsBootHwinfoReadout == WRS_BOOT_HWINFO_ERROR_MINOR
|| b->wrsBootHwinfoReadout == WRS_BOOT_HWINFO_WARNING
|| b->wrsBootLoadFPGA == WRS_BOOT_LOAD_FPGA_ERROR_MINOR
|| b->wrsBootLoadLM32 == WRS_BOOT_LOAD_LM32_ERROR_MINOR
) { /* warning */
wrsOSStatus_s.wrsBootSuccessful = WRS_BOOT_SUCCESSFUL_WARNING;
} else if ( /* check if any of fields equal to 0 */
b->wrsRestartReason == 0
|| b->wrsConfigSource == 0
|| b->wrsBootConfigStatus == 0
|| b->wrsBootHwinfoReadout == 0
|| b->wrsBootLoadFPGA == 0
|| b->wrsBootLoadLM32 == 0
) { /* warning NA */
wrsOSStatus_s.wrsBootSuccessful = WRS_BOOT_SUCCESSFUL_WARNING_NA;
} else if ( /* check if OK */
b->wrsBootCnt != 0
&& b->wrsRestartReason != WRS_RESTART_REASON_ERROR
&& b->wrsConfigSource != WRS_CONFIG_SOURCE_PROTO_ERROR
&& b->wrsConfigSource != WRS_CONFIG_SOURCE_PROTO_ERROR_MINOR /* warning */
&& b->wrsBootConfigStatus == WRS_CONFIG_STATUS_OK
&& b->wrsBootHwinfoReadout == WRS_BOOT_HWINFO_OK
&& b->wrsBootLoadFPGA == WRS_BOOT_LOAD_FPGA_OK
&& b->wrsBootLoadLM32 == WRS_BOOT_LOAD_LM32_OK
&& b->wrsBootKernelModulesMissing == 0
&& b->wrsBootUserspaceDaemonsMissing == 0
) { /* OK, but check source */
/* additional check of source */
if (
b->wrsConfigSource == WRS_CONFIG_SOURCE_PROTO_LOCAL
|| (
(
b->wrsConfigSource == WRS_CONFIG_SOURCE_PROTO_TFTP
|| b->wrsConfigSource == WRS_CONFIG_SOURCE_PROTO_HTTP
|| b->wrsConfigSource == WRS_CONFIG_SOURCE_PROTO_FTP
)
&& strnlen(b->wrsConfigSourceHost, WRS_CONFIG_SOURCE_HOST_LEN + 1)
&& strnlen(b->wrsConfigSourceFilename, WRS_CONFIG_SOURCE_FILENAME_LEN + 1)
)
) { /* OK */
/* when dotconfig is local or (remote and host not empty and filename not empty) */
wrsOSStatus_s.wrsBootSuccessful = WRS_BOOT_SUCCESSFUL_OK;
} else { /* error because of source */
wrsOSStatus_s.wrsBootSuccessful = WRS_BOOT_SUCCESSFUL_ERROR;
}
} else { /* probably bug in previous conditions,
* this should never happen */
wrsOSStatus_s.wrsBootSuccessful = WRS_BOOT_SUCCESSFUL_BUG;
}
/*********************************************************************\
|*********************** wrsTemperatureWarning ***********************|
\*********************************************************************/
if (!wrsTemperature_s.temp_fpga_thold
&& !wrsTemperature_s.temp_pll_thold
&& !wrsTemperature_s.temp_psl_thold
&& !wrsTemperature_s.temp_psr_thold) {
/* no threshold are set */
wrsOSStatus_s.wrsTemperatureWarning =
WRS_TEMPERATURE_WARNING_THOLD_NOT_SET;
} else {
/* rise warning when at least one threshold level
* is exceeded, add 2, since 0 is readings not available, 1 is
* no threshold set (WRS_TEMPERATURE_WARNING_THOLD_NOT_SET)
* 2 is ok (WRS_TEMPERATURE_WARNING_OK), 3 is temperature too
* high (WRS_TEMPERATURE_WARNING_TOO_HIGH) */
wrsOSStatus_s.wrsTemperatureWarning = 2 +
((wrsTemperature_s.temp_fpga > wrsTemperature_s.temp_fpga_thold)
|| (wrsTemperature_s.temp_pll > wrsTemperature_s.temp_pll_thold)
|| (wrsTemperature_s.temp_psl > wrsTemperature_s.temp_psl_thold)
|| (wrsTemperature_s.temp_psr > wrsTemperature_s.temp_psr_thold));
}
/* there was an update, return current time */
return time_update;
}
#define GT_OID WRSOSSTATUS_OID
#define GT_PICKINFO wrsOSStatus_pickinfo
#define GT_DATA_FILL_FUNC wrsOSStatus_data_fill
#define GT_DATA_STRUCT wrsOSStatus_s
#define GT_GROUP_NAME "wrsOSStatusGroup"
#define GT_INIT_FUNC init_wrsOSStatusGroup
#include "wrsGroupTemplate.h"
#ifndef WRS_OSSTATUS_GROUP_H
#define WRS_OSSTATUS_GROUP_H
#define WRSOSSTATUS_OID WRS_OID, 6, 2, 1
#define WRS_BOOT_SUCCESSFUL_OK 1 /* ok */
#define WRS_BOOT_SUCCESSFUL_ERROR 2 /* error */
#define WRS_BOOT_SUCCESSFUL_WARNING 3 /* warning */
#define WRS_BOOT_SUCCESSFUL_WARNING_NA 4 /* warning, at least one field is
* equal to 0 (NA),shouldn't happen in
* normal operation */
#define WRS_BOOT_SUCCESSFUL_BUG 5 /* warning */
#define WRS_TEMPERATURE_WARNING_THOLD_NOT_SET 1 /* warning */
#define WRS_TEMPERATURE_WARNING_OK 2 /* ok */
#define WRS_TEMPERATURE_WARNING_TOO_HIGH 3 /* warning */
struct wrsOSStatus_s {
int wrsBootSuccessful;
int wrsTemperatureWarning;
};
extern struct wrsOSStatus_s wrsOSStatus_s;
time_t wrsOSStatus_data_fill(void);
void init_wrsOSStatusGroup(void);
#endif /* WRS_OSSTATUS_GROUP_H */
#include "wrsSnmp.h"
#include "snmp_shmem.h"
#include "wrsPortStatusTable.h"
/* Our data: per-port information */
struct wrsPortStatusTable_s wrsPortStatusTable_array[WRS_N_PORTS];
static struct pickinfo wrsPortStatusTable_pickinfo[] = {
FIELD(wrsPortStatusTable_s, ASN_UNSIGNED, index), /* not reported */
FIELD(wrsPortStatusTable_s, ASN_OCTET_STR, port_name),
FIELD(wrsPortStatusTable_s, ASN_INTEGER, link_up),
FIELD(wrsPortStatusTable_s, ASN_INTEGER, port_mode),
FIELD(wrsPortStatusTable_s, ASN_INTEGER, port_locked),
FIELD(wrsPortStatusTable_s, ASN_OCTET_STR, peer_id),
FIELD(wrsPortStatusTable_s, ASN_OCTET_STR, sfp_vn),
FIELD(wrsPortStatusTable_s, ASN_OCTET_STR, sfp_pn),
FIELD(wrsPortStatusTable_s, ASN_OCTET_STR, sfp_vs),
FIELD(wrsPortStatusTable_s, ASN_INTEGER, sfp_in_db),
FIELD(wrsPortStatusTable_s, ASN_INTEGER, sfp_GbE),
FIELD(wrsPortStatusTable_s, ASN_INTEGER, sfp_error),
};
time_t wrsPortStatusTable_data_fill(unsigned int *n_rows)
{
unsigned ii, i;
unsigned retries = 0;
static time_t time_update;
time_t time_cur;
/* number of rows does not change for wrsPortStatusTable */
if (n_rows)
*n_rows = WRS_N_PORTS;
time_cur = time(NULL);
if (time_update
&& time_cur - time_update < WRSPORTSTATUSTABLE_CACHE_TIMEOUT) {
/* cache not updated, return last update time */
return time_update;
}
time_update = time_cur;
/* read data, with the sequential lock to have all data consistent */
struct hal_port_state *port_state;
memset(wrsPortStatusTable_array, 0, sizeof(wrsPortStatusTable_array));
while (1) {
ii = wrs_shm_seqbegin(hal_head);
for (i = 0; i < hal_nports_local; ++i) {
/* Assume that number of ports does not change between
* reads */
snprintf(wrsPortStatusTable_array[i].port_name, 10,
"wr%d", i);
port_state = hal_lookup_port(hal_ports,
hal_nports_local,
wrsPortStatusTable_array[i].port_name);
/* No need to copy all ports structures, only what
* we're interested in.
* Keep value 0 for Not available */
wrsPortStatusTable_array[i].link_up =
1 + state_up(port_state->state);
wrsPortStatusTable_array[i].port_mode =
port_state->mode;
if (port_state->state == HAL_PORT_STATE_DISABLED) {
wrsPortStatusTable_array[i].sfp_error =
WRS_PORT_STATUS_SFP_ERROR_PORT_DOWN;
/* if port is disabled don't fill
* other fields */
continue;
}
/* Keep value 0 for Not available */
wrsPortStatusTable_array[i].port_locked =
1 + port_state->locked;
/* FIXME: get real peer_id */
memset(&wrsPortStatusTable_array[i].peer_id, 0xff,
sizeof(ClockIdentity));
wrsPortStatusTable_array[i].sfp_in_db =
port_state->calib.sfp.flags & SFP_FLAG_IN_DB ? 2 : 1;
wrsPortStatusTable_array[i].sfp_GbE =
port_state->calib.sfp.flags & SFP_FLAG_1GbE ? 2 : 1;
strncpy(wrsPortStatusTable_array[i].sfp_vn,
port_state->calib.sfp.vendor_name,
sizeof(wrsPortStatusTable_array[i].sfp_vn));
strncpy(wrsPortStatusTable_array[i].sfp_pn,
port_state->calib.sfp.part_num,
sizeof(wrsPortStatusTable_array[i].sfp_pn));
strncpy(wrsPortStatusTable_array[i].sfp_vs,
port_state->calib.sfp.vendor_serial,
sizeof(wrsPortStatusTable_array[i].sfp_vs));
/* sfp error when SFP is not 1 GbE or
* (port is not wr-non mode and sfp not in data base)
* Keep value 0 for Not available
* sfp ok is 1 (WRS_PORT_STATUS_SFP_ERROR_SFP_OK)
* sfp error is 2 WRS_PORT_STATUS_SFP_ERROR_SFP_ERROR
* port down, set above, is 3
* (WRS_PORT_STATUS_SFP_ERROR_PORT_DOWN) */
wrsPortStatusTable_array[i].sfp_error = 1 +
((wrsPortStatusTable_array[i].sfp_GbE == 1) ||
((port_state->mode != HEXP_PORT_MODE_NON_WR) &&
(wrsPortStatusTable_array[i].sfp_in_db == 1)));
logmsg("reading ports name %s link %d, mode %d, "
"locked %d\n", port_state->name,
wrsPortStatusTable_array[i].link_up,
wrsPortStatusTable_array[i].port_mode,
wrsPortStatusTable_array[i].port_locked);
}
retries++;
if (retries > 100) {
snmp_log(LOG_ERR, "%s: too many retries to read HAL\n",
__func__);
retries = 0;
}
if (!wrs_shm_seqretry(hal_head, ii))
break; /* consistent read */
usleep(1000);
}
/* there was an update, return current time */
return time_cur;
}
#define TT_OID WRSPORTSTATUSTABLE_OID
#define TT_PICKINFO wrsPortStatusTable_pickinfo
#define TT_DATA_FILL_FUNC wrsPortStatusTable_data_fill
#define TT_DATA_ARRAY wrsPortStatusTable_array
#define TT_GROUP_NAME "wrsPortStatusTable"
#define TT_INIT_FUNC init_wrsPortStatusTable
#define TT_CACHE_TIMEOUT WRSPORTSTATUSTABLE_CACHE_TIMEOUT
#include "wrsTableTemplate.h"
#ifndef WRS_PORT_STATUS_TABLE_H
#define WRS_PORT_STATUS_TABLE_H
#define WRSPORTSTATUSTABLE_CACHE_TIMEOUT 5
#define WRSPORTSTATUSTABLE_OID WRS_OID, 7, 6
#define WRS_PORT_STATUS_SFP_ERROR_SFP_OK 1 /* ok */
#define WRS_PORT_STATUS_SFP_ERROR_SFP_ERROR 2 /* error */
#define WRS_PORT_STATUS_SFP_ERROR_PORT_DOWN 3 /* ok */
struct wrsPortStatusTable_s {
uint32_t index; /* not reported, index fields has to be marked
* as not-accessible in MIB */
char port_name[12]; /* port name */
ClockIdentity peer_id;
/* These can't be "unsigned char" because we scanf a %i in there */
unsigned link_up;
unsigned port_mode;
unsigned port_locked;
char sfp_vn[16]; /* vendor name */
char sfp_pn[16]; /* part name */
char sfp_vs[16]; /* vendor serial */
int sfp_in_db;
int sfp_GbE;
int sfp_error;
};
extern struct wrsPortStatusTable_s wrsPortStatusTable_array[WRS_N_PORTS];
time_t wrsPortStatusTable_data_fill(unsigned int *rows);
void init_wrsPortStatusTable(void);
#endif /* WRS_PORT_STATUS_TABLE_H */
This diff is collapsed.
/*
* 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)));
}
This diff is collapsed.
#ifndef WRS_PSTATS_TABLE_H
#define WRS_PSTATS_TABLE_H
#define WRSPSTATSTABLE_CACHE_TIMEOUT 5
#define WRSPSTATSTABLE_OID WRS_OID, 7, 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 */
This diff is collapsed.
#ifndef WRS_PTP_DATA_TABLE_H
#define WRS_PTP_DATA_TABLE_H
#define WRSPTPDATATABLE_CACHE_TIMEOUT 5
#define WRSPTPDATATABLE_OID WRS_OID, 7, 5
/* Right now we allow only one servo instance, it will change in the future
* when switchover is implemented */
#define WRS_MAX_N_SERVO_INSTANCES 1
struct wrsPtpDataTable_s {
uint32_t index; /* not reported, index fields has to be marked
* as not-accessible in MIB */
char port_name[12]; /* port name on which ptp servo instance in
* running FIXME: not implemented */
ClockIdentity gm_id; /* FIXME: not implemented */
ClockIdentity my_id; /* FIXME: not implemented */
int ppsi_mode; /* FIXME: not implemented */
char servo_state_name[32]; /* State as string */
int servo_state; /* state number */
int tracking_enabled;
char sync_source[32]; /* FIXME: not implemented */
int64_t clock_offset;
int32_t clock_offsetHR; /* Human readable version of clock_offset,
* saturated to int limits */
int32_t skew;
int64_t rtt;
uint32_t llength;
uint32_t servo_updates;
int32_t delta_tx_m;
int32_t delta_rx_m;
int32_t delta_tx_s;
int32_t delta_rx_s;
};
time_t wrsPtpDataTable_data_fill(unsigned int *rows);
void init_wrsPtpDataTable(void);
#endif /* WRS_PTP_DATA_TABLE_H */
#ifndef WRS_SNMP_H
#define WRS_SNMP_H
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
/* Crap! -- everybody makes them different, and even ppsi::ieee wants them */
#undef FALSE
#undef TRUE
/* conflict between definition in net-snmp-agent-includes.h (which include
* snmp_vars.h) and ppsi.h where INST is defined as a inline function */
#undef INST
#include <ppsi/ieee1588_types.h> /* for ClockIdentity */
/*
* local hack: besides the file pointer, that is there anyways,
......@@ -77,12 +89,17 @@ static inline int dumpstruct(FILE *dest, char *name, void *ptr, int size)
/* Scalar is just a stupid thing, but let's keep it */
extern void init_wrsScalar(void);
/* Real stuff follows */
extern void init_wrsPstats(void);
extern void init_wrsPpsi(void);
extern void init_wrsVersion(void);
extern void init_wrsDate(void);
#define WRS_OID 1, 3, 6, 1, 4, 1, 96, 100
struct pickinfo {
/* Following fields are used to format the output */
int type; int offset; int len;
};
#define FIELD(_struct, _type, _field) { \
.type = _type, \
.offset = offsetof(struct _struct, _field), \
.len = sizeof(((struct _struct *)0)->_field), \
}
#endif /* WRS_SNMP_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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