aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-06-07 20:12:33 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-08-25 23:17:24 +0200
commit5135fbefd06920c5797c200c7f3b18f786e1ef2a (patch)
tree84d9affa28b7aeabdeee30812e1dec85d828ed7f /openbsc
parent934355a2681b673a4f1ab943a968284a0563bc66 (diff)
bsc: Attempt to respond to paging to the MSC that paged
Inspect the message and see if it is a paging response, then try to find the MSC that has paged this subscriber and select this as the target MSC, also move the MSC to the back of the list for 'load balancing'.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_filter.c71
1 files changed, 67 insertions, 4 deletions
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
index 7271fc8c3..200360ac9 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
@@ -53,8 +53,9 @@ static void handle_lu_request(struct gsm_subscriber_connection *conn,
}
}
-/* we will need to stop the paging request */
-static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
+/* extract a subscriber from the paging response */
+static struct gsm_subscriber *extract_sub(struct gsm_subscriber_connection *conn,
+ struct msgb *msg)
{
uint8_t mi_type;
char mi_string[GSM48_MI_SIZE];
@@ -64,7 +65,7 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) {
LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg));
- return -1;
+ return NULL;
}
gh = msgb_l3(msg);
@@ -88,6 +89,14 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
break;
}
+ return subscr;
+}
+
+/* we will need to stop the paging request */
+static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
+{
+ struct gsm_subscriber *subscr = extract_sub(conn, msg);
+
if (!subscr) {
LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n");
return -1;
@@ -100,10 +109,36 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
struct msgb *msg)
{
+ struct gsm48_hdr *gh;
+ int8_t pdisc;
+ uint8_t mtype;
struct osmo_bsc_data *bsc;
- struct osmo_msc_data *msc;
+ struct osmo_msc_data *msc, *pag_msc;
+ struct gsm_subscriber *subscr;
bsc = conn->bts->network->bsc_data;
+
+ if (msgb_l3len(msg) < sizeof(*gh)) {
+ LOGP(DMSC, LOGL_ERROR, "There is no GSM48 header here.\n");
+ return NULL;
+ }
+
+ gh = msgb_l3(msg);
+ pdisc = gh->proto_discr & 0x0f;
+ mtype = gh->msg_type & 0xbf;
+
+ /*
+ * We are asked to select a MSC here but they are not equal. We
+ * want to respond to a paging request on the MSC where we got the
+ * request from. This is where we need to decide where this connection
+ * will go.
+ */
+ if (pdisc == GSM48_PDISC_RR && mtype == GSM48_MT_RR_PAG_RESP)
+ goto paging;
+ else
+ goto round_robin;
+
+round_robin:
llist_for_each_entry(msc, &bsc->mscs, entry) {
if (!msc->msc_con->is_authenticated)
continue;
@@ -114,6 +149,34 @@ struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
}
return NULL;
+
+paging:
+ subscr = extract_sub(conn, msg);
+
+ if (!subscr) {
+ LOGP(DMSC, LOGL_ERROR, "Got paged but no subscriber found.\n");
+ return NULL;
+ }
+
+ pag_msc = paging_get_data(conn->bts, subscr);
+ subscr_put(subscr);
+
+ llist_for_each_entry(msc, &bsc->mscs, entry) {
+ if (msc != pag_msc)
+ continue;
+
+ /*
+ * We don't check if the MSC is connected. In case it
+ * is not the connection will be dropped.
+ */
+
+ /* force round robin by moving it to the end */
+ llist_move_tail(&msc->entry, &bsc->mscs);
+ return msc;
+ }
+
+ LOGP(DMSC, LOGL_ERROR, "Got paged but no request found.\n");
+ return NULL;
}