lynxis lazus submitted this change.

View Change



17 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.

Approvals: daniel: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve
Implement correct Routing Area based paging

Previous the SGSN would not support multiple BSS within the
same routing area.
Add support paging of a whole routing area.

Change-Id: I181da9f656e394ccfcb8999021a5b7e13ca0419f
---
M include/osmocom/sgsn/gprs_bssgp.h
M include/osmocom/sgsn/gprs_routing_area.h
M src/sgsn/gprs_bssgp.c
M src/sgsn/gprs_routing_area.c
M src/sgsn/sgsn_libgtp.c
M src/sgsn/sgsn_vty.c
M tests/gprs_routing_area/gprs_routing_area_test.c
M tests/gprs_routing_area/gprs_routing_area_test.ok
8 files changed, 139 insertions(+), 18 deletions(-)

diff --git a/include/osmocom/sgsn/gprs_bssgp.h b/include/osmocom/sgsn/gprs_bssgp.h
index abfe9f1..e2faf38 100644
--- a/include/osmocom/sgsn/gprs_bssgp.h
+++ b/include/osmocom/sgsn/gprs_bssgp.h
@@ -11,5 +11,5 @@
/* called by the bssgp layer to send NS PDUs */
int sgsn_bssgp_dispatch_ns_unitdata_req_cb(void *ctx, struct msgb *msg);

-/* page a MS in its routing area */
-int sgsn_bssgp_page_ps_ra(struct sgsn_mm_ctx *mmctx);
+/* page a MS in a single cell */
+int sgsn_bssgp_page_ps_bvci(struct sgsn_mm_ctx *mmctx, uint16_t nsei, uint16_t bvci);
diff --git a/include/osmocom/sgsn/gprs_routing_area.h b/include/osmocom/sgsn/gprs_routing_area.h
index 34e29cb..caaed47 100644
--- a/include/osmocom/sgsn/gprs_routing_area.h
+++ b/include/osmocom/sgsn/gprs_routing_area.h
@@ -9,6 +9,7 @@
#include <osmocom/gsm/gsm23003.h>

struct sgsn_instance;
+struct sgsn_mm_ctx;

struct sgsn_ra_global {
/* list of struct sgsn_ra */
@@ -86,3 +87,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_geran_page_ra(struct osmo_routing_area_id *ra_id, struct sgsn_mm_ctx *mmctx);
diff --git a/src/sgsn/gprs_bssgp.c b/src/sgsn/gprs_bssgp.c
index fd82b15..e738f0b 100644
--- a/src/sgsn/gprs_bssgp.c
+++ b/src/sgsn/gprs_bssgp.c
@@ -22,7 +22,6 @@
*/

#include <osmocom/core/prim.h>
-#include <osmocom/core/rate_ctr.h>

#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns2.h>
@@ -95,26 +94,20 @@
return 0;
}

-int sgsn_bssgp_page_ps_ra(struct sgsn_mm_ctx *mmctx)
+int sgsn_bssgp_page_ps_bvci(struct sgsn_mm_ctx *mmctx, uint16_t nsei, uint16_t bvci)
{
struct bssgp_paging_info pinfo;
- int rc;
-
- /* FIXME: page whole routing area, not only the last known cell */

/* initiate PS PAGING procedure */
memset(&pinfo, 0, sizeof(pinfo));
pinfo.mode = BSSGP_PAGING_PS;
pinfo.scope = BSSGP_PAGING_BVCI;
- pinfo.bvci = mmctx->gb.bvci;
+ pinfo.bvci = bvci;
pinfo.imsi = mmctx->imsi;
pinfo.ptmsi = &mmctx->p_tmsi;
pinfo.drx_params = mmctx->drx_parms;
pinfo.qos[0] = 0; // FIXME
- rc = bssgp_tx_paging(mmctx->gb.nsei, 0, &pinfo);
- rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
-
- return rc;
+ return bssgp_tx_paging(nsei, 0, &pinfo);
}

/* called by the bssgp layer to send NS PDUs */
diff --git a/src/sgsn/gprs_routing_area.c b/src/sgsn/gprs_routing_area.c
index 977caa2..67b15ae 100644
--- a/src/sgsn/gprs_routing_area.c
+++ b/src/sgsn/gprs_routing_area.c
@@ -22,11 +22,11 @@

#include <osmocom/core/linuxlist.h>
#include <osmocom/core/logging.h>
-#include <osmocom/sgsn/debug.h>
-
-
+#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/gsm48.h>
-
+#include <osmocom/sgsn/debug.h>
+#include <osmocom/sgsn/gprs_bssgp.h>
+#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/sgsn.h>

#include <osmocom/sgsn/gprs_routing_area.h>
@@ -330,6 +330,28 @@
return found ? 0 : -ENOENT;
}

+int sgsn_ra_geran_page_ra(struct osmo_routing_area_id *ra_id, struct sgsn_mm_ctx *mmctx)
+{
+ struct sgsn_ra *ra;
+ struct sgsn_ra_cell *cell;
+ int ret = -ENOENT;
+
+ rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
+
+ ra = sgsn_ra_get_ra(ra_id);
+ if (!ra)
+ return -ENOENT;
+
+ llist_for_each_entry(cell, &ra->cells, list) {
+ if (cell->ran_type == RA_TYPE_GERAN_Gb) {
+ sgsn_bssgp_page_ps_bvci(mmctx, cell->u.geran.nsei, cell->u.geran.bvci);
+ ret = 0;
+ }
+ }
+
+
+ return ret;
+}

void sgsn_ra_init(struct sgsn_instance *inst)
{
diff --git a/src/sgsn/sgsn_libgtp.c b/src/sgsn/sgsn_libgtp.c
index faf0e7f..8eb77b0 100644
--- a/src/sgsn/sgsn_libgtp.c
+++ b/src/sgsn/sgsn_libgtp.c
@@ -47,6 +47,7 @@
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_ns.h>
#include <osmocom/sgsn/gprs_llc.h>
+#include <osmocom/sgsn/gprs_routing_area.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_sm.h>
@@ -864,7 +865,7 @@
LOGMMCTXP(LOGL_INFO, mm, "Paging MS in GMM state %s, MM state %s\n",
osmo_fsm_inst_state_name(mm->gmm_fsm),
osmo_fsm_inst_state_name(mm->gb.mm_state_fsm));
- sgsn_bssgp_page_ps_ra(mm);
+ sgsn_ra_geran_page_ra(&mm->ra, mm);

/* FIXME: queue the packet we received from GTP */
break;
diff --git a/src/sgsn/sgsn_vty.c b/src/sgsn/sgsn_vty.c
index bcb8dc2..a7e8045 100644
--- a/src/sgsn/sgsn_vty.c
+++ b/src/sgsn/sgsn_vty.c
@@ -41,6 +41,7 @@
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_bssgp.h>
#include <osmocom/sgsn/mmctx.h>
+#include <osmocom/sgsn/gprs_routing_area.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gtp_mme.h>
#include <osmocom/sgsn/vty.h>
@@ -1333,7 +1334,7 @@
return CMD_WARNING;
}

- sgsn_bssgp_page_ps_ra(mm);
+ sgsn_ra_geran_page_ra(&mm->ra, mm);
return CMD_SUCCESS;
}

diff --git a/tests/gprs_routing_area/gprs_routing_area_test.c b/tests/gprs_routing_area/gprs_routing_area_test.c
index d879f39..e1aec0f 100644
--- a/tests/gprs_routing_area/gprs_routing_area_test.c
+++ b/tests/gprs_routing_area/gprs_routing_area_test.c
@@ -44,6 +44,17 @@
void *tall_sgsn_ctx;
struct sgsn_instance *sgsn;

+struct paging_exp {
+ uint16_t nsei;
+ uint16_t bvci;
+ /* paged when we send one paging request */
+ bool paged;
+ /* valid when this entry contains valid data */
+ bool valid;
+};
+
+struct paging_exp g_paging[4];
+
static void cleanup_test(void)
{
TALLOC_FREE(sgsn);
@@ -326,6 +337,93 @@
cleanup_test();
}

