~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/samples/bpf/test_lwt_bpf.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
  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  * This program is distributed in the hope that it will be useful, but
  8  * WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 10  * General Public License for more details.
 11  */
 12 
 13 #include "vmlinux.h"
 14 #include "net_shared.h"
 15 #include <bpf/bpf_helpers.h>
 16 #include <string.h>
 17 
 18 # define printk(fmt, ...)                                               \
 19                 ({                                                      \
 20                         char ____fmt[] = fmt;                           \
 21                         bpf_trace_printk(____fmt, sizeof(____fmt),      \
 22                                      ##__VA_ARGS__);                    \
 23                 })
 24 
 25 #define CB_MAGIC 1234
 26 
 27 /* Test: Pass all packets through */
 28 SEC("nop")
 29 int do_nop(struct __sk_buff *skb)
 30 {
 31         return BPF_OK;
 32 }
 33 
 34 /* Test: Verify context information can be accessed */
 35 SEC("test_ctx")
 36 int do_test_ctx(struct __sk_buff *skb)
 37 {
 38         skb->cb[0] = CB_MAGIC;
 39         printk("len %d hash %d protocol %d", skb->len, skb->hash,
 40                skb->protocol);
 41         printk("cb %d ingress_ifindex %d ifindex %d", skb->cb[0],
 42                skb->ingress_ifindex, skb->ifindex);
 43 
 44         return BPF_OK;
 45 }
 46 
 47 /* Test: Ensure skb->cb[] buffer is cleared */
 48 SEC("test_cb")
 49 int do_test_cb(struct __sk_buff *skb)
 50 {
 51         printk("cb0: %x cb1: %x cb2: %x", skb->cb[0], skb->cb[1],
 52                skb->cb[2]);
 53         printk("cb3: %x cb4: %x", skb->cb[3], skb->cb[4]);
 54 
 55         return BPF_OK;
 56 }
 57 
 58 /* Test: Verify skb data can be read */
 59 SEC("test_data")
 60 int do_test_data(struct __sk_buff *skb)
 61 {
 62         void *data = (void *)(long)skb->data;
 63         void *data_end = (void *)(long)skb->data_end;
 64         struct iphdr *iph = data;
 65 
 66         if (data + sizeof(*iph) > data_end) {
 67                 printk("packet truncated");
 68                 return BPF_DROP;
 69         }
 70 
 71         printk("src: %x dst: %x", iph->saddr, iph->daddr);
 72 
 73         return BPF_OK;
 74 }
 75 
 76 #define IP_CSUM_OFF offsetof(struct iphdr, check)
 77 #define IP_DST_OFF offsetof(struct iphdr, daddr)
 78 #define IP_SRC_OFF offsetof(struct iphdr, saddr)
 79 #define IP_PROTO_OFF offsetof(struct iphdr, protocol)
 80 #define TCP_CSUM_OFF offsetof(struct tcphdr, check)
 81 #define UDP_CSUM_OFF offsetof(struct udphdr, check)
 82 #define IS_PSEUDO 0x10
 83 
 84 static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip,
 85                           uint32_t new_ip, int rw_daddr)
 86 {
 87         int ret, off = 0, flags = IS_PSEUDO;
 88         uint8_t proto;
 89 
 90         ret = bpf_skb_load_bytes(skb, IP_PROTO_OFF, &proto, 1);
 91         if (ret < 0) {
 92                 printk("bpf_l4_csum_replace failed: %d", ret);
 93                 return BPF_DROP;
 94         }
 95 
 96         switch (proto) {
 97         case IPPROTO_TCP:
 98                 off = TCP_CSUM_OFF;
 99                 break;
100 
101         case IPPROTO_UDP:
102                 off = UDP_CSUM_OFF;
103                 flags |= BPF_F_MARK_MANGLED_0;
104                 break;
105 
106         case IPPROTO_ICMPV6:
107                 off = offsetof(struct icmp6hdr, icmp6_cksum);
108                 break;
109         }
110 
111         if (off) {
112                 ret = bpf_l4_csum_replace(skb, off, old_ip, new_ip,
113                                           flags | sizeof(new_ip));
114                 if (ret < 0) {
115                         printk("bpf_l4_csum_replace failed: %d");
116                         return BPF_DROP;
117                 }
118         }
119 
120         ret = bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip));
121         if (ret < 0) {
122                 printk("bpf_l3_csum_replace failed: %d", ret);
123                 return BPF_DROP;
124         }
125 
126         if (rw_daddr)
127                 ret = bpf_skb_store_bytes(skb, IP_DST_OFF, &new_ip, sizeof(new_ip), 0);
128         else
129                 ret = bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0);
130 
131         if (ret < 0) {
132                 printk("bpf_skb_store_bytes() failed: %d", ret);
133                 return BPF_DROP;
134         }
135 
136         return BPF_OK;
137 }
138 
139 /* Test: Verify skb data can be modified */
140 SEC("test_rewrite")
141 int do_test_rewrite(struct __sk_buff *skb)
142 {
143         uint32_t old_ip, new_ip = 0x3fea8c0;
144         int ret;
145 
146         ret = bpf_skb_load_bytes(skb, IP_DST_OFF, &old_ip, 4);
147         if (ret < 0) {
148                 printk("bpf_skb_load_bytes failed: %d", ret);
149                 return BPF_DROP;
150         }
151 
152         if (old_ip == 0x2fea8c0) {
153                 printk("out: rewriting from %x to %x", old_ip, new_ip);
154                 return rewrite(skb, old_ip, new_ip, 1);
155         }
156 
157         return BPF_OK;
158 }
159 
160 static inline int __do_push_ll_and_redirect(struct __sk_buff *skb)
161 {
162         uint64_t smac = SRC_MAC, dmac = DST_MAC;
163         int ret, ifindex = DST_IFINDEX;
164         struct ethhdr ehdr;
165 
166         ret = bpf_skb_change_head(skb, 14, 0);
167         if (ret < 0) {
168                 printk("skb_change_head() failed: %d", ret);
169         }
170 
171         ehdr.h_proto = bpf_htons(ETH_P_IP);
172         memcpy(&ehdr.h_source, &smac, 6);
173         memcpy(&ehdr.h_dest, &dmac, 6);
174 
175         ret = bpf_skb_store_bytes(skb, 0, &ehdr, sizeof(ehdr), 0);
176         if (ret < 0) {
177                 printk("skb_store_bytes() failed: %d", ret);
178                 return BPF_DROP;
179         }
180 
181         return bpf_redirect(ifindex, 0);
182 }
183 
184 SEC("push_ll_and_redirect_silent")
185 int do_push_ll_and_redirect_silent(struct __sk_buff *skb)
186 {
187         return __do_push_ll_and_redirect(skb);
188 }
189 
190 SEC("push_ll_and_redirect")
191 int do_push_ll_and_redirect(struct __sk_buff *skb)
192 {
193         int ret, ifindex = DST_IFINDEX;
194 
195         ret = __do_push_ll_and_redirect(skb);
196         if (ret >= 0)
197                 printk("redirected to %d", ifindex);
198 
199         return ret;
200 }
201 
202 static inline void __fill_garbage(struct __sk_buff *skb)
203 {
204         uint64_t f = 0xFFFFFFFFFFFFFFFF;
205 
206         bpf_skb_store_bytes(skb, 0, &f, sizeof(f), 0);
207         bpf_skb_store_bytes(skb, 8, &f, sizeof(f), 0);
208         bpf_skb_store_bytes(skb, 16, &f, sizeof(f), 0);
209         bpf_skb_store_bytes(skb, 24, &f, sizeof(f), 0);
210         bpf_skb_store_bytes(skb, 32, &f, sizeof(f), 0);
211         bpf_skb_store_bytes(skb, 40, &f, sizeof(f), 0);
212         bpf_skb_store_bytes(skb, 48, &f, sizeof(f), 0);
213         bpf_skb_store_bytes(skb, 56, &f, sizeof(f), 0);
214         bpf_skb_store_bytes(skb, 64, &f, sizeof(f), 0);
215         bpf_skb_store_bytes(skb, 72, &f, sizeof(f), 0);
216         bpf_skb_store_bytes(skb, 80, &f, sizeof(f), 0);
217         bpf_skb_store_bytes(skb, 88, &f, sizeof(f), 0);
218 }
219 
220 SEC("fill_garbage")
221 int do_fill_garbage(struct __sk_buff *skb)
222 {
223         __fill_garbage(skb);
224         printk("Set initial 96 bytes of header to FF");
225         return BPF_OK;
226 }
227 
228 SEC("fill_garbage_and_redirect")
229 int do_fill_garbage_and_redirect(struct __sk_buff *skb)
230 {
231         int ifindex = DST_IFINDEX;
232         __fill_garbage(skb);
233         printk("redirected to %d", ifindex);
234         return bpf_redirect(ifindex, 0);
235 }
236 
237 /* Drop all packets */
238 SEC("drop_all")
239 int do_drop_all(struct __sk_buff *skb)
240 {
241         printk("dropping with: %d", BPF_DROP);
242         return BPF_DROP;
243 }
244 
245 char _license[] SEC("license") = "GPL";
246 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php