[PATCH] libosmo-sccp[master]: SUA/M3UA: Implement T(r) recovery timer of Application Serve...

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
Fri Apr 14 20:49:05 UTC 2017


Hello Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/2349

to look at the new patch set (#2).

SUA/M3UA: Implement T(r) recovery timer of Application Server FSM

When an AS goes "down" it first entres a recovery state, in which any
to-be-transmitted messages are enqueued until the timer T(r) expires.

Once the timer expires, the messages are discarded.  If the AS goes
ACTIVE before timer expiration, queued messages are sent.

Change-Id: I22725bf35306299a00c66d7b3637f5e198c26247
---
M src/m3ua.c
M src/sua.c
M src/xua_as_fsm.c
M src/xua_as_fsm.h
M src/xua_asp_fsm.c
5 files changed, 147 insertions(+), 46 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/49/2349/2

diff --git a/src/m3ua.c b/src/m3ua.c
index 7dc2afb..a7ef06c 100644
--- a/src/m3ua.c
+++ b/src/m3ua.c
@@ -39,6 +39,7 @@
 #include <osmocom/sigtran/protocol/m3ua.h>
 #include <osmocom/sigtran/protocol/sua.h>
 
+#include "xua_as_fsm.h"
 #include "xua_asp_fsm.h"
 #include "xua_internal.h"
 
@@ -420,16 +421,14 @@
  * Transmitting M3UA messsages to SCTP
  ***********************************************************************/
 
-/* transmit given xua_msg via given ASP. callee takes xua ownership */
-static int m3ua_tx_xua_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+/* Convert M3UA from xua_msg to msgb and set PPID/stream */
+static struct msgb *m3ua_to_msg(struct xua_msg *xua)
 {
 	struct msgb *msg = xua_to_msg(M3UA_VERSION, xua);
 
-	OSMO_ASSERT(asp->cfg.proto == OSMO_SS7_ASP_PROT_M3UA);
-
 	if (!msg) {
 		LOGP(DLM3UA, LOGL_ERROR, "Error encoding M3UA Msg\n");
-		return -1;
+		return NULL;
 	}
 
 	if (xua->hdr.msg_class == M3UA_MSGC_XFER)
@@ -437,6 +436,20 @@
 	else
 		msgb_sctp_stream(msg) = 0;
 	msgb_sctp_ppid(msg) = M3UA_PPID;
+
+	return msg;
+}
+
+/* transmit given xua_msg via given ASP */
+static int m3ua_tx_xua_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+{
+	struct msgb *msg = m3ua_to_msg(xua);
+
+	OSMO_ASSERT(asp->cfg.proto == OSMO_SS7_ASP_PROT_M3UA);
+
+	if (!msg)
+		return -1;
+
 	return osmo_ss7_asp_send(asp, msg);
 }
 
@@ -446,8 +459,8 @@
  *  \return 0 on success; negative on error */
 int m3ua_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua)
 {
-	struct osmo_ss7_asp *asp;
-	unsigned int i;
+	struct msgb *msg;
+	int rc;
 
 	OSMO_ASSERT(as->cfg.proto == OSMO_SS7_ASP_PROT_M3UA);
 
@@ -455,19 +468,16 @@
 	if (as->cfg.routing_key.context)
 		xua_msg_add_u32(xua, M3UA_IEI_ROUTE_CTX, as->cfg.routing_key.context);
 
-	for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) {
-		asp = as->cfg.asps[i];
-		if (!asp)
-			continue;
-		if (asp)
-			break;
-	}
-	if (!asp) {
-		LOGP(DLM3UA, LOGL_ERROR, "No ASP entroy in AS, dropping message\n");
-		return -ENODEV;
-	}
+	msg = m3ua_to_msg(xua);
+	if (!msg)
+		return -1;
 
