Skip to content

Commit 19a45d8

Browse files
liuhangbinkernel-patches-bot
authored andcommitted
samples/bpf: add xdp_redirect_map with xdp_prog support
This patch add running xdp program on egress interface support for xdp_redirect_map sample. The new prog will change the IP ttl based on egress ifindex. Signed-off-by: Hangbin Liu <[email protected]>
1 parent b7ba953 commit 19a45d8

File tree

2 files changed

+86
-9
lines changed

2 files changed

+86
-9
lines changed

samples/bpf/xdp_redirect_map_kern.c

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
struct {
2323
__uint(type, BPF_MAP_TYPE_DEVMAP);
2424
__uint(key_size, sizeof(int));
25-
__uint(value_size, sizeof(int));
25+
__uint(value_size, sizeof(struct bpf_devmap_val));
2626
__uint(max_entries, 100);
2727
} tx_port SEC(".maps");
2828

@@ -52,6 +52,48 @@ static void swap_src_dst_mac(void *data)
5252
p[5] = dst[2];
5353
}
5454

55+
static __always_inline __u16 csum_fold_helper(__u32 csum)
56+
{
57+
__u32 sum;
58+
sum = (csum & 0xffff) + (csum >> 16);
59+
sum += (sum >> 16);
60+
return ~sum;
61+
}
62+
63+
static __always_inline __u16 ipv4_csum(__u16 seed, struct iphdr *iphdr_new,
64+
struct iphdr *iphdr_old)
65+
{
66+
__u32 csum, size = sizeof(struct iphdr);
67+
csum = bpf_csum_diff((__be32 *)iphdr_old, size,
68+
(__be32 *)iphdr_new, size, seed);
69+
return csum_fold_helper(csum);
70+
}
71+
72+
static void parse_ipv4(void *data, u64 nh_off, void *data_end, u8 ttl)
73+
{
74+
struct iphdr *iph = data + nh_off;
75+
struct iphdr iph_old;
76+
__u16 csum_old;
77+
78+
if (iph + 1 > data_end)
79+
return;
80+
81+
iph_old = *iph;
82+
csum_old = iph->check;
83+
iph->ttl = ttl;
84+
iph->check = ipv4_csum(~csum_old, iph, &iph_old);
85+
}
86+
87+
static void parse_ipv6(void *data, u64 nh_off, void *data_end, u8 hop_limit)
88+
{
89+
struct ipv6hdr *ip6h = data + nh_off;
90+
91+
if (ip6h + 1 > data_end)
92+
return;
93+
94+
ip6h->hop_limit = hop_limit;
95+
}
96+
5597
SEC("xdp_redirect_map")
5698
int xdp_redirect_map_prog(struct xdp_md *ctx)
5799
{
@@ -82,6 +124,36 @@ int xdp_redirect_map_prog(struct xdp_md *ctx)
82124
return bpf_redirect_map(&tx_port, vport, 0);
83125
}
84126

127+
/* This map prog will set new IP ttl based on egress ifindex */
128+
SEC("xdp_devmap/map_prog")
129+
int xdp_devmap_prog(struct xdp_md *ctx)
130+
{
131+
char fmt[] = "devmap redirect: egress dev %u with new ttl %u\n";
132+
void *data_end = (void *)(long)ctx->data_end;
133+
void *data = (void *)(long)ctx->data;
134+
struct ethhdr *eth = data;
135+
u16 h_proto;
136+
u64 nh_off;
137+
u8 ttl;
138+
139+
nh_off = sizeof(struct ethhdr);
140+
if (data + nh_off > data_end)
141+
return XDP_DROP;
142+
143+
/* set new ttl based on egress ifindex */
144+
ttl = ctx->egress_ifindex % 64;
145+
146+
h_proto = eth->h_proto;
147+
if (h_proto == htons(ETH_P_IP))
148+
parse_ipv4(data, nh_off, data_end, ttl);
149+
else if (h_proto == htons(ETH_P_IPV6))
150+
parse_ipv6(data, nh_off, data_end, ttl);
151+
152+
bpf_trace_printk(fmt, sizeof(fmt), ctx->egress_ifindex, ttl);
153+
154+
return XDP_PASS;
155+
}
156+
85157
/* Redirect require an XDP bpf_prog loaded on the TX device */
86158
SEC("xdp_redirect_dummy")
87159
int xdp_redirect_dummy_prog(struct xdp_md *ctx)

samples/bpf/xdp_redirect_map_user.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,13 @@ int main(int argc, char **argv)
9898
{
9999
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
100100
struct bpf_prog_load_attr prog_load_attr = {
101-
.prog_type = BPF_PROG_TYPE_XDP,
101+
.prog_type = BPF_PROG_TYPE_UNSPEC,
102102
};
103-
struct bpf_program *prog, *dummy_prog;
103+
struct bpf_program *prog, *dummy_prog, *devmap_prog;
104+
int prog_fd, dummy_prog_fd, devmap_prog_fd;
105+
struct bpf_devmap_val devmap_val;
104106
struct bpf_prog_info info = {};
105107
__u32 info_len = sizeof(info);
106-
int prog_fd, dummy_prog_fd;
107108
const char *optstr = "FSN";
108109
struct bpf_object *obj;
109110
int ret, opt, key = 0;
@@ -157,16 +158,18 @@ int main(int argc, char **argv)
157158
return 1;
158159

159160
prog = bpf_program__next(NULL, obj);
160-
dummy_prog = bpf_program__next(prog, obj);
161-
if (!prog || !dummy_prog) {
161+
devmap_prog = bpf_object__find_program_by_title(obj, "xdp_devmap/map_prog");
162+
dummy_prog = bpf_object__find_program_by_title(obj, "xdp_redirect_dummy");
163+
if (!prog || !devmap_prog || !dummy_prog) {
162164
printf("finding a prog in obj file failed\n");
163165
return 1;
164166
}
165167
/* bpf_prog_load_xattr gives us the pointer to first prog's fd,
166-
* so we're missing only the fd for dummy prog
168+
* so we're missing the fd for devmap and dummy prog
167169
*/
170+
devmap_prog_fd = bpf_program__fd(devmap_prog);
168171
dummy_prog_fd = bpf_program__fd(dummy_prog);
169-
if (prog_fd < 0 || dummy_prog_fd < 0) {
172+
if (prog_fd < 0 || devmap_prog_fd < 0 || dummy_prog_fd < 0) {
170173
printf("bpf_prog_load_xattr: %s\n", strerror(errno));
171174
return 1;
172175
}
@@ -209,7 +212,9 @@ int main(int argc, char **argv)
209212
signal(SIGTERM, int_exit);
210213

211214
/* populate virtual to physical port map */
212-
ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0);
215+
devmap_val.bpf_prog.fd = devmap_prog_fd;
216+
devmap_val.ifindex = ifindex_out;
217+
ret = bpf_map_update_elem(tx_port_map_fd, &key, &devmap_val, 0);
213218
if (ret) {
214219
perror("bpf_update_elem");
215220
goto out;

0 commit comments

Comments
 (0)