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

Change subject: AS loadsharing: Initial routing implementation based on 
extended-SLS
......................................................................

AS loadsharing: Initial routing implementation based on extended-SLS

This commit adds a new set of APIs and structs to support routing based
on OPC,DPC,SLS fields and hence to support AS-loadshare.

The routing decision is still actually left as beforehand, ie. the first
AS/linkset in the combined_linkset is selected.

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 in the combined link based on a
      round robin approach.

Related: SYS#7112
Change-Id: I0fb4ca4959096f748a23082efa0481300de56436
---
M include/osmocom/sigtran/osmo_ss7.h
M src/osmo_ss7_combined_linkset.c
M src/osmo_ss7_hmrt.c
M src/osmo_ss7_instance.c
M src/osmo_ss7_route.c
M src/osmo_ss7_route_table.c
M src/osmo_ss7_vty.c
M src/sccp_scrc.c
M src/ss7_combined_linkset.h
M src/ss7_instance.h
M src/ss7_route_table.h
M src/xua_rkm.c
M src/xua_snm.c
M tests/ss7/ss7_test.c
M tests/vty/osmo_stp_test.vty
15 files changed, 293 insertions(+), 48 deletions(-)

Approvals:
  Jenkins Builder: Verified
  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




diff --git a/include/osmocom/sigtran/osmo_ss7.h 
b/include/osmocom/sigtran/osmo_ss7.h
index 66cbfe6..264507b 100644
--- a/include/osmocom/sigtran/osmo_ss7.h
+++ b/include/osmocom/sigtran/osmo_ss7.h
@@ -125,7 +125,8 @@
 struct osmo_ss7_route;

 struct osmo_ss7_route *
-osmo_ss7_route_lookup(struct osmo_ss7_instance *inst, uint32_t dpc);
+osmo_ss7_route_lookup(struct osmo_ss7_instance *inst, uint32_t dpc)
+       OSMO_DEPRECATED("Use internal ss7_instance_lookup_route() instead");
 const char *osmo_ss7_route_print(const struct osmo_ss7_route *rt);
 const char *osmo_ss7_route_name(struct osmo_ss7_route *rt, bool list_asps);
 struct osmo_ss7_as *
diff --git a/src/osmo_ss7_combined_linkset.c b/src/osmo_ss7_combined_linkset.c
index 2e068b4..90a54f6 100644
--- a/src/osmo_ss7_combined_linkset.c
+++ b/src/osmo_ss7_combined_linkset.c
@@ -126,9 +126,86 @@
 void ss7_combined_linkset_del_route(struct osmo_ss7_route *rt)
 {
        struct osmo_ss7_combined_linkset *clset = rt->clset;
+
+       /* Remove route from eSLS table: */
+       for (unsigned int i = 0; i < ARRAY_SIZE(clset->esls_table); i++) {
+               if (clset->esls_table[i].normal_rt == rt)
+                       clset->esls_table[i].normal_rt = NULL;
+               if (clset->esls_table[i].alt_rt == rt)
+                       clset->esls_table[i].alt_rt = NULL;
+       }
+
        llist_del(&rt->list);
        rt->clset = NULL;
        clset->num_routes--;
        if (clset->num_routes == 0)
                ss7_combined_linkset_free(clset);
 }
