falconia has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-bts/+/32099 )
Change subject: speech TCH, all models: implement option of Themyscira BFI packets
......................................................................
speech TCH, all models: implement option of Themyscira BFI packets
Themyscira Wireless System Software is an external add-on to Osmocom
CNI that provides interconnection between an Osmocom GSM network
and regular national public telephone networks, developed initially
for USA PSTN. Voice plane interconnection to PSTN is achieved
by way of G.711 RTP streams, and these public-interfacing RTP streams
are required to be fully continuous, emitting 160 PCM samples every
20 ms no matter what is happening on the GSM side. The transcoding
boundary MGW component of ThemWi is responsible for comfort noise
generation during GSM DTXu pauses and error concealment any time
GSM UL traffic frames are lost for any other reason - but it
requires a bit of assistance from the IP BTS that is the ultimate
origin of the outgoing RTP stream: when FR or EFR codec is used,
ThemWi transcoding MGW expects the IP BTS to emit special
Themyscira-invented BFI packets any time a BFI condition occurs.
These Themyscira BFI packets also carry a TAF bit exactly like
the one in GSM 08.60 TRAU UL frames.
The present change extends the rtp always-output vty option added
just previously: the new option becomes rtp always-output [themyscira-bfi],
and if the last qualifier is included, the special Themyscira
extension mode is enabled. In this mode, which only affects FR and
EFR codecs, RTP packets emitted when there is no speech or SID
frame to be sent change from zero-length RTP payload to Themyscira
BFI marker format, including TAF.
Related: OS#5975
Change-Id: Ib935efb1f7c9c8d919a4a0ea2bef244a47e5fb24
---
M include/osmo-bts/bts.h
M src/common/l1sap.c
M src/common/vty.c
M src/osmo-bts-trx/l1_if.c
M src/osmo-bts-trx/sched_lchan_tchf.c
5 files changed, 95 insertions(+), 15 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/99/32099/1
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 14c78a3..56bf289 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -315,6 +315,7 @@
int rtp_priority;
bool rtp_nogaps_mode; /* emit RTP stream without any gaps */
+ bool rtp_themyscira_ext; /* Themyscira extension for FR/EFR BFI */
struct {
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index f8320b0..3e4d2a0 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -1252,6 +1252,9 @@
* on our own TDMA timing. */
if (!resp_msg->len)
return false;
+ /* Likewise weed out Themyscira BFI marker packets. */
+ if (resp_msg->len == 2 && resp_msg->data[0] == 0xBF)
+ return false;
/* Avoid sending bw-efficient AMR to lower layers, most bts models
* don't support it. */
if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR &&
@@ -1610,13 +1613,27 @@
* if the lower layers sent us a non-empty payload OR if
* rtp always-output mode is configured. */
if (msg->len || bts->rtp_nogaps_mode) {
+ uint8_t *rtp_pl = msg->data;
+ uint16_t rtp_pl_len = msg->len;
+ uint8_t bfi[2];
+
+ /* Generate and substitute Themyscira BFI packet if necessary */
+ if (!msg->len && bts->rtp_themyscira_ext &&
+ (lchan->type == GSM_LCHAN_TCH_F) &&
+ (lchan->tch_mode == GSM48_CMODE_SPEECH_V1 ||
+ lchan->tch_mode == GSM48_CMODE_SPEECH_EFR)) {
+ bfi[0] = 0xBF;
+ bfi[1] = (fn % 104 == 52); /* TAF */
+ rtp_pl = bfi;
+ rtp_pl_len = 2;
+ }
/* hand msg to RTP code for transmission */
if (lchan->abis_ip.osmux.use) {
- lchan_osmux_send_frame(lchan, msg->data, msg->len,
+ lchan_osmux_send_frame(lchan, rtp_pl, rtp_pl_len,
fn_ms_adj(fn, lchan), lchan->rtp_tx_marker);
} else if (lchan->abis_ip.rtp_socket) {
osmo_rtp_send_frame_ext(lchan->abis_ip.rtp_socket,
- msg->data, msg->len, fn_ms_adj(fn, lchan), lchan->rtp_tx_marker);
+ rtp_pl, rtp_pl_len, fn_ms_adj(fn, lchan), lchan->rtp_tx_marker);
}
/* if loopback is enabled, also queue received RTP data */
if (lchan->loopback) {
diff --git a/src/common/vty.c b/src/common/vty.c
index aa49f6b..a8155bf 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -421,8 +421,12 @@
vty_out(vty, " rtp ip-dscp %i%s", bts->rtp_ip_dscp, VTY_NEWLINE);
if (bts->rtp_priority != -1)
vty_out(vty, " rtp socket-priority %i%s", bts->rtp_priority,
VTY_NEWLINE);
- if (bts->rtp_nogaps_mode)
- vty_out(vty, " rtp always-output%s", VTY_NEWLINE);
+ if (bts->rtp_nogaps_mode) {
+ vty_out(vty, " rtp always-output");
+ if (bts->rtp_themyscira_ext)
+ vty_out(vty, " themyscira-bfi");
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
vty_out(vty, " paging queue-size %u%s",
paging_get_queue_max(bts->paging_state),
VTY_NEWLINE);
vty_out(vty, " paging lifetime %u%s",
paging_get_lifetime(bts->paging_state),
@@ -784,12 +788,17 @@
DEFUN(cfg_bts_rtp_always_output,
cfg_bts_rtp_always_output_cmd,
- "rtp always-output",
- RTP_STR "Always emit an RTP packet every 20 ms\n")
+ "rtp always-output [themyscira-bfi]",
+ RTP_STR "Always emit an RTP packet every 20 ms\n"
+ "Emit Themyscira BFI packets for FR and EFR\n")
{
struct gsm_bts *bts = vty->index;
bts->rtp_nogaps_mode = true;
+ if (argc > 0)
+ bts->rtp_themyscira_ext = true;
+ else
+ bts->rtp_themyscira_ext = false;
return CMD_SUCCESS;
}
@@ -801,6 +810,7 @@
struct gsm_bts *bts = vty->index;
bts->rtp_nogaps_mode = false;
+ bts->rtp_themyscira_ext = false;
return CMD_SUCCESS;
}
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index 2ed1868..93161b2 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -439,8 +439,14 @@
break;
}
- /* attempt to allocate an Error Concealment Unit instance, if available */
- lchan->ecu_state = osmo_ecu_init(trx, lchan2ecu_codec(lchan));
+ /* Attempt to allocate an Error Concealment Unit
+ * instance, if available - but not in Themyscira
+ * environment, where in-BTS ECU is undesirable.
+ */
+ if (!trx->bts->rtp_themyscira_ext)
+ lchan->ecu_state = osmo_ecu_init(trx, lchan2ecu_codec(lchan));
+ else
+ lchan->ecu_state = NULL;
/* activate dedicated channel */
trx_sched_set_lchan(lchan, chan_nr, LID_DEDIC, true);
@@ -473,7 +479,10 @@
/* ECU for possibly new codec */
if (lchan->ecu_state)
osmo_ecu_destroy(lchan->ecu_state);
- lchan->ecu_state = osmo_ecu_init(trx, lchan2ecu_codec(lchan));
+ if (!trx->bts->rtp_themyscira_ext)
+ lchan->ecu_state = osmo_ecu_init(trx, lchan2ecu_codec(lchan));
+ else
+ lchan->ecu_state = NULL;
/* change mode */
trx_sched_set_mode(lchan->ts, chan_nr,
lchan->rsl_cmode, lchan->tch_mode,
diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c
index a7e45aa..7211496 100644
--- a/src/osmo-bts-trx/sched_lchan_tchf.c
+++ b/src/osmo-bts-trx/sched_lchan_tchf.c
@@ -301,14 +301,22 @@
switch (tch_mode) {
case GSM48_CMODE_SPEECH_V1: /* FR */
- memset(tch_data, 0, GSM_FR_BYTES);
- tch_data[0] = 0xd0;
- rc = GSM_FR_BYTES;
+ if (bts->rtp_themyscira_ext)
+ rc = 0;
+ else {
+ memset(tch_data, 0, GSM_FR_BYTES);
+ tch_data[0] = 0xd0;
+ rc = GSM_FR_BYTES;
+ }
break;
case GSM48_CMODE_SPEECH_EFR: /* EFR */
- memset(tch_data, 0, GSM_EFR_BYTES);
- tch_data[0] = 0xc0;
- rc = GSM_EFR_BYTES;
+ if (bts->rtp_themyscira_ext)
+ rc = 0;
+ else {
+ memset(tch_data, 0, GSM_EFR_BYTES);
+ tch_data[0] = 0xc0;
+ rc = GSM_EFR_BYTES;
+ }
break;
case GSM48_CMODE_SPEECH_AMR: /* AMR */
rc = osmo_amr_rtp_enc(tch_data,
--
To view, visit
https://gerrit.osmocom.org/c/osmo-bts/+/32099
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Ib935efb1f7c9c8d919a4a0ea2bef244a47e5fb24
Gerrit-Change-Number: 32099
Gerrit-PatchSet: 1
Gerrit-Owner: falconia <falcon(a)freecalypso.org>
Gerrit-MessageType: newchange