summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2013-01-10 00:10:24 +0000
committerae <ae@FreeBSD.org>2013-01-10 00:10:24 +0000
commit0bad7195e9475f33750e9d06c45763523c287188 (patch)
treeec1e9f997c536ee747062ea14752fe4b0276fc3e /sys/netinet6
parent02d4d8c423473847e67beaab4c1143cc7b2105dd (diff)
downloadFreeBSD-src-0bad7195e9475f33750e9d06c45763523c287188.zip
FreeBSD-src-0bad7195e9475f33750e9d06c45763523c287188.tar.gz
Simplify in6_setscope() function to get better performance.
Currently we use interface indeces as zone IDs for link-local and interface-local scopes, and since we don't have any tool to configure zone IDs, there is no need to acquire the afdata lock several times per packet only to read if_index value. So, now in6_setscope reads zone IDs for interface-local, link-local and global scopes without a lock. Sponsored by: Yandex LLC MFC after: 2 weeks
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/scope6.c63
1 files changed, 17 insertions, 46 deletions
diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c
index 79040c2..b6479a1 100644
--- a/sys/netinet6/scope6.c
+++ b/sys/netinet6/scope6.c
@@ -420,59 +420,30 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
* interface.
*/
if (IN6_IS_ADDR_LOOPBACK(in6)) {
- if (!(ifp->if_flags & IFF_LOOPBACK)) {
+ if (!(ifp->if_flags & IFF_LOOPBACK))
return (EINVAL);
- } else {
- if (ret_id != NULL)
- *ret_id = 0; /* there's no ambiguity */
- return (0);
+ } else {
+ scope = in6_addrscope(in6);
+ if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL ||
+ scope == IPV6_ADDR_SCOPE_LINKLOCAL) {
+ /*
+ * Currently we use interface indeces as the
+ * zone IDs for interface-local and link-local
+ * scopes.
+ */
+ zoneid = ifp->if_index;
+ in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
+ } else if (scope != IPV6_ADDR_SCOPE_GLOBAL) {
+ IF_AFDATA_RLOCK(ifp);
+ sid = SID(ifp);
+ zoneid = sid->s6id_list[scope];
+ IF_AFDATA_RUNLOCK(ifp);
}
}
- 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 */
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_LINKLOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_SITELOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_ORGLOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL];
- break;
-
- default:
- zoneid = 0; /* XXX: treat as global. */
- break;
- }
- IF_AFDATA_RUNLOCK(ifp);
-
if (ret_id != NULL)
*ret_id = zoneid;
- if (IN6_IS_SCOPE_EMBED(in6))
- in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
-
return (0);
}
OpenPOWER on IntegriCloud