Change in ...osmo-bts[master]: osmo-bts-trx/trx_if.c: introduce TRXD header version handling

fixeria gerrit-no-reply at lists.osmocom.org
Wed Jun 26 06:50:00 UTC 2019


fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bts/+/14592


Change subject: osmo-bts-trx/trx_if.c: introduce TRXD header version handling
......................................................................

osmo-bts-trx/trx_if.c: introduce TRXD header version handling

It may be necessary to extend the message specific header with
more information. Since this is not a TLV-based protocol, we
need to include the header format version.

  +-----------------+---------------------------+
  | 7 6 5 4 3 2 1 0 | bit numbers (value range) |
  +-----------------+---------------------------+
  | X X X X . . . . | header version (0..15)    |
  +-----------------+---------------------------+
  | . . . . . X X X | TDMA TN (0..7)            |
  +-----------------+---------------------------+
  | . . . . X . . . | RESERVED (0)              |
  +-----------------+---------------------------+

Instead of prepending an additional byte, it was decided to use
4 MSB bits of the first octet, which used to be zero-initialized
due to the value range of TDMA TN (0..7). Therefore the current
header format has implicit version 0x00.

Otherwise Wireshark (or trx_sniff.py) would have to guess the
header version, or alternatively follow the control channel
looking for the version setting command.

This change introduces a new structure 'trx_ul_burst_ind', which
represents an Uplink burst and the corresponding meta info. The
purpose of this structure is to avoid overloading the existing
functions, such as trx_sched_ul_burst(), with more and more
arguments every time we bump the version.

On receipt of a TRXD message, trx_data_read_cb() now parses
the header version, and calls the corresponding dissector
function, e.g. trx_data_handle_v0() for version 0x00.

Change-Id: I171c18229ca3e5cab70de0064a31e47c78602c0c
Related: OS#4006
---
M include/osmo-bts/scheduler.h
M src/common/scheduler.c
M src/osmo-bts-trx/trx_if.c
3 files changed, 180 insertions(+), 53 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/92/14592/1

diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index c862307..695700d 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -173,10 +173,6 @@
 /*! \brief PHY informs us of new (current) GSM frame number */
 int trx_sched_clock(struct gsm_bts *bts, uint32_t fn);
 
-/*! \brief handle an UL burst received by PHY */
-int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-        sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa);
-
 /*! \brief set multiframe scheduler to given physical channel config */
 int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
         enum gsm_phys_chan_config pchan);
@@ -231,4 +227,20 @@
 bool trx_sched_is_sacch_fn(struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink);
 extern const struct trx_sched_multiframe trx_sched_multiframes[];
 
+/*! UL burst indication with the corresponding meta info */
+struct trx_ul_burst_ind {
+	/* Mandatory fields */
+	uint32_t fn;		/*!< TDMA frame number */
+	uint8_t tn;		/*!< TDMA time-slot number */
+	int16_t toa256;		/*!< Timing of Arrival in units of 1/256 of symbol */
+	int8_t rssi;		/*!< Received Signal Strength Indication */
+
+	/* Burst soft-bits */
+	size_t burst_len;
+	sbit_t *burst;
+};
+
+/*! Handle an UL burst received by PHY */
+int trx_sched_ul_burst(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi);
+
 #endif /* TRX_SCHEDULER_H */
diff --git a/src/common/scheduler.c b/src/common/scheduler.c
index 3f804a9..7b51a2a 100644
--- a/src/common/scheduler.c
+++ b/src/common/scheduler.c
@@ -1313,11 +1313,10 @@
 	return 0;
 }
 
-/* process uplink burst */
-int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	sbit_t *bits, uint16_t nbits, int8_t rssi, int16_t toa256)
+/* Process an Uplink burst indication */
+int trx_sched_ul_burst(struct l1sched_trx *l1t, const struct trx_ul_burst_ind *bi)
 {
-	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
+	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, bi->tn);
 	struct l1sched_chan_state *l1cs;
 	const struct trx_sched_frame *frame;
 	uint8_t offset, period, bid;
@@ -1329,7 +1328,7 @@
 
 	/* get frame from multiframe */
 	period = l1ts->mf_period;
-	offset = fn % period;
+	offset = bi->fn % period;
 	frame = l1ts->mf_frames + offset;
 
 	chan = frame->ul_chan;
@@ -1346,28 +1345,29 @@
 		return -EINVAL;
 
 	/* calculate how many TDMA frames were potentially lost */
-	trx_sched_calc_frame_loss(l1t, l1cs, tn, fn);
+	trx_sched_calc_frame_loss(l1t, l1cs, bi->tn, bi->fn);
 
 	/* update TDMA frame counters */
-	l1cs->last_tdma_fn = fn;
+	l1cs->last_tdma_fn = bi->fn;
 	l1cs->proc_tdma_fs++;
 
 	/* decrypt */
-	if (bits && l1cs->ul_encr_algo) {
+	if (bi->burst && l1cs->ul_encr_algo) {
 		ubit_t ks[114];
 		int i;
 
-		osmo_a5(l1cs->ul_encr_algo, l1cs->ul_encr_key, fn, NULL, ks);
+		osmo_a5(l1cs->ul_encr_algo, l1cs->ul_encr_key, bi->fn, NULL, ks);
 		for (i = 0; i < 57; i++) {
 			if (ks[i])
-				bits[i + 3] = - bits[i + 3];
+				bi->burst[i + 3] = - bi->burst[i + 3];
 			if (ks[i + 57])
-				bits[i + 88] = - bits[i + 88];
+				bi->burst[i + 88] = - bi->burst[i + 88];
 		}
 	}
 
-	/* put burst to function */
-	func(l1t, tn, fn, chan, bid, bits, nbits, rssi, toa256);
+	/* put burst to function
+	 * TODO: rather pass a pointer to trx_ul_burst_ind */
+	func(l1t, bi->tn, bi->fn, chan, bid, bi->burst, bi->burst_len, bi->rssi, bi->toa256);
 
 	return 0;
 }
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index fde4d50..e4abc8a 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -7,6 +7,7 @@
  *
  * Copyright (C) 2013  Andreas Eversberg <jolly at eversberg.eu>
  * Copyright (C) 2016-2017  Harald Welte <laforge at gnumonks.org>
+ * Copyright (C) 2019  Vadim Yanitskiy <axilirator at gmail.com>
  *
  * All Rights Reserved
  *
@@ -590,65 +591,179 @@
  * TRX burst data socket
  */
 
+/* Common header length: 1/2 VER + 1/2 TDMA TN + 4 TDMA FN */
+#define TRX_CHDR_LEN (1 + 4)
+/* Uplink v0 header length: 1 RSSI + 2 ToA256 */
+#define TRX_UL_V0HDR_LEN (TRX_CHDR_LEN + 1 + 2)
+
+/* TRXD header dissector for version 0x00 */
+static int trx_data_handle_v0(struct trx_l1h *l1h,
+			      struct trx_ul_burst_ind *bi,
+			      const uint8_t *buf, size_t buf_len)
+{
+	/* Make sure we have enough data */
+	if (buf_len < TRX_UL_V0HDR_LEN) {
+		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR,
+			"Short read on TRXD, missing version 0 header "
+			"(len=%zu vs expected %d)\n", buf_len, TRX_UL_V0HDR_LEN);
+		return -EIO;
+	}
+
+	bi->tn = buf[0] & 0b111;
+	bi->fn = osmo_load32be(buf + 1);
+	bi->rssi = -(int8_t)buf[5];
+	bi->toa256 = (int16_t) osmo_load16be(buf + 6);
+
+	if (bi->fn >= GSM_HYPERFRAME) {
+		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR,
+			"Illegal TDMA fn=%u\n", bi->fn);
+		return -EINVAL;
+	}
+
+	return TRX_UL_V0HDR_LEN;
+}
+
+/* Parse TRXD message from transceiver, compose an UL burst indication.
+ *
+ * This message contains a demodulated Uplink burst with fixed-size
+ * header preceding the burst bits. The header consists of the common
+ * and message specific part.
+ *
+ *   +---------------+-----------------+------------+
+ *   | common header | specific header | burst bits |
+ *   +---------------+-----------------+------------+
+ *
+ * Common header is the same as for Downlink message:
+ *
+ *   +-----------------+----------------+-------------------+
+ *   | VER (1/2 octet) | TN (1/2 octet) | FN (4 octets, BE) |
+ *   +-----------------+----------------+-------------------+
+ *
+ * and among with TDMA parameters, contains the version indicator:
+ *
+ *   +-----------------+------------------------+
+ *   | 7 6 5 4 3 2 1 0 | bit numbers            |
+ *   +-----------------+------------------------+
+ *   | X X X X . . . . | header version (0..15) |
+ *   +-----------------+------------------------+
+ *   | . . . . . X X X | TDMA TN (0..7)         |
+ *   +-----------------+------------------------+
+ *   | . . . . X . . . | RESERVED (0)           |
+ *   +-----------------+------------------------+
+ *
+ * which is encoded in 4 MSB bits of the first octet, which used to be
+ * zero-initialized due to the value range of TDMA TN. Therefore, the
+ * old header format has implicit version 0x00.
+ *
+ * The message specific header has the following structure:
+ *
+ * == Version 0x00
+ *
+ *   +------+-----+--------------------+
+ *   | RSSI | ToA | soft-bits (254..0) |
+ *   +------+-----+--------------------+
+ *
+ * where:
+ *
+ *   - RSSI (1 octet) - Received Signal Strength Indication
+ *     encoded without the negative sign.
+ *   - ToA (2 octets) - Timing of Arrival in units of 1/256
+ *     of symbol (big endian).
+ *
+ * == Coding of the burst bits
+ *
+ * Unlike to be transmitted bursts, the received bursts are designated
+ * using the soft-bits notation, so the receiver can indicate its
+ * assurance from 0 to -127 that a given bit is 1, and from 0 to +127
+ * that a given bit is 0.
+ *
+ * Each soft-bit (-127..127) of the burst is encoded as an unsigned
+ * value in range (254..0) respectively using the constant shift.
+ *
+ */
 static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
 {
 	struct trx_l1h *l1h = ofd->data;
 	uint8_t buf[TRX_MAX_BURST_LEN];
-	int len;
-	uint8_t tn;
-	int8_t rssi;
-	int16_t toa256 = 0;
-	uint32_t fn;
 	sbit_t bits[EGPRS_BURST_LEN];
-	int i, burst_len = GSM_BURST_LEN;
+	struct trx_ul_burst_ind bi;
+	ssize_t hdr_len, buf_len;
+	uint8_t *burst_bits;
+	uint8_t hdr_ver;
+	int i;
 
-	len = recv(ofd->fd, buf, sizeof(buf), 0);
-	if (len <= 0) {
-		return len;
-	} else if (len == EGPRS_BURST_LEN + 10) {
-		burst_len = EGPRS_BURST_LEN;
-	/* Accept bursts ending with 2 bytes of padding (OpenBTS compatible trx) or without them: */
-	} else if (len != GSM_BURST_LEN + 10 && len != GSM_BURST_LEN + 8) {
-		LOGPPHI(l1h->phy_inst, DTRX, LOGL_NOTICE, "Got data message with invalid lenght "
-			"'%d'\n", len);
+	buf_len = recv(ofd->fd, buf, sizeof(buf), 0);
+	if (buf_len <= 0) {
+		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR,
+			"recv() failed on TRXD with rc=%zd\n", buf_len);
+		return buf_len;
+	}
+
+	/* Parse the header depending on its version */
+	hdr_ver = buf[0] >> 4;
+	switch (hdr_ver) {
+	case 0x00:
+		/* Legacy protocol has no version indicator */
+		hdr_len = trx_data_handle_v0(l1h, &bi, buf, buf_len);
+		break;
+	default:
+		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR,
+			"TRXD header version %u is not supported\n", hdr_ver);
+		return -ENOTSUP;
+	}
+
+	/* Header parsing error */
+	if (hdr_len < 0)
+		return hdr_len;
+
+	/* We're done with the header now */
+	burst_bits = buf + hdr_len;
+	buf_len -= hdr_len;
+
+	/* Verify burst length */
+	switch (buf_len) {
+	/* Legacy transceivers append two padding bytes */
+	case EGPRS_BURST_LEN + 2:
+	case GSM_BURST_LEN + 2:
+		buf_len -= 2;
+		break;
+	case EGPRS_BURST_LEN:
+	case GSM_BURST_LEN:
+		break;
+
+	default:
+		LOGPPHI(l1h->phy_inst, DTRX, LOGL_NOTICE,
+			"Rx TRXD message with odd burst length %zu\n", buf_len);
 		return -EINVAL;
 	}
-	tn = buf[0];
-	fn =  osmo_load32be(buf + 1);
-	rssi = -(int8_t)buf[5];
-	toa256 = (int16_t) osmo_load16be(buf + 6);
 
-	/* copy and convert bits {254..0} to sbits {-127..127} */
-	for (i = 0; i < burst_len; i++) {
-		if (buf[8 + i] == 255)
+	/* Convert unsigned soft-bits [254..0] to soft-bits [-127..127] */
+	for (i = 0; i < buf_len; i++) {
+		if (burst_bits[i] == 255)
 			bits[i] = -127;
 		else
-			bits[i] = 127 - buf[8 + i];
+			bits[i] = 127 - burst_bits[i];
 	}
 
-	if (tn >= 8) {
-		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR, "Illegal TS %d\n", tn);
-		return -EINVAL;
-	}
-	if (fn >= GSM_HYPERFRAME) {
-		LOGPPHI(l1h->phy_inst, DTRX, LOGL_ERROR, "Illegal FN %u\n", fn);
-		return -EINVAL;
-	}
+	bi.burst_len = buf_len;
+	bi.burst = bits;
 
-	LOGPPHI(l1h->phy_inst, DTRX, LOGL_DEBUG, "RX burst tn=%u fn=%u rssi=%d toa256=%d\n",
-		tn, fn, rssi, toa256);
+	LOGPPHI(l1h->phy_inst, DTRX, LOGL_DEBUG,
+		"Rx UL burst (hdr_ver=%u) tn=%u fn=%u rssi=%d toa256=%d\n",
+		hdr_ver, bi.tn, bi.fn, bi.rssi, bi.toa256);
 
 #ifdef TOA_RSSI_DEBUG
 	char deb[128];
 
 	sprintf(deb, "|                                0              "
-		"                 | rssi=%4d  toa=%5d fn=%u", rssi, toa256, fn);
-	deb[1 + (128 + rssi) / 4] = '*';
+		"                 | rssi=%4d  toa=%5d fn=%u",
+		bi.rssi, bi.toa256, bi.fn);
+	deb[1 + (128 + bi.rssi) / 4] = '*';
 	fprintf(stderr, "%s\n", deb);
 #endif
 
 	/* feed received burst into scheduler code */
-	trx_sched_ul_burst(&l1h->l1s, tn, fn, bits, burst_len, rssi, toa256);
+	trx_sched_ul_burst(&l1h->l1s, &bi);
 
 	return 0;
 }

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/14592
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I171c18229ca3e5cab70de0064a31e47c78602c0c
Gerrit-Change-Number: 14592
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <axilirator at gmail.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190626/4ced5970/attachment-0001.html>


More information about the gerrit-log mailing list