Skip to content

v1.19: backport gateway-api fixes - #46826

Merged
aanm merged 19 commits into
cilium:v1.19from
0xch4z:pr/ck/v1.19-gateway-api-backports
Jul 15, 2026
Merged

aanm merged 19 commits into
cilium:v1.19from
0xch4z:pr/ck/v1.19-gateway-api-backports

Conversation

@0xch4z

@0xch4z 0xch4z commented Jul 1, 2026 •

Copy link
Copy Markdown
Member

@maintainer-s-little-helper maintainer-s-little-helper Bot added backport/1.19 This PR represents a backport for Cilium 1.19.x of a PR that was merged to main. kind/backports This PR provides functionality previously merged into the main branch. labels Jul 1, 2026
@0xch4z

0xch4z commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

/test

@0xch4z
0xch4z marked this pull request as ready for review July 1, 2026 05:07
@0xch4z
0xch4z requested a review from a team as a code owner July 1, 2026 05:07
@joestringer

joestringer commented Jul 1, 2026 •

Copy link
Copy Markdown
Member

@0xch4z FYI the release tooling doesn't handle multi-line release notes well. Actually, for backports the standard tooling will instead add a section like this to the PR, and this will cause the release notes to show up correctly:

```upstream-prs
44962 45693 44889
```

Could you update the PR description to include this, and drop the release note section? Thanks!

@joestringer

Copy link
Copy Markdown
Member

@cilium/sig-servicemesh would be good for one of you to review this, particularly the patches with conflicts

@asauber asauber left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Currently working on a complete review. This is the most notable thing so far.

Because this is missing cb05729f33#diff-bd6864af98902e6616a2162225ab9a00a74010b41a9d245cddc615c732fe1001R240, the per-port listeners change would have no effect, and instead silently drop traffic for one of the ports.

@asauber
asauber self-requested a review July 3, 2026 08:12
@asauber

asauber commented Jul 3, 2026 •

Copy link
Copy Markdown
Member

I am a bit confused by this test, and wondering if we need to correct the behavior on main.

The purpose of the commit is to reject same-port listener conflicts. However, the test output data tests that those conflicted listeners end up listening.

The status writes appear to be correct, and appear in the output data (for example Programmed=False) https://github.com/0xch4z/cilium/blob/de555016ac13d847fe362930d87a4ffb2ceeb6d7/operator/pkg/gateway-api/testdata/gateway/tlsroute-mixed-protocol-listeners/output/gateway-tlsroute-mixed.yaml#L97-L116

However, the CEC output continues to include the 443 listener (meaning in practice Programmed=True). https://github.com/0xch4z/cilium/blob/de555016ac13d847fe362930d87a4ffb2ceeb6d7/operator/pkg/gateway-api/testdata/gateway/tlsroute-mixed-protocol-listeners/output/cec-gateway-tlsroute-mixed.yaml

This seems to me like another issue caused by our lack of a consistent parsing, validation and pruning pipeline. This will be addressed in the future by #46681, but modifying translation is the last phase of the implementation (which will be merged into main as a series of patches). So, we probably need a separate fix for this on main in the meantime.

Otherwise, the backport looks like a correct backport of the functionality.

@eufriction

Copy link
Copy Markdown
Contributor

@asauber Currently on holiday with stochastic availability for computer time. From a brief look, the second link you provided include plain HTTP and only one TLS listener. For the changes from #44889 to trigger, the idea was that there needs to be at least two of either HTTPS and TLS.

The plan was to also add plain HTTP to the same code path and remove the old path but I haven’t started on that as I’m unsure of the implications of #46681 and in what order the project would want things to happen. See #46681 (comment) for the question.

If needed, I can try to perform a deeper analysis during the weekend.

@asauber

asauber commented Jul 3, 2026 via email

Copy link
Copy Markdown
Member

@eufriction

Copy link
Copy Markdown
Contributor

@asauber I just came to think of that there were a few related PRs by other contributors that solved other parts of this puzzle. The clues should be in the comments of #44889 as I got heads up by multiple people during this work. I don’t know if those changes are backported as well?

@0xch4z

0xch4z commented Jul 5, 2026

Copy link
Copy Markdown
Member Author

@eufriction thanks for looking through!

