lynxis lazus has submitted this change. (
https://gerrit.osmocom.org/c/osmo-sgsn/+/37866?usp=email )
(
17 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: Implement correct Routing Area based paging
......................................................................
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(-)
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
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
https://gerrit.osmocom.org/c/osmo-sgsn/+/37866?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: I181da9f656e394ccfcb8999021a5b7e13ca0419f
Gerrit-Change-Number: 37866
Gerrit-PatchSet: 18
Gerrit-Owner: lynxis lazus <lynxis(a)fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>