lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-sgsn/+/40813?usp=email )
Change subject: WIP iuh ......................................................................
WIP iuh
Change-Id: I1b1aedd2a7c358bd388aa3d8a9f3c6a0011b4889 --- M include/osmocom/sgsn/gprs_routing_area.h M src/sgsn/gprs_ranap.c M src/sgsn/gprs_routing_area.c 3 files changed, 93 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/13/40813/1
diff --git a/include/osmocom/sgsn/gprs_routing_area.h b/include/osmocom/sgsn/gprs_routing_area.h index 1e60ccc..c32e332 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; @@ -100,14 +105,18 @@ /* 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);
+/* UTRAN */ +int sgsn_ra_utran_register(const struct osmo_routing_area_id *rai, const struct osmo_rnc_id *rnc_id); + 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 *rai); struct sgsn_ra *sgsn_ra_get_ra_geran(const struct osmo_routing_area_id *rai); - +struct sgsn_ra *sgsn_ra_get_ra_utran(const struct osmo_routing_area_id *rai);
/* * return value for callbacks. @@ -125,3 +134,4 @@
/* 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); +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 3252ee6..2ff7397 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,24 @@
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 40bee05..9a84c02 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> @@ -150,6 +151,19 @@ return NULL; }
+struct sgsn_ra *sgsn_ra_get_ra_utran(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; +} + struct sgsn_ra_cell *sgsn_ra_get_cell_by_gb(uint16_t nsei, uint16_t bvci) { struct sgsn_ra *ra; @@ -390,6 +404,42 @@ sgsn_ra_nsei_failure_ind(nsei); }
+/* 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; + } + + if (ra->ran_type == RA_TYPE_UTRAN_Iu) { + if (osmo_rnc_id_cmp(&ra->u.utran.rnc_id, rnc_id) == 0) + return 0; + + 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; + } else { + 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; + } + + return -ENOENT; +} + int sgsn_ra_geran_page_ra(const struct osmo_routing_area_id *rai, struct sgsn_mm_ctx *mmctx) { struct sgsn_ra *ra; @@ -413,6 +463,23 @@ return ret; }
+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_get_ra_utran(ra_id); + if (!ra) + return -ENOENT; + + if (mmctx->p_tmsi != GSM_RESERVED_TMSI) + return ranap_iu_page_ps2(mmctx->imsi, &mmctx->p_tmsi, ra_id); + else if (mmctx->p_tmsi_old != GSM_RESERVED_TMSI) + return ranap_iu_page_ps2(mmctx->imsi, &mmctx->p_tmsi_old, ra_id); + else + return ranap_iu_page_ps2(mmctx->imsi, NULL, ra_id); +} + void sgsn_ra_init(struct sgsn_instance *inst) { inst->routing_area = talloc_zero(inst, struct sgsn_ra_global);