[BSC] Implement per-timeslot ARFCN lists for frequency hopping
We now compute the Cell Channel Description for SI 1 by bit-wise OR of the ARFCN bitmask of each timeslot on all the TRX of the BTS. Also, support generating a GSM 04.08 Channel Description IE for the hopping case (with HSN/MAIO instead of ARFCN). What's still missing now: Sending the 04.08 Mobile Allocation IE
This commit is contained in:
parent
6e0cd04725
commit
a39b0f2bb7
|
@ -63,5 +63,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg);
|
|||
|
||||
struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value);
|
||||
struct msgb *gsm48_create_loc_upd_rej(uint8_t cause);
|
||||
void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
|
||||
const struct gsm_lchan *lchan);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -338,8 +338,11 @@ struct gsm_bts_trx_ts {
|
|||
u_int8_t nm_chan_comb;
|
||||
|
||||
struct {
|
||||
int enabled;
|
||||
u_int8_t maio;
|
||||
u_int8_t hsn;
|
||||
struct bitvec arfcns;
|
||||
u_int8_t arfcns_data[1024/8];
|
||||
} hopping;
|
||||
|
||||
/* To which E1 subslot are we connected */
|
||||
|
|
|
@ -1976,11 +1976,23 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
|
|||
NM_OC_CHANNEL, bts->bts_nr,
|
||||
ts->trx->nr, ts->nr);
|
||||
msgb_tv_put(msg, NM_ATT_CHAN_COMB, chan_comb);
|
||||
if (ts->hopping.hsn) {
|
||||
if (ts->hopping.enabled) {
|
||||
unsigned int i;
|
||||
uint8_t *len;
|
||||
|
||||
msgb_tv_put(msg, NM_ATT_HSN, ts->hopping.hsn);
|
||||
msgb_tv_put(msg, NM_ATT_MAIO, ts->hopping.maio);
|
||||
/* FIXME: compute ARFCN list */
|
||||
msgb_tlv16_put(msg, NM_ATT_ARFCN_LIST, 1, &arfcn);
|
||||
|
||||
/* build the ARFCN list */
|
||||
msgb_put_u8(msg, NM_ATT_ARFCN_LIST);
|
||||
len = msgb_put(msg, 1);
|
||||
*len = 0;
|
||||
for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) {
|
||||
if (bitvec_get_bit_pos(&ts->hopping.arfcns, i)) {
|
||||
msgb_put_u16(msg, i);
|
||||
*len += sizeof(uint16_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
msgb_tv_put(msg, NM_ATT_TSC, bts->tsc); /* training sequence */
|
||||
if (bts->type == GSM_BTS_TYPE_BS11)
|
||||
|
|
|
@ -1195,15 +1195,16 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
|
|||
ia.proto_discr = GSM48_PDISC_RR;
|
||||
ia.msg_type = GSM48_MT_RR_IMM_ASS;
|
||||
ia.page_mode = GSM48_PM_SAME;
|
||||
ia.chan_desc.chan_nr = lchan2chan_nr(lchan);
|
||||
ia.chan_desc.h0.h = 0;
|
||||
ia.chan_desc.h0.arfcn_high = arfcn >> 8;
|
||||
ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
|
||||
ia.chan_desc.h0.tsc = bts->tsc;
|
||||
gsm48_lchan2chan_desc(&ia.chan_desc, lchan);
|
||||
|
||||
/* use request reference extracted from CHAN_RQD */
|
||||
memcpy(&ia.req_ref, rqd_ref, sizeof(ia.req_ref));
|
||||
ia.timing_advance = rqd_ta;
|
||||
ia.mob_alloc_len = 0;
|
||||
if (!lchan->ts->hopping.enabled) {
|
||||
ia.mob_alloc_len = 0;
|
||||
} else {
|
||||
/* FIXME: Mobile Allocation in case of hopping */
|
||||
}
|
||||
|
||||
DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
|
||||
"r=%s ra=0x%02x\n", gsm_lchan_name(lchan), arfcn, subch,
|
||||
|
|
|
@ -305,13 +305,21 @@ static void config_write_ts_single(struct vty *vty, struct gsm_bts_trx_ts *ts)
|
|||
if (ts->pchan != GSM_PCHAN_NONE)
|
||||
vty_out(vty, " phys_chan_config %s%s",
|
||||
gsm_pchan_name(ts->pchan), VTY_NEWLINE);
|
||||
if (ts->hopping.hsn) {
|
||||
vty_out(vty, " hopping sequence number %u%s",
|
||||
vty_out(vty, " hopping enabled %u%s",
|
||||
ts->hopping.enabled, VTY_NEWLINE);
|
||||
if (ts->hopping.enabled) {
|
||||
unsigned int i;
|
||||
vty_out(vty, " hopping sequence-number %u%s",
|
||||
ts->hopping.hsn, VTY_NEWLINE);
|
||||
vty_out(vty, " hopping maio %u%s",
|
||||
vty_out(vty, " hopping maio %u%s",
|
||||
ts->hopping.maio, VTY_NEWLINE);
|
||||
/* FIXME: ARFCN list */
|
||||
}
|
||||
for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) {
|
||||
if (!bitvec_get_bit_pos(&ts->hopping.arfcns, i))
|
||||
continue;
|
||||
vty_out(vty, " hopping arfcn add %u%s",
|
||||
i, VTY_NEWLINE);
|
||||
}
|
||||
} else
|
||||
config_write_e1_link(vty, &ts->e1_link, " ");
|
||||
}
|
||||
|
||||
|
@ -1984,9 +1992,25 @@ DEFUN(cfg_ts_pchan,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define HOPPING_STR "Configure frequency hopping\n"
|
||||
|
||||
DEFUN(cfg_ts_hopping,
|
||||
cfg_ts_hopping_cmd,
|
||||
"hopping enabled (0|1)",
|
||||
HOPPING_STR "Enable or disable frequency hopping\n"
|
||||
"Disable frequency hopping\n" "Enable frequency hopping\n")
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = vty->index;
|
||||
|
||||
ts->hopping.enabled = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ts_hsn,
|
||||
cfg_ts_hsn_cmd,
|
||||
"hopping sequence number <0-63>",
|
||||
"hopping sequence-number <0-63>",
|
||||
HOPPING_STR
|
||||
"Which hopping sequence to use for this channel")
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = vty->index;
|
||||
|
@ -1999,6 +2023,7 @@ DEFUN(cfg_ts_hsn,
|
|||
DEFUN(cfg_ts_maio,
|
||||
cfg_ts_maio_cmd,
|
||||
"hopping maio <0-63>",
|
||||
HOPPING_STR
|
||||
"Which hopping MAIO to use for this channel")
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = vty->index;
|
||||
|
@ -2011,24 +2036,28 @@ DEFUN(cfg_ts_maio,
|
|||
DEFUN(cfg_ts_arfcn_add,
|
||||
cfg_ts_arfcn_add_cmd,
|
||||
"hopping arfcn add <0-1023>",
|
||||
"Add an entry to the hopping ARFCN list")
|
||||
HOPPING_STR "Configure hopping ARFCN list\n"
|
||||
"Add an entry to the hopping ARFCN list\n" "ARFCN\n")
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = vty->index;
|
||||
int arfcn = atoi(argv[0]);
|
||||
|
||||
/* FIXME */
|
||||
bitvec_set_bit_pos(&ts->hopping.arfcns, arfcn, 1);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ts_arfcn_del,
|
||||
cfg_ts_arfcn_del_cmd,
|
||||
"hopping arfcn del <0-1023>",
|
||||
"Delete an entry to the hopping ARFCN list")
|
||||
HOPPING_STR "Configure hopping ARFCN list\n"
|
||||
"Delete an entry to the hopping ARFCN list\n" "ARFCN\n")
|
||||
{
|
||||
struct gsm_bts_trx_ts *ts = vty->index;
|
||||
int arfcn = atoi(argv[0]);
|
||||
|
||||
/* FIXME */
|
||||
bitvec_set_bit_pos(&ts->hopping.arfcns, arfcn, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2193,6 +2222,7 @@ int bsc_vty_init(void)
|
|||
install_element(TS_NODE, &ournode_exit_cmd);
|
||||
install_element(TS_NODE, &ournode_end_cmd);
|
||||
install_element(TS_NODE, &cfg_ts_pchan_cmd);
|
||||
install_element(TS_NODE, &cfg_ts_hopping_cmd);
|
||||
install_element(TS_NODE, &cfg_ts_hsn_cmd);
|
||||
install_element(TS_NODE, &cfg_ts_maio_cmd);
|
||||
install_element(TS_NODE, &cfg_ts_arfcn_add_cmd);
|
||||
|
|
|
@ -312,16 +312,24 @@ static void gsm48_cell_desc(struct gsm48_cell_desc *cd,
|
|||
cd->arfcn_lo = bts->c0->arfcn & 0xff;
|
||||
}
|
||||
|
||||
static void gsm48_chan_desc(struct gsm48_chan_desc *cd,
|
||||
const struct gsm_lchan *lchan)
|
||||
void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
|
||||
const struct gsm_lchan *lchan)
|
||||
{
|
||||
u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
|
||||
|
||||
cd->chan_nr = lchan2chan_nr(lchan);
|
||||
cd->h0.tsc = lchan->ts->trx->bts->tsc;
|
||||
cd->h0.h = 0;
|
||||
cd->h0.arfcn_high = arfcn >> 8;
|
||||
cd->h0.arfcn_low = arfcn & 0xff;
|
||||
if (!lchan->ts->hopping.enabled) {
|
||||
cd->h0.tsc = lchan->ts->trx->bts->tsc;
|
||||
cd->h0.h = 0;
|
||||
cd->h0.arfcn_high = arfcn >> 8;
|
||||
cd->h0.arfcn_low = arfcn & 0xff;
|
||||
} else {
|
||||
cd->h1.tsc = lchan->ts->trx->bts->tsc;
|
||||
cd->h1.h = 1;
|
||||
cd->h1.maio_high = lchan->ts->hopping.maio >> 2;
|
||||
cd->h1.maio_low = lchan->ts->hopping.maio & 0x03;
|
||||
cd->h1.hsn = lchan->ts->hopping.hsn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Chapter 9.1.15: Handover Command */
|
||||
|
@ -339,7 +347,7 @@ int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
|
|||
|
||||
/* mandatory bits */
|
||||
gsm48_cell_desc(&ho->cell_desc, new_lchan->ts->trx->bts);
|
||||
gsm48_chan_desc(&ho->chan_desc, new_lchan);
|
||||
gsm48_lchan2chan_desc(&ho->chan_desc, new_lchan);
|
||||
ho->ho_ref = ho_ref;
|
||||
ho->power_command = power_command;
|
||||
|
||||
|
@ -370,7 +378,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan,
|
|||
* the chan_desc. But as long as multi-slot configurations
|
||||
* are not used we seem to be fine.
|
||||
*/
|
||||
gsm48_chan_desc(&ass->chan_desc, lchan);
|
||||
gsm48_lchan2chan_desc(&ass->chan_desc, lchan);
|
||||
ass->power_command = power_command;
|
||||
|
||||
msgb_tv_put(msg, GSM48_IE_CHANMODE_1, lchan->tch_mode);
|
||||
|
@ -409,11 +417,7 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
|
|||
|
||||
/* fill the channel information element, this code
|
||||
* should probably be shared with rsl_rx_chan_rqd() */
|
||||
cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
|
||||
cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
|
||||
cmm->chan_desc.h0.h = 0;
|
||||
cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
|
||||
cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
|
||||
gsm48_lchan2chan_desc(&cmm->chan_desc, lchan);
|
||||
cmm->mode = mode;
|
||||
|
||||
/* in case of multi rate we need to attach a config */
|
||||
|
|
|
@ -154,6 +154,9 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
|
|||
ts->nr = k;
|
||||
ts->pchan = GSM_PCHAN_NONE;
|
||||
|
||||
ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
|
||||
ts->hopping.arfcns.data = ts->hopping.arfcns_data;
|
||||
|
||||
for (l = 0; l < TS_MAX_LCHAN; l++) {
|
||||
struct gsm_lchan *lchan;
|
||||
lchan = &ts->lchan[l];
|
||||
|
|
|
@ -177,9 +177,23 @@ static int generate_cell_chan_list(u_int8_t *chan_list, struct gsm_bts *bts)
|
|||
struct gsm_bts_trx *trx;
|
||||
struct bitvec *bv = &bts->si_common.cell_alloc;
|
||||
|
||||
/* Zero-initialize the bit-vector */
|
||||
memset(&bv->data, 0, bv->data_len);
|
||||
|
||||
/* first we generate a bitvec of all TRX ARFCN's in our BTS */
|
||||
llist_for_each_entry(trx, &bts->trx_list, list)
|
||||
llist_for_each_entry(trx, &bts->trx_list, list) {
|
||||
unsigned int i, j;
|
||||
/* Always add the TRX's ARFCN */
|
||||
bitvec_set_bit_pos(bv, trx->arfcn, 1);
|
||||
for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
|
||||
struct gsm_bts_trx_ts *ts = &trx->ts[i];
|
||||
/* Add any ARFCNs present in hopping channels */
|
||||
for (j = 0; j < 1024; j++) {
|
||||
if (bitvec_get_bit_pos(&ts->hopping.arfcns, j))
|
||||
bitvec_set_bit_pos(bv, j, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* then we generate a GSM 04.08 frequency list from the bitvec */
|
||||
return bitvec2freq_list(chan_list, bv, bts);
|
||||
|
@ -191,6 +205,9 @@ static int generate_bcch_chan_list(u_int8_t *chan_list, struct gsm_bts *bts)
|
|||
struct gsm_bts *cur_bts;
|
||||
struct bitvec *bv = &bts->si_common.neigh_list;
|
||||
|
||||
/* Zero-initialize the bit-vector */
|
||||
memset(&bv->data, 0, bv->data_len);
|
||||
|
||||
/* first we generate a bitvec of the BCCH ARFCN's in our BSC */
|
||||
llist_for_each_entry(cur_bts, &bts->network->bts_list, list) {
|
||||
if (cur_bts == bts)
|
||||
|
|
Loading…
Reference in New Issue