net/mlx5e: MPLSoUDP decap, use vlan push_eth instead of pedit
Currently action pedit of source and destination MACs is used to fill the MACs in L2 push step in MPLSoUDP decap offload, this isn't aligned to tc SW which use vlan eth_push action to do this. To fix that, offload support for vlan veth_push action is added together with mpls pop action, and deprecate the use of pedit of MACs. Flow example: filter protocol mpls_uc pref 1 flower chain 0 filter protocol mpls_uc pref 1 flower chain 0 handle 0x1 eth_type 8847 mpls_label 555 enc_dst_port 6635 in_hw in_hw_count 1 action order 1: tunnel_key unset pipe index 2 ref 1 bind 1 used_hw_stats delayed action order 2: mpls pop protocol ip pipe index 2 ref 1 bind 1 used_hw_stats delayed action order 3: vlan push_eth dst_mac de:a2:ec:d6:69:c8 src_mac de:a2:ec:d6:69:c8 pipe index 2 ref 1 bind 1 used_hw_stats delayed action order 4: mirred (Egress Redirect to device enp8s0f0_0) stolen index 2 ref 1 bind 1 used_hw_stats delayed Signed-off-by: Maor Dickman <maord@nvidia.com> Reviewed-by: Roi Dayan <roid@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Родитель
ab95465cde
Коммит
697319b295
|
@ -35,6 +35,12 @@ 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,
|
||||
};
|
||||
|
||||
/* Must be aligned with enum flow_action_id. */
|
||||
|
|
|
@ -22,6 +22,7 @@ struct mlx5e_tc_act_parse_state {
|
|||
bool encap;
|
||||
bool decap;
|
||||
bool mpls_push;
|
||||
bool eth_push;
|
||||
bool ptype_host;
|
||||
const struct ip_tunnel_info *tun_info;
|
||||
struct mlx5e_mpls_info mpls_info;
|
||||
|
|
|
@ -125,6 +125,11 @@ tc_act_can_offload_mirred(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -42,13 +42,12 @@ out_err:
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_pedit_to_modify_hdr(struct mlx5e_priv *priv,
|
||||
const struct flow_action_entry *act, int namespace,
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||
struct netlink_ext_ack *extack)
|
||||
int
|
||||
mlx5e_tc_act_pedit_parse_action(struct mlx5e_priv *priv,
|
||||
const struct flow_action_entry *act, int namespace,
|
||||
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 @@ out_err:
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,7 @@ struct pedit_headers_action {
|
|||
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 pedit_headers_action *hdrs,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
#endif /* __MLX5_EN_TC_ACT_PEDIT_H__ */
|
||||
|
|
|
@ -34,7 +34,8 @@ parse_tc_vlan_action(struct mlx5e_priv *priv,
|
|||
const struct flow_action_entry *act,
|
||||
struct mlx5_esw_flow_attr *attr,
|
||||
u32 *action,
|
||||
struct netlink_ext_ack *extack)
|
||||
struct netlink_ext_ack *extack,
|
||||
struct mlx5e_tc_act_parse_state *parse_state)
|
||||
{
|
||||
u8 vlan_idx = attr->total_vlan;
|
||||
|
||||
|
@ -84,6 +85,13 @@ parse_tc_vlan_action(struct mlx5e_priv *priv,
|
|||
*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
|
||||
}
|
||||
break;
|
||||
case FLOW_ACTION_VLAN_PUSH_ETH:
|
||||
if (!flow_flag_test(parse_state->flow, L3_TO_L2_DECAP))
|
||||
return -EOPNOTSUPP;
|
||||
parse_state->eth_push = true;
|
||||
memcpy(attr->eth.h_dest, act->vlan_push_eth.dst, ETH_ALEN);
|
||||
memcpy(attr->eth.h_source, act->vlan_push_eth.src, ETH_ALEN);
|
||||
break;
|
||||
default:
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unexpected action id for VLAN");
|
||||
return -EINVAL;
|
||||
|
@ -109,7 +117,7 @@ mlx5e_tc_act_vlan_add_push_action(struct mlx5e_priv *priv,
|
|||
};
|
||||
int err;
|
||||
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action, extack);
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action, extack, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -139,7 +147,7 @@ mlx5e_tc_act_vlan_add_pop_action(struct mlx5e_priv *priv,
|
|||
priv->netdev->lower_level;
|
||||
while (nest_level--) {
|
||||
err = parse_tc_vlan_action(priv, &vlan_act, attr->esw_attr, &attr->action,
|
||||
extack);
|
||||
extack, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
@ -174,7 +182,7 @@ tc_act_parse_vlan(struct mlx5e_tc_act_parse_state *parse_state,
|
|||
parse_state->extack);
|
||||
} else {
|
||||
err = parse_tc_vlan_action(priv, act, esw_attr, &attr->action,
|
||||
parse_state->extack);
|
||||
parse_state->extack, parse_state);
|
||||
}
|
||||
|
||||
if (err)
|
||||
|
|
|
@ -43,8 +43,8 @@ mlx5e_tc_act_vlan_add_rewrite_action(struct mlx5e_priv *priv, int namespace,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = mlx5e_tc_act_pedit_parse_action(priv, &pedit_act, namespace, parse_attr,
|
||||
NULL, extack);
|
||||
err = mlx5e_tc_act_pedit_parse_action(priv, &pedit_act, namespace, parse_attr->hdrs,
|
||||
extack);
|
||||
*action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||
|
||||
return err;
|
||||
|
|
|
@ -41,7 +41,6 @@ struct mlx5e_tc_flow_parse_attr {
|
|||
struct pedit_headers_action hdrs[__PEDIT_CMD_MAX];
|
||||
struct mlx5e_tc_mod_hdr_acts mod_hdr_acts;
|
||||
int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS];
|
||||
struct ethhdr eth;
|
||||
struct mlx5e_tc_act_parse_state parse_state;
|
||||
};
|
||||
|
||||
|
|
|
@ -906,20 +906,18 @@ int mlx5e_attach_decap(struct mlx5e_priv *priv,
|
|||
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
||||
struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr;
|
||||
struct mlx5_pkt_reformat_params reformat_params;
|
||||
struct mlx5e_tc_flow_parse_attr *parse_attr;
|
||||
struct mlx5e_decap_entry *d;
|
||||
struct mlx5e_decap_key key;
|
||||
uintptr_t hash_key;
|
||||
int err = 0;
|
||||
|
||||
parse_attr = flow->attr->parse_attr;
|
||||
if (sizeof(parse_attr->eth) > MLX5_CAP_ESW(priv->mdev, max_encap_header_size)) {
|
||||
if (sizeof(attr->eth) > MLX5_CAP_ESW(priv->mdev, max_encap_header_size)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"encap header larger than max supported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
key.key = parse_attr->eth;
|
||||
key.key = attr->eth;
|
||||
hash_key = hash_decap_info(&key);
|
||||
mutex_lock(&esw->offloads.decap_tbl_lock);
|
||||
d = mlx5e_decap_get(priv, &key, hash_key);
|
||||
|
@ -949,8 +947,8 @@ int mlx5e_attach_decap(struct mlx5e_priv *priv,
|
|||
|
||||
memset(&reformat_params, 0, sizeof(reformat_params));
|
||||
reformat_params.type = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
|
||||
reformat_params.size = sizeof(parse_attr->eth);
|
||||
reformat_params.data = &parse_attr->eth;
|
||||
reformat_params.size = sizeof(attr->eth);
|
||||
reformat_params.data = &attr->eth;
|
||||
d->pkt_reformat = mlx5_packet_reformat_alloc(priv->mdev,
|
||||
&reformat_params,
|
||||
MLX5_FLOW_NAMESPACE_FDB);
|
||||
|
|
|
@ -474,6 +474,7 @@ struct mlx5_esw_flow_attr {
|
|||
int src_port_rewrite_act_id;
|
||||
} dests[MLX5_MAX_FLOW_FWD_VPORTS];
|
||||
struct mlx5_rx_tun_attr *rx_tun_attr;
|
||||
struct ethhdr eth;
|
||||
struct mlx5_pkt_reformat *decap_pkt_reformat;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче