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
This commit is contained in:
Pau Espin Pedrol 2020-12-21 18:12:58 +01:00 committed by Pau Espin Pedrol
parent 63f98f22a0
commit 55a015dddf
14 changed files with 471 additions and 7 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -41,6 +41,7 @@ EXTRA_DIST = \
osmo-bsc.vty \
timer.vty \
power_ctrl.vty \
ctrl/osmo-bsc-neigh-test.cfg \
$(NULL)
TESTSUITE = $(srcdir)/testsuite

View File

@ -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) \

View File

@ -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

View File

@ -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))

View File

@ -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)

View File

@ -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