[osmo-bts,1/3,v6] src: Add OML support for sending failure message from manager
diff mbox

Message ID 1397125427-28274-1-git-send-email-anayuso@sysmocom.de
State Superseded
Headers show

Commit Message

Alvaro Neira April 10, 2014, 10:23 a.m. UTC
From: Álvaro Neira Ayuso <anayuso@sysmocom.de>

With this patch, the manager monitors the sensors and send
OML Failure message from the Manager to the BTS and the BTS
to BSC, for having a report system of the sensors.

Signed-off-by: Alvaro Neira Ayuso <anayuso@sysmocom.de>
---
[changes in v6]
* Fixed some coding style errors.
* Used the function sizeof for removing the constant IPA_HEADER_SIZE.
* Checked that the message receive from the unix domain socket connetion
  isn't malformed and added logging.
* Fixed some memory leaks.
* Removed the disconnect verification in the function connect.

 src/osmo-bts-sysmo/main.c               |  149 +++++++++++++++++++++++++++++++
 src/osmo-bts-sysmo/misc/sysmobts_mgr.c  |   88 ++++++++++++++++++
 src/osmo-bts-sysmo/misc/sysmobts_misc.c |  143 ++++++++++++++++++++++++++++-
 src/osmo-bts-sysmo/misc/sysmobts_misc.h |   33 +++++++
 4 files changed, 412 insertions(+), 1 deletion(-)

Comments