+
+static ext_sls_t osmo_ss7_instance_calc_itu_ext_sls(const struct 
osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlabel)
+{
+       /* Take 6 bits from OPC and DPC according to config: */
+       uint8_t opc6 = (uint8_t)((rtlabel->opc >> inst->cfg.opc_shift) & 0x3f);
+       uint8_t dpc6 = (uint8_t)((rtlabel->dpc >> inst->cfg.dpc_shift) & 0x3f);
+
+       /* Derivate 3-bit value from OPC and DPC: */
+       uint8_t opc3 = ((opc6 >> 3) ^ (opc6 & 0x07)) & 0x07;
+       uint8_t dpc3 = ((dpc6 >> 3) ^ (dpc6 & 0x07)) & 0x07;
+       uint8_t opc_dpc3 = (opc3 ^ dpc3) & 0x07;
+
+       /* Generate 7 bit extended-SLS: 3-bit OPC-DPC + 4 bit SLS: */
+       uint8_t ext_sls = (opc_dpc3 << 4) | ((rtlabel->sls) & 0x0f);
+       OSMO_ASSERT(ext_sls < NUM_EXT_SLS);
+
+       /* Pick extended-SLS bits according to config: */
+       ext_sls = ext_sls >> inst->cfg.sls_shift;
+       return ext_sls;
+}
+
+/* ITU Q.704 4.2.1: "current link set (combined link set)". Pick available 
already selected route */
+struct osmo_ss7_route *current_rt(const struct osmo_ss7_esls_entry *eslse)
+{
+       if (eslse->normal_rt && ss7_route_is_available(eslse->normal_rt))
+               return eslse->normal_rt;
+       if (eslse->alt_rt && ss7_route_is_available(eslse->alt_rt))
+               return eslse->alt_rt;
+       return NULL;
+}
+
+struct osmo_ss7_route *
+ss7_combined_linkset_lookup_route(struct osmo_ss7_combined_linkset *clset, 
const struct osmo_ss7_route_label *rtlabel)
+{
+       struct osmo_ss7_route *rt;
+       ext_sls_t esls = 
osmo_ss7_instance_calc_itu_ext_sls(clset->rtable->inst, rtlabel);
+       struct osmo_ss7_esls_entry *eslse = &clset->esls_table[esls];
+
+       /* First check if we have a cached route for this ESLS */
+       rt = current_rt(eslse);
+       if (rt) {
+               if (rt == eslse->normal_rt) {
+                       /* We can transmit over normal route.
+                        * Clean up alternative route since it's not needed 
anymore */
+                       eslse->alt_rt = NULL;
+                       return rt;
+               }
+               /* We can transmit over alternative route: */
+               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. */
+
+       /* 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);
+
+       /* 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... */
+       if (rt)
+               clset->esls_table[esls].normal_rt = rt;
+
+       return rt;
+}
diff --git a/src/osmo_ss7_hmrt.c b/src/osmo_ss7_hmrt.c
index 118acab..1e000b4 100644
--- a/src/osmo_ss7_hmrt.c
+++ b/src/osmo_ss7_hmrt.c
@@ -153,11 +153,16 @@
                                    struct xua_msg *xua)
 {
        uint32_t dpc = xua->mtp.dpc;
+       struct osmo_ss7_route_label rtlabel = {
+               .opc = xua->mtp.opc,
+               .dpc = xua->mtp.dpc,
+               .sls = xua->mtp.sls,
+       };
        struct osmo_ss7_route *rt;

-       /* find route for DPC */
+       /* find route for OPC+DPC+SLS: */
        /* FIXME: unify with gen_mtp_transfer_req_xua() */
-       rt = osmo_ss7_route_lookup(inst, dpc);
+       rt = ss7_instance_lookup_route(inst, &rtlabel);
        if (rt) {
                /* FIXME: DPC SP restart? */
                /* FIXME: DPC Congested? */
diff --git a/src/osmo_ss7_instance.c b/src/osmo_ss7_instance.c
index f7d9a41..527cf2a 100644
--- a/src/osmo_ss7_instance.c
+++ b/src/osmo_ss7_instance.c
@@ -202,6 +202,15 @@
        return -1;
 }

+/*! \brief Find a SS7 route for given destination point code in given SS7 */
+struct osmo_ss7_route *
+ss7_instance_lookup_route(struct osmo_ss7_instance *inst, const struct 
osmo_ss7_route_label *rtlabel)
+{
+       OSMO_ASSERT(ss7_initialized);
+       return ss7_route_table_lookup_route(inst->rtable_system, rtlabel);
+}
+
+
 /***********************************************************************
  * SS7 Application Server
  ***********************************************************************/
diff --git a/src/osmo_ss7_route.c b/src/osmo_ss7_route.c
index f1fe150..f75e32a 100644
--- a/src/osmo_ss7_route.c
+++ b/src/osmo_ss7_route.c
@@ -335,12 +335,21 @@
        return buf;
 }

