aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-06-15 16:45:51 +0200
committerHarald Welte <laforge@gnumonks.org>2010-06-20 10:44:53 +0200
commit29aca17ed0f33aa0f8ce646425425b6b57892025 (patch)
tree71c78e2008215085bb2b7e9544a3eaf18e6755e4 /openbsc/src
parent7401ae6a7932dd8156087bdaf6fc476e6a49f96f (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.
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/abis_rsl.c5
-rw-r--r--openbsc/src/bsc_init.c31
-rw-r--r--openbsc/src/gsm_04_08_utils.c27
3 files changed, 55 insertions, 8 deletions
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);