Change in osmo-bsc[master]: move BTS level stats and counters to bsc_stats.[hc]

neels gerrit-no-reply at lists.osmocom.org
Sun Aug 29 13:53:43 UTC 2021


neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/25275 )


Change subject: move BTS level stats and counters to bsc_stats.[hc]
......................................................................

move BTS level stats and counters to bsc_stats.[hc]

After adding bsc_stats.c, I figured it would make sense to also move the
BTS level statistics definitions to this file, so that we have one place
to find statistics for any reporting level.

Related: SYS#5542
Change-Id: I58c5c1f8a5a09e9942aa6d1bdfe7f9766773963c
---
M include/osmocom/bsc/bsc_stats.h
M include/osmocom/bsc/bts.h
M src/osmo-bsc/abis_rsl.c
M src/osmo-bsc/bsc_stats.c
M src/osmo-bsc/bsc_vty.c
M src/osmo-bsc/bts.c
M src/osmo-bsc/chan_alloc.c
M src/osmo-bsc/lchan_fsm.c
M src/osmo-bsc/osmo_bsc_filter.c
M src/osmo-bsc/timeslot_fsm.c
10 files changed, 678 insertions(+), 670 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/75/25275/1

diff --git a/include/osmocom/bsc/bsc_stats.h b/include/osmocom/bsc/bsc_stats.h
index 4250079..8d2f77f 100644
--- a/include/osmocom/bsc/bsc_stats.h
+++ b/include/osmocom/bsc/bsc_stats.h
@@ -97,7 +97,7 @@
 	BSC_STAT_NUM_MSC_TOTAL,
 };
 
-/* BTS counter index if a BTS could not be found
+/* BTS counter index if a BTS could not be found, for both rate_ctr and stat_item.
  * 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)
@@ -105,3 +105,167 @@
 extern const struct osmo_stat_item_group_desc bsc_statg_desc;
 
 void bsc_update_connection_stats(struct gsm_network *net);
+
+/* per BTS rate counters */
+enum bts_counter_id {
+	BTS_CTR_CHREQ_TOTAL,
+	BTS_CTR_CHREQ_ATTEMPTED_EMERG,
+	BTS_CTR_CHREQ_ATTEMPTED_CALL,
+	BTS_CTR_CHREQ_ATTEMPTED_LOCATION_UPD,
+	BTS_CTR_CHREQ_ATTEMPTED_PAG,
+	BTS_CTR_CHREQ_ATTEMPTED_PDCH,
+	BTS_CTR_CHREQ_ATTEMPTED_OTHER,
+	BTS_CTR_CHREQ_ATTEMPTED_UNKNOWN,
+	BTS_CTR_CHREQ_SUCCESSFUL,
+	BTS_CTR_CHREQ_NO_CHANNEL,
+	BTS_CTR_CHREQ_MAX_DELAY_EXCEEDED,
+	BTS_CTR_CHAN_RF_FAIL,
+	BTS_CTR_CHAN_RF_FAIL_TCH,
+	BTS_CTR_CHAN_RF_FAIL_SDCCH,
+	BTS_CTR_CHAN_RLL_ERR,
+	BTS_CTR_BTS_OML_FAIL,
+	BTS_CTR_BTS_RSL_FAIL,
+	BTS_CTR_CODEC_AMR_F,
+	BTS_CTR_CODEC_AMR_H,
+	BTS_CTR_CODEC_EFR,
+	BTS_CTR_CODEC_V1_FR,
+	BTS_CTR_CODEC_V1_HR,
+	BTS_CTR_PAGING_ATTEMPTED,
+	BTS_CTR_PAGING_ALREADY,
+	BTS_CTR_PAGING_RESPONDED,
+	BTS_CTR_PAGING_EXPIRED,
+	BTS_CTR_PAGING_NO_ACTIVE_PAGING,
+	BTS_CTR_PAGING_MSC_FLUSH,
+	BTS_CTR_CHAN_ACT_TOTAL,
+	BTS_CTR_CHAN_ACT_SDCCH,
+	BTS_CTR_CHAN_ACT_TCH,
+	BTS_CTR_CHAN_ACT_NACK,
+	BTS_CTR_RSL_UNKNOWN,
+	BTS_CTR_RSL_IPA_NACK,
+	BTS_CTR_RSL_DELETE_IND,
+	BTS_CTR_MODE_MODIFY_NACK,
+	BTS_CTR_LCHAN_BORKEN_FROM_UNUSED,
+	BTS_CTR_LCHAN_BORKEN_FROM_WAIT_ACTIV_ACK,
+	BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RF_RELEASE_ACK,
+	BTS_CTR_LCHAN_BORKEN_FROM_BORKEN,
+	BTS_CTR_LCHAN_BORKEN_FROM_UNKNOWN,
+	BTS_CTR_LCHAN_BORKEN_EV_CHAN_ACTIV_ACK,
+	BTS_CTR_LCHAN_BORKEN_EV_CHAN_ACTIV_NACK,
+	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_EV_TS_ERROR,
+	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,
+	BTS_CTR_TS_BORKEN_FROM_PDCH,
+	BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_DEACT,
+	BTS_CTR_TS_BORKEN_FROM_IN_USE,
+	BTS_CTR_TS_BORKEN_FROM_BORKEN,
+	BTS_CTR_TS_BORKEN_FROM_UNKNOWN,
+	BTS_CTR_TS_BORKEN_EV_PDCH_ACT_ACK_NACK,
+	BTS_CTR_TS_BORKEN_EV_PDCH_DEACT_ACK_NACK,
+	BTS_CTR_TS_BORKEN_EV_TEARDOWN,
+	BTS_CTR_ASSIGNMENT_ATTEMPTED,
+	BTS_CTR_ASSIGNMENT_ATTEMPTED_SIGN,
+	BTS_CTR_ASSIGNMENT_ATTEMPTED_SPEECH,
+	BTS_CTR_ASSIGNMENT_COMPLETED,
+	BTS_CTR_ASSIGNMENT_COMPLETED_SIGN,
+	BTS_CTR_ASSIGNMENT_COMPLETED_SPEECH,
+	BTS_CTR_ASSIGNMENT_STOPPED,
+	BTS_CTR_ASSIGNMENT_STOPPED_SIGN,
+	BTS_CTR_ASSIGNMENT_STOPPED_SPEECH,
+	BTS_CTR_ASSIGNMENT_NO_CHANNEL,
+	BTS_CTR_ASSIGNMENT_NO_CHANNEL_SIGN,
+	BTS_CTR_ASSIGNMENT_NO_CHANNEL_SPEECH,
+	BTS_CTR_ASSIGNMENT_TIMEOUT,
+	BTS_CTR_ASSIGNMENT_TIMEOUT_SIGN,
+	BTS_CTR_ASSIGNMENT_TIMEOUT_SPEECH,
+	BTS_CTR_ASSIGNMENT_FAILED,
+	BTS_CTR_ASSIGNMENT_FAILED_SIGN,
+	BTS_CTR_ASSIGNMENT_FAILED_SPEECH,
+	BTS_CTR_ASSIGNMENT_ERROR,
+	BTS_CTR_ASSIGNMENT_ERROR_SIGN,
+	BTS_CTR_ASSIGNMENT_ERROR_SPEECH,
+	BTS_CTR_LOCATION_UPDATE_ACCEPT,
+	BTS_CTR_LOCATION_UPDATE_REJECT,
+	BTS_CTR_LOCATION_UPDATE_DETACH,
+	BTS_CTR_LOCATION_UPDATE_UNKNOWN,
+	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,
+	BTS_CTR_SRVCC_ATTEMPTED,
+	BTS_CTR_SRVCC_COMPLETED,
+	BTS_CTR_SRVCC_STOPPED,
+	BTS_CTR_SRVCC_NO_CHANNEL,
+	BTS_CTR_SRVCC_TIMEOUT,
+	BTS_CTR_SRVCC_FAILED,
+	BTS_CTR_SRVCC_ERROR,
+};
+
+extern const struct rate_ctr_desc bts_ctr_description[];
+extern const struct rate_ctr_group_desc bts_ctrg_desc;
+
+/* per BTS stat items */
+enum {
+	BTS_STAT_UPTIME_SECONDS,
+	BTS_STAT_CHAN_LOAD_AVERAGE,
+	BTS_STAT_CHAN_CCCH_SDCCH4_USED,
+	BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL,
+	BTS_STAT_CHAN_TCH_F_USED,
+	BTS_STAT_CHAN_TCH_F_TOTAL,
+	BTS_STAT_CHAN_TCH_H_USED,
+	BTS_STAT_CHAN_TCH_H_TOTAL,
+	BTS_STAT_CHAN_SDCCH8_USED,
+	BTS_STAT_CHAN_SDCCH8_TOTAL,
+	BTS_STAT_CHAN_TCH_F_PDCH_USED,
+	BTS_STAT_CHAN_TCH_F_PDCH_TOTAL,
+	BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED,
+	BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL,
+	BTS_STAT_CHAN_SDCCH8_CBCH_USED,
+	BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL,
+	BTS_STAT_CHAN_OSMO_DYN_USED,
+	BTS_STAT_CHAN_OSMO_DYN_TOTAL,
+	BTS_STAT_T3122,
+	BTS_STAT_RACH_BUSY,
+	BTS_STAT_RACH_ACCESS,
+	BTS_STAT_OML_CONNECTED,
+	BTS_STAT_RSL_CONNECTED,
+	BTS_STAT_LCHAN_BORKEN,
+	BTS_STAT_TS_BORKEN,
+};
+
+extern const struct osmo_stat_item_group_desc bts_statg_desc;
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h
index 291ec10..841c92e 100644
--- a/include/osmocom/bsc/bts.h
+++ b/include/osmocom/bsc/bts.h
@@ -17,169 +17,6 @@
 #include "osmocom/bsc/bts_sm.h"
 #include "osmocom/bsc/abis_om2000.h"
 
-enum bts_counter_id {
-	BTS_CTR_CHREQ_TOTAL,
-	BTS_CTR_CHREQ_ATTEMPTED_EMERG,
-	BTS_CTR_CHREQ_ATTEMPTED_CALL,
-	BTS_CTR_CHREQ_ATTEMPTED_LOCATION_UPD,
-	BTS_CTR_CHREQ_ATTEMPTED_PAG,
-	BTS_CTR_CHREQ_ATTEMPTED_PDCH,
-	BTS_CTR_CHREQ_ATTEMPTED_OTHER,
-	BTS_CTR_CHREQ_ATTEMPTED_UNKNOWN,
-	BTS_CTR_CHREQ_SUCCESSFUL,
-	BTS_CTR_CHREQ_NO_CHANNEL,
-	BTS_CTR_CHREQ_MAX_DELAY_EXCEEDED,
-	BTS_CTR_CHAN_RF_FAIL,
-	BTS_CTR_CHAN_RF_FAIL_TCH,
-	BTS_CTR_CHAN_RF_FAIL_SDCCH,
-	BTS_CTR_CHAN_RLL_ERR,
-	BTS_CTR_BTS_OML_FAIL,
-	BTS_CTR_BTS_RSL_FAIL,
-	BTS_CTR_CODEC_AMR_F,
-	BTS_CTR_CODEC_AMR_H,
-	BTS_CTR_CODEC_EFR,
-	BTS_CTR_CODEC_V1_FR,
-	BTS_CTR_CODEC_V1_HR,
-	BTS_CTR_PAGING_ATTEMPTED,
-	BTS_CTR_PAGING_ALREADY,
-	BTS_CTR_PAGING_RESPONDED,
-	BTS_CTR_PAGING_EXPIRED,
-	BTS_CTR_PAGING_NO_ACTIVE_PAGING,
-	BTS_CTR_PAGING_MSC_FLUSH,
-	BTS_CTR_CHAN_ACT_TOTAL,
-	BTS_CTR_CHAN_ACT_SDCCH,
-	BTS_CTR_CHAN_ACT_TCH,
-	BTS_CTR_CHAN_ACT_NACK,
-	BTS_CTR_RSL_UNKNOWN,
-	BTS_CTR_RSL_IPA_NACK,
-	BTS_CTR_RSL_DELETE_IND,
-	BTS_CTR_MODE_MODIFY_NACK,
-	BTS_CTR_LCHAN_BORKEN_FROM_UNUSED,
-	BTS_CTR_LCHAN_BORKEN_FROM_WAIT_ACTIV_ACK,
-	BTS_CTR_LCHAN_BORKEN_FROM_WAIT_RF_RELEASE_ACK,
-	BTS_CTR_LCHAN_BORKEN_FROM_BORKEN,
-	BTS_CTR_LCHAN_BORKEN_FROM_UNKNOWN,
-	BTS_CTR_LCHAN_BORKEN_EV_CHAN_ACTIV_ACK,
-	BTS_CTR_LCHAN_BORKEN_EV_CHAN_ACTIV_NACK,
-	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_EV_TS_ERROR,
-	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,
-	BTS_CTR_TS_BORKEN_FROM_PDCH,
-	BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_DEACT,
-	BTS_CTR_TS_BORKEN_FROM_IN_USE,
-	BTS_CTR_TS_BORKEN_FROM_BORKEN,
-	BTS_CTR_TS_BORKEN_FROM_UNKNOWN,
-	BTS_CTR_TS_BORKEN_EV_PDCH_ACT_ACK_NACK,
-	BTS_CTR_TS_BORKEN_EV_PDCH_DEACT_ACK_NACK,
-	BTS_CTR_TS_BORKEN_EV_TEARDOWN,
-	BTS_CTR_ASSIGNMENT_ATTEMPTED,
-	BTS_CTR_ASSIGNMENT_ATTEMPTED_SIGN,
-	BTS_CTR_ASSIGNMENT_ATTEMPTED_SPEECH,
-	BTS_CTR_ASSIGNMENT_COMPLETED,
-	BTS_CTR_ASSIGNMENT_COMPLETED_SIGN,
-	BTS_CTR_ASSIGNMENT_COMPLETED_SPEECH,
-	BTS_CTR_ASSIGNMENT_STOPPED,
-	BTS_CTR_ASSIGNMENT_STOPPED_SIGN,
-	BTS_CTR_ASSIGNMENT_STOPPED_SPEECH,
-	BTS_CTR_ASSIGNMENT_NO_CHANNEL,
-	BTS_CTR_ASSIGNMENT_NO_CHANNEL_SIGN,
-	BTS_CTR_ASSIGNMENT_NO_CHANNEL_SPEECH,
-	BTS_CTR_ASSIGNMENT_TIMEOUT,
-	BTS_CTR_ASSIGNMENT_TIMEOUT_SIGN,
-	BTS_CTR_ASSIGNMENT_TIMEOUT_SPEECH,
-	BTS_CTR_ASSIGNMENT_FAILED,
-	BTS_CTR_ASSIGNMENT_FAILED_SIGN,
-	BTS_CTR_ASSIGNMENT_FAILED_SPEECH,
-	BTS_CTR_ASSIGNMENT_ERROR,
-	BTS_CTR_ASSIGNMENT_ERROR_SIGN,
-	BTS_CTR_ASSIGNMENT_ERROR_SPEECH,
-	BTS_CTR_LOCATION_UPDATE_ACCEPT,
-	BTS_CTR_LOCATION_UPDATE_REJECT,
-	BTS_CTR_LOCATION_UPDATE_DETACH,
-	BTS_CTR_LOCATION_UPDATE_UNKNOWN,
-	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,
-	BTS_CTR_SRVCC_ATTEMPTED,
-	BTS_CTR_SRVCC_COMPLETED,
-	BTS_CTR_SRVCC_STOPPED,
-	BTS_CTR_SRVCC_NO_CHANNEL,
-	BTS_CTR_SRVCC_TIMEOUT,
-	BTS_CTR_SRVCC_FAILED,
-	BTS_CTR_SRVCC_ERROR,
-};
-
-extern const struct rate_ctr_desc bts_ctr_description[];
-extern const struct rate_ctr_group_desc bts_ctrg_desc;
-
-enum {
-	BTS_STAT_UPTIME_SECONDS,
-	BTS_STAT_CHAN_LOAD_AVERAGE,
-	BTS_STAT_CHAN_CCCH_SDCCH4_USED,
-	BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL,
-	BTS_STAT_CHAN_TCH_F_USED,
-	BTS_STAT_CHAN_TCH_F_TOTAL,
-	BTS_STAT_CHAN_TCH_H_USED,
-	BTS_STAT_CHAN_TCH_H_TOTAL,
-	BTS_STAT_CHAN_SDCCH8_USED,
-	BTS_STAT_CHAN_SDCCH8_TOTAL,
-	BTS_STAT_CHAN_TCH_F_PDCH_USED,
-	BTS_STAT_CHAN_TCH_F_PDCH_TOTAL,
-	BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED,
-	BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL,
-	BTS_STAT_CHAN_SDCCH8_CBCH_USED,
-	BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL,
-	BTS_STAT_CHAN_OSMO_DYN_USED,
-	BTS_STAT_CHAN_OSMO_DYN_TOTAL,
-	BTS_STAT_T3122,
-	BTS_STAT_RACH_BUSY,
-	BTS_STAT_RACH_ACCESS,
-	BTS_STAT_OML_CONNECTED,
-	BTS_STAT_RSL_CONNECTED,
-	BTS_STAT_LCHAN_BORKEN,
-	BTS_STAT_TS_BORKEN,
-};
-
-extern const struct osmo_stat_item_desc bts_stat_desc[];
-extern const struct osmo_stat_item_group_desc bts_statg_desc;
-
 enum gsm_bts_type {
 	GSM_BTS_TYPE_UNKNOWN,
 	GSM_BTS_TYPE_BS11,
diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c
index 26231ac..879e5b4 100644
--- a/src/osmo-bsc/abis_rsl.c
+++ b/src/osmo-bsc/abis_rsl.c
@@ -55,6 +55,7 @@
 #include <osmocom/bsc/handover_fsm.h>
 #include <osmocom/bsc/smscb.h>
 #include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/bsc_stats.h>
 
 static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
 			      struct gsm_meas_rep *resp)
diff --git a/src/osmo-bsc/bsc_stats.c b/src/osmo-bsc/bsc_stats.c
index f33e6c8..e12426a 100644
--- a/src/osmo-bsc/bsc_stats.c
+++ b/src/osmo-bsc/bsc_stats.c
@@ -181,3 +181,509 @@
 			   trx_rsl_connected_total);
 	osmo_stat_item_set(osmo_stat_item_group_get_item(net->bsc_statg, BSC_STAT_NUM_TRX_TOTAL), num_trx_total);
 }
+
+const struct rate_ctr_desc bts_ctr_description[] = {
+	[BTS_CTR_CHREQ_TOTAL] = \
+		{ "chreq:total",
+		  "Received channel requests" },
+	[BTS_CTR_CHREQ_ATTEMPTED_EMERG] = \
+		{ "chreq:attempted_emerg",
+		  "Received channel requests EMERG" },
+	[BTS_CTR_CHREQ_ATTEMPTED_CALL] = \
+		{ "chreq:attempted_call",
+		  "Received channel requests CALL" },
+	[BTS_CTR_CHREQ_ATTEMPTED_LOCATION_UPD] = \
+		{ "chreq:attempted_location_upd",
+		  "Received channel requests LOCATION_UPD" },
+	[BTS_CTR_CHREQ_ATTEMPTED_PAG] = \
+		{ "chreq:attempted_pag",
+		  "Received channel requests PAG" },
+	[BTS_CTR_CHREQ_ATTEMPTED_PDCH] = \
+		{ "chreq:attempted_pdch",
+		  "Received channel requests PDCH" },
+	[BTS_CTR_CHREQ_ATTEMPTED_OTHER] = \
+		{ "chreq:attempted_other",
+		  "Received channel requests OTHER" },
+	[BTS_CTR_CHREQ_ATTEMPTED_UNKNOWN] = \
+		{ "chreq:attempted_unknown",
+		  "Received channel requests UNKNOWN" },
+	[BTS_CTR_CHREQ_SUCCESSFUL] = \
+		{ "chreq:successful",
+		  "Successful channel requests (immediate assign sent)" },
+	[BTS_CTR_CHREQ_NO_CHANNEL] = \
+		{ "chreq:no_channel",
+		  "Sent to MS no channel available" },
+	[BTS_CTR_CHREQ_MAX_DELAY_EXCEEDED] = \
+		{ "chreq:max_delay_exceeded",
+		  "Received channel requests with greater than permitted access delay" },
+	[BTS_CTR_CHAN_RF_FAIL] = \
+		{ "chan:rf_fail",
+		  "Received a RF failure indication from BTS" },
+	[BTS_CTR_CHAN_RF_FAIL_TCH] = \
+		{ "chan:rf_fail_tch",
+		  "Received a RF failure indication from BTS on a TCH channel" },
+	[BTS_CTR_CHAN_RF_FAIL_SDCCH] = \
+		{ "chan:rf_fail_sdcch",
+		  "Received a RF failure indication from BTS on an SDCCH channel" },
+	[BTS_CTR_CHAN_RLL_ERR] = \
+		{ "chan:rll_err",
+		  "Received a RLL failure with T200 cause from BTS" },
+	[BTS_CTR_BTS_OML_FAIL] = \
+		{ "oml_fail",
+		  "Received a TEI down on a OML link" },
+	[BTS_CTR_BTS_RSL_FAIL] = \
+		{ "rsl_fail",
+		  "Received a TEI down on a OML link" },
+	[BTS_CTR_CODEC_AMR_F] = \
+		{ "codec:amr_f",
+		  "Count the usage of AMR/F codec by channel mode requested" },
+	[BTS_CTR_CODEC_AMR_H] = \
+		{ "codec:amr_h",
+		  "Count the usage of AMR/H codec by channel mode requested" },
+	[BTS_CTR_CODEC_EFR] = \
+		{ "codec:efr",
+		  "Count the usage of EFR codec by channel mode requested" },
+	[BTS_CTR_CODEC_V1_FR] = \
+		{ "codec:fr",
+		  "Count the usage of FR codec by channel mode requested" },
+	[BTS_CTR_CODEC_V1_HR] = \
+		{ "codec:hr",
+		  "Count the usage of HR codec by channel mode requested" },
+	[BTS_CTR_PAGING_ATTEMPTED] = \
+		{ "paging:attempted",
+		  "Paging attempts for a subscriber" },
+	[BTS_CTR_PAGING_ALREADY] = \
+		{ "paging:already",
+		  "Paging attempts ignored as subscriber was already being paged" },
+	[BTS_CTR_PAGING_RESPONDED] = \
+		{ "paging:responded",
+		  "Paging attempts with successful paging response" },
+	[BTS_CTR_PAGING_EXPIRED] = \
+		{ "paging:expired",
+		  "Paging Request expired because of timeout T3113" },
+	[BTS_CTR_PAGING_NO_ACTIVE_PAGING] = \
+		{ "paging:no_active_paging",
+		  "Paging response without an active paging request (arrived after paging expiration?)" },
+	[BTS_CTR_PAGING_MSC_FLUSH] = \
+		{ "paging:msc_flush",
+		  "Paging flushed due to MSC Reset BSSMAP message" },
+	[BTS_CTR_CHAN_ACT_TOTAL] = \
+		{ "chan_act:total",
+		  "Total number of Channel Activations" },
+	[BTS_CTR_CHAN_ACT_SDCCH] = \
+		{ "chan_act:sdcch",
+		  "Number of SDCCH Channel Activations" },
+	[BTS_CTR_CHAN_ACT_TCH] = \
+		{ "chan_act:tch",
+		  "Number of TCH Channel Activations" },
+	[BTS_CTR_CHAN_ACT_NACK] = \
+		{ "chan_act:nack",
+		  "Number of Channel Activations that the BTS NACKed" },
+	[BTS_CTR_RSL_UNKNOWN] = \
+		{ "rsl:unknown",
+		  "Number of unknown/unsupported RSL messages received from BTS" },
+	[BTS_CTR_RSL_IPA_NACK] = \
+		{ "rsl:ipa_nack",
+		  "Number of IPA (RTP/dyn-PDCH) related NACKs received from BTS" },
+	[BTS_CTR_RSL_DELETE_IND] = \
+		{ "rsl:delete_ind",
+		  "Number of RSL DELETE INDICATION (DL CCCH overload)" },
+	[BTS_CTR_MODE_MODIFY_NACK] = \
+		{ "chan:mode_modify_nack",
+		  "Number of Channel Mode Modify NACKs received from BTS" },
+
+	/* lchan/TS BORKEN state counters */
+	[BTS_CTR_LCHAN_BORKEN_FROM_UNUSED] = \
+		{ "lchan_borken:from_state:unused",
+		  "Transitions from lchan UNUSED state to BORKEN state" },
+	[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" },
+	[BTS_CTR_LCHAN_BORKEN_EV_RF_CHAN_REL_ACK] = \
+		{ "lchan_borken:event:rf_chan_rel_ack",
+		  "RF_CHAN_REL_ACK received in the lchan BORKEN state" },
+	[BTS_CTR_LCHAN_BORKEN_EV_VTY] = \
+		{ "lchan_borken:event:vty",
+		  "VTY commands received in the lchan BORKEN state" },
+	[BTS_CTR_LCHAN_BORKEN_EV_TEARDOWN] = \
+		{ "lchan_borken:event:teardown",
+		  "lchan in a BORKEN state is shutting down (BTS disconnected?)" },
+	[BTS_CTR_LCHAN_BORKEN_EV_TS_ERROR] = \
+		{ "lchan_borken:event:ts_error",
+		  "LCHAN_EV_TS_ERROR received in a BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_NOT_INITIALIZED] = \
+		{ "ts_borken:from_state:not_initialized",
+		  "Transitions from TS NOT_INITIALIZED state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_UNUSED] = \
+		{ "ts_borken:from_state:unused",
+		  "Transitions from TS UNUSED state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_ACT] = \
+		{ "ts_borken:from_state:wait_pdch_act",
+		  "Transitions from TS WAIT_PDCH_ACT state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_PDCH] = \
+		{ "ts_borken:from_state:pdch",
+		  "Transitions from TS PDCH state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_DEACT] = \
+		{ "ts_borken:from_state:wait_pdch_deact",
+		  "Transitions from TS WAIT_PDCH_DEACT state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_IN_USE] = \
+		{ "ts_borken:from_state:in_use",
+		  "Transitions from TS IN_USE state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_BORKEN] = \
+		{ "ts_borken:from_state:borken",
+		  "Transitions from TS BORKEN state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_FROM_UNKNOWN] = \
+		{ "ts_borken:from_state:unknown",
+		  "Transitions from an unknown TS state to BORKEN state" },
+	[BTS_CTR_TS_BORKEN_EV_PDCH_ACT_ACK_NACK] = \
+		{ "ts_borken:event:pdch_act_ack_nack",
+		  "PDCH_ACT_ACK/NACK received in the TS BORKEN state" },
+	[BTS_CTR_TS_BORKEN_EV_PDCH_DEACT_ACK_NACK] = \
+		{ "ts_borken:event:pdch_deact_ack_nack",
+		  "PDCH_DEACT_ACK/NACK received in the TS BORKEN state" },
+	[BTS_CTR_TS_BORKEN_EV_TEARDOWN] = \
+		{ "ts_borken:event:teardown",
+		  "TS in a BORKEN state is shutting down (BTS disconnected?)" },
+	[BTS_CTR_ASSIGNMENT_ATTEMPTED] = \
+		{ "assignment:attempted",
+		  "Assignment attempts" },
+	[BTS_CTR_ASSIGNMENT_ATTEMPTED_SIGN] = \
+		{ "assignment:attempted_sign",
+		  "Assignment of signaling lchan attempts" },
+	[BTS_CTR_ASSIGNMENT_ATTEMPTED_SPEECH] = \
+		{ "assignment:attempted_speech",
+		  "Assignment of speech lchan attempts" },
+	[BTS_CTR_ASSIGNMENT_COMPLETED] = \
+		{ "assignment:completed",
+		  "Assignment completed" },
+	[BTS_CTR_ASSIGNMENT_COMPLETED_SIGN] = \
+		{ "assignment:completed_sign",
+		  "Assignment of signaling lchan completed" },
+	[BTS_CTR_ASSIGNMENT_COMPLETED_SPEECH] = \
+		{ "assignment:completed_speech",
+		  "Assignment if speech lchan completed" },
+	[BTS_CTR_ASSIGNMENT_STOPPED] = \
+		{ "assignment:stopped",
+		  "Connection ended during Assignment" },
+	[BTS_CTR_ASSIGNMENT_STOPPED_SIGN] = \
+		{ "assignment:stopped_sign",
+		  "Connection ended during signaling lchan Assignment" },
+	[BTS_CTR_ASSIGNMENT_STOPPED_SPEECH] = \
+		{ "assignment:stopped_speech",
+		  "Connection ended during speech lchan Assignment" },
+	[BTS_CTR_ASSIGNMENT_NO_CHANNEL] = \
+		{ "assignment:no_channel",
+		  "Failure to allocate lchan for Assignment" },
+	[BTS_CTR_ASSIGNMENT_NO_CHANNEL_SIGN] = \
+		{ "assignment:no_channel_sign",
+		  "Failure to allocate signaling lchan for Assignment" },
+	[BTS_CTR_ASSIGNMENT_NO_CHANNEL_SPEECH] = \
+		{ "assignment:no_channel_speech",
+		  "Failure to allocate speech lchan for Assignment" },
+	[BTS_CTR_ASSIGNMENT_TIMEOUT] = \
+		{ "assignment:timeout",
+		  "Assignment timed out" },
+	[BTS_CTR_ASSIGNMENT_TIMEOUT_SIGN] = \
+		{ "assignment:timeout_sign",
+		  "Assignment of signaling lchan timed out" },
+	[BTS_CTR_ASSIGNMENT_TIMEOUT_SPEECH] = \
+		{ "assignment:timeout_speech",
+		  "Assignment of speech lchan timed out" },
+	[BTS_CTR_ASSIGNMENT_FAILED] = \
+		{ "assignment:failed",
+		  "Received Assignment Failure message" },
+	[BTS_CTR_ASSIGNMENT_FAILED_SIGN] = \
+		{ "assignment:failed_sign",
+		  "Received Assignment Failure message on signaling lchan" },
+	[BTS_CTR_ASSIGNMENT_FAILED_SPEECH] = \
+		{ "assignment:failed_speech",
+		  "Received Assignment Failure message on speech lchan" },
+	[BTS_CTR_ASSIGNMENT_ERROR] = \
+		{ "assignment:error",
+		  "Assignment failed for other reason" },
+	[BTS_CTR_ASSIGNMENT_ERROR_SIGN] = \
+		{ "assignment:error_sign",
+		  "Assignment of signaling lchan failed for other reason" },
+	[BTS_CTR_ASSIGNMENT_ERROR_SPEECH] = \
+		{ "assignment:error_speech",
+		  "Assignment of speech lchan failed for other reason" },
+	[BTS_CTR_LOCATION_UPDATE_ACCEPT] = \
+		{ "location_update:accept",
+		  "Location Update Accept" },
+	[BTS_CTR_LOCATION_UPDATE_REJECT] = \
+		{ "location_update:reject",
+		  "Location Update Reject" },
+	[BTS_CTR_LOCATION_UPDATE_DETACH] = \
+		{ "location_update:detach",
+		  "Location Update Detach" },
+	[BTS_CTR_LOCATION_UPDATE_UNKNOWN] = \
+		{ "location_update:unknown",
+		  "Location Update UNKNOWN" },
+	[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" },
+
+	[BTS_CTR_SRVCC_ATTEMPTED] = \
+		{ "srvcc:attempted",
+		  "Intra-BSC handover attempts" },
+	[BTS_CTR_SRVCC_COMPLETED] = \
+		{ "srvcc:completed",
+		  "Intra-BSC handover completed" },
+	[BTS_CTR_SRVCC_STOPPED] = \
+		{ "srvcc:stopped",
+		  "Connection ended during HO" },
+	[BTS_CTR_SRVCC_NO_CHANNEL] = \
+		{ "srvcc:no_channel",
+		  "Failure to allocate lchan for HO" },
+	[BTS_CTR_SRVCC_TIMEOUT] = \
+		{ "srvcc:timeout",
+		   "Handover timed out" },
+	[BTS_CTR_SRVCC_FAILED] = \
+		{ "srvcc:failed",
+		  "Received Handover Fail messages" },
+	[BTS_CTR_SRVCC_ERROR] = \
+		{ "srvcc:error",
+		  "Re-assignment failed for other reason" },
+};
+
+const struct rate_ctr_group_desc bts_ctrg_desc = {
+	"bts",
+	"base transceiver station",
+	OSMO_STATS_CLASS_GLOBAL,
+	ARRAY_SIZE(bts_ctr_description),
+	bts_ctr_description,
+};
+
+const struct osmo_stat_item_desc bts_stat_desc[] = {
+	[BTS_STAT_UPTIME_SECONDS] = \
+		{ "uptime:seconds",
+		  "Seconds of uptime",
+		  "s", 60, 0 },
+	[BTS_STAT_CHAN_LOAD_AVERAGE] = \
+		{ "chanloadavg",
+		  "Channel load average",
+		  "%", 60, 0 },
+	[BTS_STAT_CHAN_CCCH_SDCCH4_USED] = \
+		{ "chan_ccch_sdcch4:used",
+		  "Number of CCCH+SDCCH4 channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL] = \
+		{ "chan_ccch_sdcch4:total",
+		  "Number of CCCH+SDCCH4 channels total",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_TCH_F_USED] = \
+		{ "chan_tch_f:used",
+		  "Number of TCH/F channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_TCH_F_TOTAL] = \
+		{ "chan_tch_f:total",
+		  "Number of TCH/F channels total",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_TCH_H_USED] = \
+		{ "chan_tch_h:used",
+		  "Number of TCH/H channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_TCH_H_TOTAL] = \
+		{ "chan_tch_h:total",
+		  "Number of TCH/H channels total",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_SDCCH8_USED] = \
+		{ "chan_sdcch8:used",
+		  "Number of SDCCH8 channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_SDCCH8_TOTAL] = \
+		{ "chan_sdcch8:total",
+		  "Number of SDCCH8 channels total",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_TCH_F_PDCH_USED] = \
+		{ "chan_tch_f_pdch:used",
+		  "Number of TCH/F_PDCH channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_TCH_F_PDCH_TOTAL] = \
+		{ "chan_tch_f_pdch:total",
+		  "Number of TCH/F_PDCH channels total",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED] = \
+		{ "chan_ccch_sdcch4_cbch:used",
+		  "Number of CCCH+SDCCH4+CBCH channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL] = \
+		{ "chan_ccch_sdcch4_cbch:total",
+		  "Number of CCCH+SDCCH4+CBCH channels total",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_SDCCH8_CBCH_USED] = \
+		{ "chan_sdcch8_cbch:used",
+		  "Number of SDCCH8+CBCH channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL] = \
+		{ "chan_sdcch8_cbch:total",
+		  "Number of SDCCH8+CBCH channels total",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_OSMO_DYN_USED] = \
+		{ "chan_osmo_dyn:used",
+		  "Number of TCH/F_TCH/H_SDCCH8_PDCH channels used",
+		  "", 60, 0 },
+	[BTS_STAT_CHAN_OSMO_DYN_TOTAL] = \
+		{ "chan_osmo_dyn:total",
+		  "Number of TCH/F_TCH/H_SDCCH8_PDCH channels total",
+		  "", 60, 0 },
+	[BTS_STAT_T3122] = \
+		{ "T3122",
+		  "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator",
+		  "s", 60, GSM_T3122_DEFAULT },
+	[BTS_STAT_RACH_BUSY] = \
+		{ "rach_busy",
+		  "RACH slots with signal above threshold",
+		  "%", 60, 0 },
+	[BTS_STAT_RACH_ACCESS] = \
+		{ "rach_access",
+		  "RACH slots with access bursts in them",
+		  "%", 60, 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 },
+};
+
+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,
+};
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 5ce1d69..cb844e0 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -63,6 +63,7 @@
 #include <osmocom/bsc/bsc_subscr_conn_fsm.h>
 #include <osmocom/bsc/assignment_fsm.h>
 #include <osmocom/bsc/bssmap_reset.h>
+#include <osmocom/bsc/bsc_stats.h>
 
 #include <inttypes.h>
 
diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c
index c0d6634..d647a70 100644
--- a/src/osmo-bsc/bts.c
+++ b/src/osmo-bsc/bts.c
@@ -24,6 +24,7 @@
 #include <osmocom/bsc/bts.h>
 #include <osmocom/bsc/debug.h>
 #include <osmocom/bsc/nm_common_fsm.h>
+#include <osmocom/bsc/bsc_stats.h>
 
 const struct value_string bts_attribute_names[] = {
 	OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
@@ -816,509 +817,3 @@
 	osmo_stat_item_set(osmo_stat_item_group_get_item(bts->bts_statg, BTS_STAT_CHAN_OSMO_DYN_USED), 0);
 	osmo_stat_item_set(osmo_stat_item_group_get_item(bts->bts_statg, BTS_STAT_CHAN_OSMO_DYN_TOTAL), 0);
 }
-
-const struct rate_ctr_desc bts_ctr_description[] = {
-	[BTS_CTR_CHREQ_TOTAL] = \
-		{ "chreq:total",
-		  "Received channel requests" },
-	[BTS_CTR_CHREQ_ATTEMPTED_EMERG] = \
-		{ "chreq:attempted_emerg",
-		  "Received channel requests EMERG" },
-	[BTS_CTR_CHREQ_ATTEMPTED_CALL] = \
-		{ "chreq:attempted_call",
-		  "Received channel requests CALL" },
-	[BTS_CTR_CHREQ_ATTEMPTED_LOCATION_UPD] = \
-		{ "chreq:attempted_location_upd",
-		  "Received channel requests LOCATION_UPD" },
-	[BTS_CTR_CHREQ_ATTEMPTED_PAG] = \
-		{ "chreq:attempted_pag",
-		  "Received channel requests PAG" },
-	[BTS_CTR_CHREQ_ATTEMPTED_PDCH] = \
-		{ "chreq:attempted_pdch",
-		  "Received channel requests PDCH" },
-	[BTS_CTR_CHREQ_ATTEMPTED_OTHER] = \
-		{ "chreq:attempted_other",
-		  "Received channel requests OTHER" },
-	[BTS_CTR_CHREQ_ATTEMPTED_UNKNOWN] = \
-		{ "chreq:attempted_unknown",
-		  "Received channel requests UNKNOWN" },
-	[BTS_CTR_CHREQ_SUCCESSFUL] = \
-		{ "chreq:successful",
-		  "Successful channel requests (immediate assign sent)" },
-	[BTS_CTR_CHREQ_NO_CHANNEL] = \
-		{ "chreq:no_channel",
-		  "Sent to MS no channel available" },
-	[BTS_CTR_CHREQ_MAX_DELAY_EXCEEDED] = \
-		{ "chreq:max_delay_exceeded",
-		  "Received channel requests with greater than permitted access delay" },
-	[BTS_CTR_CHAN_RF_FAIL] = \
-		{ "chan:rf_fail",
-		  "Received a RF failure indication from BTS" },
-	[BTS_CTR_CHAN_RF_FAIL_TCH] = \
-		{ "chan:rf_fail_tch",
-		  "Received a RF failure indication from BTS on a TCH channel" },
-	[BTS_CTR_CHAN_RF_FAIL_SDCCH] = \
-		{ "chan:rf_fail_sdcch",
-		  "Received a RF failure indication from BTS on an SDCCH channel" },
-	[BTS_CTR_CHAN_RLL_ERR] = \
-		{ "chan:rll_err",
-		  "Received a RLL failure with T200 cause from BTS" },
-	[BTS_CTR_BTS_OML_FAIL] = \
-		{ "oml_fail",
-		  "Received a TEI down on a OML link" },
-	[BTS_CTR_BTS_RSL_FAIL] = \
-		{ "rsl_fail",
-		  "Received a TEI down on a OML link" },
-	[BTS_CTR_CODEC_AMR_F] = \
-		{ "codec:amr_f",
-		  "Count the usage of AMR/F codec by channel mode requested" },
-	[BTS_CTR_CODEC_AMR_H] = \
-		{ "codec:amr_h",
-		  "Count the usage of AMR/H codec by channel mode requested" },
-	[BTS_CTR_CODEC_EFR] = \
-		{ "codec:efr",
-		  "Count the usage of EFR codec by channel mode requested" },
-	[BTS_CTR_CODEC_V1_FR] = \
-		{ "codec:fr",
-		  "Count the usage of FR codec by channel mode requested" },
-	[BTS_CTR_CODEC_V1_HR] = \
-		{ "codec:hr",
-		  "Count the usage of HR codec by channel mode requested" },
-	[BTS_CTR_PAGING_ATTEMPTED] = \
-		{ "paging:attempted",
-		  "Paging attempts for a subscriber" },
-	[BTS_CTR_PAGING_ALREADY] = \
-		{ "paging:already",
-		  "Paging attempts ignored as subscriber was already being paged" },
-	[BTS_CTR_PAGING_RESPONDED] = \
-		{ "paging:responded",
-		  "Paging attempts with successful paging response" },
-	[BTS_CTR_PAGING_EXPIRED] = \
-		{ "paging:expired",
-		  "Paging Request expired because of timeout T3113" },
-	[BTS_CTR_PAGING_NO_ACTIVE_PAGING] = \
-		{ "paging:no_active_paging",
-		  "Paging response without an active paging request (arrived after paging expiration?)" },
-	[BTS_CTR_PAGING_MSC_FLUSH] = \
-		{ "paging:msc_flush",
-		  "Paging flushed due to MSC Reset BSSMAP message" },
-	[BTS_CTR_CHAN_ACT_TOTAL] = \
-		{ "chan_act:total",
-		  "Total number of Channel Activations" },
-	[BTS_CTR_CHAN_ACT_SDCCH] = \
-		{ "chan_act:sdcch",
-		  "Number of SDCCH Channel Activations" },
-	[BTS_CTR_CHAN_ACT_TCH] = \
-		{ "chan_act:tch",
-		  "Number of TCH Channel Activations" },
-	[BTS_CTR_CHAN_ACT_NACK] = \
-		{ "chan_act:nack",
-		  "Number of Channel Activations that the BTS NACKed" },
-	[BTS_CTR_RSL_UNKNOWN] = \
-		{ "rsl:unknown",
-		  "Number of unknown/unsupported RSL messages received from BTS" },
-	[BTS_CTR_RSL_IPA_NACK] = \
-		{ "rsl:ipa_nack",
-		  "Number of IPA (RTP/dyn-PDCH) related NACKs received from BTS" },
-	[BTS_CTR_RSL_DELETE_IND] = \
-		{ "rsl:delete_ind",
-		  "Number of RSL DELETE INDICATION (DL CCCH overload)" },
-	[BTS_CTR_MODE_MODIFY_NACK] = \
-		{ "chan:mode_modify_nack",
-		  "Number of Channel Mode Modify NACKs received from BTS" },
-
-	/* lchan/TS BORKEN state counters */
-	[BTS_CTR_LCHAN_BORKEN_FROM_UNUSED] = \
-		{ "lchan_borken:from_state:unused",
-		  "Transitions from lchan UNUSED state to BORKEN state" },
-	[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" },
-	[BTS_CTR_LCHAN_BORKEN_EV_RF_CHAN_REL_ACK] = \
-		{ "lchan_borken:event:rf_chan_rel_ack",
-		  "RF_CHAN_REL_ACK received in the lchan BORKEN state" },
-	[BTS_CTR_LCHAN_BORKEN_EV_VTY] = \
-		{ "lchan_borken:event:vty",
-		  "VTY commands received in the lchan BORKEN state" },
-	[BTS_CTR_LCHAN_BORKEN_EV_TEARDOWN] = \
-		{ "lchan_borken:event:teardown",
-		  "lchan in a BORKEN state is shutting down (BTS disconnected?)" },
-	[BTS_CTR_LCHAN_BORKEN_EV_TS_ERROR] = \
-		{ "lchan_borken:event:ts_error",
-		  "LCHAN_EV_TS_ERROR received in a BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_NOT_INITIALIZED] = \
-		{ "ts_borken:from_state:not_initialized",
-		  "Transitions from TS NOT_INITIALIZED state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_UNUSED] = \
-		{ "ts_borken:from_state:unused",
-		  "Transitions from TS UNUSED state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_ACT] = \
-		{ "ts_borken:from_state:wait_pdch_act",
-		  "Transitions from TS WAIT_PDCH_ACT state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_PDCH] = \
-		{ "ts_borken:from_state:pdch",
-		  "Transitions from TS PDCH state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_WAIT_PDCH_DEACT] = \
-		{ "ts_borken:from_state:wait_pdch_deact",
-		  "Transitions from TS WAIT_PDCH_DEACT state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_IN_USE] = \
-		{ "ts_borken:from_state:in_use",
-		  "Transitions from TS IN_USE state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_BORKEN] = \
-		{ "ts_borken:from_state:borken",
-		  "Transitions from TS BORKEN state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_FROM_UNKNOWN] = \
-		{ "ts_borken:from_state:unknown",
-		  "Transitions from an unknown TS state to BORKEN state" },
-	[BTS_CTR_TS_BORKEN_EV_PDCH_ACT_ACK_NACK] = \
-		{ "ts_borken:event:pdch_act_ack_nack",
-		  "PDCH_ACT_ACK/NACK received in the TS BORKEN state" },
-	[BTS_CTR_TS_BORKEN_EV_PDCH_DEACT_ACK_NACK] = \
-		{ "ts_borken:event:pdch_deact_ack_nack",
-		  "PDCH_DEACT_ACK/NACK received in the TS BORKEN state" },
-	[BTS_CTR_TS_BORKEN_EV_TEARDOWN] = \
-		{ "ts_borken:event:teardown",
-		  "TS in a BORKEN state is shutting down (BTS disconnected?)" },
-	[BTS_CTR_ASSIGNMENT_ATTEMPTED] = \
-		{ "assignment:attempted",
-		  "Assignment attempts" },
-	[BTS_CTR_ASSIGNMENT_ATTEMPTED_SIGN] = \
-		{ "assignment:attempted_sign",
-		  "Assignment of signaling lchan attempts" },
-	[BTS_CTR_ASSIGNMENT_ATTEMPTED_SPEECH] = \
-		{ "assignment:attempted_speech",
-		  "Assignment of speech lchan attempts" },
-	[BTS_CTR_ASSIGNMENT_COMPLETED] = \
-		{ "assignment:completed",
-		  "Assignment completed" },
-	[BTS_CTR_ASSIGNMENT_COMPLETED_SIGN] = \
-		{ "assignment:completed_sign",
-		  "Assignment of signaling lchan completed" },
-	[BTS_CTR_ASSIGNMENT_COMPLETED_SPEECH] = \
-		{ "assignment:completed_speech",
-		  "Assignment if speech lchan completed" },
-	[BTS_CTR_ASSIGNMENT_STOPPED] = \
-		{ "assignment:stopped",
-		  "Connection ended during Assignment" },
-	[BTS_CTR_ASSIGNMENT_STOPPED_SIGN] = \
-		{ "assignment:stopped_sign",
-		  "Connection ended during signaling lchan Assignment" },
-	[BTS_CTR_ASSIGNMENT_STOPPED_SPEECH] = \
-		{ "assignment:stopped_speech",
-		  "Connection ended during speech lchan Assignment" },
-	[BTS_CTR_ASSIGNMENT_NO_CHANNEL] = \
-		{ "assignment:no_channel",
-		  "Failure to allocate lchan for Assignment" },
-	[BTS_CTR_ASSIGNMENT_NO_CHANNEL_SIGN] = \
-		{ "assignment:no_channel_sign",
-		  "Failure to allocate signaling lchan for Assignment" },
-	[BTS_CTR_ASSIGNMENT_NO_CHANNEL_SPEECH] = \
-		{ "assignment:no_channel_speech",
-		  "Failure to allocate speech lchan for Assignment" },
-	[BTS_CTR_ASSIGNMENT_TIMEOUT] = \
-		{ "assignment:timeout",
-		  "Assignment timed out" },
-	[BTS_CTR_ASSIGNMENT_TIMEOUT_SIGN] = \
-		{ "assignment:timeout_sign",
-		  "Assignment of signaling lchan timed out" },
-	[BTS_CTR_ASSIGNMENT_TIMEOUT_SPEECH] = \
-		{ "assignment:timeout_speech",
-		  "Assignment of speech lchan timed out" },
-	[BTS_CTR_ASSIGNMENT_FAILED] = \
-		{ "assignment:failed",
-		  "Received Assignment Failure message" },
-	[BTS_CTR_ASSIGNMENT_FAILED_SIGN] = \
-		{ "assignment:failed_sign",
-		  "Received Assignment Failure message on signaling lchan" },
-	[BTS_CTR_ASSIGNMENT_FAILED_SPEECH] = \
-		{ "assignment:failed_speech",
-		  "Received Assignment Failure message on speech lchan" },
-	[BTS_CTR_ASSIGNMENT_ERROR] = \
-		{ "assignment:error",
-		  "Assignment failed for other reason" },
-	[BTS_CTR_ASSIGNMENT_ERROR_SIGN] = \
-		{ "assignment:error_sign",
-		  "Assignment of signaling lchan failed for other reason" },
-	[BTS_CTR_ASSIGNMENT_ERROR_SPEECH] = \
-		{ "assignment:error_speech",
-		  "Assignment of speech lchan failed for other reason" },
-	[BTS_CTR_LOCATION_UPDATE_ACCEPT] = \
-		{ "location_update:accept",
-		  "Location Update Accept" },
-	[BTS_CTR_LOCATION_UPDATE_REJECT] = \
-		{ "location_update:reject",
-		  "Location Update Reject" },
-	[BTS_CTR_LOCATION_UPDATE_DETACH] = \
-		{ "location_update:detach",
-		  "Location Update Detach" },
-	[BTS_CTR_LOCATION_UPDATE_UNKNOWN] = \
-		{ "location_update:unknown",
-		  "Location Update UNKNOWN" },
-	[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" },
-
-	[BTS_CTR_SRVCC_ATTEMPTED] = \
-		{ "srvcc:attempted",
-		  "Intra-BSC handover attempts" },
-	[BTS_CTR_SRVCC_COMPLETED] = \
-		{ "srvcc:completed",
-		  "Intra-BSC handover completed" },
-	[BTS_CTR_SRVCC_STOPPED] = \
-		{ "srvcc:stopped",
-		  "Connection ended during HO" },
-	[BTS_CTR_SRVCC_NO_CHANNEL] = \
-		{ "srvcc:no_channel",
-		  "Failure to allocate lchan for HO" },
-	[BTS_CTR_SRVCC_TIMEOUT] = \
-		{ "srvcc:timeout",
-		   "Handover timed out" },
-	[BTS_CTR_SRVCC_FAILED] = \
-		{ "srvcc:failed",
-		  "Received Handover Fail messages" },
-	[BTS_CTR_SRVCC_ERROR] = \
-		{ "srvcc:error",
-		  "Re-assignment failed for other reason" },
-};
-
-const struct rate_ctr_group_desc bts_ctrg_desc = {
-	"bts",
-	"base transceiver station",
-	OSMO_STATS_CLASS_GLOBAL,
-	ARRAY_SIZE(bts_ctr_description),
-	bts_ctr_description,
-};
-
-const struct osmo_stat_item_desc bts_stat_desc[] = {
-	[BTS_STAT_UPTIME_SECONDS] = \
-		{ "uptime:seconds",
-		  "Seconds of uptime",
-		  "s", 60, 0 },
-	[BTS_STAT_CHAN_LOAD_AVERAGE] = \
-		{ "chanloadavg",
-		  "Channel load average",
-		  "%", 60, 0 },
-	[BTS_STAT_CHAN_CCCH_SDCCH4_USED] = \
-		{ "chan_ccch_sdcch4:used",
-		  "Number of CCCH+SDCCH4 channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL] = \
-		{ "chan_ccch_sdcch4:total",
-		  "Number of CCCH+SDCCH4 channels total",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_TCH_F_USED] = \
-		{ "chan_tch_f:used",
-		  "Number of TCH/F channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_TCH_F_TOTAL] = \
-		{ "chan_tch_f:total",
-		  "Number of TCH/F channels total",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_TCH_H_USED] = \
-		{ "chan_tch_h:used",
-		  "Number of TCH/H channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_TCH_H_TOTAL] = \
-		{ "chan_tch_h:total",
-		  "Number of TCH/H channels total",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_SDCCH8_USED] = \
-		{ "chan_sdcch8:used",
-		  "Number of SDCCH8 channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_SDCCH8_TOTAL] = \
-		{ "chan_sdcch8:total",
-		  "Number of SDCCH8 channels total",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_TCH_F_PDCH_USED] = \
-		{ "chan_tch_f_pdch:used",
-		  "Number of TCH/F_PDCH channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_TCH_F_PDCH_TOTAL] = \
-		{ "chan_tch_f_pdch:total",
-		  "Number of TCH/F_PDCH channels total",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED] = \
-		{ "chan_ccch_sdcch4_cbch:used",
-		  "Number of CCCH+SDCCH4+CBCH channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL] = \
-		{ "chan_ccch_sdcch4_cbch:total",
-		  "Number of CCCH+SDCCH4+CBCH channels total",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_SDCCH8_CBCH_USED] = \
-		{ "chan_sdcch8_cbch:used",
-		  "Number of SDCCH8+CBCH channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL] = \
-		{ "chan_sdcch8_cbch:total",
-		  "Number of SDCCH8+CBCH channels total",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_OSMO_DYN_USED] = \
-		{ "chan_osmo_dyn:used",
-		  "Number of TCH/F_TCH/H_SDCCH8_PDCH channels used",
-		  "", 60, 0 },
-	[BTS_STAT_CHAN_OSMO_DYN_TOTAL] = \
-		{ "chan_osmo_dyn:total",
-		  "Number of TCH/F_TCH/H_SDCCH8_PDCH channels total",
-		  "", 60, 0 },
-	[BTS_STAT_T3122] = \
-		{ "T3122",
-		  "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator",
-		  "s", 60, GSM_T3122_DEFAULT },
-	[BTS_STAT_RACH_BUSY] = \
-		{ "rach_busy",
-		  "RACH slots with signal above threshold",
-		  "%", 60, 0 },
-	[BTS_STAT_RACH_ACCESS] = \
-		{ "rach_access",
-		  "RACH slots with access bursts in them",
-		  "%", 60, 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 },
-};
-
-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,
-};
diff --git a/src/osmo-bsc/chan_alloc.c b/src/osmo-bsc/chan_alloc.c
index fea4efd..ce648c3 100644
--- a/src/osmo-bsc/chan_alloc.c
+++ b/src/osmo-bsc/chan_alloc.c
@@ -35,6 +35,7 @@
 #include <osmocom/bsc/lchan_fsm.h>
 #include <osmocom/bsc/gsm_04_08_rr.h>
 #include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/bsc_stats.h>
 
 #include <osmocom/core/talloc.h>
 
diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c
index def70de..0e97869 100644
--- a/src/osmo-bsc/lchan_fsm.c
+++ b/src/osmo-bsc/lchan_fsm.c
@@ -40,6 +40,7 @@
 #include <osmocom/bsc/bsc_msc_data.h>
 #include <osmocom/bsc/codec_pref.h>
 #include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/bsc_stats.h>
 
 static struct osmo_fsm lchan_fsm;
 
diff --git a/src/osmo-bsc/osmo_bsc_filter.c b/src/osmo-bsc/osmo_bsc_filter.c
index 2b58ccf..1ee2625 100644
--- a/src/osmo-bsc/osmo_bsc_filter.c
+++ b/src/osmo-bsc/osmo_bsc_filter.c
@@ -27,6 +27,7 @@
 #include <osmocom/bsc/paging.h>
 #include <osmocom/bsc/gsm_04_08_rr.h>
 #include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/bsc_stats.h>
 
 #include <stdlib.h>
 
diff --git a/src/osmo-bsc/timeslot_fsm.c b/src/osmo-bsc/timeslot_fsm.c
index adca31d..5a00784 100644
--- a/src/osmo-bsc/timeslot_fsm.c
+++ b/src/osmo-bsc/timeslot_fsm.c
@@ -29,6 +29,7 @@
 #include <osmocom/bsc/abis_rsl.h>
 #include <osmocom/bsc/pcu_if.h>
 #include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/bsc_stats.h>
 
 static struct osmo_fsm ts_fsm;
 

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/25275
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I58c5c1f8a5a09e9942aa6d1bdfe7f9766773963c
Gerrit-Change-Number: 25275
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210829/b7a5cda8/attachment-0001.htm>


More information about the gerrit-log mailing list