[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lwip-users] Dead PCB-problem when IP-address changes
From: |
Anders Carlman |
Subject: |
[lwip-users] Dead PCB-problem when IP-address changes |
Date: |
Fri, 28 Mar 2003 12:08:00 +0100 |
I recently discovered an unpleasant pitfall when i made a small test program
with DHCP-client-functionality. However, although the problems can arise when
using DHCP, I believe the solution should be applied on a "lower level", since
the problems can occur also when using (and changing) a static IP-address...
Here's what happened:
1. My test program first initialized the netif with a default, static IP-address
2. Then the DHCP was started.
3. Immidiately after that a connection was established and some data was
received (using blocking sockets)...
What then happened when the program was started was that in the middle of
receiving data, the program suddenly froze, and nothing more happened. After
some digging I found the reason: The binding of the dhcp-supplied address
wasn't complete until a while after the connection had already been
established. So the connection was made using the "old" static IP-address and
when the local address suddenly changed, the data to the "old" address was
discarded, which explained the freezing.
The problem here is not that the connection itself is destroyed, of course you
can't expect a TCP connection to "survive" an address change. However, the way
active connections (pcb:s) are handled at address changes, i.e. not handled at
all, is a problem. In some cases tcp calls to a "dead" pcb will simply return
with an error, which is OK. But in other cases, e.g. blocking accept and
receive calls, the application will enter a "waiting forever" deadlock, which
is quite bad... In the case of my test program the problem could be avoided by
wating until the dhcp state was "bound", before doing the connection. However
leases can expire and renewals can occur at any time, and I'm sure there could
be other scenarios too, when the IP-address is changed in an asynchronous
fashion (for example by a manual call to netif_set_ipaddr())...
I think the following is a good solution:
In the netif_set_ipaddr()-function some code can be added that aborts active
pcbs that belongs to the IP address of the netif, before the address is
actually changed. The abort should be made by calling tcp_abort()-for all
related pcbs. tcp_abort() will not only remove the pcbs, but it will also call
the error-callback functions, telling the "listeners" that the connection has
been aborted. In the socket case, this will "unlock" all blocking calls and
make them return with an error, thus preventing deadlock situations, like the
one that happened to me. When it comes to listening PCB:s, I believe they don't
have to be aborted, instead the listening address of related PCB:s is simply
changed to the "new" address. Look at my alternative implementation of
netif_set_ipaddr():
/*-----------------------------------------------------------------------------------*/
void
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
{
// Handling of obsolete pcbs
struct tcp_pcb *pcb;
struct tcp_pcb_listen *lpcb;
pcb=tcp_active_pcbs;
while(pcb != NULL)
{
if(ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr)))
{
// The PCB is connected using the old ipaddr and must be aborted
struct tcp_pcb *next=pcb->next;
tcp_abort(pcb);
pcb=next;
}
else
pcb=pcb->next;
}
for(lpcb = tcp_listen_pcbs; lpcb != NULL; lpcb = lpcb->next)
{
if(ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))
{
// The PCB is listening to the old ipaddr and is set to listen to the
new one instead
ip_addr_set(&(lpcb->local_ip), ipaddr);
}
}
ip_addr_set(&(netif->ip_addr), ipaddr);
DEBUGF(NETIF_DEBUG, ("netif: setting IP address of interface %c%c to
%d.%d.%d.%d\n",
netif->name[0], netif->name[1],
(u8_t)(ntohl(ipaddr->addr) >> 24 & 0xff),
(u8_t)(ntohl(ipaddr->addr) >> 16 & 0xff),
(u8_t)(ntohl(ipaddr->addr) >> 8 & 0xff),
(u8_t)(ntohl(ipaddr->addr) & 0xff)));
}
---------------
Regards
Anders Carlman
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lwip-users] Dead PCB-problem when IP-address changes,
Anders Carlman <=