gsm48_parse_meas_rep: fix parsing multi-band list
When looking up "BCCH-FREQ-NCELL i" from the measurement report, don't treat the BCCH channel list as one list sorted by ascending ARFCN. Instead, treat it as two sub lists, one for the same band, and one for channels in different bands, as described in 3GPP TS 04.08 § 10.5.2.20. This fixes getting the wrong ARFCN from measurement reports in multi-band BSS, which leads to failing handovers. Fixes: OS#5717 Related: osmo-ttcn3-hacks I4fe6bb9e4b5a69ea6204585ebdf1f157a68a8286 Change-Id: Ic5e4f0531e08685460948b102367825588d839ba
This commit is contained in:
parent
63f4171f50
commit
5bdc3eca68
|
@ -7,6 +7,7 @@
|
|||
|
||||
struct gsm_bts;
|
||||
|
||||
int band_compatible(const struct gsm_bts *bts, int arfcn);
|
||||
int generate_cell_chan_alloc(struct gsm_bts *bts);
|
||||
int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts);
|
||||
int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
|
||||
|
|
|
@ -766,6 +766,56 @@ int gsm48_rx_rr_modif_ack(struct msgb *msg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Get the ARFCN from the BCCH channel list by the index "BCCH-FREQ-NCELL i"
|
||||
* (idx) as described in 3GPP TS 144.018 § 10.5.2.20. The BCCH channel list is
|
||||
* split into two sub lists, each ascendingly ordered by ARFCN > 0:
|
||||
* 1) SI* and SI*bis entries
|
||||
* 2) SI*ter entries (if available)
|
||||
* ARFCN 0 is at the end of each sub list.
|
||||
* Both sub lists are stored in one bitvec (nbv), iterate twice through it. */
|
||||
static int neigh_list_get_arfcn(struct gsm_bts *bts, const struct bitvec *nbv, unsigned int idx)
|
||||
{
|
||||
unsigned int arfcn, i = 0;
|
||||
|
||||
/* First sub list, ARFCN > 0 */
|
||||
for (arfcn = 1; arfcn < nbv->data_len * 8; arfcn++) {
|
||||
if (bitvec_get_bit_pos(nbv, arfcn) == ZERO)
|
||||
continue;
|
||||
/* Skip SI*ter */
|
||||
if (!band_compatible(bts, arfcn))
|
||||
continue;
|
||||
if (i == idx)
|
||||
return arfcn;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* First sub list, ARFCN == 0 (last position) */
|
||||
if (bitvec_get_bit_pos(nbv, 0) == ONE && band_compatible(bts, 0)) {
|
||||
if (i == idx)
|
||||
return 0;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Second sub list, ARFCN > 0 */
|
||||
for (arfcn = 1; arfcn < nbv->data_len * 8; arfcn++) {
|
||||
if (bitvec_get_bit_pos(nbv, arfcn) == ZERO)
|
||||
continue;
|
||||
/* Require SI*ter */
|
||||
if (band_compatible(bts, arfcn))
|
||||
continue;
|
||||
if (i == idx)
|
||||
return arfcn;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Second sub list, ARFCN == 0 (last position) */
|
||||
if (bitvec_get_bit_pos(nbv, 0) == ONE && !band_compatible(bts, 0) && i == idx)
|
||||
return 0;
|
||||
|
||||
LOGP(DRR, LOGL_ERROR, "Invalid BCCH channel list index %d in measurement report\n", idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
|
@ -800,7 +850,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
|
|||
mrc = &rep->cell[0];
|
||||
mrc->rxlev = data[3] & 0x3f;
|
||||
mrc->neigh_idx = data[4] >> 3;
|
||||
mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
|
||||
mrc->arfcn = neigh_list_get_arfcn(bts, nbv, mrc->neigh_idx);
|
||||
mrc->bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5);
|
||||
if (rep->num_cell < 2)
|
||||
return 0;
|
||||
|
@ -808,7 +858,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
|
|||
mrc = &rep->cell[1];
|
||||
mrc->rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7);
|
||||
mrc->neigh_idx = (data[6] >> 2) & 0x1f;
|
||||
mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
|
||||
mrc->arfcn = neigh_list_get_arfcn(bts, nbv, mrc->neigh_idx);
|
||||
mrc->bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4);
|
||||
if (rep->num_cell < 3)
|
||||
return 0;
|
||||
|
@ -816,7 +866,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
|
|||
mrc = &rep->cell[2];
|
||||
mrc->rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6);
|
||||
mrc->neigh_idx = (data[8] >> 1) & 0x1f;
|
||||
mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
|
||||
mrc->arfcn = neigh_list_get_arfcn(bts, nbv, mrc->neigh_idx);
|
||||
mrc->bsic = ((data[8] & 0x01) << 5) | (data[9] >> 3);
|
||||
if (rep->num_cell < 4)
|
||||
return 0;
|
||||
|
@ -824,7 +874,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
|
|||
mrc = &rep->cell[3];
|
||||
mrc->rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5);
|
||||
mrc->neigh_idx = data[10] & 0x1f;
|
||||
mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
|
||||
mrc->arfcn = neigh_list_get_arfcn(bts, nbv, mrc->neigh_idx);
|
||||
mrc->bsic = data[11] >> 2;
|
||||
if (rep->num_cell < 5)
|
||||
return 0;
|
||||
|
@ -832,7 +882,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
|
|||
mrc = &rep->cell[4];
|
||||
mrc->rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4);
|
||||
mrc->neigh_idx = ((data[12] & 0xf) << 1) | (data[13] >> 7);
|
||||
mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
|
||||
mrc->arfcn = neigh_list_get_arfcn(bts, nbv, mrc->neigh_idx);
|
||||
mrc->bsic = (data[13] >> 1) & 0x3f;
|
||||
if (rep->num_cell < 6)
|
||||
return 0;
|
||||
|
@ -840,7 +890,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
|
|||
mrc = &rep->cell[5];
|
||||
mrc->rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3);
|
||||
mrc->neigh_idx = ((data[14] & 0x07) << 2) | (data[15] >> 6);
|
||||
mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
|
||||
mrc->arfcn = neigh_list_get_arfcn(bts, nbv, mrc->neigh_idx);
|
||||
mrc->bsic = data[15] & 0x3f;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -52,7 +52,7 @@ struct gsm0808_cell_id_list2;
|
|||
* array. DCS1800 and PCS1900 can not be used at the same time so conserve
|
||||
* memory and do the below.
|
||||
*/
|
||||
static int band_compatible(const struct gsm_bts *bts, int arfcn)
|
||||
int band_compatible(const struct gsm_bts *bts, int arfcn)
|
||||
{
|
||||
enum gsm_band band;
|
||||
|
||||
|
|
|
@ -38,14 +38,10 @@ expect-ts-use trx 4 0 states * - - - - - - -
|
|||
meas-rep lchan 0 0 1 0 rxlev 20 rxqual 0 ta 0 neighbors 35 0 0 0
|
||||
|
||||
# If the BSC parsed the list correctly, it will request a handover to BTS 4.
|
||||
# expect-ho from lchan 0 0 1 0 to lchan 4 0 1 0
|
||||
expect-ho from lchan 0 0 1 0 to lchan 4 0 1 0
|
||||
|
||||
# FIXME: parses IDX=0 as ARFCN=0 instead of ARFCN=800, no handover is done
|
||||
expect-no-chan
|
||||
|
||||
# FIXME: should be on TRX 4 after handover
|
||||
expect-ts-use trx 0 0 states * TCH/F - - - - - -
|
||||
expect-ts-use trx 0 0 states * - - - - - - -
|
||||
expect-ts-use trx 1 0 states * - - - - - - -
|
||||
expect-ts-use trx 2 0 states * - - - - - - -
|
||||
expect-ts-use trx 3 0 states * - - - - - - -
|
||||
expect-ts-use trx 4 0 states * - - - - - - -
|
||||
expect-ts-use trx 4 0 states * TCH/F - - - - - -
|
||||
|
|
Loading…
Reference in New Issue