bpf: Annotate context types
Annotate BPF program context types with program-side type and kernel-side type. This type information is used by the verifier. btf_get_prog_ctx_type() is used in the later patches to verify that BTF type of ctx in BPF program matches to kernel expected ctx type. For example, the XDP program type is: BPF_PROG_TYPE(BPF_PROG_TYPE_XDP, xdp, struct xdp_md, struct xdp_buff) That means that XDP program should be written as: int xdp_prog(struct xdp_md *ctx) { ... } Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Song Liu <songliubraving@fb.com> Link: https://lore.kernel.org/bpf/20191114185720.1641606-16-ast@kernel.org
This commit is contained in:
parent
9cc31b3a09
commit
91cc1a9974
6 changed files with 176 additions and 43 deletions
|
@ -747,7 +747,7 @@ DECLARE_PER_CPU(int, bpf_prog_active);
|
||||||
extern const struct file_operations bpf_map_fops;
|
extern const struct file_operations bpf_map_fops;
|
||||||
extern const struct file_operations bpf_prog_fops;
|
extern const struct file_operations bpf_prog_fops;
|
||||||
|
|
||||||
#define BPF_PROG_TYPE(_id, _name) \
|
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
|
||||||
extern const struct bpf_prog_ops _name ## _prog_ops; \
|
extern const struct bpf_prog_ops _name ## _prog_ops; \
|
||||||
extern const struct bpf_verifier_ops _name ## _verifier_ops;
|
extern const struct bpf_verifier_ops _name ## _verifier_ops;
|
||||||
#define BPF_MAP_TYPE(_id, _ops) \
|
#define BPF_MAP_TYPE(_id, _ops) \
|
||||||
|
@ -1213,6 +1213,15 @@ static inline u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_INET
|
#ifdef CONFIG_INET
|
||||||
|
struct sk_reuseport_kern {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct sock *sk;
|
||||||
|
struct sock *selected_sk;
|
||||||
|
void *data_end;
|
||||||
|
u32 hash;
|
||||||
|
u32 reuseport_id;
|
||||||
|
bool bind_inany;
|
||||||
|
};
|
||||||
bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
|
bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
|
||||||
struct bpf_insn_access_aux *info);
|
struct bpf_insn_access_aux *info);
|
||||||
|
|
||||||
|
|
|
@ -2,42 +2,68 @@
|
||||||
/* internal file - do not include directly */
|
/* internal file - do not include directly */
|
||||||
|
|
||||||
#ifdef CONFIG_NET
|
#ifdef CONFIG_NET
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_SOCKET_FILTER, sk_filter)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_SOCKET_FILTER, sk_filter,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_SCHED_CLS, tc_cls_act)
|
struct __sk_buff, struct sk_buff)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_SCHED_ACT, tc_cls_act)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_SCHED_CLS, tc_cls_act,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_XDP, xdp)
|
struct __sk_buff, struct sk_buff)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_SCHED_ACT, tc_cls_act,
|
||||||
|
struct __sk_buff, struct sk_buff)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_XDP, xdp,
|
||||||
|
struct xdp_md, struct xdp_buff)
|
||||||
#ifdef CONFIG_CGROUP_BPF
|
#ifdef CONFIG_CGROUP_BPF
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SKB, cg_skb)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SKB, cg_skb,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK, cg_sock)
|
struct __sk_buff, struct sk_buff)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, cg_sock_addr)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK, cg_sock,
|
||||||
|
struct bpf_sock, struct sock)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, cg_sock_addr,
|
||||||
|
struct bpf_sock_addr, struct bpf_sock_addr_kern)
|
||||||
#endif
|
#endif
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_IN, lwt_in)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_IN, lwt_in,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_OUT, lwt_out)
|
struct __sk_buff, struct sk_buff)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_XMIT, lwt_xmit)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_OUT, lwt_out,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_SEG6LOCAL, lwt_seg6local)
|
struct __sk_buff, struct sk_buff)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_SOCK_OPS, sock_ops)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_XMIT, lwt_xmit,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_SK_SKB, sk_skb)
|
struct __sk_buff, struct sk_buff)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_SK_MSG, sk_msg)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_LWT_SEG6LOCAL, lwt_seg6local,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_FLOW_DISSECTOR, flow_dissector)
|
struct __sk_buff, struct sk_buff)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_SOCK_OPS, sock_ops,
|
||||||
|
struct bpf_sock_ops, struct bpf_sock_ops_kern)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_SK_SKB, sk_skb,
|
||||||
|
struct __sk_buff, struct sk_buff)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_SK_MSG, sk_msg,
|
||||||
|
struct sk_msg_md, struct sk_msg)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_FLOW_DISSECTOR, flow_dissector,
|
||||||
|
struct __sk_buff, struct bpf_flow_dissector)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BPF_EVENTS
|
#ifdef CONFIG_BPF_EVENTS
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_KPROBE, kprobe)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_KPROBE, kprobe,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_TRACEPOINT, tracepoint)
|
bpf_user_pt_regs_t, struct pt_regs)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_PERF_EVENT, perf_event)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_TRACEPOINT, tracepoint,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT, raw_tracepoint)
|
__u64, u64)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, raw_tracepoint_writable)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_PERF_EVENT, perf_event,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_TRACING, tracing)
|
struct bpf_perf_event_data, struct bpf_perf_event_data_kern)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT, raw_tracepoint,
|
||||||
|
struct bpf_raw_tracepoint_args, u64)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, raw_tracepoint_writable,
|
||||||
|
struct bpf_raw_tracepoint_args, u64)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_TRACING, tracing,
|
||||||
|
void *, void *)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CGROUP_BPF
|
#ifdef CONFIG_CGROUP_BPF
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev,
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SYSCTL, cg_sysctl)
|
struct bpf_cgroup_dev_ctx, struct bpf_cgroup_dev_ctx)
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCKOPT, cg_sockopt)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SYSCTL, cg_sysctl,
|
||||||
|
struct bpf_sysctl, struct bpf_sysctl_kern)
|
||||||
|
BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCKOPT, cg_sockopt,
|
||||||
|
struct bpf_sockopt, struct bpf_sockopt_kern)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BPF_LIRC_MODE2
|
#ifdef CONFIG_BPF_LIRC_MODE2
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_LIRC_MODE2, lirc_mode2)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_LIRC_MODE2, lirc_mode2,
|
||||||
|
__u32, u32)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_INET
|
#ifdef CONFIG_INET
|
||||||
BPF_PROG_TYPE(BPF_PROG_TYPE_SK_REUSEPORT, sk_reuseport)
|
BPF_PROG_TYPE(BPF_PROG_TYPE_SK_REUSEPORT, sk_reuseport,
|
||||||
|
struct sk_reuseport_md, struct sk_reuseport_kern)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
|
BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
|
||||||
|
|
114
kernel/bpf/btf.c
114
kernel/bpf/btf.c
|
@ -2,6 +2,8 @@
|
||||||
/* Copyright (c) 2018 Facebook */
|
/* Copyright (c) 2018 Facebook */
|
||||||
|
|
||||||
#include <uapi/linux/btf.h>
|
#include <uapi/linux/btf.h>
|
||||||
|
#include <uapi/linux/bpf.h>
|
||||||
|
#include <uapi/linux/bpf_perf_event.h>
|
||||||
#include <uapi/linux/types.h>
|
#include <uapi/linux/types.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
@ -16,6 +18,9 @@
|
||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
#include <linux/bpf_verifier.h>
|
#include <linux/bpf_verifier.h>
|
||||||
#include <linux/btf.h>
|
#include <linux/btf.h>
|
||||||
|
#include <linux/skmsg.h>
|
||||||
|
#include <linux/perf_event.h>
|
||||||
|
#include <net/sock.h>
|
||||||
|
|
||||||
/* BTF (BPF Type Format) is the meta data format which describes
|
/* BTF (BPF Type Format) is the meta data format which describes
|
||||||
* the data types of BPF program/map. Hence, it basically focus
|
* the data types of BPF program/map. Hence, it basically focus
|
||||||
|
@ -3439,13 +3444,98 @@ errout:
|
||||||
|
|
||||||
extern char __weak _binary__btf_vmlinux_bin_start[];
|
extern char __weak _binary__btf_vmlinux_bin_start[];
|
||||||
extern char __weak _binary__btf_vmlinux_bin_end[];
|
extern char __weak _binary__btf_vmlinux_bin_end[];
|
||||||
|
extern struct btf *btf_vmlinux;
|
||||||
|
|
||||||
|
#define BPF_MAP_TYPE(_id, _ops)
|
||||||
|
static union {
|
||||||
|
struct bpf_ctx_convert {
|
||||||
|
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
|
||||||
|
prog_ctx_type _id##_prog; \
|
||||||
|
kern_ctx_type _id##_kern;
|
||||||
|
#include <linux/bpf_types.h>
|
||||||
|
#undef BPF_PROG_TYPE
|
||||||
|
} *__t;
|
||||||
|
/* 't' is written once under lock. Read many times. */
|
||||||
|
const struct btf_type *t;
|
||||||
|
} bpf_ctx_convert;
|
||||||
|
enum {
|
||||||
|
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
|
||||||
|
__ctx_convert##_id,
|
||||||
|
#include <linux/bpf_types.h>
|
||||||
|
#undef BPF_PROG_TYPE
|
||||||
|
};
|
||||||
|
static u8 bpf_ctx_convert_map[] = {
|
||||||
|
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
|
||||||
|
[_id] = __ctx_convert##_id,
|
||||||
|
#include <linux/bpf_types.h>
|
||||||
|
#undef BPF_PROG_TYPE
|
||||||
|
};
|
||||||
|
#undef BPF_MAP_TYPE
|
||||||
|
|
||||||
|
static const struct btf_member *
|
||||||
|
btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
|
||||||
|
const struct btf_type *t, enum bpf_prog_type prog_type)
|
||||||
|
{
|
||||||
|
const struct btf_type *conv_struct;
|
||||||
|
const struct btf_type *ctx_struct;
|
||||||
|
const struct btf_member *ctx_type;
|
||||||
|
const char *tname, *ctx_tname;
|
||||||
|
|
||||||
|
conv_struct = bpf_ctx_convert.t;
|
||||||
|
if (!conv_struct) {
|
||||||
|
bpf_log(log, "btf_vmlinux is malformed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
t = btf_type_by_id(btf, t->type);
|
||||||
|
while (btf_type_is_modifier(t))
|
||||||
|
t = btf_type_by_id(btf, t->type);
|
||||||
|
if (!btf_type_is_struct(t)) {
|
||||||
|
/* Only pointer to struct is supported for now.
|
||||||
|
* That means that BPF_PROG_TYPE_TRACEPOINT with BTF
|
||||||
|
* is not supported yet.
|
||||||
|
* BPF_PROG_TYPE_RAW_TRACEPOINT is fine.
|
||||||
|
*/
|
||||||
|
bpf_log(log, "BPF program ctx type is not a struct\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tname = btf_name_by_offset(btf, t->name_off);
|
||||||
|
if (!tname) {
|
||||||
|
bpf_log(log, "BPF program ctx struct doesn't have a name\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* prog_type is valid bpf program type. No need for bounds check. */
|
||||||
|
ctx_type = btf_type_member(conv_struct) + bpf_ctx_convert_map[prog_type] * 2;
|
||||||
|
/* ctx_struct is a pointer to prog_ctx_type in vmlinux.
|
||||||
|
* Like 'struct __sk_buff'
|
||||||
|
*/
|
||||||
|
ctx_struct = btf_type_by_id(btf_vmlinux, ctx_type->type);
|
||||||
|
if (!ctx_struct)
|
||||||
|
/* should not happen */
|
||||||
|
return NULL;
|
||||||
|
ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_struct->name_off);
|
||||||
|
if (!ctx_tname) {
|
||||||
|
/* should not happen */
|
||||||
|
bpf_log(log, "Please fix kernel include/linux/bpf_types.h\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* only compare that prog's ctx type name is the same as
|
||||||
|
* kernel expects. No need to compare field by field.
|
||||||
|
* It's ok for bpf prog to do:
|
||||||
|
* struct __sk_buff {};
|
||||||
|
* int socket_filter_bpf_prog(struct __sk_buff *skb)
|
||||||
|
* { // no fields of skb are ever used }
|
||||||
|
*/
|
||||||
|
if (strcmp(ctx_tname, tname))
|
||||||
|
return NULL;
|
||||||
|
return ctx_type;
|
||||||
|
}
|
||||||
|
|
||||||
struct btf *btf_parse_vmlinux(void)
|
struct btf *btf_parse_vmlinux(void)
|
||||||
{
|
{
|
||||||
struct btf_verifier_env *env = NULL;
|
struct btf_verifier_env *env = NULL;
|
||||||
struct bpf_verifier_log *log;
|
struct bpf_verifier_log *log;
|
||||||
struct btf *btf = NULL;
|
struct btf *btf = NULL;
|
||||||
int err;
|
int err, i;
|
||||||
|
|
||||||
env = kzalloc(sizeof(*env), GFP_KERNEL | __GFP_NOWARN);
|
env = kzalloc(sizeof(*env), GFP_KERNEL | __GFP_NOWARN);
|
||||||
if (!env)
|
if (!env)
|
||||||
|
@ -3479,6 +3569,26 @@ struct btf *btf_parse_vmlinux(void)
|
||||||
if (err)
|
if (err)
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
|
/* find struct bpf_ctx_convert for type checking later */
|
||||||
|
for (i = 1; i <= btf->nr_types; i++) {
|
||||||
|
const struct btf_type *t;
|
||||||
|
const char *tname;
|
||||||
|
|
||||||
|
t = btf_type_by_id(btf, i);
|
||||||
|
if (!__btf_type_is_struct(t))
|
||||||
|
continue;
|
||||||
|
tname = __btf_name_by_offset(btf, t->name_off);
|
||||||
|
if (!strcmp(tname, "bpf_ctx_convert")) {
|
||||||
|
/* btf_parse_vmlinux() runs under bpf_verifier_lock */
|
||||||
|
bpf_ctx_convert.t = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i > btf->nr_types) {
|
||||||
|
err = -ENOENT;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
btf_verifier_env_free(env);
|
btf_verifier_env_free(env);
|
||||||
refcount_set(&btf->refcnt, 1);
|
refcount_set(&btf->refcnt, 1);
|
||||||
return btf;
|
return btf;
|
||||||
|
@ -3492,8 +3602,6 @@ errout:
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct btf *btf_vmlinux;
|
|
||||||
|
|
||||||
bool btf_ctx_access(int off, int size, enum bpf_access_type type,
|
bool btf_ctx_access(int off, int size, enum bpf_access_type type,
|
||||||
const struct bpf_prog *prog,
|
const struct bpf_prog *prog,
|
||||||
struct bpf_insn_access_aux *info)
|
struct bpf_insn_access_aux *info)
|
||||||
|
|
|
@ -43,7 +43,7 @@ static DEFINE_SPINLOCK(map_idr_lock);
|
||||||
int sysctl_unprivileged_bpf_disabled __read_mostly;
|
int sysctl_unprivileged_bpf_disabled __read_mostly;
|
||||||
|
|
||||||
static const struct bpf_map_ops * const bpf_map_types[] = {
|
static const struct bpf_map_ops * const bpf_map_types[] = {
|
||||||
#define BPF_PROG_TYPE(_id, _ops)
|
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
|
||||||
#define BPF_MAP_TYPE(_id, _ops) \
|
#define BPF_MAP_TYPE(_id, _ops) \
|
||||||
[_id] = &_ops,
|
[_id] = &_ops,
|
||||||
#include <linux/bpf_types.h>
|
#include <linux/bpf_types.h>
|
||||||
|
@ -1189,7 +1189,7 @@ err_put:
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct bpf_prog_ops * const bpf_prog_types[] = {
|
static const struct bpf_prog_ops * const bpf_prog_types[] = {
|
||||||
#define BPF_PROG_TYPE(_id, _name) \
|
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
|
||||||
[_id] = & _name ## _prog_ops,
|
[_id] = & _name ## _prog_ops,
|
||||||
#define BPF_MAP_TYPE(_id, _ops)
|
#define BPF_MAP_TYPE(_id, _ops)
|
||||||
#include <linux/bpf_types.h>
|
#include <linux/bpf_types.h>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "disasm.h"
|
#include "disasm.h"
|
||||||
|
|
||||||
static const struct bpf_verifier_ops * const bpf_verifier_ops[] = {
|
static const struct bpf_verifier_ops * const bpf_verifier_ops[] = {
|
||||||
#define BPF_PROG_TYPE(_id, _name) \
|
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
|
||||||
[_id] = & _name ## _verifier_ops,
|
[_id] = & _name ## _verifier_ops,
|
||||||
#define BPF_MAP_TYPE(_id, _ops)
|
#define BPF_MAP_TYPE(_id, _ops)
|
||||||
#include <linux/bpf_types.h>
|
#include <linux/bpf_types.h>
|
||||||
|
|
|
@ -8684,16 +8684,6 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_INET
|
#ifdef CONFIG_INET
|
||||||
struct sk_reuseport_kern {
|
|
||||||
struct sk_buff *skb;
|
|
||||||
struct sock *sk;
|
|
||||||
struct sock *selected_sk;
|
|
||||||
void *data_end;
|
|
||||||
u32 hash;
|
|
||||||
u32 reuseport_id;
|
|
||||||
bool bind_inany;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void bpf_init_reuseport_kern(struct sk_reuseport_kern *reuse_kern,
|
static void bpf_init_reuseport_kern(struct sk_reuseport_kern *reuse_kern,
|
||||||
struct sock_reuseport *reuse,
|
struct sock_reuseport *reuse,
|
||||||
struct sock *sk, struct sk_buff *skb,
|
struct sock *sk, struct sk_buff *skb,
|
||||||
|
|
Loading…
Add table
Reference in a new issue