From 73e028416e82f5f6b21d7f323fd907110ae02d74 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 11 Apr 2018 01:28:21 +0200 Subject: prevent ARFCN+BSIC collisions in config If multiple BTS are configured with identical ARFCN+BSIC, handover cannot possibly work. Add warn_on_arfcn_bsic_collisions() and when collisions are detected: - exit right away on program startup. - warn on vty bts node-exit (go_parent_cb()), i.e. when ARFCN+BSIC collide implicitly from default values. - warn on vty bts/base_station_id_code cmd coming from telnet vty, i.e. when the user actively configures colliding BSIC. - warn on vty trx/arfcn cmd coming from telnet vty, i.e. when the user actively configures colliding ARFCN. When warning, warn on all of: - DHO log, - stderr, - vty_out() in case a vty instance is passed (i.e. from interactive vty). It's better to log this once too often than let the user miss it. Rationale: when I started to implement ttcn3 tests for inter-bsc HO, I saw that the new code based on ARFCN+BSIC would cause a handover request intended to go from BTS 0 to BTS 1 to instead go from BTS 0 to back to BTS 0 -- because of identical ARFCN+BSIC in the config of ttcn3-bsc-tests. Such a config badly confuses handover: measurement reports interpreted to come from the wrong cell, all handovers attempted to go to the first BTS (sometimes correctly, sometimes wrongly), in short, non-obvious failure across the handover board. The network would appear to work well, but occasionally a handover would kill a call without apparent reason. It seems worthwhile to prevent such misconfiguration as early as possible, and even allow previous ARFCN+BSIC misconfiguration that used to work to instead break now (only upon reading config during program startup, to not cause program exit just because a user introduces a temporary collision in an interactive vty session). Change-Id: Ia7c38188ccbad5d8b7398e3e5220015e62c08c8b --- include/osmocom/bsc/vty.h | 2 ++ src/osmo-bsc/bsc_vty.c | 30 ++++++++++++++++++++++++++++++ src/osmo-bsc/osmo_bsc_main.c | 4 ++++ 3 files changed, 36 insertions(+) diff --git a/include/osmocom/bsc/vty.h b/include/osmocom/bsc/vty.h index e63275546..bfea69d2a 100644 --- a/include/osmocom/bsc/vty.h +++ b/include/osmocom/bsc/vty.h @@ -35,4 +35,6 @@ int bsc_vty_init_extra(void); struct gsm_network *gsmnet_from_vty(struct vty *vty); +int warn_on_arfcn_bsic_collisions(struct gsm_network *net, struct vty *vty); + #endif diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c index 27e1bc697..5298644e6 100644 --- a/src/osmo-bsc/bsc_vty.c +++ b/src/osmo-bsc/bsc_vty.c @@ -2119,6 +2119,30 @@ DEFUN_HIDDEN(cfg_bts_tsc, return CMD_SUCCESS; } +int warn_on_arfcn_bsic_collisions(struct gsm_network *net, struct vty *vty) +{ + struct gsm_bts *bts, *bts2; + int errors = 0; + + llist_for_each_entry(bts, &net->bts_list, list) { + struct neighbor_ident_key *nik = bts_ident_key(bts); + + bts2 = bts_by_neighbor_ident(net, nik); + if (bts != bts2) { + LOGP(DHO, LOGL_ERROR, "CONFIG ERROR: Multiple BTS match %s: %d and %d\n", + neighbor_ident_key_name(nik), bts->nr, bts2->nr); + fprintf(stderr, "CONFIG ERROR: Multiple BTS match %s: %d and %d\n", + neighbor_ident_key_name(nik), bts->nr, bts2->nr); + if (vty) + vty_out(vty, "%% CONFIG ERROR: Multiple BTS match %s: %d and %d%s", + neighbor_ident_key_name(nik), bts->nr, bts2->nr, + VTY_NEWLINE); + errors ++; + } + } + return errors; +} + DEFUN(cfg_bts_bsic, cfg_bts_bsic_cmd, "base_station_id_code <0-63>", @@ -2135,6 +2159,9 @@ DEFUN(cfg_bts_bsic, } bts->bsic = bsic; + if (vty->type != VTY_FILE) + warn_on_arfcn_bsic_collisions(bts->network, vty); + return CMD_SUCCESS; } @@ -3884,6 +3911,9 @@ DEFUN(cfg_trx_arfcn, /* FIXME: use OML layer to update the ARFCN */ /* FIXME: use RSL layer to update SYSTEM INFORMATION */ + if (vty->type != VTY_FILE) + warn_on_arfcn_bsic_collisions(trx->bts->network, vty); + return CMD_SUCCESS; } diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c index 69db32e55..c46d2fa9e 100644 --- a/src/osmo-bsc/osmo_bsc_main.c +++ b/src/osmo-bsc/osmo_bsc_main.c @@ -539,6 +539,8 @@ static int bsc_vty_go_parent(struct vty *vty) vty->index = bts->network; vty->index_sub = NULL; } + if (vty->type != VTY_FILE) + warn_on_arfcn_bsic_collisions(bsc_gsmnet, vty); break; case TRX_NODE: vty->node = BTS_NODE; @@ -826,6 +828,8 @@ int main(int argc, char **argv) fprintf(stderr, "Bootstrapping the network failed. exiting.\n"); exit(1); } + if (warn_on_arfcn_bsic_collisions(bsc_gsmnet, NULL)) + exit(1); /* start control interface after reading config for * ctrl_vty_get_bind_addr() */ -- cgit v1.2.3