diff --git a/sys/net/pfil.c b/sys/net/pfil.c index 01bd688..af941a4 100644 --- a/sys/net/pfil.c +++ b/sys/net/pfil.c @@ -51,6 +51,8 @@ static struct mtx pfil_global_lock; MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", MTX_DEF); +#define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock) +#define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock) static int pfil_list_add(pfil_list_t *, struct packet_filter_hook *, int); @@ -62,7 +64,6 @@ LIST_HEAD(pfilheadhead, pfil_head); VNET_DEFINE(struct pfilheadhead, pfil_head_list); #define V_pfil_head_list VNET(pfil_head_list) VNET_DEFINE(struct rmlock, pfil_lock); -#define V_pfil_lock VNET(pfil_lock) /* * pfil_run_hooks() runs the specified packet filter hooks. @@ -76,7 +77,7 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp, struct mbuf *m = *mp; int rv = 0; - PFIL_RLOCK(ph, &rmpt); + PFIL_HEAD_RLOCK(ph, &rmpt); KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0")); for (pfh = pfil_hook_get(dir, ph); pfh != NULL; pfh = TAILQ_NEXT(pfh, pfil_link)) { @@ -87,73 +88,12 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp, break; } } - PFIL_RUNLOCK(ph, &rmpt); + PFIL_HEAD_RUNLOCK(ph, &rmpt); *mp = m; return (rv); } /* - * pfil_try_rlock() acquires rm reader lock for specified head - * if this is immediately possible, - */ -int -pfil_try_rlock(struct pfil_head *ph, struct rm_priotracker *tracker) -{ - - return (PFIL_TRY_RLOCK(ph, tracker)); -} - -/* - * pfil_rlock() acquires rm reader lock for specified head. - */ -void -pfil_rlock(struct pfil_head *ph, struct rm_priotracker *tracker) -{ - - PFIL_RLOCK(ph, tracker); -} - -/* - * pfil_runlock() releases reader lock for specified head. - */ -void -pfil_runlock(struct pfil_head *ph, struct rm_priotracker *tracker) -{ - - PFIL_RUNLOCK(ph, tracker); -} - -/* - * pfil_wlock() acquires writer lock for specified head. - */ -void -pfil_wlock(struct pfil_head *ph) -{ - - PFIL_WLOCK(ph); -} - -/* - * pfil_wunlock() releases writer lock for specified head. - */ -void -pfil_wunlock(struct pfil_head *ph) -{ - - PFIL_WUNLOCK(ph); -} - -/* - * pfil_wowned() returns a non-zero value if the current thread owns - * an exclusive lock. - */ -int -pfil_wowned(struct pfil_head *ph) -{ - - return (PFIL_WOWNED(ph)); -} -/* * pfil_head_register() registers a pfil_head with the packet filter hook * mechanism. */ @@ -170,7 +110,7 @@ pfil_head_register(struct pfil_head *ph) return (EEXIST); } } - PFIL_LOCK_INIT(ph); + PFIL_HEAD_LOCK_INIT(ph); ph->ph_nhooks = 0; TAILQ_INIT(&ph->ph_in); TAILQ_INIT(&ph->ph_out); @@ -188,7 +128,7 @@ int pfil_head_unregister(struct pfil_head *ph) { struct packet_filter_hook *pfh, *pfnext; - + PFIL_LIST_LOCK(); LIST_REMOVE(ph, ph_list); PFIL_LIST_UNLOCK(); @@ -196,7 +136,7 @@ pfil_head_unregister(struct pfil_head *ph) free(pfh, M_IFADDR); TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext) free(pfh, M_IFADDR); - PFIL_LOCK_DESTROY(ph); + PFIL_HEAD_LOCK_DESTROY(ph); return (0); } @@ -248,7 +188,7 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, goto error; } } - PFIL_WLOCK(ph); + PFIL_HEAD_WLOCK(ph); if (flags & PFIL_IN) { pfh1->pfil_func = func; pfh1->pfil_arg = arg; @@ -268,10 +208,10 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, } ph->ph_nhooks++; } - PFIL_WUNLOCK(ph); + PFIL_HEAD_WUNLOCK(ph); return (0); locked_error: - PFIL_WUNLOCK(ph); + PFIL_HEAD_WUNLOCK(ph); error: if (pfh1 != NULL) free(pfh1, M_IFADDR); @@ -290,7 +230,7 @@ pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, { int err = 0; - PFIL_WLOCK(ph); + PFIL_HEAD_WLOCK(ph); if (flags & PFIL_IN) { err = pfil_list_remove(&ph->ph_in, func, arg); if (err == 0) @@ -301,7 +241,7 @@ pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, if (err == 0) ph->ph_nhooks--; } - PFIL_WUNLOCK(ph); + PFIL_HEAD_WUNLOCK(ph); return (err); } @@ -358,7 +298,7 @@ vnet_pfil_init(const void *unused) { LIST_INIT(&V_pfil_head_list); - PFIL_LOCK_INIT_REAL(&V_pfil_lock, "shared"); + PFIL_LOCK_INIT(&V_pfil_lock, "shared"); return (0); } @@ -370,7 +310,7 @@ vnet_pfil_uninit(const void *unused) { /* XXX should panic if list is not empty */ - PFIL_LOCK_DESTROY_REAL(&V_pfil_lock); + PFIL_LOCK_DESTROY(&V_pfil_lock); return (0); } diff --git a/sys/net/pfil.h b/sys/net/pfil.h index fabfe9a..8a4d526 100644 --- a/sys/net/pfil.h +++ b/sys/net/pfil.h @@ -66,6 +66,9 @@ typedef TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t; #define PFIL_FLAG_PRIVATE_LOCK 0x01 /* Personal lock instead of global */ +VNET_DECLARE(struct rmlock, pfil_lock); +#define V_pfil_lock VNET(pfil_lock) + struct pfil_head { pfil_list_t ph_in; pfil_list_t ph_out; @@ -94,43 +97,40 @@ int pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *, int, struct inpcb *inp); -struct rm_priotracker; /* Do not require including rmlock header */ -int pfil_try_rlock(struct pfil_head *, struct rm_priotracker *); -void pfil_rlock(struct pfil_head *, struct rm_priotracker *); -void pfil_runlock(struct pfil_head *, struct rm_priotracker *); -void pfil_wlock(struct pfil_head *); -void pfil_wunlock(struct pfil_head *); -int pfil_wowned(struct pfil_head *ph); - int pfil_head_register(struct pfil_head *); int pfil_head_unregister(struct pfil_head *); struct pfil_head *pfil_head_get(int, u_long); -#define PFIL_HOOKED(p) ((p)->ph_nhooks > 0) -#define PFIL_LOCK_INIT_REAL(l, t) \ +#define PFIL_HOOKED(h) ((h)->ph_nhooks > 0) + +#define PFIL_LOCK_INIT(l, t) \ rm_init_flags(l, "PFil " t " rmlock", RM_RECURSE) -#define PFIL_LOCK_DESTROY_REAL(l) \ - rm_destroy(l) -#define PFIL_LOCK_INIT(p) do { \ - if ((p)->flags & PFIL_FLAG_PRIVATE_LOCK) { \ - PFIL_LOCK_INIT_REAL(&(p)->ph_lock, "private"); \ - (p)->ph_plock = &(p)->ph_lock; \ +#define PFIL_LOCK_DESTROY(l) rm_destroy(l) +#define PFIL_HEAD_LOCK_INIT(h) do { \ + if ((h)->flags & PFIL_FLAG_PRIVATE_LOCK) { \ + PFIL_LOCK_INIT(&(h)->ph_lock, "private"); \ + (h)->ph_plock = &(h)->ph_lock; \ } else \ - (p)->ph_plock = &V_pfil_lock; \ -} while (0) -#define PFIL_LOCK_DESTROY(p) do { \ - if ((p)->flags & PFIL_FLAG_PRIVATE_LOCK) \ - PFIL_LOCK_DESTROY_REAL((p)->ph_plock); \ + (h)->ph_plock = &V_pfil_lock; \ } while (0) -#define PFIL_TRY_RLOCK(p, t) rm_try_rlock((p)->ph_plock, (t)) -#define PFIL_RLOCK(p, t) rm_rlock((p)->ph_plock, (t)) -#define PFIL_WLOCK(p) rm_wlock((p)->ph_plock) -#define PFIL_RUNLOCK(p, t) rm_runlock((p)->ph_plock, (t)) -#define PFIL_WUNLOCK(p) rm_wunlock((p)->ph_plock) -#define PFIL_WOWNED(p) rm_wowned((p)->ph_plock) -#define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock) -#define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock) +#define PFIL_HEAD_LOCK_DESTROY(h) \ + if ((h)->flags & PFIL_FLAG_PRIVATE_LOCK) \ + PFIL_LOCK_DESTROY((h)->ph_plock); + +#define PFIL_TRY_RLOCK(l, t) rm_try_rlock((l), (t)) +#define PFIL_RLOCK(l, t) rm_rlock((l), (t)) +#define PFIL_WLOCK(l) rm_wlock(l) +#define PFIL_RUNLOCK(l, t) rm_runlock((l), (t)) +#define PFIL_WUNLOCK(l) rm_wunlock(l) +#define PFIL_WOWNED(l) rm_wowned(l) + +#define PFIL_HEAD_TRY_RLOCK(h, t) PFIL_TRY_RLOCK((h)->ph_plock, (t)) +#define PFIL_HEAD_RLOCK(h, t) PFIL_RLOCK((h)->ph_plock, (t)) +#define PFIL_HEAD_WLOCK(h) PFIL_WLOCK((h)->ph_plock) +#define PFIL_HEAD_RUNLOCK(h, t) PFIL_RUNLOCK((h)->ph_plock, (t)) +#define PFIL_HEAD_WUNLOCK(h) PFIL_WUNLOCK((h)->ph_plock) +#define PFIL_HEAD_WOWNED(h) PFIL_WOWNED((h)->ph_plock) static __inline struct packet_filter_hook * pfil_hook_get(int dir, struct pfil_head *ph) diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index 7113626..7907751 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c index 3c49ee7..74a6737 100644 --- a/sys/netpfil/ipfw/ip_fw_dynamic.c +++ b/sys/netpfil/ipfw/ip_fw_dynamic.c @@ -46,11 +46,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include /* for ETHERTYPE_IP */ #include +#include #include #include diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c index 87d9561..6d65dd4 100644 --- a/sys/netpfil/ipfw/ip_fw_nat.c +++ b/sys/netpfil/ipfw/ip_fw_nat.c @@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */ @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -494,6 +495,7 @@ ipfw_nat_del(struct sockopt *sopt) static int ipfw_nat_get_cfg(struct sockopt *sopt) { + IPFW_RLOCK_TRACKER(tracker); struct ip_fw_chain *chain = &V_layer3_chain; struct cfg_nat *n; struct cfg_redir *r; @@ -554,6 +556,7 @@ retry: static int ipfw_nat_get_log(struct sockopt *sopt) { + IPFW_RLOCK_TRACKER(tracker); uint8_t *data; struct cfg_nat *ptr; int i, size; diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 77a8c2f..80db9a2 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -227,7 +227,6 @@ struct ip_fw_chain { spinlock_t rwmtx; spinlock_t uh_lock; #else - struct rwlock rwmtx; struct rwlock uh_lock; /* lock for upper half */ #endif uint32_t id; /* ruleset id */ @@ -268,6 +267,7 @@ if (update_counters != 0) { \ * so the variable and the macros must be here. */ +#if defined( __linux__ ) || defined( _WIN32 ) #define IPFW_LOCK_INIT(_chain) do { \ rw_init(&(_chain)->rwmtx, "IPFW static rules"); \ rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ @@ -280,7 +280,7 @@ if (update_counters != 0) { \ #define IPFW_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_RLOCKED) #define IPFW_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_WLOCKED) - +#define IPFW_RLOCK_TRACKER(tracker) #define IPFW_RLOCK(p) rw_rlock(&(p)->rwmtx) #define IPFW_RUNLOCK(p) rw_runlock(&(p)->rwmtx) #define IPFW_WLOCK(p) rw_wlock(&(p)->rwmtx) @@ -288,6 +288,22 @@ if (update_counters != 0) { \ /* These macros are used in the packet flow path, i.e. in the ipfw_chk */ #define IPFW_PF_RLOCK(p) IPFW_RLOCK(p) #define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p) +#else /* FreeBSD */ + +#define IPFW_LOCK_INIT(_chain) rw_init(&(_chain)->uh_lock, \ + "IPFW UH lock"); +#define IPFW_LOCK_DESTROY(_chain) rw_destroy(&(_chain)->uh_lock); +#define IPFW_RLOCK_ASSERT(_chain) /* XXX: NOTYET */ +#define IPFW_WLOCK_ASSERT(_chain) KASSERT(PFIL_WOWNED(&V_pfil_lock) != 0) +#define IPFW_RLOCK_TRACKER(tracker) struct rm_priotracker tracker +#define IPFW_RLOCK(p) PFIL_RLOCK(&V_pfil_lock, &tracker) +#define IPFW_RUNLOCK(p) PFIL_RUNLOCK(&V_pfil_lock, &tracker) +#define IPFW_WLOCK(p) PFIL_WLOCK(&V_pfil_lock) +#define IPFW_WUNLOCK(p) PFIL_WUNLOCK(&V_pfil_lock) +#define IPFW_PF_RLOCK(p) +#define IPFW_PF_RUNLOCK(p) + +#endif #define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED) #define IPFW_UH_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_WLOCKED) diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index b681612..ecd4155 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -49,11 +49,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -939,6 +941,7 @@ int ipfw_ctl(struct sockopt *sopt) { #define RULE_MAXSIZE (512*sizeof(u_int32_t)) + IPFW_RLOCK_TRACKER(tracker); int error; size_t size, len, valsize; struct ip_fw *buf, *rule; diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 27c13ca..5a08549 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -52,9 +52,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include /* ip_fw.h requires IFNAMSIZ */ +#include #include #include #include