diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index fe19ff441..a8b2de958 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -26,20 +26,6 @@ static inline struct msgb *gsm48_msgb_alloc_name(const char *name) name); } -static inline int get_radio_link_timeout(struct gsm48_cell_options *cell_options) -{ - return (cell_options->radio_link_timeout + 1) << 2; -} - -static inline void set_radio_link_timeout(struct gsm48_cell_options *cell_options, int value) -{ - if (value < 4) - value = 4; - if (value > 64) - value = 64; - cell_options->radio_link_timeout = (value >> 2) - 1; -} - /* config options controlling the behaviour of the lower leves */ void gsm0408_allow_everyone(int allow); void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 5ab7c3fbd..a97405105 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -590,4 +590,7 @@ void bts_depend_clear(struct gsm_bts *bts, int dep); int bts_depend_check(struct gsm_bts *bts); int bts_depend_is_depedency(struct gsm_bts *base, struct gsm_bts *other); +int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts); +void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value); + #endif /* _GSM_DATA_H */ diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index d3fd75700..4c71a075e 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -872,6 +872,8 @@ struct gsm_bts { } data; } si_common; bool early_classmark_allowed; + /* for testing only: Have an infinitely long radio link timeout */ + bool infinite_radio_link_timeout; /* do we use static (user-defined) system information messages? (bitmask) */ uint32_t si_mode_static; diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 2fc39ab4c..9fc289503 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -604,9 +604,11 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " periodic location update %u%s", bts->si_common.chan_desc.t3212 * 6, VTY_NEWLINE); - vty_out(vty, " radio-link-timeout %d%s", - get_radio_link_timeout(&bts->si_common.cell_options), - VTY_NEWLINE); + if (gsm_bts_get_radio_link_timeout(bts) < 0) + vty_out(vty, " radio-link-timeout infinite%s", VTY_NEWLINE); + else + vty_out(vty, " radio-link-timeout %d%s", + gsm_bts_get_radio_link_timeout(bts), VTY_NEWLINE); vty_out(vty, " channel allocator %s%s", bts->chan_alloc_reverse ? "descending" : "ascending", VTY_NEWLINE); @@ -2299,7 +2301,25 @@ DEFUN(cfg_bts_radio_link_timeout, cfg_bts_radio_link_timeout_cmd, { struct gsm_bts *bts = vty->index; - set_radio_link_timeout(&bts->si_common.cell_options, atoi(argv[0])); + gsm_bts_set_radio_link_timeout(bts, atoi(argv[0])); + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_radio_link_timeout_inf, cfg_bts_radio_link_timeout_inf_cmd, + "radio-link-timeout infinite", + "Radio link timeout criterion (BTS side)\n" + "Infinite Radio link timeout value (use only for BTS RF testing)\n") +{ + struct gsm_bts *bts = vty->index; + + if (bts->type != GSM_BTS_TYPE_OSMOBTS) { + vty_out(vty, "%% infinite radio link timeout not supported by this BTS%s", VTY_NEWLINE); + return CMD_WARNING; + } + + vty_out(vty, "%% INFINITE RADIO LINK TIMEOUT, USE ONLY FOR BTS RF TESTING%s", VTY_NEWLINE); + gsm_bts_set_radio_link_timeout(bts, -1); return CMD_SUCCESS; } @@ -4180,6 +4200,7 @@ int bsc_vty_init(struct gsm_network *network) install_element(BTS_NODE, &cfg_bts_penalty_time_cmd); install_element(BTS_NODE, &cfg_bts_penalty_time_rsvd_cmd); install_element(BTS_NODE, &cfg_bts_radio_link_timeout_cmd); + install_element(BTS_NODE, &cfg_bts_radio_link_timeout_inf_cmd); install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd); install_element(BTS_NODE, &cfg_bts_gprs_11bit_rach_support_for_egprs_cmd); install_element(BTS_NODE, &cfg_bts_gprs_ns_timer_cmd); diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c b/openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c index 0291129d0..473e1caea 100644 --- a/openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c +++ b/openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c @@ -38,6 +38,7 @@ struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts) { struct msgb *msgb; uint8_t buf[256]; + int rlt; msgb = msgb_alloc(1024, "nanobts_attr_bts"); memcpy(buf, "\x55\x5b\x61\x67\x6d\x73", 6); @@ -46,9 +47,16 @@ struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts) /* interference avg. period in numbers of SACCH multifr */ msgb_tv_put(msgb, NM_ATT_INTAVE_PARAM, 0x06); - /* conn fail based on SACCH error rate */ - buf[0] = 0x01; - buf[1] = get_radio_link_timeout(&bts->si_common.cell_options); + rlt = gsm_bts_get_radio_link_timeout(bts); + if (rlt == -1) { + /* Osmocom extension: Use infinite radio link timeout */ + buf[0] = 0xFF; + buf[1] = 0x00; + } else { + /* conn fail based on SACCH error rate */ + buf[0] = 0x01; + buf[1] = rlt; + } msgb_tl16v_put(msgb, NM_ATT_CONN_FAIL_CRIT, 2, buf); memcpy(buf, "\x1e\x24\x24\xa8\x34\x21\xa8", 7); diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 8830ce144..db7de082d 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -323,8 +323,7 @@ struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_typ bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5; /* paging frames */ bts->si_common.chan_desc.bs_ag_blks_res = 1; /* reserved AGCH blocks */ bts->si_common.chan_desc.t3212 = 5; /* Use 30 min periodic update interval as sane default */ - set_radio_link_timeout(&bts->si_common.cell_options, 32); - /* Use RADIO LINK TIMEOUT of 32 seconds */ + gsm_bts_set_radio_link_timeout(bts, 32); /* Use RADIO LINK TIMEOUT of 32 */ llist_add_tail(&bts->list, &net->bts_list); @@ -435,3 +434,40 @@ int bts_depend_check(struct gsm_bts *bts) } return 1; } + +/* get the radio link timeout (based on SACCH decode errors, according + * to algorithm specified in TS 05.08 section 5.2. A value of -1 + * indicates we should use an infinitely long timeout, which only works + * with OsmoBTS as the BTS implementation */ +int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts) +{ + const struct gsm48_cell_options *cell_options = &bts->si_common.cell_options; + + if (bts->infinite_radio_link_timeout) + return -1; + else { + /* Encoding as per Table 10.5.21 of TS 04.08 */ + return (cell_options->radio_link_timeout + 1) << 2; + } +} + +/* set the radio link timeout (based on SACCH decode errors, according + * to algorithm specified in TS 05.08 Section 5.2. A value of -1 + * indicates we should use an infinitely long timeout, which only works + * with OsmoBTS as the BTS implementation */ +void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value) +{ + struct gsm48_cell_options *cell_options = &bts->si_common.cell_options; + + if (value < 0) + bts->infinite_radio_link_timeout = true; + else { + bts->infinite_radio_link_timeout = false; + /* Encoding as per Table 10.5.21 of TS 04.08 */ + if (value < 4) + value = 4; + if (value > 64) + value = 64; + cell_options->radio_link_timeout = (value >> 2) - 1; + } +}