Skip to content

sockets: Terminate sockets with BPF socket iterators #38693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 4, 2025

Conversation

jrife
Copy link
Contributor

@jrife jrife commented Apr 2, 2025

This is a follow up to #37907...

bpf_sock_destroy(), a kfunc introduced in the 6.5 kernel by @aditighag was implemented as a way to destroy UDP sockets connected to a stale UDP backend. While the original RFC mentions one possible advantage being the elimination of exposure and traversal of every network namespace, the final patch series still requires that socket iteration be done per namespace.

We are currently leaning towards invoking the sock_destroy API
directly from BPF programs. This allows us to have an effective
mechanism without having to enter every possible container network
namespace on a node, and rely on the CONFIG_INET_DIAG_DESTROY config
with the right permissions. BPF programs attached to cgroup hooks can
store client sockets connected to a backend, and invoke destroy APIs
when backends are deleted.

However, this approach still reduces dependence on CONFIG_INET_DIAG_DESTROY, which the RFC claims is disabled by default. Perhaps a future kernel improvement to BPF socket iterators could allow for namespace iteration to be pushed to the BPF layer as well.

The API is behind the CONFIG_INET_DIAG_DESTROY config that's disabled by default

It seems that this change has been planned for awhile, so this PR takes a stab at implementing it. Originally, this was blocked by the availability of bpf_sock_destroy() in production kernels and the availability of newer versions of LLVM inside Cilium. However, 6.8+ is now the default kernel version on many Ubuntu distros, and LLVM has long since been upgraded, not that the LLVM version shipped with Cilium matters much, since this PR bakes in bpf_sock_term.o into the Cilium agent image (more on this below).

This PR splits BPF, control plane, and test changes into different commits for easier review.

BPF Changes: bpf_sock_term.c

bpf_sock_term.c implements cil_sock_udp_destroy. cil_sock_udp_destroy is meant to be used in conjunction with BPF socket iterators to iterate through all sockets in a network namespace and destroy any matching the configured filter. cilium_sock_term_filter is a single-element array containing the filter, a value consisting of a backend's address family, address, and port.

An earlier prototype of the program simply used DECLARE_CONFIG for each of the filter fields, requiring a new program to be configured and loaded for each new backend filter. This was convenient since there was no need to coordinate access to the map in userspace between parallel calls to TerminateUDPConnectionsToBackend(), but was ultimately too slow
(about 100x slower according to a simple benchmark). So, userspace needs to synchronize access to the map and this program using a mutex. Each "iterator instance" needs to follow this sequence:

  1. Acquire some lock.
  2. Set the value of the filter in cilium_sock_term_filter.
  3. Create a new socket iterator.
  4. Read all items in the iterator.
  5. Release the lock.

It's OK for different calls to TerminateUDPConnectionsToBackend() to intertwine as long as these "critical sections" are sequential between threads.

The program combines the current socket's cookie and the configured filter into a cilium_lb(4|6)_reverse_sk map key and checks for the existence of that key to see if this socket was connected to the now obsolete backend. If so, it destroys it with the bpf_sock_destroy() kfunc.

A couple of points worth calling out:

  1. bpf_sock_term.c uses sparse definitions of struct bpf_iter__udp and its dependencies to avoid pulling in vmlinux.h or a long chain of dependencies; it's not as straightforward as other definitions which can be cleanly copied in by syncing some header from the kernel.
  2. I tried using Co-Re helpers around field accesses but had limited success. While I could use them to get a pointer to sk, I couldn't pass that pointer to the bpf_sock_destroy() kfunc without the verifier complaining about unsafe pointers or some such thing. This could use some further investigation, but at least right now I'm not sure how to get this to work. So, I guess there's some risk of the field accesses breaking on newer kernels if offsets change in struct bpf_iter__udp. This probably warrants some discussion.
  3. bpf_sock_term.c is compiled once and built into the Cilium agent image, a big departure from other programs which are compiled at runtime, but hopefully not an unwelcome one. With the clang-free milestone underway, I figured I would just skip right to the end with this new program and bake it into the image. I'm not sure how well this aligns with the long term vision, so it would probably be good to get some input from @ti-mo and @dylandreimerink who are driving the clang-free effort.

