aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-12-29 17:09:07 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-01-06 14:52:53 +0100
commit49b3ed2226e43b4d8e8d85efafbdcce2ae7f362f (patch)
treea91130a17101190a900b05c5063baa2cd9ebd3a6 /openbsc/src
parent182c81f04e364a947c584c682ba443a3a51ea3f8 (diff)
subscr: Stop stopping paging requests behind the back of subscr
The transaction layer was stopping paging requests that might or might not have been owned by the transaction. This makes the subscr code get stuck delivering requests. This code is mostly a band aid and just makes sure that we will kick the queue if it is needed.
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/gsm_04_08.c39
-rw-r--r--openbsc/src/transaction.c9
2 files changed, 36 insertions, 12 deletions
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index ea11a7109..160f9672c 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -1407,17 +1407,15 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *_conn, void *param)
{
+ int found = 0;
struct gsm_subscriber_connection *conn = _conn;
- struct gsm_subscriber *subscr = param;
+ struct gsm_network **paging_request = param, *net;
struct gsm_trans *transt, *tmp;
- struct gsm_network *net;
if (hooknum != GSM_HOOK_RR_PAGING)
return -EINVAL;
- if (!subscr)
- return -EINVAL;
- net = subscr->net;
+ net = *paging_request;
if (!net) {
DEBUGP(DCC, "Error Network not set!\n");
return -EINVAL;
@@ -1425,16 +1423,18 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
/* check all tranactions (without lchan) for subscriber */
llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
- if (transt->subscr != subscr || transt->conn)
+ if (transt->paging_request != paging_request || transt->conn)
continue;
switch (event) {
case GSM_PAGING_SUCCEEDED:
if (!conn) // paranoid
break;
DEBUGP(DCC, "Paging subscr %s succeeded!\n",
- subscr->extension);
+ transt->subscr->extension);
+ found = 1;
/* Assign lchan */
if (!transt->conn) {
+ transt->paging_request = NULL;
transt->conn = conn;
conn->put_channel = 1;
}
@@ -1444,17 +1444,29 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
case GSM_PAGING_EXPIRED:
case GSM_PAGING_BUSY:
DEBUGP(DCC, "Paging subscr %s expired!\n",
- subscr->extension);
+ transt->subscr->extension);
/* Temporarily out of order */
+ found = 1;
mncc_release_ind(transt->subscr->net, transt,
transt->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_DEST_OOO);
transt->callref = 0;
+ transt->paging_request = NULL;
trans_free(transt);
break;
}
}
+
+ talloc_free(paging_request);
+
+ /*
+ * FIXME: The queue needs to be kicked. This is likely to go through a RF
+ * failure and then the subscr will be poke again. This needs a lot of fixing
+ * in the subscriber queue code.
+ */
+ if (!found && conn)
+ conn->put_channel = 1;
return 0;
}
@@ -3070,7 +3082,16 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
/* Get a channel */
- subscr_get_channel(subscr, RSL_CHANNEED_TCH_F, setup_trig_pag_evt, subscr);
+ trans->paging_request = talloc_zero(subscr->net, struct gsm_network*);
+ if (!trans->paging_request) {
+ LOGP(DCC, LOGL_ERROR, "Failed to allocate paging token.\n");
+ subscr_put(subscr);
+ trans_free(trans);
+ return 0;
+ }
+
+ *trans->paging_request = subscr->net;
+ subscr_get_channel(subscr, RSL_CHANNEED_TCH_F, setup_trig_pag_evt, trans->paging_request);
subscr_put(subscr);
return 0;
diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c
index 09b6ad4a5..9b4af1aac 100644
--- a/openbsc/src/transaction.c
+++ b/openbsc/src/transaction.c
@@ -95,9 +95,12 @@ void trans_free(struct gsm_trans *trans)
break;
}
- if (!trans->conn && trans->subscr && trans->subscr->net) {
- /* Stop paging on all bts' */
- paging_request_stop(NULL, trans->subscr, NULL, NULL);
+ /* FIXME: implement a sane way to stop this. */
+ if (!trans->conn && trans->paging_request) {
+ LOGP(DNM, LOGL_ERROR,
+ "Transaction freed while paging for sub: %llu\n",
+ trans->subscr->id);
+ trans->paging_request = NULL;
}
if (trans->subscr)