diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/ipaccess/Makefile.am | 12 | ||||
-rw-r--r-- | src/ipaccess/ipaccess-config.c | 7 | ||||
-rw-r--r-- | src/ipaccess/stubs.c | 43 | ||||
-rw-r--r-- | src/libbsc/Makefile.am | 70 | ||||
-rw-r--r-- | src/libbsc/bsc_init.c | 591 | ||||
-rw-r--r-- | src/osmo-bsc/Makefile.am | 58 | ||||
-rw-r--r-- | src/osmo-bsc/a_reset.c (renamed from src/libbsc/a_reset.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/abis_bs11.c | 21 | ||||
-rw-r--r-- | src/osmo-bsc/abis_nm.c (renamed from src/libbsc/abis_nm.c) | 7 | ||||
-rw-r--r-- | src/osmo-bsc/abis_nm_ipaccess.c (renamed from src/libbsc/abis_nm_ipaccess.c) | 2 | ||||
-rw-r--r-- | src/osmo-bsc/abis_nm_vty.c (renamed from src/libbsc/abis_nm_vty.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/abis_om2000.c (renamed from src/libbsc/abis_om2000.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/abis_om2000_vty.c (renamed from src/libbsc/abis_om2000_vty.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/abis_rsl.c (renamed from src/libbsc/abis_rsl.c) | 32 | ||||
-rw-r--r-- | src/osmo-bsc/acc_ramp.c (renamed from src/libbsc/acc_ramp.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/arfcn_range_encode.c (renamed from src/libbsc/arfcn_range_encode.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_api.c (renamed from src/libbsc/bsc_api.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_ctrl_commands.c (renamed from src/libbsc/bsc_ctrl_commands.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_ctrl_lookup.c (renamed from src/libbsc/bsc_ctrl_lookup.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_dyn_ts.c (renamed from src/libbsc/bsc_dyn_ts.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_init.c | 288 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_rf_ctrl.c (renamed from src/libbsc/bsc_rf_ctrl.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_rll.c (renamed from src/libbsc/bsc_rll.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_subscr_conn_fsm.c (renamed from src/libbsc/bsc_subscr_conn_fsm.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_subscriber.c (renamed from src/libbsc/bsc_subscriber.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_vty.c (renamed from src/libbsc/bsc_vty.c) | 2 | ||||
-rw-r--r-- | src/osmo-bsc/bts_ericsson_rbs2000.c (renamed from src/libbsc/bts_ericsson_rbs2000.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bts_init.c (renamed from src/libbsc/bts_init.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bts_ipaccess_nanobts.c (renamed from src/libbsc/bts_ipaccess_nanobts.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c (renamed from src/libbsc/bts_ipaccess_nanobts_omlattr.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bts_nokia_site.c (renamed from src/libbsc/bts_nokia_site.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bts_siemens_bs11.c (renamed from src/libbsc/bts_siemens_bs11.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bts_sysmobts.c (renamed from src/libbsc/bts_sysmobts.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/bts_unknown.c (renamed from src/libbsc/bts_unknown.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/chan_alloc.c (renamed from src/libbsc/chan_alloc.c) | 12 | ||||
-rw-r--r-- | src/osmo-bsc/e1_config.c (renamed from src/libbsc/e1_config.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/gsm_04_08_utils.c (renamed from src/libbsc/gsm_04_08_utils.c) | 20 | ||||
-rw-r--r-- | src/osmo-bsc/gsm_04_80_utils.c (renamed from src/libbsc/gsm_04_80_utils.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/gsm_data.c (renamed from src/libbsc/gsm_data.c) | 75 | ||||
-rw-r--r-- | src/osmo-bsc/handover_cfg.c (renamed from src/libbsc/handover_cfg.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/handover_decision.c (renamed from src/libbsc/handover_decision.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/handover_decision_2.c (renamed from src/libbsc/handover_decision_2.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/handover_logic.c (renamed from src/libbsc/handover_logic.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/handover_vty.c (renamed from src/libbsc/handover_vty.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/meas_feed.c (renamed from src/libbsc/meas_feed.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/meas_rep.c (renamed from src/libbsc/meas_rep.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/net_init.c (renamed from src/libbsc/net_init.c) | 60 | ||||
-rw-r--r-- | src/osmo-bsc/osmo_bsc_lcls.c (renamed from src/libbsc/osmo_bsc_lcls.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/osmo_bsc_main.c | 369 | ||||
-rw-r--r-- | src/osmo-bsc/paging.c (renamed from src/libbsc/paging.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/pcu_sock.c (renamed from src/libbsc/pcu_sock.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/penalty_timers.c (renamed from src/libbsc/penalty_timers.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/rest_octets.c (renamed from src/libbsc/rest_octets.c) | 0 | ||||
-rw-r--r-- | src/osmo-bsc/system_information.c (renamed from src/libbsc/system_information.c) | 0 | ||||
-rw-r--r-- | src/utils/Makefile.am | 13 | ||||
-rw-r--r-- | src/utils/bs11_config.c | 3 | ||||
-rw-r--r-- | src/utils/stubs.c | 36 |
58 files changed, 914 insertions, 815 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index fc9bf8e1a..6c63eead8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,15 +19,9 @@ AM_LDFLAGS = \ $(COVERAGE_LDFLAGS) \ $(NULL) -# Libraries SUBDIRS = \ - libbsc \ libfilter \ - $(NULL) - -# Programs -SUBDIRS += \ + osmo-bsc \ utils \ ipaccess \ - osmo-bsc \ $(NULL) diff --git a/src/ipaccess/Makefile.am b/src/ipaccess/Makefile.am index 0f9045fd0..2c6282d11 100644 --- a/src/ipaccess/Makefile.am +++ b/src/ipaccess/Makefile.am @@ -33,31 +33,37 @@ bin_PROGRAMS = \ $(NULL) abisip_find_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ $(OSMO_LIBS) \ $(NULL) abisip_find_SOURCES = \ abisip-find.c \ + stubs.c \ $(NULL) ipaccess_config_SOURCES = \ ipaccess-config.c \ ipaccess-firmware.c \ network_listen.c \ + stubs.c \ $(NULL) # FIXME: resolve the bogus dependencies patched around here: ipaccess_config_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ + $(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 \ + $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/net_init.o \ $(OSMO_LIBS) \ $(NULL) ipaccess_proxy_SOURCES = \ ipaccess-proxy.c \ + stubs.c \ + $(top_srcdir)/src/osmo-bsc/gsm_data.c \ $(NULL) ipaccess_proxy_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ $(OSMO_LIBS) \ $(NULL) diff --git a/src/ipaccess/ipaccess-config.c b/src/ipaccess/ipaccess-config.c index 223606373..079bae2b9 100644 --- a/src/ipaccess/ipaccess-config.c +++ b/src/ipaccess/ipaccess-config.c @@ -39,7 +39,6 @@ #include <osmocom/core/select.h> #include <osmocom/core/timer.h> #include <osmocom/bsc/ipaccess.h> -#include <osmocom/bsc/common_bsc.h> #include <osmocom/abis/e1_input.h> #include <osmocom/bsc/abis_nm.h> #include <osmocom/bsc/signal.h> @@ -54,6 +53,7 @@ #include <osmocom/core/talloc.h> #include <osmocom/abis/abis.h> #include <osmocom/gsm/protocol/gsm_12_21.h> +#include <osmocom/bsc/bss.h> struct gsm_network *bsc_gsmnet; @@ -873,8 +873,6 @@ static void print_options(void) print_value_string(&ipa_test_strs[0], ARRAY_SIZE(ipa_test_strs)); } -extern void bts_model_nanobts_init(); - static const struct log_info_cat log_categories[] = { [DNM] = { .name = "DNM", @@ -898,6 +896,7 @@ int main(int argc, char **argv) int rc, option_index = 0, stream_id = 0xff; tall_ctx_config = talloc_named_const(NULL, 0, "ipaccess-config"); + tall_bsc_ctx = tall_ctx_config; msgb_talloc_ctx_init(tall_ctx_config, 0); osmo_init_logging2(tall_ctx_config, &log_info); @@ -1034,7 +1033,7 @@ int main(int argc, char **argv) libosmo_abis_init(tall_ctx_config); - bsc_gsmnet = bsc_network_init(tall_bsc_ctx); + bsc_gsmnet = gsm_network_init(tall_ctx_config); if (!bsc_gsmnet) exit(1); diff --git a/src/ipaccess/stubs.c b/src/ipaccess/stubs.c new file mode 100644 index 000000000..c52d52b77 --- /dev/null +++ b/src/ipaccess/stubs.c @@ -0,0 +1,43 @@ +/* Stubs required for linking */ + +/* (C) 2018 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 <stdbool.h> +struct gsm_bts; +struct gsm_bts_trx_ts; +struct msgb; +struct bsc_msc_data; + +bool on_gsm_ts_init(struct gsm_bts_trx_ts *ts) +{ + /* No TS init required here. */ + return true; +} + +int abis_rsl_rcvmsg(struct msgb *msg) +{ + /* No RSL handling here */ + return 0; +} + +void paging_flush_bts(struct gsm_bts *bts, struct bsc_msc_data *msc) +{ + /* No paging flushing */ +} diff --git a/src/libbsc/Makefile.am b/src/libbsc/Makefile.am deleted file mode 100644 index 2e447292f..000000000 --- a/src/libbsc/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOGSM_CFLAGS) \ - $(LIBOSMOVTY_CFLAGS) \ - $(LIBOSMOABIS_CFLAGS) \ - $(LIBOSMOMGCP_CFLAGS) \ - $(LIBOSMOSIGTRAN_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(LIBOSMOMGCPCLIENT_CFLAGS) \ - $(NULL) - -noinst_LIBRARIES = \ - libbsc.a \ - $(NULL) - -libbsc_a_SOURCES = \ - abis_nm.c \ - abis_nm_vty.c \ - abis_om2000.c \ - abis_om2000_vty.c \ - abis_rsl.c \ - a_reset.c \ - acc_ramp.c \ - bsc_rll.c \ - bsc_subscriber.c \ - paging.c \ - bts_ericsson_rbs2000.c \ - bts_ipaccess_nanobts.c \ - bts_siemens_bs11.c \ - bts_nokia_site.c \ - bts_unknown.c \ - bts_sysmobts.c \ - chan_alloc.c \ - gsm_data.c \ - handover_decision.c \ - handover_logic.c \ - meas_rep.c \ - pcu_sock.c \ - rest_octets.c \ - system_information.c \ - e1_config.c \ - bsc_api.c \ - bsc_vty.c \ - gsm_04_08_utils.c \ - gsm_04_80_utils.c \ - bsc_init.c \ - bts_init.c \ - bsc_rf_ctrl.c \ - arfcn_range_encode.c \ - bsc_ctrl_commands.c \ - bsc_ctrl_lookup.c \ - net_init.c \ - bsc_dyn_ts.c \ - bts_ipaccess_nanobts_omlattr.c \ - handover_vty.c \ - handover_cfg.c \ - penalty_timers.c \ - handover_decision_2.c \ - bsc_subscr_conn_fsm.c \ - meas_feed.c \ - osmo_bsc_lcls.c \ - $(NULL) - diff --git a/src/libbsc/bsc_init.c b/src/libbsc/bsc_init.c deleted file mode 100644 index 508a7f410..000000000 --- a/src/libbsc/bsc_init.c +++ /dev/null @@ -1,591 +0,0 @@ -/* A hackish minimal BSC (+MSC +HLR) implementation */ - -/* (C) 2008-2018 by Harald Welte <laforge@gnumonks.org> - * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * 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/bsc/gsm_data.h> -#include <osmocom/gsm/gsm_utils.h> -#include <osmocom/bsc/abis_rsl.h> -#include <osmocom/bsc/abis_nm.h> -#include <osmocom/bsc/debug.h> -#include <osmocom/bsc/misdn.h> -#include <osmocom/vty/telnet_interface.h> -#include <osmocom/vty/ports.h> -#include <osmocom/bsc/system_information.h> -#include <osmocom/bsc/paging.h> -#include <osmocom/bsc/signal.h> -#include <osmocom/bsc/chan_alloc.h> -#include <osmocom/core/talloc.h> -#include <osmocom/bsc/ipaccess.h> -#include <osmocom/gsm/sysinfo.h> -#include <osmocom/bsc/e1_config.h> -#include <osmocom/bsc/common_bsc.h> -#include <osmocom/bsc/pcu_if.h> - -#include <time.h> -#include <limits.h> -#include <stdbool.h> - -/* Callback function for NACK on the OML NM */ -static int oml_msg_nack(struct nm_nack_signal_data *nack) -{ - if (nack->mt == NM_MT_GET_ATTR_NACK) { - LOGP(DNM, LOGL_ERROR, "BTS%u does not support Get Attributes " - "OML message.\n", nack->bts->nr); - return 0; - } - - if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) - LOGP(DNM, LOGL_ERROR, "Failed to set BTS attributes. That is fatal. " - "Was the bts type and frequency properly specified?\n"); - else - LOGP(DNM, LOGL_ERROR, "Got %s NACK going to drop the OML links.\n", - abis_nm_nack_name(nack->mt)); - - if (!nack->bts) { - LOGP(DNM, LOGL_ERROR, "Unknown bts. Can not drop it.\n"); - return 0; - } - - if (is_ipaccess_bts(nack->bts)) - ipaccess_drop_oml(nack->bts); - - return 0; -} - -/* Callback function to be called every time we receive a signal from NM */ -static int nm_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) -{ - struct nm_nack_signal_data *nack; - - switch (signal) { - case S_NM_NACK: - nack = signal_data; - return oml_msg_nack(nack); - default: - break; - } - return 0; -} - -int bsc_shutdown_net(struct gsm_network *net) -{ - struct gsm_bts *bts; - - llist_for_each_entry(bts, &net->bts_list, list) { - LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr); - osmo_signal_dispatch(SS_L_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts); - } - - 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; - int rc, j; - - if (si_len) { - DEBUGP(DRR, "SI%s: %s\n", get_value_string(osmo_sitype_strs, i), - osmo_hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN)); - } else - DEBUGP(DRR, "SI%s: OFF\n", get_value_string(osmo_sitype_strs, i)); - - switch (i) { - case SYSINFO_TYPE_5: - case SYSINFO_TYPE_5bis: - case SYSINFO_TYPE_5ter: - case SYSINFO_TYPE_6: - rc = rsl_sacch_filling(trx, osmo_sitype2rsl(i), - si_len ? GSM_BTS_SI(bts, i) : NULL, si_len); - break; - case SYSINFO_TYPE_2quater: - if (si_len == 0) { - rc = rsl_bcch_info(trx, i, NULL, 0); - break; - } - rc = 0; - for (j = 0; j <= bts->si2q_count; j++) - rc = rsl_bcch_info(trx, i, (const uint8_t *)GSM_BTS_SI2Q(bts, j), GSM_MACBLOCK_LEN); - break; - default: - rc = rsl_bcch_info(trx, i, si_len ? GSM_BTS_SI(bts, i) : NULL, si_len); - break; - } - - return rc; -} - -/* set all system information types for a TRX */ -int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) -{ - int i, rc; - struct gsm_bts *bts = trx->bts; - uint8_t gen_si[_MAX_SYSINFO_TYPE], n_si = 0, n; - int si_len[_MAX_SYSINFO_TYPE]; - - bts->si_common.cell_sel_par.ms_txpwr_max_ccch = - ms_pwr_ctl_lvl(bts->band, bts->ms_max_power); - bts->si_common.cell_sel_par.neci = bts->network->neci; - - /* Zero/forget the state of the dynamically computed SIs, leeping the static ones */ - bts->si_valid = bts->si_mode_static; - - /* First, we determine which of the SI messages we actually need */ - - if (trx == bts->c0) { - /* 1...4 are always present on a C0 TRX */ - gen_si[n_si++] = SYSINFO_TYPE_1; - gen_si[n_si++] = SYSINFO_TYPE_2; - gen_si[n_si++] = SYSINFO_TYPE_2bis; - gen_si[n_si++] = SYSINFO_TYPE_2ter; - gen_si[n_si++] = SYSINFO_TYPE_2quater; - gen_si[n_si++] = SYSINFO_TYPE_3; - gen_si[n_si++] = SYSINFO_TYPE_4; - - /* 13 is always present on a C0 TRX of a GPRS BTS */ - if (bts->gprs.mode != BTS_GPRS_NONE) - gen_si[n_si++] = SYSINFO_TYPE_13; - } - - /* 5 and 6 are always present on every TRX */ - gen_si[n_si++] = SYSINFO_TYPE_5; - gen_si[n_si++] = SYSINFO_TYPE_5bis; - gen_si[n_si++] = SYSINFO_TYPE_5ter; - gen_si[n_si++] = SYSINFO_TYPE_6; - - /* Second, we generate the selected SI via RSL */ - - for (n = 0; n < n_si; n++) { - i = gen_si[n]; - /* Only generate SI if this SI is not in "static" (user-defined) mode */ - if (!(bts->si_mode_static & (1 << i))) { - /* Set SI as being valid. gsm_generate_si() might unset - * it, if SI is not required. */ - bts->si_valid |= (1 << i); - rc = gsm_generate_si(bts, i); - if (rc < 0) - goto err_out; - si_len[i] = rc; - } else { - if (i == SYSINFO_TYPE_5 || i == SYSINFO_TYPE_5bis - || i == SYSINFO_TYPE_5ter) - si_len[i] = 18; - else if (i == SYSINFO_TYPE_6) - si_len[i] = 11; - else - si_len[i] = 23; - } - } - - /* Third, we send the selected SI via RSL */ - - for (n = 0; n < n_si; n++) { - i = gen_si[n]; - /* if we don't currently have this SI, we send a zero-length - * RSL BCCH FILLING / SACCH FILLING * in order to deactivate - * the SI, in case it might have previously been active */ - if (!GSM_BTS_HAS_SI(bts, i)) - rc = rsl_si(trx, i, 0); - else - rc = rsl_si(trx, i, si_len[i]); - if (rc < 0) - return rc; - } - - /* Make sure the PCU is aware (in case anything GPRS related has - * changed in SI */ - pcu_info_update(bts); - - return 0; -err_out: - LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u: error <%s>, " - "most likely a problem with neighbor cell list generation\n", - get_value_string(osmo_sitype_strs, i), bts->nr, strerror(-rc)); - return rc; -} - -/* set all system information types for a BTS */ -int gsm_bts_set_system_infos(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - - /* Generate a new ID */ - bts->bcch_change_mark += 1; - bts->bcch_change_mark %= 0x7; - - llist_for_each_entry(trx, &bts->trx_list, list) { - int rc; - - rc = gsm_bts_trx_set_system_infos(trx); - if (rc != 0) - return rc; - } - - return 0; -} - -/* Produce a MA as specified in 10.5.2.21 */ -static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts) -{ - /* we have three bitvecs: the per-timeslot ARFCNs, the cell chan ARFCNs - * and the MA */ - struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc; - struct bitvec *ts_arfcn = &ts->hopping.arfcns; - struct bitvec *ma = &ts->hopping.ma; - unsigned int num_cell_arfcns, bitnum, n_chan; - int i; - - /* re-set the MA to all-zero */ - ma->cur_bit = 0; - ts->hopping.ma_len = 0; - memset(ma->data, 0, ma->data_len); - - if (!ts->hopping.enabled) - return 0; - - /* count the number of ARFCNs in the cell channel allocation */ - num_cell_arfcns = 0; - for (i = 0; i < 1024; i++) { - if (bitvec_get_bit_pos(cell_chan, i)) - num_cell_arfcns++; - } - - /* pad it to octet-aligned number of bits */ - ts->hopping.ma_len = num_cell_arfcns / 8; - if (num_cell_arfcns % 8) - ts->hopping.ma_len++; - - n_chan = 0; - for (i = 0; i < 1024; i++) { - if (!bitvec_get_bit_pos(cell_chan, i)) - continue; - /* set the corresponding bit in the MA */ - bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan; - if (bitvec_get_bit_pos(ts_arfcn, i)) - bitvec_set_bit_pos(ma, bitnum, 1); - else - bitvec_set_bit_pos(ma, bitnum, 0); - n_chan++; - } - - /* ARFCN 0 is special: It is coded last in the bitmask */ - if (bitvec_get_bit_pos(cell_chan, 0)) { - n_chan++; - /* set the corresponding bit in the MA */ - bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan; - if (bitvec_get_bit_pos(ts_arfcn, 0)) - bitvec_set_bit_pos(ma, bitnum, 1); - else - bitvec_set_bit_pos(ma, bitnum, 0); - } - - return 0; -} - -static void bootstrap_rsl(struct gsm_bts_trx *trx) -{ - unsigned int i; - - LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) " - "on ARFCN %u using MCC-MNC %s LAC=%u CID=%u BSIC=%u\n", - trx->bts->nr, trx->nr, trx->arfcn, - osmo_plmn_name(&bsc_gsmnet->plmn), - trx->bts->location_area_code, - trx->bts->cell_identity, trx->bts->bsic); - - if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) { - rsl_nokia_si_begin(trx); - } - - /* - * Trigger ACC ramping before sending system information to BTS. - * This ensures that RACH control in system information is configured correctly. - * TRX 0 should be usable and unlocked, otherwise starting ACC ramping is pointless. - */ - if (trx_is_usable(trx) && trx->mo.nm_state.administrative == NM_STATE_UNLOCKED) - acc_ramp_trigger(&trx->bts->acc_ramp); - - gsm_bts_trx_set_system_infos(trx); - - if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) { - /* channel unspecific, power reduction in 2 dB steps */ - rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2); - rsl_nokia_si_end(trx); - } - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { - struct gsm_bts_trx_ts *ts = &trx->ts[i]; - generate_ma_for_ts(ts); - gsm_ts_check_init(ts); - } -} - -/* Callback function to be called every time we receive a signal from INPUT */ -static int inp_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) -{ - struct input_signal_data *isd = signal_data; - struct gsm_bts_trx *trx = isd->trx; - int ts_no, lchan_no; - /* N. B: we rely on attribute order when parsing response in abis_nm_rx_get_attr_resp() */ - const uint8_t bts_attr[] = { NM_ATT_MANUF_ID, NM_ATT_SW_CONFIG, }; - const uint8_t trx_attr[] = { NM_ATT_MANUF_STATE, NM_ATT_SW_CONFIG, }; - - /* we should not request more attributes than we're ready to handle */ - OSMO_ASSERT(sizeof(bts_attr) < MAX_BTS_ATTR); - OSMO_ASSERT(sizeof(trx_attr) < MAX_BTS_ATTR); - - if (subsys != SS_L_INPUT) - return -EINVAL; - - LOGP(DLMI, LOGL_DEBUG, "%s(): Input signal '%s' received\n", __func__, - get_value_string(e1inp_signal_names, signal)); - switch (signal) { - case S_L_INP_TEI_UP: - if (isd->link_type == E1INP_SIGN_OML) { - /* TODO: this is required for the Nokia BTS, hopping is configured - during OML, other MA is not set. */ - struct gsm_bts_trx *cur_trx; - /* was static in system_information.c */ - extern int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts); - uint8_t ca[20]; - /* has to be called before generate_ma_for_ts to - set bts->si_common.cell_alloc */ - generate_cell_chan_list(ca, trx->bts); - - /* Request generic BTS-level attributes */ - abis_nm_get_attr(trx->bts, NM_OC_BTS, 0xFF, 0xFF, 0xFF, bts_attr, sizeof(bts_attr)); - - llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) { - int i; - /* Request TRX-level attributes */ - abis_nm_get_attr(cur_trx->bts, NM_OC_BASEB_TRANSC, 0, cur_trx->nr, 0xFF, - trx_attr, sizeof(trx_attr)); - for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++) - generate_ma_for_ts(&cur_trx->ts[i]); - } - } - if (isd->link_type == E1INP_SIGN_RSL) - bootstrap_rsl(trx); - break; - case S_L_INP_TEI_DN: - LOGP(DLMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", isd->link_type, trx); - - if (isd->link_type == E1INP_SIGN_OML) - rate_ctr_inc(&trx->bts->bts_ctrs->ctr[BTS_CTR_BTS_OML_FAIL]); - else if (isd->link_type == E1INP_SIGN_RSL) { - rate_ctr_inc(&trx->bts->bts_ctrs->ctr[BTS_CTR_BTS_RSL_FAIL]); - acc_ramp_abort(&trx->bts->acc_ramp); - } - - /* - * free all allocated channels. change the nm_state so the - * trx and trx_ts becomes unusable and chan_alloc.c can not - * allocate from it. - */ - for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) { - struct gsm_bts_trx_ts *ts = &trx->ts[ts_no]; - - for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) { - if (ts->lchan[lchan_no].state != LCHAN_S_NONE) - lchan_free(&ts->lchan[lchan_no]); - lchan_reset(&ts->lchan[lchan_no]); - } - } - - gsm_bts_mo_reset(trx->bts); - - abis_nm_clear_queue(trx->bts); - break; - default: - break; - } - - return 0; -} - -static int bootstrap_bts(struct gsm_bts *bts) -{ - int i, n; - - if (!bts->model) - return -EFAULT; - - if (bts->model->start && !bts->model->started) { - int ret = bts->model->start(bts->network); - if (ret < 0) - return ret; - - bts->model->started = true; - } - - /* FIXME: What about secondary TRX of a BTS? What about a BTS that has TRX - * in different bands? Why is 'band' a parameter of the BTS and not of the TRX? */ - switch (bts->band) { - case GSM_BAND_1800: - if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) { - LOGP(DNM, LOGL_ERROR, "GSM1800 channel must be between 512-885.\n"); - return -EINVAL; - } - break; - case GSM_BAND_1900: - if (bts->c0->arfcn < 512 || bts->c0->arfcn > 810) { - LOGP(DNM, LOGL_ERROR, "GSM1900 channel must be between 512-810.\n"); - return -EINVAL; - } - break; - case GSM_BAND_900: - if ((bts->c0->arfcn > 124 && bts->c0->arfcn < 955) || - bts->c0->arfcn > 1023) { - LOGP(DNM, LOGL_ERROR, "GSM900 channel must be between 0-124, 955-1023.\n"); - return -EINVAL; - } - break; - case GSM_BAND_850: - if (bts->c0->arfcn < 128 || bts->c0->arfcn > 251) { - LOGP(DNM, LOGL_ERROR, "GSM850 channel must be between 128-251.\n"); - return -EINVAL; - } - break; - default: - LOGP(DNM, LOGL_ERROR, "Unsupported frequency band.\n"); - return -EINVAL; - } - - /* Control Channel Description is set from vty/config */ - - /* T3212 is set from vty/config */ - - /* Set ccch config by looking at ts config */ - for (n=0, i=0; i<8; i++) - n += bts->c0->ts[i].pchan == GSM_PCHAN_CCCH ? 1 : 0; - - /* Indicate R99 MSC in SI3 */ - bts->si_common.chan_desc.mscr = 1; - - switch (n) { - case 0: - bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C; - /* Limit reserved block to 2 on combined channel according to - 3GPP TS 44.018 Table 10.5.2.11.1 */ - if (bts->si_common.chan_desc.bs_ag_blks_res > 2) { - LOGP(DNM, LOGL_NOTICE, "CCCH is combined with SDCCHs, " - "reducing BS-AG-BLKS-RES value %d -> 2\n", - bts->si_common.chan_desc.bs_ag_blks_res); - bts->si_common.chan_desc.bs_ag_blks_res = 2; - } - break; - case 1: - bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_NC; - break; - case 2: - bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_2_NC; - break; - case 3: - bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_3_NC; - break; - case 4: - bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_4_NC; - break; - default: - LOGP(DNM, LOGL_ERROR, "Unsupported CCCH timeslot configuration\n"); - return -EINVAL; - } - - bts->si_common.cell_options.pwrc = 0; /* PWRC not set */ - - bts->si_common.cell_sel_par.acs = 0; - - bts->si_common.ncc_permitted = 0xff; - - bts->chan_load_samples_idx = 0; - - /* ACC ramping is initialized from vty/config */ - - /* Initialize the BTS state */ - gsm_bts_mo_reset(bts); - - return 0; -} - -int bsc_network_alloc(void) -{ - /* initialize our data structures */ - bsc_gsmnet = bsc_network_init(tall_bsc_ctx); - if (!bsc_gsmnet) - return -ENOMEM; - - return 0; -} - -int bsc_network_configure(const char *config_file) -{ - struct gsm_bts *bts; - int rc; - - rc = vty_read_config_file(config_file, NULL); - if (rc < 0) { - LOGP(DNM, LOGL_FATAL, "Failed to parse the config file: '%s'\n", config_file); - return rc; - } - - /* start telnet after reading config for vty_get_bind_addr() */ - rc = telnet_init_dynif(tall_bsc_ctx, bsc_gsmnet, vty_get_bind_addr(), - OSMO_VTY_PORT_NITB_BSC); - if (rc < 0) - return rc; - - osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL); - osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL); - - llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) { - rc = bootstrap_bts(bts); - if (rc < 0) { - LOGP(DNM, LOGL_FATAL, "Error bootstrapping BTS\n"); - return rc; - } - rc = e1_reconfig_bts(bts); - if (rc < 0) { - LOGP(DNM, LOGL_FATAL, "Error enabling E1 input driver\n"); - return rc; - } - } - - return 0; -} diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am index cc9674396..a459a928b 100644 --- a/src/osmo-bsc/Makefile.am +++ b/src/osmo-bsc/Makefile.am @@ -26,21 +26,65 @@ bin_PROGRAMS = \ $(NULL) osmo_bsc_SOURCES = \ - osmo_bsc_main.c \ - osmo_bsc_vty.c \ + a_reset.c \ + abis_nm.c \ + abis_nm_vty.c \ + abis_om2000.c \ + abis_om2000_vty.c \ + abis_rsl.c \ + acc_ramp.c \ + arfcn_range_encode.c \ + bsc_api.c \ + bsc_ctrl_commands.c \ + bsc_ctrl_lookup.c \ + bsc_dyn_ts.c \ + bsc_init.c \ + bsc_rf_ctrl.c \ + bsc_rll.c \ + bsc_subscr_conn_fsm.c \ + bsc_subscriber.c \ + bsc_vty.c \ + bts_ericsson_rbs2000.c \ + bts_init.c \ + bts_ipaccess_nanobts.c \ + bts_ipaccess_nanobts_omlattr.c \ + bts_nokia_site.c \ + bts_siemens_bs11.c \ + bts_sysmobts.c \ + bts_unknown.c \ + chan_alloc.c \ + e1_config.c \ + gsm_04_08_utils.c \ + gsm_04_80_utils.c \ + gsm_data.c \ + handover_cfg.c \ + handover_decision.c \ + handover_decision_2.c \ + handover_logic.c \ + handover_vty.c \ + meas_feed.c \ + meas_rep.c \ + net_init.c \ osmo_bsc_api.c \ + osmo_bsc_audio.c \ + osmo_bsc_bssap.c \ + osmo_bsc_ctrl.c \ + osmo_bsc_filter.c \ osmo_bsc_grace.c \ + osmo_bsc_lcls.c \ + osmo_bsc_main.c \ osmo_bsc_msc.c \ osmo_bsc_sigtran.c \ - osmo_bsc_filter.c \ - osmo_bsc_bssap.c \ - osmo_bsc_audio.c \ - osmo_bsc_ctrl.c \ + osmo_bsc_vty.c \ + paging.c \ + pcu_sock.c \ + penalty_timers.c \ + rest_octets.c \ + system_information.c \ $(NULL) osmo_bsc_LDADD = \ $(top_builddir)/src/libfilter/libfilter.a \ - $(top_builddir)/src/libbsc/libbsc.a \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOVTY_LIBS) \ diff --git a/src/libbsc/a_reset.c b/src/osmo-bsc/a_reset.c index b8f8c8cbd..b8f8c8cbd 100644 --- a/src/libbsc/a_reset.c +++ b/src/osmo-bsc/a_reset.c diff --git a/src/osmo-bsc/abis_bs11.c b/src/osmo-bsc/abis_bs11.c new file mode 100644 index 000000000..8b721fa77 --- /dev/null +++ b/src/osmo-bsc/abis_bs11.c @@ -0,0 +1,21 @@ +/* Siemens BS11 specific Abis implementations */ + +/* (C) 2008-2018 by Harald Welte <laforge@gnumonks.org> + * + * 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/>. + * + */ + diff --git a/src/libbsc/abis_nm.c b/src/osmo-bsc/abis_nm.c index ea94d3766..9dc1f62cb 100644 --- a/src/libbsc/abis_nm.c +++ b/src/osmo-bsc/abis_nm.c @@ -164,13 +164,6 @@ static int abis_nm_sendmsg_direct(struct gsm_bts *bts, struct msgb *msg) static int abis_nm_rcvmsg_sw(struct msgb *mb); -bool nm_is_running(const struct gsm_nm_state *s) { - return (s->operational == NM_OPSTATE_ENABLED) && ( - (s->availability == NM_AVSTATE_OK) || - (s->availability == 0xff) - ); -} - /* Update the administrative state of a given object in our in-memory data * structures and send an event to the higher layer */ static int update_admstate(struct gsm_bts *bts, uint8_t obj_class, diff --git a/src/libbsc/abis_nm_ipaccess.c b/src/osmo-bsc/abis_nm_ipaccess.c index b8225383a..964b92e26 100644 --- a/src/libbsc/abis_nm_ipaccess.c +++ b/src/osmo-bsc/abis_nm_ipaccess.c @@ -20,6 +20,8 @@ * */ +#include <stdint.h> + /* A list of all the 'embedded' attributes of ip.access */ enum ipa_embedded_att { IPA_ATT_ARFCN_WHITELIST = 0x01, diff --git a/src/libbsc/abis_nm_vty.c b/src/osmo-bsc/abis_nm_vty.c index 3019eb828..3019eb828 100644 --- a/src/libbsc/abis_nm_vty.c +++ b/src/osmo-bsc/abis_nm_vty.c diff --git a/src/libbsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index d533ea198..d533ea198 100644 --- a/src/libbsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c diff --git a/src/libbsc/abis_om2000_vty.c b/src/osmo-bsc/abis_om2000_vty.c index faf39c106..faf39c106 100644 --- a/src/libbsc/abis_om2000_vty.c +++ b/src/osmo-bsc/abis_om2000_vty.c diff --git a/src/libbsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c index 48cc39f87..7bbde47d7 100644 --- a/src/libbsc/abis_rsl.c +++ b/src/osmo-bsc/abis_rsl.c @@ -3033,38 +3033,8 @@ int rsl_direct_rf_release(struct gsm_lchan *lchan) } /* Initial timeslot actions when a timeslot first comes into operation. */ -static bool gsm_ts_init(struct gsm_bts_trx_ts *ts) +bool on_gsm_ts_init(struct gsm_bts_trx_ts *ts) { dyn_ts_init(ts); return true; } - -/* Trigger initial timeslot actions iff both OML and RSL are setup. */ -void gsm_ts_check_init(struct gsm_bts_trx_ts *ts) -{ - struct gsm_bts *bts = ts->trx->bts; - if (bts->model->oml_is_ts_ready - && !bts->model->oml_is_ts_ready(ts)) - return; - if (!ts->trx->rsl_link) - return; - if (ts->initialized) - return; - ts->initialized = gsm_ts_init(ts); -} - -void gsm_trx_mark_all_ts_uninitialized(struct gsm_bts_trx *trx) -{ - int i; - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { - struct gsm_bts_trx_ts *ts = &trx->ts[i]; - ts->initialized = false; - } -} - -void gsm_bts_mark_all_ts_uninitialized(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - llist_for_each_entry(trx, &bts->trx_list, list) - gsm_trx_mark_all_ts_uninitialized(trx); -} diff --git a/src/libbsc/acc_ramp.c b/src/osmo-bsc/acc_ramp.c index ac9f02da1..ac9f02da1 100644 --- a/src/libbsc/acc_ramp.c +++ b/src/osmo-bsc/acc_ramp.c diff --git a/src/libbsc/arfcn_range_encode.c b/src/osmo-bsc/arfcn_range_encode.c index 84f9f635f..84f9f635f 100644 --- a/src/libbsc/arfcn_range_encode.c +++ b/src/osmo-bsc/arfcn_range_encode.c diff --git a/src/libbsc/bsc_api.c b/src/osmo-bsc/bsc_api.c index 8ae781e96..8ae781e96 100644 --- a/src/libbsc/bsc_api.c +++ b/src/osmo-bsc/bsc_api.c diff --git a/src/libbsc/bsc_ctrl_commands.c b/src/osmo-bsc/bsc_ctrl_commands.c index 171feaff0..171feaff0 100644 --- a/src/libbsc/bsc_ctrl_commands.c +++ b/src/osmo-bsc/bsc_ctrl_commands.c diff --git a/src/libbsc/bsc_ctrl_lookup.c b/src/osmo-bsc/bsc_ctrl_lookup.c index 38d1ba4ea..38d1ba4ea 100644 --- a/src/libbsc/bsc_ctrl_lookup.c +++ b/src/osmo-bsc/bsc_ctrl_lookup.c diff --git a/src/libbsc/bsc_dyn_ts.c b/src/osmo-bsc/bsc_dyn_ts.c index ed7caed7f..ed7caed7f 100644 --- a/src/libbsc/bsc_dyn_ts.c +++ b/src/osmo-bsc/bsc_dyn_ts.c diff --git a/src/osmo-bsc/bsc_init.c b/src/osmo-bsc/bsc_init.c new file mode 100644 index 000000000..b6bd41025 --- /dev/null +++ b/src/osmo-bsc/bsc_init.c @@ -0,0 +1,288 @@ +/* A hackish minimal BSC (+MSC +HLR) implementation */ + +/* (C) 2008-2018 by Harald Welte <laforge@gnumonks.org> + * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> + * 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/bsc/gsm_data.h> +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/bsc/abis_rsl.h> +#include <osmocom/bsc/debug.h> +#include <osmocom/bsc/misdn.h> +#include <osmocom/bsc/system_information.h> +#include <osmocom/bsc/paging.h> +#include <osmocom/bsc/signal.h> +#include <osmocom/bsc/chan_alloc.h> +#include <osmocom/core/talloc.h> +#include <osmocom/bsc/ipaccess.h> +#include <osmocom/gsm/sysinfo.h> +#include <osmocom/bsc/pcu_if.h> +#include <osmocom/bsc/bsc_msc_data.h> +#include <osmocom/bsc/handover_cfg.h> +#include <osmocom/bsc/gsm_04_08_utils.h> + +#include <time.h> +#include <limits.h> +#include <stdbool.h> + +int bsc_shutdown_net(struct gsm_network *net) +{ + struct gsm_bts *bts; + + llist_for_each_entry(bts, &net->bts_list, list) { + LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr); + osmo_signal_dispatch(SS_L_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts); + } + + 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; + int rc, j; + + if (si_len) { + DEBUGP(DRR, "SI%s: %s\n", get_value_string(osmo_sitype_strs, i), + osmo_hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN)); + } else + DEBUGP(DRR, "SI%s: OFF\n", get_value_string(osmo_sitype_strs, i)); + + switch (i) { + case SYSINFO_TYPE_5: + case SYSINFO_TYPE_5bis: + case SYSINFO_TYPE_5ter: + case SYSINFO_TYPE_6: + rc = rsl_sacch_filling(trx, osmo_sitype2rsl(i), + si_len ? GSM_BTS_SI(bts, i) : NULL, si_len); + break; + case SYSINFO_TYPE_2quater: + if (si_len == 0) { + rc = rsl_bcch_info(trx, i, NULL, 0); + break; + } + rc = 0; + for (j = 0; j <= bts->si2q_count; j++) + rc = rsl_bcch_info(trx, i, (const uint8_t *)GSM_BTS_SI2Q(bts, j), GSM_MACBLOCK_LEN); + break; + default: + rc = rsl_bcch_info(trx, i, si_len ? GSM_BTS_SI(bts, i) : NULL, si_len); + break; + } + + return rc; +} + +/* set all system information types for a TRX */ +int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) +{ + int i, rc; + struct gsm_bts *bts = trx->bts; + uint8_t gen_si[_MAX_SYSINFO_TYPE], n_si = 0, n; + int si_len[_MAX_SYSINFO_TYPE]; + + bts->si_common.cell_sel_par.ms_txpwr_max_ccch = + ms_pwr_ctl_lvl(bts->band, bts->ms_max_power); + bts->si_common.cell_sel_par.neci = bts->network->neci; + + /* Zero/forget the state of the dynamically computed SIs, leeping the static ones */ + bts->si_valid = bts->si_mode_static; + + /* First, we determine which of the SI messages we actually need */ + + if (trx == bts->c0) { + /* 1...4 are always present on a C0 TRX */ + gen_si[n_si++] = SYSINFO_TYPE_1; + gen_si[n_si++] = SYSINFO_TYPE_2; + gen_si[n_si++] = SYSINFO_TYPE_2bis; + gen_si[n_si++] = SYSINFO_TYPE_2ter; + gen_si[n_si++] = SYSINFO_TYPE_2quater; + gen_si[n_si++] = SYSINFO_TYPE_3; + gen_si[n_si++] = SYSINFO_TYPE_4; + + /* 13 is always present on a C0 TRX of a GPRS BTS */ + if (bts->gprs.mode != BTS_GPRS_NONE) + gen_si[n_si++] = SYSINFO_TYPE_13; + } + + /* 5 and 6 are always present on every TRX */ + gen_si[n_si++] = SYSINFO_TYPE_5; + gen_si[n_si++] = SYSINFO_TYPE_5bis; + gen_si[n_si++] = SYSINFO_TYPE_5ter; + gen_si[n_si++] = SYSINFO_TYPE_6; + + /* Second, we generate the selected SI via RSL */ + + for (n = 0; n < n_si; n++) { + i = gen_si[n]; + /* Only generate SI if this SI is not in "static" (user-defined) mode */ + if (!(bts->si_mode_static & (1 << i))) { + /* Set SI as being valid. gsm_generate_si() might unset + * it, if SI is not required. */ + bts->si_valid |= (1 << i); + rc = gsm_generate_si(bts, i); + if (rc < 0) + goto err_out; + si_len[i] = rc; + } else { + if (i == SYSINFO_TYPE_5 || i == SYSINFO_TYPE_5bis + || i == SYSINFO_TYPE_5ter) + si_len[i] = 18; + else if (i == SYSINFO_TYPE_6) + si_len[i] = 11; + else + si_len[i] = 23; + } + } + + /* Third, we send the selected SI via RSL */ + + for (n = 0; n < n_si; n++) { + i = gen_si[n]; + /* if we don't currently have this SI, we send a zero-length + * RSL BCCH FILLING / SACCH FILLING * in order to deactivate + * the SI, in case it might have previously been active */ + if (!GSM_BTS_HAS_SI(bts, i)) + rc = rsl_si(trx, i, 0); + else + rc = rsl_si(trx, i, si_len[i]); + if (rc < 0) + return rc; + } + + /* Make sure the PCU is aware (in case anything GPRS related has + * changed in SI */ + pcu_info_update(bts); + + return 0; +err_out: + LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u: error <%s>, " + "most likely a problem with neighbor cell list generation\n", + get_value_string(osmo_sitype_strs, i), bts->nr, strerror(-rc)); + return rc; +} + +/* set all system information types for a BTS */ +int gsm_bts_set_system_infos(struct gsm_bts *bts) +{ + struct gsm_bts_trx *trx; + + /* Generate a new ID */ + bts->bcch_change_mark += 1; + bts->bcch_change_mark %= 0x7; + + llist_for_each_entry(trx, &bts->trx_list, list) { + int rc; + + rc = gsm_bts_trx_set_system_infos(trx); + if (rc != 0) + return rc; + } + + return 0; +} + +/* XXX hard-coded for now */ +#define T3122_CHAN_LOAD_SAMPLE_INTERVAL 1 /* in seconds */ + +static void update_t3122_chan_load_timer(void *data) +{ + struct gsm_network *net = data; + struct gsm_bts *bts; + + llist_for_each_entry(bts, &net->bts_list, list) + bts_update_t3122_chan_load(bts); + + /* Keep this timer ticking. */ + osmo_timer_schedule(&net->t3122_chan_load_timer, T3122_CHAN_LOAD_SAMPLE_INTERVAL, 0); +} + +static struct gsm_network *bsc_network_init(void *ctx) +{ + struct gsm_network *net = gsm_network_init(ctx); + + net->bsc_data = talloc_zero(net, struct osmo_bsc_data); + if (!net->bsc_data) { + talloc_free(net); + return NULL; + } + + /* Init back pointer */ + net->bsc_data->auto_off_timeout = -1; + net->bsc_data->network = net; + INIT_LLIST_HEAD(&net->bsc_data->mscs); + + net->ho = ho_cfg_init(net, NULL); + net->hodec2.congestion_check_interval_s = HO_CFG_CONGESTION_CHECK_DEFAULT; + + /* init statistics */ + net->bsc_ctrs = rate_ctr_group_alloc(net, &bsc_ctrg_desc, 0); + if (!net->bsc_ctrs) { + talloc_free(net); + return NULL; + } + + gsm_net_update_ctype(net); + + /* + * At present all BTS in the network share one channel load timeout. + * If this becomes a problem for networks with a lot of BTS, this + * code could be refactored to run the timeout individually per BTS. + */ + osmo_timer_setup(&net->t3122_chan_load_timer, update_t3122_chan_load_timer, net); + osmo_timer_schedule(&net->t3122_chan_load_timer, T3122_CHAN_LOAD_SAMPLE_INTERVAL, 0); + + return net; +} + +int bsc_network_alloc(void) +{ + /* initialize our data structures */ + bsc_gsmnet = bsc_network_init(tall_bsc_ctx); + if (!bsc_gsmnet) + return -ENOMEM; + + return 0; +} + +struct gsm_bts *bsc_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type, uint8_t bsic) +{ + struct gsm_bts *bts = gsm_bts_alloc_register(net, type, bsic); + + bts->ho = ho_cfg_init(bts, net->ho); + + return bts; +} diff --git a/src/libbsc/bsc_rf_ctrl.c b/src/osmo-bsc/bsc_rf_ctrl.c index f4a21b53a..f4a21b53a 100644 --- a/src/libbsc/bsc_rf_ctrl.c +++ b/src/osmo-bsc/bsc_rf_ctrl.c diff --git a/src/libbsc/bsc_rll.c b/src/osmo-bsc/bsc_rll.c index ebf9b8856..ebf9b8856 100644 --- a/src/libbsc/bsc_rll.c +++ b/src/osmo-bsc/bsc_rll.c diff --git a/src/libbsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c index bafe14589..bafe14589 100644 --- a/src/libbsc/bsc_subscr_conn_fsm.c +++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c diff --git a/src/libbsc/bsc_subscriber.c b/src/osmo-bsc/bsc_subscriber.c index d9d90baa9..d9d90baa9 100644 --- a/src/libbsc/bsc_subscriber.c +++ b/src/osmo-bsc/bsc_subscriber.c diff --git a/src/libbsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c index 757a8a1cf..5d0feb663 100644 --- a/src/libbsc/bsc_vty.c +++ b/src/osmo-bsc/bsc_vty.c @@ -1945,7 +1945,7 @@ DEFUN(cfg_bts, return CMD_WARNING; } else if (bts_nr == gsmnet->num_bts) { /* allocate a new one */ - bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_UNKNOWN, + bts = bsc_bts_alloc_register(gsmnet, GSM_BTS_TYPE_UNKNOWN, HARDCODED_BSIC); /* * Initalize bts->acc_ramp here. Else we could segfault while diff --git a/src/libbsc/bts_ericsson_rbs2000.c b/src/osmo-bsc/bts_ericsson_rbs2000.c index 9c8b90ee2..9c8b90ee2 100644 --- a/src/libbsc/bts_ericsson_rbs2000.c +++ b/src/osmo-bsc/bts_ericsson_rbs2000.c diff --git a/src/libbsc/bts_init.c b/src/osmo-bsc/bts_init.c index 18f1ed4c8..18f1ed4c8 100644 --- a/src/libbsc/bts_init.c +++ b/src/osmo-bsc/bts_init.c diff --git a/src/libbsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c index 843f264ae..843f264ae 100644 --- a/src/libbsc/bts_ipaccess_nanobts.c +++ b/src/osmo-bsc/bts_ipaccess_nanobts.c diff --git a/src/libbsc/bts_ipaccess_nanobts_omlattr.c b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c index 1a8d9b07b..1a8d9b07b 100644 --- a/src/libbsc/bts_ipaccess_nanobts_omlattr.c +++ b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c diff --git a/src/libbsc/bts_nokia_site.c b/src/osmo-bsc/bts_nokia_site.c index 4a24c3931..4a24c3931 100644 --- a/src/libbsc/bts_nokia_site.c +++ b/src/osmo-bsc/bts_nokia_site.c diff --git a/src/libbsc/bts_siemens_bs11.c b/src/osmo-bsc/bts_siemens_bs11.c index 2d2351702..2d2351702 100644 --- a/src/libbsc/bts_siemens_bs11.c +++ b/src/osmo-bsc/bts_siemens_bs11.c diff --git a/src/libbsc/bts_sysmobts.c b/src/osmo-bsc/bts_sysmobts.c index 91d1118c5..91d1118c5 100644 --- a/src/libbsc/bts_sysmobts.c +++ b/src/osmo-bsc/bts_sysmobts.c diff --git a/src/libbsc/bts_unknown.c b/src/osmo-bsc/bts_unknown.c index 5ecf875c1..5ecf875c1 100644 --- a/src/libbsc/bts_unknown.c +++ b/src/osmo-bsc/bts_unknown.c diff --git a/src/libbsc/chan_alloc.c b/src/osmo-bsc/chan_alloc.c index 4eccff0df..a24fbea94 100644 --- a/src/libbsc/chan_alloc.c +++ b/src/osmo-bsc/chan_alloc.c @@ -65,18 +65,6 @@ bool ts_is_usable(const struct gsm_bts_trx_ts *ts) return true; } -bool trx_is_usable(const struct gsm_bts_trx *trx) -{ - /* FIXME: How does this behave for BS-11 ? */ - if (is_ipaccess_bts(trx->bts)) { - if (!nm_is_running(&trx->mo.nm_state) || - !nm_is_running(&trx->bb_transc.mo.nm_state)) - return false; - } - - return true; -} - static int trx_count_free_ts(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) { struct gsm_bts_trx_ts *ts; diff --git a/src/libbsc/e1_config.c b/src/osmo-bsc/e1_config.c index e7398ed9c..e7398ed9c 100644 --- a/src/libbsc/e1_config.c +++ b/src/osmo-bsc/e1_config.c diff --git a/src/libbsc/gsm_04_08_utils.c b/src/osmo-bsc/gsm_04_08_utils.c index f30640fb1..5bfdf97ff 100644 --- a/src/libbsc/gsm_04_08_utils.c +++ b/src/osmo-bsc/gsm_04_08_utils.c @@ -302,26 +302,6 @@ static void gsm48_cell_desc(struct gsm48_cell_desc *cd, cd->arfcn_lo = bts->c0->arfcn & 0xff; } -void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd, - const struct gsm_lchan *lchan) -{ - uint16_t arfcn = lchan->ts->trx->arfcn & 0x3ff; - - cd->chan_nr = gsm_lchan2chan_nr(lchan); - if (!lchan->ts->hopping.enabled) { - cd->h0.tsc = gsm_ts_tsc(lchan->ts); - cd->h0.h = 0; - cd->h0.arfcn_high = arfcn >> 8; - cd->h0.arfcn_low = arfcn & 0xff; - } else { - cd->h1.tsc = gsm_ts_tsc(lchan->ts); - cd->h1.h = 1; - cd->h1.maio_high = lchan->ts->hopping.maio >> 2; - cd->h1.maio_low = lchan->ts->hopping.maio & 0x03; - cd->h1.hsn = lchan->ts->hopping.hsn; - } -} - /*! \brief Encode a TS 04.08 multirate config LV according to 10.5.2.21aa * \param[out] lv caller-allocated buffer of 7 bytes. First octet is IS length * \param[in] mr multi-rate configuration to encode diff --git a/src/libbsc/gsm_04_80_utils.c b/src/osmo-bsc/gsm_04_80_utils.c index d67f3c568..d67f3c568 100644 --- a/src/libbsc/gsm_04_80_utils.c +++ b/src/osmo-bsc/gsm_04_80_utils.c diff --git a/src/libbsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index ea2aea064..0f062d25a 100644 --- a/src/libbsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -648,6 +648,10 @@ static const struct gprs_rlc_cfg rlc_cfg_default = { .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); @@ -716,8 +720,6 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num) bts->bcch_change_mark = 1; bts->chan_load_avg = 0; - bts->ho = ho_cfg_init(bts, net->ho); - /* timer overrides */ bts->T3122 = 0; /* not overriden by default */ @@ -1232,3 +1234,72 @@ bool ts_is_tch(struct gsm_bts_trx_ts *ts) { return pchan_is_tch(ts_pchan(ts)); } + +bool trx_is_usable(const struct gsm_bts_trx *trx) +{ + /* FIXME: How does this behave for BS-11 ? */ + if (is_ipaccess_bts(trx->bts)) { + if (!nm_is_running(&trx->mo.nm_state) || + !nm_is_running(&trx->bb_transc.mo.nm_state)) + return false; + } + + return true; +} + +void gsm_trx_mark_all_ts_uninitialized(struct gsm_bts_trx *trx) +{ + int i; + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + ts->initialized = false; + } +} + +void gsm_bts_mark_all_ts_uninitialized(struct gsm_bts *bts) +{ + struct gsm_bts_trx *trx; + llist_for_each_entry(trx, &bts->trx_list, list) + gsm_trx_mark_all_ts_uninitialized(trx); +} + +/* Trigger initial timeslot actions iff both OML and RSL are setup. */ +void gsm_ts_check_init(struct gsm_bts_trx_ts *ts) +{ + struct gsm_bts *bts = ts->trx->bts; + if (bts->model->oml_is_ts_ready + && !bts->model->oml_is_ts_ready(ts)) + return; + if (!ts->trx->rsl_link) + return; + if (ts->initialized) + return; + ts->initialized = on_gsm_ts_init(ts); +} + +void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd, + const struct gsm_lchan *lchan) +{ + uint16_t arfcn = lchan->ts->trx->arfcn & 0x3ff; + + cd->chan_nr = gsm_lchan2chan_nr(lchan); + if (!lchan->ts->hopping.enabled) { + cd->h0.tsc = gsm_ts_tsc(lchan->ts); + cd->h0.h = 0; + cd->h0.arfcn_high = arfcn >> 8; + cd->h0.arfcn_low = arfcn & 0xff; + } else { + cd->h1.tsc = gsm_ts_tsc(lchan->ts); + cd->h1.h = 1; + cd->h1.maio_high = lchan->ts->hopping.maio >> 2; + cd->h1.maio_low = lchan->ts->hopping.maio & 0x03; + cd->h1.hsn = lchan->ts->hopping.hsn; + } +} + +bool nm_is_running(const struct gsm_nm_state *s) { + return (s->operational == NM_OPSTATE_ENABLED) && ( + (s->availability == NM_AVSTATE_OK) || + (s->availability == 0xff) + ); +} diff --git a/src/libbsc/handover_cfg.c b/src/osmo-bsc/handover_cfg.c index 14f5d8e84..14f5d8e84 100644 --- a/src/libbsc/handover_cfg.c +++ b/src/osmo-bsc/handover_cfg.c diff --git a/src/libbsc/handover_decision.c b/src/osmo-bsc/handover_decision.c index 887c2993f..887c2993f 100644 --- a/src/libbsc/handover_decision.c +++ b/src/osmo-bsc/handover_decision.c diff --git a/src/libbsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c index 7ac54df95..7ac54df95 100644 --- a/src/libbsc/handover_decision_2.c +++ b/src/osmo-bsc/handover_decision_2.c diff --git a/src/libbsc/handover_logic.c b/src/osmo-bsc/handover_logic.c index 960bf6993..960bf6993 100644 --- a/src/libbsc/handover_logic.c +++ b/src/osmo-bsc/handover_logic.c diff --git a/src/libbsc/handover_vty.c b/src/osmo-bsc/handover_vty.c index 51e448e03..51e448e03 100644 --- a/src/libbsc/handover_vty.c +++ b/src/osmo-bsc/handover_vty.c diff --git a/src/libbsc/meas_feed.c b/src/osmo-bsc/meas_feed.c index 2e80754d4..2e80754d4 100644 --- a/src/libbsc/meas_feed.c +++ b/src/osmo-bsc/meas_feed.c diff --git a/src/libbsc/meas_rep.c b/src/osmo-bsc/meas_rep.c index 73d9a1f21..73d9a1f21 100644 --- a/src/libbsc/meas_rep.c +++ b/src/osmo-bsc/meas_rep.c diff --git a/src/libbsc/net_init.c b/src/osmo-bsc/net_init.c index f03a2e12f..db84e2a53 100644 --- a/src/libbsc/net_init.c +++ b/src/osmo-bsc/net_init.c @@ -22,28 +22,13 @@ #include <osmocom/bsc/gsm_04_08_utils.h> #include <osmocom/bsc/handover_cfg.h> #include <osmocom/bsc/chan_alloc.h> -#include <osmocom/bsc/common_bsc.h> -/* XXX hard-coded for now */ -#define T3122_CHAN_LOAD_SAMPLE_INTERVAL 1 /* in seconds */ - -static void update_t3122_chan_load_timer(void *data) -{ - struct gsm_network *net = data; - struct gsm_bts *bts; - - llist_for_each_entry(bts, &net->bts_list, list) - bts_update_t3122_chan_load(bts); - - /* Keep this timer ticking. */ - osmo_timer_schedule(&net->t3122_chan_load_timer, T3122_CHAN_LOAD_SAMPLE_INTERVAL, 0); -} - -struct gsm_network *bsc_network_init(void *ctx) +/* Initialize the bare minimum of struct gsm_network, minimizing required 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_network_init()). */ +struct gsm_network *gsm_network_init(void *ctx) { - struct gsm_network *net; - - net = talloc_zero(ctx, struct gsm_network); + struct gsm_network *net = talloc_zero(ctx, struct gsm_network); if (!net) return NULL; @@ -65,17 +50,7 @@ struct gsm_network *bsc_network_init(void *ctx) net->bsc_subscribers = talloc_zero(net, struct llist_head); INIT_LLIST_HEAD(net->bsc_subscribers); - net->bsc_data = talloc_zero(net, struct osmo_bsc_data); - if (!net->bsc_data) { - talloc_free(net); - return NULL; - } - - /* Init back pointer */ - net->bsc_data->auto_off_timeout = -1; - net->bsc_data->network = net; - INIT_LLIST_HEAD(&net->bsc_data->mscs); - + INIT_LLIST_HEAD(&net->bts_list); net->num_bts = 0; net->T3101 = GSM_T3101_DEFAULT; net->T3103 = GSM_T3103_DEFAULT; @@ -90,28 +65,5 @@ struct gsm_network *bsc_network_init(void *ctx) net->T3122 = GSM_T3122_DEFAULT; net->T3141 = GSM_T3141_DEFAULT; - net->ho = ho_cfg_init(net, NULL); - net->hodec2.congestion_check_interval_s = HO_CFG_CONGESTION_CHECK_DEFAULT; - - INIT_LLIST_HEAD(&net->bts_list); - - /* - * At present all BTS in the network share one channel load timeout. - * If this becomes a problem for networks with a lot of BTS, this - * code could be refactored to run the timeout individually per BTS. - */ - osmo_timer_setup(&net->t3122_chan_load_timer, update_t3122_chan_load_timer, net); - osmo_timer_schedule(&net->t3122_chan_load_timer, T3122_CHAN_LOAD_SAMPLE_INTERVAL, 0); - - /* init statistics */ - net->bsc_ctrs = rate_ctr_group_alloc(net, &bsc_ctrg_desc, 0); - if (!net->bsc_ctrs) { - talloc_free(net); - return NULL; - } - - gsm_net_update_ctype(net); - return net; } - diff --git a/src/libbsc/osmo_bsc_lcls.c b/src/osmo-bsc/osmo_bsc_lcls.c index c2b076090..c2b076090 100644 --- a/src/libbsc/osmo_bsc_lcls.c +++ b/src/osmo-bsc/osmo_bsc_lcls.c diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c index fefc04180..5c6a872b4 100644 --- a/src/osmo-bsc/osmo_bsc_main.c +++ b/src/osmo-bsc/osmo_bsc_main.c @@ -42,9 +42,15 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/stats.h> #include <osmocom/gsm/protocol/gsm_12_21.h> +#include <osmocom/vty/telnet_interface.h> +#include <osmocom/vty/ports.h> #include <osmocom/abis/abis.h> #include <osmocom/bsc/abis_om2000.h> +#include <osmocom/bsc/abis_nm.h> +#include <osmocom/bsc/abis_rsl.h> +#include <osmocom/bsc/chan_alloc.h> +#include <osmocom/bsc/e1_config.h> #include <osmocom/mgcp_client/mgcp_client.h> @@ -147,6 +153,369 @@ static void handle_options(int argc, char **argv) } } +/* Callback function for NACK on the OML NM */ +static int oml_msg_nack(struct nm_nack_signal_data *nack) +{ + if (nack->mt == NM_MT_GET_ATTR_NACK) { + LOGP(DNM, LOGL_ERROR, "BTS%u does not support Get Attributes " + "OML message.\n", nack->bts->nr); + return 0; + } + + if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) + LOGP(DNM, LOGL_ERROR, "Failed to set BTS attributes. That is fatal. " + "Was the bts type and frequency properly specified?\n"); + else + LOGP(DNM, LOGL_ERROR, "Got %s NACK going to drop the OML links.\n", + abis_nm_nack_name(nack->mt)); + + if (!nack->bts) { + LOGP(DNM, LOGL_ERROR, "Unknown bts. Can not drop it.\n"); + return 0; + } + + if (is_ipaccess_bts(nack->bts)) + ipaccess_drop_oml(nack->bts); + + return 0; +} + +/* Callback function to be called every time we receive a signal from NM */ +static int nm_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct nm_nack_signal_data *nack; + + switch (signal) { + case S_NM_NACK: + nack = signal_data; + return oml_msg_nack(nack); + default: + break; + } + return 0; +} + +/* Produce a MA as specified in 10.5.2.21 */ +static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts) +{ + /* we have three bitvecs: the per-timeslot ARFCNs, the cell chan ARFCNs + * and the MA */ + struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc; + struct bitvec *ts_arfcn = &ts->hopping.arfcns; + struct bitvec *ma = &ts->hopping.ma; + unsigned int num_cell_arfcns, bitnum, n_chan; + int i; + + /* re-set the MA to all-zero */ + ma->cur_bit = 0; + ts->hopping.ma_len = 0; + memset(ma->data, 0, ma->data_len); + + if (!ts->hopping.enabled) + return 0; + + /* count the number of ARFCNs in the cell channel allocation */ + num_cell_arfcns = 0; + for (i = 0; i < 1024; i++) { + if (bitvec_get_bit_pos(cell_chan, i)) + num_cell_arfcns++; + } + + /* pad it to octet-aligned number of bits */ + ts->hopping.ma_len = num_cell_arfcns / 8; + if (num_cell_arfcns % 8) + ts->hopping.ma_len++; + + n_chan = 0; + for (i = 0; i < 1024; i++) { + if (!bitvec_get_bit_pos(cell_chan, i)) + continue; + /* set the corresponding bit in the MA */ + bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan; + if (bitvec_get_bit_pos(ts_arfcn, i)) + bitvec_set_bit_pos(ma, bitnum, 1); + else + bitvec_set_bit_pos(ma, bitnum, 0); + n_chan++; + } + + /* ARFCN 0 is special: It is coded last in the bitmask */ + if (bitvec_get_bit_pos(cell_chan, 0)) { + n_chan++; + /* set the corresponding bit in the MA */ + bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan; + if (bitvec_get_bit_pos(ts_arfcn, 0)) + bitvec_set_bit_pos(ma, bitnum, 1); + else + bitvec_set_bit_pos(ma, bitnum, 0); + } + + return 0; +} + +static void bootstrap_rsl(struct gsm_bts_trx *trx) +{ + unsigned int i; + + LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) " + "on ARFCN %u using MCC-MNC %s LAC=%u CID=%u BSIC=%u\n", + trx->bts->nr, trx->nr, trx->arfcn, + osmo_plmn_name(&bsc_gsmnet->plmn), + trx->bts->location_area_code, + trx->bts->cell_identity, trx->bts->bsic); + + if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) { + rsl_nokia_si_begin(trx); + } + + /* + * Trigger ACC ramping before sending system information to BTS. + * This ensures that RACH control in system information is configured correctly. + * TRX 0 should be usable and unlocked, otherwise starting ACC ramping is pointless. + */ + if (trx_is_usable(trx) && trx->mo.nm_state.administrative == NM_STATE_UNLOCKED) + acc_ramp_trigger(&trx->bts->acc_ramp); + + gsm_bts_trx_set_system_infos(trx); + + if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) { + /* channel unspecific, power reduction in 2 dB steps */ + rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2); + rsl_nokia_si_end(trx); + } + + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + generate_ma_for_ts(ts); + gsm_ts_check_init(ts); + } +} + +/* Callback function to be called every time we receive a signal from INPUT */ +static int inp_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct input_signal_data *isd = signal_data; + struct gsm_bts_trx *trx = isd->trx; + int ts_no, lchan_no; + /* N. B: we rely on attribute order when parsing response in abis_nm_rx_get_attr_resp() */ + const uint8_t bts_attr[] = { NM_ATT_MANUF_ID, NM_ATT_SW_CONFIG, }; + const uint8_t trx_attr[] = { NM_ATT_MANUF_STATE, NM_ATT_SW_CONFIG, }; + + /* we should not request more attributes than we're ready to handle */ + OSMO_ASSERT(sizeof(bts_attr) < MAX_BTS_ATTR); + OSMO_ASSERT(sizeof(trx_attr) < MAX_BTS_ATTR); + + if (subsys != SS_L_INPUT) + return -EINVAL; + + LOGP(DLMI, LOGL_DEBUG, "%s(): Input signal '%s' received\n", __func__, + get_value_string(e1inp_signal_names, signal)); + switch (signal) { + case S_L_INP_TEI_UP: + if (isd->link_type == E1INP_SIGN_OML) { + /* TODO: this is required for the Nokia BTS, hopping is configured + during OML, other MA is not set. */ + struct gsm_bts_trx *cur_trx; + /* was static in system_information.c */ + extern int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts); + uint8_t ca[20]; + /* has to be called before generate_ma_for_ts to + set bts->si_common.cell_alloc */ + generate_cell_chan_list(ca, trx->bts); + + /* Request generic BTS-level attributes */ + abis_nm_get_attr(trx->bts, NM_OC_BTS, 0xFF, 0xFF, 0xFF, bts_attr, sizeof(bts_attr)); + + llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) { + int i; + /* Request TRX-level attributes */ + abis_nm_get_attr(cur_trx->bts, NM_OC_BASEB_TRANSC, 0, cur_trx->nr, 0xFF, + trx_attr, sizeof(trx_attr)); + for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++) + generate_ma_for_ts(&cur_trx->ts[i]); + } + } + if (isd->link_type == E1INP_SIGN_RSL) + bootstrap_rsl(trx); + break; + case S_L_INP_TEI_DN: + LOGP(DLMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", isd->link_type, trx); + + if (isd->link_type == E1INP_SIGN_OML) + rate_ctr_inc(&trx->bts->bts_ctrs->ctr[BTS_CTR_BTS_OML_FAIL]); + else if (isd->link_type == E1INP_SIGN_RSL) { + rate_ctr_inc(&trx->bts->bts_ctrs->ctr[BTS_CTR_BTS_RSL_FAIL]); + acc_ramp_abort(&trx->bts->acc_ramp); + } + + /* + * free all allocated channels. change the nm_state so the + * trx and trx_ts becomes unusable and chan_alloc.c can not + * allocate from it. + */ + for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) { + struct gsm_bts_trx_ts *ts = &trx->ts[ts_no]; + + for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) { + if (ts->lchan[lchan_no].state != LCHAN_S_NONE) + lchan_free(&ts->lchan[lchan_no]); + lchan_reset(&ts->lchan[lchan_no]); + } + } + + gsm_bts_mo_reset(trx->bts); + + abis_nm_clear_queue(trx->bts); + break; + default: + break; + } + + return 0; +} + +static int bootstrap_bts(struct gsm_bts *bts) +{ + int i, n; + + if (!bts->model) + return -EFAULT; + + if (bts->model->start && !bts->model->started) { + int ret = bts->model->start(bts->network); + if (ret < 0) + return ret; + + bts->model->started = true; + } + + /* FIXME: What about secondary TRX of a BTS? What about a BTS that has TRX + * in different bands? Why is 'band' a parameter of the BTS and not of the TRX? */ + switch (bts->band) { + case GSM_BAND_1800: + if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) { + LOGP(DNM, LOGL_ERROR, "GSM1800 channel must be between 512-885.\n"); + return -EINVAL; + } + break; + case GSM_BAND_1900: + if (bts->c0->arfcn < 512 || bts->c0->arfcn > 810) { + LOGP(DNM, LOGL_ERROR, "GSM1900 channel must be between 512-810.\n"); + return -EINVAL; + } + break; + case GSM_BAND_900: + if ((bts->c0->arfcn > 124 && bts->c0->arfcn < 955) || + bts->c0->arfcn > 1023) { + LOGP(DNM, LOGL_ERROR, "GSM900 channel must be between 0-124, 955-1023.\n"); + return -EINVAL; + } + break; + case GSM_BAND_850: + if (bts->c0->arfcn < 128 || bts->c0->arfcn > 251) { + LOGP(DNM, LOGL_ERROR, "GSM850 channel must be between 128-251.\n"); + return -EINVAL; + } + break; + default: + LOGP(DNM, LOGL_ERROR, "Unsupported frequency band.\n"); + return -EINVAL; + } + + /* Control Channel Description is set from vty/config */ + + /* T3212 is set from vty/config */ + + /* Set ccch config by looking at ts config */ + for (n=0, i=0; i<8; i++) + n += bts->c0->ts[i].pchan == GSM_PCHAN_CCCH ? 1 : 0; + + /* Indicate R99 MSC in SI3 */ + bts->si_common.chan_desc.mscr = 1; + + switch (n) { + case 0: + bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C; + /* Limit reserved block to 2 on combined channel according to + 3GPP TS 44.018 Table 10.5.2.11.1 */ + if (bts->si_common.chan_desc.bs_ag_blks_res > 2) { + LOGP(DNM, LOGL_NOTICE, "CCCH is combined with SDCCHs, " + "reducing BS-AG-BLKS-RES value %d -> 2\n", + bts->si_common.chan_desc.bs_ag_blks_res); + bts->si_common.chan_desc.bs_ag_blks_res = 2; + } + break; + case 1: + bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_NC; + break; + case 2: + bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_2_NC; + break; + case 3: + bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_3_NC; + break; + case 4: + bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_4_NC; + break; + default: + LOGP(DNM, LOGL_ERROR, "Unsupported CCCH timeslot configuration\n"); + return -EINVAL; + } + + bts->si_common.cell_options.pwrc = 0; /* PWRC not set */ + + bts->si_common.cell_sel_par.acs = 0; + + bts->si_common.ncc_permitted = 0xff; + + bts->chan_load_samples_idx = 0; + + /* ACC ramping is initialized from vty/config */ + + /* Initialize the BTS state */ + gsm_bts_mo_reset(bts); + + return 0; +} + +static int bsc_network_configure(const char *config_file) +{ + struct gsm_bts *bts; + int rc; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + LOGP(DNM, LOGL_FATAL, "Failed to parse the config file: '%s'\n", config_file); + return rc; + } + + /* start telnet after reading config for vty_get_bind_addr() */ + rc = telnet_init_dynif(tall_bsc_ctx, bsc_gsmnet, vty_get_bind_addr(), + OSMO_VTY_PORT_NITB_BSC); + if (rc < 0) + return rc; + + osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL); + osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL); + + llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) { + rc = bootstrap_bts(bts); + if (rc < 0) { + LOGP(DNM, LOGL_FATAL, "Error bootstrapping BTS\n"); + return rc; + } + rc = e1_reconfig_bts(bts); + if (rc < 0) { + LOGP(DNM, LOGL_FATAL, "Error enabling E1 input driver\n"); + return rc; + } + } + + return 0; +} + static int bsc_vty_go_parent(struct vty *vty) { switch (vty->node) { diff --git a/src/libbsc/paging.c b/src/osmo-bsc/paging.c index d6bff2a42..d6bff2a42 100644 --- a/src/libbsc/paging.c +++ b/src/osmo-bsc/paging.c diff --git a/src/libbsc/pcu_sock.c b/src/osmo-bsc/pcu_sock.c index 64422c724..64422c724 100644 --- a/src/libbsc/pcu_sock.c +++ b/src/osmo-bsc/pcu_sock.c diff --git a/src/libbsc/penalty_timers.c b/src/osmo-bsc/penalty_timers.c index b80fec946..b80fec946 100644 --- a/src/libbsc/penalty_timers.c +++ b/src/osmo-bsc/penalty_timers.c diff --git a/src/libbsc/rest_octets.c b/src/osmo-bsc/rest_octets.c index 9f2b4c0ab..9f2b4c0ab 100644 --- a/src/libbsc/rest_octets.c +++ b/src/osmo-bsc/rest_octets.c diff --git a/src/libbsc/system_information.c b/src/osmo-bsc/system_information.c index d99153f24..d99153f24 100644 --- a/src/libbsc/system_information.c +++ b/src/osmo-bsc/system_information.c diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 6e21ccc78..543344b53 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -46,15 +46,18 @@ endif bs11_config_SOURCES = \ bs11_config.c \ + stubs.c \ $(NULL) bs11_config_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/osmo-bsc/abis_nm.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 \ + $(top_builddir)/src/osmo-bsc/net_init.o \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOABIS_LIBS) \ - $(LIBOSMOSIGTRAN_LIBS) \ - $(LIBOSMOMGCPCLIENT_LIBS) \ $(NULL) isdnsync_SOURCES = \ @@ -114,12 +117,14 @@ osmo_meas_udp2db_CFLAGS = \ meas_json_SOURCES = \ meas_json.c \ + stubs.c \ $(NULL) meas_json_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/osmo-bsc/gsm_data.o \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOABIS_LIBS) \ $(NULL) meas_json_CFLAGS = \ diff --git a/src/utils/bs11_config.c b/src/utils/bs11_config.c index 8d4de0152..ae307c796 100644 --- a/src/utils/bs11_config.c +++ b/src/utils/bs11_config.c @@ -32,7 +32,6 @@ #include <sys/stat.h> -#include <osmocom/bsc/common_bsc.h> #include <osmocom/bsc/abis_nm.h> #include <osmocom/core/msgb.h> #include <osmocom/core/utils.h> @@ -915,7 +914,7 @@ int main(int argc, char **argv) handle_options(argc, argv); bts_model_bs11_init(); - gsmnet = bsc_network_init(tall_bs11cfg_ctx); + gsmnet = gsm_network_init(tall_bs11cfg_ctx); if (!gsmnet) { fprintf(stderr, "Unable to allocate gsm network\n"); exit(1); diff --git a/src/utils/stubs.c b/src/utils/stubs.c new file mode 100644 index 000000000..624797fde --- /dev/null +++ b/src/utils/stubs.c @@ -0,0 +1,36 @@ +/* Stubs required for linking */ + +/* (C) 2018 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 <stdbool.h> +struct gsm_bts_trx_ts; +struct msgb; + +bool on_gsm_ts_init(struct gsm_bts_trx_ts *ts) +{ + /* No TS init required here. */ + return true; +} + +int abis_rsl_rcvmsg(struct msgb *msg) +{ + /* No RSL handling here */ + return 0; +} |