[vty] Add option to disable RF on a given TRX.

- Make sure that on runtime the Radio Carrier can be
  locked and unlocked. The vty code calls into the
  Abis NM to lock/unlock the channel and the state is
  stored there.

- Make sure that on start the Radio Carries remains
  offline and we are not starting it. On start the
  radio carrier is either locked or unlocked. This means
  the RSL will not connect until the RF is unlocked. It
  will connect then. To see RSL bringup failures one
  needs to parse the RSL nack message.

- When the TRX is locked on startup the RSL link will
  only be established after it will be unlocked.
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 86a872b..638b035 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -257,6 +257,9 @@
 		} bs11;
 	};
 	struct gsm_bts_trx_ts ts[TRX_NR_TS];
+
+	/* NM state */
+	int rf_locked;
 };
 
 enum gsm_bts_type {
@@ -518,4 +521,6 @@
 enum gsm_auth_policy gsm_auth_policy_parse(const char *arg);
 const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
 
+void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
+
 #endif
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index 4d4cec0..b1fe97d 100755
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -2699,6 +2699,19 @@
 				     attr, attr_len);
 }
 
+void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked)
+{
+	int new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;
+
+	trx->rf_locked = locked;
+	if (!trx->bts || !trx->bts->oml_link)
+		return;
+
+	abis_nm_chg_adm_state(trx->bts, NM_OC_RADIO_CARRIER,
+			      trx->bts->bts_nr, trx->nr, 0xff,
+			      new_state);
+}
+
 static const char *ipacc_testres_names[] = {
 	[NM_IPACC_TESTRES_SUCCESS]	= "SUCCESS",
 	[NM_IPACC_TESTRES_TIMEOUT]	= "TIMEOUT",
diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c
index 66d5606..153e024 100644
--- a/openbsc/src/bsc_init.c
+++ b/openbsc/src/bsc_init.c
@@ -420,7 +420,18 @@
 		/* TRX software is active, tell it to initiate RSL Link */
 		abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
 		break;
-	case NM_OC_RADIO_CARRIER:
+	case NM_OC_RADIO_CARRIER: {
+		/*
+		 * Locking the radio carrier will make it go
+		 * offline again and we would come here. The
+		 * framework should determine that there was
+		 * no change and avoid recursion.
+		 *
+		 * This code is here to make sure that on start
+		 * a TRX remains locked.
+		 */
+		int rc_state = trx->rf_locked ?
+					NM_STATE_LOCKED : NM_STATE_UNLOCKED;
 		/* Patch ARFCN into radio attribute */
 		nanobts_attr_radio[5] &= 0xf0;
 		nanobts_attr_radio[5] |= trx->arfcn >> 8;
@@ -429,10 +440,11 @@
 				       sizeof(nanobts_attr_radio));
 		abis_nm_chg_adm_state(trx->bts, foh->obj_class,
 				      trx->bts->bts_nr, trx->nr, 0xff,
-				      NM_STATE_UNLOCKED);
+				      rc_state);
 		abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
 				trx->nr, 0xff);
 		break;
+		}
 	}
 	return 0;
 }
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index 69a9096..8212346 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -27,6 +27,7 @@
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/talloc.h>
+#include <openbsc/abis_nm.h>
 
 void *tall_bsc_ctx;
 
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index f8bba2c..066dfd5 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -1200,6 +1200,17 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_trx_rf_locked,
+      cfg_trx_rf_locked_cmd,
+      "rf_locked (0|1)",
+      "Turn off RF of the TRX.\n")
+{
+	int locked = atoi(argv[0]);
+	struct gsm_bts_trx *trx = vty->index;
+
+	gsm_trx_lock_rf(trx, locked);
+	return CMD_SUCCESS;
+}
 
 /* per TS configuration */
 DEFUN(cfg_ts,
@@ -1321,6 +1332,7 @@
 	install_element(TRX_NODE, &cfg_trx_max_power_red_cmd);
 	install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd);
 	install_element(TRX_NODE, &cfg_trx_rsl_e1_tei_cmd);
+	install_element(TRX_NODE, &cfg_trx_rf_locked_cmd);
 
 	install_element(TRX_NODE, &cfg_ts_cmd);
 	install_node(&ts_node, dummy_config_write);