The common use-case in production is to have multiple cgroup-bpf programs per attach type that cover multiple use-cases. Such programs are attached with BPF_F_ALLOW_MULTI and can be maintained by different people. Order of programs usually matters, for example imagine two egress programs: the first one drops packets and the second one counts packets. If they're swapped the result of counting program will be different. It brings operational challenges with updating cgroup-bpf program(s) attached with BPF_F_ALLOW_MULTI since there is no way to replace a program: * One way to update is to detach all programs first and then attach the new version(s) again in the right order. This introduces an interruption in the work a program is doing and may not be acceptable (e.g. if it's egress firewall); * Another way is attach the new version of a program first and only then detach the old version. This introduces the time interval when two versions of same program are working, what may not be acceptable if a program is not idempotent. It also imposes additional burden on program developers to make sure that two versions of their program can co-exist. Solve the problem by introducing a "replace" mode in BPF_PROG_ATTACH command for cgroup-bpf programs being attached with BPF_F_ALLOW_MULTI flag. This mode is enabled by newly introduced BPF_F_REPLACE attach flag and bpf_attr.replace_bpf_fd attribute to pass fd of the old program to replace That way user can replace any program among those attached with BPF_F_ALLOW_MULTI flag without the problems described above. Details of the new API: * If BPF_F_REPLACE is set but replace_bpf_fd doesn't have valid descriptor of BPF program, BPF_PROG_ATTACH will return corresponding error (EINVAL or EBADF). * If replace_bpf_fd has valid descriptor of BPF program but such a program is not attached to specified cgroup, BPF_PROG_ATTACH will return ENOENT. BPF_F_REPLACE is introduced to make the user intent clear, since replace_bpf_fd alone can't be used for this (its default value, 0, is a valid fd). BPF_F_REPLACE also makes it possible to extend the API in the future (e.g. add BPF_F_BEFORE and BPF_F_AFTER if needed).
Showing the changes to include/linux (1 of 6 files). Show all
Unified · Split
| @@ -85,6 +85,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp); · 84 unmodified lines | ||
| 85 | 85 | void cgroup_bpf_offline(struct cgroup *cgrp); |
| 86 | 86 | |
| 87 | 87 | int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, |
| 88 | + struct bpf_prog *replace_prog, | |
| 88 | 89 | enum bpf_attach_type type, u32 flags); |
| 89 | 90 | int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, |
| 90 | 91 | enum bpf_attach_type type); |
| @@ -93,7 +94,8 @@ int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, · 2 unmodified lines | ||
| 93 | 94 | |
| 94 | 95 | /* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */ |
| 95 | 96 | int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, |
| 96 | − enum bpf_attach_type type, u32 flags); | |
| 97 | + struct bpf_prog *replace_prog, enum bpf_attach_type type, | |
| 98 | + u32 flags); | |
| 97 | 99 | int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, |
| 98 | 100 | enum bpf_attach_type type, u32 flags); |
| 99 | 101 | int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, |