Skip to contentSkip to conversation

ipv6: RFC7217 stable privacy addresses implementation

PATCH Applied Hannes Frederic Sowa 2 participants 10 messages Mar 23, 2015 – Mar 24, 2015

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

v2 cover ipv6: RFC7217 stable privacy addresses implementation

Hi all,

this is an implementation of basic support for RFC7217 stable privacy addresses. Please review and consider for net-next.

Bye and thanks,
Hannes

v2:
* Correct references to RFC 7212 -> RFC 7217 in documentation patch (thanks, Eric!)

Hannes Frederic Sowa (8):
lib: EXPORT_SYMBOL sha_init
ipv6: introduce secret_stable to ipv6_devconf
ipv6: generation of stable privacy addresses for link-local and
autoconf
ipv6: introduce IFA_F_STABLE_PRIVACY flag
ipv6: collapse state_lock and lock
ipv6: do retries on stable privacy addresses
ipv6: introduce idgen_delay and idgen_retries knobs
ipv6: add documentation for stable_secret, idgen_delay and
idgen_retries knobs

 Documentation/networking/ip-sysctl.txt |  25 +++
 include/linux/ipv6.h                   |   4 +
 include/net/if_inet6.h                 |   4 +-
 include/net/netns/ipv6.h               |   2 +
 include/uapi/linux/if_addr.h           |   1 +
 include/uapi/linux/if_link.h           |   1 +
 include/uapi/linux/ipv6.h              |   1 +
 lib/sha1.c                             |   1 +
 net/ipv6/addrconf.c                    | 293 ++++++++++++++++++++++++++++++---
 net/ipv6/af_inet6.c                    |   2 +
 net/ipv6/sysctl_net_ipv6.c             |  16 ++
 11 files changed, 321 insertions(+), 29 deletions(-)
Signature · 1 line
2.1.0
#1 lore raw

PATCH v2 1/8 lib: EXPORT_SYMBOL sha_init

We need this symbol later on in ipv6.ko, thus export it via EXPORT_SYMBOL like sha_transform already is.

---
 lib/sha1.c | 1 +
 1 file changed, 1 insertion(+)
lib/sha1.c +1 -0
index 1df191e..5a56dfd 100644
@@ -198,3 +198,4 @@ void sha_init(__u32 *buf)
 	buf[3] = 0x10325476;
 	buf[4] = 0xc3d2e1f0;
 }
+EXPORT_SYMBOL(sha_init);
Signature · 1 line
2.1.0
#2 lore raw

PATCH v2 2/8 ipv6: introduce secret_stable to ipv6_devconf

In reply to Hannes Frederic Sowa

This patch implements the procfs logic for the stable_address knob:
The secret is formatted as an ipv6 address and will be stored per interface and per namespace. We track initialized flag and return EIO errors until the secret is set.

We don't inherit the secret to newly created namespaces.

Cc Erik Kline <[email protected]>
Cc Fernando Gont <[email protected]>
Cc Lorenzo Colitti <[email protected]>
Cc YOSHIFUJI Hideaki/吉藤英明 <[email protected]>
---
 include/linux/ipv6.h      |  4 +++
 include/uapi/linux/ipv6.h |  1 +
 net/ipv6/addrconf.c       | 68 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)
include/linux/ipv6.h +4 -0
index 4d5169f..82806c6 100644
@@ -53,6 +53,10 @@ struct ipv6_devconf {
 	__s32           ndisc_notify;
 	__s32		suppress_frag_ndisc;
 	__s32		accept_ra_mtu;
+	struct ipv6_stable_secret {
+		bool initialized;
+		struct in6_addr secret;
+	} stable_secret;
 	void		*sysctl;
 };
 
include/uapi/linux/ipv6.h +1 -0
index 437a6a4..5efa54a 100644
@@ -170,6 +170,7 @@ enum {
 	DEVCONF_ACCEPT_RA_FROM_LOCAL,
 	DEVCONF_USE_OPTIMISTIC,
 	DEVCONF_ACCEPT_RA_MTU,
+	DEVCONF_STABLE_SECRET,
 	DEVCONF_MAX
 };
 
net/ipv6/addrconf.c +68 -0

116 lines not on this page · raw message

Signature · 1 line
2.1.0
#3 lore raw

PATCH v2 3/8 ipv6: generation of stable privacy addresses for link-local and autoconf

In reply to Hannes Frederic Sowa

This patch implements the stable privacy address generation for link-local and autoconf addresses as specified in RFC7217.

RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key)

is the RID (random identifier). As the hash function F we chose one round of sha1. Prefix will be either the link-local prefix or the router advertised one. As Net_Iface we use the MAC address of the device. DAD_Counter and secret_key are implemented as specified.

We don't use Network_ID, as it couples the code too closely to other subsystems. It is specified as optional in the RFC.

As Net_Iface we only use the MAC address: we simply have no stable identifier in the kernel we could possibly use: because this code might run very early, we cannot depend on names, as they might be changed by user space early on during the boot process.

A new address generation mode is introduced, IN6_ADDR_GEN_MODE_STABLE_PRIVACY. With iproute2 one can switch back to none or eui64 address configuration mode although the stable_secret is already set.

We refuse writes to ipv6/conf/all/stable_secret but only allow ipv6/conf/default/stable_secret and the interface specific file to be written to. The default stable_secret is used as the parameter for the namespace, the interface specific can overwrite the secret, e.g. when switching a network configuration from one system to another while inheriting the secret.

Cc Erik Kline <[email protected]>
Cc Fernando Gont <[email protected]>
Cc Lorenzo Colitti <[email protected]>
Cc YOSHIFUJI Hideaki/吉藤英明 <[email protected]>
---
 include/uapi/linux/if_link.h |   1 +
 net/ipv6/addrconf.c          | 130 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 127 insertions(+), 4 deletions(-)