-/*! \brief Find a SS7 route for given destination point code in given SS7 */
+/*! \brief Find a SS7 route for given destination point code in given SS7
+ *
+ *   NOTE: DEPRECATED, use ss7_instance_lookup_route() instead
+ */
 struct osmo_ss7_route *
 osmo_ss7_route_lookup(struct osmo_ss7_instance *inst, uint32_t dpc)
 {
        OSMO_ASSERT(ss7_initialized);
-       return ss7_route_table_find_route_by_dpc(inst->rtable_system, dpc);
+       struct osmo_ss7_route_label rtlb = {
+               .opc = 0,
+               .dpc = dpc,
+               .sls = 0,
+       };
+
+       return ss7_instance_lookup_route(inst, &rtlb);
 }

 /*! \brief Get destination AS of route
@@ -353,7 +362,6 @@
        return rt->dest.as;
 }

-
 /* Whether route is available, ITU Q.704 */
 bool ss7_route_is_available(const struct osmo_ss7_route *rt)
 {
diff --git a/src/osmo_ss7_route_table.c b/src/osmo_ss7_route_table.c
index b230521..734db88 100644
--- a/src/osmo_ss7_route_table.c
+++ b/src/osmo_ss7_route_table.c
@@ -19,6 +19,8 @@
  *
  */

+ #include <stdio.h>
+
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/logging.h>
 #include <osmocom/sigtran/mtp_sap.h>
@@ -29,6 +31,22 @@
 #include "ss7_route_table.h"
 #include "ss7_internal.h"

+
+/***********************************************************************
+ * SS7 Route Label
+ ***********************************************************************/
+
+char *ss7_route_label_to_str(char *buf, size_t buf_len, const struct 
osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlb)
+{
+       if (buf_len == 0)
+               return NULL;
+       snprintf(buf, buf_len, "OPC=%u=%s,DPC=%u=%s,SLS=%u",
+                rtlb->opc, osmo_ss7_pointcode_print(inst, rtlb->opc),
+                rtlb->dpc, osmo_ss7_pointcode_print2(inst, rtlb->dpc),
+                rtlb->sls);
+       return buf;
+}
+
 /***********************************************************************
  * SS7 Route Tables
  ***********************************************************************/
@@ -83,25 +101,10 @@
        talloc_free(rtbl);
 }

-/*! \brief Find a SS7 route for given destination point code in given table */
-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);
-
-       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 */
+/*! \brief Find a SS7 route for given destination point code + mask in given 
table.
+ *
+ * This function is used for route management procedures, not for packet 
routing lookup procedures!
+ */
 struct osmo_ss7_route *
 ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, 
uint32_t dpc,
                                uint32_t mask)
@@ -227,3 +230,27 @@
                }
        }
 }
+
+struct osmo_ss7_route *
+ss7_route_table_lookup_route(struct osmo_ss7_route_table *rtbl, const struct 
osmo_ss7_route_label *rtlabel)
+{
+       struct osmo_ss7_combined_linkset *clset;
+       struct osmo_ss7_route *rt;
+       struct osmo_ss7_route_label rtlb = {
+               .opc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, 
rtlabel->opc),
+               .dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, 
rtlabel->dpc),
+               .sls = rtlabel->sls,
+       };
+       /* 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 ((rtlb.dpc & clset->cfg.mask) != clset->cfg.pc)
+                       continue;
+               rt = ss7_combined_linkset_lookup_route(clset, &rtlb);
+               if (!rt)
+                       continue;
+               return rt;
+       }
+       return NULL;
+}
diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c
index 2704742..81ce0ce 100644
--- a/src/osmo_ss7_vty.c
+++ b/src/osmo_ss7_vty.c
@@ -290,6 +290,41 @@
        return CMD_SUCCESS;
 }

+
+DEFUN_ATTR(cs7_opc_dpc_shift, cs7_opc_dpc_shift_cmd,
+          "sls-opc-dpc [opc-shift] [<0-8>] [dpc-shift] [<0-8>]",
+          "Shift OPC and DPC bits used during routing decision\n"
+          "Shift OPC bits used during routing decision\n"
+          "How many bits from ITU OPC field (starting from 
least-significant-bit) to skip (default=0). 6 bits are always used\n"
+          "Shift DPC bits used during routing decision\n"
+          "How many bits from ITU DPC field (starting from 
least-significant-bit) to skip (default=0). 6 bits are always used\n",
+          CMD_ATTR_IMMEDIATE)
+{
+       struct osmo_ss7_instance *inst = vty->index;
+       if (argc == 4)
+               inst->cfg.dpc_shift = atoi(argv[3]);
+       else if (argc == 3)
+               inst->cfg.dpc_shift = 0;
+       if (argc >= 2)
+               inst->cfg.opc_shift = atoi(argv[1]);
+       else if (argc == 1)
+               inst->cfg.opc_shift = 0;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cs7_sls_shift, cs7_sls_shift_cmd,
+          "sls-shift <0-6>",
+          "Shift SLS bits used during routing decision\n"
+          "How many bits from derivated 7-bit extended-SLS (OPC, DPC, SLS) 
field (starting from least-significant-bit) to skip\n",
+          CMD_ATTR_IMMEDIATE)
+{
+       struct osmo_ss7_instance *inst = vty->index;
+       inst->cfg.sls_shift = atoi(argv[0]);
+
+       return CMD_SUCCESS;
+}
+
 static void write_one_cs7(struct vty *vty, struct osmo_ss7_instance *inst, 
bool show_dyn_config);

 static int write_all_cs7(struct vty *vty, bool show_dyn_config)
@@ -584,7 +619,7 @@
        bool list_asps = argc > 4;
        struct osmo_ss7_instance *inst;
        struct osmo_ss7_route *rt;
-       uint32_t dpc;
+       struct osmo_ss7_route_label rtlabel = {};
        int pc;

        inst = osmo_ss7_instance_find(id);
@@ -598,18 +633,22 @@
                vty_out(vty, "Invalid point code (%s)%s", argv[1], VTY_NEWLINE);
                return CMD_WARNING;
        }
-       dpc = pc;
+       rtlabel.dpc = pc;

        pc = osmo_ss7_pointcode_parse(inst, argv[2]);
        if (pc < 0 || !osmo_ss7_pc_is_valid((uint32_t)pc)) {
                vty_out(vty, "Invalid point code (%s)%s", argv[2], VTY_NEWLINE);
                return CMD_WARNING;
        }
+       rtlabel.opc = pc;

-       rt = osmo_ss7_route_lookup(inst, dpc);
+       rtlabel.sls = atoi(argv[3]);
+
+       rt = ss7_instance_lookup_route(inst, &rtlabel);
        if (!rt) {
-               vty_out(vty, "No route found for DPC %s%s",
-                       osmo_ss7_pointcode_print(inst, dpc), VTY_NEWLINE);
+               char buf[256];
+               vty_out(vty, "No route found for label '%s'%s",
+                       ss7_route_label_to_str(buf, sizeof(buf), inst, 
&rtlabel), VTY_NEWLINE);
                return CMD_WARNING;
        }

@@ -2971,6 +3010,13 @@
        if (inst->cfg.permit_dyn_rkm_alloc)
                vty_out(vty, " xua rkm routing-key-allocation 
dynamic-permitted%s", VTY_NEWLINE);

+       if (inst->cfg.opc_shift != 0 || inst->cfg.dpc_shift != 0)
+               vty_out(vty, " sls-opc-dpc opc-shift %u dpc-shift %u%s",
+                       inst->cfg.opc_shift, inst->cfg.dpc_shift, VTY_NEWLINE);
+
+       if (inst->cfg.sls_shift != 0)
+               vty_out(vty, " sls-shift %u%s", inst->cfg.sls_shift, 
VTY_NEWLINE);
+
        /* first dump ASPs, as ASs reference them */
        llist_for_each_entry(asp, &inst->asp_list, list)
                write_one_asp(vty, asp, show_dyn_config);
@@ -3133,6 +3179,8 @@
        install_lib_element(L_CS7_NODE, &cs7_pc_format_def_cmd);
        install_lib_element(L_CS7_NODE, &cs7_pc_delimiter_cmd);
        install_lib_element(L_CS7_NODE, &cs7_permit_dyn_rkm_cmd);
+       install_lib_element(L_CS7_NODE, &cs7_opc_dpc_shift_cmd);
+       install_lib_element(L_CS7_NODE, &cs7_sls_shift_cmd);

        install_node(&asp_node, NULL);
        install_lib_element_ve(&show_cs7_asp_cmd);
diff --git a/src/sccp_scrc.c b/src/sccp_scrc.c
index 23c3f2d..869235c 100644
--- a/src/sccp_scrc.c
+++ b/src/sccp_scrc.c
@@ -37,6 +37,7 @@
 #include "ss7_instance.h"
 #include "ss7_linkset.h"
 #include "ss7_route.h"
+#include "ss7_route_table.h"
 #include "xua_internal.h"


@@ -120,6 +121,7 @@
                                    const struct osmo_sccp_addr *called)
 {
        struct osmo_ss7_route *rt;
+       struct osmo_ss7_route_label rtlabel;

        /* this is a bit fishy due to the different requirements of
         * classic SSCP/MTP compared to various SIGTRAN stackings.
@@ -144,7 +146,13 @@
                return -1;
        }

-       rt = osmo_ss7_route_lookup(inst->ss7, xua->mtp.dpc);
+       rtlabel = (struct osmo_ss7_route_label){
+               .opc = xua->mtp.opc,
+               .dpc = xua->mtp.dpc,
+               .sls = xua->mtp.sls,
+       };
+
+       rt = ss7_instance_lookup_route(inst->ss7, &rtlabel);
        if (!rt) {
                LOGP(DLSCCP, LOGL_ERROR, "MTP-TRANSFER.req from SCCP for "
                        "DPC %u: no route!\n", xua->mtp.dpc);
diff --git a/src/ss7_combined_linkset.h b/src/ss7_combined_linkset.h
index 1c3b684..e2f9c9d 100644
--- a/src/ss7_combined_linkset.h
+++ b/src/ss7_combined_linkset.h
@@ -10,6 +10,17 @@

 struct osmo_ss7_instance;
 struct osmo_ss7_link;
+struct osmo_ss7_route_label;
+
+#define NUM_EXT_SLS 128
+typedef uint8_t ext_sls_t; /* range: 0-127, 7 bit */
+
+struct osmo_ss7_esls_entry {
+       /* ITU Q.704 4.2.1: "normal link set (combined link set)" */
+       struct osmo_ss7_route *normal_rt;
+       /* ITU Q.704 4.2.1: "alternative link set (combined link set)" */
+       struct osmo_ss7_route *alt_rt;
+};

 struct osmo_ss7_combined_linkset {
        /*! member in \ref osmo_ss7_route_table.combined_linksets */
@@ -17,6 +28,7 @@

        /*! \ref osmo_ss7_route_table to which we belong */
        struct osmo_ss7_route_table *rtable;
+       struct osmo_ss7_esls_entry esls_table[NUM_EXT_SLS];

        /*! list of \ref osmo_ss7_route */
        struct llist_head routes;
@@ -41,3 +53,5 @@
 ss7_combined_linkset_add_route(struct osmo_ss7_combined_linkset *clset, struct 
osmo_ss7_route *rt);
 void
 ss7_combined_linkset_del_route(struct osmo_ss7_route *rt);
+struct osmo_ss7_route *
+ss7_combined_linkset_lookup_route(struct osmo_ss7_combined_linkset *clset, 
const struct osmo_ss7_route_label *rtlabel);
diff --git a/src/ss7_instance.h b/src/ss7_instance.h
index d76891f..bb8815b 100644
--- a/src/ss7_instance.h
+++ b/src/ss7_instance.h
@@ -10,6 +10,7 @@

 struct osmo_ss7_user;
 struct osmo_ss7_route_table;
+struct osmo_ss7_route_label;
 struct osmo_sccp_instance;

 struct osmo_ss7_pc_fmt {
@@ -49,6 +50,15 @@
                bool permit_dyn_rkm_alloc;
                struct llist_head sccp_address_book;
                uint32_t secondary_pc;
+               /* How many bits from ITU OPC/DPC field (starting from 
least-significant-bit)
+                * to skip for routing decisions (always takes 6 bits).
+                * range 0-8, defaults to 0, which means take least significant 
6 bits. */
+               uint8_t opc_shift;
+               uint8_t dpc_shift;
+               /* How many bits from ITU SLS field (starting from 
least-significant-bit)
+                * to skip for routing decisions.
+                * range 0-3, defaults to 0, which means take all 4 bits. */
+               uint8_t sls_shift;
        } cfg;
 };

@@ -56,6 +66,8 @@
 ss7_instance_alloc(void *ctx, uint32_t id);

 uint32_t ss7_find_free_l_rk_id(struct osmo_ss7_instance *inst);
+struct osmo_ss7_route *
+ss7_instance_lookup_route(struct osmo_ss7_instance *inst, const struct 
osmo_ss7_route_label *rtlabel);

 #define _LOGSS7(inst, subsys, level, fmt, args ...) \
        LOGP(subsys, level, "%u: " fmt, inst ? (inst)->cfg.id : 0, ## args)
diff --git a/src/ss7_route_table.h b/src/ss7_route_table.h
index c88c742..1de3be5 100644
--- a/src/ss7_route_table.h
+++ b/src/ss7_route_table.h
@@ -1,6 +1,7 @@
 #pragma once

 #include <stdint.h>
+#include <unistd.h>
 #include <osmocom/core/linuxlist.h>

 /***********************************************************************
@@ -9,6 +10,13 @@

 struct osmo_ss7_instance;

+struct osmo_ss7_route_label {
+       uint32_t opc;
+       uint32_t dpc;
+       uint8_t sls;
+};
+char *ss7_route_label_to_str(char *buf, size_t buf_len, const struct 
osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlb);
+
 struct osmo_ss7_route_table {
        /*! member in list of routing tables */
        struct llist_head list;
@@ -30,10 +38,10 @@
 void ss7_route_table_destroy(struct osmo_ss7_route_table *rtbl);

 struct osmo_ss7_route *
-ss7_route_table_find_route_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t 
dpc);
-struct osmo_ss7_route *
 ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, 
uint32_t dpc,
                        uint32_t mask);
