Skip to content

Commit e255d32

Browse files
borkmannAlexei Starovoitov
authored andcommitted
Merge branch 'bpf-ring-buffer'
Andrii Nakryiko says: ==================== Implement a new BPF ring buffer, as presented at BPF virtual conference ([0]). It presents an alternative to perf buffer, following its semantics closely, but allowing sharing same instance of ring buffer across multiple CPUs efficiently. Most patches have extensive commentary explaining various aspects, so I'll keep cover letter short. Overall structure of the patch set: - patch #1 adds BPF ring buffer implementation to kernel and necessary verifier support; - patch #2 adds libbpf consumer implementation for BPF ringbuf; - patch #3 adds selftest, both for single BPF ring buf use case, as well as using it with array/hash of maps; - patch #4 adds extensive benchmarks and provide some analysis in commit message, it builds upon selftests/bpf's bench runner. - patch #5 adds most of patch #1 commit message as a doc under Documentation/bpf/ringbuf.rst. Litmus tests, validating consumer/producer protocols and memory orderings, were moved out as discussed in [1] and are going to be posted against -rcu tree and put under Documentation/litmus-tests/bpf-rb. [0] https://docs.google.com/presentation/d/18ITdg77Bj6YDOH2LghxrnFxiPWe0fAqcmJY95t_qr0w [1] https://lkml.org/lkml/2020/5/22/1011 v3->v4: - fix ringbuf freeing (vunmap, __free_page); verified with a trivial loop creating and closing ringbuf map endlessly (Daniel); v2->v3: - dropped unnecessary smp_wmb() (Paul); - verifier reference type enhancement patch was dropped (Alexei); - better verifier message for various memory access checks (Alexei); - clarified a bit roundup_len() bit shifting (Alexei); - converted doc to .rst (Alexei); - fixed warning on 32-bit arches regarding tautological ring area size check. v1->v2: - commit()/discard()/output() accept flags (NO_WAKEUP/FORCE_WAKEUP) (Stanislav); - bpf_ringbuf_query() added, returning available data size, ringbuf size, consumer/producer positions, needed to implement smarter notification policy (Stanislav); - added ringbuf UAPI constants to include/uapi/linux/bpf.h (Jonathan); - fixed sample size check, added proper ringbuf size check (Jonathan, Alexei); - wake_up_all() is done through irq_work (Alexei); - consistent use of smp_load_acquire/smp_store_release, no READ_ONCE/WRITE_ONCE (Alexei); - added Documentation/bpf/ringbuf.txt (Stanislav); - updated litmus test with smp_load_acquire/smp_store_release changes; - added ring_buffer__consume() API to libbpf for busy-polling; - ring_buffer__poll() on success returns number of records consumed; - fixed EPOLL notifications, don't assume available data, done similarly to perfbuf's implementation; - both ringbuf and perfbuf now have --rb-sampled mode, instead of pb-raw/pb-custom mode, updated benchmark results; - extended ringbuf selftests to validate epoll logic/manual notification logic, as well as bpf_ringbuf_query(). ==================== Signed-off-by: Daniel Borkmann <[email protected]>
2 parents 43dd115 + 97abb2b commit e255d32

35 files changed

+2630
-72
lines changed

