1
2
3
4
5
6
7
8
9
10
11
12#define KBUILD_MODNAME "foo"
13#include <uapi/linux/bpf.h>
14#include <linux/in.h>
15#include <linux/if_ether.h>
16#include <linux/if_packet.h>
17#include <linux/if_vlan.h>
18#include <linux/ip.h>
19#include <linux/ipv6.h>
20#include <bpf/bpf_helpers.h>
21
22
23
24
25struct {
26 __uint(type, BPF_MAP_TYPE_DEVMAP);
27 __uint(key_size, sizeof(int));
28 __uint(value_size, sizeof(int));
29 __uint(max_entries, 100);
30} tx_port_general SEC(".maps");
31
32struct {
33 __uint(type, BPF_MAP_TYPE_DEVMAP);
34 __uint(key_size, sizeof(int));
35 __uint(value_size, sizeof(struct bpf_devmap_val));
36 __uint(max_entries, 100);
37} tx_port_native SEC(".maps");
38
39
40
41
42struct {
43 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
44 __type(key, u32);
45 __type(value, long);
46 __uint(max_entries, 1);
47} rxcnt SEC(".maps");
48
49
50struct {
51 __uint(type, BPF_MAP_TYPE_ARRAY);
52 __type(key, u32);
53 __type(value, __be64);
54 __uint(max_entries, 1);
55} tx_mac SEC(".maps");
56
57static void swap_src_dst_mac(void *data)
58{
59 unsigned short *p = data;
60 unsigned short dst[3];
61
62 dst[0] = p[0];
63 dst[1] = p[1];
64 dst[2] = p[2];
65 p[0] = p[3];
66 p[1] = p[4];
67 p[2] = p[5];
68 p[3] = dst[0];
69 p[4] = dst[1];
70 p[5] = dst[2];
71}
72
73static __always_inline int xdp_redirect_map(struct xdp_md *ctx, void *redirect_map)
74{
75 void *data_end = (void *)(long)ctx->data_end;
76 void *data = (void *)(long)ctx->data;
77 struct ethhdr *eth = data;
78 int rc = XDP_DROP;
79 long *value;
80 u32 key = 0;
81 u64 nh_off;
82 int vport;
83
84 nh_off = sizeof(*eth);
85 if (data + nh_off > data_end)
86 return rc;
87
88
89 vport = 0;
90
91
92 value = bpf_map_lookup_elem(&rxcnt, &key);
93 if (value)
94 *value += 1;
95
96 swap_src_dst_mac(data);
97
98
99 return bpf_redirect_map(redirect_map, vport, 0);
100}
101
102SEC("xdp_redirect_general")
103int xdp_redirect_map_general(struct xdp_md *ctx)
104{
105 return xdp_redirect_map(ctx, &tx_port_general);
106}
107
108SEC("xdp_redirect_native")
109int xdp_redirect_map_native(struct xdp_md *ctx)
110{
111 return xdp_redirect_map(ctx, &tx_port_native);
112}
113
114SEC("xdp_devmap/map_prog")
115int xdp_redirect_map_egress(struct xdp_md *ctx)
116{
117 void *data_end = (void *)(long)ctx->data_end;
118 void *data = (void *)(long)ctx->data;
119 struct ethhdr *eth = data;
120 __be64 *mac;
121 u32 key = 0;
122 u64 nh_off;
123
124 nh_off = sizeof(*eth);
125 if (data + nh_off > data_end)
126 return XDP_DROP;
127
128 mac = bpf_map_lookup_elem(&tx_mac, &key);
129 if (mac)
130 __builtin_memcpy(eth->h_source, mac, ETH_ALEN);
131
132 return XDP_PASS;
133}
134
135
136SEC("xdp_redirect_dummy")
137int xdp_redirect_dummy_prog(struct xdp_md *ctx)
138{
139 return XDP_PASS;
140}
141
142char _license[] SEC("license") = "GPL";
143