aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c107
1 files changed, 68 insertions, 39 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 3a8f8f0098cd..c04f2ad9d387 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -41,6 +41,7 @@
#include <sys/malloc.h>
#include <sys/sbuf.h>
#include <sys/bus.h>
+#include <sys/epoch.h>
#include <sys/mbuf.h>
#include <sys/systm.h>
#include <sys/priv.h>
@@ -560,8 +561,8 @@ if_alloc(u_char type)
TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp);
ifp->if_afdata_initialized = 0;
IF_AFDATA_LOCK_INIT(ifp);
- TAILQ_INIT(&ifp->if_addrhead);
- TAILQ_INIT(&ifp->if_multiaddrs);
+ CK_STAILQ_INIT(&ifp->if_addrhead);
+ CK_STAILQ_INIT(&ifp->if_multiaddrs);
TAILQ_INIT(&ifp->if_groups);
#ifdef MAC
mac_ifnet_init(ifp);
@@ -830,7 +831,7 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
sdl->sdl_len = masklen;
while (namelen != 0)
sdl->sdl_data[--namelen] = 0xff;
- TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
+ CK_STAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
/* Reliably crash if used uninitialized. */
ifp->if_broadcastaddr = NULL;
@@ -872,7 +873,7 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
* of the interface.
*/
for (ifa = ifp->if_addr; ifa != NULL;
- ifa = TAILQ_NEXT(ifa, ifa_link)) {
+ ifa = CK_STAILQ_NEXT(ifa, ifa_link)) {
if (ifa->ifa_addr->sa_family == AF_LINK) {
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
sdl->sdl_index = ifp->if_index;
@@ -957,7 +958,7 @@ if_purgeaddrs(struct ifnet *ifp)
struct ifaddr *ifa, *next;
/* XXX cannot hold IF_ADDR_WLOCK over called functions. */
- TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
+ CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
if (ifa->ifa_addr->sa_family == AF_LINK)
continue;
#ifdef INET
@@ -982,7 +983,7 @@ if_purgeaddrs(struct ifnet *ifp)
}
#endif /* INET6 */
IF_ADDR_WLOCK(ifp);
- TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
+ CK_STAILQ_REMOVE(&ifp->if_addrhead, ifa, ifaddr, ifa_link);
IF_ADDR_WUNLOCK(ifp);
ifa_free(ifa);
}
@@ -998,9 +999,9 @@ if_purgemaddrs(struct ifnet *ifp)
struct ifmultiaddr *ifma;
IF_ADDR_WLOCK(ifp);
- while (!TAILQ_EMPTY(&ifp->if_multiaddrs)) {
- ifma = TAILQ_FIRST(&ifp->if_multiaddrs);
- TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
+ while (!CK_STAILQ_EMPTY(&ifp->if_multiaddrs)) {
+ ifma = CK_STAILQ_FIRST(&ifp->if_multiaddrs);
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link);
if_delmulti_locked(ifp, ifma, 1);
}
IF_ADDR_WUNLOCK(ifp);
@@ -1172,9 +1173,9 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
/* We can now free link ifaddr. */
IF_ADDR_WLOCK(ifp);
- if (!TAILQ_EMPTY(&ifp->if_addrhead)) {
- ifa = TAILQ_FIRST(&ifp->if_addrhead);
- TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
+ if (!CK_STAILQ_EMPTY(&ifp->if_addrhead)) {
+ ifa = CK_STAILQ_FIRST(&ifp->if_addrhead);
+ CK_STAILQ_REMOVE(&ifp->if_addrhead, ifa, ifaddr, ifa_link);
IF_ADDR_WUNLOCK(ifp);
ifa_free(ifa);
} else
@@ -1807,19 +1808,28 @@ ifa_ref(struct ifaddr *ifa)
refcount_acquire(&ifa->ifa_refcnt);
}
+static void
+ifa_destroy(epoch_context_t ctx)
+{
+ struct ifaddr *ifa;
+
+ ifa = __containerof(ctx, struct ifaddr, ifa_epoch_ctx);
+ counter_u64_free(ifa->ifa_opackets);
+ counter_u64_free(ifa->ifa_ipackets);
+ counter_u64_free(ifa->ifa_obytes);
+ counter_u64_free(ifa->ifa_ibytes);
+ free(ifa, M_IFADDR);
+}
+
void
ifa_free(struct ifaddr *ifa)
{
- if (refcount_release(&ifa->ifa_refcnt)) {
- counter_u64_free(ifa->ifa_opackets);
- counter_u64_free(ifa->ifa_ipackets);
- counter_u64_free(ifa->ifa_obytes);
- counter_u64_free(ifa->ifa_ibytes);
- free(ifa, M_IFADDR);
- }
+ if (refcount_release(&ifa->ifa_refcnt))
+ epoch_call(net_epoch_preempt, &ifa->ifa_epoch_ctx, ifa_destroy);
}
+
static int
ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
struct sockaddr *ia)
@@ -1896,7 +1906,7 @@ ifa_ifwithaddr_internal(const struct sockaddr *addr, int getref)
IFNET_RLOCK_NOSLEEP();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
IF_ADDR_RLOCK(ifp);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
if (sa_equal(addr, ifa->ifa_addr)) {
@@ -1953,7 +1963,7 @@ ifa_ifwithbroadaddr(const struct sockaddr *addr, int fibnum)
if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum))
continue;
IF_ADDR_RLOCK(ifp);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
if ((ifp->if_flags & IFF_BROADCAST) &&
@@ -1990,7 +2000,7 @@ ifa_ifwithdstaddr(const struct sockaddr *addr, int fibnum)
if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum))
continue;
IF_ADDR_RLOCK(ifp);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
if (ifa->ifa_dstaddr != NULL &&
@@ -2042,7 +2052,7 @@ ifa_ifwithnet(const struct sockaddr *addr, int ignore_ptp, int fibnum)
if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum))
continue;
IF_ADDR_RLOCK(ifp);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
const char *cp, *cp2, *cp3;
if (ifa->ifa_addr->sa_family != af)
@@ -2127,7 +2137,7 @@ ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
if (af >= AF_MAX)
return (NULL);
IF_ADDR_RLOCK(ifp);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != af)
continue;
if (ifa_maybe == NULL)
@@ -2249,7 +2259,7 @@ if_unroute(struct ifnet *ifp, int flag, int fam)
ifp->if_flags &= ~flag;
getmicrotime(&ifp->if_lastchange);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
ifp->if_qflush(ifp);
@@ -2272,7 +2282,7 @@ if_route(struct ifnet *ifp, int flag, int fam)
ifp->if_flags |= flag;
getmicrotime(&ifp->if_lastchange);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
pfctlinput(PRC_IFUP, ifa->ifa_addr);
if (ifp->if_carp)
@@ -3264,7 +3274,7 @@ again:
addrs = 0;
IF_ADDR_RLOCK(ifp);
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa = ifa->ifa_addr;
if (prison_if(curthread->td_ucred, sa) != 0)
@@ -3336,7 +3346,7 @@ if_findmulti(struct ifnet *ifp, const struct sockaddr *sa)
IF_ADDR_LOCK_ASSERT(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (sa->sa_family == AF_LINK) {
if (sa_dl_equal(ifma->ifma_addr, sa))
break;
@@ -3406,8 +3416,8 @@ if_allocmulti(struct ifnet *ifp, struct sockaddr *sa, struct sockaddr *llsa,
#ifdef MCAST_VERBOSE
extern void kdb_backtrace(void);
#endif
-void
-if_freemulti(struct ifmultiaddr *ifma)
+static void
+if_freemulti_internal(struct ifmultiaddr *ifma)
{
KASSERT(ifma->ifma_refcount == 0, ("if_freemulti: refcount %d",
@@ -3423,6 +3433,25 @@ if_freemulti(struct ifmultiaddr *ifma)
free(ifma, M_IFMADDR);
}
+static void
+if_destroymulti(epoch_context_t ctx)
+{
+ struct ifmultiaddr *ifma;
+
+ ifma = __containerof(ctx, struct ifmultiaddr, ifma_epoch_ctx);
+ if_freemulti_internal(ifma);
+}
+
+void
+if_freemulti(struct ifmultiaddr *ifma)
+{
+ KASSERT(ifma->ifma_refcount == 0, ("if_freemulti_epoch: refcount %d",
+ ifma->ifma_refcount));
+
+ epoch_call(net_epoch_preempt, &ifma->ifma_epoch_ctx, if_destroymulti);
+}
+
+
/*
* Register an additional multicast address with a network interface.
*
@@ -3516,7 +3545,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
error = ENOMEM;
goto free_llsa_out;
}
- TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma,
+ CK_STAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma,
ifma_link);
} else
ll_ifma->ifma_refcount++;
@@ -3528,7 +3557,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
* referenced link layer address. Add the primary address to the
* ifnet address list.
*/
- TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
+ CK_STAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
if (retifma != NULL)
*retifma = ifma;
@@ -3620,7 +3649,7 @@ if_delallmulti(struct ifnet *ifp)
struct ifmultiaddr *next;
IF_ADDR_WLOCK(ifp);
- TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
+ CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
if_delmulti_locked(ifp, ifma, 0);
IF_ADDR_WUNLOCK(ifp);
}
@@ -3731,7 +3760,7 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
return 0;
if (ifp != NULL && detaching == 0)
- TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link);
/*
* If this ifma is a network-layer ifma, a link-layer ifma may
@@ -3745,7 +3774,7 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
ll_ifma->ifma_ifp = NULL; /* XXX */
if (--ll_ifma->ifma_refcount == 0) {
if (ifp != NULL) {
- TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma,
+ CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr,
ifma_link);
}
if_freemulti(ll_ifma);
@@ -3755,7 +3784,7 @@ if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching)
if (ifp) {
struct ifmultiaddr *ifmatmp;
- TAILQ_FOREACH(ifmatmp, &ifp->if_multiaddrs, ifma_link)
+ CK_STAILQ_FOREACH(ifmatmp, &ifp->if_multiaddrs, ifma_link)
MPASS(ifma != ifmatmp);
}
#endif
@@ -4284,7 +4313,7 @@ if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max)
uint8_t *lmta = (uint8_t *)mta;
int mcnt = 0;
- TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
+ CK_STAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
@@ -4319,7 +4348,7 @@ if_multiaddr_count(if_t ifp, int max)
count = 0;
if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
+ CK_STAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
count++;
@@ -4337,7 +4366,7 @@ if_multi_apply(struct ifnet *ifp, int (*filter)(void *, struct ifmultiaddr *, in
int cnt = 0;
if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
+ CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
cnt += filter(arg, ifma, cnt);
if_maddr_runlock(ifp);
return (cnt);