aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-04-25 18:45:07 +0200
committerlaforge <laforge@osmocom.org>2021-04-26 19:43:31 +0000
commit5b0ec1ce67ede894d2fc8f96422f915280d07611 (patch)
tree7c7c25a7301fb5a5b6c14fbe883a23e68698dd86
parent6b799aeb67c09ce4c4b9e531afb0bcc7093ebd37 (diff)
ipa: Move automatic route add/del from ASP to AS level
SS7 routes operate on AS level, not ASP level. However, the automatic SS7 route creation/destruction for IPA was implemented at the ASP level. This works for single-connection ASs, but obviously fails in load-share situations: We attempt to add the same route several times, and we delete it at the first ASP disconnect, even while other ASPs still exist. This patch moves the IPA route creation/deletion from the ASP level to the AS level. When the AS becomes active, the route is added; when it goes to DOWN state, it is removed. Change-Id: Idb602beae3e9bc19f7bd96355c02ec8dfd9c5d6c
-rw-r--r--src/xua_as_fsm.c64
-rw-r--r--src/xua_asp_fsm.c55
2 files changed, 64 insertions, 55 deletions
diff --git a/src/xua_as_fsm.c b/src/xua_as_fsm.c
index 7c791cf..f66ba88 100644
--- a/src/xua_as_fsm.c
+++ b/src/xua_as_fsm.c
@@ -202,6 +202,66 @@ struct xua_as_fsm_priv {
} recovery;
};
+/* is the given AS one with a single ASP of IPA type? */
+static bool is_single_ipa_asp(struct osmo_ss7_as *as)
+{
+ unsigned int asp_count = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) {
+ struct osmo_ss7_asp *asp = as->cfg.asps[i];
+ if (!asp)
+ continue;
+ asp_count++;
+ if (asp->cfg.proto != OSMO_SS7_ASP_PROT_IPA)
+ return false;
+ }
+ if (asp_count == 1)
+ return true;
+ return false;
+}
+
+static void ipa_add_route(struct osmo_fsm_inst *fi)
+{
+ struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv;
+ struct osmo_ss7_as *as = xafp->as;
+ struct osmo_ss7_instance *inst = as->inst;
+
+ /* As opposed to M3UA, there is no RKM and we have to implicitly
+ * automatically add a route once an IPA connection has come up */
+ osmo_ss7_route_create(inst->rtable_system, as->cfg.routing_key.pc, 0xffffff, as->cfg.name);
+}
+
+static void ipa_del_route(struct osmo_fsm_inst *fi)
+{
+ struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv;
+ struct osmo_ss7_as *as = xafp->as;
+ struct osmo_ss7_instance *inst = as->inst;
+ struct osmo_ss7_route *rt;
+
+ /* find the route which we have created if we ever reached ipa_asp_fsm_wait_id_ack2 */
+ rt = osmo_ss7_route_find_dpc_mask(inst->rtable_system, as->cfg.routing_key.pc, 0xffffff);
+ /* no route found, bail out */
+ if (!rt) {
+ LOGPFSML(fi, LOGL_NOTICE, "Attempting to delete route for this IPA AS, but cannot "
+ "find route for DPC %s. Did you manually delete it?\n",
+ osmo_ss7_pointcode_print(inst, as->cfg.routing_key.pc));
+ return;
+ }
+
+ /* route points to different AS, bail out */
+ if (rt->dest.as != as) {
+ LOGPFSML(fi, LOGL_NOTICE, "Attempting to delete route for this IPA ASP, but found "
+ "route for DPC %s points to different AS (%s)\n",
+ osmo_ss7_pointcode_print(inst, as->cfg.routing_key.pc), rt->dest.as->cfg.name);
+ return;
+ }
+
+ osmo_ss7_route_destroy(rt);
+}
+
+
+
/* is any other ASP in this AS in state != DOWN? */
static bool check_any_other_asp_not_down(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp_cmp)
{
@@ -309,12 +369,16 @@ static void xua_as_fsm_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
npar.status_info = M3UA_NOTIFY_I_AS_INACT;
break;
case XUA_AS_S_ACTIVE:
+ if (is_single_ipa_asp(as))
+ ipa_add_route(fi);
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:
+ if (is_single_ipa_asp(as))
+ ipa_del_route(fi);
/* RFC4666 sec 4.3.2 AS States:
If we end up here, it means no ASP is ACTIVE or INACTIVE,
meaning no ASP can have already configured the traffic mode
diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c
index f8683d5..ec85d21 100644
--- a/src/xua_asp_fsm.c
+++ b/src/xua_asp_fsm.c
@@ -939,23 +939,11 @@ out_err:
/* Server: We're waiting for an ID ACK */
static void ipa_asp_fsm_wait_id_ack2(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
- struct ipa_asp_fsm_priv *iafp = fi->priv;
- struct osmo_ss7_asp *asp = iafp->asp;
- struct osmo_ss7_instance *inst = asp->inst;
- struct osmo_ss7_as *as;
-
- xua_find_as_for_asp(&as, asp, NULL);
- OSMO_ASSERT(as);
-
switch (event) {
case IPA_ASP_E_ID_ACK:
/* ACK received, we can go to active state now. The
* ACTIVE onenter function will inform the AS */
osmo_fsm_inst_state_chg(fi, IPA_ASP_S_ACTIVE, 0, 0);
- /* As opposed to M3UA, there is no RKM and we have to implicitly automatically add
- * a route once an IPA connection has come up */
- osmo_ss7_route_create(inst->rtable_system, as->cfg.routing_key.pc, 0xffffff,
- as->cfg.name);
break;
}
}
@@ -1011,48 +999,12 @@ static void ipa_asp_fsm_wait_id_ack(struct osmo_fsm_inst *fi, uint32_t event, vo
}
}
-static void ipa_asp_fsm_del_route(struct osmo_fsm_inst *fi)
-{
- struct ipa_asp_fsm_priv *iafp = fi->priv;
- struct osmo_ss7_asp *asp = iafp->asp;
- struct osmo_ss7_instance *inst = asp->inst;
- struct osmo_ss7_as *as;
- struct osmo_ss7_route *rt;
-
- xua_find_as_for_asp(&as, asp, NULL);
- OSMO_ASSERT(as);
-
- /* find the route which we have created if we ever reached ipa_asp_fsm_wait_id_ack2 */
- rt = osmo_ss7_route_find_dpc_mask(inst->rtable_system, as->cfg.routing_key.pc, 0xffffff);
- /* no route found, bail out */
- if (!rt) {
- LOGPFSML(fi, LOGL_NOTICE, "Attempting to delete route for this IPA ASP, but cannot "
- "find route for DPC %s. Did you manually delete it?\n",
- osmo_ss7_pointcode_print(inst, as->cfg.routing_key.pc));
- return;
- }
-
- /* route points to different AS, bail out */
- if (rt->dest.as != as) {
- LOGPFSML(fi, LOGL_NOTICE, "Attempting to delete route for this IPA ASP, but found "
- "route for DPC %s points to different AS (%s)\n",
- osmo_ss7_pointcode_print(inst, as->cfg.routing_key.pc), rt->dest.as->cfg.name);
- return;
- }
-
- osmo_ss7_route_destroy(rt);
- /* FIXME: Why don't we also delete this timer if we return early above?
- * FIXME: Where is this timer even scheduled? */
- osmo_timer_del(&iafp->pong_timer);
-}
-
/* Server + Client: We're actively transmitting user data */
static void ipa_asp_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
case XUA_ASP_E_M_ASP_DOWN_REQ:
case XUA_ASP_E_M_ASP_INACTIVE_REQ:
- ipa_asp_fsm_del_route(fi);
osmo_fsm_inst_state_chg(fi, IPA_ASP_S_DOWN, 0, 0);
break;
}
@@ -1062,7 +1014,6 @@ static void ipa_asp_fsm_inactive(struct osmo_fsm_inst *fi, uint32_t event, void
{
switch (event) {
case XUA_ASP_E_M_ASP_DOWN_REQ:
- ipa_asp_fsm_del_route(fi);
osmo_fsm_inst_state_chg(fi, IPA_ASP_S_DOWN, 0, 0);
break;
}
@@ -1187,11 +1138,6 @@ static const struct osmo_fsm_state ipa_asp_states[] = {
},
};
-static void ipa_asp_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
-{
- ipa_asp_fsm_del_route(fi);
-}
-
struct osmo_fsm ipa_asp_fsm = {
.name = "IPA_ASP",
.states = ipa_asp_states,
@@ -1204,7 +1150,6 @@ struct osmo_fsm ipa_asp_fsm = {
S(XUA_ASP_E_ASPSM_BEAT) |
S(XUA_ASP_E_ASPSM_BEAT_ACK),
.allstate_action = ipa_asp_allstate,
- .cleanup = ipa_asp_fsm_cleanup,
};