diff options
author | Harald Welte <laforge@netfilter.org> | 2009-12-21 09:26:17 +0100 |
---|---|---|
committer | Harald Welte <laforge@netfilter.org> | 2009-12-21 13:33:10 +0100 |
commit | 38fe2a67e1a376e4370ddfed2f75687075cc9e6b (patch) | |
tree | a0911edf70783dc13139ee26ad1c5607708f3b62 /openbsc/src/meas_rep.c | |
parent | 56315f02bb88f0595d369c2d80f6556922758f62 (diff) |
meas_rep: utility function for processing of measurement reports
This provides two functions: get_meas_rep_avg() to obtain the sliding
window average of one particular field, and meas_rep_n_out_of_m_be()
to check if at least N out of M measurments are >= BE.
Diffstat (limited to 'openbsc/src/meas_rep.c')
-rw-r--r-- | openbsc/src/meas_rep.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/openbsc/src/meas_rep.c b/openbsc/src/meas_rep.c new file mode 100644 index 000000000..4b9cc1a0c --- /dev/null +++ b/openbsc/src/meas_rep.c @@ -0,0 +1,114 @@ +/* Measurement Report Processing */ + +/* (C) 2009 by Harald Welte <laforge@gnumonks.org> + * + * 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 <sys/types.h> + +#include <openbsc/gsm_data.h> +#include <openbsc/meas_rep.h> + +static int get_field(const struct gsm_meas_rep *rep, + enum meas_rep_field field) +{ + switch (field) { + case MEAS_REP_DL_RXLEV_FULL: + return rep->dl.full.rx_lev; + case MEAS_REP_DL_RXLEV_SUB: + return rep->dl.sub.rx_lev; + case MEAS_REP_DL_RXQUAL_FULL: + return rep->dl.full.rx_qual; + case MEAS_REP_DL_RXQUAL_SUB: + return rep->dl.sub.rx_qual; + case MEAS_REP_UL_RXLEV_FULL: + return rep->ul.full.rx_lev; + case MEAS_REP_UL_RXLEV_SUB: + return rep->ul.sub.rx_lev; + case MEAS_REP_UL_RXQUAL_FULL: + return rep->ul.full.rx_qual; + case MEAS_REP_UL_RXQUAL_SUB: + return rep->ul.sub.rx_qual; + } + + return 0; +} + + +unsigned int calc_initial_idx(unsigned int array_size, + unsigned int meas_rep_idx, + unsigned int num_values) +{ + int offs, idx; + + /* from which element do we need to start if we're interested + * in an average of 'num' elements */ + offs = meas_rep_idx - num_values; + + if (offs < 0) + idx = array_size + offs; + else + idx = offs; + + return idx; +} + +/* obtain an average over the last 'num' fields in the meas reps */ +int get_meas_rep_avg(const struct gsm_lchan *lchan, + enum meas_rep_field field, unsigned int num) +{ + unsigned int i, idx; + int avg = 0; + + idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep), + lchan->meas_rep_idx, num); + + for (i = 0; i < num; i++) { + int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep); + + avg += get_field(&lchan->meas_rep[j], field); + } + + return avg / num; +} + +/* Check if N out of M last values for FIELD are >= bd */ +int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan, + enum meas_rep_field field, + unsigned int n, unsigned int m, int be) +{ + unsigned int i, idx; + int count = 0; + + idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep), + lchan->meas_rep_idx, m); + + for (i = 0; i < m; i++) { + int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep); + int val = get_field(&lchan->meas_rep[j], field); + + if (val >= be) + count++; + + if (count >= n) + return 1; + } + + return 0; +} |