ipv4: nexthop version of fib_info_nh_uses_dev
Similar to the last path, need to fix fib_info_nh_uses_dev for
external nexthops to avoid referencing multiple nh_grp structs.
Move the device check in fib_info_nh_uses_dev to a helper and
create a nexthop version that is called if the fib_info uses an
external nexthop.
Fixes: 430a049190
("nexthop: Add support for nexthop groups")
Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
af7888ad9e
commit
1fd1c768f3
|
@ -447,6 +447,16 @@ static inline int fib_num_tclassid_users(struct net *net)
|
||||||
#endif
|
#endif
|
||||||
int fib_unmerge(struct net *net);
|
int fib_unmerge(struct net *net);
|
||||||
|
|
||||||
|
static inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc,
|
||||||
|
const struct net_device *dev)
|
||||||
|
{
|
||||||
|
if (nhc->nhc_dev == dev ||
|
||||||
|
l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Exported by fib_semantics.c */
|
/* Exported by fib_semantics.c */
|
||||||
int ip_fib_check_default(__be32 gw, struct net_device *dev);
|
int ip_fib_check_default(__be32 gw, struct net_device *dev);
|
||||||
int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
|
int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
|
||||||
|
|
|
@ -266,6 +266,31 @@ struct fib_nh_common *nexthop_get_nhc_lookup(const struct nexthop *nh,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool nexthop_uses_dev(const struct nexthop *nh,
|
||||||
|
const struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct nh_info *nhi;
|
||||||
|
|
||||||
|
if (nh->is_group) {
|
||||||
|
struct nh_group *nhg = rcu_dereference(nh->nh_grp);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < nhg->num_nh; i++) {
|
||||||
|
struct nexthop *nhe = nhg->nh_entries[i].nh;
|
||||||
|
|
||||||
|
nhi = rcu_dereference(nhe->nh_info);
|
||||||
|
if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nhi = rcu_dereference(nh->nh_info);
|
||||||
|
if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned int fib_info_num_path(const struct fib_info *fi)
|
static inline unsigned int fib_info_num_path(const struct fib_info *fi)
|
||||||
{
|
{
|
||||||
if (unlikely(fi->nh))
|
if (unlikely(fi->nh))
|
||||||
|
|
|
@ -309,19 +309,20 @@ bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev)
|
||||||
{
|
{
|
||||||
bool dev_match = false;
|
bool dev_match = false;
|
||||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||||
|
if (unlikely(fi->nh)) {
|
||||||
|
dev_match = nexthop_uses_dev(fi->nh, dev);
|
||||||
|
} else {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
for (ret = 0; ret < fib_info_num_path(fi); ret++) {
|
for (ret = 0; ret < fib_info_num_path(fi); ret++) {
|
||||||
const struct fib_nh_common *nhc = fib_info_nhc(fi, ret);
|
const struct fib_nh_common *nhc = fib_info_nhc(fi, ret);
|
||||||
|
|
||||||
if (nhc->nhc_dev == dev) {
|
if (nhc_l3mdev_matches_dev(nhc, dev)) {
|
||||||
dev_match = true;
|
|
||||||
break;
|
|
||||||
} else if (l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) {
|
|
||||||
dev_match = true;
|
dev_match = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (fib_info_nhc(fi, 0)->nhc_dev == dev)
|
if (fib_info_nhc(fi, 0)->nhc_dev == dev)
|
||||||
dev_match = true;
|
dev_match = true;
|
||||||
|
|
Loading…
Reference in New Issue