[handover] Implement 04.08 HANDOVER COMMAND

This is needed by a yet-to-be-implemented handover algorithm, after
it has allocated a new lchan for the MS.  Also missing: handling
the actual HANDOVER COMPLETE / FAIL messages in response.
This commit is contained in:
Harald Welte 2009-11-29 20:02:53 +01:00
parent ccd5a8892d
commit 8c83af65c1
3 changed files with 73 additions and 6 deletions

View File

@ -75,3 +75,15 @@ were achieved with the following settings:
* RXQUAL >= 6: 1 dB
== Actual Handover on a protocol level ==
After the BSC has decided a handover shall be done, it has to
# allocate a channel at the new BTS
# allocate a handover reference
# activate the channel on the BTS side using RSL CHANNEL ACTIVATION,
indicating the HO reference
# BTS responds with CHAN ACT ACK, including GSM frame number
# BSC sends 04.08 HO CMD to MS using old BTS

View File

@ -90,6 +90,22 @@ struct gsm48_ass_cmd {
u_int8_t data[0];
} __attribute__((packed));
/* Chapter 10.5.2.2 */
struct gsm48_cell_desc {
u_int8_t bcc:3,
ncc:3,
arfcn_hi:2;
u_int8_t arfcn_lo;
} __attribute__((packed));
/* Chapter 9.1.15 */
struct gsm48_ho_cmd {
struct gsm48_cell_desc cell_desc;
struct gsm48_chan_desc chan_desc;
u_int8_t ho_ref;
u_int8_t power_command;
u_int8_t data[0];
} __attribute__((packed));
/* Chapter 9.1.18 */
struct gsm48_imm_ass {

View File

@ -519,6 +519,50 @@ int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
return rsl_encryption_cmd(msg);
}
static void gsm48_cell_desc(struct gsm48_cell_desc *cd,
const struct gsm_bts *bts)
{
cd->ncc = (bts->bsic >> 3 & 0x7);
cd->bcc = (bts->bsic & 0x7);
cd->arfcn_hi = bts->c0->arfcn >> 8;
cd->arfcn_lo = bts->c0->arfcn & 0xff;
}
static void gsm48_chan_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;
}
/* 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)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
struct gsm48_ho_cmd *ho =
(struct gsm48_ho_cmd *) msgb_put(msg, sizeof(*ho));
static u_int8_t ho_ref;
msg->lchan = old_lchan;
/* mandatory bits */
gsm48_cell_desc(&ho->cell_desc, new_lchan->ts->trx->bts);
gsm48_chan_desc(&ho->chan_desc, new_lchan);
ho->ho_ref = ho_ref++;
ho->power_command = power_command;
/* FIXME: optional bits for type of synchronization? */
return gsm48_sendmsg(msg, NULL);
}
/* Chapter 9.1.2: Assignment Command */
int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
{
@ -526,7 +570,6 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
struct gsm48_ass_cmd *ass =
(struct gsm48_ass_cmd *) msgb_put(msg, sizeof(*ass));
u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
DEBUGP(DRR, "-> ASSIGNMENT COMMAND tch_mode=0x%02x\n", lchan->tch_mode);
@ -542,11 +585,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
* the chan_desc. But as long as multi-slot configurations
* are not used we seem to be fine.
*/
ass->chan_desc.chan_nr = lchan2chan_nr(lchan);
ass->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
ass->chan_desc.h0.h = 0;
ass->chan_desc.h0.arfcn_high = arfcn >> 8;
ass->chan_desc.h0.arfcn_low = arfcn & 0xff;
gsm48_chan_desc(&ass->chan_desc, lchan);
ass->power_command = power_command;
/* in case of multi rate we need to attach a config */