pespin submitted this change.
mtp: Support MTP-TRANSFER.req/ind of raw IPA messages
This is needed ie. in SCCPLite, where MGCP and CTRL messages need to be
sent/received over the same IPA multiplex TCP conn as the SCCPLite
(SCCP/IPA) one towards a given MSC.
Prior to this, osmo-bsc-sccplite was doing lots of manual
libosmo-sigtran APIs to obtain a route, an AS, and ASP, sending over an
ASP, etc. Similary, the rx_unknown callback was added to libosmo-sigtran
to hook into the ASP level. Tons of stuff which should really be done
properly inside libosmo-sigtran and provided over the existing public
SAPs, as this patch proposes.
With the proposed approach, an SCCPLite client (eg. osmo-bsc), besides
setting up an sccp_user to handle SCCP, also sets an ss7_user (MTP SAP)
with the newly introduced new Service Indicator (SI) MTP_SI_NI11_OSMO_IPA
to be able to manage the IPA[MGCP/CTRL] traffic towards a given MTP peer
(SCCPLite client, ie. MSC).
The new Service Indicator (SI) MTP_SI_NI11_OSMO_IPA is added with a
value of 0x02 (reserved in specs) to avoid collision with existing
protocols even if NI=International is used.
Ideally, from conceptual point of view when using SCCPLite one would
configure an ss7 instance with NI=National, or even better
NI=Spare-National, since that SI doesn't exist in International networks.
In practice, it doesn't matter much since this SI is the end only used
in IPA ASP, which are not really standarized, and the SI is not even
transmitted through the wire with IPA, hence it's only a matter of
local configuration.
At an SGP (STP), the changes included in this commit also allow now
routing of IPA frames (other than SCCP), which are routed based on
ASP/AS routing configuration. This means now one could envision having
an SCCPlite BSC connected to an SCCPlite MSC using an STP in between.
Related: SYS#6880
Change-Id: I9fedb26ccd3434fc7f272feb3c45cf4bdb80c7ae
---
M TODO-RELEASE
M include/osmocom/sigtran/protocol/mtp.h
M src/ipa.c
3 files changed, 67 insertions(+), 31 deletions(-)
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 8a42b9c..b83fbf9 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -13,3 +13,4 @@
libosmo-sigtran add osmo_ss7_user_mtp_sap_prim_down()
libosmo-sigtran add osmo_mtp_prim_xfer_req_prepend()
libosmo-sigtran add osmo_ss7_user_find_by_si()
+libosmo-sigtran add MTP_SI_NI11_OSMO_IPA
diff --git a/include/osmocom/sigtran/protocol/mtp.h b/include/osmocom/sigtran/protocol/mtp.h
index 21e3d60..c0a1230 100644
--- a/include/osmocom/sigtran/protocol/mtp.h
+++ b/include/osmocom/sigtran/protocol/mtp.h
@@ -23,6 +23,18 @@
};
extern const struct value_string mtp_si_vals[];
+/* Q.704 14.2.2: "In the case of only one national signalling network the spare code of the
+ * network indicator reserved for national use can be used, for example, to define an additional
+ * 16 User Parts (making a total of 32 User Parts) for that national signalling network."
+ * Hence, we keep service indicators for Network Indicator "International network" (00) the same
+ * as for "National network" (10), and use "Reserved for national use" to specify extension
+ * service indicators.
+ * Note we pick enum values reserved in NI00 above in order to allow forming a
+ * superset so it can still be used with other NI values. */
+enum mtp_si_ni11 {
+ MTP_SI_NI11_OSMO_IPA = 2, /* Contains an IPA header + payload */
+};
+
/* Q.704 14.2.2 Sub-service field (Network Indicator) */
enum mtp_network_indicator {
MTP_NI_INTERNATIONAL = 0,
diff --git a/src/ipa.c b/src/ipa.c
index 4c197ff..2e74414 100644
--- a/src/ipa.c
+++ b/src/ipa.c
@@ -81,28 +81,39 @@
return NULL;
data_hdr = (struct m3ua_data_hdr *) data_ie->dat;
- if (data_hdr->si != MTP_SI_SCCP) {
- LOGP(DLSS7, LOGL_ERROR, "Cannot transmit non-SCCP SI (%u) to IPA peer\n",
- data_hdr->si);
- return NULL;
- }
-
/* and even the data part still has the header prepended */
src = data_ie->dat + sizeof(struct m3ua_data_hdr);
src_len = data_ie->len - sizeof(struct m3ua_data_hdr);
- /* sufficient headroom for osmo_ipa_msg_push_header() */
- msg = ipa_msg_alloc(16);
- if (!msg)
+ if (src_len == 0) {
+ LOGP(DLSS7, LOGL_NOTICE, "Discarding Tx empty IPA msg/payload\n");
return NULL;
+ }
- dst = msgb_put(msg, src_len);
- memcpy(dst, src, src_len);
-
- /* TODO: if we ever need something beyond SCCP, we can use the
- * M3UA SIO to determine the protocol */
- osmo_ipa_msg_push_header(msg, IPAC_PROTO_SCCP);
- return msg;
+ switch (data_hdr->si) {
+ case MTP_SI_SCCP:
+ /* sufficient headroom for osmo_ipa_msg_push_header() */
+ msg = ipa_msg_alloc(16);
+ if (!msg)
+ return NULL;
+ dst = msgb_put(msg, src_len);
+ memcpy(dst, src, src_len);
+ osmo_ipa_msg_push_header(msg, IPAC_PROTO_SCCP);
+ return msg;
+ case MTP_SI_NI11_OSMO_IPA:
+ /* Process our SI extension: full IPA with hdr + payload, used in SCCPlite
+ * between BSC and MSC to send MGCP and CTRL over IPA multiplex */
+ msg = msgb_alloc(src_len, "MTP_SI_NI11_OSMO_IPA");
+ if (!msg)
+ return NULL;
+ dst = msgb_put(msg, src_len);
+ memcpy(dst, src, src_len);
+ return msg;
+ default:
+ LOGP(DLSS7, LOGL_ERROR, "Cannot transmit non-SCCP SI (%u) to IPA peer\n",
+ data_hdr->si);
+ return NULL;
+ }
}
/*! \brief Send a given xUA message via a given IPA "Application Server"
@@ -229,9 +240,12 @@
return sccp_msg_out;
}
-static int ipa_rx_msg_sccp(struct osmo_ss7_asp *asp, struct msgb *msg, uint8_t sls)
+/* Received an IPA frame containing either SCCP, MGCP or CTRL over the IPA multiplex.
+ * All those are either forwarded (routing) or locally distributed up the stack to an MTP User. */
+static int ipa_rx_msg_up(struct osmo_ss7_asp *asp, struct msgb *msg, uint8_t sls)
{
int rc;
+ enum ipaccess_proto ipa_proto = osmo_ipa_msgb_cb_proto(msg);
struct m3ua_data_hdr data_hdr;
struct xua_msg *xua = NULL;
struct osmo_ss7_as *as = ipa_find_as_for_asp(asp);
@@ -295,23 +309,34 @@
/* Second, create a MTP3/M3UA label with those point codes */
memset(&data_hdr, 0, sizeof(data_hdr));
- data_hdr.si = MTP_SI_SCCP;
data_hdr.opc = osmo_htonl(opc);
data_hdr.dpc = osmo_htonl(dpc);
data_hdr.sls = sls;
data_hdr.ni = as->inst->cfg.network_indicator;
- /* Third, patch this into the SCCP message and create M3UA message in XUA structure */
- if (as->cfg.pc_override.sccp_mode == OSMO_SS7_PATCH_BOTH) {
- struct msgb *msg_patched = patch_sccp_with_pc(asp, msg, opc, dpc);
- if (!msg_patched) {
- LOGPASP(asp, DLSS7, LOGL_ERROR, "Unable to patch PC into SCCP message; dropping\n");
- return -1;
+ switch (ipa_proto) {
+ case IPAC_PROTO_SCCP:
+ /* Third, patch this into the SCCP message and create M3UA message in XUA structure */
+ data_hdr.si = MTP_SI_SCCP;
+ if (as->cfg.pc_override.sccp_mode == OSMO_SS7_PATCH_BOTH) {
+ struct msgb *msg_patched = patch_sccp_with_pc(asp, msg, opc, dpc);
+ if (!msg_patched) {
+ LOGPASP(asp, DLSS7, LOGL_ERROR, "Unable to patch PC into SCCP message; dropping\n");
+ return -1;
+ }
+ xua = m3ua_xfer_from_data(&data_hdr, msgb_data(msg_patched), msgb_length(msg_patched));
+ msgb_free(msg_patched);
+ } else {
+ xua = m3ua_xfer_from_data(&data_hdr, msgb_data(msg), msgb_length(msg));
}
- xua = m3ua_xfer_from_data(&data_hdr, msgb_data(msg_patched), msgb_length(msg_patched));
- msgb_free(msg_patched);
- } else {
+ break;
+ default:
+ /* Submit IPA headers+payload is up the stack so MTP-USER can receive it. This is useful to
+ * obtain MGCP/CTRL proto payloads from the SCCPLite IPA multiplex. */
+ data_hdr.si = MTP_SI_NI11_OSMO_IPA;
+ osmo_ipa_msg_push_headers(msg, ipa_proto, osmo_ipa_msgb_cb_proto_ext(msg));
xua = m3ua_xfer_from_data(&data_hdr, msgb_data(msg), msgb_length(msg));
+ break;
}
/* Update xua->mtp with values from data_hdr */
@@ -342,11 +367,9 @@
case IPAC_PROTO_IPACCESS:
rc = ipa_rx_msg_ccm(asp, msg);
break;
- case IPAC_PROTO_SCCP:
- rc = ipa_rx_msg_sccp(asp, msg, sls);
- break;
default:
- rc = ss7_asp_rx_unknown(asp, osmo_ipa_msgb_cb_proto(msg), msg);
+ rc = ipa_rx_msg_up(asp, msg, sls);
+ break;
}
return rc;
To view, visit change 41410. To unsubscribe, or for help writing mail filters, visit settings.