netinet: Remove IP(V6)_BINDMULTI

This option was added in commit 0a100a6f1e but was never completed.
In particular, there is no logic to map flowids to different listening
sockets, so it accomplishes basically the same thing as SO_REUSEPORT.
Meanwhile, we've since added SO_REUSEPORT_LB, which at least tries to
balance among listening sockets using a hash of the 4-tuple and some
optional NUMA policy.

The option was never documented or completed, and an exp-run revealed
nothing using it in the ports tree.  Moreover, it complicates the
already very complicated in_pcbbind_setup(), and the checking in
in_pcbbind_check_bindmulti() is insufficient.  So, let's remove it.

PR:		261398 (exp-run)
Reviewed by:	glebius
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D38574
This commit is contained in:
Mark Johnston 2023-02-27 09:52:28 -05:00
parent b9199d152f
commit 3aff4ccdd7
7 changed files with 4 additions and 84 deletions

View File

@ -463,7 +463,6 @@ VNET_DECLARE(uint32_t, in_loopback_mask);
/* unused; was IP_FAITH */
#define IP_ONESBCAST 23 /* bool: send all-ones broadcast */
#define IP_BINDANY 24 /* bool: allow bind to any address */
#define IP_BINDMULTI 25 /* bool: allow multiple listeners on a tuple */
#define IP_RSS_LISTEN_BUCKET 26 /* int; set RSS listen bucket */
#define IP_ORIGDSTADDR 27 /* bool: receive IP dst addr/port w/dgram */
#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR

View File

@ -860,36 +860,6 @@ inp_so_options(const struct inpcb *inp)
}
#endif /* INET || INET6 */
/*
* Check if a new BINDMULTI socket is allowed to be created.
*
* ni points to the new inp.
* oi points to the existing inp.
*
* This checks whether the existing inp also has BINDMULTI and
* whether the credentials match.
*/
int
in_pcbbind_check_bindmulti(const struct inpcb *ni, const struct inpcb *oi)
{
/* Check permissions match */
if ((ni->inp_flags2 & INP_BINDMULTI) &&
(ni->inp_cred->cr_uid !=
oi->inp_cred->cr_uid))
return (0);
/* Check the existing inp has BINDMULTI set */
if ((ni->inp_flags2 & INP_BINDMULTI) &&
((oi->inp_flags2 & INP_BINDMULTI) == 0))
return (0);
/*
* We're okay - either INP_BINDMULTI isn't set on ni, or
* it is and it matches the checks.
*/
return (1);
}
#ifdef INET
/*
* Set up a bind operation on a PCB, performing port allocation
@ -993,8 +963,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr_in *sin, in_addr_t *laddrp,
* XXX
* This entire block sorely needs a rewrite.
*/
if (t &&
((inp->inp_flags2 & INP_BINDMULTI) == 0) &&
if (t != NULL &&
(so->so_type != SOCK_STREAM ||
ntohl(t->inp_faddr.s_addr) == INADDR_ANY) &&
(ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
@ -1004,20 +973,10 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr_in *sin, in_addr_t *laddrp,
(inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
/*
* If the socket is a BINDMULTI socket, then
* the credentials need to match and the
* original socket also has to have been bound
* with BINDMULTI.
*/
if (t && (! in_pcbbind_check_bindmulti(inp, t)))
return (EADDRINUSE);
}
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, lookupflags, cred);
if (t && ((inp->inp_flags2 & INP_BINDMULTI) == 0) &&
(reuseport & inp_so_options(t)) == 0 &&
if (t != NULL && (reuseport & inp_so_options(t)) == 0 &&
(reuseport_lb & inp_so_options(t)) == 0) {
#ifdef INET6
if (ntohl(sin->sin_addr.s_addr) !=
@ -1028,8 +987,6 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr_in *sin, in_addr_t *laddrp,
(t->inp_vflag & INP_IPV6PROTO) == 0)
#endif
return (EADDRINUSE);
if (t && (! in_pcbbind_check_bindmulti(inp, t)))
return (EADDRINUSE);
}
}
}

View File

@ -669,7 +669,6 @@ int inp_so_options(const struct inpcb *inp);
#define INP_REUSEPORT 0x00000008 /* SO_REUSEPORT option is set */
/* 0x00000010 */
#define INP_REUSEADDR 0x00000020 /* SO_REUSEADDR option is set */
#define INP_BINDMULTI 0x00000040 /* IP_BINDMULTI option is set */
#define INP_RSS_BUCKET_SET 0x00000080 /* IP_RSS_LISTEN_BUCKET is set */
#define INP_RECVFLOWID 0x00000100 /* populate recv datagram with flow info */
#define INP_RECVRSSBUCKETID 0x00000200 /* populate recv datagram with bucket id */
@ -734,9 +733,6 @@ void in_pcbinfo_destroy(struct inpcbinfo *);
void in_pcbstorage_init(void *);
void in_pcbstorage_destroy(void *);
int in_pcbbind_check_bindmulti(const struct inpcb *ni,
const struct inpcb *oi);
void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *);
int in_pcballoc(struct socket *, struct inpcbinfo *);
int in_pcbbind(struct inpcb *, struct sockaddr_in *, struct ucred *);

