diff options
author | Harald Welte <laforge@gnumonks.org> | 2009-08-09 21:49:48 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2009-08-09 21:49:48 +0200 |
commit | 39c7debc9c4495deba2261ea6036505ed86ac5e5 (patch) | |
tree | 456d8c0998443a15da5b64b8039005c5fd9168a4 /openbsc/src/abis_nm.c | |
parent | cf845cb8d3b2a3678c9482f6677a41d1c54c3bb3 (diff) |
verify bs11 channel combination constraints
Diffstat (limited to 'openbsc/src/abis_nm.c')
-rw-r--r-- | openbsc/src/abis_nm.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 31f1df009..cd551217f 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1652,6 +1652,62 @@ int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, u_int8_t *attr, int attr_len return abis_nm_sendmsg(trx->bts, msg); } +static int verify_chan_comb(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb) +{ + int i; + + /* As it turns out, the BS-11 has some very peculiar restrictions + * on the channel combinations it allows */ + if (ts->trx->bts->type == GSM_BTS_TYPE_BS11) { + switch (chan_comb) { + case NM_CHANC_TCHHalf: + case NM_CHANC_TCHHalf2: + /* not supported */ + return -EINVAL; + case NM_CHANC_SDCCH: + /* only one SDCCH/8 per TRX */ + for (i = 0; i < TRX_NR_TS; i++) { + if (i == ts->nr) + continue; + if (ts->trx->ts[i].nm_chan_comb == + NM_CHANC_SDCCH) + return -EINVAL; + } + /* not allowed for TS0 of BCCH-TRX */ + if (ts->trx == ts->trx->bts->c0 && + ts->nr == 0) + return -EINVAL; + /* not on the same TRX that has a BCCH+SDCCH4 + * combination */ + if (ts->trx == ts->trx->bts->c0 && + (ts->trx->ts[0].nm_chan_comb == 5 || + ts->trx->ts[0].nm_chan_comb == 8)) + return -EINVAL; + break; + case NM_CHANC_mainBCCH: + case NM_CHANC_BCCHComb: + /* allowed only for TS0 of C0 */ + if (ts->trx != ts->trx->bts->c0 || + ts->nr != 0) + return -EINVAL; + break; + case NM_CHANC_BCCH: + /* allowed only for TS 2/4/6 of C0 */ + if (ts->trx != ts->trx->bts->c0) + return -EINVAL; + if (ts->nr != 2 && ts->nr != 4 && + ts->nr != 6) + return -EINVAL; + break; + case 8: /* this is not like 08.58, but in fact + * FCCH+SCH+BCCH+CCCH+SDCCH/4+SACCH/C4+CBCH */ + /* FIXME: only one CBCH allowed per cell */ + break; + } + } + return 0; +} + /* Chapter 8.6.3 */ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb) { @@ -1666,6 +1722,12 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb) len += 4 + 2 + 2 + 3; DEBUGP(DNM, "Set Chan Attr %s\n", gsm_ts_name(ts)); + if (verify_chan_comb(ts, chan_comb) < 0) { + msgb_free(msg); + DEBUGP(DNM, "Invalid Channel Combination!!!\n"); + return -EINVAL; + } + ts->nm_chan_comb = chan_comb; oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); fill_om_fom_hdr(oh, len, NM_MT_SET_CHAN_ATTR, |