aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/src/bsc_msc_ip.c18
-rw-r--r--openbsc/src/bssap.c35
2 files changed, 47 insertions, 6 deletions
diff --git a/openbsc/src/bsc_msc_ip.c b/openbsc/src/bsc_msc_ip.c
index 0a1d1be27..ce37fe590 100644
--- a/openbsc/src/bsc_msc_ip.c
+++ b/openbsc/src/bsc_msc_ip.c
@@ -351,7 +351,7 @@ static int handle_ass_compl(struct msgb *msg)
}
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
- LOGP(DMSC, LOGL_ERROR, "assignment failure invalid: %d\n",
+ LOGP(DMSC, LOGL_ERROR, "assignment compl invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh));
put_subscr_con(&msg->lchan->conn, 0);
return -1;
@@ -382,6 +382,7 @@ static int handle_ass_compl(struct msgb *msg)
*/
static int handle_ass_fail(struct msgb *msg)
{
+ u_int8_t *rr_cause;
struct gsm48_hdr *gh = msgb_l3(msg);
LOGP(DMSC, LOGL_ERROR, "ASSIGNMENT FAILURE from MS, forwarding to MSC\n");
@@ -391,21 +392,26 @@ static int handle_ass_fail(struct msgb *msg)
return -1;
}
- if (msg->lchan->msc_data->secondary_lchan != msg->lchan) {
- LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n");
+ /* assignment failure comes on the old link */
+ if (msg->lchan->msc_data->lchan != msg->lchan) {
+ LOGP(DMSC, LOGL_NOTICE, "Failure should come on the old link.\n");
+ msg->lchan->msc_data = NULL;
put_subscr_con(&msg->lchan->conn, 0);
return -1;
}
+ /* Giving up the secondary will happen in bssap */
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
LOGP(DMSC, LOGL_ERROR, "assignment failure invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh));
- put_subscr_con(&msg->lchan->conn, 0);
- return -1;
+ rr_cause = NULL;
+ } else {
+ rr_cause = &gh->data[0];
}
+ /* this will also free the secondary channel */
gsm0808_send_assignment_failure(msg->lchan,
- GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, &gh->data[0]);
+ GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, rr_cause);
return 1;
}
diff --git a/openbsc/src/bssap.c b/openbsc/src/bssap.c
index ee51a392f..edbe66717 100644
--- a/openbsc/src/bssap.c
+++ b/openbsc/src/bssap.c
@@ -295,14 +295,48 @@ reject:
}
/*
+ * handle network failures... and free the secondary lchan
+ */
+static void bssmap_free_secondary(struct bss_sccp_connection_data *data)
+{
+ struct gsm_lchan *lchan;
+
+ if (!data || !data->secondary_lchan)
+ return;
+
+ lchan = data->secondary_lchan;
+ if (lchan->msc_data != data) {
+ LOGP(DMSC, LOGL_ERROR, "MSC data does not match on lchan and cb.\n");
+ data->secondary_lchan = NULL;
+ }
+
+ /* give up additional data */
+ lchan->msc_data->secondary_lchan = NULL;
+ if (lchan->msc_data->lchan == lchan)
+ lchan->msc_data->lchan = NULL;
+ lchan->msc_data = NULL;
+
+ /* give up the new channel to not do a SACCH deactivate */
+ subscr_put(lchan->conn.subscr);
+ lchan->conn.subscr = NULL;
+ put_subscr_con(&lchan->conn, 1);
+}
+
+/*
* Handle the network configurable T10 parameter
*/
static void bssmap_t10_fired(void *_conn)
{
+ struct bss_sccp_connection_data *msc_data;
struct sccp_connection *conn = (struct sccp_connection *) _conn;
struct msgb *resp;
LOGP(DMSC, LOGL_ERROR, "T10 fired, assignment failed: %p\n", conn);
+
+ /* free the secondary channel if we have one */
+ msc_data = conn->data_ctx;
+ bssmap_free_secondary(msc_data);
+
resp = bssmap_create_assignment_failure(
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
if (!resp) {
@@ -1293,6 +1327,7 @@ void gsm0808_send_assignment_failure(struct gsm_lchan *lchan, u_int8_t cause, u_
struct msgb *resp;
bsc_del_timer(&lchan->msc_data->T10);
+ bssmap_free_secondary(lchan->msc_data);
resp = bssmap_create_assignment_failure(cause, rr_value);
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Allocation failure: %p\n", lchan_get_sccp(lchan));