lchan: Introduce T3109 handling for the release procedure

T3109 is started when the SACCH is deactivated. It is stopped when
the phones sends the DISC/UA/UM on LAPDm for the main signalling
link. In case of timeout the abnormal release procedure will be
initiated. Make sure to not issue the SACCH Deactivate twice to
avoid confusing the equipment.

This is still not fully spec compliant. In case of a timeout the
abnormal release handling will be started which involves starting
T3111+2. The error handling should be split out of the rf channel
release method, e.g. lchan_release should be called and check if
the channel release was already initiated.
This commit is contained in:
Holger Hans Peter Freyther 2011-12-28 16:21:05 +01:00
parent 638da51a78
commit b348939d86
12 changed files with 63 additions and 24 deletions

View File

@ -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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,