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

Change subject: Re-introduce Iu/UTRAN support
......................................................................

Re-introduce Iu/UTRAN support

Add support for UTRAN routing areas.

Change-Id: I1b1aedd2a7c358bd388aa3d8a9f3c6a0011b4889
---
M include/osmocom/sgsn/gprs_routing_area.h
M src/sgsn/gprs_ranap.c
M src/sgsn/gprs_routing_area.c
M tests/gprs_routing_area/gprs_routing_area_test.c
4 files changed, 206 insertions(+), 2 deletions(-)

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




diff --git a/include/osmocom/sgsn/gprs_routing_area.h 
b/include/osmocom/sgsn/gprs_routing_area.h
index a807227..60dfd71 100644
--- a/include/osmocom/sgsn/gprs_routing_area.h
+++ b/include/osmocom/sgsn/gprs_routing_area.h
@@ -56,6 +56,12 @@
         * For UTRAN only do a LAC/RAC <> RNC relation and don't have a 
specific cell relation.
         */
        enum sgsn_ra_ran_type ran_type;
+       union {
+               struct {
+                       /* the RNC id must be the same for a given Routing Area 
*/
+                       struct osmo_rnc_id rnc_id;
+               } utran;
+       } u;

        /* GERAN/UTRAN: cells contains a list of sgsn_ra_cells which are alive 
*/
        struct llist_head cells_alive_list;
@@ -77,8 +83,7 @@
                } geran;

                struct {
-                       /* TODO: unused */
-                       uint16_t rncid;
+                       /* the RNC id must be the same for a given Routing Area 
*/
                        uint16_t sac;
                } utran;
        } u;
@@ -107,10 +112,15 @@
 struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_cgi(const struct 
osmo_cell_global_id *cgi);
 struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_ra(const struct sgsn_ra *ra, 
uint16_t cell_id);
 struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_gb(uint16_t nsei, uint16_t 
bvci);
+
+/* UTRAN */
+int sgsn_ra_utran_register(const struct osmo_routing_area_id *rai, const 
struct osmo_rnc_id *rnc_id);
+
 struct sgsn_ra *sgsn_ra_geran_get_ra(const struct osmo_routing_area_id *rai);

 /* Page the whole routing area for this mmctx */
 int sgsn_ra_geran_page_ra(const struct osmo_routing_area_id *rai, struct 
sgsn_mm_ctx *mmctx);
+struct sgsn_ra *sgsn_ra_utran_get_ra(const struct osmo_routing_area_id *rai);

 /*
  * return value for callbacks.
@@ -125,3 +135,6 @@
 typedef int (sgsn_ra_cb_t)(struct sgsn_ra_cell *ra_cell, void *cb_data);
 int sgsn_ra_foreach_cell(struct sgsn_ra *ra, sgsn_ra_cb_t *cb, void *cb_data);
 int sgsn_ra_foreach_cell2(struct osmo_routing_area_id *rai, sgsn_ra_cb_t *cb, 
void *cb_data);
+
+/* Page the whole routing area for this mmctx */
+int sgsn_ra_utran_page_ra(const struct osmo_routing_area_id *rai, const struct 
sgsn_mm_ctx *mmctx);
diff --git a/src/sgsn/gprs_ranap.c b/src/sgsn/gprs_ranap.c
index 3e2c891..08fc625 100644
--- a/src/sgsn/gprs_ranap.c
+++ b/src/sgsn/gprs_ranap.c
@@ -38,6 +38,7 @@
 #include <osmocom/sgsn/gprs_ranap.h>
 #include <osmocom/sgsn/gprs_gmm_attach.h>
 #include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
+#include <osmocom/sgsn/gprs_routing_area.h>
 #include <osmocom/sgsn/gtp_ggsn.h>
 #include <osmocom/sgsn/gtp.h>
 #include <osmocom/sgsn/pdpctx.h>
@@ -202,12 +203,23 @@

 int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum 
