Change in osmo-bsc[master]: WIP: Support set up of C/I parameters for osmo-bts MS Power Control Loop

pespin gerrit-no-reply at lists.osmocom.org
Tue Aug 31 19:19:51 UTC 2021


pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/25298 )


Change subject: WIP: Support set up of C/I parameters for osmo-bts MS Power Control Loop
......................................................................

WIP: Support set up of C/I parameters for osmo-bts MS Power Control Loop

This commit extends existing VTY and RSL infrastructure to configure and
manage MS Power Parameters used in MS Power Control loop, by adding
support to set up Carrier-to-Interference (CI) parameters.

Using C/I instead of existing RxQual is preferred due to extended
granularity of C/I (bigger range than RxQual's 0-7).
Furthermore, existing literature (such as "GSM/EDGE: Evolution and Performance"
Table 10.3) provides detailed information about expected target values,
even different values for different channel types. Hence, it was decided
to support setting different MS Power Parameters for different channel
types.

These MS Power Parameters are Osmocom specific, ie. supported only by
newish versions of osmo-bts. Older versions of osmo-bts should ignore
the new IEs added just fine. The new IEs containing the MS POwer
Parameters are not send for non osmo-bts BTSs, hence this commit is
secure with regards to running  osmo-bsc against an ip.access BTS such
as nanoBTS.

TODO: Update user manual!!!!

Related: SYS#4917
Change-Id: I7e76ec47b323d469f777624b74b08752d1f5584f
---
M doc/manuals/chapters/power_control.adoc
M include/osmocom/bsc/gsm_data.h
M src/osmo-bsc/bts_ipaccess_nanobts.c
M src/osmo-bsc/bts_vty.c
M src/osmo-bsc/gsm_data.c
M tests/power_ctrl.vty
6 files changed, 446 insertions(+), 35 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/98/25298/1

diff --git a/doc/manuals/chapters/power_control.adoc b/doc/manuals/chapters/power_control.adoc
index 4d212f1..7b3272d 100644
--- a/doc/manuals/chapters/power_control.adoc
+++ b/doc/manuals/chapters/power_control.adoc
@@ -106,6 +106,8 @@
 
 ==== Power control mode
 
+# THIS SECTION NEEDS UPDATE WHEN ADDING C/I SUPPORT!
+
 Three power control modes exist:
 
 ----
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index db0f249..234c814 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -1343,6 +1343,13 @@
 	/* Measurement averaging parameters for RxLev & RxQual */
 	struct gsm_power_ctrl_meas_params rxqual_meas;
 	struct gsm_power_ctrl_meas_params rxlev_meas;
+	/* Measurement averaging parameters for C/I: */
+	struct gsm_power_ctrl_meas_params ci_fr_meas;
+	struct gsm_power_ctrl_meas_params ci_hr_meas;
+	struct gsm_power_ctrl_meas_params ci_amr_fr_meas;
+	struct gsm_power_ctrl_meas_params ci_amr_hr_meas;
+	struct gsm_power_ctrl_meas_params ci_sdcch_meas;
+	struct gsm_power_ctrl_meas_params ci_gprs_meas;
 };
 
 extern const struct gsm_power_ctrl_params power_ctrl_params_def;
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c
index 8d2908f..d26f13f 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts.c
@@ -867,10 +867,65 @@
 	*ie_len = msg->tail - (ie_len + 1);
 }
 
