lwip-users
[Top][All Lists]
Advanced

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

Re: [lwip-users] UDP socket thread safe problem - arp proccess error if


From: Darius Babrauskas
Subject: Re: [lwip-users] UDP socket thread safe problem - arp proccess error if ARP_QUEUEING 1
Date: Fri, 23 Mar 2012 10:50:45 +0200

Hi all,

Possible, I found error in ARP proccess LWIP 1.2 version . Maybe this error exists and in new versions 1.4
I tested it with udp raw api, but think  udp,tcp socket have same problem.

My problem was:
#define ARP_QUEUEING 1
Currently I replace udp socket in one thread with RAW api functions. Now select function in other thread working ok. But tread with RAW udp connection work not good. Because I get first respond in call_back function after 10s. (because send IP not in arp table and send function packet is queueing)

Problem in etharp_query function, which send etharp_request if not in arp table. After send etharp_request if defined ARP_QUEUEING 1 , udp packet queued .

Problem are, that etharp_request very fast - and it executed before udp packet queued. So queued packet not send, when get arp response. It send later, maybe after arp timer, or when receiving other packet.

To resolve this problem, posible need use semaphores to protect arp table.
But my successful test was move etharp_request code after "packet queued" code. Now I get first responce very fast. Before 10s, after <100ms.


err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
{
 struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
 err_t result = ERR_MEM;
 s8_t i; /* ARP entry index */
 u8_t k; /* Ethernet address octet index */

 /* non-unicast address? */
 if (ip_addr_isbroadcast(ipaddr, netif) ||
     ip_addr_ismulticast(ipaddr) ||
     ip_addr_isany(ipaddr)) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
   return ERR_ARG;
 }

 /* find entry in ARP cache, ask to create entry if queueing packet */
 i = find_entry(ipaddr, ETHARP_TRY_HARD);

 /* could not find or create entry? */
 if (i < 0)
 {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not create ARP entry\n")); if (q) LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: packet dropped\n"));
   return (err_t)i;
 }

 /* mark a fresh entry as pending (we just sent a request) */
 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
   arp_table[i].state = ETHARP_STATE_PENDING;
 }

 /* { i is either a STABLE or (new or existing) PENDING entry } */
 LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
 ((arp_table[i].state == ETHARP_STATE_PENDING) ||
  (arp_table[i].state == ETHARP_STATE_STABLE)));

#if ARP_QUEUEING

#else
 /* do we have a pending entry? or an implicit query request? */
 if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
   /* try to resolve it; send out ARP request */
   result = etharp_request(netif, ipaddr);
 }
#endif


 /* packet given? */
 if (q != NULL) {
   /* stable entry? */
   if (arp_table[i].state == ETHARP_STATE_STABLE) {
     /* we have a valid IP->Ethernet address mapping,
      * fill in the Ethernet header for the outgoing packet */
     struct eth_hdr *ethhdr = q->payload;
     k = netif->hwaddr_len;
     while(k > 0) {
       k--;
       ethhdr->dest.addr[k] = arp_table[i].ethaddr.addr[k];
       ethhdr->src.addr[k]  = srcaddr->addr[k];
     }
     ethhdr->type = htons(ETHTYPE_IP);
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending packet %p\n", (void *)q));
     /* send the packet */
     result = netif->linkoutput(netif, q);
   /* pending entry? (either just created or already pending */
   } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
#if ARP_QUEUEING /* queue the given q packet */
     struct pbuf *p;
     /* copy any PBUF_REF referenced payloads into PBUF_RAM */
     /* (the caller of lwIP assumes the referenced payload can be
      * freed after it returns from the lwIP call that brought us here) */
     p = pbuf_take(q);
     /* packet could be taken over? */
     if (p != NULL) {
       /* queue packet ... */
       if (arp_table[i].p == NULL) {
         /* ... in the empty queue */
         pbuf_ref(p);
         arp_table[i].p = p;
#if 0 /* multi-packet-queueing disabled, see bug #11400 */
       } else {
         /* ... at tail of non-empty queue */
         pbuf_queue(arp_table[i].p, p);
#endif
       }
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
       result = ERR_OK;
     } else {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
       /* { result == ERR_MEM } through initialization */
     }
#else /* ARP_QUEUEING == 0 */
     /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
     /* { result == ERR_MEM } through initialization */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
#endif
   }
 }
#if ARP_QUEUEING
 /*darius: moved her*/
 if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
   /* try to resolve it; send out ARP request */
//result = etharp_request(netif, ipaddr);//rezultatui itakos tures jeigu q == NULL ir arp_table[i].state == ETHARP_STATE_STABLE
   err_t result_etharp_request = etharp_request(netif, ipaddr);
   if( (q == NULL) || arp_table[i].state != ETHARP_STATE_STABLE )
    result=result_etharp_request;

if( (q != NULL) && (arp_table[i].state == ETHARP_STATE_STABLE || arp_table[i].state == ETHARP_STATE_PENDING ) )
    ; //not change result
   else
    result=result_etharp_request;


 }
#endif

 return result;
}






----- Original Message ----- From: "Darius Babrauskas" <address@hidden>
To: "Mailing list for lwIP users" <address@hidden>
Sent: Wednesday, March 07, 2012 10:50 AM
Subject: Re: [lwip-users] UDP socket thread safe problem


serialise your use of lwIP sockets into a single thread.
Yes I think about this idea. But I do not know, how 2 udp socket working in one thread with select function. Because in my system used FreeRtos and Lwip. select function using FreeRtos task timeout struct. Maybe 2 udp socket can't work with select function in one thread?

Currently I replace udp socket in one thread with RAW api functions. Now select function in other thread working ok. But tread with RAW udp connection work not good. Because I get first respond in call_back function after 10s. (because send IP not in arp table and send function packet is queueing)


LWIP options

#define SYS_LIGHTWEIGHT_PROT 1

#define ARP_QUEUEING 1

Maybe need manualy refresh arp request quene?


----- Original Message ----- From: "Kieran Mansley" <address@hidden>
To: "Mailing list for lwIP users" <address@hidden>
Sent: Tuesday, March 06, 2012 9:58 PM
Subject: Re: [lwip-users] UDP socket thread safe problem



On 23 Feb 2012, at 08:34, Darius Babrauskas wrote:

I have old project with LWIP v.1.2. for AVR32.

Problem:

2 threads A and B . Each treads have 1 UDP socket with No( 0 and 1 ). Each thread have self timeout struct.

I think if you don't want to update to the latest version of lwIP you will probably have to serialise your use of lwIP sockets into a single thread.

Kieran
_______________________________________________
lwip-users mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/lwip-users


_______________________________________________
lwip-users mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/lwip-users




reply via email to

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