Change in libosmo-sccp[master]: xua_snm: Implement handling of DUPU messages

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Wed Feb 10 18:59:54 UTC 2021


laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sccp/+/22835 )


Change subject: xua_snm: Implement handling of DUPU messages
......................................................................

xua_snm: Implement handling of DUPU messages

A DUPU message in SUA and M3UA indicates the unavailability of
a (MTP-level) user, i.e. the entire SCCP, ISUP, ... is not available.

If we receive a DUPU (destination user part unavailable) message in ASP
role, then we must
 * distribute it to any other ASPs for which we operate in SG mode
 * pass it as MTP-STATUS.ind to SCCP, which can then generates
   N-PCSTATE.ind to the SCCP User

Change-Id: I1559ed0f761a8495b222df48c6bd43798e220471
---
M include/osmocom/sigtran/protocol/mtp.h
M src/m3ua.c
M src/osmo_ss7.c
M src/sccp_internal.h
M src/sccp_scmg.c
M src/sua.c
M src/xua_internal.h
M src/xua_snm.c
8 files changed, 222 insertions(+), 1 deletion(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/35/22835/1

diff --git a/include/osmocom/sigtran/protocol/mtp.h b/include/osmocom/sigtran/protocol/mtp.h
index 8b990c0..2f0c7ac 100644
--- a/include/osmocom/sigtran/protocol/mtp.h
+++ b/include/osmocom/sigtran/protocol/mtp.h
@@ -22,3 +22,18 @@
 };
 
 extern const struct value_string mtp_si_vals[];
+
+
+/* Chapter 15.17.5 of Q.705 */
+enum mtp_unavail_cause {
+	MTP_UNAVAIL_C_UNKNOWN		= 0x0,
+	MTP_UNAVAIL_C_UNEQUIP_REM_USER	= 0x1,
+	MTP_UNAVAIL_C_INACC_REM_USER	= 0x2,
+	/* reserved */
+};
+
+extern const struct value_string mtp_unavail_cause_vals[];
+
+static inline const char *mtp_unavail_cause_str(enum mtp_unavail_cause cs) {
+	return get_value_string(mtp_unavail_cause_vals, cs);
+}
diff --git a/src/m3ua.c b/src/m3ua.c
index 6639c28..77326e0 100644
--- a/src/m3ua.c
+++ b/src/m3ua.c
@@ -812,8 +812,29 @@
 }
 #endif
 
