Compare commits

...

2 Commits

Author SHA1 Message Date
Harald Welte
f0bf5de82d 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.
2015-12-13 17:08:13 +01:00
Harald Welte
feee8d52bd LAPDm: Use T200 settings from OML rather than libosmocore defaults 2015-12-12 21:39:39 +01:00
5 changed files with 139 additions and 12 deletions

View File

@@ -37,4 +37,8 @@ int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type, int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
uint8_t cause); uint8_t cause);
/* Configure LAPDm T200 timers for this lchan according to OML */
int oml_set_lchan_t200(struct gsm_lchan *lchan);
extern const uint8_t oml_default_t200_ms[7];
#endif // _OML_H */ #endif // _OML_H */

View File

@@ -109,6 +109,7 @@ int bts_init(struct gsm_bts *bts)
btsb->max_ta = 63; btsb->max_ta = 63;
btsb->ny1 = 4; btsb->ny1 = 4;
btsb->t3105_ms = 300; btsb->t3105_ms = 300;
memcpy(btsb->t200_ms, oml_default_t200_ms, sizeof(btsb->t200_ms));
/* default RADIO_LINK_TIMEOUT */ /* default RADIO_LINK_TIMEOUT */
btsb->radio_link_timeout = 32; btsb->radio_link_timeout = 32;
@@ -260,6 +261,7 @@ int lchan_init_lapdm(struct gsm_lchan *lchan)
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY); lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
lapdm_channel_set_l1(lc, NULL, lchan); lapdm_channel_set_l1(lc, NULL, lchan);
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan); lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
oml_set_lchan_t200(lchan);
return 0; return 0;
} }

View File

@@ -386,11 +386,69 @@ static const uint8_t abis_nm_t200_mult[] = {
[T200_FACCH_F] = 5, [T200_FACCH_F] = 5,
[T200_FACCH_H] = 5, [T200_FACCH_H] = 5,
[T200_SACCH_TCH_SAPI0] = 10, [T200_SACCH_TCH_SAPI0] = 10,
[T200_SACCH_SDCCH] = 10, [T200_SACCH_SDCCH] = 10,
[T200_SDCCH_SAPI3] = 5, [T200_SDCCH_SAPI3] = 5,
[T200_SACCH_TCH_SAPI3] = 10 [T200_SACCH_TCH_SAPI3] = 10
}; };
/* the below defaults correpsond to the libocmocore default of 1s for
* DCCH and 2s for ACCH. The BSC should overried this via OML anyway. */
const uint8_t oml_default_t200_ms[7] = {
[T200_SDCCH] = 1000/5,
[T200_FACCH_F] = 1000/5,
[T200_FACCH_H] = 1000/5,
[T200_SACCH_TCH_SAPI0] = 2000/10,
[T200_SACCH_SDCCH] = 2000/10,
[T200_SDCCH_SAPI3] = 1000/5,
[T200_SACCH_TCH_SAPI3] = 2000/10,
};
static void dl_set_t200(struct lapdm_datalink *dl, unsigned int t200_msec)
{
dl->dl.t200_sec = t200_msec / 1000;
dl->dl.t200_usec = t200_msec % 1000;
}
/* Configure LAPDm T200 timers for this lchan according to OML */
int oml_set_lchan_t200(struct gsm_lchan *lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
struct lapdm_channel *lc = &lchan->lapdm_ch;
unsigned int t200_dcch, t200_dcch_sapi3, t200_acch, t200_acch_sapi3;
/* set T200 for main and associated channel */
switch (lchan->type) {
case GSM_LCHAN_SDCCH:
t200_dcch = btsb->t200_ms[T200_SDCCH];
t200_dcch_sapi3 = btsb->t200_ms[T200_SDCCH_SAPI3];
t200_acch = btsb->t200_ms[T200_SACCH_SDCCH];
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_SDCCH];
break;
case GSM_LCHAN_TCH_F:
t200_dcch = btsb->t200_ms[T200_FACCH_F];
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_F];
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
break;
case GSM_LCHAN_TCH_H:
t200_dcch = btsb->t200_ms[T200_FACCH_H];
t200_dcch_sapi3 = btsb->t200_ms[T200_FACCH_H];
t200_acch = btsb->t200_ms[T200_SACCH_TCH_SAPI0];
t200_acch_sapi3 = btsb->t200_ms[T200_SACCH_TCH_SAPI3];
break;
default:
return -1;
}
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI0], t200_dcch);
dl_set_t200(&lc->lapdm_dcch.datalink[DL_SAPI3], t200_dcch_sapi3);
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI0], t200_acch);
dl_set_t200(&lc->lapdm_acch.datalink[DL_SAPI3], t200_acch_sapi3);
return 0;
}
/* 8.6.1 Set BTS Attributes has been received */ /* 8.6.1 Set BTS Attributes has been received */
static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg) static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
{ {

View File

@@ -49,7 +49,7 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx)) if (!trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx))
return 0; return 0;
if (lchan->ms_power_ctrl.fixed) if (!lchan->power_control.ul.dynamic)
return 0; return 0;
/* The phone hasn't reached the power level yet */ /* The phone hasn't reached the power level yet */

