Date: Sat, 12 Jul 2014 05:46:33 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r268562 - head/sys/netinet6 Message-ID: <201407120546.s6C5kX66049852@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <sys/param.h> #include <sys/kernel.h> @@ -102,6 +103,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/in_pcb.h> #include <netinet/tcp_var.h> #include <netinet6/nd6.h> +#include <netinet/in_rss.h> #ifdef IPSEC #include <netipsec/ipsec.h> @@ -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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407120546.s6C5kX66049852>