From deaa6fd624903c60a6d83bd02b430376203dcee8 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 16 Jul 2020 20:53:21 +0200 Subject: Introduce support for ACC subset rotation See updated documentation section in manuals/chapters/bts.adoc regarding an explanation on how the system works. Related: SYS#4911 Change-Id: I952c9eeae02809c7184078c655574ec817902e06 --- configure.ac | 1 + doc/manuals/chapters/bts.adoc | 77 ++++- include/osmocom/bsc/acc.h | 72 +++-- include/osmocom/bsc/bts.h | 1 + src/osmo-bsc/acc.c | 366 ++++++++++++++++++---- src/osmo-bsc/bsc_vty.c | 35 +++ src/osmo-bsc/bts.c | 1 + src/osmo-bsc/system_information.c | 15 +- tests/Makefile.am | 1 + tests/acc/Makefile.am | 37 +++ tests/acc/acc_test.c | 493 ++++++++++++++++++++++++++++++ tests/acc/acc_test.ok | 620 ++++++++++++++++++++++++++++++++++++++ tests/gsm0408/gsm0408_test.c | 2 + tests/testsuite.at | 6 + 14 files changed, 1610 insertions(+), 117 deletions(-) create mode 100644 tests/acc/Makefile.am create mode 100644 tests/acc/acc_test.c create mode 100644 tests/acc/acc_test.ok diff --git a/configure.ac b/configure.ac index d25925b41..4a5807985 100644 --- a/configure.ac +++ b/configure.ac @@ -241,6 +241,7 @@ AC_OUTPUT( src/utils/Makefile tests/Makefile tests/atlocal + tests/acc/Makefile tests/gsm0408/Makefile tests/bsc/Makefile tests/codec_pref/Makefile diff --git a/doc/manuals/chapters/bts.adoc b/doc/manuals/chapters/bts.adoc index 94e89a41c..6e7a308c7 100644 --- a/doc/manuals/chapters/bts.adoc +++ b/doc/manuals/chapters/bts.adoc @@ -416,17 +416,28 @@ have to deal with an increased load due to duplicate RACH requests. However, in order to minimize the delay when a RACH request or response gets lost the MS should not wait too long before retransmitting. -==== Load Management +==== Access Control Class Load Management -Every SIM card is member of one of the ten regular ACCs (0-9). Access to the -BTS can be restricted to SIMs that are members of certain ACCs. +Every SIM card is member of one of the ten regular ACCs (0-9). Access to the BTS +can be restricted to SIMs that are members of certain ACCs. -Since the ACCs are distributed uniformly across all SIMs allowing only ACCs -0-4 to connect to the BTS should reduce its load by 50%. +Furthermore, high priority users (such as PLMN staff, public or emergency +services, etc.) may be members of one or more ACCs from 11-15. + +Since the ACCs 0-9 are distributed uniformly across all SIMs, for instance +allowing only ACCs 0-4 to connect to the BTS should reduce its load by 50% at +the expense of not serving 50% of the subscribers. The default is to allow all ACCs to connect. -.Example: Restrict access to the BTS by ACC +OsmoBSC supports several levels of ACC management to allow or restrict access +either permanently or temporarily on each BTS. + +The first level of management consists of an access list to flag specific ACCs +as permanently barred (the list can be updated at any time through VTY as seen +below). As indicated above, the default is to allow all ACCs (0-15). + +.Example: Restrict permanent access to the BTS by ACC ---- network bts 0 @@ -436,12 +447,33 @@ network <1> Disallow SIMs with access-class 1 from connecting to the BTS <2> Permit SIMs with access-class 9 to connect to the BTS. +On really crowded areas, a BTS may struggle to service all mobile stations +willing to use it, and which may end up in collapse. In this kind of scenarios +it is a good idea to temporarily further restrict the amount of allowed ACCs +(hence restrict the amount of subscribers allowed to reach the BTS). +However, doing so on a permanent basis would be unfair to subscribers from +barred ACCs. Hence, OsmoBSC can be configured to temporarily generate ACC +subsets of the permanent set presented above, and rotate them over time to allow +fair access to all subscribers. This feature is only aimed at ACCs 0-9, +since ACCs 11-15 are considered high priority and hence are always configured +based on permanent list policy. + +.Example: Configure rotative access to the BTS +---- +network + bts 0 + access-control-rotate 3 <1> + access-control-rotate-quantum 20 <2> +---- +<1> Only allow up to 3 concurrent allowed ACCs from the permanent list +<2> Rotate the generated permanent list subsets every 20 seconds in a fair fashion -Smaller cells with lots of subscribers can be overwhelmed with traffic after -the network is turned on. This is especially true in areas with little to no -reception from other networks. To manage the load OsmoBSC has an option to -enable one Access Class at a time so initial access to the network is -distributed across a longer time. +Furthermore, cells with large number of subscribers and limited overlapping +coverage may become overwhelmed with traffic after the cell starts brodacasting. +This is especially true in areas with little to no reception from other +networks. To manage the load, OsmoBSC has an option to further restrict the +rotating ACC subset during startup and slowly increment it over time and taking +current load into account. .Example: Ramp up access to the BTS after startup ---- @@ -456,6 +488,29 @@ network <3> At each step enable one more ACC +Here a full example of all the mechanisms combined can be found: + +.Example: Full ACC Load Management config setup +---- +bts 0 + rach access-control-class 5 barred <1> + rach access-control-class 6 barred + rach access-control-class 7 barred + rach access-control-class 8 barred + rach access-control-class 9 barred + access-control-class-rotate 3 <2> + access-control-class-rotate-quantum 20 <3> + access-control-class-ramping <4> + access-control-class-ramping-step-size 1 <5> + access-control-class-ramping-step-interval dynamic <6> +---- +<1> ACCs 5-9 are administratively barred, ie they will never be used until somebody manually enables them in VTY config +<2> Allow access through temporary subsets of len=3 from ACC set 0-4: (0,1,2) -> (1,2,3) -> (2,3,4) -> (3,4,0), etc. +<3> Each subset iteration will happen every 20 seconds +<4> During startup since ramping is enabled, it will further restrict the rotate subset size parameter (len=3) +<5> The rotate subset size parameter will be increased one ACC slot at a time: len=0 -> len=1 -> len=2 -> len=3 +<6> The time until the subset size is further increased will be calculated based on current channel load + ==== RACH Parameter Configuration The following parameters allow control over how the MS can access the random diff --git a/include/osmocom/bsc/acc.h b/include/osmocom/bsc/acc.h index 31fc74fbd..bd75f9599 100644 --- a/include/osmocom/bsc/acc.h +++ b/include/osmocom/bsc/acc.h @@ -27,6 +27,40 @@ #include #include +#define ACC_MGR_QUANTUM_DEFAULT 20 /* 20 seconds */ + +/* Manage rotating subset of allowed Access Class as per configuration */ +struct acc_mgr { + struct gsm_bts *bts; /*!< backpointer to BTS using this ACC manager */ + /* Administrative Maximum Number of ACC 0-9 to be allowed at the same time. + Configurable through VTY cmd "access-control-class-roundrobin", + defaults to all allowed (10) */ + uint8_t len_allowed_adm; + /* Further limiting the number of ACC to use. It may be lower due + to ramping, based for instance on channel or system load. */ + uint8_t len_allowed_ramp; + + /* Time until next subset is generated */ + uint32_t rotation_time_sec; + struct osmo_timer_list rotate_timer; + + /* Bitmask containing subset of allowed ACC 0-9 on current rotation iteration */ + uint16_t allowed_subset_mask; + /* Number of bits (ACC) set in allowed_subset_mask: 0->min(len_allowed_ramp, len_allowed_adm) */ + uint8_t allowed_subset_mask_count; + /* Number of ACC 0-9 allowed as per adminsitrative (permanent) config. */ + uint8_t allowed_permanent_count; +}; + +void acc_mgr_init(struct acc_mgr *acc_mgr, struct gsm_bts *bts); +uint8_t acc_mgr_get_len_allowed_adm(struct acc_mgr *acc_mgr); +uint8_t acc_mgr_get_len_allowed_ramp(struct acc_mgr *acc_mgr); +void acc_mgr_set_len_allowed_adm(struct acc_mgr *acc_mgr, uint8_t len_allowed_adm); +void acc_mgr_set_len_allowed_ramp(struct acc_mgr *acc_mgr, uint8_t len_allowed_ramp); +void acc_mgr_set_rotation_time(struct acc_mgr *acc_mgr, uint32_t rotation_time_sec); +void acc_mgr_perm_subset_changed(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control); +void acc_mgr_apply_acc(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control); + /*! * Access control class (ACC) ramping is used to slowly make the cell available to * an increasing number of MS. This avoids overload at startup time in cases where @@ -49,17 +83,6 @@ struct acc_ramp { bool acc_ramping_enabled; /*!< whether ACC ramping is enabled */ - /*! - * Bitmask which keeps track of access control classes that are currently denied - * access. The function acc_ramp_apply() uses this mask to modulate bits from - * octets 2 and 3 in RACH Control Parameters (see 3GPP 44.018 10.5.2.29). - * Ramping is only concerned with ACCs 0-9. While any of the bits 0-9 is set, - * the corresponding ACC is barred. - * ACCs 11-15 should always be allowed, and ACC 10 denies emergency calls for - * all ACCs from 0-9 inclusive; these ACCs are ignored in this implementation. - */ - uint16_t barred_accs; - /*! * This controls the maximum number of ACCs to allow per ramping step (1 - 10). * The compile-time default value is ACC_RAMP_STEP_SIZE_DEFAULT. @@ -126,33 +149,6 @@ static inline bool acc_ramp_step_interval_is_dynamic(struct acc_ramp *acc_ramp) return !(acc_ramp->step_interval_is_fixed); } -/*! - * Return bitmasks which correspond to access control classes that are currently - * denied access. Ramping is only concerned with those bits which control access - * for ACCs 0-9, and any of the other bits will always be set to zero in these masks, i.e. - * it is safe to OR these bitmasks with the corresponding fields in struct gsm48_rach_control. - * \param[in] acc_ramp Pointer to acc_ramp structure. - */ -static inline uint8_t acc_ramp_get_barred_t2(struct acc_ramp *acc_ramp) -{ - return ((acc_ramp->barred_accs >> 8) & 0x03); -}; -static inline uint8_t acc_ramp_get_barred_t3(struct acc_ramp *acc_ramp) -{ - return (acc_ramp->barred_accs & 0xff); -} - -/*! - * Potentially mark certain Access Control Classes (ACCs) as barred in accordance to ACC ramping. - * \param[in] rach_control RACH control parameters in which barred ACCs will be configured. - * \param[in] acc_ramp Pointer to acc_ramp structure. - */ -static inline void acc_ramp_apply(struct gsm48_rach_control *rach_control, struct acc_ramp *acc_ramp) -{ - rach_control->t2 |= acc_ramp_get_barred_t2(acc_ramp); - rach_control->t3 |= acc_ramp_get_barred_t3(acc_ramp); -} - void acc_ramp_init(struct acc_ramp *acc_ramp, struct gsm_bts *bts); int acc_ramp_set_step_size(struct acc_ramp *acc_ramp, unsigned int step_size); int acc_ramp_set_step_interval(struct acc_ramp *acc_ramp, unsigned int step_interval); diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h index 730dee9e0..16053a3bb 100644 --- a/include/osmocom/bsc/bts.h +++ b/include/osmocom/bsc/bts.h @@ -449,6 +449,7 @@ struct gsm_bts { uint32_t si_mode_static; /* access control class ramping */ + struct acc_mgr acc_mgr; struct acc_ramp acc_ramp; /* exclude the BTS from the global RF Lock handling */ diff --git a/src/osmo-bsc/acc.c b/src/osmo-bsc/acc.c index a1941e42e..b25f2fdc3 100644 --- a/src/osmo-bsc/acc.c +++ b/src/osmo-bsc/acc.c @@ -1,4 +1,4 @@ -/* (C) 2018 by sysmocom s.f.m.c. GmbH +/* (C) 2018-2020 by sysmocom s.f.m.c. GmbH * * Author: Stefan Sperling * @@ -20,6 +20,8 @@ */ #include +#include +#include #include #include @@ -43,42 +45,319 @@ static bool acc_is_permanently_barred(struct gsm_bts *bts, unsigned int acc) return (bts->si_common.rach_control.t3 & (1 << (acc))); } -static void allow_one_acc(struct acc_ramp *acc_ramp, unsigned int acc) +/*! + * Return bitmasks which correspond to access control classes that are currently + * denied access. Ramping is only concerned with those bits which control access + * for ACCs 0-9, and any of the other bits will always be set to zero in these masks, i.e. + * it is safe to OR these bitmasks with the corresponding fields in struct gsm48_rach_control. + * \param[in] acc_mgr Pointer to acc_mgr structure. + */ +static inline uint8_t acc_mgr_get_barred_t2(struct acc_mgr *acc_mgr) { - OSMO_ASSERT(acc <= 9); - if (acc_ramp->barred_accs & (1 << acc)) - LOG_BTS(acc_ramp->bts, DRSL, LOGL_NOTICE, - "ACC RAMP: allowing Access Control Class %u\n", acc); - acc_ramp->barred_accs &= ~(1 << acc); + return ((~acc_mgr->allowed_subset_mask) >> 8) & 0x03; +}; +static inline uint8_t acc_mgr_get_barred_t3(struct acc_mgr *acc_mgr) +{ + return (~acc_mgr->allowed_subset_mask) & 0xff; } -static void barr_one_acc(struct acc_ramp *acc_ramp, unsigned int acc) +static uint8_t acc_mgr_subset_len(struct acc_mgr *acc_mgr) { - OSMO_ASSERT(acc <= 9); - if ((acc_ramp->barred_accs & (1 << acc)) == 0) - LOG_BTS(acc_ramp->bts, DRSL, LOGL_NOTICE, - "ACC RAMP: barring Access Control Class %u\n", acc); - acc_ramp->barred_accs |= (1 << acc); + return OSMO_MIN(acc_mgr->len_allowed_ramp, acc_mgr->len_allowed_adm); } -static void barr_all_accs(struct acc_ramp *acc_ramp) +static void acc_mgr_enable_rotation_cond(struct acc_mgr *acc_mgr) { - unsigned int acc; - for (acc = 0; acc < 10; acc++) { - if (!acc_is_permanently_barred(acc_ramp->bts, acc)) - barr_one_acc(acc_ramp, acc); + if (acc_mgr->allowed_permanent_count && acc_mgr->allowed_subset_mask_count && + acc_mgr->allowed_permanent_count != acc_mgr->allowed_subset_mask_count) { + if (!osmo_timer_pending(&acc_mgr->rotate_timer)) + osmo_timer_schedule(&acc_mgr->rotate_timer, acc_mgr->rotation_time_sec, 0); + } else { + /* No rotation needed, disable rotation timer */ + if (osmo_timer_pending(&acc_mgr->rotate_timer)) + osmo_timer_del(&acc_mgr->rotate_timer); } } -static void allow_all_accs(struct acc_ramp *acc_ramp) +static void acc_mgr_gen_subset(struct acc_mgr *acc_mgr, bool update_si) { - unsigned int acc; + uint8_t acc; + + acc_mgr->allowed_subset_mask = 0; /* clean mask */ + acc_mgr->allowed_subset_mask_count = 0; + acc_mgr->allowed_permanent_count = 0; + for (acc = 0; acc < 10; acc++) { - if (!acc_is_permanently_barred(acc_ramp->bts, acc)) - allow_one_acc(acc_ramp, acc); + if (acc_is_permanently_barred(acc_mgr->bts, acc)) + continue; + acc_mgr->allowed_permanent_count++; + if (acc_mgr->allowed_subset_mask_count < acc_mgr_subset_len(acc_mgr)) { + acc_mgr->allowed_subset_mask |= (1 << acc); + acc_mgr->allowed_subset_mask_count++; + } + } + + acc_mgr_enable_rotation_cond(acc_mgr); + + LOG_BTS(acc_mgr->bts, DRSL, LOGL_INFO, + "ACC: New ACC allowed subset 0x%03" PRIx16 " (active_len=%" PRIu8 + ", ramp_len=%" PRIu8 ", adm_len=%" PRIu8 ", perm_len=%" PRIu8 ", rotation=%s)\n", + acc_mgr->allowed_subset_mask, acc_mgr->allowed_subset_mask_count, + acc_mgr->len_allowed_ramp, acc_mgr->len_allowed_adm, + acc_mgr->allowed_permanent_count, + osmo_timer_pending(&(acc_mgr)->rotate_timer) ? "on" : "off"); + + /* Trigger SI data update, acc_mgr_apply_acc will bew called */ + if (update_si) + gsm_bts_set_system_infos(acc_mgr->bts); +} + +static uint8_t get_highest_allowed_acc(uint16_t mask) +{ + for (int i = 9; i >= 0; i--) { + if (mask & (1 << i)) + return i; + } + OSMO_ASSERT(0); + return 0; +} + +static uint8_t get_lowest_allowed_acc(uint16_t mask) +{ + for (int i = 0; i < 10; i++) { + if (mask & (1 << i)) + return i; + } + OSMO_ASSERT(0); + return 0; +} + +#define LOG_ACC_CHG(acc_mgr, level, old_mask, verb_str) \ + LOG_BTS((acc_mgr)->bts, DRSL, level, \ + "ACC: %s ACC allowed active subset 0x%03" PRIx16 " -> 0x%03" PRIx16 \ + " (active_len=%" PRIu8 ", ramp_len=%" PRIu8 ", adm_len=%" PRIu8 \ + ", perm_len=%" PRIu8 ", rotation=%s)\n", \ + verb_str, old_mask, (acc_mgr)->allowed_subset_mask, \ + (acc_mgr)->allowed_subset_mask_count, \ + (acc_mgr)->len_allowed_ramp, (acc_mgr)->len_allowed_adm, \ + (acc_mgr)->allowed_permanent_count, \ + osmo_timer_pending(&(acc_mgr)->rotate_timer) ? "on" : "off") + +/* Call when either adm_len or ramp_len changed (and values have been updated) */ +static void acc_mgr_subset_length_changed(struct acc_mgr *acc_mgr) +{ + uint16_t old_mask = acc_mgr->allowed_subset_mask; + uint8_t curr_len = acc_mgr->allowed_subset_mask_count; + uint8_t new_len = acc_mgr_subset_len(acc_mgr); + int8_t diff = new_len - curr_len; + uint8_t i; + + if (curr_len == new_len) + return; + + if (new_len == 0) { + acc_mgr->allowed_subset_mask = 0; + acc_mgr->allowed_subset_mask_count = 0; + acc_mgr_enable_rotation_cond(acc_mgr); + LOG_ACC_CHG(acc_mgr, LOGL_INFO, old_mask, "update"); + gsm_bts_set_system_infos(acc_mgr->bts); + return; + } + + if (curr_len == 0) { + acc_mgr_gen_subset(acc_mgr, true); + return; + } + + /* Try to add new ACCs to the set starting from highest one (since we rotate rolling up) */ + if (diff > 0) { /* curr_len < new_len */ + uint8_t highest = get_highest_allowed_acc(acc_mgr->allowed_subset_mask); + /* It's fine skipping highest in the loop since it's known to be already set: */ + for (i = (highest + 1) % 10; i != highest; i = (i + 1) % 10) { + if (acc_is_permanently_barred(acc_mgr->bts, i)) + continue; + if (acc_mgr->allowed_subset_mask & (1 << i)) + continue; /* already in set */ + acc_mgr->allowed_subset_mask |= (1 << i); + acc_mgr->allowed_subset_mask_count++; + diff--; + if (diff == 0) + break; + } + } else { /* curr_len > new_len, try removing from lowest one. */ + uint8_t lowest = get_lowest_allowed_acc(acc_mgr->allowed_subset_mask); + i = lowest; + do { + if ((acc_mgr->allowed_subset_mask & (1 << i))) { + acc_mgr->allowed_subset_mask &= ~(1 << i); + acc_mgr->allowed_subset_mask_count--; + diff++; + if (diff == 0) + break; + } + i = (i + 1) % 10; + } while(i != lowest); + } + + acc_mgr_enable_rotation_cond(acc_mgr); + LOG_ACC_CHG(acc_mgr, LOGL_INFO, old_mask, "update"); + + /* if we updated the set, notify about it */ + if (curr_len != acc_mgr->allowed_subset_mask_count) + gsm_bts_set_system_infos(acc_mgr->bts); + +} + +/* Eg: (2,3,4) -> first=2; last=4. (3,7,8) -> first=3, last=8; (8,9,2) -> first=8, last=2 */ +void get_subset_limits(struct acc_mgr *acc_mgr, uint8_t *first, uint8_t *last) +{ + uint8_t lowest = get_lowest_allowed_acc(acc_mgr->allowed_subset_mask); + uint8_t highest = get_highest_allowed_acc(acc_mgr->allowed_subset_mask); + /* check if there's unselected ACCs between lowest and highest, that + * means subset is wrapping around, eg: (8,9,1) + * Assumption: The permanent set is bigger than the current selected subset */ + bool is_wrapped = false; + uint8_t i = (lowest + 1) % 10; + do { + if (!acc_is_permanently_barred(acc_mgr->bts, i) && + !(acc_mgr->allowed_subset_mask & (1 << i))) { + is_wrapped = true; + break; + } + i = (i + 1 ) % 10; + } while (i != (highest + 1) % 10); + + if (is_wrapped) { + *first = highest; + *last = lowest; + } else { + *first = lowest; + *last = highest; } } +static void do_acc_rotate_step(void *data) +{ + struct acc_mgr *acc_mgr = data; + uint8_t i; + uint8_t first, last; + uint16_t old_mask = acc_mgr->allowed_subset_mask; + + /* Assumption: The size of the subset didn't change, that's handled by + * acc_mgr_subset_length_changed() + */ + + /* Assumption: Rotation timer has been disabled if no ACC is allowed */ + OSMO_ASSERT(acc_mgr->allowed_subset_mask_count != 0); + + /* One ACC is rotated at a time: Drop first ACC and add next from last ACC */ + get_subset_limits(acc_mgr, &first, &last); + + acc_mgr->allowed_subset_mask &= ~(1 << first); + i = (last + 1) % 10; + do { + if (!acc_is_permanently_barred(acc_mgr->bts, i) && + !(acc_mgr->allowed_subset_mask & (1 << i))) { + /* found first one which can be allowed, do it and be done */ + acc_mgr->allowed_subset_mask |= (1 << i); + break; + } + i = (i + 1 ) % 10; + } while (i != (last + 1) % 10); + osmo_timer_schedule(&acc_mgr->rotate_timer, acc_mgr->rotation_time_sec, 0); + + if (old_mask != acc_mgr->allowed_subset_mask) { + LOG_ACC_CHG(acc_mgr, LOGL_INFO, old_mask, "rotate"); + gsm_bts_set_system_infos(acc_mgr->bts); + } +} + +void acc_mgr_init(struct acc_mgr *acc_mgr, struct gsm_bts *bts) +{ + acc_mgr->bts = bts; + acc_mgr->len_allowed_adm = 10; /* Allow all by default */ + acc_mgr->len_allowed_ramp = 10; + acc_mgr->rotation_time_sec = ACC_MGR_QUANTUM_DEFAULT; + osmo_timer_setup(&acc_mgr->rotate_timer, do_acc_rotate_step, acc_mgr); + /* FIXME: Don't update SI yet, avoid crash due to bts->model being NULL */ + acc_mgr_gen_subset(acc_mgr, false); +} + +uint8_t acc_mgr_get_len_allowed_adm(struct acc_mgr *acc_mgr) +{ + return acc_mgr->len_allowed_adm; +} + +uint8_t acc_mgr_get_len_allowed_ramp(struct acc_mgr *acc_mgr) +{ + return acc_mgr->len_allowed_ramp; +} + +void acc_mgr_set_len_allowed_adm(struct acc_mgr *acc_mgr, uint8_t len_allowed_adm) +{ + uint8_t old_len; + + OSMO_ASSERT(len_allowed_adm <= 10); + + if (acc_mgr->len_allowed_adm == len_allowed_adm) + return; + + LOG_BTS(acc_mgr->bts, DRSL, LOGL_DEBUG, + "ACC: administrative rotate subset size set to %" PRIu8 "\n", len_allowed_adm); + + old_len = acc_mgr_subset_len(acc_mgr); + acc_mgr->len_allowed_adm = len_allowed_adm; + if (old_len != acc_mgr_subset_len(acc_mgr)) + acc_mgr_subset_length_changed(acc_mgr); +} +void acc_mgr_set_len_allowed_ramp(struct acc_mgr *acc_mgr, uint8_t len_allowed_ramp) +{ + uint8_t old_len; + + OSMO_ASSERT(len_allowed_ramp <= 10); + + if (acc_mgr->len_allowed_ramp == len_allowed_ramp) + return; + + LOG_BTS(acc_mgr->bts, DRSL, LOGL_DEBUG, + "ACC: ramping rotate subset size set to %" PRIu8 "\n", len_allowed_ramp); + + old_len = acc_mgr_subset_len(acc_mgr); + acc_mgr->len_allowed_ramp = len_allowed_ramp; + if (old_len != acc_mgr_subset_len(acc_mgr)) + acc_mgr_subset_length_changed(acc_mgr); +} + +void acc_mgr_set_rotation_time(struct acc_mgr *acc_mgr, uint32_t rotation_time_sec) +{ + LOG_BTS(acc_mgr->bts, DRSL, LOGL_DEBUG, + "ACC: rotate subset time set to %" PRIu32 " seconds\n", rotation_time_sec); + acc_mgr->rotation_time_sec = rotation_time_sec; +} + +void acc_mgr_perm_subset_changed(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control) +{ + /* Even if amount is the same, the allowed/barred ones may have changed, + * so let's retrigger generation of an entire subset rather than + * rotating it */ + acc_mgr_gen_subset(acc_mgr, true); +} + +/*! + * Potentially mark certain Access Control Classes (ACCs) as barred in accordance to ACC policy. + * \param[in] acc_mgr Pointer to acc_mgr structure. + * \param[in] rach_control RACH control parameters in which barred ACCs will be configured. + */ +void acc_mgr_apply_acc(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_control) +{ + rach_control->t2 |= acc_mgr_get_barred_t2(acc_mgr); + rach_control->t3 |= acc_mgr_get_barred_t3(acc_mgr); +} + + +////////////////////////// +// acc_ramp +////////////////////////// static unsigned int get_next_step_interval(struct acc_ramp *acc_ramp) { struct gsm_bts *bts = acc_ramp->bts; @@ -104,42 +383,14 @@ static unsigned int get_next_step_interval(struct acc_ramp *acc_ramp) static void do_acc_ramping_step(void *data) { struct acc_ramp *acc_ramp = data; - int i; - - /* Shortcut in case we only do one ramping step. */ - if (acc_ramp->step_size == ACC_RAMP_STEP_SIZE_MAX) { - allow_all_accs(acc_ramp); - gsm_bts_set_system_infos(acc_ramp->bts); - return; - } - - /* Allow 'step_size' ACCs, starting from ACC0. ACC9 will be allowed last. */ - for (i = 0; i < acc_ramp->step_size; i++) { - int idx = ffs(acc_ramp_get_barred_t3(acc_ramp)); - if (idx > 0) { - /* One of ACC0-ACC7 is still bared. */ - unsigned int acc = idx - 1; - if (!acc_is_permanently_barred(acc_ramp->bts, acc)) - allow_one_acc(acc_ramp, acc); - } else { - idx = ffs(acc_ramp_get_barred_t2(acc_ramp)); - if (idx == 1 || idx == 2) { - /* ACC8 or ACC9 is still barred. */ - unsigned int acc = idx - 1 + 8; - if (!acc_is_permanently_barred(acc_ramp->bts, acc)) - allow_one_acc(acc_ramp, acc); - } else { - /* All ACCs are now allowed. */ - break; - } - } - } + struct acc_mgr *acc_mgr = &acc_ramp->bts->acc_mgr; + uint8_t old_len = acc_mgr_get_len_allowed_ramp(acc_mgr); + uint8_t new_len = OSMO_MIN(10, old_len + acc_ramp->step_size); - gsm_bts_set_system_infos(acc_ramp->bts); + acc_mgr_set_len_allowed_ramp(acc_mgr, new_len); /* If we have not allowed all ACCs yet, schedule another ramping step. */ - if (acc_ramp_get_barred_t2(acc_ramp) != 0x00 || - acc_ramp_get_barred_t3(acc_ramp) != 0x00) + if (new_len != 10) osmo_timer_schedule(&acc_ramp->step_timer, get_next_step_interval(acc_ramp), 0); } @@ -279,7 +530,6 @@ void acc_ramp_init(struct acc_ramp *acc_ramp, struct gsm_bts *bts) acc_ramp->step_size = ACC_RAMP_STEP_SIZE_DEFAULT; acc_ramp->step_interval_sec = ACC_RAMP_STEP_INTERVAL_MIN; acc_ramp->step_interval_is_fixed = false; - allow_all_accs(acc_ramp); osmo_timer_setup(&acc_ramp->step_timer, do_acc_ramping_step, acc_ramp); osmo_signal_register_handler(SS_NM, acc_ramp_nm_sig_cb, acc_ramp); } @@ -344,7 +594,7 @@ void acc_ramp_trigger(struct acc_ramp *acc_ramp) if (acc_ramp_is_enabled(acc_ramp)) { /* Set all available ACCs to barred and start ramping up. */ - barr_all_accs(acc_ramp); + acc_mgr_set_len_allowed_ramp(&acc_ramp->bts->acc_mgr, 0); do_acc_ramping_step(acc_ramp); } } @@ -358,5 +608,5 @@ void acc_ramp_abort(struct acc_ramp *acc_ramp) if (osmo_timer_pending(&acc_ramp->step_timer)) osmo_timer_del(&acc_ramp->step_timer); - allow_all_accs(acc_ramp); + acc_mgr_set_len_allowed_ramp(&acc_ramp->bts->acc_mgr, 10); } diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c index 9cc76730e..0be4e6d45 100644 --- a/src/osmo-bsc/bsc_vty.c +++ b/src/osmo-bsc/bsc_vty.c @@ -404,6 +404,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) VTY_NEWLINE); vty_out(vty, " Cell Reselection Hysteresis: %u dBm%s", bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE); + vty_out(vty, " Access Control Class rotation allow mask: 0x%" PRIx16 "%s", + bts->acc_mgr.allowed_subset_mask, VTY_NEWLINE); vty_out(vty, " Access Control Class ramping: %senabled%s", acc_ramp_is_enabled(&bts->acc_ramp) ? "" : "not ", VTY_NEWLINE); if (acc_ramp_is_enabled(&bts->acc_ramp)) { @@ -948,6 +950,10 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) for (i = 0; i < 8; i++) if ((i != 2) && (bts->si_common.rach_control.t2 & (0x1 << i))) vty_out(vty, " rach access-control-class %d barred%s", i+8, VTY_NEWLINE); + if (bts->acc_mgr.len_allowed_adm < 10) + vty_out(vty, " access-control-class-rotate %" PRIu8 "%s", bts->acc_mgr.len_allowed_adm, VTY_NEWLINE); + if (bts->acc_mgr.rotation_time_sec != ACC_MGR_QUANTUM_DEFAULT) + vty_out(vty, " access-control-class-rotate-quantum %" PRIu32 "%s", bts->acc_mgr.rotation_time_sec, VTY_NEWLINE); vty_out(vty, " %saccess-control-class-ramping%s", acc_ramp_is_enabled(&bts->acc_ramp) ? "" : "no ", VTY_NEWLINE); if (!acc_ramp_step_interval_is_dynamic(&bts->acc_ramp)) { vty_out(vty, " access-control-class-ramping-step-interval %u%s", @@ -2745,6 +2751,9 @@ DEFUN(cfg_bts_rach_ac_class, cfg_bts_rach_ac_class_cmd, else bts->si_common.rach_control.t2 |= (0x1 << (control_class - 8)); + if (control_class < 10) + acc_mgr_perm_subset_changed(&bts->acc_mgr, &bts->si_common.rach_control); + return CMD_SUCCESS; } @@ -3640,6 +3649,30 @@ DEFUN(cfg_bts_pcu_sock, cfg_bts_pcu_sock_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_acc_rotate, + cfg_bts_acc_rotate_cmd, + "access-control-class-rotate <0-10>", + "Enable Access Control Class allowed subset rotation\n" + "Size of the rotating allowed ACC 0-9 subset (default=10, no subset)\n") +{ + struct gsm_bts *bts = vty->index; + int len_allowed_adm = atoi(argv[0]); + acc_mgr_set_len_allowed_adm(&bts->acc_mgr, len_allowed_adm); + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_acc_rotate_quantum, + cfg_bts_acc_rotate_quantum_cmd, + "access-control-class-rotate-quantum <1-65535>", + "Time between rotation of ACC 0-9 generated subsets\n" + "Time in seconds (default=" OSMO_STRINGIFY_VAL(ACC_MGR_QUANTUM_DEFAULT) ")\n") +{ + struct gsm_bts *bts = vty->index; + uint32_t rotation_time_sec = (uint32_t)atoi(argv[0]); + acc_mgr_set_rotation_time(&bts->acc_mgr, rotation_time_sec); + return CMD_SUCCESS; +} + DEFUN(cfg_bts_acc_ramping, cfg_bts_acc_ramping_cmd, "access-control-class-ramping", @@ -6493,6 +6526,8 @@ int bsc_vty_init(struct gsm_network *network) install_element(BTS_NODE, &cfg_bts_amr_hr_hyst3_cmd); install_element(BTS_NODE, &cfg_bts_amr_hr_start_mode_cmd); install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd); + install_element(BTS_NODE, &cfg_bts_acc_rotate_cmd); + install_element(BTS_NODE, &cfg_bts_acc_rotate_quantum_cmd); install_element(BTS_NODE, &cfg_bts_acc_ramping_cmd); install_element(BTS_NODE, &cfg_bts_no_acc_ramping_cmd); install_element(BTS_NODE, &cfg_bts_acc_ramping_step_interval_cmd); diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c index 779402416..4318b7ef9 100644 --- a/src/osmo-bsc/bts.c +++ b/src/osmo-bsc/bts.c @@ -387,6 +387,7 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num) bts_init_cbch_state(&bts->cbch_basic, bts); bts_init_cbch_state(&bts->cbch_extended, bts); + acc_mgr_init(&bts->acc_mgr, bts); acc_ramp_init(&bts->acc_ramp, bts); return bts; diff --git a/src/osmo-bsc/system_information.c b/src/osmo-bsc/system_information.c index fe78e8e8c..7011127ba 100644 --- a/src/osmo-bsc/system_information.c +++ b/src/osmo-bsc/system_information.c @@ -723,8 +723,7 @@ static int generate_si1(enum osmo_sysinfo_type t, struct gsm_bts *bts) list_arfcn(si1->cell_channel_description, 0xce, "Serving cell:"); si1->rach_control = bts->si_common.rach_control; - if (acc_ramp_is_enabled(&bts->acc_ramp)) - acc_ramp_apply(&si1->rach_control, &bts->acc_ramp); + acc_mgr_apply_acc(&bts->acc_mgr, &si1->rach_control); /* * SI1 Rest Octets (10.5.2.32), contains NCH position and band @@ -755,8 +754,7 @@ static int generate_si2(enum osmo_sysinfo_type t, struct gsm_bts *bts) si2->ncc_permitted = bts->si_common.ncc_permitted; si2->rach_control = bts->si_common.rach_control; - if (acc_ramp_is_enabled(&bts->acc_ramp)) - acc_ramp_apply(&si2->rach_control, &bts->acc_ramp); + acc_mgr_apply_acc(&bts->acc_mgr, &si2->rach_control); return sizeof(*si2); } @@ -790,8 +788,7 @@ static int generate_si2bis(enum osmo_sysinfo_type t, struct gsm_bts *bts) bts->si_valid &= ~(1 << SYSINFO_TYPE_2bis); si2b->rach_control = bts->si_common.rach_control; - if (acc_ramp_is_enabled(&bts->acc_ramp)) - acc_ramp_apply(&si2b->rach_control, &bts->acc_ramp); + acc_mgr_apply_acc(&bts->acc_mgr, &si2b->rach_control); /* SI2bis Rest Octets as per 3GPP TS 44.018 ยง10.5.2.33 */ rc = rest_octets_si2bis(si2b->rest_octets); @@ -912,8 +909,7 @@ static int generate_si3(enum osmo_sysinfo_type t, struct gsm_bts *bts) si3->cell_options = bts->si_common.cell_options; si3->cell_sel_par = bts->si_common.cell_sel_par; si3->rach_control = bts->si_common.rach_control; - if (acc_ramp_is_enabled(&bts->acc_ramp)) - acc_ramp_apply(&si3->rach_control, &bts->acc_ramp); + acc_mgr_apply_acc(&bts->acc_mgr, &si3->rach_control); /* allow/disallow DTXu */ gsm48_set_dtx(&si3->cell_options, bts->dtxu, bts->dtxu, true); @@ -962,8 +958,7 @@ static int generate_si4(enum osmo_sysinfo_type t, struct gsm_bts *bts) gsm48_generate_lai2(&si4->lai, bts_lai(bts)); si4->cell_sel_par = bts->si_common.cell_sel_par; si4->rach_control = bts->si_common.rach_control; - if (acc_ramp_is_enabled(&bts->acc_ramp)) - acc_ramp_apply(&si4->rach_control, &bts->acc_ramp); + acc_mgr_apply_acc(&bts->acc_mgr, &si4->rach_control); /* Optional: CBCH Channel Description + CBCH Mobile Allocation */ cbch_lchan = gsm_bts_get_cbch(bts); diff --git a/tests/Makefile.am b/tests/Makefile.am index 9f2e0e0f0..07de847e3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = \ + acc \ bsc \ codec_pref \ gsm0408 \ diff --git a/tests/acc/Makefile.am b/tests/acc/Makefile.am new file mode 100644 index 000000000..4726ddc72 --- /dev/null +++ b/tests/acc/Makefile.am @@ -0,0 +1,37 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + -ggdb3 \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOABIS_CFLAGS) \ + $(LIBOSMOGSM_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(NULL) + +EXTRA_DIST = \ + acc_test.ok \ + $(NULL) + +noinst_PROGRAMS = \ + acc_test \ + $(NULL) + +acc_test_SOURCES = \ + acc_test.c \ + $(NULL) + +acc_test_LDADD = \ + $(top_builddir)/src/osmo-bsc/abis_nm.o \ + $(top_builddir)/src/osmo-bsc/acc.o \ + $(top_builddir)/src/osmo-bsc/bts.o \ + $(top_builddir)/src/osmo-bsc/bts_trx.o \ + $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/net_init.o \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOABIS_LIBS) \ + $(LIBOSMOGSM_LIBS) \ + $(NULL) diff --git a/tests/acc/acc_test.c b/tests/acc/acc_test.c new file mode 100644 index 000000000..54f3de1fa --- /dev/null +++ b/tests/acc/acc_test.c @@ -0,0 +1,493 @@ +/* + * (C) 2020 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +static void clock_debug(char* str) +{ + struct timespec ts; + struct timeval tv; + osmo_clock_gettime(CLOCK_MONOTONIC, &ts); + osmo_gettimeofday(&tv, NULL); + fprintf(stderr, "sys={%lu.%06lu}: %s\n", + tv.tv_sec, tv.tv_usec, str); +} + +#define bts_init(net) _bts_init(net, __func__) +static inline struct gsm_bts *_bts_init(struct gsm_network *net, const char *msg) +{ + struct gsm_bts *bts = gsm_bts_alloc(net, 0); + if (!bts) { + fprintf(stderr, "BTS allocation failure in %s()\n", msg); + exit(1); + } + fprintf(stderr, "BTS allocation OK in %s()\n", msg); + + bts->network = net; + + return bts; +} + +#define bts_del(bts) _bts_del(bts, __func__) +static inline void _bts_del(struct gsm_bts *bts, const char *msg) +{ + osmo_stat_item_group_free(bts->bts_statg); + rate_ctr_group_free(bts->bts_ctrs); + if (osmo_timer_pending(&bts->acc_mgr.rotate_timer)) + osmo_timer_del(&bts->acc_mgr.rotate_timer); + /* no need to llist_del(&bts->list), we never registered the bts there. */ + talloc_free(bts); + fprintf(stderr, "BTS deallocated OK in %s()\n", msg); +} + +static void do_allowed_len_adm_loop(struct acc_mgr *acc_mgr, uint8_t jump) +{ + int i; + fprintf(stderr, "%s(%" PRIu8 ")\n", __func__, jump); + /* Test decreasing the administrative (VTY) max subset size */ + for (i = 10; i >= 0; i -= jump) { + acc_mgr_set_len_allowed_adm(acc_mgr, i); + } + if (i != 0) + acc_mgr_set_len_allowed_adm(acc_mgr, 0); + /* Test increasing the administrative (VTY) max subset size */ + for (i = 0; i <= 10; i += jump) { + acc_mgr_set_len_allowed_adm(acc_mgr, i); + } + if (i != 10) + acc_mgr_set_len_allowed_adm(acc_mgr, 10); +} + +static void do_allowed_len_ramp_loop(struct acc_mgr *acc_mgr, uint8_t jump) +{ + int i; + fprintf(stderr, "%s(%" PRIu8 ")\n", __func__, jump); + /* Test decreasing the administrative (VTY) max subset size */ + for (i = 10; i >= 0; i -= jump) { + acc_mgr_set_len_allowed_ramp(acc_mgr, i); + } + if (i != 0) + acc_mgr_set_len_allowed_ramp(acc_mgr, 0); + /* Test increasing the administrative (VTY) max subset size */ + for (i = 0; i <= 10; i += jump) { + acc_mgr_set_len_allowed_ramp(acc_mgr, i); + } + if (i != 10) + acc_mgr_set_len_allowed_ramp(acc_mgr, 10); +} + +static void test_acc_mgr_no_ramp(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_mgr_get_len_allowed_adm(acc_mgr) == 10); + OSMO_ASSERT(acc_mgr_get_len_allowed_ramp(acc_mgr) == 10); + OSMO_ASSERT(acc_mgr->rotation_time_sec == ACC_MGR_QUANTUM_DEFAULT); + OSMO_ASSERT(acc_mgr->allowed_subset_mask == 0x3ff); + OSMO_ASSERT(acc_mgr->allowed_subset_mask_count == 10); + OSMO_ASSERT(acc_mgr->allowed_permanent_count == 10); + + + do_allowed_len_adm_loop(acc_mgr, 1); + do_allowed_len_adm_loop(acc_mgr, 4); + + /* Now permantenly barr some ACC */ + fprintf(stderr, "*** Barring some ACCs ***\n"); + bts->si_common.rach_control.t2 |= 0x02; + bts->si_common.rach_control.t3 |= 0xa5; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + + do_allowed_len_adm_loop(acc_mgr, 1); + do_allowed_len_adm_loop(acc_mgr, 4); + + fprintf(stderr, "*** Barring ALL ACCs ***\n"); + bts->si_common.rach_control.t2 |= 0x03; + bts->si_common.rach_control.t3 |= 0xff; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + + fprintf(stderr, "*** Barring zero ACCs ***\n"); + bts->si_common.rach_control.t2 = 0xfc; + bts->si_common.rach_control.t3 = 0x00; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + + bts_del(bts); +} + +static void test_acc_mgr_manual_ramp(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_mgr_get_len_allowed_adm(acc_mgr) == 10); + OSMO_ASSERT(acc_mgr_get_len_allowed_ramp(acc_mgr) == 10); + OSMO_ASSERT(acc_mgr->rotation_time_sec == ACC_MGR_QUANTUM_DEFAULT); + OSMO_ASSERT(acc_mgr->allowed_subset_mask == 0x3ff); + OSMO_ASSERT(acc_mgr->allowed_subset_mask_count == 10); + OSMO_ASSERT(acc_mgr->allowed_permanent_count == 10); + + do_allowed_len_ramp_loop(acc_mgr, 1); + do_allowed_len_ramp_loop(acc_mgr, 4); + + /* Now permantenly barr some ACC */ + fprintf(stderr, "*** Barring some ACCs ***\n"); + bts->si_common.rach_control.t2 |= 0x01; + bts->si_common.rach_control.t3 |= 0xb3; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + + do_allowed_len_ramp_loop(acc_mgr, 1); + do_allowed_len_ramp_loop(acc_mgr, 4); + + fprintf(stderr, "*** Barring ALL ACCs ***\n"); + bts->si_common.rach_control.t2 |= 0x03; + bts->si_common.rach_control.t3 |= 0xff; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + do_allowed_len_ramp_loop(acc_mgr, 1); + do_allowed_len_ramp_loop(acc_mgr, 4); + + fprintf(stderr, "*** Barring zero ACCs ***\n"); + bts->si_common.rach_control.t2 = 0xfc; + bts->si_common.rach_control.t3 = 0x00; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + do_allowed_len_ramp_loop(acc_mgr, 1); + do_allowed_len_ramp_loop(acc_mgr, 4); + + fprintf(stderr, "*** Barring some ACCs + adm len 4 ***\n"); + acc_mgr_set_len_allowed_adm(acc_mgr, 4); + bts->si_common.rach_control.t2 = 0xfd; + bts->si_common.rach_control.t3 = 0xb3; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + do_allowed_len_ramp_loop(acc_mgr, 1); + do_allowed_len_ramp_loop(acc_mgr, 4); + + bts_del(bts); +} + +static void test_acc_mgr_rotate(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + int i; + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + + osmo_gettimeofday_override_time = (struct timeval) {0, 0}; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_mgr_get_len_allowed_adm(acc_mgr) == 10); + OSMO_ASSERT(acc_mgr_get_len_allowed_ramp(acc_mgr) == 10); + OSMO_ASSERT(acc_mgr->rotation_time_sec == ACC_MGR_QUANTUM_DEFAULT); + OSMO_ASSERT(acc_mgr->allowed_subset_mask == 0x3ff); + OSMO_ASSERT(acc_mgr->allowed_subset_mask_count == 10); + OSMO_ASSERT(acc_mgr->allowed_permanent_count == 10); + + /* Test that rotation won't go over permanently barred ACC*/ + fprintf(stderr, "*** Barring one ACC ***\n"); + bts->si_common.rach_control.t2 |= 0x02; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + + + acc_mgr_set_rotation_time(acc_mgr, 2); + acc_mgr_set_len_allowed_adm(acc_mgr, 4); + + for (i = 0; i < 20; i++) { + osmo_gettimeofday_override_time.tv_sec += 2; + clock_debug("select()"); + osmo_select_main(0); + } + + bts_del(bts); +} + +static void test_acc_ramp_fixed(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + int i; + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + struct acc_ramp *acc_ramp = &bts->acc_ramp; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); + OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_step_interval_is_dynamic(acc_ramp) == true); + + /* Set super high rotation time so it doesn't interfer here: */ + acc_mgr_set_rotation_time(acc_mgr, 5000); + + //acc_ramp_set_step_interval_dynamic(acc_ramp); + OSMO_ASSERT(acc_ramp_set_step_interval(acc_ramp, 1) == -ERANGE); + OSMO_ASSERT(acc_ramp_set_step_interval(acc_ramp, 50) == 0); + acc_ramp_set_step_size(acc_ramp, 1); + acc_ramp_set_enabled(acc_ramp, true); + + osmo_gettimeofday_override_time = (struct timeval) {0, 0}; + acc_ramp_trigger(acc_ramp); + + for (i = 0; i < 9; i++) { + osmo_gettimeofday_override_time.tv_sec += 50; + clock_debug("select()"); + osmo_select_main(0); + } + + bts_del(bts); +} + +static void test_acc_ramp_fixed2(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + int i; + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + struct acc_ramp *acc_ramp = &bts->acc_ramp; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); + OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_step_interval_is_dynamic(acc_ramp) == true); + + /* Set super high rotation time so it doesn't interfer here: */ + acc_mgr_set_rotation_time(acc_mgr, 5000); + /* Set adm len to test that ramping won't go over it */ + acc_mgr_set_len_allowed_adm(acc_mgr, 7); + + acc_ramp_set_step_size(acc_ramp, 3); + acc_ramp_set_enabled(acc_ramp, true); + + osmo_gettimeofday_override_time = (struct timeval) {0, 0}; + acc_ramp_trigger(acc_ramp); + + for (i = 0; i < 3; i++) { + osmo_gettimeofday_override_time.tv_sec += ACC_RAMP_STEP_INTERVAL_MIN; + clock_debug("select()"); + osmo_select_main(0); + } + + bts_del(bts); +} + +static void test_acc_ramp_fixed3(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + int i; + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + struct acc_ramp *acc_ramp = &bts->acc_ramp; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); + OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_step_interval_is_dynamic(acc_ramp) == true); + + /* Set super high rotation time so it doesn't interfer here: */ + acc_mgr_set_rotation_time(acc_mgr, 5000); + /* Test that ramping won't go over permanently barred ACC*/ + fprintf(stderr, "*** Barring some ACCs ***\n"); + bts->si_common.rach_control.t2 |= 0x02; + bts->si_common.rach_control.t3 |= 0xa5; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + + acc_ramp_set_step_size(acc_ramp, 1); + acc_ramp_set_enabled(acc_ramp, true); + + osmo_gettimeofday_override_time = (struct timeval) {0, 0}; + acc_ramp_trigger(acc_ramp); + + for (i = 0; i < 9; i++) { + osmo_gettimeofday_override_time.tv_sec += ACC_RAMP_STEP_INTERVAL_MIN; + clock_debug("select()"); + osmo_select_main(0); + } + + bts_del(bts); +} + +static void test_acc_ramp_dynamic(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + char buf[128]; + unsigned int step_sec; + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + struct acc_ramp *acc_ramp = &bts->acc_ramp; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); + OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_step_interval_is_dynamic(acc_ramp) == true); + + /* Set super high rotation time so it doesn't interfer here: */ + acc_mgr_set_rotation_time(acc_mgr, 5000); + + acc_ramp_set_step_interval_dynamic(acc_ramp); + acc_ramp_set_step_size(acc_ramp, 1); + acc_ramp_set_enabled(acc_ramp, true); + + bts->chan_load_avg = 0; /*set 70% channel load */ + + osmo_gettimeofday_override_time = (struct timeval) {0, 0}; + acc_ramp_trigger(acc_ramp); + + while (osmo_timer_pending(&acc_ramp->step_timer)) { + bts->chan_load_avg += 10; + step_sec = ((bts->chan_load_avg * ACC_RAMP_STEP_INTERVAL_MAX) / 100); + osmo_gettimeofday_override_time.tv_sec += step_sec; + snprintf(buf, sizeof(buf), "select(): load=%" PRIu8 " -> step_sec=%u", + bts->chan_load_avg, step_sec); + clock_debug(buf); + osmo_select_main(0); + } + + bts_del(bts); +} + +static void test_acc_ramp_fixed_rotate(struct gsm_network *net) +{ + fprintf(stderr, "===%s===\n", __func__); + struct gsm_bts *bts = bts_init(net); + struct acc_mgr *acc_mgr = &bts->acc_mgr; + struct acc_ramp *acc_ramp = &bts->acc_ramp; + + /* Validate are all allowed by default after allocation: */ + OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); + OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_step_interval_is_dynamic(acc_ramp) == true); + + OSMO_ASSERT(acc_ramp_set_step_interval(acc_ramp, 250) == 0); + acc_mgr_set_rotation_time(acc_mgr, 100); + /* Test that ramping + rotation won't go over permanently barred ACC*/ + fprintf(stderr, "*** Barring one ACC ***\n"); + bts->si_common.rach_control.t2 |= 0x02; + acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); + + acc_ramp_set_step_size(acc_ramp, 1); + acc_ramp_set_enabled(acc_ramp, true); + + osmo_gettimeofday_override_time = (struct timeval) {0, 0}; + acc_ramp_trigger(acc_ramp); + + while (true) { + if (osmo_timer_pending(&acc_mgr->rotate_timer)) { + if ((osmo_gettimeofday_override_time.tv_sec + 50) % 250 == 0) + osmo_gettimeofday_override_time.tv_sec += 50; + else + osmo_gettimeofday_override_time.tv_sec += 100; + } else if (osmo_timer_pending(&acc_ramp->step_timer)) { + osmo_gettimeofday_override_time.tv_sec -= osmo_gettimeofday_override_time.tv_sec % 250; + osmo_gettimeofday_override_time.tv_sec += 250; + } else { + /* Once ramping is done, adm level is big enough and hence + * rotation is not needed and will be disabled. We are then done + */ + break; + } + clock_debug("select()"); + osmo_select_main(0); + } + + bts_del(bts); +} + +static const struct log_info_cat log_categories[] = { + [DRSL] = { + .name = "DRSL", + .description = "A-bis Radio Signalling Link (RSL)", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +static const struct log_info log_info = { + .cat = log_categories, + .num_cat = ARRAY_SIZE(log_categories), +}; + +int main(int argc, char **argv) +{ + struct gsm_network *net; + + osmo_gettimeofday_override = true; + osmo_gettimeofday_override_time = (struct timeval) {0, 0}; + + tall_bsc_ctx = talloc_named_const(NULL, 0, "gsm0408_test"); + osmo_init_logging2(tall_bsc_ctx, &log_info); + log_set_log_level(osmo_stderr_target, LOGL_INFO); + log_set_print_category_hex(osmo_stderr_target, false); + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + log_set_use_color(osmo_stderr_target, 0); + + net = gsm_network_init(tall_bsc_ctx); + if (!net) { + fprintf(stderr, "Network init failure.\n"); + return EXIT_FAILURE; + } + + test_acc_mgr_no_ramp(net); + test_acc_mgr_manual_ramp(net); + test_acc_mgr_rotate(net); + test_acc_ramp_fixed(net); + test_acc_ramp_fixed2(net); + test_acc_ramp_fixed3(net); + test_acc_ramp_dynamic(net); + test_acc_ramp_fixed_rotate(net); + + return EXIT_SUCCESS; +} + +/* Whenever ACC code changes the set of barred ACCs, gsm_bts_set_system_infos() + * is called which ends up calling pcu_info_update */ +void pcu_info_update(struct gsm_bts *bts) { + struct gsm48_rach_control rach_control = {0}; + + acc_mgr_apply_acc(&bts->acc_mgr, &rach_control); + fprintf(stderr, "%s(): t2=0x%02" PRIx8 " t3=0x%02" PRIx8 "\n", + __func__, rach_control.t2, rach_control.t3); +} + + +struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_network *net) { + OSMO_ASSERT(0); +} + +bool on_gsm_ts_init(struct gsm_bts_trx_ts *ts) { return true; } +void ts_fsm_alloc(struct gsm_bts_trx_ts *ts) {} +int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan) { return 0; } +int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data, int len) { return 0; } +int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len) +{ return 0; } +int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type) { return 0; } diff --git a/tests/acc/acc_test.ok b/tests/acc/acc_test.ok new file mode 100644 index 000000000..f377651ef --- /dev/null +++ b/tests/acc/acc_test.ok @@ -0,0 +1,620 @@ +===test_acc_mgr_no_ramp=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_mgr_no_ramp() +do_allowed_len_adm_loop(1) +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3fe (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x01 +(bts=0) ACC: update ACC allowed active subset 0x3fe -> 0x3fc (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x03 +(bts=0) ACC: update ACC allowed active subset 0x3fc -> 0x3f8 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x07 +(bts=0) ACC: update ACC allowed active subset 0x3f8 -> 0x3f0 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x0f +(bts=0) ACC: update ACC allowed active subset 0x3f0 -> 0x3e0 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x1f +(bts=0) ACC: update ACC allowed active subset 0x3e0 -> 0x3c0 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x3f +(bts=0) ACC: update ACC allowed active subset 0x3c0 -> 0x380 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x7f +(bts=0) ACC: update ACC allowed active subset 0x380 -> 0x300 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x300 -> 0x200 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on) +pcu_info_update(): t2=0x01 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x200 -> 0x000 (active_len=0, ramp_len=10, adm_len=0, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x001 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfe +(bts=0) ACC: update ACC allowed active subset 0x001 -> 0x003 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfc +(bts=0) ACC: update ACC allowed active subset 0x003 -> 0x007 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf8 +(bts=0) ACC: update ACC allowed active subset 0x007 -> 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x01f (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe0 +(bts=0) ACC: update ACC allowed active subset 0x01f -> 0x03f (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc0 +(bts=0) ACC: update ACC allowed active subset 0x03f -> 0x07f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x80 +(bts=0) ACC: update ACC allowed active subset 0x07f -> 0x0ff (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x1ff (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on) +pcu_info_update(): t2=0x02 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +do_allowed_len_adm_loop(4) +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3f0 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x0f +(bts=0) ACC: update ACC allowed active subset 0x3f0 -> 0x300 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x300 -> 0x000 (active_len=0, ramp_len=10, adm_len=0, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x0ff (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +*** Barring some ACCs *** +(bts=0) ACC: New ACC allowed subset 0x15a (active_len=5, ramp_len=10, adm_len=10, perm_len=5, rotation=off) +pcu_info_update(): t2=0x02 t3=0xa5 +do_allowed_len_adm_loop(1) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=9, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=8, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=7, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=6, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x158 (active_len=4, ramp_len=10, adm_len=4, perm_len=5, rotation=on) +pcu_info_update(): t2=0x02 t3=0xa7 +(bts=0) ACC: update ACC allowed active subset 0x158 -> 0x150 (active_len=3, ramp_len=10, adm_len=3, perm_len=5, rotation=on) +pcu_info_update(): t2=0x02 t3=0xaf +(bts=0) ACC: update ACC allowed active subset 0x150 -> 0x140 (active_len=2, ramp_len=10, adm_len=2, perm_len=5, rotation=on) +pcu_info_update(): t2=0x02 t3=0xbf +(bts=0) ACC: update ACC allowed active subset 0x140 -> 0x100 (active_len=1, ramp_len=10, adm_len=1, perm_len=5, rotation=on) +pcu_info_update(): t2=0x02 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x100 -> 0x000 (active_len=0, ramp_len=10, adm_len=0, perm_len=5, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x002 (active_len=1, ramp_len=10, adm_len=1, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfd +(bts=0) ACC: update ACC allowed active subset 0x002 -> 0x00a (active_len=2, ramp_len=10, adm_len=2, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf5 +(bts=0) ACC: update ACC allowed active subset 0x00a -> 0x01a (active_len=3, ramp_len=10, adm_len=3, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe5 +(bts=0) ACC: update ACC allowed active subset 0x01a -> 0x05a (active_len=4, ramp_len=10, adm_len=4, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xa5 +(bts=0) ACC: update ACC allowed active subset 0x05a -> 0x15a (active_len=5, ramp_len=10, adm_len=5, perm_len=5, rotation=off) +pcu_info_update(): t2=0x02 t3=0xa5 +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=6, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=7, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=8, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=9, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=10, perm_len=5, rotation=off) +do_allowed_len_adm_loop(4) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=6, perm_len=5, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x140 (active_len=2, ramp_len=10, adm_len=2, perm_len=5, rotation=on) +pcu_info_update(): t2=0x02 t3=0xbf +(bts=0) ACC: update ACC allowed active subset 0x140 -> 0x000 (active_len=0, ramp_len=10, adm_len=0, perm_len=5, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x05a (active_len=4, ramp_len=10, adm_len=4, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xa5 +(bts=0) ACC: update ACC allowed active subset 0x05a -> 0x15a (active_len=5, ramp_len=10, adm_len=8, perm_len=5, rotation=off) +pcu_info_update(): t2=0x02 t3=0xa5 +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=10, perm_len=5, rotation=off) +*** Barring ALL ACCs *** +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=10, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +*** Barring zero ACCs *** +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +BTS deallocated OK in test_acc_mgr_no_ramp() +===test_acc_mgr_manual_ramp=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_mgr_manual_ramp() +do_allowed_len_ramp_loop(1) +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3fe (active_len=9, ramp_len=9, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x01 +(bts=0) ACC: update ACC allowed active subset 0x3fe -> 0x3fc (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x03 +(bts=0) ACC: update ACC allowed active subset 0x3fc -> 0x3f8 (active_len=7, ramp_len=7, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x07 +(bts=0) ACC: update ACC allowed active subset 0x3f8 -> 0x3f0 (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x0f +(bts=0) ACC: update ACC allowed active subset 0x3f0 -> 0x3e0 (active_len=5, ramp_len=5, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x1f +(bts=0) ACC: update ACC allowed active subset 0x3e0 -> 0x3c0 (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x3f +(bts=0) ACC: update ACC allowed active subset 0x3c0 -> 0x380 (active_len=3, ramp_len=3, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x7f +(bts=0) ACC: update ACC allowed active subset 0x380 -> 0x300 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x300 -> 0x200 (active_len=1, ramp_len=1, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x01 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x200 -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x001 (active_len=1, ramp_len=1, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfe +(bts=0) ACC: update ACC allowed active subset 0x001 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfc +(bts=0) ACC: update ACC allowed active subset 0x003 -> 0x007 (active_len=3, ramp_len=3, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf8 +(bts=0) ACC: update ACC allowed active subset 0x007 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe0 +(bts=0) ACC: update ACC allowed active subset 0x01f -> 0x03f (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc0 +(bts=0) ACC: update ACC allowed active subset 0x03f -> 0x07f (active_len=7, ramp_len=7, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x80 +(bts=0) ACC: update ACC allowed active subset 0x07f -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x02 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +do_allowed_len_ramp_loop(4) +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3f0 (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x0f +(bts=0) ACC: update ACC allowed active subset 0x3f0 -> 0x300 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x300 -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +*** Barring some ACCs *** +(bts=0) ACC: New ACC allowed subset 0x24c (active_len=4, ramp_len=10, adm_len=10, perm_len=4, rotation=off) +pcu_info_update(): t2=0x01 t3=0xb3 +do_allowed_len_ramp_loop(1) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=9, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=8, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=7, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=6, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=5, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x248 (active_len=3, ramp_len=3, adm_len=10, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xb7 +(bts=0) ACC: update ACC allowed active subset 0x248 -> 0x240 (active_len=2, ramp_len=2, adm_len=10, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xbf +(bts=0) ACC: update ACC allowed active subset 0x240 -> 0x200 (active_len=1, ramp_len=1, adm_len=10, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x200 -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=4, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x004 (active_len=1, ramp_len=1, adm_len=10, perm_len=4, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfb +(bts=0) ACC: update ACC allowed active subset 0x004 -> 0x00c (active_len=2, ramp_len=2, adm_len=10, perm_len=4, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf3 +(bts=0) ACC: update ACC allowed active subset 0x00c -> 0x04c (active_len=3, ramp_len=3, adm_len=10, perm_len=4, rotation=on) +pcu_info_update(): t2=0x03 t3=0xb3 +(bts=0) ACC: update ACC allowed active subset 0x04c -> 0x24c (active_len=4, ramp_len=4, adm_len=10, perm_len=4, rotation=off) +pcu_info_update(): t2=0x01 t3=0xb3 +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=5, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=6, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=7, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=8, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=9, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=10, adm_len=10, perm_len=4, rotation=off) +do_allowed_len_ramp_loop(4) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=6, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x240 (active_len=2, ramp_len=2, adm_len=10, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xbf +(bts=0) ACC: update ACC allowed active subset 0x240 -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=4, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x24c (active_len=4, ramp_len=4, adm_len=10, perm_len=4, rotation=off) +pcu_info_update(): t2=0x01 t3=0xb3 +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=8, adm_len=10, perm_len=4, rotation=off) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x24c (active_len=4, ramp_len=10, adm_len=10, perm_len=4, rotation=off) +*** Barring ALL ACCs *** +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=10, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +do_allowed_len_ramp_loop(1) +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=9, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=8, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=7, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=6, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=5, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=4, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=3, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=2, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=1, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=1, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=2, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=3, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=4, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=5, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=6, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=7, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=8, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=9, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=10, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +do_allowed_len_ramp_loop(4) +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=6, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=2, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=4, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=8, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x000 (active_len=0, ramp_len=10, adm_len=10, perm_len=0, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +*** Barring zero ACCs *** +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +do_allowed_len_ramp_loop(1) +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3fe (active_len=9, ramp_len=9, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x01 +(bts=0) ACC: update ACC allowed active subset 0x3fe -> 0x3fc (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x03 +(bts=0) ACC: update ACC allowed active subset 0x3fc -> 0x3f8 (active_len=7, ramp_len=7, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x07 +(bts=0) ACC: update ACC allowed active subset 0x3f8 -> 0x3f0 (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x0f +(bts=0) ACC: update ACC allowed active subset 0x3f0 -> 0x3e0 (active_len=5, ramp_len=5, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x1f +(bts=0) ACC: update ACC allowed active subset 0x3e0 -> 0x3c0 (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x3f +(bts=0) ACC: update ACC allowed active subset 0x3c0 -> 0x380 (active_len=3, ramp_len=3, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x7f +(bts=0) ACC: update ACC allowed active subset 0x380 -> 0x300 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x300 -> 0x200 (active_len=1, ramp_len=1, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x01 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x200 -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x001 (active_len=1, ramp_len=1, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfe +(bts=0) ACC: update ACC allowed active subset 0x001 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfc +(bts=0) ACC: update ACC allowed active subset 0x003 -> 0x007 (active_len=3, ramp_len=3, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf8 +(bts=0) ACC: update ACC allowed active subset 0x007 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe0 +(bts=0) ACC: update ACC allowed active subset 0x01f -> 0x03f (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc0 +(bts=0) ACC: update ACC allowed active subset 0x03f -> 0x07f (active_len=7, ramp_len=7, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x80 +(bts=0) ACC: update ACC allowed active subset 0x07f -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x02 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +do_allowed_len_ramp_loop(4) +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3f0 (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x0f +(bts=0) ACC: update ACC allowed active subset 0x3f0 -> 0x300 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x300 -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +*** Barring some ACCs + adm len 4 *** +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3c0 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x3f +(bts=0) ACC: New ACC allowed subset 0x24c (active_len=4, ramp_len=10, adm_len=4, perm_len=4, rotation=off) +pcu_info_update(): t2=0x01 t3=0xb3 +do_allowed_len_ramp_loop(1) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x248 (active_len=3, ramp_len=3, adm_len=4, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xb7 +(bts=0) ACC: update ACC allowed active subset 0x248 -> 0x240 (active_len=2, ramp_len=2, adm_len=4, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xbf +(bts=0) ACC: update ACC allowed active subset 0x240 -> 0x200 (active_len=1, ramp_len=1, adm_len=4, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xff +(bts=0) ACC: update ACC allowed active subset 0x200 -> 0x000 (active_len=0, ramp_len=0, adm_len=4, perm_len=4, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x004 (active_len=1, ramp_len=1, adm_len=4, perm_len=4, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfb +(bts=0) ACC: update ACC allowed active subset 0x004 -> 0x00c (active_len=2, ramp_len=2, adm_len=4, perm_len=4, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf3 +(bts=0) ACC: update ACC allowed active subset 0x00c -> 0x04c (active_len=3, ramp_len=3, adm_len=4, perm_len=4, rotation=on) +pcu_info_update(): t2=0x03 t3=0xb3 +(bts=0) ACC: update ACC allowed active subset 0x04c -> 0x24c (active_len=4, ramp_len=4, adm_len=4, perm_len=4, rotation=off) +pcu_info_update(): t2=0x01 t3=0xb3 +do_allowed_len_ramp_loop(4) +(bts=0) ACC: update ACC allowed active subset 0x24c -> 0x240 (active_len=2, ramp_len=2, adm_len=4, perm_len=4, rotation=on) +pcu_info_update(): t2=0x01 t3=0xbf +(bts=0) ACC: update ACC allowed active subset 0x240 -> 0x000 (active_len=0, ramp_len=0, adm_len=4, perm_len=4, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x24c (active_len=4, ramp_len=4, adm_len=4, perm_len=4, rotation=off) +pcu_info_update(): t2=0x01 t3=0xb3 +BTS deallocated OK in test_acc_mgr_manual_ramp() +===test_acc_mgr_rotate=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_mgr_rotate() +*** Barring one ACC *** +(bts=0) ACC: New ACC allowed subset 0x1ff (active_len=9, ramp_len=10, adm_len=10, perm_len=9, rotation=off) +pcu_info_update(): t2=0x02 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1e0 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x1f +sys={2.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1e0 -> 0x1c1 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x3e +sys={4.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x0c3 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x3c +sys={6.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0c3 -> 0x047 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xb8 +sys={8.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x047 -> 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +sys={10.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x00f -> 0x01e (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe1 +sys={12.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x01e -> 0x03c (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc3 +sys={14.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x03c -> 0x078 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x87 +sys={16.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x078 -> 0x0f0 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x0f +sys={18.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0f0 -> 0x1e0 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x1f +sys={20.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1e0 -> 0x1c1 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x3e +sys={22.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x0c3 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x3c +sys={24.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0c3 -> 0x047 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xb8 +sys={26.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x047 -> 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +sys={28.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x00f -> 0x01e (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe1 +sys={30.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x01e -> 0x03c (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc3 +sys={32.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x03c -> 0x078 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x87 +sys={34.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x078 -> 0x0f0 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x0f +sys={36.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0f0 -> 0x1e0 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x1f +sys={38.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1e0 -> 0x1c1 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x3e +sys={40.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x0c3 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x3c +BTS deallocated OK in test_acc_mgr_rotate() +===test_acc_ramp_fixed=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_ramp_fixed() +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x001 (active_len=1, ramp_len=1, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfe +sys={50.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x001 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfc +sys={100.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x003 -> 0x007 (active_len=3, ramp_len=3, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf8 +sys={150.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x007 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +sys={200.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe0 +sys={250.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x01f -> 0x03f (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc0 +sys={300.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x03f -> 0x07f (active_len=7, ramp_len=7, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x80 +sys={350.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x07f -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +sys={400.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x02 t3=0x00 +sys={450.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +BTS deallocated OK in test_acc_ramp_fixed() +===test_acc_ramp_fixed2=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_ramp_fixed2() +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3f8 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on) +pcu_info_update(): t2=0x00 t3=0x07 +(bts=0) ACC: update ACC allowed active subset 0x3f8 -> 0x000 (active_len=0, ramp_len=0, adm_len=7, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x007 (active_len=3, ramp_len=3, adm_len=7, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf8 +sys={30.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x007 -> 0x03f (active_len=6, ramp_len=6, adm_len=7, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc0 +sys={60.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x03f -> 0x07f (active_len=7, ramp_len=9, adm_len=7, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x80 +sys={90.000000}: select() +BTS deallocated OK in test_acc_ramp_fixed2() +===test_acc_ramp_fixed3=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_ramp_fixed3() +*** Barring some ACCs *** +(bts=0) ACC: New ACC allowed subset 0x15a (active_len=5, ramp_len=10, adm_len=10, perm_len=5, rotation=off) +pcu_info_update(): t2=0x02 t3=0xa5 +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=5, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x002 (active_len=1, ramp_len=1, adm_len=10, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfd +sys={30.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x002 -> 0x00a (active_len=2, ramp_len=2, adm_len=10, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf5 +sys={60.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x00a -> 0x01a (active_len=3, ramp_len=3, adm_len=10, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe5 +sys={90.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x01a -> 0x05a (active_len=4, ramp_len=4, adm_len=10, perm_len=5, rotation=on) +pcu_info_update(): t2=0x03 t3=0xa5 +sys={120.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x05a -> 0x15a (active_len=5, ramp_len=5, adm_len=10, perm_len=5, rotation=off) +pcu_info_update(): t2=0x02 t3=0xa5 +sys={150.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=6, adm_len=10, perm_len=5, rotation=off) +sys={180.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=7, adm_len=10, perm_len=5, rotation=off) +sys={210.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=8, adm_len=10, perm_len=5, rotation=off) +sys={240.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=9, adm_len=10, perm_len=5, rotation=off) +sys={270.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x15a -> 0x15a (active_len=5, ramp_len=10, adm_len=10, perm_len=5, rotation=off) +BTS deallocated OK in test_acc_ramp_fixed3() +===test_acc_ramp_dynamic=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_ramp_dynamic() +(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x001 (active_len=1, ramp_len=1, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfe +sys={60.000000}: select(): load=10 -> step_sec=60 +(bts=0) ACC: update ACC allowed active subset 0x001 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfc +sys={180.000000}: select(): load=20 -> step_sec=120 +(bts=0) ACC: update ACC allowed active subset 0x003 -> 0x007 (active_len=3, ramp_len=3, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf8 +sys={360.000000}: select(): load=30 -> step_sec=180 +(bts=0) ACC: update ACC allowed active subset 0x007 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf0 +sys={600.000000}: select(): load=40 -> step_sec=240 +(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe0 +sys={900.000000}: select(): load=50 -> step_sec=300 +(bts=0) ACC: update ACC allowed active subset 0x01f -> 0x03f (active_len=6, ramp_len=6, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc0 +sys={1260.000000}: select(): load=60 -> step_sec=360 +(bts=0) ACC: update ACC allowed active subset 0x03f -> 0x07f (active_len=7, ramp_len=7, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x80 +sys={1680.000000}: select(): load=70 -> step_sec=420 +(bts=0) ACC: update ACC allowed active subset 0x07f -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +sys={2160.000000}: select(): load=80 -> step_sec=480 +(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=10, rotation=on) +pcu_info_update(): t2=0x02 t3=0x00 +sys={2700.000000}: select(): load=90 -> step_sec=540 +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +pcu_info_update(): t2=0x00 t3=0x00 +BTS deallocated OK in test_acc_ramp_dynamic() +===test_acc_ramp_fixed_rotate=== +(bts=0) ACC: New ACC allowed subset 0x3ff (active_len=10, ramp_len=10, adm_len=10, perm_len=10, rotation=off) +BTS allocation OK in test_acc_ramp_fixed_rotate() +*** Barring one ACC *** +(bts=0) ACC: New ACC allowed subset 0x1ff (active_len=9, ramp_len=10, adm_len=10, perm_len=9, rotation=off) +pcu_info_update(): t2=0x02 t3=0x00 +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x000 (active_len=0, ramp_len=0, adm_len=10, perm_len=9, rotation=off) +pcu_info_update(): t2=0x03 t3=0xff +(bts=0) ACC: New ACC allowed subset 0x001 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfe +sys={100.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x001 -> 0x002 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfd +sys={200.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x002 -> 0x004 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xfb +sys={250.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x004 -> 0x00c (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xf3 +sys={350.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x00c -> 0x018 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe7 +sys={450.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x018 -> 0x030 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xcf +sys={500.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x030 -> 0x070 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x8f +sys={600.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x070 -> 0x0e0 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x1f +sys={700.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0e0 -> 0x1c0 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x3f +sys={750.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x1c0 -> 0x1c1 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x3e +sys={850.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x0c3 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x3c +sys={950.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0c3 -> 0x047 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xb8 +sys={1000.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x047 -> 0x0c7 (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x38 +sys={1100.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0c7 -> 0x04f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xb0 +sys={1200.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x04f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xe0 +sys={1250.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x01f -> 0x03f (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0xc0 +sys={1350.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x03f -> 0x07e (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x81 +sys={1450.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x07e -> 0x0fc (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x03 +sys={1500.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x0fc -> 0x1fc (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x03 +sys={1600.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1fc -> 0x1f9 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x06 +sys={1700.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1f9 -> 0x0fb (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x04 +sys={1750.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x0fb -> 0x1fb (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x04 +sys={1850.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x1fb -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x03 t3=0x00 +sys={1950.000000}: select() +(bts=0) ACC: rotate ACC allowed active subset 0x0ff -> 0x1fe (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on) +pcu_info_update(): t2=0x02 t3=0x01 +sys={2000.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x1fe -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=9, rotation=off) +pcu_info_update(): t2=0x02 t3=0x00 +sys={2250.000000}: select() +(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1ff (active_len=9, ramp_len=10, adm_len=10, perm_len=9, rotation=off) +BTS deallocated OK in test_acc_ramp_fixed_rotate() diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c index e53b83aba..35531f81a 100644 --- a/tests/gsm0408/gsm0408_test.c +++ b/tests/gsm0408/gsm0408_test.c @@ -140,6 +140,8 @@ static inline void _bts_del(struct gsm_bts *bts, const char *msg) { osmo_stat_item_group_free(bts->bts_statg); rate_ctr_group_free(bts->bts_ctrs); + if (osmo_timer_pending(&bts->acc_mgr.rotate_timer)) + osmo_timer_del(&bts->acc_mgr.rotate_timer); /* no need to llist_del(&bts->list), we never registered the bts there. */ talloc_free(bts); printf("BTS deallocated OK in %s()\n", msg); diff --git a/tests/testsuite.at b/tests/testsuite.at index 1a190dda3..1c43249bd 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -20,6 +20,12 @@ cat $abs_srcdir/abis/abis_test.ok > expout AT_CHECK([$abs_top_builddir/tests/abis/abis_test], [], [expout], [ignore]) AT_CLEANUP +AT_SETUP([acc]) +AT_KEYWORDS([acc]) +cat $abs_srcdir/acc/acc_test.ok > experr +AT_CHECK([$abs_top_builddir/tests/acc/acc_test], [], [ignore], [experr]) +AT_CLEANUP + AT_SETUP([bsc]) AT_KEYWORDS([bsc]) cat $abs_srcdir/bsc/bsc_test.ok > expout -- cgit v1.2.3