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 extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, 16 __u64 *timestamp) __ksym; 17 extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, 18 __u32 *hash) __ksym; 19 20 SEC("xdp") 21 int rx(struct xdp_md *ctx) 22 { 23 void *data, *data_meta, *data_end; 24 struct ipv6hdr *ip6h = NULL; 25 struct ethhdr *eth = NULL; 26 struct udphdr *udp = NULL; 27 struct iphdr *iph = NULL; 28 struct xdp_meta *meta; 29 int ret; 30 31 data = (void *)(long)ctx->data; 32 data_end = (void *)(long)ctx->data_end; 33 eth = data; 34 if (eth + 1 < data_end) { 35 if (eth->h_proto == bpf_htons(ETH_P_IP)) { 36 iph = (void *)(eth + 1); 37 if (iph + 1 < data_end && iph->protocol == IPPROTO_UDP) 38 udp = (void *)(iph + 1); 39 } 40 if (eth->h_proto == bpf_htons(ETH_P_IPV6)) { 41 ip6h = (void *)(eth + 1); 42 if (ip6h + 1 < data_end && ip6h->nexthdr == IPPROTO_UDP) 43 udp = (void *)(ip6h + 1); 44 } 45 if (udp && udp + 1 > data_end) 46 udp = NULL; 47 } 48 49 if (!udp) 50 return XDP_PASS; 51 52 if (udp->dest != bpf_htons(9091)) 53 return XDP_PASS; 54 55 bpf_printk("forwarding UDP:9091 to AF_XDP"); 56 57 ret = bpf_xdp_adjust_meta(ctx, -(int)sizeof(struct xdp_meta)); 58 if (ret != 0) { 59 bpf_printk("bpf_xdp_adjust_meta returned %d", ret); 60 return XDP_PASS; 61 } 62 63 data = (void *)(long)ctx->data; 64 data_meta = (void *)(long)ctx->data_meta; 65 meta = data_meta; 66 67 if (meta + 1 > data) { 68 bpf_printk("bpf_xdp_adjust_meta doesn't appear to work"); 69 return XDP_PASS; 70 } 71 72 if (!bpf_xdp_metadata_rx_timestamp(ctx, &meta->rx_timestamp)) 73 bpf_printk("populated rx_timestamp with %llu", meta->rx_timestamp); 74 else 75 meta->rx_timestamp = 0; /* Used by AF_XDP as not avail signal */ 76 77 if (!bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash)) 78 bpf_printk("populated rx_hash with %u", meta->rx_hash); 79 else 80 meta->rx_hash = 0; /* Used by AF_XDP as not avail signal */ 81 82 return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS); 83 } 84 85 char _license[] SEC("license") = "GPL"; 86