pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-sigtran/+/39391?usp=email )
Change subject: AS loadsharing: Implement AS loadshare, skip unavailable AS/lset when
choosing
......................................................................
AS loadsharing: Implement AS loadshare, skip unavailable AS/lset when choosing
Pick normal route containing destination AS/lset to serve a given
func(<OPC,DPC,SLS>)=eSLS on a round-robin base.
If normal route becomes unavailable, pick an alternative route in a
similar way. This alternative route will be used until itself becomes
unavailable or the normal route becomes available again.
Related: SYS#7112
Change-Id: I928fb1ef5db6922f1386a188e3fbf9e70780f25d
---
M src/osmo_ss7_combined_linkset.c
M src/osmo_ss7_link.c
M src/osmo_ss7_linkset.c
M src/osmo_ss7_route.c
M src/ss7_combined_linkset.h
M src/ss7_link.h
M src/ss7_linkset.h
M tests/ss7/ss7_test.c
8 files changed, 92 insertions(+), 19 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/91/39391/1
diff --git a/src/osmo_ss7_combined_linkset.c b/src/osmo_ss7_combined_linkset.c
index ed0fc79..23b3ae0 100644
--- a/src/osmo_ss7_combined_linkset.c
+++ b/src/osmo_ss7_combined_linkset.c
@@ -49,6 +49,20 @@
* 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
@@ -135,6 +149,14 @@
clset->esls_table[i].alt_rt = NULL;
}
+ /* 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 there's only one left, remove state: */
+ if (rt == clset->last_route_roundrobin)
+ clset->last_route_roundrobin = NULL;
+ }
+
llist_del(&rt->list);
rt->clset = NULL;
clset->num_routes--;
@@ -172,6 +194,27 @@
return NULL;
}
+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;
+ }
+ }
+
+ if (!rt_found)
+ return NULL;
+
+ return rt_found;
+}
+
struct osmo_ss7_route *
ss7_combined_linkset_lookup_route(struct osmo_ss7_combined_linkset *clset, const struct
osmo_ss7_route_label *rtlabel)
{
@@ -192,20 +235,20 @@
return rt;
}
- /* TODO: Check if the AS/linkset in rt is actually UP and can be
- * used, otherwise start ITU Q.704 section 7 "forced rerouting" prcoedure:
- * we need to pick a temporary dst (update the esls_table entry) while the
- * original one is DOWN. */
+ /* No current route available, try to find a new current route: */
- /* We need to pick a new AS/linkset from the combined linkset and cache
- * it so it is always used for this eSLS: */
- /* FIXME: for now we simply take the first AS in the combined linksed, to be improved
later... */
- rt = llist_first_entry_or_null(&clset->routes, struct osmo_ss7_route, list);
+ /* 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: */
+ eslse->normal_rt = rt;
+ return rt;
+ }
- /* TODO: here we'd need to actually check if dst AS/linkset in the route
- * is actually UP, otherwise pick next one in the roundrobin list... */
+ /* Normal route unavailable and no alternative route (or unavailable too).
+ * start ITU Q.704 section 7 "forced rerouting" procedure: */
+ rt = ss7_combined_linkset_select_route_roundrobin(clset);
if (rt)
- clset->esls_table[esls].normal_rt = rt;
-
+ eslse->alt_rt = rt;
return rt;
}
diff --git a/src/osmo_ss7_link.c b/src/osmo_ss7_link.c
index 321d72e..6310824 100644
--- a/src/osmo_ss7_link.c
+++ b/src/osmo_ss7_link.c
@@ -75,3 +75,11 @@
return link;
}
+
+/* Whether link is available, ITU Q.704 section 3.2 */
+bool
+ss7_link_is_available(const struct osmo_ss7_link *link)
+{
+ /* TODO: manage operational availability of a link... */
+ return link->cfg.adm_state == OSMO_SS7_LS_ENABLED;
+}
diff --git a/src/osmo_ss7_linkset.c b/src/osmo_ss7_linkset.c
index 5b4b316..8f63505 100644
--- a/src/osmo_ss7_linkset.c
+++ b/src/osmo_ss7_linkset.c
@@ -101,3 +101,14 @@
return lset;
}
+
+bool
+ss7_linkset_is_available(const struct osmo_ss7_linkset *lset)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(lset->links); i++) {
+ struct osmo_ss7_link *link = lset->links[i];
+ if (link && ss7_link_is_available(link))
+ return true;
+ }
+ return false;
+}
diff --git a/src/osmo_ss7_route.c b/src/osmo_ss7_route.c
index 9683dd3..194d5dd 100644
--- a/src/osmo_ss7_route.c
+++ b/src/osmo_ss7_route.c
@@ -306,12 +306,9 @@
bool ss7_route_is_available(const struct osmo_ss7_route *rt)
{
OSMO_ASSERT(rt);
- if (rt->dest.as) {
- if (osmo_ss7_as_active(rt->dest.as))
- return true;
-
- } else {
- /* TODO: linkset */
- }
+ if (rt->dest.as)
+ return osmo_ss7_as_active(rt->dest.as);
+ if (rt->dest.linkset)
+ return ss7_linkset_is_available(rt->dest.linkset);
return false;
}
diff --git a/src/ss7_combined_linkset.h b/src/ss7_combined_linkset.h
index e2f9c9d..b80a007 100644
--- a/src/ss7_combined_linkset.h
+++ b/src/ss7_combined_linkset.h
@@ -33,6 +33,7 @@
/*! list of \ref osmo_ss7_route */
struct llist_head routes;
unsigned int num_routes;
+ void *last_route_roundrobin;
struct {
uint32_t pc;
diff --git a/src/ss7_link.h b/src/ss7_link.h
index 5ea6556..b0014c6 100644
--- a/src/ss7_link.h
+++ b/src/ss7_link.h
@@ -31,3 +31,5 @@
void ss7_link_destroy(struct osmo_ss7_link *link);
struct osmo_ss7_link *
ss7_link_find_or_create(struct osmo_ss7_linkset *lset, uint32_t id);
+bool
+ss7_link_is_available(const struct osmo_ss7_link *link);
diff --git a/src/ss7_linkset.h b/src/ss7_linkset.h
index daa442f..beb60a1 100644
--- a/src/ss7_linkset.h
+++ b/src/ss7_linkset.h
@@ -30,3 +30,6 @@
ss7_linkset_find_by_name(struct osmo_ss7_instance *inst, const char *name);
struct osmo_ss7_linkset *
ss7_linkset_find_or_create(struct osmo_ss7_instance *inst, const char *name, uint32_t
pc);
+
+bool
+ss7_linkset_is_available(const struct osmo_ss7_linkset *lset);
diff --git a/tests/ss7/ss7_test.c b/tests/ss7/ss7_test.c
index 95fa1b1..f61ee0a 100644
--- a/tests/ss7/ss7_test.c
+++ b/tests/ss7/ss7_test.c
@@ -154,6 +154,7 @@
{
struct osmo_ss7_route_table *rtbl;
struct osmo_ss7_linkset *lset_a, *lset_b;
+ struct osmo_ss7_link *l_a, *l_b;
struct osmo_ss7_route *rt, *rt12, *rtdef;
struct osmo_ss7_route_label route_label;
@@ -173,8 +174,15 @@
lset_a = ss7_linkset_find_or_create(s7i, "a", 100);
OSMO_ASSERT(lset_a);
+ l_a = ss7_link_find_or_create(lset_a, 0);
+ OSMO_ASSERT(l_a);
+ l_a->cfg.adm_state = OSMO_SS7_LS_ENABLED;
+
lset_b = ss7_linkset_find_or_create(s7i, "b", 200);
OSMO_ASSERT(lset_b);
+ l_b = ss7_link_find_or_create(lset_b, 0);
+ OSMO_ASSERT(l_b);
+ l_b->cfg.adm_state = OSMO_SS7_LS_ENABLED;
/* route with full mask */
route_label = RT_LABEL(0, 12, 0);
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-sigtran/+/39391?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: I928fb1ef5db6922f1386a188e3fbf9e70780f25d
Gerrit-Change-Number: 39391
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>