pespin has uploaded this change for review.
Support AS routing filtering based on its routing-key SI
Pass the full ss7_mtp3_rtlabel instead of the generic osmo_ss7_routing_label
to combined_linkset() lookup, which contains also the SIO of the message
being routed.
Then, update ss7_route_is_available_for_rtlabel() ->
ss7_route_is_available_for_mtp3_rtlabel() to also take into account the
SIO field when figuring out if the message can be routed to an AS.
Also update the VTY "route-lookup" command to require an SI from the
user, since routing may changed based on it now.
Related: OS#7070
Change-Id: Iec4af5d9a3607747006c26e2baa61ab945f88532
---
M src/ss7_combined_linkset.c
M src/ss7_combined_linkset.h
M src/ss7_route.c
M src/ss7_route.h
M src/ss7_route_table.c
M src/ss7_vty.c
M tests/vty/osmo_stp_route_prio.vty
7 files changed, 41 insertions(+), 37 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/45/43845/1
diff --git a/src/ss7_combined_linkset.c b/src/ss7_combined_linkset.c
index 59c7007..b3b4ccd 100644
--- a/src/ss7_combined_linkset.c
+++ b/src/ss7_combined_linkset.c
@@ -172,11 +172,11 @@
return avail;
}
-static ext_sls_t osmo_ss7_instance_calc_itu_ext_sls(const struct osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlabel)
+static ext_sls_t osmo_ss7_instance_calc_itu_ext_sls(const struct osmo_ss7_instance *inst, const struct ss7_mtp3_rtlabel *mtp3_rtlb)
{
/* 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);
+ uint8_t opc6 = (uint8_t)((mtp3_rtlb->rtlabel.opc >> inst->cfg.opc_shift) & 0x3f);
+ uint8_t dpc6 = (uint8_t)((mtp3_rtlb->rtlabel.dpc >> inst->cfg.dpc_shift) & 0x3f);
/* Derivate 3-bit value from OPC and DPC: */
uint8_t opc3 = ((opc6 >> 3) ^ (opc6 & 0x07)) & 0x07;
@@ -184,7 +184,7 @@
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);
+ uint8_t ext_sls = (opc_dpc3 << 4) | ((mtp3_rtlb->rtlabel.sls) & 0x0f);
OSMO_ASSERT(ext_sls < NUM_EXT_SLS);
/* Pick extended-SLS bits according to config: */
@@ -194,11 +194,11 @@
/* 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,
- const struct osmo_ss7_route_label *rtlabel)
+ const struct ss7_mtp3_rtlabel *mtp3_rtlb)
{
- if (eslse->normal_rt && ss7_route_is_available_for_rtlabel(eslse->normal_rt, rtlabel))
+ if (eslse->normal_rt && ss7_route_is_available_for_mtp3_rtlabel(eslse->normal_rt, mtp3_rtlb))
return eslse->normal_rt;
- if (eslse->alt_rt && ss7_route_is_available_for_rtlabel(eslse->alt_rt, rtlabel))
+ if (eslse->alt_rt && ss7_route_is_available_for_mtp3_rtlabel(eslse->alt_rt, mtp3_rtlb))
return eslse->alt_rt;
return NULL;
}
@@ -225,29 +225,29 @@
/* 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,
- const struct osmo_ss7_route_label *rtlabel)
+ const struct ss7_mtp3_rtlabel *mtp3_rtlb)
{
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_tx, struct osmo_ss7_route, list);
- if (rt && ss7_route_is_available_for_rtlabel(rt, rtlabel))
+ if (rt && ss7_route_is_available_for_mtp3_rtlabel(rt, mtp3_rtlb))
return 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)
+ss7_combined_linkset_lookup_route(struct osmo_ss7_combined_linkset *clset, const struct ss7_mtp3_rtlabel *mtp3_rtlb)
{
struct osmo_ss7_route *rt;
struct osmo_ss7_instance *inst = clset->rtable->inst;
- ext_sls_t esls = osmo_ss7_instance_calc_itu_ext_sls(inst, rtlabel);
+ ext_sls_t esls = osmo_ss7_instance_calc_itu_ext_sls(inst, mtp3_rtlb);
struct osmo_ss7_esls_entry *eslse = &clset->esls_table[esls];
char buf[256];
/* First check if we have a cached route for this ESLS */
- rt = current_rt(eslse, rtlabel);
+ rt = current_rt(eslse, mtp3_rtlb);
if (rt) {
if (rt == eslse->normal_rt) {
/* We can transmit over normal route.
@@ -255,14 +255,14 @@
if (eslse->alt_rt) {
LOGPCLSET(clset, DLSS7, LOGL_NOTICE, "RT lookup: %s -> eSLS=%u: "
"Normal Route via '%s' became available, drop use of Alternative Route via '%s'\n",
- ss7_route_label_to_str(buf, sizeof(buf), inst, rtlabel), esls,
+ ss7_mtp3_rtlabel_to_str(buf, sizeof(buf), inst, mtp3_rtlb), esls,
eslse->normal_rt->dest.as ? eslse->normal_rt->dest.as->cfg.name : "<linkset>",
eslse->alt_rt->dest.as ? eslse->alt_rt->dest.as->cfg.name : "<linkset>");
eslse->alt_rt = NULL;
}
LOGPCLSET(clset, DLSS7, LOGL_DEBUG,
"RT lookup: %s -> eSLS=%u: use Normal Route via '%s'\n",
- ss7_route_label_to_str(buf, sizeof(buf), inst, rtlabel), esls,
+ ss7_mtp3_rtlabel_to_str(buf, sizeof(buf), inst, mtp3_rtlb), esls,
eslse->normal_rt->dest.as ? eslse->normal_rt->dest.as->cfg.name : "<linkset>");
return rt;
}
@@ -281,10 +281,10 @@
if (!rt)
return NULL;
eslse->normal_rt = rt;
- rt_avail = ss7_route_is_available_for_rtlabel(eslse->normal_rt, rtlabel);
+ rt_avail = ss7_route_is_available_for_mtp3_rtlabel(eslse->normal_rt, mtp3_rtlb);
LOGPCLSET(clset, DLSS7, LOGL_INFO, "RT loookup: %s -> eSLS=%u: "
"picked Normal Route via '%s' round-robin style (%s)\n",
- ss7_route_label_to_str(buf, sizeof(buf), inst, rtlabel), esls,
+ ss7_mtp3_rtlabel_to_str(buf, sizeof(buf), inst, mtp3_rtlb), esls,
rt->dest.as ? rt->dest.as->cfg.name : "<linkset>",
rt_avail ? "available" : "unavailable");
if (rt_avail) {
@@ -297,19 +297,19 @@
/* 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, rtlabel);
+ rt = ss7_combined_linkset_select_route_roundrobin(clset, mtp3_rtlb);
if (rt) {
eslse->alt_rt = rt;
LOGPCLSET(clset, DLSS7, LOGL_NOTICE, "RT Lookup: %s -> eSLS=%u: "
"Normal Route via '%s' unavailable, picked Alternative Route via '%s' round-robin style\n",
- ss7_route_label_to_str(buf, sizeof(buf), inst, rtlabel), esls,
+ ss7_mtp3_rtlabel_to_str(buf, sizeof(buf), inst, mtp3_rtlb), esls,
eslse->normal_rt->dest.as ? eslse->normal_rt->dest.as->cfg.name : "<linkset>",
eslse->alt_rt->dest.as ? eslse->alt_rt->dest.as->cfg.name : "<linkset>");
} else {
/* No alternative route found, NULL is returned. */
LOGPCLSET(clset, DLSS7, LOGL_INFO, "RT Lookup: %s -> eSLS=%u: "
"Normal Route via '%s' unavailable, all Alternative Routes unavailable\n",
- ss7_route_label_to_str(buf, sizeof(buf), inst, rtlabel), esls,
+ ss7_mtp3_rtlabel_to_str(buf, sizeof(buf), inst, mtp3_rtlb), esls,
eslse->normal_rt->dest.as ? eslse->normal_rt->dest.as->cfg.name : "<linkset>");
}
return rt;
diff --git a/src/ss7_combined_linkset.h b/src/ss7_combined_linkset.h
index e3756b6..8058b6a 100644
--- a/src/ss7_combined_linkset.h
+++ b/src/ss7_combined_linkset.h
@@ -10,7 +10,7 @@
struct osmo_ss7_instance;
struct osmo_ss7_link;
-struct osmo_ss7_route_label;
+struct ss7_mtp3_rtlabel;
#define NUM_EXT_SLS 128
typedef uint8_t ext_sls_t; /* range: 0-127, 7 bit */
@@ -56,7 +56,7 @@
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);
+ss7_combined_linkset_lookup_route(struct osmo_ss7_combined_linkset *clset, const struct ss7_mtp3_rtlabel *mtp3_rtlb);
bool ss7_combined_linkset_is_available(const struct osmo_ss7_combined_linkset *clset);
#define LOGPCLSET(clset, subsys, level, fmt, args ...) do { \
diff --git a/src/ss7_route.c b/src/ss7_route.c
index d0a6c69..550bfae 100644
--- a/src/ss7_route.c
+++ b/src/ss7_route.c
@@ -461,8 +461,8 @@
return false;
}
-bool ss7_route_is_available_for_rtlabel(const struct osmo_ss7_route *rt,
- const struct osmo_ss7_route_label *rtlabel)
+bool ss7_route_is_available_for_mtp3_rtlabel(const struct osmo_ss7_route *rt,
+ const struct ss7_mtp3_rtlabel *mtp3_rtlb)
{
if (!ss7_route_dest_is_available(rt))
return false;
@@ -470,11 +470,13 @@
struct osmo_ss7_as *as = rt->dest.as;
OSMO_ASSERT(as);
struct osmo_ss7_routing_key *rkey = &as->cfg.routing_key;
- if (rtlabel->dpc != rkey->pc)
+ if (mtp3_rtlb->rtlabel.dpc != rkey->pc)
return false;
- if ((rtlabel->opc & rkey->opc_mask) != rkey->opc)
+ if ((mtp3_rtlb->rtlabel.opc & rkey->opc_mask) != rkey->opc)
return false;
- /* TODO: match rkey->si */
+ if (rkey->si != OSSMO_SS7_RKEY_SI_UNSET &&
+ MTP_SIO_SI(mtp3_rtlb->sio) != rkey->si)
+ return false;
/* TODO: match rkey->ssn */
}
return true;
diff --git a/src/ss7_route.h b/src/ss7_route.h
index fa6bdc9..04edb8c 100644
--- a/src/ss7_route.h
+++ b/src/ss7_route.h
@@ -10,7 +10,7 @@
struct osmo_ss7_instance;
struct osmo_ss7_route_table;
-struct osmo_ss7_route_label;
+struct ss7_mtp3_rtlabel;
struct osmo_ss7_linkset;
struct osmo_ss7_as;
@@ -77,8 +77,8 @@
bool ss7_route_dest_is_available(const struct osmo_ss7_route *rt);
bool ss7_route_is_available(const struct osmo_ss7_route *rt);
-bool ss7_route_is_available_for_rtlabel(const struct osmo_ss7_route *rt,
- const struct osmo_ss7_route_label *rtlabel);
+bool ss7_route_is_available_for_mtp3_rtlabel(const struct osmo_ss7_route *rt,
+ const struct ss7_mtp3_rtlabel *mtp3_rtlb);
bool ss7_route_is_fully_qualified(const struct osmo_ss7_route *rt);
static inline bool ss7_route_is_summary(const struct osmo_ss7_route *rt)
diff --git a/src/ss7_route_table.c b/src/ss7_route_table.c
index 9523d99..b115c24 100644
--- a/src/ss7_route_table.c
+++ b/src/ss7_route_table.c
@@ -361,7 +361,7 @@
llist_for_each_entry(clset, &rtbl->combined_linksets, list) {
if ((rtlb.rtlabel.dpc & clset->cfg.mask) != clset->cfg.pc)
continue;
- rt = ss7_combined_linkset_lookup_route(clset, &rtlb.rtlabel);
+ rt = ss7_combined_linkset_lookup_route(clset, &rtlb);
if (!rt)
continue;
return rt;
diff --git a/src/ss7_vty.c b/src/ss7_vty.c
index 2127958..e53f36f 100644
--- a/src/ss7_vty.c
+++ b/src/ss7_vty.c
@@ -736,19 +736,21 @@
}
DEFUN(show_cs7_route_lookup, show_cs7_route_lookup_cmd,
- "show cs7 instance <0-15> route-lookup POINT_CODE from POINT_CODE sls <0-15> [list-asps]",
+ "show cs7 instance <0-15> route-lookup POINT_CODE from POINT_CODE sls <0-15> si <0-15> [list-asps]",
SHOW_STR CS7_STR INST_STR INST_STR
"Look up route\n" "Destination PC\n"
"From\n" "Origin PC\n"
"SLS\n" "SLS value\n"
+ "Service Indicator\n" "SI value\n"
"List ASPs of the AS if route points to an AS")
{
int id = atoi(argv[0]);
- bool list_asps = argc > 4;
+ bool list_asps = argc > 5;
struct osmo_ss7_instance *inst;
struct osmo_ss7_route *rt;
struct ss7_mtp3_rtlabel mtp3_rtlb = {};
int pc;
+ int si;
inst = osmo_ss7_instance_find(id);
if (!inst) {
@@ -769,16 +771,16 @@
return CMD_WARNING;
}
mtp3_rtlb.rtlabel.opc = pc;
-
mtp3_rtlb.rtlabel.sls = atoi(argv[3]);
- /* TODO: set mtp3_rtlb.sio through VTY param once we use it during route lookup below: */
+ si = atoi(argv[4]);
+ mtp3_rtlb.sio = MTP_SIO(si, inst->cfg.network_indicator);
rt = ss7_instance_lookup_route(inst, &mtp3_rtlb);
if (!rt) {
char buf[256];
vty_out(vty, "No route found for label '%s'%s",
- ss7_route_label_to_str(buf, sizeof(buf), inst, &mtp3_rtlb.rtlabel), VTY_NEWLINE);
+ ss7_mtp3_rtlabel_to_str(buf, sizeof(buf), inst, &mtp3_rtlb), VTY_NEWLINE);
return CMD_WARNING;
}
diff --git a/tests/vty/osmo_stp_route_prio.vty b/tests/vty/osmo_stp_route_prio.vty
index 2422043..a40e6f8 100644
--- a/tests/vty/osmo_stp_route_prio.vty
+++ b/tests/vty/osmo_stp_route_prio.vty
@@ -274,5 +274,5 @@
127 - - - -
OsmoSTP(config-cs7-rt)# ! NOW TEST LOOKUP FAILS AS EXPECTED (all route links are down):
-OsmoSTP(config-cs7-rt)# do show cs7 instance 0 route-lookup 3.2.1 from 0.0.1 sls 0
-No route found for label 'OPC=1=0.0.1,DPC=6161=3.2.1,SLS=0'
+OsmoSTP(config-cs7-rt)# do show cs7 instance 0 route-lookup 3.2.1 from 0.0.1 sls 0 si 3
+No route found for label 'OPC=1=0.0.1,DPC=6161=3.2.1,SLS=0,SIO=3=sccp'
To view, visit change 43845. To unsubscribe, or for help writing mail filters, visit settings.