<p>Max has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/12952">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Rewrite EGPRS Packet Uplink Assignment<br><br>Use bitvec_set_*() directly without external write pointer tracking to<br>simplify the code. This is part of IA Rest Octets (3GPP TS 44.018<br>§10.5.2.16) which is the last part of the message so it should not<br>interfere with the rest of encoding functions. Reusable fragments are<br>split into static helpers.<br><br>That's updated version of reverted commit.<br><br>Change-Id: I19cc4226e7e831e7d7f70212b2078f5589a87ff0<br>Related: OS#3014<br>---<br>M src/encoding.cpp<br>1 file changed, 117 insertions(+), 55 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/52/12952/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 29a62e7..6488b6e 100644</span><br><span>--- a/src/encoding.cpp</span><br><span>+++ b/src/encoding.cpp</span><br><span>@@ -36,6 +36,13 @@</span><br><span> #include <errno.h></span><br><span> #include <string.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define check(rc) { if (rc < 0) return rc; }</span><br><span style="color: hsl(120, 100%, 40%);">+#define set_x(bv, x) { if (bitvec_set_bit(bv, x) < 0) return -EOWNERDEAD; }</span><br><span style="color: hsl(120, 100%, 40%);">+#define set_0(bv) set_x(bv, ZERO)</span><br><span style="color: hsl(120, 100%, 40%);">+#define set_1(bv) set_x(bv, ONE)</span><br><span style="color: hsl(120, 100%, 40%);">+#define set_L(bv) set_x(bv, L)</span><br><span style="color: hsl(120, 100%, 40%);">+#define set_H(bv) set_x(bv, H)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* { 0 | 1 < TIMING_ADVANCE_INDEX : bit (4) > } */</span><br><span> static inline bool write_tai(bitvec *dest, unsigned& wp, int8_t tai)</span><br><span> {</span><br><span>@@ -88,6 +95,70 @@</span><br><span>              bitvec_write_field(dest, &wp, ts, 3);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 44.018 § 10.5.2.16:</span><br><span style="color: hsl(120, 100%, 40%);">+   { 0 | 1 < ALPHA : bit (4) > }</span><br><span style="color: hsl(120, 100%, 40%);">+   < GAMMA : bit (5) ></span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int write_alpha_gamma(bitvec *dest, uint8_t alpha, uint8_t gamma)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (alpha) {</span><br><span style="color: hsl(120, 100%, 40%);">+          set_1(dest);</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = bitvec_set_u64(dest, alpha, 4, false); /* ALPHA */</span><br><span style="color: hsl(120, 100%, 40%);">+               check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else</span><br><span style="color: hsl(120, 100%, 40%);">+                set_0(dest);                                /* No ALPHA */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = bitvec_set_u64(dest, gamma, 5, false);         /* GAMMA */</span><br><span style="color: hsl(120, 100%, 40%);">+       check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 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%);">+/* TBF_STARTING_TIME -- same as 3GPP TS 44.018 §10.5.2.38 Starting Time without tag: */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int write_tbf_start_time(bitvec *dest, uint32_t fn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Set values according to 3GPP TS 44.018 Table 10.5.2.38.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = bitvec_set_u64(dest, (fn / (26 * 51)) % 32, 5, false); /* T1' */</span><br><span style="color: hsl(120, 100%, 40%);">+     check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = bitvec_set_u64(dest, fn % 51, 6, false);               /* T3  */</span><br><span style="color: hsl(120, 100%, 40%);">+ check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = bitvec_set_u64(dest, fn % 26, 5, false);               /* T2  */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return rc;</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%);">+/* 3GPP TS 44.018 § 10.5.2.16:</span><br><span style="color: hsl(120, 100%, 40%);">+   < TFI_ASSIGNMENT : bit (5) ></span><br><span style="color: hsl(120, 100%, 40%);">+   < POLLING : bit ></span><br><span style="color: hsl(120, 100%, 40%);">+   0 -- The value '1' was allocated in an earlier version of the protocol and shall not be used.</span><br><span style="color: hsl(120, 100%, 40%);">+   < USF: bit (3) ></span><br><span style="color: hsl(120, 100%, 40%);">+   < USF_GRANULARITY : bit ></span><br><span style="color: hsl(120, 100%, 40%);">+   { 0 | 1 < P0 : bit (4) > < PR_MODE : bit (1) > }</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int write_tfi_usf(bitvec *dest, const gprs_rlcmac_ul_tbf *tbf, uint8_t usf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = bitvec_set_u64(dest, tbf->tfi(), 5, false); /* TFI_ASSIGNMENT */</span><br><span style="color: hsl(120, 100%, 40%);">+      check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  set_0(dest); /* POLLING -- no action is required from MS */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ set_0(dest); /* '1' was allocated in an earlier spec version and shall not be used */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = bitvec_set_u64(dest, usf, 3, false); /* USF */</span><br><span style="color: hsl(120, 100%, 40%);">+   check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+    set_0(dest); /* USF_GRANULARITY -- the mobile station shall transmit one RLC/MAC block */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   set_0(dest); /* No P0 nor PR_MODE */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int write_ia_rest_downlink(</span><br><span>         gprs_rlcmac_dl_tbf *tbf,</span><br><span>     bitvec * dest, unsigned& wp,</span><br><span>@@ -185,68 +256,60 @@</span><br><span>     return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int write_ia_rest_egprs_uplink(</span><br><span style="color: hsl(0, 100%, 40%);">-        gprs_rlcmac_ul_tbf *tbf,</span><br><span style="color: hsl(0, 100%, 40%);">-        bitvec * dest, unsigned& wp,</span><br><span style="color: hsl(0, 100%, 40%);">-        uint8_t usf, uint32_t fn,</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t alpha, uint8_t gamma, int8_t ta_idx,</span><br><span style="color: hsl(0, 100%, 40%);">-    enum ph_burst_type burst_type, uint16_t ra)</span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 44.018 §10.5.2.16 IA Rest Octets ::= EGPRS Packet Uplink Assignment */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline int write_ia_rest_egprs_uplink(const gprs_rlcmac_ul_tbf *tbf, bitvec *dest,</span><br><span style="color: hsl(120, 100%, 40%);">+                                         uint8_t usf, uint32_t fn,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             uint8_t alpha, uint8_t gamma, int8_t ta_idx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                          enum ph_burst_type burst_type, uint16_t ra)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   uint8_t extended_ra = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     extended_ra = (ra & 0x1F);</span><br><span style="color: hsl(120, 100%, 40%);">+        set_L(dest); set_H(dest);</span><br><span style="color: hsl(120, 100%, 40%);">+     set_0(dest); set_0(dest); /* 00 EGPRS Packet Uplink Assignment */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   bitvec_write_field(dest, &wp, 1, 2);    /* LH */</span><br><span style="color: hsl(0, 100%, 40%);">-    bitvec_write_field(dest, &wp, 0, 2);    /* 0 EGPRS Uplink Assignment */</span><br><span style="color: hsl(0, 100%, 40%);">-     bitvec_write_field(dest, &wp, extended_ra, 5);    /* Extended RA */</span><br><span style="color: hsl(0, 100%, 40%);">- bitvec_write_field(dest, &wp, 0, 1);    /* Access technology Request */</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = bitvec_set_u64(dest, ra & 0x1F, 5, false); /* Extended RA */</span><br><span style="color: hsl(120, 100%, 40%);">+ check(rc);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  if (tbf == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+    set_0(dest);                                    /* No Access Technologies Request */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                bitvec_write_field(dest, &wp, 0, 1); /* multiblock allocation */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+            set_1(dest); /* Single Block Allocation */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          if (alpha) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    bitvec_write_field(dest, &wp, 0x1, 1); /* ALPHA =yes */</span><br><span style="color: hsl(0, 100%, 40%);">-                     bitvec_write_field(dest, &wp, alpha, 4); /* ALPHA */</span><br><span style="color: hsl(0, 100%, 40%);">-                } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        bitvec_write_field(dest, &wp, 0x0, 1); /* ALPHA = no */</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = write_tfi_usf(dest, tbf, usf);</span><br><span style="color: hsl(120, 100%, 40%);">+           check(rc);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power contrl */</span><br><span style="color: hsl(0, 100%, 40%);">-           bitvec_write_field(dest, &wp, (fn / (26 * 51)) % 32, 5);/* T1' */</span><br><span style="color: hsl(0, 100%, 40%);">-               bitvec_write_field(dest, &wp, fn % 51, 6);              /* T3 */</span><br><span style="color: hsl(0, 100%, 40%);">-            bitvec_write_field(dest, &wp, fn % 26, 5);              /* T2 */</span><br><span style="color: hsl(0, 100%, 40%);">-            bitvec_write_field(dest, &wp, 0, 2); /* Radio block allocation */</span><br><span style="color: hsl(120, 100%, 40%);">+         /* 3GPP TS 44.060 §12.10d EGPRS Modulation and coding Scheme description: */</span><br><span style="color: hsl(120, 100%, 40%);">+         rc = bitvec_set_u64(dest, tbf->current_cs().to_num() - 1, 4, false); /* EGPRS CHANNEL_CODING_COMMAND */</span><br><span style="color: hsl(120, 100%, 40%);">+            check(rc);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          bitvec_write_field(dest, &wp, 0, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = bitvec_set_bit(dest, (bit_value)tbf->tlli());                   /* TLLI_BLOCK_CHANNEL_CODING */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+           set_0(dest);                                                         /* No BEP_PERIOD2 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Retransmitted RLC data blocks shall not be re-segmented: (see 3GPP TS 44.060 §12.10e) */</span><br><span style="color: hsl(120, 100%, 40%);">+          set_0(dest); /* RESEGMENT */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                rc = bitvec_set_u64(dest, enc_ws(tbf->window_size()), 5, false); /* EGPRS Window Size */</span><br><span style="color: hsl(120, 100%, 40%);">+           check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = write_alpha_gamma(dest, alpha, gamma);                 /* ALPHA and GAMMA */</span><br><span style="color: hsl(120, 100%, 40%);">+             check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          set_0(dest);                                                /* No TIMING_ADVANCE_INDEX */</span><br><span style="color: hsl(120, 100%, 40%);">+             set_0(dest);                                                /* No TBF_STARTING_TIME */</span><br><span style="color: hsl(120, 100%, 40%);">+                bitvec_set_bit(dest, L);                                    /* No Additions for Rel-7 */</span><br><span>     } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                bitvec_write_field(dest, &wp, 1, 1);     /* single block alloc */</span><br><span style="color: hsl(0, 100%, 40%);">-           bitvec_write_field(dest, &wp, tbf->tfi(), 5);/* TFI assignment */</span><br><span style="color: hsl(0, 100%, 40%);">-                bitvec_write_field(dest, &wp, 0, 1);     /* polling bit */</span><br><span style="color: hsl(0, 100%, 40%);">-          bitvec_write_field(dest, &wp, 0, 1);     /* constant */</span><br><span style="color: hsl(0, 100%, 40%);">-             bitvec_write_field(dest, &wp, usf, 3);   /* USF bit */</span><br><span style="color: hsl(0, 100%, 40%);">-              bitvec_write_field(dest, &wp, 0, 1);     /* USF granularity */</span><br><span style="color: hsl(0, 100%, 40%);">-              bitvec_write_field(dest, &wp, 0, 1);     /* P0 */</span><br><span style="color: hsl(0, 100%, 40%);">-           /* MCS */</span><br><span style="color: hsl(0, 100%, 40%);">-               bitvec_write_field(dest, &wp, tbf->current_cs().to_num()-1, 4);</span><br><span style="color: hsl(0, 100%, 40%);">-          /* tlli channel block */</span><br><span style="color: hsl(0, 100%, 40%);">-                bitvec_write_field(dest, &wp, tbf->tlli(), 1);</span><br><span style="color: hsl(0, 100%, 40%);">-           bitvec_write_field(dest, &wp, 0, 1);   /* BEP period present */</span><br><span style="color: hsl(0, 100%, 40%);">-             bitvec_write_field(dest, &wp, 0, 1);   /* resegmentation */</span><br><span style="color: hsl(0, 100%, 40%);">-         write_ws(dest, &wp, tbf->window_size()); /* EGPRS window size */</span><br><span style="color: hsl(120, 100%, 40%);">+               set_0(dest); /* Multi Block Allocation */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (alpha) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    bitvec_write_field(dest, &wp, 0x1, 1);   /* ALPHA =yes */</span><br><span style="color: hsl(0, 100%, 40%);">-                   bitvec_write_field(dest, &wp, alpha, 4); /* ALPHA */</span><br><span style="color: hsl(0, 100%, 40%);">-                } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        bitvec_write_field(dest, &wp, 0x0, 1);   /* ALPHA = no */</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = write_alpha_gamma(dest, alpha, gamma); /* ALPHA and GAMMA */</span><br><span style="color: hsl(120, 100%, 40%);">+             check(rc);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power contrl */</span><br><span style="color: hsl(0, 100%, 40%);">-           bitvec_write_field(dest, &wp, 0, 1); /* TIMING_ADVANCE_INDEX */</span><br><span style="color: hsl(0, 100%, 40%);">-             bitvec_write_field(dest, &wp, 0, 1); /* TBF_STARTING_TIME_FLAG */</span><br><span style="color: hsl(0, 100%, 40%);">-           bitvec_write_field(dest, &wp, 0, 1); /* NULL */</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = write_tbf_start_time(dest, fn);        /* TBF_STARTING_TIME */</span><br><span style="color: hsl(120, 100%, 40%);">+           check(rc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          set_0(dest); /* NUMBER OF RADIO BLOCKS ALLOCATED: */</span><br><span style="color: hsl(120, 100%, 40%);">+          set_0(dest); /* 1 radio block reserved for uplink transmission */</span><br><span style="color: hsl(120, 100%, 40%);">+             set_0(dest); /* No P0 */</span><br><span>     }</span><br><span> </span><br><span>        return 0;</span><br><span>@@ -402,11 +465,10 @@</span><br><span>                                        polling, gsm48_ta_is_valid(ta), fn,</span><br><span>                      alpha, gamma, ta_idx);</span><br><span>       else if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||</span><br><span style="color: hsl(0, 100%, 40%);">-                 (burst_type == GSM_L1_BURST_TYPE_ACCESS_2)))</span><br><span style="color: hsl(0, 100%, 40%);">-            rc = write_ia_rest_egprs_uplink(as_ul_tbf(tbf), dest, wp,</span><br><span style="color: hsl(0, 100%, 40%);">-                       usf, fn,</span><br><span style="color: hsl(0, 100%, 40%);">-                        alpha, gamma, ta_idx, burst_type, ra);</span><br><span style="color: hsl(0, 100%, 40%);">-  else</span><br><span style="color: hsl(120, 100%, 40%);">+            (burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {</span><br><span style="color: hsl(120, 100%, 40%);">+              dest->cur_bit = wp;</span><br><span style="color: hsl(120, 100%, 40%);">+                rc = write_ia_rest_egprs_uplink(as_ul_tbf(tbf), dest, usf, fn, alpha, gamma, ta_idx, burst_type, ra);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else</span><br><span>               rc = write_ia_rest_uplink(as_ul_tbf(tbf), dest, wp,</span><br><span>                  usf, fn,</span><br><span>                     alpha, gamma, ta_idx);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12952">change 12952</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/12952"/><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-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I19cc4226e7e831e7d7f70212b2078f5589a87ff0 </div>
<div style="display:none"> Gerrit-Change-Number: 12952 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Max <msuraev@sysmocom.de> </div>