pespin has uploaded this change for review.

View Change

WIP: Introduce combined_linkset

A "Combined linkset" is a set of routes for different AS or linksets
whose destination (DPC & mask) and priority are the same.

An SP is expected to load share traffic among linksets/AS of a given
combined linkset, based on DPC/OPC,SLS. This means certain state or
heuristics need to be stored in the combined linkset in order to keep
forwarding messages of the same transaction (SLS) over the same specific
AS/linkset.

This commit introduces the osmo_ss7_combined_linkset object, which
is roughly a set of osmo_ss7_routei sharing DPC+MASK+PRIO key, and
it is places in between the osmo_ss7_route_table and osmo_ss7_route
entries.
User still operates/manages indiviual routes, but those are grouped
internally inside its corresponding combined linkset.

No routing change is implemented in this commit. Code is only tweaked
minimally so far to retrieve the first route in the combined link.
This will allow future work, i.e to:
- Check if data can be sent over the combined link (at least one
AS/linkset is ACTIVE), and otherwise try using a combined link with a
less specific match (shorter prefix mask or/and lower priority).
- Select one of the AS/linksets insert the combined link, based on
OPC/DPC/SLS of the message.

Change-Id: I500ec74ba975e3c93071771027e4e5fe6000e6f3
---
M src/Makefile.am
A src/osmo_ss7_combined_linkset.c
M src/osmo_ss7_linkset.c
M src/osmo_ss7_route.c
M src/osmo_ss7_route_table.c
M src/osmo_ss7_vty.c
A src/ss7_combined_linkset.h
M src/ss7_route.h
M src/ss7_route_table.h
9 files changed, 332 insertions(+), 84 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/31/38731/1
diff --git a/src/Makefile.am b/src/Makefile.am
index dc35ecc..1f316b0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,6 +7,7 @@
ss7_as.h \
ss7_asp.h \
ss7_asp_peer.h \
+ ss7_combined_linkset.h \
ss7_instance.h \
ss7_internal.h \
ss7_link.h \
@@ -44,6 +45,7 @@
osmo_ss7_as.c \
osmo_ss7_asp.c \
osmo_ss7_asp_peer.c \
+ osmo_ss7_combined_linkset.c \
osmo_ss7_hmrt.c \
osmo_ss7_instance.c \
osmo_ss7_link.c \
diff --git a/src/osmo_ss7_combined_linkset.c b/src/osmo_ss7_combined_linkset.c
new file mode 100644
index 0000000..f7499b5
--- /dev/null
+++ b/src/osmo_ss7_combined_linkset.c
@@ -0,0 +1,119 @@
+ /* (C) 2024 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <errno.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/sigtran/osmo_ss7.h>
+
+#include "ss7_combined_linkset.h"
+#include "ss7_route.h"
+#include "ss7_route_table.h"
+#include "ss7_internal.h"
+
+/***********************************************************************
+ * SS7 Combined Linkset
+ ***********************************************************************/
+
+/*! \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
+ *
+ * A combined link is only really used once it has been inserted into its routing table.
+ *
+ * insert the route in the ordered list of routes. The list is sorted by
+ * mask length, so that the more specific (longer mask) routes are
+ * first, while the less specific routes with shorter masks are last.
+ * Within the same mask length, the routes are ordered by priority.
+ * Hence, the first matching route in a linear iteration is the most
+ * specific match.
+ */
+static void ss7_combined_link_insert(struct osmo_ss7_combined_linkset *clset)
+{
+ struct osmo_ss7_route_table *rtbl = clset->rtable;
+ struct osmo_ss7_route *it;
+
+ llist_for_each_entry(it, &rtbl->combined_linksets, list) {
+ if (it->cfg.mask == clset->cfg.mask &&
+ it->cfg.priority > clset->cfg.priority) {
+ /* insert before the current entry */
+ llist_add(&clset->list, it->list.prev);
+ return;
+ }
+ if (it->cfg.mask < clset->cfg.mask) {
+ /* insert before the current entry */
+ llist_add(&clset->list, it->list.prev);
+ return;
+ }
+ }
+ /* not added, i.e. no smaller mask length and priority found: we are the
+ * smallest mask and priority and thus should go last */
+ llist_add_tail(&clset->list, &rtbl->combined_linksets);
+}
+
+struct osmo_ss7_combined_linkset *
+ss7_combined_linkset_alloc(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio)
+{
+ struct osmo_ss7_combined_linkset *clset;
+
+ clset = talloc_zero(rtbl, struct osmo_ss7_combined_linkset);
+ if (!clset)
+ return NULL;
+
+ clset->rtable = rtbl;
+ /* truncate mask to maximum. Let's avoid callers specifying arbitrary large
+ * masks to ensure we don't fail duplicate detection with longer mask lengths */
+ clset->cfg.mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask);
+ clset->cfg.pc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, pc);
+ clset->cfg.priority = prio;
+ INIT_LLIST_HEAD(&clset->routes);
+
+ ss7_combined_link_insert(clset);
+ return clset;
+}
+
+void
+ss7_combined_linkset_free(struct osmo_ss7_combined_linkset *clset)
+{
+ if (!clset)
+ return;
+ llist_del(&clset->list);
+ talloc_free(clset);
+}
+
+void ss7_combined_link_add_route(struct osmo_ss7_combined_linkset *clset, struct osmo_ss7_route *rt)
+{
+ llist_add_tail(&rt->list, &clset->routes);
+ clset->num_routes++;
+ rt->clset = clset;
+}
+
+/* clset may end up freed as a result: */
+void ss7_combined_link_del_route(struct osmo_ss7_route *rt)
+{
+ struct osmo_ss7_combined_linkset *clset = rt->clset;
+ llist_del(&rt->list);
+ rt->clset = NULL;
+ clset->num_routes--;
+ if (clset->num_routes == 0)
+ ss7_combined_linkset_free(clset);
+}
diff --git a/src/osmo_ss7_linkset.c b/src/osmo_ss7_linkset.c
index 146ec92..5b4b316 100644
--- a/src/osmo_ss7_linkset.c
+++ b/src/osmo_ss7_linkset.c
@@ -25,6 +25,7 @@
#include <osmocom/core/logging.h>
#include <osmocom/sigtran/osmo_ss7.h>

+#include "ss7_combined_linkset.h"
#include "ss7_link.h"
#include "ss7_linkset.h"
#include "ss7_route.h"
diff --git a/src/osmo_ss7_route.c b/src/osmo_ss7_route.c
index 1afc75c..20097ce 100644
--- a/src/osmo_ss7_route.c
+++ b/src/osmo_ss7_route.c
@@ -26,6 +26,7 @@
#include <osmocom/sigtran/mtp_sap.h>
#include <osmocom/sigtran/osmo_ss7.h>

+#include "ss7_combined_linkset.h"
#include "ss7_linkset.h"
#include "ss7_as.h"
#include "ss7_route.h"
@@ -131,34 +132,6 @@
return 0;
}

-/* insert the route in the ordered list of routes. The list is sorted by
- * mask length, so that the more specific (longer mask) routes are
- * first, while the less specific routes with shorter masks are last.
- * Within the same mask length, the routes are ordered by priority.
- * Hence, the first matching route in a linear iteration is the most
- * specific match. */
-static void route_insert_sorted(struct osmo_ss7_route_table *rtbl,
- struct osmo_ss7_route *cmp)
-{
- struct osmo_ss7_route *rt;
-
- llist_for_each_entry(rt, &rtbl->routes, list) {
- if (rt->cfg.mask == cmp->cfg.mask &&
- rt->cfg.priority > cmp->cfg.priority) {
- /* insert before the current entry */
- llist_add(&cmp->list, rt->list.prev);
- return;
- }
- if (rt->cfg.mask < cmp->cfg.mask) {
- /* insert before the current entry */
- llist_add(&cmp->list, rt->list.prev);
- return;
- }
- }
- /* not added, i.e. no smaller mask length and priority found: we are the
- * smallest mask and priority and thus should go last */
- llist_add_tail(&cmp->list, &rtbl->routes);
-}

/*! \brief Insert route into its routing table
* \param[in] rt Route to be inserted into its routing table
@@ -169,7 +142,7 @@
int
ss7_route_insert(struct osmo_ss7_route *rt)
{
- struct osmo_ss7_route *prev_rt;
+ struct osmo_ss7_combined_linkset *clset;
struct osmo_ss7_route_table *rtbl = rt->rtable;

if (ss7_route_inserted(rt)) {
@@ -182,17 +155,24 @@
return -EINVAL;
}

- /* check for duplicates */
- prev_rt = ss7_route_table_find_route_by_dpc_mask(rtbl, rt->cfg.pc, rt->cfg.mask);
- if (prev_rt && !strcmp(prev_rt->cfg.linkset_name, rt->cfg.linkset_name)) {
- LOGSS7(rtbl->inst, LOGL_ERROR,
- "Refusing to create route with existing linkset name: pc=%u=%s mask=0x%x via linkset/AS '%s'\n",
- rt->cfg.pc, osmo_ss7_pointcode_print(rtbl->inst, rt->cfg.pc),
- rt->cfg.mask, rt->cfg.linkset_name);
- return -EADDRINUSE;
+ clset = ss7_route_table_find_combined_linkset(rtbl, rt->cfg.pc, rt->cfg.mask, rt->cfg.priority);
+ if (clset) { /* check for duplicates */
+ struct osmo_ss7_route *prev_rt;
+ llist_for_each_entry(prev_rt, &clset->routes, list) {
+ if (!strcmp(prev_rt->cfg.linkset_name, rt->cfg.linkset_name)) {
+ LOGSS7(rtbl->inst, LOGL_ERROR,
+ "Refusing to create route with existing linkset name: pc=%u=%s mask=0x%x via linkset/AS '%s'\n",
+ rt->cfg.pc, osmo_ss7_pointcode_print(rtbl->inst, rt->cfg.pc),
+ rt->cfg.mask, rt->cfg.linkset_name);
+ return -EADDRINUSE;
+ }
+ }
+ } else {
+ clset = ss7_combined_linkset_alloc(rtbl, rt->cfg.pc, rt->cfg.mask, rt->cfg.priority);
+ OSMO_ASSERT(clset);
}

- route_insert_sorted(rtbl, rt);
+ ss7_combined_link_add_route(clset, rt);
return 0;
}

@@ -249,7 +229,7 @@
"Destroying route: pc=%u=%s mask=0x%x via linkset/ASP '%s'\n",
rt->cfg.pc, osmo_ss7_pointcode_print(inst, rt->cfg.pc),
rt->cfg.mask, rt->cfg.linkset_name);
- llist_del(&rt->list);
+ ss7_combined_link_del_route(rt);
}
talloc_free(rt);
}
diff --git a/src/osmo_ss7_route_table.c b/src/osmo_ss7_route_table.c
index 03596d0..b230521 100644
--- a/src/osmo_ss7_route_table.c
+++ b/src/osmo_ss7_route_table.c
@@ -24,6 +24,7 @@
#include <osmocom/sigtran/mtp_sap.h>
#include <osmocom/sigtran/osmo_ss7.h>

+#include "ss7_combined_linkset.h"
#include "ss7_route.h"
#include "ss7_route_table.h"
#include "ss7_internal.h"
@@ -44,7 +45,7 @@

rtbl->inst = inst;
rtbl->cfg.name = talloc_strdup(rtbl, name);
- INIT_LLIST_HEAD(&rtbl->routes);
+ INIT_LLIST_HEAD(&rtbl->combined_linksets);
llist_add_tail(&rtbl->list, &inst->rtable_list);
return rtbl;
}
@@ -77,8 +78,8 @@
ss7_route_table_destroy(struct osmo_ss7_route_table *rtbl)
{
llist_del(&rtbl->list);
- /* routes are allocated as children of route table, will be
- * automatically freed() */
+ /* combined links & routes are allocated as children of route table,
+ * will be automatically freed() */
talloc_free(rtbl);
}

@@ -86,20 +87,18 @@
struct osmo_ss7_route *
ss7_route_table_find_route_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc)
{
+ struct osmo_ss7_combined_linkset *clset;
struct osmo_ss7_route *rt;

OSMO_ASSERT(ss7_initialized);

dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc);

- /* we assume the routes are sorted by mask length, i.e. more
- * specific routes first, and less specific routes with shorter
- * mask later */
- llist_for_each_entry(rt, &rtbl->routes, list) {
- if ((dpc & rt->cfg.mask) == rt->cfg.pc)
- return rt;
- }
- return NULL;
+ clset = ss7_route_table_find_combined_linkset_by_dpc(rtbl, dpc);
+ if (!clset)
+ return NULL;
+ rt = llist_first_entry_or_null(&clset->routes, struct osmo_ss7_route, list);
+ return rt;
}

/*! \brief Find a SS7 route for given destination point code + mask in given table */
@@ -107,40 +106,124 @@
ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc,
uint32_t mask)
{
+ struct osmo_ss7_combined_linkset *clset;
struct osmo_ss7_route *rt;

OSMO_ASSERT(ss7_initialized);
- mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask);
- dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc);

- /* we assume the routes are sorted by mask length, i.e. more
- * specific routes first, and less specific routes with shorter
+ dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc);
+ mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask);
+
+ clset = ss7_route_table_find_combined_linkset_by_dpc_mask(rtbl, dpc, mask);
+ if (!clset)
+ return NULL;
+ rt = llist_first_entry_or_null(&clset->routes, struct osmo_ss7_route, list);
+ return rt;
+}
+
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_combined_linkset_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc)
+{
+ struct osmo_ss7_combined_linkset *clset;
+
+ OSMO_ASSERT(ss7_initialized);
+
+ dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc);
+ /* we assume the combined_links are sorted by mask length, i.e. more
+ * specific combined links first, and less specific combined links with shorter
* mask later */
- llist_for_each_entry(rt, &rtbl->routes, list) {
- if (dpc == rt->cfg.pc && mask == rt->cfg.mask)
- return rt;
+ llist_for_each_entry(clset, &rtbl->combined_linksets, list) {
+ if ((dpc & clset->cfg.mask) != clset->cfg.pc)
+ continue;
+ return clset;
}
return NULL;
}

-/* find any routes pointing to this linkset and remove them */
-void ss7_route_table_del_routes_by_linkset(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_linkset *lset)
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_combined_linkset_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask)
{
- struct osmo_ss7_route *rt, *rt2;
+ struct osmo_ss7_combined_linkset *clset;

- llist_for_each_entry_safe(rt, rt2, &rtbl->routes, list) {
- if (rt->dest.linkset == lset)
- ss7_route_destroy(rt);
+ OSMO_ASSERT(ss7_initialized);
+
+ dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc);
+ /* we assume the combined_links are sorted by mask length, i.e. more
+ * specific combined links first, and less specific combined links with shorter
+ * mask later */
+ llist_for_each_entry(clset, &rtbl->combined_linksets, list) {
+ if ((dpc & clset->cfg.mask) != clset->cfg.pc)
+ continue;
+ if (mask != clset->cfg.mask)
+ continue;
+ return clset;
}
+ return NULL;
+}
+
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask, uint32_t prio)
+{
+ struct osmo_ss7_combined_linkset *clset;
+
+ /* we assume the combined_links are sorted by mask length, i.e. more
+ * specific routes first, and less specific routes with shorter
+ * mask later */
+ llist_for_each_entry(clset, &rtbl->combined_linksets, list) {
+ if (mask < clset->cfg.mask)
+ break;
+ if (dpc == clset->cfg.pc && mask == clset->cfg.mask) {
+ if (prio > clset->cfg.priority)
+ break;
+ if (prio == clset->cfg.priority)
+ return clset;
+ }
+ }
+ return NULL;
+}
+
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_or_create_combined_linkset(struct osmo_ss7_route_table *rtable, uint32_t pc, uint32_t mask, uint32_t prio)
+{
+ struct osmo_ss7_combined_linkset *clset;
+ clset = ss7_route_table_find_combined_linkset(rtable, pc, mask, prio);
+ if (!clset)
+ clset = ss7_combined_linkset_alloc(rtable, pc, mask, prio);
+ return clset;
}

/* find any routes pointing to this AS and remove them */
void ss7_route_table_del_routes_by_as(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_as *as)
{
- struct osmo_ss7_route *rt, *rt2;
+ struct osmo_ss7_combined_linkset *clset, *clset2;

- llist_for_each_entry_safe(rt, rt2, &rtbl->routes, list) {
- if (rt->dest.as == as)
- ss7_route_destroy(rt);
+ llist_for_each_entry_safe(clset, clset2, &rtbl->combined_linksets, list) {
+ struct osmo_ss7_route *rt;
+ llist_for_each_entry(rt, &clset->routes, list) {
+ if (rt->dest.as == as) {
+ ss7_route_destroy(rt);
+ /* clset may have been freed here. Same AS can't be twice in a combined
+ * linkset, so simply continue iterating in the upper loop. */
+ break;
+ }
+ }
+ }
+}
+
+/* find any routes pointing to this linkset and remove them */
+void ss7_route_table_del_routes_by_linkset(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_linkset *lset)
+{
+ struct osmo_ss7_combined_linkset *clset, *clset2;
+
+ llist_for_each_entry_safe(clset, clset2, &rtbl->combined_linksets, list) {
+ struct osmo_ss7_route *rt;
+ llist_for_each_entry(rt, &clset->routes, list) {
+ if (rt->dest.linkset == lset) {
+ ss7_route_destroy(rt);
+ /* clset may have been freed here. Same linkset can't be twice in a combined
+ * linkset, so simply continue iterating in the upper loop. */
+ break;
+ }
+ }
}
}
diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c
index 6b404b3..547b420 100644
--- a/src/osmo_ss7_vty.c
+++ b/src/osmo_ss7_vty.c
@@ -48,6 +48,7 @@
#include "sccp_internal.h"
#include "ss7_as.h"
#include "ss7_asp.h"
+#include "ss7_combined_linkset.h"
#include "ss7_route.h"
#include "ss7_route_table.h"
#include "ss7_internal.h"
@@ -487,26 +488,30 @@

static void write_one_rtable(struct vty *vty, struct osmo_ss7_route_table *rtable)
{
+ struct osmo_ss7_combined_linkset *clset;
struct osmo_ss7_route *rt;

vty_out(vty, " route-table %s%s", rtable->cfg.name, VTY_NEWLINE);
if (rtable->cfg.description)
vty_out(vty, " description %s%s", rtable->cfg.description, VTY_NEWLINE);
- llist_for_each_entry(rt, &rtable->routes, list) {
- vty_out(vty, " update route %s %s linkset %s",
- osmo_ss7_pointcode_print(rtable->inst, rt->cfg.pc),
- osmo_ss7_pointcode_print2(rtable->inst, rt->cfg.mask),
- rt->cfg.linkset_name);
- if (rt->cfg.priority != OSMO_SS7_ROUTE_PRIO_DEFAULT)
- vty_out(vty, " priority %u", rt->cfg.priority);
- if (rt->cfg.qos_class)
- vty_out(vty, " qos-class %u", rt->cfg.qos_class);
- vty_out(vty, "%s", VTY_NEWLINE);
+ llist_for_each_entry(clset, &rtable->combined_linksets, list) {
+ llist_for_each_entry(rt, &clset->routes, list) {
+ vty_out(vty, " update route %s %s linkset %s",
+ osmo_ss7_pointcode_print(rtable->inst, rt->cfg.pc),
+ osmo_ss7_pointcode_print2(rtable->inst, rt->cfg.mask),
+ rt->cfg.linkset_name);
+ if (rt->cfg.priority != OSMO_SS7_ROUTE_PRIO_DEFAULT)
+ vty_out(vty, " priority %u", rt->cfg.priority);
+ if (rt->cfg.qos_class)
+ vty_out(vty, " qos-class %u", rt->cfg.qos_class);
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
}
}

static void vty_dump_rtable(struct vty *vty, struct osmo_ss7_route_table *rtbl)
{
+ struct osmo_ss7_combined_linkset *clset;
struct osmo_ss7_route *rt;

vty_out(vty, "Routing table = %s%s", rtbl->cfg.name, VTY_NEWLINE);
@@ -515,10 +520,12 @@
vty_out(vty, "Destination C Q P Linkset Name Linkset Non-adj Route%s", VTY_NEWLINE);
vty_out(vty, "---------------------- - - - ------------------- ------- ------- -------%s", VTY_NEWLINE);

- llist_for_each_entry(rt, &rtbl->routes, list) {
- vty_out(vty, "%-22s %c %c %u %-19s %-7s %-7s %-7s%s",
- osmo_ss7_route_print(rt),
- ' ', ' ', rt->cfg.priority, rt->cfg.linkset_name, "?", "?", "?", VTY_NEWLINE);
+ llist_for_each_entry(clset, &rtbl->combined_linksets, list) {
+ llist_for_each_entry(rt, &clset->routes, list) {
+ vty_out(vty, "%-22s %c %c %u %-19s %-7s %-7s %-7s%s",
+ osmo_ss7_route_print(rt),
+ ' ', ' ', rt->cfg.priority, rt->cfg.linkset_name, "?", "?", "?", VTY_NEWLINE);
+ }
}
}

diff --git a/src/ss7_combined_linkset.h b/src/ss7_combined_linkset.h
new file mode 100644
index 0000000..c353f03
--- /dev/null
+++ b/src/ss7_combined_linkset.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+
+/***********************************************************************
+ * SS7 Combined Linksets
+ * Set of routes with same destination and priority.
+ ***********************************************************************/
+
+struct osmo_ss7_instance;
+struct osmo_ss7_link;
+
+struct osmo_ss7_combined_linkset {
+ /*! member in \ref osmo_ss7_route_table.combined_linksets */
+ struct llist_head list;
+
+ /*! \ref osmo_ss7_route_table to which we belong */
+ struct osmo_ss7_route_table *rtable;
+
+ /*! list of \ref osmo_ss7_route */
+ struct llist_head routes;
+ unsigned int num_routes;
+
+ struct {
+ uint32_t pc;
+ uint32_t mask;
+ /*! lower priority is higher */
+ uint32_t priority;
+ } cfg;
+};
+
+struct osmo_ss7_combined_linkset *
+ss7_combined_linkset_alloc(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio);
+void
+ss7_combined_linkset_free(struct osmo_ss7_combined_linkset *clset);
+struct osmo_ss7_linkset *
+ss7_combined_linkset_find_or_create(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio);
+
+void
+ss7_combined_link_add_route(struct osmo_ss7_combined_linkset *clset, struct osmo_ss7_route *rt);
+void
+ss7_combined_link_del_route(struct osmo_ss7_route *rt);
diff --git a/src/ss7_route.h b/src/ss7_route.h
index 7a29b7b..2fd0be3 100644
--- a/src/ss7_route.h
+++ b/src/ss7_route.h
@@ -15,10 +15,12 @@
#define OSMO_SS7_ROUTE_PRIO_DEFAULT 5

struct osmo_ss7_route {
- /*! member in \ref osmo_ss7_route_table.routes */
+ /*! member in \ref osmo_ss7_combined_linkset.routes */
struct llist_head list;
/*! \ref osmo_ss7_route_table to which we belong */
struct osmo_ss7_route_table *rtable;
+ /* Combined linkset this route is part of */
+ struct osmo_ss7_combined_linkset *clset;

struct {
/*! pointer to linkset (destination) of route */
diff --git a/src/ss7_route_table.h b/src/ss7_route_table.h
index 38cff31..c88c742 100644
--- a/src/ss7_route_table.h
+++ b/src/ss7_route_table.h
@@ -14,8 +14,8 @@
struct llist_head list;
/*! \ref osmo_ss7_instance to which we belong */
struct osmo_ss7_instance *inst;
- /*! list of \ref osmo_ss7_route */
- struct llist_head routes;
+ /*! list of \ref osmo_ss7_combined_linksets*/
+ struct llist_head combined_linksets;

struct {
char *name;
@@ -35,5 +35,16 @@
ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc,
uint32_t mask);

+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask, uint32_t prio);
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_or_create_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio);
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_combined_linkset_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc);
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_combined_linkset_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask);
+struct osmo_ss7_combined_linkset *
+ss7_route_table_find_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask, uint32_t prio);
+
void ss7_route_table_del_routes_by_as(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_as *as);
void ss7_route_table_del_routes_by_linkset(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_linkset *lset);

To view, visit change 38731. To unsubscribe, or for help writing mail filters, visit settings.

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