Report interference levels in RSL RF RESource INDication
This change implements general interference averaging logic for the higher layers. In l1sap_info_time_ind(), where we receive TDMA time updates from BTS model, call rsl_tx_rf_res() for each transceiver according to the interval defined by the Intave parameter received from the BSC. In rsl_tx_rf_res() perform the actual averaging for each inactive logical channel, and then send everything to the BSC over the A-bis/RSL. The BTS model specific code needs to report the measurements for each logical channel every 104 TDMA frames (SACCH period) by calling gsm_lchan_interf_meas_push(). Change-Id: Id80fdbef087de625149755165c025c0a9563dc85 Related: SYS#5313, OS#1569
This commit is contained in:
parent
64e1c1222e
commit
d4efc3f9c5
|
@ -96,7 +96,6 @@ Common Core
|
|||
* System Information limited to 1,2,2bis,2ter,2quater,3,4,5,6,9,13
|
||||
* No RATSCCH in AMR
|
||||
* Will reject TS 12.21 STARTING TIME in SET BTS ATTR / SET CHAN ATTR
|
||||
* No reporting of interference levels as part of TS 08.58 RF RES IND
|
||||
* No support of TS 08.58 MultiRate Control
|
||||
* No support of TS 08.58 Supported Codec Types
|
||||
* No support of Bter frame / ENHANCED MEASUREMENT REPORT
|
||||
|
|
|
@ -394,8 +394,8 @@ stored items are currently not used in the OsmoBTS code base.
|
|||
| 0x13 | 9.4.19 | File Version | | _ignored_
|
||||
| 0x14 | 9.4.20 | GSM Time | | _ignored_
|
||||
| 0x16 | 9.4.22 | HW Configuration | | _ignored_
|
||||
| 0x18 | 9.4.24 | Intave Parameter | <- | _ignored_
|
||||
| 0x19 | 9.4.25 | Interference level Boundaries | <- | _ignored_
|
||||
| 0x18 | 9.4.24 | Intave Parameter | <- |
|
||||
| 0x19 | 9.4.25 | Interference level Boundaries | <- |
|
||||
| 0x1a | 9.4.26 | List of Required Attributes | | _ignored_
|
||||
| 0x1c | 9.4.28 | Manufacturer Dependent State | | _ignored_
|
||||
| 0x1d | 9.4.29 | Manufacturer Dependent Thresholds | | _ignored_
|
||||
|
|
|
@ -337,6 +337,9 @@ struct gsm_lchan {
|
|||
/* standard deviation of toa256 value during measurement period */
|
||||
uint16_t toa256_std_dev;
|
||||
} ext;
|
||||
/* Interference levels reported by PHY (in dBm) */
|
||||
int16_t interf_meas_dbm[31]; /* Intave max is 31 */
|
||||
uint8_t interf_meas_num;
|
||||
} meas;
|
||||
struct {
|
||||
struct amr_multirate_conf amr_mr;
|
||||
|
@ -537,6 +540,9 @@ uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
|
|||
uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
|
||||
enum gsm_phys_chan_config as_pchan);
|
||||
|
||||
void gsm_lchan_interf_meas_push(struct gsm_lchan *lchan, int dbm);
|
||||
int gsm_lchan_interf_meas_calc_band(struct gsm_lchan *lchan);
|
||||
|
||||
#define BSIC2BCC(bsic) ((bsic) & 0x07)
|
||||
#define BTS_TSC(bts) BSIC2BCC((bts)->bsic)
|
||||
|
||||
|
@ -558,4 +564,16 @@ int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts,
|
|||
|
||||
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
|
||||
|
||||
static inline bool lchan_is_dcch(const struct gsm_lchan *lchan)
|
||||
{
|
||||
switch (lchan->type) {
|
||||
case GSM_LCHAN_SDCCH:
|
||||
case GSM_LCHAN_TCH_F:
|
||||
case GSM_LCHAN_TCH_H:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _GSM_DATA_H */
|
||||
|
|
|
@ -280,6 +280,54 @@ uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
|
|||
return gsm_pchan2chan_nr(as_pchan, lchan->ts->nr, lchan->nr);
|
||||
}
|
||||
|
||||
/* Called by the model specific code every 104 TDMA frames (SACCH period) */
|
||||
void gsm_lchan_interf_meas_push(struct gsm_lchan *lchan, int dbm)
|
||||
{
|
||||
const uint8_t meas_num = lchan->meas.interf_meas_num;
|
||||
|
||||
if (meas_num >= ARRAY_SIZE(lchan->meas.interf_meas_dbm)) {
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_ERROR, "Not enough room "
|
||||
"to store interference report (%ddBm)\n", dbm);
|
||||
return;
|
||||
}
|
||||
|
||||
lchan->meas.interf_meas_dbm[meas_num] = dbm;
|
||||
lchan->meas.interf_meas_num++;
|
||||
}
|
||||
|
||||
/* Called by the higher layers every Intave * 104 TDMA frames */
|
||||
int gsm_lchan_interf_meas_calc_band(struct gsm_lchan *lchan)
|
||||
{
|
||||
const uint8_t meas_num = lchan->meas.interf_meas_num;
|
||||
const struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
int b, meas_avg, meas_sum = 0;
|
||||
|
||||
/* There must be at least one sample */
|
||||
if (meas_num == 0)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Calculate the sum of all collected samples (in -x dBm) */
|
||||
while (lchan->meas.interf_meas_num) {
|
||||
uint8_t i = --lchan->meas.interf_meas_num;
|
||||
meas_sum += lchan->meas.interf_meas_dbm[i];
|
||||
}
|
||||
|
||||
/* Calculate the average of all collected samples */
|
||||
meas_avg = meas_sum / (int) meas_num;
|
||||
|
||||
/* Determine the band using interference boundaries from BSC */
|
||||
for (b = 0; b < ARRAY_SIZE(bts->interference.boundary); b++) {
|
||||
if (meas_avg >= bts->interference.boundary[b])
|
||||
break; /* Current 'b' is the band value */
|
||||
}
|
||||
|
||||
LOGPLCHAN(lchan, DL1C, LOGL_DEBUG,
|
||||
"Interference AVG: %ddBm (band %d)\n",
|
||||
meas_avg, b);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/* determine logical channel based on TRX and channel number IE */
|
||||
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
int *rc)
|
||||
|
|
|
@ -588,6 +588,20 @@ static unsigned int calc_exprd_rach_frames(struct gsm_bts *bts, uint32_t fn)
|
|||
return rach_frames_expired;
|
||||
}
|
||||
|
||||
static void l1sap_interf_meas_report(struct gsm_bts *bts)
|
||||
{
|
||||
const uint32_t period = bts->interference.intave * 104;
|
||||
struct gsm_bts_trx *trx;
|
||||
|
||||
if (bts->interference.intave == 0)
|
||||
return;
|
||||
if (bts->gsm_time.fn % period != 0)
|
||||
return;
|
||||
|
||||
llist_for_each_entry(trx, &bts->trx_list, list)
|
||||
rsl_tx_rf_res(trx);
|
||||
}
|
||||
|
||||
/* time information received from bts model */
|
||||
static int l1sap_info_time_ind(struct gsm_bts *bts,
|
||||
struct osmo_phsap_prim *l1sap,
|
||||
|
@ -620,6 +634,9 @@ static int l1sap_info_time_ind(struct gsm_bts *bts,
|
|||
bts->load.rach.total += calc_exprd_rach_frames(bts, fn);
|
||||
}
|
||||
|
||||
/* Report interference levels to the BSC */
|
||||
l1sap_interf_meas_report(bts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -427,6 +427,7 @@ static int rsl_tx_error_report(struct gsm_bts_trx *trx, uint8_t cause, const uin
|
|||
/* 8.6.1 sending RF RESOURCE INDICATION */
|
||||
int rsl_tx_rf_res(struct gsm_bts_trx *trx)
|
||||
{
|
||||
unsigned int tn, ln;
|
||||
struct msgb *nmsg;
|
||||
|
||||
LOGP(DRSL, LOGL_INFO, "Tx RSL RF RESource INDication\n");
|
||||
|
@ -434,8 +435,40 @@ int rsl_tx_rf_res(struct gsm_bts_trx *trx)
|
|||
nmsg = rsl_msgb_alloc(sizeof(struct abis_rsl_common_hdr));
|
||||
if (!nmsg)
|
||||
return -ENOMEM;
|
||||
// FIXME: add interference levels of TRX
|
||||
msgb_tlv_put(nmsg, RSL_IE_RESOURCE_INFO, 0, NULL);
|
||||
|
||||
/* Add interference levels for each logical channel */
|
||||
uint8_t *len = msgb_tl_put(nmsg, RSL_IE_RESOURCE_INFO);
|
||||
|
||||
for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
|
||||
struct gsm_bts_trx_ts *ts = &trx->ts[tn];
|
||||
|
||||
for (ln = 0; ln < ARRAY_SIZE(ts->lchan); ln++) {
|
||||
struct gsm_lchan *lchan = &ts->lchan[ln];
|
||||
|
||||
/* We're not interested in active lchans */
|
||||
if (lchan->state == LCHAN_S_ACTIVE) {
|
||||
/* Avoid potential buffer overflow */
|
||||
lchan->meas.interf_meas_num = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Only for GSM_LCHAN_{SDCCH,TCH_F,TCH_H} */
|
||||
if (!lchan_is_dcch(lchan))
|
||||
continue;
|
||||
|
||||
/* Average all collected samples */
|
||||
int band = gsm_lchan_interf_meas_calc_band(lchan);
|
||||
if (band < 0)
|
||||
continue;
|
||||
|
||||
msgb_v_put(nmsg, gsm_lchan2chan_nr(lchan));
|
||||
msgb_v_put(nmsg, (band & 0x07) << 5);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate length of the V part */
|
||||
*len = msgb_l3len(nmsg) - 2;
|
||||
|
||||
rsl_trx_push_hdr(nmsg, RSL_MT_RF_RES_IND);
|
||||
nmsg->trx = trx;
|
||||
|
||||
|
|
Loading…
Reference in New Issue