Change in osmo-bts[master]: power_control: implement EWMA based Uplink power filtering

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
Thu Oct 15 08:20:24 UTC 2020


fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bts/+/20657 )


Change subject: power_control: implement EWMA based Uplink power filtering
......................................................................

power_control: implement EWMA based Uplink power filtering

So far the Uplink power control loop did not filter the Uplink RSSI
measurements (reported by the BTS) at all.  The lack of filtering
makes our implementation too quick on the trigger, so in the real
deployments there will be unneeded Tx power oscillations.

In order to reduce this effect, let's implement a very simple EWMA
(also known as Single Pole IIR) filtering that is defined as follows:

  Avg[n] = a * Pwr[n] + (1 - a) * Avg[n - 1]

where parameter 'a' determines how much weight of the latest UL RSSI
measurement result 'Pwr[n]' carries vs the weight of the average
'Avg[n - 1]'.  The value of 'a' is usually a float in range 0 .. 1, so:

  - value 0.5 gives equal weight to both 'Pwr[n]' and 'Avg[n - 1]';
  - value 1.0 means no filtering at all (pass through);
  - value 0.0 makes no sense.

This formula was further optimized with the use of '+=' operator.
The floating point math was also eliminated by scaling everything
up (by 100).  For more details, see:

https://en.wikipedia.org/wiki/Moving_average
https://en.wikipedia.org/wiki/Low-pass_filter#Simple_infinite_impulse_response_filter
https://tomroelandts.com/articles/low-pass-single-pole-iir-filter

The EWMA filtering is *not* enabled by default, but can be enabled,
disabled, or (re-)configured over the VTY at any time:

  ! Enable EWMA smoothing with the given parameters
  uplink-power-filtering algo ewma beta <1-99>

  ! Completely disable filtering
  no uplink-power-filtering

Note that the VTY command expects 'beta' instead of 'alpha':

  alpha = (100 - beta)

and the value must be in %.  This is done for simplicity:

  1% means lowest smoothing,
  99% means highest smoothing.

Let's say we have EWMA filtering enabled with alpha = 0.4, and get
-98 dBm on the input, while the last output value was -60 dBm.
The new output would be:

  Avg[n] = 0.4 * Pwr[n] + 0.6 * Avg[n - 1]
  Avg[n] = (0.4 * -98) + (0.6 * -60)
  Avg[n] = -75.2 => around -75

Of course, this is not a silver bullet, but better than nothing.

Change-Id: Ib6dcadbf14ef59696c6a546bd323bda92d399f17
Related: SYS#4916
---
M include/osmo-bts/bts.h
M include/osmo-bts/gsm_data.h
M src/common/bts.c
M src/common/power_control.c
M src/common/vty.c
M tests/power/power_test.c
M tests/power/power_test.err
M tests/power/power_test.ok
8 files changed, 236 insertions(+), 3 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/57/20657/1

diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 4e496b5..cf69b43 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -95,6 +95,12 @@
 	struct smscb_msg *default_msg; /* default broadcast message; NULL if none */
 };
 
+/* Tx power filtering algorithm */
+enum ms_ul_pf_algo {
+	MS_UL_PF_ALGO_NONE = 0,
+	MS_UL_PF_ALGO_EWMA,
+};
+
 /* One BTS */
 struct gsm_bts {
 	/* list header in net->bts_list */
@@ -289,8 +295,23 @@
 		bool vty_override;	/* OML value overridden by VTY */
 	} radio_link_timeout;
 
+	/* TODO: move it to bts->ul_power_ctrl struct */
 	int ul_power_target;		/* Uplink Rx power target */
 
+	/* Uplink power control */
+	struct {
+		/* UL RSSI filtering algorithm */
+		enum ms_ul_pf_algo pf_algo;
+		/* (Optional) filtering parameters */
+		union {
+			/* Exponentially Weighted Moving Average */
+			struct {
+				/* Smoothing factor: higher the value - less smoothing */
+				uint8_t alpha; /* 1 .. 99 (in %) */
+			} ewma;
+		} pf;
+	} ul_power_ctrl;
+
 	/* used by the sysmoBTS to adjust band */
 	uint8_t auto_band;
 
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index c6fe609..1c1c5d4 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -286,6 +286,9 @@
 		uint8_t current;
 		uint8_t max;
 		bool fixed;
