kern/106400: fatal trap 12 at restart of PF with ALTQ if ng0
device has detached
Max Laier
max at love2party.net
Thu Dec 7 11:10:18 PST 2006
The following reply was made to PR kern/106400; it has been noted by GNATS.
From: Max Laier <max at love2party.net>
To: bug-followup at freebsd.org,
bst2006 at dva.dyndns.org
Cc:
Subject: Re: kern/106400: fatal trap 12 at restart of PF with ALTQ if ng0 device has detached
Date: Thu, 7 Dec 2006 20:00:25 +0100
--Boundary-00=_LTGeFqtfh+L0SPO
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Okay, this is highly untested and certainly needs more work, but I don't
have a crashbox set up right now, so if you could give it a try we might
be getting somewhere quick.
Please turn on misc debugging (pfctl -xm).
This also might be a way to use ALTQ on not yet created interfaces, though
this needs even more work.
Report back if this changes anything. If you get a crash I'd like to see
a dump and dmesg if possible.
Thanks a lot.
--
Max
--Boundary-00=_LTGeFqtfh+L0SPO
Content-Type: text/x-diff;
charset="us-ascii";
name="altq_remove_if.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="altq_remove_if.diff"
Index: pf_ioctl.c
===================================================================
RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pf_ioctl.c,v
retrieving revision 1.20.2.4
diff -u -r1.20.2.4 pf_ioctl.c
--- pf_ioctl.c 9 Sep 2006 00:50:25 -0000 1.20.2.4
+++ pf_ioctl.c 7 Dec 2006 18:54:24 -0000
@@ -211,6 +211,8 @@
static int pf_load(void);
static int pf_unload(void);
+void pf_detach_ifnet_event(void * __unused, struct ifnet *);
+
static struct cdevsw pf_cdevsw = {
.d_ioctl = pfioctl,
.d_name = PF_NAME,
@@ -221,6 +223,8 @@
struct mtx pf_task_mtx;
pflog_packet_t *pflog_packet_ptr = NULL;
+eventhandler_tag pf_detach_cookie = NULL;
+
void
init_pf_mutex(void)
{
@@ -351,9 +355,52 @@
/* XXX do our best to avoid a conflict */
pf_status.hostid = arc4random();
+ pf_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
+ pf_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
return (error);
}
+
+void
+pf_detach_ifnet_event(void *arg __unused, struct ifnet *ifp)
+{
+#ifdef ALTQ
+ struct pf_altq *altq;
+ int err, error = 0;
+
+ PF_LOCK();
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+ if (strncmp(ifp->if_xname, altq->ifname, IFNAMSIZ) != 0)
+ continue;
+ if (altq->qname[0] != 0) {
+/* XXX: maybe later
+ altq->flags |= PFALTQ_FLAG_IF_REMOVED;
+ */
+ continue;
+ }
+ KASSERT((altq->flags & PFALTQ_FLAG_IF_REMOVED) == 0,
+ ("flag already in use"));
+ /* detach and destroy the discipline */
+ DPFPRINTF(PF_DEBUG_MISC, ("pf: remove altq %s.%s ...",
+ altq->ifname, altq->parent));
+ if (pf_altq_running)
+ error = pf_disable_altq(altq);
+ DPFPRINTF(PF_DEBUG_MISC, ("%d ", error));
+ err = altq_pfdetach(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ DPFPRINTF(PF_DEBUG_MISC, ("%d ", error));
+ err = altq_remove(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ DPFPRINTF(PF_DEBUG_MISC, ("%d\n", error));
+ altq->flags |= PFALTQ_FLAG_IF_REMOVED;
+ }
+ PF_UNLOCK();
+#endif
+}
+
+
#else /* !__FreeBSD__ */
void
pfattach(int num)
@@ -1042,7 +1089,8 @@
/* Purge the old altq list */
while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
+ if (altq->qname[0] == 0 &&
+ (altq->flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
/* detach and destroy the discipline */
error = altq_remove(altq);
} else
@@ -1067,7 +1115,8 @@
/* Purge the old altq list */
while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
+ if (altq->qname[0] == 0 &&
+ (altq->flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
/* detach and destroy the discipline */
error = altq_remove(altq);
} else
@@ -1112,7 +1161,8 @@
/* Purge the old altq list */
while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
+ if (altq->qname[0] == 0 &&
+ (altq->flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
/* detach and destroy the discipline */
if (pf_altq_running)
error = pf_disable_altq(altq);
@@ -1139,6 +1189,9 @@
struct tb_profile tb;
int s, error = 0;
+ if (altq->flags & PFALTQ_FLAG_IF_REMOVED)
+ return (0);
+
if ((ifp = ifunit(altq->ifname)) == NULL)
return (EINVAL);
@@ -1170,6 +1223,9 @@
struct tb_profile tb;
int s, error;
+ if (altq->flags & PFALTQ_FLAG_IF_REMOVED)
+ return (0);
+
if ((ifp = ifunit(altq->ifname)) == NULL)
return (EINVAL);
@@ -3548,6 +3604,7 @@
PF_LOCK();
pf_status.running = 0;
PF_UNLOCK();
+ EVENTHANDLER_DEREGISTER(ifnet_departure_event, pf_detach_cookie);
error = dehook_pf();
if (error) {
/*
Index: pfvar.h
===================================================================
RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pfvar.h,v
retrieving revision 1.11.2.2
diff -u -r1.11.2.2 pfvar.h
--- pfvar.h 30 Dec 2005 00:50:18 -0000 1.11.2.2
+++ pfvar.h 7 Dec 2006 18:33:46 -0000
@@ -1214,6 +1214,8 @@
u_int8_t priority; /* priority */
u_int16_t qlimit; /* queue size limit */
u_int16_t flags; /* misc flags */
+/* XXX: unused?!? */
+#define PFALTQ_FLAG_IF_REMOVED 0x8000
union {
struct cbq_opts cbq_opts;
struct priq_opts priq_opts;
--Boundary-00=_LTGeFqtfh+L0SPO--
More information about the freebsd-pf
mailing list