From d4efc3f9c5ea8b67ee9c34095dc8e593acfff3e0 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 8 Jun 2021 16:23:57 +0200 Subject: 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 --- README.md | 1 - doc/manuals/abis/oml.adoc | 4 ++-- include/osmo-bts/gsm_data.h | 18 +++++++++++++++++ src/common/gsm_data.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ src/common/l1sap.c | 17 ++++++++++++++++ src/common/rsl.c | 37 ++++++++++++++++++++++++++++++++-- 6 files changed, 120 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5527ef16..51aa2760 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/doc/manuals/abis/oml.adoc b/doc/manuals/abis/oml.adoc index 984ab8c2..b77894cb 100644 --- a/doc/manuals/abis/oml.adoc +++ b/doc/manuals/abis/oml.adoc @@ -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_ diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h index 6ce5c3b7..808b48a0 100644 --- a/include/osmo-bts/gsm_data.h +++ b/include/osmo-bts/gsm_data.h @@ -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 */ diff --git a/src/common/gsm_data.c b/src/common/gsm_data.c index 09664e24..9afb61ed 100644 --- a/src/common/gsm_data.c +++ b/src/common/gsm_data.c @@ -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) diff --git a/src/common/l1sap.c b/src/common/l1sap.c index 0debae04..c4f258a6 100644 --- a/src/common/l1sap.c +++ b/src/common/l1sap.c @@ -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; } diff --git a/src/common/rsl.c b/src/common/rsl.c index a4b1b7d8..502e6194 100644 --- a/src/common/rsl.c +++ b/src/common/rsl.c @@ -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; -- cgit v1.2.3