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

Make the sysmobts-mgr sends a manufacturer O&M message
with the relative value that we want to reduce in the
sysmobts. The sysmobts receives this messages. Messages
passing a sanity check takes the relative value that we
want to reduce and the sysmobts reduces the transmit
power. The sysmobts-mgr receives a ACK/NACK for knowing
that the transmit power has been updated.

Signed-off-by: Alvaro Neira Ayuso <[email protected]>
---
[changes in v10]
* Changed the variable NM_ATT_O_REDUCEPOWER to NM_ATT_OSMO_REDUCEPOWER.
* Changed abis_nm_att_tlvdef to abis_nm_osmo_att_tlvdef for parsing the
  the osmocom attributes
* Changed the function take_reduce_power for using abis_om_fom_hdr and the len
  of the l3h and not the message.
* Checked if the message that we have checked is the type that we expect.
* Used the new function for doing the sanity check to the ipa header and
  later the oml message

 src/osmo-bts-sysmo/main.c               |  128 ++++++++++++++++++++++++++++++-
 src/osmo-bts-sysmo/misc/sysmobts_mgr.c  |   41 +++++++---
 src/osmo-bts-sysmo/misc/sysmobts_mgr.h  |    5 ++
 src/osmo-bts-sysmo/misc/sysmobts_misc.c |   80 +++++++++++++++++++
 src/osmo-bts-sysmo/misc/sysmobts_misc.h |    2 +
 5 files changed, 245 insertions(+), 11 deletions(-)

diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index 797f174..ec3ea78 100644
--- a/src/osmo-bts-sysmo/main.c
+++ b/src/osmo-bts-sysmo/main.c
@@ -39,6 +39,7 @@
 #include <osmocom/vty/telnet_interface.h>
 #include <osmocom/vty/logging.h>
 #include <osmocom/gsm/protocol/ipaccess.h>
+#include <osmocom/gsm/abis_nm.h>
 
 #include <osmo-bts/gsm_data.h>
 #include <osmo-bts/logging.h>
@@ -294,10 +295,100 @@ static int write_pid_file(char *procname)
        return 0;
 }
 
