}
 }
 
+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;
+}
+
 void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
 {
        struct prefix_info *pinfo;
                                       in6_dev->token.s6_addr + 8, 8);
                                read_unlock_bh(&in6_dev->lock);
                                tokenized = true;
-                       } else if (in6_dev->addr_gen_mode ==
-                                  IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
+                       } else if (is_addr_mode_generate_stable(in6_dev) &&
                                   !ipv6_generate_stable_address(&addr, 0,
                                                                 in6_dev)) {
                                addr_flags |= IFA_F_STABLE_PRIVACY;
        return 0;
 }
 
+static void ipv6_gen_mode_random_init(struct inet6_dev *idev)
+{
+       struct ipv6_stable_secret *s = &idev->cnf.stable_secret;
+
+       if (s->initialized)
+               return;
+       s = &idev->cnf.stable_secret;
+       get_random_bytes(&s->secret, sizeof(s->secret));
+       s->initialized = true;
+}
+
 static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
 {
        struct in6_addr addr;
 
        ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
 
-       if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY) {
+       switch (idev->addr_gen_mode) {
+       case IN6_ADDR_GEN_MODE_RANDOM:
+               ipv6_gen_mode_random_init(idev);
+               /* fallthrough */
+       case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
                if (!ipv6_generate_stable_address(&addr, 0, idev))
                        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) {
+               break;
+       case IN6_ADDR_GEN_MODE_EUI64:
                /* addrconf_add_linklocal also adds a prefix_route and we
                 * only need to care about prefix routes if ipv6_generate_eui64
                 * couldn't generate one.
                        addrconf_add_linklocal(idev, &addr, 0);
                else if (prefix_route)
                        addrconf_prefix_route(&addr, 64, idev->dev, 0, 0);
+               break;
+       case IN6_ADDR_GEN_MODE_NONE:
+       default:
+               /* will not add any link local address */
+               break;
        }
 }
 
            (dev->type != ARPHRD_INFINIBAND) &&
            (dev->type != ARPHRD_IEEE1394) &&
            (dev->type != ARPHRD_TUNNEL6) &&
-           (dev->type != ARPHRD_6LOWPAN)) {
+           (dev->type != ARPHRD_6LOWPAN) &&
+           (dev->type != ARPHRD_NONE)) {
                /* Alas, we support only Ethernet autoconfiguration. */
                return;
        }
        if (IS_ERR(idev))
                return;
 
+       /* 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;
+
        addrconf_addr_gen(idev, false);
 }
 
 
                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_STABLE_PRIVACY &&
+                   mode != IN6_ADDR_GEN_MODE_RANDOM)
                        return -EINVAL;
 
                if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&