1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-24 16:10:11 +00:00

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
This commit is contained in:
Andrey V. Elsukov 2013-01-10 00:10:24 +00:00
parent c9bfe3d179
commit 3ea87cb57f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=245244

View File

@ -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);
}