diff options
-rw-r--r-- | openbsc/doc/channel_release.txt | 2 | ||||
-rw-r--r-- | openbsc/include/openbsc/bsc_api.h | 1 | ||||
-rw-r--r-- | openbsc/include/openbsc/chan_alloc.h | 4 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 27 | ||||
-rw-r--r-- | openbsc/include/openbsc/osmo_msc.h | 1 | ||||
-rw-r--r-- | openbsc/src/bsc_api.c | 11 | ||||
-rw-r--r-- | openbsc/src/bsc_vty.c | 4 | ||||
-rw-r--r-- | openbsc/src/chan_alloc.c | 51 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08.c | 24 | ||||
-rw-r--r-- | openbsc/src/gsm_04_11.c | 5 | ||||
-rw-r--r-- | openbsc/src/gsm_subscriber_base.c | 2 | ||||
-rw-r--r-- | openbsc/src/handover_logic.c | 3 | ||||
-rw-r--r-- | openbsc/src/osmo_msc.c | 28 | ||||
-rw-r--r-- | openbsc/src/silent_call.c | 4 | ||||
-rw-r--r-- | openbsc/src/transaction.c | 17 |
15 files changed, 78 insertions, 106 deletions
diff --git a/openbsc/doc/channel_release.txt b/openbsc/doc/channel_release.txt index bacf09c8d..a10e9d50f 100644 --- a/openbsc/doc/channel_release.txt +++ b/openbsc/doc/channel_release.txt @@ -31,6 +31,8 @@ GSM 04.08 3.4.13: RR connection release procedure == Implementation in OpenBSC == +THIS IS OUTDATED and will be updated... + chan_alloc.c:lchan_auto_release() * checks if use count still > 0 (abort) * calls gsm48_send_rr_release() diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h index e92da216a..da942d268 100644 --- a/openbsc/include/openbsc/bsc_api.h +++ b/openbsc/include/openbsc/bsc_api.h @@ -28,5 +28,6 @@ int bsc_api_init(struct gsm_network *network, struct bsc_api *api); int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id); int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_len, uint8_t *mi, int chan_type); +int gsm0808_clear(struct gsm_subscriber_connection *conn); #endif diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h index bbbe5362a..3afcb3c47 100644 --- a/openbsc/include/openbsc/chan_alloc.h +++ b/openbsc/include/openbsc/chan_alloc.h @@ -46,8 +46,8 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type); void lchan_free(struct gsm_lchan *lchan); void lchan_reset(struct gsm_lchan *lchan); -/* Consider releasing the channel */ -int lchan_auto_release(struct gsm_lchan *lchan); +/* Release the given lchan */ +int lchan_release(struct gsm_lchan *lchan, int sach_deact, int reason); struct load_counter { unsigned int total; diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index b1091cdb2..491cca12a 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -120,26 +120,6 @@ typedef int gsm_cbfn(unsigned int hooknum, struct msgb *msg, void *data, void *param); -/* - * Use the channel. As side effect the lchannel recycle timer - * will be started. - */ -#define LCHAN_RELEASE_TIMEOUT 20, 0 -#define use_subscr_con(con) \ - do { (con)->use_count++; \ - DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \ - (con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \ - (con)->lchan->nr, (con)->use_count); \ - bsc_schedule_timer(&(con)->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0); - -#define put_subscr_con(con) \ - do { (con)->use_count--; \ - DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \ - (con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \ - (con)->lchan->nr, (con)->use_count); \ - } while(0); - - /* Real authentication information containing Ki */ enum gsm_auth_algo { AUTH_ALGO_NONE, @@ -239,22 +219,17 @@ struct gsm_subscriber_connection { /* To whom we are allocated at the moment */ struct gsm_subscriber *subscr; - /* Timer started to release the channel */ - struct timer_list release_timer; - /* * Operations that have a state and might be pending */ struct gsm_loc_updating_operation *loc_operation; struct gsm_security_operation *sec_operation; - /* use count. how many users use this channel */ - unsigned int use_count; - /* Are we part of a special "silent" call */ int silent_call; /* back pointers */ + int in_release; struct gsm_lchan *lchan; struct gsm_bts *bts; }; diff --git a/openbsc/include/openbsc/osmo_msc.h b/openbsc/include/openbsc/osmo_msc.h index d5d8917df..beb3f5e4c 100644 --- a/openbsc/include/openbsc/osmo_msc.h +++ b/openbsc/include/openbsc/osmo_msc.h @@ -6,5 +6,6 @@ #include "bsc_api.h" struct bsc_api *msc_bsc_api(); +void msc_release_connection(struct gsm_subscriber_connection *conn); #endif diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c index 92fe66118..46a3343e0 100644 --- a/openbsc/src/bsc_api.c +++ b/openbsc/src/bsc_api.c @@ -104,13 +104,20 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id) if (rc != BSC_API_CONN_POL_ACCEPT) { subscr_con_free(lchan->conn); - lchan_auto_release(lchan); + lchan_release(lchan, 0, 0); } } return 0; } +int gsm0808_clear(struct gsm_subscriber_connection* conn) +{ + subscr_con_free(conn); + lchan_release(conn->lchan, 1, 0); + return 0; +} + static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id) { struct bsc_api *api; @@ -155,12 +162,12 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal, if (!lchan || !lchan->conn) return 0; - bsc = lchan->ts->trx->bts->network->bsc_api; if (!bsc || !bsc->clear_request) return 0; bsc->clear_request(lchan->conn, 0); + subscr_con_free(lchan->conn); return 0; } diff --git a/openbsc/src/bsc_vty.c b/openbsc/src/bsc_vty.c index 321574504..a308ec475 100644 --- a/openbsc/src/bsc_vty.c +++ b/openbsc/src/bsc_vty.c @@ -700,8 +700,8 @@ static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan) lchan->nr, lchan->ts->nr, lchan->ts->trx->nr, lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE); - vty_out(vty, " Use Count: %u, State: %s%s", - lchan->conn ? lchan->conn->use_count : -23, + vty_out(vty, " Connection: %u, State: %s%s", + lchan->conn ? 1: 0, gsm_lchans_name(lchan->state), VTY_NEWLINE); vty_out(vty, " BS Power: %u dBm, MS Power: %u dBm%s", lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index f5c4ec65e..62d476ad9 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -35,8 +35,6 @@ #include <osmocore/talloc.h> -static void auto_release_channel(void *_lchan); - static int ts_is_usable(struct gsm_bts_trx_ts *ts) { /* FIXME: How does this behave for BS-11 ? */ @@ -296,18 +294,8 @@ void lchan_free(struct gsm_lchan *lchan) if (lchan->conn) { - if (lchan->conn->subscr) { - subscr_put(lchan->conn->subscr); - lchan->conn->subscr = NULL; - } - /* We might kill an active channel... */ - if (lchan->conn->use_count != 0) { - dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); - lchan->conn->use_count = 0; - } - /* stop the timer */ - bsc_del_timer(&lchan->conn->release_timer); + dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); } @@ -334,6 +322,7 @@ void lchan_free(struct gsm_lchan *lchan) dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig); if (lchan->conn) { + LOGP(DRLL, LOGL_ERROR, "the subscriber connection should be gone.\n"); subscr_con_free(lchan->conn); lchan->conn = NULL; } @@ -364,40 +353,19 @@ void lchan_reset(struct gsm_lchan *lchan) /* Consider releasing the channel now */ -int lchan_auto_release(struct gsm_lchan *lchan) +int lchan_release(struct gsm_lchan *lchan, int sach_deact, int reason) { - if (!lchan->conn) - return 0; - - if (lchan->conn->use_count > 0) { - return 0; - } - /* Assume we have GSM04.08 running and send a release */ - if (lchan->conn->subscr) { + if (sach_deact) { gsm48_send_rr_release(lchan); } - /* spoofed? message */ - if (lchan->conn->use_count < 0) - LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n", - lchan->conn->use_count); - DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ); rsl_release_request(lchan, 0, 0); return 1; } -/* Auto release the channel when the use count is zero */ -static void auto_release_channel(void *_lchan) -{ - struct gsm_lchan *lchan = _lchan; - - if (!lchan_auto_release(lchan)) - bsc_schedule_timer(&lchan->conn->release_timer, LCHAN_RELEASE_TIMEOUT); -} - static struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { struct gsm_bts_trx *trx; int ts_no, lchan_no; @@ -490,10 +458,6 @@ struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan) /* Configure the time and start it so it will be closed */ conn->lchan = lchan; conn->bts = lchan->ts->trx->bts; - conn->release_timer.cb = auto_release_channel; - conn->release_timer.data = lchan; - bsc_schedule_timer(&conn->release_timer, LCHAN_RELEASE_TIMEOUT); - lchan->conn = conn; return conn; } @@ -507,6 +471,13 @@ void subscr_con_free(struct gsm_subscriber_connection *conn) if (!conn) return; + + if (conn->subscr) { + subscr_put(conn->subscr); + conn->subscr = NULL; + } + + lchan = conn->lchan; talloc_free(conn); diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index e8070522d..c1b438ef5 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -109,13 +109,11 @@ static void release_security_operation(struct gsm_subscriber_connection *conn) talloc_free(conn->sec_operation); conn->sec_operation = NULL; - put_subscr_con(conn); + msc_release_connection(conn); } static void allocate_security_operation(struct gsm_subscriber_connection *conn) { - use_subscr_con(conn) - conn->sec_operation = talloc_zero(tall_authciphop_ctx, struct gsm_security_operation); } @@ -222,12 +220,13 @@ static void release_loc_updating_req(struct gsm_subscriber_connection *conn) bsc_del_timer(&conn->loc_operation->updating_timer); talloc_free(conn->loc_operation); conn->loc_operation = 0; - put_subscr_con(conn); + msc_release_connection(conn); } static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn) { - use_subscr_con(conn) + if (conn->loc_operation) + LOGP(DMM, LOGL_ERROR, "Connection already had operation.\n"); release_loc_updating_req(conn); conn->loc_operation = talloc_zero(tall_locop_ctx, @@ -263,7 +262,6 @@ static int _gsm0408_authorize_sec_cb(unsigned int hooknum, unsigned int event, /* try to close channel ASAP */ release_loc_updating_req(conn); - lchan_auto_release(conn->lchan); break; default: @@ -285,6 +283,10 @@ static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb void gsm0408_clear_request(struct gsm_subscriber_connection* conn, uint32_t cause) { struct gsm_trans *trans, *temp; + + /* avoid someone issuing a clear */ + conn->in_release = 1; + /* * Cancel any outstanding location updating request * operation taking place on the subscriber connection. @@ -424,7 +426,6 @@ static void loc_upd_rej_cb(void *data) gsm0408_loc_upd_rej(conn, bts->network->reject_cause); release_loc_updating_req(conn); - lchan_auto_release(lchan); } static void schedule_reject(struct gsm_subscriber_connection *conn) @@ -710,7 +711,6 @@ static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value); msg->lchan = conn->lchan; - use_subscr_con(conn); return gsm48_conn_sendmsg(msg, conn, NULL); } @@ -871,8 +871,6 @@ static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg) * imagine an IMSI DETACH happening during an active call! */ /* subscriber is detached: should we release lchan? */ - lchan_auto_release(msg->lchan); - return 0; } @@ -1385,7 +1383,6 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, /* Assign lchan */ if (!transt->conn) { transt->conn = conn; - use_subscr_con(transt->conn); } /* send SETUP request to called party */ gsm48_cc_tx_setup(transt, &transt->cc.msg); @@ -2289,9 +2286,6 @@ static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg) case GSM_CSTATE_RELEASE_REQ: rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel); - /* FIXME: in case of multiple calls, we can't simply - * hang up here ! */ - lchan_auto_release(msg->lchan); break; default: rc = mncc_recvmsg(trans->subscr->net, trans, @@ -2924,7 +2918,6 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) } /* Assign lchan */ trans->conn = conn; - use_subscr_con(trans->conn); subscr_put(subscr); } @@ -3065,7 +3058,6 @@ static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *m } /* Assign transaction */ trans->conn = conn; - use_subscr_con(trans->conn); } /* find function for current state and message */ diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index d4df989d1..6cce57db1 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -943,7 +943,6 @@ int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, trans->sms.link_id = UM_SAPI_SMS; trans->conn = conn; - use_subscr_con(trans->conn); } switch(msg_type) { @@ -1066,7 +1065,6 @@ static int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sm trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */ trans->conn = conn; - use_subscr_con(trans->conn); /* Hardcode SMSC Originating Address for now */ data = (u_int8_t *)msgb_put(msg, 8); @@ -1122,7 +1120,6 @@ static int paging_cb_send_sms(unsigned int hooknum, unsigned int event, switch (event) { case GSM_PAGING_SUCCEEDED: - use_subscr_con(conn); gsm411_send_sms(conn, sms); break; case GSM_PAGING_EXPIRED: @@ -1147,7 +1144,6 @@ int gsm411_send_sms_subscr(struct gsm_subscriber *subscr, * if yes, send the SMS this way */ conn = connection_for_subscr(subscr); if (conn) { - use_subscr_con(conn); return gsm411_send_sms(conn, sms); } @@ -1174,7 +1170,6 @@ static int subscr_sig_cb(unsigned int subsys, unsigned int signal, sms = db_sms_get_unsent_for_subscr(subscr); if (!sms) break; - use_subscr_con(conn); gsm411_send_sms(conn, sms); break; default: diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c index 264f12855..50e6865bf 100644 --- a/openbsc/src/gsm_subscriber_base.c +++ b/openbsc/src/gsm_subscriber_base.c @@ -205,8 +205,6 @@ void subscr_put_channel(struct gsm_subscriber_connection *conn) * will listen to the paging requests before we timeout */ - put_subscr_con(conn); - if (conn->subscr && !llist_empty(&conn->subscr->requests)) subscr_send_paging_request(conn->subscr); } diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c index b75dc98ba..baf03b34b 100644 --- a/openbsc/src/handover_logic.c +++ b/openbsc/src/handover_logic.c @@ -231,7 +231,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) trans_lchan_change(ho->old_lchan->conn, new_lchan->conn); rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE); - lchan_auto_release(ho->old_lchan); + lchan_release(ho->old_lchan, 0, 1); /* do something to re-route the actual speech frames ! */ @@ -259,7 +259,6 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan) bsc_del_timer(&ho->T3103); llist_del(&ho->list); conn = ho->new_lchan->conn; - put_subscr_con(conn); talloc_free(ho); return 0; diff --git a/openbsc/src/osmo_msc.c b/openbsc/src/osmo_msc.c index 569634d55..6a94e7abb 100644 --- a/openbsc/src/osmo_msc.c +++ b/openbsc/src/osmo_msc.c @@ -24,6 +24,7 @@ #include <openbsc/bsc_api.h> #include <openbsc/debug.h> +#include <openbsc/transaction.h> #include <openbsc/gsm_04_11.h> @@ -64,3 +65,30 @@ static struct bsc_api msc_handler = { struct bsc_api *msc_bsc_api() { return &msc_handler; } + +/* lchan release handling */ +void msc_release_connection(struct gsm_subscriber_connection *conn) +{ + struct gsm_trans *trans; + + /* skip when we are in release, e.g. due an error */ + if (conn->in_release) + return; + + /* skip releasing of silent calls as they have no transaction */ + if (conn->silent_call) + return; + + /* check if there is a pending operation */ + if (conn->loc_operation || conn->sec_operation) + return; + + llist_for_each_entry(trans, &conn->bts->network->trans_list, entry) { + if (trans->conn == conn) + return; + } + + /* no more connections, asking to release the channel */ + conn->in_release = 1; + gsm0808_clear(conn); +} diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c index 397a3e4b9..7ba451b65 100644 --- a/openbsc/src/silent_call.c +++ b/openbsc/src/silent_call.c @@ -57,7 +57,6 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event, conn->silent_call = 1; /* increment lchan reference count */ dispatch_signal(SS_SCALL, S_SCALL_SUCCESS, &sigdata); - use_subscr_con(conn); break; case GSM_PAGING_EXPIRED: DEBUGP(DSMS, "expired\n"); @@ -135,7 +134,8 @@ int gsm_silent_call_stop(struct gsm_subscriber *subscr) if (!conn->silent_call) return -EINVAL; - put_subscr_con(conn); + conn->silent_call = 0; + msc_release_connection(conn); return 0; } diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c index c7478d668..ffabdd316 100644 --- a/openbsc/src/transaction.c +++ b/openbsc/src/transaction.c @@ -95,9 +95,6 @@ void trans_free(struct gsm_trans *trans) break; } - if (trans->conn) - put_subscr_con(trans->conn); - if (!trans->conn && trans->subscr && trans->subscr->net) { /* Stop paging on all bts' */ paging_request_stop(NULL, trans->subscr, NULL); @@ -108,6 +105,10 @@ void trans_free(struct gsm_trans *trans) llist_del(&trans->entry); + if (trans->conn) + msc_release_connection(trans->conn); + + talloc_free(trans); } @@ -155,15 +156,17 @@ int trans_lchan_change(struct gsm_subscriber_connection *conn_old, struct gsm_trans *trans; int num = 0; + if (conn_old == conn_new) { + LOGP(DCC, LOGL_ERROR, "Exchanging transaction with itself.\n"); + return; + } + llist_for_each_entry(trans, &net->trans_list, entry) { if (trans->conn == conn_old) { + msc_release_connection(conn_old); - /* drop old channel use count */ - put_subscr_con(conn_old); /* assign new channel */ trans->conn = conn_new; - /* bump new channel use count */ - use_subscr_con(conn_new); num++; } } |