@asauber I've added #45949 to this backport and validated the datapath for the gateway-multi-port-https and gateway-cross-protocol-same-hostname fixtures in a cluster locally.

manifests
# gateway-multi-port-https
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: echo-gw
  namespace: gw-test
spec:
  gatewayClassName: cilium
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      hostname: echo.example.test
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: echo-tls
      allowedRoutes:
        namespaces:
          from: Same
    - name: https-alt
      protocol: HTTPS
      port: 50051
      hostname: echo.example.test
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: echo-tls
      allowedRoutes:
        namespaces:
          from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: route-443
  namespace: gw-test
spec:
  parentRefs:
    - name: echo-gw
      sectionName: https
  hostnames:
    - echo.example.test
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      filters:
        - type: ResponseHeaderModifier
          responseHeaderModifier:
            set:
              - name: X-Served-By
                value: listener-443
      backendRefs:
        - name: whoami
          port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: route-50051
  namespace: gw-test
spec:
  parentRefs:
    - name: echo-gw
      sectionName: https-alt
  hostnames:
    - echo.example.test
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      filters:
        - type: ResponseHeaderModifier
          responseHeaderModifier:
            set:
              - name: X-Served-By
                value: listener-50051
      backendRefs:
        - name: whoami
          port: 80
---
# gateway-cross-protocol-same-hostname
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: xp-gw
  namespace: xp-test
spec:
  gatewayClassName: cilium
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      hostname: xp.example.test
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: xp-gw-tls
      allowedRoutes:
        namespaces:
          from: Same
    - name: tls-passthrough
      protocol: TLS
      port: 9443
      hostname: xp.example.test
      tls:
        mode: Passthrough
      allowedRoutes:
        namespaces:
          from: Same
        kinds:
          - kind: TLSRoute
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: https-route
  namespace: xp-test
spec:
  parentRefs:
    - name: xp-gw
      sectionName: https
  hostnames:
    - xp.example.test
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      filters:
        - type: ResponseHeaderModifier
          responseHeaderModifier:
            set:
              - name: X-Served-By
                value: listener-443-terminate
      backendRefs:
        - name: whoami
          port: 80
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: tls-route
  namespace: xp-test
spec:
  parentRefs:
    - name: xp-gw
      sectionName: tls-passthrough
  hostnames:
    - xp.example.test
  rules:
    - backendRefs:
        - name: whoami-tls
          port: 443

Gateway with 2 https listeners, same host, different ports. Each frontend get its own L7LB proxy port:

 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• 5m 16s ❱ kubectl -n gw-test get gateway,httproute
NAME                                        CLASS    ADDRESS          PROGRAMMED   AGE
gateway.gateway.networking.k8s.io/echo-gw   cilium   172.18.255.193   True         150m

NAME                                              HOSTNAMES               AGE
httproute.gateway.networking.k8s.io/route-443     ["echo.example.test"]   150m
httproute.gateway.networking.k8s.io/route-50051   ["echo.example.test"]   150m
 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• ❱ curl -sk -D- --resolve echo.example.test:50051:172.18.255.193 https://echo.example.test:50051/ | grep 'x-served-by'
x-served-by: listener-50051
 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• ❱ curl -sk -D- --resolve echo.example.test:443:172.18.255.193 https://echo.example.test:443/ | grep 'x-served-by'
x-served-by: listener-443
 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• ❱ kubectl -n kube-system exec ds/cilium -- cilium-dbg bpf lb list | grep "172.18.255.193" | grep -i "proxy port"
172.18.255.193:50051/TCP (0)       0.0.0.0:0 (26) (0) [LoadBalancer, l7-load-balancer] (L7LB Proxy Port: 12930)
172.18.255.193:443/TCP (0)         0.0.0.0:0 (25) (0) [LoadBalancer, l7-load-balancer] (L7LB Proxy Port: 10682)

Gateway with tls (passthrough) listener and https listener, same host.

 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• ❱ kubectl -n xp-test get gateway,tlsroute,httproute
NAME                                      CLASS    ADDRESS          PROGRAMMED   AGE
gateway.gateway.networking.k8s.io/xp-gw   cilium   172.18.255.194   True         37m

NAME                                           AGE
tlsroute.gateway.networking.k8s.io/tls-route   37m

