aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorÁlvaro Neira Ayuso <anayuso@sysmocom.de>2014-05-17 10:45:50 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-05-18 09:41:29 +0200
commitc6ab90b27006ff2d1fdfb0b1d7fc01e1dd4a696d (patch)
tree46bb0d2443ef44dfdc1eaad5695bfc43424187ea
parent73d9d3af6cd79e674cb326d814dbb50134f76f64 (diff)
sysmobts: Add beginnings of an OML router and create Failure Messages in the sysmobts-manager
Make the sysmobts listen for OML messages on a Unix Domain Socket. Messages passing a sanity check will be forwarded to the BSC. In case the sysmobts-mgr detects a temperature above or below temperature threshold an OML failure message will be sent to the BTS. [moved confinfo into the #ifdef BUILD_SBTS2050] Signed-off-by: Alvaro Neira Ayuso <anayuso@sysmocom.de>
-rw-r--r--src/osmo-bts-sysmo/Makefile.am4
-rw-r--r--src/osmo-bts-sysmo/main.c95
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_mgr.c92
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_mgr.h7
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_misc.c138
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_misc.h32
-rw-r--r--src/osmo-bts-sysmo/utils.c160
-rw-r--r--src/osmo-bts-sysmo/utils.h16
8 files changed, 541 insertions, 3 deletions
diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am
index 1c08af3..e9ba949 100644
--- a/src/osmo-bts-sysmo/Makefile.am
+++ b/src/osmo-bts-sysmo/Makefile.am
@@ -22,8 +22,8 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD)
sysmobts_mgr_SOURCES = \
misc/sysmobts_mgr.c misc/sysmobts_misc.c \
- misc/sysmobts_par.c misc/sysmobts_nl.c
-sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS)
+ misc/sysmobts_par.c misc/sysmobts_nl.c utils.c
+sysmobts_mgr_LDADD = $(COMMON_LDADD)
sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c
sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index 20cfe9c..bd6a181 100644
--- a/src/osmo-bts-sysmo/main.c
+++ b/src/osmo-bts-sysmo/main.c
@@ -35,8 +35,10 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/application.h>
+#include <osmocom/core/socket.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
+#include <osmocom/gsm/protocol/ipaccess.h>
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/logging.h>
@@ -45,6 +47,9 @@
#include <osmo-bts/vty.h>
#include <osmo-bts/bts_model.h>
#include <osmo-bts/pcu_if.h>
+#include <osmo-bts/oml.h>
+
+#include "misc/sysmobts_mgr.h"
#define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock"
@@ -258,6 +263,7 @@ static void signal_handler(int signal)
case SIGINT:
//osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
bts_shutdown(bts, "SIGINT");
+ unlink(SOCKET_PATH);
break;
case SIGABRT:
case SIGUSR1:
@@ -288,6 +294,88 @@ static int write_pid_file(char *procname)
return 0;
}
+static int read_sock(struct osmo_fd *fd, unsigned int what)
+{
+ struct msgb *msg;
+ struct gsm_abis_mo *mo;
+ int rc;
+
+ msg = oml_msgb_alloc();
+ if (msg == NULL) {
+ LOGP(DL1C, LOGL_ERROR,
+ "Failed to allocate oml msgb.\n");
+ return -1;
+ }
+
+ rc = recv(fd->fd, msg->tail, msg->data_len, 0);
+ if (rc <= 0) {
+ close(fd->fd);
+ osmo_fd_unregister(fd);
+ fd->fd = -1;
+ goto err;
+ }
+
+ msgb_put(msg, rc);
+
+ if (check_oml_msg(msg) < 0) {
+ LOGP(DL1C, LOGL_ERROR, "Malformed receive message\n");
+ goto err;
+ }
+
+ mo = &bts->mo;
+ msg->trx = mo->bts->c0;
+
+ return abis_oml_sendmsg(msg);
+
+err:
+ msgb_free(msg);
+ return -1;
+}
+
+static int accept_unix_sock(struct osmo_fd *fd, unsigned int what)
+{
+ int sfd = fd->fd, cl;
+ struct osmo_fd *read_fd = (struct osmo_fd *)fd->data;
+
+ if (read_fd->fd > -1) {
+ close(read_fd->fd);
+ osmo_fd_unregister(read_fd);
+ read_fd->fd = -1;
+ }
+
+ cl = accept(sfd, NULL, NULL);
+ if (cl < 0) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to accept. errno: %s.\n",
+ strerror(errno));
+ return -1;
+ }
+
+ read_fd->fd = cl;
+ if (osmo_fd_register(read_fd) != 0) {
+ LOGP(DL1C, LOGL_ERROR, "Register the read file desc.\n");
+ close(cl);
+ read_fd->fd = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int oml_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read)
+{
+ int rc;
+
+ accept->cb = accept_unix_sock;
+ read->cb = read_sock;
+ read->when = BSC_FD_READ;
+ read->fd = -1;
+ accept->data = read;
+
+ rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH,
+ OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK);
+ return rc;
+}
+
int main(int argc, char **argv)
{
struct stat st;
@@ -295,6 +383,7 @@ int main(int argc, char **argv)
struct gsm_bts_role_bts *btsb;
struct e1inp_line *line;
void *tall_msgb_ctx;
+ struct osmo_fd accept_fd, read_fd;
int rc;
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context");
@@ -373,6 +462,12 @@ int main(int argc, char **argv)
exit(1);
}
+ rc = oml_sock_unix_init(&accept_fd, &read_fd);
+ if (rc < 0) {
+ perror("Error creating socket domain creation");
+ exit(1);
+ }
+
if (daemonize) {
rc = osmo_daemonize();
if (rc < 0) {
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
index 6c64d0f..85ebd80 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
+++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
@@ -36,6 +36,7 @@
#include <osmocom/core/timer.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/serial.h>
+#include <osmocom/core/socket.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
@@ -55,8 +56,67 @@ void *tall_mgr_ctx;
/* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */
#define HOURS_TIMER_SECS (1 * 3600)
+/* every 5 minutes try to reconnect if we have a problem in the communication*/
+#define CONNECT_TIMER_SECS 300
+
#ifdef BUILD_SBTS2050
+static int fd_unix = -1;
+static int trx_nr = -1;
+static int state_connection;
+static struct sbts2050_config_info confinfo;
+
static struct osmo_timer_list temp_uc_timer;
+static struct osmo_timer_list connect_timer;
+static void socket_connect_cb(void *data)
+{
+ fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH,
+ OSMO_SOCK_F_CONNECT);
+ if (fd_unix < 0) {
+ osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0);
+ return;
+ }
+
+ osmo_timer_del(&connect_timer);
+ state_connection = SYSMO_MGR_CONNECTED;
+}
+
+static int check_temperature(struct uc *ucontrol0, int lowlimit, int highlimit,
+ int current_temp,
+ enum sbts2050_temp_sensor sensor,
+ enum sbts2050_alert_lvl alert)
+{
+ int rc;
+
+ if (lowlimit >= current_temp || highlimit <= current_temp) {
+ switch (alert) {
+ case SBTS2050_WARN_ALERT:
+ rc = send_omlfailure(fd_unix, alert, sensor, &confinfo,
+ trx_nr);
+ break;
+ case SBTS2050_SEVERE_ALERT:
+ rc = send_omlfailure(fd_unix, alert, sensor,
+ &confinfo, trx_nr);
+ sbts2050_uc_power(ucontrol0, confinfo.master_power_act,
+ confinfo.slave_power_act,
+ confinfo.pa_power_act);
+ break;
+ default:
+ LOGP(DFIND, LOGL_ERROR, "Unknown alert type %d\n",
+ alert);
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+
+ state_connection = rc;
+
+ if (state_connection == SYSMO_MGR_DISCONNECTED)
+ socket_connect_cb(NULL);
+
+ return 1;
+}
+
static void check_uctemp_timer_cb(void *data)
{
int temp_pa = 0, temp_board = 0;
@@ -64,6 +124,33 @@ static void check_uctemp_timer_cb(void *data)
sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board);
+ confinfo.temp_pa_cur = temp_pa;
+ confinfo.temp_board_cur = temp_board;
+
+ check_temperature(ucontrol0,
+ confinfo.temp_min_pa_warn_limit,
+ confinfo.temp_max_pa_warn_limit,
+ temp_pa, SBTS2050_TEMP_PA,
+ SBTS2050_WARN_ALERT);
+
+ check_temperature(ucontrol0,
+ confinfo.temp_min_pa_severe_limit,
+ confinfo.temp_max_pa_severe_limit,
+ temp_pa, SBTS2050_TEMP_PA,
+ SBTS2050_SEVERE_ALERT);
+
+ check_temperature(ucontrol0,
+ confinfo.temp_min_board_warn_limit,
+ confinfo.temp_max_board_warn_limit,
+ temp_board, SBTS2050_TEMP_BOARD,
+ SBTS2050_WARN_ALERT);
+
+ check_temperature(ucontrol0,
+ confinfo.temp_min_board_severe_limit,
+ confinfo.temp_max_board_severe_limit,
+ temp_board, SBTS2050_TEMP_BOARD,
+ SBTS2050_SEVERE_ALERT);
+
osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0);
}
#endif
@@ -93,6 +180,7 @@ static void initialize_sbts2050(void)
if (val != 0)
return;
}
+ trx_nr = val;
ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200);
if (ucontrol0.fd < 0) {
@@ -101,6 +189,10 @@ static void initialize_sbts2050(void)
return;
}
+ /* start handle for reconnect the socket in case of error */
+ connect_timer.cb = socket_connect_cb;
+ socket_connect_cb(NULL);
+
temp_uc_timer.cb = check_uctemp_timer_cb;
temp_uc_timer.data = &ucontrol0;
check_uctemp_timer_cb(&ucontrol0);
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
index ddb6774..21f30a4 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
+++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
@@ -7,4 +7,11 @@ enum {
DFIND,
};
+enum {
+ SYSMO_MGR_DISCONNECTED = 0,
+ SYSMO_MGR_CONNECTED,
+};
+
+#define SOCKET_PATH "/var/run/bts_oml"
+
#endif
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
index 9ea26c2..2417c3d 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c
+++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
@@ -29,14 +29,19 @@
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <arpa/inet.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/socket.h>
#include <osmocom/core/application.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
+#include <osmocom/gsm/abis_nm.h>
+#include <osmocom/gsm/protocol/ipaccess.h>
+#include "utils.h"
#include "btsconfig.h"
#include "sysmobts_misc.h"
#include "sysmobts_par.h"
@@ -49,9 +54,140 @@
#define SERIAL_ALLOC_SIZE 300
#define SIZE_HEADER_RSP 5
#define SIZE_HEADER_CMD 4
-
+#define OM_ALLOC_SIZE 1024
+#define OM_HEADROOM_SIZE 128
#ifdef BUILD_SBTS2050
+static void add_sw_descr(struct msgb *msg)
+{
+ char file_version[255];
+ char file_id[255];
+
+ strncpy(file_id, "sysmomgr", strlen("sysmomgr"));
+ file_id[sizeof(file_id) - 1] = '\0';
+ strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION));
+ file_version[sizeof(file_version) - 1] = '\0';
+ msgb_v_put(msg, NM_ATT_SW_DESCR);
+ msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id),
+ (uint8_t *)file_id);
+ msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version),
+ (uint8_t *)file_version);
+}
+
+static void add_probable_cause(struct msgb *msg)
+{
+ msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF);
+ msgb_v_put(msg, 0);
+ msgb_v_put(msg, 0);
+}
+
+static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type,
+ uint8_t obj_class, uint8_t bts_nr,
+ uint8_t trx_nr, uint8_t ts_nr, int is_manuf)
+{
+ struct abis_om_fom_hdr *foh;
+ struct abis_om_hdr *omh;
+
+ msg->l3h = msgb_push(msg, sizeof(*foh));
+ foh = (struct abis_om_fom_hdr *) msg->l3h;
+
+ foh->msg_type = msg_type;
+ foh->obj_class = obj_class;
+ foh->obj_inst.bts_nr = bts_nr;
+ foh->obj_inst.trx_nr = trx_nr;
+ foh->obj_inst.ts_nr = ts_nr;
+
+ if (is_manuf)
+ add_manufacturer_id_label(msg, OSMOCOM_MANUF_ID);
+
+ msg->l2h = msgb_push(msg, sizeof(*omh));
+ omh = (struct abis_om_hdr *) msg->l2h;
+
+ if (is_manuf)
+ omh->mdisc = ABIS_OM_MDISC_MANUF;
+ else
+ omh->mdisc = ABIS_OM_MDISC_FOM;
+ omh->placement = ABIS_OM_PLACEMENT_ONLY;
+ omh->sequence = 0;
+ omh->length = msgb_l3len(msg);
+}
+
+int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert,
+ enum sbts2050_temp_sensor sensor,
+ struct sbts2050_config_info *add_info, int trx_nr)
+{
+ int rc;
+ struct msgb *msg;
+ const char *buf, *nsensor;
+
+ msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
+ if (msg == NULL) {
+ LOGP(DTEMP, LOGL_ERROR, "Failed to allocate oml msgb\n");
+ return -1;
+ }
+
+ add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 255, 0);
+
+ msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL);
+
+ switch (alert) {
+ case SBTS2050_WARN_ALERT:
+ msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING);
+ break;
+ case SBTS2050_SEVERE_ALERT:
+ msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL);
+ break;
+ default:
+ LOGP(DTEMP, LOGL_ERROR, "Unknown attr severity type %d\n",
+ alert);
+ goto err;
+ }
+
+ add_probable_cause(msg);
+
+ add_sw_descr(msg);
+
+ switch (sensor) {
+ case SBTS2050_TEMP_BOARD:
+ buf = "Unusual temperature on the Board";
+ nsensor = "Board";
+ break;
+ case SBTS2050_TEMP_PA:
+ buf = "Unusual temperature on the PA";
+ nsensor = "PA";
+ break;
+ default:
+ LOGP(DTEMP, LOGL_ERROR, "Unknown sensor type %d\n", sensor);
+ goto err;
+ }
+ strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor));
+ add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0';
+
+ msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf);
+
+ msgb_tl16v_put(msg, NM_ATT_ADD_INFO,
+ sizeof(struct sbts2050_config_info),
+ (const uint8_t *)add_info);
+
+ prepend_oml_ipa_header(msg);
+
+ rc = send(fd_unix, msg->data, msg->len, 0);
+ if (rc < 0 || rc != msg->len) {
+ LOGP(DTEMP, LOGL_ERROR,
+ "send error %s during send the Failure Event Report msg\n",
+ strerror(errno));
+ close(fd_unix);
+ msgb_free(msg);
+ return SYSMO_MGR_DISCONNECTED;
+ }
+
+ msgb_free(msg);
+ return SYSMO_MGR_CONNECTED;
+err:
+ msgb_free(msg);
+ return -1;
+}
+
/**********************************************************************
* Functions read/write from serial interface
*********************************************************************/
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h
index 01878f2..c22a54b 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h
+++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h
@@ -32,6 +32,34 @@ struct ucinfo {
int pa;
};
+enum sbts2050_alert_lvl {
+ SBTS2050_WARN_ALERT,
+ SBTS2050_SEVERE_ALERT
+};
+
+enum sbts2050_temp_sensor {
+ SBTS2050_TEMP_BOARD,
+ SBTS2050_TEMP_PA
+};
+
+struct sbts2050_config_info {
+ char name_sensor[8];
+ int temp_max_pa_warn_limit;
+ int temp_min_pa_warn_limit;
+ int temp_max_pa_severe_limit;
+ int temp_min_pa_severe_limit;
+ int temp_max_board_warn_limit;
+ int temp_min_board_warn_limit;
+ int temp_max_board_severe_limit;
+ int temp_min_board_severe_limit;
+ int reduce_max_power;
+ int slave_power_act;
+ int master_power_act;
+ int pa_power_act;
+ int temp_pa_cur;
+ int temp_board_cur;
+};
+
int sysmobts_temp_get(enum sysmobts_temp_sensor sensor,
enum sysmobts_temp_type type);
@@ -43,6 +71,10 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa);
int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status);
+int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert,
+ enum sbts2050_temp_sensor sensor,
+ struct sbts2050_config_info *add_info, int trx_nr);
+
int sysmobts_update_hours(int no_epprom_write);
enum sysmobts_firmware_type {
diff --git a/src/osmo-bts-sysmo/utils.c b/src/osmo-bts-sysmo/utils.c
index af1e5d2..2da1228 100644
--- a/src/osmo-bts-sysmo/utils.c
+++ b/src/osmo-bts-sysmo/utils.c
@@ -27,6 +27,9 @@
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/logging.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/ipaccess.h>
+
#include "femtobts.h"
#include "l1_if.h"
@@ -147,3 +150,160 @@ int sysmobts_get_power_trx(struct gsm_bts_trx *trx)
return power_transmitter;
}
+
+void prepend_oml_ipa_header(struct msgb *msg)
+{
+ struct ipaccess_head *hh;
+
+ hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh));
+ hh->proto = IPAC_PROTO_OML;
+ hh->len = htons(msg->len - sizeof(struct ipaccess_head));
+}
+
+/**
+ * \brief Check that the data in \param msg is a proper OML message
+ *
+ * This function verifies that the data in \param in msg is a proper
+ * OML message and can be handled by later functions. In the successful
+ * case the msg->l2h will now point to the OML header and the msg->l3h
+ * will point to the FOM header. The value of l2h/l3h is undefined in
+ * case the verification of the \param msg is failing.
+ *
+ * \param msg The message to analyze. msg->len starting from msg->data
+ * will be analyzed.
+ * \return This function returns the msg with the l2h/l3h pointers in the right
+ * direction on success and on failure, in the case that the msg doesn't contain
+ * the OML header or the OML header values aren't the expect, the function
+ * doesn't set the l2h and l3h. In the case that the msg don't contains the FOM
+ * header or the FOM header values aren't the expect, the function set the l2h
+ * but doesn't set the l3h.
+ */
+
+int check_oml_msg(struct msgb *msg)
+{
+ struct ipaccess_head *hh;
+ struct abis_om_hdr *omh;
+ int abis_oml_hdr_len;
+ char label_id[255];
+
+ if (msg->len < sizeof(struct ipaccess_head)) {
+ LOGP(DL1C, LOGL_ERROR, "Ipa header insufficient space %d %d\n",
+ msg->len, sizeof(struct ipaccess_head));
+ return -1;
+ }
+
+ hh = (struct ipaccess_head *)msg->data;
+
+ if (hh->proto != IPAC_PROTO_OML) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header protocol %x %x\n",
+ hh->proto, IPAC_PROTO_OML);
+ return -1;
+ }
+
+ if (ntohs(hh->len) != msg->len - sizeof(struct ipaccess_head)) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header msg size %d %d\n",
+ ntohs(hh->len), msg->len - sizeof(struct ipaccess_head));
+ return -1;
+ }
+
+ msgb_pull(msg, sizeof(struct ipaccess_head));
+
+ abis_oml_hdr_len = sizeof(struct abis_om_hdr);
+
+ if (msg->len < abis_oml_hdr_len) {
+ LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n",
+ msg->len, abis_oml_hdr_len);
+ return -1;
+ }
+
+ msg->l2h = msg->data;
+
+ omh = (struct abis_om_hdr *) msg->l2h;
+
+ if (omh->mdisc != ABIS_OM_MDISC_FOM &&
+ omh->mdisc != ABIS_OM_MDISC_MANUF) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x\n",
+ omh->mdisc);
+ return -1;
+ }
+
+ if (omh->placement != ABIS_OM_PLACEMENT_ONLY) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n",
+ omh->placement, ABIS_OM_PLACEMENT_ONLY);
+ return -1;
+ }
+
+ if (omh->sequence != 0) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n",
+ omh->sequence);
+ return -1;
+ }
+
+ if (omh->length != sizeof(struct abis_om_fom_hdr)) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect om length value %d %d\n",
+ omh->length, sizeof(struct abis_om_fom_hdr));
+ return -1;
+ }
+
+ if (omh->mdisc == ABIS_OM_MDISC_MANUF) {
+ abis_oml_hdr_len += sizeof(ipaccess_magic);
+
+ if (msg->len < abis_oml_hdr_len) {
+ LOGP(DL1C, LOGL_ERROR,
+ "ID manuf label insufficient space %d %d\n",
+ msg->len, abis_oml_hdr_len);
+ return -1;
+ }
+ }
+
+ abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr);
+
+ if (msg->len < abis_oml_hdr_len) {
+ LOGP(DL1C, LOGL_ERROR, "Fom header insufficient space %d %d\n",
+ msg->len, abis_oml_hdr_len);
+ return -1;
+ }
+
+ msg->l3h = msg->data + sizeof(struct abis_om_hdr);
+
+ if (omh->mdisc == ABIS_OM_MDISC_MANUF) {
+ strncpy(label_id, (const char *) msg->l3h + 1,
+ sizeof(ipaccess_magic) + 1);
+
+ if (strncmp(ipaccess_magic, label_id,
+ sizeof(ipaccess_magic) + 1) == 0)
+ msg->l3h = msg->l3h + sizeof(ipaccess_magic) + 1;
+ else if (strncmp(osmocom_magic, label_id,
+ sizeof(osmocom_magic) + 1) == 0)
+ msg->l3h = msg->l3h + sizeof(osmocom_magic) + 1;
+ else {
+ msg->l3h = NULL;
+ LOGP(DL1C, LOGL_ERROR,
+ "Manuf Label Unknown %s\n", label_id);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int add_manufacturer_id_label(struct msgb *msg, int manuf_type_id)
+{
+ uint8_t *manuf;
+
+ switch (manuf_type_id) {
+ case IPACCESS_MANUF_ID:
+ manuf = msgb_push(msg, 1 + sizeof(ipaccess_magic));
+ manuf[0] = sizeof(ipaccess_magic);
+ memcpy(manuf+1, ipaccess_magic, sizeof(ipaccess_magic));
+ break;
+ case OSMOCOM_MANUF_ID:
+ manuf = msgb_push(msg, 1 + sizeof(osmocom_magic));
+ manuf[0] = sizeof(osmocom_magic);
+ memcpy(manuf+1, osmocom_magic, sizeof(osmocom_magic));
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/osmo-bts-sysmo/utils.h b/src/osmo-bts-sysmo/utils.h
index aef774c..85a5e88 100644
--- a/src/osmo-bts-sysmo/utils.h
+++ b/src/osmo-bts-sysmo/utils.h
@@ -13,4 +13,20 @@ int sysmobts_select_femto_band(struct gsm_bts_trx *trx, uint16_t arfcn);
int sysmobts_get_nominal_power(struct gsm_bts_trx *trx);
int sysmobts_get_power_trx(struct gsm_bts_trx *trx);
+
+struct msgb;
+
+enum manuf_type_id {
+ IPACCESS_MANUF_ID,
+ OSMOCOM_MANUF_ID,
+};
+
+static const char osmocom_magic[] = "org.osmocom";
+static const char ipaccess_magic[] = "com.ipaccess";
+
+int add_manufacturer_id_label(struct msgb *msg, int manuf_type_id);
+
+void prepend_oml_ipa_header(struct msgb *msg);
+
+int check_oml_msg(struct msgb *msg);
#endif