net/mlx5e: MPLSoUDP decap, use vlan push_eth instead of pedit
authorMaor Dickman <maord@nvidia.com>
Tue, 15 Mar 2022 11:02:10 +0000 (13:02 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 17 Mar 2022 02:59:42 +0000 (19:59 -0700)
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>
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mpls.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan_mangle.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h

index cb8f7593a00ccc7d6741ebd7c2b05a3e38275328..24403593b9520ed0821488169418f735174b22b3 100644 (file)
@@ -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. */
index 94a7cf38d6b1b3b33889b16d22973088a05a795e..2616aee6ebf0a4c4f9b36ac05d35b314c74bc1c8 100644 (file)
@@ -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;
index 05a42fb4ba97a2632da1ed2ca729d1cf023908a1..14cfa39d30f798b48da8d36a4c041e916494806f 100644 (file)
@@ -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
index 96a80e03d129537dd3ab2a89719a8cef773feed8..f106190bf37c1c3e73b20669b0935bf432eff9da 100644 (file)
@@ -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);
 
index 39f8f71bed9edd706f8ee4d08d37e53cb389c796..47597c524e598ab6dd1d1a0bd259dc887df84355 100644 (file)
@@ -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;
 }
 
index 258f030a2dc63c0334ae98cefa7936d751e9ad86..434c8bd710a290ac5e6ef093970034d847a46779 100644 (file)
@@ -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__ */
index 6378b7558ba2ced044e80ac4ad848f7a9d8d5697..cf1acf6782706e3e5e17810d13d77be768211d9e 100644 (file)
@@ -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)
index 28444d4ffd7336cc1d9c6f2d070b6355ddaffccc..9a8a1a6bd99e5eb6028a890887f24bd8cb9b3fa4 100644 (file)
@@ -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;
index 03c953dacb09d20f8d5916cc6279d5cac4d6cba6..3b74a6fd5c43f2dd63d12f05c9bd5e72f82d93c7 100644 (file)
@@ -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;
 };
 
index 5105c8018d37fceca8406da33ba2b0fc74709417..5aff979143678fd2b01134665e76384484069a31 100644 (file)
@@ -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);
index 973281bdb4a2b55dda66bccc8268e8083ebc58e8..bac5160837c5101b28b74b8756703a6f7a794730 100644 (file)
@@ -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;
 };