History

Merge tag 'bpf-next-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Pull bpf updates from Alexei Starovoitov: - Add BPF uprobe session support (Jiri Olsa) - Optimize uprobe performance (Andrii Nakryiko) - Add bpf_fastcall support to helpers and kfuncs (Eduard Zingerman) - Avoid calling free_htab_elem() under hash map bucket lock (Hou Tao) - Prevent tailcall infinite loop caused by freplace (Leon Hwang) - Mark raw_tracepoint arguments as nullable (Kumar Kartikeya Dwivedi) - Introduce uptr support in the task local storage map (Martin KaFai Lau) - Stringify errno log messages in libbpf (Mykyta Yatsenko) - Add kmem_cache BPF iterator for perf's lock profiling (Namhyung Kim) - Support BPF objects of either endianness in libbpf (Tony Ambardar) - Add ksym to struct_ops trampoline to fix stack trace (Xu Kuohai) - Introduce private stack for eligible BPF programs (Yonghong Song) - Migrate samples/bpf tests to selftests/bpf test_progs (Daniel T. Lee) - Migrate test_sock to selftests/bpf test_progs (Jordan Rife) * tag 'bpf-next-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (152 commits) libbpf: Change hash_combine parameters from long to unsigned long selftests/bpf: Fix build error with llvm 19 libbpf: Fix memory leak in bpf_program__attach_uprobe_multi bpf: use common instruction history across all states bpf: Add necessary migrate_disable to range_tree. bpf: Do not alloc arena on unsupported arches selftests/bpf: Set test path for token/obj_priv_implicit_token_envvar selftests/bpf: Add a test for arena range tree algorithm bpf: Introduce range_tree data structure and use it in bpf arena samples/bpf: Remove unused variable in xdp2skb_meta_kern.c samples/bpf: Remove unused variables in tc_l2_redirect_kern.c bpftool: Cast variable `var` to long long bpf, x86: Propagate tailcall info only for subprogs bpf: Add kernel symbol for struct_ops trampoline bpf: Use function pointers count as struct_ops links count bpf: Remove unused member rcu from bpf_struct_ops_map selftests/bpf: Add struct_ops prog private stack tests bpf: Support private stack for struct_ops progs selftests/bpf: Add tracing prog private stack tests bpf, x86: Support private stack in jit ...

Linus Torvalds committed 1 year ago

Commit 6e95ef02 parents 43fb83c 2c8b09a211 files · +6961 −3473Browse files

Showing the changes to samples (25 of 211 files). Show all

Unified · Split

25 files
  1. samples/bpf/Makefile +0 −25
  2. samples/bpf/sock_flags.bpf.c +0 −47
  3. samples/bpf/syscall_nrs.c +5 −0
  4. samples/bpf/tc_l2_redirect_kern.c +0 −6
  5. samples/bpf/test_cgrp2_array_pin.c +0 −106
  6. samples/bpf/test_cgrp2_attach.c +0 −177
  7. samples/bpf/test_cgrp2_sock.c +0 −294
  8. samples/bpf/test_cgrp2_sock.sh +0 −137
  9. samples/bpf/test_cgrp2_sock2.c +0 −95
  10. samples/bpf/test_cgrp2_sock2.sh +0 −103
  11. samples/bpf/test_cgrp2_tc.bpf.c +0 −56
  12. samples/bpf/test_cgrp2_tc.sh +0 −187
  13. samples/bpf/test_current_task_under_cgroup.bpf.c +0 −43
  14. samples/bpf/test_current_task_under_cgroup_user.c +0 −115
  15. samples/bpf/test_overhead_kprobe.bpf.c +0 −41
  16. samples/bpf/test_overhead_raw_tp.bpf.c +0 −17
  17. samples/bpf/test_overhead_tp.bpf.c +0 −23
  18. samples/bpf/test_overhead_user.c +0 −225
  19. samples/bpf/test_override_return.sh +0 −16
  20. samples/bpf/test_probe_write_user.bpf.c +0 −52
  21. samples/bpf/test_probe_write_user_user.c +0 −108
  22. samples/bpf/tracex7.bpf.c +0 −15
  23. samples/bpf/tracex7_user.c +0 −56
  24. samples/bpf/xdp2skb_meta_kern.c +1 −1
  25. samples/bpf/xdp_adjust_tail_kern.c +1 −0
