aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2019-05-21 02:38:43 +0200
committerHarald Welte <laforge@gnumonks.org>2019-05-23 19:16:11 +0000
commit590b23ce3c78d8cca5baa15f92019edf74a9323c (patch)
tree1315f0bc45d13541ab39551bb43b0c05b1bd2520
parentd7be09caf8d49ac65ed626bca9de2fb738a365b6 (diff)
cbch: Add counters; queue length limits and CBCH LOAD reporting
This adds the final missing part to full CBCH support: * keep a tab on the current queue length for basic + extended CBCH * keep rate counters about the number of sent / transmitted SMSCB * send CBCH LOAD information via RSL to the BSC Change-Id: I7068c7937a60a900c40439115bb84dc3ee0d061f
-rw-r--r--include/osmo-bts/cbch.h8
-rw-r--r--include/osmo-bts/gsm_data_shared.h4
-rw-r--r--include/osmo-bts/rsl.h2
-rw-r--r--src/common/bts.c25
-rw-r--r--src/common/cbch.c39
-rw-r--r--src/common/rsl.c26
-rw-r--r--src/common/vty.c35
7 files changed, 137 insertions, 2 deletions
diff --git a/include/osmo-bts/cbch.h b/include/osmo-bts/cbch.h
index af5fd9a3..6bba5fa2 100644
--- a/include/osmo-bts/cbch.h
+++ b/include/osmo-bts/cbch.h
@@ -6,6 +6,14 @@
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/bts.h>
+enum {
+ CBCH_CTR_RCVD_QUEUED,
+ CBCH_CTR_RCVD_DROPPED,
+ CBCH_CTR_SENT_SINGLE,
+ CBCH_CTR_SENT_DEFAULT,
+ CBCH_CTR_SENT_NULL,
+};
+
/* incoming SMS broadcast command from RSL */
int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_type,
bool extended_cbch, uint8_t msg_len, const uint8_t *msg);
diff --git a/include/osmo-bts/gsm_data_shared.h b/include/osmo-bts/gsm_data_shared.h
index 860c296c..415e6bc0 100644
--- a/include/osmo-bts/gsm_data_shared.h
+++ b/include/osmo-bts/gsm_data_shared.h
@@ -542,6 +542,7 @@ struct gprs_rlc_cfg {
struct bts_smscb_state {
struct llist_head queue; /* list of struct smscb_msg */
int queue_len;
+ struct rate_ctr_group *ctrs;
struct smscb_msg *cur_msg; /* current SMS-CB */
struct smscb_msg *default_msg; /* default broadcast message; NULL if none */
};
@@ -744,6 +745,9 @@ struct gsm_bts {
/* State for SMSCB (Cell Broadcast) for BASIC and EXTENDED channel */
struct bts_smscb_state smscb_basic;
struct bts_smscb_state smscb_extended;
+ int smscb_queue_tgt_len; /* ideal/target queue length */
+ int smscb_queue_max_len; /* maximum queue length */
+ int smscb_queue_hyst; /* hysteresis for CBCH laod indications */
float min_qual_rach; /* minimum quality for RACH bursts */
float min_qual_norm; /* minimum quality for normal daata */
diff --git a/include/osmo-bts/rsl.h b/include/osmo-bts/rsl.h
index 0361841d..186018eb 100644
--- a/include/osmo-bts/rsl.h
+++ b/include/osmo-bts/rsl.h
@@ -43,4 +43,6 @@ void cb_ts_disconnected(struct gsm_bts_trx_ts *ts);
void cb_ts_connected(struct gsm_bts_trx_ts *ts, int rc);
void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc);
+int rsl_tx_cbch_load_indication(struct gsm_bts *bts, bool ext_cbch, bool overflow, uint8_t amount);
+
#endif // _RSL_H */
diff --git a/src/common/bts.c b/src/common/bts.c
index 4af219b1..5220406d 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -49,6 +49,7 @@
#include <osmo-bts/oml.h>
#include <osmo-bts/signal.h>
#include <osmo-bts/dtx_dl_amr_fsm.h>
+#include <osmo-bts/cbch.h>
#define MIN_QUAL_RACH 5.0f /* at least 5 dB C/I */
#define MIN_QUAL_NORM -0.5f /* at least -1 dB C/I */
@@ -105,6 +106,22 @@ static const struct rate_ctr_group_desc bts_ctrg_desc = {
bts_ctr_desc
};
+static const struct rate_ctr_desc cbch_ctr_desc[] = {
+ [CBCH_CTR_RCVD_QUEUED] = {"cbch:rcvd_queued", "Received + queued CBCH messages (Abis)" },
+ [CBCH_CTR_RCVD_DROPPED] = {"cbch:rcvd_dropped", "Received + dropped CBCH messages (Abis)" },
+
+ [CBCH_CTR_SENT_SINGLE] = {"cbch:sent_single", "Sent single CBCH messages (Um)" },
+ [CBCH_CTR_SENT_DEFAULT] = {"cbch:sent_default", "Sent default CBCH messages (Um)" },
+ [CBCH_CTR_SENT_NULL] = {"cbch:sent_null", "Sent NULL CBCH messages (Um)" },
+};
+static const struct rate_ctr_group_desc cbch_ctrg_desc = {
+ "cbch",
+ "cell broadcast channel",
+ OSMO_STATS_CLASS_GLOBAL,
+ ARRAY_SIZE(cbch_ctr_desc),
+ cbch_ctr_desc
+};
+
/* Initialize the BTS data structures, called before config
* file reading */
int bts_init(struct gsm_bts *bts)
@@ -191,7 +208,15 @@ int bts_init(struct gsm_bts *bts)
}
INIT_LLIST_HEAD(&bts->smscb_basic.queue);
+ bts->smscb_basic.ctrs = rate_ctr_group_alloc(bts, &cbch_ctrg_desc, 0);
+ OSMO_ASSERT(bts->smscb_basic.ctrs);
INIT_LLIST_HEAD(&bts->smscb_extended.queue);
+ bts->smscb_extended.ctrs = rate_ctr_group_alloc(bts, &cbch_ctrg_desc, 1);
+ OSMO_ASSERT(bts->smscb_extended.ctrs);
+ bts->smscb_queue_max_len = 15;
+ bts->smscb_queue_tgt_len = 2;
+ bts->smscb_queue_hyst = 2;
+
INIT_LLIST_HEAD(&bts->oml_queue);
/* register DTX DL FSM */
diff --git a/src/common/cbch.c b/src/common/cbch.c
index 2107f115..6b65679f 100644
--- a/src/common/cbch.c
+++ b/src/common/cbch.c
@@ -26,6 +26,7 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/cbch.h>
+#include <osmo-bts/rsl.h>
#include <osmo-bts/logging.h>
/* internal representation of one SMS-CB message (e.g. in the pending queue */
@@ -37,6 +38,28 @@ struct smscb_msg {
uint8_t num_segs; /* total number of segments */
};
+/* determine if current queue length differes more than permitted hysteresis from target
+ * queue length. If it does, send CBCH LOAD IND */
+static void check_and_send_cbch_load(struct gsm_bts *bts, struct bts_smscb_state *bts_ss)
+{
+ int delta = bts_ss->queue_len - bts->smscb_queue_tgt_len;
+ bool extended_cbch = false;
+
+ if (bts_ss == &bts->smscb_extended)
+ extended_cbch = true;
+
+ if (abs(delta) < bts->smscb_queue_hyst)
+ return;
+
+ if (delta < 0) {
+ /* Underrun */
+ rsl_tx_cbch_load_indication(bts, extended_cbch, false, OSMO_MIN(15, -delta));
+ } else {
+ /* Overrun */
+ rsl_tx_cbch_load_indication(bts, extended_cbch, true, OSMO_MIN(15, delta));
+ }
+}
+
/* determine SMSCB state by tb number */
static struct bts_smscb_state *bts_smscb_state(struct gsm_bts *bts, uint8_t tb)
{
@@ -182,9 +205,16 @@ int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_typ
case RSL_CB_CMD_TYPE_SCHEDULE:
case RSL_CB_CMD_TYPE_NULL:
/* def_bcast is ignored as per Section 9.3.41 of 3GPP TS 48.058 */
+ /* limit queue size and optionally send CBCH LOAD Information (overflow) via RSL */
+ if (bts_ss->queue_len >= bts->smscb_queue_max_len) {
+ rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_RCVD_DROPPED);
+ talloc_free(scm);
+ break;
+ }
llist_add_tail(&scm->list, &bts_ss->queue);
bts_ss->queue_len++;
- /* FIXME: limit queue size and optionally send CBCH LOAD Information (overflow) via RSL */
+ check_and_send_cbch_load(bts, bts_ss);
+ rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_RCVD_QUEUED);
break;
case RSL_CB_CMD_TYPE_DEFAULT:
/* old default msg will be free'd in get_smscb_block() if it is currently in transit
@@ -217,20 +247,25 @@ static struct smscb_msg *select_next_smscb(struct gsm_bts *bts, uint8_t tb)
if (msg) {
llist_del(&msg->list);
bts_ss->queue_len--;
+ check_and_send_cbch_load(bts, bts_ss);
DEBUGP(DLSMS, "%s: Dequeued msg\n", __func__);
+ rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_SINGLE);
return msg;
}
- /* FIXME: send CBCH LOAD Information (underflow) via RSL */
+ /* send CBCH LOAD Information (underflow) via RSL */
+ check_and_send_cbch_load(bts, bts_ss);
/* choose the default message, if any */
msg = bts_ss->default_msg;
if (msg) {
DEBUGP(DLSMS, "%s: Using default msg\n", __func__);
+ rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_DEFAULT);
return msg;
}
DEBUGP(DLSMS, "%s: No queued msg nor default\n", __func__);
+ rate_ctr_inc2(bts_ss->ctrs, CBCH_CTR_SENT_NULL);
return NULL;
}
diff --git a/src/common/rsl.c b/src/common/rsl.c
index 364e8291..af0b72d1 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -1636,6 +1636,32 @@ static int rsl_rx_sacch_inf_mod(struct msgb *msg)
return 0;
}
+/* 8.5.8 CBCH Load Information */
+int rsl_tx_cbch_load_indication(struct gsm_bts *bts, bool ext_cbch, bool overflow, uint8_t amount)
+{
+ struct gsm_lchan *lchan = gsm_bts_get_cbch(bts);
+ struct msgb *msg;
+ uint8_t load_info;
+
+ msg = rsl_msgb_alloc(sizeof(struct abis_rsl_cchan_hdr));
+ if (!msg)
+ return -ENOMEM;
+
+ /* 9.3.1 Channel Number */
+ rsl_cch_push_hdr(msg, RSL_MT_CBCH_LOAD_IND, gsm_lchan2chan_nr(lchan));
+
+ /* 9.3.43 CBCH Load Information */
+ load_info = ((overflow & 1) << 7) | (amount & 0x0F);
+ msgb_tv_put(msg, RSL_IE_CBCH_LOAD_INFO, load_info);
+ /* 9.3.44 SMSCB Channel Indicator */
+ if (ext_cbch)
+ msgb_tv_put(msg, RSL_IE_SMSCB_CHAN_INDICATOR, 0x01);
+
+ msg->trx = bts->c0;
+
+ return abis_bts_rsl_sendmsg(msg);
+}
+
/*
* ip.access related messages
*/
diff --git a/src/common/vty.c b/src/common/vty.c
index fab55161..1d25bfb5 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -310,6 +310,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " pcu-socket %s%s", bts->pcu.sock_path, VTY_NEWLINE);
if (bts->supp_meas_toa256)
vty_out(vty, " supp-meas-info toa256%s", VTY_NEWLINE);
+ vty_out(vty, " smscb queue-max-length %d%s", bts->smscb_queue_max_len, VTY_NEWLINE);
+ vty_out(vty, " smscb queue-target-length %d%s", bts->smscb_queue_tgt_len, VTY_NEWLINE);
+ vty_out(vty, " smscb queue-hysteresis %d%s", bts->smscb_queue_hyst, VTY_NEWLINE);
bts_model_config_write_bts(vty, bts);
@@ -687,6 +690,33 @@ DEFUN(cfg_bts_no_supp_meas_toa256, cfg_bts_no_supp_meas_toa256_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_bts_smscb_max_qlen, cfg_bts_smscb_max_qlen_cmd,
+ "smscb queue-max-length <1-60>",
+ "Maximum queue length for SMSCB (CBCH) queue. In count of messages/pages (Default: 15)")
+{
+ struct gsm_bts *bts = vty->index;
+ bts->smscb_queue_max_len = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_smscb_tgt_qlen, cfg_bts_smscb_tgt_qlen_cmd,
+ "smscb queue-target-length <1-30>",
+ "Target queue length for SMSCB (CBCH) queue. In count of messages/pages (Default: 2)")
+{
+ struct gsm_bts *bts = vty->index;
+ bts->smscb_queue_tgt_len = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_smscb_qhyst, cfg_bts_smscb_qhyst_cmd,
+ "smscb queue-hysteresis <0-30>",
+ "Hysteresis for SMSCB (CBCH) queue. In count of messages/pages (Default: 2)")
+{
+ struct gsm_bts *bts = vty->index;
+ bts->smscb_queue_hyst = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
#define DB_DBM_STR \
"Unit is dB (decibels)\n" \
@@ -854,6 +884,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
bts->agch_queue.rejected_msgs, bts->agch_queue.agch_msgs,
bts->agch_queue.pch_msgs,
VTY_NEWLINE);
+ vty_out(vty, " CBCH queue target: %d, hysteresis: %d, maximum: %d%s",
+ bts->smscb_queue_tgt_len, bts->smscb_queue_max_len, bts->smscb_queue_hyst, VTY_NEWLINE);
vty_out(vty, " CBCH backlog queue length (BASIC): %d%s",
bts->smscb_basic.queue_len, VTY_NEWLINE);
vty_out(vty, " CBCH backlog queue length (EXTENDED): %u%s",
@@ -1614,6 +1646,9 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);
install_element(BTS_NODE, &cfg_bts_supp_meas_toa256_cmd);
install_element(BTS_NODE, &cfg_bts_no_supp_meas_toa256_cmd);
+ install_element(BTS_NODE, &cfg_bts_smscb_max_qlen_cmd);
+ install_element(BTS_NODE, &cfg_bts_smscb_tgt_qlen_cmd);
+ install_element(BTS_NODE, &cfg_bts_smscb_qhyst_cmd);
install_element(BTS_NODE, &cfg_trx_gsmtap_sapi_cmd);
install_element(BTS_NODE, &cfg_trx_no_gsmtap_sapi_cmd);