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