+/* BSSGP Paging RA */
+int bssgp_tx_paging(uint16_t nsei, uint16_t _bvci,
+ struct bssgp_paging_info *pinfo)
+{
+ bool found = false;
+
+ OSMO_ASSERT(pinfo);
+ fprintf(stderr, "Tx paging for nsei %05u / bvci %05u\n", nsei, pinfo->bvci);
+ /* match against list of expect pagings */
+ for (int i = 0; i < ARRAY_SIZE(g_paging); i++) {
+ struct paging_exp *exp = &g_paging[i];
+ if (exp->paged || !exp->valid)
+ continue;
+
+ if (exp->nsei == nsei && exp->bvci == pinfo->bvci) {
+ exp->paged = true;
+ found = true;
+ break;
+ }
+ }
+
+ OSMO_ASSERT(found);
+ return 0;
+}
+
+static void check_paging(void)
+{
+ for (int i = 0; i < ARRAY_SIZE(g_paging); i++) {
+ struct paging_exp *exp = &g_paging[i];
+ if (!exp->valid)
+ continue;
+ OSMO_ASSERT(exp->paged)
+ }
+}
+
+void test_routing_area_paging(void)
+{
+ struct sgsn_mm_ctx *mmctx;
+ struct osmo_routing_area_id ra_id = {
+ .lac = {
+ .plmn = { .mcc = 262, .mnc = 42, .mnc_3_digits = false },
+ .lac = 24
+ },
+ .rac = 43
+ };
+
+ uint16_t cell_id = 9999;
+ struct osmo_cell_global_id_ps cgi_ps = {
+ .rai = ra_id,
+ .cell_identity = cell_id,
+ };
+
+ uint16_t nsei = 2, bvci = 3;
+ int rc;
+
+ printf("Testing Routing Area paging\n");
+
+ sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
+
+ memset(g_paging, 0, sizeof(g_paging));
+ g_paging[0].bvci = bvci;
+ g_paging[0].nsei = nsei;
+ g_paging[0].valid = true;
+ g_paging[0].paged = false;
+
+ rc = sgsn_ra_bvc_reset_ind(nsei, bvci, &cgi_ps);
+ OSMO_ASSERT(rc == 0);
+
+ cgi_ps.cell_identity++;
+ rc = sgsn_ra_bvc_reset_ind(nsei, bvci+1, &cgi_ps);
+ OSMO_ASSERT(rc == 0);
+
+ g_paging[1].bvci = bvci+1;
+ g_paging[1].nsei = nsei;
+ g_paging[1].valid = true;
+ g_paging[1].paged = false;
+
+ mmctx = sgsn_mm_ctx_alloc_gb(0xc0001234, &ra_id);
+
+ sgsn_ra_geran_page_ra(&ra_id, mmctx);
+ check_paging();
+
+ sgsn_mm_ctx_cleanup_free(mmctx);
+
+ cleanup_test();
+}
+
static struct log_info_cat gprs_categories[] = {
[DMM] = {
.name = "DMM",
@@ -387,6 +485,7 @@
test_routing_area_free_empty();
test_routing_area_reset_ind();
test_routing_area_nsei_free();
+ test_routing_area_paging();
printf("Done\n");

talloc_report_full(osmo_sgsn_ctx, stderr);
diff --git a/tests/gprs_routing_area/gprs_routing_area_test.ok b/tests/gprs_routing_area/gprs_routing_area_test.ok
index dccbb5e..78cee7e 100644
--- a/tests/gprs_routing_area/gprs_routing_area_test.ok
+++ b/tests/gprs_routing_area/gprs_routing_area_test.ok
@@ -3,4 +3,5 @@
Testing Routing Area create/free
Testing Routing Area BSSGP BVC RESET IND
Testing Routing Area nsei failure
+Testing Routing Area paging
Done

To view, visit change 37866. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: I181da9f656e394ccfcb8999021a5b7e13ca0419f
Gerrit-Change-Number: 37866
Gerrit-PatchSet: 18
Gerrit-Owner: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann@sysmocom.de>
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-CC: fixeria <vyanitskiy@sysmocom.de>