aboutsummaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorRobert Watson <rwatson@FreeBSD.org>2009-06-21 19:30:33 +0000
committerRobert Watson <rwatson@FreeBSD.org>2009-06-21 19:30:33 +0000
commit1099f828b3c0026cd8d03616473dda5a0cc7429f (patch)
tree2cfffa4418c1fa90f1e9d094aa882742d0ababb9 /sys/net
parentc808c9632d567c38d12e8c9e59bf05abe60f5fe4 (diff)
downloadsrc-1099f828b3c0026cd8d03616473dda5a0cc7429f.tar.gz
src-1099f828b3c0026cd8d03616473dda5a0cc7429f.zip
Clean up common ifaddr management:
- Unify reference count and lock initialization in a single function, ifa_init(). - Move tear-down from a macro (IFAFREE) to a function ifa_free(). - Move reference count bump from a macro (IFAREF) to a function ifa_ref(). - Instead of using a u_int protected by a mutex to refcount(9) for reference count management. The ifa_mtx is now used for exactly one ioctl, and possibly should be removed. MFC after: 3 weeks
Notes
Notes: svn path=/head/; revision=194602
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c39
-rw-r--r--sys/net/if_var.h27
-rw-r--r--sys/net/route.c12
-rw-r--r--sys/net/rtsock.c4
4 files changed, 47 insertions, 35 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index c5e1a56f61c6..fa708e97b134 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -758,7 +758,7 @@ if_attach_internal(struct ifnet *ifp, int vmove)
socksize = roundup2(socksize, sizeof(long));
ifasize = sizeof(*ifa) + 2 * socksize;
ifa = malloc(ifasize, M_IFADDR, M_WAITOK | M_ZERO);
- IFA_LOCK_INIT(ifa);
+ ifa_init(ifa);
sdl = (struct sockaddr_dl *)(ifa + 1);
sdl->sdl_len = socksize;
sdl->sdl_family = AF_LINK;
@@ -775,7 +775,6 @@ if_attach_internal(struct ifnet *ifp, int vmove)
sdl->sdl_len = masklen;
while (namelen != 0)
sdl->sdl_data[--namelen] = 0xff;
- ifa->ifa_refcnt = 1;
TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
/* Reliably crash if used uninitialized. */
ifp->if_broadcastaddr = NULL;
@@ -896,7 +895,7 @@ if_purgeaddrs(struct ifnet *ifp)
}
#endif /* INET6 */
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
- IFAFREE(ifa);
+ ifa_free(ifa);
}
}
@@ -1013,7 +1012,7 @@ if_detach_internal(struct ifnet *ifp, int vmove)
if (!TAILQ_EMPTY(&ifp->if_addrhead)) {
ifa = TAILQ_FIRST(&ifp->if_addrhead);
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
- IFAFREE(ifa);
+ ifa_free(ifa);
}
}
@@ -1420,6 +1419,34 @@ if_rtdel(struct radix_node *rn, void *arg)
}
/*
+ * Reference count functions for ifaddrs.
+ */
+void
+ifa_init(struct ifaddr *ifa)
+{
+
+ mtx_init(&ifa->ifa_mtx, "ifaddr", NULL, MTX_DEF);
+ refcount_init(&ifa->ifa_refcnt, 1);
+}
+
+void
+ifa_ref(struct ifaddr *ifa)
+{
+
+ refcount_acquire(&ifa->ifa_refcnt);
+}
+
+void
+ifa_free(struct ifaddr *ifa)
+{
+
+ if (refcount_release(&ifa->ifa_refcnt)) {
+ mtx_destroy(&ifa->ifa_mtx);
+ free(ifa, M_IFADDR);
+ }
+}
+
+/*
* XXX: Because sockaddr_dl has deeper structure than the sockaddr
* structs used to represent other address families, it is necessary
* to perform a different comparison.
@@ -1711,10 +1738,10 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
return;
ifa = ifaof_ifpforaddr(dst, ifp);
if (ifa) {
- IFAREF(ifa); /* XXX */
+ ifa_ref(ifa); /* XXX */
oifa = rt->rt_ifa;
rt->rt_ifa = ifa;
- IFAFREE(oifa);
+ ifa_free(oifa);
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
ifa->ifa_rtrequest(cmd, rt, info);
}
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 556aace8fae1..cbd274afc9fb 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -706,11 +706,14 @@ struct ifaddr {
/* for compatibility with other BSDs */
#define ifa_list ifa_link
-#define IFA_LOCK_INIT(ifa) \
- mtx_init(&(ifa)->ifa_mtx, "ifaddr", NULL, MTX_DEF)
+#ifdef _KERNEL
#define IFA_LOCK(ifa) mtx_lock(&(ifa)->ifa_mtx)
#define IFA_UNLOCK(ifa) mtx_unlock(&(ifa)->ifa_mtx)
-#define IFA_DESTROY(ifa) mtx_destroy(&(ifa)->ifa_mtx)
+
+void ifa_free(struct ifaddr *ifa);
+void ifa_init(struct ifaddr *ifa);
+void ifa_ref(struct ifaddr *ifa);
+#endif
/*
* The prefix structure contains information about one prefix
@@ -741,24 +744,6 @@ struct ifmultiaddr {
};
#ifdef _KERNEL
-#define IFAFREE(ifa) \
- do { \
- IFA_LOCK(ifa); \
- KASSERT((ifa)->ifa_refcnt > 0, \
- ("ifa %p !(ifa_refcnt > 0)", ifa)); \
- if (--(ifa)->ifa_refcnt == 0) { \
- IFA_DESTROY(ifa); \
- free(ifa, M_IFADDR); \
- } else \
- IFA_UNLOCK(ifa); \
- } while (0)
-
-#define IFAREF(ifa) \
- do { \
- IFA_LOCK(ifa); \
- ++(ifa)->ifa_refcnt; \
- IFA_UNLOCK(ifa); \
- } while (0)
extern struct rwlock ifnet_lock;
#define IFNET_LOCK_INIT() \
diff --git a/sys/net/route.c b/sys/net/route.c
index aaa38d76c6b0..1705e98e0193 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -474,7 +474,7 @@ rtfree(struct rtentry *rt)
* e.g other routes and ifaddrs.
*/
if (rt->rt_ifa)
- IFAFREE(rt->rt_ifa);
+ ifa_free(rt->rt_ifa);
/*
* The key is separatly alloc'd so free it (see rt_setgate()).
* This also frees the gateway, as they are always malloc'd
@@ -1126,7 +1126,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
* This moved from below so that rnh->rnh_addaddr() can
* examine the ifa and ifa->ifa_ifp if it so desires.
*/
- IFAREF(ifa);
+ ifa_ref(ifa);
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
rt->rt_rmx.rmx_weight = 1;
@@ -1136,7 +1136,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
if (rn_mpath_capable(rnh) &&
rt_mpath_conflict(rnh, rt, netmask)) {
if (rt->rt_ifa) {
- IFAFREE(rt->rt_ifa);
+ ifa_free(rt->rt_ifa);
}
Free(rt_key(rt));
RT_LOCK_DESTROY(rt);
@@ -1153,7 +1153,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
*/
if (rn == NULL) {
if (rt->rt_ifa)
- IFAFREE(rt->rt_ifa);
+ ifa_free(rt->rt_ifa);
Free(rt_key(rt));
RT_LOCK_DESTROY(rt);
uma_zfree(V_rtzone, rt);
@@ -1409,8 +1409,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
*/
if (memcmp(rt->rt_ifa->ifa_addr,
ifa->ifa_addr, ifa->ifa_addr->sa_len)) {
- IFAFREE(rt->rt_ifa);
- IFAREF(ifa);
+ ifa_free(rt->rt_ifa);
+ ifa_ref(ifa);
rt->rt_ifp = ifa->ifa_ifp;
rt->rt_ifa = ifa;
}
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 56bb3a7bf0c2..ab3855721587 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -694,7 +694,7 @@ route_output(struct mbuf *m, struct socket *so)
rt->rt_ifa->ifa_rtrequest != NULL) {
rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
&info);
- IFAFREE(rt->rt_ifa);
+ ifa_free(rt->rt_ifa);
}
if (info.rti_info[RTAX_GATEWAY] != NULL) {
RT_UNLOCK(rt);
@@ -712,7 +712,7 @@ route_output(struct mbuf *m, struct socket *so)
}
if (info.rti_ifa != NULL &&
info.rti_ifa != rt->rt_ifa) {
- IFAREF(info.rti_ifa);
+ ifa_ref(info.rti_ifa);
rt->rt_ifa = info.rti_ifa;
rt->rt_ifp = info.rti_ifp;
}