From owner-svn-src-all@FreeBSD.ORG Sat Jul 12 05:46:34 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 19B7D177; Sat, 12 Jul 2014 05:46:34 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 072C62107; Sat, 12 Jul 2014 05:46:34 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6C5kXIQ049855; Sat, 12 Jul 2014 05:46:33 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6C5kX66049852; Sat, 12 Jul 2014 05:46:33 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201407120546.s6C5kX66049852@svn.freebsd.org> From: Adrian Chadd Date: Sat, 12 Jul 2014 05:46:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r268562 - head/sys/netinet6 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 12 Jul 2014 05:46:34 -0000 Author: adrian Date: Sat Jul 12 05:46:33 2014 New Revision: 268562 URL: http://svnweb.freebsd.org/changeset/base/268562 Log: Add IPv6 flowid, bindmulti and RSS awareness. Modified: head/sys/netinet6/in6_pcb.c head/sys/netinet6/ip6_output.c Modified: head/sys/netinet6/in6_pcb.c ============================================================================== --- head/sys/netinet6/in6_pcb.c Sat Jul 12 05:45:53 2014 (r268561) +++ head/sys/netinet6/in6_pcb.c Sat Jul 12 05:46:33 2014 (r268562) @@ -202,6 +202,7 @@ in6_pcbbind(register struct inpcb *inp, &sin6->sin6_addr, lport, INPLOOKUP_WILDCARD, cred); if (t && + ((inp->inp_flags2 & INP_BINDMULTI) == 0) && ((t->inp_flags & INP_TIMEWAIT) == 0) && (so->so_type != SOCK_STREAM || IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) && @@ -211,6 +212,16 @@ in6_pcbbind(register struct inpcb *inp, (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); + #ifdef INET if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { @@ -221,6 +232,7 @@ in6_pcbbind(register struct inpcb *inp, sin.sin_addr, lport, INPLOOKUP_WILDCARD, cred); if (t && + ((inp->inp_flags2 & INP_BINDMULTI) == 0) && ((t->inp_flags & INP_TIMEWAIT) == 0) && (so->so_type != SOCK_STREAM || @@ -229,6 +241,9 @@ in6_pcbbind(register struct inpcb *inp, (inp->inp_cred->cr_uid != t->inp_cred->cr_uid)) return (EADDRINUSE); + + if (t && (! in_pcbbind_check_bindmulti(inp, t))) + return (EADDRINUSE); } #endif } @@ -891,6 +906,71 @@ in6_pcblookup_group(struct inpcbinfo *pc } /* + * Then look for a wildcard match in the pcbgroup. + */ + if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { + struct inpcb *local_wild = NULL, *local_exact = NULL; + struct inpcb *jail_wild = NULL; + int injail; + + /* + * Order of socket selection - we always prefer jails. + * 1. jailed, non-wild. + * 2. jailed, wild. + * 3. non-jailed, non-wild. + * 4. non-jailed, wild. + */ + head = &pcbgroup->ipg_hashbase[ + INP_PCBHASH(INADDR_ANY, lport, 0, pcbgroup->ipg_hashmask)]; + LIST_FOREACH(inp, head, inp_pcbgrouphash) { + /* XXX inp locking */ + if ((inp->inp_vflag & INP_IPV6) == 0) + continue; + + if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) || + inp->inp_lport != lport) { + continue; + } + + /* XXX inp locking */ + if (faith && (inp->inp_flags & INP_FAITH) == 0) + continue; + + injail = prison_flag(inp->inp_cred, PR_IP6); + if (injail) { + if (prison_check_ip6(inp->inp_cred, + laddr) != 0) + continue; + } else { + if (local_exact != NULL) + continue; + } + + if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr)) { + if (injail) + goto found; + else + local_exact = inp; + } else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { + if (injail) + jail_wild = inp; + else + local_wild = inp; + } + } /* LIST_FOREACH */ + + inp = jail_wild; + if (inp == NULL) + inp = jail_wild; + if (inp == NULL) + inp = local_exact; + if (inp == NULL) + inp = local_wild; + if (inp != NULL) + goto found; + } + + /* * Then look for a wildcard match, if requested. */ if ((lookupflags & INPLOOKUP_WILDCARD) != 0) { Modified: head/sys/netinet6/ip6_output.c ============================================================================== --- head/sys/netinet6/ip6_output.c Sat Jul 12 05:45:53 2014 (r268561) +++ head/sys/netinet6/ip6_output.c Sat Jul 12 05:46:33 2014 (r268562) @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ipsec.h" #include "opt_sctp.h" #include "opt_route.h" +#include "opt_rss.h" #include #include @@ -102,6 +103,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef IPSEC #include @@ -1287,6 +1289,10 @@ ip6_ctloutput(struct socket *so, struct int level, op, optname; int optlen; struct thread *td; +#ifdef RSS + uint32_t rss_bucket; + int retval; +#endif level = sopt->sopt_level; op = sopt->sopt_dir; @@ -1390,6 +1396,10 @@ ip6_ctloutput(struct socket *so, struct case IPV6_V6ONLY: case IPV6_AUTOFLOWLABEL: case IPV6_BINDANY: + case IPV6_BINDMULTI: +#ifdef RSS + case IPV6_RSS_LISTEN_BUCKET: +#endif if (optname == IPV6_BINDANY && td != NULL) { error = priv_check(td, PRIV_NETINET_BINDANY); @@ -1439,6 +1449,16 @@ do { \ } while (/*CONSTCOND*/ 0) #define OPTBIT(bit) (in6p->inp_flags & (bit) ? 1 : 0) +#define OPTSET2(bit, val) do { \ + INP_WLOCK(in6p); \ + if (val) \ + in6p->inp_flags2 |= bit; \ + else \ + in6p->inp_flags2 &= ~bit; \ + INP_WUNLOCK(in6p); \ +} while (0) +#define OPTBIT2(bit) (in6p->inp_flags2 & (bit) ? 1 : 0) + case IPV6_RECVPKTINFO: /* cannot mix with RFC2292 */ if (OPTBIT(IN6P_RFC2292)) { @@ -1557,6 +1577,21 @@ 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) && + (optval < rss_getnumbuckets())) { + in6p->inp_rss_listen_bucket = optval; + OPTSET2(INP_RSS_BUCKET_SET, 1); + } else { + error = EINVAL; + } + break; +#endif } break; @@ -1772,6 +1807,11 @@ do { \ case IPV6_RECVTCLASS: case IPV6_AUTOFLOWLABEL: case IPV6_BINDANY: + case IPV6_FLOWID: + case IPV6_FLOWTYPE: +#ifdef RSS + case IPV6_RSSBUCKETID: +#endif switch (optname) { case IPV6_RECVHOPOPTS: @@ -1837,6 +1877,31 @@ do { \ case IPV6_BINDANY: optval = OPTBIT(INP_BINDANY); break; + + case IPV6_FLOWID: + optval = in6p->inp_flowid; + break; + + case IPV6_FLOWTYPE: + optval = in6p->inp_flowtype; + break; +#ifdef RSS + case IPV6_RSSBUCKETID: + retval = + rss_hash2bucket(in6p->inp_flowid, + in6p->inp_flowtype, + &rss_bucket); + if (retval == 0) + optval = rss_bucket; + else + error = EINVAL; + break; +#endif + + case IPV6_BINDMULTI: + optval = OPTBIT2(INP_BINDMULTI); + break; + } if (error) break;