pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/42105?usp=email )
Change subject: Introduce struct osmo_ss7_as_asp_assoc ......................................................................
Introduce struct osmo_ss7_as_asp_assoc
This new struct allows supporting unlimited number of ASPs per AS. It can also potentially be used in the future to: * Hold M3UA "ASP Identifier" per AS<->ASP association * Speed up iterating over AS served by a given ASP.
NOTE: Having >16 ASPs per AS may not be desirable, for instance under loadshare traffic mode ITU SLS is 4 bit, so despite having ext_sls extending the table to 128 entries based on OPC, it may not provide enough entropy to properly loadshare among all of them.
Related: OS#7519 Change-Id: I149ab467899633ac50cba3e482b2cae02124279d --- M src/ss7_as.c M src/ss7_as.h M src/ss7_as_vty.c M src/ss7_combined_linkset.c M src/ss7_instance.c M src/ss7_internal.h M src/ss7_route.c M src/tcap_as_loadshare.c M src/xua_as_fsm.c M src/xua_asp_fsm.c M src/xua_default_lm_fsm.c 11 files changed, 191 insertions(+), 180 deletions(-)
Approvals: Jenkins Builder: Verified osmith: Looks good to me, approved laforge: Looks good to me, but someone else must approve
diff --git a/src/ss7_as.c b/src/ss7_as.c index f1c9528..4090d4a 100644 --- a/src/ss7_as.c +++ b/src/ss7_as.c @@ -51,6 +51,33 @@ #include "xua_msg.h"
/*********************************************************************** + * SS7 AS<->ASP association (N<->M arity) + ***********************************************************************/ +static struct ss7_as_asp_assoc *ss7_as_asp_assoc_alloc(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp) +{ + struct ss7_as_asp_assoc *assoc; + OSMO_ASSERT(as); + OSMO_ASSERT(asp); + + assoc = talloc_zero(as->inst, struct ss7_as_asp_assoc); + if (!assoc) + return NULL; + assoc->as = as; + assoc->asp = asp; + llist_add_tail(&assoc->as_entry, &as->assoc_asp_list); + as->num_assoc_asps++; + + return assoc; +} + +static void ss7_as_asp_assoc_free(struct ss7_as_asp_assoc *assoc) +{ + llist_del(&assoc->as_entry); + assoc->as->num_assoc_asps--; + talloc_free(assoc); +} + +/*********************************************************************** * SS7 Application Server ***********************************************************************/
@@ -137,15 +164,13 @@ } rate_ctr_group_set_name(as->ctrg, name); as->inst = inst; + INIT_LLIST_HEAD(&as->assoc_asp_list); as->cfg.name = talloc_strdup(as, name); as->cfg.proto = proto; as->cfg.mode = OSMO_SS7_AS_TMOD_OVERRIDE; as->cfg.recovery_timeout_msec = 2000; as->cfg.routing_key.l_rk_id = ss7_find_free_l_rk_id(inst);
- /* Pick 1st ASP upon 1st roundrobin assignment: */ - as->cfg.last_asp_idx_assigned = ARRAY_SIZE(as->cfg.asps) - 1; - #ifdef WITH_TCAP_LOADSHARING /* loadshare-tcap based id sharing */ hash_init(as->tcap.tid_ranges); @@ -176,7 +201,8 @@ * \returns 0 on success; negative in case of error */ int ss7_as_add_asp(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp) { - unsigned int i; + struct ss7_as_asp_assoc *assoc; + OSMO_ASSERT(as); OSMO_ASSERT(asp);
if (osmo_ss7_as_has_asp(as, asp)) @@ -184,17 +210,13 @@
LOGPAS(as, DLSS7, LOGL_INFO, "Adding ASP %s to AS\n", asp->cfg.name);
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - if (!as->cfg.asps[i]) { - as->cfg.asps[i] = asp; - if (asp->fi) - osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_AS_ASSIGNED, as); - return 0; - } - } + assoc = ss7_as_asp_assoc_alloc(as, asp); + OSMO_ASSERT(assoc);
- LOGPAS(as, DLSS7, LOGL_ERROR, "Failed adding ASP %s to AS, ASP table is full!\n", asp->cfg.name); - return -ENOSPC; + if (asp->fi) + osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_AS_ASSIGNED, as); + + return 0; }
/*! \brief Add given ASP to given AS @@ -213,6 +235,36 @@ return ss7_as_add_asp(as, asp); }
+static struct ss7_as_asp_assoc *ss7_as_asp_assoc_find(const struct osmo_ss7_as *as, + const struct osmo_ss7_asp *asp) +{ + struct ss7_as_asp_assoc *assoc; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + if (assoc->asp == asp) + return assoc; + } + return NULL; +} + +/* Update a given llist_round_robin state pointer which may point to an asp being freed. + * Selects next in list if available, or sets pointer to null. */ +void ss7_as_del_asp_update_llist_round_robin(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp, struct ss7_as_asp_assoc **state) +{ + struct ss7_as_asp_assoc *assoc; + + OSMO_ASSERT(state); + assoc = *state; + if (!assoc) + return; + if (asp != assoc->asp) + return; + + assoc = ss7_as_asp_assoc_llist_round_robin(as, (void **)state); + /* If there's only one left, remove state: */ + if (asp == assoc->asp) + *state = NULL; +} + /*! \brief Delete given ASP from given AS * \param[in] as Application Server from which \ref asp is deleted * \param[in] asp Application Server Process to delete from \ref as @@ -221,8 +273,11 @@ * \ref as may be freed during the function call. */ int ss7_as_del_asp(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp) { - unsigned int i; - bool found = false; + struct ss7_as_asp_assoc *assoc; + + assoc = ss7_as_asp_assoc_find(as, asp); + if (!assoc) + return -EINVAL;
LOGPAS(as, DLSS7, LOGL_INFO, "Removing ASP %s from AS\n", asp->cfg.name);
@@ -238,23 +293,19 @@ tcap_as_del_asp(as, asp); #endif /* WITH_TCAP_LOADSHARING */
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - if (as->cfg.asps[i] == asp) { - as->cfg.asps[i] = NULL; - found = true; - break; - } - } + /* Update round robin state */ + ss7_as_del_asp_update_llist_round_robin(as, asp, &as->last_asp_idx_assigned); + ss7_as_del_asp_update_llist_round_robin(as, asp, &as->last_asp_idx_sent); + ss7_as_asp_assoc_free(assoc);
/* RKM-dynamically allocated AS: If there are no other ASPs, destroy the AS. * RFC 4666 4.4.2: "If a Deregistration results in no more ASPs in an * Application Server, an SG MAY delete the Routing Key data." */ - if (as->rkm_dyn_allocated && osmo_ss7_as_count_asp(as) == 0) + if (as->rkm_dyn_allocated && llist_empty(&as->assoc_asp_list)) osmo_ss7_as_destroy(as);
- - return found ? 0 : -EINVAL; + return 0; }
/*! \brief Delete given ASP from given AS @@ -277,6 +328,7 @@ * \param[in] as Application Server to destroy */ void osmo_ss7_as_destroy(struct osmo_ss7_as *as) { + struct ss7_as_asp_assoc *assoc; OSMO_ASSERT(ss7_initialized); LOGPAS(as, DLSS7, LOGL_INFO, "Destroying AS\n");
@@ -290,6 +342,9 @@ /* find any routes pointing to this AS and remove them */ ss7_route_table_del_routes_by_as(as->inst->rtable_system, as);
+ while ((assoc = llist_first_entry_or_null(&as->assoc_asp_list, struct ss7_as_asp_assoc, as_entry))) + ss7_as_asp_assoc_free(assoc); + as->inst = NULL; llist_del(&as->list); rate_ctr_group_free(as->ctrg); @@ -303,48 +358,22 @@ bool osmo_ss7_as_has_asp(const struct osmo_ss7_as *as, const struct osmo_ss7_asp *asp) { - unsigned int i; - OSMO_ASSERT(ss7_initialized); - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - if (as->cfg.asps[i] == asp) - return true; - } - return false; -} - -/*! Determine amount of ASPs associated to an AS. - * \param[in] as Application Server. - * \returns number of ASPs associated to as */ -unsigned int osmo_ss7_as_count_asp(const struct osmo_ss7_as *as) -{ - unsigned int i; - unsigned int cnt = 0; - - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - if (as->cfg.asps[i]) - cnt++; - } - return cnt; + return !!ss7_as_asp_assoc_find(as, asp); }
/* Determine which role (SG/ASP/IPSP) we operate in. * return enum osmo_ss7_asp_role on success, negative otherwise. */ int ss7_as_get_local_role(const struct osmo_ss7_as *as) { - unsigned int i; + struct ss7_as_asp_assoc *assoc;
/* this is a bit tricky. "osmo_ss7_as" has no configuration of a role, * only the ASPs have. As they all must be of the same role, let's simply * find the first one and return its role */ - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - struct osmo_ss7_asp *asp = as->cfg.asps[i]; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) + return assoc->asp->cfg.role;
- if (!asp) - continue; - - return asp->cfg.role; - } /* No ASPs associated to this AS yet? */ return -1; } @@ -373,16 +402,13 @@
static struct osmo_ss7_asp *ss7_as_select_asp_override(struct osmo_ss7_as *as) { - struct osmo_ss7_asp *asp; - unsigned int i; + struct ss7_as_asp_assoc *assoc;
- /* FIXME: proper selection of the ASP based on the SLS! */ - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - asp = as->cfg.asps[i]; - if (asp && osmo_ss7_asp_active(asp)) - break; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + if (osmo_ss7_asp_active(assoc->asp)) + return assoc->asp; } - return asp; + return NULL; }
/* Pick an ASP serving AS in a round-robin fashion. @@ -394,41 +420,27 @@ * distribution. */ static struct osmo_ss7_asp *ss7_as_assign_asp_roundrobin(struct osmo_ss7_as *as) { - struct osmo_ss7_asp *asp; - unsigned int i; - unsigned int first_idx; + struct ss7_as_asp_assoc *assoc;
- first_idx = (as->cfg.last_asp_idx_assigned + 1) % ARRAY_SIZE(as->cfg.asps); - i = first_idx; - do { - asp = as->cfg.asps[i]; - if (asp) - break; - i = (i + 1) % ARRAY_SIZE(as->cfg.asps); - } while (i != first_idx); - as->cfg.last_asp_idx_assigned = i; - - return asp; + for (unsigned int i = 0; i < as->num_assoc_asps; i++) { + assoc = ss7_as_asp_assoc_llist_round_robin(as, &as->last_asp_idx_assigned); + if (assoc) + return assoc->asp; + } + return NULL; }
/* Pick an active ASP serving AS in a round-robin fashion, to send a message to. */ static struct osmo_ss7_asp *ss7_as_select_asp_roundrobin(struct osmo_ss7_as *as) { - struct osmo_ss7_asp *asp; - unsigned int i; - unsigned int first_idx; + struct ss7_as_asp_assoc *assoc;
- first_idx = (as->cfg.last_asp_idx_sent + 1) % ARRAY_SIZE(as->cfg.asps); - i = first_idx; - do { - asp = as->cfg.asps[i]; - if (asp && osmo_ss7_asp_active(asp)) - break; - i = (i + 1) % ARRAY_SIZE(as->cfg.asps); - } while (i != first_idx); - as->cfg.last_asp_idx_sent = i; - - return asp; + for (unsigned int i = 0; i < as->num_assoc_asps; i++) { + assoc = ss7_as_asp_assoc_llist_round_robin(as, &as->last_asp_idx_sent); + if (assoc && osmo_ss7_asp_active(assoc->asp)) + return assoc->asp; + } + return NULL; }
/* Reset loadshare bindings table. It will be filled in as needed. @@ -437,7 +449,7 @@ void ss7_as_loadshare_binding_table_reset(struct osmo_ss7_as *as) { memset(&as->aesls_table[0], 0, sizeof(as->aesls_table)); - as->cfg.last_asp_idx_assigned = ARRAY_SIZE(as->cfg.asps) - 1; + as->last_asp_idx_assigned = NULL; }
static as_ext_sls_t osmo_ss7_instance_calc_itu_as_ext_sls(const struct osmo_ss7_as *as, uint32_t opc, uint8_t sls) @@ -550,16 +562,15 @@ /* returns NULL if multiple ASPs would need to be selected. */ static struct osmo_ss7_asp *ss7_as_select_asp_broadcast(struct osmo_ss7_as *as) { - struct osmo_ss7_asp *asp; + struct ss7_as_asp_assoc *assoc; struct osmo_ss7_asp *asp_found = NULL;
- for (unsigned int i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - asp = as->cfg.asps[i]; - if (!asp || !osmo_ss7_asp_active(asp)) + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + if (!osmo_ss7_asp_active(assoc->asp)) continue; if (asp_found) /* >1 ASPs selected, early return */ return NULL; - asp_found = asp; + asp_found = assoc->asp; } return asp_found; } diff --git a/src/ss7_as.h b/src/ss7_as.h index 252e863..db219e0 100644 --- a/src/ss7_as.h +++ b/src/ss7_as.h @@ -83,6 +83,13 @@ struct osmo_ss7_asp *alt_asp; };
+struct ss7_as_asp_assoc { + /* Entry in (struct osmo_ss7_as*)->assoc_asp_list */ + struct llist_head as_entry; + struct osmo_ss7_as *as; /* backpointer */ + struct osmo_ss7_asp *asp; /* backpointer */ +}; + struct osmo_ss7_as { /*! entry in 'ref osmo_ss7_instance.as_list */ struct llist_head list; @@ -118,6 +125,13 @@ } tcap; #endif /* WITH_TCAP_LOADSHARING */
+ /* used for load-sharing traffic mode (round robin implementation) */ + struct ss7_as_asp_assoc *last_asp_idx_assigned; + struct ss7_as_asp_assoc *last_asp_idx_sent; + + struct llist_head assoc_asp_list; /* list of struct ss7_as_asp_assoc */ + unsigned int num_assoc_asps; /* amount of ss7_as_asp_assoc/ss7_asp in assoc_asp_list */ + struct { char *name; char *description; @@ -138,11 +152,6 @@ enum osmo_ss7_as_patch_sccp_mode sccp_mode; } pc_override;
- struct osmo_ss7_asp *asps[16]; - /* used for load-sharing traffic mode (round robin implementation) */ - uint8_t last_asp_idx_assigned; - uint8_t last_asp_idx_sent; - struct { /* How many bits from ITU SLS field (starting from least-significant-bit) * to skip for routing decisions. @@ -159,7 +168,7 @@ struct { bool enabled; unsigned int timeout_s; - uint8_t last_asp_idx_sent; + struct ss7_as_asp_assoc *last_asp_idx_sent; } tcap; #endif /* WITH_TCAP_LOADSHARING */ } loadshare; @@ -169,11 +178,14 @@ enum osmo_ss7_asp_protocol proto); struct osmo_ss7_asp *ss7_as_select_asp(struct osmo_ss7_as *as, const struct xua_msg *xua);
-unsigned int osmo_ss7_as_count_asp(const struct osmo_ss7_as *as); int ss7_as_add_asp(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp); int ss7_as_del_asp(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp); int ss7_as_get_local_role(const struct osmo_ss7_as *as); void ss7_as_loadshare_binding_table_reset(struct osmo_ss7_as *as);
+void ss7_as_del_asp_update_llist_round_robin(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp, struct ss7_as_asp_assoc **state); +#define ss7_as_asp_assoc_llist_round_robin(as, state) \ + ss7_llist_round_robin(&(as)->assoc_asp_list, (void **)state, struct ss7_as_asp_assoc, as_entry) + #define LOGPAS(as, subsys, level, fmt, args ...) \ _LOGSS7((as)->inst, subsys, level, "AS(%s) " fmt, (as)->cfg.name, ## args) diff --git a/src/ss7_as_vty.c b/src/ss7_as_vty.c index f92b6d7..2f59c3d 100644 --- a/src/ss7_as_vty.c +++ b/src/ss7_as_vty.c @@ -41,6 +41,7 @@ #ifdef WITH_TCAP_LOADSHARING #include "tcap_as_loadshare.h" #endif /* WITH_TCAP_LOADSHARING */ +#include "ss7_as.h" #include "ss7_asp.h" #include "ss7_route.h" #include "ss7_route_table.h" @@ -468,7 +469,7 @@ void ss7_vty_write_one_as(struct vty *vty, struct osmo_ss7_as *as, bool show_dyn_config) { struct osmo_ss7_routing_key *rkey; - unsigned int i; + struct ss7_as_asp_assoc *assoc;
/* skip any dynamically allocated AS definitions */ if ((as->rkm_dyn_allocated || as->simple_client_allocated) @@ -479,8 +480,8 @@ osmo_ss7_asp_protocol_name(as->cfg.proto), VTY_NEWLINE); if (as->cfg.description) vty_out(vty, " description %s%s", as->cfg.description, VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - struct osmo_ss7_asp *asp = as->cfg.asps[i]; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp = assoc->asp; if (!asp) continue; /* skip any dynamically created ASPs (e.g. auto-created at connect time) */ diff --git a/src/ss7_combined_linkset.c b/src/ss7_combined_linkset.c index 0b6dd3c..9f53b7b 100644 --- a/src/ss7_combined_linkset.c +++ b/src/ss7_combined_linkset.c @@ -50,20 +50,6 @@ * link set) or of an alternative link set (combined link set)." *****************************************************************************/
-static inline struct llist_head *_ss7_llist_round_robin(struct llist_head *list, void **state) -{ - struct llist_head *e = *state; - if (!e || e->next == list) - e = list; - e = e->next; - if (e == list) - e = NULL; - *state = e; - return e; -} -#define ss7_llist_round_robin(list, state, struct_type, entry_name) \ - llist_entry(_ss7_llist_round_robin(list, state), struct_type, entry_name) - /*! \brief Insert combined_link into its routing table * \param[in] clset Combined link to be inserted into its routing table * \returns 0 on success, negative on error diff --git a/src/ss7_instance.c b/src/ss7_instance.c index b51f1b9..1c5e113 100644 --- a/src/ss7_instance.c +++ b/src/ss7_instance.c @@ -408,11 +408,11 @@ osmo_ss7_asp_find_by_proto(struct osmo_ss7_as *as, enum osmo_ss7_asp_protocol proto) { - unsigned int i; + struct ss7_as_asp_assoc *assoc;
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - if (as->cfg.asps[i] && as->cfg.asps[i]->cfg.proto == proto) - return as->cfg.asps[i]; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + if (assoc->asp->cfg.proto == proto) + return assoc->asp; }
return NULL; diff --git a/src/ss7_internal.h b/src/ss7_internal.h index cfa092a..b70954e 100644 --- a/src/ss7_internal.h +++ b/src/ss7_internal.h @@ -4,6 +4,8 @@
#include <stdbool.h> #include <stdint.h> + +#include <osmocom/core/linuxlist.h> #include <osmocom/netif/stream.h> #include <osmocom/sigtran/osmo_ss7.h>
@@ -28,5 +30,19 @@
int xua_tcp_segmentation_cb(struct msgb *msg);
+static inline struct llist_head *_ss7_llist_round_robin(struct llist_head *list, void **state) +{ + struct llist_head *e = *state; + if (!e || e->next == list) + e = list; + e = e->next; + if (e == list) + e = NULL; + *state = e; + return e; +} +#define ss7_llist_round_robin(list, state, struct_type, entry_name) \ + llist_entry(_ss7_llist_round_robin(list, state), struct_type, entry_name) + /* VTY */ #define XUA_VAR_STR "(sua|m3ua|ipa)" diff --git a/src/ss7_route.c b/src/ss7_route.c index 713cc6a..7d22144 100644 --- a/src/ss7_route.c +++ b/src/ss7_route.c @@ -326,14 +326,12 @@
if (rt->dest.as) { struct osmo_ss7_as *as = rt->dest.as; - int i; APPEND(" via AS %s proto=%s", as->cfg.name, osmo_ss7_asp_protocol_name(as->cfg.proto));
if (list_asps) { - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - struct osmo_ss7_asp *asp = as->cfg.asps[i]; - if (!asp) - continue; + struct ss7_as_asp_assoc *assoc; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp = assoc->asp; APPEND(" ASP"); if (asp->cfg.name) APPEND(" %s", asp->cfg.name); diff --git a/src/tcap_as_loadshare.c b/src/tcap_as_loadshare.c index 5c964ce..356a982 100644 --- a/src/tcap_as_loadshare.c +++ b/src/tcap_as_loadshare.c @@ -230,21 +230,13 @@
static struct osmo_ss7_asp *find_asp_no_tcap_range(struct osmo_ss7_as *as) { - struct osmo_ss7_asp *asp; - unsigned int i; - unsigned int first_idx; + struct ss7_as_asp_assoc *assoc;
- first_idx = (as->cfg.loadshare.tcap.last_asp_idx_sent + 1) % ARRAY_SIZE(as->cfg.asps); - i = first_idx; - do { - asp = as->cfg.asps[i]; - if (asp && osmo_ss7_asp_active(asp) && asp->tcap.enabled) { - as->cfg.loadshare.tcap.last_asp_idx_sent = i; - return asp; - } - i = (i + 1) % ARRAY_SIZE(as->cfg.asps); - } while (i != first_idx); - + for (unsigned int i = 0; i < as->num_assoc_asps; i++) { + assoc = ss7_as_asp_assoc_llist_round_robin(as, &as->cfg.loadshare.tcap.last_asp_idx_sent); + if (assoc && osmo_ss7_asp_active(assoc->asp) && assoc->asp->tcap.enabled) + return assoc->asp; + } return NULL; }
@@ -923,6 +915,8 @@ if (!asp->tcap.enabled) return;
+ /* Update round robin state */ + ss7_as_del_asp_update_llist_round_robin(as, asp, &as->cfg.loadshare.tcap.last_asp_idx_sent); _tcap_range_asp_down(as, asp); if (as->tcap.contains_pc || as->tcap.contains_ssn) tcap_range_as_update_pc_ssn(as); @@ -945,6 +939,7 @@ as->cfg.loadshare.tcap.enabled = false; as->tcap.contains_pc = false; as->tcap.contains_ssn = false; + as->cfg.loadshare.tcap.last_asp_idx_sent = NULL; tcap_trans_track_garbage_collect_stop(as); tcap_trans_track_entries_free_all(as); } diff --git a/src/xua_as_fsm.c b/src/xua_as_fsm.c index 53e2c00..bdcd0d5 100644 --- a/src/xua_as_fsm.c +++ b/src/xua_as_fsm.c @@ -103,8 +103,9 @@ static int as_notify_all_asp(struct osmo_ss7_as *as, struct osmo_xlm_prim_notify *npar) { struct msgb *msg; - unsigned int i, sent = 0; + unsigned int sent = 0; const char *type_name, *info_name, *info_str; + struct ss7_as_asp_assoc *assoc;
/* we don't send notify to IPA peers! */ if (as->cfg.proto == OSMO_SS7_ASP_PROT_IPA) @@ -117,11 +118,8 @@ type_name, info_name, info_str);
/* iterate over all non-DOWN ASPs and send them the message */ - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - struct osmo_ss7_asp *asp = as->cfg.asps[i]; - - if (!asp) - continue; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp = assoc->asp;
/* NOTIFY are only sent by SG or IPSP role */ if (asp->cfg.role == OSMO_SS7_ASP_ROLE_ASP) @@ -165,7 +163,7 @@ int xua_as_transmit_msg_broadcast(struct osmo_ss7_as *as, struct xua_msg *xua) { struct osmo_ss7_asp *asp; - unsigned int i; + struct ss7_as_asp_assoc *assoc; struct msgb *msg; struct msgb *msg_cpy; bool sent = false; @@ -173,9 +171,9 @@ msg = xua_as_encode_msg(as, xua); OSMO_ASSERT(msg);
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - asp = as->cfg.asps[i]; - if (!asp || !osmo_ss7_asp_active(asp)) + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + asp = assoc->asp; + if (!osmo_ss7_asp_active(asp)) continue; msg_cpy = msgb_copy(msg, "xua_bcast_cpy"); if (osmo_ss7_asp_send(asp, msg_cpy) == 0) @@ -273,13 +271,10 @@ /* 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) { - unsigned int i; + struct ss7_as_asp_assoc *assoc;
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - struct osmo_ss7_asp *asp = as->cfg.asps[i]; - if (!asp) - continue; - + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp = assoc->asp; if (asp_cmp == asp) continue;
@@ -293,13 +288,10 @@ /* is any other ASP in this AS in state ACTIVE? */ static bool check_any_other_asp_in_active(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp_cmp) { - unsigned int i; + struct ss7_as_asp_assoc *assoc;
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - struct osmo_ss7_asp *asp = as->cfg.asps[i]; - if (!asp) - continue; - + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp = assoc->asp; if (asp_cmp == asp) continue;
@@ -316,7 +308,7 @@ * */ static void notify_any_other_active_asp_as_inactive(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp_cmp) { - unsigned int i; + struct ss7_as_asp_assoc *assoc; struct msgb *msg; struct osmo_xlm_prim_notify npar = { .status_type = M3UA_NOTIFY_T_OTHER, @@ -326,9 +318,9 @@ if (asp_cmp->remote_asp_id_present) npar.asp_id = asp_cmp->remote_asp_id;
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - struct osmo_ss7_asp *asp = as->cfg.asps[i]; - if (!asp || !osmo_ss7_asp_active(asp)) + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp = assoc->asp; + if (!osmo_ss7_asp_active(asp)) continue;
if (asp_cmp == asp) diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c index 5ae0d0f..32986fc 100644 --- a/src/xua_asp_fsm.c +++ b/src/xua_asp_fsm.c @@ -1355,14 +1355,14 @@ { for (unsigned int sls = 0; sls <= 0x0f; sls++) { bool used = false; - for (unsigned i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - if (!as->cfg.asps[i]) + struct ss7_as_asp_assoc *assoc; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + struct osmo_ss7_asp *asp_it = assoc->asp; + if (asp_it == asp) continue; - if (as->cfg.asps[i] == asp) + if (!asp_it->ipa.sls_assigned) continue; - if (!as->cfg.asps[i]->ipa.sls_assigned) - continue; - if (as->cfg.asps[i]->ipa.sls == sls) { + if (asp_it->ipa.sls == sls) { used = true; break; } diff --git a/src/xua_default_lm_fsm.c b/src/xua_default_lm_fsm.c index fb9ac1e..11dd32e 100644 --- a/src/xua_default_lm_fsm.c +++ b/src/xua_default_lm_fsm.c @@ -160,9 +160,9 @@ struct osmo_ss7_as *as;
llist_for_each_entry(as, &asp->inst->as_list, list) { - unsigned int i; - for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { - if (as->cfg.asps[i] == asp) + struct ss7_as_asp_assoc *assoc; + llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) { + if (assoc->asp == asp) return as; } }