From 45450b9214a01351ad88710430b43884fa161243 Mon Sep 17 00:00:00 2001
From: Alexander Chemeris <Alexander.Chemeris@gmail.com>
Date: Sat, 12 Sep 2015 20:25:09 -0400
Subject: [PATCH 3/3] mncc: Send "Dest OOO" cause in case of a link radio
 failure.

Previously we were sending a generic "Resource unavailable" cause code making
it impossible to distinguish real error cases from a regular radio link failure.
This was the reason for many "unknown" call errors we've seen at Rhizomatica
installations. Now they are properly classified as non-erroneous call failures.
---
 openbsc/include/openbsc/transaction.h |  1 +
 openbsc/src/libbsc/bsc_api.c          |  2 +-
 openbsc/src/libmsc/gsm_04_08.c        | 14 ++++++++++----
 openbsc/src/libmsc/transaction.c      |  9 +++++++--
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h
index 6ef1612..303ef6e 100644
--- a/openbsc/include/openbsc/transaction.h
+++ b/openbsc/include/openbsc/transaction.h
@@ -70,6 +70,7 @@ struct gsm_trans *trans_alloc(struct gsm_network *net,
 			      struct gsm_subscriber *subscr,
 			      uint8_t protocol, uint8_t trans_id,
 			      uint32_t callref);
+void trans_free_cause(struct gsm_trans *trans, int gsm0808_cause);
 void trans_free(struct gsm_trans *trans);
 
 int trans_assign_trans_id(struct gsm_network *net, struct gsm_subscriber *subscr,
diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c
index 76ceb2d..0afce2f 100644
--- a/openbsc/src/libbsc/bsc_api.c
+++ b/openbsc/src/libbsc/bsc_api.c
@@ -816,7 +816,7 @@ static void handle_release(struct gsm_subscriber_connection *conn,
 
 	/* clear the connection now */
 	if (bsc->clear_request)
-		destruct = bsc->clear_request(conn, 0);
+		destruct = bsc->clear_request(conn, GSM0808_CAUSE_RADIO_INTERFACE_FAILURE);
 
 	/* now give up all channels */
 	if (conn->lchan == lchan)
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 01f1391..13e4297 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -57,6 +57,7 @@
 
 #include <osmocom/gsm/gsm48.h>
 #include <osmocom/gsm/gsm0480.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
 #include <osmocom/gsm/gsm_utils.h>
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/talloc.h>
@@ -407,7 +408,7 @@ void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t caus
 restart:
 	llist_for_each_entry_safe(trans, temp, &conn->bts->network->trans_list, entry) {
 		if (trans->conn == conn) {
-			trans_free(trans);
+			trans_free_cause(trans, cause);
 			goto restart;
 		}
 	}
@@ -1396,16 +1397,21 @@ int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
 
 /* Call Control Specific transaction release.
  * gets called by trans_free, DO NOT CALL YOURSELF! */
-void _gsm48_cc_trans_free(struct gsm_trans *trans)
+void _gsm48_cc_trans_free(struct gsm_trans *trans, int gsm0808_cause)
 {
 	gsm48_stop_cc_timer(trans);
 
 	/* send release to L4, if callref still exists */
 	if (trans->callref) {
-		/* Ressource unavailable */
+		/* Release CC connection */
+		int cc_cause = GSM48_CC_CAUSE_RESOURCE_UNAVAIL;
+		if (gsm0808_cause == GSM0808_CAUSE_RADIO_INTERFACE_FAILURE)
+		{
+			cc_cause = GSM48_CC_CAUSE_DEST_OOO;
+		}
 		mncc_release_ind(trans->net, trans, trans->callref,
 				 GSM48_CAUSE_LOC_PRN_S_LU,
-				 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
+				 cc_cause);
 	}
 	if (trans->cc.state != GSM_CSTATE_NULL)
 		new_cc_state(trans, GSM_CSTATE_NULL);
diff --git a/openbsc/src/libmsc/transaction.c b/openbsc/src/libmsc/transaction.c
index a750362..95939d3 100644
--- a/openbsc/src/libmsc/transaction.c
+++ b/openbsc/src/libmsc/transaction.c
@@ -31,7 +31,7 @@
 
 void *tall_trans_ctx;
 
-void _gsm48_cc_trans_free(struct gsm_trans *trans);
+void _gsm48_cc_trans_free(struct gsm_trans *trans, int gsm0808_cause);
 
 struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn,
 				   uint8_t proto, uint8_t trans_id)
@@ -89,9 +89,14 @@ struct gsm_trans *trans_alloc(struct gsm_network *net,
 
 void trans_free(struct gsm_trans *trans)
 {
+	trans_free_cause(trans, -1);
+}
+
+void trans_free_cause(struct gsm_trans *trans, int gsm0808_cause)
+{
 	switch (trans->protocol) {
 	case GSM48_PDISC_CC:
-		_gsm48_cc_trans_free(trans);
+		_gsm48_cc_trans_free(trans, gsm0808_cause);
 		break;
 	case GSM48_PDISC_SMS:
 		_gsm411_sms_trans_free(trans);
-- 
1.9.1

