aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Sperling <ssperling@sysmocom.de>2018-12-26 16:36:02 +0100
committerStefan Sperling <ssperling@sysmocom.de>2018-12-28 13:26:19 +0100
commitab8821793fd1add03d32ff91f7cfc2696eea66ae (patch)
tree930c56717835d676ee6aff060d78182c29753600
parentc9029a62996bac557cc75b8513ebc7135038ab92 (diff)
basic conversion to MSC situation; vty parts still todostsp/neighbor_ident
-rw-r--r--include/osmocom/msc/Makefile.am2
-rw-r--r--include/osmocom/msc/gsm_data.h5
-rw-r--r--include/osmocom/msc/neighbor_ident.h75
-rw-r--r--src/libmsc/msc_vty.c2
-rw-r--r--src/libmsc/neighbor_ident.c203
-rw-r--r--src/libmsc/neighbor_ident_vty.c542
6 files changed, 285 insertions, 544 deletions
diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am
index c035a2d..e821993 100644
--- a/include/osmocom/msc/Makefile.am
+++ b/include/osmocom/msc/Makefile.am
@@ -19,7 +19,7 @@ noinst_HEADERS = \
msc_common.h \
msc_ifaces.h \
msc_mgcp.h \
- neighor_ident.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 gsm_network {
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
index 17bffbc..d79d262 100644
--- a/include/osmocom/msc/neighbor_ident.h
+++ b/include/osmocom/msc/neighbor_ident.h
@@ -5,54 +5,67 @@
#include <stdbool.h>
#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/gsm0808.h>
struct vty;
struct gsm_network;
-struct gsm_bts;
-struct neighbor_ident_list;
-struct gsm0808_cell_id_list2;
-#define NEIGHBOR_IDENT_KEY_ANY_BTS -1
+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;
-#define BSIC_ANY 0xff
+ /* Address of a neighboring BSC or MSC. */
+ struct neighbor_ident_addr addr;
-struct neighbor_ident_key {
- int from_bts; /*< BTS nr 0..255 or NEIGHBOR_IDENT_KEY_ANY_BTS */
- uint16_t arfcn;
- uint8_t bsic;
+ /* IDs of cells in this neighbor's domain. */
+ struct gsm0808_cell_id_list2 cell_ids;
};
-const char *neighbor_ident_key_name(const struct neighbor_ident_key *ni_key);
+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_key_match(const struct neighbor_ident_key *entry,
- const struct neighbor_ident_key *search_for,
- bool exact_match);
+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_key *key,
- const struct gsm0808_cell_id_list2 *val);
+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_key *key);
-bool neighbor_ident_del(struct neighbor_ident_list *nil, const struct neighbor_ident_key *key);
+ 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_key *key,
- const struct gsm0808_cell_id_list2 *val,
+ 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, struct neighbor_ident_list *nil);
-void neighbor_ident_vty_write(struct vty *vty, const char *indent, struct gsm_bts *bts);
-
-#define NEIGHBOR_IDENT_VTY_KEY_PARAMS "arfcn <0-1023> bsic (<0-63>|any)"
-#define NEIGHBOR_IDENT_VTY_KEY_DOC \
- "ARFCN of neighbor cell\n" "ARFCN value\n" \
- "BSIC of neighbor cell\n" "BSIC value\n" \
- "for all BSICs / use any BSIC in this ARFCN\n"
-bool neighbor_ident_vty_parse_key_params(struct vty *vty, const char **argv,
- struct neighbor_ident_key *key);
-bool neighbor_ident_bts_parse_key_params(struct vty *vty, struct gsm_bts *bts, const char **argv,
- struct neighbor_ident_key *key);
+void neighbor_ident_vty_init(struct gsm_network *net);
+void neighbor_ident_vty_write(struct vty *vty);
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 @@ void msc_vty_init(struct gsm_network *msc_network)
#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
index 4a0cd47..877b5e6 100644
--- a/src/libmsc/neighbor_ident.c
+++ b/src/libmsc/neighbor_ident.c
@@ -1,14 +1,10 @@
-/* Manage identity of neighboring BSS cells for inter-BSC handover.
- *
- * Measurement reports tell us about neighbor ARFCN and BSIC. If that ARFCN and BSIC is not managed by
- * this local BSS, we need to tell the MSC a cell identity, like CGI, LAC+CI, etc. -- hence we need a
- * mapping from ARFCN+BSIC to Cell Identifier List, which needs to be configured by the user.
- */
+/* Manage identity of neighboring BSS cells for inter-MSC handover. */
/* (C) 2018 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
+ * Author: Stefan Sperling <ssperling@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
@@ -30,54 +26,33 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/sigtran/osmo_ss7.h>
-#include <osmocom/bsc/neighbor_ident.h>
-
-struct neighbor_ident_list {
- struct llist_head list;
-};
+#include <osmocom/msc/neighbor_ident.h>
+#include <osmocom/msc/gsm_data.h>
-struct neighbor_ident {
- struct llist_head entry;
+/* XXX greater than or equal to IPA_STIRNG_MAX (libosmocore) and MAX_PC_STR_LEN (libosmo-sccp). */
+#define NEIGHBOR_IDENT_ADDR_STRING_MAX 64
- struct neighbor_ident_key key;
- struct gsm0808_cell_id_list2 val;
-};
-
-#define APPEND_THING(func, args...) do { \
- int remain = buflen - (pos - buf); \
- int l = func(pos, remain, ##args); \
- if (l < 0 || l > remain) \
- pos = buf + buflen; \
- else \
- pos += l; \
- } while(0)
-#define APPEND_STR(fmt, args...) APPEND_THING(snprintf, fmt, ##args)
-
-const char *_neighbor_ident_key_name(char *buf, size_t buflen, const struct neighbor_ident_key *ni_key)
+const char *neighbor_ident_addr_name(struct gsm_network *net, const struct neighbor_ident_addr *na)
{
- char *pos = buf;
-
- APPEND_STR("BTS ");
- if (ni_key->from_bts == NEIGHBOR_IDENT_KEY_ANY_BTS)
- APPEND_STR("*");
- else if (ni_key->from_bts >= 0 && ni_key->from_bts <= 255)
- APPEND_STR("%d", ni_key->from_bts);
- else
- APPEND_STR("invalid(%d)", ni_key->from_bts);
-
- APPEND_STR(" to ");
- if (ni_key->bsic == BSIC_ANY)
- APPEND_STR("ARFCN %u (any BSIC)", ni_key->arfcn);
- else
- APPEND_STR("ARFCN %u BSIC %u", ni_key->arfcn, ni_key->bsic & 0x3f);
- return buf;
-}
+ 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;
+ }
-const char *neighbor_ident_key_name(const struct neighbor_ident_key *ni_key)
-{
- static char buf[64];
- return _neighbor_ident_key_name(buf, sizeof(buf), ni_key);
+ return buf;
}
struct neighbor_ident_list *neighbor_ident_init(void *talloc_ctx)
@@ -95,57 +70,28 @@ void neighbor_ident_free(struct neighbor_ident_list *nil)
talloc_free(nil);
}
-/* Return true when the entry matches the search_for requirements.
- * If exact_match is false, a BSIC_ANY entry acts as wildcard to match any search_for on that ARFCN,
- * and a BSIC_ANY in search_for likewise returns any one entry that matches the ARFCN;
- * also a from_bts == NEIGHBOR_IDENT_KEY_ANY_BTS in either entry or search_for will match.
- * If exact_match is true, only identical bsic values and identical from_bts values return a match.
- * Note, typically wildcard BSICs are only in entry, e.g. the user configured list, and search_for
- * contains a specific BSIC, e.g. as received from a Measurement Report. */
-bool neighbor_ident_key_match(const struct neighbor_ident_key *entry,
- const struct neighbor_ident_key *search_for,
- bool exact_match)
-{
- if (exact_match
- && entry->from_bts != search_for->from_bts)
- return false;
-
- if (search_for->from_bts != NEIGHBOR_IDENT_KEY_ANY_BTS
- && entry->from_bts != NEIGHBOR_IDENT_KEY_ANY_BTS
- && entry->from_bts != search_for->from_bts)
- return false;
-
- if (entry->arfcn != search_for->arfcn)
- return false;
-
- if (exact_match && entry->bsic != search_for->bsic)
- return false;
-
- if (entry->bsic == BSIC_ANY || search_for->bsic == BSIC_ANY)
- return true;
-
- return entry->bsic == search_for->bsic;
-}
-
static struct neighbor_ident *_neighbor_ident_get(const struct neighbor_ident_list *nil,
- const struct neighbor_ident_key *key,
- bool exact_match)
+ const struct neighbor_ident_addr *na)
{
struct neighbor_ident *ni;
- struct neighbor_ident *wildcard_match = NULL;
- /* Do both exact-bsic and wildcard matching in the same iteration:
- * Any exact match returns immediately, while for a wildcard match we still go through all
- * remaining items in case an exact match exists. */
llist_for_each_entry(ni, &nil->list, entry) {
- if (neighbor_ident_key_match(&ni->key, key, true))
- return ni;
- if (!exact_match) {
- if (neighbor_ident_key_match(&ni->key, key, false))
- wildcard_match = ni;
+ 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 wildcard_match;
+
+ return NULL;
}
static void _neighbor_ident_free(struct neighbor_ident *ni)
@@ -154,26 +100,15 @@ static void _neighbor_ident_free(struct neighbor_ident *ni)
talloc_free(ni);
}
-bool neighbor_ident_key_valid(const struct neighbor_ident_key *key)
-{
- if (key->from_bts != NEIGHBOR_IDENT_KEY_ANY_BTS
- && (key->from_bts < 0 || key->from_bts > 255))
- return false;
-
- if (key->bsic != BSIC_ANY && key->bsic > 0x3f)
- return false;
- return true;
-}
-
-/*! Add Cell Identifiers to an ARFCN+BSIC entry.
- * Exactly one kind of identifier is allowed per ARFCN+BSIC entry, and any number of entries of that kind
+/*! 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, key).
+ * 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_key *key,
- const struct gsm0808_cell_id_list2 *val)
+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;
@@ -181,49 +116,59 @@ int neighbor_ident_add(struct neighbor_ident_list *nil, const struct neighbor_id
if (!nil)
return -ENOMEM;
- if (!neighbor_ident_key_valid(key))
- return -ERANGE;
-
- ni = _neighbor_ident_get(nil, key, true);
+ ni = _neighbor_ident_get(nil, addr);
if (!ni) {
ni = talloc_zero(nil, struct neighbor_ident);
OSMO_ASSERT(ni);
- *ni = (struct neighbor_ident){
- .key = *key,
- .val = *val,
- };
+ ni->addr = *addr;
llist_add_tail(&ni->entry, &nil->list);
- return ni->val.id_list_len;
+ return ni->cell_ids.id_list_len;
}
- rc = gsm0808_cell_id_list_add(&ni->val, val);
+ rc = gsm0808_cell_id_list_add(&ni->cell_ids, cell_id);
if (rc < 0)
return rc;
- return ni->val.id_list_len;
+ return ni->cell_ids.id_list_len;
}
-/*! Find cell identity for given BTS, ARFCN and BSIC, as previously added by neighbor_ident_add().
+/*! 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_key *key)
+ const struct neighbor_ident_addr *addr)
{
struct neighbor_ident *ni;
if (!nil)
return NULL;
- ni = _neighbor_ident_get(nil, key, false);
+ ni = _neighbor_ident_get(nil, addr);
if (!ni)
return NULL;
- return &ni->val;
+ 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_key *key)
+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, key, true);
+ ni = _neighbor_ident_get(nil, addr);
if (!ni)
return false;
_neighbor_ident_free(ni);
@@ -240,8 +185,8 @@ void neighbor_ident_clear(struct neighbor_ident_list *nil)
/*! 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_key *key,
- const struct gsm0808_cell_id_list2 *val,
+ bool (* iter_cb )(const struct neighbor_ident_addr *addr,
+ const struct gsm0808_cell_id_list2 *cell_ids,
void *cb_data),
void *cb_data)
{
@@ -249,7 +194,7 @@ void neighbor_ident_iter(const struct neighbor_ident_list *nil,
if (!nil)
return;
llist_for_each_entry_safe(ni, ni_next, &nil->list, entry) {
- if (!iter_cb(&ni->key, &ni->val, cb_data))
+ 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
index 203b150..f126e12 100644
--- a/src/libmsc/neighbor_ident_vty.c
+++ b/src/libmsc/neighbor_ident_vty.c
@@ -26,53 +26,17 @@
#include <osmocom/vty/command.h>
#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/sigtran/osmo_ss7.h>
-#include <osmocom/bsc/vty.h>
-#include <osmocom/bsc/neighbor_ident.h>
-#include <osmocom/bsc/gsm_data.h>
-
-static struct gsm_network *g_net = NULL;
-static struct neighbor_ident_list *g_neighbor_cells = NULL;
-
-/* Parse VTY parameters matching NEIGHBOR_IDENT_VTY_KEY_PARAMS. Pass a pointer so that argv[0] is the
- * ARFCN value followed by the BSIC keyword and value. vty *must* reference a BTS_NODE. */
-bool neighbor_ident_vty_parse_key_params(struct vty *vty, const char **argv,
- struct neighbor_ident_key *key)
-{
- struct gsm_bts *bts = vty->index;
-
- OSMO_ASSERT(vty->node == BTS_NODE);
- OSMO_ASSERT(bts);
-
- return neighbor_ident_bts_parse_key_params(vty, bts, argv, key);
-}
-
-/* same as neighbor_ident_vty_parse_key_params() but pass an explicit bts, so it works on any node. */
-bool neighbor_ident_bts_parse_key_params(struct vty *vty, struct gsm_bts *bts, const char **argv,
- struct neighbor_ident_key *key)
-{
- const char *arfcn_str = argv[0];
- const char *bsic_str = argv[1];
-
- OSMO_ASSERT(bts);
-
- *key = (struct neighbor_ident_key){
- .from_bts = bts->nr,
- .arfcn = atoi(arfcn_str),
- };
-
- if (!strcmp(bsic_str, "any"))
- key->bsic = BSIC_ANY;
- else
- key->bsic = atoi(bsic_str);
- return true;
-}
+#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_DOC "Manage local and remote-BSS neighbor cells\n"
+#define NEIGHBOR_DOC "Manage neighbor BSS cells\n"
#define NEIGHBOR_ADD_DOC NEIGHBOR_DOC "Add "
-#define NEIGHBOR_DEL_DOC NO_STR "Remove local or remote-BSS neighbor cell\n"
+#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"
@@ -83,26 +47,14 @@ bool neighbor_ident_bts_parse_key_params(struct vty *vty, struct gsm_bts *bts, c
#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 LOCAL_BTS_PARAMS "bts <0-255>"
-#define LOCAL_BTS_DOC "Neighbor cell by local BTS number\n" "BTS number\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_bts *neighbor_ident_vty_parse_bts_nr(struct vty *vty, const char **argv)
-{
- const char *bts_nr_str = argv[0];
- struct gsm_bts *bts = gsm_bts_num(g_net, atoi(bts_nr_str));
- if (!bts)
- vty_out(vty, "%% No such BTS: nr = %s%s\n", bts_nr_str, VTY_NEWLINE);
- return bts;
-}
-
-static struct gsm_bts *bts_by_cell_id(struct vty *vty, struct gsm0808_cell_id *cell_id)
-{
- struct gsm_bts *bts = gsm_bts_by_cell_id(g_net, cell_id, 0);
- if (!bts)
- vty_out(vty, "%% No such BTS: %s%s\n", gsm0808_cell_id_name(cell_id), VTY_NEWLINE);
- return bts;
-}
+static struct gsm_network *g_net = NULL;
+#if 0
static struct gsm0808_cell_id *neighbor_ident_vty_parse_lac(struct vty *vty, const char **argv)
{
static struct gsm0808_cell_id cell_id;
@@ -125,6 +77,7 @@ static struct gsm0808_cell_id *neighbor_ident_vty_parse_lac_ci(struct vty *vty,
};
return &cell_id;
}
+#endif
static struct gsm0808_cell_id *neighbor_ident_vty_parse_cgi(struct vty *vty, const char **argv)
{
@@ -153,77 +106,23 @@ static struct gsm0808_cell_id *neighbor_ident_vty_parse_cgi(struct vty *vty, con
return &cell_id;
}
-static int add_local_bts(struct vty *vty, struct gsm_bts *neigh)
+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;
- struct gsm_bts *bts = vty->index;
- if (vty->node != BTS_NODE) {
- vty_out(vty, "%% Error: cannot add local BTS neighbor, not on BTS node%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (!bts) {
- vty_out(vty, "%% Error: cannot add local BTS neighbor, no BTS on this node%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (!neigh) {
- vty_out(vty, "%% Error: cannot add local BTS neighbor to BTS %u, no such neighbor BTS%s"
- "%% (To add remote-BSS neighbors, pass full ARFCN and BSIC as well)%s",
- bts->nr, VTY_NEWLINE, VTY_NEWLINE);
- return CMD_WARNING;
- }
- rc = gsm_bts_local_neighbor_add(bts, neigh);
- if (rc < 0) {
- vty_out(vty, "%% Error: cannot add local BTS %u as neighbor to BTS %u: %s%s",
- neigh->nr, bts->nr, strerror(-rc), VTY_NEWLINE);
- return CMD_WARNING;
- } else
- vty_out(vty, "%% BTS %u %s local neighbor BTS %u with LAC %u CI %u and ARFCN %u BSIC %u%s",
- bts->nr, rc? "now has" : "already had",
- neigh->nr, neigh->location_area_code, neigh->cell_identity,
- neigh->c0->arfcn, neigh->bsic, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-static int del_local_bts(struct vty *vty, struct gsm_bts *neigh)
-{
- int rc;
- struct gsm_bts *bts = vty->index;
- if (vty->node != BTS_NODE) {
- vty_out(vty, "%% Error: cannot remove local BTS neighbor, not on BTS node%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (!bts) {
- vty_out(vty, "%% Error: cannot remove local BTS neighbor, no BTS on this node%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (!neigh) {
- vty_out(vty, "%% Error: cannot remove local BTS neighbor from BTS %u, no such neighbor BTS%s",
- bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
- rc = gsm_bts_local_neighbor_del(bts, neigh);
+ 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 remove local BTS %u neighbor from BTS %u: %s%s",
- neigh->nr, bts->nr, strerror(-rc), VTY_NEWLINE);
+ 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;
}
- if (rc == 0)
- vty_out(vty, "%% BTS %u is no neighbor of BTS %u%s",
- neigh->nr, bts->nr, VTY_NEWLINE);
return CMD_SUCCESS;
}
-DEFUN(cfg_neighbor_add_bts_nr, cfg_neighbor_add_bts_nr_cmd,
- NEIGHBOR_ADD_CMD LOCAL_BTS_PARAMS,
- NEIGHBOR_ADD_DOC LOCAL_BTS_DOC)
-{
- return add_local_bts(vty, neighbor_ident_vty_parse_bts_nr(vty, argv));
-}
-
+#if 0
DEFUN(cfg_neighbor_add_lac, cfg_neighbor_add_lac_cmd,
NEIGHBOR_ADD_CMD LAC_PARAMS,
NEIGHBOR_ADD_DOC LAC_DOC)
@@ -237,344 +136,221 @@ DEFUN(cfg_neighbor_add_lac_ci, cfg_neighbor_add_lac_ci_cmd,
{
return add_local_bts(vty, bts_by_cell_id(vty, neighbor_ident_vty_parse_lac_ci(vty, argv)));
}
+#endif
-DEFUN(cfg_neighbor_add_cgi, cfg_neighbor_add_cgi_cmd,
- NEIGHBOR_ADD_CMD CGI_PARAMS,
- NEIGHBOR_ADD_DOC CGI_DOC)
-{
- return add_local_bts(vty, bts_by_cell_id(vty, neighbor_ident_vty_parse_cgi(vty, argv)));
-}
-
-bool neighbor_ident_key_matches_bts(const struct neighbor_ident_key *key, struct gsm_bts *bts)
+static int parse_point_code(const char *point_code_str)
{
- if (!bts || !key)
- return false;
- return key->arfcn == bts->c0->arfcn
- && (key->bsic == BSIC_ANY || key->bsic == bts->bsic);
+ 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);
}
-static int add_remote_or_local_bts(struct vty *vty, const struct gsm0808_cell_id *cell_id,
- const struct neighbor_ident_key *key)
+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)
{
- int rc;
- struct gsm_bts *local_neigh;
- const struct gsm0808_cell_id_list2 *exists;
- struct gsm0808_cell_id_list2 cil;
- struct gsm_bts *bts = vty->index;
-
- if (vty->node != BTS_NODE) {
- vty_out(vty, "%% Error: cannot add BTS neighbor, not on BTS node%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (!bts) {
- vty_out(vty, "%% Error: cannot add BTS neighbor, no BTS on this node%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Is there a local BTS that matches the cell_id? */
- local_neigh = gsm_bts_by_cell_id(g_net, cell_id, 0);
- if (local_neigh) {
- /* But do the advertised ARFCN and BSIC match as intended?
- * The user may omit ARFCN and BSIC for local cells, but if they are provided,
- * they need to match. */
- if (!neighbor_ident_key_matches_bts(key, local_neigh)) {
- vty_out(vty, "%% Error: bts %u: neighbor cell id %s indicates local BTS %u,"
- " but it does not match ARFCN+BSIC %s%s",
- bts->nr, gsm0808_cell_id_name(cell_id), local_neigh->nr,
- neighbor_ident_key_name(key), VTY_NEWLINE);
- /* TODO: error out fatally for non-interactive VTY? */
- return CMD_WARNING;
- }
- return add_local_bts(vty, local_neigh);
- }
+ struct neighbor_ident_addr addr;
+ int point_code = parse_point_code(argv[4]);
- /* Allow only one cell ID per remote-BSS neighbor, see OS#3656 */
- exists = neighbor_ident_get(g_neighbor_cells, key);
- if (exists) {
- vty_out(vty, "%% Error: only one Cell Identifier entry is allowed per remote neighbor."
- " Already have: %s -> %s%s", neighbor_ident_key_name(key),
- gsm0808_cell_id_list_name(exists), VTY_NEWLINE);
+ if (point_code < 0) {
+ vty_out(vty, "Could not parse point code '%s'%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
- /* The cell_id is not known in this BSS, so it must be a remote cell. */
- gsm0808_cell_id_to_list(&cil, cell_id);
- rc = neighbor_ident_add(g_neighbor_cells, key, &cil);
-
- if (rc < 0) {
- const char *reason;
- switch (rc) {
- case -EINVAL:
- reason = ": mismatching type between current and newly added cell identifier";
- break;
- case -ENOSPC:
- reason = ": list is full";
- break;
- default:
- reason = "";
- break;
- }
+ 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));
+}
- vty_out(vty, "%% Error adding neighbor-BSS Cell Identifier %s%s%s",
- gsm0808_cell_id_name(cell_id), reason, VTY_NEWLINE);
- return CMD_WARNING;
- }
+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;
- vty_out(vty, "%% %s now has %d remote BSS Cell Identifier List %s%s",
- neighbor_ident_key_name(key), rc, rc == 1? "entry" : "entries", VTY_NEWLINE);
- return CMD_SUCCESS;
+ 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_key(struct vty *vty, const struct neighbor_ident_key *key)
+static int del_by_addr(struct vty *vty, const struct neighbor_ident_addr *addr)
{
int removed = 0;
- int rc;
- struct gsm_bts *bts = vty->index;
- struct gsm_bts_ref *neigh, *safe;
- if (vty->node != BTS_NODE) {
- vty_out(vty, "%% Error: cannot remove BTS neighbor, not on BTS node%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (!bts) {
- vty_out(vty, "%% Error: cannot remove BTS neighbor, no BTS on this node%s",
- VTY_NEWLINE);
+ if (vty->node != MSC_NODE) {
+ vty_out(vty, "%% Error: cannot remove neighbor, not on MSC node%s", VTY_NEWLINE);
return CMD_WARNING;
}
- /* Is there a local BTS that matches the key? */
- llist_for_each_entry_safe(neigh, safe, &bts->local_neighbors, entry) {
- struct gsm_bts *neigh_bts = neigh->bts;
- if (!neighbor_ident_key_matches_bts(key, neigh->bts))
- continue;
- rc = gsm_bts_local_neighbor_del(bts, neigh->bts);
- if (rc > 0) {
- vty_out(vty, "%% Removed local neighbor bts %u to bts %u%s",
- bts->nr, neigh_bts->nr, VTY_NEWLINE);
- removed += rc;
- }
- }
-
- if (neighbor_ident_del(g_neighbor_cells, key)) {
- vty_out(vty, "%% Removed remote BSS neighbor %s%s",
- neighbor_ident_key_name(key), VTY_NEWLINE);
- removed ++;
+ 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_key_name(key), VTY_NEWLINE);
+ neighbor_ident_addr_name(g_net, addr), VTY_NEWLINE);
return CMD_WARNING;
}
- return CMD_SUCCESS;
-}
-DEFUN(cfg_neighbor_add_lac_arfcn_bsic, cfg_neighbor_add_lac_arfcn_bsic_cmd,
- NEIGHBOR_ADD_CMD LAC_PARAMS " " NEIGHBOR_IDENT_VTY_KEY_PARAMS,
- NEIGHBOR_ADD_DOC LAC_DOC NEIGHBOR_IDENT_VTY_KEY_DOC)
-{
- struct neighbor_ident_key nik;
- struct gsm0808_cell_id *cell_id = neighbor_ident_vty_parse_lac(vty, argv);
- if (!cell_id)
- return CMD_WARNING;
- if (!neighbor_ident_vty_parse_key_params(vty, argv + 1, &nik))
- return CMD_WARNING;
- return add_remote_or_local_bts(vty, cell_id, &nik);
+ return CMD_SUCCESS;
}
-DEFUN(cfg_neighbor_add_lac_ci_arfcn_bsic, cfg_neighbor_add_lac_ci_arfcn_bsic_cmd,
- NEIGHBOR_ADD_CMD LAC_CI_PARAMS " " NEIGHBOR_IDENT_VTY_KEY_PARAMS,
- NEIGHBOR_ADD_DOC LAC_CI_DOC NEIGHBOR_IDENT_VTY_KEY_DOC)
+DEFUN(cfg_del_neighbor_bsc, cfg_del_neighbor_bsc_cmd,
+ "del neighbor " 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_key nik;
- struct gsm0808_cell_id *cell_id = neighbor_ident_vty_parse_lac_ci(vty, argv);
- if (!cell_id)
- return CMD_WARNING;
- if (!neighbor_ident_vty_parse_key_params(vty, argv + 2, &nik))
- return CMD_WARNING;
- return add_remote_or_local_bts(vty, cell_id, &nik);
-}
+ struct neighbor_ident_addr addr;
+ int point_code = parse_point_code(argv[0]);
-DEFUN(cfg_neighbor_add_cgi_arfcn_bsic, cfg_neighbor_add_cgi_arfcn_bsic_cmd,
- NEIGHBOR_ADD_CMD CGI_PARAMS " " NEIGHBOR_IDENT_VTY_KEY_PARAMS,
- NEIGHBOR_ADD_DOC CGI_DOC NEIGHBOR_IDENT_VTY_KEY_DOC)
-{
- struct neighbor_ident_key nik;
- struct gsm0808_cell_id *cell_id = neighbor_ident_vty_parse_cgi(vty, argv);
- if (!cell_id)
+ if (point_code < 0) {
+ vty_out(vty, "Could not parse point code '%s'%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
- if (!neighbor_ident_vty_parse_key_params(vty, argv + 4, &nik))
- return CMD_WARNING;
- return add_remote_or_local_bts(vty, cell_id, &nik);
-}
+ }
-DEFUN(cfg_neighbor_del_bts_nr, cfg_neighbor_del_bts_nr_cmd,
- NEIGHBOR_DEL_CMD LOCAL_BTS_PARAMS,
- NEIGHBOR_DEL_DOC LOCAL_BTS_DOC)
-{
- return del_local_bts(vty, neighbor_ident_vty_parse_bts_nr(vty, argv));
+ addr.type = MSC_NEIGHBOR_TYPE_BSC;
+ addr.a.point_code = point_code;
+ return del_by_addr(vty, &addr);
}
-DEFUN(cfg_neighbor_del_arfcn_bsic, cfg_neighbor_del_arfcn_bsic_cmd,
- NEIGHBOR_DEL_CMD NEIGHBOR_IDENT_VTY_KEY_PARAMS,
- NEIGHBOR_DEL_DOC NEIGHBOR_IDENT_VTY_KEY_DOC)
+DEFUN(cfg_del_neighbor_msc, cfg_del_neighbor_msc_cmd,
+ "del neighbor " 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_key key;
-
- if (!neighbor_ident_vty_parse_key_params(vty, argv, &key))
- return CMD_WARNING;
+ struct neighbor_ident_addr addr;
- return del_by_key(vty, &key);
+ addr.type = MSC_NEIGHBOR_TYPE_MSC;
+ addr.a.ipa_name = argv[0];
+ return del_by_addr(vty, &addr);
}
-struct write_neighbor_ident_entry_data {
- struct vty *vty;
- const char *indent;
- struct gsm_bts *bts;
-};
-
-static bool write_neighbor_ident_list(const struct neighbor_ident_key *key,
- const struct gsm0808_cell_id_list2 *val,
- void *cb_data)
+static void write_neighbor_ident(struct vty *vty, const struct neighbor_ident *ni)
{
- struct write_neighbor_ident_entry_data *d = cb_data;
- struct vty *vty = d->vty;
+ 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;
- if (d->bts) {
- if (d->bts->nr != key->from_bts)
- return true;
- } else if (key->from_bts != NEIGHBOR_IDENT_KEY_ANY_BTS)
- return true;
-
-#define NEIGH_BSS_WRITE(fmt, args...) do { \
- vty_out(vty, "%sneighbor " fmt " arfcn %u ", d->indent, ## args, key->arfcn); \
- if (key->bsic == BSIC_ANY) \
- vty_out(vty, "bsic any"); \
- else \
- vty_out(vty, "bsic %u", key->bsic & 0x3f); \
- vty_out(vty, "%s", VTY_NEWLINE); \
- } while(0)
-
- switch (val->id_discr) {
+ switch (cell_ids->id_discr) {
case CELL_IDENT_LAC:
- for (i = 0; i < val->id_list_len; i++) {
- NEIGH_BSS_WRITE("lac %u", val->id_list[i].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 < val->id_list_len; i++) {
- NEIGH_BSS_WRITE("lac-ci %u %u",
- val->id_list[i].lac_and_ci.lac,
- val->id_list[i].lac_and_ci.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 < val->id_list_len; i++) {
- const struct osmo_cell_global_id *cgi = &val->id_list[i].global;
- NEIGH_BSS_WRITE("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);
+ 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;
}
-#undef NEIGH_BSS_WRITE
- return true;
+ 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_remote_bss(struct vty *vty, const char *indent, struct gsm_bts *bts)
+void neighbor_ident_vty_write(struct vty *vty)
{
- struct write_neighbor_ident_entry_data d = {
- .vty = vty,
- .indent = indent,
- .bts = bts,
- };
+ const struct neighbor_ident *ni;
- neighbor_ident_iter(g_neighbor_cells, write_neighbor_ident_list, &d);
+ llist_for_each_entry(ni, &g_net->neighbor_list->list, entry)
+ write_neighbor_ident(vty, ni);
}
-void neighbor_ident_vty_write_local_neighbors(struct vty *vty, const char *indent, struct gsm_bts *bts)
+DEFUN(show_neighbor_bsc, show_neighbor_bsc_cmd,
+ "show neighbor " 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)
{
- struct gsm_bts_ref *neigh;
+ int point_code;
+ struct neighbor_ident *ni;
+ int found = 0;
- llist_for_each_entry(neigh, &bts->local_neighbors, entry) {
- vty_out(vty, "%sneighbor bts %u%s", indent, neigh->bts->nr, VTY_NEWLINE);
+ 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;
}
-}
-void neighbor_ident_vty_write(struct vty *vty, const char *indent, struct gsm_bts *bts)
-{
- neighbor_ident_vty_write_local_neighbors(vty, indent, bts);
- neighbor_ident_vty_write_remote_bss(vty, indent, bts);
+ 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_bts_neighbor, show_bts_neighbor_cmd,
- "show bts <0-255> neighbor " NEIGHBOR_IDENT_VTY_KEY_PARAMS,
- SHOW_STR "Display information about a BTS\n" "BTS number\n"
- "Query which cell would be the target for this neighbor ARFCN+BSIC\n"
- NEIGHBOR_IDENT_VTY_KEY_DOC)
+DEFUN(show_neighbor_msc, show_neighbor_msc_cmd,
+ "show neighbor " 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;
- struct neighbor_ident_key key;
- struct gsm_bts_ref *neigh;
- const struct gsm0808_cell_id_list2 *res;
- struct gsm_bts *bts = gsm_bts_num(g_net, atoi(argv[0]));
- struct write_neighbor_ident_entry_data d = {
- .vty = vty,
- .indent = "% ",
- .bts = bts,
- };
-
- if (!bts) {
- vty_out(vty, "%% Error: cannot find BTS '%s'%s", argv[0],
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (!neighbor_ident_bts_parse_key_params(vty, bts, &argv[1], &key))
- return CMD_WARNING;
- /* Is there a local BTS that matches the key? */
- llist_for_each_entry(neigh, &bts->local_neighbors, entry) {
- if (!neighbor_ident_key_matches_bts(&key, neigh->bts))
+ llist_for_each_entry(ni, &g_net->neighbor_list->list, entry) {
+ if (ni->addr.type != MSC_NEIGHBOR_TYPE_MSC)
continue;
- vty_out(vty, "%% %s resolves to local BTS %u lac-ci %u %u%s",
- neighbor_ident_key_name(&key), neigh->bts->nr, neigh->bts->location_area_code,
- neigh->bts->cell_identity, VTY_NEWLINE);
- found++;
- }
-
- res = neighbor_ident_get(g_neighbor_cells, &key);
- if (res) {
- write_neighbor_ident_list(&key, res, &d);
- found++;
+ 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", neighbor_ident_key_name(&key), VTY_NEWLINE);
+ vty_out(vty, "%% No entry for %s%s", ipa_name, VTY_NEWLINE);
return CMD_SUCCESS;
}
-void neighbor_ident_vty_init(struct gsm_network *net, struct neighbor_ident_list *nil)
+void neighbor_ident_vty_init(struct gsm_network *net)
{
g_net = net;
- g_neighbor_cells = nil;
- install_element(BTS_NODE, &cfg_neighbor_add_bts_nr_cmd);
- install_element(BTS_NODE, &cfg_neighbor_add_lac_cmd);
- install_element(BTS_NODE, &cfg_neighbor_add_lac_ci_cmd);
- install_element(BTS_NODE, &cfg_neighbor_add_cgi_cmd);
- install_element(BTS_NODE, &cfg_neighbor_add_lac_arfcn_bsic_cmd);
- install_element(BTS_NODE, &cfg_neighbor_add_lac_ci_arfcn_bsic_cmd);
- install_element(BTS_NODE, &cfg_neighbor_add_cgi_arfcn_bsic_cmd);
- install_element(BTS_NODE, &cfg_neighbor_del_bts_nr_cmd);
- install_element(BTS_NODE, &cfg_neighbor_del_arfcn_bsic_cmd);
- install_element_ve(&show_bts_neighbor_cmd);
+ g_net->neighbor_list = neighbor_ident_init(net);
+#if 0
+ install_element(MSC_NODE, &cfg_neighbor_add_lac_cmd);
+ install_element(MSC_NODE, &cfg_neighbor_add_lac_ci_cmd);
+#endif
+ 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_bsc_cmd);
+ install_element_ve(&show_neighbor_msc_cmd);
}