Change in osmo-bsc[master]: heighbor_ident: add/del neighbor cells via ctrl interface

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

dexter gerrit-no-reply at lists.osmocom.org
Wed Oct 27 09:12:12 UTC 2021


dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/25976 )


Change subject: heighbor_ident: add/del neighbor cells via ctrl interface
......................................................................

heighbor_ident: add/del neighbor cells via ctrl interface

The VTY allows flexible control over the neighbor cell information via
the neighbor command, which can be found in the configure terminal under
the bts node. Lets add pendant of this command on the control interface
as well.

Change-Id: I343a40e18fa9b91e6c381912c0426a002841e079
Related: SYS#5641
---
M doc/manuals/chapters/control.adoc
M include/osmocom/bsc/neighbor_ident.h
M src/osmo-bsc/Makefile.am
M src/osmo-bsc/bsc_ctrl_commands.c
A src/osmo-bsc/neighbor_ident_ctrl.c
M src/osmo-bsc/neighbor_ident_vty.c
6 files changed, 729 insertions(+), 29 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/76/25976/1

diff --git a/doc/manuals/chapters/control.adoc b/doc/manuals/chapters/control.adoc
index 2585126..40a5cb9 100644
--- a/doc/manuals/chapters/control.adoc
+++ b/doc/manuals/chapters/control.adoc
@@ -121,3 +121,28 @@
 accepted.
 
 FIXME: add variables defined in src/ctrl/control_if.c?
+
+=== add/del neighbor cell
+
+The control interface allows for editing the neighbor cell configuration. Neighbor
+cells can be added or removed during runtime. It is also possible to clear the
+entire neighbor list if necessary.
+
+.Variables available over control interface
+[options="header",width="100%",cols="20%,5%,5%,50%,20%"]
+|===
+|Name|Access|Trap|Value|Comment
+|bts.N.neighbor-bts.add|WO|No|"<num>"|Add neighbor cell by local BTS number.
+|bts.N.neighbor-bts.del|WO|No|"<num>"|Delete neighbor cell by local BTS number.
+|bts.N.neighbor-lac.add|WO|No|"<lac>[-<arfcn>-<bsic>]"|Add neighbor cell by LAC.
+|bts.N.neighbor-lac.del|WO|No|"<lac>[-<arfcn>-<bsic>]"|Delete neighbor cell by LAC.
+|bts.N.neighbor-lac-ci.add|WO|No|"<lac>-<ci>[-<arfcn>-<bsic>]"|Add neighbor cell by LAC and CI.
+|bts.N.neighbor-lac-ci.del|WO|No|"<lac>-<ci>[-<arfcn>-<bsic>]"|Delete neighbor cell by LAC and CI.
+|bts.N.neighbor-cgi.add|WO|No|"<mcc>-<mnc>-<lac>-<ci>[-<arfcn>-<bsic>]"|Add neighbor cell by cgi.
+|bts.N.neighbor-cgi.del|WO|No|"<mcc>-<mnc>-<lac>-<ci>[-<arfcn>-<bsic>]"|Delete neighbor cell by cgi.
+|bts.N.neighbor-cgi-ps.add|WO|No|"<mcc>-<mnc>-<lac>-<rac>-<ci>[-<arfcn>-<bsic>]"|Add neighbor cell by cgi (Packet Switched, with RAC)
+|bts.N.neighbor-cgi-ps.del|WO|No|"<mcc>-<mnc>-<lac>-<rac>-<ci>[-<arfcn>-<bsic>]"|Delete neighbor cell by cgi (Packet Switched, with RAC).
+|bts.N.neighbor-clear|WO|No|Ignored|Delete all neighbor cells.
+|===
+
+NOTE: The bsic-number (<bsic>) can also be set to "any" if no explcit bsic shall be given
diff --git a/include/osmocom/bsc/neighbor_ident.h b/include/osmocom/bsc/neighbor_ident.h
index 58300ba..c6a2c42 100644
--- a/include/osmocom/bsc/neighbor_ident.h
+++ b/include/osmocom/bsc/neighbor_ident.h
@@ -77,6 +77,10 @@
 void neighbor_ident_vty_write_bts(struct vty *vty, const char *indent, struct gsm_bts *bts);
 void neighbor_ident_vty_write_network(struct vty *vty, const char *indent);
 
