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
This commit is contained in:
Harald Welte 2021-02-06 23:21:55 +01:00
parent 6cb841b92b
commit 943affdd48
6 changed files with 233 additions and 1 deletions

View File

@ -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;
};

View File

@ -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_'

View File

@ -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);

68
src/sccp_lbcs.c Normal file
View File

@ -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);
}
}

83
src/sccp_scmg.c Normal file
View File

@ -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] */
}

View File

@ -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))