Change in osmocom-bb[master]: trxcon/scheduler: fix Measurement Reporting on SACCH

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Vadim Yanitskiy gerrit-no-reply at lists.osmocom.org
Fri Sep 28 01:30:02 UTC 2018


Vadim Yanitskiy has uploaded this change for review. ( https://gerrit.osmocom.org/11138


Change subject: trxcon/scheduler: fix Measurement Reporting on SACCH
......................................................................

trxcon/scheduler: fix Measurement Reporting on SACCH

According to 3GPP TS 04.08, section 3.4.1, SACCH logical channel
accompanies either a traffic or a signaling channel. It has the
particularity that continuous transmission must occur in both
directions, so on the Uplink direction measurement result messages
are sent at each possible occasion when nothing else has to be sent.
The LAPDm fill frames (0x01, 0x03, 0x01, 0x2b, ...) are not
applicable on SACCH channels!

Unfortunately, 3GPP TS 04.08 doesn't clearly state which "else
messages" besides Measurement Reports can be send by the MS on
SACCH channels. However, in sub-clause 3.4.1 it's stated that
the interval between two successive measurement result messages
shall not exceed one L2 frame.

This change introduces a separate handler for SACCH primitives,
which dequeues a SACCH primitive from transmit queue, if present.
Otherwise it dequeues a cached Measurement Report (the last
received one). Finally, if the cache is empty, a "dummy"
measurement report is used. When it's possible,
a non-MR primitive is prioritized.

Change-Id: If1b8dc74ced746d6270676fdde75fcda32f91a3d
Related: OS#2988
---
M src/host/trxcon/sched_prim.c
M src/host/trxcon/sched_trx.c
M src/host/trxcon/sched_trx.h
3 files changed, 197 insertions(+), 14 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/38/11138/1

diff --git a/src/host/trxcon/sched_prim.c b/src/host/trxcon/sched_prim.c
index e03f93f..0f3258f 100644
--- a/src/host/trxcon/sched_prim.c
+++ b/src/host/trxcon/sched_prim.c
@@ -126,6 +126,180 @@
 	return 0;
 }
 
