0001
0002
0003
0004
0005
0006
0007 #define KBUILD_MODNAME "foo"
0008 #include <uapi/linux/bpf.h>
0009 #include <linux/in.h>
0010 #include <linux/if_ether.h>
0011 #include <linux/if_packet.h>
0012 #include <linux/if_vlan.h>
0013 #include <linux/ip.h>
0014 #include <linux/ipv6.h>
0015 #include <bpf/bpf_helpers.h>
0016
0017 struct {
0018 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0019 __type(key, u32);
0020 __type(value, long);
0021 __uint(max_entries, 256);
0022 } rxcnt SEC(".maps");
0023
0024 static int parse_ipv4(void *data, u64 nh_off, void *data_end)
0025 {
0026 struct iphdr *iph = data + nh_off;
0027
0028 if (iph + 1 > data_end)
0029 return 0;
0030 return iph->protocol;
0031 }
0032
0033 static int parse_ipv6(void *data, u64 nh_off, void *data_end)
0034 {
0035 struct ipv6hdr *ip6h = data + nh_off;
0036
0037 if (ip6h + 1 > data_end)
0038 return 0;
0039 return ip6h->nexthdr;
0040 }
0041
0042 #define XDPBUFSIZE 64
0043 SEC("xdp.frags")
0044 int xdp_prog1(struct xdp_md *ctx)
0045 {
0046 __u8 pkt[XDPBUFSIZE] = {};
0047 void *data_end = &pkt[XDPBUFSIZE-1];
0048 void *data = pkt;
0049 struct ethhdr *eth = data;
0050 int rc = XDP_DROP;
0051 long *value;
0052 u16 h_proto;
0053 u64 nh_off;
0054 u32 ipproto;
0055
0056 if (bpf_xdp_load_bytes(ctx, 0, pkt, sizeof(pkt)))
0057 return rc;
0058
0059 nh_off = sizeof(*eth);
0060 if (data + nh_off > data_end)
0061 return rc;
0062
0063 h_proto = eth->h_proto;
0064
0065
0066 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
0067 struct vlan_hdr *vhdr;
0068
0069 vhdr = data + nh_off;
0070 nh_off += sizeof(struct vlan_hdr);
0071 if (data + nh_off > data_end)
0072 return rc;
0073 h_proto = vhdr->h_vlan_encapsulated_proto;
0074 }
0075
0076 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
0077 struct vlan_hdr *vhdr;
0078
0079 vhdr = data + nh_off;
0080 nh_off += sizeof(struct vlan_hdr);
0081 if (data + nh_off > data_end)
0082 return rc;
0083 h_proto = vhdr->h_vlan_encapsulated_proto;
0084 }
0085
0086 if (h_proto == htons(ETH_P_IP))
0087 ipproto = parse_ipv4(data, nh_off, data_end);
0088 else if (h_proto == htons(ETH_P_IPV6))
0089 ipproto = parse_ipv6(data, nh_off, data_end);
0090 else
0091 ipproto = 0;
0092
0093 value = bpf_map_lookup_elem(&rxcnt, &ipproto);
0094 if (value)
0095 *value += 1;
0096
0097 return rc;
0098 }
0099
0100 char _license[] SEC("license") = "GPL";