diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-11-15 10:31:53 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-11-15 20:06:50 +0100 |
commit | b4e72f881cb307f52678bdb2535691ab7d12e49a (patch) | |
tree | f306aa8b6b82c91a758bc3dd5cda9414c8f1d6fd | |
parent | 16e958dc6850a1b63a794fc4337b76bf7c21c357 (diff) |
bsc: Implement queuing of messages to the MSC before the con is established
-rw-r--r-- | openbsc/include/openbsc/osmo_bsc.h | 3 | ||||
-rw-r--r-- | openbsc/src/bsc/osmo_bsc_sccp.c | 50 |
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; |