neels has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-bsc/+/32385 )

Change subject: SCCP N-PCSTATE: trigger MSC status on PC availability
......................................................................

SCCP N-PCSTATE: trigger MSC status on PC availability

Backport of 8f8af409743ee03b4a620a21d22facda304f3e68 to 2023q1,
with this tweak in osmo_bsc_sigtran.c:

 -               handle_pcstate_ind(osmo_sccp_get_ss7(sccp), 
&scu_prim->u.pcstate);
 +               handle_pcstate_ind(osmo_sccp_get_ss7(osmo_sccp_get_sccp(scu)), 
&scu_prim->u.pcstate);

because the patch that introduced local variable 'sccp' is not merged
here yet:
'Optimize subscr_conns lookup'
85062ccad31e9fb73e0256a5ee556c6ae0a16449
I667d3ec1dad0ab7bc0fa4799d9611f3a914d07e5

Related: SYS#6319
Related: Ia1aea4e33230d6a685b72ea5ba20dd9c7d265d44 osmo-ttcn3-hacks
Related: Ib4a5330df30a73e744c316898817b2fa3271d75e osmo-ttcn3-hacks
Change-Id: I3a0869598b8395601a16d78dbc46eec400c0ea84
---
M include/osmocom/bsc/bssmap_reset.h
M src/osmo-bsc/bssmap_reset.c
M src/osmo-bsc/osmo_bsc_sigtran.c
3 files changed, 135 insertions(+), 1 deletion(-)

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




diff --git a/include/osmocom/bsc/bssmap_reset.h 
b/include/osmocom/bsc/bssmap_reset.h
index fcd850b..c0de13c 100644
--- a/include/osmocom/bsc/bssmap_reset.h
+++ b/include/osmocom/bsc/bssmap_reset.h
@@ -28,4 +28,5 @@
 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);
diff --git a/src/osmo-bsc/bssmap_reset.c b/src/osmo-bsc/bssmap_reset.c
index fa6684d..ac304a5 100644
--- a/src/osmo-bsc/bssmap_reset.c
+++ b/src/osmo-bsc/bssmap_reset.c
@@ -251,6 +251,12 @@
        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);
diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c
index 04c2e99..2b5554a 100644
--- a/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -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
@@ -119,7 +120,7 @@
                                  &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;
@@ -134,6 +135,21 @@
        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)
 {
@@ -206,6 +222,89 @@
        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)
 {
@@ -271,6 +370,10 @@
                }
                break;

+       case OSMO_PRIM(OSMO_SCU_PRIM_N_PCSTATE, PRIM_OP_INDICATION):
+               handle_pcstate_ind(osmo_sccp_get_ss7(osmo_sccp_get_sccp(scu)), 
&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);

--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/32385
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: 2023q1
Gerrit-Change-Id: I3a0869598b8395601a16d78dbc46eec400c0ea84
Gerrit-Change-Number: 32385
Gerrit-PatchSet: 2
Gerrit-Owner: neels <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <[email protected]>
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: neels <[email protected]>
Gerrit-MessageType: merged

Reply via email to