1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2020 Cloudflare 3 4 #include <errno.h> 5 #include <stdbool.h> 6 #include <linux/bpf.h> 7 8 #include <bpf/bpf_helpers.h> 9 10 struct { 11 __uint(type, BPF_MAP_TYPE_SOCKMAP); 12 __uint(max_entries, 2); 13 __type(key, __u32); 14 __type(value, __u64); 15 } sock_map SEC(".maps"); 16 17 struct { 18 __uint(type, BPF_MAP_TYPE_SOCKHASH); 19 __uint(max_entries, 2); 20 __type(key, __u32); 21 __type(value, __u64); 22 } sock_hash SEC(".maps"); 23 24 struct { 25 __uint(type, BPF_MAP_TYPE_ARRAY); 26 __uint(max_entries, 2); 27 __type(key, int); 28 __type(value, unsigned int); 29 } verdict_map SEC(".maps"); 30 31 struct { 32 __uint(type, BPF_MAP_TYPE_ARRAY); 33 __uint(max_entries, 1); 34 __type(key, int); 35 __type(value, int); 36 } parser_map SEC(".maps"); 37 38 bool test_sockmap = false; /* toggled by user-space */ 39 bool test_ingress = false; /* toggled by user-space */ 40 41 SEC("sk_skb/stream_parser") 42 int prog_stream_parser(struct __sk_buff *skb) 43 { 44 int *value; 45 __u32 key = 0; 46 47 value = bpf_map_lookup_elem(&parser_map, &key); 48 if (value && *value) 49 return *value; 50 51 return skb->len; 52 } 53 54 SEC("sk_skb/stream_verdict") 55 int prog_stream_verdict(struct __sk_buff *skb) 56 { 57 unsigned int *count; 58 __u32 zero = 0; 59 int verdict; 60 61 if (test_sockmap) 62 verdict = bpf_sk_redirect_map(skb, &sock_map, zero, 0); 63 else 64 verdict = bpf_sk_redirect_hash(skb, &sock_hash, &zero, 0); 65 66 count = bpf_map_lookup_elem(&verdict_map, &verdict); 67 if (count) 68 (*count)++; 69 70 return verdict; 71 } 72 73 SEC("sk_skb") 74 int prog_skb_verdict(struct __sk_buff *skb) 75 { 76 unsigned int *count; 77 __u32 zero = 0; 78 int verdict; 79 80 if (test_sockmap) 81 verdict = bpf_sk_redirect_map(skb, &sock_map, zero, 82 test_ingress ? BPF_F_INGRESS : 0); 83 else 84 verdict = bpf_sk_redirect_hash(skb, &sock_hash, &zero, 85 test_ingress ? BPF_F_INGRESS : 0); 86 87 count = bpf_map_lookup_elem(&verdict_map, &verdict); 88 if (count) 89 (*count)++; 90 91 return verdict; 92 } 93 94 SEC("sk_msg") 95 int prog_msg_verdict(struct sk_msg_md *msg) 96 { 97 unsigned int *count; 98 __u32 zero = 0; 99 int verdict; 100 101 if (test_sockmap) 102 verdict = bpf_msg_redirect_map(msg, &sock_map, zero, 0); 103 else 104 verdict = bpf_msg_redirect_hash(msg, &sock_hash, &zero, 0); 105 106 count = bpf_map_lookup_elem(&verdict_map, &verdict); 107 if (count) 108 (*count)++; 109 110 return verdict; 111 } 112 113 SEC("sk_reuseport") 114 int prog_reuseport(struct sk_reuseport_md *reuse) 115 { 116 unsigned int *count; 117 int err, verdict; 118 __u32 zero = 0; 119 120 if (test_sockmap) 121 err = bpf_sk_select_reuseport(reuse, &sock_map, &zero, 0); 122 else 123 err = bpf_sk_select_reuseport(reuse, &sock_hash, &zero, 0); 124 verdict = err ? SK_DROP : SK_PASS; 125 126 count = bpf_map_lookup_elem(&verdict_map, &verdict); 127 if (count) 128 (*count)++; 129 130 return verdict; 131 } 132 133 char _license[] SEC("license") = "GPL"; 134