1 /* Copyright (c) 2016 PLUMgrid
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
7 #define KBUILD_MODNAME "foo"
8 #include <uapi/linux/bpf.h>
10 #include <linux/if_ether.h>
11 #include <linux/if_packet.h>
12 #include <linux/if_vlan.h>
14 #include <linux/ipv6.h>
15 #include "bpf_helpers.h"
17 struct bpf_map_def
SEC("maps") rxcnt
= {
18 .type
= BPF_MAP_TYPE_PERCPU_ARRAY
,
19 .key_size
= sizeof(u32
),
20 .value_size
= sizeof(long),
24 static void swap_src_dst_mac(void *data
)
26 unsigned short *p
= data
;
27 unsigned short dst
[3];
40 static int parse_ipv4(void *data
, u64 nh_off
, void *data_end
)
42 struct iphdr
*iph
= data
+ nh_off
;
44 if (iph
+ 1 > data_end
)
49 static int parse_ipv6(void *data
, u64 nh_off
, void *data_end
)
51 struct ipv6hdr
*ip6h
= data
+ nh_off
;
53 if (ip6h
+ 1 > data_end
)
59 int xdp_prog1(struct xdp_md
*ctx
)
61 void *data_end
= (void *)(long)ctx
->data_end
;
62 void *data
= (void *)(long)ctx
->data
;
63 struct ethhdr
*eth
= data
;
70 nh_off
= sizeof(*eth
);
71 if (data
+ nh_off
> data_end
)
74 h_proto
= eth
->h_proto
;
76 if (h_proto
== htons(ETH_P_8021Q
) || h_proto
== htons(ETH_P_8021AD
)) {
77 struct vlan_hdr
*vhdr
;
80 nh_off
+= sizeof(struct vlan_hdr
);
81 if (data
+ nh_off
> data_end
)
83 h_proto
= vhdr
->h_vlan_encapsulated_proto
;
85 if (h_proto
== htons(ETH_P_8021Q
) || h_proto
== htons(ETH_P_8021AD
)) {
86 struct vlan_hdr
*vhdr
;
89 nh_off
+= sizeof(struct vlan_hdr
);
90 if (data
+ nh_off
> data_end
)
92 h_proto
= vhdr
->h_vlan_encapsulated_proto
;
95 if (h_proto
== htons(ETH_P_IP
))
96 ipproto
= parse_ipv4(data
, nh_off
, data_end
);
97 else if (h_proto
== htons(ETH_P_IPV6
))
98 ipproto
= parse_ipv6(data
, nh_off
, data_end
);
102 value
= bpf_map_lookup_elem(&rxcnt
, &ipproto
);
106 if (ipproto
== IPPROTO_UDP
) {
107 swap_src_dst_mac(data
);
114 char _license
[] SEC("license") = "GPL";