pespin has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-smlc/+/40665?usp=email )

 (

4 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted 
one.
 )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, 155 insertions(+), 2 deletions(-)

Approvals:
  laforge: Looks good to me, but someone else must approve
  fixeria: Looks good to me, approved
  Jenkins Builder: Verified




diff --git a/include/osmocom/smlc/lb_peer.h b/include/osmocom/smlc/lb_peer.h
index 5851a95..dc65b24 100644
--- a/include/osmocom/smlc/lb_peer.h
+++ b/include/osmocom/smlc/lb_peer.h
@@ -1,5 +1,7 @@
 #pragma once

+#include <stdint.h>
+
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/gsm/gsm0808.h>
 #include <osmocom/sigtran/sccp_sap.h>
@@ -49,6 +51,8 @@
        LB_PEER_EV_MSG_DOWN_CO,
        LB_PEER_EV_RX_RESET,
        LB_PEER_EV_RX_RESET_ACK,
+       LB_PEER_EV_AVAILABLE,
+       LB_PEER_EV_UNAVAILABLE,
 };

 struct lb_peer_ev_ctx {
@@ -59,6 +63,7 @@

 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(const struct sccp_lb_inst *sli, const struct 
osmo_sccp_addr *peer_addr);
+struct lb_peer *lb_peer_find_by_pc(const struct sccp_lb_inst *sli, uint32_t 
pc);

 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);
diff --git a/src/osmo-smlc/lb_peer.c b/src/osmo-smlc/lb_peer.c
index 54e0ad2..fa2bc17 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 <[email protected]>
+ * (C) 2019-2025 by sysmocom - s.f.m.c. GmbH <[email protected]>
  * All Rights Reserved
  *
  * SPDX-License-Identifier: AGPL-3.0+
@@ -80,6 +80,15 @@
        return NULL;
 }

+/* Find an lb_peer by its remote SCCP address */
+struct lb_peer *lb_peer_find_by_pc(const struct sccp_lb_inst *sli, uint32_t pc)
+{
+       struct osmo_sccp_addr rem_addr;
+
+       osmo_sccp_make_addr_pc_ssn(&rem_addr, pc, OSMO_SCCP_SSN_BSC_BSSAP_LE);
+       return lb_peer_find(sli, &rem_addr);
+}
+
 static const struct osmo_tdef_state_timeout lb_peer_fsm_timeouts[32] = {
        [LB_PEER_ST_WAIT_RX_RESET_ACK] = { .T = -13 },
        [LB_PEER_ST_DISCARDING] = { .T = -14 },
@@ -235,6 +244,15 @@
                lb_peer_rx_reset(lbp, msg);
                return;

+       case LB_PEER_EV_AVAILABLE:
+               /* Send a RESET to the peer. */
+               lb_peer_reset(lbp);
+               return;
+
+       case LB_PEER_EV_UNAVAILABLE:
+               /* Do nothing, wait for peer to come up again. */
+               return;
+
        default:
                LOG_LB_PEER(lbp, LOGL_ERROR, "Unhandled event: %s\n", 
osmo_fsm_event_name(&lb_peer_fsm, event));
                return;
@@ -270,6 +288,15 @@
                lb_peer_rx_reset(lbp, msg);
                return;

+       case LB_PEER_EV_AVAILABLE:
+               /* Send a RESET to the peer. */
+               lb_peer_reset(lbp);
+               return;
+
+       case LB_PEER_EV_UNAVAILABLE:
+               lb_peer_state_chg(lbp, LB_PEER_ST_WAIT_RX_RESET);
+               return;
+
        default:
                LOG_LB_PEER(lbp, LOGL_ERROR, "Unhandled event: %s\n", 
osmo_fsm_event_name(&lb_peer_fsm, event));
                return;
@@ -334,6 +361,16 @@
                lb_peer_rx_reset(lbp, msg);
                return;

+       case LB_PEER_EV_AVAILABLE:
+               /* Send a RESET to the peer. */
+               lb_peer_reset(lbp);
+               return;
+
+       case LB_PEER_EV_UNAVAILABLE:
+               lb_peer_discard_all_conns(lbp);
+               lb_peer_state_chg(lbp, LB_PEER_ST_WAIT_RX_RESET);
+               return;
+
        default:
                LOG_LB_PEER(lbp, LOGL_ERROR, "Unhandled event: %s\n", 
osmo_fsm_event_name(&lb_peer_fsm, event));
                return;
@@ -363,6 +400,8 @@
        OSMO_VALUE_STRING(LB_PEER_EV_MSG_DOWN_CO),
        OSMO_VALUE_STRING(LB_PEER_EV_RX_RESET),
        OSMO_VALUE_STRING(LB_PEER_EV_RX_RESET_ACK),
+       OSMO_VALUE_STRING(LB_PEER_EV_AVAILABLE),
+       OSMO_VALUE_STRING(LB_PEER_EV_UNAVAILABLE),
        {}
 };

