Change in osmo-bsc[master]: power_control: add VTY commands for per-BTS configuration

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Tue Dec 22 11:11:08 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/21685 )

Change subject: power_control: add VTY commands for per-BTS configuration
......................................................................

power_control: add VTY commands for per-BTS configuration

Change-Id: Ifd6ea29c3b9dbaccf92856131d5fb2e352b84eb2
Related: SYS#4918
---
M include/osmocom/bsc/vty.h
M src/osmo-bsc/bsc_vty.c
M src/osmo-bsc/osmo_bsc_main.c
M tests/Makefile.am
A tests/power_ctrl.vty
5 files changed, 677 insertions(+), 0 deletions(-)

Approvals:
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  Jenkins Builder: Verified



diff --git a/include/osmocom/bsc/vty.h b/include/osmocom/bsc/vty.h
index cfdcbfc..92f7932 100644
--- a/include/osmocom/bsc/vty.h
+++ b/include/osmocom/bsc/vty.h
@@ -28,6 +28,7 @@
 	CBC_SERVER_NODE,
 	CBC_CLIENT_NODE,
 	SMLC_NODE,
+	POWER_CTRL_NODE,
 };
 
 struct log_info;
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 3858da8..91ce2df 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -153,6 +153,12 @@
 	1,
 };
 
+struct cmd_node power_ctrl_node = {
+	POWER_CTRL_NODE,
+	"%s(config-power-ctrl)# ",
+	1,
+};
+
 struct cmd_node trx_node = {
 	TRX_NODE,
 	"%s(config-net-bts-trx)# ",
@@ -869,6 +875,99 @@
 		vty_out(vty, "auto%s", VTY_NEWLINE);
 }
 
