[PATCH] osmo-bts[master]: DTX DL: split ONSET state handling

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

Max gerrit-no-reply at lists.osmocom.org
Tue Oct 25 17:34:19 UTC 2016


Hello Harald Welte, Jenkins Builder,

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

    https://gerrit.osmocom.org/1145

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

DTX DL: split ONSET state handling

Handle ONSET cause by Voice and FACCH separately. In case of Voice we
have RTP payload which we have to cache and send later on in next
response to L1 RTS. FACCH have higher priority so it preempts both voice
and silence alike - hence we can send ONSET immediately but still have
to track previous state in order to get back to it gracefully.

This affects lc15 and sysmo hw as there's no FSM-based DTX
implementation for other models yet.

Change-Id: Idba14dcd0cb12cd7aee86391fcc152c49fcd7052
Related: OS#1801
---
M include/osmo-bts/dtx_dl_amr_fsm.h
M src/common/dtx_dl_amr_fsm.c
M src/osmo-bts-litecell15/l1_if.c
M src/osmo-bts-litecell15/tch.c
M src/osmo-bts-sysmo/l1_if.c
M src/osmo-bts-sysmo/tch.c
6 files changed, 84 insertions(+), 31 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/45/1145/4

diff --git a/include/osmo-bts/dtx_dl_amr_fsm.h b/include/osmo-bts/dtx_dl_amr_fsm.h
index 8b19595..5c13c19 100644
--- a/include/osmo-bts/dtx_dl_amr_fsm.h
+++ b/include/osmo-bts/dtx_dl_amr_fsm.h
@@ -16,7 +16,6 @@
 	ST_U_INH,
 	ST_SID_U,
 	ST_ONSET_V,
-	ST_ONSET_F,
 	ST_FACCH_V,
 	ST_FACCH,
 };
diff --git a/src/common/dtx_dl_amr_fsm.c b/src/common/dtx_dl_amr_fsm.c
index b110cf2..a75fd00 100644
--- a/src/common/dtx_dl_amr_fsm.c
+++ b/src/common/dtx_dl_amr_fsm.c
@@ -53,7 +53,7 @@
 		osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
 		break;
 	case E_FACCH:
-		osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
+		osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
 		break;
 	case E_COMPL:
 		osmo_fsm_inst_state_chg(fi, ST_SID_F2, 0, 0);
@@ -81,7 +81,7 @@
 		osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
 		break;
 	case E_FACCH:
-		osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
+		osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
 		break;
 	default:
 		LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
@@ -97,7 +97,7 @@
 		osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
 		break;
 	case E_FACCH:
-		osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
+		osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
 		break;
 	default:
 		LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
@@ -113,7 +113,7 @@
 		osmo_fsm_inst_state_chg(fi, ST_ONSET_V, 0, 0);
 		break;
 	case E_FACCH:
-		osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
+		osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
 		break;
 	default:
 		LOGP(DL1P, LOGL_ERROR, "Unexpected event %d\n", event);