ranap_iu_event_type type, void *data)
 {
+       struct ranap_iu_event_new_area *new_area;
+
        switch (type) {
        case RANAP_IU_EVENT_RAB_ASSIGN:
        case RANAP_IU_EVENT_IU_RELEASE:
        case RANAP_IU_EVENT_LINK_INVALIDATED:
        case RANAP_IU_EVENT_SECURITY_MODE_COMPLETE:
                return sgsn_ranap_iu_event_mmctx(ctx, type, data);
+       case RANAP_IU_EVENT_NEW_AREA:
+               /* inform the Routing Area code about a new RA for Iu */
+               new_area = data;
+
+               /* Only interesting in Routing Area changes, but not Location 
Area */
+               if (new_area->cell_type != RANAP_IU_NEW_RAC)
+                       return 0;
+
+               return sgsn_ra_utran_register(new_area->u.rai, 
new_area->rnc_id);
        default:
                LOGP(DRANAP, LOGL_NOTICE, "Iu: Unknown event received: type: 
%d\n", type);
                return -1;
diff --git a/src/sgsn/gprs_routing_area.c b/src/sgsn/gprs_routing_area.c
index 721f0c9..4400d6d 100644
--- a/src/sgsn/gprs_routing_area.c
+++ b/src/sgsn/gprs_routing_area.c
@@ -24,6 +24,7 @@
 #include <osmocom/core/logging.h>
 #include <osmocom/core/rate_ctr.h>
 #include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm23003.h>
 #include <osmocom/gsm/gsm48.h>
 #include <osmocom/sgsn/debug.h>
 #include <osmocom/sgsn/gprs_bssgp.h>
@@ -181,6 +182,19 @@
        return NULL;
 }

+struct sgsn_ra *sgsn_ra_utran_get_ra(const struct osmo_routing_area_id *ra_id)
+{
+       struct sgsn_ra *ra = sgsn_ra_get_ra(ra_id);
+
+       if (!ra)
+               return ra;
+
+       if (ra->ran_type == RA_TYPE_UTRAN_Iu)
+               return ra;
+
+       return NULL;
+}
+
 int sgsn_ra_foreach_cell(struct sgsn_ra *ra, sgsn_ra_cb_t *cb, void *cb_data)
 {
        struct sgsn_ra_cell *cell, *tmp;
@@ -419,6 +433,74 @@
        return ret;
 }

+#ifdef BUILD_IU
+/* Register a new UTRAN Routing Area if possible.
+ * Return 0 on success and < 0 on failure. */
+int sgsn_ra_utran_register(const struct osmo_routing_area_id *rai, const 
struct osmo_rnc_id *rnc_id)
+{
+       struct sgsn_ra *ra = sgsn_ra_get_ra(rai);
+       if (!ra) {
+               ra = sgsn_ra_alloc(rai, RA_TYPE_UTRAN_Iu);
+               if (!ra) {
+                       LOGP(DRA, LOGL_ERROR, "Couldn't create new RA for %s 
ran type %s\n",
+                            osmo_rai_name2(rai), 
get_value_string(sgsn_ra_ran_type_names, ra->ran_type));
+                       return -ENOMEM;
+               }
+               ra->u.utran.rnc_id = *rnc_id;
+               LOGRA(LOGL_INFO, ra, "New UTRAN RA by RNC %s\n", 
osmo_rnc_id_name(&ra->u.utran.rnc_id));
+               return 0;
+       }
+
+       if (ra->ran_type == RA_TYPE_GERAN_Gb) {
+               LOGRA(LOGL_ERROR, ra, "rejecting new RA of type %s, because 
already present RA has ran type %s\n",
+                     get_value_string(sgsn_ra_ran_type_names, 
RA_TYPE_UTRAN_Iu),
+                     get_value_string(sgsn_ra_ran_type_names, ra->ran_type));
+               return -ENOENT;
+       }
+
+       /* RA already known */
+       if (osmo_rnc_id_cmp(&ra->u.utran.rnc_id, rnc_id) == 0)
+               return 0;
+
+       /* RNC id changed */
+       char new_rnc_id_name[32];
+       osmo_rnc_id_name_buf(new_rnc_id_name, sizeof(new_rnc_id_name), rnc_id);
+       LOGRA(LOGL_INFO, ra, "RNC Id changed from %s to %s\n",
+               osmo_rnc_id_name(&ra->u.utran.rnc_id), new_rnc_id_name);
+
+       ra->u.utran.rnc_id = *rnc_id;
+       return 0;
+}
+
+int sgsn_ra_utran_page_ra(const struct osmo_routing_area_id *ra_id, const 
struct sgsn_mm_ctx *mmctx)
+{
+       struct sgsn_ra *ra;
+       rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
+
+       ra = sgsn_ra_utran_get_ra(ra_id);
+       if (!ra)
+               return -ENOENT;
+
+       /* Try to page by TMSI if possible */
+       if (mmctx->p_tmsi != GSM_RESERVED_TMSI)
+               return ranap_iu_page_ps2(mmctx->imsi, &mmctx->p_tmsi, ra_id);
+       if (mmctx->p_tmsi_old != GSM_RESERVED_TMSI)
+               return ranap_iu_page_ps2(mmctx->imsi, &mmctx->p_tmsi_old, 
ra_id);
+
+       /* Page by IMSI */
+       return ranap_iu_page_ps2(mmctx->imsi, NULL, ra_id);
+}
+#else
+int sgsn_ra_utran_page_ra(const struct osmo_routing_area_id *ra_id, const 
struct sgsn_mm_ctx *mmctx)
+{
+       return -1;
+}
+int sgsn_ra_utran_register(const struct osmo_routing_area_id *rai, const 
struct osmo_rnc_id *rnc_id)
+{
+       return -1;
+}
+#endif /* BUILD_IU */
+
 void sgsn_ra_init(struct sgsn_instance *inst)
 {
        inst->routing_area = talloc_zero(inst, struct sgsn_ra_global);
diff --git a/tests/gprs_routing_area/gprs_routing_area_test.c 
b/tests/gprs_routing_area/gprs_routing_area_test.c
index b9840b9..b4b5b21 100644
--- a/tests/gprs_routing_area/gprs_routing_area_test.c
+++ b/tests/gprs_routing_area/gprs_routing_area_test.c
@@ -24,6 +24,7 @@
 #include <osmocom/core/rate_ctr.h>
 #include <osmocom/core/utils.h>
 #include <osmocom/gsm/apn.h>
+#include <osmocom/gsm/gsm23003.h>
 #include <osmocom/gsm/gsm_utils.h>
 #include <osmocom/gsm/gsup.h>
 #include <osmocom/gprs/gprs_bssgp.h>
@@ -537,6 +538,98 @@
        cleanup_test();
 }

+/* check if UTRAN RA gets rejected, if a GERAN RA/cell with the same LAC is 
already registered
+ * The SGSN does not support the same LAC/RA for GERAN and UTRAN at the same 
time.
+ */
+void test_routing_area_mv_utran_geran_reject(void)
+{
+       int rc;
+
+       /* GERAN */
+       struct osmo_routing_area_id geran_rai = {
+               .lac = {
+                       .plmn = { .mcc = 262, .mnc = 42, .mnc_3_digits = false 
},
+                       .lac = 24
+               },
+               .rac = 43
+       };
+       struct osmo_cell_global_id_ps cgi_ps = {
+               .rai = geran_rai,
+               .cell_identity = 9998,
+       };
+       uint16_t nsei = 2, bvci = 3;
+
+       /* UTRAN */
+       struct osmo_routing_area_id utran_rai = {
+               .lac = {
+                       .plmn = { .mcc = 262, .mnc = 42, .mnc_3_digits = false 
},
+                       .lac = 24
+               },
+               .rac = 43
+       };
+       struct osmo_rnc_id rnc_id = {
+               .plmn = utran_rai.lac.plmn,
+               .rnc_id = 2222
+       };
+
+       sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
+
+       /* Registering UTRAN RA */
+       rc = sgsn_ra_utran_register(&utran_rai, &rnc_id);
+       OSMO_ASSERT(rc == 0);
+
+       /* Registering GERAN RA/cell via BVC Reset Ind (should fail) */
+       rc = sgsn_ra_geran_bvc_cell_reset_ind(nsei, bvci, &cgi_ps);
+       OSMO_ASSERT(rc != 0);
+
+       cleanup_test();
+}
+
+/* check if a UTRAN RA with the same LAC as an already register GERAN RA gets 
rejected */
+void test_routing_area_mv_geran_utran_reject(void)
+{
+       int rc;
+
+       /* GERAN */
+       struct osmo_routing_area_id geran_rai = {
+               .lac = {
+                       .plmn = { .mcc = 262, .mnc = 42, .mnc_3_digits = false 
},
+                       .lac = 24
+               },
+               .rac = 43
+       };
+       struct osmo_cell_global_id_ps cgi_ps = {
+               .rai = geran_rai,
+               .cell_identity = 9998,
+       };
+       uint16_t nsei = 2, bvci = 3;
+
+       /* UTRAN */
+       struct osmo_routing_area_id utran_rai = {
+               .lac = {
+                       .plmn = { .mcc = 262, .mnc = 42, .mnc_3_digits = false 
},
+                       .lac = 24
+               },
+               .rac = 43
+       };
+       struct osmo_rnc_id rnc_id = {
+               .plmn = utran_rai.lac.plmn,
+               .rnc_id = 2222
+       };
+
+       sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
+
+       /* Registering GERAN RA/cell via BVC Reset Ind */
+       rc = sgsn_ra_geran_bvc_cell_reset_ind(nsei, bvci, &cgi_ps);
+       OSMO_ASSERT(rc == 0);
+
+       /* Registering UTRAN RA (should fail) */
+       rc = sgsn_ra_utran_register(&utran_rai, &rnc_id);
+       OSMO_ASSERT(rc != 0);
+
+       cleanup_test();
+}
+
 static struct log_info_cat gprs_categories[] = {
        [DMM] = {
                .name = "DMM",
@@ -601,6 +694,10 @@
        test_routing_area_paging();
        test_routing_area_geran_geran_sig_reset();
        test_routing_area_geran_geran_bvci_change();
+#ifdef BUILD_IU
+       test_routing_area_mv_geran_utran_reject();
+       test_routing_area_mv_utran_geran_reject();
+#endif
        printf("Done\n");

        talloc_report_full(osmo_sgsn_ctx, stderr);

--
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/40813?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: I1b1aedd2a7c358bd388aa3d8a9f3c6a0011b4889
Gerrit-Change-Number: 40813
Gerrit-PatchSet: 7
Gerrit-Owner: lynxis lazus <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <[email protected]>
Gerrit-Reviewer: lynxis lazus <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to