]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - samples/bpf/xdp_redirect_map_kern.c
Merge branch 'for-next' into for-linus
[mirror_ubuntu-jammy-kernel.git] / samples / bpf / xdp_redirect_map_kern.c
CommitLineData
9d6e0052
JF
1/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io
2 *
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.
6 *
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
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>
7cf245a3 20#include <bpf/bpf_helpers.h>
9d6e0052 21
6e66fbb1
HL
22/* The 2nd xdp prog on egress does not support skb mode, so we define two
23 * maps, tx_port_general and tx_port_native.
24 */
451d1dc8
DL
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);
6e66fbb1
HL
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");
9d6e0052 38
306da4e6
JDB
39/* Count RX packets, as XDP bpf_prog doesn't get direct TX-success
40 * feedback. Redirect TX errors can be caught via a tracepoint.
41 */
451d1dc8
DL
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");
9d6e0052 48
6e66fbb1
HL
49/* map to store egress interface mac address */
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
9d6e0052
JF
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
6e66fbb1 73static __always_inline int xdp_redirect_map(struct xdp_md *ctx, void *redirect_map)
9d6e0052
JF
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;
9d6e0052
JF
79 long *value;
80 u32 key = 0;
81 u64 nh_off;
6e66fbb1 82 int vport;
9d6e0052
JF
83
84 nh_off = sizeof(*eth);
85 if (data + nh_off > data_end)
86 return rc;
87
88 /* constant virtual port */
89 vport = 0;
90
91 /* count packet in global counter */
92 value = bpf_map_lookup_elem(&rxcnt, &key);
93 if (value)
94 *value += 1;
95
96 swap_src_dst_mac(data);
97
98 /* send packet out physical port */
6e66fbb1
HL
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;
9d6e0052
JF
133}
134
306da4e6
JDB
135/* Redirect require an XDP bpf_prog loaded on the TX device */
136SEC("xdp_redirect_dummy")
3edcf18e 137int xdp_redirect_dummy_prog(struct xdp_md *ctx)
306da4e6
JDB
138{
139 return XDP_PASS;
140}
141
9d6e0052 142char _license[] SEC("license") = "GPL";