Commit e8567951 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Daniel Borkmann says:

====================
pull-request: bpf-next 2018-10-16

The following pull-request contains BPF updates for your *net-next* tree.

The main changes are:

1) Convert BPF sockmap and kTLS to both use a new sk_msg API and enable
   sk_msg BPF integration for the latter, from Daniel and John.

2) Enable BPF syscall side to indicate for maps that they do not support
   a map lookup operation as opposed to just missing key, from Prashant.

3) Add bpftool map create command which after map creation pins the
   map into bpf fs for further processing, from Jakub.

4) Add bpftool support for attaching programs to maps allowing sock_map
   and sock_hash to be used from bpftool, from John.

5) Improve syscall BPF map update/delete path for map-in-map types to
   wait a RCU grace period for pending references to complete, from Daniel.

6) Couple of follow-up fixes for the BPF socket lookup to get it
   enabled also when IPv6 is compiled as a module, from Joe.

7) Fix a generic-XDP bug to handle the case when the Ethernet header
   was mangled and thus update skb's protocol and data, from Jesper.

8) Add a missing BTF header length check between header copies from
   user space, from Wenwen.

9) Minor fixups in libbpf to use __u32 instead u32 types and include
   proper perf_event.h uapi header instead of perf internal one, from Yonghong.

10) Allow to pass user-defined flags through EXTRA_CFLAGS and EXTRA_LDFLAGS
    to bpftool's build, from Jiri.

11) BPF kselftest tweaks to add LWTUNNEL to config fragment and to install
    with_addr.sh script from flow dissector selftest, from Anders.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c45d7150 0b592b5a
