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 --- v3: Changed the unix domain socket path for having an appropriate location
src/osmo-bts-sysmo/main.c | 65 ++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 +++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 140 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++++ 4 files changed, 314 insertions(+), 1 deletion(-)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..2992e5b 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,6 +35,7 @@
#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>
@@ -45,8 +46,10 @@ #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"
#include "utils.h" #include "eeprom.h" @@ -258,6 +261,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 +292,55 @@ 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) + return -1; + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + return -1; + } + + msgb_put(msg, rc); + + /*Remove the IPA header for removing the conflict with the new IPA + * header*/ + msgb_pull(msg, sizeof(struct ipaccess_head *)-1); + + mo = &bts->mo; + msg->trx = mo->bts->c0; + msg->l2h = msg->data; + msg->l3h = msg->data + sizeof(struct abis_om_fom_hdr); + + return abis_oml_sendmsg(msg); +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *ofd = (struct osmo_fd *)fd->data; + + cl = accept(sfd, NULL, NULL); + if (cl < 0) + return -1; + + ofd->fd = cl; + if (osmo_fd_register(ofd) != 0) { + close(cl); + return -1; + } + + return 0; +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +348,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd fd, rfd; int rc;
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +424,17 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); } + fd.cb = accept_unix_sock; + rfd.cb = read_sock; + rfd.when = BSC_FD_READ; + fd.data = &rfd; + + rc = osmo_sock_unix_init_ofd(&fd, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(3); + }
if (daemonize) { rc = osmo_daemonize(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..525e526 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,11 @@
static int no_eeprom_write = 0; static int daemonize = 0; +static int trx_nr = -1; +static int fd_unix = -1; +static int state_connection = 0; 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 +60,29 @@ 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 struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + if (state_connection == 0) { + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error creating unix socket\n"); + return; + } + + state_connection = 1; + } + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +91,50 @@ 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; + + if (confinfo.temp_min_pa_warn_limit > temp_pa || + confinfo.temp_max_pa_warn_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + } else if (confinfo.temp_min_pa_sever_limit > temp_pa || + confinfo.temp_max_pa_sever_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_MASTER), + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_SLAVE), + confinfo.pa_power_act); + } + + if (confinfo.temp_min_board_warn_limit > temp_board || + confinfo.temp_max_board_warn_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + } else if (confinfo.temp_min_board_sever_limit > temp_board || + confinfo.temp_max_board_sever_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_PA)); + } + + if (state_connection == 0) + close(fd_unix); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +164,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) { @@ -169,6 +241,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: @@ -363,6 +436,10 @@ int main(int argc, char **argv) hours_timer.cb = hours_timer_cb; hours_timer_cb(NULL);
+ /*start handle for reconnect the socket in case of error*/ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + /* start uc temperature check timer */ initialize_sbts2050();
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 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,144 @@ #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]; + + strcpy(file_id, "sysmomgr"); + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); + 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; + } + memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor)); + strncpy(add_info->name_sensor, nsensor, strlen(nsensor)); + + 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..b19606e 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 pa_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,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 {
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 --- v4: Fixed situation that we have a connection opened with the manager and we have other connection with other manager.
src/osmo-bts-sysmo/main.c | 73 ++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 +++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 140 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++++ 4 files changed, 322 insertions(+), 1 deletion(-)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..269f442 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,6 +35,7 @@
#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>
@@ -45,8 +46,10 @@ #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"
#include "utils.h" #include "eeprom.h" @@ -258,6 +261,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 +292,62 @@ 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) + 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; + return -1; + } + + msgb_put(msg, rc); + + /*Remove the IPA header for removing the conflict with the new IPA + * header*/ + msgb_pull(msg, sizeof(struct ipaccess_head *)-1); + + mo = &bts->mo; + msg->trx = mo->bts->c0; + msg->l2h = msg->data; + msg->l3h = msg->data + sizeof(struct abis_om_fom_hdr); + + return abis_oml_sendmsg(msg); +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *ofd = (struct osmo_fd *)fd->data; + + if (ofd->fd > -1) { + close(ofd->fd); + osmo_fd_unregister(ofd); + ofd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) + return -1; + + ofd->fd = cl; + if (osmo_fd_register(ofd) != 0) { + close(cl); + return -1; + } + + return 0; +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +355,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd fd, rfd; int rc;
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +431,18 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); } + fd.cb = accept_unix_sock; + rfd.cb = read_sock; + rfd.when = BSC_FD_READ; + rfd.fd = -1; + fd.data = &rfd; + + rc = osmo_sock_unix_init_ofd(&fd, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(3); + }
if (daemonize) { rc = osmo_daemonize(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..525e526 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,11 @@
static int no_eeprom_write = 0; static int daemonize = 0; +static int trx_nr = -1; +static int fd_unix = -1; +static int state_connection = 0; 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 +60,29 @@ 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 struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + if (state_connection == 0) { + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error creating unix socket\n"); + return; + } + + state_connection = 1; + } + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +91,50 @@ 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; + + if (confinfo.temp_min_pa_warn_limit > temp_pa || + confinfo.temp_max_pa_warn_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + } else if (confinfo.temp_min_pa_sever_limit > temp_pa || + confinfo.temp_max_pa_sever_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_MASTER), + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_SLAVE), + confinfo.pa_power_act); + } + + if (confinfo.temp_min_board_warn_limit > temp_board || + confinfo.temp_max_board_warn_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + } else if (confinfo.temp_min_board_sever_limit > temp_board || + confinfo.temp_max_board_sever_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_PA)); + } + + if (state_connection == 0) + close(fd_unix); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +164,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) { @@ -169,6 +241,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: @@ -363,6 +436,10 @@ int main(int argc, char **argv) hours_timer.cb = hours_timer_cb; hours_timer_cb(NULL);
+ /*start handle for reconnect the socket in case of error*/ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + /* start uc temperature check timer */ initialize_sbts2050();
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 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,144 @@ #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]; + + strcpy(file_id, "sysmomgr"); + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); + 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; + } + memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor)); + strncpy(add_info->name_sensor, nsensor, strlen(nsensor)); + + 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..b19606e 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 pa_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,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 {
Hi Alvaro,
A couple of comments below.
On Wed, Apr 02, 2014 at 01:36:57PM +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
v4: Fixed situation that we have a connection opened with the manager and we have other connection with other manager.
src/osmo-bts-sysmo/main.c | 73 ++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 +++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 140 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++++ 4 files changed, 322 insertions(+), 1 deletion(-)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..269f442 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,6 +35,7 @@
#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>
@@ -45,8 +46,10 @@ #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"
#include "utils.h" #include "eeprom.h" @@ -258,6 +261,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT");
break; case SIGABRT: case SIGUSR1:unlink(SOCKET_PATH);@@ -288,6 +292,62 @@ 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)
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;return -1;- }
- msgb_put(msg, rc);
- /*Remove the IPA header for removing the conflict with the new IPA
* header*/- msgb_pull(msg, sizeof(struct ipaccess_head *)-1);
- mo = &bts->mo;
- msg->trx = mo->bts->c0;
- msg->l2h = msg->data;
- msg->l3h = msg->data + sizeof(struct abis_om_fom_hdr);
- return abis_oml_sendmsg(msg);
+}
+static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{
- int sfd = fd->fd, cl;
- struct osmo_fd *ofd = (struct osmo_fd *)fd->data;
- if (ofd->fd > -1) {
close(ofd->fd);osmo_fd_unregister(ofd);ofd->fd = -1;- }
- cl = accept(sfd, NULL, NULL);
- if (cl < 0)
return -1;- ofd->fd = cl;
- if (osmo_fd_register(ofd) != 0) {
close(cl);return -1;- }
- return 0;
+}
int main(int argc, char **argv) { struct stat st; @@ -295,6 +355,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx;
- struct osmo_fd fd, rfd;
Perhaps you can rename fd and rfd to something a bit more descriptive, eg. accept_ofd and ofd.
int rc;
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +431,18 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); }
fd.cb = accept_unix_sock;
rfd.cb = read_sock;
rfd.when = BSC_FD_READ;
rfd.fd = -1;
fd.data = &rfd;
rc = osmo_sock_unix_init_ofd(&fd, SOCK_SEQPACKET, 0, SOCKET_PATH,
OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK);if (rc < 0) {
perror("Error creating socket domain creation");exit(3);}
if (daemonize) { rc = osmo_daemonize();
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..525e526 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,11 @@
static int no_eeprom_write = 0; static int daemonize = 0; +static int trx_nr = -1; +static int fd_unix = -1; +static int state_connection = 0;
Please, use some enum for this small state machine, eg.
enum { SYSMO_MGR_DISCONNECTED = 0, SYSMO_MGR_CONNECTED, };
It should help to make the code a bit more readable.
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 +60,29 @@ 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)
^ ^ You can remove those parenthesis.
+/* unix domain socket file descriptor */ +#define SOCKET_PATH "/var/run/bts_oml"
#ifdef BUILD_SBTS2050 +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{
- if (state_connection == 0) {
fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH,OSMO_SOCK_F_CONNECT);if (fd_unix < 0) {LOGP(DTEMP, LOGL_ERROR, "Error creating unix socket\n");return;}state_connection = 1;- }
- osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0);
This timer keeps running even if we're connected. I think you should enable it only if we are in disconnected state.
+}
static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +91,50 @@ 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;
- if (confinfo.temp_min_pa_warn_limit > temp_pa ||
confinfo.temp_max_pa_warn_limit < temp_pa) {
Should this be >= and <= ?
state_connection = sendto_osmobts(fd_unix, ucontrol0,SBTS2050_WARN_ALERT,SBTS2050_TEMP_PA,&confinfo, trx_nr);- } else if (confinfo.temp_min_pa_sever_limit > temp_pa ||
confinfo.temp_max_pa_sever_limit < temp_pa) {
Same here.
state_connection = sendto_osmobts(fd_unix, ucontrol0,SBTS2050_SEVER_ALERT,SBTS2050_TEMP_PA,&confinfo, trx_nr);sbts2050_uc_power(ucontrol0,sbts2050_uc_status(ucontrol0,SBTS2050_STATUS_MASTER),sbts2050_uc_status(ucontrol0,SBTS2050_STATUS_SLAVE),confinfo.pa_power_act);- }
- if (confinfo.temp_min_board_warn_limit > temp_board ||
confinfo.temp_max_board_warn_limit < temp_board) {state_connection = sendto_osmobts(fd_unix, ucontrol0,SBTS2050_WARN_ALERT,SBTS2050_TEMP_BOARD,&confinfo, trx_nr);
This code looks very similar, perhaps you can encapsulate it in a function, ie.
check_temperature(confinfo.temp_min_board_warn_limit, confinfo.temp_max_board_warn_limit, temp_board, SBTS2050_TEMP_BOARD);
- } else if (confinfo.temp_min_board_sever_limit > temp_board ||
confinfo.temp_max_board_sever_limit < temp_board) {state_connection = sendto_osmobts(fd_unix, ucontrol0,SBTS2050_SEVER_ALERT,SBTS2050_TEMP_BOARD,&confinfo, trx_nr);sbts2050_uc_power(ucontrol0, confinfo.master_power_act,confinfo.slave_power_act,sbts2050_uc_status(ucontrol0,SBTS2050_STATUS_PA));- }
- if (state_connection == 0)
close(fd_unix);- osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0);
} #endif @@ -93,6 +164,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) {
@@ -169,6 +241,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write);
exit(0); break; case SIGABRT:close(fd_unix);@@ -363,6 +436,10 @@ int main(int argc, char **argv) hours_timer.cb = hours_timer_cb; hours_timer_cb(NULL);
- /*start handle for reconnect the socket in case of error*/
^ ^
Missing spaces.
/* Start handle ... */
- connect_timer.cb = socket_connect_cb;
- socket_connect_cb(NULL);
- /* start uc temperature check timer */ initialize_sbts2050();
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 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,144 @@ #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];
- strcpy(file_id, "sysmomgr");
Better use strncpy here.
- strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION));
And make sure you nul-terminate these strings.
file_version[strlen(PACKAGE_VERSION)-1] = '\0';
As strncpy doesn't append the \0.
I remember you couldn't use strlcpy, right?
- msgb_v_put(msg, NM_ATT_SW_DESCR);
- msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id),
(uint8_t *)file_id);
Coding style nitpick, perhaps:
msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), (uint8_t *)file_id);
Hi
On 05.04.2014 19:12, Pablo Neira Ayuso wrote:
On Wed, Apr 02, 2014 at 01:36:57PM +0200, Alvaro Neira Ayuso wrote:
From: Álvaro Neira Ayuso anayuso@sysmocom.de
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc. @@ -49,10 +53,144 @@ #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];
- strcpy(file_id, "sysmomgr");
Better use strncpy here.
- strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION));
And make sure you nul-terminate these strings.
file_version[strlen(PACKAGE_VERSION)-1] = '\0';
This just the same like strcpy(file_version, PACKAGE_VERSION).
I'd rather expect
strncpy(file_version, PACKAGE_VERSION, sizeof(file_version)); file_version[sizeof(file_version)-1] = '\0';
As strncpy doesn't append the \0.
Jacob
On Mon, Apr 07, 2014 at 09:34:10AM +0200, Jacob Erlbeck wrote:
Hi
On 05.04.2014 19:12, Pablo Neira Ayuso wrote:
On Wed, Apr 02, 2014 at 01:36:57PM +0200, Alvaro Neira Ayuso wrote:
From: Álvaro Neira Ayuso anayuso@sysmocom.de
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc. @@ -49,10 +53,144 @@ #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];
- strcpy(file_id, "sysmomgr");
Better use strncpy here.
- strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION));
And make sure you nul-terminate these strings.
file_version[strlen(PACKAGE_VERSION)-1] = '\0';This just the same like strcpy(file_version, PACKAGE_VERSION).
I'd rather expect
strncpy(file_version, PACKAGE_VERSION, sizeof(file_version));
Ah I see, you mean the sizeof(...) instead strlen(...). I didn't notice. Indeed, that needs to be fixed Alvaro, thanks for spotting it :).
file_version[sizeof(file_version)-1] = '\0';
As strncpy doesn't append the \0.
El 07/04/14 09:34, Jacob Erlbeck escribió:
Hi
On 05.04.2014 19:12, Pablo Neira Ayuso wrote:
On Wed, Apr 02, 2014 at 01:36:57PM +0200, Alvaro Neira Ayuso wrote:
From: Álvaro Neira Ayuso anayuso@sysmocom.de
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc. @@ -49,10 +53,144 @@ #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];
- strcpy(file_id, "sysmomgr");
Better use strncpy here.
- strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION));
And make sure you nul-terminate these strings.
file_version[strlen(PACKAGE_VERSION)-1] = '\0';This just the same like strcpy(file_version, PACKAGE_VERSION).
I'd rather expect
strncpy(file_version, PACKAGE_VERSION, sizeof(file_version)); file_version[sizeof(file_version)-1] = '\0';
As strncpy doesn't append the \0.
Sorry for don't answering the email before, but I have preferred answer you after send another version.
Thanks a lot Pablo and Jacob, I have applied yours corrections in my new patch.
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 --- v5: Changed the osmo_fd name variables for using anothers more clear. Used enum for declaring states in the connections. Refactored some code for doing some functions for having a code more short and clear. Changed the function connect for only using the timer in the case that the socket is disconnected. Changed some fails when i have used strncpy. And changed some coding style fails.
src/osmo-bts-sysmo/main.c | 115 +++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 90 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 142 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 +++++++ 4 files changed, 379 insertions(+), 1 deletion(-)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..61a5716 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,19 @@ #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_HEADER_SIZE 3 +#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 +266,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: @@ -287,6 +296,95 @@ 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 ipaccess_head *)msg->data; + struct abis_om_hdr *omh; + + if (hh->proto != IPA_OML_PROTO) + return -1; + + if (ntohs(hh->len) != msg->len) + return -1; + + msgb_pull(msg, IPA_HEADER_SIZE); + + msg->l2h = msg->data; + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) + return -1; + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) + return -1; + + if (omh->sequence != 0) + return -1; + + if (omh->length != sizeof(struct abis_om_fom_hdr)) + 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) + 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; + return -1; + } + + msgb_put(msg, rc); + + if (test_recv_msg(msg) < 0) { + LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message"); + return -1; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); +} + +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
int main(int argc, char **argv) { @@ -295,6 +393,9 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; +#ifdef BUILD_SBTS2050 + struct osmo_fd accept_fd, read_fd; +#endif int rc;
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +471,20 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); } +#ifdef BUILD_SBTS2050 + accept_fd.cb = accept_unix_sock; + read_fd.cb = read_sock; + read_fd.when = BSC_FD_READ; + read_fd.fd = -1; + accept_fd.data = &read_fd; + + rc = osmo_sock_unix_init_ofd(&accept_fd, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(3); + } +#endif
if (daemonize) { rc = osmo_daemonize(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..b8813f0 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,63 @@ 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) +{ + if (state_connection == SYSMO_MGR_DISCONNECTED) { + 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 +128,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 +177,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 +186,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 +258,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..20f7ea7 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,146 @@ #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; + } + memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor)); + strncpy(add_info->name_sensor, nsensor, strlen(nsensor)); + + 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 {
Hi Alvaro,
Several comments below.
On Tue, Apr 08, 2014 at 02:31:33PM +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
v5: Changed the osmo_fd name variables for using anothers more clear. Used enum for declaring states in the connections. Refactored some code for doing some functions for having a code more short and clear. Changed the function connect for only using the timer in the case that the socket is disconnected. Changed some fails when i have used strncpy. And changed some coding style fails.
Please, use a item list next time. It's a bit more readable.
src/osmo-bts-sysmo/main.c | 115 +++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 90 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 142 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 +++++++ 4 files changed, 379 insertions(+), 1 deletion(-)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..61a5716 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,19 @@ #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"
^^^^^ I can see spaces here, this should be indented with tabs.
+#define IPA_HEADER_SIZE 3
Please, better use sizeof(struct ipaccess_head) instead of this constant.
+#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 +266,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT");
break; case SIGABRT: case SIGUSR1:unlink(SOCKET_PATH);@@ -287,6 +296,95 @@ 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 ipaccess_head *)msg->data;
- struct abis_om_hdr *omh;
Insufficiente sanity checks here:
if (msg->len < sizeof(struct ipaccess_head)) return -1;
Now you can safely access the content of the ipa header.
hh = (struct ipaccess_head *)msg->data;
- if (hh->proto != IPA_OML_PROTO)
return -1;- if (ntohs(hh->len) != msg->len)
return -1;- msgb_pull(msg, IPA_HEADER_SIZE);
OK, now you can pull the ipa header.
- msg->l2h = msg->data;
- msg->l3h = msg->data + sizeof(struct abis_om_hdr);
Now you have to sanity check the abis OM header before you can access it, is there room for this?
- omh = (struct abis_om_hdr *) msg->l2h;
- if (omh->mdisc != ABIS_OM_MDISC_FOM)
return -1;- if (omh->placement != ABIS_OM_PLACEMENT_ONLY)
return -1;- if (omh->sequence != 0)
return -1;- if (omh->length != sizeof(struct abis_om_fom_hdr))
return -1;
Use logging to inform about malformed messages?
- 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)
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;
You're leaking msg.
msgb_free(msg)
return -1;- }
- msgb_put(msg, rc);
- if (test_recv_msg(msg) < 0) {
LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message");
Same here, please release the msg.
return -1;- }
- mo = &bts->mo;
- msg->trx = mo->bts->c0;
- return abis_oml_sendmsg(msg);
+}
+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
int main(int argc, char **argv) { @@ -295,6 +393,9 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; +#ifdef BUILD_SBTS2050
- struct osmo_fd accept_fd, read_fd;
+#endif int rc;
tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +471,20 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); } +#ifdef BUILD_SBTS2050
- accept_fd.cb = accept_unix_sock;
- read_fd.cb = read_sock;
- read_fd.when = BSC_FD_READ;
- read_fd.fd = -1;
- accept_fd.data = &read_fd;
- rc = osmo_sock_unix_init_ofd(&accept_fd, SOCK_SEQPACKET, 0, SOCKET_PATH,
OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK);- if (rc < 0) {
perror("Error creating socket domain creation");exit(3);- }
+#endif
You can probably encapsulate this in a function:
rc = sbts2050_sock_unix_init(...);
Then in this function you can do:
int sbts2050_sock_unix_init(...) { #ifdef BUILD_SBTS2050 ... #else return 0; #endif }
if (daemonize) { rc = osmo_daemonize(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..b8813f0 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,63 @@ 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
This is quite a lot, you should retry a bit more often, at least every 30 seconds I'd say.
+/* 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) +{
- if (state_connection == SYSMO_MGR_DISCONNECTED) {
Is it possible to run socket_connect_cb in connected state? I don't think so, so you can remove this if branch.
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 +128,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 +177,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 +186,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 +258,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write);
exit(0); break; case SIGABRT:close(fd_unix);diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..20f7ea7 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,146 @@ #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';
Comestic nitpick, I prefer:
file_id[sizeof(file_id) - 1] = '\0';
It's debatable anyway.
- 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;- }
- memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor));
You don't need to memset this to zero if you ...
- strncpy(add_info->name_sensor, nsensor, strlen(nsensor));
^............^
use sizeof up there and nul-terminate this.
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)*/
Two comment styles:
/* Blah blah blah */
or, for multi-lines comments:
/* Blah ... * Blah ... */
That is preferred.
- 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 {
1.7.10.4
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; + + 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 {
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");
break; case SIGABRT: case SIGUSR1:unlink(SOCKET_PATH);@@ -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);
exit(0); break; case SIGABRT:close(fd_unix);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.
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 --- [change in v7] * Added specific error report in all the errors case that we can find * Refactor some code using a new variable abis_om_hdr_len * Changed LOGL_NOTICE to LOGL_ERROR in all the LOGP that I have used for reporting errors * Change the function send_to for using the states variables that I have created for showing the connection state between sysmobts-mgr and sysmobts * Fixed a leak in the function send_to
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..b93667d 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, "Failed: ipa header insufficient space\n"); + return -1; + } + + hh = (struct ipaccess_head *)msg->data; + + if (hh->proto != IPA_OML_PROTO) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect ipa header protocol\n"); + return -1; + } + + if (ntohs(hh->len) != msg->len) { + LOGP(DL1C, LOGL_ERROR, "Failed: 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, "Failed: 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, "Failed: 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, "Failed: incorrect om mdisc value\n"); + return -1; + } + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect om placement value\n"); + return -1; + } + + if (omh->sequence != 0) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect om sequence value\n"); + return -1; + } + + if (omh->length != sizeof(struct abis_om_fom_hdr)) { + LOGP(DL1C, LOGL_ERROR, "Failed: 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, "Failed: 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 new connection.\n"); + return -1; + } + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + LOGP(DL1C, LOGL_ERROR, "Failed to 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..87e8916 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, "Failed: 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, "Failed: 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 {
On Thu, Apr 10, 2014 at 03:40:38PM +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
[change in v7]
- Added specific error report in all the errors case that we can find
- Refactor some code using a new variable abis_om_hdr_len
- Changed LOGL_NOTICE to LOGL_ERROR in all the LOGP that I have used for reporting errors
- Change the function send_to for using the states variables that I have created for showing the connection state between sysmobts-mgr and sysmobts
- Fixed a leak in the function send_to
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..b93667d 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");
break; case SIGABRT: case SIGUSR1:unlink(SOCKET_PATH);@@ -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, "Failed: ipa header insufficient space\n");
^^^^^^^
You have to remove the "Failed:", LOGL_ERROR already includes the tag.
Now this fits in one line per 80-chars:
if (msg->len < sizeof(struct ipaccess_head)) { LOGP(DL1C, LOGL_ERROR, "ipa header insufficient space\n");
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 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 {
On Sun, Apr 13, 2014 at 03:18:45PM +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.
Unless the project leaders have any further concern, this looks good to me:
Acked-by: Pablo Neira Ayuso pablo@gnumonks.org
P.S: I think we don't use the acked-by here yet. Signed-off-by is questionable since there's is not Developer's certificate of origin in the project yet, but I like the Acked-by: for traceability reasons. Just in case you consider to include this. Patchwork automagically includes it when you download the patch from it btw.
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 v9] * Closed the file descriptor in the case that the register fail * Added LOGP more information about the error * Changed the name of the function test_recv_msg to check_oml_msg * Removed the variable IPA_OML_PROTO for using IPAC_PROTO_OML * Moved SOCKET_PATH to sysmobts_mgr.h for using the same variable in the main program and the manager. * Changed the name of the function sbts2050_sock_init to oml_sock_unix_init * Changed the variable which contains the name SEVER to SEVERE * Changed the parameters of check_temperature to lowlimit and highlimit * Changed the name of the function sendto_osmobts to send_omlfailure * Removed the parameter ucontrol in the function send_omlfailure * Removed the close when I have checked the state disconnect in the function connect * Changed the name of the function add_ipa_header to prepend_ipa_header * Fixed the ipa header len for not considering the ipa_header size in the variable * Changed the variable which contains sever to severe in the structure config * Added function descriptions
src/osmo-bts-sysmo/main.c | 183 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 84 ++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 156 +++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 ++++++ 5 files changed, 461 insertions(+), 1 deletion(-)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..11e1878 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"
@@ -52,6 +57,7 @@ #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 +264,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 +295,175 @@ static int write_pid_file(char *procname) return 0; }
+/********************************************************************** + * Function for checking that the OML msg received is well-formed + *********************************************************************/ +static int check_oml_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 %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; + + 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); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x %x\n", + omh->mdisc, ABIS_OM_MDISC_FOM); + 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; + } + + return 0; +} + +/********************************************************************** + * Function for read the incoming OML msg from the unix domain socket + *********************************************************************/ +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 (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; +} + +/********************************************************************** + * Function for accept connection from the unix domain socket + *********************************************************************/ +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); + read_fd->fd = -1; + return -1; + } + + return 0; +} + +/********************************************************************** + * Function for initialize the unix domain socket + *********************************************************************/ +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 +471,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 +548,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..b686c79 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,62 @@ 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 trx_nr = -1; +static int state_connection; + + +/********************************************************************** + * Function for establish the connection with unix domain server + *********************************************************************/ +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; +} + +/********************************************************************** + * Function for check if the temperature is in warning/severe limits + *********************************************************************/ +static void 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; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) + socket_connect_cb(NULL); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +122,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_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 +171,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 +180,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 +252,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..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..037cb6f 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,160 @@ #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 /********************************************************************** + * Function for add TLV SW_DESCR + *********************************************************************/ +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); +} + +/********************************************************************** + * Function for add TLV PROB_CAUSE + *********************************************************************/ +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); +} + +/********************************************************************** + * Function for add the Ipa header + *********************************************************************/ +static void prepend_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)); +} + +/********************************************************************** + * Function for add the OM and FOM OML header + *********************************************************************/ +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); +} + +/********************************************************************** + * Function for send the oml failure event using the unix domain socket + *********************************************************************/ +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, "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_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); + + /* 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); + + prepend_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + 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..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 {
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 v10] * Removed useless function description in this patch
src/osmo-bts-sysmo/main.c | 176 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 ++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 142 ++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 ++++++ 5 files changed, 433 insertions(+), 1 deletion(-)
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..aafbc50 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"
@@ -52,6 +57,7 @@ #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 +264,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 +295,168 @@ static int write_pid_file(char *procname) return 0; }
+/* + * In succesfully case, this function set again the pointers of the l2h and l3h + * of the OML message that we have received. In other case, we don't set the + * pointers of l2h and l3h + */ +static int check_oml_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 %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; + + 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); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x %x\n", + omh->mdisc, ABIS_OM_MDISC_FOM); + 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; + } + + 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 (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, "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); + 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 +464,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 +541,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..8dd97ec 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,55 @@ 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 trx_nr = -1; +static int state_connection; + +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 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; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) + socket_connect_cb(NULL); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +115,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_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 +164,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 +173,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 +245,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..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..5e43089 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,9 +53,145 @@ #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", 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 prepend_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)); +} + +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 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, "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_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); + + /* 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); + + prepend_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + 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 *********************************************************************/ 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 {
On Wed, Apr 16, 2014 at 02:06:22PM +0200, Alvaro Neira Ayuso wrote:
+/*
- In succesfully case, this function set again the pointers of the l2h and l3h
- of the OML message that we have received. In other case, we don't set the
- pointers of l2h and l3h
- */
+static int check_oml_msg(struct msgb *msg) +{
- msg->l2h = msg->data;
...
- if (msg->len < abis_oml_hdr_len)
return -1;- msg->l3h = msg->data + sizeof(struct abis_om_hdr);
- if (omh->mdisc != ABIS_OM_MDISC_FOM)
return -1;
Code and comment do not match. This is why I asked you to say that in the error case the behavior is undefined. The other option would be to re-set l2h/l3h to NULL to make the code match your description. In terms of structure I had thought of a documentation like this:
/** * \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 X on success and Y on failure. */
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 v11] * Moved the function prepend_oml_ipa_header and check_oml_msg to utils for using in the future. * Added Manufacture support in the function check_oml_msg * Changed the description of the function check_oml_msg for having more information about that function. * Changed the function check_temperature for returing 1 in the case that the current_temperature is between the parameters limit that we have used. Return 0 in the other case.
src/osmo-bts-sysmo/Makefile.am | 4 +- src/osmo-bts-sysmo/main.c | 93 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 92 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 143 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 +++++++ src/osmo-bts-sysmo/utils.c | 124 +++++++++++++++++++++++++++ src/osmo-bts-sysmo/utils.h | 7 ++ 8 files changed, 499 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 921103e..acdf6fc 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,86 @@ 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 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 (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, "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); + 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 +381,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 +458,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..51fdd83 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,63 @@ 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 trx_nr = -1; +static int state_connection; + +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 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 struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +123,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 +179,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 +188,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 +260,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..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..fbbd6ee 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,145 @@ #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", 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_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) { + /* length byte, string + 0 termination */ + uint8_t *manuf = msgb_push(msg, 1 + sizeof(osmobts_magic)); + manuf[0] = strlen(osmobts_magic)+1; + memcpy(manuf+1, osmobts_magic, strlen(osmobts_magic)); + } + + 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, "Error creating oml msg\n"); + return -1; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0, 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); + + /* 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); + + prepend_oml_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + 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 *********************************************************************/ 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..ecf3960 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,124 @@ 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; + + 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(osmobts_magic) + 1; + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, + "ID manuf osmobts 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) + msg->l3h = msg->l3h + sizeof(osmobts_magic) + 1; + + return 0; +} + diff --git a/src/osmo-bts-sysmo/utils.h b/src/osmo-bts-sysmo/utils.h index aef774c..10782bb 100644 --- a/src/osmo-bts-sysmo/utils.h +++ b/src/osmo-bts-sysmo/utils.h @@ -13,4 +13,11 @@ 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; +static const char osmobts_magic[] = "com.osmobts"; + +void prepend_oml_ipa_header(struct msgb *msg); + +int check_oml_msg(struct msgb *msg); #endif
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 v12] * Changed check_oml_msg for making a general function that we can use in the future for check and restructure received oml message.
src/osmo-bts-sysmo/Makefile.am | 4 +- src/osmo-bts-sysmo/main.c | 93 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 92 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 143 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 +++++++ src/osmo-bts-sysmo/utils.c | 139 ++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/utils.h | 9 ++ 8 files changed, 516 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 921103e..acdf6fc 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,86 @@ 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 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 (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, "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); + 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 +381,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 +458,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..51fdd83 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,63 @@ 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 trx_nr = -1; +static int state_connection; + +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 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 struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +123,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 +179,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 +188,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 +260,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..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..2030888 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,145 @@ #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", 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_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) { + /* length byte, string + 0 termination */ + uint8_t *manuf = msgb_push(msg, 1 + sizeof(osmocom_magic)); + manuf[0] = strlen(osmocom_magic)+1; + memcpy(manuf+1, osmocom_magic, strlen(osmocom_magic)); + } + + 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, "Error creating oml msg\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); + + /* 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); + + prepend_oml_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + 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 *********************************************************************/ 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..36ba198 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,139 @@ 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; +} + diff --git a/src/osmo-bts-sysmo/utils.h b/src/osmo-bts-sysmo/utils.h index aef774c..b1ca0c0 100644 --- a/src/osmo-bts-sysmo/utils.h +++ b/src/osmo-bts-sysmo/utils.h @@ -13,4 +13,13 @@ 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; + +static const char osmocom_magic[] = "org.osmocom"; +static const char ipaccess_magic[] = "com.ipaccess"; + +void prepend_oml_ipa_header(struct msgb *msg); + +int check_oml_msg(struct msgb *msg); #endif
On Mon, May 05, 2014 at 04:09:51PM +0200, Alvaro Neira Ayuso wrote:
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.
Sorry but the above is not too clear. Please try again.
+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);
What prevents socket_connect_cb(NULL) be called _while_ the timer is pending? While timers for check_temperature and socket_connect_cb might match now one should make sure the timer is stopped.
+static int check_temperature(struct uc *ucontrol0, int lowlimit, int highlimit, @@ -169,6 +260,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write);
exit(0);close(fd_unix);
Well, if we close it we should set fd_unix to -1 and unregister the fd. This might not be signal-safe, so why to close it at all?
- 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);
That is odd. You use "sizeof" which includes the NUL and then you use strlen on file_id which will remove the NUL. This appears to be not consistent.
- if (is_manuf) {
/* length byte, string + 0 termination */uint8_t *manuf = msgb_push(msg, 1 + sizeof(osmocom_magic));manuf[0] = strlen(osmocom_magic)+1;memcpy(manuf+1, osmocom_magic, strlen(osmocom_magic));- }
The sizes look odd here. Sure you want to have one byte for the length, the string and the NUL byte but you expect/assume that the msg is NUL at strlen(osmocom_magic)+1. Maybe it is better to not make this assumption?
- strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor));
- /* 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);
yes? but it is sent to a BSC which might be another machine? Is this relevant?
From: Álvaro Neira Ayuso anayuso@sysmocom.de
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.
Signed-off-by: Alvaro Neira Ayuso anayuso@sysmocom.de --- [changes in v13] * Deleted the socket connect timer in case that the connection is successful. * Removed the function close when the sysmobts-mgr receives the signal SIGINT. * Fixed inconsistence when we make the information that we use for initialize the attributes NM_ATT_SW_DESCR and NM_ATT_FILE_VERSION. * Fixed inconsistence when we make and add the manufacturer Id label. In the last, I have assumed wrong that always we have NUL termination. And too moved this part of code to utils for doing a new function for adding the manufacturer label ID. * Removed a irrelevant commentary when we add the attribute NM_ATT_ADD_INFO.
src/osmo-bts-sysmo/Makefile.am | 4 +- src/osmo-bts-sysmo/main.c | 95 ++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 92 ++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 138 +++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 +++++++ src/osmo-bts-sysmo/utils.c | 160 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/utils.h | 16 ++++ 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..3148c7d 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>
@@ -48,6 +49,7 @@ static int no_eeprom_write = 0; static int daemonize = 0; 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,8 +57,66 @@ 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 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