Skip to content

fix: shorten the duplicate packet window to 800 ms - #1930

Merged
bdraco merged 3 commits into
masterfrom
shorter_duplicate_window
Oct 31, 2026
Merged

bdraco merged 3 commits into
masterfrom
shorter_duplicate_window

Conversation

@bdraco

@bdraco bdraco commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Summary

Lowers the duplicate packet window from 1000 ms to 800 ms so the second copy of a repeated announcement is no longer thrown away when it lands just under a second after the first.

RFC 6762 §8.3 has responders repeat announcements about a second apart. lwIP's responder (used by the LibreTiny boards ESPHome supports) jitters that to 926 to 1028 ms on receipt, so roughly a quarter of the time the second announcement was dropped as a duplicate before any listener saw it.

Details

  • _DUPLICATE_QUESTION_INTERVAL stays at 999 ms. The two constants were never actually linked. The question interval started as _BROWSER_TIME - 1 in Implement duplicate question supression #770, when the browser's first requery was 1000 ms. The packet window became 1000 ms in Limit duplicate packet suppression to 1s intervals #841 to match the RFC 6762 §6 rule that a responder must not multicast a record more than once a second. When feat: significantly improve efficiency of the ServiceBrowser scheduler #1335 raised _BROWSER_TIME to 10 s, 999 became a literal and picked up the "1ms less" comment, but nothing depends on it. The question interval also spaces our own QM requeries, which RFC 6762 wants at least a second apart, so it should stay where it is.
  • Our own answers still follow the once a second rule, since QueryHandler checks that separately and sends recently multicast records through out_delay_queue.
  • Real duplicates (the same packet on several interfaces, or v4 and v6) arrive within a few ms, so they are still dropped.

Test plan

  • New test in tests/test_listener.py: a repeat 5 ms later is dropped, a repeat 926 ms later is processed.
  • Bench run against BK7238 and CB3S boards, 10 reboots each with the window patched to 1000, 900 and 800 ms. At 800 ms every reboot that could see both announcements did (7 of 7, gaps down to 945 ms), against 0 of 5 for gaps under a second at 1000 ms.

Responders that jitter their repeated announcements a little under a
second apart had the second copy dropped as a duplicate.
@bdraco
bdraco marked this pull request as ready for review October 31, 2026 04:06
@halibsbot

Copy link
Copy Markdown

PR Review — fix: shorten the duplicate packet window to 800 ms

Merge-ready: the change is small and does what the description says, with one comment nit.

Strengths:

  • Both dedup paths in _process_datagram_at_time (the last_time check and _recent_packets) read the same constant, so a single-value change moves both consistently.
  • Keeping _DUPLICATE_QUESTION_INTERVAL at 999 is correct. _history.py and the QM requery spacing in info.py:377-383 use it independently of the packet window, so dropping the old "1ms less" comment loses no enforced constraint.
  • The new test would fail with the old 1000 ms value, and it also pins that a 5 ms repeat is still dropped. The new constant comment cites RFC 6762 §8.3.
  • Responder rate limiting still holds. Repeated QM queries at 800-999 ms now reach async_response, but _has_mcast_record_in_last_second sends recently multicast records to the delayed queue (_core.py:201).

Needs attention:

  • Stale "~1s" wording remains in _listener.py:254 and tests/test_listener.py:392 (non-blocking).

Accepted trade-offs:

  • Under a sustained flood, the cap rises from one parse per payload per 1000 ms to one per 800 ms.
  • A peer's repeat at 800-999 ms now refreshes the question history for questions we can answer. Our own identical query can therefore stay suppressed slightly longer.

Not verified: the shell for this review blocked Python, so I did not run the tests. The test and bench results in the description are the author's claims.



Checklist

  • No hardcoded secrets
  • Input validation at boundaries
  • Timing change cites the relevant RFC section
  • New behaviour covered by a test that fails on the old value
  • Duplicate suppression stays bounded under flood
  • No Cython .pxd changes required

Automated review by Kōan (Claude) HEAD=047dbc4 2 min 4s

@halibsbot halibsbot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

No blocking issues found — ready to merge.

@github-actions

Copy link
Copy Markdown

Thanks for contributing! A quick note: this project is in the process of moving from LGPL-2.1 to Apache 2.0, and may keep LGPL-2.1-or-later as an OR option so GPL-2.0-only projects can keep using the library, see #1835.

By continuing with this pull request you agree that this new contribution is offered under both Apache 2.0 and LGPL-2.1-or-later, so it is covered under either outcome.

This notice does not affect your previous contributions. If you would like to consent to relicensing those as well, please post the consent statement on #1835; silence is never treated as consent for past work.

If offering this contribution under these licenses does not work for you, no hard feelings; reply with the exact phrase I do not agree to the Apache 2.0 license or simply close this pull request.

@codecov

codecov Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.87%. Comparing base (bd107c6) to head (f267a03).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1930   +/-   ##
=======================================
  Coverage   99.87%   99.87%           
=======================================
  Files          33       33           
  Lines        3913     3913           
  Branches      568      568           
=======================================
  Hits         3908     3908           
  Misses          3        3           
  Partials        2        2           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed

codspeed Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

1 warning

⚠️ 1 benchmark is dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

✅ 24 untouched benchmarks


Comparing shorter_duplicate_window (f267a03) with master (bd107c6)

Open in CodSpeed

@bdraco

bdraco commented Oct 31, 2026

Copy link
Copy Markdown
Member Author

Fixed the stale "~1s" wording in _listener.py and tests/test_listener.py so the comments refer to the suppression interval rather than a fixed second.

@bdraco
bdraco merged commit c245c2f into master Oct 31, 2026
38 of 39 checks passed
@bdraco
bdraco deleted the shorter_duplicate_window branch October 31, 2026 04:53
@bdraco bdraco mentioned this pull request Oct 31, 2026
7 of 21 tasks
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.

2 participants