View File

@@ -719,13 +719,27 @@ static int encr_info2lchan(struct gsm_lchan *lchan,
return 0; 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 */ /* 8.4.1 CHANnel ACTIVation is received */
static int rsl_rx_chan_activ(struct msgb *msg) static int rsl_rx_chan_activ(struct msgb *msg)
{ {
struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);
struct gsm_lchan *lchan = msg->lchan; struct gsm_lchan *lchan = msg->lchan;
struct rsl_ie_chan_mode *cm; struct rsl_ie_chan_mode *cm;
struct tlv_parsed tp; struct tlv_parsed tp, tp_eie;
uint8_t type; uint8_t type;
int rc; int rc;
@@ -739,7 +753,7 @@ static int rsl_rx_chan_activ(struct msgb *msg)
/* Initialize channel defaults */ /* Initialize channel defaults */
lchan->ms_power = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0); 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.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)); 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 */ /* 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->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 */ /* 9.3.13 MS Power */
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) { if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) {
lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER); lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER);
lchan->ms_power_ctrl.current = lchan->ms_power; lchan->power_control.ul.static_level = lchan->ms_power;
lchan->ms_power_ctrl.fixed = 0; lchan->power_control.ul.dynamic = 0;
} }
/* 9.3.24 Timing Advance */ /* 9.3.24 Timing Advance */
if (TLVP_PRESENT(&tp, RSL_IE_TIMING_ADVANCE)) if (TLVP_PRESENT(&tp, RSL_IE_TIMING_ADVANCE))
lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE); lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE);
/* 9.3.32 BS Power Parameters */ /* 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 */ /* 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.16 Physical Context */
/* 9.3.29 SACCH Information */ /* 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) static int rsl_rx_ms_pwr_ctrl(struct msgb *msg)
{ {
struct gsm_lchan *lchan = msg->lchan; 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)); rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
/* 9.3.13 MS Power */
if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) { if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER)) {
uint8_t pwr = *TLVP_VAL(&tp, RSL_IE_MS_POWER) & 0x1F; lchan->ms_power = *TLVP_VAL(&tp, RSL_IE_MS_POWER) & 0x1F;
lchan->ms_power_ctrl.fixed = 1; lchan->power_control.ul.static_level = lchan->ms_power;
lchan->ms_power_ctrl.current = pwr; 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", LOGP(DRSL, LOGL_NOTICE, "%s forcing power to %d\n",
gsm_lchan_name(lchan), lchan->ms_power_ctrl.current); gsm_lchan_name(lchan), lchan->ms_power_ctrl.current);
bts_model_adjst_ms_pwr(lchan);
} }
bts_model_adjst_ms_pwr(lchan);
return 0; return 0;
} }