Commit 42722fbf authored by Konstantinos Asteriou's avatar Konstantinos Asteriou Committed by Konstantinos Asteriou

Timing application (SNMP based) for Virgo WR-node (spec7)

parent b7682436
Pipeline #5154 passed with stage
in 4 minutes and 8 seconds
This diff is collapsed.
......@@ -33,17 +33,11 @@
#include "storage.h"
#include "softpll_ng.h"
#include <wrpc.h>
#include "lib/snmp.h"
static spll_gain_schedule_t spll_main_ocxo_gain_sched;
struct
{
struct gpio_device gpio_aux;
struct spi_bus spi_ltc6950;
struct ltc695x_device ltc6950_pll;
struct pca9554_gpio_device gpio_tim_main_board;
int pll_wr_mode;
} board;
struct spec7_board board;
static struct gpio_pin pin_pll_cs_n_o = { &board.gpio_aux, 0 };
static struct gpio_pin pin_pll_mosi_o = { &board.gpio_aux, 1 };
......@@ -167,7 +161,6 @@ void gpio_control_init()
{
int i;
uint8_t io_stat;
board_dbg("Initializing GPIO control...\n");
pca9554_write_reg(&board.gpio_tim_main_board, PCA9554_REG_CONFIG, 0x00); // Configure all IO as output
pca9554_write_reg(&board.gpio_tim_main_board, PCA9554_REG_OUT, 0x00); // LEDs, SEL_GROUP_0/1 and SEL_IRIG_B all '0'
......@@ -285,6 +278,73 @@ int pll_sync(void)
return 1;
}
#if defined(CONFIG_SNMP) && defined(SNMP_SET)
/* Functions and struct used by the SNMP protocol to control the timing output */
const struct snmp_oid oid_array_wrpcBoardSpecificGroup[] = {
OID_FIELD_VAR( oid_wrpcSelGroup0, get_select_group, set_select_group, ASN_INTEGER, &(board.gpio_tim_main_board)),
OID_FIELD_VAR( oid_wrpcSelGroup1, get_select_group, set_select_group, ASN_INTEGER, &(board.gpio_tim_main_board)),
{ 0, }
};
int set_select_group(uint8_t *buf, struct snmp_oid *obj){
static const int sel_group_offset = 3;
uint8_t io_stat;
uint8_t len = buf[1];
uint8_t *oid_data = buf + 2;
uint8_t sel_group = *(buf - 2) + sel_group_offset; // add offset to get the appropriate value from board.h
uint8_t sel_group_reg = WBGEN2_GEN_MASK(sel_group, 1);
uint8_t asn_incoming = buf[0];
uint8_t asn_expected = obj->asn;
uint32_t tmp_u32;
if (asn_incoming != asn_expected) { /* wrong data type */
snmp_verbose("%s: wrong asn 0x%02x, expected 0x%02x\n",
__func__, asn_incoming, asn_expected);
return -SNMP_ERR_BADVALUE;
}
io_stat = pca9554_read_reg(obj->p, PCA9554_REG_OUT);
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);
if(tmp_u32){
pca9554_write_reg(obj->p, PCA9554_REG_OUT, io_stat | sel_group_reg);
}
else{
pca9554_write_reg(obj->p, PCA9554_REG_OUT, io_stat & ~sel_group_reg);
}
return len + 2;
}
int get_select_group(uint8_t *buf, struct snmp_oid *obj){
static const int sel_group_offset = 3;
uint8_t *oid_data = buf + 2;
uint8_t *len = &buf[1];
uint32_t on = htonl(1);
uint32_t off = htonl(0);
uint8_t sel_group = *(buf - 2) + sel_group_offset; // add offset to get the appropriate value from board.h
uint8_t reg_stat = pca9554_read_reg(obj->p, PCA9554_REG_OUT);
uint8_t sel_group_reg = WBGEN2_GEN_MASK(sel_group, 1);
uint8_t sel_group_status = reg_stat & sel_group_reg;
*len = sizeof(uint32_t);
buf[0] = obj->asn;
if(sel_group_status){
memcpy((char*)oid_data, &on, *len);
}
else{
memcpy((char*)oid_data, &off, *len);
}
return *len + 2;
}
#endif
int spec7_init()
{
/* most of the I/Os of the slow peripherals (i2c, spi) are bitbanged. First, let's
......@@ -311,7 +371,6 @@ int spec7_init()
/* Setup the SoftPLL for the OCXO we have */
spec7_spll_setup();
ltc695x_init(&board.ltc6950_pll, &board.spi_ltc6950);
// Reset the PLL (RES6950 clears itself)
......@@ -377,9 +436,6 @@ int wrc_board_init()
ep_set_mac_addr(&wrc_endpoint_dev, mac_addr);
ep_pfilter_init_default(&wrc_endpoint_dev);
pca9554_write_reg(&board.gpio_tim_main_board, PCA9554_REG_CONFIG, 0x00); // Configure all IO as output
pca9554_write_reg(&board.gpio_tim_main_board, PCA9554_REG_OUT, 0x00); // LEDs, SEL_GROUP_0/1 and SEL_IRIG_B all '0'
return 0;
}
......
......@@ -9,7 +9,7 @@
#include "dev/gpio.h"
#include "dev/ltc695x.h"
#include "dev/pca9554.h"
#include "lib/snmp.h"
/*
* This is meant to be automatically included by the Makefile,
* when wrpc-sw is build for wrc (node) -- as opposed to wrs (switch)
......@@ -70,7 +70,8 @@
/* I2C address of the Unique ID EEPROM and Unique ID address */
#define UID_EEPROM_ADR 0x51
#define UID_OFFSET 0xfa
/* macro for extended SNMP support on the SPEC7 board */
#define CONFIG_SNMP_BOARD_SPECIFIC
/* I2C address of the I2C multiplexer */
#define PCA9554_ADR 0x23
......@@ -86,10 +87,21 @@
#define SDBFS_REC 5
// PLL WR_MODE options:
# define PLL_WR_MODE_MASTER 1
# define PLL_WR_MODE_SLAVE 2
# define PLL_WR_MODE_GM 3
#define PLL_WR_MODE_MASTER 1
#define PLL_WR_MODE_SLAVE 2
#define PLL_WR_MODE_GM 3
struct spec7_board
{
struct gpio_device gpio_aux;
struct spi_bus spi_ltc6950;
struct ltc695x_device ltc6950_pll;
struct pca9554_gpio_device gpio_tim_main_board;
int pll_wr_mode;
};
extern struct spec7_board board;
void gpio_control_init(void);
int gpio_control_poll(void);
void board_pre_pll_lock(int pll_wr_mode);
......@@ -103,4 +115,16 @@ extern int phy_calibration_done(void);
void sdb_find_devices(void);
void sdb_print_devices(void);
#if defined(CONFIG_SNMP) && defined(SNMP_SET)
int set_select_group(uint8_t *buf, struct snmp_oid *obj);
int get_select_group(uint8_t *buf, struct snmp_oid *obj);
/* wrpcSelGroup entries */
static const uint8_t oid_wrpcSelGroup0[] = {1,0};
static const uint8_t oid_wrpcSelGroup1[] = {2,0};
/* oid_wprcBoardSpecific*/
static const uint8_t oid_wrpcBoardSpecificGroup[] = {0x2B,6,1,4,1,96,101,1,13};
/* wrpcBoardSpecificGroup array */
extern const struct snmp_oid oid_array_wrpcBoardSpecificGroup[];
#endif
#endif /* __BOARD_SPEC7_H */
......@@ -17,7 +17,7 @@
#include <wrpc.h>
#include <string.h>
#include <limits.h>
#include "board.h"
#include "dev/endpoint.h"
#include "dev/minic.h"
#include "ipv4.h"
......@@ -34,215 +34,7 @@
#include "shell.h"
#include "storage.h"
#include "wrc_global.h"
#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
#ifdef CONFIG_SNMP_AUX_DIAG
#define SNMP_AUX_DIAG_ENABLED 1
#else
#define SNMP_AUX_DIAG_ENABLED 0
#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)
#define PTP_SERVO_STATE_N_STANDARD_PTP 99
/* defines used by get_servo function */
#define SERVO_STATEN (void *) 1
#define SERVO_CLOCKOFFSET (void *) 2
#define SERVO_SKEW (void *) 3
#define SERVO_RTT (void *) 4
#define SERVO_UPDATE_TIME (void *) 5
#define SERVO_DELTA_TX_M (void *) 6
#define SERVO_DELTA_RX_M (void *) 7
#define SERVO_DELTA_TX_S (void *) 8
#define SERVO_DELTA_RX_S (void *) 9
#define SERVO_N_ERR_STATE (void *) 10
#define SERVO_N_ERR_OFFSET (void *) 11
#define SERVO_N_ERR_DELTA_RTT (void *) 12
#define SERVO_ASYMMETRY (void *) 13
/* 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
/* new defines for wrpcInitScriptConfigApply, some are used from
* wrpcPtpConfigApply */
#define writeToFlash 1
#define applyFailedEmptyLine 201
/* new defines for oid_wrpcSdbApply, some are used from
* wrpcPtpConfigApply */
#define applyFailedEmptyParam 201
/* new defines for oid_wrpcShellCmdRun */
#define execute 12
#define executionSuccessful 100
#define executionFailed 200
#define executionFailedEmptyLine 201
#define executionFailedSetMagicTo44451 202
#define shellCmdReturnCodeMAGIC 44451
/* 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
/* Index of a byte in the OID corresponding to the ID of the aux diag
* registers */
#define AUX_DIAG_ID_INDEX 8
/* Index of a byte in the OID corresponding to the version of the aux diag
* registers */
#define AUX_DIAG_VER_INDEX 9
#define AUX_DIAG_RO (void *) DIAG_RO_BANK
#define AUX_DIAG_RW (void *) DIAG_RW_BANK
/* add the AUX_DIAG_DATA_COL_SHIFT to the aux diag register's index to get
* column in the table. Columns are following:
* col 1 -- index
* col 2 -- number of registers
* col 3 -- first aux diag register
*/
#define AUX_DIAG_DATA_COL_SHIFT 3
#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 {
const 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 {
const 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;
};
#include "snmp.h"
static struct s_sfpinfo snmp_ptp_config;
static int ptp_config_apply_status;
......@@ -280,7 +72,6 @@ static uint8_t snmp_version;
static DECLARE_WRPC_SOCKET(snmp_socket, 256);
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,
......@@ -332,6 +123,7 @@ static const uint8_t oid_wrpcSdbGroup[] = {0x2B,6,1,4,1,96,101,1,10};
static const uint8_t oid_wrpcNetconsoleGetGroup[] = {0x2B,6,1,4,1,96,101,1,11,1};
static const uint8_t oid_wrpcNetconsoleSetGroup[] = {0x2B,6,1,4,1,96,101,1,11,2};
static const uint8_t oid_wrpcShellCmdGroup[] = {0x2B,6,1,4,1,96,101,1,12};
/* In below OIDs zeros will be replaced in the snmp_init function by values
* read from FPA */
static uint8_t oid_wrpcAuxRoTable[] = {0x2B,6,1,4,1,96,101,2,0,0,1,1};
......@@ -433,8 +225,8 @@ static const uint8_t oid_wrpcShellCmdReturnCode[] = {4,0};
/* wrpcVersionGroup */
static const struct snmp_oid oid_array_wrpcVersionGroup[] = {
OID_FIELD_VAR( oid_wrpcVersionHwType, get_p, NO_SET, ASN_OCTET_STR, (void *)&wrc_global_link.wrc_hw_name),
OID_FIELD_VAR( oid_wrpcVersionSwVersion, get_p, NO_SET, ASN_OCTET_STR, (void *)&build_id.commit_id),
OID_FIELD_VAR( oid_wrpcVersionSwBuildBy, get_p, NO_SET, ASN_OCTET_STR, (void *)&build_id.build_by),
OID_FIELD_VAR( oid_wrpcVersionSwVersion, get_p, NO_SET, ASN_OCTET_STR, (void *)&build_id.commit_id),
OID_FIELD_VAR( oid_wrpcVersionSwBuildBy, get_p, NO_SET, ASN_OCTET_STR, (void *)&build_id.build_by),
OID_FIELD_VAR( oid_wrpcVersionSwBuildDate, get_p, NO_SET, ASN_OCTET_STR, (void *)&snmp_build_date),
{ 0, }
};
......@@ -561,6 +353,7 @@ static const struct snmp_oid oid_array_wrpcShellCmdGroup[] = {
{ 0, }
};
static const struct snmp_oid oid_array_wrpcAuxRoTable[] = {
OID_FIELD_VAR(NULL, get_aux_diag, NO_SET, ASN_UNSIGNED, AUX_DIAG_RO),
{ 0, }
......@@ -602,6 +395,9 @@ static const struct snmp_oid_limb oid_limb_array[] = {
#ifdef CONFIG_SNMP_AUX_DIAG
OID_LIMB_FIELD(oid_wrpcAuxRoTable, func_aux_diag, (void *)oid_array_wrpcAuxRoTable),
OID_LIMB_FIELD(oid_wrpcAuxRwTable, func_aux_diag, (void *)oid_array_wrpcAuxRwTable),
#endif
#if defined(CONFIG_SNMP_BOARD_SPECIFIC) && defined(CONFIG_SNMP_SET)
OID_LIMB_FIELD(oid_wrpcBoardSpecificGroup, func_group, (void *)oid_array_wrpcBoardSpecificGroup),
#endif
{ 0, }
};
......@@ -988,6 +784,8 @@ static int func_aux_diag(uint8_t *buf, uint8_t in_oid_limb_matched_len,
return return_len;
}
static int get_servo(uint8_t *buf, struct snmp_oid *obj)
{
uint64_t tmp_uint64;
......
/*
* 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.
*/
#ifndef __SNMP_H
#define __SNMP_H
#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
#ifdef CONFIG_SNMP_AUX_DIAG
#define SNMP_AUX_DIAG_ENABLED 1
#else
#define SNMP_AUX_DIAG_ENABLED 0
#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)
#define PTP_SERVO_STATE_N_STANDARD_PTP 99
/* defines used by get_servo function */
#define SERVO_STATEN (void *) 1
#define SERVO_CLOCKOFFSET (void *) 2
#define SERVO_SKEW (void *) 3
#define SERVO_RTT (void *) 4
#define SERVO_UPDATE_TIME (void *) 5
#define SERVO_DELTA_TX_M (void *) 6
#define SERVO_DELTA_RX_M (void *) 7
#define SERVO_DELTA_TX_S (void *) 8
#define SERVO_DELTA_RX_S (void *) 9
#define SERVO_N_ERR_STATE (void *) 10
#define SERVO_N_ERR_OFFSET (void *) 11
#define SERVO_N_ERR_DELTA_RTT (void *) 12
#define SERVO_ASYMMETRY (void *) 13
/* 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
/* new defines for wrpcInitScriptConfigApply, some are used from
* wrpcPtpConfigApply */
#define writeToFlash 1
#define applyFailedEmptyLine 201
/* new defines for oid_wrpcSdbApply, some are used from
* wrpcPtpConfigApply */
#define applyFailedEmptyParam 201
/* new defines for oid_wrpcShellCmdRun */
#define execute 12
#define executionSuccessful 100
#define executionFailed 200
#define executionFailedEmptyLine 201
#define executionFailedSetMagicTo44451 202
#define shellCmdReturnCodeMAGIC 44451
/* 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
/* Index of a byte in the OID corresponding to the ID of the aux diag
* registers */
#define AUX_DIAG_ID_INDEX 8
/* Index of a byte in the OID corresponding to the version of the aux diag
* registers */
#define AUX_DIAG_VER_INDEX 9
#define AUX_DIAG_RO (void *) DIAG_RO_BANK
#define AUX_DIAG_RW (void *) DIAG_RW_BANK
/* add the AUX_DIAG_DATA_COL_SHIFT to the aux diag register's index to get
* column in the table. Columns are following:
* col 1 -- index
* col 2 -- number of registers
* col 3 -- first aux diag register
*/
#define AUX_DIAG_DATA_COL_SHIFT 3
#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 {
const 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 {
const 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;
};
#endif
\ No newline at end of file
from pysnmp.smi import builder, view, error
from pysnmp.hlapi import *
import os
class SnmpHandler():
snmpPort = 161
wrpcCommunityString = 'public'
group = "Group"
mibLeaves = {}
def __init__(self, targetIp=None, wrpcMibName=None, mibDir=None, coreOid=None):
self.coreOid = coreOid
self.mibDir = os.path.expanduser(mibDir)
self.wrpcMibName = wrpcMibName
self.targetIp = targetIp
self.controller = self.create_MibController()
self.mibLeaves = self.get_local_info()
def create_MibController(self):
try:
mibBuilder = builder.MibBuilder()
mibPath = mibBuilder.getMibSources()+(builder.DirMibSource(self.mibDir),)
mibBuilder.setMibSources(*mibPath)
mibBuilder.loadModules(self.wrpcMibName)
mibController = view.MibViewController(mibBuilder)
except Exception as e:
print(f"An error occurred: {e}")
return None
return mibController
def print_local_info(self):
for key, value in self.mibLeaves.items():
print(f"{key} : {value[0]}")
def walk(self):
for key, _ in self.mibLeaves.items():
self.get(key)
def get(self, name):
if name in self.mibLeaves:
flag = self.mibLeaves[name][1]
else:
print("Invalid name was entered")
return
if flag:
object = ObjectType(ObjectIdentity(self.wrpcMibName, name, 0))
else:
object = ObjectType(ObjectIdentity(self.wrpcMibName, name))
try:
_, _, _, varBinds = next(
getCmd(SnmpEngine(),
CommunityData(self.wrpcCommunityString),
UdpTransportTarget((self.targetIp, self.snmpPort)),
ContextData(),
object))
except error.SmiError as e:
print(f"An error occured during the get operation. {e}")
return
return varBinds
def set(self, name, value):
if name in self.mibLeaves:
flag = self.mibLeaves[name][1]
else:
print("Invalid name was entered")
return
if flag:
object = ObjectType(ObjectIdentity(self.wrpcMibName, name, 0), value)
else:
object = ObjectType(ObjectIdentity(self.wrpcMibName, name), value)
try:
next(
setCmd(SnmpEngine(),
CommunityData(self.wrpcCommunityString),
UdpTransportTarget((self.targetIp, self.snmpPort)),
ContextData(),
object))
except error.SmiError as e:
print(f"An error occured during the set operation. {e}")
return
def get_local_info(self):
leaves = {}
labels_list = []
nodes = []
oid, _, _ = self.controller.getNodeName(self.coreOid)
modName, _, _ = self.controller.getNodeLocation(self.coreOid)
table_flag = 0
while True:
try:
oid, labels, _ = self.controller.getNextNodeName(oid)
modName, _, _ = self.controller.getNodeLocation(oid)
# gather only white rabbit related MIB variables
if modName == self.wrpcMibName:
labels_list.append((labels))
table_flag = any(self.group in label for label in labels)
nodes.append((labels[-1], oid, table_flag))
table_flag = 0
except Exception as e:
print(f"An exception occured during retrieving information from local MIB. {e}")
break
# the name of every leaf must appear only once
occurrences = 0
for (name, oid, table_flag) in nodes:
for label in labels_list:
occurrences += label.count(name)
if occurrences == 1:
leaves[name] = (oid, table_flag)
occurrences = 0
return leaves
\ No newline at end of file
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QLabel, QGridLayout, QLineEdit, QMainWindow
from PyQt6.QtGui import QPixmap
from backend import SnmpHandler
coreOid = ((1, 3, 6, 1, 4, 1, 96, 101, 1))
mibDir = '~/.pysnmp/mibs'
wrpcMibName = 'WR-WRPC-MIB'
class MyWindow(QMainWindow):
def __init__(self, targetIp):
super().__init__()
# setup window
self.setGeometry(10, 100, 2000, 800)
self.setWindowTitle('Virgo Demonstrator Box')
# init snmp_handler
self.snmp_handler = SnmpHandler(targetIp, wrpcMibName, mibDir, coreOid)
self.edit_button_list = []
# Set up the background image
pixmap = QPixmap('Virgo_WR_Front_Panel/FrontPanel.jpg')
self.background_label = QLabel(self)
self.background_label.setPixmap(pixmap)
self.background_label.setGeometry(0, 0, self.width(), self.height())
self.grid = QGridLayout()
self.init_ui()
def configure_ui(self, button, qedit, id):
base = 10
offset = 110
button.setGeometry(base + offset*id, 10, 100, 30)
button.clicked.connect(lambda: self.toggle(id))
qedit.setReadOnly(True)
qedit.setGeometry(base + offset*id, 50, 100, 30)
def init_ui(self):
for i in range(2):
edit = QLineEdit(self)
button = QPushButton(f'SelGroup {i}', self)
self.configure_ui(button, edit, i)
# Append the tuple to the list
self.edit_button_list.append((edit, button))
def update_timing_status(self, id, status):
self.edit_button_list[id][0].setText(status)
def toggle(self, id):
SelGroup = "wrpcSelGroup" + str(id)
try:
varBinds = self.snmp_handler.get(SelGroup)
for varBind in varBinds:
_, value = varBind
current_value = value.prettyPrint()
if current_value == "0":
self.snmp_handler.set(SelGroup, 1)
self.update_timing_status(id, "10MHz")
elif current_value == "1":
self.snmp_handler.set(SelGroup, 0)
self.update_timing_status(id, "100MHz")
except Exception as e:
print(f"Connection issue? Wrong target IP? : {e}")
if __name__ == '__main__':
# get target's IP address
if len(sys.argv) != 2:
print("Usage: python script.py <IP_ADDRESS>")
sys.exit(1)
targetIp = sys.argv[1]
app = QApplication([])
window = MyWindow(targetIp)
window.show()
sys.exit(app.exec())
\ No newline at end of file
import subprocess
import os
linux_packages = ["snmp-mibs-downloader", "libxcb-cursor0"]
python_packages = ["pysnmp-pysmi", "pyQt6", "pysnmp"]
def install_linux_packages(packages):
for package in packages:
subprocess.run(["sudo", "apt-get", "install", "-y", package])
def install_python_packages(packages):
for package in packages:
subprocess.run(["pip", "install", package])
def remove_last_two_directories(path):
components = path.split('/')
# Check if the path has more than 3 components
if len(components) > 3:
components = components[:-2]
updated_path = '/'.join(components)
return updated_path
else:
return path
def convert_mib(path):
# Expand the tilde in the path
mibdump_path = os.path.expanduser("~/.local/bin/mibdump")
# passed a path variable since relative paths were buggy
mib_file_path = os.path.abspath(path + "/boards/spec7/WR-WRPC-MIB-SPEC7.txt")
command = [mibdump_path, mib_file_path]
subprocess.run(command)
if __name__ == '__main__':
# Install Linux packages
install_linux_packages(linux_packages)
# Install Python packages
install_python_packages(python_packages)
# Get the path where wrpc-sw is located.
current_path = os.getcwd()
wrpc_sw_path = remove_last_two_directories(current_path)
# Convert MIB from .txt to .py
convert_mib(wrpc_sw_path)
\ No newline at end of file
# SPEC7 SNMP Control Application
This Python application allows users to interact with a SPEC7 board using SNMP (Simple Network Management Protocol) for performing get and set requests.
It consists of three main parts:
1. **setup.py**: This script needs to be run first to install all the necessary dependencies.
It handles the installation of Linux dependencies such as `snmp-mibs-downloader`, `libxcb-cursor0`, and Python dependencies including `pysnmp`, `pysmi`, and `PyQt6`.
2. **gui.py**: This script is responsible for creating an interactive graphical user interface (GUI) for the application.
Once the setup is complete, users can simply run this script to access the GUI and interact with the SPEC7 board.
3. **backend.py**: This script contains the functionality for handling SNMP get and set requests.
It serves as the backend for the GUI, enabling users to send SNMP requests to the SPEC7 board.
## Installation and Setup
To set up the application, follow these steps:
1. Clone or download the repository to your local machine.
2. Open a terminal window and navigate to the directory containing the repository.
3. Run the `setup.py` script to install the necessary dependencies:
```bash
python setup.py
```
4. Once the setup is complete, you can run the `gui.py` script to launch the GUI:
```bash
python gui.py
```
5. Use the GUI interface to interact with the SPEC7 board, sending SNMP get and set requests as needed.
## Requirements
- Python 3.x
- Linux environment (for `snmp-mibs-downloader`)
- `pysnmp` package
- `PyQt6` package
## Usage
- Run `setup.py` to install dependencies.
- Run `backend.py` to launch the GUI interface.
- Use the GUI to send SNMP get and set requests to the SPEC7 board.
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