pespin has uploaded this change for review.

View Change

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, 60 insertions(+), 17 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/08/39708/1
diff --git a/src/osmo_ss7_combined_linkset.c b/src/osmo_ss7_combined_linkset.c
index a741aba..37da4fc 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,6 +201,36 @@
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).
+ * Morevoer, 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;
+ 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_ass, struct osmo_ss7_route, list);
+ if (rt) {
+ rt_found = rt;
+ break;
+ }
+ }
+
+ if (!rt_found)
+ return NULL;
+
+ return rt_found;
+}
+
+/* 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;
@@ -203,8 +239,8 @@

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 = ss7_llist_round_robin(&clset->routes, &clset->last_route_roundrobin_tx, struct osmo_ss7_route, list);
+ if (rt && ss7_route_is_available(rt)) {
rt_found = rt;
break;
}
@@ -256,18 +292,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 change 39708. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I6daf114416c69c84bdc3042efcaf2918f91c2e87
Gerrit-Change-Number: 39708
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>