pespin has submitted this change. ( 
https://gerrit.osmocom.org/c/libosmo-sigtran/+/39708?usp=email )

Change subject: AS loadsharing: Normal route distribution regardless of active 
state
......................................................................

AS loadsharing: Normal route distribution regardless of active state

Before this patch, the normal route for a given loadshare eSLS entry (seed)
would only be filled in with available routes.
That means that if eg. N routes are configured but only 1 is really
available upon startup and a lot of traffic happens, the full eSLS will
be filled with that route, and as a result all traffic on that combined
linkset will be sent through that route.

Instead, we want to populate the eSLS table with Normal Route field
properly distributed over all routes. If a given route is not active at
that time, then simply pick an Alternative Route during that time.

Change-Id: I6daf114416c69c84bdc3042efcaf2918f91c2e87
---
M src/osmo_ss7_combined_linkset.c
M src/ss7_combined_linkset.h
2 files changed, 54 insertions(+), 29 deletions(-)

Approvals:
  osmith: Looks good to me, but someone else must approve
  laforge: Looks good to me, but someone else must approve
  pespin: Looks good to me, approved
  Jenkins Builder: Verified




diff --git a/src/osmo_ss7_combined_linkset.c b/src/osmo_ss7_combined_linkset.c
index a741aba..b4cd914 100644
--- a/src/osmo_ss7_combined_linkset.c
+++ b/src/osmo_ss7_combined_linkset.c
@@ -151,11 +151,17 @@
        }

        /* Update round robin state */
-       if (rt == clset->last_route_roundrobin) {
-               ss7_llist_round_robin(&clset->routes, 
&clset->last_route_roundrobin, struct osmo_ss7_route, list);
+       if (rt == clset->last_route_roundrobin_ass) {
+               ss7_llist_round_robin(&clset->routes, 
&clset->last_route_roundrobin_ass, struct osmo_ss7_route, list);
                /* If there's only one left, remove state: */
-               if (rt == clset->last_route_roundrobin)
-                       clset->last_route_roundrobin = NULL;
+               if (rt == clset->last_route_roundrobin_ass)
+                       clset->last_route_roundrobin_ass = NULL;
+       }
+       if (rt == clset->last_route_roundrobin_tx) {
+               ss7_llist_round_robin(&clset->routes, 
&clset->last_route_roundrobin_tx, struct osmo_ss7_route, list);
+               /* If there's only one left, remove state: */
+               if (rt == clset->last_route_roundrobin_tx)
+                       clset->last_route_roundrobin_tx = NULL;
        }

        llist_del(&rt->list);
@@ -195,25 +201,37 @@
        return NULL;
 }

+/* Pick a Route from Combined Linkset in a round-robin fashion.
+ * During Loadshare eSLS table generation we want to pick Normal Route
+ * in a distributed fashion, regardless of active state (Alternative Route will
+ * be picked up temporarily later on if needed).
+ * Moreover, we must use a different index from the "active"
+ * ss7_combined_linkset_select_route_roundrobin() below, in order to avoid 
tainting
+ * the distribution.
+ */
+static struct osmo_ss7_route 
*ss7_combined_linkset_assign_route_roundrobin(struct osmo_ss7_combined_linkset 
*clset)
+{
+       struct osmo_ss7_route *rt;
+
+       for (unsigned int i = 0; i < clset->num_routes; i++) {
+               rt = ss7_llist_round_robin(&clset->routes, 
&clset->last_route_roundrobin_ass, struct osmo_ss7_route, list);
+               if (rt)
+                       return rt;
+       }
+       return NULL;
+}
+
+/* Pick an available route from Combined Linkset in a round-robin fashion, to 
send a message through. */
 static struct osmo_ss7_route 
