en/tc/act/tun.o en/tc/act/csum.o en/tc/act/pedit.o \
                                        en/tc/act/vlan.o en/tc/act/vlan_mangle.o en/tc/act/mpls.o \
                                        en/tc/act/mirred.o en/tc/act/mirred_nic.o \
-                                       en/tc/act/ct.o
+                                       en/tc/act/ct.o en/tc/act/sample.o en/tc/act/ptype.o
 
 mlx5_core-$(CONFIG_MLX5_TC_CT)      += en/tc_ct.o
 mlx5_core-$(CONFIG_MLX5_TC_SAMPLE)   += en/tc/sample.o
 
        &mlx5e_tc_act_pedit,
        &mlx5e_tc_act_csum,
        NULL, /* FLOW_ACTION_MARK, */
-       NULL, /* FLOW_ACTION_PTYPE, */
+       &mlx5e_tc_act_ptype,
        NULL, /* FLOW_ACTION_PRIORITY, */
        NULL, /* FLOW_ACTION_WAKE, */
        NULL, /* FLOW_ACTION_QUEUE, */
-       NULL, /* FLOW_ACTION_SAMPLE, */
+       &mlx5e_tc_act_sample,
        NULL, /* FLOW_ACTION_POLICE, */
        &mlx5e_tc_act_ct,
        NULL, /* FLOW_ACTION_CT_METADATA, */
 
        bool encap;
        bool decap;
        bool mpls_push;
+       bool ptype_host;
        const struct ip_tunnel_info *tun_info;
        struct pedit_headers_action hdrs[__PEDIT_CMD_MAX];
        int ifindexes[MLX5_MAX_FLOW_FWD_VPORTS];
        int if_count;
        struct mlx5_tc_ct_priv *ct_priv;
+       struct mlx5e_sample_attr sample_attr;
 };
 
 struct mlx5e_tc_act {
 extern struct mlx5e_tc_act mlx5e_tc_act_mirred;
 extern struct mlx5e_tc_act mlx5e_tc_act_mirred_nic;
 extern struct mlx5e_tc_act mlx5e_tc_act_ct;
+extern struct mlx5e_tc_act mlx5e_tc_act_sample;
+extern struct mlx5e_tc_act mlx5e_tc_act_ptype;
 
 struct mlx5e_tc_act *
 mlx5e_tc_act_get(enum flow_action_id act_id,
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+#include "act.h"
+#include "en/tc_priv.h"
+
+static bool
+tc_act_can_offload_ptype(struct mlx5e_tc_act_parse_state *parse_state,
+                        const struct flow_action_entry *act,
+                        int act_index)
+{
+       return true;
+}
+
+static int
+tc_act_parse_ptype(struct mlx5e_tc_act_parse_state *parse_state,
+                  const struct flow_action_entry *act,
+                  struct mlx5e_priv *priv,
+                  struct mlx5_flow_attr *attr)
+{
+       struct netlink_ext_ack *extack = parse_state->extack;
+
+       if (act->ptype != PACKET_HOST) {
+               NL_SET_ERR_MSG_MOD(extack, "skbedit ptype is only supported with type host");
+               return -EOPNOTSUPP;
+       }
+
+       parse_state->ptype_host = true;
+       return 0;
+}
+
+struct mlx5e_tc_act mlx5e_tc_act_ptype = {
+       .can_offload = tc_act_can_offload_ptype,
+       .parse_action = tc_act_parse_ptype,
+};
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+#include <net/psample.h>
+#include "act.h"
+#include "en/tc_priv.h"
+
+static bool
+tc_act_can_offload_sample(struct mlx5e_tc_act_parse_state *parse_state,
+                         const struct flow_action_entry *act,
+                         int act_index)
+{
+       struct netlink_ext_ack *extack = parse_state->extack;
+
+       if (flow_flag_test(parse_state->flow, CT)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Sample action with connection tracking is not supported");
+               return false;
+       }
+
+       return true;
+}
+
+static int
+tc_act_parse_sample(struct mlx5e_tc_act_parse_state *parse_state,
+                   const struct flow_action_entry *act,
+                   struct mlx5e_priv *priv,
+                   struct mlx5_flow_attr *attr)
+{
+       struct mlx5e_sample_attr *sample_attr = &parse_state->sample_attr;
+
+       sample_attr->rate = act->sample.rate;
+       sample_attr->group_num = act->sample.psample_group->group_num;
+
+       if (act->sample.truncate)
+               sample_attr->trunc_size = act->sample.trunc_size;
+
+       flow_flag_set(parse_state->flow, SAMPLE);
+
+       return 0;
+}
+
+struct mlx5e_tc_act mlx5e_tc_act_sample = {
+       .can_offload = tc_act_can_offload_sample,
+       .parse_action = tc_act_parse_sample,
+};
 
 #include <linux/rhashtable.h>
 #include <linux/refcount.h>
 #include <linux/completion.h>
-#include <net/psample.h>
 #include <net/arp.h>
 #include <net/ipv6_stubs.h>
 #include <net/bareudp.h>
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5e_tc_act_parse_state *parse_state;
        struct mlx5e_tc_flow_parse_attr *parse_attr;
-       struct mlx5e_sample_attr sample_attr = {};
        struct mlx5_flow_attr *attr = flow->attr;
        enum mlx5_flow_namespace_type ns_type;
        const struct flow_action_entry *act;
        struct mlx5_esw_flow_attr *esw_attr;
        struct pedit_headers_action *hdrs;
        struct mlx5e_tc_act *tc_act;
-       bool ptype_host = false;
        int err, i;
 
        err = flow_action_supported(flow_action, extack);
 
        flow_action_for_each(i, act, flow_action) {
                switch (act->id) {
-               case FLOW_ACTION_PTYPE:
-                       if (act->ptype != PACKET_HOST) {
-                               NL_SET_ERR_MSG_MOD(extack,
-                                                  "skbedit ptype is only supported with type host");
-                               return -EOPNOTSUPP;
-                       }
-
-                       ptype_host = true;
-                       break;
                case FLOW_ACTION_REDIRECT_INGRESS: {
                        struct net_device *out_dev;
 
                                return -EOPNOTSUPP;
                        }
 
-                       if (!ptype_host) {
+                       if (!parse_state->ptype_host) {
                                NL_SET_ERR_MSG_MOD(extack,
                                                   "redirect to int port ingress requires ptype=host action");
                                return -EOPNOTSUPP;
 
                        break;
                }
-               case FLOW_ACTION_SAMPLE:
-                       if (flow_flag_test(flow, CT)) {
-                               NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported");
-                               return -EOPNOTSUPP;
-                       }
-                       sample_attr.rate = act->sample.rate;
-                       sample_attr.group_num = act->sample.psample_group->group_num;
-                       if (act->sample.truncate)
-                               sample_attr.trunc_size = act->sample.trunc_size;
-                       flow_flag_set(flow, SAMPLE);
-                       break;
                default:
                        break;
                }
                attr->sample_attr = kzalloc(sizeof(*attr->sample_attr), GFP_KERNEL);
                if (!attr->sample_attr)
                        return -ENOMEM;
-               *attr->sample_attr = sample_attr;
+               *attr->sample_attr = parse_state->sample_attr;
        }
 
        return 0;