Three random picked mib object from ptpbase_mib is initialized in sub agent and data is received from ptp4l. All different MIBs should be placed in separate .c files and use the combined .h file (snmpd_mib.h) for their global initialization function.
Signed-off-by: Anders Selhammer <anders.selham...@est.tech> --- makefile | 2 +- optprg.sh | 2 +- ptpbase_mib.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ snmpd.c | 39 ++++++++++ snmpd_mib.h | 32 ++++++++ 5 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 ptpbase_mib.c create mode 100644 snmpd_mib.h diff --git a/makefile b/makefile index fdf3747..5c28059 100644 --- a/makefile +++ b/makefile @@ -52,7 +52,7 @@ ptp4l: $(OBJ) nsm: config.o filter.o hash.o mave.o mmedian.o msg.o nsm.o print.o raw.o \ rtnl.o sk.o transport.o tlv.o tsproc.o udp.o udp6.o uds.o util.o version.o -snmpd: config.o hash.o msg.o pmc_common.o print.o raw.o sk.o \ +snmpd: config.o hash.o msg.o pmc_common.o print.o ptpbase_mib.o raw.o sk.o \ snmpd.o tlv.o transport.o udp.o udp6.o uds.o util.o pmc: config.o hash.o msg.o pmc.o pmc_common.o print.o raw.o sk.o tlv.o \ diff --git a/optprg.sh b/optprg.sh index dda04dc..3074dd3 100755 --- a/optprg.sh +++ b/optprg.sh @@ -25,7 +25,7 @@ snmp_files() { libsnmp=/usr/include/net-snmp/ if [ -d ${libsnmp} ]; then - printf " snmpd snmpd.o" + printf " snmpd snmpd.o ptpbase_mib.o" fi } diff --git a/ptpbase_mib.c b/ptpbase_mib.c new file mode 100644 index 0000000..9ee2a07 --- /dev/null +++ b/ptpbase_mib.c @@ -0,0 +1,231 @@ +/** + * @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 "print.h" +#include "snmpd_mib.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_DEFAULT_DS_ENTRY SNMP_OID_PTPBASE_OBJ_CLOCKINFO, 3, 1 +#define SNMP_OID_PTPBASE_CLOCK_PORT_DS_ENTRY SNMP_OID_PTPBASE_OBJ_CLOCKINFO, 8, 1 + +/* + * other internal defines and types + */ +#define CMD_MAX_LEN 1024 + +enum rettype { + SNMPD_UNSIGNED = 0, +}; + +union retval { + unsigned int ui; +}; + +struct retdata { + enum rettype type; + union retval val; +}; + +/* + * function declarations + */ +static int get_mgmt_data(struct ptp_message *msg, + struct management_tlv **mgt) +{ + int action; + struct TLV *tlv; + + if (msg_type(msg) != MANAGEMENT) { + pr_err("msg type not MANAGEMENT"); + return -1; + } + + action = management_action(msg); + if (action < GET || action > ACKNOWLEDGE) { + pr_err("incorrect action"); + return -1; + } + + if (msg->tlv_count != 1) { + pr_err("incorrect tlv count"); + return -1; + } + + 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 -1; + } else { + pr_err("unknown-tlv"); + return -1; + } + + *mgt = (struct management_tlv *) msg->management.suffix; + if ((*mgt)->length == 2 && (*mgt)->id != TLV_NULL_MANAGEMENT) { + pr_err("empty-tlv"); + return -1; + } + return 0; +} + +static int get_msg_retdata(struct ptp_message *msg, struct retdata *ret) +{ + struct management_tlv *mgt = NULL; + struct management_tlv_datum *mtd; + struct tlv_extra *extra = NULL; + + if (get_mgmt_data(msg, &mgt)) { + return -1; + } + extra = TAILQ_FIRST(&msg->tlv_list); + + switch (mgt->id) { + case TLV_PRIORITY1: + case TLV_PRIORITY2: + case TLV_VERSION_NUMBER: + mtd = (struct management_tlv_datum *) mgt->data; + ret->val.ui = mtd->val; + ret->type = SNMPD_UNSIGNED; + break; + } + (void)extra; // Avoid build warning in example + return 0; +} + +static int command_lookup(char *name, char *cmd) +{ + if (strcmp(name, "default_ds_priority1") == 0) { + snprintf(cmd, CMD_MAX_LEN, "GET PRIORITY1"); + } else if (strcmp(name, "default_ds_priority2") == 0) { + snprintf(cmd, CMD_MAX_LEN, "GET PRIORITY2"); + } else if (strcmp(name, "port_ds_ptp_version") == 0) { + snprintf(cmd, CMD_MAX_LEN, "GET VERSION_NUMBER"); + } else { + return -1; + } + return 0; +} + +static int handle_pdu(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + struct ptp_message *msg; + char cmd[CMD_MAX_LEN]; + struct retdata ret; + int err = -1; + + if (command_lookup(reginfo->handlerName, cmd)) { + pr_err("Failed to lookup command from reginfo"); + return SNMP_ERR_GENERR; + } + + switch (reqinfo->mode) { + case MODE_GET: + msg = run_pmc(cmd); + if (!msg) { + return SNMP_ERR_GENERR; + } + if (get_msg_retdata(msg, &ret)) { + msg_put(msg); + return SNMP_ERR_GENERR; + } + msg_put(msg); + switch (ret.type) { + case SNMPD_UNSIGNED: + err = snmp_set_var_typed_value(requests->requestvb, + ASN_UNSIGNED, + &ret.val.ui, + sizeof(ret.val)); + break; + } + if (err) { + return SNMP_ERR_GENERR; + } + break; + default: + snmp_log(LOG_ERR, "unknown mode (%d) in handle_totalClients\n", + reqinfo->mode); + return SNMP_ERR_GENERR; + } + return SNMP_ERR_NOERROR; +} + +static int init_default_ds_priority1(void) +{ + netsnmp_handler_registration *hr; + const oid default_ds_priority1_oid[] = { SNMP_OID_PTPBASE_CLOCK_DEFAULT_DS_ENTRY, 6 }; + + hr = netsnmp_create_handler_registration("default_ds_priority1", + handle_pdu, + default_ds_priority1_oid, + OID_LENGTH(default_ds_priority1_oid), + HANDLER_CAN_RONLY); + return netsnmp_register_scalar(hr); +} + +static int init_default_ds_priority2(void) +{ + netsnmp_handler_registration *hr; + const oid default_ds_priority2_oid[] = { SNMP_OID_PTPBASE_CLOCK_DEFAULT_DS_ENTRY, 7 }; + + hr = netsnmp_create_handler_registration("default_ds_priority2", + handle_pdu, + default_ds_priority2_oid, + OID_LENGTH(default_ds_priority2_oid), + HANDLER_CAN_RONLY); + return netsnmp_register_scalar(hr); +} + +static int init_port_ds_ptp_version(void) +{ + netsnmp_handler_registration *hr; + const oid port_ds_ptp_version_oid[] = { SNMP_OID_PTPBASE_CLOCK_PORT_DS_ENTRY, 15 }; + + hr = netsnmp_create_handler_registration("port_ds_ptp_version", + handle_pdu, + port_ds_ptp_version_oid, + OID_LENGTH(port_ds_ptp_version_oid), + HANDLER_CAN_RONLY); + return netsnmp_register_scalar(hr); +} + +void init_ptpbase_mib() +{ + if (init_default_ds_priority1()) { + pr_err("Failed to initialize default_ds_priority1"); + } + if (init_default_ds_priority2()) { + pr_err("Failed to initialize default_ds_priority2"); + } + if (init_port_ds_ptp_version()) { + pr_err("Failed to initialize port_ds_ptp_version"); + } +} diff --git a/snmpd.c b/snmpd.c index e0e9727..803cf74 100644 --- a/snmpd.c +++ b/snmpd.c @@ -17,6 +17,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include <errno.h> +#include <poll.h> + #include <net-snmp/net-snmp-config.h> #include <net-snmp/net-snmp-includes.h> #include <net-snmp/agent/net-snmp-agent-includes.h> @@ -24,10 +27,44 @@ #include "config.h" #include "pmc_common.h" #include "print.h" +#include "snmpd_mib.h" #include "util.h" +#define SNMP_NFD 1 static struct pmc *pmc; +struct ptp_message* run_pmc(char *cmd) +{ + struct pollfd pollfd[SNMP_NFD]; + int cnt, tmo = 100; + + pollfd[0].fd = pmc_get_transport_fd(pmc); + pollfd[0].events = POLLIN | POLLPRI; + + if (pmc_do_command(pmc, cmd)) { + pr_err("bad command: %s", cmd); + } + + while (is_running()) { + cnt = poll(pollfd, SNMP_NFD, tmo); + if (cnt < 0) { + if (EINTR == errno) { + continue; + } else { + pr_emerg("poll failed"); + break; + } + } else if (!cnt) { + break; + } + + if (pollfd[0].revents & (POLLIN|POLLPRI)) { + return pmc_recv(pmc); + } + } + return NULL; +} + static int open_pmc(struct config *cfg) { char uds_local[MAX_IFNAME_SIZE + 1]; @@ -45,6 +82,8 @@ static int open_snmp() NETSNMP_DS_AGENT_ROLE, 1); init_agent("linuxptpAgent"); + init_ptpbase_mib(); + init_snmp("linuxptpAgent"); return 0; diff --git a/snmpd_mib.h b/snmpd_mib.h new file mode 100644 index 0000000..e27de3e --- /dev/null +++ b/snmpd_mib.h @@ -0,0 +1,32 @@ +/** + * @file snmpd_mib.h + * @brief Common header file for all supported mibs in linuxptp + * @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. + */ +#ifndef SNMPDMIB_H +#define SNMPDMIB_H + +#include "msg.h" + +/* + * function declarations + */ +struct ptp_message* run_pmc(char *cmd); + +void init_ptpbase_mib(); + +#endif /* SNMPDMIB_H */ -- 1.8.3.1 --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel