[PATCH] libosmo-sccp[master]: WIP: default layer manager using RKM to register PC with SG

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 19:28:48 UTC 2017


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

WIP: default layer manager using RKM to register PC with SG

Change-Id: I78d4623dd213b5c59007a026a6cc3cfe5c04af50
---
M include/osmocom/sigtran/osmo_ss7.h
M include/osmocom/sigtran/sigtran_sap.h
M src/Makefile.am
M src/sccp_sap.c
A src/xua_default_lm_fsm.c
M src/xua_rkm.c
6 files changed, 399 insertions(+), 7 deletions(-)


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

diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h
index e33a9ad..7ddebae 100644
--- a/include/osmocom/sigtran/osmo_ss7.h
+++ b/include/osmocom/sigtran/osmo_ss7.h
@@ -343,7 +343,8 @@
 	bool asp_id_present;
 
 	/* Layer Manager to which we talk */
-	struct osmo_xua_layer_manager *lm;
+	const struct osmo_xua_layer_manager *lm;
+	void *lm_priv;
 
 	struct {
 		char *name;
diff --git a/include/osmocom/sigtran/sigtran_sap.h b/include/osmocom/sigtran/sigtran_sap.h
index d18aa3d..419498e 100644
--- a/include/osmocom/sigtran/sigtran_sap.h
+++ b/include/osmocom/sigtran/sigtran_sap.h
@@ -1,6 +1,8 @@
 #pragma once
 #include <osmocom/core/prim.h>
 
+#include <osmocom/sigtran/osmo_ss7.h>
+
 
 enum osmo_sigtran_sap {
 	SCCP_SAP_USER	= _SAP_SS7_BASE,
@@ -46,14 +48,31 @@
 	uint32_t code;
 };
 
+struct osmo_xlm_prim_rk_reg {
+	/* local routing key ID */
+	uint32_t l_rk_id;
+	/* routing key */
+	struct osmo_ss7_routing_key key;
+	enum osmo_ss7_as_traffic_mode traf_mode;
+};
+
+struct osmo_xlm_prim_rk_dereg {
+	uint32_t route_ctx;
+};
+
 struct osmo_xlm_prim {
 	struct osmo_prim_hdr oph;
 	union {
 		struct osmo_xlm_prim_notify notify;
 		struct osmo_xlm_prim_error error;
+		struct osmo_xlm_prim_rk_reg rk_reg;
+		struct osmo_xlm_prim_rk_dereg rk_dereg;
 	} u;
 };
 
 #define msgb_xlm_prim(msg) ((struct osmo_xlm_prim *)(msg)->l1h)
 
 char *osmo_xlm_prim_name(struct osmo_prim_hdr *oph);
+
+/* XUA LM-SAP towards stack */
+int osmo_xlm_sap_down(struct osmo_ss7_asp *asp, struct osmo_prim_hdr *oph);
diff --git a/src/Makefile.am b/src/Makefile.am
index 7867282..f9b87b0 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 xua_rkm.c \
+			     sccp_user.c xua_rkm.c xua_default_lm_fsm.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/sccp_sap.c b/src/sccp_sap.c
index 2211f71..d4580ae 100644
--- a/src/sccp_sap.c
+++ b/src/sccp_sap.c
@@ -45,11 +45,43 @@
 {
 	const char *name = get_value_string(osmo_scu_prim_names, oph->primitive);
 
-	prim_name_buf[0] = '\0';
-	strncpy(prim_name_buf, name, sizeof(prim_name_buf)-1);
-	prim_name_buf[sizeof(prim_name_buf)-1] = '\0';
-	name = get_value_string(osmo_prim_op_names, oph->operation);
-	strncat(prim_name_buf, name, sizeof(prim_name_buf)-strlen(prim_name_buf)-2);
+	snprintf(prim_name_buf, sizeof(prim_name_buf), "%s.%s", name,
+		 get_value_string(osmo_prim_op_names, oph->operation));
+
+	return prim_name_buf;
+}
+
+
+#include <osmocom/sigtran/sigtran_sap.h>
+
+const struct value_string osmo_xlm_prim_names[] = {
+	{ OSMO_XLM_PRIM_M_SCTP_ESTABLISH,	"M-SCTP_ESTABLISH" },
+	{ OSMO_XLM_PRIM_M_SCTP_RELEASE,		"M-SCTP_RELEASE" },
+	{ OSMO_XLM_PRIM_M_SCTP_RESTART,		"M-SCTP_RESTART" },
+	{ OSMO_XLM_PRIM_M_SCTP_STATUS,		"M-SCTP_STATUS" },
+	{ OSMO_XLM_PRIM_M_ASP_STATUS,		"M-ASP_STATUS" },
+	{ OSMO_XLM_PRIM_M_AS_STATUS,		"M-AS_STATUS" },
+	{ OSMO_XLM_PRIM_M_NOTIFY,		"M-NOTIFY" },
+	{ OSMO_XLM_PRIM_M_ERROR,		"M-ERROR" },
+	{ OSMO_XLM_PRIM_M_ASP_UP,		"M-ASP_UP" },
+	{ OSMO_XLM_PRIM_M_ASP_DOWN,		"M-ASP_DOWN" },
+	{ OSMO_XLM_PRIM_M_ASP_ACTIVE,		"M-ASP_ACTIVE" },
+	{ OSMO_XLM_PRIM_M_ASP_INACTIVE,		"M-ASP_INACTIVE" },
+	{ OSMO_XLM_PRIM_M_AS_ACTIVE,		"M-AS_ACTIVE" },
+	{ OSMO_XLM_PRIM_M_AS_INACTIVE,		"M-AS_INACTIVE" },
+	{ OSMO_XLM_PRIM_M_AS_DOWN,		"M-AS_DOWN" },
+	/* optional as per spec, not implemented yet */
+	{ OSMO_XLM_PRIM_M_RK_REG,		"M-RK_REG" },
+	{ OSMO_XLM_PRIM_M_RK_DEREG,		"M-RK_DEREG" },
+	{ 0, NULL },
+};
+
+char *osmo_xlm_prim_name(struct osmo_prim_hdr *oph)
+{
+	const char *name = get_value_string(osmo_xlm_prim_names, oph->primitive);
+
+	snprintf(prim_name_buf, sizeof(prim_name_buf), "%s.%s", name,
+		 get_value_string(osmo_prim_op_names, oph->operation));
 
 	return prim_name_buf;
 }
diff --git a/src/xua_default_lm_fsm.c b/src/xua_default_lm_fsm.c
new file mode 100644
index 0000000..9606841
--- /dev/null
+++ b/src/xua_default_lm_fsm.c
@@ -0,0 +1,282 @@
+/* Default XUA Layer Manager */
+/* (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/>.
+ */
+
+/* The idea of this default Layer Manager is as follows:
+ * - we wait until a SCTP connection is established
+ * - we issue the ASP-UP request and wait for the ASP being in UP state
+ * - we wait if we receive a M-NOTIFY indication about any AS in this ASP 
+ * - if that's not received, we use RKM to register a routing context
+ *   for our locally configured ASP
+ */
+
+#include <errno.h>
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/sigtran/sigtran_sap.h>
+
+#include "xua_internal.h"
+#include "xua_asp_fsm.h"
+
+#define S(x)	(1 << (x))
+
+enum lm_state {
+	/* idle state, SCTP not connected */
+	S_IDLE,
+	/* we're waiting for the ASP-UP to be confirmed */
+	S_WAIT_ASP_UP,
+	/* we are waiting for any NOTIFY about an AS in this ASP */
+	S_WAIT_NOTIFY,
+	/* we've sent a RK REG REQ and wait for the result */
+	S_RKM_REG,
+	/* all systems up, we're communicating */
+	S_ACTIVE,
+};
+
+enum lm_event {
+	LM_E_SCTP_EST_IND,
+	LM_E_ASP_UP_IND,
+	LM_E_NOTIFY_IND,
+	LM_E_AS_INACTIVE_IND,
+	LM_E_AS_ACTIVE_IND,
+	LM_E_AS_STATUS_IND,
+	LM_E_RKM_REG_CONF,
+	LM_E_SCTP_DISC_IND,
+};
+
+static const struct value_string lm_event_names[] = {
+	{ LM_E_SCTP_EST_IND,	"SCTP-ESTABLISH.ind" },
+	{ LM_E_ASP_UP_IND,	"ASP-UP.ind" },
+	{ LM_E_NOTIFY_IND,	"NOTIFY.ind" },
+	{ LM_E_AS_INACTIVE_IND,	"AS-INACTIVE.ind" },
+	{ LM_E_AS_ACTIVE_IND,	"AS-ACTIVE.ind" },
+	{ LM_E_AS_STATUS_IND,	"AS-STATUS.ind" },
+	{ LM_E_RKM_REG_CONF,	"RKM_REG.conf" },
+	{ LM_E_SCTP_DISC_IND,	"SCTP-RELEASE.ind" },
+	{ 0, NULL }
+};
+
+enum lm_timer {
+	T_WAIT_ASP_UP,
+	T_WAIT_NOTIFY,
+	T_WAIT_NOTIFY_RKM,
+	T_WAIT_RK_REG_RESP,
+};
+
+struct lm_fsm_priv {
+	struct osmo_ss7_asp *asp;
+};
+
+static void lm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct lm_fsm_priv *lmp = fi->priv;
+
+	switch (event) {
+	case LM_E_SCTP_EST_IND:
+		/* Try to transition to ASP-UP */
+		osmo_fsm_inst_state_chg(fi, S_WAIT_ASP_UP, 20, T_WAIT_ASP_UP);
+		osmo_fsm_inst_dispatch(lmp->asp->fi, XUA_ASP_E_M_ASP_UP_REQ, NULL);
+		break;
+	}
+}
+
+static void lm_wait_asp_up(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	switch (event) {
+	case LM_E_ASP_UP_IND:
+		/* ASP is sup, wait for some time if any NOTIFY
+		 * indications about AS in this ASP are received */
+		osmo_fsm_inst_state_chg(fi, S_WAIT_NOTIFY, 2, T_WAIT_NOTIFY);
+		break;
+	}
+}
+
+
+static int lm_timer_cb(struct osmo_fsm_inst *fi)
+{
+	struct lm_fsm_priv *lmp = fi->priv;
+	struct osmo_xlm_prim *prim;
+
+	switch (fi->T) {
+	case T_WAIT_ASP_UP:
+		/* we have been waiting for the ASP to come up, but it
+		 * failed to do so */
+		/* FIXME: kill SCTP connection and re-try? */
+		break;
+	case T_WAIT_NOTIFY:
+		/* No AS has reported via NOTIFY that is was
+		 * (statically) configured at the SG for this ASP, so
+		 * let's dynamically register */
+		osmo_fsm_inst_state_chg(fi, S_RKM_REG, 10, T_WAIT_RK_REG_RESP);
+		prim = xua_xlm_prim_alloc(OSMO_XLM_PRIM_M_RK_REG, PRIM_OP_REQUEST);
+		osmo_xlm_sap_down(lmp->asp, &prim->oph);
+		break;
+	case T_WAIT_NOTIFY_RKM:
+		/* No AS has reported via NOTIFY even after dynamic RKM
+		 * configuration */
+		/* FIXME: disconnect/reconnect SCTP? */
+		break;
+	case T_WAIT_RK_REG_RESP:
+		/* timeout of registration of routing key */
+		/* FIXME: disconnect/reconect SCTP? */
+		break;
+	}
+	return 0;
+}
+
+static void lm_wait_notify(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct lm_fsm_priv *lmp = fi->priv;
+
+	switch (event) {
+	case LM_E_AS_INACTIVE_IND:
+		/* we now know that an AS is associated with this ASP at
+		 * the SG, and that this AS is currently inactive */
+		/* request the ASP to go into active state (which
+		 * hopefully will bring the AS to active, too) */
+		osmo_fsm_inst_state_chg(fi, S_ACTIVE, 0, 0);
+		osmo_fsm_inst_dispatch(lmp->asp->fi, XUA_ASP_E_M_ASP_ACTIVE_REQ, NULL);
+		break;
+	}
+};
+
+static void lm_rkm_reg(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	switch (event) {
+	case LM_E_RKM_REG_CONF:
+		/* RKM registration was successful, we can transition to
+		 * WAIT_NOTIFY state and assume that an
+		 * NOTIFY/AS-INACTIVE arrives within 20 seconds */
+		osmo_fsm_inst_state_chg(fi, S_WAIT_NOTIFY, 20, T_WAIT_NOTIFY_RKM);
+		break;
+	}
+}
+
+static void lm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct lm_fsm_priv *lmp = fi->priv;
+
+	switch (event) {
+	case LM_E_AS_INACTIVE_IND:
+		/* request the ASP to go into active state */
+		osmo_fsm_inst_dispatch(lmp->asp->fi, XUA_ASP_E_M_ASP_ACTIVE_REQ, NULL);
+		break;
+	}
+}
+
+static void lm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	switch (event) {
+	case LM_E_SCTP_DISC_IND:
+		/* FIXME: disconnect/reconnect SCTP? */
+		break;
+	}
+}
+
+static const struct osmo_fsm_state lm_states[] = {
+	[S_IDLE] = {
+		.in_event_mask = S(LM_E_SCTP_EST_IND),
+		.out_state_mask = S(S_WAIT_NOTIFY),
+		.name = "IDLE",
+		.action = lm_idle,
+	},
+	[S_WAIT_ASP_UP] = {
+		.in_event_mask = S(LM_E_ASP_UP_IND),
+		.out_state_mask = S(S_WAIT_NOTIFY),
+		.name = "WAIT_ASP_UP",
+		.action = lm_wait_asp_up,
+	},
+	[S_WAIT_NOTIFY] = {
+		.in_event_mask = S(LM_E_AS_INACTIVE_IND) | S(LM_E_NOTIFY_IND),
+		.out_state_mask = S(S_RKM_REG) | S(S_ACTIVE),
+		.name = "WAIT_NOTIFY",
+		.action = lm_wait_notify,
+	},
+	[S_RKM_REG] = {
+		.in_event_mask = S(LM_E_RKM_REG_CONF),
+		.out_state_mask = S(S_WAIT_NOTIFY),
+		.name = "RKM_REG",
+		.action = lm_rkm_reg,
+	},
+	[S_ACTIVE] = {
+		.in_event_mask = S(LM_E_AS_INACTIVE_IND),
+		.name = "ACTIVE",
+		.action = lm_active,
+	},
+};
+
+/* Map from incoming XLM SAP primitives towards FSM events */
+static const struct osmo_prim_event_map lm_event_map[] = {
+	{ XUA_SAP_LM, OSMO_XLM_PRIM_M_SCTP_ESTABLISH, PRIM_OP_INDICATION, LM_E_SCTP_EST_IND },
+	{ XUA_SAP_LM, OSMO_XLM_PRIM_M_SCTP_RELEASE, PRIM_OP_INDICATION, LM_E_SCTP_DISC_IND },
+	{ XUA_SAP_LM, OSMO_XLM_PRIM_M_AS_STATUS, PRIM_OP_INDICATION, LM_E_AS_STATUS_IND },
+	{ XUA_SAP_LM, OSMO_XLM_PRIM_M_NOTIFY, PRIM_OP_INDICATION, LM_E_NOTIFY_IND },
+	{ XUA_SAP_LM, OSMO_XLM_PRIM_M_AS_INACTIVE, PRIM_OP_INDICATION, LM_E_AS_INACTIVE_IND },
+	{ XUA_SAP_LM, OSMO_XLM_PRIM_M_AS_ACTIVE, PRIM_OP_INDICATION, LM_E_AS_ACTIVE_IND },
+	{ XUA_SAP_LM, OSMO_XLM_PRIM_M_RK_REG, PRIM_OP_CONFIRM, LM_E_RKM_REG_CONF },
+	{ 0, 0, OSMO_NO_EVENT },
+};
+
+
+struct osmo_fsm default_lm_fsm = {
+	.name = "XUA default LM",
+	.states = lm_states,
+	.num_states = ARRAY_SIZE(lm_states),
+	.timer_cb = lm_timer_cb,
+	.event_names = lm_event_names,
+	.allstate_event_mask = S(LM_E_SCTP_DISC_IND),
+	.allstate_action = lm_allstate,
+};
+
+
+/* layer manager primitive call-back function, registered osmo_ss7 */
+static int default_lm_prim_cb(struct osmo_prim_hdr *oph, void *_asp)
+{
+	struct osmo_ss7_asp *asp = _asp;
+	struct osmo_fsm_inst *fi = asp->lm_priv;
+	uint32_t event = osmo_event_for_prim(oph, lm_event_map);
+
+	osmo_fsm_inst_dispatch(fi, event, oph);
+
+	return 0;
+}
+
+static const struct osmo_xua_layer_manager default_layer_manager = {
+	.prim_cb = default_lm_prim_cb,
+};
+
+int xua_asp_use_default_lm(struct osmo_ss7_asp *asp, int log_level)
+{
+	struct lm_fsm_priv *lmp;
+	struct osmo_fsm_inst *fi;
+
+	fi = osmo_fsm_inst_alloc(&default_lm_fsm, asp, NULL, log_level, asp->cfg.name);
+
+	lmp = talloc_zero(fi, struct lm_fsm_priv);
+	if (!lmp) {
+		osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
+		return -ENOMEM;
+	}
+	lmp->asp = asp;
+	fi->priv = lmp;
+
+	asp->lm = &default_layer_manager;
+	asp->lm_priv = fi;
+
+	return 0;
+}
+
diff --git a/src/xua_rkm.c b/src/xua_rkm.c
index 12d59c7..d906db4 100644
--- a/src/xua_rkm.c
+++ b/src/xua_rkm.c
@@ -75,6 +75,41 @@
 	return msg->tail - old_tail;
 }
 
+static void xua_rkm_send_reg_req(struct osmo_ss7_asp *asp, uint32_t l_rk_id,
+				 const struct osmo_ss7_routing_key *rkey,
+				 enum osmo_ss7_as_traffic_mode traf_mode)
+{
+	struct msgb *msg = m3ua_msgb_alloc(__func__);
+	int tmod = osmo_ss7_tmode_to_xua(traf_mode);
+
+	/* One individual Registration Request according to Chapter 3.6.1 */
+	msgb_put_u16(msg, M3UA_IEI_ROUT_KEY); /* outer IEI */
+	msgb_put_u16(msg, 32 + 4); /* outer length */
+	/* nested IEIs */
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_LOC_RKEY_ID, l_rk_id);
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_ROUTE_CTX, rkey->context);
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_TRAF_MODE_TYP, tmod);
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_DEST_PC, rkey->pc);
+
+	msgb_push_m3ua_hdr(msg, M3UA_MSGC_RKM, M3UA_RKM_REG_REQ);
+
+	osmo_ss7_asp_send(asp, msg);
+}
+
+static void xua_rkm_send_dereg_req(struct osmo_ss7_asp *asp, uint32_t route_ctx)
+{
+	struct msgb *msg = m3ua_msgb_alloc(__func__);
+
+	/* One individual De-Registration Request according to Chapter 3.6.3 */
+	msgb_t16l16vp_put_u32(msg, M3UA_IEI_ROUTE_CTX, route_ctx);
+
+	msgb_push_m3ua_hdr(msg, M3UA_MSGC_RKM, M3UA_RKM_DEREG_REQ);
+
+	osmo_ss7_asp_send(asp, msg);
+}
+
+
+
 /* 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)
@@ -294,3 +329,26 @@
 	}
 	return rc;
 }
+
+int osmo_xlm_sap_down(struct osmo_ss7_asp *asp, struct osmo_prim_hdr *oph)
+{
+	struct osmo_xlm_prim *prim = (struct osmo_xlm_prim *) oph;
+
+	LOGPASP(asp, DLSS7, LOGL_DEBUG, "Received XUA Layer Manager Primitive: %s)\n",
+		osmo_xlm_prim_name(&prim->oph));
+
+	switch (OSMO_PRIM_HDR(&prim->oph)) {
+	case OSMO_PRIM(OSMO_XLM_PRIM_M_RK_REG, PRIM_OP_REQUEST):
+		xua_rkm_send_reg_req(asp, prim->u.rk_reg.l_rk_id, &prim->u.rk_reg.key,
+					prim->u.rk_reg.traf_mode);
+		break;
+	case OSMO_PRIM(OSMO_XLM_PRIM_M_RK_DEREG, PRIM_OP_REQUEST):
+		xua_rkm_send_dereg_req(asp, prim->u.rk_dereg.route_ctx);
+		break;
+	default:
+		LOGPASP(asp, DLSS7, LOGL_ERROR, "Unknown XUA Layer Manager Primitive: %s\n",
+			osmo_xlm_prim_name(&prim->oph));
+	}
+
+	return 0;
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I78d4623dd213b5c59007a026a6cc3cfe5c04af50
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