aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2021-06-08 16:23:57 +0200
committerVadim Yanitskiy <vyanitskiy@sysmocom.de>2021-06-18 18:56:57 +0200
commitd4efc3f9c5ea8b67ee9c34095dc8e593acfff3e0 (patch)
tree734f45e02efaa7bee70c2923ab019072c56aa03f
parent64e1c1222e1331536fe45f1505229126e0b25fc9 (diff)
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
-rw-r--r--README.md1
-rw-r--r--doc/manuals/abis/oml.adoc4
-rw-r--r--include/osmo-bts/gsm_data.h18
-rw-r--r--src/common/gsm_data.c48
-rw-r--r--src/common/l1sap.c17
-rw-r--r--src/common/rsl.c37
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;