Commit 69f53c93 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

Merge branch 'snmp-support' into proposed_master

parents 699fb5da da0dcab6
......@@ -136,6 +136,23 @@ config SYSLOG
The user (or init script) must use "syslog <ipaddr> <macaddr>"
to enable it. The special "off" ipaddr disables syslog.
config SNMP
depends on IP
default y
boolean "Mini SNMP responder"
config SNMP_SET
depends on SNMP
default y
boolean "Add SET support to the Mini SNMP responder"
help
This option enables support for SET requests for Mini SNMP responder
config SNMP_HW_TYPE
depends on SNMP
default "spec"
string "Hardware type reported by SNMP"
config BUILD_INIT
depends on WR_NODE
default n
......@@ -360,6 +377,12 @@ config WRC_VERBOSE
help
This enables some more diagnostic messages. Normally off.
config SNMP_VERBOSE
depends on DEVELOPER && SNMP
boolean "More verbose messages in SNMP"
help
This enables some more diagnostic messages. Normally off.
config FAKE_TEMPERATURES
depends on DEVELOPER
boolean "Offer an array of 3 fake temperatures, for testing"
......
......@@ -110,6 +110,12 @@ OUTPUT-$(CONFIG_WR_SWITCH) = rt_cpu
OUTPUT := $(OUTPUT-y)
GIT_VER = $(shell git describe --always --dirty | sed 's;^wr-switch-sw-;;')
GIT_USR = $(shell git config --get-all user.name)
# if user.name is not available from git use user@hostname
ifeq ($(GIT_USR),)
GIT_USR = $(shell whoami)@$(shell hostname)
endif
all: tools $(OUTPUT).elf $(arch-files-y)
......@@ -140,7 +146,7 @@ sdb-lib/libsdbfs.a:
$(MAKE) -C sdb-lib
$(OUTPUT).elf: $(LDS-y) $(AUTOCONF) gitmodules $(OUTPUT).o config.o
$(CC) $(CFLAGS) -D__GIT_VER__="\"$(GIT_VER)\"" -c revision.c
$(CC) $(CFLAGS) -D__GIT_VER__="\"$(GIT_VER)\"" -D__GIT_USR__="\"$(GIT_USR)\"" -c revision.c
${CC} -o $@ revision.o config.o $(OUTPUT).o $(LDFLAGS)
${OBJDUMP} -d $(OUTPUT).elf > $(OUTPUT)_disasm.S
$(SIZE) $@
......
#
# Automatically generated make config: don't edit
#
# CONFIG_WR_SWITCH is not set
CONFIG_WR_NODE=y
CONFIG_PRINT_BUFSIZE=128
CONFIG_PRINTF_XINT=y
CONFIG_RAMSIZE=131072
CONFIG_TEMP_POLL_INTERVAL=15
CONFIG_VLAN_NR=0
CONFIG_VLAN_1_FOR_CLASS7=0
CONFIG_VLAN_2_FOR_CLASS7=0
CONFIG_VLAN_FOR_CLASS6=0
# CONFIG_HOST_PROCESS is not set
CONFIG_LM32=y
CONFIG_EMBEDDED_NODE=y
# CONFIG_WR_NODE_PCS16 is not set
CONFIG_STACKSIZE=2048
CONFIG_PPSI=y
CONFIG_UART=y
CONFIG_W1=y
CONFIG_LATENCY_ETHTYPE=0
CONFIG_IP=y
# CONFIG_CMD_CONFIG is not set
# CONFIG_SYSLOG is not set
CONFIG_SNMP=y
# CONFIG_SNMP_SET is not set
CONFIG_SNMP_HW_TYPE="spec"
# CONFIG_BUILD_INIT is not set
CONFIG_INIT_COMMAND=""
CONFIG_HAS_BUILD_INIT=0
CONFIG_HAS_FLASH_INIT=1
CONFIG_FLASH_INIT=y
#
# wrpc-sw is tainted if you change the following options
#
# CONFIG_DEVELOPER is not set
CONFIG_SDB_STORAGE=y
# CONFIG_LEGACY_EEPROM is not set
CONFIG_VLAN_ARRAY_SIZE=1
#
# Automatically generated make config: don't edit
#
# CONFIG_WR_SWITCH is not set
CONFIG_WR_NODE=y
CONFIG_PRINT_BUFSIZE=128
CONFIG_PRINTF_XINT=y
CONFIG_RAMSIZE=131072
CONFIG_TEMP_POLL_INTERVAL=15
# CONFIG_PLL_VERBOSE is not set
# CONFIG_PFILTER_VERBOSE is not set
# CONFIG_WRC_VERBOSE is not set
# CONFIG_VLAN is not set
CONFIG_VLAN_NR=0
CONFIG_VLAN_1_FOR_CLASS7=0
CONFIG_VLAN_2_FOR_CLASS7=0
CONFIG_VLAN_FOR_CLASS6=0
# CONFIG_HOST_PROCESS is not set
CONFIG_LM32=y
CONFIG_EMBEDDED_NODE=y
# CONFIG_WR_NODE_PCS16 is not set
CONFIG_STACKSIZE=2048
CONFIG_PPSI=y
CONFIG_UART=y
CONFIG_W1=y
CONFIG_LATENCY_ETHTYPE=0
CONFIG_IP=y
# CONFIG_CMD_CONFIG is not set
# CONFIG_SYSLOG is not set
CONFIG_SNMP=y
CONFIG_SNMP_SET=y
CONFIG_SNMP_HW_TYPE="spec"
# CONFIG_BUILD_INIT is not set
CONFIG_INIT_COMMAND=""
CONFIG_HAS_BUILD_INIT=0
CONFIG_HAS_FLASH_INIT=1
CONFIG_FLASH_INIT=y
#
# wrpc-sw is tainted if you change the following options
#
CONFIG_DEVELOPER=y
# CONFIG_CMD_LL is not set
# CONFIG_CHECK_RESET is not set
# CONFIG_SPLL_FIFO_LOG is not set
# CONFIG_PRINTF_FULL is not set
# CONFIG_PRINTF_MINI is not set
# CONFIG_PRINTF_NONE is not set
# CONFIG_DETERMINISTIC_BINARY is not set
# CONFIG_UART_SW is not set
# CONFIG_NET_VERBOSE is not set
CONFIG_SNMP_VERBOSE=y
CONFIG_FAKE_TEMPERATURES=y
CONFIG_SDB_STORAGE=y
# CONFIG_LEGACY_EEPROM is not set
# CONFIG_LATENCY_PROBE is not set
CONFIG_VLAN_ARRAY_SIZE=1
......@@ -57,6 +57,10 @@
* ------------------------------------------------
*/
#define SFP_DB_EMPTY 0xff
static uint8_t sfpcount = SFP_DB_EMPTY;
uint8_t has_eeprom = 0;
static int i2cif, i2c_addr; /* globals, using the names we always used */
......@@ -137,7 +141,7 @@ static int eeprom_write(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset,
int32_t storage_sfpdb_erase(void)
{
uint8_t sfpcount = 0;
sfpcount = 0;
//just a dummy function that writes '0' to sfp count field of the SFP DB
if (eeprom_write(i2cif, i2c_addr, EE_BASE_SFP, &sfpcount,
......@@ -147,28 +151,44 @@ int32_t storage_sfpdb_erase(void)
return sfpcount;
}
int storage_get_sfp(struct s_sfpinfo * sfp,
uint8_t add, uint8_t pos)
static uint8_t sfp_chksum(uint8_t *ptr)
{
int i;
uint8_t chksum = 0;
/* '-1' because we do not include chksum in computation */
for (i = 0; i < sizeof(struct s_sfpinfo) - 1; ++i)
chksum = (uint8_t) ((uint16_t) chksum + *(ptr++)) & 0xff;
return chksum;
}
int storage_get_sfp(struct s_sfpinfo *sfp, uint8_t oper, uint8_t pos)
{
static uint8_t sfpcount = 0;
uint8_t i, chksum = 0;
uint8_t *ptr;
uint8_t i;
struct s_sfpinfo dbsfp;
if (pos >= SFPS_MAX)
return EE_RET_POSERR; //position in database outside the range
if (pos >= SFPS_MAX) {
/* position in database outside the range */
return EE_RET_POSERR;
}
//read how many SFPs are in the database, but only in the first call (pos==0)
if (!pos
/* Read how many SFPs are in the database, but only in the first call
*/
if (sfpcount == SFP_DB_EMPTY
&& eeprom_read(i2cif, i2c_addr, EE_BASE_SFP, &sfpcount,
sizeof(sfpcount)) != sizeof(sfpcount))
return EE_RET_I2CERR;
if (add && sfpcount == SFPS_MAX) //no more space in the database to add new SFPs
return EE_RET_DBFULL;
else if (!pos && !add && sfpcount == 0) //there are no SFPs in the database to read
return sfpcount;
/* for not written flash set sfpcount to 0 */
if (sfpcount == SFP_DB_EMPTY)
sfpcount = 0;
if (oper == SFP_GET) {
if (sfpcount == 0) {
/* There are no SFPs in the database to read */
return 0;
}
if (!add) {
if (eeprom_read(i2cif, i2c_addr,
EE_BASE_SFP + sizeof(sfpcount)
+ pos * sizeof(struct s_sfpinfo),
......@@ -176,27 +196,42 @@ int storage_get_sfp(struct s_sfpinfo * sfp,
!= sizeof(struct s_sfpinfo) )
return EE_RET_I2CERR;
ptr = (uint8_t *) sfp;
for (i = 0; i < sizeof(struct s_sfpinfo) - 1; ++i) //'-1' because we do not include chksum in computation
chksum =
(uint8_t) ((uint16_t) chksum + *(ptr++)) & 0xff;
if (chksum != sfp->chksum)
if (sfp_chksum((uint8_t *)sfp) != sfp->chksum)
return EE_RET_CORRPT;
} else {
/*count checksum */
ptr = (uint8_t *) sfp;
for (i = 0; i < sizeof(struct s_sfpinfo) - 1; ++i) //'-1' because we do not include chksum in computation
chksum =
(uint8_t) ((uint16_t) chksum + *(ptr++)) & 0xff;
sfp->chksum = chksum;
/*add SFP at the end of DB */
}
if (oper == SFP_ADD) {
for (i = 0; i < sfpcount; i++) {
if (eeprom_read(i2cif, i2c_addr,
EE_BASE_SFP + sizeof(sfpcount)
+ i * sizeof(struct s_sfpinfo),
(uint8_t *)&dbsfp, sizeof(struct s_sfpinfo))
!= sizeof(struct s_sfpinfo))
return EE_RET_I2CERR;
if (!strncmp(dbsfp.pn, sfp->pn, 16)) { /* sfp matched */
pp_printf("Update existing SFP entry\n");
break;
}
}
if (i >= SFPS_MAX) { /* database is full */
return EE_RET_DBFULL;
}
/* Count checksum */
sfp->chksum = sfp_chksum((uint8_t *)sfp);
/* Add an entry at the given pos in the DB */
eeprom_write(i2cif, i2c_addr,
EE_BASE_SFP + sizeof(sfpcount)
+ sfpcount * sizeof(struct s_sfpinfo),
+ i * sizeof(struct s_sfpinfo),
(uint8_t *) sfp, sizeof(struct s_sfpinfo));
sfpcount++;
eeprom_write(i2cif, i2c_addr, EE_BASE_SFP, &sfpcount,
sizeof(sfpcount));
if (i >= sfpcount) {
pp_printf("Adding new SFP entry\n");
/* We're adding a new entry, update sfpcount */
sfpcount++;
eeprom_write(i2cif, i2c_addr, EE_BASE_SFP, &sfpcount,
sizeof(sfpcount));
}
}
return sfpcount;
......@@ -204,19 +239,15 @@ int storage_get_sfp(struct s_sfpinfo * sfp,
int storage_match_sfp(struct s_sfpinfo * sfp)
{
uint8_t sfpcount = 1;
int8_t i, temp;
int8_t i;
int sfp_cnt = 1;
struct s_sfpinfo dbsfp;
for (i = 0; i < sfpcount; ++i) {
temp = storage_get_sfp(&dbsfp, 0, i);
if (!i) {
sfpcount = temp; //only in first round valid sfpcount is returned from eeprom_get_sfp
if (sfpcount == 0 || sfpcount == 0xFF)
return 0;
else if (sfpcount < 0)
return sfpcount;
}
for (i = 0; i < sfp_cnt; ++i) {
sfp_cnt = storage_get_sfp(&dbsfp, SFP_GET, i);
if (sfp_cnt <= 0)
return sfp_cnt;
if (!strncmp(dbsfp.pn, sfp->pn, 16)) {
sfp->dTx = dbsfp.dTx;
sfp->dRx = dbsfp.dRx;
......
......@@ -80,6 +80,11 @@ int flash_write(uint32_t addr, uint8_t *buf, int count)
}
bbspi_transfer(1,0);
/* make sure the write is complete */
while (flash_rsr() & 0x01) {
/* do nothing */
}
return count;
}
......
......@@ -52,16 +52,7 @@
static volatile uint32_t dma_tx_buf[MINIC_DMA_TX_BUF_SIZE / 4];
static volatile uint32_t dma_rx_buf[MINIC_DMA_RX_BUF_SIZE / 4];
struct wr_minic {
volatile uint32_t *rx_head, *rx_base;
uint32_t rx_avail, rx_size;
volatile uint32_t *tx_head, *tx_base;
uint32_t tx_avail, tx_size;
int tx_count, rx_count;
};
static struct wr_minic minic;
struct wr_minic minic;
static inline void minic_writel(uint32_t reg, uint32_t data)
{
......
......@@ -7,7 +7,6 @@
*
* Released according to the GNU GPL, version 2 or any later version.
*/
//#include <string.h>
#include <wrc.h>
#include <w1.h>
#include <storage.h>
......@@ -166,7 +165,7 @@ static void storage_sdb_list(struct sdbfs *fs)
{
struct sdb_device *d;
int new = 1;
while ( (d = sdbfs_scan(fs, new)) != NULL) {
while ((d = sdbfs_scan(fs, new)) != NULL) {
d->sdb_component.product.record_type = '\0';
pp_printf("file 0x%08x @ %4i, name %s\n",
(int)(d->sdb_component.product.device_id),
......@@ -196,12 +195,12 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
uint32_t magic = 0;
static unsigned entry_points_eeprom[] = {0, 64, 128, 256, 512, 1024};
static unsigned entry_points_flash[] = {
0x000000, // flash base
0x100, // second page in flash
0x200, // IPMI with MultiRecord
0x300, // IPMI with larger MultiRecord
0x170000, // after first FPGA bitstream
0x2e0000}; // after MultiBoot bitstream
0x000000, /* flash base */
0x100, /* second page in flash */
0x200, /* IPMI with MultiRecord */
0x300, /* IPMI with larger MultiRecord */
0x170000, /* after first FPGA bitstream */
0x2e0000}; /* after MultiBoot bitstream */
int i, ret;
/*
......@@ -209,7 +208,7 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
*/
for (i = 0; i < ARRAY_SIZE(entry_points_flash); i++) {
flash_read(entry_points_flash[i], (void *)&magic, sizeof(magic));
if(magic == SDB_MAGIC)
if (magic == SDB_MAGIC)
break;
}
if (magic == SDB_MAGIC) {
......@@ -292,7 +291,7 @@ found_exit:
* setting if no sdbfs is there, but CONFIG_SDB_STORAGE depends on
* CONFIG_W1 anyways.
*/
int get_persistent_mac(uint8_t portnum, uint8_t * mac)
int get_persistent_mac(uint8_t portnum, uint8_t *mac)
{
int ret;
int i, class;
......@@ -310,7 +309,7 @@ int get_persistent_mac(uint8_t portnum, uint8_t * mac)
ret = sdbfs_fread(&wrc_sdb, 0, mac, 6);
sdbfs_close(&wrc_sdb);
if(ret < 0)
if (ret < 0)
pp_printf("%s: SDB error\n", __func__);
if (mac[0] == 0xff ||
(mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]) == 0) {
......@@ -340,7 +339,7 @@ int get_persistent_mac(uint8_t portnum, uint8_t * mac)
return 0;
}
int set_persistent_mac(uint8_t portnum, uint8_t * mac)
int set_persistent_mac(uint8_t portnum, uint8_t *mac)
{
int ret;
......@@ -383,7 +382,7 @@ int32_t storage_sfpdb_erase(void)
if (sdbfs_open_id(&wrc_sdb, SDB_VENDOR, SDB_DEV_SFP) < 0)
return -1;
ret = sdbfs_ferase(&wrc_sdb, 0, wrc_sdb.f_len);
if(ret == wrc_sdb.f_len)
if (ret == wrc_sdb.f_len)
ret = 1;
sdbfs_close(&wrc_sdb);
return ret == 1 ? 0 : -1;
......@@ -394,51 +393,59 @@ int32_t storage_sfpdb_erase(void)
static int sfp_valid(struct s_sfpinfo *sfp)
{
int i;
for(i=0; i<SFP_PN_LEN; ++i) {
if(sfp->pn[i] == 0xff)
for (i = 0; i < SFP_PN_LEN; ++i) {
if (sfp->pn[i] == 0xff)
return 0;
}
return 1;
}
int storage_get_sfp(struct s_sfpinfo * sfp,
uint8_t add, uint8_t pos)
static int sfp_entry(struct s_sfpinfo *sfp, uint8_t oper, uint8_t pos)
{
static uint8_t sfpcount = 0;
struct s_sfpinfo tempsfp;
int ret = -1;
uint8_t i, chksum = 0;
uint8_t *ptr;
int sdb_offset;
if (pos >= SFPS_MAX)
return EE_RET_POSERR; //position outside the range
return EE_RET_POSERR; /* position outside the range */
if (sdbfs_open_id(&wrc_sdb, SDB_VENDOR, SDB_DEV_SFP) < 0)
return -1;
//read how many SFPs are in the database, but only in the first call
if(!pos) {
/* Read how many SFPs are in the database, but only in the first
* call */
if (!pos) {
sfpcount = 0;
while (sdbfs_fread(&wrc_sdb, sizeof(sfpcount) +
sfpcount*sizeof(tempsfp), &tempsfp,
sdb_offset = sizeof(sfpcount);
while (sdbfs_fread(&wrc_sdb, sdb_offset, &tempsfp,
sizeof(tempsfp)) == sizeof(tempsfp)) {
if(!sfp_valid(&tempsfp))
if (!sfp_valid(&tempsfp))
break;
sfpcount++;
sdb_offset = sizeof(sfpcount) + sfpcount * sizeof(tempsfp);
}
}
if (add && sfpcount == SFPS_MAX) //no more space to add new SFPs
return EE_RET_DBFULL;
if (!pos && !add && sfpcount == 0) // no SFPs in the database
return 0;
if ((oper == SFP_ADD) && (sfpcount == SFPS_MAX)) {
/* no more space to add new SFPs */
ret = EE_RET_DBFULL;
goto out;
}
if (!add) {
if (sdbfs_fread(&wrc_sdb, sizeof(sfpcount) + pos * sizeof(*sfp),
sfp, sizeof(*sfp))
!= sizeof(*sfp))
if (!pos && (oper == SFP_GET) && sfpcount == 0) {
/* no SFPs in the database */
ret = 0;
goto out;
}
if (oper == SFP_GET) {
sdb_offset = sizeof(sfpcount) + pos * sizeof(*sfp);
if (sdbfs_fread(&wrc_sdb, sdb_offset, sfp, sizeof(*sfp))
!= sizeof(*sfp))
goto out;
ptr = (uint8_t *)sfp;
......@@ -449,46 +456,99 @@ int storage_get_sfp(struct s_sfpinfo * sfp,
pp_printf("sfp: corrupted checksum\n");
goto out;
}
} else {
/*count checksum */
}
if (oper == SFP_ADD) {
/* count checksum */
ptr = (uint8_t *)sfp;
/* use sizeof() - 1 because we don't include checksum */
for (i = 0; i < sizeof(struct s_sfpinfo) - 1; ++i)
chksum = chksum + *(ptr++);
sfp->chksum = chksum;
/* add SFP at the end of DB */
if (sdbfs_fwrite(&wrc_sdb, sizeof(sfpcount)
+ sfpcount * sizeof(*sfp), sfp, sizeof(*sfp))
!= sizeof(*sfp))
sdb_offset = sizeof(sfpcount) + sfpcount * sizeof(*sfp);
if (sdbfs_fwrite(&wrc_sdb, sdb_offset, sfp, sizeof(*sfp))
!= sizeof(*sfp)) {
goto out;
}
sfpcount++;
if (sdbfs_fwrite(&wrc_sdb, 0, &sfpcount, sizeof(sfpcount))
!= sizeof(sfpcount))
goto out;
}
ret = sfpcount;
out:
sdbfs_close(&wrc_sdb);
return ret;
return 0;
}
int storage_match_sfp(struct s_sfpinfo * sfp)
static int storage_update_sfp(struct s_sfpinfo *sfp)
{
int sfpcount = 1;
int temp;
int8_t i;
struct s_sfpinfo sfp_db[SFPS_MAX];
struct s_sfpinfo *dbsfp;
/* copy entries from flash to the memory, update entry if matched */
for (i = 0; i < sfpcount; ++i) {
dbsfp = &sfp_db[i];
sfpcount = sfp_entry(dbsfp, SFP_GET, i);
if (sfpcount <= 0)
return sfpcount;
if (!strncmp(dbsfp->pn, sfp->pn, 16)) {
/* update matched entry */
dbsfp->dTx = sfp->dTx;
dbsfp->dRx = sfp->dRx;
dbsfp->alpha = sfp->alpha;
}
}
/* erase entire database */
if (storage_sfpdb_erase() == EE_RET_I2CERR) {
pp_printf("Could not erase DB\n");
return -1;
}
/* add all SFPs */
for (i = 0; i < sfpcount; ++i) {
dbsfp = &sfp_db[i];
temp = sfp_entry(dbsfp, SFP_ADD, 0);
if (temp < 0) {
/* if error, return it */
return temp;
}
}
return i;
}
int storage_get_sfp(struct s_sfpinfo *sfp, uint8_t oper, uint8_t pos)
{
struct s_sfpinfo tmp_sfp;
if (oper == SFP_GET) {
/* Get SFP entry */
return sfp_entry(sfp, SFP_GET, pos);
}
/* storage_match_sfp replaces content of parameter, so do the copy
* first */
tmp_sfp = *sfp;
if (!storage_match_sfp(&tmp_sfp)) { /* add a new sfp entry */
pp_printf("Adding new SFP entry\n");
return sfp_entry(sfp, SFP_ADD, 0);
}
pp_printf("Update existing SFP entry\n");
return storage_update_sfp(sfp);
}
int storage_match_sfp(struct s_sfpinfo *sfp)
{
uint8_t sfpcount = 1;
int8_t i, temp;
int8_t i;
struct s_sfpinfo dbsfp;
for (i = 0; i < sfpcount; ++i) {
temp = storage_get_sfp(&dbsfp, 0, i);
if (!i) {
// first round: valid sfpcount is returned
sfpcount = temp;
if (sfpcount == 0 || sfpcount == 0xFF)
return 0;
else if (sfpcount < 0)
return sfpcount;
}
sfpcount = sfp_entry(&dbsfp, SFP_GET, i);
if (sfpcount <= 0)
return sfpcount;
if (!strncmp(dbsfp.pn, sfp->pn, 16)) {
sfp->dTx = dbsfp.dTx;
sfp->dRx = dbsfp.dRx;
......@@ -504,8 +564,7 @@ int storage_match_sfp(struct s_sfpinfo * sfp)
* Phase transition ("calibration" file)
*/
#define VALIDITY_BIT 0x80000000
int storage_phtrans(uint32_t * valp,
uint8_t write)
int storage_phtrans(uint32_t *valp, uint8_t write)
{
int ret = -1;
uint32_t value;
......@@ -551,7 +610,7 @@ int storage_init_erase(void)
if (sdbfs_open_id(&wrc_sdb, SDB_VENDOR, SDB_DEV_INIT) < 0)
return -1;
ret = sdbfs_ferase(&wrc_sdb, 0, wrc_sdb.f_len);
if(ret == wrc_sdb.f_len)
if (ret == wrc_sdb.f_len)
ret = 1;
sdbfs_close(&wrc_sdb);
return ret == 1 ? 0 : -1;
......@@ -576,7 +635,7 @@ int storage_init_add(const char *args[])
while (sdbfs_fread(&wrc_sdb, sizeof(used)+used, &byte, 1) == 1) {
if (byte == 0xff)
break;
used ++;
used++;
}
if (used > 256 /* 0xffff or wrong */)
......@@ -589,7 +648,7 @@ int storage_init_add(const char *args[])
(void *)args[i], len) != len)
goto out;
used += len;
if(args[i+1] != NULL) /* next one is another word of the same command */
if (args[i+1] != NULL) /* next one is another word of the same command */
separator = ' ';
else /* no more words, end command with '\n' */
separator = '\n';
......@@ -622,18 +681,18 @@ int storage_init_show(void)
if (sdbfs_open_id(&wrc_sdb, SDB_VENDOR, SDB_DEV_INIT) < 0)
return -1;
used = 0;
do {
if (sdbfs_fread(&wrc_sdb, sizeof(used) + used, &byte, 1) != 1)
goto out;
if(byte != 0xff) {
if (byte != 0xff) {
pp_printf("%c", byte);
used++;
}
} while(byte != 0xff);
} while (byte != 0xff);
if(used == 0)
if (used == 0)
pp_printf("Empty init script...\n");
ret = 0;
out:
......
......@@ -10,10 +10,21 @@
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <errno.h>
#include "syscon.h"
#include "i2c.h"
#include "sfp.h"
#include "storage.h"
/* Calibration data (from EEPROM if available) */
int32_t sfp_alpha = 73622176; /* default values if could not read EEPROM */
int32_t sfp_deltaTx = 0;
int32_t sfp_deltaRx = 0;
int32_t sfp_in_db = 0;
char sfp_pn[SFP_PN_LEN];
int sfp_present(void)
{
......@@ -52,3 +63,27 @@ int sfp_read_part_id(char *part_id)
return -1;
}
int sfp_match(void)
{
struct s_sfpinfo sfp;
sfp_pn[0] = '\0';
if (!sfp_present()) {
return -ENODEV;
}
if (sfp_read_part_id(sfp_pn)) {
return -EIO;
}
strncpy(sfp.pn, sfp_pn, SFP_PN_LEN);
if (storage_match_sfp(&sfp) == 0) {
sfp_in_db = SFP_NOT_MATCHED;
return -ENXIO;
}
sfp_deltaTx = sfp.dTx;
sfp_deltaRx = sfp.dRx;
sfp_alpha = sfp.alpha;
sfp_in_db = SFP_MATCHED;
return 0;
}
......@@ -594,7 +594,6 @@ is presented below:
@example
wrc# init erase
wrc# init add ptp stop
wrc# init add sfp detect
wrc# init add sfp match
wrc# init add mode slave
wrc# init add ptp start
......@@ -622,13 +621,15 @@ script:
@example
executing: ptp stop
executing: sfp detect
AXGE-3454-0531
PTP stop
executing: sfp match
SFP matched, dTx=180707, dRx=148323, alpha=-73685416
AXGE-3454-0531
SFP matched, dTx=180707 dRx=148323 alpha=-73685416
executing: mode slave
PTP stop
Locking PLL
executing: ptp start
PTP start
Slave Only, clock class set to 255
@end example
......@@ -700,6 +701,414 @@ signal on the LEMO connector No. 1. Please remember to use oscilloscope cables
of the same length and type (with the same delay), or take their delay
difference into account in your measurements.
@c ==========================================================================
@node Diagnostics via SNMP
@section Diagnostics via SNMP
Up to the version 3.1 of @sc{wrpc} the only way to perform diagnostics
of the @t{wrpc-sw} was to use serial console with tools like @i{gui}, @i{stat},
etc. For some set-ups, like standalone node, it is very inconvenient to use
external console for diagnostics.
From the version 3.1 of @sc{wrpc} it is possible to include the @i{Mini
SNMP responder}, which allows to perform remote diagnostics using @i{SNMP} via
a port connected to the @i{Write Rabbit} network.
The configuration file of @sc{wrpc} contains the following
SNMP-related options:
@itemize
@item @t{CONFIG_SNMP} -- include the @i{Mini SNMP responder} into @sc{wrpc}
@item @t{CONFIG_SNMP_SET} -- enable the support of SNMP @i{SET} packets
@item @t{CONFIG_SNMP_VERBOSE} -- enable verbose output from the @i{Mini SNMP
responder} on the @sc{wrpc}'s console
@end itemize
The MIB file describing @sc{wrpc}'s OIDs can be found in the @t{lib} directory
of the @t{wrpc-sw} repo.
So far, the @i{Mini SNMP responder} supports version 1 and a subset of version
2c of the SNMP protocol.
The following types of requests are supported:
@itemize @bullet
@item GET -- get value of a given OID
@item GETNEXT -- get value of a next OID after the given OID (this is used
for @t{snmpwalk}s)
@item SET -- change the value of a given OID (so far used only for adding
SFP's to the database and PTP restarts)
@end itemize
The @i{Mini SNMP responder} does not support:
@itemize @bullet
@item bulk requests packets (GETBULK)
@item more than one OID in the request packet
@item @t{trap} and @t{inform} packets
@item encryption
@item authentication
@item SNMPv2c return error types; all returned error types follows SNMPv1
@end itemize
To make examples more readable, listings below use @t{SNMP_OPT} environment
variable. Make sure you set it properly in your shell.
@example
$ SNMP_OPT="-c public -v 2c -m WR-WRPC-MIB -M +/var/lib/mibs/ietf:lib \
192.168.1.20"
@end example
where:
@itemize @bullet
@item @t{-c public} -- sets SNMP community as "@i{public}"
@item @t{-v 2c} -- specifies SNMP version
@item @t{-m WR-WRPC-MIB} -- specifies MIBs to be loaded
@item @t{-M +/var/lib/mibs/ietf:lib} -- contains path to MIBs in the host
system (@t{/var/lib/mibs/ietf}) and path to @t{WR-WRPC-MIB} (@t{lib});
on Debian-like systems default MIBs can be downloaded using
@t{download-mibs} command (package @t{snmp-mibs-downloader}); on
CentOS and RedHat MIBs are included in the @t{libsmi} package
@item @t{192.168.1.20} -- the IP address of the target board
@end itemize
For example, to get the system uptime please execute the @t{snmpget} command:
@example
$ snmpget $SNMP_OPT wrpcTimeSystemUptime.0
@end example
To get dump of all available OIDs please execute the @t{snmpwalk} command:
@example
$ snmpwalk $SNMP_OPT wrpcCore
@end example
Part of the @t{snmpwalk}'s output:
@example
WR-WRPC-MIB::wrpcVersionHwType.0 = STRING: spec
WR-WRPC-MIB::wrpcVersionSwVersion.0 = STRING: wrpc-v3.0-251-g14e952e
WR-WRPC-MIB::wrpcVersionSwBuildBy.0 = STRING: Adam Wujek
WR-WRPC-MIB::wrpcVersionSwBuildDate.0 = STRING: Jun 7 2016 18:12:24
WR-WRPC-MIB::wrpcTimeTAI.0 = Counter64: 1465375022
WR-WRPC-MIB::wrpcTimeTAIString.0 = STRING: 2016-06-08-08:37:02
WR-WRPC-MIB::wrpcTimeSystemUptime.0 = Timeticks: (18186) 0:03:01.86
WR-WRPC-MIB::wrpcTemperatureName.1 = STRING: pcb
WR-WRPC-MIB::wrpcTemperatureValue.1 = STRING: 38.5625
WR-WRPC-MIB::wrpcSpllMode.0 = INTEGER: slave(3)
WR-WRPC-MIB::wrpcSpllIrqCnt.0 = Counter32: 1259605
[...]
WR-WRPC-MIB::wrpcPortSfpInDB.0 = INTEGER: inDataBase(2)
WR-WRPC-MIB::wrpcPortInternalTx.0 = Counter32: 452
WR-WRPC-MIB::wrpcPortInternalRx.0 = Counter32: 869
WR-WRPC-MIB::wrpcSfpPn.1 = STRING: AXGE-1254-0531
WR-WRPC-MIB::wrpcSfpDeltaTx.1 = INTEGER: 180625
WR-WRPC-MIB::wrpcSfpDeltaRx.1 = INTEGER: 148451
WR-WRPC-MIB::wrpcSfpAlpha.1 = INTEGER: 72169888
End of MIB
@end example
It is recommended to use SNMP v2c for communication with the @sc{wrpc}.
Please note that when the version 1 of SNMP is used, 64 bit counters are not
supported. This makes it impossible to read some @sc{wrpc}'s objects with
SNMPv1.
@c --------------------------------------------------------------------------
@node Managing SFP database via SNMP
@subsection Managing SFP database via SNMP
The SFPs database can be displayed using the @t{sfp show} command from
the @sc{wrpc}'s console:
@example
wrc# sfp show
1: PN:AXGE-1254-0531 dTx: 180625 dRx: 148451 alpha: 72169888
2: PN:AXGE-3454-0531 dTx: 180625 dRx: 148451 alpha: -73685416
@end example
The same data is exported by the @i{Mini SNMP responder} via the table
@t{wrpcSfpTable}:
@example
$ snmpwalk $SNMP_OPT wrpcSfpTable
WR-WRPC-MIB::wrpcSfpPn.1 = STRING: AXGE-1254-0531
WR-WRPC-MIB::wrpcSfpPn.2 = STRING: AXGE-3454-0531
WR-WRPC-MIB::wrpcSfpDeltaTx.1 = INTEGER: 180625
WR-WRPC-MIB::wrpcSfpDeltaTx.2 = INTEGER: 180625
WR-WRPC-MIB::wrpcSfpDeltaRx.1 = INTEGER: 148451
WR-WRPC-MIB::wrpcSfpDeltaRx.2 = INTEGER: 148451
WR-WRPC-MIB::wrpcSfpAlpha.1 = INTEGER: 72169888
WR-WRPC-MIB::wrpcSfpAlpha.2 = INTEGER: -73685416
End of MIB
@end example
When the SET support is compiled into the @i{Mini SNMP responder}, it is
possible to erase or add/replace SFP entires to the SFPs database via SNMP.
Addition (or modification) of one SFP to the database can done by a row of
SNMP SETs. Firstly, please set the delta Tx (@t{wrpcPtpConfigDeltaTx.0}), the
delta Rx (@t{wrpcPtpConfigDeltaRx.0}) and the alpha (@t{wrpcPtpConfigAlpha.0})
with new values.
Then, to commit the change to the SFP database, perform the SNMP SET on
the @t{wrpcPtpConfigApply.0} with the value @t{writeToFlashCurrentSfp}. It will
add/update values for the currently plugged SFP.
To add/update entries for different SFPs, please set deltas and alpha like
above, then set PN of an SFP to the @t{wrpcPtpConfigSfpPn.0} and commit
the change by setting @t{writeToFlashGivenSfp} to the @t{wrpcPtpConfigApply.0}.
It is also possible to update values in the memory for the current SFP.
For that, please set delta Tx, delta Rx and alpha as described above,
then set @t{writeToMemoryCurrentSfp} to the @t{wrpcPtpConfigApply.0}
Please be aware that these changes will be lost after a power cycle of a board,
soft reset of @sc{wrpc} or unplug/plug of a fiber/SFP.
Currently, after the update of SFP values in the memory, PTP is restarted.
Such restart is necessary because PTP does not support on-the-fly changes of
deltas nor alpha. It is expected that this behavior will change in the future.
If a database entry of the SFP, which is currently used was updated, it is
necessary to perform a restart of the PTP daemon
(set @t{wrpcPtpConfigRestart.0} with the value @t{restartPtp}).
Each SNMP SET of @t{wrpcPtpConfigApply.0} or @t{wrpcPtpConfigRestart.0} returns
the status of a performed action. For details please check @t{WR-WRPC-MIB}
file.
Commands below add an SFP with PN as "@t{NEW-SFP}", delta Tx "@t{1111}",
delta Rx "@t{2222}" and alpha "@t{3333}".
@example
$ snmpset $SNMP_OPT wrpcPtpConfigDeltaTx.0 = 1111
WR-WRPC-MIB::wrpcPtpConfigDeltaTx.0 = INTEGER: 1111
$ snmpset $SNMP_OPT wrpcPtpConfigDeltaRx.0 = 2222
WR-WRPC-MIB::wrpcPtpConfigDeltaRx.0 = INTEGER: 2222
$ snmpset $SNMP_OPT wrpcPtpConfigAlpha.0 = 3333
WR-WRPC-MIB::wrpcPtpConfigAlpha.0 = INTEGER: 3333
$ snmpset $SNMP_OPT wrpcPtpConfigSfpPn.0 = NEW-SFP
WR-WRPC-MIB::wrpcPtpConfigSfpPn.0 = STRING: "NEW-SFP"
$ snmpset $SNMP_OPT wrpcPtpConfigApply.0 = writeToFlashGivenSfp
WR-WRPC-MIB::wrpcPtpConfigApply.0 = INTEGER: applySuccessful(100)
@end example
In case the SFP database does not contain the currently plugged SFP, the last
@t{snmpset} command will return @t{applySuccessfulMatchFailed(101)}.
Optionally restart the PTP:
@example
$ snmpset $SNMP_OPT wrpcPtpConfigRestart.0 = restartPtp
WR-WRPC-MIB::wrpcPtpConfigRestart.0 = INTEGER: restartPtpSuccessful(100)
@end example
Simple verification of performed actions:
@example
wrc# sfp show
1: PN:AXGE-1254-0531 dTx: 180625 dRx: 148451 alpha: 72169888
2: PN:AXGE-3454-0531 dTx: 180625 dRx: 148451 alpha: -73685416
3: PN:NEW-SFP dTx: 1111 dRx: 2222 alpha: 3333
@end example
The same add can also be achieved by performing @t{sfp add} command in
the @sc{wrpc}'s console:
@example
wrc# sfp add NEW-SFP 1111 2222 3333
Update existing SFP entry
3 SFPs in DB
@end example
Verify the result via SNMP:
@example
$ snmpwalk $SNMP_OPT wrpcSfpTable
WR-WRPC-MIB::wrpcSfpPn.1 = STRING: AXGE-1254-0531
WR-WRPC-MIB::wrpcSfpPn.2 = STRING: AXGE-3454-0531
WR-WRPC-MIB::wrpcSfpPn.3 = STRING: NEW-SFP
WR-WRPC-MIB::wrpcSfpDeltaTx.1 = INTEGER: 180625
WR-WRPC-MIB::wrpcSfpDeltaTx.2 = INTEGER: 180625
WR-WRPC-MIB::wrpcSfpDeltaTx.3 = INTEGER: 1111
WR-WRPC-MIB::wrpcSfpDeltaRx.1 = INTEGER: 148451
WR-WRPC-MIB::wrpcSfpDeltaRx.2 = INTEGER: 148451
WR-WRPC-MIB::wrpcSfpDeltaRx.3 = INTEGER: 2222
WR-WRPC-MIB::wrpcSfpAlpha.1 = INTEGER: 72169888
WR-WRPC-MIB::wrpcSfpAlpha.2 = INTEGER: -73685416
WR-WRPC-MIB::wrpcSfpAlpha.3 = INTEGER: 3333
End of MIB
@end example
It is also possible to erase the SFPs database via SNMP (equivalent of
the @t{sfp erase} command):
@example
$ snmpset $SNMP_OPT wrpcPtpConfigApply.0 = eraseFlash
WR-WRPC-MIB::wrpcPtpConfigApply.0 = INTEGER: applySuccessful(100)
@end example
To verify that database is empty:
@example
wrc# sfp show
SFP database empty
@end example
@c --------------------------------------------------------------------------
@node Adding new objects to the SNMP
@subsection Adding new objects to the SNMP
The @i{Mini SNMP responder} can be easily expanded to export new objects.
Values of new objects can come from @sc{wrpc}'s variables or other HDL modules
as long as there is a proper interface to the @sc{wrpc} to read these values.
This section contains the instruction how to export new objects with
the given variables' content.
The @i{Mini SNMP responder} internally divides all OIDs into two parts.
The first part is called @i{limb}. The @i{limb} part of the incoming OID is
matched by a function @t{snmp_respond}, with the defined @i{limb} parts of OIDs
in the structure @t{oid_limb_array}.
When the @i{limb} part is matched then the corresponding function from
the structure @t{oid_limb_array} is called to try to match the second part of
OID (the @i{twig} part).
The example below adds to the @i{Mini SNMP responder} an @t{int32_t} variable
(@t{example_i32var}) with OID @t{1.3.6.1.4.1.96.102.1.1.0} and a string
(@t{example_string}) with OID @t{1.3.6.1.4.1.96.102.1.2.0}.
Before assigning new OIDs in your projects please contact the maintainer of
@t{wrpc-sw} repo to avoid conflicts.
@itemize
@item First declare @t{example_i32var} and @t{example_string}:
@smallexample
static int32_t example_i32var;
static char example_string[] = "test string";
@end smallexample
@item Define the @i{limb} part of the OID:
@smallexample
static uint8_t oid_wrpcExampleGroup[] = {0x2B,6,1,4,1,96,101,99};
@end smallexample
@item Define the @i{twig} part of the OID:
@smallexample
static uint8_t oid_wrpcExampleV1[] = {1,0};
static uint8_t oid_wrpcExampleV2[] = {2,0};
@end smallexample
@item Add a group definition to the @t{struct snmp_oid_limb oid_limb_array}.
Please note that this structure has to be sorted by ascending OIDs.
@smallexample
OID_LIMB_FIELD(oid_wrpcExampleGroup, func_group, oid_array_wrpcExampleGroup),
@end smallexample
The macro @t{OID_LIMB_FIELD} takes the following arguments:
@itemize @bullet
@item @t{oid_wrpcExampleGroup} -- an array with the @i{limb} part of the
OID
@item @t{func_group} -- a function to be called when the @i{limb} part of
the OID is matched; this function will try to match the @i{twig} part
of the OID within a table or a group.
@item @t{oid_array_wrpcExampleGroup} -- an array of @i{twig} parts of OIDs
@end itemize
@item Declare a previously used @t{oid_wrpcExampleGroup}. Please note that
this structure has to be sorted by ascending @i{twig} part of OIDs.
@smallexample
static struct snmp_oid oid_array_wrpcExampleGroup[] = {
OID_FIELD_VAR(oid_wrpcExampleV1, get_p, set_p, ASN_INTEGER, &example_i32var),
OID_FIELD_VAR(oid_wrpcExampleV2, get_p, set_p, ASN_OCTET_STR, &example_string),
{ 0, }
};
@end smallexample
The macro @t{OID_FIELD_VAR} takes the following arguments:
@itemize @bullet
@item @t{oid_wrpcExampleV1} -- an array with @i{twig} part of the OID
@item @t{get_p} (or @t{get_pp)} -- a function to be called when @i{twig}
part of the OID is matched for SNMP GET requests;
@item @t{set_p} (or @t{set_pp)} -- a function to be called when a @i{twig}
part of the OID is matched for SNMP SET requests; if no SET
functionality is planned, please use NULL
@item @t{ASN_INTEGER, ASN_OCTET_STR} -- type of the OID; please
check the source for other possible types
@item @t{&example_i32var, &example_string} -- addresses to the data in
memory
@end itemize
In case the address of variables is not known at boot, it is possible to define
a pointer to the variable which will be initialized (e.g. in the @t{snmp_init}
the function) at the boot time. In that case function @t{get_pp} (@t{set_pp}) has
to be used instead of @t{get_p} (@t{set_p}). For variables that are a part of
a structure and have to be accessed via a pointer, a macro @t{OID_FIELD_STRUCT}
is available.
For more complex extraction of variables or run-time value corrections,
it is possible to use a custom @i{get} function. It is possible to pass
a constant number to the custom function instead of an address. For example:
@smallexample
OID_FIELD_VAR(oid_wrpcPtpServoUpdateTime, get_servo, NO_SET, ASN_COUNTER64, \
SERVO_UPDATE_TIME),
@end smallexample
@end itemize
Perform a @t{snmpwalk} to get new OIDs:
@smallexample
$ snmpwalk -On $SNMP_OPT 1.3.6.1.4.1.96.102.1
.1.3.6.1.4.1.96.102.1.1.0 = INTEGER: 123432
.1.3.6.1.4.1.96.102.1.2.0 = STRING: "test string"
End of MIB
@end smallexample
Trying to set too long string into the @t{example_string} results in an error:
@smallexample
$ snmpset -On $SNMP_OPT 1.3.6.1.4.1.96.102.1.2.0 s "new long string"
Error in packet.
Reason: (badValue) The value given has the wrong type or length.
Failed object: .1.3.6.1.4.1.96.102.1.2.0
@end smallexample
A short enough (not longer than defined @t{"test string"}) value succeeds:
@smallexample
$ snmpset -On $SNMP_OPT 1.3.6.1.4.1.96.102.1.2.0 s "new value12"
.1.3.6.1.4.1.96.102.1.2.0 = STRING: "new value12"
@end smallexample
Set 999 to the @t{example_i32var}:
@smallexample
$ snmpset -On $SNMP_OPT 1.3.6.1.4.1.96.102.1.1.0 i 999
.1.3.6.1.4.1.96.102.1.1.0 = INTEGER: 999
@end smallexample
Perform @t{snmpwalk} to verify changes:
@smallexample
$ snmpwalk -On $SNMP_OPT 1.3.6.1.4.1.96.102.1
.1.3.6.1.4.1.96.102.1.1.0 = INTEGER: 999
.1.3.6.1.4.1.96.102.1.2.0 = STRING: "new value12"
End of MIB
@end smallexample
@c --------------------------------------------------------------------------
@node Mini SNMP responder's tests
@subsection Mini SNMP responder's tests
In the @t{wrpc-sw} repo, automatic tests are available to validate the @i{Mini
SNMP responder} implementation. These tests are placed in the @t{test/snmp}
directory.
They use the @t{bats} framework (@uref{https://github.com/sstephenson/bats}).
To run these tests, please go to @t{test/snmp} directory, then set
@t{TARGET_IP} environment varaible to the IP of your target board, then type
@t{make}. For example:
@example
$ TARGET_IP=192.168.1.20 make
bats/libexec/bats snmp_tests_*.bats
Host up 192.168.1.20
Check the presence of snmpget
Check the presence of snmpgetnext
Check the presence of snmpwalk
Check the presence of snmpset
snmpget existing oid 1.3.6.1.4.1.96.101.1.1.1.0
[...]
snmpwalk 1.3.6.1.4.1.95
snmpwalk 1.3.6 count all OIDs
100 tests, 0 failures
@end example
On the left of each test there will be a tick symbol shown or an @t{x}
depending of the test's result (not included in the example above).
Be aware that it might be necessary to clone the @t{bats} repo first.
@t{make} command will inform whether this is needed.
In case the number of OIDs changes please correct variable @t{TOTAL_NUM_OIDS}
in file @t{snmp_test_config.bash}.
These tests have to be executed after any changes are made to the @i{Mini SNMP
responder}.
@c ##########################################################################
@node Troubleshooting
@chapter Troubleshooting
......@@ -811,18 +1220,15 @@ Slave mode)
aligned to external 1-PPS and 10 MHz)
@item @code{time setnsec <nsec>} @tab sets only nanoseconds of the @sc{wrpc} time
@item @code{sfp detect} @tab prints the ID of a currently used @sc{sfp}
transceiver
@item @code{sfp erase} @tab erases the @sc{sfp} database stored in the Flash/EEPROM
@item @code{sfp add <ID> <deltaTx> <deltaRx> <alpha>} @tab stores calibration
@item @code{sfp add <PN> <deltaTx> <deltaRx> <alpha>} @tab stores calibration
parameters for @sc{sfp} to a file in Flash/EEPROM
@item @code{sfp show} @tab prints all @sc{sfp} transceivers stored in database
@item @code{sfp match} @tab tries to load the calibration parameters for
currently used @sc{sfp} transceiver (@t{sfp detect} must be executed before @t{match})
@item @code{sfp match} @tab prints the ID of a currently used @sc{sfp}
transceiver and tries to load the calibration parameters for it
@item @code{init erase} @tab erases the initialization script in Flash/EEPROM
@item @code{init add <cmd>} @tab adds shell command at the end of the
......
......@@ -33,6 +33,17 @@ struct wr_ethhdr_vlan {
uint16_t ethtype_2;
};
struct wr_minic {
volatile uint32_t *rx_head, *rx_base;
uint32_t rx_avail, rx_size;
volatile uint32_t *tx_head, *tx_base;
uint32_t tx_avail, tx_size;
int tx_count, rx_count;
};
extern struct wr_minic minic;
int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
struct hw_timestamp *hwts);
int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t * payload, uint32_t size,
......
......@@ -4,5 +4,6 @@
extern const char *build_revision;
extern const char *build_date;
extern const char *build_time;
extern const char *build_by;
#endif /* __REVISION_H__ */
......@@ -9,10 +9,27 @@
#include <stdint.h>
#define SFP_PN_LEN 16
#define SFP_NOT_MATCHED 1
#define SFP_MATCHED 2
#define SFP_GET 0
#define SFP_ADD 1
extern char sfp_pn[SFP_PN_LEN];
extern int32_t sfp_in_db;
extern int32_t sfp_alpha;
extern int32_t sfp_deltaTx;
extern int32_t sfp_deltaRx;
/* Returns 1 if there's a SFP transceiver inserted in the socket. */
int sfp_present(void);
/* Reads the part ID of the SFP from its configuration EEPROM */
int sfp_read_part_id(char *part_id);
/* Match plugged SFP with a DB entry */
int sfp_match(void);
#endif
......@@ -9,21 +9,43 @@
#ifndef __STORAGE_H
#define __STORAGE_H
#include "sfp.h"
#define SFP_SECTION_PATTERN 0xdeadbeef
#if defined CONFIG_LEGACY_EEPROM
#define EE_BASE_CAL (4 * 1024)
#define EE_BASE_SFP (4 * 1024 + 4)
/* Limit SFPs to 3, see comments below why. */
#define SFPS_MAX 3
/* The definition of EE_BASE_INIT below is wrong! But kept for backward
* compatibility. */
#define EE_BASE_INIT (4 * 1024 + 4 * 29)
/* It should be:
* #define EE_BASE_INIT (EE_BASE_SFP + sizeof(sfpcount) + \
* SFPS_MAX * sizeof(struct s_sfpinfo))
* The used definition define the start of the init script 5 bytes
* (sizeof(sfpcount) + sizeof(t24p)) before the end of SFP database.
* To make the init script working during the update of old versions of wrpc
* SFPS_MAX is limited to 3. Adding the 4th SFP will corrupt the init script
* anyway.
* If someone needs to have 4 SFPs in the database SFPS_MAX can be set to 4 and
* the proper define should be used.
* SDB is not affected by this bug.
*/
#endif
#if defined CONFIG_SDB_STORAGE
#define SFPS_MAX 4
#define SFP_PN_LEN 16
#define EE_BASE_CAL 4*1024
#define EE_BASE_SFP 4*1024+4
#define EE_BASE_INIT 4*1024+SFPS_MAX*29
#endif
#define EE_RET_I2CERR -1
#define EE_RET_DBFULL -2
#define EE_RET_CORRPT -3
#define EE_RET_POSERR -4
extern int32_t sfp_alpha;
extern int32_t sfp_deltaTx;
extern int32_t sfp_deltaRx;
extern uint32_t cal_phase_transition;
extern uint8_t has_eeprom;
......
......@@ -25,6 +25,12 @@
#define WRC_IS_VERBOSE 0
#endif
#ifdef CONFIG_SNMP_VERBOSE
#define SNMP_IS_VERBOSE 1
#else
#define SNMP_IS_VERBOSE 0
#endif
#define pll_verbose(...) \
({if (PLL_IS_VERBOSE) __debug_printf(__VA_ARGS__);})
......@@ -37,6 +43,9 @@
#define net_verbose(...) \
({if (NET_IS_VERBOSE) __debug_printf(__VA_ARGS__);})
#define snmp_verbose(...) \
({if (SNMP_IS_VERBOSE) __debug_printf(__VA_ARGS__);})
#ifdef CONFIG_HOST_PROCESS
#define IS_HOST_PROCESS 1
......
......@@ -21,6 +21,13 @@
#define vprintf pp_vprintf
#define sprintf pp_sprintf
#ifndef min
#define min(a, b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
#endif
#undef offsetof
#define offsetof(TYPE, MEMBER) ((long) &((TYPE *)0)->MEMBER)
#undef ARRAY_SIZE
......
WR-WRPC-MIB DEFINITIONS ::= BEGIN
-- Based on the WR-SWITCH-MIB
-- Adam Wujek, BE-CO-HT, CERN
-- IMPORTS: Include definitions from other mibs here
IMPORTS
OBJECT-TYPE, Integer32, Unsigned32, Counter32, Counter64,
MODULE-IDENTITY, enterprises, TimeTicks FROM SNMPv2-SMI
DisplayString FROM SNMPv2-TC;
wrWrpcMIB MODULE-IDENTITY
LAST-UPDATED "201607061700Z"
ORGANIZATION "CERN"
CONTACT-INFO "postal: BE-CO-HT, CERN, Geneva
email: ht-drivers@cern.ch
"
DESCRIPTION "White Rabbit WRPC internal details
"
REVISION "201607061700Z"
DESCRIPTION
"Clean up MIB."
REVISION "201604181000Z"
DESCRIPTION
"Create wrpc structure."
REVISION "201603081000Z"
DESCRIPTION
"First revision. For testing purposes only."
::= { cern 101 }
cern OBJECT IDENTIFIER ::= { enterprises 96 }
-- Define typical mib nodes
-- we'll prefix everything in this mib with wrpc
wrpcCore OBJECT IDENTIFIER ::= { wrWrpcMIB 1 }
--x wrpcCustom OBJECT IDENTIFIER ::= { wrWrpcMIB 2 }
-- ****************************************************************************
wrpcVersionGroup OBJECT IDENTIFIER ::= { wrpcCore 1 }
wrpcVersionHwType OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..31))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The hw type"
::= { wrpcVersionGroup 1 }
wrpcVersionSwVersion OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..31))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The software version, as returned from 'git describe' at build time"
::= { wrpcVersionGroup 2 }
wrpcVersionSwBuildBy OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..31))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The software build by, as returned from
'git config -get-all user.name' at build time"
::= { wrpcVersionGroup 3 }
wrpcVersionSwBuildDate OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..31))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The build time and date of the software"
::= { wrpcVersionGroup 4 }
--x wrpcVersionGwVersion OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..31))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The version of gateware (FPGA bitstream)"
--x ::= { wrpcVersionGroup 5 }
--x wrpcVersionGwBuild OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..31))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The build ID of gateware (FPGA bitstream)"
--x ::= { wrpcVersionGroup 6 }
--x wrpcVersionGwBuildDate OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..31))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The build date of gateware (FPGA bitstream)"
--x ::= { wrpcVersionGroup 7 }
--x wrpcVersionGwBuildBy OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..31))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The build author of gateware (FPGA bitstream)"
--x ::= { wrpcVersionGroup 8 }
--x wrpcVersionGwCommitId OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..31))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The gateware version: commit ID of XXXXXXXXX"
--x ::= { wrpcVersionGroup 9 }
--x wrpcVersionGeneralCoresCommitId OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..31))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The gateware version: commit of general-cores"
--x ::= { wrpcVersionGroup 10 }
--x wrpcVersionWrCoresCommitId OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..31))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The gateware version: commit of wr-cores"
--x ::= { wrpcVersionGroup 11 }
-- ****************************************************************************
wrpcTimeGroup OBJECT IDENTIFIER ::= { wrpcCore 2 }
wrpcTimeTAI OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The current time, in TAI seconds"
::= { wrpcTimeGroup 1 }
wrpcTimeTAIString OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..31))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The current TAI time, printed as %y-%m-%d-%H:%M:%S (no time zone)"
::= { wrpcTimeGroup 2 }
wrpcTimeSystemUptime OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"System uptime in hundreds of second"
::= { wrpcTimeGroup 3 }
-- ****************************************************************************
wrpcTemperatureTable OBJECT-TYPE
SYNTAX SEQUENCE OF WrpcTemperatureEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Information for each mounted partition"
::= { wrpcCore 3 }
wrpcTemperatureEntry OBJECT-TYPE
SYNTAX WrpcTemperatureEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"An entry containing partitions' details"
INDEX { wrpcTemperatureIndex }
::= { wrpcTemperatureTable 1 }
WrpcTemperatureEntry ::=
SEQUENCE {
wrpcTemperatureIndex Unsigned32,
wrpcTemperatureName DisplayString,
wrpcTemperatureValue DisplayString
}
wrpcTemperatureIndex OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Index for wrpcTemperatureTable"
::= { wrpcTemperatureEntry 1 }
wrpcTemperatureName OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..32))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Temperature sensor's name"
::= { wrpcTemperatureEntry 2 }
wrpcTemperatureValue OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..32))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Temperature in tenths of a celsius degree of given sensor"
::= { wrpcTemperatureEntry 3 }
-- ****************************************************************************
wrpcSpllStatusGroup OBJECT IDENTIFIER ::= { wrpcCore 4 }
wrpcSpllMode OBJECT-TYPE
SYNTAX INTEGER {
na(0),
grandmaster(1),
master(2),
slave(3)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Mode of Soft PLL (values taken from softpll_export.h)"
::= { wrpcSpllStatusGroup 1 }
wrpcSpllIrqCnt OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of interrupts in Soft PLL"
::= { wrpcSpllStatusGroup 2 }
wrpcSpllSeqState OBJECT-TYPE
SYNTAX INTEGER {
startExt(1),
waitExt(2),
startHelper(3),
waitHelper(4),
startMain(5),
waitMain(6),
disabled(7),
ready(8),
clearDacs(9),
waitClearDacs(10)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Sequence state of Soft PLL (values taken from file softpll_export.h in wrpc-sw repo)"
::= { wrpcSpllStatusGroup 3 }
wrpcSpllAlignState OBJECT-TYPE
SYNTAX INTEGER {
extOff(0),
start(1),
initCsync(2),
waitCsync(3),
waitSample(4),
compensateDelay(5),
locked(6),
startAlignment(7),
startMain(8)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Align state of Soft PLL (values taken from file spll_external.c in wrpc-sw repo)"
::= { wrpcSpllStatusGroup 4 }
wrpcSpllHlock OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"HLock in Soft PLL"
::= { wrpcSpllStatusGroup 5 }
wrpcSpllMlock OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"MLock at Soft PLL"
::= { wrpcSpllStatusGroup 6 }
wrpcSpllHY OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"H_y at Soft PLL"
::= { wrpcSpllStatusGroup 7 }
wrpcSpllMY OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"M_y at Soft PLL"
::= { wrpcSpllStatusGroup 8 }
wrpcSpllDelCnt OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Del counter at Soft PLL"
::= { wrpcSpllStatusGroup 9 }
-- ****************************************************************************
wrpcPtpGroup OBJECT IDENTIFIER ::= { wrpcCore 5 }
--x wrpcPtpGrandmasterID OBJECT-TYPE
--x SYNTAX OCTET STRING (SIZE(8))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The ClockID of the current grandmaster"
--x ::= { wrpcPtpGroup 1 }
--x wrpcPtpOwnID OBJECT-TYPE
--x SYNTAX OCTET STRING (SIZE(8))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The ClockID of this WR device"
--x ::= { wrpcPtpGroup 2 }
--x wrpcPtpMode OBJECT-TYPE
--x SYNTAX INTEGER {
--x unknown(0), ---- same as WRC_MODE macros
--x grandmaster(1),
--x master(2),
--x slave(3)
--x }
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The mode of this clock"
--x ::= { wrpcPtpGroup 3 }
--x wrpcPtpServoState OBJECT-TYPE
--x SYNTAX DisplayString (SIZE (0..32))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "The servo state if slave"
--x ::= { wrpcPtpGroup 4 }
wrpcPtpServoStateN OBJECT-TYPE
SYNTAX INTEGER {
uninitialized(0),
syncNsec(1),
syncSec(2),
syncPhase(3),
trackPhase(4),
waitOffsetStable(5)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Numeric representation of servo state"
::= { wrpcPtpGroup 5 }
--x wrpcPtpPhaseTracking OBJECT-TYPE
--x SYNTAX INTEGER {
--x na(0),
--x notTracking(1),
--x tracking(2)
--x }
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "Whether phase tracking is enabled in the servo"
--x ::= { wrpcPtpGroup 6 }
--x wrpcPtpClockOffsetPs OBJECT-TYPE
--x SYNTAX Counter64 ---- integer64
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "Current clock offset from master, in picoseconds"
--x ::= { wrpcPtpGroup 7 }
wrpcPtpClockOffsetPsHR OBJECT-TYPE
SYNTAX Integer32 -- should be something like gauge32, but with int range
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Human Readable current clock offset from master, in picoseconds
with saturation to integer"
::= { wrpcPtpGroup 8 }
wrpcPtpSkew OBJECT-TYPE
SYNTAX Integer32 -- should be something like gauge32, but with int range
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The estimated change of master-to-slave delay, in picoseconds.
Saturated to +/- int32."
::= { wrpcPtpGroup 9 }
wrpcPtpRTT OBJECT-TYPE
SYNTAX Counter64 -- unsigned64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The round-trip-time, from master, in picoseconds"
::= { wrpcPtpGroup 10 }
--x wrpcPtpLinkLength OBJECT-TYPE
--x SYNTAX Unsigned32
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "Estimated fiber length, from master-to-slave delay, in meters"
--x ::= { wrpcPtpGroup 11 }
wrpcPtpServoUpdates OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"How many times did the servo run"
::= { wrpcPtpGroup 12 }
wrpcPtpServoUpdateTime OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"TAI Nanosecond of the last servo's update"
::= { wrpcPtpGroup 13 }
wrpcPtpDeltaTxM OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Fixed Tx latency on Master side"
::= { wrpcPtpGroup 14 }
wrpcPtpDeltaRxM OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Fixed Rx latency on Master side"
::= { wrpcPtpGroup 15 }
wrpcPtpDeltaTxS OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Fixed Tx latency on Slave side"
::= { wrpcPtpGroup 16 }
wrpcPtpDeltaRxS OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Fixed Rx latency on Slave side"
::= { wrpcPtpGroup 17 }
wrpcPtpServoStateErrCnt OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of servo updates with wrong servo state"
::= { wrpcPtpGroup 18 }
wrpcPtpClockOffsetErrCnt OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of servo updates with wrong clock offset"
::= { wrpcPtpGroup 19 }
wrpcPtpRTTErrCnt OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of servo updates with wrong RTT"
::= { wrpcPtpGroup 20 }
--x wrpcPtpPeer OBJECT-TYPE
--x SYNTAX OCTET STRING (SIZE(8))
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "ptp peer ID"
--x ::= { wrpcPtpGroup 21 }
wrpcPtpAsymmetry OBJECT-TYPE
SYNTAX Counter64 -- unsigned64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Asymmetry of Total link asymmetry"
::= { wrpcPtpGroup 22 }
wrpcPtpTx OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"TX ptp packets"
::= { wrpcPtpGroup 23 }
wrpcPtpRx OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"RX ptp packets"
::= { wrpcPtpGroup 24 }
--x wrpcPtpConfigWord OBJECT-TYPE
--x SYNTAX Unsigned32
--x MAX-ACCESS read-only
--x STATUS current
--x DESCRIPTION
--x "Configuration word of PTP"
--x ::= { wrpcPtpGroup 25 }
wrpcPtpAlpha OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Alpha used by PTP"
::= { wrpcPtpGroup 26 }
-- ****************************************************************************
wrpcPtpConfigGroup OBJECT IDENTIFIER ::= { wrpcCore 6 }
wrpcPtpConfigRestart OBJECT-TYPE
SYNTAX INTEGER {
na(0),
restartPtp(1),
restartPtpSuccessful(100),
restartPtpFailed(200)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"restart PTP
restartPtp - trigger the restart of PTP
restartPtpSuccessful - PTP restart triggered
restartPtpFailed - failed to trigger PTP restart"
::= { wrpcPtpConfigGroup 1 }
wrpcPtpConfigApply OBJECT-TYPE
SYNTAX INTEGER {
na(0),
writeToFlashGivenSfp(1),
writeToFlashCurrentSfp(2),
writeToMemoryCurrentSfp(3),
eraseFlash(50),
applySuccessful(100),
applySuccessfulMatchFailed(101),
applyFailed(200),
applyFailedI2CError(201),
applyFailedDBFull(202),
applyFailedInvalidPN(203)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Apply configuration of the ptp
writeToFlashGivenSfp - Write delta TX/RX and alpha for provided SFP's PN to the sfp database in the flash. Perform sfp match.
writeToFlashCurrentSfp - Write delta TX/RX and alpha for currently used SFP to the sfp database in the flash. Perform sfp match.
writeToMemoryCurrentSfp - Write delta TX/RX and alpha for currently used SFP to the the memory. Do not perform sfp match.
eraseFlash - Erase sfp database in the flash. Do not perform sfp match.
applySuccessful - Configuration applied successfully.
applySuccessfulMatchFailed - SFP entry written, but failed to match with the plugged SFP.
applyFailed - Failed to apply configuration.
applyFailedI2CError - Failed to apply configuration due to communication error with the flash memory.
applyFailedDBFull - Failed to apply configuration. Database is full.
applyFailedInvalidPN - Invalid Product Number (PN) provided."
::= { wrpcPtpConfigGroup 2 }
wrpcPtpConfigSfpPn OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..16))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"SFP product number identifying which entry in the flash to update."
::= { wrpcPtpConfigGroup 3 }
wrpcPtpConfigDeltaTx OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Delta tx to be set"
::= { wrpcPtpConfigGroup 4 }
wrpcPtpConfigDeltaRx OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Delta rx to be set"
::= { wrpcPtpConfigGroup 5 }
wrpcPtpConfigAlpha OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Alpha to be set"
::= { wrpcPtpConfigGroup 6 }
-- ****************************************************************************
wrpcPortGroup OBJECT IDENTIFIER ::= { wrpcCore 7 }
wrpcPortLinkStatus OBJECT-TYPE
SYNTAX INTEGER {
na(0),
down(1),
up(2)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Whether the link is up or down"
::= { wrpcPortGroup 1 }
wrpcPortSfpPn OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..16))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"SFP product number identifying matched SFP."
::= { wrpcPortGroup 2 }
wrpcPortSfpInDB OBJECT-TYPE
SYNTAX INTEGER {
na(0),
notInDataBase(1),
inDataBase(2)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Whether the SFP is in data base or not"
::= { wrpcPortGroup 3 }
wrpcPortInternalTx OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"RX ptp packets"
::= { wrpcPortGroup 4 }
wrpcPortInternalRx OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"TX ptp packets"
::= { wrpcPortGroup 5 }
-- ****************************************************************************
wrpcSfpTable OBJECT-TYPE
SYNTAX SEQUENCE OF WrpcSfpEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Information of the SFPs database"
::= { wrpcCore 8 }
wrpcSfpEntry OBJECT-TYPE
SYNTAX WrpcSfpEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"An entry containing SFP entry"
INDEX { wrpcSfpIndex }
::= { wrpcSfpTable 1 }
WrpcSfpEntry ::=
SEQUENCE {
wrpcSfpIndex Unsigned32,
wrpcSfpPn DisplayString,
wrpcSfpDeltaTx Integer32,
wrpcSfpDeltaRx Integer32,
wrpcSfpAlpha Integer32
}
wrpcSfpIndex OBJECT-TYPE
SYNTAX Unsigned32
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Index for wrpcSfpTable"
::= { wrpcSfpEntry 1 }
wrpcSfpPn OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..16))
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"SFPs Product Number"
::= { wrpcSfpEntry 2 }
wrpcSfpDeltaTx OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"SFPs Delta TX"
::= { wrpcSfpEntry 3 }
wrpcSfpDeltaRx OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"SFPs Delta RX"
::= { wrpcSfpEntry 4 }
wrpcSfpAlpha OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"SFPs Alpha"
::= { wrpcSfpEntry 5 }
-- ****************************************************************************
END
......@@ -9,3 +9,4 @@ obj-$(CONFIG_WR_NODE) += lib/net.o
obj-$(CONFIG_IP) += lib/ipv4.o lib/arp.o lib/icmp.o lib/udp.o lib/bootp.o
obj-$(CONFIG_SYSLOG) += lib/syslog.o
obj-$(CONFIG_LATENCY_PROBE) += lib/latency.o
obj-$(CONFIG_SNMP) += lib/snmp.o
......@@ -24,8 +24,6 @@
#include "softpll_ng.h"
#include "ipv4.h"
#define min(x,y) ((x) < (y) ? (x) : (y))
static struct wrpc_socket *socks[NET_MAX_SOCKETS];
//#define net_verbose pp_printf
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2016 GSI (www.gsi.de), CERN (www.cern.ch)
* Author: Alessandro Rubini <a.rubini@gsi.de>
* Author: Adam Wujek <adam.wujek@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/*
* Naming:
* Each OID is divided into the limb and twig part.
* The twig part can be handled as a group or a table
*/
#include <string.h>
#include <wrpc.h>
#include <minic.h>
#include <limits.h>
#include "endpoint.h"
#include "ipv4.h"
#include "ptpd_netif.h"
#include "pps_gen.h"
#include "hw/memlayout.h"
#include "hw/etherbone-config.h"
#include "revision.h"
#include "softpll_ng.h"
#include "temperature.h"
#include "sfp.h"
#include "storage.h"
#ifndef htons
#define htons(x) x
#endif
#define ASN_BOOLEAN ((u_char)0x01)
#define ASN_INTEGER ((u_char)0x02)
#define ASN_OCTET_STR ((u_char)0x04)
#define ASN_NULL ((u_char)0x05)
#define ASN_OBJECT_ID ((u_char)0x06)
#define ASN_APPLICATION ((u_char)0x40)
#define ASN_IPADDRESS (ASN_APPLICATION | 0)
#define ASN_COUNTER (ASN_APPLICATION | 1)
#define ASN_GAUGE (ASN_APPLICATION | 2)
#define ASN_UNSIGNED (ASN_APPLICATION | 2) /* RFC 1902 - same as GAUGE */
#define ASN_TIMETICKS (ASN_APPLICATION | 3)
#define ASN_COUNTER64 (ASN_APPLICATION | 6)
/*
* (error codes from net-snmp's snmp.h)
* Error codes (the value of the field error-status in PDUs)
*/
#define SNMP_ERR_NOERROR (0)
#define SNMP_ERR_TOOBIG (1)
#define SNMP_ERR_NOSUCHNAME (2)
#define SNMP_ERR_BADVALUE (3)
#define SNMP_ERR_READONLY (4)
#define SNMP_ERR_GENERR (5)
#define SNMP_GET 0xA0
#define SNMP_GET_NEXT 0xA1
#define SNMP_GET_RESPONSE 0xA2
#define SNMP_SET 0xA3
#define SNMP_V1 0
#define SNMP_V2c 1
#define SNMP_V_MAX 1 /* Maximum supported version */
#ifdef CONFIG_SNMP_SET
#define SNMP_SET_ENABLED 1
#define SNMP_SET_FUNCTION(X) .set = (X)
#else
#define SNMP_SET_ENABLED 0
#define SNMP_SET_FUNCTION(X) .set = NULL
#endif
#define MASK_SET 0x1
#define MASK_GET 0x2
#define MASK_GET_NEXT 0x4
#define RETURN_FIRST 0x8
/* used to define write only OIDs */
#define NO_SET NULL
/* limit string len */
#define MAX_OCTET_STR_LEN 32
/* defines used by get_time function */
#define TIME_STRING 1
#define TIME_NUM 0
#define TYPE_MASK 1
#define UPTIME_MASK 2
#define TAI_MASK 4
#define TAI_STRING (void *) (TAI_MASK | TIME_STRING)
#define TAI_NUM (void *) (TAI_MASK | TIME_NUM)
#define UPTIME_NUM (void *) (UPTIME_MASK | TIME_NUM)
/* defines used by get_servo function */
#define SERVO_UPDATE_TIME (void *) 1
#define SERVO_ASYMMETRY (void *) 2
/* defines used by get_port function */
#define PORT_LINK_STATUS (void *) 1
/* defines for wrpcPtpConfigRestart */
#define restartPtp 1
#define restartPtpSuccessful 100
#define restartPtpFailed 200
/* defines for wrpcPtpConfigApply */
#define writeToFlashGivenSfp 1
#define writeToFlashCurrentSfp 2
#define writeToMemoryCurrentSfp 3
#define eraseFlash 50
#define applySuccessful 100
#define applySuccessfulMatchFailed 101
#define applyFailed 200
#define applyFailedI2CError 201
#define applyFailedDBFull 202
#define applyFailedInvalidPN 203
/* defines for wrpcTemperatureTable */
#define TABLE_ROW 1
#define TABLE_COL 0
#define TABLE_ENTRY 0
#define TABLE_FIRST_ROW 1
#define TABLE_FIRST_COL 2
/* Limit community length. Standard says nothing about maximum length, but we
* want to limit it to save memory */
#define MAX_COMMUNITY_LEN 32
/* Limit the request-id. Standard says max is 4 */
#define MAX_REQID_LEN 4
/* Limit the OID length */
#define MAX_OID_LEN 40
#define OID_FIELD_STRUCT(_oid, _getf, _setf, _asn, _type, _pointer, _field) { \
.oid_match = _oid, \
.oid_len = sizeof(_oid), \
.get = _getf, \
SNMP_SET_FUNCTION(_setf), \
.asn = _asn, \
.p = _pointer, \
.offset = offsetof(_type, _field), \
.data_size = sizeof(((_type *)0)->_field) \
}
#define OID_FIELD(_oid, _fname, _asn) { \
.oid_match = _oid, \
.oid_len = sizeof(_oid), \
.get = _fname, \
.asn = _asn, \
}
#define OID_FIELD_VAR(_oid, _getf, _setf, _asn, _pointer) { \
.oid_match = _oid, \
.oid_len = sizeof(_oid), \
.get = _getf, \
SNMP_SET_FUNCTION(_setf), \
.asn = _asn, \
.p = _pointer, \
.offset = 0, \
.data_size = sizeof(*_pointer) \
}
struct snmp_oid {
uint8_t *oid_match;
int (*get)(uint8_t *buf, struct snmp_oid *obj);
/* *set is needed only when support for SNMP SET is enabled */
int (*set)(uint8_t *buf, struct snmp_oid *obj);
void *p;
uint8_t oid_len;
uint8_t asn;
uint8_t offset; /* increase it if it is not enough */
uint8_t data_size;
};
#define OID_LIMB_FIELD(_oid, _func, _obj_array) { \
.oid_match = _oid, \
.oid_len = sizeof(_oid), \
.twig_func = _func, \
.obj_array = _obj_array, \
}
struct snmp_oid_limb {
uint8_t *oid_match;
int (*twig_func)(uint8_t *buf, uint8_t in_oid_limb_matched_len,
struct snmp_oid *obj, uint8_t flags);
struct snmp_oid *obj_array;
uint8_t oid_len;
};
static struct s_sfpinfo snmp_ptp_config;
static int ptp_config_apply_status;
static int ptp_restart_status;
extern struct pp_instance ppi_static;
static struct wr_servo_state *wr_s_state;
#define SNMP_HW_TYPE_LEN 32
char snmp_hw_type[SNMP_HW_TYPE_LEN] = CONFIG_SNMP_HW_TYPE;
/* __DATE__ and __TIME__ is already stored in struct spll_stats stats, but
* redefining it here makes code smaller than concatenate existing one */
static char *snmp_build_date = __DATE__ " " __TIME__;
/* store SNMP version, not fully used yet */
uint8_t snmp_version;
static uint8_t __snmp_queue[256];
static struct wrpc_socket __static_snmp_socket = {
.queue.buff = __snmp_queue,
.queue.size = sizeof(__snmp_queue),
};
static struct wrpc_socket *snmp_socket;
static int func_group(uint8_t *buf, uint8_t in_oid_limb_matched_len,
struct snmp_oid *obj, uint8_t flags);
static int func_table(uint8_t *buf, uint8_t in_oid_limb_matched_len,
struct snmp_oid *obj, uint8_t flags);
static int get_value(uint8_t *buf, uint8_t asn, void *p);
static int get_pp(uint8_t *buf, struct snmp_oid *obj);
static int get_p(uint8_t *buf, struct snmp_oid *obj);
static int get_i32sat(uint8_t *buf, uint8_t asn, void *p);
static int get_i32sat_pp(uint8_t *buf, struct snmp_oid *obj);
static int get_time(uint8_t *buf, struct snmp_oid *obj);
static int get_servo(uint8_t *buf, struct snmp_oid *obj);
static int get_port(uint8_t *buf, struct snmp_oid *obj);
static int get_temp(uint8_t *buf, struct snmp_oid *obj);
static int get_sfp(uint8_t *buf, struct snmp_oid *obj);
static int set_value(uint8_t *set_buff, struct snmp_oid *obj, void *p);
static int set_pp(uint8_t *buf, struct snmp_oid *obj);
static int set_p(uint8_t *buf, struct snmp_oid *obj);
static int set_ptp_restart(uint8_t *buf, struct snmp_oid *obj);
static int set_ptp_config(uint8_t *buf, struct snmp_oid *obj);
static void print_oid_verbose(uint8_t *oid, int len);
static void snmp_fix_size(uint8_t *buf, int size);
static uint8_t oid_wrpcVersionGroup[] = {0x2B,6,1,4,1,96,101,1,1};
static uint8_t oid_wrpcTimeGroup[] = {0x2B,6,1,4,1,96,101,1,2};
/* Include wrpcTemperatureEntry into OID */
static uint8_t oid_wrpcTemperatureTable[] = {0x2B,6,1,4,1,96,101,1,3,1};
static uint8_t oid_wrpcSpllStatusGroup[] = {0x2B,6,1,4,1,96,101,1,4};
static uint8_t oid_wrpcPtpGroup[] = {0x2B,6,1,4,1,96,101,1,5};
static uint8_t oid_wrpcPtpConfigGroup[] = {0x2B,6,1,4,1,96,101,1,6};
static uint8_t oid_wrpcPortGroup[] = {0x2B,6,1,4,1,96,101,1,7};
/* Include wrpcSfpEntry into OID */
static uint8_t oid_wrpcSfpTable[] = {0x2B,6,1,4,1,96,101,1,8,1};
/* wrpcVersionGroup */
static uint8_t oid_wrpcVersionHwType[] = {1,0};
static uint8_t oid_wrpcVersionSwVersion[] = {2,0};
static uint8_t oid_wrpcVersionSwBuildBy[] = {3,0};
static uint8_t oid_wrpcVersionSwBuildDate[] = {4,0};
/* wrpcTimeGroup */
static uint8_t oid_wrpcTimeTAI[] = {1,0};
static uint8_t oid_wrpcTimeTAIString[] = {2,0};
static uint8_t oid_wrpcTimeSystemUptime[] = {3,0};
/* wrpcTemperatureTable */
static uint8_t oid_wrpcTemperatureName[] = {2};
static uint8_t oid_wrpcTemperatureValue[] = {3};
/* wrpcSpllStatusGroup */
static uint8_t oid_wrpcSpllMode[] = {1,0};
static uint8_t oid_wrpcSpllIrqCnt[] = {2,0};
static uint8_t oid_wrpcSpllSeqState[] = {3,0};
static uint8_t oid_wrpcSpllAlignState[] = {4,0};
static uint8_t oid_wrpcSpllHlock[] = {5,0};
static uint8_t oid_wrpcSpllMlock[] = {6,0};
static uint8_t oid_wrpcSpllHY[] = {7,0};
static uint8_t oid_wrpcSpllMY[] = {8,0};
static uint8_t oid_wrpcSpllDelCnt[] = {9,0};
/* wrpcPtpGroup */
static uint8_t oid_wrpcPtpServoStateN[] = { 5,0};
static uint8_t oid_wrpcPtpClockOffsetPsHR[] = { 8,0};
static uint8_t oid_wrpcPtpSkew[] = { 9,0};
static uint8_t oid_wrpcPtpRTT[] = {10,0};
static uint8_t oid_wrpcPtpServoUpdates[] = {12,0};
static uint8_t oid_wrpcPtpServoUpdateTime[] = {13,0};
static uint8_t oid_wrpcPtpDeltaTxM[] = {14,0};
static uint8_t oid_wrpcPtpDeltaRxM[] = {15,0};
static uint8_t oid_wrpcPtpDeltaTxS[] = {16,0};
static uint8_t oid_wrpcPtpDeltaRxS[] = {17,0};
static uint8_t oid_wrpcPtpServoStateErrCnt[] = {18,0};
static uint8_t oid_wrpcPtpClockOffsetErrCnt[] = {19,0};
static uint8_t oid_wrpcPtpRTTErrCnt[] = {20,0};
static uint8_t oid_wrpcPtpAsymmetry[] = {22,0};
static uint8_t oid_wrpcPtpTX[] = {23,0};
static uint8_t oid_wrpcPtpRX[] = {24,0};
static uint8_t oid_wrpcPtpAlpha[] = {26,0};
/* wrpcPtpConfigGroup */
static uint8_t oid_wrpcPtpConfigRestart[] = {1,0};
static uint8_t oid_wrpcPtpConfigApply[] = {2,0};
static uint8_t oid_wrpcPtpConfigSfpPn[] = {3,0};
static uint8_t oid_wrpcPtpConfigDeltaTx[] = {4,0};
static uint8_t oid_wrpcPtpConfigDeltaRx[] = {5,0};
static uint8_t oid_wrpcPtpConfigAlpha[] = {6,0};
/* wrpcPortGroup */
static uint8_t oid_wrpcPortLinkStatus[] = {1,0};
static uint8_t oid_wrpcPortSfpPn[] = {2,0};
static uint8_t oid_wrpcPortSfpInDB[] = {3,0};
static uint8_t oid_wrpcPortInternalTX[] = {4,0};
static uint8_t oid_wrpcPortInternalRX[] = {5,0};
/* oid_wrpcSfpTable */
static uint8_t oid_wrpcSfpPn[] = {2};
static uint8_t oid_wrpcSfpDeltaTx[] = {3};
static uint8_t oid_wrpcSfpDeltaRx[] = {4};
static uint8_t oid_wrpcSfpAlpha[] = {5};
/* NOTE: to have SNMP_GET_NEXT working properly this array has to be sorted by
OIDs */
/* wrpcVersionGroup */
static struct snmp_oid oid_array_wrpcVersionGroup[] = {
OID_FIELD_VAR( oid_wrpcVersionHwType, get_p, NO_SET, ASN_OCTET_STR, &snmp_hw_type),
OID_FIELD_VAR( oid_wrpcVersionSwVersion, get_pp, NO_SET, ASN_OCTET_STR, &build_revision),
OID_FIELD_VAR( oid_wrpcVersionSwBuildBy, get_pp, NO_SET, ASN_OCTET_STR, &build_by),
OID_FIELD_VAR( oid_wrpcVersionSwBuildDate, get_pp, NO_SET, ASN_OCTET_STR, &snmp_build_date),
{ 0, }
};
/* wrpcTimeGroup */
static struct snmp_oid oid_array_wrpcTimeGroup[] = {
OID_FIELD_VAR( oid_wrpcTimeTAI, get_time, NO_SET, ASN_COUNTER64, TAI_NUM),
OID_FIELD_VAR( oid_wrpcTimeTAIString, get_time, NO_SET, ASN_OCTET_STR, TAI_STRING),
OID_FIELD_VAR( oid_wrpcTimeSystemUptime, get_time, NO_SET, ASN_TIMETICKS, UPTIME_NUM),
{ 0, }
};
/* wrpcTemperatureTable */
static struct snmp_oid oid_array_wrpcTemperatureTable[] = {
OID_FIELD_VAR( oid_wrpcTemperatureName, get_temp, NO_SET, ASN_OCTET_STR, NULL),
OID_FIELD_VAR( oid_wrpcTemperatureValue, get_temp, NO_SET, ASN_OCTET_STR, NULL),
{ 0, }
};
/* wrpcSpllStatusGroup */
static struct snmp_oid oid_array_wrpcSpllStatusGroup[] = {
OID_FIELD_VAR( oid_wrpcSpllMode, get_p, NO_SET, ASN_INTEGER, &stats.mode),
OID_FIELD_VAR( oid_wrpcSpllIrqCnt, get_p, NO_SET, ASN_COUNTER, &stats.irq_cnt),
OID_FIELD_VAR( oid_wrpcSpllSeqState, get_p, NO_SET, ASN_INTEGER, &stats.seq_state),
OID_FIELD_VAR( oid_wrpcSpllAlignState, get_p, NO_SET, ASN_INTEGER, &stats.align_state),
OID_FIELD_VAR( oid_wrpcSpllHlock, get_p, NO_SET, ASN_COUNTER, &stats.H_lock),
OID_FIELD_VAR( oid_wrpcSpllMlock, get_p, NO_SET, ASN_COUNTER, &stats.M_lock),
OID_FIELD_VAR( oid_wrpcSpllHY, get_p, NO_SET, ASN_INTEGER, &stats.H_y),
OID_FIELD_VAR( oid_wrpcSpllMY, get_p, NO_SET, ASN_INTEGER, &stats.M_y),
OID_FIELD_VAR( oid_wrpcSpllDelCnt, get_p, NO_SET, ASN_COUNTER, &stats.del_cnt),
{ 0, }
};
/* wrpcPtpGroup */
static struct snmp_oid oid_array_wrpcPtpGroup[] = {
OID_FIELD_STRUCT(oid_wrpcPtpServoStateN, get_pp, NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, state),
OID_FIELD_STRUCT(oid_wrpcPtpClockOffsetPsHR, get_i32sat_pp,NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, offset),
OID_FIELD_STRUCT(oid_wrpcPtpSkew, get_i32sat_pp,NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, skew),
OID_FIELD_STRUCT(oid_wrpcPtpRTT, get_pp, NO_SET, ASN_COUNTER64, struct wr_servo_state, &wr_s_state, picos_mu),
OID_FIELD_STRUCT(oid_wrpcPtpServoUpdates, get_pp, NO_SET, ASN_COUNTER, struct wr_servo_state, &wr_s_state, update_count),
OID_FIELD_VAR( oid_wrpcPtpServoUpdateTime, get_servo, NO_SET, ASN_COUNTER64, SERVO_UPDATE_TIME),
OID_FIELD_STRUCT(oid_wrpcPtpDeltaTxM, get_pp, NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, delta_tx_m),
OID_FIELD_STRUCT(oid_wrpcPtpDeltaRxM, get_pp, NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, delta_rx_m),
OID_FIELD_STRUCT(oid_wrpcPtpDeltaTxS, get_pp, NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, delta_tx_s),
OID_FIELD_STRUCT(oid_wrpcPtpDeltaRxS, get_pp, NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, delta_rx_s),
OID_FIELD_STRUCT(oid_wrpcPtpServoStateErrCnt,get_pp, NO_SET, ASN_COUNTER, struct wr_servo_state, &wr_s_state, n_err_state),
OID_FIELD_STRUCT(oid_wrpcPtpClockOffsetErrCnt,get_pp, NO_SET, ASN_COUNTER, struct wr_servo_state, &wr_s_state, n_err_offset),
OID_FIELD_STRUCT(oid_wrpcPtpRTTErrCnt, get_pp, NO_SET, ASN_COUNTER, struct wr_servo_state, &wr_s_state, n_err_delta_rtt),
OID_FIELD_VAR( oid_wrpcPtpAsymmetry, get_servo, NO_SET, ASN_COUNTER64, SERVO_ASYMMETRY),
OID_FIELD_VAR( oid_wrpcPtpTX, get_p, NO_SET, ASN_COUNTER, &ppi_static.ptp_tx_count),
OID_FIELD_VAR( oid_wrpcPtpRX, get_p, NO_SET, ASN_COUNTER, &ppi_static.ptp_rx_count),
OID_FIELD_STRUCT(oid_wrpcPtpAlpha, get_pp, NO_SET, ASN_INTEGER, struct wr_servo_state, &wr_s_state, fiber_fix_alpha),
{ 0, }
};
/* wrpcPtpConfigGroup */
static struct snmp_oid oid_array_wrpcPtpConfigGroup[] = {
OID_FIELD_VAR( oid_wrpcPtpConfigRestart, get_p, set_ptp_restart,ASN_INTEGER, &ptp_restart_status),
OID_FIELD_VAR( oid_wrpcPtpConfigApply, get_p, set_ptp_config, ASN_INTEGER, &ptp_config_apply_status),
OID_FIELD_VAR( oid_wrpcPtpConfigSfpPn, get_p, set_p, ASN_OCTET_STR, &snmp_ptp_config.pn),
OID_FIELD_VAR( oid_wrpcPtpConfigDeltaTx, get_p, set_p, ASN_INTEGER, &snmp_ptp_config.dTx),
OID_FIELD_VAR( oid_wrpcPtpConfigDeltaRx, get_p, set_p, ASN_INTEGER, &snmp_ptp_config.dRx),
OID_FIELD_VAR( oid_wrpcPtpConfigAlpha, get_p, set_p, ASN_INTEGER, &snmp_ptp_config.alpha),
{ 0, }
};
/* wrpcPortGroup */
static struct snmp_oid oid_array_wrpcPortGroup[] = {
OID_FIELD_VAR( oid_wrpcPortLinkStatus, get_port, NO_SET, ASN_INTEGER, PORT_LINK_STATUS),
OID_FIELD_VAR( oid_wrpcPortSfpPn, get_p, NO_SET, ASN_OCTET_STR, &sfp_pn),
OID_FIELD_VAR( oid_wrpcPortSfpInDB, get_p, NO_SET, ASN_INTEGER, &sfp_in_db),
OID_FIELD_VAR( oid_wrpcPortInternalTX, get_p, NO_SET, ASN_COUNTER, &minic.tx_count),
OID_FIELD_VAR( oid_wrpcPortInternalRX, get_p, NO_SET, ASN_COUNTER, &minic.rx_count),
{ 0, }
};
/* wrpcSfpTable */
static struct snmp_oid oid_array_wrpcSfpTable[] = {
OID_FIELD_VAR( oid_wrpcSfpPn, get_sfp, NULL, ASN_OCTET_STR, NULL),
OID_FIELD_VAR( oid_wrpcSfpDeltaTx, get_sfp, NULL, ASN_INTEGER, NULL),
OID_FIELD_VAR( oid_wrpcSfpDeltaRx, get_sfp, NULL, ASN_INTEGER, NULL),
OID_FIELD_VAR( oid_wrpcSfpAlpha, get_sfp, NULL, ASN_INTEGER, NULL),
{ 0, }
};
/* Array of groups and tables */
static struct snmp_oid_limb oid_limb_array[] = {
OID_LIMB_FIELD(oid_wrpcVersionGroup, func_group, oid_array_wrpcVersionGroup),
OID_LIMB_FIELD(oid_wrpcTimeGroup, func_group, oid_array_wrpcTimeGroup),
OID_LIMB_FIELD(oid_wrpcTemperatureTable, func_table, oid_array_wrpcTemperatureTable),
OID_LIMB_FIELD(oid_wrpcSpllStatusGroup, func_group, oid_array_wrpcSpllStatusGroup),
OID_LIMB_FIELD(oid_wrpcPtpGroup, func_group, oid_array_wrpcPtpGroup),
OID_LIMB_FIELD(oid_wrpcPtpConfigGroup, func_group, oid_array_wrpcPtpConfigGroup),
OID_LIMB_FIELD(oid_wrpcPortGroup, func_group, oid_array_wrpcPortGroup),
OID_LIMB_FIELD(oid_wrpcSfpTable, func_table, oid_array_wrpcSfpTable),
{ 0, }
};
static void snmp_init(void)
{
/* Use UDP engine activated by function arguments */
snmp_socket = ptpd_netif_create_socket(&__static_snmp_socket, NULL,
PTPD_SOCK_UDP, 161 /* snmp */);
/* TODO: check if pointer(s) is initialized already */
wr_s_state =
&((struct wr_data *)ppi_static.ext_data)->servo_state;
}
static int func_group(uint8_t *buf, uint8_t in_oid_limb_matched_len,
struct snmp_oid *twigs_array, uint8_t flags)
{
int oid_twig_len = buf[0] - in_oid_limb_matched_len;
uint8_t *in_oid = &buf[1];
uint8_t *in_oid_limb_end = &buf[1 + in_oid_limb_matched_len];
int8_t cmp_result = 0;
uint8_t oid_twig_matching_len;
int return_len;
struct snmp_oid *oid;
uint8_t return_first = 0;
if (flags & RETURN_FIRST)
return_first = 1;
for (oid = twigs_array; oid->oid_len; oid++) {
snmp_verbose("%s: checking twig: ", __func__);
print_oid_verbose(oid->oid_match, oid->oid_len);
snmp_verbose("\n");
if (return_first) {
/* For the "return first" case, usually the length of
* the requested oid is smaller than
* in_oid_limb_matched_len, so the special case is
* needed */
oid_twig_matching_len = oid->oid_len;
} else {
/* Decide what is shorter the twig part of the OID, or
* the matching part */
oid_twig_matching_len = min(oid_twig_len,
oid->oid_len);
}
if ((flags & MASK_GET || flags & MASK_SET)
&& (oid_twig_len != oid->oid_len)) {
/* For GET and SET lengths have to be equal, we can
* skip to the next OID */
continue;
}
if (return_first == 0) {
/* Compare the OID's twig part. For the first match we
* want to use this OID anyway */
cmp_result = memcmp(oid->oid_match, in_oid_limb_end,
oid_twig_matching_len);
if (cmp_result == 0
&& (flags & MASK_GET_NEXT)
&& oid_twig_matching_len == oid->oid_len) {
/* Exact match for the GET_NEXT, go to the
* next OID */
continue;
}
}
if ((cmp_result == 0) /* exact match */
|| ((flags & MASK_GET_NEXT) && cmp_result > 0) /* Found next */
|| (return_first)) {
if (flags & MASK_GET_NEXT) {
snmp_verbose("%s: OID match for GET_NEXT\n",
__func__);
/* Copy new OID */
snmp_verbose("%s: return OID ", __func__);
print_oid_verbose(oid->oid_match, oid->oid_len);
snmp_verbose("\n");
memcpy(in_oid_limb_end, oid->oid_match,
oid->oid_len);
/* Update OID len, since it might be different,
* this is only the length of the twig part
* add the rest after return */
buf[0] = oid->oid_len;
}
snmp_verbose("%s: using OID: ", __func__);
print_oid_verbose(in_oid, in_oid_limb_matched_len);
snmp_verbose(" ");
print_oid_verbose(in_oid_limb_end, oid->oid_len);
snmp_verbose(" calling %p\n", oid->get);
/* Handle the SET request */
if (flags & MASK_SET) {
snmp_verbose("%s SET\n", __func__);
if (!oid->set) {
snmp_verbose("%s: no SET function!\n",
__func__);
return -SNMP_ERR_READONLY;
}
/* Finally call the SET function */
return_len = oid->set(in_oid_limb_end
+ oid->oid_len, oid);
if (return_len < 0) /* if error */ {
snmp_verbose("%s: SET error %d\n",
__func__, return_len);
return return_len;
}
}
/* Finally call the GET function */
snmp_verbose("%s GET\n", __func__);
return_len = oid->get(in_oid_limb_end + oid->oid_len,
oid);
/* add the length of twig part of the OID */
if (!return_len)
continue;
return_len += oid->oid_len;
return return_len;
}
if (cmp_result > 0) {
/* we went too far, no hope to find anything more */
return 0;
}
}
return 0;
}
static int func_table(uint8_t *buf, uint8_t in_oid_limb_matched_len,
struct snmp_oid *twigs_array, uint8_t flags)
{
int oid_twig_len = buf[0] - in_oid_limb_matched_len;
uint8_t *in_oid_limb_end = &buf[1 + in_oid_limb_matched_len];
int8_t cmp_result = 0;
uint8_t oid_twig_matching_len;
struct snmp_oid *oid;
struct snmp_oid leaf_obj;
int return_first = 0;
int i;
int get_next_increase_oid = 0;
int snmp_get_next = 0;
int return_len;
if (flags & MASK_SET) {
/* We don't support SETs yet */
return -SNMP_ERR_READONLY;
}
if (flags & RETURN_FIRST)
return_first = 1;
snmp_verbose("%s: table wants coordinates:", __func__);
for (i = 0; i < oid_twig_len; i++)
snmp_verbose(" %d", in_oid_limb_end[i]);
snmp_verbose("\n");
if (flags & MASK_GET_NEXT) {
/* By default increase OID for SNMP_GET_NEXT */
get_next_increase_oid = 1;
snmp_get_next = 1;
}
for (oid = twigs_array; oid->oid_len; oid++) {
snmp_verbose("%s: checking twig: ", __func__);
print_oid_verbose(oid->oid_match, oid->oid_len);
snmp_verbose("\n");
/* Decide what is shorter the rest of the oid, or the
* matching part */
oid_twig_matching_len = min(oid_twig_len, oid->oid_len);
cmp_result = memcmp(oid->oid_match, in_oid_limb_end,
oid_twig_matching_len);
if ((return_first)
|| (snmp_get_next && cmp_result == 0 && (oid_twig_len < oid->oid_len + 1))
|| (snmp_get_next && cmp_result > 0)) {
/* For the "return first" case, usually the length of
* the requested oid is smaller than
* in_oid_limb_matched_len, so the special case is
* needed */
/* Use the matched twig part of the OID */
memcpy(in_oid_limb_end, oid->oid_match,
oid->oid_len);
/* use the first row */
*(in_oid_limb_end + oid->oid_len) = TABLE_FIRST_ROW;
/* Don't increase OID for SNMP_GET_NEXT */
get_next_increase_oid = 0;
break;
}
if ((cmp_result == 0) /* We want a match */
&& (
/* And the exact OID len */
(oid_twig_len == oid->oid_len + 1)
/* oid_twig_len can be longer for snmp_get_next */
|| (snmp_get_next && (oid_twig_len > oid->oid_len + 1))
)
) {
break;
}
}
if (!oid->oid_len) {
/* Return 0 if the end of twigs_array was reached */
return 0;
}
snmp_verbose("%s: OID matched for table: ", __func__);
print_oid_verbose(oid->oid_match, oid->oid_len + 1);
snmp_verbose("%s\n", snmp_get_next ? "GET_NEXT" : "");
/* Copy OID information to the leaf_obj */
leaf_obj.oid_len = oid->oid_len;
leaf_obj.oid_match = in_oid_limb_end;
leaf_obj.asn = oid->asn;
leaf_obj.p = oid->p;
if (get_next_increase_oid)
in_oid_limb_end[TABLE_ROW]++;
/* Get the value for the leaf */
return_len = oid->get(&in_oid_limb_end[oid->oid_len + 1], &leaf_obj);
if (return_len == 0 && get_next_increase_oid) {
oid++;
/* Check if OID is valid */
if (!oid->oid_len)
return 0;
/* Copy the new OID */
memcpy(in_oid_limb_end, oid->oid_match,
oid->oid_len);
/* Copy the new row number */
*(in_oid_limb_end + oid->oid_len) = TABLE_FIRST_ROW;
/* Update leaf_obj with changed values */
leaf_obj.oid_len = oid->oid_len;
leaf_obj.asn = oid->asn;
leaf_obj.p = oid->p;
/* Get the value for the leaf in the next column, first row */
return_len = oid->get(&in_oid_limb_end[oid->oid_len + 1],
&leaf_obj);
/* If no value is available for first row in next column,
* it means previous column was the last one */
if (return_len == 0)
return 0;
}
/* Leaf not found */
if (return_len == 0)
return 0;
if (return_len < 0) /* If error */ {
snmp_verbose("%s: GET error %d\n",
__func__, return_len);
return return_len;
}
return_len += oid->oid_len + 1;
if (snmp_get_next || return_first) {
buf[0] = oid->oid_len + 1;
}
return return_len;
}
static int get_servo(uint8_t *buf, struct snmp_oid *obj)
{
uint64_t tmp_uint64;
switch ((int) obj->p) {
case (int)SERVO_ASYMMETRY:
tmp_uint64 = wr_s_state->picos_mu - 2LL * wr_s_state->delta_ms;
return get_value(buf, obj->asn, &tmp_uint64);
case (int)SERVO_UPDATE_TIME:
tmp_uint64 = ((uint64_t) wr_s_state->update_time.seconds) *
1000000000LL
+ wr_s_state->update_time.nanoseconds;
return get_value(buf, obj->asn, &tmp_uint64);
default:
break;
}
return -1;
}
static int get_port(uint8_t *buf, struct snmp_oid *obj)
{
int32_t tmp_int32;
switch ((int) obj->p) {
case (int)PORT_LINK_STATUS:
/* overkill, since we need the link to be up to use SNMP */
tmp_int32 = 1 + ep_link_up(NULL);
return get_value(buf, obj->asn, &tmp_int32);
default:
break;
}
return -1;
}
static int get_time(uint8_t *buf, struct snmp_oid *obj)
{
uint64_t secs;
uint32_t tics;
char *datestr;
int req = (int)obj->p;
if (req & UPTIME_MASK) {
/* It will overflow after ~49 days. The counter in FPGA is
* implemented as 32bit. */
tics = timer_get_tics() / 10;
return get_value(buf, obj->asn, &tics);
} else if (req & TAI_MASK) {
shw_pps_gen_get_time(&secs, NULL);
}
if ((req & TYPE_MASK) == TIME_STRING) {
datestr = format_time(secs, TIME_FORMAT_SORTED);
return get_value(buf, obj->asn, datestr);
} else /* TAI_NUM */
return get_value(buf, obj->asn, &secs);
}
static int get_value(uint8_t *buf, uint8_t asn, void *p)
{
uint32_t tmp;
uint64_t tmp_uint64;
uint8_t *oid_data = buf + 2;
uint8_t *len;
buf[0] = asn;
len = &buf[1];
switch (asn) {
case ASN_COUNTER:
case ASN_UNSIGNED:
case ASN_INTEGER:
case ASN_TIMETICKS:
tmp = htonl(*(uint32_t *)p);
memcpy(oid_data, &tmp, sizeof(tmp));
*len = sizeof(tmp);
snmp_verbose("%s: 0x%x\n", __func__, *(uint32_t *)p);
break;
case ASN_COUNTER64:
if (snmp_version == SNMP_V1) {
/* There is no support for 64bit counters in SNMPv1 */
return 0;
}
tmp_uint64 = *(uint64_t *)p;
memcpy(oid_data, &tmp_uint64, sizeof(tmp_uint64));
*len = sizeof(tmp_uint64);
/* Our printf has disabled printing of 64bit values */
snmp_verbose("%s: 64bit value 0x%08x|%08x\n", __func__,
(uint32_t)(tmp_uint64 >> 32), (uint32_t)tmp_uint64);
break;
case ASN_OCTET_STR:
*len = strnlen((char *)p, MAX_OCTET_STR_LEN - 1);
memcpy(oid_data, p, *len + 1);
snmp_verbose("%s: %s len %d\n", __func__, (char *)p, *len);
break;
default:
return 0;
}
return 2 + buf[1];
}
static int get_pp(uint8_t *buf, struct snmp_oid *obj)
{
/* calculate pointer, treat obj-> as void ** */
return get_value(buf, obj->asn, *(void **)obj->p + obj->offset);
}
static int get_p(uint8_t *buf, struct snmp_oid *obj)
{
/* calculate pointer, treat obj-> as void * */
return get_value(buf, obj->asn, obj->p + obj->offset);
}
static int get_i32sat(uint8_t *buf, uint8_t asn, void *p)
{
int64_t tmp_int64;
int32_t tmp_int32;
/* if we want to modify an object we need to do that on a copy,
* otherwise pointers to the values will be overwritten */
tmp_int64 = *(int64_t *)p;
/* Our printf has disabled printing of 64bit values */
snmp_verbose("%s: 64bit value 0x%08x|%08x\n", __func__,
(int32_t)((tmp_int64) >> 32), (uint32_t)tmp_int64);
/* saturate int32 */
if (tmp_int64 >= INT_MAX)
tmp_int64 = INT_MAX;
else if (tmp_int64 <= INT_MIN)
tmp_int64 = INT_MIN;
/* get_value will print saturated value anyway */
tmp_int32 = (int32_t) tmp_int64;
return get_value(buf, asn, &tmp_int32);
}
static int get_i32sat_pp(uint8_t *buf, struct snmp_oid *obj)
{
/* calculate pointer, treat obj-> as void ** */
return get_i32sat(buf, obj->asn,
*(void **)obj->p + obj->offset);
}
static int get_temp(uint8_t *buf, struct snmp_oid *obj)
{
struct wrc_onetemp *p;
int l = 0, i = TABLE_FIRST_ROW;
int32_t t;
int row;
int col;
char buffer[20];
row = obj->oid_match[TABLE_ROW];
col = obj->oid_match[TABLE_COL];
snmp_verbose("%s: row%d, col%d\n", __func__, row, col);
for (p = wrc_temp_getnext(NULL); p; p = wrc_temp_getnext(p), i++) {
if (row == i) {
t = p->t;
if (col == 2) {
sprintf(buffer, "%s", p->name);
break;
}
if (col == 3) {
if (t == TEMP_INVALID) {
l += sprintf(buffer, "INVALID");
break;
}
if (t < 0) {
t = -(signed)t;
l += sprintf(buffer, "-");
}
sprintf(buffer, "%d.%04d", t >> 16,
((t & 0xffff) * 10 * 1000 >> 16));
break;
}
}
}
if (p) {
/* data found return it */
return get_value(buf, obj->asn, buffer);
}
return 0;
}
static int get_sfp(uint8_t *buf, struct snmp_oid *obj)
{
int i;
struct s_sfpinfo sfp;
int row;
int col;
void *p = NULL;
int sfpcount = 1;
int temp;
char sfp_pn[SFP_PN_LEN + 1];
row = obj->oid_match[TABLE_ROW];
col = obj->oid_match[TABLE_COL];
snmp_verbose("%s: row%d, col%d\n", __func__, row, col);
for (i = 1; i < sfpcount+1; ++i) {
sfpcount = storage_get_sfp(&sfp, SFP_GET, i - 1);
if (sfpcount == 0) {
snmp_verbose("SFP database empty...\n");
return 0;
} else if (sfpcount == -1) {
snmp_verbose("SFP database corrupted...\n");
return 0;
}
snmp_verbose("%d: PN:", i);
for (temp = 0; temp < SFP_PN_LEN; ++temp)
snmp_verbose("%c", sfp.pn[temp]);
snmp_verbose(" dTx: %8d dRx: %8d alpha: %8d\n", sfp.dTx,
sfp.dRx, sfp.alpha);
if (row == i) {
if (col == 2) {
/* Use local buffer for sfp PN, since stored
* version is without null character at
* the end */
memcpy(sfp_pn, sfp.pn, SFP_PN_LEN);
sfp_pn[SFP_PN_LEN] = '\0';
p = sfp_pn;
break;
}
if (col == 3) {
p = &sfp.dTx;
break;
}
if (col == 4) {
p = &sfp.dRx;
break;
}
if (col == 5) {
p = &sfp.alpha;
break;
}
}
}
if (p) {
/* Data found, return it */
return get_value(buf, obj->asn, p);
}
return 0;
}
static int set_value(uint8_t *set_buff, struct snmp_oid *obj, void *p)
{
uint8_t asn_incoming = set_buff[0];
uint8_t asn_expected = obj->asn;
uint8_t len = set_buff[1];
uint8_t *oid_data = set_buff + 2;
uint32_t tmp_u32;
if (asn_incoming != asn_expected) { /* wrong asn */
snmp_verbose("%s: wrong asn 0x%02x, expected 0x%02x\n",
__func__, asn_incoming, asn_expected);
return -SNMP_ERR_BADVALUE;
}
switch (asn_incoming) {
case ASN_UNSIGNED:
case ASN_INTEGER:
if (len > sizeof(uint32_t))
return -SNMP_ERR_BADVALUE;
tmp_u32 = 0;
memcpy(&tmp_u32, oid_data, len);
tmp_u32 = ntohl(tmp_u32);
/* move data when shorter than 4 bytes */
tmp_u32 = tmp_u32 >> ((4 - len) * 8);
*(uint32_t *)p = tmp_u32;
snmp_verbose("%s: 0x%08x 0x%08x len %d\n", __func__,
*(uint32_t *)p, tmp_u32, len);
break;
case ASN_OCTET_STR:
/* Check the string size */
if (len > obj->data_size) {
snmp_verbose("%s: string too long (%d), max expected %d\n",
len, obj->data_size,__func__);
return -SNMP_ERR_BADVALUE;
}
memcpy(p, oid_data, len);
*(char *)(p + len) = '\0';
snmp_verbose("%s: %s len %d\n", __func__, (char *)p, len);
break;
default:
return 0;
}
return len + 2;
}
static int set_pp(uint8_t *buf, struct snmp_oid *obj)
{
/* calculate pointer, treat obj-> as void ** */
return set_value(buf, obj, *(void **)obj->p + obj->offset);
}
static int set_p(uint8_t *buf, struct snmp_oid *obj)
{
/* calculate pointer, treat obj-> as void * */
return set_value(buf, obj, obj->p + obj->offset);
}
static int set_ptp_restart(uint8_t *buf, struct snmp_oid *obj)
{
int ret;
int32_t *restart_val;
restart_val = obj->p;
ret = set_value(buf, obj, restart_val);
if (ret <= 0)
return ret;
switch (*restart_val) {
case restartPtp:
snmp_verbose("%s: restart PTP\n", __func__);
wrc_ptp_stop();
wrc_ptp_start();
*restart_val = restartPtpSuccessful;
break;
default:
*restart_val = restartPtpFailed;
}
return ret;
}
static int set_ptp_config(uint8_t *buf, struct snmp_oid *obj)
{
int ret;
int32_t *apply_mode;
int temp;
apply_mode = obj->p;
ret = set_value(buf, obj, apply_mode);
if (ret <= 0)
return ret;
switch (*apply_mode) {
case writeToMemoryCurrentSfp:
sfp_deltaTx = snmp_ptp_config.dTx;
sfp_deltaRx = snmp_ptp_config.dRx;
sfp_alpha = snmp_ptp_config.alpha;
/* Since ppsi does not support update of deltas in runtime,
* we need to restart the ppsi */
pp_printf("SNMP: SFP updated in memory, restart PTP\n");
wrc_ptp_stop();
wrc_ptp_start();
*apply_mode = applySuccessful;
break;
case writeToFlashCurrentSfp:
memcpy(snmp_ptp_config.pn, sfp_pn, SFP_PN_LEN);
/* continue with writeToFlashGivenSfp */
case writeToFlashGivenSfp:
if (snmp_ptp_config.pn[0] == '\0') { /* empty PN */
snmp_verbose("%s: Invalid PN\n", __func__);
*apply_mode = applyFailedInvalidPN;
break;
}
temp = strnlen(snmp_ptp_config.pn, SFP_PN_LEN);
/* padding with spaces */
while (temp < SFP_PN_LEN)
snmp_ptp_config.pn[temp++] = ' ';
/* add a sfp to the DB */
temp = storage_get_sfp(&snmp_ptp_config, SFP_ADD, 0);
if (temp == EE_RET_DBFULL) {
snmp_verbose("%s: SFP DB is full\n", __func__);
*apply_mode = applyFailedDBFull;
break;
} else if (temp == EE_RET_I2CERR) {
snmp_verbose("%s: I2C error\n", __func__);
*apply_mode = applyFailedI2CError;
break;
}
/* perform a sfp match */
temp = sfp_match();
if (temp) {
snmp_verbose("%s: Match error (%d)\n", __func__, temp);
*apply_mode = applySuccessfulMatchFailed;
break;
}
*apply_mode = applySuccessful;
break;
case eraseFlash:
if (storage_sfpdb_erase() == EE_RET_I2CERR)
*apply_mode = applyFailed;
else
*apply_mode = applySuccessful;
break;
default:
*apply_mode = applyFailed;
}
snmp_verbose("%s: delta tx: %d\ndelta rx: %d\nalpha: %d\n", __func__,
snmp_ptp_config.dTx, snmp_ptp_config.dRx,
snmp_ptp_config.alpha);
return ret;
}
/*
* Perverse... snmpwalk does getnext anyways.
*
* We support the following ones:
* RFC1213-MIB::sysName.0 (string) .1.3.6.1.2.1.1.5.0
* HOST-RESOURCES-MIB::hrSystemUptime.0 (ticks) .1.3.6.1.2.1.25.1.1.0
* HOST-RESOURCES-MIB::hrSystemDate.0 (string) .1.3.6.1.2.1.25.1.2.0
*
* The request for sysname is like this (-c public):
* 30 29 sequence of 0x29
* 02 01 00 int: snmp version 1 (0x00)
* 04 06 70 75 62 6C 69 63 string of 6: "public"
* A0 1C get request of 0x1c
* 02 04 27 05 36 A9 int of 4: request ID
* 02 01 00 int of 1: error
* 02 01 00 int of 1: error index
* 30 0E sequence of 0x0e
* 30 0C sequence of 0x0c
* 06 08 2B 06 01 02 01 01 05 00 oid of 8: .1.3.6.1.2.1.1.5.0
* 05 00 null
*
*
* Response for sysname:
* 30 30
* 02 01 00
* 04 06 70 75 62 6C 69 63 "public"
* A2 23
* 02 04 27 05 36 A9 seqID
* 02 01 00
* 02 01 00
* 30 15
* 30 13
* 06 08 2B 06 01 02 01 01 05 00
* 04 07 6C 61 70 74 6F 70 6F "laptopo"
*
*/
/*
* The following array defines the frame format, sizes are ignored on read
* but must be filled on write, so mark them specially
*/
#define BYTE_SIZE 0xff
#define BYTE_IGNORE 0xfe
#define BYTE_PDU 0xfd
#define BYTE_ERROR 0xfc
#define BYTE_ERROR_INDEX 0xfb
#define BYTE_VERSION 0xfa
#define BYTE_REQ_SIZE 0xf9
/* indexes of bytes in snmp packet */
#define BYTE_PACKET_SIZE_i 1
#define BYTE_COMMUNITY_LEN_i 6
/* indexes below are without the length of the community string */
#define BYTE_PDU_i 7
/* below indexes are without the length of request ID */
#define BYTE_REQ_SIZE_i 10
#define BYTE_ERROR_i 13
#define BYTE_ERROR_INDEX_i 16
#define BYTE_OIDLEN_INDEX_i 22
static uint8_t match_array[] = {
0x30, BYTE_SIZE,
0x02, 0x01, BYTE_VERSION, /* ASN_INTEGER, size 1 byte, version */
0x04, 0x06, /* ASN_OCTET_STR, strlen("public") */
0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, /* "public" */
BYTE_PDU, BYTE_SIZE, /* SNMP packet type, size of following data */
0x02, BYTE_REQ_SIZE, /*
* ASN_INTEGER, size in bytes, Request/Message ID */
0x02, 0x01, BYTE_ERROR, /* ASN_INTEGER, size 1 byte, error type */
0x02, 0x01, BYTE_ERROR_INDEX, /* ASN_INTEGER, size 1 byte,
* error index */
0x30, BYTE_SIZE,
0x30, BYTE_SIZE,
0x06, /* ASN_OBJECT_ID */
/* OID length and oid follows */
};
static void print_oid_verbose(uint8_t *oid, int len)
{
/*uint8_t * oid_end = oid + len;*/
int i = 0;
if (*oid == 0x2b) {/* print first byte */
snmp_verbose(".1.3");
i = 1;
}
for (; i < len; i++)
snmp_verbose(".%d", *(oid + i));
}
/* fix sizes of fields in the SNMP packet */
static void snmp_fix_size(uint8_t *buf, int size)
{
int remain;
int a_i, h_i;
size--;
/* now fix all size fields and change PDU */
for (a_i = 0, h_i = 0; a_i < sizeof(match_array); a_i++, h_i++) {
remain = size - h_i;
if (match_array[a_i] == BYTE_PDU)
buf[h_i] = SNMP_GET_RESPONSE;
if (match_array[a_i] == BYTE_REQ_SIZE) {
h_i += buf[h_i];
continue;
}
if (match_array[a_i] != BYTE_SIZE)
continue;
snmp_verbose("%s: offset %i 0x%02x is len %i\n", __func__,
h_i, h_i, remain);
buf[h_i] = remain;
}
}
/* prepare packet to return error, leave the rest of packet as it was */
static uint8_t snmp_prepare_error(uint8_t *buf, uint8_t error)
{
uint8_t ret_size;
uint8_t community_len;
uint8_t shift;
uint8_t reqid_size;
uint8_t oid_len;
community_len = buf[BYTE_COMMUNITY_LEN_i];
/* If community_len is too long, it will return malformed
* packet, but at least something useful for debugging */
shift = min(community_len, MAX_COMMUNITY_LEN);
buf[BYTE_PDU_i + shift] = SNMP_GET_RESPONSE;
reqid_size = buf[BYTE_REQ_SIZE_i + shift];
shift += min(reqid_size, MAX_REQID_LEN);
buf[BYTE_ERROR_i + shift] = error;
buf[BYTE_ERROR_INDEX_i + shift] = 1;
oid_len = buf[BYTE_OIDLEN_INDEX_i + shift];
shift += min(oid_len, MAX_OID_LEN);
/* write ASN_NULL after the OID */
buf[BYTE_OIDLEN_INDEX_i + shift + 1] = ASN_NULL;
buf[BYTE_OIDLEN_INDEX_i + shift + 2] = 0;
ret_size = BYTE_OIDLEN_INDEX_i + shift + 2 + 1;
/* recalculate sizes of the fields inside packet */
snmp_fix_size(buf, ret_size);
snmp_verbose("%s: error returning %i bytes\n", __func__, ret_size);
return ret_size;
}
/* And, now, work out your generic frame responder... */
static int snmp_respond(uint8_t *buf)
{
struct snmp_oid_limb *oid_limb = NULL;
uint8_t *newbuf = NULL;
uint8_t *new_oid;
uint8_t *buf_oid_len;
int a_i, h_i;
uint8_t snmp_mode = 0;
int8_t cmp_result;
uint8_t oid_branch_matching_len;
/* Hack to avoid compiler warnings "function defined but not used" for
* functions below when SNMP compiled without SET support.
* These functions will never be called here. */
if (0) {
set_p(NULL, NULL);
set_pp(NULL, NULL);
set_ptp_config(NULL, NULL);
set_ptp_restart(NULL, NULL);
}
for (a_i = 0, h_i = 0; a_i < sizeof(match_array); a_i++, h_i++) {
switch (match_array[a_i]) {
case BYTE_SIZE:
case BYTE_IGNORE:
case BYTE_ERROR:
case BYTE_ERROR_INDEX:
continue;
case BYTE_REQ_SIZE:
h_i += buf[h_i];
continue;
case BYTE_VERSION:
snmp_version = buf[h_i];
if (snmp_version > SNMP_V_MAX)
return snmp_prepare_error(buf,
SNMP_ERR_GENERR);
continue;
case BYTE_PDU:
if (SNMP_GET == buf[h_i])
snmp_mode = MASK_GET;
if (SNMP_GET_NEXT == buf[h_i])
snmp_mode = MASK_GET_NEXT;
if (SNMP_SET_ENABLED && (SNMP_SET == buf[h_i]))
snmp_mode = MASK_SET;
if (!(snmp_mode))
return snmp_prepare_error(buf,
SNMP_ERR_GENERR);
break;
default:
if (buf[h_i] != match_array[a_i])
return snmp_prepare_error(buf,
SNMP_ERR_GENERR);
}
}
snmp_verbose("%s: header match ok\n", __func__);
buf_oid_len = buf + h_i;
newbuf = buf + h_i + 1;
new_oid = buf + h_i + 1;
/* Save the size of the incoming OID */
for (oid_limb = oid_limb_array; oid_limb->oid_len; oid_limb++) {
int res;
uint8_t flags;
snmp_verbose("%s: checking oid: ", __func__);
print_oid_verbose(oid_limb->oid_match, oid_limb->oid_len);
snmp_verbose("\n");
oid_branch_matching_len = min(oid_limb->oid_len, *buf_oid_len);
if ((snmp_mode & MASK_GET || snmp_mode & MASK_SET)
&& oid_limb->oid_len > *buf_oid_len) {
/* For GET and SET incoming OID cannot be shorter than
* the one we check now */
snmp_verbose("%s: continue\n", __func__);
continue;
}
cmp_result = memcmp(oid_limb->oid_match, new_oid,
oid_branch_matching_len);
flags = snmp_mode;
if ((snmp_mode & MASK_GET_NEXT)
&& ((cmp_result > 0)
|| ((oid_limb->oid_len >= *buf_oid_len) && (cmp_result == 0))
)) {
/* return first item in the match within group */
flags |= RETURN_FIRST;
/* we want to return the considered oid */
oid_branch_matching_len = oid_limb->oid_len;
snmp_verbose("%s: return first oid from the branch\n",
__func__);
}
if (((oid_limb->oid_len == oid_branch_matching_len) && (cmp_result == 0)) /* exact match */
|| flags & RETURN_FIRST /* SNMP_GET_NEXT, we're after the OID we got */
) {
/* branch part of the oid found ! */
snmp_verbose("%s: group match\n", __func__);
if (snmp_mode & MASK_GET_NEXT
|| (flags & RETURN_FIRST)) {
/* copy new OID */
memcpy(new_oid, oid_limb->oid_match,
oid_limb->oid_len);
}
/* pass buf from the oid len, then there is oid itself,
* value type, value length and value itself */
res = oid_limb->twig_func(buf_oid_len,
oid_branch_matching_len,
oid_limb->obj_array,
flags);
if (res > 0) {
/* OID found and the return value is filled! */
if (snmp_mode & MASK_GET_NEXT
|| (flags & RETURN_FIRST)) {
/* Update OID len, since it might be
* different. Len of the part within
* the group was already added in the
* twig_func function */
*buf_oid_len += oid_limb->oid_len;
}
newbuf += oid_limb->oid_len;
newbuf += res;
break;
} else if (res == 0) {
/* oid is not within searched group, take
* the next oid */
continue;
} else if (res < 0) {
return snmp_prepare_error(buf,
-res);
}
}
if (cmp_result > 0) {
/* we went too far,no hope to find anything more for
* GET and SET, this case for GET_NEXT was considered
* earlier */
oid_limb = NULL;
break;
}
continue;
}
if (!oid_limb || !oid_limb->oid_len) {
snmp_verbose("%s: OID not found! ", __func__);
print_oid_verbose(new_oid, *buf_oid_len);
snmp_verbose("\n");
/* also for last GET_NEXT element */
return snmp_prepare_error(buf, SNMP_ERR_NOSUCHNAME);
}
snmp_fix_size(buf, newbuf - buf);
snmp_verbose("%s: returning %i bytes\n", __func__, newbuf - buf);
return newbuf - buf;
}
/* receive snmp through the UDP mechanism */
static int snmp_poll(void)
{
struct wr_sockaddr addr;
uint8_t buf[200];
int len;
/* no need to wait for IP address: we won't get queries */
len = ptpd_netif_recvfrom(snmp_socket, &addr,
buf, sizeof(buf), NULL);
if (len <= UDP_END + sizeof(match_array))
return 0;
len = snmp_respond(buf + UDP_END);
if (len < 0)
return 0;
len += UDP_END;
fill_udp(buf, len, NULL);
ptpd_netif_sendto(snmp_socket, &addr, buf, len, 0);
return 1;
}
DEFINE_WRC_TASK(snmp) = {
.name = "snmp",
.enable = &link_status,
.init = snmp_init,
.job = snmp_poll,
};
......@@ -13,6 +13,7 @@ const char *build_revision = stats.commit_id;
const char *build_date = stats.build_date;
const char *build_time = stats.build_time;
const char *build_by = stats.build_by;
/*
* We export softpll internal status to the ARM cpu, for SNMP. Thus,
* we place this structure at a known address in the linker script
......@@ -22,9 +23,12 @@ struct spll_stats stats __attribute__((section(".stats"))) = {
.ver = SPLL_STATS_VER,
#ifdef CONFIG_DETERMINISTIC_BINARY
.build_date = "",
.build_time = "",
.build_by = "",
#else
.build_date = __DATE__,
.build_time = __TIME__,
.build_by = __GIT_USR__,
#endif
.commit_id = __GIT_VER__,
};
......@@ -7,18 +7,18 @@
*
* Released according to the GNU GPL, version 2 or any later version.
*/
/* Command: sfp
Arguments: subcommand [subcommand-specific args]
Description: SFP detection/database manipulation.
Subcommands:
add vendor_type delta_tx delta_rx alpha - adds an SFP to the database, with given alpha/delta_rx/delta_rx values
show - shows the SFP database
match - tries to get calibration parameters from DB for a detected SFP
erase - cleans the SFP database
detect - detects the transceiver type
*/
/* Command: sfp
* Arguments: subcommand [subcommand-specific args]
*
* Description: SFP detection/database manipulation.
* Subcommands:
* add <product_number> <delta_tx> <delta_rx> <alpha> - adds an SFP to
* the database, with given alpha/delta_rx/delta_tx values
* show - shows the SFP database
* match - detects the transceiver type and tries to get calibration parameters
* from DB for a detected SFP
* erase - cleans the SFP database
*/
#include <string.h>
#include <stdlib.h>
......@@ -34,87 +34,90 @@
static int cmd_sfp(const char *args[])
{
int8_t sfpcount = 1, i, temp;
int8_t sfpcount = 1, i, temp, ret;
struct s_sfpinfo sfp;
static char pn[SFP_PN_LEN + 1] = "\0";
if (args[0] && !strcasecmp(args[0], "detect")) {
if (!sfp_present())
pp_printf("No SFP.\n");
else
sfp_read_part_id(pn);
pn[16] = 0;
pp_printf("%s\n", pn);
return 0;
if (!args[0]) {
pp_printf("Wrong parameter\n");
return -EINVAL;
}
// else if (!strcasecmp(args[0], "i2cscan"))
// {
// mi2c_scan(WRPC_FMC_I2C);
// return 0;
// }
else if (!strcasecmp(args[0], "erase")) {
if (storage_sfpdb_erase() ==
EE_RET_I2CERR)
if (!strcasecmp(args[0], "erase")) {
if (storage_sfpdb_erase() == EE_RET_I2CERR) {
pp_printf("Could not erase DB\n");
return -EIO;
}
return 0;
} else if (args[4] && !strcasecmp(args[0], "add")) {
if (strlen(args[1]) > 16)
temp = 16;
else
temp = strlen(args[1]);
temp = strnlen(args[1], SFP_PN_LEN);
for (i = 0; i < temp; ++i)
sfp.pn[i] = args[1][i];
while (i < 16)
while (i < SFP_PN_LEN)
sfp.pn[i++] = ' '; //padding
sfp.dTx = atoi(args[2]);
sfp.dRx = atoi(args[3]);
sfp.alpha = atoi(args[4]);
temp = storage_get_sfp(&sfp, 1, 0);
if (temp == EE_RET_DBFULL)
temp = storage_get_sfp(&sfp, SFP_ADD, 0);
if (temp == EE_RET_DBFULL) {
pp_printf("SFP DB is full\n");
else if (temp == EE_RET_I2CERR)
return -ENOSPC;
} else if (temp == EE_RET_I2CERR) {
pp_printf("I2C error\n");
else
pp_printf("%d SFPs in DB\n", temp);
} else if (args[0] && !strcasecmp(args[0], "show")) {
return -EIO;
} else if (temp < 0) {
pp_printf("SFP database error (%d)\n", temp);
return -EFAULT;
}
pp_printf("%d SFPs in DB\n", temp);
return 0;
} else if (!strcasecmp(args[0], "show")) {
for (i = 0; i < sfpcount; ++i) {
temp = storage_get_sfp(&sfp, 0, i);
if (!i) {
sfpcount = temp; //only in first round valid sfpcount is returned from storage_get_sfp
if (sfpcount == 0 || sfpcount == 0xFF) {
pp_printf("SFP database empty...\n");
return 0;
} else if (sfpcount == -1) {
pp_printf("SFP database corrupted...\n");
return 0;
}
sfpcount = storage_get_sfp(&sfp, SFP_GET, i);
if (sfpcount == 0) {
pp_printf("SFP database empty\n");
return 0;
} else if (sfpcount < 0) {
pp_printf("SFP database error (%d)\n",
sfpcount);
return -EFAULT;
}
pp_printf("%d: PN:", i + 1);
for (temp = 0; temp < 16; ++temp)
for (temp = 0; temp < SFP_PN_LEN; ++temp)
pp_printf("%c", sfp.pn[temp]);
pp_printf(" dTx: %d, dRx: %d, alpha: %d\n", sfp.dTx,
pp_printf(" dTx: %8d dRx: %8d alpha: %8d\n", sfp.dTx,
sfp.dRx, sfp.alpha);
}
} else if (args[0] && !strcasecmp(args[0], "match")) {
if (pn[0] == '\0') {
pp_printf("Run sfp detect first\n");
return 0;
return 0;
} else if (!strcasecmp(args[0], "match")) {
ret = sfp_match();
if (ret == -ENODEV) {
pp_printf("No SFP.\n");
return ret;
}
if (ret == -EIO) {
pp_printf("SFP read error\n");
return ret;
}
strncpy(sfp.pn, pn, SFP_PN_LEN);
if (storage_match_sfp(&sfp) > 0) {
pp_printf("SFP matched, dTx=%d, dRx=%d, alpha=%d\n",
sfp.dTx, sfp.dRx, sfp.alpha);
sfp_deltaTx = sfp.dTx;
sfp_deltaRx = sfp.dRx;
sfp_alpha = sfp.alpha;
} else
/* SFP read correctly */
for (temp = 0; temp < SFP_PN_LEN; ++temp)
pp_printf("%c", sfp_pn[temp]);
pp_printf("\n");
if (ret == -ENXIO) {
pp_printf("Could not match to DB\n");
return 0;
} else if (args[0] && !strcasecmp(args[0], "ena")) {
if(!args[1])
return -EINVAL;
return ret;
}
/* match successful */
pp_printf("SFP matched, dTx=%d dRx=%d alpha=%d\n",
sfp_deltaTx, sfp_deltaRx, sfp_alpha);
return ret;
} else if (args[1] && !strcasecmp(args[0], "ena")) {
ep_sfp_enable(atoi(args[1]));
return 0;
} else {
pp_printf("Wrong parameter\n");
return -EINVAL;
}
return 0;
}
......
......@@ -18,12 +18,23 @@
#define SUPPORT ""
#endif
#ifdef CONFIG_DETERMINISTIC_BINARY
#define DETERMINISTIC_BINARY 1
#else
#define DETERMINISTIC_BINARY 0
#endif
static int cmd_ver(const char *args[])
{
int hwram = sysc_get_memsize();
pp_printf("WR Core build: %s%s\n", build_revision, SUPPORT);
pp_printf("Built: %s %s\n", build_date, build_time); /* may be empty */
/* may be empty if build with CONFIG_DETERMINISTIC_BINARY */
if (DETERMINISTIC_BINARY)
pp_printf("Deterministic binary build\n");
else
pp_printf("Built: %s %s by %s\n", build_date, build_time,
build_by);
pp_printf("Built for %d kB RAM, stack is %d bytes\n",
CONFIG_RAMSIZE / 1024, CONFIG_STACKSIZE);
/* hardware reports memory size, with a 16kB granularity */
......
/*
* 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_export.h: public SoftPLL stats API header */
#ifndef __SOFTPLL_EXPORT_H
#define __SOFTPLL_EXPORT_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
#define SEQ_START_EXT 1
#define SEQ_WAIT_EXT 2
#define SEQ_START_HELPER 3
#define SEQ_WAIT_HELPER 4
#define SEQ_START_MAIN 5
#define SEQ_WAIT_MAIN 6
#define SEQ_DISABLED 7
#define SEQ_READY 8
#define SEQ_CLEAR_DACS 9
#define SEQ_WAIT_CLEAR_DACS 10
#define AUX_DISABLED 1
#define AUX_LOCK_PLL 2
#define AUX_ALIGN_PHASE 3
#define AUX_READY 4
#define ALIGN_STATE_EXT_OFF 0
#define ALIGN_STATE_START 1
#define ALIGN_STATE_INIT_CSYNC 2
#define ALIGN_STATE_WAIT_CSYNC 3
#define ALIGN_STATE_START_ALIGNMENT 7
#define ALIGN_STATE_WAIT_SAMPLE 4
#define ALIGN_STATE_COMPENSATE_DELAY 5
#define ALIGN_STATE_LOCKED 6
#define ALIGN_STATE_START_MAIN 8
#define ALIGN_STATE_WAIT_CLKIN 9
#define ALIGN_STATE_WAIT_PLOCK 10
#define SPLL_STATS_VER 3
/* info reported through .stat section */
/* due to endiannes problem strings has to be 4 bytes alligned */
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;
int start_cnt;
char commit_id[32];
char build_date[16];
char build_time[16];
char build_by[32];
};
extern struct spll_stats stats;
#endif /* __SOFTPLL_EXPORT_H */
......@@ -37,22 +37,6 @@ int spll_n_chan_ref, spll_n_chan_out;
#define MAIN_CHANNEL (spll_n_chan_ref)
#define SEQ_START_EXT 1
#define SEQ_WAIT_EXT 2
#define SEQ_START_HELPER 3
#define SEQ_WAIT_HELPER 4
#define SEQ_START_MAIN 5
#define SEQ_WAIT_MAIN 6
#define SEQ_DISABLED 7
#define SEQ_READY 8
#define SEQ_CLEAR_DACS 9
#define SEQ_WAIT_CLEAR_DACS 10
#define AUX_DISABLED 1
#define AUX_LOCK_PLL 2
#define AUX_ALIGN_PHASE 3
#define AUX_READY 4
static const struct stringlist_entry seq_states [] =
{
{ SEQ_START_EXT, "start-ext" },
......@@ -641,20 +625,19 @@ int spll_update()
}
ret += spll_update_aux_clocks();
/* currently we have statistics only in the switch */
if (is_wr_switch) {
stats.sequence++;
stats.mode = softpll.mode;
stats.irq_cnt = softpll.irq_count;
stats.seq_state = softpll.seq_state;
stats.align_state = softpll.ext.align_state;
stats.H_lock = softpll.helper.ld.locked;
stats.M_lock = softpll.mpll.ld.locked;
stats.H_y = softpll.helper.pi.y;
stats.M_y = softpll.mpll.pi.y;
stats.del_cnt = softpll.delock_count;
stats.sequence++;
}
/* store statistics */
stats.sequence++;
stats.mode = softpll.mode;
stats.irq_cnt = softpll.irq_count;
stats.seq_state = softpll.seq_state;
stats.align_state = softpll.ext.align_state;
stats.H_lock = softpll.helper.ld.locked;
stats.M_lock = softpll.mpll.ld.locked;
stats.H_y = softpll.helper.pi.y;
stats.M_y = softpll.mpll.pi.y;
stats.del_cnt = softpll.delock_count;
stats.sequence++;
return ret != 0;
}
......
......@@ -14,6 +14,7 @@
#include <stdint.h>
#include "util.h"
#include "softpll_export.h"
#include "spll_defs.h"
#include "spll_common.h"
#include "spll_debug.h"
......@@ -23,20 +24,6 @@
#include "spll_external.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
......@@ -125,31 +112,6 @@ int spll_get_dac(int out_channel);
void check_vco_frequencies(void);
#define SPLL_STATS_VER 2
/* info reported through .stat section */
/* due to endiannes problem strings has to be 4 bytes alligned */
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;
int start_cnt;
char commit_id[32];
char build_date[16];
char build_time[16];
};
/* This only exists in wr-switch, but we should use it always */
extern struct spll_stats stats;
/*
* Aux and main state:
* used to be in .c file, but we need it here for memory dumping
......
......@@ -14,17 +14,6 @@
#include "softpll_ng.h"
#include "irq.h"
#define ALIGN_STATE_EXT_OFF 0
#define ALIGN_STATE_START 1
#define ALIGN_STATE_INIT_CSYNC 2
#define ALIGN_STATE_WAIT_CSYNC 3
#define ALIGN_STATE_START_ALIGNMENT 7
#define ALIGN_STATE_WAIT_SAMPLE 4
#define ALIGN_STATE_COMPENSATE_DELAY 5
#define ALIGN_STATE_LOCKED 6
#define ALIGN_STATE_START_MAIN 8
#define ALIGN_STATE_WAIT_CLKIN 9
#define ALIGN_STATE_WAIT_PLOCK 10
#define ALIGN_SAMPLE_PERIOD 100000
#define ALIGN_TARGET 0
......
bats
snmp_test_config.bash
ifndef TARGET_IP
$(error TARGET_IP is not set)
endif
all: test
prepare: bats/libexec/bats
bats/libexec/bats:
@echo "bats not installed!"
@echo "Please perform the following commands:"
@echo "git clone https://github.com/sstephenson/bats"
# be sure which version we use
@echo "cd bats; git checkout 03608115"
@exit 1
test: prepare
bats/libexec/bats snmp_tests_*.bats
SNMP_OPTIONS_NO_M="-On -c public -v 2c "
# be sure you have run download-mibs to download MIBs
SNMP_OPTIONS="$SNMP_OPTIONS_NO_M -m WR-WRPC-MIB -M +/var/lib/mibs/ietf:../../lib"
TOTAL_NUM_OIDS_EXPECT_TEXT="4 temperature sensors, 4 entries in the SFPs database"
# number of OIDs expected
TOTAL_NUM_OIDS=69
helper_snmpget() {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP $1 | grep "$2" | wc -l)"
[ "$result" -eq 1 ]
}
helper_snmpget_oidnotfound() {
run snmpget $SNMP_OPTIONS $TARGET_IP $1
[ "$status" -eq 2 ]
}
helper_snmpget_oidfound() {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP $1 | grep "$1" | wc -l)"
[ "$result" -eq 1 ]
}
helper_snmpgetnext() {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP $1 | grep "$2" | wc -l)"
[ "$result" -eq 1 ]
}
helper_snmpset() {
result="$(snmpset $SNMP_OPTIONS $TARGET_IP $1 = "$2" | grep "$2" | wc -l)"
[ "$result" -eq 1 ]
}
helper_erase_sfp_database() {
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = eraseFlash | grep applySuccessful | wc -l)"
[ "$result" -eq 1 ]
}
load snmp_test_config
@test "Host up $TARGET_IP" {
if [ x"$TARGET_IP" = "x" ]; then
echo "no TARGET_IP set"
fi
# to know if out target system is up
run ping -c 1 $TARGET_IP -W 2
[ "$status" -eq 0 ]
}
@test "Check the presence of snmpget" {
# to know if we have snmpget available
run command -v snmpget
[ "$status" -eq 0 ]
}
@test "Check the presence of snmpgetnext" {
# to know if we have snmpgetnext available
run command -v snmpgetnext
[ "$status" -eq 0 ]
}
@test "Check the presence of snmpwalk" {
# to know if we have snmpwalk available
run command -v snmpwalk
[ "$status" -eq 0 ]
}
@test "Check the presence of snmpset" {
# to know if we have snmpset available
run command -v snmpset
[ "$status" -eq 0 ]
}
load snmp_test_config
load snmp_test_helpers
@test "snmpget existing oid 1.3.6.1.4.1.96.101.1.1.1.0" {
helper_snmpget 1.3.6.1.4.1.96.101.1.1.1.0 1.3.6.1.4.1.96.101.1.1.1.0
}
@test "snmpget existing oid 1.3.6.1.4.1.96.101.1.1.2.0" {
helper_snmpget 1.3.6.1.4.1.96.101.1.1.2.0 1.3.6.1.4.1.96.101.1.1.2.0
[ "$result" -eq 1 ]
}
@test "snmpget non existing oid 1.3.6.1.4.1.96.101.1.1.2" {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.2 | grep 1.3.6.1.4.1.96.101.1.1.2 | wc -l)"
[ "$result" -eq 0 ]
}
@test "snmpget non existing oid 1.3.6.1.4.1.96.101.1.1" {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1 | grep 1.3.6.1.4.1.96.101.1.1 | wc -l)"
[ "$result" -eq 0 ]
}
@test "snmpget non existing oid 1.3.6.1.4.1.96.101.1" {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1 | grep 1.3.6.1.4.1.96.101.1 | wc -l)"
[ "$result" -eq 0 ]
}
@test "snmpget non existing oid 1.3.6.1.4.1.96.101" {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1 | grep 1.3.6.1.4.1.96.101.1 | wc -l)"
[ "$result" -eq 0 ]
}
@test "snmpget non existing oid 1.3.6.1.4.1.96" {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96 | grep 1.3.6.1.4.1.96 | wc -l)"
[ "$result" -eq 0 ]
}
@test "snmpget non existing oid 1.3.6.1.4.1" {
result="$(snmpget $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1 | grep 1.3.6.1.4.1 | wc -l)"
[ "$result" -eq 0 ]
}
load snmp_test_config
@test "Get next object after 1.3.6.1.4.1.96.101.1.1.3.0, check if other returned" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.3.0 | grep 1.3.6.1.4.1.96.101.1.1.3.0 | wc -l)"
[ "$result" -eq 0 ]
}
@test "Get next object after 1.3.6.1.4.1.96.101.1.1.3.0, check if correct returned" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.3.0 | grep 1.3.6.1.4.1.96.101.1.1.4.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after 1.3.6.1.4.1.95 (first object)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.95 | grep 1.3.6.1.4.1.96.101.1.1.1.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after the last object (getnext 1.3.6.1.4.1.97)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.97 | wc -l)"
[ "$result" -eq 0 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96 (oid too short)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96 | grep 1.3.6.1.4.1.96.101.1.1.1.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.0 (oid too short with 0 at the end)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.0 | grep 1.3.6.1.4.1.96.101.1.1.1.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101 (oid too short)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101 | grep 1.3.6.1.4.1.96.101.1.1.1.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1 (oid too short)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1 | grep 1.3.6.1.4.1.96.101.1.1.1.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1.1 (oid too short)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1 | grep 1.3.6.1.4.1.96.101.1.1.1.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1.1.1 (missing 0 at the end)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.1 | grep 1.3.6.1.4.1.96.101.1.1.1.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1.1.2 (missing 0 at the end)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.2 | grep 1.3.6.1.4.1.96.101.1.1.2.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1.1.1.0 (jump to the next oid in the branch)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.1.0 | grep 1.3.6.1.4.1.96.101.1.1.2.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1.1.1.1 (too deep in the branch)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.1.1 | grep 1.3.6.1.4.1.96.101.1.1.2.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1.1.1.1.1 (too deep in the branch)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.1.1.1 | grep 1.3.6.1.4.1.96.101.1.1.2.0 | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get next object after oid 1.3.6.1.4.1.96.101.1.1.1.1.1.0 (too deep in the branch)" {
result="$(snmpgetnext $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1.1.1.1.0 | grep 1.3.6.1.4.1.96.101.1.1.2.0 | wc -l)"
[ "$result" -eq 1 ]
}
load snmp_test_config
@test "Get Counter64 OID (WR-WRPC-MIB::wrpcPtpAsymmetry.0) with SNMPv2" {
result="$(snmpget $SNMP_OPTIONS -Os $TARGET_IP wrpcPtpAsymmetry.0 | grep "wrpcPtpAsymmetry.0" | wc -l)"
[ "$result" -eq 1 ]
}
@test "Get Counter64 OID (WR-WRPC-MIB::wrpcPtpAsymmetry.0) with SNMPv1 (not supported)" {
# SNMP v1 does not support counter64, so it should return oid not found
result="$(snmpget $SNMP_OPTIONS -Os -v 1 $TARGET_IP wrpcPtpAsymmetry.0 | grep "wrpcPtpAsymmetry.0" | wc -l)"
[ "$result" -eq 0 ]
}
@test "Getnext OID before Counter64 WR-WRPC-MIB::wrpcPtpAsymmetry.0 with SNMPv1" {
# should point after the Counter64 (wrpcPtpRTTErrCnt.0) to the wrpcPtpTx.0
result="$(snmpgetnext $SNMP_OPTIONS -Os -v 1 $TARGET_IP wrpcPtpRTTErrCnt.0 | grep "wrpcPtpTx.0" | wc -l)"
[ "$result" -eq 1 ]
}
@test "Getnext Counter64 OID WR-WRPC-MIB::wrpcPtpAsymmetry.0 with SNMPv1" {
# should point after Counter64 (wrpcPtpAsymmetry.0) to the wrpcPtpTx.0
result="$(snmpgetnext $SNMP_OPTIONS -Os -v 1 $TARGET_IP wrpcPtpAsymmetry.0 | grep "wrpcPtpTx.0" | wc -l)"
[ "$result" -eq 1 ]
}
load snmp_test_config
load snmp_test_helpers
@test "set wrpcPtpConfigDeltaTx" {
helper_snmpset wrpcPtpConfigDeltaTx.0 141415
helper_snmpget wrpcPtpConfigDeltaTx.0 141415
}
@test "set read only wrpcSpllHlock" {
run snmpset $SNMP_OPTIONS $TARGET_IP wrpcSpllHlock.0 = 141415
[ "$status" -eq 2 ]
}
@test "set wrpcPtpConfigDeltaTx with two different values" {
helper_snmpset wrpcPtpConfigDeltaTx.0 141415
helper_snmpget wrpcPtpConfigDeltaTx.0 141415
helper_snmpset wrpcPtpConfigDeltaTx.0 151516
helper_snmpget wrpcPtpConfigDeltaTx.0 151516
}
@test "set wrpcPtpConfigDeltaRx with two different values" {
helper_snmpset wrpcPtpConfigDeltaRx.0 141416
helper_snmpget wrpcPtpConfigDeltaRx.0 141416
helper_snmpset wrpcPtpConfigDeltaRx.0 151517
helper_snmpget wrpcPtpConfigDeltaRx.0 151517
}
@test "set wrpcPtpConfigAlpha with two different values" {
helper_snmpset wrpcPtpConfigAlpha.0 141417
helper_snmpget wrpcPtpConfigAlpha.0 141417
helper_snmpset wrpcPtpConfigAlpha.0 151518
helper_snmpget wrpcPtpConfigAlpha.0 151518
}
@test "set wrpcPtpConfigSfpPn with two different values" {
helper_snmpset wrpcPtpConfigSfpPn.0 "TEST sfp"
helper_snmpget wrpcPtpConfigSfpPn.0 "TEST sfp"
helper_snmpset wrpcPtpConfigSfpPn.0 "sfp other"
helper_snmpget wrpcPtpConfigSfpPn.0 "sfp other"
}
@test "set wrpcPtpConfigSfpPn with empty value" {
helper_snmpset wrpcPtpConfigSfpPn.0 ""
helper_snmpget wrpcPtpConfigSfpPn.0 ""
}
@test "set wrpcPtpConfigSfpPn with too long value (error from host)" {
# set known value first
helper_snmpset wrpcPtpConfigSfpPn.0 "TEST sfp1"
# set too long, bad length (error from snmpget program)
run snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigSfpPn.0 = "0123456789012345678"
[ "$status" -eq 1 ]
# expect value to be not changed
helper_snmpget wrpcPtpConfigSfpPn.0 "TEST sfp1"
}
@test "set wrpcPtpConfigSfpPn with too long value (erorr from target)" {
# set known value first
helper_snmpset wrpcPtpConfigSfpPn.0 "TEST sfp2"
# set too long, bad length (erorr from target)
run snmpset $SNMP_OPTIONS_NO_M $TARGET_IP .1.3.6.1.4.1.96.101.1.6.3.0 s "0123456789012345678"
echo $status
[ "$status" -eq 2 ]
# expect value to be not changed
helper_snmpget wrpcPtpConfigSfpPn.0 "TEST sfp2"
}
@test "set wrong type of wrpcPtpConfigSfpPn" {
# set known value first
helper_snmpset wrpcPtpConfigSfpPn.0 "TEST sfp3"
# set too long, bad length (erorr from target)
run snmpset $SNMP_OPTIONS_NO_M $TARGET_IP .1.3.6.1.4.1.96.101.1.6.3.0 i "012345678"
echo $status
[ "$status" -eq 2 ]
# expect value to be not changed
helper_snmpget wrpcPtpConfigSfpPn.0 "TEST sfp3"
}
@test "erase sfp database" {
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = eraseFlash | grep applySuccessful | wc -l)"
[ "$result" -eq 1 ]
}
@test "erase sfp database test helper" {
helper_erase_sfp_database
}
@test "add sfp with invalid PN to the database" {
# Empty PN is invalid
# erase database first
helper_erase_sfp_database
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "11112"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "11113"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "11114"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 ""
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep "applyFailedInvalidPN" | wc -l)"
[ "$result" -eq 1 ]
}
@test "add sfp to the database" {
# erase database first
helper_erase_sfp_database
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 1234
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 4343
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 1258
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashCurrentSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
}
@test "add 4 sfps to the database" {
# following entries should be written to the database
# unfortunately it is not possible to verify these entries now via snmp
# sfp show
# 1: PN:test PN1 dTx: 11112 dRx: 11113 alpha: 11114
# 2: PN:test PN2 dTx: 22223 dRx: 22224 alpha: 22225
# 3: PN:test PN3 dTx: 33334 dRx: 33335 alpha: 33336
# 4: PN:test PN4 dTx: 44445 dRx: 44446 alpha: 44447
# erase database first
helper_erase_sfp_database
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "11112"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "11113"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "11114"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN1"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
echo $result
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "22223"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "22224"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "22225"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN2"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "33334"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "33335"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "33336"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN3"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "44445"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "44446"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "44447"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN4"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
}
@test "add 5 sfps to the database" {
# following entries should be written to the database, 5th should generate error
# unfortunately it is not possible to verify these entries now via snmp
# sfp show
# 1: PN:test PN1 dTx: 11112 dRx: 11113 alpha: 11114
# 2: PN:test PN2 dTx: 22223 dRx: 22224 alpha: 22225
# 3: PN:test PN3 dTx: 33334 dRx: 33335 alpha: 33336
# 4: PN:test PN4 dTx: 44445 dRx: 44446 alpha: 44447
# erase database first
helper_erase_sfp_database
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "11112"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "11113"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "11114"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN1"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "22223"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "22224"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "22225"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN2"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "33334"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "33335"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "33336"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN3"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "44445"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "44446"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "44447"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN4"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "55556"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "55557"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "55558"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN5"
# add sfp to the database, it is full now
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep "applyFailedDBFull" | wc -l)"
[ "$result" -eq 1 ]
}
@test "add 4 sfps to the database, test replacement" {
# following entries should be written to the database, 5th should replace second entry
# unfortunately it is not possible to verify these entries now via snmp
# sfp show
# 1: PN:test PN1 dTx: 11112 dRx: 11113 alpha: 11114
# 2: PN:test PN2 dTx: 22223 dRx: 22224 alpha: 22225
# 3: PN:test PN3 dTx: 33334 dRx: 33335 alpha: 33336
# 4: PN:test PN4 dTx: 44445 dRx: 44446 alpha: 44447
# erase database first
helper_erase_sfp_database
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "11112"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "11113"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "11114"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN1"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "22223"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "22224"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "22225"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN2"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "33334"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "33335"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "33336"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN3"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "44445"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "44446"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "44447"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN4"
# add sfp to the database, we don't care if match was successful
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
#set delta TX for SFP
helper_snmpset wrpcPtpConfigDeltaTx.0 "99999"
#set delta RX for SFP
helper_snmpset wrpcPtpConfigDeltaRx.0 "99999"
#set delta Alpha for SFP
helper_snmpset wrpcPtpConfigAlpha.0 "99999"
#set PN of SFP
helper_snmpset wrpcPtpConfigSfpPn.0 "test PN2"
# add sfp to the database, it is full now
result="$(snmpset $SNMP_OPTIONS $TARGET_IP wrpcPtpConfigApply.0 = writeToFlashGivenSfp | grep -e "applySuccessful" -e "applySuccessfulMatchFailed" | wc -l)"
[ "$result" -eq 1 ]
}
load snmp_test_config
load snmp_test_helpers
@test "Get wrpcTemperatureTable" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3
}
@test "Get wrpcTemperatureTable.0" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.0
}
@test "Get wrpcTemperatureTable.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1
}
@test "Get wrpcTemperatureTable.1.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.1
}
@test "Get wrpcTemperatureTable.1.1.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.1.1
}
@test "Get wrpcTemperatureTable.1.1.1.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.1.1.1
}
@test "Get wrpcTemperatureTable.1.2" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.2
}
@test "Get wrpcTemperatureTable.1.2.1" {
helper_snmpget_oidfound .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get wrpcTemperatureTable.1.2.1.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.2.1.1
}
@test "Get wrpcTemperatureTable.1.2.1.1.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.2.1.1.1
}
@test "Get wrpcTemperatureTable.1.3" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.3
}
@test "Get wrpcTemperatureTable.1.3.1" {
helper_snmpget_oidfound .1.3.6.1.4.1.96.101.1.3.1.3.1
}
@test "Get wrpcTemperatureTable.1.3.1.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.3.1.1
}
@test "Get wrpcTemperatureTable.1.3.1.1.1" {
helper_snmpget_oidnotfound .1.3.6.1.4.1.96.101.1.3.1.3.1.1.1
}
@test "Get next wrpcTemperatureTable" {
helper_snmpgetnext wrpcTemperatureTable .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.0" {
helper_snmpgetnext wrpcTemperatureTable.0 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1" {
helper_snmpgetnext wrpcTemperatureTable.1 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.1" {
helper_snmpgetnext wrpcTemperatureTable.1.1 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.1.1" {
helper_snmpgetnext wrpcTemperatureTable.1.1.1 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.1.1.1" {
helper_snmpgetnext wrpcTemperatureTable.1.1.1.1 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.1.1.1.1" {
helper_snmpgetnext wrpcTemperatureTable.1.1.1.1.1 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.1.1.1.2" {
helper_snmpgetnext wrpcTemperatureTable.1.1.1.1.2 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.1.2" {
helper_snmpgetnext wrpcTemperatureTable.1.1.2 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.2" {
helper_snmpgetnext wrpcTemperatureTable.1.2 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.2.0" {
helper_snmpgetnext wrpcTemperatureTable.1.2.0 .1.3.6.1.4.1.96.101.1.3.1.2.1
}
@test "Get next wrpcTemperatureTable.1.2.1" {
helper_snmpgetnext wrpcTemperatureTable.1.2.1 .1.3.6.1.4.1.96.101.1.3.1.2.2
}
@test "Get next wrpcTemperatureTable.1.2.1.1" {
helper_snmpgetnext wrpcTemperatureTable.1.2.1.1 .1.3.6.1.4.1.96.101.1.3.1.2.2
}
@test "Get next wrpcTemperatureTable.1.2.2" {
helper_snmpgetnext wrpcTemperatureTable.1.2.2 .1.3.6.1.4.1.96.101.1.3.1.2.3
}
@test "Get next wrpcTemperatureTable.1.2.3" {
helper_snmpgetnext wrpcTemperatureTable.1.2.3 .1.3.6.1.4.1.96.101.1.3.1.2.4
}
@test "Get next wrpcTemperatureTable.1.2.4" {
helper_snmpgetnext wrpcTemperatureTable.1.2.4 .1.3.6.1.4.1.96.101.1.3.1.3.1
}
@test "Get next wrpcTemperatureTable.1.2.5" {
helper_snmpgetnext wrpcTemperatureTable.1.2.5 .1.3.6.1.4.1.96.101.1.3.1.3.1
}
@test "Get next wrpcTemperatureTable.1.3" {
helper_snmpgetnext wrpcTemperatureTable.1.3 .1.3.6.1.4.1.96.101.1.3.1.3.1
}
@test "Get next wrpcTemperatureTable.1.3.0" {
helper_snmpgetnext wrpcTemperatureTable.1.3.0 .1.3.6.1.4.1.96.101.1.3.1.3.1
}
@test "Get next wrpcTemperatureTable.1.3.0.0" {
helper_snmpgetnext wrpcTemperatureTable.1.3.0.0 .1.3.6.1.4.1.96.101.1.3.1.3.1
}
@test "Get next wrpcTemperatureTable.1.3.1" {
helper_snmpgetnext wrpcTemperatureTable.1.3.1 .1.3.6.1.4.1.96.101.1.3.1.3.2
}
@test "Get next wrpcTemperatureTable.1.3.2" {
helper_snmpgetnext wrpcTemperatureTable.1.3.2 .1.3.6.1.4.1.96.101.1.3.1.3.3
}
@test "Get next wrpcTemperatureTable.1.3.3" {
helper_snmpgetnext wrpcTemperatureTable.1.3.3 .1.3.6.1.4.1.96.101.1.3.1.3.4
}
@test "Get next wrpcTemperatureTable.1.3.4" {
helper_snmpgetnext wrpcTemperatureTable.1.3.4 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.1.3.4.0" {
helper_snmpgetnext wrpcTemperatureTable.1.3.4.0 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.1.3.4.1" {
helper_snmpgetnext wrpcTemperatureTable.1.3.4.1 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.1.3.4.1.1" {
helper_snmpgetnext wrpcTemperatureTable.1.3.4.1.1 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.1.3.5" {
helper_snmpgetnext wrpcTemperatureTable.1.3.5 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.1.4" {
helper_snmpgetnext wrpcTemperatureTable.1.4 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.1.4.0" {
helper_snmpgetnext wrpcTemperatureTable.1.4.0 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.1.4.1" {
helper_snmpgetnext wrpcTemperatureTable.1.4.1 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.2" {
helper_snmpgetnext wrpcTemperatureTable.2 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "Get next wrpcTemperatureTable.2.0" {
helper_snmpgetnext wrpcTemperatureTable.2.0 .1.3.6.1.4.1.96.101.1.4.1.0
}
@test "set read only wrpcTemperatureTable.1.2.1" {
run snmpset $SNMP_OPTIONS $TARGET_IP wrpcTemperatureTable.1.2.1 = 141415
[ "$status" -eq 2 ]
}
load snmp_test_config
@test "snmpwalk 1.3.6.1.4.1.96.101.1.1" {
result="$(snmpwalk $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.96.101.1.1 | wc -l)"
[ "$result" -eq 4 ]
}
@test "snmpwalk 1.3.6.1.4.1.95" {
result="$(snmpwalk $SNMP_OPTIONS $TARGET_IP 1.3.6.1.4.1.95 | wc -l)"
[ "$result" -eq 0 ]
}
@test "snmpwalk 1.3.6 count all OIDs" {
result="$(snmpwalk $SNMP_OPTIONS $TARGET_IP 1.3.6 | wc -l)"
if [ "$result" -ne $TOTAL_NUM_OIDS ]; then
echo "Wrong number of OIDs! We expect $TOTAL_NUM_OIDS, while got $result"
echo "Please check WRPC's configuration. We expect to be in the WRPC:"
echo $TOTAL_NUM_OIDS_EXPECT_TEXT
false
fi
}
#
# Automatically generated make config: don't edit
#
# CONFIG_WR_SWITCH is not set
CONFIG_WR_NODE=y
CONFIG_PRINT_BUFSIZE=128
CONFIG_PRINTF_XINT=y
CONFIG_RAMSIZE=131072
CONFIG_TEMP_POLL_INTERVAL=15
# CONFIG_PLL_VERBOSE is not set
# CONFIG_PFILTER_VERBOSE is not set
# CONFIG_WRC_VERBOSE is not set
# CONFIG_VLAN is not set
CONFIG_VLAN_NR=0
CONFIG_VLAN_1_FOR_CLASS7=0
CONFIG_VLAN_2_FOR_CLASS7=0
CONFIG_VLAN_FOR_CLASS6=0
# CONFIG_HOST_PROCESS is not set
CONFIG_LM32=y
CONFIG_EMBEDDED_NODE=y
# CONFIG_WR_NODE_PCS16 is not set
CONFIG_STACKSIZE=2048
CONFIG_PPSI=y
CONFIG_UART=y
CONFIG_W1=y
CONFIG_IP=y
CONFIG_CMD_CONFIG=y
CONFIG_SYSLOG=y
CONFIG_SNMP=y
CONFIG_SNMP_SET=y
CONFIG_SNMP_HW_TYPE="spec"
CONFIG_BUILD_INIT=y
CONFIG_INIT_COMMAND="ptp stop"
CONFIG_HAS_BUILD_INIT=1
CONFIG_HAS_FLASH_INIT=1
CONFIG_FLASH_INIT=y
#
# wrpc-sw is tainted if you change the following options
#
CONFIG_DEVELOPER=y
CONFIG_TEMP_HIGH_THRESHOLD=70
CONFIG_TEMP_HIGH_RAPPEL=60
# CONFIG_CMD_LL is not set
# CONFIG_CHECK_RESET is not set
# CONFIG_SPLL_FIFO_LOG is not set
# CONFIG_PRINTF_FULL is not set
# CONFIG_PRINTF_MINI is not set
# CONFIG_PRINTF_NONE is not set
# CONFIG_DETERMINISTIC_BINARY is not set
# CONFIG_UART_SW is not set
# CONFIG_NET_VERBOSE is not set
# CONFIG_SNMP_VERBOSE is not set
CONFIG_FAKE_TEMPERATURES=y
CONFIG_SDB_STORAGE=y
# CONFIG_LEGACY_EEPROM is not set
CONFIG_VLAN_ARRAY_SIZE=1
......@@ -38,11 +38,6 @@ int wrc_ui_mode = UI_SHELL_MODE;
int wrc_ui_refperiod = TICS_PER_SECOND; /* 1 sec */
int wrc_phase_tracking = 1;
///////////////////////////////////
//Calibration data (from EEPROM if available)
int32_t sfp_alpha = 73622176; //default values if could not read EEPROM
int32_t sfp_deltaTx = 0;
int32_t sfp_deltaRx = 0;
uint32_t cal_phase_transition = 2389;
int wrc_vlan_number = CONFIG_VLAN_NR;
......@@ -121,6 +116,7 @@ static int wrc_check_link(void)
if (!prev_state && state) {
wrc_verbose("Link up.\n");
gpio_out(GPIO_LED_LINK, 1);
sfp_match();
wrc_ptp_start();
link_status = LINK_WENT_UP;
rv = 1;
......
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