+int neighbor_ident_add_neighbor(struct vty *vty, struct gsm_bts *bts, struct neighbor *n);
+int neighbor_ident_del_neighbor(struct vty *vty, struct gsm_bts *bts, struct neighbor *n);
+int neighbor_ident_ctrl_init(void);
+
 int neighbors_check_cfg();
 
 #define CELL_AB_VTY_PARAMS "arfcn <0-1023> bsic (<0-63>|any)"
diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am
index 19af569..3d6666e 100644
--- a/src/osmo-bsc/Makefile.am
+++ b/src/osmo-bsc/Makefile.am
@@ -78,6 +78,7 @@
 	meas_rep.c \
 	neighbor_ident.c \
 	neighbor_ident_vty.c \
+	neighbor_ident_ctrl.c \
 	net_init.c \
 	nm_common_fsm.c \
 	nm_bb_transc_fsm.c \
diff --git a/src/osmo-bsc/bsc_ctrl_commands.c b/src/osmo-bsc/bsc_ctrl_commands.c
index 4c8cb99..a902eb2 100644
--- a/src/osmo-bsc/bsc_ctrl_commands.c
+++ b/src/osmo-bsc/bsc_ctrl_commands.c
@@ -35,6 +35,7 @@
 #include <osmocom/bsc/osmo_bsc_rf.h>
 #include <osmocom/bsc/bsc_msc_data.h>
 #include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/neighbor_ident.h>
 
 static int verify_net_apply_config_file(struct ctrl_cmd *cmd, const char *value, void *_data)
 {
@@ -706,6 +707,8 @@
 	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_c0_power_red);
 	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_resend_si);
 
+	rc |= neighbor_ident_ctrl_init();
+
 	rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_max_power);
 	rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_arfcn);
 	rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_rf_locked);
