From 38fe2a67e1a376e4370ddfed2f75687075cc9e6b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 21 Dec 2009 09:26:17 +0100 Subject: 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. --- openbsc/include/openbsc/meas_rep.h | 27 +++++++++ openbsc/src/Makefile.am | 2 +- openbsc/src/meas_rep.c | 114 +++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 openbsc/src/meas_rep.c (limited to 'openbsc') diff --git a/openbsc/include/openbsc/meas_rep.h b/openbsc/include/openbsc/meas_rep.h index c36352e2a..fd5fced43 100644 --- a/openbsc/include/openbsc/meas_rep.h +++ b/openbsc/include/openbsc/meas_rep.h @@ -1,11 +1,14 @@ #ifndef _MEAS_REP_H #define _MEAS_REP_H +#define MRC_F_PROCESSED 0x0001 + /* extracted from a L3 measurement report IE */ struct gsm_meas_rep_cell { u_int8_t rxlev; u_int8_t bsic; u_int16_t arfcn; + unsigned int flags; }; /* RX Level and RX Quality */ @@ -54,4 +57,28 @@ struct gsm_meas_rep { struct gsm_meas_rep_cell cell[6]; }; +enum meas_rep_field { + MEAS_REP_DL_RXLEV_FULL, + MEAS_REP_DL_RXLEV_SUB, + MEAS_REP_DL_RXQUAL_FULL, + MEAS_REP_DL_RXQUAL_SUB, + MEAS_REP_UL_RXLEV_FULL, + MEAS_REP_UL_RXLEV_SUB, + MEAS_REP_UL_RXQUAL_FULL, + MEAS_REP_UL_RXQUAL_SUB, +}; + +/* 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); + +/* 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 calc_initial_idx(unsigned int array_size, + unsigned int meas_rep_idx, + unsigned int num_values); + #endif /* _MEAS_REP_H */ diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index 5692ac4e4..f36a701bc 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -12,7 +12,7 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \ trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \ input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \ talloc_ctx.c system_information.c bitvec.c rest_octets.c \ - handover_decision.c + handover_decision.c meas_rep.c libmsc_a_SOURCES = gsm_subscriber.c db.c telnet_interface.c \ mncc.c rtp_proxy.c gsm_04_08.c gsm_04_11.c transaction.c \ 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 + * + * 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 + +#include +#include + +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; +} -- cgit v1.2.3