+/* TODO: generalize and move indention handling to libosmocore */
+#define cfg_out(fmt, args...) \
+	vty_out(vty, "%*s" fmt, indent, "", ##args);
+
+static void config_write_power_ctrl_meas(struct vty *vty, unsigned int indent,
+					 const struct gsm_power_ctrl_params *cp,
+					 uint8_t ptype)
+{
+	const struct gsm_power_ctrl_meas_params *mp;
+	const char *param;
+
+	switch (ptype) {
+	case IPAC_RXLEV_AVE:
+		mp = &cp->rxlev_meas;
+		param = "rxlev";
+		break;
+	case IPAC_RXQUAL_AVE:
+		mp = &cp->rxqual_meas;
+		param = "rxqual";
+		break;
+	default:
+		/* Shall not happen */
+		OSMO_ASSERT(0);
+	}
+
+	cfg_out("%s-thresh lower %u upper %u%s",
+		param, mp->lower_thresh, mp->upper_thresh,
+		VTY_NEWLINE);
+	cfg_out("%s-thresh-comp lower %u %u upper %u %u%s",
+		param, mp->lower_cmp_p, mp->lower_cmp_n,
+		mp->upper_cmp_p, mp->upper_cmp_n,
+		VTY_NEWLINE);
+
+	switch (mp->algo) {
+	case GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE:
+		cfg_out("no %s-avg%s", param, VTY_NEWLINE);
+		return; /* we're done */
+	case GSM_PWR_CTRL_MEAS_AVG_ALGO_UNWEIGHTED:
+		cfg_out("%s-avg algo unweighted%s", param, VTY_NEWLINE);
+		break;
+	case GSM_PWR_CTRL_MEAS_AVG_ALGO_WEIGHTED:
+		cfg_out("%s-avg algo weighted%s", param, VTY_NEWLINE);
+		break;
+	case GSM_PWR_CTRL_MEAS_AVG_ALGO_MOD_MEDIAN:
+		cfg_out("%s-avg algo mod-median%s", param, VTY_NEWLINE);
+		break;
+	case GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA:
+		cfg_out("%s-avg algo osmo-ewma beta %u%s",
+			param, 100 - mp->ewma.alpha,
+			VTY_NEWLINE);
+		break;
+	}
+
+	cfg_out("%s-avg params hreqave %u hreqt %u%s",
+		param, mp->h_reqave, mp->h_reqt,
+		VTY_NEWLINE);
+}
+
+static void config_write_power_ctrl(struct vty *vty, unsigned int indent,
+				    const struct gsm_power_ctrl_params *cp)
+{
+	const char *node_name;
+
+	if (cp->dir == GSM_PWR_CTRL_DIR_UL)
+		node_name = "ms-power-control";
+	else
+		node_name = "bs-power-control";
+
+	switch (cp->mode) {
+	case GSM_PWR_CTRL_MODE_NONE:
+		cfg_out("no %s%s", node_name, VTY_NEWLINE);
+		break;
+	case GSM_PWR_CTRL_MODE_STATIC:
+		cfg_out("%s%s", node_name, VTY_NEWLINE);
+		cfg_out(" mode static%s", VTY_NEWLINE);
+		break;
+	case GSM_PWR_CTRL_MODE_DYN_BTS:
+		cfg_out("%s%s", node_name, VTY_NEWLINE);
+		cfg_out(" mode dyn-bts%s", VTY_NEWLINE);
+
+		cfg_out(" step-size inc %u red %u%s",
+			cp->inc_step_size_db, cp->red_step_size_db,
+			VTY_NEWLINE);
+
+		/* Measurement processing / averaging parameters */
+		config_write_power_ctrl_meas(vty, indent + 1, cp, IPAC_RXLEV_AVE);
+		config_write_power_ctrl_meas(vty, indent + 1, cp, IPAC_RXQUAL_AVE);
+		break;
+	}
+}
+
+#undef cfg_out
+
 static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
 {
 	int i;
@@ -1129,6 +1228,10 @@
 	    || bts->repeated_acch_policy.dl_facch_cmd)
 		vty_out(vty, "  repeat rxqual %u%s", bts->repeated_acch_policy.rxqual, VTY_NEWLINE);
 
+	/* BS/MS Power Control parameters */
+	config_write_power_ctrl(vty, 2, &bts->bs_power_ctrl);
+	config_write_power_ctrl(vty, 2, &bts->ms_power_ctrl);
+
 	config_write_bts_model(vty, bts);
 }
 
@@ -4722,6 +4825,344 @@
 	return CMD_SUCCESS;
 }
 
+#define BS_POWER_CONTROL_CMD \
+	"bs-power-control"
+#define MS_POWER_CONTROL_CMD \
+	"ms-power-control"
+#define POWER_CONTROL_CMD \
+	"(" BS_POWER_CONTROL_CMD "|" MS_POWER_CONTROL_CMD ")"
+#define POWER_CONTROL_DESC \
+	"BS (Downlink) power control parameters\n" \
+	"MS (Uplink) power control parameters\n"
+
+#define BTS_POWER_CTRL_PARAMS(bts) \
+	(strcmp(argv[0], BS_POWER_CONTROL_CMD) == 0) ? \
+		&bts->bs_power_ctrl : &bts->ms_power_ctrl
+
+DEFUN_USRATTR(cfg_bts_no_power_ctrl,
+	      cfg_bts_no_power_ctrl_cmd,
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "no " POWER_CONTROL_CMD,
+	      NO_STR POWER_CONTROL_DESC)
+{
+	struct gsm_power_ctrl_params *params;
+	struct gsm_bts *bts = vty->index;
+
+	params = BTS_POWER_CTRL_PARAMS(bts);
+	params->mode = GSM_PWR_CTRL_MODE_NONE;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_power_ctrl,
+      cfg_bts_power_ctrl_cmd,
+      POWER_CONTROL_CMD,
+      POWER_CONTROL_DESC)
+{
+	struct gsm_bts *bts = vty->index;
+
+	vty->index = BTS_POWER_CTRL_PARAMS(bts);
+	vty->node = POWER_CTRL_NODE;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_mode,
+	      cfg_power_ctrl_mode_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "mode (static|dyn-bts) [reset]",
+	      "Power control mode\n"
+	      "Instruct the MS/BTS to use a static power level (default)\n"
+	      "Power control to be performed dynamically by the BTS itself\n"
+	      "Reset to default parameters for the given mode\n")
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+
+	/* Do we need to reset? */
+	if (argc > 1) {
+		vty_out(vty, "%% Reset to default parameters%s", VTY_NEWLINE);
+		enum gsm_power_ctrl_dir dir = params->dir;
+		*params = power_ctrl_params_def;
+		params->dir = dir;
+	}
+
+	if (strcmp(argv[0], "static") == 0)
+		params->mode = GSM_PWR_CTRL_MODE_STATIC;
+	else if (strcmp(argv[0], "dyn-bts") == 0)
+		params->mode = GSM_PWR_CTRL_MODE_DYN_BTS;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_step_size,
+	      cfg_power_ctrl_step_size_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "step-size inc <2-6> red <2-4>",
+	      "Set power change step size (for dynamic mode)\n"
+	      "Increase step size (default is 4 dB)\n"
+	      "Step size (2, 4, or 6 dB)\n"
+	      "Reduce step size (default is 2 dB)\n"
+	      "Step size (2 or 4 dB)\n")
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+
+	if (atoi(argv[0]) % 2 || atoi(argv[1]) % 2) {
+		vty_out(vty, "%% Power change step size must be "
+			"an even number%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	params->inc_step_size_db = atoi(argv[0]);
+	params->red_step_size_db = atoi(argv[1]);
+
+	return CMD_SUCCESS;
+}
+
+#define POWER_CONTROL_MEAS_RXLEV_DESC \
+	"RxLev value (signal strength, 0 is worst, 63 is best)\n"
+#define POWER_CONTROL_MEAS_RXQUAL_DESC \
+	"RxQual value (signal quality, 0 is best, 7 is worst)\n"
+
+DEFUN_USRATTR(cfg_power_ctrl_rxlev_thresh,
+	      cfg_power_ctrl_rxlev_thresh_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "rxlev-thresh lower <0-63> upper <0-63>",
+	      "Set target RxLev thresholds (for dynamic mode)\n"
+	      "Lower RxLev value (default is 32, i.e. -78 dBm)\n"
+	      "Lower " POWER_CONTROL_MEAS_RXLEV_DESC
+	      "Upper RxLev value (default is 38, i.e. -72 dBm)\n"
+	      "Upper " POWER_CONTROL_MEAS_RXLEV_DESC)
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	int lower = atoi(argv[0]);
+	int upper = atoi(argv[1]);
+
+	if (lower > upper) {
+		vty_out(vty, "%% Lower 'rxlev-thresh' (%d) must be less than upper (%d)%s",
+			lower, upper, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	params->rxlev_meas.lower_thresh = lower;
+	params->rxlev_meas.upper_thresh = upper;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_rxqual_thresh,
+	      cfg_power_ctrl_rxqual_thresh_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "rxqual-thresh lower <0-7> upper <0-7>",
+	      "Set target RxQual thresholds (for dynamic mode)\n"
+	      "Lower RxQual value (default is 0, i.e. BER < 0.2%)\n"
+	      "Lower " POWER_CONTROL_MEAS_RXQUAL_DESC
+	      "Upper RxQual value (default is 3, i.e. 0.8% <= BER < 1.6%)\n"
+	      "Upper " POWER_CONTROL_MEAS_RXQUAL_DESC)
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	int lower = atoi(argv[0]);
+	int upper = atoi(argv[1]);
+
+	if (lower > upper) {
+		vty_out(vty, "%% Lower 'rxqual-rxqual' (%d) must be less than upper (%d)%s",
+			lower, upper, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	params->rxqual_meas.lower_thresh = lower;
+	params->rxqual_meas.upper_thresh = upper;
+
+	return CMD_SUCCESS;
+}
+
+#define POWER_CONTROL_MEAS_THRESH_COMP_CMD(meas) \
+	meas " lower <0-31> <0-31> upper <0-31> <0-31>"
+#define POWER_CONTROL_MEAS_THRESH_COMP_DESC(meas, lp, ln, up, un) \
+	"Set " meas " threshold comparators (for dynamic mode)\n" \
+	"Lower " meas " threshold comparators (see 3GPP TS 45.008, A.3.2.1)\n" lp ln \
+	"Upper " meas " threshold comparators (see 3GPP TS 45.008, A.3.2.1)\n" up un
+
+DEFUN_USRATTR(cfg_power_ctrl_rxlev_thresh_comp,
+	      cfg_power_ctrl_rxlev_thresh_comp_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      POWER_CONTROL_MEAS_THRESH_COMP_CMD("rxlev-thresh-comp"),
+	      POWER_CONTROL_MEAS_THRESH_COMP_DESC("RxLev",
+		"P1 (default 10)\n", "N1 (default 12)\n",
+		"P2 (default 10)\n", "N2 (default 12)\n"))
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	int lower_cmp_p = atoi(argv[0]);
+	int lower_cmp_n = atoi(argv[1]);
+	int upper_cmp_p = atoi(argv[2]);
+	int upper_cmp_n = atoi(argv[3]);
+
+	if (lower_cmp_p > lower_cmp_n) {
+		vty_out(vty, "%% Lower RxLev P1 %d must be less than N1 %d%s",
+			lower_cmp_p, lower_cmp_n, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (upper_cmp_p > upper_cmp_n) {
+		vty_out(vty, "%% Upper RxLev P2 %d must be less than N2 %d%s",
+			lower_cmp_p, lower_cmp_n, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	params->rxlev_meas.lower_cmp_p = lower_cmp_p;
+	params->rxlev_meas.lower_cmp_n = lower_cmp_n;
+	params->rxlev_meas.upper_cmp_p = upper_cmp_p;
+	params->rxlev_meas.upper_cmp_n = upper_cmp_n;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_rxqual_thresh_comp,
+	      cfg_power_ctrl_rxqual_thresh_comp_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      POWER_CONTROL_MEAS_THRESH_COMP_CMD("rxqual-thresh-comp"),
+	      POWER_CONTROL_MEAS_THRESH_COMP_DESC("RxQual",
+		"P3 (default 5)\n", "N3 (default 7)\n",
+		"P4 (default 15)\n", "N4 (default 18)\n"))
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	int lower_cmp_p = atoi(argv[0]);
+	int lower_cmp_n = atoi(argv[1]);
+	int upper_cmp_p = atoi(argv[2]);
+	int upper_cmp_n = atoi(argv[3]);
+
+	if (lower_cmp_p > lower_cmp_n) {
+		vty_out(vty, "%% Lower RxQual P3 %d must be less than N3 %d%s",
+			lower_cmp_p, lower_cmp_n, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (upper_cmp_p > upper_cmp_n) {
+		vty_out(vty, "%% Upper RxQual P4 %d must be less than N4 %d%s",
+			lower_cmp_p, lower_cmp_n, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	params->rxqual_meas.lower_cmp_p = lower_cmp_p;
+	params->rxqual_meas.lower_cmp_n = lower_cmp_n;
+	params->rxqual_meas.upper_cmp_p = upper_cmp_p;
+	params->rxqual_meas.upper_cmp_n = upper_cmp_n;
+
+	return CMD_SUCCESS;
+}
+
+#define POWER_CONTROL_MEAS_AVG_CMD \
+	"(rxlev-avg|rxqual-avg)"
+#define POWER_CONTROL_MEAS_AVG_DESC \
+	"RxLev (signal strength) measurement averaging (for dynamic mode)\n" \
+	"RxQual (signal quality) measurement averaging (for dynamic mode)\n"
+
+#define POWER_CONTROL_MEAS_AVG_PARAMS(params) \
+	(strncmp(argv[0], "rxlev", 5) == 0) ? \
+		&params->rxlev_meas : &params->rxqual_meas
+
+DEFUN_USRATTR(cfg_power_ctrl_no_avg,
+	      cfg_power_ctrl_no_avg_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "no " POWER_CONTROL_MEAS_AVG_CMD,
+	      NO_STR POWER_CONTROL_MEAS_AVG_DESC)
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	struct gsm_power_ctrl_meas_params *avg_params;
+
+	avg_params = POWER_CONTROL_MEAS_AVG_PARAMS(params);
+	avg_params->algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_avg_params,
+	      cfg_power_ctrl_avg_params_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      POWER_CONTROL_MEAS_AVG_CMD " params hreqave <1-31> hreqt <1-31>",
+	      POWER_CONTROL_MEAS_AVG_DESC "Configure general averaging parameters\n"
+	      "Hreqave: the period over which an average is produced\n"
+	      "Hreqave value (so that Hreqave * Hreqt < 32)\n"
+	      "Hreqt: the number of averaged results that are maintained\n"
+	      "Hreqt value (so that Hreqave * Hreqt < 32)\n")
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	struct gsm_power_ctrl_meas_params *avg_params;
+	int h_reqave = atoi(argv[1]);
+	int h_reqt = atoi(argv[2]);
+
+	if (h_reqave * h_reqt > 31) {
+		vty_out(vty, "%% Hreqave (%d) * Hreqt (%d) = %d must be < 32%s",
+			h_reqave, h_reqt, h_reqave * h_reqt, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	avg_params = POWER_CONTROL_MEAS_AVG_PARAMS(params);
+	avg_params->h_reqave = h_reqave;
+	avg_params->h_reqt = h_reqt;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_avg_algo,
+	      cfg_power_ctrl_avg_algo_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      /* FIXME: add algorithm specific parameters */
+	      POWER_CONTROL_MEAS_AVG_CMD " algo (unweighted|weighted|mod-median)",
+	      POWER_CONTROL_MEAS_AVG_DESC "Select the averaging algorithm\n"
+	      "Un-weighted average\n" "Weighted average\n"
+	      "Modified median calculation\n")
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	struct gsm_power_ctrl_meas_params *avg_params;
+
+	avg_params = POWER_CONTROL_MEAS_AVG_PARAMS(params);
+	if (strcmp(argv[1], "unweighted") == 0)
+		avg_params->algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_UNWEIGHTED;
+	else if (strcmp(argv[1], "weighted") == 0)
+		avg_params->algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_WEIGHTED;
+	else if (strcmp(argv[1], "mod-median") == 0)
+		avg_params->algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_MOD_MEDIAN;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_avg_osmo_ewma,
+	      cfg_power_ctrl_avg_osmo_ewma_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      POWER_CONTROL_MEAS_AVG_CMD " algo osmo-ewma beta <1-99>",
+	      POWER_CONTROL_MEAS_AVG_DESC "Select the averaging algorithm\n"
+	      "Exponentially Weighted Moving Average (EWMA)\n"
+	      "Smoothing factor (in %): beta = (100 - alpha)\n"
+	      "1% - lowest smoothing, 99% - highest smoothing\n")
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	struct gsm_power_ctrl_meas_params *avg_params;
+
+#if 0
+	if (trx->bts->type != GSM_BTS_TYPE_OSMOBTS) {
+		vty_out(vty, "%% EWMA is an OsmoBTS specific algorithm, "
+			"it's not usable for other BTS types%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+#endif
+
+	avg_params = POWER_CONTROL_MEAS_AVG_PARAMS(params);
+	avg_params->algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA;
+	avg_params->ewma.alpha = 100 - atoi(argv[1]);
+
+	return CMD_SUCCESS;
+}
+
 #define TRX_TEXT "Radio Transceiver\n"
 
 /* per TRX configuration */
@@ -7194,6 +7635,20 @@
 	neighbor_ident_vty_init(network, network->neighbor_bss_cells);
 	/* See also handover commands added on bts level from handover_vty.c */
 
+	install_element(BTS_NODE, &cfg_bts_power_ctrl_cmd);
+	install_element(BTS_NODE, &cfg_bts_no_power_ctrl_cmd);
+	install_node(&power_ctrl_node, dummy_config_write);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_mode_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_step_size_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_rxlev_thresh_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_rxqual_thresh_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_rxlev_thresh_comp_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_rxqual_thresh_comp_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_no_avg_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_avg_params_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_avg_algo_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_avg_osmo_ewma_cmd);
+
 	install_element(BTS_NODE, &cfg_trx_cmd);
 	install_node(&trx_node, dummy_config_write);
 	install_element(TRX_NODE, &cfg_trx_arfcn_cmd);
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index 4ab0430..ed561aa 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -583,6 +583,21 @@
 			vty->index_sub = NULL;
 		}
 		break;
+	case POWER_CTRL_NODE:
+		vty->node = BTS_NODE;
+		{
+			const struct gsm_power_ctrl_params *cp = vty->index;
+			struct gsm_bts *bts;
+
+			if (cp->dir == GSM_PWR_CTRL_DIR_UL)
+				bts = container_of(cp, struct gsm_bts, ms_power_ctrl);
+			else
+				bts = container_of(cp, struct gsm_bts, bs_power_ctrl);
+
+			vty->index_sub = &bts->description;
+			vty->index = bts;
+		}
+		break;
 	case TRX_NODE:
 		vty->node = BTS_NODE;
 		{
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c061baa..b11b905 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -40,6 +40,7 @@
 	nri_cfg.vty \
 	osmo-bsc.vty \
 	timer.vty \
+	power_ctrl.vty \
 	$(NULL)
 
 TESTSUITE = $(srcdir)/testsuite
diff --git a/tests/power_ctrl.vty b/tests/power_ctrl.vty
new file mode 100644
index 0000000..abd2768
--- /dev/null
+++ b/tests/power_ctrl.vty
@@ -0,0 +1,205 @@
+OsmoBSC> enable
+
+OsmoBSC# ### Dynamic power control must be disabled by default
+OsmoBSC# show running-config
+...
+  bs-power-control
+   mode static
+  ms-power-control
+   mode static
+...
+
+OsmoBSC# ### Check that 'power-ctrl' node and its commands exist
+OsmoBSC# configure terminal
+OsmoBSC(config)# network
+OsmoBSC(config-net)# bts 0
+OsmoBSC(config-net-bts)# list with-flags
+...
+  . ...  (bs-power-control|ms-power-control)
+  . ..l  no (bs-power-control|ms-power-control)
+...
+
+OsmoBSC(config-net-bts)# bs-power-control
+OsmoBSC(config-power-ctrl)# list with-flags
+...
+  . lv  mode (static|dyn-bts) [reset]
+  . lv  step-size inc <2-6> red <2-4>
+  . lv  rxlev-thresh lower <0-63> upper <0-63>
+  . lv  rxqual-thresh lower <0-7> upper <0-7>
+  . lv  rxlev-thresh-comp lower <0-31> <0-31> upper <0-31> <0-31>
+  . lv  rxqual-thresh-comp lower <0-31> <0-31> upper <0-31> <0-31>
+  . lv  no (rxlev-avg|rxqual-avg)
+  . lv  (rxlev-avg|rxqual-avg) params hreqave <1-31> hreqt <1-31>
+  . lv  (rxlev-avg|rxqual-avg) algo (unweighted|weighted|mod-median)
+  . lv  (rxlev-avg|rxqual-avg) algo osmo-ewma beta <1-99>
+
+OsmoBSC(config-power-ctrl)# ### Check default BS Power Parameters
+OsmoBSC(config-power-ctrl)# mode dyn-bts
+OsmoBSC(config-power-ctrl)# show running-config
+...
+  bs-power-control
+   mode dyn-bts
+   step-size inc 4 red 2
+   rxlev-thresh lower 32 upper 38
+   rxlev-thresh-comp lower 10 12 upper 19 20
+   no rxlev-avg
+   rxqual-thresh lower 0 upper 3
+   rxqual-thresh-comp lower 5 7 upper 15 18
+   no rxqual-avg
+  ms-power-control
+   mode static
+...
+
+OsmoBSC(config-power-ctrl)# exit
+OsmoBSC(config-net-bts)# ms-power-control
+OsmoBSC(config-power-ctrl)# list with-flags
+...
+  . lv  mode (static|dyn-bts) [reset]
+  . lv  step-size inc <2-6> red <2-4>
+  . lv  rxlev-thresh lower <0-63> upper <0-63>
+  . lv  rxqual-thresh lower <0-7> upper <0-7>
+  . lv  rxlev-thresh-comp lower <0-31> <0-31> upper <0-31> <0-31>
+  . lv  rxqual-thresh-comp lower <0-31> <0-31> upper <0-31> <0-31>
+  . lv  no (rxlev-avg|rxqual-avg)
+  . lv  (rxlev-avg|rxqual-avg) params hreqave <1-31> hreqt <1-31>
+  . lv  (rxlev-avg|rxqual-avg) algo (unweighted|weighted|mod-median)
+  . lv  (rxlev-avg|rxqual-avg) algo osmo-ewma beta <1-99>
+
+OsmoBSC(config-power-ctrl)# ### Check default MS Power Parameters
+OsmoBSC(config-power-ctrl)# mode dyn-bts
+OsmoBSC(config-power-ctrl)# show running-config
+...
+  bs-power-control
+   mode dyn-bts
+   step-size inc 4 red 2
+   rxlev-thresh lower 32 upper 38
+   rxlev-thresh-comp lower 10 12 upper 19 20
+   no rxlev-avg
+   rxqual-thresh lower 0 upper 3
+   rxqual-thresh-comp lower 5 7 upper 15 18
+   no rxqual-avg
+  ms-power-control
+   mode dyn-bts
+   step-size inc 4 red 2
+   rxlev-thresh lower 32 upper 38
+   rxlev-thresh-comp lower 10 12 upper 19 20
+   no rxlev-avg
+   rxqual-thresh lower 0 upper 3
+   rxqual-thresh-comp lower 5 7 upper 15 18
+   no rxqual-avg
+...
+
+OsmoBSC(config-power-ctrl)# step-size inc 5 red 4
+% Power change step size must be an even number
+OsmoBSC(config-power-ctrl)# step-size inc 2 red 3
+% Power change step size must be an even number
+OsmoBSC(config-power-ctrl)# step-size inc 2 red 4
+OsmoBSC(config-power-ctrl)# show running-config
+...
+  bs-power-control
+   mode dyn-bts
+   step-size inc 4 red 2
+...
+  ms-power-control
+   mode dyn-bts
+   step-size inc 2 red 4
+...
+
+OsmoBSC(config-power-ctrl)# rxlev-thresh lower?
+  lower  Lower RxLev value (default is 32, i.e. -78 dBm)
+OsmoBSC(config-power-ctrl)# rxlev-thresh lower ?
+  <0-63>  Lower RxLev value (signal strength, 0 is worst, 63 is best)
+OsmoBSC(config-power-ctrl)# rxlev-thresh lower 30 upper?
+  upper  Upper RxLev value (default is 38, i.e. -72 dBm)
+OsmoBSC(config-power-ctrl)# rxlev-thresh lower 30 upper ?
+  <0-63>  Upper RxLev value (signal strength, 0 is worst, 63 is best)
+OsmoBSC(config-power-ctrl)# rxlev-thresh lower 30 upper 63
+OsmoBSC(config-power-ctrl)# show running-config
+...
+  bs-power-control
+... !rxlev-thresh
+   rxlev-thresh lower 32 upper 38
+...
+  ms-power-control
+... !rxlev-thresh
+   rxlev-thresh lower 30 upper 63
+...
+
+OsmoBSC(config-power-ctrl)# rxqual-thresh lower?
+  lower  Lower RxQual value (default is 0, i.e. BER < 0.2%)
+OsmoBSC(config-power-ctrl)# rxqual-thresh lower ?
+  <0-7>  Lower RxQual value (signal quality, 0 is best, 7 is worst)
+OsmoBSC(config-power-ctrl)# rxqual-thresh lower 0 upper?
+  upper  Upper RxQual value (default is 3, i.e. 0.8% <= BER < 1.6%)
+OsmoBSC(config-power-ctrl)# rxqual-thresh lower 0 upper ?
+  <0-7>  Upper RxQual value (signal quality, 0 is best, 7 is worst)
+OsmoBSC(config-power-ctrl)# rxqual-thresh lower 0 upper 7
+OsmoBSC(config-power-ctrl)# show running-config
+...
+  bs-power-control
+... !rxqual-thresh
+   rxqual-thresh lower 0 upper 3
+...
+  ms-power-control
+... !rxqual-thresh
+   rxqual-thresh lower 0 upper 7
+...
+
+OsmoBSC(config-power-ctrl)# rxlev-avg algo osmo-ewma beta 50
+OsmoBSC(config-power-ctrl)# rxqual-avg algo unweighted
+OsmoBSC(config-power-ctrl)# show running-config
+...
+  bs-power-control
+... !(rxlev-avg|rxqual-avg)
+   no rxlev-avg
+... !(rxlev-avg|rxqual-avg)
+   no rxqual-avg
+...
+  ms-power-control
+... !(rxlev-avg|rxqual-avg)
+   rxlev-avg algo osmo-ewma beta 50
+   rxlev-avg params hreqave 4 hreqt 6
+... !(rxlev-avg|rxqual-avg)
+   rxqual-avg algo unweighted
+   rxqual-avg params hreqave 4 hreqt 6
+...
+
+OsmoBSC(config-power-ctrl)# rxlev-avg params hreqave 2 hreqt 20
+% Hreqave (2) * Hreqt (20) = 40 must be < 32
+OsmoBSC(config-power-ctrl)# rxlev-avg params hreqave 2 hreqt 15
+OsmoBSC(config-power-ctrl)# show running-config
+...
+  bs-power-control
+... !rxlev-avg params
+  ms-power-control
+... !rxlev-avg params
+   rxlev-avg params hreqave 2 hreqt 15
+...
+
+OsmoBSC(config-power-ctrl)# exit
+OsmoBSC(config-net-bts)# ### Disable BS/MS Power Control
+OsmoBSC(config-net-bts)# no bs-power-control
+OsmoBSC(config-net-bts)# no ms-power-control
+OsmoBSC(config-net-bts)# show running-config
+...
+  no bs-power-control
+  no ms-power-control
+...
+
+OsmoBSC(config-net-bts)# bs-power-control
+OsmoBSC(config-power-ctrl)# mode static reset
+% Reset to default parameters
+OsmoBSC(config-power-ctrl)# exit
+
+OsmoBSC(config-net-bts)# ms-power-control
+OsmoBSC(config-power-ctrl)# mode static reset
+% Reset to default parameters
+OsmoBSC(config-power-ctrl)# exit
+
+OsmoBSC(config-net-bts)# show running-config
+...
+  bs-power-control
+   mode static
+  ms-power-control
+   mode static
+...

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

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Ifd6ea29c3b9dbaccf92856131d5fb2e352b84eb2
Gerrit-Change-Number: 21685
Gerrit-PatchSet: 7
Gerrit-Owner: fixeria <vyanitskiy at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201222/937a9b5d/attachment.htm>


More information about the gerrit-log mailing list