l1sap: Accept RFC5993 and TS 101.318 HR GSM payload

Unfotunately there are two different RTP formats for HR GSM specified
and it is unclear which should be used with GSM networks. Also esch BTS
model may have a preference for either one or the other format.

Lets set internal flags to determine the preference for each BTS model
and then lets use this information to convert incoming RTP packets into
the prefered format. Doing so we will make sure that always both formats
are accepted.

Change-Id: I17f0b546042fa333780fd2f5c315898ab0df574c
Related: OS#5688
This commit is contained in:
Philipp Maier 2022-12-08 16:44:06 +01:00
parent c2261bb62e
commit 6020cb3dc1
8 changed files with 70 additions and 3 deletions

View File

@ -65,6 +65,11 @@ const char *btsvariant2str(enum gsm_bts_type_variant v);
#define BTS_INTERNAL_FLAG_NM_RCHANNEL_DEPENDS_RCARRIER (1 << 2)
/* Whether the BTS model reports interference measurements to L1SAP. */
#define BTS_INTERNAL_FLAG_INTERF_MEAS (1 << 3)
/* Whether the BTS model supports HR GSM RTP payload in
* GSM ETSI TS.101.138 (TIPHON) format */
#define BTS_INTERNAL_FLAG_SPEECH_H_V1_TS101318 (1 << 4)
/* Whether the BTS model supports HR GSM RTP payload in RFC 5883 format */
#define BTS_INTERNAL_FLAG_SPEECH_H_V1_RFC5993 (1 << 5)
/* BTS implementation flags (internal use, not exposed via OML) */
#define bts_internal_flag_get(bts, flag) \

View File

@ -164,6 +164,7 @@ struct gsm_lchan {
uint8_t rtp_payload;
uint8_t rtp_payload2;
uint8_t speech_mode;
bool rtp_hr_rfc5993;
struct {
bool use;
uint8_t local_cid;

View File

@ -1253,6 +1253,28 @@ static bool rtppayload_is_valid(struct gsm_lchan *lchan, struct msgb *resp_msg)
osmo_hexdump(resp_msg->data, resp_msg->len));
return false;
}
/* Avoid sending an incompatible HR GSM RTP format to lower layers. Two
* formats exist: ETSI TS 101.318 and RFC 5993. This check is only
* carried out when the BTS model explicitly states a preference. */
if (lchan->tch_mode == GSM48_CMODE_SPEECH_V1 && lchan->type == GSM_LCHAN_TCH_H) {
if (bts_internal_flag_get(lchan->ts->trx->bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_RFC5993)) {
if (resp_msg->len != GSM_HR_BYTES + 1) {
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE,
"RTP->L1: Dropping unexpected HR GSM encoding (expected RFC 5993, got TS 101.318?) %s\n",
osmo_hexdump(resp_msg->data, resp_msg->len));
return false;
}
} else if (bts_internal_flag_get(lchan->ts->trx->bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_TS101318)) {
if (resp_msg->len != GSM_HR_BYTES) {
LOGPLCHAN(lchan, DL1P, LOGL_NOTICE,
"RTP->L1: Dropping unexpected HR GSM encoding (expected TS 101.318, got RFC 5993?) %s\n",
osmo_hexdump(resp_msg->data, resp_msg->len));
return false;
}
}
}
return true;
}
@ -1888,10 +1910,43 @@ void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
if (lchan->loopback)
return;
msg = l1sap_msgb_alloc(rtp_pl_len);
if (!msg)
/* There are two different specifications that describe how HR GSM audio should be encapsulated in RTP frames:
* RFC 5993 and ETSI TS 101.318 (TIPHON). In order to be able to accept both formats we convert them on
* reception depending on what the particular BTS model supports. */
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
if (lchan->type == GSM_LCHAN_TCH_H && rtp_pl_len == GSM_HR_BYTES
&& bts_internal_flag_get(lchan->ts->trx->bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_RFC5993)) {
msg = l1sap_msgb_alloc(rtp_pl_len + 1);
if (!msg)
return;
/* Note: The only difference between both formats is that RFC 5993 specifies an additional one
* byte TOC header in front of the audio payload. (See also: RFC 5993, section 5.2) */
msgb_put_u8(msg, 0x00);
memcpy(msgb_put(msg, rtp_pl_len), rtp_pl, rtp_pl_len);
break;
} else if (lchan->type == GSM_LCHAN_TCH_H && rtp_pl_len == GSM_HR_BYTES + 1
&& bts_internal_flag_get(lchan->ts->trx->bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_TS101318)) {
msg = l1sap_msgb_alloc(rtp_pl_len - 1);
if (!msg)
return;
memcpy(msgb_put(msg, rtp_pl_len - 1), rtp_pl + 1, rtp_pl_len - 1);
break;
}
/* NOTE: Each BTS model must specify which HR GSM RTP format it supports. Since forwarding a random
* payload format might lead to unexpected effects and unreliable operation in the field it is better
* to drop the payload early. */
LOGP(DL1P, LOGL_ERROR,
"BTS model does not specify HR GSM RTP format (RFC5993 or ETSI TS 101.318?), dropping payload!\n");
return;
memcpy(msgb_put(msg, rtp_pl_len), rtp_pl, rtp_pl_len);
default:
msg = l1sap_msgb_alloc(rtp_pl_len);
if (!msg)
return;
memcpy(msgb_put(msg, rtp_pl_len), rtp_pl, rtp_pl_len);
}
msgb_pull(msg, sizeof(struct osmo_phsap_prim));
/* Store RTP header Marker bit in control buffer */

View File

@ -113,6 +113,7 @@ int bts_model_init(struct gsm_bts *bts)
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MS_PWR_CTRL_DSP);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_NM_RCHANNEL_DEPENDS_RCARRIER);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_TS101318);
return 0;
}

View File

@ -114,6 +114,7 @@ int bts_model_init(struct gsm_bts *bts)
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MS_PWR_CTRL_DSP);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_NM_RCHANNEL_DEPENDS_RCARRIER);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_TS101318);
return 0;
}

View File

@ -81,6 +81,7 @@ int bts_model_init(struct gsm_bts *bts)
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MEAS_PAYLOAD_COMB);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MS_PWR_CTRL_DSP);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_NM_RCHANNEL_DEPENDS_RCARRIER);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_TS101318);
return 0;
}

View File

@ -157,6 +157,7 @@ int bts_model_init(struct gsm_bts *bts)
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MEAS_PAYLOAD_COMB);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_INTERF_MEAS);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_RFC5993);
return 0;
}

View File

@ -71,6 +71,8 @@ int bts_model_init(struct gsm_bts *bts)
osmo_bts_set_feature(bts->features, BTS_FEAT_SPEECH_H_AMR);
osmo_bts_set_feature(bts->features, BTS_FEAT_SPEECH_H_V1);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_SPEECH_H_V1_RFC5993);
return 0;
}