Change in osmo-bts[master]: power_control: implement Downlink power control

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

fixeria gerrit-no-reply at lists.osmocom.org
Tue Dec 1 17:41:36 UTC 2020


fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bts/+/21447 )


Change subject: power_control: implement Downlink power control
......................................................................

power_control: implement Downlink power control

Change-Id: I5b509e71d5f668b6b8b2abf8053c27f2a7c78451
Related: SYS#4918
---
M include/osmo-bts/gsm_data.h
M include/osmo-bts/power_control.h
M src/common/l1sap.c
M src/common/power_control.c
M src/common/rsl.c
M src/common/scheduler.c
M src/common/vty.c
7 files changed, 148 insertions(+), 22 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/47/21447/1

diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index 04c6629..6af96fe 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -316,11 +316,9 @@
 	/* RTP header Marker bit to indicate beginning of speech after pause  */
 	bool rtp_tx_marker;
 
-	/* MS power control */
+	/* MS/BS power control */
 	struct lchan_power_ctrl_state ms_power_ctrl;
-
-	/* BTS power reduction (in dB) */
-	uint8_t bs_power_red;
+	struct lchan_power_ctrl_state bs_power_ctrl;
 
 	struct msgb *pending_rel_ind_msg;
 
diff --git a/include/osmo-bts/power_control.h b/include/osmo-bts/power_control.h
index cb566a8..f2e14cf 100644
--- a/include/osmo-bts/power_control.h
+++ b/include/osmo-bts/power_control.h
@@ -6,3 +6,6 @@
 int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
 		      const uint8_t ms_power_lvl,
 		      const int8_t ul_rssi_dbm);
+
+int lchan_bs_pwr_ctrl(struct gsm_lchan *lchan,
+		      const struct gsm48_hdr *gh);
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index 2038fba..33d10a5 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -1546,6 +1546,7 @@
 		lchan->meas.flags |= LC_UL_M_F_L1_VALID;
 
 		lchan_ms_pwr_ctrl(lchan, data[0] & 0x1f, data_ind->rssi);
+		lchan_bs_pwr_ctrl(lchan, (const struct gsm48_hdr *) &data[5]);
 	} else
 		le = &lchan->lapdm_ch.lapdm_dcch;
 
diff --git a/src/common/power_control.c b/src/common/power_control.c
index 592e4f6..71808c8 100644
--- a/src/common/power_control.c
+++ b/src/common/power_control.c
@@ -219,3 +219,105 @@
 
 	return 1;
 }
+
+ /*! compute the new Downlink attenuation value for the given logical channel.
+  *  \param lchan logical channel for which to compute (and in which to store) new power value.
+  *  \param[in] gh pointer to the beginning of (presumably) a Measurement Report.
+  */
+int lchan_bs_pwr_ctrl(struct gsm_lchan *lchan,
+		      const struct gsm48_hdr *gh)
+{
+	struct gsm_bts_trx *trx = lchan->ts->trx;
+	struct gsm_bts *bts = trx->bts;
+	uint8_t rxqual_full, rxqual_sub;
+	uint8_t rxlev_full, rxlev_sub;
+	uint8_t rxqual, rxlev;
+	int delta, new;
+
+	const struct bts_power_ctrl_params *params = &bts->dl_power_ctrl;
+	struct lchan_power_ctrl_state *state = &lchan->bs_power_ctrl;
+
+	/* Check if BS Power Control is enabled */
+	if (state->fixed)
+		return 0;
+	/* Check if this is a Measurement Report */
+	if (gh->proto_discr != GSM48_PDISC_RR)
+		return 0;
+	if (gh->msg_type != GSM48_MT_RR_MEAS_REP)
+		return 0;
+
+	/* Check if the measurement results are valid */
+	if ((gh->data[1] & 0x40) == 0x40) {
+		LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG,
+			  "The measurement results are not valid\n");
+		return 0;
+	}
+
+	/* See 3GPP TS 44.018, section 10.5.2.20 */
+	rxqual_full = (gh->data[2] >> 4) & 0x7;
+	rxqual_sub = (gh->data[2] >> 1) & 0x7;
+
+	rxlev_full = gh->data[0] & 0x3f;
+	rxlev_sub = gh->data[1] & 0x3f;
+
+	LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Rx DL Measurement Report: "
+		  "RXLEV-FULL(%02u), RXQUAL-FULL(%u), "
+		  "RXLEV-SUB(%02u), RXQUAL-SUB(%u), "
+		  "DTx is %s => using %s\n",
+		  rxqual_full, rxqual_sub, rxlev_full, rxlev_sub,
+		  lchan->tch.dtx.dl_active ? "enabled" : "disabled",
+		  lchan->tch.dtx.dl_active ? "SUB" : "FULL");
+
+	/* If DTx is active on Downlink, use the '-SUB' */
+	if (lchan->tch.dtx.dl_active) {
+		rxqual = rxqual_sub;
+		rxlev = rxlev_sub;
+	} else { /* ... otherwise use the '-FULL' */
+		rxqual = rxqual_full;
+		rxlev = rxlev_full;
+	}
+
+	/* Bit Error Rate > 0 => reduce by 2 */
+	if (rxqual > 0) {
+		LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Reducing Downlink attenuation "
+			  "by half: %u -> %u dB due to RXQUAL %u > 0\n",
+			  state->current, state->current / 2, rxqual);
+		state->current /= 2;
+		return 1;
+	}
+
+	/* Calculate a 'delta' for the current attenuation level */
+	delta = calc_delta(params, state, rxlev2dbm(rxlev));
+
+	/* Basic signal transmission / reception formula:
+	 *
+	 *   RxLev = TxPwr - (PathLoss + TxAtt)
+	 *
+	 * Here we want to change RxLev at the MS side, so:
+	 *
+	 *   RxLev + Delta = TxPwr - (PathLoss + TxAtt) + Delta
+	 *
+	 * The only parameter we can change here is TxAtt, so:
+	 *
+	 *   RxLev + Delta = TxPwr - PathLoss -  TxAtt + Delta
+	 *   RxLev + Delta = TxPwr - PathLoss - (TxAtt - Delta)
+	 */
+	new = state->current - delta;
+	if (new > state->max)
+		new = state->max;
+	if (new < 0)
+		new = 0;
+
+	if (state->current != new) {
+		LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Changing Downlink attenuation: "
+			  "%u -> %u dB (maximum %u dB, target %d dBm, delta %d dB)\n",
+			  state->current, new, state->max, params->target, delta);
+		state->current = new;
+		return 1;
+	} else {
+		LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Keeping Downlink attenuation "
+			  "at %u dB (maximum %u dB, target %d dBm, delta %d dB)\n",
+			  state->current, state->max, params->target, delta);
+		return 0;
+	}
+}
diff --git a/src/common/rsl.c b/src/common/rsl.c
index 8760c24..2ebfb32 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -1036,8 +1036,8 @@
 	lchan->tch_mode = 0;
 	memset(&lchan->encr, 0, sizeof(lchan->encr));
 	memset(&lchan->ho, 0, sizeof(lchan->ho));
-	lchan->bs_power_red = 0;
 	memset(&lchan->ms_power_ctrl, 0, sizeof(lchan->ms_power_ctrl));
+	memset(&lchan->bs_power_ctrl, 0, sizeof(lchan->bs_power_ctrl));
 	lchan->rqd_ta = 0;
 	copy_sacch_si_to_lchan(lchan);
 	memset(&lchan->tch, 0, sizeof(lchan->tch));
@@ -1153,11 +1153,16 @@
 	LOGPLCHAN(lchan, DRSL, LOGL_DEBUG, "rx Channel Activation in state: %s.\n",
 		  gsm_lchans_name(lchan->state));
 
-	/* Initialize channel defaults */
+	/* Initialize MS Power Control defaults */
 	lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0);
 	lchan->ms_power_ctrl.current = lchan->ms_power_ctrl.max;
 	lchan->ms_power_ctrl.fixed = true;
 
+	/* Initialize BS Power Control defaults */
+	lchan->bs_power_ctrl.max = 2 * 15;
+	lchan->bs_power_ctrl.current = 0;
+	lchan->bs_power_ctrl.fixed = true;
+
 	rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
 
 	/* 9.3.3 Activation Type */
@@ -1209,9 +1214,11 @@
 			return rsl_tx_chan_act_nack(lchan, RSL_ERR_SERV_OPT_UNIMPL);
 		}
 
-		lchan->bs_power_red = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER));
+		lchan->bs_power_ctrl.max = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER));
+		lchan->bs_power_ctrl.current = lchan->bs_power_ctrl.max;
+
 		LOGPLCHAN(lchan, DRSL, LOGL_DEBUG, "BS Power attenuation %u dB\n",
-			  lchan->bs_power_red);
+			  lchan->bs_power_ctrl.current);
 	}
 
 	/* 9.3.13 MS Power */
@@ -1224,7 +1231,6 @@
 	if (TLVP_PRES_LEN(&tp, RSL_IE_TIMING_ADVANCE, 1))
 		lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE);
 
-	/* 9.3.32 BS Power Parameters */
 	/* 9.3.31 MS Power Parameters */
 	if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) {
 		/* Spec explicitly states BTS should only perform
@@ -1232,6 +1238,14 @@
 		* Parameters' IE is present! */
 		lchan->ms_power_ctrl.fixed = false;
 	}
+
+	/* 9.3.32 BS Power Parameters */
+	if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) {
+		/* NOTE: it's safer to start from 0 */
+		lchan->bs_power_ctrl.current = 0;
+		lchan->bs_power_ctrl.fixed = false;
+	}
+
 	/* 9.3.16 Physical Context */
 
 	/* 9.3.29 SACCH Information */
