aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2014-01-23 16:12:04 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-03-10 13:38:07 +0100
commit00b4e064ffc4c4bb2863c1f8ce40e4e1e1bbbbff (patch)
tree3db0e5901ec8de62afce5ab50cc5414caa9e7f3e
parent8ade45e795d1ee531423d529dfa2c441ece1196a (diff)
handover: Add generic handling for handover
The BTS layer needs to inform the handover code when an access burst has been received. In turn the handover layer will ask the bts to modify the channel, it will schedule the physical information inform the BSC with the HANDOVER DETECTION and waits for the BTS layer to inform it about the first received frame to stop a timer.
-rw-r--r--include/osmo-bts/bts_model.h1
-rw-r--r--include/osmo-bts/handover.h2
-rw-r--r--src/common/handover.c112
-rw-r--r--src/osmo-bts-sysmo/oml.c9
-rw-r--r--tests/stubs.c2
5 files changed, 126 insertions, 0 deletions
diff --git a/include/osmo-bts/bts_model.h b/include/osmo-bts/bts_model.h
index 2f6ae98d..cb5433b4 100644
--- a/include/osmo-bts/bts_model.h
+++ b/include/osmo-bts/bts_model.h
@@ -29,6 +29,7 @@ int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp);
int bts_model_rsl_chan_rel(struct gsm_lchan *lchan);
+int bts_model_rsl_chan_mod(struct gsm_lchan *lchan);
int bts_model_rsl_deact_sacch(struct gsm_lchan *lchan);
int bts_model_rsl_mode_modify(struct gsm_lchan *lchan);
diff --git a/include/osmo-bts/handover.h b/include/osmo-bts/handover.h
index 1cf5d696..35d5c690 100644
--- a/include/osmo-bts/handover.h
+++ b/include/osmo-bts/handover.h
@@ -6,5 +6,7 @@ enum {
HANDOVER_WAIT_FRAME,
};
+void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay);
+void handover_frame(struct gsm_lchan *lchan);
void handover_reset(struct gsm_lchan *lchan);
diff --git a/src/common/handover.c b/src/common/handover.c
index c40219db..ab3cbcf8 100644
--- a/src/common/handover.c
+++ b/src/common/handover.c
@@ -34,6 +34,118 @@
#include <osmo-bts/logging.h>
#include <osmo-bts/handover.h>
+/* Transmit a handover related PHYS INFO on given lchan */
+static int ho_tx_phys_info(struct gsm_lchan *lchan)
+{
+ struct msgb *msg = msgb_alloc_headroom(1024, 128, "PHYS INFO");
+ struct gsm48_hdr *gh;
+
+ if (!msg)
+ return -ENOMEM;
+
+ LOGP(DHO, LOGL_INFO,
+ "%s Sending PHYSICAL INFORMATION to MS.\n",
+ gsm_lchan_name(lchan));
+
+ /* Build RSL UNITDATA REQUEST message with 04.08 PHYS INFO */
+ msg->l3h = msg->data;
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_RR;
+ gh->msg_type = GSM48_MT_RR_HANDO_INFO;
+ msgb_put_u8(msg, lchan->rqd_ta);
+
+ rsl_rll_push_l3(msg, RSL_MT_UNIT_DATA_REQ, gsm_lchan2chan_nr(lchan),
+ 0x00, 0);
+
+ lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch);
+ return 0;
+}
+
+/* timer call-back for T3105 (handover PHYS INFO re-transmit) */
+static void ho_t3105_cb(void *data)
+{
+ struct gsm_lchan *lchan = data;
+ struct gsm_bts *bts = lchan->ts->trx->bts;
+ struct gsm_bts_role_bts *btsb = bts->role;
+
+ LOGP(DHO, LOGL_INFO, "%s T3105 timeout (%d resends left)\n",
+ gsm_lchan_name(lchan), btsb->ny1 - lchan->ho.phys_info_count);
+
+ if (lchan->state != LCHAN_S_ACTIVE) {
+ LOGP(DHO, LOGL_NOTICE,
+ "%s is in not active. It is in state %s. Ignoring\n",
+ gsm_lchan_name(lchan), gsm_lchans_name(lchan->state));
+ return;
+ }
+
+ if (lchan->ho.phys_info_count >= btsb->ny1) {
+ /* HO Abort */
+ LOGP(DHO, LOGL_NOTICE, "%s NY1 reached, sending CONNection "
+ "FAILure to BSC.\n", gsm_lchan_name(lchan));
+ rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
+ return;
+ }
+
+ ho_tx_phys_info(lchan);
+ lchan->ho.phys_info_count++;
+ osmo_timer_schedule(&lchan->ho.t3105, 0, btsb->t3105_ms * 1000);
+}
+
+/* received random access on dedicated channel */
+void handover_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
+{
+ struct gsm_bts *bts = lchan->ts->trx->bts;
+ struct gsm_bts_role_bts *btsb = bts->role;
+
+ /* Ignore invalid handover ref */
+ if (lchan->ho.ref != ra) {
+ LOGP(DHO, LOGL_INFO, "%s RACH on dedicated channel received, but "
+ "ra=0x%02x != expected ref=0x%02x. (This is no bug)\n",
+ gsm_lchan_name(lchan), ra, lchan->ho.ref);
+ return;
+ }
+
+ LOGP(DHO, LOGL_NOTICE,
+ "%s RACH on dedicated channel received with TA=%u\n",
+ gsm_lchan_name(lchan), acc_delay);
+
+ /* Set timing advance */
+ lchan->rqd_ta = acc_delay;
+
+ /* Stop handover detection, wait for valid frame */
+ lchan->ho.active = HANDOVER_WAIT_FRAME;
+ if (bts_model_rsl_chan_mod(lchan) != 0) {
+ LOGP(DHO, LOGL_ERROR,
+ "%s failed to modify channel after handover\n",
+ gsm_lchan_name(lchan));
+ rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
+ return;
+ }
+
+ /* Send HANDover DETect to BSC */
+ rsl_tx_hando_det(lchan, &lchan->rqd_ta);
+
+ /* Send PHYS INFO */
+ lchan->ho.phys_info_count = 1;
+ ho_tx_phys_info(lchan);
+
+ /* Start T3105 */
+ LOGP(DHO, LOGL_DEBUG,
+ "%s Starting T3105 with %u ms\n",
+ gsm_lchan_name(lchan), btsb->t3105_ms);
+ lchan->ho.t3105.cb = ho_t3105_cb;
+ lchan->ho.t3105.data = lchan;
+ osmo_timer_schedule(&lchan->ho.t3105, 0, btsb->t3105_ms * 1000);
+}
+
+/* received frist valid data frame on dedicated channel */
+void handover_frame(struct gsm_lchan *lchan)
+{
+ LOGP(DHO, LOGL_INFO,
+ "%s First valid frame detected\n", gsm_lchan_name(lchan));
+ handover_frame(lchan);
+}
+
/* release handover state */
void handover_reset(struct gsm_lchan *lchan)
{
diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c
index 11222b18..53ad45ba 100644
--- a/src/osmo-bts-sysmo/oml.c
+++ b/src/osmo-bts-sysmo/oml.c
@@ -1577,6 +1577,15 @@ int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp)
return 0;
}
+/**
+ * Modify the given lchan in the handover scenario. This is a lot like
+ * second channel activation but with some additional activation.
+ */
+int bts_model_rsl_chan_mod(struct gsm_lchan *lchan)
+{
+ return -1;
+}
+
int bts_model_rsl_chan_rel(struct gsm_lchan *lchan)
{
/* A duplicate RF Release Request, ignore it */
diff --git a/tests/stubs.c b/tests/stubs.c
index c0955f3a..53aa434e 100644
--- a/tests/stubs.c
+++ b/tests/stubs.c
@@ -37,6 +37,8 @@ int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp)
{ return 0; }
int bts_model_rsl_mode_modify(struct gsm_lchan *lchan)
{ return 0; }
+int bts_model_rsl_chan_mod(struct gsm_lchan *lchan)
+{ return 0; }
void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
unsigned int rtp_pl_len) {}