aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2015-12-13 17:08:13 +0100
committerHarald Welte <laforge@gnumonks.org>2015-12-13 17:08:13 +0100
commitf0bf5de82d48bca4e574469aa85a0e0ed146caae (patch)
tree61b3d13c4e657fe08a2edfe5e824d406894e5e2d
parentfeee8d52bdfe50d9dab722bdc48b85e01d5f08d9 (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.c2
-rw-r--r--src/common/rsl.c83
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;
}