lynxis lazus has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-sgsn/+/41001?usp=email )

Change subject: ranap: Take into account RNC availability during paging
......................................................................

ranap: Take into account RNC availability during paging

Avoid transmitting a RANAP paging message to an RNC if we already know
it's not currently available over SCCP.
Take into account that information when deciding/printing whether the
paging could be sent or not.

Take the chance to clean up the iu paging function helpers inherited
from osmo-iuh iu_client.c to better fit the data domain in osmo-sgsn
(iu_rnc).

Change-Id: I24e5446bcf4c958028577230b231960acea9e5b9
---
M include/osmocom/sgsn/gprs_ranap.h
M include/osmocom/sgsn/iu_rnc.h
M include/osmocom/sgsn/iu_rnc_fsm.h
M src/sgsn/gprs_ranap.c
M src/sgsn/iu_client.c
M src/sgsn/iu_rnc.c
M src/sgsn/iu_rnc_fsm.c
7 files changed, 144 insertions(+), 115 deletions(-)

Approvals:
  lynxis lazus: Looks good to me, approved
  Jenkins Builder: Verified
  osmith: Looks good to me, but someone else must approve




diff --git a/include/osmocom/sgsn/gprs_ranap.h 
b/include/osmocom/sgsn/gprs_ranap.h
index 62914ba..b959b57 100644
--- a/include/osmocom/sgsn/gprs_ranap.h
+++ b/include/osmocom/sgsn/gprs_ranap.h
@@ -30,9 +30,6 @@
 int sgsn_ranap_iu_tx_sec_mode_cmd(struct ranap_ue_conn_ctx *uectx, struct 
osmo_auth_vector *vec,
                             int send_ck, int new_key);
 int sgsn_ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *ue_ctx, const char 
*imsi);
-int sgsn_ranap_iu_tx_paging_cmd(struct osmo_sccp_addr *called_addr,
-                    const char *imsi, const uint32_t *tmsi,
-                    bool is_ps, uint32_t paging_cause);

 int sgsn_ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct 
RANAP_Cause *cause);
 /* Transmit a Iu Release Command and submit event RANAP_IU_EVENT_IU_RELEASE 
upon
diff --git a/include/osmocom/sgsn/iu_rnc.h b/include/osmocom/sgsn/iu_rnc.h
index b0e5be3..0382b74 100644
--- a/include/osmocom/sgsn/iu_rnc.h
+++ b/include/osmocom/sgsn/iu_rnc.h
@@ -1,6 +1,7 @@
 #pragma once

 #include <stdbool.h>
+#include <stdint.h>

 #include <osmocom/core/defs.h>
 #include <osmocom/core/linuxlist.h>
@@ -43,6 +44,12 @@

 void iu_rnc_discard_all_ue_ctx(struct ranap_iu_rnc *rnc);

+int iu_rnc_tx_paging_cmd(struct ranap_iu_rnc *rnc,
+                        const char *imsi,
+                        const uint32_t *tmsi,
+                        bool is_ps,
+                        uint32_t paging_cause);
+
 #define LOG_RNC_CAT(IU_RNC, subsys, loglevel, fmt, args ...) \
        LOGPFSMSL((IU_RNC)->fi, subsys, loglevel, fmt, ## args)

diff --git a/include/osmocom/sgsn/iu_rnc_fsm.h 
b/include/osmocom/sgsn/iu_rnc_fsm.h
index d9be576..f69d82e 100644
--- a/include/osmocom/sgsn/iu_rnc_fsm.h
+++ b/include/osmocom/sgsn/iu_rnc_fsm.h
@@ -29,6 +29,7 @@
        IU_RNC_EV_MSG_UP_CO, /* struct iu_rnc_ev_msg_up_co_ctx* */
        IU_RNC_EV_RX_RESET, /* no param */
        IU_RNC_EV_RX_RESET_ACK, /* no param */
+       IU_RNC_EV_MSG_DOWN_CL, /* struct msgb* */
        IU_RNC_EV_AVAILABLE,
        IU_RNC_EV_UNAVAILABLE
 };
diff --git a/src/sgsn/gprs_ranap.c b/src/sgsn/gprs_ranap.c
index df9cc9e..1cdb72b 100644
--- a/src/sgsn/gprs_ranap.c
+++ b/src/sgsn/gprs_ranap.c
@@ -287,22 +287,6 @@
        return sgsn_scu_iups_tx_data_req(uectx->rnc->scu_iups, uectx->conn_id, 
msg);
 }