+/* 3.4.5 Destination User Part Unavailable (DUPU) */
+static struct xua_msg *m3ua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx,
+					uint32_t dpc, uint16_t user, uint16_t cause,
+					const char *info_string)
+{
+	struct xua_msg *xua = xua_msg_alloc();
+	uint32_t user_cause = (user << 16) | cause;
 
-/* TODO: 3.4.5 Destination User Part Unavailable (DUPU) */
+	xua->hdr = XUA_HDR(M3UA_MSGC_SNM, M3UA_SNM_DUNA);
+	xua->hdr.version = M3UA_VERSION;
+	if (rctx)
+		xua_msg_add_data(xua, M3UA_IEI_ROUTE_CTX, num_rctx * sizeof(*rctx), (const uint8_t *)rctx);
+
+	xua_msg_add_u32(xua, M3UA_IEI_AFFECTED_PC, dpc);
+	xua_msg_add_u32(xua, M3UA_IEI_USER_CAUSE, user_cause);
+
+	if (info_string) {
+		xua_msg_add_data(xua, M3UA_IEI_INFO_STRING,
+				 strlen(info_string)+1,
+				 (const uint8_t *) info_string);
+	}
+	return xua;
+}
 
 /*! Transmit SSNM DUNA/DAVA message indicating [un]availability of certain point code[s]
  *  \param[in] asp ASP through which to transmit message. Must be ACTIVE.
@@ -837,6 +858,21 @@
 	m3ua_tx_xua_asp(asp, xua);
 }
 
+/*! Transmit SSNM DUPU message indicating user unavailability.
+ *  \param[in] asp ASP through which to transmit message. Must be ACTIVE.
+ *  \param[in] rctx array of Routing Contexts in network byte order.
+ *  \param[in] num_rctx number of rctx
+ *  \param[in] dpc affected point code
+ *  \param[in] user the user (SI) that is unavailable
+ *  \param[in] cause the cause of the user unavailability
+ *  \param[in] info_string optional information string (can be NULL). */
+void m3ua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
+		  uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str)
+{
+	struct xua_msg *xua = m3ua_encode_dupu(rctx, num_rctx, dpc, user, cause, info_str);
+	m3ua_tx_xua_asp(asp, xua);
+}
+
 /* received SNM message on ASP side */
 static int m3ua_rx_snm_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
 {
@@ -857,6 +893,8 @@
 		xua_snm_rx_dava(asp, as, xua);
 		break;
 	case M3UA_SNM_DUPU:
+		xua_snm_rx_dupu(asp, as, xua);
+		break;
 	case M3UA_SNM_SCON:
 	case M3UA_SNM_DRST:
 		LOGPASP(asp, DLM3UA, LOGL_NOTICE, "Received unsupported M3UA SNM message type %u\n",
diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c
index e549708..a801cc9 100644
--- a/src/osmo_ss7.c
+++ b/src/osmo_ss7.c
@@ -59,6 +59,13 @@
 static int32_t next_rctx = 1;
 static int32_t next_l_rk_id = 1;
 
+const struct value_string mtp_unavail_cause_vals[] = {
+	{ MTP_UNAVAIL_C_UNKNOWN,		"unknown" },
+	{ MTP_UNAVAIL_C_UNEQUIP_REM_USER,	"unequipped-remote-user" },
+	{ MTP_UNAVAIL_C_INACC_REM_USER,		"inaccessible-remote-user" },
+	{ 0, NULL }
+};
+
 struct value_string osmo_ss7_as_traffic_mode_vals[] = {
 	{ OSMO_SS7_AS_TMOD_BCAST,	"broadcast" },
 	{ OSMO_SS7_AS_TMOD_LOADSHARE,	"loadshare" },
diff --git a/src/sccp_internal.h b/src/sccp_internal.h
index a95b07d..23b3ef3 100644
--- a/src/sccp_internal.h
+++ b/src/sccp_internal.h
@@ -4,6 +4,7 @@
 #include <osmocom/core/prim.h>
 #include <osmocom/sigtran/sccp_sap.h>
 #include <osmocom/sigtran/osmo_ss7.h>
+#include <osmocom/sigtran/protocol/mtp.h>
 
 #define SCCP_STR "Signalling Connection Control Part\n"
 
@@ -141,4 +142,5 @@
 void sccp_scmg_rx_ssn_prohibited(struct osmo_sccp_instance *inst, uint32_t dpc, uint32_t ssn, uint32_t smi);
 void sccp_scmg_rx_mtp_pause(struct osmo_sccp_instance *inst, uint32_t dpc);
 void sccp_scmg_rx_mtp_resume(struct osmo_sccp_instance *inst, uint32_t dpc);
+void sccp_scmg_rx_mtp_status(struct osmo_sccp_instance *inst, uint32_t dpc, enum mtp_unavail_cause cause);
 int sccp_scmg_init(struct osmo_sccp_instance *inst);
diff --git a/src/sccp_scmg.c b/src/sccp_scmg.c
index 49e09ca..a5d6226 100644
--- a/src/sccp_scmg.c
+++ b/src/sccp_scmg.c
@@ -122,6 +122,39 @@
 	 * [this would require us to track SSNs at each PC, which we don't] */
 }
 
+void sccp_scmg_rx_mtp_status(struct osmo_sccp_instance *inst, uint32_t dpc, enum mtp_unavail_cause cause)
+{
+	struct osmo_scu_pcstate_param pcstate;
+	/* 1) Informs the translation function to update the translation tables. */
+	/* 2) In the case where the SCCP has received an MTP-STATUS indication primitive relating to
+	      Mark the status of the SCCP and each SSN for the relevant destination to "prohibited"
+	      and initiates a subsystem status test with SSN = 1. If the cause in the MTP-STATUS
+	      indication primitive indicates "unequipped user", then no subsystem status test is
+	      initiated. */
+	/* 3) Discontinues all subsystem status tests (including SSN = 1) if an MTP-STATUS
+	      indication primitive is received with a cause of "unequipped SCCP". The SCCP
+	      discontinues all subsystem status tests, except for SSN = 1, if an MTP-STATUS
+	      indication primitive is received with a cause of either "unknown" or "inaccessible" */
+	switch (cause) {
+	case MTP_UNAVAIL_C_UNKNOWN:
+	case MTP_UNAVAIL_C_UNEQUIP_REM_USER:
+	case MTP_UNAVAIL_C_INACC_REM_USER:
+		break;
+	}
+
+	/* 4) local broadcast of "user-out-of-service" for each SSN at that dest
+	 * [this would require us to track SSNs at each PC, which we don't] */
+
+	/* 6) local broadcast of "remote SCCP unavailable" */
+	pcstate = (struct osmo_scu_pcstate_param) {
+		.affected_pc = dpc,
+		.restricted_importance_level = 0,
+		.sp_status = OSMO_SCCP_SP_S_ACCESSIBLE,
+		.remote_sccp_status = OSMO_SCCP_REM_SCCP_S_UNAVAILABLE_UNKNOWN,
+	};
+	sccp_lbcs_local_bcast_pcstate(inst, &pcstate);
+}
+
 const struct value_string sccp_scmg_msgt_names[] = {
 	{ SCCP_SCMG_MSGT_SSA, "SSA (Subsystem Allowed)" },
 	{ SCCP_SCMG_MSGT_SSP, "SSP (Subsystem Prohibited)" },
diff --git a/src/sua.c b/src/sua.c
index c9e880f..2ff5a9a 100644
--- a/src/sua.c
+++ b/src/sua.c
@@ -823,6 +823,28 @@
 }
 #endif
 
+/* 3.4.5 Destination User Part Unavailable (DUPU) */
+static struct xua_msg *sua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx,
+					uint32_t dpc, uint16_t user, uint16_t cause,
+					const char *info_string)
+{
+	struct xua_msg *xua = xua_msg_alloc();
+	uint32_t user_cause = (user << 16) | cause;
+
+	xua->hdr = XUA_HDR(SUA_MSGC_SNM, SUA_SNM_DUNA);
+	xua->hdr.version = SUA_VERSION;
+	if (rctx)
+		xua_msg_add_data(xua, SUA_IEI_ROUTE_CTX, num_rctx * sizeof(*rctx), (const uint8_t *)rctx);
+
+	xua_msg_add_u32(xua, SUA_IEI_AFFECTED_PC, dpc);
+	xua_msg_add_u32(xua, SUA_IEI_USER_CAUSE, user_cause);
+
+	if (info_string) {
+		xua_msg_add_data(xua, SUA_IEI_INFO_STRING, strlen(info_string)+1,
+				 (const uint8_t *) info_string);
+	}
+	return xua;
+}
 
 /*! Transmit SSNM DUNA/DAVA message indicating [un]availability of certain point code[s]
  *  \param[in] asp ASP through whihc to transmit message. Must be ACTIVE.
@@ -848,6 +870,21 @@
 	sua_tx_xua_asp(asp, xua);
 }
 
+/*! Transmit SSNM DUPU message indicating user unavailability.
+ *  \param[in] asp ASP through which to transmit message. Must be ACTIVE.
+ *  \param[in] rctx array of Routing Contexts in network byte order.
+ *  \param[in] num_rctx number of rctx
+ *  \param[in] dpc affected point code
+ *  \param[in] user the user (SI) that is unavailable
+ *  \param[in] cause the cause of the user unavailability
+ *  \param[in] info_string optional information string (can be NULL). */
+void sua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
+		 uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str)
+{
+	struct xua_msg *xua = sua_encode_dupu(rctx, num_rctx, dpc, user, cause, info_str);
+	sua_tx_xua_asp(asp, xua);
+}
+
 /* received SNM message on ASP side */
 static int sua_rx_snm_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
 {
@@ -867,6 +904,8 @@
 		xua_snm_rx_dava(asp, as, xua);
 		break;
 	case SUA_SNM_DUPU:
+		xua_snm_rx_dupu(asp, as, xua);
+		break;
 	case SUA_SNM_SCON:
 	case SUA_SNM_DRST:
 		LOGPASP(asp, DLSUA, LOGL_NOTICE, "Received unsupported SUA SNM message type %u\n",
diff --git a/src/xua_internal.h b/src/xua_internal.h
index e76fddf..4c6bb29 100644
--- a/src/xua_internal.h
+++ b/src/xua_internal.h
@@ -21,6 +21,8 @@
 void sua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
 			  const uint32_t *aff_pc, unsigned int num_aff_pc, const uint32_t *aff_ssn,
 			  const uint32_t *smi, const char *info_string, bool available);
+void sua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
+		 uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str);
 
 struct osmo_mtp_prim *m3ua_to_xfer_ind(struct xua_msg *xua);
 int m3ua_hmdc_rx_from_l2(struct osmo_ss7_instance *inst, struct xua_msg *xua);
@@ -28,9 +30,12 @@
 void m3ua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
 			   const uint32_t *aff_pc, unsigned int num_aff_pc,
 			   const char *info_string, bool available);
