Hey,
I had some time during a train ride to do some updates to the existing patch set. I have merged the hopefully non controversial parts already and would like to share the current set with you.
What is missing: - There are still plenty of FIXMEs and the channel allocation is pretty stupid. One request after another, no attempt to do GSM submit and call handling at the same time... we just release the channel and start paging again.
- VLR handling in db.c (remember where the subscriber was and load it....)
- Testing, I have not seen a powered up Siemens BS11 lately and need to test
What is there:
- Having two requests (SMS submit and Phone) should work in a way... and the API should be "finished".
feedback is welcomed z.
From 890b5c3c519dcbbcb140284b1e68b22b8ae71532 Mon Sep 17 00:00:00 2001 From: Holger Freyther <ich@tamarin.(none)> Date: Tue, 31 Mar 2009 04:35:19 +0200 Subject: [PATCH] Proposal for a "channel request" interface...
Reuqests for a subscriber a stored within the gsm_subscriber datastructure and it will keep track how many channels are allocated for this user and of which type to decide on policy...
e.g. attempt to submit SMS during a phone call and not doing paging but a simple (immediate) assignment of the channel... --- include/openbsc/gsm_subscriber.h | 5 +++++ src/gsm_04_08.c | 2 +- src/gsm_subscriber.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletions(-)
diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h index 7da896e..52c2c66 100644 --- a/include/openbsc/gsm_subscriber.h +++ b/include/openbsc/gsm_subscriber.h @@ -24,6 +24,9 @@ struct gsm_subscriber { int use_count; struct llist_head entry; struct gsm_bts *current_bts; + + /* pending requests */ + struct llist_head requests; };
enum gsm_subscriber_field { @@ -44,6 +47,8 @@ struct gsm_subscriber *subscr_get_by_imsi(const char *imsi); struct gsm_subscriber *subscr_get_by_extension(const char *ext); int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason); void subscr_put_channel(struct gsm_lchan *lchan); +void subscr_get_channel(struct gsm_subscriber *subscr, int type, + gsm_cbfn *cbfn, void *data);
/* internal */ struct gsm_subscriber *subscr_alloc(void); diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c index 85af502..7a941b9 100644 --- a/src/gsm_04_08.c +++ b/src/gsm_04_08.c @@ -1098,7 +1098,7 @@ static int gsm48_cc_rx_setup(struct msgb *msg) call->called_subscr = called_subscr;
/* start paging of the receiving end of the call */ - paging_request(msg->trx->bts, called_subscr, RSL_CHANNEED_TCH_F, + subscr_get_channel(called_subscr, RSL_CHANNEED_TCH_F, setup_trig_pag_evt, call);
/* send a CALL PROCEEDING message to the MO */ diff --git a/src/gsm_subscriber.c b/src/gsm_subscriber.c index 0c2dd7c..bfb4983 100644 --- a/src/gsm_subscriber.c +++ b/src/gsm_subscriber.c @@ -44,6 +44,8 @@ struct gsm_subscriber *subscr_alloc(void) llist_add_tail(&s->entry, &active_subscribers); s->use_count = 1;
+ INIT_LLIST_HEAD(&s->requests); + return s; }
@@ -123,6 +125,16 @@ struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr) return NULL; }
+void subscr_get_channel(struct gsm_subscriber *subscr, int type, + gsm_cbfn *cbfn, void *data) +{ + /* current_bts is the current VLR of the MobileStation */ + if (!subscr->current_bts) + return; + + paging_request(subscr->current_bts, subscr, type, cbfn, data); +} + void subscr_put_channel(struct gsm_lchan *lchan) { /*
From dbc38882d295bdd50912ba33f544a7202f5907e6 Mon Sep 17 00:00:00 2001 From: Holger Freyther <ich@tamarin.(none)> Date: Sun, 5 Apr 2009 14:36:33 +0200 Subject: [PATCH] [paging] Immediately fail if we don't have something like a VLR
If we don't know where to search for a GSM subscriber then do not try to page it at all. Introduce an enum value for this and call the callback from within the get_channel request. --- include/openbsc/gsm_data.h | 1 + src/gsm_subscriber.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h index 6c08b03..21b05ea 100644 --- a/include/openbsc/gsm_data.h +++ b/include/openbsc/gsm_data.h @@ -24,6 +24,7 @@ enum gsm_hooks { enum gsm_paging_event { GSM_PAGING_SUCCEEDED, GSM_PAGING_EXPIRED, + GSM_PAGING_VLR_UNKNOWN, };
struct msgb; diff --git a/src/gsm_subscriber.c b/src/gsm_subscriber.c index bfb4983..3082880 100644 --- a/src/gsm_subscriber.c +++ b/src/gsm_subscriber.c @@ -129,8 +129,12 @@ void subscr_get_channel(struct gsm_subscriber *subscr, int type, gsm_cbfn *cbfn, void *data) { /* current_bts is the current VLR of the MobileStation */ - if (!subscr->current_bts) + if (!subscr->current_bts) { + if (cbfn) + cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_VLR_UNKNOWN, + NULL, NULL, data); return; + }
paging_request(subscr->current_bts, subscr, type, cbfn, data); }
From 6e7180aba476679428db7444341d1de77b7b2a6f Mon Sep 17 00:00:00 2001 From: Holger Freyther <ich@tamarin.(none)> Date: Sat, 18 Apr 2009 13:48:55 +0200 Subject: [PATCH] [channel] Handle and dispatch paging requests in gsm_subscriber
Implement subscr_get_channel to a degree that a pending SMS Submit and a phone call should work. --- include/openbsc/gsm_data.h | 1 + include/openbsc/gsm_subscriber.h | 1 + src/gsm_subscriber.c | 106 +++++++++++++++++++++++++++++++++++++- 3 files changed, 106 insertions(+), 2 deletions(-)
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h index 21b05ea..44bf340 100644 --- a/include/openbsc/gsm_data.h +++ b/include/openbsc/gsm_data.h @@ -25,6 +25,7 @@ enum gsm_paging_event { GSM_PAGING_SUCCEEDED, GSM_PAGING_EXPIRED, GSM_PAGING_VLR_UNKNOWN, + GSM_PAGING_OOM, };
struct msgb; diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h index 52c2c66..8ea6bdd 100644 --- a/include/openbsc/gsm_subscriber.h +++ b/include/openbsc/gsm_subscriber.h @@ -26,6 +26,7 @@ struct gsm_subscriber { struct gsm_bts *current_bts;
/* pending requests */ + int in_callback; struct llist_head requests; };
diff --git a/src/gsm_subscriber.c b/src/gsm_subscriber.c index 3082880..0464102 100644 --- a/src/gsm_subscriber.c +++ b/src/gsm_subscriber.c @@ -25,13 +25,71 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <assert.h>
#include <openbsc/gsm_subscriber.h> +#include <openbsc/paging.h> #include <openbsc/db.h>
- LLIST_HEAD(active_subscribers);
+/* + * 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; + + /* back reference */ + struct gsm_subscriber *subscr; + + /* the requested channel type */ + int channel_type; + + /* the callback data */ + gsm_cbfn *cbfn; + void *data; +}; + +/* + * We got the channel assigned and can now hand this channel + * over to one of our callbacks. + */ +static void subscr_paging_cb(unsigned int hooknum, unsigned int event, + struct msgb *msg, void *data, void *param) +{ + struct subscr_request *request; + struct gsm_subscriber *subscr = (struct gsm_subscriber *)data; + + assert(!llist_empty(&subscr->requests)); + + /* + * FIXME: What to do with paging requests coming during + * this callback? We must be sure to not start paging when + * we have an active connection to a subscriber and to make + * the subscr_put_channel work as required... + */ + request = (struct subscr_request *)subscr->requests.next; + llist_del(&request->entry); + subscr->in_callback = 1; + request->cbfn(hooknum, event, msg, request->data, param); + subscr->in_callback = 0; + + free(request); +} + +static void subscr_send_paging_request(struct gsm_subscriber *subscr) +{ + struct subscr_request *request; + assert(!llist_empty(&subscr->requests)); + + request = (struct subscr_request *)subscr->requests.next; + paging_request(subscr->current_bts, subscr, request->channel_type, + subscr_paging_cb, subscr); +} + struct gsm_subscriber *subscr_alloc(void) { struct gsm_subscriber *s; @@ -128,6 +186,8 @@ struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr) void subscr_get_channel(struct gsm_subscriber *subscr, int type, gsm_cbfn *cbfn, void *data) { + struct subscr_request *request; + /* current_bts is the current VLR of the MobileStation */ if (!subscr->current_bts) { if (cbfn) @@ -136,7 +196,33 @@ void subscr_get_channel(struct gsm_subscriber *subscr, int type, return; }
- paging_request(subscr->current_bts, subscr, type, cbfn, data); + request = (struct subscr_request *)malloc(sizeof(*request)); + if (!request) { + if (cbfn) + cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_OOM, + NULL, NULL, data); + return; + } + + memset(request, 0, sizeof(*request)); + request->subscr = subscr; + request->channel_type = type; + request->cbfn = cbfn; + request->data = data; + + /* + * FIXME: We might be able to assign more than one + * channel, e.g. voice and SMS submit at the same + * time. + */ + if (!subscr->in_callback && llist_empty(&subscr->requests)) { + /* add to the list, send a request */ + llist_add_tail(&request->entry, &subscr->requests); + subscr_send_paging_request(subscr); + } else { + /* this will be picked up later */ + llist_add_tail(&request->entry, &subscr->requests); + } }
void subscr_put_channel(struct gsm_lchan *lchan) @@ -147,5 +233,21 @@ void subscr_put_channel(struct gsm_lchan *lchan) * of the lchan after having asked the next requestee to handle * the channel. */ + /* + * FIXME: is the lchan is of a different type we could still + * issue an immediate assignment for another channel and then + * close this one. + */ + /* + * Currently we will drop the last ref of the lchan which + * will result in a channel release on RSL and we will start + * the paging. This should work most of the time as the MS + * will listen to the paging requests before we timeout + */ + put_lchan(lchan); + + if (lchan->subscr && !llist_empty(&lchan->subscr->requests)) { + subscr_send_paging_request(lchan->subscr); + } }