1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/if_ether.h> 4 5 #include <linux/bpf.h> 6 #include <bpf/bpf_helpers.h> 7 #include <bpf/bpf_endian.h> 8 9 struct { 10 __uint(type, BPF_MAP_TYPE_DEVMAP); 11 __uint(max_entries, 8); 12 __uint(key_size, sizeof(int)); 13 __uint(value_size, sizeof(int)); 14 } tx_port SEC(".maps"); 15 16 SEC("xdp") 17 int xdp_redirect_map_0(struct xdp_md *xdp) 18 { 19 return bpf_redirect_map(&tx_port, 0, 0); 20 } 21 22 SEC("xdp") 23 int xdp_redirect_map_1(struct xdp_md *xdp) 24 { 25 return bpf_redirect_map(&tx_port, 1, 0); 26 } 27 28 SEC("xdp") 29 int xdp_redirect_map_2(struct xdp_md *xdp) 30 { 31 return bpf_redirect_map(&tx_port, 2, 0); 32 } 33 34 struct { 35 __uint(type, BPF_MAP_TYPE_ARRAY); 36 __uint(max_entries, 3); 37 __type(key, __u32); 38 __type(value, __u64); 39 } rxcnt SEC(".maps"); 40 41 static int xdp_count(struct xdp_md *xdp, __u32 key) 42 { 43 void *data_end = (void *)(long)xdp->data_end; 44 void *data = (void *)(long)xdp->data; 45 struct ethhdr *eth = data; 46 __u64 *count; 47 48 if (data + sizeof(*eth) > data_end) 49 return XDP_DROP; 50 51 if (bpf_htons(eth->h_proto) == ETH_P_IP) { 52 /* We only count IPv4 packets */ 53 count = bpf_map_lookup_elem(&rxcnt, &key); 54 if (count) 55 *count += 1; 56 } 57 58 return XDP_PASS; 59 } 60 61 SEC("xdp") 62 int xdp_count_0(struct xdp_md *xdp) 63 { 64 return xdp_count(xdp, 0); 65 } 66 67 SEC("xdp") 68 int xdp_count_1(struct xdp_md *xdp) 69 { 70 return xdp_count(xdp, 1); 71 } 72 73 SEC("xdp") 74 int xdp_count_2(struct xdp_md *xdp) 75 { 76 return xdp_count(xdp, 2); 77 } 78 79 struct { 80 __uint(type, BPF_MAP_TYPE_ARRAY); 81 __uint(max_entries, 2); 82 __type(key, __u32); 83 __type(value, __be64); 84 } rx_mac SEC(".maps"); 85 86 static int store_mac(struct xdp_md *xdp, __u32 id) 87 { 88 void *data_end = (void *)(long)xdp->data_end; 89 void *data = (void *)(long)xdp->data; 90 struct ethhdr *eth = data; 91 __u32 key = id; 92 __be64 mac = 0; 93 94 if (data + sizeof(*eth) > data_end) 95 return XDP_DROP; 96 97 /* Only store IPv4 MAC to avoid being polluted by IPv6 packets */ 98 if (eth->h_proto == bpf_htons(ETH_P_IP)) { 99 __builtin_memcpy(&mac, eth->h_source, ETH_ALEN); 100 bpf_map_update_elem(&rx_mac, &key, &mac, 0); 101 bpf_printk("%s - %x", __func__, mac); 102 } 103 104 return XDP_PASS; 105 } 106 107 SEC("xdp") 108 int store_mac_1(struct xdp_md *xdp) 109 { 110 return store_mac(xdp, 0); 111 } 112 113 SEC("xdp") 114 int store_mac_2(struct xdp_md *xdp) 115 { 116 return store_mac(xdp, 1); 117 } 118 119 char _license[] SEC("license") = "GPL"; 120