samples/bpf/Makefile+0−25
@@ -17,20 +17,12 @@ tprogs-y += tracex3 · 16 unmodified lines
17tprogs-y += tracex417tprogs-y += tracex4
18tprogs-y += tracex518tprogs-y += tracex5
19tprogs-y += tracex619tprogs-y += tracex6
20tprogs-y += tracex7
21tprogs-y += test_probe_write_user
22tprogs-y += trace_output20tprogs-y += trace_output
23tprogs-y += lathist21tprogs-y += lathist
24tprogs-y += offwaketime22tprogs-y += offwaketime
25tprogs-y += spintest23tprogs-y += spintest
26tprogs-y += map_perf_test24tprogs-y += map_perf_test
27tprogs-y += test_overhead
28tprogs-y += test_cgrp2_array_pin
29tprogs-y += test_cgrp2_attach
30tprogs-y += test_cgrp2_sock
31tprogs-y += test_cgrp2_sock2
32tprogs-y += xdp_router_ipv425tprogs-y += xdp_router_ipv4
33tprogs-y += test_current_task_under_cgroup
34tprogs-y += trace_event26tprogs-y += trace_event
35tprogs-y += sampleip27tprogs-y += sampleip
36tprogs-y += tc_l2_redirect28tprogs-y += tc_l2_redirect
@@ -66,20 +58,12 @@ tracex3-objs := tracex3_user.o · 29 unmodified lines
66tracex4-objs := tracex4_user.o58tracex4-objs := tracex4_user.o
67tracex5-objs := tracex5_user.o $(TRACE_HELPERS)59tracex5-objs := tracex5_user.o $(TRACE_HELPERS)
68tracex6-objs := tracex6_user.o60tracex6-objs := tracex6_user.o
69tracex7-objs := tracex7_user.o
70test_probe_write_user-objs := test_probe_write_user_user.o
71trace_output-objs := trace_output_user.o61trace_output-objs := trace_output_user.o
72lathist-objs := lathist_user.o62lathist-objs := lathist_user.o
73offwaketime-objs := offwaketime_user.o $(TRACE_HELPERS)63offwaketime-objs := offwaketime_user.o $(TRACE_HELPERS)
74spintest-objs := spintest_user.o $(TRACE_HELPERS)64spintest-objs := spintest_user.o $(TRACE_HELPERS)
75map_perf_test-objs := map_perf_test_user.o65map_perf_test-objs := map_perf_test_user.o
76test_overhead-objs := test_overhead_user.o66test_overhead-objs := test_overhead_user.o
77test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o
78test_cgrp2_attach-objs := test_cgrp2_attach.o
79test_cgrp2_sock-objs := test_cgrp2_sock.o
80test_cgrp2_sock2-objs := test_cgrp2_sock2.o
81test_current_task_under_cgroup-objs := $(CGROUP_HELPERS) \
82 test_current_task_under_cgroup_user.o
83trace_event-objs := trace_event_user.o $(TRACE_HELPERS)67trace_event-objs := trace_event_user.o $(TRACE_HELPERS)
84sampleip-objs := sampleip_user.o $(TRACE_HELPERS)68sampleip-objs := sampleip_user.o $(TRACE_HELPERS)
85tc_l2_redirect-objs := tc_l2_redirect_user.o69tc_l2_redirect-objs := tc_l2_redirect_user.o
@@ -107,9 +91,6 @@ always-y += tracex3.bpf.o · 21 unmodified lines
107always-y += tracex4.bpf.o91always-y += tracex4.bpf.o
108always-y += tracex5.bpf.o92always-y += tracex5.bpf.o
109always-y += tracex6.bpf.o93always-y += tracex6.bpf.o
110always-y += tracex7.bpf.o
111always-y += sock_flags.bpf.o
112always-y += test_probe_write_user.bpf.o
113always-y += trace_output.bpf.o94always-y += trace_output.bpf.o
114always-y += tcbpf1_kern.o95always-y += tcbpf1_kern.o
115always-y += tc_l2_redirect_kern.o96always-y += tc_l2_redirect_kern.o
@@ -117,12 +98,7 @@ always-y += lathist_kern.o · 1 unmodified line
117always-y += offwaketime.bpf.o98always-y += offwaketime.bpf.o
118always-y += spintest.bpf.o99always-y += spintest.bpf.o
119always-y += map_perf_test.bpf.o100always-y += map_perf_test.bpf.o
120always-y += test_overhead_tp.bpf.o
121always-y += test_overhead_raw_tp.bpf.o
122always-y += test_overhead_kprobe.bpf.o
123always-y += parse_varlen.o parse_simple.o parse_ldabs.o101always-y += parse_varlen.o parse_simple.o parse_ldabs.o
124always-y += test_cgrp2_tc.bpf.o
125always-y += test_current_task_under_cgroup.bpf.o
126always-y += trace_event_kern.o102always-y += trace_event_kern.o
127always-y += sampleip_kern.o103always-y += sampleip_kern.o
128always-y += lwt_len_hist.bpf.o104always-y += lwt_len_hist.bpf.o
@@ -195,7 +171,6 @@ TPROGLDLIBS_xdp_router_ipv4 += -lm -pthread · 66 unmodified lines
195TPROGLDLIBS_tracex4 += -lrt171TPROGLDLIBS_tracex4 += -lrt
196TPROGLDLIBS_trace_output += -lrt172TPROGLDLIBS_trace_output += -lrt
197TPROGLDLIBS_map_perf_test += -lrt173TPROGLDLIBS_map_perf_test += -lrt
198TPROGLDLIBS_test_overhead += -lrt
199 174
200# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:175# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
201# make M=samples/bpf LLC=~/git/llvm-project/llvm/build/bin/llc CLANG=~/git/llvm-project/llvm/build/bin/clang176# make M=samples/bpf LLC=~/git/llvm-project/llvm/build/bin/llc CLANG=~/git/llvm-project/llvm/build/bin/clang
samples/bpf/sock_flags.bpf.c+0−47
@@ -1,47 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2#include "vmlinux.h"
3#include "net_shared.h"
4#include <bpf/bpf_helpers.h>
5
6SEC("cgroup/sock")
7int bpf_prog1(struct bpf_sock *sk)
8{
9 char fmt[] = "socket: family %d type %d protocol %d\n";
10 char fmt2[] = "socket: uid %u gid %u\n";
11 __u64 gid_uid = bpf_get_current_uid_gid();
12 __u32 uid = gid_uid & 0xffffffff;
13 __u32 gid = gid_uid >> 32;
14
15 bpf_trace_printk(fmt, sizeof(fmt), sk->family, sk->type, sk->protocol);
16 bpf_trace_printk(fmt2, sizeof(fmt2), uid, gid);
17
18 /* block AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6 sockets
19 * ie., make ping6 fail
20 */
21 if (sk->family == AF_INET6 &&
22 sk->type == SOCK_DGRAM &&
23 sk->protocol == IPPROTO_ICMPV6)
24 return 0;
25
26 return 1;
27}
28
29SEC("cgroup/sock")
30int bpf_prog2(struct bpf_sock *sk)
31{
32 char fmt[] = "socket: family %d type %d protocol %d\n";
33
34 bpf_trace_printk(fmt, sizeof(fmt), sk->family, sk->type, sk->protocol);
35
36 /* block AF_INET, SOCK_DGRAM, IPPROTO_ICMP sockets
37 * ie., make ping fail
38 */
39 if (sk->family == AF_INET &&
40 sk->type == SOCK_DGRAM &&
41 sk->protocol == IPPROTO_ICMP)
42 return 0;
43
44 return 1;
45}
46
47char _license[] SEC("license") = "GPL";
samples/bpf/syscall_nrs.c+5−0
@@ -2,6 +2,9 @@ · 1 unmodified line
2#include <uapi/linux/unistd.h>2#include <uapi/linux/unistd.h>
3#include <linux/kbuild.h>3#include <linux/kbuild.h>
4 4
5#pragma GCC diagnostic push
6#pragma GCC diagnostic ignored "-Wmissing-prototypes"
7
5#define SYSNR(_NR) DEFINE(SYS ## _NR, _NR)8#define SYSNR(_NR) DEFINE(SYS ## _NR, _NR)
6 9
7void syscall_defines(void)10void syscall_defines(void)
@@ -17,3 +20,5 @@ void syscall_defines(void) · 9 unmodified lines
17#endif20#endif
18 21
19}22}
23
24#pragma GCC diagnostic pop
samples/bpf/tc_l2_redirect_kern.c+0−6
@@ -58,14 +58,11 @@ static __always_inline bool is_vip_addr(__be16 eth_proto, __be32 daddr) · 57 unmodified lines
58SEC("l2_to_iptun_ingress_forward")58SEC("l2_to_iptun_ingress_forward")
59int _l2_to_iptun_ingress_forward(struct __sk_buff *skb)59int _l2_to_iptun_ingress_forward(struct __sk_buff *skb)
60{60{
61 struct bpf_tunnel_key tkey = {};
62 void *data = (void *)(long)skb->data;61 void *data = (void *)(long)skb->data;
63 struct eth_hdr *eth = data;62 struct eth_hdr *eth = data;
64 void *data_end = (void *)(long)skb->data_end;63 void *data_end = (void *)(long)skb->data_end;
65 int key = 0, *ifindex;64 int key = 0, *ifindex;
66 65
67 int ret;
68
69 if (data + sizeof(*eth) > data_end)66 if (data + sizeof(*eth) > data_end)
70 return TC_ACT_OK;67 return TC_ACT_OK;
71 68
@@ -115,8 +112,6 @@ int _l2_to_iptun_ingress_redirect(struct __sk_buff *skb) · 43 unmodified lines
115 void *data_end = (void *)(long)skb->data_end;112 void *data_end = (void *)(long)skb->data_end;
116 int key = 0, *ifindex;113 int key = 0, *ifindex;
117 114
118 int ret;
119
120 if (data + sizeof(*eth) > data_end)115 if (data + sizeof(*eth) > data_end)
121 return TC_ACT_OK;116 return TC_ACT_OK;
122 117
@@ -205,7 +200,6 @@ int _l2_to_ip6tun_ingress_redirect(struct __sk_buff *skb) · 82 unmodified lines
205SEC("drop_non_tun_vip")200SEC("drop_non_tun_vip")
206int _drop_non_tun_vip(struct __sk_buff *skb)201int _drop_non_tun_vip(struct __sk_buff *skb)
207{202{
208 struct bpf_tunnel_key tkey = {};
209 void *data = (void *)(long)skb->data;203 void *data = (void *)(long)skb->data;
210 struct eth_hdr *eth = data;204 struct eth_hdr *eth = data;
211 void *data_end = (void *)(long)skb->data_end;205 void *data_end = (void *)(long)skb->data_end;
samples/bpf/test_cgrp2_array_pin.c+0−106
@@ -1,106 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2016 Facebook
3 */
4#include <linux/unistd.h>
5#include <linux/bpf.h>
6
7#include <stdio.h>
8#include <stdint.h>
9#include <unistd.h>
10#include <string.h>
11#include <errno.h>
12#include <fcntl.h>
13
14#include <bpf/bpf.h>
15
16static void usage(void)
17{
18 printf("Usage: test_cgrp2_array_pin [...]\n");
19 printf(" -F <file> File to pin an BPF cgroup array\n");
20 printf(" -U <file> Update an already pinned BPF cgroup array\n");
21 printf(" -v <value> Full path of the cgroup2\n");
22 printf(" -h Display this help\n");
23}
24
25int main(int argc, char **argv)
26{
27 const char *pinned_file = NULL, *cg2 = NULL;
28 int create_array = 1;
29 int array_key = 0;
30 int array_fd = -1;
31 int cg2_fd = -1;
32 int ret = -1;
33 int opt;
34
35 while ((opt = getopt(argc, argv, "F:U:v:")) != -1) {
36 switch (opt) {
37 /* General args */
38 case 'F':
39 pinned_file = optarg;
40 break;
41 case 'U':
42 pinned_file = optarg;
43 create_array = 0;
44 break;
45 case 'v':
46 cg2 = optarg;
47 break;
48 default:
49 usage();
50 goto out;
51 }
52 }
53
54 if (!cg2 || !pinned_file) {
55 usage();
56 goto out;
57 }
58
59 cg2_fd = open(cg2, O_RDONLY);
60 if (cg2_fd < 0) {
61 fprintf(stderr, "open(%s,...): %s(%d)\n",
62 cg2, strerror(errno), errno);
63 goto out;
64 }
65
66 if (create_array) {
67 array_fd = bpf_map_create(BPF_MAP_TYPE_CGROUP_ARRAY, NULL,
68 sizeof(uint32_t), sizeof(uint32_t),
69 1, NULL);
70 if (array_fd < 0) {
71 fprintf(stderr,
72 "bpf_create_map(BPF_MAP_TYPE_CGROUP_ARRAY,...): %s(%d)\n",
73 strerror(errno), errno);
74 goto out;
75 }
76 } else {
77 array_fd = bpf_obj_get(pinned_file);
78 if (array_fd < 0) {
79 fprintf(stderr, "bpf_obj_get(%s): %s(%d)\n",
80 pinned_file, strerror(errno), errno);
81 goto out;
82 }
83 }
84
85 ret = bpf_map_update_elem(array_fd, &array_key, &cg2_fd, 0);
86 if (ret) {
87 perror("bpf_map_update_elem");
88 goto out;
89 }
90
91 if (create_array) {
92 ret = bpf_obj_pin(array_fd, pinned_file);
93 if (ret) {
94 fprintf(stderr, "bpf_obj_pin(..., %s): %s(%d)\n",
95 pinned_file, strerror(errno), errno);
96 goto out;
97 }
98 }
99
100out:
101 if (array_fd != -1)
102 close(array_fd);
103 if (cg2_fd != -1)
104 close(cg2_fd);
105 return ret;
106}
samples/bpf/test_cgrp2_attach.c+0−177
@@ -1,177 +0,0 @@
1/* eBPF example program:
2 *
3 * - Creates arraymap in kernel with 4 bytes keys and 8 byte values
4 *
5 * - Loads eBPF program
6 *
7 * The eBPF program accesses the map passed in to store two pieces of
8 * information. The number of invocations of the program, which maps
9 * to the number of packets received, is stored to key 0. Key 1 is
10 * incremented on each iteration by the number of bytes stored in
11 * the skb.
12 *
13 * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
14 *
15 * - Every second, reads map[0] and map[1] to see how many bytes and
16 * packets were seen on any socket of tasks in the given cgroup.
17 */
18
19#define _GNU_SOURCE
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <stddef.h>
24#include <string.h>
25#include <unistd.h>
26#include <assert.h>
27#include <errno.h>
28#include <fcntl.h>
29
30#include <linux/bpf.h>
31#include <bpf/bpf.h>
32
33#include "bpf_insn.h"
34#include "bpf_util.h"
35
36enum {
37 MAP_KEY_PACKETS,
38 MAP_KEY_BYTES,
39};
40
41char bpf_log_buf[BPF_LOG_BUF_SIZE];
42
43static int prog_load(int map_fd, int verdict)
44{
45 struct bpf_insn prog[] = {
46 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), /* save r6 so it's not clobbered by BPF_CALL */
47
48 /* Count packets */
49 BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_PACKETS), /* r0 = 0 */
50 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
51 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
52 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */
53 BPF_LD_MAP_FD(BPF_REG_1, map_fd), /* load map fd to r1 */
54 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
55 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
56 BPF_MOV64_IMM(BPF_REG_1, 1), /* r1 = 1 */
57 BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_1, 0),
58
59 /* Count bytes */
60 BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_BYTES), /* r0 = 1 */
61 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
62 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
63 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */
64 BPF_LD_MAP_FD(BPF_REG_1, map_fd),
65 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
66 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
67 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offsetof(struct __sk_buff, len)), /* r1 = skb->len */
68
69 BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_1, 0),
70
71 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
72 BPF_EXIT_INSN(),
73 };
74 size_t insns_cnt = ARRAY_SIZE(prog);
75 LIBBPF_OPTS(bpf_prog_load_opts, opts,
76 .log_buf = bpf_log_buf,
77 .log_size = BPF_LOG_BUF_SIZE,
78 );
79
80 return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB, NULL, "GPL",
81 prog, insns_cnt, &opts);
82}
83
84static int usage(const char *argv0)
85{
86 printf("Usage: %s [-d] [-D] <cg-path> <egress|ingress>\n", argv0);
87 printf(" -d Drop Traffic\n");
88 printf(" -D Detach filter, and exit\n");
89 return EXIT_FAILURE;
90}
91
92static int attach_filter(int cg_fd, int type, int verdict)
93{
94 int prog_fd, map_fd, ret, key;
95 long long pkt_cnt, byte_cnt;
96
97 map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL,
98 sizeof(key), sizeof(byte_cnt),
99 256, NULL);
100 if (map_fd < 0) {
101 printf("Failed to create map: '%s'\n", strerror(errno));
102 return EXIT_FAILURE;
103 }
104
105 prog_fd = prog_load(map_fd, verdict);
106 printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf);
107
108 if (prog_fd < 0) {
109 printf("Failed to load prog: '%s'\n", strerror(errno));
110 return EXIT_FAILURE;
111 }
112
113 ret = bpf_prog_attach(prog_fd, cg_fd, type, 0);
114 if (ret < 0) {
115 printf("Failed to attach prog to cgroup: '%s'\n",
116 strerror(errno));
117 return EXIT_FAILURE;
118 }
119 while (1) {
120 key = MAP_KEY_PACKETS;
121 assert(bpf_map_lookup_elem(map_fd, &key, &pkt_cnt) == 0);
122
123 key = MAP_KEY_BYTES;
124 assert(bpf_map_lookup_elem(map_fd, &key, &byte_cnt) == 0);
125
126 printf("cgroup received %lld packets, %lld bytes\n",
127 pkt_cnt, byte_cnt);
128 sleep(1);
129 }
130
131 return EXIT_SUCCESS;
132}
133
134int main(int argc, char **argv)
135{
136 int detach_only = 0, verdict = 1;
137 enum bpf_attach_type type;
138 int opt, cg_fd, ret;
139
140 while ((opt = getopt(argc, argv, "Dd")) != -1) {
141 switch (opt) {
142 case 'd':
143 verdict = 0;
144 break;
145 case 'D':
146 detach_only = 1;
147 break;
148 default:
149 return usage(argv[0]);
150 }
151 }
152
153 if (argc - optind < 2)
154 return usage(argv[0]);
155
156 if (strcmp(argv[optind + 1], "ingress") == 0)
157 type = BPF_CGROUP_INET_INGRESS;
158 else if (strcmp(argv[optind + 1], "egress") == 0)
159 type = BPF_CGROUP_INET_EGRESS;
160 else
161 return usage(argv[0]);
162
163 cg_fd = open(argv[optind], O_DIRECTORY | O_RDONLY);
164 if (cg_fd < 0) {
165 printf("Failed to open cgroup path: '%s'\n", strerror(errno));
166 return EXIT_FAILURE;
167 }
168
169 if (detach_only) {
170 ret = bpf_prog_detach(cg_fd, type);
171 printf("bpf_prog_detach() returned '%s' (%d)\n",
172 strerror(errno), errno);
173 } else
174 ret = attach_filter(cg_fd, type, verdict);
175
176 return ret;
177}
samples/bpf/test_cgrp2_sock.c+0−294
@@ -1,294 +0,0 @@
1/* eBPF example program:
2 *
3 * - Loads eBPF program
4 *
5 * The eBPF program sets the sk_bound_dev_if index in new AF_INET{6}
6 * sockets opened by processes in the cgroup.
7 *
8 * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
9 */
10
11#define _GNU_SOURCE
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <stddef.h>
16#include <string.h>
17#include <unistd.h>
18#include <assert.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <net/if.h>
22#include <inttypes.h>
23#include <linux/bpf.h>
24#include <bpf/bpf.h>
25
26#include "bpf_insn.h"
27
28char bpf_log_buf[BPF_LOG_BUF_SIZE];
29
30static int prog_load(__u32 idx, __u32 mark, __u32 prio)
31{
32 /* save pointer to context */
33 struct bpf_insn prog_start[] = {
34 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
35 };
36 struct bpf_insn prog_end[] = {
37 BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
38 BPF_EXIT_INSN(),
39 };
40
41 /* set sk_bound_dev_if on socket */
42 struct bpf_insn prog_dev[] = {
43 BPF_MOV64_IMM(BPF_REG_3, idx),
44 BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)),
45 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)),
46 };
47
48 /* set mark on socket */
49 struct bpf_insn prog_mark[] = {
50 /* get uid of process */
51 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
52 BPF_FUNC_get_current_uid_gid),
53 BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff),
54
55 /* if uid is 0, use given mark, else use the uid as the mark */
56 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
57 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
58 BPF_MOV64_IMM(BPF_REG_3, mark),
59
60 /* set the mark on the new socket */
61 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
62 BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, mark)),
63 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, mark)),
64 };
65
66 /* set priority on socket */
67 struct bpf_insn prog_prio[] = {
68 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
69 BPF_MOV64_IMM(BPF_REG_3, prio),
70 BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, priority)),
71 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, priority)),
72 };
73 LIBBPF_OPTS(bpf_prog_load_opts, opts,
74 .log_buf = bpf_log_buf,
75 .log_size = BPF_LOG_BUF_SIZE,
76 );
77
78 struct bpf_insn *prog;
79 size_t insns_cnt;
80 void *p;
81 int ret;
82
83 insns_cnt = sizeof(prog_start) + sizeof(prog_end);
84 if (idx)
85 insns_cnt += sizeof(prog_dev);
86
87 if (mark)
88 insns_cnt += sizeof(prog_mark);
89
90 if (prio)
91 insns_cnt += sizeof(prog_prio);
92
93 p = prog = malloc(insns_cnt);
94 if (!prog) {
95 fprintf(stderr, "Failed to allocate memory for instructions\n");
96 return EXIT_FAILURE;
97 }
98
99 memcpy(p, prog_start, sizeof(prog_start));
100 p += sizeof(prog_start);
101
102 if (idx) {
103 memcpy(p, prog_dev, sizeof(prog_dev));
104 p += sizeof(prog_dev);
105 }
106
107 if (mark) {
108 memcpy(p, prog_mark, sizeof(prog_mark));
109 p += sizeof(prog_mark);
110 }
111
112 if (prio) {
113 memcpy(p, prog_prio, sizeof(prog_prio));
114 p += sizeof(prog_prio);
115 }
116
117 memcpy(p, prog_end, sizeof(prog_end));
118 p += sizeof(prog_end);
119
120 insns_cnt /= sizeof(struct bpf_insn);
121
122 ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, NULL, "GPL",
123 prog, insns_cnt, &opts);
124
125 free(prog);
126
127 return ret;
128}
129
130static int get_bind_to_device(int sd, char *name, size_t len)
131{
132 socklen_t optlen = len;
133 int rc;
134
135 name[0] = '\0';
136 rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen);
137 if (rc < 0)
138 perror("setsockopt(SO_BINDTODEVICE)");
139
140 return rc;
141}
142
143static unsigned int get_somark(int sd)
144{
145 unsigned int mark = 0;
146 socklen_t optlen = sizeof(mark);
147 int rc;
148
149 rc = getsockopt(sd, SOL_SOCKET, SO_MARK, &mark, &optlen);
150 if (rc < 0)
151 perror("getsockopt(SO_MARK)");
152
153 return mark;
154}
155
156static unsigned int get_priority(int sd)
157{
158 unsigned int prio = 0;
159 socklen_t optlen = sizeof(prio);
160 int rc;
161
162 rc = getsockopt(sd, SOL_SOCKET, SO_PRIORITY, &prio, &optlen);
163 if (rc < 0)
164 perror("getsockopt(SO_PRIORITY)");
165
166 return prio;
167}
168
169static int show_sockopts(int family)
170{
171 unsigned int mark, prio;
172 char name[16];
173 int sd;
174
175 sd = socket(family, SOCK_DGRAM, 17);
176 if (sd < 0) {
177 perror("socket");
178 return 1;
179 }
180
181 if (get_bind_to_device(sd, name, sizeof(name)) < 0)
182 return 1;
183
184 mark = get_somark(sd);
185 prio = get_priority(sd);
186
187 close(sd);
188
189 printf("sd %d: dev %s, mark %u, priority %u\n", sd, name, mark, prio);
190
191 return 0;
192}
193
194static int usage(const char *argv0)
195{
196 printf("Usage:\n");
197 printf(" Attach a program\n");
198 printf(" %s -b bind-to-dev -m mark -p prio cg-path\n", argv0);
199 printf("\n");
200 printf(" Detach a program\n");
201 printf(" %s -d cg-path\n", argv0);
202 printf("\n");
203 printf(" Show inherited socket settings (mark, priority, and device)\n");
204 printf(" %s [-6]\n", argv0);
205 return EXIT_FAILURE;
206}
207
208int main(int argc, char **argv)
209{
210 __u32 idx = 0, mark = 0, prio = 0;
211 const char *cgrp_path = NULL;
212 int cg_fd, prog_fd, ret;
213 int family = PF_INET;
214 int do_attach = 1;
215 int rc;
216
217 while ((rc = getopt(argc, argv, "db:m:p:6")) != -1) {
218 switch (rc) {
219 case 'd':
220 do_attach = 0;
221 break;
222 case 'b':
223 idx = if_nametoindex(optarg);
224 if (!idx) {
225 idx = strtoumax(optarg, NULL, 0);
226 if (!idx) {
227 printf("Invalid device name\n");
228 return EXIT_FAILURE;
229 }
230 }
231 break;
232 case 'm':
233 mark = strtoumax(optarg, NULL, 0);
234 break;
235 case 'p':
236 prio = strtoumax(optarg, NULL, 0);
237 break;
238 case '6':
239 family = PF_INET6;
240 break;
241 default:
242 return usage(argv[0]);
243 }
244 }
245
246 if (optind == argc)
247 return show_sockopts(family);
248
249 cgrp_path = argv[optind];
250 if (!cgrp_path) {
251 fprintf(stderr, "cgroup path not given\n");
252 return EXIT_FAILURE;
253 }
254
255 if (do_attach && !idx && !mark && !prio) {
256 fprintf(stderr,
257 "One of device, mark or priority must be given\n");
258 return EXIT_FAILURE;
259 }
260
261 cg_fd = open(cgrp_path, O_DIRECTORY | O_RDONLY);
262 if (cg_fd < 0) {
263 printf("Failed to open cgroup path: '%s'\n", strerror(errno));
264 return EXIT_FAILURE;
265 }
266
267 if (do_attach) {
268 prog_fd = prog_load(idx, mark, prio);
269 if (prog_fd < 0) {
270 printf("Failed to load prog: '%s'\n", strerror(errno));
271 printf("Output from kernel verifier:\n%s\n-------\n",
272 bpf_log_buf);
273 return EXIT_FAILURE;
274 }
275
276 ret = bpf_prog_attach(prog_fd, cg_fd,
277 BPF_CGROUP_INET_SOCK_CREATE, 0);
278 if (ret < 0) {
279 printf("Failed to attach prog to cgroup: '%s'\n",
280 strerror(errno));
281 return EXIT_FAILURE;
282 }
283 } else {
284 ret = bpf_prog_detach(cg_fd, BPF_CGROUP_INET_SOCK_CREATE);
285 if (ret < 0) {
286 printf("Failed to detach prog from cgroup: '%s'\n",
287 strerror(errno));
288 return EXIT_FAILURE;
289 }
290 }
291
292 close(cg_fd);
293 return EXIT_SUCCESS;
294}
samples/bpf/test_cgrp2_sock.sh+0−137
@@ -1,137 +0,0 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3
4# Test various socket options that can be set by attaching programs to cgroups.
5
6MY_DIR=$(dirname $0)
7TEST=$MY_DIR/test_cgrp2_sock
8CGRP_MNT="/tmp/cgroupv2-test_cgrp2_sock"
9
10################################################################################
11#
12print_result()
13{
14 local rc=$1
15 local status=" OK "
16
17 [ $rc -ne 0 ] && status="FAIL"
18
19 printf "%-50s [%4s]\n" "$2" "$status"
20}
21
22check_sock()
23{
24 out=$($TEST)
25 echo $out | grep -q "$1"
26 if [ $? -ne 0 ]; then
27 print_result 1 "IPv4: $2"
28 echo " expected: $1"
29 echo " have: $out"
30 rc=1
31 else
32 print_result 0 "IPv4: $2"
33 fi
34}
35
36check_sock6()
37{
38 out=$($TEST -6)
39 echo $out | grep -q "$1"
40 if [ $? -ne 0 ]; then
41 print_result 1 "IPv6: $2"
42 echo " expected: $1"
43 echo " have: $out"
44 rc=1
45 else
46 print_result 0 "IPv6: $2"
47 fi
48}
49
50################################################################################
51#
52
53cleanup()
54{
55 echo $$ >> ${CGRP_MNT}/cgroup.procs
56 rmdir ${CGRP_MNT}/sockopts
57}
58
59cleanup_and_exit()
60{
61 local rc=$1
62 local msg="$2"
63
64 [ -n "$msg" ] && echo "ERROR: $msg"
65
66 $TEST -d ${CGRP_MNT}/sockopts
67 ip li del cgrp2_sock
68 umount ${CGRP_MNT}
69
70 exit $rc
71}
72
73
74################################################################################
75# main
76
77rc=0
78
79ip li add cgrp2_sock type dummy 2>/dev/null
80
81set -e
82mkdir -p ${CGRP_MNT}
83mount -t cgroup2 none ${CGRP_MNT}
84set +e
85
86
87# make sure we have a known start point
88cleanup 2>/dev/null
89
90mkdir -p ${CGRP_MNT}/sockopts
91[ $? -ne 0 ] && cleanup_and_exit 1 "Failed to create cgroup hierarchy"
92
93
94# set pid into cgroup
95echo $$ > ${CGRP_MNT}/sockopts/cgroup.procs
96
97# no bpf program attached, so socket should show no settings
98check_sock "dev , mark 0, priority 0" "No programs attached"
99check_sock6 "dev , mark 0, priority 0" "No programs attached"
100
101# verify device is set
102#
103$TEST -b cgrp2_sock ${CGRP_MNT}/sockopts
104if [ $? -ne 0 ]; then
105 cleanup_and_exit 1 "Failed to install program to set device"
106fi
107check_sock "dev cgrp2_sock, mark 0, priority 0" "Device set"
108check_sock6 "dev cgrp2_sock, mark 0, priority 0" "Device set"
109
110# verify mark is set
111#
112$TEST -m 666 ${CGRP_MNT}/sockopts
113if [ $? -ne 0 ]; then
114 cleanup_and_exit 1 "Failed to install program to set mark"
115fi
116check_sock "dev , mark 666, priority 0" "Mark set"
117check_sock6 "dev , mark 666, priority 0" "Mark set"
118
119# verify priority is set
120#
121$TEST -p 123 ${CGRP_MNT}/sockopts
122if [ $? -ne 0 ]; then
123 cleanup_and_exit 1 "Failed to install program to set priority"
124fi
125check_sock "dev , mark 0, priority 123" "Priority set"
126check_sock6 "dev , mark 0, priority 123" "Priority set"
127
128# all 3 at once
129#
130$TEST -b cgrp2_sock -m 666 -p 123 ${CGRP_MNT}/sockopts
131if [ $? -ne 0 ]; then
132 cleanup_and_exit 1 "Failed to install program to set device, mark and priority"
133fi
134check_sock "dev cgrp2_sock, mark 666, priority 123" "Priority set"
135check_sock6 "dev cgrp2_sock, mark 666, priority 123" "Priority set"
136
137cleanup_and_exit $rc
samples/bpf/test_cgrp2_sock2.c+0−95
@@ -1,95 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/* eBPF example program:
3 *
4 * - Loads eBPF program
5 *
6 * The eBPF program loads a filter from file and attaches the
7 * program to a cgroup using BPF_PROG_ATTACH
8 */
9
10#define _GNU_SOURCE
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <stddef.h>
15#include <string.h>
16#include <unistd.h>
17#include <assert.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <net/if.h>
21#include <linux/bpf.h>
22#include <bpf/bpf.h>
23#include <bpf/libbpf.h>
24
25#include "bpf_insn.h"
26
27static int usage(const char *argv0)
28{
29 printf("Usage: %s cg-path filter-path [filter-id]\n", argv0);
30 return EXIT_FAILURE;
31}
32
33int main(int argc, char **argv)
34{
35 int cg_fd, err, ret = EXIT_FAILURE, filter_id = 0, prog_cnt = 0;
36 const char *link_pin_path = "/sys/fs/bpf/test_cgrp2_sock2";
37 struct bpf_link *link = NULL;
38 struct bpf_program *progs[2];
39 struct bpf_program *prog;
40 struct bpf_object *obj;
41
42 if (argc < 3)
43 return usage(argv[0]);
44
45 if (argc > 3)
46 filter_id = atoi(argv[3]);
47
48 cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
49 if (cg_fd < 0) {
50 printf("Failed to open cgroup path: '%s'\n", strerror(errno));
51 return ret;
52 }
53
54 obj = bpf_object__open_file(argv[2], NULL);
55 if (libbpf_get_error(obj)) {
56 printf("ERROR: opening BPF object file failed\n");
57 return ret;
58 }
59
60 bpf_object__for_each_program(prog, obj) {
61 progs[prog_cnt] = prog;
62 prog_cnt++;
63 }
64
65 if (filter_id >= prog_cnt) {
66 printf("Invalid program id; program not found in file\n");
67 goto cleanup;
68 }
69
70 /* load BPF program */
71 if (bpf_object__load(obj)) {
72 printf("ERROR: loading BPF object file failed\n");
73 goto cleanup;
74 }
75
76 link = bpf_program__attach_cgroup(progs[filter_id], cg_fd);
77 if (libbpf_get_error(link)) {
78 printf("ERROR: bpf_program__attach failed\n");
79 link = NULL;
80 goto cleanup;
81 }
82
83 err = bpf_link__pin(link, link_pin_path);
84 if (err < 0) {
85 printf("ERROR: bpf_link__pin failed: %d\n", err);
86 goto cleanup;
87 }
88
89 ret = EXIT_SUCCESS;
90
91cleanup:
92 bpf_link__destroy(link);
93 bpf_object__close(obj);
94 return ret;
95}
samples/bpf/test_cgrp2_sock2.sh+0−103
@@ -1,103 +0,0 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4BPFFS=/sys/fs/bpf
5MY_DIR=$(dirname $0)
6TEST=$MY_DIR/test_cgrp2_sock2
7LINK_PIN=$BPFFS/test_cgrp2_sock2
8BPF_PROG=$MY_DIR/sock_flags.bpf.o
9
10function config_device {
11 ip netns add at_ns0
12 ip link add veth0 type veth peer name veth0b
13 ip link set veth0 netns at_ns0
14 ip netns exec at_ns0 sysctl -q net.ipv6.conf.veth0.disable_ipv6=0
15 ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0
16 ip netns exec at_ns0 ip addr add 2401:db00::1/64 dev veth0 nodad
17 ip netns exec at_ns0 ip link set dev veth0 up
18 sysctl -q net.ipv6.conf.veth0b.disable_ipv6=0
19 ip addr add 172.16.1.101/24 dev veth0b
20 ip addr add 2401:db00::2/64 dev veth0b nodad
21 ip link set veth0b up
22}
23
24function config_cgroup {
25 rm -rf /tmp/cgroupv2
26 mkdir -p /tmp/cgroupv2
27 mount -t cgroup2 none /tmp/cgroupv2
28 mkdir -p /tmp/cgroupv2/foo
29 echo $$ >> /tmp/cgroupv2/foo/cgroup.procs
30}
31
32function config_bpffs {
33 if mount | grep $BPFFS > /dev/null; then
34 echo "bpffs already mounted"
35 else
36 echo "bpffs not mounted. Mounting..."
37 mount -t bpf none $BPFFS
38 fi
39}
40
41function attach_bpf {
42 $TEST /tmp/cgroupv2/foo $BPF_PROG $1
43 [ $? -ne 0 ] && exit 1
44}
45
46function cleanup {
47 rm -rf $LINK_PIN
48 ip link del veth0b
49 ip netns delete at_ns0
50 umount /tmp/cgroupv2
51 rm -rf /tmp/cgroupv2
52}
53
54cleanup 2>/dev/null
55
56set -e
57config_device
58config_cgroup
59config_bpffs
60set +e
61
62#
63# Test 1 - fail ping6
64#
65attach_bpf 0
66ping -c1 -w1 172.16.1.100
67if [ $? -ne 0 ]; then
68 echo "ping failed when it should succeed"
69 cleanup
70 exit 1
71fi
72
73ping6 -c1 -w1 2401:db00::1
74if [ $? -eq 0 ]; then
75 echo "ping6 succeeded when it should not"
76 cleanup
77 exit 1
78fi
79
80rm -rf $LINK_PIN
81sleep 1 # Wait for link detach
82
83#
84# Test 2 - fail ping
85#
86attach_bpf 1
87ping6 -c1 -w1 2401:db00::1
88if [ $? -ne 0 ]; then
89 echo "ping6 failed when it should succeed"
90 cleanup
91 exit 1
92fi
93
94ping -c1 -w1 172.16.1.100
95if [ $? -eq 0 ]; then
96 echo "ping succeeded when it should not"
97 cleanup
98 exit 1
99fi
100
101cleanup
102echo
103echo "*** PASS ***"
samples/bpf/test_cgrp2_tc.bpf.c+0−56
@@ -1,56 +0,0 @@
1/* Copyright (c) 2016 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#define KBUILD_MODNAME "foo"
8#include "vmlinux.h"
9#include "net_shared.h"
10#include <bpf/bpf_helpers.h>
11
12/* copy of 'struct ethhdr' without __packed */
13struct eth_hdr {
14 unsigned char h_dest[ETH_ALEN];
15 unsigned char h_source[ETH_ALEN];
16 unsigned short h_proto;
17};
18
19struct {
20 __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
21 __type(key, u32);
22 __type(value, u32);
23 __uint(pinning, LIBBPF_PIN_BY_NAME);
24 __uint(max_entries, 1);
25} test_cgrp2_array_pin SEC(".maps");
26
27SEC("filter")
28int handle_egress(struct __sk_buff *skb)
29{
30 void *data = (void *)(long)skb->data;
31 struct eth_hdr *eth = data;
32 struct ipv6hdr *ip6h = data + sizeof(*eth);
33 void *data_end = (void *)(long)skb->data_end;
34 char dont_care_msg[] = "dont care %04x %d\n";
35 char pass_msg[] = "pass\n";
36 char reject_msg[] = "reject\n";
37
38 /* single length check */
39 if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
40 return TC_ACT_OK;
41
42 if (eth->h_proto != bpf_htons(ETH_P_IPV6) ||
43 ip6h->nexthdr != IPPROTO_ICMPV6) {
44 bpf_trace_printk(dont_care_msg, sizeof(dont_care_msg),
45 eth->h_proto, ip6h->nexthdr);
46 return TC_ACT_OK;
47 } else if (bpf_skb_under_cgroup(skb, &test_cgrp2_array_pin, 0) != 1) {
48 bpf_trace_printk(pass_msg, sizeof(pass_msg));
49 return TC_ACT_OK;
50 } else {
51 bpf_trace_printk(reject_msg, sizeof(reject_msg));
52 return TC_ACT_SHOT;
53 }
54}
55
56char _license[] SEC("license") = "GPL";
samples/bpf/test_cgrp2_tc.sh+0−187
@@ -1,187 +0,0 @@
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4MY_DIR=$(dirname $0)
5# Details on the bpf prog
6BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin'
7BPF_PROG="$MY_DIR/test_cgrp2_tc.bpf.o"
8BPF_SECTION='filter'
9
10[ -z "$TC" ] && TC='tc'
11[ -z "$IP" ] && IP='ip'
12
13# Names of the veth interface, net namespace...etc.
14HOST_IFC='ve'
15NS_IFC='vens'
16NS='ns'
17
18find_mnt() {
19 cat /proc/mounts | \
20 awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }'
21}
22
23# Init cgroup2 vars
24init_cgrp2_vars() {
25 CGRP2_ROOT=$(find_mnt cgroup2)
26 if [ -z "$CGRP2_ROOT" ]
27 then
28 CGRP2_ROOT='/mnt/cgroup2'
29 MOUNT_CGRP2="yes"
30 fi
31 CGRP2_TC="$CGRP2_ROOT/tc"
32 CGRP2_TC_LEAF="$CGRP2_TC/leaf"
33}
34
35# Init bpf fs vars
36init_bpf_fs_vars() {
37 local bpf_fs_root=$(find_mnt bpf)
38 [ -n "$bpf_fs_root" ] || return -1
39 BPF_FS_TC_SHARE="$bpf_fs_root/tc/globals"
40}
41
42setup_cgrp2() {
43 case $1 in
44 start)
45 if [ "$MOUNT_CGRP2" == 'yes' ]
46 then
47 [ -d $CGRP2_ROOT ] || mkdir -p $CGRP2_ROOT
48 mount -t cgroup2 none $CGRP2_ROOT || return $?
49 fi
50 mkdir -p $CGRP2_TC_LEAF
51 ;;
52 *)
53 rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC
54 [ "$MOUNT_CGRP2" == 'yes' ] && umount $CGRP2_ROOT
55 ;;
56 esac
57}
58
59setup_bpf_cgrp2_array() {
60 local bpf_cgrp2_array="$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME"
61 case $1 in
62 start)
63 $MY_DIR/test_cgrp2_array_pin -U $bpf_cgrp2_array -v $CGRP2_TC
64 ;;
65 *)
66 [ -d "$BPF_FS_TC_SHARE" ] && rm -f $bpf_cgrp2_array
67 ;;
68 esac
69}
70
71setup_net() {
72 case $1 in
73 start)
74 $IP link add $HOST_IFC type veth peer name $NS_IFC || return $?
75 $IP link set dev $HOST_IFC up || return $?
76 sysctl -q net.ipv6.conf.$HOST_IFC.disable_ipv6=0
77 sysctl -q net.ipv6.conf.$HOST_IFC.accept_dad=0
78
79 $IP netns add $NS || return $?
80 $IP link set dev $NS_IFC netns $NS || return $?
81 $IP -n $NS link set dev $NS_IFC up || return $?
82 $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.disable_ipv6=0
83 $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0
84 $TC qdisc add dev $HOST_IFC clsact || return $?
85 $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $?
86 ;;
87 *)
88 $IP netns del $NS
89 $IP link del $HOST_IFC
90 ;;
91 esac
92}
93
94run_in_cgrp() {
95 # Fork another bash and move it under the specified cgroup.
96 # It makes the cgroup cleanup easier at the end of the test.
97 cmd='echo $$ > '
98 cmd="$cmd $1/cgroup.procs; exec $2"
99 bash -c "$cmd"
100}
101
102do_test() {
103 run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null"
104 local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \
105 awk '/drop/{print substr($7, 0, index($7, ",")-1)}')
106 if [[ $dropped -eq 0 ]]
107 then
108 echo "FAIL"
109 return 1
110 else
111 echo "Successfully filtered $dropped packets"
112 return 0
113 fi
114}
115
116do_exit() {
117 if [ "$DEBUG" == "yes" ] && [ "$MODE" != 'cleanuponly' ]
118 then
119 echo "------ DEBUG ------"
120 echo "mount: "; mount | grep -E '(cgroup2|bpf)'; echo
121 echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo
122 if [ -d "$BPF_FS_TC_SHARE" ]
123 then
124 echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo
125 fi
126 echo "Host net:"
127 $IP netns
128 $IP link show dev $HOST_IFC
129 $IP -6 a show dev $HOST_IFC
130 $TC -s qdisc show dev $HOST_IFC
131 echo
132 echo "$NS net:"
133 $IP -n $NS link show dev $NS_IFC
134 $IP -n $NS -6 link show dev $NS_IFC
135 echo "------ DEBUG ------"
136 echo
137 fi
138
139 if [ "$MODE" != 'nocleanup' ]
140 then
141 setup_net stop
142 setup_bpf_cgrp2_array stop
143 setup_cgrp2 stop
144 fi
145}
146
147init_cgrp2_vars
148init_bpf_fs_vars
149
150while [[ $# -ge 1 ]]
151do
152 a="$1"
153 case $a in
154 debug)
155 DEBUG='yes'
156 shift 1
157 ;;
158 cleanup-only)
159 MODE='cleanuponly'
160 shift 1
161 ;;
162 no-cleanup)
163 MODE='nocleanup'
164 shift 1
165 ;;
166 *)
167 echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]"
168 echo " debug: Print cgrp and network setup details at the end of the test"
169 echo " cleanup-only: Try to cleanup things from last test. No test will be run"
170 echo " no-cleanup: Run the test but don't do cleanup at the end"
171 echo "[Note: If no arg is given, it will run the test and do cleanup at the end]"
172 echo
173 exit -1
174 ;;
175 esac
176done
177
178trap do_exit 0
179
180[ "$MODE" == 'cleanuponly' ] && exit
181
182setup_cgrp2 start || exit $?
183setup_net start || exit $?
184init_bpf_fs_vars || exit $?
185setup_bpf_cgrp2_array start || exit $?
186do_test
187echo
samples/bpf/test_current_task_under_cgroup.bpf.c+0−43
@@ -1,43 +0,0 @@
1/* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me>
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7
8#include "vmlinux.h"
9#include <linux/version.h>
10#include <bpf/bpf_helpers.h>
11#include <bpf/bpf_tracing.h>
12#include <bpf/bpf_core_read.h>
13
14struct {
15 __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
16 __uint(key_size, sizeof(u32));
17 __uint(value_size, sizeof(u32));
18 __uint(max_entries, 1);
19} cgroup_map SEC(".maps");
20
21struct {
22 __uint(type, BPF_MAP_TYPE_ARRAY);
23 __type(key, u32);
24 __type(value, u64);
25 __uint(max_entries, 1);
26} perf_map SEC(".maps");
27
28/* Writes the last PID that called sync to a map at index 0 */
29SEC("ksyscall/sync")
30int BPF_KSYSCALL(bpf_prog1)
31{
32 u64 pid = bpf_get_current_pid_tgid();
33 int idx = 0;
34
35 if (!bpf_current_task_under_cgroup(&cgroup_map, 0))
36 return 0;
37
38 bpf_map_update_elem(&perf_map, &idx, &pid, BPF_ANY);
39 return 0;
40}
41
42char _license[] SEC("license") = "GPL";
43u32 _version SEC("version") = LINUX_VERSION_CODE;
samples/bpf/test_current_task_under_cgroup_user.c+0−115
@@ -1,115 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me>
3 */
4
5#define _GNU_SOURCE
6#include <stdio.h>
7#include <unistd.h>
8#include <bpf/bpf.h>
9#include <bpf/libbpf.h>
10#include "cgroup_helpers.h"
11
12#define CGROUP_PATH "/my-cgroup"
13
14int main(int argc, char **argv)
15{
16 pid_t remote_pid, local_pid = getpid();
17 int cg2 = -1, idx = 0, rc = 1;
18 struct bpf_link *link = NULL;
19 struct bpf_program *prog;
20 struct bpf_object *obj;
21 char filename[256];
22 int map_fd[2];
23
24 snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
25 obj = bpf_object__open_file(filename, NULL);
26 if (libbpf_get_error(obj)) {
27 fprintf(stderr, "ERROR: opening BPF object file failed\n");
28 return 0;
29 }
30
31 prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
32 if (!prog) {
33 printf("finding a prog in obj file failed\n");
34 goto cleanup;
35 }
36
37 /* load BPF program */
38 if (bpf_object__load(obj)) {
39 fprintf(stderr, "ERROR: loading BPF object file failed\n");
40 goto cleanup;
41 }
42
43 map_fd[0] = bpf_object__find_map_fd_by_name(obj, "cgroup_map");
44 map_fd[1] = bpf_object__find_map_fd_by_name(obj, "perf_map");
45 if (map_fd[0] < 0 || map_fd[1] < 0) {
46 fprintf(stderr, "ERROR: finding a map in obj file failed\n");
47 goto cleanup;
48 }
49
50 link = bpf_program__attach(prog);
51 if (libbpf_get_error(link)) {
52 fprintf(stderr, "ERROR: bpf_program__attach failed\n");
53 link = NULL;
54 goto cleanup;
55 }
56
57 if (setup_cgroup_environment())
58 goto err;
59
60 cg2 = create_and_get_cgroup(CGROUP_PATH);
61
62 if (cg2 < 0)
63 goto err;
64
65 if (bpf_map_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) {
66 log_err("Adding target cgroup to map");
67 goto err;
68 }
69
70 if (join_cgroup(CGROUP_PATH))
71 goto err;
72
73 /*
74 * The installed helper program catched the sync call, and should
75 * write it to the map.
76 */
77
78 sync();
79 bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid);
80
81 if (local_pid != remote_pid) {
82 fprintf(stderr,
83 "BPF Helper didn't write correct PID to map, but: %d\n",
84 remote_pid);
85 goto err;
86 }
87
88 /* Verify the negative scenario; leave the cgroup */
89 if (join_cgroup("/"))
90 goto err;
91
92 remote_pid = 0;
93 bpf_map_update_elem(map_fd[1], &idx, &remote_pid, BPF_ANY);
94
95 sync();
96 bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid);
97
98 if (local_pid == remote_pid) {
99 fprintf(stderr, "BPF cgroup negative test did not work\n");
100 goto err;
101 }
102
103 rc = 0;
104
105err:
106 if (cg2 != -1)
107 close(cg2);
108
109 cleanup_cgroup_environment();
110
111cleanup:
112 bpf_link__destroy(link);
113 bpf_object__close(obj);
114 return rc;
115}
samples/bpf/test_overhead_kprobe.bpf.c+0−41
@@ -1,41 +0,0 @@
1/* Copyright (c) 2016 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include "vmlinux.h"
8#include <linux/version.h>
9#include <bpf/bpf_helpers.h>
10#include <bpf/bpf_tracing.h>
11#include <bpf/bpf_core_read.h>
12
13SEC("kprobe/__set_task_comm")
14int prog(struct pt_regs *ctx)
15{
16 struct signal_struct *signal;
17 struct task_struct *tsk;
18 char oldcomm[TASK_COMM_LEN] = {};
19 char newcomm[TASK_COMM_LEN] = {};
20 u16 oom_score_adj;
21 u32 pid;
22
23 tsk = (void *)PT_REGS_PARM1_CORE(ctx);
24
25 pid = BPF_CORE_READ(tsk, pid);
26 bpf_core_read_str(oldcomm, sizeof(oldcomm), &tsk->comm);
27 bpf_core_read_str(newcomm, sizeof(newcomm),
28 (void *)PT_REGS_PARM2(ctx));
29 signal = BPF_CORE_READ(tsk, signal);
30 oom_score_adj = BPF_CORE_READ(signal, oom_score_adj);
31 return 0;
32}
33
34SEC("kprobe/fib_table_lookup")
35int prog2(struct pt_regs *ctx)
36{
37 return 0;
38}
39
40char _license[] SEC("license") = "GPL";
41u32 _version SEC("version") = LINUX_VERSION_CODE;
samples/bpf/test_overhead_raw_tp.bpf.c+0−17
@@ -1,17 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2018 Facebook */
3#include "vmlinux.h"
4#include <bpf/bpf_helpers.h>
5
6SEC("raw_tracepoint/task_rename")
7int prog(struct bpf_raw_tracepoint_args *ctx)
8{
9 return 0;
10}
11
12SEC("raw_tracepoint/fib_table_lookup")
13int prog2(struct bpf_raw_tracepoint_args *ctx)
14{
15 return 0;
16}
17char _license[] SEC("license") = "GPL";
samples/bpf/test_overhead_tp.bpf.c+0−23
@@ -1,23 +0,0 @@
1/* Copyright (c) 2016 Facebook
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include "vmlinux.h"
8#include <bpf/bpf_helpers.h>
9
10/* from /sys/kernel/tracing/events/task/task_rename/format */
11SEC("tracepoint/task/task_rename")
12int prog(struct trace_event_raw_task_rename *ctx)
13{
14 return 0;
15}
16
17/* from /sys/kernel/tracing/events/fib/fib_table_lookup/format */
18SEC("tracepoint/fib/fib_table_lookup")
19int prog2(struct trace_event_raw_fib_table_lookup *ctx)
20{
21 return 0;
22}
23char _license[] SEC("license") = "GPL";
samples/bpf/test_overhead_user.c+0−225
@@ -1,225 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2016 Facebook
3 */
4#define _GNU_SOURCE
5#include <sched.h>
6#include <errno.h>
7#include <stdio.h>
8#include <sys/types.h>
9#include <asm/unistd.h>
10#include <fcntl.h>
11#include <unistd.h>
12#include <assert.h>
13#include <sys/wait.h>
14#include <sys/socket.h>
15#include <arpa/inet.h>
16#include <stdlib.h>
17#include <signal.h>
18#include <linux/bpf.h>
19#include <string.h>
20#include <time.h>
21#include <bpf/bpf.h>
22#include <bpf/libbpf.h>
23
24#define MAX_CNT 1000000
25#define DUMMY_IP "127.0.0.1"
26#define DUMMY_PORT 80
27
28static struct bpf_link *links[2];
29static struct bpf_object *obj;
30static int cnt;
31
32static __u64 time_get_ns(void)
33{
34 struct timespec ts;
35
36 clock_gettime(CLOCK_MONOTONIC, &ts);
37 return ts.tv_sec * 1000000000ull + ts.tv_nsec;
38}
39
40static void test_task_rename(int cpu)
41{
42 char buf[] = "test\n";
43 __u64 start_time;
44 int i, fd;
45
46 fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
47 if (fd < 0) {
48 printf("couldn't open /proc\n");
49 exit(1);
50 }
51 start_time = time_get_ns();
52 for (i = 0; i < MAX_CNT; i++) {
53 if (write(fd, buf, sizeof(buf)) < 0) {
54 printf("task rename failed: %s\n", strerror(errno));
55 close(fd);
56 return;
57 }
58 }
59 printf("task_rename:%d: %lld events per sec\n",
60 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
61 close(fd);
62}
63
64static void test_fib_table_lookup(int cpu)
65{
66 struct sockaddr_in addr;
67 char buf[] = "test\n";
68 __u64 start_time;
69 int i, fd;
70
71 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
72 if (fd < 0) {
73 printf("couldn't open socket\n");
74 exit(1);
75 }
76 memset((char *)&addr, 0, sizeof(addr));
77 addr.sin_addr.s_addr = inet_addr(DUMMY_IP);
78 addr.sin_port = htons(DUMMY_PORT);
79 addr.sin_family = AF_INET;
80 start_time = time_get_ns();
81 for (i = 0; i < MAX_CNT; i++) {
82 if (sendto(fd, buf, strlen(buf), 0,
83 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
84 printf("failed to start ping: %s\n", strerror(errno));
85 close(fd);
86 return;
87 }
88 }
89 printf("fib_table_lookup:%d: %lld events per sec\n",
90 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
91 close(fd);
92}
93
94static void loop(int cpu, int flags)
95{
96 cpu_set_t cpuset;
97
98 CPU_ZERO(&cpuset);
99 CPU_SET(cpu, &cpuset);
100 sched_setaffinity(0, sizeof(cpuset), &cpuset);
101
102 if (flags & 1)
103 test_task_rename(cpu);
104 if (flags & 2)
105 test_fib_table_lookup(cpu);
106}
107
108static void run_perf_test(int tasks, int flags)
109{
110 pid_t pid[tasks];
111 int i;
112
113 for (i = 0; i < tasks; i++) {
114 pid[i] = fork();
115 if (pid[i] == 0) {
116 loop(i, flags);
117 exit(0);
118 } else if (pid[i] == -1) {
119 printf("couldn't spawn #%d process\n", i);
120 exit(1);
121 }
122 }
123 for (i = 0; i < tasks; i++) {
124 int status;
125
126 assert(waitpid(pid[i], &status, 0) == pid[i]);
127 assert(status == 0);
128 }
129}
130
131static int load_progs(char *filename)
132{
133 struct bpf_program *prog;
134 int err = 0;
135
136 obj = bpf_object__open_file(filename, NULL);
137 err = libbpf_get_error(obj);
138 if (err < 0) {
139 fprintf(stderr, "ERROR: opening BPF object file failed\n");
140 return err;
141 }
142
143 /* load BPF program */
144 err = bpf_object__load(obj);
145 if (err < 0) {
146 fprintf(stderr, "ERROR: loading BPF object file failed\n");
147 return err;
148 }
149
150 bpf_object__for_each_program(prog, obj) {
151 links[cnt] = bpf_program__attach(prog);
152 err = libbpf_get_error(links[cnt]);
153 if (err < 0) {
154 fprintf(stderr, "ERROR: bpf_program__attach failed\n");
155 links[cnt] = NULL;
156 return err;
157 }
158 cnt++;
159 }
160
161 return err;
162}
163
164static void unload_progs(void)
165{
166 while (cnt)
167 bpf_link__destroy(links[--cnt]);
168
169 bpf_object__close(obj);
170}
171
172int main(int argc, char **argv)
173{
174 int num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
175 int test_flags = ~0;
176 char filename[256];
177 int err = 0;
178
179
180 if (argc > 1)
181 test_flags = atoi(argv[1]) ? : test_flags;
182 if (argc > 2)
183 num_cpu = atoi(argv[2]) ? : num_cpu;
184
185 if (test_flags & 0x3) {
186 printf("BASE\n");
187 run_perf_test(num_cpu, test_flags);
188 }
189
190 if (test_flags & 0xC) {
191 snprintf(filename, sizeof(filename),
192 "%s_kprobe.bpf.o", argv[0]);
193
194 printf("w/KPROBE\n");
195 err = load_progs(filename);
196 if (!err)
197 run_perf_test(num_cpu, test_flags >> 2);
198
199 unload_progs();
200 }
201
202 if (test_flags & 0x30) {
203 snprintf(filename, sizeof(filename),
204 "%s_tp.bpf.o", argv[0]);
205 printf("w/TRACEPOINT\n");
206 err = load_progs(filename);
207 if (!err)
208 run_perf_test(num_cpu, test_flags >> 4);
209
210 unload_progs();
211 }
212
213 if (test_flags & 0xC0) {
214 snprintf(filename, sizeof(filename),
215 "%s_raw_tp.bpf.o", argv[0]);
216 printf("w/RAW_TRACEPOINT\n");
217 err = load_progs(filename);
218 if (!err)
219 run_perf_test(num_cpu, test_flags >> 6);
220
221 unload_progs();
222 }
223
224 return err;
225}
samples/bpf/test_override_return.sh+0−16
@@ -1,16 +0,0 @@
1#!/bin/bash
2
3rm -r tmpmnt
4rm -f testfile.img
5dd if=/dev/zero of=testfile.img bs=1M seek=1000 count=1
6DEVICE=$(losetup --show -f testfile.img)
7mkfs.btrfs -f $DEVICE
8mkdir tmpmnt
9./tracex7 $DEVICE
10if [ $? -eq 0 ]
11then
12 echo "SUCCESS!"
13else
14 echo "FAILED!"
15fi
16losetup -d $DEVICE
samples/bpf/test_probe_write_user.bpf.c+0−52
@@ -1,52 +0,0 @@
1/* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me>
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#include "vmlinux.h"
8#include <string.h>
9#include <linux/version.h>
10#include <bpf/bpf_helpers.h>
11#include <bpf/bpf_tracing.h>
12#include <bpf/bpf_core_read.h>
13
14struct {
15 __uint(type, BPF_MAP_TYPE_HASH);
16 __type(key, struct sockaddr_in);
17 __type(value, struct sockaddr_in);
18 __uint(max_entries, 256);
19} dnat_map SEC(".maps");
20
21/* kprobe is NOT a stable ABI
22 * kernel functions can be removed, renamed or completely change semantics.
23 * Number of arguments and their positions can change, etc.
24 * In such case this bpf+kprobe example will no longer be meaningful
25 *
26 * This example sits on a syscall, and the syscall ABI is relatively stable
27 * of course, across platforms, and over time, the ABI may change.
28 */
29SEC("ksyscall/connect")
30int BPF_KSYSCALL(bpf_prog1, int fd, struct sockaddr_in *uservaddr,
31 int addrlen)
32{
33 struct sockaddr_in new_addr, orig_addr = {};
34 struct sockaddr_in *mapped_addr;
35
36 if (addrlen > sizeof(orig_addr))
37 return 0;
38
39 if (bpf_probe_read_user(&orig_addr, sizeof(orig_addr), uservaddr) != 0)
40 return 0;
41
42 mapped_addr = bpf_map_lookup_elem(&dnat_map, &orig_addr);
43 if (mapped_addr != NULL) {
44 memcpy(&new_addr, mapped_addr, sizeof(new_addr));
45 bpf_probe_write_user(uservaddr, &new_addr,
46 sizeof(new_addr));
47 }
48 return 0;
49}
50
51char _license[] SEC("license") = "GPL";
52u32 _version SEC("version") = LINUX_VERSION_CODE;
samples/bpf/test_probe_write_user_user.c+0−108
@@ -1,108 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <stdio.h>
3#include <assert.h>
4#include <unistd.h>
5#include <bpf/bpf.h>
6#include <bpf/libbpf.h>
7#include <sys/socket.h>
8#include <netinet/in.h>
9#include <arpa/inet.h>
10
11int main(int ac, char **argv)
12{
13 struct sockaddr_in *serv_addr_in, *mapped_addr_in, *tmp_addr_in;
14 struct sockaddr serv_addr, mapped_addr, tmp_addr;
15 int serverfd, serverconnfd, clientfd, map_fd;
16 struct bpf_link *link = NULL;
17 struct bpf_program *prog;
18 struct bpf_object *obj;
19 socklen_t sockaddr_len;
20 char filename[256];
21 char *ip;
22
23 serv_addr_in = (struct sockaddr_in *)&serv_addr;
24 mapped_addr_in = (struct sockaddr_in *)&mapped_addr;
25 tmp_addr_in = (struct sockaddr_in *)&tmp_addr;
26
27 snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
28 obj = bpf_object__open_file(filename, NULL);
29 if (libbpf_get_error(obj)) {
30 fprintf(stderr, "ERROR: opening BPF object file failed\n");
31 return 0;
32 }
33
34 prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
35 if (libbpf_get_error(prog)) {
36 fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
37 goto cleanup;
38 }
39
40 /* load BPF program */
41 if (bpf_object__load(obj)) {
42 fprintf(stderr, "ERROR: loading BPF object file failed\n");
43 goto cleanup;
44 }
45
46 map_fd = bpf_object__find_map_fd_by_name(obj, "dnat_map");
47 if (map_fd < 0) {
48 fprintf(stderr, "ERROR: finding a map in obj file failed\n");
49 goto cleanup;
50 }
51
52 link = bpf_program__attach(prog);
53 if (libbpf_get_error(link)) {
54 fprintf(stderr, "ERROR: bpf_program__attach failed\n");
55 link = NULL;
56 goto cleanup;
57 }
58
59 assert((serverfd = socket(AF_INET, SOCK_STREAM, 0)) > 0);
60 assert((clientfd = socket(AF_INET, SOCK_STREAM, 0)) > 0);
61
62 /* Bind server to ephemeral port on lo */
63 memset(&serv_addr, 0, sizeof(serv_addr));
64 serv_addr_in->sin_family = AF_INET;
65 serv_addr_in->sin_port = 0;
66 serv_addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
67
68 assert(bind(serverfd, &serv_addr, sizeof(serv_addr)) == 0);
69
70 sockaddr_len = sizeof(serv_addr);
71 assert(getsockname(serverfd, &serv_addr, &sockaddr_len) == 0);
72 ip = inet_ntoa(serv_addr_in->sin_addr);
73 printf("Server bound to: %s:%d\n", ip, ntohs(serv_addr_in->sin_port));
74
75 memset(&mapped_addr, 0, sizeof(mapped_addr));
76 mapped_addr_in->sin_family = AF_INET;
77 mapped_addr_in->sin_port = htons(5555);
78 mapped_addr_in->sin_addr.s_addr = inet_addr("255.255.255.255");
79
80 assert(!bpf_map_update_elem(map_fd, &mapped_addr, &serv_addr, BPF_ANY));
81
82 assert(listen(serverfd, 5) == 0);
83
84 ip = inet_ntoa(mapped_addr_in->sin_addr);
85 printf("Client connecting to: %s:%d\n",
86 ip, ntohs(mapped_addr_in->sin_port));
87 assert(connect(clientfd, &mapped_addr, sizeof(mapped_addr)) == 0);
88
89 sockaddr_len = sizeof(tmp_addr);
90 ip = inet_ntoa(tmp_addr_in->sin_addr);
91 assert((serverconnfd = accept(serverfd, &tmp_addr, &sockaddr_len)) > 0);
92 printf("Server received connection from: %s:%d\n",
93 ip, ntohs(tmp_addr_in->sin_port));
94
95 sockaddr_len = sizeof(tmp_addr);
96 assert(getpeername(clientfd, &tmp_addr, &sockaddr_len) == 0);
97 ip = inet_ntoa(tmp_addr_in->sin_addr);
98 printf("Client's peer address: %s:%d\n",
99 ip, ntohs(tmp_addr_in->sin_port));
100
101 /* Is the server's getsockname = the socket getpeername */
102 assert(memcmp(&serv_addr, &tmp_addr, sizeof(struct sockaddr_in)) == 0);
103
104cleanup:
105 bpf_link__destroy(link);
106 bpf_object__close(obj);
107 return 0;
108}
samples/bpf/tracex7.bpf.c+0−15
@@ -1,15 +0,0 @@
1#include "vmlinux.h"
2#include <linux/version.h>
3#include <bpf/bpf_helpers.h>
4
5SEC("kprobe/open_ctree")
6int bpf_prog1(struct pt_regs *ctx)
7{
8 unsigned long rc = -12;
9
10 bpf_override_return(ctx, rc);
11 return 0;
12}
13
14char _license[] SEC("license") = "GPL";
15u32 _version SEC("version") = LINUX_VERSION_CODE;
samples/bpf/tracex7_user.c+0−56
@@ -1,56 +0,0 @@
1#define _GNU_SOURCE
2
3#include <stdio.h>
4#include <unistd.h>
5#include <bpf/libbpf.h>
6
7int main(int argc, char **argv)
8{
9 struct bpf_link *link = NULL;
10 struct bpf_program *prog;
11 struct bpf_object *obj;
12 char filename[256];
13 char command[256];
14 int ret = 0;
15 FILE *f;
16
17 if (!argv[1]) {
18 fprintf(stderr, "ERROR: Run with the btrfs device argument!\n");
19 return 0;
20 }
21
22 snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
23 obj = bpf_object__open_file(filename, NULL);
24 if (libbpf_get_error(obj)) {
25 fprintf(stderr, "ERROR: opening BPF object file failed\n");
26 return 0;
27 }
28
29 prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
30 if (!prog) {
31 fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
32 goto cleanup;
33 }
34
35 /* load BPF program */
36 if (bpf_object__load(obj)) {
37 fprintf(stderr, "ERROR: loading BPF object file failed\n");
38 goto cleanup;
39 }
40
41 link = bpf_program__attach(prog);
42 if (libbpf_get_error(link)) {
43 fprintf(stderr, "ERROR: bpf_program__attach failed\n");
44 link = NULL;
45 goto cleanup;
46 }
47
48 snprintf(command, 256, "mount %s tmpmnt/", argv[1]);
49 f = popen(command, "r");
50 ret = pclose(f);
51
52cleanup:
53 bpf_link__destroy(link);
54 bpf_object__close(obj);
55 return ret ? 0 : 1;
56}
samples/bpf/xdp2skb_meta_kern.c+1−1
@@ -32,7 +32,7 @@ SEC("xdp_mark") · 31 unmodified lines
32int _xdp_mark(struct xdp_md *ctx)32int _xdp_mark(struct xdp_md *ctx)
33{33{
34 struct meta_info *meta;34 struct meta_info *meta;
35 void *data, *data_end;35 void *data;
36 int ret;36 int ret;
37 37
38 /* Reserve space in-front of data pointer for our meta info.38 /* Reserve space in-front of data pointer for our meta info.
samples/bpf/xdp_adjust_tail_kern.c+1−0
@@ -57,6 +57,7 @@ static __always_inline void swap_mac(void *data, struct ethhdr *orig_eth) · 56 unmodified lines
57 57
58static __always_inline __u16 csum_fold_helper(__u32 csum)58static __always_inline __u16 csum_fold_helper(__u32 csum)
59{59{
60 csum = (csum & 0xffff) + (csum >> 16);
60 return ~((csum & 0xffff) + (csum >> 16));61 return ~((csum & 0xffff) + (csum >> 16));
61}62}
62 63

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t