include/uapi/linux/if_link.h +1 -0
index f5f5edd..7ffb18d 100644
@@ -216,6 +216,7 @@ enum {
 enum in6_addr_gen_mode {
 	IN6_ADDR_GEN_MODE_EUI64,
 	IN6_ADDR_GEN_MODE_NONE,
+	IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
 };
 
 /* Bridge section */
net/ipv6/addrconf.c +126 -4

172 lines not on this page · raw message

Signature · 1 line
2.1.0
#4 lore raw

PATCH v2 4/8 ipv6: introduce IFA_F_STABLE_PRIVACY flag

In reply to Hannes Frederic Sowa

We need to mark appropriate addresses so we can do retries in case their DAD failed.

Cc Erik Kline <[email protected]>
Cc Fernando Gont <[email protected]>
Cc Lorenzo Colitti <[email protected]>
Cc YOSHIFUJI Hideaki/吉藤英明 <[email protected]>
---
 include/uapi/linux/if_addr.h |  1 +
 net/ipv6/addrconf.c          | 14 ++++++++------
 2 files changed, 9 insertions(+), 6 deletions(-)
include/uapi/linux/if_addr.h +1 -0
index 40fdfea..4318ab1 100644
@@ -51,6 +51,7 @@ enum {
 #define IFA_F_MANAGETEMPADDR	0x100
 #define IFA_F_NOPREFIXROUTE	0x200
 #define IFA_F_MCAUTOJOIN	0x400
+#define IFA_F_STABLE_PRIVACY	0x800
 
 struct ifa_cacheinfo {
 	__u32	ifa_prefered;
net/ipv6/addrconf.c +8 -6
index 6813268..c2357b6 100644
@@ -2199,6 +2199,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
 	__u32 valid_lft;
 	__u32 prefered_lft;
 	int addr_type;
+	u32 addr_flags = 0;
 	struct inet6_dev *in6_dev;
 	struct net *net = dev_net(dev);
 
@@ -2309,6 +2310,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
 				   IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
 				   !ipv6_generate_stable_address(&addr, 0,
 								 in6_dev)) {
+				addr_flags |= IFA_F_STABLE_PRIVACY;
 				goto ok;
 			} else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
 				   ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
@@ -2328,7 +2330,6 @@ ok:
 
 		if (ifp == NULL && valid_lft) {
 			int max_addresses = in6_dev->cnf.max_addresses;
-			u32 addr_flags = 0;
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
 			if (in6_dev->cnf.optimistic_dad &&
@@ -2807,10 +2808,11 @@ static void init_loopback(struct net_device *dev)
 	}
 }
 
-static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)
+static void addrconf_add_linklocal(struct inet6_dev *idev,
+				   const struct in6_addr *addr, u32 flags)
 {
 	struct inet6_ifaddr *ifp;
-	u32 addr_flags = IFA_F_PERMANENT;
+	u32 addr_flags = flags | IFA_F_PERMANENT;
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
 	if (idev->cnf.optimistic_dad &&
@@ -2818,7 +2820,6 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr
 		addr_flags |= IFA_F_OPTIMISTIC;
 #endif
 
-
 	ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
 			    INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
 	if (!IS_ERR(ifp)) {
@@ -2916,7 +2917,8 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
 
 	if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY) {
 		if (!ipv6_generate_stable_address(&addr, 0, idev))
-			addrconf_add_linklocal(idev, &addr);
+			addrconf_add_linklocal(idev, &addr,
+					       IFA_F_STABLE_PRIVACY);
 		else if (prefix_route)
 			addrconf_prefix_route(&addr, 64, idev->dev, 0, 0);
 	} else if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64) {
@@ -2925,7 +2927,7 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
 		 * couldn't generate one.
 		 */
 		if (ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) == 0)
-			addrconf_add_linklocal(idev, &addr);
+			addrconf_add_linklocal(idev, &addr, 0);
 		else if (prefix_route)
 			addrconf_prefix_route(&addr, 64, idev->dev, 0, 0);
 	}
Signature · 1 line
2.1.0
#5 lore raw

PATCH v2 5/8 ipv6: collapse state_lock and lock

In reply to Hannes Frederic Sowa
Cc Erik Kline <[email protected]>
Cc Fernando Gont <[email protected]>
Cc Lorenzo Colitti <[email protected]>
Cc YOSHIFUJI Hideaki/吉藤英明 <[email protected]>
---
 include/net/if_inet6.h |  3 +--
 net/ipv6/addrconf.c    | 31 +++++++++++++++----------------
 2 files changed, 16 insertions(+), 18 deletions(-)
include/net/if_inet6.h +1 -2
index 98e5f95..d89397a 100644
@@ -41,13 +41,12 @@ enum {
 struct inet6_ifaddr {
 	struct in6_addr		addr;
 	__u32			prefix_len;
-	
+
 	/* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
 	__u32			valid_lft;
 	__u32			prefered_lft;
 	atomic_t		refcnt;
 	spinlock_t		lock;
-	spinlock_t		state_lock;
 
 	int			state;
 
net/ipv6/addrconf.c +15 -16
index c2357b6..1cc5320 100644
@@ -873,7 +873,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
 		ifa->peer_addr = *peer_addr;
 
 	spin_lock_init(&ifa->lock);
-	spin_lock_init(&ifa->state_lock);
 	INIT_DELAYED_WORK(&ifa->dad_work, addrconf_dad_work);
 	INIT_HLIST_NODE(&ifa->addr_lst);
 	ifa->scope = scope;
@@ -1016,10 +1015,10 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 
 	ASSERT_RTNL();
 
-	spin_lock_bh(&ifp->state_lock);
+	spin_lock_bh(&ifp->lock);
 	state = ifp->state;
 	ifp->state = INET6_IFADDR_STATE_DEAD;
-	spin_unlock_bh(&ifp->state_lock);
+	spin_unlock_bh(&ifp->lock);
 
 	if (state == INET6_IFADDR_STATE_DEAD)
 		goto out;
@@ -1699,12 +1698,12 @@ static int addrconf_dad_end(struct inet6_ifaddr *ifp)
 {
 	int err = -ENOENT;
 
-	spin_lock_bh(&ifp->state_lock);
+	spin_lock_bh(&ifp->lock);
 	if (ifp->state == INET6_IFADDR_STATE_DAD) {
 		ifp->state = INET6_IFADDR_STATE_POSTDAD;
 		err = 0;
 	}
-	spin_unlock_bh(&ifp->state_lock);
+	spin_unlock_bh(&ifp->lock);
 
 	return err;
 }
@@ -1737,10 +1736,10 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 		}
 	}
 
-	spin_lock_bh(&ifp->state_lock);
+	spin_lock_bh(&ifp->lock);
 	/* transition from _POSTDAD to _ERRDAD */
 	ifp->state = INET6_IFADDR_STATE_ERRDAD;
-	spin_unlock_bh(&ifp->state_lock);
+	spin_unlock_bh(&ifp->lock);
 
 	addrconf_mod_dad_work(ifp, 0);
 }
@@ -2369,7 +2368,7 @@ ok:
 			u32 stored_lft;
 
 			/* update lifetime (RFC2462 5.5.3 e) */
-			spin_lock(&ifp->lock);
+			spin_lock_bh(&ifp->lock);
 			now = jiffies;
 			if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
 				stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
@@ -2399,12 +2398,12 @@ ok:
 				ifp->tstamp = now;
 				flags = ifp->flags;
 				ifp->flags &= ~IFA_F_DEPRECATED;
-				spin_unlock(&ifp->lock);
+				spin_unlock_bh(&ifp->lock);
 
 				if (!(flags&IFA_F_TENTATIVE))
 					ipv6_ifa_notify(0, ifp);
 			} else
-				spin_unlock(&ifp->lock);
+				spin_unlock_bh(&ifp->lock);
 
 			manage_tempaddrs(in6_dev, ifp, valid_lft, prefered_lft,
 					 create, now);
@@ -3265,10 +3264,10 @@ restart:
 
 		write_unlock_bh(&idev->lock);
 
-		spin_lock_bh(&ifa->state_lock);
+		spin_lock_bh(&ifa->lock);
 		state = ifa->state;
 		ifa->state = INET6_IFADDR_STATE_DEAD;
-		spin_unlock_bh(&ifa->state_lock);
+		spin_unlock_bh(&ifa->lock);
 
 		if (state != INET6_IFADDR_STATE_DEAD) {
 			__ipv6_ifa_notify(RTM_DELADDR, ifa);
@@ -3426,12 +3425,12 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp)
 {
 	bool begin_dad = false;
 
-	spin_lock_bh(&ifp->state_lock);
+	spin_lock_bh(&ifp->lock);
 	if (ifp->state != INET6_IFADDR_STATE_DEAD) {
 		ifp->state = INET6_IFADDR_STATE_PREDAD;
 		begin_dad = true;
 	}
-	spin_unlock_bh(&ifp->state_lock);
+	spin_unlock_bh(&ifp->lock);
 
 	if (begin_dad)
 		addrconf_mod_dad_work(ifp, 0);
@@ -3453,7 +3452,7 @@ static void addrconf_dad_work(struct work_struct *w)
 
 	rtnl_lock();
 
-	spin_lock_bh(&ifp->state_lock);
+	spin_lock_bh(&ifp->lock);
 	if (ifp->state == INET6_IFADDR_STATE_PREDAD) {
 		action = DAD_BEGIN;
 		ifp->state = INET6_IFADDR_STATE_DAD;
@@ -3461,7 +3460,7 @@ static void addrconf_dad_work(struct work_struct *w)
 		action = DAD_ABORT;
 		ifp->state = INET6_IFADDR_STATE_POSTDAD;
 	}
-	spin_unlock_bh(&ifp->state_lock);
+	spin_unlock_bh(&ifp->lock);
 
 	if (action == DAD_BEGIN) {
 		addrconf_dad_begin(ifp);
Signature · 1 line
2.1.0
#6 lore raw

PATCH v2 6/8 ipv6: do retries on stable privacy addresses

In reply to Hannes Frederic Sowa

If a DAD conflict is detected, we want to retry privacy stable address generation up to idgen_retries (= 3) times with a delay of idgen_delay (= 1 second). Add the logic to addrconf_dad_failure.

By design, we don't clean up dad failed permanent addresses.

Cc Erik Kline <[email protected]>
Cc Fernando Gont <[email protected]>
Cc Lorenzo Colitti <[email protected]>
Cc YOSHIFUJI Hideaki/吉藤英明 <[email protected]>
---
 include/net/if_inet6.h |  1 +
 net/ipv6/addrconf.c    | 57 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 55 insertions(+), 3 deletions(-)
include/net/if_inet6.h +1 -0
index d89397a..1c8b682 100644
@@ -52,6 +52,7 @@ struct inet6_ifaddr {
 
 	__u32			flags;
 	__u8			dad_probes;
+	__u8			stable_privacy_retry;
 
 	__u16			scope;
 
net/ipv6/addrconf.c +54 -3

76 lines not on this page · raw message

Signature · 1 line
2.1.0
#7 lore raw

PATCH v2 7/8 ipv6: introduce idgen_delay and idgen_retries knobs

In reply to Hannes Frederic Sowa

This is specified by RFC 7217.

Cc Erik Kline <[email protected]>
Cc Fernando Gont <[email protected]>
Cc Lorenzo Colitti <[email protected]>
Cc YOSHIFUJI Hideaki/吉藤英明 <[email protected]>
---
 include/net/netns/ipv6.h   |  2 ++
 net/ipv6/addrconf.c        | 11 ++++-------
 net/ipv6/af_inet6.c        |  2 ++
 net/ipv6/sysctl_net_ipv6.c | 16 ++++++++++++++++
 4 files changed, 24 insertions(+), 7 deletions(-)
include/net/netns/ipv6.h +2 -0
index ca0db12..d2527bf 100644
@@ -32,6 +32,8 @@ struct netns_sysctl_ipv6 {
 	int icmpv6_time;
 	int anycast_src_echo_reply;
 	int fwmark_reflect;
+	int idgen_retries;
+	int idgen_delay;
 };
 
 struct netns_ipv6 {
net/ipv6/addrconf.c +4 -7
index 9b51fdb..d2d2383 100644
@@ -1712,6 +1712,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 {
 	struct in6_addr addr;
 	struct inet6_dev *idev = ifp->idev;
+	struct net *net = dev_net(ifp->idev->dev);
 
 	if (addrconf_dad_end(ifp)) {
 		in6_ifa_put(ifp);
@@ -1730,11 +1731,9 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 		struct inet6_ifaddr *ifp2;
 		u32 valid_lft, preferred_lft;
 		int pfxlen = ifp->prefix_len;
-		const unsigned int idgen_retries = 3;
-		const unsigned int idgen_delay = 1 * HZ;
 		int retries = ifp->stable_privacy_retry + 1;
 
-		if (retries > idgen_retries) {
+		if (retries > net->ipv6.sysctl.idgen_retries) {
 			net_info_ratelimited("%s: privacy stable address generation failed because of DAD conflicts!\n",
 					     ifp->idev->dev->name);
 			goto errdad;
@@ -1769,7 +1768,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 		ifp2->state = INET6_IFADDR_STATE_PREDAD;
 		spin_unlock_bh(&ifp2->lock);
 
-		addrconf_mod_dad_work(ifp2, idgen_delay);
+		addrconf_mod_dad_work(ifp2, net->ipv6.sysctl.idgen_delay);
 		in6_ifa_put(ifp2);
 lock_errdad:
 		spin_lock_bh(&ifp->lock);
@@ -2899,8 +2898,6 @@ static int ipv6_generate_stable_address(struct in6_addr *address,
 					u8 dad_count,
 					const struct inet6_dev *idev)
 {
-	static const int idgen_retries = 3;
-
 	static DEFINE_SPINLOCK(lock);
 	static __u32 digest[SHA_DIGEST_WORDS];
 	static __u32 workspace[SHA_WORKSPACE_WORDS];
@@ -2950,7 +2947,7 @@ retry:
 
 	if (ipv6_reserved_interfaceid(temp)) {
 		dad_count++;
-		if (dad_count > idgen_retries)
+		if (dad_count > dev_net(idev->dev)->ipv6.sysctl.idgen_retries)
 			return -1;
 		goto retry;
 	}
net/ipv6/af_inet6.c +2 -0
index 6bafcc2..d8dcc52 100644
@@ -766,6 +766,8 @@ static int __net_init inet6_net_init(struct net *net)
 	net->ipv6.sysctl.icmpv6_time = 1*HZ;
 	net->ipv6.sysctl.flowlabel_consistency = 1;
 	net->ipv6.sysctl.auto_flowlabels = 0;
+	net->ipv6.sysctl.idgen_retries = 3;
+	net->ipv6.sysctl.idgen_delay = 1 * HZ;
 	atomic_set(&net->ipv6.fib6_sernum, 1);
 
 	err = ipv6_init_mibs(net);
net/ipv6/sysctl_net_ipv6.c +16 -0
index c5c10fa..30f5a4a 100644
@@ -54,6 +54,20 @@ static struct ctl_table ipv6_table_template[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
+	{
+		.procname	= "idgen_retries",
+		.data		= &init_net.ipv6.sysctl.idgen_retries,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "idgen_delay",
+		.data		= &init_net.ipv6.sysctl.idgen_delay,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_jiffies,
+	},
 	{ }
 };
 
@@ -93,6 +107,8 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
 	ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency;
 	ipv6_table[3].data = &net->ipv6.sysctl.auto_flowlabels;
 	ipv6_table[4].data = &net->ipv6.sysctl.fwmark_reflect;
+	ipv6_table[5].data = &net->ipv6.sysctl.idgen_retries;
+	ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay;
 
 	ipv6_route_table = ipv6_route_sysctl_init(net);
 	if (!ipv6_route_table)
Signature · 1 line
2.1.0
#8 lore raw

PATCH v2 8/8 ipv6: add documentation for stable_secret, idgen_delay and idgen_retries knobs

In reply to Hannes Frederic Sowa
Cc Erik Kline <[email protected]>
Cc Fernando Gont <[email protected]>
Cc Lorenzo Colitti <[email protected]>
Cc YOSHIFUJI Hideaki/吉藤英明 <[email protected]>
---
 Documentation/networking/ip-sysctl.txt | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
Documentation/networking/ip-sysctl.txt +25 -0
index 6c07c2b..071fb18 100644
@@ -1220,6 +1220,17 @@ anycast_src_echo_reply - BOOLEAN
 	FALSE: disabled
 	Default: FALSE
 
+idgen_delay - INTEGER
+	Controls the delay in seconds after which time to retry
+	privacy stable address generation if a DAD conflict is
+	detected.
+	Default: 1 (as specified in RFC7217)
+
+idgen_retries - INTEGER
+	Controls the number of retries to generate a stable privacy
+	address if a DAD conflict is detected.
+	Default: 3 (as specified in RFC7217)
+
 mld_qrv - INTEGER
 	Controls the MLD query robustness variable (see RFC3810 9.1).
 	Default: 2 (as specified by RFC3810 9.1)
@@ -1540,6 +1551,20 @@ use_optimistic - BOOLEAN
 		0: disabled (default)
 		1: enabled
 
+stable_secret - IPv6 address
+	This IPv6 address will be used as a secret to generate IPv6
+	addresses for link-local addresses and autoconfigured
+	ones. All addresses generated after setting this secret will
+	be stable privacy ones by default. This can be changed via the
+	addrgenmode ip-link. conf/default/stable_secret is used as the
+	secret for the namespace, the interface specific ones can
+	overwrite that. Writes to conf/all/stable_secret are refused.
+
+	It is recommended to generate this secret during installation
+	of a system and keep it stable after that.
+
+	By default the stable secret is unset.
+
 icmp/*:
 ratelimit - INTEGER
 	Limit the maximal rates for sending ICMPv6 packets.
Signature · 1 line
2.1.0
maintainer Applied
#9 lore raw
In reply to Hannes Frederic Sowa

From: Hannes Frederic Sowa <[email protected]>
Date: Mon, 23 Mar 2015 23:35:58 +0100

Quoted 5 lines

this is an implementation of basic support for RFC7217 stable privacy addresses. Please review and consider for net-next.

v2:
* Correct references to RFC 7212 -> RFC 7217 in documentation patch (thanks, Eric!)

Applied, thanks!