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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">osmo-bts-virtual: implement GSMTAP_CHANNEL_VOICE<br><br>GSMTAP_CHANNEL_VOICE is the mechanism by which GSMTAP can [finally!]<br>be used to transport circuit-switched voice codec payload, and not<br>just signalling.<br><br>Original patch by Neels Hofmeyr, heavily extended by Harald Welte.<br><br>Depends: libosmocore.git I952044a17334f35712e087dc41781805000aebc1<br>Change-Id: I1cd9a251ce0b87181a0822d7940bbfc9f1428543<br>---<br>M src/osmo-bts-virtual/l1_if.c<br>M src/osmo-bts-virtual/scheduler_virtbts.c<br>2 files changed, 79 insertions(+), 12 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/osmo-bts-virtual/l1_if.c b/src/osmo-bts-virtual/l1_if.c</span><br><span>index ab2cb76..b6a3507 100644</span><br><span>--- a/src/osmo-bts-virtual/l1_if.c</span><br><span>+++ b/src/osmo-bts-virtual/l1_if.c</span><br><span>@@ -128,12 +128,7 @@</span><br><span>           break;</span><br><span>       case GSMTAP_CHANNEL_TCH_F:</span><br><span>   case GSMTAP_CHANNEL_TCH_H:</span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(0, 100%, 40%);">-         /* TODO: handle voice messages */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!facch && ! tch_acch) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_INDICATION, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(120, 100%, 40%);">+               /* This is TCH signalling, for voice frames see GSMTAP_CHANNEL_VOICE */</span><br><span>      case GSMTAP_CHANNEL_SDCCH4:</span><br><span>  case GSMTAP_CHANNEL_SDCCH8:</span><br><span>  case GSMTAP_CHANNEL_PACCH:</span><br><span>@@ -151,6 +146,19 @@</span><br><span>            l1sap.u.data.pdch_presence_info = PRES_INFO_BOTH;</span><br><span>            l1if_process_meas_res(pinst->trx, timeslot, fn, chan_nr, 0, 0, 0, 0);</span><br><span>             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case GSMTAP_CHANNEL_VOICE_F:</span><br><span style="color: hsl(120, 100%, 40%);">+  case GSMTAP_CHANNEL_VOICE_H:</span><br><span style="color: hsl(120, 100%, 40%);">+          /* the first byte indicates the type of voice codec (gsmtap_um_voice_type) */</span><br><span style="color: hsl(120, 100%, 40%);">+         msg->l2h = msgb_pull(msg, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_INDICATION, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+                l1sap.u.tch.chan_nr = chan_nr;</span><br><span style="color: hsl(120, 100%, 40%);">+                l1sap.u.tch.fn = fn;</span><br><span style="color: hsl(120, 100%, 40%);">+          l1sap.u.tch.rssi = 0; /* Radio Signal Strength Indicator. Best -> 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+             l1sap.u.tch.ber10k = 0; /* Bit Error Rate in 0.01%. Best -> 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+           l1sap.u.tch.ta_offs_256bits = 0; /* Burst time of arrival in quarter bits. Probably used for Timing Advance calc. Best -> 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+             l1sap.u.tch.lqual_cb = 10 * signal_dbm; /* Link quality in centiBel = 10 * dB. */</span><br><span style="color: hsl(120, 100%, 40%);">+             l1if_process_meas_res(pinst->trx, timeslot, fn, chan_nr, 0, 0, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span>       case GSMTAP_CHANNEL_AGCH:</span><br><span>    case GSMTAP_CHANNEL_PCH:</span><br><span>     case GSMTAP_CHANNEL_BCCH:</span><br><span>diff --git a/src/osmo-bts-virtual/scheduler_virtbts.c b/src/osmo-bts-virtual/scheduler_virtbts.c</span><br><span>index 90288d1..72a6874 100644</span><br><span>--- a/src/osmo-bts-virtual/scheduler_virtbts.c</span><br><span>+++ b/src/osmo-bts-virtual/scheduler_virtbts.c</span><br><span>@@ -52,8 +52,8 @@</span><br><span>  * This will at first wrap the msg with a GSMTAP header and then write it to the declared multicast socket.</span><br><span>  * TODO: we might want to remove unused argument uint8_t tn</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span style="color: hsl(0, 100%, 40%);">-                        enum trx_chan_type chan, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+static void _tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span style="color: hsl(120, 100%, 40%);">+                       enum trx_chan_type chan, struct msgb *msg, bool is_voice_frame)</span><br><span> {</span><br><span>      const struct trx_chan_desc *chdesc = &trx_chan_desc[chan];</span><br><span>       struct msgb *outmsg;                    /* msg to send with gsmtap header prepended */</span><br><span>@@ -76,7 +76,7 @@</span><br><span>       l1sap_fn2ccch_block(fn) >= num_agch(l1t->trx, "PH-DATA-REQ"))</span><br><span>            gsmtap_chantype = GSMTAP_CHANNEL_PCH;</span><br><span>        else</span><br><span style="color: hsl(0, 100%, 40%);">-            gsmtap_chantype = chantype_rsl2gsmtap(rsl_chantype, chdesc->link_id); /* the logical channel type */</span><br><span style="color: hsl(120, 100%, 40%);">+               gsmtap_chantype = chantype_rsl2gsmtap2(rsl_chantype, chdesc->link_id, is_voice_frame); /* the logical channel type */</span><br><span> </span><br><span> #if MODULO_HYPERFRAME</span><br><span>        /* Restart fn after every superframe (26 * 51 frames) to simulate hyperframe overflow each 6 seconds. */</span><br><span>@@ -105,6 +105,65 @@</span><br><span>      msgb_free(msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span style="color: hsl(120, 100%, 40%);">+                   enum trx_chan_type chan, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       _tx_to_virt_um(l1t, tn, fn, chan, msg, false);</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%);">+static struct gsm_lchan *lchan_from_l1t(struct l1sched_trx *l1t, uint8_t tn, enum trx_chan_type chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_bts_trx_ts *ts;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t subslot = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(l1t && l1t->trx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (chan == TRXC_TCHH_1)</span><br><span style="color: hsl(120, 100%, 40%);">+              subslot = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ts = &l1t->trx->ts[tn];</span><br><span style="color: hsl(120, 100%, 40%);">+     return &ts->lchan[subslot];</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%);">+/* Determine the gsmtap_um_voice_type of a gsm_lchan */</span><br><span style="color: hsl(120, 100%, 40%);">+static int get_um_voice_type(const struct gsm_lchan *lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (lchan->tch_mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_SPEECH_V1:</span><br><span style="color: hsl(120, 100%, 40%);">+           if (lchan->type == GSM_LCHAN_TCH_H)</span><br><span style="color: hsl(120, 100%, 40%);">+                        return GSMTAP_UM_VOICE_HR;</span><br><span style="color: hsl(120, 100%, 40%);">+            else</span><br><span style="color: hsl(120, 100%, 40%);">+                  return GSMTAP_UM_VOICE_FR;</span><br><span style="color: hsl(120, 100%, 40%);">+    case GSM48_CMODE_SPEECH_EFR:</span><br><span style="color: hsl(120, 100%, 40%);">+          return GSMTAP_UM_VOICE_EFR;</span><br><span style="color: hsl(120, 100%, 40%);">+   case GSM48_CMODE_SPEECH_AMR:</span><br><span style="color: hsl(120, 100%, 40%);">+          return GSMTAP_UM_VOICE_AMR;</span><br><span style="color: hsl(120, 100%, 40%);">+   default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</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%);">+static void tx_to_virt_um_voice_frame(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     enum trx_chan_type chan, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_lchan *lchan = lchan_from_l1t(l1t, tn, chan);</span><br><span style="color: hsl(120, 100%, 40%);">+      int um_voice_type;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+   um_voice_type = get_um_voice_type(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (um_voice_type < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           LOGPLCHAN(lchan, DL1P, LOGL_ERROR, "Cannot determine Um voice type from lchan\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          um_voice_type = 0xff;</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%);">+   /* the first byte indicates the type of voice codec (gsmtap_um_voice_type) */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_pull_to_l2(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_push_u8(msg, um_voice_type);</span><br><span style="color: hsl(120, 100%, 40%);">+     msg->l2h = msg->data;</span><br><span style="color: hsl(120, 100%, 40%);">+   _tx_to_virt_um(l1t, tn, fn, chan, msg, true);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*</span><br><span>  * TX on downlink</span><br><span>  */</span><br><span>@@ -414,8 +473,8 @@</span><br><span>   if (msg_facch) {</span><br><span>             tx_to_virt_um(l1t, tn, fn, chan, msg_facch);</span><br><span>                 msgb_free(msg_tch);</span><br><span style="color: hsl(0, 100%, 40%);">-     } else</span><br><span style="color: hsl(0, 100%, 40%);">-          tx_to_virt_um(l1t, tn, fn, chan, msg_tch);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (msg_tch)</span><br><span style="color: hsl(120, 100%, 40%);">+           tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch);</span><br><span> </span><br><span> send_burst:</span><br><span> </span><br><span>@@ -456,7 +515,7 @@</span><br><span>          tx_to_virt_um(l1t, tn, fn, chan, msg_facch);</span><br><span>                 msgb_free(msg_tch);</span><br><span>  } else if (msg_tch)</span><br><span style="color: hsl(0, 100%, 40%);">-             tx_to_virt_um(l1t, tn, fn, chan, msg_tch);</span><br><span style="color: hsl(120, 100%, 40%);">+            tx_to_virt_um_voice_frame(l1t, tn, fn, chan, msg_tch);</span><br><span> </span><br><span> send_burst:</span><br><span>    return NULL;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bts/+/17377">change 17377</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/+/17377"/><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: I1cd9a251ce0b87181a0822d7940bbfc9f1428543 </div>
<div style="display:none"> Gerrit-Change-Number: 17377 </div>
<div style="display:none"> Gerrit-PatchSet: 6 </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: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>