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
Review at https://gerrit.osmocom.org/2349
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
4 files changed, 145 insertions(+), 43 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/49/2349/1
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..cbbd85b 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,
@@ -88,6 +115,10 @@
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 +161,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 +241,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 +262,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 +327,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 +338,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 +376,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;
--
To view, visit https://gerrit.osmocom.org/2349
To unsubscribe, visit https://gerrit.osmocom.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I22725bf35306299a00c66d7b3637f5e198c26247
Gerrit-PatchSet: 1
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>