* [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K
@ 2020-11-06 18:07 Tanner Love
2020-11-06 18:07 ` [PATCH net-next 1/2] " Tanner Love
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Tanner Love @ 2020-11-06 18:07 UTC (permalink / raw)
To: netdev; +Cc: davem, Tanner Love
From: Tanner Love <tannerlove@google.com>
First patch makes the change; second patch adds unit tests.
Tanner Love (2):
net/packet: make packet_fanout.arr size configurable up to 64K
selftests/net: test max_num_members, fanout_args in psock_fanout
include/uapi/linux/if_packet.h | 12 ++++
net/packet/af_packet.c | 37 +++++++----
net/packet/internal.h | 5 +-
tools/testing/selftests/net/psock_fanout.c | 72 +++++++++++++++++++++-
4 files changed, 109 insertions(+), 17 deletions(-)
--
2.29.1.341.ge80a0c044ae-goog
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH net-next 1/2] net/packet: make packet_fanout.arr size configurable up to 64K
2020-11-06 18:07 [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K Tanner Love
@ 2020-11-06 18:07 ` Tanner Love
2020-11-06 18:07 ` [PATCH net-next 2/2] selftests/net: test max_num_members, fanout_args in psock_fanout Tanner Love
2020-11-10 1:11 ` [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K Jakub Kicinski
2 siblings, 0 replies; 4+ messages in thread
From: Tanner Love @ 2020-11-06 18:07 UTC (permalink / raw)
To: netdev; +Cc: davem, Tanner Love, Willem de Bruijn, Eric Dumazet
From: Tanner Love <tannerlove@google.com>
One use case of PACKET_FANOUT is lockless reception with one socket
per CPU. 256 is a practical limit on increasingly many machines.
Increase PACKET_FANOUT_MAX to 64K. Expand setsockopt PACKET_FANOUT to
take an extra argument max_num_members. Also explicitly define a
fanout_args struct, instead of implicitly casting to an integer. This
documents the API and simplifies the control flow.
If max_num_members is not specified or is set to 0, then 256 is used,
same as before.
Signed-off-by: Tanner Love <tannerlove@google.com>
Signed-off-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
include/uapi/linux/if_packet.h | 12 +++++++++++
net/packet/af_packet.c | 37 +++++++++++++++++++++++-----------
net/packet/internal.h | 5 +++--
3 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index 3d884d68eb30..c07caf7b40db 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -2,6 +2,7 @@
#ifndef __LINUX_IF_PACKET_H
#define __LINUX_IF_PACKET_H
+#include <asm/byteorder.h>
#include <linux/types.h>
struct sockaddr_pkt {
@@ -296,6 +297,17 @@ struct packet_mreq {
unsigned char mr_address[8];
};
+struct fanout_args {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u16 id;
+ __u16 type_flags;
+#else
+ __u16 type_flags;
+ __u16 id;
+#endif
+ __u32 max_num_members;
+};
+
#define PACKET_MR_MULTICAST 0
#define PACKET_MR_PROMISC 1
#define PACKET_MR_ALLMULTI 2
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index cefbd50c1090..62ebfaa7adcb 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1636,13 +1636,15 @@ static bool fanout_find_new_id(struct sock *sk, u16 *new_id)
return false;
}
-static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
+static int fanout_add(struct sock *sk, struct fanout_args *args)
{
struct packet_rollover *rollover = NULL;
struct packet_sock *po = pkt_sk(sk);
+ u16 type_flags = args->type_flags;
struct packet_fanout *f, *match;
u8 type = type_flags & 0xff;
u8 flags = type_flags >> 8;
+ u16 id = args->id;
int err;
switch (type) {
@@ -1700,11 +1702,21 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
}
}
err = -EINVAL;
- if (match && match->flags != flags)
- goto out;
- if (!match) {
+ if (match) {
+ if (match->flags != flags)
+ goto out;
+ if (args->max_num_members &&
+ args->max_num_members != match->max_num_members)
+ goto out;
+ } else {
+ if (args->max_num_members > PACKET_FANOUT_MAX)
+ goto out;
+ if (!args->max_num_members)
+ /* legacy PACKET_FANOUT_MAX */
+ args->max_num_members = 256;
err = -ENOMEM;
- match = kzalloc(sizeof(*match), GFP_KERNEL);
+ match = kvzalloc(struct_size(match, arr, args->max_num_members),
+ GFP_KERNEL);
if (!match)
goto out;
write_pnet(&match->net, sock_net(sk));
@@ -1720,6 +1732,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
match->prot_hook.func = packet_rcv_fanout;
match->prot_hook.af_packet_priv = match;
match->prot_hook.id_match = match_fanout_group;
+ match->max_num_members = args->max_num_members;
list_add(&match->list, &fanout_list);
}
err = -EINVAL;
@@ -1730,7 +1743,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
match->prot_hook.type == po->prot_hook.type &&
match->prot_hook.dev == po->prot_hook.dev) {
err = -ENOSPC;
- if (refcount_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
+ if (refcount_read(&match->sk_ref) < match->max_num_members) {
__dev_remove_pack(&po->prot_hook);
po->fanout = match;
po->rollover = rollover;
@@ -1744,7 +1757,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
if (err && !refcount_read(&match->sk_ref)) {
list_del(&match->list);
- kfree(match);
+ kvfree(match);
}
out:
@@ -3075,7 +3088,7 @@ static int packet_release(struct socket *sock)
kfree(po->rollover);
if (f) {
fanout_release_data(f);
- kfree(f);
+ kvfree(f);
}
/*
* Now the socket is dead. No more input will appear.
@@ -3866,14 +3879,14 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
}
case PACKET_FANOUT:
{
- int val;
+ struct fanout_args args = { 0 };
- if (optlen != sizeof(val))
+ if (optlen != sizeof(int) && optlen != sizeof(args))
return -EINVAL;
- if (copy_from_sockptr(&val, optval, sizeof(val)))
+ if (copy_from_sockptr(&args, optval, optlen))
return -EFAULT;
- return fanout_add(sk, val & 0xffff, val >> 16);
+ return fanout_add(sk, &args);
}
case PACKET_FANOUT_DATA:
{
diff --git a/net/packet/internal.h b/net/packet/internal.h
index fd41ecb7f605..baafc3f3fa25 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -77,11 +77,12 @@ struct packet_ring_buffer {
};
extern struct mutex fanout_mutex;
-#define PACKET_FANOUT_MAX 256
+#define PACKET_FANOUT_MAX (1 << 16)
struct packet_fanout {
possible_net_t net;
unsigned int num_members;
+ u32 max_num_members;
u16 id;
u8 type;
u8 flags;
@@ -90,10 +91,10 @@ struct packet_fanout {
struct bpf_prog __rcu *bpf_prog;
};
struct list_head list;
- struct sock *arr[PACKET_FANOUT_MAX];
spinlock_t lock;
refcount_t sk_ref;
struct packet_type prot_hook ____cacheline_aligned_in_smp;
+ struct sock *arr[];
};
struct packet_rollover {
--
2.29.1.341.ge80a0c044ae-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH net-next 2/2] selftests/net: test max_num_members, fanout_args in psock_fanout
2020-11-06 18:07 [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K Tanner Love
2020-11-06 18:07 ` [PATCH net-next 1/2] " Tanner Love
@ 2020-11-06 18:07 ` Tanner Love
2020-11-10 1:11 ` [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K Jakub Kicinski
2 siblings, 0 replies; 4+ messages in thread
From: Tanner Love @ 2020-11-06 18:07 UTC (permalink / raw)
To: netdev; +Cc: davem, Tanner Love
From: Tanner Love <tannerlove@google.com>
Add an additional control test that verifies:
-specifying two different max_num_members values fails
-specifying max_num_members > PACKET_FANOUT_MAX fails
In datapath tests, set max_num_members to PACKET_FANOUT_MAX.
Signed-off-by: Tanner Love <tannerlove@google.com>
---
tools/testing/selftests/net/psock_fanout.c | 72 +++++++++++++++++++++-
1 file changed, 69 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/net/psock_fanout.c b/tools/testing/selftests/net/psock_fanout.c
index 2c522f7a0aec..db4521335722 100644
--- a/tools/testing/selftests/net/psock_fanout.c
+++ b/tools/testing/selftests/net/psock_fanout.c
@@ -56,12 +56,15 @@
#define RING_NUM_FRAMES 20
+static uint32_t cfg_max_num_members;
+
/* Open a socket in a given fanout mode.
* @return -1 if mode is bad, a valid socket otherwise */
static int sock_fanout_open(uint16_t typeflags, uint16_t group_id)
{
struct sockaddr_ll addr = {0};
- int fd, val;
+ struct fanout_args args;
+ int fd, val, err;
fd = socket(PF_PACKET, SOCK_RAW, 0);
if (fd < 0) {
@@ -83,8 +86,18 @@ static int sock_fanout_open(uint16_t typeflags, uint16_t group_id)
exit(1);
}
- val = (((int) typeflags) << 16) | group_id;
- if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &val, sizeof(val))) {
+ if (cfg_max_num_members) {
+ args.id = group_id;
+ args.type_flags = typeflags;
+ args.max_num_members = cfg_max_num_members;
+ err = setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &args,
+ sizeof(args));
+ } else {
+ val = (((int) typeflags) << 16) | group_id;
+ err = setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &val,
+ sizeof(val));
+ }
+ if (err) {
if (close(fd)) {
perror("close packet");
exit(1);
@@ -286,6 +299,56 @@ static void test_control_group(void)
}
}
+/* Test illegal max_num_members values */
+static void test_control_group_max_num_members(void)
+{
+ int fds[3];
+
+ fprintf(stderr, "test: control multiple sockets, max_num_members\n");
+
+ /* expected failure on greater than PACKET_FANOUT_MAX */
+ cfg_max_num_members = (1 << 16) + 1;
+ if (sock_fanout_open(PACKET_FANOUT_HASH, 0) != -1) {
+ fprintf(stderr, "ERROR: max_num_members > PACKET_FANOUT_MAX\n");
+ exit(1);
+ }
+
+ cfg_max_num_members = 256;
+ fds[0] = sock_fanout_open(PACKET_FANOUT_HASH, 0);
+ if (fds[0] == -1) {
+ fprintf(stderr, "ERROR: failed open\n");
+ exit(1);
+ }
+
+ /* expected failure on joining group with different max_num_members */
+ cfg_max_num_members = 257;
+ if (sock_fanout_open(PACKET_FANOUT_HASH, 0) != -1) {
+ fprintf(stderr, "ERROR: set different max_num_members\n");
+ exit(1);
+ }
+
+ /* success on joining group with same max_num_members */
+ cfg_max_num_members = 256;
+ fds[1] = sock_fanout_open(PACKET_FANOUT_HASH, 0);
+ if (fds[1] == -1) {
+ fprintf(stderr, "ERROR: failed to join group\n");
+ exit(1);
+ }
+
+ /* success on joining group with max_num_members unspecified */
+ cfg_max_num_members = 0;
+ fds[2] = sock_fanout_open(PACKET_FANOUT_HASH, 0);
+ if (fds[2] == -1) {
+ fprintf(stderr, "ERROR: failed to join group\n");
+ exit(1);
+ }
+
+ if (close(fds[2]) || close(fds[1]) || close(fds[0])) {
+ fprintf(stderr, "ERROR: closing sockets\n");
+ exit(1);
+ }
+}
+
/* Test creating a unique fanout group ids */
static void test_unique_fanout_group_ids(void)
{
@@ -426,8 +489,11 @@ int main(int argc, char **argv)
test_control_single();
test_control_group();
+ test_control_group_max_num_members();
test_unique_fanout_group_ids();
+ /* PACKET_FANOUT_MAX */
+ cfg_max_num_members = 1 << 16;
/* find a set of ports that do not collide onto the same socket */
ret = test_datapath(PACKET_FANOUT_HASH, port_off,
expect_hash[0], expect_hash[1]);
--
2.29.1.341.ge80a0c044ae-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K
2020-11-06 18:07 [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K Tanner Love
2020-11-06 18:07 ` [PATCH net-next 1/2] " Tanner Love
2020-11-06 18:07 ` [PATCH net-next 2/2] selftests/net: test max_num_members, fanout_args in psock_fanout Tanner Love
@ 2020-11-10 1:11 ` Jakub Kicinski
2 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2020-11-10 1:11 UTC (permalink / raw)
To: Tanner Love; +Cc: netdev, davem, Tanner Love
On Fri, 6 Nov 2020 13:07:39 -0500 Tanner Love wrote:
> From: Tanner Love <tannerlove@google.com>
>
> First patch makes the change; second patch adds unit tests.
Applied, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-11-10 1:11 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-11-06 18:07 [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K Tanner Love
2020-11-06 18:07 ` [PATCH net-next 1/2] " Tanner Love
2020-11-06 18:07 ` [PATCH net-next 2/2] selftests/net: test max_num_members, fanout_args in psock_fanout Tanner Love
2020-11-10 1:11 ` [PATCH net-next 0/2] net/packet: make packet_fanout.arr size configurable up to 64K Jakub Kicinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.