+struct osmo_ss7_route *
+ss7_route_table_lookup_route(struct osmo_ss7_route_table *rtbl, const struct 
osmo_ss7_route_label *rtlabel);

 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);
diff --git a/src/xua_rkm.c b/src/xua_rkm.c
index 98f41c5..8fa8c3b 100644
--- a/src/xua_rkm.c
+++ b/src/xua_rkm.c
@@ -393,7 +393,7 @@
                return -1;
        }

-       rt = ss7_route_table_find_route_by_dpc(inst->rtable_system, 
as->cfg.routing_key.pc);
+       rt = ss7_route_table_find_route_by_dpc_mask(inst->rtable_system, 
as->cfg.routing_key.pc, 0xffffff);
        if (!rt) {
                msgb_append_dereg_res(resp, M3UA_RKM_DEREG_ERR_UNKNOWN, 0);
                return -1;
diff --git a/src/xua_snm.c b/src/xua_snm.c
index 971380b..acdfe0c 100644
--- a/src/xua_snm.c
+++ b/src/xua_snm.c
@@ -34,6 +34,7 @@
 #include "ss7_as.h"
 #include "ss7_asp.h"
 #include "ss7_internal.h"
+#include "ss7_route_table.h"
 #include "xua_internal.h"
 #include "sccp_internal.h"

@@ -340,8 +341,14 @@
                if (mask == 0) {
                        /* one single point code */

+                       struct osmo_ss7_route_label rtlabel = {
+                               .opc = xua->mtp.opc, /* Use OPC of received 
DAUD. FIXME: is this correct? */
+                               .dpc = pc,
+                               .sls = 0,
+                       };
+
                        /* FIXME: don't just check for a route; but also check 
if the route is "active" */
-                       if (osmo_ss7_route_lookup(s7i, pc))
+                       if (ss7_instance_lookup_route(s7i, &rtlabel))
                                is_available = true;

                        xua_tx_snm_available(asp, rctx, num_rctx, &aff_pc[i], 
1, "Response to DAUD",
diff --git a/tests/ss7/ss7_test.c b/tests/ss7/ss7_test.c
index 6fe1110..95fa1b1 100644
--- a/tests/ss7/ss7_test.c
+++ b/tests/ss7/ss7_test.c
@@ -147,11 +147,15 @@
        osmo_ss7_user_destroy(user2);
 }

+#define RT_LABEL(opc_val, dpc_val, sls_val) \
+       (struct osmo_ss7_route_label){ .opc = (opc_val), .dpc = (dpc_val), .sls 
= (sls_val) }
+
 static void test_route(void)
 {
        struct osmo_ss7_route_table *rtbl;
        struct osmo_ss7_linkset *lset_a, *lset_b;
        struct osmo_ss7_route *rt, *rt12, *rtdef;
+       struct osmo_ss7_route_label route_label;

        printf("Testing SS7 routing\n");

@@ -173,32 +177,45 @@
        OSMO_ASSERT(lset_b);

        /* route with full mask */
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == NULL);
+       route_label = RT_LABEL(0, 12, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == NULL);
        rt = ss7_route_create(rtbl, 12, 0xffff, "a");
        printf("route with full mask: %s\n", osmo_ss7_route_print(rt));
        OSMO_ASSERT(rt);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt);
+       route_label = RT_LABEL(0, 12, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
        ss7_route_destroy(rt);

        /* route with partial mask */
        rt = ss7_route_create(rtbl, 8, 0xfff8, "a");
        printf("route with partial mask: %s\n", osmo_ss7_route_print(rt));
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 8) == rt);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 9) == rt);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == NULL);
+       route_label = RT_LABEL(0, 8, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
+       route_label = RT_LABEL(0, 9, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
+       route_label = RT_LABEL(0, 12, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
+       route_label = RT_LABEL(0, 15, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
+       route_label = RT_LABEL(0, 16, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == NULL);
        /* insert more specific route for 12, must have higher priority
         * than existing one */
        rt12 = ss7_route_create(rtbl, 12, 0xffff, "b");
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt12);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == NULL);
+       route_label = RT_LABEL(0, 12, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt12);
+       route_label = RT_LABEL(0, 15, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
+       route_label = RT_LABEL(0, 16, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == NULL);
        /* add a default route, which should have lowest precedence */
        rtdef = ss7_route_create(rtbl, 0, 0, "a");
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt12);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt);
-       OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == rtdef);
+       route_label = RT_LABEL(0, 12, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt12);
+       route_label = RT_LABEL(0, 15, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
+       route_label = RT_LABEL(0, 16, 0);
+       OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rtdef);

        ss7_route_destroy(rtdef);
        ss7_route_destroy(rt12);
