diff options
Diffstat (limited to 'src/osmo-bts-sysmo')
-rw-r--r-- | src/osmo-bts-sysmo/l1_if.c | 26 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/oml.c | 53 |
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) |