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/uapi/linux (1 of 6 files). Show all
Unified · Split
| @@ -231,6 +231,11 @@ enum bpf_attach_type { · 230 unmodified lines | ||
| 231 | 231 | * When children program makes decision (like picking TCP CA or sock bind) |
| 232 | 232 | * parent program has a chance to override it. |
| 233 | 233 | * |
| 234 | + * With BPF_F_ALLOW_MULTI a new program is added to the end of the list of | |
| 235 | + * programs for a cgroup. Though it's possible to replace an old program at | |
| 236 | + * any position by also specifying BPF_F_REPLACE flag and position itself in | |
| 237 | + * replace_bpf_fd attribute. Old program at this position will be released. | |
| 238 | + * | |
| 234 | 239 | * A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups. |
| 235 | 240 | * A cgroup with NONE doesn't allow any programs in sub-cgroups. |
| 236 | 241 | * Ex1: |
| @@ -249,6 +254,7 @@ enum bpf_attach_type { · 12 unmodified lines | ||
| 249 | 254 | */ |
| 250 | 255 | #define BPF_F_ALLOW_OVERRIDE (1U << 0) |
| 251 | 256 | #define BPF_F_ALLOW_MULTI (1U << 1) |
| 257 | +#define BPF_F_REPLACE (1U << 2) | |
| 252 | 258 | |
| 253 | 259 | /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the |
| 254 | 260 | * verifier will perform strict alignment checking as if the kernel |
| @@ -442,6 +448,10 @@ union bpf_attr { · 187 unmodified lines | ||
| 442 | 448 | __u32 attach_bpf_fd; /* eBPF program to attach */ |
| 443 | 449 | __u32 attach_type; |
| 444 | 450 | __u32 attach_flags; |
| 451 | + __u32 replace_bpf_fd; /* previously attached eBPF | |
| 452 | + * program to replace if | |
| 453 | + * BPF_F_REPLACE is used | |
| 454 | + */ | |
| 445 | 455 | }; |
| 446 | 456 | |
| 447 | 457 | struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */ |