Convert in_ifaddr_lock and in6_ifaddr_lock to rmlock.

Both are used to protect access to IP addresses lists and they can be
acquired for reading several times per packet. To reduce lock contention
it is better to use rmlock here.

Reviewed by:	gnn (previous version)
Obtained from:	Yandex LLC
Sponsored by:	Yandex LLC
Differential Revision:	https://reviews.freebsd.org/D3149
This commit is contained in:
Andrey V. Elsukov 2015-07-29 08:12:05 +00:00
parent a09a7146a7
commit cc0a3c8ca4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=286001
18 changed files with 142 additions and 90 deletions

View File

@ -36,9 +36,11 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/taskqueue.h>
@ -762,6 +764,7 @@ t4_clip_task(void *arg, int count)
static void
update_clip_table(struct adapter *sc, struct tom_data *td)
{
struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
struct in6_addr *lip, tlip;
struct clip_head stale;
@ -770,7 +773,7 @@ update_clip_table(struct adapter *sc, struct tom_data *td)
ASSERT_SYNCHRONIZED_OP(sc);
IN6_IFADDR_RLOCK();
IN6_IFADDR_RLOCK(&in6_ifa_tracker);
mtx_lock(&td->clip_table_lock);
if (gen == td->clip_gen)
@ -862,7 +865,7 @@ update_clip_table(struct adapter *sc, struct tom_data *td)
td->clip_gen = gen;
done:
mtx_unlock(&td->clip_table_lock);
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
}
static void

View File

@ -28,7 +28,9 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/rmlock.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <sys/syslog.h>

View File

@ -84,10 +84,12 @@
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
@ -530,6 +532,7 @@ stf_checkaddr4(sc, in, inifp)
struct in_addr *in;
struct ifnet *inifp; /* incoming interface */
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia4;
/*
@ -553,16 +556,16 @@ stf_checkaddr4(sc, in, inifp)
/*
* reject packets with broadcast
*/
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) {
if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
continue;
if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return -1;
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* perform ingress filter

View File

@ -42,12 +42,14 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/syslog.h>
@ -563,6 +565,7 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_log_per_second,
static void
in_arpinput(struct mbuf *m)
{
struct rm_priotracker in_ifa_tracker;
struct arphdr *ah;
struct ifnet *ifp = m->m_pkthdr.rcvif;
struct llentry *la = NULL;
@ -621,7 +624,7 @@ in_arpinput(struct mbuf *m)
* of the receive interface. (This will change slightly
* when we have clusters of interfaces).
*/
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) ||
ia->ia_ifp == ifp) &&
@ -629,7 +632,7 @@ in_arpinput(struct mbuf *m)
(ia->ia_ifa.ifa_carp == NULL ||
(*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) {
ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
}
@ -638,7 +641,7 @@ in_arpinput(struct mbuf *m)
ia->ia_ifp == ifp) &&
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
@ -657,13 +660,13 @@ in_arpinput(struct mbuf *m)
if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) {
ifa_ref(&ia->ia_ifa);
ifp = ia->ia_ifp;
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
}
}
#undef BDG_MEMBER_MATCHES_ARP
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* No match, use the first inet address on the receive interface
@ -684,13 +687,13 @@ in_arpinput(struct mbuf *m)
/*
* If bridging, fall back to using any inet address.
*/
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) {
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto drop;
}
ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
match:
if (!enaddr)
enaddr = (u_int8_t *)IF_LLADDR(ifp);

View File

