From 59a1bf3dae0d0a9e914d3c615c6aa7fc8955d7b5 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 15 Apr 2016 16:04:46 +0200 Subject: Add basic SI2quater support * support for sending arbitrary static SI2quater. * vty interface for neightbor EARFCNs specific to SI2quater. * dynamic generation of SI2quater messages. * unit test for SI2quater messages. Fixes: OS#1630 --- openbsc/src/libbsc/bsc_init.c | 6 +- openbsc/src/libbsc/bsc_vty.c | 71 ++++++++++++ openbsc/src/libbsc/rest_octets.c | 200 ++++++++++++++++++++++++++++++++ openbsc/src/libbsc/system_information.c | 23 ++++ 4 files changed, 297 insertions(+), 3 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index fd8dd6677..fea65629f 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -192,9 +192,9 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) return 0; err_out: - LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u, most likely " - "a problem with neighbor cell list generation\n", - get_value_string(osmo_sitype_strs, i), bts->nr); + LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u: error <%s>," + "most likely a problem with neighbor cell list generation\n", + get_value_string(osmo_sitype_strs, i), bts->nr, strerror(-rc)); return rc; } diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 29f2501f8..9634508e1 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -692,6 +692,21 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + for (i = 0; i < MAX_EARFCN_LIST; i++) { + if (bts->si_common.si2quater_neigh_list.arfcn[i] != + OSMO_EARFCN_INVALID) { + vty_out(vty, " si2quater neighbor-list add earfcn %u threshold %u", + bts->si_common.si2quater_neigh_list.arfcn[i], + bts->si_common.si2quater_neigh_list.thresh_hi); + if (bts->si_common.si2quater_neigh_list.meas_bw[i] != + OSMO_EARFCN_MEAS_INVALID) + vty_out(vty, " %u", + bts->si_common.si2quater_neigh_list.meas_bw[i]); + + vty_out(vty, "%s", VTY_NEWLINE); + } + } + vty_out(vty, " codec-support fr"); if (bts->codec.hr) vty_out(vty, " hr"); @@ -2743,6 +2758,60 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, + "si2quater neighbor-list add earfcn <1900-2200> threshold <0-1000> " + "[<0-255>]", "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" + "EARFCN of neighbor\n" "EARFCN of neighbor\n" "threshold high bits\n" + "threshold high bits\n" "measurement bandwidth\n") +{ + struct gsm_bts *bts = vty->index; + struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + uint16_t arfcn = atoi(argv[0]); + uint8_t meas = OSMO_EARFCN_MEAS_INVALID, thresh = atoi(argv[1]); + int r; + + if (3 == argc) + meas = atoi(argv[2]); + + r = osmo_earfcn_add(e, arfcn, meas); + + if (r < 0) { + vty_out(vty, "Unable to add arfcn %u: %s%s", arfcn, strerror(r), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (e->thresh_hi && thresh != e->thresh_hi) + vty_out(vty, "Warning: multiple thresholds are not supported, " + "overriding previous threshold %u%s", + e->thresh_hi, VTY_NEWLINE); + + e->thresh_hi = thresh; + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, + "si2quater neighbor-list del earfcn <1900-2200>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" + "Delete from SI2quater manual neighbor list\n" + "EARFCN of neighbor\n") +{ + struct gsm_bts *bts = vty->index; + struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + uint16_t arfcn = atoi(argv[1]); + int r = osmo_earfcn_del(e, arfcn); + if (r < 0) { + vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn, + strerror(r), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd, "si5 neighbor-list (add|del) arfcn <0-1023>", "SI5 Neighbor List\n" @@ -3873,6 +3942,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd); install_element(BTS_NODE, &cfg_bts_neigh_cmd); install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 83cf2ec1f..113af5ca9 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -24,10 +24,15 @@ #include #include #include +#include +#include #include #include #include +#include + +#define SI2Q_MAX_LEN 160 /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) @@ -53,6 +58,201 @@ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) return bv.data_len; } +/* Append Repeated E-UTRAN Neighbour Cell to bitvec: + * see 3GPP TS 44.018 Table 10.5.2.33b.1 + */ +static inline void append_eutran_neib_cell(struct bitvec *bv, + const struct osmo_earfcn_si2q *e) +{ + unsigned i; + for (i = 0; i < e->length; i++) { + if (e->arfcn[i] != OSMO_EARFCN_INVALID) { + bitvec_set_bit(bv, 1); /* EARFCN: */ + bitvec_set_uint(bv, e->arfcn[i], 16); + + if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i]) + bitvec_set_bit(bv, 0); + else { + /* Measurement Bandwidth: 9.1.54 */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->meas_bw[i], 3); + } + } + } + + /* stop bit - end of EARFCN + Measurement Bandwidth sequence */ + bitvec_set_bit(bv, 0); + + if (e->prio_valid) { + /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->prio, 3); + } else + bitvec_set_bit(bv, 0); + + /* THRESH_E-UTRAN_high */ + bitvec_set_uint(bv, e->thresh_hi, 5); + + if (e->thresh_lo_valid) { + /* THRESH_E-UTRAN_low: */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->thresh_lo, 5); + } else + bitvec_set_bit(bv, 0); + + if (e->qrxlm_valid) { + /* E-UTRAN_QRXLEVMIN: */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->qrxlm, 5); + } else + bitvec_set_bit(bv, 0); +} + +static inline int append_earfcn_size(const struct osmo_earfcn_si2q *e) +{ + if (!e) + return -EFAULT; + /* account for all the constant bits */ + return 25 + osmo_earfcn_bit_size(e); +} + +static inline void append_earfcn(struct bitvec *bv, + const struct osmo_earfcn_si2q *e) +{ + /* Additions in Rel-5: */ + bitvec_set_bit(bv, H); + /* No 3G Additional Measurement Param. Descr. */ + bitvec_set_bit(bv, 0); + /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-6: */ + bitvec_set_bit(bv, H); + /* 3G_CCN_ACTIVE */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-7: */ + bitvec_set_bit(bv, H); + /* No 700_REPORTING_OFFSET */ + bitvec_set_bit(bv, 0); + /* No 810_REPORTING_OFFSET */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-8: */ + bitvec_set_bit(bv, H); + + /* Priority and E-UTRAN Parameters Description */ + bitvec_set_bit(bv, 1); + + /* No Serving Cell Priority Parameters Descr. */ + bitvec_set_bit(bv, 0); + /* No 3G Priority Parameters Description */ + bitvec_set_bit(bv, 0); + /* E-UTRAN Parameters Description */ + bitvec_set_bit(bv, 1); + + /* E-UTRAN_CCN_ACTIVE */ + bitvec_set_bit(bv, 0); + /* E-UTRAN_Start: 9.1.54 */ + bitvec_set_bit(bv, 1); + /* E-UTRAN_Stop: 9.1.54 */ + bitvec_set_bit(bv, 1); + + /* No E-UTRAN Measurement Parameters Descr. */ + bitvec_set_bit(bv, 0); + /* No GPRS E-UTRAN Measurement Param. Descr. */ + bitvec_set_bit(bv, 0); + + /* Note: each of next 3 "repeated" structures might be repeated any + (0, 1, 2...) times - we only support 1 and 0 */ + + /* Repeated E-UTRAN Neighbour Cells */ + bitvec_set_bit(bv, 1); + + /* Note: we don't support different EARFCN arrays each with different + priority, threshold etc. */ + append_eutran_neib_cell(bv, e); + + /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */ + bitvec_set_bit(bv, 0); + + /* Note: following 2 repeated structs are not supported ATM */ + /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */ + bitvec_set_bit(bv, 0); + /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */ + bitvec_set_bit(bv, 0); + + /* Priority and E-UTRAN Parameters Description ends here */ + /* No 3G CSG Description */ + bitvec_set_bit(bv, 0); + /* No E-UTRAN CSG Description */ + bitvec_set_bit(bv, 0); + /* No Additions in Rel-9: */ + bitvec_set_bit(bv, L); +} + +/* generate SI2quater rest octets: 3GPP TS 44.018 ยง 10.5.2.33b */ +int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, + bool uarfcn, bool earfcn) +{ + int rc; + struct bitvec bv; + bv.data = data; + bv.data_len = 20; + bitvec_zero(&bv); + + /* BA_IND */ + bitvec_set_bit(&bv, 1); + /* 3G_BA_IND */ + bitvec_set_bit(&bv, 1); + /* MP_CHANGE_MARK */ + bitvec_set_bit(&bv, 0); + + /* we do not support multiple si2quater messages at the moment: */ + /* SI2quater_INDEX */ + bitvec_set_uint(&bv, 0, 4); + /* SI2quater_COUNT */ + bitvec_set_uint(&bv, 0, 4); + + /* No Measurement_Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_Real Time Difference Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_BSIC Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_REPORT PRIORITY Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_MEASUREMENT_Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No NC Measurement Parameters */ + bitvec_set_bit(&bv, 0); + /* No extension (length) */ + bitvec_set_bit(&bv, 0); + + if (uarfcn) { + + } else { /* No 3G Neighbour Cell Description */ + bitvec_set_bit(&bv, 0); + } + + /* No 3G Measurement Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_3G_MEASUREMENT Parameters Descr. */ + bitvec_set_bit(&bv, 0); + + if (earfcn) { + rc = append_earfcn_size(e); + if (rc < 0) + return rc; + if (rc + bv.cur_bit > SI2Q_MAX_LEN) + return -ENOMEM; + append_earfcn(&bv, e); + } else { + /* No Additions in Rel-5: */ + bitvec_set_bit(&bv, L); + } + + bitvec_spare_padding(&bv, (bv.data_len * 8) - 1); + return bv.data_len; +} + /* Append selection parameters to bitvec */ static void append_selection_params(struct bitvec *bv, const struct gsm48_si_selection_params *sp) diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 5490c8361..43a492af1 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -494,6 +494,28 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts) return sizeof(*si2t); } +static int generate_si2quater(uint8_t *output, struct gsm_bts *bts) +{ + int rc; + struct gsm48_system_information_type_2quater *si2q = + (struct gsm48_system_information_type_2quater *) output; + + memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN); + + si2q->header.l2_plen = GSM48_LEN2PLEN(22); + si2q->header.rr_protocol_discriminator = GSM48_PDISC_RR; + si2q->header.skip_indicator = 0; + si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; + + rc = rest_octets_si2quater(si2q->rest_octets, + &bts->si_common.si2quater_neigh_list, false, + true); + if (rc < 0) + return rc; + + return sizeof(*si2q) + rc; +} + static struct gsm48_si_ro_info si_info = { .selection_params = { .present = 0, @@ -831,6 +853,7 @@ static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = { [SYSINFO_TYPE_2] = &generate_si2, [SYSINFO_TYPE_2bis] = &generate_si2bis, [SYSINFO_TYPE_2ter] = &generate_si2ter, + [SYSINFO_TYPE_2quater] = &generate_si2quater, [SYSINFO_TYPE_3] = &generate_si3, [SYSINFO_TYPE_4] = &generate_si4, [SYSINFO_TYPE_5] = &generate_si5, -- cgit v1.2.3