diff --git a/src/osmo-bsc/neighbor_ident_ctrl.c b/src/osmo-bsc/neighbor_ident_ctrl.c
new file mode 100644
index 0000000..d476da6
--- /dev/null
+++ b/src/osmo-bsc/neighbor_ident_ctrl.c
@@ -0,0 +1,656 @@
+/* CTRL interface implementation to manage identity of neighboring BSS cells for inter-BSC handover. */
+/* (C) 2021 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <nhofmeyr at sysmocom.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <errno.h>
+#include <time.h>
+
+#include <osmocom/ctrl/control_cmd.h>
+
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/misc.h>
+
+#include <osmocom/bsc/neighbor_ident.h>
+#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bsc_msc_data.h>
+#include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/vty.h>
+
+/* Continue to parse ARFCN and BSIC, which are optional parameters at the end of the parameter string in most of the
+ * commands. The result is ignored when parameter n is set to NULL. */
+static int continue_parse_arfcn_and_bsic(char **saveptr, struct neighbor *n)
+{
+	int arfcn;
+	int bsic;
+	char *tok;
+
+	tok = strtok_r(NULL, "-", saveptr);
+
+	/* No ARFCN and BSIC persent - stop */
+	if (!tok)
+		return 0;
+
+	if (osmo_str_to_int(&arfcn, tok, 10, 0, 1023) < 0)
+		return 1;
+	
+	tok = strtok_r(NULL, "-", saveptr);
+
+	/* When an ARFCN is given, then the BSIC parameter is
+	 * mandatory */
+	if (!tok)
+		return 1;
+
+	if (strcmp(tok, "any") == 0) {
+		bsic = BSIC_ANY;
+	} else {
+		if (osmo_str_to_int(&bsic, tok, 10, 0, 63) < 0)
+			return 1;
+	}
+
+	/* Make sure there are no excess parameters */
+	if(strtok_r(NULL, "-", saveptr))
+		return 1;
+
+	if (n) {
+		n->cell_id.ab_present = true;
+		n->cell_id.ab.arfcn = arfcn;
+		n->cell_id.ab.bsic = bsic;		
+	}
+
+	return 0;
+}
+
+/* This and the following: Add/Remove a BTS as neighbor */
+static int verify_neighbor_bts(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	struct gsm_bts *bts = cmd->node;	
+	const int neigh_bts_nr = atoi(value);
+	struct gsm_bts *neigh_bts = gsm_bts_num(bts->network, neigh_bts_nr);
+
+	if (!neigh_bts) {
+		cmd->reply = "Invalid Neighbor BTS number - no such BTS";
+		return 1;
+	}
+
+	return 0;
+}
+
+static int verify_neighbor_bts_add(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return verify_neighbor_bts(cmd, value, _data);
+}
+
+static int set_neighbor_bts_add(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	const int bts_nr = atoi(cmd->value);
+	int rc;
+
+	struct neighbor n = {
+		.type = NEIGHBOR_TYPE_BTS_NR,
+		.bts_nr = bts_nr,
+	};
+	rc = neighbor_ident_add_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_bts_add, "neighbor-bts add");
+
+static int verify_neighbor_bts_del(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return verify_neighbor_bts(cmd, value, _data);
+}
+
+static int set_neighbor_bts_del(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	const int bts_nr = atoi(cmd->value);
+	int rc;
+
+	struct neighbor n = {
+		.type = NEIGHBOR_TYPE_BTS_NR,
+		.bts_nr = bts_nr,
+	};
+	rc = neighbor_ident_del_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_bts_del, "neighbor-bts del");
+
+
+/* This and the following: Add/Remove a LAC as neighbor */
+static int parse_lac(void *ctx, struct neighbor *n, const char *value)
+{
+	char *tmp = NULL, *tok, *saveptr;
+	int rc = 0;
+	int lac;
+
+	if (n)
+		memset(n, 0, sizeof(*n));
+	
+	tmp = talloc_strdup(ctx, value);
+	if (!tmp)
+		return 1;
+
+	/* Parse LAC */	
+	tok = strtok_r(tmp, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&lac, tok, 10, 0, 65535) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}
+
+	/* Optional parameters: ARFCN and BSIC */
+	if(continue_parse_arfcn_and_bsic(&saveptr, n)) {
+		rc = 1;
+		goto exit;
+	}
+
+	if (n) {
+		n->type = NEIGHBOR_TYPE_CELL_ID;
+		n->cell_id.id.id_discr = CELL_IDENT_LAC;
+		n->cell_id.id.id.lac = lac;
+	}
+	
+exit:
+	talloc_free(tmp);
+	return rc;
+}
+
+static int verify_neighbor_lac_add(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return parse_lac(cmd, NULL, value);
+}
+
+static int set_neighbor_lac_add(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+
+	parse_lac(cmd, &n, cmd->value);
+	rc = neighbor_ident_add_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_lac_add, "neighbor-lac add");
+
+static int verify_neighbor_lac_del(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return  parse_lac(cmd, NULL, value);
+}
+
+static int set_neighbor_lac_del(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+	parse_lac(cmd, &n, cmd->value);
+	rc = neighbor_ident_del_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_lac_del, "neighbor-lac del");
+
+
+/* This and the following: Add/Remove a LAC-CI as neighbor */
+static int parse_lac_ci(void *ctx, struct neighbor *n, const char *value)
+{
+	char *tmp = NULL, *tok, *saveptr;
+	int rc = 0;
+	int lac;
+	int ci;	
+
+	if (n)
+		memset(n, 0, sizeof(*n));
+	
+	tmp = talloc_strdup(ctx, value);
+	if (!tmp)
+		return 1;
+
+	/* Parse LAC */
+	tok = strtok_r(tmp, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&lac, tok, 10, 0, 65535) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}
+
+	/* Parse CI */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&ci, tok, 10, 0, 65535) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}	
+
+	/* Optional parameters: ARFCN and BSIC */
+	if(continue_parse_arfcn_and_bsic(&saveptr, n)) {
+		rc = 1;
+		goto exit;
+	}
+
+	if (n) {
+		n->type = NEIGHBOR_TYPE_CELL_ID;
+		n->cell_id.id.id_discr = CELL_IDENT_LAC_AND_CI;
+		n->cell_id.id.id.lac = lac;
+		n->cell_id.id.id.ci = ci;
+	}
+	
+exit:
+	talloc_free(tmp);
+	return rc;
+}
+
+static int verify_neighbor_lac_ci_add(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return parse_lac_ci(cmd, NULL, value);
+}
+
+static int set_neighbor_lac_ci_add(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+
+	parse_lac_ci(cmd, &n, cmd->value);
+	rc = neighbor_ident_add_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_lac_ci_add, "neighbor-lac-ci add");
+
+static int verify_neighbor_lac_ci_del(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return  parse_lac_ci(cmd, NULL, value);
+}
+
+static int set_neighbor_lac_ci_del(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+	parse_lac_ci(cmd, &n, cmd->value);
+	rc = neighbor_ident_del_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_lac_ci_del, "neighbor-lac-ci del");
+
+
+/* This and the following: Add/Remove a CGI as neighbor */
+static int parse_cgi(void *ctx, struct neighbor *n, const char *value)
+{
+	char *tmp = NULL, *tok, *saveptr;
+	int rc = 0;
+	uint16_t mcc;
+	uint16_t mnc;	
+	bool mnc_3_digits;	
+	int lac;
+	int ci;
+	
+	if (n)
+		memset(n, 0, sizeof(*n));
+	
+	tmp = talloc_strdup(ctx, value);
+	if (!tmp)
+		return 1;
+
+	/* Parse MCC */
+	tok = strtok_r(tmp, "-", &saveptr);
+	if (tok) {
+		if (osmo_mcc_from_str(tok, &mcc)) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}
+
+	/* Parse MNC */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_mnc_from_str(tok, &mnc, &mnc_3_digits)) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}	
+
+	/* Parse LAC */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&lac, tok, 10, 0, 65535) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}
+
+	/* Parse CI */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&ci, tok, 10, 0, 65535) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}	
+	
+	/* Optional parameters: ARFCN and BSIC */
+	if(continue_parse_arfcn_and_bsic(&saveptr, n)) {
+		rc = 1;
+		goto exit;
+	}
+
+	if (n) {
+		n->type = NEIGHBOR_TYPE_CELL_ID;
+		n->cell_id.id.id_discr = CELL_IDENT_WHOLE_GLOBAL;
+		n->cell_id.id.id.global.lai.lac = lac;
+		n->cell_id.id.id.global.lai.plmn.mcc = mcc;
+		n->cell_id.id.id.global.lai.plmn.mnc = mnc;
+		n->cell_id.id.id.global.lai.plmn.mnc_3_digits = mnc_3_digits;
+		n->cell_id.id.id.global.cell_identity = ci;
+	}
+	
+exit:
+	talloc_free(tmp);
+	return rc;
+}
+
+static int verify_neighbor_cgi_add(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return parse_cgi(cmd, NULL, value);
+}
+
+static int set_neighbor_cgi_add(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+
+	parse_cgi(cmd, &n, cmd->value);
+	rc = neighbor_ident_add_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_cgi_add, "neighbor-cgi add");
+
+static int verify_neighbor_cgi_del(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return  parse_cgi(cmd, NULL, value);
+}
+
+static int set_neighbor_cgi_del(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+	parse_cgi(cmd, &n, cmd->value);
+	rc = neighbor_ident_del_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_cgi_del, "neighbor-cgi del");
+
+
+/* This and the following: Add/Remove a CGI-PS as neighbor */
+static int parse_cgi_ps(void *ctx, struct neighbor *n, const char *value)
+{
+	char *tmp = NULL, *tok, *saveptr;
+	int rc = 0;
+	uint16_t mcc;
+	uint16_t mnc;	
+	bool mnc_3_digits;	
+	int lac;
+	int rac;	
+	int ci;
+	
+	if (n)
+		memset(n, 0, sizeof(*n));
+	
+	tmp = talloc_strdup(ctx, value);
+	if (!tmp)
+		return 1;
+
+	/* Parse MCC */
+	tok = strtok_r(tmp, "-", &saveptr);
+	if (tok) {
+		if (osmo_mcc_from_str(tok, &mcc)) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}
+
+	/* Parse MNC */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_mnc_from_str(tok, &mnc, &mnc_3_digits)) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}	
+
+	/* Parse LAC */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&lac, tok, 10, 0, 65535) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}
+
+	/* Parse RAC */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&rac, tok, 10, 0, 255) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}
+
+	/* Parse CI */
+	tok = strtok_r(NULL, "-", &saveptr);
+	if (tok) {
+		if (osmo_str_to_int(&ci, tok, 10, 0, 65535) < 0) {
+			rc = 1;
+			goto exit;
+		}
+	} else {
+		rc = 1;
+		goto exit;
+	}	
+	
+	/* Optional parameters: ARFCN and BSIC */
+	if(continue_parse_arfcn_and_bsic(&saveptr, n)) {
+		rc = 1;
+		goto exit;
+	}
+
+	if (n) {
+		n->type = NEIGHBOR_TYPE_CELL_ID;
+		n->cell_id.id.id_discr = CELL_IDENT_WHOLE_GLOBAL_PS;
+		n->cell_id.id.id.global_ps.rai.lac.lac = lac;
+		n->cell_id.id.id.global_ps.rai.rac = lac;		
+		n->cell_id.id.id.global_ps.rai.lac.plmn.mcc = mcc;
+		n->cell_id.id.id.global_ps.rai.lac.plmn.mnc = mnc;
+		n->cell_id.id.id.global_ps.rai.lac.plmn.mnc_3_digits = mnc_3_digits;
+		n->cell_id.id.id.global_ps.cell_identity = ci;
+	}
+	
+exit:
+	talloc_free(tmp);
+	return rc;
+}
+
+static int verify_neighbor_cgi_ps_add(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return parse_cgi_ps(cmd, NULL, value);
+}
+
+static int set_neighbor_cgi_ps_add(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+
+	parse_cgi_ps(cmd, &n, cmd->value);
+	rc = neighbor_ident_add_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_cgi_ps_add, "neighbor-cgi-ps add");
+
+static int verify_neighbor_cgi_ps_del(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+	return  parse_cgi_ps(cmd, NULL, value);
+}
+
+static int set_neighbor_cgi_ps_del(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;
+	int rc;
+
+	struct neighbor n;
+	parse_cgi_ps(cmd, &n, cmd->value);
+	rc = neighbor_ident_del_neighbor(NULL, bts, &n);
+	if (rc != CMD_SUCCESS)
+		return CTRL_CMD_ERROR;
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO(neighbor_cgi_ps_del, "neighbor-cgi-ps del");
+
+
+/* This and the following: clear all neighbor cell information */
+static int set_neighbor_clear(struct ctrl_cmd *cmd, void *data)
+{
+	struct gsm_bts *bts = cmd->node;	
+	struct neighbor *neighbor;
+	struct neighbor *neighbor_tmp;
+
+        llist_for_each_entry_safe(neighbor, neighbor_tmp, &bts->neighbors, entry) {
+		llist_del(&neighbor->entry);
+		talloc_free(neighbor);
+	}
+
+	cmd->reply = "OK";
+	return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_WO_NOVRF(neighbor_clear, "neighbor-clear");
+
+
+/* Register control interface commands implemented above */
+int neighbor_ident_ctrl_init(void)
+{
+	int rc = 0;
+
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_bts_add);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_bts_del);	
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_lac_add);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_lac_del);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_lac_ci_add);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_lac_ci_del);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_cgi_add);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_cgi_del);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_cgi_ps_add);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_cgi_ps_del);
+	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_neighbor_clear);
+
+	return rc;
+}
diff --git a/src/osmo-bsc/neighbor_ident_vty.c b/src/osmo-bsc/neighbor_ident_vty.c
index b500b34..9630b10 100644
--- a/src/osmo-bsc/neighbor_ident_vty.c
+++ b/src/osmo-bsc/neighbor_ident_vty.c
@@ -146,23 +146,32 @@
 	};
 }
 
