Merge branch 'net-ipv6-addrconf-ensure-that-temporary-addresses-preferred-lifetimes-are-long-enough'
Alex Henrie says: ==================== net: ipv6/addrconf: ensure that temporary addresses' preferred lifetimes are long enough v2 corrects and updates the documentation for these features. Changes from v1: - Update the typical minimum lifetime stated in the documentation, and make it a range to emphasize the variability - Fix spelling of "determine" in the documentation - Mention RFC 8981's requirements in the documentation - Arrange variables in "reverse Christmas tree" - Update documentation of what happens if temp_prefered_lft is less than the minimum required lifetime Thanks to David, Paolo, and Dan for your feedback. ==================== Link: https://lore.kernel.org/r/20240214062711.608363-1-alexhenrie24@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@ -2503,7 +2503,7 @@ use_tempaddr - INTEGER
|
||||
|
||||
temp_valid_lft - INTEGER
|
||||
valid lifetime (in seconds) for temporary addresses. If less than the
|
||||
minimum required lifetime (typically 5 seconds), temporary addresses
|
||||
minimum required lifetime (typically 5-7 seconds), temporary addresses
|
||||
will not be created.
|
||||
|
||||
Default: 172800 (2 days)
|
||||
@ -2511,7 +2511,7 @@ temp_valid_lft - INTEGER
|
||||
temp_prefered_lft - INTEGER
|
||||
Preferred lifetime (in seconds) for temporary addresses. If
|
||||
temp_prefered_lft is less than the minimum required lifetime (typically
|
||||
5 seconds), temporary addresses will not be created. If
|
||||
5-7 seconds), the preferred lifetime is the minimum required. If
|
||||
temp_prefered_lft is greater than temp_valid_lft, the preferred lifetime
|
||||
is temp_valid_lft.
|
||||
|
||||
@ -2535,6 +2535,16 @@ max_desync_factor - INTEGER
|
||||
|
||||
Default: 600
|
||||
|
||||
regen_min_advance - INTEGER
|
||||
How far in advance (in seconds), at minimum, to create a new temporary
|
||||
address before the current one is deprecated. This value is added to
|
||||
the amount of time that may be required for duplicate address detection
|
||||
to determine when to create a new address. Linux permits setting this
|
||||
value to less than the default of 2 seconds, but a value less than 2
|
||||
does not conform to RFC 8981.
|
||||
|
||||
Default: 2
|
||||
|
||||
regen_max_retry - INTEGER
|
||||
Number of attempts before give up attempting to generate
|
||||
valid temporary addresses.
|
||||
|
@ -27,6 +27,7 @@ struct ipv6_devconf {
|
||||
__s32 use_tempaddr;
|
||||
__s32 temp_valid_lft;
|
||||
__s32 temp_prefered_lft;
|
||||
__s32 regen_min_advance;
|
||||
__s32 regen_max_retry;
|
||||
__s32 max_desync_factor;
|
||||
__s32 max_addresses;
|
||||
|
@ -8,8 +8,9 @@
|
||||
|
||||
#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */
|
||||
|
||||
#define TEMP_VALID_LIFETIME (7*86400)
|
||||
#define TEMP_PREFERRED_LIFETIME (86400)
|
||||
#define TEMP_VALID_LIFETIME (7*86400) /* 1 week */
|
||||
#define TEMP_PREFERRED_LIFETIME (86400) /* 24 hours */
|
||||
#define REGEN_MIN_ADVANCE (2) /* 2 seconds */
|
||||
#define REGEN_MAX_RETRY (3)
|
||||
#define MAX_DESYNC_FACTOR (600)
|
||||
|
||||
|
@ -195,6 +195,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
|
||||
.use_tempaddr = 0,
|
||||
.temp_valid_lft = TEMP_VALID_LIFETIME,
|
||||
.temp_prefered_lft = TEMP_PREFERRED_LIFETIME,
|
||||
.regen_min_advance = REGEN_MIN_ADVANCE,
|
||||
.regen_max_retry = REGEN_MAX_RETRY,
|
||||
.max_desync_factor = MAX_DESYNC_FACTOR,
|
||||
.max_addresses = IPV6_MAX_ADDRESSES,
|
||||
@ -257,6 +258,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
||||
.use_tempaddr = 0,
|
||||
.temp_valid_lft = TEMP_VALID_LIFETIME,
|
||||
.temp_prefered_lft = TEMP_PREFERRED_LIFETIME,
|
||||
.regen_min_advance = REGEN_MIN_ADVANCE,
|
||||
.regen_max_retry = REGEN_MAX_RETRY,
|
||||
.max_desync_factor = MAX_DESYNC_FACTOR,
|
||||
.max_addresses = IPV6_MAX_ADDRESSES,
|
||||
@ -1339,12 +1341,20 @@ out:
|
||||
in6_ifa_put(ifp);
|
||||
}
|
||||
|
||||
static unsigned long ipv6_get_regen_advance(struct inet6_dev *idev)
|
||||
{
|
||||
return idev->cnf.regen_min_advance + idev->cnf.regen_max_retry *
|
||||
idev->cnf.dad_transmits *
|
||||
max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
|
||||
}
|
||||
|
||||
static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
|
||||
{
|
||||
struct inet6_dev *idev = ifp->idev;
|
||||
unsigned long tmp_tstamp, age;
|
||||
unsigned long regen_advance;
|
||||
unsigned long now = jiffies;
|
||||
u32 if_public_preferred_lft;
|
||||
s32 cnf_temp_preferred_lft;
|
||||
struct inet6_ifaddr *ift;
|
||||
struct ifa6_config cfg;
|
||||
@ -1380,9 +1390,7 @@ retry:
|
||||
|
||||
age = (now - ifp->tstamp) / HZ;
|
||||
|
||||
regen_advance = idev->cnf.regen_max_retry *
|
||||
idev->cnf.dad_transmits *
|
||||
max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
|
||||
regen_advance = ipv6_get_regen_advance(idev);
|
||||
|
||||
/* recalculate max_desync_factor each time and update
|
||||
* idev->desync_factor if it's larger
|
||||
@ -1402,11 +1410,13 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
if_public_preferred_lft = ifp->prefered_lft;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.valid_lft = min_t(__u32, ifp->valid_lft,
|
||||
idev->cnf.temp_valid_lft + age);
|
||||
cfg.preferred_lft = cnf_temp_preferred_lft + age - idev->desync_factor;
|
||||
cfg.preferred_lft = min_t(__u32, ifp->prefered_lft, cfg.preferred_lft);
|
||||
cfg.preferred_lft = min_t(__u32, if_public_preferred_lft, cfg.preferred_lft);
|
||||
cfg.preferred_lft = min_t(__u32, cfg.valid_lft, cfg.preferred_lft);
|
||||
|
||||
cfg.plen = ifp->prefix_len;
|
||||
@ -1415,19 +1425,41 @@ retry:
|
||||
|
||||
write_unlock_bh(&idev->lock);
|
||||
|
||||
/* A temporary address is created only if this calculated Preferred
|
||||
* Lifetime is greater than REGEN_ADVANCE time units. In particular,
|
||||
* an implementation must not create a temporary address with a zero
|
||||
* Preferred Lifetime.
|
||||
/* From RFC 4941:
|
||||
*
|
||||
* A temporary address is created only if this calculated Preferred
|
||||
* Lifetime is greater than REGEN_ADVANCE time units. In
|
||||
* particular, an implementation must not create a temporary address
|
||||
* with a zero Preferred Lifetime.
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* When creating a temporary address, the lifetime values MUST be
|
||||
* derived from the corresponding prefix as follows:
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* * Its Preferred Lifetime is the lower of the Preferred Lifetime
|
||||
* of the public address or TEMP_PREFERRED_LIFETIME -
|
||||
* DESYNC_FACTOR.
|
||||
*
|
||||
* To comply with the RFC's requirements, clamp the preferred lifetime
|
||||
* to a minimum of regen_advance, unless that would exceed valid_lft or
|
||||
* ifp->prefered_lft.
|
||||
*
|
||||
* Use age calculation as in addrconf_verify to avoid unnecessary
|
||||
* temporary addresses being generated.
|
||||
*/
|
||||
age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
|
||||
if (cfg.preferred_lft <= regen_advance + age) {
|
||||
in6_ifa_put(ifp);
|
||||
in6_dev_put(idev);
|
||||
ret = -1;
|
||||
goto out;
|
||||
cfg.preferred_lft = regen_advance + age + 1;
|
||||
if (cfg.preferred_lft > cfg.valid_lft ||
|
||||
cfg.preferred_lft > if_public_preferred_lft) {
|
||||
in6_ifa_put(ifp);
|
||||
in6_dev_put(idev);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
cfg.ifa_flags = IFA_F_TEMPORARY;
|
||||
@ -4595,9 +4627,7 @@ restart:
|
||||
!ifp->regen_count && ifp->ifpub) {
|
||||
/* This is a non-regenerated temporary addr. */
|
||||
|
||||
unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
|
||||
ifp->idev->cnf.dad_transmits *
|
||||
max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
|
||||
unsigned long regen_advance = ipv6_get_regen_advance(ifp->idev);
|
||||
|
||||
if (age + regen_advance >= ifp->prefered_lft) {
|
||||
struct inet6_ifaddr *ifpub = ifp->ifpub;
|
||||
@ -6816,6 +6846,13 @@ static const struct ctl_table addrconf_sysctl[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "regen_min_advance",
|
||||
.data = &ipv6_devconf.regen_min_advance,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "regen_max_retry",
|
||||
.data = &ipv6_devconf.regen_max_retry,
|
||||
|
Reference in New Issue
Block a user