pespin has submitted this change. (
https://gerrit.osmocom.org/c/libosmo-sigtran/+/40460?usp=email )
Change subject: ipa: Implement ASP Hearbeat procedure
......................................................................
ipa: Implement ASP Hearbeat procedure
This implements M3UA/SUA Heartbeat Procedure using own IPA PING & PONG
messages.
Related: OS#4072
Change-Id: I0947977b192447d433ecf6b3ccb830141d8ae04d
---
M src/ipa.c
M src/xua_asp_fsm.c
M src/xua_internal.h
3 files changed, 105 insertions(+), 18 deletions(-)
Approvals:
Jenkins Builder: Verified
osmith: Looks good to me, but someone else must approve
laforge: Looks good to me, but someone else must approve
pespin: Looks good to me, approved
diff --git a/src/ipa.c b/src/ipa.c
index c04b476..58646fa 100644
--- a/src/ipa.c
+++ b/src/ipa.c
@@ -52,6 +52,20 @@
#include "ss7_internal.h"
#include "xua_asp_fsm.h"
+/* generate a msgb containing an IPA CCM PING message */
+struct msgb *ipa_gen_ping(void)
+{
+ /* sufficient headroom for osmo_ipa_msg_push_header() */
+ struct msgb *msg = ipa_msg_alloc(16);
+ if (!msg)
+ return NULL;
+
+ msgb_put_u8(msg, IPAC_MSGT_PING);
+ ipa_prepend_header(msg, IPAC_PROTO_IPACCESS);
+
+ return msg;
+}
+
struct msgb *ipa_to_msg(struct xua_msg *xua)
{
struct xua_msg_part *data_ie;
diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c
index 1d6b078..adc9f0e 100644
--- a/src/xua_asp_fsm.c
+++ b/src/xua_asp_fsm.c
@@ -879,8 +879,11 @@
/* Structure holding parsed data of the IPA CCM ID exchange */
struct ipaccess_unit *ipa_unit;
- /* Timer for tracking if no PONG is received in response to PING */
- struct osmo_timer_list pong_timer;
+ /* Timer for tracking PING without PONG response */
+ struct {
+ struct osmo_timer_list timer;
+ uint32_t unacked_beats;
+ } t_beat;
/* Did we receive IPA ID ACK before IPA ID RESP ? */
bool ipa_id_ack_rcvd;
};
@@ -907,11 +910,82 @@
return fd;
}
+static void ipa_t_beat_stop(struct osmo_fsm_inst *fi)
+{
+ struct ipa_asp_fsm_priv *iafp = fi->priv;
+
+ LOGPFSML(fi, LOGL_DEBUG, "T(beat) stopped\n");
+ osmo_timer_del(&iafp->t_beat.timer);
+ iafp->t_beat.unacked_beats = 0;
+}
+
+static void ipa_t_beat_send(struct osmo_fsm_inst *fi)
+{
+ struct ipa_asp_fsm_priv *iafp = fi->priv;
+ struct msgb *msg;
+ uint32_t timeout_sec;
+
+ timeout_sec = osmo_tdef_get(iafp->asp->cfg.T_defs_xua, SS7_ASP_XUA_T_BEAT,
OSMO_TDEF_S, -1);
+
+ /* T(beat) disabled */
+ if (timeout_sec == 0) {
+ ipa_t_beat_stop(fi);
+ return;
+ }
+
+ LOGPFSML(fi, LOGL_DEBUG, "Tx HEARTBEAT (%u unacked)\n",
iafp->t_beat.unacked_beats);
+
+ /* Avoid increasing in case some extra gratuitous PING is transmitted: */
+ if (!osmo_timer_pending(&iafp->t_beat.timer))
+ iafp->t_beat.unacked_beats++;
+
+ /* (re-)arm T(beat): */
+ osmo_timer_schedule(&iafp->t_beat.timer, timeout_sec, 0);
+
+ /* Send PING: */
+ if ((msg = ipa_gen_ping()))
+ osmo_ss7_asp_send(iafp->asp, msg);
+ /* we don't own msg anymore in any case here */
+}
+
+static void ipa_t_beat_cb(void *_fi)
+{
+ struct osmo_fsm_inst *fi = _fi;
+ struct ipa_asp_fsm_priv *iafp = fi->priv;
+
+ if (iafp->t_beat.unacked_beats < 2) {
+ if (iafp->t_beat.unacked_beats == 1)
+ LOGPFSML(fi, LOGL_NOTICE,
+ "Peer didn't respond to PING with PONG, retrying once more\n");
+ ipa_t_beat_send(fi);
+ return;
+ }
+
+ /* RFC4666 4.3.4.6: If no Heartbeat Ack message (or any other M3UA
+ * message) is received from the M3UA peer within 2*T(beat), the remote
+ * M3UA peer is considered unavailable. Transmission of Heartbeat
+ * messages is stopped, and the signalling process SHOULD attempt to
+ * re-establish communication if it is configured as the client for the
+ * disconnected M3UA peer.
+ */
+ LOGPFSML(fi, LOGL_NOTICE, "Peer didn't respond to PING with PONG and became
disconnected\n");
+ ss7_asp_disconnect_stream(iafp->asp);
+
+}
+
/***************
** FSM states **
***************/
/* Server + Client: Initial State, wait for M-ASP-UP.req */
+static void ipa_asp_fsm_down_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct xua_asp_fsm_priv *xafp = fi->priv;
+ struct osmo_ss7_asp *asp = xafp->asp;
+ ipa_t_beat_stop(fi);
+ dispatch_to_all_as(fi, XUA_ASPAS_ASP_DOWN_IND, asp);
+}
+
static void ipa_asp_fsm_down(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct ipa_asp_fsm_priv *iafp = fi->priv;
@@ -1079,6 +1153,10 @@
.asp = asp,
.asp_requires_notify = false,
};
+
+ /* Now we are done with IPA handshake, Start Hearbeat Procedure, T(beat): */
+ ipa_t_beat_send(fi);
+
dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND, &pars);
dispatch_to_all_as(fi, XUA_ASPAS_ASP_ACTIVE_IND, asp);
}
@@ -1163,8 +1241,8 @@
ipaccess_send_pong(fd);
break;
case XUA_ASP_E_ASPSM_BEAT_ACK:
- /* stop timer, if any */
- osmo_timer_del(&iafp->pong_timer);
+ LOGPFSML(fi, LOGL_DEBUG, "Rx HEARTBEAT ACK\n");
+ iafp->t_beat.unacked_beats = 0;
break;
case XUA_ASP_E_AS_ASSIGNED:
as = data;
@@ -1183,16 +1261,6 @@
}
}
-static void ipa_pong_timer_cb(void *_fi)
-{
- struct osmo_fsm_inst *fi = _fi;
- struct ipa_asp_fsm_priv *iafp = fi->priv;
-
- LOGPFSML(fi, LOGL_NOTICE, "Peer didn't respond to PING? with PONG!\n");
- /* kill ASP and (wait for) re-connect */
- osmo_ss7_asp_disconnect(iafp->asp);
-}
-
static int ipa_asp_fsm_timer_cb(struct osmo_fsm_inst *fi)
{
struct ipa_asp_fsm_priv *iafp = fi->priv;
@@ -1207,7 +1275,12 @@
{
struct ipa_asp_fsm_priv *iafp = fi->priv;
- if (iafp && iafp->asp)
+ if (!iafp)
+ return;
+
+ ipa_t_beat_stop(fi);
+
+ if (iafp->asp)
iafp->asp->fi = NULL;
}
@@ -1219,7 +1292,7 @@
S(IPA_ASP_S_WAIT_ID_RESP),
.name = "ASP_DOWN",
.action = ipa_asp_fsm_down,
- .onenter = xua_asp_fsm_down_onenter,
+ .onenter = ipa_asp_fsm_down_onenter,
},
/* Server Side */
[IPA_ASP_S_WAIT_ID_RESP] = {
@@ -1340,8 +1413,7 @@
iafp->asp = asp;
iafp->ipa_unit = talloc_zero(iafp, struct ipaccess_unit);
iafp->ipa_unit->unit_name = talloc_strdup(iafp->ipa_unit, unit_name);
- iafp->pong_timer.cb = ipa_pong_timer_cb;
- iafp->pong_timer.data = fi;
+ osmo_timer_setup(&iafp->t_beat.timer, ipa_t_beat_cb, fi);
fi->priv = iafp;
diff --git a/src/xua_internal.h b/src/xua_internal.h
index 60d751c..576708f 100644
--- a/src/xua_internal.h
+++ b/src/xua_internal.h
@@ -116,6 +116,7 @@
int xua_find_as_for_asp(struct osmo_ss7_as **as, const struct osmo_ss7_asp *asp,
const struct xua_msg_part *rctx_ie);
+struct msgb *ipa_gen_ping(void);
struct msgb *ipa_to_msg(struct xua_msg *xua);
int ipa_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua);
int ipa_rx_msg(struct osmo_ss7_asp *asp, struct msgb *msg, uint8_t sls);
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-sigtran/+/40460?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I0947977b192447d433ecf6b3ccb830141d8ae04d
Gerrit-Change-Number: 40460
Gerrit-PatchSet: 5
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>