lwip-users
[Top][All Lists]
Advanced

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

Re: [lwip-users] UDP packet sending problem


From: patrick Deflandre
Subject: Re: [lwip-users] UDP packet sending problem
Date: Thu, 2 Jul 2009 14:30:32 +0200



2009/6/29 Kieran Mansley <address@hidden>

It is not your problem for sure, as lwIP receives the UDP packet, thinks
the checksum is correct, and sends a response.  The response gets lots
somewhere in etharp_output() before making it onto the network though.

I notice that in the udp_echo.trace.txt there is the following:

<LF>find_entry: selecting empty entry 1
<LF>etharp_request: sending ARP request.etharp_raw: sending raw ARP
packet.etharp_query: queued packet 215bf0 on ARP entry 1

This is odd for two reasons: (i) it should already have an entry for the
PC's MAC address as it's updated that entry lots already from the other
ARP requests seen on the network earlier; and (ii) the packet it sends
is not an ARP request for the PC's MAC, but a gratuitous ARP of its own
MAC.  I think there is definitely something going wrong here.


So I find where it was not working. I will try to explain why it doesn't work, sorry if it  is not as clear as it should but my English is a bit poor...

As you said, the response was lost somewhere in etharp_output. This is actually done in ip_output_if (file src/core/ipv4/ip.c line 510) because lwIP then write the destination ip in the ip header with the use of the pointer dest.

This pointer was obtained at the beginning of the process by the function and macro use :
    buf = netconn_recv(conn);
    addr = netbuf_fromaddr(buf);

addr is a copy of the buf->addr which is pointing on the source ip header field. The buf is created by the netconn_recv call.

We use addr to connect to the remote port with netconn_connect(conn, addr, port)
But if we don't set this buf->addr to NULL , then it will be used by the do_send function (src/api/api_msg.c line 881) to send the packet.

But as buf->addr is a pointer to the source ip header, this value will be overwrite by ip_output_if when writing the new source in the new header ip (file src/core/ipv4/ip.c line 510). So the dest in this function which is use at the end on the call netif->output(netif, p, dest) will be in fact the source ip. It then result on an ARP gratuitous request which is never reply and a lost of the packet.

So here is the solution :
===================

Add a line in the contrib/ports/unix/proj/unixsim/apps/udpecho.c example which set buf->addr to NULL :

void
udpecho_thread(void *arg)
{
  static struct netconn *conn;
  static struct netbuf *buf;
  static struct ip_addr *addr;
  static unsigned short port;
  char buffer[4096];
 
  conn = netconn_new(NETCONN_UDP);
  netconn_bind(conn, NULL, 7);

  while (1) {
    buf = netconn_recv(conn);
    addr = netbuf_fromaddr(buf);
    port = netbuf_fromport(buf);
    netconn_connect(conn, addr, port);
    netbuf_copy(buf, buffer, buf->p->tot_len);
    buffer[buf->p->tot_len] = '\0';

   buf->addr = NULL; // we must set addr to NULL, because addr is a pointer on the source ip header which
                      // will be overwrite by ip_output_if function. This lead to an ARP gratuitous request
                      // and a failure to send the buf.
                      // if we set buf-addr to NULL, then we force the do_send function to use the
                      // udp_send which then will use the pcb->remote_ip destination ip

    netconn_send(conn, buf);
    printf("got %s\n", buffer);
    netbuf_delete(buf);
  }
}


I didn't try to compile and test this example on a Linux station, but it does'nt work without this modification on my embedded target.

If you have any suggestions on what should be better to do, please let me know.

Thanks to Kieran for it's very valuated help.

Patrick.


reply via email to

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