svn commit: r245199 - head/sys/netinet6

Andrey V. Elsukov ae at FreeBSD.org
Wed Jan 9 00:36:06 UTC 2013


Author: ae
Date: Wed Jan  9 00:36:06 2013
New Revision: 245199
URL: http://svnweb.freebsd.org/changeset/base/245199

Log:
  The in6_setscope() function determines the scope zone id of an address
  and embeds it into address. Inside the kernel we keep addresses with
  embedded zone id only for two scopes: link-local and interface-local.
  
  For other scopes this function is nop in most cases. To reduce an
  overhead of locking, first check that address is capable for embedding.
  Also, handle the loopback address before acquire the lock.
  
  Sponsored by:	Yandex LLC
  MFC after:	1 week

Modified:
  head/sys/netinet6/scope6.c

Modified: head/sys/netinet6/scope6.c
==============================================================================
--- head/sys/netinet6/scope6.c	Wed Jan  9 00:22:53 2013	(r245198)
+++ head/sys/netinet6/scope6.c	Wed Jan  9 00:36:06 2013	(r245199)
@@ -420,33 +420,34 @@ in6_setscope(struct in6_addr *in6, struc
 	u_int32_t zoneid = 0;
 	struct scope6_id *sid;
 
-	IF_AFDATA_RLOCK(ifp);
-
-	sid = SID(ifp);
-
-#ifdef DIAGNOSTIC
-	if (sid == NULL) { /* should not happen */
-		panic("in6_setscope: scope array is NULL");
-		/* NOTREACHED */
-	}
-#endif
-
 	/*
 	 * special case: the loopback address can only belong to a loopback
 	 * interface.
 	 */
 	if (IN6_IS_ADDR_LOOPBACK(in6)) {
 		if (!(ifp->if_flags & IFF_LOOPBACK)) {
-			IF_AFDATA_RUNLOCK(ifp);
 			return (EINVAL);
 		} else {
 			if (ret_id != NULL)
 				*ret_id = 0; /* there's no ambiguity */
-			IF_AFDATA_RUNLOCK(ifp);
 			return (0);
 		}
 	}
 
+	if (ret_id == NULL && !IN6_IS_SCOPE_EMBED(in6))
+		return (0);
+
+	IF_AFDATA_RLOCK(ifp);
+
+	sid = SID(ifp);
+
+#ifdef DIAGNOSTIC
+	if (sid == NULL) { /* should not happen */
+		panic("in6_setscope: scope array is NULL");
+		/* NOTREACHED */
+	}
+#endif
+
 	scope = in6_addrscope(in6);
 	switch (scope) {
 	case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */
@@ -474,7 +475,7 @@ in6_setscope(struct in6_addr *in6, struc
 	if (ret_id != NULL)
 		*ret_id = zoneid;
 
-	if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6))
+	if (IN6_IS_SCOPE_EMBED(in6))
 		in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
 
 	return (0);


More information about the svn-src-all mailing list