diff --git a/tests/vty/osmo_stp_test.vty b/tests/vty/osmo_stp_test.vty
index 747c7b7..200fff8 100644
--- a/tests/vty/osmo_stp_test.vty
+++ b/tests/vty/osmo_stp_test.vty
@@ -112,6 +112,8 @@
   point-code format default
   point-code delimiter (default|dash)
   xua rkm routing-key-allocation (static-only|dynamic-permitted)
+  sls-opc-dpc [opc-shift] [<0-8>] [dpc-shift] [<0-8>]
+  sls-shift <0-6>
   asp NAME <0-65535> <0-65535> (sua|m3ua|ipa)
   asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) (sctp|tcp)
   no asp NAME
@@ -132,6 +134,8 @@
   point-code         Configure the local Point Code
   secondary-pc       Configure the local Secondary Point Code
   xua                SIGTRAN xxxUA related
+  sls-opc-dpc        Shift OPC and DPC bits used during routing decision
+  sls-shift          Shift SLS bits used during routing decision
   asp                Configure Application Server Process
   no                 Negate a command or set its defaults
   as                 Configure an Application Server

--
To view, visit https://gerrit.osmocom.org/c/libosmo-sigtran/+/39377?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: I0fb4ca4959096f748a23082efa0481300de56436
Gerrit-Change-Number: 39377
Gerrit-PatchSet: 12
Gerrit-Owner: pespin <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: osmith <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to