diff options
-rw-r--r-- | include/osmocom/core/rate_ctr.h | 2 | ||||
-rw-r--r-- | src/rate_ctr.c | 118 | ||||
-rw-r--r-- | tests/gb/gprs_ns_test.c | 2 | ||||
-rw-r--r-- | tests/stats/stats_test.ok | 84 |
4 files changed, 161 insertions, 45 deletions
diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h index 74414e98..6ce2dfed 100644 --- a/include/osmocom/core/rate_ctr.h +++ b/include/osmocom/core/rate_ctr.h @@ -48,7 +48,7 @@ struct rate_ctr_group_desc { /*! The class to which this group belongs */ int class_id; /*! The number of counters in this group */ - const unsigned int num_ctr; + unsigned int num_ctr; /*! Pointer to array of counter names */ const struct rate_ctr_desc *ctr_desc; }; diff --git a/src/rate_ctr.c b/src/rate_ctr.c index a04a7760..6de59a02 100644 --- a/src/rate_ctr.c +++ b/src/rate_ctr.c @@ -1,4 +1,4 @@ -/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> +/* (C) 2009-2017 by Harald Welte <laforge@gnumonks.org> * * All Rights Reserved * @@ -55,6 +55,7 @@ * * \file rate_ctr.c */ +#include <stdbool.h> #include <stdint.h> #include <string.h> @@ -63,11 +64,117 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/timer.h> #include <osmocom/core/rate_ctr.h> +#include <osmocom/core/logging.h> static LLIST_HEAD(rate_ctr_groups); static void *tall_rate_ctr_ctx; + +static bool rate_ctrl_group_desc_validate(const struct rate_ctr_group_desc *desc, bool quiet) +{ + unsigned int i; + const struct rate_ctr_desc *ctr_desc = desc->ctr_desc; + + if (!desc) { + LOGP(DLGLOBAL, LOGL_ERROR, "NULL is not a valid counter group descriptor\n"); + return false; + } + + DEBUGP(DLGLOBAL, "validating counter group %p(%s) with %u counters\n", desc, + desc->group_name_prefix, desc->num_ctr); + + if (!osmo_identifier_valid(desc->group_name_prefix)) { + if (!quiet) + LOGP(DLGLOBAL, LOGL_ERROR, "'%s' is not a valid counter group identifier\n", + desc->group_name_prefix); + return false; + } + + for (i = 0; i < desc->num_ctr; i++) { + if (!osmo_identifier_valid(ctr_desc[i].name)) { + if (!quiet) + LOGP(DLGLOBAL, LOGL_ERROR, "'%s' is not a valid counter identifier\n", + ctr_desc[i].name); + return false; + } + } + + return true; +} + +/* return 'in' if it doesn't contaon any '.'; otherwise allocate a copy and + * replace all '.' with ':' */ +static char *mangle_identifier_ifneeded(const void *ctx, const char *in) +{ + char *out; + unsigned int i; + + if (!in) + return NULL; + + if (!strchr(in, '.')) + return (char *)in; + + out = talloc_strdup(ctx, in); + OSMO_ASSERT(out); + + for (i = 0; i < strlen(out); i++) { + if (out[i] == '.') + out[i] = ':'; + } + + return out; +} + +/* "mangle" a rate counter group descriptor, i.e. replace any '.' with ':' */ +static struct rate_ctr_group_desc * +rate_ctr_group_desc_mangle(void *ctx, const struct rate_ctr_group_desc *desc) +{ + struct rate_ctr_group_desc *desc_new = talloc_zero(ctx, struct rate_ctr_group_desc); + int i; + + OSMO_ASSERT(desc_new); + + /* mangle the name_prefix but copy/keep the rest */ + desc_new->group_name_prefix = mangle_identifier_ifneeded(desc_new, desc->group_name_prefix); + desc_new->group_description = desc->group_description; + desc_new->class_id = desc->class_id; + desc_new->num_ctr = desc->num_ctr; + desc_new->ctr_desc = talloc_array(desc_new, struct rate_ctr_desc, desc_new->num_ctr); + OSMO_ASSERT(desc_new->ctr_desc); + + for (i = 0; i < desc->num_ctr; i++) { + struct rate_ctr_desc *ctrd_new = (struct rate_ctr_desc *) desc_new->ctr_desc; + const struct rate_ctr_desc *ctrd = desc->ctr_desc; + + if (!ctrd[i].name) { + LOGP(DLGLOBAL, LOGL_ERROR, "counter group '%s'[%d] == NULL, aborting\n", + desc->group_name_prefix, i); + goto err_free; + } + + ctrd_new[i].name = mangle_identifier_ifneeded(desc_new->ctr_desc, ctrd[i].name); + ctrd_new[i].description = ctrd[i].description; + } + + if (!rate_ctrl_group_desc_validate(desc_new, false)) { + /* simple mangling of identifiers ('.' -> ':') was not sufficient to render a valid + * descriptor, we have to bail out */ + LOGP(DLGLOBAL, LOGL_ERROR, "counter group '%s' still invalid after mangling\n", + desc->group_name_prefix); + goto err_free; + } + + LOGP(DLGLOBAL, LOGL_INFO, "Needed to mangle ounter group '%s' names still using '.' as " + "separator, please consider updating the application\n", desc->group_name_prefix); + + return desc_new; +err_free: + talloc_free(desc_new); + return NULL; +} + /*! Allocate a new group of counters according to description * \param[in] ctx \ref talloc context * \param[in] desc Rate counter group description @@ -80,6 +187,15 @@ struct rate_ctr_group *rate_ctr_group_alloc(void *ctx, unsigned int size; struct rate_ctr_group *group; + /* attempt to mangle all '.' in identifiers to ':' for backwards compat */ + if (!rate_ctrl_group_desc_validate(desc, true)) { + /* don't use 'ctx' here as it would screw up memory leak debugging e.g. + * in osmo-msc */ + desc = rate_ctr_group_desc_mangle(NULL, desc); + if (!desc) + return NULL; + } + size = sizeof(struct rate_ctr_group) + desc->num_ctr * sizeof(struct rate_ctr); diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index 0bbf9432..fac3c36f 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -261,7 +261,7 @@ static void dump_rate_ctr_group(FILE *stream, const char *prefix, for (i = 0; i < ctrg->desc->num_ctr; i++) { struct rate_ctr *ctr = &ctrg->ctr[i]; - if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.')) + if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, ':')) fprintf(stream, " %s%s: %llu%s", prefix, ctrg->desc->ctr_desc[i].description, (long long)ctr->current, diff --git a/tests/stats/stats_test.ok b/tests/stats/stats_test.ok index a0c001b9..cb9daf22 100644 --- a/tests/stats/stats_test.ok +++ b/tests/stats/stats_test.ok @@ -2,14 +2,14 @@ Start test: test_reporting test1: open test2: open report (initial): - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test1: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test1: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test1: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 - test1: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test1: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 + test1: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 test2: item p= g=test.one i=2 n=item.a v=-1 u=ma test1: item p= g=test.one i=2 n=item.a v=-1 u=ma test2: item p= g=test.one i=2 n=item.b v=-1 u=kb @@ -19,19 +19,19 @@ report (initial): test2: item p= g=test.one i=1 n=item.b v=-1 u=kb test1: item p= g=test.one i=1 n=item.b v=-1 u=kb report (srep1 global): - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 test2: item p= g=test.one i=2 n=item.a v=-1 u=ma test2: item p= g=test.one i=2 n=item.b v=-1 u=kb test2: item p= g=test.one i=1 n=item.a v=-1 u=ma test2: item p= g=test.one i=1 n=item.b v=-1 u=kb report (srep1 peer): - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 test2: item p= g=test.one i=2 n=item.a v=-1 u=ma test1: item p= g=test.one i=2 n=item.a v=-1 u=ma test2: item p= g=test.one i=2 n=item.b v=-1 u=kb @@ -41,14 +41,14 @@ report (srep1 peer): test2: item p= g=test.one i=1 n=item.b v=-1 u=kb test1: item p= g=test.one i=1 n=item.b v=-1 u=kb report (srep1 subscriber): - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test1: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test1: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test1: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 - test1: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test1: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 + test1: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 test2: item p= g=test.one i=2 n=item.a v=-1 u=ma test1: item p= g=test.one i=2 n=item.a v=-1 u=ma test2: item p= g=test.one i=2 n=item.b v=-1 u=kb @@ -59,49 +59,49 @@ report (srep1 subscriber): test1: item p= g=test.one i=1 n=item.b v=-1 u=kb report (srep2 disabled): test2: close - test1: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test1: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test1: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test1: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test1: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test1: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 test1: item p= g=test.one i=2 n=item.a v=-1 u=ma test1: item p= g=test.one i=2 n=item.b v=-1 u=kb test1: item p= g=test.one i=1 n=item.a v=-1 u=ma test1: item p= g=test.one i=1 n=item.b v=-1 u=kb report (srep2 enabled, no flush forced): test2: open - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=1 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=1 n=ctr:b v=0 d=0 test2: item p= g=test.one i=2 n=item.a v=-1 u=ma test2: item p= g=test.one i=2 n=item.b v=-1 u=kb test2: item p= g=test.one i=1 n=item.a v=-1 u=ma test2: item p= g=test.one i=1 n=item.b v=-1 u=kb report (should be empty): report (group 1, counter 1 update): - test2: counter p= g=ctr-test.one i=1 n=ctr.a v=1 d=1 - test1: counter p= g=ctr-test.one i=1 n=ctr.a v=1 d=1 + test2: counter p= g=ctr-test:one i=1 n=ctr:a v=1 d=1 + test1: counter p= g=ctr-test:one i=1 n=ctr:a v=1 d=1 report (group 1, item 1 update): test2: item p= g=test.one i=1 n=item.a v=10 u=ma test1: item p= g=test.one i=1 n=item.a v=10 u=ma report (remove statg1, ctrg1): - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test1: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 - test1: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 + test1: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 test2: item p= g=test.one i=2 n=item.a v=-1 u=ma test1: item p= g=test.one i=2 n=item.a v=-1 u=ma test2: item p= g=test.one i=2 n=item.b v=-1 u=kb test1: item p= g=test.one i=2 n=item.b v=-1 u=kb report (remove srep1): test1: close - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 test2: item p= g=test.one i=2 n=item.a v=-1 u=ma test2: item p= g=test.one i=2 n=item.b v=-1 u=kb report (remove statg2): - test2: counter p= g=ctr-test.one i=2 n=ctr.a v=0 d=0 - test2: counter p= g=ctr-test.one i=2 n=ctr.b v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:a v=0 d=0 + test2: counter p= g=ctr-test:one i=2 n=ctr:b v=0 d=0 report (remove srep2): test2: close report (remove ctrg2, should be empty): |