Change in osmo-sysmon[master]: Add ping probe support

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Max gerrit-no-reply at lists.osmocom.org
Thu Jan 31 10:22:34 UTC 2019


Max has submitted this change and it was merged. ( https://gerrit.osmocom.org/12710 )

Change subject: Add ping probe support
......................................................................

Add ping probe support

Use liboping (new dependency) to add 'ping XXX' entries support in .cfg
file, where XXX can be either IP address or FQDN.

Sample output:
...
  ping
    ya.ru
      IP: 2a02:6b8::2:242
      dropped: 3/3
    8.8.8.8
      IP: 8.8.8.8
      dropped: 0/3
      latency: 20.4 ms
      TTL: 120
...

N. B: to gather actual ping statistic we have to be able to send ICMP
requests (have enough privileges to work with RAW sockets).

Related: SYS#2655
Change-Id: Ife32540b532fb54368f63c78fb7837b84d4e8c76
---
M configure.ac
M src/Makefile.am
M src/osysmon.h
M src/osysmon_main.c
A src/osysmon_ping.c
5 files changed, 281 insertions(+), 2 deletions(-)

Approvals:
  Jenkins Builder: Verified
  osmith: Looks good to me, approved



diff --git a/configure.ac b/configure.ac
index 734ac99..d98de89 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,6 +43,8 @@
 PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.11.0)
 PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.11.0)
 PKG_CHECK_MODULES(LIBMNL, libmnl)
+dnl FIXME: bump to 1.10.0 once it's available on build slaves and remove workaround from osysmon_ping.c
+PKG_CHECK_MODULES(LIBOPING, liboping >= 1.9.0)
 
 dnl checks for header files
 AC_HEADER_STDC
diff --git a/src/Makefile.am b/src/Makefile.am
index cb85da2..d0d6a22 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,11 +24,12 @@
 libintern_la_SOURCES = simple_ctrl.c
 libintern_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
 
-osmo_sysmon_CFLAGS = $(LIBMNL_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(AM_CFLAGS)
+osmo_sysmon_CFLAGS = $(LIBMNL_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOPING_CFLAGS) $(AM_CFLAGS)
 
 osmo_sysmon_LDADD = $(LDADD) \
 	$(LIBOSMOVTY_LIBS) \
 	$(LIBMNL_LIBS) \
+	$(LIBOPING_LIBS) \
 	$(NULL)
 
 osmo_sysmon_SOURCES = \
@@ -37,6 +38,7 @@
 	osysmon_sysinfo.c \
 	osysmon_rtnl.c \
 	osysmon_file.c \
+	osysmon_ping.c \
 	osysmon_main.c \
 	$(NULL)
 
diff --git a/src/osysmon.h b/src/osysmon.h
index 735b11e..df8bf8d 100644
--- a/src/osysmon.h
+++ b/src/osysmon.h
@@ -9,6 +9,7 @@
 #include "value_node.h"
 
 struct rtnl_client_state;
+struct ping_state;
 
 struct osysmon_state {
 	struct rtnl_client_state *rcs;
@@ -18,6 +19,7 @@
 	struct llist_head netdevs;
 	/* list of 'struct osysmon_file' */
 	struct llist_head files;
+	struct ping_state *pings;
 };
 
 extern struct osysmon_state *g_oss;
@@ -28,6 +30,7 @@
 	CTRL_CLIENT_NODE = _LAST_OSMOVTY_NODE + 1,
 	CTRL_CLIENT_GETVAR_NODE,
 	NETDEV_NODE,
+	PING_NODE,
 };
 
 
@@ -42,5 +45,8 @@
 int osysmon_sysinfo_init();
 int osysmon_sysinfo_poll(struct value_node *parent);
 
+int osysmon_ping_init();
+int osysmon_ping_poll(struct value_node *parent);
+
 int osysmon_file_init();
 int osysmon_file_poll(struct value_node *parent);