@@ -126,7 +126,7 @@
 {
 	switch (event) {
 	case E_FACCH:
-		osmo_fsm_inst_state_chg(fi, ST_ONSET_F, 0, 0);
+		osmo_fsm_inst_state_chg(fi, ST_FACCH, 0, 0);
 		break;
 	case E_VOICE:
 		osmo_fsm_inst_state_chg(fi, ST_VOICE, 0, 0);
@@ -234,7 +234,7 @@
 	   start of silence period (might be interrupted in case of AMR HR) */
 	[ST_SID_F1]= {
 		.in_event_mask = X(E_SID_F) | X(E_SID_U) | X(E_VOICE) | X(E_FACCH) | X(E_COMPL) | X(E_INHIB) | X(E_ONSET),
-		.out_state_mask = X(ST_SID_U) | X(ST_VOICE) | X(ST_ONSET_F) | X(ST_SID_F2) | X(ST_F1_INH) | X(ST_ONSET_V),
+		.out_state_mask = X(ST_SID_U) | X(ST_VOICE) | X(ST_FACCH) | X(ST_SID_F2) | X(ST_F1_INH) | X(ST_ONSET_V),
 		.name = "SID-FIRST (P1)",
 		.action = dtx_fsm_sid_f1,
 	},
@@ -242,7 +242,7 @@
 	   actual start of silence period in case of AMR HR*/
 	[ST_SID_F2]= {
 		.in_event_mask = X(E_SID_U) | X(E_VOICE) | X(E_FACCH),
-		.out_state_mask = X(ST_SID_U) | X(ST_VOICE) | X(ST_ONSET_F),
+		.out_state_mask = X(ST_SID_U) | X(ST_VOICE) | X(ST_FACCH),
 		.name = "SID-FIRST (P2)",
 		.action = dtx_fsm_sid_f2,
 	},
@@ -265,7 +265,7 @@
 	/* Silence period with periodic comfort noise data updates */
 	[ST_SID_U]= {
 		.in_event_mask = X(E_FACCH) | X(E_VOICE) | X(E_INHIB) | X(E_SID_U) | X(E_SID_F) | X(E_ONSET),
-		.out_state_mask = X(ST_ONSET_F) | X(ST_VOICE) | X(ST_U_INH) | X(ST_SID_U) | X(ST_ONSET_V),
+		.out_state_mask = X(ST_FACCH) | X(ST_VOICE) | X(ST_U_INH) | X(ST_SID_U) | X(ST_ONSET_V),
 		.name = "SID-UPDATE",
 		.action = dtx_fsm_sid_upd,
 	},
@@ -275,13 +275,6 @@
 		.out_state_mask = X(ST_VOICE) | X(ST_FACCH_V),
 		.name = "ONSET (SPEECH)",
 		.action = dtx_fsm_onset_v,
-	},
-	/* ONSET - end of silent period due to incoming FACCH frame */
-	[ST_ONSET_F]= {
-		.in_event_mask = X(E_VOICE) | X(E_FACCH) | X(E_SID_U),
-		.out_state_mask = X(ST_VOICE) | X(ST_FACCH),
-		.name = "ONSET (FACCH)",
-		.action = dtx_fsm_onset_f,
 	},
 	/* FACCH sending state: SPEECH was observed before so once we're done
 	   FSM should get back to VOICE state */
diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c
index f47634e..b98e95a 100644
--- a/src/osmo-bts-litecell15/l1_if.c
+++ b/src/osmo-bts-litecell15/l1_if.c
@@ -53,6 +53,7 @@
 #include <osmo-bts/cbch.h>
 #include <osmo-bts/bts_model.h>
 #include <osmo-bts/l1sap.h>
+#include <osmo-bts/dtx_dl_amr_fsm.h>
 
 #include <nrw/litecell15/litecell15.h>
 #include <nrw/litecell15/gsml1prim.h>
@@ -330,13 +331,15 @@
 }
 
 static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
-		       struct osmo_phsap_prim *l1sap)
+		       struct osmo_phsap_prim *l1sap, bool use_cache)
 {
 	struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx);
 	struct msgb *l1msg = l1p_msgb_alloc();
+	struct gsm_lchan *lchan;
 	uint32_t u32Fn;
 	uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0;
 	uint8_t chan_nr, link_id;
+	bool rec = false;
 	int len;
 
 	if (!msg) {
@@ -401,14 +404,41 @@
 	if (len) {
 		/* data request */
 		GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
+		lchan = get_lchan_by_chan_nr(trx, chan_nr);
+
+		if (use_cache)
+			memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer,
+			       lchan->tch.dtx.facch, msgb_l2len(msg));
+		else if (trx->bts->dtxd && // FIXME: separate FACCH/H?
+			 (sapi == GsmL1_Sapi_FacchF ||
+			  sapi == GsmL1_Sapi_FacchH)) {
+			if (lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) {
+				/* FACCH interruption of DTX silence */
+				/* cache FACCH data */
+				memcpy(lchan->tch.dtx.facch, msg->l2h,
+				       msgb_l2len(msg));
+				/* prepare ONSET message */
+				len = 3;
+				l1p->u.phDataReq.msgUnitParam.u8Buffer[0] =
+					GsmL1_TchPlType_Amr_Onset;
+				/* ignored CMR/CMI pair */
+				l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0;
+				l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0;
+				/* ONSET is ready, recursive call is necessary */
+				rec = true;
+			}
+		}
 
 		data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr, len);
 
-		OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer));
-		memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, msgb_l2len(msg));
+		if (!rec && !use_cache) {
+			OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer));
+			memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h,
+			       msgb_l2len(msg));
+		}
 		LOGP(DL1P, LOGL_DEBUG, "PH-DATA.req(%s)\n",
-			osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer,
-				     l1p->u.phDataReq.msgUnitParam.u8Size));
+		     osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer,
+					  l1p->u.phDataReq.msgUnitParam.u8Size));
 	} else {
 		/* empty frame */
 		GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
@@ -422,6 +452,8 @@
 		msgb_free(l1msg);
 	}
 
+	if (rec)
+		ph_data_req(trx, msg, l1sap, true);
 	return 0;
 }
 
@@ -566,7 +598,7 @@
 	 * free()d below */
 	switch (OSMO_PRIM_HDR(&l1sap->oph)) {
 	case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST):
-		rc = ph_data_req(trx, msg, l1sap);
+		rc = ph_data_req(trx, msg, l1sap, false);
 		break;
 	case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST):
 		rc = ph_tch_req(trx, msg, l1sap, false, l1sap->u.tch.marker);
diff --git a/src/osmo-bts-litecell15/tch.c b/src/osmo-bts-litecell15/tch.c
index b251388..2565e23 100644
--- a/src/osmo-bts-litecell15/tch.c
+++ b/src/osmo-bts-litecell15/tch.c
@@ -285,10 +285,9 @@
 		/* DTX DL-specific logic below: */
 		switch (lchan->tch.dtx.dl_amr_fsm->state) {
 		case ST_ONSET_V:
-		case ST_ONSET_F:
 			*payload_type = GsmL1_TchPlType_Amr_Onset;
 			dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0);
-			*len = 1;
+			*len = 3;
 			return 1;
 		case ST_VOICE:
 			*payload_type = GsmL1_TchPlType_Amr;
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index bef2d30..eefcdaf 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -325,13 +325,15 @@
 }
 
 static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
-		       struct osmo_phsap_prim *l1sap)
+		       struct osmo_phsap_prim *l1sap, bool use_cache)
 {
 	struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx);
 	struct msgb *l1msg = l1p_msgb_alloc();
+	struct gsm_lchan *lchan;
 	uint32_t u32Fn;
 	uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0;
 	uint8_t chan_nr, link_id;
+	bool rec = false;
 	int len;
 
 	if (!msg) {
@@ -396,14 +398,41 @@
 	if (len) {
 		/* data request */
 		GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
+		lchan = get_lchan_by_chan_nr(trx, chan_nr);
+
+		if (use_cache)
+			memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer,
+			       lchan->tch.dtx.facch, msgb_l2len(msg));
+		else if (trx->bts->dtxd && // FIXME: separate FACCH/H?
+			 (sapi == GsmL1_Sapi_FacchF ||
+			  sapi == GsmL1_Sapi_FacchH)) {
+			if (lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) {
+				/* FACCH interruption of DTX silence */
+				/* cache FACCH data */
+				memcpy(lchan->tch.dtx.facch, msg->l2h,
+				       msgb_l2len(msg));
+				/* prepare ONSET message */
+				len = 3;
+				l1p->u.phDataReq.msgUnitParam.u8Buffer[0] =
+					GsmL1_TchPlType_Amr_Onset;
+				/* ignored CMR/CMI pair */
+				l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0;
+				l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0;
+				/* ONSET is ready, recursive call is necessary */
+				rec = true;
+			}
+		}
 
 		data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr, len);
 
-		OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer));
-		memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, msgb_l2len(msg));
+		if (!rec && !use_cache) {
+			OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer));
+			memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h,
+			       msgb_l2len(msg));
+		}
 		LOGP(DL1P, LOGL_DEBUG, "PH-DATA.req(%s)\n",
-			osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer,
-				     l1p->u.phDataReq.msgUnitParam.u8Size));
+		     osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer,
+					  l1p->u.phDataReq.msgUnitParam.u8Size));
 	} else {
 		/* empty frame */
 		GsmL1_Prim_t *l1p = msgb_l1prim(l1msg);
@@ -417,6 +446,8 @@
 		msgb_free(l1msg);
 	}
 
+	if (rec)
+		ph_data_req(trx, msg, l1sap, true);
 	return 0;
 }
 
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c
index b08ba7e..5e517e9 100644
--- a/src/osmo-bts-sysmo/tch.c
+++ b/src/osmo-bts-sysmo/tch.c
@@ -383,10 +383,9 @@
 		/* DTX DL-specific logic below: */
 		switch (lchan->tch.dtx.dl_amr_fsm->state) {
 		case ST_ONSET_V:
-		case ST_ONSET_F:
 			*payload_type = GsmL1_TchPlType_Amr_Onset;
 			dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0);
-			*len = 1;
+			*len = 3;
 			return 1;
 		case ST_VOICE:
 			*payload_type = GsmL1_TchPlType_Amr;

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

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Idba14dcd0cb12cd7aee86391fcc152c49fcd7052
Gerrit-PatchSet: 4
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Owner: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Max <msuraev at sysmocom.de>



More information about the gerrit-log mailing list