<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bsc/+/19303">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: Introduce support for ACC subset rotation<br><br>Change-Id: I952c9eeae02809c7184078c655574ec817902e06<br>---<br>M include/osmocom/bsc/acc_ramp.h<br>M include/osmocom/bsc/bts.h<br>M src/osmo-bsc/acc_ramp.c<br>M src/osmo-bsc/bsc_vty.c<br>M src/osmo-bsc/bts.c<br>M src/osmo-bsc/system_information.c<br>M tests/gsm0408/gsm0408_test.c<br>7 files changed, 342 insertions(+), 94 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/03/19303/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/acc_ramp.h b/include/osmocom/bsc/acc_ramp.h</span><br><span>index 31fc74f..483f437 100644</span><br><span>--- a/include/osmocom/bsc/acc_ramp.h</span><br><span>+++ b/include/osmocom/bsc/acc_ramp.h</span><br><span>@@ -27,6 +27,40 @@</span><br><span> #include <osmocom/core/timer.h></span><br><span> #include <osmocom/gsm/protocol/gsm_04_08.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define ACC_MGR_QUANTUM_DEFAULT 20       /* 20 seconds */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Manage rotating subset of allowed Access Class as per configuration */</span><br><span style="color: hsl(120, 100%, 40%);">+struct acc_mgr {</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_bts *bts; /*!< backpointer to BTS using this ACC manager */</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Administrative Maximum Number of ACC 0-9 to be allowed at the same time.</span><br><span style="color: hsl(120, 100%, 40%);">+      Configurable through VTY cmd "access-control-class-roundrobin",</span><br><span style="color: hsl(120, 100%, 40%);">+     defaults to all allowed (10) */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t len_allowed_adm;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Further limiting the number of ACC to use. It may be lower due</span><br><span style="color: hsl(120, 100%, 40%);">+        to ramping, based for instance on channel or system load. */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t len_allowed_ramp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Time until next subset is generated */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t rotation_time_sec;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_timer_list rotate_timer;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Bitmask containing subset of allowed ACC 0-9 on current rotation iteration */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t allowed_subset_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Number of bits (ACC) set in allowed_subset_mask: 0->min(len_allowed_ramp, len_allowed_adm) */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t allowed_subset_mask_count;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Number of ACC 0-9 allowed as per adminsitrative (permanent) config. */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t allowed_permanent_count;</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%);">+void acc_mgr_init(struct acc_mgr *acc_mgr, struct gsm_bts *bts);</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t acc_mgr_get_len_allowed_adm(struct acc_mgr *acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+uint8_t acc_mgr_get_len_allowed_ramp(struct acc_mgr *acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+void acc_mgr_set_len_allowed_adm(struct acc_mgr *acc_mgr, uint8_t len_allowed_adm);</span><br><span style="color: hsl(120, 100%, 40%);">+void acc_mgr_set_len_allowed_ramp(struct acc_mgr *acc_mgr, uint8_t len_allowed_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+void acc_mgr_set_rotation_time(struct acc_mgr *acc_mgr, uint32_t rotation_time_sec);</span><br><span style="color: hsl(120, 100%, 40%);">+void acc_mgr_perm_subset_changed(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control);</span><br><span style="color: hsl(120, 100%, 40%);">+void acc_mgr_apply_acc(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span>  * Access control class (ACC) ramping is used to slowly make the cell available to</span><br><span>  * an increasing number of MS. This avoids overload at startup time in cases where</span><br><span>@@ -126,33 +160,6 @@</span><br><span>        return !(acc_ramp->step_interval_is_fixed);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * Return bitmasks which correspond to access control classes that are currently</span><br><span style="color: hsl(0, 100%, 40%);">- * denied access. Ramping is only concerned with those bits which control access</span><br><span style="color: hsl(0, 100%, 40%);">- * for ACCs 0-9, and any of the other bits will always be set to zero in these masks, i.e.</span><br><span style="color: hsl(0, 100%, 40%);">- * it is safe to OR these bitmasks with the corresponding fields in struct gsm48_rach_control.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] acc_ramp Pointer to acc_ramp structure.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static inline uint8_t acc_ramp_get_barred_t2(struct acc_ramp *acc_ramp)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      return ((acc_ramp->barred_accs >> 8) & 0x03);</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-static inline uint8_t acc_ramp_get_barred_t3(struct acc_ramp *acc_ramp)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    return (acc_ramp->barred_accs & 0xff);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * Potentially mark certain Access Control Classes (ACCs) as barred in accordance to ACC ramping.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] rach_control RACH control parameters in which barred ACCs will be configured.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] acc_ramp Pointer to acc_ramp structure.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static inline void acc_ramp_apply(struct gsm48_rach_control *rach_control, struct acc_ramp *acc_ramp)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     rach_control->t2 |= acc_ramp_get_barred_t2(acc_ramp);</span><br><span style="color: hsl(0, 100%, 40%);">-        rach_control->t3 |= acc_ramp_get_barred_t3(acc_ramp);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> void acc_ramp_init(struct acc_ramp *acc_ramp, struct gsm_bts *bts);</span><br><span> int acc_ramp_set_step_size(struct acc_ramp *acc_ramp, unsigned int step_size);</span><br><span> int acc_ramp_set_step_interval(struct acc_ramp *acc_ramp, unsigned int step_interval);</span><br><span>diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h</span><br><span>index 730dee9..16053a3 100644</span><br><span>--- a/include/osmocom/bsc/bts.h</span><br><span>+++ b/include/osmocom/bsc/bts.h</span><br><span>@@ -449,6 +449,7 @@</span><br><span>  uint32_t si_mode_static;</span><br><span> </span><br><span>         /* access control class ramping */</span><br><span style="color: hsl(120, 100%, 40%);">+    struct acc_mgr acc_mgr;</span><br><span>      struct acc_ramp acc_ramp;</span><br><span> </span><br><span>        /* exclude the BTS from the global RF Lock handling */</span><br><span>diff --git a/src/osmo-bsc/acc_ramp.c b/src/osmo-bsc/acc_ramp.c</span><br><span>index 761ab09..8406b82 100644</span><br><span>--- a/src/osmo-bsc/acc_ramp.c</span><br><span>+++ b/src/osmo-bsc/acc_ramp.c</span><br><span>@@ -20,6 +20,8 @@</span><br><span>  */</span><br><span> </span><br><span> #include <strings.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span> #include <errno.h></span><br><span> #include <stdbool.h></span><br><span> </span><br><span>@@ -43,42 +45,276 @@</span><br><span>    return (bts->si_common.rach_control.t3 & (1 << (acc)));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void allow_one_acc(struct acc_ramp *acc_ramp, unsigned int acc)</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return bitmasks which correspond to access control classes that are currently</span><br><span style="color: hsl(120, 100%, 40%);">+ * denied access. Ramping is only concerned with those bits which control access</span><br><span style="color: hsl(120, 100%, 40%);">+ * for ACCs 0-9, and any of the other bits will always be set to zero in these masks, i.e.</span><br><span style="color: hsl(120, 100%, 40%);">+ * it is safe to OR these bitmasks with the corresponding fields in struct gsm48_rach_control.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] acc_ramp Pointer to acc_ramp structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t acc_mgr_get_barred_t2(struct acc_mgr *acc_mgr)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(acc <= 9);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (acc_ramp->barred_accs & (1 << acc))</span><br><span style="color: hsl(0, 100%, 40%);">-            LOG_BTS(acc_ramp->bts, DRSL, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">-                    "ACC RAMP: allowing Access Control Class %u\n", acc);</span><br><span style="color: hsl(0, 100%, 40%);">- acc_ramp->barred_accs &= ~(1 << acc);</span><br><span style="color: hsl(120, 100%, 40%);">+    return ((~acc_mgr->allowed_subset_mask) >> 8) & 0x03;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint8_t acc_mgr_get_barred_t3(struct acc_mgr *acc_mgr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return (~acc_mgr->allowed_subset_mask) & 0xff;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void barr_one_acc(struct acc_ramp *acc_ramp, unsigned int acc)</span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t acc_mgr_subset_len(struct acc_mgr *acc_mgr)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(acc <= 9);</span><br><span style="color: hsl(0, 100%, 40%);">-       if ((acc_ramp->barred_accs & (1 << acc)) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">-             LOG_BTS(acc_ramp->bts, DRSL, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">-                    "ACC RAMP: barring Access Control Class %u\n", acc);</span><br><span style="color: hsl(0, 100%, 40%);">-  acc_ramp->barred_accs |= (1 << acc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return OSMO_MIN(acc_mgr->len_allowed_ramp, acc_mgr->len_allowed_adm);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void barr_all_accs(struct acc_ramp *acc_ramp)</span><br><span style="color: hsl(120, 100%, 40%);">+static void acc_mgr_enable_rotation_cond(struct acc_mgr *acc_mgr)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        unsigned int acc;</span><br><span style="color: hsl(0, 100%, 40%);">-       for (acc = 0; acc < 10; acc++) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!acc_is_permanently_barred(acc_ramp->bts, acc))</span><br><span style="color: hsl(0, 100%, 40%);">-                  barr_one_acc(acc_ramp, acc);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (acc_mgr->allowed_permanent_count &&</span><br><span style="color: hsl(120, 100%, 40%);">+        acc_mgr->allowed_permanent_count == acc_mgr->allowed_subset_mask_count) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!osmo_timer_pending(&acc_mgr->rotate_timer))</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmo_timer_schedule(&acc_mgr->rotate_timer, acc_mgr->rotation_time_sec, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* No rotation needed, disable rotation timer */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (osmo_timer_pending(&acc_mgr->rotate_timer))</span><br><span style="color: hsl(120, 100%, 40%);">+                        osmo_timer_del(&acc_mgr->rotate_timer);</span><br><span>       }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void allow_all_accs(struct acc_ramp *acc_ramp)</span><br><span style="color: hsl(120, 100%, 40%);">+static void acc_mgr_gen_subset(struct acc_mgr *acc_mgr, bool update_si)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   unsigned int acc;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t acc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        acc_mgr->allowed_subset_mask = 0; /* clean mask */</span><br><span style="color: hsl(120, 100%, 40%);">+ acc_mgr->allowed_subset_mask_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    acc_mgr->allowed_permanent_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   for (acc = 0; acc < 10; acc++) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!acc_is_permanently_barred(acc_ramp->bts, acc))</span><br><span style="color: hsl(0, 100%, 40%);">-                  allow_one_acc(acc_ramp, acc);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (acc_is_permanently_barred(acc_mgr->bts, acc))</span><br><span style="color: hsl(120, 100%, 40%);">+                  continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             acc_mgr->allowed_permanent_count++;</span><br><span style="color: hsl(120, 100%, 40%);">+                if (acc_mgr->allowed_subset_mask_count < acc_mgr_subset_len(acc_mgr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 acc_mgr->allowed_subset_mask &= (1 << acc);</span><br><span style="color: hsl(120, 100%, 40%);">+                      acc_mgr->allowed_subset_mask_count++;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   LOG_BTS(acc_mgr->bts, DRSL, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+             "ACC: New ACC allowed subset 0x%" PRIx16 " (allowed=%" PRIu8</span><br><span style="color: hsl(120, 100%, 40%);">+              ", adm_len=%" PRIu8 ", ramp_len=%" PRIu8 ")\n",</span><br><span style="color: hsl(120, 100%, 40%);">+         acc_mgr->allowed_subset_mask, acc_mgr->allowed_subset_mask_count,</span><br><span style="color: hsl(120, 100%, 40%);">+               acc_mgr->len_allowed_adm, acc_mgr->len_allowed_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ acc_mgr_enable_rotation_cond(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Trigger SI data update, acc_mgr_apply_acc will bew called */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (update_si)</span><br><span style="color: hsl(120, 100%, 40%);">+                gsm_bts_set_system_infos(acc_mgr->bts);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static uint8_t get_highest_allowed_acc(uint16_t mask)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ for (int i = 9; i >= 0; i--) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (mask & (1 << i))</span><br><span style="color: hsl(120, 100%, 40%);">+                        return i;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(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%);">+static uint8_t get_lowest_allowed_acc(uint16_t mask)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       for (int i = 0; i < 10; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (mask & (1 << i))</span><br><span style="color: hsl(120, 100%, 40%);">+                        return i;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(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%);">+/* Call when either adm_len or ramp_len changed (and values have been updated) */</span><br><span style="color: hsl(120, 100%, 40%);">+static void acc_mgr_subset_length_changed(struct acc_mgr *acc_mgr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t curr_len = acc_mgr->allowed_subset_mask_count;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t new_len = acc_mgr_subset_len(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t diff = new_len - curr_len;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (curr_len == new_len)</span><br><span style="color: hsl(120, 100%, 40%);">+              return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (new_len == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           acc_mgr->allowed_subset_mask = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+          acc_mgr->allowed_subset_mask_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            acc_mgr_enable_rotation_cond(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+                gsm_bts_set_system_infos(acc_mgr->bts);</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</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 (curr_len == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          acc_mgr_gen_subset(acc_mgr, true);</span><br><span style="color: hsl(120, 100%, 40%);">+            return;</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%);">+   /* Try to add new ACCs to the set starting from highest one (since we rotate rolling up) */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (diff > 0) { /* curr_len < new_len */</span><br><span style="color: hsl(120, 100%, 40%);">+                uint8_t highest = get_highest_allowed_acc(acc_mgr->allowed_subset_mask);</span><br><span style="color: hsl(120, 100%, 40%);">+           /* It's fine skipping highest in the loop since it's known to be already set: */</span><br><span style="color: hsl(120, 100%, 40%);">+              for (i = (highest + 1) % 10; i != highest; i = (i + 1) % 10) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (acc_is_permanently_barred(acc_mgr->bts, i))</span><br><span style="color: hsl(120, 100%, 40%);">+                            continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (acc_mgr->allowed_subset_mask & (1 << i))</span><br><span style="color: hsl(120, 100%, 40%);">+                             continue; /* already in set */</span><br><span style="color: hsl(120, 100%, 40%);">+                        acc_mgr->allowed_subset_mask &= (1 << i);</span><br><span style="color: hsl(120, 100%, 40%);">+                        acc_mgr->allowed_subset_mask_count++;</span><br><span style="color: hsl(120, 100%, 40%);">+                      diff--;</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (diff == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else { /* curr_len > new_len, try removing from lowest one. */</span><br><span style="color: hsl(120, 100%, 40%);">+           uint8_t lowest = get_lowest_allowed_acc(acc_mgr->allowed_subset_mask);</span><br><span style="color: hsl(120, 100%, 40%);">+             i = lowest;</span><br><span style="color: hsl(120, 100%, 40%);">+           do {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if ((acc_mgr->allowed_subset_mask & (1 << i))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         acc_mgr->allowed_subset_mask &= ~(1 << i);</span><br><span style="color: hsl(120, 100%, 40%);">+                               acc_mgr->allowed_subset_mask_count--;</span><br><span style="color: hsl(120, 100%, 40%);">+                              diff++;</span><br><span style="color: hsl(120, 100%, 40%);">+                               if (diff == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     i = (i + 1) % 10;</span><br><span style="color: hsl(120, 100%, 40%);">+             } while(i != lowest);</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%);">+   acc_mgr_enable_rotation_cond(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* if we updated the set, notify about it */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (curr_len != acc_mgr->allowed_subset_mask_count)</span><br><span style="color: hsl(120, 100%, 40%);">+                gsm_bts_set_system_infos(acc_mgr->bts);</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%);">+static void do_acc_rotate_step(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct acc_mgr *acc_mgr = data;</span><br><span style="color: hsl(120, 100%, 40%);">+       int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t old_mask = acc_mgr->allowed_subset_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Assumption: The size of the subset didn't change, that's handled by</span><br><span style="color: hsl(120, 100%, 40%);">+         * acc_mgr_subset_length_changed()</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%);">+ /* Assumption: Rotation timer has been disabled if no ACC is allowed */</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(acc_mgr->allowed_subset_mask_count != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* One ACC is rotated at a time: Drop lowest ACC and add next from highest ACC */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t lowest = get_lowest_allowed_acc(acc_mgr->allowed_subset_mask);</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t highest = get_highest_allowed_acc(acc_mgr->allowed_subset_mask);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ acc_mgr->allowed_subset_mask &= ~(1 << lowest);</span><br><span style="color: hsl(120, 100%, 40%);">+  i = (highest + 1) % 10;</span><br><span style="color: hsl(120, 100%, 40%);">+       do {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!acc_is_permanently_barred(acc_mgr->bts, i) &&</span><br><span style="color: hsl(120, 100%, 40%);">+             !(acc_mgr->allowed_subset_mask & (1 << i))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* found first one which can be allowed, do it and be done */</span><br><span style="color: hsl(120, 100%, 40%);">+                 acc_mgr->allowed_subset_mask &= (1 << i);</span><br><span style="color: hsl(120, 100%, 40%);">+                        acc_mgr->allowed_subset_mask_count++;</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             i = (i + 1 ) % 10;</span><br><span style="color: hsl(120, 100%, 40%);">+    } while (i != (highest + 1) % 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (old_mask != acc_mgr->allowed_subset_mask) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOG_BTS(acc_mgr->bts, DRSL, LOGL_INFO,</span><br><span style="color: hsl(120, 100%, 40%);">+                     "ACC: New ACC allowed subset 0x%" PRIx16 " -> 0x%" PRIx16</span><br><span style="color: hsl(120, 100%, 40%);">+                      " (allowed=%" PRIu8 ", adm_len=%" PRIu8 ", ramp_len=%" PRIu8 ")\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   old_mask, acc_mgr->allowed_subset_mask,</span><br><span style="color: hsl(120, 100%, 40%);">+                    acc_mgr->allowed_subset_mask_count,</span><br><span style="color: hsl(120, 100%, 40%);">+                        acc_mgr->len_allowed_adm, acc_mgr->len_allowed_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+           gsm_bts_set_system_infos(acc_mgr->bts);</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_timer_schedule(&acc_mgr->rotate_timer, acc_mgr->rotation_time_sec, 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%);">+void acc_mgr_init(struct acc_mgr *acc_mgr, struct gsm_bts *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        acc_mgr->bts = bts;</span><br><span style="color: hsl(120, 100%, 40%);">+        acc_mgr->len_allowed_adm = 10; /* Allow all by default */</span><br><span style="color: hsl(120, 100%, 40%);">+  acc_mgr->len_allowed_ramp = 10;</span><br><span style="color: hsl(120, 100%, 40%);">+    acc_mgr->rotation_time_sec = ACC_MGR_QUANTUM_DEFAULT;</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_timer_setup(&acc_mgr->rotate_timer, do_acc_rotate_step, acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: Don't update SI yet, avoid crash due to bts->model being NULL */</span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_gen_subset(acc_mgr, 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%);">+uint8_t acc_mgr_get_len_allowed_adm(struct acc_mgr *acc_mgr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return acc_mgr->len_allowed_adm;</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%);">+uint8_t acc_mgr_get_len_allowed_ramp(struct acc_mgr *acc_mgr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    return acc_mgr->len_allowed_ramp;</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%);">+void acc_mgr_set_len_allowed_adm(struct acc_mgr *acc_mgr, uint8_t len_allowed_adm)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t old_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (acc_mgr->len_allowed_adm == len_allowed_adm)</span><br><span style="color: hsl(120, 100%, 40%);">+           return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     LOG_BTS(acc_mgr->bts, DRSL, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+            "ACC: administrative rotate subset size set to %" PRIu8 "\n", len_allowed_adm);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ old_len = acc_mgr_subset_len(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+        acc_mgr->len_allowed_adm = len_allowed_adm;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (old_len != acc_mgr_subset_len(acc_mgr))</span><br><span style="color: hsl(120, 100%, 40%);">+           acc_mgr_subset_length_changed(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+void acc_mgr_set_len_allowed_ramp(struct acc_mgr *acc_mgr, uint8_t len_allowed_ramp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t old_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (acc_mgr->len_allowed_ramp == len_allowed_ramp)</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     LOG_BTS(acc_mgr->bts, DRSL, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+            "ACC: ramping rotate subset size set to %" PRIu8 "\n", len_allowed_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       old_len = acc_mgr_subset_len(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+        acc_mgr->len_allowed_ramp = len_allowed_ramp;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (old_len != acc_mgr_subset_len(acc_mgr))</span><br><span style="color: hsl(120, 100%, 40%);">+           acc_mgr_subset_length_changed(acc_mgr);</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%);">+void acc_mgr_set_rotation_time(struct acc_mgr *acc_mgr, uint32_t rotation_time_sec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  LOG_BTS(acc_mgr->bts, DRSL, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+            "ACC: rotate subset time set to  %" PRIu32 "\n", rotation_time_sec);</span><br><span style="color: hsl(120, 100%, 40%);">+      acc_mgr->rotation_time_sec = rotation_time_sec;</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%);">+void acc_mgr_perm_subset_changed(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Even if amount is the same, the allowed/barred ones may have changed,</span><br><span style="color: hsl(120, 100%, 40%);">+       * so let's retrigger generation of an entire subset rather than</span><br><span style="color: hsl(120, 100%, 40%);">+   * rotating it */</span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_gen_subset(acc_mgr, true);</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%);">+ * Potentially mark certain Access Control Classes (ACCs) as barred in accordance to ACC policy.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] acc_mgr Pointer to acc_mgr structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] rach_control RACH control parameters in which barred ACCs will be configured.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void acc_mgr_apply_acc(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    rach_control->t2 |= acc_mgr_get_barred_t2(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+        rach_control->t3 |= acc_mgr_get_barred_t3(acc_mgr);</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%);">+//////////////////////////</span><br><span style="color: hsl(120, 100%, 40%);">+// acc_ramp</span><br><span style="color: hsl(120, 100%, 40%);">+//////////////////////////</span><br><span> static unsigned int get_next_step_interval(struct acc_ramp *acc_ramp)</span><br><span> {</span><br><span>     struct gsm_bts *bts = acc_ramp->bts;</span><br><span>@@ -104,42 +340,14 @@</span><br><span> static void do_acc_ramping_step(void *data)</span><br><span> {</span><br><span>  struct acc_ramp *acc_ramp = data;</span><br><span style="color: hsl(0, 100%, 40%);">-       int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct acc_mgr *acc_mgr = &acc_ramp->bts->acc_mgr;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t old_len = acc_mgr_get_len_allowed_ramp(acc_mgr);</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t new_len = OSMO_MIN(10, old_len + acc_ramp->step_size);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Shortcut in case we only do one ramping step. */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (acc_ramp->step_size == ACC_RAMP_STEP_SIZE_MAX) {</span><br><span style="color: hsl(0, 100%, 40%);">-         allow_all_accs(acc_ramp);</span><br><span style="color: hsl(0, 100%, 40%);">-               gsm_bts_set_system_infos(acc_ramp->bts);</span><br><span style="color: hsl(0, 100%, 40%);">-             return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Allow 'step_size' ACCs, starting from ACC0. ACC9 will be allowed last. */</span><br><span style="color: hsl(0, 100%, 40%);">-    for (i = 0; i < acc_ramp->step_size; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               int idx = ffs(acc_ramp_get_barred_t3(acc_ramp));</span><br><span style="color: hsl(0, 100%, 40%);">-                if (idx > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       /* One of ACC0-ACC7 is still bared. */</span><br><span style="color: hsl(0, 100%, 40%);">-                  unsigned int acc = idx - 1;</span><br><span style="color: hsl(0, 100%, 40%);">-                     if (!acc_is_permanently_barred(acc_ramp->bts, acc))</span><br><span style="color: hsl(0, 100%, 40%);">-                          allow_one_acc(acc_ramp, acc);</span><br><span style="color: hsl(0, 100%, 40%);">-           } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        idx = ffs(acc_ramp_get_barred_t2(acc_ramp));</span><br><span style="color: hsl(0, 100%, 40%);">-                    if (idx == 1 || idx == 2) {</span><br><span style="color: hsl(0, 100%, 40%);">-                             /* ACC8 or ACC9 is still barred. */</span><br><span style="color: hsl(0, 100%, 40%);">-                             unsigned int acc = idx - 1 + 8;</span><br><span style="color: hsl(0, 100%, 40%);">-                         if (!acc_is_permanently_barred(acc_ramp->bts, acc))</span><br><span style="color: hsl(0, 100%, 40%);">-                                  allow_one_acc(acc_ramp, acc);</span><br><span style="color: hsl(0, 100%, 40%);">-                   } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                /* All ACCs are now allowed. */</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%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       gsm_bts_set_system_infos(acc_ramp->bts);</span><br><span style="color: hsl(120, 100%, 40%);">+   acc_mgr_set_len_allowed_ramp(acc_mgr, new_len);</span><br><span> </span><br><span>  /* If we have not allowed all ACCs yet, schedule another ramping step. */</span><br><span style="color: hsl(0, 100%, 40%);">-       if (acc_ramp_get_barred_t2(acc_ramp) != 0x00 ||</span><br><span style="color: hsl(0, 100%, 40%);">-     acc_ramp_get_barred_t3(acc_ramp) != 0x00)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (new_len != 10)</span><br><span>           osmo_timer_schedule(&acc_ramp->step_timer, get_next_step_interval(acc_ramp), 0);</span><br><span> }</span><br><span> </span><br><span>@@ -279,7 +487,6 @@</span><br><span>       acc_ramp->step_size = ACC_RAMP_STEP_SIZE_DEFAULT;</span><br><span>         acc_ramp->step_interval_sec = ACC_RAMP_STEP_INTERVAL_MIN;</span><br><span>         acc_ramp->step_interval_is_fixed = false;</span><br><span style="color: hsl(0, 100%, 40%);">-    allow_all_accs(acc_ramp);</span><br><span>    osmo_timer_setup(&acc_ramp->step_timer, do_acc_ramping_step, acc_ramp);</span><br><span>       osmo_signal_register_handler(SS_NM, acc_ramp_nm_sig_cb, acc_ramp);</span><br><span> }</span><br><span>@@ -344,7 +551,7 @@</span><br><span> </span><br><span>    if (acc_ramp_is_enabled(acc_ramp)) {</span><br><span>                 /* Set all available ACCs to barred and start ramping up. */</span><br><span style="color: hsl(0, 100%, 40%);">-            barr_all_accs(acc_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+              acc_mgr_set_len_allowed_ramp(&acc_ramp->bts->acc_mgr, 0);</span><br><span>          do_acc_ramping_step(acc_ramp);</span><br><span>       }</span><br><span> }</span><br><span>@@ -358,5 +565,5 @@</span><br><span>         if (osmo_timer_pending(&acc_ramp->step_timer))</span><br><span>                osmo_timer_del(&acc_ramp->step_timer);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       allow_all_accs(acc_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_set_len_allowed_ramp(&acc_ramp->bts->acc_mgr, 10);</span><br><span> }</span><br><span>diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c</span><br><span>index 11e51be..2afb8f6 100644</span><br><span>--- a/src/osmo-bsc/bsc_vty.c</span><br><span>+++ b/src/osmo-bsc/bsc_vty.c</span><br><span>@@ -404,6 +404,8 @@</span><br><span>                 VTY_NEWLINE);</span><br><span>        vty_out(vty, "  Cell Reselection Hysteresis: %u dBm%s",</span><br><span>            bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+       vty_out(vty, "  Access Control Class rotation allow mask: 0x%" PRIx16 "%s",</span><br><span style="color: hsl(120, 100%, 40%);">+               bts->acc_mgr.allowed_subset_mask, VTY_NEWLINE);</span><br><span>   vty_out(vty, "  Access Control Class ramping: %senabled%s",</span><br><span>                acc_ramp_is_enabled(&bts->acc_ramp) ? "" : "not ", VTY_NEWLINE);</span><br><span>  if (acc_ramp_is_enabled(&bts->acc_ramp)) {</span><br><span>@@ -948,6 +950,10 @@</span><br><span>             for (i = 0; i < 8; i++)</span><br><span>                   if ((i != 2) && (bts->si_common.rach_control.t2 & (0x1 << i)))</span><br><span>                          vty_out(vty, "  rach access-control-class %d barred%s", i+8, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (bts->acc_mgr.len_allowed_adm < 10)</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "  access-control-class-rotate %" PRIu8 "%s", bts->acc_mgr.len_allowed_adm, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bts->acc_mgr.rotation_time_sec != ACC_MGR_QUANTUM_DEFAULT)</span><br><span style="color: hsl(120, 100%, 40%);">+             vty_out(vty, "  access-control-class-rotate-quantum %" PRIu32 "%s", bts->acc_mgr.rotation_time_sec, VTY_NEWLINE);</span><br><span>     vty_out(vty, "  %saccess-control-class-ramping%s", acc_ramp_is_enabled(&bts->acc_ramp) ? "" : "no ", VTY_NEWLINE);</span><br><span>      if (!acc_ramp_step_interval_is_dynamic(&bts->acc_ramp)) {</span><br><span>             vty_out(vty, "  access-control-class-ramping-step-interval %u%s",</span><br><span>@@ -2745,6 +2751,9 @@</span><br><span>          else</span><br><span>                         bts->si_common.rach_control.t2 |= (0x1 << (control_class - 8));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  if (control_class < 10)</span><br><span style="color: hsl(120, 100%, 40%);">+            acc_mgr_perm_subset_changed(&bts->acc_mgr, &bts->si_common.rach_control);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    return CMD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span>@@ -3640,6 +3649,30 @@</span><br><span>        return CMD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(cfg_bts_acc_rotate,</span><br><span style="color: hsl(120, 100%, 40%);">+      cfg_bts_acc_rotate_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "access-control-rotate <0-10>",</span><br><span style="color: hsl(120, 100%, 40%);">+      "Enable Access Control Class allowed subset rotation\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "Size of the rotating allowed ACC 0-9 subset (default=10, no subset)\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_bts *bts = vty->index;</span><br><span style="color: hsl(120, 100%, 40%);">+  int len_allowed_adm = atoi(argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+  acc_mgr_set_len_allowed_adm(&bts->acc_mgr, len_allowed_adm);</span><br><span style="color: hsl(120, 100%, 40%);">+   return CMD_SUCCESS;</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%);">+DEFUN(cfg_bts_acc_rotate_quantum,</span><br><span style="color: hsl(120, 100%, 40%);">+      cfg_bts_acc_rotate_quantum_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "access-control-rotate-quantum <1-65535>",</span><br><span style="color: hsl(120, 100%, 40%);">+      "Time between rotation of ACC 0-9 generated subsets\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "Time in seconds (default=" OSMO_STRINGIFY_VAL(ACC_MGR_QUANTUM_DEFAULT) ")\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm_bts *bts = vty->index;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t rotation_time_sec = (uint32_t)atoi(argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ acc_mgr_set_rotation_time(&bts->acc_mgr, rotation_time_sec);</span><br><span style="color: hsl(120, 100%, 40%);">+   return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> DEFUN(cfg_bts_acc_ramping,</span><br><span>       cfg_bts_acc_ramping_cmd,</span><br><span>       "access-control-class-ramping",</span><br><span>@@ -6493,6 +6526,8 @@</span><br><span>  install_element(BTS_NODE, &cfg_bts_amr_hr_hyst3_cmd);</span><br><span>    install_element(BTS_NODE, &cfg_bts_amr_hr_start_mode_cmd);</span><br><span>       install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ install_element(BTS_NODE, &cfg_bts_acc_rotate_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+       install_element(BTS_NODE, &cfg_bts_acc_rotate_quantum_cmd);</span><br><span>      install_element(BTS_NODE, &cfg_bts_acc_ramping_cmd);</span><br><span>     install_element(BTS_NODE, &cfg_bts_no_acc_ramping_cmd);</span><br><span>  install_element(BTS_NODE, &cfg_bts_acc_ramping_step_interval_cmd);</span><br><span>diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c</span><br><span>index 7794024..4318b7e 100644</span><br><span>--- a/src/osmo-bsc/bts.c</span><br><span>+++ b/src/osmo-bsc/bts.c</span><br><span>@@ -387,6 +387,7 @@</span><br><span>    bts_init_cbch_state(&bts->cbch_basic, bts);</span><br><span>   bts_init_cbch_state(&bts->cbch_extended, bts);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_init(&bts->acc_mgr, bts);</span><br><span>     acc_ramp_init(&bts->acc_ramp, bts);</span><br><span> </span><br><span>       return bts;</span><br><span>diff --git a/src/osmo-bsc/system_information.c b/src/osmo-bsc/system_information.c</span><br><span>index 13d0f46..be70600 100644</span><br><span>--- a/src/osmo-bsc/system_information.c</span><br><span>+++ b/src/osmo-bsc/system_information.c</span><br><span>@@ -723,8 +723,7 @@</span><br><span>   list_arfcn(si1->cell_channel_description, 0xce, "Serving cell:");</span><br><span> </span><br><span>   si1->rach_control = bts->si_common.rach_control;</span><br><span style="color: hsl(0, 100%, 40%);">-  if (acc_ramp_is_enabled(&bts->acc_ramp))</span><br><span style="color: hsl(0, 100%, 40%);">-         acc_ramp_apply(&si1->rach_control, &bts->acc_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_apply_acc(&bts->acc_mgr, &si1->rach_control);</span><br><span> </span><br><span>      /*</span><br><span>    * SI1 Rest Octets (10.5.2.32), contains NCH position and band</span><br><span>@@ -755,8 +754,7 @@</span><br><span> </span><br><span>     si2->ncc_permitted = bts->si_common.ncc_permitted;</span><br><span>     si2->rach_control = bts->si_common.rach_control;</span><br><span style="color: hsl(0, 100%, 40%);">-  if (acc_ramp_is_enabled(&bts->acc_ramp))</span><br><span style="color: hsl(0, 100%, 40%);">-         acc_ramp_apply(&si2->rach_control, &bts->acc_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_apply_acc(&bts->acc_mgr, &si2->rach_control);</span><br><span> </span><br><span>      return sizeof(*si2);</span><br><span> }</span><br><span>@@ -790,8 +788,7 @@</span><br><span>              bts->si_valid &= ~(1 << SYSINFO_TYPE_2bis);</span><br><span> </span><br><span>         si2b->rach_control = bts->si_common.rach_control;</span><br><span style="color: hsl(0, 100%, 40%);">- if (acc_ramp_is_enabled(&bts->acc_ramp))</span><br><span style="color: hsl(0, 100%, 40%);">-         acc_ramp_apply(&si2b->rach_control, &bts->acc_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+    acc_mgr_apply_acc(&bts->acc_mgr, &si2b->rach_control);</span><br><span> </span><br><span>     /* SI2bis Rest Octets as per 3GPP TS 44.018 ยง10.5.2.33 */</span><br><span>   rc = rest_octets_si2bis(si2b->rest_octets);</span><br><span>@@ -912,8 +909,7 @@</span><br><span>         si3->cell_options = bts->si_common.cell_options;</span><br><span>       si3->cell_sel_par = bts->si_common.cell_sel_par;</span><br><span>       si3->rach_control = bts->si_common.rach_control;</span><br><span style="color: hsl(0, 100%, 40%);">-  if (acc_ramp_is_enabled(&bts->acc_ramp))</span><br><span style="color: hsl(0, 100%, 40%);">-         acc_ramp_apply(&si3->rach_control, &bts->acc_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_apply_acc(&bts->acc_mgr, &si3->rach_control);</span><br><span> </span><br><span>      /* allow/disallow DTXu */</span><br><span>    gsm48_set_dtx(&si3->cell_options, bts->dtxu, bts->dtxu, true);</span><br><span>@@ -962,8 +958,7 @@</span><br><span>    gsm48_generate_lai2(&si4->lai, bts_lai(bts));</span><br><span>         si4->cell_sel_par = bts->si_common.cell_sel_par;</span><br><span>       si4->rach_control = bts->si_common.rach_control;</span><br><span style="color: hsl(0, 100%, 40%);">-  if (acc_ramp_is_enabled(&bts->acc_ramp))</span><br><span style="color: hsl(0, 100%, 40%);">-         acc_ramp_apply(&si4->rach_control, &bts->acc_ramp);</span><br><span style="color: hsl(120, 100%, 40%);">+     acc_mgr_apply_acc(&bts->acc_mgr, &si4->rach_control);</span><br><span> </span><br><span>      /* Optional: CBCH Channel Description + CBCH Mobile Allocation */</span><br><span>    cbch_lchan = gsm_bts_get_cbch(bts);</span><br><span>diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c</span><br><span>index e53b83a..35531f8 100644</span><br><span>--- a/tests/gsm0408/gsm0408_test.c</span><br><span>+++ b/tests/gsm0408/gsm0408_test.c</span><br><span>@@ -140,6 +140,8 @@</span><br><span> {</span><br><span>  osmo_stat_item_group_free(bts->bts_statg);</span><br><span>        rate_ctr_group_free(bts->bts_ctrs);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (osmo_timer_pending(&bts->acc_mgr.rotate_timer))</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_timer_del(&bts->acc_mgr.rotate_timer);</span><br><span>   /* no need to llist_del(&bts->list), we never registered the bts there. */</span><br><span>    talloc_free(bts);</span><br><span>    printf("BTS deallocated OK in %s()\n", msg);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/19303">change 19303</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-bsc/+/19303"/><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-Change-Id: I952c9eeae02809c7184078c655574ec817902e06 </div>
<div style="display:none"> Gerrit-Change-Number: 19303 </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>