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 <kirr(a)nexedi.com>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-CC: osmith <osmith(a)sysmocom.de>
Gerrit-CC: pespin <pespin(a)sysmocom.de>