diff --git a/openbsc/doc/channel_release.txt b/openbsc/doc/channel_release.txt index bd707b451..c9cdfebca 100644 --- a/openbsc/doc/channel_release.txt +++ b/openbsc/doc/channel_release.txt @@ -61,7 +61,8 @@ chan_alloc.c:lchan_release(chan, sacch_deactivate, reason) * Release all SAPI's > 0 as local end (The BTS should send a REL_CONF a message) * Send SACH Deactivate on SAPI=0 if required. - * It should start T3109 but it does not. + * Start T3109 (stop it when the main signalling link is disconnected) + or when the channel released. On timeout start the error handling. * abis_rsl.c schedules the RSL_MT_RF_CHAN_REL once all SAPI's are released and after T3111 has timed out or there is an error. diff --git a/openbsc/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg b/openbsc/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg index 654d39716..36065e254 100644 --- a/openbsc/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg +++ b/openbsc/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg @@ -30,7 +30,7 @@ network timer t3103 0 timer t3105 0 timer t3107 0 - timer t3109 0 + timer t3109 4 timer t3111 0 timer t3113 60 timer t3115 0 diff --git a/openbsc/doc/examples/osmo-nitb/hsl/openbsc.cfg b/openbsc/doc/examples/osmo-nitb/hsl/openbsc.cfg index 3d95748a3..b0af85598 100644 --- a/openbsc/doc/examples/osmo-nitb/hsl/openbsc.cfg +++ b/openbsc/doc/examples/osmo-nitb/hsl/openbsc.cfg @@ -31,7 +31,7 @@ network timer t3103 0 timer t3105 0 timer t3107 0 - timer t3109 0 + timer t3109 4 timer t3111 0 timer t3113 60 timer t3115 0 diff --git a/openbsc/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg b/openbsc/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg index 7a187f881..bea0b7dfc 100644 --- a/openbsc/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg +++ b/openbsc/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg @@ -30,7 +30,7 @@ network timer t3103 0 timer t3105 0 timer t3107 0 - timer t3109 0 + timer t3109 4 timer t3111 0 timer t3113 60 timer t3115 0 diff --git a/openbsc/doc/examples/osmo-nitb/nanobts/openbsc.cfg b/openbsc/doc/examples/osmo-nitb/nanobts/openbsc.cfg index 78e9787b9..7a443087c 100644 --- a/openbsc/doc/examples/osmo-nitb/nanobts/openbsc.cfg +++ b/openbsc/doc/examples/osmo-nitb/nanobts/openbsc.cfg @@ -30,7 +30,7 @@ network timer t3103 0 timer t3105 0 timer t3107 0 - timer t3109 0 + timer t3109 4 timer t3111 0 timer t3113 60 timer t3115 0 diff --git a/openbsc/doc/examples/osmo-nitb/rbs2308/openbsc.cfg b/openbsc/doc/examples/osmo-nitb/rbs2308/openbsc.cfg index 7135042ff..97cd9df50 100644 --- a/openbsc/doc/examples/osmo-nitb/rbs2308/openbsc.cfg +++ b/openbsc/doc/examples/osmo-nitb/rbs2308/openbsc.cfg @@ -29,7 +29,7 @@ network timer t3103 0 timer t3105 0 timer t3107 0 - timer t3109 0 + timer t3109 4 timer t3111 0 timer t3113 60 timer t3115 0 diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index 45af4a6fc..4f2b6b551 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -99,6 +99,7 @@ int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduc int rsl_release_sapis_from(struct gsm_lchan *lchan, int start, enum rsl_rel_mode release_mode); +int rsl_start_t3109(struct gsm_lchan *lchan); #endif /* RSL_MT_H */ diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 21fa6456a..ba431da03 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -217,6 +217,7 @@ struct gsm_lchan { #ifdef ROLE_BSC struct osmo_timer_list T3101; + struct osmo_timer_list T3109; struct osmo_timer_list T3111; struct osmo_timer_list error_timer; struct osmo_timer_list act_timer; diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 04d5c61b3..6e1ce7852 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -46,6 +46,11 @@ #define RSL_ALLOC_SIZE 1024 #define RSL_ALLOC_HEADROOM 128 +enum sacch_deact { + SACCH_NONE, + SACCH_DEACTIVATE, +}; + static int rsl_send_imm_assignment(struct gsm_lchan *lchan); static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan, @@ -644,12 +649,16 @@ static void error_timeout_cb(void *data) static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan); /* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */ -static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error) +static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error, + enum sacch_deact deact_sacch) { struct abis_rsl_dchan_hdr *dh; struct msgb *msg; int rc; + /* Stop timers that should lead to a channel release */ + osmo_timer_del(&lchan->T3109); + if (lchan->state == LCHAN_S_REL_ERR) { LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n", gsm_lchan_name(lchan)); @@ -688,7 +697,8 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error) /* * sacch de-activate and "local end release" */ - rsl_deact_sacch(lchan); + if (deact_sacch == SACCH_DEACTIVATE) + rsl_deact_sacch(lchan); rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END); /* @@ -939,7 +949,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC) rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN); else - rsl_rf_chan_release(msg->lchan, 1); + rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE); } else rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN); @@ -969,7 +979,7 @@ static int rsl_rx_conn_fail(struct msgb *msg) LOGPC(DRSL, LOGL_NOTICE, "\n"); /* FIXME: only free it after channel release ACK */ osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail); - return rsl_rf_chan_release(msg->lchan, 1); + return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE); } static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru, @@ -1250,7 +1260,7 @@ static void t3101_expired(void *data) { struct gsm_lchan *lchan = data; - rsl_rf_chan_release(lchan, 1); + rsl_rf_chan_release(lchan, 1, SACCH_DEACTIVATE); } /* If T3111 expires, we will send the RF Channel Request */ @@ -1258,7 +1268,17 @@ static void t3111_expired(void *data) { struct gsm_lchan *lchan = data; - rsl_rf_chan_release(lchan, 0); + rsl_rf_chan_release(lchan, 0, SACCH_NONE); +} + +/* If T3109 expires the MS has not send a UA/UM do the error release */ +static void t3109_expired(void *data) +{ + struct gsm_lchan *lchan = data; + + LOGP(DRSL, LOGL_ERROR, + "%s SACCH deactivation timeout.\n", gsm_lchan_name(lchan)); + rsl_rf_chan_release(lchan, 1, SACCH_NONE); } #define GSM48_LEN2PLEN(a) (((a) << 2) | 1) @@ -1516,7 +1536,7 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) { osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err); - return rsl_rf_chan_release(msg->lchan, 1); + return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE); } return 0; @@ -1544,8 +1564,8 @@ static void rsl_handle_release(struct gsm_lchan *lchan) } - - /* wait a bit to send the RF Channel Release */ + /* Stop T3109 and wait for T3111 before re-using the channel */ + osmo_timer_del(&lchan->T3109); lchan->T3111.cb = t3111_expired; lchan->T3111.data = lchan; bts = lchan->ts->trx->bts; @@ -2107,3 +2127,17 @@ int rsl_release_sapis_from(struct gsm_lchan *lchan, int start, return no_sapi; } + +int rsl_start_t3109(struct gsm_lchan *lchan) +{ + struct gsm_bts *bts = lchan->ts->trx->bts; + + /* Disabled, mostly legacy code */ + if (bts->network->T3109 == 0) + return -1; + + lchan->T3109.cb = t3109_expired; + lchan->T3109.data = lchan; + osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0); + return 0; +} diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 61b091120..dfe80c9e7 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -1379,7 +1379,7 @@ DECLARE_TIMER(3101, "Set the timeout value for IMMEDIATE ASSIGNMENT.\n") DECLARE_TIMER(3103, "Set the timeout value for HANDOVER.\n") DECLARE_TIMER(3105, "Set the timer for repetition of PHYSICAL INFORMATION.\n") DECLARE_TIMER(3107, "Currently not used.\n") -DECLARE_TIMER(3109, "Currently not used.\n") +DECLARE_TIMER(3109, "Set the RSL SACCH deactivation timeout.\n") DECLARE_TIMER(3111, "Set the RSL timeout to wait before releasing the RF Channel.\n") DECLARE_TIMER(3113, "Set the time to try paging a subscriber.\n") DECLARE_TIMER(3115, "Currently not used.\n") diff --git a/openbsc/src/libbsc/chan_alloc.c b/openbsc/src/libbsc/chan_alloc.c index a8b15d177..9b59d5df0 100644 --- a/openbsc/src/libbsc/chan_alloc.c +++ b/openbsc/src/libbsc/chan_alloc.c @@ -362,6 +362,7 @@ void lchan_free(struct gsm_lchan *lchan) void lchan_reset(struct gsm_lchan *lchan) { osmo_timer_del(&lchan->T3101); + osmo_timer_del(&lchan->T3109); osmo_timer_del(&lchan->T3111); osmo_timer_del(&lchan->error_timer); @@ -376,7 +377,7 @@ void lchan_reset(struct gsm_lchan *lchan) /* Drive the release process of the lchan */ static void _lchan_handle_release(struct gsm_lchan *lchan, - int sach_deact, int mode) + int sacch_deact, int mode) { /* Release all SAPIs on the local end and continue */ rsl_release_sapis_from(lchan, 1, RSL_REL_LOCAL_END); @@ -386,10 +387,15 @@ static void _lchan_handle_release(struct gsm_lchan *lchan, * release indication from the BTS or just take it down (e.g. * on assignment requests) */ - if (sach_deact) + if (sacch_deact) { gsm48_send_rr_release(lchan); - else + + /* Deactivate the SACCH on the BTS side */ + rsl_deact_sacch(lchan); + rsl_start_t3109(lchan); + } else { rsl_release_request(lchan, 0, mode); + } } /* Consider releasing the channel now */ diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c index 968e62ec6..de596de09 100644 --- a/openbsc/src/libbsc/gsm_04_08_utils.c +++ b/openbsc/src/libbsc/gsm_04_08_utils.c @@ -231,11 +231,7 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan) lchan->nr, lchan->type); /* Send actual release request to MS */ - gsm48_sendmsg(msg); - /* FIXME: Start Timer T3109 */ - - /* Deactivate the SACCH on the BTS side */ - return rsl_deact_sacch(lchan); + return gsm48_sendmsg(msg); } int send_siemens_mrpci(struct gsm_lchan *lchan,