Blame view

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

d9094bda5   Brenden Blanco   bpf: make xdp sam...
85
  	value = bpf_map_lookup_elem(&rxcnt, &ipproto);
86af8b419   Brenden Blanco   Add sample for ad...
86
87
88
89
90
91
92
  	if (value)
  		*value += 1;
  
  	return rc;
  }
  
  char _license[] SEC("license") = "GPL";