From: Álvaro Neira Ayuso <[email protected]>

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 <[email protected]>
---
[changes in v8]
* Changed the message in the log functions for using a incorrect message format

 src/osmo-bts-sysmo/main.c               |  168 +++++++++++++++++++++++++++++++
 src/osmo-bts-sysmo/misc/sysmobts_mgr.c  |   82 +++++++++++++++
 src/osmo-bts-sysmo/misc/sysmobts_mgr.h  |    5 +
 src/osmo-bts-sysmo/misc/sysmobts_misc.c |  145 +++++++++++++++++++++++++-
 src/osmo-bts-sysmo/misc/sysmobts_misc.h |   33 ++++++
 5 files changed, 432 insertions(+), 1 deletion(-)

diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index 74ee47f..98da626 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,159 @@ 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;
+       int abis_oml_hdr_len;
+
+       if (msg->len < sizeof(struct ipaccess_head)) {
+               LOGP(DL1C, LOGL_ERROR, "Ipa header insufficient space\n");
+               return -1;
+       }
+
+       hh = (struct ipaccess_head *)msg->data;
+
+       if (hh->proto != IPA_OML_PROTO) {
+               LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header protocol\n");
+               return -1;
+       }
+
+       if (ntohs(hh->len) != msg->len) {
+               LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header message size\n");
+               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\n");
+               return -1;
+       }
+
+       msg->l2h = msg->data;
+
+       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\n");
+               return -1;
+       }
+
+       msg->l3h = msg->data + sizeof(struct abis_om_hdr);
+
+       omh = (struct abis_om_hdr *) msg->l2h;
+
+       if (omh->mdisc != ABIS_OM_MDISC_FOM) {
+               LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value\n");
+               return -1;
+       }
+
+       if (omh->placement != ABIS_OM_PLACEMENT_ONLY) {
+               LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value\n");
+               return -1;
+       }
+
+       if (omh->sequence != 0) {
+               LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value\n");
+               return -1;
+       }
+
+       if (omh->length != sizeof(struct abis_om_fom_hdr)) {
+               LOGP(DL1C, LOGL_ERROR, "Incorrect om length value\n");
+               return -1;
+       }
+
+       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 alloc oml message.\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 (test_recv_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, "Accept new unix domain connection.\n");
+               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);
+               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 +456,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 +533,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(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..51fa539 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>
 
@@ -47,7 +48,9 @@
 
 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 +58,60 @@ 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 +120,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 +169,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 +178,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 +250,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_mgr.h 
b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
index ddb6774..87668e0 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
+++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
@@ -7,4 +7,9 @@ enum {
        DFIND,
 };
 
+enum {
+       SYSMO_MGR_DISCONNECTED = 0,
+       SYSMO_MGR_CONNECTED,
+};
+
 #endif
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c 
b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
index 9ea26c2..1cd2e9c 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,149 @@
 #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");
+               return -1;
+       }
+
+       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:
+               LOGP(DTEMP, LOGL_ERROR, "Unknown attr severity type\n");
+               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\n");
+               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);
+
+       /* 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 SYSMO_MGR_DISCONNECTED;
+       }
+
+       msgb_free(msg);
+       return SYSMO_MGR_CONNECTED;
+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 {
-- 
1.7.10.4


Reply via email to