Merge branch 'l3mdev-send-enslaved'
David Ahern says: ==================== net: l3mdev: Allow send on enslaved interface First patch preps for the second. The second is required for several use cases such as ping on an interface and BFD that need to send packets on a specific interface, including ones enslaved to a VRF device. v2 - fixed brackets on both patches per comment from DaveM ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
20e61335d8
@ -648,6 +648,8 @@ static int vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
|
||||
|
||||
fl4->flowi4_flags |= FLOWI_FLAG_SKIP_NH_OIF;
|
||||
fl4->flowi4_iif = LOOPBACK_IFINDEX;
|
||||
/* make sure oif is set to VRF device for lookup */
|
||||
fl4->flowi4_oif = dev->ifindex;
|
||||
fl4->flowi4_tos = tos & IPTOS_RT_MASK;
|
||||
fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
|
||||
RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
|
||||
|
@ -130,52 +130,9 @@ static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int l3mdev_get_saddr(struct net *net, int ifindex,
|
||||
struct flowi4 *fl4)
|
||||
{
|
||||
struct net_device *dev;
|
||||
int rc = 0;
|
||||
int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4);
|
||||
|
||||
if (ifindex) {
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
dev = dev_get_by_index_rcu(net, ifindex);
|
||||
if (dev && netif_is_l3_master(dev) &&
|
||||
dev->l3mdev_ops->l3mdev_get_saddr) {
|
||||
rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
|
||||
const struct flowi6 *fl6)
|
||||
{
|
||||
if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rt6_dst)
|
||||
return dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
|
||||
const struct flowi6 *fl6)
|
||||
{
|
||||
struct dst_entry *dst = NULL;
|
||||
struct net_device *dev;
|
||||
|
||||
dev = dev_get_by_index(net, fl6->flowi6_oif);
|
||||
if (dev) {
|
||||
dst = l3mdev_get_rt6_dst(dev, fl6);
|
||||
dev_put(dev);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6);
|
||||
|
||||
#else
|
||||
|
||||
@ -233,14 +190,7 @@ static inline int l3mdev_get_saddr(struct net *net, int ifindex,
|
||||
}
|
||||
|
||||
static inline
|
||||
struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
|
||||
const struct flowi6 *fl6)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline
|
||||
struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
|
||||
const struct flowi6 *fl6)
|
||||
struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2146,6 +2146,7 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
||||
unsigned int flags = 0;
|
||||
struct fib_result res;
|
||||
struct rtable *rth;
|
||||
int master_idx;
|
||||
int orig_oif;
|
||||
int err = -ENETUNREACH;
|
||||
|
||||
@ -2155,6 +2156,9 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
||||
|
||||
orig_oif = fl4->flowi4_oif;
|
||||
|
||||
master_idx = l3mdev_master_ifindex_by_index(net, fl4->flowi4_oif);
|
||||
if (master_idx)
|
||||
fl4->flowi4_oif = master_idx;
|
||||
fl4->flowi4_iif = LOOPBACK_IFINDEX;
|
||||
fl4->flowi4_tos = tos & IPTOS_RT_MASK;
|
||||
fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
|
||||
|
@ -1190,7 +1190,7 @@ struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
|
||||
struct dst_entry *dst;
|
||||
bool any_src;
|
||||
|
||||
dst = l3mdev_rt6_dst_by_oif(net, fl6);
|
||||
dst = l3mdev_get_rt6_dst(net, fl6);
|
||||
if (dst)
|
||||
return dst;
|
||||
|
||||
|
@ -97,3 +97,66 @@ u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
|
||||
return tb_id;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l3mdev_fib_table_by_index);
|
||||
|
||||
/**
|
||||
* l3mdev_get_rt6_dst - IPv6 route lookup based on flow. Returns
|
||||
* cached route for L3 master device if relevant
|
||||
* to flow
|
||||
* @net: network namespace for device index lookup
|
||||
* @fl6: IPv6 flow struct for lookup
|
||||
*/
|
||||
|
||||
struct dst_entry *l3mdev_get_rt6_dst(struct net *net,
|
||||
const struct flowi6 *fl6)
|
||||
{
|
||||
struct dst_entry *dst = NULL;
|
||||
struct net_device *dev;
|
||||
|
||||
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_rt6_dst)
|
||||
dst = dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l3mdev_get_rt6_dst);
|
||||
|
||||
/**
|
||||
* l3mdev_get_saddr - get source address for a flow based on an interface
|
||||
* enslaved to an L3 master device
|
||||
* @net: network namespace for device index lookup
|
||||
* @ifindex: Interface index
|
||||
* @fl4: IPv4 flow struct
|
||||
*/
|
||||
|
||||
int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4)
|
||||
{
|
||||
struct net_device *dev;
|
||||
int rc = 0;
|
||||
|
||||
if (ifindex) {
|
||||
rcu_read_lock();
|
||||
|
||||
dev = dev_get_by_index_rcu(net, ifindex);
|
||||
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_saddr)
|
||||
rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(l3mdev_get_saddr);
|
||||
|
Loading…
x
Reference in New Issue
Block a user