+static void enc_osmo_meas_proc_params(struct msgb *msg, const struct gsm_power_ctrl_params *mp)
+{
+	struct osmo_preproc_ave_cfg *ave_cfg;
+	uint8_t *ie_len;
+
+	/* No averaging => no Measurement Averaging parameters */
+	if (mp->ci_fr_meas.algo == GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE &&
+	    mp->ci_hr_meas.algo == GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE &&
+	    mp->ci_amr_fr_meas.algo == GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE &&
+	    mp->ci_amr_hr_meas.algo == GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE &&
+	    mp->ci_sdcch_meas.algo == GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE &&
+	    mp->ci_gprs_meas.algo == GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE)
+		return;
+
+	/* (TLV) Measurement Averaging parameters for RxLev/RxQual */
+	ie_len = msgb_tl_put(msg, RSL_IPAC_EIE_OSMO_MEAS_AVG_CFG);
+
+	ave_cfg = (struct osmo_preproc_ave_cfg *) msgb_put(msg, sizeof(*ave_cfg));
+
+#define ENC_PROC(PARAMS, TO, TYPE) do { \
+	(TO)->TYPE.ave_enabled = (PARAMS)->TYPE##_meas.algo != GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE; \
+	if ((TO)->TYPE.ave_enabled) { \
+		/* H_REQAVE and H_REQT */ \
+		(TO)->TYPE.h_reqave = (PARAMS)->TYPE##_meas.h_reqave & 0x1f; \
+		(TO)->TYPE.h_reqt = (PARAMS)->TYPE##_meas.h_reqt & 0x1f; \
+		/* Averaging method and parameters */ \
+		(TO)->TYPE.ave_method = ((PARAMS)->TYPE##_meas.algo - 1) & 0x07; \
+		switch ((PARAMS)->TYPE##_meas.algo) { \
+		case GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA: \
+			msgb_v_put(msg, (PARAMS)->TYPE##_meas.ewma.alpha); \
+			break; \
+		case GSM_PWR_CTRL_MEAS_AVG_ALGO_WEIGHTED: \
+		case GSM_PWR_CTRL_MEAS_AVG_ALGO_MOD_MEDIAN: \
+			/* FIXME: unknown format */ \
+			break; \
+		case GSM_PWR_CTRL_MEAS_AVG_ALGO_UNWEIGHTED: \
+		case GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE: \
+			/* No parameters here */ \
+			break; \
+		} \
+	} \
+	} while (0)
+	ENC_PROC(mp, ave_cfg, ci_fr);
+	ENC_PROC(mp, ave_cfg, ci_hr);
+	ENC_PROC(mp, ave_cfg, ci_amr_fr);
+	ENC_PROC(mp, ave_cfg, ci_amr_hr);
+	ENC_PROC(mp, ave_cfg, ci_sdcch);
+	ENC_PROC(mp, ave_cfg, ci_gprs);
+#undef ENC_PROC
+
+	/* Update length part of the containing IE */
+	*ie_len = msg->tail - (ie_len + 1);
+}
+
 static void enc_power_params(struct msgb *msg, const struct gsm_power_ctrl_params *cp)
 {
 	struct ipac_preproc_pc_comp *thresh_comp;
 	struct ipac_preproc_pc_thresh *thresh;
+	bool add_ci_ext;
 
 	/* These parameters are valid for dynamic mode only */
 	OSMO_ASSERT(cp->mode == GSM_PWR_CTRL_MODE_DYN_BTS);
@@ -918,6 +973,55 @@
 	/* Change step limitations: POWER_{INC,RED}_STEP_SIZE */
 	thresh_comp->inc_step_size = cp->inc_step_size_db & 0x0f;
 	thresh_comp->red_step_size = cp->red_step_size_db & 0x0f;
+
+	if (cp->dir == GSM_PWR_CTRL_DIR_UL) {
+		const struct gsm_bts *bts = container_of(cp, struct gsm_bts, ms_power_ctrl);
+		add_ci_ext = is_osmobts(bts);
+	} else {
+		add_ci_ext = false;
+	}
+	if (add_ci_ext) {
+		struct osmo_preproc_pc_thresh *osmo_thresh;
+		struct osmo_preproc_pc_comp *osmo_thresh_comp;
+		uint8_t *ie_len;
+
+		/* (TLV) Measurement Averaging Configure (C/I) */
+		enc_osmo_meas_proc_params(msg, cp);
+
+		/* (TLV) Thresholds (C/I) */
+		ie_len = msgb_tl_put(msg, RSL_IPAC_EIE_OSMO_MS_PWR_CTL);
+		osmo_thresh = (struct osmo_preproc_pc_thresh *) msgb_put(msg, sizeof(*osmo_thresh));
+		#define ENC_THRESH_CI(TYPE) \
+			osmo_thresh->l_##TYPE = cp->TYPE##_meas.lower_thresh; \
+			osmo_thresh->u_##TYPE = cp->TYPE##_meas.upper_thresh
+		ENC_THRESH_CI(ci_fr);
+		ENC_THRESH_CI(ci_hr);
+		ENC_THRESH_CI(ci_amr_fr);
+		ENC_THRESH_CI(ci_amr_hr);
+		ENC_THRESH_CI(ci_sdcch);
+		ENC_THRESH_CI(ci_gprs);
+		#undef ENC_THRESH_CI
+		/* Update length part of the containing IE */
+		*ie_len = msg->tail - (ie_len + 1);
+
+		/* (TLV) PC Threshold Comparators (C/I) */
+		ie_len = msgb_tl_put(msg, RSL_IPAC_EIE_OSMO_PC_THRESH_COMP);
+		osmo_thresh_comp = (struct osmo_preproc_pc_comp *) msgb_put(msg, sizeof(*osmo_thresh_comp));
+		#define ENC_THRESH_CI(TYPE) \
+			osmo_thresh_comp->TYPE.lower_p = cp->TYPE##_meas.lower_cmp_p & 0x1f; \
+			osmo_thresh_comp->TYPE.lower_n = cp->TYPE##_meas.lower_cmp_n & 0x1f; \
+			osmo_thresh_comp->TYPE.upper_p = cp->TYPE##_meas.upper_cmp_p & 0x1f; \
+			osmo_thresh_comp->TYPE.upper_n = cp->TYPE##_meas.upper_cmp_n & 0x1f
+		ENC_THRESH_CI(ci_fr);
+		ENC_THRESH_CI(ci_hr);
+		ENC_THRESH_CI(ci_amr_fr);
+		ENC_THRESH_CI(ci_amr_hr);
+		ENC_THRESH_CI(ci_sdcch);
+		ENC_THRESH_CI(ci_gprs);
+		#undef ENC_THRESH_CI
+		/* Update length part of the containing IE */
+		*ie_len = msg->tail - (ie_len + 1);
+	}
 }
 
 static void add_power_params_ie(struct msgb *msg, enum abis_rsl_ie iei,
diff --git a/src/osmo-bsc/bts_vty.c b/src/osmo-bsc/bts_vty.c
index 2b7b42b..e9df22f 100644
--- a/src/osmo-bsc/bts_vty.c
+++ b/src/osmo-bsc/bts_vty.c
@@ -3000,6 +3000,8 @@
 	"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"
+#define POWER_CONTROL_MEAS_CI_DESC \
+	"C/I value (Carrier-to-Interference (dB), 0 is worst, 30 is best)\n"
 
 DEFUN_USRATTR(cfg_power_ctrl_rxlev_thresh,
 	      cfg_power_ctrl_rxlev_thresh_cmd,
@@ -3056,10 +3058,74 @@
 	return CMD_SUCCESS;
 }
 
+#define VTY_CMD_CI_TYPE "(fr-efr|hr|amr-fr|amr-hr|sdcch|gprs)"
+#define VTY_DESC_CI_TYPE \
+	"Channel Type FR/EFR\n" \
+	"Channel Type HR\n" \
+	"Channel Type AMR FR\n" \
+	"Channel Type AMR HR\n" \
+	"Channel Type SDCCH\n" \
+	"Channel Type (E)GPRS\n"
+static struct gsm_power_ctrl_meas_params *ci_thresh_by_conn_type(struct gsm_power_ctrl_params *params, const char *type)
+{
+	if (!strcmp(type, "fr-efr"))
+		return &params->ci_fr_meas;
+	if (!strcmp(type, "hr"))
+		return &params->ci_hr_meas;
+	if (!strcmp(type, "amr-fr"))
+		return &params->ci_amr_fr_meas;
+	if (!strcmp(type, "amr-hr"))
+		return &params->ci_amr_hr_meas;
+	if (!strcmp(type, "sdcch"))
+		return &params->ci_sdcch_meas;
+	if (!strcmp(type, "gprs"))
+		return &params->ci_gprs_meas;
+	OSMO_ASSERT(false);
+	return NULL;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_ci_thresh,
+	      cfg_power_ctrl_ci_thresh_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "ci-thresh " VTY_CMD_CI_TYPE " lower <0-30> upper <0-30>",
+	      "Set target C/I thresholds (for dynamic mode), only available in ms-power-control\n"
+	      VTY_DESC_CI_TYPE
+	      "Lower C/I value\n"
+	      "Lower " POWER_CONTROL_MEAS_RXQUAL_DESC
+	      "Upper C/I value\n"
+	      "Upper " POWER_CONTROL_MEAS_RXQUAL_DESC)
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	const char *type = argv[0];
+	int lower = atoi(argv[1]);
+	int upper = atoi(argv[2]);
+	struct gsm_power_ctrl_meas_params *meas_params;
+
+	if (params->dir != GSM_PWR_CTRL_DIR_UL) {
+		vty_out(vty, "%% C/I based power loop only possible in Uplink!%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (lower > upper) {
+		vty_out(vty, "%% Lower 'rxqual-rxqual' (%d) must be less than upper (%d)%s",
+			upper, lower, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	meas_params = ci_thresh_by_conn_type(params, type);
+
+	meas_params->lower_thresh = lower;
+	meas_params->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) \
+#define POWER_CONTROL_MEAS_THRESH_COMP_DESC(meas, opt_param, lp, ln, up, un) \
 	"Set " meas " threshold comparators (for dynamic mode)\n" \
+	opt_param \
 	"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
 
@@ -3068,7 +3134,7 @@
 	      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",
+	      POWER_CONTROL_MEAS_THRESH_COMP_DESC("RxLev",,
 		"P1 (default 10)\n", "N1 (default 12)\n",
 		"P2 (default 10)\n", "N2 (default 12)\n"))
 {
@@ -3103,7 +3169,7 @@
 	      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",
+	      POWER_CONTROL_MEAS_THRESH_COMP_DESC("RxQual",,
 		"P3 (default 5)\n", "N3 (default 7)\n",
 		"P4 (default 15)\n", "N4 (default 18)\n"))
 {
@@ -3133,6 +3199,45 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN_USRATTR(cfg_power_ctrl_ci_thresh_comp,
+	      cfg_power_ctrl_ci_thresh_comp_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      POWER_CONTROL_MEAS_THRESH_COMP_CMD("ci-thresh-comp " VTY_CMD_CI_TYPE),
+	      POWER_CONTROL_MEAS_THRESH_COMP_DESC("Carrier-to_interference (C/I)",
+		VTY_DESC_CI_TYPE,
+		"Lower P (default 5)\n", "Upper N (default 7)\n",
+		"Upper P (default 15)\n", "Upper N (default 18)\n"))
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	struct gsm_power_ctrl_meas_params *meas_params;
+	int lower_cmp_p = atoi(argv[1]);
+	int lower_cmp_n = atoi(argv[2]);
+	int upper_cmp_p = atoi(argv[3]);
+	int upper_cmp_n = atoi(argv[4]);
+
+	if (lower_cmp_p > lower_cmp_n) {
+		vty_out(vty, "%% Lower C/I P %d must be less than N %d%s",
+			lower_cmp_p, lower_cmp_n, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (upper_cmp_p > upper_cmp_n) {
+		vty_out(vty, "%% Upper C/I P %d must be less than N %d%s",
+			lower_cmp_p, lower_cmp_n, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	meas_params = ci_thresh_by_conn_type(params, argv[0]);
+
+	meas_params->lower_cmp_p = lower_cmp_p;
+	meas_params->lower_cmp_n = lower_cmp_n;
+	meas_params->upper_cmp_p = upper_cmp_p;
+	meas_params->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 \
@@ -3244,6 +3349,114 @@
 	return CMD_SUCCESS;
 }
 
+/* C/I related power control measurements */
+#define POWER_CONTROL_CI_MEAS_AVG_DESC \
+	"C/I (Carrier-toInterference) measurement averaging (for dynamic mode)\n"
+
+DEFUN_USRATTR(cfg_power_ctrl_no_ci_avg,
+	      cfg_power_ctrl_no_ci_avg_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "no ci-avg " VTY_CMD_CI_TYPE,
+	      NO_STR POWER_CONTROL_CI_MEAS_AVG_DESC VTY_DESC_CI_TYPE)
+{
+	struct gsm_power_ctrl_params *params = vty->index;
+	struct gsm_power_ctrl_meas_params *avg_params;
+
+	avg_params = ci_thresh_by_conn_type(params, argv[0]);
+	avg_params->algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_ci_avg_params,
+	      cfg_power_ctrl_ci_avg_params_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "ci-avg " VTY_CMD_CI_TYPE " params hreqave <1-31> hreqt <1-31>",
+	      POWER_CONTROL_CI_MEAS_AVG_DESC VTY_DESC_CI_TYPE
+	      "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 = ci_thresh_by_conn_type(params, argv[0]);
+	avg_params->h_reqave = h_reqave;
+	avg_params->h_reqt = h_reqt;
+
+	return CMD_SUCCESS;
+}
+
+DEFUN_USRATTR(cfg_power_ctrl_ci_avg_algo,
+	      cfg_power_ctrl_ci_avg_algo_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      /* FIXME: add algorithm specific parameters */
+	      "ci-avg " VTY_CMD_CI_TYPE " algo (unweighted|weighted|mod-median)",
+	      POWER_CONTROL_CI_MEAS_AVG_DESC VTY_DESC_CI_TYPE
+	      "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 = ci_thresh_by_conn_type(params, argv[0]);
+	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_ci_avg_osmo_ewma,
+	      cfg_power_ctrl_ci_avg_osmo_ewma_cmd,
+	      X(BSC_VTY_ATTR_VENDOR_SPECIFIC) |
+	      X(BSC_VTY_ATTR_NEW_LCHAN),
+	      "ci-avg " VTY_CMD_CI_TYPE " algo osmo-ewma beta <1-99>",
+	      POWER_CONTROL_CI_MEAS_AVG_DESC VTY_DESC_CI_TYPE
+	      "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;
+	const struct gsm_bts *bts;
+
+	if (params->dir == GSM_PWR_CTRL_DIR_UL)
+		bts = container_of(params, struct gsm_bts, ms_power_ctrl);
+	else
+		bts = container_of(params, struct gsm_bts, bs_power_ctrl);
+
+	if (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;
+	}
+
+	avg_params = ci_thresh_by_conn_type(params, argv[0]);
+	avg_params->algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA;
+	avg_params->ewma.alpha = 100 - atoi(argv[1]);
+
+	return CMD_SUCCESS;
+}
+
 static void vty_out_neigh_list(struct vty *vty, struct bitvec *bv)
 {
 	int count = 0;
@@ -3619,31 +3832,14 @@
 	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, const char *param2)
 {
-	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,
+	cfg_out("%s-thresh%s lower %u upper %u%s",
+		param, param2, 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,
+	cfg_out("%s-thresh-comp%s lower %u %u upper %u %u%s",
+		param, param2, mp->lower_cmp_p, mp->lower_cmp_n,
 		mp->upper_cmp_p, mp->upper_cmp_n,
 		VTY_NEWLINE);
 
@@ -3652,23 +3848,23 @@
 		/* Do not print any averaging parameters */
 		return; /* we're done */
 	case GSM_PWR_CTRL_MEAS_AVG_ALGO_UNWEIGHTED:
-		cfg_out("%s-avg algo unweighted%s", param, VTY_NEWLINE);
+		cfg_out("%s-avg%s algo unweighted%s", param, param2, VTY_NEWLINE);
 		break;
 	case GSM_PWR_CTRL_MEAS_AVG_ALGO_WEIGHTED:
-		cfg_out("%s-avg algo weighted%s", param, VTY_NEWLINE);
+		cfg_out("%s-avg%s algo weighted%s", param, param2, VTY_NEWLINE);
 		break;
 	case GSM_PWR_CTRL_MEAS_AVG_ALGO_MOD_MEDIAN:
-		cfg_out("%s-avg algo mod-median%s", param, VTY_NEWLINE);
+		cfg_out("%s-avg%s algo mod-median%s", param, param2, 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,
+		cfg_out("%s-avg%s algo osmo-ewma beta %u%s",
+			param, param2, 100 - mp->ewma.alpha,
 			VTY_NEWLINE);
 		break;
 	}
 
-	cfg_out("%s-avg params hreqave %u hreqt %u%s",
-		param, mp->h_reqave, mp->h_reqt,
+	cfg_out("%s-avg%s params hreqave %u hreqt %u%s",
+		param, param2, mp->h_reqave, mp->h_reqt,
 		VTY_NEWLINE);
 }
 
@@ -3705,8 +3901,14 @@
 			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);
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->rxlev_meas, "rxlev", "");
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->rxqual_meas, "rxqual", "");
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->ci_fr_meas, "ci", " fr");
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->ci_hr_meas, "ci", " hr");
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->ci_amr_fr_meas, "ci", " amr-fr");
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->ci_amr_hr_meas, "ci", " amr-hr");
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->ci_sdcch_meas, "ci", " sdcch");
+		config_write_power_ctrl_meas(vty, indent + 1, &cp->ci_gprs_meas, "ci", " gprs");
 		break;
 	}
 }