Documentation/bpf/ringbuf.rst

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
===============
2+
BPF ring buffer
3+
===============
4+
5+
This document describes BPF ring buffer design, API, and implementation details.
6+
7+
.. contents::
8+
:local:
9+
:depth: 2
10+
11+
Motivation
12+
----------
13+
14+
There are two distinctive motivators for this work, which are not satisfied by
15+
existing perf buffer, which prompted creation of a new ring buffer
16+
implementation.
17+
18+
- more efficient memory utilization by sharing ring buffer across CPUs;
19+
- preserving ordering of events that happen sequentially in time, even across
20+
multiple CPUs (e.g., fork/exec/exit events for a task).
21+
22+
These two problems are independent, but perf buffer fails to satisfy both.
23+
Both are a result of a choice to have per-CPU perf ring buffer. Both can be
24+
also solved by having an MPSC implementation of ring buffer. The ordering
25+
problem could technically be solved for perf buffer with some in-kernel
26+
counting, but given the first one requires an MPSC buffer, the same solution
27+
would solve the second problem automatically.
28+
29+
Semantics and APIs
30+
------------------
31+
32+
Single ring buffer is presented to BPF programs as an instance of BPF map of
33+
type ``BPF_MAP_TYPE_RINGBUF``. Two other alternatives considered, but
34+
ultimately rejected.
35+
36+
One way would be to, similar to ``BPF_MAP_TYPE_PERF_EVENT_ARRAY``, make
37+
``BPF_MAP_TYPE_RINGBUF`` could represent an array of ring buffers, but not
38+
enforce "same CPU only" rule. This would be more familiar interface compatible
39+
with existing perf buffer use in BPF, but would fail if application needed more
40+
advanced logic to lookup ring buffer by arbitrary key.
41+
``BPF_MAP_TYPE_HASH_OF_MAPS`` addresses this with current approach.
42+
Additionally, given the performance of BPF ringbuf, many use cases would just
43+
opt into a simple single ring buffer shared among all CPUs, for which current
44+
approach would be an overkill.
45+
46+
Another approach could introduce a new concept, alongside BPF map, to represent
47+
generic "container" object, which doesn't necessarily have key/value interface
48+
with lookup/update/delete operations. This approach would add a lot of extra
49+
infrastructure that has to be built for observability and verifier support. It
50+
would also add another concept that BPF developers would have to familiarize
51+
themselves with, new syntax in libbpf, etc. But then would really provide no
52+
additional benefits over the approach of using a map. ``BPF_MAP_TYPE_RINGBUF``
53+
doesn't support lookup/update/delete operations, but so doesn't few other map
54+
types (e.g., queue and stack; array doesn't support delete, etc).
55+
56+
The approach chosen has an advantage of re-using existing BPF map
57+
infrastructure (introspection APIs in kernel, libbpf support, etc), being
58+
familiar concept (no need to teach users a new type of object in BPF program),
59+
and utilizing existing tooling (bpftool). For common scenario of using a single
60+
ring buffer for all CPUs, it's as simple and straightforward, as would be with
61+
a dedicated "container" object. On the other hand, by being a map, it can be
62+
combined with ``ARRAY_OF_MAPS`` and ``HASH_OF_MAPS`` map-in-maps to implement
63+
a wide variety of topologies, from one ring buffer for each CPU (e.g., as
64+
a replacement for perf buffer use cases), to a complicated application
65+
hashing/sharding of ring buffers (e.g., having a small pool of ring buffers
66+
with hashed task's tgid being a look up key to preserve order, but reduce
67+
contention).
68+
69+
Key and value sizes are enforced to be zero. ``max_entries`` is used to specify
70+
the size of ring buffer and has to be a power of 2 value.
71+
72+
There are a bunch of similarities between perf buffer
73+
(``BPF_MAP_TYPE_PERF_EVENT_ARRAY``) and new BPF ring buffer semantics:
74+
75+
- variable-length records;
76+
- if there is no more space left in ring buffer, reservation fails, no
77+
blocking;
78+
- memory-mappable data area for user-space applications for ease of
79+
consumption and high performance;
80+
- epoll notifications for new incoming data;
81+
- but still the ability to do busy polling for new data to achieve the
82+
lowest latency, if necessary.
83+
84+
BPF ringbuf provides two sets of APIs to BPF programs:
85+
86+
- ``bpf_ringbuf_output()`` allows to *copy* data from one place to a ring
87+
buffer, similarly to ``bpf_perf_event_output()``;
88+
- ``bpf_ringbuf_reserve()``/``bpf_ringbuf_commit()``/``bpf_ringbuf_discard()``
89+
APIs split the whole process into two steps. First, a fixed amount of space
90+
is reserved. If successful, a pointer to a data inside ring buffer data
91+
area is returned, which BPF programs can use similarly to a data inside
92+
array/hash maps. Once ready, this piece of memory is either committed or
93+
discarded. Discard is similar to commit, but makes consumer ignore the
94+
record.
95+
96+
``bpf_ringbuf_output()`` has disadvantage of incurring extra memory copy,
97+
because record has to be prepared in some other place first. But it allows to
98+
submit records of the length that's not known to verifier beforehand. It also
99+
closely matches ``bpf_perf_event_output()``, so will simplify migration
100+
significantly.
101+
102+
``bpf_ringbuf_reserve()`` avoids the extra copy of memory by providing a memory
103+
pointer directly to ring buffer memory. In a lot of cases records are larger
104+
than BPF stack space allows, so many programs have use extra per-CPU array as
105+
a temporary heap for preparing sample. bpf_ringbuf_reserve() avoid this needs
106+
completely. But in exchange, it only allows a known constant size of memory to
107+
be reserved, such that verifier can verify that BPF program can't access memory
108+
outside its reserved record space. bpf_ringbuf_output(), while slightly slower
109+
due to extra memory copy, covers some use cases that are not suitable for
110+
``bpf_ringbuf_reserve()``.
111+
112+
The difference between commit and discard is very small. Discard just marks
113+
a record as discarded, and such records are supposed to be ignored by consumer
114+
code. Discard is useful for some advanced use-cases, such as ensuring
115+
all-or-nothing multi-record submission, or emulating temporary
116+
``malloc()``/``free()`` within single BPF program invocation.
117+
118+
Each reserved record is tracked by verifier through existing
119+
reference-tracking logic, similar to socket ref-tracking. It is thus
120+
impossible to reserve a record, but forget to submit (or discard) it.
121+
122+
``bpf_ringbuf_query()`` helper allows to query various properties of ring
123+
buffer. Currently 4 are supported:
124+
125+
- ``BPF_RB_AVAIL_DATA`` returns amount of unconsumed data in ring buffer;
126+
- ``BPF_RB_RING_SIZE`` returns the size of ring buffer;
127+
- ``BPF_RB_CONS_POS``/``BPF_RB_PROD_POS`` returns current logical possition
128+
of consumer/producer, respectively.
129+
130+
Returned values are momentarily snapshots of ring buffer state and could be
131+
off by the time helper returns, so this should be used only for
132+
debugging/reporting reasons or for implementing various heuristics, that take
133+
into account highly-changeable nature of some of those characteristics.
134+
135+
One such heuristic might involve more fine-grained control over poll/epoll
136+
notifications about new data availability in ring buffer. Together with
137+
``BPF_RB_NO_WAKEUP``/``BPF_RB_FORCE_WAKEUP`` flags for output/commit/discard
138+
helpers, it allows BPF program a high degree of control and, e.g., more
139+
efficient batched notifications. Default self-balancing strategy, though,
140+
should be adequate for most applications and will work reliable and efficiently
141+
already.
142+
143+
Design and Implementation
144+
-------------------------
145+
146+
This reserve/commit schema allows a natural way for multiple producers, either
147+
on different CPUs or even on the same CPU/in the same BPF program, to reserve
148+
independent records and work with them without blocking other producers. This
149+
means that if BPF program was interruped by another BPF program sharing the
150+
same ring buffer, they will both get a record reserved (provided there is
151+
enough space left) and can work with it and submit it independently. This
152+
applies to NMI context as well, except that due to using a spinlock during
153+
reservation, in NMI context, ``bpf_ringbuf_reserve()`` might fail to get
154+
a lock, in which case reservation will fail even if ring buffer is not full.
155+
156+
The ring buffer itself internally is implemented as a power-of-2 sized
157+
circular buffer, with two logical and ever-increasing counters (which might
158+
wrap around on 32-bit architectures, that's not a problem):
159+
160+
- consumer counter shows up to which logical position consumer consumed the
161+
data;
162+
- producer counter denotes amount of data reserved by all producers.
163+
164+
Each time a record is reserved, producer that "owns" the record will
165+
successfully advance producer counter. At that point, data is still not yet
166+
ready to be consumed, though. Each record has 8 byte header, which contains the
167+
length of reserved record, as well as two extra bits: busy bit to denote that
168+
record is still being worked on, and discard bit, which might be set at commit
169+
time if record is discarded. In the latter case, consumer is supposed to skip
170+
the record and move on to the next one. Record header also encodes record's
171+
relative offset from the beginning of ring buffer data area (in pages). This
172+
allows ``bpf_ringbuf_commit()``/``bpf_ringbuf_discard()`` to accept only the
173+
pointer to the record itself, without requiring also the pointer to ring buffer
174+
itself. Ring buffer memory location will be restored from record metadata
175+
header. This significantly simplifies verifier, as well as improving API
176+
usability.
177+
178+
Producer counter increments are serialized under spinlock, so there is
179+
a strict ordering between reservations. Commits, on the other hand, are
180+
completely lockless and independent. All records become available to consumer
181+
in the order of reservations, but only after all previous records where
182+
already committed. It is thus possible for slow producers to temporarily hold
183+
off submitted records, that were reserved later.
184+
185+
Reservation/commit/consumer protocol is verified by litmus tests in
186+
Documentation/litmus_tests/bpf-rb/_.
187+
188+
One interesting implementation bit, that significantly simplifies (and thus
189+
speeds up as well) implementation of both producers and consumers is how data
190+
area is mapped twice contiguously back-to-back in the virtual memory. This
191+
allows to not take any special measures for samples that have to wrap around
192+
at the end of the circular buffer data area, because the next page after the
193+
last data page would be first data page again, and thus the sample will still
194+
appear completely contiguous in virtual memory. See comment and a simple ASCII
195+
diagram showing this visually in ``bpf_ringbuf_area_alloc()``.
196+
197+
Another feature that distinguishes BPF ringbuf from perf ring buffer is
198+
a self-pacing notifications of new data being availability.
199+
``bpf_ringbuf_commit()`` implementation will send a notification of new record
200+
being available after commit only if consumer has already caught up right up to
201+
the record being committed. If not, consumer still has to catch up and thus
202+
will see new data anyways without needing an extra poll notification.
203+
Benchmarks (see tools/testing/selftests/bpf/benchs/bench_ringbuf.c_) show that
204+
this allows to achieve a very high throughput without having to resort to
205+
tricks like "notify only every Nth sample", which are necessary with perf
206+
buffer. For extreme cases, when BPF program wants more manual control of
207+
notifications, commit/discard/output helpers accept ``BPF_RB_NO_WAKEUP`` and
208+
``BPF_RB_FORCE_WAKEUP`` flags, which give full control over notifications of
209+
data availability, but require extra caution and diligence in using this API.

include/linux/bpf.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ struct bpf_map_ops {
9090
int (*map_direct_value_meta)(const struct bpf_map *map,
9191
u64 imm, u32 *off);
9292
int (*map_mmap)(struct bpf_map *map, struct vm_area_struct *vma);
93+
__poll_t (*map_poll)(struct bpf_map *map, struct file *filp,
94+
struct poll_table_struct *pts);
9395
};
9496

9597
struct bpf_map_memory {
@@ -244,6 +246,9 @@ enum bpf_arg_type {
244246
ARG_PTR_TO_LONG, /* pointer to long */
245247
ARG_PTR_TO_SOCKET, /* pointer to bpf_sock (fullsock) */
246248
ARG_PTR_TO_BTF_ID, /* pointer to in-kernel struct */
249+
ARG_PTR_TO_ALLOC_MEM, /* pointer to dynamically allocated memory */
250+
ARG_PTR_TO_ALLOC_MEM_OR_NULL, /* pointer to dynamically allocated memory or NULL */
251+
ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */
247252
};
248253

249254
/* type of values returned from helper functions */
@@ -255,6 +260,7 @@ enum bpf_return_type {
255260
RET_PTR_TO_SOCKET_OR_NULL, /* returns a pointer to a socket or NULL */
256261
RET_PTR_TO_TCP_SOCK_OR_NULL, /* returns a pointer to a tcp_sock or NULL */
257262
RET_PTR_TO_SOCK_COMMON_OR_NULL, /* returns a pointer to a sock_common or NULL */
263+
RET_PTR_TO_ALLOC_MEM_OR_NULL, /* returns a pointer to dynamically allocated memory or NULL */
258264
};
259265

260266
/* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs
@@ -322,6 +328,8 @@ enum bpf_reg_type {
322328
PTR_TO_XDP_SOCK, /* reg points to struct xdp_sock */
323329
PTR_TO_BTF_ID, /* reg points to kernel struct */
324330
PTR_TO_BTF_ID_OR_NULL, /* reg points to kernel struct or NULL */
331+
PTR_TO_MEM, /* reg points to valid memory region */
332+
PTR_TO_MEM_OR_NULL, /* reg points to valid memory region or NULL */
325333
};
326334

327335
/* The information passed from prog-specific *_is_valid_access
@@ -1611,6 +1619,11 @@ extern const struct bpf_func_proto bpf_tcp_sock_proto;
16111619
extern const struct bpf_func_proto bpf_jiffies64_proto;
16121620
extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
16131621
extern const struct bpf_func_proto bpf_event_output_data_proto;
1622+
extern const struct bpf_func_proto bpf_ringbuf_output_proto;
1623+
extern const struct bpf_func_proto bpf_ringbuf_reserve_proto;
1624+
extern const struct bpf_func_proto bpf_ringbuf_submit_proto;
1625+
extern const struct bpf_func_proto bpf_ringbuf_discard_proto;
1626+
extern const struct bpf_func_proto bpf_ringbuf_query_proto;
16141627

16151628
const struct bpf_func_proto *bpf_tracing_func_proto(
16161629
enum bpf_func_id func_id, const struct bpf_prog *prog);

include/linux/bpf_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_STACK, stack_map_ops)
118118
#if defined(CONFIG_BPF_JIT)
119119
BPF_MAP_TYPE(BPF_MAP_TYPE_STRUCT_OPS, bpf_struct_ops_map_ops)
120120
#endif
121+
BPF_MAP_TYPE(BPF_MAP_TYPE_RINGBUF, ringbuf_map_ops)
121122

122123
BPF_LINK_TYPE(BPF_LINK_TYPE_RAW_TRACEPOINT, raw_tracepoint)
123124
BPF_LINK_TYPE(BPF_LINK_TYPE_TRACING, tracing)

include/linux/bpf_verifier.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ struct bpf_reg_state {
5454

5555
u32 btf_id; /* for PTR_TO_BTF_ID */
5656

57+
u32 mem_size; /* for PTR_TO_MEM | PTR_TO_MEM_OR_NULL */
58+
5759
/* Max size from any of the above. */
5860
unsigned long raw;
5961
};
@@ -63,6 +65,8 @@ struct bpf_reg_state {
6365
* offset, so they can share range knowledge.
6466
* For PTR_TO_MAP_VALUE_OR_NULL this is used to share which map value we
6567
* came from, when one is tested for != NULL.
68+
* For PTR_TO_MEM_OR_NULL this is used to identify memory allocation
69+
* for the purpose of tracking that it's freed.
6670
* For PTR_TO_SOCKET this is used to share which pointers retain the
6771
* same reference to the socket, to determine proper reference freeing.
6872
*/

include/uapi/linux/bpf.h

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ enum bpf_map_type {
147147
BPF_MAP_TYPE_SK_STORAGE,
148148
BPF_MAP_TYPE_DEVMAP_HASH,
149149
BPF_MAP_TYPE_STRUCT_OPS,
150+
BPF_MAP_TYPE_RINGBUF,
150151
};
151152

152153
/* Note that tracing related programs such as
@@ -3157,6 +3158,59 @@ union bpf_attr {
31573158
* **bpf_sk_cgroup_id**\ ().
31583159
* Return
31593160
* The id is returned or 0 in case the id could not be retrieved.
3161+
*
3162+
* void *bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
3163+
* Description
3164+
* Copy *size* bytes from *data* into a ring buffer *ringbuf*.
3165+
* If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
3166+
* new data availability is sent.
3167+
* IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
3168+
* new data availability is sent unconditionally.
3169+
* Return
3170+
* 0, on success;
3171+
* < 0, on error.
3172+
*
3173+
* void *bpf_ringbuf_reserve(void *ringbuf, u64 size, u64 flags)
3174+
* Description
3175+
* Reserve *size* bytes of payload in a ring buffer *ringbuf*.
3176+
* Return
3177+
* Valid pointer with *size* bytes of memory available; NULL,
3178+
* otherwise.
3179+
*
3180+
* void bpf_ringbuf_submit(void *data, u64 flags)
3181+
* Description
3182+
* Submit reserved ring buffer sample, pointed to by *data*.
3183+
* If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
3184+
* new data availability is sent.
3185+
* IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
3186+
* new data availability is sent unconditionally.
3187+
* Return
3188+
* Nothing. Always succeeds.
3189+
*
3190+
* void bpf_ringbuf_discard(void *data, u64 flags)
3191+
* Description
3192+
* Discard reserved ring buffer sample, pointed to by *data*.
3193+
* If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
3194+
* new data availability is sent.
3195+
* IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
3196+
* new data availability is sent unconditionally.
3197+
* Return
3198+
* Nothing. Always succeeds.
3199+
*
3200+
* u64 bpf_ringbuf_query(void *ringbuf, u64 flags)
3201+
* Description
3202+
* Query various characteristics of provided ring buffer. What
3203+
* exactly is queries is determined by *flags*:
3204+
* - BPF_RB_AVAIL_DATA - amount of data not yet consumed;
3205+
* - BPF_RB_RING_SIZE - the size of ring buffer;
3206+
* - BPF_RB_CONS_POS - consumer position (can wrap around);
3207+
* - BPF_RB_PROD_POS - producer(s) position (can wrap around);
3208+
* Data returned is just a momentary snapshots of actual values
3209+
* and could be inaccurate, so this facility should be used to
3210+
* power heuristics and for reporting, not to make 100% correct
3211+
* calculation.
3212+
* Return
3213+
* Requested value, or 0, if flags are not recognized.
31603214
*/
31613215
#define __BPF_FUNC_MAPPER(FN) \
31623216
FN(unspec), \
@@ -3288,7 +3342,12 @@ union bpf_attr {
32883342
FN(seq_printf), \
32893343
FN(seq_write), \
32903344
FN(sk_cgroup_id), \
3291-
FN(sk_ancestor_cgroup_id),
3345+
FN(sk_ancestor_cgroup_id), \
3346+
FN(ringbuf_output), \
3347+
FN(ringbuf_reserve), \
3348+
FN(ringbuf_submit), \
3349+
FN(ringbuf_discard), \
3350+
FN(ringbuf_query),
32923351

32933352
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
32943353
* function eBPF program intends to call
@@ -3398,6 +3457,29 @@ enum {
33983457
BPF_F_GET_BRANCH_RECORDS_SIZE = (1ULL << 0),
33993458
};
34003459

3460+
/* BPF_FUNC_bpf_ringbuf_commit, BPF_FUNC_bpf_ringbuf_discard, and
3461+
* BPF_FUNC_bpf_ringbuf_output flags.
3462+
*/
3463+
enum {
3464+
BPF_RB_NO_WAKEUP = (1ULL << 0),
3465+
BPF_RB_FORCE_WAKEUP = (1ULL << 1),
3466+
};
3467+
3468+
/* BPF_FUNC_bpf_ringbuf_query flags */
3469+
enum {
3470+
BPF_RB_AVAIL_DATA = 0,
3471+
BPF_RB_RING_SIZE = 1,
3472+
BPF_RB_CONS_POS = 2,
3473+
BPF_RB_PROD_POS = 3,
3474+
};
3475+
3476+
/* BPF ring buffer constants */
3477+
enum {
3478+
BPF_RINGBUF_BUSY_BIT = (1U << 31),
3479+
BPF_RINGBUF_DISCARD_BIT = (1U << 30),
3480+
BPF_RINGBUF_HDR_SZ = 8,
3481+
};
3482+
34013483
/* Mode for BPF_FUNC_skb_adjust_room helper. */
34023484
enum bpf_adj_room_mode {
34033485
BPF_ADJ_ROOM_NET,

0 commit comments

Comments
 (0)