• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 struct mlx5_flow_table *
esw_acl_table_create(struct mlx5_eswitch * esw,u16 vport_num,int ns,int size)9 esw_acl_table_create(struct mlx5_eswitch *esw, u16 vport_num, int ns, int size)
10 {
11 	struct mlx5_core_dev *dev = esw->dev;
12 	struct mlx5_flow_namespace *root_ns;
13 	struct mlx5_flow_table *acl;
14 	int acl_supported;
15 	int vport_index;
16 	int err;
17 
18 	acl_supported = (ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS) ?
19 			MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support) :
20 			MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support);
21 
22 	if (!acl_supported)
23 		return ERR_PTR(-EOPNOTSUPP);
24 
25 	esw_debug(dev, "Create vport[%d] %s ACL table\n", vport_num,
26 		  ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS ? "ingress" : "egress");
27 
28 	vport_index = mlx5_eswitch_vport_num_to_index(esw, vport_num);
29 	root_ns = mlx5_get_flow_vport_acl_namespace(dev, ns, vport_index);
30 	if (!root_ns) {
31 		esw_warn(dev, "Failed to get E-Switch root namespace for vport (%d)\n",
32 			 vport_num);
33 		return ERR_PTR(-EOPNOTSUPP);
34 	}
35 
36 	acl = mlx5_create_vport_flow_table(root_ns, 0, size, 0, vport_num);
37 	if (IS_ERR(acl)) {
38 		err = PTR_ERR(acl);
39 		esw_warn(dev, "vport[%d] create %s ACL table, err(%d)\n", vport_num,
40 			 ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS ? "ingress" : "egress", err);
41 	}
42 	return acl;
43 }
44 
esw_egress_acl_vlan_create(struct mlx5_eswitch * esw,struct mlx5_vport * vport,struct mlx5_flow_destination * fwd_dest,u16 vlan_id,u32 flow_action)45 int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw,
46 			       struct mlx5_vport *vport,
47 			       struct mlx5_flow_destination *fwd_dest,
48 			       u16 vlan_id, u32 flow_action)
49 {
50 	struct mlx5_flow_act flow_act = {};
51 	struct mlx5_flow_spec *spec;
52 	int err = 0;
53 
54 	if (vport->egress.allowed_vlan)
55 		return -EEXIST;
56 
57 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
58 	if (!spec)
59 		return -ENOMEM;
60 
61 	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
62 	MLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);
63 	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);
64 	MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vlan_id);
65 
66 	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
67 	flow_act.action = flow_action;
68 	vport->egress.allowed_vlan =
69 		mlx5_add_flow_rules(vport->egress.acl, spec,
70 				    &flow_act, fwd_dest, 0);
71 	if (IS_ERR(vport->egress.allowed_vlan)) {
72 		err = PTR_ERR(vport->egress.allowed_vlan);
73 		esw_warn(esw->dev,
74 			 "vport[%d] configure egress vlan rule failed, err(%d)\n",
75 			 vport->vport, err);
76 		vport->egress.allowed_vlan = NULL;
77 	}
78 
79 	kvfree(spec);
80 	return err;
81 }
82 
esw_acl_egress_vlan_destroy(struct mlx5_vport * vport)83 void esw_acl_egress_vlan_destroy(struct mlx5_vport *vport)
84 {
85 	if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan)) {
86 		mlx5_del_flow_rules(vport->egress.allowed_vlan);
87 		vport->egress.allowed_vlan = NULL;
88 	}
89 }
90 
esw_acl_egress_vlan_grp_create(struct mlx5_eswitch * esw,struct mlx5_vport * vport)91 int esw_acl_egress_vlan_grp_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
92 {
93 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
94 	struct mlx5_flow_group *vlan_grp;
95 	void *match_criteria;
96 	u32 *flow_group_in;
97 	int ret = 0;
98 
99 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
100 	if (!flow_group_in)
101 		return -ENOMEM;
102 
103 	MLX5_SET(create_flow_group_in, flow_group_in,
104 		 match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
105 	match_criteria = MLX5_ADDR_OF(create_flow_group_in,
106 				      flow_group_in, match_criteria);
107 	MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
108 	MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);
109 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
110 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
111 
112 	vlan_grp = mlx5_create_flow_group(vport->egress.acl, flow_group_in);
113 	if (IS_ERR(vlan_grp)) {
114 		ret = PTR_ERR(vlan_grp);
115 		esw_warn(esw->dev,
116 			 "Failed to create E-Switch vport[%d] egress pop vlans flow group, err(%d)\n",
117 			 vport->vport, ret);
118 		goto out;
119 	}
120 	vport->egress.vlan_grp = vlan_grp;
121 
122 out:
123 	kvfree(flow_group_in);
124 	return ret;
125 }
126 
esw_acl_egress_vlan_grp_destroy(struct mlx5_vport * vport)127 void esw_acl_egress_vlan_grp_destroy(struct mlx5_vport *vport)
128 {
129 	if (!IS_ERR_OR_NULL(vport->egress.vlan_grp)) {
130 		mlx5_destroy_flow_group(vport->egress.vlan_grp);
131 		vport->egress.vlan_grp = NULL;
132 	}
133 }
134 
esw_acl_egress_table_destroy(struct mlx5_vport * vport)135 void esw_acl_egress_table_destroy(struct mlx5_vport *vport)
136 {
137 	if (IS_ERR_OR_NULL(vport->egress.acl))
138 		return;
139 
140 	mlx5_destroy_flow_table(vport->egress.acl);
141 	vport->egress.acl = NULL;
142 }
143 
esw_acl_ingress_table_destroy(struct mlx5_vport * vport)144 void esw_acl_ingress_table_destroy(struct mlx5_vport *vport)
145 {
146 	if (!vport->ingress.acl)
147 		return;
148 
149 	mlx5_destroy_flow_table(vport->ingress.acl);
150 	vport->ingress.acl = NULL;
151 }
152 
esw_acl_ingress_allow_rule_destroy(struct mlx5_vport * vport)153 void esw_acl_ingress_allow_rule_destroy(struct mlx5_vport *vport)
154 {
155 	if (!vport->ingress.allow_rule)
156 		return;
157 
158 	mlx5_del_flow_rules(vport->ingress.allow_rule);
159 	vport->ingress.allow_rule = NULL;
160 }
161