Skip to content

Commit 7fd2561

Browse files
Erik Klinedavem330
authored andcommitted
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. Signed-off-by: Erik Kline <ek@google.com> Acked-by: Lorenzo Colitti <lorenzo@google.com> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 8b243a6 commit 7fd2561

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

Documentation/networking/ip-sysctl.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,19 @@ suppress_frag_ndisc - INTEGER
14601460
1 - (default) discard fragmented neighbor discovery packets
14611461
0 - allow fragmented neighbor discovery packets
14621462

1463+
optimistic_dad - BOOLEAN
1464+
Whether to perform Optimistic Duplicate Address Detection (RFC 4429).
1465+
0: disabled (default)
1466+
1: enabled
1467+
1468+
use_optimistic - BOOLEAN
1469+
If enabled, do not classify optimistic addresses as deprecated during
1470+
source address selection. Preferred addresses will still be chosen
1471+
before optimistic addresses, subject to other ranking in the source
1472+
address selection algorithm.
1473+
0: disabled (default)
1474+
1: enabled
1475+
14631476
icmp/*:
14641477
ratelimit - INTEGER
14651478
Limit the maximal rates for sending ICMPv6 packets.

include/linux/ipv6.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct ipv6_devconf {
4242
__s32 accept_ra_from_local;
4343
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
4444
__s32 optimistic_dad;
45+
__s32 use_optimistic;
4546
#endif
4647
#ifdef CONFIG_IPV6_MROUTE
4748
__s32 mc_forwarding;

include/uapi/linux/ipv6.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ enum {
164164
DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
165165
DEVCONF_SUPPRESS_FRAG_NDISC,
166166
DEVCONF_ACCEPT_RA_FROM_LOCAL,
167+
DEVCONF_USE_OPTIMISTIC,
167168
DEVCONF_MAX
168169
};
169170

net/ipv6/addrconf.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,9 @@ enum {
11701170
IPV6_SADDR_RULE_PRIVACY,
11711171
IPV6_SADDR_RULE_ORCHID,
11721172
IPV6_SADDR_RULE_PREFIX,
1173+
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
1174+
IPV6_SADDR_RULE_NOT_OPTIMISTIC,
1175+
#endif
11731176
IPV6_SADDR_RULE_MAX
11741177
};
11751178

@@ -1197,6 +1200,15 @@ static inline int ipv6_saddr_preferred(int type)
11971200
return 0;
11981201
}
11991202

1203+
static inline bool ipv6_use_optimistic_addr(struct inet6_dev *idev)
1204+
{
1205+
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
1206+
return idev && idev->cnf.optimistic_dad && idev->cnf.use_optimistic;
1207+
#else
1208+
return false;
1209+
#endif
1210+
}
1211+
12001212
static int ipv6_get_saddr_eval(struct net *net,
12011213
struct ipv6_saddr_score *score,
12021214
struct ipv6_saddr_dst *dst,
@@ -1257,10 +1269,16 @@ static int ipv6_get_saddr_eval(struct net *net,
12571269
score->scopedist = ret;
12581270
break;
12591271
case IPV6_SADDR_RULE_PREFERRED:
1272+
{
12601273
/* Rule 3: Avoid deprecated and optimistic addresses */
1274+
u8 avoid = IFA_F_DEPRECATED;
1275+
1276+
if (!ipv6_use_optimistic_addr(score->ifa->idev))
1277+
avoid |= IFA_F_OPTIMISTIC;
12611278
ret = ipv6_saddr_preferred(score->addr_type) ||
1262-
!(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
1279+
!(score->ifa->flags & avoid);
12631280
break;
1281+
}
12641282
#ifdef CONFIG_IPV6_MIP6
12651283
case IPV6_SADDR_RULE_HOA:
12661284
{
@@ -1306,6 +1324,14 @@ static int ipv6_get_saddr_eval(struct net *net,
13061324
ret = score->ifa->prefix_len;
13071325
score->matchlen = ret;
13081326
break;
1327+
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
1328+
case IPV6_SADDR_RULE_NOT_OPTIMISTIC:
1329+
/* Optimistic addresses still have lower precedence than other
1330+
* preferred addresses.
1331+
*/
1332+
ret = !(score->ifa->flags & IFA_F_OPTIMISTIC);
1333+
break;
1334+
#endif
13091335
default:
13101336
ret = 0;
13111337
}
@@ -3222,8 +3248,15 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
32223248
* Optimistic nodes can start receiving
32233249
* Frames right away
32243250
*/
3225-
if (ifp->flags & IFA_F_OPTIMISTIC)
3251+
if (ifp->flags & IFA_F_OPTIMISTIC) {
32263252
ip6_ins_rt(ifp->rt);
3253+
if (ipv6_use_optimistic_addr(idev)) {
3254+
/* Because optimistic nodes can use this address,
3255+
* notify listeners. If DAD fails, RTM_DELADDR is sent.
3256+
*/
3257+
ipv6_ifa_notify(RTM_NEWADDR, ifp);
3258+
}
3259+
}
32273260

32283261
addrconf_dad_kick(ifp);
32293262
out:
@@ -4330,6 +4363,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
43304363
array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
43314364
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
43324365
array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
4366+
array[DEVCONF_USE_OPTIMISTIC] = cnf->use_optimistic;
43334367
#endif
43344368
#ifdef CONFIG_IPV6_MROUTE
43354369
array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
@@ -5155,6 +5189,14 @@ static struct addrconf_sysctl_table
51555189
.proc_handler = proc_dointvec,
51565190

51575191
},
5192+
{
5193+
.procname = "use_optimistic",
5194+
.data = &ipv6_devconf.use_optimistic,
5195+
.maxlen = sizeof(int),
5196+
.mode = 0644,
5197+
.proc_handler = proc_dointvec,
5198+
5199+
},
51585200
#endif
51595201
#ifdef CONFIG_IPV6_MROUTE
51605202
{

0 commit comments

Comments
 (0)