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

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

Merge branch 'per-nexthop-offload'



Jiri Pirko says:

====================
ipv4: fib: Provide per-nexthop offload indication

Ido says:

Offload indication for IPv4 routes is currently set in the FIB info's
flags. When multipath routes are employed, this can lead to a route being
marked as offloaded although only one of its nexthops is actually
offloaded.

Instead, this patchset aims to proivde a higher resolution for the offload
indication and report it on a per-nexthop basis.

Example output from patched iproute:

$ ip route show 192.168.200.0/24
192.168.200.0/24
        nexthop via 192.168.100.2 dev enp3s0np7 weight 1 offload
        nexthop via 192.168.101.3 dev enp3s0np8 weight 1

And once the second gateway is resolved:

$ ip route show 192.168.200.0/24
192.168.200.0/24
        nexthop via 192.168.100.2 dev enp3s0np7 weight 1 offload
        nexthop via 192.168.101.3 dev enp3s0np8 weight 1 offload

First patch teaches the kernel to look for the offload indication in the
nexthop flags. Patches 2-5 adjust current capable drivers to provide
offload indication on a per-nexthop basis. Last patch removes no longer
used functions to set offload indication in the FIB info's flags.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9820355f 2202e35d
Loading
Loading
Loading
Loading
+60 −13
Original line number Original line Diff line number Diff line
@@ -394,7 +394,6 @@ struct mlxsw_sp_fib_entry {
	enum mlxsw_sp_fib_entry_type type;
	enum mlxsw_sp_fib_entry_type type;
	struct list_head nexthop_group_node;
	struct list_head nexthop_group_node;
	struct mlxsw_sp_nexthop_group *nh_group;
	struct mlxsw_sp_nexthop_group *nh_group;
	bool offloaded;
};
};


struct mlxsw_sp_fib4_entry {
struct mlxsw_sp_fib4_entry {
@@ -1653,6 +1652,24 @@ mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
	return 0;
	return 0;
}
}


static void
mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry,
				   enum mlxsw_reg_ralue_op op, int err);

static void
mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group *nh_grp)
{
	enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_WRITE;
	struct mlxsw_sp_fib_entry *fib_entry;

	list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
		if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node,
						      fib_entry))
			continue;
		mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
	}
}

static void
static void
mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
			       struct mlxsw_sp_nexthop_group *nh_grp)
			       struct mlxsw_sp_nexthop_group *nh_grp)
@@ -1740,6 +1757,10 @@ mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
		dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n");
		dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n");
		goto set_trap;
		goto set_trap;
	}
	}

	/* Offload state within the group changed, so update the flags. */
	mlxsw_sp_nexthop_fib_entries_refresh(nh_grp);

	return;
	return;


set_trap:
set_trap:
@@ -2103,13 +2124,45 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
	}
	}
}
}


static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
static void
mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
{
	struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
	int i;

	if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) {
		nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
		return;
	}

	for (i = 0; i < nh_grp->count; i++) {
		struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];

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

static void
mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
{
{
	fib_entry->offloaded = true;
	struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
	int i;

	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;
	}
}

