mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn.git
synced 2025-10-23 08:21:59 +00:00
Add Routing Areas
Add a routing area layer which tracks routing area and cells within a routing area. Change-Id: I2474b19a7471a1dea3c863ddf8372b16180211aa
This commit is contained in:
@@ -243,6 +243,7 @@ AC_OUTPUT(
|
||||
tests/Makefile
|
||||
tests/atlocal
|
||||
tests/gprs/Makefile
|
||||
tests/gprs_routing_area/Makefile
|
||||
tests/sgsn/Makefile
|
||||
tests/gtphub/Makefile
|
||||
tests/xid/Makefile
|
||||
|
@@ -14,6 +14,7 @@ noinst_HEADERS = \
|
||||
gprs_llc.h \
|
||||
gprs_llc_xid.h \
|
||||
gprs_ranap.h \
|
||||
gprs_routing_area.h \
|
||||
gprs_sm.h \
|
||||
gprs_sndcp_comp.h \
|
||||
gprs_sndcp_dcomp.h \
|
||||
|
@@ -27,6 +27,7 @@ enum {
|
||||
DGTP,
|
||||
DOBJ,
|
||||
DRIM,
|
||||
DRA, /* Routing Area handling */
|
||||
Debug_LastEntry,
|
||||
};
|
||||
|
||||
|
88
include/osmocom/sgsn/gprs_routing_area.h
Normal file
88
include/osmocom/sgsn/gprs_routing_area.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*! \file gprs_routing_area.h */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
|
||||
struct sgsn_instance;
|
||||
|
||||
struct sgsn_ra_global {
|
||||
/* list of struct sgsn_ra */
|
||||
struct llist_head ra_list;
|
||||
};
|
||||
|
||||
struct sgsn_ra {
|
||||
/* Entry in sgsn_ra_global->ra_list */
|
||||
struct llist_head list;
|
||||
|
||||
struct osmo_routing_area_id rai;
|
||||
/* cells contains a list of sgsn_ra_cells which are alive */
|
||||
struct llist_head cells;
|
||||
};
|
||||
|
||||
enum sgsn_ra_ran_type {
|
||||
RA_TYPE_GERAN_Gb,
|
||||
RA_TYPE_UTRAN_Iu,
|
||||
};
|
||||
|
||||
struct sgsn_ra_cell {
|
||||
/* Entry in sgsn_ra->cells */
|
||||
struct llist_head list;
|
||||
|
||||
/*! link back to the parent */
|
||||
struct sgsn_ra *ra;
|
||||
|
||||
enum sgsn_ra_ran_type ran_type;
|
||||
|
||||
uint16_t cell_id;
|
||||
union {
|
||||
struct {
|
||||
uint16_t nsei;
|
||||
uint16_t bvci;
|
||||
} geran;
|
||||
struct {
|
||||
/* TODO: unused */
|
||||
uint16_t rncid;
|
||||
uint16_t sac;
|
||||
} utran;
|
||||
} u;
|
||||
};
|
||||
|
||||
void sgsn_ra_init(struct sgsn_instance *inst);
|
||||
|
||||
struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai);
|
||||
void sgsn_ra_free(struct sgsn_ra *ra);
|
||||
struct sgsn_ra_cell *sgsn_ra_cell_alloc_geran(struct sgsn_ra *ra, uint16_t cell_id, uint16_t nsei, uint16_t bvci);
|
||||
void sgsn_ra_cell_free(struct sgsn_ra_cell *cell);
|
||||
|
||||
/* Called by BSSGP layer to inform about a reset on a BVCI */
|
||||
int sgsn_ra_bvc_reset_ind(uint16_t nsei, uint16_t bvci, struct osmo_cell_global_id_ps *cgi_ps);
|
||||
/* FIXME: handle BVC BLOCK/UNBLOCK/UNAVAILABLE */
|
||||
/* Called by NS-VC layer to inform about an unavailable NSEI (and all BVCI on them) */
|
||||
int sgsn_ra_nsei_failure_ind(uint16_t nsei);
|
||||
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_cgi_ps(const struct osmo_cell_global_id_ps *cgi_ps);
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_lai(const struct osmo_location_area_id *lai, uint16_t cell_id);
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_cgi(const struct osmo_cell_global_id *cgi);
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_ra(const struct sgsn_ra *ra, uint16_t cell_id);
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_gb(uint16_t nsei, uint16_t bvci);
|
||||
struct sgsn_ra *sgsn_ra_get_ra(const struct osmo_routing_area_id *ra_id);
|
||||
|
||||
|
||||
/*
|
||||
* return value for callbacks.
|
||||
* STOP: stop calling the callback for the remaining cells, sgsn_ra_foreach_ra() returns 0
|
||||
* CONT: continue to call the callback for remaining cells
|
||||
* ABORT: stop calling the callback for the remaining cells, sgsn_ra_foreach_ra() returns -1
|
||||
*/
|
||||
#define SGSN_RA_CB_STOP 1
|
||||
#define SGSN_RA_CB_CONT 0
|
||||
#define SGSN_RA_CB_ERROR -1
|
||||
|
||||
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);
|
@@ -152,6 +152,9 @@ struct sgsn_instance {
|
||||
ares_channel ares_channel;
|
||||
struct ares_addr_node *ares_servers;
|
||||
|
||||
/* Routing areas */
|
||||
struct sgsn_ra_global *routing_area;
|
||||
|
||||
struct rate_ctr_group *rate_ctrs;
|
||||
|
||||
struct llist_head apn_list; /* list of struct sgsn_apn_ctx */
|
||||
|
@@ -47,6 +47,7 @@ osmo_sgsn_SOURCES = \
|
||||
gprs_gmm_fsm.c \
|
||||
gprs_mm_state_gb_fsm.c \
|
||||
gprs_ns.c \
|
||||
gprs_routing_area.c \
|
||||
gprs_sm.c \
|
||||
gprs_sndcp.c \
|
||||
gprs_sndcp_comp.c \
|
||||
|
@@ -20,6 +20,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/prim.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
@@ -30,9 +31,26 @@
|
||||
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_routing_area.h>
|
||||
#include <osmocom/sgsn/sgsn_rim.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
static int bssgp_nm_bvc_reset_ind(struct osmo_bssgp_prim *bp)
|
||||
{
|
||||
struct osmo_cell_global_id_ps cgi_ps = {};
|
||||
|
||||
if (!bp->tp)
|
||||
return -EINVAL;
|
||||
|
||||
if (!TLVP_PRES_LEN(bp->tp, BSSGP_IE_CELL_ID, 8))
|
||||
return -EINVAL;
|
||||
|
||||
bssgp_parse_cell_id2(&cgi_ps.rai, &cgi_ps.cell_identity, TLVP_VAL(bp->tp, BSSGP_IE_CELL_ID), 8);
|
||||
return sgsn_ra_bvc_reset_ind(bp->nsei, bp->bvci, &cgi_ps);
|
||||
}
|
||||
|
||||
/* call-back function for the BSSGP protocol */
|
||||
int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph)
|
||||
{
|
||||
@@ -58,6 +76,18 @@ int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph)
|
||||
}
|
||||
break;
|
||||
case SAP_BSSGP_NM:
|
||||
switch (oph->primitive) {
|
||||
case PRIM_NM_BVC_RESET:
|
||||
if (oph->operation == PRIM_OP_INDICATION)
|
||||
bssgp_nm_bvc_reset_ind(bp);
|
||||
break;
|
||||
case PRIM_NM_BVC_BLOCK:
|
||||
case PRIM_NM_BVC_UNBLOCK:
|
||||
case PRIM_NM_STATUS:
|
||||
case PRIM_NM_LLC_DISCARDED:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case SAP_BSSGP_RIM:
|
||||
return sgsn_rim_rx_from_gb(bp, oph->msg);
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gprs/gprs_bssgp_bss.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_routing_area.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -52,6 +53,7 @@ void gprs_ns_prim_status_cb(struct osmo_gprs_ns2_prim *nsp)
|
||||
break;
|
||||
case GPRS_NS2_AFF_CAUSE_FAILURE:
|
||||
LOGP(DGPRS, LOGL_NOTICE, "NS-E %d became unavailable\n", nsp->nsei);
|
||||
sgsn_ra_nsei_failure_ind(nsp->nsei);
|
||||
break;
|
||||
default:
|
||||
LOGP(DGPRS, LOGL_NOTICE, "NS: %s Unknown prim %d from NS\n",
|
||||
|
340
src/sgsn/gprs_routing_area.c
Normal file
340
src/sgsn/gprs_routing_area.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/* SGSN Routing Area for 2G */
|
||||
|
||||
/* (C) 2024 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* Author: Alexander Couzens <lynxis@fe80.eu>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_routing_area.h>
|
||||
|
||||
static void _sgsn_ra_cell_free(struct sgsn_ra_cell *cell, bool drop_empty_ra)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
|
||||
if (!cell)
|
||||
return;
|
||||
|
||||
llist_del(&cell->list);
|
||||
/* to prevent double free of the Cell when freeing a Routing Area */
|
||||
if (!drop_empty_ra) {
|
||||
talloc_free(cell);
|
||||
return;
|
||||
}
|
||||
|
||||
ra = cell->ra;
|
||||
talloc_free(cell);
|
||||
|
||||
if (llist_empty(&ra->cells))
|
||||
sgsn_ra_free(ra);
|
||||
}
|
||||
|
||||
void sgsn_ra_cell_free(struct sgsn_ra_cell *cell)
|
||||
{
|
||||
_sgsn_ra_cell_free(cell, true);
|
||||
}
|
||||
|
||||
void sgsn_ra_free(struct sgsn_ra *ra)
|
||||
{
|
||||
struct sgsn_ra_cell *cell, *cell2;
|
||||
|
||||
if (!ra)
|
||||
return;
|
||||
|
||||
llist_for_each_entry_safe(cell, cell2, &ra->cells, list) {
|
||||
_sgsn_ra_cell_free(cell, false);
|
||||
}
|
||||
|
||||
llist_del(&ra->list);
|
||||
talloc_free(ra);
|
||||
}
|
||||
|
||||
struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
ra = talloc_zero(sgsn->routing_area, struct sgsn_ra);
|
||||
if (!ra)
|
||||
return NULL;
|
||||
|
||||
INIT_LLIST_HEAD(&ra->cells);
|
||||
ra->rai = *rai;
|
||||
llist_add(&ra->list, &sgsn->routing_area->ra_list);
|
||||
return ra;
|
||||
}
|
||||
|
||||
struct sgsn_ra_cell *sgsn_ra_cell_alloc_geran(struct sgsn_ra *ra, uint16_t cell_id, uint16_t nsei, uint16_t bvci)
|
||||
{
|
||||
struct sgsn_ra_cell *cell;
|
||||
|
||||
cell = talloc_zero(ra, struct sgsn_ra_cell);
|
||||
if (!cell)
|
||||
return NULL;
|
||||
|
||||
cell->ra = ra;
|
||||
cell->cell_id = cell_id;
|
||||
cell->ran_type = RA_TYPE_GERAN_Gb;
|
||||
cell->u.geran.bvci = bvci;
|
||||
cell->u.geran.nsei = nsei;
|
||||
|
||||
llist_add(&cell->list, &ra->cells);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
struct sgsn_ra *sgsn_ra_get_ra(const struct osmo_routing_area_id *ra_id)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
|
||||
llist_for_each_entry(ra, &sgsn->routing_area->ra_list, list)
|
||||
if (osmo_rai_cmp(&ra->rai, ra_id) == 0)
|
||||
return ra;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_gb(uint16_t nsei, uint16_t bvci)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
struct sgsn_ra_cell *cell;
|
||||
|
||||
/* BVCI = 0 is invalid, only valid for signalling within the BSSGP, not for a single cell */
|
||||
if (bvci == 0)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(ra, &sgsn->routing_area->ra_list, list) {
|
||||
llist_for_each_entry(cell, &ra->cells, list) {
|
||||
if (cell->ran_type != RA_TYPE_GERAN_Gb)
|
||||
continue;
|
||||
|
||||
if (cell->u.geran.bvci == bvci && cell->u.geran.nsei == nsei)
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
int ret = -ENOENT;
|
||||
|
||||
OSMO_ASSERT(cb);
|
||||
|
||||
llist_for_each_entry_safe(cell, tmp, &ra->cells, list) {
|
||||
ret = cb(cell, cb_data);
|
||||
switch (ret) {
|
||||
case SGSN_RA_CB_CONT:
|
||||
continue;
|
||||
case SGSN_RA_CB_STOP:
|
||||
return 0;
|
||||
case SGSN_RA_CB_ERROR:
|
||||
return -1;
|
||||
default:
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sgsn_ra_foreach_cell2(struct osmo_routing_area_id *ra_id, sgsn_ra_cb_t *cb, void *cb_data)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
OSMO_ASSERT(ra_id);
|
||||
OSMO_ASSERT(cb);
|
||||
|
||||
ra = sgsn_ra_get_ra(ra_id);
|
||||
if (!ra)
|
||||
return -ENOENT;
|
||||
|
||||
return sgsn_ra_foreach_cell(ra, cb, cb_data);
|
||||
}
|
||||
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_ra(const struct sgsn_ra *ra, uint16_t cell_id)
|
||||
{
|
||||
struct sgsn_ra_cell *cell;
|
||||
|
||||
llist_for_each_entry(cell, &ra->cells, list) {
|
||||
if (cell->cell_id == cell_id)
|
||||
return cell;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_lai(const struct osmo_location_area_id *lai, uint16_t cell_id)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
struct sgsn_ra_cell *cell;
|
||||
|
||||
/* This is a little bit in-efficient. A more performance way, but more complex would
|
||||
* adding a llist for LAC on top of the routing areas */
|
||||
llist_for_each_entry(ra, &sgsn->routing_area->ra_list, list) {
|
||||
if (osmo_lai_cmp(&ra->rai.lac, lai) != 0)
|
||||
continue;
|
||||
|
||||
llist_for_each_entry(cell, &ra->cells, list) {
|
||||
if (cell->cell_id == cell_id)
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! Return the cell by searching for the RA, when found, search the cell within the RA
|
||||
*
|
||||
* \param cgi_ps
|
||||
* \return the cell or NULL if not found
|
||||
*/
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_cgi_ps(const struct osmo_cell_global_id_ps *cgi_ps)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
|
||||
OSMO_ASSERT(cgi_ps);
|
||||
|
||||
ra = sgsn_ra_get_ra(&cgi_ps->rai);
|
||||
if (!ra)
|
||||
return NULL;
|
||||
|
||||
return sgsn_ra_get_cell_by_ra(ra, cgi_ps->cell_identity);
|
||||
}
|
||||
|
||||
struct sgsn_ra_cell *sgsn_ra_get_cell_by_cgi(const struct osmo_cell_global_id *cgi)
|
||||
{
|
||||
OSMO_ASSERT(cgi);
|
||||
|
||||
return sgsn_ra_get_cell_by_lai(&cgi->lai, cgi->cell_identity);
|
||||
}
|
||||
|
||||
/*! Callback from the BSSGP layer on NM RESET IND
|
||||
*
|
||||
* \param nsei
|
||||
* \param bvci
|
||||
* \param cgi_ps
|
||||
* \return 0 on success or -ENOMEM
|
||||
*/
|
||||
int sgsn_ra_bvc_reset_ind(uint16_t nsei, uint16_t bvci, struct osmo_cell_global_id_ps *cgi_ps)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
struct sgsn_ra_cell *cell;
|
||||
bool ra_created = false;
|
||||
OSMO_ASSERT(cgi_ps);
|
||||
|
||||
/* TODO: do we have to move all MS to GMM IDLE state when this happens for a alive cell which got reseted? */
|
||||
ra = sgsn_ra_get_ra(&cgi_ps->rai);
|
||||
if (!ra) {
|
||||
ra = sgsn_ra_alloc(&cgi_ps->rai);
|
||||
if (!ra)
|
||||
return -ENOMEM;
|
||||
ra_created = true;
|
||||
}
|
||||
|
||||
if (!ra_created) {
|
||||
cell = sgsn_ra_get_cell_by_ra(ra, cgi_ps->cell_identity);
|
||||
if (cell && cell->ran_type == RA_TYPE_GERAN_Gb) {
|
||||
/* Cell already exist, update NSEI/BVCI */
|
||||
if (cell->u.geran.bvci != bvci || cell->u.geran.nsei != nsei) {
|
||||
LOGP(DRA, LOGL_INFO, "GERAN Cell changed DLCI. Old: nsei/bvci %05u/%05u New: nsei/bvci %05u/%05u\n",
|
||||
cell->u.geran.nsei, cell->u.geran.bvci, nsei, bvci);
|
||||
cell->u.geran.bvci = bvci;
|
||||
cell->u.geran.nsei = nsei;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cell && cell->ran_type != RA_TYPE_GERAN_Gb) {
|
||||
/* How can we have here a RA change? Must be a configuration error. */
|
||||
LOGP(DRA, LOGL_INFO, "CGI %s: RAN change detected to GERAN!", osmo_cgi_ps_name(cgi_ps));
|
||||
_sgsn_ra_cell_free(cell, false);
|
||||
cell = NULL;
|
||||
}
|
||||
|
||||
if (!cell) {
|
||||
char old_ra[32];
|
||||
char new_ra[32];
|
||||
/* check for the same cell id within the location area. The cell id is also unique for the cell within the LAC
|
||||
* This should only happen when a Cell is changing routing areas */
|
||||
cell = sgsn_ra_get_cell_by_lai(&cgi_ps->rai.lac, cgi_ps->cell_identity);
|
||||
if (cell) {
|
||||
LOGP(DRA, LOGL_INFO, "CGI %s: changed Routing Area. Old: %s, New: %s\n",
|
||||
osmo_cgi_ps_name(cgi_ps),
|
||||
osmo_rai_name2_buf(old_ra, sizeof(old_ra), &cell->ra->rai),
|
||||
osmo_rai_name2_buf(new_ra, sizeof(new_ra), &cgi_ps->rai));
|
||||
|
||||
OSMO_ASSERT(cell->ra != ra);
|
||||
|
||||
/* the old RA is definitive not our ra! Drop the old ra */
|
||||
_sgsn_ra_cell_free(cell, true);
|
||||
cell = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cell = sgsn_ra_cell_alloc_geran(ra, cgi_ps->cell_identity, nsei, bvci);
|
||||
if (!cell)
|
||||
return -ENOMEM;
|
||||
|
||||
LOGP(DRA, LOGL_INFO, "New cell registered %s via nsei/bvci %05u/%05u\n", osmo_cgi_ps_name(cgi_ps), nsei, bvci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: call it on BSSGP BLOCK + unavailable with BVCI */
|
||||
int sgsn_ra_nsei_failure_ind(uint16_t nsei)
|
||||
{
|
||||
struct sgsn_ra *ra, *ra2;
|
||||
struct sgsn_ra_cell *cell, *cell2;
|
||||
bool found = false;
|
||||
|
||||
llist_for_each_entry_safe(ra, ra2, &sgsn->routing_area->ra_list, list) {
|
||||
llist_for_each_entry_safe(cell, cell2, &ra->cells, list) {
|
||||
if (cell->ran_type != RA_TYPE_GERAN_Gb)
|
||||
continue;
|
||||
|
||||
if (cell->u.geran.nsei == nsei) {
|
||||
found = true;
|
||||
_sgsn_ra_cell_free(cell, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (llist_empty(&ra->cells))
|
||||
sgsn_ra_free(ra);
|
||||
|
||||
}
|
||||
|
||||
return found ? 0 : -ENOENT;
|
||||
}
|
||||
|
||||
|
||||
void sgsn_ra_init(struct sgsn_instance *inst)
|
||||
{
|
||||
inst->routing_area = talloc_zero(inst, struct sgsn_ra_global);
|
||||
OSMO_ASSERT(inst->routing_area);
|
||||
|
||||
INIT_LLIST_HEAD(&inst->routing_area->ra_list);
|
||||
}
|
@@ -55,6 +55,7 @@
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/sgsn/gprs_routing_area.h>
|
||||
|
||||
#include <pdp.h>
|
||||
|
||||
@@ -189,6 +190,7 @@ struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx)
|
||||
/* These are mostly setting up stuff not related to VTY cfg, so they can be set up here: */
|
||||
sgsn_auth_init(inst);
|
||||
sgsn_cdr_init(inst);
|
||||
sgsn_ra_init(inst);
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,7 @@
|
||||
#include <osmocom/sgsn/gprs_ranap.h>
|
||||
#include <osmocom/sgsn/gprs_ns.h>
|
||||
#include <osmocom/sgsn/gprs_bssgp.h>
|
||||
#include <osmocom/sgsn/gprs_routing_area.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
|
||||
@@ -348,6 +349,11 @@ static struct log_info_cat gprs_categories[] = {
|
||||
.description = "RAN Information Management (RIM)",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DRA] = {
|
||||
.name = "DRA",
|
||||
.description = "Routing Area",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct log_info gprs_log_info = {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
SUBDIRS = \
|
||||
gprs \
|
||||
gtphub \
|
||||
gprs_routing_area \
|
||||
sgsn \
|
||||
xid \
|
||||
sndcp_xid \
|
||||
|
93
tests/gprs_routing_area/Makefile.am
Normal file
93
tests/gprs_routing_area/Makefile.am
Normal file
@@ -0,0 +1,93 @@
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOCTRL_CFLAGS) \
|
||||
$(LIBOSMOABIS_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(LIBOSMOGSUPCLIENT_CFLAGS) \
|
||||
$(LIBCARES_CFLAGS) \
|
||||
$(LIBGTP_CFLAGS) \
|
||||
$(NULL)
|
||||
if BUILD_IU
|
||||
AM_CFLAGS += \
|
||||
$(LIBASN1C_CFLAGS) \
|
||||
$(LIBOSMOSIGTRAN_CFLAGS) \
|
||||
$(LIBOSMORANAP_CFLAGS) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = \
|
||||
gprs_routing_area_test.ok \
|
||||
$(NULL)
|
||||
|
||||
check_PROGRAMS = \
|
||||
gprs_routing_area_test \
|
||||
$(NULL)
|
||||
|
||||
gprs_routing_area_test_SOURCES = \
|
||||
gprs_routing_area_test.c \
|
||||
$(NULL)
|
||||
|
||||
gprs_routing_area_test_LDADD = \
|
||||
$(top_builddir)/src/sgsn/apn.o \
|
||||
$(top_builddir)/src/sgsn/gprs_bssgp.o \
|
||||
$(top_builddir)/src/sgsn/gprs_llc.o \
|
||||
$(top_builddir)/src/sgsn/gprs_ns.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sndcp.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm_attach.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm_fsm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_mm_state_gb_fsm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_routing_area.o \
|
||||
$(top_builddir)/src/sgsn/gtp_ggsn.o \
|
||||
$(top_builddir)/src/sgsn/gtp_mme.o \
|
||||
$(top_builddir)/src/sgsn/mmctx.o \
|
||||
$(top_builddir)/src/sgsn/pdpctx.o \
|
||||
$(top_builddir)/src/sgsn/sgsn.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_cdr.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_ctrl.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_vty.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_libgtp.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_auth.o \
|
||||
$(top_builddir)/src/sgsn/gprs_subscriber.o \
|
||||
$(top_builddir)/src/sgsn/gprs_llc_xid.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sndcp_xid.o \
|
||||
$(top_builddir)/src/sgsn/slhc.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sndcp_comp.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sndcp_pcomp.o \
|
||||
$(top_builddir)/src/sgsn/v42bis.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sndcp_dcomp.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_rim.o \
|
||||
$(top_builddir)/src/gprs/gprs_utils.o \
|
||||
$(top_builddir)/src/gprs/gprs_llc_parse.o \
|
||||
$(top_builddir)/src/gprs/crc24.o \
|
||||
$(top_builddir)/src/gprs/sgsn_ares.o \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOCTRL_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOGB_LIBS) \
|
||||
$(LIBOSMOGSUPCLIENT_LIBS) \
|
||||
$(LIBCARES_LIBS) \
|
||||
$(LIBGTP_LIBS) \
|
||||
-lrt \
|
||||
-lm \
|
||||
$(NULL)
|
||||
|
||||
if BUILD_IU
|
||||
gprs_routing_area_test_LDADD += \
|
||||
$(top_builddir)/src/sgsn/gprs_ranap.o \
|
||||
$(top_builddir)/src/sgsn/gprs_mm_state_iu_fsm.o \
|
||||
$(LIBOSMORANAP_LIBS) \
|
||||
$(LIBOSMOSIGTRAN_LIBS) \
|
||||
$(LIBASN1C_LIBS) \
|
||||
$(NULL)
|
||||
endif
|
404
tests/gprs_routing_area/gprs_routing_area_test.c
Normal file
404
tests/gprs_routing_area/gprs_routing_area_test.c
Normal file
@@ -0,0 +1,404 @@
|
||||
/* Test the SGSN routing ares */
|
||||
/*
|
||||
* (C) 2024 by sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
* Author: Alexander Couzens <lynxis@fe80.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/gsup.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
|
||||
#include <osmocom/gsupclient/gsup_client.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_routing_area.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void *tall_sgsn_ctx;
|
||||
struct sgsn_instance *sgsn;
|
||||
|
||||
static void cleanup_test(void)
|
||||
{
|
||||
TALLOC_FREE(sgsn);
|
||||
}
|
||||
|
||||
/* Create RA, free RA */
|
||||
static void test_routing_area_create(void)
|
||||
{
|
||||
struct sgsn_ra *ra;
|
||||
struct osmo_routing_area_id raid = {
|
||||
.lac = {
|
||||
.plmn = { .mcc = 262, .mnc = 42, .mnc_3_digits = false },
|
||||
.lac = 23
|
||||
},
|
||||
.rac = 42
|
||||
};
|
||||
|
||||
printf("Testing Routing Area create/free\n");
|
||||
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
ra = sgsn_ra_alloc(&raid);
|
||||
OSMO_ASSERT(ra);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
sgsn_ra_free(ra);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
/* Cleanup */
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
static void test_routing_area_free_empty(void)
|
||||
{
|
||||
|
||||
struct sgsn_ra *ra;
|
||||
struct sgsn_ra_cell *cell_a;
|
||||
struct osmo_routing_area_id raid = {
|
||||
.lac = {
|
||||
.plmn = { .mcc = 262, .mnc = 42, .mnc_3_digits = false },
|
||||
.lac = 24
|
||||
},
|
||||
.rac = 43
|
||||
};
|
||||
|
||||
uint16_t cell_id = 9999;
|
||||
uint16_t nsei = 2, bvci = 3;
|
||||
|
||||
printf("Testing Routing Area create/free\n");
|
||||
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
ra = sgsn_ra_alloc(&raid);
|
||||
OSMO_ASSERT(ra);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
cell_a = sgsn_ra_cell_alloc_geran(ra, cell_id, nsei, bvci);
|
||||
OSMO_ASSERT(cell_a);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
OSMO_ASSERT(llist_count(&ra->cells) == 1);
|
||||
|
||||
sgsn_ra_free(ra);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
ra = sgsn_ra_alloc(&raid);
|
||||
OSMO_ASSERT(ra);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
cell_a = sgsn_ra_cell_alloc_geran(ra, cell_id, nsei, bvci);
|
||||
OSMO_ASSERT(cell_a);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
OSMO_ASSERT(llist_count(&ra->cells) == 1);
|
||||
|
||||
sgsn_ra_free(ra);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
/* Create RA, use different find functiosn, free RA */
|
||||
static void test_routing_area_find(void)
|
||||
{
|
||||
struct sgsn_ra *ra_a, *ra_b;
|
||||
struct sgsn_ra_cell *cell_a, *cell_b;
|
||||
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, cell_id_not_found = 44;
|
||||
struct osmo_cell_global_id_ps cgi_ps = {
|
||||
.rai = ra_id,
|
||||
.cell_identity = cell_id,
|
||||
};
|
||||
struct osmo_cell_global_id cgi = {
|
||||
.lai = ra_id.lac,
|
||||
.cell_identity = cell_id
|
||||
};
|
||||
|
||||
uint16_t nsei = 2, bvci = 3;
|
||||
|
||||
printf("Testing Routing Area find\n");
|
||||
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
ra_a = sgsn_ra_alloc(&ra_id);
|
||||
OSMO_ASSERT(ra_a);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
ra_b = sgsn_ra_get_ra(&ra_id);
|
||||
OSMO_ASSERT(ra_a == ra_b);
|
||||
|
||||
cell_a = sgsn_ra_cell_alloc_geran(ra_a, cell_id, nsei, bvci);
|
||||
OSMO_ASSERT(cell_a);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_cgi_ps(&cgi_ps);
|
||||
OSMO_ASSERT(cell_b);
|
||||
OSMO_ASSERT(cell_b == cell_a);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_ra(ra_a, cgi.cell_identity);
|
||||
OSMO_ASSERT(cell_b);
|
||||
OSMO_ASSERT(cell_b == cell_a);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_cgi(&cgi);
|
||||
OSMO_ASSERT(cell_b);
|
||||
OSMO_ASSERT(cell_b == cell_a);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_lai(&cgi.lai, cgi.cell_identity);
|
||||
OSMO_ASSERT(cell_b);
|
||||
OSMO_ASSERT(cell_b == cell_a);
|
||||
|
||||
sgsn_ra_free(ra_a);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
/* try to search for a cell id which isn't present */
|
||||
cgi.cell_identity = cell_id_not_found;
|
||||
cgi_ps.cell_identity = cell_id_not_found;
|
||||
|
||||
ra_a = sgsn_ra_alloc(&ra_id);
|
||||
OSMO_ASSERT(ra_a);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
cell_a = sgsn_ra_cell_alloc_geran(ra_a, cell_id, nsei, bvci);
|
||||
OSMO_ASSERT(cell_a);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_cgi_ps(&cgi_ps);
|
||||
OSMO_ASSERT(!cell_b);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_ra(ra_a, cgi_ps.cell_identity);
|
||||
OSMO_ASSERT(!cell_b);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_cgi(&cgi);
|
||||
OSMO_ASSERT(!cell_b);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_lai(&cgi.lai, cgi.cell_identity);
|
||||
OSMO_ASSERT(!cell_b);
|
||||
|
||||
/* try to find for a different RAC */
|
||||
cgi_ps.rai.rac = 45;
|
||||
ra_id.rac = 46;
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_cgi_ps(&cgi_ps);
|
||||
OSMO_ASSERT(!cell_b);
|
||||
|
||||
ra_b = sgsn_ra_get_ra(&ra_id);
|
||||
OSMO_ASSERT(!ra_b);
|
||||
|
||||
/* try to find for different LAC */
|
||||
cgi.lai.lac = 46;
|
||||
cell_b = sgsn_ra_get_cell_by_cgi(&cgi);
|
||||
OSMO_ASSERT(!cell_b);
|
||||
|
||||
sgsn_ra_free(ra_a);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
static void test_routing_area_reset_ind(void)
|
||||
{
|
||||
struct sgsn_ra *ra_a;
|
||||
struct sgsn_ra_cell *cell_a, *cell_b;
|
||||
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,
|
||||
};
|
||||
struct osmo_cell_global_id cgi = {
|
||||
.lai = ra_id.lac,
|
||||
.cell_identity = cell_id
|
||||
};
|
||||
|
||||
uint16_t nsei = 2, bvci = 3;
|
||||
int rc;
|
||||
|
||||
printf("Testing Routing Area BSSGP BVC RESET IND\n");
|
||||
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
ra_a = sgsn_ra_alloc(&ra_id);
|
||||
OSMO_ASSERT(ra_a);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
OSMO_ASSERT(llist_count(&ra_a->cells) == 0);
|
||||
|
||||
rc = sgsn_ra_bvc_reset_ind(nsei, bvci, &cgi_ps);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
OSMO_ASSERT(llist_count(&ra_a->cells) == 1);
|
||||
|
||||
cell_a = sgsn_ra_get_cell_by_cgi(&cgi);
|
||||
OSMO_ASSERT(cell_a);
|
||||
|
||||
rc = sgsn_ra_bvc_reset_ind(nsei, bvci, &cgi_ps);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
cell_b = sgsn_ra_get_cell_by_cgi(&cgi);
|
||||
OSMO_ASSERT(cell_b);
|
||||
OSMO_ASSERT(cell_a == cell_b);
|
||||
|
||||
sgsn_ra_free(ra_a);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
rc = sgsn_ra_bvc_reset_ind(nsei, bvci, &cgi_ps);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
|
||||
|
||||
ra_a = sgsn_ra_get_ra(&cgi_ps.rai);
|
||||
sgsn_ra_free(ra_a);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void test_routing_area_nsei_free(void)
|
||||
{
|
||||
struct sgsn_ra *ra_a;
|
||||
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 nsei failure\n");
|
||||
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
rc = sgsn_ra_bvc_reset_ind(nsei, bvci, &cgi_ps);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
ra_a = sgsn_ra_get_ra(&cgi_ps.rai);
|
||||
OSMO_ASSERT(llist_count(&ra_a->cells) == 1);
|
||||
|
||||
rc = sgsn_ra_nsei_failure_ind(nsei);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
rc = sgsn_ra_nsei_failure_ind(nsei);
|
||||
OSMO_ASSERT(rc == -ENOENT);
|
||||
OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
static struct log_info_cat gprs_categories[] = {
|
||||
[DMM] = {
|
||||
.name = "DMM",
|
||||
.description = "Layer3 Mobility Management (MM)",
|
||||
.color = "\033[1;33m",
|
||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||
},
|
||||
[DPAG] = {
|
||||
.name = "DPAG",
|
||||
.description = "Paging Subsystem",
|
||||
.color = "\033[1;38m",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DREF] = {
|
||||
.name = "DREF",
|
||||
.description = "Reference Counting",
|
||||
.enabled = 0, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DGPRS] = {
|
||||
.name = "DGPRS",
|
||||
.description = "GPRS Packet Service",
|
||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||
},
|
||||
[DLLC] = {
|
||||
.name = "DLLC",
|
||||
.description = "GPRS Logical Link Control Protocol (LLC)",
|
||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||
},
|
||||
[DRA] = {
|
||||
.name = "DRA",
|
||||
.description = "Routing Area",
|
||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||
},
|
||||
};
|
||||
|
||||
static struct log_info info = {
|
||||
.cat = gprs_categories,
|
||||
.num_cat = ARRAY_SIZE(gprs_categories),
|
||||
};
|
||||
|
||||
static struct vty_app_info vty_info = {
|
||||
.name = "testSGSN",
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *osmo_sgsn_ctx;
|
||||
void *msgb_ctx;
|
||||
|
||||
osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
|
||||
osmo_init_logging2(osmo_sgsn_ctx, &info);
|
||||
tall_sgsn_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "sgsn");
|
||||
msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
|
||||
|
||||
vty_init(&vty_info);
|
||||
|
||||
test_routing_area_create();
|
||||
test_routing_area_find();
|
||||
test_routing_area_free_empty();
|
||||
test_routing_area_reset_ind();
|
||||
test_routing_area_nsei_free();
|
||||
printf("Done\n");
|
||||
|
||||
talloc_report_full(osmo_sgsn_ctx, stderr);
|
||||
OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
|
||||
OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* stubs */
|
||||
struct osmo_prim_hdr;
|
||||
int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
|
||||
{
|
||||
abort();
|
||||
}
|
6
tests/gprs_routing_area/gprs_routing_area_test.ok
Normal file
6
tests/gprs_routing_area/gprs_routing_area_test.ok
Normal file
@@ -0,0 +1,6 @@
|
||||
Testing Routing Area create/free
|
||||
Testing Routing Area find
|
||||
Testing Routing Area create/free
|
||||
Testing Routing Area BSSGP BVC RESET IND
|
||||
Testing Routing Area nsei failure
|
||||
Done
|
@@ -60,6 +60,7 @@ sgsn_test_LDADD = \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm_fsm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_mm_state_gb_fsm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_routing_area.o \
|
||||
$(top_builddir)/src/sgsn/gtp_ggsn.o \
|
||||
$(top_builddir)/src/sgsn/gtp_mme.o \
|
||||
$(top_builddir)/src/sgsn/mmctx.o \
|
||||
|
@@ -14,6 +14,13 @@ cat $abs_srcdir/sgsn/sgsn_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/sgsn/sgsn_test], [], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([gprs_routing_area])
|
||||
AT_KEYWORDS([gprs_routing_area])
|
||||
AT_CHECK([test "$enable_gprs_routing_area_test" != no || exit 77])
|
||||
cat $abs_srcdir/gprs_routing_area/gprs_routing_area_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/gprs_routing_area/gprs_routing_area_test], [], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([gtphub])
|
||||
AT_KEYWORDS([gtphub])
|
||||
AT_CHECK([test "$enable_gtphub_test" != no || exit 77])
|
||||
|
Reference in New Issue
Block a user