-/* Send a paging command down a given SCCP User. tmsi and paging_cause are
- * optional and may be passed NULL and 0, respectively, to disable their use.
- * See enum RANAP_PagingCause.
- *
- * If TMSI is given, the IMSI is not sent over the air interface. Nevertheless,
- * the IMSI is still required for resolution in the HNB-GW and/or(?) RNC. */
-int sgsn_ranap_iu_tx_paging_cmd(struct osmo_sccp_addr *called_addr,
-                          const char *imsi, const uint32_t *tmsi,
-                          bool is_ps, uint32_t paging_cause)
-{
-       struct msgb *msg;
-       msg = ranap_new_msg_paging_cmd(imsi, tmsi, is_ps ? 1 : 0, paging_cause);
-       msg->l2h = msg->data;
-       return osmo_sccp_tx_unitdata_msg(sgsn->sccp.scu_iups->scu, 
&sgsn->sccp.scu_iups->local_sccp_addr, called_addr, msg);
-}
-
 int sgsn_ranap_iu_tx(struct msgb *msg_nas, uint8_t sapi)
 {
        struct ranap_ue_conn_ctx *uectx = msg_nas->dst;
diff --git a/src/sgsn/iu_client.c b/src/sgsn/iu_client.c
index cb5d096..164ff71 100644
--- a/src/sgsn/iu_client.c
+++ b/src/sgsn/iu_client.c
@@ -43,12 +43,6 @@
 #include <osmocom/sgsn/sccp.h>
 #include <osmocom/sgsn/sgsn.h>

-#define LOGPIU(level, fmt, args...) \
-       LOGP(DRANAP, level, fmt, ## args)
-
-#define LOGPIUC(level, fmt, args...) \
-       LOGPC(DRANAP, level, fmt, ## args)
-
 const struct value_string iu_client_event_type_names[] = {
        OSMO_VALUE_STRING(RANAP_IU_EVENT_RAB_ASSIGN),
        OSMO_VALUE_STRING(RANAP_IU_EVENT_SECURITY_MODE_COMPLETE),
@@ -66,7 +60,7 @@
        if (ue_ctx && !ue_ctx->notification)
                return 0;

-       LOGPIU(LOGL_DEBUG, "Submit Iu event to upper layer: %s\n", 
iu_client_event_type_str(type));
+       LOGP(DRANAP, LOGL_DEBUG, "Submit Iu event to upper layer: %s\n", 
iu_client_event_type_str(type));

        return sgsn_ranap_iu_event(ue_ctx, type, data);
 }
@@ -126,78 +120,74 @@
  ***********************************************************************/

 /* legacy, do a first match with ignoring PLMN */
-static bool iu_rnc_lac_rac_find_legacy(struct ranap_iu_rnc **rnc, struct 
iu_lac_rac_entry **lre,
-                                      uint16_t lac, uint8_t rac)
-{
-       struct ranap_iu_rnc *r;
-       struct iu_lac_rac_entry *e;
-
-       if (rnc)
-               *rnc = NULL;
-       if (lre)
-               *lre = NULL;
-
-       llist_for_each_entry(r, &sgsn->rnc_list, entry) {
-               llist_for_each_entry(e, &r->lac_rac_list, entry) {
-                       if (e->rai.lac.lac == lac && e->rai.rac == rac) {
-                               if (rnc)
-                                       *rnc = r;
-                               if (lre)
-                                       *lre = e;
-                               return true;
-                       }
-               }
-       }
-       return false;
-}
-
-static int iu_page(const char *imsi, const uint32_t *tmsi_or_ptmsi,
-                  uint16_t lac, uint8_t rac, bool is_ps)
+static struct ranap_iu_rnc *iu_rnc_lac_rac_find_legacy(uint16_t lac, uint8_t 
rac)
 {
        struct ranap_iu_rnc *rnc;
-       const char *log_msg;
-       int log_level;
-       int paged = 0;
+       struct iu_lac_rac_entry *e;

-       iu_rnc_lac_rac_find_legacy(&rnc, NULL, lac, rac);
-       if (rnc) {
-               if (sgsn_ranap_iu_tx_paging_cmd(&rnc->sccp_addr, imsi, 
tmsi_or_ptmsi, is_ps, 0) == 0) {
-                       log_msg = "Paging";
-                       log_level = LOGL_DEBUG;
-                       paged = 1;
-               } else {
-                       log_msg = "Paging failed";
-                       log_level = LOGL_ERROR;
+       llist_for_each_entry(rnc, &sgsn->rnc_list, entry) {
+               llist_for_each_entry(e, &rnc->lac_rac_list, entry) {
+                       if (e->rai.lac.lac == lac && e->rai.rac == rac)
+                               return rnc;
                }
-       } else {
-               log_msg = "Found no RNC to Page";
-               log_level = LOGL_ERROR;
        }
-
-       if (is_ps)
-               LOGPIU(log_level, "IuPS: %s on LAC %d RAC %d", log_msg, lac, 
rac);
-       else
-               LOGPIU(log_level, "IuCS: %s on LAC %d", log_msg, lac);
-       if (rnc)
-               LOGPIUC(log_level, " at SCCP-addr %s", 
osmo_sccp_addr_dump(&rnc->sccp_addr));
-       if (tmsi_or_ptmsi)
-               LOGPIUC(log_level, ", for %s %08x\n", is_ps ? "PTMSI" : "TMSI", 
*tmsi_or_ptmsi);
-       else
-               LOGPIUC(log_level, ", for IMSI %s\n", imsi);
-
-       return paged;
+       return NULL;
 }

 /*! Old paging() doesn't use PLMN and transmit paging command only to the 
first RNC  */
 int ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac)
 {
-       return iu_page(imsi, tmsi, lac, 0, false);
+       struct ranap_iu_rnc *rnc;
+       char log_msg[32] = {};
+       int rc;
+
+       if (tmsi)
+               snprintf(log_msg, sizeof(log_msg), "TMSI %08x\n", *tmsi);
+       else
+               snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi);
+
+       rnc = iu_rnc_lac_rac_find_legacy(lac, 0);
+       if (!rnc) {
+               LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page CS on LAC %u for 
%s",
+                    lac, log_msg);
+               return 0;
+       }
+
+       rc = iu_rnc_tx_paging_cmd(rnc, imsi, tmsi, false, 0);
+       if (rc != 0) {
+               LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging CS for LAC %u for 
%s",
+                       lac, log_msg);
+               return 0;
+       }
+       return 1;
 }

 /*! Old paging() doesn't use PLMN and transmit paging command only to the 
first RNC  */
 int ranap_iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, 
uint8_t rac)
 {
-       return iu_page(imsi, ptmsi, lac, rac, true);
+       struct ranap_iu_rnc *rnc;
+       char log_msg[32] = {};
+       int rc;
+
+       if (ptmsi)
+               snprintf(log_msg, sizeof(log_msg), "P-TMSI %08x\n", *ptmsi);
+       else
+               snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi);
+
+       rnc = iu_rnc_lac_rac_find_legacy(lac, rac);
+       if (!rnc) {
+               LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page PS on LAC %u RAC 
%u for %s",
+                    lac, rac, log_msg);
+               return 0;
+       }
+
+       rc = iu_rnc_tx_paging_cmd(rnc, imsi, ptmsi, true, 0);
+       if (rc != 0) {
+               LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging PS for LAC %u RAC 
%u for %s",
+                       lac, rac, log_msg);
+               return 0;
+       }
+       return 1;
 }

 /*! Transmit a single page request towards all RNCs serving the specific LAI 
(no page retransmission).
@@ -212,8 +202,13 @@
        struct ranap_iu_rnc *rnc;
        struct iu_lac_rac_entry *entry;
        char log_msg[32] = {};
-       int paged = 0;
-       int rc = 0;
+       unsigned int paged = 0;
+       int rc;
+
+       if (tmsi)
+               snprintf(log_msg, sizeof(log_msg), "TMSI %08x\n", *tmsi);
+       else
+               snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi);

        /* find all RNCs which are serving this LA */
        llist_for_each_entry(rnc, &sgsn->rnc_list, entry) {
@@ -221,27 +216,23 @@
                        if (osmo_lai_cmp(&entry->rai.lac, lai))
                                continue;

-                       rc = sgsn_ranap_iu_tx_paging_cmd(&rnc->sccp_addr, imsi, 
tmsi, false, 0);
-                       if (rc > 0) {
-                               LOGPIU(LOGL_ERROR, "IuCS: Failed to tx Paging 
RNC %s for LAC %s for IMSI %s / TMSI %08x",
-                                      osmo_rnc_id_name(&rnc->rnc_id),
-                                      osmo_lai_name(lai), imsi, tmsi ? *tmsi : 
GSM_RESERVED_TMSI);
+                       rc = iu_rnc_tx_paging_cmd(rnc, imsi, tmsi, false, 0);
+                       if (rc != 0) {
+                               LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging 
CS for LAI %s for %s",
+                                       osmo_lai_name(lai), log_msg);
+                       } else {
+                               paged++;
                        }
-                       paged++;
                        break;
                }
        }

-       if (tmsi)
-               snprintf(log_msg, sizeof(log_msg), "for TMSI %08x\n", *tmsi);
-       else
-               snprintf(log_msg, sizeof(log_msg) - 1, "for IMSI %s\n", imsi);
-
        if (paged)
-               LOGPIU(LOGL_DEBUG, "IuPS: Paged %d RNCs on LAI %s for %s", 
paged, osmo_lai_name(lai), log_msg);
+               LOGP(DRANAP, LOGL_DEBUG, "Paged CS %u RNCs on LAI %s for %s",
+                    paged, osmo_lai_name(lai), log_msg);
        else
-               LOGPIU(LOGL_INFO, "IuPS: Found no RNC to Page on LAI %s for 
%s", osmo_lai_name(lai), log_msg);
-
+               LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page CS on LAI %s for 
%s",
+                    osmo_lai_name(lai), log_msg);

        return paged;
 }
@@ -249,7 +240,7 @@
 /*! Transmit a single page request towards all RNCs serving the specific RAI 
(no page retransmission).
  *
  * \param imsi the imsi as human readable string
- * \param ptmsi NULL or pointer to the tmsi
+ * \param ptmsi NULL or pointer to the ptmsi
  * \param rai full Location Area Identifier
  * \return amount of paged RNCs. 0 when no RNC found.
  */
