drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
Extension
.c
Size
9489 bytes
Lines
338
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ifindexes[i] == out_dev->ifindex) {
			NL_SET_ERR_MSG_MOD(extack, "can't duplicate output to same device");
			netdev_err(dev, "can't duplicate output to same device: %s\n",
				   out_dev->name);
			return true;
		}
	}

	return false;
}

static struct net_device *
get_fdb_out_dev(struct net_device *uplink_dev, struct net_device *out_dev)
{
	struct net_device *fdb_out_dev = out_dev;
	struct net_device *uplink_upper;

	rcu_read_lock();
	uplink_upper = netdev_master_upper_dev_get_rcu(uplink_dev);
	if (uplink_upper && netif_is_lag_master(uplink_upper) &&
	    uplink_upper == out_dev) {
		fdb_out_dev = uplink_dev;
	} else if (netif_is_lag_master(out_dev)) {
		fdb_out_dev = bond_option_active_slave_get_rcu(netdev_priv(out_dev));
		if (fdb_out_dev &&
		    (!mlx5e_eswitch_rep(fdb_out_dev) ||
		     !netdev_port_same_parent_id(fdb_out_dev, uplink_dev)))
			fdb_out_dev = NULL;
	}
	rcu_read_unlock();
	return fdb_out_dev;
}

static bool
tc_act_can_offload_mirred(struct mlx5e_tc_act_parse_state *parse_state,
			  const struct flow_action_entry *act,
			  int act_index,
			  struct mlx5_flow_attr *attr)
{
	struct netlink_ext_ack *extack = parse_state->extack;
	struct mlx5e_tc_flow *flow = parse_state->flow;
	struct mlx5e_tc_flow_parse_attr *parse_attr;
	struct net_device *out_dev = act->dev;
	struct mlx5e_priv *priv = flow->priv;
	struct mlx5_esw_flow_attr *esw_attr;

	parse_attr = attr->parse_attr;
	esw_attr = attr->esw_attr;

	if (!out_dev) {
		/* out_dev is NULL when filters with
		 * non-existing mirred device are replayed to
		 * the driver.
		 */
		return false;
	}

	if (parse_state->mpls_push && !netif_is_bareudp(out_dev)) {
		NL_SET_ERR_MSG_MOD(extack, "mpls is supported only through a bareudp device");
		return false;
	}

	if (parse_state->eth_pop && !parse_state->mpls_push) {
		NL_SET_ERR_MSG_MOD(extack, "vlan pop eth is supported only with mpls push");
		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
		 * block on a normal nft offload setup.
		 */
		return false;
	}

	if (esw_attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) {
		NL_SET_ERR_MSG_MOD(extack,
				   "can't support more output ports, can't offload forwarding");
		netdev_warn(priv->netdev,
			    "can't support more than %d output ports, can't offload forwarding\n",
			    esw_attr->out_count);
		return false;
	}

	if (parse_state->encap ||

Annotation

Implementation Notes