pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/41949?usp=email )
Change subject: xua: Implement User Part Unavailable HMDT -> HMRT ......................................................................
xua: Implement User Part Unavailable HMDT -> HMRT
Related: OS#6891 Change-Id: Iab2ffc3a86243d5eeedcc4fd3d558796ede9afc3 --- M src/m3ua.c M src/mtp3_hmdt.c M src/sua.c M src/xua_internal.h 4 files changed, 127 insertions(+), 8 deletions(-)
Approvals: pespin: Looks good to me, approved fixeria: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve
diff --git a/src/m3ua.c b/src/m3ua.c index 2b7c1e7..e4173bd 100644 --- a/src/m3ua.c +++ b/src/m3ua.c @@ -910,9 +910,9 @@ }
/* 3.4.5 Destination User Part Unavailable (DUPU) */ -static struct xua_msg *m3ua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx, - uint32_t dpc, uint16_t user, uint16_t cause, - const char *info_string) +struct xua_msg *m3ua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx, + uint32_t dpc, uint16_t user, uint16_t cause, + const char *info_string) { struct xua_msg *xua = xua_msg_alloc(); uint32_t user_cause = (cause << 16) | user; diff --git a/src/mtp3_hmdt.c b/src/mtp3_hmdt.c index a6cf1b3..a844864 100644 --- a/src/mtp3_hmdt.c +++ b/src/mtp3_hmdt.c @@ -23,14 +23,124 @@ * */
+#include <osmocom/core/logging.h> + #include <osmocom/sigtran/protocol/m3ua.h> +#include <osmocom/sigtran/protocol/sua.h> +#include <osmocom/sigtran/osmo_ss7.h> #include <osmocom/sigtran/mtp_sap.h>
+#include "ss7_as.h" #include "ss7_instance.h" +#include "ss7_internal.h" +#include "ss7_route.h" +#include "ss7_route_table.h" #include "ss7_user.h" #include "xua_internal.h" #include "xua_msg.h"
+/* Generate a DUPU message to be sent back to originator. */ +static struct xua_msg *gen_dupu_ret_msg(enum osmo_ss7_asp_protocol proto, uint8_t user_part, const struct xua_msg *orig_xua) +{ + struct xua_msg *xua; + struct xua_msg_part *rctx_ie; + unsigned int num_rctx = 0; + uint32_t rctx = 0; + const char *info_str = "(Local) User Part Unavailable"; + const uint16_t cause = MTP_UNAVAIL_C_UNKNOWN; + + switch (proto) { + case OSMO_SS7_ASP_PROT_M3UA: + if ((rctx_ie = xua_msg_find_tag(orig_xua, M3UA_IEI_ROUTE_CTX))) { + 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); + 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); + break; + default: + OSMO_ASSERT(0); + } + OSMO_ASSERT(xua); + + xua->mtp = orig_xua->mtp; + xua->mtp.opc = orig_xua->mtp.dpc; + xua->mtp.dpc = orig_xua->mtp.opc; + return xua; +} + +/* ITU Q.704 Figure 25/Q.704 (sheet 2 of 3) "User Part Unavailable HMDT -> HMRT" + * See also ITU Q.704 2.4.2 */ +static int mtp3_hmdt_rx_msg_for_local_unavailable_part(struct osmo_ss7_instance *inst, uint8_t user_part, const struct xua_msg *orig_xua) +{ + 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)) { + /* 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... */ + LOGSS7(inst, LOGL_ERROR, "Rx xUA message from local PC and unavailable part!\n"); + return -1; + } + + /* 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); + 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), + 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)); + 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), + 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)); + return 0; + } + + switch (rt->dest.as->cfg.proto) { + 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), + 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)); + 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), + 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)); + return 0; + default: + LOGSS7(inst, LOGL_ERROR, "DUPU message for ASP of unknown protocol %u\n", + rt->dest.as->cfg.proto); + return 0; + } + + return 0; +}
/* convert from M3UA message to MTP-TRANSFER.ind osmo_mtp_prim */ static struct osmo_mtp_prim *m3ua_to_xfer_ind(struct xua_msg *xua) @@ -86,6 +196,7 @@ struct m3ua_data_hdr *mdh; const struct osmo_ss7_user *osu; uint32_t service_ind; + int rc;
switch (xua->hdr.msg_class) { case M3UA_MSGC_XFER: @@ -116,9 +227,10 @@ if (!osu) { /* "Discard Message" */ LOGSS7(inst, LOGL_NOTICE, "No MTP-User for SI %u\n", service_ind); - /* FIXME: User Part Unavailable HMDT -> HMRT */ + /* User Part Unavailable HMDT -> HMRT */ + rc = mtp3_hmdt_rx_msg_for_local_unavailable_part(inst, service_ind, xua); xua_msg_free(xua); - return -1; + return rc; }
/* "MTP Transfer indication HMDT→L4" */ diff --git a/src/sua.c b/src/sua.c index e81590d..eccecdd 100644 --- a/src/sua.c +++ b/src/sua.c @@ -886,9 +886,9 @@ }
/* 3.4.5 Destination User Part Unavailable (DUPU) */ -static struct xua_msg *sua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx, - uint32_t dpc, uint16_t user, uint16_t cause, - const char *info_string) +struct xua_msg *sua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx, + uint32_t dpc, uint16_t user, uint16_t cause, + const char *info_string) { struct xua_msg *xua = xua_msg_alloc(); uint32_t user_cause = (user << 16) | cause; diff --git a/src/xua_internal.h b/src/xua_internal.h index 8674ef5..c5bd009 100644 --- a/src/xua_internal.h +++ b/src/xua_internal.h @@ -37,6 +37,10 @@ void sua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx, uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str);
+struct xua_msg *sua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx, + uint32_t dpc, uint16_t user, uint16_t cause, + const char *info_string); + struct xua_msg *sua_gen_cldr(const struct xua_msg *xua_in, uint32_t route_ctx, uint32_t ret_cause);
struct msgb *m3ua_to_msg(struct xua_msg *xua); @@ -56,6 +60,9 @@ struct xua_msg *m3ua_encode_duna(const uint32_t *rctx, unsigned int num_rctx, const uint32_t *aff_pc, unsigned int num_aff_pc, const char *info_string); +struct xua_msg *m3ua_encode_dupu(const uint32_t *rctx, unsigned int num_rctx, + uint32_t dpc, uint16_t user, uint16_t cause, + const char *info_string);
void xua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx, const uint32_t *aff_pc, unsigned int num_aff_pc,