net: vrf: Implement get_saddr for IPv6

IPv6 source address selection needs to consider the real egress route.
Similar to IPv4 implement a get_saddr6 method which is called if
source address has not been set.  The get_saddr6 method does a full
lookup which means pulling a route from the VRF FIB table and properly
considering linklocal/multicast destination addresses. Lookup failures
(eg., unreachable) then cause the source address selection to fail
which gets propagated back to the caller.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David Ahern
2016-06-16 16:24:25 -07:00
committed by David S. Miller
parent a2e2ff560f
commit 0d240e7811
4 changed files with 86 additions and 2 deletions
+24
View File
@@ -162,6 +162,30 @@ int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4)
}
EXPORT_SYMBOL_GPL(l3mdev_get_saddr);
int l3mdev_get_saddr6(struct net *net, const struct sock *sk,
struct flowi6 *fl6)
{
struct net_device *dev;
int rc = 0;
if (fl6->flowi6_oif) {
rcu_read_lock();
dev = dev_get_by_index_rcu(net, fl6->flowi6_oif);
if (dev && netif_is_l3_slave(dev))
dev = netdev_master_upper_dev_get_rcu(dev);
if (dev && netif_is_l3_master(dev) &&
dev->l3mdev_ops->l3mdev_get_saddr6)
rc = dev->l3mdev_ops->l3mdev_get_saddr6(dev, sk, fl6);
rcu_read_unlock();
}
return rc;
}
EXPORT_SYMBOL_GPL(l3mdev_get_saddr6);
/**
* l3mdev_fib_rule_match - Determine if flowi references an
* L3 master device