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>