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 <>: 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 <> 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 +<>, 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 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 <>). + +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.... +GET_REPLY ---- +---- + +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 #include +#include 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 +#include +#include + +#include +#include +#include + 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 ,,,"); + 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 #include #include +#include + +#include #include #include @@ -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 ,,,') + + 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