+
+		/* Scaled up (100 times) average UL RSSI */
+		int avg100_ul_rssi;
 	} ms_power_ctrl;
 
 	/* BTS power reduction (in dB) */
diff --git a/src/common/bts.c b/src/common/bts.c
index 5890c1a..4d7a5d9 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -303,6 +303,7 @@
 	/* configurable via VTY */
 	bts->paging_state = paging_init(bts, 200, 0);
 	bts->ul_power_target = -75;	/* dBm default */
+	bts->ul_power_ctrl.pf_algo = MS_UL_PF_ALGO_NONE;
 	bts->rtp_jitter_adaptive = false;
 	bts->rtp_port_range_start = 16384;
 	bts->rtp_port_range_end = 17407;
diff --git a/src/common/power_control.c b/src/common/power_control.c
index d36f157..4798f4f 100644
--- a/src/common/power_control.c
+++ b/src/common/power_control.c
@@ -1,6 +1,7 @@
 /* MS Power Control Loop L1 */
 
 /* (C) 2014 by Holger Hans Peter Freyther
+ * Contributions by sysmocom - s.m.f.c. GmbH <info at sysmocom.de>
  *
  * All Rights Reserved
  *
@@ -36,6 +37,60 @@
 #define MS_RAISE_MAX_DB 4
 #define MS_LOWER_MAX_DB 8
 
+/* We don't want to deal with floating point, so we scale up */
+#define EWMA_SCALE_FACTOR 100
+
+/* Base Low-Pass Single-Pole IIR Filter (EWMA) formula:
+ *
+ *   Avg[n] = a * Pwr[n] + (1 - a) * Avg[n - 1]
+ *
+ * where parameter 'a' determines how much weight of the latest UL RSSI measurement
+ * result 'Pwr[n]' carries vs the weight of the average 'Avg[n - 1]'.  The value of
+ * 'a' is usually a float in range 0 .. 1, so:
+ *
+ *  - value 0.5 gives equal weight to both 'Pwr[n]' and 'Avg[n - 1]';
+ *  - value 1.0 means no filtering at all (pass through);
+ *  - value 0.0 makes no sense.
+ *
+ * Further optimization:
+ *
+ *   Avg[n] = a * Pwr[n] + Avg[n - 1] - a * Avg[n - 1]
+ *   ^^^^^^                ^^^^^^^^^^
+ *
+ * a) this can be implemented in C using '+=' operator:
+ *
+ *   Avg += a * Pwr - a * Avg
+ *   Avg += a * (Pwr - Avg)
+ *
+ * b) everything is scaled up by 100 to avoid floating point stuff:
+ *
+ *   Avg100 += A * (Pwr - Avg)
+ *
+ * where 'Avg100' is 'Avg * 100' and 'A' is 'a * 100'.
+ *
+ * For more details, see:
+ *
+ *   https://en.wikipedia.org/wiki/Moving_average
+ *   https://en.wikipedia.org/wiki/Low-pass_filter#Simple_infinite_impulse_response_filter
+ *   https://tomroelandts.com/articles/low-pass-single-pole-iir-filter
+ */
+static int8_t lchan_ul_pf_ewma(const struct gsm_bts *bts,
+			       struct gsm_lchan *lchan,
+			       const int8_t Pwr)
+{
+	const uint8_t A = bts->ul_power_ctrl.pf.ewma.alpha;
+	int *Avg100 = &lchan->ms_power_ctrl.avg100_ul_rssi;
+
+	/* We don't have 'Avg[n - 1]' if this is the first run */
+	if (lchan->meas.res_nr == 0) {
+		*Avg100 = Pwr * EWMA_SCALE_FACTOR;
+		return Pwr;
+	}
+
+	*Avg100 += A * (Pwr - *Avg100 / EWMA_SCALE_FACTOR);
+	return *Avg100 / EWMA_SCALE_FACTOR;
+}
+
  /*! compute the new MS POWER LEVEL communicated to the MS and store it in lchan.
   *  \param lchan logical channel for which to compute (and in which to store) new power value.
   *  \param[in] ms_power_lvl MS Power Level received from Uplink L1 SACCH Header in SACCH block.
@@ -51,6 +106,7 @@
 	enum gsm_band band = bts->band;
 	int8_t new_power_lvl; /* TS 05.05 power level */
 	int8_t ms_dbm, new_dbm, current_dbm, bsc_max_dbm;
