Change in libosmo-sccp[master]: sccp: Add minimalistic SCMG implementation

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
Thu Feb 11 11:58:11 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sccp/+/22789 )

Change subject: sccp: Add minimalistic SCMG implementation
......................................................................

sccp: Add minimalistic SCMG implementation

SCMG (SCCP Management) is a special sub-system that normally resides
at SSN=1.  In Osmocom we so far ignored its existence.  However,
in terms of interop with other implementation, we should implement
at least some basic features.

The only procedure implemented in this initial commit is the response
to an incoming SST (Subsystem Test) message.  If we don't respond to
this message, a remote SCCP entity could assume the SSN is dead on
our side, rendering communication impossible.

Change-Id: I04b162476f7652ef0540b5ea7299e9447efd1d09
---
M include/osmocom/sigtran/Makefile.am
A include/osmocom/sigtran/protocol/sccp_scmg.h
M src/sccp_internal.h
M src/sccp_scmg.c
M src/sccp_user.c
5 files changed, 166 insertions(+), 1 deletion(-)

Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved



diff --git a/include/osmocom/sigtran/Makefile.am b/include/osmocom/sigtran/Makefile.am
index 0aa90cb..d9cc20c 100644
--- a/include/osmocom/sigtran/Makefile.am
+++ b/include/osmocom/sigtran/Makefile.am
@@ -3,5 +3,6 @@
 
 sigtrandir = $(includedir)/osmocom/sigtran
 
-sigtran_prot_HEADERS = protocol/sua.h protocol/m3ua.h protocol/mtp.h
+sigtran_prot_HEADERS = protocol/sua.h protocol/m3ua.h protocol/mtp.h \
+		       protocol/sccp_scmg.h
 sigtran_protdir = $(includedir)/osmocom/sigtran/protocol
diff --git a/include/osmocom/sigtran/protocol/sccp_scmg.h b/include/osmocom/sigtran/protocol/sccp_scmg.h
new file mode 100644
index 0000000..5d97828
--- /dev/null
+++ b/include/osmocom/sigtran/protocol/sccp_scmg.h
@@ -0,0 +1,25 @@
+#pragma once
+
+/* SCCP Management as per Section 5.3 of ITU-T Q.713 */
+
+enum sccp_scmg_msg_type {
+	SCCP_SCMG_MSGT_SSA	= 0x01,	/* Subsystem Allowed */
+	SCCP_SCMG_MSGT_SSP	= 0x02,	/* Subsystem Prohibited */
+	SCCP_SCMG_MSGT_SST	= 0x03,	/* Subsystem Status Test */
+	SCCP_SCMG_MSGT_SOR	= 0x04,	/* Subsystem Out-of-service Request */
+	SCCP_SCMG_MSGT_SOG	= 0x05,	/* Subsystem Out-of-service Grant */
+	SCCP_SCMG_MSGT_SSC	= 0x06,	/* Subsystem Congested */
+};
+
+struct sccp_scmg_msg {
+	uint8_t msg_type;	/* enum sccp_scmg_msg_type */
+	uint8_t affected_ssn;
+	uint16_t affected_pc;
+	uint8_t smi;
+	/* one octet, only in case of SSC */
+	uint8_t ssc_congestion_lvl[0];
+} __attribute__ ((packed));
+
+extern const struct value_string sccp_scmg_msgt_names[];
+static inline const char *sccp_scmg_msgt_name(enum sccp_scmg_msg_type msgt)
+{ return get_value_string(sccp_scmg_msgt_names, msgt); }
diff --git a/src/sccp_internal.h b/src/sccp_internal.h
index 6ad7ee3..6bd2af9 100644
--- a/src/sccp_internal.h
+++ b/src/sccp_internal.h
@@ -139,3 +139,4 @@
 /* SCCP Management (SCMG) */
 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);
+int sccp_scmg_init(struct osmo_sccp_instance *inst);
diff --git a/src/sccp_scmg.c b/src/sccp_scmg.c
index 4a8ccf6..0e3905d 100644
--- a/src/sccp_scmg.c
+++ b/src/sccp_scmg.c
@@ -30,6 +30,7 @@
 
 #include <osmocom/sigtran/sccp_sap.h>
 #include <osmocom/sigtran/protocol/sua.h>
+#include <osmocom/sigtran/protocol/sccp_scmg.h>
 #include <osmocom/sccp/sccp_types.h>
 
 #include "xua_internal.h"
@@ -81,3 +82,133 @@
 	/* 8) local broadcast of "user-in-service"
 	 * [this would require us to track SSNs at each PC, which we don't] */
 }
+
+const struct value_string sccp_scmg_msgt_names[] = {
+	{ SCCP_SCMG_MSGT_SSA, "SSA (Subsystem Allowed)" },
+	{ SCCP_SCMG_MSGT_SSP, "SSP (Subsystem Prohibited)" },
+	{ SCCP_SCMG_MSGT_SST, "SST (Subsystem Status Test)" },
+	{ SCCP_SCMG_MSGT_SOR, "SOR (Subsystem Out-of-service Request)" },
+	{ SCCP_SCMG_MSGT_SOG, "SOG (Subsystem Out-of-service Grant)" },
+	{ SCCP_SCMG_MSGT_SSC, "SSC (Subsystem Congested)" },
+	{ 0, NULL }
+};
+
+static int sccp_scmg_tx(struct osmo_sccp_user *scu, const struct osmo_sccp_addr *calling_addr,
+			const struct osmo_sccp_addr *called_addr,
+			uint8_t msg_type, uint8_t ssn, uint16_t pc, uint8_t smi, uint8_t *ssc_cong_lvl)
+{
+	struct msgb *msg = sccp_msgb_alloc(__func__);
+	struct osmo_scu_prim *prim;
+	struct osmo_scu_unitdata_param *param;
+	struct sccp_scmg_msg *scmg;
+
+	/* fill primitive header */
+	prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
+	param = &prim->u.unitdata;
+	memcpy(&param->calling_addr, calling_addr, sizeof(*calling_addr));
+	memcpy(&param->called_addr, called_addr, sizeof(*called_addr));
+	osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_REQUEST, msg);
+
+	/* Fill the actual SCMG message */
+	msg->l2h = msgb_put(msg, sizeof(*scmg));
+	scmg = (struct sccp_scmg_msg *) msg->l2h;
+	scmg->msg_type = msg_type;
+	scmg->affected_ssn = ssn;
+	scmg->affected_pc = pc;
+	scmg->smi = smi;
+
+	/* add congestion level in case of SSC message */
+	if (msg_type == SCCP_SCMG_MSGT_SSC) {
+		msgb_put(msg, 1);
+		OSMO_ASSERT(ssc_cong_lvl);
+		scmg->ssc_congestion_lvl[1] = *ssc_cong_lvl;
+	}
+
+	return osmo_sccp_user_sap_down(scu, &prim->oph);
+}
+
+
+/* Subsystem Test received */
+static int scmg_rx_sst(struct osmo_sccp_user *scu, const struct osmo_sccp_addr *calling_addr,
+			const struct osmo_sccp_addr *called_addr, const struct sccp_scmg_msg *sst)
+{
+	/* Q.714 5.3.4.3 Actions at the receiving side (of SST) */
+
+	/* check "ignore subsystem status test" and bail out */
+	/* check if SSN in question is available. If yes, return SSA. If not, ignore */
+	scu = sccp_user_find(scu->inst, sst->affected_ssn, sst->affected_pc);
+	if (!scu)
+		return 0;
+
+	/* is subsystem available? */
+	if (0 /* !subsys_available(scu) */)
+		return 0;
+
+	return sccp_scmg_tx(scu, called_addr, calling_addr, SCCP_SCMG_MSGT_SSA,
+			    sst->affected_ssn, sst->affected_pc, 0, NULL);
+}
+
+static int scmg_rx(struct osmo_sccp_user *scu, const struct osmo_sccp_addr *calling_addr,
+		   const struct osmo_sccp_addr *called_addr, const struct sccp_scmg_msg *scmg)
+{
+	switch (scmg->msg_type) {
+	case SCCP_SCMG_MSGT_SST:
+		return scmg_rx_sst(scu, calling_addr, called_addr, scmg);
+	case SCCP_SCMG_MSGT_SSP:
+	case SCCP_SCMG_MSGT_SSA:
+	case SCCP_SCMG_MSGT_SOR:
+	case SCCP_SCMG_MSGT_SOG:
+	case SCCP_SCMG_MSGT_SSC:
+	default:
+		LOGP(DLSCCP, LOGL_NOTICE, "Rx unsupported SCCP SCMG %s, ignoring",
+			sccp_scmg_msgt_name(scmg->msg_type));
+		break;
+	}
+	return 0;
+}
+
+/* main entry point for SCCP user primitives from SCRC/SCOC */
+static int scmg_prim_cb(struct osmo_prim_hdr *oph, void *_scu)
+{
+	struct osmo_sccp_user *scu = _scu;
+	struct osmo_scu_prim *prim = (struct osmo_scu_prim *) oph;
+	struct osmo_scu_unitdata_param *param;
+	struct sccp_scmg_msg *scmg;
+	int rc = 0;
+
+	switch (OSMO_PRIM_HDR(oph)) {
+	case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
+		param = &prim->u.unitdata;
+		scmg = msgb_l2(oph->msg);
+		/* ensure minimum length based on message type */
+		if (msgb_l2len(oph->msg) < sizeof(*scmg)) {
+			rc = -1;
+			break;
+		}
+		if (scmg->msg_type == SCCP_SCMG_MSGT_SSC && msgb_l2len(oph->msg) < sizeof(*scmg)+1) {
+			rc = -1;
+			break;
+		}
+		/* interestingly, PC is specified to be encoded in little endian ?!? */
+		scmg->affected_pc = osmo_load16le(&scmg->affected_pc);
+		rc = scmg_rx(scu, &param->calling_addr, &param->called_addr, scmg);
+		break;
+	default:
+		LOGP(DLSCCP, LOGL_ERROR, "unsupported SCCP user primitive %s\n",
+			osmo_scu_prim_name(oph));
+		break;
+	}
+
+	msgb_free(oph->msg);
+	return rc;
+}
+
+/* register SCMG as SCCP user for SSN=1 */
+int sccp_scmg_init(struct osmo_sccp_instance *inst)
+{
+	struct osmo_sccp_user *scu;
+	scu = osmo_sccp_user_bind(inst, "SCCP Maangement", scmg_prim_cb, SCCP_SSN_MANAGEMENT);
+	if (!scu)
+		return -1;
+	return 0;
+}
diff --git a/src/sccp_user.c b/src/sccp_user.c
index 880cab1..d8e78f0 100644
--- a/src/sccp_user.c
+++ b/src/sccp_user.c
@@ -220,6 +220,7 @@
 osmo_sccp_instance_create(struct osmo_ss7_instance *ss7, void *priv)
 {
 	struct osmo_sccp_instance *inst;
+	int rc;
 
 	inst = talloc_zero(ss7, struct osmo_sccp_instance);
 	if (!inst)
@@ -235,6 +236,12 @@
 	inst->ss7_user.prim_cb = mtp_user_prim_cb;
 	inst->ss7_user.priv = inst;
 
+	rc = sccp_scmg_init(inst);
+	if (rc < 0) {
+		talloc_free(inst);
+		return NULL;
+	}
+
 	osmo_ss7_user_register(ss7, MTP_SI_SCCP, &inst->ss7_user);
 
 	llist_add_tail(&inst->list, &sccp_instances);

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

Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Change-Id: I04b162476f7652ef0540b5ea7299e9447efd1d09
Gerrit-Change-Number: 22789
Gerrit-PatchSet: 3
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210211/35b10b7f/attachment.htm>


More information about the gerrit-log mailing list