@@ -376,6 +415,8 @@
                        | S(LB_PEER_EV_RX_RESET)
                        | S(LB_PEER_EV_MSG_UP_CO_INITIAL)
                        | S(LB_PEER_EV_MSG_UP_CO)
+                       | S(LB_PEER_EV_AVAILABLE)
+                       | S(LB_PEER_EV_UNAVAILABLE)
                        ,
                .out_state_mask = 0
                        | S(LB_PEER_ST_WAIT_RX_RESET)
@@ -392,6 +433,8 @@
                        | S(LB_PEER_EV_RX_RESET_ACK)
                        | S(LB_PEER_EV_MSG_UP_CO_INITIAL)
                        | S(LB_PEER_EV_MSG_UP_CO)
+                       | S(LB_PEER_EV_AVAILABLE)
+                       | S(LB_PEER_EV_UNAVAILABLE)
                        ,
                .out_state_mask = 0
                        | S(LB_PEER_ST_WAIT_RX_RESET)
@@ -410,6 +453,8 @@
                        | S(LB_PEER_EV_MSG_DOWN_CO_INITIAL)
                        | S(LB_PEER_EV_MSG_DOWN_CO)
                        | S(LB_PEER_EV_MSG_DOWN_CL)
+                       | S(LB_PEER_EV_AVAILABLE)
+                       | S(LB_PEER_EV_UNAVAILABLE)
                        ,
                .out_state_mask = 0
                        | S(LB_PEER_ST_WAIT_RX_RESET)
diff --git a/src/osmo-smlc/sccp_lb_inst.c b/src/osmo-smlc/sccp_lb_inst.c
index e10effe..bfe8a0e 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 <[email protected]>
+ * (C) 2020-2025 by sysmocom - s.f.m.c. GmbH <[email protected]>
  * All Rights Reserved
  *
  * SPDX-License-Identifier: AGPL-3.0+
@@ -85,6 +85,96 @@
        return sli;
 }

+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 = lb_peer_find_by_pc(sli, pcst->affected_pc);
+       if (!lbp) {
+               LOG_SCCP_LB(sli, LOGL_DEBUG, "No lb_peer found under 
pc=%u=%s\n",
+                           pcst->affected_pc, osmo_ss7_pointcode_print(cs7, 
pcst->affected_pc));
+               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) {
+               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));
+               osmo_fsm_inst_dispatch(lbp->fi, LB_PEER_EV_UNAVAILABLE, NULL);
+       } else if (connected) {
+               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));
+               osmo_fsm_inst_dispatch(lbp->fi, LB_PEER_EV_AVAILABLE, NULL);
+       }
+}
+
 static int sccp_lb_sap_up(struct osmo_prim_hdr *oph, void *_scu)
 {
        struct osmo_sccp_user *scu = _scu;
@@ -163,6 +253,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: merged
Gerrit-Project: osmo-smlc
Gerrit-Branch: master
Gerrit-Change-Id: Id034a0c4d8bff0647a64658480dfa9b4cea563de
Gerrit-Change-Number: 40665
Gerrit-PatchSet: 5
Gerrit-Owner: pespin <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to