summaryrefslogtreecommitdiffstats
path: root/src/rate_ctr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rate_ctr.c')
-rw-r--r--src/rate_ctr.c118
1 files changed, 117 insertions, 1 deletions
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);