Loading drivers/net/ethernet/mellanox/mlx5/core/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en_tc.o en/rep/tc.o en/rep/neigh.o \ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/act/trap.o \ en/tc/act/accept.o en/tc/act/mark.o en/tc/act/goto.o \ en/tc/act/tun.o en/tc/act/csum.o en/tc/act/tun.o en/tc/act/csum.o en/tc/act/pedit.o mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o Loading drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c +4 −4 Original line number Diff line number Diff line Loading @@ -20,8 +20,8 @@ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = { NULL, /* FLOW_ACTION_VLAN_MANGLE, */ &mlx5e_tc_act_tun_encap, &mlx5e_tc_act_tun_decap, NULL, /* FLOW_ACTION_MANGLE, */ NULL, /* FLOW_ACTION_ADD, */ &mlx5e_tc_act_pedit, &mlx5e_tc_act_pedit, &mlx5e_tc_act_csum, }; Loading @@ -40,8 +40,8 @@ static struct mlx5e_tc_act *tc_acts_nic[NUM_FLOW_ACTIONS] = { NULL, /* FLOW_ACTION_VLAN_MANGLE, */ NULL, /* FLOW_ACTION_TUNNEL_ENCAP, */ NULL, /* FLOW_ACTION_TUNNEL_DECAP, */ NULL, /* FLOW_ACTION_MANGLE, */ NULL, /* FLOW_ACTION_ADD, */ &mlx5e_tc_act_pedit, &mlx5e_tc_act_pedit, &mlx5e_tc_act_csum, &mlx5e_tc_act_mark, }; Loading drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h +4 −0 Original line number Diff line number Diff line Loading @@ -4,9 +4,11 @@ #ifndef __MLX5_EN_TC_ACT_H__ #define __MLX5_EN_TC_ACT_H__ #include <net/tc_act/tc_pedit.h> #include <net/flow_offload.h> #include <linux/netlink.h> #include "eswitch.h" #include "pedit.h" struct mlx5_flow_attr; Loading @@ -17,6 +19,7 @@ struct mlx5e_tc_act_parse_state { bool encap; bool decap; const struct ip_tunnel_info *tun_info; struct pedit_headers_action hdrs[__PEDIT_CMD_MAX]; }; struct mlx5e_tc_act { Loading @@ -38,6 +41,7 @@ extern struct mlx5e_tc_act mlx5e_tc_act_goto; extern struct mlx5e_tc_act mlx5e_tc_act_tun_encap; extern struct mlx5e_tc_act mlx5e_tc_act_tun_decap; extern struct mlx5e_tc_act mlx5e_tc_act_csum; extern struct mlx5e_tc_act mlx5e_tc_act_pedit; struct mlx5e_tc_act * mlx5e_tc_act_get(enum flow_action_id act_id, Loading drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c 0 → 100644 +165 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include <linux/if_vlan.h> #include "act.h" #include "pedit.h" #include "en/tc_priv.h" #include "en/mod_hdr.h" static int pedit_header_offsets[] = { [FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth), [FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4), [FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6), [FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp), [FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp), }; #define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype]) static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset, struct pedit_headers_action *hdrs, struct netlink_ext_ack *extack) { u32 *curr_pmask, *curr_pval; curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset); curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset); if (*curr_pmask & mask) { /* disallow acting twice on the same location */ NL_SET_ERR_MSG_MOD(extack, "curr_pmask and new mask same. Acting twice on same location"); goto out_err; } *curr_pmask |= mask; *curr_pval |= (val & mask); return 0; 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 pedit_headers_action *hdrs, struct netlink_ext_ack *extack) { u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1; u8 htype = act->mangle.htype; int err = -EOPNOTSUPP; u32 mask, val, offset; if (htype == FLOW_ACT_MANGLE_UNSPEC) { NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded"); goto out_err; } if (!mlx5e_mod_hdr_max_actions(priv->mdev, namespace)) { NL_SET_ERR_MSG_MOD(extack, "The pedit offload action is not supported"); goto out_err; } mask = act->mangle.mask; val = act->mangle.val; offset = act->mangle.offset; err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd], extack); if (err) goto out_err; hdrs[cmd].pedits++; return 0; 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 pedit_headers_action *hdrs, 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, hdrs, extack); } static bool tc_act_can_offload_pedit(struct mlx5e_tc_act_parse_state *parse_state, const struct flow_action_entry *act, int act_index) { return true; } static int tc_act_parse_pedit(struct mlx5e_tc_act_parse_state *parse_state, const struct flow_action_entry *act, struct mlx5e_priv *priv, struct mlx5_flow_attr *attr) { struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; struct mlx5e_tc_flow *flow = parse_state->flow; enum mlx5_flow_namespace_type ns_type; int err; ns_type = mlx5e_get_flow_namespace(flow); err = mlx5e_tc_act_pedit_parse_action(flow->priv, act, ns_type, attr->parse_attr, parse_state->hdrs, flow, 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; } struct mlx5e_tc_act mlx5e_tc_act_pedit = { .can_offload = tc_act_can_offload_pedit, .parse_action = tc_act_parse_pedit, }; drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.h 0 → 100644 +32 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #ifndef __MLX5_EN_TC_ACT_PEDIT_H__ #define __MLX5_EN_TC_ACT_PEDIT_H__ #include "en_tc.h" struct pedit_headers { struct ethhdr eth; struct vlan_hdr vlan; struct iphdr ip4; struct ipv6hdr ip6; struct tcphdr tcp; struct udphdr udp; }; struct pedit_headers_action { struct pedit_headers vals; struct pedit_headers masks; u32 pedits; }; 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 mlx5e_tc_flow *flow, struct netlink_ext_ack *extack); #endif /* __MLX5_EN_TC_ACT_PEDIT_H__ */ Loading
drivers/net/ethernet/mellanox/mlx5/core/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en_tc.o en/rep/tc.o en/rep/neigh.o \ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/act/trap.o \ en/tc/act/accept.o en/tc/act/mark.o en/tc/act/goto.o \ en/tc/act/tun.o en/tc/act/csum.o en/tc/act/tun.o en/tc/act/csum.o en/tc/act/pedit.o mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o Loading
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c +4 −4 Original line number Diff line number Diff line Loading @@ -20,8 +20,8 @@ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = { NULL, /* FLOW_ACTION_VLAN_MANGLE, */ &mlx5e_tc_act_tun_encap, &mlx5e_tc_act_tun_decap, NULL, /* FLOW_ACTION_MANGLE, */ NULL, /* FLOW_ACTION_ADD, */ &mlx5e_tc_act_pedit, &mlx5e_tc_act_pedit, &mlx5e_tc_act_csum, }; Loading @@ -40,8 +40,8 @@ static struct mlx5e_tc_act *tc_acts_nic[NUM_FLOW_ACTIONS] = { NULL, /* FLOW_ACTION_VLAN_MANGLE, */ NULL, /* FLOW_ACTION_TUNNEL_ENCAP, */ NULL, /* FLOW_ACTION_TUNNEL_DECAP, */ NULL, /* FLOW_ACTION_MANGLE, */ NULL, /* FLOW_ACTION_ADD, */ &mlx5e_tc_act_pedit, &mlx5e_tc_act_pedit, &mlx5e_tc_act_csum, &mlx5e_tc_act_mark, }; Loading
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h +4 −0 Original line number Diff line number Diff line Loading @@ -4,9 +4,11 @@ #ifndef __MLX5_EN_TC_ACT_H__ #define __MLX5_EN_TC_ACT_H__ #include <net/tc_act/tc_pedit.h> #include <net/flow_offload.h> #include <linux/netlink.h> #include "eswitch.h" #include "pedit.h" struct mlx5_flow_attr; Loading @@ -17,6 +19,7 @@ struct mlx5e_tc_act_parse_state { bool encap; bool decap; const struct ip_tunnel_info *tun_info; struct pedit_headers_action hdrs[__PEDIT_CMD_MAX]; }; struct mlx5e_tc_act { Loading @@ -38,6 +41,7 @@ extern struct mlx5e_tc_act mlx5e_tc_act_goto; extern struct mlx5e_tc_act mlx5e_tc_act_tun_encap; extern struct mlx5e_tc_act mlx5e_tc_act_tun_decap; extern struct mlx5e_tc_act mlx5e_tc_act_csum; extern struct mlx5e_tc_act mlx5e_tc_act_pedit; struct mlx5e_tc_act * mlx5e_tc_act_get(enum flow_action_id act_id, Loading
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c 0 → 100644 +165 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include <linux/if_vlan.h> #include "act.h" #include "pedit.h" #include "en/tc_priv.h" #include "en/mod_hdr.h" static int pedit_header_offsets[] = { [FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth), [FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4), [FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6), [FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp), [FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp), }; #define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype]) static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset, struct pedit_headers_action *hdrs, struct netlink_ext_ack *extack) { u32 *curr_pmask, *curr_pval; curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset); curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset); if (*curr_pmask & mask) { /* disallow acting twice on the same location */ NL_SET_ERR_MSG_MOD(extack, "curr_pmask and new mask same. Acting twice on same location"); goto out_err; } *curr_pmask |= mask; *curr_pval |= (val & mask); return 0; 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 pedit_headers_action *hdrs, struct netlink_ext_ack *extack) { u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1; u8 htype = act->mangle.htype; int err = -EOPNOTSUPP; u32 mask, val, offset; if (htype == FLOW_ACT_MANGLE_UNSPEC) { NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded"); goto out_err; } if (!mlx5e_mod_hdr_max_actions(priv->mdev, namespace)) { NL_SET_ERR_MSG_MOD(extack, "The pedit offload action is not supported"); goto out_err; } mask = act->mangle.mask; val = act->mangle.val; offset = act->mangle.offset; err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd], extack); if (err) goto out_err; hdrs[cmd].pedits++; return 0; 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 pedit_headers_action *hdrs, 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, hdrs, extack); } static bool tc_act_can_offload_pedit(struct mlx5e_tc_act_parse_state *parse_state, const struct flow_action_entry *act, int act_index) { return true; } static int tc_act_parse_pedit(struct mlx5e_tc_act_parse_state *parse_state, const struct flow_action_entry *act, struct mlx5e_priv *priv, struct mlx5_flow_attr *attr) { struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; struct mlx5e_tc_flow *flow = parse_state->flow; enum mlx5_flow_namespace_type ns_type; int err; ns_type = mlx5e_get_flow_namespace(flow); err = mlx5e_tc_act_pedit_parse_action(flow->priv, act, ns_type, attr->parse_attr, parse_state->hdrs, flow, 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; } struct mlx5e_tc_act mlx5e_tc_act_pedit = { .can_offload = tc_act_can_offload_pedit, .parse_action = tc_act_parse_pedit, };
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.h 0 → 100644 +32 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ /* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #ifndef __MLX5_EN_TC_ACT_PEDIT_H__ #define __MLX5_EN_TC_ACT_PEDIT_H__ #include "en_tc.h" struct pedit_headers { struct ethhdr eth; struct vlan_hdr vlan; struct iphdr ip4; struct ipv6hdr ip6; struct tcphdr tcp; struct udphdr udp; }; struct pedit_headers_action { struct pedit_headers vals; struct pedit_headers masks; u32 pedits; }; 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 mlx5e_tc_flow *flow, struct netlink_ext_ack *extack); #endif /* __MLX5_EN_TC_ACT_PEDIT_H__ */