#include "xdp_common.h"
SEC("xdp")
int zenith_xdp_stats(struct xdp_md *ctx)
{
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
u32 queue_id;
u32 fail_closed;
fail_closed = get_config_u32(CONFIG_KEY_FAIL_CLOSED);
if ((void *)(data + ETH_HLEN) > data_end) {
update_stats(STATS_RX_DROP_SHORT, 1);
return XDP_DROP;
}
queue_id = ctx->rx_queue_index;
update_stats(STATS_RX_PACKETS, 1);
struct ethhdr *eth = data;
if (eth->h_proto == bpf_htons(ETH_P_IP)) {
if ((void *)(data + sizeof(struct ethhdr) + sizeof(struct iphdr)) <= data_end) {
struct iphdr *iph = (struct iphdr *)(eth + 1);
switch (iph->protocol) {
case IPPROTO_TCP:
update_stats(STATS_RX_VALID, 1);
break;
case IPPROTO_UDP:
update_stats(STATS_RX_VALID, 1);
break;
case IPPROTO_ICMP:
update_stats(STATS_RX_VALID, 1);
break;
default:
break;
}
}
} else if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {
update_stats(STATS_RX_VALID, 1);
}
u32 *xsk_fd;
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);
}
char _license[] SEC("license") = "GPL";