diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2021-01-15 09:27:30 +0100 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2021-01-19 11:49:07 +0100 |
commit | 3025e69814eeb38e9e17450c58a801c02585b077 (patch) | |
tree | c144a3c6f6075a54633d630793bf317ec28db278 | |
parent | 434d3ae2ed5f1ad7c101aa100287658bed99aae6 (diff) |
hodec2: fix congestion resolution on dyn TS
For handover algorithm 2, properly figure out what effects the target
cell will see for the *other* TCH kind when a handover would occupy a
dynamic timeslot.
Before this, only TCH/F or TCH/H would be regarded at a time. This
introduces detection of whether a dynamic timeslot would be occupied by
a handover, and how losing one unused dynamic timeslot affects the
congestion situation for the TCH kind that is not targeted by the
handover.
In other words, if a handover to TCH/F causes congestion in TCH/H
because of a dynamic timeslot becoming occupied, the handover will not
be performed. Before this, oscillation situations could occur.
A subsequent patch will do the same for congestion balancing.
Related: SYS#5297
Change-Id: I1536b60f03cb0aeb6ba14a72b518aec82fa572fe
-rw-r--r-- | src/osmo-bsc/handover_decision_2.c | 30 | ||||
-rw-r--r-- | tests/handover/test_dyn_ts_congestion_tch_f_vs_tch_h.ho_vty | 28 |
2 files changed, 38 insertions, 20 deletions
diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c index 0362c9b95..92374e909 100644 --- a/src/osmo-bsc/handover_decision_2.c +++ b/src/osmo-bsc/handover_decision_2.c @@ -40,6 +40,7 @@ #include <osmocom/bsc/neighbor_ident.h> #include <osmocom/bsc/timeslot_fsm.h> #include <osmocom/bsc/bts.h> +#include <osmocom/bsc/lchan_select.h> #define LOGPHOBTS(bts, level, fmt, args...) \ LOGP(DHODEC, level, "(BTS %u) " fmt, bts->nr, ## args) @@ -118,6 +119,9 @@ struct ho_candidate { int min_free_tchf; int free_tchh; int min_free_tchh; + /* Effects of occupying a dynamic timeslot: */ + int next_tchf_reduces_tchh; + int next_tchh_reduces_tchf; } target; }; @@ -637,11 +641,15 @@ static void check_requirements(struct ho_candidate *c) /* the minimum free timeslots that are defined for this cell must * be maintained _after_ handover/assignment */ if (requirement & REQUIREMENT_A_TCHF) { - if (c->target.free_tchf - 1 >= c->target.min_free_tchf) + if ((c->target.free_tchf - 1) >= c->target.min_free_tchf + && (!c->target.next_tchf_reduces_tchh + || (c->target.free_tchh - c->target.next_tchf_reduces_tchh) >= c->target.min_free_tchh)) requirement |= REQUIREMENT_B_TCHF; } if (requirement & REQUIREMENT_A_TCHH) { - if (c->target.free_tchh - 1 >= c->target.min_free_tchh) + if ((c->target.free_tchh - 1) >= c->target.min_free_tchh + && (!c->target.next_tchh_reduces_tchf + || (c->target.free_tchf - c->target.next_tchh_reduces_tchf) >= c->target.min_free_tchf)) requirement |= REQUIREMENT_B_TCHH; } @@ -894,6 +902,8 @@ static inline void debug_candidate(struct ho_candidate *candidate) static void candidate_set_free_tch(struct ho_candidate *c) { + struct gsm_lchan *next_lchan; + c->current.free_tch = bts_count_free_ts(c->current.bts, c->current.lchan->ts->pchan_is); switch (c->current.lchan->ts->pchan_is) { case GSM_PCHAN_TCH_F: @@ -909,6 +919,22 @@ static void candidate_set_free_tch(struct ho_candidate *c) c->target.min_free_tchf = ho_get_hodec2_tchf_min_slots(c->target.bts->ho); c->target.free_tchh = bts_count_free_ts(c->target.bts, GSM_PCHAN_TCH_H); c->target.min_free_tchh = ho_get_hodec2_tchh_min_slots(c->target.bts->ho); + + /* Would the next TCH/F lchan occupy a dynamic timeslot that currently counts for free TCH/H timeslots? */ + next_lchan = lchan_avail_by_type(c->target.bts, GSM_LCHAN_TCH_F); + if (next_lchan && next_lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH) + c->target.next_tchf_reduces_tchh = 2; + else + c->target.next_tchf_reduces_tchh = 0; + + /* Would the next TCH/H lchan occupy a dynamic timeslot that currently counts for free TCH/F timeslots? + * Note that a dyn TS already in TCH/H mode (half occupied) would not reduce free TCH/F. */ + next_lchan = lchan_avail_by_type(c->target.bts, GSM_LCHAN_TCH_H); + if (next_lchan && next_lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH + && next_lchan->ts->pchan_is != GSM_PCHAN_TCH_H) + c->target.next_tchh_reduces_tchf = 1; + else + c->target.next_tchh_reduces_tchf = 0; } /* add candidate for re-assignment within the current cell */ diff --git a/tests/handover/test_dyn_ts_congestion_tch_f_vs_tch_h.ho_vty b/tests/handover/test_dyn_ts_congestion_tch_f_vs_tch_h.ho_vty index bc2c8840e..c5890a513 100644 --- a/tests/handover/test_dyn_ts_congestion_tch_f_vs_tch_h.ho_vty +++ b/tests/handover/test_dyn_ts_congestion_tch_f_vs_tch_h.ho_vty @@ -20,12 +20,8 @@ meas-rep lchan * * * * rxlev 40 rxqual 0 ta 0 neighbors 30 expect-no-chan meas-rep lchan 0 0 1 0 rxlev 20 rxqual 0 ta 0 neighbors 40 -# FAIL: should not handover because that results in congestion on TCH/H in bts 1 -expect-ho from lchan 0 0 1 0 to lchan 1 0 5 0 - -expect-ts-use trx 0 0 states * - - - pdch pdch pdch * -expect-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/HH TCH/F pdch * - +# no handover because that results in congestion on TCH/H in bts 1 +expect-no-chan ### @@ -34,11 +30,9 @@ set-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/HH TCH/F pdch * meas-rep lchan * * * * rxlev 40 rxqual 0 ta 0 neighbors 30 congestion-check -# FAIL: really weird: handover one TCH/H to the same cell to TCH/F, taking up another dyn TS. -# TCH/H congestion hence actually gets worse. -expect-ho from lchan 1 0 4 1 to lchan 1 0 6 0 -expect-ts-use trx 0 0 states * - - - pdch pdch pdch * -expect-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/H- TCH/F TCH/F * +expect-ho from lchan 1 0 4 1 to lchan 0 0 4 0 +expect-ts-use trx 0 0 states * - - - TCH/H- pdch pdch * +expect-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/H- TCH/F pdch * ### @@ -65,12 +59,9 @@ meas-rep lchan 1 * * * rxlev 40 rxqual 0 ta 0 neighbors 30 expect-no-chan meas-rep lchan 0 * * * rxlev 30 rxqual 0 ta 0 neighbors 40 -# FAIL: back to bts 1 because of rxlev, plus moving TCH/H to TCH/F!? -expect-ho from lchan 0 0 4 0 to lchan 1 0 4 0 - -expect-ts-use trx 0 0 states * - - - pdch pdch pdch * -expect-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/F TCH/F TCH/F * - +# no HO because the target is congested on TCH/H. Moving to TCH/F would also +# reduce TCH/H lchans because it would convert another dyn TS. +expect-no-chan ### @@ -78,5 +69,6 @@ set-ts-use trx 0 0 states * - - - pdch pdch pdch * set-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/F TCH/F TCH/F * congestion-check +# FAIL: TCH/F occupy dynamic timeslots -- should hand over to bts 0 to free a +# dyn TS and reduce TCH/H congestion. expect-no-chan -# Stable situation now only because TCH/F has min-free-slots set to 0 |