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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">assignment_fsm: allow assignment to a specific lchan<br><br>So far the assignment FSM always tried to satisfy the channel mode and<br>rate by either re-using the current lchan or finding a new, unused<br>lchan. For VAMOS however, we want to pick one specific lchan.<br><br>Add target_lchan to struct assignment_request and skip all mode matching<br>and lchan selection when a specific target_lchan is set.<br><br>Related: SYS#5315 OS#4940<br>Change-Id: I71e0d4ff4746706e0be5266e4574d70ca432e3d7<br>---<br>M include/osmocom/bsc/assignment_fsm.h<br>M include/osmocom/bsc/gsm_data.h<br>M src/osmo-bsc/assignment_fsm.c<br>3 files changed, 97 insertions(+), 19 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/assignment_fsm.h b/include/osmocom/bsc/assignment_fsm.h</span><br><span>index b4af335..d4ed846 100644</span><br><span>--- a/include/osmocom/bsc/assignment_fsm.h</span><br><span>+++ b/include/osmocom/bsc/assignment_fsm.h</span><br><span>@@ -41,6 +41,10 @@</span><br><span> </span><br><span> void assignment_fsm_init();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int reassignment_request_to_lchan(enum assign_for assign_for, struct gsm_lchan *lchan, struct gsm_lchan *to_lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+int reassignment_request_to_chan_type(enum assign_for assign_for, struct gsm_lchan *lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   enum gsm_chan_t new_lchan_type);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts *bts,</span><br><span>                     struct assignment_request *req);</span><br><span> void assignment_reset(struct gsm_subscriber_connection *conn);</span><br><span>diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h</span><br><span>index 3ed624f..58ec124 100644</span><br><span>--- a/include/osmocom/bsc/gsm_data.h</span><br><span>+++ b/include/osmocom/bsc/gsm_data.h</span><br><span>@@ -154,6 +154,14 @@</span><br><span>     /* Rate/codec setting in preference order (need at least 1 !) */</span><br><span>     int n_ch_mode_rate;</span><br><span>  struct channel_mode_and_rate ch_mode_rate_list[3];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* An assignment request usually requests to assign any available lchan, to match above requirements. This may</span><br><span style="color: hsl(120, 100%, 40%);">+         * also choose to just keep the current lchan and merely modify it as appropriate. In these cases, keep</span><br><span style="color: hsl(120, 100%, 40%);">+        * target_lchan == NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+       * In some situations, an assignment to a specific target lchan is requested (congestion resolution, VAMOS</span><br><span style="color: hsl(120, 100%, 40%);">+     * multiplexing, user request via VTY). In these situations, select a target lchan beforehand and point</span><br><span style="color: hsl(120, 100%, 40%);">+        * target_lchan to it. */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm_lchan *target_lchan;</span><br><span> };</span><br><span> </span><br><span> /* State of an ongoing Assignment, while the assignment_fsm is still busy. This serves as state separation to keep the</span><br><span>diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c</span><br><span>index 83d2917..b96dbb3 100644</span><br><span>--- a/src/osmo-bsc/assignment_fsm.c</span><br><span>+++ b/src/osmo-bsc/assignment_fsm.c</span><br><span>@@ -438,6 +438,48 @@</span><br><span>  return false;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int _reassignment_request(enum assign_for assign_for, struct gsm_lchan *lchan, struct gsm_lchan *to_lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+                              enum gsm_chan_t new_lchan_type)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_subscriber_connection *conn = lchan->conn;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct assignment_request req = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .assign_for = assign_for,</span><br><span style="color: hsl(120, 100%, 40%);">+             .aoip = gscon_is_aoip(conn),</span><br><span style="color: hsl(120, 100%, 40%);">+          .msc_assigned_cic = conn->user_plane.msc_assigned_cic,</span><br><span style="color: hsl(120, 100%, 40%);">+             .msc_rtp_port = conn->user_plane.msc_assigned_rtp_port,</span><br><span style="color: hsl(120, 100%, 40%);">+            .n_ch_mode_rate = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+          .ch_mode_rate_list = { lchan->current_ch_mode_rate },</span><br><span style="color: hsl(120, 100%, 40%);">+              .target_lchan = to_lchan,</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 (to_lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+         new_lchan_type = to_lchan->type;</span><br><span style="color: hsl(120, 100%, 40%);">+   req.ch_mode_rate_list[0].chan_rate = chan_t_to_chan_rate(new_lchan_type);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* lchan activation will automatically convert chan_mode to a VAMOS equivalent if required.</span><br><span style="color: hsl(120, 100%, 40%);">+    * So rather always pass the plain non-VAMOS mode. */</span><br><span style="color: hsl(120, 100%, 40%);">+ req.ch_mode_rate_list[0].chan_mode = gsm48_chan_mode_to_non_vamos(lchan->current_ch_mode_rate.chan_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_STRLCPY_ARRAY(req.msc_rtp_addr, conn->user_plane.msc_assigned_rtp_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (conn->user_plane.mgw_endpoint_ci_msc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                req.use_osmux = osmo_mgcpc_ep_ci_get_crcx_info_to_osmux_cid(conn->user_plane.mgw_endpoint_ci_msc,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                      &req.osmux_cid);</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 osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_ASSIGNMENT_START, &req);</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%);">+int reassignment_request_to_lchan(enum assign_for assign_for, struct gsm_lchan *lchan, struct gsm_lchan *to_lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return _reassignment_request(assign_for, lchan, to_lchan, 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%);">+int reassignment_request_to_chan_type(enum assign_for assign_for, struct gsm_lchan *lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      enum gsm_chan_t new_lchan_type)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return _reassignment_request(assign_for, lchan, NULL, new_lchan_type);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts *bts,</span><br><span>                          struct assignment_request *req)</span><br><span> {</span><br><span>@@ -470,13 +512,8 @@</span><br><span>        if (check_requires_voice_stream(conn) < 0)</span><br><span>                return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     /* There may be an already existing lchan, if yes, try to work with</span><br><span style="color: hsl(0, 100%, 40%);">-      * the existing lchan.</span><br><span style="color: hsl(0, 100%, 40%);">-   * If an RTP FSM is already set up for the lchan, Mode Modify is not yet supported -- see handling of</span><br><span style="color: hsl(0, 100%, 40%);">-    * LCHAN_EV_REQUEST_MODE_MODIFY in lchan_fsm.c. To not break the lchan, do not even attempt to re-use an lchan</span><br><span style="color: hsl(0, 100%, 40%);">-   * that already has an RTP stream set up, rather establish a new lchan (that transition is well implemented). */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (reuse_existing_lchan(conn) && !conn->lchan->fi_rtp) {</span><br><span style="color: hsl(0, 100%, 40%);">-         /* The new lchan is the old lchan, keep new_lchan == NULL. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!req->target_lchan && reuse_existing_lchan(conn)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* The already existing lchan is suitable for this mode */</span><br><span>           conn->assignment.new_lchan = NULL;</span><br><span> </span><br><span>            /* If the requested mode and the current TCH mode matches up, just send the</span><br><span>@@ -512,19 +549,48 @@</span><br><span>          return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Try to allocate a new lchan in order of preference */</span><br><span style="color: hsl(0, 100%, 40%);">-        for (i = 0; i < req->n_ch_mode_rate; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               conn->assignment.new_lchan = lchan_select_by_chan_mode(bts,</span><br><span style="color: hsl(0, 100%, 40%);">-              req->ch_mode_rate_list[i].chan_mode, req->ch_mode_rate_list[i].chan_rate);</span><br><span style="color: hsl(0, 100%, 40%);">-            if (!conn->assignment.new_lchan)</span><br><span style="color: hsl(0, 100%, 40%);">-                     continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               LOG_ASSIGNMENT(conn, LOGL_DEBUG, "selected new lchan %s for mode[%d] = %s channel_rate=%d\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                        gsm_lchan_name(conn->assignment.new_lchan),</span><br><span style="color: hsl(0, 100%, 40%);">-                          i, gsm48_chan_mode_name(req->ch_mode_rate_list[i].chan_mode),</span><br><span style="color: hsl(0, 100%, 40%);">-                        req->ch_mode_rate_list[i].chan_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (req->target_lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+           bool matching_mode;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         conn->assignment.selected_ch_mode_rate = req->ch_mode_rate_list[i];</span><br><span style="color: hsl(0, 100%, 40%);">-               break;</span><br><span style="color: hsl(120, 100%, 40%);">+                /* The caller already picked a target lchan to assign to. No need to try re-using the current lchan or</span><br><span style="color: hsl(120, 100%, 40%);">+                 * picking a new one. */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (!lchan_state_is(req->target_lchan, LCHAN_ST_UNUSED)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 assignment_fail(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "Assignment to lchan %s requested, but lchan is already in use (state=%s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                       gsm_lchan_name(req->target_lchan),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 osmo_fsm_inst_state_name(req->target_lchan->fi));</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%);">+           conn->assignment.new_lchan = req->target_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+         matching_mode = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                for (i = 0; i < req->n_ch_mode_rate; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (!lchan_type_compat_with_mode(conn->assignment.new_lchan->type, &req->ch_mode_rate_list[i]))</span><br><span style="color: hsl(120, 100%, 40%);">+                          continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     conn->assignment.selected_ch_mode_rate = req->ch_mode_rate_list[i];</span><br><span style="color: hsl(120, 100%, 40%);">+                     matching_mode = true;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!matching_mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 assignment_fail(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    "Assignment to lchan %s requested, but lchan is not compatible\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                  gsm_lchan_name(req->target_lchan));</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%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Try to allocate a new lchan in order of preference */</span><br><span style="color: hsl(120, 100%, 40%);">+              for (i = 0; i < req->n_ch_mode_rate; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     conn->assignment.new_lchan = lchan_select_by_chan_mode(bts,</span><br><span style="color: hsl(120, 100%, 40%);">+                            req->ch_mode_rate_list[i].chan_mode, req->ch_mode_rate_list[i].chan_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (!conn->assignment.new_lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+                           continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOG_ASSIGNMENT(conn, LOGL_DEBUG, "selected new lchan %s for mode[%d] = %s channel_rate=%d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                      gsm_lchan_name(conn->assignment.new_lchan),</span><br><span style="color: hsl(120, 100%, 40%);">+                                i, gsm48_chan_mode_name(req->ch_mode_rate_list[i].chan_mode),</span><br><span style="color: hsl(120, 100%, 40%);">+                                      req->ch_mode_rate_list[i].chan_rate);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     conn->assignment.selected_ch_mode_rate = req->ch_mode_rate_list[i];</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span>    }</span><br><span> </span><br><span>        /* Check whether the lchan allocation was successful or not and tear</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/24362">change 24362</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-bsc/+/24362"/><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-Change-Id: I71e0d4ff4746706e0be5266e4574d70ca432e3d7 </div>
<div style="display:none"> Gerrit-Change-Number: 24362 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@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: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>