aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-11-29 20:02:53 +0100
committerHarald Welte <laforge@gnumonks.org>2009-11-29 20:02:53 +0100
commit8c83af65c1902811d8e9823153af09cc59f4d9f6 (patch)
tree676d70a05087c038c86cec04cae3eb13158af2bd
parentccd5a8892ded0832bd378fb33a24412b92920963 (diff)
[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.
-rw-r--r--openbsc/doc/handover.txt12
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h16
-rw-r--r--openbsc/src/gsm_04_08_utils.c51
3 files changed, 73 insertions, 6 deletions
diff --git a/openbsc/doc/handover.txt b/openbsc/doc/handover.txt
index 524d38625..ac19e8725 100644
--- a/openbsc/doc/handover.txt
+++ b/openbsc/doc/handover.txt
@@ -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
+
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index cd85dff8f..359aa1b39 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -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 {
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index ad038fba6..d3e4689b5 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -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 */