.seg6_require_hmac      = 0,
 #endif
        .enhanced_dad           = 1,
+       .addr_gen_mode          = IN6_ADDR_GEN_MODE_EUI64,
 };
 
 static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
        .seg6_require_hmac      = 0,
 #endif
        .enhanced_dad           = 1,
+       .addr_gen_mode          = IN6_ADDR_GEN_MODE_EUI64,
 };
 
 /* Check if a valid qdisc is available */
        memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
 
        if (ndev->cnf.stable_secret.initialized)
-               ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+               ndev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
        else
-               ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64;
+               ndev->cnf.addr_gen_mode = ipv6_devconf_dflt.addr_gen_mode;
 
        ndev->cnf.mtu6 = dev->mtu;
        ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
 
 static bool is_addr_mode_generate_stable(struct inet6_dev *idev)
 {
-       return idev->addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
-              idev->addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM;
+       return idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
+              idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM;
 }
 
 int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
 
        ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
 
-       switch (idev->addr_gen_mode) {
+       switch (idev->cnf.addr_gen_mode) {
        case IN6_ADDR_GEN_MODE_RANDOM:
                ipv6_gen_mode_random_init(idev);
                /* fallthrough */
 
        /* this device type has no EUI support */
        if (dev->type == ARPHRD_NONE &&
-           idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)
-               idev->addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM;
+           idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)
+               idev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM;
 
        addrconf_addr_gen(idev, false);
 }
        array[DEVCONF_SEG6_REQUIRE_HMAC] = cnf->seg6_require_hmac;
 #endif
        array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad;
+       array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode;
 }
 
 static inline size_t inet6_ifla6_size(void)
        if (!nla)
                goto nla_put_failure;
 
-       if (nla_put_u8(skb, IFLA_INET6_ADDR_GEN_MODE, idev->addr_gen_mode))
+       if (nla_put_u8(skb, IFLA_INET6_ADDR_GEN_MODE, idev->cnf.addr_gen_mode))
                goto nla_put_failure;
 
        read_lock_bh(&idev->lock);
        return nla_parse_nested(tb, IFLA_INET6_MAX, nla, inet6_af_policy);
 }
 
+static int check_addr_gen_mode(int mode)
+{
+       if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
+           mode != IN6_ADDR_GEN_MODE_NONE &&
+           mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
+           mode != IN6_ADDR_GEN_MODE_RANDOM)
+               return -EINVAL;
+       return 1;
+}
+
+static int check_stable_privacy(struct inet6_dev *idev, struct net *net,
+                               int mode)
+{
+       if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
+           !idev->cnf.stable_secret.initialized &&
+           !net->ipv6.devconf_dflt->stable_secret.initialized)
+               return -EINVAL;
+       return 1;
+}
+
 static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
 {
        int err = -EINVAL;
        if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
                u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
 
-               if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
-                   mode != IN6_ADDR_GEN_MODE_NONE &&
-                   mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
-                   mode != IN6_ADDR_GEN_MODE_RANDOM)
-                       return -EINVAL;
-
-               if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
-                   !idev->cnf.stable_secret.initialized &&
-                   !dev_net(dev)->ipv6.devconf_dflt->stable_secret.initialized)
+               if (check_addr_gen_mode(mode) < 0 ||
+                   check_stable_privacy(idev, dev_net(dev), mode) < 0)
                        return -EINVAL;
 
-               idev->addr_gen_mode = mode;
+               idev->cnf.addr_gen_mode = mode;
                err = 0;
        }
 
        return ret;
 }
 
+static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
+                                        void __user *buffer, size_t *lenp,
+                                        loff_t *ppos)
+{
+       int ret = 0;
+       int new_val;
+       struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
+       struct net *net = (struct net *)ctl->extra2;
+
+       ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+
+       if (write) {
+               new_val = *((int *)ctl->data);
+
+               if (check_addr_gen_mode(new_val) < 0)
+                       return -EINVAL;
+
+               /* request for default */
+               if (&net->ipv6.devconf_dflt->addr_gen_mode == ctl->data) {
+                       ipv6_devconf_dflt.addr_gen_mode = new_val;
+
+               /* request for individual net device */
+               } else {
+                       if (!idev)
+                               return ret;
+
+                       if (check_stable_privacy(idev, net, new_val) < 0)
+                               return -EINVAL;
+
+                       if (idev->cnf.addr_gen_mode != new_val) {
+                               idev->cnf.addr_gen_mode = new_val;
+                               rtnl_lock();
+                               addrconf_dev_config(idev->dev);
+                               rtnl_unlock();
+                       }
+               }
+       }
+
+       return ret;
+}
+
 static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
                                         void __user *buffer, size_t *lenp,
                                         loff_t *ppos)
                        struct inet6_dev *idev = __in6_dev_get(dev);
 
                        if (idev) {
-                               idev->addr_gen_mode =
+                               idev->cnf.addr_gen_mode =
                                        IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
                        }
                }
        } else {
                struct inet6_dev *idev = ctl->extra1;
 
-               idev->addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+               idev->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
        }
 
 out:
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+       {
+               .procname               = "addr_gen_mode",
+               .data                   = &ipv6_devconf.addr_gen_mode,
+               .maxlen                 = sizeof(int),
+               .mode                   = 0644,
+               .proc_handler   = addrconf_sysctl_addr_gen_mode,
+       },
        {
                /* sentinel */
        }