When pf is disabled (pfctl -d), pf_remove_queues() detaches hfsc from the
interface but the queues are not removed from pf_queues_active.
The next time pf rules are loaded, pf_commit_queues() calls pf_remove_queues()
and in turn hfsc_delqueue() for each queue in pf_queues_active. This fails
since hfsc has already been detached.
Example:
# echo 'queue root on em0 bandwidth 2M default' > /tmp/pf.conf
# pfctl -f /tmp/pf.conf
# pfctl -d
# sudo pfctl -f /tmp/pf.conf
pfctl: DIOCXCOMMIT: Invalid argument
Also, if queues are loaded after pf is disabled they become immediately
active rather than remaining inactive until pf is enabled. Example:
# pfctl -Fa
# pfctl -d
# pfctl -f /tmp/pf.conf
# pfctl -vs queue
[ pkts: 0 bytes: 0 dropped pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 ]
queue root on em0 bandwidth 2M default qlimit 50
[ pkts: 180 bytes: 25352 dropped pkts: 0 bytes: 0 ]
[ qlength: 0/ 50 ]
The diff below also allows 'pfctl -vs queue' to show zeros rather than an
error when pf is disabled.
Nathanael
Index: sys/net/pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.272
diff -u -p -r1.272 pf_ioctl.c
--- sys/net/pf_ioctl.c 22 Apr 2014 14:41:03 -0000 1.272
+++ sys/net/pf_ioctl.c 1 Jul 2014 12:36:08 -0000
@@ -591,7 +591,7 @@ pf_commit_queues(void)
struct pf_queuehead *qswap;
int error;
- if ((error = pf_remove_queues(NULL)) != 0)
+ if (pf_status.running && (error = pf_remove_queues(NULL)) != 0)
return (error);
/* swap */
@@ -600,7 +600,9 @@ pf_commit_queues(void)
pf_queues_inactive = qswap;
pf_free_queues(pf_queues_inactive, NULL);
- return (pf_create_queues());
+ if (pf_status.running && (error = pf_create_queues()) != 0)
+ return (error);
+ return (0);
}
#define PF_MD5_UPD(st, elm) \
@@ -1004,8 +1006,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
break;
}
bcopy(qs, &pq->queue, sizeof(pq->queue));
- error = hfsc_qstats(qs, pq->buf, &nbytes);
- if (error == 0)
+ pq->nbytes = 0;
+ if (pf_status.running &&
+ (error = hfsc_qstats(qs, pq->buf, &nbytes)) == 0)
pq->nbytes = nbytes;
break;
}