Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include "base/hinic3_cmd.h"
6 : : #include "base/hinic3_compat.h"
7 : : #include "base/hinic3_hwdev.h"
8 : : #include "base/hinic3_hwif.h"
9 : : #include "base/hinic3_nic_cfg.h"
10 : : #include "hinic3_ethdev.h"
11 : : #include "hinic3_nic_io.h"
12 : :
13 : : #define HINIC3_INVALID_INDEX -1
14 : :
15 : : #define HINIC3_DEV_PRIVATE_TO_TCAM_INFO(nic_dev) \
16 : : (&((struct hinic3_nic_dev *)(nic_dev))->tcam)
17 : :
18 : : /**
19 : : * Perform a bitwise AND operation on the input key value and mask, and stores
20 : : * the result in the key_y array.
21 : : *
22 : : * @param[out] key_y
23 : : * Array for storing results.
24 : : * @param[in] src_input
25 : : * Input key array.
26 : : * @param[in] mask
27 : : * Mask array.
28 : : * @param[in] len
29 : : * Length of the key value and mask.
30 : : */
31 : : static void
32 : : tcam_translate_key_y(uint8_t *key_y, uint8_t *src_input, uint8_t *mask, uint8_t len)
33 : : {
34 : : uint8_t idx;
35 : :
36 [ # # ]: 0 : for (idx = 0; idx < len; idx++)
37 : 0 : key_y[idx] = src_input[idx] & mask[idx];
38 : : }
39 : :
40 : : /**
41 : : * Convert key_y to key_x using the exclusive OR operation.
42 : : *
43 : : * @param[out] key_x
44 : : * Array for storing results.
45 : : * @param[in] key_y
46 : : * Input key array.
47 : : * @param[in] mask
48 : : * Mask array.
49 : : * @param[in] len
50 : : * Length of the key value and mask.
51 : : */
52 : : static void
53 : : tcam_translate_key_x(uint8_t *key_x, uint8_t *key_y, uint8_t *mask, uint8_t len)
54 : : {
55 : : uint8_t idx;
56 : :
57 [ # # ]: 0 : for (idx = 0; idx < len; idx++)
58 : 0 : key_x[idx] = key_y[idx] ^ mask[idx];
59 : : }
60 : :
61 : : static void
62 : 0 : tcam_key_calculate(struct hinic3_tcam_key *tcam_key,
63 : : struct hinic3_tcam_cfg_rule *fdir_tcam_rule)
64 : : {
65 : 0 : tcam_translate_key_y(fdir_tcam_rule->key.y, (uint8_t *)(&tcam_key->key_info),
66 : 0 : (uint8_t *)(&tcam_key->key_mask),
67 : : HINIC3_TCAM_FLOW_KEY_SIZE);
68 : 0 : tcam_translate_key_x(fdir_tcam_rule->key.x, fdir_tcam_rule->key.y,
69 : : (uint8_t *)(&tcam_key->key_mask),
70 : : HINIC3_TCAM_FLOW_KEY_SIZE);
71 : 0 : }
72 : :
73 : : static void
74 : : hinic3_fdir_tcam_ipv4_init(struct hinic3_fdir_filter *rule,
75 : : struct hinic3_tcam_key *tcam_key)
76 : : {
77 : : /* Fill type of ip. */
78 : 0 : tcam_key->key_mask.ip_type = HINIC3_UINT1_MAX;
79 : 0 : tcam_key->key_info.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
80 : 0 : tcam_key->key_mask.vlan_flag = HINIC3_UINT1_MAX;
81 : 0 : tcam_key->key_info.vlan_flag = 0;
82 : :
83 : : /* Fill src IPv4. */
84 : 0 : tcam_key->key_mask.sipv4_h =
85 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv4.src_ip);
86 : 0 : tcam_key->key_mask.sipv4_l =
87 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv4.src_ip);
88 : 0 : tcam_key->key_info.sipv4_h =
89 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv4.src_ip);
90 : 0 : tcam_key->key_info.sipv4_l =
91 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv4.src_ip);
92 : :
93 : : /* Fill dst IPv4. */
94 : 0 : tcam_key->key_mask.dipv4_h =
95 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv4.dst_ip);
96 : 0 : tcam_key->key_mask.dipv4_l =
97 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv4.dst_ip);
98 : 0 : tcam_key->key_info.dipv4_h =
99 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv4.dst_ip);
100 : 0 : tcam_key->key_info.dipv4_l =
101 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv4.dst_ip);
102 : 0 : }
103 : :
104 : 0 : static void hinic3_fdir_ipv6_tcam_key_init_sip(struct hinic3_fdir_filter *rule,
105 : : struct hinic3_tcam_key *tcam_key)
106 : : {
107 : 0 : tcam_key->key_mask_ipv6.sipv6_key0 =
108 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.src_ip[0]);
109 : 0 : tcam_key->key_mask_ipv6.sipv6_key1 =
110 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.src_ip[0]);
111 : 0 : tcam_key->key_mask_ipv6.sipv6_key2 =
112 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.src_ip[0x1]);
113 : 0 : tcam_key->key_mask_ipv6.sipv6_key3 =
114 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.src_ip[0x1]);
115 : 0 : tcam_key->key_mask_ipv6.sipv6_key4 =
116 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.src_ip[0x2]);
117 : 0 : tcam_key->key_mask_ipv6.sipv6_key5 =
118 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.src_ip[0x2]);
119 : 0 : tcam_key->key_mask_ipv6.sipv6_key6 =
120 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.src_ip[0x3]);
121 : 0 : tcam_key->key_mask_ipv6.sipv6_key7 =
122 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.src_ip[0x3]);
123 : 0 : tcam_key->key_info_ipv6.sipv6_key0 =
124 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.src_ip[0]);
125 : 0 : tcam_key->key_info_ipv6.sipv6_key1 =
126 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.src_ip[0]);
127 : 0 : tcam_key->key_info_ipv6.sipv6_key2 =
128 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.src_ip[0x1]);
129 : 0 : tcam_key->key_info_ipv6.sipv6_key3 =
130 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.src_ip[0x1]);
131 : 0 : tcam_key->key_info_ipv6.sipv6_key4 =
132 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.src_ip[0x2]);
133 : 0 : tcam_key->key_info_ipv6.sipv6_key5 =
134 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.src_ip[0x2]);
135 : 0 : tcam_key->key_info_ipv6.sipv6_key6 =
136 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.src_ip[0x3]);
137 : 0 : tcam_key->key_info_ipv6.sipv6_key7 =
138 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.src_ip[0x3]);
139 : 0 : }
140 : :
141 : 0 : static void hinic3_fdir_ipv6_tcam_key_init_dip(struct hinic3_fdir_filter *rule,
142 : : struct hinic3_tcam_key *tcam_key)
143 : : {
144 : 0 : tcam_key->key_mask_ipv6.dipv6_key0 =
145 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.dst_ip[0]);
146 : 0 : tcam_key->key_mask_ipv6.dipv6_key1 =
147 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.dst_ip[0]);
148 : 0 : tcam_key->key_mask_ipv6.dipv6_key2 =
149 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.dst_ip[0x1]);
150 : 0 : tcam_key->key_mask_ipv6.dipv6_key3 =
151 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.dst_ip[0x1]);
152 : 0 : tcam_key->key_mask_ipv6.dipv6_key4 =
153 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.dst_ip[0x2]);
154 : 0 : tcam_key->key_mask_ipv6.dipv6_key5 =
155 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.dst_ip[0x2]);
156 : 0 : tcam_key->key_mask_ipv6.dipv6_key6 =
157 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.dst_ip[0x3]);
158 : 0 : tcam_key->key_mask_ipv6.dipv6_key7 =
159 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv6.dst_ip[0x3]);
160 : 0 : tcam_key->key_info_ipv6.dipv6_key0 =
161 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.dst_ip[0]);
162 : 0 : tcam_key->key_info_ipv6.dipv6_key1 =
163 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.dst_ip[0]);
164 : 0 : tcam_key->key_info_ipv6.dipv6_key2 =
165 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.dst_ip[0x1]);
166 : 0 : tcam_key->key_info_ipv6.dipv6_key3 =
167 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.dst_ip[0x1]);
168 : 0 : tcam_key->key_info_ipv6.dipv6_key4 =
169 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.dst_ip[0x2]);
170 : 0 : tcam_key->key_info_ipv6.dipv6_key5 =
171 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.dst_ip[0x2]);
172 : 0 : tcam_key->key_info_ipv6.dipv6_key6 =
173 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv6.dst_ip[0x3]);
174 : 0 : tcam_key->key_info_ipv6.dipv6_key7 =
175 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.dst_ip[0x3]);
176 : 0 : }
177 : :
178 : : static void hinic3_fdir_ipv6_tcam_key_init(struct hinic3_fdir_filter *rule,
179 : : struct hinic3_tcam_key *tcam_key)
180 : : {
181 : 0 : hinic3_fdir_ipv6_tcam_key_init_sip(rule, tcam_key);
182 : 0 : hinic3_fdir_ipv6_tcam_key_init_dip(rule, tcam_key);
183 : 0 : }
184 : :
185 : : static void
186 : 0 : hinic3_fdir_tcam_ipv6_init(struct hinic3_fdir_filter *rule,
187 : : struct hinic3_tcam_key *tcam_key)
188 : : {
189 : : /* Fill type of ip. */
190 : 0 : tcam_key->key_mask_ipv6.ip_type = HINIC3_UINT1_MAX;
191 : 0 : tcam_key->key_info_ipv6.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
192 : 0 : tcam_key->key_mask_ipv6.vlan_flag = HINIC3_UINT1_MAX;
193 : 0 : tcam_key->key_info_ipv6.vlan_flag = 0;
194 : :
195 : : hinic3_fdir_ipv6_tcam_key_init(rule, tcam_key);
196 : 0 : }
197 : :
198 : : /**
199 : : * Set the TCAM information in notunnel scenario.
200 : : *
201 : : * @param[in] dev
202 : : * Pointer to ethernet device structure.
203 : : * @param[in] rule
204 : : * Pointer to the filtering rule.
205 : : * @param[in] tcam_key
206 : : * Pointer to the TCAM key.
207 : : */
208 : : static void
209 : 0 : hinic3_fdir_tcam_notunnel_init(struct rte_eth_dev *dev,
210 : : struct hinic3_fdir_filter *rule,
211 : : struct hinic3_tcam_key *tcam_key)
212 : : {
213 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
214 : :
215 : : /* Fill tcam_key info. */
216 : 0 : tcam_key->key_mask.sport = rule->key_mask.src_port;
217 : 0 : tcam_key->key_info.sport = rule->key_spec.src_port;
218 : :
219 : 0 : tcam_key->key_mask.dport = rule->key_mask.dst_port;
220 : 0 : tcam_key->key_info.dport = rule->key_spec.dst_port;
221 : :
222 : 0 : tcam_key->key_mask.tunnel_type = HINIC3_UINT4_MAX;
223 : 0 : tcam_key->key_info.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
224 : :
225 : 0 : tcam_key->key_mask.function_id = HINIC3_UINT15_MAX;
226 : :
227 : 0 : tcam_key->key_mask.vlan_flag = 1;
228 : 0 : tcam_key->key_info.vlan_flag = 0;
229 : :
230 : 0 : tcam_key->key_info.function_id = hinic3_global_func_id(nic_dev->hwdev) &
231 : : HINIC3_UINT15_MAX;
232 : :
233 : 0 : tcam_key->key_mask.ip_proto = rule->key_mask.proto;
234 : 0 : tcam_key->key_info.ip_proto = rule->key_spec.proto;
235 : :
236 [ # # ]: 0 : if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV4)
237 : : hinic3_fdir_tcam_ipv4_init(rule, tcam_key);
238 [ # # ]: 0 : else if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV6)
239 : 0 : hinic3_fdir_tcam_ipv6_init(rule, tcam_key);
240 : 0 : }
241 : :
242 : : static void
243 : : hinic3_fdir_tcam_vxlan_ipv4_init(struct hinic3_fdir_filter *rule,
244 : : struct hinic3_tcam_key *tcam_key)
245 : : {
246 : : /* Fill type of ip. */
247 : 0 : tcam_key->key_mask.ip_type = HINIC3_UINT1_MAX;
248 : 0 : tcam_key->key_info.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
249 : 0 : tcam_key->key_mask.vlan_flag = HINIC3_UINT1_MAX;
250 : 0 : tcam_key->key_info.vlan_flag = 0;
251 : :
252 : : /* Fill src ipv4. */
253 : 0 : tcam_key->key_mask.sipv4_h =
254 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.inner_ipv4.src_ip);
255 : 0 : tcam_key->key_mask.sipv4_l =
256 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.inner_ipv4.src_ip);
257 : 0 : tcam_key->key_info.sipv4_h =
258 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.inner_ipv4.src_ip);
259 : 0 : tcam_key->key_info.sipv4_l =
260 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.inner_ipv4.src_ip);
261 : :
262 : : /* Fill dst ipv4. */
263 : 0 : tcam_key->key_mask.dipv4_h =
264 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.inner_ipv4.dst_ip);
265 : 0 : tcam_key->key_mask.dipv4_l =
266 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.inner_ipv4.dst_ip);
267 : 0 : tcam_key->key_info.dipv4_h =
268 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.inner_ipv4.dst_ip);
269 : 0 : tcam_key->key_info.dipv4_l =
270 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.inner_ipv4.dst_ip);
271 : 0 : }
272 : :
273 : : static void
274 : 0 : hinic3_fdir_tcam_vxlan_ipv6_init(struct hinic3_fdir_filter *rule,
275 : : struct hinic3_tcam_key *tcam_key)
276 : : {
277 : : /* Fill type of ip. */
278 : 0 : tcam_key->key_mask_vxlan_ipv6.ip_type = HINIC3_UINT1_MAX;
279 : 0 : tcam_key->key_info_vxlan_ipv6.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
280 : 0 : tcam_key->key_mask_vxlan_ipv6.vlan_flag = HINIC3_UINT1_MAX;
281 : 0 : tcam_key->key_info_vxlan_ipv6.vlan_flag = 0;
282 : :
283 : : /* Use inner dst ipv6 to fill the dst ipv6 of tcam_key. */
284 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key0 =
285 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0]);
286 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key1 =
287 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0]);
288 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key2 =
289 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0x1]);
290 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key3 =
291 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0x1]);
292 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key4 =
293 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0x2]);
294 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key5 =
295 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0x2]);
296 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key6 =
297 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0x3]);
298 : 0 : tcam_key->key_mask_vxlan_ipv6.dipv6_key7 =
299 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.inner_ipv6.dst_ip[0x3]);
300 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key0 =
301 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0]);
302 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key1 =
303 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0]);
304 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key2 =
305 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0x1]);
306 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key3 =
307 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0x1]);
308 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key4 =
309 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0x2]);
310 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key5 =
311 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0x2]);
312 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key6 =
313 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0x3]);
314 : 0 : tcam_key->key_info_vxlan_ipv6.dipv6_key7 =
315 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.inner_ipv6.dst_ip[0x3]);
316 : 0 : }
317 : :
318 : : static void
319 : 0 : hinic3_fdir_tcam_ipv6_vxlan_init(struct rte_eth_dev *dev,
320 : : struct hinic3_fdir_filter *rule,
321 : : struct hinic3_tcam_key *tcam_key)
322 : : {
323 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
324 : :
325 : 0 : tcam_key->key_mask_ipv6.ip_proto = rule->key_mask.proto;
326 : 0 : tcam_key->key_info_ipv6.ip_proto = rule->key_spec.proto;
327 : :
328 : 0 : tcam_key->key_mask_ipv6.tunnel_type = HINIC3_UINT4_MAX;
329 : 0 : tcam_key->key_info_ipv6.tunnel_type = rule->tunnel_type;
330 : :
331 : 0 : tcam_key->key_mask_ipv6.outer_ip_type = HINIC3_UINT1_MAX;
332 : 0 : tcam_key->key_info_ipv6.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
333 : :
334 : 0 : tcam_key->key_mask_ipv6.vlan_flag = HINIC3_UINT1_MAX;
335 : 0 : tcam_key->key_info_ipv6.vlan_flag = 0;
336 : :
337 : 0 : tcam_key->key_mask_ipv6.function_id = HINIC3_UINT15_MAX;
338 : 0 : tcam_key->key_info_ipv6.function_id =
339 : 0 : hinic3_global_func_id(nic_dev->hwdev) & HINIC3_UINT15_MAX;
340 : :
341 : 0 : tcam_key->key_mask_ipv6.dport = rule->key_mask.dst_port;
342 : 0 : tcam_key->key_info_ipv6.dport = rule->key_spec.dst_port;
343 : :
344 : 0 : tcam_key->key_mask_ipv6.sport = rule->key_mask.src_port;
345 : 0 : tcam_key->key_info_ipv6.sport = rule->key_spec.src_port;
346 : :
347 [ # # ]: 0 : if (rule->ip_type == HINIC3_FDIR_IP_TYPE_ANY)
348 : : hinic3_fdir_ipv6_tcam_key_init(rule, tcam_key);
349 : 0 : }
350 : :
351 : : /**
352 : : * Sets the TCAM information in the VXLAN scenario.
353 : : *
354 : : * @param[in] dev
355 : : * Pointer to ethernet device structure.
356 : : * @param[in] rule
357 : : * Pointer to the filtering rule.
358 : : * @param[in] tcam_key
359 : : * Pointer to the TCAM key.
360 : : */
361 : : static void
362 : 0 : hinic3_fdir_tcam_vxlan_init(struct rte_eth_dev *dev,
363 : : struct hinic3_fdir_filter *rule,
364 : : struct hinic3_tcam_key *tcam_key)
365 : : {
366 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
367 : :
368 [ # # ]: 0 : if (rule->outer_ip_type == HINIC3_FDIR_IP_TYPE_IPV6) {
369 : 0 : hinic3_fdir_tcam_ipv6_vxlan_init(dev, rule, tcam_key);
370 : 0 : return;
371 : : }
372 : :
373 : 0 : tcam_key->key_mask.ip_proto = rule->key_mask.proto;
374 : 0 : tcam_key->key_info.ip_proto = rule->key_spec.proto;
375 : :
376 : 0 : tcam_key->key_mask.sport = rule->key_mask.src_port;
377 : 0 : tcam_key->key_info.sport = rule->key_spec.src_port;
378 : :
379 : 0 : tcam_key->key_mask.dport = rule->key_mask.dst_port;
380 : 0 : tcam_key->key_info.dport = rule->key_spec.dst_port;
381 : :
382 : 0 : tcam_key->key_mask.outer_sipv4_h =
383 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv4.src_ip);
384 : 0 : tcam_key->key_mask.outer_sipv4_l =
385 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv4.src_ip);
386 : 0 : tcam_key->key_info.outer_sipv4_h =
387 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv4.src_ip);
388 : 0 : tcam_key->key_info.outer_sipv4_l =
389 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv4.src_ip);
390 : :
391 : 0 : tcam_key->key_mask.outer_dipv4_h =
392 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv4.dst_ip);
393 : 0 : tcam_key->key_mask.outer_dipv4_l =
394 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.ipv4.dst_ip);
395 : 0 : tcam_key->key_info.outer_dipv4_h =
396 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.ipv4.dst_ip);
397 : 0 : tcam_key->key_info.outer_dipv4_l =
398 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv4.dst_ip);
399 : :
400 : 0 : tcam_key->key_mask.vni_h =
401 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.tunnel.tunnel_id);
402 : 0 : tcam_key->key_mask.vni_l =
403 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.tunnel.tunnel_id);
404 : 0 : tcam_key->key_info.vni_h =
405 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.tunnel.tunnel_id);
406 : 0 : tcam_key->key_info.vni_l =
407 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.tunnel.tunnel_id);
408 : :
409 : 0 : tcam_key->key_mask.tunnel_type = HINIC3_UINT4_MAX;
410 : 0 : tcam_key->key_info.tunnel_type = rule->tunnel_type;
411 : :
412 : 0 : tcam_key->key_mask.vlan_flag = 1;
413 : 0 : tcam_key->key_mask.function_id = HINIC3_UINT15_MAX;
414 : 0 : tcam_key->key_info.vlan_flag = 0;
415 : 0 : tcam_key->key_info.function_id = hinic3_global_func_id(nic_dev->hwdev) &
416 : : HINIC3_UINT15_MAX;
417 : :
418 [ # # ]: 0 : if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV4)
419 : : hinic3_fdir_tcam_vxlan_ipv4_init(rule, tcam_key);
420 : :
421 [ # # ]: 0 : else if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV6)
422 : 0 : hinic3_fdir_tcam_vxlan_ipv6_init(rule, tcam_key);
423 : : }
424 : :
425 : : static void
426 : 0 : hinic3_fdir_tcam_info_init(struct rte_eth_dev *dev,
427 : : struct hinic3_fdir_filter *rule,
428 : : struct hinic3_tcam_key *tcam_key,
429 : : struct hinic3_tcam_cfg_rule *fdir_tcam_rule)
430 : : {
431 : : /* Initialize the TCAM based on the tunnel type. */
432 [ # # ]: 0 : if (rule->tunnel_type == HINIC3_FDIR_TUNNEL_MODE_NORMAL)
433 : 0 : hinic3_fdir_tcam_notunnel_init(dev, rule, tcam_key);
434 : : else
435 : 0 : hinic3_fdir_tcam_vxlan_init(dev, rule, tcam_key);
436 : :
437 : : /* Set the queue index. */
438 : 0 : fdir_tcam_rule->data.qid = rule->rq_index;
439 : : /* Calculate key of TCAM. */
440 : 0 : tcam_key_calculate(tcam_key, fdir_tcam_rule);
441 : 0 : }
442 : :
443 : : static void
444 : : hinic3_fdir_tcam_key_set_ipv4_sip_dip(struct rte_eth_ipv4_flow *ipv4_mask,
445 : : struct rte_eth_ipv4_flow *ipv4_spec,
446 : : struct hinic3_tcam_key *tcam_key)
447 : : {
448 : 0 : tcam_key->key_mask_htn.sipv4_h =
449 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_mask->src_ip);
450 : 0 : tcam_key->key_mask_htn.sipv4_l =
451 : : HINIC3_32_LOWER_16_BITS(ipv4_mask->src_ip);
452 : 0 : tcam_key->key_info_htn.sipv4_h =
453 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_spec->src_ip);
454 : 0 : tcam_key->key_info_htn.sipv4_l =
455 : : HINIC3_32_LOWER_16_BITS(ipv4_spec->src_ip);
456 : :
457 : 0 : tcam_key->key_mask_htn.dipv4_h =
458 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_mask->dst_ip);
459 : 0 : tcam_key->key_mask_htn.dipv4_l =
460 : : HINIC3_32_LOWER_16_BITS(ipv4_mask->dst_ip);
461 : 0 : tcam_key->key_info_htn.dipv4_h =
462 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_spec->dst_ip);
463 : 0 : tcam_key->key_info_htn.dipv4_l =
464 : : HINIC3_32_LOWER_16_BITS(ipv4_spec->dst_ip);
465 : : }
466 : :
467 : : static void
468 : 0 : hinic3_fdir_tcam_key_set_ipv6_sip(struct rte_eth_ipv6_flow *ipv6_mask,
469 : : struct rte_eth_ipv6_flow *ipv6_spec,
470 : : struct hinic3_tcam_key *tcam_key)
471 : : {
472 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key0 =
473 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->src_ip[0]);
474 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key1 =
475 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->src_ip[0]);
476 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key2 =
477 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->src_ip[0x1]);
478 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key3 =
479 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->src_ip[0x1]);
480 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key4 =
481 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->src_ip[0x2]);
482 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key5 =
483 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->src_ip[0x2]);
484 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key6 =
485 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->src_ip[0x3]);
486 : 0 : tcam_key->key_mask_ipv6_htn.sipv6_key7 =
487 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->src_ip[0x3]);
488 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key0 =
489 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->src_ip[0]);
490 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key1 =
491 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->src_ip[0]);
492 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key2 =
493 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->src_ip[0x1]);
494 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key3 =
495 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->src_ip[0x1]);
496 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key4 =
497 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->src_ip[0x2]);
498 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key5 =
499 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->src_ip[0x2]);
500 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key6 =
501 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->src_ip[0x3]);
502 : 0 : tcam_key->key_info_ipv6_htn.sipv6_key7 =
503 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->src_ip[0x3]);
504 : 0 : }
505 : :
506 : : static void
507 : 0 : hinic3_fdir_tcam_key_set_ipv6_dip(struct rte_eth_ipv6_flow *ipv6_mask,
508 : : struct rte_eth_ipv6_flow *ipv6_spec,
509 : : struct hinic3_tcam_key *tcam_key)
510 : : {
511 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key0 =
512 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->dst_ip[0]);
513 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key1 =
514 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->dst_ip[0]);
515 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key2 =
516 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->dst_ip[0x1]);
517 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key3 =
518 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->dst_ip[0x1]);
519 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key4 =
520 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->dst_ip[0x2]);
521 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key5 =
522 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->dst_ip[0x2]);
523 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key6 =
524 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_mask->dst_ip[0x3]);
525 : 0 : tcam_key->key_mask_ipv6_htn.dipv6_key7 =
526 : : HINIC3_32_LOWER_16_BITS(ipv6_mask->dst_ip[0x3]);
527 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key0 =
528 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->dst_ip[0]);
529 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key1 =
530 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->dst_ip[0]);
531 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key2 =
532 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->dst_ip[0x1]);
533 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key3 =
534 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->dst_ip[0x1]);
535 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key4 =
536 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->dst_ip[0x2]);
537 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key5 =
538 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->dst_ip[0x2]);
539 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key6 =
540 : 0 : HINIC3_32_UPPER_16_BITS(ipv6_spec->dst_ip[0x3]);
541 : 0 : tcam_key->key_info_ipv6_htn.dipv6_key7 =
542 : : HINIC3_32_LOWER_16_BITS(ipv6_spec->dst_ip[0x3]);
543 : 0 : }
544 : :
545 : : static void
546 : : hinic3_fdir_tcam_key_set_outer_ipv4_sip_dip(struct rte_eth_ipv4_flow *ipv4_mask,
547 : : struct rte_eth_ipv4_flow *ipv4_spec,
548 : : struct hinic3_tcam_key *tcam_key)
549 : : {
550 : 0 : tcam_key->key_mask_htn.outer_sipv4_h =
551 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_mask->src_ip);
552 : 0 : tcam_key->key_mask_htn.outer_sipv4_l =
553 : : HINIC3_32_LOWER_16_BITS(ipv4_mask->src_ip);
554 : 0 : tcam_key->key_info_htn.outer_sipv4_h =
555 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_spec->src_ip);
556 : 0 : tcam_key->key_info_htn.outer_sipv4_l =
557 : : HINIC3_32_LOWER_16_BITS(ipv4_spec->src_ip);
558 : :
559 : 0 : tcam_key->key_mask_htn.outer_dipv4_h =
560 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_mask->dst_ip);
561 : 0 : tcam_key->key_mask_htn.outer_dipv4_l =
562 : : HINIC3_32_LOWER_16_BITS(ipv4_mask->dst_ip);
563 : 0 : tcam_key->key_info_htn.outer_dipv4_h =
564 : 0 : HINIC3_32_UPPER_16_BITS(ipv4_spec->dst_ip);
565 : 0 : tcam_key->key_info_htn.outer_dipv4_l =
566 : : HINIC3_32_LOWER_16_BITS(ipv4_spec->dst_ip);
567 : : }
568 : :
569 : : static void
570 : : hinic3_fdir_tcam_key_set_ipv4_info(struct hinic3_fdir_filter *rule,
571 : : struct hinic3_tcam_key *tcam_key)
572 : : {
573 : 0 : tcam_key->key_mask_htn.ip_type = HINIC3_UINT2_MAX;
574 : 0 : tcam_key->key_info_htn.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
575 : :
576 : : hinic3_fdir_tcam_key_set_ipv4_sip_dip(&rule->key_mask.ipv4,
577 : : &rule->key_spec.ipv4, tcam_key);
578 : 0 : }
579 : :
580 : 0 : static void hinic3_fdir_tcam_key_set_ipv6_info(struct hinic3_fdir_filter *rule,
581 : : struct hinic3_tcam_key *tcam_key)
582 : : {
583 : 0 : tcam_key->key_mask_ipv6_htn.ip_type = HINIC3_UINT2_MAX;
584 : 0 : tcam_key->key_info_ipv6_htn.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
585 : :
586 : 0 : hinic3_fdir_tcam_key_set_ipv6_sip(&rule->key_mask.ipv6,
587 : : &rule->key_spec.ipv6, tcam_key);
588 : 0 : hinic3_fdir_tcam_key_set_ipv6_dip(&rule->key_mask.ipv6,
589 : : &rule->key_spec.ipv6, tcam_key);
590 : 0 : }
591 : :
592 : : static void
593 : 0 : hinic3_fdir_tcam_notunnel_htn_init(struct hinic3_fdir_filter *rule,
594 : : struct hinic3_tcam_key *tcam_key)
595 : : {
596 : 0 : tcam_key->key_mask_htn.tunnel_type = HINIC3_UINT3_MAX;
597 : 0 : tcam_key->key_info_htn.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
598 : :
599 [ # # ]: 0 : if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV4)
600 : : hinic3_fdir_tcam_key_set_ipv4_info(rule, tcam_key);
601 [ # # ]: 0 : else if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV6)
602 : 0 : hinic3_fdir_tcam_key_set_ipv6_info(rule, tcam_key);
603 : 0 : }
604 : :
605 : : static void
606 : : hinic3_fdir_tcam_key_set_outer_ipv4_info(struct hinic3_fdir_filter *rule,
607 : : struct hinic3_tcam_key *tcam_key)
608 : : {
609 : 0 : tcam_key->key_mask_ipv6_htn.outer_ip_type = HINIC3_UINT1_MAX;
610 : 0 : tcam_key->key_info_ipv6_htn.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
611 : :
612 : : hinic3_fdir_tcam_key_set_outer_ipv4_sip_dip(&rule->key_mask.ipv4,
613 : : &rule->key_spec.ipv4, tcam_key);
614 : 0 : }
615 : :
616 : : static void
617 : : hinic3_fdir_tcam_key_set_inner_ipv4_info(struct hinic3_fdir_filter *rule,
618 : : struct hinic3_tcam_key *tcam_key)
619 : : {
620 : 0 : tcam_key->key_mask_htn.ip_type = HINIC3_UINT2_MAX;
621 : 0 : tcam_key->key_info_htn.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
622 : :
623 : : hinic3_fdir_tcam_key_set_ipv4_sip_dip(&rule->key_mask.inner_ipv4,
624 : : &rule->key_spec.inner_ipv4, tcam_key);
625 : 0 : }
626 : :
627 : : static void
628 : : hinic3_fdir_tcam_key_set_inner_ipv6_info(struct hinic3_fdir_filter *rule,
629 : : struct hinic3_tcam_key *tcam_key)
630 : : {
631 : 0 : tcam_key->key_mask_vxlan_ipv6_htn.ip_type = HINIC3_UINT2_MAX;
632 : 0 : tcam_key->key_info_vxlan_ipv6_htn.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
633 : :
634 : 0 : hinic3_fdir_tcam_key_set_ipv6_dip(&rule->key_mask.inner_ipv6,
635 : : &rule->key_spec.inner_ipv6, tcam_key);
636 : 0 : }
637 : :
638 : : static void
639 : 0 : hinic3_fdir_tcam_tunnel_htn_init(struct hinic3_fdir_filter *rule,
640 : : struct hinic3_tcam_key *tcam_key)
641 : : {
642 : 0 : tcam_key->key_mask_htn.tunnel_type = HINIC3_UINT3_MAX;
643 : 0 : tcam_key->key_info_htn.tunnel_type = rule->tunnel_type;
644 : :
645 : 0 : tcam_key->key_mask_htn.vni_h =
646 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_mask.tunnel.tunnel_id);
647 : 0 : tcam_key->key_mask_htn.vni_l =
648 : : HINIC3_32_LOWER_16_BITS(rule->key_mask.tunnel.tunnel_id);
649 : 0 : tcam_key->key_info_htn.vni_h =
650 : 0 : HINIC3_32_UPPER_16_BITS(rule->key_spec.tunnel.tunnel_id);
651 : 0 : tcam_key->key_info_htn.vni_l =
652 : : HINIC3_32_LOWER_16_BITS(rule->key_spec.tunnel.tunnel_id);
653 : :
654 [ # # ]: 0 : if (rule->outer_ip_type == HINIC3_FDIR_IP_TYPE_IPV4)
655 : : hinic3_fdir_tcam_key_set_outer_ipv4_info(rule, tcam_key);
656 : :
657 [ # # ]: 0 : if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV4)
658 : : hinic3_fdir_tcam_key_set_inner_ipv4_info(rule, tcam_key);
659 [ # # ]: 0 : else if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV6)
660 : : hinic3_fdir_tcam_key_set_inner_ipv6_info(rule, tcam_key);
661 : 0 : }
662 : :
663 : : static void
664 : 0 : hinic3_fdir_tcam_info_htn_init(struct rte_eth_dev *dev,
665 : : struct hinic3_fdir_filter *rule,
666 : : struct hinic3_tcam_key *tcam_key,
667 : : struct hinic3_tcam_cfg_rule *fdir_tcam_rule)
668 : : {
669 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
670 : :
671 : 0 : tcam_key->key_mask_htn.function_id_h = HINIC3_UINT5_MAX;
672 : 0 : tcam_key->key_mask_htn.function_id_l = HINIC3_UINT5_MAX;
673 : 0 : tcam_key->key_info_htn.function_id_l =
674 : 0 : hinic3_global_func_id(nic_dev->hwdev) & HINIC3_UINT5_MAX;
675 : 0 : tcam_key->key_info_htn.function_id_h =
676 : 0 : (hinic3_global_func_id(nic_dev->hwdev) >> HINIC3_UINT5_WIDTH) & HINIC3_UINT5_MAX;
677 : :
678 : 0 : tcam_key->key_mask_htn.ip_proto = rule->key_mask.proto;
679 : 0 : tcam_key->key_info_htn.ip_proto = rule->key_spec.proto;
680 : :
681 : 0 : tcam_key->key_mask_htn.sport = rule->key_mask.src_port;
682 : 0 : tcam_key->key_info_htn.sport = rule->key_spec.src_port;
683 : :
684 : 0 : tcam_key->key_mask_htn.dport = rule->key_mask.dst_port;
685 : 0 : tcam_key->key_info_htn.dport = rule->key_spec.dst_port;
686 [ # # ]: 0 : if (rule->tunnel_type == HINIC3_FDIR_TUNNEL_MODE_NORMAL)
687 : 0 : hinic3_fdir_tcam_notunnel_htn_init(rule, tcam_key);
688 : : else
689 : 0 : hinic3_fdir_tcam_tunnel_htn_init(rule, tcam_key);
690 : :
691 : 0 : fdir_tcam_rule->data.qid = rule->rq_index;
692 : :
693 : 0 : tcam_key_calculate(tcam_key, fdir_tcam_rule);
694 : 0 : }
695 : :
696 : : /**
697 : : * Find filter in given ethertype filter list.
698 : : *
699 : : * @param[in] filter_list
700 : : * Point to the Ether filter list.
701 : : * @param[in] key
702 : : * The tcam key to find.
703 : : * @return
704 : : * If a matching filter is found, the filter is returned, otherwise
705 : : * RTE_ETH_FILTER_NONE.
706 : : */
707 : : static inline uint16_t
708 : : hinic3_ethertype_filter_lookup(struct hinic3_ethertype_filter_list *ethertype_list,
709 : : uint16_t type)
710 : : {
711 : : struct rte_flow *it;
712 : : struct hinic3_filter_t *filter_rules;
713 : :
714 [ # # ]: 0 : TAILQ_FOREACH(it, ethertype_list, node) {
715 : 0 : filter_rules = it->rule;
716 [ # # ]: 0 : if (type == filter_rules->ethertype_filter.ether_type)
717 : : return filter_rules->ethertype_filter.ether_type;
718 : : }
719 : :
720 : : return RTE_ETH_FILTER_NONE;
721 : : }
722 : :
723 : : /**
724 : : * Find the filter that matches the given key in the TCAM filter list.
725 : : *
726 : : * @param[in] filter_list
727 : : * Point to the tcam filter list.
728 : : * @param[in] key
729 : : * The tcam key to find.
730 : : * @param[in] action_type
731 : : * The type of action.
732 : : * @param[in] tcam_index
733 : : * The index of tcam.
734 : : * @return
735 : : * If a matching filter is found, the filter is returned, otherwise NULL.
736 : : */
737 : : static inline struct hinic3_tcam_filter *
738 : 0 : hinic3_tcam_filter_lookup(struct hinic3_tcam_filter_list *filter_list,
739 : : struct hinic3_tcam_key *key,
740 : : uint8_t action_type, uint16_t tcam_index)
741 : : {
742 : : struct hinic3_tcam_filter *it;
743 : :
744 [ # # ]: 0 : if (action_type == HINIC3_ACTION_ADD) {
745 [ # # ]: 0 : TAILQ_FOREACH(it, filter_list, entries) {
746 [ # # ]: 0 : if (memcmp(key, &it->tcam_key, sizeof(struct hinic3_tcam_key)) == 0)
747 : 0 : return it;
748 : : }
749 : : } else {
750 [ # # ]: 0 : TAILQ_FOREACH(it, filter_list, entries) {
751 : 0 : if (tcam_index ==
752 [ # # ]: 0 : (it->index + HINIC3_PKT_TCAM_DYNAMIC_INDEX_START(it->dynamic_block_id)))
753 : 0 : return it;
754 : : }
755 : : }
756 : :
757 : : return NULL;
758 : : }
759 : : /**
760 : : * Allocate memory for dynamic blocks and then add them to the queue.
761 : : *
762 : : * @param[in] tcam_info
763 : : * Point to TCAM information.
764 : : * @param[in] dynamic_block_id
765 : : * Indicate the ID of a dynamic block.
766 : : * @return
767 : : * Return the pointer to the dynamic block, or NULL if the allocation fails.
768 : : */
769 : : static struct hinic3_tcam_dynamic_block *
770 : 0 : hinic3_alloc_dynamic_block_resource(struct hinic3_tcam_info *tcam_info,
771 : : uint16_t dynamic_block_id)
772 : : {
773 : : struct hinic3_tcam_dynamic_block *dynamic_block_ptr = NULL;
774 : :
775 : : dynamic_block_ptr =
776 : 0 : rte_zmalloc("hinic3_tcam_dynamic_mem",
777 : : sizeof(struct hinic3_tcam_dynamic_block), 0);
778 [ # # ]: 0 : if (dynamic_block_ptr == NULL) {
779 : 0 : PMD_DRV_LOG(ERR,
780 : : "Alloc fdir filter dynamic block index %d memory failed!",
781 : : dynamic_block_id);
782 : 0 : return NULL;
783 : : }
784 : :
785 : 0 : dynamic_block_ptr->dynamic_block_id = dynamic_block_id;
786 : :
787 : : /* Add new block to the end of the TCAM dynamic block list. */
788 : 0 : TAILQ_INSERT_TAIL(&tcam_info->tcam_dynamic_info.tcam_dynamic_list,
789 : : dynamic_block_ptr, entries);
790 : :
791 : 0 : tcam_info->tcam_dynamic_info.dynamic_block_cnt++;
792 : :
793 : 0 : return dynamic_block_ptr;
794 : : }
795 : :
796 : : static void
797 : 0 : hinic3_free_dynamic_block_resource(struct hinic3_tcam_info *tcam_info,
798 : : struct hinic3_tcam_dynamic_block *dynamic_block_ptr)
799 : : {
800 [ # # ]: 0 : if (dynamic_block_ptr == NULL)
801 : : return;
802 : :
803 : : /* Remove the incoming dynamic block from the TCAM dynamic list. */
804 [ # # ]: 0 : TAILQ_REMOVE(&tcam_info->tcam_dynamic_info.tcam_dynamic_list,
805 : : dynamic_block_ptr, entries);
806 : 0 : rte_free(dynamic_block_ptr);
807 : :
808 : 0 : tcam_info->tcam_dynamic_info.dynamic_block_cnt--;
809 : : }
810 : :
811 : : /**
812 : : * Check whether there are free positions in the dynamic TCAM filter.
813 : : *
814 : : * @param[in] dev
815 : : * Pointer to ethernet device structure.
816 : : * @param[in] tcam_info
817 : : * Ternary Content-Addressable Memory (TCAM) information.
818 : : * @param[out] tcam_index
819 : : * Indicate the TCAM index to be searched for.
820 : : * @result
821 : : * Pointer to the TCAM dynamic block. If the search fails, NULL is returned.
822 : : */
823 : : static struct hinic3_tcam_dynamic_block *
824 : 0 : hinic3_dynamic_lookup_tcam_filter(struct hinic3_nic_dev *nic_dev,
825 : : struct hinic3_tcam_info *tcam_info,
826 : : uint16_t *tcam_index)
827 : : {
828 : 0 : uint16_t block_cnt = tcam_info->tcam_dynamic_info.dynamic_block_cnt;
829 : : struct hinic3_tcam_dynamic_block *dynamic_block_ptr = NULL;
830 : : struct hinic3_tcam_dynamic_block *tmp = NULL;
831 : 0 : uint16_t rule_nums = nic_dev->tcam_rule_nums;
832 : : int block_alloc_flag = 0;
833 : 0 : uint16_t dynamic_block_id = 0;
834 : : uint16_t index;
835 : : int err;
836 : :
837 [ # # ]: 0 : if ((hinic3_get_driver_feature(nic_dev) & NIC_F_HTN_FDIR) != 0)
838 : 0 : rule_nums += nic_dev->ethertype_rule_nums;
839 : : /*
840 : : * Check whether the number of filtering rules reaches the maximum
841 : : * capacity of dynamic TCAM blocks.
842 : : */
843 [ # # ]: 0 : if (rule_nums >= block_cnt * HINIC3_TCAM_DYNAMIC_BLOCK_SIZE) {
844 [ # # ]: 0 : if (block_cnt >= (HINIC3_TCAM_DYNAMIC_MAX_FILTERS /
845 : : HINIC3_TCAM_DYNAMIC_BLOCK_SIZE)) {
846 : 0 : PMD_DRV_LOG(ERR,
847 : : "Dynamic tcam block is full, alloc failed!");
848 : 0 : goto failed;
849 : : }
850 : : /*
851 : : * The TCAM blocks are insufficient.
852 : : * Apply for a new TCAM block.
853 : : */
854 : 0 : err = hinic3_alloc_tcam_block(nic_dev->hwdev, &dynamic_block_id);
855 [ # # ]: 0 : if (err) {
856 : 0 : PMD_DRV_LOG(ERR,
857 : : "Fdir filter dynamic tcam alloc block failed!");
858 : 0 : goto failed;
859 : : }
860 : :
861 : : block_alloc_flag = 1;
862 : :
863 : : /* Applying for Memory. */
864 : : dynamic_block_ptr =
865 : 0 : hinic3_alloc_dynamic_block_resource(tcam_info,
866 : : dynamic_block_id);
867 [ # # ]: 0 : if (dynamic_block_ptr == NULL) {
868 : 0 : PMD_DRV_LOG(ERR, "Fdir filter dynamic alloc block memory failed!");
869 : 0 : goto block_alloc_failed;
870 : : }
871 : : }
872 : :
873 : : /*
874 : : * Find the first dynamic TCAM block that meets dynamci_index_cnt <
875 : : * HINIC3_TCAM_DYNAMIC_BLOCK_SIZE.
876 : : */
877 [ # # ]: 0 : TAILQ_FOREACH(tmp, &tcam_info->tcam_dynamic_info.tcam_dynamic_list,
878 : : entries) {
879 [ # # ]: 0 : if (tmp->dynamic_index_cnt < HINIC3_TCAM_DYNAMIC_BLOCK_SIZE)
880 : : break;
881 : : }
882 : :
883 [ # # ]: 0 : if (tmp == NULL ||
884 [ # # ]: 0 : tmp->dynamic_index_cnt >= HINIC3_TCAM_DYNAMIC_BLOCK_SIZE) {
885 : 0 : PMD_DRV_LOG(ERR, "Fdir filter dynamic lookup for index failed!");
886 : 0 : goto look_up_failed;
887 : : }
888 : :
889 [ # # ]: 0 : for (index = 0; index < HINIC3_TCAM_DYNAMIC_BLOCK_SIZE; index++) {
890 [ # # ]: 0 : if (tmp->dynamic_index[index] == 0)
891 : : break;
892 : : }
893 : :
894 : : /* Find the first free position. */
895 [ # # ]: 0 : if (index == HINIC3_TCAM_DYNAMIC_BLOCK_SIZE) {
896 : 0 : PMD_DRV_LOG(ERR, "tcam block 0x%x supports filter rules is full!",
897 : : tmp->dynamic_block_id);
898 : 0 : goto look_up_failed;
899 : : }
900 : :
901 : 0 : *tcam_index = index;
902 : :
903 : 0 : return tmp;
904 : :
905 : 0 : look_up_failed:
906 [ # # ]: 0 : if (dynamic_block_ptr != NULL)
907 : 0 : hinic3_free_dynamic_block_resource(tcam_info, dynamic_block_ptr);
908 : :
909 : 0 : block_alloc_failed:
910 [ # # ]: 0 : if (block_alloc_flag == 1)
911 : 0 : hinic3_free_tcam_block(nic_dev->hwdev, &dynamic_block_id);
912 : :
913 : 0 : failed:
914 : : return NULL;
915 : : }
916 : :
917 : : static void
918 : 0 : hinic3_tcam_index_free(struct hinic3_nic_dev *nic_dev, uint16_t index, uint16_t block_id)
919 : : {
920 : 0 : struct hinic3_tcam_info *tcam_info = HINIC3_DEV_PRIVATE_TO_TCAM_INFO(nic_dev);
921 : : struct hinic3_tcam_dynamic_block *tmp = NULL;
922 : :
923 [ # # ]: 0 : TAILQ_FOREACH(tmp, &tcam_info->tcam_dynamic_info.tcam_dynamic_list, entries) {
924 [ # # ]: 0 : if (tmp->dynamic_block_id == block_id)
925 : : break;
926 : : }
927 : :
928 [ # # # # ]: 0 : if (tmp == NULL || tmp->dynamic_block_id != block_id) {
929 : 0 : PMD_DRV_LOG(ERR, "Fdir filter del dynamic lookup for block failed!");
930 : 0 : return;
931 : : }
932 : :
933 : 0 : tmp->dynamic_index[index] = 0;
934 : 0 : tmp->dynamic_index_cnt--;
935 [ # # ]: 0 : if (tmp->dynamic_index_cnt == 0) {
936 : 0 : hinic3_free_tcam_block(nic_dev->hwdev, &block_id);
937 : 0 : hinic3_free_dynamic_block_resource(tcam_info, tmp);
938 : : }
939 : : }
940 : :
941 : : static uint16_t
942 : 0 : hinic3_tcam_alloc_index(void *dev, uint16_t *block_id)
943 : : {
944 : : struct hinic3_nic_dev *nic_dev = (struct hinic3_nic_dev *)dev;
945 : 0 : struct hinic3_tcam_info *tcam_info = HINIC3_DEV_PRIVATE_TO_TCAM_INFO(nic_dev);
946 : : struct hinic3_tcam_dynamic_block *tmp = NULL;
947 : 0 : uint16_t index = 0;
948 : :
949 : 0 : tmp = hinic3_dynamic_lookup_tcam_filter(nic_dev, tcam_info, &index);
950 [ # # ]: 0 : if (tmp == NULL) {
951 : 0 : PMD_DRV_LOG(ERR, "Dynamic lookup tcam filter failed!");
952 : 0 : return HINIC3_TCAM_INVALID_INDEX;
953 : : }
954 : :
955 : 0 : tmp->dynamic_index[index] = 1;
956 : 0 : tmp->dynamic_index_cnt++;
957 : :
958 : 0 : *block_id = tmp->dynamic_block_id;
959 : :
960 : 0 : return index;
961 : : }
962 : :
963 : : static int
964 : 0 : hinic3_set_fdir_ethertype_filter(void *hwdev, uint8_t pkt_type, void *filter, uint8_t en)
965 : : {
966 : : struct hinic3_set_fdir_ethertype_rule ethertype_cmd;
967 : : struct hinic3_ethertype_filter *ethertype_filter = (struct hinic3_ethertype_filter *)filter;
968 : 0 : uint16_t out_size = sizeof(ethertype_cmd);
969 : : uint16_t block_id;
970 : : uint32_t index = 0;
971 : : int err;
972 : :
973 [ # # ]: 0 : if (!hwdev)
974 : : return -EINVAL;
975 : 0 : struct hinic3_nic_dev *nic_dev =
976 : : (struct hinic3_nic_dev *)((struct hinic3_hwdev *)hwdev)->dev_handle;
977 : :
978 [ # # ]: 0 : if ((hinic3_get_driver_feature(nic_dev) & NIC_F_HTN_FDIR) != 0) {
979 [ # # ]: 0 : if (en != 0) {
980 : 0 : index = hinic3_tcam_alloc_index(nic_dev, &block_id);
981 [ # # ]: 0 : if (index == HINIC3_TCAM_INVALID_INDEX)
982 : : return -ENOMEM;
983 : 0 : index += HINIC3_PKT_TCAM_DYNAMIC_INDEX_START(block_id);
984 : : } else {
985 : 0 : index = ethertype_filter->tcam_index[pkt_type];
986 : : }
987 : : }
988 : :
989 : : memset(ðertype_cmd, 0, sizeof(struct hinic3_set_fdir_ethertype_rule));
990 : 0 : ethertype_cmd.func_id = hinic3_global_func_id(hwdev);
991 : 0 : ethertype_cmd.pkt_type = pkt_type;
992 : 0 : ethertype_cmd.pkt_type_en = en;
993 : 0 : ethertype_cmd.index = index;
994 : 0 : ethertype_cmd.qid = (uint8_t)ethertype_filter->queue;
995 : :
996 : 0 : err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_L2NIC,
997 : : HINIC3_NIC_CMD_SET_FDIR_STATUS,
998 : : ðertype_cmd, sizeof(ethertype_cmd),
999 : : ðertype_cmd, &out_size);
1000 [ # # # # : 0 : if (err || ethertype_cmd.head.status || !out_size) {
# # ]
1001 : 0 : PMD_DRV_LOG(ERR,
1002 : : "set fdir ethertype rule failed, err: %d, status: 0x%x, out size: 0x%x, func_id %d",
1003 : : err, ethertype_cmd.head.status, out_size, ethertype_cmd.func_id);
1004 : 0 : return -EIO;
1005 : : }
1006 [ # # ]: 0 : if ((hinic3_get_driver_feature(nic_dev) & NIC_F_HTN_FDIR) != 0) {
1007 [ # # ]: 0 : if (en == 0) {
1008 : 0 : hinic3_tcam_index_free(nic_dev, HINIC3_TCAM_GET_INDEX_IN_BLOCK(index),
1009 : 0 : HINIC3_TCAM_GET_DYNAMIC_BLOCK_INDEX(index));
1010 : : } else {
1011 : 0 : ethertype_filter->tcam_index[pkt_type] = index;
1012 : : }
1013 : : }
1014 : :
1015 : : return 0;
1016 : : }
1017 : :
1018 : : /**
1019 : : * Add a TCAM filter.
1020 : : *
1021 : : * @param[in] dev
1022 : : * Pointer to ethernet device structure.
1023 : : * @param[in] tcam_key
1024 : : * Pointer to the TCAM key.
1025 : : * @param[in] fdir_tcam_rule
1026 : : * Pointer to the TCAM filtering rule.
1027 : : * @return
1028 : : * 0 on success, non-zero on failure.
1029 : : */
1030 : : static int
1031 : 0 : hinic3_add_tcam_filter(struct rte_eth_dev *dev,
1032 : : struct hinic3_tcam_key *tcam_key,
1033 : : struct hinic3_tcam_cfg_rule *fdir_tcam_rule)
1034 : : {
1035 : : struct hinic3_tcam_info *tcam_info =
1036 : 0 : HINIC3_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private);
1037 : : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1038 : : struct hinic3_tcam_filter *tcam_filter;
1039 : : int err;
1040 : :
1041 : : /* Alloc TCAM filter memory. */
1042 : 0 : tcam_filter = rte_zmalloc("hinic3_fdir_filter",
1043 : : sizeof(struct hinic3_tcam_filter), 0);
1044 [ # # ]: 0 : if (tcam_filter == NULL)
1045 : : return -ENOMEM;
1046 : :
1047 : 0 : tcam_filter->tcam_key = *tcam_key;
1048 : 0 : tcam_filter->queue = (uint16_t)(fdir_tcam_rule->data.qid);
1049 : 0 : tcam_filter->index = hinic3_tcam_alloc_index(nic_dev, &tcam_filter->dynamic_block_id);
1050 [ # # ]: 0 : if (tcam_filter->index == HINIC3_TCAM_INVALID_INDEX)
1051 : 0 : goto failed;
1052 : 0 : fdir_tcam_rule->index = HINIC3_PKT_TCAM_DYNAMIC_INDEX_START(tcam_filter->dynamic_block_id) +
1053 : 0 : tcam_filter->index;
1054 : :
1055 : : /* Add a new TCAM rule to the network device. */
1056 : 0 : err = hinic3_add_tcam_rule(nic_dev->hwdev, fdir_tcam_rule, TCAM_RULE_FDIR_TYPE);
1057 [ # # ]: 0 : if (err) {
1058 : 0 : PMD_DRV_LOG(ERR, "Fdir_tcam_rule add failed!");
1059 : 0 : goto add_tcam_rules_failed;
1060 : : }
1061 : :
1062 : : /* If there are no rules, TCAM filtering is enabled. */
1063 [ # # ]: 0 : if (!(nic_dev->ethertype_rule_nums + nic_dev->tcam_rule_nums)) {
1064 : 0 : err = hinic3_set_fdir_tcam_rule_filter(nic_dev->hwdev, true);
1065 [ # # ]: 0 : if (err)
1066 : 0 : goto enable_failed;
1067 : : }
1068 : :
1069 : : /* Add a filter to the end of the queue. */
1070 : 0 : TAILQ_INSERT_TAIL(&tcam_info->tcam_list, tcam_filter, entries);
1071 : :
1072 : 0 : nic_dev->tcam_rule_nums++;
1073 : :
1074 : 0 : PMD_DRV_LOG(INFO,
1075 : : "Add fdir tcam rule succeed, function_id: 0x%x",
1076 : : hinic3_global_func_id(nic_dev->hwdev));
1077 : 0 : PMD_DRV_LOG(INFO,
1078 : : "tcam_block_id: %d, local_index: %d, global_index: %d, queue: %d, tcam_rule_nums: %d",
1079 : : tcam_filter->dynamic_block_id, tcam_filter->index, fdir_tcam_rule->index,
1080 : : fdir_tcam_rule->data.qid, nic_dev->tcam_rule_nums);
1081 : 0 : return 0;
1082 : :
1083 : : enable_failed:
1084 : 0 : hinic3_del_tcam_rule(nic_dev->hwdev,
1085 : : fdir_tcam_rule->index,
1086 : : TCAM_RULE_FDIR_TYPE);
1087 : :
1088 : 0 : add_tcam_rules_failed:
1089 : 0 : hinic3_tcam_index_free(nic_dev, tcam_filter->index, tcam_filter->dynamic_block_id);
1090 : :
1091 : 0 : failed:
1092 : 0 : rte_free(tcam_filter);
1093 : 0 : return -EFAULT;
1094 : : }
1095 : :
1096 : : /**
1097 : : * Delete a TCAM filter.
1098 : : *
1099 : : * @param[in] dev
1100 : : * Pointer to ethernet device structure.
1101 : : * @param[in] tcam_filter
1102 : : * TCAM Filters to Delete.
1103 : : * @return
1104 : : * 0 on success, non-zero on failure.
1105 : : */
1106 : : static int
1107 : 0 : hinic3_del_dynamic_tcam_filter(struct rte_eth_dev *dev,
1108 : : struct hinic3_tcam_filter *tcam_filter)
1109 : : {
1110 : : struct hinic3_tcam_info *tcam_info =
1111 : 0 : HINIC3_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private);
1112 : : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1113 : 0 : uint16_t dynamic_block_id = tcam_filter->dynamic_block_id;
1114 : : struct hinic3_tcam_dynamic_block *tmp = NULL;
1115 : : uint32_t index = 0;
1116 : : int err;
1117 : :
1118 : : /* Traverse to find the block that matches the given ID. */
1119 [ # # ]: 0 : TAILQ_FOREACH(tmp, &tcam_info->tcam_dynamic_info.tcam_dynamic_list,
1120 : : entries) {
1121 [ # # ]: 0 : if (tmp->dynamic_block_id == dynamic_block_id)
1122 : : break;
1123 : : }
1124 : :
1125 [ # # # # ]: 0 : if (tmp == NULL || tmp->dynamic_block_id != dynamic_block_id) {
1126 : 0 : PMD_DRV_LOG(ERR, "Fdir filter del dynamic lookup for block failed!");
1127 : 0 : return -EINVAL;
1128 : : }
1129 : : /* Calculate TCAM index. */
1130 : 0 : index = HINIC3_PKT_TCAM_DYNAMIC_INDEX_START(tmp->dynamic_block_id) +
1131 : 0 : tcam_filter->index;
1132 : :
1133 : : /* Delete a specified rule. */
1134 : 0 : err = hinic3_del_tcam_rule(nic_dev->hwdev, index, TCAM_RULE_FDIR_TYPE);
1135 [ # # ]: 0 : if (err) {
1136 : 0 : PMD_DRV_LOG(ERR, "Fdir tcam rule del failed!");
1137 : 0 : return -EFAULT;
1138 : : }
1139 : :
1140 : 0 : PMD_DRV_LOG(INFO,
1141 : : "Del fdir_tcam_dynamic_rule succeed, function_id: 0x%x",
1142 : : hinic3_global_func_id(nic_dev->hwdev));
1143 : 0 : PMD_DRV_LOG(INFO,
1144 : : "tcam_block_id: %d, local_index: %d, global_index: %d, local_rules_nums: %d, global_rule_nums: %d",
1145 : : dynamic_block_id, tcam_filter->index, index,
1146 : : tmp->dynamic_index_cnt - 1, nic_dev->tcam_rule_nums - 1);
1147 : :
1148 : 0 : hinic3_tcam_index_free(nic_dev, tcam_filter->index, tmp->dynamic_block_id);
1149 : :
1150 : 0 : nic_dev->tcam_rule_nums--;
1151 : :
1152 : : /* If the number of rules is 0, the TCAM filter is disabled. */
1153 [ # # ]: 0 : if (!(nic_dev->ethertype_rule_nums + nic_dev->tcam_rule_nums))
1154 : 0 : hinic3_set_fdir_tcam_rule_filter(nic_dev->hwdev, false);
1155 : :
1156 : : return 0;
1157 : : }
1158 : :
1159 : : static int
1160 : 0 : hinic3_del_tcam_filter(struct rte_eth_dev *dev,
1161 : : struct hinic3_tcam_filter *tcam_filter)
1162 : : {
1163 : : struct hinic3_tcam_info *tcam_info =
1164 : 0 : HINIC3_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private);
1165 : : int err;
1166 : :
1167 : 0 : err = hinic3_del_dynamic_tcam_filter(dev, tcam_filter);
1168 [ # # ]: 0 : if (err < 0) {
1169 : 0 : PMD_DRV_LOG(ERR, "Del dynamic tcam filter failed!");
1170 : 0 : return err;
1171 : : }
1172 : :
1173 : : /* Remove the filter from the TCAM list. */
1174 [ # # ]: 0 : TAILQ_REMOVE(&tcam_info->tcam_list, tcam_filter, entries);
1175 : :
1176 : 0 : rte_free(tcam_filter);
1177 : :
1178 : 0 : return 0;
1179 : : }
1180 : :
1181 : : /**
1182 : : * Add or deletes an fdir filter rule. This is the core function for operating
1183 : : * filters.
1184 : : *
1185 : : * @param[in] dev
1186 : : * Pointer to ethernet device structure.
1187 : : * @param[in] fdir_filter
1188 : : * Pointer to the fdir filter.
1189 : : * @param[in] add
1190 : : * This is a Boolean value (of the bool type) indicating whether the action to
1191 : : * be performed is to add (true) or delete (false) the filter rule.
1192 : : * @return
1193 : : * 0 on success, non-zero on failure.
1194 : : */
1195 : : int
1196 : 0 : hinic3_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
1197 : : struct hinic3_fdir_filter *fdir_filter,
1198 : : bool add)
1199 : : {
1200 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1201 : : struct hinic3_tcam_info *tcam_info =
1202 : : HINIC3_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private);
1203 : : struct hinic3_tcam_filter *tcam_filter;
1204 : : struct hinic3_tcam_cfg_rule fdir_tcam_rule;
1205 : : struct hinic3_tcam_key tcam_key;
1206 : : int ret;
1207 : :
1208 : : memset(&fdir_tcam_rule, 0, sizeof(struct hinic3_tcam_cfg_rule));
1209 : : memset((void *)&tcam_key, 0, sizeof(struct hinic3_tcam_key));
1210 : :
1211 [ # # ]: 0 : if ((hinic3_get_driver_feature(nic_dev) & NIC_F_HTN_FDIR) == 0)
1212 : 0 : hinic3_fdir_tcam_info_init(dev, fdir_filter, &tcam_key, &fdir_tcam_rule);
1213 : : else
1214 : 0 : hinic3_fdir_tcam_info_htn_init(dev, fdir_filter, &tcam_key, &fdir_tcam_rule);
1215 : :
1216 : : /* Search for a filter. */
1217 : : tcam_filter =
1218 : 0 : hinic3_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key,
1219 : : HINIC3_ACTION_ADD, HINIC3_INVALID_INDEX);
1220 [ # # ]: 0 : if (tcam_filter != NULL && add) {
1221 : 0 : PMD_DRV_LOG(ERR, "Filter exists.");
1222 : 0 : return -EEXIST;
1223 : : }
1224 [ # # ]: 0 : if (tcam_filter == NULL && !add) {
1225 : 0 : PMD_DRV_LOG(ERR, "Filter doesn't exist.");
1226 : 0 : return -ENOENT;
1227 : : }
1228 : :
1229 : : /*
1230 : : * If the value of Add is true, the system performs the adding
1231 : : * operation.
1232 : : */
1233 [ # # ]: 0 : if (add) {
1234 : 0 : ret = hinic3_add_tcam_filter(dev, &tcam_key, &fdir_tcam_rule);
1235 [ # # ]: 0 : if (ret)
1236 : 0 : goto cfg_tcam_filter_err;
1237 : :
1238 : 0 : fdir_filter->tcam_index = (int)(fdir_tcam_rule.index);
1239 : : } else {
1240 : 0 : tcam_filter = hinic3_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key,
1241 : : HINIC3_ACTION_NOT_ADD,
1242 : 0 : fdir_filter->tcam_index);
1243 [ # # ]: 0 : if (tcam_filter == NULL) {
1244 : 0 : PMD_DRV_LOG(ERR, "Filter doesn't exist.");
1245 : 0 : return -ENOENT;
1246 : : }
1247 : 0 : PMD_DRV_LOG(INFO, "begin to del tcam filter");
1248 : 0 : ret = hinic3_del_tcam_filter(dev, tcam_filter);
1249 [ # # ]: 0 : if (ret)
1250 : 0 : goto cfg_tcam_filter_err;
1251 : : }
1252 : :
1253 : : return 0;
1254 : :
1255 : : cfg_tcam_filter_err:
1256 : :
1257 : : return ret;
1258 : : }
1259 : :
1260 : : /**
1261 : : * Enable or disable the TCAM filter for the receive queue.
1262 : : *
1263 : : * @param[in] dev
1264 : : * Pointer to ethernet device structure.
1265 : : * @param[in] able
1266 : : * Flag to enable or disable the filter.
1267 : : * @return
1268 : : * 0 on success, non-zero on failure.
1269 : : */
1270 : : int
1271 : 0 : hinic3_enable_rxq_fdir_filter(struct rte_eth_dev *dev, uint32_t queue_id, uint32_t able)
1272 : : {
1273 : : struct hinic3_tcam_info *tcam_info =
1274 [ # # ]: 0 : HINIC3_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private);
1275 : : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1276 : : struct hinic3_tcam_filter *it;
1277 : : struct hinic3_tcam_cfg_rule fdir_tcam_rule;
1278 : : int ret;
1279 : : uint32_t queue_res;
1280 : : uint16_t index;
1281 : :
1282 : : memset(&fdir_tcam_rule, 0, sizeof(struct hinic3_tcam_cfg_rule));
1283 : :
1284 [ # # ]: 0 : if (able) {
1285 [ # # ]: 0 : TAILQ_FOREACH(it, &tcam_info->tcam_list, entries) {
1286 [ # # ]: 0 : if (queue_id == it->queue) {
1287 : 0 : index = (uint16_t)(HINIC3_PKT_TCAM_DYNAMIC_INDEX_START
1288 : 0 : (it->dynamic_block_id) + it->index);
1289 : :
1290 : : /*
1291 : : * When the rxq is start, find invalid rxq_id
1292 : : * and delete the fdir rule from the tcam.
1293 : : */
1294 : 0 : ret = hinic3_del_tcam_rule(nic_dev->hwdev,
1295 : : index,
1296 : : TCAM_RULE_FDIR_TYPE);
1297 [ # # ]: 0 : if (ret) {
1298 : 0 : PMD_DRV_LOG(ERR, "del invalid tcam rule failed!");
1299 : 0 : return -EFAULT;
1300 : : }
1301 : :
1302 : 0 : fdir_tcam_rule.index = index;
1303 : 0 : fdir_tcam_rule.data.qid = queue_id;
1304 : 0 : tcam_key_calculate(&it->tcam_key,
1305 : : &fdir_tcam_rule);
1306 : :
1307 : : /* To enable a rule, add a rule. */
1308 : 0 : ret = hinic3_add_tcam_rule(nic_dev->hwdev,
1309 : : &fdir_tcam_rule,
1310 : : TCAM_RULE_FDIR_TYPE);
1311 [ # # ]: 0 : if (ret) {
1312 : 0 : PMD_DRV_LOG(ERR, "add correct tcam rule failed!");
1313 : 0 : return -EFAULT;
1314 : : }
1315 : : }
1316 : : }
1317 : : } else {
1318 : 0 : queue_res = HINIC3_INVALID_QID_BASE | queue_id;
1319 : :
1320 [ # # ]: 0 : TAILQ_FOREACH(it, &tcam_info->tcam_list, entries) {
1321 [ # # ]: 0 : if (queue_id == it->queue) {
1322 : 0 : index = (uint16_t)(HINIC3_PKT_TCAM_DYNAMIC_INDEX_START
1323 : 0 : (it->dynamic_block_id) + it->index);
1324 : :
1325 : : /*
1326 : : * When the rxq is stop, delete the fdir rule
1327 : : * from the tcam and add the correct fdir rule
1328 : : * from the tcam.
1329 : : */
1330 : 0 : ret = hinic3_del_tcam_rule(nic_dev->hwdev,
1331 : : index,
1332 : : TCAM_RULE_FDIR_TYPE);
1333 [ # # ]: 0 : if (ret) {
1334 : 0 : PMD_DRV_LOG(ERR, "del correct tcam rule failed!");
1335 : 0 : return -EFAULT;
1336 : : }
1337 : :
1338 : 0 : fdir_tcam_rule.index = index;
1339 : 0 : fdir_tcam_rule.data.qid = queue_res;
1340 : 0 : tcam_key_calculate(&it->tcam_key,
1341 : : &fdir_tcam_rule);
1342 : :
1343 : : /* Add the correct fdir rule from the tcam. */
1344 : 0 : ret = hinic3_add_tcam_rule(nic_dev->hwdev,
1345 : : &fdir_tcam_rule,
1346 : : TCAM_RULE_FDIR_TYPE);
1347 [ # # ]: 0 : if (ret) {
1348 : 0 : PMD_DRV_LOG(ERR, "add invalid tcam rule failed!");
1349 : 0 : return -EFAULT;
1350 : : }
1351 : : }
1352 : : }
1353 : : }
1354 : :
1355 : : return ret;
1356 : : }
1357 : :
1358 : : void
1359 : 0 : hinic3_free_fdir_filter(struct rte_eth_dev *dev)
1360 : : {
1361 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1362 : :
1363 : 0 : hinic3_set_fdir_tcam_rule_filter(nic_dev->hwdev, false);
1364 : :
1365 : 0 : hinic3_flush_tcam_rule(nic_dev->hwdev);
1366 : 0 : }
1367 : :
1368 : : static int
1369 : 0 : hinic3_flow_set_arp_filter(struct rte_eth_dev *dev,
1370 : : struct hinic3_ethertype_filter *ethertype_filter,
1371 : : bool add)
1372 : : {
1373 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1374 : : int ret;
1375 : :
1376 : : /* Setting the ARP Filter. */
1377 : 0 : ret = hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1378 : : HINIC3_PKT_TYPE_ARP,
1379 : : ethertype_filter, add);
1380 [ # # ]: 0 : if (ret) {
1381 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s fdir ethertype rule failed, err: %d",
1382 : : add ? "Add" : "Del", ret);
1383 : 0 : return ret;
1384 : : }
1385 : :
1386 : : /* Setting the ARP Request Filter. */
1387 : 0 : ret = hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1388 : : HINIC3_PKT_TYPE_ARP_REQ,
1389 : : ethertype_filter, add);
1390 [ # # ]: 0 : if (ret) {
1391 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s arp request rule failed, err: %d",
1392 : : add ? "Add" : "Del", ret);
1393 : 0 : goto set_arp_req_failed;
1394 : : }
1395 : :
1396 : : /* Setting the ARP Response Filter. */
1397 : 0 : ret = hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1398 : : HINIC3_PKT_TYPE_ARP_REP,
1399 : : ethertype_filter, add);
1400 [ # # ]: 0 : if (ret) {
1401 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s arp response rule failed, err: %d",
1402 : : add ? "Add" : "Del", ret);
1403 : 0 : goto set_arp_rep_failed;
1404 : : }
1405 : :
1406 : : return 0;
1407 : :
1408 : : set_arp_rep_failed:
1409 : 0 : hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1410 : : HINIC3_PKT_TYPE_ARP_REQ,
1411 : 0 : ethertype_filter, !add);
1412 : :
1413 : 0 : set_arp_req_failed:
1414 : 0 : hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1415 : : HINIC3_PKT_TYPE_ARP,
1416 : 0 : ethertype_filter, !add);
1417 : :
1418 : 0 : return ret;
1419 : : }
1420 : :
1421 : : static int
1422 : 0 : hinic3_flow_set_slow_filter(struct rte_eth_dev *dev,
1423 : : struct hinic3_ethertype_filter *ethertype_filter,
1424 : : bool add)
1425 : : {
1426 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1427 : : int ret;
1428 : :
1429 : : /* Setting the LACP Filter. */
1430 : 0 : ret = hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1431 : : HINIC3_PKT_TYPE_LACP,
1432 : : ethertype_filter, add);
1433 [ # # ]: 0 : if (ret) {
1434 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s lacp fdir rule failed, err: %d",
1435 : : add ? "Add" : "Del", ret);
1436 : 0 : return ret;
1437 : : }
1438 : :
1439 : : /* Setting the OAM Filter. */
1440 : 0 : ret = hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1441 : : HINIC3_PKT_TYPE_OAM,
1442 : : ethertype_filter, add);
1443 [ # # ]: 0 : if (ret) {
1444 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s oam rule failed, err: %d",
1445 : : add ? "Add" : "Del", ret);
1446 : 0 : goto set_arp_oam_failed;
1447 : : }
1448 : :
1449 : : return 0;
1450 : :
1451 : : set_arp_oam_failed:
1452 : 0 : hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1453 : : HINIC3_PKT_TYPE_LACP,
1454 : 0 : ethertype_filter, !add);
1455 : :
1456 : 0 : return ret;
1457 : : }
1458 : :
1459 : : static int
1460 : 0 : hinic3_flow_set_lldp_filter(struct rte_eth_dev *dev,
1461 : : struct hinic3_ethertype_filter *ethertype_filter,
1462 : : bool add)
1463 : : {
1464 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1465 : : int ret;
1466 : :
1467 : : /* Setting the LLDP Filter. */
1468 : 0 : ret = hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1469 : : HINIC3_PKT_TYPE_LLDP,
1470 : : ethertype_filter, add);
1471 [ # # ]: 0 : if (ret) {
1472 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s lldp fdir rule failed, err: %d",
1473 : : add ? "Add" : "Del", ret);
1474 : 0 : return ret;
1475 : : }
1476 : :
1477 : : /* Setting the CDCP Filter. */
1478 : 0 : ret = hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1479 : : HINIC3_PKT_TYPE_CDCP,
1480 : : ethertype_filter, add);
1481 [ # # ]: 0 : if (ret) {
1482 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s cdcp fdir rule failed, err: %d",
1483 : : add ? "Add" : "Del", ret);
1484 : 0 : goto set_arp_cdcp_failed;
1485 : : }
1486 : :
1487 : : return 0;
1488 : :
1489 : : set_arp_cdcp_failed:
1490 : 0 : hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1491 : : HINIC3_PKT_TYPE_LLDP,
1492 : 0 : ethertype_filter, !add);
1493 : :
1494 : 0 : return ret;
1495 : : }
1496 : :
1497 : : static int
1498 : 0 : hinic3_flow_add_del_ethertype_filter_rule(struct rte_eth_dev *dev,
1499 : : struct hinic3_ethertype_filter *ethertype_filter,
1500 : : bool add)
1501 : : {
1502 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1503 : : struct hinic3_ethertype_filter_list *ethertype_list =
1504 : : &nic_dev->filter_ethertype_list;
1505 : :
1506 : : /* Check whether the transferred rule exists. */
1507 [ # # ]: 0 : if (hinic3_ethertype_filter_lookup(ethertype_list,
1508 : 0 : ethertype_filter->ether_type)) {
1509 [ # # ]: 0 : if (add) {
1510 : 0 : PMD_DRV_LOG(ERR,
1511 : : "The rule already exists, can not to be added");
1512 : 0 : return -EPERM;
1513 : : }
1514 : : } else {
1515 [ # # ]: 0 : if (!add) {
1516 : 0 : PMD_DRV_LOG(ERR,
1517 : : "The rule not exists, can not to be delete");
1518 : 0 : return -EPERM;
1519 : : }
1520 : : }
1521 : : /* Create a filter based on the protocol type. */
1522 [ # # # # : 0 : switch (ethertype_filter->ether_type) {
# # # ]
1523 : 0 : case RTE_ETHER_TYPE_ARP:
1524 : 0 : return hinic3_flow_set_arp_filter(dev, ethertype_filter, add);
1525 : 0 : case RTE_ETHER_TYPE_RARP:
1526 : 0 : return hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1527 : : HINIC3_PKT_TYPE_RARP, ethertype_filter, add);
1528 : :
1529 : 0 : case RTE_ETHER_TYPE_SLOW:
1530 : 0 : return hinic3_flow_set_slow_filter(dev, ethertype_filter, add);
1531 : :
1532 : 0 : case RTE_ETHER_TYPE_LLDP:
1533 : 0 : return hinic3_flow_set_lldp_filter(dev, ethertype_filter, add);
1534 : :
1535 : 0 : case RTE_ETHER_TYPE_CNM:
1536 : 0 : return hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1537 : : HINIC3_PKT_TYPE_CNM, ethertype_filter, add);
1538 : :
1539 : 0 : case RTE_ETHER_TYPE_ECP:
1540 : 0 : return hinic3_set_fdir_ethertype_filter(nic_dev->hwdev,
1541 : : HINIC3_PKT_TYPE_ECP, ethertype_filter, add);
1542 : :
1543 : 0 : default:
1544 : 0 : PMD_DRV_LOG(ERR, "Unknown ethertype %d queue_id %d",
1545 : : ethertype_filter->ether_type,
1546 : : ethertype_filter->queue);
1547 : 0 : return -EPERM;
1548 : : }
1549 : : }
1550 : :
1551 : : static int
1552 : 0 : hinic3_flow_ethertype_rule_nums(struct hinic3_ethertype_filter *ethertype_filter)
1553 : : {
1554 [ # # # # : 0 : switch (ethertype_filter->ether_type) {
# # # ]
1555 : : case RTE_ETHER_TYPE_ARP:
1556 : : return HINIC3_ARP_RULE_NUM;
1557 : 0 : case RTE_ETHER_TYPE_RARP:
1558 : 0 : return HINIC3_RARP_RULE_NUM;
1559 : 0 : case RTE_ETHER_TYPE_SLOW:
1560 : 0 : return HINIC3_SLOW_RULE_NUM;
1561 : 0 : case RTE_ETHER_TYPE_LLDP:
1562 : 0 : return HINIC3_LLDP_RULE_NUM;
1563 : 0 : case RTE_ETHER_TYPE_CNM:
1564 : 0 : return HINIC3_CNM_RULE_NUM;
1565 : 0 : case RTE_ETHER_TYPE_ECP:
1566 : 0 : return HINIC3_ECP_RULE_NUM;
1567 : :
1568 : 0 : default:
1569 : 0 : PMD_DRV_LOG(ERR, "Unknown ethertype %d",
1570 : : ethertype_filter->ether_type);
1571 : 0 : return 0;
1572 : : }
1573 : : }
1574 : :
1575 : : /**
1576 : : * Add or delete an Ethernet type filter rule.
1577 : : *
1578 : : * @param[in] dev
1579 : : * Pointer to ethernet device structure.
1580 : : * @param[in] ethertype_filter
1581 : : * Pointer to ethertype filter.
1582 : : * @param[in] add
1583 : : * This is a Boolean value (of the bool type) indicating whether the action to
1584 : : * be performed is to add (true) or delete (false) the Ethernet type filter
1585 : : * rule.
1586 : : * @return
1587 : : * 0 on success, non-zero on failure.
1588 : : */
1589 : : int
1590 : 0 : hinic3_flow_add_del_ethertype_filter(struct rte_eth_dev *dev,
1591 : : struct hinic3_ethertype_filter *ethertype_filter,
1592 : : bool add)
1593 : : {
1594 : : /* Get dev private info. */
1595 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1596 : : int ret;
1597 : : /* Add or remove an Ethernet type filter rule. */
1598 : 0 : ret = hinic3_flow_add_del_ethertype_filter_rule(dev, ethertype_filter, add);
1599 : :
1600 [ # # ]: 0 : if (ret) {
1601 [ # # ]: 0 : PMD_DRV_LOG(ERR, "%s fdir ethertype rule failed, err: %d",
1602 : : add ? "Add" : "Del", ret);
1603 : 0 : return ret;
1604 : : }
1605 : : /*
1606 : : * If a rule is added and the rule is the first rule, rule filtering is
1607 : : * enabled. If a rule is deleted and the rule is the last one, rule
1608 : : * filtering is disabled.
1609 : : */
1610 [ # # ]: 0 : if (add) {
1611 [ # # ]: 0 : if (nic_dev->ethertype_rule_nums == 0) {
1612 : 0 : ret = hinic3_set_fdir_tcam_rule_filter(nic_dev->hwdev, true);
1613 [ # # ]: 0 : if (ret) {
1614 : 0 : PMD_DRV_LOG(ERR,
1615 : : "enable fdir rule failed, err: %d",
1616 : : ret);
1617 : 0 : goto enable_fdir_failed;
1618 : : }
1619 : : }
1620 : 0 : nic_dev->ethertype_rule_nums =
1621 : 0 : nic_dev->ethertype_rule_nums +
1622 : 0 : hinic3_flow_ethertype_rule_nums(ethertype_filter);
1623 : : } else {
1624 : 0 : nic_dev->ethertype_rule_nums =
1625 : 0 : nic_dev->ethertype_rule_nums -
1626 : 0 : hinic3_flow_ethertype_rule_nums(ethertype_filter);
1627 : :
1628 [ # # ]: 0 : if (!(nic_dev->ethertype_rule_nums + nic_dev->tcam_rule_nums)) {
1629 : 0 : ret = hinic3_set_fdir_tcam_rule_filter(nic_dev->hwdev, false);
1630 [ # # ]: 0 : if (ret) {
1631 : 0 : PMD_DRV_LOG(ERR,
1632 : : "disable fdir rule failed, err: %d",
1633 : : ret);
1634 : : }
1635 : : }
1636 : : }
1637 : :
1638 : : return 0;
1639 : :
1640 : : enable_fdir_failed:
1641 : 0 : hinic3_flow_add_del_ethertype_filter_rule(dev, ethertype_filter, !add);
1642 : 0 : return ret;
1643 : : }
|