<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21387">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Dl TBF: Get rid of LLC UI dummy blocks following other data<br><br>According to:<br>* 3GPP TS 44.060 version 16.0.0 "9.3.1a Delayed release of downlink Temporary Block Flow"<br>* 3GPP TS 44.064 version 16.0.0 "6.4.2.2 Unconfirmed Information (UI) Dummy command"<br><br>LLC UI Dummy frames are to be used when there no more data to send, only<br>in order to delay the release of a TBF. Hence, while not incorrect per<br>se, makes no sense to send those LLC UI Dummy frames inserted into<br>rlcmac blocks which already contain other LLC frames, since the MS in<br>that case is already being kept active.<br>It only makes sense to send those LLC UI Dummy frames when we have<br>nothing else to send, that is, alone inside a RLCMAC block without other<br>LLC frames.<br><br>Related: OS#4849<br>Change-Id: Ifae1a7b2b3dfad8df19585063088ba0df2749c8f<br>---<br>M src/encoding.cpp<br>M src/encoding.h<br>M src/tbf_dl.cpp<br>3 files changed, 80 insertions(+), 60 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/87/21387/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/encoding.cpp b/src/encoding.cpp</span><br><span>index 23e1460..847e0a1 100644</span><br><span>--- a/src/encoding.cpp</span><br><span>+++ b/src/encoding.cpp</span><br><span>@@ -1397,9 +1397,10 @@</span><br><span>                      "larger than space (%d) left in block: copy "</span><br><span>                      "only remaining space, and we are done\n",</span><br><span>                         chunk, space);</span><br><span style="color: hsl(0, 100%, 40%);">-          /* block is filled, so there is no extension */</span><br><span style="color: hsl(0, 100%, 40%);">-         if (e_pointer)</span><br><span style="color: hsl(0, 100%, 40%);">-                  *e_pointer |= 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (e_pointer) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* LLC frame not finished, so there is no extension octet */</span><br><span style="color: hsl(120, 100%, 40%);">+                  *e_pointer |= 0x02; /* set previous M bit = 1 */</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span>            /* fill only space */</span><br><span>                llc->consume(data, space);</span><br><span>                if (count_payload)</span><br><span>@@ -1438,6 +1439,10 @@</span><br><span>          if (delimiter != data)</span><br><span>                       memmove(delimiter + 1, delimiter,</span><br><span>                            data - delimiter);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (e_pointer) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      *e_pointer &= 0xfe; /* set previous E bit = 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+                  *e_pointer |= 0x02; /* set previous M bit = 1 */</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span>            data++;</span><br><span>              (*offset)++;</span><br><span>                 space--;</span><br><span>@@ -1465,12 +1470,16 @@</span><br><span>   /* make space for delimiter */</span><br><span>       if (delimiter != data)</span><br><span>               memmove(delimiter + 1, delimiter, data - delimiter);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (e_pointer) {</span><br><span style="color: hsl(120, 100%, 40%);">+              *e_pointer &= 0xfe; /* set previous E bit = 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+          *e_pointer |= 0x02; /* set previous M bit = 1 */</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span>    data++;</span><br><span>      (*offset)++;</span><br><span>         space--;</span><br><span>     /* add LI to delimit frame */</span><br><span>        li = (struct rlc_li_field *)delimiter;</span><br><span style="color: hsl(0, 100%, 40%);">-  li->e = 0; /* Extension bit, maybe set later */</span><br><span style="color: hsl(120, 100%, 40%);">+    li->e = 1; /*  not more extension, maybe set later */</span><br><span>     li->m = 0; /* will be set later, if there is more LLC data */</span><br><span>     li->li = chunk; /* length of chunk */</span><br><span>     rdbi->e = 0; /* 0: extensions present */</span><br><span>@@ -1483,22 +1492,19 @@</span><br><span>        space -= chunk;</span><br><span>      (*offset) += chunk;</span><br><span>  /* if we have more data and we have space left */</span><br><span style="color: hsl(0, 100%, 40%);">-       if (space > 0 && !is_final) {</span><br><span style="color: hsl(0, 100%, 40%);">-                li->m = 1; /* we indicate more frames to follow */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (space > 0 && !is_final)</span><br><span>               return Encoding::AR_COMPLETED_SPACE_LEFT;</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* if we don't have more LLC frames */</span><br><span>   if (is_final) {</span><br><span>              LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "</span><br><span>                       "done.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-           li->e = 1; /* we cannot extend */</span><br><span>                 rdbi->cv = 0;</span><br><span>             return Encoding::AR_COMPLETED_BLOCK_FILLED;</span><br><span>  }</span><br><span>    /* we have no space left */</span><br><span>  LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "</span><br><span>                 "done.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-   li->e = 1; /* we cannot extend */</span><br><span>         return Encoding::AR_COMPLETED_BLOCK_FILLED;</span><br><span> }</span><br><span> </span><br><span>@@ -1594,7 +1600,7 @@</span><br><span>         space     -= 1;</span><br><span>      /* add LI to delimit frame */</span><br><span>        li = (struct rlc_li_field_egprs *)delimiter;</span><br><span style="color: hsl(0, 100%, 40%);">-    li->e = 1; /* Extension bit, maybe set later */</span><br><span style="color: hsl(120, 100%, 40%);">+    li->e = 1; /* not more extension, maybe set later */</span><br><span>      li->li = chunk; /* length of chunk */</span><br><span>     /* tell previous extension header about the new one */</span><br><span>       if (prev_li)</span><br><span>@@ -1611,56 +1617,21 @@</span><br><span>       space -= chunk;</span><br><span>      (*offset) += chunk;</span><br><span>  /* if we have more data and we have space left */</span><br><span style="color: hsl(0, 100%, 40%);">-       if (space > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!is_final)</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!is_final) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (space > 0) {</span><br><span>                  return Encoding::AR_COMPLETED_SPACE_LEFT;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* we have no space left */</span><br><span style="color: hsl(120, 100%, 40%);">+                   LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "</span><br><span style="color: hsl(120, 100%, 40%);">+                          "done.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                 return Encoding::AR_COMPLETED_BLOCK_FILLED;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span>             /* we don't have more LLC frames */</span><br><span style="color: hsl(0, 100%, 40%);">-         /* We will have to add another chunk with filling octets */</span><br><span style="color: hsl(0, 100%, 40%);">-             LOGP(DRLCMACDL, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">-                     "-- There is remaining space (%d): add filling byte chunk\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                 space);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         if (delimiter != data)</span><br><span style="color: hsl(0, 100%, 40%);">-                  memmove(delimiter + 1, delimiter, data - delimiter);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            data      += 1;</span><br><span style="color: hsl(0, 100%, 40%);">-         (*offset) += 1;</span><br><span style="color: hsl(0, 100%, 40%);">-         space     -= 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         /* set filling bytes extension */</span><br><span style="color: hsl(0, 100%, 40%);">-               li = (struct rlc_li_field_egprs *)delimiter;</span><br><span style="color: hsl(0, 100%, 40%);">-            li->e = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-           li->li = 127;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                /* tell previous extension header about the new one */</span><br><span style="color: hsl(0, 100%, 40%);">-          if (prev_li)</span><br><span style="color: hsl(0, 100%, 40%);">-                    prev_li->e = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              delimiter++;</span><br><span style="color: hsl(0, 100%, 40%);">-            (*num_chunks)++;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                rdbi->cv = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "</span><br><span style="color: hsl(0, 100%, 40%);">-                  "are done.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               *offset = rdbi->data_len;</span><br><span style="color: hsl(0, 100%, 40%);">-            return Encoding::AR_COMPLETED_BLOCK_FILLED;</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 (is_final) {</span><br><span style="color: hsl(0, 100%, 40%);">-         /* we don't have more LLC frames */</span><br><span style="color: hsl(0, 100%, 40%);">-         LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "</span><br><span style="color: hsl(0, 100%, 40%);">-                  "are done.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we are done.\n");</span><br><span>          rdbi->cv = 0;</span><br><span>             return Encoding::AR_COMPLETED_BLOCK_FILLED;</span><br><span>  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* we have no space left */</span><br><span style="color: hsl(0, 100%, 40%);">-     LOGP(DRLCMACDL, LOGL_DEBUG, "-- No space left, so we are "</span><br><span style="color: hsl(0, 100%, 40%);">-            "done.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-   return Encoding::AR_COMPLETED_BLOCK_FILLED;</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -1697,6 +1668,36 @@</span><br><span>         return AR_NEED_MORE_BLOCKS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void Encoding::rlc_data_to_dl_append_egprs_li_padding(</span><br><span style="color: hsl(120, 100%, 40%);">+  int offset, int num_chunks, uint8_t *data_block)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct rlc_li_field_egprs *li;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct rlc_li_field_egprs *prev_li;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t *delimiter, *data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGP(DRLCMACDL, LOGL_DEBUG, "Adding LI=127 to signal padding\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ data = data_block + offset;</span><br><span style="color: hsl(120, 100%, 40%);">+   delimiter = data_block + num_chunks;</span><br><span style="color: hsl(120, 100%, 40%);">+  prev_li = (struct rlc_li_field_egprs *)</span><br><span style="color: hsl(120, 100%, 40%);">+               (num_chunks ? delimiter - 1 : NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* we don't have more LLC frames */</span><br><span style="color: hsl(120, 100%, 40%);">+       /* We will have to add another chunk with filling octets */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (delimiter != data)</span><br><span style="color: hsl(120, 100%, 40%);">+                memmove(delimiter + 1, delimiter, data - delimiter);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* set filling bytes extension */</span><br><span style="color: hsl(120, 100%, 40%);">+     li = (struct rlc_li_field_egprs *)delimiter;</span><br><span style="color: hsl(120, 100%, 40%);">+  li->e = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ li->li = 127;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* tell previous extension header about the new one */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (prev_li)</span><br><span style="color: hsl(120, 100%, 40%);">+          prev_li->e = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*</span><br><span>  * Refer 44.060 version 7.27.0 Release 7</span><br><span>  * section 7.1.3.2.1 On receipt of a PACKET RESOURCE REQUEST message</span><br><span>diff --git a/src/encoding.h b/src/encoding.h</span><br><span>index 5f8496e..6ac004d 100644</span><br><span>--- a/src/encoding.h</span><br><span>+++ b/src/encoding.h</span><br><span>@@ -104,4 +104,6 @@</span><br><span>                 struct gprs_rlc_data_block_info *rdbi, enum CodingScheme cs,</span><br><span>                 gprs_llc *llc, int *offset, int *num_chunks,</span><br><span>                 uint8_t *data, bool is_final, int *count_payload);</span><br><span style="color: hsl(120, 100%, 40%);">+    static void rlc_data_to_dl_append_egprs_li_padding(</span><br><span style="color: hsl(120, 100%, 40%);">+           int offset, int num_chunks, uint8_t *data_block);</span><br><span> };</span><br><span>diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp</span><br><span>index 4b184b8..d932a83 100644</span><br><span>--- a/src/tbf_dl.cpp</span><br><span>+++ b/src/tbf_dl.cpp</span><br><span>@@ -680,9 +680,30 @@</span><br><span>          int payload_written = 0;</span><br><span> </span><br><span>                 if (m_llc.frame_length() == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* nothing to sent - delay the release of the TBF */</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* It is not clear, when the next real data will</span><br><span style="color: hsl(120, 100%, 40%);">+                       * arrive, so request a DL ack/nack now */</span><br><span style="color: hsl(120, 100%, 40%);">+                    request_dl_ack();</span><br><span> </span><br><span>                        int space = block_data_len - write_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (num_chunks != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                /* Nothing to send, and we already put some data in</span><br><span style="color: hsl(120, 100%, 40%);">+                            * rlcmac data block, we are done */</span><br><span style="color: hsl(120, 100%, 40%);">+                          LOGPTBFDL(this, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "LLC queue completely drained and there's "</span><br><span style="color: hsl(120, 100%, 40%);">+                                     "still %d free bytes in rlcmac data block\n", space);</span><br><span style="color: hsl(120, 100%, 40%);">+                             if (mcs_is_edge(cs)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        /* in EGPRS there's no M bit, so we need</span><br><span style="color: hsl(120, 100%, 40%);">+                                   * to flag padding with LI=127 */</span><br><span style="color: hsl(120, 100%, 40%);">+                                     Encoding::rlc_data_to_dl_append_egprs_li_padding(write_offset, num_chunks, data);</span><br><span style="color: hsl(120, 100%, 40%);">+                             }</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%);">+                   /* Nothing to send from upper layers (LLC), but still</span><br><span style="color: hsl(120, 100%, 40%);">+                  * requested to send something to MS to delay the</span><br><span style="color: hsl(120, 100%, 40%);">+                      * release of the TBF. See 3GPP TS 44.060 9.3.1a</span><br><span style="color: hsl(120, 100%, 40%);">+                       * "Delayed release of downlink Temporary Block Flow" */</span><br><span>                   /* A header will need to by added, so we just need</span><br><span>                    * space-1 octets */</span><br><span>                         m_llc.put_dummy_frame(space - 1);</span><br><span>@@ -691,10 +712,6 @@</span><br><span>                     if (m_last_dl_drained_fn < 0)</span><br><span>                             m_last_dl_drained_fn = fn;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                  /* It is not clear, when the next real data will</span><br><span style="color: hsl(0, 100%, 40%);">-                         * arrive, so request a DL ack/nack now */</span><br><span style="color: hsl(0, 100%, 40%);">-                      request_dl_ack();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>                    LOGPTBFDL(this, LOGL_DEBUG,</span><br><span>                            "Empty chunk, added LLC dummy command of size %d, drained_since=%d\n",</span><br><span>                             m_llc.frame_length(), frames_since_last_drain(fn));</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21387">change 21387</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-pcu/+/21387"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-pcu </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ifae1a7b2b3dfad8df19585063088ba0df2749c8f </div>
<div style="display:none"> Gerrit-Change-Number: 21387 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>