pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/40461?usp=email )
Change subject: m3ua/sua: Implement ASP Hearbeat procedure ......................................................................
m3ua/sua: Implement ASP Hearbeat procedure
This implements M3UA/SUA Heartbeat Procedure.
Change-Id: Ie4d90447ef8f1b1174085aad55114ab6460ca559 --- M src/xua_asp_fsm.c 1 file changed, 88 insertions(+), 2 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve pespin: Looks good to me, approved
diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c index adc9f0e..26f3a78 100644 --- a/src/xua_asp_fsm.c +++ b/src/xua_asp_fsm.c @@ -89,6 +89,12 @@ struct osmo_timer_list timer; int out_event; } t_ack; + + /* Timer for tracking HEARTBEAT without HEARTBEAT ACK */ + struct { + struct osmo_timer_list timer; + uint32_t unacked_beats; + } t_beat; };
struct osmo_xlm_prim *xua_xlm_prim_alloc(enum osmo_xlm_prim_type prim_type, @@ -388,6 +394,67 @@ } }
+static void xua_t_beat_stop(struct osmo_fsm_inst *fi) +{ + struct xua_asp_fsm_priv *xafp = fi->priv; + + LOGPFSML(fi, LOGL_DEBUG, "T(beat) stopped\n"); + osmo_timer_del(&xafp->t_beat.timer); + xafp->t_beat.unacked_beats = 0; +} + +static void xua_t_beat_send(struct osmo_fsm_inst *fi) +{ + struct xua_asp_fsm_priv *xafp = fi->priv; + uint32_t timeout_sec; + + timeout_sec = osmo_tdef_get(xafp->asp->cfg.T_defs_xua, SS7_ASP_XUA_T_BEAT, OSMO_TDEF_S, -1); + + /* T(beat) disabled */ + if (timeout_sec == 0) { + xua_t_beat_stop(fi); + return; + } + + LOGPFSML(fi, LOGL_DEBUG, "Tx HEARTBEAT (%u unacked)\n", xafp->t_beat.unacked_beats); + + /* Avoid increasing in case some extra gratuitous PING is transmitted: */ + if (!osmo_timer_pending(&xafp->t_beat.timer)) + xafp->t_beat.unacked_beats++; + + /* (re-)arm T(beat): */ + osmo_timer_schedule(&xafp->t_beat.timer, timeout_sec, 0); + + /* Send HEARTBEAT: */ + peer_send(fi, XUA_ASP_E_ASPSM_BEAT, NULL); + +} + +static void xua_t_beat_cb(void *_fi) +{ + struct osmo_fsm_inst *fi = _fi; + struct xua_asp_fsm_priv *xafp = fi->priv; + + if (xafp->t_beat.unacked_beats < 2) { + if (xafp->t_beat.unacked_beats == 1) + LOGPFSML(fi, LOGL_NOTICE, + "Peer didn't respond to HEARTBEAT with HEARTBEAT ACK, retrying once more\n"); + xua_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 HEARTBEAT with HEARTBEAT ACK and became disconnected\n"); + ss7_asp_disconnect_stream(xafp->asp); + +} + #define ENSURE_ASP_OR_IPSP(fi, event) \ do { \ struct xua_asp_fsm_priv *_xafp = fi->priv; \ @@ -423,6 +490,7 @@ { struct xua_asp_fsm_priv *xafp = fi->priv; struct osmo_ss7_asp *asp = xafp->asp; + xua_t_beat_stop(fi); dispatch_to_all_as(fi, XUA_ASPAS_ASP_DOWN_IND, asp); }
@@ -489,6 +557,13 @@ { struct xua_asp_fsm_priv *xafp = fi->priv; struct osmo_ss7_asp *asp = xafp->asp; + bool went_up = (prev_state == XUA_ASP_S_DOWN); + + if (went_up) { + /* Now we are done with IPA handshake, Start Hearbeat Procedure, T(beat): */ + xua_t_beat_send(fi); + } + /* RFC4666 4.3.4.5: "When an ASP moves from ASP-DOWN to ASP-INACTIVE within a * particular AS, a Notify message SHOULD be sent, by the ASP-UP receptor, * after sending the ASP-UP-ACK, in order to inform the ASP of the current AS @@ -498,7 +573,7 @@ struct xua_as_event_asp_inactive_ind_pars pars = { .asp = asp, .asp_requires_notify = (asp->cfg.role != OSMO_SS7_ASP_ROLE_ASP) && - (prev_state == XUA_ASP_S_DOWN), + went_up, }; dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND, &pars); } @@ -620,6 +695,13 @@ { struct xua_asp_fsm_priv *xafp = fi->priv; struct osmo_ss7_asp *asp = xafp->asp; + bool went_up = (prev_state == XUA_ASP_S_DOWN); + + if (went_up) { + /* Now we are done with IPA handshake, Start Hearbeat Procedure, T(beat): */ + xua_t_beat_send(fi); + } + dispatch_to_all_as(fi, XUA_ASPAS_ASP_ACTIVE_IND, asp); }
@@ -717,7 +799,8 @@ peer_send(fi, XUA_ASP_E_ASPSM_BEAT_ACK, xua); break; case XUA_ASP_E_ASPSM_BEAT_ACK: - /* FIXME: stop timer, if any */ + LOGPFSML(fi, LOGL_DEBUG, "Rx HEARTBEAT ACK\n"); + xafp->t_beat.unacked_beats = 0; break; case XUA_ASP_E_AS_ASSIGNED: /* Ignore, only used in IPA asps so far. */ @@ -742,6 +825,7 @@ return;
osmo_timer_del(&xafp->t_ack.timer); + xua_t_beat_stop(fi);
if (xafp->asp) xafp->asp->fi = NULL; @@ -839,6 +923,8 @@ xafp->role = role; xafp->asp = asp;
+ osmo_timer_setup(&xafp->t_beat.timer, xua_t_beat_cb, fi); + fi->priv = xafp;
/* Attach FSM to ASP: */