aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@espeweb.net>2020-12-21 18:12:58 +0100
committerPau Espin Pedrol <pespin@sysmocom.de>2021-01-13 17:14:09 +0100
commit55a015dddf7fa1467b2b9b9def0174990a514490 (patch)
treee18aa2c4e66c8e54bfc4de7b8f08fd7f752ec6cc /src
parent63f98f22a019ee92cfdab9a9c73990e474c90dc9 (diff)
Introduce Neighbor Resolution Service
This new CTRL interface allows users of this BSC (such as attached PCU) to gather neighbor information. This interface is needed for PCU to translate ARFCN+BSIC keys provided by MS in the Um side into CGI + RAC keys used to identify target cells in RIM procedures against SGSNs on the Gb interface. This patch extends the already existing neighbor information storage in the VTY by allowing storage of CGI + RAC (RAC couldn't be stored beforehand). Related: SYS#4909 Depends: libosmocore.git Change-Id If48f412c32e8e5a3e604a78d12b74787a4786374 Change-Id: Ib07c9d23026332a207d4b7a0f7b4e76c0094e379
Diffstat (limited to 'src')
-rw-r--r--src/osmo-bsc/bsc_vty.c4
-rw-r--r--src/osmo-bsc/bts.c4
-rw-r--r--src/osmo-bsc/neighbor_ident.c103
-rw-r--r--src/osmo-bsc/neighbor_ident_vty.c91
-rw-r--r--src/osmo-bsc/osmo_bsc_main.c13
5 files changed, 213 insertions, 2 deletions
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index d61d379dc..400e1a6d6 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -1175,7 +1175,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
VTY_NEWLINE);
}
- neighbor_ident_vty_write(vty, " ", bts);
+ neighbor_ident_vty_write_bts(vty, " ", bts);
vty_out(vty, " codec-support fr");
if (bts->codec.hr)
@@ -1315,6 +1315,8 @@ static int config_write_net(struct vty *vty)
vty_out(vty, "%s", VTY_NEWLINE);
}
+ neighbor_ident_vty_write_network(vty, " ");
+
return CMD_SUCCESS;
}
diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c
index 39122ae03..0774721e0 100644
--- a/src/osmo-bsc/bts.c
+++ b/src/osmo-bsc/bts.c
@@ -388,6 +388,10 @@ bool gsm_bts_matches_cell_id(const struct gsm_bts *bts, const struct gsm0808_cel
case CELL_IDENT_WHOLE_GLOBAL:
return gsm_bts_matches_lai(bts, &id->global.lai)
&& id->global.cell_identity == bts->cell_identity;
+ case CELL_IDENT_WHOLE_GLOBAL_PS:
+ return gsm_bts_matches_lai(bts, &id->global_ps.rai.lac)
+ && id->global_ps.rai.rac == bts->gprs.rac
+ && id->global_ps.cell_identity == bts->cell_identity;
case CELL_IDENT_LAC_AND_CI:
return id->lac_and_ci.lac == bts->location_area_code
&& id->lac_and_ci.ci == bts->cell_identity;
diff --git a/src/osmo-bsc/neighbor_ident.c b/src/osmo-bsc/neighbor_ident.c
index 4a0cd47ad..185cd0b07 100644
--- a/src/osmo-bsc/neighbor_ident.c
+++ b/src/osmo-bsc/neighbor_ident.c
@@ -33,6 +33,13 @@
#include <osmocom/bsc/neighbor_ident.h>
+#include <osmocom/ctrl/control_cmd.h>
+#include <osmocom/ctrl/control_if.h>
+
+#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/debug.h>
+
struct neighbor_ident_list {
struct llist_head list;
};
@@ -253,3 +260,99 @@ void neighbor_ident_iter(const struct neighbor_ident_list *nil,
return;
}
}
+
+/* Neighbor Resolution CTRL iface */
+
+CTRL_CMD_DEFINE_RO(neighbor_resolve_cgi_ps_from_lac_ci, "neighbor_resolve_cgi_ps_from_lac_ci");
+
+static int get_neighbor_resolve_cgi_ps_from_lac_ci(struct ctrl_cmd *cmd, void *data)
+{
+ struct gsm_network *net = (struct gsm_network *)data;
+ struct gsm_bts *bts_tmp, *bts_found = NULL;
+ const struct gsm0808_cell_id_list2 *tgt_cell_li = NULL;
+ char *tmp = NULL, *tok, *saveptr;
+ struct neighbor_ident_key ni;
+ unsigned lac, cell_id;
+ const struct osmo_cell_global_id_ps *cgi_ps;
+
+ if (!cmd->variable)
+ goto fmt_err;
+
+ tmp = talloc_strdup(cmd, cmd->variable);
+ if (!tmp) {
+ cmd->reply = "OOM";
+ return CTRL_CMD_ERROR;
+ }
+
+ if (!(tok = strtok_r(tmp, ".", &saveptr)))
+ goto fmt_err;
+ OSMO_ASSERT(strcmp(tok, "neighbor_resolve_cgi_ps_from_lac_ci") == 0);
+
+ if (!(tok = strtok_r(NULL, ".", &saveptr)))
+ goto fmt_err;
+ lac = atoi(tok);
+
+ if (!(tok = strtok_r(NULL, ".", &saveptr)))
+ goto fmt_err;
+ cell_id = atoi(tok);
+
+ if (!(tok = strtok_r(NULL, ".", &saveptr)))
+ goto fmt_err;
+ ni.arfcn = atoi(tok);
+
+ if (!(tok = strtok_r(NULL, "\0", &saveptr)))
+ goto fmt_err;
+ ni.bsic = atoi(tok);
+
+ ni.from_bts = NEIGHBOR_IDENT_KEY_ANY_BTS;
+
+ llist_for_each_entry(bts_tmp, &net->bts_list, list) {
+ if (bts_tmp->location_area_code != lac)
+ continue;
+ if (bts_tmp->cell_identity != cell_id)
+ continue;
+ bts_found = bts_tmp;
+ ni.from_bts = bts_tmp->nr;
+ break;
+ }
+
+ if (!bts_found)
+ goto notfound_err;
+
+ LOG_BTS(bts_found, DLINP, LOGL_DEBUG, "Resolving neigbhor arfcn=%u bsic=%u\n", ni.arfcn, ni.bsic);
+
+ if (!neighbor_ident_key_valid(&ni))
+ goto fmt_err;
+
+ tgt_cell_li = neighbor_ident_get(net->neighbor_bss_cells, &ni);
+ if (!tgt_cell_li || tgt_cell_li->id_discr != CELL_IDENT_WHOLE_GLOBAL_PS || tgt_cell_li->id_list_len < 1)
+ goto notfound_err;
+ cgi_ps = &tgt_cell_li->id_list[0].global_ps;
+
+ ctrl_cmd_reply_printf(cmd, "%s", osmo_cgi_ps_name(cgi_ps));
+ talloc_free(tmp);
+ return CTRL_CMD_REPLY;
+
+notfound_err:
+ talloc_free(tmp);
+ cmd->reply = talloc_strdup(cmd, "No target CGI PS found");
+ return CTRL_CMD_ERROR;
+fmt_err:
+ talloc_free(tmp);
+ cmd->reply = talloc_strdup(cmd, "The format is <src_lac>,<src_cell_id>,<dst_arfcn>,<dst_bsic>");
+ return CTRL_CMD_ERROR;
+}
+
+int neighbor_ctrl_cmds_install(struct gsm_network *net)
+{
+ int rc;
+
+ rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_neighbor_resolve_cgi_ps_from_lac_ci);
+ return rc;
+}
+
+struct ctrl_handle *neighbor_controlif_setup(struct gsm_network *net)
+{
+ return ctrl_interface_setup_dynip2(net, net->neigh_ctrl.addr, net->neigh_ctrl.port,
+ NULL, _LAST_CTRL_NODE_NEIGHBOR);
+}
diff --git a/src/osmo-bsc/neighbor_ident_vty.c b/src/osmo-bsc/neighbor_ident_vty.c
index 7feed2a27..72c11b0a7 100644
--- a/src/osmo-bsc/neighbor_ident_vty.c
+++ b/src/osmo-bsc/neighbor_ident_vty.c
@@ -23,6 +23,9 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <inttypes.h>
+
+#include <osmocom/ctrl/ports.h>
#include <osmocom/vty/command.h>
#include <osmocom/gsm/gsm0808.h>
@@ -84,6 +87,9 @@ 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 CGI_PS_PARAMS "cgi-ps <0-999> <0-999> <0-65535> <0-255> <0-65535>"
+#define CGI_PS_DOC "Neighbor cell by cgi (Packet Switched, with RAC)\n" "MCC\n" "MNC\n" "LAC\n" "RAC\n" "CI\n"
+
#define LOCAL_BTS_PARAMS "bts <0-255>"
#define LOCAL_BTS_DOC "Neighbor cell by local BTS number\n" "BTS number\n"
@@ -154,6 +160,34 @@ static struct gsm0808_cell_id *neighbor_ident_vty_parse_cgi(struct vty *vty, con
return &cell_id;
}
+static struct gsm0808_cell_id *neighbor_ident_vty_parse_cgi_ps(struct vty *vty, const char **argv)
+{
+ static struct gsm0808_cell_id cell_id = {
+ .id_discr = CELL_IDENT_WHOLE_GLOBAL_PS,
+ };
+ struct osmo_cell_global_id_ps *cgi_ps = &cell_id.id.global_ps;
+ const char *mcc = argv[0];
+ const char *mnc = argv[1];
+ const char *lac = argv[2];
+ const char *rac = argv[3];
+ const char *ci = argv[4];
+
+ if (osmo_mcc_from_str(mcc, &cgi_ps->rai.lac.plmn.mcc)) {
+ vty_out(vty, "%% Error decoding MCC: %s%s", mcc, VTY_NEWLINE);
+ return NULL;
+ }
+
+ if (osmo_mnc_from_str(mnc, &cgi_ps->rai.lac.plmn.mnc, &cgi_ps->rai.lac.plmn.mnc_3_digits)) {
+ vty_out(vty, "%% Error decoding MNC: %s%s", mnc, VTY_NEWLINE);
+ return NULL;
+ }
+
+ cgi_ps->rai.lac.lac = atoi(lac);
+ cgi_ps->rai.rac = atoi(rac);
+ cgi_ps->cell_identity = atoi(ci);
+ return &cell_id;
+}
+
static int add_local_bts(struct vty *vty, struct gsm_bts *neigh)
{
int rc;
@@ -246,6 +280,13 @@ DEFUN(cfg_neighbor_add_cgi, cfg_neighbor_add_cgi_cmd,
return add_local_bts(vty, bts_by_cell_id(vty, neighbor_ident_vty_parse_cgi(vty, argv)));
}
+DEFUN(cfg_neighbor_add_cgi_ps, cfg_neighbor_add_cgi_ps_cmd,
+ NEIGHBOR_ADD_CMD CGI_PS_PARAMS,
+ NEIGHBOR_ADD_DOC CGI_PS_DOC)
+{
+ return add_local_bts(vty, bts_by_cell_id(vty, neighbor_ident_vty_parse_cgi_ps(vty, argv)));
+}
+
bool neighbor_ident_key_matches_bts(const struct neighbor_ident_key *key, struct gsm_bts *bts)
{
if (!bts || !key)
@@ -497,6 +538,19 @@ DEFUN(cfg_neighbor_add_cgi_arfcn_bsic, cfg_neighbor_add_cgi_arfcn_bsic_cmd,
return add_remote_or_local_bts(vty, cell_id, &nik);
}
+DEFUN(cfg_neighbor_add_cgi_ps_arfcn_bsic, cfg_neighbor_add_cgi_ps_arfcn_bsic_cmd,
+ NEIGHBOR_ADD_CMD CGI_PS_PARAMS " " NEIGHBOR_IDENT_VTY_KEY_PARAMS,
+ NEIGHBOR_ADD_DOC CGI_PS_DOC NEIGHBOR_IDENT_VTY_KEY_DOC)
+{
+ struct neighbor_ident_key nik;
+ struct gsm0808_cell_id *cell_id = neighbor_ident_vty_parse_cgi_ps(vty, argv);
+ if (!cell_id)
+ return CMD_WARNING;
+ if (!neighbor_ident_vty_parse_key_params(vty, argv + 5, &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)
@@ -525,6 +579,27 @@ DEFUN(cfg_neighbor_del_all, cfg_neighbor_del_all_cmd,
return neighbor_del_all(vty);
}
+DEFUN(cfg_neighbor_bind, cfg_neighbor_bind_cmd,
+ "neighbor-resolution bind " VTY_IPV46_CMD " [<0-65535>]",
+ NEIGHBOR_DOC "Bind Neighbor Resolution Service (CTRL interface) to given ip and port\n"
+ IP_STR IPV6_STR "Port to bind the service to [defaults to 4248 if not provided]\n")
+{
+ osmo_talloc_replace_string(g_net, &g_net->neigh_ctrl.addr, argv[0]);
+ if (argc > 1)
+ g_net->neigh_ctrl.port = atoi(argv[1]);
+ else
+ g_net->neigh_ctrl.port = OSMO_CTRL_PORT_BSC_NEIGH;
+ return CMD_SUCCESS;
+}
+
+void neighbor_ident_vty_write_network(struct vty *vty, const char *indent)
+{
+ if (g_net->neigh_ctrl.addr)
+ vty_out(vty, "%sneighbor-resolution bind %s %" PRIu16 "%s", indent, g_net->neigh_ctrl.addr,
+ g_net->neigh_ctrl.port, VTY_NEWLINE);
+}
+
+
struct write_neighbor_ident_entry_data {
struct vty *vty;
const char *indent;
@@ -576,6 +651,16 @@ static bool write_neighbor_ident_list(const struct neighbor_ident_key *key,
cgi->lai.lac, cgi->cell_identity);
}
break;
+ case CELL_IDENT_WHOLE_GLOBAL_PS:
+ for (i = 0; i < val->id_list_len; i++) {
+ const struct osmo_cell_global_id_ps *cgi_ps = &val->id_list[i].global_ps;
+ NEIGH_BSS_WRITE("cgi-ps %s %s %u %u %u",
+ osmo_mcc_name(cgi_ps->rai.lac.plmn.mcc),
+ osmo_mnc_name(cgi_ps->rai.lac.plmn.mnc, cgi_ps->rai.lac.plmn.mnc_3_digits),
+ cgi_ps->rai.lac.lac, cgi_ps->rai.rac,
+ cgi_ps->cell_identity);
+ }
+ break;
default:
vty_out(vty, "%% Unsupported Cell Identity%s", VTY_NEWLINE);
}
@@ -604,7 +689,7 @@ void neighbor_ident_vty_write_local_neighbors(struct vty *vty, const char *inden
}
}
-void neighbor_ident_vty_write(struct vty *vty, const char *indent, struct gsm_bts *bts)
+void neighbor_ident_vty_write_bts(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);
@@ -662,13 +747,17 @@ void neighbor_ident_vty_init(struct gsm_network *net, struct neighbor_ident_list
{
g_net = net;
g_neighbor_cells = nil;
+ install_element(GSMNET_NODE, &cfg_neighbor_bind_cmd);
+
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_cgi_ps_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_add_cgi_ps_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(BTS_NODE, &cfg_neighbor_del_all_cmd);
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index ed561aad5..d751fc1aa 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -960,6 +960,19 @@ int main(int argc, char **argv)
exit(1);
}
+ if (bsc_gsmnet->neigh_ctrl.addr) {
+ bsc_gsmnet->neigh_ctrl.handle = neighbor_controlif_setup(bsc_gsmnet);
+ if (!bsc_gsmnet->neigh_ctrl.handle) {
+ fprintf(stderr, "Failed to bind Neighbor Resolution Service. Exiting.\n");
+ exit(1);
+ }
+ rc = neighbor_ctrl_cmds_install(bsc_gsmnet);
+ if (rc < 0) {
+ fprintf(stderr, "Failed to install Neighbor Resolution Service commands. Exiting.\n");
+ exit(1);
+ }
+ }
+
if (rf_ctrl)
osmo_talloc_replace_string(bsc_gsmnet, &bsc_gsmnet->rf_ctrl_name, rf_ctrl);