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 <info(a)sysmocom.de>
+ * (C) 2019-2025 by sysmocom - s.f.m.c. GmbH <info(a)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 <info(a)sysmocom.de>
+ * (C) 2020-2025 by sysmocom - s.f.m.c. GmbH <info(a)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 <pespin(a)sysmocom.de>