pespin has uploaded this change for review.
xua_msg: Use new internal struct to carry routing label
struct osmo_mtp_transfer_param is a public struct used to pass
information on primitives from MTP SAP. Using it internally is
inconvinient since it cannot be extended.
Instead, add a new struct ss7_mtp3_rtlabel which contains a struct
osmo_ss7_route_label, which can then be passed and used more easily
during routing decisions.
It will also allow extending the routing label to account for user part
labels to route on those in the future.
This commit, although extense, contains no significance change in
behavior.
Related: OS#7070
Change-Id: Ic7982f38babcc11d740745a04b155de856517504
---
M src/ipa.c
M src/m3ua.c
M src/mtp3_hmdc.c
M src/mtp3_hmdt.c
M src/mtp3_hmrt.c
M src/mtp3_rtpc.c
M src/sccp_instance.c
M src/sccp_sclc.c
M src/sccp_scoc.c
M src/sccp_scoc_fsm.c
M src/sccp_scrc.c
M src/ss7_as.c
M src/ss7_instance.c
M src/ss7_instance.h
M src/ss7_route.c
M src/ss7_route_table.c
M src/ss7_route_table.h
M src/ss7_vty.c
M src/sua.c
M src/tcap_as_loadshare.c
M src/xua_as_fsm.c
M src/xua_internal.h
M src/xua_msg.h
M tests/ss7/ss7_test.c
24 files changed, 279 insertions(+), 205 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/44/43844/1
diff --git a/src/ipa.c b/src/ipa.c
index 2f48167..6a43c2c 100644
--- a/src/ipa.c
+++ b/src/ipa.c
@@ -336,7 +336,7 @@
}
/* Update xua->mtp with values from data_hdr */
- m3ua_dh_to_xfer_param(&xua->mtp, &data_hdr);
+ m3ua_dh_to_mtp3_rtlabel(&xua->mtp, &data_hdr);
/* Pass on as if we had received it from an M3UA ASP.
* xua ownership is passed here: */
diff --git a/src/m3ua.c b/src/m3ua.c
index 39272ee..9762c4b 100644
--- a/src/m3ua.c
+++ b/src/m3ua.c
@@ -520,27 +520,27 @@
},
};
-/* convert osmo_mtp_transfer_param to m3ua_data_hdr */
-void mtp_xfer_param_to_m3ua_dh(struct m3ua_data_hdr *mdh,
- const struct osmo_mtp_transfer_param *param)
+/* convert ss7_mtp3_rtlabel to m3ua_data_hdr */
+void mtp3_rtlabel_to_m3ua_dh(struct m3ua_data_hdr *mdh,
+ const struct ss7_mtp3_rtlabel *rtlb)
{
- mdh->opc = htonl(param->opc);
- mdh->dpc = htonl(param->dpc);
- mdh->si = MTP_SIO_SI(param->sio);
- mdh->ni = MTP_SIO_NI(param->sio);
- mdh->mp = MTP_SIO_MP(param->sio);
- mdh->sls = param->sls;
+ mdh->opc = htonl(rtlb->rtlabel.opc);
+ mdh->dpc = htonl(rtlb->rtlabel.dpc);
+ mdh->si = MTP_SIO_SI(rtlb->sio);
+ mdh->ni = MTP_SIO_NI(rtlb->sio);
+ mdh->mp = MTP_SIO_MP(rtlb->sio);
+ mdh->sls = rtlb->rtlabel.sls;
}
-/* convert m3ua_data_hdr to osmo_mtp_transfer_param */
-void m3ua_dh_to_xfer_param(struct osmo_mtp_transfer_param *param,
- const struct m3ua_data_hdr *mdh)
+/* convert m3ua_data_hdr to ss7_mtp3_rtlabel */
+void m3ua_dh_to_mtp3_rtlabel(struct ss7_mtp3_rtlabel *rtlb,
+ const struct m3ua_data_hdr *mdh)
{
- param->opc = ntohl(mdh->opc);
- param->dpc = ntohl(mdh->dpc);
- param->sls = mdh->sls;
+ rtlb->rtlabel.opc = ntohl(mdh->opc);
+ rtlb->rtlabel.dpc = ntohl(mdh->dpc);
+ rtlb->rtlabel.sls = mdh->sls;
/* re-construct SIO */
- param->sio = MTP_SIO_EXT(mdh->si, mdh->ni, mdh->mp);
+ rtlb->sio = MTP_SIO_EXT(mdh->si, mdh->ni, mdh->mp);
}
struct msgb *m3ua_msgb_alloc(const char *name)
@@ -924,12 +924,12 @@
/* store the MTP-level information in the xua_msg for use by
* higher layer protocols */
dh = (struct m3ua_data_hdr *) data_ie->dat;
- m3ua_dh_to_xfer_param(&xua->mtp, dh);
+ m3ua_dh_to_mtp3_rtlabel(&xua->mtp, dh);
LOGPASP(asp, DLM3UA, LOGL_DEBUG,
"%s(): M3UA data header: opc=%u=%s dpc=%u=%s sls=%u\n",
- __func__, xua->mtp.opc, osmo_ss7_pointcode_print(asp->inst, xua->mtp.opc),
- xua->mtp.dpc, osmo_ss7_pointcode_print2(asp->inst, xua->mtp.dpc),
- xua->mtp.sls);
+ __func__, xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print(asp->inst, xua->mtp.rtlabel.opc),
+ xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print2(asp->inst, xua->mtp.rtlabel.dpc),
+ xua->mtp.rtlabel.sls);
rc = xua_find_as_for_asp(&as, asp, rctx_ie);
if (rc)
@@ -943,8 +943,8 @@
}
rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_TOTAL);
- OSMO_ASSERT(xua->mtp.sls <= 0xf);
- rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.sls);
+ OSMO_ASSERT(xua->mtp.rtlabel.sls <= 0xf);
+ rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.rtlabel.sls);
if (rctx_ie) {
/* remove ROUTE_CTX as in the routing case we want to add a new
diff --git a/src/mtp3_hmdc.c b/src/mtp3_hmdc.c
index 68154a2..9127252 100644
--- a/src/mtp3_hmdc.c
+++ b/src/mtp3_hmdc.c
@@ -40,7 +40,7 @@
* Ownership of xua_msg passed is transferred to this function. */
int mtp3_hmdc_rx_from_l2(struct osmo_ss7_instance *inst, struct xua_msg *xua)
{
- uint32_t dpc = xua->mtp.dpc;
+ uint32_t dpc = xua->mtp.rtlabel.dpc;
if (osmo_ss7_pc_is_local(inst, dpc)) {
LOGSS7(inst, LOGL_DEBUG, "%s(): found dpc=%u=%s as local\n",
__func__, dpc, osmo_ss7_pointcode_print(inst, dpc));
diff --git a/src/mtp3_hmdt.c b/src/mtp3_hmdt.c
index a844864..8cc2f68 100644
--- a/src/mtp3_hmdt.c
+++ b/src/mtp3_hmdt.c
@@ -55,14 +55,14 @@
rctx = xua_msg_part_get_u32(rctx_ie);
num_rctx = 1;
}
- xua = m3ua_encode_dupu(&rctx, num_rctx, orig_xua->mtp.dpc, user_part, cause, info_str);
+ xua = m3ua_encode_dupu(&rctx, num_rctx, orig_xua->mtp.rtlabel.dpc, user_part, cause, info_str);
break;
case OSMO_SS7_ASP_PROT_SUA:
if ((rctx_ie = xua_msg_find_tag(orig_xua, SUA_IEI_ROUTE_CTX))) {
rctx = xua_msg_part_get_u32(rctx_ie);
num_rctx = 1;
}
- xua = sua_encode_dupu(&rctx, num_rctx, orig_xua->mtp.dpc, user_part, cause, info_str);
+ xua = sua_encode_dupu(&rctx, num_rctx, orig_xua->mtp.rtlabel.dpc, user_part, cause, info_str);
break;
default:
OSMO_ASSERT(0);
@@ -70,8 +70,8 @@
OSMO_ASSERT(xua);
xua->mtp = orig_xua->mtp;
- xua->mtp.opc = orig_xua->mtp.dpc;
- xua->mtp.dpc = orig_xua->mtp.opc;
+ xua->mtp.rtlabel.opc = orig_xua->mtp.rtlabel.dpc;
+ xua->mtp.rtlabel.dpc = orig_xua->mtp.rtlabel.opc;
return xua;
}
@@ -82,10 +82,9 @@
struct xua_msg *xua;
char buf_orig_opc[MAX_PC_STR_LEN];
char buf_orig_dpc[MAX_PC_STR_LEN];
- struct osmo_ss7_route_label rtlabel;
struct osmo_ss7_route *rt;
- if (osmo_ss7_pc_is_local(inst, orig_xua->mtp.opc)) {
+ if (osmo_ss7_pc_is_local(inst, orig_xua->mtp.rtlabel.opc)) {
/* This shouldn't happen, if a MTP3 User sends data down the
* stack it should also be there to receive it back and hence we
* shouldn't have entered this step... */
@@ -95,24 +94,19 @@
/* We should only be sending DUPU to M3UA peers, hence why we don't
* simply call mtp3_hmrt_message_for_routing() here. */
- rtlabel = (struct osmo_ss7_route_label){
- .opc = orig_xua->mtp.dpc,
- .dpc = orig_xua->mtp.opc,
- .sls = orig_xua->mtp.sls,
- };
- rt = ss7_instance_lookup_route(inst, &rtlabel);
+ rt = ss7_instance_lookup_route(inst, &orig_xua->mtp);
if (!rt) {
LOGSS7(inst, LOGL_NOTICE, "Tx DUPU %u=%s User %u=%s to concerned SP %u=%s: no route!\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
user_part, get_value_string(mtp_si_vals, user_part),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
return 0;
}
if (!rt->dest.as) {
LOGSS7(inst, LOGL_ERROR, "Tx DUPU %u=%s User %u=%s to concerned SP %u=%s: unsupported for linkset!\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
user_part, get_value_string(mtp_si_vals, user_part),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
return 0;
}
@@ -120,18 +114,18 @@
case OSMO_SS7_ASP_PROT_M3UA:
case OSMO_SS7_ASP_PROT_SUA:
LOGSS7(inst, LOGL_INFO, "Message received for unavailable SP %u=%s User %u=%s. Tx DUPU to concerned SP %u=%s\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
user_part, get_value_string(mtp_si_vals, user_part),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
xua = gen_dupu_ret_msg(rt->dest.as->cfg.proto, user_part, orig_xua);
return m3ua_tx_xua_as(rt->dest.as, xua);
case OSMO_SS7_ASP_PROT_IPA:
/* FIXME: No DUPU in IPA, maybe send SUA CLDR (SCCP UDTS) instead? (see send_back_udts()) */
LOGSS7(inst, LOGL_INFO, "Message received for unavailable SP %u=%s User %u=%s, "
"but concerned SP %u=%s is IPA-based and doesn't support DUPU\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
user_part, get_value_string(mtp_si_vals, user_part),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
return 0;
default:
LOGSS7(inst, LOGL_ERROR, "DUPU message for ASP of unknown protocol %u\n",
@@ -158,7 +152,7 @@
prim = mtp_prim_xfer_ind_alloc(NULL,
data_ie->dat + sizeof(*data_hdr),
data_ie->len - sizeof(*data_hdr));
- m3ua_dh_to_xfer_param(&prim->u.transfer, data_hdr);
+ mtp3_rtlabel_to_mtp_xfer_param(&prim->u.transfer, &xua->mtp);
return prim;
}
@@ -177,7 +171,6 @@
rc = -1;
goto ret_free;
}
- prim->u.transfer = xua->mtp;
rc = ss7_user_mtp_sap_prim_up(osu, prim);
diff --git a/src/mtp3_hmrt.c b/src/mtp3_hmrt.c
index 25b2bc4..0b15640 100644
--- a/src/mtp3_hmrt.c
+++ b/src/mtp3_hmrt.c
@@ -53,17 +53,12 @@
*/
int mtp3_hmrt_message_for_routing(struct osmo_ss7_instance *inst, 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,
- };
+ uint32_t dpc = xua->mtp.rtlabel.dpc;
struct osmo_ss7_route *rt;
/* find route for OPC+DPC+SLS: */
/* FIXME: unify with gen_mtp_transfer_req_xua() */
- rt = ss7_instance_lookup_route(inst, &rtlabel);
+ rt = ss7_instance_lookup_route(inst, &xua->mtp);
if (rt) {
/* FIXME: DPC SP restart? */
/* FIXME: DPC Congested? */
@@ -82,8 +77,8 @@
}
rate_ctr_inc2(as->ctrg, SS7_AS_CTR_TX_MSU_TOTAL);
- OSMO_ASSERT(xua->mtp.sls <= 0xf);
- rate_ctr_inc2(as->ctrg, SS7_AS_CTR_TX_MSU_SLS_0 + xua->mtp.sls);
+ OSMO_ASSERT(xua->mtp.rtlabel.sls <= 0xf);
+ rate_ctr_inc2(as->ctrg, SS7_AS_CTR_TX_MSU_SLS_0 + xua->mtp.rtlabel.sls);
switch (as->cfg.proto) {
case OSMO_SS7_ASP_PROT_M3UA:
@@ -126,12 +121,14 @@
{
struct m3ua_data_hdr data_hdr;
struct xua_msg *xua;
+ struct ss7_mtp3_rtlabel mtp3_rtlabel;
/* convert from osmo_mtp_prim MTP-TRANSFER.req to xua_msg */
- mtp_xfer_param_to_m3ua_dh(&data_hdr, param);
+ mtp_xfer_param_to_mtp3_rtlabel(&mtp3_rtlabel, param);
+ mtp3_rtlabel_to_m3ua_dh(&data_hdr, &mtp3_rtlabel);
xua = m3ua_xfer_from_data(&data_hdr, user_data, user_data_len);
OSMO_ASSERT(xua);
- xua->mtp = *param;
+ xua->mtp = mtp3_rtlabel;
/* normally we would call mtp3_hmrt_message_for_routing() here, if we were to follow the state
* diagrams of the ITU-T Q.70x specifications. However, what if a local MTP user sends a
diff --git a/src/mtp3_rtpc.c b/src/mtp3_rtpc.c
index a1a8856..fe6538c 100644
--- a/src/mtp3_rtpc.c
+++ b/src/mtp3_rtpc.c
@@ -43,7 +43,7 @@
struct xua_msg_part *rctx_ie;
unsigned int num_rctx = 0;
uint32_t *rctx_raw = NULL;
- uint32_t aff_pc = htonl(orig_xua->mtp.dpc);
+ uint32_t aff_pc = htonl(orig_xua->mtp.rtlabel.dpc);
if ((rctx_ie = xua_msg_find_tag(orig_xua, M3UA_IEI_ROUTE_CTX))) {
rctx_raw = (uint32_t *) rctx_ie->dat;
@@ -54,8 +54,8 @@
OSMO_ASSERT(xua);
xua->mtp = orig_xua->mtp;
- xua->mtp.opc = orig_xua->mtp.dpc;
- xua->mtp.dpc = orig_xua->mtp.opc;
+ xua->mtp.rtlabel.opc = orig_xua->mtp.rtlabel.dpc;
+ xua->mtp.rtlabel.dpc = orig_xua->mtp.rtlabel.opc;
return xua;
}
@@ -65,18 +65,18 @@
struct xua_msg *xua;
char buf_orig_opc[MAX_PC_STR_LEN];
char buf_orig_dpc[MAX_PC_STR_LEN];
- struct osmo_ss7_route_label rtlabel;
+ struct ss7_mtp3_rtlabel mtp3_rtlabel_tfp;
struct osmo_ss7_route *rt;
/* Start T8 */
- if (ss7_instance_t8_inaccessible_sp_running(inst, orig_xua->mtp.dpc)) {
+ if (ss7_instance_t8_inaccessible_sp_running(inst, orig_xua->mtp.rtlabel.dpc)) {
/* T8 is running for this SP, inhibit Tx of transfer prohibited */
LOGSS7(inst, LOGL_DEBUG, "Tx TFP (DUNA) inaccessible SP %u=%s to concerned SP %u=%s: inhibit due to T8\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
return 0;
}
- ss7_instance_t8_inaccessible_sp_start(inst, orig_xua->mtp.dpc);
+ ss7_instance_t8_inaccessible_sp_start(inst, orig_xua->mtp.rtlabel.dpc);
/* "transfer prohibited RTPC -> HMRT", "To concerned SP or STP".
* See also Q.704 13.2 Transfer-prohibited. */
@@ -89,45 +89,43 @@
* Best match for it is DUNA, so DUNA we send.
*/
- if (osmo_ss7_pc_is_local(inst, orig_xua->mtp.opc)) {
+ if (osmo_ss7_pc_is_local(inst, orig_xua->mtp.rtlabel.opc)) {
xua = gen_duna_ret_msg(inst, orig_xua);
return mtp3_hmdt_message_for_distribution(inst, xua);
}
/* We should only be sending DUNA to M3UA peers, hence why we don't
* simply call mtp3_hmrt_message_for_routing() here. */
- rtlabel = (struct osmo_ss7_route_label){
- .opc = orig_xua->mtp.dpc,
- .dpc = orig_xua->mtp.opc,
- .sls = orig_xua->mtp.sls,
- };
- rt = ss7_instance_lookup_route(inst, &rtlabel);
+ mtp3_rtlabel_tfp = orig_xua->mtp;
+ mtp3_rtlabel_tfp.rtlabel.opc = orig_xua->mtp.rtlabel.dpc;
+ mtp3_rtlabel_tfp.rtlabel.dpc = orig_xua->mtp.rtlabel.opc;
+ rt = ss7_instance_lookup_route(inst, &mtp3_rtlabel_tfp);
if (!rt) {
LOGSS7(inst, LOGL_NOTICE, "Tx TFP (DUNA) inaccessible SP %u=%s to concerned SP %u=%s: no route!\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
return 0;
}
if (!rt->dest.as) {
LOGSS7(inst, LOGL_ERROR, "Tx TFP (DUNA) inaccessible SP %u=%s to concerned SP %u=%s: unsupported for linkset!\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
return 0;
}
switch (rt->dest.as->cfg.proto) {
case OSMO_SS7_ASP_PROT_M3UA:
LOGSS7(inst, LOGL_INFO, "Message received for inaccessible SP %u=%s. Tx TFP (DUNA) to concerned SP %u=%s\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
xua = gen_duna_ret_msg(inst, orig_xua);
return m3ua_tx_xua_as(rt->dest.as, xua);
case OSMO_SS7_ASP_PROT_IPA:
/* FIXME: No DUNA in IPA, maybe send SUA CLDR (SCCP UDTS) instead? */
LOGSS7(inst, LOGL_INFO, "Message received for inaccessible SP %u=%s, "
"but concerned SP %u=%s is IPA-based and doesn't support TFP (DUNA)\n",
- orig_xua->mtp.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.dpc),
- orig_xua->mtp.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.opc));
+ orig_xua->mtp.rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_orig_dpc, sizeof(buf_orig_dpc), inst, orig_xua->mtp.rtlabel.dpc),
+ orig_xua->mtp.rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_orig_opc, sizeof(buf_orig_opc), inst, orig_xua->mtp.rtlabel.opc));
return 0;
default:
LOGSS7(inst, LOGL_ERROR, "DUNA message for ASP of unknown protocol %u\n",
diff --git a/src/sccp_instance.c b/src/sccp_instance.c
index fc7edaf..097665a 100644
--- a/src/sccp_instance.c
+++ b/src/sccp_instance.c
@@ -274,7 +274,7 @@
rc = -1;
break;
}
- xua->mtp = omp->u.transfer;
+ mtp_xfer_param_to_mtp3_rtlabel(&xua->mtp, &omp->u.transfer);
/* hand this primitive into SCCP via the SCRC code */
rc = scrc_rx_mtp_xfer_ind_xua(inst, xua);
xua_msg_free(xua);
diff --git a/src/sccp_sclc.c b/src/sccp_sclc.c
index 1d821f0..68cd397 100644
--- a/src/sccp_sclc.c
+++ b/src/sccp_sclc.c
@@ -85,7 +85,7 @@
* "They are transferred independently of each other.
* Therefore, they may be delivered to the SCCP user out-of-sequence."
*/
- xua->mtp.sls = rand() & 0xf;
+ xua->mtp.rtlabel.sls = rand() & 0xf;
} else {
/* "ITU-T Q.711 6.2.1 Class 1:
* "The SCCP user can invoke this service by means of the parameter
@@ -98,7 +98,7 @@
* stream of NSDUs with the same sequence control parameter".
* SLS is 4 bits, as described in ITU Q.704 Figure 3.
*/
- xua->mtp.sls = udpar->in_sequence_control & 0x0f;
+ xua->mtp.rtlabel.sls = udpar->in_sequence_control & 0x0f;
}
switch (msg_type) {
@@ -369,7 +369,7 @@
case SUA_CL_CLDT:
xua_out = gen_ret_msg(inst, xua_in, cause);
/* TODO: Message Return Option? */
- if (!osmo_ss7_pc_is_local(inst->ss7, xua_in->mtp.opc)) {
+ if (!osmo_ss7_pc_is_local(inst->ss7, xua_in->mtp.rtlabel.opc)) {
/* non-local originator: send UDTS */
/* TODO: Assign SLS */
sccp_scrc_rx_sclc_msg(inst, xua_out);
diff --git a/src/sccp_scoc.c b/src/sccp_scoc.c
index 74f8db4..ffcc039 100644
--- a/src/sccp_scoc.c
+++ b/src/sccp_scoc.c
@@ -189,7 +189,7 @@
/* amend this with point code information; The SUA RELRE
* includes neither called nor calling party address! */
- xua->mtp.dpc = conn->remote_pc;
+ xua->mtp.rtlabel.dpc = conn->remote_pc;
sccp_scrc_rx_scoc_conn_msg(conn->inst, xua);
xua_msg_free(xua);
return 0;
@@ -290,10 +290,10 @@
/* amend this with point code information; Many CO msgs
* includes neither called nor calling party address! */
- xua->mtp.dpc = conn->remote_pc;
+ xua->mtp.rtlabel.dpc = conn->remote_pc;
/* Apply SLS calculated for the connection (ITU-T Q.714 1.1.2.3). */
- xua->mtp.sls = conn->tx_co_mtp_sls;
+ xua->mtp.rtlabel.sls = conn->tx_co_mtp_sls;
switch (msg_type) {
case SUA_CO_CORE: /* Connect Request == SCCP CR */
@@ -555,8 +555,8 @@
xua = gen_coerr(route_ctx, dest_ref, err_cause);
/* copy over the MTP parameters */
- xua->mtp.dpc = in->mtp.opc;
- xua->mtp.opc = in->mtp.dpc;
+ xua->mtp.rtlabel.dpc = in->mtp.rtlabel.opc;
+ xua->mtp.rtlabel.opc = in->mtp.rtlabel.dpc;
xua->mtp.sio = in->mtp.sio;
/* sent to SCRC for transmission */
@@ -593,8 +593,8 @@
xua = gen_relco(route_ctx, dest_ref, src_ref);
/* copy over the MTP parameters */
- xua->mtp.dpc = in->mtp.opc;
- xua->mtp.opc = in->mtp.dpc;
+ xua->mtp.rtlabel.dpc = in->mtp.rtlabel.opc;
+ xua->mtp.rtlabel.opc = in->mtp.rtlabel.dpc;
xua->mtp.sio = in->mtp.sio;
/* send to SCRC for transmission */
@@ -632,8 +632,8 @@
/* Generate RLSD towards remote peer */
xua = gen_rlsd(route_ctx, dest_ref, src_ref);
/* copy over the MTP parameters */
- xua->mtp.dpc = in->mtp.opc;
- xua->mtp.opc = in->mtp.dpc;
+ xua->mtp.rtlabel.dpc = in->mtp.rtlabel.opc;
+ xua->mtp.rtlabel.opc = in->mtp.rtlabel.dpc;
xua->mtp.sio = in->mtp.sio;
/* send to SCRC for transmission */
sccp_scrc_rx_scoc_conn_msg(conn->inst, xua);
@@ -641,8 +641,8 @@
/* Generate RLSD towards local peer */
xua = gen_rlsd(conn->inst->route_ctx, conn->conn_id, conn->remote_ref);
- xua->mtp.dpc = in->mtp.dpc;
- xua->mtp.opc = conn->remote_pc;
+ xua->mtp.rtlabel.dpc = in->mtp.rtlabel.dpc;
+ xua->mtp.rtlabel.opc = conn->remote_pc;
xua->mtp.sio = in->mtp.sio;
osmo_fsm_inst_dispatch(conn->fi, SCOC_E_RCOC_RLSD_IND, xua);
xua_msg_free(xua);
@@ -721,8 +721,8 @@
LOGPSCC(conn, LOGL_NOTICE,
"Received message %s on conn with mismatching remote pc=%u=%s\n",
xua_hdr_dump(xua, &xua_dialect_sua),
- xua->mtp.opc,
- osmo_ss7_pointcode_print_buf(buf_opc, sizeof(buf_opc), conn->inst->ss7, xua->mtp.opc));
+ xua->mtp.rtlabel.opc,
+ osmo_ss7_pointcode_print_buf(buf_opc, sizeof(buf_opc), conn->inst->ss7, xua->mtp.rtlabel.opc));
/* we have received a message with invalid origin PC and thus
* apply the action indicated in Table B.2/Q.714 */
@@ -805,7 +805,7 @@
}
/* Check if received OPC != the remote_pc we stored locally */
- if (xua->mtp.opc != conn->remote_pc) {
+ if (xua->mtp.rtlabel.opc != conn->remote_pc) {
sccp_scoc_rx_inval_opc(conn, xua);
return;
}
diff --git a/src/sccp_scoc_fsm.c b/src/sccp_scoc_fsm.c
index 895435c..8b8feea 100644
--- a/src/sccp_scoc_fsm.c
+++ b/src/sccp_scoc_fsm.c
@@ -160,7 +160,7 @@
conn->remote_pc = conn->calling_addr.pc;
else {
/* Hack to get the MTP label here ?!? */
- conn->remote_pc = xua->mtp.opc;
+ conn->remote_pc = xua->mtp.rtlabel.opc;
}
rc = sua_addr_parse(&conn->called_addr, xua, SUA_IEI_DEST_ADDR);
@@ -284,7 +284,7 @@
* MTP-TRANSFER.indication primitive which conveyed the
* CC message [plus the MTP-SAP instance]) is associated
* with the connection section. */
- conn->remote_pc = xua->mtp.opc;
+ conn->remote_pc = xua->mtp.rtlabel.opc;
osmo_fsm_inst_state_chg(fi, S_ACTIVE, 0, 0);
/* If CR which was used to initiate this connection had excessive Optional Data which we had to cache,
@@ -326,7 +326,7 @@
* MTP-TRANSFER.indication primitive which conveyed the
* CC message [plus the MTP-SAP instance]) is associated
* with the connection section. */
- conn->remote_pc = xua->mtp.opc;
+ conn->remote_pc = xua->mtp.rtlabel.opc;
/* released to SCRC */
sccp_conn_xua_gen_relre_and_send(conn, conn->release_cause, NULL);
diff --git a/src/sccp_scrc.c b/src/sccp_scrc.c
index f18ce02..b97c26c 100644
--- a/src/sccp_scrc.c
+++ b/src/sccp_scrc.c
@@ -105,7 +105,7 @@
struct osmo_mtp_prim *omp;
struct osmo_mtp_transfer_param *param;
struct osmo_ss7_instance *s7i = inst->ss7;
- uint32_t remote_pc = sua->mtp.dpc;
+ uint32_t remote_pc = sua->mtp.rtlabel.dpc;
/* 1) encode the SUA in xua_msg to SCCP message */
msg = osmo_sua_to_sccp(sua);
@@ -117,8 +117,8 @@
/* 2) wrap into MTP-TRANSFER.req primitive */
omp = osmo_mtp_prim_xfer_req_prepend(NULL, msg);
param = &omp->u.transfer;
- if (sua->mtp.opc)
- param->opc = sua->mtp.opc;
+ if (sua->mtp.rtlabel.opc)
+ param->opc = sua->mtp.rtlabel.opc;
else {
if (!osmo_ss7_pc_is_valid(s7i->cfg.primary_pc)) {
LOGPSCI(inst, LOGL_ERROR, "SS7 instance %u: no primary point-code set\n",
@@ -128,7 +128,7 @@
param->opc = s7i->cfg.primary_pc;
}
param->dpc = remote_pc;
- param->sls = sua->mtp.sls;
+ param->sls = sua->mtp.rtlabel.sls;
param->sio = MTP_SIO(MTP_SI_SCCP, s7i->cfg.network_indicator);
/* 3) send via MTP-SAP (osmo_ss7_instance) */
@@ -142,7 +142,6 @@
{
struct osmo_sccp_addr calling;
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.
@@ -160,23 +159,17 @@
if (sua_addr_parse(&calling, xua, SUA_IEI_SRC_ADDR) == 0 &&
(calling.presence & OSMO_SCCP_ADDR_T_PC))
- xua->mtp.opc = calling.pc;
+ xua->mtp.rtlabel.opc = calling.pc;
if (called->presence & OSMO_SCCP_ADDR_T_PC)
- xua->mtp.dpc = called->pc;
+ xua->mtp.rtlabel.dpc = called->pc;
- 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);
+ rt = ss7_instance_lookup_route(inst->ss7, &xua->mtp);
if (!rt) {
char buf[256];
LOGPSCI(inst, LOGL_ERROR, "MTP-TRANSFER.req from SCCP for %s: no route!\n",
- ss7_route_label_to_str(buf, sizeof(buf), inst->ss7, &rtlabel));
+ ss7_route_label_to_str(buf, sizeof(buf), inst->ss7, &xua->mtp.rtlabel));
sccp_rout_fail_enqueue(inst, xua, SCCP_RETURN_CAUSE_MTP_FAILURE, xua->hdr.msg_class == SUA_MSGC_CO);
return -1;
}
@@ -245,11 +238,11 @@
rc = sua_addr_parse(&called, xua, SUA_IEI_DEST_ADDR);
if (rc < 0) {
/* Q.714 2.2.2: It is expectd that CO msgs != CREQ have no "Called Address".
- * Use MTP DPC info provided by SCOC in xua->mtp.dpc instead. */
+ * Use MTP DPC info provided by SCOC in xua->mtp.rtlabel.dpc instead. */
called = (struct osmo_sccp_addr){
.ri = OSMO_SCCP_RI_SSN_PC,
.presence = OSMO_SCCP_ADDR_T_PC,
- .pc = xua->mtp.dpc,
+ .pc = xua->mtp.rtlabel.dpc,
};
}
if (!(called.presence & OSMO_SCCP_ADDR_T_PC)) {
@@ -524,7 +517,7 @@
/* add the M3UA OPC to the address to ensure that the recipient
* can actually respond back to the source */
calling.presence |= OSMO_SCCP_ADDR_T_PC;
- calling.pc = xua->mtp.opc;
+ calling.pc = xua->mtp.rtlabel.opc;
xua_msg_free_tag(xua, SUA_IEI_SRC_ADDR);
xua_msg_add_sccp_addr(xua, SUA_IEI_SRC_ADDR, &calling);
}
diff --git a/src/ss7_as.c b/src/ss7_as.c
index 605a646..3d856b3 100644
--- a/src/ss7_as.c
+++ b/src/ss7_as.c
@@ -549,12 +549,12 @@
return NULL;
}
-static struct osmo_ss7_asp *ss7_as_select_asp_loadshare(struct osmo_ss7_as *as, const struct osmo_mtp_transfer_param *mtp)
+static struct osmo_ss7_asp *ss7_as_select_asp_loadshare(struct osmo_ss7_as *as, const struct ss7_mtp3_rtlabel *rtlb)
{
as_ext_sls_t as_ext_sls;
struct osmo_ss7_asp *asp;
- as_ext_sls = osmo_ss7_instance_calc_itu_as_ext_sls(as, mtp->opc, mtp->sls);
+ as_ext_sls = osmo_ss7_instance_calc_itu_as_ext_sls(as, rtlb->rtlabel.opc, rtlb->rtlabel.sls);
struct osmo_ss7_as_esls_entry *aeslse = &as->aesls_table[as_ext_sls];
/* First check if we have a cached route for this ESLS */
@@ -566,19 +566,19 @@
if (aeslse->alt_asp) {
LOGPAS(as, DLSS7, LOGL_NOTICE, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: "
"Normal ASP '%s' became available, drop use of Alternative ASP '%s'\n",
- mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc),
- mtp->sls, as_ext_sls, asp->cfg.name, aeslse->alt_asp->cfg.name);
+ rtlb->rtlabel.opc, osmo_ss7_pointcode_print(as->inst, rtlb->rtlabel.opc),
+ rtlb->rtlabel.sls, as_ext_sls, asp->cfg.name, aeslse->alt_asp->cfg.name);
aeslse->alt_asp = NULL;
}
LOGPAS(as, DLSS7, LOGL_DEBUG, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: use Normal ASP '%s'\n",
- mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc),
- mtp->sls, as_ext_sls, asp->cfg.name);
+ rtlb->rtlabel.opc, osmo_ss7_pointcode_print(as->inst, rtlb->rtlabel.opc),
+ rtlb->rtlabel.sls, as_ext_sls, asp->cfg.name);
return asp;
}
/* We can transmit over alternative ASP: */
LOGPAS(as, DLSS7, LOGL_INFO, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: use Alternative ASP '%s'\n",
- mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc),
- mtp->sls, as_ext_sls, asp->cfg.name);
+ rtlb->rtlabel.opc, osmo_ss7_pointcode_print(as->inst, rtlb->rtlabel.opc),
+ rtlb->rtlabel.sls, as_ext_sls, asp->cfg.name);
return asp;
}
@@ -594,8 +594,8 @@
aeslse->normal_asp = asp;
LOGPAS(as, DLSS7, LOGL_DEBUG, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: "
"picked Normal ASP '%s' round-robin style\n",
- mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc),
- mtp->sls, as_ext_sls, aeslse->normal_asp->cfg.name);
+ rtlb->rtlabel.opc, osmo_ss7_pointcode_print(as->inst, rtlb->rtlabel.opc),
+ rtlb->rtlabel.sls, as_ext_sls, aeslse->normal_asp->cfg.name);
if (osmo_ss7_asp_active(aeslse->normal_asp)) {
/* Found active Normal Route: */
return aeslse->normal_asp;
@@ -611,8 +611,8 @@
aeslse->alt_asp = asp;
LOGPAS(as, DLSS7, LOGL_NOTICE, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: "
"Normal ASP '%s' unavailable, picked Alternative ASP '%s' round-robin style\n",
- mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc),
- mtp->sls, as_ext_sls, aeslse->normal_asp->cfg.name, asp->cfg.name);
+ rtlb->rtlabel.opc, osmo_ss7_pointcode_print(as->inst, rtlb->rtlabel.opc),
+ rtlb->rtlabel.sls, as_ext_sls, aeslse->normal_asp->cfg.name, asp->cfg.name);
}
return asp;
}
@@ -642,7 +642,7 @@
*/
struct osmo_ss7_asp *ss7_as_select_asp(struct osmo_ss7_as *as, const struct xua_msg *xua)
{
- const struct osmo_mtp_transfer_param *mtp = &xua->mtp;
+ const struct ss7_mtp3_rtlabel *mtp3_rtlabel = &xua->mtp;
struct osmo_ss7_asp *asp = NULL;
switch (as->cfg.mode) {
@@ -654,12 +654,12 @@
if (as->cfg.loadshare.tcap.enabled) {
int rc = tcap_as_select_asp_loadshare(&asp, as, xua);
if (rc == -EPROTONOSUPPORT) /* fallback to non-tcap loadsharing */
- asp = ss7_as_select_asp_loadshare(as, mtp);
+ asp = ss7_as_select_asp_loadshare(as, mtp3_rtlabel);
/* for all other cases, the asp has been either set to NULL or the corresponding asp */
} else
#endif
{
- asp = ss7_as_select_asp_loadshare(as, mtp);
+ asp = ss7_as_select_asp_loadshare(as, mtp3_rtlabel);
}
break;
case OSMO_SS7_AS_TMOD_ROUNDROBIN:
@@ -687,7 +687,7 @@
struct osmo_ss7_asp *osmo_ss7_as_select_asp(struct osmo_ss7_as *as)
{
struct osmo_ss7_asp *asp = NULL;
- struct osmo_mtp_transfer_param mtp;
+ struct ss7_mtp3_rtlabel mtp3_rtlabel;
switch (as->cfg.mode) {
case OSMO_SS7_AS_TMOD_OVERRIDE:
@@ -697,8 +697,8 @@
/* We don't have OPC and SLS information in this API (which is
actually only used to route IPA msgs nowadays by osmo-bsc, so we
don't care. Use hardcoded value to provide some fallback for this scenario: */
- mtp = (struct osmo_mtp_transfer_param){0};
- asp = ss7_as_select_asp_loadshare(as, &mtp);
+ mtp3_rtlabel = (struct ss7_mtp3_rtlabel){0};
+ asp = ss7_as_select_asp_loadshare(as, &mtp3_rtlabel);
break;
case OSMO_SS7_AS_TMOD_ROUNDROBIN:
asp = ss7_as_select_asp_roundrobin(as);
diff --git a/src/ss7_instance.c b/src/ss7_instance.c
index a006fe5..82c0fc2 100644
--- a/src/ss7_instance.c
+++ b/src/ss7_instance.c
@@ -297,7 +297,7 @@
/*! \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)
+ss7_instance_lookup_route(struct osmo_ss7_instance *inst, const struct ss7_mtp3_rtlabel *rtlabel)
{
OSMO_ASSERT(ss7_initialized);
return ss7_route_table_lookup_route(inst->rtable_system, rtlabel);
diff --git a/src/ss7_instance.h b/src/ss7_instance.h
index 8a8e3aa..ea8586d 100644
--- a/src/ss7_instance.h
+++ b/src/ss7_instance.h
@@ -16,7 +16,7 @@
struct osmo_ss7_user;
struct osmo_ss7_route_table;
-struct osmo_ss7_route_label;
+struct ss7_mtp3_rtlabel;
struct osmo_sccp_instance;
enum ss7_instance_xua_timer {
@@ -107,7 +107,7 @@
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);
+ss7_instance_lookup_route(struct osmo_ss7_instance *inst, const struct ss7_mtp3_rtlabel *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.c b/src/ss7_route.c
index ce60bc1..a75b32c 100644
--- a/src/ss7_route.c
+++ b/src/ss7_route.c
@@ -416,10 +416,13 @@
osmo_ss7_route_lookup(struct osmo_ss7_instance *inst, uint32_t dpc)
{
OSMO_ASSERT(ss7_initialized);
- struct osmo_ss7_route_label rtlb = {
- .opc = 0,
- .dpc = dpc,
- .sls = 0,
+ struct ss7_mtp3_rtlabel rtlb = {
+ .rtlabel = {
+ .opc = 0,
+ .dpc = dpc,
+ .sls = 0,
+ },
+ .sio = 0,
};
return ss7_instance_lookup_route(inst, &rtlb);
diff --git a/src/ss7_route_table.c b/src/ss7_route_table.c
index 210d69c..9523d99 100644
--- a/src/ss7_route_table.c
+++ b/src/ss7_route_table.c
@@ -50,6 +50,46 @@
return buf;
}
+char *ss7_mtp3_rtlabel_to_str(char *buf, size_t buf_len, const struct osmo_ss7_instance *inst, const struct ss7_mtp3_rtlabel *mtp3_rtlabel)
+{
+ char buf_opc[MAX_PC_STR_LEN];
+ char buf_dpc[MAX_PC_STR_LEN];
+
+ if (buf_len == 0)
+ return NULL;
+ snprintf(buf, buf_len, "OPC=%u=%s,DPC=%u=%s,SLS=%u,SIO=%u=%s",
+ mtp3_rtlabel->rtlabel.opc, osmo_ss7_pointcode_print_buf(buf_opc, sizeof(buf_opc), inst, mtp3_rtlabel->rtlabel.opc),
+ mtp3_rtlabel->rtlabel.dpc, osmo_ss7_pointcode_print_buf(buf_dpc, sizeof(buf_dpc), inst, mtp3_rtlabel->rtlabel.dpc),
+ mtp3_rtlabel->rtlabel.sls,
+ mtp3_rtlabel->sio, get_value_string(mtp_si_vals, mtp3_rtlabel->sio & 0xf));
+ return buf;
+}
+
+/* convert osmo_mtp_transfer_param to ss7_mtp3_rtlabel */
+void mtp_xfer_param_to_mtp3_rtlabel(struct ss7_mtp3_rtlabel *rtlb,
+ const struct osmo_mtp_transfer_param *param)
+{
+ *rtlb = (struct ss7_mtp3_rtlabel){
+ .rtlabel = {
+ .opc = param->opc,
+ .dpc = param->dpc,
+ .sls = param->sls,
+ },
+ .sio = param->sio,
+ };
+}
+
+void mtp3_rtlabel_to_mtp_xfer_param(struct osmo_mtp_transfer_param *param,
+ const struct ss7_mtp3_rtlabel *rtlb)
+{
+ *param = (struct osmo_mtp_transfer_param){
+ .opc = rtlb->rtlabel.opc,
+ .dpc = rtlb->rtlabel.dpc,
+ .sls = rtlb->rtlabel.sls,
+ .sio = rtlb->sio,
+ };
+}
+
/***********************************************************************
* SS7 Route Tables
***********************************************************************/
@@ -302,22 +342,26 @@
/* Choose a specific route to transmit a packet.
* Note: This function potentially modifies loadsharing state context of chosen combined linkset. */
struct osmo_ss7_route *
-ss7_route_table_lookup_route(const struct osmo_ss7_route_table *rtbl, const struct osmo_ss7_route_label *rtlabel)
+ss7_route_table_lookup_route(const struct osmo_ss7_route_table *rtbl,
+ const struct ss7_mtp3_rtlabel *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,
+ struct ss7_mtp3_rtlabel rtlb = {
+ .rtlabel = {
+ .opc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, rtlabel->rtlabel.opc),
+ .dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, rtlabel->rtlabel.dpc),
+ .sls = rtlabel->rtlabel.sls,
+ },
+ .sio = rtlabel->sio,
};
/* 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)
+ if ((rtlb.rtlabel.dpc & clset->cfg.mask) != clset->cfg.pc)
continue;
- rt = ss7_combined_linkset_lookup_route(clset, &rtlb);
+ rt = ss7_combined_linkset_lookup_route(clset, &rtlb.rtlabel);
if (!rt)
continue;
return rt;
diff --git a/src/ss7_route_table.h b/src/ss7_route_table.h
index 24b2d9c..8a72c33 100644
--- a/src/ss7_route_table.h
+++ b/src/ss7_route_table.h
@@ -11,15 +11,43 @@
struct osmo_ss7_as;
struct osmo_ss7_linkset;
struct osmo_ss7_instance;
+struct osmo_mtp_transfer_param;
enum osmo_ss7_route_status;
+/* Q.703 3.1.4 Message labelling
+ * Q.704 2.2 Routing label
+ * Q.704 15.2 Label */
+#define OSMO_SS7_RTLABEL_SLS_UNSET 0
struct osmo_ss7_route_label {
- uint32_t opc;
- uint32_t dpc;
- uint8_t sls;
+ uint32_t opc; /* Q.704 2.2.3 */
+ uint32_t dpc; /* Q.704 2.2.3 */
+ uint8_t sls; /* Q.704 2.2.4 */
};
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);
+/* MTP3 Label: SI + Routing Label + User Part specific label
+ * Q.703 3.1.4 Message labelling
+ * Q.704 2.1.5, 2.1.6, 2.3.1
+ * Q.704 14.1 (Common characteristics of message signal unit formats) */
+struct ss7_mtp3_rtlabel {
+ struct osmo_ss7_route_label rtlabel;
+ uint8_t sio; /* Q.704 14.2 Service information octet */
+#if 0
+ union { /* Q.704 14.3 Label (User Part labels) */
+ struct { /* si = MTP_SI_SCCP */
+ uint32_t ssn;
+ } sccp;
+ } u;
+#endif
+};
+char *ss7_mtp3_rtlabel_to_str(char *buf, size_t buf_len,
+ const struct osmo_ss7_instance *inst,
+ const struct ss7_mtp3_rtlabel *rtlb);
+void mtp_xfer_param_to_mtp3_rtlabel(struct ss7_mtp3_rtlabel *rtlb,
+ const struct osmo_mtp_transfer_param *param);
+void mtp3_rtlabel_to_mtp_xfer_param(struct osmo_mtp_transfer_param *param,
+ const struct ss7_mtp3_rtlabel *rtlb);
+
struct osmo_ss7_route_table {
/*! member in list of routing tables */
struct llist_head list;
@@ -47,7 +75,8 @@
ss7_route_table_find_route_by_dpc_mask_as(const 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(const struct osmo_ss7_route_table *rtbl, const struct osmo_ss7_route_label *rtlabel);
+ss7_route_table_lookup_route(const struct osmo_ss7_route_table *rtbl,
+ const struct ss7_mtp3_rtlabel *rtlabel);
bool ss7_route_table_dpc_is_accessible(const struct osmo_ss7_route_table *rtbl, uint32_t dpc);
bool ss7_route_table_dpc_is_accessible_via_as(const struct osmo_ss7_route_table *rtbl, uint32_t dpc, const struct osmo_ss7_as *as);
bool ss7_route_table_dpc_is_accessible_skip_as(const struct osmo_ss7_route_table *rtbl, uint32_t dpc, const struct osmo_ss7_as *as);
diff --git a/src/ss7_vty.c b/src/ss7_vty.c
index eec4a80..935529e 100644
--- a/src/ss7_vty.c
+++ b/src/ss7_vty.c
@@ -746,7 +746,7 @@
bool list_asps = argc > 4;
struct osmo_ss7_instance *inst;
struct osmo_ss7_route *rt;
- struct osmo_ss7_route_label rtlabel = {};
+ struct ss7_mtp3_rtlabel mtp3_rtlb = {};
int pc;
inst = osmo_ss7_instance_find(id);
@@ -760,22 +760,24 @@
vty_out(vty, "Invalid point code (%s)%s", argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
- rtlabel.dpc = pc;
+ mtp3_rtlb.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;
+ mtp3_rtlb.rtlabel.opc = pc;
- rtlabel.sls = atoi(argv[3]);
+ mtp3_rtlb.rtlabel.sls = atoi(argv[3]);
- rt = ss7_instance_lookup_route(inst, &rtlabel);
+ /* TODO: set mtp3_rtlb.sio through VTY param once we use it during route lookup below: */
+
+ 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, &rtlabel), VTY_NEWLINE);
+ ss7_route_label_to_str(buf, sizeof(buf), inst, &mtp3_rtlb.rtlabel), VTY_NEWLINE);
return CMD_WARNING;
}
diff --git a/src/sua.c b/src/sua.c
index 37364c5..9b98074 100644
--- a/src/sua.c
+++ b/src/sua.c
@@ -929,8 +929,8 @@
return rc;
rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_TOTAL);
- OSMO_ASSERT(xua->mtp.sls <= 0xf);
- rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.sls);
+ OSMO_ASSERT(xua->mtp.rtlabel.sls <= 0xf);
+ rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.rtlabel.sls);
switch (xua->hdr.msg_type) {
case 0: /* Reserved, permitted by ETSI TS 101 592 5.2.3.2 */
@@ -961,8 +961,8 @@
return rc;
rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_TOTAL);
- OSMO_ASSERT(xua->mtp.sls <= 0xf);
- rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.sls);
+ OSMO_ASSERT(xua->mtp.rtlabel.sls <= 0xf);
+ rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.rtlabel.sls);
switch (xua->hdr.msg_type) {
case 0: /* Reserved, permitted by ETSI TS 101 592 5.2.3.2 */
@@ -1107,8 +1107,8 @@
}
#if 0
- xua->mtp.opc = ;
- xua->mtp.dpc = ;
+ xua->mtp.rtlabel.opc = /* TODO */;
+ xua->mtp.rtlabel.dpc = /* TODO */;
#endif
xua->mtp.sio = MTP_SIO(MTP_SI_SCCP, asp->inst->cfg.network_indicator);
diff --git a/src/tcap_as_loadshare.c b/src/tcap_as_loadshare.c
index 5e8cbb8..2e8d86a 100644
--- a/src/tcap_as_loadshare.c
+++ b/src/tcap_as_loadshare.c
@@ -408,7 +408,7 @@
* @return 0 on success, negative on error
*/
static int send_back_udts(struct osmo_ss7_as *as,
- const struct osmo_mtp_transfer_param *orig_mtp,
+ const struct ss7_mtp3_rtlabel *orig_mtp3_rtlb,
const struct xua_msg *orig_sua,
uint8_t cause_code)
{
@@ -444,9 +444,11 @@
goto free_sua;
}
- new_mtp = *orig_mtp;
- new_mtp.opc = orig_mtp->dpc;
- new_mtp.dpc = orig_mtp->opc;
+ /* Build MTP3 transfer params with swapped OPC and DPC: */
+ new_mtp.opc = orig_mtp3_rtlb->rtlabel.dpc;
+ new_mtp.dpc = orig_mtp3_rtlb->rtlabel.opc;
+ new_mtp.sls = orig_mtp3_rtlb->rtlabel.sls;
+ new_mtp.sio = orig_mtp3_rtlb->sio;
mtp3_hmrt_mtp_xfer_request_l4_to_l3(as->inst, &new_mtp, msgb_data(msg), msgb_length(msg));
msgb_free(msg);
free_sua:
@@ -463,12 +465,16 @@
* \return 0 on success or -ENOKEY
*/
static int asp_loadshare_tcap_route_fallback(struct osmo_ss7_as *as,
- const struct osmo_mtp_transfer_param *orig_mtp,
+ const struct ss7_mtp3_rtlabel *orig_mtp3_rtlb,
const struct msgb *sccp_msg)
{
- struct osmo_mtp_transfer_param new_mtp = *orig_mtp;
+ struct osmo_mtp_transfer_param new_mtp;
int rc = 0;
+
+ new_mtp.opc = orig_mtp3_rtlb->rtlabel.opc;
new_mtp.dpc = as->cfg.loadshare.tcap.unroutable_tcap_fallback_dpc;
+ new_mtp.sls = orig_mtp3_rtlb->rtlabel.sls;
+ new_mtp.sio = orig_mtp3_rtlb->sio;
/* l2 contains the sccp message */
rc = mtp3_hmrt_mtp_xfer_request_l4_to_l3(as->inst, &new_mtp, msgb_l2(sccp_msg), msgb_l2len(sccp_msg));
@@ -489,7 +495,7 @@
*/
static int asp_loadshare_tcap_handle_unroutable(struct osmo_ss7_asp **rasp,
struct osmo_ss7_as *as,
- const struct osmo_mtp_transfer_param *mtp,
+ const struct ss7_mtp3_rtlabel *mtp3_rtlb,
const struct msgb *sccp_msg)
{
struct osmo_ss7_asp *asp = NULL;
@@ -505,7 +511,7 @@
break;
case SS7_AS_TCAP_UNROUTABLE_ROUTE_FALLBACK:
/* No ASP selection. Try to route the SCCP msg to the fallback DPC */
- rc = asp_loadshare_tcap_route_fallback(as, mtp, sccp_msg);
+ rc = asp_loadshare_tcap_route_fallback(as, mtp3_rtlb, sccp_msg);
if (!rc) /* rc == 0 would require a valid asp, use > 0 to drop the msg, but don't send an error back if needed */
rc = 1;
break;
@@ -532,7 +538,7 @@
* -EPROTONOSUPPORT: let caller (regular loadsharing) handle those.
*/
static int asp_loadshare_tcap_sccp(struct osmo_ss7_asp **rasp, struct osmo_ss7_as *as,
- const struct osmo_mtp_transfer_param *mtp, struct msgb *sccp_msg)
+ const struct ss7_mtp3_rtlabel *mtp3_rtlabel, struct msgb *sccp_msg)
{
struct tcap_parsed parsed = {};
struct xua_msg *sua;
@@ -652,7 +658,7 @@
asp = tcap_as_asp_find_by_tcap_id(as, &calling_addr, &called_addr, parsed.dtid);
if (!asp) {
/* Couldn't find a matching TCAP endpoint for an ongoing session */
- rc = asp_loadshare_tcap_handle_unroutable(&asp, as, mtp, sccp_msg);
+ rc = asp_loadshare_tcap_handle_unroutable(&asp, as, mtp3_rtlabel, sccp_msg);
if (rc)
goto out_free_sua;
@@ -684,7 +690,7 @@
asp = tcap_as_asp_find_by_tcap_id(as, &calling_addr, &called_addr, parsed.dtid);
if (!asp) {
/* Couldn't find a matching TCAP endpoint for an ongoing session */
- rc = asp_loadshare_tcap_handle_unroutable(&asp, as, mtp, sccp_msg);
+ rc = asp_loadshare_tcap_handle_unroutable(&asp, as, mtp3_rtlabel, sccp_msg);
if (rc)
goto out_free_sua;
@@ -715,7 +721,7 @@
* if the return option is used."
* See also ITU Q.714 4.2 */
if (rc < 0 && rc != -EPROTONOSUPPORT) {
- send_back_udts(as, mtp, sua, SCCP_RETURN_CAUSE_SUBSYSTEM_FAILURE);
+ send_back_udts(as, mtp3_rtlabel, sua, SCCP_RETURN_CAUSE_SUBSYSTEM_FAILURE);
rc = 0;
}
xua_msg_free(sua);
diff --git a/src/xua_as_fsm.c b/src/xua_as_fsm.c
index 9460cf8..926d44e 100644
--- a/src/xua_as_fsm.c
+++ b/src/xua_as_fsm.c
@@ -185,7 +185,7 @@
case OSMO_SS7_AS_TMOD_OVERRIDE:
case OSMO_SS7_AS_TMOD_LOADSHARE:
/* TODO: OSMO_SS7_AS_TMOD_LOADSHARE: actually use the SLS value
- * in xua->mtp.sls to ensure same SLS goes through same ASP. Not
+ * in xua->mtp.rtlabel.sls to ensure same SLS goes through same ASP. Not
* strictly required by M3UA RFC, but would fit the overall
* principle. */
case OSMO_SS7_AS_TMOD_ROUNDROBIN:
diff --git a/src/xua_internal.h b/src/xua_internal.h
index 2c0658f..b178c75 100644
--- a/src/xua_internal.h
+++ b/src/xua_internal.h
@@ -13,6 +13,7 @@
struct osmo_sccp_addr;
struct m3ua_data_hdr;
+struct ss7_mtp3_rtlabel;
int sua_addr_parse_part(struct osmo_sccp_addr *out,
const struct xua_msg_part *param);
@@ -80,10 +81,10 @@
struct xua_msg *m3ua_xfer_from_data(const struct m3ua_data_hdr *data_hdr,
const uint8_t *data, unsigned int data_len);
struct m3ua_data_hdr *data_hdr_from_m3ua(const struct xua_msg *xua);
-void m3ua_dh_to_xfer_param(struct osmo_mtp_transfer_param *param,
- const struct m3ua_data_hdr *mdh);
-void mtp_xfer_param_to_m3ua_dh(struct m3ua_data_hdr *mdh,
- const struct osmo_mtp_transfer_param *param);
+void m3ua_dh_to_mtp3_rtlabel(struct ss7_mtp3_rtlabel *rtlb,
+ const struct m3ua_data_hdr *mdh);
+void mtp3_rtlabel_to_m3ua_dh(struct m3ua_data_hdr *mdh,
+ const struct ss7_mtp3_rtlabel *rtlb);
extern const struct xua_msg_class m3ua_msg_class_mgmt;
diff --git a/src/xua_msg.h b/src/xua_msg.h
index 9b968a6..bf05670 100644
--- a/src/xua_msg.h
+++ b/src/xua_msg.h
@@ -17,12 +17,13 @@
*/
#pragma once
-#include "xua_types.h"
+#include <stdint.h>
+#include <stdint.h>
#include <osmocom/core/linuxlist.h>
-#include <osmocom/sigtran/mtp_sap.h>
-#include <stdint.h>
-#include <stdint.h>
+
+#include "xua_types.h"
+#include "ss7_route_table.h"
#define XUA_HDR(class, type) ((struct xua_common_hdr) { .spare = 0, .msg_class = (class), .msg_type = (type) })
@@ -33,7 +34,7 @@
struct xua_msg {
struct llist_head entry; /* Allows queueing a xua_msg into a llist */
struct xua_common_hdr hdr;
- struct osmo_mtp_transfer_param mtp;
+ struct ss7_mtp3_rtlabel mtp;
struct llist_head headers;
};
diff --git a/tests/ss7/ss7_test.c b/tests/ss7/ss7_test.c
index f2abb08..1161144 100644
--- a/tests/ss7/ss7_test.c
+++ b/tests/ss7/ss7_test.c
@@ -143,8 +143,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) }
+#define MTP3_RTLABEL(opc_val, dpc_val, sls_val, sio_val) \
+ (struct ss7_mtp3_rtlabel){ \
+ .rtlabel = { \
+ .opc = (opc_val), \
+ .dpc = (dpc_val), \
+ .sls = (sls_val) \
+ }, \
+ .sio = (sio_val), \
+ }
static void test_route(void)
{
@@ -152,7 +159,7 @@
struct osmo_ss7_linkset *lset_a, *lset_b;
struct osmo_ss7_link *l_a, *l_b;
struct osmo_ss7_route *rt, *rt12, *rtdef;
- struct osmo_ss7_route_label route_label;
+ struct ss7_mtp3_rtlabel route_label;
printf("Testing SS7 routing\n");
@@ -181,44 +188,44 @@
l_b->cfg.adm_state = OSMO_SS7_LS_ENABLED;
/* route with full mask */
- route_label = RT_LABEL(0, 12, 0);
+ route_label = MTP3_RTLABEL(0, 12, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == NULL);
rt = ss7_route_create(rtbl, 12, 0xffff, false, "a");
printf("route with full mask: %s\n", osmo_ss7_route_print(rt));
OSMO_ASSERT(rt);
- route_label = RT_LABEL(0, 12, 0);
+ route_label = MTP3_RTLABEL(0, 12, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
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, false, "a");
printf("route with partial mask: %s\n", osmo_ss7_route_print(rt));
- route_label = RT_LABEL(0, 8, 0);
+ route_label = MTP3_RTLABEL(0, 8, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
- route_label = RT_LABEL(0, 9, 0);
+ route_label = MTP3_RTLABEL(0, 9, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
- route_label = RT_LABEL(0, 12, 0);
+ route_label = MTP3_RTLABEL(0, 12, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
- route_label = RT_LABEL(0, 15, 0);
+ route_label = MTP3_RTLABEL(0, 15, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
- route_label = RT_LABEL(0, 16, 0);
+ route_label = MTP3_RTLABEL(0, 16, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
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, false, "b");
- route_label = RT_LABEL(0, 12, 0);
+ route_label = MTP3_RTLABEL(0, 12, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt12);
- route_label = RT_LABEL(0, 15, 0);
+ route_label = MTP3_RTLABEL(0, 15, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
- route_label = RT_LABEL(0, 16, 0);
+ route_label = MTP3_RTLABEL(0, 16, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
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, false, "a");
- route_label = RT_LABEL(0, 12, 0);
+ route_label = MTP3_RTLABEL(0, 12, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt12);
- route_label = RT_LABEL(0, 15, 0);
+ route_label = MTP3_RTLABEL(0, 15, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt);
- route_label = RT_LABEL(0, 16, 0);
+ route_label = MTP3_RTLABEL(0, 16, 0, MTP_SIO(MTP_SI_SCCP, MTP_NI_INTERNATIONAL));
OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rtdef);
ss7_route_destroy(rtdef);
To view, visit change 43844. To unsubscribe, or for help writing mail filters, visit settings.