buglwIP - A Lightweight TCP/IP stack - Bugs: bug #27140, tcp/ip stack hang becouse remains...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

bug #27140: tcp/ip stack hang becouse remains a pbuf_free

Submitter:  juan schiavoni <jjsch>
Submitted:  Thu 30 Jul 2009 01:14:34 AM UTC
   
 
Category:  None Severity:  3 - Normal
Item Group:  Crash Error Status:  Invalid
Privacy:  Public Assigned to:  None
Open/Closed:  Closed Planned Release:  None
lwIP version:  CVS Head

Jump to the original submission

Tue 04 Aug 2009 12:31:31 PM UTC, comment #11: 

Hi, the change work fine, now the slow_timer is assigned to the tcpip_thread.

I need to know if there are a setting to limit the connection closed that are in time_wait? My solution was to change the TCP_MSL to 250 mS.

juan schiavoni <jjsch>
Tue 04 Aug 2009 12:10:13 AM UTC, comment #10: 

Hi, tomorrow I will do the change for tcpip_input.


   /* if( ERR_OK != ethernet_input( p, netif ) )
    {
      pbuf_free(p);
      p = NULL;
    }
    */

    /* points to packet payload, which starts with an Ethernet header */
    ethhdr = p->payload;

    switch( htons( ethhdr->type ) )
    {
      /* IP or ARP packet? */
case ETHTYPE_IP:
case ETHTYPE_ARP:
#if PPPOE_SUPPORT
     /* PPPoE packet? */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
    /* full packet send to tcpip_thread to process */
if( netif->input( p, netif ) != ERR_OK )
{
  LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
  pbuf_free(p);
  p = NULL;
}
        break;

        default:
          pbuf_free(p);
         p = NULL;
        break;
    }

juan schiavoni <jjsch>
Mon 03 Aug 2009 07:17:11 PM UTC, comment #9: 

As to the first one, the error is calling ethernetif_input from your input function. Call tcpip_input instead.

As to the second one, I don't think I understand where the problem is.

Simon Goldschmidt <goldsimon>
Group administrator
Mon 03 Aug 2009 06:08:41 PM UTC, comment #8: 

Hi, Today I could do more test with the hardware. The error has two point, the first one is that tcp_timer_needed is called from the ethernetif_input function, that run in a diferent thread that tcpip_thread. The second one is that tcp_ticks of tcp_slowtmr function, increase the timeout, to free the memory for a connection already closed.

If disable the timer by thread, and increase the tcp_tick in 500 by time, the webserver run fine, but I understand that this is not a good solution. Could you give some help?

I put the source code of the ethernetif_input:

/**

  • This function should be called when a packet is ready to be read
  • from the interface. It uses the function low_level_input() that
  • should handle the actual reception of bytes from the network
  • interface. Then the type of the received packet is determined and
  • the appropriate input function is called.

 *

  • @param netif the lwip network interface structure for this ethernetif

 */
static void ethernetif_input(void * pvParameters)
{
  struct netif      netif = (struct netif )pvParameters;
  struct pbuf       *p;


  for( ;; )
  {
    do
    {
      /* move received packet into a new pbuf */
      p = low_level_input( netif );
      if( p == NULL )
      {
        /* No packet could be read.  Wait a for an interrupt to tell us
        there is more data available. */
        vMACBWaitForInput(100);
      }
    }while( p == NULL );

    if( ERR_OK != ethernet_input( p, netif ) )
    {
      pbuf_free(p);
      p = NULL;
    }
  }
}



juan schiavoni <jjsch>
Mon 03 Aug 2009 10:40:25 AM UTC, comment #7: 

I'm closing this as it looks like it's down to the port not calling the tcp timers properly.  Please re-open if it turns out to be an lwIP problem.

Kieran Mansley <kieranm>
Group Member
Mon 03 Aug 2009 06:48:06 AM UTC, comment #6: 

Can we have any update on this one? Is it really a bug? Does it interfere with 1.3.1?

Simon Goldschmidt <goldsimon>
Group administrator
Fri 31 Jul 2009 02:27:22 PM UTC, comment #5: 

The port should arrange for tcp_tmr() to be called every 250ms (I think)

Kieran Mansley <kieranm>
Group Member
Fri 31 Jul 2009 02:01:02 PM UTC, comment #4: 

thanks for the explanation. I did further research, and found that buffer is not freed when a new connection is established, because the tcp_tmr never runs. I think the problem is an error in the avr32 uc porting.

struct tcp_pcb *
tcp_alloc(u8_t prio)
{
  struct tcp_pcb *pcb;
  u32_t iss;

  pcb = memp_malloc(MEMP_TCP_PCB);  -> this buffer is no freed
  ....
  ....
  return pcb;
}

I may be abusing of your patience, but please could you explain the way the timeout works?

Thanks a lot
Juan

juan schiavoni <jjsch>
Fri 31 Jul 2009 09:00:09 AM UTC, comment #3: 

netconn_write doesn't allocate a pbuf. 

The data to write it passed through the message box to the raw API which will call do_write()->do_writemore()->tcp_write()->tcp_enqueue() and this will then create a pbuf if there is space to enqueue the packet. There are a few reasons why it might not get this far, so make sure that netconn_write isn't returning an error.

If you're sure it's getting enqueued, then the pbuf would normally be freed by the stack once the packet has been acknowledged by the other end - see the call to tcp_seg_free() in tcp_receive().  If you're not getting this acknowledgement, that could explain why the pbuf is not freed.

Kieran Mansley <kieranm>
Group Member
Thu 30 Jul 2009 04:53:41 PM UTC, comment #2: 

Hi Kieran, the missing pbuf_free is from netconn_write. You could give me son advice where in the source code is the free of buffer allocated for the netconn_write?