+/**
+ * Composes a new primitive using either cached (if populated),
+ * or "dummy" Measurement Report message.
+ *
+ * @param  lchan lchan to assign a primitive
+ * @return       SACCH primitive to be transmitted
+ */
+static struct trx_ts_prim *prim_compose_mr(struct trx_lchan_state *lchan)
+{
+	struct trx_ts_prim *prim;
+	uint8_t *mr_src_ptr;
+	bool cached;
+	int rc;
+
+	/* "Dummy" Measurement Report */
+	static const uint8_t meas_rep_dummy[] = {
+		/* L1 SACCH pseudo-header */
+		0x0f, 0x00,
+
+		/* LAPDm header */
+		0x01, 0x03, 0x49,
+
+		/* Measurement report */
+		0x06, 0x15, 0x36, 0x36, 0x01, 0xC0,
+
+		/* TODO: Padding? Randomize if so */
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	};
+
+	/* Allocate a new primitive */
+	rc = sched_prim_init(lchan, &prim, GSM_MACBLOCK_LEN,
+		trx_lchan_desc[lchan->type].chan_nr, TRX_CH_LID_SACCH);
+	OSMO_ASSERT(rc == 0);
+
+	/* Check if the MR cache is populated (verify LAPDm header) */
+	cached = (lchan->sacch.mr_cache[2] != 0x00
+		&& lchan->sacch.mr_cache[3] != 0x00
+		&& lchan->sacch.mr_cache[4] != 0x00);
+	if (cached) { /* Use the cached one */
+		mr_src_ptr = lchan->sacch.mr_cache;
+		lchan->sacch.mr_cache_usage++;
+	} else { /* Use "dummy" one */
+		mr_src_ptr = (uint8_t *) meas_rep_dummy;
+	}
+
+	/* Compose a new Measurement Report primitive */
+	memcpy(prim->payload, mr_src_ptr, GSM_MACBLOCK_LEN);
+
+#if 0 /* Conflicts with the distance spoofing feature */
+	/* Update L1 SACCH pseudo-header */
+	prim->payload[0] = trx->tx_power;
+	prim->payload[1] = trx->ta;
+#endif
+
+	/* Inform about the cache usage count */
+	if (cached && lchan->sacch.mr_cache_usage > 5) {
+		LOGP(DSCHD, LOGL_NOTICE, "SACCH MR cache usage count=%u > 5 "
+			"on lchan=%s => ancient measurements, please fix!\n",
+			lchan->sacch.mr_cache_usage,
+			trx_lchan_desc[lchan->type].name);
+	}
+
+	LOGP(DSCHD, LOGL_NOTICE, "Transmitting a %s Measurement Report "
+		"on lchan=%s\n", (cached ? "cached" : "dummy"),
+		trx_lchan_desc[lchan->type].name);
+
+	return prim;
+}
+
+/**
+ * Dequeues a SACCH primitive from transmit queue, if present.
+ * Otherwise dequeues a cached Measurement Report (the last
+ * received one). Finally, if the cache is empty, a "dummy"
+ * measurement report is used.
+ *
+ * According to 3GPP TS 04.08, section 3.4.1, SACCH channel
+ * accompanies either a traffic or a signaling channel. It
+ * has the particularity that continuous transmission must
+ * occur in both directions, so on the Uplink direction
+ * measurement result messages are sent at each possible
+ * occasion when nothing else has to be sent. The LAPDm
+ * fill frames (0x01, 0x03, 0x01, 0x2b, ...) are not
+ * applicable on SACCH channels!
+ *
+ * Unfortunately, 3GPP TS 04.08 doesn't clearly state
+ * which "else messages" besides Measurement Reports
+ * can be send by the MS on SACCH channels. However,
+ * in sub-clause 3.4.1 it's stated that the interval
+ * between two successive measurement result messages
+ * shall not exceed one L2 frame.
+ *
+ * @param  queue transmit queue to take a prim from
+ * @param  lchan lchan to assign a primitive
+ * @return       SACCH primitive to be transmitted
+ */
+static struct trx_ts_prim *prim_dequeue_sacch(struct llist_head *queue,
+	struct trx_lchan_state *lchan)
+{
+	struct trx_ts_prim *prim_nmr = NULL;
+	struct trx_ts_prim *prim_mr = NULL;
+	struct trx_ts_prim *prim;
+	bool mr_now;
+
+	/* Shall we transmit MR now? */
+	mr_now = !lchan->sacch.mr_tx_last;
+
+#define PRIM_IS_MR(prim) \
+	(prim->payload[5] == GSM48_PDISC_RR \
+		&& prim->payload[6] == GSM48_MT_RR_MEAS_REP)
+
+	/* Iterate over all primitives in the queue */
+	llist_for_each_entry(prim, queue, list) {
+		/* We are looking for particular channel */
+		if (prim->chan != lchan->type)
+			continue;
+
+		/* Just to be sure... */
+		if (prim->payload_len != GSM_MACBLOCK_LEN)
+			continue;
+
+		/* Look for a Measurement Report */
+		if (!prim_mr && PRIM_IS_MR(prim))
+			prim_mr = prim;
+
+		/* Look for anything else */
+		if (!prim_nmr && !PRIM_IS_MR(prim))
+			prim_nmr = prim;
+
+		/* Should we look further? */
+		if (mr_now && prim_mr)
+			break; /* MR was found */
+		else if (!mr_now && prim_nmr)
+			break; /* something else was found */
+	}
+
+	LOGP(DSCHD, LOGL_DEBUG, "SACCH MR selection on lchan=%s: "
+		"mr_tx_last=%d prim_mr=%p prim_nmr=%p\n",
+		trx_lchan_desc[lchan->type].name,
+		lchan->sacch.mr_tx_last,
+		prim_mr, prim_nmr);
+
+	/* Prioritize non-MR prim if possible */
+	if (mr_now && prim_mr)
+		prim = prim_mr;
+	else if (!mr_now && prim_nmr)
+		prim = prim_nmr;
+	else if (!mr_now && prim_mr)
+		prim = prim_mr;
+	else /* Nothing was found */
+		prim = NULL;
+
+	/* Have we found what we were looking for? */
+	if (prim) /* Dequeue if so */
+		llist_del(&prim->list);
+	else /* Otherwise compose a new MR */
+		prim = prim_compose_mr(lchan);
+
+	/* Update the cached report */
+	if (prim == prim_mr) {
+		memcpy(lchan->sacch.mr_cache,
+			prim->payload, GSM_MACBLOCK_LEN);
+		lchan->sacch.mr_cache_usage = 0;
+
+		LOGP(DSCHD, LOGL_DEBUG, "SACCH MR cache has been updated "
+			"for lchan=%s\n", trx_lchan_desc[lchan->type].name);
+	}
+
+	/* Update the MR transmission state */
+	lchan->sacch.mr_tx_last = PRIM_IS_MR(prim);
+
+	return prim;
+}
+
 /* Dequeues a primitive of a given channel type */
 static struct trx_ts_prim *prim_dequeue_one(struct llist_head *queue,
 	enum trx_lchan_type lchan_type)
@@ -289,6 +463,10 @@
 struct trx_ts_prim *sched_prim_dequeue(struct llist_head *queue,
 	uint32_t fn, struct trx_lchan_state *lchan)
 {
+	/* SACCH is unorthodox, see 3GPP TS 04.08, section 3.4.1 */
+	if (CHAN_IS_SACCH(lchan->type))
+		return prim_dequeue_sacch(queue, lchan);
+
 	/* There is nothing to dequeue */
 	if (llist_empty(queue))
 		return NULL;
@@ -350,6 +528,8 @@
 
 	/* Make sure that there is no existing primitive */
 	OSMO_ASSERT(lchan->prim == NULL);
+	/* Not applicable for SACCH! */
+	OSMO_ASSERT(!CHAN_IS_SACCH(lchan->type));
 
 	/**
 	 * Determine what actually should be generated:
@@ -364,18 +544,8 @@
 		/* FIXME: should we do anything for CSD? */
 		return 0;
 	} else {
-		uint8_t *cur = prim_buffer;
-
-		if (CHAN_IS_SACCH(chan)) {
-			/* Add 2-byte SACCH header */
-			/* FIXME: How to get TA and MS Tx Power from l1l->trx->tx_power + l1l->trx->ta? */
-			cur[0] = cur[1] = 0x00;
-			cur += 2;
-		}
-
-		/* Copy a fill frame payload */
-		memcpy(cur, lapdm_fill_frame, sizeof(lapdm_fill_frame));
-		cur += sizeof(lapdm_fill_frame);
+		/* Copy LAPDm fill frame's header */
+		memcpy(prim_buffer, lapdm_fill_frame, sizeof(lapdm_fill_frame));
 
 		/**
 		 * TS 144.006, section 5.2 "Frame delimitation and fill bits"
@@ -383,7 +553,7 @@
 		 * be set to the binary value "00101011", each fill bit should
 		 * be set to a random value when sent by the network.
 		 */
-		for (i = cur - prim_buffer; i < GSM_MACBLOCK_LEN; i++)
+		for (i = sizeof(lapdm_fill_frame); i < GSM_MACBLOCK_LEN; i++)
 			prim_buffer[i] = (uint8_t) rand();
 
 		/* Define a prim length */
diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c
index fc29998..0b83af3 100644
--- a/src/host/trxcon/sched_trx.c
+++ b/src/host/trxcon/sched_trx.c
@@ -460,7 +460,7 @@
 	/* Forget the current prim */
 	sched_prim_drop(lchan);
 
-	/* TCH specific variables */
+	/* Channel specific stuff */
 	if (CHAN_IS_TCH(lchan->type)) {
 		lchan->dl_ongoing_facch = 0;
 		lchan->ul_facch_blocks = 0;
@@ -469,6 +469,9 @@
 
 		/* Reset AMR state */
 		memset(&lchan->amr, 0x00, sizeof(lchan->amr));
+	} else if (CHAN_IS_SACCH(lchan->type)) {
+		/* Reset SACCH state */
+		memset(&lchan->sacch, 0x00, sizeof(lchan->sacch));
 	}
 
 	/* Reset ciphering state */
diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h
index 818c95a..0feaeec 100644
--- a/src/host/trxcon/sched_trx.h
+++ b/src/host/trxcon/sched_trx.h
@@ -186,6 +186,16 @@
 		int32_t toa256_sum;
 	} meas;
 
+	/*! \brief SACCH state */
+	struct {
+		/*! \brief Cached measurement report (last received) */
+		uint8_t mr_cache[GSM_MACBLOCK_LEN];
+		/*! \brief Cache usage counter */
+		uint8_t mr_cache_usage;
+		/*! \brief What MR transmitted last time? */
+		uint8_t mr_tx_last; /*!< 0x01 - yes, 0x00 - no */
+	} sacch;
+
 	/* AMR specific */
 	struct {
 		/*! \brief 4 possible codecs for AMR */

-- 
To view, visit https://gerrit.osmocom.org/11138
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: If1b8dc74ced746d6270676fdde75fcda32f91a3d
Gerrit-Change-Number: 11138
Gerrit-PatchSet: 1
Gerrit-Owner: Vadim Yanitskiy <axilirator at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180928/98baa23d/attachment.htm>


More information about the gerrit-log mailing list