@@ -4199,12 +4401,18 @@
 	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_ci_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_ci_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(POWER_CTRL_NODE, &cfg_power_ctrl_no_ci_avg_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_ci_avg_params_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_ci_avg_algo_cmd);
+	install_element(POWER_CTRL_NODE, &cfg_power_ctrl_ci_avg_osmo_ewma_cmd);
 
 
 	return bts_trx_vty_init();
diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c
index e976a5b..2fb98dd 100644
--- a/src/osmo-bsc/gsm_data.c
+++ b/src/osmo-bsc/gsm_data.c
@@ -1189,6 +1189,72 @@
 		/* Hreqt: the number of averaged results maintained */
 		.h_reqt = 6, /* TODO: investigate a reasonable default value */
 	},
+
+	/* C/I measurement parameters.
+	 * Target C/I retrieved from "GSM/EDGE: Evolution and Performance" Table 10.3.
+	 * Set lower and upper so that (lower + upper) / 2 is equal or slightly
+	 * above the target.
+	 */
+	.ci_fr_meas = { /* Target C/I = 15 dB, Soft blocking threshold = 10 dB */
+		.lower_thresh = 13,
+		.upper_thresh = 17,
+		/* FIXME: C/I averaging is not yet implemented */
+		.algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,
+		/* Hreqave: the period over which an average is produced */
+		.h_reqave = 4, /* TODO: investigate a reasonable default value */
+		/* Hreqt: the number of averaged results maintained */
+		.h_reqt = 6, /* TODO: investigate a reasonable default value */
+	},
+	.ci_hr_meas = { /* Target C/I = 18 dB, Soft blocking threshold = 13 dB */
+		.lower_thresh = 16,
+		.upper_thresh = 21,
+		/* FIXME: C/I averaging is not yet implemented */
+		.algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,
+		/* Hreqave: the period over which an average is produced */
+		.h_reqave = 4, /* TODO: investigate a reasonable default value */
+		/* Hreqt: the number of averaged results maintained */
+		.h_reqt = 6, /* TODO: investigate a reasonable default value */
+	},
+	.ci_amr_fr_meas = { /* Target C/I = 9 dB, Soft blocking threshold = 4 dB */
+		.lower_thresh = 7,
+		.upper_thresh = 11,
+		/* FIXME: C/I averaging is not yet implemented */
+		.algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,
+		/* Hreqave: the period over which an average is produced */
+		.h_reqave = 4, /* TODO: investigate a reasonable default value */
+		/* Hreqt: the number of averaged results maintained */
+		.h_reqt = 6, /* TODO: investigate a reasonable default value */
+	},
+	.ci_amr_hr_meas = { /* Target C/I = 15 dB, Soft blocking threshold = 10 dB */
+		.lower_thresh = 13,
+		.upper_thresh = 17,
+		/* FIXME: C/I averaging is not yet implemented */
+		.algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,
+		/* Hreqave: the period over which an average is produced */
+		.h_reqave = 4, /* TODO: investigate a reasonable default value */
+		/* Hreqt: the number of averaged results maintained */
+		.h_reqt = 6, /* TODO: investigate a reasonable default value */
+	},
+	.ci_sdcch_meas = { /* Target C/I = 14 dB, Soft blocking threshold = 9 dB */
+		.lower_thresh = 12,
+		.upper_thresh = 16,
+		/* FIXME: C/I averaging is not yet implemented */
+		.algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,
+		/* Hreqave: the period over which an average is produced */
+		.h_reqave = 4, /* TODO: investigate a reasonable default value */
+		/* Hreqt: the number of averaged results maintained */
+		.h_reqt = 6, /* TODO: investigate a reasonable default value */
+	},
+	.ci_gprs_meas = { /* Target C/I = 20 dB, Soft blocking threshold = 15 dB */
+		.lower_thresh = 18,
+		.upper_thresh = 24,
+		/* FIXME: C/I averaging is not yet implemented */
+		.algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,
+		/* Hreqave: the period over which an average is produced */
+		.h_reqave = 4, /* TODO: investigate a reasonable default value */
+		/* Hreqt: the number of averaged results maintained */
+		.h_reqt = 6, /* TODO: investigate a reasonable default value */
+	},
 };
 
 enum rsl_cmod_spd chan_mode_to_rsl_cmod_spd(enum gsm48_chan_mode chan_mode)