-	return m3ua_tx_xua_asp(asp, xua);
+	/* send the msg to the AS for transmission.  The AS FSM might
+	 * (depending on its state) enqueue it before trnsmission */
+	rc = osmo_fsm_inst_dispatch(as->fi, XUA_AS_E_TRANSFER_REQ, msg);
+	if (rc < 0)
+		msgb_free(msg);
+	return rc;
 }
 
 /***********************************************************************
diff --git a/src/sua.c b/src/sua.c
index 3bff855..97a0785 100644
--- a/src/sua.c
+++ b/src/sua.c
@@ -40,6 +40,7 @@
 #include <osmocom/sigtran/protocol/m3ua.h>
 #include <osmocom/sigtran/osmo_ss7.h>
 
+#include "xua_as_fsm.h"
 #include "xua_asp_fsm.h"
 #include "xua_internal.h"
 #include "sccp_internal.h"
@@ -252,18 +253,38 @@
  * Transmitting SUA messsages to SCTP
  ***********************************************************************/
 
-static int sua_tx_xua_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+static struct msgb *sua_to_msg(struct xua_msg *xua)
 {
 	struct msgb *msg = xua_to_msg(SUA_VERSION, xua);
 
-	OSMO_ASSERT(asp->cfg.proto == OSMO_SS7_ASP_PROT_SUA);
-
 	if (!msg) {
-		LOGPASP(asp, DLSUA, LOGL_ERROR, "Error encoding SUA Msg\n");
-		return -1;
+		LOGP(DLSUA, LOGL_ERROR, "Error encoding SUA Msg\n");
+		return NULL;
 	}
 
+	switch (xua->hdr.msg_class) {
+	case SUA_MSGC_CL:
+	case SUA_MSGC_CO:
+		msgb_sctp_stream(msg) = 1;
+		break;
+	default:
+		msgb_sctp_stream(msg) = 0;
+		break;
+	}
 	msgb_sctp_ppid(msg) = SUA_PPID;
+
+	return msg;
+}
+
+static int sua_tx_xua_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
+{
+	struct msgb *msg = sua_to_msg(xua);
+
+	OSMO_ASSERT(asp->cfg.proto == OSMO_SS7_ASP_PROT_SUA);
+
+	if (!msg)
+		return -1;
+
 	return osmo_ss7_asp_send(asp, msg);
 }
 
@@ -273,25 +294,25 @@
  *  \return 0 on success; negative on error */
 int sua_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua)
 {
-	struct osmo_ss7_asp *asp;
-	unsigned int i;
+	struct msgb *msg;
+	int rc;
 
 	OSMO_ASSERT(as->cfg.proto == OSMO_SS7_ASP_PROT_SUA);
 
-	/* FIXME: Select ASP within AS depending on traffic mode */
-	for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) {
-		asp = as->cfg.asps[i];
-		if (!asp)
-			continue;
-		if (asp)
-			break;
-	}
-	if (!asp) {
-		LOGP(DLSUA, LOGL_ERROR, "No ASP in AS, dropping message\n");
-		return -ENODEV;
-	}
+	/* Add RC for this AS */
+	if (as->cfg.routing_key.context)
+		xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, as->cfg.routing_key.context);
 
-	return sua_tx_xua_asp(asp, xua);
+	msg = sua_to_msg(xua);
+	if (!msg)
+		return -1;
+
+	/* send the msg to the AS for transmission.  The AS FSM might
+	 * (depending on its state) enqueue it before trnsmission */
+	rc = osmo_fsm_inst_dispatch(as->fi, XUA_AS_E_TRANSFER_REQ, msg);
+	if (rc < 0)
+		msgb_free(msg);
+	return rc;
 }
 
 /***********************************************************************
diff --git a/src/xua_as_fsm.c b/src/xua_as_fsm.c
index 740070b..282a6bf 100644
--- a/src/xua_as_fsm.c
+++ b/src/xua_as_fsm.c
@@ -65,12 +65,39 @@
 	return sent;
 }
 
+/* actually transmit a message through this AS */
+static int xua_as_transmit_msg(struct osmo_ss7_as *as, struct msgb *msg)
+{
+	struct osmo_ss7_asp *asp;
+	unsigned int i;
+
+	/* FIXME: proper selection of the ASP based on the SLS and the
+	 * traffic mode type! */
+	for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) {
+		asp = as->cfg.asps[i];
+		if (!asp)
+			continue;
+		if (asp)
+			break;
+	}
+
+	if (!asp) {
+		LOGPFSM(as->fi, "No ASP in AS, dropping message\n");
+		msgb_free(msg);
+		return -1;
+	}
+
+	return osmo_ss7_asp_send(asp, msg);
+}
+
 
 /***********************************************************************
  * Actual FSM
  ***********************************************************************/
 
 #define S(x)	(1 << (x))
+
+#define MSEC_TO_S_US(x)		(x/1000), ((x%1000)*10)
 
 enum xua_as_state {
 	XUA_AS_S_DOWN,
@@ -83,11 +110,17 @@
 	{ XUA_ASPAS_ASP_INACTIVE_IND, 	"ASPAS-ASP_INACTIVE.ind" },
 	{ XUA_ASPAS_ASP_DOWN_IND,	"ASPAS-ASP_DOWN.ind" },
 	{ XUA_ASPAS_ASP_ACTIVE_IND,	"ASPAS-ASP_ACTIVE.ind" },
+	{ XUA_AS_E_RECOVERY_EXPD,	"AS-T_REC_EXPD.ind" },
+	{ XUA_AS_E_TRANSFER_REQ,	"AS-TRANSFER.req" },
 	{ 0, NULL }
 };
 
 struct xua_as_fsm_priv {
 	struct osmo_ss7_as *as;
+	struct {
+		struct osmo_timer_list t_r;
+		struct llist_head queued_msgs;
+	} recovery;
 };
 
 /* is any other ASP in this AS in state != DOWN? */
@@ -130,6 +163,11 @@
 	return false;
 }
 
+static void t_r_callback(void *_fi)
+{
+	struct osmo_fsm_inst *fi = _fi;
+	osmo_fsm_inst_dispatch(fi, XUA_AS_E_RECOVERY_EXPD, NULL);
+}
 
 static void xua_as_fsm_down(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 {
@@ -205,16 +243,20 @@
 static void xua_as_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 {
 	struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv;
-	struct osmo_ss7_asp *asp = data;
+	struct osmo_ss7_asp *asp;
+	struct msgb *msg;
 
 	switch (event) {
 	case XUA_ASPAS_ASP_DOWN_IND:
 	case XUA_ASPAS_ASP_INACTIVE_IND:
+		asp = data;
 		if (check_any_other_asp_in_active(xafp->as, asp)) {
 			/* ignore, we stay AS_ACTIVE */
 		} else {
+			uint32_t recovery_msec = xafp->as->cfg.recovery_timeout_msec;
 			osmo_fsm_inst_state_chg(fi, XUA_AS_S_PENDING, 0, 0);
-			/* FIXME: Start T(r) */
+			/* Start T(r) */
+			osmo_timer_schedule(&xafp->recovery.t_r, MSEC_TO_S_US(recovery_msec));
 			/* FIXME: Queue all signalling messages until
 			 * recovery or T(r) expiry */
 		}
@@ -222,21 +264,44 @@
 	case XUA_ASPAS_ASP_ACTIVE_IND:
 		/* ignore */
 		break;
+	case XUA_AS_E_TRANSFER_REQ:
+		/* message for transmission */
+		msg = data;
+		xua_as_transmit_msg(xafp->as, msg);
+		break;
 	}
 }
 
 static void xua_as_fsm_pending(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 {
+	struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv;
+	struct msgb *msg;
+
 	switch (event) {
 	case XUA_ASPAS_ASP_ACTIVE_IND:
 		/* one ASP transitions into ASP-ACTIVE */
+		osmo_timer_del(&xafp->recovery.t_r);
 		osmo_fsm_inst_state_chg(fi, XUA_AS_S_ACTIVE, 0, 0);
+		/* push out any pending queued messages */
+		while ((msg = msgb_dequeue(&xafp->recovery.queued_msgs)))
+			xua_as_transmit_msg(xafp->as, msg);
 		break;
 	case XUA_ASPAS_ASP_INACTIVE_IND:
 		/* ignore */
 		break;
 	case XUA_ASPAS_ASP_DOWN_IND:
 		/* ignore */
+		break;
+	case XUA_AS_E_RECOVERY_EXPD:
+		LOGPFSM(fi, "T(r) expired; dropping queued messages\n");
+		while ((msg = msgb_dequeue(&xafp->recovery.queued_msgs)))
+			talloc_free(msg);
+		osmo_fsm_inst_state_chg(fi, XUA_AS_S_DOWN, 0, 0);
+		break;
+	case XUA_AS_E_TRANSFER_REQ:
+		/* enqueue the to-be-transferred message */
+		msg = data;
+		msgb_enqueue(&xafp->recovery.queued_msgs, msg);
 		break;
 	}
 }
@@ -264,7 +329,8 @@
 	[XUA_AS_S_ACTIVE] = {
 		.in_event_mask = S(XUA_ASPAS_ASP_DOWN_IND) |
 				 S(XUA_ASPAS_ASP_INACTIVE_IND) |
-				 S(XUA_ASPAS_ASP_ACTIVE_IND),
+				 S(XUA_ASPAS_ASP_ACTIVE_IND) |
+				 S(XUA_AS_E_TRANSFER_REQ),
 		.out_state_mask = S(XUA_AS_S_ACTIVE) |
 				  S(XUA_AS_S_PENDING),
 		.name = "AS_ACTIVE",
@@ -274,7 +340,9 @@
 	[XUA_AS_S_PENDING] = {
 		.in_event_mask = S(XUA_ASPAS_ASP_INACTIVE_IND) |
 				 S(XUA_ASPAS_ASP_DOWN_IND) |
-				 S(XUA_ASPAS_ASP_ACTIVE_IND),
+				 S(XUA_ASPAS_ASP_ACTIVE_IND) |
+				 S(XUA_AS_E_TRANSFER_REQ) |
+				 S(XUA_AS_E_RECOVERY_EXPD),
 		.out_state_mask = S(XUA_AS_S_DOWN) |
 				  S(XUA_AS_S_INACTIVE) |
 				  S(XUA_AS_S_ACTIVE) |
@@ -310,6 +378,9 @@
 		return NULL;
 	}
 	xafp->as = as;
+	xafp->recovery.t_r.cb = t_r_callback;
+	xafp->recovery.t_r.data = fi;
+	INIT_LLIST_HEAD(&xafp->recovery.queued_msgs);
 
 	fi->priv = xafp;
 
diff --git a/src/xua_as_fsm.h b/src/xua_as_fsm.h
index 3b8e5b7..0128919 100644
--- a/src/xua_as_fsm.h
+++ b/src/xua_as_fsm.h
@@ -6,6 +6,8 @@
 	XUA_ASPAS_ASP_INACTIVE_IND,
 	XUA_ASPAS_ASP_DOWN_IND,
 	XUA_ASPAS_ASP_ACTIVE_IND,
+	XUA_AS_E_RECOVERY_EXPD,
+	XUA_AS_E_TRANSFER_REQ,
 };
 
 extern struct osmo_fsm xua_as_fsm;
diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c
index 59887a4..f4d9cf0 100644
--- a/src/xua_asp_fsm.c
+++ b/src/xua_asp_fsm.c
@@ -380,9 +380,6 @@
 	struct osmo_ss7_instance *inst = asp->inst;
 	struct osmo_ss7_as *as;
 
-	if (xafp->role != XUA_ASPFSM_ROLE_SG)
-		return;
-
 	llist_for_each_entry(as, &inst->as_list, list) {
 		if (!osmo_ss7_as_has_asp(as, asp))
 			continue;

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

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I22725bf35306299a00c66d7b3637f5e198c26247
Gerrit-PatchSet: 2
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list