All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukasz Stelmach <stlman@poczta.fm>
To: David Miller <davem@davemloft.net>
Cc: linux-kernel@vger.kernel.org, yoshfuji@linux-ipv6.org,
	netdev@vger.kernel.org
Subject: Re: [PATCH] Temporary IPv6 address asignment
Date: Mon, 04 May 2009 00:45:05 +0200	[thread overview]
Message-ID: <49FE1E71.6090500@poczta.fm> (raw)
In-Reply-To: <20090503.153428.07349534.davem@davemloft.net>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 9136 bytes --]

David Miller pisze:
> Please fix this up and make a fresh submission of your patch to
> netdev@vger.kernel.org

-----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


----------------------------------------------------------------------
Dzwonki na komorkê!
Sprawdz >> http://link.interia.pl/f2152 

[-- Attachment #2: stlman.vcf --]
[-- Type: text/x-vcard, Size: 177 bytes --]

begin: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


  reply	other threads:[~2009-05-03 22:45 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-03 21:45 [PATCH] Temporary IPv6 address asignment Lukasz Stelmach
2009-05-03 21:47 ` David Miller
2009-05-03 22:20   ` Lukasz Stelmach
2009-05-03 22:34     ` David Miller
2009-05-03 22:45       ` Lukasz Stelmach [this message]
2009-05-03 23:58         ` Eric W. Biederman
2009-05-04  0:21           ` David Miller
2009-05-04 10:57         ` YOSHIFUJI Hideaki / 吉藤英明
2009-05-04 13:30 ` [PATCH] Temporary IPv6 address asignment (v.1.1) Lukasz Stelmach

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49FE1E71.6090500@poczta.fm \
    --to=stlman@poczta.fm \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.