dexter has uploaded this change for review. ( https://gerrit.osmocom.org/11060


Change subject: codec_pref: handle S0-S15 in ASSIGNMENT REQUEST
......................................................................

codec_pref: handle S0-S15 in ASSIGNMENT REQUEST

Opposed to all other codecs that are common in GSM, AMR requires a codec
configuration that is expressed by a bitmask (S0 to S15) in the speech
codec list in the ASSIGNMENT REQUEST. Also the BSC acknowledges those
configuration in the ASSIGNMENT COMPLETE message.

At the moment osmo-bsc ignores all incoming configuration bits. The bits
in the ASSIGNMENT COMPLETE speech codec (choosen) field are hardcoded.

- Store the configuration bits while parsing the ASSIGNMENT COMPLETE
- Create an intersection with the configuration that is actually
  supported by the BSS
- Return the resulting (choosen) configuration bits with the assignment
  complete message.

Change-Id: I2d8ded51b3eb4c003fe2da6f2d6f48d001b73737
Related: OS#3529
---
M include/osmocom/bsc/codec_pref.h
M include/osmocom/bsc/gsm_data.h
M src/osmo-bsc/assignment_fsm.c
M src/osmo-bsc/codec_pref.c
M src/osmo-bsc/handover_fsm.c
M src/osmo-bsc/osmo_bsc_bssap.c
M tests/codec_pref/codec_pref_test.c
7 files changed, 89 insertions(+), 50 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/60/11060/1

diff --git a/include/osmocom/bsc/codec_pref.h b/include/osmocom/bsc/codec_pref.h
index 09aaa60..3085ad4 100644
--- a/include/osmocom/bsc/codec_pref.h
+++ b/include/osmocom/bsc/codec_pref.h
@@ -12,11 +12,11 @@

 int match_codec_pref(enum gsm48_chan_mode *chan_mode,
                     bool *full_rate,
+                    uint16_t *s15_s0,
                     const struct gsm0808_channel_type *ct,
                     const struct gsm0808_speech_codec_list *scl,
-                    struct gsm_audio_support * const *audio_support,
-                    int audio_length,
-                    const struct bts_codec_conf *bts_codec);
+                    const struct bsc_msc_data *msc,
+                    const struct gsm_bts *bts);

 void gen_bss_supported_codec_list(struct gsm0808_speech_codec_list *scl,
                                  const struct bsc_msc_data *msc,
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 33a5a8d..7c91e59 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -109,6 +109,7 @@

        enum gsm48_chan_mode chan_mode;
        bool full_rate;
+       uint16_t s15_s0;
 };

 struct assignment_fsm_data {
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c
index 5304d6c..221657e 100644
--- a/src/osmo-bsc/assignment_fsm.c
+++ b/src/osmo-bsc/assignment_fsm.c
@@ -169,8 +169,8 @@
                 * assignment complete message. */
                if (gscon_is_aoip(conn)) {
                        /* Extrapolate speech codec from speech mode */
-                       /* FIXME: AMR codec configuration must be derived from 
lchan1! */
                        gsm0808_speech_codec_from_chan_type(&sc, perm_spch);
+                       sc.cfg = conn->assignment.req.s15_s0;
                        sc_ptr = ≻
                }
        }
diff --git a/src/osmo-bsc/codec_pref.c b/src/osmo-bsc/codec_pref.c
index c998e60..7aa5130 100644
--- a/src/osmo-bsc/codec_pref.c
+++ b/src/osmo-bsc/codec_pref.c
@@ -94,14 +94,18 @@
  * matches one of the permitted speech settings of the channel type element.
  * The matched permitted speech value is then also compared against the
  * speech codec list. (optional, only relevant for AoIP) */
-static bool test_codec_pref(const struct gsm0808_channel_type *ct,
-                           const struct gsm0808_speech_codec_list *scl, 
uint8_t perm_spch)
+static bool test_codec_pref(const struct gsm0808_speech_codec **sc_match,
+                           const struct gsm0808_speech_codec_list *scl,
+                           const struct gsm0808_channel_type *ct,
+                           uint8_t perm_spch)
 {
        unsigned int i;
        bool match = false;
        struct gsm0808_speech_codec sc;
        int rc;

+       *sc_match = NULL;
+
        /* Try to find the given permitted speech value in the
         * codec list of the channel type element */
        for (i = 0; i < ct->perm_spch_len; i++) {
@@ -129,8 +133,10 @@
        /* Try to find extrapolated speech codec data in
         * the speech codec list */
        for (i = 0; i < scl->len; i++) {
-               if (sc.type == scl->codec[i].type)
+               if (sc.type == scl->codec[i].type) {
+                       *sc_match = &scl->codec[i];
                        return true;
+               }
        }

        return false;
@@ -168,40 +174,74 @@
        return false;
 }

+/* Helper function to generate the bss supported amr configuration bits 
(S0-S15) */
+static uint16_t gen_bss_supported_amr_s15_s0(const struct bsc_msc_data *msc, 
const struct gsm_bts *bts, bool hr)
+{
+       const struct gsm48_multi_rate_conf *amr_cfg_bts;
+       const struct gsm48_multi_rate_conf *amr_cfg_msc;
+       uint16_t amr_s15_s0_bts;
+       uint16_t amr_s15_s0_msc;
+
+       /* Lookup the BTS specific AMR rate configuration. Thsi config is set
+        * via the VTY for each BTS individually. In cases where no 
configuration
+        * is set we will assume a safe default */
+       if (hr) {
+               amr_cfg_bts = (struct gsm48_multi_rate_conf 
*)&bts->mr_half.gsm48_ie;
+               amr_s15_s0_bts = gsm0808_sc_cfg_from_gsm48_mr_cfg(amr_cfg_bts, 
false);
+       } else {
+               amr_cfg_bts = (struct gsm48_multi_rate_conf 
*)&bts->mr_full.gsm48_ie;
+               amr_s15_s0_bts = gsm0808_sc_cfg_from_gsm48_mr_cfg(amr_cfg_bts, 
true);
+       }
+
+       /* Lookup the AMR rate configuration that is set for the MSC */
+       amr_cfg_msc = &msc->amr_conf;
+       amr_s15_s0_msc = gsm0808_sc_cfg_from_gsm48_mr_cfg(amr_cfg_msc, true);
+
+       /* Calculate the intersection of the two configurations and update 
S0-S15
+        * in the codec list. */
+       return amr_s15_s0_bts & amr_s15_s0_msc;
+}
+
 /*! Match the codec preferences from local config with a received codec 
preferences IEs received from the
  * MSC and the BTS' codec configuration.
  *  \param[out] chan_mode GSM 04.08 channel mode.
  *  \param[out] full_rate true if full-rate.
+ *  \param[out] s15_s0 codec configuration bits S15-S0 (AMR)
  *  \param[in] ct GSM 08.08 channel type received from MSC.
  *  \param[in] scl GSM 08.08 speech codec list received from MSC (optional).
- *  \param[in] audio_support List of allowed codecs as from local config.
- *  \param[in] audio_length Number of items in audio_support.
- *  \param[in] bts_codec BTS codec configuration.
+ *  \param[in] msc associated msc (current codec settings).
+ *  \param[in] bts associated bts (current codec settings).
  *  \returns 0 on success, -1 in case no match was found */
 int match_codec_pref(enum gsm48_chan_mode *chan_mode,
                     bool *full_rate,
+                    uint16_t *s15_s0,
                     const struct gsm0808_channel_type *ct,
                     const struct gsm0808_speech_codec_list *scl,
-                    struct gsm_audio_support * const *audio_support,
-                    int audio_length,
-                    const struct bts_codec_conf *bts_codec)
+                    const struct bsc_msc_data *msc,
+                    const struct gsm_bts *bts)
 {
        unsigned int i;
        uint8_t perm_spch;
        bool match = false;
+       const struct gsm0808_speech_codec *sc_match = NULL;
+       uint16_t amr_s15_s0_supported;

-       for (i = 0; i < audio_length; i++) {
+       /* Note: Normally the MSC should never try to advertise a codec that
+        * we did not advertise as supported before. In order to ensure that
+        * no unsupported codec is accepted, we make sure that the codec is
+        * indeed available with the current BTS and MSC configuration */
+       for (i = 0; i < msc->audio_length; i++) {
                /* Pick a permitted speech value from the global codec 
configuration list */
-               perm_spch = audio_support_to_gsm88(audio_support[i]);
+               perm_spch = audio_support_to_gsm88(msc->audio_support[i]);
 
                /* Check this permitted speech value against the BTS specific 
parameters.
                 * if the BTS does not support the codec, try the next one */
-               if (!test_codec_support_bts(bts_codec, perm_spch))
+               if (!test_codec_support_bts(&bts->codec, perm_spch))
                        continue;

                /* Match the permitted speech value against the codec lists 
that were
                 * advertised by the MS and the MSC */
-               if (test_codec_pref(ct, scl, perm_spch)) {
+               if (test_codec_pref(&sc_match, scl, ct, perm_spch)) {
                        match = true;
                        break;
                }
@@ -211,6 +251,7 @@
        if (!match) {
                *full_rate = false;
                *chan_mode = GSM48_CMODE_SIGN;
+               *s15_s0 = 0;
                return -1;
        }

@@ -240,6 +281,24 @@
        /* Lookup a channel mode for the selected codec */
        *chan_mode = gsm88_to_chan_mode(perm_spch);

+       /* Special handling for AMR */
+       if (perm_spch == GSM0808_PERM_HR3 || perm_spch == GSM0808_PERM_FR3)
+       {
+               /* Normally the MSC should never try to advertise an AMR codec
+                * configuration that we did not previously advertised as
+                * supported. However, to ensure that no unsupported AMR codec
+                * configuration enters the further processing steps we agein
+                * lookup what we support and generate an intersection. All
+                * further processing is then done with this intersection
+                * result */
+               amr_s15_s0_supported = gen_bss_supported_amr_s15_s0(msc, bts, 
(perm_spch == GSM0808_PERM_HR3));
+               if (sc_match)
+                       *s15_s0 = sc_match->cfg & amr_s15_s0_supported;
+               else
+                       *s15_s0 = amr_s15_s0_supported;
+       } else
+               *s15_s0 = 0;
+
        return 0;
 }

@@ -254,11 +313,6 @@
        uint8_t perm_spch;
        unsigned int i;
        int rc;
-       uint16_t amr_s15_s0_bts;
-       uint16_t amr_s15_s0_msc;
-       uint16_t amr_s15_s0;
-       const struct gsm48_multi_rate_conf *amr_cfg_bts;
-       const struct gsm48_multi_rate_conf *amr_cfg_msc;

        memset(scl, 0, sizeof(*scl));

@@ -280,28 +334,8 @@
                /* AMR (HR/FR version 3) is the only codec that requires a codec
                 * configuration (S0-S15). Determine the current configuration 
and update
                 * the cfg flag. */
-               if (msc->audio_support[i]->ver == 3) {
-
-                       /* First lookup the BTS specific AMR rate 
configuration. Thsi config
-                        * is set via the VTY for each BTS individually. In 
cases where no
-                        * configuration is set we will assume a safe default */
-                       if (msc->audio_support[i]->hr) {
-                               amr_cfg_bts = (struct gsm48_multi_rate_conf 
*)&bts->mr_half.gsm48_ie;
-                               amr_s15_s0_bts = 
gsm0808_sc_cfg_from_gsm48_mr_cfg(amr_cfg_bts, false);
-                       } else {
-                               amr_cfg_bts = (struct gsm48_multi_rate_conf 
*)&bts->mr_full.gsm48_ie;
-                               amr_s15_s0_bts = 
gsm0808_sc_cfg_from_gsm48_mr_cfg(amr_cfg_bts, true);
-                       }
-
-                       /* At next, lookup the AMR rate configuration that is 
set for the MSC */
-                       amr_cfg_msc = &msc->amr_conf;
-                       amr_s15_s0_msc = 
gsm0808_sc_cfg_from_gsm48_mr_cfg(amr_cfg_msc, true);
-
-                       /* Calculate the intersection of the two configurations 
and update S0-S15
-                        * in the codec list. */
-                       amr_s15_s0 = amr_s15_s0_bts & amr_s15_s0_msc;
-                       scl->codec[scl->len].cfg = amr_s15_s0;
-               }
+               if (msc->audio_support[i]->ver == 3)
+                       scl->codec[scl->len].cfg = 
gen_bss_supported_amr_s15_s0(msc, bts, msc->audio_support[i]->hr);

                scl->len++;
        }
diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c
index 9d558bc..e95ab9c 100644
--- a/src/osmo-bsc/handover_fsm.c
+++ b/src/osmo-bsc/handover_fsm.c
@@ -522,6 +522,7 @@
        int match_idx;
        enum gsm48_chan_mode mode;
        bool full_rate;
+       uint16_t s15_s0;
        struct osmo_fsm_inst *fi;

        handover_fsm_alloc(conn);
@@ -560,8 +561,9 @@
                       bts->nr, req->cell_id_target_name);

                /* Figure out channel type */
-               if (match_codec_pref(&mode, &full_rate, &req->ct, &req->scl, 
msc->audio_support,
-                                    msc->audio_length, &bts->codec)) {
+               if (match_codec_pref(&mode, &full_rate, &s15_s0, &req->ct, 
&req->scl, msc, bts)) {
+                       /* FIXME: use the value in s15_s0 that has been 
computed by
+                        * match_codec_pref(). */
                        LOG_HO(conn, LOGL_DEBUG,
                               "BTS %u has no matching channel codec (%s, 
speech codec list len = %u)",
                               bts->nr, gsm0808_channel_type_name(&req->ct), 
req->scl.len);
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index 97daa5c..537b851 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -603,6 +603,7 @@
        uint16_t cic = 0;
        enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
        bool full_rate = false;
+       uint16_t s15_s0 = 0;
        bool aoip = false;
        struct sockaddr_storage rtp_addr;
        struct gsm0808_channel_type ct;
@@ -706,9 +707,8 @@

                /* Match codec information from the assignment command against 
the
                 * local preferences of the BSC and BTS */
-               rc = match_codec_pref(&chan_mode, &full_rate, &ct, 
&conn->codec_list,
-                                     msc->audio_support, msc->audio_length,
-                                     &conn_get_bts(conn)->codec);
+               rc = match_codec_pref(&chan_mode, &full_rate, &s15_s0, &ct, 
&conn->codec_list,
+                                     msc, conn_get_bts(conn));
                if (rc < 0) {
                        LOGP(DMSC, LOGL_ERROR, "No supported audio type found 
for channel_type ="
                             " { ch_indctr=0x%x, ch_rate_type=0x%x, perm_spch=[ 
%s] }\n",
@@ -730,6 +730,7 @@
                        .msc_assigned_cic = cic,
                        .chan_mode = chan_mode,
                        .full_rate = full_rate,
+                       .s15_s0 = s15_s0
                };
                if (aoip) {
                        unsigned int rc = 
osmo_sockaddr_to_str_and_uint(req.msc_rtp_addr,
diff --git a/tests/codec_pref/codec_pref_test.c 
b/tests/codec_pref/codec_pref_test.c
index 20e3525..34b8c75 100644
--- a/tests/codec_pref/codec_pref_test.c
+++ b/tests/codec_pref/codec_pref_test.c
@@ -374,6 +374,7 @@
        unsigned int i;
        bool full_rate;
        enum gsm48_chan_mode chan_mode;
+       uint16_t s15_s0;

        printf("Determining channel mode and rate:\n");

@@ -398,7 +399,7 @@
        printf("   codec->efr=%u\n", bts->codec.efr);
        printf("   codec->amr=%u\n", bts->codec.amr);

-       rc = match_codec_pref(&chan_mode, &full_rate, ct, scl, 
msc->audio_support, msc->audio_length, &bts->codec);
+       rc = match_codec_pref(&chan_mode, &full_rate, &s15_s0, ct, scl, msc, 
bts);
        printf(" * result: rc=%i, full_rate=%i, chan_mode=%s\n", rc, full_rate, 
gsm48_chan_mode_name(chan_mode));

        printf("\n");

--
To view, visit https://gerrit.osmocom.org/11060
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I2d8ded51b3eb4c003fe2da6f2d6f48d001b73737
Gerrit-Change-Number: 11060
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pma...@sysmocom.de>

Reply via email to