ctrl: Implement a global result for rf_locked

Create a one stop command to give a statement for the
entire network. This can be used to check the policy
and the state of the entire network.
diff --git a/openbsc/src/libbsc/bsc_ctrl_commands.c b/openbsc/src/libbsc/bsc_ctrl_commands.c
index 30d0a52..1d91c5f 100644
--- a/openbsc/src/libbsc/bsc_ctrl_commands.c
+++ b/openbsc/src/libbsc/bsc_ctrl_commands.c
@@ -366,8 +366,33 @@
 
 static int get_net_rf_lock(struct ctrl_cmd *cmd, void *data)
 {
-	cmd->reply = "get only works for the individual trx properties.";
-	return CTRL_CMD_ERROR;
+	struct gsm_network *net = cmd->node;
+	struct gsm_bts *bts;
+	const char *policy_name;
+
+	policy_name = osmo_bsc_rf_get_policy_name(net->bsc_data->rf_ctrl->policy);
+
+	llist_for_each_entry(bts, &net->bts_list, list) {
+		struct gsm_bts_trx *trx;
+
+		/* Exclude the BTS from the global lock */
+		if (bts->excl_from_rf_lock)
+			continue;
+
+		llist_for_each_entry(trx, &bts->trx_list, list) {
+			if (trx->mo.nm_state.availability == NM_AVSTATE_OK &&
+			    trx->mo.nm_state.operational != NM_OPSTATE_DISABLED) {
+				cmd->reply = talloc_asprintf(cmd,
+						"state=on,policy=%s,bts=%u,trx=%u",
+						policy_name, bts->nr, trx->nr);
+				return CTRL_CMD_REPLY;
+			}
+		}
+	}
+
+	cmd->reply = talloc_asprintf(cmd, "state=off,policy=%s",
+			policy_name);
+	return CTRL_CMD_REPLY;
 }
 
 #define TIME_FORMAT_RFC2822 "%a, %d %b %Y %T %z"
diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py
index 160333d..9e56457 100644
--- a/openbsc/tests/ctrl_test_runner.py
+++ b/openbsc/tests/ctrl_test_runner.py
@@ -305,6 +305,11 @@
         self.assertEquals(r['var'], 'bts.0.rf_state')
         self.assertEquals(r['value'], 'inoperational,locked,off')
 
+        r = self.do_get('rf_locked')
+        self.assertEquals(r['mtype'], 'GET_REPLY')
+        self.assertEquals(r['var'], 'rf_locked')
+        self.assertEquals(r['value'], 'state=off,policy=off')
+
         r = self.do_set('rf_locked', '0')
         self.assertEquals(r['mtype'], 'SET_REPLY')
         self.assertEquals(r['var'], 'rf_locked')
@@ -317,6 +322,11 @@
         self.assertEquals(r['var'], 'bts.0.rf_state')
         self.assertEquals(r['value'], 'inoperational,unlocked,on')
 
+        r = self.do_get('rf_locked')
+        self.assertEquals(r['mtype'], 'GET_REPLY')
+        self.assertEquals(r['var'], 'rf_locked')
+        self.assertEquals(r['value'], 'state=off,policy=on')
+
     def testTimezone(self):
         r = self.do_get('bts.0.timezone')
         self.assertEquals(r['mtype'], 'GET_REPLY')