Skip to content

Commit

Permalink
Implement correct Routing Area based paging
Browse files Browse the repository at this point in the history
Previous the SGSN would not support multiple BSS within the
same routing area.
Add support paging of a whole routing area.

Change-Id: I181da9f656e394ccfcb8999021a5b7e13ca0419f
  • Loading branch information
lynxis committed Oct 21, 2024
1 parent e8c82d9 commit e7303ad
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 18 deletions.
4 changes: 2 additions & 2 deletions include/osmocom/sgsn/gprs_bssgp.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph);
/* 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);
4 changes: 4 additions & 0 deletions include/osmocom/sgsn/gprs_routing_area.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -86,3 +87,6 @@ struct sgsn_ra *sgsn_ra_get_ra(const struct osmo_routing_area_id *ra_id);
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);
13 changes: 3 additions & 10 deletions src/sgsn/gprs_bssgp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -95,26 +94,20 @@ int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph)
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 */
Expand Down
30 changes: 26 additions & 4 deletions src/sgsn/gprs_routing_area.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -330,6 +330,28 @@ int sgsn_ra_nsei_failure_ind(uint16_t nsei)
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)
{
Expand Down
3 changes: 2 additions & 1 deletion src/sgsn/sgsn_libgtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -864,7 +865,7 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
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;
Expand Down
3 changes: 2 additions & 1 deletion src/sgsn/sgsn_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -1333,7 +1334,7 @@ DEFUN(page_subscr, page_subscr_info_cmd,
return CMD_WARNING;
}

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

Expand Down
99 changes: 99 additions & 0 deletions tests/gprs_routing_area/gprs_routing_area_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -326,6 +337,93 @@ void test_routing_area_nsei_free(void)
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",
Expand Down Expand Up @@ -387,6 +485,7 @@ int main(int argc, char **argv)
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);
Expand Down
1 change: 1 addition & 0 deletions tests/gprs_routing_area/gprs_routing_area_test.ok
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ Testing Routing Area find
Testing Routing Area create/free
Testing Routing Area BSSGP BVC RESET IND
Testing Routing Area nsei failure
Testing Routing Area paging
Done

0 comments on commit e7303ad

Please sign in to comment.