Skip to content

Commit dd3abc4

Browse files
committed
ipv6 route: Prefer outgoing interface with source address assigned.
Outgoing interface is selected by the route decision if unspecified. Let's prefer routes via interface(s) with the address assigned if we have multiple routes with same cost. With help from Naohiro Ooiwa <nooiwa@miraclelinux.com>. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
1 parent 1b34be7 commit dd3abc4

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

net/ipv6/route.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,20 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
237237

238238
static inline struct rt6_info *rt6_device_match(struct net *net,
239239
struct rt6_info *rt,
240+
struct in6_addr *saddr,
240241
int oif,
241242
int flags)
242243
{
243244
struct rt6_info *local = NULL;
244245
struct rt6_info *sprt;
245246

246-
if (oif) {
247-
for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
248-
struct net_device *dev = sprt->rt6i_dev;
247+
if (!oif && ipv6_addr_any(saddr))
248+
goto out;
249+
250+
for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
251+
struct net_device *dev = sprt->rt6i_dev;
252+
253+
if (oif) {
249254
if (dev->ifindex == oif)
250255
return sprt;
251256
if (dev->flags & IFF_LOOPBACK) {
@@ -259,14 +264,21 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
259264
}
260265
local = sprt;
261266
}
267+
} else {
268+
if (ipv6_chk_addr(net, saddr, dev,
269+
flags & RT6_LOOKUP_F_IFACE))
270+
return sprt;
262271
}
272+
}
263273

274+
if (oif) {
264275
if (local)
265276
return local;
266277

267278
if (flags & RT6_LOOKUP_F_IFACE)
268279
return net->ipv6.ip6_null_entry;
269280
}
281+
out:
270282
return rt;
271283
}
272284

@@ -539,7 +551,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
539551
fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
540552
restart:
541553
rt = fn->leaf;
542-
rt = rt6_device_match(net, rt, fl->oif, flags);
554+
rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags);
543555
BACKTRACK(net, &fl->fl6_src);
544556
out:
545557
dst_use(&rt->u.dst, jiffies);

0 commit comments

Comments
 (0)