Control Plane Changes

Beyond the obvious plumbing that needs to happen to initialize programs and maps, this PR implements an alternative strategy for destroying sockets in the current net namespace called BPFSocketDestroyer and moves the original netlink-based Destroy() function to a new SocketDestroyer called NetlinkSocketDestroyer. backendConnectionHandler uses BPFSocketDestroyer by default but falls back to NetlinkSocketDestroyer if that fails, as would be the case if the current kernel does not support the bpf_sock_destroy() kfunc.

BPFSockDestroyer#Destroy() lazy-initializes the socket iterator program, sets the value in the socket filter map, initializes the socket iterator, then iterates to completion. It takes a lock over this whole sequence to ensure calls to Destroy() are serialized across parallel instances of TerminateUDPConnectionsToBackend().

Test

This PR includes BPF unit tests as well as integration tests for netlink and BPF socket destroyer variants, but here's a small demo of the BPF socket destroyer working with a workload I put together earlier to test connected UDP sockets.

apiVersion: v1
data:
  config.js: |
    {
      "port": 8125,
      "address_ipv6": true,
      "backends": [ "./backends/console" ],
      "debug": true,
      "dumpMessages": true,
    }
kind: ConfigMap
metadata:
  name: statsd-config
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: statsd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: statsd
  template:
    metadata:
      labels:
        app: statsd
    spec:
      containers:
      - name: statsd
        image: statsd/statsd:latest # Or specify a particular version
        command:
        - ./bin/statsd
        - /etc/statsd/config.js
        ports:
        - containerPort: 8125
          name: statsd
        volumeMounts:
        - name: config-volume
          mountPath: /etc/statsd
      volumes:
      - name: config-volume
        configMap:
          name: statsd-config
---
apiVersion: v1
kind: Service
metadata:
  name: statsd
spec:
  ipFamilyPolicy: PreferDualStack
  ipFamilies:
  - IPv6
  - IPv4
  selector:
    app: statsd
  ports:
  - protocol: UDP
    port: 8125
    targetPort: 8125
    name: statsd
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gen-stats
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gen-stats
  template:
    metadata:
      labels:
        app: gen-stats
    spec:
      containers:
      - name: gen-stats
        image: python:3.9-slim-buster
        command:
          - python
          - /etc/gen-stats/gen-stats.py
          - $(POD_NAME)
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        volumeMounts:
        - name: config-volume
          mountPath: /etc/gen-stats
      volumes:
      - name: config-volume
        configMap:
          name: gen-stats
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: gen-stats
data:
  gen-stats.py: |
    import time
    import sys
    import socket

    pod_name = sys.argv[1]
    family, _, _, _, addr = socket.getaddrinfo('statsd', 8125, socket.AF_INET6, socket.SOCK_DGRAM)[0]
    print('Address: ' + str(addr), flush=True)
    sock = socket.socket(family, socket.SOCK_DGRAM)
    sock.bind(('', 10001))
    sock.connect(addr)

    while True:
        try:
          sock.send(bytes(pod_name + ':1|c', encoding='ascii'))
        except OSError as e:
          print('send failed: ' + str(e), flush=True)
          try:
            sock = socket.socket(family, socket.SOCK_DGRAM)
            sock.bind(('', 10001))
            sock.connect(addr)
          except OSError as e:
            print('recreate socket failed: ' + str(e), flush=True)
          else:
            print('Recreated socket', flush=True)
        else:
          print('send completed', flush=True)

        time.sleep(1)
jordan@t14:~/code/cilium$ kubectl get pods -A -o wide
NAMESPACE            NAME                                         READY   STATUS    RESTARTS   AGE     IP             NODE                 NOMINATED NODE   READINESS GATES
default              gen-stats-6b7ff59478-rdl6j                   1/1     Running   0          56s     10.244.1.46    kind-worker2         <none>           <none>
default              statsd-654f7b64b4-56lwq                      1/1     Running   0          56s     10.244.1.6     kind-worker2         <none>           <none>
...
jordan@t14:~/code/cilium$ kubectl delete pods statsd-654f7b64b4-56lwq
pod "statsd-654f7b64b4-56lwq" deleted
jordan@t14:~/code/cilium$ 

Meanwhile,

jordan@t14:~/code/cilium$ kubectl logs -f gen-stats-6b7ff59478-rdl6j
Address: ('fd00:10:96::5ebf', 8125, 0, 0)
...
send completed
send completed
send failed: [Errno 89] Destination address required
recreate socket failed: [Errno 1] Operation not permitted
send failed: [Errno 89] Destination address required
recreate socket failed: [Errno 1] Operation not permitted
send failed: [Errno 89] Destination address required
recreate socket failed: [Errno 1] Operation not permitted
send failed: [Errno 89] Destination address required
Recreated socket
send completed
send completed
send completed
send completed
send completed
^C
jordan@t14:~/code/cilium$ kubectl logs -n kube-system cilium-rx545 | grep -i terminated
time=2025-04-07T21:03:12Z level=info msg="Forcefully terminated sockets" module=agent.controlplane.service-manager filter="{DestIp:fd00:10:244:1::e9d7 DestPort:8125 Family:10 Protocol:17 DestroyCB:0x2f87d20}" destroyed=2
jordan@t14:~/code/cilium$ 

Related Kernel Patches

I made some improvements upstream that eliminate scenarios where some sockets may be skipped or repeated during iteration for TCP and UDP socket iterators. This should make socket iterators as a mechanism for this sort of thing a bit more reliable.

Fixes: #37907

sockets: In socket-LB mode, terminate sockets connected to deleted backends using BPF socket iterators.

@maintainer-s-little-helper

This comment was marked as resolved.

@maintainer-s-little-helper maintainer-s-little-helper bot added dont-merge/needs-sign-off The author needs to add signoff to their commits before merge. dont-merge/needs-release-note-label The author needs to describe the release impact of these changes. labels Apr 2, 2025
@jrife jrife changed the title Jrife/terminate socks split sockets: Terminate UDP sockets with BPF socket iterators Apr 2, 2025
@jrife jrife force-pushed the jrife/terminate-socks-split branch from 2f1f523 to eb68f15 Compare April 2, 2025 21:46
@maintainer-s-little-helper maintainer-s-little-helper bot removed the dont-merge/needs-sign-off The author needs to add signoff to their commits before merge. label Apr 2, 2025
@jrife jrife force-pushed the jrife/terminate-socks-split branch 16 times, most recently from 7fafc73 to 86636db Compare April 7, 2025 21:24
@jrife jrife marked this pull request as ready for review April 7, 2025 21:46
@jrife jrife requested review from a team as code owners April 7, 2025 21:46
@jrife jrife requested a review from brlbil April 7, 2025 21:46
jrife added 5 commits August 1, 2025 11:54
Move cilium_lb(4|6)_reverse_sk map definitions to sock.h so that they
can be shared with bpf_sock_term.c, a program added in subsequent
commits which can destroy sockets connected to a particular backend.

Fixes: cilium#37907

Signed-off-by: Jordan Rife <jrife@google.com>
Implement bpf_sock_term.c, the program that handles socket destruction,
and its unit tests. cil_sock_(udp|tcp)_destroy_v4 and
cil_sock_(udp|tcp)_destroy_v6 are meant to be used in conjunction with
BPF socket iterators to iterate through all sockets in a network
namespace and destroy any matching the configured filter.
cilium_sock_term_filter is a variable containing the filter, a value
consisting of a backend's address family, address, and port.

