diff options
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/libmsc/gsm_04_08.c | 8 | ||||
-rw-r--r-- | openbsc/src/libmsc/gsm_subscriber.c | 106 |
2 files changed, 82 insertions, 32 deletions
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index cf16fcc35..31633f131 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1157,7 +1157,7 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m classmark_is_r99(&conn->classmark), conn->via_ran == RAN_UTRAN_IU); - return rc; + return 0; } static int gsm48_rx_rr_app_info(struct gsm_subscriber_connection *conn, struct msgb *msg) @@ -3440,13 +3440,11 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) trans_free(trans); return 0; } - /* store setup informations until paging was successfull */ + /* store setup information until paging succeeds */ memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc)); /* Request a channel */ - trans->paging_request = subscr_request_channel( - vsub, - RSL_CHANNEED_TCH_F, + trans->paging_request = subscr_request_conn(subscr, setup_trig_pag_evt, trans); if (!trans->paging_request) { diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index 9a6c7a871..63e8fdcdf 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -59,10 +59,7 @@ static struct bsc_subscr *vlr_subscr_to_bsc_sub(struct llist_head *bsc_subscribe return sub; } -/* - * We got the channel assigned and can now hand this channel - * over to one of our callbacks. - */ +/* A connection is established and the paging callbacks may run now. */ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, struct msgb *msg, void *data, void *param) { @@ -73,12 +70,25 @@ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, struct bsc_subscr *bsub; struct gsm_network *net; - OSMO_ASSERT(vsub && vsub->cs.is_paging); + OSMO_ASSERT(vsub); net = vsub->vlr->user_ctx; + OSMO_ASSERT(hooknum == GSM_HOOK_RR_PAGING); + OSMO_ASSERT(!(conn && (conn->vsub != vsub))); + OSMO_ASSERT(!((event == GSM_PAGING_SUCCEEDED) && !conn)); + + LOGP(DPAG, LOGL_DEBUG, "Paging %s for %s (event=%d)\n", + event == GSM_PAGING_SUCCEEDED ? "success" : "failure", + subscr_name(subscr), event); + + if (!subscr->is_paging) { + LOGP(DPAG, LOGL_ERROR, + "Paging Response received for subscriber" + " that is not paging.\n"); + return -EINVAL; + } /* Inform parts of the system we don't know */ sig_data.vsub = vsub; - sig_data.bts = conn ? conn->bts : NULL; sig_data.conn = conn; sig_data.paging_result = event; osmo_signal_dispatch( @@ -90,7 +100,11 @@ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, llist_for_each_entry_safe(request, tmp, &vsub->cs.requests, entry) { llist_del(&request->entry); - request->cbfn(hooknum, event, msg, data, request->param); + if (request->cbfn) { + LOGP(DPAG, LOGL_DEBUG, "Calling paging cbfn.\n"); + request->cbfn(hooknum, event, msg, data, request->param); + } else + LOGP(DPAG, LOGL_DEBUG, "Paging without action.\n"); talloc_free(request); } @@ -100,28 +114,59 @@ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, return 0; } +static void paging_timeout_release(struct gsm_subscriber *subscr) +{ + DEBUGP(DPAG, "Paging timeout released for %s\n", subscr_name(subscr)); + osmo_timer_del(&subscr->paging_timeout); +} + +static void paging_timeout(void *data) +{ + struct gsm_subscriber *subscr = data; + DEBUGP(DPAG, "Paging timeout reached for %s\n", subscr_name(subscr)); + paging_timeout_release(subscr); + subscr_paging_dispatch(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, + NULL, NULL, subscr); +} + +static void paging_timeout_start(struct gsm_subscriber *subscr) +{ + DEBUGP(DPAG, "Starting paging timeout for %s\n", subscr_name(subscr)); + subscr->paging_timeout.data = subscr; + subscr->paging_timeout.cb = paging_timeout; + osmo_timer_schedule(&subscr->paging_timeout, 10, 0); + /* TODO: configurable timeout duration? */ +} + + static int subscr_paging_sec_cb(unsigned int hooknum, unsigned int event, struct msgb *msg, void *data, void *param) { int rc; + struct gsm_subscriber_connection *conn = data; + OSMO_ASSERT(conn); switch (event) { case GSM_SECURITY_AUTH_FAILED: - /* Dispatch as paging failure */ + LOGP(DPAG, LOGL_ERROR, + "Dropping Paging Response:" + " authorization failed for subscriber %s\n", + subscr_name(conn->subscr)); rc = subscr_paging_dispatch( GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, - msg, data, param); + msg, conn, conn->subscr); break; case GSM_SECURITY_NOAVAIL: case GSM_SECURITY_SUCCEEDED: - /* Dispatch as paging failure */ rc = subscr_paging_dispatch( GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED, - msg, data, param); + msg, conn, conn->subscr); break; default: + LOGP(DPAG, LOGL_FATAL, + "Invalid authorization event: %d\n", event); rc = -EINVAL; } @@ -138,6 +183,8 @@ int subscr_rx_paging_response(struct msgb *msg, gh = msgb_l3(msg); pr = (struct gsm48_pag_resp *)gh->data; + paging_timeout_release(conn->subscr); + /* Secure the connection */ if (subscr_authorized(conn->subscr)) return gsm48_secure_channel(conn, pr->key_seq, @@ -149,9 +196,21 @@ int subscr_rx_paging_response(struct msgb *msg, return -1; } -struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub, - int channel_type, - gsm_cbfn *cbfn, void *param) +static int msc_paging_request(struct gsm_subscriber *subscr) +{ + /* The subscriber was last seen in subscr->lac. Find out which + * BSCs/RNCs are responsible and send them a paging request via open + * SCCP connections (if any). */ + /* TODO Implementing only RNC paging, since this is code on the iu branch. + * Need to add BSC paging at some point. */ + return iu_page_cs(subscr->imsi, + subscr->tmsi == GSM_RESERVED_TMSI? + NULL : &subscr->tmsi, + subscr->lac); +} + +struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub, + gsm_cbfn *cbfn, void *param) { int rc; struct subscr_request *request; @@ -159,20 +218,10 @@ struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub, struct gsm_network *net = vsub->vlr->user_ctx; /* Start paging.. we know it is async so we can do it before */ - if (!vsub->cs.is_paging) { - LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet.\n", + if (!subscr->is_paging) { + LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet, start paging.\n", vlr_subscr_name(vsub)); -#if 0 - TODO implement paging response in libmsc! - Excluding this to be able to link without libbsc: - - bsub = vlr_subscr_to_bsc_sub(net->bsc_subscribers, vsub); - rc = paging_request(net, bsub, channel_type, subscr_paging_cb, - vsub); - bsc_subscr_put(bsub); -#else - rc = -ENOTSUP; -#endif + rc = msc_paging_request(vsub); if (rc <= 0) { LOGP(DMM, LOGL_ERROR, "Subscriber %s paging failed: %d\n", vlr_subscr_name(vsub), rc); @@ -181,6 +230,9 @@ struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub, /* reduced on the first paging callback */ vlr_subscr_get(vsub); vsub->cs.is_paging = true; + } else { + LOGP(DMM, LOGL_DEBUG, "Subscriber %s already paged.\n", + subscr_name(subscr)); } /* TODO: Stop paging in case of memory allocation failure */ |