From patchwork Tue Feb 25 13:56:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenz Bauer X-Patchwork-Id: 1244270 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.a=rsa-sha256 header.s=google header.b=cTWhodGJ; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48RgTR292Jz9sQt for ; Wed, 26 Feb 2020 00:56:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730288AbgBYN4m (ORCPT ); Tue, 25 Feb 2020 08:56:42 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:39372 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726019AbgBYN4m (ORCPT ); Tue, 25 Feb 2020 08:56:42 -0500 Received: by mail-wm1-f67.google.com with SMTP id c84so3237419wme.4 for ; Tue, 25 Feb 2020 05:56:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=p/IkxmE2XQKvvaJ3+jizWlUITUqYZdNJGm8v0gfliUM=; b=cTWhodGJPh3JS/kke4UU4bdd2oU+0z1lMqE8gGZz1xxDYClfUD119d5whmo+rfsK8m u1WlcdFsUkQcSo3ZXtYt7Zl+Il8epgBbAsrbKUIk/6+D7mortM5qdCsUFYftnXAh6oIQ oT1RpuLOVjeBSHPKcb9GFj5aN9G22eDTGsgMU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=p/IkxmE2XQKvvaJ3+jizWlUITUqYZdNJGm8v0gfliUM=; b=WJO2Sf7WZ9CjxJYiSYA6d68+eMMBVA4xJmpW2yb06/GClDlyZBAur6mwnnWjZ1onO+ Fksrg+Nn4EzhvuGwsfFSfNKe1XO8ANWuFBij3IXEkyWZh8e6uSLFJoATgiXm0lSpqhpN UWsi4B+5MwLjr3KfPrgfRJKYvuJMUAT+xVyqFa0Xrr2b2NTEEPV9Xw1Uflj9cKAGUDmL 5uFc0Q8k6w2WTzh4vD25D2dkrlv+ZxPclcZKggPU6xrhvUXKj/Liww/ifTZTyjpNTumL 4i1Zosb+EE2XhQCbDqKo4/Mp6x6hQWl6YfJqWYz3Tmp3JTpe/Z1D7G+PzxiqnLD+Pvpd gzgA== X-Gm-Message-State: APjAAAVa374/FwnJSuFLt7yALcKmu6OBfk3OGhZjzNjeIy1LjCJNCQXI MBc0Xb0T1hdEGRdHNvmCgcZGSQ== X-Google-Smtp-Source: APXvYqyYeqYl/GpMwckv9yHpES5fKL/iEnsM03HXewDNyYnWWDYNSS129uIzzAwlsBDIc04rrUcIAQ== X-Received: by 2002:a1c:4c5:: with SMTP id 188mr5403025wme.82.1582639000922; Tue, 25 Feb 2020 05:56:40 -0800 (PST) Received: from localhost.localdomain ([2a06:98c0:1000:8800:3dea:15ba:1870:8e94]) by smtp.gmail.com with ESMTPSA id t128sm4463580wmf.28.2020.02.25.05.56.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 05:56:40 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, kernel-team@cloudflare.com, Lorenz Bauer Subject: [PATCH bpf-next 1/7] bpf: sockmap: only check ULP for TCP sockets Date: Tue, 25 Feb 2020 13:56:30 +0000 Message-Id: <20200225135636.5768-2-lmb@cloudflare.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225135636.5768-1-lmb@cloudflare.com> References: <20200225135636.5768-1-lmb@cloudflare.com> MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org The sock map code checks that a socket does not have an active upper layer protocol before inserting it into the map. This requires casting via inet_csk, which isn't valid for UDP sockets. Guard checks for ULP by checking inet_sk(sk)->is_icsk first. Signed-off-by: Lorenz Bauer Acked-by: Song Liu --- include/linux/skmsg.h | 8 +++++++- net/core/sock_map.c | 11 +++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 112765bd146d..54a9a3e36b29 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -360,7 +360,13 @@ static inline void sk_psock_restore_proto(struct sock *sk, struct sk_psock *psock) { sk->sk_prot->unhash = psock->saved_unhash; - tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); + if (inet_sk(sk)->is_icsk) { + tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); + } else { + sk->sk_write_space = psock->saved_write_space; + /* Pairs with lockless read in sk_clone_lock() */ + WRITE_ONCE(sk->sk_prot, psock->sk_proto); + } } static inline void sk_psock_set_state(struct sk_psock *psock, diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 2e0f465295c3..695ecacc7afa 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -94,6 +94,11 @@ static void sock_map_sk_release(struct sock *sk) release_sock(sk); } +static bool sock_map_sk_has_ulp(struct sock *sk) +{ + return inet_sk(sk)->is_icsk && !!inet_csk(sk)->icsk_ulp_ops; +} + static void sock_map_add_link(struct sk_psock *psock, struct sk_psock_link *link, struct bpf_map *map, void *link_raw) @@ -384,7 +389,6 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx, struct sock *sk, u64 flags) { struct bpf_stab *stab = container_of(map, struct bpf_stab, map); - struct inet_connection_sock *icsk = inet_csk(sk); struct sk_psock_link *link; struct sk_psock *psock; struct sock *osk; @@ -395,7 +399,7 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx, return -EINVAL; if (unlikely(idx >= map->max_entries)) return -E2BIG; - if (unlikely(rcu_access_pointer(icsk->icsk_ulp_data))) + if (sock_map_sk_has_ulp(sk)) return -EINVAL; link = sk_psock_init_link(); @@ -738,7 +742,6 @@ static int sock_hash_update_common(struct bpf_map *map, void *key, struct sock *sk, u64 flags) { struct bpf_htab *htab = container_of(map, struct bpf_htab, map); - struct inet_connection_sock *icsk = inet_csk(sk); u32 key_size = map->key_size, hash; struct bpf_htab_elem *elem, *elem_new; struct bpf_htab_bucket *bucket; @@ -749,7 +752,7 @@ static int sock_hash_update_common(struct bpf_map *map, void *key, WARN_ON_ONCE(!rcu_read_lock_held()); if (unlikely(flags > BPF_EXIST)) return -EINVAL; - if (unlikely(icsk->icsk_ulp_data)) + if (sock_map_sk_has_ulp(sk)) return -EINVAL; link = sk_psock_init_link(); From patchwork Tue Feb 25 13:56:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenz Bauer X-Patchwork-Id: 1244272 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.a=rsa-sha256 header.s=google header.b=bTWWed71; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48RgTV5sShz9sRQ for ; Wed, 26 Feb 2020 00:56:46 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730468AbgBYN4q (ORCPT ); Tue, 25 Feb 2020 08:56:46 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36921 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726019AbgBYN4o (ORCPT ); Tue, 25 Feb 2020 08:56:44 -0500 Received: by mail-wm1-f68.google.com with SMTP id a6so3245762wme.2 for ; Tue, 25 Feb 2020 05:56:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1l3ad/jyN4Df3AeGsUOqno7cqBsAfUEwYTf8KTkCXE0=; b=bTWWed710QEJeE/XIjd9StabwkGR7Kwf/L5VgOQfDsKk5pvpsUQX6lMFE4oqK3cllO 31SWFnVt5XbedmVDMpAuFspAYY4AgLGv8e9nLQXmGJfnu2+xni8MOqTntPiXB5f6GdwJ gVjJvKheesdBAAggEoubJWHj6pi36eBctGtXM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1l3ad/jyN4Df3AeGsUOqno7cqBsAfUEwYTf8KTkCXE0=; b=S3juurZ+KTYYYMcIFd9E6rqOU8oJHV1zjw+yrO8E3kt40TopAQrflH54p1UPi0nipB opYjONFd+SurZ9tjcN/h5ue5dO26ooO7qQF+BT9Rp84bY9I2olhCgSzo/hc0Isxijiqe HuvSkkiKeBqeaQVZSLwY49Yiy0MghnducHz01pHMNf1I1XR0v6gNNQK9ioaEf5xlabPD xsIebvLclYEWUponZ89RWLc9Ug088vs3xPAojXjnNuL3eFWTHWT9fmglxHOSy6hxpO5x SnooyXQqjQPPZFc5g8t+dYG6r1aGfKszhK4ONL6nlEraZ7MGHhzOH3gU3um0Mjghjk+W uxdA== X-Gm-Message-State: APjAAAXIdBmUrr+1kcLkw3/Yvj9eYz81V25F+TG5swwrJiq3RFjgZwcE fytKn9DxkyFkK5n3RrwXV4V6D/JzG1tGkA== X-Google-Smtp-Source: APXvYqxSyOXKEpIxFtldnNXgJf/lPkF5tOmtky3OIcKKiLi3A/kGmApdP0nyUXlfBnFkZQ5jNdm1bQ== X-Received: by 2002:a1c:e488:: with SMTP id b130mr5275392wmh.108.1582639002429; Tue, 25 Feb 2020 05:56:42 -0800 (PST) Received: from localhost.localdomain ([2a06:98c0:1000:8800:3dea:15ba:1870:8e94]) by smtp.gmail.com with ESMTPSA id t128sm4463580wmf.28.2020.02.25.05.56.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 05:56:41 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, kernel-team@cloudflare.com, Lorenz Bauer Subject: [PATCH bpf-next 2/7] bpf: sockmap: move generic sockmap hooks from BPF TCP Date: Tue, 25 Feb 2020 13:56:31 +0000 Message-Id: <20200225135636.5768-3-lmb@cloudflare.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225135636.5768-1-lmb@cloudflare.com> References: <20200225135636.5768-1-lmb@cloudflare.com> MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org The close, unhash and clone handlers from TCP sockmap are actually generic, and can be reused by UDP sockmap. Move the helpers into the sockmap code base and expose them. Signed-off-by: Lorenz Bauer --- include/linux/bpf.h | 4 ++- include/linux/skmsg.h | 28 ---------------- net/core/sock_map.c | 77 +++++++++++++++++++++++++++++++++++++++++-- net/ipv4/tcp_bpf.c | 55 ++----------------------------- 4 files changed, 79 insertions(+), 85 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 49b1a70e12c8..8422ab6a63d8 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1355,6 +1355,8 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map) #if defined(CONFIG_BPF_STREAM_PARSER) int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which); int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog); +void sock_map_unhash(struct sock *sk); +void sock_map_close(struct sock *sk, long timeout); #else static inline int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which) @@ -1367,7 +1369,7 @@ static inline int sock_map_get_from_fd(const union bpf_attr *attr, { return -EINVAL; } -#endif +#endif /* CONFIG_BPF_STREAM_PARSER */ #if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL) void bpf_sk_reuseport_detach(struct sock *sk); diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 54a9a3e36b29..c881094387db 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -323,14 +323,6 @@ static inline void sk_psock_free_link(struct sk_psock_link *link) } struct sk_psock_link *sk_psock_link_pop(struct sk_psock *psock); -#if defined(CONFIG_BPF_STREAM_PARSER) -void sk_psock_unlink(struct sock *sk, struct sk_psock_link *link); -#else -static inline void sk_psock_unlink(struct sock *sk, - struct sk_psock_link *link) -{ -} -#endif void __sk_psock_purge_ingress_msg(struct sk_psock *psock); @@ -387,26 +379,6 @@ static inline bool sk_psock_test_state(const struct sk_psock *psock, return test_bit(bit, &psock->state); } -static inline struct sk_psock *sk_psock_get_checked(struct sock *sk) -{ - struct sk_psock *psock; - - rcu_read_lock(); - psock = sk_psock(sk); - if (psock) { - if (sk->sk_prot->recvmsg != tcp_bpf_recvmsg) { - psock = ERR_PTR(-EBUSY); - goto out; - } - - if (!refcount_inc_not_zero(&psock->refcnt)) - psock = ERR_PTR(-EBUSY); - } -out: - rcu_read_unlock(); - return psock; -} - static inline struct sk_psock *sk_psock_get(struct sock *sk) { struct sk_psock *psock; diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 695ecacc7afa..459b3ba16023 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -146,6 +146,26 @@ static void sock_map_unref(struct sock *sk, void *link_raw) } } +static struct sk_psock *sock_map_psock_get_checked(struct sock *sk) +{ + struct sk_psock *psock; + + rcu_read_lock(); + psock = sk_psock(sk); + if (psock) { + if (sk->sk_prot->recvmsg != tcp_bpf_recvmsg) { + psock = ERR_PTR(-EBUSY); + goto out; + } + + if (!refcount_inc_not_zero(&psock->refcnt)) + psock = ERR_PTR(-EBUSY); + } +out: + rcu_read_unlock(); + return psock; +} + static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, struct sock *sk) { @@ -177,7 +197,7 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, } } - psock = sk_psock_get_checked(sk); + psock = sock_map_psock_get_checked(sk); if (IS_ERR(psock)) { ret = PTR_ERR(psock); goto out_progs; @@ -240,7 +260,7 @@ static int sock_map_link_no_progs(struct bpf_map *map, struct sock *sk) struct sk_psock *psock; int ret; - psock = sk_psock_get_checked(sk); + psock = sock_map_psock_get_checked(sk); if (IS_ERR(psock)) return PTR_ERR(psock); @@ -1132,7 +1152,7 @@ int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, return 0; } -void sk_psock_unlink(struct sock *sk, struct sk_psock_link *link) +static void sock_map_unlink(struct sock *sk, struct sk_psock_link *link) { switch (link->map->map_type) { case BPF_MAP_TYPE_SOCKMAP: @@ -1145,3 +1165,54 @@ void sk_psock_unlink(struct sock *sk, struct sk_psock_link *link) break; } } + +static void sock_map_remove_links(struct sock *sk, struct sk_psock *psock) +{ + struct sk_psock_link *link; + + while ((link = sk_psock_link_pop(psock))) { + sock_map_unlink(sk, link); + sk_psock_free_link(link); + } +} + +void sock_map_unhash(struct sock *sk) +{ + void (*saved_unhash)(struct sock *sk); + struct sk_psock *psock; + + rcu_read_lock(); + psock = sk_psock(sk); + if (unlikely(!psock)) { + rcu_read_unlock(); + if (sk->sk_prot->unhash) + sk->sk_prot->unhash(sk); + return; + } + + saved_unhash = psock->saved_unhash; + sock_map_remove_links(sk, psock); + rcu_read_unlock(); + saved_unhash(sk); +} + +void sock_map_close(struct sock *sk, long timeout) +{ + void (*saved_close)(struct sock *sk, long timeout); + struct sk_psock *psock; + + lock_sock(sk); + rcu_read_lock(); + psock = sk_psock(sk); + if (unlikely(!psock)) { + rcu_read_unlock(); + release_sock(sk); + return sk->sk_prot->close(sk, timeout); + } + + saved_close = psock->saved_close; + sock_map_remove_links(sk, psock); + rcu_read_unlock(); + release_sock(sk); + saved_close(sk, timeout); +} diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 7d6e1b75d4d4..90955c96a9a8 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -528,57 +528,6 @@ static int tcp_bpf_sendpage(struct sock *sk, struct page *page, int offset, return copied ? copied : err; } -static void tcp_bpf_remove(struct sock *sk, struct sk_psock *psock) -{ - struct sk_psock_link *link; - - while ((link = sk_psock_link_pop(psock))) { - sk_psock_unlink(sk, link); - sk_psock_free_link(link); - } -} - -static void tcp_bpf_unhash(struct sock *sk) -{ - void (*saved_unhash)(struct sock *sk); - struct sk_psock *psock; - - rcu_read_lock(); - psock = sk_psock(sk); - if (unlikely(!psock)) { - rcu_read_unlock(); - if (sk->sk_prot->unhash) - sk->sk_prot->unhash(sk); - return; - } - - saved_unhash = psock->saved_unhash; - tcp_bpf_remove(sk, psock); - rcu_read_unlock(); - saved_unhash(sk); -} - -static void tcp_bpf_close(struct sock *sk, long timeout) -{ - void (*saved_close)(struct sock *sk, long timeout); - struct sk_psock *psock; - - lock_sock(sk); - rcu_read_lock(); - psock = sk_psock(sk); - if (unlikely(!psock)) { - rcu_read_unlock(); - release_sock(sk); - return sk->sk_prot->close(sk, timeout); - } - - saved_close = psock->saved_close; - tcp_bpf_remove(sk, psock); - rcu_read_unlock(); - release_sock(sk); - saved_close(sk, timeout); -} - enum { TCP_BPF_IPV4, TCP_BPF_IPV6, @@ -599,8 +548,8 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], struct proto *base) { prot[TCP_BPF_BASE] = *base; - prot[TCP_BPF_BASE].unhash = tcp_bpf_unhash; - prot[TCP_BPF_BASE].close = tcp_bpf_close; + prot[TCP_BPF_BASE].unhash = sock_map_unhash; + prot[TCP_BPF_BASE].close = sock_map_close; prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg; prot[TCP_BPF_BASE].stream_memory_read = tcp_bpf_stream_read; From patchwork Tue Feb 25 13:56:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenz Bauer X-Patchwork-Id: 1244276 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.a=rsa-sha256 header.s=google header.b=KAFScvGa; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48RgTZ43gZz9sPk for ; Wed, 26 Feb 2020 00:56:50 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730240AbgBYN4t (ORCPT ); Tue, 25 Feb 2020 08:56:49 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:51209 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729411AbgBYN4q (ORCPT ); Tue, 25 Feb 2020 08:56:46 -0500 Received: by mail-wm1-f65.google.com with SMTP id t23so3102648wmi.1 for ; Tue, 25 Feb 2020 05:56:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6trGj3ZxAEym4kOmMJM6kP41Fhmdj2jr0SexhJ+xY5g=; b=KAFScvGaqf/JHH7ZB91aznHMnA9aBRAI44mdZm2EfMFxlNcUFqlj+FqDDG4rc3/xy+ Bj/jPzuJtjqy9iEDkJWglLH32jLZfLRGPVzVMecj8HtJxbDI7J5Ry2DFHM8Z9y80wzFJ bP/hhS43DPEY25E4FS4Z+x+seObLXz7JwxvTY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6trGj3ZxAEym4kOmMJM6kP41Fhmdj2jr0SexhJ+xY5g=; b=J2TJJtEm5nAAFCnC0s1CuROurS/P4KZbS5u7DrEGnU3TMGWj1F7v82l9G9pBT3ommI fNHi04+85nNaEY6SITfW698rbaoalMhEZVyV6rkfJxaNTDVHeoPpNQ2V4441cFcniV2u Hc+BjC9n+8rcVXmRZywlHKVSuJaK2ZFyecw2+qC+oyr6t3zCeTqD7PZn95/z9jOoQzk8 sgjZRCjuXaoqRPfe6G5e34nvFt3bFNff6ROnYzcQNXMyZftd39wNLv4MYGAM/RyTuxkA xg/lBRtTrZerSqaalTT5jRFCyOZkoM7M1mY6Bin0kn64K1pOIhVjARwzWf9ism5VO3he yzPg== X-Gm-Message-State: APjAAAU1iOclKELRq8xWEqjSjuQhs9sTkf4GVnawQ9K0xsm7V0HigViK iJfcSjNKG5WqueamQ3m5SSYHEw== X-Google-Smtp-Source: APXvYqznxpdPPmOfbgK9/GYySRY5epb29T6UH54vlkhq5WJ4yhSLWLzeDL+cuAhcfpkV7KK/+xO0wg== X-Received: by 2002:a05:600c:2104:: with SMTP id u4mr5538875wml.93.1582639003927; Tue, 25 Feb 2020 05:56:43 -0800 (PST) Received: from localhost.localdomain ([2a06:98c0:1000:8800:3dea:15ba:1870:8e94]) by smtp.gmail.com with ESMTPSA id t128sm4463580wmf.28.2020.02.25.05.56.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 05:56:43 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, kernel-team@cloudflare.com, Lorenz Bauer Subject: [PATCH bpf-next 3/7] skmsg: introduce sk_psock_hooks Date: Tue, 25 Feb 2020 13:56:32 +0000 Message-Id: <20200225135636.5768-4-lmb@cloudflare.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225135636.5768-1-lmb@cloudflare.com> References: <20200225135636.5768-1-lmb@cloudflare.com> MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org The sockmap works by overriding some of the callbacks in sk->sk_prot, while leaving others untouched. This means that we need access to the struct proto for any protocol we want to support. For IPv4 this is trivial, since both TCP and UDP are always compiled in. IPv6 may be disabled or compiled as a module, so the existing TCP sockmap hooks use some trickery to lazily initialize the modified struct proto for TCPv6. Pull this logic into a standalone struct sk_psock_hooks, so that it can be re-used by UDP sockmap. Signed-off-by: Lorenz Bauer --- include/linux/skmsg.h | 36 ++++++++----- include/net/tcp.h | 1 - net/core/skmsg.c | 52 +++++++++++++++++++ net/core/sock_map.c | 24 ++++----- net/ipv4/tcp_bpf.c | 114 ++++++++++++------------------------------ 5 files changed, 116 insertions(+), 111 deletions(-) diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index c881094387db..70d65ab10b5c 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -109,6 +109,16 @@ struct sk_psock { }; }; +struct sk_psock_hooks { + struct proto *base_ipv6; + struct proto *ipv4; + struct proto *ipv6; + spinlock_t ipv6_lock; + int (*rebuild_proto)(struct proto prot[], struct proto *base); + struct proto *(*choose_proto)(struct proto prot[], + struct sk_psock *psock); +}; + int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len, int elem_first_coalesce); int sk_msg_clone(struct sock *sk, struct sk_msg *dst, struct sk_msg *src, @@ -335,23 +345,14 @@ static inline void sk_psock_cork_free(struct sk_psock *psock) } } -static inline void sk_psock_update_proto(struct sock *sk, - struct sk_psock *psock, - struct proto *ops) -{ - psock->saved_unhash = sk->sk_prot->unhash; - psock->saved_close = sk->sk_prot->close; - psock->saved_write_space = sk->sk_write_space; - - psock->sk_proto = sk->sk_prot; - /* Pairs with lockless read in sk_clone_lock() */ - WRITE_ONCE(sk->sk_prot, ops); -} - static inline void sk_psock_restore_proto(struct sock *sk, struct sk_psock *psock) { + if (!psock->sk_proto) + return; + sk->sk_prot->unhash = psock->saved_unhash; + if (inet_sk(sk)->is_icsk) { tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); } else { @@ -424,4 +425,13 @@ static inline void psock_progs_drop(struct sk_psock_progs *progs) psock_set_prog(&progs->skb_verdict, NULL); } +static inline int sk_psock_hooks_init(struct sk_psock_hooks *hooks, + struct proto *ipv4_base) +{ + hooks->ipv6_lock = __SPIN_LOCK_UNLOCKED(); + return hooks->rebuild_proto(hooks->ipv4, ipv4_base); +} + +int sk_psock_hooks_install(struct sk_psock_hooks *hooks, struct sock *sk); + #endif /* _LINUX_SKMSG_H */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 07f947cc80e6..ccf39d80b695 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -2196,7 +2196,6 @@ 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, diff --git a/net/core/skmsg.c b/net/core/skmsg.c index eeb28cb85664..a9bdf02c2539 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -844,3 +844,55 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) strp_stop(&parser->strp); parser->enabled = false; } + +static inline int sk_psock_hooks_init_ipv6(struct sk_psock_hooks *hooks, + struct proto *base) +{ + int ret = 0; + + if (likely(base == smp_load_acquire(&hooks->base_ipv6))) + return 0; + + spin_lock_bh(&hooks->ipv6_lock); + if (likely(base != hooks->base_ipv6)) { + ret = hooks->rebuild_proto(hooks->ipv6, base); + if (!ret) + smp_store_release(&hooks->base_ipv6, base); + } + spin_unlock_bh(&hooks->ipv6_lock); + return ret; +} + +int sk_psock_hooks_install(struct sk_psock_hooks *hooks, struct sock *sk) +{ + struct sk_psock *psock = sk_psock(sk); + struct proto *prot_base; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + if (unlikely(!psock)) + return -EINVAL; + + /* Initialize saved callbacks and original proto only once. + * Since we've not installed the hooks, psock is not yet in use and + * we can initialize it without synchronization. + */ + if (!psock->sk_proto) { + struct proto *prot = READ_ONCE(sk->sk_prot); + + if (sk->sk_family == AF_INET6 && + sk_psock_hooks_init_ipv6(hooks, prot)) + return -EINVAL; + + psock->saved_unhash = prot->unhash; + psock->saved_close = prot->close; + psock->saved_write_space = sk->sk_write_space; + + psock->sk_proto = prot; + } + + /* Pairs with lockless read in sk_clone_lock() */ + prot_base = sk->sk_family == AF_INET ? hooks->ipv4 : hooks->ipv6; + WRITE_ONCE(sk->sk_prot, hooks->choose_proto(prot_base, psock)); + return 0; +} diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 459b3ba16023..c84cc9fc7f6b 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -170,8 +170,8 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, struct sock *sk) { struct bpf_prog *msg_parser, *skb_parser, *skb_verdict; - bool skb_progs, sk_psock_is_new = false; struct sk_psock *psock; + bool skb_progs; int ret; skb_verdict = READ_ONCE(progs->skb_verdict); @@ -206,9 +206,8 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, if (psock) { if ((msg_parser && READ_ONCE(psock->progs.msg_parser)) || (skb_progs && READ_ONCE(psock->progs.skb_parser))) { - sk_psock_put(sk, psock); ret = -EBUSY; - goto out_progs; + goto out_drop; } } else { psock = sk_psock_init(sk, map->numa_node); @@ -216,18 +215,14 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, ret = -ENOMEM; goto out_progs; } - sk_psock_is_new = true; } if (msg_parser) psock_set_prog(&psock->progs.msg_parser, msg_parser); - if (sk_psock_is_new) { - ret = tcp_bpf_init(sk); - if (ret < 0) - goto out_drop; - } else { - tcp_bpf_reinit(sk); - } + + ret = tcp_bpf_init(sk); + if (ret < 0) + goto out_drop; write_lock_bh(&sk->sk_callback_lock); if (skb_progs && !psock->parser.enabled) { @@ -264,15 +259,14 @@ static int sock_map_link_no_progs(struct bpf_map *map, struct sock *sk) if (IS_ERR(psock)) return PTR_ERR(psock); - if (psock) { - tcp_bpf_reinit(sk); - return 0; - } + if (psock) + goto init; psock = sk_psock_init(sk, map->numa_node); if (!psock) return -ENOMEM; +init: ret = tcp_bpf_init(sk); if (ret < 0) sk_psock_put(sk, psock); diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 90955c96a9a8..81c0431a8dbd 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -528,25 +528,23 @@ static int tcp_bpf_sendpage(struct sock *sk, struct page *page, int offset, return copied ? copied : err; } -enum { - TCP_BPF_IPV4, - TCP_BPF_IPV6, - TCP_BPF_NUM_PROTS, -}; - enum { TCP_BPF_BASE, TCP_BPF_TX, TCP_BPF_NUM_CFGS, }; -static struct proto *tcpv6_prot_saved __read_mostly; -static DEFINE_SPINLOCK(tcpv6_prot_lock); -static struct proto tcp_bpf_prots[TCP_BPF_NUM_PROTS][TCP_BPF_NUM_CFGS]; - -static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], - struct proto *base) +static int tcp_bpf_rebuild_proto(struct proto prot[], struct proto *base) { + /* In order to avoid retpoline, we make assumptions when we call + * into ops if e.g. a psock is not present. Make sure they are + * indeed valid assumptions. + */ + if (base->recvmsg != tcp_recvmsg || + base->sendmsg != tcp_sendmsg || + base->sendpage != tcp_sendpage) + return -ENOTSUPP; + prot[TCP_BPF_BASE] = *base; prot[TCP_BPF_BASE].unhash = sock_map_unhash; prot[TCP_BPF_BASE].close = sock_map_close; @@ -556,91 +554,42 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], prot[TCP_BPF_TX] = prot[TCP_BPF_BASE]; prot[TCP_BPF_TX].sendmsg = tcp_bpf_sendmsg; prot[TCP_BPF_TX].sendpage = tcp_bpf_sendpage; -} - -static void tcp_bpf_check_v6_needs_rebuild(struct sock *sk, struct proto *ops) -{ - if (sk->sk_family == AF_INET6 && - unlikely(ops != smp_load_acquire(&tcpv6_prot_saved))) { - spin_lock_bh(&tcpv6_prot_lock); - if (likely(ops != tcpv6_prot_saved)) { - tcp_bpf_rebuild_protos(tcp_bpf_prots[TCP_BPF_IPV6], ops); - smp_store_release(&tcpv6_prot_saved, ops); - } - spin_unlock_bh(&tcpv6_prot_lock); - } -} - -static int __init tcp_bpf_v4_build_proto(void) -{ - tcp_bpf_rebuild_protos(tcp_bpf_prots[TCP_BPF_IPV4], &tcp_prot); return 0; } -core_initcall(tcp_bpf_v4_build_proto); -static void tcp_bpf_update_sk_prot(struct sock *sk, struct sk_psock *psock) +static struct proto *tcp_bpf_choose_proto(struct proto prot[], + struct sk_psock *psock) { - int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; - int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE; + int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE; - sk_psock_update_proto(sk, psock, &tcp_bpf_prots[family][config]); + return &prot[config]; } -static void tcp_bpf_reinit_sk_prot(struct sock *sk, struct sk_psock *psock) -{ - int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; - int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE; - - /* Reinit occurs when program types change e.g. TCP_BPF_TX is removed - * or added requiring sk_prot hook updates. We keep original saved - * hooks in this case. - * - * Pairs with lockless read in sk_clone_lock(). - */ - WRITE_ONCE(sk->sk_prot, &tcp_bpf_prots[family][config]); -} - -static int tcp_bpf_assert_proto_ops(struct proto *ops) -{ - /* In order to avoid retpoline, we make assumptions when we call - * into ops if e.g. a psock is not present. Make sure they are - * indeed valid assumptions. - */ - return ops->recvmsg == tcp_recvmsg && - ops->sendmsg == tcp_sendmsg && - ops->sendpage == tcp_sendpage ? 0 : -ENOTSUPP; -} +static struct proto tcp_bpf_ipv4[TCP_BPF_NUM_CFGS]; +static struct proto tcp_bpf_ipv6[TCP_BPF_NUM_CFGS]; +static struct sk_psock_hooks tcp_bpf_hooks __read_mostly = { + .ipv4 = &tcp_bpf_ipv4[0], + .ipv6 = &tcp_bpf_ipv6[0], + .rebuild_proto = tcp_bpf_rebuild_proto, + .choose_proto = tcp_bpf_choose_proto, +}; -void tcp_bpf_reinit(struct sock *sk) +static int __init tcp_bpf_init_psock_hooks(void) { - struct sk_psock *psock; - - sock_owned_by_me(sk); - - rcu_read_lock(); - psock = sk_psock(sk); - tcp_bpf_reinit_sk_prot(sk, psock); - rcu_read_unlock(); + return sk_psock_hooks_init(&tcp_bpf_hooks, &tcp_prot); } +core_initcall(tcp_bpf_init_psock_hooks); int tcp_bpf_init(struct sock *sk) { - struct proto *ops = READ_ONCE(sk->sk_prot); - struct sk_psock *psock; + int ret; sock_owned_by_me(sk); rcu_read_lock(); - psock = sk_psock(sk); - if (unlikely(!psock || psock->sk_proto || - tcp_bpf_assert_proto_ops(ops))) { - rcu_read_unlock(); - return -EINVAL; - } - tcp_bpf_check_v6_needs_rebuild(sk, ops); - tcp_bpf_update_sk_prot(sk, psock); + ret = sk_psock_hooks_install(&tcp_bpf_hooks, sk); rcu_read_unlock(); - return 0; + return ret; } /* If a child got cloned from a listening socket that had tcp_bpf @@ -650,9 +599,10 @@ int tcp_bpf_init(struct sock *sk) */ void tcp_bpf_clone(const struct sock *sk, struct sock *newsk) { - int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; - struct proto *prot = newsk->sk_prot; + struct proto *prot = READ_ONCE(sk->sk_prot); - if (prot == &tcp_bpf_prots[family][TCP_BPF_BASE]) + /* TCP_LISTEN can only use TCP_BPF_BASE, so this is safe */ + if (unlikely(prot == &tcp_bpf_ipv4[TCP_BPF_BASE] || + prot == &tcp_bpf_ipv6[TCP_BPF_BASE])) newsk->sk_prot = sk->sk_prot_creator; } From patchwork Tue Feb 25 13:56:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenz Bauer X-Patchwork-Id: 1244274 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.a=rsa-sha256 header.s=google header.b=MXNOXsKC; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48RgTX6LHQz9sPk for ; Wed, 26 Feb 2020 00:56:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730478AbgBYN4r (ORCPT ); Tue, 25 Feb 2020 08:56:47 -0500 Received: from mail-wm1-f52.google.com ([209.85.128.52]:39708 "EHLO mail-wm1-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730240AbgBYN4q (ORCPT ); Tue, 25 Feb 2020 08:56:46 -0500 Received: by mail-wm1-f52.google.com with SMTP id c84so3237682wme.4 for ; Tue, 25 Feb 2020 05:56:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=59eBK88lSB2D3XYVgkWiAVbz/oypnY57KcXTslgb3N4=; b=MXNOXsKCId+2rMAmz4n/MBNehlvM6kr6+fn0eMk8c5kXH862yUO29DckTmxPSyxa/H lwOfk2FInlStT3opaXvII+8lqm6rAqUUjh1FQwxlo3oubAuwfbhWyHqDa505pRO4IEwR /40NMURLeXMg3RoOPNtZZvL/+6dF+C5Jr6Otg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=59eBK88lSB2D3XYVgkWiAVbz/oypnY57KcXTslgb3N4=; b=qhPfhwdVy+lIivxkRzP+OBtxT0AkG5AuzF1bBPbQKyt8gLp8IcEWmcOVoxYhdH0CcB jUh022e/sx+EqDE2E+k40z5jLOpzQ8vku2HQW8TlD3S9kMnCYxHXrD+SPBlFcaMBeDg6 A3NtrdYu5plz1orPrvgN/7a0SU1W4odpwIXYBs4PLnBi4Y8LP4rZvpExscjLf1lVyoV9 c3k3jYJCDMHUacV+gJX71wc8Yh0A421eaDgANj4dyhcSkULm/ErTTnnIlvke9okm9nkI QngkSpJrgkndCi6/fNManZKSIWjoBd/Q4zQU4lg69Fh4X8UtSpdzRRQvps1OROAqA/7m HiWQ== X-Gm-Message-State: APjAAAVciATh5wGMbDG/m1Drk65ikmjSkGOth8L8f+J+qP1LeYBCS4iY uYzLk4MSB+KrQ5T+Tp8Ih2rdoQ== X-Google-Smtp-Source: APXvYqxTNO5ANWSYyQ1ef+Vvc2vX6TKpdqbsIY57CNG7Sjv2XfE5AkWTWeBaOm6Pzc5QqTZurorIHg== X-Received: by 2002:a1c:1d90:: with SMTP id d138mr3608448wmd.163.1582639005208; Tue, 25 Feb 2020 05:56:45 -0800 (PST) Received: from localhost.localdomain ([2a06:98c0:1000:8800:3dea:15ba:1870:8e94]) by smtp.gmail.com with ESMTPSA id t128sm4463580wmf.28.2020.02.25.05.56.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 05:56:44 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, kernel-team@cloudflare.com, Lorenz Bauer Subject: [PATCH bpf-next 4/7] bpf: sockmap: allow UDP sockets Date: Tue, 25 Feb 2020 13:56:33 +0000 Message-Id: <20200225135636.5768-5-lmb@cloudflare.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225135636.5768-1-lmb@cloudflare.com> References: <20200225135636.5768-1-lmb@cloudflare.com> MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Add basic psock hooks for UDP sockets. This allows adding and removing sockets, as well as automatic removal on unhash and close. Signed-off-by: Lorenz Bauer --- MAINTAINERS | 1 + include/linux/udp.h | 4 ++++ net/core/sock_map.c | 47 +++++++++++++++++++++++----------------- net/ipv4/Makefile | 1 + net/ipv4/udp_bpf.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 net/ipv4/udp_bpf.c diff --git a/MAINTAINERS b/MAINTAINERS index 2af5fa73155e..495ba52038ad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9358,6 +9358,7 @@ F: include/linux/skmsg.h F: net/core/skmsg.c F: net/core/sock_map.c F: net/ipv4/tcp_bpf.c +F: net/ipv4/udp_bpf.c LANTIQ / INTEL Ethernet drivers M: Hauke Mehrtens diff --git a/include/linux/udp.h b/include/linux/udp.h index aa84597bdc33..d90d8fd5f73d 100644 --- a/include/linux/udp.h +++ b/include/linux/udp.h @@ -143,4 +143,8 @@ static inline bool udp_unexpected_gso(struct sock *sk, struct sk_buff *skb) #define IS_UDPLITE(__sk) (__sk->sk_protocol == IPPROTO_UDPLITE) +#if defined(CONFIG_NET_SOCK_MSG) +int udp_bpf_init(struct sock *sk); +#endif + #endif /* _LINUX_UDP_H */ diff --git a/net/core/sock_map.c b/net/core/sock_map.c index c84cc9fc7f6b..f998192c425f 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -153,7 +153,7 @@ static struct sk_psock *sock_map_psock_get_checked(struct sock *sk) rcu_read_lock(); psock = sk_psock(sk); if (psock) { - if (sk->sk_prot->recvmsg != tcp_bpf_recvmsg) { + if (sk->sk_prot->close != sock_map_close) { psock = ERR_PTR(-EBUSY); goto out; } @@ -166,6 +166,14 @@ static struct sk_psock *sock_map_psock_get_checked(struct sock *sk) return psock; } +static int sock_map_init_hooks(struct sock *sk) +{ + if (sk->sk_type == SOCK_DGRAM) + return udp_bpf_init(sk); + else + return tcp_bpf_init(sk); +} + static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, struct sock *sk) { @@ -220,7 +228,7 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, if (msg_parser) psock_set_prog(&psock->progs.msg_parser, msg_parser); - ret = tcp_bpf_init(sk); + ret = sock_map_init_hooks(sk); if (ret < 0) goto out_drop; @@ -267,7 +275,7 @@ static int sock_map_link_no_progs(struct bpf_map *map, struct sock *sk) return -ENOMEM; init: - ret = tcp_bpf_init(sk); + ret = sock_map_init_hooks(sk); if (ret < 0) sk_psock_put(sk, psock); return ret; @@ -394,9 +402,14 @@ static int sock_map_get_next_key(struct bpf_map *map, void *key, void *next) return 0; } +static bool sock_map_sk_is_tcp(const struct sock *sk) +{ + return sk->sk_type == SOCK_STREAM && sk->sk_protocol == IPPROTO_TCP; +} + static bool sock_map_redirect_allowed(const struct sock *sk) { - return sk->sk_state != TCP_LISTEN; + return sock_map_sk_is_tcp(sk) && sk->sk_state != TCP_LISTEN; } static int sock_map_update_common(struct bpf_map *map, u32 idx, @@ -466,15 +479,17 @@ static bool sock_map_op_okay(const struct bpf_sock_ops_kern *ops) ops->op == BPF_SOCK_OPS_TCP_LISTEN_CB; } +static bool sock_map_sk_is_udp(const struct sock *sk) +{ + return sk->sk_type == SOCK_DGRAM && sk->sk_protocol == IPPROTO_UDP; +} + static bool sock_map_sk_is_suitable(const struct sock *sk) { - return sk->sk_type == SOCK_STREAM && - sk->sk_protocol == IPPROTO_TCP; -} + const int tcp_flags = TCPF_ESTABLISHED | TCPF_LISTEN | TCPF_SYN_RECV; -static bool sock_map_sk_state_allowed(const struct sock *sk) -{ - return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN); + return (sock_map_sk_is_udp(sk) && sk_hashed(sk)) || + (sock_map_sk_is_tcp(sk) && (1 << sk->sk_state) & tcp_flags); } static int sock_map_update_elem(struct bpf_map *map, void *key, @@ -501,13 +516,9 @@ static int sock_map_update_elem(struct bpf_map *map, void *key, ret = -EINVAL; goto out; } - if (!sock_map_sk_is_suitable(sk)) { - ret = -EOPNOTSUPP; - goto out; - } sock_map_sk_acquire(sk); - if (!sock_map_sk_state_allowed(sk)) + if (!sock_map_sk_is_suitable(sk)) ret = -EOPNOTSUPP; else ret = sock_map_update_common(map, idx, sk, flags); @@ -849,13 +860,9 @@ static int sock_hash_update_elem(struct bpf_map *map, void *key, ret = -EINVAL; goto out; } - if (!sock_map_sk_is_suitable(sk)) { - ret = -EOPNOTSUPP; - goto out; - } sock_map_sk_acquire(sk); - if (!sock_map_sk_state_allowed(sk)) + if (!sock_map_sk_is_suitable(sk)) ret = -EOPNOTSUPP; else ret = sock_hash_update_common(map, key, sk, flags); diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 9d97bace13c8..48cc05d365e4 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o +obj-$(CONFIG_NET_SOCK_MSG) += udp_bpf.o obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c new file mode 100644 index 000000000000..e085a0648a94 --- /dev/null +++ b/net/ipv4/udp_bpf.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Cloudflare Ltd https://cloudflare.com */ + +#include +#include +#include +#include +#include +#include + +#include + +static int udp_bpf_rebuild_protos(struct proto *prot, struct proto *base) +{ + *prot = *base; + prot->unhash = sock_map_unhash; + prot->close = sock_map_close; + return 0; +} + +static struct proto *udp_bpf_choose_proto(struct proto prot[], + struct sk_psock *psock) +{ + return prot; +} + +static struct proto udpv4_proto; +static struct proto udpv6_proto; + +static struct sk_psock_hooks udp_psock_proto __read_mostly = { + .ipv4 = &udpv4_proto, + .ipv6 = &udpv6_proto, + .rebuild_proto = udp_bpf_rebuild_protos, + .choose_proto = udp_bpf_choose_proto, +}; + +static int __init udp_bpf_init_psock_hooks(void) +{ + return sk_psock_hooks_init(&udp_psock_proto, &udp_prot); +} +core_initcall(udp_bpf_init_psock_hooks); + +int udp_bpf_init(struct sock *sk) +{ + int ret; + + sock_owned_by_me(sk); + + rcu_read_lock(); + ret = sk_psock_hooks_install(&udp_psock_proto, sk); + rcu_read_unlock(); + return ret; +} From patchwork Tue Feb 25 13:56:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenz Bauer X-Patchwork-Id: 1244277 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.a=rsa-sha256 header.s=google header.b=x6O/9aXU; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48RgTb23kbz9sRQ for ; Wed, 26 Feb 2020 00:56:51 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730487AbgBYN4t (ORCPT ); Tue, 25 Feb 2020 08:56:49 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:45284 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730240AbgBYN4t (ORCPT ); Tue, 25 Feb 2020 08:56:49 -0500 Received: by mail-wr1-f67.google.com with SMTP id g3so14796120wrs.12 for ; Tue, 25 Feb 2020 05:56:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qgZ3nu/Bbfdwe+GDZ451yJiCX8ETGH9pPjG5oF9BPog=; b=x6O/9aXUU05oL3dc4nKNs8zNtN8koSz9cOra3Csbb7Sch7rCCBxHiRlKZ9m7Kb+4y1 RFtjkjmqeXClHkVQk9WP+aPoDIX0OQjYhDgRn6EbYTmL5acnNuKkBSeDjwtSu21sTsd4 ZkPt+DIu6GwQKP9F8DX59Qw12dlKjZohhp3z8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qgZ3nu/Bbfdwe+GDZ451yJiCX8ETGH9pPjG5oF9BPog=; b=KoZugQobO1rQgsnYbTF2aK5j8caS1vFbJxCbeEyFEqDexiL6wJ5ZKf/KvywHdkFGtC ZnELS10U49Cf0SwidaPLRVDokMfVh8HXlxW41ntM5iwHsdtpNmRBlkw99a7Wx+1rw2v0 Urj5OaN2jaMN/kg8n/LOiUN+J6N12smUvl+4+1F5AP72ohE67aMT5bWF08ulKHzOKDvB 7a+iLDxZ7phpClGOhxOdpixUBQ4QL7vl2UYGgca2g9f63rheRM/gclYGn2GoihmXOxPx MwZ3g9uU0VIyjWuWjpEsvBCq6lzOpsDI2iUESsGbURCXbmk+AzK0Ngrqv1yHGHtO6O5E p1nQ== X-Gm-Message-State: APjAAAXoqd222c84y7BbIIZuA+ydyy2zKpj6mGzJ/X2x8I1mnYNS/ZuJ 2Cyj7eZ7N4acgOd3Td9pGvDQUA== X-Google-Smtp-Source: APXvYqwHmyyRUk3vIYhYbkETSsdfnRNKlwdruvH4vxIu9zuczLmgZcnvpYxsdMndcEHYvD277UP+wQ== X-Received: by 2002:a5d:45d1:: with SMTP id b17mr4423208wrs.59.1582639006633; Tue, 25 Feb 2020 05:56:46 -0800 (PST) Received: from localhost.localdomain ([2a06:98c0:1000:8800:3dea:15ba:1870:8e94]) by smtp.gmail.com with ESMTPSA id t128sm4463580wmf.28.2020.02.25.05.56.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 05:56:45 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, kernel-team@cloudflare.com, Lorenz Bauer Subject: [PATCH bpf-next 5/7] selftests: bpf: don't listen() on UDP sockets Date: Tue, 25 Feb 2020 13:56:34 +0000 Message-Id: <20200225135636.5768-6-lmb@cloudflare.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225135636.5768-1-lmb@cloudflare.com> References: <20200225135636.5768-1-lmb@cloudflare.com> MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Most tests for TCP sockmap can be adapted to UDP sockmap if the listen call is skipped. Rename listen_loopback, etc. to socket_loopback and skip listen() for SOCK_DGRAM. Signed-off-by: Lorenz Bauer --- .../selftests/bpf/prog_tests/sockmap_listen.c | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c index b1b2acea0638..4ba41dd26d6b 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c +++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c @@ -230,7 +230,7 @@ static int enable_reuseport(int s, int progfd) return 0; } -static int listen_loopback_reuseport(int family, int sotype, int progfd) +static int socket_loopback_reuseport(int family, int sotype, int progfd) { struct sockaddr_storage addr; socklen_t len; @@ -249,6 +249,9 @@ static int listen_loopback_reuseport(int family, int sotype, int progfd) if (err) goto close; + if (sotype == SOCK_DGRAM) + return s; + err = xlisten(s, SOMAXCONN); if (err) goto close; @@ -259,9 +262,9 @@ static int listen_loopback_reuseport(int family, int sotype, int progfd) return -1; } -static int listen_loopback(int family, int sotype) +static int socket_loopback(int family, int sotype) { - return listen_loopback_reuseport(family, sotype, -1); + return socket_loopback_reuseport(family, sotype, -1); } static void test_insert_invalid(int family, int sotype, int mapfd) @@ -333,7 +336,7 @@ static void test_insert_listening(int family, int sotype, int mapfd) u32 key; int s; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -349,7 +352,7 @@ static void test_delete_after_insert(int family, int sotype, int mapfd) u32 key; int s; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -366,7 +369,7 @@ static void test_delete_after_close(int family, int sotype, int mapfd) u64 value; u32 key; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -390,7 +393,7 @@ static void test_lookup_after_insert(int family, int sotype, int mapfd) u32 key; int s; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -417,7 +420,7 @@ static void test_lookup_after_delete(int family, int sotype, int mapfd) u64 value; u32 key; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -439,7 +442,7 @@ static void test_lookup_32_bit_value(int family, int sotype, int mapfd) u32 key, value32; int err, s; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -470,11 +473,11 @@ static void test_update_listening(int family, int sotype, int mapfd) u64 value; u32 key; - s1 = listen_loopback(family, sotype); + s1 = socket_loopback(family, sotype); if (s1 < 0) return; - s2 = listen_loopback(family, sotype); + s2 = socket_loopback(family, sotype); if (s2 < 0) goto close_s1; @@ -500,7 +503,7 @@ static void test_destroy_orphan_child(int family, int sotype, int mapfd) u64 value; u32 key; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -534,7 +537,7 @@ static void test_clone_after_delete(int family, int sotype, int mapfd) u64 value; u32 key; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s < 0) return; @@ -570,7 +573,7 @@ static void test_accept_after_delete(int family, int sotype, int mapfd) socklen_t len; u64 value; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s == -1) return; @@ -624,7 +627,7 @@ static void test_accept_before_delete(int family, int sotype, int mapfd) socklen_t len; u64 value; - s = listen_loopback(family, sotype); + s = socket_loopback(family, sotype); if (s == -1) return; @@ -735,7 +738,7 @@ static void test_syn_recv_insert_delete(int family, int sotype, int mapfd) int err, s; u64 value; - s = listen_loopback(family, sotype | SOCK_NONBLOCK); + s = socket_loopback(family, sotype | SOCK_NONBLOCK); if (s < 0) return; @@ -877,7 +880,7 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd, zero_verdict_count(verd_mapfd); - s = listen_loopback(family, sotype | SOCK_NONBLOCK); + s = socket_loopback(family, sotype | SOCK_NONBLOCK); if (s < 0) return; @@ -1009,7 +1012,7 @@ static void redir_to_listening(int family, int sotype, int sock_mapfd, zero_verdict_count(verd_mapfd); - s = listen_loopback(family, sotype | SOCK_NONBLOCK); + s = socket_loopback(family, sotype | SOCK_NONBLOCK); if (s < 0) return; @@ -1120,7 +1123,7 @@ static void test_reuseport_select_listening(int family, int sotype, zero_verdict_count(verd_map); - s = listen_loopback_reuseport(family, sotype, reuseport_prog); + s = socket_loopback_reuseport(family, sotype, reuseport_prog); if (s < 0) return; @@ -1174,7 +1177,7 @@ static void test_reuseport_select_connected(int family, int sotype, zero_verdict_count(verd_map); - s = listen_loopback_reuseport(family, sotype, reuseport_prog); + s = socket_loopback_reuseport(family, sotype, reuseport_prog); if (s < 0) return; @@ -1249,11 +1252,11 @@ static void test_reuseport_mixed_groups(int family, int sotype, int sock_map, zero_verdict_count(verd_map); /* Create two listeners, each in its own reuseport group */ - s1 = listen_loopback_reuseport(family, sotype, reuseport_prog); + s1 = socket_loopback_reuseport(family, sotype, reuseport_prog); if (s1 < 0) return; - s2 = listen_loopback_reuseport(family, sotype, reuseport_prog); + s2 = socket_loopback_reuseport(family, sotype, reuseport_prog); if (s2 < 0) goto close_srv1; From patchwork Tue Feb 25 13:56:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenz Bauer X-Patchwork-Id: 1244280 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.a=rsa-sha256 header.s=google header.b=HZfxrO2D; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48RgTf2fzJz9sPk for ; Wed, 26 Feb 2020 00:56:54 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730347AbgBYN4x (ORCPT ); Tue, 25 Feb 2020 08:56:53 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:33376 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730483AbgBYN4u (ORCPT ); Tue, 25 Feb 2020 08:56:50 -0500 Received: by mail-wr1-f68.google.com with SMTP id u6so14879995wrt.0 for ; Tue, 25 Feb 2020 05:56:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SLU+VXTwa+gQnfRMK9gYsKNfXb9lUcrwS038svEJU5o=; b=HZfxrO2DE5QWccPhGVGfoZMWEldWLluhX2dBzmqcX5v2Dwhw5kzZWu4eScPwt0X7wv YYh4uw6WJJJfEyqNSjN3j/Q7UJ/m/UCmCuGeqXfHG6dn+wPGT8J8yg+FxTi+X9R1xw9R eC8O8GHxOuIdzLF5MUntG0vk08oZPlbhR5cv8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SLU+VXTwa+gQnfRMK9gYsKNfXb9lUcrwS038svEJU5o=; b=DnrQ/igCmc5r+J6ECc8o7//OsBxdmKxLFUvJkovNn+iaCSxCvXjczx3aFXH9IW6bqt EeM5BReHBxx7yecCYZSVbbLxlVboO60IltAi/k1LHmRvk9CXnl8uMrZhQMwBQeKhmcSq mPTzK501Ih/TVJIgsn3kSecfYItmpB8/BA9/oQJWiEkLHHPNPkuBnf72nJrnxnsRdCUt Psbe1MKIp+Y2UwJlt0YrwXAz8Urmsll95faJprCkPxQckwkvpQFnFN/BlWmPqtzkgh9V ljKz5vWA9lqufDQEGJkgW3k2I1YK7y6A249m88hMHXIYBLXHDsTTvQqMqnyPotIrmlCR 6CzQ== X-Gm-Message-State: APjAAAVs0LOHM2KE21iYYaMe9qbDzcp3JjXYUtI+MIKgRbRXm7TJ9Cz9 oNKHuGGaPljUha+fnTLOi9Jqhg== X-Google-Smtp-Source: APXvYqy688F/sc2m+LBgUuAqrJ9I2d4Ungk/+caFLjiRNU2gXHG5tKH4rokIF/aLY+j3dwMM82/UkA== X-Received: by 2002:adf:d0c1:: with SMTP id z1mr77903608wrh.371.1582639008036; Tue, 25 Feb 2020 05:56:48 -0800 (PST) Received: from localhost.localdomain ([2a06:98c0:1000:8800:3dea:15ba:1870:8e94]) by smtp.gmail.com with ESMTPSA id t128sm4463580wmf.28.2020.02.25.05.56.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 05:56:47 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, kernel-team@cloudflare.com, Lorenz Bauer Subject: [PATCH bpf-next 6/7] selftests: bpf: add tests for UDP sockets in sockmap Date: Tue, 25 Feb 2020 13:56:35 +0000 Message-Id: <20200225135636.5768-7-lmb@cloudflare.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225135636.5768-1-lmb@cloudflare.com> References: <20200225135636.5768-1-lmb@cloudflare.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Expand the TCP sockmap test suite to also check UDP sockets. Signed-off-by: Lorenz Bauer --- .../selftests/bpf/prog_tests/sockmap_listen.c | 92 +++++++++++++------ 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c index 4ba41dd26d6b..72e578a5a5d2 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c +++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c @@ -330,7 +330,7 @@ static void test_insert_bound(int family, int sotype, int mapfd) xclose(s); } -static void test_insert_listening(int family, int sotype, int mapfd) +static void test_insert(int family, int sotype, int mapfd) { u64 value; u32 key; @@ -467,7 +467,7 @@ static void test_lookup_32_bit_value(int family, int sotype, int mapfd) xclose(s); } -static void test_update_listening(int family, int sotype, int mapfd) +static void test_update_existing(int family, int sotype, int mapfd) { int s1, s2; u64 value; @@ -1302,11 +1302,15 @@ static void test_reuseport_mixed_groups(int family, int sotype, int sock_map, xclose(s1); } -#define TEST(fn) \ +#define TEST_SOTYPE(fn, sotype) \ { \ - fn, #fn \ + fn, #fn, sotype \ } +#define TEST(fn) TEST_SOTYPE(fn, 0) +#define TEST_STREAM(fn) TEST_SOTYPE(fn, SOCK_STREAM) +#define TEST_DGRAM(fn) TEST_SOTYPE(fn, SOCK_DGRAM) + static void test_ops_cleanup(const struct bpf_map *map) { const struct bpf_map_def *def; @@ -1353,18 +1357,31 @@ static const char *map_type_str(const struct bpf_map *map) } } +static const char *sotype_str(int sotype) +{ + switch (sotype) { + case SOCK_DGRAM: + return "UDP"; + case SOCK_STREAM: + return "TCP"; + default: + return "unknown"; + } +} + static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map, int family, int sotype) { const struct op_test { void (*fn)(int family, int sotype, int mapfd); const char *name; + int sotype; } tests[] = { /* insert */ TEST(test_insert_invalid), TEST(test_insert_opened), - TEST(test_insert_bound), - TEST(test_insert_listening), + TEST_STREAM(test_insert_bound), + TEST(test_insert), /* delete */ TEST(test_delete_after_insert), TEST(test_delete_after_close), @@ -1373,28 +1390,33 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map, TEST(test_lookup_after_delete), TEST(test_lookup_32_bit_value), /* update */ - TEST(test_update_listening), + TEST(test_update_existing), /* races with insert/delete */ - TEST(test_destroy_orphan_child), - TEST(test_syn_recv_insert_delete), - TEST(test_race_insert_listen), + TEST_STREAM(test_destroy_orphan_child), + TEST_STREAM(test_syn_recv_insert_delete), + TEST_STREAM(test_race_insert_listen), /* child clone */ - TEST(test_clone_after_delete), - TEST(test_accept_after_delete), - TEST(test_accept_before_delete), + TEST_STREAM(test_clone_after_delete), + TEST_STREAM(test_accept_after_delete), + TEST_STREAM(test_accept_before_delete), }; - const char *family_name, *map_name; + const char *family_name, *map_name, *sotype_name; const struct op_test *t; char s[MAX_TEST_NAME]; int map_fd; family_name = family_str(family); map_name = map_type_str(map); + sotype_name = sotype_str(sotype); map_fd = bpf_map__fd(map); + for (t = tests; t < tests + ARRAY_SIZE(tests); t++) { - snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, - t->name); + snprintf(s, sizeof(s), "%s %s %s %s", map_name, family_name, + sotype_name, t->name); + + if (t->sotype != 0 && t->sotype != sotype) + continue; if (!test__start_subtest(s)) continue; @@ -1411,22 +1433,28 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map, void (*fn)(struct test_sockmap_listen *skel, struct bpf_map *map, int family, int sotype); const char *name; + int sotype; } tests[] = { - TEST(test_skb_redir_to_connected), - TEST(test_skb_redir_to_listening), - TEST(test_msg_redir_to_connected), - TEST(test_msg_redir_to_listening), + TEST_STREAM(test_skb_redir_to_connected), + TEST_STREAM(test_skb_redir_to_listening), + TEST_STREAM(test_msg_redir_to_connected), + TEST_STREAM(test_msg_redir_to_listening), }; - const char *family_name, *map_name; + const char *family_name, *map_name, *sotype_name; const struct redir_test *t; char s[MAX_TEST_NAME]; family_name = family_str(family); map_name = map_type_str(map); + sotype_name = sotype_str(sotype); for (t = tests; t < tests + ARRAY_SIZE(tests); t++) { - snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, - t->name); + snprintf(s, sizeof(s), "%s %s %s %s", map_name, family_name, + sotype_name, t->name); + + if (t->sotype != 0 && t->sotype != sotype) + continue; + if (!test__start_subtest(s)) continue; @@ -1441,26 +1469,31 @@ static void test_reuseport(struct test_sockmap_listen *skel, void (*fn)(int family, int sotype, int socket_map, int verdict_map, int reuseport_prog); const char *name; + int sotype; } tests[] = { - TEST(test_reuseport_select_listening), - TEST(test_reuseport_select_connected), - TEST(test_reuseport_mixed_groups), + TEST_STREAM(test_reuseport_select_listening), + TEST_STREAM(test_reuseport_select_connected), + TEST_STREAM(test_reuseport_mixed_groups), }; int socket_map, verdict_map, reuseport_prog; - const char *family_name, *map_name; + const char *family_name, *map_name, *sotype_name; const struct reuseport_test *t; char s[MAX_TEST_NAME]; family_name = family_str(family); map_name = map_type_str(map); + sotype_name = sotype_str(sotype); socket_map = bpf_map__fd(map); verdict_map = bpf_map__fd(skel->maps.verdict_map); reuseport_prog = bpf_program__fd(skel->progs.prog_reuseport); for (t = tests; t < tests + ARRAY_SIZE(tests); t++) { - snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, - t->name); + snprintf(s, sizeof(s), "%s %s %s %s", map_name, family_name, + sotype_name, t->name); + + if (t->sotype != 0 && t->sotype != sotype) + continue; if (!test__start_subtest(s)) continue; @@ -1473,6 +1506,7 @@ static void run_tests(struct test_sockmap_listen *skel, struct bpf_map *map, int family) { test_ops(skel, map, family, SOCK_STREAM); + test_ops(skel, map, family, SOCK_DGRAM); test_redir(skel, map, family, SOCK_STREAM); test_reuseport(skel, map, family, SOCK_STREAM); } From patchwork Tue Feb 25 13:56:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenz Bauer X-Patchwork-Id: 1244281 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=quarantine dis=none) header.from=cloudflare.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=cloudflare.com header.i=@cloudflare.com header.a=rsa-sha256 header.s=google header.b=s5u3MDHX; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48RgTg2khVz9sP7 for ; Wed, 26 Feb 2020 00:56:55 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730507AbgBYN4w (ORCPT ); Tue, 25 Feb 2020 08:56:52 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:38125 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730490AbgBYN4w (ORCPT ); Tue, 25 Feb 2020 08:56:52 -0500 Received: by mail-wm1-f66.google.com with SMTP id a9so3247779wmj.3 for ; Tue, 25 Feb 2020 05:56:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=tdUpExQ3hzj21QBKAtvqnsJNrL5zKnYkhtRdt8iWk7k=; b=s5u3MDHXfeJEdDUkFi2tRNaJM12+acezT/J5c/Y0dUXkBOk/Z9YD1zJLa8EIPBuT6B 7h7PRy4x1vohUccQmHB+TwhLO9VWNXD0fiWJOJKZU1nlmtsRs+w7A2QaomMVn+NiNi3u 6GoTma0klKIR0YB8fQI4/PbM1mqrws28FonEQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tdUpExQ3hzj21QBKAtvqnsJNrL5zKnYkhtRdt8iWk7k=; b=ZOib4ke1D+oKgawG5M4I+SsiUdKP2HJ0SDwVkqWeNV2MWdzsI8iYXNlGMX+6YS9k2a Mh/5/Kyz3JFR0R6NuwAL2ZHOPDhkm3ctdbSMPvklLVhry8u21MrS1t79bwAstAwNsK1s eeHoIw+bL2zrxdntVorfk9RUfLTKdzIcufbkFOp3hEMRr79atGZVrBbRcTk9mXxv/KyT C8gbyv0A1IfIjVn0ID+XvZV04Y9j0dCLqJLSoD+I7kowmfk7etzO3dzYTizUeKCZQtyd lka/p8AsALnY4aP6VPW6Kayao9/12opysNvx1SINbtalMmxthPGeYJ3IhZTKXHqsHanw yfXQ== X-Gm-Message-State: APjAAAVK/JXVSGTMG34Aj6Lk6mnd6zLP2nH7y/sUXO4kIDu0vsmEERlx t1YMSlh/BQcLvlZb/qPTtRSNDzqxELFdCg== X-Google-Smtp-Source: APXvYqwmAujwCf7IqxSUcZ5V29CAKHVHg254H8PhRtUSEgNxQ9uaMCXdJUMj69n1j+nAigX8UVaXsg== X-Received: by 2002:a7b:c450:: with SMTP id l16mr5662485wmi.31.1582639009440; Tue, 25 Feb 2020 05:56:49 -0800 (PST) Received: from localhost.localdomain ([2a06:98c0:1000:8800:3dea:15ba:1870:8e94]) by smtp.gmail.com with ESMTPSA id t128sm4463580wmf.28.2020.02.25.05.56.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 05:56:48 -0800 (PST) From: Lorenz Bauer To: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, kernel-team@cloudflare.com, Lorenz Bauer Subject: [PATCH bpf-next 7/7] selftests: bpf: enable UDP sockmap reuseport tests Date: Tue, 25 Feb 2020 13:56:36 +0000 Message-Id: <20200225135636.5768-8-lmb@cloudflare.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200225135636.5768-1-lmb@cloudflare.com> References: <20200225135636.5768-1-lmb@cloudflare.com> MIME-Version: 1.0 Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org Remove the guard that disables UDP tests now that sockmap has support for them. Signed-off-by: Lorenz Bauer --- tools/testing/selftests/bpf/prog_tests/select_reuseport.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/select_reuseport.c b/tools/testing/selftests/bpf/prog_tests/select_reuseport.c index 68d452bb9fd9..4c09766344a4 100644 --- a/tools/testing/selftests/bpf/prog_tests/select_reuseport.c +++ b/tools/testing/selftests/bpf/prog_tests/select_reuseport.c @@ -816,13 +816,6 @@ static void test_config(int sotype, sa_family_t family, bool inany) if (!test__start_subtest(s)) continue; - if (sotype == SOCK_DGRAM && - inner_map_type != BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) { - /* SOCKMAP/SOCKHASH don't support UDP yet */ - test__skip(); - continue; - } - setup_per_test(sotype, family, inany, t->no_inner_map); t->fn(sotype, family); cleanup_per_test(t->no_inner_map);