osmith has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc-nat/+/27767 )
Change subject: bssap: forward paging to relevant BSCs only ......................................................................
bssap: forward paging to relevant BSCs only
With osmo-bsc I28e0f9497043e90f999b593602b7ffd812787430, OsmoBSC can be configured to send a cell identifier list in BSSMAP reset. Use this to send pagings only to relevant BSCs instead of all BSCs.
Related: SYS#5560 Related: OS#5522 Change-Id: Iad3d1de8339206fa80f9fd10ac9213a7728a3c73 --- M include/osmocom/bsc_nat/bsc.h M src/osmo-bsc-nat/bsc.c M src/osmo-bsc-nat/bssap.c 3 files changed, 104 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc-nat refs/changes/67/27767/1
diff --git a/include/osmocom/bsc_nat/bsc.h b/include/osmocom/bsc_nat/bsc.h index 7c11a82..20af445 100644 --- a/include/osmocom/bsc_nat/bsc.h +++ b/include/osmocom/bsc_nat/bsc.h @@ -19,14 +19,19 @@
#pragma once
+#include <osmocom/gsm/gsm0808_utils.h> #include <osmocom/sigtran/sccp_sap.h>
struct bsc { struct llist_head list; struct osmo_sccp_addr addr; + struct gsm0808_cell_id_list2 cil; };
struct bsc *bsc_alloc(struct osmo_sccp_addr *addr); struct bsc *bsc_get_by_pc(uint32_t pointcode); + +bool bsc_cil_match(struct bsc *bsc, struct gsm0808_cell_id_list2 *cil); + void bsc_free(struct bsc *bsc); void bsc_free_subscr_conn_all(struct bsc *bsc); diff --git a/src/osmo-bsc-nat/bsc.c b/src/osmo-bsc-nat/bsc.c index 0461909..744ebfc 100644 --- a/src/osmo-bsc-nat/bsc.c +++ b/src/osmo-bsc-nat/bsc.c @@ -52,6 +52,60 @@ return NULL; }
+bool bsc_cil_match(struct bsc *bsc, struct gsm0808_cell_id_list2 *cil) +{ + unsigned int i, j; + const struct osmo_lac_and_ci_id *bsc_id; + + /* OsmoBSC sends cell identifier list with discriminator LAC and CI, + * see gsm_bts_cell_id() in osmo-bsc.git. */ + if (bsc->cil.id_discr != CELL_IDENT_LAC_AND_CI) { + LOGP(DMAIN, LOGL_ERROR, "%s: unexpected id_discr 0x%x, assuming match\n", talloc_get_name(bsc), + bsc->cil.id_discr); + return true; + } + + for (i = 0; i < bsc->cil.id_list_len; i++) { + bsc_id = &bsc->cil.id_list[i].lac_and_ci; + + for (j = 0; j < cil->id_list_len; j++) { + switch (cil->id_discr) { + case CELL_IDENT_NO_CELL: + case CELL_IDENT_BSS: + return true; + + case CELL_IDENT_WHOLE_GLOBAL: + if (bsc_id->lac == cil->id_list[j].global.lai.lac + && bsc_id->ci == cil->id_list[j].global.cell_identity) + return true; + + case CELL_IDENT_LAC_AND_CI: + if (bsc_id->lac == cil->id_list[j].lac_and_ci.lac + && bsc_id->ci == cil->id_list[j].lac_and_ci.ci) + return true; + + case CELL_IDENT_CI: + if (bsc_id->ci == cil->id_list[j].ci) + return true; + + case CELL_IDENT_LAI_AND_LAC: + if (bsc_id->lac == cil->id_list[j].lai_and_lac.lac) + return true; + + case CELL_IDENT_LAC: + if (bsc_id->lac == cil->id_list[j].lac) + return true; + default: + LOGP(DMAIN, LOGL_ERROR, "%s(0x%x) is not implemented, assuming match\n", __func__, cil->id_discr); + return true; + } + + } + } + + return false; +} + void bsc_free_subscr_conn_all(struct bsc *bsc) { struct subscr_conn *subscr_conn; diff --git a/src/osmo-bsc-nat/bssap.c b/src/osmo-bsc-nat/bssap.c index 8e73a50..893d1a6 100644 --- a/src/osmo-bsc-nat/bssap.c +++ b/src/osmo-bsc-nat/bssap.c @@ -45,6 +45,9 @@ struct bsc *bsc; int ret = 0; int rc; + struct tlv_parsed tp; + struct tlv_p_entry *e; + struct gsm0808_cell_id_list2 cil;
if (msc->addr.pc != addr->pc) { LOGP(DMAIN, LOGL_ERROR, "Unexpected Rx PAGING in CN from %s, which is not %s\n", @@ -54,10 +57,32 @@
LOGP(DMAIN, LOGL_DEBUG, "Rx PAGING from %s\n", talloc_get_name(msc));
+ tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, length - 1, 0, 0); + + if (!(e = TLVP_GET(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST))) { + LOGP(DMAIN, LOGL_ERROR, "Missing IE: cell identifier list\n"); + return -1; + } + if (gsm0808_dec_cell_id_list2(&cil, e->val, e->len) < 0) { + LOGP(DMAIN, LOGL_ERROR, "Invalid IE: cell identifier list\n"); + return -1; + } + msgb_pull_to_l2(msg);
- /* Page all BSCs */ + /* Page all relevant BSCs */ llist_for_each_entry(bsc, &g_bsc_nat->ran.bscs, list) { + if (bsc->cil.id_list_len) { + if (!bsc_cil_match(bsc, &cil)) { + LOGP(DMAIN, LOGL_DEBUG, "%s: cell identifier list doesn't match\n", + talloc_get_name(bsc)); + continue; + } + } else { + LOGP(DMAIN, LOGL_DEBUG, "%s: no cell identifier list, can't check if paging is relevant\n", + talloc_get_name(bsc)); + } + LOGP(DMAIN, LOGL_DEBUG, "Fwd to %s\n", talloc_get_name(bsc)); rc = osmo_sccp_tx_unitdata(sccp_inst->scu, &sccp_inst->addr, @@ -112,13 +137,31 @@ { struct bsc_nat_sccp_inst *sccp_inst = g_bsc_nat->ran.sccp_inst; struct bsc *bsc; + struct tlv_parsed tp; + struct tlv_p_entry *e; + struct gsm0808_cell_id_list2 cil; + + tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, length - 1, 0, 0); + + /* Osmocom extension: BSSMAP RESET may contain a cell identifier list, + * which OsmoBSCNAT uses in paging code (OS#5522) */ + if ((e = TLVP_GET(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST))) { + if (gsm0808_dec_cell_id_list2(&cil, e->val, e->len) < 0) { + LOGP(DMAIN, LOGL_ERROR, "Invalid IE: cell identifier list\n"); + return -1; + } + }
/* Store the BSC, since RESET was done the BSCNAT should accept its messages */ bsc = bsc_get_by_pc(addr->pc); if (!bsc) bsc = bsc_alloc(addr);
- LOGP(DMAIN, LOGL_NOTICE, "Rx RESET from %s\n", bsc_nat_print_addr_ran(addr)); + if (e) + bsc->cil = cil; + + LOGP(DMAIN, LOGL_NOTICE, "Rx RESET from %s (%s cell identifier list)\n", bsc_nat_print_addr_ran(addr), + e ? "with" : "without");
LOGP(DMAIN, LOGL_NOTICE, "Tx RESET ACK to %s\n", bsc_nat_print_addr_ran(addr)); msg = gsm0808_create_reset_ack();