[osmo-bts,5/5,v7] main: Added support for changing the power transmitter in sbts2050
diff mbox

Message ID 1398686488-20113-1-git-send-email-anayuso@sysmocom.de
State Changes Requested
Headers show

Commit Message

Alvaro Neira April 28, 2014, 12:01 p.m. UTC
From: Álvaro Neira Ayuso <anayuso@sysmocom.de>

Added functions for changing the power transmitter in case of we receive
a Failure Event report from the manager. The sbts2050 decress the
power transmitter with the value that we have configured in the manager.
For doing that the manager send a OML message with the power that we want
to decress in warning case and too send another OML message for restoring
the power transmitter.

Signed-off-by: Alvaro Neira Ayuso <anayuso@sysmocom.de>
---
[changes in v7]
* Changed the reduce support. Now, We have the timer in the manager and in
  warning case, we will send a OML MANUF message to the BTS for saying that the
  BTS need to reduce the power with the value that we have configured in the
  manager. If everything is correct on the BTS, the BTS send a ACK to the
  manager for confirm that the power has been updated. In other case, the BTS
  send a NACK.

 src/osmo-bts-sysmo/main.c               |  123 ++++++++++++++++++++++++++++++-
 src/osmo-bts-sysmo/misc/sysmobts_mgr.c  |   32 +++++---
 src/osmo-bts-sysmo/misc/sysmobts_mgr.h  |    9 +++
 src/osmo-bts-sysmo/misc/sysmobts_misc.c |   69 +++++++++++++++++
 src/osmo-bts-sysmo/misc/sysmobts_misc.h |    2 +
 5 files changed, 224 insertions(+), 11 deletions(-)

Patch
diff mbox

diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index acdf6fc..695bdaa 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,107 @@  static int write_pid_file(char *procname)
 	return 0;
 }
 
+#define oml_tlv_parse(dec, buf, len)	\
+	tlv_parse(dec, &abis_nm_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) {
+	/* 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(*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, "Error writting in unix socket\n");
+		close(fd_unix);
+		msgb_free(msg);
+		return -1;
+	}
+
+	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 msgb *msg)
+{
+	int recv_reduce_power;
+	struct tlv_parsed tlv_out;
+	struct gsm_bts_trx *trx = bts->c0;
+	int rc, abis_oml_hdr_len;
+
+	abis_oml_hdr_len = sizeof(struct abis_om_hdr);
+	abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr);
+	abis_oml_hdr_len += sizeof(osmobts_magic) + 1;
+
+	rc = oml_tlv_parse(&tlv_out, msg->data + abis_oml_hdr_len,
+			   msg->len - abis_oml_hdr_len);
+
+	if (rc < 0) {
+		msgb_free(msg);
+		return -1;
+	}
+
+	if (TLVP_PRESENT(&tlv_out, NM_ATT_SBTS_REDUCEPOWER))
+		recv_reduce_power = *TLVP_VAL(&tlv_out,
+					      NM_ATT_SBTS_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();
@@ -323,9 +421,32 @@  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;
 
-	return abis_oml_sendmsg(msg);
+	switch (fom->msg_type) {
+	case NM_MT_SET_RADIO_ATTR:
+		rc = take_reduce_power(msg);
+		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:
+		rc = abis_oml_sendmsg(msg);
+		break;
+	default:
+		LOGP(DL1C, LOGL_ERROR, "Unknown Fom message type %d\n",
+		     fom->msg_type);
+		goto err;
+	}
 
+	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 99e95d5..bb9bcac 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 = {
 #ifdef BUILD_SBTS2050
 static int trx_nr = -1;
 static int state_connection;
+static int status_change_power_red;
 
 static struct osmo_timer_list connect_timer;
 static void socket_connect_cb(void *data)
@@ -138,17 +139,18 @@  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,
@@ -156,11 +158,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,
@@ -168,6 +170,16 @@  static void check_uctemp_timer_cb(void *data)
 			  temp_board, SBTS2050_TEMP_BOARD,
 			  SBTS2050_SEVERE_ALERT);
 
+	if ((pa_warning || board_warning) &&
+	    status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) {
+		status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER;
+		send_omlreduce(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_omlreduce(fd_unix, 0, trx_nr);
+	}
+
 	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..cf549fe 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
+++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h
@@ -15,8 +15,17 @@  enum {
 	SYSMO_MGR_CONNECTED,
 };
 
+enum {
+	SBTS2050_DISABLE_CHANGE_POWER = 0,
+	SBTS2050_ENABLE_CHANGE_POWER,
+};
+
 #define SOCKET_PATH		"/var/run/bts_oml"
 
+enum {
+	NM_ATT_SBTS_REDUCEPOWER = 0x1b,
+};
+
 struct sbts2050_config_info;
 
 enum mgr_vty_node {
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c
index fbbd6ee..4023b01 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_omlreduce_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];
@@ -116,6 +133,58 @@  static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type,
 	omh->length = msgb_l3len(msg);
 }
 
+int send_omlreduce(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, 0, 0, trx_nr, 0, 1);
+
+	msgb_tv_put(msg, NM_ATT_SBTS_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, "Error writting to unix socket\n");
+		goto err;
+	}
+
+	msgb_reset(msg);
+	rc = recv(fd_unix, msg->tail, msg->data_len, 0);
+	if (rc <= 0) {
+		LOGP(DTEMP, LOGL_ERROR, "Error reading from unix socket\n");
+		goto err;
+	}
+	msgb_put(msg, rc);
+
+	if (check_oml_msg(msg) < 0) {
+		close(fd_unix);
+		msgb_free(msg);
+		return -1;
+	}
+
+	if (check_omlreduce_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..158e7a2 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_omlreduce(int fd_unix, int reduce_power, int trx_nr);
+
 int sysmobts_update_hours(int no_epprom_write);
 
 enum sysmobts_firmware_type {