<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-pcu/+/20919">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">alloc_algo_b: Select TRX with least assigned TFIs during TBF alloc<br><br>Before this patch, it would always allocate all TBFs on the first TRX<br>until all TFIs were filled, then second, and so on. But it would<br>actually fail around 8th MS requesting an UL TBF because despite a TFI<br>was successfuly assigned, because all USFs were already exhausted for<br>that PDCH.<br><br>Related: OS#1775<br>Change-Id: Iccfc8acfbfdc258ed16cc5af01f12b376fe73b72<br>---<br>M src/bts.cpp<br>M tests/tbf/TbfTest.cpp<br>2 files changed, 53 insertions(+), 30 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/19/20919/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/bts.cpp b/src/bts.cpp</span><br><span>index da62b30..833dcca 100644</span><br><span>--- a/src/bts.cpp</span><br><span>+++ b/src/bts.cpp</span><br><span>@@ -536,18 +536,51 @@</span><br><span>       return m_bts.trx[trx].pdch[ts].ul_tbf_by_tfi(tfi);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t trx_count_free_tfi(const struct gprs_rlcmac_trx *trx, enum gprs_rlcmac_tbf_direction dir, uint32_t *free_tfi_mask)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct gprs_rlcmac_pdch *pdch;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t ts;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned i;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t free_tfi = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool has_pdch = false;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t mask = NO_FREE_TFI;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (ts = 0; ts < 8; ts++) {</span><br><span style="color: hsl(120, 100%, 40%);">+               pdch = &trx->pdch[ts];</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!pdch->is_enabled())</span><br><span style="color: hsl(120, 100%, 40%);">+                   continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             has_pdch = true;</span><br><span style="color: hsl(120, 100%, 40%);">+              mask &= ~pdch->assigned_tfi(dir);</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 (!has_pdch || !mask) {</span><br><span style="color: hsl(120, 100%, 40%);">+             *free_tfi_mask = 0;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *free_tfi_mask = mask;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Count free tfis and return */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < sizeof(uint32_t)*8 ; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if(mask & 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                      free_tfi++;</span><br><span style="color: hsl(120, 100%, 40%);">+           mask >>= 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return free_tfi;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*</span><br><span style="color: hsl(0, 100%, 40%);">- * Search for free TFI and return TFI, TRX.</span><br><span style="color: hsl(0, 100%, 40%);">- * This method returns the first TFI that is currently not used in any PDCH of</span><br><span style="color: hsl(0, 100%, 40%);">- * a TRX. The first TRX that contains such an TFI is returned. Negative values</span><br><span style="color: hsl(0, 100%, 40%);">- * indicate errors.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Search for free TFI and return TFI, TRX. This method returns the first TFI</span><br><span style="color: hsl(120, 100%, 40%);">+ * that is currently not used in any PDCH of a the TRX with least TFIs currently</span><br><span style="color: hsl(120, 100%, 40%);">+ * assigned. Negative values indicate errors.</span><br><span>  */</span><br><span> int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx) const</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    const struct gprs_rlcmac_pdch *pdch;</span><br><span style="color: hsl(0, 100%, 40%);">-    uint32_t free_tfis;</span><br><span style="color: hsl(0, 100%, 40%);">-     bool has_pdch = false;</span><br><span style="color: hsl(0, 100%, 40%);">-  uint8_t trx_from, trx_to, trx, ts, tfi;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t trx_from, trx_to, trx, tfi;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t best_trx_nr = 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t best_cnt = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t best_mask = 0;</span><br><span> </span><br><span>  if (use_trx >= 0 && use_trx < 8)</span><br><span>               trx_from = trx_to = use_trx;</span><br><span>@@ -558,47 +591,36 @@</span><br><span> </span><br><span>     /* find a TFI that is unused on all PDCH */</span><br><span>  for (trx = trx_from; trx <= trx_to; trx++) {</span><br><span style="color: hsl(0, 100%, 40%);">-         bool trx_has_pdch = false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          free_tfis = NO_FREE_TFI;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                for (ts = 0; ts < 8; ts++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 pdch = &m_bts.trx[trx].pdch[ts];</span><br><span style="color: hsl(0, 100%, 40%);">-                    if (!pdch->is_enabled())</span><br><span style="color: hsl(0, 100%, 40%);">-                             continue;</span><br><span style="color: hsl(0, 100%, 40%);">-                       free_tfis &= ~pdch->assigned_tfi(dir);</span><br><span style="color: hsl(0, 100%, 40%);">-                   trx_has_pdch = true;</span><br><span style="color: hsl(0, 100%, 40%);">-                    has_pdch = true;</span><br><span style="color: hsl(120, 100%, 40%);">+              uint32_t tmp_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+            uint8_t tmp_cnt;</span><br><span style="color: hsl(120, 100%, 40%);">+              tmp_cnt = trx_count_free_tfi(&m_bts.trx[trx], dir, &tmp_mask);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (tmp_cnt > best_cnt) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  best_cnt = tmp_cnt;</span><br><span style="color: hsl(120, 100%, 40%);">+                   best_mask = tmp_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+                 best_trx_nr = trx;</span><br><span>           }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (trx_has_pdch && free_tfis)</span><br><span style="color: hsl(0, 100%, 40%);">-                  break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          free_tfis = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!has_pdch) {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-           return -EINVAL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!free_tfis) {</span><br><span style="color: hsl(120, 100%, 40%);">+     if (best_trx_nr == 0xff || best_cnt == 0) {</span><br><span>          LOGP(DRLCMAC, LOGL_NOTICE, "No TFI available (suggested TRX: %d).\n", use_trx);</span><br><span>            return -EBUSY;</span><br><span>       }</span><br><span> </span><br><span> </span><br><span>    LOGP(DRLCMAC, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">-               "Searching for first unallocated TFI: TRX=%d\n", trx);</span><br><span style="color: hsl(120, 100%, 40%);">+              "Searching for first unallocated TFI: TRX=%d\n", best_trx_nr);</span><br><span> </span><br><span>         /* find the first */</span><br><span>         for (tfi = 0; tfi < 32; tfi++) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (free_tfis & 1 << tfi)</span><br><span style="color: hsl(120, 100%, 40%);">+           if (best_mask & 1 << tfi)</span><br><span>                  break;</span><br><span>       }</span><br><span> </span><br><span>        OSMO_ASSERT(tfi < 32);</span><br><span> </span><br><span>        LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi);</span><br><span style="color: hsl(0, 100%, 40%);">-   *_trx = trx;</span><br><span style="color: hsl(120, 100%, 40%);">+  *_trx = best_trx_nr;</span><br><span>         return tfi;</span><br><span> }</span><br><span> </span><br><span>diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp</span><br><span>index 2b5bda5..8a6789b 100644</span><br><span>--- a/tests/tbf/TbfTest.cpp</span><br><span>+++ b/tests/tbf/TbfTest.cpp</span><br><span>@@ -197,6 +197,7 @@</span><br><span>  tfi = the_bts->tfi_find_free(GPRS_RLCMAC_DL_TBF, &trx_no, -1);</span><br><span>        OSMO_ASSERT(tfi >= 0);</span><br><span>    dl_tbf = tbf_alloc_dl_tbf(bts, ms, trx_no, true);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(dl_tbf);</span><br><span>         dl_tbf->set_ta(0);</span><br><span>        check_tbf(dl_tbf);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-pcu/+/20919">change 20919</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/c/osmo-pcu/+/20919"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-pcu </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Iccfc8acfbfdc258ed16cc5af01f12b376fe73b72 </div>
<div style="display:none"> Gerrit-Change-Number: 20919 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>