Page MenuHomeVyOS Platform

dhcp: Kea HA max-response-delay equals heartbeat-delay (disagrees with Kea defaults)
Closed, ResolvedPublicBUG

Description

Summary

When service dhcp-server high-availability is configured, VyOS generates Kea
HA hook parameters in python/vyos/template.py (kea_high_availability_json)
as:

"heartbeat-delay": 10000,
"max-response-delay": 10000,
"max-ack-delay": 5000,
"max-unacked-clients": 0

Kea's Administrator Reference Manual (HA hook / libdhcp_ha.so) documents:

  • heartbeat-delay — default 10000 ms
  • max-response-delay — default 60000 ms; duration since last successful partner communication after which communication is assumed interrupted. "This duration should be greater than the heartbeat-delay; typically it should be a multiple of heartbeat-delay."
  • max-unacked-clients — default 10; special value 0 disables the client-based failure-detection mechanism and transitions to partner-down immediately when the control channel fails
  • max-ack-delay — default 10000 ms (VyOS currently emits 5000; secondary)

With max-response-delay equal to heartbeat-delay, Kea opens a false-positive
window every heartbeat cycle: peer age reaches ~10s →
communication-interrupted=true for a fraction of a second while in-touch can
still be true and HA state stays load-balancing. That matches production
status-get polling and the ISC guidance that equal timers are incorrect.

max-unacked-clients: 0 additionally means any real communication-interrupted
condition skips unacked-client failure detection and can go partner-down
immediately (ARM: "disables the failure-detection mechanism").

Why it matters

  1. Healthy HA pairs log HA_COMMUNICATION_INTERRUPTED / CLIENT4 noise and briefly flip communication-interrupted on status-get even when the SYNC control channel and peer are fine.
  1. Monitoring that keys on communication-interrupted (or HA state) false-fires or goes "pending" without a real peer outage.
  1. Operators who trust stock generated Kea JSON are not getting Kea's documented defaults — they are getting a more aggressive / flaky timer set.

Reproduction

  1. Configure two routers with service dhcp-server high-availability (active-active / load-balancing or active-passive).
  2. Inspect /run/kea/kea-dhcp4.conf — observe equal 10000/10000 and max-unacked-clients 0.
  3. Poll status-get ~0.5s for 30–60s while healthy: remote.age cycles 0..10 remote.communication-interrupted becomes true when age hits 10 remote.in-touch often remains true; local state stays load-balancing
  4. Optional: patch max-response-delay to 60000, re-apply dhcp-server — age=10 no longer sets communication-interrupted.

Suggested fix

In kea_high_availability_json (python/vyos/template.py), align with Kea ARM
defaults:

'heartbeat-delay': 10000,        # unchanged
'max-response-delay': 60000,     # was 10000
'max-ack-delay': 5000,           # optional: 10000 to match Kea default
'max-unacked-clients': 10,       # was 0

Minimal change is max-response-delay + max-unacked-clients only.

Optional follow-up: expose the four timers under

service dhcp-server high-availability …

with those defaults, so sites can tune without patching template.py.

No CLI schema change is required for the minimal fix.

Environment

  • VyOS 1.5 Circinus rolling
  • Kea DHCP4 HA over a dedicated SYNC network (TCP :647)
  • Confirmed on multiple HA pairs (load-balancing)

Workaround

Patch installed template.py kea_high_availability_json defaults, then re-run
conf_mode service_dhcp-server.py (or any dhcp-server re-apply). Does not
survive image upgrades until fixed upstream.

References

  • Kea ARM — High Availability hook parameters (heartbeat-delay, max-response-delay, max-ack-delay, max-unacked-clients): https://kea.readthedocs.io/en/latest/arm/hooks.html (section libdhcp_ha.so / high availability parameters)
  • Related but distinct: T8392 (peer name must be peer hostname; Closed, Wontfix). That task's attached kea-dhcp4.conf also showed the equal 10000/10000 timers as generated by VyOS; this task is only about timer defaults, not peer naming.

Details

Version
Rolling / 1.5 Circinus
Is it a breaking change?
Perfectly compatible
Issue type
Bug (incorrect behavior)