On Wed, May 26, 2010 at 10:06:54AM +0100, Stuart Henderson wrote:
> On 2010/05/21 23:54, Chris Bayly wrote:
> > Okay, I believe I've finally simplified this down to something manageable,
> > and hopefully a heck of alot more repeatable.
> >
> > I have a second Alix 3D3 board running -current as of the 19th.
> >
> > I can make it start leaking mbufs with the following setup.
> >
> > - Completely bone stock OpenBSD install.
> > - At install time setup one interface (vr0) as dhcp
> > - After install, issue the following commands:
> >
> > ifconfig vr1 up # Note: no cable connected on vr1
> > ifconfig bridge0 add vr0
> > ifconfig bridge0 add vr1
> > ifconfig bridge0 up
> >
> > netstat -m # will now show an increasing number of mbuf 2048 byte clusters
> > # being used
>
> in vr_start() [if_vr.c:1228] we have this
>
> if (ifp->if_flags & IFF_OACTIVE || sc->vr_link == 0)
> return;
>
> the sc->vr_link check was added to prevent watchdog timeouts,
> but because these frames aren't transmitted we have a leak.
>
> not sure if this is the best way, but it seems to do the trick:
>
> Index: if_vr.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_vr.c,v
> retrieving revision 1.105
> diff -u -p -r1.105 if_vr.c
> --- if_vr.c 19 May 2010 15:27:35 -0000 1.105
> +++ if_vr.c 26 May 2010 09:05:51 -0000
> @@ -1225,7 +1225,7 @@ vr_start(struct ifnet *ifp)
>
> sc = ifp->if_softc;
>
> - if (ifp->if_flags & IFF_OACTIVE || sc->vr_link == 0)
> + if (ifp->if_flags & IFF_OACTIVE)
> return;
>
> cur_tx = sc->vr_cdata.vr_tx_prod;
> @@ -1233,6 +1233,11 @@ vr_start(struct ifnet *ifp)
> IFQ_DEQUEUE(&ifp->if_snd, m_head);
> if (m_head == NULL)
> break;
> + /* transmitting without link results in watchdog timeouts */
> + if (sc->vr_link == 0) {
> + m_freem(m_head);
> + return;
> + }
>
> /* Pack the data into the descriptor. */
> if (vr_encap(sc, cur_tx, m_head)) {
>
Hmm. The IFQ should have a limit and when reaching that packets will be
dropped. So after 256 packets no more packets should leak.
Unless something is calling IF_ENQUEUE() without checking IF_QFULL() first.
Ugh, the these ifq makros are stupid.
Still I think the current behaviour is strange and your diff makes more
sense. Any idea why vr(4) is using IFQ_DEQUEUE() + IF_PREPEND instead of
doing the IFQ_POLL(), IFQ_DEQUEUE() dance?
--
:wq Claudio