@@ -1753,7 +1767,7 @@
 	struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);
 	struct gsm_lchan *lchan = msg->lchan;
 	struct tlv_parsed tp;
-	uint8_t old_bs_power_red;
+	uint8_t old, new;
 
 	rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
 
@@ -1766,18 +1780,24 @@
 		return rsl_tx_error_report(msg->trx, RSL_ERR_SERV_OPT_UNIMPL, &dch->chan_nr, NULL, msg);
 	}
 
-	old_bs_power_red = lchan->bs_power_red;
-	lchan->bs_power_red = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER));
-
-	LOGPLCHAN(lchan, DRSL, LOGL_INFO, "BS POWER CONTROL Attenuation %d -> %d dB\n",
-		  old_bs_power_red, lchan->bs_power_red);
+	new = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER));
+	old = lchan->bs_power_ctrl.current;
 
 	/* 9.3.31 MS Power Parameters (O) */
 	if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) {
-		/* Spec explicitly states BTS should perform autonomous
-		 * BS power control loop in BTS if 'BS Power Parameters'
-		 * IE is present!  WE don't support that. */
-		return rsl_tx_error_report(msg->trx, RSL_ERR_OPT_IE_ERROR, &dch->chan_nr, NULL, msg);
+		/* NOTE: it's safer to start from 0 */
+		lchan->bs_power_ctrl.current = 0;
+		lchan->bs_power_ctrl.max = new;
+		lchan->bs_power_ctrl.fixed = false;
+	} else {
+		lchan->bs_power_ctrl.current = new;
+		lchan->bs_power_ctrl.fixed = true;
+	}
+
+	if (lchan->bs_power_ctrl.current != old) {
+		LOGPLCHAN(lchan, DRSL, LOGL_INFO, "BS POWER CONTROL: "
+			  "attenuation change %u -> %u dB\n",
+			  old, lchan->bs_power_ctrl.current);
 	}
 
 	return 0;
@@ -2975,7 +2995,7 @@
 		msgb_tlv_put(msg, RSL_IE_UPLINK_MEAS, ie_len, meas_res);
 		lchan->meas.flags &= ~LC_UL_M_F_RES_VALID;
 	}
-	msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power_red / 2);
+	msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power_ctrl.current / 2);
 	if (lchan->meas.flags & LC_UL_M_F_L1_VALID) {
 		msgb_tv_fixed_put(msg, RSL_IE_L1_INFO, 2, lchan->meas.l1_info);
 		lchan->meas.flags &= ~LC_UL_M_F_L1_VALID;
diff --git a/src/common/scheduler.c b/src/common/scheduler.c
index 84918e3..3d780fd 100644
--- a/src/common/scheduler.c
+++ b/src/common/scheduler.c
@@ -1237,7 +1237,7 @@
 
 	/* BS Power reduction (in dB) per logical channel */
 	if (l1cs->lchan != NULL)
-		br->att = l1cs->lchan->bs_power_red;
+		br->att = l1cs->lchan->bs_power_ctrl.current;
 
 	/* encrypt */
 	if (br->burst_len && l1cs->dl_encr_algo) {
diff --git a/src/common/vty.c b/src/common/vty.c
index 0e78ad3..f366956 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -1381,10 +1381,13 @@
 		lchan->state == LCHAN_S_BROKEN ? " Error reason: " : "",
 		lchan->state == LCHAN_S_BROKEN ? lchan->broken_reason : "",
 		VTY_NEWLINE);
+#if 0
+	/* TODO: print more info about MS/BS Power Control */
 	vty_out(vty, "  BS Power: %d dBm, MS Power: %u dBm%s",
 		lchan->ts->trx->nominal_power - (lchan->ts->trx->max_power_red + lchan->bs_power_red),
 		ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power_ctrl.max),
 		VTY_NEWLINE);
+#endif
 	vty_out(vty, "  Channel Mode / Codec: %s%s",
 		gsm48_chan_mode_name(lchan->tch_mode),
 		VTY_NEWLINE);
@@ -1426,7 +1429,6 @@
 	if (lchan->loopback)
 		vty_out(vty, "  RTP/PDCH Loopback Enabled%s", VTY_NEWLINE);
 	vty_out(vty, "  Radio Link Failure Counter 'S': %d%s", lchan->s, VTY_NEWLINE);
-	/* TODO: MS Power Control */
 }
 
 static void lchan_dump_short_vty(struct vty *vty, const struct gsm_lchan *lchan)

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/21447
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I5b509e71d5f668b6b8b2abf8053c27f2a7c78451
Gerrit-Change-Number: 21447
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201201/997b8646/attachment.htm>


More information about the gerrit-log mailing list