...@@ -8193,6 +8193,16 @@ S: Maintained ...@@ -8193,6 +8193,16 @@ S: Maintained
F: net/l3mdev F: net/l3mdev
F: include/net/l3mdev.h F: include/net/l3mdev.h
L7 BPF FRAMEWORK
M: John Fastabend <john.fastabend@gmail.com>
M: Daniel Borkmann <daniel@iogearbox.net>
L: netdev@vger.kernel.org
S: Maintained
F: include/linux/skmsg.h
F: net/core/skmsg.c
F: net/core/sock_map.c
F: net/ipv4/tcp_bpf.c
LANTIQ / INTEL Ethernet drivers LANTIQ / INTEL Ethernet drivers
M: Hauke Mehrtens <hauke@hauke-m.de> M: Hauke Mehrtens <hauke@hauke-m.de>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
......
...@@ -737,32 +737,17 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map) ...@@ -737,32 +737,17 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
} }
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */ #endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
#if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_INET) #if defined(CONFIG_BPF_STREAM_PARSER)
struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key); int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which);
struct sock *__sock_hash_lookup_elem(struct bpf_map *map, void *key); int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
int sockmap_get_from_fd(const union bpf_attr *attr, int type,
struct bpf_prog *prog);
#else #else
static inline struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key) static inline int sock_map_prog_update(struct bpf_map *map,
{ struct bpf_prog *prog, u32 which)
return NULL;
}
static inline struct sock *__sock_hash_lookup_elem(struct bpf_map *map,
void *key)
{
return NULL;
}
static inline int sock_map_prog(struct bpf_map *map,
struct bpf_prog *prog,
u32 type)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int sockmap_get_from_fd(const union bpf_attr *attr, int type, static inline int sock_map_get_from_fd(const union bpf_attr *attr,
struct bpf_prog *prog) struct bpf_prog *prog)
{ {
return -EINVAL; return -EINVAL;
...@@ -839,6 +824,10 @@ extern const struct bpf_func_proto bpf_get_stack_proto; ...@@ -839,6 +824,10 @@ extern const struct bpf_func_proto bpf_get_stack_proto;
extern const struct bpf_func_proto bpf_sock_map_update_proto; extern const struct bpf_func_proto bpf_sock_map_update_proto;
extern const struct bpf_func_proto bpf_sock_hash_update_proto; extern const struct bpf_func_proto bpf_sock_hash_update_proto;
extern const struct bpf_func_proto bpf_get_current_cgroup_id_proto; extern const struct bpf_func_proto bpf_get_current_cgroup_id_proto;
extern const struct bpf_func_proto bpf_msg_redirect_hash_proto;
extern const struct bpf_func_proto bpf_msg_redirect_map_proto;
extern const struct bpf_func_proto bpf_sk_redirect_hash_proto;
extern const struct bpf_func_proto bpf_sk_redirect_map_proto;
extern const struct bpf_func_proto bpf_get_local_storage_proto; extern const struct bpf_func_proto bpf_get_local_storage_proto;
......
...@@ -57,7 +57,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_of_maps_map_ops) ...@@ -57,7 +57,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_of_maps_map_ops)
BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops)
#ifdef CONFIG_NET #ifdef CONFIG_NET
BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops)
#if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_INET) #if defined(CONFIG_BPF_STREAM_PARSER)
BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops)
BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops)
#endif #endif
......
...@@ -520,24 +520,6 @@ struct bpf_skb_data_end { ...@@ -520,24 +520,6 @@ struct bpf_skb_data_end {
void *data_end; void *data_end;
}; };
struct sk_msg_buff {
void *data;
void *data_end;
__u32 apply_bytes;
__u32 cork_bytes;
int sg_copybreak;
int sg_start;
int sg_curr;
int sg_end;
struct scatterlist sg_data[MAX_SKB_FRAGS];
bool sg_copy[MAX_SKB_FRAGS];
__u32 flags;
struct sock *sk_redir;
struct sock *sk;
struct sk_buff *skb;
struct list_head list;
};
struct bpf_redirect_info { struct bpf_redirect_info {
u32 ifindex; u32 ifindex;
u32 flags; u32 flags;
...@@ -833,9 +815,6 @@ void xdp_do_flush_map(void); ...@@ -833,9 +815,6 @@ void xdp_do_flush_map(void);
void bpf_warn_invalid_xdp_action(u32 act); void bpf_warn_invalid_xdp_action(u32 act);
struct sock *do_sk_redirect_map(struct sk_buff *skb);
struct sock *do_msg_redirect_map(struct sk_msg_buff *md);
#ifdef CONFIG_INET #ifdef CONFIG_INET
struct sock *bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk, struct sock *bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
struct bpf_prog *prog, struct sk_buff *skb, struct bpf_prog *prog, struct sk_buff *skb,
......
This diff is collapsed.
...@@ -265,6 +265,11 @@ extern const struct ipv6_stub *ipv6_stub __read_mostly; ...@@ -265,6 +265,11 @@ extern const struct ipv6_stub *ipv6_stub __read_mostly;
struct ipv6_bpf_stub { struct ipv6_bpf_stub {
int (*inet6_bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len, int (*inet6_bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len,
bool force_bind_address_no_port, bool with_lock); bool force_bind_address_no_port, bool with_lock);
struct sock *(*udp6_lib_lookup)(struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
int dif, int sdif, struct udp_table *tbl,
struct sk_buff *skb);
}; };
extern const struct ipv6_bpf_stub *ipv6_bpf_stub __read_mostly; extern const struct ipv6_bpf_stub *ipv6_bpf_stub __read_mostly;
......
...@@ -2214,10 +2214,6 @@ static inline struct page_frag *sk_page_frag(struct sock *sk) ...@@ -2214,10 +2214,6 @@ static inline struct page_frag *sk_page_frag(struct sock *sk)
bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag); bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag);
int sk_alloc_sg(struct sock *sk, int len, struct scatterlist *sg,
int sg_start, int *sg_curr, unsigned int *sg_size,
int first_coalesce);
/* /*
* Default write policy as shown to user space via poll/select/SIGIO * Default write policy as shown to user space via poll/select/SIGIO
*/ */
......
...@@ -858,6 +858,21 @@ static inline void bpf_compute_data_end_sk_skb(struct sk_buff *skb) ...@@ -858,6 +858,21 @@ static inline void bpf_compute_data_end_sk_skb(struct sk_buff *skb)
TCP_SKB_CB(skb)->bpf.data_end = skb->data + skb_headlen(skb); TCP_SKB_CB(skb)->bpf.data_end = skb->data + skb_headlen(skb);
} }
static inline bool tcp_skb_bpf_ingress(const struct sk_buff *skb)
{
return TCP_SKB_CB(skb)->bpf.flags & BPF_F_INGRESS;
}
static inline struct sock *tcp_skb_bpf_redirect_fetch(struct sk_buff *skb)
{
return TCP_SKB_CB(skb)->bpf.sk_redir;
}
static inline void tcp_skb_bpf_redirect_clear(struct sk_buff *skb)
{
TCP_SKB_CB(skb)->bpf.sk_redir = NULL;
}
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
/* This is the variant of inet6_iif() that must be used by TCP, /* This is the variant of inet6_iif() that must be used by TCP,
* as TCP moves IP6CB into a different location in skb->cb[] * as TCP moves IP6CB into a different location in skb->cb[]
...@@ -2057,7 +2072,6 @@ struct tcp_ulp_ops { ...@@ -2057,7 +2072,6 @@ struct tcp_ulp_ops {
int tcp_register_ulp(struct tcp_ulp_ops *type); int tcp_register_ulp(struct tcp_ulp_ops *type);
void tcp_unregister_ulp(struct tcp_ulp_ops *type); void tcp_unregister_ulp(struct tcp_ulp_ops *type);
int tcp_set_ulp(struct sock *sk, const char *name); int tcp_set_ulp(struct sock *sk, const char *name);
int tcp_set_ulp_id(struct sock *sk, const int ulp);
void tcp_get_available_ulp(char *buf, size_t len); void tcp_get_available_ulp(char *buf, size_t len);
void tcp_cleanup_ulp(struct sock *sk); void tcp_cleanup_ulp(struct sock *sk);
...@@ -2065,6 +2079,18 @@ void tcp_cleanup_ulp(struct sock *sk); ...@@ -2065,6 +2079,18 @@ void tcp_cleanup_ulp(struct sock *sk);
__MODULE_INFO(alias, alias_userspace, name); \ __MODULE_INFO(alias, alias_userspace, name); \
__MODULE_INFO(alias, alias_tcp_ulp, "tcp-ulp-" name) __MODULE_INFO(alias, alias_tcp_ulp, "tcp-ulp-" name)
struct sk_msg;
struct sk_psock;
int tcp_bpf_init(struct sock *sk);
void tcp_bpf_reinit(struct sock *sk);
int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, u32 bytes,
int flags);
int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len);
int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
struct msghdr *msg, int len);
/* Call BPF_SOCK_OPS program that returns an int. If the return value /* Call BPF_SOCK_OPS program that returns an int. If the return value
* is < 0, then the BPF op failed (for example if the loaded BPF * is < 0, then the BPF op failed (for example if the loaded BPF
* program does not support the chosen operation or there is no BPF * program does not support the chosen operation or there is no BPF
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/skmsg.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/strparser.h> #include <net/strparser.h>
#include <crypto/aead.h> #include <crypto/aead.h>
...@@ -103,15 +105,13 @@ struct tls_rec { ...@@ -103,15 +105,13 @@ struct tls_rec {
int tx_flags; int tx_flags;
int inplace_crypto; int inplace_crypto;
/* AAD | sg_plaintext_data | sg_tag */ struct sk_msg msg_plaintext;
struct scatterlist sg_plaintext_data[MAX_SKB_FRAGS + 1]; struct sk_msg msg_encrypted;
/* AAD | sg_encrypted_data (data contain overhead for hdr&iv&tag) */
struct scatterlist sg_encrypted_data[MAX_SKB_FRAGS + 1];
unsigned int sg_plaintext_size; /* AAD | msg_plaintext.sg.data | sg_tag */
unsigned int sg_encrypted_size; struct scatterlist sg_aead_in[2];
int sg_plaintext_num_elem; /* AAD | msg_encrypted.sg.data (data contains overhead for hdr & iv & tag) */
int sg_encrypted_num_elem; struct scatterlist sg_aead_out[2];
char aad_space[TLS_AAD_SPACE_SIZE]; char aad_space[TLS_AAD_SPACE_SIZE];
struct aead_request aead_req; struct aead_request aead_req;
...@@ -142,8 +142,7 @@ struct tls_sw_context_rx { ...@@ -142,8 +142,7 @@ struct tls_sw_context_rx {
struct strparser strp; struct strparser strp;
void (*saved_data_ready)(struct sock *sk); void (*saved_data_ready)(struct sock *sk);
unsigned int (*sk_poll)(struct file *file, struct socket *sock,
struct poll_table_struct *wait);
struct sk_buff *recv_pkt; struct sk_buff *recv_pkt;
u8 control; u8 control;
bool decrypted; bool decrypted;
...@@ -223,8 +222,8 @@ struct tls_context { ...@@ -223,8 +222,8 @@ struct tls_context {
unsigned long flags; unsigned long flags;
bool in_tcp_sendpages; bool in_tcp_sendpages;
bool pending_open_record_frags;
u16 pending_open_record_frags;
int (*push_pending_record)(struct sock *sk, int flags); int (*push_pending_record)(struct sock *sk, int flags);
void (*sk_write_space)(struct sock *sk); void (*sk_write_space)(struct sock *sk);
...@@ -272,8 +271,7 @@ void tls_sw_free_resources_rx(struct sock *sk); ...@@ -272,8 +271,7 @@ void tls_sw_free_resources_rx(struct sock *sk);
void tls_sw_release_resources_rx(struct sock *sk); void tls_sw_release_resources_rx(struct sock *sk);
int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len); int nonblock, int flags, int *addr_len);
unsigned int tls_sw_poll(struct file *file, struct socket *sock, bool tls_sw_stream_read(const struct sock *sk);
struct poll_table_struct *wait);
ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
struct pipe_inode_info *pipe, struct pipe_inode_info *pipe,
size_t len, unsigned int flags); size_t len, unsigned int flags);
......
...@@ -13,11 +13,6 @@ ifeq ($(CONFIG_XDP_SOCKETS),y) ...@@ -13,11 +13,6 @@ ifeq ($(CONFIG_XDP_SOCKETS),y)
obj-$(CONFIG_BPF_SYSCALL) += xskmap.o obj-$(CONFIG_BPF_SYSCALL) += xskmap.o
endif endif
obj-$(CONFIG_BPF_SYSCALL) += offload.o obj-$(CONFIG_BPF_SYSCALL) += offload.o
ifeq ($(CONFIG_STREAM_PARSER),y)
ifeq ($(CONFIG_INET),y)
obj-$(CONFIG_BPF_SYSCALL) += sockmap.o
endif
endif
endif endif
ifeq ($(CONFIG_PERF_EVENTS),y) ifeq ($(CONFIG_PERF_EVENTS),y)
obj-$(CONFIG_BPF_SYSCALL) += stackmap.o obj-$(CONFIG_BPF_SYSCALL) += stackmap.o
......
...@@ -449,7 +449,7 @@ static void fd_array_map_free(struct bpf_map *map) ...@@ -449,7 +449,7 @@ static void fd_array_map_free(struct bpf_map *map)
static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key) static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
{ {
return NULL; return ERR_PTR(-EOPNOTSUPP);
} }
/* only called from syscall */ /* only called from syscall */
......
...@@ -2114,6 +2114,9 @@ static int btf_parse_hdr(struct btf_verifier_env *env, void __user *btf_data, ...@@ -2114,6 +2114,9 @@ static int btf_parse_hdr(struct btf_verifier_env *env, void __user *btf_data,
hdr = &btf->hdr; hdr = &btf->hdr;
if (hdr->hdr_len != hdr_len)
return -EINVAL;
btf_verifier_log_hdr(env, btf_data_size); btf_verifier_log_hdr(env, btf_data_size);
if (hdr->magic != BTF_MAGIC) { if (hdr->magic != BTF_MAGIC) {
......
...@@ -1792,8 +1792,6 @@ const struct bpf_func_proto bpf_ktime_get_ns_proto __weak; ...@@ -1792,8 +1792,6 @@ const struct bpf_func_proto bpf_ktime_get_ns_proto __weak;
const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak; const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak;
const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak; const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
const struct bpf_func_proto bpf_get_current_comm_proto __weak; const struct bpf_func_proto bpf_get_current_comm_proto __weak;
const struct bpf_func_proto bpf_sock_map_update_proto __weak;
const struct bpf_func_proto bpf_sock_hash_update_proto __weak;
const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak; const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
const struct bpf_func_proto bpf_get_local_storage_proto __weak; const struct bpf_func_proto bpf_get_local_storage_proto __weak;
......
This diff is collapsed.
...@@ -505,7 +505,7 @@ const struct bpf_func_proto bpf_get_stack_proto = { ...@@ -505,7 +505,7 @@ const struct bpf_func_proto bpf_get_stack_proto = {
/* Called from eBPF program */ /* Called from eBPF program */
static void *stack_map_lookup_elem(struct bpf_map *map, void *key) static void *stack_map_lookup_elem(struct bpf_map *map, void *key)
{ {
return NULL; return ERR_PTR(-EOPNOTSUPP);
} }
/* Called from syscall */ /* Called from syscall */
......
...@@ -719,10 +719,15 @@ static int map_lookup_elem(union bpf_attr *attr) ...@@ -719,10 +719,15 @@ static int map_lookup_elem(union bpf_attr *attr)
} else { } else {
rcu_read_lock(); rcu_read_lock();
ptr = map->ops->map_lookup_elem(map, key); ptr = map->ops->map_lookup_elem(map, key);
if (ptr) if (IS_ERR(ptr)) {
err = PTR_ERR(ptr);
} else if (!ptr) {
err = -ENOENT;
} else {
err = 0;
memcpy(value, ptr, value_size); memcpy(value, ptr, value_size);
}
rcu_read_unlock(); rcu_read_unlock();
err = ptr ? 0 : -ENOENT;
} }
if (err) if (err)
...@@ -743,6 +748,17 @@ static int map_lookup_elem(union bpf_attr *attr) ...@@ -743,6 +748,17 @@ static int map_lookup_elem(union bpf_attr *attr)
return err; return err;
} }
static void maybe_wait_bpf_programs(struct bpf_map *map)
{
/* Wait for any running BPF programs to complete so that
* userspace, when we return to it, knows that all programs
* that could be running use the new map value.
*/
if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
synchronize_rcu();
}
#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
static int map_update_elem(union bpf_attr *attr) static int map_update_elem(union bpf_attr *attr)
...@@ -837,6 +853,7 @@ static int map_update_elem(union bpf_attr *attr) ...@@ -837,6 +853,7 @@ static int map_update_elem(union bpf_attr *attr)
} }
__this_cpu_dec(bpf_prog_active); __this_cpu_dec(bpf_prog_active);
preempt_enable(); preempt_enable();
maybe_wait_bpf_programs(map);
out: out:
free_value: free_value:
kfree(value); kfree(value);
...@@ -889,6 +906,7 @@ static int map_delete_elem(union bpf_attr *attr) ...@@ -889,6 +906,7 @@ static int map_delete_elem(union bpf_attr *attr)
rcu_read_unlock(); rcu_read_unlock();
__this_cpu_dec(bpf_prog_active); __this_cpu_dec(bpf_prog_active);
preempt_enable(); preempt_enable();
maybe_wait_bpf_programs(map);
out: out:
kfree(key); kfree(key);
err_put: err_put:
...@@ -1646,7 +1664,7 @@ static int bpf_prog_attach(const union bpf_attr *attr) ...@@ -1646,7 +1664,7 @@ static int bpf_prog_attach(const union bpf_attr *attr)
switch (ptype) { switch (ptype) {
case BPF_PROG_TYPE_SK_SKB: case BPF_PROG_TYPE_SK_SKB:
case BPF_PROG_TYPE_SK_MSG: case BPF_PROG_TYPE_SK_MSG:
ret = sockmap_get_from_fd(attr, ptype, prog); ret = sock_map_get_from_fd(attr, prog);
break; break;
case BPF_PROG_TYPE_LIRC_MODE2: case BPF_PROG_TYPE_LIRC_MODE2:
ret = lirc_prog_attach(attr, prog); ret = lirc_prog_attach(attr, prog);
...@@ -1700,10 +1718,10 @@ static int bpf_prog_detach(const union bpf_attr *attr) ...@@ -1700,10 +1718,10 @@ static int bpf_prog_detach(const union bpf_attr *attr)
ptype = BPF_PROG_TYPE_CGROUP_DEVICE; ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
break; break;
case BPF_SK_MSG_VERDICT: case BPF_SK_MSG_VERDICT:
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_MSG, NULL); return sock_map_get_from_fd(attr, NULL);
case BPF_SK_SKB_STREAM_PARSER: case BPF_SK_SKB_STREAM_PARSER:
case BPF_SK_SKB_STREAM_VERDICT: case BPF_SK_SKB_STREAM_VERDICT:
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, NULL); return sock_map_get_from_fd(attr, NULL);
case BPF_LIRC_MODE2: case BPF_LIRC_MODE2:
return lirc_prog_detach(attr); return lirc_prog_detach(attr);
case BPF_FLOW_DISSECTOR: case BPF_FLOW_DISSECTOR:
......
...@@ -154,7 +154,7 @@ void __xsk_map_flush(struct bpf_map *map) ...@@ -154,7 +154,7 @@ void __xsk_map_flush(struct bpf_map *map)
static void *xsk_map_lookup_elem(struct bpf_map *map, void *key) static void *xsk_map_lookup_elem(struct bpf_map *map, void *key)
{ {
return NULL; return ERR_PTR(-EOPNOTSUPP);
} }
static int xsk_map_update_elem(struct bpf_map *map, void *key, void *value, static int xsk_map_update_elem(struct bpf_map *map, void *key, void *value,
......
...@@ -300,8 +300,11 @@ config BPF_JIT ...@@ -300,8 +300,11 @@ config BPF_JIT
config BPF_STREAM_PARSER config BPF_STREAM_PARSER
bool "enable BPF STREAM_PARSER" bool "enable BPF STREAM_PARSER"
depends on INET
depends on BPF_SYSCALL depends on BPF_SYSCALL
depends on CGROUP_BPF
select STREAM_PARSER select STREAM_PARSER
select NET_SOCK_MSG
---help--- ---help---
Enabling this allows a stream parser to be used with Enabling this allows a stream parser to be used with
BPF_MAP_TYPE_SOCKMAP. BPF_MAP_TYPE_SOCKMAP.
...@@ -413,6 +416,14 @@ config GRO_CELLS ...@@ -413,6 +416,14 @@ config GRO_CELLS
config SOCK_VALIDATE_XMIT config SOCK_VALIDATE_XMIT
bool bool
config NET_SOCK_MSG
bool
default n
help
The NET_SOCK_MSG provides a framework for plain sockets (e.g. TCP) or
ULPs (upper layer modules, e.g. TLS) to process L7 application data
with the help of BPF programs.
config NET_DEVLINK config NET_DEVLINK
tristate "Network physical/parent device Netlink interface" tristate "Network physical/parent device Netlink interface"
help help
......
...@@ -16,6 +16,7 @@ obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ ...@@ -16,6 +16,7 @@ obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \
obj-y += net-sysfs.o obj-y += net-sysfs.o
obj-$(CONFIG_PAGE_POOL) += page_pool.o obj-$(CONFIG_PAGE_POOL) += page_pool.o
obj-$(CONFIG_PROC_FS) += net-procfs.o obj-$(CONFIG_PROC_FS) += net-procfs.o
obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
obj-$(CONFIG_NET_PKTGEN) += pktgen.o obj-$(CONFIG_NET_PKTGEN) += pktgen.o
obj-$(CONFIG_NETPOLL) += netpoll.o obj-$(CONFIG_NETPOLL) += netpoll.o
obj-$(CONFIG_FIB_RULES) += fib_rules.o obj-$(CONFIG_FIB_RULES) += fib_rules.o
...@@ -27,6 +28,7 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o ...@@ -27,6 +28,7 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
obj-$(CONFIG_LWTUNNEL) += lwtunnel.o obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o
obj-$(CONFIG_BPF_STREAM_PARSER) += sock_map.o
obj-$(CONFIG_DST_CACHE) += dst_cache.o obj-$(CONFIG_DST_CACHE) += dst_cache.o
obj-$(CONFIG_HWBM) += hwbm.o obj-$(CONFIG_HWBM) += hwbm.o
obj-$(CONFIG_NET_DEVLINK) += devlink.o obj-$(CONFIG_NET_DEVLINK) += devlink.o
......
...@@ -4291,6 +4291,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, ...@@ -4291,6 +4291,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
struct netdev_rx_queue *rxqueue; struct netdev_rx_queue *rxqueue;
void *orig_data, *orig_data_end; void *orig_data, *orig_data_end;
u32 metalen, act = XDP_DROP; u32 metalen, act = XDP_DROP;
__be16 orig_eth_type;
struct ethhdr *eth;
bool orig_bcast;
int hlen, off; int hlen, off;
u32 mac_len; u32 mac_len;
...@@ -4331,6 +4334,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, ...@@ -4331,6 +4334,9 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
xdp->data_hard_start = skb->data - skb_headroom(skb); xdp->data_hard_start = skb->data - skb_headroom(skb);
orig_data_end = xdp->data_end; orig_data_end = xdp->data_end;
orig_data = xdp->data; orig_data = xdp->data;
eth = (struct ethhdr *)xdp->data;
orig_bcast = is_multicast_ether_addr_64bits(eth->h_dest);
orig_eth_type = eth->h_proto;
rxqueue = netif_get_rxqueue(skb); rxqueue = netif_get_rxqueue(skb);
xdp->rxq = &rxqueue->xdp_rxq; xdp->rxq = &rxqueue->xdp_rxq;
...@@ -4354,6 +4360,14 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, ...@@ -4354,6 +4360,14 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
} }
/* check if XDP changed eth hdr such SKB needs update */
eth = (struct ethhdr *)xdp->data;
if ((orig_eth_type != eth->h_proto) ||
(orig_bcast != is_multicast_ether_addr_64bits(eth->h_dest))) {
__skb_push(skb, ETH_HLEN);
skb->protocol = eth_type_trans(skb, skb->dev);
}
switch (act) { switch (act) {
case XDP_REDIRECT: case XDP_REDIRECT:
case XDP_TX: case XDP_TX:
......
This diff is collapsed.
This diff is collapsed.
...@@ -2239,67 +2239,6 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag) ...@@ -2239,67 +2239,6 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag)
} }
EXPORT_SYMBOL(sk_page_frag_refill); EXPORT_SYMBOL(sk_page_frag_refill);
int sk_alloc_sg(struct sock *sk, int len, struct scatterlist *sg,
int sg_start, int *sg_curr_index, unsigned int *sg_curr_size,
int first_coalesce)
{
int sg_curr = *sg_curr_index, use = 0, rc = 0;
unsigned int size = *sg_curr_size;
struct page_frag *pfrag;
struct scatterlist *sge;
len -= size;
pfrag = sk_page_frag(sk);
while (len > 0) {
unsigned int orig_offset;
if (!sk_page_frag_refill(sk, pfrag)) {
rc = -ENOMEM;
goto out;
}
use = min_t(int, len, pfrag->size - pfrag->offset);
if (!sk_wmem_schedule(sk, use)) {
rc = -ENOMEM;
goto out;
}
sk_mem_charge(sk, use);
size += use;
orig_offset = pfrag->offset;
pfrag->offset += use;
sge = sg + sg_curr - 1;
if (sg_curr > first_coalesce && sg_page(sge) == pfrag->page &&
sge->offset + sge->length == orig_offset) {
sge->length += use;
} else {
sge = sg + sg_curr;
sg_unmark_end(sge);
sg_set_page(sge, pfrag->page, use, orig_offset);
get_page(pfrag->page);
sg_curr++;
if (sg_curr == MAX_SKB_FRAGS)
sg_curr = 0;
if (sg_curr == sg_start) {
rc = -ENOSPC;
break;
}
}
len -= use;
}
out:
*sg_curr_size = size;
*sg_curr_index = sg_curr;
return rc;
}
EXPORT_SYMBOL(sk_alloc_sg);
static void __lock_sock(struct sock *sk) static void __lock_sock(struct sock *sk)
__releases(&sk->sk_lock.slock) __releases(&sk->sk_lock.slock)
__acquires(&sk->sk_lock.slock) __acquires(&sk->sk_lock.slock)
......
This diff is collapsed.
...@@ -63,6 +63,7 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o ...@@ -63,6 +63,7 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o
obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o
obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
*/ */
#include<linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -29,18 +29,6 @@ static struct tcp_ulp_ops *tcp_ulp_find(const char *name) ...@@ -29,18 +29,6 @@ static struct tcp_ulp_ops *tcp_ulp_find(const char *name)
return NULL; return NULL;
} }
static struct tcp_ulp_ops *tcp_ulp_find_id(const int ulp)
{
struct tcp_ulp_ops *e;
list_for_each_entry_rcu(e, &tcp_ulp_list, list) {
if (e->uid == ulp)
return e;
}
return NULL;
}
static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name) static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)
{ {
const struct tcp_ulp_ops *ulp = NULL; const struct tcp_ulp_ops *ulp = NULL;
...@@ -63,18 +51,6 @@ static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name) ...@@ -63,18 +51,6 @@ static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)
return ulp; return ulp;
} }
static const struct tcp_ulp_ops *__tcp_ulp_lookup(const int uid)
{
const struct tcp_ulp_ops *ulp;
rcu_read_lock();
ulp = tcp_ulp_find_id(uid);
if (!ulp || !try_module_get(ulp->owner))
ulp = NULL;
rcu_read_unlock();
return ulp;
}
/* Attach new upper layer protocol to the list /* Attach new upper layer protocol to the list
* of available protocols. * of available protocols.
*/ */
...@@ -123,6 +99,8 @@ void tcp_cleanup_ulp(struct sock *sk) ...@@ -123,6 +99,8 @@ void tcp_cleanup_ulp(struct sock *sk)
{ {
struct inet_connection_sock *icsk = inet_csk(sk); struct inet_connection_sock *icsk = inet_csk(sk);
sock_owned_by_me(sk);
if (!icsk->icsk_ulp_ops) if (!icsk->icsk_ulp_ops)
return; return;
...@@ -133,54 +111,35 @@ void tcp_cleanup_ulp(struct sock *sk) ...@@ -133,54 +111,35 @@ void tcp_cleanup_ulp(struct sock *sk)
icsk->icsk_ulp_ops = NULL; icsk->icsk_ulp_ops = NULL;
} }
/* Change upper layer protocol for socket */ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
int tcp_set_ulp(struct sock *sk, const char *name)
{ {
struct inet_connection_sock *icsk = inet_csk(sk); struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_ulp_ops *ulp_ops; int err;
int err = 0;
err = -EEXIST;
if (icsk->icsk_ulp_ops) if (icsk->icsk_ulp_ops)
return -EEXIST; goto out_err;
ulp_ops = __tcp_ulp_find_autoload(name);
if (!ulp_ops)
return -ENOENT;
if (!ulp_ops->user_visible) {
module_put(ulp_ops->owner);
return -ENOENT;
}
err = ulp_ops->init(sk); err = ulp_ops->init(sk);
if (err) { if (err)
module_put(ulp_ops->owner); goto out_err;
return err;
}
icsk->icsk_ulp_ops = ulp_ops; icsk->icsk_ulp_ops = ulp_ops;
return 0; return 0;
out_err:
module_put(ulp_ops->owner);
return err;
} }
int tcp_set_ulp_id(struct sock *sk, int ulp) int tcp_set_ulp(struct sock *sk, const char *name)
{ {
struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_ulp_ops *ulp_ops; const struct tcp_ulp_ops *ulp_ops;
int err;
if (icsk->icsk_ulp_ops) sock_owned_by_me(sk);
return -EEXIST;
ulp_ops = __tcp_ulp_lookup(ulp); ulp_ops = __tcp_ulp_find_autoload(name);
if (!ulp_ops) if (!ulp_ops)
return -ENOENT; return -ENOENT;
err = ulp_ops->init(sk); return __tcp_set_ulp(sk, ulp_ops);
if (err) {
module_put(ulp_ops->owner);
return err;
}
icsk->icsk_ulp_ops = ulp_ops;
return 0;
} }
...@@ -901,6 +901,7 @@ static const struct ipv6_stub ipv6_stub_impl = { ...@@ -901,6 +901,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = { static const struct ipv6_bpf_stub ipv6_bpf_stub_impl = {
.inet6_bind = __inet6_bind, .inet6_bind = __inet6_bind,
.udp6_lib_lookup = __udp6_lib_lookup,
}; };
static int __init inet6_init(void) static int __init inet6_init(void)
......
config STREAM_PARSER config STREAM_PARSER
tristate def_bool n
default n
...@@ -8,6 +8,7 @@ config TLS ...@@ -8,6 +8,7 @@ config TLS
select CRYPTO_AES select CRYPTO_AES
select CRYPTO_GCM select CRYPTO_GCM
select STREAM_PARSER select STREAM_PARSER
select NET_SOCK_MSG
default n default n
---help--- ---help---
Enable kernel support for TLS protocol. This allows symmetric Enable kernel support for TLS protocol. This allows symmetric
......
...@@ -421,7 +421,7 @@ static int tls_push_data(struct sock *sk, ...@@ -421,7 +421,7 @@ static int tls_push_data(struct sock *sk,
tls_push_record_flags = flags; tls_push_record_flags = flags;
if (more) { if (more) {
tls_ctx->pending_open_record_frags = tls_ctx->pending_open_record_frags =
record->num_frags; !!record->num_frags;
break; break;
} }
......
...@@ -621,10 +621,12 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], ...@@ -621,10 +621,12 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG],
prot[TLS_BASE][TLS_SW] = prot[TLS_BASE][TLS_BASE]; prot[TLS_BASE][TLS_SW] = prot[TLS_BASE][TLS_BASE];
prot[TLS_BASE][TLS_SW].recvmsg = tls_sw_recvmsg; prot[TLS_BASE][TLS_SW].recvmsg = tls_sw_recvmsg;
prot[TLS_BASE][TLS_SW].stream_memory_read = tls_sw_stream_read;
prot[TLS_BASE][TLS_SW].close = tls_sk_proto_close; prot[TLS_BASE][TLS_SW].close = tls_sk_proto_close;
prot[TLS_SW][TLS_SW] = prot[TLS_SW][TLS_BASE]; prot[TLS_SW][TLS_SW] = prot[TLS_SW][TLS_BASE];
prot[TLS_SW][TLS_SW].recvmsg = tls_sw_recvmsg; prot[TLS_SW][TLS_SW].recvmsg = tls_sw_recvmsg;
prot[TLS_SW][TLS_SW].stream_memory_read = tls_sw_stream_read;
prot[TLS_SW][TLS_SW].close = tls_sk_proto_close; prot[TLS_SW][TLS_SW].close = tls_sk_proto_close;
#ifdef CONFIG_TLS_DEVICE #ifdef CONFIG_TLS_DEVICE
...@@ -724,7 +726,6 @@ static int __init tls_register(void) ...@@ -724,7 +726,6 @@ static int __init tls_register(void)
build_protos(tls_prots[TLSV4], &tcp_prot); build_protos(tls_prots[TLSV4], &tcp_prot);
tls_sw_proto_ops = inet_stream_ops; tls_sw_proto_ops = inet_stream_ops;
tls_sw_proto_ops.poll = tls_sw_poll;
tls_sw_proto_ops.splice_read = tls_sw_splice_read; tls_sw_proto_ops.splice_read = tls_sw_splice_read;
#ifdef CONFIG_TLS_DEVICE #ifdef CONFIG_TLS_DEVICE
......
This diff is collapsed.
...@@ -25,6 +25,8 @@ MAP COMMANDS ...@@ -25,6 +25,8 @@ MAP COMMANDS
| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] | **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
| **bpftool** **prog pin** *PROG* *FILE* | **bpftool** **prog pin** *PROG* *FILE*
| **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] | **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* *MAP*
| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* *MAP*
| **bpftool** **prog help** | **bpftool** **prog help**
| |
| *MAP* := { **id** *MAP_ID* | **pinned** *FILE* } | *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
...@@ -37,6 +39,7 @@ MAP COMMANDS ...@@ -37,6 +39,7 @@ MAP COMMANDS
| **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** | | **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
| **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** | **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6**
| } | }
| *ATTACH_TYPE* := { **msg_verdict** | **skb_verdict** | **skb_parse** }
DESCRIPTION DESCRIPTION
...@@ -90,6 +93,14 @@ DESCRIPTION ...@@ -90,6 +93,14 @@ DESCRIPTION
Note: *FILE* must be located in *bpffs* mount. Note: *FILE* must be located in *bpffs* mount.
**bpftool prog attach** *PROG* *ATTACH_TYPE* *MAP*
Attach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
to the map *MAP*.
**bpftool prog detach** *PROG* *ATTACH_TYPE* *MAP*
Detach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
from the map *MAP*.
**bpftool prog help** **bpftool prog help**
Print short help message. Print short help message.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment