FR & EFR: support TW-TS-001 output via rtp fr-efr-format vty option

Themyscira Wireless Technical Specification TW-TS-001 defines
an alternative RTP payload format for FR and EFR codecs specifically
for use within a GSM RAN, replicating the full functionality and
semantics of T1/E1 Abis.  Add support for emitting this RTP format
instead of standard TS 101 318 by way of a vty config option.

Change-Id: I8536256101ca669ab416d4f2e91b576430c930fc
This commit is contained in:
Mychaela N. Falconia 2023-06-29 01:08:25 +00:00
parent 437989de37
commit 6b58035ce3
4 changed files with 71 additions and 5 deletions

View File

@ -301,6 +301,7 @@ struct gsm_bts {
bool rtp_nogaps_mode; /* emit RTP stream without any gaps */
bool use_ul_ecu; /* "rtp internal-uplink-ecu" option */
bool emit_fr_twts001;
bool emit_hr_rfc5993;
struct {

View File

@ -1813,21 +1813,64 @@ static void send_rtp_rfc5993(struct gsm_lchan *lchan, uint32_t fn,
send_ul_rtp_packet(lchan, fn, msg->data, msg->len);
}
/* a helper function for emitting FR/EFR UL in TW-TS-001 format */
static void send_rtp_twts001(struct gsm_lchan *lchan, uint32_t fn,
struct msgb *msg, bool good_frame)
{
uint8_t teh;
bool send_frame;
if (msg->len == GSM_FR_BYTES || msg->len == GSM_EFR_BYTES) {
if (good_frame)
teh = 0xE0;
else
teh = 0xE2;
send_frame = true;
} else {
teh = 0xE6;
send_frame = false;
}
/* always set DTXd and TAF bits */
if (lchan->ts->trx->bts->dtxd)
teh |= 0x08;
if (fn % 104 == 52)
teh |= 0x01;
if (send_frame) {
msgb_push_u8(msg, teh);
send_ul_rtp_packet(lchan, fn, msg->data, msg->len);
} else {
send_ul_rtp_packet(lchan, fn, &teh, 1);
}
}
/* A helper function for l1sap_tch_ind(): handling BFI
*
* Please note that we pass the msgb to this function, even though it is
* currently not used. This msgb passing is a provision for adding
* support for TRAU-UL-like RTP payload formats like TW-TS-001 that allow
* indicating BFI along with deemed-bad frame data bits, just like
* Please note that the msgb passed to this function is used only when
* the BTS is configured to emit FR & EFR UL in TW-TS-001 format,
* indicating BFI along with deemed-bad frame data bits just like
* GSM 08.60 and 08.61 TRAU-UL frames.
*/
static void tch_ul_bfi_handler(struct gsm_lchan *lchan,
const struct gsm_time *g_time, struct msgb *msg)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
uint32_t fn = g_time->fn;
uint8_t ecu_out[GSM_FR_BYTES];
int rc;
/* Are we on TCH/FS or TCH/EFS, configured to emit TW-TS-001 extended
* RTP format? If so, emit BFI per that spec. The placement of
* this check before the ECU is intentional: the modes of TW-TS-001
* UL output (closely replicating the classic GSM architecture in which
* a BTS never applies an ECU to its UL output) and internal UL ECU
* are mutually exclusive. */
if (bts->emit_fr_twts001 && lchan->type == GSM_LCHAN_TCH_F &&
(lchan->tch_mode == GSM48_CMODE_SPEECH_V1 ||
lchan->tch_mode == GSM48_CMODE_SPEECH_EFR)) {
send_rtp_twts001(lchan, fn, msg, false);
return;
}
/* Are we applying an ECU to this uplink, and are we in a state
* (not DTX pause) where we emit ECU output? */
if (lchan->ecu_state && !osmo_ecu_is_dtx_pause(lchan->ecu_state)) {
@ -1842,7 +1885,7 @@ static void tch_ul_bfi_handler(struct gsm_lchan *lchan,
/* Are we in rtp continuous-streaming special mode? If so, send out
* a BFI packet as zero-length RTP payload. */
if (lchan->ts->trx->bts->rtp_nogaps_mode) {
if (bts->rtp_nogaps_mode) {
send_ul_rtp_packet(lchan, fn, NULL, 0);
return;
}
@ -1903,6 +1946,11 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
if (bts->emit_hr_rfc5993 && lchan->type == GSM_LCHAN_TCH_H &&
lchan->tch_mode == GSM48_CMODE_SPEECH_V1)
send_rtp_rfc5993(lchan, fn, msg);
else if (bts->emit_fr_twts001 &&
lchan->type == GSM_LCHAN_TCH_F &&
(lchan->tch_mode == GSM48_CMODE_SPEECH_V1 ||
lchan->tch_mode == GSM48_CMODE_SPEECH_EFR))
send_rtp_twts001(lchan, fn, msg, true);
else
send_ul_rtp_packet(lchan, fn, msg->data, msg->len);
/* if loopback is enabled, also queue received RTP data */

View File

@ -420,6 +420,8 @@ static void config_write_bts_single(struct vty *vty, const struct gsm_bts *bts)
vty_out(vty, " rtp continuous-streaming%s", VTY_NEWLINE);
vty_out(vty, " %srtp internal-uplink-ecu%s",
bts->use_ul_ecu ? "" : "no ", VTY_NEWLINE);
vty_out(vty, " rtp fr-efr-format %s%s",
bts->emit_fr_twts001 ? "tw-ts-001" : "ts101318", VTY_NEWLINE);
vty_out(vty, " rtp hr-format %s%s",
bts->emit_hr_rfc5993 ? "rfc5993" : "ts101318", VTY_NEWLINE);
vty_out(vty, " paging queue-size %u%s", paging_get_queue_max(bts->paging_state),
@ -823,6 +825,19 @@ DEFUN(cfg_bts_no_rtp_int_ul_ecu,
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_bts_rtp_fr_format,
cfg_bts_rtp_fr_format_cmd,
"rtp fr-efr-format (ts101318|tw-ts-001)",
RTP_STR "FR & EFR output format\n"
"TS 101 318 (standard)\n" "TW-TS-001 (non-standard)\n",
CMD_ATTR_IMMEDIATE)
{
struct gsm_bts *bts = vty->index;
bts->emit_fr_twts001 = !strcmp(argv[0], "tw-ts-001");
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_bts_rtp_hr_format,
cfg_bts_rtp_hr_format_cmd,
"rtp hr-format (rfc5993|ts101318)",
@ -2726,6 +2741,7 @@ int bts_vty_init(void *ctx)
install_element(BTS_NODE, &cfg_bts_no_rtp_cont_stream_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_int_ul_ecu_cmd);
install_element(BTS_NODE, &cfg_bts_no_rtp_int_ul_ecu_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_fr_format_cmd);
install_element(BTS_NODE, &cfg_bts_rtp_hr_format_cmd);
install_element(BTS_NODE, &cfg_bts_band_cmd);
install_element(BTS_NODE, &cfg_description_cmd);

View File

@ -237,6 +237,7 @@ OsmoBTS(bts)# list
no rtp continuous-streaming
rtp internal-uplink-ecu
no rtp internal-uplink-ecu
rtp fr-efr-format (ts101318|tw-ts-001)
rtp hr-format (rfc5993|ts101318)
band (450|GSM450|480|GSM480|750|GSM750|810|GSM810|850|GSM850|900|GSM900|1800|DCS1800|1900|PCS1900)
description .TEXT