Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3cf53d82 authored by Erik Kline's avatar Erik Kline Committed by Ruchi Kandoi
Browse files

net: ipv6: Add a sysctl to make optimistic addresses useful candidates



Add a sysctl that causes an interface's optimistic addresses
to be considered equivalent to other non-deprecated addresses
for source address selection purposes.  Preferred addresses
will still take precedence over optimistic addresses, subject
to other ranking in the source address selection algorithm.

This is useful where different interfaces are connected to
different networks from different ISPs (e.g., a cell network
and a home wifi network).

The current behaviour complies with RFC 3484/6724, and it
makes sense if the host has only one interface, or has
multiple interfaces on the same network (same or cooperating
administrative domain(s), but not in the multiple distinct
networks case.

For example, if a mobile device has an IPv6 address on an LTE
network and then connects to IPv6-enabled wifi, while the wifi
IPv6 address is undergoing DAD, IPv6 connections will try use
the wifi default route with the LTE IPv6 address, and will get
stuck until they time out.

Also, because optimistic nodes can receive frames, issue
an RTM_NEWADDR as soon as DAD starts (with the IFA_F_OPTIMSTIC
flag appropriately set).  A second RTM_NEWADDR is sent if DAD
completes (the address flags have changed), otherwise an
RTM_DELADDR is sent.

Also: add an entry in ip-sysctl.txt for optimistic_dad.

[cherry-pick of net-next 7fd2561e4ebdd070ebba6d3326c4c5b13942323f]

Signed-off-by: default avatarErik Kline <ek@google.com>
Acked-by: default avatarLorenzo Colitti <lorenzo@google.com>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Bug: 17769720
Change-Id: Ic7e50781c607e1f3a492d9ce7395946efb95c533
parent a8e63b36
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -1470,6 +1470,19 @@ suppress_frag_ndisc - INTEGER
	1 - (default) discard fragmented neighbor discovery packets
	1 - (default) discard fragmented neighbor discovery packets
	0 - allow fragmented neighbor discovery packets
	0 - allow fragmented neighbor discovery packets


optimistic_dad - BOOLEAN
	Whether to perform Optimistic Duplicate Address Detection (RFC 4429).
		0: disabled (default)
		1: enabled

use_optimistic - BOOLEAN
	If enabled, do not classify optimistic addresses as deprecated during
	source address selection.  Preferred addresses will still be chosen
	before optimistic addresses, subject to other ranking in the source
	address selection algorithm.
		0: disabled (default)
		1: enabled

icmp/*:
icmp/*:
ratelimit - INTEGER
ratelimit - INTEGER
	Limit the maximal rates for sending ICMPv6 packets.
	Limit the maximal rates for sending ICMPv6 packets.
+1 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ struct ipv6_devconf {
	__s32		accept_ra_from_local;
	__s32		accept_ra_from_local;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
	__s32		optimistic_dad;
	__s32		optimistic_dad;
	__s32		use_optimistic;
#endif
#endif
#ifdef CONFIG_IPV6_MROUTE
#ifdef CONFIG_IPV6_MROUTE
	__s32		mc_forwarding;
	__s32		mc_forwarding;
+1 −0
Original line number Original line Diff line number Diff line
@@ -165,6 +165,7 @@ enum {
	DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
	DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
	DEVCONF_SUPPRESS_FRAG_NDISC,
	DEVCONF_SUPPRESS_FRAG_NDISC,
	DEVCONF_ACCEPT_RA_FROM_LOCAL,
	DEVCONF_ACCEPT_RA_FROM_LOCAL,
	DEVCONF_USE_OPTIMISTIC,
	DEVCONF_MAX
	DEVCONF_MAX
};
};


+44 −2
Original line number Original line Diff line number Diff line
@@ -1172,6 +1172,9 @@ enum {
	IPV6_SADDR_RULE_PRIVACY,
	IPV6_SADDR_RULE_PRIVACY,
	IPV6_SADDR_RULE_ORCHID,
	IPV6_SADDR_RULE_ORCHID,
	IPV6_SADDR_RULE_PREFIX,
	IPV6_SADDR_RULE_PREFIX,
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
	IPV6_SADDR_RULE_NOT_OPTIMISTIC,
#endif
	IPV6_SADDR_RULE_MAX
	IPV6_SADDR_RULE_MAX
};
};


@@ -1199,6 +1202,15 @@ static inline int ipv6_saddr_preferred(int type)
	return 0;
	return 0;
}
}


static inline bool ipv6_use_optimistic_addr(struct inet6_dev *idev)
{
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
	return idev && idev->cnf.optimistic_dad && idev->cnf.use_optimistic;
#else
	return false;
#endif
}

static int ipv6_get_saddr_eval(struct net *net,
static int ipv6_get_saddr_eval(struct net *net,
			       struct ipv6_saddr_score *score,
			       struct ipv6_saddr_score *score,
			       struct ipv6_saddr_dst *dst,
			       struct ipv6_saddr_dst *dst,
@@ -1259,10 +1271,16 @@ static int ipv6_get_saddr_eval(struct net *net,
		score->scopedist = ret;
		score->scopedist = ret;
		break;
		break;
	case IPV6_SADDR_RULE_PREFERRED:
	case IPV6_SADDR_RULE_PREFERRED:
	    {
		/* Rule 3: Avoid deprecated and optimistic addresses */
		/* Rule 3: Avoid deprecated and optimistic addresses */
		u8 avoid = IFA_F_DEPRECATED;

		if (!ipv6_use_optimistic_addr(score->ifa->idev))
			avoid |= IFA_F_OPTIMISTIC;
		ret = ipv6_saddr_preferred(score->addr_type) ||
		ret = ipv6_saddr_preferred(score->addr_type) ||
		      !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
		      !(score->ifa->flags & avoid);
		break;
		break;
	    }
#ifdef CONFIG_IPV6_MIP6
#ifdef CONFIG_IPV6_MIP6
	case IPV6_SADDR_RULE_HOA:
	case IPV6_SADDR_RULE_HOA:
	    {
	    {
@@ -1308,6 +1326,14 @@ static int ipv6_get_saddr_eval(struct net *net,
			ret = score->ifa->prefix_len;
			ret = score->ifa->prefix_len;
		score->matchlen = ret;
		score->matchlen = ret;
		break;
		break;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
	case IPV6_SADDR_RULE_NOT_OPTIMISTIC:
		/* Optimistic addresses still have lower precedence than other
		 * preferred addresses.
		 */
		ret = !(score->ifa->flags & IFA_F_OPTIMISTIC);
		break;
#endif
	default:
	default:
		ret = 0;
		ret = 0;
	}
	}
@@ -3250,8 +3276,15 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
	 * Optimistic nodes can start receiving
	 * Optimistic nodes can start receiving
	 * Frames right away
	 * Frames right away
	 */
	 */
	if (ifp->flags & IFA_F_OPTIMISTIC)
	if (ifp->flags & IFA_F_OPTIMISTIC) {
		ip6_ins_rt(ifp->rt);
		ip6_ins_rt(ifp->rt);
		if (ipv6_use_optimistic_addr(idev)) {
			/* Because optimistic nodes can use this address,
			 * notify listeners. If DAD fails, RTM_DELADDR is sent.
			 */
			ipv6_ifa_notify(RTM_NEWADDR, ifp);
		}
	}


	addrconf_dad_kick(ifp);
	addrconf_dad_kick(ifp);
out:
out:
@@ -4359,6 +4392,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
	array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
	array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
	array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
	array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
	array[DEVCONF_USE_OPTIMISTIC] = cnf->use_optimistic;
#endif
#endif
#ifdef CONFIG_IPV6_MROUTE
#ifdef CONFIG_IPV6_MROUTE
	array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
	array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
@@ -5192,6 +5226,14 @@ static struct addrconf_sysctl_table
			.proc_handler   = proc_dointvec,
			.proc_handler   = proc_dointvec,


		},
		},
		{
			.procname       = "use_optimistic",
			.data           = &ipv6_devconf.use_optimistic,
			.maxlen         = sizeof(int),
			.mode           = 0644,
			.proc_handler   = proc_dointvec,

		},
#endif
#endif
#ifdef CONFIG_IPV6_MROUTE
#ifdef CONFIG_IPV6_MROUTE
		{
		{