Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatchin...
[sfrench/cifs-2.6.git] / samples / bpf / xdp1_user.c
index 8bfda95c77ad77ade1bc2b553d8940f3da0f60a8..6a64e93365e1021411224d3e41937f8e47c0ae22 100644 (file)
 #include "bpf/libbpf.h"
 
 static int ifindex;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
+static __u32 prog_id;
 
 static void int_exit(int sig)
 {
-       bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+       __u32 curr_prog_id = 0;
+
+       if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
+               printf("bpf_get_link_xdp_id failed\n");
+               exit(1);
+       }
+       if (prog_id == curr_prog_id)
+               bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+       else if (!curr_prog_id)
+               printf("couldn't find a prog id on a given interface\n");
+       else
+               printf("program on interface changed, not removing\n");
        exit(0);
 }
 
@@ -63,7 +75,8 @@ static void usage(const char *prog)
                "usage: %s [OPTS] IFACE\n\n"
                "OPTS:\n"
                "    -S    use skb-mode\n"
-               "    -N    enforce native mode\n",
+               "    -N    enforce native mode\n"
+               "    -F    force loading prog\n",
                prog);
 }
 
@@ -73,11 +86,14 @@ int main(int argc, char **argv)
        struct bpf_prog_load_attr prog_load_attr = {
                .prog_type      = BPF_PROG_TYPE_XDP,
        };
-       const char *optstr = "SN";
+       struct bpf_prog_info info = {};
+       __u32 info_len = sizeof(info);
+       const char *optstr = "FSN";
        int prog_fd, map_fd, opt;
        struct bpf_object *obj;
        struct bpf_map *map;
        char filename[256];
+       int err;
 
        while ((opt = getopt(argc, argv, optstr)) != -1) {
                switch (opt) {
@@ -87,6 +103,9 @@ int main(int argc, char **argv)
                case 'N':
                        xdp_flags |= XDP_FLAGS_DRV_MODE;
                        break;
+               case 'F':
+                       xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+                       break;
                default:
                        usage(basename(argv[0]));
                        return 1;
@@ -135,6 +154,13 @@ int main(int argc, char **argv)
                return 1;
        }
 
+       err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+       if (err) {
+               printf("can't get prog info - %s\n", strerror(errno));
+               return err;
+       }
+       prog_id = info.id;
+
        poll_stats(map_fd, 2);
 
        return 0;