pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/39640?usp=email )
Change subject: Make sure to NOTIFY current state to peer after ASP UP ACK / REG RESP ...................................................................... Make sure to NOTIFY current state to peer after ASP UP ACK / REG RESP As per 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 state.""" It also needs to be done for REG RESP in order to support dynamic ASPs/ASs, since in that case if dynamic ASP sends to SG an ASP-UP msg, it contains no RCTX/AS reference, and hence the ASP will only be assigned to an AS after the REG-REQ is sent, at which point we can send the AS status to it. Change-Id: I3dffa2e9c554f03c7c721b757ff33a89961665b5 --- M src/xua_as_fsm.c M src/xua_as_fsm.h M src/xua_asp_fsm.c M src/xua_rkm.c 4 files changed, 129 insertions(+), 27 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved diff --git a/src/xua_as_fsm.c b/src/xua_as_fsm.c index 577c7d3..c4a167c 100644 --- a/src/xua_as_fsm.c +++ b/src/xua_as_fsm.c @@ -39,6 +39,19 @@ return msg; } +static void tx_notify(struct osmo_ss7_asp *asp, const struct osmo_xlm_prim_notify *npar) +{ + const char *type_name, *info_name, *info_str; + type_name = get_value_string(m3ua_ntfy_type_names, npar->status_type); + info_name = m3ua_ntfy_info_name(npar->status_type, npar->status_info); + info_str = npar->info_string ? npar->info_string : ""; + + LOGPASP(asp, DLSS7, LOGL_INFO, "Tx NOTIFY Type %s:%s (%s)\n", + type_name, info_name, info_str); + struct msgb *msg = encode_notify(npar); + osmo_ss7_asp_send(asp, msg); +} + static int as_notify_all_asp(struct osmo_ss7_as *as, struct osmo_xlm_prim_notify *npar) { struct msgb *msg; @@ -184,6 +197,37 @@ bool ipa_route_created; }; +static void fill_notify_statchg_pars(const struct osmo_fsm_inst *fi, struct osmo_xlm_prim_notify *npar) +{ + struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv; + struct osmo_ss7_as *as = xafp->as; + *npar = (struct osmo_xlm_prim_notify){ + .status_type = M3UA_NOTIFY_T_STATCHG, + }; + + switch (fi->state) { + case XUA_AS_S_INACTIVE: + npar->status_info = M3UA_NOTIFY_I_AS_INACT; + break; + case XUA_AS_S_ACTIVE: + npar->status_info = M3UA_NOTIFY_I_AS_ACT; + break; + case XUA_AS_S_PENDING: + npar->status_info = M3UA_NOTIFY_I_AS_PEND; + break; + case XUA_AS_S_DOWN: + default: + /* Nothing will be sent anyway... */ + return; + } + + /* Add the routing context, if it is configured */ + if (as->cfg.routing_key.context) { + npar->presence |= NOTIFY_PAR_P_ROUTE_CTX; + npar->route_ctx = as->cfg.routing_key.context; + } +} + /* is the given AS one with a single ASP of IPA type? */ static bool is_single_ipa_asp(struct osmo_ss7_as *as) { @@ -351,21 +395,21 @@ { struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv; struct osmo_ss7_as *as = xafp->as; - struct osmo_xlm_prim_notify npar = { - .status_type = M3UA_NOTIFY_T_STATCHG, - }; + struct osmo_xlm_prim_notify npar; + + fill_notify_statchg_pars(fi, &npar); switch (fi->state) { case XUA_AS_S_INACTIVE: - npar.status_info = M3UA_NOTIFY_I_AS_INACT; + /* continue below */ break; case XUA_AS_S_ACTIVE: if (is_single_ipa_asp(as)) ipa_add_route(fi); - npar.status_info = M3UA_NOTIFY_I_AS_ACT; + /* continue below */ break; case XUA_AS_S_PENDING: - npar.status_info = M3UA_NOTIFY_I_AS_PEND; + /* continue below */ break; case XUA_AS_S_DOWN: if (is_single_ipa_asp(as)) @@ -384,11 +428,7 @@ return; } - /* Add the routing context, if it is configured */ - if (as->cfg.routing_key.context) { - npar.presence |= NOTIFY_PAR_P_ROUTE_CTX; - npar.route_ctx = as->cfg.routing_key.context; - } + fill_notify_statchg_pars(fi, &npar); /* TODO: ASP-Id of ASP triggering this state change */ @@ -409,10 +449,13 @@ static void xua_as_fsm_inactive(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 xua_as_event_asp_inactive_ind_pars *inact_ind_pars; + struct osmo_xlm_prim_notify npar; switch (event) { case XUA_ASPAS_ASP_DOWN_IND: + asp = data; /* one ASP transitions into ASP-DOWN */ if (check_any_other_asp_not_down(xafp->as, asp)) { /* ignore, we stay AS_INACTIVE */ @@ -424,7 +467,11 @@ osmo_fsm_inst_state_chg(fi, XUA_AS_S_ACTIVE, 0, 0); break; case XUA_ASPAS_ASP_INACTIVE_IND: - /* ignore */ + inact_ind_pars = data; + if (inact_ind_pars->asp_requires_notify) { + fill_notify_statchg_pars(fi, &npar); + tx_notify(inact_ind_pars->asp, &npar); + } break; } } @@ -433,14 +480,19 @@ { struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv; struct osmo_ss7_asp *asp; + struct xua_as_event_asp_inactive_ind_pars *inact_ind_pars; struct msgb *msg; + struct osmo_xlm_prim_notify npar; 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 */ + inact_ind_pars = data; + if (check_any_other_asp_in_active(xafp->as, inact_ind_pars->asp)) { + if (event == XUA_ASPAS_ASP_INACTIVE_IND && inact_ind_pars->asp_requires_notify) { + fill_notify_statchg_pars(fi, &npar); + tx_notify(inact_ind_pars->asp, &npar); + } /* ASP_DOWN_IND: ignore, nothing to be sent */ } else { uint32_t recovery_msec = xafp->as->cfg.recovery_timeout_msec; osmo_fsm_inst_state_chg(fi, XUA_AS_S_PENDING, 0, 0); @@ -467,7 +519,9 @@ 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 xua_as_event_asp_inactive_ind_pars *inact_ind_pars; struct msgb *msg; + struct osmo_xlm_prim_notify npar; switch (event) { case XUA_ASPAS_ASP_ACTIVE_IND: @@ -479,7 +533,11 @@ xua_as_transmit_msg(xafp->as, msg); break; case XUA_ASPAS_ASP_INACTIVE_IND: - /* ignore */ + inact_ind_pars = data; + if (inact_ind_pars->asp_requires_notify) { + fill_notify_statchg_pars(fi, &npar); + tx_notify(inact_ind_pars->asp, &npar); + } break; case XUA_ASPAS_ASP_DOWN_IND: /* ignore */ diff --git a/src/xua_as_fsm.h b/src/xua_as_fsm.h index 0e71350..cf897e2 100644 --- a/src/xua_as_fsm.h +++ b/src/xua_as_fsm.h @@ -1,6 +1,7 @@ #pragma once struct osmo_ss7_as; +struct osmo_ss7_asp; enum xua_as_state { XUA_AS_S_DOWN, @@ -9,8 +10,17 @@ XUA_AS_S_PENDING, }; +struct xua_as_event_asp_inactive_ind_pars { + struct osmo_ss7_asp *asp; + /* 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 + * state." */ + bool asp_requires_notify; +}; + enum xua_as_event { - XUA_ASPAS_ASP_INACTIVE_IND, + XUA_ASPAS_ASP_INACTIVE_IND, /* param: struct xua_as_event_asp_inactive_ind_pars* */ XUA_ASPAS_ASP_DOWN_IND, XUA_ASPAS_ASP_ACTIVE_IND, XUA_AS_E_RECOVERY_EXPD, diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c index 12640d6..0e39b0d 100644 --- a/src/xua_asp_fsm.c +++ b/src/xua_asp_fsm.c @@ -355,7 +355,7 @@ /* Helper function to dispatch an ASP->AS event to all AS of which this * ASP is a memmber. Ignores routing contexts for now. */ -static void dispatch_to_all_as(struct osmo_fsm_inst *fi, uint32_t event) +static void dispatch_to_all_as(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct xua_asp_fsm_priv *xafp = fi->priv; struct osmo_ss7_asp *asp = xafp->asp; @@ -365,7 +365,7 @@ llist_for_each_entry(as, &inst->as_list, list) { if (!osmo_ss7_as_has_asp(as, asp)) continue; - osmo_fsm_inst_dispatch(as->fi, event, asp); + osmo_fsm_inst_dispatch(as->fi, event, data); } } @@ -418,7 +418,9 @@ static void xua_asp_fsm_down_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { - dispatch_to_all_as(fi, XUA_ASPAS_ASP_DOWN_IND); + struct xua_asp_fsm_priv *xafp = fi->priv; + struct osmo_ss7_asp *asp = xafp->asp; + dispatch_to_all_as(fi, XUA_ASPAS_ASP_DOWN_IND, asp); } static void xua_asp_fsm_down(struct osmo_fsm_inst *fi, uint32_t event, void *data) @@ -478,7 +480,17 @@ static void xua_asp_fsm_inactive_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { - dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND); + struct xua_asp_fsm_priv *xafp = fi->priv; + /* 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 + * state." + */ + struct xua_as_event_asp_inactive_ind_pars pars = { + .asp = xafp->asp, + .asp_requires_notify = (prev_state == XUA_ASP_S_DOWN), + }; + dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND, &pars); } static void xua_asp_fsm_inactive(struct osmo_fsm_inst *fi, uint32_t event, void *data) @@ -596,7 +608,9 @@ static void xua_asp_fsm_active_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { - dispatch_to_all_as(fi, XUA_ASPAS_ASP_ACTIVE_IND); + struct xua_asp_fsm_priv *xafp = fi->priv; + struct osmo_ss7_asp *asp = xafp->asp; + dispatch_to_all_as(fi, XUA_ASPAS_ASP_ACTIVE_IND, asp); } static void xua_asp_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data) @@ -1047,8 +1061,14 @@ static void ipa_asp_fsm_active_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { - dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND); - dispatch_to_all_as(fi, XUA_ASPAS_ASP_ACTIVE_IND); + struct ipa_asp_fsm_priv *iafp = fi->priv; + struct osmo_ss7_asp *asp = iafp->asp; + struct xua_as_event_asp_inactive_ind_pars pars = { + .asp = asp, + .asp_requires_notify = false, + }; + dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND, &pars); + dispatch_to_all_as(fi, XUA_ASPAS_ASP_ACTIVE_IND, asp); } /* Server + Client: We're actively transmitting user data */ @@ -1064,7 +1084,12 @@ static void ipa_asp_fsm_inactive_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { - dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND); + struct ipa_asp_fsm_priv *iafp = fi->priv; + struct xua_as_event_asp_inactive_ind_pars pars = { + .asp = iafp->asp, + .asp_requires_notify = false, + }; + dispatch_to_all_as(fi, XUA_ASPAS_ASP_INACTIVE_IND, &pars); } static void ipa_asp_fsm_inactive(struct osmo_fsm_inst *fi, uint32_t event, void *data) diff --git a/src/xua_rkm.c b/src/xua_rkm.c index f616a3a..9e77095 100644 --- a/src/xua_rkm.c +++ b/src/xua_rkm.c @@ -346,7 +346,16 @@ if (!as) continue; /* Notify AS that it has an INACTIVE ASP */ - osmo_fsm_inst_dispatch(as->fi, XUA_ASPAS_ASP_INACTIVE_IND, asp); + /* 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 + * state." + */ + struct xua_as_event_asp_inactive_ind_pars pars = { + .asp = asp, + .asp_requires_notify = true, + }; + osmo_fsm_inst_dispatch(as->fi, XUA_ASPAS_ASP_INACTIVE_IND, &pars); } return 0; -- To view, visit https://gerrit.osmocom.org/c/libosmo-sigtran/+/39640?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: I3dffa2e9c554f03c7c721b757ff33a89961665b5 Gerrit-Change-Number: 39640 Gerrit-PatchSet: 6 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: osmith <osm...@sysmocom.de> Gerrit-Reviewer: pespin <pes...@sysmocom.de>