View File

@ -1166,7 +1166,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
break;
}
/* FALLTHROUGH */
case IP_BINDMULTI:
#ifdef RSS
case IP_RSS_LISTEN_BUCKET:
#endif
@ -1262,9 +1261,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_RECVTOS:
OPTSET(INP_RECVTOS);
break;
case IP_BINDMULTI:
OPTSET2(INP_BINDMULTI, optval);
break;
case IP_RECVFLOWID:
OPTSET2(INP_RECVFLOWID, optval);
break;
@ -1416,7 +1412,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_DONTFRAG:
case IP_BINDANY:
case IP_RECVTOS:
case IP_BINDMULTI:
case IP_FLOWID:
case IP_FLOWTYPE:
case IP_RECVFLOWID:
@ -1509,9 +1504,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
optval = OPTBIT2(INP_RECVRSSBUCKETID);
break;
#endif
case IP_BINDMULTI:
optval = OPTBIT2(INP_BINDMULTI);
break;
case IP_VLAN_PCP:
if (OPTBIT2(INP_2PCP_SET)) {
optval = (inp->inp_flags2 &

View File

@ -484,7 +484,6 @@ struct route_in6 {
#define IPV6_BINDANY 64 /* bool: allow bind to any address */
#define IPV6_BINDMULTI 65 /* bool; allow multibind to same addr/port */
#define IPV6_RSS_LISTEN_BUCKET 66 /* int; set RSS listen bucket */
#define IPV6_FLOWID 67 /* int; flowid of given socket */
#define IPV6_FLOWTYPE 68 /* int; flowtype of given socket */

View File

@ -249,8 +249,7 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred)
t = in6_pcblookup_local(pcbinfo,
&sin6->sin6_addr, lport,
INPLOOKUP_WILDCARD, cred);
if (t &&
((inp->inp_flags2 & INP_BINDMULTI) == 0) &&
if (t != NULL &&
(so->so_type != SOCK_STREAM ||
IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
@ -261,15 +260,6 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred)
t->inp_cred->cr_uid))
return (EADDRINUSE);
/*
* If the socket is a BINDMULTI socket, then
* the credentials need to match and the
* original socket also has to have been bound
* with BINDMULTI.
*/
if (t && (! in_pcbbind_check_bindmulti(inp, t)))
return (EADDRINUSE);
#ifdef INET
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
@ -279,17 +269,13 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred)
t = in_pcblookup_local(pcbinfo,
sin.sin_addr, lport,
INPLOOKUP_WILDCARD, cred);
if (t &&
((inp->inp_flags2 & INP_BINDMULTI) == 0) &&
if (t != NULL &&
(so->so_type != SOCK_STREAM ||
ntohl(t->inp_faddr.s_addr) ==
INADDR_ANY) &&
(inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
if (t && (! in_pcbbind_check_bindmulti(inp, t)))
return (EADDRINUSE);
}
#endif
}

View File

@ -1752,7 +1752,6 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
case IPV6_AUTOFLOWLABEL:
case IPV6_ORIGDSTADDR:
case IPV6_BINDANY:
case IPV6_BINDMULTI:
#ifdef RSS
case IPV6_RSS_LISTEN_BUCKET:
#endif
@ -1933,10 +1932,6 @@ do { \
case IPV6_BINDANY:
OPTSET(INP_BINDANY);
break;
case IPV6_BINDMULTI:
OPTSET2(INP_BINDMULTI, optval);
break;
#ifdef RSS
case IPV6_RSS_LISTEN_BUCKET:
if ((optval >= 0) &&
@ -2195,7 +2190,6 @@ do { \
case IPV6_RSSBUCKETID:
case IPV6_RECVRSSBUCKETID:
#endif
case IPV6_BINDMULTI:
case IPV6_VLAN_PCP:
switch (optname) {
case IPV6_RECVHOPOPTS:
@ -2290,9 +2284,6 @@ do { \
break;
#endif
case IPV6_BINDMULTI:
optval = OPTBIT2(INP_BINDMULTI);
break;
case IPV6_VLAN_PCP:
if (OPTBIT2(INP_2PCP_SET)) {