diff options
author | Harald Welte <laforge@osmocom.org> | 2021-02-06 23:21:55 +0100 |
---|---|---|
committer | Harald Welte <laforge@osmocom.org> | 2021-02-08 18:00:56 +0100 |
commit | 943affdd48151dfeca009976dd78db79fb77ca55 (patch) | |
tree | a23bf7616ca06d3c964efbcdf0dec9aab0e6a9e0 | |
parent | 6cb841b92bf1457dd11cba02fca25ce74836d2e5 (diff) |
sccp: Notify users of point code available/unavailable
* add N-PCSTATE.ind and N-STATE.ind definitions to SCCP user SAP
* add minimal SCMG (SCCP Management) and LBCS (Local Broadcast)
* generate MTP-PAUSE.ind/MTP-RESUME.ind based on received xUA DUNA/DAVA
* generate N-PCSTATE.ind towards the local SCCP users
Change-Id: Idb799f7d7ab329ad12f07b7cbe6336da0891ae92
Related: OS#2623, OS#3403, OS#4701
-rw-r--r-- | include/osmocom/sigtran/sccp_sap.h | 33 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/sccp_internal.h | 10 | ||||
-rw-r--r-- | src/sccp_lbcs.c | 68 | ||||
-rw-r--r-- | src/sccp_scmg.c | 83 | ||||
-rw-r--r-- | src/xua_snm.c | 37 |
6 files changed, 233 insertions, 1 deletions
diff --git a/include/osmocom/sigtran/sccp_sap.h b/include/osmocom/sigtran/sccp_sap.h index de9b24c..d741644 100644 --- a/include/osmocom/sigtran/sccp_sap.h +++ b/include/osmocom/sigtran/sccp_sap.h @@ -137,6 +137,21 @@ enum osmo_sccp_ssn { OSMO_SCCP_SSN_BSSAP = 254, }; +/* Q.711 6.3.2.2.5 Signalling point status */ +enum osmo_sccp_sp_status { + OSMO_SCCP_SP_S_INACCESSIBLE = 1, + OSMO_SCCP_SP_S_CONGESTED = 2, + OSMO_SCCP_SP_S_ACCESSIBLE = 3, +}; +/* Q.711 6.3.2.2.6 Remote SCCP status */ +enum osmo_sccp_rem_sccp_status { + OSMO_SCCP_REM_SCCP_S_AVAILABLE = 1, + OSMO_SCCP_REM_SCCP_S_UNAVAILABLE_UNKNOWN = 2, + OSMO_SCCP_REM_SCCP_S_UNEQUIPPED = 3, + OSMO_SCCP_REM_SCCP_S_INACCESSIBLE = 4, + OSMO_SCCP_REM_SCCP_S_CONGESTED = 5, +}; + /* legacy shim for name change */ #define OSMO_SCCP_SSN_SMLC_BSSAP OSMO_SCCP_SSN_SMLC_BSSAP_LE @@ -226,6 +241,22 @@ struct osmo_scu_notice_param { /* user data */ }; +/* OSMO_SCU_PRIM_N_STATE */ +struct osmo_scu_state_param { + uint32_t affected_pc; + uint32_t affected_ssn; + bool user_in_service; /* true: UIS; false: UOS */ + uint32_t ssn_multiplicity_ind; +}; + +/* OSMO_ASCU_PRIM_N_PCSTATE */ +struct osmo_scu_pcstate_param { + uint32_t affected_pc; + uint32_t restricted_importance_level; + enum osmo_sccp_sp_status sp_status; + enum osmo_sccp_rem_sccp_status remote_sccp_status; +}; + struct osmo_scu_prim { struct osmo_prim_hdr oph; union { @@ -235,6 +266,8 @@ struct osmo_scu_prim { struct osmo_scu_reset_param reset; struct osmo_scu_unitdata_param unitdata; struct osmo_scu_notice_param notice; + struct osmo_scu_state_param state; + struct osmo_scu_pcstate_param pcstate; } u; }; diff --git a/src/Makefile.am b/src/Makefile.am index 41d2a8d..4558810 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,8 @@ LIBVERSION=5:0:0 libosmo_sigtran_la_SOURCES = sccp_sap.c sua.c m3ua.c xua_msg.c sccp_helpers.c \ sccp2sua.c sccp_scrc.c sccp_sclc.c sccp_scoc.c \ - sccp_user.c sccp_types.c xua_rkm.c xua_shared.c xua_default_lm_fsm.c \ + sccp_user.c sccp_types.c sccp_lbcs.c sccp_scmg.c \ + xua_rkm.c xua_shared.c xua_default_lm_fsm.c \ osmo_ss7.c osmo_ss7_hmrt.c xua_asp_fsm.c xua_as_fsm.c \ xua_snm.c osmo_ss7_vty.c sccp_vty.c ipa.c libosmo_sigtran_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined -export-symbols-regex '^osmo_' diff --git a/src/sccp_internal.h b/src/sccp_internal.h index 98f6d37..6ad7ee3 100644 --- a/src/sccp_internal.h +++ b/src/sccp_internal.h @@ -129,3 +129,13 @@ const struct osmo_sccp_timer_val *osmo_sccp_timer_get(const struct osmo_sccp_ins bool default_if_unset); void osmo_sccp_vty_write_cs7_node(struct vty *vty, const char *indent, struct osmo_sccp_instance *inst); + +/* Local Broadcast (LBCS) */ +void sccp_lbcs_local_bcast_pcstate(struct osmo_sccp_instance *inst, + const struct osmo_scu_pcstate_param *pcstate); +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_mtp_pause(struct osmo_sccp_instance *inst, uint32_t dpc); +void sccp_scmg_rx_mtp_resume(struct osmo_sccp_instance *inst, uint32_t dpc); diff --git a/src/sccp_lbcs.c b/src/sccp_lbcs.c new file mode 100644 index 0000000..3aa4f7a --- /dev/null +++ b/src/sccp_lbcs.c @@ -0,0 +1,68 @@ +/* SCCP Local Broadcast (LBCS) according to ITU-T Q.713/Q.714 */ + +/* (C) 2021 by Harald Welte <laforge@gnumonks.org> + * All Rights reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <string.h> + +#include <osmocom/core/utils.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/fsm.h> + +#include <osmocom/sigtran/sccp_sap.h> +#include <osmocom/sigtran/protocol/sua.h> +#include <osmocom/sccp/sccp_types.h> + +#include "xua_internal.h" +#include "sccp_internal.h" + +/* perform a "local broadcast" of a N-PCSTATE.ind */ +void sccp_lbcs_local_bcast_pcstate(struct osmo_sccp_instance *inst, + const struct osmo_scu_pcstate_param *pcstate) +{ + struct osmo_sccp_user *scu; + + llist_for_each_entry(scu, &inst->users, list) { + struct msgb *upmsg = sccp_msgb_alloc(__func__); + struct osmo_scu_prim *prim = (struct osmo_scu_prim *) msgb_put(upmsg, sizeof(*prim)); + osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_PCSTATE, + PRIM_OP_INDICATION, upmsg); + prim->u.pcstate = *pcstate; + sccp_user_prim_up(scu, prim); + } +} + +/* perform a "local broadcast" of a N-STATE.ind */ +void sccp_lbcs_local_bcast_state(struct osmo_sccp_instance *inst, + const struct osmo_scu_state_param *state) +{ + struct osmo_sccp_user *scu; + + llist_for_each_entry(scu, &inst->users, list) { + struct msgb *upmsg = sccp_msgb_alloc(__func__); + struct osmo_scu_prim *prim = (struct osmo_scu_prim *) msgb_put(upmsg, sizeof(*prim)); + osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_STATE, + PRIM_OP_INDICATION, upmsg); + prim->u.state = *state; + sccp_user_prim_up(scu, prim); + } +} diff --git a/src/sccp_scmg.c b/src/sccp_scmg.c new file mode 100644 index 0000000..4a8ccf6 --- /dev/null +++ b/src/sccp_scmg.c @@ -0,0 +1,83 @@ +/* SCCP Management (SCMG) according to ITU-T Q.713/Q.714 */ + +/* (C) 2021 by Harald Welte <laforge@gnumonks.org> + * All Rights reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <string.h> + +#include <osmocom/core/utils.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/fsm.h> + +#include <osmocom/sigtran/sccp_sap.h> +#include <osmocom/sigtran/protocol/sua.h> +#include <osmocom/sccp/sccp_types.h> + +#include "xua_internal.h" +#include "sccp_internal.h" + +/*! 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) +{ + struct osmo_scu_pcstate_param pcstate; + /* 1) Informs the translation function to update the translation tables. */ + /* 2) SCCP management marks as "prohibited" the status of the remote signalling point, the + remote SCCP and each subsystem at the remote signalling point. */ + /* 3) Discontinues all subsystem status tests (including SSN = 1) */ + + /* 4) local broadcast of "user-out-of-service" for each SSN at that dest + * [this would require us to track SSNs at each PC, which we don't] */ + + /* 5) local broadcast of "signaling point inaccessible" */ + /* 6) local broadcast of "remote SCCP unavailable" */ + pcstate = (struct osmo_scu_pcstate_param) { + .affected_pc = dpc, + .restricted_importance_level = 0, + .sp_status = OSMO_SCCP_SP_S_INACCESSIBLE, + .remote_sccp_status = OSMO_SCCP_REM_SCCP_S_UNAVAILABLE_UNKNOWN, + }; + sccp_lbcs_local_bcast_pcstate(inst, &pcstate); +} + +/*! brief MTP -> SNM (MTP-RESUME.ind) - ability of providing the MTP service Q.714 5.2.3 */ +void sccp_scmg_rx_mtp_resume(struct osmo_sccp_instance *inst, uint32_t dpc) +{ + struct osmo_scu_pcstate_param pcstate; + /* 1) Sets the congestion state of that signalling point */ + /* 2) Instructs the translation function to update the translation tables. */ + /* 3) Marks as "allowed" the status of that destination, and the SCCP */ + /* 4) - not applicable */ + /* 5) Marks as "allowed" the status of remote subsystems */ + + /* 6) local broadcast of "signalling point accessible" */ + /* 7) local broadcast of "remote SCCP accessible" */ + pcstate = (struct osmo_scu_pcstate_param) { + .affected_pc = dpc, + .restricted_importance_level = 0, + .sp_status = OSMO_SCCP_SP_S_ACCESSIBLE, + .remote_sccp_status = OSMO_SCCP_REM_SCCP_S_AVAILABLE, + }; + sccp_lbcs_local_bcast_pcstate(inst, &pcstate); + + /* 8) local broadcast of "user-in-service" + * [this would require us to track SSNs at each PC, which we don't] */ +} diff --git a/src/xua_snm.c b/src/xua_snm.c index c4dffbb..e3efc8e 100644 --- a/src/xua_snm.c +++ b/src/xua_snm.c @@ -31,6 +31,7 @@ #include <osmocom/sigtran/protocol/sua.h> #include "xua_internal.h" +#include "sccp_internal.h" /* we can share this code between M3UA and SUA as the below conditions are true */ osmo_static_assert(M3UA_SNM_DUNA == SUA_SNM_DUNA, _sa_duna); @@ -98,6 +99,37 @@ static void xua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, } } +/* generate MTP-PAUSE / MTP-RESUME towards local SCCP users */ +static void xua_snm_pc_available_to_sccp(struct osmo_sccp_instance *sccp, + const uint32_t *aff_pc, unsigned int num_aff_pc, + bool available) +{ + int i; + for (i = 0; i < num_aff_pc; i++) { + uint32_t _aff_pc = ntohl(aff_pc[i]); + uint32_t pc = _aff_pc & 0xffffff; + uint8_t mask = _aff_pc >> 24; + + if (!mask) { + if (available) + sccp_scmg_rx_mtp_resume(sccp, pc); + else + sccp_scmg_rx_mtp_pause(sccp, pc); + } else { + /* we have to send one MTP primitive for each individual point + * code within that mask */ + uint32_t maskbits = (1 << mask) - 1; + uint32_t fullpc; + for (fullpc = (pc & ~maskbits); fullpc <= (pc | maskbits); fullpc++) { + if (available) + sccp_scmg_rx_mtp_resume(sccp, pc); + else + sccp_scmg_rx_mtp_pause(sccp, pc); + } + } + } +} + /* advertise availability of point codes (with masks) */ void xua_snm_pc_available(struct osmo_ss7_as *as, const uint32_t *aff_pc, unsigned int num_aff_pc, const char *info_str, bool available) @@ -107,6 +139,11 @@ void xua_snm_pc_available(struct osmo_ss7_as *as, const uint32_t *aff_pc, uint32_t rctx[32]; unsigned int num_rctx; + /* inform local users via a MTP-{PAUSE, RESUME} primitive */ + if (s7i->sccp) + xua_snm_pc_available_to_sccp(s7i->sccp, aff_pc, num_aff_pc, available); + + /* inform remote 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)) |