Back to home page

OSCL-LXR

 
 

    


0001 /* Copyright (c) 2016 PLUMgrid
0002  *
0003  * This program is free software; you can redistribute it and/or
0004  * modify it under the terms of version 2 of the GNU General Public
0005  * License as published by the Free Software Foundation.
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     /* Handle VLAN tagged packet */
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     /* Handle double VLAN tagged packet */
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";