github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/examples/xdp/xdp.c (about) 1 //go:build ignore 2 3 #include "bpf_endian.h" 4 #include "common.h" 5 6 char __license[] SEC("license") = "Dual MIT/GPL"; 7 8 #define MAX_MAP_ENTRIES 16 9 10 /* Define an LRU hash map for storing packet count by source IPv4 address */ 11 struct { 12 __uint(type, BPF_MAP_TYPE_LRU_HASH); 13 __uint(max_entries, MAX_MAP_ENTRIES); 14 __type(key, __u32); // source IPv4 address 15 __type(value, __u32); // packet count 16 } xdp_stats_map SEC(".maps"); 17 18 /* 19 Attempt to parse the IPv4 source address from the packet. 20 Returns 0 if there is no IPv4 header field; otherwise returns non-zero. 21 */ 22 static __always_inline int parse_ip_src_addr(struct xdp_md *ctx, __u32 *ip_src_addr) { 23 void *data_end = (void *)(long)ctx->data_end; 24 void *data = (void *)(long)ctx->data; 25 26 // First, parse the ethernet header. 27 struct ethhdr *eth = data; 28 if ((void *)(eth + 1) > data_end) { 29 return 0; 30 } 31 32 if (eth->h_proto != bpf_htons(ETH_P_IP)) { 33 // The protocol is not IPv4, so we can't parse an IPv4 source address. 34 return 0; 35 } 36 37 // Then parse the IP header. 38 struct iphdr *ip = (void *)(eth + 1); 39 if ((void *)(ip + 1) > data_end) { 40 return 0; 41 } 42 43 // Return the source IP address in network byte order. 44 *ip_src_addr = (__u32)(ip->saddr); 45 return 1; 46 } 47 48 SEC("xdp") 49 int xdp_prog_func(struct xdp_md *ctx) { 50 __u32 ip; 51 if (!parse_ip_src_addr(ctx, &ip)) { 52 // Not an IPv4 packet, so don't count it. 53 goto done; 54 } 55 56 __u32 *pkt_count = bpf_map_lookup_elem(&xdp_stats_map, &ip); 57 if (!pkt_count) { 58 // No entry in the map for this IP address yet, so set the initial value to 1. 59 __u32 init_pkt_count = 1; 60 bpf_map_update_elem(&xdp_stats_map, &ip, &init_pkt_count, BPF_ANY); 61 } else { 62 // Entry already exists for this IP address, 63 // so increment it atomically using an LLVM built-in. 64 __sync_fetch_and_add(pkt_count, 1); 65 } 66 67 done: 68 // Try changing this to XDP_DROP and see what happens! 69 return XDP_PASS; 70 }