+void m3ua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
+		  uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str);
 void xua_snm_rx_daud(struct osmo_ss7_asp *asp, struct xua_msg *xua);
 void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua);
 void xua_snm_rx_dava(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua);
+void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua);
 int m3ua_rx_msg(struct osmo_ss7_asp *asp, struct msgb *msg);
 
 struct msgb *m3ua_msgb_alloc(const char *name);
diff --git a/src/xua_snm.c b/src/xua_snm.c
index 2a383c7..0c14964 100644
--- a/src/xua_snm.c
+++ b/src/xua_snm.c
@@ -29,6 +29,7 @@
 #include <osmocom/sigtran/osmo_ss7.h>
 #include <osmocom/sigtran/protocol/m3ua.h>
 #include <osmocom/sigtran/protocol/sua.h>
+#include <osmocom/sigtran/protocol/mtp.h>
 
 #include "xua_internal.h"
 #include "sccp_internal.h"
@@ -99,6 +100,22 @@
 	}
 }
 
+static void xua_tx_upu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
+			uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str)
+{
+	switch (asp->cfg.proto) {
+	case OSMO_SS7_ASP_PROT_M3UA:
+		m3ua_tx_dupu(asp, rctx, num_rctx, dpc, user, cause, info_str);
+		break;
+	case OSMO_SS7_ASP_PROT_SUA:
+		sua_tx_dupu(asp, rctx, num_rctx, dpc, user, cause, info_str);
+		break;
+	default:
+		break;
+	}
+}
+
+
 /* generate MTP-PAUSE / MTP-RESUME towards local SCCP users */
 static void xua_snm_pc_available_to_sccp(struct osmo_sccp_instance *sccp,
 					 const uint32_t *aff_pc, unsigned int num_aff_pc,
@@ -208,6 +225,37 @@
 	}
 }
 
