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.
This commit is contained in:
Andreas Eversberg 2014-01-23 16:12:04 +01:00 committed by Holger Hans Peter Freyther
parent 8ade45e795
commit 00b4e064ff
5 changed files with 126 additions and 0 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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 */

View File

@ -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) {}