pespin has uploaded this change for review.
xUA: Handle rx multiple Routing Context in SNM messages
All those messages can contain multiple routing contexts inside the
Routing Context IE according to both M3UA and SUA specs.
Make sure all the Routing Contexts are validated and processed.
Change-Id: I9ef1e343e95961d497f55e4a512068d3e7585a0c
---
M src/m3ua.c
M src/sua.c
M src/xua_internal.h
M src/xua_shared.c
M src/xua_snm.c
5 files changed, 167 insertions(+), 72 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/26/43226/1
diff --git a/src/m3ua.c b/src/m3ua.c
index f2455eb..a7b7aee 100644
--- a/src/m3ua.c
+++ b/src/m3ua.c
@@ -1045,27 +1045,28 @@
* xua is owned by parent call m3ua_rx_snm() */
static int m3ua_rx_snm_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
{
- struct osmo_ss7_as *as = NULL;
+ struct osmo_ss7_as *as_array[OSMO_SS7_MAX_RCTX_COUNT];
+ unsigned int as_count = 0;
struct xua_msg_part *rctx_ie = xua_msg_find_tag(xua, M3UA_IEI_ROUTE_CTX);
int rc;
- rc = xua_find_as_for_asp(&as, asp, rctx_ie);
+ rc = xua_find_multiple_as_for_asp(&as_array[0], &as_count, ARRAY_SIZE(as_array), asp, rctx_ie);
if (rc)
return rc;
/* report those up the stack so both other ASPs and local SCCP users can be notified */
switch (xua->hdr.msg_type) {
case M3UA_SNM_DUNA:
- xua_snm_rx_duna(asp, as, xua);
+ xua_snm_rx_duna(asp, as_array, as_count, xua);
break;
case M3UA_SNM_DAVA:
- xua_snm_rx_dava(asp, as, xua);
+ xua_snm_rx_dava(asp, as_array, as_count, xua);
break;
case M3UA_SNM_DUPU:
- xua_snm_rx_dupu(asp, as, xua);
+ xua_snm_rx_dupu(asp, as_array, as_count, xua);
break;
case M3UA_SNM_SCON:
- xua_snm_rx_scon(asp, as, xua);
+ xua_snm_rx_scon(asp, as_array, as_count, xua);
break;
case M3UA_SNM_DRST:
LOGPASP(asp, DLM3UA, LOGL_NOTICE, "Received unsupported M3UA SNM message type %u\n",
@@ -1097,7 +1098,8 @@
* xua is owned by parent call m3ua_rx_snm() */
static int m3ua_rx_snm_sg(struct osmo_ss7_asp *asp, struct xua_msg *xua)
{
- struct osmo_ss7_as *as = NULL;
+ struct osmo_ss7_as *as_array[OSMO_SS7_MAX_RCTX_COUNT];
+ unsigned int as_count = 0;
struct xua_msg_part *rctx_ie;
int rc = 0;
@@ -1109,10 +1111,10 @@
* to an M3UA peer, indicating that the congestion level of the M3UA layer or the
* ASP has changed.*/
rctx_ie = xua_msg_find_tag(xua, M3UA_IEI_ROUTE_CTX);
- rc = xua_find_as_for_asp(&as, asp, rctx_ie);
+ rc = xua_find_multiple_as_for_asp(&as_array[0], &as_count, ARRAY_SIZE(as_array), asp, rctx_ie);
if (rc)
return rc;
- xua_snm_rx_scon(asp, as, xua);
+ xua_snm_rx_scon(asp, as_array, as_count, xua);
break;
case M3UA_SNM_DAUD:
/* Audit: ASP inquires about availability of Point Codes */
@@ -1131,7 +1133,8 @@
* xua is owned by parent call m3ua_rx_snm() */
static int m3ua_rx_snm_ipsp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
{
- struct osmo_ss7_as *as = NULL;
+ struct osmo_ss7_as *as_array[OSMO_SS7_MAX_RCTX_COUNT];
+ unsigned int as_count = 0;
struct xua_msg_part *rctx_ie;
int rc = 0;
@@ -1142,10 +1145,10 @@
* An IPSP can only be connected against another IPSP, hence if an IPSP can send
* an SCON, it can be derived that it is expected it can receive it: */
rctx_ie = xua_msg_find_tag(xua, M3UA_IEI_ROUTE_CTX);
- rc = xua_find_as_for_asp(&as, asp, rctx_ie);
+ rc = xua_find_multiple_as_for_asp(&as_array[0], &as_count, ARRAY_SIZE(as_array), asp, rctx_ie);
if (rc)
return rc;
- xua_snm_rx_scon(asp, as, xua);
+ xua_snm_rx_scon(asp, as_array, as_count, xua);
break;
case M3UA_SNM_DAUD:
/* RFC states only permitted in ASP->SG direction, not reverse nor IPSP. But some
diff --git a/src/sua.c b/src/sua.c
index f5dcd66..30a2694 100644
--- a/src/sua.c
+++ b/src/sua.c
@@ -991,26 +991,27 @@
/* received SNM message on ASP side */
static int sua_rx_snm_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
{
- struct osmo_ss7_as *as = NULL;
+ struct osmo_ss7_as *as_array[OSMO_SS7_MAX_RCTX_COUNT];
+ unsigned int as_count = 0;
struct xua_msg_part *rctx_ie = xua_msg_find_tag(xua, SUA_IEI_ROUTE_CTX);
int rc;
- rc = xua_find_as_for_asp(&as, asp, rctx_ie);
+ rc = xua_find_multiple_as_for_asp(&as_array[0], &as_count, ARRAY_SIZE(as_array), asp, rctx_ie);
if (rc)
return rc;
switch (xua->hdr.msg_type) {
case SUA_SNM_DUNA:
- xua_snm_rx_duna(asp, as, xua);
+ xua_snm_rx_duna(asp, as_array, as_count, xua);
break;
case SUA_SNM_DAVA:
- xua_snm_rx_dava(asp, as, xua);
+ xua_snm_rx_dava(asp, as_array, as_count, xua);
break;
case SUA_SNM_DUPU:
- xua_snm_rx_dupu(asp, as, xua);
+ xua_snm_rx_dupu(asp, as_array, as_count, xua);
break;
case SUA_SNM_SCON:
- xua_snm_rx_scon(asp, as, xua);
+ xua_snm_rx_scon(asp, as_array, as_count, xua);
break;
case SUA_SNM_DRST:
LOGPASP(asp, DLSUA, LOGL_NOTICE, "Received unsupported SUA SNM message type %u\n",
@@ -1041,7 +1042,8 @@
/* received SNM message on SG side */
static int sua_rx_snm_sg(struct osmo_ss7_asp *asp, struct xua_msg *xua)
{
- struct osmo_ss7_as *as = NULL;
+ struct osmo_ss7_as *as_array[OSMO_SS7_MAX_RCTX_COUNT];
+ unsigned int as_count = 0;
struct xua_msg_part *rctx_ie;
int rc = 0;
@@ -1050,10 +1052,11 @@
/* RFC3868 1.5.6: "The SUA layer at an ASP or IPSP MAY indicate local congestion to
* an SUA peer with an SCON message." */
rctx_ie = xua_msg_find_tag(xua, SUA_IEI_ROUTE_CTX);
- rc = xua_find_as_for_asp(&as, asp, rctx_ie);
+ rc = xua_find_multiple_as_for_asp(&as_array[0], &as_count, ARRAY_SIZE(as_array), asp, rctx_ie);
+
if (rc)
return rc;
- xua_snm_rx_scon(asp, as, xua);
+ xua_snm_rx_scon(asp, as_array, as_count, xua);
break;
case SUA_SNM_DAUD: /* Audit: ASP inquires about availability of Point Codes */
xua_snm_rx_daud(asp, xua);
@@ -1070,7 +1073,8 @@
/* received SNM message on IPSP side */
static int sua_rx_snm_ipsp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
{
- struct osmo_ss7_as *as = NULL;
+ struct osmo_ss7_as *as_array[OSMO_SS7_MAX_RCTX_COUNT];
+ unsigned int as_count = 0;
struct xua_msg_part *rctx_ie;
int rc = 0;
@@ -1079,10 +1083,10 @@
/* RFC3868 1.5.6: "The SUA layer at an ASP or IPSP MAY indicate local congestion to
* an SUA peer with an SCON message." */
rctx_ie = xua_msg_find_tag(xua, SUA_IEI_ROUTE_CTX);
- rc = xua_find_as_for_asp(&as, asp, rctx_ie);
+ rc = xua_find_multiple_as_for_asp(&as_array[0], &as_count, ARRAY_SIZE(as_array), asp, rctx_ie);
if (rc)
return rc;
- xua_snm_rx_scon(asp, as, xua);
+ xua_snm_rx_scon(asp, as_array, as_count, xua);
break;
case SUA_SNM_DAUD:
/* RFC states only permitted in ASP->SG direction, not reverse nor IPSP. But some
diff --git a/src/xua_internal.h b/src/xua_internal.h
index 0317669..5b9e48b 100644
--- a/src/xua_internal.h
+++ b/src/xua_internal.h
@@ -69,10 +69,10 @@
const char *info_str, bool available);
void xua_snm_rx_daud(struct osmo_ss7_asp *asp, const struct xua_msg *xua);
-void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, const struct xua_msg *xua);
-void xua_snm_rx_dava(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, const struct xua_msg *xua);
-void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, const struct xua_msg *xua);
-void xua_snm_rx_scon(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, const struct xua_msg *xua);
+void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as[], unsigned int as_count, const struct xua_msg *xua);
+void xua_snm_rx_dava(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as[], unsigned int as_count, const struct xua_msg *xua);
+void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as[], unsigned int as_count, const struct xua_msg *xua);
+void xua_snm_rx_scon(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as[], unsigned int as_count, const struct xua_msg *xua);
int m3ua_rx_msg(struct osmo_ss7_asp *asp, struct msgb *msg);
struct msgb *m3ua_msgb_alloc(const char *name);
@@ -134,6 +134,11 @@
int xua_find_as_for_asp(struct osmo_ss7_as **as, const struct osmo_ss7_asp *asp,
const struct xua_msg_part *rctx_ie);
+int xua_find_multiple_as_for_asp(struct osmo_ss7_as **as_array,
+ unsigned int *as_array_count,
+ unsigned int as_array_len,
+ const struct osmo_ss7_asp *asp,
+ const struct xua_msg_part *rctx_ie);
struct msgb *ipa_gen_ping(void);
struct msgb *ipa_to_msg(struct xua_msg *xua);
diff --git a/src/xua_shared.c b/src/xua_shared.c
index 53b7337..4051287 100644
--- a/src/xua_shared.c
+++ b/src/xua_shared.c
@@ -43,46 +43,123 @@
osmo_static_assert(M3UA_ERR_INVAL_ROUT_CTX == SUA_ERR_INVAL_ROUT_CTX, _err_rctx);
osmo_static_assert(M3UA_ERR_NO_CONFGD_AS_FOR_ASP == SUA_ERR_NO_CONFGD_AS_FOR_ASP, _err_as_for_asp);
osmo_static_assert(M3UA_ERR_PARAM_FIELD_ERR == SUA_ERR_PARAM_FIELD_ERR, _err_param_field_err);
+osmo_static_assert(M3UA_ERR_UNEXP_PARAM == SUA_ERR_UNEXP_PARAM, _err_unexp_param);
-/*! Find the AS for given ASP + optional routing context IE.
- * if rctx_ie == NULL, we assume that this ASP is only part of a single AS;
- * if rctx_ie is given, then we look-up the ASP based on the routing context,
- * and verify that this ASP is part of it.
- * \param[out] as caller-provided address-of-pointer to store the found AS
- * \param[in] asp ASP for which we want to look-up the AS
- * \param[in] rctx_ie routing context IE (may be NULL) to use for look-up
- * \returns 0 in case of success; {M3UA,SUA}_ERR_* code in case of error. */
-int xua_find_as_for_asp(struct osmo_ss7_as **as, const struct osmo_ss7_asp *asp,
- const struct xua_msg_part *rctx_ie)
+static int xua_find_as_for_asp_no_rctx(struct osmo_ss7_as **as, const struct osmo_ss7_asp *asp)
{
int log_ss = osmo_ss7_asp_get_log_subsys(asp);
*as = NULL;
+ if (asp->num_assoc_as != 1) {
+ LOGPASP(asp, log_ss, LOGL_ERROR,
+ "%s(): ASP sent M3UA without Routing Context IE but unable to uniquely "
+ "identify the AS for this message\n", __func__);
+ return M3UA_ERR_INVAL_ROUT_CTX;
+ }
+ *as = ss7_asp_get_first_as(asp);
+ return 0;
+}
+/*! Find the AS for given ASP + optional routing context IE.
+ *
+ * \param[out] as caller-provided address-of-pointer to store the found AS
+ * \param[in] asp ASP for which we want to look-up the AS
+ * \param[in] rctx_ie routing context IE (may be NULL) to use for look-up
+ * \returns 0 in case of success; {M3UA,SUA}_ERR_* code in case of error.
+ *
+ * if rctx_ie == NULL, we assume that this ASP is only part of a single AS;
+ * if rctx_ie is given, then we look-up the AS on the ASP based on the routing context.
+ */
+int xua_find_as_for_asp(struct osmo_ss7_as **as, const struct osmo_ss7_asp *asp,
+ const struct xua_msg_part *rctx_ie)
+{
+ int log_ss;
- if (rctx_ie) {
- if (rctx_ie->len < 4) {
- LOGPASP(asp, log_ss, LOGL_ERROR, "%s(): Received Routing Context with len < 4\n", __func__);
- return M3UA_ERR_PARAM_FIELD_ERR;
- }
- /* Use routing context IE to look up the AS for which the
- * message was received. */
- uint32_t rctx = xua_msg_part_get_u32(rctx_ie);
- *as = ss7_asp_find_as_by_rctx(asp, rctx);
- if (!*as) {
+ if (!rctx_ie)
+ return xua_find_as_for_asp_no_rctx(as, asp);
+
+ log_ss = osmo_ss7_asp_get_log_subsys(asp);
+ *as = NULL;
+
+ if (rctx_ie->len < 4) {
+ LOGPASP(asp, log_ss, LOGL_ERROR, "%s(): Received Routing Context with len < 4\n", __func__);
+ return M3UA_ERR_PARAM_FIELD_ERR;
+ }
+ /* Use routing context IE to look up the AS for which the
+ * message was received. */
+ uint32_t rctx = xua_msg_part_get_u32(rctx_ie);
+ *as = ss7_asp_find_as_by_rctx(asp, rctx);
+ if (!*as) {
+ LOGPASP(asp, log_ss, LOGL_ERROR,
+ "%s(): This Application Server Process is not serving any AS with routing context: %u\n",
+ __func__, rctx);
+ return M3UA_ERR_NO_CONFGD_AS_FOR_ASP;
+ }
+ return 0;
+}
+
+/*! Find multiple AS for given ASP + optional routing context IE.
+ * \param[out] as_array caller-provided address of array to store the found ASs.
+ * Usually of OSMO_SS7_MAX_RCTX_COUNT elements.
+ * \param[out] as_array_count filled by the callee, contains number of elements filled in as_array
+ * \param[in] as_array_len caller provided, provides the amount of elements allocated in as_array.
+ * Usually OSMO_SS7_MAX_RCTX_COUNT.
+ * \param[in] asp ASP for which we want to look-up the AS
+ * \param[in] rctx_ie routing context IE (may be NULL) to use for look-up
+ * \returns 0 in case of success; {M3UA,SUA}_ERR_* code in case of error.
+ *
+ * if rctx_ie == NULL, we assume that this ASP is only psart of a single AS;
+ * if rctx_ie is given, then we look-up the ASs on the ASP based on the routing contexts.
+ * This function always returns at least one AS in the as_array if it succeeds.
+ **/
+int xua_find_multiple_as_for_asp(struct osmo_ss7_as **as_array,
+ unsigned int *as_array_count,
+ unsigned int as_array_len,
+ const struct osmo_ss7_asp *asp,
+ const struct xua_msg_part *rctx_ie)
+{
+ int log_ss;
+ unsigned int rctx_count = 0;
+ *as_array_count = 0;
+
+ if (!rctx_ie) {
+ int rc = xua_find_as_for_asp_no_rctx(&as_array[0], asp);
+ if (rc == 0)
+ *as_array_count = 1;
+ return rc;
+ }
+
+ log_ss = osmo_ss7_asp_get_log_subsys(asp);
+
+ if (rctx_ie->len == 0) {
+ LOGPASP(asp, log_ss, LOGL_ERROR, "%s(): Received Routing Context with len 0\n", __func__);
+ return M3UA_ERR_PARAM_FIELD_ERR;
+ }
+
+ if (rctx_ie->len & 0x03) {
+ LOGPASP(asp, log_ss, LOGL_ERROR,
+ "%s(): Received Routing Context IE length non-multiple of 4!\n", __func__);
+ return M3UA_ERR_PARAM_FIELD_ERR;
+ }
+
+ rctx_count = rctx_ie->len >> 2;
+ if (rctx_count > as_array_len) {
+ LOGP(DLM3UA, LOGL_ERROR,
+ "%s(): Received Routing Context IE containing > %u items not supported!\n",
+ __func__, as_array_len);
+ return M3UA_ERR_UNEXP_PARAM;
+ }
+
+ for (unsigned int i = 0; i < rctx_count; i++) {
+ /* Use routing context IE to look up the AS for which the message was received. */
+ uint32_t rctx = ntohl(*(uint32_t *)&rctx_ie->dat[i << 2]);
+
+ as_array[*as_array_count] = ss7_asp_find_as_by_rctx(asp, rctx);
+ if (!as_array[*as_array_count]) {
LOGPASP(asp, log_ss, LOGL_ERROR,
"%s(): This Application Server Process is not serving any AS with routing context: %u\n",
__func__, rctx);
return M3UA_ERR_NO_CONFGD_AS_FOR_ASP;
}
- } else {
- /* no explicit routing context; this only works if there is only one AS in the ASP */
- if (asp->num_assoc_as != 1) {
- LOGPASP(asp, log_ss, LOGL_ERROR,
- "%s(): ASP sent M3UA without Routing Context IE but unable to uniquely "
- "identify the AS for this message\n", __func__);
- return M3UA_ERR_INVAL_ROUT_CTX;
- }
- *as = ss7_asp_get_first_as(asp);
+ (*as_array_count)++;
}
-
return 0;
}
diff --git a/src/xua_snm.c b/src/xua_snm.c
index 03addcf..4520281 100644
--- a/src/xua_snm.c
+++ b/src/xua_snm.c
@@ -487,13 +487,11 @@
}
/* an incoming xUA DUNA was received from a remote SG */
-void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, const struct xua_msg *xua)
+void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as_array[], unsigned int as_count, const 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);
int log_ss = osmo_ss7_asp_get_log_subsys(asp);
OSMO_ASSERT(ie_aff_pc);
@@ -507,20 +505,23 @@
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;
+ const uint32_t *smi_ptr = xua_msg_get_u32p(xua, SUA_IEI_SMI, &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);
+ for (unsigned int i = 0; i < as_count; i++)
+ sua_snm_ssn_available(as_array[i], pc, ssn, smi_ptr, 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);
+ for (unsigned int i = 0; i < as_count; i++)
+ xua_snm_pc_available(as_array[i], (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, const struct xua_msg *xua)
+void xua_snm_rx_dava(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as_array[], unsigned int as_count, const 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);
@@ -540,20 +541,23 @@
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;
+ const uint32_t *smi_ptr = xua_msg_get_u32p(xua, SUA_IEI_SMI, &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);
+ for (unsigned int i = 0; i < as_count; i++)
+ sua_snm_ssn_available(as_array[i], pc, ssn, smi_ptr, 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,
+ for (unsigned int i = 0; i < as_count; i++)
+ xua_snm_pc_available(as_array[i], (const uint32_t *)ie_aff_pc->dat,
ie_aff_pc->len / sizeof(uint32_t), info_str, true);
}
}
/* an incoming SUA/M3UA DUPU was received from a remote SG */
-void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, const struct xua_msg *xua)
+void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as_array[], unsigned int as_count, const struct xua_msg *xua)
{
uint32_t aff_pc = xua_msg_get_u32(xua, M3UA_IEI_AFFECTED_PC);
const char *info_str = xua_msg_get_str(xua, M3UA_IEI_INFO_STRING);
@@ -582,11 +586,12 @@
info_str ? info_str : "", osmo_ss7_pointcode_print(asp->inst, aff_pc),
get_value_string(mtp_si_vals, user), cause);
- xua_snm_upu(as, aff_pc, user, cause, info_str);
+ for (unsigned int i = 0; i < as_count; i++)
+ xua_snm_upu(as_array[i], aff_pc, user, cause, info_str);
}
/* an incoming SUA/M3UA SCON was received from a remote ASP/SG/IPSP */
-void xua_snm_rx_scon(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, const struct xua_msg *xua)
+void xua_snm_rx_scon(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as_array[], unsigned int as_count, const struct xua_msg *xua)
{
struct xua_msg_part *ie_aff_pc = xua_msg_find_tag(xua, M3UA_IEI_AFFECTED_PC);
const char *info_str = xua_msg_get_str(xua, M3UA_IEI_INFO_STRING);
@@ -600,6 +605,7 @@
LOGPASP(asp, log_ss, LOGL_NOTICE, "RX SCON(%s) for %s level=%u\n", info_str ? info_str : "",
format_affected_pcs(asp->inst, ie_aff_pc), cong_level ? *cong_level : 0);
- xua_snm_scon(as, (const uint32_t *) ie_aff_pc->dat, ie_aff_pc->len / sizeof(uint32_t),
- concerned_dpc, (const uint8_t *) cong_level, info_str);
+ for (unsigned int i = 0; i < as_count; i++)
+ xua_snm_scon(as_array[i], (const uint32_t *) ie_aff_pc->dat, ie_aff_pc->len / sizeof(uint32_t),
+ concerned_dpc, (const uint8_t *) cong_level, info_str);
}
To view, visit change 43226. To unsubscribe, or for help writing mail filters, visit settings.