+static void xua_snm_upu(struct osmo_ss7_as *as, uint32_t dpc, uint16_t user, uint16_t cause,
+			const char *info_str)
+{
+	struct osmo_ss7_instance *s7i = as->inst;
+	struct osmo_ss7_asp *asp;
+	uint32_t rctx[32];
+	unsigned int num_rctx;
+
+	/* Translate to MTP-STATUS.ind towards SCCP (will create N-PCSTATE.ind to SCU) */
+	if (s7i->sccp && user == MTP_SI_SCCP)
+		sccp_scmg_rx_mtp_status(s7i->sccp, dpc, cause);
+
+	/* inform remote ASPs via DUPU */
+	llist_for_each_entry(asp, &s7i->asp_list, list) {
+		/* SSNM is only permitted for ASPs in ACTIVE state */
+		if (!osmo_ss7_asp_active(asp))
+			continue;
+
+		/* only send DAVA/DUNA if we locally are the SG and the remote is ASP */
+		if (asp->cfg.role != OSMO_SS7_ASP_ROLE_SG)
+			continue;
+
+		num_rctx = get_all_rctx_for_asp(rctx, ARRAY_SIZE(rctx), asp, as);
+		/* this can happen if the given ASP is only in the AS that reports the change,
+		 * which shall be excluded */
+		if (num_rctx == 0)
+			continue;
+
+		xua_tx_upu(asp, rctx, num_rctx, dpc, user, cause, info_str);
+	}
+}
 
 /* receive DAUD from ASP; pc is 'affected PC' IE with mask in network byte order! */
 void xua_snm_rx_daud(struct osmo_ss7_asp *asp, struct xua_msg *xua)
@@ -323,3 +371,37 @@
 				     ie_aff_pc->len / sizeof(uint32_t), info_str, true);
 	}
 }
+
+/* an incoming SUA/M3UA DUPU was received from a remote SG */
+void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua)
+{
+	uint32_t aff_pc = xua_msg_get_u32(xua, SUA_IEI_AFFECTED_PC);
+	const char *info_str = xua_msg_get_str(xua, SUA_IEI_INFO_STRING);
+	/* TODO: should our processing depend on the RCTX included? I somehow don't think so */
+	//struct xua_msg_part *ie_rctx = xua_msg_find_tag(xua, SUA_IEI_ROUTE_CTX);
+	int log_ss = osmo_ss7_asp_get_log_subsys(asp);
+	uint32_t cause_user;
+	uint16_t cause, user;
+
+	if (asp->cfg.role != OSMO_SS7_ASP_ROLE_ASP)
+		return;
+
+	switch (asp->cfg.proto) {
+	case OSMO_SS7_ASP_PROT_M3UA:
+		cause_user = xua_msg_get_u32(xua, M3UA_IEI_USER_CAUSE);
+		break;
+	case OSMO_SS7_ASP_PROT_SUA:
+		cause_user = xua_msg_get_u32(xua, SUA_IEI_USER_CAUSE);
+		break;
+	default:
+		return;
+	}
+
+	cause = cause_user >> 16;
+	user = cause_user & 0xffff;
+	LOGPASP(asp, log_ss, LOGL_NOTICE, "Rx DUPU(%s) for %s User %s, cause %u\n",
+		info_str ? info_str : "", osmo_ss7_pointcode_print(asp->inst, aff_pc),
+		get_value_string(mtp_si_vals, user), cause);
+
+	xua_snm_upu(as, aff_pc, user, cause, info_str);
+}

-- 
To view, visit https://gerrit.osmocom.org/c/libosmo-sccp/+/22835
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Change-Id: I1559ed0f761a8495b222df48c6bd43798e220471
Gerrit-Change-Number: 22835
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210210/9e74e610/attachment.htm>


More information about the gerrit-log mailing list