aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-sysmo
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-01-23 16:15:10 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-03-10 13:38:07 +0100
commit9c4a52444459819af9d72bb6a82954b8b06ff0ef (patch)
tree1a942e3117b506aa0042928deccc22598fce64cc /src/osmo-bts-sysmo
parentbb76d816da905e8da5948b466f7a3d2b5aff30e8 (diff)
handover,sysmobts: Handle handover in the sysmobts code
When the lchan was activated for handover configure it to wait for a RACH burst. On release make sure to always release the RACH SAPI (in case it has been allocated). On the first frame inform handover.c about it and forward the received access burst to the handover layer. Using an E71 it was possible to make a handover for SDCCH and TCH/F from a nanoBTS but also from itself to itself. The vty commands of OpenBSC and the silent-call have been used for that. I didn't verify audio handling so far.
Diffstat (limited to 'src/osmo-bts-sysmo')
-rw-r--r--src/osmo-bts-sysmo/l1_if.c26
-rw-r--r--src/osmo-bts-sysmo/oml.c53
2 files changed, 77 insertions, 2 deletions
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 32da5d9f..bdd06f0d 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -47,6 +47,7 @@
#include <osmo-bts/paging.h>
#include <osmo-bts/measurement.h>
#include <osmo-bts/pcu_if.h>
+#include <osmo-bts/handover.h>
#include <sysmocom/femtobts/superfemto.h>
#include <sysmocom/femtobts/gsml1prim.h>
@@ -705,6 +706,9 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
data_ind->msgUnitParam.u8Size));
dump_meas_res(LOGL_DEBUG, &data_ind->measParam);
+ if (lchan->ho.active == HANDOVER_WAIT_FRAME)
+ handover_frame(lchan);
+
switch (data_ind->sapi) {
case GsmL1_Sapi_Sacch:
radio_link_timeout(lchan, (data_ind->msgUnitParam.u8Size == 0));
@@ -819,11 +823,26 @@ static int check_acc_delay(GsmL1_PhRaInd_t *ra_ind, struct gsm_bts_role_bts *bts
return *acc_delay <= btsb->max_ta;
}
+static int handle_handover(struct gsm_lchan *lchan, struct gsm_bts_role_bts *btsb,
+ GsmL1_PhRaInd_t *ra_ind)
+{
+ uint8_t acc_delay;
+ if (!check_acc_delay(ra_ind, btsb, &acc_delay)) {
+ LOGP(DHO, LOGL_INFO, "%s ignoring RACH request %u > max_ta(%u)\n",
+ gsm_lchan_name(lchan), acc_delay, btsb->max_ta);
+ return 0;
+ }
+
+ handover_rach(lchan, ra_ind->msgUnitParam.u8Buffer[0], acc_delay);
+ return 0;
+}
+
static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind)
{
struct gsm_bts_trx *trx = fl1->priv;
struct gsm_bts *bts = trx->bts;
struct gsm_bts_role_bts *btsb = bts->role;
+ struct gsm_lchan *lchan;
struct osmo_phsap_prim pp;
struct lapdm_channel *lc;
uint8_t acc_delay;
@@ -836,6 +855,13 @@ static int handle_ph_ra_ind(struct femtol1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind)
if (ra_ind->measParam.fLinkQuality < fl1->min_qual_rach)
return 0;
+ /*
+ * Check if this is a handover
+ */
+ lchan = l1if_hLayer_to_lchan(trx, ra_ind->hLayer2);
+ if (lchan && lchan->ho.active == HANDOVER_ENABLED)
+ return handle_handover(lchan, btsb, ra_ind);
+
/* increment number of RACH slots with valid RACH burst */
if (trx == bts->c0)
btsb->load.rach.access++;
diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c
index 53ad45ba..056ef5d2 100644
--- a/src/osmo-bts-sysmo/oml.c
+++ b/src/osmo-bts-sysmo/oml.c
@@ -1,5 +1,5 @@
/* (C) 2011 by Harald Welte <laforge@gnumonks.org>
- * (C) 2013 by Holger Hans Peter Freyther
+ * (C) 2013-2014 by Holger Hans Peter Freyther
*
* All Rights Reserved
*
@@ -35,6 +35,7 @@
#include <osmo-bts/amr.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/bts_model.h>
+#include <osmo-bts/handover.h>
#include "l1_if.h"
#include "femtobts.h"
@@ -460,6 +461,10 @@ static const struct sapi_dir pdtch_sapis[] = {
#endif
};
+static const struct sapi_dir ho_sapis[] = {
+ { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink },
+};
+
struct lchan_sapis {
const struct sapi_dir *sapis;
unsigned int num_sapis;
@@ -488,6 +493,11 @@ static const struct lchan_sapis sapis_for_lchan[_GSM_LCHAN_MAX] = {
},
};
+static const struct lchan_sapis sapis_for_ho = {
+ .sapis = ho_sapis,
+ .num_sapis = ARRAY_SIZE(ho_sapis),
+};
+
static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd);
static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd);
static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd);
@@ -939,6 +949,11 @@ int lchan_activate(struct gsm_lchan *lchan)
"%s Trying to activate lchan, but commands in queue\n",
gsm_lchan_name(lchan));
+ /* override the regular SAPIs if this is the first hand-over
+ * related activation of the LCHAN */
+ if (lchan->ho.active == HANDOVER_ENABLED)
+ s4l = &sapis_for_ho;
+
for (i = 0; i < s4l->num_sapis; i++) {
int sapi = s4l->sapis[i].sapi;
int dir = s4l->sapis[i].dir;
@@ -1370,6 +1385,18 @@ static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir)
return enqueue_sapi_deact_cmd(lchan, sapi, dir);
}
+static int release_sapis_for_ho(struct gsm_lchan *lchan)
+{
+ int res = 0;
+ int i;
+
+ const struct lchan_sapis *s4l = &sapis_for_ho;
+
+ for (i = s4l->num_sapis-1; i >= 0; i--)
+ res |= check_sapi_release(lchan,
+ s4l->sapis[i].sapi, s4l->sapis[i].dir);
+ return res;
+}
static int lchan_deactivate_sapis(struct gsm_lchan *lchan)
{
@@ -1389,6 +1416,9 @@ static int lchan_deactivate_sapis(struct gsm_lchan *lchan)
res |= check_sapi_release(lchan, s4l->sapis[i].sapi, s4l->sapis[i].dir);
}
+ /* always attempt to disable the RACH burst */
+ res |= release_sapis_for_ho(lchan);
+
/* nothing was queued */
if (res == 0) {
LOGP(DL1C, LOGL_ERROR, "%s all SAPIs already released?\n",
@@ -1583,7 +1613,26 @@ int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp)
*/
int bts_model_rsl_chan_mod(struct gsm_lchan *lchan)
{
- return -1;
+ const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type];
+ unsigned int i;
+
+ if (lchan->ho.active == HANDOVER_NONE)
+ return -1;
+
+ LOGP(DHO, LOGL_ERROR, "%s modifying channel for handover\n",
+ gsm_lchan_name(lchan));
+
+ /* Give up listening to RACH bursts */
+ release_sapis_for_ho(lchan);
+
+ /* Activate the normal SAPIs */
+ for (i = 0; i < s4l->num_sapis; i++) {
+ int sapi = s4l->sapis[i].sapi;
+ int dir = s4l->sapis[i].dir;
+ enqueue_sapi_act_cmd(lchan, sapi, dir);
+ }
+
+ return 0;
}
int bts_model_rsl_chan_rel(struct gsm_lchan *lchan)