<p>fixeria <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bts/+/21906">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">power_control: handle MS/BS Power control params on A-bis/RSL<br><br>Change-Id: I5a901eca5a78a0335a6954064e602e65cda85390<br>Depends: I2f4ed56837dd479dbbd10c0a7df0ed7565d3946a<br>Related: SYS#4918<br>---<br>M src/common/rsl.c<br>1 file changed, 229 insertions(+), 14 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/common/rsl.c b/src/common/rsl.c</span><br><span>index 29b64b4..bca365e 100644</span><br><span>--- a/src/common/rsl.c</span><br><span>+++ b/src/common/rsl.c</span><br><span>@@ -2,6 +2,7 @@</span><br><span> </span><br><span> /* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu></span><br><span>  * (C) 2011-2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>  *</span><br><span>@@ -698,6 +699,167 @@</span><br><span> </span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Parser for ip.access specific MS/BS Power parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+static int parse_power_ctrl_params(struct gsm_power_ctrl_params *params,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 const uint8_t *data, size_t data_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct tlv_p_entry *ie;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct tlv_parsed tp[2];</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* There can be multiple RSL_IPAC_EIE_MEAS_AVG_CFG, so we use tlv_parse2() */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = tlv_parse2(&tp[0], ARRAY_SIZE(tp), &rsl_ipac_eie_tlvdef,</span><br><span style="color: hsl(120, 100%, 40%);">+                 data, data_len, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Either of RSL_IPAC_EIE_{BS,MS}_PWR_CTL must be present */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (TLVP_PRESENT(&tp[0], RSL_IPAC_EIE_BS_PWR_CTL) &&</span><br><span style="color: hsl(120, 100%, 40%);">+          TLVP_PRESENT(&tp[0], RSL_IPAC_EIE_MS_PWR_CTL))</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* (TV) Thresholds: {L,U}_RXLEV_XX_P and {L,U}_RXQUAL_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_BS_PWR_CTL)) != NULL ||</span><br><span style="color: hsl(120, 100%, 40%);">+       (ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_MS_PWR_CTL)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+           const struct ipac_preproc_pc_thresh *thresh;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                thresh = (const struct ipac_preproc_pc_thresh *) ie->val;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                params->rxlev_meas.lower_thresh = thresh->l_rxlev;</span><br><span style="color: hsl(120, 100%, 40%);">+              params->rxlev_meas.upper_thresh = thresh->u_rxlev;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            params->rxqual_meas.lower_thresh = thresh->l_rxqual;</span><br><span style="color: hsl(120, 100%, 40%);">+            params->rxqual_meas.upper_thresh = thresh->u_rxqual;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* (TV) PC Threshold Comparators */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_PC_THRESH_COMP)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+               const struct ipac_preproc_pc_comp *thresh_comp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             thresh_comp = (const struct ipac_preproc_pc_comp *) ie->val;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* RxLev: P1, N1, P2, N2 (see 3GPP TS 45.008, A.3.2.1, a & b) */</span><br><span style="color: hsl(120, 100%, 40%);">+          params->rxlev_meas.lower_cmp_p = thresh_comp->p1;</span><br><span style="color: hsl(120, 100%, 40%);">+               params->rxlev_meas.lower_cmp_n = thresh_comp->n1;</span><br><span style="color: hsl(120, 100%, 40%);">+               params->rxlev_meas.upper_cmp_p = thresh_comp->p2;</span><br><span style="color: hsl(120, 100%, 40%);">+               params->rxlev_meas.upper_cmp_n = thresh_comp->n2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* RxQual: P3, N3, P4, N4 (see 3GPP TS 45.008, A.3.2.1, c & d) */</span><br><span style="color: hsl(120, 100%, 40%);">+         params->rxqual_meas.lower_cmp_p = thresh_comp->p3;</span><br><span style="color: hsl(120, 100%, 40%);">+              params->rxqual_meas.lower_cmp_n = thresh_comp->n3;</span><br><span style="color: hsl(120, 100%, 40%);">+              params->rxqual_meas.upper_cmp_p = thresh_comp->p4;</span><br><span style="color: hsl(120, 100%, 40%);">+              params->rxqual_meas.upper_cmp_n = thresh_comp->n4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* FIXME: TIMER_PWR_CON_INTERVAL (P_Con_INTERVAL) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Power increase / reduce step size: POWER_{INC,RED}_STEP_SIZE */</span><br><span style="color: hsl(120, 100%, 40%);">+            params->inc_step_size_db = thresh_comp->inc_step_size;</span><br><span style="color: hsl(120, 100%, 40%);">+          params->red_step_size_db = thresh_comp->red_step_size;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* (TLV) Measurement Averaging parameters for RxLev/RxQual */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ARRAY_SIZE(tp); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             const struct ipac_preproc_ave_cfg *ave_cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+           struct gsm_power_ctrl_meas_params *mp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_MEAS_AVG_CFG);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (ie == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              if (ie->len < sizeof(*ave_cfg))</span><br><span style="color: hsl(120, 100%, 40%);">+                 return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             ave_cfg = (const struct ipac_preproc_ave_cfg *) ie->val;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         switch (ave_cfg->param_id) {</span><br><span style="color: hsl(120, 100%, 40%);">+               case IPAC_RXQUAL_AVE:</span><br><span style="color: hsl(120, 100%, 40%);">+                 mp = &params->rxqual_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case IPAC_RXLEV_AVE:</span><br><span style="color: hsl(120, 100%, 40%);">+                  mp = &params->rxlev_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* Skip unknown parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+                 continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           mp->h_reqave = ave_cfg->h_reqave;</span><br><span style="color: hsl(120, 100%, 40%);">+               mp->h_reqt = ave_cfg->h_reqt;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         mp->algo = ave_cfg->ave_method + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             switch (ave_cfg->ave_method) {</span><br><span style="color: hsl(120, 100%, 40%);">+             case IPAC_OSMO_EWMA_AVE:</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (ie->len > sizeof(*ave_cfg))</span><br><span style="color: hsl(120, 100%, 40%);">+                         mp->ewma.alpha = ave_cfg->params[0];</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              /* FIXME: not implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+          case IPAC_UNWEIGHTED_AVE:</span><br><span style="color: hsl(120, 100%, 40%);">+             case IPAC_WEIGHTED_AVE:</span><br><span style="color: hsl(120, 100%, 40%);">+               case IPAC_MEDIAN_AVE:</span><br><span style="color: hsl(120, 100%, 40%);">+                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* ip.access specific Measurement Pre-processing Defaults for MS/BS Power control */</span><br><span style="color: hsl(120, 100%, 40%);">+static int rsl_rx_meas_preproc_dft(struct gsm_bts_trx *trx, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const struct gsm_bts *bts = trx->bts;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gsm_power_ctrl_params *params;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct tlv_p_entry *ie;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct tlv_parsed tp;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGPTRX(trx, DRSL, LOGL_INFO, "Rx Measurement Pre-processing Defaults\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGPTRX(trx, DRSL, LOGL_ERROR, "Failed to parse ip.access specific "</span><br><span style="color: hsl(120, 100%, 40%);">+                        "Measurement Pre-processing Defaults for MS/BS Power control\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           return rsl_tx_error_report(trx, RSL_ERR_PROTO, NULL, NULL, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* TLV (O) BS Power Parameters IE */</span><br><span style="color: hsl(120, 100%, 40%);">+  if ((ie = TLVP_GET(&tp, RSL_IE_BS_POWER_PARAM)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Allocate a new chunk and initialize with default values */</span><br><span style="color: hsl(120, 100%, 40%);">+         params = talloc_memdup(trx, &power_ctrl_params_def, sizeof(*params));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ie->len && parse_power_ctrl_params(params, ie->val, ie->len) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Initially it points to the global defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (trx->bs_dpc_params != &bts->bs_dpc_params)</span><br><span style="color: hsl(120, 100%, 40%);">+                              talloc_free(trx->bs_dpc_params);</span><br><span style="color: hsl(120, 100%, 40%);">+                   trx->bs_dpc_params = params;</span><br><span style="color: hsl(120, 100%, 40%);">+               } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGPTRX(trx, DRSL, LOGL_ERROR, "Failed to parse BS Power Parameters IE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                        talloc_free(params);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* TLV (O) MS Power Parameters IE */</span><br><span style="color: hsl(120, 100%, 40%);">+  if ((ie = TLVP_GET(&tp, RSL_IE_MS_POWER_PARAM)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Allocate a new chunk and initialize with default values */</span><br><span style="color: hsl(120, 100%, 40%);">+         params = talloc_memdup(trx, &power_ctrl_params_def, sizeof(*params));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ie->len && parse_power_ctrl_params(params, ie->val, ie->len) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Initially it points to the global defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (trx->ms_dpc_params != &bts->ms_dpc_params)</span><br><span style="color: hsl(120, 100%, 40%);">+                              talloc_free(trx->ms_dpc_params);</span><br><span style="color: hsl(120, 100%, 40%);">+                   trx->ms_dpc_params = params;</span><br><span style="color: hsl(120, 100%, 40%);">+               } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGPTRX(trx, DRSL, LOGL_ERROR, "Failed to parse MS Power Parameters IE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 rsl_tx_error_report(trx, RSL_ERR_IE_CONTENT, NULL, NULL, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                        talloc_free(params);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* 8.5.6 IMMEDIATE ASSIGN COMMAND is received */</span><br><span> static int rsl_rx_imm_ass(struct gsm_bts_trx *trx, struct msgb *msg)</span><br><span> {</span><br><span>@@ -1125,6 +1287,7 @@</span><br><span>      struct gsm_bts_trx_ts *ts = lchan->ts;</span><br><span>    struct rsl_ie_chan_mode *cm;</span><br><span>         struct tlv_parsed tp;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct tlv_p_entry *ie;</span><br><span>        uint8_t type;</span><br><span>        int rc;</span><br><span> </span><br><span>@@ -1236,19 +1399,42 @@</span><br><span>        if (TLVP_PRES_LEN(&tp, RSL_IE_TIMING_ADVANCE, 1))</span><br><span>                lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       /* 9.3.31 MS Power Parameters */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   /* 9.3.31 (TLV) MS Power Parameters IE (vendor specific) */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((ie = TLVP_GET(&tp, RSL_IE_MS_POWER_PARAM)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                struct gsm_power_ctrl_params *params = &lchan->ms_dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Parsed parameters will override per-TRX defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(params, ts->trx->ms_dpc_params, sizeof(*params));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              if (ie->len && parse_power_ctrl_params(params, ie->val, ie->len) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Failed to parse MS Power Parameters IE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     return rsl_tx_chan_act_nack(lchan, RSL_ERR_IE_CONTENT);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          /* Spec explicitly states BTS should only perform</span><br><span>            * autonomous MS power control loop in BTS if 'MS Power</span><br><span>           * Parameters' IE is present! */</span><br><span>          lchan->ms_power_ctrl.fixed = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->ms_power_ctrl.dpc_params = params;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* 9.3.32 BS Power Parameters */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   /* 9.3.32 (TLV) BS Power Parameters IE (vendor specific) */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((ie = TLVP_GET(&tp, RSL_IE_BS_POWER_PARAM)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                struct gsm_power_ctrl_params *params = &lchan->bs_dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Parsed parameters will override per-TRX defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(params, ts->trx->bs_dpc_params, sizeof(*params));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Parsed parameters will override per-TRX defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (ie->len && parse_power_ctrl_params(params, ie->val, ie->len) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Failed to parse BS Power Parameters IE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     return rsl_tx_chan_act_nack(lchan, RSL_ERR_IE_CONTENT);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          /* NOTE: it's safer to start from 0 */</span><br><span>           lchan->bs_power_ctrl.current = 0;</span><br><span>                 lchan->bs_power_ctrl.fixed = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->bs_power_ctrl.dpc_params = params;</span><br><span>         }</span><br><span> </span><br><span>        /* 9.3.16 Physical Context */</span><br><span>@@ -1721,6 +1907,7 @@</span><br><span>        struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);</span><br><span>       struct gsm_lchan *lchan = msg->lchan;</span><br><span>     struct gsm_bts *bts = lchan->ts->trx->bts;</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct tlv_p_entry *ie;</span><br><span>        struct tlv_parsed tp;</span><br><span>        uint8_t pwr;</span><br><span>         int max_pwr, curr_pwr;</span><br><span>@@ -1736,14 +1923,25 @@</span><br><span> </span><br><span>         LOGPLCHAN(lchan, DRSL, LOGL_INFO, "Rx MS POWER CONTROL %" PRIu8 "\n", pwr);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     /* 9.3.31 MS Power Parameters (O) */</span><br><span style="color: hsl(0, 100%, 40%);">-    if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             /* Spec explicitly states BTS should only perform</span><br><span style="color: hsl(0, 100%, 40%);">-               * autonomous MS power control loop in BTS if 'MS Power</span><br><span style="color: hsl(0, 100%, 40%);">-              * Parameters' IE is present! */</span><br><span style="color: hsl(0, 100%, 40%);">-             lchan->ms_power_ctrl.fixed = false;</span><br><span style="color: hsl(0, 100%, 40%);">-  } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                lchan->ms_power_ctrl.fixed = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Spec explicitly states BTS should only perform autonomous MS Power</span><br><span style="color: hsl(120, 100%, 40%);">+  * control loop in BTS if 'MS Power Parameters' IE is present! */</span><br><span style="color: hsl(120, 100%, 40%);">+     lchan->ms_power_ctrl.fixed = !TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM);</span><br><span style="color: hsl(120, 100%, 40%);">+        lchan->ms_power_ctrl.dpc_params = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* 9.3.31 (TLV) MS Power Parameters IE (vendor specific) */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((ie = TLVP_GET(&tp, RSL_IE_MS_POWER_PARAM)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                struct gsm_power_ctrl_params *params = &lchan->ms_dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Parsed parameters will override per-TRX defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(params, msg->trx->ms_dpc_params, sizeof(*params));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Parsed parameters will override per-TRX defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (ie->len && parse_power_ctrl_params(params, ie->val, ie->len) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Failed to parse MS Power Parameters IE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     return rsl_tx_chan_act_nack(lchan, RSL_ERR_IE_CONTENT);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           lchan->ms_power_ctrl.dpc_params = params;</span><br><span>         }</span><br><span> </span><br><span>        /* Only set current to max if actual value of current</span><br><span>@@ -1773,6 +1971,7 @@</span><br><span> {</span><br><span>   struct abis_rsl_dchan_hdr *dch = msgb_l2(msg);</span><br><span>       struct gsm_lchan *lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct tlv_p_entry *ie;</span><br><span>        struct tlv_parsed tp;</span><br><span>        uint8_t old, new;</span><br><span> </span><br><span>@@ -1790,13 +1989,26 @@</span><br><span>      new = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER));</span><br><span>      old = lchan->bs_power_ctrl.current;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /* 9.3.31 MS Power Parameters (O) */</span><br><span style="color: hsl(0, 100%, 40%);">-    if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   /* 9.3.32 (TLV) BS Power Parameters IE (vendor specific) */</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((ie = TLVP_GET(&tp, RSL_IE_BS_POWER_PARAM)) != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                struct gsm_power_ctrl_params *params = &lchan->bs_dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Parsed parameters will override per-TRX defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(params, msg->trx->bs_dpc_params, sizeof(*params));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Parsed parameters will override per-TRX defaults */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (ie->len && parse_power_ctrl_params(params, ie->val, ie->len) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Failed to parse BS Power Parameters IE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     return rsl_tx_chan_act_nack(lchan, RSL_ERR_IE_CONTENT);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          /* NOTE: it's safer to start from 0 */</span><br><span>           lchan->bs_power_ctrl.current = 0;</span><br><span>                 lchan->bs_power_ctrl.max = new;</span><br><span>           lchan->bs_power_ctrl.fixed = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->bs_power_ctrl.dpc_params = params;</span><br><span>         } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              lchan->bs_power_ctrl.dpc_params = NULL;</span><br><span>           lchan->bs_power_ctrl.current = new;</span><br><span>               lchan->bs_power_ctrl.fixed = true;</span><br><span>        }</span><br><span>@@ -3242,6 +3454,9 @@</span><br><span>    case RSL_MT_SACCH_FILL:</span><br><span>              ret = rsl_rx_sacch_fill(trx, msg);</span><br><span>           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case RSL_MT_IPAC_MEAS_PREPROC_DFT:</span><br><span style="color: hsl(120, 100%, 40%);">+            ret = rsl_rx_meas_preproc_dft(trx, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span>       default:</span><br><span>             LOGP(DRSL, LOGL_NOTICE, "undefined RSL TRX msg_type 0x%02x\n",</span><br><span>                     th->msg_type);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bts/+/21906">change 21906</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bts/+/21906"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bts </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I5a901eca5a78a0335a6954064e602e65cda85390 </div>
<div style="display:none"> Gerrit-Change-Number: 21906 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>