+#define oml_tlv_parse(dec, buf, len)   \
+       tlv_parse(dec, &abis_nm_osmo_att_tlvdef, buf, len, 0, 0)
+
+static int send_oml_fom_ack_nack(int fd_unix, struct msgb *old_msg,
+                                uint8_t cause, int is_manuf)
+{
+       struct abis_om_hdr *old_om = msgb_l2(old_msg);
+       struct abis_om_fom_hdr *old_foh = msgb_l3(old_msg);
+       struct msgb *msg;
+       struct abis_om_fom_hdr *foh;
+       struct abis_om_hdr *om;
+       int rc;
+
+       msg = oml_msgb_alloc();
+       if (!msg)
+               return -ENOMEM;
+
+       msg->l3h = msgb_push(msg, sizeof(*foh));
+       foh = (struct abis_om_fom_hdr *) msg->l3h;
+       memcpy(foh, old_foh, sizeof(*foh));
+
+       if (is_manuf)
+               add_manufacturer_id_label(msg, OSMOCOM_MANUF_ID);
+
+       msg->l2h = msgb_push(msg, sizeof(*om));
+       om = (struct abis_om_hdr *) msg->l2h;
+       memcpy(om, old_om, sizeof(*om));
+
+       /* alter message type */
+       if (cause) {
+               LOGP(DOML, LOGL_ERROR, "Sending FOM NACK with cause %s.\n",
+                    abis_nm_nack_cause_name(cause));
+               foh->msg_type += 2; /* nack */
+               msgb_tv_put(msg, NM_ATT_NACK_CAUSES, cause);
+       } else {
+               LOGP(DOML, LOGL_DEBUG, "Sending FOM ACK.\n");
+               foh->msg_type++; /* ack */
+       }
+
+       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 ACK/NACK message send\n",
+                    strerror(errno));
+               close(fd_unix);
+               msgb_free(msg);
+               return -1;
+       }
+
+       msgb_free(msg);
+       return rc;
+}
+
+static void update_transmiter_power(struct gsm_bts_trx *trx)
+{
+       struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
+
+       if (fl1h->hLayer1)
+               l1if_set_txpower(fl1h, sysmobts_get_power_trx(trx));
+}
+
+static int take_reduce_power(struct abis_om_fom_hdr *fom, int len)
+{
+       int recv_reduce_power;
+       struct tlv_parsed tlv_out;
+       struct gsm_bts_trx *trx = bts->c0;
+       int rc;
+
+       rc = oml_tlv_parse(&tlv_out, fom->data,
+                          len - sizeof(struct abis_om_fom_hdr));
+
+       if (rc < 0)
+               return -1;
+
+       if (TLVP_PRESENT(&tlv_out, NM_ATT_OSMO_REDUCEPOWER))
+               recv_reduce_power = *TLVP_VAL(&tlv_out,
+                                             NM_ATT_OSMO_REDUCEPOWER);
+       else
+               return -1;
+
+       trx->power_reduce = recv_reduce_power;
+
+       update_transmiter_power(trx);
+
+       return 0;
+}
+
 static int read_sock(struct osmo_fd *fd, unsigned int what)
 {
        struct msgb *msg;
        struct gsm_abis_mo *mo;
+       struct abis_om_fom_hdr *fom;
        int rc;
 
        msg = oml_msgb_alloc();
@@ -333,9 +424,44 @@ static int read_sock(struct osmo_fd *fd, unsigned int what)
 
        mo = &bts->mo;
        msg->trx = mo->bts->c0;
+       fom = (struct abis_om_fom_hdr *) msg->l3h;
+
+       switch (fom->msg_type) {
+       case NM_MT_SET_RADIO_ATTR:
+               if (rc == MANUFACTURER_MSG_OSMO_TYPE)
+                       rc = take_reduce_power(fom, msgb_l3len(msg));
+               else {
+                       LOGP(DL1C, LOGL_ERROR, "Incorrect message type %d\n",
+                            rc);
+                       rc = -1;
+               }
+               if (rc < 0) {
+                       rc = send_oml_fom_ack_nack(fd->fd, msg,
+                                                  NM_NACK_INCORR_STRUCT, 1);
+               } else {
+                       rc = send_oml_fom_ack_nack(fd->fd, msg, 0, 1);
+               }
+               msgb_free(msg);
+               break;
+       case NM_MT_FAILURE_EVENT_REP:
+               if (rc == OML_MSG_TYPE)
+                       rc = abis_oml_sendmsg(msg);
+               else {
+                       LOGP(DL1C, LOGL_ERROR, "Incorrect message type %d\n",
+                            rc);
+                       rc = -1;
+               }
+               break;
+       default:
+               LOGP(DL1C, LOGL_ERROR, "Unknown Fom message type %d\n",
+                    fom->msg_type);
+               goto err;
+       }
 
-       return abis_oml_sendmsg(msg);
+       if (rc < 0)
+               goto err;
 
+       return rc;
 err:
        msgb_free(msg);
        return -1;
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c 
b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
index e45d41f..4aa2cbf 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
+++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
@@ -82,6 +82,7 @@ static struct vty_app_info vty_info = {
 static int fd_unix = -1;
 static int trx_nr = -1;
 static int state_connection;
+static int status_change_power_red;
 
 static struct osmo_timer_list temp_uc_timer;
 static struct osmo_timer_list connect_timer;
@@ -135,21 +136,39 @@ static int check_temperature(struct uc *ucontrol0, int 
lowlimit, int highlimit,
        return 1;
 }
 
+static int check_warning_state(int pa_warning, int board_warning)
+{
+       if ((pa_warning || board_warning) &&
+           status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) {
+               status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER;
+               send_manufacturer_reduce_msg(fd_unix, confinfo.reduce_max_power,
+                                            trx_nr);
+       } else if (!pa_warning && !board_warning &&
+                  status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) {
+               status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER;
+               send_manufacturer_reduce_msg(fd_unix, 0, trx_nr);
+       } else
+               return -1;
+
+       return 0;
+}
+
 static void check_uctemp_timer_cb(void *data)
 {
        int temp_pa = 0, temp_board = 0;
        struct uc *ucontrol0 = data;
+       int pa_warning, board_warning;
 
        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);
+       pa_warning = 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,
@@ -157,11 +176,11 @@ static void check_uctemp_timer_cb(void *data)
                          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);
+       board_warning = 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,
@@ -169,6 +188,8 @@ static void check_uctemp_timer_cb(void *data)
                          temp_board, SBTS2050_TEMP_BOARD,
                          SBTS2050_SEVERE_ALERT);
 
