ipv6: introduce idgen_delay and idgen_retries knobs
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Mon, 23 Mar 2015 22:36:05 +0000 (23:36 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 24 Mar 2015 02:12:09 +0000 (22:12 -0400)
This is specified by RFC 7217.

Cc: Erik Kline <ek@google.com>
Cc: Fernando Gont <fgont@si6networks.com>
Cc: Lorenzo Colitti <lorenzo@google.com>
Cc: YOSHIFUJI Hideaki/吉藤英明 <hideaki.yoshifuji@miraclelinux.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/netns/ipv6.h
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/sysctl_net_ipv6.c

index ca0db12..d2527bf 100644 (file)
@@ -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 {
index 9b51fdb..d2d2383 100644 (file)
@@ -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;
        }
index 6bafcc2..d8dcc52 100644 (file)
@@ -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);
index c5c10fa..30f5a4a 100644 (file)
@@ -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)