svn commit: r268562 - head/sys/netinet6
Adrian Chadd
adrian at FreeBSD.org
Sat Jul 12 05:46:34 UTC 2014
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;
More information about the svn-src-all
mailing list