Skip to content

[core] Add RTP_BUG_DONT_REPORT_FLUSHED_AS_LOST to exclude flushed packets from RTCP loss - #3071

Open
securepii-dev wants to merge 1 commit into
signalwire:masterfrom
securepii-dev:rtp-bug-dont-report-flushed-as-lost
Open

[core] Add RTP_BUG_DONT_REPORT_FLUSHED_AS_LOST to exclude flushed packets from RTCP loss#3071
securepii-dev wants to merge 1 commit into
signalwire:masterfrom
securepii-dev:rtp-bug-dont-report-flushed-as-lost

Conversation

@securepii-dev

Copy link
Copy Markdown

Summary

Adds an opt-in RTP bug flag RTP_BUG_DONT_REPORT_FLUSHED_AS_LOST (default off) that stops packets FreeSWITCH deliberately flushed from being reported as lost in the outbound RTCP receiver report.

Resolves #3070.

Problem

On DTMF-heavy systems with no jitter buffer, a sending endpoint (including FreeSWITCH itself) sets the RTP marker bit on the first voice packet after a DTMF event (talkspurt onset). This triggers do_flush(), which drains queued RTP from the socket and discards it. Those packets arrived over the network — FreeSWITCH just chose not to play them — but the resulting sequence gap is then reported as lost in RTCP. On calls with frequent DTMF the phantom loss accumulates and drags the MOS reported by upstream monitors below 4.0, hiding genuine quality problems behind spurious low-MOS calls.

Existing workarounds are unsatisfying:

  • IGNORE_MARK_BIT disables all marker-driven flushing — too blunt, breaks legitimate marker uses (hold, etc.).
  • Running a jitter buffer bypasses the flush, but adds delay on bridged calls for what is really a reporting problem.

Change

rtcp_generate_report_block() subtracts the number of packets flushed during the current RTCP interval from pkt_lost when the flag is set. A per-interval baseline (last_rpt_flush_count, added to switch_rtcp_numbers_t) is captured in rtcp_stats_init() and at each report reset. Genuine network loss (packets that never arrived, hence never counted as flushed) is unaffected — only deliberately-flushed, already-received packets are excluded.

Enable per channel: rtp_manual_rtp_bugs=DONT_REPORT_FLUSHED_AS_LOST.

Validation

Reproduced and A/B-tested on FreeSWITCH 1.11.1 behind rtpengine, DTMF-heavy bridged calls, no jitter buffer, matched measurement windows:

metric flag OFF flag ON
packets flushed by FS ~500 ~500 (unchanged)
max RTCP loss reported / call 30 1
calls with MOS < 4.0 1 (MOS 3.5) 0 (all MOS 4.3)

Flushing is identical in both arms; with the flag on the phantom loss disappears and MOS stays clean, while genuine loss would still be reported.

Notes

  • Default off — no behavior change for existing deployments.
  • 3 files, +31/-4.

…kets from RTCP loss

When FreeSWITCH flushes received RTP (e.g. do_flush() on the talkspurt
marker bit that follows a DTMF event, with no jitter buffer), the flushed
packets are discarded but the resulting sequence-number gap is reported as
lost in the outbound RTCP receiver report. Those packets were delivered by
the network and merely dropped locally, so counting them as transport loss
is misleading. On DTMF-heavy calls the phantom loss accumulates and drags
down the MOS reported by upstream monitors, masking genuine quality issues.

Add an opt-in RTP bug flag, RTP_BUG_DONT_REPORT_FLUSHED_AS_LOST (default
off), which subtracts the number of packets flushed during the current RTCP
interval from the reported loss count in rtcp_generate_report_block(). A
per-interval baseline is captured in rtcp_stats_init() and at each report
reset. Genuine network loss (packets that never arrived) is unaffected.

Enable per channel with rtp_manual_rtp_bugs=DONT_REPORT_FLUSHED_AS_LOST.

Fixes signalwire#3070

Signed-off-by: securepii-dev <245771355+securepii-dev@users.noreply.github.com>
@securepii-dev
securepii-dev marked this pull request as ready for review July 10, 2026 02:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dont report flushed packets as lost in RTCP

1 participant