summaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorDaniel Willmann <daniel@totalueberwachung.de>2011-04-21 11:43:55 +0200
committerHarald Welte <laforge@gnumonks.org>2014-08-21 15:34:12 +0200
commite9f5894e2c72c39e55bb9173470dff40de61a326 (patch)
treec189931b5582b32b865ce9049e20db89479bf34c /openbsc/src
parentfcf010f7215cbd33b68132023ab756a309265a55 (diff)
libctrl: Add commands to query counters and rate_cntr
These commands are installed in controlif_setup. Query them like this: "rate_ctr.<interval>.<counter group>.<index>.<counter name>" for rate counters and "counter.<counter name>" for regular counters. <interval> may be either "abs" for absolute values or one or "per_{sec,min,hour,day}". It is possible to query all rate counters in a group (regardless of index) or all counters in a group and with a certain index if you omit <counter name> and <index> or just <counter name>.
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/libctrl/control_if.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/openbsc/src/libctrl/control_if.c b/openbsc/src/libctrl/control_if.c
index a607b10b..0e625cd7 100644
--- a/openbsc/src/libctrl/control_if.c
+++ b/openbsc/src/libctrl/control_if.c
@@ -49,7 +49,9 @@
#include <openbsc/abis_nm.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/select.h>
+#include <osmocom/core/statistics.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gsm/tlv.h>
@@ -342,6 +344,259 @@ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
return ret;
}
+static uint64_t get_rate_ctr_value(const struct rate_ctr *ctr, int intv)
+{
+ if (intv >= RATE_CTR_INTV_NUM)
+ return 0;
+
+ /* Absolute value */
+ if (intv == -1) {
+ return ctr->current;
+ } else {
+ return ctr->intv[intv].rate;
+ }
+}
+
+static char *get_all_rate_ctr_in_group(const struct rate_ctr_group *ctrg, int intv)
+{
+ int i;
+ char *counters = talloc_strdup(tall_bsc_ctx, "");
+ if (!counters)
+ return NULL;
+
+ for (i=0;i<ctrg->desc->num_ctr;i++) {
+ counters = talloc_asprintf_append(counters, "\n%s.%u.%s %lu",
+ ctrg->desc->group_name_prefix, ctrg->idx,
+ ctrg->desc->ctr_desc[i].name,
+ get_rate_ctr_value(&ctrg->ctr[i], intv));
+ if (!counters)
+ return NULL;
+ }
+ return counters;
+}
+
+static int get_rate_ctr_group(const char *ctr_group, int intv, struct ctrl_cmd *cmd)
+{
+ int i;
+ char *counters;
+ struct rate_ctr_group *ctrg;
+
+ cmd->reply = talloc_asprintf(cmd, "All counters in group %s", ctr_group);
+ if (!cmd->reply)
+ goto oom;
+
+ for (i=0;;i++) {
+ ctrg = rate_ctr_get_group_by_name_idx(ctr_group, i);
+ if (!ctrg)
+ break;
+
+ counters = get_all_rate_ctr_in_group(ctrg, intv);
+ if (!counters)
+ goto oom;
+
+ cmd->reply = talloc_asprintf_append(cmd->reply, "%s", counters);
+ talloc_free(counters);
+ if (!cmd->reply)
+ goto oom;
+ }
+
+ /* We found no counter group by that name */
+ if (i == 0) {
+ cmd->reply = talloc_asprintf(cmd, "No counter group with name %s.", ctr_group);
+ return CTRL_CMD_ERROR;
+ }
+
+ return CTRL_CMD_REPLY;
+oom:
+ cmd->reply = "OOM.";
+ return CTRL_CMD_ERROR;
+}
+
+static int get_rate_ctr_group_idx(const struct rate_ctr_group *ctrg, int intv, struct ctrl_cmd *cmd)
+{
+ char *counters;
+
+ counters = get_all_rate_ctr_in_group(ctrg, intv);
+ if (!counters)
+ goto oom;
+
+ cmd->reply = talloc_asprintf(cmd, "All counters in %s.%u%s",
+ ctrg->desc->group_name_prefix, ctrg->idx, counters);
+ talloc_free(counters);
+ if (!cmd->reply)
+ goto oom;
+
+ return CTRL_CMD_REPLY;
+oom:
+ cmd->reply = "OOM.";
+ return CTRL_CMD_ERROR;
+}
+
+/* rate_ctr */
+CTRL_CMD_DEFINE(rate_ctr, "rate_ctr *");
+int get_rate_ctr(struct ctrl_cmd *cmd, void *data)
+{
+ int intv;
+ unsigned int idx;
+ char *ctr_group, *ctr_idx, *ctr_name, *tmp, *dup, *saveptr, *interval;
+ struct rate_ctr_group *ctrg;
+ const struct rate_ctr *ctr;
+
+ dup = talloc_strdup(cmd, cmd->variable);
+ if (!dup)
+ goto oom;
+
+ /* Skip over possible prefixes (net.) */
+ tmp = strstr(dup, "rate_ctr");
+ if (!tmp) {
+ talloc_free(dup);
+ cmd->reply = "rate_ctr not a token in rate_ctr command!";
+ goto err;
+ }
+
+ strtok_r(tmp, ".", &saveptr);
+ interval = strtok_r(NULL, ".", &saveptr);
+ if (!interval) {
+ talloc_free(dup);
+ cmd->reply = "Missing interval.";
+ goto err;
+ }
+
+ if (!strcmp(interval, "abs")) {
+ intv = -1;
+ } else if (!strcmp(interval, "per_sec")) {
+ intv = RATE_CTR_INTV_SEC;
+ } else if (!strcmp(interval, "per_min")) {
+ intv = RATE_CTR_INTV_MIN;
+ } else if (!strcmp(interval, "per_hour")) {
+ intv = RATE_CTR_INTV_HOUR;
+ } else if (!strcmp(interval, "per_day")) {
+ intv = RATE_CTR_INTV_DAY;
+ } else {
+ talloc_free(dup);
+ cmd->reply = "Wrong interval.";
+ goto err;
+ }
+
+ ctr_group = strtok_r(NULL, ".", &saveptr);
+ tmp = strtok_r(NULL, ".", &saveptr);
+ if (!ctr_group || !tmp) {
+ talloc_free(dup);
+ cmd->reply = "Counter group must be of form a.b";
+ goto err;
+ }
+ ctr_group[strlen(ctr_group)] = '.';
+
+ ctr_idx = strtok_r(NULL, ".", &saveptr);
+ if (!ctr_idx) {
+ talloc_free(dup);
+ return get_rate_ctr_group(ctr_group, intv, cmd);
+ }
+ idx = atoi(ctr_idx);
+
+ ctrg = rate_ctr_get_group_by_name_idx(ctr_group, idx);
+ if (!ctrg) {
+ talloc_free(dup);
+ cmd->reply = "Counter group not found.";
+ goto err;
+ }
+
+ ctr_name = strtok_r(NULL, "\0", &saveptr);
+ if (!ctr_name) {
+ talloc_free(dup);
+ return get_rate_ctr_group_idx(ctrg, intv, cmd);
+ }
+
+ ctr = rate_ctr_get_by_name(ctrg, ctr_name);
+ if (!ctr) {
+ cmd->reply = "Counter name not found.";
+ talloc_free(dup);
+ goto err;
+ }
+
+ talloc_free(dup);
+
+ cmd->reply = talloc_asprintf(cmd, "%lu", get_rate_ctr_value(ctr, intv));
+ if (!cmd->reply)
+ goto oom;
+
+ return CTRL_CMD_REPLY;
+oom:
+ cmd->reply = "OOM";
+err:
+ return CTRL_CMD_ERROR;
+}
+
+int set_rate_ctr(struct ctrl_cmd *cmd, void *data)
+{
+ cmd->reply = "Can't set rate counter.";
+
+ return CTRL_CMD_ERROR;
+}
+
+int verify_rate_ctr(struct ctrl_cmd *cmd, const char *value, void *data)
+{
+ return 0;
+}
+
+/* counter */
+CTRL_CMD_DEFINE(counter, "counter *");
+int get_counter(struct ctrl_cmd *cmd, void *data)
+{
+ char *ctr_name, *tmp, *dup, *saveptr;
+ struct osmo_counter *counter;
+
+ cmd->reply = "OOM";
+ dup = talloc_strdup(cmd, cmd->variable);
+ if (!dup)
+ goto err;
+
+
+ tmp = strstr(dup, "counter");
+ if (!tmp) {
+ talloc_free(dup);
+ goto err;
+ }
+
+ strtok_r(tmp, ".", &saveptr);
+ ctr_name = strtok_r(NULL, "\0", &saveptr);
+
+ if (!ctr_name)
+ goto err;
+
+ counter = osmo_counter_get_by_name(ctr_name);
+ if (!counter) {
+ cmd->reply = "Counter name not found.";
+ talloc_free(dup);
+ goto err;
+ }
+
+ talloc_free(dup);
+
+ cmd->reply = talloc_asprintf(cmd, "%lu", counter->value);
+ if (!cmd->reply) {
+ cmd->reply = "OOM";
+ goto err;
+ }
+
+ return CTRL_CMD_REPLY;
+err:
+ return CTRL_CMD_ERROR;
+}
+
+int set_counter(struct ctrl_cmd *cmd, void *data)
+{
+
+ cmd->reply = "Can't set counter.";
+
+ return CTRL_CMD_ERROR;
+}
+
+int verify_counter(struct ctrl_cmd *cmd, const char *value, void *data)
+{
+ return 0;
+}
+
int controlif_setup(struct gsm_network *gsmnet, uint16_t port)
{
int ret;
@@ -365,5 +620,8 @@ int controlif_setup(struct gsm_network *gsmnet, uint16_t port)
return ret;
}
+ ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_rate_ctr);
+ ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_counter);
+
return ret;
}