diff --git a/openbsc/configure.in b/openbsc/configure.in index f43f6e61b..50189a4aa 100644 --- a/openbsc/configure.in +++ b/openbsc/configure.in @@ -22,7 +22,7 @@ AC_SEARCH_LIBS(gtp_new, gtp, AM_CONDITIONAL(HAVE_LIBGTP, test "x$GPRS_LIBGTP" != "x") -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.14) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.15) PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.9) dnl checks for header files diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index a66804533..e276e1eee 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -540,6 +540,10 @@ struct gsm_bts { } data; } si_common; + /* do we use static (user-defined) system information messages? (bitmask) */ + uint32_t si_mode_static; + /* bitmask of all SI that are present/valid in si_buf */ + uint32_t si_valid; /* buffers where we put the pre-computed SI */ sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE]; diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c index ce668086d..7d9a520aa 100644 --- a/openbsc/src/bsc_init.c +++ b/openbsc/src/bsc_init.c @@ -787,9 +787,12 @@ static int generate_and_rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i struct gsm_bts *bts = trx->bts; int rc; - rc = gsm_generate_si(bts, i); - if (rc < 0) - return rc; + /* Only generate SI if this SI is not in "static" (user-defined) mode */ + if (!(bts->si_mode_static & (1 << i))) { + rc = gsm_generate_si(bts, i); + if (rc < 0) + return rc; + } DEBUGP(DRR, "SI%s: %s\n", gsm_sitype_name(i), hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN)); @@ -821,26 +824,31 @@ static int set_system_infos(struct gsm_bts_trx *trx) ms_pwr_ctl_lvl(bts->band, bts->ms_max_power); bts->si_common.cell_sel_par.neci = bts->network->neci; + /* First, we determine which of the SI messages we actually need */ + if (trx == bts->c0) { - for (i = SYSINFO_TYPE_1; i <= SYSINFO_TYPE_4; i++) { - rc = generate_and_rsl_si(trx, i); - if (rc < 0) - goto err_out; - } - if (bts->gprs.mode != BTS_GPRS_NONE) { - rc = generate_and_rsl_si(trx, SYSINFO_TYPE_13); - if (rc < 0) - goto err_out; - } + /* 1...4 are always present on a C0 TRX */ + for (i = SYSINFO_TYPE_1; i <= SYSINFO_TYPE_4; i++) + bts->si_valid |= (1 << i); + + /* 13 is always present on a C0 TRX of a GPRS BTS */ + if (bts->gprs.mode != BTS_GPRS_NONE) + bts->si_valid |= (1 << SYSINFO_TYPE_13); } - rc = generate_and_rsl_si(trx, SYSINFO_TYPE_5); - if (rc < 0) - goto err_out; + /* 5 and 6 are always present on every TRX */ + bts->si_valid |= (1 << SYSINFO_TYPE_5); + bts->si_valid |= (1 << SYSINFO_TYPE_6); - rc = generate_and_rsl_si(trx, SYSINFO_TYPE_6); - if (rc < 0) - goto err_out; + /* Second, we generate and send the selected SI via RSL */ + for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) { + if (!(bts->si_valid & (1 << i))) + continue; + + rc = generate_and_rsl_si(trx, i); + if (rc < 0) + goto err_out; + } return 0; err_out: diff --git a/openbsc/src/bsc_vty.c b/openbsc/src/bsc_vty.c index a308ec475..739fd8c57 100644 --- a/openbsc/src/bsc_vty.c +++ b/openbsc/src/bsc_vty.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include "../bscconfig.h" @@ -225,6 +227,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) VTY_NEWLINE); if (bts->si_common.rach_control.cell_bar) vty_out(vty, " CELL IS BARRED%s", VTY_NEWLINE); + vty_out(vty, "System Information present: 0x%08x, static: 0x%08x%s", + bts->si_valid, bts->si_mode_static, VTY_NEWLINE); if (is_ipaccess_bts(bts)) vty_out(vty, " Unit ID: %u/%u/0, OML Stream ID 0x%02x%s", bts->ip_access.site_id, bts->ip_access.bts_id, @@ -386,6 +390,7 @@ static void config_write_bts_gprs(struct vty *vty, struct gsm_bts *bts) static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) { struct gsm_bts_trx *trx; + int i; vty_out(vty, " bts %u%s", bts->nr, VTY_NEWLINE); vty_out(vty, " type %s%s", btstype2str(bts->type), VTY_NEWLINE); @@ -424,6 +429,16 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " cell barred 1%s", VTY_NEWLINE); if ((bts->si_common.rach_control.t2 & 0x4) == 0) vty_out(vty, " rach emergency call allowed 1%s", VTY_NEWLINE); + for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) { + if (bts->si_mode_static & (1 << i)) { + vty_out(vty, " system-information %s mode static%s", + get_value_string(osmo_sitype_strs, i), VTY_NEWLINE); + vty_out(vty, " system-information %s static %s%s", + get_value_string(osmo_sitype_strs, i), + hexdump_nospc(bts->si_buf[i], sizeof(bts->si_buf[i])), + VTY_NEWLINE); + } + } if (is_ipaccess_bts(bts)) { vty_out(vty, " ip.access unit_id %u %u%s", bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE); @@ -1838,6 +1853,88 @@ DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd, return CMD_SUCCESS; } +#define SI_TEXT "System Information Messages\n" +#define SI_TYPE_TEXT "(1|2|3|4|5|6|7|8|9|10|13|16|17|18|19|20|2bis|2ter|2quater|5bis|5ter)" +#define SI_TYPE_HELP "System Information Type 1\n" \ + "System Information Type 2\n" \ + "System Information Type 3\n" \ + "System Information Type 4\n" \ + "System Information Type 5\n" \ + "System Information Type 6\n" \ + "System Information Type 7\n" \ + "System Information Type 8\n" \ + "System Information Type 9\n" \ + "System Information Type 10\n" \ + "System Information Type 13\n" \ + "System Information Type 16\n" \ + "System Information Type 17\n" \ + "System Information Type 18\n" \ + "System Information Type 19\n" \ + "System Information Type 20\n" \ + "System Information Type 2bis\n" \ + "System Information Type 2ter\n" \ + "System Information Type 2quater\n" \ + "System Information Type 5bis\n" \ + "System Information Type 5ter\n" + +DEFUN(cfg_bts_si_mode, cfg_bts_si_mode_cmd, + "system-information " SI_TYPE_TEXT " mode (static|computed)", + SI_TEXT SI_TYPE_HELP + "System Information Mode\n" + "Static user-specified\n" + "Dynamic, BSC-computed\n") +{ + struct gsm_bts *bts = vty->index; + int type; + + type = get_string_value(osmo_sitype_strs, argv[0]); + if (type < 0) { + vty_out(vty, "Error SI Type%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (!strcmp(argv[1], "static")) + bts->si_mode_static |= (1 << type); + else + bts->si_mode_static &= ~(1 << type); + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd, + "system-information " SI_TYPE_TEXT " static HEXSTRING", + SI_TEXT SI_TYPE_HELP + "Static System Information filling\n" + "Static user-specified SI content in HEX notation\n") +{ + struct gsm_bts *bts = vty->index; + int rc, type; + + type = get_string_value(osmo_sitype_strs, argv[0]); + if (type < 0) { + vty_out(vty, "Error SI Type%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (!(bts->si_mode_static & (1 << type))) { + vty_out(vty, "SI Type %s is not configured in static mode%s", + get_value_string(osmo_sitype_strs, type), VTY_NEWLINE); + return CMD_WARNING; + } + + rc = hexparse(argv[1], bts->si_buf[type], sizeof(bts->si_buf[0])); + if (rc < 0 || rc > sizeof(bts->si_buf[0])) { + vty_out(vty, "Error parsing HEXSTRING%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* Mark this SI as present */ + bts->si_valid |= (1 << type); + + return CMD_SUCCESS; +} + + #define TRX_TEXT "Radio Transceiver\n" /* per TRX configuration */ @@ -2223,6 +2320,8 @@ int bsc_vty_init(void) install_element(BTS_NODE, &cfg_bts_gprs_nsvc_lport_cmd); install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rport_cmd); install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rip_cmd); + install_element(BTS_NODE, &cfg_bts_si_mode_cmd); + install_element(BTS_NODE, &cfg_bts_si_static_cmd); install_element(BTS_NODE, &cfg_trx_cmd); install_node(&trx_node, dummy_config_write);