diff options
| author | Martin KaFai Lau <kafai@fb.com> | 2016-12-07 18:53:14 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-12-08 14:25:13 -0500 |
| commit | 12d8bb64e3f65f5287ff17c084d076a28daa8096 (patch) | |
| tree | e772f55d041956a3e07a487b48b42df8a0b830bf /samples | |
| parent | ea3349a03519dcd4f32d949cd80ab995623dc5ac (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/Makefile | 4 | ||||
| -rw-r--r-- | samples/bpf/bpf_helpers.h | 2 | ||||
| -rw-r--r-- | samples/bpf/bpf_load.c | 94 | ||||
| -rw-r--r-- | samples/bpf/bpf_load.h | 1 | ||||
| -rw-r--r-- | samples/bpf/xdp1_user.c | 93 | ||||
| -rw-r--r-- | samples/bpf/xdp_tx_iptunnel_common.h | 37 | ||||
| -rw-r--r-- | samples/bpf/xdp_tx_iptunnel_kern.c | 236 | ||||
| -rw-r--r-- | samples/bpf/xdp_tx_iptunnel_user.c | 256 |
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 | |||
| 33 | hostprogs-y += sampleip | 33 | hostprogs-y += sampleip |
| 34 | hostprogs-y += tc_l2_redirect | 34 | hostprogs-y += tc_l2_redirect |
| 35 | hostprogs-y += lwt_len_hist | 35 | hostprogs-y += lwt_len_hist |
| 36 | hostprogs-y += xdp_tx_iptunnel | ||
| 36 | 37 | ||
| 37 | test_lru_dist-objs := test_lru_dist.o libbpf.o | 38 | test_lru_dist-objs := test_lru_dist.o libbpf.o |
| 38 | sock_example-objs := sock_example.o libbpf.o | 39 | sock_example-objs := sock_example.o libbpf.o |
| @@ -67,6 +68,7 @@ trace_event-objs := bpf_load.o libbpf.o trace_event_user.o | |||
| 67 | sampleip-objs := bpf_load.o libbpf.o sampleip_user.o | 68 | sampleip-objs := bpf_load.o libbpf.o sampleip_user.o |
| 68 | tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o | 69 | tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o |
| 69 | lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o | 70 | lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o |
| 71 | xdp_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 |
| 72 | always := $(hostprogs-y) | 74 | always := $(hostprogs-y) |
| @@ -99,6 +101,7 @@ always += test_current_task_under_cgroup_kern.o | |||
| 99 | always += trace_event_kern.o | 101 | always += trace_event_kern.o |
| 100 | always += sampleip_kern.o | 102 | always += sampleip_kern.o |
| 101 | always += lwt_len_hist_kern.o | 103 | always += lwt_len_hist_kern.o |
| 104 | always += xdp_tx_iptunnel_kern.o | ||
| 102 | 105 | ||
| 103 | HOSTCFLAGS += -I$(objtree)/usr/include | 106 | HOSTCFLAGS += -I$(objtree)/usr/include |
| 104 | HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/ | 107 | HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/ |
| @@ -129,6 +132,7 @@ HOSTLOADLIBES_trace_event += -lelf | |||
| 129 | HOSTLOADLIBES_sampleip += -lelf | 132 | HOSTLOADLIBES_sampleip += -lelf |
| 130 | HOSTLOADLIBES_tc_l2_redirect += -l elf | 133 | HOSTLOADLIBES_tc_l2_redirect += -l elf |
| 131 | HOSTLOADLIBES_lwt_len_hist += -l elf | 134 | HOSTLOADLIBES_lwt_len_hist += -l elf |
| 135 | HOSTLOADLIBES_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; |
| 58 | static unsigned long long (*bpf_get_prandom_u32)(void) = | 58 | static unsigned long long (*bpf_get_prandom_u32)(void) = |
| 59 | (void *) BPF_FUNC_get_prandom_u32; | 59 | (void *) BPF_FUNC_get_prandom_u32; |
| 60 | static 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 | |||
| 458 | int 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 | |||
| 543 | cleanup: | ||
| 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 | ||
| 32 | int load_kallsyms(void); | 32 | int load_kallsyms(void); |
| 33 | struct ksym *ksym_search(long key); | 33 | struct ksym *ksym_search(long key); |
| 34 | int 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 | ||