*ss7_combined_linkset_select_route_roundrobin(struct osmo_ss7_combined_linkset 
*clset)
 {
        struct osmo_ss7_route *rt;
-       struct osmo_ss7_route *rt_found = NULL;
-       unsigned int i = 0;

-       while (i < clset->num_routes) {
-               i++;
-               rt = ss7_llist_round_robin(&clset->routes, 
&clset->last_route_roundrobin, struct osmo_ss7_route, list);
-               if (ss7_route_is_available(rt)) {
-                       rt_found = rt;
-                       break;
-               }
+       for (unsigned int i = 0; i < clset->num_routes; i++) {
+               rt = ss7_llist_round_robin(&clset->routes, 
&clset->last_route_roundrobin_tx, struct osmo_ss7_route, list);
+               if (rt && ss7_route_is_available(rt))
+                       return rt;
        }
-
-       if (!rt_found)
-               return NULL;
-
-       return rt_found;
+       return NULL;
 }

 struct osmo_ss7_route *
@@ -256,18 +274,24 @@

        /* No normal route selected yet: */
        if (!eslse->normal_rt) {
-               rt = ss7_combined_linkset_select_route_roundrobin(clset);
-               /* Either a normal route was selected or none found: */
+               /* Establish a Normal Route, regardless of available state: */
+               rt = ss7_combined_linkset_assign_route_roundrobin(clset);
+               /* No route found for Normal Route, regardless of state... */
+               if (!rt)
+                       return NULL;
                eslse->normal_rt = rt;
-               if (rt) {
-                       LOGPCLSET(clset, DLSS7, LOGL_DEBUG, "RT loookup: 
OPC=%u=%s,DPC=%u=%s,SLS=%u -> eSLS=%u: "
-                                 "picked Normal Route via '%s' round-robin 
style\n",
-                                 rtlabel->opc, osmo_ss7_pointcode_print(inst, 
rtlabel->opc),
-                                 rtlabel->dpc, osmo_ss7_pointcode_print2(inst, 
rtlabel->dpc),
-                                 rtlabel->sls, esls,
-                                 rt->dest.as ? rt->dest.as->cfg.name : 
"<linkset>");
+               LOGPCLSET(clset, DLSS7, LOGL_DEBUG, "RT loookup: 
OPC=%u=%s,DPC=%u=%s,SLS=%u -> eSLS=%u: "
+                         "picked Normal Route via '%s' round-robin style\n",
+                         rtlabel->opc, osmo_ss7_pointcode_print(inst, 
rtlabel->opc),
+                         rtlabel->dpc, osmo_ss7_pointcode_print2(inst, 
rtlabel->dpc),
+                         rtlabel->sls, esls,
+                         rt->dest.as ? rt->dest.as->cfg.name : "<linkset>");
+               if (ss7_route_is_available(eslse->normal_rt)) {
+                       /* Found available Normal Route: */
+                       return eslse->normal_rt;
                }
-               return rt;
+               /* Normal Route was assigned, but it is not active, fall-through
+                * below to attempt transmission through Alternative Route: */
        }

        /* Normal route unavailable and no alternative route (or unavailable 
too).
diff --git a/src/ss7_combined_linkset.h b/src/ss7_combined_linkset.h
index b79810b..432ebd7 100644
--- a/src/ss7_combined_linkset.h
+++ b/src/ss7_combined_linkset.h
@@ -33,7 +33,8 @@
        /*! list of \ref osmo_ss7_route */
        struct llist_head routes;
        unsigned int num_routes;
-       void *last_route_roundrobin;
+       void *last_route_roundrobin_ass;
+       void *last_route_roundrobin_tx;

        struct {
                uint32_t pc;

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

Gerrit-MessageType: merged
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I6daf114416c69c84bdc3042efcaf2918f91c2e87
Gerrit-Change-Number: 39708
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pes...@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <lafo...@osmocom.org>
Gerrit-Reviewer: osmith <osm...@sysmocom.de>
Gerrit-Reviewer: pespin <pes...@sysmocom.de>

Reply via email to