On Wed, Dec 13, 2000 at 09:59:06PM +0000, Dag Brattli wrote:
> Hi,
>
> To me it sounds like somebody have sent a frame down the IrDA stack, that
> is still one somebodies list, or somebody is some how touching the skb next pointer
> after it's been passed down the stack. The frame has been queued by IrLAP waiting
> for ack, but somebody is changing the list pointer (next) while it's sitting in this
>queue.
> So when an incomming frame acks this frame, and IrLAP tries to dequeue it, then
> it will try to follow that NULL pointer.
>
> Are you sure nobody changes the skb after it's been passed down the stack? Maybe
> it's sitting on somebodies list further up, or somebody clears it's struct or
>something!?
>
> -- Dag
Good point ! Unfortunately, we will have to find another thing
to blame.
If you look carefully at the code in skbuff.h/skbuff.c and co,
the only way to have next == NULL is if someone free, dequeue or
unlink the skb. I can't see any other operation setting this stuff to
NULL.
As skb_dequeue(), skb_dequeue_tail() explicitely check that
the skb is in the relevant list, and kfree_skb() check explicitely
that it is not in a list (log message in that case), we must assume
that it would happen through an skb_unlink().
Both IrDA and ppp doesn't use skb_unlink() :-(
We could still assume kfree_skb() and assume that the relevant
log messages were cut out of the report. Hum...
Now, a little analisys of IrNET :
Packets are sent to IrNET by ppp_generic.c. There are two
places doing that, and they look like :
------------------------------
skb = skb_dequeue(&pch->file.xq);
if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
/* put the packet back and try again later */
skb_queue_head(&pch->file.xq, skb);
break;
}
------------------------------
And
------------------------------
while (ppp->xmit_pending == 0
&& (skb = skb_dequeue(&ppp->file.xq)) != 0)
ppp_send_frame(ppp, skb);
[...]
ppp->xmit_pending = skb;
ppp_push(ppp);
[...]
struct sk_buff *skb = ppp->xmit_pending;
[...]
if (pch->chan->ops->start_xmit(pch->chan, skb))
ppp->xmit_pending = 0;
------------------------------
They both use skb_dequeue() and seem proper...
And in IrNET, we have :
---------------------
/* Is the skb headroom large enough to contain all IrDA-headers? */
if((skb_headroom(skb) < (ap->max_header_size + needaddr)) ||
(skb_shared(skb)))
{
struct sk_buff * new_skb;
DEBUG(PPP_INFO, "Reallocating skb\n");
---------------------
So, if the skb is shared, we don't pass it to IrDA.
One sure way to tell if the skb is still in a list when
comming to IrNET would be to force reallocation above and see if kfree
complains about it.
Anyway, I think I should be able to see this bug it in my
testing ?
Jean
_______________________________________________
Linux-IrDA mailing list - [EMAIL PROTECTED]
http://www.pasta.cs.UiT.No/mailman/listinfo/linux-irda