From 3a38ee6c3d9985200b10229b27f3b9ae9edd50ae Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 16 Mar 2016 14:27:29 +0100 Subject: abis: Send the message without enforcing to wait for a response The user might issue restarts while no BTS is connected and we should not block the abis queue because of these messages. --- openbsc/src/libbsc/abis_nm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c index c05e2f94f..3afc4c497 100644 --- a/openbsc/src/libbsc/abis_nm.c +++ b/openbsc/src/libbsc/abis_nm.c @@ -2598,7 +2598,7 @@ int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx) fill_om_fom_hdr(oh, 0, NM_MT_IPACC_RESTART, NM_OC_BASEB_TRANSC, trx->bts->nr, trx->nr, 0xff); - return abis_nm_sendmsg(trx->bts, msg); + return abis_nm_sendmsg_direct(trx->bts, msg); } int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, uint8_t obj_class, -- cgit v1.2.3 From 740e65fb7bd1516117cd23c7b524976548e1a397 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 16 Mar 2016 13:45:23 +0100 Subject: bsc: Add code to send ip.access reboot command to nanoBTS The nanoBTS continues to be buggy and seems to have broken BSSGP when changing SIs across new OML connections. Add an easy command to force the reboot of the system through OML. --- openbsc/src/libbsc/bsc_vty.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 7fdee054c..29f2501f8 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -3596,6 +3596,44 @@ DEFUN(drop_bts, return CMD_SUCCESS; } +DEFUN(restart_bts, restart_bts_cmd, + "restart-bts <0-65535>", + "Restart ip.access nanoBTS through OML\n" + "BTS Number\n") +{ + struct gsm_network *gsmnet; + struct gsm_bts_trx *trx; + struct gsm_bts *bts; + unsigned int bts_nr; + + gsmnet = gsmnet_from_vty(vty); + + bts_nr = atoi(argv[0]); + if (bts_nr >= gsmnet->num_bts) { + vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s", + gsmnet->num_bts, bts_nr, VTY_NEWLINE); + return CMD_WARNING; + } + + bts = gsm_bts_num(gsmnet, bts_nr); + if (!bts) { + vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE); + return CMD_WARNING; + } + + if (!is_ipaccess_bts(bts) || is_sysmobts_v2(bts)) { + vty_out(vty, "This command only works for ipaccess nanoBTS.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* go from last TRX to c0 */ + llist_for_each_entry_reverse(trx, &bts->trx_list, list) + abis_nm_ipaccess_restart(trx); + + return CMD_SUCCESS; +} + DEFUN(smscb_cmd, smscb_cmd_cmd, "bts <0-255> smscb-command <1-4> HEXSTRING", "BTS related commands\n" "BTS Number\n" @@ -3895,6 +3933,7 @@ int bsc_vty_init(const struct log_info *cat) install_element(TS_NODE, &cfg_ts_e1_subslot_cmd); install_element(ENABLE_NODE, &drop_bts_cmd); + install_element(ENABLE_NODE, &restart_bts_cmd); install_element(ENABLE_NODE, &pdch_act_cmd); install_element(ENABLE_NODE, &smscb_cmd_cmd); -- cgit v1.2.3 From c6a65511f326340783f0e837c6eb58b0cf2c6abc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 16 Mar 2016 15:27:38 +0100 Subject: bsc: Add parameter to restart a bts The ip.access nanoBTS seems to have severe issues with BSSGP when changing the country code and/or network code. It is unlikely that the proprietary code is getting fixed so we extend the parameter for the apply-configuration command to carry the 'restart' param. --- openbsc/src/libbsc/bsc_ctrl_commands.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_ctrl_commands.c b/openbsc/src/libbsc/bsc_ctrl_commands.c index b6b1c9a8b..7e8479734 100644 --- a/openbsc/src/libbsc/bsc_ctrl_commands.c +++ b/openbsc/src/libbsc/bsc_ctrl_commands.c @@ -90,7 +90,17 @@ static int set_net_apply_config(struct ctrl_cmd *cmd, void *data) if (!is_ipaccess_bts(bts)) continue; - ipaccess_drop_oml(bts); + /* + * The ip.access nanoBTS seems to be unrelaible on BSSGP + * so let's us just reboot it. For the sysmoBTS we can just + * restart the process as all state is gone. + */ + if (!is_sysmobts_v2(bts) && strcmp(cmd->value, "restart") == 0) { + struct gsm_bts_trx *trx; + llist_for_each_entry_reverse(trx, &bts->trx_list, list) + abis_nm_ipaccess_restart(trx); + } else + ipaccess_drop_oml(bts); } cmd->reply = "Tried to drop the BTS"; -- cgit v1.2.3 From 687f048ab04ed135eeb11deb29e6b4cb9727c27d Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 8 Apr 2016 11:52:34 +0200 Subject: Fix segfault with broken config Fixes OS#1691 --- openbsc/src/libbsc/bsc_init.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 859d9998f..713109c23 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -373,6 +373,9 @@ static int bootstrap_bts(struct gsm_bts *bts) { int i, n; + if (!bts->model) + return -EFAULT; + if (bts->model->start && !bts->model->started) { int ret = bts->model->start(bts->network); if (ret < 0) -- cgit v1.2.3 From 7a301d357612347723e59c7f16a97227814d406e Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 7 Apr 2016 11:38:52 +0200 Subject: Remove trivial wrapper function Rename gsm48_tx_chan_mode_modify() to gsm48_lchan_modify() and remove corresponding wrapper code. --- openbsc/src/libbsc/gsm_04_08_utils.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c index 8c6dbef9b..635665a3d 100644 --- a/openbsc/src/libbsc/gsm_04_08_utils.c +++ b/openbsc/src/libbsc/gsm_04_08_utils.c @@ -463,7 +463,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, /* * fill the channel information element, this code * should probably be shared with rsl_rx_chan_rqd(), - * gsm48_tx_chan_mode_modify. But beware that 10.5.2.5 + * gsm48_lchan_modify(). But beware that 10.5.2.5 * 10.5.2.5.a have slightly different semantic for * the chan_desc. But as long as multi-slot configurations * are not used we seem to be fine. @@ -488,7 +488,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, } /* 9.1.5 Channel mode modify: Modify the mode on the MS side */ -int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode) +int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode) { struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD"); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); @@ -513,17 +513,6 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode) return gsm48_sendmsg(msg); } -int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode) -{ - int rc; - - rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode); - if (rc < 0) - return rc; - - return rc; -} - int gsm48_rx_rr_modif_ack(struct msgb *msg) { int rc; -- cgit v1.2.3 From f3f3505f493f63e9e79c72e407907783913b9c9c Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 15 Apr 2016 16:04:44 +0200 Subject: Add SI2quater support to SI3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Advertise SI2 quater presence and location (if available) using SI3 according to 3GPP TS 44.018 § 10.5.2.34 --- openbsc/src/libbsc/bsc_init.c | 1 + openbsc/src/libbsc/rest_octets.c | 9 +++++++++ openbsc/src/libbsc/system_information.c | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 713109c23..fd8dd6677 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -140,6 +140,7 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) gen_si[n_si++] = SYSINFO_TYPE_2; gen_si[n_si++] = SYSINFO_TYPE_2bis; gen_si[n_si++] = SYSINFO_TYPE_2ter; + gen_si[n_si++] = SYSINFO_TYPE_2quater; gen_si[n_si++] = SYSINFO_TYPE_3; gen_si[n_si++] = SYSINFO_TYPE_4; diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 4545794a9..83cf2ec1f 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -129,6 +129,15 @@ int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3) /* GPRS Indicator */ append_gprs_ind(&bv, &si3->gprs_ind); + /* 3G Early Classmark Sending Restriction controlled by + * early_cm_ctrl above */ + bitvec_set_bit(&bv, H); + + if (si3->si2quater_indicator) { + bitvec_set_bit(&bv, H); /* indicator struct present */ + bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */ + } + bitvec_spare_padding(&bv, (bv.data_len*8)-1); return bv.data_len; } diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 1ee9d41c2..62ee30659 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -510,6 +510,7 @@ static struct gsm48_si_ro_info si_info = { .ra_colour = 0, .present = 1, }, + .si2quater_indicator = 0, .lsa_params = { .present = 0, }, @@ -545,7 +546,12 @@ static int generate_si3(uint8_t *output, struct gsm_bts *bts) } else { si_info.si2ter_indicator = 0; } - + if ((bts->si_valid & (1 << SYSINFO_TYPE_2quater))) { + LOGP(DRR, LOGL_INFO, "SI 2quater is included.\n"); + si_info.si2quater_indicator = 1; + } else { + si_info.si2quater_indicator = 0; + } /* SI3 Rest Octets (10.5.2.34), containing CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME Power Offset, 2ter Indicator, Early Classmark Sending, -- cgit v1.2.3 From 5fa7e36bbc100c5cec4542280ca717ae4800b316 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 15 Apr 2016 16:04:45 +0200 Subject: Refactor SI-related code Move define to header file. Use inline functions where appropriate. Change int variables which are used as boolean into actual bool to make code easier to follow. --- openbsc/src/libbsc/abis_rsl.c | 2 -- openbsc/src/libbsc/system_information.c | 37 +++++++++++++++++---------------- 2 files changed, 19 insertions(+), 20 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 8e9258ca5..df7678832 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -1332,8 +1332,6 @@ static void t3109_expired(void *data) rsl_rf_chan_release(lchan, 1, SACCH_NONE); } -#define GSM48_LEN2PLEN(a) (((a) << 2) | 1) - /* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */ static int rsl_send_imm_ass_rej(struct gsm_bts *bts, unsigned int num_req_refs, diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 62ee30659..5490c8361 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -67,8 +68,8 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } -static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter, - const int pgsm, const int arfcn) +static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, + const bool pgsm, const int arfcn) { if (bts->force_combined_si) return !bis && !ter; @@ -135,9 +136,9 @@ static int freq_list_bmrel_set_arfcn(uint8_t *chan_list, unsigned int arfcn) } /* generate a variable bitmap */ -static int enc_freq_lst_var_bitmap(uint8_t *chan_list, +static inline int enc_freq_lst_var_bitmap(uint8_t *chan_list, struct bitvec *bv, const struct gsm_bts *bts, - int bis, int ter, int min, int pgsm) + bool bis, bool ter, int min, bool pgsm) { int i; @@ -164,9 +165,9 @@ static int enc_freq_lst_var_bitmap(uint8_t *chan_list, } /* generate a frequency list with the range 512 format */ -static int enc_freq_lst_range(uint8_t *chan_list, +static inline int enc_freq_lst_range(uint8_t *chan_list, struct bitvec *bv, const struct gsm_bts *bts, - int bis, int ter, int pgsm) + bool bis, bool ter, bool pgsm) { int arfcns[RANGE_ENC_MAX_ARFCNS]; int w[RANGE_ENC_MAX_ARFCNS]; @@ -226,15 +227,15 @@ static int enc_freq_lst_range(uint8_t *chan_list, /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv, - const struct gsm_bts *bts, int bis, int ter) + const struct gsm_bts *bts, bool bis, bool ter) { - int i, rc, min = -1, max = -1, pgsm = 0, arfcns = 0; - + int i, rc, min = -1, max = -1, arfcns = 0; + bool pgsm = false; memset(chan_list, 0, 16); if (bts->band == GSM_BAND_900 && bts->c0->arfcn >= 1 && bts->c0->arfcn <= 124) - pgsm = 1; + pgsm = true; /* P-GSM-only handsets only support 'bit map 0 format' */ if (!bis && !ter && pgsm) { chan_list[0] = 0; @@ -327,12 +328,12 @@ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv, } /* then we generate a GSM 04.08 frequency list from the bitvec */ - return bitvec2freq_list(chan_list, bv, bts, 0, 0); + return bitvec2freq_list(chan_list, bv, bts, false, false); } /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ static int generate_bcch_chan_list(uint8_t *chan_list, struct gsm_bts *bts, - int si5, int bis, int ter) + bool si5, bool bis, bool ter) { struct gsm_bts *cur_bts; struct bitvec *bv; @@ -422,7 +423,7 @@ static int generate_si2(uint8_t *output, struct gsm_bts *bts) si2->header.skip_indicator = 0; si2->header.system_information = GSM48_MT_RR_SYSINFO_2; - rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, 0, 0, 0); + rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, false, false, false); if (rc < 0) return rc; list_arfcn(si2->bcch_frequency_list, 0xce, @@ -448,7 +449,7 @@ static int generate_si2bis(uint8_t *output, struct gsm_bts *bts) si2b->header.skip_indicator = 0; si2b->header.system_information = GSM48_MT_RR_SYSINFO_2bis; - rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, 0, 1, 0); + rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, false, true, false); if (rc < 0) return rc; n = list_arfcn(si2b->bcch_frequency_list, 0xce, @@ -482,7 +483,7 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts) si2t->header.skip_indicator = 0; si2t->header.system_information = GSM48_MT_RR_SYSINFO_2ter; - rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, 0, 0, 1); + rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, false, false, true); if (rc < 0) return rc; n = list_arfcn(si2t->ext_bcch_frequency_list, 0x8e, @@ -630,7 +631,7 @@ static int generate_si5(uint8_t *output, struct gsm_bts *bts) si5->rr_protocol_discriminator = GSM48_PDISC_RR; si5->skip_indicator = 0; si5->system_information = GSM48_MT_RR_SYSINFO_5; - rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, 1, 0, 0); + rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, true, false, false); if (rc < 0) return rc; list_arfcn(si5->bcch_frequency_list, 0xce, @@ -665,7 +666,7 @@ static int generate_si5bis(uint8_t *output, struct gsm_bts *bts) si5b->rr_protocol_discriminator = GSM48_PDISC_RR; si5b->skip_indicator = 0; si5b->system_information = GSM48_MT_RR_SYSINFO_5bis; - rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, 1, 1, 0); + rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, true, true, false); if (rc < 0) return rc; n = list_arfcn(si5b->bcch_frequency_list, 0xce, @@ -709,7 +710,7 @@ static int generate_si5ter(uint8_t *output, struct gsm_bts *bts) si5t->rr_protocol_discriminator = GSM48_PDISC_RR; si5t->skip_indicator = 0; si5t->system_information = GSM48_MT_RR_SYSINFO_5ter; - rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, 1, 0, 1); + rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, true, false, true); if (rc < 0) return rc; n = list_arfcn(si5t->bcch_frequency_list, 0x8e, -- cgit v1.2.3 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 From 36212f28501e36fed43edb579a9abd6b7adc0f27 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 12:06:05 +0200 Subject: Fix documentation for command parameters --- openbsc/src/libbsc/bsc_vty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 9634508e1..3a699c4ab 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2797,7 +2797,8 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" - "EARFCN of neighbor\n") + "EARFCN of neighbor\n" + "EARFCN\n") { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; -- cgit v1.2.3 From 0c1bc26b644c2ea7832afd615e9269095921c159 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 12:06:06 +0200 Subject: Fix earfcn deletion * fix typo in arg index * fix sign in error reporting * add vty test --- openbsc/src/libbsc/bsc_vty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 3a699c4ab..85b8394b1 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2802,11 +2802,11 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; - uint16_t arfcn = atoi(argv[1]); + uint16_t arfcn = atoi(argv[0]); 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); + strerror(-r), VTY_NEWLINE); return CMD_WARNING; } -- cgit v1.2.3 From 26679e0475593aca645c7029e1aad899da73217a Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 15:57:13 +0200 Subject: Add basic UARFCN support * add data structures, generation functions * vty interface for neightbor UARFCNs specific to SI2quater * vty test * unit test Fixes: OS#1666 --- openbsc/src/libbsc/bsc_vty.c | 53 ++++++++++++ openbsc/src/libbsc/rest_octets.c | 91 ++++++++++++++++----- openbsc/src/libbsc/system_information.c | 139 +++++++++++++++++++++++++++++++- 3 files changed, 262 insertions(+), 21 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 85b8394b1..cc4686577 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -707,6 +707,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + for (i = 0; i < bts->si_common.uarfcn_length; i++) { + vty_out(vty, " si2quater neighbor-list add uarfcn %u %u %u%s", + bts->si_common.data.uarfcn_list[i], + bts->si_common.data.scramble_list[i] & ~(1 << 9), + (bts->si_common.data.scramble_list[i] >> 9) & 1, + VTY_NEWLINE); + } + vty_out(vty, " codec-support fr"); if (bts->codec.hr) vty_out(vty, " hr"); @@ -2813,6 +2821,49 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, + "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" + "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" + "diversity bit\n") +{ + struct gsm_bts *bts = vty->index; + uint16_t arfcn = atoi(argv[0]), scramble = atoi(argv[1]); + + switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) { + case -ENOMEM: + vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " + "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + case -EADDRINUSE: + vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", + arfcn, scramble, VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, + "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" + "Delete from SI2quater manual neighbor list\n" + "UARFCN of neighbor\n" + "UARFCN\n" + "scrambling code\n") +{ + struct gsm_bts *bts = vty->index; + + if (bts_uarfcn_del(bts, atoi(argv[0]), atoi(argv[1])) < 0) { + vty_out(vty, "Unable to delete uarfcn: pair not found%s", + 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" @@ -3945,6 +3996,8 @@ int bsc_vty_init(const struct log_info *cat) 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_si2quater_uarfcn_add_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_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 113af5ca9..b59430bcc 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -31,8 +31,7 @@ #include #include #include - -#define SI2Q_MAX_LEN 160 +#include /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) @@ -108,14 +107,6 @@ static inline void append_eutran_neib_cell(struct bitvec *bv, 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) { @@ -188,11 +179,62 @@ static inline void append_earfcn(struct bitvec *bv, bitvec_set_bit(bv, L); } +static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u, + const uint16_t *sc, size_t length) +{ + int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length]; + uint8_t chan_list[16] = {0}; + + /* 3G Neighbour Cell Description */ + bitvec_set_bit(bv, 1); + /* No Index_Start_3G */ + bitvec_set_bit(bv, 0); + /* No Absolute_Index_Start_EMR */ + bitvec_set_bit(bv, 0); + + /* UTRAN FDD Description */ + bitvec_set_bit(bv, 1); + /* No Bandwidth_FDD */ + bitvec_set_bit(bv, 0); + + memset(w, 0, sizeof(w)); + for (i = 0; i < length; i++) + a[i] = sc[i]; + + /* Note: we do not support repeating Neighbour Cells ATM */ + /* Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 1); + + /* FDD-ARFCN */ + bitvec_set_bit(bv, 0); + /* Note: we do not support multiple UARFCN values ATM: */ + bitvec_set_uint(bv, u[0], 14); + + arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc); + range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0); + range_enc_range1024(chan_list, 0, f0_inc, w); + + /* FDD_Indic0: parameter value '0000000000' is not a member of the set */ + bitvec_set_bit(bv, f0_inc); + /* NR_OF_FDD_CELLS */ + bitvec_set_uint(bv, length, 5); + + i = bv->cur_bit; + bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list); + bv->cur_bit = i + range1024_p(length); + + /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 0); + + /* UTRAN TDD Description */ + bitvec_set_bit(bv, 0); +} + /* 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) + const uint16_t *u, const uint16_t *sc, size_t u_len) { - int rc; + unsigned sz; struct bitvec bv; bv.data = data; bv.data_len = 20; @@ -226,8 +268,17 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* No extension (length) */ bitvec_set_bit(&bv, 0); - if (uarfcn) { - + if (u_len) { + sz = uarfcn_size(u, sc, u_len); + /* Even if we do not append EARFCN we still need to set 3 bits */ + if (sz + bv.cur_bit + 3 > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add UARFCNs bits, current %u + required %u + " + "reminder %u > max %u\n", bv.cur_bit, sz, 3, + SI2Q_MAX_LEN); + return -ENOMEM; + } + append_uarfcn(&bv, u, sc, u_len); } else { /* No 3G Neighbour Cell Description */ bitvec_set_bit(&bv, 0); } @@ -237,12 +288,14 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* 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) + if (e) { + sz = earfcn_size(e); + if (sz + bv.cur_bit > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add EARFCNs bits, current %u + required %u > max " + "%u\n", bv.cur_bit, sz, SI2Q_MAX_LEN); return -ENOMEM; + } append_earfcn(&bv, e); } else { /* No Additions in Rel-5: */ diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 43a492af1..8952534c1 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -68,6 +68,139 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ +unsigned range1024_p(unsigned n) +{ + switch (n) { + case 0: return 0; + case 1: return 10; + case 2: return 19; + case 3: return 28; + case 4: return 36; + case 5: return 44; + case 6: return 52; + case 7: return 60; + case 8: return 67; + case 9: return 74; + case 10: return 81; + case 11: return 88; + case 12: return 95; + case 13: return 102; + case 14: return 109; + case 15: return 116; + case 16: return 122; + default: return 0; + } +} + +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1b, 3GPP TS 44.018 */ +unsigned range512_q(unsigned m) +{ + switch (m) { + case 0: return 0; + case 1: return 9; + case 2: return 17; + case 3: return 25; + case 4: return 32; + case 5: return 39; + case 6: return 46; + case 7: return 53; + case 8: return 59; + case 9: return 65; + case 10: return 71; + case 11: return 77; + case 12: return 83; + case 13: return 89; + case 14: return 95; + case 15: return 101; + case 16: return 106; + case 17: return 111; + case 18: return 116; + case 19: return 121; + case 20: return 126; + default: return 0; + } +} + +unsigned earfcn_size(const struct osmo_earfcn_si2q *e) +{ + /* account for all the constant bits in append_earfcn() */ + return 25 + osmo_earfcn_bit_size(e); +} + +unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len) +{ + /*account for all the constant bits in append_uarfcn() */ + return 29 + range1024_p(u_len); +} + +/* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ +uint16_t encode_fdd(uint16_t scramble, bool diversity) +{ + if (diversity) + return scramble | (1 << 9); + return scramble; +} + +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble) +{ + uint16_t sc0 = encode_fdd(scramble, false), sc1 = encode_fdd(scramble, true), + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list; + size_t len = bts->si_common.uarfcn_length, i; + for (i = 0; i < len; i++) { + if (arfcn == ual[i] && (sc0 == scl[i] || sc1 == scl[i])) { + /* we rely on the assumption that (uarfcn, scramble) + tuple is unique in the lists */ + if (i != len - 1) { /* move the tail if necessary */ + memmove(ual + i, ual + i + 1, 2 * (len - i + 1)); + memmove(scl + i, scl + i + 1, 2 * (len - i + 1)); + } + break; + } + } + + if (i == len) + return -EINVAL; + + bts->si_common.uarfcn_length--; + return 0; +} + +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity) +{ + size_t len = bts->si_common.uarfcn_length, i, k; + uint16_t scr, chk, + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list, + scramble1 = encode_fdd(scramble, true), + scramble0 = encode_fdd(scramble, false); + + scr = diversity ? scramble1 : scramble0; + chk = diversity ? scramble0 : scramble1; + + if (len == MAX_EARFCN_LIST) + return -ENOMEM; + + for (i = 0, k = 0; i < len; i++) { + if (arfcn == ual[i] && (scr == scl[i] || chk == scl[i])) + return -EADDRINUSE; + if (scr > scl[i]) + k = i + 1; + } + /* we keep lists sorted by scramble code: + insert into appropriate position and move the tail */ + if (len - k) { + memmove(ual + k + 1, ual + k, (len - k) * 2); + memmove(scl + k + 1, scl + k, (len - k) * 2); + } + ual[k] = arfcn; + scl[k] = scr; + bts->si_common.uarfcn_length++; + return 0; +} + static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, const bool pgsm, const int arfcn) { @@ -508,8 +641,10 @@ static int generate_si2quater(uint8_t *output, struct gsm_bts *bts) si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; rc = rest_octets_si2quater(si2q->rest_octets, - &bts->si_common.si2quater_neigh_list, false, - true); + &bts->si_common.si2quater_neigh_list, + bts->si_common.data.uarfcn_list, + bts->si_common.data.scramble_list, + bts->si_common.uarfcn_length); if (rc < 0) return rc; -- cgit v1.2.3 From aafff96c4060e9bf6ceb9dee9652a91d293a6e1e Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 15:57:14 +0200 Subject: Add vty check for max si2quater size Explicitly check if added (U|E)ARFCN will fit into available si2quater message. --- openbsc/src/libbsc/bsc_vty.c | 23 +++++++++++++++-------- openbsc/src/libbsc/system_information.c | 21 ++++++++++++++++++++- 2 files changed, 35 insertions(+), 9 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index cc4686577..e81308b30 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2789,15 +2789,19 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, VTY_NEWLINE); return CMD_WARNING; } + if (si2q_size_check(bts)) { + 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); - 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; + e->thresh_hi = thresh; + return CMD_SUCCESS; + } + vty_out(vty, "Warning: not enough space in si2quater for a given arfcn%s" + , VTY_NEWLINE); + osmo_earfcn_del(e, arfcn); + return CMD_WARNING; } DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, @@ -2835,6 +2839,9 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, case -ENOMEM: vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + case -ENOSPC: + vty_out(vty, "Warning: not enough space in si2quater for a " + "given arfcn%s", VTY_NEWLINE); case -EADDRINUSE: vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", arfcn, scramble, VTY_NEWLINE); diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 8952534c1..3b0f889a1 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -134,6 +134,20 @@ unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len) return 29 + range1024_p(u_len); } +bool si2q_size_check(const struct gsm_bts *bts) +{ + const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + const uint16_t *u = bts->si_common.data.uarfcn_list, + *sc = bts->si_common.data.scramble_list; + size_t len = bts->si_common.uarfcn_length; + unsigned e_sz = e ? earfcn_size(e) : 1, + u_sz = len ? uarfcn_size(u, sc, len) : 1; + /* 2 bits are used in between UARFCN and EARFCN structs */ + if (SI2Q_MIN_LEN + u_sz + 2 + e_sz > SI2Q_MAX_LEN) + return false; + return true; +} + /* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ uint16_t encode_fdd(uint16_t scramble, bool diversity) { @@ -198,7 +212,12 @@ int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, ual[k] = arfcn; scl[k] = scr; bts->si_common.uarfcn_length++; - return 0; + + if (si2q_size_check(bts)) + return 0; + + bts_uarfcn_del(bts, arfcn, scramble); + return -ENOSPC; } static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, -- cgit v1.2.3 From 8db12e42638483adb2feaf42cfd163dfe1fa973c Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 18 Apr 2016 23:11:18 +0200 Subject: Add extra debug output with channel mode and type This provides helpful information for debugging internal MNCC handler. --- openbsc/src/libbsc/bsc_api.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index e6d820d7e..b8b596782 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -393,11 +393,13 @@ int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, in if (handle_new_assignment(conn, chan_mode, full_rate) != 0) goto error; } else { - LOGP(DMSC, LOGL_NOTICE, - "Sending ChanModify for speech %d %d\n", chan_mode, full_rate); if (chan_mode == GSM48_CMODE_SPEECH_AMR) handle_mr_config(conn, conn->lchan, full_rate); + LOGP(DMSC, LOGL_NOTICE, + "Sending ChanModify for speech: %s on channel %s\n", + get_value_string(gsm48_chan_mode_names, chan_mode), + get_value_string(gsm_chan_t_names, conn->lchan->type)); gsm48_lchan_modify(conn->lchan, chan_mode); } -- cgit v1.2.3 From e01f5050efbc3828defa2df9b789624854297663 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 23 Apr 2016 18:00:18 +0200 Subject: Add missing include --- openbsc/src/libbsc/rest_octets.c | 1 + 1 file changed, 1 insertion(+) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index b59430bcc..aa286e578 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 299a9994656e97defea85689467e61ba34e8577e Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 28 Apr 2016 17:51:15 +0200 Subject: Fix comment typo --- openbsc/src/libbsc/system_information.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 3b0f889a1..0d96621b2 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -68,7 +68,7 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } -/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ +/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ unsigned range1024_p(unsigned n) { switch (n) { -- cgit v1.2.3 From 35697b9a109f08791c00dbb1a8dfaaaff29a8a80 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 29 Apr 2016 12:51:31 +0200 Subject: Adjust si2quater ranges Change ranges of arguments for si2quater neighbor lists to proper values according to 3GPP spec. --- openbsc/src/libbsc/bsc_vty.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'openbsc/src/libbsc') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index e81308b30..b928738c6 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2766,9 +2766,10 @@ 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 add earfcn <0-65535> threshold <0-31> " + "[<0-7>]", "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") @@ -2805,7 +2806,7 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, } DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, - "si2quater neighbor-list del earfcn <1900-2200>", + "si2quater neighbor-list del earfcn <0-65535>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" @@ -2826,7 +2827,7 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, - "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "si2quater neighbor-list add uarfcn <0-16383> <0-511> <0-1>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" @@ -2852,7 +2853,7 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, - "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "si2quater neighbor-list del uarfcn <0-16383> <0-511>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" -- cgit v1.2.3