kirr has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmocom-bb/+/40080?usp=email )


Change subject: trx_toolkit/data_msg: Optimize RxMsg/TxMsg serialization
......................................................................

trx_toolkit/data_msg: Optimize RxMsg/TxMsg serialization

Thread all calls related to serialization to be done at C-level and with
explicit types. Replace struct.pack and bytearray .append and .extend
with C-level custom routines to do so.

Change-Id: Ia203d39c8906ca8bb2fac078a818219dcdcf2565
---
M src/target/trx_toolkit/data_if.pyx
M src/target/trx_toolkit/data_msg.pxd
M src/target/trx_toolkit/data_msg.pyx
3 files changed, 54 insertions(+), 13 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/80/40080/1

diff --git a/src/target/trx_toolkit/data_if.pyx 
b/src/target/trx_toolkit/data_if.pyx
index 71a1878..a23a52b 100644
--- a/src/target/trx_toolkit/data_if.pyx
+++ b/src/target/trx_toolkit/data_if.pyx
@@ -103,7 +103,7 @@
        cdef _send_msg(self, Msg msg, bint legacy = False):
                try:
                        # Validate and encode a TRXD message
-                       payload = msg.gen_msg(legacy)
+                       payload = msg._gen_msg(legacy)
                except ValueError as e:
                        log.error("Failed to encode a TRXD message ('%s') "
                                "due to error: %s" % (msg.desc_hdr(), e))
diff --git a/src/target/trx_toolkit/data_msg.pxd 
b/src/target/trx_toolkit/data_msg.pxd
index 6823397..29d1702 100644
--- a/src/target/trx_toolkit/data_msg.pxd
+++ b/src/target/trx_toolkit/data_msg.pxd
@@ -36,6 +36,7 @@
        cdef parse_burst(self, bytearray burst)
        cdef int _parse_msg(self, bytearray msg) except -1
        cdef _validate(self)
+       cdef bytearray _gen_msg(self, bint legacy)

        @staticmethod
        cdef void __usbit2sbit(const uint8_t *usbits, Py_ssize_t l, int8_t 
*sbits) noexcept
diff --git a/src/target/trx_toolkit/data_msg.pyx 
b/src/target/trx_toolkit/data_msg.pyx
index 34f6a12..98dbece 100644
--- a/src/target/trx_toolkit/data_msg.pyx
+++ b/src/target/trx_toolkit/data_msg.pyx
@@ -30,8 +30,10 @@
 from cpython.bytearray cimport PyByteArray_AS_STRING, PyByteArray_GET_SIZE
 from xpy cimport PyByteArray_Resize

+from libc.string cimport memcpy
+
+
 import random
-import struct
 import abc

 from typing import List
@@ -241,20 +243,22 @@
                if self.tn < 0 or self.tn > 7:
                        raise ValueError("TDMA time-slot %d is out of range" % 
self.tn)

-       def gen_msg(self, legacy = False):
+       def gen_msg(self, bint legacy = False):
+               return self._gen_msg(legacy)
+       cdef bytearray _gen_msg(self, bint legacy):
                ''' Generate a TRX DATA message. '''

                # Validate all the fields
                self._validate()

                # Allocate an empty byte-array
-               buf = bytearray()
+               cdef bytearray buf = PyByteArray_FromStringAndSize(NULL, 0)

                # Put version (4 bits) and TDMA TN (3 bits)
-               buf.append((self.ver << 4) | (self.tn & 0x07))
+               _append_u8(buf, (self.ver << 4) | (self.tn & 0x07))

                # Put TDMA FN (4 octets, BE)
-               buf += struct.pack(">L", self.fn)
+               _append_u32(buf, self.fn)

                # Generate message specific header part
                self.append_hdr_to(buf)
@@ -265,7 +269,7 @@
                # This is a rudiment from (legacy) OpenBTS transceiver,
                # some L1 implementations still expect two dummy bytes.
                if legacy and self.ver == 0x00:
-                       buf += bytearray(2)
+                       _append_u16(buf, 0)

                return buf

@@ -388,7 +392,7 @@
                ''' Generate message specific header by appending it to buf. '''

                # Put power
-               buf.append(self.pwr)
+               _append_u8(buf, self.pwr)

        cdef parse_hdr(self, bytearray msg):
                ''' Parse message specific header part. '''
@@ -404,7 +408,10 @@
                # Copy burst 'as is'
                if self.burst is None:
                        return
-               return buf.extend(self.burst)
+               l = PyByteArray_GET_SIZE(buf)
+               PyByteArray_Resize(buf, l+len(self.burst))
+               memcpy(&PyByteArray_AS_STRING(buf)[l],
+                          PyByteArray_AS_STRING(self.burst), len(self.burst))

        cdef parse_burst(self, bytearray burst):
                ''' Parse message specific burst. '''
@@ -691,19 +698,20 @@
                ''' Generate message specific header by appending it to buf. '''

                # Put RSSI
-               buf.append(-self.rssi)
+               _append_u8(buf, -self.rssi)

                # Encode ToA (Time of Arrival)
                # Big endian, 2 bytes (int32_t)
-               buf += struct.pack(">h", self.toa256)
+               _append_s16(buf, self.toa256)

                if self.ver >= 0x01:
                        # Modulation and Training Sequence info
                        mts = self.gen_mts()
-                       buf.append(mts)
+                       _append_u8(buf, mts)
+

                        # C/I: Carrier-to-Interference ratio (in centiBels)
-                       buf += struct.pack(">h", self.ci)
+                       _append_s16(buf, self.ci)

        cdef parse_hdr(self, bytearray msg):
                ''' Parse message specific header part. '''
@@ -786,6 +794,38 @@

 # ---- misc ----

+# _append_(u|s)(8|16|32) append to bytearray buf big-endian representation of 
specified integer v.
+
+cdef int _append_u8(bytearray buf, uint8_t v) except -1:
+       l = PyByteArray_GET_SIZE(buf)
+       PyByteArray_Resize(buf, l+1)
+       PyByteArray_AS_STRING(buf)[l] = v
+
+
+cdef int _append_u16(bytearray buf, uint16_t v) except -1:
+       l = PyByteArray_GET_SIZE(buf)
+       PyByteArray_Resize(buf, l+2)
+       x = &PyByteArray_AS_STRING(buf)[l]
+       x[0] = (v >> 8) & 0xff
+       x[1] = (v >> 0) & 0xff
+
+cdef int _append_s16(bytearray buf, int16_t v) except -1:
+       l = PyByteArray_GET_SIZE(buf)
+       PyByteArray_Resize(buf, l+2)
+       x = &PyByteArray_AS_STRING(buf)[l]
+       x[0] = <uint8_t>((v >> 8) & 0xff)
+       x[1] = <uint8_t>((v >> 0) & 0xff)
+
+cdef int _append_u32(bytearray buf, uint32_t v) except -1:
+       l = PyByteArray_GET_SIZE(buf)
+       PyByteArray_Resize(buf, l+4)
+       x = &PyByteArray_AS_STRING(buf)[l]
+       x[0] = (v >> 24) & 0xff
+       x[1] = (v >> 16) & 0xff
+       x[2] = (v >>  8) & 0xff
+       x[3] = (v >>  0) & 0xff
+
+
 # _unpack_(u|s)(16|32) deserialize big-endian representation of corresponding 
integer type from memory pointed by b.

 cdef int16_t _unpack_s16(const uint8_t *b):

--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/40080?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: Ia203d39c8906ca8bb2fac078a818219dcdcf2565
Gerrit-Change-Number: 40080
Gerrit-PatchSet: 1
Gerrit-Owner: kirr <k...@nexedi.com>
Gerrit-CC: fixeria <vyanits...@sysmocom.de>
Gerrit-CC: osmith <osm...@sysmocom.de>
Gerrit-CC: pespin <pes...@sysmocom.de>

Reply via email to