crash on a lot of outgoing packets

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

crash on a lot of outgoing packets

kyle treleaven
Hi all,

I'm using the RAW api, in a Xilinx port of lwip to their ppc405 in
virtex4 FPGA.  I mimicked the following process for sending out data
from a basic echo server example (there seems to be a real scarcity of
raw api examples out there).  The whole thing works ok, but if I start
trying to send packets faster than they can actually go out, I go into
an infinite loop of bad pbuf_alloc's.  My short term goal is to make
the thing not crash like that, because my application can easily wait
for buffers to clear up before proceeding.  But they don't seem to
want to clear themselves out.  In the long term, I'd also like to
increase my throughput, because I have a feeling that the code below
is less than optimum-- for one, I think the data changes pbuf hands a
number of times before it actually gets out.

Thanks in advance,
Kyle


***** SENDING SNIPPET *****
{
  p = pbuf_alloc( PBUF_TRANSPORT, out_idx, PBUF_POOL );
  if ( p == NULL )
  {
    xil_printf( "bad pbuf_alloc.\r\n" );
    tcp_send_buf( pcb, state );
    return;
  }

  b_ptr = out_buffer;
  /* assume that data and packet will be flush. */
  /* should be a good assumption. */
  for ( q = p; q != NULL; q = q->next )
  {
    for ( i=0; i < q->len; i++ )
      ((u8_t *)q->payload)[i] = *b_ptr++;
  }
       
  if ( state->p_out )
    pbuf_chain( state->p_out, p );
  else
    state->p_out = p;

  tcp_send_buf( pcb, state );
}

               
***** tcp_send_buf *****
tcp_send_buf(struct tcp_pcb *pcb, struct tcp_server_state *state)
{
  struct pbuf *q;
  if ( state == NULL )
  {
    tcp_close( pcb );
    return;
  }

  while ( q = state->p_out )
  {
    state->p_out = pbuf_dechain(q);
    if( tcp_write( pcb, q->payload, q->len, 1 ) == ERR_MEM )
    {
      pbuf_chain(q, state->p_out);
      state->p_out = q;
      break;
    }
    pbuf_free(q);
  }
  tcp_output( pcb );
}


_______________________________________________
lwip-users mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: crash on a lot of outgoing packets

Leon Woestenberg
Hello Kyle,

kyle treleaven wrote:

>Hi all,
>
>I'm using the RAW api, in a Xilinx port of lwip to their ppc405 in
>virtex4 FPGA.  I mimicked the following process for sending out data
>from a basic echo server example (there seems to be a real scarcity of
>raw api examples out there).  The whole thing works ok, but if I start
>trying to send packets faster than they can actually go out, I go into
>an infinite loop of bad pbuf_alloc's.
>
Two things here:

1) Infinite? Not good. Your Ethernet outgoing queue should eventually
free the pbufs that were put on the wire and memory
should be available again.

2) Somewhere you should make a blocking call that waits for your
Ethernet queue to become non-full again, as lwIP does
not know about this. Typically, you would wait for an interrupt from the
MAC if you work async, or just block until room
is available in the MAC before you submit the packet to it.

Regards,

Leon.


_______________________________________________
lwip-users mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: crash on a lot of outgoing packets

Sathya Thammanur
Hi Kyle,
One thing that can be done to send the data fast is to keep checking the TCP send buffer to see if how much space is left. Based on the amount of space left, the tcp_write() function can be called to send more data. Here is a snippet of a send function:

void
send_data(struct tcp_pcb *pcb, struct echo_state *ps)
{
  err_t err = ERR_OK;
  u16_t len;

  /* We cannot send more data than space available in the send
     buffer. */    
  if (tcp_sndbuf(pcb) < ps->left) {
    len = tcp_sndbuf(pcb);
  } else {
    len = ps->left;
  }

  if (len > 0) {
    err = tcp_write(pcb, ps->buf_p, len, 1);
  }

}

Keep track of the data sent in the echo_state variable and update the state in the echo_sent function that would be called by lwIP whenever an acknowledgement has been received for data sent. The send_data() function can be called more frequently that will cause more data to be sent as and where is space available in the TCP send buffer.

Hope this helps

Sathya





On 12/14/05, Leon Woestenberg <[hidden email]> wrote:
Hello Kyle,

kyle treleaven wrote:

>Hi all,
>
>I'm using the RAW api, in a Xilinx port of lwip to their ppc405 in
>virtex4 FPGA.  I mimicked the following process for sending out data
>from a basic echo server example (there seems to be a real scarcity of
>raw api examples out there).  The whole thing works ok, but if I start
>trying to send packets faster than they can actually go out, I go into
>an infinite loop of bad pbuf_alloc's.
>
Two things here:

1) Infinite? Not good. Your Ethernet outgoing queue should eventually
free the pbufs that were put on the wire and memory
should be available again.

2) Somewhere you should make a blocking call that waits for your
Ethernet queue to become non-full again, as lwIP does
not know about this. Typically, you would wait for an interrupt from the
MAC if you work async, or just block until room
is available in the MAC before you submit the packet to it.

Regards,

Leon.


_______________________________________________
lwip-users mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/lwip-users


_______________________________________________
lwip-users mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/lwip-users
Reply | Threaded
Open this post in threaded view
|

Re: crash on a lot of outgoing packets

Christiaan Simons
In reply to this post by kyle treleaven

Note: I'm posting this to the lwip-ussers list again,
there were some mail problems earlier...

Kyle Treleaven wrote:

> I have a few questions though.  First, it seems to me that the new
> echo server will only keep a connection open that is constantly
> active.  Is that correct?

Yes, otherwise clients could eat up the server resources
if connections stay open infinitely.

> Second, as far as the transmit goes I've
> noticed two major changes:  1) it blocks on pbuf_free to make
> absolutely sure it gets freed,

Yes, this is to ensure it really gets freed. The return value must be 0.

> and 2) there's a pbuf_ref call on the
> new state chain, es->p.  First, what would cause a pbuf not to free?

The ref count not being 1.

> And I guess my real question is, what is the pbuf_ref doing?

If there are multiple references (pointers) to the pbuf,
and you call pbuf_free, the ref counter is decremented.
A pbuf_free on the last reference may actually perform the
deallocation.

This is explained a bit further in the comments in lwip/src/core/pbuf.c

Actually I "abuse" the pbuf_ref increment to chop pbufs at
the head of the chain.

Regards,

Christiaan Simons

Hardware / Software Engineer
Axon Digital Design

+31 (0)13 511 66 66
+31 (0)13 511 41 51

http://www.axon.tv


This email and any files transmitted with it are confidential and intended
solely for the use of the individual or entity to whom they are addressed.
If you have received this email in error please notify the system manager.
This message contains confidential information and is intended only for the
individual named.  If you are not the named addressee you should not
disseminate, distribute or copy this e-mail.



_______________________________________________
lwip-users mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/lwip-users