From 764449ec2ea6d6b45239278eae90613df8c93f59 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Tue, 9 Mar 2021 17:11:45 +0100 Subject: fix/refactor neighbor config The neighbor configuration storage is fundamentally broken: it requires all local cells to be configured before being able to list them as neighbors of each other. Upon config write-back, the neighbor config however is placed back inline with the other config, and hence a written-out neighbor config no longer works on program restart. The cause of this problem is that the config is stored as explicit pointers between local cells (struct gsm_bts), which of course requires the pointer to exist before being able to reference it. Instead, store the actual configuration that the user entered as-is, without pointers or references to objects that need to be ready. Resolve the neighbors every time a neighbor is needed. Hence the user may enter any config at any place in the config file, even non-working config (like a BTS number that doesn't exist), and the relation to actual local or remote neighbor cells is made at runtime. Abort program startup if the initial neighbor configuration contains errors. Related: OS#5018 Change-Id: I9ed992f8bfff888b3933733c0576f92d50f2625b --- include/osmocom/bsc/bts.h | 11 +++-- include/osmocom/bsc/gsm_data.h | 19 ++++---- include/osmocom/bsc/handover.h | 5 ++- include/osmocom/bsc/neighbor_ident.h | 86 ++++++++++++++++++++++-------------- 4 files changed, 72 insertions(+), 49 deletions(-) (limited to 'include') diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h index efa413411..f40aa3ec2 100644 --- a/include/osmocom/bsc/bts.h +++ b/include/osmocom/bsc/bts.h @@ -496,10 +496,13 @@ struct gsm_bts { struct handover_cfg *ho; - /* A list of struct gsm_bts_ref, indicating neighbors of this BTS. - * When the si_common neigh_list is in automatic mode, it is populated from this list as well as - * gsm_network->neighbor_bss_cells. */ - struct llist_head local_neighbors; + /* Local and remote neighbor configuration: a list of neighbors as written in the VTY config, not resolved to + * actual cells. Entries may point at non-existing BTS numbers, or yet unconfigured ARFCN+BSIC. The point of + * this list is to keep the config as the user entered it: a) to write it back exactly as entered, and b) to + * allow adding neighbor cells that will only be configured further down in the config file. + * An actual neighbor cell object (local or remote-BSS) is resolved "at runtime" whenever a neighbor is being + * looked up. */ + struct llist_head neighbors; /* BTS-specific overrides for timer values from struct gsm_network. */ uint8_t T3122; /* ASSIGNMENT REJECT wait indication */ diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index 1bf21aef1..2a9da26bc 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #define GSM_T3122_DEFAULT 10 @@ -174,10 +173,16 @@ extern const struct value_string handover_scope_names[]; inline static const char *handover_scope_name(enum handover_scope val) { return get_value_string(handover_scope_names, val); } +/* Cell ARFCN + BSIC. */ +struct cell_ab { + uint16_t arfcn; + uint8_t bsic; +}; + struct handover_out_req { enum hodec_id from_hodec_id; struct gsm_lchan *old_lchan; - struct neighbor_ident_key target_nik; + struct cell_ab target_cell_ab; enum gsm_chan_t new_lchan_type; /*< leave GSM_LCHAN_NONE to use same as old_lchan */ }; @@ -205,7 +210,7 @@ struct handover { enum hodec_id from_hodec_id; enum handover_scope scope; enum gsm_chan_t new_lchan_type; - struct neighbor_ident_key target_cell; + struct cell_ab target_cell_ab; /* For inter-BSC handover, this may reflect more than one Cell ID. Must also be set for intra-BSC handover, * because it is used as key for penalty timers (e.g. in handover decision 2). */ @@ -850,12 +855,6 @@ struct load_counter { unsigned int used; }; -/* Useful to track N-N relations between BTS, for example neighbors. */ -struct gsm_bts_ref { - struct llist_head entry; - struct gsm_bts *bts; -}; - /* A single Page of a SMSCB message */ struct bts_smscb_page { /* SMSCB message we're part of */ @@ -1219,8 +1218,6 @@ struct gsm_network { struct osmo_tdef *tdefs; } mgw; - /* Remote BSS Cell Identifier Lists */ - struct neighbor_ident_list *neighbor_bss_cells; /* Remote BSS resolution sevice (CTRL iface) */ struct { char *addr; diff --git a/include/osmocom/bsc/handover.h b/include/osmocom/bsc/handover.h index a71bb98f0..f67149142 100644 --- a/include/osmocom/bsc/handover.h +++ b/include/osmocom/bsc/handover.h @@ -82,8 +82,9 @@ enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn); int find_handover_target_cell(struct gsm_bts **local_target_cell_p, - const struct gsm0808_cell_id_list2 **remote_target_cell_p, - struct gsm_subscriber_connection *conn, const struct neighbor_ident_key *search_for, + struct gsm0808_cell_id_list2 *remote_target_cells, + struct gsm_subscriber_connection *conn, + const struct cell_ab *search_for, bool log_errors); void handover_parse_inter_bsc_mt(struct gsm_subscriber_connection *conn, diff --git a/include/osmocom/bsc/neighbor_ident.h b/include/osmocom/bsc/neighbor_ident.h index cab7f9e29..0565d528c 100644 --- a/include/osmocom/bsc/neighbor_ident.h +++ b/include/osmocom/bsc/neighbor_ident.h @@ -7,62 +7,84 @@ #include #include +#include + struct vty; struct gsm_network; struct gsm_bts; -struct neighbor_ident_list; struct gsm0808_cell_id_list2; #define NEIGHBOR_IDENT_KEY_ANY_BTS -1 #define BSIC_ANY 0xff -struct neighbor_ident_key { - int from_bts; /*< BTS nr 0..255 or NEIGHBOR_IDENT_KEY_ANY_BTS */ - uint16_t arfcn; - uint8_t bsic; +enum neighbor_type { + NEIGHBOR_TYPE_UNSET = 0, + NEIGHBOR_TYPE_BTS_NR = 1, + NEIGHBOR_TYPE_CELL_ID = 2, +}; + +/* One line of VTY neighbor configuration as entered by the user. + * One of three variants: + * + * - just the local-BSS neighbor BTS nr: + * neighbor bts 123 + * + * - a neighbor cell identifier *without* ARFCN+BSIC: + * neighbor (lac|lac-ci|cgi|cgi-ps) 1 2 3... + * This is an elaborate / BTS-nr-agnostic way of indicating a local-BSS neighbor cell. + * + * - a neighbor cell identifier *with* ARFCN+BSIC: + * neighbor (lac|lac-ci|cgi|cgi-ps) 1 2 3... arfcn 456 bsic (23|any) + * This can either be + * - a remote-BSS neighbor cell, or + * - a super elaborate way of indicating a local-BSS neighbor, if this cell id exists in the local BSS. + */ +struct neighbor { + struct llist_head entry; + + enum neighbor_type type; + union { + uint8_t bts_nr; + struct { + struct gsm0808_cell_id id; + bool ab_present; + struct cell_ab ab; + } cell_id; + }; }; -const char *neighbor_ident_key_name(const struct neighbor_ident_key *ni_key); +int resolve_local_neighbor(struct gsm_bts **local_neighbor_p, const struct gsm_bts *from_bts, + const struct neighbor *neighbor); +int resolve_remote_neighbors(struct gsm_bts *from_bts, const struct cell_ab *target_ab); -struct neighbor_ident_list *neighbor_ident_init(void *talloc_ctx); -void neighbor_ident_free(struct neighbor_ident_list *nil); +int cell_ab_to_str_buf(char *buf, size_t buflen, const struct cell_ab *cell); +char *cell_ab_to_str_c(void *ctx, const struct cell_ab *cell); -bool neighbor_ident_key_match(const struct neighbor_ident_key *entry, - const struct neighbor_ident_key *search_for, - bool exact_match); +bool cell_ab_match(const struct cell_ab *entry, const struct cell_ab *search_for, bool exact_match); +bool cell_ab_valid(const struct cell_ab *cell); -int neighbor_ident_add(struct neighbor_ident_list *nil, const struct neighbor_ident_key *key, - const struct gsm0808_cell_id_list2 *val); -const struct gsm0808_cell_id_list2 *neighbor_ident_get(const struct neighbor_ident_list *nil, - const struct neighbor_ident_key *key); -bool neighbor_ident_del(struct neighbor_ident_list *nil, const struct neighbor_ident_key *key); -void neighbor_ident_clear(struct neighbor_ident_list *nil); +int neighbor_to_str_buf(char *buf, size_t buflen, const struct neighbor *n); +char *neighbor_to_str_c(void *ctx, const struct neighbor *n); +bool neighbor_same(const struct neighbor *a, const struct neighbor *b, bool check_cell_ab); -void neighbor_ident_iter(const struct neighbor_ident_list *nil, - bool (* iter_cb )(const struct neighbor_ident_key *key, - const struct gsm0808_cell_id_list2 *val, - void *cb_data), - void *cb_data); +void bts_cell_ab(struct cell_ab *arfcn_bsic, const struct gsm_bts *bts); -struct neighbor_ident_key *bts_ident_key(const struct gsm_bts *bts); +int resolve_neighbors(struct gsm_bts **local_neighbor_p, struct gsm0808_cell_id_list2 *remote_neighbors, + struct gsm_bts *from_bts, const struct cell_ab *target_ab, bool log_errors); -void neighbor_ident_vty_init(struct gsm_network *net, struct neighbor_ident_list *nil); +void neighbor_ident_vty_init(); void neighbor_ident_vty_write_bts(struct vty *vty, const char *indent, struct gsm_bts *bts); void neighbor_ident_vty_write_network(struct vty *vty, const char *indent); -bool neighbor_ident_bts_entry_exists(uint8_t from_bts); +int neighbors_check_cfg(); -#define NEIGHBOR_IDENT_VTY_KEY_PARAMS "arfcn <0-1023> bsic (<0-63>|any)" -#define NEIGHBOR_IDENT_VTY_KEY_DOC \ +#define CELL_AB_VTY_PARAMS "arfcn <0-1023> bsic (<0-63>|any)" +#define CELL_AB_VTY_DOC \ "ARFCN of neighbor cell\n" "ARFCN value\n" \ "BSIC of neighbor cell\n" "BSIC value\n" \ "for all BSICs / use any BSIC in this ARFCN\n" -bool neighbor_ident_vty_parse_key_params(struct vty *vty, const char **argv, - struct neighbor_ident_key *key); -bool neighbor_ident_bts_parse_key_params(struct vty *vty, struct gsm_bts *bts, const char **argv, - struct neighbor_ident_key *key); - +void neighbor_ident_vty_parse_arfcn_bsic(struct cell_ab *ab, const char **argv); struct ctrl_handle *neighbor_controlif_setup(struct gsm_network *net); int neighbor_ctrl_cmds_install(struct gsm_network *net); -- cgit v1.2.3