pespin has uploaded this change for review.

View Change

sccp: Introduce N-DISCONNECT.req Release/Refusal reason

N-DISCONNECT.req has a "Reason" Parameter. the "Reason" Parameter is
mandatory according to Table 6/Q.711. The options possible for the
"Reason" can be found in ITU Q.711 "6.1.1.2.4 Release phase", and
contain no explicit value. That enum is different from the wire-format
defined in:
* ITU-T Q.713, Section 3.11 Release cause
* ITU-T Q.713 Section 3.15 Refusal cause

Actually, ITU-T Q.713 "ANNEX A" describes a mapping between the former
(N-DISCONNECT.req Reason) and the later (SCCP Release/Refusal cause).

Use that table to translate as much as possible between the two (despite
the mapping is described as being one-to-one, well, it leaves a lot to
interpretation due to missing enums, N-to-M mappings, etc.).

Related: OS#2601
Change-Id: I158463c2e9b34abe06554371d628e4fa7ea8c5c1
---
M include/osmocom/sigtran/sccp_sap.h
M src/sccp_connection.c
M src/sccp_sap.c
M src/sccp_scoc.c
M src/sccp_scoc_fsm.c
M src/sccp_user.h
6 files changed, 422 insertions(+), 5 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/63/43763/1
diff --git a/include/osmocom/sigtran/sccp_sap.h b/include/osmocom/sigtran/sccp_sap.h
index 7399b3d..d8ee43e 100644
--- a/include/osmocom/sigtran/sccp_sap.h
+++ b/include/osmocom/sigtran/sccp_sap.h
@@ -137,6 +137,67 @@
OSMO_SCCP_SSN_BSSAP = 254,
};

