Skip to content

Enabling Calico eBPF results in extreme degradation of HTTP/3 traffic throughput (many packet drops) #11367

@kylepl

Description

@kylepl

main_go.txt

As said, by switching to Calico eBPF (by turning of 'bpfEnabled' in the 'FelixConfiguration', and disabling kube-proxy) - it resulted in nice benefits like preserving the client IP.

Expected Behavior

Throughput for HTTP/3 (UDP) traffic should be ~the same for kube-proxy or Calico-based service implementations.

Current Behavior

The HTTP/3 (UDP) throughput is ~1/30th of the HTTP/2 (TCP) rate. If I revert back, this difference vanishes. Note that the rate is extremely slow when in the broken state - like 30kBps.

Notably, HTTP/2 (TCP) seems unaffected by the change to eBPF.

Also, the quic library I am using has hooks to detect lost packets and when packets are acknowledged, and it shows a lot of packet drops. An excerpt:

2025-11-11 19:55:27.424 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 0
2025-11-11 19:55:27.424 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 1
2025-11-11 19:55:27.424 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 2
2025-11-11 19:55:27.424 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 0
2025-11-11 19:55:27.424 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 1
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 2
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 3
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 19
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 4 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 5 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 6 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 7 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 8 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 9 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 10 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 11 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 12 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 13 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 14 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 15 reason: 0
2025-11-11 19:55:27.451 UTC‑05:002025/11/12 00:55:27 Packet lost: 16 reason: 0
2025-11-11 19:55:27.458 UTC‑05:002025/11/12 00:55:27 Packet lost: 17 reason: 1
2025-11-11 19:55:27.458 UTC‑05:002025/11/12 00:55:27 Packet lost: 18 reason: 1
2025-11-11 19:55:27.460 UTC‑05:002025/11/12 00:55:27 Packet acknowledged: 26

Steps to Reproduce (for bugs)

I have attached a minimal version that reproduces the issue (well, the go server part of it). It starts an HTTP/2 and HTTP/3 server. Visit /serve_data to get 1MB of data. If you are using a browser to trigger it, the first request will be HTTP/2, but after that, it should switch to HTTP/3 (which then shows the degradation).

It also includes logging for acked / lost packets.

You can see it running at https://http3test.morsel.ca/serve_data, where hitting that with HTTP/2 will be fast, with HTTP/3 it will be slow.

Context

Trying to preserve client IP on a managed Kubernetes environment.

You can also see discussion on Slack about this issue.

Your Environment

  • Kubernetes
  • Vultr VKE version: v1.34.1+1
  • OS: Ubuntu 24.04.3 LTS
  • Kernel: 6.8.0-79-generic
  • containerd://1.7.25
  • Calico version: v3.30.3

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions