History

bpf: Support replacing cgroup-bpf program in MULTI mode

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).

Andrey Ignatov committed 6 years ago

Commit 7dd68b31 parent 9fab3296 files · +54 −9Browse files

Showing the changes to include/uapi/linux (1 of 6 files). Show all

Unified · Split

include/uapi/linux/bpf.h+10−0
@@ -231,6 +231,11 @@ enum bpf_attach_type { · 230 unmodified lines
231231 * When children program makes decision (like picking TCP CA or sock bind)
232232 * parent program has a chance to override it.
233233 *
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+ *
234239 * A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups.
235240 * A cgroup with NONE doesn't allow any programs in sub-cgroups.
236241 * Ex1:
@@ -249,6 +254,7 @@ enum bpf_attach_type { · 12 unmodified lines
249254 */
250255 #define BPF_F_ALLOW_OVERRIDE (1U << 0)
251256 #define BPF_F_ALLOW_MULTI (1U << 1)
257+#define BPF_F_REPLACE (1U << 2)
252258
253259 /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
254260 * verifier will perform strict alignment checking as if the kernel
@@ -442,6 +448,10 @@ union bpf_attr { · 187 unmodified lines
442448 __u32 attach_bpf_fd; /* eBPF program to attach */
443449 __u32 attach_type;
444450 __u32 attach_flags;
451+ __u32 replace_bpf_fd; /* previously attached eBPF
452+ * program to replace if
453+ * BPF_F_REPLACE is used
454+ */
445455 };
446456
447457 struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */