<p>Neels Hofmeyr <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/12388">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">make sure early lchan act failure resets the lchan<br><br>Fix crash after AMR configuration fails.<br><br>The crash is due to an assertion that finds a non-NULL conn in the lchan, when<br>re-using an lchan that has failed in AMR configuration earlier on. That is<br>because the AMR config still happens in state UNUSED.<br><br>  DCHAN ERROR lchan(0-0-2-TCH_F_TCH_H_PDCH-0)[0x6120000066a0]{UNUSED}: (type=TCH_F) lchan allocation failed in state UNUSED: Can not generate multirate configuration IE<br>  ...<br>  DCHAN DEBUG lchan(0-0-2-TCH_F_TCH_H_PDCH-0)[0x6120000066a0]{UNUSED}: (type=TCH_F) After failure handling, already in state UNUSED<br>  ...<br>  ...<br>  DCHAN DEBUG lchan(0-0-2-TCH_F_TCH_H_PDCH-0)[0x6120000066a0]{UNUSED}: Received Event LCHAN_EV_ACTIVATE (lchan_fsm.c:324)<br>  Assert failed !lchan->conn ../../../../src/osmo-bsc/src/osmo-bsc/lchan_fsm.c:491<br><br>The FSM design idea is that when returning to the UNUSED state, all lchan state<br>is cleared. However, when calling lchan_activate(), a failure may happen still<br>in state UNUSED, so that we don't transition *back* to UNUSED properly.<br><br>So, first transition out of UNUSED before failures can happen. (Other ways to<br>solve this would be to invoke lchan clearing even if already in UNUSED, but<br>semantically, transitioning first makes more sense.)<br><br>Upon LCHAN_EV_ACTIVATE, just remember the lchan_activate_info and transition to<br>WAIT_TS_READY, so that on lchan_fail(), we can normally transition back to<br>UNUSED and clear the lchan.<br><br>Move the initial lchan activation code to lchan_fsm_wait_ts_ready_onenter().<br><br>Also, there is a bit of duplication of members of the lchan->activate (lchan<br>state) and the lchan_activate_info (passed to lchan_activate()) structs. The<br>fix for this also removes the dup:<br><br>Add struct lchan_activate_info as child struct at lchan->activate.info, drop<br>the other lchan->activate members that would dup .info.*. Move struct<br>lchan_activate_info declaration to gsm_data.h.<br><br>Apply the new '.info' member struct throughout the code.<br><br>Related: OS#3737<br>Change-Id: Ide665b10fa3f4583059c55346db8da833959e3cc<br>---<br>M include/osmocom/bsc/gsm_data.h<br>M include/osmocom/bsc/lchan_fsm.h<br>M src/osmo-bsc/assignment_fsm.c<br>M src/osmo-bsc/bsc_subscr_conn_fsm.c<br>M src/osmo-bsc/handover_fsm.c<br>M src/osmo-bsc/lchan_fsm.c<br>M src/osmo-bsc/lchan_rtp_fsm.c<br>M src/osmo-bsc/osmo_bsc_bssap.c<br>8 files changed, 105 insertions(+), 107 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h</span><br><span>index cf34c6f..2090142 100644</span><br><span>--- a/include/osmocom/bsc/gsm_data.h</span><br><span>+++ b/include/osmocom/bsc/gsm_data.h</span><br><span>@@ -503,6 +503,19 @@</span><br><span> static inline const char *lchan_activate_mode_name(enum lchan_activate_mode activ_for)</span><br><span> { return get_value_string(lchan_activate_mode_names, activ_for); }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct lchan_activate_info {</span><br><span style="color: hsl(120, 100%, 40%);">+ enum lchan_activate_mode activ_for;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_subscriber_connection *for_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* This always is for a specific lchan, so its lchan->type indicates full or half rate.</span><br><span style="color: hsl(120, 100%, 40%);">+     * When a dyn TS was selected, the lchan->type has been set to the desired rate. */</span><br><span style="color: hsl(120, 100%, 40%);">+        enum gsm48_chan_mode chan_mode;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint16_t s15_s0;</span><br><span style="color: hsl(120, 100%, 40%);">+      bool requires_voice_stream;</span><br><span style="color: hsl(120, 100%, 40%);">+   bool wait_before_switching_rtp; /*< true = requires LCHAN_EV_READY_TO_SWITCH_RTP */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t msc_assigned_cic;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gsm_lchan *re_use_mgw_endpoint_from_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct gsm_lchan {</span><br><span>        /* The TS that we're part of */</span><br><span>  struct gsm_bts_trx_ts *ts;</span><br><span>@@ -517,18 +530,14 @@</span><br><span>   struct mgwep_ci *mgw_endpoint_ci_bts;</span><br><span> </span><br><span>    struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                enum lchan_activate_mode activ_for;</span><br><span style="color: hsl(120, 100%, 40%);">+           struct lchan_activate_info info;</span><br><span>             bool activ_ack; /*< true as soon as RSL Chan Activ Ack is received */</span><br><span>             bool immediate_assignment_sent;</span><br><span>              /*! This flag ensures that when an lchan activation has succeeded, and we have already</span><br><span>                * sent ACKs like Immediate Assignment or BSSMAP Assignment Complete, and if other errors</span><br><span>             * occur later, e.g. during release, that we don't send a NACK out of context. */</span><br><span>                bool concluded;</span><br><span style="color: hsl(0, 100%, 40%);">-         bool requires_voice_stream;</span><br><span style="color: hsl(0, 100%, 40%);">-             bool wait_before_switching_rtp; /*< true = requires LCHAN_EV_READY_TO_SWITCH_RTP */</span><br><span style="color: hsl(0, 100%, 40%);">-          uint16_t msc_assigned_cic;</span><br><span>           enum gsm0808_cause gsm0808_error_cause;</span><br><span style="color: hsl(0, 100%, 40%);">-         struct gsm_lchan *re_use_mgw_endpoint_from_lchan;</span><br><span>    } activate;</span><br><span> </span><br><span>      struct {</span><br><span>diff --git a/include/osmocom/bsc/lchan_fsm.h b/include/osmocom/bsc/lchan_fsm.h</span><br><span>index 48cd383..55ab024 100644</span><br><span>--- a/include/osmocom/bsc/lchan_fsm.h</span><br><span>+++ b/include/osmocom/bsc/lchan_fsm.h</span><br><span>@@ -52,19 +52,6 @@</span><br><span> void lchan_release(struct gsm_lchan *lchan, bool do_rr_release,</span><br><span>               bool err, enum gsm48_rr_cause cause_rr);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct lchan_activate_info {</span><br><span style="color: hsl(0, 100%, 40%);">-     enum lchan_activate_mode activ_for;</span><br><span style="color: hsl(0, 100%, 40%);">-     struct gsm_subscriber_connection *for_conn;</span><br><span style="color: hsl(0, 100%, 40%);">-     /* This always is for a specific lchan, so its lchan->type indicates full or half rate.</span><br><span style="color: hsl(0, 100%, 40%);">-       * When a dyn TS was selected, the lchan->type has been set to the desired rate. */</span><br><span style="color: hsl(0, 100%, 40%);">-  enum gsm48_chan_mode chan_mode;</span><br><span style="color: hsl(0, 100%, 40%);">- uint16_t s15_s0;</span><br><span style="color: hsl(0, 100%, 40%);">-        bool requires_voice_stream;</span><br><span style="color: hsl(0, 100%, 40%);">-     bool wait_before_switching_rtp;</span><br><span style="color: hsl(0, 100%, 40%);">- uint16_t msc_assigned_cic;</span><br><span style="color: hsl(0, 100%, 40%);">-      struct gsm_lchan *old_lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> void lchan_activate(struct gsm_lchan *lchan, struct lchan_activate_info *info);</span><br><span> void lchan_ready_to_switch_rtp(struct gsm_lchan *lchan);</span><br><span> </span><br><span>diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c</span><br><span>index 93362f8..a24f7f9 100644</span><br><span>--- a/src/osmo-bsc/assignment_fsm.c</span><br><span>+++ b/src/osmo-bsc/assignment_fsm.c</span><br><span>@@ -385,7 +385,7 @@</span><br><span>             .s15_s0 = req->s15_s0,</span><br><span>            .requires_voice_stream = conn->assignment.requires_voice_stream,</span><br><span>          .msc_assigned_cic = req->msc_assigned_cic,</span><br><span style="color: hsl(0, 100%, 40%);">-           .old_lchan = conn->lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+          .re_use_mgw_endpoint_from_lchan = conn->lchan,</span><br><span>    };</span><br><span>   lchan_activate(conn->assignment.new_lchan, &info);</span><br><span> }</span><br><span>diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>index 85e754f..c1ac6eb 100644</span><br><span>--- a/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>+++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>@@ -550,7 +550,7 @@</span><br><span>    } else</span><br><span>               verb = MGCP_VERB_CRCX;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      gscon_ensure_mgw_endpoint(conn, for_lchan->activate.msc_assigned_cic);</span><br><span style="color: hsl(120, 100%, 40%);">+     gscon_ensure_mgw_endpoint(conn, for_lchan->activate.info.msc_assigned_cic);</span><br><span> </span><br><span>   if (!conn->user_plane.mgw_endpoint) {</span><br><span>             LOGPFSML(conn->fi, LOGL_ERROR, "Unable to allocate endpoint info\n");</span><br><span>diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c</span><br><span>index aae50b9..35f2e55 100644</span><br><span>--- a/src/osmo-bsc/handover_fsm.c</span><br><span>+++ b/src/osmo-bsc/handover_fsm.c</span><br><span>@@ -360,7 +360,7 @@</span><br><span>            .chan_mode = conn->lchan->tch_mode,</span><br><span>            .requires_voice_stream = conn->lchan->mgw_endpoint_ci_bts ? true : false,</span><br><span>              .msc_assigned_cic = conn->ho.inter_bsc_in.msc_assigned_cic,</span><br><span style="color: hsl(0, 100%, 40%);">-          .old_lchan = conn->lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+          .re_use_mgw_endpoint_from_lchan = conn->lchan,</span><br><span>            .wait_before_switching_rtp = true,</span><br><span>   };</span><br><span> </span><br><span>@@ -706,7 +706,7 @@</span><br><span>         ho_perf_params.chosen_encr_alg = lchan->encr.alg_id;</span><br><span>      ho_perf_params.chosen_encr_alg_present = true;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      if (ho->new_lchan->activate.requires_voice_stream) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ho->new_lchan->activate.info.requires_voice_stream) {</span><br><span>              /* Speech Version (chosen) 3.2.2.51 */</span><br><span>               ho_perf_params.speech_version_chosen = gsm0808_permitted_speech(lchan->type, lchan->tch_mode);</span><br><span>                 ho_perf_params.speech_version_chosen_present = true;</span><br><span>@@ -1010,7 +1010,7 @@</span><br><span>         struct gsm_subscriber_connection *conn = ho_fi_conn(fi);</span><br><span>     struct handover *ho = &conn->ho;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (ho->new_lchan->activate.requires_voice_stream</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ho->new_lchan->activate.info.requires_voice_stream</span><br><span>             && (ho->scope & HO_INTER_BSC_IN))</span><br><span>                 ho_fsm_state_chg(HO_ST_WAIT_MGW_ENDPOINT_TO_MSC);</span><br><span>    else</span><br><span>diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c</span><br><span>index c873025..fc1bcbf 100644</span><br><span>--- a/src/osmo-bsc/lchan_fsm.c</span><br><span>+++ b/src/osmo-bsc/lchan_fsm.c</span><br><span>@@ -151,7 +151,7 @@</span><br><span>              return;</span><br><span>      lchan->activate.concluded = true;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        switch (lchan->activate.activ_for) {</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (lchan->activate.info.activ_for) {</span><br><span>         case FOR_MS_CHANNEL_REQUEST:</span><br><span>                 /* No signalling to do here, MS is free to use the channel, and should go on to connect</span><br><span>               * to the MSC and establish a subscriber connection. */</span><br><span>@@ -201,7 +201,7 @@</span><br><span> </span><br><span>    default:</span><br><span>             LOG_LCHAN(lchan, LOGL_NOTICE, "lchan %s fully established\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                   lchan_activate_mode_name(lchan->activate.activ_for));</span><br><span style="color: hsl(120, 100%, 40%);">+                      lchan_activate_mode_name(lchan->activate.info.activ_for));</span><br><span>              break;</span><br><span>       }</span><br><span> }</span><br><span>@@ -238,7 +238,7 @@</span><br><span>                 lchan_set_last_error(_lchan, "lchan %s in state %s: " fmt, \</span><br><span>                                    _lchan->activate.concluded ? "failure" : "allocation failed", \</span><br><span>                               osmo_fsm_state_name(fsm, state_was), ## args); \</span><br><span style="color: hsl(0, 100%, 40%);">-           lchan_on_activation_failure(_lchan, _lchan->activate.activ_for, _lchan->conn); \</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan_on_activation_failure(_lchan, _lchan->activate.info.activ_for, _lchan->conn); \</span><br><span>          if (fi->state != state_chg) \</span><br><span>                     lchan_fsm_state_chg(state_chg); \</span><br><span>            else \</span><br><span>@@ -481,8 +481,6 @@</span><br><span> {</span><br><span>    struct lchan_activate_info *info = data;</span><br><span>     struct gsm_lchan *lchan = lchan_fi_lchan(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-   struct gsm_bts *bts = lchan->ts->trx->bts;</span><br><span style="color: hsl(0, 100%, 40%);">-     struct gsm48_multi_rate_conf mr_conf;</span><br><span> </span><br><span>    switch (event) {</span><br><span> </span><br><span>@@ -493,63 +491,8 @@</span><br><span>          lchan_set_last_error(lchan, NULL);</span><br><span>           lchan->release.requested = false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                lchan->conn = info->for_conn;</span><br><span style="color: hsl(0, 100%, 40%);">-             lchan->activate.activ_for = info->activ_for;</span><br><span style="color: hsl(0, 100%, 40%);">-              lchan->activate.requires_voice_stream = info->requires_voice_stream;</span><br><span style="color: hsl(0, 100%, 40%);">-              lchan->activate.wait_before_switching_rtp = info->wait_before_switching_rtp;</span><br><span style="color: hsl(0, 100%, 40%);">-              lchan->activate.msc_assigned_cic = info->msc_assigned_cic;</span><br><span style="color: hsl(120, 100%, 40%);">+              lchan->activate.info = *info;</span><br><span>             lchan->activate.concluded = false;</span><br><span style="color: hsl(0, 100%, 40%);">-           lchan->activate.re_use_mgw_endpoint_from_lchan = info->old_lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         if (info->old_lchan)</span><br><span style="color: hsl(0, 100%, 40%);">-                 lchan->encr = info->old_lchan->encr;</span><br><span style="color: hsl(0, 100%, 40%);">-           else {</span><br><span style="color: hsl(0, 100%, 40%);">-                  lchan->encr = (struct gsm_encr){</span><br><span style="color: hsl(0, 100%, 40%);">-                             .alg_id = RSL_ENC_ALG_A5(0),    /* no encryption */</span><br><span style="color: hsl(0, 100%, 40%);">-                     };</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* If there is a previous lchan, and the new lchan is on the same cell as previous one,</span><br><span style="color: hsl(0, 100%, 40%);">-          * take over power and TA values. Otherwise, use max power and zero TA. */</span><br><span style="color: hsl(0, 100%, 40%);">-              if (info->old_lchan && info->old_lchan->ts->trx->bts == bts) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   lchan->ms_power = info->old_lchan->ms_power;</span><br><span style="color: hsl(0, 100%, 40%);">-                   lchan->bs_power = info->old_lchan->bs_power;</span><br><span style="color: hsl(0, 100%, 40%);">-                   lchan->rqd_ta = info->old_lchan->rqd_ta;</span><br><span style="color: hsl(0, 100%, 40%);">-               } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* From lchan_reset():</span><br><span style="color: hsl(0, 100%, 40%);">-                   * - bs_power is still zero, 0dB reduction, output power = Pn.</span><br><span style="color: hsl(0, 100%, 40%);">-                   * - TA is still zero, to be determined by RACH. */</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, info->s15_s0);</span><br><span style="color: hsl(0, 100%, 40%);">-                        if (lchan_mr_config(lchan, &mr_conf) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                              lchan_fail("Can not generate multirate configuration IE\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                          return;</span><br><span style="color: hsl(0, 100%, 40%);">-                 }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               switch (info->chan_mode) {</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-           case GSM48_CMODE_SIGN:</span><br><span style="color: hsl(0, 100%, 40%);">-                  lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;</span><br><span style="color: hsl(0, 100%, 40%);">-                        lchan->tch_mode = GSM48_CMODE_SIGN;</span><br><span style="color: hsl(0, 100%, 40%);">-                  break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM48_CMODE_SPEECH_V1:</span><br><span style="color: hsl(0, 100%, 40%);">-             case GSM48_CMODE_SPEECH_EFR:</span><br><span style="color: hsl(0, 100%, 40%);">-            case GSM48_CMODE_SPEECH_AMR:</span><br><span style="color: hsl(0, 100%, 40%);">-                    lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;</span><br><span style="color: hsl(0, 100%, 40%);">-                      lchan->tch_mode = info->chan_mode;</span><br><span style="color: hsl(0, 100%, 40%);">-                        break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          default:</span><br><span style="color: hsl(0, 100%, 40%);">-                        lchan_fail("Not implemented: cannot activate for chan mode %s",</span><br><span style="color: hsl(0, 100%, 40%);">-                                  gsm48_chan_mode_name(info->chan_mode));</span><br><span style="color: hsl(0, 100%, 40%);">-                   return;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>            lchan_fsm_state_chg(LCHAN_ST_WAIT_TS_READY);</span><br><span>                 break;</span><br><span> </span><br><span>@@ -561,18 +504,75 @@</span><br><span> static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>        struct gsm_lchan *lchan = lchan_fi_lchan(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-   struct mgwep_ci *use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_multi_rate_conf mr_conf;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_bts *bts = lchan->ts->trx->bts;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct mgwep_ci *use_mgwep_ci;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lchan_activate_info *info = &lchan->activate.info;</span><br><span> </span><br><span>         if (lchan->release.requested) {</span><br><span>           lchan_fail("Release requested while activating");</span><br><span>          return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->conn = info->for_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (old_lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->encr = old_lchan->encr;</span><br><span style="color: hsl(120, 100%, 40%);">+  else {</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->encr = (struct gsm_encr){</span><br><span style="color: hsl(120, 100%, 40%);">+                   .alg_id = RSL_ENC_ALG_A5(0),    /* no encryption */</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%);">+   /* If there is a previous lchan, and the new lchan is on the same cell as previous one,</span><br><span style="color: hsl(120, 100%, 40%);">+        * take over power and TA values. Otherwise, use max power and zero TA. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (old_lchan && old_lchan->ts->trx->bts == bts) {</span><br><span style="color: hsl(120, 100%, 40%);">+           lchan->ms_power = old_lchan->ms_power;</span><br><span style="color: hsl(120, 100%, 40%);">+          lchan->bs_power = old_lchan->bs_power;</span><br><span style="color: hsl(120, 100%, 40%);">+          lchan->rqd_ta = old_lchan->rqd_ta;</span><br><span style="color: hsl(120, 100%, 40%);">+      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);</span><br><span style="color: hsl(120, 100%, 40%);">+              /* From lchan_reset():</span><br><span style="color: hsl(120, 100%, 40%);">+                 * - bs_power is still zero, 0dB reduction, output power = Pn.</span><br><span style="color: hsl(120, 100%, 40%);">+                 * - TA is still zero, to be determined by RACH. */</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%);">+   if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) {</span><br><span style="color: hsl(120, 100%, 40%);">+           gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, info->s15_s0);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (lchan_mr_config(lchan, &mr_conf) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    lchan_fail("Can not generate multirate configuration IE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                        return;</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%);">+   switch (info->chan_mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       case GSM48_CMODE_SIGN:</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;</span><br><span style="color: hsl(120, 100%, 40%);">+              lchan->tch_mode = GSM48_CMODE_SIGN;</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%);">+      case GSM48_CMODE_SPEECH_V1:</span><br><span style="color: hsl(120, 100%, 40%);">+   case GSM48_CMODE_SPEECH_EFR:</span><br><span style="color: hsl(120, 100%, 40%);">+  case GSM48_CMODE_SPEECH_AMR:</span><br><span style="color: hsl(120, 100%, 40%);">+          lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;</span><br><span style="color: hsl(120, 100%, 40%);">+            lchan->tch_mode = info->chan_mode;</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%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              lchan_fail("Not implemented: cannot activate for chan mode %s",</span><br><span style="color: hsl(120, 100%, 40%);">+                        gsm48_chan_mode_name(info->chan_mode));</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</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%);">+   use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>       LOG_LCHAN(lchan, LOGL_INFO,</span><br><span>            "Activation requested: %s voice=%s MGW-ci=%s type=%s tch-mode=%s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  lchan_activate_mode_name(lchan->activate.activ_for),</span><br><span style="color: hsl(0, 100%, 40%);">-                 lchan->activate.requires_voice_stream ? "yes" : "no",</span><br><span style="color: hsl(0, 100%, 40%);">-            lchan->activate.requires_voice_stream ?</span><br><span style="color: hsl(120, 100%, 40%);">+            lchan_activate_mode_name(lchan->activate.info.activ_for),</span><br><span style="color: hsl(120, 100%, 40%);">+                  lchan->activate.info.requires_voice_stream ? "yes" : "no",</span><br><span style="color: hsl(120, 100%, 40%);">+             lchan->activate.info.requires_voice_stream ?</span><br><span>                    (use_mgwep_ci ? mgwep_ci_name(use_mgwep_ci) : "new")</span><br><span>                       : "none",</span><br><span>            gsm_lchant_name(lchan->type),</span><br><span>@@ -583,7 +583,7 @@</span><br><span>     osmo_fsm_inst_dispatch(lchan->ts->fi, TS_EV_LCHAN_REQUESTED, lchan);</span><br><span> </span><br><span>       /* Prepare an MGW endpoint CI if appropriate. */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (lchan->activate.requires_voice_stream)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lchan->activate.info.requires_voice_stream)</span><br><span>           lchan_rtp_fsm_start(lchan);</span><br><span> }</span><br><span> </span><br><span>@@ -627,7 +627,7 @@</span><br><span>           return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   switch (lchan->activate.activ_for) {</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (lchan->activate.info.activ_for) {</span><br><span>         case FOR_MS_CHANNEL_REQUEST:</span><br><span>                 act_type = RSL_ACT_INTRA_IMM_ASS;</span><br><span>            break;</span><br><span>@@ -709,7 +709,7 @@</span><br><span>                 return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   switch (lchan->activate.activ_for) {</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (lchan->activate.info.activ_for) {</span><br><span> </span><br><span>     case FOR_MS_CHANNEL_REQUEST:</span><br><span>                 rc = rsl_tx_imm_assignment(lchan);</span><br><span>@@ -764,7 +764,7 @@</span><br><span> </span><br><span>         default:</span><br><span>             LOG_LCHAN(lchan, LOGL_NOTICE, "lchan %s is now active\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                       lchan_activate_mode_name(lchan->activate.activ_for));</span><br><span style="color: hsl(120, 100%, 40%);">+                      lchan_activate_mode_name(lchan->activate.info.activ_for));</span><br><span>              break;</span><br><span>       }</span><br><span> </span><br><span>@@ -784,7 +784,7 @@</span><br><span>  switch (event) {</span><br><span> </span><br><span>         case LCHAN_EV_RLL_ESTABLISH_IND:</span><br><span style="color: hsl(0, 100%, 40%);">-                if (!lchan->activate.requires_voice_stream</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!lchan->activate.info.requires_voice_stream</span><br><span>               || lchan_rtp_established(lchan))</span><br><span>                         lchan_fsm_state_chg(LCHAN_ST_ESTABLISHED);</span><br><span>           return;</span><br><span>@@ -1381,6 +1381,8 @@</span><br><span>      if (!lchan)</span><br><span>          return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   lchan->activate.info.for_conn = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   conn = lchan->conn;</span><br><span>       if (conn) {</span><br><span>          /* Log for both lchan FSM and conn FSM to ease reading the log in case of problems */</span><br><span>diff --git a/src/osmo-bsc/lchan_rtp_fsm.c b/src/osmo-bsc/lchan_rtp_fsm.c</span><br><span>index 6ab3da4..84cc287 100644</span><br><span>--- a/src/osmo-bsc/lchan_rtp_fsm.c</span><br><span>+++ b/src/osmo-bsc/lchan_rtp_fsm.c</span><br><span>@@ -111,9 +111,9 @@</span><br><span> </span><br><span>         /* Use old lchan only if there is an MGW endpoint present. Otherwise, on ROLLBACK, we might put</span><br><span>       * an endpoint "back" to an lchan that never had one to begin with. */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (lchan->activate.re_use_mgw_endpoint_from_lchan</span><br><span style="color: hsl(0, 100%, 40%);">-       && !lchan->activate.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts)</span><br><span style="color: hsl(0, 100%, 40%);">-              lchan->activate.re_use_mgw_endpoint_from_lchan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (lchan->activate.info.re_use_mgw_endpoint_from_lchan</span><br><span style="color: hsl(120, 100%, 40%);">+        && !lchan->activate.info.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts)</span><br><span style="color: hsl(120, 100%, 40%);">+               lchan->activate.info.re_use_mgw_endpoint_from_lchan = NULL;</span><br><span> </span><br><span>   lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_AVAILABLE);</span><br><span> }</span><br><span>@@ -127,8 +127,8 @@</span><br><span>                return lchan->mgw_endpoint_ci_bts;</span><br><span>        if (lchan_state_is(lchan, LCHAN_ST_ESTABLISHED))</span><br><span>             return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    if (lchan->activate.re_use_mgw_endpoint_from_lchan)</span><br><span style="color: hsl(0, 100%, 40%);">-          return lchan->activate.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (lchan->activate.info.re_use_mgw_endpoint_from_lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+           return lchan->activate.info.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts;</span><br><span>       return NULL;</span><br><span> }</span><br><span> </span><br><span>@@ -147,7 +147,7 @@</span><br><span>          return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   mgwep = gscon_ensure_mgw_endpoint(lchan->conn, lchan->activate.msc_assigned_cic);</span><br><span style="color: hsl(120, 100%, 40%);">+       mgwep = gscon_ensure_mgw_endpoint(lchan->conn, lchan->activate.info.msc_assigned_cic);</span><br><span>         if (!mgwep) {</span><br><span>                lchan_rtp_fail("Internal error: cannot obtain MGW endpoint handle for conn");</span><br><span>              return;</span><br><span>@@ -232,7 +232,7 @@</span><br><span> {</span><br><span>   struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (lchan->activate.wait_before_switching_rtp) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (lchan->activate.info.wait_before_switching_rtp) {</span><br><span>             LOG_LCHAN_RTP(lchan, LOGL_DEBUG,</span><br><span>                           "Waiting for an event by caller before switching RTP\n");</span><br><span>            lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_READY_TO_SWITCH_RTP);</span><br><span>@@ -305,7 +305,7 @@</span><br><span>                return;</span><br><span> </span><br><span>  case LCHAN_RTP_EV_READY_TO_SWITCH_RTP:</span><br><span style="color: hsl(0, 100%, 40%);">-          lchan->activate.wait_before_switching_rtp = false;</span><br><span style="color: hsl(120, 100%, 40%);">+         lchan->activate.info.wait_before_switching_rtp = false;</span><br><span>           return;</span><br><span> </span><br><span>  case LCHAN_RTP_EV_RELEASE:</span><br><span>@@ -365,7 +365,7 @@</span><br><span>             return;</span><br><span> </span><br><span>  case LCHAN_RTP_EV_READY_TO_SWITCH_RTP:</span><br><span style="color: hsl(0, 100%, 40%);">-          lchan->activate.wait_before_switching_rtp = false;</span><br><span style="color: hsl(120, 100%, 40%);">+         lchan->activate.info.wait_before_switching_rtp = false;</span><br><span>           return;</span><br><span> </span><br><span>  case LCHAN_RTP_EV_RELEASE:</span><br><span>@@ -437,7 +437,7 @@</span><br><span>                                                            uint32_t prev_state)</span><br><span> {</span><br><span>     struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-       struct gsm_lchan *old_lchan = lchan->activate.re_use_mgw_endpoint_from_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan;</span><br><span> </span><br><span>    if (lchan->release.requested) {</span><br><span>           lchan_rtp_fail("Release requested while activating");</span><br><span>@@ -514,7 +514,7 @@</span><br><span> static void lchan_rtp_fsm_rollback_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>      struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-       struct gsm_lchan *old_lchan = lchan->activate.re_use_mgw_endpoint_from_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan;</span><br><span> </span><br><span>    if (!lchan->mgw_endpoint_ci_bts || !old_lchan) {</span><br><span>          osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, 0);</span><br><span>@@ -526,7 +526,7 @@</span><br><span> static void lchan_rtp_fsm_rollback(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>     struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);</span><br><span style="color: hsl(0, 100%, 40%);">-       struct gsm_lchan *old_lchan = lchan->activate.re_use_mgw_endpoint_from_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan;</span><br><span> </span><br><span>    switch (event) {</span><br><span> </span><br><span>@@ -560,7 +560,7 @@</span><br><span>   struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);</span><br><span> </span><br><span>        /* Make sure that we will not hand back the MGW endpoint to any old lchan from here on. */</span><br><span style="color: hsl(0, 100%, 40%);">-      lchan->activate.re_use_mgw_endpoint_from_lchan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     lchan->activate.info.re_use_mgw_endpoint_from_lchan = NULL;</span><br><span> }</span><br><span> </span><br><span> static void lchan_rtp_fsm_established(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span>diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c</span><br><span>index 60ec5fb..f2ccf2c 100644</span><br><span>--- a/src/osmo-bsc/osmo_bsc_bssap.c</span><br><span>+++ b/src/osmo-bsc/osmo_bsc_bssap.c</span><br><span>@@ -1101,7 +1101,7 @@</span><br><span>      };</span><br><span> </span><br><span>       /* speech_codec_chosen */</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ho->new_lchan->activate.requires_voice_stream && gscon_is_aoip(conn)) {</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ho->new_lchan->activate.info.requires_voice_stream && gscon_is_aoip(conn)) {</span><br><span>               int perm_spch = gsm0808_permitted_speech(lchan->type, lchan->tch_mode);</span><br><span>                params.speech_codec_chosen_present = true;</span><br><span>           rc = gsm0808_speech_codec_from_chan_type(&params.speech_codec_chosen, perm_spch);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12388">change 12388</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/12388"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ide665b10fa3f4583059c55346db8da833959e3cc </div>
<div style="display:none"> Gerrit-Change-Number: 12388 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: Pau Espin Pedrol <pespin@sysmocom.de> </div>