Pablo Neira Ayuso April 10, 2014, 11:12 a.m. UTC | #1
On Thu, Apr 10, 2014 at 12:23:47PM +0200, Alvaro Neira Ayuso wrote:
> From: Álvaro Neira Ayuso <anayuso@sysmocom.de>
> 
> With this patch, the manager monitors the sensors and send
> OML Failure message from the Manager to the BTS and the BTS
> to BSC, for having a report system of the sensors.
> 
> Signed-off-by: Alvaro Neira Ayuso <anayuso@sysmocom.de>
> ---
> [changes in v6]
> * Fixed some coding style errors.
> * Used the function sizeof for removing the constant IPA_HEADER_SIZE.
> * Checked that the message receive from the unix domain socket connetion
>   isn't malformed and added logging.
> * Fixed some memory leaks.
> * Removed the disconnect verification in the function connect.
> 
>  src/osmo-bts-sysmo/main.c               |  149 +++++++++++++++++++++++++++++++
>  src/osmo-bts-sysmo/misc/sysmobts_mgr.c  |   88 ++++++++++++++++++
>  src/osmo-bts-sysmo/misc/sysmobts_misc.c |  143 ++++++++++++++++++++++++++++-
>  src/osmo-bts-sysmo/misc/sysmobts_misc.h |   33 +++++++
>  4 files changed, 412 insertions(+), 1 deletion(-)
> 
> diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
> index 74ee47f..7e332ad 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,13 +47,18 @@
>  #include <osmo-bts/vty.h>
>  #include <osmo-bts/bts_model.h>
>  #include <osmo-bts/pcu_if.h>
> +#include <osmo-bts/oml.h>
>  
>  #define SYSMOBTS_RF_LOCK_PATH	"/var/lock/bts_rf_lock"
> +#define SOCKET_PATH		"/var/run/bts_oml"
> +
> +#define IPA_OML_PROTO		0xFF
>  
>  #include "utils.h"
>  #include "eeprom.h"
>  #include "l1_if.h"
>  #include "hw_misc.h"
> +#include "btsconfig.h"
>  
>  /* FIXME: read from real hardware */
>  const uint8_t abis_mac[6] = { 0,1,2,3,4,5 };
> @@ -258,6 +265,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 +296,140 @@ static int write_pid_file(char *procname)
>  	return 0;
>  }
>  
> +#ifdef BUILD_SBTS2050
> +static int test_recv_msg(struct msgb *msg)
> +{
> +	struct ipaccess_head *hh;
> +	struct abis_om_hdr *omh;
> +
> +	if (msg->len < sizeof(struct ipaccess_head))
> +		goto err_ipa;
> +
> +	hh = (struct ipaccess_head *)msg->data;
> +
> +	if (hh->proto != IPA_OML_PROTO)
> +		goto err_ipa;
> +
> +	if (ntohs(hh->len) != msg->len)
> +		goto err_ipa;

I'm not convinced this is a good way to report errors. If you ever
have to debug problems, you will not know what condition has exactly
triggered the error message, so please better make one LOGP per
condition.

> +	msgb_pull(msg, sizeof(struct ipaccess_head));
> +

I'd suggest to add:     int abis_oml_hdr_len; then

        abis_om_hdr_len = sizeof(struct abis_om_hdr);

> +	if (msg->len < sizeof(struct abis_om_hdr))
> +		goto err_om;
> +
> +	msg->l2h = msg->data;
> +

        abis_om_hdr_len += sizeof(struct abis_om_fom_hdr);

> +	if (msg->len <
> +	    sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr)) {

        if (msg->len < abis_om_hdr_len) {
                ...

> +		LOGP(DL1C, LOGL_NOTICE, "Failed: fom headermalformed message");
                                ^^^^^^   ^^^^^^
Use LOGL_ERROR and remove the failed. Moreover, return -1 here.

> +	}
> +
> +	msg->l3h = msg->data + sizeof(struct abis_om_hdr);
> +
> +	omh = (struct abis_om_hdr *) msg->l2h;
> +
> +	if (omh->mdisc != ABIS_OM_MDISC_FOM)
> +		goto err_om;

I prefer specific error messages.

> +
> +	if (omh->placement != ABIS_OM_PLACEMENT_ONLY)
> +		goto err_om;
> +
> +	if (omh->sequence != 0)
> +		goto err_om;
> +
> +	if (omh->length != sizeof(struct abis_om_fom_hdr))
> +		goto err_om;
> +
> +	return 0;
> +
> +err_ipa:
> +	LOGP(DL1C, LOGL_NOTICE, "Failed: ipacess header malformed message");
> +	return -1;
> +err_om:
> +	LOGP(DL1C, LOGL_NOTICE, "Failed: om header malformed message");
> +	return -1;
> +}
> +
> +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)
> +		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 (test_recv_msg(msg) < 0) {
> +		LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message");
                           ^---------^   ^^^^^^

Use LOGL_ERROR.

> +		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)
> +		return -1;
> +
> +	read_fd->fd = cl;
> +	if (osmo_fd_register(read_fd) != 0) {
> +		close(cl);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +#endif
> +
> +static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read)
> +{
> +#ifdef BUILD_SBTS2050
> +	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;
> +#else
> +	return 0;
> +#endif
> +}
> +
>  int main(int argc, char **argv)
>  {
>  	struct stat st;
> @@ -295,6 +437,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");
> @@ -371,6 +514,12 @@ int main(int argc, char **argv)
>  		exit(1);
>  	}
>  
> +	rc = sbts2050_sock_unix_init(&accept_fd, &read_fd);
> +	if (rc < 0) {
> +		perror("Error creating socket domain creation");
> +		exit(3);
> +	}
> +
>  	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..7a50bdc 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>
>  
> @@ -45,9 +46,16 @@
>  #include "misc/sysmobts_nl.h"
>  #include "misc/sysmobts_par.h"
>  
> +enum {
> +	SYSMO_MGR_DISCONNECTED = 0,
> +	SYSMO_MGR_CONNECTED,
> +};
> +
>  static int no_eeprom_write = 0;
>  static int daemonize = 0;
> +static int fd_unix = -1;
>  void *tall_mgr_ctx;
> +static struct sbts2050_config_info confinfo;
>  
>  /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */
>  #define TEMP_TIMER_SECS		(6 * 3600)
> @@ -55,7 +63,61 @@ 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
> +
> +/* unix domain socket file descriptor */
> +#define SOCKET_PATH     "/var/run/bts_oml"
> +
>  #ifdef BUILD_SBTS2050
> +static int trx_nr = -1;
> +static int state_connection = 0;
> +
> +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);

This two lines above fit in one line.

