Make xdp samples consistent with iproute2 behavior and set the
XDP_FLAGS_UPDATE_IF_NOEXIST by default when setting the xdp program on
interface. Provide an option for user to force the program loading,
which as a result will not include the mentioned flag in
bpf_set_link_xdp_fd call.

Signed-off-by: Maciej Fijalkowski <maciejromanfijalkow...@gmail.com>
Reviewed-by: Jakub Kicinski <jakub.kicin...@netronome.com>
---
 samples/bpf/xdp1_user.c             | 10 +++++---
 samples/bpf/xdp_adjust_tail_user.c  |  8 ++++--
 samples/bpf/xdp_redirect_cpu_user.c |  8 ++++--
 samples/bpf/xdp_redirect_map_user.c | 10 +++++---
 samples/bpf/xdp_redirect_user.c     | 10 +++++---
 samples/bpf/xdp_router_ipv4_user.c  | 50 +++++++++++++++++++++++++++----------
 samples/bpf/xdp_rxq_info_user.c     |  8 ++++--
 samples/bpf/xdp_sample_pkts_user.c  | 40 +++++++++++++++++++++++------
 samples/bpf/xdp_tx_iptunnel_user.c  |  8 ++++--
 samples/bpf/xdpsock_user.c          |  7 ++++--
 10 files changed, 119 insertions(+), 40 deletions(-)

diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c
index 8bfda95c77ad..505bce207165 100644
--- a/samples/bpf/xdp1_user.c
+++ b/samples/bpf/xdp1_user.c
@@ -22,7 +22,7 @@
 #include "bpf/libbpf.h"
 
 static int ifindex;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 
 static void int_exit(int sig)
 {
@@ -63,7 +63,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,7 +74,7 @@ int main(int argc, char **argv)
        struct bpf_prog_load_attr prog_load_attr = {
                .prog_type      = BPF_PROG_TYPE_XDP,
        };
-       const char *optstr = "SN";
+       const char *optstr = "FSN";
        int prog_fd, map_fd, opt;
        struct bpf_object *obj;
        struct bpf_map *map;
@@ -87,6 +88,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;
diff --git a/samples/bpf/xdp_adjust_tail_user.c 
b/samples/bpf/xdp_adjust_tail_user.c
index 3042ce37dae8..049bddf7778b 100644
--- a/samples/bpf/xdp_adjust_tail_user.c
+++ b/samples/bpf/xdp_adjust_tail_user.c
@@ -24,7 +24,7 @@
 #define STATS_INTERVAL_S 2U
 
 static int ifindex = -1;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 
 static void int_exit(int sig)
 {
@@ -60,6 +60,7 @@ static void usage(const char *cmd)
        printf("    -T <stop-after-X-seconds> Default: 0 (forever)\n");
        printf("    -S use skb-mode\n");
        printf("    -N enforce native mode\n");
+       printf("    -F force loading prog\n");
        printf("    -h Display this help\n");
 }
 
@@ -70,8 +71,8 @@ int main(int argc, char **argv)
                .prog_type      = BPF_PROG_TYPE_XDP,
        };
        unsigned char opt_flags[256] = {};
+       const char *optstr = "i:T:SNFh";
        unsigned int kill_after_s = 0;
-       const char *optstr = "i:T:SNh";
        int i, prog_fd, map_fd, opt;
        struct bpf_object *obj;
        struct bpf_map *map;
@@ -96,6 +97,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(argv[0]);
                        return 1;
diff --git a/samples/bpf/xdp_redirect_cpu_user.c 
b/samples/bpf/xdp_redirect_cpu_user.c
index 1b91e72dd423..8ebe95c8181f 100644
--- a/samples/bpf/xdp_redirect_cpu_user.c
+++ b/samples/bpf/xdp_redirect_cpu_user.c
@@ -33,7 +33,7 @@ static int ifindex = -1;
 static char ifname_buf[IF_NAMESIZE];
 static char *ifname;
 
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static int cpu_map_fd;
 static int rx_cnt_map_fd;
 static int redirect_err_cnt_map_fd;
@@ -62,6 +62,7 @@ static const struct option long_options[] = {
        {"cpu",         required_argument,      NULL, 'c' },
        {"stress-mode", no_argument,            NULL, 'x' },
        {"no-separators", no_argument,          NULL, 'z' },
+       {"force",       no_argument,            NULL, 'F' },
        {0, 0, NULL,  0 }
 };
 
@@ -638,7 +639,7 @@ int main(int argc, char **argv)
        mark_cpus_unavailable();
 
        /* Parse commands line args */
-       while ((opt = getopt_long(argc, argv, "hSd:",
+       while ((opt = getopt_long(argc, argv, "hSd:s:p:q:c:xzF",
                                  long_options, &longindex)) != -1) {
                switch (opt) {
                case 'd':
@@ -693,6 +694,9 @@ int main(int argc, char **argv)
                case 'q':
                        qsize = atoi(optarg);
                        break;
+               case 'F':
+                       xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+                       break;
                case 'h':
                error:
                default:
diff --git a/samples/bpf/xdp_redirect_map_user.c 
b/samples/bpf/xdp_redirect_map_user.c
index 60d46eea225b..470e1a7e8810 100644
--- a/samples/bpf/xdp_redirect_map_user.c
+++ b/samples/bpf/xdp_redirect_map_user.c
@@ -30,7 +30,7 @@ static int ifindex_in;
 static int ifindex_out;
 static bool ifindex_out_xdp_dummy_attached = true;
 
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static int rxcnt_map_fd;
 
 static void int_exit(int sig)
@@ -70,7 +70,8 @@ static void usage(const char *prog)
                "usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\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);
 }
 
@@ -82,7 +83,7 @@ int main(int argc, char **argv)
        };
        struct bpf_program *prog, *dummy_prog;
        int prog_fd, dummy_prog_fd;
-       const char *optstr = "SN";
+       const char *optstr = "FSN";
        struct bpf_object *obj;
        int ret, opt, key = 0;
        char filename[256];
@@ -96,6 +97,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;
diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c
index 93404820df68..be6058cda97c 100644
--- a/samples/bpf/xdp_redirect_user.c
+++ b/samples/bpf/xdp_redirect_user.c
@@ -30,7 +30,7 @@ static int ifindex_in;
 static int ifindex_out;
 static bool ifindex_out_xdp_dummy_attached = true;
 
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static int rxcnt_map_fd;
 
 static void int_exit(int sig)
@@ -70,7 +70,8 @@ static void usage(const char *prog)
                "usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\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);
 }
 
@@ -83,7 +84,7 @@ int main(int argc, char **argv)
        };
        struct bpf_program *prog, *dummy_prog;
        int prog_fd, tx_port_map_fd, opt;
-       const char *optstr = "SN";
+       const char *optstr = "FSN";
        struct bpf_object *obj;
        char filename[256];
        int dummy_prog_fd;
@@ -97,6 +98,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;
diff --git a/samples/bpf/xdp_router_ipv4_user.c 
b/samples/bpf/xdp_router_ipv4_user.c
index c63c6beec7d6..208d6a996478 100644
--- a/samples/bpf/xdp_router_ipv4_user.c
+++ b/samples/bpf/xdp_router_ipv4_user.c
@@ -26,8 +26,9 @@
 #include "bpf_util.h"
 #include "bpf/libbpf.h"
 #include <sys/resource.h>
+#include <libgen.h>
 
-int sock, sock_arp, flags = 0;
+int sock, sock_arp, flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static int total_ifindex;
 int *ifindex_list;
 char buf[8192];
@@ -608,33 +609,56 @@ static int monitor_route(void)
        return ret;
 }
 
+static void usage(const char *prog)
+{
+       fprintf(stderr,
+               "%s: %s [OPTS] interface name list\n\n"
+               "OPTS:\n"
+               "    -S    use skb-mode\n"
+               "    -F    force loading prog\n",
+               __func__, prog);
+}
+
 int main(int ac, char **argv)
 {
        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        struct bpf_prog_load_attr prog_load_attr = {
                .prog_type      = BPF_PROG_TYPE_XDP,
        };
+       const char *optstr = "SF";
        struct bpf_object *obj;
        char filename[256];
        char **ifname_list;
-       int prog_fd;
+       int prog_fd, opt;
        int i = 1;
 
        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
        prog_load_attr.file = filename;
 
-       if (ac < 2) {
-               printf("usage: %s [-S] Interface name list\n", argv[0]);
-               return 1;
+       total_ifindex = ac - 1;
+       ifname_list = (argv + 1);
+
+       while ((opt = getopt(ac, argv, optstr)) != -1) {
+               switch (opt) {
+               case 'S':
+                       flags |= XDP_FLAGS_SKB_MODE;
+                       total_ifindex--;
+                       ifname_list++;
+                       break;
+               case 'F':
+                       flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+                       total_ifindex--;
+                       ifname_list++;
+                       break;
+               default:
+                       usage(basename(argv[0]));
+                       return 1;
+               }
        }
-       if (!strcmp(argv[1], "-S")) {
-               flags = XDP_FLAGS_SKB_MODE;
-               total_ifindex = ac - 2;
-               ifname_list = (argv + 2);
-       } else {
-               flags = 0;
-               total_ifindex = ac - 1;
-               ifname_list = (argv + 1);
+
+       if (optind == ac) {
+               usage(basename(argv[0]));
+               return 1;
        }
 
        if (setrlimit(RLIMIT_MEMLOCK, &r)) {
diff --git a/samples/bpf/xdp_rxq_info_user.c b/samples/bpf/xdp_rxq_info_user.c
index ef26f882f92f..e7a98c2a440f 100644
--- a/samples/bpf/xdp_rxq_info_user.c
+++ b/samples/bpf/xdp_rxq_info_user.c
@@ -30,7 +30,7 @@ static int ifindex = -1;
 static char ifname_buf[IF_NAMESIZE];
 static char *ifname;
 
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 
 static struct bpf_map *stats_global_map;
 static struct bpf_map *rx_queue_index_map;
@@ -52,6 +52,7 @@ static const struct option long_options[] = {
        {"action",      required_argument,      NULL, 'a' },
        {"readmem",     no_argument,            NULL, 'r' },
        {"swapmac",     no_argument,            NULL, 'm' },
+       {"force",       no_argument,            NULL, 'F' },
        {0, 0, NULL,  0 }
 };
 
@@ -487,7 +488,7 @@ int main(int argc, char **argv)
        }
 
        /* Parse commands line args */
-       while ((opt = getopt_long(argc, argv, "hSd:",
+       while ((opt = getopt_long(argc, argv, "FhSrmzd:s:a:",
                                  long_options, &longindex)) != -1) {
                switch (opt) {
                case 'd':
@@ -524,6 +525,9 @@ int main(int argc, char **argv)
                case 'm':
                        cfg_options |= SWAP_MAC;
                        break;
+               case 'F':
+                       xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+                       break;
                case 'h':
                error:
                default:
diff --git a/samples/bpf/xdp_sample_pkts_user.c 
b/samples/bpf/xdp_sample_pkts_user.c
index 5f5828ee0761..362ad35b524d 100644
--- a/samples/bpf/xdp_sample_pkts_user.c
+++ b/samples/bpf/xdp_sample_pkts_user.c
@@ -13,6 +13,8 @@
 #include <libbpf.h>
 #include <bpf/bpf.h>
 #include <sys/resource.h>
+#include <libgen.h>
+#include <linux/if_link.h>
 
 #include "perf-sys.h"
 #include "trace_helpers.h"
@@ -21,12 +23,13 @@
 static int pmu_fds[MAX_CPUS], if_idx;
 static struct perf_event_mmap_page *headers[MAX_CPUS];
 static char *if_name;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 
 static int do_attach(int idx, int fd, const char *name)
 {
        int err;
 
-       err = bpf_set_link_xdp_fd(idx, fd, 0);
+       err = bpf_set_link_xdp_fd(idx, fd, xdp_flags);
        if (err < 0)
                printf("ERROR: failed to attach program to %s\n", name);
 
@@ -98,21 +101,42 @@ static void sig_handler(int signo)
        exit(0);
 }
 
+static void usage(const char *prog)
+{
+       fprintf(stderr,
+               "%s: %s [OPTS] IFINDEX\n\n"
+               "OPTS:\n"
+               "    -F    force loading prog\n",
+               __func__, prog);
+}
+
 int main(int argc, char **argv)
 {
        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        struct bpf_prog_load_attr prog_load_attr = {
                .prog_type      = BPF_PROG_TYPE_XDP,
        };
+       const char *optstr = "F";
+       int prog_fd, map_fd, opt;
        struct bpf_object *obj;
        struct bpf_map *map;
-       int prog_fd, map_fd;
        char filename[256];
        int ret, err, i;
        int numcpus;
 
-       if (argc < 2) {
-               printf("Usage: %s <ifname>\n", argv[0]);
+       while ((opt = getopt(argc, argv, optstr)) != -1) {
+               switch (opt) {
+               case 'F':
+                       xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+                       break;
+               default:
+                       usage(basename(argv[0]));
+                       return 1;
+               }
+       }
+
+       if (optind == argc) {
+               usage(basename(argv[0]));
                return 1;
        }
 
@@ -143,16 +167,16 @@ int main(int argc, char **argv)
        }
        map_fd = bpf_map__fd(map);
 
-       if_idx = if_nametoindex(argv[1]);
+       if_idx = if_nametoindex(argv[optind]);
        if (!if_idx)
-               if_idx = strtoul(argv[1], NULL, 0);
+               if_idx = strtoul(argv[optind], NULL, 0);
 
        if (!if_idx) {
                fprintf(stderr, "Invalid ifname\n");
                return 1;
        }
-       if_name = argv[1];
-       err = do_attach(if_idx, prog_fd, argv[1]);
+       if_name = argv[optind];
+       err = do_attach(if_idx, prog_fd, if_name);
        if (err)
                return err;
 
diff --git a/samples/bpf/xdp_tx_iptunnel_user.c 
b/samples/bpf/xdp_tx_iptunnel_user.c
index 5093d8220da5..e3de60930d27 100644
--- a/samples/bpf/xdp_tx_iptunnel_user.c
+++ b/samples/bpf/xdp_tx_iptunnel_user.c
@@ -25,7 +25,7 @@
 #define STATS_INTERVAL_S 2U
 
 static int ifindex = -1;
-static __u32 xdp_flags = 0;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static int rxcnt_map_fd;
 
 static void int_exit(int sig)
@@ -83,6 +83,7 @@ static void usage(const char *cmd)
        printf("    -P <IP-Protocol> Default is TCP\n");
        printf("    -S use skb-mode\n");
        printf("    -N enforce native mode\n");
+       printf("    -F Force loading the XDP prog\n");
        printf("    -h Display this help\n");
 }
 
@@ -145,7 +146,7 @@ int main(int argc, char **argv)
        };
        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        int min_port = 0, max_port = 0, vip2tnl_map_fd;
-       const char *optstr = "i:a:p:s:d:m:T:P:SNh";
+       const char *optstr = "i:a:p:s:d:m:T:P:FSNh";
        unsigned char opt_flags[256] = {};
        unsigned int kill_after_s = 0;
        struct iptnl_info tnl = {};
@@ -217,6 +218,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(argv[0]);
                        return 1;
diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c
index 57ecadc58403..188723784768 100644
--- a/samples/bpf/xdpsock_user.c
+++ b/samples/bpf/xdpsock_user.c
@@ -68,7 +68,7 @@ enum benchmark_type {
 };
 
 static enum benchmark_type opt_bench = BENCH_RXDROP;
-static u32 opt_xdp_flags;
+static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static const char *opt_if = "";
 static int opt_ifindex;
 static int opt_queue;
@@ -682,7 +682,7 @@ static void parse_command_line(int argc, char **argv)
        opterr = 0;
 
        for (;;) {
-               c = getopt_long(argc, argv, "rtli:q:psSNn:cz", long_options,
+               c = getopt_long(argc, argv, "Frtli:q:psSNn:cz", long_options,
                                &option_index);
                if (c == -1)
                        break;
@@ -725,6 +725,9 @@ static void parse_command_line(int argc, char **argv)
                case 'c':
                        opt_xdp_bind_flags |= XDP_COPY;
                        break;
+               case 'F':
+                       opt_xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+                       break;
                default:
                        usage(basename(argv[0]));
                }
-- 
2.16.1

Reply via email to