|
From: | Joe Eykholt |
Subject: | Re: [lwip-devel] LWIP_ASSERT at ip_output "p->ref == 1" |
Date: | Wed, 24 Oct 2012 09:50:32 -0700 |
User-agent: | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:15.0) Gecko/20120824 Thunderbird/15.0 |
A web search turned up this old post:I see the assert as well in lwip-1.4.0-rc1 (same as 1.4). In my case it occurs because the driver takes a ref after it gets the packet for output, and it hasn't released it yet (because the device is stuck). I think this is a legitimate thing to do so that the driver can free the packet. But now TCP is retransmitting the packet and it now has ref==2, one for TCP, and one for the previous call to the driver. Worse, to retransmit the packet, TCP sets p->payload back to point to the TCP header, but the driver still thinks it "owns" the packet and has permission to prepend headers, etc. My fix for this is to skip retransmission if the packet has more than 1 reference, assuming that the extra reference is by the driver. Do you see any problem with that? One issue might be if the driver does send the packet but doesn't free it right away. This would happen with device drivers that have large descriptor rings and don't free pbufs until sometime long after the transmission, but that would be presumably be done only on large memory systems with plenty of pbufs. Here's my patch: --- a/LwIP/ver1.4.0.rc1/src/core/tcp_out.c +++ b/LwIP/ver1.4.0.rc1/src/core/tcp_out.c @@ -1120,6 +1120,15 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); } + + /* + * If the reference count is more than 1, we assume the driver still + * has a reference and it is still queued to be sent from before, + * so we don't need to retransmit. + */ + if (seg->p->ref > 1) { + return; + } LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + seg->len)); (END) |
[Prev in Thread] | Current Thread | [Next in Thread] |