#include "xdp_common.h"
static __always_inline int
zenith_xdp_redirect_impl(struct xdp_md *ctx)
{
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
u32 queue_id;
u32 fail_closed;
if ((void *)(data + ETH_HLEN) > data_end) {
update_stats(STATS_RX_DROP_SHORT, 1);
return XDP_DROP;
}
struct ethhdr *eth = data;
__u16 proto = eth->h_proto;
if (proto != bpf_htons(ETH_P_IP) &&
proto != bpf_htons(ETH_P_IPV6) &&
proto != bpf_htons(ETH_P_ARP)) {
update_stats(STATS_RX_DROP_PROTO, 1);
return XDP_PASS;
}
fail_closed = get_config_u32(CONFIG_KEY_FAIL_CLOSED);
queue_id = ctx->rx_queue_index;
u32 *xsk_fd = bpf_map_lookup_elem(&xsk_map, &queue_id);
if (!xsk_fd) {
update_stats(STATS_RX_DROP_NO_XSK, 1);
if (fail_closed)
return XDP_DROP;
return XDP_PASS;
}
update_stats(STATS_REDIRECTED, 1);
return bpf_redirect_map(&xsk_map, queue_id, XDP_PASS);
}
SEC("xdp")
int zenith_xdp_redirect_a(struct xdp_md *ctx)
{
return zenith_xdp_redirect_impl(ctx);
}
SEC("xdp")
int zenith_xdp_redirect_b(struct xdp_md *ctx)
{
return zenith_xdp_redirect_impl(ctx);
}
char _license[] SEC("license") = "GPL";