pespin submitted this change.
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(-)
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) |
To view, visit change 42573. To unsubscribe, or for help writing mail filters, visit settings.