Regards,
Juan

juan schiavoni <jjsch>
Thu 30 Jul 2009 01:35:52 PM UTC, comment #1: 

It's not clear to me what's going wrong.  Do you know were the missing pbuf_free() is?

Kieran Mansley <kieranm>
Group Member
Thu 30 Jul 2009 01:14:34 AM UTC, original submission:  

Hi, I use the lwip stack ported to avr32 uc. I run the BasicWeb example for FreeRtos, and always hang at 100 hits. In the debug log I see that never free a pbuffer of the netconn_write. I use the CVS version 1.3.2.rc with MEM_LIBC_MALLOC = 1, MEMP_MEM_MALLOC = 1, and MEM_ALIGNMENT = 4.

The log:

pbuf_alloc(length=479)
 -> Get from webrowser
pbuf_alloc: allocated pbuf

pbuf_alloc(length=479) == 36872

update_arp_entry()
 
pbuf_alloc(length=44)
 -> buffer of the ok answer.
pbuf_alloc(length=44) == 51504

pbuf_alloc(length=248)
 -> buffer of hit counter
pbuf_alloc(length=248) == 51624

pbuf_alloc(length=292)
 -> buffer of task list.
pbuf_alloc(length=292) == 51952

pbuf_free(36872)
 -> free reception buffer.
pbuf_alloc(length=0)
 -> close
pbuf_alloc(length=0) == 36872

pbuf_alloc(length=60)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=60) == 52320

update_arp_entry()

pbuf_free(51504)
 -> free first write
pbuf_free(51624)
 -> free second write
pbuf_free(52320)
 
pbuf_alloc(length=60)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=60) == 51504

update_arp_entry()

pbuf_free(36872)

pbuf_free(51504)

pbuf_alloc(length=60)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=60) == 36872

update_arp_entry()

pbuf_alloc(length=20)

pbuf_alloc(length=20) == 51176

pbuf_free(51176)

pbuf_free(36872)

pbuf_alloc(length=62)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=62) == 36896

update_arp_entry()

pbuf_alloc(length=4)

pbuf_alloc(length=4) == 51352

pbuf_free(36896)

pbuf_alloc(length=60)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=60) == 36896

update_arp_entry()

pbuf_free(51352)

pbuf_free(36896)

pbuf_alloc(length=479)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=479) == 36896

update_arp_entry()

pbuf_alloc(length=44)

pbuf_alloc(length=44) == 51680

pbuf_alloc(length=248)

pbuf_alloc(length=248) == 51800

pbuf_alloc(length=292)

pbuf_alloc(length=292) == 52128

pbuf_free(36896)

pbuf_alloc(length=0)

pbuf_alloc(length=0) == 36896

pbuf_alloc(length=60)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=60) == 52496

update_arp_entry()

pbuf_free(51680)

pbuf_free(51800)

pbuf_free(52496)

pbuf_alloc(length=60)

pbuf_alloc: allocated pbuf

pbuf_alloc(length=60) == 51680

update_arp_entry()

pbuf_free(36896)

pbuf_free(51680)


The third write buffer never free.

/*! brief parse the incoming request

  •         parse the HTML request and send file

 *

  •  param pxNetCon   Input. The netconn to use to send and receive data.

 *
 */
static void prvweb_ParseHTMLRequest( struct netconn *pxNetCon )
{
struct netbuf *pxRxBuffer;
portCHAR *pcRxString;
unsigned portSHORT usLength;
static unsigned portLONG ulPageHits = 0;
u16_t len;

/* We expect to immediately get data. */
pxRxBuffer = netconn_recv( pxNetCon );

if( pxRxBuffer != NULL )
{
/* Where is the data? */
netbuf_data( pxRxBuffer, ( void * ) &pcRxString, &usLength );

/* Is this a GET?  We don't handle anything else. */
if(( NULL != pcRxString               )
&& ( !strncmp( pcRxString, "GET", 3 ) ))
{
/* Update the hit count. */
ulPageHits++;
sprintf( cPageHits, "%d", (int)ulPageHits );

len = strlen( webHTTP_OK );

/* Write out the HTTP OK header. */
netconn_write( pxNetCon, webHTTP_OK, (u16_t) len, NETCONN_COPY );

/* Generate the dynamic page... First the page header. */
strcpy( cDynamicPage, webHTML_START );

/* ... Then the hit count... */
strcat( cDynamicPage, cPageHits );
strcat( cDynamicPage, "<p><pre>Task          State  Priority  Stack #<br>************************************************<br>" );

len = strlen( cDynamicPage );

netconn_write( pxNetCon, cDynamicPage, len, NETCONN_COPY );

/* ... Then the list of tasks and their status... */
vTaskList( ( signed portCHAR * ) cDynamicPage + strlen( cDynamicPage ) );
vTaskList( ( signed portCHAR * ) cDynamicPage );

/* ... Finally the page footer. */
strcat( cDynamicPage, webHTML_END );

len = strlen( cDynamicPage );

/* Write out the dynamically generated page. */
netconn_write( pxNetCon, cDynamicPage, len, NETCONN_COPY );
}
netbuf_delete( pxRxBuffer );
}

netconn_close( pxNetCon );
netconn_delete( pxNetCon );
}

juan schiavoni <jjsch>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by goldsimon (Posted a comment)
  • -email is unavailable- added by kieranm (Posted a comment)
  • -email is unavailable- added by jjsch
  • -email is unavailable- added by jjsch (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

     

    Follow 4 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2009-08-03 kieranm StatusNone Invalid
        Open/ClosedOpen Closed
    2009-07-31 kieranm Assigned to#67738 None
    2009-07-30 jjsch Carbon-Copy- Added jjsch

    Back to the top

    Powered by Savane 3.13-3230.
    Corresponding source code