[PATCH] libosmo-sccp[master]: Add M3UA RKM (routing key management) support, SGW side only

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/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Sun Apr 9 16:57:01 UTC 2017


Review at  https://gerrit.osmocom.org/2260

Add M3UA RKM (routing key management) support, SGW side only

Change-Id: I9b1cf438a42519c0fe2f555c1672fafa499122a1
---
M src/Makefile.am
M src/m3ua.c
M src/xua_internal.h
A src/xua_rkm.c
4 files changed, 289 insertions(+), 2 deletions(-)


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

diff --git a/src/Makefile.am b/src/Makefile.am
index a4cfeeb..7867282 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,7 +28,7 @@
 
 libosmo_sigtran_la_SOURCES = sccp_sap.c sua.c m3ua.c xua_msg.c sccp_helpers.c \
 			     sccp2sua.c sccp_scrc.c sccp_sclc.c sccp_scoc.c \
-			     sccp_user.c \
+			     sccp_user.c xua_rkm.c \
 			     osmo_ss7.c osmo_ss7_hmrt.c xua_asp_fsm.c xua_as_fsm.c
 libosmo_sigtran_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined -export-symbols-regex '^osmo_'
 libosmo_sigtran_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMONETIF_LIBS) $(LIBSCTP_LIBS)
diff --git a/src/m3ua.c b/src/m3ua.c
index 4f20c6e..5708985 100644
--- a/src/m3ua.c
+++ b/src/m3ua.c
@@ -666,8 +666,10 @@
 	case M3UA_MSGC_MGMT:
 		rc = m3ua_rx_mgmt(asp, xua);
 		break;
-	case M3UA_MSGC_SNM:
 	case M3UA_MSGC_RKM:
+		rc = m3ua_rx_rkm(asp, xua);
+		break;
+	case M3UA_MSGC_SNM:
 		/* FIXME */
 		LOGPASP(asp, DLM3UA, LOGL_NOTICE, "Received unsupported M3UA "
 			"Message Class %u\n", xua->hdr.msg_class);
diff --git a/src/xua_internal.h b/src/xua_internal.h
index c6f79b7..24fcb1c 100644
--- a/src/xua_internal.h
+++ b/src/xua_internal.h
@@ -58,3 +58,4 @@
 struct xua_msg *m3ua_encode_notify(const struct m3ua_notify_params *npar);
 int m3ua_decode_notify(struct m3ua_notify_params *npar, void *ctx,
 			const struct xua_msg *xua);
+int m3ua_rx_rkm(struct osmo_ss7_asp *asp, struct xua_msg *xua);
diff --git a/src/xua_rkm.c b/src/xua_rkm.c
new file mode 100644
index 0000000..5215af1
--- /dev/null
+++ b/src/xua_rkm.c
@@ -0,0 +1,284 @@
+/* xUA Routing Key Management (RKM) as per RFC 4666 */
+/* (C) 2017 by Harald Welte <laforge at gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arpa/inet.h>
+
+#include <osmocom/core/logging.h>
+#include <osmocom/core/linuxlist.h>
+
+#include <osmocom/sigtran/xua_msg.h>
+#include <osmocom/sigtran/osmo_ss7.h>
+#include <osmocom/sigtran/protocol/m3ua.h>
+
+#include "xua_internal.h"
+
+/* push a M3UA header to the front of the given message */
+static void msgb_push_m3ua_hdr(struct msgb *msg, uint8_t msg_class, uint8_t msg_type)
+{
+	struct xua_common_hdr *hdr;
+
+	msg->l2h = msgb_push(msg, sizeof(*msg));
+	hdr = (struct xua_common_hdr *) msg->l2h;
+
+	hdr->version = M3UA_VERSION;
+	hdr->spare = 0;
+	hdr->msg_class = msg_class;
+	hdr->msg_type = msg_type;
+	hdr->msg_length = htonl(msgb_l2len(msg));
+}
+
+/* append a single registration result to given msgb */
+static int msgb_append_reg_res(struct msgb *msg, uint32_t local_rk_id,
+				uint32_t status, uint32_t rctx)
+{
+	uint8_t *old_tail = msg->tail;
+
+	/* One individual Registration Result according to Chapter 3.6.2 */
+	msgb_put_u16(msg, M3UA_IEI_REG_RESULT); /* outer IEI */
+	msgb_put_u16(msg, 24 + 4); /* outer length */
+	/* nested IEIs */
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_LOC_RKEY_ID, local_rk_id);
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_REG_STATUS, status);
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_ROUTE_CTX, rctx);
+
+	return msg->tail - old_tail;
+}
+
+/* append a single de-registration result to given msgb */
+static int msgb_append_dereg_res(struct msgb *msg,
+				 uint32_t status, uint32_t rctx)
+{
+	uint8_t *old_tail = msg->tail;
+
+	/* One individual De-Registration Result according to Chapter 3.6.4 */
+	msgb_put_u16(msg, M3UA_IEI_DEREG_RESULT); /* outer IEI */
+	msgb_put_u16(msg, 16 + 4); /* outer length */
+	/* nested IEIs */
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_ROUTE_CTX, rctx);
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_DEREG_STATUS, status);
+
+	return msg->tail - old_tail;
+}
+
+/* handle a single registration request IE (nested IEs in 'innner' */
+static int handle_rkey_reg(struct osmo_ss7_asp *asp, struct xua_msg *inner,
+			   struct msgb *resp)
+{
+	uint32_t rk_id, rctx, _tmode, dpc;
+	enum osmo_ss7_as_traffic_mode tmode;
+	struct osmo_ss7_as *as;
+	struct osmo_ss7_route *rt;
+	char namebuf[32];
+
+	/* mandatory local routing key ID */
+	rk_id = xua_msg_get_u32(inner, M3UA_IEI_LOC_RKEY_ID);
+	/* ASP may already include a routing context value here */
+	rctx = xua_msg_get_u32(inner, M3UA_IEI_ROUTE_CTX);
+
+	/* traffic mode type (0 = undefined) */
+	_tmode = xua_msg_get_u32(inner, M3UA_IEI_TRAF_MODE_TYP);
+	tmode = osmo_ss7_tmode_from_xua(_tmode);
+
+	/* destination point code (mandatory) */
+	dpc = xua_msg_get_u32(inner, M3UA_IEI_DEST_PC);
+
+	/* We don't support routing keys with the following criteria, so
+	 * we have to reject those */
+	/* TODO: network appearance (optional) */
+	/* TODO: service indicators (optional) */
+	/* TODO: originating point code list (optional) */
+	if (xua_msg_find_tag(inner, M3UA_IEI_NET_APPEAR) ||
+	    xua_msg_find_tag(inner, M3UA_IEI_SVC_IND) ||
+	    xua_msg_find_tag(inner, M3UA_IEI_ORIG_PC)) {
+		LOGPASP(asp, DLSS7, LOGL_NOTICE, "Unsupported Routing Key\n");
+		msgb_append_reg_res(resp, rk_id, M3UA_RKM_REG_ERR_UNSUPP_RK_PARAM, 0);
+		return -1;
+	}
+
+	/* if the ASP did not include a routing context number, allocate
+	 * one locally (will be part of response) */
+	if (!rctx)
+		rctx = osmo_ss7_find_free_rctx(asp->inst);
+
+	LOGPASP(asp, DLSS7, LOGL_INFO, "Registering routing key %u for DPC %s\n",
+		rctx, osmo_ss7_pointcode_print(asp->inst, dpc));
+
+	/* check if there is already an AS for this routing key */
+	if (osmo_ss7_as_find_by_rctx(asp->inst, rctx)) {
+		LOGPASP(asp, DLSS7, LOGL_NOTICE, "RCTX %u already in use\n", rctx);
+		msgb_append_reg_res(resp, rk_id, M3UA_RKM_REG_ERR_RKEY_ALRDY_REGD, 0);
+		return -1;
+	}
+
+	/* Create an AS for this routing key */
+	snprintf(namebuf, sizeof(namebuf), "as-rkm-%u", rctx);
+	as = osmo_ss7_as_find_or_create(asp->inst, namebuf, OSMO_SS7_ASP_PROT_M3UA);
+	if (!as) {
+		msgb_append_reg_res(resp, rk_id, M3UA_RKM_REG_ERR_INSUFF_RESRC, 0);
+		return -1;
+	}
+
+	as->cfg.description = talloc_strdup(as, "Auto-generated by RKM");
+	as->cfg.mode = tmode;
+	/* fill routing key */
+	as->cfg.routing_key.context = rctx;
+	as->cfg.routing_key.pc = dpc;
+
+	/* add route for that routing key */
+	rt = osmo_ss7_route_create(as->inst->rtable_system, dpc, 0xFFFFFF, namebuf);
+	if (!rt) {
+		osmo_ss7_as_destroy(as);
+		msgb_append_reg_res(resp, rk_id, M3UA_RKM_REG_ERR_CANT_SUPP_UNQ_RT, 0);
+		return -1;
+	}
+
+	/* Success: Add just-create AS to connected ASP + report success */
+	osmo_ss7_as_add_asp(as, asp->cfg.name);
+	msgb_append_reg_res(resp, rk_id, M3UA_RKM_REG_SUCCESS, rctx);
+	return 0;
+}
+
+/* receive a deregistration requuest (SG role) */
+static int m3ua_rx_rkm_reg_req(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+{
+	struct xua_msg_part *part;
+	struct msgb *resp = m3ua_msgb_alloc(__func__);
+
+	/* iterate over all routing key IEs in message */
+	llist_for_each_entry(part, &xua->headers, entry) {
+		struct xua_msg *inner;
+
+		if (part->tag != M3UA_IEI_ROUT_KEY)
+			continue;
+
+		inner = xua_from_nested(part);
+		if (!inner) {
+			LOGPASP(asp, DLSS7, LOGL_NOTICE, "Unable to parse "
+				"nested IE for Routing Key\n");
+			continue;
+		}
+		/* handle single registration and append result to
+		 * 'resp' */
+		handle_rkey_reg(asp, inner, resp);
+	}
+	msgb_push_m3ua_hdr(resp, M3UA_MSGC_RKM, M3UA_RKM_REG_RSP);
+
+	return 0;
+}
+
+/* receive a deregistration requuest (SG role) */
+static int handle_rkey_dereg(struct osmo_ss7_asp *asp, uint32_t rctx,
+			     struct msgb *resp)
+{
+	struct osmo_ss7_instance *inst = asp->inst;
+	struct osmo_ss7_as *as;
+	struct osmo_ss7_route *rt;
+
+	as = osmo_ss7_as_find_by_rctx(inst, rctx);
+	if (!as) {
+		msgb_append_dereg_res(resp, M3UA_RKM_DEREG_ERR_INVAL_RCTX, 0);
+		return -1;
+	}
+
+	/* Reject if ASP is not even part of AS */
+	if (!osmo_ss7_as_has_asp(as, asp)) {
+		msgb_append_dereg_res(resp, M3UA_RKM_DEREG_ERR_INVAL_RCTX, 0);
+		return -1;
+	}
+
+	/* FIXME Reject if any ASP stillactively using this RCTX */
+
+	rt = osmo_ss7_route_find_dpc(inst->rtable_system, as->cfg.routing_key.pc);
+	if (!rt) {
+		msgb_append_dereg_res(resp, M3UA_RKM_DEREG_ERR_UNKNOWN, 0);
+		return -1;
+	}
+
+	LOGPASP(asp, DLSS7, LOGL_INFO, "De-Registering rctx %u for DPC %s\n",
+		rctx, osmo_ss7_pointcode_print(inst, as->cfg.routing_key.pc));
+
+	/* remove route + AS definition */
+	osmo_ss7_route_destroy(rt);
+	osmo_ss7_as_destroy(as);
+	/* report success */
+	msgb_append_dereg_res(resp, M3UA_RKM_DEREG_SUCCESS, rctx);
+
+	return 0;
+}
+
+static int m3ua_rx_rkm_dereg_req(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+{
+	struct xua_msg_part *part = xua_msg_find_tag(xua, M3UA_IEI_ROUTE_CTX);
+	struct msgb *resp = m3ua_msgb_alloc(__func__);
+	uint32_t *rctx;
+
+	if (!part)
+		return -1;
+
+	for (rctx = (uint32_t *)part->dat; (uint8_t *)rctx < part->dat + part->len; rctx++)
+		handle_rkey_dereg(asp, ntohl(*rctx), resp);
+
+	msgb_push_m3ua_hdr(resp, M3UA_MSGC_RKM, M3UA_RKM_DEREG_RSP);
+
+	return 0;
+}
+
+/* receive a registration response (ASP role) */
+static int m3ua_rx_rkm_reg_rsp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+{
+	/* TODO */
+}
+
+/* receive a deregistration response (ASP role) */
+static int m3ua_rx_rkm_dereg_rsp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+{
+	/* TODO */
+}
+
+/* process an incoming RKM message in xua format */
+int m3ua_rx_rkm(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+{
+	int rc;
+
+	switch (xua->hdr.msg_type) {
+	/* SG Side */
+	case M3UA_RKM_REG_REQ:
+		/* TOOD: ensure we are role SG */
+		rc = m3ua_rx_rkm_reg_req(asp, xua);
+		break;
+	case M3UA_RKM_DEREG_REQ:
+		/* TOOD: ensure we are role SG */
+		rc = m3ua_rx_rkm_dereg_req(asp, xua);
+		break;
+	/* ASP Side */
+	case M3UA_RKM_REG_RSP:
+		/* TOOD: ensure we are role ASP */
+		rc = m3ua_rx_rkm_reg_rsp(asp, xua);
+		break;
+	case M3UA_RKM_DEREG_RSP:
+		/* TOOD: ensure we are role ASP */
+		rc = m3ua_rx_rkm_dereg_rsp(asp, xua);
+		break;
+	default:
+		LOGPASP(asp, DLSS7, LOGL_ERROR, "Received unknown RKM msg_type %u\n",
+			xua->hdr.msg_type);
+		rc = -1;
+		break;
+	}
+	return rc;
+}

-- 
To view, visit https://gerrit.osmocom.org/2260
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I9b1cf438a42519c0fe2f555c1672fafa499122a1
Gerrit-PatchSet: 1
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>



More information about the gerrit-log mailing list