[PATCH] osmocom-bb[fixeria/trx]: trxcon/scheduler: transmit dummy frames on CBTX lchans

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
Sun Mar 11 08:00:20 UTC 2018


trxcon/scheduler: transmit dummy frames on CBTX lchans

If at the moment of transmission there are no frames in TX buffer,
then either a dummy LAPDm frame (0x01, 0x03, 0x01, 0x2b ...) or a
silence frame (depending on a codec in use) shall be transmitted.
This is required for proper measurements on the BTS side.

Change-Id: Ie590990f2274ea476678f6b2079f90eeadab6501
---
M src/host/trxcon/sched_prim.c
M src/host/trxcon/sched_trx.c
M src/host/trxcon/sched_trx.h
M src/host/trxcon/trxcon.c
4 files changed, 118 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/06/7206/2

diff --git a/src/host/trxcon/sched_prim.c b/src/host/trxcon/sched_prim.c
index fb5f0a0..f046666 100644
--- a/src/host/trxcon/sched_prim.c
+++ b/src/host/trxcon/sched_prim.c
@@ -23,6 +23,7 @@
  */
 
 #include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 #include <talloc.h>
 
@@ -31,6 +32,7 @@
 #include <osmocom/core/linuxlist.h>
 
 #include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
 
 #include "scheduler.h"
 #include "sched_trx.h"
@@ -227,6 +229,93 @@
 }
 
 /**
+ * Assigns a dummy primitive to a lchan depending on its type.
+ * Could be used when there is nothing to transmit, but
+ * CBTX (Continuous Burst Transmission) is assumed.
+ *
+ * @param  lchan lchan to assing a primitive
+ * @return       zero in case of success, otherwise a error code
+ */
+int sched_prim_dummy(struct trx_lchan_state *lchan)
+{
+	enum trx_lchan_type chan = lchan->type;
+	uint8_t tch_mode = lchan->tch_mode;
+	struct trx_ts_prim *prim;
+	uint8_t prim_buffer[40];
+	size_t prim_len = 0;
+	int i;
+
+	/**
+	 * TS 144.006, section 8.4.2.3 "Fill frames"
+	 * A fill frame is a UI command frame for SAPI 0, P=0
+	 * and with an information field of 0 octet length.
+	 */
+	static const uint8_t lapdm_fill_frame[] = {
+		0x01, 0x03, 0x01,
+		/* Pending part is to be randomized */
+	};
+
+	/* Make sure that there is no existing primitive */
+	OSMO_ASSERT(lchan->prim == NULL);
+
+	/**
+	 * Determine what actually should be generated:
+	 * TCH in GSM48_CMODE_SIGN: LAPDm fill frame;
+	 * TCH in other modes: silence frame;
+	 * other channels: LAPDm fill frame.
+	 */
+	if (CHAN_IS_TCH(chan) && TCH_MODE_IS_SPEECH(tch_mode)) {
+		/**
+		 * Silence frame indication
+		 * HACK: use actual rsl_cmode!
+		 */
+		prim_len = sched_bad_frame_ind(prim_buffer,
+			RSL_CMOD_SPD_SPEECH, tch_mode);
+	} else if (CHAN_IS_TCH(chan) && TCH_MODE_IS_DATA(tch_mode)) {
+		/* FIXME: should we do anything for CSD? */
+		return 0;
+	} else {
+		/**
+		 * TS 144.006, section 8.1.2.3 "Fill frames"
+		 * A fill frame is a UI command frame for SAPI 0, P=0
+		 * and with an information field of 0 octet length.
+		 */
+		memcpy(prim_buffer, lapdm_fill_frame, 3);
+
+		/* Randomize pending unused bytes */
+		for (i = 3; i < GSM_MACBLOCK_LEN; i++)
+			prim_buffer[i] = (uint8_t) rand();
+
+		/* Define a prim length */
+		prim_len = GSM_MACBLOCK_LEN;
+	}
+
+	/* Nothing to allocate / assign */
+	if (!prim_len)
+		return 0;
+
+	/* Allocate a new primitive */
+	prim = talloc_zero_size(lchan, sizeof(struct trx_ts_prim) + prim_len);
+	if (prim == NULL)
+		return -ENOMEM;
+
+	/* Init primitive header */
+	prim->payload_len = prim_len;
+	prim->chan = lchan->type;
+
+	/* Fill in the payload */
+	memcpy(prim->payload, prim_buffer, prim_len);
+
+	/* Assign the current prim */
+	lchan->prim = prim;
+
+	LOGP(DSCH, LOGL_DEBUG, "Transmitting a dummy / silence frame "
+		"on lchan=%s\n", trx_lchan_desc[chan].name);
+
+	return 0;
+}
+
+/**
  * Flushes a queue of primitives
  *
  * @param list list of prims going to be flushed
diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c
index 8c859de..168c4ef 100644
--- a/src/host/trxcon/sched_trx.c
+++ b/src/host/trxcon/sched_trx.c
@@ -97,6 +97,19 @@
 		if (lchan->prim == NULL)
 			lchan->prim = sched_prim_dequeue(&ts->tx_prims, chan);
 
+		/* TODO: report TX buffers health to the higher layers */
+
+		/* If CBTX (Continuous Burst Transmission) is assumed */
+		if (trx_lchan_desc[chan].flags & TRX_CH_FLAG_CBTX) {
+			/**
+			 * Probably, a TX buffer is empty. Nevertheless,
+			 * we shall continuously transmit anything on
+			 * CBTX channels.
+			 */
+			if (lchan->prim == NULL)
+				sched_prim_dummy(lchan);
+		}
+
 		/* If there is no primitive, do nothing */
 		if (lchan->prim == NULL)
 			continue;
diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h
index 6a02543..d9e0c8e 100644
--- a/src/host/trxcon/sched_trx.h
+++ b/src/host/trxcon/sched_trx.h
@@ -275,6 +275,17 @@
 int sched_prim_push(struct trx_instance *trx,
 	struct trx_ts_prim *prim, uint8_t chan_nr);
 
+#define TCH_MODE_IS_SPEECH(mode)       \
+	  (mode == GSM48_CMODE_SPEECH_V1   \
+	|| mode == GSM48_CMODE_SPEECH_EFR  \
+	|| mode == GSM48_CMODE_SPEECH_AMR)
+
+#define TCH_MODE_IS_DATA(mode)        \
+	  (mode == GSM48_CMODE_DATA_14k5  \
+	|| mode == GSM48_CMODE_DATA_12k0  \
+	|| mode == GSM48_CMODE_DATA_6k0   \
+	|| mode == GSM48_CMODE_DATA_3k6)
+
 #define CHAN_IS_TCH(chan) \
 	(chan == TRXC_TCHF || chan == TRXC_TCHH_0 || chan == TRXC_TCHH_1)
 
@@ -286,6 +297,7 @@
 
 struct trx_ts_prim *sched_prim_dequeue(struct llist_head *queue,
 	enum trx_lchan_type lchan_type);
+int sched_prim_dummy(struct trx_lchan_state *lchan);
 void sched_prim_drop(struct trx_lchan_state *lchan);
 void sched_prim_flush_queue(struct llist_head *list);
 
diff --git a/src/host/trxcon/trxcon.c b/src/host/trxcon/trxcon.c
index 5542240..43c98a5 100644
--- a/src/host/trxcon/trxcon.c
+++ b/src/host/trxcon/trxcon.c
@@ -28,6 +28,7 @@
 #include <getopt.h>
 #include <unistd.h>
 #include <signal.h>
+#include <time.h>
 
 #include <arpa/inet.h>
 
@@ -293,6 +294,9 @@
 		}
 	}
 
+	/* Initialize pseudo-random generator */
+	srand(time(NULL));
+
 	while (!app_data.quit)
 		osmo_select_main(0);
 

-- 
To view, visit https://gerrit.osmocom.org/7206
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Ie590990f2274ea476678f6b2079f90eeadab6501
Gerrit-PatchSet: 2
Gerrit-Project: osmocom-bb
Gerrit-Branch: fixeria/trx
Gerrit-Owner: Vadim Yanitskiy <axilirator at gmail.com>



More information about the gerrit-log mailing list