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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">lapdm: Allow user to specify T200 values; Use correct N200 values<br><br>TS 04.06 specifies a N200 re-transmission counter that depends on the<br>channel type, which we didn't care about at all so far.  Let's have the<br>caller tell us the channel type so we can internally look up the correct<br>N200 value for it.<br><br>At the same time, permit the user to specify T200 re-transmission timer<br>values for each SAPI on both DCCH and ACCH, which is required at least<br>in the BTS as per GSM TS 12.21.  Also, extend the timer resolution of<br>the API from seconds to milli-seconds, which is more applicable as<br>particularly on the FACCH the recommended values are in the 200ms range.<br><br>Change-Id: I90fdc4dd4720d4e02213197c894eb0a55a39158c<br>Related: OS#3906<br>Related: OS#2294<br>Related: OS#4037<br>---<br>M include/osmocom/gsm/lapdm.h<br>M src/gsm/lapdm.c<br>M src/gsm/libosmogsm.map<br>3 files changed, 85 insertions(+), 15 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/gsm/lapdm.h b/include/osmocom/gsm/lapdm.h</span><br><span>index e01d065..931de80 100644</span><br><span>--- a/include/osmocom/gsm/lapdm.h</span><br><span>+++ b/include/osmocom/gsm/lapdm.h</span><br><span>@@ -1,6 +1,7 @@</span><br><span> #pragma once</span><br><span> </span><br><span> #include <osmocom/gsm/l1sap.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm_utils.h></span><br><span> #include <osmocom/gsm/lapd_core.h></span><br><span> </span><br><span> /*! \defgroup lapdm LAPDm implementation according to GSM TS 04.06</span><br><span>@@ -81,9 +82,14 @@</span><br><span> struct lapdm_datalink *lapdm_datalink_for_sapi(struct lapdm_entity *le, uint8_t sapi);</span><br><span> </span><br><span> /* initialize a LAPDm entity */</span><br><span style="color: hsl(0, 100%, 40%);">-void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode, int t200);</span><br><span style="color: hsl(0, 100%, 40%);">-void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode, int t200)</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_DEPRECATED("Use lapdm_entity_init2() instead");</span><br><span style="color: hsl(120, 100%, 40%);">+void lapdm_entity_init2(struct lapdm_entity *le, enum lapdm_mode mode,</span><br><span style="color: hsl(120, 100%, 40%);">+                        const int *t200_ms, int n200);</span><br><span style="color: hsl(120, 100%, 40%);">+void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_DEPRECATED("Use lapdm_channel_init2() instead");</span><br><span style="color: hsl(120, 100%, 40%);">+int lapdm_channel_init2(struct lapdm_channel *lc, enum lapdm_mode mode,</span><br><span style="color: hsl(120, 100%, 40%);">+                      const int *t200_ms_dcch, const int *t200_ms_acch, enum gsm_chan_t chan_t);</span><br><span> /* deinitialize a LAPDm entity */</span><br><span> void lapdm_entity_exit(struct lapdm_entity *le);</span><br><span> void lapdm_channel_exit(struct lapdm_channel *lc);</span><br><span>diff --git a/src/gsm/lapdm.c b/src/gsm/lapdm.c</span><br><span>index f1651d6..8084029 100644</span><br><span>--- a/src/gsm/lapdm.c</span><br><span>+++ b/src/gsm/lapdm.c</span><br><span>@@ -1,7 +1,7 @@</span><br><span> /*! \file lapdm.c</span><br><span>  * GSM LAPDm (TS 04.06) implementation. */</span><br><span> /*</span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2010-2017 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2010-2019 by Harald Welte <laforge@gnumonks.org></span><br><span>  * (C) 2010-2011 by Andreas Eversberg <jolly@eversberg.eu></span><br><span>  * (C) 2014-2016 by sysmocom - s.f.m.c GmbH</span><br><span>  *</span><br><span>@@ -132,7 +132,7 @@</span><br><span> static int update_pending_frames(struct lapd_msg_ctx *lctx);</span><br><span> </span><br><span> static void lapdm_dl_init(struct lapdm_datalink *dl,</span><br><span style="color: hsl(0, 100%, 40%);">-                      struct lapdm_entity *entity, int t200)</span><br><span style="color: hsl(120, 100%, 40%);">+                        struct lapdm_entity *entity, int t200_ms, uint32_t n200)</span><br><span> {</span><br><span>      memset(dl, 0, sizeof(*dl));</span><br><span>  dl->entity = entity;</span><br><span>@@ -142,39 +142,101 @@</span><br><span>     dl->dl.send_dlsap = send_rslms_dlsap;</span><br><span>     dl->dl.update_pending_frames = update_pending_frames;</span><br><span>     dl->dl.n200_est_rel = N200_EST_REL;</span><br><span style="color: hsl(0, 100%, 40%);">-  dl->dl.n200 = N200;</span><br><span style="color: hsl(120, 100%, 40%);">+        dl->dl.n200 = n200;</span><br><span>       dl->dl.t203_sec = 0; dl->dl.t203_usec = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-        dl->dl.t200_sec = t200; dl->dl.t200_usec = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   dl->dl.t200_sec = t200_ms / 1000; dl->dl.t200_usec = (t200_ms % 1000) * 1000;</span><br><span> }</span><br><span> </span><br><span> /*! initialize a LAPDm entity and all datalinks inside</span><br><span>  *  \param[in] le LAPDm entity</span><br><span>  *  \param[in] mode \ref lapdm_mode (BTS/MS)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] t200 T200 re-transmission timer for all SAPIs in seconds</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Don't use this function; It doesn't support different T200 values per API</span><br><span style="color: hsl(120, 100%, 40%);">+ *  and doesn't permit the caller to specify the N200 counter, both of which</span><br><span style="color: hsl(120, 100%, 40%);">+ *  are required by GSM specs and supported by lapdm_entity_init2().</span><br><span>  */</span><br><span> void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode, int t200)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+   /* convert from single full-second value to per-SAPI milli-second value */</span><br><span style="color: hsl(120, 100%, 40%);">+    int t200_ms_sapi_arr[_NR_DL_SAPI];</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < ARRAY_SIZE(t200_ms_sapi_arr); i++)</span><br><span style="color: hsl(120, 100%, 40%);">+         t200_ms_sapi_arr[i] = t200 * 1000;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return lapdm_entity_init2(le, mode, t200_ms_sapi_arr, N200);</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%);">+/*! initialize a LAPDm entity and all datalinks inside</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] le LAPDm entity</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] mode lapdm_mode (BTS/MS)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] t200_ms per-SAPI array of T200 re-transmission timer in milli-seconds</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] n200 N200 re-transmisison count</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void lapdm_entity_init2(struct lapdm_entity *le, enum lapdm_mode mode,</span><br><span style="color: hsl(120, 100%, 40%);">+                 const int *t200_ms, int n200)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span>     unsigned int i;</span><br><span> </span><br><span>  for (i = 0; i < ARRAY_SIZE(le->datalink); i++)</span><br><span style="color: hsl(0, 100%, 40%);">-            lapdm_dl_init(&le->datalink[i], le, t200);</span><br><span style="color: hsl(120, 100%, 40%);">+             lapdm_dl_init(&le->datalink[i], le, t200_ms[i], n200);</span><br><span> </span><br><span>    lapdm_entity_set_mode(le, mode);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int get_n200_dcch(enum gsm_chan_t chan_t)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (chan_t) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM_LCHAN_SDCCH:</span><br><span style="color: hsl(120, 100%, 40%);">+         return N200_TR_SDCCH;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM_LCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+         return N200_TR_FACCH_FR;</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM_LCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         return N200_TR_FACCH_HR;</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%);">+/*! initialize a LAPDm channel and all its channels</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] lc lapdm_channel to be initialized</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] mode lapdm_mode (BTS/MS)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Don't use this function; It doesn't support different T200 values per API</span><br><span style="color: hsl(120, 100%, 40%);">+ *  and doesn't set the correct N200 counter, both of which</span><br><span style="color: hsl(120, 100%, 40%);">+ *  are required by GSM specs and supported by lapdm_channel_init2().</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   /* emulate old backwards-compatible behavior with 1s/2s */</span><br><span style="color: hsl(120, 100%, 40%);">+    const int t200_ms_dcch[_NR_DL_SAPI] = { 1000, 1000 };</span><br><span style="color: hsl(120, 100%, 40%);">+ const int t200_ms_acch[_NR_DL_SAPI] = { 2000, 2000 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       lapdm_channel_init2(lc, mode, t200_ms_dcch, t200_ms_acch, GSM_LCHAN_SDCCH);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! initialize a LAPDm channel and all its channels</span><br><span>  *  \param[in] lc \ref lapdm_channel to be initialized</span><br><span>  *  \param[in] mode \ref lapdm_mode (BTS/MS)</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This really is a convenience wrapper around calling \ref</span><br><span style="color: hsl(0, 100%, 40%);">- * lapdm_entity_init twice.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] t200_ms_dcch per-SAPI array of T200 in milli-seconds for DCCH</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] t200_ms_acch per-SAPI array of T200 in milli-seconds for SACCH</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] chan_t GSM channel type (to correctly set N200)</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)</span><br><span style="color: hsl(120, 100%, 40%);">+int lapdm_channel_init2(struct lapdm_channel *lc, enum lapdm_mode mode,</span><br><span style="color: hsl(120, 100%, 40%);">+                 const int *t200_ms_dcch, const int *t200_ms_acch, enum gsm_chan_t chan_t)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  lapdm_entity_init(&lc->lapdm_acch, mode, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+   int n200_dcch = get_n200_dcch(chan_t);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (n200_dcch < 0)</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%);">+     lapdm_entity_init2(&lc->lapdm_acch, mode, t200_ms_acch, N200_TR_SACCH);</span><br><span>       lc->lapdm_acch.lapdm_ch = lc;</span><br><span style="color: hsl(0, 100%, 40%);">-        /* FIXME: this depends on chan type */</span><br><span style="color: hsl(0, 100%, 40%);">-  lapdm_entity_init(&lc->lapdm_dcch, mode, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ lapdm_entity_init2(&lc->lapdm_dcch, mode, t200_ms_dcch, n200_dcch);</span><br><span>   lc->lapdm_dcch.lapdm_ch = lc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span> }</span><br><span> </span><br><span> /*! flush and release all resoures in LAPDm entity */</span><br><span>diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map</span><br><span>index 9aa9683..34a1543 100644</span><br><span>--- a/src/gsm/libosmogsm.map</span><br><span>+++ b/src/gsm/libosmogsm.map</span><br><span>@@ -457,6 +457,7 @@</span><br><span> </span><br><span> lapdm_channel_exit;</span><br><span> lapdm_channel_init;</span><br><span style="color: hsl(120, 100%, 40%);">+lapdm_channel_init2;</span><br><span> lapdm_channel_reset;</span><br><span> lapdm_channel_set_flags;</span><br><span> lapdm_channel_set_l1;</span><br><span>@@ -465,6 +466,7 @@</span><br><span> lapdm_datalink_for_sapi;</span><br><span> lapdm_entity_exit;</span><br><span> lapdm_entity_init;</span><br><span style="color: hsl(120, 100%, 40%);">+lapdm_entity_init2;</span><br><span> lapdm_entity_reset;</span><br><span> lapdm_entity_set_flags;</span><br><span> lapdm_entity_set_mode;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/14339">change 14339</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/libosmocore/+/14339"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I90fdc4dd4720d4e02213197c894eb0a55a39158c </div>
<div style="display:none"> Gerrit-Change-Number: 14339 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-CC: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>