mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2026-08-09 17:13:49 +08:00
nd6: improve address autoconfiguration support
In summary, this patch aims to resolve bugs #47923 and #48162, by decoupling address autoconfiguration from the on-link prefix list, since those are not related. Important necessary changes are needed to meet this goal, ultimately bringing the lwIP ND6 implementation closer to compliance with RFC 4862. The main changes are: 1. support for address lifetimes, and, 2. addition of a new DUPLICATED address state. The decoupling implies that the prefix list can no longer be used to maintain state for address autoconfiguration. Most importantly, the lifetime of each address, which was previously derived from the prefix slot's lifetime, must now be associated with the address itself. This patch implements address lifetime tracking, maintaining both a valid and a preferred lifetime for each address, along with the corresponding address state changes (e.g., between PREFERRED and DEPRECATED), all as required by RFC 4862. The support for address lifetimes can be enabled with a new LWIP_IPV6_ADDRESS_LIFETIMES setting in lwipopts.h. It is required for autoconfiguration and enabled by default if autoconfiguration is enabled as well, but it may also be enabled separately, so as to allow application-controlled lifetime management (e.g., if autoconfiguration is implemented in a separate application). A special valid-lifetime of zero is used to denote a static address--that is, an address that was configured manually, that does not have lifetimes, and that should be left alone by the autoconfiguration functionality. Addresses assigned without setting a lifetime are deemed static, thus preserving compatibility with existing lwIP-based applications in this respect. Similarly, the decoupling implies that the prefix list can no longer be used to remember cases of address duplication. Previously, the detection of a duplicated address would simply result in removal of the address altogether. Instead, this patch introduces a new state "DUPLICATED", indicating that the address, while technically still present, has been found to conflict with other node addresses, and no attempt should be made to produce an autoconfiguration address for that prefix. Manually added addresses, including the link-local address, once set to DUPLICATED, will remain in that state until manual intervention. Autoconfigured DUPLICATED addresses will expire according to their valid-lifetime, essentially preserving the current behavior but without the use of the prefix list. As a first attempt to approach compliance with RFC 4862 Sec. 5.4.5, if the link-local address is detected to be duplicated, all derived addresses are marked duplicated as well, and no new addresses will be autoconfigured. More work is to be done for full compliance with that section, however. Together, those two main changes indeed do fully decouple address autoconfiguration from the on-link prefix list. Changes to the latter thus no longer affect the former, resolving bug #47923. Moreover, as a result, autoconfiguration can, and does, now also take place on advertised prefixes that do not have the on-link flag set, resolving bug #48162. The routing changes mentioned in the discussion of that bug are left to a separate patch, though.
This commit is contained in:
committed by
Dirk Ziegelmeier
parent
3cc7b319d9
commit
e0c5e1988f
@@ -234,6 +234,7 @@ typedef struct ip6_addr ip6_addr_t;
|
||||
#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */
|
||||
#define IP6_ADDR_PREFERRED 0x30
|
||||
#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */
|
||||
#define IP6_ADDR_DUPLICATED 0x40 /* Failed DAD test, not valid */
|
||||
|
||||
#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */
|
||||
|
||||
@@ -242,6 +243,14 @@ typedef struct ip6_addr ip6_addr_t;
|
||||
#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */
|
||||
#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED)
|
||||
#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED)
|
||||
#define ip6_addr_isduplicated(addr_state) (addr_state == IP6_ADDR_DUPLICATED)
|
||||
|
||||
#if LWIP_IPV6_ADDRESS_LIFETIMES
|
||||
#define IP6_ADDR_LIFE_STATIC (0)
|
||||
#define IP6_ADDR_LIFE_INFINITE (0xffffffffUL)
|
||||
#define ip6_addr_life_isstatic(addr_life) ((addr_life) == IP6_ADDR_LIFE_STATIC)
|
||||
#define ip6_addr_life_isinfinite(addr_life) ((addr_life) == IP6_ADDR_LIFE_INFINITE)
|
||||
#endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
|
||||
|
||||
#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \
|
||||
LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \
|
||||
|
||||
@@ -238,6 +238,13 @@ struct netif {
|
||||
/** The state of each IPv6 address (Tentative, Preferred, etc).
|
||||
* @see ip6_addr.h */
|
||||
u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
|
||||
#if LWIP_IPV6_ADDRESS_LIFETIMES
|
||||
/** Remaining valid and preferred lifetime of each IPv6 address, in seconds.
|
||||
* For valid lifetimes, the special value of IP6_ADDR_LIFE_STATIC (0)
|
||||
* indicates the address is static and has no lifetimes. */
|
||||
u32_t ip6_addr_valid_life[LWIP_IPV6_NUM_ADDRESSES];
|
||||
u32_t ip6_addr_pref_life[LWIP_IPV6_NUM_ADDRESSES];
|
||||
#endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
|
||||
#endif /* LWIP_IPV6 */
|
||||
/** This function is called by the network device driver
|
||||
* to pass a packet up the TCP/IP stack. */
|
||||
@@ -459,6 +466,20 @@ s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr);
|
||||
void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit);
|
||||
err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx);
|
||||
#define netif_set_ip6_autoconfig_enabled(netif, action) do { if(netif) { (netif)->ip6_autoconfig_enabled = (action); }}while(0)
|
||||
#if LWIP_IPV6_ADDRESS_LIFETIMES
|
||||
#define netif_ip6_addr_valid_life(netif, i) \
|
||||
(((netif) != NULL) ? ((netif)->ip6_addr_valid_life[i]) : IP6_ADDR_LIFE_STATIC)
|
||||
#define netif_ip6_addr_set_valid_life(netif, i, secs) \
|
||||
do { if (netif != NULL) { (netif)->ip6_addr_valid_life[i] = (secs); }} while (0)
|
||||
#define netif_ip6_addr_pref_life(netif, i) \
|
||||
(((netif) != NULL) ? ((netif)->ip6_addr_pref_life[i]) : IP6_ADDR_LIFE_STATIC)
|
||||
#define netif_ip6_addr_set_pref_life(netif, i, secs) \
|
||||
do { if (netif != NULL) { (netif)->ip6_addr_pref_life[i] = (secs); }} while (0)
|
||||
#define netif_ip6_addr_isstatic(netif, i) \
|
||||
(netif_ip6_addr_valid_life((netif), (i)) == IP6_ADDR_LIFE_STATIC)
|
||||
#else /* !LWIP_IPV6_ADDRESS_LIFETIMES */
|
||||
#define netif_ip6_addr_isstatic(netif, i) (1) /* all addresses are static */
|
||||
#endif /* !LWIP_IPV6_ADDRESS_LIFETIMES */
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
|
||||
@@ -2198,6 +2198,17 @@
|
||||
#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_ADDRESS_LIFETIMES==1: Keep valid and preferred lifetimes for each
|
||||
* IPv6 address. Required for LWIP_IPV6_AUTOCONFIG. May still be enabled
|
||||
* otherwise, in which case the application may assign address lifetimes with
|
||||
* the appropriate macros. Addresses with no lifetime are assumed to be static.
|
||||
* If this option is disabled, all addresses are assumed to be static.
|
||||
*/
|
||||
#if !defined LWIP_IPV6_ADDRESS_LIFETIMES || defined __DOXYGEN__
|
||||
#define LWIP_IPV6_ADDRESS_LIFETIMES (LWIP_IPV6_AUTOCONFIG)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_IPV6_DUP_DETECT_ATTEMPTS=[0..7]: Number of duplicate address detection attempts.
|
||||
*/
|
||||
|
||||
@@ -83,7 +83,7 @@ struct nd6_neighbor_cache_entry {
|
||||
u8_t state;
|
||||
u8_t isrouter;
|
||||
union {
|
||||
u32_t reachable_time; /* in ms since value may originate from network packet */
|
||||
u32_t reachable_time; /* in seconds */
|
||||
u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */
|
||||
u32_t probes_sent;
|
||||
u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */
|
||||
@@ -100,18 +100,12 @@ struct nd6_destination_cache_entry {
|
||||
struct nd6_prefix_list_entry {
|
||||
ip6_addr_t prefix;
|
||||
struct netif *netif;
|
||||
u32_t invalidation_timer; /* in ms since value may originate from network packet */
|
||||
#if LWIP_IPV6_AUTOCONFIG
|
||||
u8_t flags;
|
||||
#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01
|
||||
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02
|
||||
#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04
|
||||
#endif /* LWIP_IPV6_AUTOCONFIG */
|
||||
u32_t invalidation_timer; /* in seconds */
|
||||
};
|
||||
|
||||
struct nd6_router_list_entry {
|
||||
struct nd6_neighbor_cache_entry *neighbor_entry;
|
||||
u32_t invalidation_timer; /* in ms since value may originate from network packet */
|
||||
u32_t invalidation_timer; /* in seconds */
|
||||
u8_t flags;
|
||||
};
|
||||
|
||||
@@ -124,6 +118,8 @@ enum nd6_neighbor_cache_entry_state {
|
||||
ND6_PROBE
|
||||
};
|
||||
|
||||
#define ND6_2HRS 7200 /* two hours, expressed in number of seconds */
|
||||
|
||||
/* Router tables. */
|
||||
/* @todo make these static? and entries accessible through API? */
|
||||
extern struct nd6_neighbor_cache_entry neighbor_cache[];
|
||||
|
||||
Reference in New Issue
Block a user