1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2020 Mellanox Technologies Inc. All rights reserved. */
9 static void esw_acl_egress_lgcy_rules_destroy(struct mlx5_vport *vport)
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;
18 static int esw_acl_egress_lgcy_groups_create(struct mlx5_eswitch *esw,
19 struct mlx5_vport *vport)
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;
27 err = esw_acl_egress_vlan_grp_create(esw, vport);
31 flow_group_in = kvzalloc(inlen, GFP_KERNEL);
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",
47 vport->egress.legacy.drop_grp = drop_grp;
48 kvfree(flow_group_in);
52 kvfree(flow_group_in);
54 esw_acl_egress_vlan_grp_destroy(vport);
58 static void esw_acl_egress_lgcy_groups_destroy(struct mlx5_vport *vport)
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;
64 esw_acl_egress_vlan_grp_destroy(vport);
67 int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
68 struct mlx5_vport *vport)
70 struct mlx5_flow_destination drop_ctr_dst = {};
71 struct mlx5_flow_destination *dst = NULL;
72 struct mlx5_fc *drop_counter = NULL;
73 struct mlx5_flow_act flow_act = {};
74 /* The egress acl table contains 2 rules:
75 * 1)Allow traffic with vlan_tag=vst_vlan_id
76 * 2)Drop all other traffic.
82 if (MLX5_CAP_ESW_EGRESS_ACL(esw->dev, flow_counter)) {
83 drop_counter = mlx5_fc_create(esw->dev, false);
84 if (IS_ERR(drop_counter))
86 "vport[%d] configure egress drop rule counter err(%ld)\n",
87 vport->vport, PTR_ERR(drop_counter));
88 vport->egress.legacy.drop_counter = drop_counter;
91 esw_acl_egress_lgcy_rules_destroy(vport);
93 if (!vport->info.vlan && !vport->info.qos) {
94 esw_acl_egress_lgcy_cleanup(esw, vport);
98 if (!IS_ERR_OR_NULL(vport->egress.acl))
101 vport->egress.acl = esw_acl_table_create(esw, vport->vport,
102 MLX5_FLOW_NAMESPACE_ESW_EGRESS,
104 if (IS_ERR(vport->egress.acl)) {
105 err = PTR_ERR(vport->egress.acl);
106 vport->egress.acl = NULL;
110 err = esw_acl_egress_lgcy_groups_create(esw, vport);
115 "vport[%d] configure egress rules, vlan(%d) qos(%d)\n",
116 vport->vport, vport->info.vlan, vport->info.qos);
118 /* Allowed vlan rule */
119 err = esw_egress_acl_vlan_create(esw, vport, NULL, vport->info.vlan,
120 MLX5_FLOW_CONTEXT_ACTION_ALLOW);
124 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
126 /* Attach egress drop flow counter */
127 if (!IS_ERR_OR_NULL(drop_counter)) {
128 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
129 drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
130 drop_ctr_dst.counter_id = mlx5_fc_id(drop_counter);
134 vport->egress.legacy.drop_rule =
135 mlx5_add_flow_rules(vport->egress.acl, NULL,
136 &flow_act, dst, dest_num);
137 if (IS_ERR(vport->egress.legacy.drop_rule)) {
138 err = PTR_ERR(vport->egress.legacy.drop_rule);
140 "vport[%d] configure egress drop rule failed, err(%d)\n",
142 vport->egress.legacy.drop_rule = NULL;
149 esw_acl_egress_lgcy_cleanup(esw, vport);
153 void esw_acl_egress_lgcy_cleanup(struct mlx5_eswitch *esw,
154 struct mlx5_vport *vport)
156 if (IS_ERR_OR_NULL(vport->egress.acl))
157 goto clean_drop_counter;
159 esw_debug(esw->dev, "Destroy vport[%d] E-Switch egress ACL\n", vport->vport);
161 esw_acl_egress_lgcy_rules_destroy(vport);
162 esw_acl_egress_lgcy_groups_destroy(vport);
163 esw_acl_egress_table_destroy(vport);
166 if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter)) {
167 mlx5_fc_destroy(esw->dev, vport->egress.legacy.drop_counter);
168 vport->egress.legacy.drop_counter = NULL;