From f0bf5de82d48bca4e574469aa85a0e0ed146caae Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 13 Dec 2015 17:08:13 +0100 Subject: RSL: Be more spec compliant in terms of ms / bs power control TS 08.58 requires that BTS-autonomous MS power control is _not_ used, if only the MS Power IE is present in a channel activation. Rather, in order to enable the BTS-autonomous power control loop, the MS Power Parameters must be included. So far we were always enabling MS power control, even in the absence of the MS Power parmeters IE. This is fixed now. This meanas you will need a correspondingly new OsmoBSC/OsmoNITB that sends this IE, or you loose MS (uplink) power control altogether. The content of the MS Power Parameters IE is parsed, but the threshold values not used yet at this point. --- src/common/power_control.c | 2 +- src/common/rsl.c | 83 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/src/common/power_control.c b/src/common/power_control.c index 78d2702b..b2234055 100644 --- a/src/common/power_control.c +++ b/src/common/power_control.c @@ -49,7 +49,7 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan, if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx)) return 0; - if (lchan->ms_power_ctrl.fixed) + if (!lchan->power_control.ul.dynamic) return 0; /* The phone hasn't reached the power level yet */ diff --git a/src/common/rsl.c b/src/common/rsl.c index 03509eda..be781f31 100644 --- a/src/common/rsl.c +++ b/src/common/rsl.c @@ -719,13 +719,27 @@ static int encr_info2lchan(struct gsm_lchan *lchan, return 0; } +static int parse_power_control(struct gsm_power_control *pc, + const uint8_t *ie_val, unsigned int ie_len) +{ + if (ie_len < 3) + return -EINVAL; + + pc->rxlev.lower = ie_val[0] & 0x3f; + pc->rxlev.upper = ie_val[1] & 0x3f; + pc->rxqual.lower = (ie_val[2] >> 4) & 7; + pc->rxqual.upper = ie_val[2] & 7; + + return 0; +} + /* 8.4.1 CHANnel ACTIVation is received */ static int rsl_rx_chan_activ(struct msgb *msg) { struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); struct gsm_lchan *lchan = msg->lchan; struct rsl_ie_chan_mode *cm; - struct tlv_parsed tp; + struct tlv_parsed tp, tp_eie; uint8_t type; int rc; @@ -739,7 +753,7 @@ static int rsl_rx_chan_activ(struct msgb *msg) /* Initialize channel defaults */ lchan->ms_power = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0); lchan->ms_power_ctrl.current = lchan->ms_power; - lchan->ms_power_ctrl.fixed = 0; + lchan->power_control.ul.dynamic = 0; rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); @@ -777,20 +791,50 @@ static int rsl_rx_chan_activ(struct msgb *msg) } /* 9.3.4 BS Power */ - if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER)) + if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER)) { lchan->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER); + lchan->power_control.dl.static_level = lchan->bs_power; + lchan->power_control.dl.dynamic = 0; + } /* 9.3.13 MS Power */ if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) { lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER); - lchan->ms_power_ctrl.current = lchan->ms_power; - lchan->ms_power_ctrl.fixed = 0; + lchan->power_control.ul.static_level = lchan->ms_power; + lchan->power_control.ul.dynamic = 0; } /* 9.3.24 Timing Advance */ if (TLVP_PRESENT(&tp, RSL_IE_TIMING_ADVANCE)) lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE); /* 9.3.32 BS Power Parameters */ + if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) { + rsl_ipac_eie_tlv_parse(&tp_eie, + TLVP_VAL(&tp, RSL_IE_BS_POWER_PARAM), + TLVP_LEN(&tp, RSL_IE_BS_POWER_PARAM)); + if (TLVP_PRESENT(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL)) { + parse_power_control(&lchan->power_control.dl, + TLVP_VAL(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL), + TLVP_LEN(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL)); + } + /* if this IE is present, we use dynamic control */ + lchan->power_control.dl.dynamic = 1; + } + /* 9.3.31 MS Power Parameters */ + if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) { + rsl_ipac_eie_tlv_parse(&tp_eie, + TLVP_VAL(&tp, RSL_IE_MS_POWER_PARAM), + TLVP_LEN(&tp, RSL_IE_MS_POWER_PARAM)); + if (TLVP_PRESENT(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL)) { + parse_power_control(&lchan->power_control.ul, + TLVP_VAL(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL), + TLVP_LEN(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL)); + } + /* if this IE is present, we use dynamic control */ + lchan->power_control.ul.dynamic = 1; + lchan->ms_power_ctrl.current = lchan->ms_power; + } + /* 9.3.16 Physical Context */ /* 9.3.29 SACCH Information */ @@ -1121,19 +1165,38 @@ static int rsl_rx_mode_modif(struct msgb *msg) static int rsl_rx_ms_pwr_ctrl(struct msgb *msg) { struct gsm_lchan *lchan = msg->lchan; - struct tlv_parsed tp; + struct tlv_parsed tp, tp_eie; rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); + /* 9.3.13 MS Power */ if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) { - uint8_t pwr = *TLVP_VAL(&tp, RSL_IE_MS_POWER) & 0x1F; - lchan->ms_power_ctrl.fixed = 1; - lchan->ms_power_ctrl.current = pwr; + lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER) & 0x1F; + lchan->power_control.ul.static_level = lchan->ms_power; + lchan->power_control.ul.dynamic = 0; + lchan->ms_power_ctrl.current = lchan->ms_power; + } + + /* 9.3.31 MS Power Parameters */ + if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) { + rsl_ipac_eie_tlv_parse(&tp_eie, + TLVP_VAL(&tp, RSL_IE_MS_POWER_PARAM), + TLVP_LEN(&tp, RSL_IE_MS_POWER_PARAM)); + if (TLVP_PRESENT(&tp_eie, RSL_IPAC_EIE_BS_PWR_CTL)) { + parse_power_control(&lchan->power_control.ul, + TLVP_VAL(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL), + TLVP_LEN(&tp_eie, RSL_IPAC_EIE_MS_PWR_CTL)); + } + /* if this IE is present, we use dynamic control */ + lchan->power_control.ul.dynamic = 1; + } + if (lchan->power_control.ul.dynamic == 0) { LOGP(DRSL, LOGL_NOTICE, "%s forcing power to %d\n", gsm_lchan_name(lchan), lchan->ms_power_ctrl.current); - bts_model_adjst_ms_pwr(lchan); } + bts_model_adjst_ms_pwr(lchan); + return 0; } -- cgit v1.2.3