The programs combine the current socket's cookie and the configured
filter into a cilium_lb(4|6)_reverse_sk map key and check for the
existence of that key to see if this socket was connected to the now
obsolete backend. If so, it destroys it with the bpf_sock_destroy()
kfunc.

An earlier prototype of the program simply used DECLARE_CONFIG for each
of the filter fields, requiring a new program to be configured and
loaded for each new backend filter. This was convenient since there was
no need to coordinate access to the variable in userspace between
parallel calls to TerminateUDPConnectionsToBackend(), but was ultimately
too slow (about 100x slower according to a simple benchmark). So,
userspace needs to synchronize access to cilium_sock_term_filter and
this program using a mutex. Each "iterator instance" needs to follow
this sequence:

1) Acquire some lock.
2) Set the value of the filter in cilium_sock_term_filter.
3) Create a new socket iterator.
4) Read all items in the iterator.
5) Release the lock.

It's OK for different calls to TerminateConnectionsToBackend() to
intertwine as long as these "critical sections" are sequential between
threads.

Fixes: cilium#37907

Signed-off-by: Jordan Rife <jrife@google.com>
bpf_sock_term.o was built from the start to be "clang free". Use bpf2go
to embed compiled BPF bytecode and generate Go skeletons. Reorder struct
definitions inside union u6addr to ensure that the generated Go struct
has a [16]uint8 for the Addr field and name the anonymous structs to get
bpf2go to stop complaining. Add llvm-strip to the builder image, a
dependency of bpf2go, and use the builder image for BPF generation
(`make -C bpf generate`) to ensure reproducible results on systems with
different LLVM versions.

Bump github.com/cilium/ebpf module version to pull in [1].

[1]: cilium/ebpf#1829

Fixes: cilium#37907

Signed-off-by: Jordan Rife <jrife@google.com>
Implement an alternative strategy for destroying sockets in the current
net namespace called BPFSocketDestroyer and move the original
netlink-based Destroy() function to a new SocketDestroyer called
NetlinkSocketDestroyer. At startup, check if the bpf_sock_destroy kfunc
is supported on the current kernel, and if not, fall back to
NetlinkSocketDestroyer.

BPFSockDestroyer#Destroy() sets the value of the socket filter,
initializes the socket iterator, then iterates to completion. It takes a
lock over this whole sequence to ensure calls to Destroy() are
serialized across parallel instances of
TerminateConnectionsToBackend().

Create SocketDestroyer inside the one shot job inside
registerSocketTermination to guarantee that all LB maps have been
initialized, and plumb the socket revnat maps through to LoadSockTerm.

Fixes: cilium#37907

Signed-off-by: Jordan Rife <jrife@google.com>
Introduce test coverage and benchmarks for both SocketDestroyer
implementations.

Fixes: cilium#37907

Signed-off-by: Jordan Rife <jrife@google.com>
auto-merge was automatically disabled August 1, 2025 18:54

Head branch was pushed to by a user without write access

@jrife jrife force-pushed the jrife/terminate-socks-split branch from ef63af4 to 471113d Compare August 1, 2025 18:54
@jrife
Copy link
Contributor Author

jrife commented Aug 1, 2025

/test

@jrife
Copy link
Contributor Author

jrife commented Aug 1, 2025

/ci-ipsec-e2e

@joestringer joestringer dismissed ti-mo’s stale review August 1, 2025 22:06

Review comments addressed

@joestringer
Copy link
Member

Timo is out for a few weeks, and it looks like @jrife has done his best to address or respond to the earlier feedback. Strictly speaking that means that @cilium/loader hasn't given an approval, so I think it's reasonable to give a little extra time for someone there to see (maybe @rgo3 or @dylandreimerink ?) but if there's no further feedback in the next few days then it seems like this should be fine to merge. We can always iterate more in-tree.

@joestringer joestringer self-assigned this Aug 1, 2025
@joestringer joestringer requested a review from a team August 1, 2025 22:10
@joestringer joestringer enabled auto-merge August 4, 2025 17:14
@joestringer joestringer added this pull request to the merge queue Aug 4, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Aug 4, 2025
@joestringer
Copy link
Member

Filed #40925 for merge queue status check failure case, we've seen this before and it's unrelated to this PR.

@joestringer joestringer added this pull request to the merge queue Aug 4, 2025
Merged via the queue into cilium:main with commit a4265ec Aug 4, 2025
70 checks passed
@smagnani96
Copy link
Contributor

smagnani96 commented Aug 5, 2025

EDIT: @dylandreimerink found the culprit (🙏🏼 ), going to open a PR in a minute.

👋🏼 From commit bpf: Implement socket iterator program and tests, make kind-image-agent fails with:

❯ make kind-image-agent
kind is ready
make dev-docker-image DOCKER_IMAGE_TAG=local
make[1]: Entering directory '/home/XXX/tmp/cilium'
Using Docker Buildx builder "default" with build flags "--load".
: images/cilium/Dockerfile localhost:5000/cilium/cilium:local
docker buildx build -f images/cilium/Dockerfile  --load  --build-arg MODIFIERS="NOSTRIP= NOOPT= LOCKDEBUG= RACE= V= LIBNETWORK_PLUGIN= " --build-arg CILIUM_SHA=100f8bc179 --build-arg OPERATOR_VARIANT=cilium-dev --build-arg DEBUG_HOLD= --target release -t localhost:5000/cilium/cilium-dev:local .
[+] Building 4.9s (10/21)                                                                                                                                                                                                       docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                                                                      0.0s
 => => transferring dockerfile: 10.97kB                                                                                                                                                                                                   0.0s
 => [internal] load metadata for quay.io/cilium/cilium-envoy:v1.35.0-1753779236-ad8b8335b9191b13c3da99048bf850e439354e42@sha256:65aca8ec7223462777ca7d86394133a18dda8d41c37b6933489f1fc82945d504                                          0.4s
 => [internal] load metadata for quay.io/cilium/cilium-runtime:30803685cd0ff7897876e57fdac234a5caede8f0@sha256:551b44ea9c8e5dc6f6e8c55e8be84ad834d265f9024ed9fde8edf88abdd9424e                                                           0.6s
 => [internal] load metadata for quay.io/cilium/cilium-builder:223fc64724872068b184fc13404ba47afd389b46@sha256:282190764c045d75b5f60eec555449344aa6792ded348dbb82322e48b29ad857                                                           0.0s
 => [builder 1/7] FROM quay.io/cilium/cilium-builder:223fc64724872068b184fc13404ba47afd389b46@sha256:282190764c045d75b5f60eec555449344aa6792ded348dbb82322e48b29ad857                                                                     0.0s
 => [cilium-envoy 1/1] FROM quay.io/cilium/cilium-envoy:v1.35.0-1753779236-ad8b8335b9191b13c3da99048bf850e439354e42@sha256:65aca8ec7223462777ca7d86394133a18dda8d41c37b6933489f1fc82945d504                                               0.0s
 => [internal] load build context                                                                                                                                                                                                         3.5s
 => => transferring context: 261.00MB                                                                                                                                                                                                     3.4s
 => [release 1/8] FROM quay.io/cilium/cilium-runtime:30803685cd0ff7897876e57fdac234a5caede8f0@sha256:551b44ea9c8e5dc6f6e8c55e8be84ad834d265f9024ed9fde8edf88abdd9424e                                                                     0.0s
 => CACHED [builder 2/7] WORKDIR /go/src/github.com/cilium/cilium                                                                                                                                                                         0.0s
 => ERROR [builder 3/7] RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium     --mount=type=cache,target=/root/.cache     --mount=type=cache,target=/go/pkg     make GOARCH=amd64 DESTDIR=/tmp/install/linux/amd64   0.7s
------                                                                                                                                                                                                                                         
 > [builder 3/7] RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium     --mount=type=cache,target=/root/.cache     --mount=type=cache,target=/go/pkg     make GOARCH=amd64 DESTDIR=/tmp/install/linux/amd64 PKG_BUILD=1 $(echo NOSTRIP= NOOPT= LOCKDEBUG= RACE= V= LIBNETWORK_PLUGIN=  | tr -d '"') NOSTRIP=1     build-container install-container-binary:                                                                                                              
0.166 for i in cilium-dbg daemon cilium-health bugtool tools/mount tools/sysctlfix plugins/cilium-cni; do make  -C $i all; done                                                                                                                
0.168 make[1]: Entering directory '/go/src/github.com/cilium/cilium/cilium-dbg'                                                                                                                                                                
0.199 CGO_ENABLED=0  go build -mod=vendor -ldflags '-X "github.com/cilium/cilium/pkg/version.ciliumVersion=1.19.0-dev 100f8bc179 2025-04-01T21:21:48Z" -X "github.com/cilium/cilium/pkg/envoy.requiredEnvoyVersionSHA=ad8b8335b9191b13c3da99048bf850e439354e42" ' -tags=osusergo  -o cilium-dbg
0.456 ../pkg/datapath/bpf/sockterm_bpfel.go:198:12: pattern sockterm_bpfel.o: no matching files found
0.462 make[1]: *** [Makefile:23: cilium-dbg] Error 1
0.462 make[1]: Leaving directory '/go/src/github.com/cilium/cilium/cilium-dbg'
0.462 make: *** [Makefile:61: build-container] Error 2
------
Dockerfile:41
--------------------
  40 |     # in accordance with the supplied/default NOSTRIP setting. See "Extract debug symbols" below.
  41 | >>> RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium \
  42 | >>>     --mount=type=cache,target=/root/.cache \
  43 | >>>     --mount=type=cache,target=/go/pkg \
  44 | >>>     make GOARCH=${TARGETARCH} DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} PKG_BUILD=1 $(echo $MODIFIERS | tr -d '"') NOSTRIP=1 \
  45 | >>>     build-container install-container-binary
  46 |     
--------------------
ERROR: failed to build: failed to solve: process "/bin/sh -c make GOARCH=${TARGETARCH} DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} PKG_BUILD=1 $(echo $MODIFIERS | tr -d '\"') NOSTRIP=1     build-container install-container-binary" did not complete successfully: exit code: 2
make[1]: *** [Makefile.docker:125: dev-docker-image] Error 1
make[1]: Leaving directory '/home/XXX/tmp/cilium'
make: *** [Makefile.kind:200: kind-build-image-agent] Error 2

Any idea how to fix this?

smagnani96 added a commit that referenced this pull request Aug 5, 2025
In #38693 we added a new bpf program bpf/bpf_sock_term.c, and generated
the Go skeleton via bpf2go. Such targets, respectively pkg/datapath/bpf/sockterm_bpf{el,be}.go,
are however excluded while building docker images via `make kind-image-agent`,
resulting in the error `0.456 ../pkg/datapath/bpf/sockterm_bpfel.go:198:12: pattern sockterm_bpfel.o: no matching files found`.

The generated Dockerfile.dockerignore includes the rule  **/*.o
which instructs docker to omit any .o files. But it also includes a rule
!pkg/datapath/bpf/**/*.o which says it should add them to the context.
Due to the ordering the second rule does not work. It is placed before the
first in the file. And once you swap it, everything works.

This commits modifies how we compute the GIT_IGNORE_FILES variable.
The entire command finds all .gitignore files in the current directory
and its subdirectories, excluding those within any vendor directories.
It then sorts these .gitignore file paths by their "depth" in the directory
structure from shallowest to deepest.

Many thanks again to @dylandreimerink for the amazing investigation.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
Signed-off-by: Simone Magnani <simone.magnani@isovalent.com>
smagnani96 pushed a commit that referenced this pull request Aug 5, 2025
In #38693 we added a new bpf program bpf/bpf_sock_term.c, and generated
the Go skeleton via bpf2go. Such targets, respectively pkg/datapath/bpf/sockterm_bpf{el,be}.go,
are however excluded while building docker images via `make kind-image-agent`,
resulting in the error `0.456 ../pkg/datapath/bpf/sockterm_bpfel.go:198:12: pattern sockterm_bpfel.o: no matching files found`.

The generated Dockerfile.dockerignore includes the rule  **/*.o
which instructs docker to omit any .o files. But it also includes a rule
!pkg/datapath/bpf/**/*.o which says it should add them to the context.
Due to the ordering the second rule does not work. It is placed before the
first in the file. And once you swap it, everything works.

This commits modifies how we compute the GIT_IGNORE_FILES variable.
The entire command finds all .gitignore files in the current directory
and its subdirectories, excluding those within any vendor directories.
It then sorts these .gitignore file paths by their "depth" in the directory
structure from shallowest to deepest.

Many thanks again to @dylandreimerink for the amazing investigation.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
Signed-off-by: Simone Magnani <simone.magnani@isovalent.com>
github-merge-queue bot pushed a commit that referenced this pull request Aug 5, 2025
In #38693 we added a new bpf program bpf/bpf_sock_term.c, and generated
the Go skeleton via bpf2go. Such targets, respectively pkg/datapath/bpf/sockterm_bpf{el,be}.go,
are however excluded while building docker images via `make kind-image-agent`,
resulting in the error `0.456 ../pkg/datapath/bpf/sockterm_bpfel.go:198:12: pattern sockterm_bpfel.o: no matching files found`.

The generated Dockerfile.dockerignore includes the rule  **/*.o
which instructs docker to omit any .o files. But it also includes a rule
!pkg/datapath/bpf/**/*.o which says it should add them to the context.
Due to the ordering the second rule does not work. It is placed before the
first in the file. And once you swap it, everything works.

This commits modifies how we compute the GIT_IGNORE_FILES variable.
The entire command finds all .gitignore files in the current directory
and its subdirectories, excluding those within any vendor directories.
It then sorts these .gitignore file paths by their "depth" in the directory
structure from shallowest to deepest.

Many thanks again to @dylandreimerink for the amazing investigation.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
Signed-off-by: Simone Magnani <simone.magnani@isovalent.com>
rabelmervin pushed a commit to rabelmervin/cilium that referenced this pull request Aug 18, 2025
In cilium#38693 we added a new bpf program bpf/bpf_sock_term.c, and generated
the Go skeleton via bpf2go. Such targets, respectively pkg/datapath/bpf/sockterm_bpf{el,be}.go,
are however excluded while building docker images via `make kind-image-agent`,
resulting in the error `0.456 ../pkg/datapath/bpf/sockterm_bpfel.go:198:12: pattern sockterm_bpfel.o: no matching files found`.

The generated Dockerfile.dockerignore includes the rule  **/*.o
which instructs docker to omit any .o files. But it also includes a rule
!pkg/datapath/bpf/**/*.o which says it should add them to the context.
Due to the ordering the second rule does not work. It is placed before the
first in the file. And once you swap it, everything works.

This commits modifies how we compute the GIT_IGNORE_FILES variable.
The entire command finds all .gitignore files in the current directory
and its subdirectories, excluding those within any vendor directories.
It then sorts these .gitignore file paths by their "depth" in the directory
structure from shallowest to deepest.

Many thanks again to @dylandreimerink for the amazing investigation.

Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
Signed-off-by: Simone Magnani <simone.magnani@isovalent.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/datapath Impacts bpf/ or low-level forwarding details, including map management and monitor messages. feature/socket-lb Impacts the Socket-LB part of Cilium's kube-proxy replacement. release-note/misc This PR makes changes that have no direct user impact.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Terminate sockets using BPF kfunc helper