Change in osmo-bts[master]: power_control: implement handling of P_Con_INTERVAL parameter

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/.

fixeria gerrit-no-reply at lists.osmocom.org
Mon Feb 8 11:09:24 UTC 2021


fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/22781 )

Change subject: power_control: implement handling of P_Con_INTERVAL parameter
......................................................................

power_control: implement handling of P_Con_INTERVAL parameter

Change-Id: Ibf9956b2c6d829b38e9fda7d1f29790036219f42
Related: SYS#4918
---
M include/osmo-bts/gsm_data.h
M src/common/power_control.c
M src/common/rsl.c
M src/common/vty.c
M tests/power/bs_power_loop_test.c
M tests/power/bs_power_loop_test.err
M tests/power/bs_power_loop_test.ok
M tests/power/ms_power_loop_test.c
M tests/power/ms_power_loop_test.err
M tests/power/ms_power_loop_test.ok
10 files changed, 320 insertions(+), 3 deletions(-)

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



diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index 8071a28..05b6cf2 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -201,6 +201,9 @@
 
 /* MS/BS Power Control parameters */
 struct gsm_power_ctrl_params {
+	/* Minimum interval between power level changes */
+	uint8_t ctrl_interval; /* 1 step is 2 SACCH periods */
+
 	/* Power change step size (maximum) */
 	uint8_t inc_step_size_db; /* increasing direction */
 	uint8_t red_step_size_db; /* reducing direction */
@@ -231,6 +234,8 @@
 	const struct gsm_power_ctrl_params *dpc_params;
 	/* Measurement pre-processing state (for dynamic mode) */
 	struct gsm_power_ctrl_meas_proc_state rxlev_meas_proc;
+	/* Number of SACCH blocks to skip (for dynamic mode) */
+	int skip_block_num;
 
 	/* Depending on the context (MS or BS power control), fields 'current' and 'max'
 	 * reflect either the MS power level (magic numbers), or BS Power reduction level
diff --git a/src/common/power_control.c b/src/common/power_control.c
index be74a41..4f5d15e 100644
--- a/src/common/power_control.c
+++ b/src/common/power_control.c
@@ -1,7 +1,8 @@
 /* MS Power Control Loop L1 */
 
 /* (C) 2014 by Holger Hans Peter Freyther
- * Contributions by sysmocom - s.m.f.c. GmbH <info at sysmocom.de>
+ * (C) 2020-2021 by sysmocom - s.m.f.c. GmbH <info at sysmocom.de>
+ * Author: Vadim Yanitskiy <vyanitskiy at sysmocom.de>
  *
  * All Rights Reserved
  *
@@ -160,6 +161,17 @@
 	if (params == NULL)
 		return 0;
 
+	/* Power control interval: how many blocks do we skip? */
+	if (state->skip_block_num-- > 0)
+		return 0;
+
+	/* Reset the number of SACCH blocks to be skipped:
+	 *   ctrl_interval=0 => 0 blocks to skip,
+	 *   ctrl_interval=1 => 1 blocks to skip,
+	 *   ctrl_interval=2 => 3 blocks to skip,
+	 *     so basically ctrl_interval * 2 - 1. */
+	state->skip_block_num = params->ctrl_interval * 2 - 1;
+
 	ms_dbm = ms_pwr_dbm(band, ms_power_lvl);
 	if (ms_dbm < 0) {
 		LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
@@ -265,6 +277,17 @@
 		  lchan->tch.dtx.dl_active ? "enabled" : "disabled",
 		  lchan->tch.dtx.dl_active ? "SUB" : "FULL");
 
+	/* Power control interval: how many blocks do we skip? */
+	if (state->skip_block_num-- > 0)
+		return 0;
+
+	/* Reset the number of SACCH blocks to be skipped:
+	 *   ctrl_interval=0 => 0 blocks to skip,
+	 *   ctrl_interval=1 => 1 blocks to skip,
+	 *   ctrl_interval=2 => 3 blocks to skip,
+	 *     so basically ctrl_interval * 2 - 1. */
+	state->skip_block_num = params->ctrl_interval * 2 - 1;
+
 	/* If DTx is active on Downlink, use the '-SUB' */
 	if (lchan->tch.dtx.dl_active) {
 		rxqual = rxqual_sub;
diff --git a/src/common/rsl.c b/src/common/rsl.c
index bde53a1..3023ffa 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -763,7 +763,8 @@
 		params->rxqual_meas.upper_cmp_p = thresh_comp->p4;
 		params->rxqual_meas.upper_cmp_n = thresh_comp->n4;
 
-		/* FIXME: TIMER_PWR_CON_INTERVAL (P_Con_INTERVAL) */
+		/* Minimum interval between power level changes (P_Con_INTERVAL) */
+		params->ctrl_interval = thresh_comp->pc_interval;
 
 		/* Power increase / reduce step size: POWER_{INC,RED}_STEP_SIZE */
 		params->inc_step_size_db = thresh_comp->inc_step_size;
diff --git a/src/common/vty.c b/src/common/vty.c
index 9dd0c1a..f36c09e 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -1269,6 +1269,11 @@
 static void dump_dpc_params(struct vty *vty, const unsigned int indent,
 			    const struct gsm_power_ctrl_params *cp)
 {
+	cfg_out(vty, "Power control interval: %u ms (every %u SACCH block(s))%s",
+		cp->ctrl_interval ? cp->ctrl_interval * 2 * 480 : 480,
+		cp->ctrl_interval ? cp->ctrl_interval * 2 : 1,
+		VTY_NEWLINE);
+
 	cfg_out(vty, "Power increase step size: %u%s",
 		cp->inc_step_size_db, VTY_NEWLINE);
 	cfg_out(vty, "Power reduce step size: %u%s",
diff --git a/tests/power/bs_power_loop_test.c b/tests/power/bs_power_loop_test.c
index 5271324..6f5f2bf 100644
--- a/tests/power/bs_power_loop_test.c
+++ b/tests/power/bs_power_loop_test.c
@@ -1,5 +1,5 @@
 /*
- * (C) 2020 by sysmocom - s.m.f.c. GmbH <info at sysmocom.de>
+ * (C) 2020-2021 by sysmocom - s.m.f.c. GmbH <info at sysmocom.de>
  * Author: Vadim Yanitskiy <vyanitskiy at sysmocom.de>
  *
  * All Rights Reserved
@@ -56,6 +56,7 @@
 	PWR_TEST_ST_IND_MEAS = 0,
 	PWR_TEST_ST_IND_DUMMY,
 	PWR_TEST_ST_SET_STATE,
+	PWR_TEST_ST_SET_CTRL_INTERVAL,
 	PWR_TEST_ST_SET_STEP_SIZE,
 	PWR_TEST_ST_SET_RXLEV_PARAMS,
 	PWR_TEST_ST_ENABLE_DTXD,
@@ -84,6 +85,8 @@
 			uint8_t inc;
 			uint8_t red;
 		} step_size;
+		/* Power control interval */
+		uint8_t ctrl_interval;
 	};
 	/* Expected Tx power reduction */
 	uint8_t exp_txred;
@@ -159,6 +162,11 @@
 		printf("#%02u %s() <- Dynamic power control is disabled\n", n, __func__);
 		lchan->bs_power_ctrl.dpc_params = NULL;
 		return 0; /* we're done */
+	case PWR_TEST_ST_SET_CTRL_INTERVAL:
+		printf("#%02u %s() <- (Re)set power control interval: %u -> %u\n",
+		       n, __func__, lchan->bs_dpc_params.ctrl_interval, step->ctrl_interval);
+		lchan->bs_dpc_params.ctrl_interval = step->ctrl_interval;
+		return 0; /* we're done */
 	case PWR_TEST_ST_SET_STEP_SIZE:
 		printf("#%02u %s() <- Set step size: inc %u dB, red %u dB\n",
 		       n, __func__, step->step_size.inc, step->step_size.red);
@@ -411,6 +419,49 @@
 	{ .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET),	.exp_txred = 16 },
 };
 
+/* Verify handling of optional power control interval (P_Con_INTERVAL). */
+static const struct power_test_step TC_ctrl_interval[] = {
+	/* Initial state: 0 dB, up to 20 dB */
+	{ .type = PWR_TEST_ST_SET_STATE,
+	  .state = { .current = 0, .max = 2 * 10 } },
+
+	/* P_Con_INTERVAL=0 (480 ms): every SACCH block is handled */
+	{ .type = PWR_TEST_ST_SET_CTRL_INTERVAL, .ctrl_interval = 0 },
+
+	/* MS indicates high RxLev values (-50 dBm), red step is 2 dB */
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  2 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  4 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  6 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  8 },
+
+	/* MS indicates low RxLev values (-100 dBm), inc step is 4 dB */
+	{ .meas = DL_MEAS_FULL_SUB(0, 10),	.exp_txred =  4 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 10),	.exp_txred =  0 },
+
+	/* P_Con_INTERVAL=1 (960 ms): 1 out of 2 SACCH blocks is handled */
+	{ .type = PWR_TEST_ST_SET_CTRL_INTERVAL, .ctrl_interval = 1 },
+
+	/* MS indicates high RxLev values (-50 dBm), red step is 2 dB */
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  2 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  2 }, /* skipped */
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  4 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  4 }, /* skipped */
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  6 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  6 }, /* skipped */
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  8 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 60),	.exp_txred =  8 }, /* skipped */
+
+	/* P_Con_INTERVAL=2 (1920 ms): 1 out of 4 SACCH blocks is handled */
+	{ .type = PWR_TEST_ST_SET_CTRL_INTERVAL, .ctrl_interval = 2 },
+
+	/* MS indicates low RxLev values (-100 dBm), inc step is 4 dB */
+	{ .meas = DL_MEAS_FULL_SUB(0, 10),	.exp_txred =  4 },
+	{ .meas = DL_MEAS_FULL_SUB(0, 10),	.exp_txred =  4 }, /* skipped */
+	{ .meas = DL_MEAS_FULL_SUB(0, 10),	.exp_txred =  4 }, /* skipped */
+	{ .meas = DL_MEAS_FULL_SUB(0, 10),	.exp_txred =  4 }, /* skipped */
+	{ .meas = DL_MEAS_FULL_SUB(0, 10),	.exp_txred =  0 },
+};
+
 /* Verify that small deviations from the target do not trigger any changes. */
 static const struct power_test_step TC_rxlev_hyst[] = {
 	/* Initial state: 16 dB, up to 20 dB */
@@ -488,6 +539,7 @@
 	exec_test(TC_dtxd_mode);
 	exec_test(TC_rxqual_ber);
 	exec_test(TC_inval_dummy);
+	exec_test(TC_ctrl_interval);
 
 	exec_test(TC_rxlev_hyst);
 	exec_test(TC_rxlev_pf_ewma);
diff --git a/tests/power/bs_power_loop_test.err b/tests/power/bs_power_loop_test.err
index 7fcfb1e..c4726b1 100644
--- a/tests/power/bs_power_loop_test.err
+++ b/tests/power/bs_power_loop_test.err
@@ -135,6 +135,37 @@
 (bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 16 dB (maximum 20 dB, suggested delta 0 dB, RxLev current 30 (-80 dBm), thresholds 30 .. 30)
 (bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0), DTx is disabled => using FULL
 (bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 16 dB (maximum 20 dB, suggested delta 0 dB, RxLev current 30 (-80 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 0 -> 2 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 2 -> 4 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 6 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 6 -> 8 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 8 -> 4 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 0 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 0 -> 2 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 2 -> 4 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 6 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 6 -> 8 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 8 -> 4 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30)
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL
+(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 0 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30)
 (bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(31), RXQUAL-FULL(0), RXLEV-SUB(31), RXQUAL-SUB(0), DTx is disabled => using FULL
 (bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 12 -> 13 dB (maximum 16 dB, suggested delta 1 dB, RxLev current 31 (-79 dBm), thresholds 30 .. 30)
 (bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(28), RXQUAL-FULL(0), RXLEV-SUB(28), RXQUAL-SUB(0), DTx is disabled => using FULL
diff --git a/tests/power/bs_power_loop_test.ok b/tests/power/bs_power_loop_test.ok
index 4371c9d..2c12392 100644
--- a/tests/power/bs_power_loop_test.ok
+++ b/tests/power/bs_power_loop_test.ok
@@ -268,6 +268,70 @@
 #07 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16)
 Test case verdict: SUCCESS
 
+Starting test case 'TC_ctrl_interval'
+#00 exec_power_step() <- State (re)set (current 0 dB, max 20 dB)
+#01 exec_power_step() <- (Re)set power control interval: 0 -> 0
+#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#02 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 2 (expected 2)
+#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#03 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 4 (expected 4)
+#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#04 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 6 (expected 6)
+#05 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#05 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#05 lchan_bs_pwr_ctrl() -> BS power reduction: 6 -> 8 (expected 8)
+#06 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0)
+#06 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#06 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 4 (expected 4)
+#07 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0)
+#07 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#07 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 0 (expected 0)
+#08 exec_power_step() <- (Re)set power control interval: 0 -> 1
+#09 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#09 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#09 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 2 (expected 2)
+#10 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#10 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#10 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 2 (expected 2)
+#11 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#11 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#11 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 4 (expected 4)
+#12 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#12 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#12 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4)
+#13 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#13 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#13 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 6 (expected 6)
+#14 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#14 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#14 lchan_bs_pwr_ctrl() -> BS power reduction: 6 -> 6 (expected 6)
+#15 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#15 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#15 lchan_bs_pwr_ctrl() -> BS power reduction: 6 -> 8 (expected 8)
+#16 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0)
+#16 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#16 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 8 (expected 8)
+#17 exec_power_step() <- (Re)set power control interval: 1 -> 2
+#18 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0)
+#18 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#18 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 4 (expected 4)
+#19 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0)
+#19 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#19 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4)
+#20 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0)
+#20 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#20 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4)
+#21 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0)
+#21 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#21 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4)
+#22 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0)
+#22 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+#22 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 0 (expected 0)
+Test case verdict: SUCCESS
+
 Starting test case 'TC_rxlev_hyst'
 #00 exec_power_step() <- State (re)set (current 12 dB, max 16 dB)
 #01 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(31), RXQUAL-FULL(0), RXLEV-SUB(31), RXQUAL-SUB(0)
diff --git a/tests/power/ms_power_loop_test.c b/tests/power/ms_power_loop_test.c
index eb0e3e9..c58812b 100644
--- a/tests/power/ms_power_loop_test.c
+++ b/tests/power/ms_power_loop_test.c
@@ -248,6 +248,71 @@
 	apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 10, 1, 13);
 }
 
+static void test_power_ctrl_interval(void)
+{
+	struct gsm_lchan *lchan;
+	unsigned int i, j;
+
+	init_test(__func__);
+	lchan = &g_trx->ts[0].lchan[0];
+
+	lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 26);
+	OSMO_ASSERT(lchan->ms_power_ctrl.max == 2);
+
+	static const int script[][8][3] = {
+		{ /* P_Con_INTERVAL=0 (480 ms) */
+			/* { UL RxLev, expected rc, expected Tx power level } */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	13 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	11 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 9 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 7 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 5 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 3 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 2 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 2 },
+		},
+		{ /* P_Con_INTERVAL=1 (960 ms) */
+			/* { UL RxLev, expected rc, expected Tx power level } */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	13 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	13 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	11 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	11 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 9 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	 9 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	 7 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	 7 }, /* skipped */
+		},
+		{ /* P_Con_INTERVAL=2 (1920 ms) */
+			/* { UL RxLev, expected rc, expected Tx power level } */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	13 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	13 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	13 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	13 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	1,	11 },
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	11 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	11 }, /* skipped */
+			{ PWR_TEST_RXLEV_TARGET_DBM - 15,	0,	11 }, /* skipped */
+		},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(script); i++) {
+		lchan->ms_power_ctrl.current = ms_pwr_ctl_lvl(GSM_BAND_1800, 0);
+		OSMO_ASSERT(lchan->ms_power_ctrl.current == 15);
+
+		/* Set the corresponding power control interval */
+		printf("%s(): power control interval is now %u\n", __func__, i);
+		lchan->ms_dpc_params.ctrl_interval = i;
+
+		for (j = 0; j < ARRAY_SIZE(script[i]); j++) {
+			apply_power_test(lchan, script[i][j][0],  /* UL RxLev */
+						script[i][j][1],  /* expected rc */
+						script[i][j][2]); /* expected Tx power level */
+		}
+
+		printf("\n");
+	}
+}
+
 int main(int argc, char **argv)
 {
 	printf("Testing power loop...\n");
@@ -264,6 +329,7 @@
 	test_power_loop();
 	test_pf_algo_ewma();
 	test_power_hysteresis();
+	test_power_ctrl_interval();
 
 	printf("Power loop test OK\n");
 
diff --git a/tests/power/ms_power_loop_test.err b/tests/power/ms_power_loop_test.err
index 7f8779c..ae8ad03 100644
--- a/tests/power/ms_power_loop_test.err
+++ b/tests/power/ms_power_loop_test.err
@@ -35,3 +35,17 @@
 (bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -70 dBm, rx-target -75 dBm)
 (bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -80 dBm, rx-target -75 dBm)
 (bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -85 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 7 (16 dBm) to 5, 20 dBm (rx-ms-pwr-lvl 7, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 5 (20 dBm) to 3, 24 dBm (rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 3 (24 dBm) to 2, 26 dBm (rx-ms-pwr-lvl 3, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 2, 26 dBm (rx-ms-pwr-lvl 2, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)
diff --git a/tests/power/ms_power_loop_test.ok b/tests/power/ms_power_loop_test.ok
index 4293d28..5fea474 100644
--- a/tests/power/ms_power_loop_test.ok
+++ b/tests/power/ms_power_loop_test.ok
@@ -88,4 +88,60 @@
 	MS current power 15 -> 15 (expected 15)
 lchan_ms_pwr_ctrl(RxLvl=-85 dBm) returns 1 (expected 1)
 	MS current power 15 -> 13 (expected 13)
+
+Starting test case 'test_power_ctrl_interval'
+test_power_ctrl_interval(): power control interval is now 0
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 15 -> 13 (expected 13)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 13 -> 11 (expected 11)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 11 -> 9 (expected 9)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 9 -> 7 (expected 7)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 7 -> 5 (expected 5)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 5 -> 3 (expected 3)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 3 -> 2 (expected 2)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 1)
+	MS current power 2 -> 2 (expected 2)
+
+test_power_ctrl_interval(): power control interval is now 1
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 15 -> 13 (expected 13)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 13 -> 13 (expected 13)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 13 -> 11 (expected 11)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 11 -> 11 (expected 11)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 11 -> 9 (expected 9)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 9 -> 9 (expected 9)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 9 -> 7 (expected 7)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 7 -> 7 (expected 7)
+
+test_power_ctrl_interval(): power control interval is now 2
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 15 -> 13 (expected 13)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 13 -> 13 (expected 13)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 13 -> 13 (expected 13)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 13 -> 13 (expected 13)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 13 -> 11 (expected 11)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 11 -> 11 (expected 11)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 11 -> 11 (expected 11)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)
+	MS current power 11 -> 11 (expected 11)
+
 Power loop test OK

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

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Ibf9956b2c6d829b38e9fda7d1f29790036219f42
Gerrit-Change-Number: 22781
Gerrit-PatchSet: 3
Gerrit-Owner: fixeria <vyanitskiy at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy at sysmocom.de>
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/20210208/739bb6d6/attachment.htm>


More information about the gerrit-log mailing list