diff options
-rw-r--r-- | openbsc/doc/channel_release.txt | 20 | ||||
-rw-r--r-- | openbsc/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg | 2 | ||||
-rw-r--r-- | openbsc/doc/examples/osmo-nitb/hsl/openbsc.cfg | 2 | ||||
-rw-r--r-- | openbsc/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg | 2 | ||||
-rw-r--r-- | openbsc/doc/examples/osmo-nitb/nanobts/openbsc.cfg | 2 | ||||
-rw-r--r-- | openbsc/doc/examples/osmo-nitb/rbs2308/openbsc.cfg | 2 | ||||
-rw-r--r-- | openbsc/include/openbsc/abis_rsl.h | 9 | ||||
-rw-r--r-- | openbsc/include/openbsc/chan_alloc.h | 2 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data_shared.h | 6 | ||||
-rw-r--r-- | openbsc/src/libbsc/abis_rsl.c | 152 | ||||
-rw-r--r-- | openbsc/src/libbsc/bsc_api.c | 14 | ||||
-rw-r--r-- | openbsc/src/libbsc/bsc_vty.c | 2 | ||||
-rw-r--r-- | openbsc/src/libbsc/chan_alloc.c | 67 | ||||
-rw-r--r-- | openbsc/src/libbsc/gsm_04_08_utils.c | 6 | ||||
-rw-r--r-- | openbsc/src/libbsc/handover_logic.c | 8 | ||||
-rw-r--r-- | openbsc/src/libcommon/gsm_data_shared.c | 1 |
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 } }; |