aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ipaccess/Makefile.am4
-rw-r--r--src/ipaccess/ipaccess-config.c1
-rw-r--r--src/osmo-bsc/Makefile.am1
-rw-r--r--src/osmo-bsc/abis_nm.c9
-rw-r--r--src/osmo-bsc/abis_om2000.c1
-rw-r--r--src/osmo-bsc/abis_om2000_vty.c1
-rw-r--r--src/osmo-bsc/abis_rsl.c2
-rw-r--r--src/osmo-bsc/acc_ramp.c1
-rw-r--r--src/osmo-bsc/assignment_fsm.c1
-rw-r--r--src/osmo-bsc/bsc_ctrl_commands.c1
-rw-r--r--src/osmo-bsc/bsc_init.c19
-rw-r--r--src/osmo-bsc/bsc_rf_ctrl.c1
-rw-r--r--src/osmo-bsc/bsc_vty.c1
-rw-r--r--src/osmo-bsc/bts.c748
-rw-r--r--src/osmo-bsc/bts_ericsson_rbs2000.c1
-rw-r--r--src/osmo-bsc/bts_ipaccess_nanobts.c1
-rw-r--r--src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c2
-rw-r--r--src/osmo-bsc/bts_nokia_site.c1
-rw-r--r--src/osmo-bsc/bts_siemens_bs11.c1
-rw-r--r--src/osmo-bsc/bts_sysmobts.c1
-rw-r--r--src/osmo-bsc/bts_unknown.c1
-rw-r--r--src/osmo-bsc/cbch_scheduler.c1
-rw-r--r--src/osmo-bsc/chan_alloc.c1
-rw-r--r--src/osmo-bsc/codec_pref.c1
-rw-r--r--src/osmo-bsc/e1_config.c1
-rw-r--r--src/osmo-bsc/gsm_04_08_rr.c1
-rw-r--r--src/osmo-bsc/gsm_08_08.c1
-rw-r--r--src/osmo-bsc/gsm_data.c716
-rw-r--r--src/osmo-bsc/handover_decision.c1
-rw-r--r--src/osmo-bsc/handover_decision_2.c1
-rw-r--r--src/osmo-bsc/handover_fsm.c1
-rw-r--r--src/osmo-bsc/handover_logic.c1
-rw-r--r--src/osmo-bsc/handover_vty.c1
-rw-r--r--src/osmo-bsc/lchan_fsm.c2
-rw-r--r--src/osmo-bsc/lchan_rtp_fsm.c1
-rw-r--r--src/osmo-bsc/lchan_select.c1
-rw-r--r--src/osmo-bsc/meas_feed.c1
-rw-r--r--src/osmo-bsc/neighbor_ident_vty.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_bssap.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_ctrl.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_filter.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_grace.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_main.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_msc.c1
-rw-r--r--src/osmo-bsc/osmo_bsc_sigtran.c1
-rw-r--r--src/osmo-bsc/paging.c1
-rw-r--r--src/osmo-bsc/pcu_sock.c1
-rw-r--r--src/osmo-bsc/rest_octets.c1
-rw-r--r--src/osmo-bsc/smscb.c1
-rw-r--r--src/osmo-bsc/system_information.c1
-rw-r--r--src/osmo-bsc/timeslot_fsm.c1
-rw-r--r--src/utils/Makefile.am2
-rw-r--r--src/utils/bs11_config.c1
53 files changed, 820 insertions, 728 deletions
diff --git a/src/ipaccess/Makefile.am b/src/ipaccess/Makefile.am
index 145ea3989..273530cf5 100644
--- a/src/ipaccess/Makefile.am
+++ b/src/ipaccess/Makefile.am
@@ -46,6 +46,7 @@ ipaccess_config_SOURCES = \
# FIXME: resolve the bogus dependencies patched around here:
ipaccess_config_LDADD = \
+ $(top_builddir)/src/osmo-bsc/bts.o \
$(top_builddir)/src/osmo-bsc/abis_nm.o \
$(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts.o \
$(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.o \
@@ -57,9 +58,10 @@ ipaccess_config_LDADD = \
ipaccess_proxy_SOURCES = \
ipaccess-proxy.c \
stubs.c \
- $(top_srcdir)/src/osmo-bsc/gsm_data.c \
$(NULL)
ipaccess_proxy_LDADD = \
+ $(top_builddir)/src/osmo-bsc/bts.o \
+ $(top_builddir)/src/osmo-bsc/gsm_data.o \
$(OSMO_LIBS) \
$(NULL)
diff --git a/src/ipaccess/ipaccess-config.c b/src/ipaccess/ipaccess-config.c
index f7d733231..34ad57f1c 100644
--- a/src/ipaccess/ipaccess-config.c
+++ b/src/ipaccess/ipaccess-config.c
@@ -56,6 +56,7 @@
#include <osmocom/abis/abis.h>
#include <osmocom/gsm/protocol/gsm_12_21.h>
#include <osmocom/bsc/bss.h>
+#include <osmocom/bsc/bts.h>
struct gsm_network *bsc_gsmnet;
diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am
index 0665af6f3..f66421ac3 100644
--- a/src/osmo-bsc/Makefile.am
+++ b/src/osmo-bsc/Makefile.am
@@ -43,6 +43,7 @@ osmo_bsc_SOURCES = \
bsc_subscr_conn_fsm.c \
bsc_subscriber.c \
bsc_vty.c \
+ bts.c \
bts_ericsson_rbs2000.c \
bts_init.c \
bts_ipaccess_nanobts.c \
diff --git a/src/osmo-bsc/abis_nm.c b/src/osmo-bsc/abis_nm.c
index 8dde8de9f..4ce27f3d9 100644
--- a/src/osmo-bsc/abis_nm.c
+++ b/src/osmo-bsc/abis_nm.c
@@ -48,6 +48,7 @@
#include <osmocom/bsc/signal.h>
#include <osmocom/abis/e1_input.h>
#include <osmocom/bsc/chan_alloc.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/gsm/bts_features.h>
#define OM_ALLOC_SIZE 1024
@@ -853,14 +854,6 @@ bool all_trx_rsl_connected_unlocked(const struct gsm_bts *bts)
return true;
}
-char *get_model_oml_status(const struct gsm_bts *bts)
-{
- if (bts->model->oml_status)
- return bts->model->oml_status(bts);
-
- return "unknown";
-}
-
void abis_nm_queue_send_next(struct gsm_bts *bts)
{
int wait = 0;
diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c
index 0aea684c0..1e4ef9783 100644
--- a/src/osmo-bsc/abis_om2000.c
+++ b/src/osmo-bsc/abis_om2000.c
@@ -44,6 +44,7 @@
#include <osmocom/bsc/abis_om2000.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/timeslot_fsm.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/abis/e1_input.h>
/* FIXME: move to libosmocore */
diff --git a/src/osmo-bsc/abis_om2000_vty.c b/src/osmo-bsc/abis_om2000_vty.c
index 222546f87..b00c7ddfe 100644
--- a/src/osmo-bsc/abis_om2000_vty.c
+++ b/src/osmo-bsc/abis_om2000_vty.c
@@ -33,6 +33,7 @@
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/abis_om2000.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/bsc/vty.h>
#include <osmocom/vty/vty.h>
diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c
index f6e564b28..1ffdd06a5 100644
--- a/src/osmo-bsc/abis_rsl.c
+++ b/src/osmo-bsc/abis_rsl.c
@@ -54,7 +54,7 @@
#include <osmocom/bsc/lchan_rtp_fsm.h>
#include <osmocom/bsc/handover_fsm.h>
#include <osmocom/bsc/smscb.h>
-
+#include <osmocom/bsc/bts.h>
#define RSL_ALLOC_SIZE 1024
#define RSL_ALLOC_HEADROOM 128
diff --git a/src/osmo-bsc/acc_ramp.c b/src/osmo-bsc/acc_ramp.c
index b79c0c2ac..761ab093c 100644
--- a/src/osmo-bsc/acc_ramp.c
+++ b/src/osmo-bsc/acc_ramp.c
@@ -29,6 +29,7 @@
#include <osmocom/bsc/chan_alloc.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/abis_nm.h>
+#include <osmocom/bsc/bts.h>
/*
* Check if an ACC has been permanently barred for a BTS,
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c
index cd5abc857..ca29daabb 100644
--- a/src/osmo-bsc/assignment_fsm.c
+++ b/src/osmo-bsc/assignment_fsm.c
@@ -34,6 +34,7 @@
#include <osmocom/bsc/gsm_08_08.h>
#include <osmocom/bsc/lchan_select.h>
#include <osmocom/bsc/abis_rsl.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/bsc/assignment_fsm.h>
diff --git a/src/osmo-bsc/bsc_ctrl_commands.c b/src/osmo-bsc/bsc_ctrl_commands.c
index 774ded21b..9383167fb 100644
--- a/src/osmo-bsc/bsc_ctrl_commands.c
+++ b/src/osmo-bsc/bsc_ctrl_commands.c
@@ -30,6 +30,7 @@
#include <osmocom/bsc/chan_alloc.h>
#include <osmocom/bsc/osmo_bsc_rf.h>
#include <osmocom/bsc/bsc_msc_data.h>
+#include <osmocom/bsc/bts.h>
CTRL_CMD_DEFINE(net_mcc, "mcc");
static int get_net_mcc(struct ctrl_cmd *cmd, void *_data)
diff --git a/src/osmo-bsc/bsc_init.c b/src/osmo-bsc/bsc_init.c
index 733353352..4fc0ab1bc 100644
--- a/src/osmo-bsc/bsc_init.c
+++ b/src/osmo-bsc/bsc_init.c
@@ -36,6 +36,7 @@
#include <osmocom/bsc/handover_cfg.h>
#include <osmocom/bsc/gsm_04_08_rr.h>
#include <osmocom/bsc/neighbor_ident.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/bsc/smscb.h>
#include <osmocom/gsm/protocol/gsm_48_049.h>
@@ -68,24 +69,6 @@ int bsc_shutdown_net(struct gsm_network *net)
return 0;
}
-unsigned long long bts_uptime(const struct gsm_bts *bts)
-{
- struct timespec tp;
-
- if (!bts->uptime || !bts->oml_link) {
- LOGP(DNM, LOGL_ERROR, "BTS %u OML link uptime unavailable\n", bts->nr);
- return 0;
- }
-
- if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0) {
- LOGP(DNM, LOGL_ERROR, "BTS %u uptime computation failure: %s\n", bts->nr, strerror(errno));
- return 0;
- }
-
- /* monotonic clock helps to ensure that the conversion is valid */
- return difftime(tp.tv_sec, bts->uptime);
-}
-
static int rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i, int si_len)
{
struct gsm_bts *bts = trx->bts;
diff --git a/src/osmo-bsc/bsc_rf_ctrl.c b/src/osmo-bsc/bsc_rf_ctrl.c
index c72154a02..1e04f21c3 100644
--- a/src/osmo-bsc/bsc_rf_ctrl.c
+++ b/src/osmo-bsc/bsc_rf_ctrl.c
@@ -26,6 +26,7 @@
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/ipaccess.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 36b16a21e..aa08e8b30 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -73,6 +73,7 @@
#include <osmocom/bsc/lchan_select.h>
#include <osmocom/bsc/smscb.h>
#include <osmocom/bsc/osmo_bsc.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
#include <inttypes.h>
diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c
new file mode 100644
index 000000000..71968f640
--- /dev/null
+++ b/src/osmo-bsc/bts.c
@@ -0,0 +1,748 @@
+/* (C) 2008-2018 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <osmocom/gsm/abis_nm.h>
+
+#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/debug.h>
+
+const struct value_string bts_attribute_names[] = {
+ OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
+ OSMO_VALUE_STRING(BTS_SUB_MODEL),
+ OSMO_VALUE_STRING(TRX_PHY_VERSION),
+ { 0, NULL }
+};
+
+enum bts_attribute str2btsattr(const char *s)
+{
+ return get_string_value(bts_attribute_names, s);
+}
+
+const char *btsatttr2str(enum bts_attribute v)
+{
+ return get_value_string(bts_attribute_names, v);
+}
+
+const struct value_string osmo_bts_variant_names[_NUM_BTS_VARIANT + 1] = {
+ { BTS_UNKNOWN, "unknown" },
+ { BTS_OSMO_LITECELL15, "osmo-bts-lc15" },
+ { BTS_OSMO_OCTPHY, "osmo-bts-octphy" },
+ { BTS_OSMO_SYSMO, "osmo-bts-sysmo" },
+ { BTS_OSMO_TRX, "omso-bts-trx" },
+ { 0, NULL }
+};
+
+enum gsm_bts_type_variant str2btsvariant(const char *arg)
+{
+ return get_string_value(osmo_bts_variant_names, arg);
+}
+
+const char *btsvariant2str(enum gsm_bts_type_variant v)
+{
+ return get_value_string(osmo_bts_variant_names, v);
+}
+
+const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE + 1] = {
+ { GSM_BTS_TYPE_UNKNOWN, "unknown" },
+ { GSM_BTS_TYPE_BS11, "bs11" },
+ { GSM_BTS_TYPE_NANOBTS, "nanobts" },
+ { GSM_BTS_TYPE_RBS2000, "rbs2000" },
+ { GSM_BTS_TYPE_NOKIA_SITE, "nokia_site" },
+ { GSM_BTS_TYPE_OSMOBTS, "sysmobts" },
+ { 0, NULL }
+};
+
+const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1] = {
+ { GSM_BTS_TYPE_UNKNOWN, "Unknown BTS Type" },
+ { GSM_BTS_TYPE_BS11, "Siemens BTS (BS-11 or compatible)" },
+ { GSM_BTS_TYPE_NANOBTS, "ip.access nanoBTS or compatible" },
+ { GSM_BTS_TYPE_RBS2000, "Ericsson RBS2000 Series" },
+ { GSM_BTS_TYPE_NOKIA_SITE, "Nokia {Metro,Ultra,In}Site" },
+ { GSM_BTS_TYPE_OSMOBTS, "sysmocom sysmoBTS" },
+ { 0, NULL }
+};
+
+enum gsm_bts_type str2btstype(const char *arg)
+{
+ return get_string_value(bts_type_names, arg);
+}
+
+const char *btstype2str(enum gsm_bts_type type)
+{
+ return get_value_string(bts_type_names, type);
+}
+
+static void bts_init_cbch_state(struct bts_smscb_chan_state *cstate, struct gsm_bts *bts)
+{
+ cstate->bts = bts;
+ INIT_LLIST_HEAD(&cstate->messages);
+}
+
+static LLIST_HEAD(bts_models);
+
+struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
+{
+ struct gsm_bts_model *model;
+
+ llist_for_each_entry(model, &bts_models, list) {
+ if (model->type == type)
+ return model;
+ }
+
+ return NULL;
+}
+
+int gsm_bts_model_register(struct gsm_bts_model *model)
+{
+ if (bts_model_find(model->type))
+ return -EEXIST;
+
+ tlv_def_patch(&model->nm_att_tlvdef, &abis_nm_att_tlvdef);
+ llist_add_tail(&model->list, &bts_models);
+ return 0;
+}
+
+static const struct osmo_stat_item_desc bts_stat_desc[] = {
+ [BTS_STAT_CHAN_LOAD_AVERAGE] = { "chanloadavg", "Channel load average", "%", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_USED] = { "chan_ccch_sdcch4:used",
+ "Number of CCCH+SDCCH4 channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL] = { "chan_ccch_sdcch4:total",
+ "Number of CCCH+SDCCH4 channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_USED] = { "chan_tch_f:used",
+ "Number of TCH/F channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_TOTAL] = { "chan_tch_f:total",
+ "Number of TCH/F channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_H_USED] = { "chan_tch_h:used",
+ "Number of TCH/H channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_H_TOTAL] = { "chan_tch_h:total",
+ "Number of TCH/H channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_USED] = { "chan_sdcch8:used",
+ "Number of SDCCH8 channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_TOTAL] = { "chan_sdcch8:total",
+ "Number of SDCCH8 channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_PDCH_USED] = { "chan_tch_f_pdch:used",
+ "Number of TCH/F_PDCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_PDCH_TOTAL] = { "chan_tch_f_pdch:total",
+ "Number of TCH/F_PDCH channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED] = { "chan_ccch_sdcch4_cbch:used",
+ "Number of CCCH+SDCCH4+CBCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL] = { "chan_ccch_sdcch4_cbch:total",
+ "Number of CCCH+SDCCH4+CBCH channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_CBCH_USED] = { "chan_sdcch8_cbch:used",
+ "Number of SDCCH8+CBCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL] = { "chan_sdcch8_cbch:total",
+ "Number of SDCCH8+CBCH channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_USED] = { "chan_tch_f_tch_h_pdch:used",
+ "Number of TCH/F_TCH/H_PDCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_TOTAL] = { "chan_tch_f_tch_h_pdch:total",
+ "Number of TCH/F_TCH/H_PDCH channels total", "", 16, 0 },
+ [BTS_STAT_T3122] = { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator",
+ "s", 16, GSM_T3122_DEFAULT },
+ [BTS_STAT_RACH_BUSY] = { "rach_busy",
+ "RACH slots with signal above threshold", "%", 16, 0 },
+ [BTS_STAT_RACH_ACCESS] = { "rach_access",
+ "RACH slots with access bursts in them", "%", 16, 0 },
+ [BTS_STAT_OML_CONNECTED] = { "oml_connected", "Number of OML links connected", "", 16, 0 },
+ [BTS_STAT_RSL_CONNECTED] = { "rsl_connected", "Number of RSL links connected", "", 16, 0 },
+ [BTS_STAT_LCHAN_BORKEN] = { "lchan_borken",
+ "Number of lchans in the BORKEN state", "", 16, 0 },
+ [BTS_STAT_TS_BORKEN] = { "ts_borken",
+ "Number of timeslots in the BORKEN state", "", 16, 0 },
+};
+
+static const struct osmo_stat_item_group_desc bts_statg_desc = {
+ .group_name_prefix = "bts",
+ .group_description = "base transceiver station",
+ .class_id = OSMO_STATS_CLASS_GLOBAL,
+ .num_items = ARRAY_SIZE(bts_stat_desc),
+ .item_desc = bts_stat_desc,
+};
+
+static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
+static const uint8_t bts_cell_timer_default[] =
+ { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
+static const struct gprs_rlc_cfg rlc_cfg_default = {
+ .parameter = {
+ [RLC_T3142] = 20,
+ [RLC_T3169] = 5,
+ [RLC_T3191] = 5,
+ [RLC_T3193] = 160, /* 10ms */
+ [RLC_T3195] = 5,
+ [RLC_N3101] = 10,
+ [RLC_N3103] = 4,
+ [RLC_N3105] = 8,
+ [CV_COUNTDOWN] = 15,
+ [T_DL_TBF_EXT] = 250 * 10, /* ms */
+ [T_UL_TBF_EXT] = 250 * 10, /* ms */
+ },
+ .paging = {
+ .repeat_time = 5 * 50, /* ms */
+ .repeat_count = 3,
+ },
+ .cs_mask = 0x1fff,
+ .initial_cs = 2,
+ .initial_mcs = 6,
+};
+
+/* Initialize those parts that don't require osmo-bsc specific dependencies.
+ * This part is shared among the thin programs in osmo-bsc/src/utils/.
+ * osmo-bsc requires further initialization that pulls in more dependencies (see
+ * bsc_bts_alloc_register()). */
+struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num)
+{
+ struct gsm_bts *bts = talloc_zero(net, struct gsm_bts);
+ struct gsm48_multi_rate_conf mr_cfg;
+ int i;
+
+ if (!bts)
+ return NULL;
+
+ bts->nr = bts_num;
+ bts->num_trx = 0;
+ INIT_LLIST_HEAD(&bts->trx_list);
+ bts->network = net;
+
+ bts->ms_max_power = 15; /* dBm */
+
+ gsm_mo_init(&bts->mo, bts, NM_OC_BTS,
+ bts->nr, 0xff, 0xff);
+ gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
+ 0xff, 0xff, 0xff);
+
+ for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
+ bts->gprs.nsvc[i].bts = bts;
+ bts->gprs.nsvc[i].id = i;
+ gsm_mo_init(&bts->gprs.nsvc[i].mo, bts, NM_OC_GPRS_NSVC,
+ bts->nr, i, 0xff);
+ }
+ memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
+ sizeof(bts->gprs.nse.timer));
+ gsm_mo_init(&bts->gprs.nse.mo, bts, NM_OC_GPRS_NSE,
+ bts->nr, 0xff, 0xff);
+ memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
+ sizeof(bts->gprs.cell.timer));
+ gsm_mo_init(&bts->gprs.cell.mo, bts, NM_OC_GPRS_CELL,
+ bts->nr, 0xff, 0xff);
+ memcpy(&bts->gprs.cell.rlc_cfg, &rlc_cfg_default,
+ sizeof(bts->gprs.cell.rlc_cfg));
+
+ /* 3GPP TS 08.18, chapter 5.4.1: 0 is reserved for signalling */
+ bts->gprs.cell.bvci = 2;
+
+ /* init statistics */
+ bts->bts_ctrs = rate_ctr_group_alloc(bts, &bts_ctrg_desc, bts->nr);
+ if (!bts->bts_ctrs) {
+ talloc_free(bts);
+ return NULL;
+ }
+ bts->bts_statg = osmo_stat_item_group_alloc(bts, &bts_statg_desc, bts->nr);
+
+ /* create our primary TRX */
+ bts->c0 = gsm_bts_trx_alloc(bts);
+ if (!bts->c0) {
+ rate_ctr_group_free(bts->bts_ctrs);
+ osmo_stat_item_group_free(bts->bts_statg);
+ talloc_free(bts);
+ return NULL;
+ }
+ bts->c0->ts[0].pchan_from_config = GSM_PCHAN_CCCH_SDCCH4; /* TODO: really?? */
+
+ bts->ccch_load_ind_thresh = 10; /* 10% of Load: Start sending CCCH LOAD IND */
+ bts->rach_b_thresh = -1;
+ bts->rach_ldavg_slots = -1;
+
+ bts->paging.free_chans_need = -1;
+ INIT_LLIST_HEAD(&bts->paging.pending_requests);
+
+ bts->features.data = &bts->_features_data[0];
+ bts->features.data_len = sizeof(bts->_features_data);
+
+ /* si handling */
+ bts->bcch_change_mark = 1;
+ bts->chan_load_avg = 0;
+
+ /* timer overrides */
+ bts->T3122 = 0; /* not overridden by default */
+ bts->T3113_dynamic = true; /* dynamic by default */
+
+ bts->dtxu = GSM48_DTX_SHALL_NOT_BE_USED;
+ bts->dtxd = false;
+ bts->gprs.ctrl_ack_type_use_block = true; /* use RLC/MAC control block */
+ bts->neigh_list_manual_mode = NL_MODE_AUTOMATIC;
+ bts->early_classmark_allowed_3g = true; /* 3g Early Classmark Sending controlled by bts->early_classmark_allowed param */
+ bts->si_unused_send_empty = true;
+ bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
+ bts->si_common.cell_sel_par.rxlev_acc_min = 0;
+ bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
+ bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
+ bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
+ bts->si_common.si2quater_neigh_list.thresh_hi = 0;
+ osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
+ bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
+ bts->si_common.neigh_list.data_len =
+ sizeof(bts->si_common.data.neigh_list);
+ bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list;
+ bts->si_common.si5_neigh_list.data_len =
+ sizeof(bts->si_common.data.si5_neigh_list);
+ bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
+ bts->si_common.cell_alloc.data_len =
+ sizeof(bts->si_common.data.cell_alloc);
+ bts->si_common.rach_control.re = 1; /* no re-establishment */
+ bts->si_common.rach_control.tx_integer = 9; /* 12 slots spread - 217/115 slots delay */
+ bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
+ bts->si_common.rach_control.t2 = 4; /* no emergency calls */
+ bts->si_common.chan_desc.att = 1; /* attachment required */
+ bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5; /* paging frames */
+ bts->si_common.chan_desc.bs_ag_blks_res = 1; /* reserved AGCH blocks */
+ bts->si_common.chan_desc.t3212 = osmo_tdef_get(net->T_defs, 3212, OSMO_TDEF_CUSTOM, -1);
+ gsm_bts_set_radio_link_timeout(bts, 32); /* Use RADIO LINK TIMEOUT of 32 */
+
+ INIT_LLIST_HEAD(&bts->abis_queue);
+ INIT_LLIST_HEAD(&bts->loc_list);
+ INIT_LLIST_HEAD(&bts->local_neighbors);
+ INIT_LLIST_HEAD(&bts->oml_fail_rep);
+
+ /* Enable all codecs by default. These get reset to a more fine grained selection IF a
+ * 'codec-support' config appears in the config file (see bsc_vty.c). */
+ bts->codec = (struct bts_codec_conf){
+ .hr = 1,
+ .efr = 1,
+ .amr = 1,
+ };
+
+ /* Set reasonable defaults for AMR-FR and AMR-HR rate configuration.
+ * (see also 3GPP TS 28.062, Table 7.11.3.1.3-2) */
+ mr_cfg = (struct gsm48_multi_rate_conf) {
+ .m4_75 = 1,
+ .m5_15 = 0,
+ .m5_90 = 1,
+ .m6_70 = 0,
+ .m7_40 = 1,
+ .m7_95 = 0,
+ .m10_2 = 0,
+ .m12_2 = 1
+ };
+ memcpy(bts->mr_full.gsm48_ie, &mr_cfg, sizeof(bts->mr_full.gsm48_ie));
+ bts->mr_full.ms_mode[0].mode = 0;
+ bts->mr_full.ms_mode[1].mode = 2;
+ bts->mr_full.ms_mode[2].mode = 4;
+ bts->mr_full.ms_mode[3].mode = 7;
+ bts->mr_full.bts_mode[0].mode = 0;
+ bts->mr_full.bts_mode[1].mode = 2;
+ bts->mr_full.bts_mode[2].mode = 4;
+ bts->mr_full.bts_mode[3].mode = 7;
+ for (i = 0; i < 3; i++) {
+ bts->mr_full.ms_mode[i].hysteresis = 8;
+ bts->mr_full.ms_mode[i].threshold = 32;
+ bts->mr_full.bts_mode[i].hysteresis = 8;
+ bts->mr_full.bts_mode[i].threshold = 32;
+ }
+ bts->mr_full.num_modes = 4;
+
+ mr_cfg = (struct gsm48_multi_rate_conf) {
+ .m4_75 = 1,
+ .m5_15 = 0,
+ .m5_90 = 1,
+ .m6_70 = 0,
+ .m7_40 = 1,
+ .m7_95 = 0,
+ .m10_2 = 0,
+ .m12_2 = 0
+ };
+ memcpy(bts->mr_half.gsm48_ie, &mr_cfg, sizeof(bts->mr_half.gsm48_ie));
+ bts->mr_half.ms_mode[0].mode = 0;
+ bts->mr_half.ms_mode[1].mode = 2;
+ bts->mr_half.ms_mode[2].mode = 4;
+ bts->mr_half.ms_mode[3].mode = 7;
+ bts->mr_half.bts_mode[0].mode = 0;
+ bts->mr_half.bts_mode[1].mode = 2;
+ bts->mr_half.bts_mode[2].mode = 4;
+ bts->mr_half.bts_mode[3].mode = 7;
+ for (i = 0; i < 3; i++) {
+ bts->mr_half.ms_mode[i].hysteresis = 8;
+ bts->mr_half.ms_mode[i].threshold = 32;
+ bts->mr_half.bts_mode[i].hysteresis = 8;
+ bts->mr_half.bts_mode[i].threshold = 32;
+ }
+ bts->mr_half.num_modes = 3;
+
+ bts_init_cbch_state(&bts->cbch_basic, bts);
+ bts_init_cbch_state(&bts->cbch_extended, bts);
+
+ return bts;
+}
+
+static char ts2str[255];
+
+char *gsm_bts_name(const struct gsm_bts *bts)
+{
+ if (!bts)
+ snprintf(ts2str, sizeof(ts2str), "(bts=NULL)");
+ else
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d)", bts->nr);
+
+ return ts2str;
+}
+
+bool gsm_bts_matches_lai(const struct gsm_bts *bts, const struct osmo_location_area_id *lai)
+{
+ return osmo_plmn_cmp(&lai->plmn, &bts->network->plmn) == 0
+ && lai->lac == bts->location_area_code;
+}
+
+bool gsm_bts_matches_cell_id(const struct gsm_bts *bts, const struct gsm0808_cell_id *cell_id)
+{
+ const union gsm0808_cell_id_u *id = &cell_id->id;
+ if (!bts || !cell_id)
+ return false;
+
+ switch (cell_id->id_discr) {
+ case CELL_IDENT_WHOLE_GLOBAL:
+ return gsm_bts_matches_lai(bts, &id->global.lai)
+ && id->global.cell_identity == bts->cell_identity;
+ case CELL_IDENT_LAC_AND_CI:
+ return id->lac_and_ci.lac == bts->location_area_code
+ && id->lac_and_ci.ci == bts->cell_identity;
+ case CELL_IDENT_CI:
+ return id->ci == bts->cell_identity;
+ case CELL_IDENT_NO_CELL:
+ return false;
+ case CELL_IDENT_LAI_AND_LAC:
+ return gsm_bts_matches_lai(bts, &id->lai_and_lac);
+ case CELL_IDENT_LAC:
+ return id->lac == bts->location_area_code;
+ case CELL_IDENT_BSS:
+ return true;
+ case CELL_IDENT_UTRAN_PLMN_LAC_RNC:
+ case CELL_IDENT_UTRAN_RNC:
+ case CELL_IDENT_UTRAN_LAC_RNC:
+ return false;
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static struct gsm_bts_ref *gsm_bts_ref_find(const struct llist_head *list, const struct gsm_bts *bts)
+{
+ struct gsm_bts_ref *ref;
+ if (!bts)
+ return NULL;
+ llist_for_each_entry(ref, list, entry) {
+ if (ref->bts == bts)
+ return ref;
+ }
+ return NULL;
+}
+
+/* Add a BTS reference to the local_neighbors list.
+ * Return 1 if added, 0 if such an entry already existed, and negative on errors. */
+int gsm_bts_local_neighbor_add(struct gsm_bts *bts, struct gsm_bts *neighbor)
+{
+ struct gsm_bts_ref *ref;
+ if (!bts || !neighbor)
+ return -ENOMEM;
+
+ if (bts == neighbor)
+ return -EINVAL;
+
+ /* Already got this entry? */
+ ref = gsm_bts_ref_find(&bts->local_neighbors, neighbor);
+ if (ref)
+ return 0;
+
+ ref = talloc_zero(bts, struct gsm_bts_ref);
+ if (!ref)
+ return -ENOMEM;
+ ref->bts = neighbor;
+ llist_add_tail(&ref->entry, &bts->local_neighbors);
+ return 1;
+}
+
+/* Remove a BTS reference from the local_neighbors list.
+ * Return 1 if removed, 0 if no such entry existed, and negative on errors. */
+int gsm_bts_local_neighbor_del(struct gsm_bts *bts, const struct gsm_bts *neighbor)
+{
+ struct gsm_bts_ref *ref;
+ if (!bts || !neighbor)
+ return -ENOMEM;
+
+ ref = gsm_bts_ref_find(&bts->local_neighbors, neighbor);
+ if (!ref)
+ return 0;
+
+ llist_del(&ref->entry);
+ talloc_free(ref);
+ return 1;
+}
+
+/* return the gsm_lchan for the CBCH (if it exists at all) */
+struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts)
+{
+ struct gsm_lchan *lchan = NULL;
+ struct gsm_bts_trx *trx = bts->c0;
+
+ if (trx->ts[0].pchan_from_config == GSM_PCHAN_CCCH_SDCCH4_CBCH)
+ lchan = &trx->ts[0].lchan[2];
+ else {
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (trx->ts[i].pchan_from_config == GSM_PCHAN_SDCCH8_SACCH8C_CBCH) {
+ lchan = &trx->ts[i].lchan[2];
+ break;
+ }
+ }
+ }
+
+ return lchan;
+}
+
+int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
+{
+ struct gsm_bts_model *model;
+
+ model = bts_model_find(type);
+ if (!model)
+ return -EINVAL;
+
+ bts->type = type;
+ bts->model = model;
+
+ if (model->start && !model->started) {
+ int ret = model->start(bts->network);
+ if (ret < 0)
+ return ret;
+
+ model->started = true;
+ }
+
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS:
+ case GSM_BTS_TYPE_OSMOBTS:
+ /* Set the default OML Stream ID to 0xff */
+ bts->oml_tei = 0xff;
+ bts->c0->nominal_power = 23;
+ break;
+ case GSM_BTS_TYPE_RBS2000:
+ INIT_LLIST_HEAD(&bts->rbs2000.is.conn_groups);
+ INIT_LLIST_HEAD(&bts->rbs2000.con.conn_groups);
+ break;
+ case GSM_BTS_TYPE_BS11:
+ case GSM_BTS_TYPE_UNKNOWN:
+ case GSM_BTS_TYPE_NOKIA_SITE:
+ /* Set default BTS reset timer */
+ bts->nokia.bts_reset_timer_cnf = 15;
+ case _NUM_GSM_BTS_TYPE:
+ break;
+ }
+
+ return 0;
+}
+
+int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode)
+{
+ if (mode != BTS_GPRS_NONE &&
+ !osmo_bts_has_feature(&bts->model->features, BTS_FEAT_GPRS)) {
+ return 0;
+ }
+ if (mode == BTS_GPRS_EGPRS &&
+ !osmo_bts_has_feature(&bts->model->features, BTS_FEAT_EGPRS)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr)
+{
+ struct gsm_bts_trx *trx;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ if (trx->nr == nr)
+ return trx;
+ }
+ return NULL;
+}
+
+unsigned long long bts_uptime(const struct gsm_bts *bts)
+{
+ struct timespec tp;
+
+ if (!bts->uptime || !bts->oml_link) {
+ LOGP(DNM, LOGL_ERROR, "BTS %u OML link uptime unavailable\n", bts->nr);
+ return 0;
+ }
+
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0) {
+ LOGP(DNM, LOGL_ERROR, "BTS %u uptime computation failure: %s\n", bts->nr, strerror(errno));
+ return 0;
+ }
+
+ /* monotonic clock helps to ensure that the conversion is valid */
+ return difftime(tp.tv_sec, bts->uptime);
+}
+
+char *get_model_oml_status(const struct gsm_bts *bts)
+{
+ if (bts->model->oml_status)
+ return bts->model->oml_status(bts);
+
+ return "unknown";
+}
+
+/* reset the state of all MO in the BTS */
+void gsm_bts_mo_reset(struct gsm_bts *bts)
+{
+ struct gsm_bts_trx *trx;
+ unsigned int i;
+
+ gsm_abis_mo_reset(&bts->mo);
+ gsm_abis_mo_reset(&bts->site_mgr.mo);
+ for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++)
+ gsm_abis_mo_reset(&bts->gprs.nsvc[i].mo);
+ gsm_abis_mo_reset(&bts->gprs.nse.mo);
+ gsm_abis_mo_reset(&bts->gprs.cell.mo);
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ gsm_abis_mo_reset(&trx->mo);
+ gsm_abis_mo_reset(&trx->bb_transc.mo);
+
+ for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ gsm_abis_mo_reset(&ts->mo);
+ }
+ }
+}
+
+/* Assume there are only 256 possible bts */
+osmo_static_assert(sizeof(((struct gsm_bts *) 0)->nr) == 1, _bts_nr_is_256);
+static void depends_calc_index_bit(int bts_nr, int *idx, int *bit)
+{
+ *idx = bts_nr / (8 * 4);
+ *bit = bts_nr % (8 * 4);
+}
+
+void bts_depend_mark(struct gsm_bts *bts, int dep)
+{
+ int idx, bit;
+ depends_calc_index_bit(dep, &idx, &bit);
+
+ bts->depends_on[idx] |= 1 << bit;
+}
+
+void bts_depend_clear(struct gsm_bts *bts, int dep)
+{
+ int idx, bit;
+ depends_calc_index_bit(dep, &idx, &bit);
+
+ bts->depends_on[idx] &= ~(1 << bit);
+}
+
+int bts_depend_is_depedency(struct gsm_bts *base, struct gsm_bts *other)
+{
+ int idx, bit;
+ depends_calc_index_bit(other->nr, &idx, &bit);
+
+ /* Check if there is a depends bit */
+ return (base->depends_on[idx] & (1 << bit)) > 0;
+}
+
+static int bts_is_online(struct gsm_bts *bts)
+{
+ /* TODO: support E1 BTS too */
+ if (!is_ipaccess_bts(bts))
+ return 1;
+
+ if (!bts->oml_link)
+ return 0;
+
+ return bts->mo.nm_state.operational == NM_OPSTATE_ENABLED;
+}
+
+int bts_depend_check(struct gsm_bts *bts)
+{
+ struct gsm_bts *other_bts;
+
+ llist_for_each_entry(other_bts, &bts->network->bts_list, list) {
+ if (!bts_depend_is_depedency(bts, other_bts))
+ continue;
+ if (bts_is_online(other_bts))
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/* get the radio link timeout (based on SACCH decode errors, according
+ * to algorithm specified in TS 05.08 section 5.2. A value of -1
+ * indicates we should use an infinitely long timeout, which only works
+ * with OsmoBTS as the BTS implementation */
+int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts)
+{
+ const struct gsm48_cell_options *cell_options = &bts->si_common.cell_options;
+
+ if (bts->infinite_radio_link_timeout)
+ return -1;
+ else {
+ /* Encoding as per Table 10.5.21 of TS 04.08 */
+ return (cell_options->radio_link_timeout + 1) << 2;
+ }
+}
+
+/* set the radio link timeout (based on SACCH decode errors, according
+ * to algorithm specified in TS 05.08 Section 5.2. A value of -1
+ * indicates we should use an infinitely long timeout, which only works
+ * with OsmoBTS as the BTS implementation */
+void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value)
+{
+ struct gsm48_cell_options *cell_options = &bts->si_common.cell_options;
+
+ if (value < 0)
+ bts->infinite_radio_link_timeout = true;
+ else {
+ bts->infinite_radio_link_timeout = false;
+ /* Encoding as per Table 10.5.21 of TS 04.08 */
+ if (value < 4)
+ value = 4;
+ if (value > 64)
+ value = 64;
+ cell_options->radio_link_timeout = (value >> 2) - 1;
+ }
+}
+
+void gsm_bts_all_ts_dispatch(struct gsm_bts *bts, uint32_t ts_ev, void *data)
+{
+ struct gsm_bts_trx *trx;
+ llist_for_each_entry(trx, &bts->trx_list, list)
+ gsm_trx_all_ts_dispatch(trx, ts_ev, data);
+}
+
+
+/* Count number of free TS of given pchan type */
+int bts_count_free_ts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
+{
+ struct gsm_bts_trx *trx;
+ int count = 0;
+
+ llist_for_each_entry(trx, &bts->trx_list, list)
+ count += trx_count_free_ts(trx, pchan);
+
+ return count;
+}
diff --git a/src/osmo-bsc/bts_ericsson_rbs2000.c b/src/osmo-bsc/bts_ericsson_rbs2000.c
index 02ef46387..1297b3025 100644
--- a/src/osmo-bsc/bts_ericsson_rbs2000.c
+++ b/src/osmo-bsc/bts_ericsson_rbs2000.c
@@ -29,6 +29,7 @@
#include <osmocom/abis/e1_input.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/timeslot_fsm.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/abis/lapd.h>
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c
index 5b603671e..49720e5c2 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts.c
@@ -45,6 +45,7 @@
#include <osmocom/bsc/bts_ipaccess_nanobts_omlattr.h>
#include <osmocom/bsc/paging.h>
#include <osmocom/bsc/timeslot_fsm.h>
+#include <osmocom/bsc/bts.h>
static int bts_model_nanobts_start(struct gsm_network *net);
static void bts_model_nanobts_e1line_bind_ops(struct e1inp_line *line);
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c
index be823ae43..b979cc73d 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c
@@ -23,7 +23,7 @@
#include <osmocom/core/msgb.h>
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/abis_nm.h>
-
+#include <osmocom/bsc/bts.h>
struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts)
{
diff --git a/src/osmo-bsc/bts_nokia_site.c b/src/osmo-bsc/bts_nokia_site.c
index 523c9edf3..2b6f91876 100644
--- a/src/osmo-bsc/bts_nokia_site.c
+++ b/src/osmo-bsc/bts_nokia_site.c
@@ -37,6 +37,7 @@
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/timeslot_fsm.h>
#include <osmocom/bsc/system_information.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/core/timer.h>
diff --git a/src/osmo-bsc/bts_siemens_bs11.c b/src/osmo-bsc/bts_siemens_bs11.c
index 057a0e153..c8084214f 100644
--- a/src/osmo-bsc/bts_siemens_bs11.c
+++ b/src/osmo-bsc/bts_siemens_bs11.c
@@ -30,6 +30,7 @@
#include <osmocom/abis/e1_input.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/timeslot_fsm.h>
+#include <osmocom/bsc/bts.h>
static int bts_model_bs11_start(struct gsm_network *net);
diff --git a/src/osmo-bsc/bts_sysmobts.c b/src/osmo-bsc/bts_sysmobts.c
index 6f9dc77cb..df43d76ae 100644
--- a/src/osmo-bsc/bts_sysmobts.c
+++ b/src/osmo-bsc/bts_sysmobts.c
@@ -26,6 +26,7 @@
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/abis_nm.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/abis/e1_input.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/core/msgb.h>
diff --git a/src/osmo-bsc/bts_unknown.c b/src/osmo-bsc/bts_unknown.c
index b6b56a81b..b5471ce0c 100644
--- a/src/osmo-bsc/bts_unknown.c
+++ b/src/osmo-bsc/bts_unknown.c
@@ -21,6 +21,7 @@
#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/bsc/abis_nm.h>
diff --git a/src/osmo-bsc/cbch_scheduler.c b/src/osmo-bsc/cbch_scheduler.c
index ef93b7a4a..802180419 100644
--- a/src/osmo-bsc/cbch_scheduler.c
+++ b/src/osmo-bsc/cbch_scheduler.c
@@ -28,6 +28,7 @@
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/smscb.h>
#include <osmocom/bsc/abis_rsl.h>
+#include <osmocom/bsc/bts.h>
/* add all pages of given SMSCB so they appear as soon as possible *after* (included) base_idx. */
static int bts_smscb_sched_add_after(struct bts_smscb_page **sched_arr, int sched_arr_size,
diff --git a/src/osmo-bsc/chan_alloc.c b/src/osmo-bsc/chan_alloc.c
index 9b80df3f5..6829251e3 100644
--- a/src/osmo-bsc/chan_alloc.c
+++ b/src/osmo-bsc/chan_alloc.c
@@ -34,6 +34,7 @@
#include <osmocom/bsc/timeslot_fsm.h>
#include <osmocom/bsc/lchan_fsm.h>
#include <osmocom/bsc/gsm_04_08_rr.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/core/talloc.h>
diff --git a/src/osmo-bsc/codec_pref.c b/src/osmo-bsc/codec_pref.c
index 6ec6d05ec..58a7867c5 100644
--- a/src/osmo-bsc/codec_pref.c
+++ b/src/osmo-bsc/codec_pref.c
@@ -27,6 +27,7 @@
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/codec_pref.h>
#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bts.h>
/* Determine whether a permitted speech value is specifies a half rate or full
* rate codec */
diff --git a/src/osmo-bsc/e1_config.c b/src/osmo-bsc/e1_config.c
index 4389f66c9..9ccbbfd70 100644
--- a/src/osmo-bsc/e1_config.c
+++ b/src/osmo-bsc/e1_config.c
@@ -30,6 +30,7 @@
#include <osmocom/core/talloc.h>
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/abis_rsl.h>
+#include <osmocom/bsc/bts.h>
#define SAPI_L2ML 0
#define SAPI_OML 62
diff --git a/src/osmo-bsc/gsm_04_08_rr.c b/src/osmo-bsc/gsm_04_08_rr.c
index 07978de30..e54a93719 100644
--- a/src/osmo-bsc/gsm_04_08_rr.c
+++ b/src/osmo-bsc/gsm_04_08_rr.c
@@ -44,6 +44,7 @@
#include <osmocom/bsc/gsm_08_08.h>
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/system_information.h>
+#include <osmocom/bsc/bts.h>
int gsm48_sendmsg(struct msgb *msg)
diff --git a/src/osmo-bsc/gsm_08_08.c b/src/osmo-bsc/gsm_08_08.c
index 2829b67c7..d5915f4f0 100644
--- a/src/osmo-bsc/gsm_08_08.c
+++ b/src/osmo-bsc/gsm_08_08.c
@@ -36,6 +36,7 @@
#include <osmocom/gsm/gsm23236.h>
#include <osmocom/bsc/osmo_bsc_sigtran.h>
+#include <osmocom/bsc/bts.h>
#define LOG_COMPL_L3(pdisc, mtype, loglevel, format, args...) \
LOGP(DRSL, loglevel, "%s %s: " format, gsm48_pdisc_name(pdisc), gsm48_pdisc_msgtype_name(pdisc, mtype), ##args)
diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c
index a4f6b7f36..12955929b 100644
--- a/src/osmo-bsc/gsm_data.c
+++ b/src/osmo-bsc/gsm_data.c
@@ -44,11 +44,10 @@
#include <osmocom/bsc/handover_cfg.h>
#include <osmocom/bsc/timeslot_fsm.h>
#include <osmocom/bsc/lchan_fsm.h>
+#include <osmocom/bsc/bts.h>
void *tall_bsc_ctx = NULL;
-static LLIST_HEAD(bts_models);
-
void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr,
uint8_t e1_ts, uint8_t e1_ts_ss)
{
@@ -57,49 +56,6 @@ void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr,
ts->e1_link.e1_ts_ss = e1_ts_ss;
}
-static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
-{
- struct gsm_bts_model *model;
-
- llist_for_each_entry(model, &bts_models, list) {
- if (model->type == type)
- return model;
- }
-
- return NULL;
-}
-
-int gsm_bts_model_register(struct gsm_bts_model *model)
-{
- if (bts_model_find(model->type))
- return -EEXIST;
-
- tlv_def_patch(&model->nm_att_tlvdef, &abis_nm_att_tlvdef);
- llist_add_tail(&model->list, &bts_models);
- return 0;
-}
-
-const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1] = {
- { GSM_BTS_TYPE_UNKNOWN, "Unknown BTS Type" },
- { GSM_BTS_TYPE_BS11, "Siemens BTS (BS-11 or compatible)" },
- { GSM_BTS_TYPE_NANOBTS, "ip.access nanoBTS or compatible" },
- { GSM_BTS_TYPE_RBS2000, "Ericsson RBS2000 Series" },
- { GSM_BTS_TYPE_NOKIA_SITE, "Nokia {Metro,Ultra,In}Site" },
- { GSM_BTS_TYPE_OSMOBTS, "sysmocom sysmoBTS" },
- { 0, NULL }
-};
-
-struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr)
-{
- struct gsm_bts_trx *trx;
-
- llist_for_each_entry(trx, &bts->trx_list, list) {
- if (trx->nr == nr)
- return trx;
- }
- return NULL;
-}
-
/* Search for a BTS in the given Location Area; optionally start searching
* with start_bts (for continuing to search after the first result) */
struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
@@ -149,62 +105,6 @@ const char *bts_gprs_mode_name(enum bts_gprs_mode mode)
return get_value_string(bts_gprs_mode_names, mode);
}
-int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode)
-{
- if (mode != BTS_GPRS_NONE &&
- !osmo_bts_has_feature(&bts->model->features, BTS_FEAT_GPRS)) {
- return 0;
- }
- if (mode == BTS_GPRS_EGPRS &&
- !osmo_bts_has_feature(&bts->model->features, BTS_FEAT_EGPRS)) {
- return 0;
- }
-
- return 1;
-}
-
-int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
-{
- struct gsm_bts_model *model;
-
- model = bts_model_find(type);
- if (!model)
- return -EINVAL;
-
- bts->type = type;
- bts->model = model;
-
- if (model->start && !model->started) {
- int ret = model->start(bts->network);
- if (ret < 0)
- return ret;
-
- model->started = true;
- }
-
- switch (bts->type) {
- case GSM_BTS_TYPE_NANOBTS:
- case GSM_BTS_TYPE_OSMOBTS:
- /* Set the default OML Stream ID to 0xff */
- bts->oml_tei = 0xff;
- bts->c0->nominal_power = 23;
- break;
- case GSM_BTS_TYPE_RBS2000:
- INIT_LLIST_HEAD(&bts->rbs2000.is.conn_groups);
- INIT_LLIST_HEAD(&bts->rbs2000.con.conn_groups);
- break;
- case GSM_BTS_TYPE_BS11:
- case GSM_BTS_TYPE_UNKNOWN:
- case GSM_BTS_TYPE_NOKIA_SITE:
- /* Set default BTS reset timer */
- bts->nokia.bts_reset_timer_cnf = 15;
- case _NUM_GSM_BTS_TYPE:
- break;
- }
-
- return 0;
-}
-
struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type,
uint8_t bsic)
{
@@ -248,166 +148,14 @@ void gsm48_ra_id_by_bts(struct gsm48_ra_id *buf, struct gsm_bts *bts)
gsm48_encode_ra(buf, &raid);
}
-/* Assume there are only 256 possible bts */
-osmo_static_assert(sizeof(((struct gsm_bts *) 0)->nr) == 1, _bts_nr_is_256);
-static void depends_calc_index_bit(int bts_nr, int *idx, int *bit)
-{
- *idx = bts_nr / (8 * 4);
- *bit = bts_nr % (8 * 4);
-}
-
-void bts_depend_mark(struct gsm_bts *bts, int dep)
-{
- int idx, bit;
- depends_calc_index_bit(dep, &idx, &bit);
-
- bts->depends_on[idx] |= 1 << bit;
-}
-
-void bts_depend_clear(struct gsm_bts *bts, int dep)
-{
- int idx, bit;
- depends_calc_index_bit(dep, &idx, &bit);
-
- bts->depends_on[idx] &= ~(1 << bit);
-}
-
-int bts_depend_is_depedency(struct gsm_bts *base, struct gsm_bts *other)
-{
- int idx, bit;
- depends_calc_index_bit(other->nr, &idx, &bit);
-
- /* Check if there is a depends bit */
- return (base->depends_on[idx] & (1 << bit)) > 0;
-}
-
-static int bts_is_online(struct gsm_bts *bts)
-{
- /* TODO: support E1 BTS too */
- if (!is_ipaccess_bts(bts))
- return 1;
-
- if (!bts->oml_link)
- return 0;
-
- return bts->mo.nm_state.operational == NM_OPSTATE_ENABLED;
-}
-
-int bts_depend_check(struct gsm_bts *bts)
-{
- struct gsm_bts *other_bts;
-
- llist_for_each_entry(other_bts, &bts->network->bts_list, list) {
- if (!bts_depend_is_depedency(bts, other_bts))
- continue;
- if (bts_is_online(other_bts))
- continue;
- return 0;
- }
- return 1;
-}
-
-/* get the radio link timeout (based on SACCH decode errors, according
- * to algorithm specified in TS 05.08 section 5.2. A value of -1
- * indicates we should use an infinitely long timeout, which only works
- * with OsmoBTS as the BTS implementation */
-int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts)
-{
- const struct gsm48_cell_options *cell_options = &bts->si_common.cell_options;
-
- if (bts->infinite_radio_link_timeout)
- return -1;
- else {
- /* Encoding as per Table 10.5.21 of TS 04.08 */
- return (cell_options->radio_link_timeout + 1) << 2;
- }
-}
-
-/* set the radio link timeout (based on SACCH decode errors, according
- * to algorithm specified in TS 05.08 Section 5.2. A value of -1
- * indicates we should use an infinitely long timeout, which only works
- * with OsmoBTS as the BTS implementation */
-void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value)
-{
- struct gsm48_cell_options *cell_options = &bts->si_common.cell_options;
-
- if (value < 0)
- bts->infinite_radio_link_timeout = true;
- else {
- bts->infinite_radio_link_timeout = false;
- /* Encoding as per Table 10.5.21 of TS 04.08 */
- if (value < 4)
- value = 4;
- if (value > 64)
- value = 64;
- cell_options->radio_link_timeout = (value >> 2) - 1;
- }
-}
-
-static const struct osmo_stat_item_desc bts_stat_desc[] = {
- [BTS_STAT_CHAN_LOAD_AVERAGE] = { "chanloadavg", "Channel load average", "%", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_USED] = { "chan_ccch_sdcch4:used",
- "Number of CCCH+SDCCH4 channels used", "", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL] = { "chan_ccch_sdcch4:total",
- "Number of CCCH+SDCCH4 channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_USED] = { "chan_tch_f:used",
- "Number of TCH/F channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_TOTAL] = { "chan_tch_f:total",
- "Number of TCH/F channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_H_USED] = { "chan_tch_h:used",
- "Number of TCH/H channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_H_TOTAL] = { "chan_tch_h:total",
- "Number of TCH/H channels total", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_USED] = { "chan_sdcch8:used",
- "Number of SDCCH8 channels used", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_TOTAL] = { "chan_sdcch8:total",
- "Number of SDCCH8 channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_PDCH_USED] = { "chan_tch_f_pdch:used",
- "Number of TCH/F_PDCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_PDCH_TOTAL] = { "chan_tch_f_pdch:total",
- "Number of TCH/F_PDCH channels total", "", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED] = { "chan_ccch_sdcch4_cbch:used",
- "Number of CCCH+SDCCH4+CBCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL] = { "chan_ccch_sdcch4_cbch:total",
- "Number of CCCH+SDCCH4+CBCH channels total", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_CBCH_USED] = { "chan_sdcch8_cbch:used",
- "Number of SDCCH8+CBCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL] = { "chan_sdcch8_cbch:total",
- "Number of SDCCH8+CBCH channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_USED] = { "chan_tch_f_tch_h_pdch:used",
- "Number of TCH/F_TCH/H_PDCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_TOTAL] = { "chan_tch_f_tch_h_pdch:total",
- "Number of TCH/F_TCH/H_PDCH channels total", "", 16, 0 },
- [BTS_STAT_T3122] = { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator",
- "s", 16, GSM_T3122_DEFAULT },
- [BTS_STAT_RACH_BUSY] = { "rach_busy",
- "RACH slots with signal above threshold", "%", 16, 0 },
- [BTS_STAT_RACH_ACCESS] = { "rach_access",
- "RACH slots with access bursts in them", "%", 16, 0 },
- [BTS_STAT_OML_CONNECTED] = { "oml_connected", "Number of OML links connected", "", 16, 0 },
- [BTS_STAT_RSL_CONNECTED] = { "rsl_connected", "Number of RSL links connected", "", 16, 0 },
- [BTS_STAT_LCHAN_BORKEN] = { "lchan_borken",
- "Number of lchans in the BORKEN state", "", 16, 0 },
- [BTS_STAT_TS_BORKEN] = { "ts_borken",
- "Number of timeslots in the BORKEN state", "", 16, 0 },
-};
-
-static const struct osmo_stat_item_group_desc bts_statg_desc = {
- .group_name_prefix = "bts",
- .group_description = "base transceiver station",
- .class_id = OSMO_STATS_CLASS_GLOBAL,
- .num_items = ARRAY_SIZE(bts_stat_desc),
- .item_desc = bts_stat_desc,
-};
-
void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
{
mo->nm_state.operational = NM_OPSTATE_NULL;
mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
}
-static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
- uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3)
+void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
+ uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3)
{
mo->bts = bts;
mo->obj_class = obj_class;
@@ -417,62 +165,6 @@ static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
gsm_abis_mo_reset(mo);
}
-const struct value_string bts_attribute_names[] = {
- OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
- OSMO_VALUE_STRING(BTS_SUB_MODEL),
- OSMO_VALUE_STRING(TRX_PHY_VERSION),
- { 0, NULL }
-};
-
-enum bts_attribute str2btsattr(const char *s)
-{
- return get_string_value(bts_attribute_names, s);
-}
-
-const char *btsatttr2str(enum bts_attribute v)
-{
- return get_value_string(bts_attribute_names, v);
-}
-
-const struct value_string osmo_bts_variant_names[_NUM_BTS_VARIANT + 1] = {
- { BTS_UNKNOWN, "unknown" },
- { BTS_OSMO_LITECELL15, "osmo-bts-lc15" },
- { BTS_OSMO_OCTPHY, "osmo-bts-octphy" },
- { BTS_OSMO_SYSMO, "osmo-bts-sysmo" },
- { BTS_OSMO_TRX, "omso-bts-trx" },
- { 0, NULL }
-};
-
-enum gsm_bts_type_variant str2btsvariant(const char *arg)
-{
- return get_string_value(osmo_bts_variant_names, arg);
-}
-
-const char *btsvariant2str(enum gsm_bts_type_variant v)
-{
- return get_value_string(osmo_bts_variant_names, v);
-}
-
-const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE + 1] = {
- { GSM_BTS_TYPE_UNKNOWN, "unknown" },
- { GSM_BTS_TYPE_BS11, "bs11" },
- { GSM_BTS_TYPE_NANOBTS, "nanobts" },
- { GSM_BTS_TYPE_RBS2000, "rbs2000" },
- { GSM_BTS_TYPE_NOKIA_SITE, "nokia_site" },
- { GSM_BTS_TYPE_OSMOBTS, "sysmobts" },
- { 0, NULL }
-};
-
-enum gsm_bts_type str2btstype(const char *arg)
-{
- return get_string_value(bts_type_names, arg);
-}
-
-const char *btstype2str(enum gsm_bts_type type)
-{
- return get_value_string(bts_type_names, type);
-}
-
const struct value_string gsm_chreq_descs[] = {
{ GSM_CHREQ_REASON_EMERG, "emergency call" },
{ GSM_CHREQ_REASON_PAG, "answer to paging" },
@@ -577,44 +269,6 @@ struct gsm_bts *gsm_bts_num(const struct gsm_network *net, int num)
return NULL;
}
-bool gsm_bts_matches_lai(const struct gsm_bts *bts, const struct osmo_location_area_id *lai)
-{
- return osmo_plmn_cmp(&lai->plmn, &bts->network->plmn) == 0
- && lai->lac == bts->location_area_code;
-}
-
-bool gsm_bts_matches_cell_id(const struct gsm_bts *bts, const struct gsm0808_cell_id *cell_id)
-{
- const union gsm0808_cell_id_u *id = &cell_id->id;
- if (!bts || !cell_id)
- return false;
-
- switch (cell_id->id_discr) {
- case CELL_IDENT_WHOLE_GLOBAL:
- return gsm_bts_matches_lai(bts, &id->global.lai)
- && id->global.cell_identity == bts->cell_identity;
- case CELL_IDENT_LAC_AND_CI:
- return id->lac_and_ci.lac == bts->location_area_code
- && id->lac_and_ci.ci == bts->cell_identity;
- case CELL_IDENT_CI:
- return id->ci == bts->cell_identity;
- case CELL_IDENT_NO_CELL:
- return false;
- case CELL_IDENT_LAI_AND_LAC:
- return gsm_bts_matches_lai(bts, &id->lai_and_lac);
- case CELL_IDENT_LAC:
- return id->lac == bts->location_area_code;
- case CELL_IDENT_BSS:
- return true;
- case CELL_IDENT_UTRAN_PLMN_LAC_RNC:
- case CELL_IDENT_UTRAN_RNC:
- case CELL_IDENT_UTRAN_LAC_RNC:
- return false;
- default:
- OSMO_ASSERT(false);
- }
-}
-
/* From a list of local BTSes that match the cell_id, return the Nth one, or NULL if there is no such
* match. */
struct gsm_bts *gsm_bts_by_cell_id(const struct gsm_network *net,
@@ -636,59 +290,6 @@ struct gsm_bts *gsm_bts_by_cell_id(const struct gsm_network *net,
return NULL;
}
-struct gsm_bts_ref *gsm_bts_ref_find(const struct llist_head *list, const struct gsm_bts *bts)
-{
- struct gsm_bts_ref *ref;
- if (!bts)
- return NULL;
- llist_for_each_entry(ref, list, entry) {
- if (ref->bts == bts)
- return ref;
- }
- return NULL;
-}
-
-/* Add a BTS reference to the local_neighbors list.
- * Return 1 if added, 0 if such an entry already existed, and negative on errors. */
-int gsm_bts_local_neighbor_add(struct gsm_bts *bts, struct gsm_bts *neighbor)
-{
- struct gsm_bts_ref *ref;
- if (!bts || !neighbor)
- return -ENOMEM;
-
- if (bts == neighbor)
- return -EINVAL;
-
- /* Already got this entry? */
- ref = gsm_bts_ref_find(&bts->local_neighbors, neighbor);
- if (ref)
- return 0;
-
- ref = talloc_zero(bts, struct gsm_bts_ref);
- if (!ref)
- return -ENOMEM;
- ref->bts = neighbor;
- llist_add_tail(&ref->entry, &bts->local_neighbors);
- return 1;
-}
-
-/* Remove a BTS reference from the local_neighbors list.
- * Return 1 if removed, 0 if no such entry existed, and negative on errors. */
-int gsm_bts_local_neighbor_del(struct gsm_bts *bts, const struct gsm_bts *neighbor)
-{
- struct gsm_bts_ref *ref;
- if (!bts || !neighbor)
- return -ENOMEM;
-
- ref = gsm_bts_ref_find(&bts->local_neighbors, neighbor);
- if (!ref)
- return 0;
-
- llist_del(&ref->entry);
- talloc_free(ref);
- return 1;
-}
-
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
@@ -748,251 +349,6 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
return trx;
}
-
-static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
-static const uint8_t bts_cell_timer_default[] =
- { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
-static const struct gprs_rlc_cfg rlc_cfg_default = {
- .parameter = {
- [RLC_T3142] = 20,
- [RLC_T3169] = 5,
- [RLC_T3191] = 5,
- [RLC_T3193] = 160, /* 10ms */
- [RLC_T3195] = 5,
- [RLC_N3101] = 10,
- [RLC_N3103] = 4,
- [RLC_N3105] = 8,
- [CV_COUNTDOWN] = 15,
- [T_DL_TBF_EXT] = 250 * 10, /* ms */
- [T_UL_TBF_EXT] = 250 * 10, /* ms */
- },
- .paging = {
- .repeat_time = 5 * 50, /* ms */
- .repeat_count = 3,
- },
- .cs_mask = 0x1fff,
- .initial_cs = 2,
- .initial_mcs = 6,
-};
-
-static void bts_init_cbch_state(struct bts_smscb_chan_state *cstate, struct gsm_bts *bts)
-{
- cstate->bts = bts;
- INIT_LLIST_HEAD(&cstate->messages);
-}
-
-/* Initialize those parts that don't require osmo-bsc specific dependencies.
- * This part is shared among the thin programs in osmo-bsc/src/utils/.
- * osmo-bsc requires further initialization that pulls in more dependencies (see
- * bsc_bts_alloc_register()). */
-struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num)
-{
- struct gsm_bts *bts = talloc_zero(net, struct gsm_bts);
- struct gsm48_multi_rate_conf mr_cfg;
- int i;
-
- if (!bts)
- return NULL;
-
- bts->nr = bts_num;
- bts->num_trx = 0;
- INIT_LLIST_HEAD(&bts->trx_list);
- bts->network = net;
-
- bts->ms_max_power = 15; /* dBm */
-
- gsm_mo_init(&bts->mo, bts, NM_OC_BTS,
- bts->nr, 0xff, 0xff);
- gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
- 0xff, 0xff, 0xff);
-
- for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
- bts->gprs.nsvc[i].bts = bts;
- bts->gprs.nsvc[i].id = i;
- gsm_mo_init(&bts->gprs.nsvc[i].mo, bts, NM_OC_GPRS_NSVC,
- bts->nr, i, 0xff);
- }
- memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
- sizeof(bts->gprs.nse.timer));
- gsm_mo_init(&bts->gprs.nse.mo, bts, NM_OC_GPRS_NSE,
- bts->nr, 0xff, 0xff);
- memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
- sizeof(bts->gprs.cell.timer));
- gsm_mo_init(&bts->gprs.cell.mo, bts, NM_OC_GPRS_CELL,
- bts->nr, 0xff, 0xff);
- memcpy(&bts->gprs.cell.rlc_cfg, &rlc_cfg_default,
- sizeof(bts->gprs.cell.rlc_cfg));
-
- /* 3GPP TS 08.18, chapter 5.4.1: 0 is reserved for signalling */
- bts->gprs.cell.bvci = 2;
-
- /* init statistics */
- bts->bts_ctrs = rate_ctr_group_alloc(bts, &bts_ctrg_desc, bts->nr);
- if (!bts->bts_ctrs) {
- talloc_free(bts);
- return NULL;
- }
- bts->bts_statg = osmo_stat_item_group_alloc(bts, &bts_statg_desc, bts->nr);
-
- /* create our primary TRX */
- bts->c0 = gsm_bts_trx_alloc(bts);
- if (!bts->c0) {
- rate_ctr_group_free(bts->bts_ctrs);
- osmo_stat_item_group_free(bts->bts_statg);
- talloc_free(bts);
- return NULL;
- }
- bts->c0->ts[0].pchan_from_config = GSM_PCHAN_CCCH_SDCCH4; /* TODO: really?? */
-
- bts->ccch_load_ind_thresh = 10; /* 10% of Load: Start sending CCCH LOAD IND */
- bts->rach_b_thresh = -1;
- bts->rach_ldavg_slots = -1;
-
- bts->paging.free_chans_need = -1;
- INIT_LLIST_HEAD(&bts->paging.pending_requests);
-
- bts->features.data = &bts->_features_data[0];
- bts->features.data_len = sizeof(bts->_features_data);
-
- /* si handling */
- bts->bcch_change_mark = 1;
- bts->chan_load_avg = 0;
-
- /* timer overrides */
- bts->T3122 = 0; /* not overridden by default */
- bts->T3113_dynamic = true; /* dynamic by default */
-
- bts->dtxu = GSM48_DTX_SHALL_NOT_BE_USED;
- bts->dtxd = false;
- bts->gprs.ctrl_ack_type_use_block = true; /* use RLC/MAC control block */
- bts->neigh_list_manual_mode = NL_MODE_AUTOMATIC;
- bts->early_classmark_allowed_3g = true; /* 3g Early Classmark Sending controlled by bts->early_classmark_allowed param */
- bts->si_unused_send_empty = true;
- bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
- bts->si_common.cell_sel_par.rxlev_acc_min = 0;
- bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
- bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
- bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
- bts->si_common.si2quater_neigh_list.thresh_hi = 0;
- osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
- bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
- bts->si_common.neigh_list.data_len =
- sizeof(bts->si_common.data.neigh_list);
- bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list;
- bts->si_common.si5_neigh_list.data_len =
- sizeof(bts->si_common.data.si5_neigh_list);
- bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
- bts->si_common.cell_alloc.data_len =
- sizeof(bts->si_common.data.cell_alloc);
- bts->si_common.rach_control.re = 1; /* no re-establishment */
- bts->si_common.rach_control.tx_integer = 9; /* 12 slots spread - 217/115 slots delay */
- bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
- bts->si_common.rach_control.t2 = 4; /* no emergency calls */
- bts->si_common.chan_desc.att = 1; /* attachment required */
- bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5; /* paging frames */
- bts->si_common.chan_desc.bs_ag_blks_res = 1; /* reserved AGCH blocks */
- bts->si_common.chan_desc.t3212 = osmo_tdef_get(net->T_defs, 3212, OSMO_TDEF_CUSTOM, -1);
- gsm_bts_set_radio_link_timeout(bts, 32); /* Use RADIO LINK TIMEOUT of 32 */
-
- INIT_LLIST_HEAD(&bts->abis_queue);
- INIT_LLIST_HEAD(&bts->loc_list);
- INIT_LLIST_HEAD(&bts->local_neighbors);
- INIT_LLIST_HEAD(&bts->oml_fail_rep);
-
- /* Enable all codecs by default. These get reset to a more fine grained selection IF a
- * 'codec-support' config appears in the config file (see bsc_vty.c). */
- bts->codec = (struct bts_codec_conf){
- .hr = 1,
- .efr = 1,
- .amr = 1,
- };
-
- /* Set reasonable defaults for AMR-FR and AMR-HR rate configuration.
- * (see also 3GPP TS 28.062, Table 7.11.3.1.3-2) */
- mr_cfg = (struct gsm48_multi_rate_conf) {
- .m4_75 = 1,
- .m5_15 = 0,
- .m5_90 = 1,
- .m6_70 = 0,
- .m7_40 = 1,
- .m7_95 = 0,
- .m10_2 = 0,
- .m12_2 = 1
- };
- memcpy(bts->mr_full.gsm48_ie, &mr_cfg, sizeof(bts->mr_full.gsm48_ie));
- bts->mr_full.ms_mode[0].mode = 0;
- bts->mr_full.ms_mode[1].mode = 2;
- bts->mr_full.ms_mode[2].mode = 4;
- bts->mr_full.ms_mode[3].mode = 7;
- bts->mr_full.bts_mode[0].mode = 0;
- bts->mr_full.bts_mode[1].mode = 2;
- bts->mr_full.bts_mode[2].mode = 4;
- bts->mr_full.bts_mode[3].mode = 7;
- for (i = 0; i < 3; i++) {
- bts->mr_full.ms_mode[i].hysteresis = 8;
- bts->mr_full.ms_mode[i].threshold = 32;
- bts->mr_full.bts_mode[i].hysteresis = 8;
- bts->mr_full.bts_mode[i].threshold = 32;
- }
- bts->mr_full.num_modes = 4;
-
- mr_cfg = (struct gsm48_multi_rate_conf) {
- .m4_75 = 1,
- .m5_15 = 0,
- .m5_90 = 1,
- .m6_70 = 0,
- .m7_40 = 1,
- .m7_95 = 0,
- .m10_2 = 0,
- .m12_2 = 0
- };
- memcpy(bts->mr_half.gsm48_ie, &mr_cfg, sizeof(bts->mr_half.gsm48_ie));
- bts->mr_half.ms_mode[0].mode = 0;
- bts->mr_half.ms_mode[1].mode = 2;
- bts->mr_half.ms_mode[2].mode = 4;
- bts->mr_half.ms_mode[3].mode = 7;
- bts->mr_half.bts_mode[0].mode = 0;
- bts->mr_half.bts_mode[1].mode = 2;
- bts->mr_half.bts_mode[2].mode = 4;
- bts->mr_half.bts_mode[3].mode = 7;
- for (i = 0; i < 3; i++) {
- bts->mr_half.ms_mode[i].hysteresis = 8;
- bts->mr_half.ms_mode[i].threshold = 32;
- bts->mr_half.bts_mode[i].hysteresis = 8;
- bts->mr_half.bts_mode[i].threshold = 32;
- }
- bts->mr_half.num_modes = 3;
-
- bts_init_cbch_state(&bts->cbch_basic, bts);
- bts_init_cbch_state(&bts->cbch_extended, bts);
-
- return bts;
-}
-
-/* reset the state of all MO in the BTS */
-void gsm_bts_mo_reset(struct gsm_bts *bts)
-{
- struct gsm_bts_trx *trx;
- unsigned int i;
-
- gsm_abis_mo_reset(&bts->mo);
- gsm_abis_mo_reset(&bts->site_mgr.mo);
- for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++)
- gsm_abis_mo_reset(&bts->gprs.nsvc[i].mo);
- gsm_abis_mo_reset(&bts->gprs.nse.mo);
- gsm_abis_mo_reset(&bts->gprs.cell.mo);
-
- llist_for_each_entry(trx, &bts->trx_list, list) {
- gsm_abis_mo_reset(&trx->mo);
- gsm_abis_mo_reset(&trx->bb_transc.mo);
-
- for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
- struct gsm_bts_trx_ts *ts = &trx->ts[i];
- gsm_abis_mo_reset(&ts->mo);
- }
- }
-}
-
struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num)
{
struct gsm_bts_trx *trx;
@@ -1010,16 +366,6 @@ struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num)
static char ts2str[255];
-char *gsm_bts_name(const struct gsm_bts *bts)
-{
- if (!bts)
- snprintf(ts2str, sizeof(ts2str), "(bts=NULL)");
- else
- snprintf(ts2str, sizeof(ts2str), "(bts=%d)", bts->nr);
-
- return ts2str;
-}
-
char *gsm_trx_name(const struct gsm_bts_trx *trx)
{
if (!trx)
@@ -1289,27 +635,6 @@ uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)
return gsm_pchan2chan_nr(lchan->ts->pchan_is, lchan->ts->nr, lchan->nr);
}
-/* return the gsm_lchan for the CBCH (if it exists at all) */
-struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts)
-{
- struct gsm_lchan *lchan = NULL;
- struct gsm_bts_trx *trx = bts->c0;
-
- if (trx->ts[0].pchan_from_config == GSM_PCHAN_CCCH_SDCCH4_CBCH)
- lchan = &trx->ts[0].lchan[2];
- else {
- int i;
- for (i = 0; i < 8; i++) {
- if (trx->ts[i].pchan_from_config == GSM_PCHAN_SDCCH8_SACCH8C_CBCH) {
- lchan = &trx->ts[i].lchan[2];
- break;
- }
- }
- }
-
- return lchan;
-}
-
/* determine logical channel based on TRX and channel number IE */
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
int *rc)
@@ -1392,6 +717,12 @@ bool ts_is_tch(struct gsm_bts_trx_ts *ts)
return pchan_is_tch(ts->pchan_is);
}
+struct gsm_bts *conn_get_bts(struct gsm_subscriber_connection *conn) {
+ if (!conn || !conn->lchan)
+ return NULL;
+ return conn->lchan->ts->trx->bts;
+}
+
bool trx_is_usable(const struct gsm_bts_trx *trx)
{
/* FIXME: How does this behave for BS-11 ? */
@@ -1417,13 +748,6 @@ void gsm_trx_all_ts_dispatch(struct gsm_bts_trx *trx, uint32_t ts_ev, void *data
}
}
-void gsm_bts_all_ts_dispatch(struct gsm_bts *bts, uint32_t ts_ev, void *data)
-{
- struct gsm_bts_trx *trx;
- llist_for_each_entry(trx, &bts->trx_list, list)
- gsm_trx_all_ts_dispatch(trx, ts_ev, data);
-}
-
static void _chan_desc_fill_tail(struct gsm48_chan_desc *cd, const struct gsm_lchan *lchan)
{
if (!lchan->ts->hopping.enabled) {
@@ -1458,6 +782,14 @@ void gsm48_lchan2chan_desc_as_configured(struct gsm48_chan_desc *cd,
_chan_desc_fill_tail(cd, lchan);
}
+uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts)
+{
+ if (ts->tsc != -1)
+ return ts->tsc;
+ else
+ return ts->trx->bts->bsic & 7;
+}
+
bool nm_is_running(const struct gsm_nm_state *s) {
if (s->operational != NM_OPSTATE_ENABLED)
return false;
@@ -1633,7 +965,7 @@ bool ts_is_capable_of_lchant(struct gsm_bts_trx_ts *ts, enum gsm_chan_t type)
}
}
-static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
+int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
{
struct gsm_bts_trx_ts *ts;
struct gsm_lchan *lchan;
@@ -1681,18 +1013,6 @@ static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config
return count;
}
-/* Count number of free TS of given pchan type */
-int bts_count_free_ts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
-{
- struct gsm_bts_trx *trx;
- int count = 0;
-
- llist_for_each_entry(trx, &bts->trx_list, list)
- count += trx_count_free_ts(trx, pchan);
-
- return count;
-}
-
bool ts_is_usable(const struct gsm_bts_trx_ts *ts)
{
if (!trx_is_usable(ts->trx)) {
diff --git a/src/osmo-bsc/handover_decision.c b/src/osmo-bsc/handover_decision.c
index 533840024..7eb8f31e0 100644
--- a/src/osmo-bsc/handover_decision.c
+++ b/src/osmo-bsc/handover_decision.c
@@ -34,6 +34,7 @@
#include <osmocom/bsc/handover_fsm.h>
#include <osmocom/bsc/handover_cfg.h>
+#include <osmocom/bsc/bts.h>
/* did we get a RXLEV for a given cell in the given report? */
static int rxlev_for_cell_in_rep(struct gsm_meas_rep *mr,
diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c
index ab507e84c..8caa2e3f4 100644
--- a/src/osmo-bsc/handover_decision_2.c
+++ b/src/osmo-bsc/handover_decision_2.c
@@ -37,6 +37,7 @@
#include <osmocom/bsc/penalty_timers.h>
#include <osmocom/bsc/neighbor_ident.h>
#include <osmocom/bsc/timeslot_fsm.h>
+#include <osmocom/bsc/bts.h>
#define LOGPHOBTS(bts, level, fmt, args...) \
LOGP(DHODEC, level, "(BTS %u) " fmt, bts->nr, ## args)
diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c
index 0b88b27d8..8ed5945c5 100644
--- a/src/osmo-bsc/handover_fsm.c
+++ b/src/osmo-bsc/handover_fsm.c
@@ -43,6 +43,7 @@
#include <osmocom/bsc/osmo_bsc_lcls.h>
#include <osmocom/bsc/codec_pref.h>
#include <osmocom/bsc/gsm_08_08.h>
+#include <osmocom/bsc/bts.h>
#define LOG_FMT_BTS "bts %u lac-ci %u-%u arfcn-bsic %d-%d"
#define LOG_ARGS_BTS(bts) \
diff --git a/src/osmo-bsc/handover_logic.c b/src/osmo-bsc/handover_logic.c
index 5be838340..071228e88 100644
--- a/src/osmo-bsc/handover_logic.c
+++ b/src/osmo-bsc/handover_logic.c
@@ -43,6 +43,7 @@
#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
#include <osmocom/bsc/neighbor_ident.h>
#include <osmocom/bsc/abis_nm.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/gsm/gsm0808.h>
#include <osmocom/gsm/gsm0808_utils.h>
diff --git a/src/osmo-bsc/handover_vty.c b/src/osmo-bsc/handover_vty.c
index a418aa7ac..81313e251 100644
--- a/src/osmo-bsc/handover_vty.c
+++ b/src/osmo-bsc/handover_vty.c
@@ -27,6 +27,7 @@
#include <osmocom/bsc/vty.h>
#include <osmocom/bsc/handover_cfg.h>
#include <osmocom/bsc/handover_decision_2.h>
+#include <osmocom/bsc/bts.h>
static struct handover_cfg *ho_cfg_from_vty(struct vty *vty)
{
diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c
index bcf7c4b06..e879059da 100644
--- a/src/osmo-bsc/lchan_fsm.c
+++ b/src/osmo-bsc/lchan_fsm.c
@@ -39,7 +39,7 @@
#include <osmocom/bsc/handover_fsm.h>
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/codec_pref.h>
-
+#include <osmocom/bsc/bts.h>
static struct osmo_fsm lchan_fsm;
diff --git a/src/osmo-bsc/lchan_rtp_fsm.c b/src/osmo-bsc/lchan_rtp_fsm.c
index 4be979002..2def2f5db 100644
--- a/src/osmo-bsc/lchan_rtp_fsm.c
+++ b/src/osmo-bsc/lchan_rtp_fsm.c
@@ -30,6 +30,7 @@
#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
#include <osmocom/bsc/abis_rsl.h>
#include <osmocom/bsc/bsc_msc_data.h>
+#include <osmocom/bsc/bts.h>
static struct osmo_fsm lchan_rtp_fsm;
diff --git a/src/osmo-bsc/lchan_select.c b/src/osmo-bsc/lchan_select.c
index d63db22d3..d2dba1bb2 100644
--- a/src/osmo-bsc/lchan_select.c
+++ b/src/osmo-bsc/lchan_select.c
@@ -28,6 +28,7 @@
#include <osmocom/bsc/lchan_fsm.h>
#include <osmocom/bsc/lchan_select.h>
+#include <osmocom/bsc/bts.h>
static struct gsm_lchan *
_lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan,
diff --git a/src/osmo-bsc/meas_feed.c b/src/osmo-bsc/meas_feed.c
index f9a362600..889f6efc3 100644
--- a/src/osmo-bsc/meas_feed.c
+++ b/src/osmo-bsc/meas_feed.c
@@ -19,6 +19,7 @@
#include <osmocom/bsc/meas_feed.h>
#include <osmocom/bsc/vty.h>
#include <osmocom/bsc/debug.h>
+#include <osmocom/bsc/bts.h>
struct meas_feed_state {
struct osmo_wqueue wqueue;
diff --git a/src/osmo-bsc/neighbor_ident_vty.c b/src/osmo-bsc/neighbor_ident_vty.c
index 54d6944f5..7feed2a27 100644
--- a/src/osmo-bsc/neighbor_ident_vty.c
+++ b/src/osmo-bsc/neighbor_ident_vty.c
@@ -30,6 +30,7 @@
#include <osmocom/bsc/vty.h>
#include <osmocom/bsc/neighbor_ident.h>
#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bts.h>
static struct gsm_network *g_net = NULL;
static struct neighbor_ident_list *g_neighbor_cells = NULL;
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index 1cacfe935..bf38d107d 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -33,6 +33,7 @@
#include <osmocom/bsc/codec_pref.h>
#include <osmocom/bsc/abis_rsl.h>
#include <osmocom/bsc/handover_fsm.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/gsm/protocol/gsm_08_08.h>
#include <osmocom/gsm/gsm0808.h>
diff --git a/src/osmo-bsc/osmo_bsc_ctrl.c b/src/osmo-bsc/osmo_bsc_ctrl.c
index b94a749bf..5ebe59789 100644
--- a/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -27,6 +27,7 @@
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/a_reset.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/signal.h>
diff --git a/src/osmo-bsc/osmo_bsc_filter.c b/src/osmo-bsc/osmo_bsc_filter.c
index 08c3a5048..f664231e8 100644
--- a/src/osmo-bsc/osmo_bsc_filter.c
+++ b/src/osmo-bsc/osmo_bsc_filter.c
@@ -26,6 +26,7 @@
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/paging.h>
#include <osmocom/bsc/gsm_04_08_rr.h>
+#include <osmocom/bsc/bts.h>
#include <stdlib.h>
diff --git a/src/osmo-bsc/osmo_bsc_grace.c b/src/osmo-bsc/osmo_bsc_grace.c
index 56edee569..a26a716ad 100644
--- a/src/osmo-bsc/osmo_bsc_grace.c
+++ b/src/osmo-bsc/osmo_bsc_grace.c
@@ -25,6 +25,7 @@
#include <osmocom/bsc/paging.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/lchan_fsm.h>
+#include <osmocom/bsc/bts.h>
int bsc_grace_allow_new_connection(struct gsm_network *network, struct gsm_bts *bts)
{
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index ada60472d..84b44f70d 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -64,6 +64,7 @@
#include <osmocom/bsc/e1_config.h>
#include <osmocom/bsc/codec_pref.h>
#include <osmocom/bsc/system_information.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/mgcp_client/mgcp_client.h>
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
index f2a1e5b0f..5e02b4a39 100644
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ b/src/osmo-bsc/osmo_bsc_msc.c
@@ -29,6 +29,7 @@
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/osmo_bsc_sigtran.h>
#include <osmocom/bsc/signal.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/socket.h>
diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c
index afc6c8d8f..de4be2630 100644
--- a/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -34,6 +34,7 @@
#include <osmocom/bsc/a_reset.h>
#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/mgcp_client/mgcp_common.h>
/* A pointer to a list with all involved MSCs
diff --git a/src/osmo-bsc/paging.c b/src/osmo-bsc/paging.c
index 7859c69d0..521598f6f 100644
--- a/src/osmo-bsc/paging.c
+++ b/src/osmo-bsc/paging.c
@@ -53,6 +53,7 @@
#include <osmocom/bsc/gsm_08_08.h>
#include <osmocom/bsc/gsm_04_08_rr.h>
#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
+#include <osmocom/bsc/bts.h>
void *tall_paging_ctx = NULL;
diff --git a/src/osmo-bsc/pcu_sock.c b/src/osmo-bsc/pcu_sock.c
index 3e0b7bf79..ae4ac8a20 100644
--- a/src/osmo-bsc/pcu_sock.c
+++ b/src/osmo-bsc/pcu_sock.c
@@ -44,6 +44,7 @@
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/abis_rsl.h>
#include <osmocom/bsc/gsm_04_08_rr.h>
+#include <osmocom/bsc/bts.h>
static int pcu_sock_send(struct gsm_bts *bts, struct msgb *msg);
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
diff --git a/src/osmo-bsc/rest_octets.c b/src/osmo-bsc/rest_octets.c
index 0d806f393..7307cb888 100644
--- a/src/osmo-bsc/rest_octets.c
+++ b/src/osmo-bsc/rest_octets.c
@@ -33,6 +33,7 @@
#include <osmocom/bsc/rest_octets.h>
#include <osmocom/bsc/arfcn_range_encode.h>
#include <osmocom/bsc/system_information.h>
+#include <osmocom/bsc/bts.h>
/* generate SI1 rest octets */
int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
diff --git a/src/osmo-bsc/smscb.c b/src/osmo-bsc/smscb.c
index 8d48af9fe..436826a25 100644
--- a/src/osmo-bsc/smscb.c
+++ b/src/osmo-bsc/smscb.c
@@ -41,6 +41,7 @@
#include <osmocom/bsc/gsm_04_08_rr.h>
#include <osmocom/bsc/lchan_fsm.h>
#include <osmocom/bsc/abis_rsl.h>
+#include <osmocom/bsc/bts.h>
/*********************************************************************************
* Helper Functions
diff --git a/src/osmo-bsc/system_information.c b/src/osmo-bsc/system_information.c
index b17a909e5..13d0f4673 100644
--- a/src/osmo-bsc/system_information.c
+++ b/src/osmo-bsc/system_information.c
@@ -41,6 +41,7 @@
#include <osmocom/bsc/gsm_04_08_rr.h>
#include <osmocom/bsc/acc_ramp.h>
#include <osmocom/bsc/neighbor_ident.h>
+#include <osmocom/bsc/bts.h>
struct gsm0808_cell_id_list2;
diff --git a/src/osmo-bsc/timeslot_fsm.c b/src/osmo-bsc/timeslot_fsm.c
index 4816dafb5..0aecfaeb2 100644
--- a/src/osmo-bsc/timeslot_fsm.c
+++ b/src/osmo-bsc/timeslot_fsm.c
@@ -28,6 +28,7 @@
#include <osmocom/bsc/lchan_fsm.h>
#include <osmocom/bsc/abis_rsl.h>
#include <osmocom/bsc/pcu_if.h>
+#include <osmocom/bsc/bts.h>
static struct osmo_fsm ts_fsm;
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
index e585e0df8..669667971 100644
--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -48,6 +48,7 @@ bs11_config_SOURCES = \
bs11_config_LDADD = \
$(top_builddir)/src/osmo-bsc/abis_nm.o \
+ $(top_builddir)/src/osmo-bsc/bts.o \
$(top_builddir)/src/osmo-bsc/bts_siemens_bs11.o \
$(top_builddir)/src/osmo-bsc/e1_config.o \
$(top_builddir)/src/osmo-bsc/gsm_data.o \
@@ -117,6 +118,7 @@ meas_json_SOURCES = \
$(NULL)
meas_json_LDADD = \
+ $(top_builddir)/src/osmo-bsc/bts.o \
$(top_builddir)/src/osmo-bsc/gsm_data.o \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
diff --git a/src/utils/bs11_config.c b/src/utils/bs11_config.c
index 11562336c..c43c008bf 100644
--- a/src/utils/bs11_config.c
+++ b/src/utils/bs11_config.c
@@ -39,6 +39,7 @@
#include <osmocom/bsc/debug.h>
#include <osmocom/core/select.h>
#include <osmocom/bsc/rs232.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
#include <osmocom/abis/abis.h>