github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/cmd/examples/map_in_map/bpf/map_in_map_counter.c (about) 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #include <linux/bpf.h> 3 #include <linux/if_ether.h> 4 5 /* 6 * bpf_map_lookup_elem 7 * 8 * Perform a lookup in *map* for an entry associated to *key*. 9 * 10 * Returns 11 * Map value associated to *key*, or **NULL** if no entry was 12 * found. 13 */ 14 static void *(*bpf_map_lookup_elem)(void *map, const void *key) = (void *) 1; 15 16 #define SEC(NAME) __attribute__((section(NAME), used)) 17 18 struct bpf_map_def { 19 unsigned int type; 20 unsigned int key_size; 21 unsigned int value_size; 22 unsigned int max_entries; 23 unsigned int map_flags; 24 }; 25 26 struct datarec { 27 __u64 rx_packets; 28 }; 29 30 struct bpf_map_def SEC("maps") map_of_maps = { 31 .type = BPF_MAP_TYPE_ARRAY_OF_MAPS, 32 .key_size = sizeof(__u32), 33 .value_size = sizeof(__u32), 34 .max_entries = 2, 35 }; 36 37 38 /* LLVM maps __sync_fetch_and_add() as a built-in function to the BPF atomic add 39 * instruction (that is BPF_STX | BPF_XADD | BPF_W for word sizes) 40 */ 41 #ifndef lock_xadd 42 #define lock_xadd(ptr, val) ((void) __sync_fetch_and_add(ptr, val)) 43 #endif 44 45 SEC("xdp") 46 int xdp_stats1_func(struct xdp_md *ctx) 47 { 48 __u32 key = 0; 49 50 // Lookup the pointer to the map inner map 51 struct bpf_map_def *stats_map = bpf_map_lookup_elem(&map_of_maps, &key); 52 if (!stats_map) { 53 return XDP_ABORTED; 54 } 55 56 // Lookup datarec struct in inner map, we will use key 57 struct datarec *rec; 58 key = XDP_PASS; /* XDP_PASS = 2 */ 59 60 rec = bpf_map_lookup_elem(stats_map, &key); 61 if (!rec) 62 return XDP_ABORTED; 63 64 /* Multiple CPUs can access data record. Thus, the accounting needs to 65 * use an atomic operation. 66 */ 67 lock_xadd(&rec->rx_packets, 1); 68 69 return XDP_PASS; 70 } 71 72 char _license[] SEC("license") = "GPL";