@ -58,6 +58,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <sys/ktr.h>
#include <sys/condvar.h>
@ -1215,6 +1217,7 @@ static int
igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip,
/*const*/ struct igmp *igmp)
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_multi *inm;
@ -1237,7 +1240,7 @@ igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip,
* Replace 0.0.0.0 with the subnet address if told to do so.
*/
if (V_igmp_recvifkludge && in_nullhost(ip->ip_src)) {
IFP_TO_IA(ifp, ia);
IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL) {
ip->ip_src.s_addr = htonl(ia->ia_subnet);
ifa_free(&ia->ia_ifa);
@ -1323,6 +1326,7 @@ static int
igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip,
/*const*/ struct igmp *igmp)
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_multi *inm;
@ -1331,7 +1335,7 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip,
* leave requires knowing that we are the only member of a
* group.
*/
IFP_TO_IA(ifp, ia);
IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL && in_hosteq(ip->ip_src, IA_SIN(ia)->sin_addr)) {
ifa_free(&ia->ia_ifa);
return (0);
@ -3487,6 +3491,7 @@ igmp_intr(struct mbuf *m)
static struct mbuf *
igmp_v3_encap_report(struct ifnet *ifp, struct mbuf *m)
{
struct rm_priotracker in_ifa_tracker;
struct igmp_report *igmp;
struct ip *ip;
int hdrlen, igmpreclen;
@ -3535,7 +3540,7 @@ igmp_v3_encap_report(struct ifnet *ifp, struct mbuf *m)
if (m->m_flags & M_IGMP_LOOP) {
struct in_ifaddr *ia;
IFP_TO_IA(ifp, ia);
IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL) {
ip->ip_src = ia->ia_addr.sin_addr;
ifa_free(&ia->ia_ifa);

View File

@ -44,7 +44,9 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/proc.h>
#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/sx.h>
@ -93,17 +95,18 @@ SX_SYSINIT(in_control_sx, &in_control_sx, "in_control");
int
in_localaddr(struct in_addr in)
{
struct rm_priotracker in_ifa_tracker;
register u_long i = ntohl(in.s_addr);
register struct in_ifaddr *ia;
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (1);
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (0);
}
@ -114,16 +117,17 @@ in_localaddr(struct in_addr in)
int
in_localip(struct in_addr in)
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) {
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (1);
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (0);
}
@ -158,18 +162,19 @@ in_ifhasaddr(struct ifnet *ifp, struct in_addr in)
static struct in_ifaddr *
in_localip_more(struct in_ifaddr *ia)
{
struct rm_priotracker in_ifa_tracker;
in_addr_t in = IA_SIN(ia)->sin_addr.s_addr;
struct in_ifaddr *it;
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(it, INADDR_HASH(in), ia_hash) {
if (it != ia && IA_SIN(it)->sin_addr.s_addr == in) {
ifa_ref(&it->ia_ifa);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (it);
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (NULL);
}
@ -646,6 +651,7 @@ in_difaddr_ioctl(caddr_t data, struct ifnet *ifp, struct thread *td)
int
in_addprefix(struct in_ifaddr *target, int flags)
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
int error;
@ -659,7 +665,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
prefix.s_addr &= mask.s_addr;
}
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
/* Look for an existing address with the same prefix, mask, and fib */
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
@ -687,13 +693,13 @@ in_addprefix(struct in_ifaddr *target, int flags)
#ifdef RADIX_MPATH
if (ia->ia_addr.sin_addr.s_addr ==
target->ia_addr.sin_addr.s_addr) {
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (EEXIST);
} else
break;
#endif
if (V_nosameprefix) {
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (EEXIST);
} else {
int fibnum;
@ -701,12 +707,12 @@ in_addprefix(struct in_ifaddr *target, int flags)
fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS :
target->ia_ifp->if_fib;
rt_addrmsg(RTM_ADD, &target->ia_ifa, fibnum);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (0);
}
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* No-one seem to have this prefix route, so we try to insert it.
@ -725,6 +731,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
int
in_scrubprefix(struct in_ifaddr *target, u_int flags)
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
int error = 0;
@ -775,7 +782,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
return (0);
}
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
p = ia->ia_dstaddr.sin_addr;
@ -802,7 +809,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
*/
if ((ia->ia_flags & IFA_ROUTE) == 0) {
ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
error = rtinit(&(target->ia_ifa), (int)RTM_DELETE,
rtinitflags(target));
if (error == 0)
@ -821,7 +828,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
return (error);
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* remove all L2 entries on the given prefix

View File

@ -38,9 +38,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
@ -1748,6 +1750,7 @@ inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
int
inp_getmoptions(struct inpcb *inp, struct sockopt *sopt)
{
struct rm_priotracker in_ifa_tracker;
struct ip_mreqn mreqn;
struct ip_moptions *imo;
struct ifnet *ifp;
@ -1787,7 +1790,7 @@ inp_getmoptions(struct inpcb *inp, struct sockopt *sopt)
mreqn.imr_address = imo->imo_multicast_addr;
} else if (ifp != NULL) {
mreqn.imr_ifindex = ifp->if_index;
IFP_TO_IA(ifp, ia);
IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL) {
mreqn.imr_address =
IA_SIN(ia)->sin_addr;
@ -1878,6 +1881,7 @@ static struct ifnet *
inp_lookup_mcast_ifp(const struct inpcb *inp,
const struct sockaddr_in *gsin, const struct in_addr ina)
{
struct rm_priotracker in_ifa_tracker;
struct ifnet *ifp;
KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
@ -1902,7 +1906,7 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
struct ifnet *mifp;
mifp = NULL;
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
mifp = ia->ia_ifp;
if (!(mifp->if_flags & IFF_LOOPBACK) &&
@ -1911,7 +1915,7 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
break;
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
}
}

View File

@ -47,11 +47,13 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/callout.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/priv.h>
@ -992,6 +994,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp,
struct inpcb **oinpp, struct ucred *cred)
{
struct rm_priotracker in_ifa_tracker;
struct sockaddr_in *sin = (struct sockaddr_in *)nam;
struct in_ifaddr *ia;
struct inpcb *oinp;
@ -1028,20 +1031,20 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
* choose the broadcast address for that interface.
*/
if (faddr.s_addr == INADDR_ANY) {
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
faddr =
IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr;
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
if (cred != NULL &&
(error = prison_get_ip4(cred, &faddr)) != 0)
return (error);
} else if (faddr.s_addr == (u_long)INADDR_BROADCAST) {
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
if (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
IFF_BROADCAST)
faddr = satosin(&TAILQ_FIRST(
&V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
}
}
if (laddr.s_addr == INADDR_ANY) {
@ -1059,7 +1062,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
imo = inp->inp_moptions;
if (imo->imo_multicast_ifp != NULL) {
ifp = imo->imo_multicast_ifp;
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if ((ia->ia_ifp == ifp) &&
(cred == NULL ||
@ -1073,7 +1076,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
laddr = ia->ia_addr.sin_addr;
error = 0;
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
}
}
if (error)

View File

@ -119,15 +119,15 @@ VNET_DECLARE(u_long, in_ifaddrhmask); /* mask for hash table */
#define INADDR_HASH(x) \
(&V_in_ifaddrhashtbl[INADDR_HASHVAL(x) & V_in_ifaddrhmask])
extern struct rwlock in_ifaddr_lock;
extern struct rmlock in_ifaddr_lock;
#define IN_IFADDR_LOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_LOCKED)
#define IN_IFADDR_RLOCK() rw_rlock(&in_ifaddr_lock)
#define IN_IFADDR_RLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_RLOCKED)
#define IN_IFADDR_RUNLOCK() rw_runlock(&in_ifaddr_lock)
#define IN_IFADDR_WLOCK() rw_wlock(&in_ifaddr_lock)
#define IN_IFADDR_WLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_WLOCKED)
#define IN_IFADDR_WUNLOCK() rw_wunlock(&in_ifaddr_lock)
#define IN_IFADDR_LOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_LOCKED)
#define IN_IFADDR_RLOCK(t) rm_rlock(&in_ifaddr_lock, (t))
#define IN_IFADDR_RLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_RLOCKED)
#define IN_IFADDR_RUNLOCK(t) rm_runlock(&in_ifaddr_lock, (t))
#define IN_IFADDR_WLOCK() rm_wlock(&in_ifaddr_lock)
#define IN_IFADDR_WLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_WLOCKED)
#define IN_IFADDR_WUNLOCK() rm_wunlock(&in_ifaddr_lock)
/*
* Macro for finding the internet address structure (in_ifaddr)
@ -161,18 +161,19 @@ do { \
* Macro for finding the internet address structure (in_ifaddr) corresponding
* to a given interface (ifnet structure).
*/
#define IFP_TO_IA(ifp, ia) \
#define IFP_TO_IA(ifp, ia, t) \
/* struct ifnet *ifp; */ \
/* struct in_ifaddr *ia; */ \
/* struct rm_priotracker *t; */ \
do { \
IN_IFADDR_RLOCK(); \
IN_IFADDR_RLOCK((t)); \
for ((ia) = TAILQ_FIRST(&V_in_ifaddrhead); \
(ia) != NULL && (ia)->ia_ifp != (ifp); \
(ia) = TAILQ_NEXT((ia), ia_link)) \
continue; \
if ((ia) != NULL) \
ifa_ref(&(ia)->ia_ifa); \
IN_IFADDR_RUNLOCK(); \
IN_IFADDR_RUNLOCK((t)); \
} while (0)
/*

View File

@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
@ -647,6 +649,7 @@ icmp_input(struct mbuf **mp, int *offp, int proto)
static void
icmp_reflect(struct mbuf *m)
{
struct rm_priotracker in_ifa_tracker;
struct ip *ip = mtod(m, struct ip *);
struct ifaddr *ifa;
struct ifnet *ifp;
@ -672,15 +675,15 @@ icmp_reflect(struct mbuf *m)
* If the incoming packet was addressed directly to one of our
* own addresses, use dst as the src for the reply.
*/
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) {
if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) {
t = IA_SIN(ia)->sin_addr;
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
}
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* If the incoming packet was addressed to one of our broadcast

View File

@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <sys/rwlock.h>
#include <sys/sdt.h>
#include <sys/syslog.h>
@ -97,8 +98,8 @@ extern void ipreass_slowtimo(void);
extern void ipreass_destroy(void);
#endif
struct rwlock in_ifaddr_lock;
RW_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock");
struct rmlock in_ifaddr_lock;
RM_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock");
VNET_DEFINE(int, rsvp_on);

View File

@ -44,11 +44,13 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/rmlock.h>
#include <sys/sdt.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@ -120,6 +122,7 @@ int
ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
struct ip_moptions *imo, struct inpcb *inp)
{
struct rm_priotracker in_ifa_tracker;
struct ip *ip;
struct ifnet *ifp = NULL; /* keep compiler happy */
struct mbuf *m0;
@ -258,7 +261,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
* packets if the interface is specified.
*/
ifp = imo->imo_multicast_ifp;
IFP_TO_IA(ifp, ia);
IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia)
have_ia_ref = 1;
isbroadcast = 0; /* fool gcc */

View File

@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/rmlock.h>
#include <sys/rwlock.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
@ -724,6 +725,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
void
rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
{
struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct ifnet *ifp;
int err;
@ -731,12 +733,12 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
switch (cmd) {
case PRC_IFDOWN:
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (ia->ia_ifa.ifa_addr == sa
&& (ia->ia_flags & IFA_ROUTE)) {
ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* in_scrubprefix() kills the interface route.
*/
@ -753,21 +755,21 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
}
}
if (ia == NULL) /* If ia matched, already unlocked. */
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
break;
case PRC_IFUP:
IN_IFADDR_RLOCK();
IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (ia->ia_ifa.ifa_addr == sa)
break;
}
if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) {
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return;
}
ifa_ref(&ia->ia_ifa);
IN_IFADDR_RUNLOCK();
IN_IFADDR_RUNLOCK(&in_ifa_tracker);
flags = RTF_UP;
ifp = ia->ia_ifa.ifa_ifp;

View File

@ -80,6 +80,8 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <sys/syslog.h>
#include <net/if.h>
@ -1499,9 +1501,10 @@ in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
struct in6_ifaddr *
in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid)
{
struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
IN6_IFADDR_RLOCK();
IN6_IFADDR_RLOCK(&in6_ifa_tracker);
LIST_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) {
if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), addr)) {
if (zoneid != 0 &&
@ -1511,7 +1514,7 @@ in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid)
break;
}
}
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (ia);
}
@ -1649,20 +1652,21 @@ ip6_sprintf(char *ip6buf, const struct in6_addr *addr)
int
in6_localaddr(struct in6_addr *in6)
{
struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
return 1;
IN6_IFADDR_RLOCK();
IN6_IFADDR_RLOCK(&in6_ifa_tracker);
TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
&ia->ia_prefixmask.sin6_addr)) {
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return 1;
}
}
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0);
}
@ -1674,16 +1678,17 @@ in6_localaddr(struct in6_addr *in6)
int
in6_localip(struct in6_addr *in6)
{
struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
IN6_IFADDR_RLOCK();
IN6_IFADDR_RLOCK(&in6_ifa_tracker);
LIST_FOREACH(ia, IN6ADDR_HASH(in6), ia6_hash) {
if (IN6_ARE_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr)) {
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (1);
}
}
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0);
}
@ -1720,19 +1725,20 @@ in6_ifhasaddr(struct ifnet *ifp, struct in6_addr *addr)
int
in6_is_addr_deprecated(struct sockaddr_in6 *sa6)
{
struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
IN6_IFADDR_RLOCK();
IN6_IFADDR_RLOCK(&in6_ifa_tracker);
LIST_FOREACH(ia, IN6ADDR_HASH(&sa6->sin6_addr), ia6_hash) {
if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), &sa6->sin6_addr)) {
if (ia->ia6_flags & IN6_IFF_DEPRECATED) {
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (1); /* true */
}
break;
}
}
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0); /* false */
}

