From bca82edab74678a1af08a50201d916bdcd9b7140 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 23 Oct 2018 16:05:13 +0200 Subject: codec_pref: also check amr codec rates in check_codec_pref() The function check_codec_pref() currently only does a basic check over the general codec configuration of bts and msc. However, it does not yet check if the amr codec rate settings for the BTSs contradict the allowed/forbidden amr codec rates of the MSC. When the two settings do contradict AMR would not work, even when everything else is correctly configured. We need to check this on startup to spot configuration problems quickly. - Add function to calculate intersections of struct gsm48_multi_rate_conf variables. - Calculate the intersection between the multi rate config of each BTS with the one of the MSC Change-Id: I3537d1c89e2520d35cc0e150ba8e6d3693e06710 Related: OS#3529 --- include/osmocom/bsc/codec_pref.h | 4 ++++ src/osmo-bsc/codec_pref.c | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/osmocom/bsc/codec_pref.h b/include/osmocom/bsc/codec_pref.h index d62d29ff8..51340c118 100644 --- a/include/osmocom/bsc/codec_pref.h +++ b/include/osmocom/bsc/codec_pref.h @@ -22,4 +22,8 @@ void gen_bss_supported_codec_list(struct gsm0808_speech_codec_list *scl, const struct bsc_msc_data *msc, const struct gsm_bts *bts); +int calc_amr_rate_intersection(struct gsm48_multi_rate_conf *c, + const struct gsm48_multi_rate_conf *b, + const struct gsm48_multi_rate_conf *a); + int check_codec_pref(struct llist_head *mscs); diff --git a/src/osmo-bsc/codec_pref.c b/src/osmo-bsc/codec_pref.c index 9f30c7b7f..c99c38335 100644 --- a/src/osmo-bsc/codec_pref.c +++ b/src/osmo-bsc/codec_pref.c @@ -393,6 +393,35 @@ void gen_bss_supported_codec_list(struct gsm0808_speech_codec_list *scl, } } +/*! Calculate the intersection of the rate configuration of two multirate configuration + * IE structures. The result c will be a copy of a, but the rate configuration bits + * will be the intersection of the rate configuration bits in a and b. + * \param[out] c user provided memory to store the result. + * \param[in] a multi rate configuration a. + * \param[in] b multi rate configuration b. + * \returns 0 on success, -1 when the result contains an empty set of modes. */ +int calc_amr_rate_intersection(struct gsm48_multi_rate_conf *c, + const struct gsm48_multi_rate_conf *b, + const struct gsm48_multi_rate_conf *a) +{ + struct gsm48_multi_rate_conf res; + uint8_t *_a = (uint8_t *) a; + uint8_t *_b = (uint8_t *) b; + uint8_t *_res = (uint8_t *) & res; + + memcpy(&res, a, sizeof(res)); + + _res[1] = _a[1] & _b[1]; + + if (_res[1] == 0x00) + return -1; + + if (c) + memcpy(c, &res, sizeof(*c)); + + return 0; +} + /*! Visit the codec settings for the MSC and for each BTS in order to make sure * that the configuration does not contain any combinations that lead into a * mutually exclusive codec configuration (empty intersection). @@ -404,6 +433,8 @@ int check_codec_pref(struct llist_head *mscs) struct gsm_bts *bts; struct gsm0808_speech_codec_list scl; int rc = 0; + int rc_rate; + const struct gsm48_multi_rate_conf *bts_gsm48_ie; llist_for_each_entry(msc, mscs, entry) { llist_for_each_entry(bts, &msc->network->bts_list, list) { @@ -414,6 +445,24 @@ int check_codec_pref(struct llist_head *mscs) bts->nr, msc->nr); rc = -1; } + + bts_gsm48_ie = (struct gsm48_multi_rate_conf *)&bts->mr_full.gsm48_ie; + rc_rate = calc_amr_rate_intersection(NULL, &msc->amr_conf, bts_gsm48_ie); + if (rc_rate < 0) { + LOGP(DMSC, LOGL_FATAL, + "network amr tch-f mode config of BTS %u does not intersect with amr-config of MSC %u\n", + bts->nr, msc->nr); + rc = -1; + } + + bts_gsm48_ie = (struct gsm48_multi_rate_conf *)&bts->mr_half.gsm48_ie; + rc_rate = calc_amr_rate_intersection(NULL, &msc->amr_conf, bts_gsm48_ie); + if (rc_rate < 0) { + LOGP(DMSC, LOGL_FATAL, + "network amr tch-h mode config of BTS %u does not intersect with amr-config of MSC %u\n", + bts->nr, msc->nr); + rc = -1; + } } } -- cgit v1.2.3