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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c
Extension
.c
Size
5481 bytes
Lines
204
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

// 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 "vlan.h"
#include "en/tc_priv.h"

static int
add_vlan_prio_tag_rewrite_action(struct mlx5e_priv *priv,
				 struct mlx5e_tc_flow_parse_attr *parse_attr,
				 u32 *action, struct netlink_ext_ack *extack)
{
	const struct flow_action_entry prio_tag_act = {
		.vlan.vid = 0,
		.vlan.prio =
			MLX5_GET(fte_match_set_lyr_2_4,
				 mlx5e_get_match_headers_value(*action,
							       &parse_attr->spec),
				 first_prio) &
			MLX5_GET(fte_match_set_lyr_2_4,
				 mlx5e_get_match_headers_criteria(*action,
								  &parse_attr->spec),
				 first_prio),
	};

	return mlx5e_tc_act_vlan_add_rewrite_action(priv, MLX5_FLOW_NAMESPACE_FDB,
						    &prio_tag_act, parse_attr, action,
						    extack);
}

static int
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 mlx5e_tc_act_parse_state *parse_state)
{
	u8 vlan_idx = attr->total_vlan;

	if (vlan_idx >= MLX5_FS_VLAN_DEPTH) {
		NL_SET_ERR_MSG_MOD(extack, "Total vlans used is greater than supported");
		return -EOPNOTSUPP;
	}

	if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, vlan_idx)) {
		NL_SET_ERR_MSG_MOD(extack, "firmware vlan actions is not supported");
		return -EOPNOTSUPP;
	}

	switch (act->id) {
	case FLOW_ACTION_VLAN_POP:
		if (vlan_idx)
			*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2;
		else
			*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
		break;
	case FLOW_ACTION_VLAN_PUSH:
		attr->vlan_vid[vlan_idx] = act->vlan.vid;
		attr->vlan_prio[vlan_idx] = act->vlan.prio;
		attr->vlan_proto[vlan_idx] = act->vlan.proto;
		if (!attr->vlan_proto[vlan_idx])
			attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q);

		if (vlan_idx)
			*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2;
		else
			*action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
		break;
	case FLOW_ACTION_VLAN_POP_ETH:
		parse_state->eth_pop = true;
		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;
	}

	attr->total_vlan = vlan_idx + 1;

	return 0;
}

Annotation

Implementation Notes