NAME                                              HOSTNAMES             AGE
httproute.gateway.networking.k8s.io/https-route   ["xp.example.test"]   37m
 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• ❱ kubectl -n kube-system exec ds/cilium -- cilium-dbg bpf lb list | grep "172.18.255.194" | grep -i "proxy port"
172.18.255.194:9443/TCP (0)        0.0.0.0:0 (44) (0) [LoadBalancer, l7-load-balancer] (L7LB Proxy Port: 13498)
172.18.255.194:443/TCP (0)         0.0.0.0:0 (43) (0) [LoadBalancer, l7-load-balancer] (L7LB Proxy Port: 11216)
 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• ❱ curl -ksv --resolve xp.example.test:9443:172.18.255.194 https://xp.example.test:9443/ 2>&1 | grep subject
*   subject: CN=xp.example.test; O=backend-passthrough
 I  ~/w/c/1.19-gwapi-backports pr/ck/v1.19-gateway-api-backports• ❱ curl -ksv --resolve xp.example.test:443:172.18.255.194 https://xp.example.test:443/ 2>&1 | grep subject
*   subject: CN=xp.example.test; O=gateway-terminated

@0xch4z

0xch4z commented Jul 5, 2026

Copy link
Copy Markdown
Member Author

/test

@asauber

asauber commented Jul 6, 2026

Copy link
Copy Markdown
Member

@eufriction I've opened a separate issue to track the exact case that I'm concerned about. It can be easily reproduced, but as you mention, requires another "auxiliary" listener to be present in order for Envoy to be programmed and demonstrate the bug.

For now, let's consider it a separate issue #46917

@asauber asauber left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Let's continue backporting related tests as they are introduced.

@aanm

aanm commented Jul 15, 2026

Copy link
Copy Markdown
Member

@0xch4z there are some file conflicts and the PR can't be merged as is.

eufriction and others added 3 commits July 15, 2026 12:08
[ upstream commit 4368970 ]

Filter listener loop by parentRef.SectionName and parentRef.Port so
a non-targeted listener cannot overwrite the Accepted condition.

Fixes: cilium#45559

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit f334eb4 ]

Continue to the next listener when a Selector doesn't match instead of
returning false immediately, so a permissive listener later in the
spec is still evaluated.

Fixes: cilium#42159

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 0ac732c ]

The Gateway API ingestion layer appends a TLSPassthroughListener for every
listener regardless of protocol, so IsTLSPassthroughListenerConfigured()
and TLSPassthroughPorts() need to check len(l.Routes) > 0 rather than
just testing whether the slice is non-empty.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 61cf6e5 ]

Add HTTPSPortsSorted(), NeedsPerPortHTTPSListeners(),
IsHTTPSPortConfigured(), TLSListenerRef, and TLSSecretsToListeners().
No callers yet, preparing for next steps

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 3384426 ]

[ Backporter's notes: Minor conflicts due to authFilters not being
present on VirtualHostParameters. ]

Previously all HTTPS routes were bucketed under a single "secure" key,
so listeners on different ports (e.g. 443 and 50051) shared one
RouteConfiguration. Split the key by numeric port, gated on
NeedsPerPortHTTPSListeners() so single-port Gateways and Ingress are
unchanged.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 4f1d3fa ]

Golden inputs and expected outputs for a Gateway with HTTPS listeners
on ports 443 and 50051 sharing a hostname and TLS secret.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 5e73484 ]

[ Backporter's notes: Conflicts due to missing
httproute-backendtlspolicy-* tests on v1.19. and SDS secretes
not namespaced as expected in testdata for gateway-multi-port-https test. ]

Exercises a Gateway with HTTPS listeners on ports 443 and 50051 sharing
a TLS secret. Verifies per-port listener splitting produces separate
CiliumEnvoyConfig resources and correct Gateway/Route status conditions.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit e9b780a ]

Emit a separate Envoy Listener per TLS passthrough port when per-port
mode is active, preventing filter chain collisions on shared hostnames.

Refactor TLS passthrough filter chain helpers to support port-scoped
generation. Split ServiceListener entries per TLS passthrough port.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 4a80c9b ]

Add NeedsCrossProtocolSplit() to trigger per-port splitting when HTTPS
and TLS passthrough would produce identical Envoy ServerNames matchers.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit a64e748 ]

[ Backporter's notes: Some conflicts due to differing signatures of
isAllowed, isAttachable, GatewayAPI in operator/pkgs/gateway-api/helpers.go
and operator/pkg/model/ingestion/gateway.go ]

Use helpers.IsListenerNamespaceAllowed() for HTTPRoute, GRPCRoute, and
TLSRoute ingestion.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 42a9bc9 ]

Exercises a Gateway combining multi-port HTTPS and multi-port TLS
passthrough listeners on distinct ports with disjoint hostnames.
Validates per-port listener splitting, service mapping, and status
conditions.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 33be339 ]

Exercises a Gateway where HTTPS (port 443) and TLS passthrough (port
9443) share the same hostname. Verifies per-port listener separation,
preventing Envoy filter chain collisions.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit fc64c19 ]

Exercises a Gateway with two HTTPS listeners sharing a hostname where
one restricts routes to Same namespace and the other allows All. A
cross-namespace route is excluded from the restricted listener's route
config while accepted on the open listener.

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit cb05729 ]

[ Backporter's notes: Dropped patches for DeepEqual and
RequiresZoneUpdate as commits 2a04076 and 88ce4cc that introduced them
are not present in v1.19 tree. ]

processCEC stored one ProxyRedirect per service name. When multi-port
Gateways produced two ServiceListener entries for the same service the
second overwrote the first, leaving one port without an L7 redirect in
the BPF LB map.

Change Service.ProxyRedirect to ProxyRedirects ([]*ProxyRedirect) and
resolve per frontend via ProxyRedirects.ForPort().

Signed-off-by: Martin Lindberg <[email protected]>
[ upstream commit 3ee0933 ]

ProxyRedirects.ForPort prefers an exact port match over a wildcard
(empty Ports) fallback. A single pass returns immediately on an exact
match and tracks the first wildcard to return at the end.

Signed-off-by: Martin Lindberg <[email protected]>
@0xch4z
0xch4z force-pushed the pr/ck/v1.19-gateway-api-backports branch from 0204ac0 to 906e6fe Compare July 15, 2026 18:18
@0xch4z

0xch4z commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

/test

@0xch4z

0xch4z commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

@aanm I've rebased and re-validated from my previous comment.

@aanm
aanm enabled auto-merge July 15, 2026 21:26
@aanm
aanm added this pull request to the merge queue Jul 15, 2026
@maintainer-s-little-helper maintainer-s-little-helper Bot added the ready-to-merge This PR has passed all tests and received consensus from code owners to merge. label Jul 15, 2026
Merged via the queue into cilium:v1.19 with commit f21b3a5 Jul 15, 2026
72 of 73 checks passed
0xch4z added a commit to 0xch4z/cilium that referenced this pull request Jul 16, 2026
Relates to bf03ce5. This patch is a
continuation of the secret cleanup for newly added gateway-api golden
tests after the merge of cilium#46826 (which was rebased just before bf03ce5).

Signed-off-by: Charlie Kenney <[email protected]>
@0xch4z

0xch4z commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@aanm @joestringer rebase just missed bf03ce5, CI failed on merge. 😓

I've opened a PR with fixes for the new tests: #47229

0xch4z added a commit to 0xch4z/cilium that referenced this pull request Jul 16, 2026
Once a fixture is run with `hostNetwork = true` all following fixtures
are run with `HostNetworkConfig.Enabled = true`.

I found this bug while rebasing cilium#46826. The ordering of the
gatewayclassconfig-nodeport test is fragile, it would pass if it came
after the hostNetwork tests but fail when run on it's own or before.
With this fix the test will fail again.

Signed-off-by: Charlie Kenney <[email protected]>
HadrienPatte pushed a commit to DataDog/cilium that referenced this pull request Jul 16, 2026
Relates to bf03ce5. This patch is a
continuation of the secret cleanup for newly added gateway-api golden
tests after the merge of cilium#46826 (which was rebased just before bf03ce5).

Signed-off-by: Charlie Kenney <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/1.19 This PR represents a backport for Cilium 1.19.x of a PR that was merged to main. feature/k8s-gateway-api kind/backports This PR provides functionality previously merged into the main branch. ready-to-merge This PR has passed all tests and received consensus from code owners to merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants