[BSC] Allow manual override of neighbor cell list

So far, OpenBSC simply assumed that all BTS's configured in openbsc.cfg are
neighbors of each other.  While this is true for small site installations,
it is definitely not true in most real world cases.  We now have the
following new commands at the 'configure bts' level:

'neighbor-list mode (auto|manual)' for selecting the mode

'neighbor-list (add|del) arfcn <0-1024>'
	for adding/deleting ARFCN in manual mode
diff --git a/openbsc/src/bsc_vty.c b/openbsc/src/bsc_vty.c
index e5cc3a8..9709301 100644
--- a/openbsc/src/bsc_vty.c
+++ b/openbsc/src/bsc_vty.c
@@ -488,6 +488,16 @@
 	if (bts->paging.free_chans_need >= 0)
 		vty_out(vty, "  paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE);
 
+	vty_out(vty, "  neighbor-list mode %s%s",
+		bts->neigh_list_manual_mode ? "manual" : "automatic", VTY_NEWLINE);
+	if (bts->neigh_list_manual_mode) {
+		for (i = 0; i < 1024; i++) {
+			if (bitvec_get_bit_pos(&bts->si_common.neigh_list, i))
+				vty_out(vty, "  neighbor-list add arfcn %u%s",
+					i, VTY_NEWLINE);
+		}
+	}
+
 	config_write_bts_gprs(vty, bts);
 
 	llist_for_each_entry(trx, &bts->trx_list, list)
@@ -2116,6 +2126,50 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_bts_neigh_mode, cfg_bts_neigh_mode_cmd,
+	"neighbor-list mode (automatic|manual)",
+	"Neighbor List\n" "Mode of Neighbor List generation\n"
+	"Automatically from all BTS in this OpenBSC\n" "Manual\n")
+{
+	struct gsm_bts *bts = vty->index;
+
+	if (!strcmp(argv[0], "manual")) {
+		/* make sure we clear the current list when switching to
+		 * manual mode */
+		if (bts->neigh_list_manual_mode == 0)
+			memset(&bts->si_common.data.neigh_list, 0,
+				sizeof(bts->si_common.data.neigh_list));
+		bts->neigh_list_manual_mode = 1;
+	} else
+		bts->neigh_list_manual_mode = 0;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd,
+	"neighbor-list (add|del) arfcn <0-1024>",
+	"Neighbor List\n" "Add to manual neighbor list\n"
+	"Delete from manual neighbor list\n" "ARFCN of neighbor\n"
+	"ARFCN of neighbor\n")
+{
+	struct gsm_bts *bts = vty->index;
+	struct bitvec *bv = &bts->si_common.neigh_list;
+	uint16_t arfcn = atoi(argv[1]);
+
+	if (!bts->neigh_list_manual_mode) {
+		vty_out(vty, "%% Cannot configure neighbor list in "
+			"automatic mode%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (!strcmp(argv[0], "add"))
+		bitvec_set_bit_pos(bv, arfcn, 1);
+	else
+		bitvec_set_bit_pos(bv, arfcn, 0);
+
+	return CMD_SUCCESS;
+}
+
 
 #define TRX_TEXT "Radio Transceiver\n"
 
@@ -2614,6 +2668,8 @@
 	install_element(BTS_NODE, &cfg_bts_pag_free_cmd);
 	install_element(BTS_NODE, &cfg_bts_si_mode_cmd);
 	install_element(BTS_NODE, &cfg_bts_si_static_cmd);
+	install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd);
+	install_element(BTS_NODE, &cfg_bts_neigh_cmd);
 
 	install_element(BTS_NODE, &cfg_trx_cmd);
 	install_node(&trx_node, dummy_config_write);
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index 705c107..5ae5258 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -207,6 +207,8 @@
 	bts->num_trx = 0;
 	INIT_LLIST_HEAD(&bts->trx_list);
 	bts->ms_max_power = 15;	/* dBm */
+
+	bts->neigh_list_manual_mode = 0;
 	bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
 	bts->si_common.cell_sel_par.rxlev_acc_min = 0;
 	bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
diff --git a/openbsc/src/system_information.c b/openbsc/src/system_information.c
index 4f31c6b..5079d81 100644
--- a/openbsc/src/system_information.c
+++ b/openbsc/src/system_information.c
@@ -207,11 +207,14 @@
 	/* Zero-initialize the bit-vector */
 	memset(bv->data, 0, bv->data_len);
 
-	/* first we generate a bitvec of the BCCH ARFCN's in our BSC */
-	llist_for_each_entry(cur_bts, &bts->network->bts_list, list) {
-		if (cur_bts == bts)
-			continue;
-		bitvec_set_bit_pos(bv, cur_bts->c0->arfcn, 1);
+	/* Generate list of neighbor cells if we are in automatic mode */
+	if (bts->neigh_list_manual_mode == 0) {
+		/* first we generate a bitvec of the BCCH ARFCN's in our BSC */
+		llist_for_each_entry(cur_bts, &bts->network->bts_list, list) {
+			if (cur_bts == bts)
+				continue;
+			bitvec_set_bit_pos(bv, cur_bts->c0->arfcn, 1);
+		}
 	}
 
 	/* then we generate a GSM 04.08 frequency list from the bitvec */