lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-sgsn/+/40688?usp=email )
Change subject: routing area: introduce ran_type on the RA ......................................................................
routing area: introduce ran_type on the RA
A Routing Area should be unique identified by the RAI. Following this, it is forbidden to have a RAI which is valid in both, GERAN and UTRAN.
Change-Id: I59c35f1a4912ff11574bb31e4fe424816993548c --- M include/osmocom/sgsn/gprs_routing_area.h M src/sgsn/gprs_routing_area.c M tests/gprs_routing_area/gprs_routing_area_test.c 3 files changed, 73 insertions(+), 20 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/88/40688/1
diff --git a/include/osmocom/sgsn/gprs_routing_area.h b/include/osmocom/sgsn/gprs_routing_area.h index caaed47..6629169 100644 --- a/include/osmocom/sgsn/gprs_routing_area.h +++ b/include/osmocom/sgsn/gprs_routing_area.h @@ -6,6 +6,7 @@ #include <stdint.h>
#include <osmocom/core/linuxlist.h> +#include <osmocom/core/utils.h> #include <osmocom/gsm/gsm23003.h>
struct sgsn_instance; @@ -16,18 +17,35 @@ struct llist_head ra_list; };
+enum sgsn_ra_ran_type { + RA_TYPE_GERAN_Gb, + RA_TYPE_UTRAN_Iu, +}; + +extern const struct value_string sgsn_ra_ran_type_names[]; + 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, + /* For GERAN: every PCU is connected to the SGSN. It allows the SGSN to know every single cell + * and for routing, the SGSN must know to which PCU a given cell is connected. + * It is possible that 2x PCU serves the same Routing Area + * + * For UTRAN: only the RNC (HNB via HNBGW) is communicating with the SGSN. + * The SGSN doesn't know every cell, because they aren't accepted individual by the SGSN. + * The SGSN only "knows" RAI/SAI if they has been used. In the future it would be a good idea to + * allow configuring RA in the vty/config as well. + * Similar to the GERAN Cell, but iu_client doesn't notify us for every given SAI, only for RAC. + * Further the SGSN doesn't get informed about Service Area and can't relate the SAI to a given UE. + * For UTRAN only do a LAC/RAC <> RNC relation and don't have a specific cell relation. + */ + enum sgsn_ra_ran_type ran_type; + + /* GERAN/UTRAN: cells contains a list of sgsn_ra_cells which are alive */ + struct llist_head cells; };
struct sgsn_ra_cell { @@ -55,7 +73,7 @@
void sgsn_ra_init(struct sgsn_instance *inst);
-struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai); +struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai, enum sgsn_ra_ran_type ran_type); 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); @@ -72,6 +90,7 @@ 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); +struct sgsn_ra *sgsn_ra_get_ra_geran(const struct osmo_routing_area_id *ra_id);
/* diff --git a/src/sgsn/gprs_routing_area.c b/src/sgsn/gprs_routing_area.c index 67b15ae..23847f2 100644 --- a/src/sgsn/gprs_routing_area.c +++ b/src/sgsn/gprs_routing_area.c @@ -23,6 +23,7 @@ #include <osmocom/core/linuxlist.h> #include <osmocom/core/logging.h> #include <osmocom/core/rate_ctr.h> +#include <osmocom/core/utils.h> #include <osmocom/gsm/gsm48.h> #include <osmocom/sgsn/debug.h> #include <osmocom/sgsn/gprs_bssgp.h> @@ -31,6 +32,11 @@
#include <osmocom/sgsn/gprs_routing_area.h>
+const struct value_string sgsn_ra_ran_type_names[] = { + { RA_TYPE_GERAN_Gb, "GERAN_Gb"}, + { RA_TYPE_UTRAN_Iu, "UTRAN_Iu"}, +}; + static void _sgsn_ra_cell_free(struct sgsn_ra_cell *cell, bool drop_empty_ra) { struct sgsn_ra *ra; @@ -72,7 +78,7 @@ talloc_free(ra); }
-struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai) +struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai, enum sgsn_ra_ran_type ran_type) { struct sgsn_ra *ra; ra = talloc_zero(sgsn->routing_area, struct sgsn_ra); @@ -81,6 +87,7 @@
INIT_LLIST_HEAD(&ra->cells); ra->rai = *rai; + ra->ran_type = ran_type; llist_add(&ra->list, &sgsn->routing_area->ra_list); return ra; } @@ -115,6 +122,19 @@ return NULL; }
+struct sgsn_ra *sgsn_ra_get_ra_geran(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_GERAN_Gb) + return ra; + + return NULL; +} + struct sgsn_ra_cell *sgsn_ra_get_cell_by_gb(uint16_t nsei, uint16_t bvci) { struct sgsn_ra *ra; @@ -125,6 +145,9 @@ return NULL;
llist_for_each_entry(ra, &sgsn->routing_area->ra_list, list) { + if (ra->ran_type != RA_TYPE_GERAN_Gb) + continue; + llist_for_each_entry(cell, &ra->cells, list) { if (cell->ran_type != RA_TYPE_GERAN_Gb) continue; @@ -174,10 +197,14 @@ return sgsn_ra_foreach_cell(ra, cb, cb_data); }
+/* valid for GERAN */ struct sgsn_ra_cell *sgsn_ra_get_cell_by_ra(const struct sgsn_ra *ra, uint16_t cell_id) { struct sgsn_ra_cell *cell;
+ if (ra->ran_type != RA_TYPE_GERAN_Gb) + return NULL; + llist_for_each_entry(cell, &ra->cells, list) { if (cell->cell_id == cell_id) return cell; @@ -186,6 +213,7 @@ return NULL; }
+/* valid for GERAN */ 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; @@ -194,6 +222,9 @@ /* 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 (ra->ran_type != RA_TYPE_GERAN_Gb) + continue; + if (osmo_lai_cmp(&ra->rai.lac, lai) != 0) continue;
@@ -206,7 +237,7 @@ return NULL; }
-/*! Return the cell by searching for the RA, when found, search the cell within the RA +/*! Return the GERAN 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 @@ -217,7 +248,7 @@
OSMO_ASSERT(cgi_ps);
- ra = sgsn_ra_get_ra(&cgi_ps->rai); + ra = sgsn_ra_get_ra_geran(&cgi_ps->rai); if (!ra) return NULL;
@@ -246,9 +277,10 @@ 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); + ra = sgsn_ra_get_ra_geran(&cgi_ps->rai); if (!ra) { - ra = sgsn_ra_alloc(&cgi_ps->rai); + /* TODO: check for UTRAN rai when introducing UTRAN support */ + ra = sgsn_ra_alloc(&cgi_ps->rai, RA_TYPE_GERAN_Gb); if (!ra) return -ENOMEM; ra_created = true; @@ -312,6 +344,9 @@ bool found = false;
llist_for_each_entry_safe(ra, ra2, &sgsn->routing_area->ra_list, list) { + if (ra->ran_type != RA_TYPE_GERAN_Gb) + continue; + llist_for_each_entry_safe(cell, cell2, &ra->cells, list) { if (cell->ran_type != RA_TYPE_GERAN_Gb) continue; @@ -324,7 +359,6 @@
if (llist_empty(&ra->cells)) sgsn_ra_free(ra); - }
return found ? 0 : -ENOENT; @@ -338,7 +372,7 @@
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
- ra = sgsn_ra_get_ra(ra_id); + ra = sgsn_ra_get_ra_geran(ra_id); if (!ra) return -ENOENT;
diff --git a/tests/gprs_routing_area/gprs_routing_area_test.c b/tests/gprs_routing_area/gprs_routing_area_test.c index e1aec0f..6021d81 100644 --- a/tests/gprs_routing_area/gprs_routing_area_test.c +++ b/tests/gprs_routing_area/gprs_routing_area_test.c @@ -75,7 +75,7 @@ printf("Testing Routing Area create/free\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx); - ra = sgsn_ra_alloc(&raid); + ra = sgsn_ra_alloc(&raid, RA_TYPE_GERAN_Gb); OSMO_ASSERT(ra); OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
@@ -105,7 +105,7 @@ printf("Testing Routing Area create/free\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx); - ra = sgsn_ra_alloc(&raid); + ra = sgsn_ra_alloc(&raid, RA_TYPE_GERAN_Gb); OSMO_ASSERT(ra); OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
@@ -117,7 +117,7 @@ sgsn_ra_free(ra); OSMO_ASSERT(llist_empty(&sgsn->routing_area->ra_list));
- ra = sgsn_ra_alloc(&raid); + ra = sgsn_ra_alloc(&raid, RA_TYPE_GERAN_Gb); OSMO_ASSERT(ra); OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
@@ -160,7 +160,7 @@ printf("Testing Routing Area find\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx); - ra_a = sgsn_ra_alloc(&ra_id); + ra_a = sgsn_ra_alloc(&ra_id, RA_TYPE_GERAN_Gb); OSMO_ASSERT(ra_a); OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
@@ -194,7 +194,7 @@ cgi.cell_identity = cell_id_not_found; cgi_ps.cell_identity = cell_id_not_found;
- ra_a = sgsn_ra_alloc(&ra_id); + ra_a = sgsn_ra_alloc(&ra_id, RA_TYPE_GERAN_Gb); OSMO_ASSERT(ra_a); OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1);
@@ -263,7 +263,7 @@ printf("Testing Routing Area BSSGP BVC RESET IND\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx); - ra_a = sgsn_ra_alloc(&ra_id); + ra_a = sgsn_ra_alloc(&ra_id, RA_TYPE_GERAN_Gb); OSMO_ASSERT(ra_a); OSMO_ASSERT(llist_count(&sgsn->routing_area->ra_list) == 1); OSMO_ASSERT(llist_count(&ra_a->cells) == 0);