Download raw body.
fq_codel devbuf leak on pf reload
Hi,
I've been chasing down a leak of M_DEVBUF malloc memory which seems to
occur on one of my systems whenever I have a fq_codel queue in pf.conf:
matilda$ doas pfctl -f /etc/pf.conf ;systat malloc | grep ^devbuf
devbuf 34560 39024K 39097K 218M 35714 0
matilda$ doas pfctl -f /etc/pf.conf ;systat malloc | grep ^devbuf
devbuf 34562 39096K 39169K 218M 35728 0
matilda$ doas pfctl -f /etc/pf.conf ;systat malloc | grep ^devbuf
devbuf 34564 39169K 39242K 218M 35742 0
matilda$ doas pfctl -f /etc/pf.conf ;systat malloc | grep ^devbuf
devbuf 34566 39241K 39314K 218M 35756 0
matilda$ doas pfctl -f /etc/pf.conf ;systat malloc | grep ^devbuf
devbuf 34568 39313K 39386K 218M 35770 0
matilda$ doas pfctl -f /etc/pf.conf ;systat malloc | grep ^devbuf
devbuf 34570 39385K 39458K 218M 35784 0
If I run `pfctl -f` enough this eventually exhausts devbuf and deadlocks
this machine, with pfctl holding netlock waiting for devbuf, ISC named
holding sysctllk waiting for netlock, and everything else piled up
behind sysctllk (which is how I noticed it in the first place, since
this particular firewall runs pfctl periodically after interface changes
and was hitting the deadlock every few weeks)
After some reading of fq_codel.c I noticed that the ifq_free callback
for fq_codel (fqcodel_free) does nothing, even though there is allocated
memory hanging off the struct fqcodel, as well as the struct fqcodel
itself which should be freed (which you can see being deallocated in the
*pfq* free callback, fqcodel_pf_free).
The way I understand the code in pf_ioctl.c, the PF callbacks for discs
are never called once they actually get put on an interface: only the
ifq_free gets called past that point, so it needs to free the memory the
same way as fqcodel_pf_free does.
HFSC by contrast frees everything in hfsc_free, and makes hfsc_pf_free
call that. (And, indeed, if I change my queues to HFSC, no leak.)
I applied the following patch on my machine and it seems to resolve the
problem:
--- a/sys/net/fq_codel.c
+++ b/sys/net/fq_codel.c
@@ -908,5 +908,5 @@ fqcodel_alloc(unsigned int idx, void *arg)
void
fqcodel_free(unsigned int idx, void *arg)
{
- /* nothing to do here */
+ fqcodel_pf_free(arg);
}
Feels like an easy one to me, unless I'm missing something? (Which I
could definitely be, I'm still very new to the PF code)
fq_codel devbuf leak on pf reload