aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-11-15 10:31:53 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-11-15 20:06:50 +0100
commitb4e72f881cb307f52678bdb2535691ab7d12e49a (patch)
treef306aa8b6b82c91a758bc3dd5cda9414c8f1d6fd /openbsc
parent16e958dc6850a1b63a794fc4337b76bf7c21c357 (diff)
bsc: Implement queuing of messages to the MSC before the con is established
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/osmo_bsc.h3
-rw-r--r--openbsc/src/bsc/osmo_bsc_sccp.c50
2 files changed, 48 insertions, 5 deletions
diff --git a/openbsc/include/openbsc/osmo_bsc.h b/openbsc/include/openbsc/osmo_bsc.h
index 8aa5ddce6..ef0f11a3b 100644
--- a/openbsc/include/openbsc/osmo_bsc.h
+++ b/openbsc/include/openbsc/osmo_bsc.h
@@ -19,6 +19,9 @@ struct osmo_bsc_sccp_con {
struct timer_list sccp_it_timeout;
struct timer_list sccp_cc_timeout;
+ struct llist_head sccp_queue;
+ unsigned int sccp_queue_size;
+
struct gsm_subscriber_connection *conn;
uint8_t new_subscriber;
};
diff --git a/openbsc/src/bsc/osmo_bsc_sccp.c b/openbsc/src/bsc/osmo_bsc_sccp.c
index a7c51dd94..74c3a08c1 100644
--- a/openbsc/src/bsc/osmo_bsc_sccp.c
+++ b/openbsc/src/bsc/osmo_bsc_sccp.c
@@ -39,6 +39,32 @@
static LLIST_HEAD(active_connections);
+static void free_queued(struct osmo_bsc_sccp_con *conn)
+{
+ struct msgb *msg;
+
+ while (!llist_empty(&conn->sccp_queue)) {
+ /* this is not allowed to fail */
+ msg = msgb_dequeue(&conn->sccp_queue);
+ msgb_free(msg);
+ }
+
+ conn->sccp_queue_size = 0;
+}
+
+static void send_queued(struct osmo_bsc_sccp_con *conn)
+{
+ struct msgb *msg;
+
+ while (!llist_empty(&conn->sccp_queue)) {
+ /* this is not allowed to fail */
+ msg = msgb_dequeue(&conn->sccp_queue);
+ sccp_connection_write(conn->sccp, msg);
+ msgb_free(msg);
+ conn->sccp_queue_size -= 1;
+ }
+}
+
static void msc_outgoing_sccp_data(struct sccp_connection *conn,
struct msgb *msg, unsigned int len)
{
@@ -63,6 +89,7 @@ static void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
}
con_data->sccp = NULL;
+ free_queued(con_data);
sccp_connection_free(conn);
bsc_delete_connection(con_data);
} else if (conn->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED) {
@@ -71,6 +98,8 @@ static void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
bsc_del_timer(&con_data->sccp_cc_timeout);
bsc_schedule_timer(&con_data->sccp_it_timeout, SCCP_IT_TIMER, 0);
+
+ send_queued(con_data);
}
}
@@ -82,6 +111,7 @@ static void bsc_sccp_force_free(struct osmo_bsc_sccp_con *data)
data->conn = NULL;
}
+ free_queued(data);
sccp_connection_force_free(data->sccp);
data->sccp = NULL;
bsc_delete_connection(data);
@@ -130,14 +160,22 @@ int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
struct sccp_connection *sccp = conn->sccp;
- if (sccp->connection_state != SCCP_CONNECTION_STATE_ESTABLISHED) {
- LOGP(DMSC, LOGL_ERROR, "The connection is not established.\n");
+ if (sccp->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
+ LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
msgb_free(msg);
- return -1;
+ } else if (sccp->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED
+ && conn->sccp_queue_size == 0) {
+ sccp_connection_write(sccp, msg);
+ msgb_free(msg);
+ } else if (conn->sccp_queue_size > 10) {
+ LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
+ msgb_free(msg);
+ } else {
+ LOGP(DMSC, LOGL_DEBUG, "Queueing packet on %p. Queue size: %d\n", sccp, conn->sccp_queue_size);
+ conn->sccp_queue_size += 1;
+ msgb_enqueue(&conn->sccp_queue, msg);
}
- sccp_connection_write(sccp, msg);
- msgb_free(msg);
return 0;
}
@@ -182,6 +220,8 @@ int bsc_create_new_connection(struct gsm_subscriber_connection *conn)
bsc_con->sccp_cc_timeout.cb = sccp_cc_timeout;
bsc_con->sccp_cc_timeout.data = bsc_con;
+ INIT_LLIST_HEAD(&bsc_con->sccp_queue);
+
bsc_con->sccp = sccp;
bsc_con->msc_con = net->msc_data->msc_con;
bsc_con->conn = conn;