diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-06-15 16:45:51 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-06-20 10:44:53 +0200 |
commit | 29aca17ed0f33aa0f8ce646425425b6b57892025 (patch) | |
tree | 71c78e2008215085bb2b7e9544a3eaf18e6755e4 | |
parent | 7401ae6a7932dd8156087bdaf6fc476e6a49f96f (diff) |
[BSC] Hopping: Add MA IE to ASS CMD, IMM ASS CMD and HO CMD
Also, make sure the bit ordering in the pre-computed MA is correct,
as well as the cell channel description of the target cell being
present in the HO CMD.
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 1 | ||||
-rw-r--r-- | openbsc/src/abis_rsl.c | 5 | ||||
-rw-r--r-- | openbsc/src/bsc_init.c | 31 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08_utils.c | 27 |
4 files changed, 56 insertions, 8 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 5533fea74..4dcdd4bf0 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -347,6 +347,7 @@ struct gsm_bts_trx_ts { u_int8_t arfcns_data[1024/8]; /* This is the pre-computed MA for channel assignments */ struct bitvec ma; + u_int8_t ma_len; /* part of ma_data that is used */ u_int8_t ma_data[8]; /* 10.5.2.21: max 8 bytes value part */ } hopping; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index f38735480..e47900d4b 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1203,7 +1203,10 @@ static int rsl_rx_chan_rqd(struct msgb *msg) if (!lchan->ts->hopping.enabled) { ia.mob_alloc_len = 0; } else { - /* FIXME: Mobile Allocation in case of hopping */ + uint8_t *ma; + ia.mob_alloc_len = lchan->ts->hopping.ma_len; + ma = msgb_put(msg, ia.mob_alloc_len); + memcpy(ma, lchan->ts->hopping.ma_data, ia.mob_alloc_len); } DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s " diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c index 0066811a0..8e4aafd7d 100644 --- a/openbsc/src/bsc_init.c +++ b/openbsc/src/bsc_init.c @@ -940,32 +940,51 @@ static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts) struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc; struct bitvec *ts_arfcn = &ts->hopping.arfcns; struct bitvec *ma = &ts->hopping.ma; + unsigned int num_cell_arfcns, bitnum, n_chan; int i; /* re-set the MA to all-zero */ ma->cur_bit = 0; + ts->hopping.ma_len = 0; memset(ma->data, 0, ma->data_len); if (!ts->hopping.enabled) return 0; + /* count the number of ARFCNs in the cell channel allocation */ + num_cell_arfcns = 0; + for (i = 1; i < 1024; i++) { + if (bitvec_get_bit_pos(cell_chan, i)) + num_cell_arfcns++; + } + + /* pad it to octet-aligned number of bits */ + ts->hopping.ma_len = num_cell_arfcns / 8; + if (num_cell_arfcns % 8) + ts->hopping.ma_len++; + + n_chan = 0; for (i = 1; i < 1024; i++) { if (!bitvec_get_bit_pos(cell_chan, i)) continue; - /* append a bit to the MA */ + n_chan++; + /* set the corresponding bit in the MA */ + bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan; if (bitvec_get_bit_pos(ts_arfcn, i)) - bitvec_set_bit(ma, 1); + bitvec_set_bit_pos(ma, bitnum, 1); else - bitvec_set_bit(ma, 0); + bitvec_set_bit_pos(ma, bitnum, 0); } /* ARFCN 0 is special: It is coded last in the bitmask */ if (bitvec_get_bit_pos(cell_chan, 0)) { - /* append a bit to the MA */ + n_chan++; + /* set the corresponding bit in the MA */ + bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan; if (bitvec_get_bit_pos(ts_arfcn, 0)) - bitvec_set_bit(ma, 1); + bitvec_set_bit_pos(ma, bitnum, 1); else - bitvec_set_bit(ma, 0); + bitvec_set_bit_pos(ma, bitnum, 0); } return 0; diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index f517020f5..0b009d154 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -332,6 +332,8 @@ void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd, } } +#define GSM48_HOCMD_CCHDESC_LEN 16 + /* Chapter 9.1.15: Handover Command */ int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan, u_int8_t power_command, u_int8_t ho_ref) @@ -351,6 +353,22 @@ int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan, ho->ho_ref = ho_ref; ho->power_command = power_command; + if (new_lchan->ts->hopping.enabled) { + struct gsm_bts *bts = new_lchan->ts->trx->bts; + struct gsm48_system_information_type_1 *si1; + uint8_t *cur; + + si1 = GSM_BTS_SI(bts, SYSINFO_TYPE_1); + /* Copy the Cell Chan Desc (ARFCNS in this cell) */ + msgb_put_u8(msg, GSM48_IE_CELL_CH_DESC); + cur = msgb_put(msg, GSM48_HOCMD_CCHDESC_LEN); + memcpy(cur, si1->cell_channel_description, + GSM48_HOCMD_CCHDESC_LEN); + /* Copy the Mobile Allocation */ + msgb_tlv_put(msg, GSM48_IE_MA_BEFORE, + new_lchan->ts->hopping.ma_len, + new_lchan->ts->hopping.ma_data); + } /* FIXME: optional bits for type of synchronization? */ return gsm48_sendmsg(msg); @@ -381,8 +399,16 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, gsm48_lchan2chan_desc(&ass->chan_desc, lchan); ass->power_command = power_command; + /* optional: cell channel description */ + msgb_tv_put(msg, GSM48_IE_CHANMODE_1, lchan->tch_mode); + /* mobile allocation in case of hopping */ + if (lchan->ts->hopping.enabled) { + msgb_tlv_put(msg, GSM48_IE_MA_BEFORE, lchan->ts->hopping.ma_len, + lchan->ts->hopping.ma_data); + } + /* in case of multi rate we need to attach a config */ if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) { if (lchan->mr_conf.ver == 0) { @@ -406,7 +432,6 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode) struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); struct gsm48_chan_mode_modify *cmm = (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm)); - u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff; DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode); |