+       check_warning_state(pa_warning, board_warning);
+
        osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0);
 }
 #endif
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h 
b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
index 5e0d4a7..026afd5 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
+++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
@@ -15,6 +15,11 @@ enum {
        SYSMO_MGR_CONNECTED,
 };
 
+enum {
+       SBTS2050_DISABLE_CHANGE_POWER = 0,
+       SBTS2050_ENABLE_CHANGE_POWER,
+};
+
 #define SOCKET_PATH            "/var/run/bts_oml"
 
 struct sbts2050_config_info;
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c 
b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
index 2417c3d..4f08cfd 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c
+++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
@@ -58,6 +58,23 @@
 #define OM_HEADROOM_SIZE       128
 
 #ifdef BUILD_SBTS2050
+
+static int check_manufacturer_reduce_nach_ack(struct msgb *msg)
+{
+       struct abis_om_fom_hdr *foh = msgb_l3(msg);
+
+       if (foh->msg_type == NM_MT_SET_RADIO_ATTR + 2) { /* NACK */
+               LOGP(DTEMP, LOGL_ERROR, "Reduce Power: Received a BTS NACK\n");
+               return -1;
+       } else if (foh->msg_type != NM_MT_SET_RADIO_ATTR + 1) { /* ACK */
+               LOGP(DTEMP, LOGL_ERROR, "Unknown message type %d\n",
+                    foh->msg_type);
+               return -1;
+       }
+
+       return 0;
+}
+
 static void add_sw_descr(struct msgb *msg)
 {
        char file_version[255];
@@ -112,6 +129,69 @@ static void add_oml_hdr_msg(struct msgb *msg, uint8_t 
msg_type,
        omh->length = msgb_l3len(msg);
 }
 
+int send_manufacturer_reduce_msg(int fd_unix, int reduce_power, int trx_nr)
+{
+       int rc;
+       struct msgb *msg;
+
+       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_SET_RADIO_ATTR, 2, 0, trx_nr, 255, 1);
+
+       msgb_tv_put(msg, NM_ATT_OSMO_REDUCEPOWER, reduce_power);
+
+       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 Reduce Manufacturer O&M msg send\n",
+                    strerror(errno));
+               goto err;
+       }
+
+       msgb_reset(msg);
+       rc = recv(fd_unix, msg->tail, msg->data_len, 0);
+       if (rc <= 0) {
+               LOGP(DTEMP, LOGL_ERROR, "recv error %s during ACK/NACK recv\n",
+                    strerror(errno));
+               goto err;
+       }
+       msgb_put(msg, rc);
+
+       if (check_ipa_header(msg) < 0) {
+               close(fd_unix);
+               msgb_free(msg);
+               return -1;
+       }
+
+       msgb_pull(msg, sizeof(struct ipaccess_head));
+
+       if (check_oml_msg(msg) < 0) {
+               close(fd_unix);
+               msgb_free(msg);
+               return -1;
+       }
+
+       if (check_manufacturer_reduce_nach_ack(msg) < 0) {
+               close(fd_unix);
+               msgb_free(msg);
+               return -1;
+       }
+
+       msgb_free(msg);
+       return SYSMO_MGR_CONNECTED;
+
+err:
+       close(fd_unix);
+       msgb_free(msg);
+       return SYSMO_MGR_DISCONNECTED;
+}
+
 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)
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h 
b/src/osmo-bts-sysmo/misc/sysmobts_misc.h
index c22a54b..740ce2d 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h
+++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h
@@ -75,6 +75,8 @@ 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 send_manufacturer_reduce_msg(int fd_unix, int reduce_power, int trx_nr);
+
 int sysmobts_update_hours(int no_epprom_write);
 
 enum sysmobts_firmware_type {
-- 
1.7.10.4


Reply via email to