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
This commit is contained in:
parent
434d3ae2ed
commit
3025e69814
|
@ -40,6 +40,7 @@
|
||||||
#include <osmocom/bsc/neighbor_ident.h>
|
#include <osmocom/bsc/neighbor_ident.h>
|
||||||
#include <osmocom/bsc/timeslot_fsm.h>
|
#include <osmocom/bsc/timeslot_fsm.h>
|
||||||
#include <osmocom/bsc/bts.h>
|
#include <osmocom/bsc/bts.h>
|
||||||
|
#include <osmocom/bsc/lchan_select.h>
|
||||||
|
|
||||||
#define LOGPHOBTS(bts, level, fmt, args...) \
|
#define LOGPHOBTS(bts, level, fmt, args...) \
|
||||||
LOGP(DHODEC, level, "(BTS %u) " fmt, bts->nr, ## args)
|
LOGP(DHODEC, level, "(BTS %u) " fmt, bts->nr, ## args)
|
||||||
|
@ -118,6 +119,9 @@ struct ho_candidate {
|
||||||
int min_free_tchf;
|
int min_free_tchf;
|
||||||
int free_tchh;
|
int free_tchh;
|
||||||
int min_free_tchh;
|
int min_free_tchh;
|
||||||
|
/* Effects of occupying a dynamic timeslot: */
|
||||||
|
int next_tchf_reduces_tchh;
|
||||||
|
int next_tchh_reduces_tchf;
|
||||||
} target;
|
} target;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -637,11 +641,15 @@ static void check_requirements(struct ho_candidate *c)
|
||||||
/* the minimum free timeslots that are defined for this cell must
|
/* the minimum free timeslots that are defined for this cell must
|
||||||
* be maintained _after_ handover/assignment */
|
* be maintained _after_ handover/assignment */
|
||||||
if (requirement & REQUIREMENT_A_TCHF) {
|
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;
|
requirement |= REQUIREMENT_B_TCHF;
|
||||||
}
|
}
|
||||||
if (requirement & REQUIREMENT_A_TCHH) {
|
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;
|
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)
|
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);
|
c->current.free_tch = bts_count_free_ts(c->current.bts, c->current.lchan->ts->pchan_is);
|
||||||
switch (c->current.lchan->ts->pchan_is) {
|
switch (c->current.lchan->ts->pchan_is) {
|
||||||
case GSM_PCHAN_TCH_F:
|
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.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.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);
|
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 */
|
/* add candidate for re-assignment within the current cell */
|
||||||
|
|
|
@ -20,12 +20,8 @@ meas-rep lchan * * * * rxlev 40 rxqual 0 ta 0 neighbors 30
|
||||||
expect-no-chan
|
expect-no-chan
|
||||||
|
|
||||||
meas-rep lchan 0 0 1 0 rxlev 20 rxqual 0 ta 0 neighbors 40
|
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
|
# no 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-no-chan
|
||||||
|
|
||||||
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 *
|
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
|
@ -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
|
meas-rep lchan * * * * rxlev 40 rxqual 0 ta 0 neighbors 30
|
||||||
|
|
||||||
congestion-check
|
congestion-check
|
||||||
# FAIL: really weird: handover one TCH/H to the same cell to TCH/F, taking up another dyn TS.
|
expect-ho from lchan 1 0 4 1 to lchan 0 0 4 0
|
||||||
# TCH/H congestion hence actually gets worse.
|
expect-ts-use trx 0 0 states * - - - TCH/H- pdch pdch *
|
||||||
expect-ho from lchan 1 0 4 1 to lchan 1 0 6 0
|
expect-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/H- TCH/F pdch *
|
||||||
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 *
|
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@ -65,12 +59,9 @@ meas-rep lchan 1 * * * rxlev 40 rxqual 0 ta 0 neighbors 30
|
||||||
expect-no-chan
|
expect-no-chan
|
||||||
|
|
||||||
meas-rep lchan 0 * * * rxlev 30 rxqual 0 ta 0 neighbors 40
|
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!?
|
# no HO because the target is congested on TCH/H. Moving to TCH/F would also
|
||||||
expect-ho from lchan 0 0 4 0 to lchan 1 0 4 0
|
# reduce TCH/H lchans because it would convert another dyn TS.
|
||||||
|
expect-no-chan
|
||||||
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 *
|
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
|
@ -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 *
|
set-ts-use trx 1 0 states * TCH/F TCH/F TCH/F TCH/F TCH/F TCH/F *
|
||||||
|
|
||||||
congestion-check
|
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
|
expect-no-chan
|
||||||
# Stable situation now only because TCH/F has min-free-slots set to 0
|
|
||||||
|
|
Loading…
Reference in New Issue