Skip to content

Two VIP bindings on one port in a VPC overwrite each other #764

Closed

Description

@privateip

Summary

A node's VIP translation entries are keyed only by the VPC, protocol, direction and port, never by the VIP or backend address. Two bindings in one VPC on that node that share a port overwrite each other without any error, and removing one deletes the other's entry.

The reply side is wider still. Any workload in that VPC on the node whose traffic leaves from a bound backend port gets its source rewritten to the VIP, whether or not it is a backend.

This stays inside one tenant, unlike #716, but it sends a VIP's clients to the wrong backend and breaks unrelated flows. It must be fixed before any VIP serves traffic.

Acceptance criteria

  • Two VIPs in one VPC on the same port and protocol each reach their own backend on a shared node
  • Deleting one binding leaves every other binding on the node working
  • Traffic from a workload that is not a VIP backend leaves with its own source address and port
  • A binding that cannot be programmed without displacing another reports that on its status instead of overwriting it

Activity

  1. self-assigned this
    on Oct 7, 2026
  2. privateip commented on Oct 7, 2026

    @privateip
    CollaboratorAuthor

    Read at main 6077189. The key in internal/plumbing/ebpf/prog/usid.c is:

    struct vip_xlat_key {
    	__u64 block;
    	__u16 argument;
    	__u8 proto;
    	__u8 direction;
    	__be16 port;
    	__u16 pad2;
    };

    usid_ingress looks it up by the inner destination port and usid_egress by the source port. VipXlatTable.register in internal/plumbing/ebpf/vipxlatmap/vipxlat.go does a plain Put, and UnregisterIngress/UnregisterEgress take only block, argument, proto and port, so a second binding with the same tuple replaces the first and either binding's delete removes the shared row. The ServiceVIPBinding reconciler passes the VIP and backend addresses only as row values.

    The ingress row probably needs the VIP address in its key, and the egress row the backend address, which grows the key past 16 bytes and changes the pinned map's layout, so the migration needs a plan. No binding serves traffic in staging or prod today (all NetworkRules and ServiceVIPBindings are gone from both staging cells as of 2026-10-06), so nothing live depends on the current layout.

  3. added theissue type on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Fields

Priority

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions