pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/40558?usp=email )
Change subject: xua_snm: Add fully qualified dynamic routes to track announced PCs ......................................................................
xua_snm: Add fully qualified dynamic routes to track announced PCs
This allows building up a set of "concerned remote PCs" which can be used to indicate (MTP-PAUSE/RESUME.ind, N-PCSTATE.ind) upper layers that specific remote PCs went down eg. when a local AS becomes inactive (for instance because the last ASP SCTP/TCP link goes down).
Change-Id: Icd72e7b15ea3f18c7d1a9a7c821d6d7f7ab11a96 --- M src/ss7_route_table.c M src/ss7_route_table.h M src/xua_snm.c 3 files changed, 63 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/58/40558/1
diff --git a/src/ss7_route_table.c b/src/ss7_route_table.c index f216cff..e59fd55 100644 --- a/src/ss7_route_table.c +++ b/src/ss7_route_table.c @@ -137,6 +137,41 @@ return NULL; }
+/*! \brief Find a SS7 route for given destination point code + mask in given table via given AS. + * + * 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_as(struct osmo_ss7_route_table *rtbl, uint32_t dpc, + uint32_t mask, const struct osmo_ss7_as *as, bool dynamic) +{ + 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); + mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask); + + /* 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; + llist_for_each_entry(rt, &clset->routes, list) { + if (rt->dest.as != as) + continue; + if (rt->cfg.dyn_allocated != dynamic) + continue; + return rt; + } + } + return NULL; +} + struct osmo_ss7_combined_linkset * ss7_route_table_find_combined_linkset_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc) { diff --git a/src/ss7_route_table.h b/src/ss7_route_table.h index 1155600..a128915 100644 --- a/src/ss7_route_table.h +++ b/src/ss7_route_table.h @@ -42,6 +42,9 @@ ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask, bool dynamic); struct osmo_ss7_route * +ss7_route_table_find_route_by_dpc_mask_as(struct osmo_ss7_route_table *rtbl, uint32_t dpc, + uint32_t mask, const struct osmo_ss7_as *as, bool dynamic); +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 * diff --git a/src/xua_snm.c b/src/xua_snm.c index 42361c9..d4c9a75 100644 --- a/src/xua_snm.c +++ b/src/xua_snm.c @@ -154,16 +154,36 @@ /* RFC4666 1.4.2.5: "maintain a dynamic table of available SGP routes * for the SS7 destinations, taking into account the SS7 destination * availability/restricted/congestion status received from the SGP "*/ -static void xua_snm_srm_pc_available(struct osmo_ss7_as *as, - const uint32_t *aff_pc, unsigned int num_aff_pc, - bool available) +static void xua_snm_srm_pc_available_single(struct osmo_ss7_as *as, uint32_t pc, bool available) { struct osmo_ss7_instance *s7i = as->inst; enum osmo_ss7_route_status new_status; + struct osmo_ss7_route *rt;
new_status = available ? OSMO_SS7_ROUTE_STATUS_AVAILABLE : OSMO_SS7_ROUTE_STATUS_UNAVAILABLE;
+ /* Check if we already have a dynamic fully qualified route towards that AS: */ + rt = ss7_route_table_find_route_by_dpc_mask_as(s7i->rtable_system, pc, 0xffffff, as, true); + if (!rt) { + /* No dynamic fully qualified route found. Add dynamic fully + * squalified route and mark it as (un)available: */ + rt = ss7_route_create(s7i->rtable_system, pc, 0xffffff, true, as->cfg.name); + if (!rt) { + LOGPAS(as, DLSS7, LOGL_ERROR, "Unable to create dynamic route for pc=%u=%s status=%s\n", + pc, osmo_ss7_pointcode_print(s7i, pc), ss7_route_status_name(new_status)); + return; + } + ss7_route_update_route_status(rt, new_status); + /* No need to iterate over rtable below, since we know there was no route: */ + return; + } + ss7_route_table_update_route_status_by_as(s7i->rtable_system, new_status, as, pc); +} +static void xua_snm_srm_pc_available(struct osmo_ss7_as *as, + const uint32_t *aff_pc, unsigned int num_aff_pc, + bool available) +{ for (unsigned int i = 0; i < num_aff_pc; i++) { /* 32bit "Affected Point Code" consists of a 7-bit mask followed by 14/16/24-bit SS7 PC, * see RFC 4666 3.4.1 */ @@ -172,13 +192,13 @@ uint8_t mask = _aff_pc >> 24;
if (!mask) { - ss7_route_table_update_route_status_by_as(s7i->rtable_system, new_status, as, pc); + xua_snm_srm_pc_available_single(as, pc, available); } else { /* Update only full DPC routes. */ uint32_t maskbits = (1 << mask) - 1; uint32_t fullpc; for (fullpc = (pc & ~maskbits); fullpc <= (pc | maskbits); fullpc++) - ss7_route_table_update_route_status_by_as(s7i->rtable_system, new_status, as, fullpc); + xua_snm_srm_pc_available_single(as, fullpc, available); } } }