@@ -258,8 +249,13 @@
        struct ranap_iu_rnc *rnc;
        struct iu_lac_rac_entry *entry;
        char log_msg[32] = {};
-       int paged = 0;
-       int rc = 0;
+       unsigned int paged = 0;
+       int rc;
+
+       if (ptmsi)
+               snprintf(log_msg, sizeof(log_msg), "P-TMSI %08x\n", *ptmsi);
+       else
+               snprintf(log_msg, sizeof(log_msg), "IMSI %s\n", imsi);

        /* find all RNCs which are serving this RAC */
        llist_for_each_entry(rnc, &sgsn->rnc_list, entry) {
@@ -267,26 +263,23 @@
                        if (osmo_rai_cmp(&entry->rai, rai))
                                continue;

-                       rc = sgsn_ranap_iu_tx_paging_cmd(&rnc->sccp_addr, imsi, 
ptmsi, true, 0);
-                       if (rc > 0) {
-                               LOGPIU(LOGL_ERROR, "IuPS: Failed to tx Paging 
RNC %s for RAC %s for IMSI %s / P-TMSI %08x",
-                                      osmo_rnc_id_name(&rnc->rnc_id),
-                                      osmo_rai_name2(rai), imsi, ptmsi ? 
*ptmsi : GSM_RESERVED_TMSI);
+                       rc = iu_rnc_tx_paging_cmd(rnc, imsi, ptmsi, true, 0);
+                       if (rc != 0) {
+                               LOG_RNC(rnc, LOGL_ERROR, "Failed to tx Paging 
PS for RAI %s for %s",
+                                       osmo_rai_name2(rai), log_msg);
+                       } else {
+                               paged++;
                        }
-                       paged++;
                        break;
                }
        }

-       if (ptmsi)
-               snprintf(log_msg, sizeof(log_msg) - 1, "for PTMSI %08x\n", 
*ptmsi);
-       else
-               snprintf(log_msg, sizeof(log_msg) - 1, "for IMSI %s\n", imsi);
-
        if (paged)
-               LOGPIU(LOGL_DEBUG, "IuPS: Paged %d RNCs on RAI %s for %s", 
paged, osmo_rai_name2(rai), log_msg);
+               LOGP(DRANAP, LOGL_DEBUG, "Paged PS %u RNCs on RAI %s for %s",
+                    paged, osmo_rai_name2(rai), log_msg);
        else
-               LOGPIU(LOGL_INFO, "IuPS: Found no RNC to Page on RAI %s for 
%s", osmo_rai_name2(rai), log_msg);
+               LOGP(DRANAP, LOGL_INFO, "Found no RNC to Page PS on RAI %s for 
%s",
+                    osmo_rai_name2(rai), log_msg);

        return paged;
 }
