summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-21 19:30:33 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-21 19:30:33 +0000
commit1f7e54e8c51edb13935d195e0c1f2ec68c672794 (patch)
tree2cfffa4418c1fa90f1e9d094aa882742d0ababb9 /sys/net/if.c
parent2fc79768f33d575d200ae1482dc23207f9d93703 (diff)
downloadFreeBSD-src-1f7e54e8c51edb13935d195e0c1f2ec68c672794.zip
FreeBSD-src-1f7e54e8c51edb13935d195e0c1f2ec68c672794.tar.gz
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
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index c5e1a56..fa708e9 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);
}
OpenPOWER on IntegriCloud