Date: Tue, 27 Nov 2007 21:44:46 +0100 From: Max Laier <max@love2party.net> To: Florian Smeets <flo@kasimir.com> Cc: freebsd-pf@freebsd.org Subject: ALTQ for dynamic interfaces [Re: 7-STABLE panic: mtx_lock() of spin mutex %s @ %s:%d] Message-ID: <200711272144.52511.max@love2party.net> In-Reply-To: <474BE383.6050905@kasimir.com> References: <474B5BD0.6040004@kasimir.com> <200711270130.01165.max@love2party.net> <474BE383.6050905@kasimir.com>
next in thread | previous in thread | raw e-mail | index | archive | help
--nextPart2168564.eTSo7kHDG8 Content-Type: multipart/mixed; boundary="Boundary-01=_/GITHJDfvfmxyCv" Content-Transfer-Encoding: 7bit Content-Disposition: inline --Boundary-01=_/GITHJDfvfmxyCv Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On Tuesday 27 November 2007, Florian Smeets wrote: > Max Laier wrote: > > On Tuesday 27 November 2007, Florian Smeets wrote: > >> Hi > >> > >> i was able to reproduce a hang on a 7-STABLE (csuped just after > >> Scotts critical section MFC) firewall which runs mpd4 from ports and > >> uses pf for packet filtering. Sometimes when i restart mpd4 the box > >> just hangs. I have a up-script which calls /sbin/pfctl -f > >> /etc/pf.conf. > > > > It's an ALTQ problem, really. I don't know if there is a down-script > > that runs before the interface is destroyed, but if there is - adding > > pfctl -Fq there should work around your problem. I did have some > > patches to have ALTQ working with dynamic interfaces, but I must have > > dropped them. I'll see what I can dig up in the next few days. > > That would be great. I have a second non productive box where i can > reproduce the problem. I'll be glad to test any patches. Okay ... try this. Not final yet, but should be functional. With this=20 you should be able to: 1) Safely remove an interface with active queues 2) Re-add the interface and *magically* get the queues back 3) Write queue rules for non-existing interfaces - Note that we will assume an MTU of 1500 and you have to specify a=20 fixed bandwidth as we don't know the interface's native speed - Obviously these queues will be activated as soon as a matching=20 interface is created. BUGS: Doesn't print queues on removed interfaces at all. Should be=20 changed to something like "queue foo on bar0 (N/A) ...", but it seems I=20 was too strict with the local_flags. The error handling might need some=20 work in order to avoid panic if something goes wrong while we de-activate=20 queues. I'd like to hear back from you in order to see if I at least got the basic= =20 workings right enough so you can survive the mpd interface destroy. =20 Could you - in addition to you current setup w/ if-up script - also test=20 the magic part? i.e. load the ruleset before loading mpd. This should=20 now be possible as long as you don't put "set loginterface" or fixed=20 interface-to-address src/dst in it \o/ =2D-=20 /"\ Best regards, | mlaier@freebsd.org \ / Max Laier | ICQ #67774661 X http://pf4freebsd.love2party.net/ | mlaier@EFnet / \ ASCII Ribbon Campaign | Against HTML Mail and News --Boundary-01=_/GITHJDfvfmxyCv Content-Type: text/x-diff; charset="iso-8859-1"; name="pf.dyn_altq.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="pf.dyn_altq.diff" diff --git a/contrib/pf/pfctl/pfctl_altq.c b/contrib/pf/pfctl/pfctl_altq.c index 9104f5a..d2a21c8 100644 =2D-- a/contrib/pf/pfctl/pfctl_altq.c +++ b/contrib/pf/pfctl/pfctl_altq.c @@ -154,6 +154,10 @@ print_altq(const struct pf_altq *a, unsigned level, st= ruct node_queue_bw *bw, } =20 printf("altq on %s ", a->ifname); +#ifdef __FreeBSD__ + if (a->local_flags) + printf("N/A "); +#endif =20 switch (a->scheduler) { case ALTQT_CBQ: @@ -1145,7 +1149,11 @@ getifmtu(char *ifname) sizeof(ifr.ifr_name)) errx(1, "getifmtu: strlcpy"); if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) =3D=3D -1) +#ifdef __FreeBSD__ + ifr.ifr_mtu =3D 1500; +#else err(1, "SIOCGIFMTU"); +#endif if (shutdown(s, SHUT_RDWR) =3D=3D -1) err(1, "shutdown"); if (close(s)) diff --git a/contrib/pf/pfctl/pfctl_qstats.c b/contrib/pf/pfctl/pfctl_qstat= s.c index 3eb2987..15695cb 100644 =2D-- a/contrib/pf/pfctl/pfctl_qstats.c +++ b/contrib/pf/pfctl/pfctl_qstats.c @@ -157,7 +157,11 @@ pfctl_update_qstats(int dev, struct pf_altq_node **roo= t) warn("DIOCGETALTQ"); return (-1); } +#ifdef __FreeBSD__ + if (pa.altq.qid > 0 && !pa.altq.local_flags) { +#else if (pa.altq.qid > 0) { +#endif pq.nr =3D nr; pq.ticket =3D pa.ticket; pq.buf =3D &qstats.data; diff --git a/sys/contrib/pf/net/pf_if.c b/sys/contrib/pf/net/pf_if.c index 74e9dcb..8b09cc3 100644 =2D-- a/sys/contrib/pf/net/pf_if.c +++ b/sys/contrib/pf/net/pf_if.c @@ -893,6 +893,9 @@ pfi_attach_ifnet_event(void *arg __unused, struct ifnet= *ifp) { PF_LOCK(); pfi_attach_ifnet(ifp); +#ifdef ALTQ + pf_altq_ifnet_event(ifp, 0); +#endif PF_UNLOCK(); } =20 @@ -901,6 +904,9 @@ pfi_detach_ifnet_event(void *arg __unused, struct ifnet= *ifp) { PF_LOCK(); pfi_detach_ifnet(ifp); +#ifdef ALTQ + pf_altq_ifnet_event(ifp, 1); +#endif PF_UNLOCK(); } =20 diff --git a/sys/contrib/pf/net/pf_ioctl.c b/sys/contrib/pf/net/pf_ioctl.c index 136e710..0681abf 100644 =2D-- a/sys/contrib/pf/net/pf_ioctl.c +++ b/sys/contrib/pf/net/pf_ioctl.c @@ -787,7 +787,11 @@ pf_begin_altq(u_int32_t *ticket) /* Purge the old altq list */ while ((altq =3D TAILQ_FIRST(pf_altqs_inactive)) !=3D NULL) { TAILQ_REMOVE(pf_altqs_inactive, altq, entries); +#ifdef __FreeBSD__ + if (altq->qname[0] =3D=3D 0 && altq->local_flags =3D=3D 0) { +#else if (altq->qname[0] =3D=3D 0) { +#endif /* detach and destroy the discipline */ error =3D altq_remove(altq); } else @@ -812,7 +816,11 @@ pf_rollback_altq(u_int32_t ticket) /* Purge the old altq list */ while ((altq =3D TAILQ_FIRST(pf_altqs_inactive)) !=3D NULL) { TAILQ_REMOVE(pf_altqs_inactive, altq, entries); +#ifdef __FreeBSD__ + if (altq->qname[0] =3D=3D 0 && altq->local_flags =3D=3D 0) { +#else if (altq->qname[0] =3D=3D 0) { +#endif /* detach and destroy the discipline */ error =3D altq_remove(altq); } else @@ -842,7 +850,11 @@ pf_commit_altq(u_int32_t ticket) =20 /* Attach new disciplines */ TAILQ_FOREACH(altq, pf_altqs_active, entries) { +#ifdef __FreeBSD__ + if (altq->qname[0] =3D=3D 0 && altq->local_flags =3D=3D 0) { +#else if (altq->qname[0] =3D=3D 0) { +#endif /* attach the discipline */ error =3D altq_pfattach(altq); if (error =3D=3D 0 && pf_altq_running) @@ -857,7 +869,11 @@ pf_commit_altq(u_int32_t ticket) /* Purge the old altq list */ while ((altq =3D TAILQ_FIRST(pf_altqs_inactive)) !=3D NULL) { TAILQ_REMOVE(pf_altqs_inactive, altq, entries); +#ifdef __FreeBSD__ + if (altq->qname[0] =3D=3D 0 && altq->local_flags =3D=3D 0) { +#else if (altq->qname[0] =3D=3D 0) { +#endif /* detach and destroy the discipline */ if (pf_altq_running) error =3D pf_disable_altq(altq); @@ -943,6 +959,91 @@ pf_disable_altq(struct pf_altq *altq) =20 return (error); } + +#ifdef __FreeBSD__ +void +pf_altq_ifnet_event(struct ifnet *ifp, int remove) +{ + struct ifnet *ifp1; + struct pf_altq *a1, *a2, *a3; + u_int32_t ticket; + int error =3D 0; + + DPFPRINTF(PF_DEBUG_MISC, ("altq: ifnet event %p %d\n", ifp, remove)); + /* Interrupt userland queue modifications */ + if (altqs_inactive_open) { + DPFPRINTF(PF_DEBUG_MISC, + ("altq: detach event preempted userland\n")); + pf_rollback_altq(ticket_altqs_inactive); + } + + /* Start new altq ruleset */ + if (pf_begin_altq(&ticket)) { + DPFPRINTF(PF_DEBUG_MISC, ("altq: pf_begin_altq failed\n")); + PF_UNLOCK(); + return; + } + /* Copy the current active set */ + TAILQ_FOREACH(a1, pf_altqs_active, entries) { + a2 =3D pool_get(&pf_altq_pl, PR_NOWAIT); + if (a2 =3D=3D NULL) { + error =3D ENOMEM; + break; + } + bcopy(a1, a2, sizeof(struct pf_altq)); + + DPFPRINTF(PF_DEBUG_MISC, ("altq: copy %s.%s\n", a2->ifname, + a2->qname)); + if (a2->qname[0] !=3D 0) { + if ((a2->qid =3D pf_qname2qid(a2->qname)) =3D=3D 0) { + error =3D EBUSY; + pool_put(&pf_altq_pl, a2); + break; + } + a2->altq_disc =3D NULL; + TAILQ_FOREACH(a3, pf_altqs_inactive, entries) { + if (strncmp(a3->ifname, a2->ifname, + IFNAMSIZ) =3D=3D 0 && a3->qname[0] =3D=3D 0) { + a2->altq_disc =3D a3->altq_disc; + break; + } + } + } + /* Deactivate the interface in question */ + a2->local_flags =3D 0; + if ((ifp1 =3D ifunit(a2->ifname)) =3D=3D NULL || + (remove && ifp1 =3D=3D ifp)) { + a2->local_flags |=3D PFALTQ_FLAG_IF_REMOVED; + DPFPRINTF(PF_DEBUG_MISC, + ("altq: no interface for %s.%s\n", a2->ifname, + a2->qname)); + } else { + PF_UNLOCK(); + error =3D altq_add(a2); + PF_LOCK(); + + if (ticket !=3D ticket_altqs_inactive) + error =3D EBUSY; + + if (error) { + pool_put(&pf_altq_pl, a2); + break; + } + } + DPFPRINTF(PF_DEBUG_MISC, ("altq: adding %s.%s\n", a2->ifname, + a2->qname)); + + TAILQ_INSERT_TAIL(pf_altqs_inactive, a2, entries); + } + + if (error !=3D 0) { + DPFPRINTF(PF_DEBUG_MISC, ("altq: copy failed %d\n", error)); + pf_rollback_altq(ticket); + } else { + pf_commit_altq(ticket); + } +} +#endif #endif /* ALTQ */ =20 int @@ -2273,7 +2374,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int fla= gs, struct proc *p) =20 /* enable all altq interfaces on active list */ TAILQ_FOREACH(altq, pf_altqs_active, entries) { +#ifdef __FreeBSD__ + if (altq->qname[0] =3D=3D 0 && + altq->local_flags =3D=3D 0) { +#else if (altq->qname[0] =3D=3D 0) { +#endif error =3D pf_enable_altq(altq); if (error !=3D 0) break; @@ -2290,7 +2396,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int fla= gs, struct proc *p) =20 /* disable all altq interfaces on active list */ TAILQ_FOREACH(altq, pf_altqs_active, entries) { +#ifdef __FreeBSD__ + if (altq->qname[0] =3D=3D 0 && + altq->local_flags =3D=3D 0) { +#else if (altq->qname[0] =3D=3D 0) { +#endif error =3D pf_disable_altq(altq); if (error !=3D 0) break; @@ -2316,6 +2427,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag= s, struct proc *p) break; } bcopy(&pa->altq, altq, sizeof(struct pf_altq)); +#ifdef __FreeBSD__ + altq->local_flags =3D 0; +#endif =20 /* * if this is for a queue, find the discipline and @@ -2327,6 +2441,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag= s, struct proc *p) pool_put(&pf_altq_pl, altq); break; } + altq->altq_disc =3D NULL; TAILQ_FOREACH(a, pf_altqs_inactive, entries) { if (strncmp(a->ifname, altq->ifname, IFNAMSIZ) =3D=3D 0 && a->qname[0] =3D=3D 0) { @@ -2337,11 +2452,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int fl= ags, struct proc *p) } =20 #ifdef __FreeBSD__ =2D PF_UNLOCK(); + struct ifnet *ifp; + + if ((ifp =3D ifunit(altq->ifname)) =3D=3D NULL) { + altq->local_flags |=3D PFALTQ_FLAG_IF_REMOVED; + } else { + PF_UNLOCK(); #endif =09 error =3D altq_add(altq); #ifdef __FreeBSD__ =2D PF_LOCK(); + PF_LOCK(); + } #endif if (error) { pool_put(&pf_altq_pl, altq); @@ -2414,6 +2535,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int fla= gs, struct proc *p) break; } #ifdef __FreeBSD__ + if (altq->local_flags !=3D 0) { + error =3D ENXIO; + break; + } PF_UNLOCK(); #endif error =3D altq_getqstats(altq, pq->buf, &nbytes); diff --git a/sys/contrib/pf/net/pfvar.h b/sys/contrib/pf/net/pfvar.h index fbc87e3..8673594 100644 =2D-- a/sys/contrib/pf/net/pfvar.h +++ b/sys/contrib/pf/net/pfvar.h @@ -1247,6 +1247,11 @@ struct pf_altq { u_int32_t parent_qid; /* parent queue id */ u_int32_t bandwidth; /* queue bandwidth */ u_int8_t priority; /* priority */ +#ifdef __FreeBSD__ + u_int8_t local_flags; /* dynamic interface */ +#define PFALTQ_FLAG_IF_REMOVED 0x01 +#define PFALTQ_FLAG_BW_UNKNOWN 0x02 +#endif u_int16_t qlimit; /* queue size limit */ u_int16_t flags; /* misc flags */ union { @@ -1574,6 +1579,9 @@ extern void pf_tbladdr_remove(struct pf_addr_wrap = *); extern void pf_tbladdr_copyout(struct pf_addr_wrap *); extern void pf_calc_skip_steps(struct pf_rulequeue *); #ifdef __FreeBSD__ +#ifdef ALTQ +extern void pf_altq_ifnet_event(struct ifnet *, int); +#endif extern uma_zone_t pf_src_tree_pl, pf_rule_pl; extern uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl; extern uma_zone_t pfr_ktable_pl, pfr_kentry_pl, pfr_kentry_pl2; --Boundary-01=_/GITHJDfvfmxyCv-- --nextPart2168564.eTSo7kHDG8 Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.4 (FreeBSD) iD8DBQBHTIHEXyyEoT62BG0RAg2RAJ9wdmOOzrXb7eQ/20TFk10RE/5jCQCfdR15 24jLZrm/1wWmZJGt8T8sGcU= =aSkr -----END PGP SIGNATURE----- --nextPart2168564.eTSo7kHDG8--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711272144.52511.max>