aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2021-06-30 14:49:41 +0200
committerPhilipp Maier <pmaier@sysmocom.de>2021-07-19 10:39:06 +0200
commit6611e7f3059d26794a59135637076fe59cf52dae (patch)
treeb9d79061767a5a4e3ff7fd53f75e1db3de55df6d
parentace4e500edb702d628bb9103190aad6803b610e8 (diff)
allow to configure multiple oml remote-ip addressesHEADmaster
At the moment we can only configure a single BSC in the BTS configuration. This also means that if this single BSC fails for some reason the BTS has no alternate BSC to connect to. Lets extend the remote-ip parameter so that it can be used multiple times so that an operater can configure any number of BSCs that are tried one after another during BTS startup. Change-Id: I205f68a3a7f35fee4c38a7cfba2b014237df2727 Related: SYS#4971
-rw-r--r--include/osmo-bts/abis.h9
-rw-r--r--include/osmo-bts/bts.h9
-rw-r--r--src/common/abis.c277
-rw-r--r--src/common/bts.c1
-rw-r--r--src/common/main.c11
-rw-r--r--src/common/vty.c53
-rw-r--r--src/osmo-bts-omldummy/main.c12
7 files changed, 292 insertions, 80 deletions
diff --git a/include/osmo-bts/abis.h b/include/osmo-bts/abis.h
index 62407ece..8963c3cb 100644
--- a/include/osmo-bts/abis.h
+++ b/include/osmo-bts/abis.h
@@ -16,9 +16,14 @@ enum {
LINK_STATE_CONNECT,
};
+enum abis_link_fsm_event {
+ ABIS_LINK_EV_SIGN_LINK_DOWN,
+ ABIS_LINK_EV_VTY_RM_ADDR,
+};
+
void abis_init(struct gsm_bts *bts);
-struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
- char *model_name);
+int abis_open(struct gsm_bts *bts, char *model_name);
+
int abis_oml_sendmsg(struct msgb *msg);
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 6a61d015..6e0e47b1 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -133,6 +133,12 @@ struct gsm_bts_sm {
struct gsm_abis_mo mo;
};
+/* Struct that holds one OML-Address (Address of the BSC) */
+struct bsc_oml_host {
+ struct llist_head list;
+ char *addr;
+};
+
/* One BTS */
struct gsm_bts {
/* list header in net->bts_list */
@@ -295,7 +301,7 @@ struct gsm_bts {
} etws;
struct paging_state *paging_state;
- char *bsc_oml_host;
+ struct llist_head bsc_oml_hosts;
struct llist_head oml_queue;
unsigned int rtp_jitter_buf_ms;
bool rtp_jitter_adaptive;
@@ -363,6 +369,7 @@ struct gsm_bts {
} gsmtap;
struct osmo_fsm_inst *shutdown_fi; /* FSM instance to manage shutdown procedure during process exit */
+ struct osmo_fsm_inst *abis_link_fi; /* FSM instance to manage abis connection during process startup and link failure */
struct osmo_tdef *T_defs; /* Timer defines */
void *model_priv; /* Allocated by bts_model, contains model specific data pointer */
diff --git a/src/common/abis.c b/src/common/abis.c
index abef8264..3325fabe 100644
--- a/src/common/abis.c
+++ b/src/common/abis.c
@@ -38,11 +38,13 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/signal.h>
#include <osmocom/core/macaddr.h>
+#include <osmocom/core/fsm.h>
#include <osmocom/abis/abis.h>
#include <osmocom/abis/e1_input.h>
#include <osmocom/abis/ipaccess.h>
#include <osmocom/gsm/ipa.h>
+#include <osmo-bts/abis.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/bts.h>
@@ -54,6 +56,204 @@
static struct gsm_bts *g_bts;
+static struct e1inp_line_ops line_ops;
+
+static struct ipaccess_unit bts_dev_info;
+
+#define S(x) (1 << (x))
+
+enum abis_link_fsm_state {
+ ABIS_LINK_ST_CONNECTING,
+ ABIS_LINK_ST_CONNECTED,
+ ABIS_LINK_ST_FAILED,
+};
+
+static const struct value_string abis_link_fsm_event_names[] = {
+ OSMO_VALUE_STRING(ABIS_LINK_EV_SIGN_LINK_DOWN),
+ OSMO_VALUE_STRING(ABIS_LINK_EV_VTY_RM_ADDR),
+ {}
+};
+
+struct abis_link_fsm_priv {
+ struct llist_head *bsc_oml_host;
+ struct gsm_bts *bts;
+ char *model_name;
+ int line_ctr;
+};
+
+static void abis_link_connected(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct abis_link_fsm_priv *priv = fi->priv;
+ struct gsm_bts *bts = priv->bts;
+ struct gsm_bts_trx *trx;
+ bool oml_rsl_was_connected = false;
+
+ OSMO_ASSERT(event == ABIS_LINK_EV_SIGN_LINK_DOWN);
+
+ /* First remove the OML signalling link */
+ if (bts->oml_link) {
+ struct timespec now;
+
+ e1inp_sign_link_destroy(bts->oml_link);
+
+ /* Log a special notice if the OML connection was dropped relatively quickly. */
+ if (bts->oml_conn_established_timestamp.tv_sec != 0 && clock_gettime(CLOCK_MONOTONIC, &now) == 0 &&
+ bts->oml_conn_established_timestamp.tv_sec + OSMO_BTS_OML_CONN_EARLY_DISCONNECT >= now.tv_sec) {
+ LOGP(DABIS, LOGL_FATAL, "OML link was closed early within %" PRIu64 " seconds. "
+ "If this situation persists, please check your BTS and BSC configuration files for errors. "
+ "A common error is a mismatch between unit_id configuration parameters of BTS and BSC.\n",
+ (uint64_t) (now.tv_sec - g_bts->oml_conn_established_timestamp.tv_sec));
+ }
+ bts->oml_link = NULL;
+ oml_rsl_was_connected = true;
+ }
+ memset(&g_bts->oml_conn_established_timestamp, 0, sizeof(bts->oml_conn_established_timestamp));
+
+ if (g_bts->osmo_link) {
+ e1inp_sign_link_destroy(g_bts->osmo_link);
+ g_bts->osmo_link = NULL;
+ oml_rsl_was_connected = true;
+ }
+
+ /* Then iterate over the RSL signalling links */
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ if (trx->rsl_link) {
+ e1inp_sign_link_destroy(trx->rsl_link);
+ trx->rsl_link = NULL;
+ oml_rsl_was_connected = true;
+ }
+ }
+
+ /* Note: if there was an OML or RSL connection present (the BTS was connected to a BSC). Then we will not try
+ * to connect to an alternate BSC. Instead we will shut down the BTS process. This will ensure that all states
+ * in the BTS (hardware and software) are reset properly. It is then up to the process management of the host
+ * to restart osmo-bts. */
+ if (oml_rsl_was_connected)
+ osmo_fsm_inst_state_chg(fi, ABIS_LINK_ST_FAILED, 0, 0);
+ else
+ osmo_fsm_inst_state_chg(fi, ABIS_LINK_ST_CONNECTING, 0, 0);
+}
+
+static void abis_link_connecting_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct e1inp_line *line;
+ struct abis_link_fsm_priv *priv = fi->priv;
+ struct gsm_bts *bts = priv->bts;
+ struct bsc_oml_host *bsc_oml_host;
+
+ if (priv->bsc_oml_host) {
+ /* Get a BSC host from the list and move the list head one position forward. */
+ bsc_oml_host = (struct bsc_oml_host *)priv->bsc_oml_host;
+ if (priv->bsc_oml_host == llist_last(&bts->bsc_oml_hosts))
+ priv->bsc_oml_host = NULL;
+ else
+ priv->bsc_oml_host = priv->bsc_oml_host->next;
+ } else {
+ LOGP(DABIS, LOGL_FATAL, "No BSC available, A-bis connection establishment failed\n");
+ osmo_fsm_inst_state_chg(fi, ABIS_LINK_ST_FAILED, 0, 0);
+ return;
+ }
+
+ LOGP(DABIS, LOGL_NOTICE, "A-bis connection establishment to BSC (%s) in progress...\n", bsc_oml_host->addr);
+
+ /* patch in various data from VTY and other sources */
+ line_ops.cfg.ipa.addr = bsc_oml_host->addr;
+ osmo_get_macaddr(bts_dev_info.mac_addr, "eth0");
+ bts_dev_info.site_id = bts->ip_access.site_id;
+ bts_dev_info.bts_id = bts->ip_access.bts_id;
+ bts_dev_info.unit_name = priv->model_name;
+ if (bts->description)
+ bts_dev_info.unit_name = bts->description;
+ bts_dev_info.location2 = priv->model_name;
+
+ line = e1inp_line_find(priv->line_ctr);
+ if (line) {
+ e1inp_line_get2(line, __FILE__); /* We want a new reference for returned line */
+ } else
+ line = e1inp_line_create(priv->line_ctr, "ipa"); /* already comes with a reference */
+
+ /* The abis connection may fail and we may have to try again with a different BSC (if configured). The next
+ * attempt must happen on a different line. */
+ priv->line_ctr++;
+
+ if (!line) {
+ osmo_fsm_inst_state_chg(fi, ABIS_LINK_ST_FAILED, 0, 0);
+ return;
+ }
+ e1inp_line_bind_ops(line, &line_ops);
+
+ /* This will open the OML connection now */
+ if (e1inp_line_update(line) < 0) {
+ osmo_fsm_inst_state_chg(fi, ABIS_LINK_ST_FAILED, 0, 0);
+ return;
+ }
+
+ /* The TCP connection to the BSC is now in progress. */
+ osmo_fsm_inst_state_chg(fi, ABIS_LINK_ST_CONNECTED, 0, 0);
+}
+
+static void abis_link_failed_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct abis_link_fsm_priv *priv = fi->priv;
+ struct gsm_bts *bts = priv->bts;
+
+ /* None of the configured BSCs was reachable or there was an existing
+ * OML/RSL connection that beoke. Initiate BTS process shut down now. */
+ bts_model_abis_close(bts);
+}
+
+static void abis_link_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct abis_link_fsm_priv *priv = fi->priv;
+ struct gsm_bts *bts = priv->bts;
+
+ if (event != ABIS_LINK_EV_VTY_RM_ADDR)
+ return;
+
+ if (priv->bsc_oml_host == data) {
+ if (llist_count(&bts->bsc_oml_hosts) <= 1)
+ priv->bsc_oml_host = NULL;
+ else if (priv->bsc_oml_host == llist_last(&bts->bsc_oml_hosts))
+ priv->bsc_oml_host = priv->bsc_oml_host->prev;
+ else
+ priv->bsc_oml_host = priv->bsc_oml_host->next;
+ }
+}
+
+static struct osmo_fsm_state abis_link_fsm_states[] = {
+ [ABIS_LINK_ST_CONNECTED] = {
+ .name = "CONNECTED",
+ .in_event_mask =
+ S(ABIS_LINK_EV_SIGN_LINK_DOWN),
+ .out_state_mask =
+ S(ABIS_LINK_ST_CONNECTING) |
+ S(ABIS_LINK_ST_FAILED),
+ .action = abis_link_connected,
+ },
+ [ABIS_LINK_ST_CONNECTING] = {
+ .name = "CONNECTING",
+ .out_state_mask =
+ S(ABIS_LINK_ST_CONNECTING) |
+ S(ABIS_LINK_ST_CONNECTED) |
+ S(ABIS_LINK_ST_FAILED),
+ .onenter = abis_link_connecting_onenter,
+ },
+ [ABIS_LINK_ST_FAILED] = {
+ .name = "FAILED",
+ .onenter = abis_link_failed_onenter,
+ },
+};
+
+static struct osmo_fsm abis_link_fsm = {
+ .name = "abis_link",
+ .states = abis_link_fsm_states,
+ .num_states = ARRAY_SIZE(abis_link_fsm_states),
+ .log_subsys = DABIS,
+ .event_names = abis_link_fsm_event_names,
+ .allstate_action = abis_link_allstate,
+ .allstate_event_mask = S(ABIS_LINK_EV_VTY_RM_ADDR),
+};
+
int abis_oml_sendmsg(struct msgb *msg)
{
struct gsm_bts *bts = msg->trx->bts;
@@ -144,41 +344,8 @@ static struct e1inp_sign_link *sign_link_up(void *unit, struct e1inp_line *line,
static void sign_link_down(struct e1inp_line *line)
{
- struct gsm_bts_trx *trx;
LOGPIL(line, DABIS, LOGL_ERROR, "Signalling link down\n");
-
- /* First remove the OML signalling link */
- if (g_bts->oml_link) {
- struct timespec now;
-
- e1inp_sign_link_destroy(g_bts->oml_link);
-
- /* Log a special notice if the OML connection was dropped relatively quickly. */
- if (g_bts->oml_conn_established_timestamp.tv_sec != 0 && clock_gettime(CLOCK_MONOTONIC, &now) == 0 &&
- g_bts->oml_conn_established_timestamp.tv_sec + OSMO_BTS_OML_CONN_EARLY_DISCONNECT >= now.tv_sec) {
- LOGP(DABIS, LOGL_FATAL, "OML link was closed early within %" PRIu64 " seconds. "
- "If this situation persists, please check your BTS and BSC configuration files for errors. "
- "A common error is a mismatch between unit_id configuration parameters of BTS and BSC.\n",
- (uint64_t)(now.tv_sec - g_bts->oml_conn_established_timestamp.tv_sec));
- }
- g_bts->oml_link = NULL;
- }
- memset(&g_bts->oml_conn_established_timestamp, 0, sizeof(g_bts->oml_conn_established_timestamp));
-
- if (g_bts->osmo_link) {
- e1inp_sign_link_destroy(g_bts->osmo_link);
- g_bts->osmo_link = NULL;
- }
-
- /* Then iterate over the RSL signalling links */
- llist_for_each_entry(trx, &g_bts->trx_list, list) {
- if (trx->rsl_link) {
- e1inp_sign_link_destroy(trx->rsl_link);
- trx->rsl_link = NULL;
- }
- }
-
- bts_model_abis_close(g_bts);
+ osmo_fsm_inst_dispatch(g_bts->abis_link_fi, ABIS_LINK_EV_SIGN_LINK_DOWN, NULL);
}
@@ -277,33 +444,27 @@ void abis_init(struct gsm_bts *bts)
osmo_signal_register_handler(SS_L_INPUT, &inp_s_cbfn, bts);
}
-struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host,
- char *model_name)
+int abis_open(struct gsm_bts *bts, char *model_name)
{
- struct e1inp_line *line;
+ struct abis_link_fsm_priv *abis_link_fsm_priv;
- /* patch in various data from VTY and other sources */
- line_ops.cfg.ipa.addr = dst_host;
- osmo_get_macaddr(bts_dev_info.mac_addr, "eth0");
- bts_dev_info.site_id = bts->ip_access.site_id;
- bts_dev_info.bts_id = bts->ip_access.bts_id;
- bts_dev_info.unit_name = model_name;
- if (bts->description)
- bts_dev_info.unit_name = bts->description;
- bts_dev_info.location2 = model_name;
+ if (llist_empty(&bts->bsc_oml_hosts)) {
+ LOGP(DABIS, LOGL_FATAL, "No BSC configured, cannot start BTS without knowing BSC OML IP\n");
+ return -EINVAL;
+ }
- line = e1inp_line_find(0);
- if (line) {
- e1inp_line_get2(line, __FILE__); /* We want a new reference for returned line */
- } else
- line = e1inp_line_create(0, "ipa"); /* already comes with a reference */
- if (!line)
- return NULL;
- e1inp_line_bind_ops(line, &line_ops);
+ OSMO_ASSERT(osmo_fsm_register(&abis_link_fsm) == 0);
+ bts->abis_link_fi = osmo_fsm_inst_alloc(&abis_link_fsm, bts, NULL, LOGL_DEBUG, "abis_link");
+ OSMO_ASSERT(bts->abis_link_fi);
- /* This will open the OML connection now */
- if (e1inp_line_update(line) < 0)
- return NULL;
+ abis_link_fsm_priv = talloc_zero(bts->abis_link_fi, struct abis_link_fsm_priv);
+ OSMO_ASSERT(abis_link_fsm_priv);
+ abis_link_fsm_priv->bsc_oml_host = bts->bsc_oml_hosts.next;
+ abis_link_fsm_priv->bts = bts;
+ abis_link_fsm_priv->model_name = model_name;
+ bts->abis_link_fi->priv = abis_link_fsm_priv;
+
+ osmo_fsm_inst_state_chg_ms(bts->abis_link_fi, ABIS_LINK_ST_CONNECTING, 1, 0);
- return line;
+ return 0;
}
diff --git a/src/common/bts.c b/src/common/bts.c
index 27c7f74c..48adf42f 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -402,6 +402,7 @@ int bts_init(struct gsm_bts *bts)
bts->smscb_queue_hyst = 2;
INIT_LLIST_HEAD(&bts->oml_queue);
+ INIT_LLIST_HEAD(&bts->bsc_oml_hosts);
/* register DTX DL FSM */
rc = osmo_fsm_register(&dtx_dl_amr_fsm);
diff --git a/src/common/main.c b/src/common/main.c
index 0b7d3fb7..bc5cf3bd 100644
--- a/src/common/main.c
+++ b/src/common/main.c
@@ -272,7 +272,6 @@ static int write_pid_file(char *procname)
int bts_main(int argc, char **argv)
{
struct gsm_bts_trx *trx;
- struct e1inp_line *line;
int rc;
/* Track the use of talloc NULL memory contexts */
@@ -397,16 +396,8 @@ int bts_main(int argc, char **argv)
signal(SIGUSR2, &signal_handler);
osmo_init_ignore_signals();
- if (!g_bts->bsc_oml_host) {
- fprintf(stderr, "Cannot start BTS without knowing BSC OML IP\n");
+ if (abis_open(g_bts, "osmo-bts") != 0)
exit(1);
- }
-
- line = abis_open(g_bts, g_bts->bsc_oml_host, "osmo-bts");
- if (!line) {
- fprintf(stderr, "unable to connect to BSC\n");
- exit(2);
- }
rc = phy_links_open();
if (rc < 0) {
diff --git a/src/common/vty.c b/src/common/vty.c
index a7d1e845..fe506a5d 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -41,7 +41,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/trau/osmo_ortp.h>
-
+#include <osmocom/core/fsm.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/gsm_data.h>
@@ -282,6 +282,7 @@ static void config_write_bts_single(struct vty *vty, const struct gsm_bts *bts)
const struct gsm_bts_trx *trx;
const char *sapi_buf;
int i;
+ struct bsc_oml_host *bsc_oml_host;
vty_out(vty, "bts %u%s", bts->nr, VTY_NEWLINE);
if (bts->description)
@@ -291,7 +292,8 @@ static void config_write_bts_single(struct vty *vty, const struct gsm_bts *bts)
vty_out(vty, " auto-band%s", VTY_NEWLINE);
vty_out(vty, " ipa unit-id %u %u%s",
bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
- vty_out(vty, " oml remote-ip %s%s", bts->bsc_oml_host, VTY_NEWLINE);
+ llist_for_each_entry(bsc_oml_host, &bts->bsc_oml_hosts, list)
+ vty_out(vty, " oml remote-ip %s%s", bsc_oml_host->addr, VTY_NEWLINE);
vty_out(vty, " rtp jitter-buffer %u", bts->rtp_jitter_buf_ms);
if (bts->rtp_jitter_adaptive)
vty_out(vty, " adaptive");
@@ -507,11 +509,51 @@ DEFUN(cfg_bts_oml_ip,
"OML Parameters\n" "OML IP Address\n" "OML IP Address\n")
{
struct gsm_bts *bts = vty->index;
+ struct bsc_oml_host *bsc_oml_host;
+
+ /* stop when the address is already in the list */
+ llist_for_each_entry(bsc_oml_host, &bts->bsc_oml_hosts, list) {
+ if (strcmp(argv[0], bsc_oml_host->addr) == 0) {
+ vty_out(vty, "%% duplicate BSC (A-Bis/OML) ip address configured ('%s')%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ bsc_oml_host = talloc_zero(bts, struct bsc_oml_host);
+ OSMO_ASSERT(bsc_oml_host);
+ bsc_oml_host->addr = talloc_strdup(bsc_oml_host, argv[0]);
+ OSMO_ASSERT(bsc_oml_host->addr);
+ llist_add_tail(&bsc_oml_host->list, &bts->bsc_oml_hosts);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_no_oml_ip,
+ cfg_bts_no_oml_ip_cmd,
+ "no oml remote-ip A.B.C.D",
+ NO_STR "OML Parameters\n" "OML IP Address\n" "OML IP Address\n")
+{
+ struct gsm_bts *bts = vty->index;
+ struct bsc_oml_host *bsc_oml_host;
+ struct bsc_oml_host *bsc_oml_host_del = NULL;
- if (bts->bsc_oml_host)
- talloc_free(bts->bsc_oml_host);
+ llist_for_each_entry(bsc_oml_host, &bts->bsc_oml_hosts, list) {
+ if (strcmp(argv[0], bsc_oml_host->addr) == 0)
+ bsc_oml_host_del = bsc_oml_host;
+ }
- bts->bsc_oml_host = talloc_strdup(bts, argv[0]);
+ if (bsc_oml_host_del) {
+ if (bts->abis_link_fi) {
+ osmo_fsm_inst_dispatch(bts->abis_link_fi, ABIS_LINK_EV_VTY_RM_ADDR, bsc_oml_host_del);
+ llist_del(&bsc_oml_host_del->list);
+ talloc_free(bsc_oml_host_del);
+ }
+ } else {
+ vty_out(vty, "%% no such BSC (A-Bis/OML) ip address configured ('%s')%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
return CMD_SUCCESS;
}
@@ -2378,6 +2420,7 @@ int bts_vty_init(void *ctx)
install_element(CONFIG_NODE, &cfg_vty_telnet_port_cmd);
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
install_element(BTS_NODE, &cfg_bts_oml_ip_cmd);
+ install_element(BTS_NODE, &cfg_bts_no_oml_ip_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_bind_ip_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_jitbuf_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_port_range_cmd);
diff --git a/src/osmo-bts-omldummy/main.c b/src/osmo-bts-omldummy/main.c
index a36e0db5..c74af745 100644
--- a/src/osmo-bts-omldummy/main.c
+++ b/src/osmo-bts-omldummy/main.c
@@ -107,7 +107,7 @@ int main(int argc, char **argv)
{
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
- struct e1inp_line *line;
+ struct bsc_oml_host *bsc_oml_host;
int i;
parse_cmdline(argc, argv);
@@ -144,9 +144,13 @@ int main(int argc, char **argv)
//btsb = bts_role_bts(bts);
abis_init(bts);
- line = abis_open(bts, cmdline.dst_host, "OMLdummy");
- if (!line)
- exit(2);
+ bsc_oml_host = talloc_zero(bts, struct bsc_oml_host);
+ OSMO_ASSERT(bsc_oml_host);
+ bsc_oml_host->addr = talloc_strdup(bsc_oml_host, cmdline.dst_host);
+ OSMO_ASSERT(bsc_oml_host->addr);
+ llist_add_tail(&bsc_oml_host->list, &bts->bsc_oml_hosts);
+ if (abis_open(bts, "OMLdummy") != 0)
+ exit(1);
while (1) {
osmo_select_main(0);