From: Holger Hans Peter Freyther <[email protected]>

E.g. for the sysmoBTS2050 we have the requirement that the first
board connects before the second due clocking. The easiest point
to enforce this is the BSC. Add a simple bitmask based system to
allow to express dependencies for IP based systems.
---
 openbsc/include/openbsc/gsm_data.h        |  5 +++
 openbsc/include/openbsc/gsm_data_shared.h |  3 ++
 openbsc/src/libbsc/bsc_vty.c              | 63 +++++++++++++++++++++++++++++++
 openbsc/src/libbsc/bts_ipaccess_nanobts.c |  7 ++++
 openbsc/src/libcommon/gsm_data.c          | 58 ++++++++++++++++++++++++++++
 5 files changed, 136 insertions(+)

diff --git a/openbsc/include/openbsc/gsm_data.h 
b/openbsc/include/openbsc/gsm_data.h
index e237ea2..89db48b 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 001a526..5d84969 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 08f9a8e..d6d66c6 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<<j)) == 0)
+                               continue;
+
+                       bts_nr = (i * sizeof(bts->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 9fa03bf..825a22e 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 03e9b85..73041fc 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;
+}
-- 
2.1.3

Reply via email to