diff options
author | Harald Welte <laforge@gnumonks.org> | 2015-12-13 17:08:13 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-12-13 17:08:13 +0100 |
commit | f0bf5de82d48bca4e574469aa85a0e0ed146caae (patch) | |
tree | 61b3d13c4e657fe08a2edfe5e824d406894e5e2d | |
parent | feee8d52bdfe50d9dab722bdc48b85e01d5f08d9 (diff) |
RSL: Be more spec compliant in terms of ms / bs power controllaforge/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.
-rw-r--r-- | src/common/power_control.c | 2 | ||||
-rw-r--r-- | 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; } |