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): | 
