aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO-RELEASE6
-rw-r--r--configure.ac8
-rw-r--r--debian/control4
-rw-r--r--doc/assignment-fsm.dot1
-rw-r--r--doc/assignment.msc8
-rw-r--r--doc/lchan-fsm.dot6
-rw-r--r--doc/lchan-rtp-fsm.dot7
-rw-r--r--doc/lchan.msc32
-rw-r--r--doc/manuals/chapters/smscb.adoc62
-rw-r--r--doc/manuals/osmobsc-usermanual.adoc2
-rw-r--r--include/osmocom/bsc/abis_rsl.h3
-rw-r--r--include/osmocom/bsc/bsc_msc_data.h1
-rw-r--r--include/osmocom/bsc/bsc_subscr_conn_fsm.h2
-rw-r--r--include/osmocom/bsc/bsc_subscriber.h1
-rw-r--r--include/osmocom/bsc/bts.h140
-rw-r--r--include/osmocom/bsc/gsm_08_08.h2
-rw-r--r--include/osmocom/bsc/gsm_data.h125
-rw-r--r--include/osmocom/bsc/lchan_fsm.h13
-rw-r--r--include/osmocom/bsc/lchan_select.h1
-rw-r--r--include/osmocom/bsc/osmo_bsc.h6
-rw-r--r--include/osmocom/bsc/osmo_bsc_grace.h5
-rw-r--r--include/osmocom/bsc/signal.h1
-rw-r--r--include/osmocom/bsc/smscb.h27
-rw-r--r--include/osmocom/bsc/vty.h2
-rw-r--r--src/osmo-bsc/a_reset.c10
-rw-r--r--src/osmo-bsc/abis_nm.c96
-rw-r--r--src/osmo-bsc/abis_om2000.c23
-rw-r--r--src/osmo-bsc/abis_rsl.c328
-rw-r--r--src/osmo-bsc/acc.c30
-rw-r--r--src/osmo-bsc/assignment_fsm.c79
-rw-r--r--src/osmo-bsc/bsc_init.c45
-rw-r--r--src/osmo-bsc/bsc_subscr_conn_fsm.c70
-rw-r--r--src/osmo-bsc/bsc_vty.c604
-rw-r--r--src/osmo-bsc/bts.c57
-rw-r--r--src/osmo-bsc/bts_ipaccess_nanobts.c29
-rw-r--r--src/osmo-bsc/cbsp_link.c376
-rw-r--r--src/osmo-bsc/chan_alloc.c2
-rw-r--r--src/osmo-bsc/gsm_04_08_rr.c75
-rw-r--r--src/osmo-bsc/gsm_08_08.c15
-rw-r--r--src/osmo-bsc/gsm_data.c1
-rw-r--r--src/osmo-bsc/handover_decision_2.c35
-rw-r--r--src/osmo-bsc/handover_fsm.c150
-rw-r--r--src/osmo-bsc/handover_logic.c40
-rw-r--r--src/osmo-bsc/lchan_fsm.c281
-rw-r--r--src/osmo-bsc/lchan_rtp_fsm.c72
-rw-r--r--src/osmo-bsc/lchan_select.c21
-rw-r--r--src/osmo-bsc/net_init.c22
-rw-r--r--src/osmo-bsc/osmo_bsc_bssap.c42
-rw-r--r--src/osmo-bsc/osmo_bsc_ctrl.c19
-rw-r--r--src/osmo-bsc/osmo_bsc_grace.c39
-rw-r--r--src/osmo-bsc/osmo_bsc_main.c34
-rw-r--r--src/osmo-bsc/osmo_bsc_msc.c5
-rw-r--r--src/osmo-bsc/osmo_bsc_sigtran.c16
-rw-r--r--src/osmo-bsc/paging.c6
-rw-r--r--src/osmo-bsc/smscb.c6
-rw-r--r--src/osmo-bsc/system_information.c26
-rw-r--r--src/osmo-bsc/timeslot_fsm.c1
-rw-r--r--tests/acc/acc_test.c41
-rw-r--r--tests/acc/acc_test.ok2071
-rw-r--r--tests/bsc/bsc_test.c2
-rw-r--r--tests/cbc.vty275
-rw-r--r--tests/handover/handover_test.c2
-rw-r--r--tests/timer.vty148
63 files changed, 4251 insertions, 1408 deletions
diff --git a/TODO-RELEASE b/TODO-RELEASE
index b822f8a20..f5d70c2b4 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -7,9 +7,5 @@
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
-manual needs common chapter cs7-config.adoc from osmo-gsm-manuals > 0.3.0
-libosmocore struct gsm0808_diagnostics Depends on libosmocore > 1.3.0
-libosmocore gsm0808_diagnostics_octet_location_str() Depends on libosmocore > 1.3.0
-libosmocore gsm0808_diagnostics_bit_location_str() Depends on libosmocore > 1.3.0
-libosmocore osmo_mobile_identity Depends on libosmocore > 1.3.0
+manual needs common chapter cs7-config.adoc, vty_cpu_sched.adoc from osmo-gsm-manuals > 0.3.0
osmo-bsc Mobile Identity Coding OsmoBSC is stricter in rejecting invalid coding of Mobile Identity IEs
diff --git a/configure.ac b/configure.ac
index 4a5807985..ed9b2cb3f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,10 +49,10 @@ AC_ARG_ENABLE([ipaccess-utils], [AS_HELP_STRING([--enable-ipaccess-utils], [Buil
AM_CONDITIONAL(BUILD_IPA_UTILS, test "x$osmo_ac_ipa_utils" = "xyes")
AC_SUBST(osmo_ac_ipa_utils)
-PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.3.0)
-PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.3.0)
-PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.3.0)
-PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.3.0)
+PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.4.0)
+PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.4.0)
+PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.4.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.6.0)
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 0.10.0)
diff --git a/debian/control b/debian/control
index 5a18c2ec6..d2ecea0ad 100644
--- a/debian/control
+++ b/debian/control
@@ -1,7 +1,7 @@
Source: osmo-bsc
Section: net
Priority: extra
-Maintainer: Alexander Couzens <lynxis@fe80.eu>
+Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Build-Depends: debhelper (>=9),
dh-autoreconf,
autotools-dev,
@@ -12,7 +12,7 @@ Build-Depends: debhelper (>=9),
python3-minimal,
libcdk5-dev,
libtalloc-dev,
- libosmocore-dev (>= 1.3.0),
+ libosmocore-dev (>= 1.4.0),
libosmo-sccp-dev (>= 0.10.0),
libosmo-sigtran-dev (>= 0.10.0),
libosmo-abis-dev (>= 0.6.0),
diff --git a/doc/assignment-fsm.dot b/doc/assignment-fsm.dot
index 5a3a2b91f..c2181535b 100644
--- a/doc/assignment-fsm.dot
+++ b/doc/assignment-fsm.dot
@@ -22,6 +22,7 @@ labelloc=t; label="Assignment FSM"
bssap -> gscon [label="GSCON_EV_ASSIGNMENT_START\ndata=struct assignment_request",style=dotted]
gscon -> WAIT_LCHAN_ACTIVE [label="assignment_fsm_start()",style=dotted]
+ gscon -> WAIT_LCHAN_ESTABLISHED [label="assignment_fsm_start()\n(mode modify)",style=dotted]
WAIT_LCHAN_ACTIVE -> lchan [label="lchan_activate()\nFOR_ASSIGNMENT",style=dotted]
lchan -> WAIT_LCHAN_ACTIVE [label="ASSIGNMENT_EV_\nLCHAN_\nACTIVE,ERROR",style=dotted]
lchan -> WAIT_LCHAN_ESTABLISHED [label="ASSIGNMENT_EV_\nLCHAN_\nESTABLISHED,ERROR",style=dotted]
diff --git a/doc/assignment.msc b/doc/assignment.msc
index 4e690a811..fae088f23 100644
--- a/doc/assignment.msc
+++ b/doc/assignment.msc
@@ -9,6 +9,14 @@ msc {
gscon note gscon [label="GSCON_EV_ASSIGNMENT_START\n data=struct assignment_request"];
gscon abox gscon [label="ST_ASSIGNMENT"];
ass <- gscon [label="assignment_fsm_start()"];
+ |||;
+ --- [label="IF current lchan supports requested channel mode (re-use)"];
+ lchan <- ass [label="LCHAN_EV_REQUEST_MODE_MODIFY"];
+ ass abox ass [label="ASSIGNMENT_ST_\nWAIT_LCHAN_ESTABLISHED"];
+ ass rbox ass [label="see below"];
+
+ |||;
+ --- [label="ELSE: if current lchan does not support requested channel mode (establish new lchan)"];
ass abox ass [label="ASSIGNMENT_ST_\nWAIT_LCHAN_ACTIVE"];
|||;
diff --git a/doc/lchan-fsm.dot b/doc/lchan-fsm.dot
index b726b0c87..fe35903f7 100644
--- a/doc/lchan-fsm.dot
+++ b/doc/lchan-fsm.dot
@@ -38,4 +38,10 @@ labelloc=t; label="lchan FSM"
rtp -> WAIT_RLL_RTP_ESTABLISH [label="LCHAN_EV_RTP_READY",style=dotted]
rtp -> ESTABLISHED [label="LCHAN_EV_RTP_RELEASED",style=dotted]
+ ESTABLISHED -> WAIT_RR_CHAN_MODE_MODIFY_ACK [label="LCHAN_EV_REQUEST_MODE_MODIFY"]
+ WAIT_RR_CHAN_MODE_MODIFY_ACK -> WAIT_RSL_CHAN_MODE_MODIFY_ACK [label="LCHAN_EV_RR_CHAN_MODE_MODIFY_ACK"]
+ WAIT_RSL_CHAN_MODE_MODIFY_ACK -> WAIT_RLL_RTP_ESTABLISH [label="LCHAN_EV_RSL_CHAN_MODE_MODIFY_ACK\nwhen adding RTP"]
+ WAIT_RSL_CHAN_MODE_MODIFY_ACK -> ESTABLISHED [label="LCHAN_EV_RSL_CHAN_MODE_MODIFY_ACK\nno change to RTP"]
+ WAIT_RR_CHAN_MODE_MODIFY_ACK -> BORKEN [label="error/timeout",style=dashed]
+ WAIT_RSL_CHAN_MODE_MODIFY_ACK -> BORKEN [label="error/timeout",style=dashed]
}
diff --git a/doc/lchan-rtp-fsm.dot b/doc/lchan-rtp-fsm.dot
index d5df643b5..4c2dd31bf 100644
--- a/doc/lchan-rtp-fsm.dot
+++ b/doc/lchan-rtp-fsm.dot
@@ -1,7 +1,7 @@
digraph G {
rankdir=TB
labelloc=t; label="lchan RTP FSM"
-
+
lchan [label="lchan\nFSM",shape=box3d]
lchan2 [label="lchan\nFSM",shape=box3d]
ho_as [label="Handover or Assignment FSM",shape=box3d]
@@ -23,14 +23,15 @@ labelloc=t; label="lchan RTP FSM"
lchan -> WAIT_LCHAN_READY [label="LCHAN_RTP_EV_LCHAN_READY",style=dashed]
WAIT_LCHAN_READY -> WAIT_IPACC_CRCX_ACK [label="IPACC BTS"]
WAIT_LCHAN_READY -> WAIT_READY_TO_SWITCH_RTP
- WAIT_IPACC_CRCX_ACK -> WAIT_IPACC_MDCX_ACK
- WAIT_IPACC_MDCX_ACK -> WAIT_READY_TO_SWITCH_RTP
+ WAIT_IPACC_CRCX_ACK -> WAIT_READY_TO_SWITCH_RTP
invisible -> ho [label="HO DETECT",style=dashed]
ho -> WAIT_READY_TO_SWITCH_RTP [label="LCHAN_RTP_EV_READY_TO_SWITCH",style=dashed]
WAIT_READY_TO_SWITCH_RTP -> WAIT_MGW_ENDPOINT_CONFIGURED
WAIT_MGW_ENDPOINT_CONFIGURED -> mgwep [label="MDCX",style=dashed]
mgwep -> WAIT_MGW_ENDPOINT_CONFIGURED [label="LCHAN_RTP_EV_\nMGW_ENDPOINT_\nCONFIGURED",style=dashed]
+ WAIT_MGW_ENDPOINT_CONFIGURED -> WAIT_IPACC_MDCX_ACK [label="IPACC BTS"]
WAIT_MGW_ENDPOINT_CONFIGURED -> RTP_READY
+ WAIT_IPACC_MDCX_ACK -> RTP_READY
RTP_READY -> lchan2 [label="LCHAN_EV_\nRTP_READY",style=dashed]
RTP_READY -> RTP_ESTABLISHED
lchan2 -> RTP_ESTABLISHED [label="LCHAN_RTP_EV_\nRELEASE",style=dashed]
diff --git a/doc/lchan.msc b/doc/lchan.msc
index e2caa4875..af9a59b52 100644
--- a/doc/lchan.msc
+++ b/doc/lchan.msc
@@ -68,10 +68,6 @@ msc {
ms <= rtp [label="IPACC CRCX"];
...;
ms => rtp [label="IPACC CRCX ACK (BTS RTP port info)"];
- rtp abox rtp [label="LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK"];
- ms <= rtp [label="IPACC MDCX (MGW RTP port info)"];
- ...;
- ms => rtp [label="IPACC MDCX ACK"];
--- [label="END ip.access style BTS"];
|||;
rtp box rtp [label="lchan_rtp_fsm_switch_rtp()"];
@@ -91,6 +87,12 @@ msc {
...;
mgwep rbox mgwep [label="MGCP: MDCX OK"];
rtp <- mgwep [label="LCHAN_RTP_EV_MGW_ENDPOINT_CONFIGURED"];
+ --- [label="IF ip.access style BTS"];
+ rtp abox rtp [label="LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK"];
+ ms <= rtp [label="IPACC MDCX (MGW RTP port info)"];
+ ...;
+ ms => rtp [label="IPACC MDCX ACK"];
+ --- [label="END ip.access style BTS"];
rtp abox rtp [label="LCHAN_RTP_ST_READY"];
lchan <- rtp [label="LCHAN_EV_RTP_READY"];
rtp note rtp [label="RTP FSM stays ready for Rollback until final establish event"];
@@ -129,6 +131,26 @@ msc {
...;
...;
+ ms rbox mgwep [label="On Mode Modify (e.g. change a TCH lchan from signalling to voice)"];
+ lchan abox lchan [label="LCHAN_ST_\nWAIT_RR_CHAN_\nMODE_MODIFY_ACK"];
+ ms <= lchan [label="RR Chan Mode Modif"];
+ ...;
+ ms => lchan [label="RR Chan Mode Modif Ack"];
+ lchan abox lchan [label="LCHAN_ST_\nWAIT_RSL_CHAN_\nMODE_MODIFY_ACK"];
+ ms <= lchan [label="RSL MT Mode Modify Req"];
+ ...;
+ ms => lchan [label="RSL MT Mode Modify Ack"];
+ --- [label="IF adding RTP stream"];
+ lchan abox lchan [label="LCHAN_ST_WAIT_\nRLL_RTP_ESTABLISH\nT3101"];
+ lchan rbox rtp [label="See above at 'LCHAN_RTP_EV_LCHAN_READY'"];
+ --- [label="IF not adding RTP stream"];
+ lchan abox lchan [label="LCHAN_ST_\nESTABLISHED"];
+ --- [label="END: whether adding voice stream"];
+
+ ...;
+ ...;
+ ...;
+
ms rbox mgwep [label="When the MS or BTS release the lchan"];
lchan abox lchan [label="LCHAN_ST_\nESTABLISHED"];
ms -> lchan [label="RLL Release Ind for SAPI=0"];
@@ -167,7 +189,7 @@ msc {
ms => lchan [label="RSL RF Channel Release Ack"];
|||;
--- [label="IF release_in_error"];
- lchan abox lchan [label="LCHAN_ST_WAIT_\nAFTER_ERROR\n(timeout: T3111+2 s, T993111)"];
+ lchan abox lchan [label="LCHAN_ST_WAIT_\nAFTER_ERROR\n(timeout: T3111+2 s, X3111)"];
...;
lchan box lchan [label="timer expires"];
--- [label="END: release_in_error"];
diff --git a/doc/manuals/chapters/smscb.adoc b/doc/manuals/chapters/smscb.adoc
index f7469a375..011aec413 100644
--- a/doc/manuals/chapters/smscb.adoc
+++ b/doc/manuals/chapters/smscb.adoc
@@ -13,7 +13,7 @@ specification is <<3gpp-ts-23-041>>.
In order to use SMSCB with OsmoBSC, you will need to
-* Configure the CBSP server and/or client
+* Configure OsmoBSC as either CBSP server or client
* Use a channel combination including a CBCH on the BTSs
=== Enabling a CBCH channel combination
@@ -41,41 +41,63 @@ addresses).
In order to comply with the specifications, OsmoBSC supports this mode
of operation as CBSP TCP server. However, to make network operation and
configuration more simple, it also can operate in TCP client mode,
-connecting to the CBC. This way the all the BSCs need to know is the CBC IP
+connecting to the CBC. This way the BSCs need to know the CBC IP
address, but not vice-versa.
-The BSC can operate both CBSP TCP server and CBSP TCP client mode in
-parallel.
+The BSC can operate in either CBSP TCP server mode or CBSP TCP client mode.
The CBC related configuration of OsmoBSC can be found in the `cbc` configuration
node of the VTY interface.
-.Example: Configure CBSP TCP client to connect to CBC at 1.2.3.4:48049
+The default port number for the CBSP server is 48049, according to the CBSP
+specification. Hence it normally suffices to configure only the IP addresses for
+the remote CBC server or the local CBSP server:
+
+.Example: Configure CBSP TCP client to connect to CBC at 1.2.3.4:48049 in osmo-bsc.cfg
----
-OsmoBSC> enable
-OsmoBSC# configure terminal
-OsmoBSC(config)# cbc
-OsmoBSC(config-cbc)# remote-ip 1.2.3.4
-OsmoBSC(config-cbc)# remote-port 48049
-OsmoBSC(config-cbc)# end
+cbc
+ mode client
+ client
+ remote-ip 1.2.3.4
----
-.Example: Disable CBSP TCP client
+In server mode, the default configuration is 127.0.0.1:48049, so it suffices to
+set `mode server` to accept CBSP connections from localhost:
+
----
-OsmoBSC> enable
-OsmoBSC# configure terminal
-OsmoBSC(config)# cbc
-OsmoBSC(config-cbc)# no remote-ip
-OsmoBSC(config-cbc)# end
+cbc
+ mode server
+----
+
+To also listen for inbound CBSP connections on all interfaces, both IPv4 and
+IPv6:
+
+.Example: Configure CBSP TCP server to listen on all interfaces in osmo-bsc.cfg
----
+cbc
+ mode server
+ server
+ local-ip ::
+----
+
+Should non-standard port numbers be required, these can be configured with the
+`client` / `local-port` or the `server` / `remote-port` settings.
+
+The `client` config also supports an explicit local bind for connecting to the
+remote CBC, using `client` / `local-ip` and `local-port`.
+
+IP addresses for client and server can remain configured at the same time, and
+the `mode` command can be used to switch between client and server operation.
+The `mode` command takes immediate effect, no restart of OsmoBSC is required.
+After changing `cbc` IP addresses in the telnet VTY, it is required to switch
+`mode` to `disabled` and back to `client` or `server` to take effect.
-.Example: Configure CBSP TCP server to listen for CBC at 127.0.0.2:9999
+.Example: Disable the CBSP link in the telnet VTY
----
OsmoBSC> enable
OsmoBSC# configure terminal
OsmoBSC(config)# cbc
-OsmoBSC(config-cbc)# listen-ip 127.0.0.2
-OsmoBSC(config-cbc)# listen-port 9999
+OsmoBSC(config-cbc)# mode disabled
OsmoBSC(config-cbc)# end
----
diff --git a/doc/manuals/osmobsc-usermanual.adoc b/doc/manuals/osmobsc-usermanual.adoc
index cb939cc90..a34d3d422 100644
--- a/doc/manuals/osmobsc-usermanual.adoc
+++ b/doc/manuals/osmobsc-usermanual.adoc
@@ -42,6 +42,8 @@ include::{srcdir}/chapters/control.adoc[]
include::{srcdir}/chapters/osmux_bsc.adoc[]
+include::./common/chapters/vty_cpu_sched.adoc[]
+
include::./common/chapters/port_numbers.adoc[]
include::./common/chapters/bibliography.adoc[]
diff --git a/include/osmocom/bsc/abis_rsl.h b/include/osmocom/bsc/abis_rsl.h
index 2611a3d00..964e282b5 100644
--- a/include/osmocom/bsc/abis_rsl.h
+++ b/include/osmocom/bsc/abis_rsl.h
@@ -118,5 +118,8 @@ int ipacc_payload_type(enum gsm48_chan_mode tch_mode, enum gsm_chan_t type);
int rsl_tx_rf_chan_release(struct gsm_lchan *lchan);
+void abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts);
+void abis_rsl_chan_rqd_queue_flush(struct gsm_bts *bts);
+
#endif /* RSL_MT_H */
diff --git a/include/osmocom/bsc/bsc_msc_data.h b/include/osmocom/bsc/bsc_msc_data.h
index b1fe14d2f..43ace2532 100644
--- a/include/osmocom/bsc/bsc_msc_data.h
+++ b/include/osmocom/bsc/bsc_msc_data.h
@@ -64,6 +64,7 @@ enum {
MSC_CTR_BSSMAP_RX_DT1_HANDOVER_CMD,
MSC_CTR_BSSMAP_RX_DT1_CLASSMARK_RQST,
MSC_CTR_BSSMAP_RX_DT1_CONFUSION,
+ MSC_CTR_BSSMAP_RX_DT1_COMMON_ID,
MSC_CTR_BSSMAP_RX_DT1_UNKNOWN,
MSC_CTR_BSSMAP_RX_DT1_DTAP,
MSC_CTR_BSSMAP_RX_DT1_DTAP_ERROR,
diff --git a/include/osmocom/bsc/bsc_subscr_conn_fsm.h b/include/osmocom/bsc/bsc_subscr_conn_fsm.h
index 78937353f..354c5ee93 100644
--- a/include/osmocom/bsc/bsc_subscr_conn_fsm.h
+++ b/include/osmocom/bsc/bsc_subscr_conn_fsm.h
@@ -14,6 +14,8 @@ enum gscon_fsm_event {
GSCON_EV_A_CLEAR_CMD,
/* MSC SCCP disconnect indication */
GSCON_EV_A_DISC_IND,
+ /* MSC has sent a BSSMAP COMMON ID */
+ GSCON_EV_A_COMMON_ID_IND,
GSCON_EV_ASSIGNMENT_START,
GSCON_EV_ASSIGNMENT_END,
diff --git a/include/osmocom/bsc/bsc_subscriber.h b/include/osmocom/bsc/bsc_subscriber.h
index 53fa7be5c..a602a9ef6 100644
--- a/include/osmocom/bsc/bsc_subscriber.h
+++ b/include/osmocom/bsc/bsc_subscriber.h
@@ -16,7 +16,6 @@ struct bsc_subscr {
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
uint32_t tmsi;
- uint16_t lac;
};
const char *bsc_subscr_name(struct bsc_subscr *bsub);
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h
index 16053a3bb..7f369042e 100644
--- a/include/osmocom/bsc/bts.h
+++ b/include/osmocom/bsc/bts.h
@@ -50,6 +50,8 @@ enum bts_counter_id {
BTS_CTR_LCHAN_BORKEN_EV_RF_CHAN_REL_ACK,
BTS_CTR_LCHAN_BORKEN_EV_VTY,
BTS_CTR_LCHAN_BORKEN_EV_TEARDOWN,
+ BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RR_CHAN_MODE_MODIFY_ACK,
+ BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RSL_CHAN_MODE_MODIFY_ACK,
BTS_CTR_TS_BORKEN_FROM_NOT_INITIALIZED,
BTS_CTR_TS_BORKEN_FROM_UNUSED,
BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_ACT,
@@ -68,6 +70,40 @@ enum bts_counter_id {
BTS_CTR_ASSIGNMENT_TIMEOUT,
BTS_CTR_ASSIGNMENT_FAILED,
BTS_CTR_ASSIGNMENT_ERROR,
+ BTS_CTR_HANDOVER_ATTEMPTED,
+ BTS_CTR_HANDOVER_COMPLETED,
+ BTS_CTR_HANDOVER_STOPPED,
+ BTS_CTR_HANDOVER_NO_CHANNEL,
+ BTS_CTR_HANDOVER_TIMEOUT,
+ BTS_CTR_HANDOVER_FAILED,
+ BTS_CTR_HANDOVER_ERROR,
+ BTS_CTR_INTRA_CELL_HO_ATTEMPTED,
+ BTS_CTR_INTRA_CELL_HO_COMPLETED,
+ BTS_CTR_INTRA_CELL_HO_STOPPED,
+ BTS_CTR_INTRA_CELL_HO_NO_CHANNEL,
+ BTS_CTR_INTRA_CELL_HO_TIMEOUT,
+ BTS_CTR_INTRA_CELL_HO_FAILED,
+ BTS_CTR_INTRA_CELL_HO_ERROR,
+ BTS_CTR_INTRA_BSC_HO_ATTEMPTED,
+ BTS_CTR_INTRA_BSC_HO_COMPLETED,
+ BTS_CTR_INTRA_BSC_HO_STOPPED,
+ BTS_CTR_INTRA_BSC_HO_NO_CHANNEL,
+ BTS_CTR_INTRA_BSC_HO_TIMEOUT,
+ BTS_CTR_INTRA_BSC_HO_FAILED,
+ BTS_CTR_INTRA_BSC_HO_ERROR,
+ BTS_CTR_INTER_BSC_HO_OUT_ATTEMPTED,
+ BTS_CTR_INTER_BSC_HO_OUT_COMPLETED,
+ BTS_CTR_INTER_BSC_HO_OUT_STOPPED,
+ BTS_CTR_INTER_BSC_HO_OUT_TIMEOUT,
+ BTS_CTR_INTER_BSC_HO_OUT_FAILED,
+ BTS_CTR_INTER_BSC_HO_OUT_ERROR,
+ BTS_CTR_INTER_BSC_HO_IN_ATTEMPTED,
+ BTS_CTR_INTER_BSC_HO_IN_COMPLETED,
+ BTS_CTR_INTER_BSC_HO_IN_STOPPED,
+ BTS_CTR_INTER_BSC_HO_IN_NO_CHANNEL,
+ BTS_CTR_INTER_BSC_HO_IN_FAILED,
+ BTS_CTR_INTER_BSC_HO_IN_TIMEOUT,
+ BTS_CTR_INTER_BSC_HO_IN_ERROR,
};
static const struct rate_ctr_desc bts_ctr_description[] = {
@@ -102,6 +138,8 @@ static const struct rate_ctr_desc bts_ctr_description[] = {
[BTS_CTR_LCHAN_BORKEN_FROM_WAIT_ACTIV_ACK] = {"lchan_borken:from_state:wait_activ_ack", "Transitions from lchan WAIT_ACTIV_ACK state to BORKEN state"},
[BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RF_RELEASE_ACK] = {"lchan_borken:from_state:wait_rf_release_ack", "Transitions from lchan WAIT_RF_RELEASE_ACK state to BORKEN state"},
[BTS_CTR_LCHAN_BORKEN_FROM_BORKEN] = {"lchan_borken:from_state:borken", "Transitions from lchan BORKEN state to BORKEN state"},
+ [BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RR_CHAN_MODE_MODIFY_ACK] = {"lchan_borken:from_state:wait_rr_chan_mode_modify_ack", "Transitions from lchan WAIT_RR_CHAN_MODE_MODIFY_ACK state to BORKEN state"},
+ [BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RSL_CHAN_MODE_MODIFY_ACK] = {"lchan_borken:from_state:wait_rsl_chan_mode_modify_ack", "Transitions from lchan RSL_CHAN_MODE_MODIFY_ACK state to BORKEN state"},
[BTS_CTR_LCHAN_BORKEN_FROM_UNKNOWN] = {"lchan_borken:from_state:unknown", "Transitions from an unknown lchan state to BORKEN state"},
[BTS_CTR_LCHAN_BORKEN_EV_CHAN_ACTIV_ACK] = {"lchan_borken:event:chan_activ_ack", "CHAN_ACTIV_ACK received in the lchan BORKEN state"},
[BTS_CTR_LCHAN_BORKEN_EV_CHAN_ACTIV_NACK] = {"lchan_borken:event:chan_activ_nack", "CHAN_ACTIV_NACK received in the lchan BORKEN state"},
@@ -127,6 +165,51 @@ static const struct rate_ctr_desc bts_ctr_description[] = {
[BTS_CTR_ASSIGNMENT_FAILED] = {"assignment:failed", "Received Assignment Failure message"},
[BTS_CTR_ASSIGNMENT_ERROR] = {"assignment:error", "Assignment failed for other reason"},
+ [BTS_CTR_HANDOVER_ATTEMPTED] = {"handover:attempted", "Intra-BSC handover attempts"},
+ [BTS_CTR_HANDOVER_COMPLETED] = {"handover:completed", "Intra-BSC handover completed"},
+ [BTS_CTR_HANDOVER_STOPPED] = {"handover:stopped", "Connection ended during HO"},
+ [BTS_CTR_HANDOVER_NO_CHANNEL] = {"handover:no_channel", "Failure to allocate lchan for HO"},
+ [BTS_CTR_HANDOVER_TIMEOUT] = {"handover:timeout", "Handover timed out"},
+ [BTS_CTR_HANDOVER_FAILED] = {"handover:failed", "Received Handover Fail messages"},
+ [BTS_CTR_HANDOVER_ERROR] = {"handover:error", "Re-assignment failed for other reason"},
+
+ [BTS_CTR_INTRA_CELL_HO_ATTEMPTED] = {"intra_cell_ho:attempted", "Intra-Cell handover attempts"},
+ [BTS_CTR_INTRA_CELL_HO_COMPLETED] = {"intra_cell_ho:completed", "Intra-Cell handover completed"},
+ [BTS_CTR_INTRA_CELL_HO_STOPPED] = {"intra_cell_ho:stopped", "Connection ended during HO"},
+ [BTS_CTR_INTRA_CELL_HO_NO_CHANNEL] = {"intra_cell_ho:no_channel", "Failure to allocate lchan for HO"},
+ [BTS_CTR_INTRA_CELL_HO_TIMEOUT] = {"intra_cell_ho:timeout", "Handover timed out"},
+ [BTS_CTR_INTRA_CELL_HO_FAILED] = {"intra_cell_ho:failed", "Received Handover Fail messages"},
+ [BTS_CTR_INTRA_CELL_HO_ERROR] = {"intra_cell_ho:error", "Re-assignment failed for other reason"},
+
+ [BTS_CTR_INTRA_BSC_HO_ATTEMPTED] = {"intra_bsc_ho:attempted", "Intra-BSC handover attempts"},
+ [BTS_CTR_INTRA_BSC_HO_COMPLETED] = {"intra_bsc_ho:completed", "Intra-BSC handover completed"},
+ [BTS_CTR_INTRA_BSC_HO_STOPPED] = {"intra_bsc_ho:stopped", "Connection ended during HO"},
+ [BTS_CTR_INTRA_BSC_HO_NO_CHANNEL] = {"intra_bsc_ho:no_channel", "Failure to allocate lchan for HO"},
+ [BTS_CTR_INTRA_BSC_HO_TIMEOUT] = {"intra_bsc_ho:timeout", "Handover timed out"},
+ [BTS_CTR_INTRA_BSC_HO_FAILED] = {"intra_bsc_ho:failed", "Received Handover Fail messages"},
+ [BTS_CTR_INTRA_BSC_HO_ERROR] = {"intra_bsc_ho:error", "Re-assignment failed for other reason"},
+
+ [BTS_CTR_INTER_BSC_HO_OUT_ATTEMPTED] = {"interbsc_ho_out:attempted",
+ "Attempts to handover to remote BSS"},
+ [BTS_CTR_INTER_BSC_HO_OUT_COMPLETED] = {"interbsc_ho_out:completed",
+ "Handover to remote BSS completed"},
+ [BTS_CTR_INTER_BSC_HO_OUT_STOPPED] = {"interbsc_ho_out:stopped", "Connection ended during HO"},
+ [BTS_CTR_INTER_BSC_HO_OUT_TIMEOUT] = {"interbsc_ho_out:timeout", "Handover timed out"},
+ [BTS_CTR_INTER_BSC_HO_OUT_FAILED] = {"interbsc_ho_out:failed", "Received Handover Fail message"},
+ [BTS_CTR_INTER_BSC_HO_OUT_ERROR] = {"interbsc_ho_out:error",
+ "Handover to remote BSS failed for other reason"},
+
+ [BTS_CTR_INTER_BSC_HO_IN_ATTEMPTED] = {"interbsc_ho_in:attempted",
+ "Attempts to handover from remote BSS"},
+ [BTS_CTR_INTER_BSC_HO_IN_COMPLETED] = {"interbsc_ho_in:completed",
+ "Handover from remote BSS completed"},
+ [BTS_CTR_INTER_BSC_HO_IN_STOPPED] = {"interbsc_ho_in:stopped", "Connection ended during HO"},
+ [BTS_CTR_INTER_BSC_HO_IN_NO_CHANNEL] = {"interbsc_ho_in:no_channel",
+ "Failure to allocate lchan for HO"},
+ [BTS_CTR_INTER_BSC_HO_IN_TIMEOUT] = {"interbsc_ho_in:timeout", "Handover from remote BSS timed out"},
+ [BTS_CTR_INTER_BSC_HO_IN_FAILED] = {"interbsc_ho_in:failed", "Received Handover Fail message"},
+ [BTS_CTR_INTER_BSC_HO_IN_ERROR] = {"interbsc_ho_in:error",
+ "Handover from remote BSS failed for other reason"},
};
static const struct rate_ctr_group_desc bts_ctrg_desc = {
@@ -164,6 +247,62 @@ enum {
BTS_STAT_TS_BORKEN,
};
+static const struct osmo_stat_item_desc bts_stat_desc[] = {
+ [BTS_STAT_CHAN_LOAD_AVERAGE] = { "chanloadavg", "Channel load average", "%", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_USED] = { "chan_ccch_sdcch4:used",
+ "Number of CCCH+SDCCH4 channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL] = { "chan_ccch_sdcch4:total",
+ "Number of CCCH+SDCCH4 channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_USED] = { "chan_tch_f:used",
+ "Number of TCH/F channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_TOTAL] = { "chan_tch_f:total",
+ "Number of TCH/F channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_H_USED] = { "chan_tch_h:used",
+ "Number of TCH/H channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_H_TOTAL] = { "chan_tch_h:total",
+ "Number of TCH/H channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_USED] = { "chan_sdcch8:used",
+ "Number of SDCCH8 channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_TOTAL] = { "chan_sdcch8:total",
+ "Number of SDCCH8 channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_PDCH_USED] = { "chan_tch_f_pdch:used",
+ "Number of TCH/F_PDCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_PDCH_TOTAL] = { "chan_tch_f_pdch:total",
+ "Number of TCH/F_PDCH channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED] = { "chan_ccch_sdcch4_cbch:used",
+ "Number of CCCH+SDCCH4+CBCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL] = { "chan_ccch_sdcch4_cbch:total",
+ "Number of CCCH+SDCCH4+CBCH channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_CBCH_USED] = { "chan_sdcch8_cbch:used",
+ "Number of SDCCH8+CBCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL] = { "chan_sdcch8_cbch:total",
+ "Number of SDCCH8+CBCH channels total", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_USED] = { "chan_tch_f_tch_h_pdch:used",
+ "Number of TCH/F_TCH/H_PDCH channels used", "", 16, 0 },
+ [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_TOTAL] = { "chan_tch_f_tch_h_pdch:total",
+ "Number of TCH/F_TCH/H_PDCH channels total", "", 16, 0 },
+ [BTS_STAT_T3122] = { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator",
+ "s", 16, GSM_T3122_DEFAULT },
+ [BTS_STAT_RACH_BUSY] = { "rach_busy",
+ "RACH slots with signal above threshold", "%", 16, 0 },
+ [BTS_STAT_RACH_ACCESS] = { "rach_access",
+ "RACH slots with access bursts in them", "%", 16, 0 },
+ [BTS_STAT_OML_CONNECTED] = { "oml_connected", "Number of OML links connected", "", 16, 0 },
+ [BTS_STAT_RSL_CONNECTED] = { "rsl_connected", "Number of RSL links connected", "", 16, 0 },
+ [BTS_STAT_LCHAN_BORKEN] = { "lchan_borken",
+ "Number of lchans in the BORKEN state", "", 16, 0 },
+ [BTS_STAT_TS_BORKEN] = { "ts_borken",
+ "Number of timeslots in the BORKEN state", "", 16, 0 },
+};
+
+static const struct osmo_stat_item_group_desc bts_statg_desc = {
+ .group_name_prefix = "bts",
+ .group_description = "base transceiver station",
+ .class_id = OSMO_STATS_CLASS_GLOBAL,
+ .num_items = ARRAY_SIZE(bts_stat_desc),
+ .item_desc = bts_stat_desc,
+};
+
enum gsm_bts_type {
GSM_BTS_TYPE_UNKNOWN,
GSM_BTS_TYPE_BS11,
@@ -495,6 +634,7 @@ struct gsm_bts {
struct osmo_timer_list etws_timer; /* when to stop ETWS PN */
struct llist_head oml_fail_rep;
+ struct llist_head chan_rqd_queue;
};
#define GSM_BTS_SI2Q(bts, i) (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
diff --git a/include/osmocom/bsc/gsm_08_08.h b/include/osmocom/bsc/gsm_08_08.h
index b46a8d306..80da297a3 100644
--- a/include/osmocom/bsc/gsm_08_08.h
+++ b/include/osmocom/bsc/gsm_08_08.h
@@ -6,7 +6,7 @@
struct gsm_subscriber_connection;
-void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci);
+void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause);
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr);
int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, uint16_t chosen_channel);
void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg);
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index cfed1f82c..90ab8eae7 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -117,7 +117,7 @@ struct assignment_request {
uint16_t msc_assigned_cic;
- char msc_rtp_addr[INET_ADDRSTRLEN];
+ char msc_rtp_addr[INET6_ADDRSTRLEN];
uint16_t msc_rtp_port;
bool use_osmux;
uint8_t osmux_cid;
@@ -192,7 +192,7 @@ struct handover_in_req {
struct gsm0808_cell_id cell_id_target;
char cell_id_target_name[64];
uint16_t msc_assigned_cic;
- char msc_assigned_rtp_addr[INET_ADDRSTRLEN];
+ char msc_assigned_rtp_addr[INET6_ADDRSTRLEN];
uint16_t msc_assigned_rtp_port;
};
@@ -261,9 +261,6 @@ struct gsm_subscriber_connection {
/* SCCP connection associatd with this subscriber_connection */
struct {
- /* for advanced ping/pong */
- int send_ping;
-
/* SCCP connection related */
struct bsc_msc_data *msc;
@@ -277,7 +274,7 @@ struct gsm_subscriber_connection {
uint16_t msc_assigned_cic;
/* RTP address where the MSC expects us to send the RTP stream coming from the BTS. */
- char msc_assigned_rtp_addr[INET_ADDRSTRLEN];
+ char msc_assigned_rtp_addr[INET6_ADDRSTRLEN];
uint16_t msc_assigned_rtp_port;
/* The endpoint at the MGW used to join both BTS and MSC side connections, e.g.
@@ -303,6 +300,8 @@ struct gsm_subscriber_connection {
/* MS Power Class, TS 05.05 sec 4.1.1 "Mobile station". 0 means unset. */
uint8_t ms_power_class:3;
+
+ bool rx_clear_command;
};
@@ -895,6 +894,8 @@ struct gsm_bts_rejected {
time_t time;
};
+extern struct osmo_tdef_group bsc_tdef_group[];
+
struct gsm_network *gsm_network_init(void *ctx);
struct gsm_bts *gsm_bts_num(const struct gsm_network *net, int num);
@@ -969,10 +970,25 @@ enum {
BSC_CTR_HANDOVER_TIMEOUT,
BSC_CTR_HANDOVER_FAILED,
BSC_CTR_HANDOVER_ERROR,
+ BSC_CTR_INTRA_CELL_HO_ATTEMPTED,
+ BSC_CTR_INTRA_CELL_HO_COMPLETED,
+ BSC_CTR_INTRA_CELL_HO_STOPPED,
+ BSC_CTR_INTRA_CELL_HO_NO_CHANNEL,
+ BSC_CTR_INTRA_CELL_HO_TIMEOUT,
+ BSC_CTR_INTRA_CELL_HO_FAILED,
+ BSC_CTR_INTRA_CELL_HO_ERROR,
+ BSC_CTR_INTRA_BSC_HO_ATTEMPTED,
+ BSC_CTR_INTRA_BSC_HO_COMPLETED,
+ BSC_CTR_INTRA_BSC_HO_STOPPED,
+ BSC_CTR_INTRA_BSC_HO_NO_CHANNEL,
+ BSC_CTR_INTRA_BSC_HO_TIMEOUT,
+ BSC_CTR_INTRA_BSC_HO_FAILED,
+ BSC_CTR_INTRA_BSC_HO_ERROR,
BSC_CTR_INTER_BSC_HO_OUT_ATTEMPTED,
BSC_CTR_INTER_BSC_HO_OUT_COMPLETED,
BSC_CTR_INTER_BSC_HO_OUT_STOPPED,
BSC_CTR_INTER_BSC_HO_OUT_TIMEOUT,
+ BSC_CTR_INTER_BSC_HO_OUT_FAILED,
BSC_CTR_INTER_BSC_HO_OUT_ERROR,
BSC_CTR_INTER_BSC_HO_IN_ATTEMPTED,
BSC_CTR_INTER_BSC_HO_IN_COMPLETED,
@@ -992,56 +1008,73 @@ enum {
};
static const struct rate_ctr_desc bsc_ctr_description[] = {
- [BSC_CTR_ASSIGNMENT_ATTEMPTED] = {"assignment:attempted", "Assignment attempts."},
- [BSC_CTR_ASSIGNMENT_COMPLETED] = {"assignment:completed", "Assignment completed."},
- [BSC_CTR_ASSIGNMENT_STOPPED] = {"assignment:stopped", "Connection ended during Assignment."},
- [BSC_CTR_ASSIGNMENT_NO_CHANNEL] = {"assignment:no_channel", "Failure to allocate lchan for Assignment."},
- [BSC_CTR_ASSIGNMENT_TIMEOUT] = {"assignment:timeout", "Assignment timed out."},
- [BSC_CTR_ASSIGNMENT_FAILED] = {"assignment:failed", "Received Assignment Failure message."},
- [BSC_CTR_ASSIGNMENT_ERROR] = {"assignment:error", "Assignment failed for other reason."},
-
- [BSC_CTR_HANDOVER_ATTEMPTED] = {"handover:attempted", "Intra-BSC handover attempts."},
- [BSC_CTR_HANDOVER_COMPLETED] = {"handover:completed", "Intra-BSC handover completed."},
- [BSC_CTR_HANDOVER_STOPPED] = {"handover:stopped", "Connection ended during HO."},
- [BSC_CTR_HANDOVER_NO_CHANNEL] = {"handover:no_channel", "Failure to allocate lchan for HO."},
- [BSC_CTR_HANDOVER_TIMEOUT] = {"handover:timeout", "Handover timed out."},
- [BSC_CTR_HANDOVER_FAILED] = {"handover:failed", "Received Handover Fail messages."},
- [BSC_CTR_HANDOVER_ERROR] = {"handover:error", "Re-assignment failed for other reason."},
+ [BSC_CTR_ASSIGNMENT_ATTEMPTED] = {"assignment:attempted", "Assignment attempts"},
+ [BSC_CTR_ASSIGNMENT_COMPLETED] = {"assignment:completed", "Assignment completed"},
+ [BSC_CTR_ASSIGNMENT_STOPPED] = {"assignment:stopped", "Connection ended during Assignment"},
+ [BSC_CTR_ASSIGNMENT_NO_CHANNEL] = {"assignment:no_channel", "Failure to allocate lchan for Assignment"},
+ [BSC_CTR_ASSIGNMENT_TIMEOUT] = {"assignment:timeout", "Assignment timed out"},
+ [BSC_CTR_ASSIGNMENT_FAILED] = {"assignment:failed", "Received Assignment Failure message"},
+ [BSC_CTR_ASSIGNMENT_ERROR] = {"assignment:error", "Assignment failed for other reason"},
+
+ [BSC_CTR_HANDOVER_ATTEMPTED] = {"handover:attempted", "Intra-BSC handover attempts"},
+ [BSC_CTR_HANDOVER_COMPLETED] = {"handover:completed", "Intra-BSC handover completed"},
+ [BSC_CTR_HANDOVER_STOPPED] = {"handover:stopped", "Connection ended during HO"},
+ [BSC_CTR_HANDOVER_NO_CHANNEL] = {"handover:no_channel", "Failure to allocate lchan for HO"},
+ [BSC_CTR_HANDOVER_TIMEOUT] = {"handover:timeout", "Handover timed out"},
+ [BSC_CTR_HANDOVER_FAILED] = {"handover:failed", "Received Handover Fail messages"},
+ [BSC_CTR_HANDOVER_ERROR] = {"handover:error", "Re-assignment failed for other reason"},
+
+ [BSC_CTR_INTRA_CELL_HO_ATTEMPTED] = {"intra_cell_ho:attempted", "Intra-Cell handover attempts"},
+ [BSC_CTR_INTRA_CELL_HO_COMPLETED] = {"intra_cell_ho:completed", "Intra-Cell handover completed"},
+ [BSC_CTR_INTRA_CELL_HO_STOPPED] = {"intra_cell_ho:stopped", "Connection ended during HO"},
+ [BSC_CTR_INTRA_CELL_HO_NO_CHANNEL] = {"intra_cell_ho:no_channel", "Failure to allocate lchan for HO"},
+ [BSC_CTR_INTRA_CELL_HO_TIMEOUT] = {"intra_cell_ho:timeout", "Handover timed out"},
+ [BSC_CTR_INTRA_CELL_HO_FAILED] = {"intra_cell_ho:failed", "Received Handover Fail messages"},
+ [BSC_CTR_INTRA_CELL_HO_ERROR] = {"intra_cell_ho:error", "Re-assignment failed for other reason"},
+
+ [BSC_CTR_INTRA_BSC_HO_ATTEMPTED] = {"intra_bsc_ho:attempted", "Intra-BSC handover attempts"},
+ [BSC_CTR_INTRA_BSC_HO_COMPLETED] = {"intra_bsc_ho:completed", "Intra-BSC handover completed"},
+ [BSC_CTR_INTRA_BSC_HO_STOPPED] = {"intra_bsc_ho:stopped", "Connection ended during HO"},
+ [BSC_CTR_INTRA_BSC_HO_NO_CHANNEL] = {"intra_bsc_ho:no_channel", "Failure to allocate lchan for HO"},
+ [BSC_CTR_INTRA_BSC_HO_TIMEOUT] = {"intra_bsc_ho:timeout", "Handover timed out"},
+ [BSC_CTR_INTRA_BSC_HO_FAILED] = {"intra_bsc_ho:failed", "Received Handover Fail messages"},
+ [BSC_CTR_INTRA_BSC_HO_ERROR] = {"intra_bsc_ho:error", "Re-assignment failed for other reason"},
[BSC_CTR_INTER_BSC_HO_OUT_ATTEMPTED] = {"interbsc_ho_out:attempted",
- "Attempts to handover to remote BSS."},
+ "Attempts to handover to remote BSS"},
[BSC_CTR_INTER_BSC_HO_OUT_COMPLETED] = {"interbsc_ho_out:completed",
- "Handover to remote BSS completed."},
- [BSC_CTR_INTER_BSC_HO_OUT_STOPPED] = {"interbsc_ho_out:stopped", "Connection ended during HO."},
- [BSC_CTR_INTER_BSC_HO_OUT_TIMEOUT] = {"interbsc_ho_out:timeout", "Handover timed out."},
+ "Handover to remote BSS completed"},
+ [BSC_CTR_INTER_BSC_HO_OUT_STOPPED] = {"interbsc_ho_out:stopped", "Connection ended during HO"},
+ [BSC_CTR_INTER_BSC_HO_OUT_TIMEOUT] = {"interbsc_ho_out:timeout", "Handover timed out"},
+ [BSC_CTR_INTER_BSC_HO_OUT_FAILED] = {"interbsc_ho_out:failed", "Received Handover Fail message"},
[BSC_CTR_INTER_BSC_HO_OUT_ERROR] = {"interbsc_ho_out:error",
- "Handover to remote BSS failed for other reason."},
+ "Handover to remote BSS failed for other reason"},
[BSC_CTR_INTER_BSC_HO_IN_ATTEMPTED] = {"interbsc_ho_in:attempted",
- "Attempts to handover from remote BSS."},
+ "Attempts to handover from remote BSS"},
[BSC_CTR_INTER_BSC_HO_IN_COMPLETED] = {"interbsc_ho_in:completed",
- "Handover from remote BSS completed."},
- [BSC_CTR_INTER_BSC_HO_IN_STOPPED] = {"interbsc_ho_in:stopped", "Connection ended during HO."},
+ "Handover from remote BSS completed"},
+ [BSC_CTR_INTER_BSC_HO_IN_STOPPED] = {"interbsc_ho_in:stopped", "Connection ended during HO"},
[BSC_CTR_INTER_BSC_HO_IN_NO_CHANNEL] = {"interbsc_ho_in:no_channel",
- "Failure to allocate lchan for HO."},
- [BSC_CTR_INTER_BSC_HO_IN_TIMEOUT] = {"interbsc_ho_in:timeout", "Handover from remote BSS timed out."},
- [BSC_CTR_INTER_BSC_HO_IN_FAILED] = {"interbsc_ho_in:failed", "Received Handover Fail message."},
+ "Failure to allocate lchan for HO"},
+ [BSC_CTR_INTER_BSC_HO_IN_TIMEOUT] = {"interbsc_ho_in:timeout", "Handover from remote BSS timed out"},
+ [BSC_CTR_INTER_BSC_HO_IN_FAILED] = {"interbsc_ho_in:failed", "Received Handover Fail message"},
[BSC_CTR_INTER_BSC_HO_IN_ERROR] = {"interbsc_ho_in:error",
- "Handover from remote BSS failed for other reason."},
+ "Handover from remote BSS failed for other reason"},
- [BSC_CTR_PAGING_ATTEMPTED] = {"paging:attempted", "Paging attempts for a subscriber."},
- [BSC_CTR_PAGING_DETACHED] = {"paging:detached", "Paging request send failures because no responsible BTS was found."},
- [BSC_CTR_PAGING_RESPONDED] = {"paging:responded", "Paging attempts with successful response."},
- [BSC_CTR_PAGING_NO_ACTIVE_PAGING] = {"paging:no_active_paging", "Paging response without an active paging request (arrived after paging expiration?)."},
+ [BSC_CTR_PAGING_ATTEMPTED] = {"paging:attempted", "Paging attempts for a subscriber"},
+ [BSC_CTR_PAGING_DETACHED] = {"paging:detached", "Paging request send failures because no responsible BTS was found"},
+ [BSC_CTR_PAGING_RESPONDED] = {"paging:responded", "Paging attempts with successful response"},
+ [BSC_CTR_PAGING_NO_ACTIVE_PAGING] = {"paging:no_active_paging", "Paging response without an active paging request (arrived after paging expiration?)"},
- [BSC_CTR_UNKNOWN_UNIT_ID] = {"abis:unknown_unit_id", "Connection attempts from unknown IPA CCM Unit ID."},
+ [BSC_CTR_UNKNOWN_UNIT_ID] = {"abis:unknown_unit_id", "Connection attempts from unknown IPA CCM Unit ID"},
[BSC_CTR_MSCPOOL_SUBSCR_NO_MSC] = {"mscpool:subscr:no_msc",
- "Complete Layer 3 requests lost because no connected MSC is found available."},
+ "Complete Layer 3 requests lost because no connected MSC is found available"},
[BSC_CTR_MSCPOOL_EMERG_FORWARDED] = {"mscpool:emerg:forwarded",
- "Emergency call requests forwarded to an MSC (see also per-MSC counters)"},
+ "Emergency call requests forwarded to an MSC (see also per-MSC counters"},
[BSC_CTR_MSCPOOL_EMERG_LOST] = {"mscpool:emerg:lost",
- "Emergency call requests lost because no MSC was found available."},
+ "Emergency call requests lost because no MSC was found available"},
};
@@ -1059,6 +1092,11 @@ enum {
BSC_STAT_NUM_BTS_TOTAL,
};
+/* BTS counter index if a BTS could not be found
+ * Currently we are limited to bts 0 - 255 in the VTY, but that might change in
+ * the future so use 2**16 */
+#define BTS_STAT_IDX_UNKNOWN (UINT16_MAX + 1)
+
struct gsm_tz {
int override; /* if 0, use system's time zone instead. */
int hr; /* hour */
@@ -1093,6 +1131,11 @@ struct gsm_network {
struct llist_head bts_list;
struct llist_head bts_rejected;
+ /* BTS-based counters when we can't find the actual BTS
+ * e.g. when conn->lchan is NULL */
+ struct rate_ctr_group *bts_unknown_ctrs;
+ struct osmo_stat_item_group *bts_unknown_statg;
+
/* see gsm_network_T_defs */
struct osmo_tdef *T_defs;
diff --git a/include/osmocom/bsc/lchan_fsm.h b/include/osmocom/bsc/lchan_fsm.h
index 55ab02400..9fe7db107 100644
--- a/include/osmocom/bsc/lchan_fsm.h
+++ b/include/osmocom/bsc/lchan_fsm.h
@@ -18,6 +18,8 @@ enum lchan_fsm_state {
LCHAN_ST_WAIT_TS_READY,
LCHAN_ST_WAIT_ACTIV_ACK, /*< After RSL Chan Act Ack, lchan is active but RTP not configured. */
LCHAN_ST_WAIT_RLL_RTP_ESTABLISH,
+ LCHAN_ST_WAIT_RR_CHAN_MODE_MODIFY_ACK,
+ LCHAN_ST_WAIT_RSL_CHAN_MODE_MODIFY_ACK,
LCHAN_ST_ESTABLISHED, /*< Active and RTP is fully configured. */
LCHAN_ST_WAIT_RLL_RTP_RELEASED,
LCHAN_ST_WAIT_BEFORE_RF_RELEASE,
@@ -40,10 +42,11 @@ enum lchan_fsm_event {
LCHAN_EV_RLL_REL_CONF,
LCHAN_EV_RSL_RF_CHAN_REL_ACK,
LCHAN_EV_RLL_ERR_IND,
-
- /* FIXME: not yet implemented: Chan Mode Modify, see assignment_fsm_start(). */
- LCHAN_EV_CHAN_MODE_MODIF_ACK,
- LCHAN_EV_CHAN_MODE_MODIF_ERROR,
+ LCHAN_EV_RR_CHAN_MODE_MODIFY_ACK,
+ LCHAN_EV_RR_CHAN_MODE_MODIFY_ERROR,
+ LCHAN_EV_RSL_CHAN_MODE_MODIFY_ACK,
+ LCHAN_EV_RSL_CHAN_MODE_MODIFY_NACK,
+ LCHAN_EV_REQUEST_MODE_MODIFY,
};
void lchan_fsm_init();
@@ -71,3 +74,5 @@ bool lchan_may_receive_data(struct gsm_lchan *lchan);
void lchan_forget_conn(struct gsm_lchan *lchan);
void lchan_set_last_error(struct gsm_lchan *lchan, const char *fmt, ...);
+
+void lchan_fsm_skip_error(struct gsm_lchan *lchan);
diff --git a/include/osmocom/bsc/lchan_select.h b/include/osmocom/bsc/lchan_select.h
index 865181bf5..41e7015cf 100644
--- a/include/osmocom/bsc/lchan_select.h
+++ b/include/osmocom/bsc/lchan_select.h
@@ -4,3 +4,4 @@
struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type);
struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts,
enum gsm48_chan_mode chan_mode, enum channel_rate chan_rate);
+struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type);
diff --git a/include/osmocom/bsc/osmo_bsc.h b/include/osmocom/bsc/osmo_bsc.h
index afc319b25..13ccdd7b2 100644
--- a/include/osmocom/bsc/osmo_bsc.h
+++ b/include/osmocom/bsc/osmo_bsc.h
@@ -19,12 +19,6 @@ struct gsm_bts;
struct bsc_api *osmo_bsc_api();
-int bsc_queue_for_msc(struct gsm_subscriber_connection *conn, struct msgb *msg);
-int bsc_open_connection(struct gsm_subscriber_connection *sccp, struct msgb *msg);
-enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn,
- struct bsc_msc_data *msc, int send_ping);
-int bsc_delete_connection(struct gsm_subscriber_connection *sccp);
-
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
diff --git a/include/osmocom/bsc/osmo_bsc_grace.h b/include/osmocom/bsc/osmo_bsc_grace.h
index d78e41c82..07dce8cd5 100644
--- a/include/osmocom/bsc/osmo_bsc_grace.h
+++ b/include/osmocom/bsc/osmo_bsc_grace.h
@@ -27,10 +27,5 @@
struct bsc_msc_data;
int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts);
-int bsc_grace_paging_request(enum signal_rf rf_policy,
- struct bsc_subscr *subscr,
- int chan_needed,
- struct bsc_msc_data *msc,
- struct gsm_bts *bts);
#endif
diff --git a/include/osmocom/bsc/signal.h b/include/osmocom/bsc/signal.h
index 952e03ce1..c7d7fe129 100644
--- a/include/osmocom/bsc/signal.h
+++ b/include/osmocom/bsc/signal.h
@@ -73,6 +73,7 @@ enum signal_nm {
S_NM_OM2K_CONF_RES, /* OM2K Configuration Result */
S_NM_OPSTART_ACK, /* Received OPSTART ACK, arg is struct msgb *oml_msg */
S_NM_GET_ATTR_REP, /* Received Get Attributes Response, arg is struct msgb *oml_msg */
+ S_NM_SET_RADIO_ATTR_ACK, /* Received Set Radio Carrier Attributes Ack, arg is struct msgb *oml_msg */
};
/* SS_LCHAN signals */
diff --git a/include/osmocom/bsc/smscb.h b/include/osmocom/bsc/smscb.h
index 22a258da9..f48c1a170 100644
--- a/include/osmocom/bsc/smscb.h
+++ b/include/osmocom/bsc/smscb.h
@@ -2,6 +2,7 @@
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/sockaddr_str.h>
#include <osmocom/netif/stream.h>
#include <osmocom/gsm/cbsp.h>
@@ -27,21 +28,25 @@ int bts_smscb_rx_cbch_load_ind(struct gsm_bts *bts, bool cbch_extended, bool is_
uint8_t slot_count);
void bts_cbch_timer_schedule(struct gsm_bts *bts);
+enum bsc_cbc_link_mode {
+ BSC_CBC_LINK_MODE_DISABLED = 0,
+ BSC_CBC_LINK_MODE_SERVER,
+ BSC_CBC_LINK_MODE_CLIENT,
+};
+
+extern const struct value_string bsc_cbc_link_mode_names[];
+static inline const char *bsc_cbc_link_mode_name(enum bsc_cbc_link_mode val)
+{ return get_value_string(bsc_cbc_link_mode_names, val); }
+
+extern const struct osmo_sockaddr_str bsc_cbc_default_server_local_addr;
+
/* cbsp_link.c */
struct bsc_cbc_link {
struct gsm_network *net;
- struct {
- /* hostname/IP of CBC */
- char *cbc_hostname;
- /* TCP port (Default: 48049) of CBC */
- int cbc_port;
- /* local listening port (0 for disabling local server) */
- int listen_port;
- /* local listening hostname/IP */
- char *listen_hostname;
- } config;
+ enum bsc_cbc_link_mode mode;
/* for handling inbound TCP connections */
struct {
+ struct osmo_sockaddr_str local_addr;
struct osmo_stream_srv *srv;
struct osmo_stream_srv_link *link;
char *sock_name;
@@ -49,6 +54,8 @@ struct bsc_cbc_link {
} server;
/* for handling outbound TCP connections */
struct {
+ struct osmo_sockaddr_str remote_addr;
+ struct osmo_sockaddr_str local_addr;
struct osmo_stream_cli *cli;
char *sock_name;
struct msgb *msg;
diff --git a/include/osmocom/bsc/vty.h b/include/osmocom/bsc/vty.h
index 10ce16b2d..ba44f5e27 100644
--- a/include/osmocom/bsc/vty.h
+++ b/include/osmocom/bsc/vty.h
@@ -25,6 +25,8 @@ enum bsc_vty_node {
OM2K_CON_GROUP_NODE,
BSC_NODE,
CBC_NODE,
+ CBC_SERVER_NODE,
+ CBC_CLIENT_NODE,
};
struct log_info;
diff --git a/src/osmo-bsc/a_reset.c b/src/osmo-bsc/a_reset.c
index 713be86fb..9446d1311 100644
--- a/src/osmo-bsc/a_reset.c
+++ b/src/osmo-bsc/a_reset.c
@@ -22,12 +22,14 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/fsm.h>
+#include <osmocom/core/signal.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/osmo_bsc_sigtran.h>
+#include <osmocom/bsc/signal.h>
#define RESET_RESEND_INTERVAL 2 /* sec */
#define RESET_RESEND_TIMER_NO 4 /* See also 3GPP TS 48.008 Chapter 3.1.4.1.3.1 */
@@ -83,8 +85,10 @@ static void fsm_disc_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)
struct bsc_msc_data *msc = reset_ctx->priv;
LOGPFSML(fi, LOGL_NOTICE, "BSSMAP MSC assocation is down, reconnecting...\n");
- if (prev_state != ST_DISC)
+ if (prev_state != ST_DISC) {
osmo_stat_item_dec(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);
+ osmo_signal_dispatch(SS_MSC, S_MSC_LOST, msc);
+ }
}
/* Connected state event handler */
@@ -116,8 +120,10 @@ static void fsm_conn_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)
struct bsc_msc_data *msc = reset_ctx->priv;
LOGPFSML(fi, LOGL_NOTICE, "BSSMAP MSC assocation is up.\n");
- if (prev_state != ST_CONN)
+ if (prev_state != ST_CONN) {
osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);
+ osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, msc);
+ }
}
/* Timer callback to retransmit the reset signal */
diff --git a/src/osmo-bsc/abis_nm.c b/src/osmo-bsc/abis_nm.c
index d88ce248a..469113750 100644
--- a/src/osmo-bsc/abis_nm.c
+++ b/src/osmo-bsc/abis_nm.c
@@ -163,6 +163,7 @@ int _abis_nm_sendmsg(struct msgb *msg)
if (!msg->dst) {
LOGP(DNM, LOGL_ERROR, "%s: msg->dst == NULL\n", __func__);
+ msgb_free(msg);
return -EINVAL;
}
@@ -431,7 +432,7 @@ static int rx_fail_evt_rep(struct msgb *mb, struct gsm_bts *bts)
sd = abis_nm_fail_evt_rep_parse(mb, bts);
if (!sd) {
- LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: failed to parse Failure Event Report\n", bts->nr);
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Failed to parse Failure Event Report\n");
return -EINVAL;
}
e_type = sd->parsed.event_type;
@@ -449,8 +450,7 @@ static int rx_fail_evt_rep(struct msgb *mb, struct gsm_bts *bts)
log_oml_fail_rep(bts, e_type, severity, p_val, p_text);
};
} else {
- LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: Failure Event Report without "
- "Probable Cause?!\n", bts->nr);
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Failure Event Report without Probable Cause?!\n");
rc = -EINVAL;
}
@@ -535,17 +535,19 @@ static inline bool handle_attr(const struct gsm_bts *bts, enum bts_attribute id,
}
/* Parse Attribute Response Info - return pointer to the actual content */
-static inline const uint8_t *parse_attr_resp_info_unreported(uint8_t bts_nr, const uint8_t *ari, uint16_t ari_len, uint16_t *out_len)
+static inline const uint8_t *parse_attr_resp_info_unreported(const struct abis_om_fom_hdr *foh,
+ const uint8_t *ari, uint16_t ari_len,
+ uint16_t *out_len)
{
uint8_t num_unreported = ari[0], i;
- DEBUGP(DNM, "BTS%u Get Attributes Response Info: %u bytes total with %u unreported attributes\n",
- bts_nr, ari_len, num_unreported);
+ DEBUGPFOH(DNM, foh, "Get Attributes Response Info: %u bytes total "
+ "with %u unreported attributes\n", ari_len, num_unreported);
/* +1 because we have to account for number of unreported attributes, prefixing the list: */
for (i = 0; i < num_unreported; i++)
- LOGP(DNM, LOGL_ERROR, "BTS%u Attribute %s is unreported\n",
- bts_nr, get_value_string(abis_nm_att_names, ari[i + 1]));
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Attribute %s is unreported\n",
+ get_value_string(abis_nm_att_names, ari[i + 1]));
/* the data starts right after the list of unreported attributes + space for length of that list */
if (out_len)
@@ -601,7 +603,7 @@ static int parse_attr_resp_info_attr(struct gsm_bts *bts, const struct gsm_bts_t
/* this attribute does not make sense on BTS level, only on TRX level */
if (trx && TLVP_PRES_LEN(tp, NM_ATT_MANUF_STATE, 1)) {
data = TLVP_VAL(tp, NM_ATT_MANUF_STATE);
- LOGPFOH(DNM, LOGL_NOTICE, foh, "%s Get Attributes Response: nominal power is %u\n", gsm_trx_name(trx), *data);
+ LOGPFOH(DNM, LOGL_NOTICE, foh, "Get Attributes Response: nominal power is %u\n", *data);
}
/* Parse Attribute Response Info content for 3GPP TS 52.021 ยง9.4.61 SW Configuration */
@@ -614,33 +616,31 @@ static int parse_attr_resp_info_attr(struct gsm_bts *bts, const struct gsm_bts_t
for (i = 0; i < rc; i++) {
if (!handle_attr(bts, str2btsattr((const char *)sw_descr[i].file_id),
sw_descr[i].file_version, sw_descr[i].file_version_len)) {
- LOGPFOH(DNM, LOGL_NOTICE, foh, "BTS%u: ARI reported sw[%d/%d]: %s "
- "is %s\n", bts->nr, i, rc, sw_descr[i].file_id,
- sw_descr[i].file_version);
+ LOGPFOH(DNM, LOGL_NOTICE, foh, "ARI reported sw[%d/%d]: %s is %s\n",
+ i, rc, sw_descr[i].file_id, sw_descr[i].file_version);
}
}
} else {
- LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: failed to parse SW-Config part of "
- "Get Attribute Response Info: %s\n", bts->nr, strerror(-rc));
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Failed to parse SW-Config part of "
+ "Get Attribute Response Info: %s\n", strerror(-rc));
}
}
if (abis_nm_tlv_attr_primary_oml(tp, &ia, &port) == 0) {
LOGPFOH(DNM, LOGL_NOTICE, foh,
- "BTS%u Get Attributes Response: Primary OML IP is %s:%u\n",
- bts->nr, inet_ntoa(ia), port);
+ "Get Attributes Response: Primary OML IP is %s:%u\n",
+ inet_ntoa(ia), port);
}
if (abis_nm_tlv_attr_unit_id(tp, unit_id, sizeof(unit_id)) == 0) {
- LOGPFOH(DNM, LOGL_NOTICE, foh, "BTS%u Get Attributes Response: Unit ID is %s\n",
- bts->nr, unit_id);
+ LOGPFOH(DNM, LOGL_NOTICE, foh, "Get Attributes Response: Unit ID is %s\n", unit_id);
}
/* nanoBTS provides Get Attribute Response Info at random position and only the unreported part of it. */
if (TLVP_PRES_LEN(tp, NM_ATT_GET_ARI, 1)) {
data = TLVP_VAL(tp, NM_ATT_GET_ARI);
len = TLVP_LEN(tp, NM_ATT_GET_ARI);
- parse_attr_resp_info_unreported(bts->nr, data, len, NULL);
+ parse_attr_resp_info_unreported(foh, data, len, NULL);
}
return 0;
@@ -653,12 +653,12 @@ static int parse_attr_resp_info(struct gsm_bts *bts, const struct gsm_bts_trx *t
uint16_t data_len;
if (!TLVP_PRES_LEN(tp, NM_ATT_GET_ARI, 1)) {
- LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: Get Attr Response without Response Info?!\n",
- bts->nr);
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Get Attr Response without Response Info?!\n");
return -EINVAL;
}
- data = parse_attr_resp_info_unreported(bts->nr, TLVP_VAL(tp, NM_ATT_GET_ARI), TLVP_LEN(tp, NM_ATT_GET_ARI),
+ data = parse_attr_resp_info_unreported(foh, TLVP_VAL(tp, NM_ATT_GET_ARI),
+ TLVP_LEN(tp, NM_ATT_GET_ARI),
&data_len);
/* After parsing unreported attribute id list inside Response info,
@@ -678,7 +678,7 @@ static int abis_nm_rx_get_attr_resp(struct msgb *mb, const struct gsm_bts_trx *t
struct tlv_parsed tp;
int rc;
- DEBUGPFOH(DNM, foh, "Get Attributes Response for BTS%u\n", bts->nr);
+ DEBUGPFOH(DNM, foh, "Get Attributes Response\n");
abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh));
@@ -723,7 +723,7 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
LOGPFOH(DNM, LOGL_ERROR, foh, "SW config not found! Can't continue.\n");
return -EINVAL;
} else {
- DEBUGP(DNM, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len));
+ DEBUGPFOH(DNM, foh, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len));
}
/* Parse up to two sw descriptions from the data */
@@ -803,13 +803,11 @@ struct gsm_bts_trx_ts *abis_nm_get_ts(const struct msgb *oml_msg)
struct gsm_bts_trx *trx = gsm_bts_trx_num(sign_link->trx->bts, foh->obj_inst.trx_nr);
uint8_t ts_nr = foh->obj_inst.ts_nr;
if (!trx) {
- LOGP(DNM, LOGL_ERROR, "%s Channel OPSTART ACK for sign_link without trx\n",
- abis_nm_dump_foh(foh));
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Channel OPSTART ACK for sign_link without trx\n");
return NULL;
}
if (ts_nr >= ARRAY_SIZE(trx->ts)) {
- LOGP(DNM, LOGL_ERROR, "bts%u-trx%u %s Channel OPSTART ACK for non-existent TS\n",
- trx->bts->nr, trx->nr, abis_nm_dump_foh(foh));
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Channel OPSTART ACK for non-existent TS\n");
return NULL;
}
return &trx->ts[ts_nr];
@@ -818,12 +816,19 @@ struct gsm_bts_trx_ts *abis_nm_get_ts(const struct msgb *oml_msg)
static int abis_nm_rx_opstart_ack(struct msgb *mb)
{
struct abis_om_fom_hdr *foh = msgb_l3(mb);
- struct e1inp_sign_link *sign_link = mb->dst;
- DEBUGPFOH(DNM, foh, "bts=%u Opstart ACK\n", sign_link->trx->bts->nr);
+ DEBUGPFOH(DNM, foh, "Opstart ACK\n");
osmo_signal_dispatch(SS_NM, S_NM_OPSTART_ACK, mb);
return 0;
}
+static int abis_nm_rx_set_radio_attr_ack(struct msgb *mb)
+{
+ struct abis_om_fom_hdr *foh = msgb_l3(mb);
+ DEBUGPFOH(DNM, foh, "Set Radio Carrier Attributes ACK\n");
+ osmo_signal_dispatch(SS_NM, S_NM_SET_RADIO_ATTR_ACK, mb);
+ return 0;
+}
+
bool all_trx_rsl_connected_unlocked(const struct gsm_bts *bts)
{
const struct gsm_bts_trx *trx;
@@ -944,6 +949,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
break;
case NM_MT_SET_RADIO_ATTR_ACK:
DEBUGPFOH(DNM, foh, "Set Radio Carrier Attributes ACK\n");
+ abis_nm_rx_set_radio_attr_ack(mb);
break;
case NM_MT_CONN_MDROP_LINK_ACK:
DEBUGPFOH(DNM, foh, "CONN MDROP LINK ACK\n");
@@ -999,7 +1005,7 @@ static int abis_nm_rcvmsg_manuf(struct msgb *mb)
break;
default:
LOGP(DNM, LOGL_ERROR, "don't know how to parse OML for this "
- "BTS type (%u)\n", bts_type);
+ "BTS type (%s)\n", btstype2str(bts_type));
rc = 0;
break;
}
@@ -1500,7 +1506,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
switch (foh->msg_type) {
case NM_MT_LOAD_END_ACK:
sw_close_file(sw);
- DEBUGPFOH(DNM, foh, "Software Load End (BTS %u)\n", sw->bts->nr);
+ DEBUGPFOH(DNM, foh, "Software Load End\n");
sw->state = SW_STATE_NONE;
if (sw->cbfn)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
@@ -1604,7 +1610,7 @@ int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname,
break;
case GSM_BTS_TYPE_UNKNOWN:
default:
- LOGPC(DNM, LOGL_ERROR, "Software Load not properly implemented.\n");
+ LOGP(DNM, LOGL_ERROR, "Software Load not properly implemented.\n");
return -1;
break;
}
@@ -1765,23 +1771,24 @@ int abis_nm_disc_terr_traf(struct abis_nm_h *h, struct abis_om_obj_inst *inst,
int abis_nm_get_attr(struct gsm_bts *bts, uint8_t obj_class, uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
const uint8_t *attr, uint8_t attr_len)
{
+ const struct abis_om_fom_hdr *foh;
struct abis_om_hdr *oh;
struct msgb *msg;
if (bts->type != GSM_BTS_TYPE_OSMOBTS && bts->type != GSM_BTS_TYPE_NANOBTS) {
- LOGPC(DNM, LOGL_NOTICE, "Getting attributes from BTS%d type %s is not supported.\n",
- bts->nr, btstype2str(bts->type));
+ LOGP(DNM, LOGL_NOTICE, "Getting attributes from BTS%d type %s is not supported.\n",
+ bts->nr, btstype2str(bts->type));
return -EINVAL;
}
- LOG_BTS(bts, DNM, LOGL_DEBUG, "Get Attr (trx=%u)\n", trx_nr);
-
msg = nm_msgb_alloc();
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
- fill_om_fom_hdr(oh, TL16V_GROSS_LEN(attr_len), NM_MT_GET_ATTR, obj_class,
- bts_nr, trx_nr, ts_nr);
+ foh = fill_om_fom_hdr(oh, TL16V_GROSS_LEN(attr_len), NM_MT_GET_ATTR,
+ obj_class, bts_nr, trx_nr, ts_nr);
msgb_tl16v_put(msg, NM_ATT_LIST_REQ_ATTR, attr_len, attr);
+ DEBUGPFOH(DNM, foh, "Tx Get Attributes (Request)\n");
+
return abis_nm_sendmsg(bts, msg);
}
@@ -2007,7 +2014,7 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
foh = fill_om_fom_hdr(oh, 0, NM_MT_SET_CHAN_ATTR, NM_OC_CHANNEL, bts->bts_nr,
ts->trx->nr, ts->nr);
- DEBUGPFOH(DNM, foh, "Set Chan Attr %s\n", gsm_ts_name(ts));
+ DEBUGPFOH(DNM, foh, "Set Chan Attr\n");
if (verify_chan_comb(ts, chan_comb, &reason) < 0) {
LOGPFOH(DNM, LOGL_ERROR, foh, "Invalid Channel Combination %d on %s. Reason: %s\n",
chan_comb, gsm_ts_name(ts), reason);
@@ -2044,8 +2051,8 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
/* BS-11 cannot handle more than 255 ARFCNs, because L is 8 bit.
* This is unlikely to happen, but better check than sorry... */
if (bts->type == GSM_BTS_TYPE_BS11 && n > 0xff) {
- LOGPFOH(DNM, LOGL_ERROR, foh, "%s cannot handle %u (more than 255) "
- "hopping channels\n", gsm_bts_name(bts), n);
+ LOGPFOH(DNM, LOGL_ERROR, foh, "Cannot handle %u (more than 255) "
+ "hopping channels\n", n);
msgb_free(msg);
return -EINVAL;
}
@@ -2186,8 +2193,11 @@ int abis_nm_perform_test(struct gsm_bts *bts, uint8_t obj_class,
DEBUGP(DNM, "PERFORM TEST %s\n", abis_nm_test_name(test_nr));
- if (!msg)
+ if (!msg) {
msg = nm_msgb_alloc();
+ if (!msg)
+ return -ENOMEM;
+ }
msgb_tv_push(msg, NM_ATT_AUTON_REPORT, auton_report);
msgb_tv_push(msg, NM_ATT_TEST_NO, test_nr);
diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c
index 5c8b378ec..a3f689add 100644
--- a/src/osmo-bsc/abis_om2000.c
+++ b/src/osmo-bsc/abis_om2000.c
@@ -2122,6 +2122,7 @@ enum om2k_trx_state {
OM2K_TRX_S_WAIT_TX,
OM2K_TRX_S_WAIT_RX,
OM2K_TRX_S_WAIT_TS,
+ OM2K_TRX_S_SEND_SI,
OM2K_TRX_S_DONE,
OM2K_TRX_S_ERROR
};
@@ -2195,14 +2196,22 @@ static void om2k_trx_s_wait_ts(struct osmo_fsm_inst *fi, uint32_t event, void *d
&ts->rbs2000.om2k_mo);
} else {
/* only after all 8 TS */
- osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_DONE, 0, 0);
+ osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_SEND_SI, 0, 0);
}
}
-static void om2k_trx_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+static void om2k_trx_s_send_si(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct om2k_trx_fsm_priv *otfp = fi->priv;
- gsm_bts_trx_set_system_infos(otfp->trx);
+
+ if (gsm_bts_trx_set_system_infos(otfp->trx) == 0)
+ osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_DONE, 0, 0);
+ else
+ osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_ERROR, 0, 0);
+}
+
+static void om2k_trx_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
}
@@ -2237,10 +2246,16 @@ static const struct osmo_fsm_state om2k_trx_states[] = {
[OM2K_TRX_S_WAIT_TS] = {
.in_event_mask = S(OM2K_TRX_EVT_TS_DONE),
.out_state_mask = S(OM2K_TRX_S_ERROR) |
- S(OM2K_TRX_S_DONE),
+ S(OM2K_TRX_S_SEND_SI),
.name = "WAIT-TS",
.action = om2k_trx_s_wait_ts,
},
+ [OM2K_TRX_S_SEND_SI] = {
+ .out_state_mask = S(OM2K_TRX_S_ERROR) |
+ S(OM2K_TRX_S_DONE),
+ .name = "SEND-SI",
+ .onenter = om2k_trx_s_send_si,
+ },
[OM2K_TRX_S_DONE] = {
.name = "DONE",
.onenter = om2k_trx_s_done_onenter,
diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c
index 1ffdd06a5..858c683e1 100644
--- a/src/osmo-bsc/abis_rsl.c
+++ b/src/osmo-bsc/abis_rsl.c
@@ -1186,10 +1186,12 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
case RSL_MT_MODE_MODIFY_ACK:
LOG_LCHAN(msg->lchan, LOGL_DEBUG, "CHANNEL MODE MODIFY ACK\n");
count_codecs(sign_link->trx->bts, msg->lchan);
+ osmo_fsm_inst_dispatch(msg->lchan->fi, LCHAN_EV_RSL_CHAN_MODE_MODIFY_ACK, NULL);
break;
case RSL_MT_MODE_MODIFY_NACK:
LOG_LCHAN(msg->lchan, LOGL_DEBUG, "CHANNEL MODE MODIFY NACK\n");
rate_ctr_inc(&sign_link->trx->bts->bts_ctrs->ctr[BTS_CTR_MODE_MODIFY_NACK]);
+ osmo_fsm_inst_dispatch(msg->lchan->fi, LCHAN_EV_RSL_CHAN_MODE_MODIFY_NACK, NULL);
break;
case RSL_MT_IPAC_PDCH_ACT_ACK:
rc = rsl_rx_ipacc_pdch(msg, "ACT ACK", TS_EV_PDCH_ACT_ACK);
@@ -1305,7 +1307,15 @@ static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
/* we need to subtract 1 byte from sizeof(*iar) since ia includes the l2_plen field */
iar->l2_plen = GSM48_LEN2PLEN((sizeof(*iar)-1));
- return rsl_imm_assign_cmd(bts, sizeof(*iar), (uint8_t *) iar);
+ /* IAR Rest Octets:
+ * 0... .... = Extended RA: Not Present
+ * .0.. .... = Extended RA: Not Present
+ * ..0. .... = Extended RA: Not Present
+ * ...0 .... = Extended RA: Not Present
+ * .... L... = Additions in Rel-13: Not Present */
+ iar->rest[0] = GSM_MACBLOCK_PADDING & 0x0f;
+
+ return rsl_imm_assign_cmd(bts, sizeof(*iar) + 1, buf);
}
int rsl_tx_imm_ass_rej(struct gsm_bts *bts, struct gsm48_req_ref *rqd_ref)
@@ -1320,120 +1330,340 @@ int rsl_tx_imm_ass_rej(struct gsm_bts *bts, struct gsm48_req_ref *rqd_ref)
return rsl_send_imm_ass_rej(bts, rqd_ref, wait_ind);
}
+struct chan_rqd {
+ struct llist_head entry;
+ struct gsm_bts *bts;
+ struct gsm48_req_ref ref;
+ enum gsm_chreq_reason_t reason;
+ uint8_t ta;
+ /* set to true to mark that the release of the release_lchan is in progress */
+ struct gsm_lchan *release_lchan;
+ time_t timestamp;
+};
+
/* Handle packet channel rach requests */
-static int rsl_rx_pchan_rqd(struct msgb *msg, struct gsm_bts *bts)
+static int rsl_rx_pchan_rqd(struct chan_rqd *rqd)
{
- struct gsm48_req_ref *rqd_ref;
- struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
- rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
- uint8_t ra = rqd_ref->ra;
uint8_t t1, t2, t3;
uint32_t fn;
uint8_t rqd_ta;
uint8_t is_11bit;
/* Process rach request and forward contained information to PCU */
- if (ra == 0x7F) {
+ if (rqd->ref.ra == 0x7F) {
is_11bit = 1;
/* FIXME: Also handle 11 bit rach requests */
- LOGP(DRSL, LOGL_ERROR, "BTS %d eleven bit access burst not supported yet!\n",bts->nr);
+ LOGP(DRSL, LOGL_ERROR, "BTS %d eleven bit access burst not supported yet!\n",rqd->bts->nr);
return -EINVAL;
} else {
is_11bit = 0;
- t1 = rqd_ref->t1;
- t2 = rqd_ref->t2;
- t3 = rqd_ref->t3_low | (rqd_ref->t3_high << 3);
+ t1 = rqd->ref.t1;
+ t2 = rqd->ref.t2;
+ t3 = rqd->ref.t3_low | (rqd->ref.t3_high << 3);
fn = (51 * ((t3-t2) % 26) + t3 + 51 * 26 * t1);
-
- rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
+ rqd_ta = rqd->ta;
}
- return pcu_tx_rach_ind(bts, rqd_ta, ra, fn, is_11bit,
+ return pcu_tx_rach_ind(rqd->bts, rqd_ta, rqd->ref.ra, fn, is_11bit,
GSM_L1_BURST_TYPE_ACCESS_0);
}
+/* Protect against RACH DoS attack: If an excessive amount of RACH requests queues up it is likely that the current BTS
+ * is under RACH DoS attack. To prevent excessive memory usage, remove all expired or at least one of the oldest channel
+ * requests from the queue to prevent the queue from growing indefinetly. */
+static void reduce_rach_dos(struct gsm_bts *bts)
+{
+ int rlt = gsm_bts_get_radio_link_timeout(bts);
+ time_t timestamp_current = time(NULL);
+ struct chan_rqd *rqd;
+ struct chan_rqd *rqd_tmp;
+ unsigned int rqd_count = 0;
+
+ /* Drop all expired channel requests in the list */
+ llist_for_each_entry_safe(rqd, rqd_tmp, &bts->chan_rqd_queue, entry) {
+ /* If the channel request is older than the radio link timeout we drop it. This also means that the
+ * queue is under its overflow limit again. */
+ if (timestamp_current - rqd->timestamp > rlt) {
+ LOG_BTS(bts, DRSL, LOGL_INFO, "CHAN RQD: tossing expired channel request"
+ "(ra=0x%02x, neci=0x%02x, chreq_reason=0x%02x)\n",
+ rqd->ref.ra, bts->network->neci, rqd->reason);
+ llist_del(&rqd->entry);
+ talloc_free(rqd);
+ } else {
+ rqd_count++;
+ }
+ }
+
+ /* If we find more than 255 (256) unexpired channel requests in the queue it is very likely that there is a
+ * problem with RACH dos on this BTS. We drop the first entry in the list to clip the growth of the list. */
+ if (rqd_count > 255) {
+ LOG_BTS(bts, DRSL, LOGL_INFO, "CHAN RQD: more than 255 queued RACH requests -- RACH DoS attack?\n");
+ rqd = llist_first_entry(&bts->chan_rqd_queue, struct chan_rqd, entry);
+ llist_del(&rqd->entry);
+ talloc_free(rqd);
+ }
+}
+
+/* Flush all channel requests pending on this BTS */
+void abis_rsl_chan_rqd_queue_flush(struct gsm_bts *bts)
+{
+ struct chan_rqd *rqd;
+ struct chan_rqd *rqd_tmp;
+
+ llist_for_each_entry_safe(rqd, rqd_tmp, &bts->chan_rqd_queue, entry) {
+ llist_del(&rqd->entry);
+ talloc_free(rqd);
+ }
+}
+
/* MS has requested a channel on the RACH */
static int rsl_rx_chan_rqd(struct msgb *msg)
{
- struct lchan_activate_info info;
struct e1inp_sign_link *sign_link = msg->dst;
struct gsm_bts *bts = sign_link->trx->bts;
struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
- struct gsm48_req_ref *rqd_ref;
- enum gsm_chan_t lctype;
- enum gsm_chreq_reason_t chreq_reason;
- struct gsm_lchan *lchan;
- uint8_t rqd_ta;
+ struct chan_rqd *rqd;
+
+ reduce_rach_dos(bts);
+
+ rqd = talloc_zero(bts, struct chan_rqd);
+ OSMO_ASSERT(rqd);
+
+ rqd->bts = bts;
+ rqd->timestamp = time(NULL);
/* parse request reference to be used in immediate assign */
- if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
+ if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE) {
+ talloc_free(rqd);
return -EINVAL;
-
- rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
+ }
+ memcpy(&rqd->ref, &rqd_hdr->data[1], sizeof(rqd->ref));
/* parse access delay and use as TA */
- if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
+ if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY) {
+ talloc_free(rqd);
return -EINVAL;
- rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
+ }
+ rqd->ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
/* Determine channel request cause code */
- chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
+ rqd->reason = get_reason_by_chreq(rqd->ref.ra, bts->network->neci);
LOG_BTS(bts, DRSL, LOGL_INFO, "CHAN RQD: reason: %s (ra=0x%02x, neci=0x%02x, chreq_reason=0x%02x)\n",
- get_value_string(gsm_chreq_descs, chreq_reason), rqd_ref->ra, bts->network->neci, chreq_reason);
+ get_value_string(gsm_chreq_descs, rqd->reason), rqd->ref.ra, bts->network->neci, rqd->reason);
+
+ rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_TOTAL]);
+
+ /* Enqueue request */
+ llist_add_tail(&rqd->entry, &bts->chan_rqd_queue);
+
+ /* Forward the request directly. Most request will be finished with one attempt so no queuing will be
+ * necessary. */
+ abis_rsl_chan_rqd_queue_poll(bts);
+
+ return 0;
+}
+
+/* Find any busy TCH/H or TCH/F lchan */
+static struct gsm_lchan *get_any_lchan(struct gsm_bts *bts)
+{
+ int trx_nr;
+ int ts_nr;
+ struct gsm_bts_trx *trx;
+ struct gsm_bts_trx_ts *ts;
+ struct gsm_lchan *lchan_est = NULL;
+ struct gsm_lchan *lchan_any = NULL;
+ struct gsm_lchan *lchan;
+
+ for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
+ trx = gsm_bts_trx_num(bts, trx_nr);
+ for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
+ ts = &trx->ts[ts_nr];
+ ts_for_each_lchan(lchan, ts) {
+ if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H) {
+ if (bts->chan_alloc_reverse) {
+ if (lchan->fi->state == LCHAN_ST_ESTABLISHED)
+ lchan_est = lchan;
+ else
+ lchan_any = lchan;
+ } else {
+ if (lchan->fi->state == LCHAN_ST_ESTABLISHED) {
+ if (!lchan_est)
+ lchan_est = lchan;
+ } else {
+ if (!lchan_any)
+ lchan_any = lchan;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (lchan_est)
+ return lchan_est;
+ else if (lchan_any)
+ return lchan_any;
+ return NULL;
+}
+
+/* Ensure that an incoming emergency call gets priority, if all voice channels are busy, terminate one regular call.
+ * Return true if freeing of a busy lchan is in progress, but not done yet, return false when done (either successfully
+ * or unsuccessfully). */
+static bool force_free_lchan_for_emergency(struct chan_rqd *rqd)
+{
+ /* If the request is not about an emergency call, we may exit early, without doing anything. */
+ if (rqd->reason != GSM_CHREQ_REASON_EMERG)
+ return false;
+
+ /* First check the situation on the BTS, if we have TCH/H or TCH/F resources available for another (EMERGENCY)
+ * call. If yes, then no (further) action has to be carried out. */
+ if (lchan_avail_by_type(rqd->bts, GSM_LCHAN_TCH_F)) {
+ LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+ "CHAN RQD/EMERGENCY-PRIORITY: at least one TCH/F is (now) available!\n");
+ return false;
+ }
+ if (lchan_avail_by_type(rqd->bts, GSM_LCHAN_TCH_H)) {
+ LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+ "CHAN RQD/EMERGENCY-PRIORITY: at least one TCH/H is (now) available!\n");
+ return false;
+ }
+
+ /* No free TCH/F or TCH/H was found, we now select one of the busy lchans and initate a release on that lchan.
+ * This will take a short amount of time. We need to come back and check regulary to see if we managed to
+ * free up another lchan. */
+ if (!rqd->release_lchan) {
+ /* Pick any busy TCH/F or TCH/H lchan and inititate a channel
+ * release to make room for the incoming emergency call */
+ rqd->release_lchan = get_any_lchan(rqd->bts);
+ if (!rqd->release_lchan) {
+ /* It can not happen that we first find out that there
+ * is no TCH/H or TCH/F available and at the same time
+ * we ware unable to find any busy TCH/H or TCH/F. In
+ * this case, the BTS probably does not have any
+ * voice channels configured? */
+ LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+ "CHAN RQD/EMERGENCY-PRIORITY: no TCH/H or TCH/F available - check VTY config!\n");
+ return false;
+ }
- /* Handle PDCH related rach requests (in case of BSC-co-located-PCU */
- if (chreq_reason == GSM_CHREQ_REASON_PDCH)
- return rsl_rx_pchan_rqd(msg, bts);
+ LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+ "CHAN RQD/EMERGENCY-PRIORITY: inducing termination of lchan %s (state:%s) in favor of incoming EMERGENCY CALL!\n",
+ gsm_lchan_name(rqd->release_lchan), osmo_fsm_inst_state_name(rqd->release_lchan->fi));
+
+ lchan_release(rqd->release_lchan, !!(rqd->release_lchan->conn), true, 0);
+ } else {
+ /* BTS is shutting down, give up... */
+ if (rqd->release_lchan->ts->fi->state == TS_ST_NOT_INITIALIZED)
+ return false;
+
+ OSMO_ASSERT(rqd->release_lchan->fi);
+
+ LOG_BTS(rqd->bts, DRSL, LOGL_NOTICE,
+ "CHAN RQD/EMERGENCY-PRIORITY: still terminating lchan %s (state:%s) in favor of incoming EMERGENCY CALL!\n",
+ gsm_lchan_name(rqd->release_lchan), osmo_fsm_inst_state_name(rqd->release_lchan->fi));
+
+ /* If the channel was released in error (not established), the
+ * lchan FSM automatically blocks the LCHAN for a short time.
+ * This is not acceptable in an emergency situation, so we skip
+ * this waiting period. */
+ if (rqd->release_lchan->fi->state == LCHAN_ST_WAIT_AFTER_ERROR)
+ lchan_fsm_skip_error(rqd->release_lchan);
+ }
+
+ /* We are still in the process of releasing a busy lchan in favvor of the incoming emergency call. */
+ return true;
+}
+
+void abis_rsl_chan_rqd_queue_poll(struct gsm_bts *bts)
+{
+ struct lchan_activate_info info;
+ enum gsm_chan_t lctype;
+ struct gsm_lchan *lchan = NULL;
+ struct chan_rqd *rqd;
+
+ rqd = llist_first_entry_or_null(&bts->chan_rqd_queue, struct chan_rqd, entry);
+ if (!rqd)
+ return;
+
+ /* Handle PDCH related rach requests (in case of BSC-co-located-PCU) */
+ if (rqd->reason == GSM_CHREQ_REASON_PDCH) {
+ rsl_rx_pchan_rqd(rqd);
+ return;
+ }
+
+ /* Ensure that emergency calls will get priority over regular calls, however releasing
+ * lchan in favor of an emergency call may take some time, so we exit here. The lchan_fsm
+ * will poll again when an lchan becomes available. */
+ if (force_free_lchan_for_emergency(rqd))
+ return;
/* determine channel type (SDCCH/TCH_F/TCH_H) based on
* request reference RA */
- lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
-
- rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_TOTAL]);
+ lctype = get_ctype_by_chreq(bts->network, rqd->ref.ra);
/* check availability / allocate channel
*
- * - First try to allocate SDCCH.
+ * - First check for EMERGENCY call attempts,
+ * - then try to allocate SDCCH.
* - If SDCCH is not available, try a TCH/H (less bandwidth).
* - If there is still no channel available, try a TCH/F.
*
*/
- lchan = lchan_select_by_type(bts, GSM_LCHAN_SDCCH);
+ if (rqd->reason == GSM_CHREQ_REASON_EMERG) {
+ if (bts->si_common.rach_control.t2 & 0x4) {
+ LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: MS attempts EMERGENCY CALL although EMERGENCY CALLS "
+ "are not allowed in sysinfo (spec violation by MS!)\n");
+ rsl_tx_imm_ass_rej(bts, &rqd->ref);
+ llist_del(&rqd->entry);
+ talloc_free(rqd);
+ return;
+ }
+ }
+
+ /* Emergency calls will be put on a free TCH/H or TCH/F directly in the code below, all other channel requests
+ * will get an SDCCH first (if possible). */
+ if (rqd->reason != GSM_CHREQ_REASON_EMERG)
+ lchan = lchan_select_by_type(bts, GSM_LCHAN_SDCCH);
+
if (!lchan) {
LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: no resources for %s 0x%x, retrying with %s\n",
- gsm_lchant_name(GSM_LCHAN_SDCCH), rqd_ref->ra, gsm_lchant_name(GSM_LCHAN_TCH_H));
+ gsm_lchant_name(GSM_LCHAN_SDCCH), rqd->ref.ra, gsm_lchant_name(GSM_LCHAN_TCH_H));
lchan = lchan_select_by_type(bts, GSM_LCHAN_TCH_H);
}
if (!lchan) {
LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: no resources for %s 0x%x, retrying with %s\n",
- gsm_lchant_name(GSM_LCHAN_SDCCH), rqd_ref->ra, gsm_lchant_name(GSM_LCHAN_TCH_F));
+ gsm_lchant_name(GSM_LCHAN_SDCCH), rqd->ref.ra, gsm_lchant_name(GSM_LCHAN_TCH_F));
lchan = lchan_select_by_type(bts, GSM_LCHAN_TCH_F);
}
if (!lchan) {
LOG_BTS(bts, DRSL, LOGL_NOTICE, "CHAN RQD: no resources for %s 0x%x\n",
- gsm_lchant_name(lctype), rqd_ref->ra);
+ gsm_lchant_name(lctype), rqd->ref.ra);
rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_NO_CHANNEL]);
- rsl_tx_imm_ass_rej(bts, rqd_ref);
- return 0;
+ rsl_tx_imm_ass_rej(bts, &rqd->ref);
+ llist_del(&rqd->entry);
+ talloc_free(rqd);
+ return;
}
/* save the RACH data as we need it after the CHAN ACT ACK */
lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
OSMO_ASSERT(lchan->rqd_ref);
- *(lchan->rqd_ref) = *rqd_ref;
- lchan->rqd_ta = rqd_ta;
+ *(lchan->rqd_ref) = rqd->ref;
+ lchan->rqd_ta = rqd->ta;
LOG_LCHAN(lchan, LOGL_DEBUG, "MS: Channel Request: reason=%s ra=0x%02x ta=%d\n",
- gsm_chreq_name(chreq_reason), rqd_ref->ra, rqd_ta);
+ gsm_chreq_name(rqd->reason), rqd->ref.ra, rqd->ta);
info = (struct lchan_activate_info){
.activ_for = FOR_MS_CHANNEL_REQUEST,
.chan_mode = GSM48_CMODE_SIGN,
};
lchan_activate(lchan, &info);
- return 0;
+ llist_del(&rqd->entry);
+ talloc_free(rqd);
+ return;
}
int rsl_tx_imm_assignment(struct gsm_lchan *lchan)
@@ -1502,8 +1732,14 @@ static int rsl_rx_ccch_load(struct msgb *msg)
sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
/* update stats group */
- busy_percent = (int32_t) sd.rach_busy_count * 100 / (int32_t) sd.rach_slot_count;
- access_percent = (int32_t) sd.rach_access_count * 100 / (int32_t) sd.rach_slot_count;
+ if (sd.rach_slot_count) {
+ access_percent = (int32_t) sd.rach_access_count * 100 / (int32_t) sd.rach_slot_count;
+ busy_percent = (int32_t) sd.rach_busy_count * 100 / (int32_t) sd.rach_slot_count;
+ } else {
+ access_percent = 0;
+ busy_percent = 100;
+ }
+
osmo_stat_item_set(sd.bts->bts_statg->items[BTS_STAT_RACH_BUSY], busy_percent);
osmo_stat_item_set(sd.bts->bts_statg->items[BTS_STAT_RACH_ACCESS], access_percent);
/* dispatch signal */
diff --git a/src/osmo-bsc/acc.c b/src/osmo-bsc/acc.c
index 74ebe9952..06f96c625 100644
--- a/src/osmo-bsc/acc.c
+++ b/src/osmo-bsc/acc.c
@@ -222,18 +222,28 @@ void get_subset_limits(struct acc_mgr *acc_mgr, uint8_t *first, uint8_t *last)
* 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 (lowest != highest) { /* len(allowed_subset_mask) > 1 */
+ 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;
+ /* Assumption: "i" is pointing to the lowest dynamically barred ACC.
+ Example: 11 1000 00>0<1. */
+ *last = i - 1;
+ while (acc_is_permanently_barred(acc_mgr->bts, *last))
+ *last -= 1;
+ *first = i + 1;
+ while (acc_is_permanently_barred(acc_mgr->bts, *first) ||
+ !(acc_mgr->allowed_subset_mask & (1 << (*first))))
+ *first += 1;
} else {
*first = lowest;
*last = highest;
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c
index ca29daabb..fde028ed9 100644
--- a/src/osmo-bsc/assignment_fsm.c
+++ b/src/osmo-bsc/assignment_fsm.c
@@ -379,9 +379,8 @@ static int check_requires_voice_stream(struct gsm_subscriber_connection *conn)
return 0;
}
-/* Check if the conn is already associated with an lchan. If yes, we will check
- * if that lchan is compatible with the preferred rate/codec. If the lchan
- * turns out to be incompatible we try with the alternate rate/codec. */
+/* Decide if we should re-use an existing lchan. For this we check if the
+ * current lchan is compatible with one of the requested modes. */
static bool reuse_existing_lchan(struct gsm_subscriber_connection *conn)
{
struct assignment_request *req = &conn->assignment.req;
@@ -395,22 +394,10 @@ static bool reuse_existing_lchan(struct gsm_subscriber_connection *conn)
for (i = 0; i < req->n_ch_mode_rate; i++)
if (lchan_type_compat_with_mode(conn->lchan->type, &req->ch_mode_rate[i])) {
conn->lchan->ch_mode_rate = req->ch_mode_rate[i];
- break;
+ return true;
}
- if (i == req->n_ch_mode_rate)
- return false;
-
- if (conn->lchan->tch_mode != conn->lchan->ch_mode_rate.chan_mode) {
- /* FIXME: send Channel Mode Modify to put the current lchan in the right mode, and kick
- * off its RTP stream setup code path. See gsm48_lchan_modify() and
- * gsm48_rx_rr_modif_ack(), and see lchan_fsm.h LCHAN_EV_CHAN_MODE_MODIF_* */
- LOG_ASSIGNMENT(conn, LOGL_DEBUG,
- "Current lchan would be compatible, but Channel Mode Modify is not implemented\n");
- return false;
- }
-
- return true;
+ return false;
}
void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts *bts,
@@ -447,22 +434,57 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts
return;
/* There may be an already existing lchan, if yes, try to work with
- * the existing lchan */
+ * the existing lchan. */
if (reuse_existing_lchan(conn)) {
+
+ /* If the requested mode and the current TCH mode matches up, just send the
+ * assignment complete directly and be done with the assignment procedure. */
+ if (conn->lchan->tch_mode == conn->lchan->ch_mode_rate.chan_mode) {
+ LOG_ASSIGNMENT(conn, LOGL_DEBUG,
+ "Current lchan mode is compatible with requested chan_mode,"
+ " sending BSSMAP Assignment Complete directly."
+ " requested chan_mode=%s; current lchan is %s\n",
+ gsm48_chan_mode_name(conn->lchan->ch_mode_rate.chan_mode),
+ gsm_lchan_name(conn->lchan));
+
+ send_assignment_complete(conn);
+ /* If something went wrong during send_assignment_complete(),
+ * the fi will be gone from error handling in there. */
+ if (conn->assignment.fi) {
+ assignment_count_result(CTR_ASSIGNMENT_COMPLETED);
+ osmo_fsm_inst_term(conn->assignment.fi, OSMO_FSM_TERM_REGULAR, 0);
+ }
+ return;
+ }
+
+ /* The requested mode does not match the current TCH mode but the lchan is
+ * compatible. We will initiate a mode modify procedure. */
LOG_ASSIGNMENT(conn, LOGL_DEBUG,
- "Current lchan is compatible with requested chan_mode,"
- " sending BSSMAP Assignment Complete directly."
- " requested chan_mode=%s; current lchan is %s\n",
+ "Current lchan mode is not compatible with requested chan_mode,"
+ " so we will modify it. requested chan_mode=%s; current lchan is %s\n",
gsm48_chan_mode_name(conn->lchan->ch_mode_rate.chan_mode),
gsm_lchan_name(conn->lchan));
- send_assignment_complete(conn);
- /* If something went wrong during send_assignment_complete(), the fi will be gone from
- * error handling in there. */
- if (conn->assignment.fi) {
- assignment_count_result(CTR_ASSIGNMENT_COMPLETED);
- osmo_fsm_inst_term(conn->assignment.fi, OSMO_FSM_TERM_REGULAR, 0);
- }
+ info = (struct lchan_activate_info){
+ .activ_for = FOR_ASSIGNMENT,
+ .for_conn = conn,
+ .chan_mode = conn->lchan->ch_mode_rate.chan_mode,
+ .encr = conn->lchan->encr,
+ .s15_s0 = conn->lchan->ch_mode_rate.s15_s0,
+ .requires_voice_stream = conn->assignment.requires_voice_stream,
+ .msc_assigned_cic = req->msc_assigned_cic,
+ .re_use_mgw_endpoint_from_lchan = conn->lchan,
+ };
+
+ osmo_fsm_inst_dispatch(conn->lchan->fi, LCHAN_EV_REQUEST_MODE_MODIFY, &info);
+
+ /* Since we opted not to allocate a new lchan, the new lchan is still the old lchan. */
+ conn->assignment.new_lchan = conn->lchan;
+
+ /* Also we need to skip the RR assignment, so we jump forward and wait for the lchan_fsm until it
+ * reaches the established state again. */
+ assignment_fsm_state_chg(ASSIGNMENT_ST_WAIT_LCHAN_ESTABLISHED);
+
return;
}
@@ -682,6 +704,7 @@ static const struct osmo_fsm_state assignment_fsm_states[] = {
.out_state_mask = 0
| S(ASSIGNMENT_ST_WAIT_LCHAN_ACTIVE)
| S(ASSIGNMENT_ST_WAIT_RR_ASS_COMPLETE)
+ | S(ASSIGNMENT_ST_WAIT_LCHAN_ESTABLISHED) /* MODE MODIFY */
,
},
[ASSIGNMENT_ST_WAIT_RR_ASS_COMPLETE] = {
diff --git a/src/osmo-bsc/bsc_init.c b/src/osmo-bsc/bsc_init.c
index e45b5e8e3..1460af44e 100644
--- a/src/osmo-bsc/bsc_init.c
+++ b/src/osmo-bsc/bsc_init.c
@@ -90,8 +90,7 @@ static struct gsm_network *bsc_network_init(void *ctx)
net->cbc = talloc_zero(net, struct bsc_cbc_link);
if (!net->cbc) {
- talloc_free(net);
- return NULL;
+ goto err_out;
}
/* Init back pointer */
@@ -104,16 +103,19 @@ static struct gsm_network *bsc_network_init(void *ctx)
/* init statistics */
net->bsc_ctrs = rate_ctr_group_alloc(net, &bsc_ctrg_desc, 0);
- if (!net->bsc_ctrs) {
- talloc_free(net);
- return NULL;
- }
+ if (!net->bsc_ctrs)
+ goto err_out;
net->bsc_statg = osmo_stat_item_group_alloc(net, &bsc_statg_desc, 0);
- if (!net->bsc_statg) {
- rate_ctr_group_free(net->bsc_ctrs);
- talloc_free(net);
- return NULL;
- }
+ if (!net->bsc_statg)
+ goto err_free_bsc_ctr;
+
+ /* init statistics */
+ net->bts_unknown_ctrs = rate_ctr_group_alloc(net, &bts_ctrg_desc, BTS_STAT_IDX_UNKNOWN);
+ if (!net->bts_unknown_ctrs)
+ goto err_free_bsc_ctr_stat;
+ net->bts_unknown_statg = osmo_stat_item_group_alloc(net, &bts_statg_desc, BTS_STAT_IDX_UNKNOWN);
+ if (!net->bts_unknown_statg)
+ goto err_free_all;
INIT_LLIST_HEAD(&net->bts_rejected);
gsm_net_update_ctype(net);
@@ -127,13 +129,24 @@ static struct gsm_network *bsc_network_init(void *ctx)
osmo_timer_schedule(&net->t3122_chan_load_timer, T3122_CHAN_LOAD_SAMPLE_INTERVAL, 0);
net->cbc->net = net;
- /* no cbc_hostname: client not started by default */
- net->cbc->config.cbc_port = CBSP_TCP_PORT;
- /* listen_port == -1: server not started by default */
- net->cbc->config.listen_port = -1;
- net->cbc->config.listen_hostname = talloc_strdup(net->cbc, "127.0.0.1");
+ net->cbc->mode = BSC_CBC_LINK_MODE_DISABLED;
+ net->cbc->server.local_addr = bsc_cbc_default_server_local_addr;
+ /* For CBSP client mode: default remote CBSP server port is CBSP_TCP_PORT == 48049. Leave the IP address unset.
+ * Also leave the local bind for the CBSP client disabled (unconfigured). */
+ net->cbc->client.remote_addr = (struct osmo_sockaddr_str){ .port = CBSP_TCP_PORT, };
+ net->cbc->client.local_addr = (struct osmo_sockaddr_str){};
return net;
+
+err_free_all:
+ rate_ctr_group_free(net->bts_unknown_ctrs);
+err_free_bsc_ctr_stat:
+ osmo_stat_item_group_free(net->bsc_statg);
+err_free_bsc_ctr:
+ rate_ctr_group_free(net->bsc_ctrs);
+err_out:
+ talloc_free(net);
+ return NULL;
}
int bsc_network_alloc(void)
diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c
index 0faf3b2df..63e54ba38 100644
--- a/src/osmo-bsc/bsc_subscr_conn_fsm.c
+++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c
@@ -73,6 +73,7 @@ static const struct value_string gscon_fsm_event_names[] = {
{GSCON_EV_A_CONN_CFM, "MO-CONNECT.cfm"},
{GSCON_EV_A_CLEAR_CMD, "CLEAR_CMD"},
{GSCON_EV_A_DISC_IND, "DISCONNET.ind"},
+ {GSCON_EV_A_COMMON_ID_IND, "COMMON_ID.ind"},
{GSCON_EV_ASSIGNMENT_START, "ASSIGNMENT_START"},
{GSCON_EV_ASSIGNMENT_END, "ASSIGNMENT_END"},
{GSCON_EV_HANDOVER_START, "HANDOVER_START"},
@@ -89,8 +90,8 @@ static const struct value_string gscon_fsm_event_names[] = {
};
struct osmo_tdef_state_timeout conn_fsm_timeouts[32] = {
- [ST_WAIT_CC] = { .T = 993210 },
- [ST_CLEARING] = { .T = 999 },
+ [ST_WAIT_CC] = { .T = -3210 },
+ [ST_CLEARING] = { .T = -4 },
};
/* Transition to a state, using the T timer defined in conn_fsm_timeouts.
@@ -140,6 +141,11 @@ static void gscon_bssmap_clear(struct gsm_subscriber_connection *conn,
struct msgb *resp;
int rc;
+ if (conn->rx_clear_command) {
+ LOGPFSML(conn->fi, LOGL_DEBUG, "Not sending BSSMAP CLEAR REQUEST, already got CLEAR COMMAND from MSC\n");
+ return;
+ }
+
LOGPFSML(conn->fi, LOGL_DEBUG, "Tx BSSMAP CLEAR REQUEST(%s) to MSC\n", gsm0808_cause_name(cause));
resp = gsm0808_create_clear_rqst(cause);
if (!resp) {
@@ -324,7 +330,7 @@ static void gscon_fsm_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
}
gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE);
if (conn->fi->state != ST_CLEARING)
- osmo_fsm_inst_state_chg(fi, ST_CLEARING, 60, 999);
+ osmo_fsm_inst_state_chg(fi, ST_CLEARING, 60, -4);
return;
default:
OSMO_ASSERT(false);
@@ -344,7 +350,7 @@ static void gscon_fsm_wait_cc(struct osmo_fsm_inst *fi, uint32_t event, void *da
confirmed connection, then instead simply drop the connection */
LOGPFSML(fi, LOGL_INFO,
"Connection confirmed but lchan was dropped previously, clearing conn\n");
- osmo_fsm_inst_state_chg(conn->fi, ST_CLEARING, 60, 999);
+ osmo_fsm_inst_state_chg(conn->fi, ST_CLEARING, 60, -4);
gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE);
break;
}
@@ -381,7 +387,6 @@ static void gscon_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *dat
return;
case GSCON_EV_HANDOVER_START:
- rate_ctr_inc(&conn->network->bsc_ctrs->ctr[BSC_CTR_HANDOVER_ATTEMPTED]);
/* Rely on handover_fsm timeout */
if (osmo_fsm_inst_state_chg(fi, ST_HANDOVER, 0, 0))
LOGPFSML(fi, LOGL_ERROR, "Cannot transition to HANDOVER state, discarding\n");
@@ -495,8 +500,11 @@ struct osmo_mgcpc_ep *gscon_ensure_mgw_endpoint(struct gsm_subscriber_connection
if (is_ipaccess_bts(for_lchan->ts->trx->bts))
/* use dynamic RTPBRIDGE endpoint allocation in MGW */
epname = mgcp_client_rtpbridge_wildcard(conn->network->mgw.client);
- else
- epname = mgcp_client_e1_epname(conn, conn->network->mgw.client, 1, for_lchan->ts->e1_link.e1_ts, 16, for_lchan->ts->e1_link.e1_ts_ss*2);
+ else {
+ epname = mgcp_client_e1_epname(conn, conn->network->mgw.client, for_lchan->ts->e1_link.e1_nr,
+ for_lchan->ts->e1_link.e1_ts, 16,
+ for_lchan->ts->e1_link.e1_ts_ss*2);
+ }
conn->user_plane.mgw_endpoint =
osmo_mgcpc_ep_alloc(conn->fi, GSCON_EV_FORGET_MGW_ENDPOINT,
@@ -654,7 +662,7 @@ void gscon_change_primary_lchan(struct gsm_subscriber_connection *conn, struct g
osmo_fsm_inst_dispatch(conn->lchan->fi_rtp, LCHAN_RTP_EV_ESTABLISHED, 0);
if (old_lchan && (old_lchan != new_lchan))
- gscon_release_lchan(conn, old_lchan, false, false, 0);
+ gscon_release_lchan(conn, old_lchan, false, false, GSM48_RR_CAUSE_NORMAL);
}
void gscon_lchan_releasing(struct gsm_subscriber_connection *conn, struct gsm_lchan *lchan)
@@ -684,7 +692,7 @@ void gscon_lchan_releasing(struct gsm_subscriber_connection *conn, struct gsm_lc
break;
default:
/* Ensure that the FSM is in ST_CLEARING. */
- osmo_fsm_inst_state_chg(conn->fi, ST_CLEARING, 60, 999);
+ osmo_fsm_inst_state_chg(conn->fi, ST_CLEARING, 60, -4);
/* fall thru, omit an error log if already in ST_CLEARING */
case ST_CLEARING:
/* Request a Clear Command from the MSC. */
@@ -756,17 +764,25 @@ static void gscon_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *d
{
struct gsm_subscriber_connection *conn = fi->priv;
const struct gscon_clear_cmd_data *ccd;
+ struct osmo_mobile_identity *mi_imsi;
/* Regular allstate event processing */
switch (event) {
case GSCON_EV_A_CLEAR_CMD:
+ conn->rx_clear_command = true;
+
+ /* Give the handover_fsm a chance to book this as handover success before tearing down everything,
+ * making it look like a sudden death failure. */
+ if (conn->ho.fi)
+ osmo_fsm_inst_dispatch(conn->ho.fi, HO_EV_CONN_RELEASING, NULL);
+
OSMO_ASSERT(data);
ccd = data;
if (conn->lchan)
conn->lchan->release.is_csfb = ccd->is_csfb;
/* MSC tells us to cleanly shut down */
if (conn->fi->state != ST_CLEARING)
- osmo_fsm_inst_state_chg(fi, ST_CLEARING, 60, 999);
+ osmo_fsm_inst_state_chg(fi, ST_CLEARING, 60, -4);
LOGPFSML(fi, LOGL_DEBUG, "Releasing all lchans (if any) after BSSMAP Clear Command\n");
gscon_release_lchans(conn, true, bsc_gsm48_rr_cause_from_gsm0808_cause(ccd->cause_0808));
/* FIXME: Release all terestrial resources in ST_CLEARING */
@@ -802,6 +818,18 @@ static void gscon_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *d
break;
case GSCON_EV_LCLS_FAIL:
break;
+ case GSCON_EV_A_COMMON_ID_IND:
+ OSMO_ASSERT(data);
+ mi_imsi = data;
+ if (!conn->bsub)
+ conn->bsub = bsc_subscr_find_or_create_by_imsi(conn->network->bsc_subscribers, mi_imsi->imsi);
+ else {
+ /* we already have a bsc_subscr associated; maybe that subscriber has no IMSI yet? */
+ if (!conn->bsub->imsi[0])
+ bsc_subscr_set_imsi(conn->bsub, mi_imsi->imsi);
+ }
+ gscon_update_id(conn);
+ break;
default:
OSMO_ASSERT(false);
break;
@@ -862,8 +890,8 @@ static int gscon_timer_cb(struct osmo_fsm_inst *fi)
struct gsm_subscriber_connection *conn = fi->priv;
switch (fi->T) {
- case 993210:
- gscon_release_lchan(conn, conn->lchan, true, true, RSL_ERR_INTERWORKING);
+ case -3210:
+ gscon_release_lchan(conn, conn->lchan, true, true, GSM48_RR_CAUSE_ABNORMAL_TIMER);
/* MSC has not responded/confirmed connection with CC, this
* could indicate a bad SCCP connection. We now inform the the
@@ -876,7 +904,7 @@ static int gscon_timer_cb(struct osmo_fsm_inst *fi)
* gscon_cleanup() above) */
osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
break;
- case 999:
+ case -4:
/* The MSC has sent a BSSMAP Clear Command, we acknowledged that, but the conn was never
* disconnected. */
LOGPFSML(fi, LOGL_ERROR, "Long after a BSSMAP Clear Command, the conn is still not"
@@ -895,7 +923,8 @@ static struct osmo_fsm gscon_fsm = {
.name = "SUBSCR_CONN",
.states = gscon_fsm_states,
.num_states = ARRAY_SIZE(gscon_fsm_states),
- .allstate_event_mask = S(GSCON_EV_A_DISC_IND) | S(GSCON_EV_A_CLEAR_CMD) | S(GSCON_EV_RSL_CONN_FAIL) |
+ .allstate_event_mask = S(GSCON_EV_A_DISC_IND) | S(GSCON_EV_A_CLEAR_CMD) | S(GSCON_EV_A_COMMON_ID_IND) |
+ S(GSCON_EV_RSL_CONN_FAIL) |
S(GSCON_EV_LCLS_FAIL) |
S(GSCON_EV_FORGET_LCHAN) |
S(GSCON_EV_FORGET_MGW_ENDPOINT),
@@ -1002,17 +1031,24 @@ static void rll_ind_cb(struct gsm_lchan *lchan, uint8_t link_id, void *_data, en
* fire after a lchan_release call and before the S_CHALLOC_FREED
* is called. Check if a conn is set before proceeding.
*/
- if (!lchan->conn)
+ if (!lchan->conn) {
+ msgb_free(msg);
return;
+ }
switch (rllr_ind) {
case BSC_RLLR_IND_EST_CONF:
rsl_data_request(msg, OBSC_LINKID_CB(msg));
break;
case BSC_RLLR_IND_REL_IND:
+ bsc_sapi_n_reject(lchan->conn, OBSC_LINKID_CB(msg),
+ GSM0808_CAUSE_MS_NOT_EQUIPPED);
+ msgb_free(msg);
+ break;
case BSC_RLLR_IND_ERR_IND:
case BSC_RLLR_IND_TIMEOUT:
- bsc_sapi_n_reject(lchan->conn, OBSC_LINKID_CB(msg));
+ bsc_sapi_n_reject(lchan->conn, OBSC_LINKID_CB(msg),
+ GSM0808_CAUSE_BSS_NOT_EQUIPPED);
msgb_free(msg);
break;
}
@@ -1052,7 +1088,7 @@ static void gsm0808_send_rsl_dtap(struct gsm_subscriber_connection *conn,
rc = rll_establish(msg->lchan, sapi, rll_ind_cb, msg);
if (rc) {
msgb_free(msg);
- bsc_sapi_n_reject(conn, link_id);
+ bsc_sapi_n_reject(conn, link_id, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
goto failed_to_send;
}
return;
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index e4842f724..003939b88 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -955,12 +955,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
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);
- vty_out(vty, " access-control-class-ramping-step-interval %u%s",
- acc_ramp_get_step_interval(&bts->acc_ramp), VTY_NEWLINE);
- vty_out(vty, " access-control-class-ramping-step-size %u%s", acc_ramp_get_step_size(&bts->acc_ramp),
- VTY_NEWLINE);
- vty_out(vty, " access-control-class-ramping-chan-load %u %u%s",
- bts->acc_ramp.chan_load_lower_threshold, bts->acc_ramp.chan_load_upper_threshold, VTY_NEWLINE);
+ if (acc_ramp_is_enabled(&bts->acc_ramp)) {
+ vty_out(vty, " access-control-class-ramping-step-interval %u%s",
+ acc_ramp_get_step_interval(&bts->acc_ramp), VTY_NEWLINE);
+ vty_out(vty, " access-control-class-ramping-step-size %u%s", acc_ramp_get_step_size(&bts->acc_ramp),
+ VTY_NEWLINE);
+ vty_out(vty, " access-control-class-ramping-chan-load %u %u%s",
+ bts->acc_ramp.chan_load_lower_threshold, bts->acc_ramp.chan_load_upper_threshold, VTY_NEWLINE);
+ }
if (!bts->si_unused_send_empty)
vty_out(vty, " no system-information unused-send-empty%s", VTY_NEWLINE);
for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) {
@@ -1146,7 +1148,8 @@ static int config_write_net(struct vty *vty)
gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
}
- osmo_tdef_vty_write(vty, gsmnet->T_defs, " timer ");
+ /* Timer introspection commands (generic osmo_tdef API) */
+ osmo_tdef_vty_groups_write(vty, " ");
{
uint16_t meas_port;
@@ -1196,7 +1199,7 @@ static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx, bool print_rs
"resulting BS power: %d dBm%s",
trx->nominal_power, trx->max_power_red,
trx->nominal_power - trx->max_power_red, VTY_NEWLINE);
- vty_out(vty, " NM State: ");
+ vty_out(vty, " Radio Carrier NM State: ");
net_dump_nmstate(vty, &trx->mo.nm_state);
if (print_rsl)
vty_out(vty, " RSL State: %s%s", trx->rsl_link? "connected" : "disconnected", VTY_NEWLINE);
@@ -1771,7 +1774,7 @@ static int ho_or_as(struct vty *vty, const char *argv[], int argc)
}
if (!new_bts) {
- vty_out(vty, "Unable to trigger handover, specified bts #%u does not exist %s",
+ vty_out(vty, "%% Unable to trigger handover, specified bts #%u does not exist %s",
bts_nr_new, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1793,7 +1796,7 @@ static int ho_or_as(struct vty *vty, const char *argv[], int argc)
}
}
- vty_out(vty, "Unable to trigger %s, specified connection (bts=%u,trx=%u,ts=%u,ss=%u) does not exist%s",
+ vty_out(vty, "%% Unable to trigger %s, specified connection (bts=%u,trx=%u,ts=%u,ss=%u) does not exist%s",
action, bts_nr, trx_nr, ts_nr, ss_nr, VTY_NEWLINE);
return CMD_WARNING;
@@ -1865,7 +1868,7 @@ static struct gsm_lchan *find_used_voice_lchan(struct vty *vty, int random_idx)
random_idx %= count;
}
- vty_out(vty, "Cannot find any ongoing voice calls%s", VTY_NEWLINE);
+ vty_out(vty, "%% Cannot find any ongoing voice calls%s", VTY_NEWLINE);
return NULL;
}
@@ -1892,7 +1895,7 @@ static struct gsm_bts *find_other_bts_with_free_slots(struct vty *vty, struct gs
return bts;
}
}
- vty_out(vty, "Cannot find any BTS (other than BTS %u) with free %s lchan%s",
+ vty_out(vty, "%% Cannot find any BTS (other than BTS %u) with free %s lchan%s",
not_this_bts? not_this_bts->nr : 255, gsm_lchant_name(free_type), VTY_NEWLINE);
return NULL;
}
@@ -2036,7 +2039,7 @@ DEFUN(show_paging_group,
page_group = gsm0502_calc_paging_group(&bts->si_common.chan_desc,
str_to_imsi(argv[1]));
- vty_out(vty, "%%Paging group for IMSI %" PRIu64 " on BTS #%d is %u%s",
+ vty_out(vty, "%% Paging group for IMSI %" PRIu64 " on BTS #%d is %u%s",
str_to_imsi(argv[1]), bts->nr,
page_group, VTY_NEWLINE);
return CMD_SUCCESS;
@@ -2916,6 +2919,15 @@ DEFUN(cfg_bts_radio_link_timeout_inf, cfg_bts_radio_link_timeout_inf_cmd,
#define GPRS_TEXT "GPRS Packet Network\n"
+#define GPRS_CHECK_ENABLED(bts) \
+ do { \
+ if (bts->gprs.mode == BTS_GPRS_NONE) { \
+ vty_out(vty, "%% GPRS is not enabled on BTS %u%s", \
+ bts->nr, VTY_NEWLINE); \
+ return CMD_WARNING; \
+ } \
+ } while (0)
+
DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
"gprs cell bvci <2-65535>",
GPRS_TEXT
@@ -2926,10 +2938,7 @@ DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
/* ETSI TS 101 343: values 0 and 1 are reserved for signalling and PTM */
struct gsm_bts *bts = vty->index;
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.cell.bvci = atoi(argv[0]);
@@ -2944,10 +2953,7 @@ DEFUN(cfg_bts_gprs_nsei, cfg_bts_gprs_nsei_cmd,
{
struct gsm_bts *bts = vty->index;
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.nse.nsei = atoi(argv[0]);
@@ -2966,10 +2972,7 @@ DEFUN(cfg_bts_gprs_nsvci, cfg_bts_gprs_nsvci_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.nsvc[idx].nsvci = atoi(argv[1]);
@@ -2987,10 +2990,7 @@ DEFUN(cfg_bts_gprs_nsvc_lport, cfg_bts_gprs_nsvc_lport_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.nsvc[idx].local_port = atoi(argv[1]);
@@ -3008,10 +3008,7 @@ DEFUN(cfg_bts_gprs_nsvc_rport, cfg_bts_gprs_nsvc_rport_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.nsvc[idx].remote_port = atoi(argv[1]);
@@ -3029,10 +3026,7 @@ DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
int idx = atoi(argv[0]);
struct in_addr ia;
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
inet_aton(argv[1], &ia);
bts->gprs.nsvc[idx].remote_ip = ntohl(ia.s_addr);
@@ -3062,10 +3056,7 @@ DEFUN(cfg_bts_gprs_ns_timer, cfg_bts_gprs_ns_timer_cmd,
int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
int val = atoi(argv[1]);
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
if (idx < 0 || idx >= ARRAY_SIZE(bts->gprs.nse.timer))
return CMD_WARNING;
@@ -3099,10 +3090,7 @@ DEFUN(cfg_bts_gprs_cell_timer, cfg_bts_gprs_cell_timer_cmd,
int idx = get_string_value(gprs_bssgp_cfg_strs, argv[0]);
int val = atoi(argv[1]);
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
if (idx < 0 || idx >= ARRAY_SIZE(bts->gprs.cell.timer))
return CMD_WARNING;
@@ -3121,10 +3109,7 @@ DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
{
struct gsm_bts *bts = vty->index;
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.rac = atoi(argv[0]);
@@ -3138,10 +3123,7 @@ DEFUN(cfg_bts_gprs_ctrl_ack, cfg_bts_gprs_ctrl_ack_cmd,
{
struct gsm_bts *bts = vty->index;
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.ctrl_ack_type_use_block = false;
@@ -3151,14 +3133,11 @@ DEFUN(cfg_bts_gprs_ctrl_ack, cfg_bts_gprs_ctrl_ack_cmd,
DEFUN(cfg_no_bts_gprs_ctrl_ack, cfg_no_bts_gprs_ctrl_ack_cmd,
"no gprs control-ack-type-rach", NO_STR GPRS_TEXT
"Set GPRS Control Ack Type for PACKET CONTROL ACKNOWLEDGMENT message to "
- "four access bursts format instead of default RLC/MAC control block\n")
+ "default RLC/MAC control block\n")
{
struct gsm_bts *bts = vty->index;
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.ctrl_ack_type_use_block = true;
@@ -3175,10 +3154,7 @@ DEFUN(cfg_bts_gprs_net_ctrl_ord, cfg_bts_gprs_net_ctrl_ord_cmd,
{
struct gsm_bts *bts = vty->index;
- if (bts->gprs.mode == BTS_GPRS_NONE) {
- vty_out(vty, "%% GPRS not enabled on BTS %u%s", bts->nr, VTY_NEWLINE);
- return CMD_WARNING;
- }
+ GPRS_CHECK_ENABLED(bts);
bts->gprs.net_ctrl_ord = atoi(argv[0] + 2);
@@ -3197,7 +3173,7 @@ DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd,
enum bts_gprs_mode mode = bts_gprs_mode_parse(argv[0], NULL);
if (!bts_gprs_mode_is_compat(bts, mode)) {
- vty_out(vty, "This BTS type does not support %s%s", argv[0],
+ vty_out(vty, "%% This BTS type does not support %s%s", argv[0],
VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3305,7 +3281,7 @@ DEFUN(cfg_bts_si_mode, cfg_bts_si_mode_cmd,
type = get_string_value(osmo_sitype_strs, argv[0]);
if (type < 0) {
- vty_out(vty, "Error SI Type%s", VTY_NEWLINE);
+ vty_out(vty, "%% Error SI Type%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3328,12 +3304,12 @@ DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd,
type = get_string_value(osmo_sitype_strs, argv[0]);
if (type < 0) {
- vty_out(vty, "Error SI Type%s", VTY_NEWLINE);
+ vty_out(vty, "%% Error SI Type%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (!(bts->si_mode_static & (1 << type))) {
- vty_out(vty, "SI Type %s is not configured in static mode%s",
+ vty_out(vty, "%% SI Type %s is not configured in static mode%s",
get_value_string(osmo_sitype_strs, type), VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3344,7 +3320,7 @@ DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd,
/* Parse the user-specified SI in hex format, [partially] overwriting padding */
rc = osmo_hexparse(argv[1], GSM_BTS_SI(bts, type), GSM_MACBLOCK_LEN);
if (rc < 0 || rc > GSM_MACBLOCK_LEN) {
- vty_out(vty, "Error parsing HEXSTRING%s", VTY_NEWLINE);
+ vty_out(vty, "%% Error parsing HEXSTRING%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3376,7 +3352,7 @@ DEFUN(cfg_bts_no_si_unused_send_empty, cfg_bts_no_si_unused_send_empty_cmd,
struct gsm_bts *bts = vty->index;
if (!is_ipaccess_bts(bts) || is_sysmobts_v2(bts)) {
- vty_out(vty, "This command is only intended for ipaccess nanoBTS. See OS#3707.%s",
+ vty_out(vty, "%% This command is only intended for ipaccess nanoBTS. See OS#3707.%s",
VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3497,24 +3473,24 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd,
switch (r) {
case 1:
- vty_out(vty, "Warning: multiple threshold-high are not supported, overriding with %u%s",
+ vty_out(vty, "%% Warning: multiple threshold-high are not supported, overriding with %u%s",
thresh_hi, VTY_NEWLINE);
break;
case EARFCN_THRESH_LOW_INVALID:
- vty_out(vty, "Warning: multiple threshold-low are not supported, overriding with %u%s",
+ vty_out(vty, "%% Warning: multiple threshold-low are not supported, overriding with %u%s",
thresh_lo, VTY_NEWLINE);
break;
case EARFCN_QRXLV_INVALID + 1:
- vty_out(vty, "Warning: multiple QRXLEVMIN are not supported, overriding with %u%s",
+ vty_out(vty, "%% Warning: multiple QRXLEVMIN are not supported, overriding with %u%s",
qrx, VTY_NEWLINE);
break;
case EARFCN_PRIO_INVALID:
- vty_out(vty, "Warning: multiple priorities are not supported, overriding with %u%s",
+ vty_out(vty, "%% Warning: multiple priorities are not supported, overriding with %u%s",
prio, VTY_NEWLINE);
break;
default:
if (r < 0) {
- vty_out(vty, "Unable to add ARFCN %u: %s%s", arfcn, strerror(-r), VTY_NEWLINE);
+ vty_out(vty, "%% Unable to add ARFCN %u: %s%s", arfcn, strerror(-r), VTY_NEWLINE);
return CMD_WARNING;
}
}
@@ -3522,7 +3498,7 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd,
if (si2q_num(bts) <= SI2Q_MAX_NUM)
return CMD_SUCCESS;
- vty_out(vty, "Warning: not enough space in SI2quater (%u/%u used) for a given EARFCN %u%s",
+ vty_out(vty, "%% Warning: not enough space in SI2quater (%u/%u used) for a given EARFCN %u%s",
bts->si2q_count, SI2Q_MAX_NUM, arfcn, VTY_NEWLINE);
osmo_earfcn_del(e, arfcn);
@@ -3542,7 +3518,7 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd,
uint16_t arfcn = atoi(argv[0]);
int r = osmo_earfcn_del(e, arfcn);
if (r < 0) {
- vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn,
+ vty_out(vty, "%% Unable to delete arfcn %u: %s%s", arfcn,
strerror(-r), VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3562,14 +3538,16 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd,
switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) {
case -ENOMEM:
- vty_out(vty, "Unable to add UARFCN: max number of UARFCNs (%u) reached%s", MAX_EARFCN_LIST, VTY_NEWLINE);
+ vty_out(vty, "%% Unable to add UARFCN: max number of UARFCNs (%u) reached%s",
+ MAX_EARFCN_LIST, VTY_NEWLINE);
return CMD_WARNING;
case -ENOSPC:
- vty_out(vty, "Warning: not enough space in SI2quater for a given UARFCN (%u, %u)%s",
+ vty_out(vty, "%% Warning: not enough space in SI2quater for a given UARFCN (%u, %u)%s",
arfcn, scramble, VTY_NEWLINE);
return CMD_WARNING;
case -EADDRINUSE:
- vty_out(vty, "Unable to add UARFCN: (%u, %u) is already added%s", arfcn, scramble, VTY_NEWLINE);
+ vty_out(vty, "%% Unable to add UARFCN: (%u, %u) is already added%s",
+ arfcn, scramble, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3588,7 +3566,7 @@ DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd,
struct gsm_bts *bts = vty->index;
if (bts_uarfcn_del(bts, atoi(argv[0]), atoi(argv[1])) < 0) {
- vty_out(vty, "Unable to delete uarfcn: pair not found%s",
+ vty_out(vty, "%% Unable to delete uarfcn: pair not found%s",
VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3707,7 +3685,11 @@ DEFUN(cfg_bts_no_acc_ramping, cfg_bts_no_acc_ramping_cmd,
if (acc_ramp_is_enabled(&bts->acc_ramp)) {
acc_ramp_abort(&bts->acc_ramp);
acc_ramp_set_enabled(&bts->acc_ramp, false);
- gsm_bts_set_system_infos(bts);
+ if (gsm_bts_set_system_infos(bts) != 0) {
+ vty_out(vty, "%% Filed to (re)generate System Information "
+ "messages, check the logs%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
return CMD_SUCCESS;
@@ -3734,9 +3716,9 @@ DEFUN(cfg_bts_acc_ramping_step_interval,
error = acc_ramp_set_step_interval(&bts->acc_ramp, atoi(argv[0]));
if (error != 0) {
if (error == -ERANGE)
- vty_out(vty, "Unable to set ACC ramp step interval: value out of range%s", VTY_NEWLINE);
+ vty_out(vty, "%% Unable to set ACC ramp step interval: value out of range%s", VTY_NEWLINE);
else
- vty_out(vty, "Unable to set ACC ramp step interval: unknown error%s", VTY_NEWLINE);
+ vty_out(vty, "%% Unable to set ACC ramp step interval: unknown error%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3757,9 +3739,9 @@ DEFUN(cfg_bts_acc_ramping_step_size,
error = acc_ramp_set_step_size(&bts->acc_ramp, atoi(argv[0]));
if (error != 0) {
if (error == -ERANGE)
- vty_out(vty, "Unable to set ACC ramp step size: value out of range%s", VTY_NEWLINE);
+ vty_out(vty, "%% Unable to set ACC ramp step size: value out of range%s", VTY_NEWLINE);
else
- vty_out(vty, "Unable to set ACC ramp step size: unknown error%s", VTY_NEWLINE);
+ vty_out(vty, "%% Unable to set ACC ramp step size: unknown error%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3778,7 +3760,7 @@ DEFUN(cfg_bts_acc_ramping_chan_load,
rc = acc_ramp_set_chan_load_thresholds(&bts->acc_ramp, atoi(argv[0]), atoi(argv[1]));
if (rc < 0) {
- vty_out(vty, "Unable to set ACC channel load thresholds%s", VTY_NEWLINE);
+ vty_out(vty, "%% Unable to set ACC channel load thresholds%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3909,20 +3891,20 @@ DEFUN(cfg_bts_depends_on, cfg_bts_depends_on_cmd,
if (!is_ipaccess_bts(bts)) {
- vty_out(vty, "This feature is only available for IP systems.%s",
+ vty_out(vty, "%% This feature is only available for IP systems.%s",
VTY_NEWLINE);
return CMD_WARNING;
}
other_bts = gsm_bts_num(bts->network, dep);
if (!other_bts || !is_ipaccess_bts(other_bts)) {
- vty_out(vty, "This feature is only available for IP systems.%s",
+ vty_out(vty, "%% This feature is only available for IP systems.%s",
VTY_NEWLINE);
return CMD_WARNING;
}
if (dep >= bts->nr) {
- vty_out(vty, "%%Need to depend on an already declared unit.%s",
+ vty_out(vty, "%% Need to depend on an already declared unit.%s",
VTY_NEWLINE);
return CMD_WARNING;
}
@@ -3964,13 +3946,13 @@ static int get_amr_from_arg(struct vty *vty, int argc, const char *argv[], int f
for (i = 0; i < argc; i++) {
mode = atoi(argv[i]);
if (mode_prev > mode) {
- vty_out(vty, "Modes must be listed in order%s",
+ vty_out(vty, "%% Modes must be listed in order%s",
VTY_NEWLINE);
return -1;
}
if (mode_prev == mode) {
- vty_out(vty, "Modes must be unique %s", VTY_NEWLINE);
+ vty_out(vty, "%% Modes must be unique %s", VTY_NEWLINE);
return -2;
}
mode_prev = mode;
@@ -4063,7 +4045,7 @@ static int check_amr_config(struct vty *vty)
rc = gsm48_multirate_config(NULL, mr_conf, mr->ms_mode, mr->num_modes);
if (rc != 0) {
vty_out(vty,
- "Invalid AMR multirate configuration (tch-f, ms) - check parameters%s",
+ "%% Invalid AMR multirate configuration (tch-f, ms) - check parameters%s",
VTY_NEWLINE);
vty_rc = CMD_WARNING;
}
@@ -4071,7 +4053,7 @@ static int check_amr_config(struct vty *vty)
rc = gsm48_multirate_config(NULL, mr_conf, mr->bts_mode, mr->num_modes);
if (rc != 0) {
vty_out(vty,
- "Invalid AMR multirate configuration (tch-f, bts) - check parameters%s",
+ "%% Invalid AMR multirate configuration (tch-f, bts) - check parameters%s",
VTY_NEWLINE);
vty_rc = CMD_WARNING;
}
@@ -4081,7 +4063,7 @@ static int check_amr_config(struct vty *vty)
rc = gsm48_multirate_config(NULL, mr_conf, mr->ms_mode, mr->num_modes);
if (rc != 0) {
vty_out(vty,
- "Invalid AMR multirate configuration (tch-h, ms) - check parameters%s",
+ "%% Invalid AMR multirate configuration (tch-h, ms) - check parameters%s",
VTY_NEWLINE);
vty_rc = CMD_WARNING;
}
@@ -4089,7 +4071,7 @@ static int check_amr_config(struct vty *vty)
rc = gsm48_multirate_config(NULL, mr_conf, mr->bts_mode, mr->num_modes);
if (rc != 0) {
vty_out(vty,
- "Invalid AMR multirate configuration (tch-h, bts) - check parameters%s",
+ "%% Invalid AMR multirate configuration (tch-h, bts) - check parameters%s",
VTY_NEWLINE);
vty_rc = CMD_WARNING;
}
@@ -4330,7 +4312,7 @@ DEFUN(cfg_bts_t3113_dynamic, cfg_bts_t3113_dynamic_cmd,
bts->T3113_dynamic = true;
break;
default:
- vty_out(vty, "T%d cannot be set to dynamic%s", d->T, VTY_NEWLINE);
+ vty_out(vty, "%% T%d cannot be set to dynamic%s", d->T, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4356,7 +4338,7 @@ DEFUN(cfg_bts_no_t3113_dynamic, cfg_bts_no_t3113_dynamic_cmd,
bts->T3113_dynamic = false;
break;
default:
- vty_out(vty, "T%d already is non-dynamic%s", d->T, VTY_NEWLINE);
+ vty_out(vty, "%% T%d already is non-dynamic%s", d->T, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4613,9 +4595,10 @@ DEFUN(cfg_ts_hopping,
int enabled = atoi(argv[0]);
if (enabled && !osmo_bts_has_feature(&ts->trx->bts->model->features, BTS_FEAT_HOPPING)) {
- vty_out(vty, "BTS model does not support hopping%s",
- VTY_NEWLINE);
- return CMD_WARNING;
+ vty_out(vty, "%% BTS model does not seem to support freq. hopping%s", VTY_NEWLINE);
+ /* Allow enabling frequency hopping anyway, because the BTS might not have
+ * connected yet (thus not sent the feature vector), so we cannot know for
+ * sure. Jet print a warning and let it go. */
}
ts->hopping.enabled = enabled;
@@ -4691,6 +4674,19 @@ DEFUN(cfg_ts_arfcn_del,
return CMD_SUCCESS;
}
+DEFUN(cfg_ts_arfcn_del_all,
+ cfg_ts_arfcn_del_all_cmd,
+ "hopping arfcn del-all",
+ HOPPING_STR "Configure hopping ARFCN list\n"
+ "Delete all previously configured entries\n")
+{
+ struct gsm_bts_trx_ts *ts = vty->index;
+
+ bitvec_zero(&ts->hopping.arfcns);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_ts_e1_subslot,
cfg_ts_e1_subslot_cmd,
"e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
@@ -4742,19 +4738,19 @@ DEFUN(drop_bts,
bts_nr = atoi(argv[0]);
if (bts_nr >= gsmnet->num_bts) {
- vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
+ vty_out(vty, "%% BTS number must be between 0 and %d. It was %d.%s",
gsmnet->num_bts, bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
bts = gsm_bts_num(gsmnet, bts_nr);
if (!bts) {
- vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
+ vty_out(vty, "%% BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
if (!is_ipaccess_bts(bts)) {
- vty_out(vty, "This command only works for ipaccess.%s", VTY_NEWLINE);
+ vty_out(vty, "%% This command only works for ipaccess.%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4768,7 +4764,7 @@ DEFUN(drop_bts,
ipaccess_drop_rsl(trx, "vty");
}
} else {
- vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
+ vty_out(vty, "%% Argument must be 'oml' or 'rsl'.%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4789,19 +4785,19 @@ DEFUN(restart_bts, restart_bts_cmd,
bts_nr = atoi(argv[0]);
if (bts_nr >= gsmnet->num_bts) {
- vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
+ vty_out(vty, "%% BTS number must be between 0 and %d. It was %d.%s",
gsmnet->num_bts, bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
bts = gsm_bts_num(gsmnet, bts_nr);
if (!bts) {
- vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
+ vty_out(vty, "%% BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
if (!is_ipaccess_bts(bts) || is_sysmobts_v2(bts)) {
- vty_out(vty, "This command only works for ipaccess nanoBTS.%s",
+ vty_out(vty, "%% This command only works for ipaccess nanoBTS.%s",
VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4826,18 +4822,22 @@ DEFUN(bts_resend, bts_resend_cmd,
bts_nr = atoi(argv[0]);
if (bts_nr >= gsmnet->num_bts) {
- vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
+ vty_out(vty, "%% BTS number must be between 0 and %d. It was %d.%s",
gsmnet->num_bts, bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
bts = gsm_bts_num(gsmnet, bts_nr);
if (!bts) {
- vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
+ vty_out(vty, "%% BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
- gsm_bts_set_system_infos(bts);
+ if (gsm_bts_set_system_infos(bts) != 0) {
+ vty_out(vty, "%% Filed to (re)generate System Information "
+ "messages, check the logs%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
return CMD_SUCCESS;
}
@@ -4872,7 +4872,7 @@ DEFUN(smscb_cmd, smscb_cmd_cmd,
}
rc = osmo_hexparse(argv[3], buf, sizeof(buf));
if (rc < 0 || rc > sizeof(buf)) {
- vty_out(vty, "Error parsing HEXSTRING%s", VTY_NEWLINE);
+ vty_out(vty, "%% Error parsing HEXSTRING%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4885,7 +4885,7 @@ DEFUN(smscb_cmd, smscb_cmd_cmd,
else if (!strcmp(type_str, "default"))
cb_cmd.command = RSL_CB_CMD_TYPE_DEFAULT;
else {
- vty_out(vty, "Error parsing type%s", VTY_NEWLINE);
+ vty_out(vty, "%% Error parsing type%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4903,7 +4903,7 @@ DEFUN(smscb_cmd, smscb_cmd_cmd,
cb_cmd.last_block = RSL_CB_CMD_LASTBLOCK_4;
break;
default:
- vty_out(vty, "Error parsing LASTBLOCK%s", VTY_NEWLINE);
+ vty_out(vty, "%% Error parsing LASTBLOCK%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -4992,57 +4992,157 @@ DEFUN(pdch_act, pdch_act_cmd,
}
-/* configure the lchan for a single AMR mode (as specified) */
-static int lchan_set_single_amr_mode(struct vty *vty, struct gsm_lchan *lchan, uint8_t amr_mode)
+
+/* Activate / Deactivate a single lchan with a specific codec mode */
+static int lchan_act_single(struct vty *vty, struct gsm_lchan *lchan, const char *codec_str, int amr_mode, int activate)
{
- struct amr_multirate_conf mr;
- struct gsm48_multi_rate_conf *mr_conf;
- int rc, vty_rc = CMD_SUCCESS;
- mr_conf = (struct gsm48_multi_rate_conf *) &mr.gsm48_ie;
-
- if (amr_mode > 7)
- return -1;
-
- memset(&mr, 0, sizeof(mr));
- mr_conf->ver = 1;
- /* bit-mask of supported modes, only one bit is set. Reflects
- * Figure 10.5.2.47a where there are no thershold and only a
- * single mode */
- mr.gsm48_ie[1] = 1 << amr_mode;
-
- mr.ms_mode[0].mode = amr_mode;
- mr.bts_mode[0].mode = amr_mode;
- mr.num_modes = 1;
-
- /* encode this configuration into the lchan for both uplink and
- * downlink direction */
- rc = gsm48_multirate_config(lchan->mr_ms_lv, mr_conf, mr.ms_mode, mr.num_modes);
- if (rc != 0) {
- vty_out(vty,
- "Invalid AMR multirate configuration (%s, amr mode %d, ms) - check parameters%s",
- gsm_lchant_name(lchan->type), amr_mode, VTY_NEWLINE);
- vty_rc = CMD_WARNING;
+ struct lchan_activate_info info = { };
+ uint16_t amr_modes[8] =
+ { GSM0808_SC_CFG_AMR_4_75, GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20, GSM0808_SC_CFG_AMR_5_90,
+ GSM0808_SC_CFG_AMR_6_70, GSM0808_SC_CFG_AMR_7_40, GSM0808_SC_CFG_AMR_7_95, GSM0808_SC_CFG_AMR_10_2,
+ GSM0808_SC_CFG_AMR_12_2 };
+
+ if (activate) {
+ LOG_LCHAN(lchan, LOGL_NOTICE, "attempt from VTY to activate lchan %s with codec %s\n",
+ gsm_lchan_name(lchan), codec_str);
+
+ int lchan_t;
+ if (lchan->fi->state != LCHAN_ST_UNUSED) {
+ vty_out(vty, "%% Cannot activate: Channel busy!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* pick a suitable lchan type */
+ lchan_t = gsm_lchan_type_by_pchan(lchan->ts->pchan_is);
+ if (lchan_t < 0) {
+ if (lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_PDCH && !strcmp(codec_str, "fr"))
+ lchan_t = GSM_LCHAN_TCH_F;
+ else if (lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH && !strcmp(codec_str, "hr"))
+ lchan_t = GSM_LCHAN_TCH_H;
+ else if ((lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_PDCH
+ || lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH)
+ && !strcmp(codec_str, "fr"))
+ lchan_t = GSM_LCHAN_TCH_F;
+ else {
+ vty_out(vty, "%% Cannot activate: Invalid lchan type (%s)!%s",
+ gsm_pchan_name(lchan->ts->pchan_on_init), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ /* configure the lchan */
+ lchan->type = lchan_t;
+ if (!strcmp(codec_str, "hr") || !strcmp(codec_str, "fr")) {
+ info = (struct lchan_activate_info) {
+ .activ_for = FOR_VTY,
+ .chan_mode = GSM48_CMODE_SPEECH_V1,
+ .requires_voice_stream = false,
+ };
+ } else if (!strcmp(codec_str, "efr")) {
+ info = (struct lchan_activate_info) {
+ .activ_for = FOR_VTY,
+ .chan_mode = GSM48_CMODE_SPEECH_EFR,
+ .s15_s0 = amr_modes[amr_mode],
+ .requires_voice_stream = false,
+ };
+ } else if (!strcmp(codec_str, "amr")) {
+ if (amr_mode == -1) {
+ vty_out(vty, "%% AMR requires specification of AMR mode%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ info = (struct lchan_activate_info) {
+ .activ_for = FOR_VTY,
+ .chan_mode = GSM48_CMODE_SPEECH_AMR,
+ .s15_s0 = amr_modes[amr_mode],
+ .requires_voice_stream = false,
+ };
+ } else if (!strcmp(codec_str, "sig")) {
+ info = (struct lchan_activate_info) {
+ .activ_for = FOR_VTY,
+ .chan_mode = GSM48_CMODE_SIGN,
+ .requires_voice_stream = false,
+ };
+ } else {
+ vty_out(vty, "%% Invalid channel mode specified!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ vty_out(vty, "%% activating lchan %s as %s%s", gsm_lchan_name(lchan), gsm_chan_t_name(lchan->type),
+ VTY_NEWLINE);
+ lchan_activate(lchan, &info);
+ } else {
+ LOG_LCHAN(lchan, LOGL_NOTICE, "attempt from VTY to release lchan %s\n", gsm_lchan_name(lchan));
+ if (!lchan->fi) {
+ vty_out(vty, "%% Cannot release: Channel not initialized%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ vty_out(vty, "%% Asking for release of %s in state %s%s", gsm_lchan_name(lchan),
+ osmo_fsm_inst_state_name(lchan->fi), VTY_NEWLINE);
+ lchan_release(lchan, !!(lchan->conn), false, 0);
}
- rc = gsm48_multirate_config(lchan->mr_bts_lv, mr_conf, mr.bts_mode, mr.num_modes);
- if (rc != 0) {
- vty_out(vty,
- "Invalid AMR multirate configuration (%s, amr mode %d, bts) - check parameters%s",
- gsm_lchant_name(lchan->type), amr_mode, VTY_NEWLINE);
- vty_rc = CMD_WARNING;
+
+ return CMD_SUCCESS;
+}
+
+/* Activate / Deactivate a single lchan with a specific codec mode */
+static int lchan_act_trx(struct vty *vty, struct gsm_bts_trx *trx, int activate)
+{
+ int ts_nr;
+ struct gsm_bts_trx_ts *ts;
+ struct gsm_lchan *lchan;
+ char *codec_str;
+ bool skip_next = false;
+
+ for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
+ ts = &trx->ts[ts_nr];
+ ts_for_each_potential_lchan(lchan, ts) {
+ switch (ts->pchan_on_init) {
+ case GSM_PCHAN_SDCCH8_SACCH8C:
+ case GSM_PCHAN_CCCH_SDCCH4_CBCH:
+ case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
+ case GSM_PCHAN_CCCH:
+ case GSM_PCHAN_CCCH_SDCCH4:
+ codec_str = "sig";
+ break;
+ case GSM_PCHAN_TCH_F:
+ case GSM_PCHAN_TCH_F_PDCH:
+ case GSM_PCHAN_TCH_F_TCH_H_PDCH:
+ codec_str = "fr";
+ break;
+ case GSM_PCHAN_TCH_H:
+ codec_str = "hr";
+ break;
+ default:
+ codec_str = NULL;
+ }
+
+ if (codec_str && skip_next == false) {
+ lchan_act_single(vty, lchan, codec_str, -1, activate);
+
+ /* We use GSM_PCHAN_TCH_F_TCH_H_PDCH slots as TCH_F for this test, so we
+ * must not use the TCH_H reserved lchan in subslot 1. */
+ if (ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH)
+ skip_next = true;
+ }
+ else {
+ vty_out(vty, "%% omitting lchan %s%s", gsm_lchan_name(lchan), VTY_NEWLINE);
+ skip_next = false;
+ }
+ }
}
- return vty_rc;
+ return CMD_SUCCESS;
}
/* Debug/Measurement command to activate a given logical channel
* manually in a given mode/codec. This is useful for receiver
* performance testing (FER/RBER/...) */
DEFUN(lchan_act, lchan_act_cmd,
- "bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7> (activate|deactivate) (hr|fr|efr|amr) [<0-7>]",
+ "bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7> (activate|deactivate) (hr|fr|efr|amr|sig) [<0-7>]",
BTS_NR_TRX_TS_SS_STR2
"Manual Channel Activation (e.g. for BER test)\n"
"Manual Channel Deactivation (e.g. for BER test)\n"
- "Half-Rate v1\n" "Full-Rate\n" "Enhanced Full Rate\n" "Adaptive Multi-Rate\n" "AMR Mode\n")
+ "Half-Rate v1\n" "Full-Rate\n" "Enhanced Full Rate\n" "Adaptive Multi-Rate\n" "Signalling\n" "AMR Mode\n")
{
struct gsm_bts_trx_ts *ts;
struct gsm_lchan *lchan;
@@ -5050,6 +5150,10 @@ DEFUN(lchan_act, lchan_act_cmd,
const char *act_str = argv[4];
const char *codec_str = argv[5];
int activate;
+ int amr_mode = -1;
+
+ if (argc > 6)
+ amr_mode = atoi(argv[6]);
ts = vty_get_ts(vty, argv[0], argv[1], argv[2]);
if (!ts)
@@ -5062,59 +5166,115 @@ DEFUN(lchan_act, lchan_act_cmd,
else
activate = 0;
- /* FIXME: allow dynamic channels with switchover, lchan_activate(lchan, FOR_VTY) */
- if (ss_nr >= pchan_subslots(ts->pchan_is)) {
- vty_out(vty, "%% subslot index %d too large for physical channel %s (%u slots)%s",
- ss_nr, gsm_pchan_name(ts->pchan_is), pchan_subslots(ts->pchan_is),
- VTY_NEWLINE);
+ return lchan_act_single(vty, lchan, codec_str, amr_mode, activate);
+}
+
+#define ACTIVATE_ALL_LCHANS_STR "Manual Channel Activation of all logical channels (e.g. for BER test)\n"
+#define DEACTIVATE_ALL_LCHANS_STR "Manual Channel Deactivation of all logical channels (e.g. for BER test)\n"
+
+/* Similar to lchan_act, but activates all lchans on the network at once,
+ * this is intended to perform lab tests / measurements. */
+DEFUN_HIDDEN(lchan_act_bts, lchan_act_all_cmd,
+ "(activate-all-lchan|deactivate-all-lchan)",
+ ACTIVATE_ALL_LCHANS_STR
+ DEACTIVATE_ALL_LCHANS_STR)
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+ const char *act_str = argv[0];
+ int activate;
+ int bts_nr;
+ struct gsm_bts *bts;
+ int trx_nr;
+ struct gsm_bts_trx *trx;
+
+ if (!strcmp(act_str, "activate-all-lchan"))
+ activate = 1;
+ else
+ activate = 0;
+
+ for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
+ bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
+ for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
+ trx = gsm_bts_trx_num(bts, trx_nr);
+ lchan_act_trx(vty, trx, activate);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+/* Similar to lchan_act, but activates all lchans on the specified BTS at once,
+ * this is intended to perform lab tests / measurements. */
+DEFUN_HIDDEN(lchan_act_all_bts, lchan_act_all_bts_cmd,
+ "bts <0-255> (activate-all-lchan|deactivate-all-lchan)",
+ "BTS Specific Commands\n" BTS_NR_STR
+ ACTIVATE_ALL_LCHANS_STR
+ DEACTIVATE_ALL_LCHANS_STR)
+{
+ int bts_nr = atoi(argv[0]);
+ const char *act_str = argv[1];
+ int activate;
+ struct gsm_bts *bts;
+ int trx_nr;
+ struct gsm_bts_trx *trx;
+
+ if (!strcmp(act_str, "activate-all-lchan"))
+ activate = 1;
+ else
+ activate = 0;
+
+ bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
+ if (!bts) {
+ vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
- if (activate) {
- int lchan_t;
- if (lchan->fi->state != LCHAN_ST_UNUSED) {
- vty_out(vty, "%% Cannot activate: Channel busy!%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- lchan_t = gsm_lchan_type_by_pchan(ts->pchan_is);
- if (lchan_t < 0)
- return CMD_WARNING;
- /* configure the lchan */
- lchan->type = lchan_t;
- lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
- if (!strcmp(codec_str, "hr") || !strcmp(codec_str, "fr"))
- lchan->tch_mode = GSM48_CMODE_SPEECH_V1;
- else if (!strcmp(codec_str, "efr"))
- lchan->tch_mode = GSM48_CMODE_SPEECH_EFR;
- else if (!strcmp(codec_str, "amr")) {
- int amr_mode, vty_rc;
- if (argc < 7) {
- vty_out(vty, "%% AMR requires specification of AMR mode%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- amr_mode = atoi(argv[6]);
- lchan->tch_mode = GSM48_CMODE_SPEECH_AMR;
- vty_rc = lchan_set_single_amr_mode(vty, lchan, amr_mode);
- if (vty_rc != CMD_SUCCESS)
- return vty_rc;
- }
- vty_out(vty, "%% activating lchan %s%s", gsm_lchan_name(lchan), VTY_NEWLINE);
- rsl_tx_chan_activ(lchan, RSL_ACT_TYPE_INITIAL, 0);
- if (is_ipaccess_bts(lchan->ts->trx->bts))
- rsl_tx_ipacc_crcx(lchan);
- } else {
- if (!lchan->fi) {
- vty_out(vty, "%% Cannot release: Channel not initialized%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- vty_out(vty, "%% Asking for release of %s in state %s%s", gsm_lchan_name(lchan),
- osmo_fsm_inst_state_name(lchan->fi), VTY_NEWLINE);
- lchan_release(lchan, !!(lchan->conn), false, 0);
+ for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
+ trx = gsm_bts_trx_num(bts, trx_nr);
+ lchan_act_trx(vty, trx, activate);
}
return CMD_SUCCESS;
}
+/* Similar to lchan_act, but activates all lchans on the specified BTS at once,
+ * this is intended to perform lab tests / measurements. */
+DEFUN_HIDDEN(lchan_act_all_trx, lchan_act_all_trx_cmd,
+ "bts <0-255> trx <0-255> (activate-all-lchan|deactivate-all-lchan)",
+ "BTS for manual command\n" BTS_NR_STR
+ "TRX for manual command\n" TRX_NR_STR
+ ACTIVATE_ALL_LCHANS_STR
+ DEACTIVATE_ALL_LCHANS_STR)
+{
+ int bts_nr = atoi(argv[0]);
+ int trx_nr = atoi(argv[1]);
+ const char *act_str = argv[2];
+ int activate;
+ struct gsm_bts *bts;
+ struct gsm_bts_trx *trx;
+
+ if (!strcmp(act_str, "activate-all-lchan"))
+ activate = 1;
+ else
+ activate = 0;
+
+ bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
+ if (!bts) {
+ vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ trx = gsm_bts_trx_num(bts, trx_nr);
+ if (!bts) {
+ vty_out(vty, "%% No such TRX (%d)%s", trx_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ lchan_act_trx(vty, trx, activate);
+
+ return CMD_SUCCESS;
+}
+
/* Debug command to send lchans from state LCHAN_ST_UNUSED to state
* LCHAN_ST_BORKEN and vice versa. */
DEFUN_HIDDEN(lchan_set_borken, lchan_set_borken_cmd,
@@ -5425,26 +5585,49 @@ DEFUN(cfg_net_meas_feed_scenario, cfg_net_meas_feed_scenario_cmd,
return CMD_SUCCESS;
}
-DEFUN(show_timer, show_timer_cmd,
- "show timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
+static void legacy_timers(struct vty *vty, const char **T_arg)
+{
+ if (!strcmp((*T_arg), "T993111") || !strcmp((*T_arg), "t993111")) {
+ vty_out(vty, "%% Legacy: timer T993111 is now X3111%s", VTY_NEWLINE);
+ (*T_arg) = "X3111";
+ } else if (!strcmp((*T_arg), "T993210") || !strcmp((*T_arg), "t993210")) {
+ vty_out(vty, "%% Legacy: timer T993210 is now X3210%s", VTY_NEWLINE);
+ (*T_arg) = "X3210";
+ } else if (!strcmp((*T_arg), "T999") || !strcmp((*T_arg), "t999")) {
+ vty_out(vty, "%% Legacy: timer T999 is now X4%s", VTY_NEWLINE);
+ (*T_arg) = "X4";
+ }
+}
+
+/* LEGACY TIMER COMMAND. The proper commands are added by osmo_tdef_vty_groups_init(), using explicit timer group
+ * naming. The old groupless timer command accesses the 'net' group only, but is still available. */
+DEFUN_HIDDEN(show_timer, show_timer_cmd,
+ "show timer " OSMO_TDEF_VTY_ARG_T,
SHOW_STR "Show timers\n"
OSMO_TDEF_VTY_DOC_T)
{
struct gsm_network *net = gsmnet_from_vty(vty);
- const char *T_arg = argc > 0 ? argv[0] : NULL;
+ const char *T_arg = argv[0];
+ if (T_arg)
+ legacy_timers(vty, &T_arg);
return osmo_tdef_vty_show_cmd(vty, net->T_defs, T_arg, NULL);
}
-DEFUN(cfg_net_timer, cfg_net_timer_cmd,
- "timer " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
+/* LEGACY TIMER COMMAND. The proper commands are added by osmo_tdef_vty_groups_init(), using explicit timer group
+ * naming. The old groupless timer command accesses the 'net' group only, but is still available. */
+DEFUN_HIDDEN(cfg_net_timer, cfg_net_timer_cmd,
+ "timer " OSMO_TDEF_VTY_ARG_T " " OSMO_TDEF_VTY_ARG_VAL_OPTIONAL,
"Configure or show timers\n"
OSMO_TDEF_VTY_DOC_SET)
{
struct gsm_network *net = gsmnet_from_vty(vty);
+ const char *mod_argv[argc];
+ memcpy(mod_argv, argv, sizeof(mod_argv));
+ legacy_timers(vty, &mod_argv[0]);
/* If any arguments are missing, redirect to 'show' */
if (argc < 2)
- return show_timer(self, vty, argc, argv);
- return osmo_tdef_vty_set_cmd(vty, net->T_defs, argv);
+ return show_timer(self, vty, argc, mod_argv);
+ return osmo_tdef_vty_set_cmd(vty, net->T_defs, mod_argv);
}
DEFUN(cfg_net_allow_unusable_timeslots, cfg_net_allow_unusable_timeslots_cmd,
@@ -5485,7 +5668,7 @@ DEFUN(cfg_net_msc, cfg_net_msc_cmd,
msc = osmo_msc_data_alloc(bsc_gsmnet, index);
if (!msc) {
- vty_out(vty, "%%Failed to allocate MSC data.%s", VTY_NEWLINE);
+ vty_out(vty, "%% Failed to allocate MSC data.%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -6141,7 +6324,7 @@ DEFUN(logging_fltr_imsi,
bsc_subscr = bsc_subscr_find_or_create_by_imsi(bsc_gsmnet->bsc_subscribers, imsi);
if (!bsc_subscr) {
- vty_out(vty, "%%failed to enable logging for subscriber with IMSI(%s)%s",
+ vty_out(vty, "%% failed to enable logging for subscriber with IMSI(%s)%s",
imsi, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -6155,7 +6338,7 @@ DEFUN(logging_fltr_imsi,
static void dump_one_sub(struct vty *vty, struct bsc_subscr *bsub)
{
- vty_out(vty, " %15s %08x %5u %d%s", bsub->imsi, bsub->tmsi, bsub->lac, bsub->use_count,
+ vty_out(vty, " %15s %08x %d%s", bsub->imsi, bsub->tmsi, bsub->use_count,
VTY_NEWLINE);
}
@@ -6166,8 +6349,8 @@ DEFUN(show_subscr_all,
{
struct bsc_subscr *bsc_subscr;
- vty_out(vty, " IMSI TMSI LAC Use%s", VTY_NEWLINE);
- /* " 001010123456789 ffffffff 65534 1" */
+ vty_out(vty, " IMSI TMSI Use%s", VTY_NEWLINE);
+ /* " 001010123456789 ffffffff 1" */
llist_for_each_entry(bsc_subscr, bsc_gsmnet->bsc_subscribers, entry)
dump_one_sub(vty, bsc_subscr);
@@ -6405,6 +6588,9 @@ int bsc_vty_init(struct gsm_network *network)
install_element(GSMNET_NODE, &cfg_net_timer_cmd);
install_element(GSMNET_NODE, &cfg_net_allow_unusable_timeslots_cmd);
+ /* Timer configuration commands (generic osmo_tdef API) */
+ osmo_tdef_vty_groups_init(GSMNET_NODE, bsc_tdef_group);
+
install_element_ve(&bsc_show_net_cmd);
install_element_ve(&show_bts_cmd);
install_element_ve(&show_bts_fail_rep_cmd);
@@ -6585,6 +6771,7 @@ int bsc_vty_init(struct gsm_network *network)
install_element(TS_NODE, &cfg_ts_maio_cmd);
install_element(TS_NODE, &cfg_ts_arfcn_add_cmd);
install_element(TS_NODE, &cfg_ts_arfcn_del_cmd);
+ install_element(TS_NODE, &cfg_ts_arfcn_del_all_cmd);
install_element(TS_NODE, &cfg_ts_e1_subslot_cmd);
install_element(ENABLE_NODE, &drop_bts_cmd);
@@ -6592,6 +6779,9 @@ int bsc_vty_init(struct gsm_network *network)
install_element(ENABLE_NODE, &bts_resend_cmd);
install_element(ENABLE_NODE, &pdch_act_cmd);
install_element(ENABLE_NODE, &lchan_act_cmd);
+ install_element(ENABLE_NODE, &lchan_act_all_cmd);
+ install_element(ENABLE_NODE, &lchan_act_all_bts_cmd);
+ install_element(ENABLE_NODE, &lchan_act_all_trx_cmd);
install_element(ENABLE_NODE, &lchan_mdcx_cmd);
install_element(ENABLE_NODE, &lchan_set_borken_cmd);
diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c
index 4318b7ef9..ce1b20068 100644
--- a/src/osmo-bsc/bts.c
+++ b/src/osmo-bsc/bts.c
@@ -120,62 +120,6 @@ int gsm_bts_model_register(struct gsm_bts_model *model)
return 0;
}
-static const struct osmo_stat_item_desc bts_stat_desc[] = {
- [BTS_STAT_CHAN_LOAD_AVERAGE] = { "chanloadavg", "Channel load average", "%", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_USED] = { "chan_ccch_sdcch4:used",
- "Number of CCCH+SDCCH4 channels used", "", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL] = { "chan_ccch_sdcch4:total",
- "Number of CCCH+SDCCH4 channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_USED] = { "chan_tch_f:used",
- "Number of TCH/F channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_TOTAL] = { "chan_tch_f:total",
- "Number of TCH/F channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_H_USED] = { "chan_tch_h:used",
- "Number of TCH/H channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_H_TOTAL] = { "chan_tch_h:total",
- "Number of TCH/H channels total", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_USED] = { "chan_sdcch8:used",
- "Number of SDCCH8 channels used", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_TOTAL] = { "chan_sdcch8:total",
- "Number of SDCCH8 channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_PDCH_USED] = { "chan_tch_f_pdch:used",
- "Number of TCH/F_PDCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_PDCH_TOTAL] = { "chan_tch_f_pdch:total",
- "Number of TCH/F_PDCH channels total", "", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED] = { "chan_ccch_sdcch4_cbch:used",
- "Number of CCCH+SDCCH4+CBCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL] = { "chan_ccch_sdcch4_cbch:total",
- "Number of CCCH+SDCCH4+CBCH channels total", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_CBCH_USED] = { "chan_sdcch8_cbch:used",
- "Number of SDCCH8+CBCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL] = { "chan_sdcch8_cbch:total",
- "Number of SDCCH8+CBCH channels total", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_USED] = { "chan_tch_f_tch_h_pdch:used",
- "Number of TCH/F_TCH/H_PDCH channels used", "", 16, 0 },
- [BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_TOTAL] = { "chan_tch_f_tch_h_pdch:total",
- "Number of TCH/F_TCH/H_PDCH channels total", "", 16, 0 },
- [BTS_STAT_T3122] = { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator",
- "s", 16, GSM_T3122_DEFAULT },
- [BTS_STAT_RACH_BUSY] = { "rach_busy",
- "RACH slots with signal above threshold", "%", 16, 0 },
- [BTS_STAT_RACH_ACCESS] = { "rach_access",
- "RACH slots with access bursts in them", "%", 16, 0 },
- [BTS_STAT_OML_CONNECTED] = { "oml_connected", "Number of OML links connected", "", 16, 0 },
- [BTS_STAT_RSL_CONNECTED] = { "rsl_connected", "Number of RSL links connected", "", 16, 0 },
- [BTS_STAT_LCHAN_BORKEN] = { "lchan_borken",
- "Number of lchans in the BORKEN state", "", 16, 0 },
- [BTS_STAT_TS_BORKEN] = { "ts_borken",
- "Number of timeslots in the BORKEN state", "", 16, 0 },
-};
-
-static const struct osmo_stat_item_group_desc bts_statg_desc = {
- .group_name_prefix = "bts",
- .group_description = "base transceiver station",
- .class_id = OSMO_STATS_CLASS_GLOBAL,
- .num_items = ARRAY_SIZE(bts_stat_desc),
- .item_desc = bts_stat_desc,
-};
-
static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
static const uint8_t bts_cell_timer_default[] =
{ 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
@@ -319,6 +263,7 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num)
INIT_LLIST_HEAD(&bts->loc_list);
INIT_LLIST_HEAD(&bts->local_neighbors);
INIT_LLIST_HEAD(&bts->oml_fail_rep);
+ INIT_LLIST_HEAD(&bts->chan_rqd_queue);
/* Enable all codecs by default. These get reset to a more fine grained selection IF a
* 'codec-support' config appears in the config file (see bsc_vty.c). */
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c
index 49720e5c2..796d20812 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts.c
@@ -185,11 +185,7 @@ static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
}
break;
case NM_OC_RADIO_CARRIER:
- trx = obj;
- if (new_state->operational == NM_OPSTATE_DISABLED &&
- new_state->availability == NM_AVSTATE_OK)
- abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
- trx->nr, 0xff);
+ /* OPSTART done after Set Radio Carrier Attributes ACK is received */
break;
case NM_OC_GPRS_NSE:
bts = container_of(obj, struct gsm_bts, gprs.nse);
@@ -285,16 +281,13 @@ static int sw_activ_rep(struct msgb *mb)
* This code is here to make sure that on start
* a TRX remains locked.
*/
- int rc_state = trx->mo.nm_state.administrative;
/* Patch ARFCN into radio attribute */
struct msgb *msgb = nanobts_attr_radio_get(trx->bts, trx);
abis_nm_set_radio_attr(trx, msgb->data, msgb->len);
msgb_free(msgb);
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff,
- rc_state);
- abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
- trx->nr, 0xff);
+ trx->mo.nm_state.administrative);
break;
}
}
@@ -328,6 +321,21 @@ static void nm_rx_opstart_ack(struct msgb *oml_msg)
}
}
+static void nm_rx_set_radio_attr_ack(struct msgb *oml_msg)
+{
+ struct abis_om_fom_hdr *foh = msgb_l3(oml_msg);
+ struct e1inp_sign_link *sign_link = oml_msg->dst;
+ struct gsm_bts *bts = sign_link->trx->bts;
+ struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
+
+ if (foh->obj_class != NM_OC_RADIO_CARRIER) {
+ LOG_TRX(trx, DNM, LOGL_ERROR, "Set Radio Carrier Attr Ack received on non Radio Carrier object!\n");
+ return;
+ }
+ abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
+ trx->nr, 0xff);
+}
+
/* Callback function to be called every time we receive a signal from NM */
static int bts_ipa_nm_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
@@ -344,6 +352,9 @@ static int bts_ipa_nm_sig_cb(unsigned int subsys, unsigned int signal,
case S_NM_OPSTART_ACK:
nm_rx_opstart_ack(signal_data);
return 0;
+ case S_NM_SET_RADIO_ATTR_ACK:
+ nm_rx_set_radio_attr_ack(signal_data);
+ return 0;
default:
break;
}
diff --git a/src/osmo-bsc/cbsp_link.c b/src/osmo-bsc/cbsp_link.c
index d93bd1a5a..492679942 100644
--- a/src/osmo-bsc/cbsp_link.c
+++ b/src/osmo-bsc/cbsp_link.c
@@ -35,6 +35,19 @@
* TCP port, we expect the CBC to connect to us. If neither of the two is configured,
* CBSP is effectively disabled */
+const struct value_string bsc_cbc_link_mode_names[] = {
+ { BSC_CBC_LINK_MODE_DISABLED, "disabled" },
+ { BSC_CBC_LINK_MODE_SERVER, "server" },
+ { BSC_CBC_LINK_MODE_CLIENT, "client" },
+ {}
+};
+
+const struct osmo_sockaddr_str bsc_cbc_default_server_local_addr = {
+ .af = AF_INET,
+ .ip = "127.0.0.1",
+ .port = CBSP_TCP_PORT,
+};
+
/*********************************************************************************
* CBSP Server (inbound TCP connection from CBC)
*********************************************************************************/
@@ -195,7 +208,7 @@ int bsc_cbc_link_restart(void)
struct bsc_cbc_link *cbc = bsc_gsmnet->cbc;
/* shut down client, if no longer configured */
- if (cbc->client.cli && !cbc->config.cbc_hostname) {
+ if (cbc->client.cli && cbc->mode != BSC_CBC_LINK_MODE_CLIENT) {
LOGP(DCBS, LOGL_NOTICE, "Stopping CBSP client\n");
osmo_stream_cli_close(cbc->client.cli);
osmo_stream_cli_destroy(cbc->client.cli);
@@ -203,7 +216,7 @@ int bsc_cbc_link_restart(void)
}
/* shut down server, if no longer configured */
- if (cbc->config.listen_port == -1) {
+ if (cbc->mode != BSC_CBC_LINK_MODE_SERVER) {
if (cbc->server.srv || cbc->server.link)
LOGP(DCBS, LOGL_NOTICE, "Stopping CBSP server\n");
if (cbc->server.srv) {
@@ -217,10 +230,16 @@ int bsc_cbc_link_restart(void)
}
}
- /* start client, if configured */
- if (cbc->config.cbc_hostname) {
- LOGP(DCBS, LOGL_NOTICE, "Starting CBSP Client (to CBC at %s:%u)\n",
- cbc->config.cbc_hostname, cbc->config.cbc_port);
+ switch (cbc->mode) {
+ case BSC_CBC_LINK_MODE_CLIENT:
+ if (!osmo_sockaddr_str_is_nonzero(&cbc->client.remote_addr)) {
+ LOGP(DCBS, LOGL_ERROR,
+ "Cannot start CBSP in client mode: invalid remote-ip or -port in 'cbc' / 'client')\n");
+ return -1;
+ }
+
+ LOGP(DCBS, LOGL_NOTICE, "Starting CBSP Client (to CBC at " OSMO_SOCKADDR_STR_FMT ")\n",
+ OSMO_SOCKADDR_STR_FMT_ARGS(&cbc->client.remote_addr));
if (!cbc->client.cli) {
cbc->client.cli = osmo_stream_cli_create(cbc);
osmo_stream_cli_set_data(cbc->client.cli, cbc);
@@ -229,32 +248,49 @@ int bsc_cbc_link_restart(void)
osmo_stream_cli_set_read_cb(cbc->client.cli, cbsp_client_read_cb);
}
/* CBC side */
- osmo_stream_cli_set_addr(cbc->client.cli, cbc->config.cbc_hostname);
- osmo_stream_cli_set_port(cbc->client.cli, cbc->config.cbc_port);
+ osmo_stream_cli_set_addr(cbc->client.cli, cbc->client.remote_addr.ip);
+ osmo_stream_cli_set_port(cbc->client.cli, cbc->client.remote_addr.port);
+ /* local side */
+ if (osmo_sockaddr_str_is_set(&cbc->client.local_addr)) {
+ osmo_stream_cli_set_local_addr(cbc->client.cli, cbc->client.local_addr.ip);
+ osmo_stream_cli_set_local_port(cbc->client.cli, cbc->client.local_addr.port);
+ }
/* Close/Reconnect? */
- osmo_stream_cli_open(cbc->client.cli);
- }
+ if (osmo_stream_cli_open(cbc->client.cli) < 0) {
+ LOGP(DCBS, LOGL_ERROR, "Cannot open CBSP client link to " OSMO_SOCKADDR_STR_FMT "\n",
+ OSMO_SOCKADDR_STR_FMT_ARGS(&cbc->client.remote_addr));
+ return -1;
+ }
+ return 0;
- /* start server, if configured */
- if (cbc->config.listen_port != -1) {
- LOGP(DCBS, LOGL_NOTICE, "Starting CBSP Server (bound to %s:%u)\n",
- cbc->config.listen_hostname, cbc->config.listen_port);
+ case BSC_CBC_LINK_MODE_SERVER:
+ if (!osmo_sockaddr_str_is_set(&cbc->server.local_addr)) {
+ LOGP(DCBS, LOGL_ERROR,
+ "Cannot start CBSP in server mode: invalid local-ip or -port in 'cbc' / 'server')\n");
+ return -1;
+ }
+ LOGP(DCBS, LOGL_NOTICE, "Starting CBSP Server (listening at " OSMO_SOCKADDR_STR_FMT ")\n",
+ OSMO_SOCKADDR_STR_FMT_ARGS(&cbc->server.local_addr));
if (!cbc->server.link) {
LOGP(DCBS, LOGL_NOTICE, "Creating CBSP Server\n");
cbc->server.link = osmo_stream_srv_link_create(cbc);
osmo_stream_srv_link_set_data(cbc->server.link, cbc);
osmo_stream_srv_link_set_accept_cb(cbc->server.link, cbsp_srv_link_accept_cb);
- osmo_stream_srv_link_set_addr(cbc->server.link, cbc->config.listen_hostname);
- osmo_stream_srv_link_set_port(cbc->server.link, cbc->config.listen_port);
+ osmo_stream_srv_link_set_addr(cbc->server.link, cbc->server.local_addr.ip);
+ osmo_stream_srv_link_set_port(cbc->server.link, cbc->server.local_addr.port);
if (osmo_stream_srv_link_open(cbc->server.link) < 0) {
- LOGP(DCBS, LOGL_ERROR, "Cannot open CBSP Server link on %s:%u\n",
- cbc->config.listen_hostname, cbc->config.listen_port);
+ LOGP(DCBS, LOGL_ERROR, "Cannot open CBSP Server link at " OSMO_SOCKADDR_STR_FMT ")\n",
+ OSMO_SOCKADDR_STR_FMT_ARGS(&cbc->server.local_addr));
+ return -1;
}
}
+ return 0;
+
+ default:
+ return 0;
}
- return 0;
}
/*! Encode + Transmit a 'decoded' CBSP message over given CBC link
@@ -301,60 +337,114 @@ DEFUN(cfg_cbc, cfg_cbc_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_cbc_remote_ip, cfg_cbc_remote_ip_cmd,
- "remote-ip A.B.C.D",
- "IP Address of the Cell Broadcast Centre\n"
- "IP Address of the Cell Broadcast Centre\n")
+DEFUN(cfg_cbc_mode, cfg_cbc_mode_cmd,
+ "mode (server|client|disabled)",
+ "Set OsmoBSC as CBSP server or client\n"
+ "CBSP Server: listen for inbound TCP connections from a remote Cell Broadcast Centre\n"
+ "CBSP Client: establish outbound TCP connection to a remote Cell Broadcast Centre\n"
+ "Disable CBSP link\n")
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
- osmo_talloc_replace_string(cbc, &cbc->config.cbc_hostname, argv[0]);
+ cbc->mode = get_string_value(bsc_cbc_link_mode_names, argv[0]);
+ OSMO_ASSERT(cbc->mode >= 0);
+
+ /* Immediately restart/stop CBSP only when coming from a telnet session. The settings from the config file take
+ * effect in osmo_bsc_main.c's invocation of bsc_cbc_link_restart(). */
+ if (vty->type != VTY_FILE)
+ bsc_cbc_link_restart();
+
return CMD_SUCCESS;
}
-DEFUN(cfg_cbc_no_remote_ip, cfg_cbc_no_remote_ip_cmd,
- "no remote-ip",
- NO_STR "Remove IP address of CBC; disables outbound CBSP connections\n")
+
+DEFUN(cfg_cbc_server, cfg_cbc_server_cmd,
+ "server", "Configure OsmoBSC's CBSP server role\n")
+{
+ vty->node = CBC_SERVER_NODE;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_cbc_server_local_ip, cfg_cbc_server_local_ip_cmd,
+ "local-ip " VTY_IPV46_CMD,
+ "Set IP Address to listen on for inbound CBSP from a Cell Broadcast Centre\n"
+ "IPv4 address\n" "IPv6 address\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ osmo_sockaddr_str_from_str(&cbc->server.local_addr, argv[0], cbc->server.local_addr.port);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_cbc_server_local_port, cfg_cbc_server_local_port_cmd,
+ "local-port <1-65535>",
+ "Set TCP port to listen on for inbound CBSP from a Cell Broadcast Centre\n"
+ "CBSP port number (Default: " OSMO_STRINGIFY_VAL(CBSP_TCP_PORT) ")\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ cbc->server.local_addr.port = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_cbc_client, cfg_cbc_client_cmd,
+ "client", "Configure OsmoBSC's CBSP client role\n")
+{
+ vty->node = CBC_CLIENT_NODE;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_cbc_client_remote_ip, cfg_cbc_client_remote_ip_cmd,
+ "remote-ip " VTY_IPV46_CMD,
+ "Set IP Address of the Cell Broadcast Centre, to establish CBSP link to\n"
+ "IPv4 address\n" "IPv6 address\n")
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
- talloc_free(cbc->config.cbc_hostname);
- cbc->config.cbc_hostname = NULL;
+ osmo_sockaddr_str_from_str(&cbc->client.remote_addr, argv[0], cbc->client.remote_addr.port);
return CMD_SUCCESS;
}
-DEFUN(cfg_cbc_remote_port, cfg_cbc_remote_port_cmd,
+DEFUN(cfg_cbc_client_remote_port, cfg_cbc_client_remote_port_cmd,
"remote-port <1-65535>",
- "TCP Port number of the Cell Broadcast Centre (Default: 48049)\n"
- "TCP Port number of the Cell Broadcast Centre (Default: 48049)\n")
+ "Set TCP port of the Cell Broadcast Centre, to establish CBSP link to\n"
+ "CBSP port number (Default: " OSMO_STRINGIFY_VAL(CBSP_TCP_PORT) ")\n")
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
- cbc->config.cbc_port = atoi(argv[0]);
+ cbc->client.remote_addr.port = atoi(argv[0]);
return CMD_SUCCESS;
}
-DEFUN(cfg_cbc_listen_port, cfg_cbc_listen_port_cmd,
- "listen-port <1-65535>",
- "Local TCP port at which BSC listens for incoming CBSP connections from CBC\n"
- "Local TCP port at which BSC listens for incoming CBSP connections from CBC\n")
+DEFUN(cfg_cbc_client_local_ip, cfg_cbc_client_local_ip_cmd,
+ "local-ip " VTY_IPV46_CMD,
+ "Set local bind address for the outbound CBSP link to the Cell Broadcast Centre\n"
+ "IPv4 address\n" "IPv6 address\n")
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
- cbc->config.listen_port = atoi(argv[0]);
+ osmo_sockaddr_str_from_str(&cbc->client.local_addr, argv[0], cbc->client.local_addr.port);
return CMD_SUCCESS;
}
-DEFUN(cfg_cbc_no_listen_port, cfg_cbc_no_listen_port_cmd,
- "no listen-port",
- NO_STR "Remove CBSP Listen Port; disables inbound CBSP connections\n")
+
+DEFUN(cfg_cbc_client_local_port, cfg_cbc_client_local_port_cmd,
+ "local-port <1-65535>",
+ "Set local bind port for the outbound CBSP link to the Cell Broadcast Centre\n"
+ "port number\n")
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
- cbc->config.listen_port = -1;
+ cbc->client.local_addr.port = atoi(argv[0]);
return CMD_SUCCESS;
}
-DEFUN(cfg_cbc_listen_ip, cfg_cbc_listen_ip_cmd,
- "listen-ip A.B.C.D",
- "Local IP Address where BSC listens for incoming CBC connections (Default: 0.0.0.0)\n"
- "Local IP Address where BSC listens for incoming CBC connections\n")
+DEFUN(cfg_cbc_client_no_local_ip, cfg_cbc_client_no_local_ip_cmd,
+ "no local-ip",
+ NO_STR "Remove local IP address bind config for the CBSP client mode\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ cbc->client.local_addr = (struct osmo_sockaddr_str){ .port = cbc->client.local_addr.port };
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_cbc_client_no_local_port, cfg_cbc_client_no_local_port_cmd,
+ "no local-port",
+ NO_STR "Remove local TCP port bind config for the CBSP client mode\n")
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
- osmo_talloc_replace_string(cbc, &cbc->config.listen_hostname, argv[0]);
+ cbc->client.local_addr.port = 0;
return CMD_SUCCESS;
}
@@ -364,23 +454,63 @@ static struct cmd_node cbc_node = {
1,
};
+static struct cmd_node cbc_server_node = {
+ CBC_SERVER_NODE,
+ "%s(config-cbc-server)# ",
+ 1,
+};
+
+static struct cmd_node cbc_client_node = {
+ CBC_CLIENT_NODE,
+ "%s(config-cbc-client)# ",
+ 1,
+};
+
static int config_write_cbc(struct vty *vty)
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ bool default_server_local;
+ bool default_client_remote;
+ bool default_client_local;
+
+ default_server_local = !osmo_sockaddr_str_cmp(&cbc->server.local_addr,
+ &bsc_cbc_default_server_local_addr);
+ default_client_remote = !osmo_sockaddr_str_is_set(&cbc->client.remote_addr);
+ default_client_local = !osmo_sockaddr_str_is_set(&cbc->client.local_addr);
+
+ /* If all reflects default values, skip the 'cbc' section */
+ if (cbc->mode == BSC_CBC_LINK_MODE_DISABLED
+ && default_server_local
+ && default_client_remote && default_client_local)
+ return 0;
+
vty_out(vty, "cbc%s", VTY_NEWLINE);
+ vty_out(vty, " mode %s%s", bsc_cbc_link_mode_name(cbc->mode), VTY_NEWLINE);
- if (cbc->config.cbc_hostname) {
- vty_out(vty, " remote-ip %s%s", cbc->config.cbc_hostname, VTY_NEWLINE);
- vty_out(vty, " remote-port %u%s", cbc->config.cbc_port, VTY_NEWLINE);
- } else
- vty_out(vty, " no remote-ip%s", VTY_NEWLINE);
+ if (!default_server_local) {
+ vty_out(vty, " server%s", VTY_NEWLINE);
- if (cbc->config.listen_port >= 0) {
- vty_out(vty, " listen-port %u%s", cbc->config.listen_port, VTY_NEWLINE);
- vty_out(vty, " listen-ip %s%s", cbc->config.listen_hostname, VTY_NEWLINE);
- } else
- vty_out(vty, " no listen-port%s", VTY_NEWLINE);
+ if (strcmp(cbc->server.local_addr.ip, bsc_cbc_default_server_local_addr.ip))
+ vty_out(vty, " local-ip %s%s", cbc->server.local_addr.ip, VTY_NEWLINE);
+ if (cbc->server.local_addr.port != bsc_cbc_default_server_local_addr.port)
+ vty_out(vty, " local-port %u%s", cbc->server.local_addr.port, VTY_NEWLINE);
+ }
+
+ if (!(default_client_remote && default_client_local)) {
+ vty_out(vty, " client%s", VTY_NEWLINE);
+
+ if (osmo_sockaddr_str_is_set(&cbc->client.remote_addr)) {
+ vty_out(vty, " remote-ip %s%s", cbc->client.remote_addr.ip, VTY_NEWLINE);
+ if (cbc->client.remote_addr.port != CBSP_TCP_PORT)
+ vty_out(vty, " remote-port %u%s", cbc->client.remote_addr.port, VTY_NEWLINE);
+ }
+
+ if (cbc->client.local_addr.ip[0])
+ vty_out(vty, " local-ip %s%s", cbc->client.local_addr.ip, VTY_NEWLINE);
+ if (cbc->client.local_addr.port)
+ vty_out(vty, " local-port %u%s", cbc->client.local_addr.port, VTY_NEWLINE);
+ }
return 0;
}
@@ -391,30 +521,136 @@ DEFUN(show_cbc, show_cbc_cmd,
{
struct bsc_cbc_link *cbc = vty_cbc_data(vty);
- if (!cbc->config.cbc_hostname)
- vty_out(vty, "CBSP Client Config: Disabled%s", VTY_NEWLINE);
- else {
- vty_out(vty, "CBSP Client Config: CBC IP=%s, CBC Port=%u%s",
- cbc->config.cbc_hostname, cbc->config.cbc_port, VTY_NEWLINE);
+ switch (cbc->mode) {
+ case BSC_CBC_LINK_MODE_DISABLED:
+ vty_out(vty, "CBSP link is disabled%s", VTY_NEWLINE);
+ break;
+
+ case BSC_CBC_LINK_MODE_SERVER:
+ vty_out(vty, "OsmoBSC is configured as CBSP Server on " OSMO_SOCKADDR_STR_FMT "%s",
+ OSMO_SOCKADDR_STR_FMT_ARGS(&cbc->server.local_addr), VTY_NEWLINE);
+ vty_out(vty, "CBSP Server Connection: %s%s",
+ cbc->server.sock_name ? cbc->server.sock_name : "Disconnected", VTY_NEWLINE);
+ break;
+
+ case BSC_CBC_LINK_MODE_CLIENT:
+ vty_out(vty, "OsmoBSC is configured as CBSP Client to remote CBC at " OSMO_SOCKADDR_STR_FMT "%s",
+ OSMO_SOCKADDR_STR_FMT_ARGS(&cbc->client.remote_addr), VTY_NEWLINE);
vty_out(vty, "CBSP Client Connection: %s%s",
cbc->client.sock_name ? cbc->client.sock_name : "Disconnected", VTY_NEWLINE);
+ break;
}
- if (cbc->config.listen_port < 0)
- vty_out(vty, "CBSP Server Config: Disabled%s\n", VTY_NEWLINE);
- else {
- vty_out(vty, "CBSP Server Config: Listen IP=%s, Port=%u%s\n",
- cbc->config.listen_hostname, cbc->config.listen_port, VTY_NEWLINE);
- vty_out(vty, "CBSP Server Connection: %s%s",
- cbc->server.sock_name ? cbc->server.sock_name : "Disconnected", VTY_NEWLINE);
+ return CMD_SUCCESS;
+}
+
+/* --- Deprecated 'cbc' commands for backwards compat --- */
+
+DEFUN_DEPRECATED(cfg_cbc_remote_ip, cfg_cbc_remote_ip_cmd,
+ "remote-ip A.B.C.D",
+ "IP Address of the Cell Broadcast Centre\n"
+ "IP Address of the Cell Broadcast Centre\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ vty_out(vty, "%% cbc/remote-ip config is deprecated, instead use cbc/client/remote-ip and cbc/ mode%s",
+ VTY_NEWLINE);
+ osmo_sockaddr_str_from_str(&cbc->client.remote_addr, argv[0], cbc->client.remote_addr.port);
+ cbc->mode = BSC_CBC_LINK_MODE_CLIENT;
+ if (vty->type != VTY_FILE)
+ bsc_cbc_link_restart();
+ return CMD_SUCCESS;
+}
+DEFUN_DEPRECATED(cfg_cbc_no_remote_ip, cfg_cbc_no_remote_ip_cmd,
+ "no remote-ip",
+ NO_STR "Remove IP address of CBC; disables outbound CBSP connections\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ vty_out(vty, "%% cbc/remote-ip config is deprecated, instead use cbc/client/remote-ip and cbc/mode%s",
+ VTY_NEWLINE);
+ if (cbc->mode == BSC_CBC_LINK_MODE_CLIENT) {
+ cbc->mode = BSC_CBC_LINK_MODE_DISABLED;
+ if (vty->type != VTY_FILE)
+ bsc_cbc_link_restart();
}
return CMD_SUCCESS;
}
+DEFUN_DEPRECATED(cfg_cbc_remote_port, cfg_cbc_remote_port_cmd,
+ "remote-port <1-65535>",
+ "TCP Port number of the Cell Broadcast Centre (Default: 48049)\n"
+ "TCP Port number of the Cell Broadcast Centre (Default: 48049)\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ vty_out(vty, "%% cbc/remote-port config is deprecated, instead use cbc/client/remote-port%s",
+ VTY_NEWLINE);
+ cbc->client.remote_addr.port = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN_DEPRECATED(cfg_cbc_listen_port, cfg_cbc_listen_port_cmd,
+ "listen-port <1-65535>",
+ "Local TCP port at which BSC listens for incoming CBSP connections from CBC\n"
+ "Local TCP port at which BSC listens for incoming CBSP connections from CBC\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ vty_out(vty, "%% cbc/listen-port config is deprecated, instead use cbc/server/local-port and cbc/mode%s",
+ VTY_NEWLINE);
+ cbc->mode = BSC_CBC_LINK_MODE_SERVER;
+ cbc->server.local_addr.port = atoi(argv[0]);
+ if (vty->type != VTY_FILE)
+ bsc_cbc_link_restart();
+ return CMD_SUCCESS;
+}
+
+DEFUN_DEPRECATED(cfg_cbc_no_listen_port, cfg_cbc_no_listen_port_cmd,
+ "no listen-port",
+ NO_STR "Remove CBSP Listen Port; disables inbound CBSP connections\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ vty_out(vty, "%% cbc/listen-port config is deprecated, instead use cbc/server/local-port and cbc/mode%s",
+ VTY_NEWLINE);
+ if (cbc->mode == BSC_CBC_LINK_MODE_SERVER) {
+ cbc->mode = BSC_CBC_LINK_MODE_DISABLED;
+ if (vty->type != VTY_FILE)
+ bsc_cbc_link_restart();
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN_DEPRECATED(cfg_cbc_listen_ip, cfg_cbc_listen_ip_cmd,
+ "listen-ip A.B.C.D",
+ "Local IP Address where BSC listens for incoming CBC connections (Default: 127.0.0.1)\n"
+ "Local IP Address where BSC listens for incoming CBC connections\n")
+{
+ struct bsc_cbc_link *cbc = vty_cbc_data(vty);
+ vty_out(vty, "%% cbc/listen-ip config is deprecated, instead use cbc/server/local-ip%s",
+ VTY_NEWLINE);
+ osmo_sockaddr_str_from_str(&cbc->server.local_addr, argv[0], cbc->server.local_addr.port);
+ return CMD_SUCCESS;
+}
+
void cbc_vty_init(void)
{
- install_element(VIEW_NODE, &show_cbc_cmd);
+ install_element_ve(&show_cbc_cmd);
+
install_element(CONFIG_NODE, &cfg_cbc_cmd);
install_node(&cbc_node, config_write_cbc);
+ install_element(CBC_NODE, &cfg_cbc_mode_cmd);
+
+ install_element(CBC_NODE, &cfg_cbc_server_cmd);
+ install_node(&cbc_server_node, NULL);
+ install_element(CBC_SERVER_NODE, &cfg_cbc_server_local_ip_cmd);
+ install_element(CBC_SERVER_NODE, &cfg_cbc_server_local_port_cmd);
+
+ install_element(CBC_NODE, &cfg_cbc_client_cmd);
+ install_node(&cbc_client_node, NULL);
+ install_element(CBC_CLIENT_NODE, &cfg_cbc_client_remote_ip_cmd);
+ install_element(CBC_CLIENT_NODE, &cfg_cbc_client_remote_port_cmd);
+ install_element(CBC_CLIENT_NODE, &cfg_cbc_client_local_ip_cmd);
+ install_element(CBC_CLIENT_NODE, &cfg_cbc_client_local_port_cmd);
+ install_element(CBC_CLIENT_NODE, &cfg_cbc_client_no_local_ip_cmd);
+ install_element(CBC_CLIENT_NODE, &cfg_cbc_client_no_local_port_cmd);
+
+ /* Deprecated, for backwards compat */
install_element(CBC_NODE, &cfg_cbc_remote_ip_cmd);
install_element(CBC_NODE, &cfg_cbc_no_remote_ip_cmd);
install_element(CBC_NODE, &cfg_cbc_remote_port_cmd);
diff --git a/src/osmo-bsc/chan_alloc.c b/src/osmo-bsc/chan_alloc.c
index 6829251e3..3569d4eaa 100644
--- a/src/osmo-bsc/chan_alloc.c
+++ b/src/osmo-bsc/chan_alloc.c
@@ -46,7 +46,7 @@ void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts)
llist_for_each_entry(trx, &bts->trx_list, list) {
int i;
- /* skip administratively deactivated tranxsceivers */
+ /* skip administratively deactivated transceivers */
if (!trx_is_usable(trx))
continue;
diff --git a/src/osmo-bsc/gsm_04_08_rr.c b/src/osmo-bsc/gsm_04_08_rr.c
index e54a93719..a7bba0d4e 100644
--- a/src/osmo-bsc/gsm_04_08_rr.c
+++ b/src/osmo-bsc/gsm_04_08_rr.c
@@ -43,6 +43,7 @@
#include <osmocom/bsc/handover_fsm.h>
#include <osmocom/bsc/gsm_08_08.h>
#include <osmocom/bsc/gsm_data.h>
+#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/system_information.h>
#include <osmocom/bsc/bts.h>
@@ -238,8 +239,8 @@ static void mr_config_for_ms(struct gsm_lchan *lchan, struct msgb *msg)
lchan->mr_ms_lv + 1);
}
-
-#define CELL_SEL_IND_AFTER_REL_MAX_BITS (3+MAX_EARFCN_LIST*20+1)
+#define CELL_SEL_IND_AFTER_REL_EARCFN_ENTRY (1+16+4+1+1)
+#define CELL_SEL_IND_AFTER_REL_MAX_BITS (3+MAX_EARFCN_LIST*CELL_SEL_IND_AFTER_REL_EARCFN_ENTRY+1)
#define CELL_SEL_IND_AFTER_REL_MAX_BYTES OSMO_BYTES_FOR_BITS(CELL_SEL_IND_AFTER_REL_MAX_BITS)
/* Generate a CSN.1 encoded "Cell Selection Indicator after release of all TCH and SDCCH"
@@ -262,15 +263,21 @@ static int generate_cell_sel_ind_after_rel(uint8_t *out, unsigned int out_len, c
if (e->arfcn[i] == OSMO_EARFCN_INVALID)
continue;
- /* tailroom must fit one more EARFCN (20 bits), plus the final list term bit. */
- if (bitvec_tailroom_bits(&bv) < 21) {
+ /* tailroom must fit one more EARFCN plus the final list term bit. */
+ if (bitvec_tailroom_bits(&bv) < CELL_SEL_IND_AFTER_REL_EARCFN_ENTRY + 1) {
LOGP(DRR, LOGL_NOTICE, "%s: Not enough room to store EARFCN %u in the "
"Cell Selection Indicator IE\n", gsm_bts_name(bts), e->arfcn[i]);
} else {
bitvec_set_bit(&bv, 1);
bitvec_set_uint(&bv, e->arfcn[i], 16);
- /* No "Measurement Bandwidth" */
- bitvec_set_bit(&bv, 0);
+
+ /* Measurement Bandwidth: 9.1.54 */
+ if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
+ bitvec_set_bit(&bv, 0);
+ else {
+ bitvec_set_bit(&bv, 1);
+ bitvec_set_uint(&bv, e->meas_bw[i], 3);
+ }
/* No "Not Allowed Cells" */
bitvec_set_bit(&bv, 0);
/* No "TARGET_PCID" */
@@ -318,8 +325,8 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan)
msgb_tlv_put(msg, GSM48_IE_CELL_SEL_IND_AFTER_REL, len, buf);
}
- DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
- lchan->nr, lchan->type);
+ DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d RR-Cause: 0x%x '%s'\n",
+ lchan->nr, lchan->type, lchan->release.rr_cause, rr_cause_name(lchan->release.rr_cause));
/* Send actual release request to MS */
return gsm48_sendmsg(msg);
@@ -522,23 +529,24 @@ struct msgb *gsm48_make_ho_cmd(struct gsm_lchan *new_lchan, uint8_t power_comman
if (new_lchan->ts->hopping.enabled) {
struct gsm_bts *bts = new_lchan->ts->trx->bts;
struct gsm48_system_information_type_1 *si1;
- uint8_t *cur;
si1 = GSM_BTS_SI(bts, SYSINFO_TYPE_1);
/* Copy the Cell Chan Desc (ARFCNS in this cell) */
- msgb_put_u8(msg, GSM48_IE_CELL_CH_DESC);
- cur = msgb_put(msg, GSM48_HOCMD_CCHDESC_LEN);
- memcpy(cur, si1->cell_channel_description,
- GSM48_HOCMD_CCHDESC_LEN);
- /* Copy the Mobile Allocation */
- msgb_tlv_put(msg, GSM48_IE_MA_BEFORE,
- new_lchan->ts->hopping.ma_len,
- new_lchan->ts->hopping.ma_data);
+ msgb_tv_fixed_put(msg, GSM48_IE_CELL_CH_DESC,
+ GSM48_HOCMD_CCHDESC_LEN,
+ si1->cell_channel_description);
}
/* FIXME: optional bits for type of synchronization? */
msgb_tv_put(msg, GSM48_IE_CHANMODE_1, new_lchan->tch_mode);
+ /* Mobile Allocation (after time), TLV (see 3GPP TS 44.018, 10.5.2.21) */
+ if (new_lchan->ts->hopping.enabled) {
+ msgb_tlv_put(msg, GSM48_IE_MA_AFTER,
+ new_lchan->ts->hopping.ma_len,
+ new_lchan->ts->hopping.ma_data);
+ }
+
/* in case of multi rate we need to attach a config */
if (new_lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
msgb_tlv_put(msg, GSM48_IE_MUL_RATE_CFG, new_lchan->mr_ms_lv[0],
@@ -653,7 +661,6 @@ int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode)
int gsm48_rx_rr_modif_ack(struct msgb *msg)
{
- int rc;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_chan_mode_modify *mod =
(struct gsm48_chan_mode_modify *) gh->data;
@@ -687,15 +694,7 @@ int gsm48_rx_rr_modif_ack(struct msgb *msg)
break;
}
- /* We've successfully modified the MS side of the channel,
- * now go on to modify the BTS side of the channel */
- rc = rsl_chan_mode_modify_req(msg->lchan);
-
- /* FIXME: we not only need to do this after mode modify, but
- * also after channel activation */
- if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && mod->mode != GSM48_CMODE_SIGN)
- rsl_tx_ipacc_crcx(msg->lchan);
- return rc;
+ return 0;
}
int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
@@ -968,9 +967,9 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
rc = gsm48_rx_rr_modif_ack(msg);
if (rc < 0)
- osmo_fsm_inst_dispatch(msg->lchan->fi, LCHAN_EV_CHAN_MODE_MODIF_ERROR, &rc);
+ osmo_fsm_inst_dispatch(msg->lchan->fi, LCHAN_EV_RR_CHAN_MODE_MODIFY_ERROR, &rc);
else
- osmo_fsm_inst_dispatch(msg->lchan->fi, LCHAN_EV_CHAN_MODE_MODIF_ACK, msg);
+ osmo_fsm_inst_dispatch(msg->lchan->fi, LCHAN_EV_RR_CHAN_MODE_MODIFY_ACK, msg);
break;
case GSM48_MT_RR_CLSM_CHG:
handle_classmark_chg(conn, msg);
@@ -988,6 +987,24 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
break;
}
break;
+ case GSM48_PDISC_CC:
+ /* Make sure that EMERGENCY CALLS can not be made if the
+ * VTY configuration does not permit. */
+ if (msg_type == GSM48_MT_CC_EMERG_SETUP) {
+ if (msg->lchan->ts->trx->bts->si_common.rach_control.t2 & 0x4) {
+ LOG_LCHAN(msg->lchan, LOGL_NOTICE, "MS attempts EMERGENCY SETUP although EMERGENCY CALLS"
+ " are not allowed in sysinfo (spec violation by MS!)\n");
+ lchan_release(msg->lchan, true, true, GSM48_RR_CAUSE_PREMPTIVE_REL);
+ break;
+ }
+ if (!conn->sccp.msc->allow_emerg) {
+ LOG_LCHAN(msg->lchan, LOGL_NOTICE, "MS attempts EMERGENCY SETUP, but EMERGENCY CALLS are"
+ " denied on this BSC (check BTS config!)\n");
+ lchan_release(msg->lchan, true, true, GSM48_RR_CAUSE_PREMPTIVE_REL);
+ break;
+ }
+ }
+ /* fall through */
default:
bsc_dtap(conn, link_id, msg);
break;
diff --git a/src/osmo-bsc/gsm_08_08.c b/src/osmo-bsc/gsm_08_08.c
index d5915f4f0..59032d68e 100644
--- a/src/osmo-bsc/gsm_08_08.c
+++ b/src/osmo-bsc/gsm_08_08.c
@@ -60,7 +60,8 @@ static bool msc_connected(struct gsm_subscriber_connection *conn)
}
/*! BTS->MSC: tell MSC a SAPI was not established. */
-void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
+void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn,
+ uint8_t dlci, enum gsm0808_cause cause)
{
int rc;
struct msgb *resp;
@@ -68,8 +69,9 @@ void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
if (!msc_connected(conn))
return;
- LOGP(DMSC, LOGL_NOTICE, "Tx MSC SAPI N REJECT DLCI=0x%02x\n", dlci);
- resp = gsm0808_create_sapi_reject(dlci);
+ LOGP(DMSC, LOGL_NOTICE, "Tx MSC SAPI N REJECT (dlci=0x%02x, cause='%s')\n",
+ dlci, gsm0808_cause_name(cause));
+ resp = gsm0808_create_sapi_reject_cause(dlci, cause);
rate_ctr_inc(&conn->sccp.msc->msc_ctrs->ctr[MSC_CTR_BSSMAP_TX_DT1_SAPI_N_REJECT]);
rc = osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_TX_SCCP, resp);
if (rc != 0)
@@ -198,6 +200,7 @@ static struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
bool is_emerg = false;
int16_t nri_v = -1;
bool is_null_nri = false;
+ struct gsm_bts *bts;
if (msgb_l3len(msg) < sizeof(*gh)) {
LOGP(DRSL, LOGL_ERROR, "There is no GSM48 header here.\n");
@@ -221,10 +224,10 @@ static struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
}
/* Has the subscriber been paged from a connected MSC? */
- if (pdisc == GSM48_PDISC_RR && mtype == GSM48_MT_RR_PAG_RESP) {
+ bts = conn_get_bts(conn);
+ if (bts && pdisc == GSM48_PDISC_RR && mtype == GSM48_MT_RR_PAG_RESP) {
subscr = bsc_subscr_find_by_mi(conn->network->bsc_subscribers, &mi);
- struct gsm_bts *bts = conn_get_bts(conn);
- if (bts && subscr) {
+ if (subscr) {
msc_target = paging_get_msc(bts, subscr);
bsc_subscr_put(subscr);
if (is_msc_usable(msc_target, is_emerg)) {
diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c
index c0c8cf6e1..fbc2ae213 100644
--- a/src/osmo-bsc/gsm_data.c
+++ b/src/osmo-bsc/gsm_data.c
@@ -601,6 +601,7 @@ static void _chan_desc_fill_tail(struct gsm48_chan_desc *cd, const struct gsm_lc
uint16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
cd->h0.tsc = gsm_ts_tsc(lchan->ts);
cd->h0.h = 0;
+ cd->h0.spare = 0;
cd->h0.arfcn_high = arfcn >> 8;
cd->h0.arfcn_low = arfcn & 0xff;
} else {
diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c
index 31919576e..c818dbbde 100644
--- a/src/osmo-bsc/handover_decision_2.c
+++ b/src/osmo-bsc/handover_decision_2.c
@@ -797,26 +797,30 @@ static int trigger_ho(struct ho_candidate *c, uint8_t requirements)
return trigger_remote_bss_ho(c, requirements);
}
+#define REQUIREMENTS_FMT "[%s%s%s]%s"
+#define REQUIREMENTS_ARGS(REQUIREMENTS, TCHX) \
+ (REQUIREMENTS) & REQUIREMENT_A_TCH##TCHX ? "A" : \
+ ((REQUIREMENTS) & REQUIREMENT_TCH##TCHX##_MASK) == 0? "-" : "", \
+ (REQUIREMENTS) & REQUIREMENT_B_TCH##TCHX ? "B" : "", \
+ (REQUIREMENTS) & REQUIREMENT_C_TCH##TCHX ? "C" : "", \
+ ((REQUIREMENTS) & REQUIREMENT_TCH##TCHX##_MASK) == 0 ? " not a candidate" : \
+ (((REQUIREMENTS) & REQUIREMENT_TCH##TCHX##_MASK) == REQUIREMENT_A_TCH##TCHX ? \
+ " more congestion" : \
+ ((REQUIREMENTS) & REQUIREMENT_B_TCH##TCHX ? \
+ " good" : \
+ /* now has to be (REQUIREMENTS) & REQUIREMENT_C_TCHX != 0: */ \
+ " less-or-equal congestion"))
+
/* verbosely log about a handover candidate */
static inline void debug_candidate(struct ho_candidate *candidate,
int8_t rxlev, int tchf_count, int tchh_count)
{
struct gsm_lchan *lchan = candidate->lchan;
-#define HO_CANDIDATE_FMT(tchx, TCHX) "TCH/" #TCHX "={free %d (want %d), [%s%s%s]%s}"
+#define HO_CANDIDATE_FMT(tchx, TCHX) "TCH/" #TCHX "={free %d (want %d), " REQUIREMENTS_FMT "}"
#define HO_CANDIDATE_ARGS(tchx, TCHX) \
tch##tchx##_count, ho_get_hodec2_tch##tchx##_min_slots(candidate->bts->ho), \
- candidate->requirements & REQUIREMENT_A_TCH##TCHX ? "A" : \
- (candidate->requirements & REQUIREMENT_TCH##TCHX##_MASK) == 0? "-" : "", \
- candidate->requirements & REQUIREMENT_B_TCH##TCHX ? "B" : "", \
- candidate->requirements & REQUIREMENT_C_TCH##TCHX ? "C" : "", \
- (candidate->requirements & REQUIREMENT_TCH##TCHX##_MASK) == 0 ? " not a candidate" : \
- ((candidate->requirements & REQUIREMENT_TCH##TCHX##_MASK) == REQUIREMENT_A_TCH##TCHX ? \
- " more congestion" : \
- (candidate->requirements & REQUIREMENT_B_TCH##TCHX ? \
- " good" : \
- /* now has to be candidate->requirements & REQUIREMENT_C_TCHX != 0: */ \
- " less-or-equal congestion"))
+ REQUIREMENTS_ARGS(candidate->requirements, TCHX)
if (!candidate->bts && !candidate->cil)
LOGPHOLCHAN(lchan, LOGL_DEBUG, "Empty candidate\n");
@@ -1503,8 +1507,11 @@ static int bts_resolve_congestion(struct gsm_bts *bts, int tchf_congestion, int
if (log_check_level(DHODEC, LOGL_DEBUG)) {
LOGPHOBTS(bts, LOGL_DEBUG, "Considering %u candidates to solve congestion:\n", candidates);
for (i = 0; i < candidates; i++) {
- LOGPHOCAND(&clist[i], LOGL_DEBUG, "#%d: req=0x%x avg-rxlev=%d\n",
- i, clist[i].requirements, clist[i].avg);
+
+ LOGPHOCAND(&clist[i], LOGL_DEBUG, "#%d: req={TCH/F:" REQUIREMENTS_FMT ", TCH/H:" REQUIREMENTS_FMT "} avg-rxlev=%d dBm\n",
+ i, REQUIREMENTS_ARGS(clist[i].requirements, F),
+ REQUIREMENTS_ARGS(clist[i].requirements, H),
+ rxlev2dbm(clist[i].avg));
}
}
diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c
index 8ed5945c5..8e231e0eb 100644
--- a/src/osmo-bsc/handover_fsm.c
+++ b/src/osmo-bsc/handover_fsm.c
@@ -80,13 +80,37 @@
/* Assume presence of local var 'conn' as struct gsm_subscriber_connection.
* This is a macro to preserve the source file and line number in logging. */
-#define ho_count(counter) do { \
- LOG_HO(conn, LOGL_DEBUG, "incrementing rate counter: %s %s\n", \
+#define ho_count_bsc(counter) do { \
+ /* If a handover target could not be found, the counter index may be -1. */ \
+ if (counter < 0) \
+ break; \
+ LOG_HO(conn, LOGL_DEBUG, "(BSC) incrementing rate counter: %s %s\n", \
bsc_ctr_description[counter].name, \
bsc_ctr_description[counter].description); \
rate_ctr_inc(&conn->network->bsc_ctrs->ctr[counter]); \
} while(0)
+/* Assume presence of local var 'conn' as struct gsm_subscriber_connection.
+ * Handles bts == NULL gracefully
+ * This is a macro to preserve the source file and line number in logging. */
+#define ho_count_bts(bts, counter) do { \
+ /* If a handover target could not be found, the counter index may be -1. */ \
+ if (counter < 0) \
+ break; \
+ LOG_HO(conn, LOGL_DEBUG, "(BTS) incrementing rate counter: %s %s\n", \
+ bts_ctr_description[counter].name, \
+ bts_ctr_description[counter].description); \
+ if (bts) \
+ rate_ctr_inc(&bts->bts_ctrs->ctr[counter]); \
+ else \
+ rate_ctr_inc(&conn->network->bts_unknown_ctrs->ctr[counter]); \
+ } while(0)
+
+#define ho_count(bts, counter) do { \
+ ho_count_bsc(BSC_##counter); \
+ ho_count_bts(bts, BTS_##counter); \
+} while(0)
+
static uint8_t g_next_ho_ref = 1;
const char *handover_status(struct gsm_subscriber_connection *conn)
@@ -305,6 +329,7 @@ void handover_start(struct handover_out_req *req)
* is to always create a handover_fsm instance, even if the target cell is not resolved yet. Any failure should
* then call handover_end(), which ensures that the conn snaps back to a valid state. */
handover_fsm_alloc(conn);
+ ho_count(conn_get_bts(conn), CTR_HANDOVER_ATTEMPTED);
ho->from_hodec_id = req->from_hodec_id;
ho->new_lchan_type = req->new_lchan_type == GSM_LCHAN_NONE ?
@@ -312,8 +337,10 @@ void handover_start(struct handover_out_req *req)
ho->target_cell = req->target_nik;
if (find_handover_target_cell(&local_target_cell, &remote_target_cell,
- conn, search_for, true))
- goto no_handover;
+ conn, search_for, true)) {
+ handover_end(conn, HO_RESULT_ERROR);
+ return;
+ }
if (local_target_cell) {
ho->new_bts = local_target_cell;
@@ -328,9 +355,6 @@ void handover_start(struct handover_out_req *req)
/* should never reach this, because find_handover_target_cell() would have returned error. */
OSMO_ASSERT(false);
-
-no_handover:
- handover_end(conn, HO_RESULT_FAIL_NO_CHANNEL);
}
/*! Hand over the specified logical channel to the specified new BTS and possibly change the lchan type.
@@ -341,23 +365,25 @@ static void handover_start_intra_bsc(struct gsm_subscriber_connection *conn)
struct handover *ho = &conn->ho;
struct osmo_fsm_inst *fi = conn->ho.fi;
struct lchan_activate_info info;
+ struct gsm_bts *bts = conn_get_bts(conn);
OSMO_ASSERT(ho->new_bts);
OSMO_ASSERT(ho->new_lchan_type != GSM_LCHAN_NONE);
OSMO_ASSERT(!ho->new_lchan);
- ho->scope = (ho->new_bts == conn->lchan->ts->trx->bts) ? HO_INTRA_CELL : HO_INTRA_BSC;
+ ho->scope = (ho->new_bts == bts) ? HO_INTRA_CELL : HO_INTRA_BSC;
ho->ho_ref = g_next_ho_ref++;
ho->async = true;
ho->new_lchan = lchan_select_by_type(ho->new_bts, ho->new_lchan_type);
- if (ho->scope & HO_INTRA_CELL)
+ if (ho->scope & HO_INTRA_CELL) {
+ ho_count(bts, CTR_INTRA_CELL_HO_ATTEMPTED);
ho_fsm_update_id(fi, "intraCell");
- else
+ } else {
+ ho_count(bts, CTR_INTRA_BSC_HO_ATTEMPTED);
ho_fsm_update_id(fi, "intraBSC");
-
- ho_count(BSC_CTR_HANDOVER_ATTEMPTED);
+ }
if (!ho->new_lchan) {
ho_fail(HO_RESULT_FAIL_NO_CHANNEL,
@@ -570,8 +596,6 @@ void handover_start_inter_bsc_in(struct gsm_subscriber_connection *conn,
return;
}
- ho_count(BSC_CTR_INTER_BSC_HO_IN_ATTEMPTED);
-
/* Figure out which cell to handover to. */
for (match_idx = 0; ; match_idx++) {
struct gsm_bts *bts;
@@ -612,6 +636,9 @@ void handover_start_inter_bsc_in(struct gsm_subscriber_connection *conn,
break;
}
+ ho_count(ho->new_bts, CTR_HANDOVER_ATTEMPTED);
+ ho_count(ho->new_bts, CTR_INTER_BSC_HO_IN_ATTEMPTED);
+
if (!ho->new_bts) {
ho_fail(HO_RESULT_ERROR, "No local cell matches the target %s",
req->cell_id_target_name);
@@ -660,34 +687,37 @@ void handover_start_inter_bsc_in(struct gsm_subscriber_connection *conn,
lchan_activate(ho->new_lchan, &info);
}
-#define FUNC_RESULT_COUNTER(name) \
-static int result_counter_##name(enum handover_result result) \
+#define FUNC_RESULT_COUNTER(obj, name) \
+static int result_counter_##obj##_##name(enum handover_result result) \
{ \
switch (result) { \
case HO_RESULT_OK: \
- return BSC_CTR_##name##_COMPLETED; \
+ return obj##_CTR_##name##_COMPLETED; \
case HO_RESULT_FAIL_NO_CHANNEL: \
- return BSC_CTR_##name##_NO_CHANNEL; \
+ return obj##_CTR_##name##_NO_CHANNEL; \
case HO_RESULT_FAIL_RR_HO_FAIL: \
- return BSC_CTR_##name##_FAILED; \
+ return obj##_CTR_##name##_FAILED; \
case HO_RESULT_FAIL_TIMEOUT: \
- return BSC_CTR_##name##_TIMEOUT; \
+ return obj##_CTR_##name##_TIMEOUT; \
case HO_RESULT_CONN_RELEASE: \
- return BSC_CTR_##name##_STOPPED; \
+ return obj##_CTR_##name##_STOPPED; \
default: \
case HO_RESULT_ERROR: \
- return BSC_CTR_##name##_ERROR; \
+ return obj##_CTR_##name##_ERROR; \
} \
}
-FUNC_RESULT_COUNTER(ASSIGNMENT)
-FUNC_RESULT_COUNTER(HANDOVER)
-FUNC_RESULT_COUNTER(INTER_BSC_HO_IN)
+FUNC_RESULT_COUNTER(BSC, HANDOVER)
+FUNC_RESULT_COUNTER(BSC, INTRA_CELL_HO)
+FUNC_RESULT_COUNTER(BSC, INTRA_BSC_HO)
+FUNC_RESULT_COUNTER(BSC, INTER_BSC_HO_IN)
-static int result_counter_INTER_BSC_HO_OUT(enum handover_result result) {
+static int result_counter_BSC_INTER_BSC_HO_OUT(enum handover_result result) {
switch (result) {
case HO_RESULT_OK:
return BSC_CTR_INTER_BSC_HO_OUT_COMPLETED;
+ case HO_RESULT_FAIL_RR_HO_FAIL:
+ return BSC_CTR_INTER_BSC_HO_OUT_FAILED;
case HO_RESULT_FAIL_TIMEOUT:
return BSC_CTR_INTER_BSC_HO_OUT_TIMEOUT;
case HO_RESULT_CONN_RELEASE:
@@ -698,22 +728,56 @@ static int result_counter_INTER_BSC_HO_OUT(enum handover_result result) {
}
}
-static int result_counter(enum handover_scope scope, enum handover_result result)
+static int result_counter_bsc(enum handover_scope scope, enum handover_result result)
{
switch (scope) {
+ default:
+ return -1;
case HO_INTRA_CELL:
- return result_counter_ASSIGNMENT(result);
+ return result_counter_BSC_INTRA_CELL_HO(result);
+ case HO_INTRA_BSC:
+ return result_counter_BSC_INTRA_BSC_HO(result);
+ case HO_INTER_BSC_OUT:
+ return result_counter_BSC_INTER_BSC_HO_OUT(result);
+ case HO_INTER_BSC_IN:
+ return result_counter_BSC_INTER_BSC_HO_IN(result);
+ }
+}
+
+FUNC_RESULT_COUNTER(BTS, HANDOVER)
+FUNC_RESULT_COUNTER(BTS, INTRA_CELL_HO)
+FUNC_RESULT_COUNTER(BTS, INTRA_BSC_HO)
+FUNC_RESULT_COUNTER(BTS, INTER_BSC_HO_IN)
+
+static int result_counter_BTS_INTER_BSC_HO_OUT(enum handover_result result) {
+ switch (result) {
+ case HO_RESULT_OK:
+ return BTS_CTR_INTER_BSC_HO_OUT_COMPLETED;
+ case HO_RESULT_FAIL_RR_HO_FAIL:
+ return BTS_CTR_INTER_BSC_HO_OUT_FAILED;
+ case HO_RESULT_FAIL_TIMEOUT:
+ return BTS_CTR_INTER_BSC_HO_OUT_TIMEOUT;
+ case HO_RESULT_CONN_RELEASE:
+ return BTS_CTR_INTER_BSC_HO_OUT_STOPPED;
default:
- LOGP(DHO, LOGL_ERROR, "invalid enum handover_scope value: %s\n",
- handover_scope_name(scope));
- /* use "normal" HO_INTRA_BSC counter... */
- case HO_NO_HANDOVER:
+ case HO_RESULT_ERROR:
+ return BTS_CTR_INTER_BSC_HO_OUT_ERROR;
+ }
+}
+
+static int result_counter_bts(enum handover_scope scope, enum handover_result result)
+{
+ switch (scope) {
+ default:
+ return -1;
+ case HO_INTRA_CELL:
+ return result_counter_BTS_INTRA_CELL_HO(result);
case HO_INTRA_BSC:
- return result_counter_HANDOVER(result);
+ return result_counter_BTS_INTRA_BSC_HO(result);
case HO_INTER_BSC_OUT:
- return result_counter_INTER_BSC_HO_OUT(result);
+ return result_counter_BTS_INTER_BSC_HO_OUT(result);
case HO_INTER_BSC_IN:
- return result_counter_INTER_BSC_HO_IN(result);
+ return result_counter_BTS_INTER_BSC_HO_IN(result);
}
}
@@ -787,6 +851,7 @@ void handover_end(struct gsm_subscriber_connection *conn, enum handover_result r
{
struct handover_decision_callbacks *hdc;
struct handover *ho = &conn->ho;
+ struct gsm_bts *bts = conn_get_bts(conn);
/* Sanity -- an error result ensures beyond doubt that we don't use the new lchan below
* when the handover isn't actually allowed to change this conn. */
@@ -858,7 +923,15 @@ void handover_end(struct gsm_subscriber_connection *conn, enum handover_result r
if (hdc && hdc->on_handover_end)
hdc->on_handover_end(conn, result);
- ho_count(result_counter(ho->scope, result));
+ /* HO_INTER_BSC_IN has the source BTS on a remote BSS, so count all of those on the target BTS; also count
+ * errors onto the HO target BTS if no lchan was obtained. */
+ if (ho->scope & HO_INTER_BSC_IN)
+ bts = ho->new_bts;
+
+ ho_count_bsc(result_counter_BSC_HANDOVER(result));
+ ho_count_bsc(result_counter_bsc(ho->scope, result));
+ ho_count_bts(bts, result_counter_BTS_HANDOVER(result));
+ ho_count_bts(bts, result_counter_bts(ho->scope, result));
LOG_HO(conn, LOGL_INFO, "Result: %s\n", handover_result_name(result));
@@ -1143,10 +1216,11 @@ static void handover_start_inter_bsc_out(struct gsm_subscriber_connection *conn,
int rc;
struct handover *ho = &conn->ho;
struct osmo_fsm_inst *fi = conn->ho.fi;
+ struct gsm_bts *bts = conn_get_bts(conn);
ho->scope = HO_INTER_BSC_OUT;
ho_fsm_update_id(fi, "interBSCout");
- ho_count(BSC_CTR_INTER_BSC_HO_OUT_ATTEMPTED);
+ ho_count(bts, CTR_INTER_BSC_HO_OUT_ATTEMPTED);
rc = bsc_tx_bssmap_ho_required(conn->lchan, target_cells);
if (rc) {
@@ -1195,6 +1269,8 @@ static void ho_out_fsm_wait_clear(struct osmo_fsm_inst *fi, uint32_t event, void
{
struct gsm_subscriber_connection *conn = ho_fi_conn(fi);
switch (event) {
+ /* See also ho_fsm_allstate_action() for ho_success() on HO_EV_CONN_RELEASING */
+
case HO_EV_RR_HO_FAIL:
ho_fail(HO_RESULT_FAIL_RR_HO_FAIL, "Received RR Handover Failure message");
return;
diff --git a/src/osmo-bsc/handover_logic.c b/src/osmo-bsc/handover_logic.c
index 071228e88..ade330d46 100644
--- a/src/osmo-bsc/handover_logic.c
+++ b/src/osmo-bsc/handover_logic.c
@@ -183,32 +183,34 @@ int find_handover_target_cell(struct gsm_bts **local_target_cell_p,
/* No explicit neighbor entries exist for this BTS. Hence apply the legacy default behavior that all
* local cells are neighbors. */
struct gsm_bts *bts;
- struct gsm_bts *wildcard_match = NULL;
+ int i;
LOG_HO(conn, LOGL_DEBUG, "No explicit neighbors, regarding all local cells as neighbors\n");
- llist_for_each_entry(bts, &net->bts_list, list) {
- struct neighbor_ident_key bts_key = *bts_ident_key(bts);
- if (neighbor_ident_key_match(&bts_key, search_for, true)) {
- if (local_target_cell) {
- if (log_errors)
- LOG_HO(conn, LOGL_ERROR,
- "NEIGHBOR CONFIGURATION ERROR: Multiple local cells match %s"
- " (BTS %d and BTS %d)."
- " Aborting Handover because of ambiguous network topology.\n",
- neighbor_ident_key_name(search_for),
- local_target_cell->nr, bts->nr);
- return -EINVAL;
+ /* For i == 0, look for an exact 1:1 match of all ident_key fields.
+ * For i == 1, interpret wildcard values, when no exact match exists. */
+ for (i = 0; i < 2; i++) {
+ bool exact_match = !i;
+ llist_for_each_entry(bts, &net->bts_list, list) {
+ struct neighbor_ident_key bts_key = *bts_ident_key(bts);
+ if (neighbor_ident_key_match(&bts_key, search_for, exact_match)) {
+ if (local_target_cell) {
+ if (log_errors)
+ LOG_HO(conn, LOGL_ERROR,
+ "NEIGHBOR CONFIGURATION ERROR: Multiple local cells match %s"
+ " (BTS %d and BTS %d)."
+ " Aborting Handover because of ambiguous network topology.\n",
+ neighbor_ident_key_name(search_for),
+ local_target_cell->nr, bts->nr);
+ return -EINVAL;
+ }
+ local_target_cell = bts;
}
- local_target_cell = bts;
}
- if (neighbor_ident_key_match(&bts_key, search_for, false))
- wildcard_match = bts;
+ if (local_target_cell)
+ break;
}
- if (!local_target_cell)
- local_target_cell = wildcard_match;
-
if (!local_target_cell) {
if (log_errors)
LOG_HO(conn, LOGL_ERROR, "Cannot Handover, no cell matches %s\n",
diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c
index 4ed95dd3f..e97c1baeb 100644
--- a/src/osmo-bsc/lchan_fsm.c
+++ b/src/osmo-bsc/lchan_fsm.c
@@ -59,6 +59,7 @@ bool lchan_may_receive_data(struct gsm_lchan *lchan)
switch (lchan->fi->state) {
case LCHAN_ST_WAIT_RLL_RTP_ESTABLISH:
case LCHAN_ST_ESTABLISHED:
+ case LCHAN_ST_WAIT_RR_CHAN_MODE_MODIFY_ACK:
return true;
default:
return false;
@@ -209,13 +210,13 @@ static void lchan_on_fully_established(struct gsm_lchan *lchan)
}
struct osmo_tdef_state_timeout lchan_fsm_timeouts[32] = {
- [LCHAN_ST_WAIT_TS_READY] = { .T=23001 },
- [LCHAN_ST_WAIT_ACTIV_ACK] = { .T=-23002 },
+ [LCHAN_ST_WAIT_TS_READY] = { .T=-5 },
+ [LCHAN_ST_WAIT_ACTIV_ACK] = { .T=-6 },
[LCHAN_ST_WAIT_RLL_RTP_ESTABLISH] = { .T=3101 },
[LCHAN_ST_WAIT_RLL_RTP_RELEASED] = { .T=3109 },
[LCHAN_ST_WAIT_BEFORE_RF_RELEASE] = { .T=3111 },
[LCHAN_ST_WAIT_RF_RELEASE_ACK] = { .T=3111 },
- [LCHAN_ST_WAIT_AFTER_ERROR] = { .T=993111 },
+ [LCHAN_ST_WAIT_AFTER_ERROR] = { .T=-3111 },
};
/* Transition to a state, using the T timer defined in lchan_fsm_timeouts.
@@ -249,7 +250,7 @@ struct osmo_tdef_state_timeout lchan_fsm_timeouts[32] = {
} while(0)
/* Which state to transition to when lchan_fail() is called in a given state. */
-uint32_t lchan_fsm_on_error[32] = {
+uint32_t lchan_fsm_on_error[34] = {
[LCHAN_ST_UNUSED] = LCHAN_ST_UNUSED,
[LCHAN_ST_WAIT_TS_READY] = LCHAN_ST_UNUSED,
[LCHAN_ST_WAIT_ACTIV_ACK] = LCHAN_ST_BORKEN,
@@ -260,6 +261,8 @@ uint32_t lchan_fsm_on_error[32] = {
[LCHAN_ST_WAIT_RF_RELEASE_ACK] = LCHAN_ST_BORKEN,
[LCHAN_ST_WAIT_AFTER_ERROR] = LCHAN_ST_UNUSED,
[LCHAN_ST_BORKEN] = LCHAN_ST_BORKEN,
+ [LCHAN_ST_WAIT_RR_CHAN_MODE_MODIFY_ACK] = LCHAN_ST_BORKEN,
+ [LCHAN_ST_WAIT_RSL_CHAN_MODE_MODIFY_ACK] = LCHAN_ST_BORKEN,
};
#define lchan_fail(fmt, args...) lchan_fail_to(lchan_fsm_on_error[fi->state], fmt, ## args)
@@ -410,22 +413,54 @@ static void lchan_reset(struct gsm_lchan *lchan)
static void lchan_fsm_unused_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
+ struct gsm_bts *bts = lchan->ts->trx->bts;
lchan_reset(lchan);
osmo_fsm_inst_dispatch(lchan->ts->fi, TS_EV_LCHAN_UNUSED, lchan);
+
+ /* Poll the channel request queue, so that waiting calls can make use of the lchan that just
+ * has become unused now. */
+ abis_rsl_chan_rqd_queue_poll(bts);
+}
+
+static void lchan_fsm_wait_after_error_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_lchan *lchan = lchan_fi_lchan(fi);
+ struct gsm_bts *bts = lchan->ts->trx->bts;
+
+ /* We also need to poll the channel request queue when the FSM enters the WAIT_AFTER_ERROR
+ * state. In case of an emergency call the channel request queue will skip the waiting
+ * period. */
+ abis_rsl_chan_rqd_queue_poll(bts);
}
/* Configure the multirate setting on this channel. */
-static int lchan_mr_config(struct gsm_lchan *lchan, const struct gsm48_multi_rate_conf *mr_conf)
+static int lchan_mr_config(struct gsm_lchan *lchan, uint16_t s15_s0)
{
+ struct gsm48_multi_rate_conf mr_conf;
bool full_rate = (lchan->type == GSM_LCHAN_TCH_F);
struct gsm_bts *bts = lchan->ts->trx->bts;
- struct bsc_msc_data *msc = lchan->conn->sccp.msc;
struct amr_multirate_conf *mr;
int rc;
int rc_rate;
struct gsm48_multi_rate_conf mr_conf_filtered;
const struct gsm48_multi_rate_conf *mr_conf_bts;
+ /* Generate mr conf struct from S15-S0 bits */
+ if (gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, s15_s0) < 0) {
+ LOG_LCHAN(lchan, LOGL_ERROR,
+ "can not determine multirate configuration, S15-S0 (%04x) are ambiguous!\n", s15_s0);
+ return -EINVAL;
+ }
+
+ /* Do not include 12.2 kbps rate when S1 is set. */
+ if (lchan->type == GSM_LCHAN_TCH_H && (s15_s0 & GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20)) {
+ /* See also 3GPP TS 28.062, chapter 7.11.3.1.3: "In case this Configuration
+ * "Config-NB-Code = 1" is signalled in the TFO Negotiation for the HR_AMR
+ * Codec Type,then it shall be assumed that AMR mode 12.2 kbps is (of course)
+ * not included. */
+ mr_conf.m12_2 = 0;
+ }
+
/* There are two different active sets, depending on the channel rate,
* make sure the appropate one is selected. */
if (full_rate)
@@ -433,16 +468,24 @@ static int lchan_mr_config(struct gsm_lchan *lchan, const struct gsm48_multi_rat
else
mr = &bts->mr_half;
- /* The VTY allows to forbid certain codec rates. Unfortunately we can
- * not articulate all of the prohibitions on through S0-S15 on the A
- * interface. To ensure that the VTY settings are observed we create
- * a manipulated copy of the mr_conf that ensures forbidden codec rates
- * are not used in the multirate configuration IE. */
- rc_rate = calc_amr_rate_intersection(&mr_conf_filtered, &msc->amr_conf, mr_conf);
- if (rc_rate < 0) {
- LOG_LCHAN(lchan, LOGL_ERROR,
- "can not encode multirate configuration (invalid amr rate setting, MSC)\n");
- return -EINVAL;
+ if (lchan->activate.info.activ_for == FOR_VTY)
+ /* If the channel is activated manually from VTY, then there is no
+ * conn attached to the lchan, also no MSC is involved. Since this
+ * option is for debugging and the codec choice is an intentional
+ * decision by the VTY user, we do not filter the mr_conf. */
+ memcpy(&mr_conf_filtered, &mr_conf, sizeof(mr_conf_filtered));
+ else {
+ /* The VTY allows to forbid certain codec rates. Unfortunately we can
+ * not articulate all of the prohibitions on through S0-S15 on the A
+ * interface. To ensure that the VTY settings are observed we create
+ * a manipulated copy of the mr_conf that ensures forbidden codec rates
+ * are not used in the multirate configuration IE. */
+ rc_rate = calc_amr_rate_intersection(&mr_conf_filtered, &lchan->conn->sccp.msc->amr_conf, &mr_conf);
+ if (rc_rate < 0) {
+ LOG_LCHAN(lchan, LOGL_ERROR,
+ "can not encode multirate configuration (invalid amr rate setting, MSC)\n");
+ return -EINVAL;
+ }
}
/* The two last codec rates which are defined for AMR do only work with
@@ -456,13 +499,17 @@ static int lchan_mr_config(struct gsm_lchan *lchan, const struct gsm48_multi_rat
}
/* Ensure that the resulting filtered conf is coherent with the
- * configuration that is set for the BTS and the specified rate */
- mr_conf_bts = (struct gsm48_multi_rate_conf *)mr->gsm48_ie;
- rc_rate = calc_amr_rate_intersection(&mr_conf_filtered, mr_conf_bts, &mr_conf_filtered);
- if (rc_rate < 0) {
- LOG_LCHAN(lchan, LOGL_ERROR,
- "can not encode multirate configuration (invalid amr rate setting, BTS)\n");
- return -EINVAL;
+ * configuration that is set for the BTS and the specified rate.
+ * if the channel activation was triggerd by the VTY, do not
+ * filter anything (see also comment above) */
+ if (lchan->activate.info.activ_for != FOR_VTY) {
+ mr_conf_bts = (struct gsm48_multi_rate_conf *)mr->gsm48_ie;
+ rc_rate = calc_amr_rate_intersection(&mr_conf_filtered, mr_conf_bts, &mr_conf_filtered);
+ if (rc_rate < 0) {
+ LOG_LCHAN(lchan, LOGL_ERROR,
+ "can not encode multirate configuration (invalid amr rate setting, BTS)\n");
+ return -EINVAL;
+ }
}
/* Proceed with the generation of the multirate configuration IE
@@ -478,6 +525,7 @@ static int lchan_mr_config(struct gsm_lchan *lchan, const struct gsm48_multi_rat
return -EINVAL;
}
+ lchan->s15_s0 = s15_s0;
return 0;
}
@@ -508,7 +556,6 @@ static void lchan_fsm_unused(struct osmo_fsm_inst *fi, uint32_t event, void *dat
static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
- struct gsm48_multi_rate_conf mr_conf;
struct gsm_bts *bts = lchan->ts->trx->bts;
struct osmo_mgcpc_ep_ci *use_mgwep_ci;
struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan;
@@ -537,26 +584,10 @@ static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t p
}
if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) {
- if (gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, info->s15_s0) < 0) {
- lchan_fail("Can not determine multirate configuration, S15-S0 (%04x) are ambiguous!\n",
- info->s15_s0);
- return;
- }
-
- /* Do not include 12.2 kbps rate when S1 is set. */
- if (lchan->type == GSM_LCHAN_TCH_H && (info->s15_s0 & GSM0808_SC_CFG_AMR_4_75_5_90_7_40_12_20)) {
- /* See also 3GPP TS 28.062, chapter 7.11.3.1.3: "In case this Configuration
- * "Config-NB-Code = 1" is signalled in the TFO Negotiation for the HR_AMR
- * Codec Type,then it shall be assumed that AMR mode 12.2 kbps is (of course)
- * not included. */
- mr_conf.m12_2 = 0;
- }
-
- if (lchan_mr_config(lchan, &mr_conf) < 0) {
+ if (lchan_mr_config(lchan, info->s15_s0) < 0) {
lchan_fail("Can not generate multirate configuration IE\n");
return;
}
- lchan->s15_s0 = info->s15_s0;
}
switch (info->chan_mode) {
@@ -796,6 +827,16 @@ static void lchan_fsm_wait_rll_rtp_establish_onenter(struct osmo_fsm_inst *fi, u
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
if (lchan->fi_rtp)
osmo_fsm_inst_dispatch(lchan->fi_rtp, LCHAN_RTP_EV_LCHAN_READY, 0);
+ /* Prepare an MGW endpoint CI if appropriate (late). */
+ else if (lchan->activate.info.requires_voice_stream)
+ lchan_rtp_fsm_start(lchan);
+
+ /* When activating a channel for VTY, skip waiting for activity from
+ * lchan_rtp_fsm, but only if no voice stream is required. */
+ if (lchan->activate.info.activ_for == FOR_VTY &&
+ !lchan->activate.info.requires_voice_stream) {
+ lchan_fsm_state_chg(LCHAN_ST_ESTABLISHED);
+ }
}
static void lchan_fsm_wait_rll_rtp_establish(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -832,6 +873,66 @@ static void lchan_fsm_wait_rll_rtp_establish(struct osmo_fsm_inst *fi, uint32_t
}
}
+static void lchan_fsm_wait_rr_chan_mode_modify_ack_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_lchan *lchan = lchan_fi_lchan(fi);
+ gsm48_lchan_modify(lchan, lchan->activate.info.chan_mode);
+}
+
+static void lchan_fsm_wait_rr_chan_mode_modify_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+
+ case LCHAN_EV_RR_CHAN_MODE_MODIFY_ACK:
+ lchan_fsm_state_chg(LCHAN_ST_WAIT_RSL_CHAN_MODE_MODIFY_ACK);
+ return;
+
+ case LCHAN_EV_RR_CHAN_MODE_MODIFY_ERROR:
+ lchan_fail("Failed to change channel mode on the MS side: %s in state %s\n",
+ osmo_fsm_event_name(fi->fsm, event),
+ osmo_fsm_inst_state_name(fi));
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void lchan_fsm_wait_rsl_chan_mode_modify_ack_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_lchan *lchan = lchan_fi_lchan(fi);
+ int rc;
+
+ rc = rsl_chan_mode_modify_req(lchan);
+ if (rc < 0) {
+ lchan_fail("Failed to send rsl message to change the channel mode on the BTS side: state %s\n",
+ osmo_fsm_inst_state_name(fi));
+ }
+}
+
+static void lchan_fsm_wait_rsl_chan_mode_modify_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gsm_lchan *lchan = lchan_fi_lchan(fi);
+ switch (event) {
+
+ case LCHAN_EV_RSL_CHAN_MODE_MODIFY_ACK:
+ if (lchan->activate.info.requires_voice_stream)
+ lchan_fsm_state_chg(LCHAN_ST_WAIT_RLL_RTP_ESTABLISH);
+ else
+ lchan_fsm_state_chg(LCHAN_ST_ESTABLISHED);
+ return;
+
+ case LCHAN_EV_RSL_CHAN_MODE_MODIFY_NACK:
+ lchan_fail("Failed to change channel mode on the BTS side: %s in state %s\n",
+ osmo_fsm_event_name(fi->fsm, event),
+ osmo_fsm_inst_state_name(fi));
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
static void lchan_fsm_established_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
{
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
@@ -908,6 +1009,8 @@ static void handle_rll_rel_ind_or_conf(struct osmo_fsm_inst *fi, uint32_t event,
static void lchan_fsm_established(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
+ struct lchan_activate_info *info;
+ struct osmo_mgcpc_ep_ci *use_mgwep_ci;
switch (event) {
case LCHAN_EV_RLL_ESTABLISH_IND:
@@ -934,6 +1037,48 @@ static void lchan_fsm_established(struct osmo_fsm_inst *fi, uint32_t event, void
osmo_fsm_inst_state_name(fi));
return;
+ case LCHAN_EV_REQUEST_MODE_MODIFY:
+
+ /* FIXME: Add missing implementation to handle an already existing RTP voice stream on MODE MODIFY.
+ * there may be transitions from VOICE to SIGNALLING and also from VOICE to VOICE with a different
+ * codec. */
+ if (lchan->fi_rtp) {
+ lchan_fail("MODE MODIFY not implemented when RTP voice stream is already active (VOICE => SIGNALLING, VOICE/CODEC_A => VOICE/CODEC_B)\n");
+ return;
+ }
+
+ info = data;
+ lchan->activate.info = *info;
+ use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);
+
+ if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) {
+ if (lchan_mr_config(lchan, info->s15_s0) < 0) {
+ lchan_fail("Can not generate multirate configuration IE\n");
+ return;
+ }
+ }
+
+ LOG_LCHAN(lchan, LOGL_INFO,
+ "Modification requested: %s voice=%s MGW-ci=%s type=%s tch-mode=%s encr-alg=A5/%u ck=%s\n",
+ lchan_activate_mode_name(lchan->activate.info.activ_for),
+ lchan->activate.info.requires_voice_stream ? "yes" : "no",
+ lchan->activate.info.requires_voice_stream ?
+ (use_mgwep_ci ? osmo_mgcpc_ep_ci_name(use_mgwep_ci) : "new")
+ : "none",
+ gsm_lchant_name(lchan->type),
+ gsm48_chan_mode_name(lchan->tch_mode),
+ (lchan->activate.info.encr.alg_id ? : 1) - 1,
+ lchan->activate.info.encr.key_len ? osmo_hexdump_nospc(lchan->activate.info.encr.key,
+ lchan->activate.info.encr.key_len) : "none");
+
+ /* While the mode is changed the lchan is virtually "not activated", at least
+ * from the FSM implementations perspective */
+ lchan->activate.concluded = false;
+
+ /* Initiate mode modification, start with the MS side (RR) */
+ lchan_fsm_state_chg(LCHAN_ST_WAIT_RR_CHAN_MODE_MODIFY_ACK);
+ return;
+
default:
OSMO_ASSERT(false);
}
@@ -1089,6 +1234,12 @@ static void lchan_fsm_borken_onenter(struct osmo_fsm_inst *fi, uint32_t prev_sta
case LCHAN_ST_BORKEN:
ctr = BTS_CTR_LCHAN_BORKEN_FROM_BORKEN;
break;
+ case LCHAN_ST_WAIT_RR_CHAN_MODE_MODIFY_ACK:
+ ctr = BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RR_CHAN_MODE_MODIFY_ACK;
+ break;
+ case LCHAN_ST_WAIT_RSL_CHAN_MODE_MODIFY_ACK:
+ ctr = BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RSL_CHAN_MODE_MODIFY_ACK;
+ break;
default:
ctr = BTS_CTR_LCHAN_BORKEN_FROM_UNKNOWN;
}
@@ -1222,6 +1373,32 @@ static const struct osmo_fsm_state lchan_fsm_states[] = {
| S(LCHAN_ST_WAIT_RLL_RTP_RELEASED)
,
},
+ [LCHAN_ST_WAIT_RR_CHAN_MODE_MODIFY_ACK] = {
+ .name = "WAIT_CHAN_RR_MODE_MODIFY_ACK",
+ .onenter = lchan_fsm_wait_rr_chan_mode_modify_ack_onenter,
+ .action = lchan_fsm_wait_rr_chan_mode_modify_ack,
+ .in_event_mask = 0
+ | S(LCHAN_EV_RR_CHAN_MODE_MODIFY_ACK)
+ | S(LCHAN_EV_RR_CHAN_MODE_MODIFY_ERROR)
+ ,
+ .out_state_mask = 0
+ | S(LCHAN_ST_BORKEN)
+ | S(LCHAN_ST_WAIT_RSL_CHAN_MODE_MODIFY_ACK)
+ ,
+ },
+ [LCHAN_ST_WAIT_RSL_CHAN_MODE_MODIFY_ACK] = {
+ .name = "WAIT_RSL_CHAN_MODE_MODIFY_ACK",
+ .onenter = lchan_fsm_wait_rsl_chan_mode_modify_ack_onenter,
+ .action = lchan_fsm_wait_rsl_chan_mode_modify_ack,
+ .in_event_mask = 0
+ | S(LCHAN_EV_RSL_CHAN_MODE_MODIFY_ACK)
+ | S(LCHAN_EV_RSL_CHAN_MODE_MODIFY_NACK)
+ ,
+ .out_state_mask = 0
+ | S(LCHAN_ST_BORKEN)
+ | S(LCHAN_ST_WAIT_RLL_RTP_ESTABLISH)
+ ,
+ },
[LCHAN_ST_ESTABLISHED] = {
.name = "ESTABLISHED",
.onenter = lchan_fsm_established_onenter,
@@ -1232,12 +1409,14 @@ static const struct osmo_fsm_state lchan_fsm_states[] = {
| S(LCHAN_EV_RLL_ESTABLISH_IND) /* ignored */
| S(LCHAN_EV_RTP_ERROR)
| S(LCHAN_EV_RTP_RELEASED)
+ | S(LCHAN_EV_REQUEST_MODE_MODIFY)
,
.out_state_mask = 0
| S(LCHAN_ST_UNUSED)
| S(LCHAN_ST_WAIT_RLL_RTP_RELEASED)
| S(LCHAN_ST_WAIT_BEFORE_RF_RELEASE)
| S(LCHAN_ST_WAIT_RF_RELEASE_ACK)
+ | S(LCHAN_ST_WAIT_RR_CHAN_MODE_MODIFY_ACK)
,
},
[LCHAN_ST_WAIT_RLL_RTP_RELEASED] = {
@@ -1283,6 +1462,7 @@ static const struct osmo_fsm_state lchan_fsm_states[] = {
},
[LCHAN_ST_WAIT_AFTER_ERROR] = {
.name = "WAIT_AFTER_ERROR",
+ .onenter = lchan_fsm_wait_after_error_onenter,
.in_event_mask = 0
| S(LCHAN_EV_RTP_RELEASED) /* ignore late lchan_rtp_fsm release events */
,
@@ -1323,12 +1503,14 @@ static const struct value_string lchan_fsm_event_names[] = {
OSMO_VALUE_STRING(LCHAN_EV_RLL_REL_CONF),
OSMO_VALUE_STRING(LCHAN_EV_RSL_RF_CHAN_REL_ACK),
OSMO_VALUE_STRING(LCHAN_EV_RLL_ERR_IND),
- OSMO_VALUE_STRING(LCHAN_EV_CHAN_MODE_MODIF_ACK),
- OSMO_VALUE_STRING(LCHAN_EV_CHAN_MODE_MODIF_ERROR),
+ OSMO_VALUE_STRING(LCHAN_EV_RR_CHAN_MODE_MODIFY_ACK),
+ OSMO_VALUE_STRING(LCHAN_EV_RR_CHAN_MODE_MODIFY_ERROR),
+ OSMO_VALUE_STRING(LCHAN_EV_RSL_CHAN_MODE_MODIFY_ACK),
+ OSMO_VALUE_STRING(LCHAN_EV_RSL_CHAN_MODE_MODIFY_NACK),
{}
};
-void lchan_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+static void lchan_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
switch (event) {
@@ -1348,7 +1530,14 @@ void lchan_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *d
}
}
-int lchan_fsm_timer_cb(struct osmo_fsm_inst *fi)
+void lchan_fsm_skip_error(struct gsm_lchan *lchan)
+{
+ struct osmo_fsm_inst *fi = lchan->fi;
+ if (fi->state == LCHAN_ST_WAIT_AFTER_ERROR)
+ lchan_fsm_state_chg(LCHAN_ST_UNUSED);
+}
+
+static int lchan_fsm_timer_cb(struct osmo_fsm_inst *fi)
{
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
switch (fi->state) {
@@ -1423,7 +1612,7 @@ exit_release_handler:
lchan->release.in_release_handler = false;
}
-void lchan_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
+static void lchan_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
{
struct gsm_lchan *lchan = lchan_fi_lchan(fi);
if (lchan->fi->state == LCHAN_ST_BORKEN) {
diff --git a/src/osmo-bsc/lchan_rtp_fsm.c b/src/osmo-bsc/lchan_rtp_fsm.c
index 1fe545286..cd195d021 100644
--- a/src/osmo-bsc/lchan_rtp_fsm.c
+++ b/src/osmo-bsc/lchan_rtp_fsm.c
@@ -43,10 +43,10 @@ struct gsm_lchan *lchan_rtp_fi_lchan(struct osmo_fsm_inst *fi)
}
struct osmo_tdef_state_timeout lchan_rtp_fsm_timeouts[32] = {
- [LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_AVAILABLE] = { .T=-23004 },
- [LCHAN_RTP_ST_WAIT_IPACC_CRCX_ACK] = { .T=-23005 },
- [LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK] = { .T=-23006 },
- [LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_CONFIGURED] = { .T=-23004 },
+ [LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_AVAILABLE] = { .T=-9 },
+ [LCHAN_RTP_ST_WAIT_IPACC_CRCX_ACK] = { .T=-7 },
+ [LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK] = { .T=-8 },
+ [LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_CONFIGURED] = { .T=-10 },
};
/* Transition to a state, using the T timer defined in lchan_rtp_fsm_timeouts.
@@ -301,10 +301,7 @@ static void lchan_rtp_fsm_wait_ipacc_crcx_ack(struct osmo_fsm_inst *fi, uint32_t
switch (event) {
case LCHAN_RTP_EV_IPACC_CRCX_ACK:
- /* the CRCX ACK parsing has already noted the RTP port information at
- * lchan->abis_ip.bound_*, see ipac_parse_rtp(). We'll use that in
- * lchan_rtp_fsm_wait_mgw_endpoint_configured_onenter(). */
- lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK);
+ lchan_rtp_fsm_switch_rtp(fi);
return;
case LCHAN_RTP_EV_IPACC_CRCX_NACK:
@@ -330,6 +327,7 @@ static void lchan_rtp_fsm_wait_ipacc_mdcx_ack_onenter(struct osmo_fsm_inst *fi,
int rc;
struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);
const struct mgcp_conn_peer *mgw_rtp;
+ struct in_addr sin;
if (lchan->release.requested) {
lchan_rtp_fail("Release requested while activating");
@@ -344,8 +342,13 @@ static void lchan_rtp_fsm_wait_ipacc_mdcx_ack_onenter(struct osmo_fsm_inst *fi,
return;
}
- /* Other RTP settings were already setup in lchan_rtp_fsm_wait_ipacc_crcx_ack_onenter() */
- lchan->abis_ip.connect_ip = ntohl(inet_addr(mgw_rtp->addr));
+ /* Other RTP settings were already set up in lchan_rtp_fsm_wait_ipacc_crcx_ack_onenter() */
+ if (inet_pton(AF_INET, mgw_rtp->addr, &sin) != 1) {
+ /* Only IPv4 addresses are supported in IPACC */
+ lchan_rtp_fail("Invalid remote IPv4 address %s", mgw_rtp->addr);
+ return;
+ }
+ lchan->abis_ip.connect_ip = ntohl(sin.s_addr);
lchan->abis_ip.connect_port = mgw_rtp->port;
/* send-recv */
@@ -360,21 +363,16 @@ static void lchan_rtp_fsm_wait_ipacc_mdcx_ack_onenter(struct osmo_fsm_inst *fi,
static void lchan_rtp_fsm_wait_ipacc_mdcx_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
- struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);
switch (event) {
case LCHAN_RTP_EV_IPACC_MDCX_ACK:
- lchan_rtp_fsm_switch_rtp(fi);
+ lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_READY);
return;
case LCHAN_RTP_EV_IPACC_MDCX_NACK:
lchan_rtp_fail("Received NACK on IPACC MDCX");
return;
- case LCHAN_RTP_EV_READY_TO_SWITCH_RTP:
- lchan->activate.info.wait_before_switching_rtp = false;
- return;
-
case LCHAN_RTP_EV_RELEASE:
case LCHAN_RTP_EV_ROLLBACK:
osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, 0);
@@ -474,10 +472,15 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_configured_onenter(struct osmo_fsm_i
static void lchan_rtp_fsm_wait_mgw_endpoint_configured(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
- switch (event) {
+ struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);
+ switch (event) {
case LCHAN_RTP_EV_MGW_ENDPOINT_CONFIGURED:
- lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_READY);
+ if (is_ipaccess_bts(lchan->ts->trx->bts))
+ lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK);
+ else {
+ lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_READY);
+ }
return;
case LCHAN_RTP_EV_MGW_ENDPOINT_ERROR:
@@ -646,23 +649,8 @@ static const struct osmo_fsm_state lchan_rtp_fsm_states[] = {
| S(LCHAN_RTP_EV_ROLLBACK)
,
.out_state_mask = 0
- | S(LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK)
- ,
- },
- [LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK] = {
- .name = "WAIT_IPACC_MDCX_ACK",
- .onenter = lchan_rtp_fsm_wait_ipacc_mdcx_ack_onenter,
- .action = lchan_rtp_fsm_wait_ipacc_mdcx_ack,
- .in_event_mask = 0
- | S(LCHAN_RTP_EV_READY_TO_SWITCH_RTP)
- | S(LCHAN_RTP_EV_IPACC_MDCX_ACK)
- | S(LCHAN_RTP_EV_IPACC_MDCX_NACK)
- | S(LCHAN_RTP_EV_RELEASE)
- | S(LCHAN_RTP_EV_ROLLBACK)
- ,
- .out_state_mask = 0
| S(LCHAN_RTP_ST_WAIT_READY_TO_SWITCH_RTP)
- | S(LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_CONFIGURED)
+ | S(LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_CONFIGURED) /*old: LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK*/
,
},
[LCHAN_RTP_ST_WAIT_READY_TO_SWITCH_RTP] = {
@@ -688,6 +676,22 @@ static const struct osmo_fsm_state lchan_rtp_fsm_states[] = {
| S(LCHAN_RTP_EV_ROLLBACK)
,
.out_state_mask = 0
+ | S(LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK)
+ | S(LCHAN_RTP_ST_READY)
+ | S(LCHAN_RTP_ST_ROLLBACK)
+ ,
+ },
+ [LCHAN_RTP_ST_WAIT_IPACC_MDCX_ACK] = {
+ .name = "WAIT_IPACC_MDCX_ACK",
+ .onenter = lchan_rtp_fsm_wait_ipacc_mdcx_ack_onenter,
+ .action = lchan_rtp_fsm_wait_ipacc_mdcx_ack,
+ .in_event_mask = 0
+ | S(LCHAN_RTP_EV_IPACC_MDCX_ACK)
+ | S(LCHAN_RTP_EV_IPACC_MDCX_NACK)
+ | S(LCHAN_RTP_EV_RELEASE)
+ | S(LCHAN_RTP_EV_ROLLBACK)
+ ,
+ .out_state_mask = 0
| S(LCHAN_RTP_ST_READY)
| S(LCHAN_RTP_ST_ROLLBACK)
,
diff --git a/src/osmo-bsc/lchan_select.c b/src/osmo-bsc/lchan_select.c
index d2dba1bb2..6d3caaced 100644
--- a/src/osmo-bsc/lchan_select.c
+++ b/src/osmo-bsc/lchan_select.c
@@ -162,15 +162,12 @@ struct gsm_lchan *lchan_select_by_chan_mode(struct gsm_bts *bts,
return lchan_select_by_type(bts, type);
}
-/* Return a matching lchan from a specific BTS that is currently available. The next logical step is
- * lchan_activate() on it, which would possibly cause dynamic timeslot pchan switching, taken care of by
- * the lchan and timeslot FSMs. */
-struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type)
+struct gsm_lchan *lchan_avail_by_type(struct gsm_bts *bts, enum gsm_chan_t type)
{
struct gsm_lchan *lchan = NULL;
enum gsm_phys_chan_config first, first_cbch, second, second_cbch;
- LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_select_by_type(%s)\n", gsm_lchant_name(type));
+ LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_avail_by_type(%s)\n", gsm_lchant_name(type));
switch (type) {
case GSM_LCHAN_SDCCH:
@@ -231,6 +228,20 @@ struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type
LOG_BTS(bts, DRLL, LOGL_ERROR, "Unknown gsm_chan_t %u\n", type);
}
+ return lchan;
+}
+
+/* Return a matching lchan from a specific BTS that is currently available. The next logical step is
+ * lchan_activate() on it, which would possibly cause dynamic timeslot pchan switching, taken care of by
+ * the lchan and timeslot FSMs. */
+struct gsm_lchan *lchan_select_by_type(struct gsm_bts *bts, enum gsm_chan_t type)
+{
+ struct gsm_lchan *lchan = NULL;
+
+ lchan = lchan_avail_by_type(bts, type);
+
+ LOG_BTS(bts, DRLL, LOGL_DEBUG, "lchan_select_by_type(%s)\n", gsm_lchant_name(type));
+
if (lchan) {
lchan->type = type;
LOG_LCHAN(lchan, LOGL_INFO, "Selected\n");
diff --git a/src/osmo-bsc/net_init.c b/src/osmo-bsc/net_init.c
index 353099ddd..8b1e080e2 100644
--- a/src/osmo-bsc/net_init.c
+++ b/src/osmo-bsc/net_init.c
@@ -37,7 +37,6 @@ static struct osmo_tdef gsm_network_T_defs[] = {
{ .T=3107, .default_val=5, .desc="(unused)" },
{ .T=3109, .default_val=5, .desc="RSL SACCH deactivation" },
{ .T=3111, .default_val=2, .desc="Wait time before RSL RF Channel Release" },
- { .T=993111, .default_val=4, .desc="Wait time after lchan was released in error (should be T3111 + 2s)" },
{ .T=3113, .default_val=7, .desc="Paging"},
{ .T=3115, .default_val=10, .desc="(unused)" },
{ .T=3117, .default_val=10, .desc="(unused)" },
@@ -46,15 +45,26 @@ static struct osmo_tdef gsm_network_T_defs[] = {
{ .T=3141, .default_val=10, .desc="(unused)" },
{ .T=3212, .default_val=5, .unit=OSMO_TDEF_CUSTOM,
.desc="Periodic Location Update timer, sent to MS (1 = 6 minutes)" },
- { .T=993210, .default_val=20, .desc="After L3 Complete, wait for MSC to confirm" },
- { .T=999, .default_val=60, .desc="After Clear Request, wait for MSC to Clear Command (sanity)" },
- { .T=992427, .default_val=4, .desc="MGCP timeout (2427 is the default MGCP port number)" },
+ { .T=-4, .default_val=60, .desc="After Clear Request, wait for MSC to Clear Command (sanity)" },
+ { .T=-5, .default_val=5, .desc="Timeout to switch dynamic timeslot PCHAN modes"},
+ { .T=-6, .default_val=5, .desc="Timeout for RSL Channel Activate ACK after sending RSL Channel Activate" },
+ { .T=-7, .default_val=5, .desc="Timeout for RSL IPA CRCX ACK after sending RSL IPA CRCX" },
+ { .T=-8, .default_val=5, .desc="Timeout for RSL IPA MDCX ACK after sending RSL IPA MDCX" },
+ { .T=-9, .default_val=5, .desc="Timeout for availability of MGW endpoint" },
+ { .T=-10, .default_val=5, .desc="Timeout for fully configured MGW endpoint" },
+ { .T=-3111, .default_val=4, .desc="Wait time after lchan was released in error (should be T3111 + 2s)" },
+ { .T=-3210, .default_val=20, .desc="After L3 Complete, wait for MSC to confirm" },
{}
};
struct osmo_tdef g_mgw_tdefs[] = {
- { .T=-1, .default_val=4, .desc="MGCP response timeout" },
- { .T=-2, .default_val=30, .desc="RTP stream establishing timeout" },
+ { .T=-2427, .default_val=5, .desc="timeout for MGCP response from MGW" },
+ {}
+};
+
+struct osmo_tdef_group bsc_tdef_group[] = {
+ { .name = "net", .tdefs = gsm_network_T_defs, .desc = "GSM network" },
+ { .name = "mgw", .tdefs = g_mgw_tdefs, .desc = "MGW (Media Gateway) interface" },
{}
};
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index bf38d107d..65fee04f5 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -121,6 +121,11 @@ page_subscriber(struct bsc_msc_data *msc, struct gsm_bts *bts,
struct bsc_subscr *subscr;
int ret;
+ if (!bsc_grace_allow_new_connection(bsc_gsmnet, bts)) {
+ LOGP(DMSC, LOGL_DEBUG, "RF-locked: not paging on BTS %u\n", bts->nr);
+ return;
+ }
+
subscr = bsc_subscr_find_or_create_by_imsi(msc->network->bsc_subscribers,
mi_string);
@@ -135,10 +140,9 @@ page_subscriber(struct bsc_msc_data *msc, struct gsm_bts *bts,
return;
}
- subscr->lac = lac;
subscr->tmsi = tmsi;
- ret = bsc_grace_paging_request(msc->network->rf_ctrl->policy, subscr, chan_needed, msc, bts);
+ ret = paging_request_bts(bts, subscr, chan_needed, msc);
if (ret == 0)
LOGP(DMSC, LOGL_INFO, "Paging request failed or repeated paging: BTS: %d IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n",
bts->nr, mi_string, tmsi, tmsi, lac);
@@ -1073,6 +1077,34 @@ static int bssmap_handle_confusion(struct gsm_subscriber_connection *conn,
return 0;
}
+/* Common ID; 3GPP TS 48.008 3.2.1.68 */
+static int bssmap_handle_common_id(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, unsigned int length)
+{
+ struct tlv_parsed tp;
+ struct osmo_mobile_identity mi_imsi;
+
+ osmo_bssap_tlv_parse(&tp, msg->l4h + 1, length - 1);
+
+ /* Check for the mandatory elements */
+ if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
+ LOGPFSML(conn->fi, LOGL_ERROR,
+ "CommonID: missing mandatory IMSI IE: %s\n",
+ osmo_hexdump(msg->l4h, length));
+ return -EINVAL;
+ }
+
+ if (osmo_mobile_identity_decode(&mi_imsi, TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI), false)
+ || mi_imsi.type != GSM_MI_TYPE_IMSI) {
+ LOGPFSML(conn->fi, LOGL_ERROR, "CommonID: could not parse IMSI\n");
+ return -EINVAL;
+ }
+
+ osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_COMMON_ID_IND, &mi_imsi);
+
+ return 0;
+}
+
static int bssmap_rcvmsg_udt(struct bsc_msc_data *msc,
struct msgb *msg, unsigned int length)
{
@@ -1153,6 +1185,10 @@ static int bssmap_rcvmsg_dt1(struct gsm_subscriber_connection *conn,
rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_CONFUSION]);
ret = bssmap_handle_confusion(conn, msg, length);
break;
+ case BSS_MAP_MSG_COMMON_ID:
+ rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_COMMON_ID]);
+ ret = bssmap_handle_common_id(conn, msg, length);
+ break;
default:
rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_UNKNOWN]);
LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
@@ -1197,7 +1233,7 @@ static int dtap_rcvmsg(struct gsm_subscriber_connection *conn,
}
rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_DTAP]);
- LOGP(DMSC, LOGL_INFO, "Rx MSC DTAP, SAPI: %u CHAN: %u\n", header->link_id & 0x07, header->link_id & 0xC0);
+ LOGP(DMSC, LOGL_INFO, "Rx MSC DTAP, SAPI: %s CHAN: %u\n", gsm0406_dlci_sapi_name(header->dlci_sapi), header->dlci_cc);
/* forward the data */
gsm48 = gsm48_msgb_alloc_name("GSM 04.08 DTAP RCV");
diff --git a/src/osmo-bsc/osmo_bsc_ctrl.c b/src/osmo-bsc/osmo_bsc_ctrl.c
index 5ebe59789..05bc86c2b 100644
--- a/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -195,7 +195,6 @@ static int get_msc_connection_status(struct ctrl_cmd *cmd, void *data)
/* Backwards compat. */
CTRL_CMD_DEFINE_RO(msc0_connection_status, "msc_connection_status");
-static int msc_connection_status = 0; /* XXX unused */
static int get_msc0_connection_status(struct ctrl_cmd *cmd, void *data)
{
@@ -214,13 +213,12 @@ static int msc_connection_status_trap_cb(unsigned int subsys, unsigned int signa
{
struct ctrl_cmd *cmd;
struct gsm_network *gsmnet = (struct gsm_network *)handler_data;
+ struct bsc_msc_data *msc = (struct bsc_msc_data *)signal_data;
- if (signal == S_MSC_LOST && msc_connection_status == 1) {
+ if (signal == S_MSC_LOST) {
LOGP(DCTRL, LOGL_DEBUG, "MSC connection lost, sending TRAP.\n");
- msc_connection_status = 0;
- } else if (signal == S_MSC_CONNECTED && msc_connection_status == 0) {
+ } else if (signal == S_MSC_CONNECTED) {
LOGP(DCTRL, LOGL_DEBUG, "MSC connection (re)established, sending TRAP.\n");
- msc_connection_status = 1;
} else {
return 0;
}
@@ -232,12 +230,19 @@ static int msc_connection_status_trap_cb(unsigned int subsys, unsigned int signa
}
cmd->id = "0";
- cmd->variable = "msc_connection_status";
+ cmd->variable = talloc_asprintf(cmd, "msc.%d.connection_status", msc->nr);
+ cmd->node = msc;
- get_msc0_connection_status(cmd, NULL);
+ get_msc_connection_status(cmd, NULL);
ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
+ if (msc->nr == 0) {
+ /* Backwards compat. */
+ cmd->variable = "msc_connection_status";
+ ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
+ }
+
talloc_free(cmd);
return 0;
diff --git a/src/osmo-bsc/osmo_bsc_grace.c b/src/osmo-bsc/osmo_bsc_grace.c
index a26a716ad..19ffe65aa 100644
--- a/src/osmo-bsc/osmo_bsc_grace.c
+++ b/src/osmo-bsc/osmo_bsc_grace.c
@@ -33,42 +33,3 @@ int bsc_grace_allow_new_connection(struct gsm_network *network, struct gsm_bts *
return 1;
return network->rf_ctrl->policy == S_RF_ON;
}
-
-
-/* Return value is like paging_request_bts():
- * returns 1 on success (one BTS was paged); 0 in case of error (e.g. TRX down) */
-static int locked_paging_bts(struct gsm_bts *bts,
- struct bsc_subscr *subscr,
- int chan_needed,
- struct bsc_msc_data *msc)
-{
- /* Return error if the BTS is not excluded from the lock. */
- if (!bts->excl_from_rf_lock)
- return 0;
-
- /* in case of no lac patching is in place, check the BTS */
- if (msc->core_lac == -1 && subscr->lac != bts->location_area_code)
- return 0;
-
- return paging_request_bts(bts, subscr, chan_needed, msc);
-}
-
-/**
- * Page a subscriber in an MSC.
- * \param[in] rf_policy if not S_RF_ON, page only BTSs which are not excluded from the RF lock
- * \param[in] subscr subscriber we want to page
- * \param[in] chan_needed value of the GSM0808_IE_CHANNEL_NEEDED IE
- * \param[in] msc MSC which has issued this paging
- * \param[in] bts The BTS to issue the paging on
- * \returns 1 if paging was issued to the BTS, 0 if not
- */
-int bsc_grace_paging_request(enum signal_rf rf_policy,
- struct bsc_subscr *subscr,
- int chan_needed,
- struct bsc_msc_data *msc,
- struct gsm_bts *bts)
-{
- if (rf_policy == S_RF_ON)
- return paging_request_bts(bts, subscr, chan_needed, msc);
- return locked_paging_bts(bts, subscr, chan_needed, msc);
-}
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index 84b44f70d..20bd620f1 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -53,6 +53,7 @@
#include <osmocom/vty/ports.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/command.h>
+#include <osmocom/vty/cpu_sched_vty.h>
#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
@@ -238,11 +239,10 @@ static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
const struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc;
const struct bitvec *ts_arfcn = &ts->hopping.arfcns;
struct bitvec *ma = &ts->hopping.ma;
- unsigned int num_cell_arfcns, bitnum, n_chan;
+ unsigned int num_cell_arfcns;
int i;
/* re-set the MA to all-zero */
- ma->cur_bit = 0;
ts->hopping.ma_len = 0;
memset(ma->data, 0, ma->data_len);
@@ -257,32 +257,27 @@ static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
}
/* pad it to octet-aligned number of bits */
- ts->hopping.ma_len = num_cell_arfcns / 8;
- if (num_cell_arfcns % 8)
- ts->hopping.ma_len++;
+ ts->hopping.ma_len = OSMO_BYTES_FOR_BITS(num_cell_arfcns);
+ ma->cur_bit = (ts->hopping.ma_len * 8) - 1;
- n_chan = 0;
- for (i = 0; i < 1024; i++) {
+ for (i = 1; i < 1024; i++) {
if (!bitvec_get_bit_pos(cell_chan, i))
continue;
/* set the corresponding bit in the MA */
- bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
if (bitvec_get_bit_pos(ts_arfcn, i))
- bitvec_set_bit_pos(ma, bitnum, 1);
+ bitvec_set_bit_pos(ma, ma->cur_bit, 1);
else
- bitvec_set_bit_pos(ma, bitnum, 0);
- n_chan++;
+ bitvec_set_bit_pos(ma, ma->cur_bit, 0);
+ ma->cur_bit--;
}
/* ARFCN 0 is special: It is coded last in the bitmask */
if (bitvec_get_bit_pos(cell_chan, 0)) {
- n_chan++;
/* set the corresponding bit in the MA */
- bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
if (bitvec_get_bit_pos(ts_arfcn, 0))
- bitvec_set_bit_pos(ma, bitnum, 1);
+ bitvec_set_bit_pos(ma, ma->cur_bit, 1);
else
- bitvec_set_bit_pos(ma, bitnum, 0);
+ bitvec_set_bit_pos(ma, ma->cur_bit, 0);
}
return 0;
@@ -310,7 +305,10 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
if (trx_is_usable(trx))
acc_ramp_trigger(&trx->bts->acc_ramp);
- gsm_bts_trx_set_system_infos(trx);
+ if (gsm_bts_trx_set_system_infos(trx) != 0) {
+ LOG_TRX(trx, DRSL, LOGL_ERROR, "Failed to generate System Information\n");
+ return;
+ }
if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) {
/* channel unspecific, power reduction in 2 dB steps */
@@ -328,6 +326,9 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
/* Start CBCH transmit timer if CBCH is present */
if (trx->nr == 0 && gsm_bts_get_cbch(trx->bts))
bts_cbch_timer_schedule(trx->bts);
+
+ /* Drop all expired channel requests in the list */
+ abis_rsl_chan_rqd_queue_flush(trx->bts);
}
static void all_ts_dispatch_event(struct gsm_bts_trx *trx, uint32_t event)
@@ -843,6 +844,7 @@ int main(int argc, char **argv)
vty_init(&vty_info);
bsc_vty_init(bsc_gsmnet);
ctrl_vty_init(tall_bsc_ctx);
+ osmo_cpu_sched_vty_init(tall_bsc_ctx);
logging_vty_add_deprecated_subsys(tall_bsc_ctx, "cc");
logging_vty_add_deprecated_subsys(tall_bsc_ctx, "mgcp");
logging_vty_add_deprecated_subsys(tall_bsc_ctx, "nat");
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
index 5e02b4a39..26d2bc8d2 100644
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ b/src/osmo-bsc/osmo_bsc_msc.c
@@ -58,6 +58,7 @@ static const struct rate_ctr_desc msc_ctr_description[] = {
[MSC_CTR_BSSMAP_RX_DT1_HANDOVER_CMD] = {"bssmap:rx:dt1:handover:cmd", "Number of received BSSMAP DT1 HANDOVER CMD messages"},
[MSC_CTR_BSSMAP_RX_DT1_CLASSMARK_RQST] = {"bssmap:rx:dt1:classmark:rqst", "Number of received BSSMAP DT1 CLASSMARK RQST messages"},
[MSC_CTR_BSSMAP_RX_DT1_CONFUSION] = {"bssmap:rx:dt1:confusion", "Number of received BSSMAP DT1 CONFUSION messages"},
+ [MSC_CTR_BSSMAP_RX_DT1_COMMON_ID] = {"bssmap:rx:dt1:common_id", "Number of received BSSMAP DT1 COMMON ID messages"},
[MSC_CTR_BSSMAP_RX_DT1_UNKNOWN] = {"bssmap:rx:dt1:err_unknown", "Number of received BSSMAP unknown DT1 messages"},
[MSC_CTR_BSSMAP_RX_DT1_DTAP] = {"bssmap:rx:dt1:dtap:good", "Number of received BSSMAP DTAP messages"},
[MSC_CTR_BSSMAP_RX_DT1_DTAP_ERROR] = {"bssmap:rx:dt1:dtap:error", "Number of received BSSMAP DTAP messages with errors"},
@@ -163,7 +164,7 @@ int osmo_bsc_msc_init(struct bsc_msc_data *msc)
else
mgw_port = MGCP_CLIENT_REMOTE_PORT_DEFAULT;
- rc = osmo_sock_init2_ofd(&msc->mgcp_ipa.ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
+ rc = osmo_sock_init2_ofd(&msc->mgcp_ipa.ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
msc->mgcp_ipa.local_addr, msc->mgcp_ipa.local_port,
net->mgw.conf->remote_addr, mgw_port,
OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT);
@@ -255,7 +256,7 @@ struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
msc_data->audio_support[4]->hr = 1;
osmo_fd_setup(&msc_data->mgcp_ipa.ofd, -1, OSMO_FD_READ, &bsc_sccplite_mgcp_proxy_cb, msc_data, 0);
- msc_data->mgcp_ipa.local_addr = talloc_strdup(msc_data, "0.0.0.0");
+ msc_data->mgcp_ipa.local_addr = NULL; /* = INADDR(6)_ANY */
msc_data->mgcp_ipa.local_port = 0; /* dynamic */
msc_data->nri_ranges = osmo_nri_ranges_alloc(msc_data);
diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c
index de4be2630..9d9e40a35 100644
--- a/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -41,10 +41,8 @@
* (a copy of the pointer location submitted with osmo_bsc_sigtran_init() */
static struct llist_head *msc_list;
-#define RESET_INTERVAL 1 /* sek */
-#define SCCP_MSG_MAXSIZE 1024
-#define CS7_POINTCODE_DEFAULT_OFFSET 2
-#define DEFAULT_ASP_REMOTE_IP "127.0.0.1"
+#define DEFAULT_ASP_LOCAL_IP "localhost"
+#define DEFAULT_ASP_REMOTE_IP "localhost"
/* The SCCP stack will not assign connection IDs to us automatically, we
* will do this ourselves using a counter variable, that counts one up
@@ -304,11 +302,11 @@ enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, s
ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
OSMO_ASSERT(ss7);
- LOGP(DMSC, LOGL_INFO, "Initializing resources for new SCCP connection to MSC: %s...\n",
- osmo_sccp_addr_name(ss7, &msc->a.msc_addr));
+ LOGP(DMSC, LOGL_INFO, "Initializing resources for new SCCP connection to MSC %d: %s...\n",
+ msc->nr, osmo_sccp_addr_name(ss7, &msc->a.msc_addr));
if (a_reset_conn_ready(msc) == false) {
- LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
+ LOGP(DMSC, LOGL_ERROR, "MSC %d is not connected. Dropping.\n", msc->nr);
return BSC_CON_REJECT_NO_LINK;
}
@@ -569,7 +567,9 @@ int osmo_bsc_sigtran_init(struct llist_head *mscs)
/* SS7 Protocol stack */
default_pc = osmo_ss7_pointcode_parse(NULL, BSC_DEFAULT_PC);
- sccp = osmo_sccp_simple_client_on_ss7_id(tall_bsc_ctx, inst->cfg.id, inst_name, default_pc, used_proto, 0, NULL,
+ sccp = osmo_sccp_simple_client_on_ss7_id(tall_bsc_ctx, inst->cfg.id, inst_name,
+ default_pc, used_proto,
+ 0, DEFAULT_ASP_LOCAL_IP,
0, DEFAULT_ASP_REMOTE_IP);
if (!sccp)
return -EINVAL;
diff --git a/src/osmo-bsc/paging.c b/src/osmo-bsc/paging.c
index 521598f6f..37ec61cef 100644
--- a/src/osmo-bsc/paging.c
+++ b/src/osmo-bsc/paging.c
@@ -60,12 +60,6 @@ void *tall_paging_ctx = NULL;
#define PAGING_TIMER 0, 500000
/*
- * TODO MSCSPLIT: the paging in libbsc is closely tied to MSC land in that the
- * MSC realm callback functions used to be invoked from the BSC/BTS level. So
- * this entire file needs to be rewired for use with an A interface.
- */
-
-/*
* Kill one paging request update the internal list...
*/
static void paging_remove_request(struct gsm_bts_paging_state *paging_bts,
diff --git a/src/osmo-bsc/smscb.c b/src/osmo-bsc/smscb.c
index 436826a25..b34780b6d 100644
--- a/src/osmo-bsc/smscb.c
+++ b/src/osmo-bsc/smscb.c
@@ -654,6 +654,8 @@ static int bts_rx_reset(struct gsm_bts *bts, const struct osmo_cbsp_decoded *dec
struct bts_smscb_chan_state *chan_state;
struct bts_smscb_message *smscb, *smscb2;
+ LOG_BTS(bts, DCBS, LOGL_NOTICE, "Rx CBSP RESET: clearing all state; disabling broadcast\n");
+
/* remove all SMSCB from CBCH BASIC this BTS */
chan_state = bts_get_smscb_chan(bts, false);
llist_for_each_entry_safe(smscb, smscb2, &chan_state->messages, list)
@@ -664,6 +666,10 @@ static int bts_rx_reset(struct gsm_bts *bts, const struct osmo_cbsp_decoded *dec
llist_for_each_entry_safe(smscb, smscb2, &chan_state->messages, list)
bts_smscb_del(smscb, chan_state, "RESET");
+ osmo_timer_del(&bts->etws_timer);
+
+ /* Make sure that broadcast is disabled */
+ rsl_etws_pn_command(bts, RSL_CHAN_PCH_AGCH, NULL, 0);
return 0;
}
diff --git a/src/osmo-bsc/system_information.c b/src/osmo-bsc/system_information.c
index 7011127ba..b9699899f 100644
--- a/src/osmo-bsc/system_information.c
+++ b/src/osmo-bsc/system_information.c
@@ -944,7 +944,7 @@ static int generate_si4(enum osmo_sysinfo_type t, struct gsm_bts *bts)
int rc;
struct gsm48_system_information_type_4 *si4 = (struct gsm48_system_information_type_4 *) GSM_BTS_SI(bts, t);
struct gsm_lchan *cbch_lchan;
- uint8_t *restoct = si4->data;
+ uint8_t *tail = si4->data;
/* length of all IEs present except SI4 rest octets and l2_plen */
int l2_plen = sizeof(*si4) - 1;
@@ -963,13 +963,25 @@ static int generate_si4(enum osmo_sysinfo_type t, struct gsm_bts *bts)
/* Optional: CBCH Channel Description + CBCH Mobile Allocation */
cbch_lchan = gsm_bts_get_cbch(bts);
if (cbch_lchan) {
+ const struct gsm_bts_trx_ts *ts = cbch_lchan->ts;
struct gsm48_chan_desc cd;
+
+ /* 10.5.2.5 (TV) CBCH Channel Description IE */
gsm48_lchan2chan_desc_as_configured(&cd, cbch_lchan);
- tv_fixed_put(si4->data, GSM48_IE_CBCH_CHAN_DESC, 3,
- (uint8_t *) &cd);
- l2_plen += 3 + 1;
- restoct += 3 + 1;
- /* we don't use hopping and thus don't need a CBCH MA */
+ tail = tv_fixed_put(tail, GSM48_IE_CBCH_CHAN_DESC,
+ sizeof(cd), (uint8_t *) &cd);
+ l2_plen += 1 + sizeof(cd);
+
+ /* 10.5.2.21 (TLV) CBCH Mobile Allocation IE */
+ if (ts->hopping.enabled) {
+ /* Prevent potential buffer overflow */
+ if (ts->hopping.ma_len > 2)
+ return -ENOMEM;
+ tail = tlv_put(tail, GSM48_IE_CBCH_MOB_AL,
+ ts->hopping.ma_len,
+ ts->hopping.ma_data);
+ l2_plen += 2 + ts->hopping.ma_len;
+ }
}
si4->header.l2_plen = GSM48_LEN2PLEN(l2_plen);
@@ -977,7 +989,7 @@ static int generate_si4(enum osmo_sysinfo_type t, struct gsm_bts *bts)
/* SI4 Rest Octets (10.5.2.35), containing
Optional Power offset, GPRS Indicator,
Cell Identity, LSA ID, Selection Parameter */
- rc = rest_octets_si4(restoct, &si_info, (uint8_t *)GSM_BTS_SI(bts, t) + GSM_MACBLOCK_LEN - restoct);
+ rc = rest_octets_si4(tail, &si_info, (uint8_t *)GSM_BTS_SI(bts, t) + GSM_MACBLOCK_LEN - tail);
return l2_plen + 1 + rc;
}
diff --git a/src/osmo-bsc/timeslot_fsm.c b/src/osmo-bsc/timeslot_fsm.c
index 0aecfaeb2..106e6a1fa 100644
--- a/src/osmo-bsc/timeslot_fsm.c
+++ b/src/osmo-bsc/timeslot_fsm.c
@@ -63,6 +63,7 @@ void ts_fsm_alloc(struct gsm_bts_trx_ts *ts)
OSMO_ASSERT(ts->trx);
ts->fi = osmo_fsm_inst_alloc(&ts_fsm, ts->trx, ts, LOGL_DEBUG, NULL);
OSMO_ASSERT(ts->fi);
+ ts_fsm_update_id(ts);
}
enum lchan_sanity {
diff --git a/tests/acc/acc_test.c b/tests/acc/acc_test.c
index 72d3212f1..f463a2e64 100644
--- a/tests/acc/acc_test.c
+++ b/tests/acc/acc_test.c
@@ -197,9 +197,9 @@ static void test_acc_mgr_manual_ramp(struct gsm_network *net)
bts_del(bts);
}
-static void test_acc_mgr_rotate(struct gsm_network *net)
+static void test_acc_mgr_rotate(struct gsm_network *net, bool barr_some, unsigned int set_len)
{
- fprintf(stderr, "===%s===\n", __func__);
+ fprintf(stderr, "===%s(%s, %u)===\n", __func__, barr_some ? "true" : "false", set_len);
int i;
struct gsm_bts *bts = bts_init(net);
struct acc_mgr *acc_mgr = &bts->acc_mgr;
@@ -215,13 +215,15 @@ static void test_acc_mgr_rotate(struct gsm_network *net)
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);
+ if (barr_some) {
+ 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);
+ acc_mgr_set_len_allowed_adm(acc_mgr, set_len);
for (i = 0; i < 20; i++) {
osmo_gettimeofday_override_time.tv_sec += 2;
@@ -232,6 +234,16 @@ static void test_acc_mgr_rotate(struct gsm_network *net)
bts_del(bts);
}
+static void test_acc_mgr_rotate_all(struct gsm_network *net)
+{
+ int i;
+ for (i = 1; i <= 8; i++) {
+ test_acc_mgr_rotate(net, true, i);
+ test_acc_mgr_rotate(net, false, i);
+ }
+ test_acc_mgr_rotate(net, false, 9);
+}
+
static void test_acc_ramp(struct gsm_network *net)
{
fprintf(stderr, "===%s===\n", __func__);
@@ -494,7 +506,7 @@ int main(int argc, char **argv)
test_acc_mgr_no_ramp(net);
test_acc_mgr_manual_ramp(net);
- test_acc_mgr_rotate(net);
+ test_acc_mgr_rotate_all(net);
test_acc_ramp(net);
test_acc_ramp2(net);
test_acc_ramp3(net);
@@ -515,8 +527,19 @@ 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);
+ fprintf(stderr, "%s(): t2=0x%02" PRIx8 " t3=0x%02" PRIx8 ", allowed:%s%s%s%s%s%s%s%s%s%s\n",
+ __func__, rach_control.t2, rach_control.t3,
+ rach_control.t3 & (1 << 0) ? "" : " 0",
+ rach_control.t3 & (1 << 1) ? "" : " 1",
+ rach_control.t3 & (1 << 2) ? "" : " 2",
+ rach_control.t3 & (1 << 3) ? "" : " 3",
+ rach_control.t3 & (1 << 4) ? "" : " 4",
+ rach_control.t3 & (1 << 5) ? "" : " 5",
+ rach_control.t3 & (1 << 6) ? "" : " 6",
+ rach_control.t3 & (1 << 7) ? "" : " 7",
+ rach_control.t2 & (1 << 0) ? "" : " 8",
+ rach_control.t2 & (1 << 1) ? "" : " 9"
+ );
}
diff --git a/tests/acc/acc_test.ok b/tests/acc/acc_test.ok
index bb6fe10af..866502e81 100644
--- a/tests/acc/acc_test.ok
+++ b/tests/acc/acc_test.ok
@@ -3,86 +3,86 @@
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
+pcu_info_update(): t2=0x00 t3=0x01, allowed: 1 2 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x03, allowed: 2 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x07, allowed: 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x1f, allowed: 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x3f, allowed: 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x7f, allowed: 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
(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
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
(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
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
(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
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
(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
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
(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
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
(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
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
(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
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
(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
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
(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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
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
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
(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
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
(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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
*** 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
+pcu_info_update(): t2=0x02 t3=0xa5, allowed: 1 3 4 6 8
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
+pcu_info_update(): t2=0x02 t3=0xa7, allowed: 3 4 6 8
(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
+pcu_info_update(): t2=0x02 t3=0xaf, allowed: 4 6 8
(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
+pcu_info_update(): t2=0x02 t3=0xbf, allowed: 6 8
(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
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
(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
+pcu_info_update(): t2=0x03 t3=0xf5, allowed: 1 3
(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
+pcu_info_update(): t2=0x03 t3=0xe5, allowed: 1 3 4
(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
+pcu_info_update(): t2=0x03 t3=0xa5, allowed: 1 3 4 6
(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
+pcu_info_update(): t2=0x02 t3=0xa5, allowed: 1 3 4 6 8
(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)
@@ -91,81 +91,81 @@ pcu_info_update(): t2=0x02 t3=0xa5
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
+pcu_info_update(): t2=0x02 t3=0xbf, allowed: 6 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xa5, allowed: 1 3 4 6
(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
+pcu_info_update(): t2=0x02 t3=0xa5, allowed: 1 3 4 6 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
*** 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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
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
+pcu_info_update(): t2=0x00 t3=0x01, allowed: 1 2 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x03, allowed: 2 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x07, allowed: 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x1f, allowed: 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x3f, allowed: 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x7f, allowed: 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
(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
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
(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
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
(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
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
(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
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
(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
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
(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
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
(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
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
(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
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
(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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
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
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
(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
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
(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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
*** 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
+pcu_info_update(): t2=0x01 t3=0xb3, allowed: 2 3 6 9
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)
@@ -173,21 +173,21 @@ do_allowed_len_ramp_loop(1)
(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
+pcu_info_update(): t2=0x01 t3=0xb7, allowed: 3 6 9
(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
+pcu_info_update(): t2=0x01 t3=0xbf, allowed: 6 9
(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
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
(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
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
(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
+pcu_info_update(): t2=0x03 t3=0xb3, allowed: 2 3 6
(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
+pcu_info_update(): t2=0x01 t3=0xb3, allowed: 2 3 6 9
(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)
@@ -197,272 +197,1349 @@ pcu_info_update(): t2=0x01 t3=0xb3
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
+pcu_info_update(): t2=0x01 t3=0xbf, allowed: 6 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x01 t3=0xb3, allowed: 2 3 6 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
*** 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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
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
+pcu_info_update(): t2=0x00 t3=0x01, allowed: 1 2 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x03, allowed: 2 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x07, allowed: 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x1f, allowed: 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x3f, allowed: 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0x7f, allowed: 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
(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
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
(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
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
(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
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
(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
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
(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
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
(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
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
(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
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
(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
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
(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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
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
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
(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
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
(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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
*** 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
+pcu_info_update(): t2=0x00 t3=0x3f, allowed: 6 7 8 9
(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
+pcu_info_update(): t2=0x01 t3=0xb3, allowed: 2 3 6 9
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
+pcu_info_update(): t2=0x01 t3=0xb7, allowed: 3 6 9
(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
+pcu_info_update(): t2=0x01 t3=0xbf, allowed: 6 9
(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
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
(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
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
(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
+pcu_info_update(): t2=0x03 t3=0xb3, allowed: 2 3 6
(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
+pcu_info_update(): t2=0x01 t3=0xb3, allowed: 2 3 6 9
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
+pcu_info_update(): t2=0x01 t3=0xbf, allowed: 6 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x01 t3=0xb3, allowed: 2 3 6 9
BTS deallocated OK in test_acc_mgr_manual_ramp()
-===test_acc_mgr_rotate===
+===test_acc_mgr_rotate(true, 1)===
(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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
+(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x100 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x100 -> 0x001 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x001 -> 0x002 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x002 -> 0x004 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x004 -> 0x008 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf7, allowed: 3
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x008 -> 0x010 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x100 -> 0x001 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x001 -> 0x002 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x002 -> 0x004 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x004 -> 0x008 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf7, allowed: 3
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x008 -> 0x010 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x100 -> 0x001 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x001 -> 0x002 (active_len=1, ramp_len=10, adm_len=1, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 1)===
+(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()
+(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x200 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x200 -> 0x001 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x001 -> 0x002 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x002 -> 0x004 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x004 -> 0x008 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf7, allowed: 3
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x008 -> 0x010 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x100 -> 0x200 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x200 -> 0x001 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x001 -> 0x002 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x002 -> 0x004 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x004 -> 0x008 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf7, allowed: 3
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x008 -> 0x010 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x100 -> 0x200 (active_len=1, ramp_len=10, adm_len=1, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xff, allowed: 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(true, 2)===
+(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, allowed: 0 1 2 3 4 5 6 7 8
+(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x180 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7f, allowed: 7 8
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x180 -> 0x101 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfe, allowed: 0 8
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x101 -> 0x003 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x006 -> 0x00c (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00c -> 0x018 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x018 -> 0x030 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x030 -> 0x060 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x9f, allowed: 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x060 -> 0x0c0 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x3f, allowed: 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0c0 -> 0x180 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7f, allowed: 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x180 -> 0x101 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfe, allowed: 0 8
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x101 -> 0x003 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x006 -> 0x00c (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00c -> 0x018 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x018 -> 0x030 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x030 -> 0x060 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x9f, allowed: 5 6
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x060 -> 0x0c0 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x3f, allowed: 6 7
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0c0 -> 0x180 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7f, allowed: 7 8
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x180 -> 0x101 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfe, allowed: 0 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x101 -> 0x003 (active_len=2, ramp_len=10, adm_len=2, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 2)===
+(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()
+(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x300 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x300 -> 0x201 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xfe, allowed: 0 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x201 -> 0x003 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x006 -> 0x00c (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00c -> 0x018 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x018 -> 0x030 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x030 -> 0x060 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x9f, allowed: 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x060 -> 0x0c0 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x3f, allowed: 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0c0 -> 0x180 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7f, allowed: 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x180 -> 0x300 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x300 -> 0x201 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xfe, allowed: 0 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x201 -> 0x003 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x006 -> 0x00c (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00c -> 0x018 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x018 -> 0x030 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x030 -> 0x060 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x9f, allowed: 5 6
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x060 -> 0x0c0 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x3f, allowed: 6 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0c0 -> 0x180 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7f, allowed: 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x180 -> 0x300 (active_len=2, ramp_len=10, adm_len=2, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xff, allowed: 8 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(true, 3)===
+(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, allowed: 0 1 2 3 4 5 6 7 8
+(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1c0 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x181 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7e, allowed: 0 7 8
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x181 -> 0x103 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfc, allowed: 0 1 8
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x103 -> 0x007 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x007 -> 0x00e (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf1, allowed: 1 2 3
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00e -> 0x01c (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe3, allowed: 2 3 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01c -> 0x038 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc7, allowed: 3 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x038 -> 0x070 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x070 -> 0x0e0 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0e0 -> 0x1c0 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x181 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7e, allowed: 0 7 8
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x181 -> 0x103 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfc, allowed: 0 1 8
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x103 -> 0x007 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x007 -> 0x00e (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf1, allowed: 1 2 3
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00e -> 0x01c (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe3, allowed: 2 3 4
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01c -> 0x038 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc7, allowed: 3 4 5
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x038 -> 0x070 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x070 -> 0x0e0 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0e0 -> 0x1c0 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x181 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7e, allowed: 0 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x181 -> 0x103 (active_len=3, ramp_len=10, adm_len=3, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfc, allowed: 0 1 8
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 3)===
+(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()
+(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x380 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x7f, allowed: 7 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x380 -> 0x301 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xfe, allowed: 0 8 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x301 -> 0x203 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xfc, allowed: 0 1 9
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x203 -> 0x007 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x007 -> 0x00e (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf1, allowed: 1 2 3
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00e -> 0x01c (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe3, allowed: 2 3 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01c -> 0x038 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc7, allowed: 3 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x038 -> 0x070 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x070 -> 0x0e0 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0e0 -> 0x1c0 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x380 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x7f, allowed: 7 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x380 -> 0x301 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xfe, allowed: 0 8 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x301 -> 0x203 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xfc, allowed: 0 1 9
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x203 -> 0x007 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x007 -> 0x00e (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf1, allowed: 1 2 3
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00e -> 0x01c (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe3, allowed: 2 3 4
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01c -> 0x038 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc7, allowed: 3 4 5
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x038 -> 0x070 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x070 -> 0x0e0 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0e0 -> 0x1c0 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x380 (active_len=3, ramp_len=10, adm_len=3, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x7f, allowed: 7 8 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(true, 4)===
+(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, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x02 t3=0x1f, allowed: 5 6 7 8
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
+pcu_info_update(): t2=0x02 t3=0x3e, allowed: 0 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x183 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7c, allowed: 0 1 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x107 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x107 -> 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
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
+pcu_info_update(): t2=0x03 t3=0xe1, allowed: 1 2 3 4
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
+pcu_info_update(): t2=0x03 t3=0xc3, allowed: 2 3 4 5
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
+pcu_info_update(): t2=0x03 t3=0x87, allowed: 3 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x0f, allowed: 4 5 6 7
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
+pcu_info_update(): t2=0x02 t3=0x1f, allowed: 5 6 7 8
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
+pcu_info_update(): t2=0x02 t3=0x3e, allowed: 0 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x183 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7c, allowed: 0 1 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x107 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x107 -> 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
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
+pcu_info_update(): t2=0x03 t3=0xe1, allowed: 1 2 3 4
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
+pcu_info_update(): t2=0x03 t3=0xc3, allowed: 2 3 4 5
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
+pcu_info_update(): t2=0x03 t3=0x87, allowed: 3 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x0f, allowed: 4 5 6 7
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
+pcu_info_update(): t2=0x02 t3=0x1f, allowed: 5 6 7 8
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
+pcu_info_update(): t2=0x02 t3=0x3e, allowed: 0 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x183 (active_len=4, ramp_len=10, adm_len=4, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7c, allowed: 0 1 7 8
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 4)===
+(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()
+(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, allowed: 6 7 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c0 -> 0x381 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x7e, allowed: 0 7 8 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x381 -> 0x303 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xfc, allowed: 0 1 8 9
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x303 -> 0x207 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xf8, allowed: 0 1 2 9
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x207 -> 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
+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=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe1, allowed: 1 2 3 4
+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=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc3, allowed: 2 3 4 5
+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=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x87, allowed: 3 4 5 6
+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=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x0f, allowed: 4 5 6 7
+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=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1f, allowed: 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e0 -> 0x3c0 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x3f, allowed: 6 7 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c0 -> 0x381 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x7e, allowed: 0 7 8 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x381 -> 0x303 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xfc, allowed: 0 1 8 9
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x303 -> 0x207 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xf8, allowed: 0 1 2 9
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x207 -> 0x00f (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x00f -> 0x01e (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe1, allowed: 1 2 3 4
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01e -> 0x03c (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc3, allowed: 2 3 4 5
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03c -> 0x078 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x87, allowed: 3 4 5 6
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x078 -> 0x0f0 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x0f, allowed: 4 5 6 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0f0 -> 0x1e0 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1f, allowed: 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e0 -> 0x3c0 (active_len=4, ramp_len=10, adm_len=4, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x3f, allowed: 6 7 8 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(true, 5)===
+(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, allowed: 0 1 2 3 4 5 6 7 8
+(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1f0 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0f, allowed: 4 5 6 7 8
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f0 -> 0x1e1 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1e, allowed: 0 5 6 7 8
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e1 -> 0x1c3 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3c, allowed: 0 1 6 7 8
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c3 -> 0x187 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x78, allowed: 0 1 2 7 8
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x187 -> 0x10f (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf0, allowed: 0 1 2 3 8
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x10f -> 0x01f (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03e -> 0x07c (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x83, allowed: 2 3 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07c -> 0x0f8 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x07, allowed: 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0f8 -> 0x1f0 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0f, allowed: 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f0 -> 0x1e1 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1e, allowed: 0 5 6 7 8
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e1 -> 0x1c3 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3c, allowed: 0 1 6 7 8
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c3 -> 0x187 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x78, allowed: 0 1 2 7 8
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x187 -> 0x10f (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf0, allowed: 0 1 2 3 8
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x10f -> 0x01f (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03e -> 0x07c (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x83, allowed: 2 3 4 5 6
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07c -> 0x0f8 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x07, allowed: 3 4 5 6 7
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0f8 -> 0x1f0 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0f, allowed: 4 5 6 7 8
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f0 -> 0x1e1 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1e, allowed: 0 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e1 -> 0x1c3 (active_len=5, ramp_len=10, adm_len=5, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x3c, allowed: 0 1 6 7 8
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 5)===
+(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()
+(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3e0 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x1f, allowed: 5 6 7 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e0 -> 0x3c1 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x3e, allowed: 0 6 7 8 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c1 -> 0x383 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x7c, allowed: 0 1 7 8 9
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x383 -> 0x307 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xf8, allowed: 0 1 2 8 9
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x307 -> 0x20f (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xf0, allowed: 0 1 2 3 9
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x20f -> 0x01f (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03e -> 0x07c (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x83, allowed: 2 3 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07c -> 0x0f8 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x07, allowed: 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0f8 -> 0x1f0 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0f, allowed: 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f0 -> 0x3e0 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x1f, allowed: 5 6 7 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e0 -> 0x3c1 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x3e, allowed: 0 6 7 8 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c1 -> 0x383 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x7c, allowed: 0 1 7 8 9
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x383 -> 0x307 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xf8, allowed: 0 1 2 8 9
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x307 -> 0x20f (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xf0, allowed: 0 1 2 3 9
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x20f -> 0x01f (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03e -> 0x07c (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x83, allowed: 2 3 4 5 6
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07c -> 0x0f8 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x07, allowed: 3 4 5 6 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0f8 -> 0x1f0 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0f, allowed: 4 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f0 -> 0x3e0 (active_len=5, ramp_len=10, adm_len=5, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x1f, allowed: 5 6 7 8 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(true, 6)===
+(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, allowed: 0 1 2 3 4 5 6 7 8
+(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1f8 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f8 -> 0x1f1 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0e, allowed: 0 4 5 6 7 8
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f1 -> 0x1e3 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1c, allowed: 0 1 5 6 7 8
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e3 -> 0x1c7 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x38, allowed: 0 1 2 6 7 8
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c7 -> 0x18f (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x70, allowed: 0 1 2 3 7 8
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x18f -> 0x11f (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xe0, allowed: 0 1 2 3 4 8
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x11f -> 0x03f (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03f -> 0x07e (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x81, allowed: 1 2 3 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07e -> 0x0fc (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x03, allowed: 2 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f8 -> 0x1f1 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0e, allowed: 0 4 5 6 7 8
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f1 -> 0x1e3 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1c, allowed: 0 1 5 6 7 8
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e3 -> 0x1c7 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x38, allowed: 0 1 2 6 7 8
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1c7 -> 0x18f (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x70, allowed: 0 1 2 3 7 8
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x18f -> 0x11f (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xe0, allowed: 0 1 2 3 4 8
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x11f -> 0x03f (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03f -> 0x07e (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x81, allowed: 1 2 3 4 5 6
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07e -> 0x0fc (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x03, allowed: 2 3 4 5 6 7
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f8 -> 0x1f1 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0e, allowed: 0 4 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f1 -> 0x1e3 (active_len=6, ramp_len=10, adm_len=6, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1c, allowed: 0 1 5 6 7 8
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 6)===
+(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()
+(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, allowed: 4 5 6 7 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f0 -> 0x3e1 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x1e, allowed: 0 5 6 7 8 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e1 -> 0x3c3 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x3c, allowed: 0 1 6 7 8 9
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c3 -> 0x387 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x78, allowed: 0 1 2 7 8 9
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x387 -> 0x30f (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xf0, allowed: 0 1 2 3 8 9
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x30f -> 0x21f (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xe0, allowed: 0 1 2 3 4 9
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x21f -> 0x03f (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03f -> 0x07e (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x81, allowed: 1 2 3 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07e -> 0x0fc (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x03, allowed: 2 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f8 -> 0x3f0 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f0 -> 0x3e1 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x1e, allowed: 0 5 6 7 8 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e1 -> 0x3c3 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x3c, allowed: 0 1 6 7 8 9
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c3 -> 0x387 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x78, allowed: 0 1 2 7 8 9
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x387 -> 0x30f (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xf0, allowed: 0 1 2 3 8 9
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x30f -> 0x21f (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xe0, allowed: 0 1 2 3 4 9
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x21f -> 0x03f (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x03f -> 0x07e (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x81, allowed: 1 2 3 4 5 6
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07e -> 0x0fc (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x03, allowed: 2 3 4 5 6 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f8 -> 0x3f0 (active_len=6, ramp_len=10, adm_len=6, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x0f, allowed: 4 5 6 7 8 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(true, 7)===
+(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, allowed: 0 1 2 3 4 5 6 7 8
+(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1fc (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x03, allowed: 2 3 4 5 6 7 8
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fc -> 0x1f9 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x06, allowed: 0 3 4 5 6 7 8
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f9 -> 0x1f3 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0c, allowed: 0 1 4 5 6 7 8
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f3 -> 0x1e7 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x18, allowed: 0 1 2 5 6 7 8
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e7 -> 0x1cf (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x30, allowed: 0 1 2 3 6 7 8
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1cf -> 0x19f (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x60, allowed: 0 1 2 3 4 7 8
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x19f -> 0x13f (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xc0, allowed: 0 1 2 3 4 5 8
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x13f -> 0x07f (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07f -> 0x0fe (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x01, allowed: 1 2 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fe -> 0x1fc (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x03, allowed: 2 3 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fc -> 0x1f9 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x06, allowed: 0 3 4 5 6 7 8
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f9 -> 0x1f3 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0c, allowed: 0 1 4 5 6 7 8
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f3 -> 0x1e7 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x18, allowed: 0 1 2 5 6 7 8
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1e7 -> 0x1cf (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x30, allowed: 0 1 2 3 6 7 8
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1cf -> 0x19f (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x60, allowed: 0 1 2 3 4 7 8
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x19f -> 0x13f (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xc0, allowed: 0 1 2 3 4 5 8
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x13f -> 0x07f (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07f -> 0x0fe (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x01, allowed: 1 2 3 4 5 6 7
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fe -> 0x1fc (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x03, allowed: 2 3 4 5 6 7 8
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fc -> 0x1f9 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x06, allowed: 0 3 4 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f9 -> 0x1f3 (active_len=7, ramp_len=10, adm_len=7, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0c, allowed: 0 1 4 5 6 7 8
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 7)===
+(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()
+(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, allowed: 3 4 5 6 7 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f8 -> 0x3f1 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x0e, allowed: 0 4 5 6 7 8 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f1 -> 0x3e3 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x1c, allowed: 0 1 5 6 7 8 9
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e3 -> 0x3c7 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x38, allowed: 0 1 2 6 7 8 9
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c7 -> 0x38f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x70, allowed: 0 1 2 3 7 8 9
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x38f -> 0x31f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xe0, allowed: 0 1 2 3 4 8 9
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x31f -> 0x23f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xc0, allowed: 0 1 2 3 4 5 9
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x23f -> 0x07f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07f -> 0x0fe (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x01, allowed: 1 2 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fe -> 0x1fc (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x03, allowed: 2 3 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fc -> 0x3f8 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x07, allowed: 3 4 5 6 7 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f8 -> 0x3f1 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x0e, allowed: 0 4 5 6 7 8 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f1 -> 0x3e3 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x1c, allowed: 0 1 5 6 7 8 9
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e3 -> 0x3c7 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x38, allowed: 0 1 2 6 7 8 9
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3c7 -> 0x38f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x70, allowed: 0 1 2 3 7 8 9
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x38f -> 0x31f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xe0, allowed: 0 1 2 3 4 8 9
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x31f -> 0x23f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0xc0, allowed: 0 1 2 3 4 5 9
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x23f -> 0x07f (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x07f -> 0x0fe (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x01, allowed: 1 2 3 4 5 6 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fe -> 0x1fc (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x03, allowed: 2 3 4 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fc -> 0x3f8 (active_len=7, ramp_len=10, adm_len=7, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x07, allowed: 3 4 5 6 7 8 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(true, 8)===
+(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, allowed: 0 1 2 3 4 5 6 7 8
+(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1fe (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x01, allowed: 1 2 3 4 5 6 7 8
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fe -> 0x1fd (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x02, allowed: 0 2 3 4 5 6 7 8
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fd -> 0x1fb (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x04, allowed: 0 1 3 4 5 6 7 8
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fb -> 0x1f7 (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x08, allowed: 0 1 2 4 5 6 7 8
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f7 -> 0x1ef (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x10, allowed: 0 1 2 3 5 6 7 8
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1ef -> 0x1df (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x20, allowed: 0 1 2 3 4 6 7 8
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1df -> 0x1bf (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x40, allowed: 0 1 2 3 4 5 7 8
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1bf -> 0x17f (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x80, allowed: 0 1 2 3 4 5 6 8
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x17f -> 0x0ff (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0ff -> 0x1fe (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x01, allowed: 1 2 3 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fe -> 0x1fd (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x02, allowed: 0 2 3 4 5 6 7 8
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fd -> 0x1fb (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x04, allowed: 0 1 3 4 5 6 7 8
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fb -> 0x1f7 (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x08, allowed: 0 1 2 4 5 6 7 8
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1f7 -> 0x1ef (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x10, allowed: 0 1 2 3 5 6 7 8
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1ef -> 0x1df (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x20, allowed: 0 1 2 3 4 6 7 8
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1df -> 0x1bf (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x40, allowed: 0 1 2 3 4 5 7 8
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1bf -> 0x17f (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x80, allowed: 0 1 2 3 4 5 6 8
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x17f -> 0x0ff (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0ff -> 0x1fe (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x01, allowed: 1 2 3 4 5 6 7 8
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fe -> 0x1fd (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x02, allowed: 0 2 3 4 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fd -> 0x1fb (active_len=8, ramp_len=10, adm_len=8, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x04, allowed: 0 1 3 4 5 6 7 8
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 8)===
+(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()
+(bts=0) ACC: update ACC allowed active subset 0x3ff -> 0x3fc (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x03, allowed: 2 3 4 5 6 7 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fc -> 0x3f9 (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x06, allowed: 0 3 4 5 6 7 8 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f9 -> 0x3f3 (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x0c, allowed: 0 1 4 5 6 7 8 9
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f3 -> 0x3e7 (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x18, allowed: 0 1 2 5 6 7 8 9
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e7 -> 0x3cf (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x30, allowed: 0 1 2 3 6 7 8 9
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3cf -> 0x39f (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x60, allowed: 0 1 2 3 4 7 8 9
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x39f -> 0x33f (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xc0, allowed: 0 1 2 3 4 5 8 9
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x33f -> 0x27f (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0x80, allowed: 0 1 2 3 4 5 6 9
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x27f -> 0x0ff (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0ff -> 0x1fe (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x01, allowed: 1 2 3 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fe -> 0x3fc (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x03, allowed: 2 3 4 5 6 7 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fc -> 0x3f9 (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x06, allowed: 0 3 4 5 6 7 8 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f9 -> 0x3f3 (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x0c, allowed: 0 1 4 5 6 7 8 9
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f3 -> 0x3e7 (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x18, allowed: 0 1 2 5 6 7 8 9
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3e7 -> 0x3cf (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x30, allowed: 0 1 2 3 6 7 8 9
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3cf -> 0x39f (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x60, allowed: 0 1 2 3 4 7 8 9
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x39f -> 0x33f (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0xc0, allowed: 0 1 2 3 4 5 8 9
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x33f -> 0x27f (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0x80, allowed: 0 1 2 3 4 5 6 9
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x27f -> 0x0ff (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0ff -> 0x1fe (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x01, allowed: 1 2 3 4 5 6 7 8
+sys={40.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1fe -> 0x3fc (active_len=8, ramp_len=10, adm_len=8, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x03, allowed: 2 3 4 5 6 7 8 9
+BTS deallocated OK in test_acc_mgr_rotate()
+===test_acc_mgr_rotate(false, 9)===
+(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()
+(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, allowed: 1 2 3 4 5 6 7 8 9
+sys={2.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fe -> 0x3fd (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x02, allowed: 0 2 3 4 5 6 7 8 9
+sys={4.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fd -> 0x3fb (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x04, allowed: 0 1 3 4 5 6 7 8 9
+sys={6.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fb -> 0x3f7 (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x08, allowed: 0 1 2 4 5 6 7 8 9
+sys={8.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f7 -> 0x3ef (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x10, allowed: 0 1 2 3 5 6 7 8 9
+sys={10.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3ef -> 0x3df (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x20, allowed: 0 1 2 3 4 6 7 8 9
+sys={12.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3df -> 0x3bf (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x40, allowed: 0 1 2 3 4 5 7 8 9
+sys={14.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3bf -> 0x37f (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x80, allowed: 0 1 2 3 4 5 6 8 9
+sys={16.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x37f -> 0x2ff (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0x00, allowed: 0 1 2 3 4 5 6 7 9
+sys={18.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x2ff -> 0x1ff (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
+sys={20.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x1ff -> 0x3fe (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x01, allowed: 1 2 3 4 5 6 7 8 9
+sys={22.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fe -> 0x3fd (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x02, allowed: 0 2 3 4 5 6 7 8 9
+sys={24.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fd -> 0x3fb (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x04, allowed: 0 1 3 4 5 6 7 8 9
+sys={26.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3fb -> 0x3f7 (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x08, allowed: 0 1 2 4 5 6 7 8 9
+sys={28.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3f7 -> 0x3ef (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x10, allowed: 0 1 2 3 5 6 7 8 9
+sys={30.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3ef -> 0x3df (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x20, allowed: 0 1 2 3 4 6 7 8 9
+sys={32.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3df -> 0x3bf (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x40, allowed: 0 1 2 3 4 5 7 8 9
+sys={34.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x3bf -> 0x37f (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x80, allowed: 0 1 2 3 4 5 6 8 9
+sys={36.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x37f -> 0x2ff (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x01 t3=0x00, allowed: 0 1 2 3 4 5 6 7 9
+sys={38.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x2ff -> 0x1ff (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
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=0) ACC: rotate ACC allowed active subset 0x1ff -> 0x3fe (active_len=9, ramp_len=10, adm_len=9, perm_len=10, rotation=on)
+pcu_info_update(): t2=0x00 t3=0x01, allowed: 1 2 3 4 5 6 7 8 9
BTS deallocated OK in test_acc_mgr_rotate()
===test_acc_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_ramp()
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
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
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
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
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
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
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
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
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
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
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
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
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
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
+pcu_info_update(): t2=0x00 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8 9
BTS deallocated OK in test_acc_ramp()
===test_acc_ramp2===
(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_ramp2()
(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
+pcu_info_update(): t2=0x00 t3=0x07, allowed: 3 4 5 6 7 8 9
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xf8, allowed: 0 1 2
sys={5.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
+pcu_info_update(): t2=0x03 t3=0xc0, allowed: 0 1 2 3 4 5
sys={10.000000}: select()
(bts=0) ACC: update ACC allowed active subset 0x03f -> 0x07f (active_len=7, ramp_len=7, adm_len=7, perm_len=10, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x80
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
sys={15.000000}: select()
BTS deallocated OK in test_acc_ramp2()
===test_acc_ramp3===
@@ -470,23 +1547,23 @@ BTS deallocated OK in test_acc_ramp2()
BTS allocation OK in test_acc_ramp3()
*** 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
+pcu_info_update(): t2=0x02 t3=0xa5, allowed: 1 3 4 6 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
sys={5.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
+pcu_info_update(): t2=0x03 t3=0xf5, allowed: 1 3
sys={10.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
+pcu_info_update(): t2=0x03 t3=0xe5, allowed: 1 3 4
sys={15.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
+pcu_info_update(): t2=0x03 t3=0xa5, allowed: 1 3 4 6
sys={20.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
+pcu_info_update(): t2=0x02 t3=0xa5, allowed: 1 3 4 6 8
sys={25.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={30.000000}: select()
@@ -503,83 +1580,83 @@ BTS deallocated OK in test_acc_ramp3()
BTS allocation OK in test_acc_ramp_up_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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
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
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
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
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
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
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
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
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
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
+pcu_info_update(): t2=0x02 t3=0x3e, allowed: 0 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x183 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7c, allowed: 0 1 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x107 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
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
+(bts=0) ACC: update ACC allowed active subset 0x107 -> 0x10f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf0, allowed: 0 1 2 3 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x10f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
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
+(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
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
+(bts=0) ACC: update ACC allowed active subset 0x03e -> 0x07e (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x81, allowed: 1 2 3 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x03, allowed: 2 3 4 5 6 7
+sys={1450.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1f8 -> 0x1f9 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x06, allowed: 0 3 4 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1f9 -> 0x1f3 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0c, allowed: 0 1 4 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1f3 -> 0x1e7 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x18, allowed: 0 1 2 5 6 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1e7 -> 0x1ef (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x10, allowed: 0 1 2 3 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1ef -> 0x1df (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x20, allowed: 0 1 2 3 4 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1df -> 0x1bf (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x40, allowed: 0 1 2 3 4 5 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1bf -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=9, rotation=off)
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
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)
sys={2500.000000}: select()
@@ -592,83 +1669,83 @@ BTS deallocated OK in test_acc_ramp_up_rotate()
BTS allocation OK in test_acc_ramp_up_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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
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
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
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
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
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
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
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
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
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
+pcu_info_update(): t2=0x02 t3=0x3e, allowed: 0 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x183 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7c, allowed: 0 1 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x107 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
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
+(bts=0) ACC: update ACC allowed active subset 0x107 -> 0x10f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf0, allowed: 0 1 2 3 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x10f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
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
+(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
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
+(bts=0) ACC: update ACC allowed active subset 0x03e -> 0x07e (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x81, allowed: 1 2 3 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x03, allowed: 2 3 4 5 6 7
+sys={1450.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1f8 -> 0x1f9 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x06, allowed: 0 3 4 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1f9 -> 0x1f3 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0c, allowed: 0 1 4 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1f3 -> 0x1e7 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x18, allowed: 0 1 2 5 6 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1e7 -> 0x1ef (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x10, allowed: 0 1 2 3 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1ef -> 0x1df (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x20, allowed: 0 1 2 3 4 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1df -> 0x1bf (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x40, allowed: 0 1 2 3 4 5 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1bf -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=9, rotation=off)
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
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)
sys={2500.000000}: select()
@@ -681,83 +1758,83 @@ BTS deallocated OK in test_acc_ramp_up_rotate()
BTS allocation OK in test_acc_ramp_up_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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
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
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
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
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
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
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
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
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
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
+pcu_info_update(): t2=0x02 t3=0x3e, allowed: 0 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1c1 -> 0x183 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7c, allowed: 0 1 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x107 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
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
+(bts=0) ACC: update ACC allowed active subset 0x107 -> 0x10f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf0, allowed: 0 1 2 3 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x10f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe0, allowed: 0 1 2 3 4
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
+(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
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
+(bts=0) ACC: update ACC allowed active subset 0x03e -> 0x07e (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x81, allowed: 1 2 3 4 5 6
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
+pcu_info_update(): t2=0x03 t3=0x03, allowed: 2 3 4 5 6 7
+sys={1450.000000}: select()
+(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1f8 -> 0x1f9 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x06, allowed: 0 3 4 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1f9 -> 0x1f3 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x0c, allowed: 0 1 4 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1f3 -> 0x1e7 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x18, allowed: 0 1 2 5 6 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1e7 -> 0x1ef (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x10, allowed: 0 1 2 3 5 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1ef -> 0x1df (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x20, allowed: 0 1 2 3 4 6 7 8
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
+(bts=0) ACC: rotate ACC allowed active subset 0x1df -> 0x1bf (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x40, allowed: 0 1 2 3 4 5 7 8
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
+(bts=0) ACC: update ACC allowed active subset 0x1bf -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=9, rotation=off)
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
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)
sys={2500.000000}: select()
@@ -770,97 +1847,97 @@ BTS deallocated OK in test_acc_ramp_up_rotate()
BTS allocation OK in test_acc_ramp_updown_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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
sys={100.000000}: select(0): chan_load_avg=0
(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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
sys={200.000000}: select(1): chan_load_avg=15
(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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
sys={250.000000}: select(2): chan_load_avg=30
(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
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
sys={350.000000}: select(3): chan_load_avg=45
(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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
sys={450.000000}: select(4): chan_load_avg=60
(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
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
sys={500.000000}: select(5): chan_load_avg=75
(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
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
sys={600.000000}: select(6): chan_load_avg=90
(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
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
sys={700.000000}: select(7): chan_load_avg=100
(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
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
sys={750.000000}: select(8): chan_load_avg=85
sys={850.000000}: select(9): chan_load_avg=70
(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x181 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x7e
+pcu_info_update(): t2=0x02 t3=0x7e, allowed: 0 7 8
sys={950.000000}: select(10): chan_load_avg=55
-(bts=0) ACC: rotate ACC allowed active subset 0x181 -> 0x083 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7c
+(bts=0) ACC: rotate ACC allowed active subset 0x181 -> 0x103 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfc, allowed: 0 1 8
sys={1000.000000}: select(11): chan_load_avg=40
-(bts=0) ACC: update ACC allowed active subset 0x083 -> 0x183 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x7c
+(bts=0) ACC: update ACC allowed active subset 0x103 -> 0x107 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
sys={1100.000000}: select(12): chan_load_avg=25
-(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x087 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x78
+(bts=0) ACC: rotate ACC allowed active subset 0x107 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
sys={1200.000000}: select(13): chan_load_avg=10
-(bts=0) ACC: rotate ACC allowed active subset 0x087 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf0
+(bts=0) ACC: rotate ACC allowed active subset 0x00f -> 0x01e (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe1, allowed: 1 2 3 4
sys={1250.000000}: select(14): chan_load_avg=0
-(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x01f (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xe0
+(bts=0) ACC: update ACC allowed active subset 0x01e -> 0x03e (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc1, allowed: 1 2 3 4 5
sys={1350.000000}: select(15): chan_load_avg=15
-(bts=0) ACC: rotate ACC allowed active subset 0x01f -> 0x03e (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xc1
-sys={1450.000000}: select(16): chan_load_avg=30
(bts=0) ACC: rotate ACC allowed active subset 0x03e -> 0x07c (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x83
+pcu_info_update(): t2=0x03 t3=0x83, allowed: 2 3 4 5 6
+sys={1450.000000}: select(16): chan_load_avg=30
+(bts=0) ACC: rotate ACC allowed active subset 0x07c -> 0x0f8 (active_len=5, ramp_len=5, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x07, allowed: 3 4 5 6 7
sys={1500.000000}: select(17): chan_load_avg=45
-(bts=0) ACC: update ACC allowed active subset 0x07c -> 0x0fc (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x03
+(bts=0) ACC: update ACC allowed active subset 0x0f8 -> 0x1f8 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x07, allowed: 3 4 5 6 7 8
sys={1600.000000}: select(18): chan_load_avg=60
-(bts=0) ACC: rotate ACC allowed active subset 0x0fc -> 0x1f8 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x07
-sys={1700.000000}: select(19): chan_load_avg=75
(bts=0) ACC: rotate ACC allowed active subset 0x1f8 -> 0x1f1 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x0e
+pcu_info_update(): t2=0x02 t3=0x0e, allowed: 0 4 5 6 7 8
+sys={1700.000000}: select(19): chan_load_avg=75
+(bts=0) ACC: rotate ACC allowed active subset 0x1f1 -> 0x1e3 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x1c, allowed: 0 1 5 6 7 8
sys={1750.000000}: select(20): chan_load_avg=90
sys={1850.000000}: select(21): chan_load_avg=100
-(bts=0) ACC: rotate ACC allowed active subset 0x1f1 -> 0x0f3 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x0c
+(bts=0) ACC: rotate ACC allowed active subset 0x1e3 -> 0x1c7 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x38, allowed: 0 1 2 6 7 8
sys={1950.000000}: select(22): chan_load_avg=85
-(bts=0) ACC: rotate ACC allowed active subset 0x0f3 -> 0x077 (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x88
+(bts=0) ACC: rotate ACC allowed active subset 0x1c7 -> 0x18f (active_len=6, ramp_len=6, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x70, allowed: 0 1 2 3 7 8
sys={2000.000000}: select(23): chan_load_avg=70
-(bts=0) ACC: update ACC allowed active subset 0x077 -> 0x0f7 (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x08
+(bts=0) ACC: update ACC allowed active subset 0x18f -> 0x19f (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x60, allowed: 0 1 2 3 4 7 8
sys={2100.000000}: select(24): chan_load_avg=55
-(bts=0) ACC: rotate ACC allowed active subset 0x0f7 -> 0x07f (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x80
+(bts=0) ACC: rotate ACC allowed active subset 0x19f -> 0x13f (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xc0, allowed: 0 1 2 3 4 5 8
sys={2200.000000}: select(25): chan_load_avg=40
-(bts=0) ACC: rotate ACC allowed active subset 0x07f -> 0x0fe (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x01
+(bts=0) ACC: rotate ACC allowed active subset 0x13f -> 0x07f (active_len=7, ramp_len=7, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x80, allowed: 0 1 2 3 4 5 6
sys={2250.000000}: select(26): chan_load_avg=25
-(bts=0) ACC: update ACC allowed active subset 0x0fe -> 0x1fe (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x01
+(bts=0) ACC: update ACC allowed active subset 0x07f -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x00, allowed: 0 1 2 3 4 5 6 7
sys={2350.000000}: select(27): chan_load_avg=10
-(bts=0) ACC: rotate ACC allowed active subset 0x1fe -> 0x1fd (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x02
+(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, allowed: 1 2 3 4 5 6 7 8
sys={2450.000000}: select(28): chan_load_avg=0
-(bts=0) ACC: rotate ACC allowed active subset 0x1fd -> 0x0ff (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x00
+(bts=0) ACC: rotate ACC allowed active subset 0x1fe -> 0x1fd (active_len=8, ramp_len=8, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x02, allowed: 0 2 3 4 5 6 7 8
sys={2500.000000}: select(29): chan_load_avg=15
-(bts=0) ACC: update ACC allowed active subset 0x0ff -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=9, rotation=off)
-pcu_info_update(): t2=0x02 t3=0x00
+(bts=0) ACC: update ACC allowed active subset 0x1fd -> 0x1ff (active_len=9, ramp_len=9, adm_len=10, perm_len=9, rotation=off)
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
sys={2750.000000}: select(30): chan_load_avg=30
(bts=0) ACC: update ACC allowed active subset 0x1ff -> 0x1ff (active_len=9, ramp_len=10, adm_len=10, perm_len=9, rotation=off)
sys={3000.000000}: select(31): chan_load_avg=45
@@ -889,305 +1966,305 @@ BTS deallocated OK in test_acc_ramp_updown_rotate()
BTS allocation OK in test_acc_ramp_updown_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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
sys={100.000000}: select(0): chan_load_avg=10
(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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
sys={200.000000}: select(1): chan_load_avg=25
(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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
sys={250.000000}: select(2): chan_load_avg=40
sys={350.000000}: select(3): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x004 -> 0x008 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf7
+pcu_info_update(): t2=0x03 t3=0xf7, allowed: 3
sys={450.000000}: select(4): chan_load_avg=70
(bts=0) ACC: rotate ACC allowed active subset 0x008 -> 0x010 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xef
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
sys={500.000000}: select(5): chan_load_avg=85
sys={600.000000}: select(6): chan_load_avg=100
(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xdf
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
sys={700.000000}: select(7): chan_load_avg=85
(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xbf
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
sys={750.000000}: select(8): chan_load_avg=70
sys={850.000000}: select(9): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7f
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
sys={950.000000}: select(10): chan_load_avg=40
(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xff
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
sys={1000.000000}: select(11): chan_load_avg=25
(bts=0) ACC: update ACC allowed active subset 0x100 -> 0x101 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xfe
+pcu_info_update(): t2=0x02 t3=0xfe, allowed: 0 8
sys={1100.000000}: select(12): chan_load_avg=10
(bts=0) ACC: rotate ACC allowed active subset 0x101 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xfc
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
sys={1200.000000}: select(13): chan_load_avg=25
(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf9
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
sys={1250.000000}: select(14): chan_load_avg=40
sys={1350.000000}: select(15): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x006 -> 0x00c (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf3
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
sys={1450.000000}: select(16): chan_load_avg=70
(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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
sys={1500.000000}: select(17): chan_load_avg=85
(bts=0) ACC: update ACC allowed active subset 0x018 -> 0x010 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xef
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
sys={1600.000000}: select(18): chan_load_avg=100
(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xdf
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
sys={1700.000000}: select(19): chan_load_avg=85
(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xbf
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
sys={1750.000000}: select(20): chan_load_avg=70
sys={1850.000000}: select(21): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7f
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
sys={1950.000000}: select(22): chan_load_avg=40
(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xff
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
sys={2000.000000}: select(23): chan_load_avg=25
(bts=0) ACC: update ACC allowed active subset 0x100 -> 0x101 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xfe
+pcu_info_update(): t2=0x02 t3=0xfe, allowed: 0 8
sys={2100.000000}: select(24): chan_load_avg=10
(bts=0) ACC: rotate ACC allowed active subset 0x101 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xfc
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
sys={2200.000000}: select(25): chan_load_avg=25
(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf9
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
sys={2250.000000}: select(26): chan_load_avg=40
sys={2350.000000}: select(27): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x006 -> 0x00c (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf3
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
sys={2450.000000}: select(28): chan_load_avg=70
(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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
sys={2500.000000}: select(29): chan_load_avg=85
(bts=0) ACC: update ACC allowed active subset 0x018 -> 0x010 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xef
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
sys={2600.000000}: select(30): chan_load_avg=100
(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xdf
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
sys={2700.000000}: select(31): chan_load_avg=85
(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xbf
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
sys={2750.000000}: select(32): chan_load_avg=70
sys={2850.000000}: select(33): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7f
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
sys={2950.000000}: select(34): chan_load_avg=40
(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xff
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
sys={3000.000000}: select(35): chan_load_avg=25
(bts=0) ACC: update ACC allowed active subset 0x100 -> 0x101 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xfe
+pcu_info_update(): t2=0x02 t3=0xfe, allowed: 0 8
sys={3100.000000}: select(36): chan_load_avg=10
(bts=0) ACC: rotate ACC allowed active subset 0x101 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xfc
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
sys={3200.000000}: select(37): chan_load_avg=25
(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf9
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
sys={3250.000000}: select(38): chan_load_avg=40
sys={3350.000000}: select(39): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x006 -> 0x00c (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf3
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
sys={3450.000000}: select(40): chan_load_avg=70
(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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
sys={3500.000000}: select(41): chan_load_avg=85
(bts=0) ACC: update ACC allowed active subset 0x018 -> 0x010 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xef
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
sys={3600.000000}: select(42): chan_load_avg=100
(bts=0) ACC: rotate ACC allowed active subset 0x010 -> 0x020 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xdf
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
sys={3700.000000}: select(43): chan_load_avg=85
(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xbf
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
sys={3750.000000}: select(44): chan_load_avg=70
sys={3850.000000}: select(45): chan_load_avg=55
(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7f
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
sys={3950.000000}: select(46): chan_load_avg=40
(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xff
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
sys={4000.000000}: select(47): chan_load_avg=25
(bts=0) ACC: update ACC allowed active subset 0x100 -> 0x101 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xfe
+pcu_info_update(): t2=0x02 t3=0xfe, allowed: 0 8
sys={4100.000000}: select(48): chan_load_avg=10
(bts=0) ACC: rotate ACC allowed active subset 0x101 -> 0x003 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xfc
+pcu_info_update(): t2=0x03 t3=0xfc, allowed: 0 1
sys={4200.000000}: select(49): chan_load_avg=25
(bts=0) ACC: rotate ACC allowed active subset 0x003 -> 0x006 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf9
+pcu_info_update(): t2=0x03 t3=0xf9, allowed: 1 2
BTS deallocated OK in test_acc_ramp_updown_rotate()
===test_acc_ramp_updown_rotate(50, 49, 0, 100, 10)===
(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_updown_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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
(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
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
sys={100.000000}: select(0): chan_load_avg=0
(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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
sys={200.000000}: select(1): chan_load_avg=10
(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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
sys={250.000000}: select(2): chan_load_avg=20
(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
+pcu_info_update(): t2=0x03 t3=0xf3, allowed: 2 3
sys={350.000000}: select(3): chan_load_avg=30
(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
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
sys={450.000000}: select(4): chan_load_avg=40
(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
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
sys={500.000000}: select(5): chan_load_avg=50
(bts=0) ACC: update ACC allowed active subset 0x030 -> 0x020 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xdf
+pcu_info_update(): t2=0x03 t3=0xdf, allowed: 5
sys={600.000000}: select(6): chan_load_avg=60
(bts=0) ACC: rotate ACC allowed active subset 0x020 -> 0x040 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xbf
+pcu_info_update(): t2=0x03 t3=0xbf, allowed: 6
sys={700.000000}: select(7): chan_load_avg=70
(bts=0) ACC: rotate ACC allowed active subset 0x040 -> 0x080 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7f
+pcu_info_update(): t2=0x03 t3=0x7f, allowed: 7
sys={750.000000}: select(8): chan_load_avg=80
sys={850.000000}: select(9): chan_load_avg=90
(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xff
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
sys={950.000000}: select(10): chan_load_avg=100
(bts=0) ACC: rotate ACC allowed active subset 0x100 -> 0x001 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xfe
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
sys={1000.000000}: select(11): chan_load_avg=90
sys={1100.000000}: select(12): chan_load_avg=80
(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
+pcu_info_update(): t2=0x03 t3=0xfd, allowed: 1
sys={1200.000000}: select(13): chan_load_avg=70
(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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
sys={1250.000000}: select(14): chan_load_avg=60
sys={1350.000000}: select(15): chan_load_avg=50
(bts=0) ACC: rotate ACC allowed active subset 0x004 -> 0x008 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf7
+pcu_info_update(): t2=0x03 t3=0xf7, allowed: 3
sys={1450.000000}: select(16): chan_load_avg=40
(bts=0) ACC: rotate ACC allowed active subset 0x008 -> 0x010 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xef
+pcu_info_update(): t2=0x03 t3=0xef, allowed: 4
sys={1500.000000}: select(17): chan_load_avg=30
(bts=0) ACC: update ACC allowed active subset 0x010 -> 0x030 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xcf
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
sys={1600.000000}: select(18): chan_load_avg=20
(bts=0) ACC: rotate ACC allowed active subset 0x030 -> 0x060 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x9f
+pcu_info_update(): t2=0x03 t3=0x9f, allowed: 5 6
sys={1700.000000}: select(19): chan_load_avg=10
(bts=0) ACC: rotate ACC allowed active subset 0x060 -> 0x0c0 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x3f
+pcu_info_update(): t2=0x03 t3=0x3f, allowed: 6 7
sys={1750.000000}: select(20): chan_load_avg=0
(bts=0) ACC: update ACC allowed active subset 0x0c0 -> 0x1c0 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x3f
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
sys={1850.000000}: select(21): chan_load_avg=10
(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x181 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x7e
+pcu_info_update(): t2=0x02 t3=0x7e, allowed: 0 7 8
sys={1950.000000}: select(22): chan_load_avg=20
-(bts=0) ACC: rotate ACC allowed active subset 0x181 -> 0x083 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7c
+(bts=0) ACC: rotate ACC allowed active subset 0x181 -> 0x103 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xfc, allowed: 0 1 8
sys={2000.000000}: select(23): chan_load_avg=30
-(bts=0) ACC: update ACC allowed active subset 0x083 -> 0x183 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0x7c
+(bts=0) ACC: update ACC allowed active subset 0x103 -> 0x107 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
sys={2100.000000}: select(24): chan_load_avg=40
-(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x087 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x78
+(bts=0) ACC: rotate ACC allowed active subset 0x107 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
sys={2200.000000}: select(25): chan_load_avg=50
-(bts=0) ACC: rotate ACC allowed active subset 0x087 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf0
+(bts=0) ACC: rotate ACC allowed active subset 0x00f -> 0x01e (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe1, allowed: 1 2 3 4
sys={2250.000000}: select(26): chan_load_avg=60
-(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x00e (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf1
+(bts=0) ACC: update ACC allowed active subset 0x01e -> 0x01c (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe3, allowed: 2 3 4
sys={2350.000000}: select(27): chan_load_avg=70
-(bts=0) ACC: rotate ACC allowed active subset 0x00e -> 0x01c (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xe3
-sys={2450.000000}: select(28): chan_load_avg=80
(bts=0) ACC: rotate ACC allowed active subset 0x01c -> 0x038 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xc7
+pcu_info_update(): t2=0x03 t3=0xc7, allowed: 3 4 5
+sys={2450.000000}: select(28): chan_load_avg=80
+(bts=0) ACC: rotate ACC allowed active subset 0x038 -> 0x070 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x8f, allowed: 4 5 6
sys={2500.000000}: select(29): chan_load_avg=90
-(bts=0) ACC: update ACC allowed active subset 0x038 -> 0x030 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xcf
+(bts=0) ACC: update ACC allowed active subset 0x070 -> 0x060 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x9f, allowed: 5 6
sys={2600.000000}: select(30): chan_load_avg=100
-(bts=0) ACC: rotate ACC allowed active subset 0x030 -> 0x060 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x9f
-sys={2700.000000}: select(31): chan_load_avg=90
(bts=0) ACC: rotate ACC allowed active subset 0x060 -> 0x0c0 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x3f
+pcu_info_update(): t2=0x03 t3=0x3f, allowed: 6 7
+sys={2700.000000}: select(31): chan_load_avg=90
+(bts=0) ACC: rotate ACC allowed active subset 0x0c0 -> 0x180 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7f, allowed: 7 8
sys={2750.000000}: select(32): chan_load_avg=80
-(bts=0) ACC: update ACC allowed active subset 0x0c0 -> 0x080 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0x7f
+(bts=0) ACC: update ACC allowed active subset 0x180 -> 0x100 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xff, allowed: 8
sys={2850.000000}: select(33): chan_load_avg=70
-(bts=0) ACC: rotate ACC allowed active subset 0x080 -> 0x100 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x02 t3=0xff
-sys={2950.000000}: select(34): chan_load_avg=60
(bts=0) ACC: rotate ACC allowed active subset 0x100 -> 0x001 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xfe
+pcu_info_update(): t2=0x03 t3=0xfe, allowed: 0
+sys={2950.000000}: select(34): chan_load_avg=60
+(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, allowed: 1
sys={3000.000000}: select(35): chan_load_avg=50
sys={3100.000000}: select(36): chan_load_avg=40
-(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={3200.000000}: select(37): chan_load_avg=30
(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
+pcu_info_update(): t2=0x03 t3=0xfb, allowed: 2
+sys={3200.000000}: select(37): chan_load_avg=30
+(bts=0) ACC: rotate ACC allowed active subset 0x004 -> 0x008 (active_len=1, ramp_len=1, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf7, allowed: 3
sys={3250.000000}: select(38): chan_load_avg=20
-(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
+(bts=0) ACC: update ACC allowed active subset 0x008 -> 0x018 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xe7, allowed: 3 4
sys={3350.000000}: select(39): chan_load_avg=10
-(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={3450.000000}: select(40): chan_load_avg=0
(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
+pcu_info_update(): t2=0x03 t3=0xcf, allowed: 4 5
+sys={3450.000000}: select(40): chan_load_avg=0
+(bts=0) ACC: rotate ACC allowed active subset 0x030 -> 0x060 (active_len=2, ramp_len=2, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x9f, allowed: 5 6
sys={3500.000000}: select(41): chan_load_avg=10
-(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
+(bts=0) ACC: update ACC allowed active subset 0x060 -> 0x0e0 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0x1f, allowed: 5 6 7
sys={3600.000000}: select(42): chan_load_avg=20
-(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={3700.000000}: select(43): chan_load_avg=30
(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
+pcu_info_update(): t2=0x02 t3=0x3f, allowed: 6 7 8
+sys={3700.000000}: select(43): chan_load_avg=30
+(bts=0) ACC: rotate ACC allowed active subset 0x1c0 -> 0x181 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7e, allowed: 0 7 8
sys={3750.000000}: select(44): chan_load_avg=40
-(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
+(bts=0) ACC: update ACC allowed active subset 0x181 -> 0x183 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0x7c, allowed: 0 1 7 8
sys={3850.000000}: select(45): chan_load_avg=50
-(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
+(bts=0) ACC: rotate ACC allowed active subset 0x183 -> 0x107 (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x02 t3=0xf8, allowed: 0 1 2 8
sys={3950.000000}: select(46): chan_load_avg=60
-(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
+(bts=0) ACC: rotate ACC allowed active subset 0x107 -> 0x00f (active_len=4, ramp_len=4, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf0, allowed: 0 1 2 3
sys={4000.000000}: select(47): chan_load_avg=70
-(bts=0) ACC: update ACC allowed active subset 0x047 -> 0x046 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xb9
+(bts=0) ACC: update ACC allowed active subset 0x00f -> 0x00e (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xf1, allowed: 1 2 3
sys={4100.000000}: select(48): chan_load_avg=80
-(bts=0) ACC: rotate ACC allowed active subset 0x046 -> 0x00e (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xf1
-sys={4200.000000}: select(49): chan_load_avg=90
(bts=0) ACC: rotate ACC allowed active subset 0x00e -> 0x01c (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
-pcu_info_update(): t2=0x03 t3=0xe3
+pcu_info_update(): t2=0x03 t3=0xe3, allowed: 2 3 4
+sys={4200.000000}: select(49): chan_load_avg=90
+(bts=0) ACC: rotate ACC allowed active subset 0x01c -> 0x038 (active_len=3, ramp_len=3, adm_len=10, perm_len=9, rotation=on)
+pcu_info_update(): t2=0x03 t3=0xc7, allowed: 3 4 5
BTS deallocated OK in test_acc_ramp_updown_rotate()
===test_acc_ramp_updown_rotate(30, 80, 30, 80, 5)===
(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_updown_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
+pcu_info_update(): t2=0x02 t3=0x00, allowed: 0 1 2 3 4 5 6 7 8
(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
+pcu_info_update(): t2=0x03 t3=0xff, allowed:
sys={250.000000}: select(0): chan_load_avg=30
sys={500.000000}: select(1): chan_load_avg=35
sys={750.000000}: select(2): chan_load_avg=40
diff --git a/tests/bsc/bsc_test.c b/tests/bsc/bsc_test.c
index dd2b1bbb5..d9996081e 100644
--- a/tests/bsc/bsc_test.c
+++ b/tests/bsc/bsc_test.c
@@ -223,7 +223,7 @@ struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_network *ne
OSMO_ASSERT(0);
}
-void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci) {}
+void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause) {}
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) {}
int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, uint16_t chosen_channel)
{ return 0; }
diff --git a/tests/cbc.vty b/tests/cbc.vty
new file mode 100644
index 000000000..a15de5993
--- /dev/null
+++ b/tests/cbc.vty
@@ -0,0 +1,275 @@
+OsmoBSC> ### CBSP link config
+
+OsmoBSC> list
+...
+ show cbc
+...
+
+OsmoBSC> enable
+OsmoBSC# list
+...
+ show cbc
+...
+
+OsmoBSC# show running-config
+... !cbc
+
+OsmoBSC# show cbc
+CBSP link is disabled
+
+OsmoBSC# configure terminal
+OsmoBSC(config)# cbc
+
+OsmoBSC(config-cbc)# list
+...
+ mode (server|client|disabled)
+ server
+ client
+
+OsmoBSC(config-cbc)# ?
+...
+ mode Set OsmoBSC as CBSP server or client
+ server Configure OsmoBSC's CBSP server role
+ client Configure OsmoBSC's CBSP client role
+
+OsmoBSC(config-cbc)# mode ?
+ server CBSP Server: listen for inbound TCP connections from a remote Cell Broadcast Centre
+ client CBSP Client: establish outbound TCP connection to a remote Cell Broadcast Centre
+ disabled Disable CBSP link
+
+OsmoBSC(config-cbc)# server
+OsmoBSC(config-cbc-server)# list
+...
+ local-ip (A.B.C.D|X:X::X:X)
+ local-port <1-65535>
+
+OsmoBSC(config-cbc-server)# ?
+...
+ local-ip Set IP Address to listen on for inbound CBSP from a Cell Broadcast Centre
+ local-port Set TCP port to listen on for inbound CBSP from a Cell Broadcast Centre
+
+OsmoBSC(config-cbc-server)# local-ip ?
+ A.B.C.D IPv4 address
+ X:X::X:X IPv6 address
+OsmoBSC(config-cbc-server)# local-port ?
+ <1-65535> CBSP port number (Default: 48049)
+
+OsmoBSC(config-cbc-server)# local-ip 1.2.3.4
+OsmoBSC(config-cbc-server)# local-port 12345
+OsmoBSC(config-cbc-server)# show running-config
+...
+cbc
+ mode disabled
+ server
+ local-ip 1.2.3.4
+ local-port 12345
+...
+
+OsmoBSC(config-cbc-server)# local-port 48049
+
+OsmoBSC(config-cbc-server)# show running-config
+...
+cbc
+ mode disabled
+ server
+ local-ip 1.2.3.4
+... !local-port
+
+OsmoBSC(config-cbc-server)# local-ip ::1
+OsmoBSC(config-cbc-server)# show running-config
+...
+cbc
+ mode disabled
+ server
+ local-ip ::1
+...
+
+OsmoBSC(config-cbc-server)# do show cbc
+CBSP link is disabled
+
+OsmoBSC(config-cbc-server)# exit
+
+OsmoBSC(config-cbc)# client
+OsmoBSC(config-cbc-client)# list
+...
+ remote-ip (A.B.C.D|X:X::X:X)
+ remote-port <1-65535>
+ local-ip (A.B.C.D|X:X::X:X)
+ local-port <1-65535>
+ no local-ip
+ no local-port
+
+OsmoBSC(config-cbc-client)# ?
+...
+ remote-ip Set IP Address of the Cell Broadcast Centre, to establish CBSP link to
+ remote-port Set TCP port of the Cell Broadcast Centre, to establish CBSP link to
+ local-ip Set local bind address for the outbound CBSP link to the Cell Broadcast Centre
+ local-port Set local bind port for the outbound CBSP link to the Cell Broadcast Centre
+ no Negate a command or set its defaults
+
+OsmoBSC(config-cbc-client)# remote-ip ?
+ A.B.C.D IPv4 address
+ X:X::X:X IPv6 address
+OsmoBSC(config-cbc-client)# remote-port ?
+ <1-65535> CBSP port number (Default: 48049)
+
+OsmoBSC(config-cbc-client)# no ?
+ local-ip Remove local IP address bind config for the CBSP client mode
+ local-port Remove local TCP port bind config for the CBSP client mode
+
+OsmoBSC(config-cbc-client)# remote-ip 1.2.3.4
+OsmoBSC(config-cbc-client)# remote-port 12345
+OsmoBSC(config-cbc-client)# show running-config
+...
+cbc
+...
+ client
+ remote-ip 1.2.3.4
+ remote-port 12345
+...
+
+OsmoBSC(config-cbc-client)# remote-port 48049
+
+OsmoBSC(config-cbc-client)# show running-config
+...
+cbc
+...
+ client
+ remote-ip 1.2.3.4
+... !remote-port
+
+OsmoBSC(config-cbc-client)# remote-ip 1:2:3:4::5
+OsmoBSC(config-cbc-client)# show running-config
+...
+cbc
+...
+ client
+ remote-ip 1:2:3:4::5
+...
+
+OsmoBSC(config-cbc-client)# local-ip 1.2.3.4
+
+OsmoBSC(config-cbc-client)# show running-config
+...
+cbc
+...
+ client
+ remote-ip 1:2:3:4::5
+ local-ip 1.2.3.4
+... !local-port
+
+OsmoBSC(config-cbc-client)# local-port 12345
+
+OsmoBSC(config-cbc-client)# show running-config
+...
+cbc
+...
+ client
+ remote-ip 1:2:3:4::5
+ local-ip 1.2.3.4
+ local-port 12345
+...
+
+OsmoBSC(config-cbc-client)# no local-ip
+
+OsmoBSC(config-cbc-client)# show running-config
+...
+cbc
+...
+ client
+ remote-ip 1:2:3:4::5
+ local-port 12345
+... !local
+
+OsmoBSC(config-cbc-client)# no local-port
+
+OsmoBSC(config-cbc-client)# show running-config
+...
+cbc
+...
+ client
+ remote-ip 1:2:3:4::5
+... !local
+
+OsmoBSC(config-cbc-client)# do show cbc
+CBSP link is disabled
+
+OsmoBSC(config-cbc-client)# exit
+
+OsmoBSC(config-cbc)# mode server
+OsmoBSC(config-cbc)# do show cbc
+OsmoBSC is configured as CBSP Server on [::1]:48049
+CBSP Server Connection: Disconnected
+
+OsmoBSC(config-cbc)# mode client
+OsmoBSC(config-cbc)# do show cbc
+OsmoBSC is configured as CBSP Client to remote CBC at [1:2:3:4::5]:48049
+CBSP Client Connection: Disconnected
+
+OsmoBSC(config-cbc)# mode disabled
+OsmoBSC(config-cbc)# do show cbc
+CBSP link is disabled
+
+
+OsmoBSC(config-cbc)# # TEST DEPRECATED COMMANDS
+
+OsmoBSC(config-cbc)# remote-ip 1.2.3.4
+% cbc/remote-ip config is deprecated, instead use cbc/client/remote-ip and cbc/ mode
+OsmoBSC(config-cbc)# remote-port 1234
+% cbc/remote-port config is deprecated, instead use cbc/client/remote-port
+OsmoBSC(config-cbc)# do show cbc
+OsmoBSC is configured as CBSP Client to remote CBC at 1.2.3.4:1234
+CBSP Client Connection: Disconnected
+OsmoBSC(config-cbc)# show running-config
+...
+cbc
+ mode client
+...
+ client
+ remote-ip 1.2.3.4
+ remote-port 1234
+...
+
+OsmoBSC(config-cbc)# no remote-ip
+% cbc/remote-ip config is deprecated, instead use cbc/client/remote-ip and cbc/mode
+OsmoBSC(config-cbc)# do show cbc
+CBSP link is disabled
+OsmoBSC(config-cbc)# show running-config
+...
+cbc
+ mode disabled
+...
+ client
+ remote-ip 1.2.3.4
+ remote-port 1234
+...
+
+OsmoBSC(config-cbc)# listen-ip 127.0.0.2
+% cbc/listen-ip config is deprecated, instead use cbc/server/local-ip
+OsmoBSC(config-cbc)# do show cbc
+CBSP link is disabled
+OsmoBSC(config-cbc)# listen-port 48049
+% cbc/listen-port config is deprecated, instead use cbc/server/local-port and cbc/mode
+OsmoBSC(config-cbc)# do show cbc
+OsmoBSC is configured as CBSP Server on 127.0.0.2:48049
+CBSP Server Connection: Disconnected
+OsmoBSC(config-cbc)# show running-config
+...
+cbc
+ mode server
+ server
+ local-ip 127.0.0.2
+ client
+ remote-ip 1.2.3.4
+ remote-port 1234
+...
+
+OsmoBSC(config-cbc)# no listen-port
+% cbc/listen-port config is deprecated, instead use cbc/server/local-port and cbc/mode
+OsmoBSC(config-cbc)# do show cbc
+CBSP link is disabled
+OsmoBSC(config-cbc)# show running-config
+...
+cbc
+ mode disabled
+...
diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c
index 6fb145ee6..78e8daf96 100644
--- a/tests/handover/handover_test.c
+++ b/tests/handover/handover_test.c
@@ -1794,7 +1794,7 @@ void trau_recv_lchan() {}
void trau_send_frame() {}
int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
-void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci) {}
+void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause) {}
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) {}
int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg, uint16_t chosen_channel)
{ return 0; }
diff --git a/tests/timer.vty b/tests/timer.vty
new file mode 100644
index 000000000..ad1d1676e
--- /dev/null
+++ b/tests/timer.vty
@@ -0,0 +1,148 @@
+OsmoBSC> enable
+
+OsmoBSC# show timer
+net: T7 = 10 s inter-BSC/MSC Handover outgoing, BSSMAP HO Required to HO Command timeout (default: 10 s)
+net: T8 = 10 s inter-BSC/MSC Handover outgoing, BSSMAP HO Command to final Clear timeout (default: 10 s)
+net: T10 = 6 s RR Assignment (default: 6 s)
+net: T101 = 10 s inter-BSC/MSC Handover incoming, BSSMAP HO Request to HO Accept (default: 10 s)
+net: T3101 = 3 s RR Immediate Assignment (default: 3 s)
+net: T3103 = 5 s Handover (default: 5 s)
+net: T3105 = 100 ms Physical Information (default: 100 ms)
+net: T3107 = 5 s (unused) (default: 5 s)
+net: T3109 = 5 s RSL SACCH deactivation (default: 5 s)
+net: T3111 = 2 s Wait time before RSL RF Channel Release (default: 2 s)
+net: T3113 = 7 s Paging (default: 7 s)
+net: T3115 = 10 s (unused) (default: 10 s)
+net: T3117 = 10 s (unused) (default: 10 s)
+net: T3119 = 10 s (unused) (default: 10 s)
+net: T3122 = 10 s Wait time after RR Immediate Assignment Reject (default: 10 s)
+net: T3141 = 10 s (unused) (default: 10 s)
+net: T3212 = 5 Periodic Location Update timer, sent to MS (1 = 6 minutes) (default: 5)
+net: X4 = 60 s After Clear Request, wait for MSC to Clear Command (sanity) (default: 60 s)
+net: X5 = 5 s Timeout to switch dynamic timeslot PCHAN modes (default: 5 s)
+net: X6 = 5 s Timeout for RSL Channel Activate ACK after sending RSL Channel Activate (default: 5 s)
+net: X7 = 5 s Timeout for RSL IPA CRCX ACK after sending RSL IPA CRCX (default: 5 s)
+net: X8 = 5 s Timeout for RSL IPA MDCX ACK after sending RSL IPA MDCX (default: 5 s)
+net: X9 = 5 s Timeout for availability of MGW endpoint (default: 5 s)
+net: X10 = 5 s Timeout for fully configured MGW endpoint (default: 5 s)
+net: X3111 = 4 s Wait time after lchan was released in error (should be T3111 + 2s) (default: 4 s)
+net: X3210 = 20 s After L3 Complete, wait for MSC to confirm (default: 20 s)
+mgw: X2427 = 5 s timeout for MGCP response from MGW (default: 5 s)
+
+OsmoBSC# show timer T3111
+T3111 = 2 s Wait time before RSL RF Channel Release (default: 2 s)
+
+OsmoBSC# # specifically test legacy timers that are moved to X timers
+OsmoBSC# show timer T993111
+% Legacy: timer T993111 is now X3111
+X3111 = 4 s Wait time after lchan was released in error (should be T3111 + 2s) (default: 4 s)
+OsmoBSC# show timer T993210
+% Legacy: timer T993210 is now X3210
+X3210 = 20 s After L3 Complete, wait for MSC to confirm (default: 20 s)
+OsmoBSC# show timer T999
+% Legacy: timer T999 is now X4
+X4 = 60 s After Clear Request, wait for MSC to Clear Command (sanity) (default: 60 s)
+
+OsmoBSC# configure terminal
+OsmoBSC(config)# network
+OsmoBSC(config-net)# timer
+net: T7 = 10 s inter-BSC/MSC Handover outgoing, BSSMAP HO Required to HO Command timeout (default: 10 s)
+net: T8 = 10 s inter-BSC/MSC Handover outgoing, BSSMAP HO Command to final Clear timeout (default: 10 s)
+net: T10 = 6 s RR Assignment (default: 6 s)
+net: T101 = 10 s inter-BSC/MSC Handover incoming, BSSMAP HO Request to HO Accept (default: 10 s)
+net: T3101 = 3 s RR Immediate Assignment (default: 3 s)
+net: T3103 = 5 s Handover (default: 5 s)
+net: T3105 = 100 ms Physical Information (default: 100 ms)
+net: T3107 = 5 s (unused) (default: 5 s)
+net: T3109 = 5 s RSL SACCH deactivation (default: 5 s)
+net: T3111 = 2 s Wait time before RSL RF Channel Release (default: 2 s)
+net: T3113 = 7 s Paging (default: 7 s)
+net: T3115 = 10 s (unused) (default: 10 s)
+net: T3117 = 10 s (unused) (default: 10 s)
+net: T3119 = 10 s (unused) (default: 10 s)
+net: T3122 = 10 s Wait time after RR Immediate Assignment Reject (default: 10 s)
+net: T3141 = 10 s (unused) (default: 10 s)
+net: T3212 = 5 Periodic Location Update timer, sent to MS (1 = 6 minutes) (default: 5)
+net: X4 = 60 s After Clear Request, wait for MSC to Clear Command (sanity) (default: 60 s)
+net: X5 = 5 s Timeout to switch dynamic timeslot PCHAN modes (default: 5 s)
+net: X6 = 5 s Timeout for RSL Channel Activate ACK after sending RSL Channel Activate (default: 5 s)
+net: X7 = 5 s Timeout for RSL IPA CRCX ACK after sending RSL IPA CRCX (default: 5 s)
+net: X8 = 5 s Timeout for RSL IPA MDCX ACK after sending RSL IPA MDCX (default: 5 s)
+net: X9 = 5 s Timeout for availability of MGW endpoint (default: 5 s)
+net: X10 = 5 s Timeout for fully configured MGW endpoint (default: 5 s)
+net: X3111 = 4 s Wait time after lchan was released in error (should be T3111 + 2s) (default: 4 s)
+net: X3210 = 20 s After L3 Complete, wait for MSC to confirm (default: 20 s)
+mgw: X2427 = 5 s timeout for MGCP response from MGW (default: 5 s)
+
+OsmoBSC(config-net)# # Using the legacy 'timer Txxx' still works:
+OsmoBSC(config-net)# timer T3111
+T3111 = 2 s Wait time before RSL RF Channel Release (default: 2 s)
+OsmoBSC(config-net)# timer T3111 23
+OsmoBSC(config-net)# timer T3111
+T3111 = 23 s Wait time before RSL RF Channel Release (default: 2 s)
+OsmoBSC(config-net)# timer T3111 default
+OsmoBSC(config-net)# timer T3111
+T3111 = 2 s Wait time before RSL RF Channel Release (default: 2 s)
+
+OsmoBSC(config-net)# # Using the new timer group commands also works:
+OsmoBSC(config-net)# timer net T3111
+net: T3111 = 2 s Wait time before RSL RF Channel Release (default: 2 s)
+OsmoBSC(config-net)# timer net T3111 42
+OsmoBSC(config-net)# timer net T3111
+net: T3111 = 42 s Wait time before RSL RF Channel Release (default: 2 s)
+OsmoBSC(config-net)# timer net T3111 default
+OsmoBSC(config-net)# timer net T3111
+net: T3111 = 2 s Wait time before RSL RF Channel Release (default: 2 s)
+OsmoBSC(config-net)# timer mgw
+mgw: X2427 = 5 s timeout for MGCP response from MGW (default: 5 s)
+OsmoBSC(config-net)# timer mgw X2427
+mgw: X2427 = 5 s timeout for MGCP response from MGW (default: 5 s)
+OsmoBSC(config-net)# timer mgw X2427 42
+OsmoBSC(config-net)# timer mgw X2427
+mgw: X2427 = 42 s timeout for MGCP response from MGW (default: 5 s)
+OsmoBSC(config-net)# timer mgw X2427 default
+OsmoBSC(config-net)# timer mgw X2427
+mgw: X2427 = 5 s timeout for MGCP response from MGW (default: 5 s)
+
+OsmoBSC(config-net)# # specifically test legacy timers that are moved to X timers
+OsmoBSC(config-net)# timer T993111
+% Legacy: timer T993111 is now X3111
+X3111 = 4 s Wait time after lchan was released in error (should be T3111 + 2s) (default: 4 s)
+OsmoBSC(config-net)# timer T993111 1
+% Legacy: timer T993111 is now X3111
+OsmoBSC(config-net)# timer T993111
+% Legacy: timer T993111 is now X3111
+X3111 = 1 s Wait time after lchan was released in error (should be T3111 + 2s) (default: 4 s)
+OsmoBSC(config-net)# timer T993111 default
+% Legacy: timer T993111 is now X3111
+OsmoBSC(config-net)# timer T993111
+% Legacy: timer T993111 is now X3111
+X3111 = 4 s Wait time after lchan was released in error (should be T3111 + 2s) (default: 4 s)
+
+OsmoBSC(config-net)# timer T993210
+% Legacy: timer T993210 is now X3210
+X3210 = 20 s After L3 Complete, wait for MSC to confirm (default: 20 s)
+OsmoBSC(config-net)# timer T993210 2
+% Legacy: timer T993210 is now X3210
+OsmoBSC(config-net)# timer T993210
+% Legacy: timer T993210 is now X3210
+X3210 = 2 s After L3 Complete, wait for MSC to confirm (default: 20 s)
+OsmoBSC(config-net)# timer T993210 default
+% Legacy: timer T993210 is now X3210
+OsmoBSC(config-net)# timer T993210
+% Legacy: timer T993210 is now X3210
+X3210 = 20 s After L3 Complete, wait for MSC to confirm (default: 20 s)
+
+OsmoBSC(config-net)# timer T999
+% Legacy: timer T999 is now X4
+X4 = 60 s After Clear Request, wait for MSC to Clear Command (sanity) (default: 60 s)
+OsmoBSC(config-net)# timer T999 3
+% Legacy: timer T999 is now X4
+OsmoBSC(config-net)# timer T999
+% Legacy: timer T999 is now X4
+X4 = 3 s After Clear Request, wait for MSC to Clear Command (sanity) (default: 60 s)
+OsmoBSC(config-net)# timer T999 default
+% Legacy: timer T999 is now X4
+OsmoBSC(config-net)# timer T999
+% Legacy: timer T999 is now X4
+X4 = 60 s After Clear Request, wait for MSC to Clear Command (sanity) (default: 60 s)