Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f4d6749 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-Move-fib_nh-and-fib6_nh-to-a-common-struct'



David Ahern says:

====================
net: Move fib_nh and fib6_nh to a common struct

First set of three with the end goal of enabling IPv6 gateways with IPv4
routes.

This set refactors ipv4 and ipv6 code to create init and release
helpers for each protocol and moving common elements to a fib_nh_common
struct.

v3
- split the reject setting into 2 with helper to the checks. This
  avoids changing cfg->fc_flags in fib6_nh_init

v2
- addressed Ido's comments: cleanup on failure path in nh_init helpers,
  ordering in fib6_nh_release, and removal of RTF_GATEWAY from fib6_info
  uses in mlxsw
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 113e59d0 979e276e
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
	/* Handle add/replace event */
	if (fi->fib_nhs == 1) {
		if (__mlx5_lag_is_active(ldev)) {
			struct net_device *nh_dev = fi->fib_nh[0].nh_dev;
			struct net_device *nh_dev = fi->fib_nh[0].fib_nh_dev;
			int i = mlx5_lag_dev_get_netdev_idx(ldev, nh_dev);

			mlx5_lag_set_port_affinity(ldev, ++i);
@@ -134,10 +134,10 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev,
		return;

	/* Verify next hops are ports of the same hca */
	if (!(fi->fib_nh[0].nh_dev == ldev->pf[0].netdev &&
	      fi->fib_nh[1].nh_dev == ldev->pf[1].netdev) &&
	    !(fi->fib_nh[0].nh_dev == ldev->pf[1].netdev &&
	      fi->fib_nh[1].nh_dev == ldev->pf[0].netdev)) {
	if (!(fi->fib_nh[0].fib_nh_dev == ldev->pf[0].netdev &&
	      fi->fib_nh[1].fib_nh_dev == ldev->pf[1].netdev) &&
	    !(fi->fib_nh[0].fib_nh_dev == ldev->pf[1].netdev &&
	      fi->fib_nh[1].fib_nh_dev == ldev->pf[0].netdev)) {
		mlx5_core_warn(ldev->pf[0].dev, "Multipath offload require two ports of the same HCA\n");
		return;
	}
@@ -167,7 +167,7 @@ static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,

	/* nh added/removed */
	if (event == FIB_EVENT_NH_DEL) {
		int i = mlx5_lag_dev_get_netdev_idx(ldev, fib_nh->nh_dev);
		int i = mlx5_lag_dev_get_netdev_idx(ldev, fib_nh->fib_nh_dev);

		if (i >= 0) {
			i = (i + 1) % 2 + 1; /* peer port */
+31 −29
Original line number Diff line number Diff line
@@ -2873,12 +2873,13 @@ mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp,
		return false;

	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
		struct fib6_nh *fib6_nh = &mlxsw_sp_rt6->rt->fib6_nh;
		struct in6_addr *gw;
		int ifindex, weight;

		ifindex = mlxsw_sp_rt6->rt->fib6_nh.nh_dev->ifindex;
		weight = mlxsw_sp_rt6->rt->fib6_nh.nh_weight;
		gw = &mlxsw_sp_rt6->rt->fib6_nh.nh_gw;
		ifindex = fib6_nh->fib_nh_dev->ifindex;
		weight = fib6_nh->fib_nh_weight;
		gw = &fib6_nh->fib_nh_gw6;
		if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp, gw, ifindex,
							 weight))
			return false;
@@ -2944,7 +2945,7 @@ mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed)
	struct net_device *dev;

	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
		dev = mlxsw_sp_rt6->rt->fib6_nh.nh_dev;
		dev = mlxsw_sp_rt6->rt->fib6_nh.fib_nh_dev;
		val ^= dev->ifindex;
	}

@@ -3610,7 +3611,7 @@ static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp *mlxsw_sp,
					const struct fib_nh *fib_nh,
					enum mlxsw_sp_ipip_type *p_ipipt)
{
	struct net_device *dev = fib_nh->nh_dev;
	struct net_device *dev = fib_nh->fib_nh_dev;

	return dev &&
	       fib_nh->nh_parent->fib_type == RTN_UNICAST &&
@@ -3637,7 +3638,7 @@ static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp *mlxsw_sp,
				       struct fib_nh *fib_nh)
{
	const struct mlxsw_sp_ipip_ops *ipip_ops;
	struct net_device *dev = fib_nh->nh_dev;
	struct net_device *dev = fib_nh->fib_nh_dev;
	struct mlxsw_sp_ipip_entry *ipip_entry;
	struct mlxsw_sp_rif *rif;
	int err;
@@ -3681,18 +3682,18 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
				  struct mlxsw_sp_nexthop *nh,
				  struct fib_nh *fib_nh)
{
	struct net_device *dev = fib_nh->nh_dev;
	struct net_device *dev = fib_nh->fib_nh_dev;
	struct in_device *in_dev;
	int err;

	nh->nh_grp = nh_grp;
	nh->key.fib_nh = fib_nh;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
	nh->nh_weight = fib_nh->nh_weight;
	nh->nh_weight = fib_nh->fib_nh_weight;
#else
	nh->nh_weight = 1;
#endif
	memcpy(&nh->gw_addr, &fib_nh->nh_gw, sizeof(fib_nh->nh_gw));
	memcpy(&nh->gw_addr, &fib_nh->fib_nh_gw4, sizeof(fib_nh->fib_nh_gw4));
	err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
	if (err)
		return err;
@@ -3705,7 +3706,7 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,

	in_dev = __in_dev_get_rtnl(dev);
	if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
	    fib_nh->nh_flags & RTNH_F_LINKDOWN)
	    fib_nh->fib_nh_flags & RTNH_F_LINKDOWN)
		return 0;

	err = mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
@@ -3804,7 +3805,7 @@ static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp *mlxsw_sp,
				   const struct fib_info *fi)
{
	return fi->fib_nh->nh_scope == RT_SCOPE_LINK ||
	return fi->fib_nh->fib_nh_scope == RT_SCOPE_LINK ||
	       mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, fi->fib_nh, NULL);
}

@@ -3946,9 +3947,9 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
		struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
		struct fib6_info *rt = mlxsw_sp_rt6->rt;

		if (nh->rif && nh->rif->dev == rt->fib6_nh.nh_dev &&
		if (nh->rif && nh->rif->dev == rt->fib6_nh.fib_nh_dev &&
		    ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
				    &rt->fib6_nh.nh_gw))
				    &rt->fib6_nh.fib_nh_gw6))
			return nh;
		continue;
	}
@@ -3966,7 +3967,7 @@ mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
	    fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE ||
	    fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP ||
	    fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP) {
		nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
		nh_grp->nexthops->key.fib_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
		return;
	}

@@ -3974,9 +3975,9 @@ mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
		struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];

		if (nh->offloaded)
			nh->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
			nh->key.fib_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
		else
			nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
			nh->key.fib_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
	}
}

@@ -3992,7 +3993,7 @@ mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
	for (i = 0; i < nh_grp->count; i++) {
		struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];

		nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
		nh->key.fib_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
	}
}

@@ -4008,19 +4009,20 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
	if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
	    fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE) {
		list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
				 list)->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD;
				 list)->rt->fib6_nh.fib_nh_flags |= RTNH_F_OFFLOAD;
		return;
	}

	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
		struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
		struct fib6_nh *fib6_nh = &mlxsw_sp_rt6->rt->fib6_nh;
		struct mlxsw_sp_nexthop *nh;

		nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
		if (nh && nh->offloaded)
			mlxsw_sp_rt6->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD;
			fib6_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
		else
			mlxsw_sp_rt6->rt->fib6_nh.nh_flags &= ~RTNH_F_OFFLOAD;
			fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
	}
}

@@ -4035,7 +4037,7 @@ mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
		struct fib6_info *rt = mlxsw_sp_rt6->rt;

		rt->fib6_nh.nh_flags &= ~RTNH_F_OFFLOAD;
		rt->fib6_nh.fib_nh_flags &= ~RTNH_F_OFFLOAD;
	}
}

@@ -4913,7 +4915,7 @@ static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
{
	/* RTF_CACHE routes are ignored */
	return (rt->fib6_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
	return !(rt->fib6_flags & RTF_ADDRCONF) && rt->fib6_nh.fib_nh_has_gw;
}

static struct fib6_info *
@@ -4972,8 +4974,8 @@ static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
					const struct fib6_info *rt,
					enum mlxsw_sp_ipip_type *ret)
{
	return rt->fib6_nh.nh_dev &&
	       mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh.nh_dev, ret);
	return rt->fib6_nh.fib_nh_dev &&
	       mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh.fib_nh_dev, ret);
}

static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
@@ -4983,7 +4985,7 @@ static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
{
	const struct mlxsw_sp_ipip_ops *ipip_ops;
	struct mlxsw_sp_ipip_entry *ipip_entry;
	struct net_device *dev = rt->fib6_nh.nh_dev;
	struct net_device *dev = rt->fib6_nh.fib_nh_dev;
	struct mlxsw_sp_rif *rif;
	int err;

@@ -5026,11 +5028,11 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
				  struct mlxsw_sp_nexthop *nh,
				  const struct fib6_info *rt)
{
	struct net_device *dev = rt->fib6_nh.nh_dev;
	struct net_device *dev = rt->fib6_nh.fib_nh_dev;

	nh->nh_grp = nh_grp;
	nh->nh_weight = rt->fib6_nh.nh_weight;
	memcpy(&nh->gw_addr, &rt->fib6_nh.nh_gw, sizeof(nh->gw_addr));
	nh->nh_weight = rt->fib6_nh.fib_nh_weight;
	memcpy(&nh->gw_addr, &rt->fib6_nh.fib_nh_gw6, sizeof(nh->gw_addr));
	mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);

	list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
@@ -5053,7 +5055,7 @@ static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
				    const struct fib6_info *rt)
{
	return rt->fib6_flags & RTF_GATEWAY ||
	return rt->fib6_nh.fib_nh_has_gw ||
	       mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
}

+5 −5
Original line number Diff line number Diff line
@@ -2288,11 +2288,11 @@ static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port, __be32 dst,

	nh = fi->fib_nh;
	nh_on_port = (fi->fib_dev == ofdpa_port->dev);
	has_gw = !!nh->nh_gw;
	has_gw = !!nh->fib_nh_gw4;

	if (has_gw && nh_on_port) {
		err = ofdpa_port_ipv4_nh(ofdpa_port, flags,
					 nh->nh_gw, &index);
					 nh->fib_nh_gw4, &index);
		if (err)
			return err;

@@ -2749,7 +2749,7 @@ static int ofdpa_fib4_add(struct rocker *rocker,
				  fen_info->tb_id, 0);
	if (err)
		return err;
	fen_info->fi->fib_nh->nh_flags |= RTNH_F_OFFLOAD;
	fen_info->fi->fib_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
	return 0;
}

@@ -2764,7 +2764,7 @@ static int ofdpa_fib4_del(struct rocker *rocker,
	ofdpa_port = ofdpa_port_dev_lower_find(fen_info->fi->fib_dev, rocker);
	if (!ofdpa_port)
		return 0;
	fen_info->fi->fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
	fen_info->fi->fib_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
	return ofdpa_port_fib_ipv4(ofdpa_port, htonl(fen_info->dst),
				   fen_info->dst_len, fen_info->fi,
				   fen_info->tb_id, OFDPA_OP_FLAG_REMOVE);
@@ -2791,7 +2791,7 @@ static void ofdpa_fib4_abort(struct rocker *rocker)
						       rocker);
		if (!ofdpa_port)
			continue;
		flow_entry->fi->fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
		flow_entry->fi->fib_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
		ofdpa_flow_tbl_del(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
				   flow_entry);
	}
+14 −0
Original line number Diff line number Diff line
@@ -237,6 +237,20 @@ static inline struct in_device *__in_dev_get_rtnl(const struct net_device *dev)
	return rtnl_dereference(dev->ip_ptr);
}

/* called with rcu_read_lock or rtnl held */
static inline bool ip_ignore_linkdown(const struct net_device *dev)
{
	struct in_device *in_dev;
	bool rc = false;

	in_dev = rcu_dereference_rtnl(dev->ip_ptr);
	if (in_dev &&
	    IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev))
		rc = true;

	return rc;
}

static inline struct neigh_parms *__in_dev_arp_parms_get_rcu(const struct net_device *dev)
{
	struct in_device *in_dev = __in_dev_get_rcu(dev);
+8 −0
Original line number Diff line number Diff line
@@ -425,6 +425,14 @@ static inline void in6_dev_hold(struct inet6_dev *idev)
	refcount_inc(&idev->refcnt);
}

/* called with rcu_read_lock held */
static inline bool ip6_ignore_linkdown(const struct net_device *dev)
{
	const struct inet6_dev *idev = __in6_dev_get(dev);

	return !!idev->cnf.ignore_routes_with_linkdown;
}

void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);

static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
Loading