+	int8_t avg_ul_rssi_dbm;
 
 	if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx))
 		return 0;
@@ -72,9 +128,20 @@
 		return 0;
 	}
 
+	/* Filter UL RSSI to reduce unnecessary Tx power oscillations */
+	switch (bts->ul_power_ctrl.pf_algo) {
+	case MS_UL_PF_ALGO_EWMA:
+		avg_ul_rssi_dbm = lchan_ul_pf_ewma(bts, lchan, ul_rssi_dbm);
+		break;
+	case MS_UL_PF_ALGO_NONE:
+	default:
+		/* No filtering (pass through) */
+		avg_ul_rssi_dbm = ul_rssi_dbm;
+	}
+
 	/* How many dBs measured power should be increased (+) or decreased (-)
 	   to reach expected power. */
-	diff = bts->ul_power_target - ul_rssi_dbm;
+	diff = bts->ul_power_target - avg_ul_rssi_dbm;
 
 	/* don't ever change more than MS_{LOWER,RAISE}_MAX_DBM during one loop
 	   iteration, i.e. reduce the speed at which the MS transmit power can
@@ -108,7 +175,7 @@
 			  "(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm)\n",
 			  new_power_lvl, new_dbm,
 			  ms_power_lvl, lchan->ms_power_ctrl.max,
-			  ul_rssi_dbm, bts->ul_power_target);
+			  avg_ul_rssi_dbm, bts->ul_power_target);
 		return 0;
 	}
 
@@ -118,7 +185,7 @@
 		  (new_dbm > current_dbm) ? "Raising" : "Lowering",
 		  lchan->ms_power_ctrl.current, current_dbm, new_power_lvl, new_dbm,
 		  ms_power_lvl, lchan->ms_power_ctrl.max,
-		  ul_rssi_dbm, bts->ul_power_target);
+		  avg_ul_rssi_dbm, bts->ul_power_target);
 
 	/* store the resulting new MS power level in the lchan */
 	lchan->ms_power_ctrl.current = new_power_lvl;
diff --git a/src/common/vty.c b/src/common/vty.c
index 534b632..00fd474 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -256,6 +256,18 @@
 	vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(bts->paging_state),
 		VTY_NEWLINE);
 	vty_out(vty, " uplink-power-target %d%s", bts->ul_power_target, VTY_NEWLINE);
+
+	/* MS Tx power filtering algorithm and parameters */
+	switch (bts->ul_power_ctrl.pf_algo) {
+	case MS_UL_PF_ALGO_EWMA:
+		vty_out(vty, " uplink-power-filtering algo ewma beta %u%s",
+			100 - bts->ul_power_ctrl.pf.ewma.alpha, VTY_NEWLINE);
+		break;
+	case MS_UL_PF_ALGO_NONE:
+	default:
+		break;
+	}
+
 	if (bts->agch_queue.thresh_level != GSM_BTS_AGCH_QUEUE_THRESH_LEVEL_DEFAULT
 		 || bts->agch_queue.low_level != GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT
 		 || bts->agch_queue.high_level != GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT)
@@ -615,6 +627,37 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN_ATTR(cfg_no_bts_ul_power_filter,
+	   cfg_bts_no_ul_power_filter_cmd,
+	   "no uplink-power-filtering",
+	   NO_STR "Disable filtering for uplink power control loop\n",
+	   CMD_ATTR_IMMEDIATE)
+{
+	struct gsm_bts *bts = vty->index;
+
+	bts->ul_power_ctrl.pf_algo = MS_UL_PF_ALGO_NONE;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_bts_ul_power_filter_ewma,
+	   cfg_bts_ul_power_filter_ewma_cmd,
+	   "uplink-power-filtering algo ewma beta <1-99>",
+	   "Configure filtering for uplink power control loop\n"
+	   "Select the filtering algorithm\n"
+	   "Exponentially Weighted Moving Average (EWMA)\n"
+	   "Smoothing factor (in %%): beta = (100 - alpha)\n"
+	   "1%% - lowest smoothing, 99%% - highest smoothing\n",
+	   CMD_ATTR_IMMEDIATE)
+{
+	struct gsm_bts *bts = vty->index;
+
+	bts->ul_power_ctrl.pf_algo = MS_UL_PF_ALGO_EWMA;
+	bts->ul_power_ctrl.pf.ewma.alpha = 100 - atoi(argv[0]);
+
+	return CMD_SUCCESS;
+}
+
 DEFUN_ATTR(cfg_bts_min_qual_rach, cfg_bts_min_qual_rach_cmd,
 	   "min-qual-rach <-100-100>",
 	   "Set the minimum link quality level of Access Bursts to be accepted\n"
@@ -1805,6 +1848,8 @@
 	install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_default_cmd);
 	install_element(BTS_NODE, &cfg_bts_agch_queue_mgmt_params_cmd);
 	install_element(BTS_NODE, &cfg_bts_ul_power_target_cmd);
+	install_element(BTS_NODE, &cfg_bts_no_ul_power_filter_cmd);
+	install_element(BTS_NODE, &cfg_bts_ul_power_filter_ewma_cmd);
 	install_element(BTS_NODE, &cfg_bts_min_qual_rach_cmd);
 	install_element(BTS_NODE, &cfg_bts_min_qual_norm_cmd);
 	install_element(BTS_NODE, &cfg_bts_max_ber_rach_cmd);
diff --git a/tests/power/power_test.c b/tests/power/power_test.c
index c3bfdf9..eff722a 100644
--- a/tests/power/power_test.c
+++ b/tests/power/power_test.c
@@ -61,6 +61,9 @@
 	old = lchan->ms_power_ctrl.current;
 	ret = lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, rxlev);
 
+	/* Keep the measurement counter updated */
+	lchan->meas.res_nr++;
+
 	printf("lchan_ms_pwr_ctrl(RxLvl=%d dBm) returns %d (expected %d)\n",
 	       rxlev, ret, exp_ret);
 	printf("\tMS current power %u -> %u (expected %u)\n",
@@ -140,6 +143,68 @@
 	apply_power_test(lchan, -40, 1, 15);
 }
 
+static void test_pf_algo_ewma(void)
+{
+	struct gsm_lchan *lchan;
+	const int *avg100;
+
+	init_test(__func__);
+	lchan = &g_trx->ts[0].lchan[0];
+	avg100 = &lchan->ms_power_ctrl.avg100_ul_rssi;
+
+	g_bts->ul_power_ctrl.pf_algo = MS_UL_PF_ALGO_EWMA;
+	g_bts->ul_power_ctrl.pf.ewma.alpha = 20; /* 80% smoothing */
+
+	lchan->ms_power_ctrl.current = ms_pwr_ctl_lvl(GSM_BAND_1800, 0);
+	OSMO_ASSERT(lchan->ms_power_ctrl.current == 15);
+	lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 26);
+	OSMO_ASSERT(lchan->ms_power_ctrl.max == 2);
+
+#define CHECK_UL_RSSI_AVG100(exp) \
+	printf("\tAvg[t] is %2.2f dBm (expected %2.2f dBm)\n", \
+	       ((float) *avg100) / 100, exp);
+
+	/* UL RSSI remains constant => no UL power change */
+	apply_power_test(lchan, -75, 0, 15);
+	CHECK_UL_RSSI_AVG100(-75.00);
+
+	/* Avg[t] = (0.2 * -90) + (0.8 * -75) = -78.0 dBm */
+	apply_power_test(lchan, -90, 1, 13);
+	CHECK_UL_RSSI_AVG100(-78.00);
+
+	/* Avg[t] = (0.2 * -90) + (0.8 * -78) = -80.4 dBm */
+	apply_power_test(lchan, -90, 1, 11);
+	CHECK_UL_RSSI_AVG100(-80.40);
+
+	/* Avg[t] = (0.2 * -70) + (0.8 * -80.4) = -78.32 dBm,
+	 * but due to up-/down-scaling artefacts we get the following:
+	 *   Avg100[t] = Avg100[t - 1] + A * (Pwr - Avg[t] / 100)
+	 *   Avg100[t] = -8040 + 20 * (-70 - (-8040 / 100))
+	 *   Avg100[t] = -8040 + 20 * (-70 - (-8040 / 100))
+	 *   Avg100[t] = -8040 + 20 * (-70 + 80)
+	 *   Avg100[t] = -8040 + 200 = -7840
+	 *   Avg[t] = -7840 / 100 = -78.4 */
+	apply_power_test(lchan, -70, 1, 9);
+	CHECK_UL_RSSI_AVG100(-78.40);
+
+	g_bts->ul_power_ctrl.pf.ewma.alpha = 70; /* 30% smoothing */
+	lchan->ms_power_ctrl.current = 15;
+	lchan->meas.res_nr = 0;
+
+	/* This is the first sample, the filter outputs it as-is */
+	apply_power_test(lchan, -50, 0, 15);
+	CHECK_UL_RSSI_AVG100(-50.00);
+
+	/* Avg[t] = (0.7 * -50) + (0.3 * -50) = -50.0 dBm */
+	apply_power_test(lchan, -50, 0, 15);
+	CHECK_UL_RSSI_AVG100(-50.0);
+
+	/* Simulate SACCH block loss (-110 dBm):
+	 * Avg[t] = (0.7 * -110) + (0.3 * -50) = -92.0 dBm */
+	apply_power_test(lchan, -110, 1, 13);
+	CHECK_UL_RSSI_AVG100(-92.0);
+}
+
 int main(int argc, char **argv)
 {
 	printf("Testing power loop...\n");
@@ -154,6 +219,7 @@
 	log_set_use_color(osmo_stderr_target, 0);
 
 	test_power_loop();
+	test_pf_algo_ewma();
 
 	printf("Power loop test OK\n");
 
diff --git a/tests/power/power_test.err b/tests/power/power_test.err
index e4d821a..786f2a7 100644
--- a/tests/power/power_test.err
+++ b/tests/power/power_test.err
@@ -21,3 +21,10 @@
 (bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 10 (10 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 10, max-ms-pwr-lvl 29, rx-current -77 dBm, rx-target -75 dBm)
 (bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 9 (12 dBm) to 14, 2 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 14, rx-current -73 dBm, rx-target -75 dBm)
 (bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 14 (2 dBm) to 15, 0 dBm (rx-ms-pwr-lvl 14, max-ms-pwr-lvl 0, rx-current -40 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 -75 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 3 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -78 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 -80 dBm, rx-target -75 dBm)
+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 11 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -78 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 -50 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 -50 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 -92 dBm, rx-target -75 dBm)
diff --git a/tests/power/power_test.ok b/tests/power/power_test.ok
index 6b7a0d4..25551d8 100644
--- a/tests/power/power_test.ok
+++ b/tests/power/power_test.ok
@@ -49,4 +49,27 @@
 	MS current power 14 -> 14 (expected 14)
 lchan_ms_pwr_ctrl(RxLvl=-40 dBm) returns 1 (expected 1)
 	MS current power 14 -> 15 (expected 15)
+
+Starting test case 'test_pf_algo_ewma'
+lchan_ms_pwr_ctrl(RxLvl=-75 dBm) returns 0 (expected 0)
+	MS current power 15 -> 15 (expected 15)
+	Avg[t] is -75.00 dBm (expected -75.00 dBm)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 15 -> 13 (expected 13)
+	Avg[t] is -78.00 dBm (expected -78.00 dBm)
+lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1)
+	MS current power 13 -> 11 (expected 11)
+	Avg[t] is -80.40 dBm (expected -80.40 dBm)
+lchan_ms_pwr_ctrl(RxLvl=-70 dBm) returns 1 (expected 1)
+	MS current power 11 -> 9 (expected 9)
+	Avg[t] is -78.40 dBm (expected -78.40 dBm)
+lchan_ms_pwr_ctrl(RxLvl=-50 dBm) returns 0 (expected 0)
+	MS current power 15 -> 15 (expected 15)
+	Avg[t] is -50.00 dBm (expected -50.00 dBm)
+lchan_ms_pwr_ctrl(RxLvl=-50 dBm) returns 0 (expected 0)
+	MS current power 15 -> 15 (expected 15)
+	Avg[t] is -50.00 dBm (expected -50.00 dBm)
+lchan_ms_pwr_ctrl(RxLvl=-110 dBm) returns 1 (expected 1)
+	MS current power 15 -> 13 (expected 13)
+	Avg[t] is -92.00 dBm (expected -92.00 dBm)
 Power loop test OK

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

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Ib6dcadbf14ef59696c6a546bd323bda92d399f17
Gerrit-Change-Number: 20657
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201015/fa046d07/attachment.htm>


More information about the gerrit-log mailing list