From e8ffac852ec5292694f19c113a24d609bd3693bf Mon Sep 17 00:00:00 2001 From: goldsimon Date: Wed, 20 Jul 2016 08:28:16 +0200 Subject: [PATCH] Fixed bug #48551 (autoip_supplied_address() does not work when address is first assigned); fixed AutoIP timeouts --- src/core/ipv4/autoip.c | 93 +++++++++++++++++++----------------------- src/include/lwip/opt.h | 8 ++-- 2 files changed, 46 insertions(+), 55 deletions(-) diff --git a/src/core/ipv4/autoip.c b/src/core/ipv4/autoip.c index bc2b9176..dbdec70a 100644 --- a/src/core/ipv4/autoip.c +++ b/src/core/ipv4/autoip.c @@ -162,30 +162,25 @@ autoip_restart(struct netif *netif) static void autoip_handle_arp_conflict(struct netif *netif) { - /* Somehow detect if we are defending or retreating */ - unsigned char defend = 1; /* tbd */ + /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where + a) means retreat on the first conflict and + b) allows to keep an already configured address when having only one + conflict in 10 seconds + We use option b) since it helps to improve the chance that one of the two + conflicting hosts may be able to retain its address. */ - if (defend) { - if (netif->autoip->lastconflict > 0) { - /* retreat, there was a conflicting ARP in the last - * DEFEND_INTERVAL seconds - */ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + if (netif->autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); - /* @todo: close all TCP sessions */ - autoip_restart(netif); - } else { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); - autoip_arp_announce(netif); - netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; - } + /* Active TCP sessions are aborted when removing the ip addresss */ + autoip_restart(netif); } else { LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); - /* @todo: close all TCP sessions */ - autoip_restart(netif); + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; } } @@ -399,14 +394,20 @@ autoip_tmr(void) ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", (u16_t)(netif->autoip->state), netif->autoip->ttw)); + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } + switch(netif->autoip->state) { case AUTOIP_STATE_PROBING: - if (netif->autoip->ttw > 0) { - netif->autoip->ttw--; - } else { + if (netif->autoip->ttw == 0) { if (netif->autoip->sent_num >= PROBE_NUM) { + /* Switch to ANNOUNCING: now we can bind to an IP address and use it */ netif->autoip->state = AUTOIP_STATE_ANNOUNCING; - netif->autoip->sent_num = 0; + autoip_bind(netif); + /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP + which counts as an announcement */ + netif->autoip->sent_num = 1; netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", @@ -414,34 +415,25 @@ autoip_tmr(void) ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); } else { autoip_arp_probe(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_tmr() PROBING Sent Probe\n")); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); netif->autoip->sent_num++; - /* calculate time to wait to next probe */ - netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % - ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + - PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + if (netif->autoip->sent_num == PROBE_NUM) { + /* calculate time to wait to for announce */ + netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + } else { + /* calculate time to wait to next probe */ + netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } } } break; case AUTOIP_STATE_ANNOUNCING: - if (netif->autoip->ttw > 0) { - netif->autoip->ttw--; - } else { - if (netif->autoip->sent_num == 0) { - /* We are here the first time, so we waited ANNOUNCE_WAIT seconds - * Now we can bind to an IP address and use it. - * - * autoip_bind calls netif_set_addr. This triggers a gratuitous ARP - * which counts as an announcement. - */ - autoip_bind(netif); - } else { - autoip_arp_announce(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_tmr() ANNOUNCING Sent Announce\n")); - } + if (netif->autoip->ttw == 0) { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; netif->autoip->sent_num++; @@ -493,9 +485,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) IPADDR2_COPY(&sipaddr, &hdr->sipaddr); IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - if ((netif->autoip->state == AUTOIP_STATE_PROBING) || - ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) && - (netif->autoip->sent_num == 0))) { + if (netif->autoip->state == AUTOIP_STATE_PROBING) { /* RFC 3927 Section 2.2.1: * from beginning to after ANNOUNCE_WAIT * seconds we have a conflict if @@ -527,14 +517,15 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) /** check if AutoIP supplied netif->ip_addr * * @param netif the netif to check - * @return 1 if AutoIP supplied netif->ip_addr (state BOUND), + * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING), * 0 otherwise */ u8_t autoip_supplied_address(const struct netif *netif) { if ((netif != NULL) && (netif->autoip != NULL)) { - if (netif->autoip->state == AUTOIP_STATE_BOUND) { + if ((netif->autoip->state == AUTOIP_STATE_BOUND) || + (netif->autoip->state == AUTOIP_STATE_ANNOUNCING)) { return 1; } } diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index e6af1e59..5d887eac 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -782,10 +782,10 @@ /** * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes - * that should be sent before falling back on AUTOIP. This can be set - * as low as 1 to get an AutoIP address very quickly, but you should - * be prepared to handle a changing IP address when DHCP overrides - * AutoIP. + * that should be sent before falling back on AUTOIP (the DHCP client keeps + * running in this case). This can be set as low as 1 to get an AutoIP address + * very quickly, but you should be prepared to handle a changing IP address + * when DHCP overrides AutoIP. */ #ifndef LWIP_DHCP_AUTOIP_COOP_TRIES #define LWIP_DHCP_AUTOIP_COOP_TRIES 9