SCCP N-PCSTATE: trigger MSC status on PC availability
Related: SYS#6319 Related: Ia1aea4e33230d6a685b72ea5ba20dd9c7d265d44 osmo-ttcn3-hacks Related: Ib4a5330df30a73e744c316898817b2fa3271d75e osmo-ttcn3-hacks Change-Id: I3a0869598b8395601a16d78dbc46eec400c0ea84
This commit is contained in:
parent
ba6fd4f8e4
commit
8f8af40974
|
@ -28,4 +28,5 @@ struct bssmap_reset {
|
|||
struct bssmap_reset *bssmap_reset_alloc(void *ctx, const char *label, const struct bssmap_reset_cfg *cfg);
|
||||
bool bssmap_reset_is_conn_ready(const struct bssmap_reset *bssmap_reset);
|
||||
void bssmap_reset_resend_reset(struct bssmap_reset *bssmap_reset);
|
||||
void bssmap_reset_set_disconnected(struct bssmap_reset *bssmap_reset);
|
||||
void bssmap_reset_term_and_free(struct bssmap_reset *bssmap_reset);
|
||||
|
|
|
@ -251,6 +251,12 @@ void bssmap_reset_resend_reset(struct bssmap_reset *bssmap_reset)
|
|||
osmo_fsm_inst_state_chg_ms(bssmap_reset->fi, BSSMAP_RESET_ST_DISC, 1, 0);
|
||||
}
|
||||
|
||||
void bssmap_reset_set_disconnected(struct bssmap_reset *bssmap_reset)
|
||||
{
|
||||
/* Go to disconnected state, with the normal RESET timeout to re-send RESET. */
|
||||
bssmap_reset_fsm_state_chg(bssmap_reset->fi, BSSMAP_RESET_ST_DISC);
|
||||
}
|
||||
|
||||
static __attribute__((constructor)) void bssmap_reset_fsm_init(void)
|
||||
{
|
||||
OSMO_ASSERT(osmo_fsm_register(&bssmap_reset_fsm) == 0);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/bts.h>
|
||||
#include <osmocom/bsc/paging.h>
|
||||
#include <osmocom/bsc/bssmap_reset.h>
|
||||
#include <osmocom/mgcp_client/mgcp_common.h>
|
||||
|
||||
/* A pointer to a list with all involved MSCs
|
||||
|
@ -92,7 +93,7 @@ void osmo_bsc_sigtran_tx_reset_ack(const struct bsc_msc_data *msc)
|
|||
&msc->a.msc_addr, msg);
|
||||
}
|
||||
|
||||
/* Find an MSC by its sigtran point code */
|
||||
/* Find an MSC by its remote SCCP address */
|
||||
static struct bsc_msc_data *get_msc_by_addr(const struct osmo_sccp_addr *msc_addr)
|
||||
{
|
||||
struct osmo_ss7_instance *ss7;
|
||||
|
@ -107,6 +108,21 @@ static struct bsc_msc_data *get_msc_by_addr(const struct osmo_sccp_addr *msc_add
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Find an MSC by its remote sigtran point code on a given cs7 instance. */
|
||||
static struct bsc_msc_data *get_msc_by_pc(struct osmo_ss7_instance *cs7, uint32_t pc)
|
||||
{
|
||||
struct bsc_msc_data *msc;
|
||||
llist_for_each_entry(msc, msc_list, entry) {
|
||||
if (msc->a.cs7_instance != cs7->cfg.id)
|
||||
continue;
|
||||
if ((msc->a.msc_addr.presence & OSMO_SCCP_ADDR_T_PC) == 0)
|
||||
continue;
|
||||
if (msc->a.msc_addr.pc == pc)
|
||||
return msc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Received data from MSC, use the connection id which MSC it is */
|
||||
static int handle_data_from_msc(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
|
@ -188,6 +204,89 @@ refuse:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void handle_pcstate_ind(struct osmo_ss7_instance *cs7, const struct osmo_scu_pcstate_param *pcst)
|
||||
{
|
||||
struct bsc_msc_data *msc;
|
||||
bool connected;
|
||||
bool disconnected;
|
||||
|
||||
LOGP(DMSC, LOGL_DEBUG, "N-PCSTATE ind: affected_pc=%u sp_status=%d remote_sccp_status=%d\n",
|
||||
pcst->affected_pc, pcst->sp_status, pcst->remote_sccp_status);
|
||||
|
||||
/* If we don't care about that point-code, ignore PCSTATE. */
|
||||
msc = get_msc_by_pc(cs7, pcst->affected_pc);
|
||||
if (!msc)
|
||||
return;
|
||||
|
||||
/* See if this marks the point code to have become available, or to have been lost.
|
||||
*
|
||||
* I want to detect two events:
|
||||
* - connection event (both indicators say PC is reachable).
|
||||
* - disconnection event (at least one indicator says the PC is not reachable).
|
||||
*
|
||||
* There are two separate incoming indicators with various possible values -- the incoming events can be:
|
||||
*
|
||||
* - neither connection nor disconnection indicated -- just indicating congestion
|
||||
* connected == false, disconnected == false --> do nothing.
|
||||
* - both incoming values indicate that we are connected
|
||||
* --> trigger connected
|
||||
* - both indicate we are disconnected
|
||||
* --> trigger disconnected
|
||||
* - one value indicates 'connected', the other indicates 'disconnected'
|
||||
* --> trigger disconnected
|
||||
*
|
||||
* Congestion could imply that we're connected, but it does not indicate that a PC's reachability changed, so no need to
|
||||
* trigger on that.
|
||||
*/
|
||||
connected = false;
|
||||
disconnected = false;
|
||||
|
||||
switch (pcst->sp_status) {
|
||||
case OSMO_SCCP_SP_S_ACCESSIBLE:
|
||||
connected = true;
|
||||
break;
|
||||
case OSMO_SCCP_SP_S_INACCESSIBLE:
|
||||
disconnected = true;
|
||||
break;
|
||||
default:
|
||||
case OSMO_SCCP_SP_S_CONGESTED:
|
||||
/* Neither connecting nor disconnecting */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pcst->remote_sccp_status) {
|
||||
case OSMO_SCCP_REM_SCCP_S_AVAILABLE:
|
||||
if (!disconnected)
|
||||
connected = true;
|
||||
break;
|
||||
case OSMO_SCCP_REM_SCCP_S_UNAVAILABLE_UNKNOWN:
|
||||
case OSMO_SCCP_REM_SCCP_S_UNEQUIPPED:
|
||||
case OSMO_SCCP_REM_SCCP_S_INACCESSIBLE:
|
||||
disconnected = true;
|
||||
connected = false;
|
||||
break;
|
||||
default:
|
||||
case OSMO_SCCP_REM_SCCP_S_CONGESTED:
|
||||
/* Neither connecting nor disconnecting */
|
||||
break;
|
||||
}
|
||||
|
||||
if (disconnected && a_reset_conn_ready(msc)) {
|
||||
LOGP(DMSC, LOGL_NOTICE,
|
||||
"(msc%d) now unreachable: N-PCSTATE ind: pc=%u sp_status=%d remote_sccp_status=%d\n",
|
||||
msc->nr, pcst->affected_pc, pcst->sp_status, pcst->remote_sccp_status);
|
||||
/* A previously usable MSC has disconnected. Kick the BSSMAP back to DISC state. */
|
||||
bssmap_reset_set_disconnected(msc->a.bssmap_reset);
|
||||
} else if (connected && !a_reset_conn_ready(msc)) {
|
||||
LOGP(DMSC, LOGL_NOTICE,
|
||||
"(msc%d) now available: N-PCSTATE ind: pc=%u sp_status=%d remote_sccp_status=%d\n",
|
||||
msc->nr, pcst->affected_pc, pcst->sp_status, pcst->remote_sccp_status);
|
||||
/* A previously unusable MSC has become reachable. Trigger immediate BSSMAP RESET -- we would resend a
|
||||
* RESET either way, but we might as well do it now to speed up connecting. */
|
||||
bssmap_reset_resend_reset(msc->a.bssmap_reset);
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback function, called by the SCCP stack when data arrives */
|
||||
static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
||||
{
|
||||
|
@ -255,6 +354,10 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
}
|
||||
break;
|
||||
|
||||
case OSMO_PRIM(OSMO_SCU_PRIM_N_PCSTATE, PRIM_OP_INDICATION):
|
||||
handle_pcstate_ind(osmo_sccp_get_ss7(sccp), &scu_prim->u.pcstate);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGP(DMSC, LOGL_ERROR, "Unhandled SIGTRAN operation %s on primitive %u\n",
|
||||
get_value_string(osmo_prim_op_names, oph->operation), oph->primitive);
|
||||
|
|
Loading…
Reference in New Issue