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

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

Commit Message

Alvaro Neira May 5, 2014, 2:22 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 v8]
* Changed the variable NM_ATT_SBTS_REDUCEPOWER to NM_ATT_O_REDUCEPOWER

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

Comments

Holger Freyther May 15, 2014, 8:47 p.m. UTC | #1
On Mon, May 05, 2014 at 04:22:59PM +0200, Alvaro Neira Ayuso wrote:
> From: Álvaro Neira Ayuso <anayuso@sysmocom.de>
> 
> Added functions for changing the power transmitter in case of we receive

				transmit power?

> a Failure Event report from the manager. The sbts2050 decress the

This is not what happens. Is it? The manager will ask for the power being
reduced. It is not related to a OML Failure Event report.

decress.. do you mean decrease?


> power transmitter with the value that we have configured in the manager.

> +	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));
> +	}

Same as in the other mail. Maybe even share this with a function
to put the osmocom manufacturer header.

> +	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;

Are you leaking the msgb here? I think I saw similar code in the
previous patch. For previous leaks I asked you to send the messages
in a loop to make it obvious that some meoyr is leaked..

> +	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);
> +	}

Move this into a method. We certainly will change the code in the
future to not just go from 0 to X for power changes. The method
should take pa_warning, board_warning, the state and it should
return -1 if no change is required and otherwise the power it
should be reduced to.


> +	rc = recv(fd_unix, msg->tail, msg->data_len, 0);
> +	if (rc <= 0) {
> +		LOGP(DTEMP, LOGL_ERROR, "Error reading from unix socket\n");

print the kind of error like in the error log messages.

Patch
diff mbox

diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index acdf6fc..76305be 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(osmocom_magic));
+		manuf[0] = strlen(osmocom_magic)+1;
+		memcpy(manuf+1, osmocom_magic, strlen(osmocom_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(osmocom_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_O_REDUCEPOWER))
+		recv_reduce_power = *TLVP_VAL(&tlv_out,
+					      NM_ATT_O_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..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 2030888..14b2985 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, 2, 0, trx_nr, 255, 1);
+
+	msgb_tv_put(msg, NM_ATT_O_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 {