aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-02-08 13:10:17 +0100
committerHarald Welte <laforge@osmocom.org>2021-02-10 19:56:03 +0100
commit0d53666108318435391de2696ba88d277e2b4211 (patch)
treed5f0534f9939413785e66ec2d37f6c58b3d5aed7
parentbf85d6f433e5d1d24a3cb7f212f6bfb65988d609 (diff)
sua: per-ssn DUNA/DAVA notification
Unlike M3UA, in SUA a DUNA/DAVA message can contain not just the point code that became available / unavailable, but it can also include a SSN. In that case, it is just the SSN that became available/unavailable, and not the entire point code. Hence, a N-STATE.ind and not a N-PCSTATE.ind must be delivered to the SCCP user. Change-Id: Ie9a45b905bc17e7b695e15fe12ba4bbadcd032bf
-rw-r--r--src/sccp_internal.h2
-rw-r--r--src/sccp_scmg.c39
-rw-r--r--src/xua_snm.c81
3 files changed, 120 insertions, 2 deletions
diff --git a/src/sccp_internal.h b/src/sccp_internal.h
index 6bd2af9..a95b07d 100644
--- a/src/sccp_internal.h
+++ b/src/sccp_internal.h
@@ -137,6 +137,8 @@ void sccp_lbcs_local_bcast_state(struct osmo_sccp_instance *inst,
const struct osmo_scu_state_param *state);
/* SCCP Management (SCMG) */
+void sccp_scmg_rx_ssn_allowed(struct osmo_sccp_instance *inst, uint32_t dpc, uint32_t ssn, uint32_t smi);
+void sccp_scmg_rx_ssn_prohibited(struct osmo_sccp_instance *inst, uint32_t dpc, uint32_t ssn, uint32_t smi);
void sccp_scmg_rx_mtp_pause(struct osmo_sccp_instance *inst, uint32_t dpc);
void sccp_scmg_rx_mtp_resume(struct osmo_sccp_instance *inst, uint32_t dpc);
int sccp_scmg_init(struct osmo_sccp_instance *inst);
diff --git a/src/sccp_scmg.c b/src/sccp_scmg.c
index 0e3905d..ed16fe7 100644
--- a/src/sccp_scmg.c
+++ b/src/sccp_scmg.c
@@ -36,6 +36,45 @@
#include "xua_internal.h"
#include "sccp_internal.h"
+/* ITU-T Q.714 5.3.3 Subsystem allowed */
+void sccp_scmg_rx_ssn_allowed(struct osmo_sccp_instance *inst, uint32_t dpc, uint32_t ssn, uint32_t smi)
+{
+ struct osmo_scu_state_param state;
+ /* 1) Instruct the translation function to update the translation tables */
+ /* 2) Mark as "allowed" the status of that subsystem. */
+ /* 3) Initiate a local broadcast of "User-in-service" information for the allowed subsystem */
+ state = (struct osmo_scu_state_param) {
+ .affected_pc = dpc,
+ .affected_ssn = ssn,
+ .user_in_service = true,
+ .ssn_multiplicity_ind = smi,
+ };
+ sccp_lbcs_local_bcast_state(inst, &state);
+ /* 4) Discontinue the subsystem status test if such a test was in progress */
+ /* 5) Initiate a broadcast of Subsystem-Allowed messages to concerned signalling points. */
+}
+
+/* ITU-T Q.714 5.3.2 Subsystem prohibited */
+void sccp_scmg_rx_ssn_prohibited(struct osmo_sccp_instance *inst, uint32_t dpc, uint32_t ssn, uint32_t smi)
+{
+ struct osmo_scu_state_param state;
+ /* 1) instruct the translation function to update the translation tables */
+ /* 2) mark as "prohibited" the status of that subsystem */
+ /* 3) initiate a local broadcast of "User-out-of-service" information */
+ state = (struct osmo_scu_state_param) {
+ .affected_pc = dpc,
+ .affected_ssn = ssn,
+ .user_in_service = false,
+ .ssn_multiplicity_ind = smi,
+ };
+ sccp_lbcs_local_bcast_state(inst, &state);
+
+ /* 4) initiate the subsystem status test procedure if the prohibited subsystem is not local */
+ /* 5) initiate a broadcast of Subsystem-Prohibited messages to concerned SP */
+ /* 6) cancel "ignore subsystem status test" and the associated timer if in progress and if
+ * the newly prohibited subsystem resides at the local node. */
+}
+
/*! brief MTP -> SNM (MTP-PAUSE.ind) - inability to providing MTP service Q.714 5.2.2 */
void sccp_scmg_rx_mtp_pause(struct osmo_sccp_instance *inst, uint32_t dpc)
{
diff --git a/src/xua_snm.c b/src/xua_snm.c
index e3efc8e..2a383c7 100644
--- a/src/xua_snm.c
+++ b/src/xua_snm.c
@@ -162,6 +162,53 @@ void xua_snm_pc_available(struct osmo_ss7_as *as, const uint32_t *aff_pc,
}
}
+/* generate SS-PROHIBITED / SS-ALLOWED towards local SCCP users */
+static void sua_snm_ssn_available_to_sccp(struct osmo_sccp_instance *sccp, uint32_t aff_pc,
+ uint32_t aff_ssn, uint32_t smi, bool available)
+{
+ if (available)
+ sccp_scmg_rx_ssn_allowed(sccp, aff_pc, aff_ssn, smi);
+ else
+ sccp_scmg_rx_ssn_prohibited(sccp, aff_pc, aff_ssn, smi);
+}
+
+/* advertise availability of a single subsystem */
+static void sua_snm_ssn_available(struct osmo_ss7_as *as, uint32_t aff_pc, uint32_t aff_ssn,
+ const uint32_t *smi, const char *info_str, bool available)
+{
+ struct osmo_ss7_instance *s7i = as->inst;
+ struct osmo_ss7_asp *asp;
+ uint32_t rctx[32];
+ unsigned int num_rctx;
+ uint32_t _smi = smi ? *smi : 0; /* 0 == reserved/unknown in SUA */
+
+ if (s7i->sccp)
+ sua_snm_ssn_available_to_sccp(s7i->sccp, aff_pc, aff_ssn, _smi, available);
+
+ /* inform remote SUA ASPs via DUNA/DAVA */
+ llist_for_each_entry(asp, &s7i->asp_list, list) {
+ /* SSNM is only permitted for ASPs in ACTIVE state */
+ if (!osmo_ss7_asp_active(asp))
+ continue;
+
+ /* only send DAVA/DUNA if we locally are the SG and the remote is ASP */
+ if (asp->cfg.role != OSMO_SS7_ASP_ROLE_SG)
+ continue;
+
+ /* DUNA/DAVA for SSN only exists in SUA */
+ if (asp->cfg.proto != OSMO_SS7_ASP_PROT_SUA)
+ continue;
+
+ num_rctx = get_all_rctx_for_asp(rctx, ARRAY_SIZE(rctx), asp, as);
+ /* this can happen if the given ASP is only in the AS that reports the change,
+ * which shall be excluded */
+ if (num_rctx == 0)
+ continue;
+ sua_tx_snm_available(asp, rctx, num_rctx, &aff_pc, 1, &aff_ssn, smi, info_str, available);
+ }
+}
+
+
/* receive DAUD from ASP; pc is 'affected PC' IE with mask in network byte order! */
void xua_snm_rx_daud(struct osmo_ss7_asp *asp, struct xua_msg *xua)
{
@@ -211,6 +258,7 @@ void xua_snm_rx_daud(struct osmo_ss7_asp *asp, struct xua_msg *xua)
void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua)
{
struct xua_msg_part *ie_aff_pc = xua_msg_find_tag(xua, M3UA_IEI_AFFECTED_PC);
+ struct xua_msg_part *ie_ssn = xua_msg_find_tag(xua, SUA_IEI_SSN);
const char *info_str = xua_msg_get_str(xua, M3UA_IEI_INFO_STRING);
/* TODO: should our processing depend on the RCTX included? I somehow don't think so */
//struct xua_msg_part *ie_rctx = xua_msg_find_tag(xua, M3UA_IEI_ROUTE_CTX);
@@ -224,13 +272,28 @@ void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xu
LOGPASP(asp, log_ss, LOGL_NOTICE, "Rx DUNA(%s) for %s\n", info_str ? info_str : "",
format_affected_pcs_c(xua, asp->inst, ie_aff_pc));
- xua_snm_pc_available(as, (const uint32_t *)ie_aff_pc->dat, ie_aff_pc->len/4, info_str, false);
+ if (asp->cfg.proto == OSMO_SS7_ASP_PROT_SUA && ie_ssn) {
+ /* when the SSN is included, DUNA corresponds to the SCCP N-STATE primitive */
+ uint32_t ssn = xua_msg_part_get_u32(ie_ssn);
+ const uint32_t *aff_pc = (const uint32_t *)ie_aff_pc->dat;
+ uint32_t pc, smi;
+ /* The Affected Point Code can only contain one point code when SSN is present */
+ if (ie_aff_pc->len/sizeof(uint32_t) != 1)
+ return;
+ pc = ntohl(aff_pc[0]) & 0xffffff;
+ sua_snm_ssn_available(as, pc, ssn, xua_msg_get_u32p(xua, SUA_IEI_SMI, &smi), info_str, false);
+ } else {
+ /* when the SSN is not included, DUNA corresponds to the SCCP N-PCSTATE primitive */
+ xua_snm_pc_available(as, (const uint32_t *)ie_aff_pc->dat,
+ ie_aff_pc->len / sizeof(uint32_t), info_str, false);
+ }
}
/* an incoming xUA DAVA was received from a remote SG */
void xua_snm_rx_dava(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua)
{
struct xua_msg_part *ie_aff_pc = xua_msg_find_tag(xua, M3UA_IEI_AFFECTED_PC);
+ struct xua_msg_part *ie_ssn = xua_msg_find_tag(xua, SUA_IEI_SSN);
const char *info_str = xua_msg_get_str(xua, M3UA_IEI_INFO_STRING);
/* TODO: should our processing depend on the RCTX included? I somehow don't think so */
//struct xua_msg_part *ie_rctx = xua_msg_find_tag(xua, M3UA_IEI_ROUTE_CTX);
@@ -244,5 +307,19 @@ void xua_snm_rx_dava(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xu
LOGPASP(asp, log_ss, LOGL_NOTICE, "Rx DAVA(%s) for %s\n", info_str ? info_str : "",
format_affected_pcs_c(xua, asp->inst, ie_aff_pc));
- xua_snm_pc_available(as, (const uint32_t *)ie_aff_pc->dat, ie_aff_pc->len/4, info_str, true);
+ if (asp->cfg.proto == OSMO_SS7_ASP_PROT_SUA && ie_ssn) {
+ /* when the SSN is included, DAVA corresponds to the SCCP N-STATE primitive */
+ uint32_t ssn = xua_msg_part_get_u32(ie_ssn);
+ const uint32_t *aff_pc = (const uint32_t *)ie_aff_pc->dat;
+ uint32_t pc, smi;
+ /* The Affected Point Code can only contain one point code when SSN is present */
+ if (ie_aff_pc->len/sizeof(uint32_t) != 1)
+ return;
+ pc = ntohl(aff_pc[0]) & 0xffffff;
+ sua_snm_ssn_available(as, pc, ssn, xua_msg_get_u32p(xua, SUA_IEI_SMI, &smi), info_str, true);
+ } else {
+ /* when the SSN is not included, DAVA corresponds to the SCCP N-PCSTATE primitive */
+ xua_snm_pc_available(as, (const uint32_t *)ie_aff_pc->dat,
+ ie_aff_pc->len / sizeof(uint32_t), info_str, true);
+ }
}