lwip-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lwip-devel] LWIP_ASSERT at ip_output "p->ref == 1"


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:
From: Simon Goldschmidt
Subject: Re: [lwip-users] LWIP_ASSERT at ip_output is failed.
Date: Wed, 07 Mar 2012 08:55:29 +0100

Segge <address@hidden> wrote:
> I have an alert message during run-time:
> Assertion "p->ref == 1" failed at line 755 in
> D:/lwIP/Library/src/core/ipv4/ip.c
> Assertion "p->ref == 1" failed at line 599 in
> D:/lwIP/Library/src/core/ipv4/ip.c
> 
> The messages are always in pair.

Does that mean your target continues to run although an assertion failed? How 
else would you see the messages in pairs?

> What does it mean? 
> Is it critical?
> Is it possible to re-configure the LwIP to prevent these errors? 

It means that the pbuf you passed to one of the send functions has a reference 
count of != 1. If it's 0, that's an error as it means the pbuf has already been 
freed. If it's > 1, that's an API violation: as the pbuf's payload gets changed 
while being sent, there may be only one reference to that pbuf. Also, a pbuf 
that has been passed to a send function may not be reused by your application 
unless that send function returned an error.

Simon 
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)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]