Index: pf.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pf.c,v retrieving revision 1.16 diff -u -r1.16 pf.c --- pf.c 23 Jul 2004 03:31:42 -0000 1.16 +++ pf.c 29 Jul 2004 03:14:29 -0000 @@ -64,6 +64,7 @@ #ifdef __FreeBSD__ #include #include +#include #else #include #endif @@ -2174,6 +2175,9 @@ struct pf_rule *r, *rm = NULL, *anchorrule = NULL; struct pf_ruleset *ruleset = NULL; +#ifdef __FreeBSD__ + PF_ASSERT(PF_REF_LOCKED); +#endif r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr); while (r && rm == NULL) { struct pf_rule_addr *src = NULL, *dst = NULL; @@ -2673,6 +2677,9 @@ int tag = -1; u_int16_t mss = tcp_mssdflt; +#ifdef __FreeBSD__ + PF_ADDREF(); +#endif r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); if (direction == PF_OUT) { @@ -2770,6 +2777,9 @@ r = *rm; a = *am; ruleset = *rsm; +#ifdef __FreeBSD__ + PF_REMREF(r); +#endif REASON_SET(&reason, PFRES_MATCH); @@ -3032,6 +3042,9 @@ struct pf_tag *pftag = NULL; int tag = -1; +#ifdef __FreeBSD__ + PF_ADDREF(); +#endif r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); if (direction == PF_OUT) { @@ -3126,6 +3139,9 @@ r = *rm; a = *am; ruleset = *rsm; +#ifdef __FreeBSD__ + PF_REMREF(r); +#endif REASON_SET(&reason, PFRES_MATCH); @@ -3331,6 +3347,9 @@ #endif /* INET6 */ } +#ifdef __FreeBSD__ + PF_ADDREF(); +#endif r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); if (direction == PF_OUT) { @@ -3433,6 +3452,9 @@ r = *rm; a = *am; ruleset = *rsm; +#ifdef __FreeBSD__ + PF_REMREF(r); +#endif REASON_SET(&reason, PFRES_MATCH); @@ -3578,6 +3600,9 @@ struct pf_tag *pftag = NULL; int tag = -1; +#ifdef __FreeBSD__ + PF_ADDREF(); +#endif r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); if (direction == PF_OUT) { @@ -3672,6 +3697,9 @@ r = *rm; a = *am; ruleset = *rsm; +#ifdef __FreeBSD__ + PF_REMREF(r); +#endif REASON_SET(&reason, PFRES_MATCH); @@ -3831,6 +3859,9 @@ struct pf_tag *pftag = NULL; int tag = -1; +#ifdef __FreeBSD__ + PF_ADDREF(); +#endif r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr); while (r != NULL) { r->evaluations++; @@ -3876,6 +3907,9 @@ r = *rm; a = *am; ruleset = *rsm; +#ifdef __FreeBSD__ + PF_REMREF(r); +#endif REASON_SET(&reason, PFRES_MATCH); @@ -6120,6 +6154,8 @@ pf_route(m0, r, dir, ifp, s); #ifdef __FreeBSD__ + if (r->refcount == 0) + pf_rm_rule(NULL, r); PF_UNLOCK(); #endif Index: pf_ioctl.c =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pf_ioctl.c,v retrieving revision 1.11 diff -u -r1.11 pf_ioctl.c --- pf_ioctl.c 17 Jun 2004 16:59:47 -0000 1.11 +++ pf_ioctl.c 29 Jul 2004 03:14:12 -0000 @@ -104,6 +104,7 @@ #include #include #include +#include #include #endif /* __FreeBSD__ */ @@ -197,13 +198,20 @@ .d_version = D_VERSION, }; -static volatile int pf_pfil_hooked = 0; -struct mtx pf_task_mtx; +static volatile int pf_pfil_hooked = 0; +struct mtx pf_task_mtx; +struct cv pf_write_cv; +struct cv pf_read_cv; +int pf_writer_cnt; +int pf_reader_cnt; void init_pf_mutex(void) { mtx_init(&pf_task_mtx, "pf task mtx", NULL, MTX_DEF); + cv_init(&pf_write_cv, "pf exclusive cv"); + cv_init(&pf_read_cv, "pf nonexclusive cv"); + pf_writer_cnt = pf_reader_cnt = 0; } void @@ -293,6 +301,7 @@ TAILQ_INIT(&state_updates); /* default rule should never be garbage collected */ + pf_default_rule.refcount = 1; pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next; pf_default_rule.action = PF_PASS; pf_default_rule.nr = -1; @@ -658,13 +667,21 @@ pf_tbladdr_remove(&rule->src.addr); pf_tbladdr_remove(&rule->dst.addr); } +#ifdef __FreeBSD__ + rule->refcount--; +#endif TAILQ_REMOVE(rulequeue, rule, entries); rule->entries.tqe_prev = NULL; rule->nr = -1; } +#ifdef __FreeBSD__ + if (rule->states > 0 || rule->src_nodes > 0 || + rule->entries.tqe_prev != NULL || rule->refcount > 0) +#else if (rule->states > 0 || rule->src_nodes > 0 || rule->entries.tqe_prev != NULL) +#endif return; pf_tag_unref(rule->tag); pf_tag_unref(rule->match_tag); @@ -946,6 +963,9 @@ return (EBUSY); /* Swap rules, keep the old. */ +#ifdef __FreeBSD__ + PF_XLOCK(); +#endif s = splsoftnet(); old_rules = rs->rules[rs_num].active.ptr; rs->rules[rs_num].active.ptr = @@ -961,6 +981,9 @@ rs->rules[rs_num].inactive.open = 0; pf_remove_if_empty_ruleset(rs); pf_update_anchor_rules(); +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); return (0); } @@ -1192,6 +1215,9 @@ rule->kif = NULL; TAILQ_INIT(&rule->rpool.list); /* initialize refcounting */ +#ifdef __FreeBSD__ + rule->refcount = 1; +#endif rule->states = 0; rule->src_nodes = 0; rule->entries.tqe_prev = NULL; @@ -1410,6 +1436,9 @@ bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); TAILQ_INIT(&newrule->rpool.list); /* initialize refcounting */ +#ifdef __FreeBSD__ + newrule->refcount = 1; +#endif newrule->states = 0; newrule->entries.tqe_prev = NULL; #ifndef INET @@ -1489,6 +1518,9 @@ } pf_empty_pool(&pf_pabuf); +#ifdef __FreeBSD__ + PF_XLOCK(); +#endif s = splsoftnet(); if (pcr->action == PF_CHANGE_ADD_HEAD) @@ -1505,6 +1537,9 @@ if (oldrule == NULL) { pf_rm_rule(NULL, newrule); error = EINVAL; +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; } @@ -1536,6 +1571,9 @@ pf_update_anchor_rules(); ruleset->rules[rs_num].active.ticket++; +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; } @@ -1919,11 +1957,17 @@ struct pf_ruleset *ruleset = &pf_main_ruleset; struct pf_rule *rule; +#ifdef __FreeBSD__ + PF_XLOCK(); /* XXX: needed? */ +#endif s = splsoftnet(); TAILQ_FOREACH(rule, ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) rule->evaluations = rule->packets = rule->bytes = 0; +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; } @@ -2339,6 +2383,9 @@ } } +#ifdef __FreeBSD__ + PF_XLOCK(); +#endif s = splsoftnet(); if (pca->action == PF_CHANGE_ADD_HEAD) @@ -2355,6 +2402,9 @@ } if (oldpa == NULL) { error = EINVAL; +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; } @@ -2380,6 +2430,9 @@ pool->cur = TAILQ_FIRST(&pool->list); PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, pca->af); +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; } @@ -2676,16 +2729,28 @@ case DIOCOSFPADD: { struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; +#ifdef __FreeBSD__ + PF_XLOCK(); +#endif s = splsoftnet(); error = pf_osfp_add(io); +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; } case DIOCOSFPGET: { struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; +#ifdef __FreeBSD__ + PF_XLOCK(); +#endif s = splsoftnet(); error = pf_osfp_get(io); +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; } @@ -2988,8 +3053,14 @@ } case DIOCOSFPFLUSH: +#ifdef __FreeBSD__ + PF_XLOCK(); +#endif s = splsoftnet(); pf_osfp_flush(); +#ifdef __FreeBSD__ + PF_XUNLOCK(); +#endif splx(s); break; Index: pfvar.h =================================================================== RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pfvar.h,v retrieving revision 1.7 diff -u -r1.7 pfvar.h --- pfvar.h 22 Jun 2004 20:13:25 -0000 1.7 +++ pfvar.h 29 Jul 2004 03:03:41 -0000 @@ -187,26 +187,71 @@ #define UMA_DESTROY(var) \ if(var) uma_zdestroy(var) -extern struct mtx pf_task_mtx; - -#define PF_ASSERT(h) mtx_assert(&pf_task_mtx, (h)) +extern struct mtx pf_task_mtx; +extern struct cv pf_write_cv; +extern struct cv pf_read_cv; +extern int pf_writer_cnt; +extern int pf_reader_cnt; + +#define PF_REF_LOCKED MA_RECURSED +#ifdef INVARIANTS +#define PF_ASSERT(h) do { \ + if ((h) == MA_OWNED || (h) == MA_NOTOWNED) \ + mtx_assert(&pf_task_mtx, (h)); \ + else if ((h) == PF_REF_LOCKED) { \ + mtx_assert(&pf_task_mtx, MA_NOTOWNED); \ + KASSERT(pf_reader_cnt > 0, "No reference!"); \ + } \ +} while (0); +#else +#define PF_ASSERT(h) +#endif -#define PF_LOCK() do { \ - PF_ASSERT(MA_NOTOWNED); \ - mtx_lock(&pf_task_mtx); \ +#define PF_LOCK() do { \ + PF_ASSERT(MA_NOTOWNED); \ + mtx_lock(&pf_task_mtx); \ } while(0) -#define PF_UNLOCK() do { \ - PF_ASSERT(MA_OWNED); \ - mtx_unlock(&pf_task_mtx); \ +#define PF_UNLOCK() do { \ + PF_ASSERT(MA_OWNED); \ + KASSERT(pf_reader_cnt > 0 || pf_write_cnt == 0, \ + "UNLOCK after XLOCK!"); \ + mtx_unlock(&pf_task_mtx); \ } while(0) - -#define PF_COPYIN(uaddr, kaddr, len, r) do { \ +#define PF_ADDREF() do { \ + PF_ASSERT(MA_OWNED); \ + while (pf_writer_cnt > 0) \ + cv_wait(&pf_read_cv, &pf_task_mtx); \ + pf_reader_cnt++; \ + PF_UNLOCK(); \ +} while (0) +#define PF_REMREF(r) do { \ + PF_LOCK(); \ + (r)->refcount++; \ + if (--pf_reader_cnt == 0 && pf_writer_cnt > 0) \ + cv_signal(&pf_write_cv); \ + (r)->refcount--; \ +} while (0) +#define PF_XLOCK() do { \ + PF_ASSERT(MA_OWNED); \ + pf_writer_cnt++; \ + if (pf_reader_cnt > 0) \ + cv_wait(&pf_write_cv, &pf_task_mtx); \ +} while (0) +#define PF_XUNLOCK() do { \ + PF_ASSERT(MA_OWNED); \ + if (--pf_writer_cnt > 0) \ + cv_signal(&pf_write_cv); \ + else \ + cv_broadcast(&pf_read_cv); \ +} while (0) + +#define PF_COPYIN(uaddr, kaddr, len, r) do { \ PF_UNLOCK(); \ r = copyin((uaddr), (kaddr), (len)); \ PF_LOCK(); \ } while(0) -#define PF_COPYOUT(kaddr, uaddr, len, r) do { \ +#define PF_COPYOUT(kaddr, uaddr, len, r) do { \ PF_UNLOCK(); \ r = copyout((kaddr), (uaddr), (len)); \ PF_LOCK(); \ @@ -215,16 +260,16 @@ extern void init_pf_mutex(void); extern void destroy_pf_mutex(void); -#define PF_MODVER 1 -#define PFLOG_MODVER 1 -#define PFSYNC_MODVER 1 - -#define PFLOG_MINVER 1 -#define PFLOG_PREFVER PFLOG_MODVER -#define PFLOG_MAXVER 1 -#define PFSYNC_MINVER 1 -#define PFSYNC_PREFVER PFSYNC_MODVER -#define PFSYNC_MAXVER 1 +#define PF_MODVER 1 +#define PFLOG_MODVER 1 +#define PFSYNC_MODVER 1 + +#define PFLOG_MINVER 1 +#define PFLOG_PREFVER PFLOG_MODVER +#define PFLOG_MAXVER 1 +#define PFSYNC_MINVER 1 +#define PFSYNC_PREFVER PFSYNC_MODVER +#define PFSYNC_MAXVER 1 /* prototyped for pf_subr.c */ struct hook_desc { @@ -579,6 +624,9 @@ pf_osfp_t os_fingerprint; u_int32_t timeout[PFTM_MAX]; +#ifdef __FreeBSD__ + u_int32_t refcount; +#endif u_int32_t states; u_int32_t max_states; u_int32_t src_nodes;