File Index
Files and directories
Sign in
FILE

egress_lgcy.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/* Copyright (c) 2020 Mellanox Technologies Inc. All rights reserved. */
  3
  4#include "mlx5_core.h"
  5#include "eswitch.h"
  6#include "helper.h"
  7#include "lgcy.h"
  8
  9static void esw_acl_egress_lgcy_rules_destroy(struct mlx5_vport *vport)
 10{
 11	esw_acl_egress_vlan_destroy(vport);
 12	if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_rule)) {
 13		mlx5_del_flow_rules(vport->egress.legacy.drop_rule);
 14		vport->egress.legacy.drop_rule = NULL;
 15	}
 16}
 17
 18static int esw_acl_egress_lgcy_groups_create(struct mlx5_eswitch *esw,
 19					     struct mlx5_vport *vport)
 20{
 21	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
 22	struct mlx5_core_dev *dev = esw->dev;
 23	struct mlx5_flow_group *drop_grp;
 24	u32 *flow_group_in;
 25	int err = 0;
 26
 27	err = esw_acl_egress_vlan_grp_create(esw, vport);
 28	if (err)
 29		return err;
 30
 31	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
 32	if (!flow_group_in) {
 33		err = -ENOMEM;
 34		goto alloc_err;
 35	}
 36
 37	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
 38	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
 39	drop_grp = mlx5_create_flow_group(vport->egress.acl, flow_group_in);
 40	if (IS_ERR(drop_grp)) {
 41		err = PTR_ERR(drop_grp);
 42		esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n",
 43			 vport->vport, err);
 44		goto drop_grp_err;
 45	}
 46
 47	vport->egress.legacy.drop_grp = drop_grp;
 48	kvfree(flow_group_in);
 49	return 0;
 50
 51drop_grp_err:
 52	kvfree(flow_group_in);
 53alloc_err:
 54	esw_acl_egress_vlan_grp_destroy(vport);
 55	return err;
 56}
 57
 58static void esw_acl_egress_lgcy_groups_destroy(struct mlx5_vport *vport)
 59{
 60	if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_grp)) {
 61		mlx5_destroy_flow_group(vport->egress.legacy.drop_grp);
 62		vport->egress.legacy.drop_grp = NULL;
 63	}
 64	esw_acl_egress_vlan_grp_destroy(vport);
 65}
 66
 67int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
 68			      struct mlx5_vport *vport)
 69{
 70	bool vst_mode_steering = esw_vst_mode_is_steering(esw);
 71	struct mlx5_flow_destination drop_ctr_dst = {};
 72	struct mlx5_flow_destination *dst = NULL;
 73	struct mlx5_fc *drop_counter = NULL;
 74	struct mlx5_flow_act flow_act = {};
 75	/* The egress acl table contains 2 rules:
 76	 * 1)Allow traffic with vlan_tag=vst_vlan_id
 77	 * 2)Drop all other traffic.
 78	 */
 79	int table_size = 2;
 80	int dest_num = 0;
 81	int actions_flag;
 82	int err = 0;
 83
 84	if (vport->egress.legacy.drop_counter) {
 85		drop_counter = vport->egress.legacy.drop_counter;
 86	} else if (MLX5_CAP_ESW_EGRESS_ACL(esw->dev, flow_counter)) {
 87		drop_counter = mlx5_fc_create(esw->dev, false);
 88		if (IS_ERR(drop_counter)) {
 89			esw_warn(esw->dev,
 90				 "vport[%d] configure egress drop rule counter err(%pe)\n",
 91				 vport->vport, drop_counter);
 92			drop_counter = NULL;
 93		}
 94		vport->egress.legacy.drop_counter = drop_counter;
 95	}
 96
 97	esw_acl_egress_lgcy_rules_destroy(vport);
 98
 99	if (!vport->info.vlan && !vport->info.qos) {
100		esw_acl_egress_lgcy_cleanup(esw, vport);
101		return 0;
102	}
103
104	if (!vport->egress.acl) {
105		vport->egress.acl = esw_acl_table_create(esw, vport,
106							 MLX5_FLOW_NAMESPACE_ESW_EGRESS,
107							 table_size);
108		if (IS_ERR(vport->egress.acl)) {
109			err = PTR_ERR(vport->egress.acl);
110			vport->egress.acl = NULL;
111			goto out;
112		}
113
114		err = esw_acl_egress_lgcy_groups_create(esw, vport);
115		if (err)
116			goto out;
117	}
118
119	esw_debug(esw->dev,
120		  "vport[%d] configure egress rules, vlan(%d) qos(%d)\n",
121		  vport->vport, vport->info.vlan, vport->info.qos);
122
123	/* Allowed vlan rule */
124	actions_flag = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
125	if (vst_mode_steering)
126		actions_flag |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
127	err = esw_egress_acl_vlan_create(esw, vport, NULL, vport->info.vlan,
128					 actions_flag);
129	if (err)
130		goto out;
131
132	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
133
134	/* Attach egress drop flow counter */
135	if (drop_counter) {
136		flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
137		drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
138		drop_ctr_dst.counter = drop_counter;
139		dst = &drop_ctr_dst;
140		dest_num++;
141	}
142	vport->egress.legacy.drop_rule =
143		mlx5_add_flow_rules(vport->egress.acl, NULL,
144				    &flow_act, dst, dest_num);
145	if (IS_ERR(vport->egress.legacy.drop_rule)) {
146		err = PTR_ERR(vport->egress.legacy.drop_rule);
147		esw_warn(esw->dev,
148			 "vport[%d] configure egress drop rule failed, err(%d)\n",
149			 vport->vport, err);
150		vport->egress.legacy.drop_rule = NULL;
151		goto out;
152	}
153
154	return err;
155
156out:
157	esw_acl_egress_lgcy_cleanup(esw, vport);
158	return err;
159}
160
161void esw_acl_egress_lgcy_cleanup(struct mlx5_eswitch *esw,
162				 struct mlx5_vport *vport)
163{
164	if (IS_ERR_OR_NULL(vport->egress.acl))
165		goto clean_drop_counter;
166
167	esw_debug(esw->dev, "Destroy vport[%d] E-Switch egress ACL\n", vport->vport);
168
169	esw_acl_egress_lgcy_rules_destroy(vport);
170	esw_acl_egress_lgcy_groups_destroy(vport);
171	esw_acl_egress_table_destroy(vport);
172
173clean_drop_counter:
174	if (vport->egress.legacy.drop_counter) {
175		mlx5_fc_destroy(esw->dev, vport->egress.legacy.drop_counter);
176		vport->egress.legacy.drop_counter = NULL;
177	}
178}
~/ Read-only file preview.