+/* Q.711 6.1.1.2.3, "Table 5/Q.711" and paragrapgs below it */
+enum osmo_sccp_reset_reason_nsp {
+ OSMO_SCCP_RESET_REASON_NSP_UNSPEC = 0x0,
+ OSMO_SCCP_RESET_REASON_NSP_LOCAL_SCCP_ORIGIN,
+};
+
+enum osmo_sccp_reset_reason_nsu {
+ OSMO_SCCP_RESET_REASON_NSU_USER_SYNCHRONIZATION = 0x0,
+};
+
+enum osmo_sccp_reset_reason_undefined {
+ OSMO_SCCP_RESET_REASON_UNDEFINED = 0x0,
+};
+
+/* Q.711 6.1.1.2.4 1) When the "originator" parameter indicates the "network service provider" */
+enum osmo_sccp_release_reason_nsp {
+ OSMO_SCCP_REL_REASON_NSP_DISC_NT = 0x100,
+ OSMO_SCCP_REL_REASON_NSP_DISC_T,
+ OSMO_SCCP_REL_REASON_NSP_DISC_INVALID_STATE,
+ OSMO_SCCP_REL_REASON_NSP_DISC_RELEASE_IN_PROGRESS,
+ OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT,
+ OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT,
+ OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T,
+ OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT,
+ OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T,
+ OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT,
+ OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T,
+ OSMO_SCCP_REL_REASON_NSP_CREF_LOCAL_ERROR,
+ OSMO_SCCP_REL_REASON_NSP_CREF_INVALID_STATE,
+ OSMO_SCCP_REL_REASON_NSP_CREF_NO_TRANSITION,
+ OSMO_SCCP_REL_REASON_NSP_CREF_IN_RESTART_PHASE,
+ OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION,
+};
+
+/* Q.711 6.1.1.2.4 2) When the "originator" parameter indicates the "network service user" */
+enum osmo_sccp_release_reason_nsu {
+ OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL = 0x100,
+ OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL,
+ OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION,
+ OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE,
+ OSMO_SCCP_REL_REASON_NSU_DISC_SCCP_USER_ORIGIN,
+ OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION,
+ OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE,
+ OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION,
+ OSMO_SCCP_REL_REASON_NSU_CREF_NT_CONDITION,
+ OSMO_SCCP_REL_REASON_NSU_CREF_T_CONDITION,
+ OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU,
+ OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN,
+ OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION,
+ OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE,
+ OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED,
+ OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_CONGESTION,
+ OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_FAILURE,
+ OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION,
+};
+
+/* Q.711 6.1.1.2.4 2) When the "originator" parameter indicates the "network service user" */
+enum osmo_sccp_release_reason_undefined {
+ OSMO_SCCP_REL_REASON_UNDEFINED = 0x100,
+};
+
/* Q.711 6.3.2.2.5 Signalling point status */
enum osmo_sccp_sp_status {
OSMO_SCCP_SP_S_INACCESSIBLE = 1,
@@ -222,6 +283,8 @@
struct osmo_scu_disconn_param {
enum osmo_sccp_originator originator;
struct osmo_sccp_addr responding_addr;
+ /* enum osmo_sccp_release_reason_* (value > 19),
+ * enum sccp_refusal_cause (ITU-T Q.713 Section 3.15 Refusal cause) value <= 19, backward compatibility */
uint32_t cause;
uint32_t conn_id;
uint32_t importance;
@@ -231,6 +294,7 @@
/* OSMO_SCU_PRIM_N_RESET */
struct osmo_scu_reset_param {
enum osmo_sccp_originator originator;
+ /* enum osmo_sccp_reset_reason_*, "Table 5/Q.711" and paragraphs below it */
uint32_t cause;
uint32_t conn_id;
};
diff --git a/src/sccp_connection.c b/src/sccp_connection.c
index 10c2760..abf13d0 100644
--- a/src/sccp_connection.c
+++ b/src/sccp_connection.c
@@ -231,6 +231,7 @@
struct osmo_scu_connect_param *uconp;
struct osmo_scu_data_param *udatp;
struct xua_msg_part *data_ie;
+ uint32_t cause;

scu_prim = scu_prim_alloc(primitive, operation);

@@ -243,7 +244,19 @@
udisp->originator = OSMO_SCCP_ORIG_UNDEFINED;
//udisp->in_sequence_control;
if (xua) {
- udisp->cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE);
+ cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE);
+ switch (cause & SUA_CAUSE_T_MASK) {
+ case SUA_CAUSE_T_REFUSAL:
+ sccp_refusal_cause_to_scu_rel_reason(&udisp->originator, &udisp->cause, cause & 0xff);
+ break;
+ case SUA_CAUSE_T_RELEASE:
+ sccp_release_cause_to_scu_rel_reason(&udisp->originator, &udisp->cause, cause & 0xff);
+ break;
+ default:
+ udisp->originator = OSMO_SCCP_ORIG_UNDEFINED;
+ udisp->cause = OSMO_SCCP_REL_REASON_UNDEFINED;
+ break;
+ }
if (xua_msg_find_tag(xua, SUA_IEI_SRC_ADDR)) {
if (sua_addr_parse(&udisp->responding_addr, xua, SUA_IEI_SRC_ADDR) < 0) {
LOGPSCC(conn, LOGL_ERROR, "XUA Message %s without valid SRC_ADDR\n",
diff --git a/src/sccp_sap.c b/src/sccp_sap.c
index 00b2563..95d2070 100644
--- a/src/sccp_sap.c
+++ b/src/sccp_sap.c
@@ -25,6 +25,8 @@

#include <osmocom/sigtran/sccp_sap.h>

+#include <osmocom/sccp/sccp_types.h>
+
#include "ss7_instance.h"
#include "sccp_connection.h"
#include "sccp_scoc_fsm.h"
@@ -174,6 +176,337 @@
{ 0, NULL }
};

+/* Table A.1/Q.713 */
+static enum sccp_refusal_cause scu_rel_reason_nsp_to_sccp_refusal_cause(uint32_t reason)
+{
+ switch (reason) {
+ case OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT:
+ return SCCP_REFUSAL_DESTINATION_ADDRESS_UKNOWN;
+ case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT:
+ return SCCP_REFUSAL_SUBSYSTEM_FAILURE;
+ case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T:
+ return SCCP_REFUSAL_DESTINATION_INACCESSIBLE;
+ case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT:
+ return SCCP_REFUSAL_NET_QOS_NON_TRANSIENT;
+ case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T:
+ return SCCP_REFUSAL_NET_QOS_TRANSIENT;
+ case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT:
+ return SCCP_REFUSAL_UNQUALIFIED;
+ case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T:
+ return SCCP_REFUSAL_EXPIRATION;
+ case OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION:
+ return SCCP_REFUSAL_HOP_COUNTER_VIOLATION;
+ /* Not specified in the table... */
+ case OSMO_SCCP_REL_REASON_NSP_DISC_NT:
+ case OSMO_SCCP_REL_REASON_NSP_DISC_T:
+ case OSMO_SCCP_REL_REASON_NSP_DISC_INVALID_STATE:
+ case OSMO_SCCP_REL_REASON_NSP_DISC_RELEASE_IN_PROGRESS:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_LOCAL_ERROR:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_INVALID_STATE:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_NO_TRANSITION:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_IN_RESTART_PHASE:
+ default:
+ return SCCP_REFUSAL_UNQUALIFIED;
+ }
+}
+
+/* Table A.1/Q.713 */
+static enum sccp_refusal_cause scu_rel_reason_nsu_to_sccp_refusal_cause(uint32_t reason)
+{
+ switch (reason) {
+ case OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU:
+ return SCCP_REFUSAL_INCOMPATIBLE_USER_DATA;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN:
+ return SCCP_REFUSAL_END_USER_ORIGINATED;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION:
+ return SCCP_REFUSAL_END_USER_CONGESTION;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE:
+ return SCCP_REFUSAL_END_USER_FAILURE;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED:
+ return SCCP_REFUSAL_SCCP_USER_ORIGINATED;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_CONGESTION:
+ return SCCP_REFUSAL_ACCESS_CONGESTION;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_FAILURE:
+ return SCCP_REFUSAL_ACCESS_FAILURE;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION:
+ return SCCP_REFUSAL_SUBSYTEM_CONGESTION;
+ /* Not specified in the table... */
+ case OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL:
+ case OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL:
+ case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION:
+ case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE:
+ case OSMO_SCCP_REL_REASON_NSU_DISC_SCCP_USER_ORIGIN:
+ case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION:
+ case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE:
+ case OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_NT_CONDITION:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_T_CONDITION:
+ default:
+ return SCCP_REFUSAL_UNQUALIFIED;
+ }
+}
+
+/* Table A.1/Q.713 */
+enum sccp_refusal_cause scu_rel_reason_to_sccp_refusal_cause(enum osmo_sccp_originator originator, uint32_t reason)
+{
+ if (reason <= SCCP_REFUSAL_UNEQUIPPED_USER) /* direct wire-format as backward compatibility */
+ return (enum sccp_refusal_cause)reason;
+
+ switch (originator) {
+ case OSMO_SCCP_ORIG_NS_PROVIDER:
+ return scu_rel_reason_nsp_to_sccp_refusal_cause(reason);
+ case OSMO_SCCP_ORIG_NS_USER:
+ return scu_rel_reason_nsu_to_sccp_refusal_cause(reason);
+ case OSMO_SCCP_ORIG_UNDEFINED:
+ default:
+ return SCCP_REFUSAL_UNQUALIFIED;
+ }
+}
+
+/* Table A.1/Q.713 */
+void sccp_refusal_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause)
+{
+ switch (sccp_cause) {
+ case SCCP_REFUSAL_END_USER_ORIGINATED:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN;
+ break;
+ case SCCP_REFUSAL_END_USER_CONGESTION:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION;
+ break;
+ case SCCP_REFUSAL_END_USER_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE;
+ break;
+ case SCCP_REFUSAL_SCCP_USER_ORIGINATED:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED;
+ break;
+ case SCCP_REFUSAL_DESTINATION_ADDRESS_UKNOWN:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT;
+ break;
+ case SCCP_REFUSAL_DESTINATION_INACCESSIBLE:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T;
+ break;
+ case SCCP_REFUSAL_NET_QOS_NON_TRANSIENT:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT;
+ break;
+ case SCCP_REFUSAL_NET_QOS_TRANSIENT:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T;
+ break;
+ case SCCP_REFUSAL_ACCESS_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE;
+ break;
+ case SCCP_REFUSAL_ACCESS_CONGESTION:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION;
+ break;
+ case SCCP_REFUSAL_SUBSYSTEM_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT;
+ break;
+ case SCCP_REFUSAL_SUBSYTEM_CONGESTION:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION;
+ break;
+ case SCCP_REFUSAL_EXPIRATION:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T;
+ break;
+ case SCCP_REFUSAL_INCOMPATIBLE_USER_DATA:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU;
+ break;
+ case SCCP_REFUSAL_UNQUALIFIED:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T;
+ break;
+ case SCCP_REFUSAL_HOP_COUNTER_VIOLATION:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION;
+ break;
+ case SCCP_REFUSAL_NO_TRANS_FOR_ADDRESS_NATURE:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT;
+ break;
+ case SCCP_REFUSAL_UNEQUIPPED_USER:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT;
+ break;
+ /* Not specified in table... */
+ case SCCP_REFUSAL_RESERVED:
+ case SCCP_REFUSAL_SCCP_FAILURE:
+ default:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT;
+ break;
+ }
+}
+
+
+/* Table A.2/Q.713 */
+static enum sccp_release_cause scu_rel_reason_nsp_to_sccp_release_cause(uint32_t reason)
+{
+ switch (reason) {
+ case OSMO_SCCP_REL_REASON_NSP_DISC_NT:
+ return SCCP_RELEASE_CAUSE_SUBSYSTEM_FAILURE;
+ case OSMO_SCCP_REL_REASON_NSP_DISC_T:
+ return SCCP_RELEASE_CAUSE_REMOTE_PROCEDURE_ERROR;
+ /* Not specified in the table... */
+ case OSMO_SCCP_REL_REASON_NSP_DISC_INVALID_STATE:
+ case OSMO_SCCP_REL_REASON_NSP_DISC_RELEASE_IN_PROGRESS:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_DST_ADDR_UNKNOWN_NT:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_NT:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_DST_INACC_T:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_NT:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_QOS_UNAVAIL_T:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_NT:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_REASON_UNSPEC_T:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_LOCAL_ERROR:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_INVALID_STATE:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_NO_TRANSITION:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_IN_RESTART_PHASE:
+ case OSMO_SCCP_REL_REASON_NSP_CREF_HOP_COUNTER_VIOLATION:
+ default:
+ return SCCP_RELEASE_CAUSE_UNQUALIFIED;
+ }
+}
+
+/* Table A.2/Q.713 */
+static enum sccp_release_cause scu_rel_reason_nsu_to_sccp_release_cause(uint32_t reason)
+{
+ switch (reason) {
+ case OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL:
+ return SCCP_RELEASE_CAUSE_END_USER_ORIGINATED;
+ case OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL:
+ return SCCP_RELEASE_CAUSE_UNQUALIFIED;
+ case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION:
+ return SCCP_RELEASE_CAUSE_END_USER_CONGESTION;
+ case OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE:
+ return SCCP_RELEASE_CAUSE_END_USER_FAILURE;
+ case OSMO_SCCP_REL_REASON_NSU_DISC_SCCP_USER_ORIGIN:
+ return SCCP_RELEASE_CAUSE_SCCP_USER_ORIGINATED;
+ case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION:
+ return SCCP_RELEASE_CAUSE_ACCESS_CONGESTION;
+ case OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE:
+ return SCCP_RELEASE_CAUSE_ACCESS_FAILURE;
+ case OSMO_SCCP_REL_REASON_NSU_CREF_SUBSYS_CONGESTION:
+ return SCCP_RELEASE_CAUSE_SUBSYSTEM_CONGESTION;
+ /* Not specified in the table... */
+ case OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_NT_CONDITION:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_T_CONDITION:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_INCOMPAT_INFO_NSDU:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_ORIGIN:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_CONGESTION:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_END_USER_FAILURE:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_CONGESTION:
+ case OSMO_SCCP_REL_REASON_NSU_CREF_ACCESS_FAILURE:
+ default:
+ return SCCP_RELEASE_CAUSE_UNQUALIFIED;
+ }
+}
+
+/* Table A.2/Q.713 */
+enum sccp_release_cause scu_rel_reason_to_sccp_release_cause(enum osmo_sccp_originator originator, uint32_t reason)
+{
+ if (reason <= SCCP_RELEASE_CAUSE_SCCP_FAILURE) /* direct wire-format as backward compatibility */
+ return (enum sccp_refusal_cause)reason;
+
+ switch (originator) {
+ case OSMO_SCCP_ORIG_NS_PROVIDER:
+ return scu_rel_reason_nsp_to_sccp_release_cause(reason);
+ case OSMO_SCCP_ORIG_NS_USER:
+ return scu_rel_reason_nsu_to_sccp_release_cause(reason);
+ case OSMO_SCCP_ORIG_UNDEFINED:
+ default:
+ return SCCP_RELEASE_CAUSE_UNQUALIFIED;
+ }
+}
+
+void sccp_release_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause)
+{
+ switch (sccp_cause) {
+ case SCCP_RELEASE_CAUSE_END_USER_ORIGINATED:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_NORMAL;
+ break;
+ case SCCP_RELEASE_CAUSE_END_USER_CONGESTION:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_CONGESTION;
+ break;
+ case SCCP_RELEASE_CAUSE_END_USER_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_END_USER_FAILURE;
+ break;
+ case SCCP_RELEASE_CAUSE_SCCP_USER_ORIGINATED:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_CREF_SCCP_USER_ORIGINATED;
+ break;
+ case SCCP_RELEASE_CAUSE_REMOTE_PROCEDURE_ERROR:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T;
+ break;
+ case SCCP_RELEASE_CAUSE_INCONSISTENT_CONN_DATA:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T;
+ break;
+ case SCCP_RELEASE_CAUSE_ACCESS_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_FAILURE;
+ break;
+ case SCCP_RELEASE_CAUSE_ACCESS_CONGESTION:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ACCESS_CONGESTION;
+ break;
+ case SCCP_RELEASE_CAUSE_SUBSYSTEM_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT;
+ break;
+ case SCCP_RELEASE_CAUSE_SUBSYSTEM_CONGESTION:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_SUBSYS_CONGESTION;
+ break;
+ case SCCP_RELEASE_CAUSE_MTP_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT;
+ break;
+ case SCCP_RELEASE_CAUSE_NETWORK_CONGESTION:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T;
+ break;
+ case SCCP_RELEASE_CAUSE_EXPIRATION_RESET:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T;
+ break;
+ case SCCP_RELEASE_CAUSE_EXPIRATION_INACTIVE:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_T;
+ break;
+ case SCCP_RELEASE_CAUSE_UNQUALIFIED:
+ *originator = OSMO_SCCP_ORIG_NS_USER;
+ *reason = OSMO_SCCP_REL_REASON_NSU_DISC_ABNORMAL;
+ break;
+ case SCCP_RELEASE_CAUSE_SCCP_FAILURE:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT;
+ break;
+ case SCCP_RELEASE_CAUSE_RESERVED:
+ default:
+ *originator = OSMO_SCCP_ORIG_NS_PROVIDER;
+ *reason = OSMO_SCCP_REL_REASON_NSP_DISC_NT;
+ break;
+ }
+}
+
+
/* get the Connection ID of the given SCU primitive */
static uint32_t scu_prim_conn_id(const struct osmo_scu_prim *prim)
{
diff --git a/src/sccp_scoc.c b/src/sccp_scoc.c
index 817f785..bbc4ed6 100644
--- a/src/sccp_scoc.c
+++ b/src/sccp_scoc.c
@@ -338,7 +338,7 @@
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref);
xua_msg_add_u32(xua, SUA_IEI_SRC_REF, conn->conn_id);
- xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_RELEASE | prim->u.disconnect.cause);
+ xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_RELEASE | scu_rel_reason_to_sccp_release_cause(prim->u.disconnect.originator, prim->u.disconnect.cause));
/* optional: data */
if (encode_opt_data)
xua_msg_add_data(xua, SUA_IEI_DATA, msgb_l2len(prim->oph.msg), msgb_l2(prim->oph.msg));
@@ -373,8 +373,7 @@
xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_COREF);
xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, conn->inst->route_ctx);
xua_msg_add_u32(xua, SUA_IEI_DEST_REF, conn->remote_ref);
- //xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_REFUSAL | prim->u.disconnect.cause);
- xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_REFUSAL | SCCP_REFUSAL_UNEQUIPPED_USER);
+ xua_msg_add_u32(xua, SUA_IEI_CAUSE, SUA_CAUSE_T_REFUSAL | scu_rel_reason_to_sccp_refusal_cause(prim->u.disconnect.originator, prim->u.disconnect.cause));
/* optional: source addr */
if (conn->called_addr.presence)
xua_msg_add_sccp_addr(xua, SUA_IEI_SRC_ADDR, &conn->called_addr);
diff --git a/src/sccp_scoc_fsm.c b/src/sccp_scoc_fsm.c
index 1833b89..895435c 100644
--- a/src/sccp_scoc_fsm.c
+++ b/src/sccp_scoc_fsm.c
@@ -225,7 +225,8 @@
switch (event) {
case SCOC_E_SCU_N_DISC_REQ:
prim = data;
- conn->release_cause = prim->u.disconnect.cause;
+ conn->release_cause = scu_rel_reason_to_sccp_release_cause(prim->u.disconnect.originator,
+ prim->u.disconnect.cause);
osmo_fsm_inst_state_chg(fi, S_WAIT_CONN_CONF, 0, 0);
/* keep conn timer running(!) */
break;
diff --git a/src/sccp_user.h b/src/sccp_user.h
index 47c8aa4..cb8ec90 100644
--- a/src/sccp_user.h
+++ b/src/sccp_user.h
@@ -8,6 +8,8 @@
#include <osmocom/sigtran/sccp_sap.h>

struct osmo_sccp_instance;
+enum sccp_refusal_cause;
+enum osmo_sccp_originator;

struct osmo_sccp_user {
/*! \brief entry in list of sccp users of \ref osmo_sccp_instance */
@@ -38,6 +40,11 @@

int sccp_user_prim_up(struct osmo_sccp_user *scut, struct osmo_scu_prim *prim);

+enum sccp_refusal_cause scu_rel_reason_to_sccp_refusal_cause(enum osmo_sccp_originator originator, uint32_t reason);
+enum sccp_release_cause scu_rel_reason_to_sccp_release_cause(enum osmo_sccp_originator originator, uint32_t reason);
+void sccp_refusal_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause);
+void sccp_release_cause_to_scu_rel_reason(enum osmo_sccp_originator *originator, uint32_t *reason, uint32_t sccp_cause);
+
#define _LOGPSCU(scu, subsys, level, fmt, args ...) \
_LOGPSCI((scu)->inst, subsys, level, "SCU(%s) " fmt, osmo_sccp_user_name(scu), ## args)
#define LOGPSCU(scu, level, fmt, args ...) \

To view, visit change 43763. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I158463c2e9b34abe06554371d628e4fa7ea8c5c1
Gerrit-Change-Number: 43763
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>