aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2012-12-23 20:21:15 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2012-12-23 20:21:15 +0100
commit7d0f60dce6dd1538db8a62e2162c108d30edaecd (patch)
tree4989a09e50b3153cb844552c1ac28b46e977aeaf
parent10049bc3b701a0e8ce1dc5242c7c683a8c0ca99b (diff)
parentb348939d86bbadab2b162dda00246abdfd33055a (diff)
Merge branch 'zecke/channel-release'
Merge the channel release re-work. The most notable change is that SAPI > 0 will now be released on the local end and that the release process should be both more fast and more standard conform. With SMS spamming/mass sending the nanoBTS is crashing but this does not appear to originate from any of these changes. I used git rebase to go through each of the change to see where the nanoBTS is crashing but couldn't reproduce it. It might be a general overload or something generated by the modems of the sysmocom modem bank. Merge it before the 29C3 so we can test this code some more.
-rw-r--r--openbsc/doc/channel_release.txt20
-rw-r--r--openbsc/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg2
-rw-r--r--openbsc/doc/examples/osmo-nitb/hsl/openbsc.cfg2
-rw-r--r--openbsc/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg2
-rw-r--r--openbsc/doc/examples/osmo-nitb/nanobts/openbsc.cfg2
-rw-r--r--openbsc/doc/examples/osmo-nitb/rbs2308/openbsc.cfg2
-rw-r--r--openbsc/include/openbsc/abis_rsl.h9
-rw-r--r--openbsc/include/openbsc/chan_alloc.h2
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h6
-rw-r--r--openbsc/src/libbsc/abis_rsl.c152
-rw-r--r--openbsc/src/libbsc/bsc_api.c14
-rw-r--r--openbsc/src/libbsc/bsc_vty.c2
-rw-r--r--openbsc/src/libbsc/chan_alloc.c67
-rw-r--r--openbsc/src/libbsc/gsm_04_08_utils.c6
-rw-r--r--openbsc/src/libbsc/handover_logic.c8
-rw-r--r--openbsc/src/libcommon/gsm_data_shared.c1
16 files changed, 180 insertions, 117 deletions
diff --git a/openbsc/doc/channel_release.txt b/openbsc/doc/channel_release.txt
index e578aa828..c9cdfebca 100644
--- a/openbsc/doc/channel_release.txt
+++ b/openbsc/doc/channel_release.txt
@@ -56,21 +56,21 @@ bsc_api.c:gsm0808_clear
* Release the primary lchan with normal release, SACH deactivate
chan_alloc.c:lchan_release(chan, sacch_deactivate, reason)
- * Start release procedure. It is working in steps with callbacks
- coming from the abis_rsl.c code.
- * Release all SAPI's > 0, wait for them to be released
- * Send SACH Deactivate on SAPI=0
- * Finally Release the channel
+ * Start the release procedure. It is working in steps with callbacks
+ coming from the abis_rsl.c code.
+ * 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.
+ * 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.
RX of RELease INDication:
* Calls internal rsl_handle_release which might release the RF.
- * Informs chan_alloc.c about the release with
- rsl_lchan_rll_release.
-RX of RELease CONFimem:
+RX of RELease CONFirmation:
* Calls internal rsl_handle_release which might release the RF.
- * Informs chan_alloc.c about the release with
- rsl_lchan_rll_release.
* RX of RF_CHAN_REL_ACK
* call lchan_free()
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 f7e2e2aac..4f2b6b551 100644
--- a/openbsc/include/openbsc/abis_rsl.h
+++ b/openbsc/include/openbsc/abis_rsl.h
@@ -67,13 +67,13 @@ int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act);
int abis_rsl_rcvmsg(struct msgb *msg);
uint64_t str_to_imsi(const char *imsi_str);
-int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason);
+int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
+ enum rsl_rel_mode release_mode);
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
/* to be provided by external code */
int rsl_deact_sacch(struct gsm_lchan *lchan);
-int rsl_lchan_rll_release(struct gsm_lchan *lchan, uint8_t link_id);
/* BCCH related code */
int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
@@ -96,5 +96,10 @@ int rsl_nokia_si_end(struct gsm_bts_trx *trx);
/* required for Nokia BTS power control */
int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction);
+
+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/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h
index f1c890e9d..f2d3c781d 100644
--- a/openbsc/include/openbsc/chan_alloc.h
+++ b/openbsc/include/openbsc/chan_alloc.h
@@ -46,7 +46,7 @@ void lchan_free(struct gsm_lchan *lchan);
void lchan_reset(struct gsm_lchan *lchan);
/* Release the given lchan */
-int lchan_release(struct gsm_lchan *lchan, int sacch_deact, int release_mode);
+int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode release_mode);
struct load_counter {
unsigned int total;
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index fda3b097b..ba431da03 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -120,6 +120,7 @@ enum gsm_lchan_state {
LCHAN_S_ACTIVE, /* channel is active and operational */
LCHAN_S_REL_REQ, /* channel release has been requested */
LCHAN_S_REL_ERR, /* channel is in an error state */
+ LCHAN_S_BROKEN, /* channel is somehow unusable */
LCHAN_S_INACTIVE, /* channel is set inactive */
};
@@ -196,9 +197,6 @@ struct gsm_lchan {
uint8_t sapis[8];
int sacch_deact;
- /** GSM 08.58 9.3.20 */
- int release_mode;
-
struct {
uint32_t bound_ip;
uint32_t connect_ip;
@@ -219,9 +217,11 @@ 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;
+ uint8_t error_cause;
/* table of neighbor cell measurements */
struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index b703c034f..6e1ce7852 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -2,6 +2,7 @@
* 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2012 by Holger Hans Peter Freyther
*
* All Rights Reserved
*
@@ -45,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,
@@ -56,6 +62,14 @@ static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
}
+static void do_lchan_free(struct gsm_lchan *lchan)
+{
+ /* we have an error timer pending to release that */
+ if (lchan->state != LCHAN_S_REL_ERR)
+ rsl_lchan_set_state(lchan, LCHAN_S_NONE);
+ lchan_free(lchan);
+}
+
static uint8_t mdisc_by_msgtype(uint8_t msg_type)
{
/* mask off the transparent bit ? */
@@ -182,7 +196,7 @@ static void lchan_act_tmr_cb(void *data)
{
struct gsm_lchan *lchan = data;
- LOGP(DRSL, LOGL_NOTICE, "%s Timeout during activation!\n",
+ LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
gsm_lchan_name(lchan));
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
@@ -193,12 +207,10 @@ static void lchan_deact_tmr_cb(void *data)
{
struct gsm_lchan *lchan = data;
- LOGP(DRSL, LOGL_NOTICE, "%s Timeout during deactivation!\n",
+ LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
gsm_lchan_name(lchan));
- if (lchan->state != LCHAN_S_REL_ERR)
- rsl_lchan_set_state(lchan, LCHAN_S_NONE);
- lchan_free(lchan);
+ do_lchan_free(lchan);
}
@@ -637,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));
@@ -660,13 +676,34 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
if (error) {
+ struct e1inp_sign_link *sign_link = msg->dst;
+
/*
- * the nanoBTS sends RLL release indications after the channel release. This can
- * be a problem when we have reassigned the channel to someone else and then can
- * not figure out who used this channel.
+ * FIXME: GSM 04.08 gives us two options for the abnormal
+ * chanel release. This can be either like in the non-existent
+ * sub-lcuase 3.5.1 or for the main signalling link deactivate
+ * the SACCH, start timer T3109 and consider the channel as
+ * released.
+ *
+ * This code is doing the later for all raido links and not
+ * only the main link. Right now all SAPIs are released on the
+ * local end, the SACCH will be de-activated and right now the
+ * T3111 will be started. First T3109 should be started and then
+ * the T3111.
+ *
+ * TODO: Move this out of the function.
*/
- struct e1inp_sign_link *sign_link = msg->dst;
+ /*
+ * sacch de-activate and "local end release"
+ */
+ if (deact_sacch == SACCH_DEACTIVATE)
+ rsl_deact_sacch(lchan);
+ rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END);
+
+ /*
+ * TODO: start T3109 now.
+ */
rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
lchan->error_timer.data = lchan;
lchan->error_timer.cb = error_timeout_cb;
@@ -696,17 +733,15 @@ static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
+ /* Stop all pending timers */
osmo_timer_del(&lchan->act_timer);
+ osmo_timer_del(&lchan->T3111);
if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
gsm_lchan_name(lchan),
gsm_lchans_name(lchan->state));
- osmo_timer_del(&lchan->T3111);
- /* we have an error timer pending to release that */
- if (lchan->state != LCHAN_S_REL_ERR)
- rsl_lchan_set_state(lchan, LCHAN_S_NONE);
- lchan_free(lchan);
+ do_lchan_free(lchan);
return 0;
}
@@ -833,7 +868,8 @@ int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
lchan_free() */
-int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason)
+int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
+ enum rsl_rel_mode release_mode)
{
struct msgb *msg;
@@ -841,14 +877,14 @@ int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason
msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
link_id, 0);
/* 0 is normal release, 1 is local end */
- msgb_tv_put(msg, RSL_IE_RELEASE_MODE, reason);
+ msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
/* FIXME: start some timer in case we don't receive a REL ACK ? */
msg->dst = lchan->ts->trx->rsl_link;
DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
- gsm_lchan_name(lchan), link_id, reason);
+ gsm_lchan_name(lchan), link_id, release_mode);
return abis_rsl_sendmsg(msg);
}
@@ -909,19 +945,18 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
print_rsl_cause(LOGL_ERROR, cause,
TLVP_LEN(&tp, RSL_IE_CAUSE));
+ msg->lchan->error_cause = *cause;
if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
- rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
+ 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_NONE);
+ rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
LOGPC(DRSL, LOGL_ERROR, "\n");
send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
-
- lchan_free(msg->lchan);
return 0;
}
@@ -944,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,
@@ -1225,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 */
@@ -1233,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)
@@ -1491,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;
@@ -1502,7 +1547,11 @@ static void rsl_handle_release(struct gsm_lchan *lchan)
int sapi;
struct gsm_bts *bts;
- /* maybe we have only brought down one RLL */
+ /*
+ * Maybe only one link/SAPI was releasd or the error handling
+ * was activated. Just return now and let the other code handle
+ * it.
+ */
if (lchan->state != LCHAN_S_REL_REQ)
return;
@@ -1515,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;
@@ -1576,7 +1625,6 @@ static int abis_rsl_rx_rll(struct msgb *msg)
rll_indication(msg->lchan, rllh->link_id,
BSC_RLLR_IND_REL_IND);
rsl_handle_release(msg->lchan);
- rsl_lchan_rll_release(msg->lchan, rllh->link_id);
break;
case RSL_MT_REL_CONF:
/* BTS informs us of having received UA from MS,
@@ -1584,7 +1632,6 @@ static int abis_rsl_rx_rll(struct msgb *msg)
DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
rsl_handle_release(msg->lchan);
- rsl_lchan_rll_release(msg->lchan, rllh->link_id);
break;
case RSL_MT_ERROR_IND:
rc = rsl_rx_rll_err_ind(msg);
@@ -2053,3 +2100,44 @@ int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduc
return abis_rsl_sendmsg(msg);
}
+
+/**
+ * Release all allocated SAPIs starting from @param start and
+ * release them with the given release mode. Once the release
+ * confirmation arrives it will be attempted to release the
+ * the RF channel.
+ */
+int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
+ enum rsl_rel_mode release_mode)
+{
+ int no_sapi = 1;
+ int sapi;
+
+ for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
+ uint8_t link_id;
+ if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
+ continue;
+
+ link_id = sapi;
+ if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
+ link_id |= 0x40;
+ rsl_release_request(lchan, link_id, release_mode);
+ no_sapi = 0;
+ }
+
+ 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_api.c b/openbsc/src/libbsc/bsc_api.c
index e0ba6063f..ad89fb2a6 100644
--- a/openbsc/src/libbsc/bsc_api.c
+++ b/openbsc/src/libbsc/bsc_api.c
@@ -141,7 +141,7 @@ static void assignment_t10_timeout(void *_conn)
* secondary_channel has not been released by the handle_chan_nack.
*/
if (conn->secondary_lchan)
- lchan_release(conn->secondary_lchan, 0, 1);
+ lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
conn->secondary_lchan = NULL;
/* inform them about the failure */
@@ -416,7 +416,7 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn,
/* swap channels */
osmo_timer_del(&conn->T10);
- lchan_release(conn->lchan, 0, 1);
+ lchan_release(conn->lchan, 0, RSL_REL_LOCAL_END);
conn->lchan = conn->secondary_lchan;
conn->secondary_lchan = NULL;
@@ -444,7 +444,7 @@ static void handle_ass_fail(struct gsm_subscriber_connection *conn,
/* stop the timer and release it */
osmo_timer_del(&conn->T10);
- lchan_release(conn->secondary_lchan, 0, 1);
+ lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
conn->secondary_lchan = NULL;
gh = msgb_l3(msg);
@@ -649,7 +649,7 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
rc = BSC_API_CONN_POL_REJECT;
lchan->conn = subscr_con_allocate(msg->lchan);
if (!lchan->conn) {
- lchan_release(lchan, 1, 0);
+ lchan_release(lchan, 1, RSL_REL_NORMAL);
return -1;
}
@@ -659,7 +659,7 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
if (rc != BSC_API_CONN_POL_ACCEPT) {
lchan->conn->lchan = NULL;
subscr_con_free(lchan->conn);
- lchan_release(lchan, 1, 0);
+ lchan_release(lchan, 1, RSL_REL_NORMAL);
}
}
@@ -698,10 +698,10 @@ int gsm0808_clear(struct gsm_subscriber_connection *conn)
bsc_clear_handover(conn, 1);
if (conn->secondary_lchan)
- lchan_release(conn->secondary_lchan, 0, 1);
+ lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
if (conn->lchan)
- lchan_release(conn->lchan, 1, 0);
+ lchan_release(conn->lchan, 1, RSL_REL_NORMAL);
conn->lchan = NULL;
conn->secondary_lchan = NULL;
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 69b2625c5..9b59d5df0 100644
--- a/openbsc/src/libbsc/chan_alloc.c
+++ b/openbsc/src/libbsc/chan_alloc.c
@@ -345,8 +345,6 @@ void lchan_free(struct gsm_lchan *lchan)
}
lchan->sacch_deact = 0;
- lchan->release_mode = 0;
-
/* FIXME: ts_free() the timeslot, if we're the last logical
* channel using it */
}
@@ -364,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,63 +375,37 @@ void lchan_reset(struct gsm_lchan *lchan)
}
}
-/* release the next allocated SAPI or return 0 */
-static int _lchan_release_next_sapi(struct gsm_lchan *lchan)
-{
- int sapi;
-
- for (sapi = 1; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
- uint8_t link_id;
- if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
- continue;
-
- link_id = sapi;
- if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
- link_id |= 0x40;
- rsl_release_request(lchan, link_id, lchan->release_mode);
- return 0;
- }
-
- return 1;
-}
-
/* Drive the release process of the lchan */
-static void _lchan_handle_release(struct gsm_lchan *lchan)
+static void _lchan_handle_release(struct gsm_lchan *lchan,
+ int sacch_deact, int mode)
{
- /* Ask for SAPI != 0 to be freed first and stop if we need to wait */
- if (_lchan_release_next_sapi(lchan) == 0)
- return;
-
- if (lchan->sacch_deact) {
+ /* Release all SAPIs on the local end and continue */
+ rsl_release_sapis_from(lchan, 1, RSL_REL_LOCAL_END);
+
+ /*
+ * Shall we send a RR Release, start T3109 and wait for the
+ * release indication from the BTS or just take it down (e.g.
+ * on assignment requests)
+ */
+ if (sacch_deact) {
gsm48_send_rr_release(lchan);
- return;
- }
-
- rsl_release_request(lchan, 0, lchan->release_mode);
- rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
-}
-/* called from abis rsl */
-int rsl_lchan_rll_release(struct gsm_lchan *lchan, uint8_t link_id)
-{
- if (lchan->state != LCHAN_S_REL_REQ)
- return -1;
-
- if ((link_id & 0x7) != 0)
- _lchan_handle_release(lchan);
- return 0;
+ /* 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 */
-int lchan_release(struct gsm_lchan *lchan, int sacch_deact, int mode)
+int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode mode)
{
DEBUGP(DRLL, "%s starting release sequence\n", gsm_lchan_name(lchan));
rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
lchan->conn = NULL;
- lchan->release_mode = mode;
- lchan->sacch_deact = sacch_deact;
- _lchan_handle_release(lchan);
+ _lchan_handle_release(lchan, sacch_deact, mode);
return 1;
}
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,
diff --git a/openbsc/src/libbsc/handover_logic.c b/openbsc/src/libbsc/handover_logic.c
index 5ce33018c..d2cd5efd9 100644
--- a/openbsc/src/libbsc/handover_logic.c
+++ b/openbsc/src/libbsc/handover_logic.c
@@ -167,7 +167,7 @@ void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan)
conn->ho_lchan = NULL;
if (free_lchan)
- lchan_release(ho->new_lchan, 0, 1);
+ lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
osmo_timer_del(&ho->T3103);
llist_del(&ho->list);
@@ -185,7 +185,7 @@ static void ho_T3103_cb(void *_ho)
ho->new_lchan->conn->ho_lchan = NULL;
ho->new_lchan->conn = NULL;
- lchan_release(ho->new_lchan, 0, 1);
+ lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
llist_del(&ho->list);
talloc_free(ho);
}
@@ -276,7 +276,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
ho->old_lchan->conn = NULL;
rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE);
- lchan_release(ho->old_lchan, 0, 1);
+ lchan_release(ho->old_lchan, 0, RSL_REL_LOCAL_END);
/* do something to re-route the actual speech frames ! */
@@ -306,7 +306,7 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
/* release the channel and forget about it */
ho->new_lchan->conn->ho_lchan = NULL;
ho->new_lchan->conn = NULL;
- lchan_release(ho->new_lchan, 0, 1);
+ lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
talloc_free(ho);
diff --git a/openbsc/src/libcommon/gsm_data_shared.c b/openbsc/src/libcommon/gsm_data_shared.c
index eaf53b770..ef29d6a17 100644
--- a/openbsc/src/libcommon/gsm_data_shared.c
+++ b/openbsc/src/libcommon/gsm_data_shared.c
@@ -109,6 +109,7 @@ static const struct value_string lchan_s_names[] = {
{ LCHAN_S_INACTIVE, "INACTIVE" },
{ LCHAN_S_REL_REQ, "RELEASE REQUESTED" },
{ LCHAN_S_REL_ERR, "RELEASE DUE ERROR" },
+ { LCHAN_S_BROKEN, "BROKEN UNUSABLE" },
{ 0, NULL }
};