Hello,
very small first step towards MP(i) friendly PF. Patch adds mutex around
fragment cache.
Patch adds a lock around fragment cache. Unlike other parts of PF the fragment
cache is self-contained subsystem. In that sense we can easily guard its entry
points (pf_reassemble(), pf_reassemble6()) by mutex. The cache is shared
by both protocols (AF_INET, AF_INET6), hence we have just one lock.
The locks (technically speaking mutexes) for other PF subsystems will follow as
soon as the remove&destroy operations for PF data objects will get untangled.
What essentially needs to be done is to split remove and destroy operations for
PF objects into separate functions. This is something, what's being worked on
currently.
As you can see the mutex, when acquired, raises interrupt level to softnet.
Same interrupt level is used by ioctl() and purge threads. IMO it should be
fine, but I'd like to hear some confirmation...
any OKs?
thanks and
regards
sasha
--------8<---------------8<---------------8<------------------8<--------
Index: pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.182
diff -u -p -r1.182 pf_norm.c
--- pf_norm.c 10 Sep 2015 08:28:31 -0000 1.182
+++ pf_norm.c 12 Sep 2015 17:18:43 -0000
@@ -134,6 +134,7 @@ int pf_reassemble6(struct mbuf **, st
struct pool pf_frent_pl, pf_frag_pl;
struct pool pf_state_scrub_pl;
int pf_nfrents;
+struct mutex pf_frag_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
void
pf_normalize_init(void)
@@ -771,6 +772,7 @@ pf_normalize_ip(struct pf_pdesc *pd, u_s
struct ip *h = mtod(pd->m, struct ip *);
u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
u_int16_t mff = (ntohs(h->ip_off) & IP_MF);
+ int rv;
if (!fragoff && !mff)
goto no_fragment;
@@ -792,8 +794,11 @@ pf_normalize_ip(struct pf_pdesc *pd, u_s
if (!pf_status.reass)
return (PF_PASS); /* no reassembly */
+ PF_FRAG_LOCK();
/* Returns PF_DROP or m is NULL or completely reassembled mbuf */
- if (pf_reassemble(&pd->m, pd->dir, reason) != PF_PASS)
+ rv = pf_reassemble(&pd->m, pd->dir, reason);
+ PF_FRAG_UNLOCK();
+ if (rv != PF_PASS)
return (PF_DROP);
if (pd->m == NULL)
return (PF_PASS); /* packet has been reassembled, no error */
@@ -813,6 +818,7 @@ int
pf_normalize_ip6(struct pf_pdesc *pd, u_short *reason)
{
struct ip6_frag frag;
+ int rv;
if (pd->fragoff == 0)
goto no_fragment;
@@ -824,9 +830,12 @@ pf_normalize_ip6(struct pf_pdesc *pd, u_
if (!pf_status.reass)
return (PF_PASS); /* no reassembly */
+ PF_FRAG_LOCK();
/* Returns PF_DROP or m is NULL or completely reassembled mbuf */
- if (pf_reassemble6(&pd->m, &frag, pd->fragoff + sizeof(frag),
- pd->extoff, pd->dir, reason) != PF_PASS)
+ rv = pf_reassemble6(&pd->m, &frag, pd->fragoff + sizeof(frag),
+ pd->extoff, pd->dir, reason);
+ PF_FRAG_UNLOCK();
+ if (rv != PF_PASS)
return (PF_DROP);
if (pd->m == NULL)
return (PF_PASS); /* packet has been reassembled, no error */
Index: pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.420
diff -u -p -r1.420 pfvar.h
--- pfvar.h 19 Aug 2015 21:22:41 -0000 1.420
+++ pfvar.h 12 Sep 2015 17:18:43 -0000
@@ -1907,7 +1907,10 @@ int pf_postprocess_addr(struct
pf_sta
void pf_cksum(struct pf_pdesc *, struct mbuf *);
-#endif /* _KERNEL */
+extern struct mutex pf_frag_mtx;
+#define PF_FRAG_LOCK() mtx_enter(&pf_frag_mtx)
+#define PF_FRAG_UNLOCK() mtx_leave(&pf_frag_mtx)
+#endif /* _KERNEL */
#endif /* _NET_PFVAR_H_ */