View File

@ -39,7 +39,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sockio.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/proc.h>
#include <sys/rmlock.h>
#include <sys/syslog.h>
#include <sys/md5.h>

View File

@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/rmlock.h>
#include <sys/sx.h>
#include <net/if.h>
@ -178,6 +179,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct inpcb *inp, struct route_in6 *ro, struct ucred *cred,
struct ifnet **ifpp, struct in6_addr *srcp)
{
struct rm_priotracker in6_ifa_tracker;
struct in6_addr dst, tmp;
struct ifnet *ifp = NULL, *oifp = NULL;
struct in6_ifaddr *ia = NULL, *ia_best = NULL;
@ -303,7 +305,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
return (error);
rule = 0;
IN6_IFADDR_RLOCK();
IN6_IFADDR_RLOCK(&in6_ifa_tracker);
TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
int new_scope = -1, new_matchlen = -1;
struct in6_addrpolicy *new_policy = NULL;
@ -501,7 +503,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
}
if ((ia = ia_best) == NULL) {
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
IP6STAT_INC(ip6s_sources_none);
return (EADDRNOTAVAIL);
}
@ -518,7 +520,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
tmp = ia->ia_addr.sin6_addr;
if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL &&
(inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) {
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
IP6STAT_INC(ip6s_sources_none);
return (EADDRNOTAVAIL);
}
@ -537,7 +539,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
IP6STAT_INC(ip6s_sources_otherscope[best_scope]);
if (IFA6_IS_DEPRECATED(ia))
IP6STAT_INC(ip6s_sources_deprecated[best_scope]);
IN6_IFADDR_RUNLOCK();
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0);
}