-static int add_neighbor(struct vty *vty, struct neighbor *n)
+#define LOGPORVTY(vty, fmt, args...) \
+{ \
+	if (vty) \
+		vty_out(vty, "%% " fmt "%s", ## args, VTY_NEWLINE); \
+	else \
+		LOGP(DLINP, LOGL_NOTICE, fmt "\n", ## args); \
+} while(0) \
+
+/* Delete a neighbor from neighborlist. When the parameter *vty is set to NULL all error messages are redirected to the
+ * logtext. */
+int neighbor_ident_add_neighbor(struct vty *vty, struct gsm_bts *bts, struct neighbor *n)
 {
-	struct gsm_bts *bts = vty->index;
 	struct neighbor *neighbor;
 
-	OSMO_ASSERT((vty->node == BTS_NODE) && bts);
+	OSMO_ASSERT(bts);
+	OSMO_ASSERT(!vty || (vty->node == BTS_NODE));
 
 	llist_for_each_entry(neighbor, &bts->neighbors, entry) {
 		/* Check against duplicates */
 		if (neighbor_same(neighbor, n, false)) {
 			/* Found a match on Cell ID or BTS number, without ARFCN+BSIC. If they are fully identical, ignore the
 			 * duplicate. If the ARFCN+BSIC part differs, it's an error. */
-			vty_out(vty, "%% BTS %u already had neighbor %s%s", bts->nr, neighbor_to_str_c(OTC_SELECT, neighbor),
-				VTY_NEWLINE);
+			LOGPORVTY(vty, "BTS %u already had neighbor %s", bts->nr, neighbor_to_str_c(OTC_SELECT, neighbor));
 			if (!neighbor_same(neighbor, n, true)) {
-				vty_out(vty, "%% ERROR: duplicate Cell ID in neighbor config, with differing ARFCN+BSIC: %s%s",
-					neighbor_to_str_c(OTC_SELECT, n), VTY_NEWLINE);
+				LOGPORVTY(vty, "ERROR: duplicate Cell ID in neighbor config, with differing ARFCN+BSIC: %s",
+					neighbor_to_str_c(OTC_SELECT, n));
 				return CMD_WARNING;
 			}
 			/* Exact same neighbor again, just ignore. */
@@ -173,9 +182,9 @@
 		if (n->type == NEIGHBOR_TYPE_CELL_ID
 		    && n->cell_id.ab_present && neighbor->cell_id.ab_present
 		    && cell_ab_match(&n->cell_id.ab, &neighbor->cell_id.ab, true)) {
-			vty_out(vty, "%% Error: only one Cell Identifier entry is allowed per remote neighbor."
-				" Already have: BTS %u -> %s%s", bts->nr,
-				neighbor_to_str_c(OTC_SELECT, neighbor), VTY_NEWLINE);
+			LOGPORVTY(vty, "Error: only one Cell Identifier entry is allowed per remote neighbor."
+				" Already have: BTS %u -> %s", bts->nr,
+				neighbor_to_str_c(OTC_SELECT, neighbor));
 			return CMD_WARNING;
 		}
 	}
@@ -186,12 +195,14 @@
 	return CMD_SUCCESS;
 }
 
-static int del_neighbor(struct vty *vty, struct neighbor *n)
+/* Delete a neighbor from neighborlist. When the parameter *vty is set to NULL all error messages are redirected to the
+ * logtext. */
+int neighbor_ident_del_neighbor(struct vty *vty, struct gsm_bts *bts, struct neighbor *n)
 {
-	struct gsm_bts *bts = vty->index;
 	struct neighbor *neighbor;
 
-	OSMO_ASSERT((vty->node == BTS_NODE) && bts);
+	OSMO_ASSERT(bts);
+	OSMO_ASSERT(!vty || (vty->node == BTS_NODE));
 
 	llist_for_each_entry(neighbor, &bts->neighbors, entry) {
 		if (neighbor->type != n->type)
@@ -216,8 +227,8 @@
 		return CMD_SUCCESS;
 	}
 
-	vty_out(vty, "%% Error: no such neighbor on BTS %d: %s%s",
-		bts->nr, neighbor_to_str_c(OTC_SELECT, n), VTY_NEWLINE);
+	LOGPORVTY(vty, "%% Error: no such neighbor on BTS %d: %s",
+		  bts->nr, neighbor_to_str_c(OTC_SELECT, n));
 	return CMD_WARNING;
 }
 
@@ -271,7 +282,7 @@
 		.type = NEIGHBOR_TYPE_BTS_NR,
 		.bts_nr = atoi(argv[0]),
 	};
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_add_lac, cfg_neighbor_add_lac_cmd,
@@ -283,7 +294,7 @@
 	};
 	if (neighbor_ident_vty_parse_lac(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_add_lac_ci, cfg_neighbor_add_lac_ci_cmd,
@@ -295,7 +306,7 @@
 	};
 	if (neighbor_ident_vty_parse_lac_ci(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_add_cgi, cfg_neighbor_add_cgi_cmd,
@@ -307,7 +318,7 @@
 	};
 	if (neighbor_ident_vty_parse_cgi(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_add_cgi_ps, cfg_neighbor_add_cgi_ps_cmd,
@@ -319,7 +330,7 @@
 	};
 	if (neighbor_ident_vty_parse_cgi_ps(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 static int neighbor_del_all(struct vty *vty)
@@ -354,7 +365,7 @@
 	if (neighbor_ident_vty_parse_lac(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
 	neighbor_ident_vty_parse_arfcn_bsic(&n.cell_id.ab, argv + LAC_ARGC);
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_add_lac_ci_arfcn_bsic, cfg_neighbor_add_lac_ci_arfcn_bsic_cmd,
@@ -368,7 +379,7 @@
 	if (neighbor_ident_vty_parse_lac_ci(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
 	neighbor_ident_vty_parse_arfcn_bsic(&n.cell_id.ab, argv + LAC_CI_ARGC);
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_add_cgi_arfcn_bsic, cfg_neighbor_add_cgi_arfcn_bsic_cmd,
@@ -382,7 +393,7 @@
 	if (neighbor_ident_vty_parse_cgi(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
 	neighbor_ident_vty_parse_arfcn_bsic(&n.cell_id.ab, argv + CGI_ARGC);
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_add_cgi_ps_arfcn_bsic, cfg_neighbor_add_cgi_ps_arfcn_bsic_cmd,
@@ -396,7 +407,7 @@
 	if (neighbor_ident_vty_parse_cgi_ps(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
 	neighbor_ident_vty_parse_arfcn_bsic(&n.cell_id.ab, argv + CGI_PS_ARGC);
-	return add_neighbor(vty, &n);
+	return neighbor_ident_add_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_del_bts_nr, cfg_neighbor_del_bts_nr_cmd,
@@ -407,7 +418,7 @@
 		.type = NEIGHBOR_TYPE_BTS_NR,
 		.bts_nr = atoi(argv[0]),
 	};
-	return del_neighbor(vty, &n);
+	return neighbor_ident_del_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_del_lac, cfg_neighbor_del_lac_cmd,
@@ -419,7 +430,7 @@
 	};
 	if (neighbor_ident_vty_parse_lac(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return del_neighbor(vty, &n);
+	return neighbor_ident_del_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_del_lac_ci, cfg_neighbor_del_lac_ci_cmd,
@@ -431,7 +442,7 @@
 	};
 	if (neighbor_ident_vty_parse_lac_ci(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return del_neighbor(vty, &n);
+	return neighbor_ident_del_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_del_cgi, cfg_neighbor_del_cgi_cmd,
@@ -443,7 +454,7 @@
 	};
 	if (neighbor_ident_vty_parse_cgi(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return del_neighbor(vty, &n);
+	return neighbor_ident_del_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_del_cgi_ps, cfg_neighbor_del_cgi_ps_cmd,
@@ -455,7 +466,7 @@
 	};
 	if (neighbor_ident_vty_parse_cgi_ps(vty, &n.cell_id.id, argv))
 		return CMD_WARNING;
-	return del_neighbor(vty, &n);
+	return neighbor_ident_del_neighbor(vty, vty->index, &n);
 }
 
 DEFUN(cfg_neighbor_del_arfcn_bsic, cfg_neighbor_del_arfcn_bsic_cmd,

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/25976
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I343a40e18fa9b91e6c381912c0426a002841e079
Gerrit-Change-Number: 25976
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20211027/26336a1a/attachment.htm>


More information about the gerrit-log mailing list