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:
Vadim Yanitskiy 2021-06-08 16:23:57 +02:00
parent 64e1c1222e
commit d4efc3f9c5
6 changed files with 120 additions and 5 deletions

View File

@ -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

View File

@ -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_

View File

@ -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 */

View File

@ -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)

View File

@ -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;
}

View File

@ -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;