pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/43831?usp=email ) Change subject: Create dynamic routes for AS statically configured routing-key ...................................................................... Create dynamic routes for AS statically configured routing-key We already do so for routing-keys registered through RKM. Let's do it too for statically configured ones. This makes it easier to configure default routing on an STP, since there's no need to set up "update route" for the most usual cases. If specific routing is required (eg. combined linkset loadsharing use over multiple AS on a given PC), it can still be configured manually using a higher prio in the routing table. The newly created dynamic routes contain the "match_as_routing_key" setting, which means they are only usable to route a given message if its routing label matches the routing-key of the AS. This opens the door to improved traffic forwarding security as well as more fine-grained traffic routing selection based on eg. OPC. So far only matching on DPC and optionaly on OPC is supported. Matching on SI and SSN is left as TODO work for the future. Related: OS#7070 Change-Id: Ie74f4b502d4e5beacbf1ac5cd772b8735ea853ed --- M src/ss7_as.c M src/ss7_as_vty.c M src/ss7_combined_linkset.c M src/ss7_route.c M src/ss7_route.h M src/ss7_vty.c M tests/vty/osmo_stp_route_prio.vty 7 files changed, 76 insertions(+), 21 deletions(-) Approvals: Jenkins Builder: Verified laforge: Looks good to me, approved osmith: Looks good to me, but someone else must approve diff --git a/src/ss7_as.c b/src/ss7_as.c index 3d856b3..59e9e06 100644 --- a/src/ss7_as.c +++ b/src/ss7_as.c @@ -757,6 +757,8 @@ if (ss7_route_set_linkset(rt, as->cfg.name) < 0) goto ret_free; + rt->cfg.match_as_routing_key = true; + rc = ss7_route_insert(rt); if (rc == -EADDRINUSE) { talloc_free(rt); @@ -783,6 +785,13 @@ if (!rt) return -ENOENT; + if (!rt->cfg.match_as_routing_key) { + LOGPAS(as, DLSS7, LOGL_NOTICE, + "Skip removing route %s without match-routing-key field!\n", + osmo_ss7_route_name(rt, false)); + return 0; + } + /* Release the associated route */ ss7_route_destroy(rt); return 0; diff --git a/src/ss7_as_vty.c b/src/ss7_as_vty.c index ca00ae3..a481a2b 100644 --- a/src/ss7_as_vty.c +++ b/src/ss7_as_vty.c @@ -446,6 +446,9 @@ ssn = OSSMO_SS7_RKEY_SSN_UNSET; } + /* Drop previous route if exists: */ + ss7_as_routing_key_delete_route(as); + rkey->context = rctx; /* truncate mask to maximum. Let's avoid callers specifying arbitrary large * masks to ensure we don't fail duplicate detection with longer mask lengths */ @@ -454,6 +457,13 @@ rkey->opc_mask = osmo_ss7_pc_normalize(&as->inst->cfg.pc_fmt, opc_mask); rkey->si = si; rkey->ssn = ssn; + + /* Add fully qualified route for routing-key: */ + if (ss7_as_routing_key_create_route(as) < 0) { + vty_out(vty, "Failed adding dynamic match-routing-key route for AS %s!%s", + as->cfg.name, VTY_NEWLINE); + return CMD_WARNING; + } return CMD_SUCCESS; } diff --git a/src/ss7_combined_linkset.c b/src/ss7_combined_linkset.c index 9f53b7b..59c7007 100644 --- a/src/ss7_combined_linkset.c +++ b/src/ss7_combined_linkset.c @@ -193,11 +193,12 @@ } /* 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) +struct osmo_ss7_route *current_rt(const struct osmo_ss7_esls_entry *eslse, + const struct osmo_ss7_route_label *rtlabel) { - if (eslse->normal_rt && ss7_route_is_available(eslse->normal_rt)) + if (eslse->normal_rt && ss7_route_is_available_for_rtlabel(eslse->normal_rt, rtlabel)) return eslse->normal_rt; - if (eslse->alt_rt && ss7_route_is_available(eslse->alt_rt)) + if (eslse->alt_rt && ss7_route_is_available_for_rtlabel(eslse->alt_rt, rtlabel)) return eslse->alt_rt; return NULL; } @@ -223,13 +224,14 @@ } /* 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) +static struct osmo_ss7_route *ss7_combined_linkset_select_route_roundrobin(struct osmo_ss7_combined_linkset *clset, + const struct osmo_ss7_route_label *rtlabel) { 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(rt)) + if (rt && ss7_route_is_available_for_rtlabel(rt, rtlabel)) return rt; } return NULL; @@ -245,7 +247,7 @@ char buf[256]; /* First check if we have a cached route for this ESLS */ - rt = current_rt(eslse); + rt = current_rt(eslse, rtlabel); if (rt) { if (rt == eslse->normal_rt) { /* We can transmit over normal route. @@ -279,7 +281,7 @@ if (!rt) return NULL; eslse->normal_rt = rt; - rt_avail = ss7_route_is_available(eslse->normal_rt); + rt_avail = ss7_route_is_available_for_rtlabel(eslse->normal_rt, rtlabel); 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, @@ -295,7 +297,7 @@ /* 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); + rt = ss7_combined_linkset_select_route_roundrobin(clset, rtlabel); if (rt) { eslse->alt_rt = rt; LOGPCLSET(clset, DLSS7, LOGL_NOTICE, "RT Lookup: %s -> eSLS=%u: " diff --git a/src/ss7_route.c b/src/ss7_route.c index a75b32c..d0a6c69 100644 --- a/src/ss7_route.c +++ b/src/ss7_route.c @@ -147,6 +147,7 @@ rt->cfg.pc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, pc); rt->cfg.priority = OSMO_SS7_ROUTE_PRIO_DEFAULT; rt->cfg.dyn_allocated = dynamic; + rt->cfg.match_as_routing_key = false; osmo_timer_setup(&rt->t10_audit_timer, t10_audit_timer_cb, rt); @@ -228,7 +229,8 @@ 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) == 0 && - prev_rt->cfg.dyn_allocated == rt->cfg.dyn_allocated) { + prev_rt->cfg.dyn_allocated == rt->cfg.dyn_allocated && + prev_rt->cfg.match_as_routing_key == rt->cfg.match_as_routing_key) { LOGPRT(rt, DLSS7, LOGL_ERROR, "Refusing to create route with existing linkset/AS name '%s'\n", rt->cfg.linkset_name); return -EADDRINUSE; @@ -384,6 +386,8 @@ if (rt->dest.as) { struct osmo_ss7_as *as = rt->dest.as; + if (rt->cfg.match_as_routing_key) + APPEND(" match-routing-key"); APPEND(" via AS %s proto=%s", as->cfg.name, osmo_ss7_asp_protocol_name(as->cfg.proto)); if (list_asps) { @@ -457,6 +461,25 @@ return false; } +bool ss7_route_is_available_for_rtlabel(const struct osmo_ss7_route *rt, + const struct osmo_ss7_route_label *rtlabel) +{ + if (!ss7_route_dest_is_available(rt)) + return false; + if (rt->cfg.match_as_routing_key) { + 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) + return false; + if ((rtlabel->opc & rkey->opc_mask) != rkey->opc) + return false; + /* TODO: match rkey->si */ + /* TODO: match rkey->ssn */ + } + return true; +} + /* Whether route mask identifies a single DPC. */ bool ss7_route_is_fully_qualified(const struct osmo_ss7_route *rt) { diff --git a/src/ss7_route.h b/src/ss7_route.h index 437a5d8..fa6bdc9 100644 --- a/src/ss7_route.h +++ b/src/ss7_route.h @@ -10,6 +10,7 @@ struct osmo_ss7_instance; struct osmo_ss7_route_table; +struct osmo_ss7_route_label; struct osmo_ss7_linkset; struct osmo_ss7_as; @@ -54,6 +55,7 @@ uint32_t priority; uint8_t qos_class; bool dyn_allocated; + bool match_as_routing_key; } cfg; }; @@ -75,6 +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_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_vty.c b/src/ss7_vty.c index 935529e..2127958 100644 --- a/src/ss7_vty.c +++ b/src/ss7_vty.c @@ -609,7 +609,7 @@ default: OSMO_ASSERT(0); } - vty_out(vty, "%-16s %-5s %c %c %u %-19s %-7s %-7s %-7s %-3s%s", + vty_out(vty, "%-16s %-5s %c %c %u %-19s %-7s %-7s %-7s %-3s %-17s%s", rt_str, clsetavail_str, ' ', @@ -620,6 +620,7 @@ nonadj_str, rtavail_str, rt->cfg.dyn_allocated ? "dyn" : "", + rt->cfg.match_as_routing_key ? "match-routing-key" : "", VTY_NEWLINE); } } diff --git a/tests/vty/osmo_stp_route_prio.vty b/tests/vty/osmo_stp_route_prio.vty index 54c9475..2422043 100644 --- a/tests/vty/osmo_stp_route_prio.vty +++ b/tests/vty/osmo_stp_route_prio.vty @@ -94,9 +94,12 @@ Destination C Q P Linkset Name Linkset Non-adj Route ---------------------- - - - ------------------- ------- ------- ------- -3.2.1/14 INACC 0 2 as3 UNAVAIL allowed UNAVAIL -3.2.1/14 INACC 0 5 as2 UNAVAIL allowed UNAVAIL -3.2.1/14 INACC 7 6 as1 UNAVAIL allowed UNAVAIL +3.2.1/14 INACC 0 2 as3 UNAVAIL allowed UNAVAIL +0.1.2/14 INACC 0 5 as1 UNAVAIL allowed UNAVAIL dyn match-routing-key +0.1.3/14 INACC 0 5 as2 UNAVAIL allowed UNAVAIL dyn match-routing-key +0.1.4/14 INACC 0 5 as3 UNAVAIL allowed UNAVAIL dyn match-routing-key +3.2.1/14 INACC 0 5 as2 UNAVAIL allowed UNAVAIL +3.2.1/14 INACC 7 6 as1 UNAVAIL allowed UNAVAIL OsmoSTP(config-cs7-rt)# ! NOW ADD MORE GENERIC ROUTES (SMALLER BITMASK LENGTH) OsmoSTP(config-cs7-rt)# update route 3.2.0 7.255.0 linkset as3 priority 3 @@ -124,14 +127,17 @@ Destination C Q P Linkset Name Linkset Non-adj Route ---------------------- - - - ------------------- ------- ------- ------- -3.2.1/14 INACC 0 2 as3 UNAVAIL allowed UNAVAIL -3.2.1/14 INACC 0 5 as2 UNAVAIL allowed UNAVAIL -3.2.1/14 INACC 7 6 as1 UNAVAIL allowed UNAVAIL -3.2.0/11 INACC 0 1 as1 UNAVAIL allowed UNAVAIL - 0 1 as2 UNAVAIL allowed UNAVAIL - 0 1 as3 UNAVAIL allowed UNAVAIL -3.2.0/11 INACC 0 2 as3 UNAVAIL allowed UNAVAIL -3.2.0/11 INACC 0 3 as3 UNAVAIL allowed UNAVAIL +3.2.1/14 INACC 0 2 as3 UNAVAIL allowed UNAVAIL +0.1.2/14 INACC 0 5 as1 UNAVAIL allowed UNAVAIL dyn match-routing-key +0.1.3/14 INACC 0 5 as2 UNAVAIL allowed UNAVAIL dyn match-routing-key +0.1.4/14 INACC 0 5 as3 UNAVAIL allowed UNAVAIL dyn match-routing-key +3.2.1/14 INACC 0 5 as2 UNAVAIL allowed UNAVAIL +3.2.1/14 INACC 7 6 as1 UNAVAIL allowed UNAVAIL +3.2.0/11 INACC 0 1 as1 UNAVAIL allowed UNAVAIL + 0 1 as2 UNAVAIL allowed UNAVAIL + 0 1 as3 UNAVAIL allowed UNAVAIL +3.2.0/11 INACC 0 2 as3 UNAVAIL allowed UNAVAIL +3.2.0/11 INACC 0 3 as3 UNAVAIL allowed UNAVAIL OsmoSTP(config-cs7-rt)# do show cs7 instance 0 route binding-table 3.2.1 -- To view, visit https://gerrit.osmocom.org/c/libosmo-sigtran/+/43831?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: Ie74f4b502d4e5beacbf1ac5cd772b8735ea853ed Gerrit-Change-Number: 43831 Gerrit-PatchSet: 6 Gerrit-Owner: pespin <pespin@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de> Gerrit-Reviewer: laforge <laforge@osmocom.org> Gerrit-Reviewer: osmith <osmith@sysmocom.de> Gerrit-Reviewer: pespin <pespin@sysmocom.de>