View File

@ -535,14 +535,14 @@ in6_addrhash(const struct in6_addr *in6)
return (fnv_32_buf(&x, sizeof(x), FNV1_32_INIT));
}
extern struct rwlock in6_ifaddr_lock;
#define IN6_IFADDR_LOCK_ASSERT( ) rw_assert(&in6_ifaddr_lock, RA_LOCKED)
#define IN6_IFADDR_RLOCK() rw_rlock(&in6_ifaddr_lock)
#define IN6_IFADDR_RLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_RLOCKED)
#define IN6_IFADDR_RUNLOCK() rw_runlock(&in6_ifaddr_lock)
#define IN6_IFADDR_WLOCK() rw_wlock(&in6_ifaddr_lock)
#define IN6_IFADDR_WLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_WLOCKED)
#define IN6_IFADDR_WUNLOCK() rw_wunlock(&in6_ifaddr_lock)
extern struct rmlock in6_ifaddr_lock;
#define IN6_IFADDR_LOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_LOCKED)
#define IN6_IFADDR_RLOCK(t) rm_rlock(&in6_ifaddr_lock, (t))
#define IN6_IFADDR_RLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_RLOCKED)
#define IN6_IFADDR_RUNLOCK(t) rm_runlock(&in6_ifaddr_lock, (t))
#define IN6_IFADDR_WLOCK() rm_wlock(&in6_ifaddr_lock)
#define IN6_IFADDR_WLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_WLOCKED)
#define IN6_IFADDR_WUNLOCK() rm_wunlock(&in6_ifaddr_lock)
#define in6_ifstat_inc(ifp, tag) \
do { \

View File

@ -82,6 +82,8 @@ __FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <sys/syslog.h>
#include <net/if.h>
@ -144,8 +146,8 @@ VNET_PCPUSTAT_SYSINIT(ip6stat);
VNET_PCPUSTAT_SYSUNINIT(ip6stat);
#endif /* VIMAGE */
struct rwlock in6_ifaddr_lock;
RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
struct rmlock in6_ifaddr_lock;
RM_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
static void ip6_init2(void *);
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);