[Top][All Lists]
[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