From 63b99ced83773d92310211d557009e1c8cc4faf4 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Tue, 22 Mar 2016 19:26:52 +0100 Subject: add preliminary paging response handling, incomplete In gsm_04_08.c, add a static handle_paging_resp() to take over from the libbsc function gsm48_handle_paging_resp(). Use the subscr->requests listing to handle a Paging Response and call the pending cbfn. In NITB, this used to be done via BTS, and I haven't entirely resolved yet how exactly to rewire this in standalone libmsc. So far, this "works for me", but is worth another visit. Still missing: enable Integrity Protection. --- openbsc/include/openbsc/gsm_subscriber.h | 14 +++++++++ openbsc/src/libmsc/gsm_04_08.c | 50 ++++++++++++++++++++++++++++---- openbsc/src/libmsc/gsm_subscriber.c | 14 --------- 3 files changed, 59 insertions(+), 19 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index 88c36e7a9..151f3dd0e 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -88,6 +88,20 @@ enum gsm_subscriber_update_reason { GSM_SUBSCRIBER_UPDATE_EQUIPMENT, }; +/* + * Struct for pending channel requests. This is managed in the + * llist_head requests of each subscriber. The reference counting + * should work in such a way that a subscriber with a pending request + * remains in memory. + */ +struct subscr_request { + struct llist_head entry; + + /* the callback data */ + gsm_cbfn *cbfn; + void *param; +}; + struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp, diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 897f97271..cccb8f717 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1245,6 +1245,47 @@ static int gsm0408_rcv_mm(struct gsm_subscriber_connection *conn, struct msgb *m return rc; } +static int handle_paging_resp(struct gsm_subscriber_connection *conn, + struct msgb *msg, struct gsm_subscriber *subscr) +{ + struct subscr_request *req, *req2; + + if (!conn->subscr) { + conn->subscr = subscr; + } else if (conn->subscr != subscr) { + LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n"); + subscr_put(subscr); + return -EINVAL; + } else { + DEBUGP(DRR, "<- Channel already owned by us\n"); + subscr_put(subscr); + subscr = conn->subscr; + } + + osmo_counter_inc(conn->network->stats.paging.completed); + + if (!subscr->is_paging) { + LOGP(DRR, LOGL_ERROR, "Paging Response received for subscriber that is not paging\n"); + return -1; + } + + llist_for_each_entry_safe(req, req2, &subscr->requests, entry) { + gsm_cbfn *cbfn = req->cbfn; + void *param = req->param; + + llist_del(&req->entry); + req = NULL; + + if (conn && cbfn) { + LOGP(DPAG, LOGL_DEBUG, "Calling paging cbfn.\n"); + cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED, + msg, conn, param); + } else + LOGP(DPAG, LOGL_DEBUG, "Paging without action.\n"); + } + return 0; +} + /* Receive a PAGING RESPONSE message from the MS */ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct msgb *msg) { @@ -1254,7 +1295,6 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m uint8_t mi_type; char mi_string[GSM48_MI_SIZE]; struct gsm_subscriber *subscr = NULL; - int rc = 0; resp = (struct gsm48_pag_resp *) &gh->data[0]; gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh), @@ -1289,12 +1329,12 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m /* We received a paging */ conn->expire_timer_stopped = 1; + /* FIXME start Integrity Protection in Iu mode */ + #if BEFORE_MSCSPLIT - rc = gsm48_handle_paging_resp(conn, msg, subscr); - return rc; + return gsm48_handle_paging_resp(conn, msg, subscr); #else - LOGP(DRR, LOGL_ERROR, "MSC wants to tell BSC to gsm48_handle_paging_resp() but A-interface not implemented\n"); - return -1; + return handle_paging_resp(conn, msg, subscr); #endif } diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index 2fd9932e5..cb9303c95 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -48,20 +48,6 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, gsm_cbfn *cb, void *cb_data); -/* - * Struct for pending channel requests. This is managed in the - * llist_head requests of each subscriber. The reference counting - * should work in such a way that a subscriber with a pending request - * remains in memory. - */ -struct subscr_request { - struct llist_head entry; - - /* the callback data */ - gsm_cbfn *cbfn; - void *param; -}; - static struct gsm_subscriber *get_subscriber(struct gsm_subscriber_group *sgrp, int type, const char *ident) { -- cgit v1.2.3