pespin has uploaded this change for review. ( 
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, 189 insertions(+), 180 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran 
refs/changes/05/42105/1

diff --git a/src/ss7_as.c b/src/ss7_as.c
index f1c9528..f5f7c82 100644
--- a/src/ss7_as.c
+++ b/src/ss7_as.c
@@ -51,6 +51,31 @@
 #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;
+
+       assoc = talloc_zero(as->inst, struct ss7_as_asp_assoc);
+       if (!as)
+               return NULL;
+       assoc->as = as;
+       assoc->asp = asp;
+       llist_add_tail(&assoc->as_entry, &as->asp_list);
+       as->num_asps++;
+
+       return assoc;
+}
+
+static void ss7_as_asp_assoc_free(struct ss7_as_asp_assoc *assoc)
+{
+       llist_del(&assoc->as_entry);
+       assoc->as->num_asps--;
+       talloc_free(assoc);
+}
+
+/***********************************************************************
  * SS7 Application Server
  ***********************************************************************/

@@ -137,15 +162,13 @@
        }
        rate_ctr_group_set_name(as->ctrg, name);
        as->inst = inst;
+       INIT_LLIST_HEAD(&as->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 +199,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 +208,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 +233,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->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 +271,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 +291,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->asp_list))
                osmo_ss7_as_destroy(as);

-
-       return found ? 0 : -EINVAL;
+       return 0;
 }

 /*! \brief Delete given ASP from given AS
@@ -277,6 +326,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 +340,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->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 +356,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->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 +400,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->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 +418,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_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_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 +447,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 +560,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->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..4819c8e 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*)->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 asp_list; /* list of struct ss7_as_asp_assoc */
+       unsigned long num_asps; /* amount of ss7_as_asp_assoc/ss7_asp in 
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)->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..6e2b582 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->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..9cf4710 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->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..914e615 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->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..f9b8bdd 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_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..0dbb481 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->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->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->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->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->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..ea5f64c 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->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..07c00fd 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->asp_list, as_entry) {
+                       if (assoc->asp == asp)
                                return as;
                }
        }

--
To view, visit https://gerrit.osmocom.org/c/libosmo-sigtran/+/42105?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I149ab467899633ac50cba3e482b2cae02124279d
Gerrit-Change-Number: 42105
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>

Reply via email to