Skip to content

Commit 0a2894e

Browse files
authored
Merge pull request #124 from xdp-project/tailgrow03.public
More examples to access XDP packet data at packet end
2 parents b13cfb8 + 3441911 commit 0a2894e

4 files changed

Lines changed: 146 additions & 0 deletions

File tree

experiment01-tailgrow/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
22

33
XDP_TARGETS := xdp_prog_kern xdp_prog_kern2
4+
XDP_TARGETS += xdp_prog_kern3
5+
XDP_TARGETS += xdp_prog_kern4
46
XDP_TARGETS += xdp_prog_fail1
57
XDP_TARGETS += xdp_prog_fail2
68

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (C) 2020 Authors of Cilium
3+
*
4+
* Code copied from cilium/bpf/include/bpf/ctx/xdp.h
5+
* https://github.com/cilium/cilium/blob/master/bpf/include/bpf/ctx/xdp.h
6+
*/
7+
8+
#ifndef _XDP_DATA_ACCESS_HELPERS_H_
9+
#define _XDP_DATA_ACCESS_HELPERS_H_
10+
11+
/* This must be a mask and all offsets guaranteed to be less than that. */
12+
//#define __CTX_OFF_MAX 0xff
13+
#define __CTX_OFF_MAX 0x1fff
14+
15+
#ifndef __maybe_unused
16+
# define __maybe_unused __attribute__((__unused__))
17+
#endif
18+
19+
#ifndef EINVAL
20+
# define EINVAL 22
21+
#endif
22+
23+
#ifndef memcpy
24+
# define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))
25+
#endif
26+
27+
static __always_inline __maybe_unused int
28+
xdp_load_bytes(struct xdp_md *ctx, __u64 off, void *to, const __u64 len)
29+
{
30+
void *from;
31+
int ret;
32+
/* LLVM tends to generate code that verifier doesn't understand,
33+
* so force it the way we want it in order to open up a range
34+
* on the reg.
35+
*/
36+
asm volatile("r1 = *(u32 *)(%[ctx] +0)\n\t"
37+
"r2 = *(u32 *)(%[ctx] +4)\n\t"
38+
"%[off] &= %[offmax]\n\t"
39+
"r1 += %[off]\n\t"
40+
"%[from] = r1\n\t"
41+
"r1 += %[len]\n\t"
42+
"if r1 > r2 goto +2\n\t"
43+
"%[ret] = 0\n\t"
44+
"goto +1\n\t"
45+
"%[ret] = %[errno]\n\t"
46+
: [ret]"=r"(ret), [from]"=r"(from)
47+
: [ctx]"r"(ctx), [off]"r"(off), [len]"ri"(len),
48+
[offmax]"i"(__CTX_OFF_MAX), [errno]"i"(-EINVAL)
49+
: "r1", "r2");
50+
if (!ret)
51+
memcpy(to, from, len);
52+
return ret;
53+
}
54+
55+
static __always_inline __maybe_unused int
56+
xdp_store_bytes(struct xdp_md *ctx, __u64 off, const void *from,
57+
const __u64 len, __u64 flags __maybe_unused)
58+
{
59+
void *to;
60+
int ret;
61+
/* See xdp_load_bytes(). */
62+
asm volatile("r1 = *(u32 *)(%[ctx] +0)\n\t"
63+
"r2 = *(u32 *)(%[ctx] +4)\n\t"
64+
"%[off] &= %[offmax]\n\t"
65+
"r1 += %[off]\n\t"
66+
"%[to] = r1\n\t"
67+
"r1 += %[len]\n\t"
68+
"if r1 > r2 goto +2\n\t"
69+
"%[ret] = 0\n\t"
70+
"goto +1\n\t"
71+
"%[ret] = %[errno]\n\t"
72+
: [ret]"=r"(ret), [to]"=r"(to)
73+
: [ctx]"r"(ctx), [off]"r"(off), [len]"ri"(len),
74+
[offmax]"i"(__CTX_OFF_MAX), [errno]"i"(-EINVAL)
75+
: "r1", "r2");
76+
if (!ret)
77+
memcpy(to, from, len);
78+
return ret;
79+
}
80+
81+
#define ctx_load_bytes xdp_load_bytes
82+
#define ctx_store_bytes xdp_store_bytes
83+
84+
#endif /* _XDP_DATA_ACCESS_HELPERS_H_ */
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#include <linux/bpf.h>
3+
#include <bpf/bpf_helpers.h>
4+
5+
/*
6+
* This BPF-prog will drop all packets, but pass verifier checks.
7+
*
8+
* General idea: Use packet length to find and access last byte.
9+
*/
10+
11+
SEC("xdp_fail1")
12+
int _xdp_fail1(struct xdp_md *ctx)
13+
{
14+
void *data_end = (void *)(long)ctx->data_end;
15+
void *data = (void *)(long)ctx->data;
16+
unsigned char *ptr;
17+
void *pos;
18+
19+
unsigned int offset = data_end - data;
20+
21+
pos = data;
22+
offset &= 0x7FFF; /* Bound/limit max value to help verifier */
23+
24+
pos += offset;
25+
26+
/* Below +1 will cause all packet to be dropped, as it will be
27+
* longer than packet length (just calc as offset).
28+
*/
29+
if (pos + 1 > data_end)
30+
return XDP_DROP;
31+
32+
ptr = pos;
33+
if (*ptr == 0xFF)
34+
return XDP_ABORTED;
35+
36+
return XDP_PASS;
37+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#include <linux/bpf.h>
3+
#include <bpf/bpf_helpers.h>
4+
5+
#include "xdp_data_access_helpers.h"
6+
7+
SEC("xdp_test1")
8+
int _xdp_test1(struct xdp_md *ctx)
9+
{
10+
// void *data_end = (void *)(long)ctx->data_end;
11+
void *data = (void *)(long)ctx->data;
12+
unsigned int len;
13+
// len = (data_end - data) - 2 ; // Not working, due to verifier
14+
len = 12;
15+
16+
unsigned int offset = len - 2;
17+
18+
if (ctx_store_bytes(ctx, offset, data, 2, 0) < 0)
19+
return XDP_ABORTED;
20+
21+
return XDP_PASS;
22+
}
23+

0 commit comments

Comments
 (0)