diff --git a/tests/power_ctrl.vty b/tests/power_ctrl.vty
index ff387ce..4760114 100644
--- a/tests/power_ctrl.vty
+++ b/tests/power_ctrl.vty
@@ -33,12 +33,18 @@
   . 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  ci-thresh (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) lower <0-30> upper <0-30>
   . 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  ci-thresh-comp (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) 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>
+  . lv  no ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs)
+  . lv  ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) params hreqave <1-31> hreqt <1-31>
+  . lv  ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) algo (unweighted|weighted|mod-median)
+  . lv  ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) algo osmo-ewma beta <1-99>
 
 OsmoBSC(config-bs-power-ctrl)# bs-power ?
   static   Fixed BS Power reduction value (for static mode)
@@ -69,6 +75,18 @@
    rxlev-thresh-comp lower 10 12 upper 19 20
    rxqual-thresh lower 3 upper 0
    rxqual-thresh-comp lower 5 7 upper 15 18
+   ci-thresh fr lower 13 upper 17
+   ci-thresh-comp fr lower 0 0 upper 0 0
+   ci-thresh hr lower 16 upper 21
+   ci-thresh-comp hr lower 0 0 upper 0 0
+   ci-thresh amr-fr lower 7 upper 11
+   ci-thresh-comp amr-fr lower 0 0 upper 0 0
+   ci-thresh amr-hr lower 13 upper 17
+   ci-thresh-comp amr-hr lower 0 0 upper 0 0
+   ci-thresh sdcch lower 12 upper 16
+   ci-thresh-comp sdcch lower 0 0 upper 0 0
+   ci-thresh gprs lower 18 upper 24
+   ci-thresh-comp gprs lower 0 0 upper 0 0
   ms-power-control
    mode dyn-bts
 ...
@@ -104,12 +122,18 @@
   . 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  ci-thresh (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) lower <0-30> upper <0-30>
   . 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  ci-thresh-comp (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) 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>
+  . lv  no ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs)
+  . lv  ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) params hreqave <1-31> hreqt <1-31>
+  . lv  ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) algo (unweighted|weighted|mod-median)
+  . lv  ci-avg (fr-efr|hr|amr-fr|amr-hr|sdcch|gprs) algo osmo-ewma beta <1-99>
 
 OsmoBSC(config-ms-power-ctrl)# ### Check default MS Power Parameters
 OsmoBSC(config-ms-power-ctrl)# show running-config

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

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I7e76ec47b323d469f777624b74b08752d1f5584f
Gerrit-Change-Number: 25298
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210831/2092e6d1/attachment-0001.htm>


More information about the gerrit-log mailing list