<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-pcu/+/26210">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  dexter: Looks good to me, but someone else must approve
  pespin: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">bts: Add counter availablePDCHAllocatedTime<br><br>We basically want to probe whether it's possible to allocate TBFs, or<br>whether we know it will fail due to all main resources being already in<br>use (TFI, USF).<br><br>Having bts_all_pdch_allocated() return false doesn't mean though that an<br>MS will be able to allocate a TBF for sure. That's because further<br>restrictions are applied based on MS: whether it was already attached to<br>a specific TRX, whether the ms_class allows for a certain multislot<br>combination, etc. However, it should provide a general idea on whether<br>for sure the PCU is unable to provide more allocations. More fine<br>grained state about failures can still be followed by looking at<br>tbf:alloc:failed:* rate counters.<br><br>Related: SYS#4878<br>Depends: Iabb17a08e6e1a86f168cdb008fba05ecd4776bdd (libosmocore)<br>Change-Id: Ie0f0c451558817bddc3fe1a0f0df531f14c9f1d3<br>---<br>M src/bts.cpp<br>M src/bts.h<br>M src/gprs_pcu.c<br>M src/gprs_pcu.h<br>M src/pdch.cpp<br>M src/pdch.h<br>M tests/alloc/AllocTest.cpp<br>7 files changed, 83 insertions(+), 0 deletions(-)<br><br></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 6fabc90..05a9cc0 100644</span><br><span>--- a/src/bts.cpp</span><br><span>+++ b/src/bts.cpp</span><br><span>@@ -83,6 +83,20 @@</span><br><span>     { .T=3191, .default_val=5,   .unit=OSMO_TDEF_S,  .desc="Reuse of TFI(s) after sending (1) last RLC Data Block on TBF(s), or (2) PACKET TBF RELEASE for an MBMS radio bearer", .val=0 },</span><br><span>    { .T=3193, .default_val=100, .unit=OSMO_TDEF_MS, .desc="Reuse of TFI(s) after reception of final PACKET DOWNLINK ACK/NACK from MS for TBF", .val=0 },</span><br><span>      { .T=3195, .default_val=5,   .unit=OSMO_TDEF_S,  .desc="Reuse of TFI(s) upon no response from the MS (radio failure or cell change) for TBF/MBMS radio bearer", .val=0 },</span><br><span style="color: hsl(120, 100%, 40%);">+   { .T = -16, .default_val = 1000, .unit = OSMO_TDEF_MS,</span><br><span style="color: hsl(120, 100%, 40%);">+                .desc = "Granularity for *:all_allocated rate counters: amount of milliseconds that one counter increment"</span><br><span style="color: hsl(120, 100%, 40%);">+                  " represents. See also X17, X18" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { .T = -17, .default_val = 0, .unit = OSMO_TDEF_MS,</span><br><span style="color: hsl(120, 100%, 40%);">+           .desc = "Rounding threshold for *:all_allocated rate counters: round up to the next counter increment"</span><br><span style="color: hsl(120, 100%, 40%);">+                      " after this many milliseconds. If set to half of X16 (or 0), employ the usual round() behavior:"</span><br><span style="color: hsl(120, 100%, 40%);">+                   " round up after half of a granularity period. If set to 1, behave like ceil(): already"</span><br><span style="color: hsl(120, 100%, 40%);">+                    " increment the counter immediately when all channels are allocated. If set >= X16, behave like"</span><br><span style="color: hsl(120, 100%, 40%);">+                 " floor(): only increment after a full X16 period of all channels being occupied."</span><br><span style="color: hsl(120, 100%, 40%);">+                  " See also X16, X18" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { .T = -18, .default_val = 60000, .unit = OSMO_TDEF_MS,</span><br><span style="color: hsl(120, 100%, 40%);">+               .desc = "Forget-sum period for *:all_allocated rate counters:"</span><br><span style="color: hsl(120, 100%, 40%);">+                      " after this amount of idle time, forget internally cumulated time remainders. Zero to always"</span><br><span style="color: hsl(120, 100%, 40%);">+                      " keep remainders. See also X16, X17." },</span><br><span>  { .T=0, .default_val=0, .unit=OSMO_TDEF_S, .desc=NULL, .val=0 } /* empty item at the end */</span><br><span> };</span><br><span> </span><br><span>@@ -92,6 +106,7 @@</span><br><span>  * the code below.</span><br><span>  */</span><br><span> static const struct rate_ctr_desc bts_ctr_description[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+        { "pdch:all_allocated",               "Cumulative counter of seconds where all enabled PDCH resources were allocated"},</span><br><span>  { "tbf:dl:alloc",             "TBF DL Allocated     "},</span><br><span>  { "tbf:dl:freed",             "TBF DL Freed         "},</span><br><span>  { "tbf:dl:aborted",           "TBF DL Aborted       "},</span><br><span>@@ -231,6 +246,8 @@</span><br><span>    bts->ms_store->cleanup();</span><br><span>      delete bts->ms_store;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_time_cc_cleanup(&bts->all_allocated_pdch);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     if (bts->ratectrs) {</span><br><span>              rate_ctr_group_free(bts->ratectrs);</span><br><span>               bts->ratectrs = NULL;</span><br><span>@@ -300,6 +317,16 @@</span><br><span>      bts->statg = osmo_stat_item_group_alloc(tall_pcu_ctx, &bts_statg_desc, 0);</span><br><span>    OSMO_ASSERT(bts->statg);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_time_cc_init(&bts->all_allocated_pdch);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_time_cc_cfg *cc_cfg = &bts->all_allocated_pdch.cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+        cc_cfg->gran_usec = 1*1000000,</span><br><span style="color: hsl(120, 100%, 40%);">+     cc_cfg->forget_sum_usec = 60*1000000,</span><br><span style="color: hsl(120, 100%, 40%);">+      cc_cfg->rate_ctr = rate_ctr_group_get_ctr(bts->ratectrs, CTR_PDCH_ALL_ALLOCATED),</span><br><span style="color: hsl(120, 100%, 40%);">+       cc_cfg->T_gran = -16,</span><br><span style="color: hsl(120, 100%, 40%);">+      cc_cfg->T_round_threshold = -17,</span><br><span style="color: hsl(120, 100%, 40%);">+   cc_cfg->T_forget_sum = -18,</span><br><span style="color: hsl(120, 100%, 40%);">+        cc_cfg->T_defs = T_defs_bts,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    llist_add_tail(&bts->list, &pcu->bts_list);</span><br><span> </span><br><span>        INIT_LLIST_HEAD(&bts->pch_timer);</span><br><span>@@ -1371,3 +1398,20 @@</span><br><span>     * B.2 Closed loop control */</span><br><span>        return 0;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Used by counter availablePDCHAllocatedTime, TS 52.402 B.2.1.45 "All available PDCH allocated time" */</span><br><span style="color: hsl(120, 100%, 40%);">+bool bts_all_pdch_allocated(const struct gprs_rlcmac_bts *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned trx_no, ts_no;</span><br><span style="color: hsl(120, 100%, 40%);">+       for (trx_no = 0; trx_no < ARRAY_SIZE(bts->trx); trx_no++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             const struct gprs_rlcmac_trx *trx = &bts->trx[trx_no];</span><br><span style="color: hsl(120, 100%, 40%);">+         for (ts_no = 0; ts_no < ARRAY_SIZE(trx->pdch); ts_no++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       const struct gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (!pdch_is_enabled(pdch))</span><br><span style="color: hsl(120, 100%, 40%);">+                           continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if(!pdch_is_full(pdch))</span><br><span style="color: hsl(120, 100%, 40%);">+                               return false;</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%);">+     return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/bts.h b/src/bts.h</span><br><span>index f947a55..6bf62c7 100644</span><br><span>--- a/src/bts.h</span><br><span>+++ b/src/bts.h</span><br><span>@@ -32,6 +32,7 @@</span><br><span> #include <osmocom/core/rate_ctr.h></span><br><span> #include <osmocom/core/stat_item.h></span><br><span> #include <osmocom/core/tdef.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/time_cc.h></span><br><span> #include <osmocom/gprs/gprs_ns2.h></span><br><span> #include <osmocom/gsm/l1sap.h></span><br><span> #include <osmocom/gsm/protocol/gsm_04_08.h></span><br><span>@@ -84,6 +85,7 @@</span><br><span> </span><br><span> </span><br><span> enum {</span><br><span style="color: hsl(120, 100%, 40%);">+ CTR_PDCH_ALL_ALLOCATED,</span><br><span>      CTR_TBF_DL_ALLOCATED,</span><br><span>        CTR_TBF_DL_FREED,</span><br><span>    CTR_TBF_DL_ABORTED,</span><br><span>@@ -278,6 +280,8 @@</span><br><span> </span><br><span>        /* List of struct bts_pch_timer for active PCH pagings */</span><br><span>    struct llist_head pch_timer;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_time_cc all_allocated_pdch;</span><br><span> };</span><br><span> </span><br><span> #ifdef __cplusplus</span><br><span>@@ -381,6 +385,7 @@</span><br><span> bool bts_cs_dl_is_supported(const struct gprs_rlcmac_bts *bts, enum CodingScheme cs);</span><br><span> const struct llist_head* bts_ms_list(struct gprs_rlcmac_bts *bts);</span><br><span> uint8_t bts_get_ms_pwr_alpha(const struct gprs_rlcmac_bts *bts);</span><br><span style="color: hsl(120, 100%, 40%);">+bool bts_all_pdch_allocated(const struct gprs_rlcmac_bts *bts);</span><br><span> #ifdef __cplusplus</span><br><span> }</span><br><span> #endif</span><br><span>diff --git a/src/gprs_pcu.c b/src/gprs_pcu.c</span><br><span>index 5ed9d7d..8b8e46b 100644</span><br><span>--- a/src/gprs_pcu.c</span><br><span>+++ b/src/gprs_pcu.c</span><br><span>@@ -47,8 +47,21 @@</span><br><span>     { .T=0, .default_val=0, .unit=OSMO_TDEF_S, .desc=NULL, .val=0 } /* empty item at the end */</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void _update_stats_timer_cb(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gprs_pcu *pcu = (struct gprs_pcu *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gprs_rlcmac_bts *bts;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        llist_for_each_entry(bts, &pcu->bts_list, list)</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_time_cc_set_flag(&bts->all_allocated_pdch, bts_all_pdch_allocated(bts));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_timer_schedule(&pcu->update_stats_timer, 1, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int gprs_pcu_talloc_destructor(struct gprs_pcu *pcu)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (osmo_timer_pending(&pcu->update_stats_timer))</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_timer_del(&pcu->update_stats_timer);</span><br><span>     neigh_cache_free(pcu->neigh_cache);</span><br><span>       si_cache_free(pcu->si_cache);</span><br><span>     return 0;</span><br><span>@@ -125,6 +138,9 @@</span><br><span>      pcu->neigh_cache = neigh_cache_alloc(pcu, osmo_tdef_get(pcu->T_defs, PCU_TDEF_NEIGH_CACHE_ALIVE, OSMO_TDEF_S, -1));</span><br><span>    pcu->si_cache = si_cache_alloc(pcu, osmo_tdef_get(pcu->T_defs, PCU_TDEF_SI_CACHE_ALIVE, OSMO_TDEF_S, -1));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_timer_setup(&pcu->update_stats_timer, _update_stats_timer_cb, pcu);</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_timer_schedule(&pcu->update_stats_timer, 1, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        return pcu;</span><br><span> }</span><br><span> </span><br><span>diff --git a/src/gprs_pcu.h b/src/gprs_pcu.h</span><br><span>index ed00221..a9e40ea 100644</span><br><span>--- a/src/gprs_pcu.h</span><br><span>+++ b/src/gprs_pcu.h</span><br><span>@@ -25,6 +25,7 @@</span><br><span> #include <stdbool.h></span><br><span> </span><br><span> #include <osmocom/core/gsmtap_util.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/timer.h></span><br><span> </span><br><span> #include "gprs_bssgp_pcu.h"</span><br><span> #include "coding_scheme.h"</span><br><span>@@ -131,6 +132,8 @@</span><br><span> </span><br><span>         struct neigh_cache *neigh_cache; /* ARFC+BSIC -> CGI PS cache */</span><br><span>  struct si_cache *si_cache; /* ARFC+BSIC -> CGI PS cache */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmo_timer_list update_stats_timer; /* Used to update some time_cc stats periodically */</span><br><span> };</span><br><span> </span><br><span> </span><br><span>diff --git a/src/pdch.cpp b/src/pdch.cpp</span><br><span>index a942b01..a5eb080 100644</span><br><span>--- a/src/pdch.cpp</span><br><span>+++ b/src/pdch.cpp</span><br><span>@@ -1286,3 +1286,13 @@</span><br><span> {</span><br><span>     return pdch->is_enabled();</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* To be called only on enabled PDCHs. Used to gather information on whether the</span><br><span style="color: hsl(120, 100%, 40%);">+ * PDCH is currently unable to allocate more TBFs due to any resource being</span><br><span style="color: hsl(120, 100%, 40%);">+ * full. Used by bts_all_pdch_allocated() for counting purposes. */</span><br><span style="color: hsl(120, 100%, 40%);">+bool pdch_is_full(const struct gprs_rlcmac_pdch *pdch)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return pdch->assigned_tfi(GPRS_RLCMAC_UL_TBF) == NO_FREE_TFI ||</span><br><span style="color: hsl(120, 100%, 40%);">+           pdch->assigned_tfi(GPRS_RLCMAC_DL_TBF) == NO_FREE_TFI ||</span><br><span style="color: hsl(120, 100%, 40%);">+           find_free_usf(pdch->assigned_usf()) < 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/pdch.h b/src/pdch.h</span><br><span>index 9405606..759d7f9 100644</span><br><span>--- a/src/pdch.h</span><br><span>+++ b/src/pdch.h</span><br><span>@@ -194,6 +194,7 @@</span><br><span> void pdch_free_all_tbf(struct gprs_rlcmac_pdch *pdch);</span><br><span> void pdch_disable(struct gprs_rlcmac_pdch *pdch);</span><br><span> bool pdch_is_enabled(const struct gprs_rlcmac_pdch *pdch);</span><br><span style="color: hsl(120, 100%, 40%);">+bool pdch_is_full(const struct gprs_rlcmac_pdch *pdch);</span><br><span> #ifdef __cplusplus</span><br><span> }</span><br><span> #endif</span><br><span>diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp</span><br><span>index 1f2bbda..6f3de43 100644</span><br><span>--- a/tests/alloc/AllocTest.cpp</span><br><span>+++ b/tests/alloc/AllocTest.cpp</span><br><span>@@ -152,6 +152,8 @@</span><br><span> </span><br><span>    OSMO_ASSERT(i == count);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(bts_all_pdch_allocated(bts));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  for (i = 0; i < count; ++i)</span><br><span>               if (tbfs[i])</span><br><span>                         tbf_free(tbfs[i]);</span><br><span>@@ -479,6 +481,7 @@</span><br><span>                     tbf_free(ms_ul_tbf(old_ms));</span><br><span>                 tbf = tbf_alloc_ul_tbf(bts, old_ms, trx_no, false);</span><br><span>          if (tbf == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    OSMO_ASSERT(trx_no != -1 || bts_all_pdch_allocated(bts));</span><br><span>                    ms_unref(old_ms);</span><br><span>                    return NULL;</span><br><span>                 }</span><br><span>@@ -490,6 +493,7 @@</span><br><span>                      tbf_free(ms_dl_tbf(old_ms));</span><br><span>                 tbf = tbf_alloc_dl_tbf(bts, old_ms, trx_no, false);</span><br><span>          if (tbf == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    OSMO_ASSERT(trx_no != -1 || bts_all_pdch_allocated(bts));</span><br><span>                    ms_unref(old_ms);</span><br><span>                    return NULL;</span><br><span>                 }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-pcu/+/26210">change 26210</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/+/26210"/><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: Ie0f0c451558817bddc3fe1a0f0df531f14c9f1d3 </div>
<div style="display:none"> Gerrit-Change-Number: 26210 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>