]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
libbpf: Add function to set link XDP fd while specifying old program
authorToke Høiland-Jørgensen <toke@redhat.com>
Wed, 25 Mar 2020 17:23:28 +0000 (18:23 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 28 Mar 2020 21:24:41 +0000 (14:24 -0700)
This adds a new function to set the XDP fd while specifying the FD of the
program to replace, using the newly added IFLA_XDP_EXPECTED_FD netlink
parameter. The new function uses the opts struct mechanism to be extendable
in the future.

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/158515700857.92963.7052131201257841700.stgit@toke.dk
tools/lib/bpf/libbpf.h
tools/lib/bpf/libbpf.map
tools/lib/bpf/netlink.c

index d38d7a6294178a21c3d7f008bd94a4ceb47a4198..bf7a35a9556db70160e6ab08cdb17bffc731fd1e 100644 (file)
@@ -444,7 +444,15 @@ struct xdp_link_info {
        __u8 attach_mode;
 };
 
+struct bpf_xdp_set_link_opts {
+       size_t sz;
+       __u32 old_fd;
+};
+#define bpf_xdp_set_link_opts__last_field old_fd
+
 LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
+LIBBPF_API int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags,
+                                       const struct bpf_xdp_set_link_opts *opts);
 LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
 LIBBPF_API int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
                                     size_t info_size, __u32 flags);
index 5129283c0284b7f46000628a43917aabfa108390..dcc87db3ca8adbbb05015f45e565e19a311e1861 100644 (file)
@@ -244,4 +244,5 @@ LIBBPF_0.0.8 {
                bpf_link__pin_path;
                bpf_link__unpin;
                bpf_program__set_attach_target;
+               bpf_set_link_xdp_fd_opts;
 } LIBBPF_0.0.7;
index 431bd25c6cdb5abb036860c972eb348acc2d77a4..18b5319025e1986de84050d55b0e579d44173b48 100644 (file)
@@ -132,7 +132,8 @@ done:
        return ret;
 }
 
-int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
+static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd,
+                                        __u32 flags)
 {
        int sock, seq = 0, ret;
        struct nlattr *nla, *nla_xdp;
@@ -178,6 +179,14 @@ int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
                nla->nla_len += nla_xdp->nla_len;
        }
 
+       if (flags & XDP_FLAGS_REPLACE) {
+               nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
+               nla_xdp->nla_type = IFLA_XDP_EXPECTED_FD;
+               nla_xdp->nla_len = NLA_HDRLEN + sizeof(old_fd);
+               memcpy((char *)nla_xdp + NLA_HDRLEN, &old_fd, sizeof(old_fd));
+               nla->nla_len += nla_xdp->nla_len;
+       }
+
        req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
 
        if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
@@ -191,6 +200,29 @@ cleanup:
        return ret;
 }
 
+int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags,
+                            const struct bpf_xdp_set_link_opts *opts)
+{
+       int old_fd = -1;
+
+       if (!OPTS_VALID(opts, bpf_xdp_set_link_opts))
+               return -EINVAL;
+
+       if (OPTS_HAS(opts, old_fd)) {
+               old_fd = OPTS_GET(opts, old_fd, -1);
+               flags |= XDP_FLAGS_REPLACE;
+       }
+
+       return __bpf_set_link_xdp_fd_replace(ifindex, fd,
+                                            old_fd,
+                                            flags);
+}
+
+int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
+{
+       return __bpf_set_link_xdp_fd_replace(ifindex, fd, 0, flags);
+}
+
 static int __dump_link_nlmsg(struct nlmsghdr *nlh,
                             libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
 {