1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <vmlinux.h> 4 #include "xdp_metadata.h" 5 #include <bpf/bpf_helpers.h> 6 #include <bpf/bpf_endian.h> 7 8 struct { 9 __uint(type, BPF_MAP_TYPE_XSKMAP); 10 __uint(max_entries, 256); 11 __type(key, __u32); 12 __type(value, __u32); 13 } xsk SEC(".maps"); 14 15 __u64 pkts_skip = 0; 16 __u64 pkts_fail = 0; 17 __u64 pkts_redir = 0; 18 19 extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, 20 __u64 *timestamp) __ksym; 21 extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash, 22 enum xdp_rss_hash_type *rss_type) __ksym; 23 24 SEC("xdp.frags") 25 int rx(struct xdp_md *ctx) 26 { 27 void *data, *data_meta, *data_end; 28 struct ipv6hdr *ip6h = NULL; 29 struct ethhdr *eth = NULL; 30 struct udphdr *udp = NULL; 31 struct iphdr *iph = NULL; 32 struct xdp_meta *meta; 33 int err; 34 35 data = (void *)(long)ctx->data; 36 data_end = (void *)(long)ctx->data_end; 37 eth = data; 38 if (eth + 1 < data_end) { 39 if (eth->h_proto == bpf_htons(ETH_P_IP)) { 40 iph = (void *)(eth + 1); 41 if (iph + 1 < data_end && iph->protocol == IPPROTO_UDP) 42 udp = (void *)(iph + 1); 43 } 44 if (eth->h_proto == bpf_htons(ETH_P_IPV6)) { 45 ip6h = (void *)(eth + 1); 46 if (ip6h + 1 < data_end && ip6h->nexthdr == IPPROTO_UDP) 47 udp = (void *)(ip6h + 1); 48 } 49 if (udp && udp + 1 > data_end) 50 udp = NULL; 51 } 52 53 if (!udp) { 54 __sync_add_and_fetch(&pkts_skip, 1); 55 return XDP_PASS; 56 } 57 58 /* Forwarding UDP:9091 to AF_XDP */ 59 if (udp->dest != bpf_htons(9091)) { 60 __sync_add_and_fetch(&pkts_skip, 1); 61 return XDP_PASS; 62 } 63 64 err = bpf_xdp_adjust_meta(ctx, -(int)sizeof(struct xdp_meta)); 65 if (err) { 66 __sync_add_and_fetch(&pkts_fail, 1); 67 return XDP_PASS; 68 } 69 70 data = (void *)(long)ctx->data; 71 data_meta = (void *)(long)ctx->data_meta; 72 meta = data_meta; 73 74 if (meta + 1 > data) { 75 __sync_add_and_fetch(&pkts_fail, 1); 76 return XDP_PASS; 77 } 78 79 err = bpf_xdp_metadata_rx_timestamp(ctx, &meta->rx_timestamp); 80 if (!err) 81 meta->xdp_timestamp = bpf_ktime_get_tai_ns(); 82 else 83 meta->rx_timestamp = 0; /* Used by AF_XDP as not avail signal */ 84 85 err = bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash, &meta->rx_hash_type); 86 if (err < 0) 87 meta->rx_hash_err = err; /* Used by AF_XDP as no hash signal */ 88 89 __sync_add_and_fetch(&pkts_redir, 1); 90 return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS); 91 } 92 93 char _license[] SEC("license") = "GPL"; 94