aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bsc')
-rw-r--r--src/osmo-bsc/bsc_ctrl_commands.c49
-rw-r--r--src/osmo-bsc/bsc_vty.c42
-rw-r--r--src/osmo-bsc/bts.c20
-rw-r--r--src/osmo-bsc/bts_osmobts.c33
4 files changed, 143 insertions, 1 deletions
diff --git a/src/osmo-bsc/bsc_ctrl_commands.c b/src/osmo-bsc/bsc_ctrl_commands.c
index 15f553645..be83b1b49 100644
--- a/src/osmo-bsc/bsc_ctrl_commands.c
+++ b/src/osmo-bsc/bsc_ctrl_commands.c
@@ -550,6 +550,54 @@ static int set_trx_max_power(struct ctrl_cmd *cmd, void *_data)
}
CTRL_CMD_DEFINE(trx_max_power, "max-power-reduction");
+static int verify_bts_c0_power_red(struct ctrl_cmd *cmd, const char *value, void *_data)
+{
+ const int red = atoi(value);
+
+ if (red < 0 || red > 6) {
+ cmd->reply = "Value is out of range";
+ return 1;
+ } else if (red % 2 != 0) {
+ cmd->reply = "Value must be even";
+ return 1;
+ }
+
+ return 0;
+}
+
+static int get_bts_c0_power_red(struct ctrl_cmd *cmd, void *data)
+{
+ const struct gsm_bts *bts = cmd->node;
+
+ cmd->reply = talloc_asprintf(cmd, "%u", bts->c0_max_power_red_db);
+ if (!cmd->reply) {
+ cmd->reply = "OOM.";
+ return CTRL_CMD_ERROR;
+ }
+
+ return CTRL_CMD_REPLY;
+}
+
+static int set_bts_c0_power_red(struct ctrl_cmd *cmd, void *data)
+{
+ struct gsm_bts *bts = cmd->node;
+ const int red = atoi(cmd->value);
+ int rc;
+
+ rc = gsm_bts_set_c0_power_red(bts, red);
+ if (rc == -ENOTSUP) {
+ cmd->reply = "BCCH carrier power reduction is not supported";
+ return CTRL_CMD_ERROR;
+ } else if (rc != 0) {
+ cmd->reply = "Failed to enable BCCH carrier power reduction";
+ return CTRL_CMD_ERROR;
+ }
+
+ return get_bts_c0_power_red(cmd, data);
+}
+
+CTRL_CMD_DEFINE(bts_c0_power_red, "c0-power-reduction");
+
int bsc_base_ctrl_cmds_install(void)
{
int rc = 0;
@@ -571,6 +619,7 @@ int bsc_base_ctrl_cmds_install(void)
rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_oml_up);
rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_gprs_mode);
rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_state);
+ rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_c0_power_red);
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_max_power);
rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_arfcn);
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 7207341a1..efa59d3e1 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -444,6 +444,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
if (strnlen(bts->pcu_version, MAX_VERSION_LENGTH))
vty_out(vty, " PCU version %s connected%s", bts->pcu_version,
VTY_NEWLINE);
+ vty_out(vty, " BCCH carrier power reduction (maximum): %u dB%s",
+ bts->c0_max_power_red_db, VTY_NEWLINE);
vty_out(vty, " MS Max power: %u dBm%s", bts->ms_max_power, VTY_NEWLINE);
vty_out(vty, " Minimum Rx Level for Access: %i dBm%s",
rxlev2dbm(bts->si_common.cell_sel_par.rxlev_acc_min),
@@ -6020,6 +6022,45 @@ DEFUN(bts_resend_power_ctrl_params,
return CMD_SUCCESS;
}
+DEFUN(bts_c0_power_red,
+ bts_c0_power_red_cmd,
+ "bts <0-255> c0-power-reduction <0-6>",
+ "BTS Specific Commands\n" BTS_NR_STR
+ "BCCH carrier power reduction operation\n"
+ "Power reduction value (in dB, even numbers only)\n")
+{
+ int bts_nr = atoi(argv[0]);
+ int red = atoi(argv[1]);
+ struct gsm_bts *bts;
+ int rc;
+
+ 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 (red % 2 != 0) {
+ vty_out(vty, "%% Incorrect BCCH power reduction value, "
+ "an even number is expected%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ rc = gsm_bts_set_c0_power_red(bts, red);
+ if (rc == -ENOTSUP) {
+ vty_out(vty, "%% BCCH carrier power reduction operation mode "
+ "is not supported for BTS%u%s", bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ } else if (rc != 0) {
+ vty_out(vty, "%% Failed to %sable BCCH carrier power reduction "
+ "operation mode for BTS%u%s", red ? "en" : "dis",
+ bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
/* this command is now hidden, as it's a low-level debug hack, and people should
* instead use osmo-cbc these days */
DEFUN_HIDDEN(smscb_cmd, smscb_cmd_cmd,
@@ -8172,6 +8213,7 @@ int bsc_vty_init(struct gsm_network *network)
install_element(ENABLE_NODE, &restart_bts_cmd);
install_element(ENABLE_NODE, &bts_resend_sysinfo_cmd);
install_element(ENABLE_NODE, &bts_resend_power_ctrl_params_cmd);
+ install_element(ENABLE_NODE, &bts_c0_power_red_cmd);
install_element(ENABLE_NODE, &pdch_act_cmd);
install_element(ENABLE_NODE, &lchan_act_cmd);
install_element(ENABLE_NODE, &lchan_act_all_cmd);
diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c
index b64890fae..c1f09ff07 100644
--- a/src/osmo-bsc/bts.c
+++ b/src/osmo-bsc/bts.c
@@ -1,5 +1,5 @@
/* (C) 2008-2018 by Harald Welte <laforge@gnumonks.org>
- * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
@@ -747,6 +747,24 @@ int gsm_bts_set_system_infos(struct gsm_bts *bts)
return 0;
}
+int gsm_bts_set_c0_power_red(struct gsm_bts *bts, const uint8_t red)
+{
+ int rc;
+
+ if (!osmo_bts_has_feature(&bts->features, BTS_FEAT_BCCH_POWER_RED))
+ return -ENOTSUP;
+ if (bts->model->power_ctrl_set_c0_power_red == NULL)
+ return -ENOTSUP;
+
+ rc = bts->model->power_ctrl_set_c0_power_red(bts, red);
+ if (rc != 0)
+ return rc;
+
+ bts->c0_max_power_red_db = red;
+
+ return 0;
+}
+
const struct rate_ctr_desc bts_ctr_description[] = {
[BTS_CTR_CHREQ_TOTAL] = \
{ "chreq:total",
diff --git a/src/osmo-bsc/bts_osmobts.c b/src/osmo-bsc/bts_osmobts.c
index 1814ada3d..9813a265d 100644
--- a/src/osmo-bsc/bts_osmobts.c
+++ b/src/osmo-bsc/bts_osmobts.c
@@ -1,6 +1,7 @@
/* Osmocom OsmoBTS specific code */
/* (C) 2010-2012 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
@@ -43,6 +44,35 @@ extern struct gsm_bts_model bts_model_nanobts;
static struct gsm_bts_model model_osmobts;
+static int power_ctrl_set_c0_power_red(const struct gsm_bts *bts,
+ const uint8_t red)
+{
+ struct abis_rsl_dchan_hdr *dh;
+ struct msgb *msg;
+
+ msg = rsl_msgb_alloc();
+ if (msg == NULL)
+ return -ENOMEM;
+
+ LOGP(DRSL, LOGL_NOTICE, "%sabling BCCH carrier power reduction "
+ "operation mode for BTS%u (maximum %u dB)\n",
+ red ? "En" : "Dis", bts->nr, red);
+
+ /* Abuse the standard BS POWER CONTROL message by specifying 'Common Channel'
+ * in the Protocol Discriminator field and 'BCCH' in the Channel Number IE. */
+ dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
+ dh->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN;
+ dh->c.msg_type = RSL_MT_BS_POWER_CONTROL;
+ dh->ie_chan = RSL_IE_CHAN_NR;
+ dh->chan_nr = RSL_CHAN_BCCH;
+
+ msgb_tv_put(msg, RSL_IE_BS_POWER, red / 2);
+
+ msg->dst = bts->c0->rsl_link_primary;
+
+ return abis_rsl_sendmsg(msg);
+}
+
int bts_model_osmobts_init(void)
{
model_osmobts = bts_model_nanobts;
@@ -52,6 +82,9 @@ int bts_model_osmobts_init(void)
/* Unlike nanoBTS, osmo-bts does support SI2bis and SI2ter fine */
model_osmobts.force_combined_si = false;
+ /* Power control API */
+ model_osmobts.power_ctrl_set_c0_power_red = &power_ctrl_set_c0_power_red;
+
model_osmobts.features.data = &model_osmobts._features_data[0];
model_osmobts.features.data_len =
sizeof(model_osmobts._features_data);