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/.
Stefan Sperling gerrit-no-reply at lists.osmocom.orgStefan Sperling has uploaded this change for review. ( https://gerrit.osmocom.org/12446
Change subject: add BSC/MSC neighbor VTY commands for inter-MSC HO
......................................................................
add BSC/MSC neighbor VTY commands for inter-MSC HO
Allow configuration of neighbor BSC/MSC via osmo-msc.cfg
and the VTY.
Each neighbor is mapped to the list of identifiers of cells
which are reachable via that neighbor. A new neighbor_ident
API manages the neighbor list and supports mapping neighboring
BSCs/MSCs to cells, and vice versa.
Neighbours are managed with the following new VTY commands:
[no] neighbor lac <0-65535> bsc-pc POINT_CODE
[no] neighbor lac <0-65535> msc-ip-name IPA_NAME
[no] neighbor lac <0-65535> ci <0-999>bsc-pc POINT_CODE
[no] neighbor lac <0-65535> ci <0-999> msc-ip-name IPA_NAME
[no] neighbor cgi <0-999> <0-999> <0-65535> <0-65535> bsc-pc POINT_CODE
[no] neighbor cgi <0-999> <0-999> <0-65535> <0-65535> msc-ipa-name IPA_NAME
show neighbor all
show neighbor bsc-pc POINT_CODE
show neighbor msc-ipa-name IPA_NAME
Change-Id: Ia0dd08b087bfd4aa22e234917669d003150a4cd4
Depends: I5535f0d149c2173294538df75764dd181b023312
---
M include/osmocom/msc/Makefile.am
M include/osmocom/msc/gsm_data.h
A include/osmocom/msc/neighbor_ident.h
M src/libmsc/Makefile.am
M src/libmsc/msc_vty.c
A src/libmsc/neighbor_ident.c
A src/libmsc/neighbor_ident_vty.c
7 files changed, 700 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/46/12446/1
diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am
index d98bc9c..e821993 100644
--- a/include/osmocom/msc/Makefile.am
+++ b/include/osmocom/msc/Makefile.am
@@ -19,6 +19,7 @@
msc_common.h \
msc_ifaces.h \
msc_mgcp.h \
+ neighbor_ident.h \
a_reset.h \
ran_conn.h \
rrlp.h \
diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h
index d2511cb..8930380 100644
--- a/include/osmocom/msc/gsm_data.h
+++ b/include/osmocom/msc/gsm_data.h
@@ -16,6 +16,7 @@
#include <osmocom/mgcp_client/mgcp_client.h>
#include <osmocom/msc/msc_common.h>
+#include <osmocom/msc/neighbor_ident.h>
#include "gsm_data_shared.h"
@@ -208,6 +209,10 @@
struct osmo_sccp_instance *sccp;
} a;
+ /* A list of neighbor BSCs. This list is defined statically via VTY and does not
+ * necessarily correspond to BSCs attached to the A interface at a given moment. */
+ struct neighbor_ident_list *neighbor_list;
+
struct {
/* MSISDN to which to route MO emergency calls */
char *route_to_msisdn;
diff --git a/include/osmocom/msc/neighbor_ident.h b/include/osmocom/msc/neighbor_ident.h
new file mode 100644
index 0000000..d79d262
--- /dev/null
+++ b/include/osmocom/msc/neighbor_ident.h
@@ -0,0 +1,71 @@
+/* Manage identity of neighboring BSS cells for inter-BSC handover */
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/gsm0808.h>
+
+struct vty;
+struct gsm_network;
+
+enum msc_neighbor_type {
+ /* Neighboring BSC reachable via SCCP. */
+ MSC_NEIGHBOR_TYPE_BSC,
+
+ /* Neighboring MSC reachable via GSUP. */
+ MSC_NEIGHBOR_TYPE_MSC
+};
+
+struct neighbor_ident_addr {
+ enum msc_neighbor_type type;
+ union {
+ int point_code; /* BSC */
+ const char *ipa_name; /* MSC */
+ } a;
+};
+
+struct neighbor_ident_list {
+ struct llist_head list;
+};
+
+struct neighbor_ident {
+ struct llist_head entry;
+
+ /* Address of a neighboring BSC or MSC. */
+ struct neighbor_ident_addr addr;
+
+ /* IDs of cells in this neighbor's domain. */
+ struct gsm0808_cell_id_list2 cell_ids;
+};
+
+struct gsm0808_cell_id;
+struct gsm0808_cell_id_list2;
+
+const char *neighbor_ident_addr_name(struct gsm_network *net, const struct neighbor_ident_addr *ni_addr);
+
+struct neighbor_ident_list *neighbor_ident_init(void *talloc_ctx);
+void neighbor_ident_free(struct neighbor_ident_list *nil);
+
+bool neighbor_ident_addr_match(const struct neighbor_ident_addr *entry,
+ const struct neighbor_ident_addr *search_for,
+ bool exact_match);
+
+int neighbor_ident_add(struct neighbor_ident_list *nil, const struct neighbor_ident_addr *addr,
+ const struct gsm0808_cell_id_list2 *cell_ids);
+const struct gsm0808_cell_id_list2 *neighbor_ident_get(const struct neighbor_ident_list *nil,
+ const struct neighbor_ident_addr *addr);
+const struct neighbor_ident_addr *neighbor_ident_lookup_cell(const struct neighbor_ident_list *nil,
+ struct gsm0808_cell_id *cell_id);
+bool neighbor_ident_del(struct neighbor_ident_list *nil, const struct neighbor_ident_addr *addr);
+void neighbor_ident_clear(struct neighbor_ident_list *nil);
+
+void neighbor_ident_iter(const struct neighbor_ident_list *nil,
+ bool (* iter_cb )(const struct neighbor_ident_addr *addr,
+ const struct gsm0808_cell_id_list2 *cell_ids,
+ void *cb_data),
+ void *cb_data);
+
+void neighbor_ident_vty_init(struct gsm_network *net);
+void neighbor_ident_vty_write(struct vty *vty);
diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am
index 9183ff9..f498001 100644
--- a/src/libmsc/Makefile.am
+++ b/src/libmsc/Makefile.am
@@ -44,6 +44,8 @@
mncc_sock.c \
msc_ifaces.c \
msc_mgcp.c \
+ neighbor_ident.c \
+ neighbor_ident_vty.c \
ran_conn.c \
rrlp.c \
silent_call.c \
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
index 7745e5d..1af42e4 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -1538,6 +1538,8 @@
#ifdef BUILD_IU
ranap_iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc);
#endif
+ neighbor_ident_vty_init(msc_network);
+
osmo_fsm_vty_add_cmds();
osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
diff --git a/src/libmsc/neighbor_ident.c b/src/libmsc/neighbor_ident.c
new file mode 100644
index 0000000..f7187a9
--- /dev/null
+++ b/src/libmsc/neighbor_ident.c
@@ -0,0 +1,206 @@
+/* Manage identity of neighboring BSS cells for inter-MSC handover. */
+/* (C) 2018 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <nhofmeyr at sysmocom.de>
+ * Author: Stefan Sperling <ssperling 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 <osmocom/core/linuxlist.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/sigtran/osmo_ss7.h>
+
+#include <osmocom/msc/neighbor_ident.h>
+#include <osmocom/msc/gsm_data.h>
+
+/* XXX greater than or equal to IPA_STIRNG_MAX (libosmocore) and MAX_PC_STR_LEN (libosmo-sccp). */
+#define NEIGHBOR_IDENT_ADDR_STRING_MAX 64
+
+const char *neighbor_ident_addr_name(struct gsm_network *net, const struct neighbor_ident_addr *na)
+{
+ static char buf[NEIGHBOR_IDENT_ADDR_STRING_MAX + 4];
+ struct osmo_ss7_instance *ss7;
+
+ switch (na->type) {
+ case MSC_NEIGHBOR_TYPE_BSC:
+ ss7 = osmo_ss7_instance_find(net->a.cs7_instance);
+ OSMO_ASSERT(ss7);
+ snprintf(buf, sizeof(buf), "BSC %s", osmo_ss7_pointcode_print(ss7, na->a.point_code));
+ break;
+ case MSC_NEIGHBOR_TYPE_MSC:
+ snprintf(buf, sizeof(buf), "MSC %s", na->a.ipa_name);
+ break;
+ default:
+ return NULL;
+ }
+
+ return buf;
+}
+
+struct neighbor_ident_list *neighbor_ident_init(void *talloc_ctx)
+{
+ struct neighbor_ident_list *nil = talloc_zero(talloc_ctx, struct neighbor_ident_list);
+ OSMO_ASSERT(nil);
+ INIT_LLIST_HEAD(&nil->list);
+ return nil;
+}
+
+void neighbor_ident_free(struct neighbor_ident_list *nil)
+{
+ if (!nil)
+ return;
+ talloc_free(nil);
+}
+
+static struct neighbor_ident *_neighbor_ident_get(const struct neighbor_ident_list *nil,
+ const struct neighbor_ident_addr *na)
+{
+ struct neighbor_ident *ni;
+
+ llist_for_each_entry(ni, &nil->list, entry) {
+ if (na->type != ni->addr.type)
+ continue;
+
+ switch (na->type) {
+ case MSC_NEIGHBOR_TYPE_BSC:
+ if (ni->addr.a.point_code == na->a.point_code)
+ return ni;
+ break;
+ case MSC_NEIGHBOR_TYPE_MSC:
+ if (strcmp(ni->addr.a.ipa_name, na->a.ipa_name) == 0)
+ return ni;
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static void _neighbor_ident_free(struct neighbor_ident *ni)
+{
+ llist_del(&ni->entry);
+ talloc_free(ni);
+}
+
+/*! Add Cell Identifiers to a neighbor BSC/MSC entry.
+ * Exactly one kind of identifier is allowed per entry, and any number of entries of that kind
+ * may be added up to the capacity of gsm0808_cell_id_list2, by one or more calls to this function. To
+ * replace an existing entry, first call neighbor_ident_del(nil, cell_id).
+ * \returns number of entries in the resulting identifier list, or negative on error:
+ * see gsm0808_cell_id_list_add() for the meaning of returned error codes;
+ * return -ENOMEM when the list is not initialized, -ERANGE when the BSIC value is too large. */
+int neighbor_ident_add(struct neighbor_ident_list *nil, const struct neighbor_ident_addr *addr,
+ const struct gsm0808_cell_id_list2 *cell_id)
+{
+ struct neighbor_ident *ni;
+ int rc;
+
+ if (!nil)
+ return -ENOMEM;
+
+ ni = _neighbor_ident_get(nil, addr);
+ if (!ni) {
+ ni = talloc_zero(nil, struct neighbor_ident);
+ OSMO_ASSERT(ni);
+ ni->addr.type = addr->type;
+ switch (ni->addr.type) {
+ case MSC_NEIGHBOR_TYPE_MSC:
+ ni->addr.a.ipa_name = talloc_strdup(ni, addr->a.ipa_name);
+ break;
+ case MSC_NEIGHBOR_TYPE_BSC:
+ ni->addr.a.point_code = addr->a.point_code;
+ break;
+ }
+ llist_add_tail(&ni->entry, &nil->list);
+ }
+
+ rc = gsm0808_cell_id_list_add(&ni->cell_ids, cell_id);
+ if (rc < 0)
+ return rc;
+
+ return ni->cell_ids.id_list_len;
+}
+
+/*! Find cell identity for given BSC or MSC, as previously added by neighbor_ident_add().
+ */
+const struct gsm0808_cell_id_list2 *neighbor_ident_get(const struct neighbor_ident_list *nil,
+ const struct neighbor_ident_addr *addr)
+{
+ struct neighbor_ident *ni;
+ if (!nil)
+ return NULL;
+ ni = _neighbor_ident_get(nil, addr);
+ if (!ni)
+ return NULL;
+ return &ni->cell_ids;
+}
+
+/*! Find a BSC or MSC, as previously added by neighbor_ident_add(), for a given cell identity.
+ */
+const struct neighbor_ident_addr *neighbor_ident_lookup_cell(const struct neighbor_ident_list *nil,
+ struct gsm0808_cell_id *cell_id)
+{
+ struct neighbor_ident *ni;
+ if (!nil)
+ return NULL;
+ llist_for_each_entry(ni, &nil->list, entry) {
+ if (gsm0808_cell_id_matches_list(cell_id, &ni->cell_ids, 0))
+ return &ni->addr;
+ }
+
+ return NULL;
+}
+
+bool neighbor_ident_del(struct neighbor_ident_list *nil, const struct neighbor_ident_addr *addr)
+{
+ struct neighbor_ident *ni;
+ if (!nil)
+ return false;
+ ni = _neighbor_ident_get(nil, addr);
+ if (!ni)
+ return false;
+ _neighbor_ident_free(ni);
+ return true;
+}
+
+void neighbor_ident_clear(struct neighbor_ident_list *nil)
+{
+ struct neighbor_ident *ni;
+ while ((ni = llist_first_entry_or_null(&nil->list, struct neighbor_ident, entry)))
+ _neighbor_ident_free(ni);
+}
+
+/*! Iterate all neighbor_ident_list entries and call iter_cb for each.
+ * If iter_cb returns false, the iteration is stopped. */
+void neighbor_ident_iter(const struct neighbor_ident_list *nil,
+ bool (* iter_cb )(const struct neighbor_ident_addr *addr,
+ const struct gsm0808_cell_id_list2 *cell_ids,
+ void *cb_data),
+ void *cb_data)
+{
+ struct neighbor_ident *ni, *ni_next;
+ if (!nil)
+ return;
+ llist_for_each_entry_safe(ni, ni_next, &nil->list, entry) {
+ if (!iter_cb(&ni->addr, &ni->cell_ids, cb_data))
+ return;
+ }
+}
diff --git a/src/libmsc/neighbor_ident_vty.c b/src/libmsc/neighbor_ident_vty.c
new file mode 100644
index 0000000..a44a284
--- /dev/null
+++ b/src/libmsc/neighbor_ident_vty.c
@@ -0,0 +1,413 @@
+/* Quagga VTY implementation to manage identity of neighboring BSS cells for inter-BSC handover. */
+/* (C) 2018 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <nhofmeyr at sysmocom.de>
+ * Author: Stefan Sperling <ssperling 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <osmocom/vty/command.h>
+#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/sigtran/osmo_ss7.h>
+
+#include <osmocom/msc/vty.h>
+#include <osmocom/msc/neighbor_ident.h>
+#include <osmocom/msc/gsm_data.h>
+
+#define NEIGHBOR_ADD_CMD "neighbor "
+#define NEIGHBOR_DEL_CMD "no neighbor "
+#define NEIGHBOR_SHOW_CMD "show neighbor "
+#define NEIGHBOR_DOC "Manage neighbor BSS cells\n"
+#define NEIGHBOR_ADD_DOC NEIGHBOR_DOC "Add "
+#define NEIGHBOR_DEL_DOC NO_STR "Remove neighbor BSS cell\n"
+
+#define LAC_PARAMS "lac <0-65535>"
+#define LAC_DOC "Neighbor cell by LAC\n" "LAC\n"
+
+#define LAC_CI_PARAMS "lac-ci <0-65535> <0-65535>"
+#define LAC_CI_DOC "Neighbor cell by LAC and CI\n" "LAC\n" "CI\n"
+
+#define CGI_PARAMS "cgi <0-999> <0-999> <0-65535> <0-65535>"
+#define CGI_DOC "Neighbor cell by cgi\n" "MCC\n" "MNC\n" "LAC\n" "CI\n"
+
+#define NEIGHBOR_IDENT_VTY_BSC_ADDR_PARAMS "bsc-pc POINT_CODE"
+#define NEIGHBOR_IDENT_VTY_BSC_ADDR_DOC "Point code of neighbor BSC\n" "Point code value\n"
+#define NEIGHBOR_IDENT_VTY_MSC_ADDR_PARAMS "msc-ipa-name IPA_NAME"
+#define NEIGHBOR_IDENT_VTY_MSC_ADDR_DOC "IPA name of neighbor MSC\n" "IPA name value\n"
+
+static struct gsm_network *g_net = NULL;
+
+static struct gsm0808_cell_id *neighbor_ident_vty_parse_lac(struct vty *vty, const char **argv)
+{
+ static struct gsm0808_cell_id cell_id;
+ cell_id = (struct gsm0808_cell_id){
+ .id_discr = CELL_IDENT_LAC,
+ .id.lac = atoi(argv[0]),
+ };
+ return &cell_id;
+}
+
+static struct gsm0808_cell_id *neighbor_ident_vty_parse_lac_ci(struct vty *vty, const char **argv)
+{
+ static struct gsm0808_cell_id cell_id;
+ cell_id = (struct gsm0808_cell_id){
+ .id_discr = CELL_IDENT_LAC_AND_CI,
+ .id.lac_and_ci = {
+ .lac = atoi(argv[0]),
+ .ci = atoi(argv[1]),
+ },
+ };
+ return &cell_id;
+}
+
+static struct gsm0808_cell_id *neighbor_ident_vty_parse_cgi(struct vty *vty, const char **argv)
+{
+ static struct gsm0808_cell_id cell_id;
+ cell_id = (struct gsm0808_cell_id){
+ .id_discr = CELL_IDENT_WHOLE_GLOBAL,
+ };
+ struct osmo_cell_global_id *cgi = &cell_id.id.global;
+ const char *mcc = argv[0];
+ const char *mnc = argv[1];
+ const char *lac = argv[2];
+ const char *ci = argv[3];
+
+ if (osmo_mcc_from_str(mcc, &cgi->lai.plmn.mcc)) {
+ vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
+ return NULL;
+ }
+
+ if (osmo_mnc_from_str(mnc, &cgi->lai.plmn.mnc, &cgi->lai.plmn.mnc_3_digits)) {
+ vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
+ return NULL;
+ }
+
+ cgi->lai.lac = atoi(lac);
+ cgi->cell_identity = atoi(ci);
+ return &cell_id;
+}
+
+static int add_neighbor(struct vty *vty, struct neighbor_ident_addr *addr, const struct gsm0808_cell_id *cell_id)
+{
+ struct gsm0808_cell_id_list2 cell_ids;
+ int rc;
+
+ gsm0808_cell_id_to_list(&cell_ids, cell_id);
+ rc = neighbor_ident_add(g_net->neighbor_list, addr, &cell_ids);
+ if (rc < 0) {
+ vty_out(vty, "%% Error: cannot add cell %s to neighbor %s: %s%s",
+ gsm0808_cell_id_name(cell_id), neighbor_ident_addr_name(g_net, addr),
+ strerror(-rc), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ return CMD_SUCCESS;
+}
+
+static int parse_point_code(const char *point_code_str)
+{
+ struct osmo_ss7_instance *ss7 = osmo_ss7_instance_find(g_net->a.cs7_instance);
+ OSMO_ASSERT(ss7);
+ return osmo_ss7_pointcode_parse(ss7, point_code_str);
+}
+
+DEFUN(cfg_neighbor_add_lac_bsc, cfg_neighbor_add_lac_bsc_cmd,
+ NEIGHBOR_ADD_CMD LAC_PARAMS " " NEIGHBOR_IDENT_VTY_BSC_ADDR_PARAMS,
+ NEIGHBOR_ADD_DOC LAC_DOC " " NEIGHBOR_IDENT_VTY_BSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+ int point_code = parse_point_code(argv[1]);
+
+ if (point_code < 0) {
+ vty_out(vty, "Could not parse point code '%s'%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ addr.type = MSC_NEIGHBOR_TYPE_BSC;
+ addr.a.point_code = point_code;
+ return add_neighbor(vty, &addr, neighbor_ident_vty_parse_lac(vty, argv + 1));
+}
+
+DEFUN(cfg_neighbor_add_lac_msc, cfg_neighbor_add_lac_msc_cmd,
+ NEIGHBOR_ADD_CMD LAC_PARAMS " " NEIGHBOR_IDENT_VTY_MSC_ADDR_PARAMS,
+ NEIGHBOR_ADD_DOC LAC_DOC " " NEIGHBOR_IDENT_VTY_MSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+
+ addr.type = MSC_NEIGHBOR_TYPE_MSC;
+ addr.a.ipa_name = argv[1];
+ return add_neighbor(vty, &addr, neighbor_ident_vty_parse_lac(vty, argv + 1));
+}
+
+DEFUN(cfg_neighbor_add_lac_ci_bsc, cfg_neighbor_add_lac_ci_bsc_cmd,
+ NEIGHBOR_ADD_CMD LAC_CI_PARAMS " " NEIGHBOR_IDENT_VTY_BSC_ADDR_PARAMS,
+ NEIGHBOR_ADD_DOC LAC_CI_DOC " " NEIGHBOR_IDENT_VTY_BSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+ int point_code = parse_point_code(argv[2]);
+
+ if (point_code < 0) {
+ vty_out(vty, "Could not parse point code '%s'%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ addr.type = MSC_NEIGHBOR_TYPE_BSC;
+ addr.a.point_code = point_code;
+ return add_neighbor(vty, &addr, neighbor_ident_vty_parse_lac_ci(vty, argv + 1));
+}
+
+DEFUN(cfg_neighbor_add_lac_ci_msc, cfg_neighbor_add_lac_ci_msc_cmd,
+ NEIGHBOR_ADD_CMD LAC_CI_PARAMS " " NEIGHBOR_IDENT_VTY_MSC_ADDR_PARAMS,
+ NEIGHBOR_ADD_DOC LAC_CI_DOC " " NEIGHBOR_IDENT_VTY_MSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+
+ addr.type = MSC_NEIGHBOR_TYPE_MSC;
+ addr.a.ipa_name = argv[2];
+ return add_neighbor(vty, &addr, neighbor_ident_vty_parse_lac_ci(vty, argv + 1));
+}
+
+DEFUN(cfg_neighbor_add_cgi_bsc, cfg_neighbor_add_cgi_bsc_cmd,
+ NEIGHBOR_ADD_CMD CGI_PARAMS " " NEIGHBOR_IDENT_VTY_BSC_ADDR_PARAMS,
+ NEIGHBOR_ADD_DOC CGI_DOC " " NEIGHBOR_IDENT_VTY_BSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+ int point_code = parse_point_code(argv[4]);
+
+ if (point_code < 0) {
+ vty_out(vty, "Could not parse point code '%s'%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ addr.type = MSC_NEIGHBOR_TYPE_BSC;
+ addr.a.point_code = point_code;
+ return add_neighbor(vty, &addr, neighbor_ident_vty_parse_cgi(vty, argv + 1));
+}
+
+DEFUN(cfg_neighbor_add_cgi_msc, cfg_neighbor_add_cgi_msc_cmd,
+ NEIGHBOR_ADD_CMD CGI_PARAMS " " NEIGHBOR_IDENT_VTY_MSC_ADDR_PARAMS,
+ NEIGHBOR_ADD_DOC CGI_DOC " " NEIGHBOR_IDENT_VTY_MSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+
+ addr.type = MSC_NEIGHBOR_TYPE_MSC;
+ addr.a.ipa_name = argv[4];
+ return add_neighbor(vty, &addr, neighbor_ident_vty_parse_cgi(vty, argv + 1));
+}
+
+static int del_by_addr(struct vty *vty, const struct neighbor_ident_addr *addr)
+{
+ int removed = 0;
+
+ if (vty->node != MSC_NODE) {
+ vty_out(vty, "%% Error: cannot remove neighbor, not on MSC node%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (neighbor_ident_del(g_net->neighbor_list, addr)) {
+ vty_out(vty, "%% Removed neighbor %s%s",
+ neighbor_ident_addr_name(g_net, addr), VTY_NEWLINE);
+ removed = 1;
+ }
+
+ if (!removed) {
+ vty_out(vty, "%% Cannot remove, no such neighbor: %s%s",
+ neighbor_ident_addr_name(g_net, addr), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_del_neighbor_bsc, cfg_del_neighbor_bsc_cmd,
+ NEIGHBOR_DEL_CMD NEIGHBOR_IDENT_VTY_BSC_ADDR_PARAMS,
+ SHOW_STR "Delete a neighbor BSC\n" "BSC point code\n"
+ "Delete a specified neighbor BSC\n"
+ NEIGHBOR_IDENT_VTY_BSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+ int point_code = parse_point_code(argv[0]);
+
+ if (point_code < 0) {
+ vty_out(vty, "Could not parse point code '%s'%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ addr.type = MSC_NEIGHBOR_TYPE_BSC;
+ addr.a.point_code = point_code;
+ return del_by_addr(vty, &addr);
+}
+
+DEFUN(cfg_del_neighbor_msc, cfg_del_neighbor_msc_cmd,
+ NEIGHBOR_DEL_CMD NEIGHBOR_IDENT_VTY_MSC_ADDR_PARAMS,
+ SHOW_STR "Delete a neighbor MSC\n" "MSC ipa-nam\n"
+ "Delete a specified neighbor MSC\n"
+ NEIGHBOR_IDENT_VTY_MSC_ADDR_DOC)
+{
+ struct neighbor_ident_addr addr;
+
+ addr.type = MSC_NEIGHBOR_TYPE_MSC;
+ addr.a.ipa_name = argv[0];
+ return del_by_addr(vty, &addr);
+}
+
+static void write_neighbor_ident(struct vty *vty, const struct neighbor_ident *ni)
+{
+ const struct neighbor_ident_addr *addr = &ni->addr;
+ const struct gsm0808_cell_id_list2 *cell_ids = &ni->cell_ids;
+ struct osmo_ss7_instance *ss7;
+ int i;
+
+ switch (cell_ids->id_discr) {
+ case CELL_IDENT_LAC:
+ for (i = 0; i < cell_ids->id_list_len; i++) {
+ vty_out(vty, " neighbor lac %u", cell_ids->id_list[i].lac);
+ }
+ break;
+ case CELL_IDENT_LAC_AND_CI:
+ for (i = 0; i < cell_ids->id_list_len; i++) {
+ vty_out(vty, " neighbor lac-ci %u %u", cell_ids->id_list[i].lac_and_ci.lac,
+ cell_ids->id_list[i].lac_and_ci.ci);
+ }
+ break;
+ case CELL_IDENT_WHOLE_GLOBAL:
+ for (i = 0; i < cell_ids->id_list_len; i++) {
+ const struct osmo_cell_global_id *cgi = &cell_ids->id_list[i].global;
+ vty_out(vty, " neighbor cgi %s %s %u %u", osmo_mcc_name(cgi->lai.plmn.mcc),
+ osmo_mnc_name(cgi->lai.plmn.mnc, cgi->lai.plmn.mnc_3_digits),
+ cgi->lai.lac, cgi->cell_identity);
+ }
+ break;
+ default:
+ vty_out(vty, "%% Unsupported Cell Identity%s", VTY_NEWLINE);
+ return;
+ }
+
+ switch (ni->addr.type) {
+ case MSC_NEIGHBOR_TYPE_BSC:
+ ss7 = osmo_ss7_instance_find(g_net->a.cs7_instance);
+ OSMO_ASSERT(ss7);
+ vty_out(vty, "bsc-pc %s%s", osmo_ss7_pointcode_print(ss7, addr->a.point_code), VTY_NEWLINE);
+ break;
+ case MSC_NEIGHBOR_TYPE_MSC:
+ vty_out(vty, "msc-ipa-name %s%s", addr->a.ipa_name, VTY_NEWLINE);
+ break;
+ }
+}
+
+void neighbor_ident_vty_write(struct vty *vty)
+{
+ const struct neighbor_ident *ni;
+
+ llist_for_each_entry(ni, &g_net->neighbor_list->list, entry)
+ write_neighbor_ident(vty, ni);
+}
+
+DEFUN(show_neighbor_all, show_neighbor_all_cmd,
+ NEIGHBOR_SHOW_CMD "all",
+ SHOW_STR "Display information about neighbor BSCs and MSCs\n"
+ "Show which cells are reachable via the neighbor BSCs and MSCs\n")
+{
+ struct neighbor_ident *ni;
+
+ llist_for_each_entry(ni, &g_net->neighbor_list->list, entry) {
+ vty_out(vty, "%s: %s%s", neighbor_ident_addr_name(g_net, &ni->addr),
+ gsm0808_cell_id_list_name(&ni->cell_ids), VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_neighbor_bsc, show_neighbor_bsc_cmd,
+ NEIGHBOR_SHOW_CMD NEIGHBOR_IDENT_VTY_BSC_ADDR_PARAMS,
+ SHOW_STR "Display information about a neighbor BSC\n" "BSC point code\n"
+ "Show which cells are reachable via the specified neighbor BSC\n"
+ NEIGHBOR_IDENT_VTY_BSC_ADDR_DOC)
+{
+ int point_code;
+ struct neighbor_ident *ni;
+ int found = 0;
+
+ point_code = parse_point_code(argv[0]);
+ if (point_code < 0) {
+ vty_out(vty, "Could not parse point code '%s'%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ llist_for_each_entry(ni, &g_net->neighbor_list->list, entry) {
+ if (ni->addr.type != MSC_NEIGHBOR_TYPE_BSC)
+ continue;
+ if (ni->addr.a.point_code == point_code) {
+ vty_out(vty, "%s%s", gsm0808_cell_id_list_name(&ni->cell_ids), VTY_NEWLINE);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ vty_out(vty, "%% No entry for %s%s", argv[0], VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_neighbor_msc, show_neighbor_msc_cmd,
+ NEIGHBOR_SHOW_CMD NEIGHBOR_IDENT_VTY_MSC_ADDR_PARAMS,
+ SHOW_STR "Display information about a neighbor MSC\n" "MSC ipa-name\n"
+ "Show which cells are reachable via the specified neighbor MSC\n"
+ NEIGHBOR_IDENT_VTY_MSC_ADDR_DOC)
+{
+ const char *ipa_name = argv[0];
+ struct neighbor_ident *ni;
+ int found = 0;
+
+ llist_for_each_entry(ni, &g_net->neighbor_list->list, entry) {
+ if (ni->addr.type != MSC_NEIGHBOR_TYPE_MSC)
+ continue;
+ if (strcmp(ni->addr.a.ipa_name, ipa_name) == 0) {
+ vty_out(vty, "%s%s", gsm0808_cell_id_list_name(&ni->cell_ids), VTY_NEWLINE);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ vty_out(vty, "%% No entry for %s%s", ipa_name, VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+void neighbor_ident_vty_init(struct gsm_network *net)
+{
+ g_net = net;
+ g_net->neighbor_list = neighbor_ident_init(net);
+
+ install_element(MSC_NODE, &cfg_neighbor_add_lac_bsc_cmd);
+ install_element(MSC_NODE, &cfg_neighbor_add_lac_msc_cmd);
+ install_element(MSC_NODE, &cfg_neighbor_add_lac_ci_bsc_cmd);
+ install_element(MSC_NODE, &cfg_neighbor_add_lac_ci_msc_cmd);
+ install_element(MSC_NODE, &cfg_neighbor_add_cgi_bsc_cmd);
+ install_element(MSC_NODE, &cfg_neighbor_add_cgi_msc_cmd);
+ install_element(MSC_NODE, &cfg_del_neighbor_bsc_cmd);
+ install_element(MSC_NODE, &cfg_del_neighbor_msc_cmd);
+ install_element_ve(&show_neighbor_all_cmd);
+ install_element_ve(&show_neighbor_bsc_cmd);
+ install_element_ve(&show_neighbor_msc_cmd);
+}
--
To view, visit https://gerrit.osmocom.org/12446
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia0dd08b087bfd4aa22e234917669d003150a4cd4
Gerrit-Change-Number: 12446
Gerrit-PatchSet: 1
Gerrit-Owner: Stefan Sperling <stsp at stsp.name>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20181229/272cf1c7/attachment.htm>