Messages in this thread Patch in this message | | | Date | Mon, 04 May 2009 00:20:51 +0200 | From | Lukasz Stelmach <> | Subject | Re: [PATCH] Temporary IPv6 address asignment |
| |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
David Miller pisze: > From: Lukasz Stelmach <stlman@poczta.fm> > Date: Sun, 03 May 2009 23:45:30 +0200 > >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> Greetings. >> >> I discovered recently and fixed some problems with IPv6 temporary >> address asignment. I have described the problem at >> http://bugzilla.kernel.org as bugs #13208 and #13221. >> >> http://bugzilla.kernel.org/show_bug.cgi?id=13208 >> http://bugzilla.kernel.org/show_bug.cgi?id=13221 >> >> The patch is available at: >> >> http://bugzilla.kernel.org/attachment.cgi?id=21201 > > Nobody is going to look at this unless you post the patch > with description and proper signoffs with netdev@vger.kernel.org > CC:'d
The description is in the patch, and a sign-off too. But all righ.
- -----CUT HERE----- A fixed mechanism to create and recreate temporary addresses, even for very short preferred lifetimes.
A new RFC-compliant DESYNC_FACTOR implemented as a sysctl variable desync_factor which is assigned a random value each time max_desync_factor is written to. Each interface has its own desync_factor and max_desync_factor. Writes to default/max_desync_factor influence only default values. Writes to all/max_desync_factor influence "all" and default values but not values of running interfaces.
The patch fixes issues described in bugs #13208 and #13221 at http://bugzilla.kernel.org.
Signed-off-by: Łukasz Stelmach <stlman@poczta.fm>
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 476d946..fa45ad2 100644 - --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -146,6 +146,7 @@ struct ipv6_devconf { __s32 temp_prefered_lft; __s32 regen_max_retry; __s32 max_desync_factor; + __s32 desync_factor; #endif __s32 max_addresses; __s32 accept_ra_defrtr; @@ -188,6 +189,7 @@ enum { DEVCONF_TEMP_PREFERED_LFT, DEVCONF_REGEN_MAX_RETRY, DEVCONF_MAX_DESYNC_FACTOR, + DEVCONF_DESYNC_FACTOR, DEVCONF_MAX_ADDRESSES, DEVCONF_FORCE_MLD_VERSION, DEVCONF_ACCEPT_RA_DEFRTR, diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index e76d3b2..951ba2c 100644 - --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -570,15 +570,16 @@ enum { NET_IPV6_TEMP_PREFERED_LFT=13, NET_IPV6_REGEN_MAX_RETRY=14, NET_IPV6_MAX_DESYNC_FACTOR=15, - - NET_IPV6_MAX_ADDRESSES=16, - - NET_IPV6_FORCE_MLD_VERSION=17, - - NET_IPV6_ACCEPT_RA_DEFRTR=18, - - NET_IPV6_ACCEPT_RA_PINFO=19, - - NET_IPV6_ACCEPT_RA_RTR_PREF=20, - - NET_IPV6_RTR_PROBE_INTERVAL=21, - - NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22, - - NET_IPV6_PROXY_NDP=23, - - NET_IPV6_ACCEPT_SOURCE_ROUTE=25, + NET_IPV6_DESYNC_FACTOR=16, + NET_IPV6_MAX_ADDRESSES=17, + NET_IPV6_FORCE_MLD_VERSION=18, + NET_IPV6_ACCEPT_RA_DEFRTR=19, + NET_IPV6_ACCEPT_RA_PINFO=20, + NET_IPV6_ACCEPT_RA_RTR_PREF=21, + NET_IPV6_RTR_PROBE_INTERVAL=22, + NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=23, + NET_IPV6_PROXY_NDP=24, + NET_IPV6_ACCEPT_SOURCE_ROUTE=26, __NET_IPV6_MAX };
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a8218bc..1b746ee 100644 - --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -116,8 +116,6 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) static int __ipv6_regen_rndid(struct inet6_dev *idev); static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); static void ipv6_regen_rndid(unsigned long data); - - - -static int desync_factor = MAX_DESYNC_FACTOR * HZ; #endif
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); @@ -172,6 +170,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { .temp_prefered_lft = TEMP_PREFERRED_LIFETIME, .regen_max_retry = REGEN_MAX_RETRY, .max_desync_factor = MAX_DESYNC_FACTOR, + .desync_factor = MAX_DESYNC_FACTOR / 2, #endif .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, @@ -206,6 +205,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { .temp_prefered_lft = TEMP_PREFERRED_LIFETIME, .regen_max_retry = REGEN_MAX_RETRY, .max_desync_factor = MAX_DESYNC_FACTOR, + .desync_factor = MAX_DESYNC_FACTOR / 2, #endif .max_addresses = IPV6_MAX_ADDRESSES, .accept_ra_defrtr = 1, @@ -831,11 +831,13 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) }
#ifdef CONFIG_IPV6_PRIVACY - -static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *ift) +static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, + struct inet6_ifaddr *ift, + unsigned long now) { struct inet6_dev *idev = ifp->idev; struct in6_addr addr, *tmpaddr; - - unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; + unsigned long tmp_prefered_lft, tmp_valid_lft; unsigned long regen_advance; int tmp_plen; int ret = 0; @@ -890,11 +892,9 @@ retry: idev->cnf.temp_valid_lft); tmp_prefered_lft = min_t(__u32, ifp->prefered_lft, - - idev->cnf.temp_prefered_lft - desync_factor / HZ); + idev->cnf.temp_prefered_lft - idev->cnf.desync_factor); tmp_plen = ifp->prefix_len; max_addresses = idev->cnf.max_addresses; - - tmp_cstamp = ifp->cstamp; - - tmp_tstamp = ifp->tstamp; spin_unlock_bh(&ifp->lock);
regen_advance = idev->cnf.regen_max_retry * @@ -938,8 +938,7 @@ retry: ift->ifpub = ifp; ift->valid_lft = tmp_valid_lft; ift->prefered_lft = tmp_prefered_lft; - - ift->cstamp = tmp_cstamp; - - ift->tstamp = tmp_tstamp; + ift->cstamp = ift->tstamp = now; spin_unlock_bh(&ift->lock);
addrconf_dad_start(ift, 0); @@ -1388,7 +1387,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp) if (ifpub) { in6_ifa_hold(ifpub); spin_unlock_bh(&ifp->lock); - - ipv6_create_tempaddr(ifpub, ifp); + ipv6_create_tempaddr(ifpub, ifp, jiffies); in6_ifa_put(ifpub); } else { spin_unlock_bh(&ifp->lock); @@ -1624,7 +1623,8 @@ static void ipv6_regen_rndid(unsigned long data)
expires = jiffies + idev->cnf.temp_prefered_lft * HZ - - - idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor; + idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - + idev->cnf.desync_factor * HZ; if (time_before(expires, jiffies)) { printk(KERN_WARNING "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n", @@ -1971,7 +1971,7 @@ ok: * also create a new temporary address. */ read_unlock_bh(&in6_dev->lock); - - ipv6_create_tempaddr(ifp, NULL); + ipv6_create_tempaddr(ifp, NULL, jiffies); } else { read_unlock_bh(&in6_dev->lock); } @@ -2809,6 +2809,11 @@ static void addrconf_dad_timer(unsigned long data) read_unlock_bh(&idev->lock);
addrconf_dad_completed(ifp); + /* + * Required to expire properly temporary addresses + * with preferred lifetimes < ADDR_CHECK_FREQUENCY + */ + addrconf_verify(0);
goto out; } @@ -3121,7 +3126,7 @@ restart: spin_lock(&ifpub->lock); ifpub->regen_count = 0; spin_unlock(&ifpub->lock); - - ipv6_create_tempaddr(ifpub, ifp); + ipv6_create_tempaddr(ifpub, ifp, now); in6_ifa_put(ifpub); in6_ifa_put(ifp); goto restart; @@ -3638,6 +3643,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft; array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry; array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; + array[DEVCONF_DESYNC_FACTOR] = cnf->desync_factor; #endif array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; @@ -3935,6 +3941,43 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) }
#ifdef CONFIG_SYSCTL +#ifdef CONFIG_IPV6_PRIVACY +static int addrconf_sysctl_desync(ctl_table *ctl, int write, + struct file *filp, void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + int ret; + + ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); + + if (write) { + __s32 df; + int *valp = ctl->data; + struct ipv6_devconf *all, *dflt; + struct inet6_dev *idev = ctl->extra1; + struct net *net = ctl->extra2; + all = net->ipv6.devconf_all; + dflt = net->ipv6.devconf_dflt; + + get_random_bytes(&df, sizeof(df)); + /* The global abs() casts to int. */; + df = ((df) < 0 ? -(df) : df) % (*valp) + + /* XXX How about some locking? */ + if(idev) + idev->cnf.desync_factor = df; + else if (valp == &dflt->max_desync_factor) + dflt->desync_factor = df; + else if (valp == &all->max_desync_factor) { + all->desync_factor = df; + dflt->max_desync_factor = all->max_desync_factor; + dflt->desync_factor = df; + } + + } + return ret; +} +#endif
static int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp, @@ -4124,6 +4167,14 @@ static struct addrconf_sysctl_table .data = &ipv6_devconf.max_desync_factor, .maxlen = sizeof(int), .mode = 0644, + .proc_handler = addrconf_sysctl_desync, + }, + { + .ctl_name = NET_IPV6_DESYNC_FACTOR, + .procname = "desync_factor", + .data = &ipv6_devconf.desync_factor, + .maxlen = sizeof(int), + .mode = 0444, .proc_handler = proc_dointvec, }, #endif @@ -4449,6 +4500,11 @@ int __init addrconf_init(void) rtnl_unlock(); if (err) goto errlo; +#ifdef CONFIG_IPV6_PRIVACY + get_random_bytes(&ipv6_devconf.desync_factor, sizeof(ipv6_devconf.desync_factor)); + ipv6_devconf.desync_factor = abs(ipv6_devconf.desync_factor) % ipv6_devconf.max_desync_factor; + ipv6_devconf_dflt.desync_factor = ipv6_devconf.desync_factor; +#endif
register_netdevice_notifier(&ipv6_dev_notf); - -----CUT HERE----- - -- Było mi bardzo miło. Czwarta pospolita klęska, [...] >Łukasz< Już nie katolicka lecz złodziejska. (c)PP -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkn+GMMACgkQNdzY8sm9K9zimACcC6NfOGMzd0vqB9J/QXrc6q0P h6oAmgKP7sG+/h0JkdjVEeLbbyDgHH/s =CryG -----END PGP SIGNATURE-----
---------------------------------------------------------------------- Gotowka na koncie. Otworz konto direct i wez podwojny limit. http://link.interia.pl/f2145begin:vcard fn;quoted-printable:=C5=81ukasz Stelmach n;quoted-printable:Stelmach;=C5=81ukasz email;internet:stlman@poczta.fm x-mozilla-html:FALSE version:2.1 end:vcard
| |