static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
{
	switch (fib_entry->fib_node->fib->proto) {
	switch (fib_entry->fib_node->fib->proto) {
	case MLXSW_SP_L3_PROTO_IPV4:
	case MLXSW_SP_L3_PROTO_IPV4:
		fib_info_offload_inc(fib_entry->nh_group->key.fi);
		mlxsw_sp_fib4_entry_offload_set(fib_entry);
		break;
		break;
	case MLXSW_SP_L3_PROTO_IPV6:
	case MLXSW_SP_L3_PROTO_IPV6:
		WARN_ON_ONCE(1);
		WARN_ON_ONCE(1);
@@ -2121,13 +2174,11 @@ mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
{
{
	switch (fib_entry->fib_node->fib->proto) {
	switch (fib_entry->fib_node->fib->proto) {
	case MLXSW_SP_L3_PROTO_IPV4:
	case MLXSW_SP_L3_PROTO_IPV4:
		fib_info_offload_dec(fib_entry->nh_group->key.fi);
		mlxsw_sp_fib4_entry_offload_unset(fib_entry);
		break;
		break;
	case MLXSW_SP_L3_PROTO_IPV6:
	case MLXSW_SP_L3_PROTO_IPV6:
		WARN_ON_ONCE(1);
		WARN_ON_ONCE(1);
	}
	}

	fib_entry->offloaded = false;
}
}


static void
static void
@@ -2136,17 +2187,13 @@ mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry,
{
{
	switch (op) {
	switch (op) {
	case MLXSW_REG_RALUE_OP_WRITE_DELETE:
	case MLXSW_REG_RALUE_OP_WRITE_DELETE:
		if (!fib_entry->offloaded)
			return;
		return mlxsw_sp_fib_entry_offload_unset(fib_entry);
		return mlxsw_sp_fib_entry_offload_unset(fib_entry);
	case MLXSW_REG_RALUE_OP_WRITE_WRITE:
	case MLXSW_REG_RALUE_OP_WRITE_WRITE:
		if (err)
		if (err)
			return;
			return;
		if (mlxsw_sp_fib_entry_should_offload(fib_entry) &&
		if (mlxsw_sp_fib_entry_should_offload(fib_entry))
		    !fib_entry->offloaded)
			mlxsw_sp_fib_entry_offload_set(fib_entry);
			mlxsw_sp_fib_entry_offload_set(fib_entry);
		else if (!mlxsw_sp_fib_entry_should_offload(fib_entry) &&
		else if (!mlxsw_sp_fib_entry_should_offload(fib_entry))
			 fib_entry->offloaded)
			mlxsw_sp_fib_entry_offload_unset(fib_entry);
			mlxsw_sp_fib_entry_offload_unset(fib_entry);
		return;
		return;
	default:
	default:
+3 −3
Original line number Original line Diff line number Diff line
@@ -2761,7 +2761,7 @@ static int ofdpa_fib4_add(struct rocker *rocker,
				  fen_info->tb_id, 0);
				  fen_info->tb_id, 0);
	if (err)
	if (err)
		return err;
		return err;
	fib_info_offload_inc(fen_info->fi);
	fen_info->fi->fib_nh->nh_flags |= RTNH_F_OFFLOAD;
	return 0;
	return 0;
}
}


@@ -2776,7 +2776,7 @@ static int ofdpa_fib4_del(struct rocker *rocker,
	ofdpa_port = ofdpa_port_dev_lower_find(fen_info->fi->fib_dev, rocker);
	ofdpa_port = ofdpa_port_dev_lower_find(fen_info->fi->fib_dev, rocker);
	if (!ofdpa_port)
	if (!ofdpa_port)
		return 0;
		return 0;
	fib_info_offload_dec(fen_info->fi);
	fen_info->fi->fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
	return ofdpa_port_fib_ipv4(ofdpa_port, htonl(fen_info->dst),
	return ofdpa_port_fib_ipv4(ofdpa_port, htonl(fen_info->dst),
				   fen_info->dst_len, fen_info->fi,
				   fen_info->dst_len, fen_info->fi,
				   fen_info->tb_id, OFDPA_OP_FLAG_REMOVE);
				   fen_info->tb_id, OFDPA_OP_FLAG_REMOVE);
@@ -2803,7 +2803,7 @@ static void ofdpa_fib4_abort(struct rocker *rocker)
						       rocker);
						       rocker);
		if (!ofdpa_port)
		if (!ofdpa_port)
			continue;
			continue;
		fib_info_offload_dec(flow_entry->fi);
		flow_entry->fi->fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
		ofdpa_flow_tbl_del(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
		ofdpa_flow_tbl_del(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
				   flow_entry);
				   flow_entry);
	}
	}
+0 −13
Original line number Original line Diff line number Diff line
@@ -124,7 +124,6 @@ struct fib_info {
#ifdef CONFIG_IP_ROUTE_MULTIPATH
#ifdef CONFIG_IP_ROUTE_MULTIPATH
	int			fib_weight;
	int			fib_weight;
#endif
#endif
	unsigned int		fib_offload_cnt;
	struct rcu_head		rcu;
	struct rcu_head		rcu;
	struct fib_nh		fib_nh[0];
	struct fib_nh		fib_nh[0];
#define fib_dev		fib_nh[0].nh_dev
#define fib_dev		fib_nh[0].nh_dev
@@ -177,18 +176,6 @@ struct fib_result_nl {


__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);


static inline void fib_info_offload_inc(struct fib_info *fi)
{
	fi->fib_offload_cnt++;
	fi->fib_flags |= RTNH_F_OFFLOAD;
}

static inline void fib_info_offload_dec(struct fib_info *fi)
{
	if (--fi->fib_offload_cnt == 0)
		fi->fib_flags &= ~RTNH_F_OFFLOAD;
}

#define FIB_RES_SADDR(net, res)				\
#define FIB_RES_SADDR(net, res)				\
	((FIB_RES_NH(res).nh_saddr_genid ==		\
	((FIB_RES_NH(res).nh_saddr_genid ==		\
	  atomic_read(&(net)->ipv4.dev_addr_genid)) ?	\
	  atomic_read(&(net)->ipv4.dev_addr_genid)) ?	\
+2 −0
Original line number Original line Diff line number Diff line
@@ -1342,6 +1342,8 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
			    IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev))
			    IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev))
				rtm->rtm_flags |= RTNH_F_DEAD;
				rtm->rtm_flags |= RTNH_F_DEAD;
		}
		}
		if (fi->fib_nh->nh_flags & RTNH_F_OFFLOAD)
			rtm->rtm_flags |= RTNH_F_OFFLOAD;
#ifdef CONFIG_IP_ROUTE_CLASSID
#ifdef CONFIG_IP_ROUTE_CLASSID
		if (fi->fib_nh[0].nh_tclassid &&
		if (fi->fib_nh[0].nh_tclassid &&
		    nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid))
		    nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid))