xref: /OK3568_Linux_fs/kernel/samples/bpf/xdp1_kern.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* Copyright (c) 2016 PLUMgrid
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or
4*4882a593Smuzhiyun  * modify it under the terms of version 2 of the GNU General Public
5*4882a593Smuzhiyun  * License as published by the Free Software Foundation.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun #define KBUILD_MODNAME "foo"
8*4882a593Smuzhiyun #include <uapi/linux/bpf.h>
9*4882a593Smuzhiyun #include <linux/in.h>
10*4882a593Smuzhiyun #include <linux/if_ether.h>
11*4882a593Smuzhiyun #include <linux/if_packet.h>
12*4882a593Smuzhiyun #include <linux/if_vlan.h>
13*4882a593Smuzhiyun #include <linux/ip.h>
14*4882a593Smuzhiyun #include <linux/ipv6.h>
15*4882a593Smuzhiyun #include <bpf/bpf_helpers.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun struct {
18*4882a593Smuzhiyun 	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
19*4882a593Smuzhiyun 	__type(key, u32);
20*4882a593Smuzhiyun 	__type(value, long);
21*4882a593Smuzhiyun 	__uint(max_entries, 256);
22*4882a593Smuzhiyun } rxcnt SEC(".maps");
23*4882a593Smuzhiyun 
parse_ipv4(void * data,u64 nh_off,void * data_end)24*4882a593Smuzhiyun static int parse_ipv4(void *data, u64 nh_off, void *data_end)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	struct iphdr *iph = data + nh_off;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	if (iph + 1 > data_end)
29*4882a593Smuzhiyun 		return 0;
30*4882a593Smuzhiyun 	return iph->protocol;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
parse_ipv6(void * data,u64 nh_off,void * data_end)33*4882a593Smuzhiyun static int parse_ipv6(void *data, u64 nh_off, void *data_end)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	struct ipv6hdr *ip6h = data + nh_off;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	if (ip6h + 1 > data_end)
38*4882a593Smuzhiyun 		return 0;
39*4882a593Smuzhiyun 	return ip6h->nexthdr;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun SEC("xdp1")
xdp_prog1(struct xdp_md * ctx)43*4882a593Smuzhiyun int xdp_prog1(struct xdp_md *ctx)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	void *data_end = (void *)(long)ctx->data_end;
46*4882a593Smuzhiyun 	void *data = (void *)(long)ctx->data;
47*4882a593Smuzhiyun 	struct ethhdr *eth = data;
48*4882a593Smuzhiyun 	int rc = XDP_DROP;
49*4882a593Smuzhiyun 	long *value;
50*4882a593Smuzhiyun 	u16 h_proto;
51*4882a593Smuzhiyun 	u64 nh_off;
52*4882a593Smuzhiyun 	u32 ipproto;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	nh_off = sizeof(*eth);
55*4882a593Smuzhiyun 	if (data + nh_off > data_end)
56*4882a593Smuzhiyun 		return rc;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	h_proto = eth->h_proto;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
61*4882a593Smuzhiyun 		struct vlan_hdr *vhdr;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 		vhdr = data + nh_off;
64*4882a593Smuzhiyun 		nh_off += sizeof(struct vlan_hdr);
65*4882a593Smuzhiyun 		if (data + nh_off > data_end)
66*4882a593Smuzhiyun 			return rc;
67*4882a593Smuzhiyun 		h_proto = vhdr->h_vlan_encapsulated_proto;
68*4882a593Smuzhiyun 	}
69*4882a593Smuzhiyun 	if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
70*4882a593Smuzhiyun 		struct vlan_hdr *vhdr;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 		vhdr = data + nh_off;
73*4882a593Smuzhiyun 		nh_off += sizeof(struct vlan_hdr);
74*4882a593Smuzhiyun 		if (data + nh_off > data_end)
75*4882a593Smuzhiyun 			return rc;
76*4882a593Smuzhiyun 		h_proto = vhdr->h_vlan_encapsulated_proto;
77*4882a593Smuzhiyun 	}
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (h_proto == htons(ETH_P_IP))
80*4882a593Smuzhiyun 		ipproto = parse_ipv4(data, nh_off, data_end);
81*4882a593Smuzhiyun 	else if (h_proto == htons(ETH_P_IPV6))
82*4882a593Smuzhiyun 		ipproto = parse_ipv6(data, nh_off, data_end);
83*4882a593Smuzhiyun 	else
84*4882a593Smuzhiyun 		ipproto = 0;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	value = bpf_map_lookup_elem(&rxcnt, &ipproto);
87*4882a593Smuzhiyun 	if (value)
88*4882a593Smuzhiyun 		*value += 1;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	return rc;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun char _license[] SEC("license") = "GPL";
94