From 5b704121fa730c7f3cc3e7cffc9552dfab72ce47 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 22 Aug 2019 20:26:40 +0200 Subject: handover2 congestion check: do not complain when no TCH/x lchans are in operation Change-Id: I688990f16efd9b5184da28def650ae706598064f --- include/osmocom/bsc/gsm_data.h | 3 ++- src/osmo-bsc/gsm_data.c | 54 +++++++++++++++++++++++++++----------- src/osmo-bsc/handover_decision_2.c | 36 ++++++++++++++----------- 3 files changed, 61 insertions(+), 32 deletions(-) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index d82d1bac8..4d0b940cf 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1701,6 +1701,7 @@ enum gsm_phys_chan_config gsm_pchan_by_lchan_type(enum gsm_chan_t type); void gsm_bts_all_ts_dispatch(struct gsm_bts *bts, uint32_t ts_ev, void *data); void gsm_trx_all_ts_dispatch(struct gsm_bts_trx *trx, uint32_t ts_ev, void *data); -int bts_count_free_ts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan); +void bts_count_free_ts(int *operative_p, int *free_p, + struct gsm_bts *bts, enum gsm_phys_chan_config pchan); #endif /* _GSM_DATA_H */ diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index ea338173e..0bc3011dc 100644 --- a/src/osmo-bsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -1605,15 +1605,17 @@ bool ts_is_capable_of_lchant(struct gsm_bts_trx_ts *ts, enum gsm_chan_t type) } } -static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) +static void trx_count_free_ts(int *operative_p, int *free_p, + struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) { struct gsm_bts_trx_ts *ts; struct gsm_lchan *lchan; int j; - int count = 0; + int operative_lchans = 0; + int free_lchans = 0; if (!trx_is_usable(trx)) - return 0; + goto return_values; for (j = 0; j < ARRAY_SIZE(trx->ts); j++) { ts = &trx->ts[j]; @@ -1624,15 +1626,20 @@ static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config /* Dynamic timeslots in PDCH mode will become TCH if needed. */ switch (ts->pchan_on_init) { case GSM_PCHAN_TCH_F_PDCH: - if (pchan == GSM_PCHAN_TCH_F) - count++; + if (pchan == GSM_PCHAN_TCH_F) { + free_lchans++; + operative_lchans++; + } continue; case GSM_PCHAN_TCH_F_TCH_H_PDCH: - if (pchan == GSM_PCHAN_TCH_F) - count++; - else if (pchan == GSM_PCHAN_TCH_H) - count += 2; + if (pchan == GSM_PCHAN_TCH_F) { + free_lchans++; + operative_lchans++; + } else if (pchan == GSM_PCHAN_TCH_H) { + free_lchans += 2; + operative_lchans += 2; + } continue; default: @@ -1645,24 +1652,39 @@ static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config continue; ts_for_each_lchan(lchan, ts) { + operative_lchans++; if (lchan_state_is(lchan, LCHAN_ST_UNUSED)) - count++; + free_lchans++; } } - return count; +return_values: + if (operative_p) + *operative_p = operative_lchans; + if (free_p) + *free_p = free_lchans; } /* Count number of free TS of given pchan type */ -int bts_count_free_ts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan) +void bts_count_free_ts(int *operative_p, int *free_p, + struct gsm_bts *bts, enum gsm_phys_chan_config pchan) { struct gsm_bts_trx *trx; - int count = 0; + int operative_lchans = 0; + int free_lchans = 0; - llist_for_each_entry(trx, &bts->trx_list, list) - count += trx_count_free_ts(trx, pchan); + llist_for_each_entry(trx, &bts->trx_list, list) { + int o; + int f; + trx_count_free_ts(&o, &f, trx, pchan); + operative_lchans += o; + free_lchans += f; + } - return count; + if (operative_p) + *operative_p = operative_lchans; + if (free_p) + *free_p = free_lchans; } bool ts_is_usable(const struct gsm_bts_trx_ts *ts) diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c index 48570adc8..24ae94062 100644 --- a/src/osmo-bsc/handover_decision_2.c +++ b/src/osmo-bsc/handover_decision_2.c @@ -604,9 +604,9 @@ static uint8_t check_requirements(struct gsm_lchan *lchan, struct gsm_bts *bts, /* the nr of free timeslots of the target cell must be >= the * free slots of the current cell _after_ handover/assignment */ - count = bts_count_free_ts(current_bts, - (lchan->type == GSM_LCHAN_TCH_H) ? - GSM_PCHAN_TCH_H : GSM_PCHAN_TCH_F); + bts_count_free_ts(NULL, &count, current_bts, + (lchan->type == GSM_LCHAN_TCH_H) ? + GSM_PCHAN_TCH_H : GSM_PCHAN_TCH_F); if (requirement & REQUIREMENT_A_TCHF) { if (tchf_count - 1 >= count + 1) requirement |= REQUIREMENT_C_TCHF; @@ -849,8 +849,8 @@ static void collect_assignment_candidate(struct gsm_lchan *lchan, struct ho_cand int tchf_count, tchh_count; struct ho_candidate c; - tchf_count = bts_count_free_ts(bts, GSM_PCHAN_TCH_F); - tchh_count = bts_count_free_ts(bts, GSM_PCHAN_TCH_H); + bts_count_free_ts(NULL, &tchf_count, bts, GSM_PCHAN_TCH_F); + bts_count_free_ts(NULL, &tchh_count, bts, GSM_PCHAN_TCH_H); c = (struct ho_candidate){ .lchan = lchan, @@ -956,8 +956,8 @@ static void collect_handover_candidate(struct gsm_lchan *lchan, struct neigh_mea } if (neighbor_bts) { - tchf_count = bts_count_free_ts(neighbor_bts, GSM_PCHAN_TCH_F); - tchh_count = bts_count_free_ts(neighbor_bts, GSM_PCHAN_TCH_H); + bts_count_free_ts(NULL, &tchf_count, neighbor_bts, GSM_PCHAN_TCH_F); + bts_count_free_ts(NULL, &tchh_count, neighbor_bts, GSM_PCHAN_TCH_H); c.requirements = check_requirements(lchan, neighbor_bts, tchf_count, tchh_count); } else @@ -1821,7 +1821,9 @@ exit: static void bts_congestion_check(struct gsm_bts *bts) { int min_free_tchf, min_free_tchh; - int tchf_count, tchh_count; + int tchf_free, tchh_free; + int tchf_operative, tchh_operative; + int tchf_congestion, tchh_congestion; int algo; global_ho_reason = HO_REASON_CONGESTION; @@ -1853,19 +1855,23 @@ static void bts_congestion_check(struct gsm_bts *bts) return; } - tchf_count = bts_count_free_ts(bts, GSM_PCHAN_TCH_F); - tchh_count = bts_count_free_ts(bts, GSM_PCHAN_TCH_H); - LOGPHOBTS(bts, LOGL_INFO, "Congestion check: (free/want-free) TCH/F=%d/%d TCH/H=%d/%d\n", - tchf_count, min_free_tchf, tchh_count, min_free_tchh); + bts_count_free_ts(&tchf_operative, &tchf_free, bts, GSM_PCHAN_TCH_F); + bts_count_free_ts(&tchh_operative, &tchh_free, bts, GSM_PCHAN_TCH_H); + LOGPHOBTS(bts, LOGL_INFO, "Congestion check: (in-operation/free/want-free) TCH/F=%d/%d/%d TCH/H=%d/%d/%d\n", + tchf_operative, tchf_free, min_free_tchf, tchh_operative, tchh_free, min_free_tchh); /* only check BTS if congested */ - if (tchf_count >= min_free_tchf && tchh_count >= min_free_tchh) { + tchf_congestion = OSMO_MAX(0, OSMO_MIN(tchf_operative, min_free_tchf - tchf_free)); + tchh_congestion = OSMO_MAX(0, OSMO_MIN(tchh_operative, min_free_tchh - tchh_free)); + + if (!(tchf_congestion || tchh_congestion)) { LOGPHOBTS(bts, LOGL_DEBUG, "Not congested\n"); return; } - LOGPHOBTS(bts, LOGL_DEBUG, "Attempting to resolve congestion...\n"); - bts_resolve_congestion(bts, min_free_tchf - tchf_count, min_free_tchh - tchh_count); + LOGPHOBTS(bts, LOGL_DEBUG, "Attempting to resolve congestion, trying to free %d TCH/F, %d TCH/H...\n", + tchf_congestion, tchh_congestion); + bts_resolve_congestion(bts, tchf_congestion, tchh_congestion); } void hodec2_congestion_check(struct gsm_network *net) -- cgit v1.2.3