[PATCH] osmo-bts[master]: LC15: Fix missing fill frame and GSM 05.08 mandatory frame

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/.

Stefan Sperling gerrit-no-reply at lists.osmocom.org
Mon Apr 9 10:27:25 UTC 2018


Hello Vadim Yanitskiy, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/5753

to look at the new patch set (#6).

LC15: Fix missing fill frame and GSM 05.08 mandatory frame

It was discovered that the LC15 BTS does not send L2 fill frame
in case there is nothing to transmit. This leads to bad RXQUAL
reported by MS during signaling in TCH channel.

BTS needs to send L2 fill frame in case there is nothing to
transmit as indicated in GSM TS 05.08, section 8.3.

Related: OS#1950
Change-Id: I40e9bf9438c0b400e4d29eb39ffae37207e34db6
---
M src/common/msg_utils.c
M src/osmo-bts-litecell15/l1_if.c
2 files changed, 127 insertions(+), 15 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/53/5753/6

diff --git a/src/common/msg_utils.c b/src/common/msg_utils.c
index f936c98..bab533b 100644
--- a/src/common/msg_utils.c
+++ b/src/common/msg_utils.c
@@ -379,15 +379,18 @@
 	static const uint8_t f[] = { 52, 53, 54, 55, 56, 57, 58, 59 },
 				h0[] = { 0, 2, 4, 6, 52, 54, 56, 58 },
 				h1[] = { 14, 16, 18, 20, 66, 68, 70, 72 };
-	if (lchan->tch_mode == GSM48_CMODE_SPEECH_V1) {
+
+	switch (lchan->tch_mode) {
+	case GSM48_CMODE_SPEECH_V1:
+	case GSM48_CMODE_SPEECH_AMR:
 		if (lchan->type == GSM_LCHAN_TCH_F)
 			return fn_chk(f, fn, ARRAY_SIZE(f));
-		else
-			return fn_chk(lchan->nr ? h1 : h0, fn,
-				      lchan->nr ? ARRAY_SIZE(h1) :
-				      ARRAY_SIZE(h0));
+
+		return fn_chk(lchan->nr ? h1 : h0, fn,
+			lchan->nr ? ARRAY_SIZE(h1) : ARRAY_SIZE(h0));
+	default:
+		return false;
 	}
-	return false;
 }
 
 /*! \brief Check if DTX DL AMR is enabled for a given lchan (it have proper type,
@@ -465,16 +468,71 @@
  */
 uint8_t repeat_last_sid(struct gsm_lchan *lchan, uint8_t *dst, uint32_t fn)
 {
-	/* FIXME: add EFR support */
-	if (lchan->tch_mode == GSM48_CMODE_SPEECH_EFR)
+	uint8_t payload_len;
+
+	static const uint8_t amr_sid_first_zero[] = {
+		0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+
+	switch (lchan->tch_mode) {
+	case GSM48_CMODE_SPEECH_EFR:
+		/* FIXME: add EFR support */
 		return 0;
 
-	if (lchan->tch_mode != GSM48_CMODE_SPEECH_AMR) {
-		if (dtx_sched_optional(lchan, fn))
-			return 0;
-	} else
+	case GSM48_CMODE_SPEECH_AMR:
 		if (dtx_amr_sid_optional(lchan, fn))
 			return 0;
+
+		if (lchan->rsl_cmode != RSL_CMOD_SPD_SPEECH)
+			break;
+
+		if (!!lchan->tch.dtx.len)
+			break;
+
+		/* Send zero SID FIRST frame */
+		payload_len = sizeof(amr_sid_first_zero);
+		memcpy(dst, amr_sid_first_zero, payload_len);
+
+		/* Debug print */
+		LOGP(DL1C, LOGL_DEBUG, "%s %s %s: Sending zero speech frame "
+			"for tch_mode=%s\n", gsm_fn_as_gsmtime_str(fn),
+			gsm_ts_name(lchan->ts), get_value_string(gsm_chan_t_names, lchan->type),
+			get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
+
+		return payload_len + 1;
+
+	default:
+		if (dtx_sched_optional(lchan, fn))
+			return 0;
+
+		if (!lchan->ts->trx->bts->dtxd)
+			break;
+
+		/* Determine the payload length */
+		switch (lchan->type) {
+		case GSM_LCHAN_TCH_F:
+			payload_len = GSM_FR_BYTES;
+			break;
+		case GSM_LCHAN_TCH_H:
+			payload_len = GSM_HR_BYTES;
+			break;
+		default:
+			return 0;
+		}
+
+		/**
+		 * Need to send zeroed TCH frame on mandatory fn,
+		 * defined in GSM TS 05.08, section 8.3
+		 */
+		memset(dst, 0x00, payload_len);
+
+		LOGP(DL1C, LOGL_DEBUG, "%s %s %s: Sending zero speech frame "
+			"for tch_mode=%s\n", gsm_fn_as_gsmtime_str(fn),
+			gsm_ts_name(lchan->ts), get_value_string(gsm_chan_t_names, lchan->type),
+			get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
+
+		return payload_len + 1;
+	}
 
 	if (lchan->tch.dtx.len) {
 		if (dtx_dl_amr_enabled(lchan)) {
@@ -502,6 +560,12 @@
 		}
 		memcpy(dst, lchan->tch.dtx.cache, lchan->tch.dtx.len);
 		lchan->tch.dtx.fn = fn;
+
+		LOGP(DL1C, LOGL_DEBUG, "%s %s %s: Sending SID buffer "
+			"for tch_mode=%s\n", gsm_fn_as_gsmtime_str(fn),
+			gsm_ts_name(lchan->ts), get_value_string(gsm_chan_t_names, lchan->type),
+			get_value_string(gsm48_chan_mode_names, lchan->tch_mode));
+
 		return lchan->tch.dtx.len + 1;
 	}
 
diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c
index 9e122cd..cb6cf7e 100644
--- a/src/osmo-bts-litecell15/l1_if.c
+++ b/src/osmo-bts-litecell15/l1_if.c
@@ -331,6 +331,44 @@
 	return empty_req;
 }
 
+/* fill frame PH-DATA.req from l1sap primitive */
+static GsmL1_PhDataReq_t *
+fill_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1,
+	uint8_t tn, uint32_t fn, uint8_t sapi, uint8_t sub_ch, uint8_t block_nr)
+{
+	GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq;
+	GsmL1_MsgUnitParam_t *msu_param;
+	uint8_t *l1_payload;
+
+	msu_param = &data_req->msgUnitParam;
+	l1_payload = &msu_param->u8Buffer[0];
+	l1p->id = GsmL1_PrimId_PhDataReq;
+
+	memset(l1_payload, 0x2b, GSM_MACBLOCK_LEN);
+
+	/* address field */
+	l1_payload[0] = 0x03;
+	/* control field */
+	l1_payload[1] = 0x03;
+	/* length field */
+	l1_payload[2] = 0x01;
+
+	/* copy fields from PH-RTS.ind */
+	data_req->hLayer1	= (HANDLE)fl1->hLayer1;
+	data_req->u8Tn 		= tn;
+	data_req->u32Fn		= fn;
+	data_req->sapi		= sapi;
+	data_req->subCh		= sub_ch;
+	data_req->u8BlockNbr	= block_nr;
+	data_req->msgUnitParam.u8Size = GSM_MACBLOCK_LEN;
+
+	LOGP(DL1C, LOGL_DEBUG, "%s tn=%u: Sending fill frame on in none DTX mode "
+		"SAPI=%d, SubCh=%d, BlockNr=%d\n", gsm_fn_as_gsmtime_str(fn),
+		tn, sapi, sub_ch, block_nr);
+
+	return data_req;
+}
+
 static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
 		       struct osmo_phsap_prim *l1sap, bool use_cache)
 {
@@ -460,10 +498,20 @@
 		     osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer,
 					  l1p->u.phDataReq.msgUnitParam.u8Size));
 	} else {
-		/* empty frame */
-		GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
 
-		empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
+		GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
+		if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN) {
+			/* fill frame */
+			fill_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
+		} else {
+			if (lchan->ts->trx->bts->dtxd) {
+				/* empty frame */
+				empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
+			} else {
+				/* fill frame */
+				fill_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr);
+			}
+		}
 	}
 
 	/* send message to DSP's queue */

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

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I40e9bf9438c0b400e4d29eb39ffae37207e34db6
Gerrit-PatchSet: 6
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Owner: Minh-Quang Nguyen <minh-quang.nguyen at nutaq.com>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Minh-Quang Nguyen <minh-quang.nguyen at nutaq.com>
Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Reviewer: Stefan Sperling <ssperling at sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilirator at gmail.com>



More information about the gerrit-log mailing list