pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/42573?usp=email )
Change subject: Support administrative block in role ASP ......................................................................
Support administrative block in role ASP
* Avoid activating later on if inactive when becoming blocked. * Move to inactive state (and notify peer with ASPIA) if active when becoming blocked. * Attempt re-activation if needed when becoming non-blocked.
Related: OS#6752 Change-Id: If32902575e874d2acc9a5fc12509af42ed151739 --- M src/ss7_asp.c M src/ss7_asp_vty.c M src/xua_asp_fsm.c M src/xua_asp_fsm.h M src/xua_default_lm_fsm.c 5 files changed, 77 insertions(+), 21 deletions(-)
Approvals: osmith: Looks good to me, but someone else must approve fixeria: Looks good to me, approved Jenkins Builder: Verified
diff --git a/src/ss7_asp.c b/src/ss7_asp.c index b33187c..f30375f 100644 --- a/src/ss7_asp.c +++ b/src/ss7_asp.c @@ -1535,6 +1535,7 @@ * A blocked ASP can't stay nor be turned into ACTIVE state. */ void ss7_asp_set_blocked(struct osmo_ss7_asp *asp, bool blocked) { + uint32_t event; if (asp->cfg.adm_state.blocked == blocked) return; LOGPASP(asp, DLSS7, LOGL_NOTICE, "Applying Adm State change: '%sblock' -> '%sblock'\n", @@ -1542,8 +1543,8 @@ blocked ? "" : "no "); asp->cfg.adm_state.blocked = blocked;
- if (asp->cfg.adm_state.blocked) - osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_ADM_BLOCKED, NULL); + event = asp->cfg.adm_state.blocked ? XUA_ASP_E_ADM_BLOCKED : XUA_ASP_E_ADM_UNBLOCKED; + osmo_fsm_inst_dispatch(asp->fi, event, NULL); }
/* Apply sane configs for unconfigured options and restart the ASP. */ diff --git a/src/ss7_asp_vty.c b/src/ss7_asp_vty.c index e3c82fe..89fb949 100644 --- a/src/ss7_asp_vty.c +++ b/src/ss7_asp_vty.c @@ -714,11 +714,6 @@ return CMD_WARNING; }
- if (asp->cfg.role == OSMO_SS7_ASP_ROLE_ASP) { - vty_out(vty, "%% 'block' not yet implemented in 'role asp'%s", VTY_NEWLINE); - return CMD_WARNING; - } - ss7_asp_set_blocked(asp, true); return CMD_SUCCESS; } diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c index 39d121f..679533b 100644 --- a/src/xua_asp_fsm.c +++ b/src/xua_asp_fsm.c @@ -78,6 +78,7 @@
{ XUA_ASP_E_AS_ASSIGNED, "AS_ASSIGNED" }, { XUA_ASP_E_ADM_BLOCKED, "ADM_BLOCKED" }, + { XUA_ASP_E_ADM_UNBLOCKED, "ADM_UNBLOCKED" },
{ IPA_ASP_E_ID_RESP, "IPA_CCM_ID_RESP" }, { IPA_ASP_E_ID_GET, "IPA_CCM_ID_GET" }, @@ -916,7 +917,13 @@ /* nothing to be done, ASPAC will be rejected when received. */ return; } - if (asp->cfg.role == OSMO_SS7_ASP_ROLE_SG) { + switch (asp->cfg.role) { + case OSMO_SS7_ASP_ROLE_ASP: + case OSMO_SS7_ASP_ROLE_IPSP: + /* Send M3UA_MSGT_ASPSM_ASPUP and start t_ack */ + peer_send_and_start_t_ack(fi, XUA_ASP_E_ASPTM_ASPIA); + break; + case OSMO_SS7_ASP_ROLE_SG: /* RFC4666 4.3.4.4: Transmit unsolicited ASPIA ACK no tnotify peer. * "If the ASP receives an ASP Inactive Ack without having sent an * ASP Inactive message, the ASP should now consider itself to be @@ -928,8 +935,32 @@ /* transition state and inform layer manager */ osmo_fsm_inst_state_chg(fi, XUA_ASP_S_INACTIVE, 0, 0); send_xlm_prim_simple(fi, OSMO_XLM_PRIM_M_ASP_INACTIVE, PRIM_OP_INDICATION); + break; } - /* TODO: implement ASP and IPSP roles. */ + break; + case XUA_ASP_E_ADM_UNBLOCKED: + if (fi->state != XUA_ASP_S_INACTIVE) { + /* nothing to be done, we are only interested in possible + * transitioning INACTIVE->ACTIVE */ + return; + } + switch (asp->cfg.role) { + case OSMO_SS7_ASP_ROLE_ASP: + case OSMO_SS7_ASP_ROLE_IPSP: + /* Forge a M-INACTIVE confirmation prim in order to give LM the opportunity + * to figure out whether some change needs to be applied to the ASP now that + * it is unblocked. */ + send_xlm_prim_simple(fi, OSMO_XLM_PRIM_M_ASP_INACTIVE, PRIM_OP_CONFIRM); + break; + case OSMO_SS7_ASP_ROLE_SG: + /* Send an unsolicited ASPIA ACK to peer to give the opportunity to retry re-activation: */ + xua_asp_tx_unsolicited_aspia_ack(asp); + /* Forge a M-INACTIVE indication prim in order to give LM the opportunity + * to figure out whether some change needs to be applied to the ASP now that + * it is unblocked. */ + send_xlm_prim_simple(fi, OSMO_XLM_PRIM_M_ASP_INACTIVE, PRIM_OP_INDICATION); + break; + } break; default: break; @@ -1018,7 +1049,8 @@ S(XUA_ASP_E_ASPSM_BEAT_ACK) | S(XUA_ASP_E_MGMT_ERROR) | S(XUA_ASP_E_AS_ASSIGNED) | - S(XUA_ASP_E_ADM_BLOCKED), + S(XUA_ASP_E_ADM_BLOCKED) | + S(XUA_ASP_E_ADM_UNBLOCKED), .allstate_action = xua_asp_allstate, .cleanup = xua_asp_fsm_cleanup, }; diff --git a/src/xua_asp_fsm.h b/src/xua_asp_fsm.h index 456aec6..6189e7a 100644 --- a/src/xua_asp_fsm.h +++ b/src/xua_asp_fsm.h @@ -34,8 +34,9 @@ /* The ASP was added to an AS. data: (struct osmo_ss7_as *) */ XUA_ASP_E_AS_ASSIGNED,
- /* The ASP became administratively blocked */ + /* The ASP became administratively (un)blocked */ XUA_ASP_E_ADM_BLOCKED, + XUA_ASP_E_ADM_UNBLOCKED,
/* IPA specific */ IPA_ASP_E_ID_RESP, diff --git a/src/xua_default_lm_fsm.c b/src/xua_default_lm_fsm.c index 40d6e0d..73c4fdc 100644 --- a/src/xua_default_lm_fsm.c +++ b/src/xua_default_lm_fsm.c @@ -199,6 +199,10 @@
static bool asp_act_needed(const struct osmo_ss7_asp *asp) { + /* Avoid activating if ASP is adminsitratively blocked locally: */ + if (asp->cfg.adm_state.blocked) + return false; + /* Don't change active ASP if there's already one active in the AS. */ if (ss7_asp_determine_traf_mode(asp) == OSMO_SS7_AS_TMOD_OVERRIDE) { struct ss7_as_asp_assoc *assoc; @@ -210,6 +214,13 @@ return true; }
+static void submit_m_asp_active_req_if_needed(struct osmo_ss7_asp *asp) +{ + if (!asp_act_needed(asp)) + return; + xlm_sap_down_simple(asp, OSMO_XLM_PRIM_M_ASP_ACTIVE, PRIM_OP_REQUEST); +} + static void lm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { @@ -342,10 +353,8 @@ struct xua_layer_manager_default_priv *lmp = fi->priv;
if (lmp->asp->cfg.role == OSMO_SS7_ASP_ROLE_ASP || - lmp->asp->cfg.role == OSMO_SS7_ASP_ROLE_IPSP) { - if (asp_act_needed(lmp->asp)) - xlm_sap_down_simple(lmp->asp, OSMO_XLM_PRIM_M_ASP_ACTIVE, PRIM_OP_REQUEST); - } + lmp->asp->cfg.role == OSMO_SS7_ASP_ROLE_IPSP) + submit_m_asp_active_req_if_needed(lmp->asp); }
static void lm_inactive(struct osmo_fsm_inst *fi, uint32_t event, void *data) @@ -360,22 +369,32 @@ * until receipt of the ASP Active Ack message". */ lm_fsm_state_chg(fi, S_ACTIVE); break; + case LM_E_ASP_INACT_CONF: + ENSURE_ASP_OR_IPSP(fi, event); + /* Local M3UA/SUA layer transmitted an ASPIA when local ASP became administratively + * blocked, and we just received confirmation. + * Request the ASP to go into active state if needed */ + submit_m_asp_active_req_if_needed(lmp->asp); + break; + case LM_E_ASP_INACT_IND: + ENSURE_SG_OR_IPSP(fi, event); + /* Peer sent an ASPIA, or local M3UA/SUA layer informs us administrative block + * status changed. Nothing to be done here. */ + break; case LM_E_ASP_ACT_IND: ENSURE_SG_OR_IPSP(fi, event); lm_fsm_state_chg(fi, S_ACTIVE); break; case LM_E_AS_INACTIVE_IND: /* request the ASP to go into active state if needed */ - if (asp_act_needed(lmp->asp)) - xlm_sap_down_simple(lmp->asp, OSMO_XLM_PRIM_M_ASP_ACTIVE, PRIM_OP_REQUEST); + submit_m_asp_active_req_if_needed(lmp->asp); break; case LM_E_NOTIFY_IND: ENSURE_ASP_OR_IPSP(fi, event); OSMO_ASSERT(oxp->oph.primitive == OSMO_XLM_PRIM_M_NOTIFY); OSMO_ASSERT(oxp->oph.operation == PRIM_OP_INDICATION); /* request the ASP to go into active state if needed */ - if (asp_act_needed(lmp->asp)) - xlm_sap_down_simple(lmp->asp, OSMO_XLM_PRIM_M_ASP_ACTIVE, PRIM_OP_REQUEST); + submit_m_asp_active_req_if_needed(lmp->asp); break; case LM_E_ERROR_IND: ENSURE_ASP_OR_IPSP(fi, event); @@ -405,11 +424,18 @@ break; case LM_E_ASP_INACT_CONF: ENSURE_ASP_OR_IPSP(fi, event); + if (lmp->asp->cfg.adm_state.blocked) { + /* M3UA/SUA transmitted an ASPIA when local ASP became administratively blocked, + * and we just received confirmation. Move to INACTIVE and wait for M3UA/SUA to + * notify about status change (ie. forged M-INACTIVE.confirm) */ + lm_fsm_state_chg(fi, S_INACTIVE); + return; + } /* RFC 4666 RFC4666 4.3.4.4: Rx unsolicited ASPIA ACK, usually triggered because * peer's ASP became administratively blocked. * Try to re-activate, if peer's ASP is indeed blocked we'll probably receive an * ERR msg and continue from there in the case LM_E_ERROR_IND below. */ - xlm_sap_down_simple(lmp->asp, OSMO_XLM_PRIM_M_ASP_ACTIVE, PRIM_OP_REQUEST); + submit_m_asp_active_req_if_needed(lmp->asp); break; case LM_E_ASP_INACT_IND: ENSURE_SG_OR_IPSP(fi, event); @@ -417,7 +443,7 @@ break; case LM_E_AS_INACTIVE_IND: /* request the ASP to go into active state */ - xlm_sap_down_simple(lmp->asp, OSMO_XLM_PRIM_M_ASP_ACTIVE, PRIM_OP_REQUEST); + submit_m_asp_active_req_if_needed(lmp->asp); break; case LM_E_NOTIFY_IND: ENSURE_ASP_OR_IPSP(fi, event); @@ -538,6 +564,7 @@ [S_INACTIVE] = { .in_event_mask = S(LM_E_ASP_ACT_CONF) | S(LM_E_ASP_ACT_IND) | + S(LM_E_ASP_INACT_IND) | S(LM_E_ASP_INACT_CONF) | S(LM_E_AS_INACTIVE_IND) | S(LM_E_NOTIFY_IND) |