diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index e237ea2a6..89db48b05 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -436,4 +436,9 @@ extern const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1]; int bsc_base_ctrl_cmds_install(void); int msc_ctrl_cmds_install(void); +/* dependency handling */ +void bts_depend_mark(struct gsm_bts *bts, int dep); +void bts_depend_clear(struct gsm_bts *bts, int dep); +int bts_depend_check(struct gsm_bts *bts); + #endif /* _GSM_DATA_H */ diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 001a526bf..5d84969ae 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -720,6 +720,9 @@ struct gsm_bts { /* supported codecs beside FR */ struct bts_codec_conf codec; + + /* BTS dependencies bit field */ + uint32_t depends_on[256/(8*4)]; #endif /* ROLE_BSC */ void *role; }; diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 08f9a8e50..d6d66c638 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -650,6 +650,23 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " %sforce-combined-si%s", bts->force_combined_si ? "" : "no ", VTY_NEWLINE); + for (i = 0; i < ARRAY_SIZE(bts->depends_on); ++i) { + int j; + + if (bts->depends_on[i] == 0) + continue; + + for (j = 0; j < sizeof(bts->depends_on[i]) * 8; ++j) { + int bts_nr; + + if ((bts->depends_on[i] & (1<depends_on[i]) * 8) + j; + vty_out(vty, " depends-on-bts %d%s", bts_nr, VTY_NEWLINE); + } + } + config_write_bts_model(vty, bts); } @@ -2772,6 +2789,50 @@ DEFUN(cfg_bts_codec4, cfg_bts_codec4_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_depends_on, cfg_bts_depends_on_cmd, + "depends-on-bts <0-255>", + "This BTS can only be started if another one is up\n" "BTS Number\n") +{ + struct gsm_bts *bts = vty->index; + struct gsm_bts *other_bts; + int dep = atoi(argv[0]); + + + if (!is_ipaccess_bts(bts)) { + vty_out(vty, "This feature is only available for IP systems.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + other_bts = gsm_bts_num(bts->network, dep); + if (!other_bts || !is_ipaccess_bts(other_bts)) { + vty_out(vty, "This feature is only available for IP systems.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + if (dep >= bts->nr) { + vty_out(vty, "%%Need to depend on an already declared unit.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + bts_depend_mark(bts, dep); + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_no_depends_on, cfg_bts_no_depends_on_cmd, + "depeneds-on-bts <0-255>", + NO_STR "This BTS can only be started if another one is up\n" + "BTS Number\n") +{ + struct gsm_bts *bts = vty->index; + int dep = atoi(argv[0]); + + bts_depend_clear(bts, dep); + return CMD_SUCCESS; +} + #define TRX_TEXT "Radio Transceiver\n" /* per TRX configuration */ @@ -3383,6 +3444,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_codec2_cmd); install_element(BTS_NODE, &cfg_bts_codec3_cmd); install_element(BTS_NODE, &cfg_bts_codec4_cmd); + install_element(BTS_NODE, &cfg_bts_depends_on_cmd); + install_element(BTS_NODE, &cfg_bts_no_depends_on_cmd); install_element(BTS_NODE, &cfg_trx_cmd); install_node(&trx_node, dummy_config_write); diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts.c b/openbsc/src/libbsc/bts_ipaccess_nanobts.c index 9fa03bfe6..825a22e2a 100644 --- a/openbsc/src/libbsc/bts_ipaccess_nanobts.c +++ b/openbsc/src/libbsc/bts_ipaccess_nanobts.c @@ -590,6 +590,13 @@ ipaccess_sign_link_up(void *unit_data, struct e1inp_line *line, /* remove old OML signal link for this BTS. */ ipaccess_drop_oml(bts); + if (!bts_depend_check(bts)) { + LOGP(DLINP, LOGL_NOTICE, + "Dependency not full-filled for %u/%u/%u\n", + dev->site_id, dev->bts_id, dev->trx_id); + return NULL; + } + /* create new OML link. */ sign_link = bts->oml_link = e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML - 1], diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 03e9b85e2..73041fcec 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -364,3 +364,61 @@ int gsm_parse_reg(void *ctx, regex_t *reg, char **str, int argc, const char **ar return ret; } +/* 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); +} + +static 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; +}