99 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include <vmlinux.h>4#include "xdp_metadata.h"5#include <bpf/bpf_helpers.h>6#include <bpf/bpf_endian.h>7 8struct {9 __uint(type, BPF_MAP_TYPE_XSKMAP);10 __uint(max_entries, 4);11 __type(key, __u32);12 __type(value, __u32);13} xsk SEC(".maps");14 15struct {16 __uint(type, BPF_MAP_TYPE_PROG_ARRAY);17 __uint(max_entries, 1);18 __type(key, __u32);19 __type(value, __u32);20} prog_arr SEC(".maps");21 22extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx,23 __u64 *timestamp) __ksym;24extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,25 enum xdp_rss_hash_type *rss_type) __ksym;26extern int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx,27 __be16 *vlan_proto,28 __u16 *vlan_tci) __ksym;29 30SEC("xdp")31int rx(struct xdp_md *ctx)32{33 void *data, *data_meta, *data_end;34 struct ipv6hdr *ip6h = NULL;35 struct ethhdr *eth = NULL;36 struct udphdr *udp = NULL;37 struct iphdr *iph = NULL;38 struct xdp_meta *meta;39 u64 timestamp = -1;40 int ret;41 42 data = (void *)(long)ctx->data;43 data_end = (void *)(long)ctx->data_end;44 eth = data;45 if (eth + 1 < data_end) {46 if (eth->h_proto == bpf_htons(ETH_P_IP)) {47 iph = (void *)(eth + 1);48 if (iph + 1 < data_end && iph->protocol == IPPROTO_UDP)49 udp = (void *)(iph + 1);50 }51 if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {52 ip6h = (void *)(eth + 1);53 if (ip6h + 1 < data_end && ip6h->nexthdr == IPPROTO_UDP)54 udp = (void *)(ip6h + 1);55 }56 if (udp && udp + 1 > data_end)57 udp = NULL;58 }59 60 if (!udp)61 return XDP_PASS;62 63 /* Forwarding UDP:8080 to AF_XDP */64 if (udp->dest != bpf_htons(8080))65 return XDP_PASS;66 67 /* Reserve enough for all custom metadata. */68 69 ret = bpf_xdp_adjust_meta(ctx, -(int)sizeof(struct xdp_meta));70 if (ret != 0)71 return XDP_DROP;72 73 data = (void *)(long)ctx->data;74 data_meta = (void *)(long)ctx->data_meta;75 76 if (data_meta + sizeof(struct xdp_meta) > data)77 return XDP_DROP;78 79 meta = data_meta;80 81 /* Export metadata. */82 83 /* We expect veth bpf_xdp_metadata_rx_timestamp to return 0 HW84 * timestamp, so put some non-zero value into AF_XDP frame for85 * the userspace.86 */87 bpf_xdp_metadata_rx_timestamp(ctx, ×tamp);88 if (timestamp == 0)89 meta->rx_timestamp = 1;90 91 bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash, &meta->rx_hash_type);92 bpf_xdp_metadata_rx_vlan_tag(ctx, &meta->rx_vlan_proto,93 &meta->rx_vlan_tci);94 95 return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);96}97 98char _license[] SEC("license") = "GPL";99