Commit 93a1ab2c authored by Paul Blakey's avatar Paul Blakey Committed by Jakub Kicinski
Browse files

net/mlx5: Refactor tc miss handling to a single function



Move tc miss handling code to en_tc.c, and remove
duplicate code.

Signed-off-by: default avatarPaul Blakey <paulb@nvidia.com>
Reviewed-by: default avatarRoi Dayan <roid@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 03a283cd
Loading
Loading
Loading
Loading
+23 −200
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2020 Mellanox Technologies. */

#include <net/dst_metadata.h>
#include <linux/netdevice.h>
#include <linux/if_macvlan.h>
#include <linux/list.h>
@@ -665,230 +664,54 @@ void mlx5e_rep_tc_netdevice_event_unregister(struct mlx5e_rep_priv *rpriv)
				 mlx5e_rep_indr_block_unbind);
}

static bool mlx5e_restore_tunnel(struct mlx5e_priv *priv, struct sk_buff *skb,
				 struct mlx5e_tc_update_priv *tc_priv,
				 u32 tunnel_id)
{
	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
	struct tunnel_match_enc_opts enc_opts = {};
	struct mlx5_rep_uplink_priv *uplink_priv;
	struct mlx5e_rep_priv *uplink_rpriv;
	struct metadata_dst *tun_dst;
	struct tunnel_match_key key;
	u32 tun_id, enc_opts_id;
	struct net_device *dev;
	int err;

	enc_opts_id = tunnel_id & ENC_OPTS_BITS_MASK;
	tun_id = tunnel_id >> ENC_OPTS_BITS;

	if (!tun_id)
		return true;

	uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
	uplink_priv = &uplink_rpriv->uplink_priv;

	err = mapping_find(uplink_priv->tunnel_mapping, tun_id, &key);
	if (err) {
		netdev_dbg(priv->netdev,
			   "Couldn't find tunnel for tun_id: %d, err: %d\n",
			   tun_id, err);
		return false;
	}

	if (enc_opts_id) {
		err = mapping_find(uplink_priv->tunnel_enc_opts_mapping,
				   enc_opts_id, &enc_opts);
		if (err) {
			netdev_dbg(priv->netdev,
				   "Couldn't find tunnel (opts) for tun_id: %d, err: %d\n",
				   enc_opts_id, err);
			return false;
		}
	}

	if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
		tun_dst = __ip_tun_set_dst(key.enc_ipv4.src, key.enc_ipv4.dst,
					   key.enc_ip.tos, key.enc_ip.ttl,
					   key.enc_tp.dst, TUNNEL_KEY,
					   key32_to_tunnel_id(key.enc_key_id.keyid),
					   enc_opts.key.len);
	} else if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
		tun_dst = __ipv6_tun_set_dst(&key.enc_ipv6.src, &key.enc_ipv6.dst,
					     key.enc_ip.tos, key.enc_ip.ttl,
					     key.enc_tp.dst, 0, TUNNEL_KEY,
					     key32_to_tunnel_id(key.enc_key_id.keyid),
					     enc_opts.key.len);
	} else {
		netdev_dbg(priv->netdev,
			   "Couldn't restore tunnel, unsupported addr_type: %d\n",
			   key.enc_control.addr_type);
		return false;
	}

	if (!tun_dst) {
		netdev_dbg(priv->netdev, "Couldn't restore tunnel, no tun_dst\n");
		return false;
	}

	tun_dst->u.tun_info.key.tp_src = key.enc_tp.src;

	if (enc_opts.key.len)
		ip_tunnel_info_opts_set(&tun_dst->u.tun_info,
					enc_opts.key.data,
					enc_opts.key.len,
					enc_opts.key.dst_opt_type);

	skb_dst_set(skb, (struct dst_entry *)tun_dst);
	dev = dev_get_by_index(&init_net, key.filter_ifindex);
	if (!dev) {
		netdev_dbg(priv->netdev,
			   "Couldn't find tunnel device with ifindex: %d\n",
			   key.filter_ifindex);
		return false;
	}

	/* Set fwd_dev so we do dev_put() after datapath */
	tc_priv->fwd_dev = dev;

	skb->dev = dev;

	return true;
}

static bool mlx5e_restore_skb_chain(struct sk_buff *skb, u32 chain, u32 reg_c1,
				    struct mlx5e_tc_update_priv *tc_priv)
{
	struct mlx5e_priv *priv = netdev_priv(skb->dev);
	u32 tunnel_id = (reg_c1 >> ESW_TUN_OFFSET) & TUNNEL_ID_MASK;

	if (chain) {
		struct mlx5_rep_uplink_priv *uplink_priv;
		struct mlx5e_rep_priv *uplink_rpriv;
		struct tc_skb_ext *tc_skb_ext;
		struct mlx5_eswitch *esw;
		u32 zone_restore_id;

		tc_skb_ext = tc_skb_ext_alloc(skb);
		if (!tc_skb_ext) {
			WARN_ON(1);
			return false;
		}
		tc_skb_ext->chain = chain;
		zone_restore_id = reg_c1 & ESW_ZONE_ID_MASK;
		esw = priv->mdev->priv.eswitch;
		uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
		uplink_priv = &uplink_rpriv->uplink_priv;
		if (!mlx5e_tc_ct_restore_flow(uplink_priv->ct_priv, skb,
					      zone_restore_id))
			return false;
	}

	return mlx5e_restore_tunnel(priv, skb, tc_priv, tunnel_id);
}

static void mlx5_rep_tc_post_napi_receive(struct mlx5e_tc_update_priv *tc_priv)
{
	if (tc_priv->fwd_dev)
		dev_put(tc_priv->fwd_dev);
}

static void mlx5e_restore_skb_sample(struct mlx5e_priv *priv, struct sk_buff *skb,
				     struct mlx5_mapped_obj *mapped_obj,
				     struct mlx5e_tc_update_priv *tc_priv)
{
	if (!mlx5e_restore_tunnel(priv, skb, tc_priv, mapped_obj->sample.tunnel_id)) {
		netdev_dbg(priv->netdev,
			   "Failed to restore tunnel info for sampled packet\n");
		return;
	}
	mlx5e_tc_sample_skb(skb, mapped_obj);
	mlx5_rep_tc_post_napi_receive(tc_priv);
}

static bool mlx5e_restore_skb_int_port(struct mlx5e_priv *priv, struct sk_buff *skb,
				       struct mlx5_mapped_obj *mapped_obj,
				       struct mlx5e_tc_update_priv *tc_priv,
				       bool *forward_tx,
				       u32 reg_c1)
{
	u32 tunnel_id = (reg_c1 >> ESW_TUN_OFFSET) & TUNNEL_ID_MASK;
	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
	struct mlx5_rep_uplink_priv *uplink_priv;
	struct mlx5e_rep_priv *uplink_rpriv;

	/* Tunnel restore takes precedence over int port restore */
	if (tunnel_id)
		return mlx5e_restore_tunnel(priv, skb, tc_priv, tunnel_id);

	uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
	uplink_priv = &uplink_rpriv->uplink_priv;

	if (mlx5e_tc_int_port_dev_fwd(uplink_priv->int_port_priv, skb,
				      mapped_obj->int_port_metadata, forward_tx)) {
		/* Set fwd_dev for future dev_put */
		tc_priv->fwd_dev = skb->dev;

		return true;
	}

	return false;
}

void mlx5e_rep_tc_receive(struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq,
			  struct sk_buff *skb)
{
	u32 reg_c1 = be32_to_cpu(cqe->ft_metadata);
	u32 reg_c0, reg_c1, zone_restore_id, tunnel_id;
	struct mlx5e_tc_update_priv tc_priv = {};
	struct mlx5_mapped_obj mapped_obj;
	struct mlx5_rep_uplink_priv *uplink_priv;
	struct mlx5e_rep_priv *uplink_rpriv;
	struct mlx5_tc_ct_priv *ct_priv;
	struct mapping_ctx *mapping_ctx;
	struct mlx5_eswitch *esw;
	bool forward_tx = false;
	struct mlx5e_priv *priv;
	u32 reg_c0;
	int err;

	reg_c0 = (be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK);
	if (!reg_c0 || reg_c0 == MLX5_FS_DEFAULT_FLOW_TAG)
		goto forward;

	/* If reg_c0 is not equal to the default flow tag then skb->mark
	/* If mapped_obj_id is not equal to the default flow tag then skb->mark
	 * is not supported and must be reset back to 0.
	 */
	skb->mark = 0;

	priv = netdev_priv(skb->dev);
	esw = priv->mdev->priv.eswitch;
	err = mapping_find(esw->offloads.reg_c0_obj_pool, reg_c0, &mapped_obj);
	if (err) {
		netdev_dbg(priv->netdev,
			   "Couldn't find mapped object for reg_c0: %d, err: %d\n",
			   reg_c0, err);
		goto free_skb;
	}
	mapping_ctx = esw->offloads.reg_c0_obj_pool;
	reg_c1 = be32_to_cpu(cqe->ft_metadata);
	zone_restore_id = reg_c1 & ESW_ZONE_ID_MASK;
	tunnel_id = (reg_c1 >> ESW_TUN_OFFSET) & TUNNEL_ID_MASK;

	if (mapped_obj.type == MLX5_MAPPED_OBJ_CHAIN) {
		if (!mlx5e_restore_skb_chain(skb, mapped_obj.chain, reg_c1, &tc_priv) &&
		    !mlx5_ipsec_is_rx_flow(cqe))
			goto free_skb;
	} else if (mapped_obj.type == MLX5_MAPPED_OBJ_SAMPLE) {
		mlx5e_restore_skb_sample(priv, skb, &mapped_obj, &tc_priv);
		goto free_skb;
	} else if (mapped_obj.type == MLX5_MAPPED_OBJ_INT_PORT_METADATA) {
		if (!mlx5e_restore_skb_int_port(priv, skb, &mapped_obj, &tc_priv,
						&forward_tx, reg_c1))
			goto free_skb;
	} else {
		netdev_dbg(priv->netdev, "Invalid mapped object type: %d\n", mapped_obj.type);
	uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
	uplink_priv = &uplink_rpriv->uplink_priv;
	ct_priv = uplink_priv->ct_priv;

	if (!mlx5_ipsec_is_rx_flow(cqe) &&
	    !mlx5e_tc_update_skb(cqe, skb, mapping_ctx, reg_c0, ct_priv, zone_restore_id, tunnel_id,
				 &tc_priv))
		goto free_skb;
	}

forward:
	if (forward_tx)
	if (tc_priv.skb_done)
		goto free_skb;

	if (tc_priv.forward_tx)
		dev_queue_xmit(skb);
	else
		napi_gro_receive(rq->cq.napi, skb);

	mlx5_rep_tc_post_napi_receive(&tc_priv);
	if (tc_priv.fwd_dev)
		dev_put(tc_priv.fwd_dev);

	return;

+2 −2
Original line number Diff line number Diff line
@@ -1792,7 +1792,7 @@ static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
	mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);

	if (mlx5e_cqe_regb_chain(cqe))
		if (!mlx5e_tc_update_skb(cqe, skb)) {
		if (!mlx5e_tc_update_skb_nic(cqe, skb)) {
			dev_kfree_skb_any(skb);
			goto free_wqe;
		}
@@ -2259,7 +2259,7 @@ static void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cq
	mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);

	if (mlx5e_cqe_regb_chain(cqe))
		if (!mlx5e_tc_update_skb(cqe, skb)) {
		if (!mlx5e_tc_update_skb_nic(cqe, skb)) {
			dev_kfree_skb_any(skb);
			goto mpwrq_cqe_out;
		}
+197 −23
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include <net/ipv6_stubs.h>
#include <net/bareudp.h>
#include <net/bonding.h>
#include <net/dst_metadata.h>
#include "en.h"
#include "en/tc/post_act.h"
#include "en/tc/act_stats.h"
@@ -5604,46 +5605,219 @@ int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
	}
}

bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe,
			 struct sk_buff *skb)
static bool mlx5e_tc_restore_tunnel(struct mlx5e_priv *priv, struct sk_buff *skb,
				    struct mlx5e_tc_update_priv *tc_priv,
				    u32 tunnel_id)
{
	u32 chain = 0, chain_tag, reg_b, zone_restore_id;
	struct mlx5e_priv *priv = netdev_priv(skb->dev);
	struct mlx5_mapped_obj mapped_obj;
	struct tc_skb_ext *tc_skb_ext;
	struct mlx5e_tc_table *tc;
	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
	struct tunnel_match_enc_opts enc_opts = {};
	struct mlx5_rep_uplink_priv *uplink_priv;
	struct mlx5e_rep_priv *uplink_rpriv;
	struct metadata_dst *tun_dst;
	struct tunnel_match_key key;
	u32 tun_id, enc_opts_id;
	struct net_device *dev;
	int err;

	reg_b = be32_to_cpu(cqe->ft_metadata);
	tc = mlx5e_fs_get_tc(priv->fs);
	chain_tag = reg_b & MLX5E_TC_TABLE_CHAIN_TAG_MASK;
	enc_opts_id = tunnel_id & ENC_OPTS_BITS_MASK;
	tun_id = tunnel_id >> ENC_OPTS_BITS;

	if (!tun_id)
		return true;

	err = mapping_find(tc->mapping, chain_tag, &mapped_obj);
	uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
	uplink_priv = &uplink_rpriv->uplink_priv;

	err = mapping_find(uplink_priv->tunnel_mapping, tun_id, &key);
	if (err) {
		netdev_dbg(priv->netdev,
			   "Couldn't find tunnel for tun_id: %d, err: %d\n",
			   tun_id, err);
		return false;
	}

	if (enc_opts_id) {
		err = mapping_find(uplink_priv->tunnel_enc_opts_mapping,
				   enc_opts_id, &enc_opts);
		if (err) {
			netdev_dbg(priv->netdev,
			   "Couldn't find chain for chain tag: %d, err: %d\n",
			   chain_tag, err);
				   "Couldn't find tunnel (opts) for tun_id: %d, err: %d\n",
				   enc_opts_id, err);
			return false;
		}
	}

	switch (key.enc_control.addr_type) {
	case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
		tun_dst = __ip_tun_set_dst(key.enc_ipv4.src, key.enc_ipv4.dst,
					   key.enc_ip.tos, key.enc_ip.ttl,
					   key.enc_tp.dst, TUNNEL_KEY,
					   key32_to_tunnel_id(key.enc_key_id.keyid),
					   enc_opts.key.len);
		break;
	case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
		tun_dst = __ipv6_tun_set_dst(&key.enc_ipv6.src, &key.enc_ipv6.dst,
					     key.enc_ip.tos, key.enc_ip.ttl,
					     key.enc_tp.dst, 0, TUNNEL_KEY,
					     key32_to_tunnel_id(key.enc_key_id.keyid),
					     enc_opts.key.len);
		break;
	default:
		netdev_dbg(priv->netdev,
			   "Couldn't restore tunnel, unsupported addr_type: %d\n",
			   key.enc_control.addr_type);
		return false;
	}

	if (mapped_obj.type == MLX5_MAPPED_OBJ_CHAIN) {
		chain = mapped_obj.chain;
	if (!tun_dst) {
		netdev_dbg(priv->netdev, "Couldn't restore tunnel, no tun_dst\n");
		return false;
	}

	tun_dst->u.tun_info.key.tp_src = key.enc_tp.src;

	if (enc_opts.key.len)
		ip_tunnel_info_opts_set(&tun_dst->u.tun_info,
					enc_opts.key.data,
					enc_opts.key.len,
					enc_opts.key.dst_opt_type);

	skb_dst_set(skb, (struct dst_entry *)tun_dst);
	dev = dev_get_by_index(&init_net, key.filter_ifindex);
	if (!dev) {
		netdev_dbg(priv->netdev,
			   "Couldn't find tunnel device with ifindex: %d\n",
			   key.filter_ifindex);
		return false;
	}

	/* Set fwd_dev so we do dev_put() after datapath */
	tc_priv->fwd_dev = dev;

	skb->dev = dev;

	return true;
}

static bool mlx5e_tc_restore_skb_chain(struct sk_buff *skb, struct mlx5_tc_ct_priv *ct_priv,
				       u32 chain, u32 zone_restore_id,
				       u32 tunnel_id,  struct mlx5e_tc_update_priv *tc_priv)
{
	struct mlx5e_priv *priv = netdev_priv(skb->dev);
	struct tc_skb_ext *tc_skb_ext;

	if (chain) {
		if (!mlx5e_tc_ct_restore_flow(ct_priv, skb, zone_restore_id))
			return false;

		tc_skb_ext = tc_skb_ext_alloc(skb);
		if (WARN_ON(!tc_skb_ext))
		if (!tc_skb_ext) {
			WARN_ON(1);
			return false;
		}

		tc_skb_ext->chain = chain;
	}

		zone_restore_id = (reg_b >> MLX5_REG_MAPPING_MOFFSET(NIC_ZONE_RESTORE_TO_REG)) &
			ESW_ZONE_ID_MASK;
	if (tc_priv)
		return mlx5e_tc_restore_tunnel(priv, skb, tc_priv, tunnel_id);

	return true;
}

static void mlx5e_tc_restore_skb_sample(struct mlx5e_priv *priv, struct sk_buff *skb,
					struct mlx5_mapped_obj *mapped_obj,
					struct mlx5e_tc_update_priv *tc_priv)
{
	if (!mlx5e_tc_restore_tunnel(priv, skb, tc_priv, mapped_obj->sample.tunnel_id)) {
		netdev_dbg(priv->netdev,
			   "Failed to restore tunnel info for sampled packet\n");
		return;
	}
	mlx5e_tc_sample_skb(skb, mapped_obj);
}

static bool mlx5e_tc_restore_skb_int_port(struct mlx5e_priv *priv, struct sk_buff *skb,
					  struct mlx5_mapped_obj *mapped_obj,
					  struct mlx5e_tc_update_priv *tc_priv,
					  u32 tunnel_id)
{
	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
	struct mlx5_rep_uplink_priv *uplink_priv;
	struct mlx5e_rep_priv *uplink_rpriv;
	bool forward_tx = false;

	/* Tunnel restore takes precedence over int port restore */
	if (tunnel_id)
		return mlx5e_tc_restore_tunnel(priv, skb, tc_priv, tunnel_id);

	uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
	uplink_priv = &uplink_rpriv->uplink_priv;

	if (mlx5e_tc_int_port_dev_fwd(uplink_priv->int_port_priv, skb,
				      mapped_obj->int_port_metadata, &forward_tx)) {
		/* Set fwd_dev for future dev_put */
		tc_priv->fwd_dev = skb->dev;
		tc_priv->forward_tx = forward_tx;

		return true;
	}

		if (!mlx5e_tc_ct_restore_flow(tc->ct, skb,
					      zone_restore_id))
	return false;
	} else {
		netdev_dbg(priv->netdev, "Invalid mapped object type: %d\n", mapped_obj.type);
}

bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe, struct sk_buff *skb,
			 struct mapping_ctx *mapping_ctx, u32 mapped_obj_id,
			 struct mlx5_tc_ct_priv *ct_priv,
			 u32 zone_restore_id, u32 tunnel_id,
			 struct mlx5e_tc_update_priv *tc_priv)
{
	struct mlx5e_priv *priv = netdev_priv(skb->dev);
	struct mlx5_mapped_obj mapped_obj;
	int err;

	err = mapping_find(mapping_ctx, mapped_obj_id, &mapped_obj);
	if (err) {
		netdev_dbg(skb->dev,
			   "Couldn't find mapped object for mapped_obj_id: %d, err: %d\n",
			   mapped_obj_id, err);
		return false;
	}

	switch (mapped_obj.type) {
	case MLX5_MAPPED_OBJ_CHAIN:
		return mlx5e_tc_restore_skb_chain(skb, ct_priv, mapped_obj.chain, zone_restore_id,
						  tunnel_id, tc_priv);
	case MLX5_MAPPED_OBJ_SAMPLE:
		mlx5e_tc_restore_skb_sample(priv, skb, &mapped_obj, tc_priv);
		tc_priv->skb_done = true;
		return true;
	case MLX5_MAPPED_OBJ_INT_PORT_METADATA:
		return mlx5e_tc_restore_skb_int_port(priv, skb, &mapped_obj, tc_priv, tunnel_id);
	default:
		netdev_dbg(priv->netdev, "Invalid mapped object type: %d\n", mapped_obj.type);
		return false;
	}

	return false;
}

bool mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, struct sk_buff *skb)
{
	struct mlx5e_priv *priv = netdev_priv(skb->dev);
	u32 mapped_obj_id, reg_b, zone_restore_id;
	struct mlx5_tc_ct_priv *ct_priv;
	struct mapping_ctx *mapping_ctx;
	struct mlx5e_tc_table *tc;

	reg_b = be32_to_cpu(cqe->ft_metadata);
	tc = mlx5e_fs_get_tc(priv->fs);
	mapped_obj_id = reg_b & MLX5E_TC_TABLE_CHAIN_TAG_MASK;
	zone_restore_id = (reg_b >> MLX5_REG_MAPPING_MOFFSET(NIC_ZONE_RESTORE_TO_REG)) &
			  ESW_ZONE_ID_MASK;
	ct_priv = tc->ct;
	mapping_ctx = tc->mapping;

	return mlx5e_tc_update_skb(cqe, skb, mapping_ctx, mapped_obj_id, ct_priv, zone_restore_id,
				   0, NULL);
}
+9 −2
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags);

struct mlx5e_tc_update_priv {
	struct net_device *fwd_dev;
	bool skb_done;
	bool forward_tx;
};

struct mlx5_nic_flow_attr {
@@ -382,14 +384,19 @@ static inline bool mlx5e_cqe_regb_chain(struct mlx5_cqe64 *cqe)
	return false;
}

bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe, struct sk_buff *skb);
bool mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, struct sk_buff *skb);
bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe, struct sk_buff *skb,
			 struct mapping_ctx *mapping_ctx, u32 mapped_obj_id,
			 struct mlx5_tc_ct_priv *ct_priv,
			 u32 zone_restore_id, u32 tunnel_id,
			 struct mlx5e_tc_update_priv *tc_priv);
#else /* CONFIG_MLX5_CLS_ACT */
static inline struct mlx5e_tc_table *mlx5e_tc_table_alloc(void) { return NULL; }
static inline void mlx5e_tc_table_free(struct mlx5e_tc_table *tc) {}
static inline bool mlx5e_cqe_regb_chain(struct mlx5_cqe64 *cqe)
{ return false; }
static inline bool
mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe, struct sk_buff *skb)
mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, struct sk_buff *skb)
{ return true; }
#endif