aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2021-07-05 12:59:50 +0200
committerlaforge <laforge@osmocom.org>2021-07-09 11:51:40 +0000
commit7225fe49026bcc8e312ef6e5a2f40f4e385529cf (patch)
tree1eba151542aa0b88b031834d0e2cc56ea6b20988
parent25ea643e19c2d95bec07e3ac783c2864afbf350c (diff)
hodec2: [1/2] implement automatic choice between FULL and SUBSET measurements
Cosmetic preparation for enabling automatic choice between FULL and SUBSET measurements depending on DTX in handover decision 2. Change the internal API to pass separate enums for the choices {RXLEV, RXQUAL}, {UL, DL} and {FULL, SUB}. Change-Id: I283e03126a6bc1f5f1b35f9801e841053edd2947
-rw-r--r--include/osmocom/bsc/meas_rep.h24
-rw-r--r--src/osmo-bsc/handover_decision.c16
-rw-r--r--src/osmo-bsc/handover_decision_2.c10
-rw-r--r--src/osmo-bsc/meas_rep.c58
4 files changed, 82 insertions, 26 deletions
diff --git a/include/osmocom/bsc/meas_rep.h b/include/osmocom/bsc/meas_rep.h
index 54e0519e8..5cfeb98fb 100644
--- a/include/osmocom/bsc/meas_rep.h
+++ b/include/osmocom/bsc/meas_rep.h
@@ -51,14 +51,32 @@ struct gsm_meas_rep {
struct gsm_meas_rep_cell cell[6];
};
+enum tdma_meas_field {
+ TDMA_MEAS_FIELD_RXLEV = 0,
+ TDMA_MEAS_FIELD_RXQUAL = 1,
+};
+
+enum tdma_meas_dir {
+ TDMA_MEAS_DIR_UL = 0,
+ TDMA_MEAS_DIR_DL = 1,
+};
+
+/* (function choose_meas_rep_field() depends on FULL and SUB being 0 and 1, but doesn't care about AUTO's value) */
+enum tdma_meas_set {
+ TDMA_MEAS_SET_FULL = 0,
+ TDMA_MEAS_SET_SUB = 1,
+ TDMA_MEAS_SET_AUTO,
+};
+
/* 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);
+ enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set,
+ 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);
+ enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set,
+ unsigned int n, unsigned int m, int be);
unsigned int calc_initial_idx(unsigned int array_size,
unsigned int meas_rep_idx,
diff --git a/src/osmo-bsc/handover_decision.c b/src/osmo-bsc/handover_decision.c
index 1eeb277ff..220fa1c7e 100644
--- a/src/osmo-bsc/handover_decision.c
+++ b/src/osmo-bsc/handover_decision.c
@@ -214,7 +214,7 @@ static void attempt_handover(struct gsm_meas_rep *mr)
static void on_measurement_report(struct gsm_meas_rep *mr)
{
struct gsm_bts *bts = mr->lchan->ts->trx->bts;
- enum meas_rep_field dlev, dqual;
+ enum tdma_meas_set meas_set;
int av_rxlev;
unsigned int pwr_interval;
@@ -231,24 +231,18 @@ static void on_measurement_report(struct gsm_meas_rep *mr)
return;
}
- if (mr->flags & MEAS_REP_F_DL_DTX) {
- dlev = MEAS_REP_DL_RXLEV_SUB;
- dqual = MEAS_REP_DL_RXQUAL_SUB;
- } else {
- dlev = MEAS_REP_DL_RXLEV_FULL;
- dqual = MEAS_REP_DL_RXQUAL_FULL;
- }
+ meas_set = (mr->flags & MEAS_REP_F_DL_DTX) ? TDMA_MEAS_SET_SUB : TDMA_MEAS_SET_FULL;
/* parse actual neighbor cell info */
if (mr->num_cell > 0 && mr->num_cell < 7)
process_meas_neigh(mr);
- av_rxlev = get_meas_rep_avg(mr->lchan, dlev,
+ av_rxlev = get_meas_rep_avg(mr->lchan, TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, meas_set,
ho_get_hodec1_rxlev_avg_win(bts->ho));
/* Interference HO */
if (rxlev2dbm(av_rxlev) > -85 &&
- meas_rep_n_out_of_m_be(mr->lchan, dqual, 3, 4, 5)) {
+ meas_rep_n_out_of_m_be(mr->lchan, TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, meas_set, 3, 4, 5)) {
LOGPC(DHO, LOGL_INFO, "HO cause: Interference HO av_rxlev=%d dBm\n",
rxlev2dbm(av_rxlev));
attempt_handover(mr);
@@ -256,7 +250,7 @@ static void on_measurement_report(struct gsm_meas_rep *mr)
}
/* Bad Quality */
- if (meas_rep_n_out_of_m_be(mr->lchan, dqual, 3, 4, 5)) {
+ if (meas_rep_n_out_of_m_be(mr->lchan, TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, meas_set, 3, 4, 5)) {
LOGPC(DHO, LOGL_INFO, "HO cause: Bad Quality av_rxlev=%d dBm\n", rxlev2dbm(av_rxlev));
attempt_handover(mr);
return;
diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c
index d77887618..67208fe90 100644
--- a/src/osmo-bsc/handover_decision_2.c
+++ b/src/osmo-bsc/handover_decision_2.c
@@ -244,18 +244,16 @@ static struct gsm_meas_rep_cell *cell_in_rep(struct gsm_meas_rep *mr, uint16_t a
static int current_rxlev(struct gsm_lchan *lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
- return get_meas_rep_avg(lchan,
- ho_get_hodec2_full_tdma(bts->ho) ?
- MEAS_REP_DL_RXLEV_FULL : MEAS_REP_DL_RXLEV_SUB,
+ return get_meas_rep_avg(lchan, TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL,
+ ho_get_hodec2_full_tdma(bts->ho) ? TDMA_MEAS_SET_FULL : TDMA_MEAS_SET_SUB,
ho_get_hodec2_rxlev_avg_win(bts->ho));
}
static int current_rxqual(struct gsm_lchan *lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
- return get_meas_rep_avg(lchan,
- ho_get_hodec2_full_tdma(bts->ho) ?
- MEAS_REP_DL_RXQUAL_FULL : MEAS_REP_DL_RXQUAL_SUB,
+ return get_meas_rep_avg(lchan, TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL,
+ ho_get_hodec2_full_tdma(bts->ho) ? TDMA_MEAS_SET_FULL : TDMA_MEAS_SET_SUB,
ho_get_hodec2_rxqual_avg_win(bts->ho));
}
diff --git a/src/osmo-bsc/meas_rep.c b/src/osmo-bsc/meas_rep.c
index 32c689db9..97c30ac1a 100644
--- a/src/osmo-bsc/meas_rep.c
+++ b/src/osmo-bsc/meas_rep.c
@@ -80,9 +80,47 @@ unsigned int calc_initial_idx(unsigned int array_size,
return idx;
}
-/* obtain an average over the last 'num' fields in the meas reps */
+static inline enum meas_rep_field choose_meas_rep_field(enum tdma_meas_field field, enum tdma_meas_dir dir,
+ enum tdma_meas_set set)
+{
+ osmo_static_assert(TDMA_MEAS_FIELD_RXLEV >= 0 && TDMA_MEAS_FIELD_RXLEV <= 1
+ && TDMA_MEAS_FIELD_RXQUAL >= 0 && TDMA_MEAS_FIELD_RXQUAL <= 1
+ && TDMA_MEAS_DIR_UL >= 0 && TDMA_MEAS_DIR_UL <= 1
+ && TDMA_MEAS_DIR_DL >= 0 && TDMA_MEAS_DIR_DL <= 1
+ && TDMA_MEAS_SET_FULL >= 0 && TDMA_MEAS_SET_FULL <= 1
+ && TDMA_MEAS_SET_SUB >= 0 && TDMA_MEAS_SET_SUB <= 1,
+ choose_meas_rep_field__mux_macro_input_ranges);
+#define MUX(FIELD, DIR, SET) ((FIELD) + ((DIR) << 1) + ((SET) << 2))
+
+ switch (MUX(field, dir, set)) {
+ case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_FULL):
+ return MEAS_REP_UL_RXLEV_FULL;
+ case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_SUB):
+ return MEAS_REP_UL_RXLEV_SUB;
+ case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_FULL):
+ return MEAS_REP_DL_RXLEV_FULL;
+ case MUX(TDMA_MEAS_FIELD_RXLEV, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_SUB):
+ return MEAS_REP_DL_RXLEV_SUB;
+ case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_FULL):
+ return MEAS_REP_UL_RXQUAL_FULL;
+ case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_UL, TDMA_MEAS_SET_SUB):
+ return MEAS_REP_UL_RXQUAL_SUB;
+ case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_FULL):
+ return MEAS_REP_DL_RXQUAL_FULL;
+ case MUX(TDMA_MEAS_FIELD_RXQUAL, TDMA_MEAS_DIR_DL, TDMA_MEAS_SET_SUB):
+ return MEAS_REP_DL_RXQUAL_SUB;
+ default:
+ OSMO_ASSERT(false);
+ }
+
+#undef MUX
+}
+
+/* obtain an average over the last 'num' fields in the meas reps. For 'field', pass either DL_RXLEV or DL_RXQUAL, and
+ * by tdma_meas_set, choose between full, subset or automatic choice of set. */
int get_meas_rep_avg(const struct gsm_lchan *lchan,
- enum meas_rep_field field, unsigned int num)
+ enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set,
+ unsigned int num)
{
unsigned int i, idx;
int avg = 0, valid_num = 0;
@@ -98,7 +136,11 @@ int get_meas_rep_avg(const struct gsm_lchan *lchan,
for (i = 0; i < num; i++) {
int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep);
- int val = get_field(&lchan->meas_rep[j], field);
+ enum meas_rep_field use_field;
+ int val;
+
+ use_field = choose_meas_rep_field(field, dir, set);
+ val = get_field(&lchan->meas_rep[j], use_field);
if (val >= 0) {
avg += val;
@@ -114,8 +156,8 @@ int get_meas_rep_avg(const struct gsm_lchan *lchan,
/* 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)
+ enum tdma_meas_field field, enum tdma_meas_dir dir, enum tdma_meas_set set,
+ unsigned int n, unsigned int m, int be)
{
unsigned int i, idx;
int count = 0;
@@ -125,7 +167,11 @@ int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
for (i = 0; i < m; i++) {
int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep);
- int val = get_field(&lchan->meas_rep[j], field);
+ enum meas_rep_field use_field;
+ int val;
+
+ use_field = choose_meas_rep_field(field, dir, set);
+ val = get_field(&lchan->meas_rep[j], use_field);
if (val >= be) /* implies that val < 0 will not count */
count++;