This patch intruduces the supported ds described in PTPBASE_MIB. The rest of the unsupported ds are not covered. These ds needs to be added in ptp4l to begin with.
Signed-off-by: Anders Selhammer <anders.selham...@est.tech> --- makefile | 6 +- ptpbase_mib.c | 898 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ snmp4lptp_mib.h | 3 + 3 files changed, 904 insertions(+), 3 deletions(-) create mode 100644 ptpbase_mib.c diff --git a/makefile b/makefile index 6995e70..3f21001 100644 --- a/makefile +++ b/makefile @@ -40,7 +40,7 @@ version := $(shell $(srcdir)/version.sh $(srcdir)) VPATH = $(srcdir) ifneq (,$(findstring -DHAVE_NET_SNMP,$(snmpflg))) -PRG += snmp4lptp +PRG += snmp4lptp ptpbase_mib.o OBJECTS += snmp4lptp.o snmplib := $(shell net-snmp-config --netsnmp-agent-libs) endif @@ -68,8 +68,8 @@ hwstamp_ctl: hwstamp_ctl.o version.o phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o -snmp4lptp: config.o hash.o msg.o pmc_common.o print.o raw.o sk.o \ - snmp4lptp.o tlv.o transport.o udp.o udp6.o uds.o util.o +snmp4lptp: config.o hash.o msg.o pmc_common.o print.o ptpbase_mib.o raw.o \ + sk.o snmp4lptp.o tlv.o transport.o udp.o udp6.o uds.o util.o $(CC) $^ $(LDFLAGS) $(LOADLIBES) $(LDLIBS) $(snmplib) -o $@ snmp4lptp.o: snmp4lptp.c diff --git a/ptpbase_mib.c b/ptpbase_mib.c new file mode 100644 index 0000000..cd39274 --- /dev/null +++ b/ptpbase_mib.c @@ -0,0 +1,898 @@ +/** + * @file ptpbase_mib.c + * @brief Implements PTPv2 Management Information Base (RFC 8173) + * @note Copyright (C) 2018 Anders Selhammer <anders.selham...@est.tech> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "clock.h" +#include "ds.h" +#include "pdt.h" +#include "print.h" +#include "snmp4lptp_mib.h" +#include "tlv.h" +#include "tmv.h" + +/* + * ptp base oid values + */ +#define SNMP_OID_PTPBASE_MIB 1, 3, 6, 1, 2, 1, 241 +#define SNMP_OID_PTPBASE_OBJ_CLOCKINFO SNMP_OID_PTPBASE_MIB, 1, 2 +#define SNMP_OID_PTPBASE_CLOCK_CDS SNMP_OID_PTPBASE_OBJ_CLOCKINFO, 1 +#define SNMP_OID_PTPBASE_CLOCK_PDS SNMP_OID_PTPBASE_OBJ_CLOCKINFO, 2 +#define SNMP_OID_PTPBASE_CLOCK_DDS SNMP_OID_PTPBASE_OBJ_CLOCKINFO, 3 +#define SNMP_OID_PTPBASE_CLOCK_TDS SNMP_OID_PTPBASE_OBJ_CLOCKINFO, 5 +#define SNMP_OID_PTPBASE_PORT_DS SNMP_OID_PTPBASE_OBJ_CLOCKINFO, 8 + +/* + * column number definitions for tables + */ + +#define COLUMN_CURRENTDS_STEPSREMOVED 4 +#define COLUMN_CURRENTDS_OFFSETFROMMASTER 5 +#define COLUMN_CURRENTDS_MEANPATHDELAY 6 +#define COLUMN_CDS_MIN COLUMN_CURRENTDS_STEPSREMOVED +#define COLUMN_CDS_MAX COLUMN_CURRENTDS_MEANPATHDELAY + +#define COLUMN_PARENTDS_PARENTPORTIDENTITY 4 +#define COLUMN_PARENTDS_PARENTSTATS 5 +#define COLUMN_PARENTDS_OFFSET 6 +#define COLUMN_PARENTDS_CLOCKPHCHRATE 7 +#define COLUMN_PARENTDS_GMCLOCKIDENTITY 8 +#define COLUMN_PARENTDS_GMCLOCKPRIORITY1 9 +#define COLUMN_PARENTDS_GMCLOCKPRIORITY2 10 +#define COLUMN_PARENTDS_GMCLOCKQUALITYCLASS 11 +#define COLUMN_PARENTDS_GMCLOCKQUALITYACCURACY 12 +#define COLUMN_PARENTDS_GMCLOCKQUALITYOFFSET 13 +#define COLUMN_PDS_MIN COLUMN_PARENTDS_PARENTPORTIDENTITY +#define COLUMN_PDS_MAX COLUMN_PARENTDS_GMCLOCKQUALITYOFFSET + +#define COLUMN_DEFAULTDS_TWOSTEPFLAG 4 +#define COLUMN_DEFAULTDS_CLOCKIDENTITY 5 +#define COLUMN_DEFAULTDS_PRIORITY1 6 +#define COLUMN_DEFAULTDS_PRIORITY2 7 +#define COLUMN_DEFAULTDS_SLAVEONLY 8 +#define COLUMN_DEFAULTDS_QUALITYCLASS 9 +#define COLUMN_DEFAULTDS_QUALITYACCURACY 10 +#define COLUMN_DEFAULTDS_QUALITYOFFSET 11 +#define COLUMN_DDS_MIN COLUMN_DEFAULTDS_TWOSTEPFLAG +#define COLUMN_DDS_MAX COLUMN_DEFAULTDS_QUALITYOFFSET + +#define COLUMN_TIMEPROPERTIESDS_CURRENTUTCOFFSETVALID 4 +#define COLUMN_TIMEPROPERTIESDS_CURRENTUTCOFFSET 5 +#define COLUMN_TIMEPROPERTIESDS_LEAP59 6 +#define COLUMN_TIMEPROPERTIESDS_LEAP61 7 +#define COLUMN_TIMEPROPERTIESDS_TIMETRACEABLE 8 +#define COLUMN_TIMEPROPERTIESDS_FREQTRACEABLE 9 +#define COLUMN_TIMEPROPERTIESDS_PTPTIMESCALE 10 +#define COLUMN_TIMEPROPERTIESDS_SOURCE 11 +#define COLUMN_TDS_MIN COLUMN_TIMEPROPERTIESDS_CURRENTUTCOFFSETVALID +#define COLUMN_TDS_MAX COLUMN_TIMEPROPERTIESDS_SOURCE + +#define COLUMN_PORTDS_NAME 5 +#define COLUMN_PORTDS_PORTIDENTITY 6 +#define COLUMN_PORTDS_LOGANNOUNCEMENTINTERVAL 7 +#define COLUMN_PORTDS_ANNOUNCERCTTIMEOUT 8 +#define COLUMN_PORTDS_LOGSYNCINTERVAL 9 +#define COLUMN_PORTDS_MINDELAYREQINTERVAL 10 +#define COLUMN_PORTDS_PEERDELAYREQINTERVAL 11 +#define COLUMN_PORTDS_DELAYMECH 12 +#define COLUMN_PORTDS_PEERMEANPATHDELAY 13 +#define COLUMN_PORTDS_GRANTDURATION 14 +#define COLUMN_PORTDS_PTPVERSION 15 +#define COLUMN_PORTDS_MIN COLUMN_PORTDS_NAME +#define COLUMN_PORTDS_MAX COLUMN_PORTDS_PTPVERSION + +/* + * other internal defines and types + */ +#define CMD_MAX_LEN 255 + +enum ptp_clock_type { + ordinaryClock = 1, + boundaryClock, + transparentClock +}; + +struct ds_idx { + u_long domain; + long clock_type; + u_long instance; + int valid; +}; + +struct ds_data { + struct ds_idx idxs; + int id; + unsigned int tmo; + struct ptp_message *cur; + TAILQ_HEAD(msg_head, ptp_message) msg; +}; + +struct mydata { + int id; + int multiple; + struct ds_data *data; +}; + + +/* + * function declarations + */ + +static void reset_ds_data(struct ds_data *data) +{ + struct ptp_message *tmp; + data->id = 0; + if (data->tmo) { + snmp_alarm_unregister(data->tmo); + data->tmo = 0; + } + while ((tmp = TAILQ_FIRST(&data->msg)) != NULL) { + TAILQ_REMOVE(&data->msg, tmp, list); + msg_put(tmp); + } +} + +static void ds_cb(unsigned int clientreg, void *clientarg) +{ + struct ds_data *data = (struct ds_data *)clientarg; + + if (data->tmo != clientreg) { + pr_err("Received unregistered timer"); + return; + } + data->idxs.valid = 0; + reset_ds_data(data); +} + +static int get_command(char *cmd, int id) +{ + switch (id) { + case TLV_DEFAULT_DATA_SET: + snprintf(cmd, CMD_MAX_LEN, "GET DEFAULT_DATA_SET"); + break; + case TLV_CURRENT_DATA_SET: + snprintf(cmd, CMD_MAX_LEN, "GET CURRENT_DATA_SET"); + break; + case TLV_PARENT_DATA_SET: + snprintf(cmd, CMD_MAX_LEN, "GET PARENT_DATA_SET"); + break; + case TLV_TIME_PROPERTIES_DATA_SET: + snprintf(cmd, CMD_MAX_LEN, "GET TIME_PROPERTIES_DATA_SET"); + break; + case TLV_PORT_DATA_SET: + snprintf(cmd, CMD_MAX_LEN, "GET PORT_DATA_SET"); + break; + default: + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int get_mgmt_data(struct ptp_message *msg, + struct management_tlv **mgt) +{ + struct TLV *tlv; + int action; + + if (msg_type(msg) != MANAGEMENT) { + pr_err("msg type not MANAGEMENT"); + return SNMP_ERR_GENERR; + } + + action = management_action(msg); + if (action < GET || action > ACKNOWLEDGE) { + pr_err("incorrect action"); + return SNMP_ERR_GENERR; + } + + if (msg_tlv_count(msg) != 1) { + pr_err("incorrect tlv count"); + return SNMP_ERR_GENERR; + } + + tlv = (struct TLV *) msg->management.suffix; + if (tlv->type == TLV_MANAGEMENT) { + ; + } else if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS) { + pr_err("MANAGEMENT_ERROR_STATUS"); + return SNMP_ERR_GENERR; + } else { + pr_err("unknown-tlv"); + return SNMP_ERR_GENERR; + } + + *mgt = (struct management_tlv *) msg->management.suffix; + if ((*mgt)->length == 2 && (*mgt)->id != TLV_NULL_MANAGEMENT) { + pr_err("empty-tlv"); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static unsigned int get_port_ds_portnum(struct ptp_message *msg) +{ + struct management_tlv *mgt; + struct portDS *ds; + + mgt = (struct management_tlv *) msg->management.suffix; + ds = (struct portDS *) mgt->data; + + return ds->portIdentity.portNumber; +} + +static int add_ds_table_indexes(netsnmp_table_registration_info *tinfo, int id) +{ + switch (id) { + case TLV_CURRENT_DATA_SET: + case TLV_PARENT_DATA_SET: + case TLV_DEFAULT_DATA_SET: + case TLV_TIME_PROPERTIES_DATA_SET: + netsnmp_table_helper_add_indexes(tinfo, + ASN_UNSIGNED, + ASN_INTEGER, + ASN_UNSIGNED, + 0); + break; + case TLV_PORT_DATA_SET: + netsnmp_table_helper_add_indexes(tinfo, + ASN_UNSIGNED, + ASN_INTEGER, + ASN_UNSIGNED, + ASN_UNSIGNED, + 0); + break; + default: + return SNMP_ERR_GENERR; + } + return SNMP_ERR_NOERROR; +} + +static void set_ds_table_indexes(netsnmp_variable_list *idx, struct ds_data *data) +{ + switch (data->id) { + case TLV_CURRENT_DATA_SET: + case TLV_PARENT_DATA_SET: + case TLV_DEFAULT_DATA_SET: + case TLV_TIME_PROPERTIES_DATA_SET: + snmp_set_var_typed_integer(idx, ASN_UNSIGNED, + data->idxs.domain); + idx = idx->next_variable; + snmp_set_var_typed_integer(idx, ASN_INTEGER, + data->idxs.clock_type); + idx = idx->next_variable; + snmp_set_var_typed_integer(idx, ASN_UNSIGNED, + data->idxs.instance); + break; + case TLV_PORT_DATA_SET: + snmp_set_var_typed_integer(idx, ASN_UNSIGNED, + data->idxs.domain); + idx = idx->next_variable; + snmp_set_var_typed_integer(idx, ASN_INTEGER, + data->idxs.clock_type); + idx = idx->next_variable; + snmp_set_var_typed_integer(idx, ASN_UNSIGNED, + data->idxs.instance); + idx = idx->next_variable; + snmp_set_var_typed_integer(idx, ASN_UNSIGNED, + get_port_ds_portnum(data->cur)); + break; + default: + pr_err("unimplemented id"); + } +} + +static int update_ds_idxs(struct ds_idx *idxs) +{ + struct management_tlv *mgt = NULL; + struct tlv_extra *extra = NULL; + int err = SNMP_ERR_NOERROR; + struct ptp_message *msg; + + msg = snmp4lptp_run_pmc("GET CLOCK_DESCRIPTION"); + if (!msg) { + return SNMP_ERR_GENERR; + } + + if (get_mgmt_data(msg, &mgt)) { + err = SNMP_ERR_GENERR; + goto out; + } + if (mgt->id != TLV_CLOCK_DESCRIPTION) { + err = SNMP_ERR_GENERR; + goto out; + } + + extra = TAILQ_FIRST(&msg->tlv_list); + switch (align16(extra->cd.clockType)) { + case CLOCK_TYPE_ORDINARY: + idxs->clock_type = ordinaryClock; + break; + case CLOCK_TYPE_BOUNDARY: + idxs->clock_type = boundaryClock; + break; + case CLOCK_TYPE_P2P: + case CLOCK_TYPE_E2E: + idxs->clock_type = transparentClock; + break; + default: + err = SNMP_ERR_GENERR; + goto out; + } + + idxs->domain = snmp4lptp_get_domain(); + idxs->instance = 0; + idxs->valid = 1; + +out: + msg_put(msg); + while ((msg = snmp4lptp_run_pmc(NULL))) { + msg_put(msg); + } + + return err; +} + +static int store_ds_msg(struct ds_data *data, struct ptp_message *msg) +{ + struct management_tlv *mgt = NULL; + + if (get_mgmt_data(msg, &mgt)) { + return SNMP_ERR_GENERR; + } + + data->id = mgt->id; + TAILQ_INSERT_TAIL(&data->msg, msg, list); + + return SNMP_ERR_NOERROR; +} + +static int update_ds_data(char *cmd, struct ds_data *data, int multiple_rsp) +{ + struct ptp_message *msg; + + msg = snmp4lptp_run_pmc(cmd); + if (!msg) { + return SNMP_ERR_GENERR; + } + do { + if (store_ds_msg(data, msg)) { + msg_put(msg); + return SNMP_ERR_GENERR; + } + } while (multiple_rsp && (msg = snmp4lptp_run_pmc(NULL))); + + return SNMP_ERR_NOERROR; +} + +static netsnmp_variable_list *get_next_data_point(void **my_loop_context, + void **my_data_context, + netsnmp_variable_list + *put_index_data, + netsnmp_iterator_info + *mydata) +{ + struct ds_data *data; + + data = (struct ds_data *)*my_loop_context; + if (!data->cur) { + return NULL; + } + + set_ds_table_indexes(put_index_data, data); + + *my_data_context = (void *) data->cur; + data->cur = TAILQ_NEXT(data->cur, list); + + return put_index_data; +} + +static netsnmp_variable_list *get_first_data_point(void **my_loop_context, + void **my_data_context, + netsnmp_variable_list + *put_index_data, + netsnmp_iterator_info + *mydata) +{ + struct mydata *my_data; + char cmd[CMD_MAX_LEN]; + + my_data = (struct mydata*)mydata->myvoid; + if (!my_data->data->idxs.valid) { + if (update_ds_idxs(&my_data->data->idxs)) { + return NULL; + } + } + if (my_data->data->id != my_data->id) { + reset_ds_data(my_data->data); + my_data->data->tmo = + snmp_alarm_register(1, 0, ds_cb, my_data->data); + if (get_command(cmd, my_data->id)) { + return NULL; + } + if (update_ds_data(cmd, my_data->data, my_data->multiple)) { + return NULL; + } + } + + my_data->data->cur = TAILQ_FIRST(&my_data->data->msg); + *my_loop_context = my_data->data; + + return get_next_data_point(my_loop_context, my_data_context, + put_index_data, mydata); +} + +static int set_cds_return_values(unsigned int column, + struct management_tlv *mgt, + netsnmp_request_info *request) +{ + struct currentDS *ds = (struct currentDS *) mgt->data; + + switch (column) { + case COLUMN_CURRENTDS_STEPSREMOVED: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + ds->stepsRemoved); + break; + case COLUMN_CURRENTDS_OFFSETFROMMASTER: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + &ds->offsetFromMaster, sizeof(ds->offsetFromMaster)); + break; + case COLUMN_CURRENTDS_MEANPATHDELAY: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + &ds->meanPathDelay, sizeof(ds->meanPathDelay)); + break; + default: + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int set_pds_return_values(unsigned int column, + struct management_tlv *mgt, + netsnmp_request_info *request) +{ + struct parentDS *ds = (struct parentDS *) mgt->data; + + switch (column) { + case COLUMN_PARENTDS_PARENTPORTIDENTITY: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + &ds->parentPortIdentity, sizeof(ds->parentPortIdentity)); + break; + case COLUMN_PARENTDS_PARENTSTATS: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->parentStats); + break; + case COLUMN_PARENTDS_OFFSET: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->observedParentOffsetScaledLogVariance); + break; + case COLUMN_PARENTDS_CLOCKPHCHRATE: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->observedParentClockPhaseChangeRate); + break; + case COLUMN_PARENTDS_GMCLOCKIDENTITY: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + &ds->grandmasterIdentity, sizeof(ds->grandmasterIdentity)); + break; + case COLUMN_PARENTDS_GMCLOCKPRIORITY1: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + ds->grandmasterPriority1); + break; + case COLUMN_PARENTDS_GMCLOCKPRIORITY2: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + ds->grandmasterPriority2); + break; + case COLUMN_PARENTDS_GMCLOCKQUALITYCLASS: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->grandmasterClockQuality.clockClass); + break; + case COLUMN_PARENTDS_GMCLOCKQUALITYACCURACY: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->grandmasterClockQuality.clockAccuracy); + break; + case COLUMN_PARENTDS_GMCLOCKQUALITYOFFSET: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + ds->grandmasterClockQuality.offsetScaledLogVariance); + break; + default: + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int set_dds_return_values(unsigned int column, + struct management_tlv *mgt, + netsnmp_request_info *request) { + struct defaultDS *ds = (struct defaultDS *) mgt->data; + + switch (column) { + case COLUMN_DEFAULTDS_TWOSTEPFLAG: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & DDS_TWO_STEP_FLAG ? 1 : 0); + break; + case COLUMN_DEFAULTDS_CLOCKIDENTITY: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + &ds->clockIdentity, sizeof(ds->clockIdentity)); + break; + case COLUMN_DEFAULTDS_PRIORITY1: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + ds->priority1); + break; + case COLUMN_DEFAULTDS_PRIORITY2: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + ds->priority2); + break; + case COLUMN_DEFAULTDS_SLAVEONLY: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & DDS_SLAVE_ONLY ? 1 : 0); + break; + case COLUMN_DEFAULTDS_QUALITYCLASS: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->clockQuality. + clockClass); + break; + case COLUMN_DEFAULTDS_QUALITYACCURACY: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->clockQuality. + clockAccuracy); + break; + case COLUMN_DEFAULTDS_QUALITYOFFSET: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->clockQuality. + offsetScaledLogVariance); + break; + default: + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int set_tds_return_values(unsigned int column, + struct management_tlv *mgt, + netsnmp_request_info *request) +{ + struct timePropertiesDS *ds = (struct timePropertiesDS *) mgt->data; + + switch (column) { + case COLUMN_TIMEPROPERTIESDS_CURRENTUTCOFFSETVALID: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & UTC_OFF_VALID ? 1 : 0); + break; + case COLUMN_TIMEPROPERTIESDS_CURRENTUTCOFFSET: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->currentUtcOffset); + break; + case COLUMN_TIMEPROPERTIESDS_LEAP59: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & LEAP_59 ? 1 : 0); + break; + case COLUMN_TIMEPROPERTIESDS_LEAP61: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & LEAP_61 ? 1 : 0); + break; + case COLUMN_TIMEPROPERTIESDS_TIMETRACEABLE: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & TIME_TRACEABLE ? 1 : 0); + break; + case COLUMN_TIMEPROPERTIESDS_FREQTRACEABLE: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & FREQ_TRACEABLE ? 1 : 0); + break; + case COLUMN_TIMEPROPERTIESDS_PTPTIMESCALE: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->flags & PTP_TIMESCALE ? 1 : 0); + break; + case COLUMN_TIMEPROPERTIESDS_SOURCE: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->timeSource); + break; + default: + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int set_port_ds_return_values(unsigned int column, + struct management_tlv *mgt, + netsnmp_request_info *request) +{ + struct portDS *ds = (struct portDS *) mgt->data; + + switch (column) { + case COLUMN_PORTDS_NAME: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + "PORTNAME", 8); + break; + case COLUMN_PORTDS_PORTIDENTITY: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + &ds->portIdentity, sizeof(ds->portIdentity)); + break; + case COLUMN_PORTDS_LOGANNOUNCEMENTINTERVAL: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->logAnnounceInterval); + break; + case COLUMN_PORTDS_ANNOUNCERCTTIMEOUT: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->announceReceiptTimeout); + break; + case COLUMN_PORTDS_LOGSYNCINTERVAL: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->logSyncInterval); + break; + case COLUMN_PORTDS_MINDELAYREQINTERVAL: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->logMinDelayReqInterval); + break; + case COLUMN_PORTDS_PEERDELAYREQINTERVAL: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->logMinPdelayReqInterval); + break; + case COLUMN_PORTDS_DELAYMECH: + snmp_set_var_typed_integer(request->requestvb, + ASN_INTEGER, + ds->delayMechanism); + break; + case COLUMN_PORTDS_PEERMEANPATHDELAY: + snmp_set_var_typed_value(request->requestvb, + ASN_OCTET_STR, + &ds->peerMeanPathDelay, sizeof(ds->peerMeanPathDelay)); + break; + case COLUMN_PORTDS_GRANTDURATION: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + 0xFFFF); + break; + case COLUMN_PORTDS_PTPVERSION: + snmp_set_var_typed_integer(request->requestvb, + ASN_UNSIGNED, + ds->versionNumber); + break; + default: + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} + +static int ds_handler(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + netsnmp_table_request_info *table_info; + netsnmp_request_info *request; + struct management_tlv *mgt; + struct ptp_message *msg; + + if (reqinfo->mode != MODE_GET) { + return SNMP_ERR_NOERROR; + } + + /* + * Read-support (also covers GetNext requests) + */ + for (request = requests; request; request = request->next) { + msg = (struct ptp_message *) + netsnmp_extract_iterator_context(request); + table_info = netsnmp_extract_table_info(request); + if (!table_info->colnum || !msg) { + netsnmp_set_request_error(reqinfo, request, + SNMP_NOSUCHINSTANCE); + continue; + } + mgt = (struct management_tlv *) msg->management.suffix; + switch (mgt->id) { + case TLV_CURRENT_DATA_SET: + if (set_cds_return_values(table_info->colnum, + mgt, request)) { + netsnmp_set_request_error(reqinfo, request, + SNMP_NOSUCHOBJECT); + } + break; + case TLV_PARENT_DATA_SET: + if (set_pds_return_values(table_info->colnum, + mgt, request)) { + netsnmp_set_request_error(reqinfo, request, + SNMP_NOSUCHOBJECT); + } + break; + case TLV_DEFAULT_DATA_SET: + if (set_dds_return_values(table_info->colnum, + mgt, request)) { + netsnmp_set_request_error(reqinfo, request, + SNMP_NOSUCHOBJECT); + } + break; + case TLV_TIME_PROPERTIES_DATA_SET: + if (set_tds_return_values(table_info->colnum, + mgt, request)) { + netsnmp_set_request_error(reqinfo, request, + SNMP_NOSUCHOBJECT); + } + break; + case TLV_PORT_DATA_SET: + if (set_port_ds_return_values(table_info->colnum, + mgt, request)) { + netsnmp_set_request_error(reqinfo, request, + SNMP_NOSUCHOBJECT); + } + break; + } + } + + return SNMP_ERR_NOERROR; +} + +static int init_ds_table(const char *ds_name, + const oid *ds_oid, + const size_t ds_oid_len, + unsigned int min_column, + unsigned int max_column, + struct mydata *mydata) +{ + netsnmp_table_registration_info *tinfo; + netsnmp_handler_registration *reg; + netsnmp_iterator_info *iinfo; + + tinfo = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); + if (add_ds_table_indexes(tinfo, mydata->id)) { + pr_err("Failed to add indexes for id: %d", mydata->id); + return SNMP_ERR_GENERR; + } + tinfo->min_column = min_column; + tinfo->max_column = max_column; + + reg = netsnmp_create_handler_registration(ds_name, + ds_handler, + ds_oid, + ds_oid_len, + HANDLER_CAN_RONLY); + + iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info); + iinfo->get_first_data_point = get_first_data_point; + iinfo->get_next_data_point = get_next_data_point; + iinfo->table_reginfo = tinfo; + iinfo->flags |= NETSNMP_ITERATOR_FLAG_SORTED; + iinfo->myvoid = mydata; + + netsnmp_register_table_iterator(reg, iinfo); + + return SNMP_ERR_NOERROR; +} + +int init_ptpbase_mib(void *data_void) +{ + static struct mydata cds_mydata = {TLV_CURRENT_DATA_SET}; + static struct mydata pds_mydata = {TLV_PARENT_DATA_SET}; + static struct mydata dds_mydata = {TLV_DEFAULT_DATA_SET}; + static struct mydata tds_mydata = {TLV_TIME_PROPERTIES_DATA_SET}; + static struct mydata port_mydata = {TLV_PORT_DATA_SET, 1}; + const oid clock_cds_oid[] = {SNMP_OID_PTPBASE_CLOCK_CDS}; + const oid clock_pds_oid[] = {SNMP_OID_PTPBASE_CLOCK_PDS}; + const oid clock_dds_oid[] = {SNMP_OID_PTPBASE_CLOCK_DDS}; + const oid clock_tds_oid[] = {SNMP_OID_PTPBASE_CLOCK_TDS}; + const oid port_ds_oid[] = {SNMP_OID_PTPBASE_PORT_DS}; + struct ds_data *data; + + data = SNMP_MALLOC_TYPEDEF(struct ds_data); + if (!data) { + pr_err("Failed to malloc memory"); + goto err; + } + cds_mydata.data = pds_mydata.data = dds_mydata.data = + tds_mydata.data = port_mydata.data = data; + + if (init_ds_table("clock_cds", clock_cds_oid, + OID_LENGTH(clock_cds_oid), + COLUMN_CDS_MIN, COLUMN_CDS_MAX, + &cds_mydata)) { + pr_err("Failed to initialize clock_current_ds"); + goto err_free; + } + if (init_ds_table("clock_pds", clock_pds_oid, + OID_LENGTH(clock_pds_oid), + COLUMN_PDS_MIN, COLUMN_PDS_MAX, + &pds_mydata)) { + pr_err("Failed to initialize clock_current_ds"); + goto err_free; + } + if (init_ds_table("clock_dds", clock_dds_oid, + OID_LENGTH(clock_dds_oid), + COLUMN_DDS_MIN, COLUMN_DDS_MAX, + &dds_mydata)) { + pr_err("Failed to initialize clock_current_ds"); + goto err_free; + } + if (init_ds_table("clock_tds", clock_tds_oid, + OID_LENGTH(clock_tds_oid), + COLUMN_TDS_MIN, COLUMN_TDS_MAX, + &tds_mydata)) { + pr_err("Failed to initialize clock_current_ds"); + goto err_free; + } + if (init_ds_table("port_ds", port_ds_oid, + OID_LENGTH(port_ds_oid), + COLUMN_PORTDS_MIN, COLUMN_PORTDS_MAX, + &port_mydata)) { + pr_err("Failed to initialize port_ds"); + goto err_free; + } + + TAILQ_INIT(&data->msg); + data_void = (void *)data; + + return SNMP_ERR_NOERROR; + +err_free: + SNMP_FREE(data); +err: + data = data_void = NULL; + + return SNMP_ERR_GENERR; +} + +void free_ptpbase_mib(void *data_void) +{ + struct ds_data *data = (struct ds_data *)data_void; + reset_ds_data(data); + SNMP_FREE(data); +} diff --git a/snmp4lptp_mib.h b/snmp4lptp_mib.h index af449ce..5079e6c 100644 --- a/snmp4lptp_mib.h +++ b/snmp4lptp_mib.h @@ -28,4 +28,7 @@ struct ptp_message* snmp4lptp_run_pmc(char *cmd); uint8_t snmp4lptp_get_domain(); +int init_ptpbase_mib(void *data_void); +void free_ptpbase_mib(void *data_void); + #endif /* HAVE_SNMP4LPTP_MIB_H */ -- 1.8.3.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel