aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/l1sap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/l1sap.c')
-rw-r--r--src/common/l1sap.c99
1 files changed, 27 insertions, 72 deletions
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index f24bc2f7..f1692c68 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -54,6 +54,7 @@
#include <osmo-bts/bts_model.h>
#include <osmo-bts/handover.h>
#include <osmo-bts/msg_utils.h>
+#include <osmo-bts/rtp_input_preen.h>
#include <osmo-bts/pcuif_proto.h>
#include <osmo-bts/cbch.h>
@@ -1216,83 +1217,23 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
return 1;
}
-static bool rtppayload_is_octet_aligned(const uint8_t *rtp_pl, uint8_t payload_len)
+/* This helper function for l1sap_tch_rts_ind() preens incoming RTP frames
+ * for FR/EFR SID: if the received frame is a valid SID per the rules of
+ * GSM 06.31/06.81 section 6.1.1, it needs to be rejuvenated by clearing
+ * all reserved bits and resetting the SID code word to error-free 95 zeros
+ * for FR or 95 ones for EFR, and if the received frame is an invalid SID
+ * per the same rules, then we need to drop it. We return false if
+ * l1sap_tch_rts_ind() needs to drop this frame, otherwise true. */
+static bool rtppayload_sid_preen(struct gsm_lchan *lchan, struct msgb *msg)
{
- /*
- * Logic: If 1st bit padding is not zero, packet is either:
- * - bandwidth-efficient AMR payload.
- * - malformed packet.
- * However, Bandwidth-efficient AMR 4,75 frame last in payload(F=0, FT=0)
- * with 4th,5ht,6th AMR payload to 0 matches padding==0.
- * Furthermore, both AMR 4,75 bw-efficient and octet alignment are 14 bytes long (AMR 4,75 encodes 95b):
- * bw-efficient: 95b, + 4b hdr + 6b ToC = 105b, + padding = 112b = 14B.
- * octet-aligned: 1B hdr + 1B ToC + 95b = 111b, + padding = 112b = 14B.
- * We cannot use other fields to match since they are inside the AMR
- * payload bits which are unknown.
- * As a result, this function may return false positive (true) for some AMR
- * 4,75 AMR frames, but given the length, CMR and FT read is the same as a
- * consequence, the damage in here is harmless other than being unable to
- * decode the audio at the other side.
- */
- #define AMR_PADDING1(rtp_pl) (rtp_pl[0] & 0x0f)
- #define AMR_PADDING2(rtp_pl) (rtp_pl[1] & 0x03)
-
- if (payload_len < 2 || AMR_PADDING1(rtp_pl) || AMR_PADDING2(rtp_pl))
- return false;
-
- return true;
-}
-
-static bool rtppayload_validate_fr(struct msgb *msg)
-{
- if (msg->len != GSM_FR_BYTES)
- return false;
- if ((msg->data[0] & 0xF0) != 0xD0)
- return false;
- return osmo_fr_sid_preen(msg->data);
-}
-
-static bool rtppayload_validate_efr(struct msgb *msg)
-{
- if (msg->len != GSM_EFR_BYTES)
- return false;
- if ((msg->data[0] & 0xF0) != 0xC0)
- return false;
- return osmo_efr_sid_preen(msg->data);
-}
-
-static bool rtppayload_is_valid(struct gsm_lchan *lchan, struct msgb *resp_msg)
-{
- /* If rtp continuous-streaming is enabled, we shall emit RTP packets
- * with zero-length payloads as BFI markers. In a TrFO scenario such
- * RTP packets sent by call leg A will be received by call leg B,
- * hence we need to handle them gracefully. For the purposes of a BTS
- * that runs on its own TDMA timing and does not need timing ticks from
- * an incoming RTP stream, the correct action upon receiving such
- * timing-tick-only RTP packets should be the same as when receiving
- * no RTP packet at all. The simplest way to produce that behavior
- * is to treat zero-length RTP payloads as invalid. */
- if (resp_msg->len == 0)
- return false;
-
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
if (lchan->type == GSM_LCHAN_TCH_F)
- return rtppayload_validate_fr(resp_msg);
+ return osmo_fr_sid_preen(msg->data);
else
- return true; /* FIXME: implement preening for HR1 */
+ return true; /* FIXME: see OS#6036 */
case GSM48_CMODE_SPEECH_EFR:
- return rtppayload_validate_efr(resp_msg);
- case GSM48_CMODE_SPEECH_AMR:
- /* Avoid forwarding bw-efficient AMR to lower layers,
- * most bts models don't support it. */
- if (!rtppayload_is_octet_aligned(resp_msg->data, resp_msg->len)) {
- LOGPLCHAN(lchan, DL1P, LOGL_NOTICE,
- "RTP->L1: Dropping unexpected AMR encoding (bw-efficient?) %s\n",
- osmo_hexdump(resp_msg->data, resp_msg->len));
- return false;
- }
- return true;
+ return osmo_efr_sid_preen(msg->data);
default:
return true;
}
@@ -1337,7 +1278,7 @@ static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx,
if (!resp_msg) {
LOGPLCGT(lchan, &g_time, DL1P, LOGL_DEBUG, "DL TCH Tx queue underrun\n");
resp_l1sap = &empty_l1sap;
- } else if (!rtppayload_is_valid(lchan, resp_msg)) {
+ } else if (!rtppayload_sid_preen(lchan, resp_msg)) {
msgb_free(resp_msg);
resp_msg = NULL;
resp_l1sap = &empty_l1sap;
@@ -1943,6 +1884,20 @@ void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
if (lchan->loopback)
return;
+ /* initial preen */
+ switch (rtp_payload_input_preen(lchan, rtp_pl, rtp_pl_len)) {
+ case PL_DECISION_DROP:
+ return;
+ case PL_DECISION_ACCEPT:
+ break;
+ case PL_DECISION_STRIP_HDR_OCTET:
+ rtp_pl++;
+ rtp_pl_len--;
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+
msg = l1sap_msgb_alloc(rtp_pl_len);
if (!msg)
return;