diff --git a/src/sgsn/iu_rnc.c b/src/sgsn/iu_rnc.c
index 38cddb5..1a15df1 100644
--- a/src/sgsn/iu_rnc.c
+++ b/src/sgsn/iu_rnc.c
@@ -213,3 +213,43 @@
                ue_conn_ctx_link_invalidated_free(ue_ctx);
        }
 }
+
+/* Send a paging command down a given SCCP User. tmsi_or_ptmsi and 
paging_cause are
+ * optional and may be passed NULL and 0, respectively, to disable their use.
+ * See enum RANAP_PagingCause.
+ *
+ * If tmsi_or_ptmsi is given, the imsi is not sent over the air interface.
+ * Nevertheless, the IMSI is still required for resolution in the HNB-GW
+ * and/or(?) RNC.
+ *
+ * returns negative if paging couldn't be sent (eg. because RNC is currently
+ * unreachable in lower layers).
+ **/
+int iu_rnc_tx_paging_cmd(struct ranap_iu_rnc *rnc,
+                        const char *imsi,
+                        const uint32_t *tmsi_or_ptmsi,
+                        bool is_ps,
+                        uint32_t paging_cause)
+{
+       struct msgb *ranap_msg;
+       int rc;
+
+       /* rnc is not ready for paging (link not ready). */
+       if (rnc->fi->state != IU_RNC_ST_READY)
+               return -ENOLINK;
+
+       LOG_RNC(rnc, LOGL_DEBUG, "Paging %s for %s=%08x IMSI=%s\n",
+               is_ps ? "PS" : "CS",
+               is_ps ? "P-TMSI" : "TMSI",
+               tmsi_or_ptmsi ? *tmsi_or_ptmsi : GSM_RESERVED_TMSI,
+               imsi);
+
+       ranap_msg = ranap_new_msg_paging_cmd(imsi, tmsi_or_ptmsi, is_ps ? 1 : 
0, paging_cause);
+       if (!ranap_msg)
+               return -EINVAL;
+
+       rc = osmo_fsm_inst_dispatch(rnc->fi, IU_RNC_EV_MSG_DOWN_CL, ranap_msg);
+       if (rc != 0)
+               msgb_free(ranap_msg);
+       return rc;
+}
diff --git a/src/sgsn/iu_rnc_fsm.c b/src/sgsn/iu_rnc_fsm.c
index 6f610b4..6b0ad41 100644
--- a/src/sgsn/iu_rnc_fsm.c
+++ b/src/sgsn/iu_rnc_fsm.c
@@ -57,6 +57,7 @@
        OSMO_VALUE_STRING(IU_RNC_EV_MSG_UP_CO),
        OSMO_VALUE_STRING(IU_RNC_EV_RX_RESET),
        OSMO_VALUE_STRING(IU_RNC_EV_RX_RESET_ACK),
+       OSMO_VALUE_STRING(IU_RNC_EV_MSG_DOWN_CL),
        OSMO_VALUE_STRING(IU_RNC_EV_AVAILABLE),
        OSMO_VALUE_STRING(IU_RNC_EV_UNAVAILABLE),
        {}
@@ -252,6 +253,11 @@
                iu_rnc_rx_reset(rnc);
                return;

+       case IU_RNC_EV_MSG_DOWN_CL:
+               OSMO_ASSERT(data);
+               sgsn_ranap_iu_tx_cl(rnc->scu_iups, &rnc->sccp_addr, (struct 
msgb *)data);
+               return;
+
        case IU_RNC_EV_AVAILABLE:
                /* Do nothing, we were already up. */
                return;
@@ -336,6 +342,7 @@
                        | S(IU_RNC_EV_RX_RESET)
                        | S(IU_RNC_EV_MSG_UP_CO_INITIAL)
                        | S(IU_RNC_EV_MSG_UP_CO)
+                       | S(IU_RNC_EV_MSG_DOWN_CL)
                        | S(IU_RNC_EV_AVAILABLE)
                        | S(IU_RNC_EV_UNAVAILABLE)
                        ,

--
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/41001?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: I24e5446bcf4c958028577230b231960acea9e5b9
Gerrit-Change-Number: 41001
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pes...@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanits...@sysmocom.de>
Gerrit-Reviewer: lynxis lazus <lyn...@fe80.eu>
Gerrit-Reviewer: osmith <osm...@sysmocom.de>

Reply via email to