From 652ab250ace76c5406b668abd898e11e8a99c2e9 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 27 Jan 2021 23:45:33 +0100 Subject: lchan activation: indicate whether TA is known On lchan activation, we already know the Timing Advance in most situations: from the Channel Request RACH, or from a previous lchan in the same cell. Place this information in lchan->activate.info.ta. So far, the lchan->last_ta (until recently called rqd_ta) was used to store the initial TA for channel activation -- move the initial TA to lchan->activate.info.ta, for proper scoping. Only an inter-cell handover does not yet know a Timing Advance (until the Handover Detection RACH is received), so indicate activate.info.ta_known = false for that case. If ta_known is false, do not include an Access Delay IE in the Channel Activation message, ensuring that the BTS does not use an arbitrary TA that is likely inaccurate. The effect for OsmoBTS is that we will *not* start the downlink SACCH on channel activation for inter-cell handover, but will wait for a HO RACH first, and then use the correct TA when enabling downlink SACCH. Related: OS#4008 SYS#5192 Change-Id: I986bf93e8acd6aef7eaf63ac962480b680aa894f --- include/osmocom/bsc/gsm_data.h | 2 ++ src/osmo-bsc/abis_rsl.c | 18 +++++++++--------- src/osmo-bsc/assignment_fsm.c | 4 ++++ src/osmo-bsc/handover_fsm.c | 7 +++++++ src/osmo-bsc/lchan_fsm.c | 8 ++++++-- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index 98822fb4f..20829711d 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -571,6 +571,8 @@ struct lchan_activate_info { /* During intra-BSC handover, we keep the MGW endpoint intact and just re-route to the new lchan. This * activate_info is for the new lchan, the re_use_mgw_endpoint_from_lchan points at the old lchan. */ struct gsm_lchan *re_use_mgw_endpoint_from_lchan; + bool ta_known; + uint8_t ta; }; struct gsm_lchan { diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c index 5bd53f1c7..63ca58fd3 100644 --- a/src/osmo-bsc/abis_rsl.c +++ b/src/osmo-bsc/abis_rsl.c @@ -521,7 +521,6 @@ int rsl_tx_chan_activ(struct gsm_lchan *lchan, uint8_t act_type, uint8_t ho_ref) struct msgb *msg; int rc; uint8_t *len; - uint8_t ta; struct rsl_ie_chan_mode cm; struct gsm48_chan_desc cd; @@ -541,12 +540,6 @@ int rsl_tx_chan_activ(struct gsm_lchan *lchan, uint8_t act_type, uint8_t ho_ref) return rc; } - ta = lchan->last_ta; - - /* BS11 requires TA shifted by 2 bits */ - if (bts->type == GSM_BTS_TYPE_BS11) - ta <<= 2; - memset(&cd, 0, sizeof(cd)); gsm48_lchan2chan_desc(&cd, lchan); @@ -601,7 +594,13 @@ int rsl_tx_chan_activ(struct gsm_lchan *lchan, uint8_t act_type, uint8_t ho_ref) if (bts->ms_power_ctrl.mode != GSM_PWR_CTRL_MODE_NONE) msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power); - msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta); + if (lchan->activate.info.ta_known) { + uint8_t ta = lchan->activate.info.ta; + /* BS11 requires TA shifted by 2 bits */ + if (bts->type == GSM_BTS_TYPE_BS11) + ta <<= 2; + msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta); + } /* BS/MS Power Control Parameters (if supported by BTS model) */ add_power_control_params(msg, RSL_IE_BS_POWER_PARAM, lchan); @@ -1744,13 +1743,14 @@ void abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts) OSMO_ASSERT(lchan->rqd_ref); *(lchan->rqd_ref) = rqd->ref; - lchan->last_ta = rqd->ta; LOG_LCHAN(lchan, LOGL_DEBUG, "MS: Channel Request: reason=%s ra=0x%02x ta=%d\n", gsm_chreq_name(rqd->reason), rqd->ref.ra, rqd->ta); info = (struct lchan_activate_info){ .activ_for = FOR_MS_CHANNEL_REQUEST, .chan_mode = GSM48_CMODE_SIGN, + .ta = rqd->ta, + .ta_known = true, }; lchan_activate(lchan, &info); diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c index 83822a185..b938ded37 100644 --- a/src/osmo-bsc/assignment_fsm.c +++ b/src/osmo-bsc/assignment_fsm.c @@ -478,6 +478,8 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts .requires_voice_stream = conn->assignment.requires_voice_stream, .msc_assigned_cic = req->msc_assigned_cic, .re_use_mgw_endpoint_from_lchan = conn->lchan, + .ta = conn->lchan->last_ta, + .ta_known = true, }; osmo_fsm_inst_dispatch(conn->lchan->fi, LCHAN_EV_REQUEST_MODE_MODIFY, &info); @@ -553,6 +555,8 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts .requires_voice_stream = conn->assignment.requires_voice_stream, .msc_assigned_cic = req->msc_assigned_cic, .re_use_mgw_endpoint_from_lchan = conn->lchan, + .ta = conn->lchan->last_ta, + .ta_known = true, }; lchan_activate(conn->assignment.new_lchan, &info); } diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c index 573f249a1..8747b8063 100644 --- a/src/osmo-bsc/handover_fsm.c +++ b/src/osmo-bsc/handover_fsm.c @@ -408,6 +408,13 @@ static void handover_start_intra_bsc(struct gsm_subscriber_connection *conn) .s15_s0 = conn->lchan->activate.info.s15_s0, }; + /* For intra-cell handover, we know the accurate Timing Advance from the previous lchan. For inter-cell + * handover, no Timing Advance for the new cell is known, so leave it unset. */ + if (ho->new_bts == bts) { + info.ta = conn->lchan->last_ta; + info.ta_known = true; + } + lchan_activate(ho->new_lchan, &info); } diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c index 80ac1a14c..d3a2d5773 100644 --- a/src/osmo-bsc/lchan_fsm.c +++ b/src/osmo-bsc/lchan_fsm.c @@ -580,7 +580,6 @@ static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t p ms_power_dbm = ms_pwr_dbm(bts->band, old_lchan->ms_power); lchan_update_ms_power_ctrl_level(lchan, ms_power_dbm >= 0 ? ms_power_dbm : bts->ms_max_power); lchan->bs_power = old_lchan->bs_power; - lchan->last_ta = old_lchan->last_ta; } else { lchan_update_ms_power_ctrl_level(lchan, bts->ms_max_power); /* Upon last entering the UNUSED state, from lchan_reset(): @@ -702,8 +701,13 @@ static void lchan_fsm_wait_activ_ack_onenter(struct osmo_fsm_inst *fi, uint32_t lchan->encr = lchan->activate.info.encr; rc = rsl_tx_chan_activ(lchan, act_type, ho_ref); - if (rc) + if (rc) { lchan_fail_to(LCHAN_ST_UNUSED, "Tx Chan Activ failed: %s (%d)", strerror(-rc), rc); + return; + } + + if (lchan->activate.info.ta_known) + lchan->last_ta = lchan->activate.info.ta; } static void lchan_fsm_post_activ_ack(struct osmo_fsm_inst *fi); -- cgit v1.2.3