diff --git a/src/osysmon_main.c b/src/osysmon_main.c
index 82df61f..eb4f50b 100644
--- a/src/osysmon_main.c
+++ b/src/osysmon_main.c
@@ -193,7 +193,7 @@
 
 int main(int argc, char **argv)
 {
-	int rc;
+	int rc, ping_init;
 
 	osmo_init_logging2(NULL, &log_info);
 
@@ -207,6 +207,7 @@
 	osysmon_sysinfo_init();
 	osysmon_ctrl_init();
 	osysmon_rtnl_init();
+	ping_init = osysmon_ping_init();
 	osysmon_file_init();
 
 	rc = vty_read_config_file(cmdline_opts.config_file, NULL);
@@ -233,6 +234,10 @@
 		osysmon_sysinfo_poll(root);
 		osysmon_ctrl_poll(root);
 		osysmon_rtnl_poll(root);
+
+		if (ping_init == 0)
+			osysmon_ping_poll(root);
+
 		osysmon_file_poll(root);
 
 		display_update(root);
diff --git a/src/osysmon_ping.c b/src/osysmon_ping.c
new file mode 100644
index 0000000..f736798
--- /dev/null
+++ b/src/osysmon_ping.c
@@ -0,0 +1,264 @@
+/* Simple Osmocom System Monitor (osysmon): Support for ping probe */
+
+/* (C) 2018 by sysmocom - s.f.m.c. GmbH.
+ * Author: Max Suraev
+ * All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ *  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 <stdbool.h>
+#include <errno.h>
+
+#include <oping.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+
+#include "osysmon.h"
+#include "value_node.h"
+
+/***********************************************************************
+ * Data model
+ ***********************************************************************/
+
+#define BUFLEN 128
+
+struct ping_state {
+       pingobj_t *ping_handle;
+};
+
+/* FIXME: replace with ping_iterator_count() once we bump requirements to liboping 1.10.0+ */
+static unsigned iterator_count(pingobj_t *p)
+{
+	unsigned count = 0;
+	pingobj_iter_t *iter;
+	for (iter = ping_iterator_get(p); iter; iter = ping_iterator_next(iter))
+		count++;
+	return count;
+}
+
+/* Workaround for liboping issue https://github.com/octo/liboping/issues/43 */
+static int add_host(pingobj_t *pinger, const char *host)
+{
+	int num_host = iterator_count(pinger),
+		rc = ping_host_add(pinger, host);
+
+	if (rc < 0) {
+		if (num_host != iterator_count(pinger))
+			ping_host_remove(pinger, host);
+	}
+
+	return rc;
+}
+
+
+static bool add_drop(pingobj_iter_t *iter, struct value_node *vn_host)
+{
+	char *s = NULL;
+	uint32_t drop, seq;
+	size_t len = sizeof(drop);
+	int rc = ping_iterator_get_info(iter, PING_INFO_DROPPED, &drop, &len);
+	if (rc)
+		return false;
+
+	len = sizeof(seq);
+	rc = ping_iterator_get_info(iter, PING_INFO_SEQUENCE, &seq, &len);
+	if (rc)
+		return false;
+
+	osmo_talloc_asprintf(vn_host, s, "%u/%u", drop, seq);
+	value_node_add(vn_host, "dropped", s);
+
+	return true;
+}
+
+static bool add_ttl(pingobj_iter_t *iter, struct value_node *vn_host)
+{
+	int ttl, rc;
+	size_t len = sizeof(ttl);
+
+	rc = ping_iterator_get_info(iter, PING_INFO_RECV_TTL, &ttl, &len);
+	if (rc)
+		return false;
+
+	if (ttl > -1) {
+		char *s = NULL;
+		osmo_talloc_asprintf(vn_host, s, "%d", ttl);
+		value_node_add(vn_host, "TTL", s);
+	}
+
+	return true;
+}
+
+static bool add_latency(pingobj_iter_t *iter, struct value_node *vn_host)
+{
+	double latency;
+	size_t len = sizeof(latency);
+	int rc = ping_iterator_get_info(iter, PING_INFO_LATENCY, &latency, &len);
+	if (rc)
+		return false;
+
+	if (latency > -1) {
+		char *s = NULL;
+		osmo_talloc_asprintf(vn_host, s, "%.1lf ms", latency);
+		value_node_add(vn_host, "latency", s);
+	}
+
+	return true;
+}
+
+
+/***********************************************************************
+ * VTY
+ ***********************************************************************/
+
+static struct cmd_node ping_node = {
+	PING_NODE,
+	"%s(config-ping)# ",
+	1,
+};
+
+int osysmon_ping_go_parent(struct vty *vty)
+{
+	switch (vty->node) {
+	case PING_NODE:
+		vty->node = CONFIG_NODE;
+		vty->index = NULL;
+		break;
+	default:
+		break;
+	}
+	return vty->node;
+}
+
+#define PING_STR "Configure a host to be monitored/pinged\n"
+
+DEFUN(cfg_ping, cfg_ping_cmd,
+      "ping HOST",
+      PING_STR "Name of the host to ping\n")
+{
+	int rc = add_host(g_oss->pings->ping_handle, argv[0]);
+	if (rc < 0) {
+		vty_out(vty, "[%d] Couldn't add pinger for %s: %s%s",
+			iterator_count(g_oss->pings->ping_handle), argv[0],
+			ping_get_error(g_oss->pings->ping_handle), VTY_NEWLINE);
+
+		return CMD_WARNING;
+	}
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_ping, cfg_no_ping_cmd,
+      "no ping HOST",
+      NO_STR PING_STR "Name of the host to ping\n")
+{
+	int rc = ping_host_remove(g_oss->pings->ping_handle, argv[0]);
+	if (rc < 0) {
+		vty_out(vty, "[%d] Couldn't remove %s pinger: %s%s",
+			iterator_count(g_oss->pings->ping_handle), argv[0],
+			ping_get_error(g_oss->pings->ping_handle), VTY_NEWLINE);
+
+		return CMD_WARNING;
+	}
+
+	return CMD_SUCCESS;
+}
+
+static int config_write_ping(struct vty *vty)
+{
+	char buf[BUFLEN];
+	pingobj_iter_t *iter;
+	for (iter = ping_iterator_get(g_oss->pings->ping_handle); iter; iter = ping_iterator_next(iter)) {
+		size_t len = BUFLEN;
+		/* hostname as it was supplied via vty 'ping' entry */
+		if (ping_iterator_get_info(iter, PING_INFO_USERNAME, buf, &len))
+			return CMD_WARNING;
+
+		vty_out(vty, "ping %s%s", buf, VTY_NEWLINE);
+	}
+
+	return CMD_SUCCESS;
+}
+
+
+/***********************************************************************
+ * Runtime Code
+ ***********************************************************************/
+
+/* called once on startup before config file parsing */
+int osysmon_ping_init()
+{
+	install_element(CONFIG_NODE, &cfg_ping_cmd);
+	install_element(CONFIG_NODE, &cfg_no_ping_cmd);
+	install_node(&ping_node, config_write_ping);
+
+	g_oss->pings = talloc_zero(NULL, struct ping_state);
+	if (!g_oss->pings)
+		return -ENOMEM;
+
+	g_oss->pings->ping_handle = ping_construct();
+
+	if (g_oss->pings->ping_handle)
+		return 0;
+
+	return -EINVAL;
+}
+
+/* called periodically */
+int osysmon_ping_poll(struct value_node *parent)
+{
+	char buf[BUFLEN];
+	struct value_node *vn_host;
+	int num_host = iterator_count(g_oss->pings->ping_handle);
+	pingobj_iter_t *iter;
+	struct value_node *vn_ping = value_node_add(parent, "ping", NULL);
+	if (!vn_ping)
+		return -ENOMEM;
+
+	for (iter = ping_iterator_get(g_oss->pings->ping_handle); iter; iter = ping_iterator_next(iter)) {
+		size_t len = BUFLEN;
+		int rc = ping_iterator_get_info(iter, PING_INFO_USERNAME, buf, &len);
+		if (rc)
+			return -EINVAL;
+
+		vn_host = value_node_find_or_add(vn_ping, talloc_strdup(vn_ping, buf));
+		if (!vn_host)
+			return -ENOMEM;
+
+		len = BUFLEN; /* IP address is looked up on-call, even 40 bytes should be enough */
+		rc = ping_iterator_get_info(iter, PING_INFO_ADDRESS, buf, &len);
+		if (rc)
+			return -EINVAL;
+
+		value_node_add(vn_host, "IP", buf);
+
+		add_drop(iter, vn_host);
+
+		/* Parameters below might be absent from output depending on the host reachability: */
+		add_latency(iter, vn_host);
+		add_ttl(iter, vn_host);
+	}
+
+	if (num_host)
+		return ping_send(g_oss->pings->ping_handle);
+
+	return 0;
+}

-- 
To view, visit https://gerrit.osmocom.org/12710
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-sysmon
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: Ife32540b532fb54368f63c78fb7837b84d4e8c76
Gerrit-Change-Number: 12710
Gerrit-PatchSet: 10
Gerrit-Owner: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Reviewer: daniel <dwillmann at sysmocom.de>
Gerrit-Reviewer: osmith <osmith at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190131/f156a91f/attachment.htm>


More information about the gerrit-log mailing list