Commit 717f1019 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'flow_offload-add-tc-vlan-push_eth-and-pop_eth-actions'

Roi Dayan says:

====================
flow_offload: add tc vlan push_eth and pop_eth actions

Offloading vlan push_eth and pop_eth actions is needed in order to
correctly offload MPLSoUDP encap and decap flows, this series extends
the flow offload API to support these actions and updates mlx5 to
parse them.
====================

Link: https://lore.kernel.org/r/20220315110211.1581468-1-roid@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents a860352e 725726fd
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -35,6 +35,13 @@ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = {
	NULL, /* FLOW_ACTION_CT_METADATA, */
	&mlx5e_tc_act_mpls_push,
	&mlx5e_tc_act_mpls_pop,
	NULL, /* FLOW_ACTION_MPLS_MANGLE, */
	NULL, /* FLOW_ACTION_GATE, */
	NULL, /* FLOW_ACTION_PPPOE_PUSH, */
	NULL, /* FLOW_ACTION_JUMP, */
	NULL, /* FLOW_ACTION_PIPE, */
	&mlx5e_tc_act_vlan,
	&mlx5e_tc_act_vlan,
};

/* Must be aligned with enum flow_action_id. */
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ struct mlx5e_tc_act_parse_state {
	bool encap;
	bool decap;
	bool mpls_push;
	bool eth_push;
	bool eth_pop;
	bool ptype_host;
	const struct ip_tunnel_info *tun_info;
	struct mlx5e_mpls_info mpls_info;
+10 −0
Original line number Diff line number Diff line
@@ -125,6 +125,16 @@ tc_act_can_offload_mirred(struct mlx5e_tc_act_parse_state *parse_state,
		return false;
	}

	if (parse_state->eth_pop && !parse_state->mpls_push) {
		NL_SET_ERR_MSG_MOD(extack, "vlan pop eth is supported only with mpls push");
		return false;
	}

	if (flow_flag_test(parse_state->flow, L3_TO_L2_DECAP) && !parse_state->eth_push) {
		NL_SET_ERR_MSG_MOD(extack, "mpls pop is only supported with vlan eth push");
		return false;
	}

	if (mlx5e_is_ft_flow(flow) && out_dev == priv->netdev) {
		/* Ignore forward to self rules generated
		 * by adding both mlx5 devs to the flow table
+4 −3
Original line number Diff line number Diff line
@@ -57,12 +57,13 @@ tc_act_can_offload_mpls_pop(struct mlx5e_tc_act_parse_state *parse_state,
	filter_dev = attr->parse_attr->filter_dev;

	/* we only support mpls pop if it is the first action
	 * or it is second action after tunnel key unset
	 * and the filter net device is bareudp. Subsequent
	 * actions can be pedit and the last can be mirred
	 * egress redirect.
	 */
	if (act_index) {
		NL_SET_ERR_MSG_MOD(extack, "mpls pop supported only as first action");
	if ((act_index == 1 && !parse_state->decap) || act_index > 1) {
		NL_SET_ERR_MSG_MOD(extack, "mpls pop supported only as first action or with decap");
		return false;
	}

@@ -80,7 +81,7 @@ tc_act_parse_mpls_pop(struct mlx5e_tc_act_parse_state *parse_state,
		      struct mlx5e_priv *priv,
		      struct mlx5_flow_attr *attr)
{
	attr->parse_attr->eth.h_proto = act->mpls_pop.proto;
	attr->esw_attr->eth.h_proto = act->mpls_pop.proto;
	attr->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
	flow_flag_set(parse_state->flow, L3_TO_L2_DECAP);

+7 −52
Original line number Diff line number Diff line
@@ -42,13 +42,12 @@ set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
	return -EOPNOTSUPP;
}

static int
parse_pedit_to_modify_hdr(struct mlx5e_priv *priv,
int
mlx5e_tc_act_pedit_parse_action(struct mlx5e_priv *priv,
				const struct flow_action_entry *act, int namespace,
			  struct mlx5e_tc_flow_parse_attr *parse_attr,
				struct pedit_headers_action *hdrs,
				struct netlink_ext_ack *extack)
{
	struct pedit_headers_action *hdrs = parse_attr->hdrs;
	u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1;
	u8 htype = act->mangle.htype;
	int err = -EOPNOTSUPP;
@@ -79,46 +78,6 @@ parse_pedit_to_modify_hdr(struct mlx5e_priv *priv,
	return err;
}

static int
parse_pedit_to_reformat(const struct flow_action_entry *act,
			struct mlx5e_tc_flow_parse_attr *parse_attr,
			struct netlink_ext_ack *extack)
{
	u32 mask, val, offset;
	u32 *p;

	if (act->id != FLOW_ACTION_MANGLE) {
		NL_SET_ERR_MSG_MOD(extack, "Unsupported action id");
		return -EOPNOTSUPP;
	}

	if (act->mangle.htype != FLOW_ACT_MANGLE_HDR_TYPE_ETH) {
		NL_SET_ERR_MSG_MOD(extack, "Only Ethernet modification is supported");
		return -EOPNOTSUPP;
	}

	mask = ~act->mangle.mask;
	val = act->mangle.val;
	offset = act->mangle.offset;
	p = (u32 *)&parse_attr->eth;
	*(p + (offset >> 2)) |= (val & mask);

	return 0;
}

int
mlx5e_tc_act_pedit_parse_action(struct mlx5e_priv *priv,
				const struct flow_action_entry *act, int namespace,
				struct mlx5e_tc_flow_parse_attr *parse_attr,
				struct mlx5e_tc_flow *flow,
				struct netlink_ext_ack *extack)
{
	if (flow && flow_flag_test(flow, L3_TO_L2_DECAP))
		return parse_pedit_to_reformat(act, parse_attr, extack);

	return parse_pedit_to_modify_hdr(priv, act, namespace, parse_attr, extack);
}

static bool
tc_act_can_offload_pedit(struct mlx5e_tc_act_parse_state *parse_state,
			 const struct flow_action_entry *act,
@@ -141,20 +100,16 @@ tc_act_parse_pedit(struct mlx5e_tc_act_parse_state *parse_state,

	ns_type = mlx5e_get_flow_namespace(flow);

	err = mlx5e_tc_act_pedit_parse_action(flow->priv, act, ns_type, attr->parse_attr,
					      flow, parse_state->extack);
	err = mlx5e_tc_act_pedit_parse_action(flow->priv, act, ns_type, attr->parse_attr->hdrs,
					      parse_state->extack);
	if (err)
		return err;

	if (flow_flag_test(flow, L3_TO_L2_DECAP))
		goto out;

	attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;

	if (ns_type == MLX5_FLOW_NAMESPACE_FDB)
		esw_attr->split_count = esw_attr->out_count;

out:
	return 0;
}

Loading