<p>dexter <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/11443">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gsm_04_08: improve gsm48_multirate_config()<br><br>The function gsm48_multirate_config() generates the multirate<br>configuration IE, that is sent via RSL to configure the active set of<br>AMR codecs inside the BTS. The function already works, but it does not<br>check the input data for consistancy. Lets add some consistancy check to<br>make sure that inconsistant parameters are rejected. Also allow the<br>output pointer to be NULL, so that the function can be used to perform<br>a dry run to be able to verify parameters.<br><br>- Check for invalid / inconsistant configuration parameters<br>- Perform a dry-run when lv pointer is set to NULL<br><br>Change-Id: I06beb7dd7236c81c3a91af4d09c31891f4b910a4<br>Related: OS#3529<br>---<br>M include/osmocom/bsc/gsm_04_08_rr.h<br>M src/osmo-bsc/bsc_vty.c<br>M src/osmo-bsc/gsm_04_08_rr.c<br>M tests/gsm0408/Makefile.am<br>M tests/gsm0408/gsm0408_test.c<br>M tests/gsm0408/gsm0408_test.ok<br>6 files changed, 237 insertions(+), 26 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/gsm_04_08_rr.h b/include/osmocom/bsc/gsm_04_08_rr.h</span><br><span>index e2e861d..8e4f787 100644</span><br><span>--- a/include/osmocom/bsc/gsm_04_08_rr.h</span><br><span>+++ b/include/osmocom/bsc/gsm_04_08_rr.h</span><br><span>@@ -23,7 +23,8 @@</span><br><span>                              struct msgb *msg, struct bsc_subscr *bsub);</span><br><span> int gsm48_send_rr_classmark_enquiry(struct gsm_lchan *lchan);</span><br><span> int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_multirate_config(uint8_t *lv, const struct amr_multirate_conf *mr, const struct amr_mode *modes);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_multirate_config(uint8_t *lv, const struct gsm48_multi_rate_conf *mr_conf,</span><br><span style="color: hsl(120, 100%, 40%);">+                     const struct amr_mode *modes, unsigned int num_modes);</span><br><span> struct msgb *gsm48_make_ho_cmd(struct gsm_lchan *new_lchan, uint8_t power_command, uint8_t ho_ref);</span><br><span> int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,</span><br><span>                uint8_t power_command, uint8_t ho_ref);</span><br><span>diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c</span><br><span>index f156cc8..08b5dad 100644</span><br><span>--- a/src/osmo-bsc/bsc_vty.c</span><br><span>+++ b/src/osmo-bsc/bsc_vty.c</span><br><span>@@ -4391,11 +4391,12 @@</span><br><span> </span><br><span>     mr.ms_mode[0].mode = amr_mode;</span><br><span>       mr.bts_mode[0].mode = amr_mode;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.num_modes = 1;</span><br><span> </span><br><span>        /* encode this configuration into the lchan for both uplink and</span><br><span>       * downlink direction */</span><br><span style="color: hsl(0, 100%, 40%);">-        gsm48_multirate_config(lchan->mr_ms_lv, &mr, mr.ms_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-        gsm48_multirate_config(lchan->mr_bts_lv, &mr, mr.bts_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+    gsm48_multirate_config(lchan->mr_ms_lv, mr_conf, mr.ms_mode, mr.num_modes);</span><br><span style="color: hsl(120, 100%, 40%);">+        gsm48_multirate_config(lchan->mr_bts_lv, mr_conf, mr.bts_mode, mr.num_modes);</span><br><span> </span><br><span>         return 0;</span><br><span> }</span><br><span>diff --git a/src/osmo-bsc/gsm_04_08_rr.c b/src/osmo-bsc/gsm_04_08_rr.c</span><br><span>index 35044a3..4659c1a 100644</span><br><span>--- a/src/osmo-bsc/gsm_04_08_rr.c</span><br><span>+++ b/src/osmo-bsc/gsm_04_08_rr.c</span><br><span>@@ -321,47 +321,113 @@</span><br><span>     cd->arfcn_lo = bts->c0->arfcn & 0xff;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Encode a TS 04.08 multirate config LV according to 10.5.2.21aa</span><br><span style="color: hsl(0, 100%, 40%);">- *  \param[out] lv caller-allocated buffer of 7 bytes. First octet is IS length</span><br><span style="color: hsl(0, 100%, 40%);">- *  \param[in] mr multi-rate configuration to encode</span><br><span style="color: hsl(0, 100%, 40%);">- *  \param[in] modes array describing the AMR modes</span><br><span style="color: hsl(0, 100%, 40%);">- *  \returns 0 on success */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_multirate_config(uint8_t *lv, const struct amr_multirate_conf *mr, const struct amr_mode *modes)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Encode a TS 04.08 multirate config LV according to 10.5.2.21aa.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] lv caller-allocated buffer of 7 bytes. First octet is is length.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] mr_conf multi-rate configuration to encode (selected modes).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] modes array describing the AMR modes.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] num_modes length of the modes array.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 on success, -EINVAL on failure. */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_multirate_config(uint8_t *lv,</span><br><span style="color: hsl(120, 100%, 40%);">+                       const struct gsm48_multi_rate_conf *mr_conf,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const struct amr_mode *modes, unsigned int num_modes)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   int num = 0, i;</span><br><span style="color: hsl(120, 100%, 40%);">+       int num = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int k;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int m = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   bool mode_valid;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t *gsm48_ie = (uint8_t *) mr_conf;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct amr_mode *modes_selected[4];</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check if modes for consistency (order and duplicates) */</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < num_modes; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (i > 0 && modes[i - 1].mode > modes[i].mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGP(DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "BUG: Multirate codec with inconsistant config (mode order).\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                      return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (i > 0 && modes[i - 1].mode == modes[i].mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 LOGP(DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "BUG: Multirate codec with inconsistant config (duplicate modes).\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Check if the active set that is defined in mr_conf has at least one</span><br><span style="color: hsl(120, 100%, 40%);">+         * mode but not more than 4 modes set */</span><br><span>     for (i = 0; i < 8; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (((mr->gsm48_ie[1] >> i) & 1))</span><br><span style="color: hsl(120, 100%, 40%);">+                if (((gsm48_ie[1] >> i) & 1))</span><br><span>                      num++;</span><br><span>       }</span><br><span>    if (num > 4) {</span><br><span style="color: hsl(0, 100%, 40%);">-               LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec with too "</span><br><span style="color: hsl(0, 100%, 40%);">-                          "many modes in config.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-           num = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "BUG: Multirate codec with too many modes in config.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              return -EINVAL;</span><br><span>      }</span><br><span>    if (num < 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-               LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec with no "</span><br><span style="color: hsl(0, 100%, 40%);">-                           "mode in config.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-         num = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+              "BUG: Multirate codec with no mode in config.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Do not accept excess hysteresis or threshold values */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < num_modes; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (modes[i].threshold >= 64) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    LOGP(DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "BUG: Multirate codec with excessive threshold values.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                    return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (modes[i].hysteresis >= 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   LOGP(DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "BUG: Multirate codec with excessive hysteresis values.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                   return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Scan through the selected modes and find a matching threshold/</span><br><span style="color: hsl(120, 100%, 40%);">+      * hysteresis value for that mode. */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < 8; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (((gsm48_ie[1] >> i) & 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     mode_valid = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                   for (k = 0; k < num_modes; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (modes[k].mode == i) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     mode_valid = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                                    modes_selected[m] = &modes[k];</span><br><span style="color: hsl(120, 100%, 40%);">+                                    m++;</span><br><span style="color: hsl(120, 100%, 40%);">+                          }</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (!mode_valid) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            LOGP(DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "BUG: Multirate codec with inconsistant config (no mode defined).\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(m <= 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* When the caller is not interested in any result, skip the actual</span><br><span style="color: hsl(120, 100%, 40%);">+    * composition of the IE (dry run) */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!lv)</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Compose output buffer */</span><br><span>  lv[0] = (num == 1) ? 2 : (num + 2);</span><br><span style="color: hsl(0, 100%, 40%);">-     memcpy(lv + 1, mr->gsm48_ie, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(lv + 1, gsm48_ie, 2);</span><br><span>         if (num == 1)</span><br><span>                return 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   lv[3] = modes[0].threshold & 0x3f;</span><br><span style="color: hsl(0, 100%, 40%);">-  lv[4] = modes[0].hysteresis << 4;</span><br><span style="color: hsl(120, 100%, 40%);">+       lv[3] = modes_selected[0]->threshold & 0x3f;</span><br><span style="color: hsl(120, 100%, 40%);">+   lv[4] = modes_selected[0]->hysteresis << 4;</span><br><span>         if (num == 2)</span><br><span>                return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-       lv[4] |= (modes[1].threshold & 0x3f) >> 2;</span><br><span style="color: hsl(0, 100%, 40%);">-    lv[5] = modes[1].threshold << 6;</span><br><span style="color: hsl(0, 100%, 40%);">-  lv[5] |= (modes[1].hysteresis & 0x0f) << 2;</span><br><span style="color: hsl(120, 100%, 40%);">+ lv[4] |= (modes_selected[1]->threshold & 0x3f) >> 2;</span><br><span style="color: hsl(120, 100%, 40%);">+     lv[5] = modes_selected[1]->threshold << 6;</span><br><span style="color: hsl(120, 100%, 40%);">+   lv[5] |= (modes_selected[1]->hysteresis & 0x0f) << 2;</span><br><span>   if (num == 3)</span><br><span>                return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-       lv[5] |= (modes[2].threshold & 0x3f) >> 4;</span><br><span style="color: hsl(0, 100%, 40%);">-    lv[6] = modes[2].threshold << 4;</span><br><span style="color: hsl(0, 100%, 40%);">-  lv[6] |= modes[2].hysteresis & 0x0f;</span><br><span style="color: hsl(120, 100%, 40%);">+      lv[5] |= (modes_selected[2]->threshold & 0x3f) >> 4;</span><br><span style="color: hsl(120, 100%, 40%);">+     lv[6] = modes_selected[2]->threshold << 4;</span><br><span style="color: hsl(120, 100%, 40%);">+   lv[6] |= modes_selected[2]->hysteresis & 0x0f;</span><br><span> </span><br><span>    return 0;</span><br><span> }</span><br><span>diff --git a/tests/gsm0408/Makefile.am b/tests/gsm0408/Makefile.am</span><br><span>index d790fc8..b207f8b 100644</span><br><span>--- a/tests/gsm0408/Makefile.am</span><br><span>+++ b/tests/gsm0408/Makefile.am</span><br><span>@@ -23,6 +23,7 @@</span><br><span>  $(NULL)</span><br><span> </span><br><span> gsm0408_test_LDADD = \</span><br><span style="color: hsl(120, 100%, 40%);">+ $(top_builddir)/src/osmo-bsc/gsm_04_08_rr.o \</span><br><span>        $(top_builddir)/src/osmo-bsc/arfcn_range_encode.o \</span><br><span>  $(top_builddir)/src/osmo-bsc/gsm_data.o \</span><br><span>    $(top_builddir)/src/osmo-bsc/gsm_timers.o \</span><br><span>diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c</span><br><span>index bc2777d..faeca39 100644</span><br><span>--- a/tests/gsm0408/gsm0408_test.c</span><br><span>+++ b/tests/gsm0408/gsm0408_test.c</span><br><span>@@ -35,6 +35,8 @@</span><br><span> #include <osmocom/gsm/sysinfo.h></span><br><span> #include <osmocom/gsm/gsm48.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/gsm_04_08_rr.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define COMPARE(result, op, value) \</span><br><span>     if (!((result) op (value))) {\</span><br><span>      fprintf(stderr, "Compare failed. Was %x should be %x in %s:%d\n",result, value, __FILE__, __LINE__); \</span><br><span>@@ -799,6 +801,106 @@</span><br><span>     OSMO_ASSERT(pass);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void test_gsm48_multirate_config()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t lv[7];</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm48_multi_rate_conf *gsm48_ie;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct amr_multirate_conf mr;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     memset(&mr, 0, sizeof(mr));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Use some made up threshold and hysteresis values */</span><br><span style="color: hsl(120, 100%, 40%);">+        mr.ms_mode[0].threshold = 11;</span><br><span style="color: hsl(120, 100%, 40%);">+ mr.ms_mode[1].threshold = 12;</span><br><span style="color: hsl(120, 100%, 40%);">+ mr.ms_mode[2].threshold = 13;</span><br><span style="color: hsl(120, 100%, 40%);">+ mr.ms_mode[0].hysteresis = 15;</span><br><span style="color: hsl(120, 100%, 40%);">+        mr.ms_mode[1].hysteresis = 12;</span><br><span style="color: hsl(120, 100%, 40%);">+        mr.ms_mode[2].hysteresis = 8;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_ie = (struct gsm48_multi_rate_conf *)&mr.gsm48_ie;</span><br><span style="color: hsl(120, 100%, 40%);">+  gsm48_ie->ver = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm48_ie->m5_90 = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_ie->m7_40 = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_ie->m7_95 = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_ie->m12_2 = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Test #1: Normal configuration with 4 active set members */</span><br><span style="color: hsl(120, 100%, 40%);">+ mr.ms_mode[0].mode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[1].mode = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[2].mode = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[3].mode = 7;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("gsm48_multirate_config(): rc=%i, lv=%s\n", rc,</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_hexdump_nospc(lv, lv[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Test #2: 4 active set members, but wrong mode order: */</span><br><span style="color: hsl(120, 100%, 40%);">+    mr.ms_mode[3].mode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[2].mode = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[1].mode = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[0].mode = 7;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == -EINVAL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Test #3: Normal configuration with 3 active set members */</span><br><span style="color: hsl(120, 100%, 40%);">+ mr.ms_mode[0].mode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[1].mode = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[2].mode = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[3].mode = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_ie->m12_2 = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[2].threshold = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  mr.ms_mode[2].hysteresis = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("gsm48_multirate_config(): rc=%i, lv=%s\n", rc,</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_hexdump_nospc(lv, lv[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Test #4: 3 active set members, but wrong mode order: */</span><br><span style="color: hsl(120, 100%, 40%);">+    mr.ms_mode[0].mode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[2].mode = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[1].mode = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == -EINVAL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Test #5: Normal configuration with 2 active set members */</span><br><span style="color: hsl(120, 100%, 40%);">+ mr.ms_mode[0].mode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[1].mode = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[2].mode = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_ie->m7_95 = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[1].threshold = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  mr.ms_mode[1].hysteresis = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("gsm48_multirate_config(): rc=%i, lv=%s\n", rc,</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_hexdump_nospc(lv, lv[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Test #6: 2 active set members, but wrong mode order: */</span><br><span style="color: hsl(120, 100%, 40%);">+    mr.ms_mode[1].mode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[0].mode = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == -EINVAL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Test #7: Normal configuration with 1 active set member */</span><br><span style="color: hsl(120, 100%, 40%);">+  mr.ms_mode[0].mode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[1].mode = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       gsm48_ie->m7_40 = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr.ms_mode[0].threshold = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  mr.ms_mode[0].hysteresis = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("gsm48_multirate_config(): rc=%i, lv=%s\n", rc,</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_hexdump_nospc(lv, lv[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Test #8: 0 active set members: */</span><br><span style="color: hsl(120, 100%, 40%);">+  mr.ms_mode[0].mode = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = gsm48_multirate_config(lv, gsm48_ie, mr.ms_mode, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(rc == -EINVAL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct log_info_cat log_categories[] = {</span><br><span> };</span><br><span> </span><br><span>@@ -839,6 +941,8 @@</span><br><span> </span><br><span>        test_gsm48_ra_id_by_bts();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        test_gsm48_multirate_config();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     printf("Done.\n");</span><br><span> </span><br><span>     return EXIT_SUCCESS;</span><br><span>@@ -854,3 +958,37 @@</span><br><span> }</span><br><span> </span><br><span> void ts_fsm_alloc(struct gsm_bts_trx_ts *ts) {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void bsc_cm_update(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+            const uint8_t *cm2, uint8_t cm2_len,</span><br><span style="color: hsl(120, 100%, 40%);">+                  const uint8_t *cm3, uint8_t cm3_len) {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)</span><br><span style="color: hsl(120, 100%, 40%);">+{ return 0; }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rsl_chan_mode_modify_req(struct gsm_lchan *ts) { return 0; }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rsl_tx_ipacc_crcx(struct gsm_lchan *lchan) { return 0; }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void gscon_submit_rsl_dtap(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+                           struct msgb *msg, int link_id, int allow_sacch) {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool lchan_may_receive_data(struct gsm_lchan *lchan) { return  true; }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg,</span><br><span style="color: hsl(120, 100%, 40%);">+          uint16_t chosen_channel) { return 0; }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id,</span><br><span style="color: hsl(120, 100%, 40%);">+           struct msgb *msg) {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+                         struct msgb *msg, uint8_t chosen_encr) {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const char *bsc_subscr_name(struct bsc_subscr *bsub) { return NULL; }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void lchan_release(struct gsm_lchan *lchan, bool sacch_deact,</span><br><span style="color: hsl(120, 100%, 40%);">+                   bool err, enum gsm48_rr_cause cause_rr) {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rsl_data_request(struct msgb *msg, uint8_t link_id) { return 0; }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rsl_encryption_cmd(struct msgb *msg) { return 0; }</span><br><span>diff --git a/tests/gsm0408/gsm0408_test.ok b/tests/gsm0408/gsm0408_test.ok</span><br><span>index 7270721..9424167 100644</span><br><span>--- a/tests/gsm0408/gsm0408_test.ok</span><br><span>+++ b/tests/gsm0408/gsm0408_test.ok</span><br><span>@@ -226,4 +226,8 @@</span><br><span> test_gsm48_ra_id_by_bts[4]: digits='999999' lac=0xffff=htons(65535) rac=0xff=255 pass</span><br><span> test_gsm48_ra_id_by_bts[5]: digits='09f909' lac=0xcdab=htons(43981) rac=0xab=171 pass</span><br><span> test_gsm48_ra_id_by_bts[6]: digits='090990' lac=0xcdab=htons(43981) rac=0xab=171 pass</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_multirate_config(): rc=0, lv=0620b40bf330</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_multirate_config(): rc=0, lv=0520340bf3</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_multirate_config(): rc=0, lv=0420140b</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_multirate_config(): rc=0, lv=0220</span><br><span> Done.</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11443">change 11443</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/11443"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I06beb7dd7236c81c3a91af4d09c31891f4b910a4 </div>
<div style="display:none"> Gerrit-Change-Number: 11443 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>