> +		return;
> +	}
> +
> +	state_connection = SYSMO_MGR_CONNECTED;
> +}
> +
> +static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit,
> +			      int current_temp,
> +			      enum sbts2050_temp_sensor sensor,
> +			      enum sbts2050_alert_lvl alert)
> +{
> +	int rc;
> +
> +	if (downlimit >= current_temp || uplimit <= current_temp) {
> +		switch (alert) {
> +		case SBTS2050_WARN_ALERT:
> +			rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor,
> +					    &confinfo, trx_nr);
> +			break;
> +		case SBTS2050_SEVER_ALERT:
> +			rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor,
> +					    &confinfo, trx_nr);
> +			sbts2050_uc_power(ucontrol0, confinfo.master_power_act,
> +					  confinfo.slave_power_act,
> +					  confinfo.pa_power_act);
> +			break;
> +		}
> +	}
> +
> +	state_connection = rc;
> +
> +	if (state_connection == SYSMO_MGR_DISCONNECTED) {
> +		close(fd_unix);
> +		socket_connect_cb(NULL);
> +	}
> +}
> +
>  static struct osmo_timer_list temp_uc_timer;
>  static void check_uctemp_timer_cb(void *data)
>  {
> @@ -64,6 +126,26 @@ 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_sever_limit,
> +			  confinfo.temp_max_pa_sever_limit,
> +			  temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_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_sever_limit,
> +			  confinfo.temp_min_board_sever_limit,
> +			  temp_board, SBTS2050_TEMP_BOARD,
> +			  SBTS2050_SEVER_ALERT);
> +
>  	osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0);
>  }
>  #endif
> @@ -93,6 +175,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 +184,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);
> @@ -169,6 +256,7 @@ static void signal_handler(int signal)
>  	case SIGINT:
>  		sysmobts_check_temp(no_eeprom_write);
>  		sysmobts_update_hours(no_eeprom_write);
> +		close(fd_unix);
>  		exit(0);
>  		break;
>  	case SIGABRT:
> diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
> index 9ea26c2..8f708b6 100644
> --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c
> +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
> @@ -29,13 +29,17 @@
>  #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 "btsconfig.h"
>  #include "sysmobts_misc.h"
> @@ -49,10 +53,147 @@
>  #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
> +#define IPA_OML_PROTO		0xFF
>  
>  #ifdef BUILD_SBTS2050
>  /**********************************************************************
> + *	Function send information to OsmoBts
> + *********************************************************************/
> +static void add_sw_descr(struct msgb *msg)
> +{
> +	char file_version[255];
> +	char file_id[255];
> +
> +	strncpy(file_id, "sysmomgr", sizeof("sysmomgr"));
> +	file_id[sizeof(file_id) - 1] = '\0';
> +	strncpy(file_version, PACKAGE_VERSION, sizeof(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_ipa_header(struct msgb *msg)
> +{
> +	struct ipaccess_head *hh;
> +
> +	hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh));
> +	hh->proto = IPA_OML_PROTO;
> +	hh->len = htons(msg->len);
> +}
> +
> +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)
> +{
> +	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;
> +
> +	msg->l2h = msgb_push(msg, sizeof(*omh));
> +	omh = (struct abis_om_hdr *) msg->l2h;
> +
> +	omh->mdisc = ABIS_OM_MDISC_FOM;
> +	omh->placement = ABIS_OM_PLACEMENT_ONLY;
> +	omh->sequence = 0;
> +	omh->length = msgb_l3len(msg);
> +}
> +
> +int sendto_osmobts(int fd_unix, struct uc *ucontrol,

This is returning the state, which is an enum, right?

> +		   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, "Error creating oml msg\n");
> +		goto err;

Please, review this, free(NULL) is legal, but I don't rememer if
msgb_free() is doing more than just that.

> +	}
> +
> +	add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 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_SEVER_ALERT:
> +		msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL);
> +		break;
> +	default:
> +		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:
> +		return -1;

Extremely unlikely to happen, but we have a leak here:

        goto err; ?

I think it would be good to log this as well: "Unknown sensor type".

Please, address this changes, thanks.

Patch
diff mbox

diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index 74ee47f..7e332ad 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,13 +47,18 @@ 
 #include <osmo-bts/vty.h>
 #include <osmo-bts/bts_model.h>
 #include <osmo-bts/pcu_if.h>
+#include <osmo-bts/oml.h>
 
 #define SYSMOBTS_RF_LOCK_PATH	"/var/lock/bts_rf_lock"
+#define SOCKET_PATH		"/var/run/bts_oml"
+
+#define IPA_OML_PROTO		0xFF
 
 #include "utils.h"
 #include "eeprom.h"
 #include "l1_if.h"
 #include "hw_misc.h"
