lynxis lazus has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-iuh/+/38945?usp=email )
Change subject: iu_client: refactor LAC/RAC handling ......................................................................
iu_client: refactor LAC/RAC handling
The iu client ignored the PLMN which might ran into duplicate RACs. Replace all lac/rac handling by the "new" osmo_routing_area_id struct which has improved handling. Further it allows to use the embedded lac when CS paging is only required. The old gprs_ra_id is still used to contain api stability.
Change-Id: Ie38fa3751cfce1c981d8d0bed1b8ff891593a638 --- M src/iu_client.c 1 file changed, 85 insertions(+), 21 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-iuh refs/changes/45/38945/1
diff --git a/src/iu_client.c b/src/iu_client.c index 3fc29bd..018813d 100644 --- a/src/iu_client.c +++ b/src/iu_client.c @@ -49,10 +49,7 @@ struct iu_lac_rac_entry { struct llist_head entry;
- /* LAC: Location Area Code (for CS and PS) */ - uint16_t lac; - /* RAC: Routing Area Code (for PS only) */ - uint8_t rac; + struct osmo_routing_area_id rai; };
/* Entry to cache conn_id <-> sccp_addr mapping in case we receive an empty CR */ @@ -229,7 +226,7 @@ * If rnc and lre pointers are not NULL, *rnc / *lre are set to NULL if no match is found, or to the * match if a match is found. Return true if a match is found. */ static bool iu_rnc_lac_rac_find(struct ranap_iu_rnc **rnc, struct iu_lac_rac_entry **lre, - uint16_t lac, uint8_t rac) + const struct osmo_routing_area_id *ra_id) { struct ranap_iu_rnc *r; struct iu_lac_rac_entry *e; @@ -241,7 +238,33 @@
llist_for_each_entry(r, &rnc_list, entry) { llist_for_each_entry(e, &r->lac_rac_list, entry) { - if (e->lac == lac && e->rac == rac) { + if (!osmo_rai_cmp(&e->rai, ra_id)) { + if (rnc) + *rnc = r; + if (lre) + *lre = e; + return true; + } + } + } + return false; +} + +/* legacy, do a first match with ignoring PLMN */ +static bool iu_rnc_lac_rac_find_legacy(struct ranap_iu_rnc **rnc, struct iu_lac_rac_entry **lre, + uint16_t lac, uint8_t rac) +{ + struct ranap_iu_rnc *r; + struct iu_lac_rac_entry *e; + + if (rnc) + *rnc = NULL; + if (lre) + *lre = NULL; + + llist_for_each_entry(r, &rnc_list, entry) { + llist_for_each_entry(e, &r->lac_rac_list, entry) { + if (e->rai.lac.lac == lac && e->rai.rac == rac) { if (rnc) *rnc = r; if (lre) @@ -270,8 +293,9 @@ return !strcmp(buf, osmo_sccp_addr_dump(b)); }
-static struct ranap_iu_rnc *iu_rnc_register(struct osmo_rnc_id *rnc_id, uint16_t lac, - uint8_t rac, struct osmo_sccp_addr *addr) +static struct ranap_iu_rnc *iu_rnc_register(struct osmo_rnc_id *rnc_id, + const struct osmo_routing_area_id *rai, + struct osmo_sccp_addr *addr) { struct ranap_iu_rnc *rnc; struct ranap_iu_rnc *old_rnc; @@ -282,31 +306,31 @@
if (rnc) { if (!same_sccp_addr(&rnc->sccp_addr, addr)) { - LOGPIU(LOGL_NOTICE, "RNC %s changed its SCCP addr to %s (LAC=%u RAC=%u)\n", - osmo_rnc_id_name(rnc_id), osmo_sccp_addr_dump(addr), lac, rac); + LOGPIU(LOGL_NOTICE, "RNC %s changed its SCCP addr to %s (LAC/RAC %s)\n", + osmo_rnc_id_name(rnc_id), osmo_sccp_addr_dump(addr), osmo_rai_name2(rai)); rnc->sccp_addr = *addr; } } else rnc = iu_rnc_alloc(rnc_id, addr);
/* Detect whether the LAC,RAC is already recorded in another RNC */ - iu_rnc_lac_rac_find(&old_rnc, &lre, lac, rac); + iu_rnc_lac_rac_find(&old_rnc, &lre, rai);
if (old_rnc && old_rnc != rnc) { - /* LAC,RAC already exists in a different RNC */ - LOGPIU(LOGL_NOTICE, "LAC %u RAC %u moved from RNC %s %s", - lac, rac, osmo_rnc_id_name(&old_rnc->rnc_id), osmo_sccp_addr_dump(&old_rnc->sccp_addr)); + /* LAC, RAC already exists in a different RNC */ + LOGPIU(LOGL_NOTICE, "LAC/RAC %s moved from RNC %s %s", + osmo_rai_name2(rai), + osmo_rnc_id_name(&old_rnc->rnc_id), osmo_sccp_addr_dump(&old_rnc->sccp_addr)); LOGPIUC(LOGL_NOTICE, " to RNC %s %s\n", osmo_rnc_id_name(&rnc->rnc_id), osmo_sccp_addr_dump(&rnc->sccp_addr));
llist_del(&lre->entry); llist_add(&lre->entry, &rnc->lac_rac_list); } else if (!old_rnc) { - /* LAC,RAC not recorded yet */ - LOGPIU(LOGL_NOTICE, "RNC %s: new LAC %u RAC %u\n", osmo_rnc_id_name(rnc_id), lac, rac); + /* LAC, RAC not recorded yet */ + LOGPIU(LOGL_NOTICE, "RNC %s: new LAC/RAC %s\n", osmo_rnc_id_name(rnc_id), osmo_rai_name2(rai)); lre = talloc_zero(rnc, struct iu_lac_rac_entry); - lre->lac = lac; - lre->rac = rac; + lre->rai = *rai; llist_add(&lre->entry, &rnc->lac_rac_list); } /* else, LAC,RAC already recorded with the current RNC. */ @@ -410,7 +434,8 @@ static int ranap_handle_co_initial_ue(void *ctx, RANAP_InitialUE_MessageIEs_t *ies) { struct new_ue_conn_ctx *new_ctx = ctx; - struct gprs_ra_id ra_id; + struct gprs_ra_id ra_id = {}; + struct osmo_routing_area_id ra_id2 = {}; struct osmo_rnc_id rnc_id = {}; uint16_t sai; struct ranap_ue_conn_ctx *ue; @@ -436,8 +461,10 @@ msgb_gmmh(msg) = msgb_put(msg, ies->nas_pdu.size); memcpy(msgb_gmmh(msg), ies->nas_pdu.buf, ies->nas_pdu.size);
+ gprs_rai_to_osmo(&ra_id2, &ra_id); + /* Make sure we know the RNC Id and LAC+RAC coming in on this connection. */ - rnc = iu_rnc_register(&rnc_id, ra_id.lac, ra_id.rac, &new_ctx->sccp_addr); + rnc = iu_rnc_register(&rnc_id, &ra_id2, &new_ctx->sccp_addr);
ue = ue_conn_ctx_alloc(rnc, new_ctx->conn_id); OSMO_ASSERT(ue); @@ -789,7 +816,7 @@ int log_level; int paged = 0;
- iu_rnc_lac_rac_find(&rnc, NULL, lac, rac); + iu_rnc_lac_rac_find_legacy(&rnc, NULL, lac, rac); if (rnc) { if (iu_tx_paging_cmd(&rnc->sccp_addr, imsi, tmsi_or_ptmsi, is_ps, 0) == 0) { log_msg = "Paging"; @@ -818,6 +845,43 @@ return paged; }
+static int iu_page2(const char *imsi, const uint32_t *tmsi_or_ptmsi, + const struct osmo_routing_area_id *ra_id, bool is_ps) +{ + struct ranap_iu_rnc *rnc; + const char *log_msg; + int log_level; + int paged = 0; + + iu_rnc_lac_rac_find(&rnc, NULL, ra_id); + if (rnc) { + if (iu_tx_paging_cmd(&rnc->sccp_addr, imsi, tmsi_or_ptmsi, is_ps, 0) == 0) { + log_msg = "Paging"; + log_level = LOGL_DEBUG; + paged = 1; + } else { + log_msg = "Paging failed"; + log_level = LOGL_ERROR; + } + } else { + log_msg = "Found no RNC to Page"; + log_level = LOGL_ERROR; + } + + if (is_ps) + LOGPIU(log_level, "IuPS: %s on RAC %s", log_msg, osmo_rai_name2(ra_id)); + else + LOGPIU(log_level, "IuCS: %s on LAC %s", log_msg, osmo_lai_name(&ra_id->lac)); + if (rnc) + LOGPIUC(log_level, " at SCCP-addr %s", osmo_sccp_addr_dump(&rnc->sccp_addr)); + if (tmsi_or_ptmsi) + LOGPIUC(log_level, ", for %s %08x\n", is_ps? "PTMSI" : "TMSI", *tmsi_or_ptmsi); + else + LOGPIUC(log_level, ", for IMSI %s\n", imsi); + + return paged; +} + int ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac) { return iu_page(imsi, tmsi, lac, 0, false);