aboutsummaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
authorMartin KaFai Lau <kafai@fb.com>2016-12-07 18:53:14 -0500
committerDavid S. Miller <davem@davemloft.net>2016-12-08 14:25:13 -0500
commit12d8bb64e3f65f5287ff17c084d076a28daa8096 (patch)
treee772f55d041956a3e07a487b48b42df8a0b830bf /samples
parentea3349a03519dcd4f32d949cd80ab995623dc5ac (diff)
bpf: xdp: Add XDP example for head adjustment
The XDP prog checks if the incoming packet matches any VIP:PORT combination in the BPF hashmap. If it is, it will encapsulate the packet with a IPv4/v6 header as instructed by the value of the BPF hashmap and then XDP_TX it out. The VIP:PORT -> IP-Encap-Info can be specified by the cmd args of the user prog. Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples')
-rw-r--r--samples/bpf/Makefile4
-rw-r--r--samples/bpf/bpf_helpers.h2
-rw-r--r--samples/bpf/bpf_load.c94
-rw-r--r--samples/bpf/bpf_load.h1
-rw-r--r--samples/bpf/xdp1_user.c93
-rw-r--r--samples/bpf/xdp_tx_iptunnel_common.h37
-rw-r--r--samples/bpf/xdp_tx_iptunnel_kern.c236
-rw-r--r--samples/bpf/xdp_tx_iptunnel_user.c256
8 files changed, 630 insertions, 93 deletions
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 00cd3081c038..f2219c1489e5 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -33,6 +33,7 @@ hostprogs-y += trace_event
33hostprogs-y += sampleip 33hostprogs-y += sampleip
34hostprogs-y += tc_l2_redirect 34hostprogs-y += tc_l2_redirect
35hostprogs-y += lwt_len_hist 35hostprogs-y += lwt_len_hist
36hostprogs-y += xdp_tx_iptunnel
36 37
37test_lru_dist-objs := test_lru_dist.o libbpf.o 38test_lru_dist-objs := test_lru_dist.o libbpf.o
38sock_example-objs := sock_example.o libbpf.o 39sock_example-objs := sock_example.o libbpf.o
@@ -67,6 +68,7 @@ trace_event-objs := bpf_load.o libbpf.o trace_event_user.o
67sampleip-objs := bpf_load.o libbpf.o sampleip_user.o 68sampleip-objs := bpf_load.o libbpf.o sampleip_user.o
68tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o 69tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o
69lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o 70lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o
71xdp_tx_iptunnel-objs := bpf_load.o libbpf.o xdp_tx_iptunnel_user.o
70 72
71# Tell kbuild to always build the programs 73# Tell kbuild to always build the programs
72always := $(hostprogs-y) 74always := $(hostprogs-y)
@@ -99,6 +101,7 @@ always += test_current_task_under_cgroup_kern.o
99always += trace_event_kern.o 101always += trace_event_kern.o
100always += sampleip_kern.o 102always += sampleip_kern.o
101always += lwt_len_hist_kern.o 103always += lwt_len_hist_kern.o
104always += xdp_tx_iptunnel_kern.o
102 105
103HOSTCFLAGS += -I$(objtree)/usr/include 106HOSTCFLAGS += -I$(objtree)/usr/include
104HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/ 107HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
@@ -129,6 +132,7 @@ HOSTLOADLIBES_trace_event += -lelf
129HOSTLOADLIBES_sampleip += -lelf 132HOSTLOADLIBES_sampleip += -lelf
130HOSTLOADLIBES_tc_l2_redirect += -l elf 133HOSTLOADLIBES_tc_l2_redirect += -l elf
131HOSTLOADLIBES_lwt_len_hist += -l elf 134HOSTLOADLIBES_lwt_len_hist += -l elf
135HOSTLOADLIBES_xdp_tx_iptunnel += -lelf
132 136
133# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: 137# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
134# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang 138# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h
index 8370a6e3839d..faaffe2e139a 100644
--- a/samples/bpf/bpf_helpers.h
+++ b/samples/bpf/bpf_helpers.h
@@ -57,6 +57,8 @@ static int (*bpf_skb_set_tunnel_opt)(void *ctx, void *md, int size) =
57 (void *) BPF_FUNC_skb_set_tunnel_opt; 57 (void *) BPF_FUNC_skb_set_tunnel_opt;
58static unsigned long long (*bpf_get_prandom_u32)(void) = 58static unsigned long long (*bpf_get_prandom_u32)(void) =
59 (void *) BPF_FUNC_get_prandom_u32; 59 (void *) BPF_FUNC_get_prandom_u32;
60static int (*bpf_xdp_adjust_head)(void *ctx, int offset) =
61 (void *) BPF_FUNC_xdp_adjust_head;
60 62
61/* llvm builtin functions that eBPF C program may use to 63/* llvm builtin functions that eBPF C program may use to
62 * emit BPF_LD_ABS and BPF_LD_IND instructions 64 * emit BPF_LD_ABS and BPF_LD_IND instructions
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 49b45ccbe153..e30b6de94f2e 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -12,6 +12,10 @@
12#include <linux/bpf.h> 12#include <linux/bpf.h>
13#include <linux/filter.h> 13#include <linux/filter.h>
14#include <linux/perf_event.h> 14#include <linux/perf_event.h>
15#include <linux/netlink.h>
16#include <linux/rtnetlink.h>
17#include <sys/types.h>
18#include <sys/socket.h>
15#include <sys/syscall.h> 19#include <sys/syscall.h>
16#include <sys/ioctl.h> 20#include <sys/ioctl.h>
17#include <sys/mman.h> 21#include <sys/mman.h>
@@ -450,3 +454,93 @@ struct ksym *ksym_search(long key)
450 /* out of range. return _stext */ 454 /* out of range. return _stext */
451 return &syms[0]; 455 return &syms[0];
452} 456}
457
458int set_link_xdp_fd(int ifindex, int fd)
459{
460 struct sockaddr_nl sa;
461 int sock, seq = 0, len, ret = -1;
462 char buf[4096];
463 struct nlattr *nla, *nla_xdp;
464 struct {
465 struct nlmsghdr nh;
466 struct ifinfomsg ifinfo;
467 char attrbuf[64];
468 } req;
469 struct nlmsghdr *nh;
470 struct nlmsgerr *err;
471
472 memset(&sa, 0, sizeof(sa));
473 sa.nl_family = AF_NETLINK;
474
475 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
476 if (sock < 0) {
477 printf("open netlink socket: %s\n", strerror(errno));
478 return -1;
479 }
480
481 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
482 printf("bind to netlink: %s\n", strerror(errno));
483 goto cleanup;
484 }
485
486 memset(&req, 0, sizeof(req));
487 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
488 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
489 req.nh.nlmsg_type = RTM_SETLINK;
490 req.nh.nlmsg_pid = 0;
491 req.nh.nlmsg_seq = ++seq;
492 req.ifinfo.ifi_family = AF_UNSPEC;
493 req.ifinfo.ifi_index = ifindex;
494 nla = (struct nlattr *)(((char *)&req)
495 + NLMSG_ALIGN(req.nh.nlmsg_len));
496 nla->nla_type = NLA_F_NESTED | 43/*IFLA_XDP*/;
497
498 nla_xdp = (struct nlattr *)((char *)nla + NLA_HDRLEN);
499 nla_xdp->nla_type = 1/*IFLA_XDP_FD*/;
500 nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
501 memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
502 nla->nla_len = NLA_HDRLEN + nla_xdp->nla_len;
503
504 req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
505
506 if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
507 printf("send to netlink: %s\n", strerror(errno));
508 goto cleanup;
509 }
510
511 len = recv(sock, buf, sizeof(buf), 0);
512 if (len < 0) {
513 printf("recv from netlink: %s\n", strerror(errno));
514 goto cleanup;
515 }
516
517 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
518 nh = NLMSG_NEXT(nh, len)) {
519 if (nh->nlmsg_pid != getpid()) {
520 printf("Wrong pid %d, expected %d\n",
521 nh->nlmsg_pid, getpid());
522 goto cleanup;
523 }
524 if (nh->nlmsg_seq != seq) {
525 printf("Wrong seq %d, expected %d\n",
526 nh->nlmsg_seq, seq);
527 goto cleanup;
528 }
529 switch (nh->nlmsg_type) {
530 case NLMSG_ERROR:
531 err = (struct nlmsgerr *)NLMSG_DATA(nh);
532 if (!err->error)
533 continue;
534 printf("nlmsg error %s\n", strerror(-err->error));
535 goto cleanup;
536 case NLMSG_DONE:
537 break;
538 }
539 }
540
541 ret = 0;
542
543cleanup:
544 close(sock);
545 return ret;
546}
diff --git a/samples/bpf/bpf_load.h b/samples/bpf/bpf_load.h
index 4adeeef53ad6..fb46a421ab41 100644
--- a/samples/bpf/bpf_load.h
+++ b/samples/bpf/bpf_load.h
@@ -31,4 +31,5 @@ struct ksym {
31 31
32int load_kallsyms(void); 32int load_kallsyms(void);
33struct ksym *ksym_search(long key); 33struct ksym *ksym_search(long key);
34int set_link_xdp_fd(int ifindex, int fd);
34#endif 35#endif
diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c
index 2b2150d6d6f7..5f040a0d7712 100644
--- a/samples/bpf/xdp1_user.c
+++ b/samples/bpf/xdp1_user.c
@@ -5,111 +5,18 @@
5 * License as published by the Free Software Foundation. 5 * License as published by the Free Software Foundation.
6 */ 6 */
7#include <linux/bpf.h> 7#include <linux/bpf.h>
8#include <linux/netlink.h>
9#include <linux/rtnetlink.h>
10#include <assert.h> 8#include <assert.h>
11#include <errno.h> 9#include <errno.h>
12#include <signal.h> 10#include <signal.h>
13#include <stdio.h> 11#include <stdio.h>
14#include <stdlib.h> 12#include <stdlib.h>
15#include <string.h> 13#include <string.h>
16#include <sys/socket.h>
17#include <unistd.h> 14#include <unistd.h>
18 15