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 ...
Showing the changes to samples (25 of 211 files). Show all
Unified · Split
| @@ -17,20 +17,12 @@ tprogs-y += tracex3 · 16 unmodified lines | ||
| 17 | 17 | tprogs-y += tracex4 |
| 18 | 18 | tprogs-y += tracex5 |
| 19 | 19 | tprogs-y += tracex6 |
| 20 | −tprogs-y += tracex7 | |
| 21 | −tprogs-y += test_probe_write_user | |
| 22 | 20 | tprogs-y += trace_output |
| 23 | 21 | tprogs-y += lathist |
| 24 | 22 | tprogs-y += offwaketime |
| 25 | 23 | tprogs-y += spintest |
| 26 | 24 | tprogs-y += map_perf_test |
| 27 | −tprogs-y += test_overhead | |
| 28 | −tprogs-y += test_cgrp2_array_pin | |
| 29 | −tprogs-y += test_cgrp2_attach | |
| 30 | −tprogs-y += test_cgrp2_sock | |
| 31 | −tprogs-y += test_cgrp2_sock2 | |
| 32 | 25 | tprogs-y += xdp_router_ipv4 |
| 33 | −tprogs-y += test_current_task_under_cgroup | |
| 34 | 26 | tprogs-y += trace_event |
| 35 | 27 | tprogs-y += sampleip |
| 36 | 28 | tprogs-y += tc_l2_redirect |
| @@ -66,20 +58,12 @@ tracex3-objs := tracex3_user.o · 29 unmodified lines | ||
| 66 | 58 | tracex4-objs := tracex4_user.o |
| 67 | 59 | tracex5-objs := tracex5_user.o $(TRACE_HELPERS) |
| 68 | 60 | tracex6-objs := tracex6_user.o |
| 69 | −tracex7-objs := tracex7_user.o | |
| 70 | −test_probe_write_user-objs := test_probe_write_user_user.o | |
| 71 | 61 | trace_output-objs := trace_output_user.o |
| 72 | 62 | lathist-objs := lathist_user.o |
| 73 | 63 | offwaketime-objs := offwaketime_user.o $(TRACE_HELPERS) |
| 74 | 64 | spintest-objs := spintest_user.o $(TRACE_HELPERS) |
| 75 | 65 | map_perf_test-objs := map_perf_test_user.o |
| 76 | 66 | test_overhead-objs := test_overhead_user.o |
| 77 | −test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o | |
| 78 | −test_cgrp2_attach-objs := test_cgrp2_attach.o | |
| 79 | −test_cgrp2_sock-objs := test_cgrp2_sock.o | |
| 80 | −test_cgrp2_sock2-objs := test_cgrp2_sock2.o | |
| 81 | −test_current_task_under_cgroup-objs := $(CGROUP_HELPERS) \ | |
| 82 | − test_current_task_under_cgroup_user.o | |
| 83 | 67 | trace_event-objs := trace_event_user.o $(TRACE_HELPERS) |
| 84 | 68 | sampleip-objs := sampleip_user.o $(TRACE_HELPERS) |
| 85 | 69 | tc_l2_redirect-objs := tc_l2_redirect_user.o |
| @@ -107,9 +91,6 @@ always-y += tracex3.bpf.o · 21 unmodified lines | ||
| 107 | 91 | always-y += tracex4.bpf.o |
| 108 | 92 | always-y += tracex5.bpf.o |
| 109 | 93 | always-y += tracex6.bpf.o |
| 110 | −always-y += tracex7.bpf.o | |
| 111 | −always-y += sock_flags.bpf.o | |
| 112 | −always-y += test_probe_write_user.bpf.o | |
| 113 | 94 | always-y += trace_output.bpf.o |
| 114 | 95 | always-y += tcbpf1_kern.o |
| 115 | 96 | always-y += tc_l2_redirect_kern.o |
| @@ -117,12 +98,7 @@ always-y += lathist_kern.o · 1 unmodified line | ||
| 117 | 98 | always-y += offwaketime.bpf.o |
| 118 | 99 | always-y += spintest.bpf.o |
| 119 | 100 | always-y += map_perf_test.bpf.o |
| 120 | −always-y += test_overhead_tp.bpf.o | |
| 121 | −always-y += test_overhead_raw_tp.bpf.o | |
| 122 | −always-y += test_overhead_kprobe.bpf.o | |
| 123 | 101 | always-y += parse_varlen.o parse_simple.o parse_ldabs.o |
| 124 | −always-y += test_cgrp2_tc.bpf.o | |
| 125 | −always-y += test_current_task_under_cgroup.bpf.o | |
| 126 | 102 | always-y += trace_event_kern.o |
| 127 | 103 | always-y += sampleip_kern.o |
| 128 | 104 | always-y += lwt_len_hist.bpf.o |
| @@ -195,7 +171,6 @@ TPROGLDLIBS_xdp_router_ipv4 += -lm -pthread · 66 unmodified lines | ||
| 195 | 171 | TPROGLDLIBS_tracex4 += -lrt |
| 196 | 172 | TPROGLDLIBS_trace_output += -lrt |
| 197 | 173 | TPROGLDLIBS_map_perf_test += -lrt |
| 198 | −TPROGLDLIBS_test_overhead += -lrt | |
| 199 | 174 | |
| 200 | 175 | # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: |
| 201 | 176 | # make M=samples/bpf LLC=~/git/llvm-project/llvm/build/bin/llc CLANG=~/git/llvm-project/llvm/build/bin/clang |
| @@ -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 | − | |
| 6 | −SEC("cgroup/sock") | |
| 7 | −int 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 | − | |
| 29 | −SEC("cgroup/sock") | |
| 30 | −int 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 | − | |
| 47 | −char _license[] SEC("license") = "GPL"; | |
| @@ -2,6 +2,9 @@ · 1 unmodified line | ||
| 2 | 2 | #include <uapi/linux/unistd.h> |
| 3 | 3 | #include <linux/kbuild.h> |
| 4 | 4 | |
| 5 | +#pragma GCC diagnostic push | |
| 6 | +#pragma GCC diagnostic ignored "-Wmissing-prototypes" | |
| 7 | + | |
| 5 | 8 | #define SYSNR(_NR) DEFINE(SYS ## _NR, _NR) |
| 6 | 9 | |
| 7 | 10 | void syscall_defines(void) |
| @@ -17,3 +20,5 @@ void syscall_defines(void) · 9 unmodified lines | ||
| 17 | 20 | #endif |
| 18 | 21 | |
| 19 | 22 | } |
| 23 | + | |
| 24 | +#pragma GCC diagnostic pop | |
| @@ -58,14 +58,11 @@ static __always_inline bool is_vip_addr(__be16 eth_proto, __be32 daddr) · 57 unmodified lines | ||
| 58 | 58 | SEC("l2_to_iptun_ingress_forward") |
| 59 | 59 | int _l2_to_iptun_ingress_forward(struct __sk_buff *skb) |
| 60 | 60 | { |
| 61 | − struct bpf_tunnel_key tkey = {}; | |
| 62 | 61 | void *data = (void *)(long)skb->data; |
| 63 | 62 | struct eth_hdr *eth = data; |
| 64 | 63 | void *data_end = (void *)(long)skb->data_end; |
| 65 | 64 | int key = 0, *ifindex; |
| 66 | 65 | |
| 67 | − int ret; | |
| 68 | − | |
| 69 | 66 | if (data + sizeof(*eth) > data_end) |
| 70 | 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 | 112 | void *data_end = (void *)(long)skb->data_end; |
| 116 | 113 | int key = 0, *ifindex; |
| 117 | 114 | |
| 118 | − int ret; | |
| 119 | − | |
| 120 | 115 | if (data + sizeof(*eth) > data_end) |
| 121 | 116 | return TC_ACT_OK; |
| 122 | 117 | |
| @@ -205,7 +200,6 @@ int _l2_to_ip6tun_ingress_redirect(struct __sk_buff *skb) · 82 unmodified lines | ||
| 205 | 200 | SEC("drop_non_tun_vip") |
| 206 | 201 | int _drop_non_tun_vip(struct __sk_buff *skb) |
| 207 | 202 | { |
| 208 | − struct bpf_tunnel_key tkey = {}; | |
| 209 | 203 | void *data = (void *)(long)skb->data; |
| 210 | 204 | struct eth_hdr *eth = data; |
| 211 | 205 | void *data_end = (void *)(long)skb->data_end; |
| @@ -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 | − | |
| 16 | −static 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 | − | |
| 25 | −int 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 | − | |
| 100 | −out: | |
| 101 | − if (array_fd != -1) | |
| 102 | − close(array_fd); | |
| 103 | − if (cg2_fd != -1) | |
| 104 | − close(cg2_fd); | |
| 105 | − return ret; | |
| 106 | −} | |
| @@ -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 | − | |
| 36 | −enum { | |
| 37 | − MAP_KEY_PACKETS, | |
| 38 | − MAP_KEY_BYTES, | |
| 39 | −}; | |
| 40 | − | |
| 41 | −char bpf_log_buf[BPF_LOG_BUF_SIZE]; | |
| 42 | − | |
| 43 | −static 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 | − | |
| 84 | −static 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 | − | |
| 92 | −static 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 | − | |
| 134 | −int 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 | −} | |
| @@ -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 | − | |
| 28 | −char bpf_log_buf[BPF_LOG_BUF_SIZE]; | |
| 29 | − | |
| 30 | −static 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 | − | |
| 130 | −static 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 | − | |
| 143 | −static 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 | − | |
| 156 | −static 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 | − | |
| 169 | −static 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 | − | |
| 194 | −static 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 | − | |
| 208 | −int 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 | −} | |
| @@ -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 | − | |
| 6 | −MY_DIR=$(dirname $0) | |
| 7 | −TEST=$MY_DIR/test_cgrp2_sock | |
| 8 | −CGRP_MNT="/tmp/cgroupv2-test_cgrp2_sock" | |
| 9 | − | |
| 10 | −################################################################################ | |
| 11 | −# | |
| 12 | −print_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 | − | |
| 22 | −check_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 | − | |
| 36 | −check_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 | − | |
| 53 | −cleanup() | |
| 54 | −{ | |
| 55 | − echo $$ >> ${CGRP_MNT}/cgroup.procs | |
| 56 | − rmdir ${CGRP_MNT}/sockopts | |
| 57 | −} | |
| 58 | − | |
| 59 | −cleanup_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 | − | |
| 77 | −rc=0 | |
| 78 | − | |
| 79 | −ip li add cgrp2_sock type dummy 2>/dev/null | |
| 80 | − | |
| 81 | −set -e | |
| 82 | −mkdir -p ${CGRP_MNT} | |
| 83 | −mount -t cgroup2 none ${CGRP_MNT} | |
| 84 | −set +e | |
| 85 | − | |
| 86 | − | |
| 87 | −# make sure we have a known start point | |
| 88 | −cleanup 2>/dev/null | |
| 89 | − | |
| 90 | −mkdir -p ${CGRP_MNT}/sockopts | |
| 91 | −[ $? -ne 0 ] && cleanup_and_exit 1 "Failed to create cgroup hierarchy" | |
| 92 | − | |
| 93 | − | |
| 94 | −# set pid into cgroup | |
| 95 | −echo $$ > ${CGRP_MNT}/sockopts/cgroup.procs | |
| 96 | − | |
| 97 | −# no bpf program attached, so socket should show no settings | |
| 98 | −check_sock "dev , mark 0, priority 0" "No programs attached" | |
| 99 | −check_sock6 "dev , mark 0, priority 0" "No programs attached" | |
| 100 | − | |
| 101 | −# verify device is set | |
| 102 | −# | |
| 103 | −$TEST -b cgrp2_sock ${CGRP_MNT}/sockopts | |
| 104 | −if [ $? -ne 0 ]; then | |
| 105 | − cleanup_and_exit 1 "Failed to install program to set device" | |
| 106 | −fi | |
| 107 | −check_sock "dev cgrp2_sock, mark 0, priority 0" "Device set" | |
| 108 | −check_sock6 "dev cgrp2_sock, mark 0, priority 0" "Device set" | |
| 109 | − | |
| 110 | −# verify mark is set | |
| 111 | −# | |
| 112 | −$TEST -m 666 ${CGRP_MNT}/sockopts | |
| 113 | −if [ $? -ne 0 ]; then | |
| 114 | − cleanup_and_exit 1 "Failed to install program to set mark" | |
| 115 | −fi | |
| 116 | −check_sock "dev , mark 666, priority 0" "Mark set" | |
| 117 | −check_sock6 "dev , mark 666, priority 0" "Mark set" | |
| 118 | − | |
| 119 | −# verify priority is set | |
| 120 | −# | |
| 121 | −$TEST -p 123 ${CGRP_MNT}/sockopts | |
| 122 | −if [ $? -ne 0 ]; then | |
| 123 | − cleanup_and_exit 1 "Failed to install program to set priority" | |
| 124 | −fi | |
| 125 | −check_sock "dev , mark 0, priority 123" "Priority set" | |
| 126 | −check_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 | |
| 131 | −if [ $? -ne 0 ]; then | |
| 132 | − cleanup_and_exit 1 "Failed to install program to set device, mark and priority" | |
| 133 | −fi | |
| 134 | −check_sock "dev cgrp2_sock, mark 666, priority 123" "Priority set" | |
| 135 | −check_sock6 "dev cgrp2_sock, mark 666, priority 123" "Priority set" | |
| 136 | − | |
| 137 | −cleanup_and_exit $rc | |
| @@ -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 | − | |
| 27 | −static int usage(const char *argv0) | |
| 28 | −{ | |
| 29 | − printf("Usage: %s cg-path filter-path [filter-id]\n", argv0); | |
| 30 | − return EXIT_FAILURE; | |
| 31 | −} | |
| 32 | − | |
| 33 | −int 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 | − | |
| 91 | −cleanup: | |
| 92 | − bpf_link__destroy(link); | |
| 93 | − bpf_object__close(obj); | |
| 94 | − return ret; | |
| 95 | −} | |
| @@ -1,103 +0,0 @@ | ||
| 1 | −#!/bin/bash | |
| 2 | −# SPDX-License-Identifier: GPL-2.0 | |
| 3 | − | |
| 4 | −BPFFS=/sys/fs/bpf | |
| 5 | −MY_DIR=$(dirname $0) | |
| 6 | −TEST=$MY_DIR/test_cgrp2_sock2 | |
| 7 | −LINK_PIN=$BPFFS/test_cgrp2_sock2 | |
| 8 | −BPF_PROG=$MY_DIR/sock_flags.bpf.o | |
| 9 | − | |
| 10 | −function 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 | − | |
| 24 | −function 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 | − | |
| 32 | −function 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 | − | |
| 41 | −function attach_bpf { | |
| 42 | − $TEST /tmp/cgroupv2/foo $BPF_PROG $1 | |
| 43 | − [ $? -ne 0 ] && exit 1 | |
| 44 | −} | |
| 45 | − | |
| 46 | −function 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 | − | |
| 54 | −cleanup 2>/dev/null | |
| 55 | − | |
| 56 | −set -e | |
| 57 | −config_device | |
| 58 | −config_cgroup | |
| 59 | −config_bpffs | |
| 60 | −set +e | |
| 61 | − | |
| 62 | −# | |
| 63 | −# Test 1 - fail ping6 | |
| 64 | −# | |
| 65 | −attach_bpf 0 | |
| 66 | −ping -c1 -w1 172.16.1.100 | |
| 67 | −if [ $? -ne 0 ]; then | |
| 68 | − echo "ping failed when it should succeed" | |
| 69 | − cleanup | |
| 70 | − exit 1 | |
| 71 | −fi | |
| 72 | − | |
| 73 | −ping6 -c1 -w1 2401:db00::1 | |
| 74 | −if [ $? -eq 0 ]; then | |
| 75 | − echo "ping6 succeeded when it should not" | |
| 76 | − cleanup | |
| 77 | − exit 1 | |
| 78 | −fi | |
| 79 | − | |
| 80 | −rm -rf $LINK_PIN | |
| 81 | −sleep 1 # Wait for link detach | |
| 82 | − | |
| 83 | −# | |
| 84 | −# Test 2 - fail ping | |
| 85 | −# | |
| 86 | −attach_bpf 1 | |
| 87 | −ping6 -c1 -w1 2401:db00::1 | |
| 88 | −if [ $? -ne 0 ]; then | |
| 89 | − echo "ping6 failed when it should succeed" | |
| 90 | − cleanup | |
| 91 | − exit 1 | |
| 92 | −fi | |
| 93 | − | |
| 94 | −ping -c1 -w1 172.16.1.100 | |
| 95 | −if [ $? -eq 0 ]; then | |
| 96 | − echo "ping succeeded when it should not" | |
| 97 | − cleanup | |
| 98 | − exit 1 | |
| 99 | −fi | |
| 100 | − | |
| 101 | −cleanup | |
| 102 | −echo | |
| 103 | −echo "*** PASS ***" | |
| @@ -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 */ | |
| 13 | −struct eth_hdr { | |
| 14 | − unsigned char h_dest[ETH_ALEN]; | |
| 15 | − unsigned char h_source[ETH_ALEN]; | |
| 16 | − unsigned short h_proto; | |
| 17 | −}; | |
| 18 | − | |
| 19 | −struct { | |
| 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 | − | |
| 27 | −SEC("filter") | |
| 28 | −int 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 | − | |
| 56 | −char _license[] SEC("license") = "GPL"; | |
| @@ -1,187 +0,0 @@ | ||
| 1 | −#!/bin/bash | |
| 2 | −# SPDX-License-Identifier: GPL-2.0 | |
| 3 | − | |
| 4 | −MY_DIR=$(dirname $0) | |
| 5 | −# Details on the bpf prog | |
| 6 | −BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin' | |
| 7 | −BPF_PROG="$MY_DIR/test_cgrp2_tc.bpf.o" | |
| 8 | −BPF_SECTION='filter' | |
| 9 | − | |
| 10 | −[ -z "$TC" ] && TC='tc' | |
| 11 | −[ -z "$IP" ] && IP='ip' | |
| 12 | − | |
| 13 | −# Names of the veth interface, net namespace...etc. | |
| 14 | −HOST_IFC='ve' | |
| 15 | −NS_IFC='vens' | |
| 16 | −NS='ns' | |
| 17 | − | |
| 18 | −find_mnt() { | |
| 19 | − cat /proc/mounts | \ | |
| 20 | − awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' | |
| 21 | −} | |
| 22 | − | |
| 23 | −# Init cgroup2 vars | |
| 24 | −init_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 | |
| 36 | −init_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 | − | |
| 42 | −setup_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 | − | |
| 59 | −setup_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 | − | |
| 71 | −setup_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 | − | |
| 94 | −run_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 | − | |
| 102 | −do_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 | − | |
| 116 | −do_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 | − | |
| 147 | −init_cgrp2_vars | |
| 148 | −init_bpf_fs_vars | |
| 149 | − | |
| 150 | −while [[ $# -ge 1 ]] | |
| 151 | −do | |
| 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 | |
| 176 | −done | |
| 177 | − | |
| 178 | −trap do_exit 0 | |
| 179 | − | |
| 180 | −[ "$MODE" == 'cleanuponly' ] && exit | |
| 181 | − | |
| 182 | −setup_cgrp2 start || exit $? | |
| 183 | −setup_net start || exit $? | |
| 184 | −init_bpf_fs_vars || exit $? | |
| 185 | −setup_bpf_cgrp2_array start || exit $? | |
| 186 | −do_test | |
| 187 | −echo | |
| @@ -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 | − | |
| 14 | −struct { | |
| 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 | − | |
| 21 | −struct { | |
| 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 */ | |
| 29 | −SEC("ksyscall/sync") | |
| 30 | −int 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 | − | |
| 42 | −char _license[] SEC("license") = "GPL"; | |
| 43 | −u32 _version SEC("version") = LINUX_VERSION_CODE; | |
| @@ -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 | − | |
| 14 | −int 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 | − | |
| 105 | −err: | |
| 106 | − if (cg2 != -1) | |
| 107 | − close(cg2); | |
| 108 | − | |
| 109 | − cleanup_cgroup_environment(); | |
| 110 | − | |
| 111 | −cleanup: | |
| 112 | − bpf_link__destroy(link); | |
| 113 | − bpf_object__close(obj); | |
| 114 | − return rc; | |
| 115 | −} | |
| @@ -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 | − | |
| 13 | −SEC("kprobe/__set_task_comm") | |
| 14 | −int 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 | − | |
| 34 | −SEC("kprobe/fib_table_lookup") | |
| 35 | −int prog2(struct pt_regs *ctx) | |
| 36 | −{ | |
| 37 | − return 0; | |
| 38 | −} | |
| 39 | − | |
| 40 | −char _license[] SEC("license") = "GPL"; | |
| 41 | −u32 _version SEC("version") = LINUX_VERSION_CODE; | |
| @@ -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 | − | |
| 6 | −SEC("raw_tracepoint/task_rename") | |
| 7 | −int prog(struct bpf_raw_tracepoint_args *ctx) | |
| 8 | −{ | |
| 9 | − return 0; | |
| 10 | −} | |
| 11 | − | |
| 12 | −SEC("raw_tracepoint/fib_table_lookup") | |
| 13 | −int prog2(struct bpf_raw_tracepoint_args *ctx) | |
| 14 | −{ | |
| 15 | − return 0; | |
| 16 | −} | |
| 17 | −char _license[] SEC("license") = "GPL"; | |
| @@ -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 */ | |
| 11 | −SEC("tracepoint/task/task_rename") | |
| 12 | −int 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 */ | |
| 18 | −SEC("tracepoint/fib/fib_table_lookup") | |
| 19 | −int prog2(struct trace_event_raw_fib_table_lookup *ctx) | |
| 20 | −{ | |
| 21 | − return 0; | |
| 22 | −} | |
| 23 | −char _license[] SEC("license") = "GPL"; | |
| @@ -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 | − | |
| 28 | −static struct bpf_link *links[2]; | |
| 29 | −static struct bpf_object *obj; | |
| 30 | −static int cnt; | |
| 31 | − | |
| 32 | −static __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 | − | |
| 40 | −static 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 | − | |
| 64 | −static 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 | − | |
| 94 | −static 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 | − | |
| 108 | −static 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 | − | |
| 131 | −static 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 | − | |
| 164 | −static void unload_progs(void) | |
| 165 | −{ | |
| 166 | − while (cnt) | |
| 167 | − bpf_link__destroy(links[--cnt]); | |
| 168 | − | |
| 169 | − bpf_object__close(obj); | |
| 170 | −} | |
| 171 | − | |
| 172 | −int 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 | −} | |
| @@ -1,16 +0,0 @@ | ||
| 1 | −#!/bin/bash | |
| 2 | − | |
| 3 | −rm -r tmpmnt | |
| 4 | −rm -f testfile.img | |
| 5 | −dd if=/dev/zero of=testfile.img bs=1M seek=1000 count=1 | |
| 6 | −DEVICE=$(losetup --show -f testfile.img) | |
| 7 | −mkfs.btrfs -f $DEVICE | |
| 8 | −mkdir tmpmnt | |
| 9 | −./tracex7 $DEVICE | |
| 10 | −if [ $? -eq 0 ] | |
| 11 | −then | |
| 12 | − echo "SUCCESS!" | |
| 13 | −else | |
| 14 | − echo "FAILED!" | |
| 15 | −fi | |
| 16 | −losetup -d $DEVICE | |
| @@ -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 | − | |
| 14 | −struct { | |
| 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 | − */ | |
| 29 | −SEC("ksyscall/connect") | |
| 30 | −int 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 | − | |
| 51 | −char _license[] SEC("license") = "GPL"; | |
| 52 | −u32 _version SEC("version") = LINUX_VERSION_CODE; | |
| @@ -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 | − | |
| 11 | −int 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 | − | |
| 104 | −cleanup: | |
| 105 | − bpf_link__destroy(link); | |
| 106 | − bpf_object__close(obj); | |
| 107 | − return 0; | |
| 108 | −} | |
| @@ -1,15 +0,0 @@ | ||
| 1 | −#include "vmlinux.h" | |
| 2 | −#include <linux/version.h> | |
| 3 | −#include <bpf/bpf_helpers.h> | |
| 4 | − | |
| 5 | −SEC("kprobe/open_ctree") | |
| 6 | −int bpf_prog1(struct pt_regs *ctx) | |
| 7 | −{ | |
| 8 | − unsigned long rc = -12; | |
| 9 | − | |
| 10 | − bpf_override_return(ctx, rc); | |
| 11 | − return 0; | |
| 12 | −} | |
| 13 | − | |
| 14 | −char _license[] SEC("license") = "GPL"; | |
| 15 | −u32 _version SEC("version") = LINUX_VERSION_CODE; | |
| @@ -1,56 +0,0 @@ | ||
| 1 | −#define _GNU_SOURCE | |
| 2 | − | |
| 3 | −#include <stdio.h> | |
| 4 | −#include <unistd.h> | |
| 5 | −#include <bpf/libbpf.h> | |
| 6 | − | |
| 7 | −int 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 | − | |
| 52 | −cleanup: | |
| 53 | − bpf_link__destroy(link); | |
| 54 | − bpf_object__close(obj); | |
| 55 | − return ret ? 0 : 1; | |
| 56 | −} | |
| @@ -32,7 +32,7 @@ SEC("xdp_mark") · 31 unmodified lines | ||
| 32 | 32 | int _xdp_mark(struct xdp_md *ctx) |
| 33 | 33 | { |
| 34 | 34 | struct meta_info *meta; |
| 35 | − void *data, *data_end; | |
| 35 | + void *data; | |
| 36 | 36 | int ret; |
| 37 | 37 | |
| 38 | 38 | /* Reserve space in-front of data pointer for our meta info. |
| @@ -57,6 +57,7 @@ static __always_inline void swap_mac(void *data, struct ethhdr *orig_eth) · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | static __always_inline __u16 csum_fold_helper(__u32 csum) |
| 59 | 59 | { |
| 60 | + csum = (csum & 0xffff) + (csum >> 16); | |
| 60 | 61 | return ~((csum & 0xffff) + (csum >> 16)); |
| 61 | 62 | } |
| 62 | 63 | |