aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2021-08-26 15:41:17 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2021-09-06 12:07:20 +0200
commit54283ba62665ce6410d9da0dddd9601bf9dd719a (patch)
tree0980c3d88ad62761cd0636fd0123a6b5ae0cdcb3 /src
parentda06d183e7dc26fcfc9fcbd447164ae24823e821 (diff)
MS Power Control Loop: Support set up of C/I parameters for osmo-bts
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. Related: SYS#4917 Depends: libosmocore.git Change-Id Iffef0611430ad6c90606149c398d80158633bbca Change-Id: I7e76ec47b323d469f777624b74b08752d1f5584f
Diffstat (limited to 'src')
-rw-r--r--src/osmo-bsc/bts_ipaccess_nanobts.c8
-rw-r--r--src/osmo-bsc/bts_osmobts.c99
-rw-r--r--src/osmo-bsc/bts_vty.c280
-rw-r--r--src/osmo-bsc/gsm_data.c132
4 files changed, 482 insertions, 37 deletions
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c
index 8d2908f69..9607068d5 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts.c
@@ -920,13 +920,17 @@ static void enc_power_params(struct msgb *msg, const struct gsm_power_ctrl_param
thresh_comp->red_step_size = cp->red_step_size_db & 0x0f;
}
+void osmobts_enc_power_params_osmo_ext(struct msgb *msg, const struct gsm_power_ctrl_params *cp);
static void add_power_params_ie(struct msgb *msg, enum abis_rsl_ie iei,
+ const struct gsm_bts_trx *trx,
const struct gsm_power_ctrl_params *cp)
{
uint8_t *ie_len = msgb_tl_put(msg, iei);
uint8_t msg_len = msgb_length(msg);
enc_power_params(msg, cp);
+ if (iei == RSL_IE_MS_POWER_PARAM && is_osmobts(trx->bts))
+ osmobts_enc_power_params_osmo_ext(msg, cp);
*ie_len = msgb_length(msg) - msg_len;
}
@@ -958,9 +962,9 @@ static int power_ctrl_send_def_params(const struct gsm_bts_trx *trx)
/* MS/BS Power Parameters IEs */
if (ms_power_ctrl->mode == GSM_PWR_CTRL_MODE_DYN_BTS)
- add_power_params_ie(msg, RSL_IE_MS_POWER_PARAM, ms_power_ctrl);
+ add_power_params_ie(msg, RSL_IE_MS_POWER_PARAM, trx, ms_power_ctrl);
if (bs_power_ctrl->mode == GSM_PWR_CTRL_MODE_DYN_BTS)
- add_power_params_ie(msg, RSL_IE_BS_POWER_PARAM, bs_power_ctrl);
+ add_power_params_ie(msg, RSL_IE_BS_POWER_PARAM, trx, bs_power_ctrl);
msg->dst = trx->rsl_link_primary;
diff --git a/src/osmo-bsc/bts_osmobts.c b/src/osmo-bsc/bts_osmobts.c
index 9813a265d..5007d2b90 100644
--- a/src/osmo-bsc/bts_osmobts.c
+++ b/src/osmo-bsc/bts_osmobts.c
@@ -44,6 +44,105 @@ extern struct gsm_bts_model bts_model_nanobts;
static struct gsm_bts_model model_osmobts;
+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);
+}
+
+/* Appends Osmocom specific extension IEs into RSL_IE_MS_POWER_PARAM */
+void osmobts_enc_power_params_osmo_ext(struct msgb *msg, const struct gsm_power_ctrl_params *cp)
+{
+ 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 int power_ctrl_set_c0_power_red(const struct gsm_bts *bts,
const uint8_t red)
{
diff --git a/src/osmo-bsc/bts_vty.c b/src/osmo-bsc/bts_vty.c
index ebc11b57f..dbfe5e46b 100644
--- a/src/osmo-bsc/bts_vty.c
+++ b/src/osmo-bsc/bts_vty.c
@@ -3034,6 +3034,8 @@ DEFUN_USRATTR(cfg_power_ctrl_step_size,
"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,
@@ -3090,10 +3092,74 @@ DEFUN_USRATTR(cfg_power_ctrl_rxqual_thresh,
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
@@ -3102,7 +3168,7 @@ DEFUN_USRATTR(cfg_power_ctrl_rxlev_thresh_comp,
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", /*empty*/,
"P1 (default 10)\n", "N1 (default 12)\n",
"P2 (default 10)\n", "N2 (default 12)\n"))
{
@@ -3137,7 +3203,7 @@ DEFUN_USRATTR(cfg_power_ctrl_rxqual_thresh_comp,
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", /*empty*/,
"P3 (default 5)\n", "N3 (default 7)\n",
"P4 (default 15)\n", "N4 (default 18)\n"))
{
@@ -3167,6 +3233,45 @@ DEFUN_USRATTR(cfg_power_ctrl_rxqual_thresh_comp,
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", "Lower 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",
+ upper_cmp_p, upper_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 \
@@ -3278,6 +3383,114 @@ DEFUN_USRATTR(cfg_power_ctrl_avg_osmo_ewma,
return CMD_SUCCESS;
}
+/* C/I related power control measurements */
+#define POWER_CONTROL_CI_MEAS_AVG_DESC \
+ "C/I (Carrier-to-Interference) 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;
@@ -3653,31 +3866,14 @@ static void config_write_bts_amr(struct vty *vty, struct gsm_bts *bts,
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);
@@ -3686,23 +3882,23 @@ static void config_write_power_ctrl_meas(struct vty *vty, unsigned int indent,
/* 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);
}
@@ -3739,8 +3935,16 @@ static void config_write_power_ctrl(struct vty *vty, unsigned int indent,
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", "");
+ if (cp->dir == GSM_PWR_CTRL_DIR_UL) {
+ config_write_power_ctrl_meas(vty, indent + 1, &cp->ci_fr_meas, "ci", " fr-efr");
+ 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;
}
}
@@ -4238,12 +4442,18 @@ int bts_vty_init(void)
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 481329bff..02d9fd7cb 100644
--- a/src/osmo-bsc/gsm_data.c
+++ b/src/osmo-bsc/gsm_data.c
@@ -1189,6 +1189,138 @@ const struct gsm_power_ctrl_params power_ctrl_params_def = {
/* 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 = { /* FR: Target C/I = 15 dB, Soft blocking threshold = 10 dB */
+ .lower_thresh = 13,
+ .upper_thresh = 17,
+
+ /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages
+ * out of LOWER_CMP_N averages are lower than L_CI_FR_XX_P */
+ .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages
+ * out of UPPER_CMP_N averages are greater than L_CI_FR_XX_P */
+ .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+ .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+
+ /* No averaging (filtering) by default */
+ .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 = { /* HR: Target C/I = 18 dB, Soft blocking threshold = 13 dB */
+ .lower_thresh = 16,
+ .upper_thresh = 21,
+
+ /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages
+ * out of LOWER_CMP_N averages are lower than L_CI_HR_XX_P */
+ .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages
+ * out of UPPER_CMP_N averages are greater than L_CI_HR_XX_P */
+ .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+ .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+
+ /* No averaging (filtering) by default */
+ .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 = { /* AMR-FR: Target C/I = 9 dB, Soft blocking threshold = 4 dB */
+ .lower_thresh = 7,
+ .upper_thresh = 11,
+
+ /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages
+ * out of LOWER_CMP_N averages are lower than L_CI_AMR_FR_XX_P */
+ .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages
+ * out of UPPER_CMP_N averages are greater than L_CI_AMR_FR_XX_P */
+ .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+ .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+
+ /* No averaging (filtering) by default */
+ .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 = { /* AMR-HR: Target C/I = 15 dB, Soft blocking threshold = 10 dB */
+ .lower_thresh = 13,
+ .upper_thresh = 17,
+
+ /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages
+ * out of LOWER_CMP_N averages are lower than L_CI_AMR_HR_XX_P */
+ .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages
+ * out of UPPER_CMP_N averages are greater than L_CI_AMR_HR_XX_P */
+ .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+ .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+
+ /* No averaging (filtering) by default */
+ .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 = { /* SDCCH: Target C/I = 14 dB, Soft blocking threshold = 9 dB */
+ .lower_thresh = 12,
+ .upper_thresh = 16,
+
+ /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages
+ * out of LOWER_CMP_N averages are lower than L_CI_SDCCH_XX_P */
+ .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages
+ * out of UPPER_CMP_N averages are greater than L_CI_SDCCH_XX_P */
+ .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+ .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+
+ /* No averaging (filtering) by default */
+ .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 = { /* GPRS: Target C/I = 20 dB, Soft blocking threshold = 15 dB */
+ .lower_thresh = 18,
+ .upper_thresh = 24,
+
+ /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages
+ * out of LOWER_CMP_N averages are lower than L_CI_GPRS_XX_P */
+ .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */
+ /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages
+ * out of UPPER_CMP_N averages are greater than L_CI_GPRS_XX_P */
+ .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+ .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */
+
+ /* No averaging (filtering) by default */
+ .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)