Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: add a UID to use for ULP socket assignment

Create a UID field and enum that can be used to assign ULPs to
sockets. This saves a set of string comparisons if the ULP id
is known.

For sockmap, which is added in the next patches, a ULP is used to
hook into TCP sockets close state. In this case the ULP being added
is done at map insert time and the ULP is known and done on the kernel
side. In this case the named lookup is not needed. Because we don't
want to expose psock internals to user space socket options a user
visible flag is also added. For TLS this is set for BPF it will be
cleared.

Alos remove pr_notice, user gets an error code back and should check
that rather than rely on logs.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

John Fastabend and committed by
Daniel Borkmann
b11a632c 7b4eb53d

+62 -5
+6
include/net/tcp.h
··· 1983 1983 #define TCP_ULP_MAX 128 1984 1984 #define TCP_ULP_BUF_MAX (TCP_ULP_NAME_MAX*TCP_ULP_MAX) 1985 1985 1986 + enum { 1987 + TCP_ULP_TLS, 1988 + }; 1989 + 1986 1990 struct tcp_ulp_ops { 1987 1991 struct list_head list; 1988 1992 ··· 1995 1991 /* cleanup ulp */ 1996 1992 void (*release)(struct sock *sk); 1997 1993 1994 + int uid; 1998 1995 char name[TCP_ULP_NAME_MAX]; 1996 + bool user_visible; 1999 1997 struct module *owner; 2000 1998 }; 2001 1999 int tcp_register_ulp(struct tcp_ulp_ops *type);
+54 -5
net/ipv4/tcp_ulp.c
··· 29 29 return NULL; 30 30 } 31 31 32 + static struct tcp_ulp_ops *tcp_ulp_find_id(const int ulp) 33 + { 34 + struct tcp_ulp_ops *e; 35 + 36 + list_for_each_entry_rcu(e, &tcp_ulp_list, list) { 37 + if (e->uid == ulp) 38 + return e; 39 + } 40 + 41 + return NULL; 42 + } 43 + 32 44 static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name) 33 45 { 34 46 const struct tcp_ulp_ops *ulp = NULL; ··· 63 51 return ulp; 64 52 } 65 53 54 + static const struct tcp_ulp_ops *__tcp_ulp_lookup(const int uid) 55 + { 56 + const struct tcp_ulp_ops *ulp; 57 + 58 + rcu_read_lock(); 59 + ulp = tcp_ulp_find_id(uid); 60 + if (!ulp || !try_module_get(ulp->owner)) 61 + ulp = NULL; 62 + rcu_read_unlock(); 63 + return ulp; 64 + } 65 + 66 66 /* Attach new upper layer protocol to the list 67 67 * of available protocols. 68 68 */ ··· 83 59 int ret = 0; 84 60 85 61 spin_lock(&tcp_ulp_list_lock); 86 - if (tcp_ulp_find(ulp->name)) { 87 - pr_notice("%s already registered or non-unique name\n", 88 - ulp->name); 62 + if (tcp_ulp_find(ulp->name)) 89 63 ret = -EEXIST; 90 - } else { 64 + else 91 65 list_add_tail_rcu(&ulp->list, &tcp_ulp_list); 92 - } 93 66 spin_unlock(&tcp_ulp_list_lock); 94 67 95 68 return ret; ··· 142 121 return -EEXIST; 143 122 144 123 ulp_ops = __tcp_ulp_find_autoload(name); 124 + if (!ulp_ops) 125 + return -ENOENT; 126 + 127 + if (!ulp_ops->user_visible) { 128 + module_put(ulp_ops->owner); 129 + return -ENOENT; 130 + } 131 + 132 + err = ulp_ops->init(sk); 133 + if (err) { 134 + module_put(ulp_ops->owner); 135 + return err; 136 + } 137 + 138 + icsk->icsk_ulp_ops = ulp_ops; 139 + return 0; 140 + } 141 + 142 + int tcp_set_ulp_id(struct sock *sk, int ulp) 143 + { 144 + struct inet_connection_sock *icsk = inet_csk(sk); 145 + const struct tcp_ulp_ops *ulp_ops; 146 + int err; 147 + 148 + if (icsk->icsk_ulp_ops) 149 + return -EEXIST; 150 + 151 + ulp_ops = __tcp_ulp_lookup(ulp); 145 152 if (!ulp_ops) 146 153 return -ENOENT; 147 154
+2
net/tls/tls_main.c
··· 484 484 485 485 static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = { 486 486 .name = "tls", 487 + .uid = TCP_ULP_TLS, 488 + .user_visible = true, 487 489 .owner = THIS_MODULE, 488 490 .init = tls_init, 489 491 };