+#include "btsconfig.h"
 
 /* FIXME: read from real hardware */
 const uint8_t abis_mac[6] = { 0,1,2,3,4,5 };
@@ -258,6 +265,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 +296,140 @@  static int write_pid_file(char *procname)
 	return 0;
 }
 
+#ifdef BUILD_SBTS2050
+static int test_recv_msg(struct msgb *msg)
+{
+	struct ipaccess_head *hh;
+	struct abis_om_hdr *omh;
+
+	if (msg->len < sizeof(struct ipaccess_head))
+		goto err_ipa;
+
+	hh = (struct ipaccess_head *)msg->data;
+
+	if (hh->proto != IPA_OML_PROTO)
+		goto err_ipa;
+
+	if (ntohs(hh->len) != msg->len)
+		goto err_ipa;
+
+	msgb_pull(msg, sizeof(struct ipaccess_head));
+
+	if (msg->len < sizeof(struct abis_om_hdr))
+		goto err_om;
+
+	msg->l2h = msg->data;
+
+	if (msg->len <
+	    sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr)) {
+		LOGP(DL1C, LOGL_NOTICE, "Failed: fom headermalformed message");
+	}
+
+	msg->l3h = msg->data + sizeof(struct abis_om_hdr);
+
+	omh = (struct abis_om_hdr *) msg->l2h;
+
+	if (omh->mdisc != ABIS_OM_MDISC_FOM)
+		goto err_om;
+
+	if (omh->placement != ABIS_OM_PLACEMENT_ONLY)
+		goto err_om;
+
+	if (omh->sequence != 0)
+		goto err_om;
+
+	if (omh->length != sizeof(struct abis_om_fom_hdr))
+		goto err_om;
+
+	return 0;
+
+err_ipa:
+	LOGP(DL1C, LOGL_NOTICE, "Failed: ipacess header malformed message");
+	return -1;
+err_om:
+	LOGP(DL1C, LOGL_NOTICE, "Failed: om header malformed message");
+	return -1;
+}
+
+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)
+		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 (test_recv_msg(msg) < 0) {
+		LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message");
+		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)
+		return -1;
+
+	read_fd->fd = cl;
+	if (osmo_fd_register(read_fd) != 0) {
+		close(cl);
+		return -1;
+	}
+
+	return 0;
+}
+#endif
+
+static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read)
+{
+#ifdef BUILD_SBTS2050
+	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;
+#else
+	return 0;
+#endif
+}
+
 int main(int argc, char **argv)
 {
 	struct stat st;
@@ -295,6 +437,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");
@@ -371,6 +514,12 @@  int main(int argc, char **argv)
 		exit(1);
 	}
 
+	rc = sbts2050_sock_unix_init(&accept_fd, &read_fd);
+	if (rc < 0) {
+		perror("Error creating socket domain creation");
+		exit(3);
+	}
+
 	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..7a50bdc 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>
 
@@ -45,9 +46,16 @@ 
 #include "misc/sysmobts_nl.h"
 #include "misc/sysmobts_par.h"
 
+enum {
+	SYSMO_MGR_DISCONNECTED = 0,
+	SYSMO_MGR_CONNECTED,
+};
+
 static int no_eeprom_write = 0;
 static int daemonize = 0;
+static int fd_unix = -1;
 void *tall_mgr_ctx;
+static struct sbts2050_config_info confinfo;
 
 /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */
 #define TEMP_TIMER_SECS		(6 * 3600)
@@ -55,7 +63,61 @@  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
+
+/* unix domain socket file descriptor */
+#define SOCKET_PATH     "/var/run/bts_oml"
+
 #ifdef BUILD_SBTS2050
+static int trx_nr = -1;
+static int state_connection = 0;
+
+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;
+	}
+
+	state_connection = SYSMO_MGR_CONNECTED;
+}
+
+static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit,
+			      int current_temp,
+			      enum sbts2050_temp_sensor sensor,
+			      enum sbts2050_alert_lvl alert)
+{
+	int rc;
+
+	if (downlimit >= current_temp || uplimit <= current_temp) {
+		switch (alert) {
+		case SBTS2050_WARN_ALERT:
+			rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor,
+					    &confinfo, trx_nr);
+			break;
+		case SBTS2050_SEVER_ALERT:
+			rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor,
+					    &confinfo, trx_nr);
+			sbts2050_uc_power(ucontrol0, confinfo.master_power_act,
+					  confinfo.slave_power_act,
+					  confinfo.pa_power_act);
+			break;
+		}
+	}
+
+	state_connection = rc;
+
+	if (state_connection == SYSMO_MGR_DISCONNECTED) {
+		close(fd_unix);
+		socket_connect_cb(NULL);
+	}
+}
+
 static struct osmo_timer_list temp_uc_timer;
 static void check_uctemp_timer_cb(void *data)
 {
@@ -64,6 +126,26 @@  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_sever_limit,
+			  confinfo.temp_max_pa_sever_limit,
+			  temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_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_sever_limit,
+			  confinfo.temp_min_board_sever_limit,
+			  temp_board, SBTS2050_TEMP_BOARD,
+			  SBTS2050_SEVER_ALERT);
+
 	osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0);
 }
 #endif
@@ -93,6 +175,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 +184,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);
@@ -169,6 +256,7 @@  static void signal_handler(int signal)
 	case SIGINT:
 		sysmobts_check_temp(no_eeprom_write);
 		sysmobts_update_hours(no_eeprom_write);
+		close(fd_unix);
 		exit(0);
 		break;
 	case SIGABRT:
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
index 9ea26c2..8f708b6 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c
+++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
@@ -29,13 +29,17 @@ 
 #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 "btsconfig.h"
 #include "sysmobts_misc.h"
@@ -49,10 +53,147 @@ 
 #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
+#define IPA_OML_PROTO		0xFF
 
 #ifdef BUILD_SBTS2050
 /**********************************************************************
+ *	Function send information to OsmoBts
+ *********************************************************************/
+static void add_sw_descr(struct msgb *msg)
+{
+	char file_version[255];
+	char file_id[255];
+
+	strncpy(file_id, "sysmomgr", sizeof("sysmomgr"));
+	file_id[sizeof(file_id) - 1] = '\0';
+	strncpy(file_version, PACKAGE_VERSION, sizeof(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_ipa_header(struct msgb *msg)
+{
+	struct ipaccess_head *hh;
+
+	hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh));
+	hh->proto = IPA_OML_PROTO;
+	hh->len = htons(msg->len);
+}
+
+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)
+{
+	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;
+
+	msg->l2h = msgb_push(msg, sizeof(*omh));
+	omh = (struct abis_om_hdr *) msg->l2h;
+
+	omh->mdisc = ABIS_OM_MDISC_FOM;
+	omh->placement = ABIS_OM_PLACEMENT_ONLY;
+	omh->sequence = 0;
+	omh->length = msgb_l3len(msg);
+}
+
+int sendto_osmobts(int fd_unix, struct uc *ucontrol,
+		   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, "Error creating oml msg\n");
+		goto err;
+	}
+
+	add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 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_SEVER_ALERT:
+		msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL);
+		break;
+	default:
+		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:
+		return -1;
+	}
+	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);
+
+	/* If we need to send this structure to other machine, we need to pass
+	 * the integer inside the structure to internet format (big endian)
+	 */
+	msgb_tl16v_put(msg, NM_ATT_ADD_INFO,
+		       sizeof(struct sbts2050_config_info),
+		       (const uint8_t *)add_info);
+
+	add_ipa_header(msg);
+
+	rc = send(fd_unix, msg->data, msg->len, 0);
+	if (rc < 0) {
+		LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n");
+		close(fd_unix);
+		msgb_free(msg);
+		return 0;
+	}
+
+	msgb_free(msg);
+	return 1;
+err:
+	msgb_free(msg);
+	return -1;
+}
+
+/**********************************************************************
  *	Functions read/write from serial interface
  *********************************************************************/
 static int hand_serial_read(int fd, struct msgb *msg, int numbytes)
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h
index 01878f2..2654348 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_SEVER_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_sever_limit;
+	int temp_min_pa_sever_limit;
+	int temp_max_board_warn_limit;
+	int temp_min_board_warn_limit;
+	int temp_max_board_sever_limit;
+	int temp_min_board_sever_limit;
+	int max_power_red;
+	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,11 @@  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 sendto_osmobts(int fd_unix, struct uc *ucontrol,
+		   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 {