pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-smlc/+/40665?usp=email )
Change subject: smlc: Initial implementation of N-PCSTATE.ind ...................................................................... smlc: Initial implementation of N-PCSTATE.ind Related: OS#5917 Change-Id: Id034a0c4d8bff0647a64658480dfa9b4cea563de --- M include/osmocom/smlc/lb_peer.h M src/osmo-smlc/lb_peer.c M src/osmo-smlc/sccp_lb_inst.c 3 files changed, 129 insertions(+), 4 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-smlc refs/changes/65/40665/1 diff --git a/include/osmocom/smlc/lb_peer.h b/include/osmocom/smlc/lb_peer.h index b5ac6d6..467bc6b 100644 --- a/include/osmocom/smlc/lb_peer.h +++ b/include/osmocom/smlc/lb_peer.h @@ -60,8 +60,11 @@ }; struct lb_peer *lb_peer_find_or_create(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *peer_addr); -struct lb_peer *lb_peer_find(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *peer_addr); +struct lb_peer *lb_peer_find(const struct sccp_lb_inst *sli, const struct osmo_sccp_addr *peer_addr); int lb_peer_up_l2(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *calling_addr, bool co, uint32_t conn_id, struct msgb *l2); void lb_peer_disconnect(struct sccp_lb_inst *sli, uint32_t conn_id); + +void lb_peer_reset(struct lb_peer *lbp); +void lb_peer_becomes_unreachable(struct lb_peer *lbp); diff --git a/src/osmo-smlc/lb_peer.c b/src/osmo-smlc/lb_peer.c index 5206628..02b1500 100644 --- a/src/osmo-smlc/lb_peer.c +++ b/src/osmo-smlc/lb_peer.c @@ -1,5 +1,5 @@ /* - * (C) 2019 by sysmocom - s.f.m.c. GmbH <i...@sysmocom.de> + * (C) 2019-2025 by sysmocom - s.f.m.c. GmbH <i...@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -69,7 +69,7 @@ return lb_peer_alloc(sli, peer_addr); } -struct lb_peer *lb_peer_find(struct sccp_lb_inst *sli, const struct osmo_sccp_addr *peer_addr) +struct lb_peer *lb_peer_find(const struct sccp_lb_inst *sli, const struct osmo_sccp_addr *peer_addr) { struct lb_peer *lbp; llist_for_each_entry(lbp, &sli->lb_peers, entry) { @@ -97,6 +97,13 @@ } } +/* N-PCSTATE.ind informs us the peer went down and is no longer reachable: */ +void lb_peer_becomes_unreachable(struct lb_peer *lbp) +{ + lb_peer_discard_all_conns(lbp); + lb_peer_state_chg(lbp, LB_PEER_ST_WAIT_RX_RESET); +} + /* Drop all SCCP connections for this lb_peer, respond with RESET ACKNOWLEDGE and move to READY state. */ static void lb_peer_rx_reset(struct lb_peer *lbp, struct msgb *msg) { diff --git a/src/osmo-smlc/sccp_lb_inst.c b/src/osmo-smlc/sccp_lb_inst.c index e10effe..de9705a 100644 --- a/src/osmo-smlc/sccp_lb_inst.c +++ b/src/osmo-smlc/sccp_lb_inst.c @@ -1,5 +1,5 @@ /* - * (C) 2020 by sysmocom - s.f.m.c. GmbH <i...@sysmocom.de> + * (C) 2020-2025 by sysmocom - s.f.m.c. GmbH <i...@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -85,6 +85,108 @@ return sli; } +/* Find an lb_peer by its remote SCCP address */ +static struct lb_peer *get_lb_peer_by_pc(const struct sccp_lb_inst *sli, uint32_t pc) +{ + struct lb_peer *lbp; + struct osmo_ss7_instance *cs7 = osmo_sccp_get_ss7(sli->sccp); + struct osmo_sccp_addr rem_addr; + + osmo_sccp_make_addr_pc_ssn(&rem_addr, pc, sli->local_sccp_addr.ssn); + lbp = lb_peer_find(sli, &rem_addr); + if (lbp) + return lbp; + LOG_SCCP_LB(sli, LOGL_DEBUG, "No lb_peer found under remote address: %s\n", osmo_sccp_addr_name(cs7, &rem_addr)); + return NULL; +} + +static void handle_pcstate_ind(struct sccp_lb_inst *sli, const struct osmo_scu_pcstate_param *pcst) +{ + struct osmo_ss7_instance *cs7 = osmo_sccp_get_ss7(sli->sccp); + struct lb_peer *lbp; + bool connected; + bool disconnected; + + LOG_SCCP_LB(sli, LOGL_DEBUG, "N-PCSTATE ind: affected_pc=%u=%s sp_status=%s remote_sccp_status=%s\n", + pcst->affected_pc, osmo_ss7_pointcode_print(cs7, pcst->affected_pc), + osmo_sccp_sp_status_name(pcst->sp_status), + osmo_sccp_rem_sccp_status_name(pcst->remote_sccp_status)); + + /* If we don't care about that point-code, ignore PCSTATE. */ + lbp = get_lb_peer_by_pc(sli, pcst->affected_pc); + if (!lbp) + 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 && lbp->fi && lbp->fi->state == LB_PEER_ST_READY) { + LOG_SCCP_LB(sli, LOGL_NOTICE, + "now unreachable: N-PCSTATE ind: pc=%u=%s sp_status=%s remote_sccp_status=%s\n", + pcst->affected_pc, osmo_ss7_pointcode_print(cs7, pcst->affected_pc), + osmo_sccp_sp_status_name(pcst->sp_status), + osmo_sccp_rem_sccp_status_name(pcst->remote_sccp_status)); + lb_peer_becomes_unreachable(lbp); + } else if (connected && lbp->fi && lbp->fi->state != LB_PEER_ST_READY) { + LOG_SCCP_LB(sli, LOGL_NOTICE, + "now available: N-PCSTATE ind: pc=%u=%s sp_status=%s remote_sccp_status=%s\n", + pcst->affected_pc, osmo_ss7_pointcode_print(cs7, pcst->affected_pc), + osmo_sccp_sp_status_name(pcst->sp_status), + osmo_sccp_rem_sccp_status_name(pcst->remote_sccp_status)); + lb_peer_reset(lbp); + } +} + static int sccp_lb_sap_up(struct osmo_prim_hdr *oph, void *_scu) { struct osmo_sccp_user *scu = _scu; @@ -163,6 +265,19 @@ rc = lb_peer_up_l2(sli, peer_addr, false, 0, oph->msg); break; + case OSMO_PRIM(OSMO_SCU_PRIM_N_PCSTATE, PRIM_OP_INDICATION): + handle_pcstate_ind(sli, &prim->u.pcstate); + rc = 0; + break; + + case OSMO_PRIM(OSMO_SCU_PRIM_N_STATE, PRIM_OP_INDICATION): + LOG_SCCP_LB(sli, LOGL_INFO, + "SCCP-User-SAP: Ignoring %s.%s\n", + osmo_scu_prim_type_name(oph->primitive), + get_value_string(osmo_prim_op_names, oph->operation)); + rc = 0; + break; + default: LOG_SCCP_LB_CL(sli, NULL, LOGL_ERROR, "%s(%s) unsupported\n", __func__, osmo_scu_prim_name(oph)); rc = -1; -- To view, visit https://gerrit.osmocom.org/c/osmo-smlc/+/40665?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: osmo-smlc Gerrit-Branch: master Gerrit-Change-Id: Id034a0c4d8bff0647a64658480dfa9b4cea563de Gerrit-Change-Number: 40665 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pes...@sysmocom.de>