aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--doc/manuals/chapters/handover.adoc101
-rw-r--r--include/osmocom/bsc/gsm_data.h6
-rw-r--r--include/osmocom/bsc/neighbor_ident.h13
-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
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/bsc/Makefile.am2
-rw-r--r--tests/ctrl/osmo-bsc-neigh-test.cfg97
-rwxr-xr-xtests/ctrl_test_runner.py30
-rw-r--r--tests/gsm0408/Makefile.am2
-rw-r--r--tests/neighbor_ident.vty11
14 files changed, 471 insertions, 7 deletions
diff --git a/doc/manuals/chapters/handover.adoc b/doc/manuals/chapters/handover.adoc
index 8601dceb3..4de744b9e 100644
--- a/doc/manuals/chapters/handover.adoc
+++ b/doc/manuals/chapters/handover.adoc
@@ -1,4 +1,5 @@
-== Handover
+[[cs_handover]]
+== CS Handover
Handover is the process of moving a continuously used channel (lchan) from one
cell to another. Usually, that is an ongoing call, so that phones are able to
@@ -144,6 +145,7 @@ more than one neighbor per given ARFCN+BSIC, these values can be re-used any
number of times across a network, and even between cells managed by one and the
same BSC.
+[[config_neigh]]
=== Configuring Neighbors
The most important step to enable handover in OsmoBSC is to configure each cell
@@ -692,3 +694,100 @@ network
4G neighbor cells can be removed using the same command, just replacing
`add` with `del`.
+
+[[ps_handover]]
+== PS Handover
+
+Packet Switch Handover is mostly managed by the packet switching nodes such as
+PCU, SGSN and GGSN. However, the PCU encounters a similar difficulty to that
+explained in <<cs_handover>>: that is, it must find a way to translate
+ARFCN+BSIC identifiers provided by the MS into the sort of identifiers
+understood by the Core Network (SGSN). These identifiers are in this case
+composed of RAC+CI (instead LAC+CI), or more specifically, CGI+RAC (named as
+"Packet Switched CGI" or "CGI-PS" from now on for convenience).
+
+Hence, it feels natural extending the <<config_neigh>> storage in the BSC to
+also provide Packet Switched related identifiers in order to provide the PCU the
+required information to do the translations, instead of duplicating the whole
+neighbor information in two different network nodes.
+
+This can be done, similarly to already presented CS related commands in
+<<config_neigh>>, by using the `neighbor cgi-ps` VTY command, which allows for
+specifying the extra identifier (RAC) required by PS related translations:
+
+.Example: configuring PS neighbors within the local BSS in osmo-bsc.cfg, identified by CGI-PS (CGI+RAC)
+----
+network
+ bts 0
+neighbor cgi-ps <MCC> <MNC> <LAC> <RAC> <CI> arfcn <0-1023> bsic (<0-63>|any)
+----
+
+This information should already be present by default if one uses the `local BTS
+number` to identify the network, as long as that BTS is properly configured to
+have GPRS enabled and the RAC code is set by `gprs routing area <0-255>`
+command:
+
+.Example: configuring PS neighbors within the local BSS in osmo-bsc.cfg, identified by local BTS number
+----
+network
+ bts 0
+ gprs mode gprs
+ gprs routing area 45
+ neighbor bts 1
+ ...
+ bts 1
+ gprs mode egprs
+ gprs routing area 48
+ neighbor bts 0
+ ...
+----
+
+This PS information is solely used by the Neighbor Resolution Service, aimed at
+nodes other than BSC itself, and described below.
+
+=== Neighbor Resolution Service CTRL interface
+
+This service is provided in order to provide the PCU a way to translate
+ARCFCN+BSIC into CGI-PS in order to use RIM services and accomplish PS
+Handovers.
+
+This interface is Osmocom specific, since the standard doesn't provide any
+specifications on how to provide this kind of information to the PCU.
+
+Since the PCU can be either BSC-colocated or BTS-colocated (hence on a different
+host than BSC), this must be a network-based interface. Since the service is
+Osmocom-specific, it was decided to re-use the CTRL interface available in most
+Osmocom processes (see <<control>>).
+
+Due to security concerns, the set of CTRL commands available in this
+service is configured in a different IP address and port, since the service
+needs to be reachable by all PCU under the BSC. This way the user can still
+constrain the regular CTRL port (which may contains lots of configuration
+related commands) listening in a more constrained address (eg. localhost).
+
+By default, this interface is disabled, and it is enabled by configuring the
+desired IP address to bind to (and optionally a different port other than
+well-known `4248`):
+
+.Example: Enable and configure Neighbor Resolution Service CTRL interface
+----
+network
+ neighbor-resolution bind 127.0.0.1 5000
+----
+
+osmo-pcu will then be able to connect to the BSC and query for resolution during eg. NACC requests from MS.
+
+The relevant commands are::
+
+* neighbor_resolve_cgi_ps_from_lac_ci:
+----
+GET neighbor_resolve_cgi_ps_from_lac_ci.<src_lac>.<src_cell_id>.<dst_arfcn>.<dst_bsic>
+GET_REPLY <MCC>-<MNC>-<LAC>-<RAC>-<CI>
+----
+
+Where the `src_lac` and `src_ci` are provided by BTS/BSC over `PCUIF` interface
+during startup (`INFO IND`), and `dst_arfcn` and `dst_bsic` are those of the
+neighbor the PCU is willing to request the CGI-PS information. Hence, from the
+`src` params the BSC is able to look up the BTS and afterwards apply the
+translation of `dst` parameters based on the neighbor information available for
+that BTS.
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 233c3b683..8b539028c 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -1213,6 +1213,12 @@ struct gsm_network {
/* Remote BSS Cell Identifier Lists */
struct neighbor_ident_list *neighbor_bss_cells;
+ /* Remote BSS resolution sevice (CTRL iface) */
+ struct {
+ char *addr;
+ uint16_t port;
+ struct ctrl_handle *handle;
+ } neigh_ctrl;
/* Don't refuse to start with mutually exclusive codec settings */
bool allow_unusable_timeslots;
diff --git a/include/osmocom/bsc/neighbor_ident.h b/include/osmocom/bsc/neighbor_ident.h
index aa3827635..c8580e22b 100644
--- a/include/osmocom/bsc/neighbor_ident.h
+++ b/include/osmocom/bsc/neighbor_ident.h
@@ -5,6 +5,7 @@
#include <stdbool.h>
#include <osmocom/core/linuxlist.h>
+#include <osmocom/ctrl/control_cmd.h>
struct vty;
struct gsm_network;
@@ -45,7 +46,8 @@ void neighbor_ident_iter(const struct neighbor_ident_list *nil,
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);
+void neighbor_ident_vty_write_bts(struct vty *vty, const char *indent, struct gsm_bts *bts);
+void neighbor_ident_vty_write_network(struct vty *vty, const char *indent);
bool neighbor_ident_bts_entry_exists(uint8_t from_bts);
@@ -58,3 +60,12 @@ 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);
+
+
+struct ctrl_handle *neighbor_controlif_setup(struct gsm_network *net);
+int neighbor_ctrl_cmds_install(struct gsm_network *net);
+
+enum neighbor_ctrl_node {
+ CTRL_NODE_NEIGH = _LAST_CTRL_NODE,
+ _LAST_CTRL_NODE_NEIGHBOR
+};
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);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b11b905f6..6bc78392e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -41,6 +41,7 @@ EXTRA_DIST = \
osmo-bsc.vty \
timer.vty \
power_ctrl.vty \
+ ctrl/osmo-bsc-neigh-test.cfg \
$(NULL)
TESTSUITE = $(srcdir)/testsuite
diff --git a/tests/bsc/Makefile.am b/tests/bsc/Makefile.am
index b6ba42102..2cc57a448 100644
--- a/tests/bsc/Makefile.am
+++ b/tests/bsc/Makefile.am
@@ -8,6 +8,7 @@ AM_CFLAGS = \
-ggdb3 \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
+ $(LIBOSMOCTRL_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
$(LIBOSMOLEGACYMGCP_CFLAGS) \
$(LIBOSMOSIGTRAN_CFLAGS) \
@@ -59,6 +60,7 @@ bsc_test_LDADD = \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(LIBOSMOVTY_LIBS) \
+ $(LIBOSMOCTRL_LIBS) \
$(LIBOSMOABIS_LIBS) \
$(LIBOSMOLEGACYMGCP_LIBS) \
$(LIBRARY_GSM) \
diff --git a/tests/ctrl/osmo-bsc-neigh-test.cfg b/tests/ctrl/osmo-bsc-neigh-test.cfg
new file mode 100644
index 000000000..f1e71b671
--- /dev/null
+++ b/tests/ctrl/osmo-bsc-neigh-test.cfg
@@ -0,0 +1,97 @@
+! osmo-bsc default configuration
+! (assumes STP to run on 127.0.0.1 and uses default point codes)
+!
+log file /tmp/osmo-bsc-neigh.log
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging timestamp 1
+ logging level set-all debug
+e1_input
+ e1_line 0 driver ipa
+network
+ network country code 1
+ mobile network code 1
+ encryption a5 0
+ neci 1
+ paging any use tch 0
+ handover 0
+ handover algorithm 1
+ handover1 window rxlev averaging 10
+ handover1 window rxqual averaging 1
+ handover1 window rxlev neighbor averaging 10
+ handover1 power budget interval 6
+ handover1 power budget hysteresis 3
+ handover1 maximum distance 9999
+ periodic location update 30
+ neighbor-resolution bind 127.0.0.1
+ bts 0
+ type sysmobts
+ band DCS1800
+ cell_identity 6969
+ location_area_code 1
+ base_station_id_code 63
+ ms max power 15
+ cell reselection hysteresis 4
+ rxlev access min 0
+ radio-link-timeout 32
+ channel allocator ascending
+ rach tx integer 9
+ rach max transmission 7
+ channel-description attach 1
+ channel-description bs-pa-mfrms 5
+ channel-description bs-ag-blks-res 1
+ early-classmark-sending forbidden
+ ipa unit-id 6969 0
+ oml ipa stream-id 255 line 0
+ codec-support fr
+ gprs mode gprs
+ neighbor cgi-ps 23 42 423 2 5 arfcn 23 bsic 32
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ ! to use full TRX power, set max_power_red 0
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config TCH/F
+ hopping enabled 0
+msc 0
+ type normal
+ allow-emergency allow
+ amr-config 12_2k forbidden
+ amr-config 10_2k forbidden
+ amr-config 7_95k forbidden
+ amr-config 7_40k forbidden
+ amr-config 6_70k forbidden
+ amr-config 5_90k allowed
+ amr-config 5_15k forbidden
+ amr-config 4_75k forbidden
+ mgw remote-ip 127.0.0.1
+ mgw remote-port 2427
+ mgw local-port 2727
+ mgw endpoint-range 1 31
+bsc
+ mid-call-timeout 0
diff --git a/tests/ctrl_test_runner.py b/tests/ctrl_test_runner.py
index 5d2af859a..fb983c984 100755
--- a/tests/ctrl_test_runner.py
+++ b/tests/ctrl_test_runner.py
@@ -488,11 +488,34 @@ class TestCtrlBSC(TestCtrlBase):
self.assertEqual(r['var'], 'mcc')
self.assertEqual(r['value'], '002')
-def add_bsc_test(suite, workdir):
+class TestCtrlBSCNeighbor(TestCtrlBase):
+
+ def tearDown(self):
+ TestCtrlBase.tearDown(self)
+ os.unlink("tmp_dummy_sock")
+
+ def ctrl_command(self):
+ return ["./src/osmo-bsc/osmo-bsc", "-r", "tmp_dummy_sock", "-c",
+ "tests/ctrl/osmo-bsc-neigh-test.cfg"]
+
+ def ctrl_app(self):
+ return (4248, "./src/osmo-bsc/osmo-bsc", "OsmoBSC", "bsc")
+
+ def testCtrlNeighborResolution(self):
+ r = self.do_get('neighbor_resolve_cgi_ps_from_lac_ci')
+ self.assertEqual(r['mtype'], 'ERROR')
+ self.assertEqual(r['error'], 'The format is <src_lac>,<src_cell_id>,<dst_arfcn>,<dst_bsic>')
+
+ r = self.do_get('neighbor_resolve_cgi_ps_from_lac_ci.1.6969.23.32')
+ self.assertEqual(r['mtype'], 'GET_REPLY')
+ self.assertEqual(r['var'], 'neighbor_resolve_cgi_ps_from_lac_ci.1.6969.23.32')
+ self.assertEqual(r['value'], '023-42-423-2-5')
+
+def add_bsc_test(suite, workdir, klass):
if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")):
print("Skipping the BSC test")
return
- test = unittest.TestLoader().loadTestsFromTestCase(TestCtrlBSC)
+ test = unittest.TestLoader().loadTestsFromTestCase(klass)
suite.addTest(test)
if __name__ == '__main__':
@@ -525,6 +548,7 @@ if __name__ == '__main__':
os.chdir(workdir)
print("Running tests for specific control commands")
suite = unittest.TestSuite()
- add_bsc_test(suite, workdir)
+ add_bsc_test(suite, workdir, TestCtrlBSC)
+ add_bsc_test(suite, workdir, TestCtrlBSCNeighbor)
res = unittest.TextTestRunner(verbosity=verbose_level).run(suite)
sys.exit(len(res.errors) + len(res.failures))
diff --git a/tests/gsm0408/Makefile.am b/tests/gsm0408/Makefile.am
index a00da466f..571e7e67f 100644
--- a/tests/gsm0408/Makefile.am
+++ b/tests/gsm0408/Makefile.am
@@ -7,6 +7,7 @@ AM_CFLAGS = \
-Wall \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
+ $(LIBOSMOCTRL_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
$(NULL)
@@ -46,5 +47,6 @@ gsm0408_test_LDADD = \
$(top_builddir)/src/osmo-bsc/nm_rcarrier_fsm.o \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
+ $(LIBOSMOCTRL_LIBS) \
$(LIBOSMOABIS_LIBS) \
$(NULL)
diff --git a/tests/neighbor_ident.vty b/tests/neighbor_ident.vty
index ce414e124..93571b772 100644
--- a/tests/neighbor_ident.vty
+++ b/tests/neighbor_ident.vty
@@ -14,6 +14,10 @@ OsmoBSC# list
OsmoBSC# configure terminal
OsmoBSC(config)# network
+
+OsmoBSC(config-net)# neighbor-resolution bind 1.2.3.4 ?
+ [<0-65535>] Port to bind the service to [defaults to 4248 if not provided]
+
OsmoBSC(config-net)# bts 0
OsmoBSC(config-net-bts)# type sysmobts
OsmoBSC(config-net-bts)# base_station_id_code 10
@@ -84,9 +88,11 @@ OsmoBSC(config-net-bts)# list
neighbor lac <0-65535>
neighbor lac-ci <0-65535> <0-65535>
neighbor cgi <0-999> <0-999> <0-65535> <0-65535>
+ neighbor cgi-ps <0-999> <0-999> <0-65535> <0-255> <0-65535>
neighbor lac <0-65535> arfcn <0-1023> bsic (<0-63>|any)
neighbor lac-ci <0-65535> <0-65535> arfcn <0-1023> bsic (<0-63>|any)
neighbor cgi <0-999> <0-999> <0-65535> <0-65535> arfcn <0-1023> bsic (<0-63>|any)
+ neighbor cgi-ps <0-999> <0-999> <0-65535> <0-255> <0-65535> arfcn <0-1023> bsic (<0-63>|any)
no neighbor bts <0-255>
no neighbor arfcn <0-1023> bsic (<0-63>|any)
no neighbors
@@ -100,6 +106,7 @@ OsmoBSC(config-net-bts)# neighbor ?
lac Add Neighbor cell by LAC
lac-ci Add Neighbor cell by LAC and CI
cgi Add Neighbor cell by cgi
+ cgi-ps Add Neighbor cell by cgi (Packet Switched, with RAC)
OsmoBSC(config-net-bts)# neighbor bts ?
<0-255> BTS number
@@ -348,12 +355,16 @@ OsmoBSC(config-net-bts)# neighbor lac 456 arfcn 123 bsic 45
OsmoBSC(config-net-bts)# neighbor lac-ci 789 10 arfcn 423 bsic any
% BTS 0 to ARFCN 423 (any BSIC) now has 1 remote BSS Cell Identifier List entry
+OsmoBSC(config-net-bts)# neighbor cgi-ps 23 42 423 2 5 arfcn 23 bsic 32
+% BTS 0 to ARFCN 23 BSIC 32 now has 1 remote BSS Cell Identifier List entry
+
OsmoBSC(config-net-bts)# no neighbors
% Removed local neighbor bts 0 to bts 1
% Removed local neighbor bts 0 to bts 2
% Removed remote BSS neighbor BTS 0 to ARFCN 23 BSIC 42
% Removed remote BSS neighbor BTS 0 to ARFCN 123 BSIC 45
% Removed remote BSS neighbor BTS 0 to ARFCN 423 (any BSIC)
+% Removed remote BSS neighbor BTS 0 to ARFCN 23 BSIC 32
OsmoBSC(config-net-bts)# show running-config
... !neighbor