diff options
Diffstat (limited to 'src/vty/stats_vty.c')
-rw-r--r-- | src/vty/stats_vty.c | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/src/vty/stats_vty.c b/src/vty/stats_vty.c new file mode 100644 index 00000000..98253fff --- /dev/null +++ b/src/vty/stats_vty.c @@ -0,0 +1,430 @@ +/* OpenBSC stats helper for the VTY */ +/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> + * (C) 2009-2014 by Holger Hans Peter Freyther + * (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * 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 <stdlib.h> +#include <string.h> + +#include "../../config.h" + +#include <osmocom/vty/command.h> +#include <osmocom/vty/buffer.h> +#include <osmocom/vty/vty.h> +#include <osmocom/vty/telnet_interface.h> +#include <osmocom/vty/telnet_interface.h> +#include <osmocom/vty/misc.h> + +#include <osmocom/core/stats.h> + +#define CFG_STATS_STR "Configure stats sub-system\n" +#define CFG_REPORTER_STR "Configure a stats reporter\n" + +#define SHOW_STATS_STR "Show statistical values\n" + +struct cmd_node cfg_stats_node = { + CFG_STATS_NODE, + "%s(config-stats)# ", + 1 +}; + +static const struct value_string stats_class_strs[] = { + { OSMO_STATS_CLASS_GLOBAL, "global" }, + { OSMO_STATS_CLASS_PEER, "peer" }, + { OSMO_STATS_CLASS_SUBSCRIBER, "subscriber" }, + { 0, NULL } +}; + +static struct osmo_stats_reporter *osmo_stats_vty2srep(struct vty *vty) +{ + if (vty->node == CFG_STATS_NODE) + return vty->index; + + return NULL; +} + +static int set_srep_parameter_str(struct vty *vty, + int (*fun)(struct osmo_stats_reporter *, const char *), + const char *val, const char *param_name) +{ + int rc; + struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty); + OSMO_ASSERT(srep); + + rc = fun(srep, val); + if (rc < 0) { + vty_out(vty, "%% Unable to set %s: %s%s", + param_name, strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +static int set_srep_parameter_int(struct vty *vty, + int (*fun)(struct osmo_stats_reporter *, int), + const char *val, const char *param_name) +{ + int rc; + int int_val; + struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty); + OSMO_ASSERT(srep); + + int_val = atoi(val); + + rc = fun(srep, int_val); + if (rc < 0) { + vty_out(vty, "%% Unable to set %s: %s%s", + param_name, strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_stats_reporter_local_ip, cfg_stats_reporter_local_ip_cmd, + "local-ip ADDR", + "Set the IP address to which we bind locally\n" + "IP Address\n") +{ + return set_srep_parameter_str(vty, osmo_stats_reporter_set_local_addr, + argv[0], "local address"); +} + +DEFUN(cfg_no_stats_reporter_local_ip, cfg_no_stats_reporter_local_ip_cmd, + "no local-ip", + NO_STR + "Set the IP address to which we bind locally\n") +{ + return set_srep_parameter_str(vty, osmo_stats_reporter_set_local_addr, + NULL, "local address"); +} + +DEFUN(cfg_stats_reporter_remote_ip, cfg_stats_reporter_remote_ip_cmd, + "remote-ip ADDR", + "Set the remote IP address to which we connect\n" + "IP Address\n") +{ + return set_srep_parameter_str(vty, osmo_stats_reporter_set_remote_addr, + argv[0], "remote address"); +} + +DEFUN(cfg_stats_reporter_remote_port, cfg_stats_reporter_remote_port_cmd, + "remote-port <1-65535>", + "Set the remote port to which we connect\n" + "Remote port number\n") +{ + return set_srep_parameter_int(vty, osmo_stats_reporter_set_remote_port, + argv[0], "remote port"); +} + +DEFUN(cfg_stats_reporter_mtu, cfg_stats_reporter_mtu_cmd, + "mtu <100-65535>", + "Set the maximum packet size\n" + "Size in byte\n") +{ + return set_srep_parameter_int(vty, osmo_stats_reporter_set_mtu, + argv[0], "mtu"); +} + +DEFUN(cfg_no_stats_reporter_mtu, cfg_no_stats_reporter_mtu_cmd, + "no mtu", + NO_STR "Set the maximum packet size\n") +{ + return set_srep_parameter_int(vty, osmo_stats_reporter_set_mtu, + "0", "mtu"); +} + +DEFUN(cfg_stats_reporter_prefix, cfg_stats_reporter_prefix_cmd, + "prefix PREFIX", + "Set the item name prefix\n" + "The prefix string\n") +{ + return set_srep_parameter_str(vty, osmo_stats_reporter_set_name_prefix, + argv[0], "prefix string"); +} + +DEFUN(cfg_no_stats_reporter_prefix, cfg_no_stats_reporter_prefix_cmd, + "no prefix", + NO_STR + "Set the item name prefix\n") +{ + return set_srep_parameter_str(vty, osmo_stats_reporter_set_name_prefix, + "", "prefix string"); +} + +DEFUN(cfg_stats_reporter_level, cfg_stats_reporter_level_cmd, + "level (global|peer|subscriber)", + "Set the maximum group level\n" + "Report global groups only\n" + "Report global and network peer related groups\n" + "Report global, peer, and subscriber groups\n") +{ + int level = get_string_value(stats_class_strs, argv[0]); + int rc; + struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty); + + OSMO_ASSERT(srep); + rc = osmo_stats_reporter_set_max_class(srep, level); + if (rc < 0) { + vty_out(vty, "%% Unable to set level: %s%s", + strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + + return 0; +} + +DEFUN(cfg_stats_reporter_enable, cfg_stats_reporter_enable_cmd, + "enable", + "Enable the reporter\n") +{ + int rc; + struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty); + OSMO_ASSERT(srep); + + rc = osmo_stats_reporter_enable(srep); + if (rc < 0) { + vty_out(vty, "%% Unable to enable the reporter: %s%s", + strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_stats_reporter_disable, cfg_stats_reporter_disable_cmd, + "disable", + "Disable the reporter\n") +{ + int rc; + struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty); + OSMO_ASSERT(srep); + + rc = osmo_stats_reporter_disable(srep); + if (rc < 0) { + vty_out(vty, "%% Unable to disable the reporter: %s%s", + strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_stats_reporter_statsd, cfg_stats_reporter_statsd_cmd, + "stats reporter statsd", + CFG_STATS_STR CFG_REPORTER_STR "Report to a STATSD server\n") +{ + struct osmo_stats_reporter *srep; + + srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL); + if (!srep) { + srep = osmo_stats_reporter_create_statsd(NULL); + if (!srep) { + vty_out(vty, "%% Unable to create statsd reporter%s", + VTY_NEWLINE); + return CMD_WARNING; + } + srep->max_class = OSMO_STATS_CLASS_GLOBAL; + /* TODO: if needed, add osmo_stats_add_reporter(srep); */ + } + + vty->index = srep; + vty->node = CFG_STATS_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_stats_interval, cfg_stats_interval_cmd, + "stats interval <1-65535>", + CFG_STATS_STR "Set the reporting interval\n" + "Interval in seconds\n") +{ + int rc; + int interval = atoi(argv[0]); + rc = osmo_stats_set_interval(interval); + if (rc < 0) { + vty_out(vty, "%% Unable to set interval: %s%s", + strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + + +DEFUN(cfg_no_stats_reporter_statsd, cfg_no_stats_reporter_statsd_cmd, + "no stats reporter statsd", + NO_STR CFG_STATS_STR CFG_REPORTER_STR "Report to a STATSD server\n") +{ + struct osmo_stats_reporter *srep; + + srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL); + if (!srep) { + vty_out(vty, "%% No statsd logging active%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + osmo_stats_reporter_free(srep); + + return CMD_SUCCESS; +} + +DEFUN(cfg_stats_reporter_log, cfg_stats_reporter_log_cmd, + "stats reporter log", + CFG_STATS_STR CFG_REPORTER_STR "Report to the logger\n") +{ + struct osmo_stats_reporter *srep; + + srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL); + if (!srep) { + srep = osmo_stats_reporter_create_log(NULL); + if (!srep) { + vty_out(vty, "%% Unable to create log reporter%s", + VTY_NEWLINE); + return CMD_WARNING; + } + srep->max_class = OSMO_STATS_CLASS_GLOBAL; + /* TODO: if needed, add osmo_stats_add_reporter(srep); */ + } + + vty->index = srep; + vty->node = CFG_STATS_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_stats_reporter_log, cfg_no_stats_reporter_log_cmd, + "no stats reporter log", + NO_STR CFG_STATS_STR CFG_REPORTER_STR "Report to the logger\n") +{ + struct osmo_stats_reporter *srep; + + srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL); + if (!srep) { + vty_out(vty, "%% No log reporting active%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + osmo_stats_reporter_free(srep); + + return CMD_SUCCESS; +} + +DEFUN(show_stats, + show_stats_cmd, + "show stats", + SHOW_STR SHOW_STATS_STR) +{ + vty_out_statistics_full(vty, ""); + + return CMD_SUCCESS; +} + +static int config_write_stats_reporter(struct vty *vty, struct osmo_stats_reporter *srep) +{ + if (srep == NULL) + return 0; + + switch (srep->type) { + case OSMO_STATS_REPORTER_STATSD: + vty_out(vty, "stats reporter statsd%s", VTY_NEWLINE); + break; + case OSMO_STATS_REPORTER_LOG: + vty_out(vty, "stats reporter log%s", VTY_NEWLINE); + break; + } + + vty_out(vty, " disable%s", VTY_NEWLINE); + + if (srep->have_net_config) { + if (srep->dest_addr_str) + vty_out(vty, " remote-ip %s%s", + srep->dest_addr_str, VTY_NEWLINE); + if (srep->dest_port) + vty_out(vty, " remote-port %d%s", + srep->dest_port, VTY_NEWLINE); + if (srep->bind_addr_str) + vty_out(vty, " local-ip %s%s", + srep->bind_addr_str, VTY_NEWLINE); + if (srep->mtu) + vty_out(vty, " mtu %d%s", + srep->mtu, VTY_NEWLINE); + } + + if (srep->max_class) + vty_out(vty, " level %s%s", + get_value_string(stats_class_strs, srep->max_class), + VTY_NEWLINE); + + if (srep->name_prefix && *srep->name_prefix) + vty_out(vty, " prefix %s%s", + srep->name_prefix, VTY_NEWLINE); + else + vty_out(vty, " no prefix%s", VTY_NEWLINE); + + if (srep->enabled) + vty_out(vty, " enable%s", VTY_NEWLINE); + + return 1; +} + +static int config_write_stats(struct vty *vty) +{ + struct osmo_stats_reporter *srep; + + /* TODO: loop through all reporters */ + srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL); + config_write_stats_reporter(vty, srep); + srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL); + config_write_stats_reporter(vty, srep); + + vty_out(vty, "stats interval %d%s", osmo_stats_config->interval, VTY_NEWLINE); + + return 1; +} + +void osmo_stats_vty_add_cmds() +{ + install_element_ve(&show_stats_cmd); + + install_element(CONFIG_NODE, &cfg_stats_reporter_statsd_cmd); + install_element(CONFIG_NODE, &cfg_no_stats_reporter_statsd_cmd); + install_element(CONFIG_NODE, &cfg_stats_reporter_log_cmd); + install_element(CONFIG_NODE, &cfg_no_stats_reporter_log_cmd); + install_element(CONFIG_NODE, &cfg_stats_interval_cmd); + + install_node(&cfg_stats_node, config_write_stats); + vty_install_default(CFG_STATS_NODE); + + install_element(CFG_STATS_NODE, &cfg_stats_reporter_local_ip_cmd); + install_element(CFG_STATS_NODE, &cfg_no_stats_reporter_local_ip_cmd); + install_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_ip_cmd); + install_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_port_cmd); + install_element(CFG_STATS_NODE, &cfg_stats_reporter_mtu_cmd); + install_element(CFG_STATS_NODE, &cfg_no_stats_reporter_mtu_cmd); + install_element(CFG_STATS_NODE, &cfg_stats_reporter_prefix_cmd); + install_element(CFG_STATS_NODE, &cfg_no_stats_reporter_prefix_cmd); + install_element(CFG_STATS_NODE, &cfg_stats_reporter_level_cmd); + install_element(CFG_STATS_NODE, &cfg_stats_reporter_enable_cmd); + install_element(CFG_STATS_NODE, &cfg_stats_reporter_disable_cmd); +} |