handover2 congestion check: do not complain when no TCH/x lchans are in operation
Change-Id: I688990f16efd9b5184da28def650ae706598064f
This commit is contained in:
parent
e1b6a16924
commit
5b704121fa
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue