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 <rte_flow_driver.h>
6 : :
7 : : #include "base/hinic3_compat.h"
8 : : #include "base/hinic3_hwdev.h"
9 : : #include "base/hinic3_nic_cfg.h"
10 : : #include "hinic3_ethdev.h"
11 : : #include "hinic3_flow.h"
12 : :
13 : : #define HINIC3_UINT8_MAX 0xff
14 : :
15 : : typedef int (*hinic3_parse_filter_t)(struct rte_eth_dev *dev,
16 : : const struct rte_flow_attr *attr,
17 : : const struct rte_flow_item pattern[],
18 : : const struct rte_flow_action actions[],
19 : : struct rte_flow_error *error,
20 : : struct hinic3_filter_t *filter);
21 : :
22 : : /* Indicate valid filter mode . */
23 : : struct hinic3_valid_pattern {
24 : : enum rte_flow_item_type *items;
25 : : hinic3_parse_filter_t parse_filter;
26 : : };
27 : :
28 : : static int hinic3_flow_parse_fdir_filter(struct rte_eth_dev *dev,
29 : : const struct rte_flow_attr *attr,
30 : : const struct rte_flow_item pattern[],
31 : : const struct rte_flow_action actions[],
32 : : struct rte_flow_error *error,
33 : : struct hinic3_filter_t *filter);
34 : :
35 : : static int hinic3_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
36 : : const struct rte_flow_attr *attr,
37 : : const struct rte_flow_item pattern[],
38 : : const struct rte_flow_action actions[],
39 : : struct rte_flow_error *error,
40 : : struct hinic3_filter_t *filter);
41 : :
42 : : static int hinic3_flow_parse_fdir_vxlan_filter(struct rte_eth_dev *dev,
43 : : const struct rte_flow_attr *attr,
44 : : const struct rte_flow_item pattern[],
45 : : const struct rte_flow_action actions[],
46 : : struct rte_flow_error *error,
47 : : struct hinic3_filter_t *filter);
48 : :
49 : : /*
50 : : * Define a supported pattern array, including the matching patterns of
51 : : * various network protocols and corresponding parsing functions.
52 : : */
53 : : static const struct hinic3_valid_pattern hinic3_supported_patterns[] = {
54 : : /* Support ethertype. */
55 : : {pattern_ethertype, hinic3_flow_parse_ethertype_filter},
56 : : /* Support ipv4 but not tunnel, and any field can be masked. */
57 : : {pattern_ipv4, hinic3_flow_parse_fdir_filter},
58 : : {pattern_ipv4_any, hinic3_flow_parse_fdir_filter},
59 : : /* Support ipv4 + l4 but not tunnel, and any field can be masked. */
60 : : {pattern_ipv4_udp, hinic3_flow_parse_fdir_filter},
61 : : {pattern_ipv4_tcp, hinic3_flow_parse_fdir_filter},
62 : : /* Support ipv4 + icmp not tunnel, and any field can be masked. */
63 : : {pattern_ipv4_icmp, hinic3_flow_parse_fdir_filter},
64 : :
65 : : /* Support ipv4 + l4 but not tunnel, and any field can be masked. */
66 : : {pattern_ethertype_udp, hinic3_flow_parse_fdir_filter},
67 : : {pattern_ethertype_tcp, hinic3_flow_parse_fdir_filter},
68 : :
69 : : /* Support ipv4 + vxlan + any, and any field can be masked. */
70 : : {pattern_ipv4_vxlan, hinic3_flow_parse_fdir_vxlan_filter},
71 : : /* Support ipv4 + vxlan + ipv4, and any field can be masked. */
72 : : {pattern_ipv4_vxlan_ipv4, hinic3_flow_parse_fdir_vxlan_filter},
73 : : /* Support ipv4 + vxlan + ipv4 + l4, and any field can be masked. */
74 : : {pattern_ipv4_vxlan_ipv4_tcp, hinic3_flow_parse_fdir_vxlan_filter},
75 : : {pattern_ipv4_vxlan_ipv4_udp, hinic3_flow_parse_fdir_vxlan_filter},
76 : : /* Support ipv4 + vxlan + ipv6, and any field can be masked. */
77 : : {pattern_ipv4_vxlan_ipv6, hinic3_flow_parse_fdir_vxlan_filter},
78 : : /* Support ipv4 + vxlan + ipv6 + l4, and any field can be masked. */
79 : : {pattern_ipv4_vxlan_ipv6_tcp, hinic3_flow_parse_fdir_vxlan_filter},
80 : : {pattern_ipv4_vxlan_ipv6_udp, hinic3_flow_parse_fdir_vxlan_filter},
81 : : /* Support ipv4 + vxlan + l4, and any field can be masked. */
82 : : {pattern_ipv4_vxlan_tcp, hinic3_flow_parse_fdir_vxlan_filter},
83 : : {pattern_ipv4_vxlan_udp, hinic3_flow_parse_fdir_vxlan_filter},
84 : : {pattern_ipv4_vxlan_any, hinic3_flow_parse_fdir_vxlan_filter},
85 : :
86 : : /* Support ipv6 but not tunnel, and any field can be masked. */
87 : : {pattern_ipv6, hinic3_flow_parse_fdir_filter},
88 : : /* Support ipv6 + l4 but not tunnel, and any field can be masked. */
89 : : {pattern_ipv6_udp, hinic3_flow_parse_fdir_filter},
90 : : {pattern_ipv6_tcp, hinic3_flow_parse_fdir_filter},
91 : :
92 : : /* Support ipv6 + vxlan + any, and any field can be masked. */
93 : : {pattern_ipv6_vxlan, hinic3_flow_parse_fdir_vxlan_filter},
94 : : {pattern_ipv6_vxlan_any, hinic3_flow_parse_fdir_vxlan_filter},
95 : :
96 : : /* Support ipv6 + vxlan + l4, and any field can be masked. */
97 : : {pattern_ipv6_vxlan_tcp, hinic3_flow_parse_fdir_vxlan_filter},
98 : : {pattern_ipv6_vxlan_udp, hinic3_flow_parse_fdir_vxlan_filter},
99 : :
100 : : };
101 : :
102 : : static inline void
103 : : net_addr_to_host(uint32_t *dst, const uint32_t *src, size_t len)
104 : : {
105 : : size_t i;
106 [ # # # # : 0 : for (i = 0; i < len; i++)
# # # # #
# # # # #
# # # # #
# # # #
# ]
107 [ # # # # : 0 : dst[i] = rte_be_to_cpu_32(src[i]);
# # # # #
# # # # #
# # # # #
# # # #
# ]
108 : : }
109 : :
110 : : static bool
111 : 0 : hinic3_match_pattern(enum rte_flow_item_type *item_array,
112 : : const struct rte_flow_item *pattern)
113 : : {
114 : : const struct rte_flow_item *item = pattern;
115 : :
116 : : /* skip the first void item. */
117 [ # # ]: 0 : while (item->type == RTE_FLOW_ITEM_TYPE_VOID)
118 : 0 : item++;
119 : :
120 : : /* Find no void item. */
121 [ # # ]: 0 : while (((*item_array == item->type) &&
122 [ # # # # ]: 0 : (*item_array != RTE_FLOW_ITEM_TYPE_END)) ||
123 : : (item->type == RTE_FLOW_ITEM_TYPE_VOID)) {
124 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_VOID) {
125 : 0 : item++;
126 : : } else {
127 : 0 : item_array++;
128 : 0 : item++;
129 : : }
130 : : }
131 : :
132 [ # # # # ]: 0 : return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
133 : : item->type == RTE_FLOW_ITEM_TYPE_END);
134 : : }
135 : :
136 : : /**
137 : : * Find matching parsing filter functions.
138 : : *
139 : : * @param[in] pattern
140 : : * Pattern to match.
141 : : * @return
142 : : * Matched resolution filter. If no resolution filter is found, return NULL.
143 : : */
144 : : static hinic3_parse_filter_t
145 : 0 : hinic3_find_parse_filter_func(const struct rte_flow_item *pattern)
146 : : {
147 : : hinic3_parse_filter_t parse_filter = NULL;
148 : : uint8_t i;
149 : : /* Traverse all supported patterns. */
150 [ # # ]: 0 : for (i = 0; i < RTE_DIM(hinic3_supported_patterns); i++) {
151 [ # # ]: 0 : if (hinic3_match_pattern(hinic3_supported_patterns[i].items, pattern)) {
152 : 0 : parse_filter =
153 : : hinic3_supported_patterns[i].parse_filter;
154 : 0 : break;
155 : : }
156 : : }
157 : :
158 : 0 : return parse_filter;
159 : : }
160 : :
161 : : /**
162 : : * Action for parsing and processing Ethernet types.
163 : : *
164 : : * @param[in] dev
165 : : * Pointer to ethernet device structure.
166 : : * @param[in] actions
167 : : * Indicates the action to be taken on the matched traffic.
168 : : * @param[out] error
169 : : * Structure that contains error information, such as error code and error
170 : : * description.
171 : : * @param[out] filter
172 : : * Filter information, its used to store and manipulate packet filtering rules.
173 : : * @return
174 : : * 0 on success, non-zero on failure.
175 : : */
176 : : static int
177 : 0 : hinic3_flow_parse_action(struct rte_eth_dev *dev,
178 : : const struct rte_flow_action *actions,
179 : : struct rte_flow_error *error,
180 : : struct hinic3_filter_t *filter)
181 : : {
182 : : const struct rte_flow_action_queue *act_q;
183 : : const struct rte_flow_action *act = actions;
184 : :
185 : : /* skip the first void item. */
186 [ # # ]: 0 : while (act->type == RTE_FLOW_ACTION_TYPE_VOID)
187 : 0 : act++;
188 : :
189 [ # # ]: 0 : switch (act->type) {
190 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
191 : 0 : act_q = (const struct rte_flow_action_queue *)act->conf;
192 : 0 : filter->fdir_filter.rq_index = act_q->index;
193 [ # # ]: 0 : if (filter->fdir_filter.rq_index >= dev->data->nb_rx_queues) {
194 : 0 : rte_flow_error_set(error, EINVAL,
195 : : RTE_FLOW_ERROR_TYPE_ACTION, act,
196 : : "Invalid action param.");
197 : 0 : return -rte_errno;
198 : : }
199 : : break;
200 : 0 : default:
201 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
202 : : act, "Invalid action type.");
203 : 0 : return -rte_errno;
204 : : }
205 : :
206 : : return 0;
207 : : }
208 : :
209 : : int
210 : 0 : hinic3_flow_parse_attr(const struct rte_flow_attr *attr,
211 : : struct rte_flow_error *error)
212 : : {
213 : : /* Not supported. */
214 [ # # # # : 0 : if (!attr->ingress || attr->egress || attr->priority || attr->group) {
# # ]
215 : 0 : rte_flow_error_set(error, EINVAL,
216 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, attr,
217 : : "Only support ingress.");
218 : 0 : return -rte_errno;
219 : : }
220 : :
221 : : return 0;
222 : : }
223 : :
224 : : static int
225 : 0 : hinic3_flow_fdir_ipv4(const struct rte_flow_item *flow_item,
226 : : struct hinic3_filter_t *filter,
227 : : struct rte_flow_error *error)
228 : : {
229 : : const struct rte_flow_item_ipv4 *spec_ipv4, *mask_ipv4;
230 : :
231 : 0 : mask_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->mask;
232 : 0 : spec_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->spec;
233 [ # # ]: 0 : if (!mask_ipv4 || !spec_ipv4) {
234 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
235 : : flow_item,
236 : : "Invalid fdir filter ipv4 mask or spec");
237 : 0 : return -rte_errno;
238 : : }
239 : :
240 : : /*
241 : : * Only support src address , dst addresses, proto,
242 : : * others should be masked.
243 : : */
244 [ # # ]: 0 : if (mask_ipv4->hdr.version_ihl || mask_ipv4->hdr.type_of_service ||
245 [ # # # # ]: 0 : mask_ipv4->hdr.total_length || mask_ipv4->hdr.packet_id ||
246 [ # # # # ]: 0 : mask_ipv4->hdr.fragment_offset || mask_ipv4->hdr.time_to_live ||
247 [ # # ]: 0 : mask_ipv4->hdr.hdr_checksum) {
248 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
249 : : flow_item,
250 : : "Not supported by fdir filter, ipv4 only support src ip, dst ip, proto");
251 : 0 : return -rte_errno;
252 : : }
253 : :
254 : : /* Set the filter information. */
255 : 0 : filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
256 : 0 : filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
257 : 0 : filter->fdir_filter.key_mask.ipv4.src_ip =
258 [ # # ]: 0 : rte_be_to_cpu_32(mask_ipv4->hdr.src_addr);
259 : 0 : filter->fdir_filter.key_spec.ipv4.src_ip =
260 [ # # ]: 0 : rte_be_to_cpu_32(spec_ipv4->hdr.src_addr);
261 : 0 : filter->fdir_filter.key_mask.ipv4.dst_ip =
262 [ # # ]: 0 : rte_be_to_cpu_32(mask_ipv4->hdr.dst_addr);
263 : 0 : filter->fdir_filter.key_spec.ipv4.dst_ip =
264 [ # # ]: 0 : rte_be_to_cpu_32(spec_ipv4->hdr.dst_addr);
265 : 0 : filter->fdir_filter.key_mask.proto = mask_ipv4->hdr.next_proto_id;
266 : 0 : filter->fdir_filter.key_spec.proto = spec_ipv4->hdr.next_proto_id;
267 : :
268 : 0 : return 0;
269 : : }
270 : :
271 : : static int
272 : 0 : hinic3_flow_fdir_ipv6(const struct rte_flow_item *flow_item,
273 : : struct hinic3_filter_t *filter,
274 : : struct rte_flow_error *error)
275 : : {
276 : : const struct rte_flow_item_ipv6 *spec_ipv6, *mask_ipv6;
277 : :
278 : 0 : mask_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->mask;
279 : 0 : spec_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->spec;
280 [ # # ]: 0 : if (!mask_ipv6 || !spec_ipv6) {
281 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
282 : : flow_item,
283 : : "Invalid fdir filter ipv6 mask or spec");
284 : 0 : return -rte_errno;
285 : : }
286 : :
287 : : /* Only support dst addresses, src addresses, proto. */
288 [ # # # # ]: 0 : if (mask_ipv6->hdr.vtc_flow || mask_ipv6->hdr.payload_len ||
289 : : mask_ipv6->hdr.hop_limits) {
290 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
291 : : flow_item,
292 : : "Not supported by fdir filter, ipv6 only support src ip, dst ip, proto");
293 : 0 : return -rte_errno;
294 : : }
295 : :
296 : : /* Set the filter information. */
297 : 0 : filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
298 : 0 : filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
299 : 0 : net_addr_to_host(filter->fdir_filter.key_mask.ipv6.src_ip,
300 : 0 : (const uint32_t *)mask_ipv6->hdr.src_addr.a, 4);
301 : 0 : net_addr_to_host(filter->fdir_filter.key_spec.ipv6.src_ip,
302 : 0 : (const uint32_t *)spec_ipv6->hdr.src_addr.a, 4);
303 : 0 : net_addr_to_host(filter->fdir_filter.key_mask.ipv6.dst_ip,
304 : 0 : (const uint32_t *)mask_ipv6->hdr.dst_addr.a, 4);
305 : 0 : net_addr_to_host(filter->fdir_filter.key_spec.ipv6.dst_ip,
306 : 0 : (const uint32_t *)spec_ipv6->hdr.dst_addr.a, 4);
307 : 0 : filter->fdir_filter.key_mask.proto = mask_ipv6->hdr.proto;
308 : 0 : filter->fdir_filter.key_spec.proto = spec_ipv6->hdr.proto;
309 : :
310 : 0 : return 0;
311 : : }
312 : :
313 : : static int
314 : 0 : hinic3_flow_fdir_tcp(const struct rte_flow_item *flow_item,
315 : : struct hinic3_filter_t *filter,
316 : : struct rte_flow_error *error)
317 : : {
318 : : const struct rte_flow_item_tcp *spec_tcp, *mask_tcp;
319 : :
320 : 0 : mask_tcp = (const struct rte_flow_item_tcp *)flow_item->mask;
321 : 0 : spec_tcp = (const struct rte_flow_item_tcp *)flow_item->spec;
322 : :
323 : 0 : filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
324 : 0 : filter->fdir_filter.key_spec.proto = IPPROTO_TCP;
325 : :
326 [ # # ]: 0 : if (!mask_tcp && !spec_tcp)
327 : : return 0;
328 : :
329 [ # # ]: 0 : if (!mask_tcp || !spec_tcp) {
330 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
331 : : flow_item,
332 : : "Invalid fdir filter tcp mask or spec");
333 : 0 : return -rte_errno;
334 : : }
335 : :
336 : : /* Only support src, dst ports, others should be masked. */
337 [ # # # # ]: 0 : if (mask_tcp->hdr.sent_seq || mask_tcp->hdr.recv_ack ||
338 [ # # # # ]: 0 : mask_tcp->hdr.data_off || mask_tcp->hdr.rx_win ||
339 [ # # # # ]: 0 : mask_tcp->hdr.tcp_flags || mask_tcp->hdr.cksum ||
340 [ # # ]: 0 : mask_tcp->hdr.tcp_urp) {
341 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
342 : : flow_item,
343 : : "Not supported by fdir filter, tcp only support src port, dst port");
344 : 0 : return -rte_errno;
345 : : }
346 : :
347 : : /* Set the filter information. */
348 : 0 : filter->fdir_filter.key_mask.src_port =
349 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.src_port);
350 : 0 : filter->fdir_filter.key_spec.src_port =
351 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.src_port);
352 : 0 : filter->fdir_filter.key_mask.dst_port =
353 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.dst_port);
354 : 0 : filter->fdir_filter.key_spec.dst_port =
355 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.dst_port);
356 : :
357 : 0 : return 0;
358 : : }
359 : :
360 : : static int
361 : 0 : hinic3_flow_fdir_udp(const struct rte_flow_item *flow_item,
362 : : struct hinic3_filter_t *filter,
363 : : struct rte_flow_error *error)
364 : : {
365 : : const struct rte_flow_item_udp *spec_udp, *mask_udp;
366 : :
367 : 0 : mask_udp = (const struct rte_flow_item_udp *)flow_item->mask;
368 : 0 : spec_udp = (const struct rte_flow_item_udp *)flow_item->spec;
369 : :
370 : 0 : filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
371 : 0 : filter->fdir_filter.key_spec.proto = IPPROTO_UDP;
372 : :
373 [ # # ]: 0 : if (!mask_udp && !spec_udp)
374 : : return 0;
375 : :
376 [ # # ]: 0 : if (!mask_udp || !spec_udp) {
377 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
378 : : flow_item,
379 : : "Invalid fdir filter udp mask or spec");
380 : 0 : return -rte_errno;
381 : : }
382 : :
383 : : /* Set the filter information. */
384 : 0 : filter->fdir_filter.key_mask.src_port =
385 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.src_port);
386 : 0 : filter->fdir_filter.key_spec.src_port =
387 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.src_port);
388 : 0 : filter->fdir_filter.key_mask.dst_port =
389 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.dst_port);
390 : 0 : filter->fdir_filter.key_spec.dst_port =
391 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.dst_port);
392 : :
393 : 0 : return 0;
394 : : }
395 : :
396 : : /**
397 : : * Parse the pattern of network traffic and apply the parsing result to the
398 : : * traffic filter.
399 : : *
400 : : * @param[in] dev
401 : : * Pointer to ethernet device structure.
402 : : * @param[in] pattern
403 : : * Indicates the pattern or matching condition of a traffic rule.
404 : : * @param[out] error
405 : : * Structure that contains error information, such as error code and error
406 : : * description.
407 : : * @param[out] filter
408 : : * Filter information, Its used to store and manipulate packet filtering rules.
409 : : * @return
410 : : * 0 on success, non-zero on failure.
411 : : */
412 : : static int
413 : 0 : hinic3_flow_parse_fdir_pattern(__rte_unused struct rte_eth_dev *dev,
414 : : const struct rte_flow_item *pattern,
415 : : struct rte_flow_error *error,
416 : : struct hinic3_filter_t *filter)
417 : : {
418 : : const struct rte_flow_item *flow_item = pattern;
419 : : enum rte_flow_item_type type;
420 : : int err;
421 : :
422 : 0 : filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_ANY;
423 : : /* Traverse all modes until RTE_FLOW_ITEM_TYPE_END is reached. */
424 [ # # ]: 0 : for (; flow_item->type != RTE_FLOW_ITEM_TYPE_END; flow_item++) {
425 [ # # ]: 0 : if (flow_item->last) {
426 : 0 : rte_flow_error_set(error, EINVAL,
427 : : RTE_FLOW_ERROR_TYPE_ITEM,
428 : : flow_item, "Not support range");
429 : 0 : return -rte_errno;
430 : : }
431 : : type = flow_item->type;
432 [ # # # # : 0 : switch (type) {
# # ]
433 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
434 [ # # # # ]: 0 : if (flow_item->spec || flow_item->mask) {
435 : 0 : rte_flow_error_set(error, EINVAL,
436 : : RTE_FLOW_ERROR_TYPE_ITEM,
437 : : flow_item,
438 : : "Not supported by fdir filter, not support mac");
439 : 0 : return -rte_errno;
440 : : }
441 : : break;
442 : :
443 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
444 : 0 : err = hinic3_flow_fdir_ipv4(flow_item, filter, error);
445 [ # # ]: 0 : if (err)
446 : 0 : return -rte_errno;
447 : : break;
448 : :
449 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
450 : 0 : err = hinic3_flow_fdir_ipv6(flow_item, filter, error);
451 [ # # ]: 0 : if (err)
452 : 0 : return -rte_errno;
453 : : break;
454 : :
455 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
456 : 0 : err = hinic3_flow_fdir_tcp(flow_item, filter, error);
457 [ # # ]: 0 : if (err)
458 : 0 : return -rte_errno;
459 : : break;
460 : :
461 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
462 : 0 : err = hinic3_flow_fdir_udp(flow_item, filter, error);
463 [ # # ]: 0 : if (err)
464 : 0 : return -rte_errno;
465 : : break;
466 : :
467 : : default:
468 : : break;
469 : : }
470 : : }
471 : :
472 : : return 0;
473 : : }
474 : :
475 : : /**
476 : : * Resolve rules for network traffic filters.
477 : : *
478 : : * @param[in] dev
479 : : * Pointer to ethernet device structure.
480 : : * @param[in] attr
481 : : * Indicates the attribute of a flow rule.
482 : : * @param[in] pattern
483 : : * Indicates the pattern or matching condition of a traffic rule.
484 : : * @param[in] actions
485 : : * Indicates the action to be taken on the matched traffic.
486 : : * @param[out] error
487 : : * Structure that contains error information, such as error code and error
488 : : * description.
489 : : * @param[out] filter
490 : : * Filter information, Its used to store and manipulate packet filtering rules.
491 : : * @return
492 : : * 0 on success, non-zero on failure.
493 : : */
494 : : static int
495 : 0 : hinic3_flow_parse_fdir_filter(struct rte_eth_dev *dev,
496 : : const struct rte_flow_attr *attr,
497 : : const struct rte_flow_item pattern[],
498 : : const struct rte_flow_action actions[],
499 : : struct rte_flow_error *error,
500 : : struct hinic3_filter_t *filter)
501 : : {
502 : : int ret;
503 : :
504 : 0 : ret = hinic3_flow_parse_fdir_pattern(dev, pattern, error, filter);
505 [ # # ]: 0 : if (ret)
506 : : return ret;
507 : :
508 : 0 : ret = hinic3_flow_parse_action(dev, actions, error, filter);
509 [ # # ]: 0 : if (ret)
510 : : return ret;
511 : :
512 : 0 : ret = hinic3_flow_parse_attr(attr, error);
513 [ # # ]: 0 : if (ret)
514 : : return ret;
515 : :
516 : 0 : filter->filter_type = RTE_ETH_FILTER_FDIR;
517 : :
518 : 0 : return 0;
519 : : }
520 : :
521 : : /**
522 : : * Parse and process the actions of the Ethernet type.
523 : : *
524 : : * @param[in] dev
525 : : * Pointer to ethernet device structure.
526 : : * @param[in] actions
527 : : * Indicates the action to be taken on the matched traffic.
528 : : * @param[out] error
529 : : * Structure that contains error information, such as error code and error
530 : : * description.
531 : : * @param[out] filter
532 : : * Filter information, Its used to store and manipulate packet filtering rules.
533 : : * @return
534 : : * 0 on success, non-zero on failure.
535 : : */
536 : : static int
537 : 0 : hinic3_flow_parse_ethertype_action(struct rte_eth_dev *dev,
538 : : const struct rte_flow_action *actions,
539 : : struct rte_flow_error *error,
540 : : struct hinic3_filter_t *filter)
541 : : {
542 : : const struct rte_flow_action *act = actions;
543 : : const struct rte_flow_action_queue *act_q;
544 : :
545 : : /* Skip the firset void item. */
546 [ # # ]: 0 : while (act->type == RTE_FLOW_ACTION_TYPE_VOID)
547 : 0 : act++;
548 : :
549 [ # # ]: 0 : switch (act->type) {
550 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
551 : 0 : act_q = (const struct rte_flow_action_queue *)act->conf;
552 : 0 : filter->ethertype_filter.queue = act_q->index;
553 [ # # ]: 0 : if (filter->ethertype_filter.queue >= dev->data->nb_rx_queues) {
554 : 0 : rte_flow_error_set(error, EINVAL,
555 : : RTE_FLOW_ERROR_TYPE_ACTION, act,
556 : : "Invalid action param.");
557 : 0 : return -rte_errno;
558 : : }
559 : : break;
560 : :
561 : 0 : default:
562 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
563 : : act, "Invalid action type.");
564 : 0 : return -rte_errno;
565 : : }
566 : :
567 : : return 0;
568 : : }
569 : :
570 : : static int
571 : 0 : hinic3_flow_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
572 : : const struct rte_flow_item *pattern,
573 : : struct rte_flow_error *error,
574 : : struct hinic3_filter_t *filter)
575 : : {
576 : : const struct rte_flow_item_eth *ether_spec, *ether_mask;
577 : : const struct rte_flow_item *flow_item = pattern;
578 : : enum rte_flow_item_type type;
579 : :
580 : : /* Traverse all modes until RTE_FLOW_ITEM_TYPE_END is reached. */
581 [ # # ]: 0 : for (; flow_item->type != RTE_FLOW_ITEM_TYPE_END; flow_item++) {
582 [ # # ]: 0 : if (flow_item->last) {
583 : 0 : rte_flow_error_set(error, EINVAL,
584 : : RTE_FLOW_ERROR_TYPE_ITEM,
585 : : flow_item, "Not support range");
586 : 0 : return -rte_errno;
587 : : }
588 : : type = flow_item->type;
589 [ # # ]: 0 : switch (type) {
590 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
591 : : /* Obtaining Ethernet Specifications and Masks. */
592 : 0 : ether_spec = (const struct rte_flow_item_eth *)
593 : : flow_item->spec;
594 : 0 : ether_mask = (const struct rte_flow_item_eth *)
595 : : flow_item->mask;
596 [ # # ]: 0 : if (!ether_spec || !ether_mask) {
597 : 0 : rte_flow_error_set(error, EINVAL,
598 : : RTE_FLOW_ERROR_TYPE_ITEM,
599 : : flow_item,
600 : : "NULL ETH spec/mask");
601 : 0 : return -rte_errno;
602 : : }
603 : :
604 : : /*
605 : : * Mask bits of source MAC address must be full of 0.
606 : : * Mask bits of destination MAC address must be full 0.
607 : : * Filters traffic based on the type of Ethernet.
608 : : */
609 [ # # # # ]: 0 : if (!rte_is_zero_ether_addr(ðer_mask->src) ||
610 : : (!rte_is_zero_ether_addr(ðer_mask->dst))) {
611 : 0 : rte_flow_error_set(error, EINVAL,
612 : : RTE_FLOW_ERROR_TYPE_ITEM,
613 : : flow_item,
614 : : "Invalid ether address mask");
615 : 0 : return -rte_errno;
616 : : }
617 : :
618 [ # # ]: 0 : if ((ether_mask->type & UINT16_MAX) != UINT16_MAX) {
619 : 0 : rte_flow_error_set(error, EINVAL,
620 : : RTE_FLOW_ERROR_TYPE_ITEM,
621 : : flow_item,
622 : : "Invalid ethertype mask");
623 : 0 : return -rte_errno;
624 : : }
625 : :
626 [ # # ]: 0 : filter->ethertype_filter.ether_type =
627 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(ether_spec->type);
628 : :
629 : : switch (filter->ethertype_filter.ether_type) {
630 : : case RTE_ETHER_TYPE_SLOW:
631 : : break;
632 : :
633 : : case RTE_ETHER_TYPE_ARP:
634 : : break;
635 : :
636 : : case RTE_ETHER_TYPE_RARP:
637 : : break;
638 : :
639 : : case RTE_ETHER_TYPE_LLDP:
640 : : break;
641 : :
642 : 0 : default:
643 : 0 : rte_flow_error_set(error, EINVAL,
644 : : RTE_FLOW_ERROR_TYPE_ITEM,
645 : : flow_item,
646 : : "Unsupported ether_type in control packet filter.");
647 : 0 : return -rte_errno;
648 : : }
649 : : break;
650 : :
651 : : default:
652 : : break;
653 : : }
654 : : }
655 : :
656 : : return 0;
657 : : }
658 : :
659 : : static int
660 : 0 : hinic3_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
661 : : const struct rte_flow_attr *attr,
662 : : const struct rte_flow_item pattern[],
663 : : const struct rte_flow_action actions[],
664 : : struct rte_flow_error *error,
665 : : struct hinic3_filter_t *filter)
666 : : {
667 : : int ret;
668 : :
669 : 0 : ret = hinic3_flow_parse_ethertype_pattern(dev, pattern, error, filter);
670 [ # # ]: 0 : if (ret)
671 : : return ret;
672 : :
673 : 0 : ret = hinic3_flow_parse_ethertype_action(dev, actions, error, filter);
674 [ # # ]: 0 : if (ret)
675 : : return ret;
676 : :
677 : 0 : ret = hinic3_flow_parse_attr(attr, error);
678 [ # # ]: 0 : if (ret)
679 : : return ret;
680 : :
681 : 0 : filter->filter_type = RTE_ETH_FILTER_ETHERTYPE;
682 : 0 : return 0;
683 : : }
684 : :
685 : : static int
686 : 0 : hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
687 : : struct hinic3_filter_t *filter,
688 : : const struct rte_flow_item *flow_item,
689 : : enum hinic3_fdir_tunnel_mode tunnel_mode)
690 : : {
691 : : const struct rte_flow_item_ipv4 *spec_ipv4, *mask_ipv4;
692 : 0 : mask_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->mask;
693 : 0 : spec_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->spec;
694 : :
695 [ # # ]: 0 : if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
696 : 0 : filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
697 : :
698 [ # # ]: 0 : if (!mask_ipv4 && !spec_ipv4)
699 : : return 0;
700 : :
701 [ # # ]: 0 : if (!mask_ipv4 || !spec_ipv4) {
702 : 0 : rte_flow_error_set(error, EINVAL,
703 : : RTE_FLOW_ERROR_TYPE_ITEM,
704 : : flow_item,
705 : : "Invalid fdir filter, vxlan outer ipv4 mask or spec");
706 : 0 : return -rte_errno;
707 : : }
708 : :
709 : : /*
710 : : * Only support src address , dst addresses, others should be
711 : : * masked.
712 : : */
713 [ # # ]: 0 : if (mask_ipv4->hdr.version_ihl ||
714 : 0 : mask_ipv4->hdr.type_of_service ||
715 [ # # # # ]: 0 : mask_ipv4->hdr.total_length || mask_ipv4->hdr.packet_id ||
716 [ # # ]: 0 : mask_ipv4->hdr.fragment_offset ||
717 [ # # ]: 0 : mask_ipv4->hdr.time_to_live ||
718 : 0 : mask_ipv4->hdr.next_proto_id ||
719 [ # # ]: 0 : mask_ipv4->hdr.hdr_checksum) {
720 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
721 : : "Not supported by fdir filter, vxlan outer ipv4 only support src ip, dst ip");
722 : 0 : return -rte_errno;
723 : : }
724 : :
725 : : /* Set the filter information. */
726 : 0 : filter->fdir_filter.key_mask.ipv4.src_ip =
727 [ # # ]: 0 : rte_be_to_cpu_32(mask_ipv4->hdr.src_addr);
728 : 0 : filter->fdir_filter.key_spec.ipv4.src_ip =
729 [ # # ]: 0 : rte_be_to_cpu_32(spec_ipv4->hdr.src_addr);
730 : 0 : filter->fdir_filter.key_mask.ipv4.dst_ip =
731 [ # # ]: 0 : rte_be_to_cpu_32(mask_ipv4->hdr.dst_addr);
732 : 0 : filter->fdir_filter.key_spec.ipv4.dst_ip =
733 [ # # ]: 0 : rte_be_to_cpu_32(spec_ipv4->hdr.dst_addr);
734 : : } else {
735 : 0 : filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
736 : :
737 [ # # ]: 0 : if (!mask_ipv4 && !spec_ipv4)
738 : : return 0;
739 : :
740 [ # # ]: 0 : if (!mask_ipv4 || !spec_ipv4) {
741 : 0 : rte_flow_error_set(error, EINVAL,
742 : : RTE_FLOW_ERROR_TYPE_ITEM,
743 : : flow_item,
744 : : "Invalid fdir filter, vxlan inner ipv4 mask or spec");
745 : 0 : return -rte_errno;
746 : : }
747 : :
748 : : /*
749 : : * Only support src addr , dst addr, ip proto, others should be
750 : : * masked.
751 : : */
752 [ # # ]: 0 : if (mask_ipv4->hdr.version_ihl ||
753 : 0 : mask_ipv4->hdr.type_of_service ||
754 [ # # # # ]: 0 : mask_ipv4->hdr.total_length || mask_ipv4->hdr.packet_id ||
755 [ # # ]: 0 : mask_ipv4->hdr.fragment_offset ||
756 [ # # ]: 0 : mask_ipv4->hdr.time_to_live ||
757 [ # # ]: 0 : mask_ipv4->hdr.hdr_checksum) {
758 : 0 : rte_flow_error_set(error, EINVAL,
759 : : RTE_FLOW_ERROR_TYPE_ITEM,
760 : : flow_item,
761 : : "Not supported by fdir filter, vxlan inner ipv4 only support src ip, dst ip, proto");
762 : 0 : return -rte_errno;
763 : : }
764 : :
765 : : /* Set the filter information. */
766 : 0 : filter->fdir_filter.key_mask.inner_ipv4.src_ip =
767 [ # # ]: 0 : rte_be_to_cpu_32(mask_ipv4->hdr.src_addr);
768 : 0 : filter->fdir_filter.key_spec.inner_ipv4.src_ip =
769 [ # # ]: 0 : rte_be_to_cpu_32(spec_ipv4->hdr.src_addr);
770 : 0 : filter->fdir_filter.key_mask.inner_ipv4.dst_ip =
771 [ # # ]: 0 : rte_be_to_cpu_32(mask_ipv4->hdr.dst_addr);
772 : 0 : filter->fdir_filter.key_spec.inner_ipv4.dst_ip =
773 [ # # ]: 0 : rte_be_to_cpu_32(spec_ipv4->hdr.dst_addr);
774 : 0 : filter->fdir_filter.key_mask.proto =
775 : 0 : mask_ipv4->hdr.next_proto_id;
776 : 0 : filter->fdir_filter.key_spec.proto =
777 : 0 : spec_ipv4->hdr.next_proto_id;
778 : : }
779 : : return 0;
780 : : }
781 : :
782 : : static int
783 : 0 : hinic3_flow_fdir_tunnel_ipv6(struct rte_flow_error *error,
784 : : struct hinic3_filter_t *filter,
785 : : const struct rte_flow_item *flow_item,
786 : : enum hinic3_fdir_tunnel_mode tunnel_mode)
787 : : {
788 : : const struct rte_flow_item_ipv6 *spec_ipv6, *mask_ipv6;
789 : :
790 : 0 : mask_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->mask;
791 : 0 : spec_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->spec;
792 : :
793 [ # # ]: 0 : if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
794 : 0 : filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
795 : :
796 [ # # ]: 0 : if (!mask_ipv6 && !spec_ipv6)
797 : : return 0;
798 : :
799 [ # # ]: 0 : if (!mask_ipv6 || !spec_ipv6) {
800 : 0 : rte_flow_error_set(error, EINVAL,
801 : : RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
802 : : "Invalid fdir filter ipv6 mask or spec");
803 : 0 : return -rte_errno;
804 : : }
805 : :
806 : : /* Only support dst addresses, src addresses. */
807 [ # # ]: 0 : if (mask_ipv6->hdr.vtc_flow || mask_ipv6->hdr.payload_len ||
808 [ # # ]: 0 : mask_ipv6->hdr.hop_limits || mask_ipv6->hdr.proto) {
809 : 0 : rte_flow_error_set(error, EINVAL,
810 : : RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
811 : : "Not supported by fdir filter, ipv6 only support src ip, dst ip, proto");
812 : 0 : return -rte_errno;
813 : : }
814 : :
815 : 0 : net_addr_to_host(filter->fdir_filter.key_mask.ipv6.src_ip,
816 : 0 : (const uint32_t *)mask_ipv6->hdr.src_addr.a, 4);
817 : 0 : net_addr_to_host(filter->fdir_filter.key_spec.ipv6.src_ip,
818 : 0 : (const uint32_t *)spec_ipv6->hdr.src_addr.a, 4);
819 : 0 : net_addr_to_host(filter->fdir_filter.key_mask.ipv6.dst_ip,
820 : 0 : (const uint32_t *)mask_ipv6->hdr.dst_addr.a, 4);
821 : 0 : net_addr_to_host(filter->fdir_filter.key_spec.ipv6.dst_ip,
822 : 0 : (const uint32_t *)spec_ipv6->hdr.dst_addr.a, 4);
823 : : } else {
824 : 0 : filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
825 : :
826 [ # # ]: 0 : if (!mask_ipv6 && !spec_ipv6)
827 : : return 0;
828 : :
829 [ # # ]: 0 : if (!mask_ipv6 || !spec_ipv6) {
830 : 0 : rte_flow_error_set(error, EINVAL,
831 : : RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
832 : : "Invalid fdir filter ipv6 mask or spec");
833 : 0 : return -rte_errno;
834 : : }
835 : :
836 : : /* Only support dst addresses, src addresses, proto. */
837 [ # # # # ]: 0 : if (mask_ipv6->hdr.vtc_flow || mask_ipv6->hdr.payload_len ||
838 : : mask_ipv6->hdr.hop_limits) {
839 : 0 : rte_flow_error_set(error, EINVAL,
840 : : RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
841 : : "Not supported by fdir filter, ipv6 only support src ip, dst ip, proto");
842 : 0 : return -rte_errno;
843 : : }
844 : :
845 : 0 : net_addr_to_host(filter->fdir_filter.key_mask.inner_ipv6.src_ip,
846 : 0 : (const uint32_t *)mask_ipv6->hdr.src_addr.a, 4);
847 : 0 : net_addr_to_host(filter->fdir_filter.key_spec.inner_ipv6.src_ip,
848 : 0 : (const uint32_t *)spec_ipv6->hdr.src_addr.a, 4);
849 : 0 : net_addr_to_host(filter->fdir_filter.key_mask.inner_ipv6.dst_ip,
850 : 0 : (const uint32_t *)mask_ipv6->hdr.dst_addr.a, 4);
851 : 0 : net_addr_to_host(filter->fdir_filter.key_spec.inner_ipv6.dst_ip,
852 : 0 : (const uint32_t *)spec_ipv6->hdr.dst_addr.a, 4);
853 : :
854 : 0 : filter->fdir_filter.key_mask.proto = mask_ipv6->hdr.proto;
855 : 0 : filter->fdir_filter.key_spec.proto = spec_ipv6->hdr.proto;
856 : : }
857 : :
858 : : return 0;
859 : : }
860 : :
861 : : static int
862 : 0 : hinic3_flow_fdir_tunnel_tcp(struct rte_flow_error *error,
863 : : struct hinic3_filter_t *filter,
864 : : enum hinic3_fdir_tunnel_mode tunnel_mode,
865 : : const struct rte_flow_item *flow_item)
866 : : {
867 : : const struct rte_flow_item_tcp *spec_tcp, *mask_tcp;
868 : :
869 [ # # ]: 0 : if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
870 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
871 : : flow_item,
872 : : "Not supported by fdir filter, vxlan only support inner tcp");
873 : 0 : return -rte_errno;
874 : : }
875 : :
876 : 0 : filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
877 : 0 : filter->fdir_filter.key_spec.proto = IPPROTO_TCP;
878 : :
879 : 0 : mask_tcp = (const struct rte_flow_item_tcp *)flow_item->mask;
880 : 0 : spec_tcp = (const struct rte_flow_item_tcp *)flow_item->spec;
881 [ # # ]: 0 : if (!mask_tcp && !spec_tcp)
882 : : return 0;
883 [ # # ]: 0 : if (!mask_tcp || !spec_tcp) {
884 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
885 : : flow_item,
886 : : "Invalid fdir filter tcp mask or spec");
887 : 0 : return -rte_errno;
888 : : }
889 : :
890 : : /* Only support src, dst ports, others should be masked. */
891 [ # # # # ]: 0 : if (mask_tcp->hdr.sent_seq || mask_tcp->hdr.recv_ack ||
892 [ # # # # ]: 0 : mask_tcp->hdr.data_off || mask_tcp->hdr.rx_win ||
893 [ # # # # ]: 0 : mask_tcp->hdr.tcp_flags || mask_tcp->hdr.cksum ||
894 [ # # ]: 0 : mask_tcp->hdr.tcp_urp) {
895 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
896 : : flow_item,
897 : : "Not supported by fdir filter, vxlan inner tcp only support src port,dst port");
898 : 0 : return -rte_errno;
899 : : }
900 : :
901 : : /* Set the filter information. */
902 : 0 : filter->fdir_filter.key_mask.src_port =
903 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.src_port);
904 : 0 : filter->fdir_filter.key_spec.src_port =
905 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.src_port);
906 : 0 : filter->fdir_filter.key_mask.dst_port =
907 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.dst_port);
908 : 0 : filter->fdir_filter.key_spec.dst_port =
909 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.dst_port);
910 : 0 : return 0;
911 : : }
912 : :
913 : : static int
914 : 0 : hinic3_flow_fdir_tunnel_udp(struct rte_flow_error *error,
915 : : struct hinic3_filter_t *filter,
916 : : enum hinic3_fdir_tunnel_mode tunnel_mode,
917 : : const struct rte_flow_item *flow_item)
918 : : {
919 : : const struct rte_flow_item_udp *spec_udp, *mask_udp;
920 : :
921 : 0 : mask_udp = (const struct rte_flow_item_udp *)flow_item->mask;
922 : 0 : spec_udp = (const struct rte_flow_item_udp *)flow_item->spec;
923 : :
924 [ # # ]: 0 : if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
925 : : /*
926 : : * UDP is used to describe protocol,
927 : : * spec and mask should be NULL.
928 : : */
929 [ # # # # ]: 0 : if (flow_item->spec || flow_item->mask) {
930 : 0 : rte_flow_error_set(error, EINVAL,
931 : : RTE_FLOW_ERROR_TYPE_ITEM,
932 : : flow_item, "Invalid UDP item");
933 : 0 : return -rte_errno;
934 : : }
935 : : } else {
936 : 0 : filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
937 : 0 : filter->fdir_filter.key_spec.proto = IPPROTO_UDP;
938 [ # # ]: 0 : if (!mask_udp && !spec_udp)
939 : : return 0;
940 : :
941 [ # # ]: 0 : if (!mask_udp || !spec_udp) {
942 : 0 : rte_flow_error_set(error, EINVAL,
943 : : RTE_FLOW_ERROR_TYPE_ITEM,
944 : : flow_item,
945 : : "Invalid fdir filter vxlan inner udp mask or spec");
946 : 0 : return -rte_errno;
947 : : }
948 : :
949 : : /* Set the filter information. */
950 : 0 : filter->fdir_filter.key_mask.src_port =
951 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.src_port);
952 : 0 : filter->fdir_filter.key_spec.src_port =
953 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.src_port);
954 : 0 : filter->fdir_filter.key_mask.dst_port =
955 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.dst_port);
956 : 0 : filter->fdir_filter.key_spec.dst_port =
957 [ # # ]: 0 : (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.dst_port);
958 : : }
959 : :
960 : : return 0;
961 : : }
962 : :
963 : : static int
964 : 0 : hinic3_flow_fdir_vxlan(struct rte_flow_error *error,
965 : : struct hinic3_filter_t *filter,
966 : : const struct rte_flow_item *flow_item)
967 : : {
968 : : const struct rte_flow_item_vxlan *spec_vxlan, *mask_vxlan;
969 : 0 : uint32_t vxlan_vni_id = 0;
970 : :
971 : 0 : spec_vxlan = (const struct rte_flow_item_vxlan *)flow_item->spec;
972 : 0 : mask_vxlan = (const struct rte_flow_item_vxlan *)flow_item->mask;
973 : :
974 : 0 : filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_VXLAN;
975 : :
976 [ # # ]: 0 : if (!spec_vxlan && !mask_vxlan) {
977 : : return 0;
978 [ # # ]: 0 : } else if (filter->fdir_filter.outer_ip_type == HINIC3_FDIR_IP_TYPE_IPV6) {
979 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
980 : : flow_item,
981 : : "Invalid fdir filter vxlan mask or spec, ipv6 vxlan, don't support vni");
982 : 0 : return -rte_errno;
983 : : }
984 : :
985 [ # # ]: 0 : if (!spec_vxlan || !mask_vxlan) {
986 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
987 : : flow_item,
988 : : "Invalid fdir filter vxlan mask or spec");
989 : 0 : return -rte_errno;
990 : : }
991 : :
992 [ # # ]: 0 : memcpy(((uint8_t *)&vxlan_vni_id + 1), spec_vxlan->vni, 3);
993 : 0 : filter->fdir_filter.key_mask.tunnel.tunnel_id =
994 [ # # ]: 0 : rte_be_to_cpu_32(vxlan_vni_id);
995 : 0 : return 0;
996 : : }
997 : :
998 : : static int
999 : 0 : hinic3_flow_parse_fdir_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
1000 : : const struct rte_flow_item *pattern,
1001 : : struct rte_flow_error *error,
1002 : : struct hinic3_filter_t *filter)
1003 : : {
1004 : : const struct rte_flow_item *flow_item = pattern;
1005 : : enum hinic3_fdir_tunnel_mode tunnel_mode =
1006 : : HINIC3_FDIR_TUNNEL_MODE_NORMAL;
1007 : : enum rte_flow_item_type type;
1008 : : int err;
1009 : :
1010 : : /* Inner and outer ip type, set it to any by default */
1011 : 0 : filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_ANY;
1012 : 0 : filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_ANY;
1013 : :
1014 [ # # ]: 0 : for (; flow_item->type != RTE_FLOW_ITEM_TYPE_END; flow_item++) {
1015 [ # # ]: 0 : if (flow_item->last) {
1016 : 0 : rte_flow_error_set(error, EINVAL,
1017 : : RTE_FLOW_ERROR_TYPE_ITEM,
1018 : : flow_item, "Not support range");
1019 : 0 : return -rte_errno;
1020 : : }
1021 : :
1022 : : type = flow_item->type;
1023 [ # # # # : 0 : switch (type) {
# # # ]
1024 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
1025 : : /* All should be masked. */
1026 [ # # # # ]: 0 : if (flow_item->spec || flow_item->mask) {
1027 : 0 : rte_flow_error_set(error, EINVAL,
1028 : : RTE_FLOW_ERROR_TYPE_ITEM,
1029 : : flow_item,
1030 : : "Not supported by fdir filter, not support mac");
1031 : 0 : return -rte_errno;
1032 : : }
1033 : : break;
1034 : :
1035 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
1036 : 0 : err = hinic3_flow_fdir_tunnel_ipv4(error,
1037 : : filter, flow_item, tunnel_mode);
1038 [ # # ]: 0 : if (err)
1039 : 0 : return -rte_errno;
1040 : : break;
1041 : :
1042 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
1043 : 0 : err = hinic3_flow_fdir_tunnel_ipv6(error,
1044 : : filter, flow_item, tunnel_mode);
1045 [ # # ]: 0 : if (err)
1046 : 0 : return -rte_errno;
1047 : : break;
1048 : :
1049 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
1050 : 0 : err = hinic3_flow_fdir_tunnel_tcp(error,
1051 : : filter, tunnel_mode, flow_item);
1052 [ # # ]: 0 : if (err)
1053 : 0 : return -rte_errno;
1054 : : break;
1055 : :
1056 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
1057 : 0 : err = hinic3_flow_fdir_tunnel_udp(error,
1058 : : filter, tunnel_mode, flow_item);
1059 [ # # ]: 0 : if (err)
1060 : 0 : return -rte_errno;
1061 : : break;
1062 : :
1063 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
1064 : 0 : err = hinic3_flow_fdir_vxlan(error, filter, flow_item);
1065 [ # # ]: 0 : if (err)
1066 : 0 : return -rte_errno;
1067 : : tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_VXLAN;
1068 : : break;
1069 : :
1070 : : default:
1071 : : break;
1072 : : }
1073 : : }
1074 : :
1075 : : return 0;
1076 : : }
1077 : :
1078 : : /**
1079 : : * Resolve VXLAN Filters in Flow Filters.
1080 : : *
1081 : : * @param[in] dev
1082 : : * Pointer to ethernet device structure.
1083 : : * @param[in] attr
1084 : : * Indicates the attribute of a flow rule.
1085 : : * @param[in] pattern
1086 : : * Indicates the pattern or matching condition of a traffic rule.
1087 : : * @param[in] actions
1088 : : * Indicates the action to be taken on the matched traffic.
1089 : : * @param[out] error
1090 : : * Structure that contains error information, such as error code and error
1091 : : * description.
1092 : : * @param[out] filter
1093 : : * Filter information, its used to store and manipulate packet filtering rules.
1094 : : * @return
1095 : : * 0 on success, non-zero on failure.
1096 : : */
1097 : : static int
1098 : 0 : hinic3_flow_parse_fdir_vxlan_filter(struct rte_eth_dev *dev,
1099 : : const struct rte_flow_attr *attr,
1100 : : const struct rte_flow_item pattern[],
1101 : : const struct rte_flow_action actions[],
1102 : : struct rte_flow_error *error,
1103 : : struct hinic3_filter_t *filter)
1104 : : {
1105 : : int ret;
1106 : :
1107 : 0 : ret = hinic3_flow_parse_fdir_vxlan_pattern(dev, pattern, error, filter);
1108 [ # # ]: 0 : if (ret)
1109 : : return ret;
1110 : :
1111 : 0 : ret = hinic3_flow_parse_action(dev, actions, error, filter);
1112 [ # # ]: 0 : if (ret)
1113 : : return ret;
1114 : :
1115 : 0 : ret = hinic3_flow_parse_attr(attr, error);
1116 [ # # ]: 0 : if (ret)
1117 : : return ret;
1118 : :
1119 : 0 : filter->filter_type = RTE_ETH_FILTER_FDIR;
1120 : :
1121 : 0 : return 0;
1122 : : }
1123 : :
1124 : : /**
1125 : : * Parse patterns and actions of network traffic.
1126 : : *
1127 : : * @param[in] dev
1128 : : * Pointer to ethernet device structure.
1129 : : * @param[in] attr
1130 : : * Indicates the attribute of a flow rule.
1131 : : * @param[in] pattern
1132 : : * Indicates the pattern or matching condition of a traffic rule.
1133 : : * @param[in] actions
1134 : : * Indicates the action to be taken on the matched traffic.
1135 : : * @param[out] error
1136 : : * Structure that contains error information, such as error code and error
1137 : : * description.
1138 : : * @param[out] filter
1139 : : * Filter information, its used to store and manipulate packet filtering rules.
1140 : : * @return
1141 : : * 0 on success, non-zero on failure.
1142 : : */
1143 : : static int
1144 : 0 : hinic3_flow_parse(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
1145 : : const struct rte_flow_item pattern[],
1146 : : const struct rte_flow_action actions[],
1147 : : struct rte_flow_error *error, struct hinic3_filter_t *filter)
1148 : : {
1149 : : hinic3_parse_filter_t parse_filter;
1150 : : uint32_t pattern_num = 0;
1151 : : int ret = 0;
1152 : : /* Check whether the parameter is valid. */
1153 [ # # # # ]: 0 : if (!pattern || !actions || !attr) {
1154 : 0 : rte_flow_error_set(error, EINVAL,
1155 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1156 : : "NULL param.");
1157 : 0 : return -rte_errno;
1158 : : }
1159 : :
1160 [ # # ]: 0 : while ((pattern + pattern_num)->type != RTE_FLOW_ITEM_TYPE_END) {
1161 : 0 : pattern_num++;
1162 [ # # ]: 0 : if (pattern_num > HINIC3_FLOW_MAX_PATTERN_NUM) {
1163 : 0 : rte_flow_error_set(error, EINVAL,
1164 : : HINIC3_FLOW_MAX_PATTERN_NUM, NULL,
1165 : : "Too many patterns.");
1166 : 0 : return -rte_errno;
1167 : : }
1168 : : }
1169 : : /*
1170 : : * The corresponding filter is returned. If the filter is not found,
1171 : : * NULL is returned.
1172 : : */
1173 : 0 : parse_filter = hinic3_find_parse_filter_func(pattern);
1174 [ # # ]: 0 : if (!parse_filter) {
1175 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1176 : : pattern, "Unsupported pattern");
1177 : 0 : return -rte_errno;
1178 : : }
1179 : : /* Parsing with filters. */
1180 : 0 : ret = parse_filter(dev, attr, pattern, actions, error, filter);
1181 : :
1182 : 0 : return ret;
1183 : : }
1184 : :
1185 : : /**
1186 : : * Check whether the traffic rule provided by the user is valid.
1187 : : *
1188 : : * @param[in] dev
1189 : : * Pointer to ethernet device structure.
1190 : : * @param[in] attr
1191 : : * Indicates the attribute of a flow rule.
1192 : : * @param[in] pattern
1193 : : * Indicates the pattern or matching condition of a traffic rule.
1194 : : * @param[in] actions
1195 : : * Indicates the action to be taken on the matched traffic.
1196 : : * @param[out] error
1197 : : * Structure that contains error information, such as error code and error
1198 : : * description.
1199 : : * @return
1200 : : * 0 on success, non-zero on failure.
1201 : : */
1202 : : static int
1203 : 0 : hinic3_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
1204 : : const struct rte_flow_item pattern[],
1205 : : const struct rte_flow_action actions[],
1206 : : struct rte_flow_error *error)
1207 : : {
1208 : 0 : struct hinic3_filter_t filter_rules = {0};
1209 : :
1210 : 0 : return hinic3_flow_parse(dev, attr, pattern, actions, error, &filter_rules);
1211 : : }
1212 : :
1213 : : /**
1214 : : * Create a flow item.
1215 : : *
1216 : : * @param[in] dev
1217 : : * Pointer to ethernet device structure.
1218 : : * @param[in] attr
1219 : : * Indicates the attribute of a flow rule.
1220 : : * @param[in] pattern
1221 : : * Indicates the pattern or matching condition of a traffic rule.
1222 : : * @param[in] actions
1223 : : * Indicates the action to be taken on the matched traffic.
1224 : : * @param[out] error
1225 : : * Structure that contains error information, such as error code and error
1226 : : * description.
1227 : : * @return
1228 : : * If the operation is successful, the created flow is returned. Otherwise, NULL
1229 : : * is returned.
1230 : : *
1231 : : */
1232 : : static struct rte_flow *
1233 : 0 : hinic3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
1234 : : const struct rte_flow_item pattern[],
1235 : : const struct rte_flow_action actions[],
1236 : : struct rte_flow_error *error)
1237 : : {
1238 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1239 : : struct hinic3_filter_t *filter_rules = NULL;
1240 : : struct rte_flow *flow = NULL;
1241 : : int ret;
1242 : :
1243 : : filter_rules =
1244 : 0 : rte_zmalloc("filter_rules", sizeof(struct hinic3_filter_t), 0);
1245 [ # # ]: 0 : if (!filter_rules) {
1246 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
1247 : : NULL,
1248 : : "Failed to allocate filter rules memory.");
1249 : 0 : return NULL;
1250 : : }
1251 : :
1252 : 0 : flow = rte_zmalloc("hinic3_rte_flow", sizeof(struct rte_flow), 0);
1253 [ # # ]: 0 : if (!flow) {
1254 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
1255 : : NULL, "Failed to allocate flow memory.");
1256 : 0 : rte_free(filter_rules);
1257 : 0 : return NULL;
1258 : : }
1259 : : /* Parses the flow rule to be created and generates a filter. */
1260 : 0 : ret = hinic3_flow_parse(dev, attr, pattern, actions, error,
1261 : : filter_rules);
1262 [ # # ]: 0 : if (ret < 0)
1263 : 0 : goto free_flow;
1264 : :
1265 [ # # # ]: 0 : switch (filter_rules->filter_type) {
1266 : 0 : case RTE_ETH_FILTER_ETHERTYPE:
1267 : 0 : ret = hinic3_flow_add_del_ethertype_filter(dev,
1268 : : &filter_rules->ethertype_filter, true);
1269 [ # # ]: 0 : if (ret) {
1270 : 0 : rte_flow_error_set(error, EINVAL,
1271 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1272 : : "Create ethertype filter failed.");
1273 : 0 : goto free_flow;
1274 : : }
1275 : :
1276 : 0 : flow->rule = filter_rules;
1277 : 0 : flow->filter_type = filter_rules->filter_type;
1278 : 0 : TAILQ_INSERT_TAIL(&nic_dev->filter_ethertype_list, flow, node);
1279 : 0 : break;
1280 : :
1281 : 0 : case RTE_ETH_FILTER_FDIR:
1282 : 0 : ret = hinic3_flow_add_del_fdir_filter(dev,
1283 : : &filter_rules->fdir_filter, true);
1284 [ # # ]: 0 : if (ret) {
1285 : 0 : rte_flow_error_set(error, EINVAL,
1286 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1287 : : "Create fdir filter failed.");
1288 : 0 : goto free_flow;
1289 : : }
1290 : :
1291 : 0 : flow->rule = filter_rules;
1292 : 0 : flow->filter_type = filter_rules->filter_type;
1293 : 0 : TAILQ_INSERT_TAIL(&nic_dev->filter_fdir_rule_list, flow, node);
1294 : 0 : break;
1295 : 0 : default:
1296 : 0 : PMD_DRV_LOG(ERR, "Filter type %d not supported",
1297 : : filter_rules->filter_type);
1298 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
1299 : : NULL, "Unsupported filter type.");
1300 : 0 : goto free_flow;
1301 : : }
1302 : :
1303 : : return flow;
1304 : :
1305 : 0 : free_flow:
1306 : 0 : rte_free(flow);
1307 : 0 : rte_free(filter_rules);
1308 : :
1309 : 0 : return NULL;
1310 : : }
1311 : :
1312 : : static int
1313 : 0 : hinic3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
1314 : : struct rte_flow_error *error)
1315 : : {
1316 : : int ret = -EINVAL;
1317 : : enum rte_filter_type type;
1318 : : struct hinic3_filter_t *rules = NULL;
1319 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1320 : :
1321 [ # # ]: 0 : if (!flow) {
1322 : 0 : PMD_DRV_LOG(ERR, "Invalid flow parameter!");
1323 : 0 : return -EPERM;
1324 : : }
1325 : :
1326 : 0 : type = flow->filter_type;
1327 : 0 : rules = (struct hinic3_filter_t *)flow->rule;
1328 : : /* Perform operations based on the type. */
1329 [ # # # ]: 0 : switch (type) {
1330 : 0 : case RTE_ETH_FILTER_ETHERTYPE:
1331 : 0 : ret = hinic3_flow_add_del_ethertype_filter(dev,
1332 : : &rules->ethertype_filter, false);
1333 [ # # ]: 0 : if (!ret)
1334 [ # # ]: 0 : TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, node);
1335 : :
1336 : 0 : flow->rule = rules;
1337 : 0 : flow->filter_type = rules->filter_type;
1338 [ # # ]: 0 : TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, node);
1339 : 0 : break;
1340 : :
1341 : 0 : case RTE_ETH_FILTER_FDIR:
1342 : 0 : ret = hinic3_flow_add_del_fdir_filter(dev, &rules->fdir_filter, false);
1343 [ # # ]: 0 : if (!ret)
1344 [ # # ]: 0 : TAILQ_REMOVE(&nic_dev->filter_fdir_rule_list, flow, node);
1345 : : break;
1346 : 0 : default:
1347 : 0 : PMD_DRV_LOG(WARNING, "Filter type %d not supported", type);
1348 : : ret = -EINVAL;
1349 : : break;
1350 : : }
1351 : :
1352 : : /* Deleted successfully. Resources are released. */
1353 [ # # ]: 0 : if (!ret) {
1354 : 0 : rte_free(rules);
1355 : 0 : rte_free(flow);
1356 : : } else {
1357 : 0 : rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE,
1358 : : NULL, "Failed to destroy flow.");
1359 : : }
1360 : :
1361 : : return ret;
1362 : : }
1363 : :
1364 : : /**
1365 : : * Clear all fdir type flow rules on the network device.
1366 : : *
1367 : : * @param[in] dev
1368 : : * Pointer to ethernet device structure.
1369 : : * @return
1370 : : * 0 on success, non-zero on failure.
1371 : : */
1372 : : static int
1373 : 0 : hinic3_flow_flush_fdir_filter(struct rte_eth_dev *dev)
1374 : : {
1375 : : int ret = 0;
1376 : : struct hinic3_filter_t *filter_rules = NULL;
1377 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1378 : : struct rte_flow *flow;
1379 : :
1380 : : while (true) {
1381 : 0 : flow = TAILQ_FIRST(&nic_dev->filter_fdir_rule_list);
1382 [ # # ]: 0 : if (flow == NULL)
1383 : : break;
1384 : 0 : filter_rules = (struct hinic3_filter_t *)flow->rule;
1385 : :
1386 : : /* Delete flow rules. */
1387 : 0 : ret = hinic3_flow_add_del_fdir_filter(dev,
1388 : : &filter_rules->fdir_filter, false);
1389 : :
1390 [ # # ]: 0 : if (ret)
1391 : 0 : return ret;
1392 : :
1393 [ # # ]: 0 : TAILQ_REMOVE(&nic_dev->filter_fdir_rule_list, flow, node);
1394 : 0 : rte_free(filter_rules);
1395 : 0 : rte_free(flow);
1396 : : }
1397 : :
1398 : : return ret;
1399 : : }
1400 : :
1401 : : /**
1402 : : * Clear all ether type flow rules on the network device.
1403 : : *
1404 : : * @param[in] dev
1405 : : * Pointer to ethernet device structure.
1406 : : * @return
1407 : : * 0 on success, non-zero on failure.
1408 : : */
1409 : : static int
1410 : 0 : hinic3_flow_flush_ethertype_filter(struct rte_eth_dev *dev)
1411 : : {
1412 : : struct hinic3_filter_t *filter_rules = NULL;
1413 : 0 : struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1414 : : struct rte_flow *flow;
1415 : : int ret = 0;
1416 : :
1417 : : while (true) {
1418 : 0 : flow = TAILQ_FIRST(&nic_dev->filter_ethertype_list);
1419 [ # # ]: 0 : if (flow == NULL)
1420 : : break;
1421 : 0 : filter_rules = (struct hinic3_filter_t *)flow->rule;
1422 : :
1423 : : /* Delete flow rules. */
1424 : 0 : ret = hinic3_flow_add_del_ethertype_filter(dev,
1425 : : &filter_rules->ethertype_filter, false);
1426 : :
1427 [ # # ]: 0 : if (ret)
1428 : 0 : return ret;
1429 : :
1430 [ # # ]: 0 : TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, node);
1431 : 0 : rte_free(filter_rules);
1432 : 0 : rte_free(flow);
1433 : : }
1434 : :
1435 : : return ret;
1436 : : }
1437 : :
1438 : : /**
1439 : : * Clear all flow rules on the network device.
1440 : : *
1441 : : * @param[in] dev
1442 : : * Pointer to ethernet device structure.
1443 : : * @param[out] error
1444 : : * Structure that contains error information, such as error code and error
1445 : : * description.
1446 : : * @return
1447 : : * 0 on success, non-zero on failure.
1448 : : */
1449 : : static int
1450 : 0 : hinic3_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1451 : : {
1452 : : int ret;
1453 : :
1454 : 0 : ret = hinic3_flow_flush_fdir_filter(dev);
1455 [ # # ]: 0 : if (ret) {
1456 : 0 : rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE,
1457 : : NULL, "Failed to flush fdir flows.");
1458 : 0 : return -rte_errno;
1459 : : }
1460 : :
1461 : 0 : ret = hinic3_flow_flush_ethertype_filter(dev);
1462 [ # # ]: 0 : if (ret) {
1463 : 0 : rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE,
1464 : : NULL, "Failed to flush ethertype flows.");
1465 : 0 : return -rte_errno;
1466 : : }
1467 : : return ret;
1468 : : }
1469 : :
1470 : : /* Structure for managing flow table operations. */
1471 : : const struct rte_flow_ops hinic3_flow_ops = {
1472 : : .validate = hinic3_flow_validate,
1473 : : .create = hinic3_flow_create,
1474 : : .destroy = hinic3_flow_destroy,
1475 : : .flush = hinic3_flow_flush,
1476 : : };
|