aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-06-17 11:58:30 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2018-01-12 03:28:14 +0100
commitbd45627a884a55250fa31ae006adf67d2b11c3e6 (patch)
tree70c4ac65981634e7aca9035c6b9d5e4b66328296
parent05b8072049d18b6a24cffd6ab1d9137e3e6a8971 (diff)
Add a queue to bsc_api to queue DTAP messages during handover/assignment
-rw-r--r--include/osmocom/bsc/gsm_data.h3
-rw-r--r--src/libbsc/bsc_api.c65
2 files changed, 68 insertions, 0 deletions
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index d03e9b52a..07ca09208 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -106,6 +106,9 @@ struct gsm_subscriber_connection {
/* penalty timers for handover */
struct llist_head ho_penalty_timers;
+
+ /* Cache DTAP messages during handover/assignment */
+ struct llist_head assignment_queue;
};
static inline struct gsm_bts *conn_get_bts(struct gsm_subscriber_connection *conn) {
diff --git a/src/libbsc/bsc_api.c b/src/libbsc/bsc_api.c
index bb5271dc6..95af07605 100644
--- a/src/libbsc/bsc_api.c
+++ b/src/libbsc/bsc_api.c
@@ -46,6 +46,13 @@ static void handle_release(struct gsm_subscriber_connection *conn, struct bsc_ap
static void handle_chan_ack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
static void handle_chan_nack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
+struct assignment_queue {
+ struct llist_head entry;
+ struct msgb *msg;
+ int link_id;
+ int allow_sacch;
+};
+
/* GSM 08.08 3.2.2.33 */
static uint8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
{
@@ -271,6 +278,7 @@ struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lcha
conn->bts = lchan->ts->trx->bts;
lchan->conn = conn;
INIT_LLIST_HEAD(&conn->ho_penalty_timers);
+ INIT_LLIST_HEAD(&conn->assignment_queue);
llist_add_tail(&conn->entry, &net->subscr_conns);
return conn;
}
@@ -307,10 +315,37 @@ void bsc_subscr_con_free(struct gsm_subscriber_connection *conn)
talloc_free(penalty);
}
+ /* flush pending messages */
+ flush_assignment_queue(conn, 0);
+
llist_del(&conn->entry);
talloc_free(conn);
}
+static void flush_assignment_queue(struct gsm_subscriber_connection *conn, int send)
+{
+ struct assignment_queue *ass_queue;
+
+ if (conn->secondary_lchan || conn->ho_lchan) {
+ LOGP(DNM, LOGL_ERROR, "Cannot send queued messages, because "
+ "handover/assignment is still ongoing, please fix!\n");
+ send = 0;
+ }
+
+ while (!llist_empty(&conn->assignment_queue)) {
+ ass_queue = llist_entry(conn->assignment_queue.next,
+ struct assignment_queue, entry);
+ llist_del(&ass_queue->entry);
+ if (send) {
+ LOGP(DNM, LOGL_DEBUG, "Sending pending DTAP message\n");
+ gsm0808_submit_dtap(conn, ass_queue->msg,
+ ass_queue->link_id, ass_queue->allow_sacch);
+ } else
+ msgb_free(ass_queue->msg);
+ talloc_free(ass_queue);
+ }
+}
+
int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
{
network->bsc_api = api;
@@ -331,6 +366,18 @@ int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
return -1;
}
+ /* buffer message during assignment / handover */
+ if (conn->secondary_lchan || conn->ho_lchan) {
+ struct assignment_queue *ass_queue;
+ LOGP(DNM, LOGL_DEBUG, "Queing DTAP message during ho/ass\n");
+ ass_queue = talloc_zero(tall_bsc_ctx, struct assignment_queue);
+ ass_queue->msg = msg;
+ ass_queue->link_id = link_id;
+ ass_queue->allow_sacch = allow_sacch;
+ llist_add_tail(&ass_queue->entry, &conn->assignment_queue);
+ return 0;
+ }
+
sapi = link_id & 0x7;
msg->lchan = conn->lchan;
msg->dst = msg->lchan->ts->trx->rsl_link;
@@ -464,6 +511,9 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn,
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_COMPL, &sig);
/* FIXME: release old channel */
+ /* send pending messages, if any */
+ flush_assignment_queue(conn, 1);
+
return;
}
@@ -486,6 +536,9 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn,
conn->lchan = conn->secondary_lchan;
conn->secondary_lchan = NULL;
+ /* send pending messages, if any */
+ flush_assignment_queue(conn, 1);
+
if (is_ipaccess_bts(conn_get_bts(conn)) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)
rsl_ipacc_crcx(conn->lchan);
@@ -514,6 +567,9 @@ static void handle_ass_fail(struct gsm_subscriber_connection *conn,
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_FAIL, &sig);
/* FIXME: release allocated new channel */
+ /* send pending messages, if any */
+ flush_assignment_queue(conn, 1);
+
return;
}
@@ -529,6 +585,9 @@ static void handle_ass_fail(struct gsm_subscriber_connection *conn,
conn->secondary_lchan = NULL;
}
+ /* send pending messages, if any */
+ flush_assignment_queue(conn, 1);
+
gh = msgb_l3(msg);
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
LOGP(DMSC, LOGL_ERROR, "assignment failure unhandled: %zu\n",
@@ -594,6 +653,9 @@ static void handle_rr_ho_compl(struct msgb *msg)
sig.mr = NULL;
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);
/* FIXME: release old channel */
+
+ /* send pending messages, if any */
+ flush_assignment_queue(msg->lchan->conn, 1);
}
/* Chapter 9.1.17 Handover Failure */
@@ -609,6 +671,9 @@ static void handle_rr_ho_fail(struct msgb *msg)
sig.mr = NULL;
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);
/* FIXME: release allocated new channel */
+
+ /* send pending messages, if any */
+ flush_assignment_queue(msg->lchan->conn, 1);
}