Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2022 Intel Corporation
3 : : */
4 : :
5 : : #include <sys/queue.h>
6 : : #include <stdio.h>
7 : : #include <errno.h>
8 : : #include <stdint.h>
9 : : #include <string.h>
10 : : #include <unistd.h>
11 : : #include <stdarg.h>
12 : : #include <rte_debug.h>
13 : : #include <rte_ether.h>
14 : : #include <rte_ethdev.h>
15 : : #include <rte_log.h>
16 : : #include <rte_malloc.h>
17 : : #include <rte_eth_ctrl.h>
18 : : #include <rte_tailq.h>
19 : : #include <rte_flow_driver.h>
20 : : #include <rte_flow.h>
21 : : #include <iavf.h>
22 : : #include "iavf_generic_flow.h"
23 : :
24 : : #define MAX_QGRP_NUM_TYPE 7
25 : : #define IAVF_IPV6_ADDR_LENGTH 16
26 : : #define MAX_INPUT_SET_BYTE 32
27 : :
28 : : #define IAVF_SW_INSET_ETHER ( \
29 : : IAVF_INSET_DMAC | IAVF_INSET_SMAC | IAVF_INSET_ETHERTYPE)
30 : : #define IAVF_SW_INSET_MAC_IPV4 ( \
31 : : IAVF_INSET_DMAC | IAVF_INSET_IPV4_DST | IAVF_INSET_IPV4_SRC | \
32 : : IAVF_INSET_IPV4_PROTO | IAVF_INSET_IPV4_TTL | IAVF_INSET_IPV4_TOS)
33 : : #define IAVF_SW_INSET_MAC_VLAN_IPV4 ( \
34 : : IAVF_SW_INSET_MAC_IPV4 | IAVF_INSET_VLAN_OUTER)
35 : : #define IAVF_SW_INSET_MAC_IPV4_TCP ( \
36 : : IAVF_INSET_DMAC | IAVF_INSET_IPV4_DST | IAVF_INSET_IPV4_SRC | \
37 : : IAVF_INSET_IPV4_TTL | IAVF_INSET_IPV4_TOS | \
38 : : IAVF_INSET_TCP_DST_PORT | IAVF_INSET_TCP_SRC_PORT)
39 : : #define IAVF_SW_INSET_MAC_IPV4_UDP ( \
40 : : IAVF_INSET_DMAC | IAVF_INSET_IPV4_DST | IAVF_INSET_IPV4_SRC | \
41 : : IAVF_INSET_IPV4_TTL | IAVF_INSET_IPV4_TOS | \
42 : : IAVF_INSET_UDP_DST_PORT | IAVF_INSET_UDP_SRC_PORT)
43 : : #define IAVF_SW_INSET_MAC_IPV6 ( \
44 : : IAVF_INSET_DMAC | IAVF_INSET_IPV6_DST | IAVF_INSET_IPV6_SRC | \
45 : : IAVF_INSET_IPV6_TC | IAVF_INSET_IPV6_HOP_LIMIT | \
46 : : IAVF_INSET_IPV6_NEXT_HDR)
47 : : #define IAVF_SW_INSET_MAC_IPV6_TCP ( \
48 : : IAVF_INSET_DMAC | IAVF_INSET_IPV6_DST | IAVF_INSET_IPV6_SRC | \
49 : : IAVF_INSET_IPV6_HOP_LIMIT | IAVF_INSET_IPV6_TC | \
50 : : IAVF_INSET_TCP_DST_PORT | IAVF_INSET_TCP_SRC_PORT)
51 : : #define IAVF_SW_INSET_MAC_IPV6_UDP ( \
52 : : IAVF_INSET_DMAC | IAVF_INSET_IPV6_DST | IAVF_INSET_IPV6_SRC | \
53 : : IAVF_INSET_IPV6_HOP_LIMIT | IAVF_INSET_IPV6_TC | \
54 : : IAVF_INSET_UDP_DST_PORT | IAVF_INSET_UDP_SRC_PORT)
55 : :
56 : : static struct iavf_flow_parser iavf_fsub_parser;
57 : :
58 : : static struct
59 : : iavf_pattern_match_item iavf_fsub_pattern_list[] = {
60 : : {iavf_pattern_ethertype, IAVF_SW_INSET_ETHER, IAVF_INSET_NONE},
61 : : {iavf_pattern_eth_ipv4, IAVF_SW_INSET_MAC_IPV4, IAVF_INSET_NONE},
62 : : {iavf_pattern_eth_vlan_ipv4, IAVF_SW_INSET_MAC_VLAN_IPV4, IAVF_INSET_NONE},
63 : : {iavf_pattern_eth_ipv4_udp, IAVF_SW_INSET_MAC_IPV4_UDP, IAVF_INSET_NONE},
64 : : {iavf_pattern_eth_ipv4_tcp, IAVF_SW_INSET_MAC_IPV4_TCP, IAVF_INSET_NONE},
65 : : {iavf_pattern_eth_ipv6, IAVF_SW_INSET_MAC_IPV6, IAVF_INSET_NONE},
66 : : {iavf_pattern_eth_ipv6_udp, IAVF_SW_INSET_MAC_IPV6_UDP, IAVF_INSET_NONE},
67 : : {iavf_pattern_eth_ipv6_tcp, IAVF_SW_INSET_MAC_IPV6_TCP, IAVF_INSET_NONE},
68 : : };
69 : :
70 : : static int
71 : 0 : iavf_fsub_create(struct iavf_adapter *ad, struct rte_flow *flow,
72 : : void *meta, struct rte_flow_error *error)
73 : : {
74 : : struct iavf_fsub_conf *filter = meta;
75 : : struct iavf_fsub_conf *rule;
76 : : int ret;
77 : :
78 : 0 : rule = rte_zmalloc("fsub_entry", sizeof(*rule), 0);
79 [ # # ]: 0 : if (!rule) {
80 : 0 : rte_flow_error_set(error, ENOMEM,
81 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
82 : : "Failed to allocate memory for fsub rule");
83 : 0 : return -rte_errno;
84 : : }
85 : :
86 : 0 : ret = iavf_flow_sub(ad, filter);
87 [ # # ]: 0 : if (ret) {
88 : 0 : rte_flow_error_set(error, -ret,
89 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
90 : : "Failed to subscribe flow rule.");
91 : 0 : goto free_entry;
92 : : }
93 : :
94 : : memcpy(rule, filter, sizeof(*rule));
95 : 0 : flow->rule = rule;
96 : :
97 : 0 : rte_free(meta);
98 : 0 : return ret;
99 : :
100 : : free_entry:
101 : 0 : rte_free(rule);
102 : 0 : return -rte_errno;
103 : : }
104 : :
105 : : static int
106 : 0 : iavf_fsub_destroy(struct iavf_adapter *ad, struct rte_flow *flow,
107 : : struct rte_flow_error *error)
108 : : {
109 : : struct iavf_fsub_conf *filter;
110 : : int ret;
111 : :
112 : 0 : filter = (struct iavf_fsub_conf *)flow->rule;
113 : :
114 : 0 : ret = iavf_flow_unsub(ad, filter);
115 [ # # ]: 0 : if (ret) {
116 : 0 : rte_flow_error_set(error, -ret,
117 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
118 : : "Failed to unsubscribe flow rule.");
119 : 0 : return -rte_errno;
120 : : }
121 : :
122 : 0 : flow->rule = NULL;
123 : 0 : rte_free(filter);
124 : :
125 : 0 : return ret;
126 : : }
127 : :
128 : : static int
129 : 0 : iavf_fsub_validation(struct iavf_adapter *ad,
130 : : __rte_unused struct rte_flow *flow,
131 : : void *meta,
132 : : struct rte_flow_error *error)
133 : : {
134 : : struct iavf_fsub_conf *filter = meta;
135 : : int ret;
136 : :
137 : 0 : ret = iavf_flow_sub_check(ad, filter);
138 [ # # ]: 0 : if (ret) {
139 : 0 : rte_flow_error_set(error, -ret,
140 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
141 : : "Failed to validate filter rule.");
142 : 0 : return -rte_errno;
143 : : }
144 : :
145 : : return ret;
146 : : };
147 : :
148 : : static int
149 : 0 : iavf_fsub_parse_pattern(const struct rte_flow_item pattern[],
150 : : const uint64_t input_set_mask,
151 : : struct rte_flow_error *error,
152 : : struct iavf_fsub_conf *filter)
153 : : {
154 : : struct virtchnl_proto_hdrs *hdrs = &filter->sub_fltr.proto_hdrs;
155 : : enum rte_flow_item_type item_type;
156 : : const struct rte_flow_item_eth *eth_spec, *eth_mask;
157 : : const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
158 : : const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
159 : : const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
160 : : const struct rte_flow_item_udp *udp_spec, *udp_mask;
161 : : const struct rte_flow_item_vlan *vlan_spec, *vlan_mask;
162 : : const struct rte_flow_item *item = pattern;
163 : : struct virtchnl_proto_hdr_w_msk *hdr, *hdr1 = NULL;
164 : : uint64_t outer_input_set = IAVF_INSET_NONE;
165 : : uint64_t *input = NULL;
166 : : uint16_t input_set_byte = 0;
167 : : uint32_t layer = 0;
168 : :
169 [ # # ]: 0 : for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
170 [ # # ]: 0 : if (item->last) {
171 : 0 : rte_flow_error_set(error, EINVAL,
172 : : RTE_FLOW_ERROR_TYPE_ITEM,
173 : : item, "Not support range");
174 : 0 : return -rte_errno;
175 : : }
176 : :
177 : : item_type = item->type;
178 [ # # # # : 0 : switch (item_type) {
# # # # ]
179 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
180 : 0 : eth_spec = item->spec;
181 : 0 : eth_mask = item->mask;
182 : :
183 : : hdr1 = &hdrs->proto_hdr_w_msk[layer];
184 : :
185 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, ETH);
186 : :
187 [ # # ]: 0 : if (eth_spec && eth_mask) {
188 : : input = &outer_input_set;
189 : :
190 [ # # ]: 0 : if (!rte_is_zero_ether_addr(ð_mask->hdr.dst_addr)) {
191 : 0 : *input |= IAVF_INSET_DMAC;
192 : 0 : input_set_byte += 6;
193 : : } else {
194 : : /* flow subscribe filter will add dst mac in kernel */
195 : 0 : input_set_byte += 6;
196 : : }
197 : :
198 [ # # ]: 0 : if (!rte_is_zero_ether_addr(ð_mask->hdr.src_addr)) {
199 : 0 : *input |= IAVF_INSET_SMAC;
200 : 0 : input_set_byte += 6;
201 : : }
202 : :
203 [ # # ]: 0 : if (eth_mask->hdr.ether_type) {
204 : 0 : *input |= IAVF_INSET_ETHERTYPE;
205 : 0 : input_set_byte += 2;
206 : : }
207 : :
208 : 0 : memcpy(hdr1->buffer_spec, eth_spec,
209 : : sizeof(struct rte_ether_hdr));
210 : 0 : memcpy(hdr1->buffer_mask, eth_mask,
211 : : sizeof(struct rte_ether_hdr));
212 : : } else {
213 : : /* flow subscribe filter will add dst mac in kernel */
214 : 0 : input_set_byte += 6;
215 : : }
216 : :
217 : 0 : hdrs->count = ++layer;
218 : 0 : break;
219 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
220 : 0 : ipv4_spec = item->spec;
221 : 0 : ipv4_mask = item->mask;
222 : :
223 : : hdr = &hdrs->proto_hdr_w_msk[layer];
224 : :
225 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV4);
226 : :
227 [ # # ]: 0 : if (ipv4_spec && ipv4_mask) {
228 : : input = &outer_input_set;
229 : : /* Check IPv4 mask and update input set */
230 [ # # ]: 0 : if (ipv4_mask->hdr.version_ihl ||
231 [ # # ]: 0 : ipv4_mask->hdr.total_length ||
232 [ # # ]: 0 : ipv4_mask->hdr.packet_id ||
233 [ # # ]: 0 : ipv4_mask->hdr.hdr_checksum) {
234 : 0 : rte_flow_error_set(error, EINVAL,
235 : : RTE_FLOW_ERROR_TYPE_ITEM,
236 : : item, "Invalid IPv4 mask.");
237 : 0 : return -rte_errno;
238 : : }
239 : :
240 [ # # ]: 0 : if (ipv4_mask->hdr.src_addr) {
241 : 0 : *input |= IAVF_INSET_IPV4_SRC;
242 : 0 : input_set_byte += 4;
243 : : }
244 [ # # ]: 0 : if (ipv4_mask->hdr.dst_addr) {
245 : 0 : *input |= IAVF_INSET_IPV4_DST;
246 : 0 : input_set_byte += 4;
247 : : }
248 [ # # ]: 0 : if (ipv4_mask->hdr.time_to_live) {
249 : 0 : *input |= IAVF_INSET_IPV4_TTL;
250 : 0 : input_set_byte++;
251 : : }
252 [ # # ]: 0 : if (ipv4_mask->hdr.next_proto_id) {
253 : 0 : *input |= IAVF_INSET_IPV4_PROTO;
254 : 0 : input_set_byte++;
255 : : }
256 [ # # ]: 0 : if (ipv4_mask->hdr.type_of_service) {
257 : 0 : *input |= IAVF_INSET_IPV4_TOS;
258 : 0 : input_set_byte++;
259 : : }
260 : :
261 : 0 : memcpy(hdr->buffer_spec, &ipv4_spec->hdr,
262 : : sizeof(ipv4_spec->hdr));
263 : 0 : memcpy(hdr->buffer_mask, &ipv4_mask->hdr,
264 : : sizeof(ipv4_spec->hdr));
265 : : }
266 : :
267 : 0 : hdrs->count = ++layer;
268 : 0 : break;
269 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6: {
270 : : int j;
271 : :
272 : 0 : ipv6_spec = item->spec;
273 : 0 : ipv6_mask = item->mask;
274 : :
275 : : hdr = &hdrs->proto_hdr_w_msk[layer];
276 : :
277 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV6);
278 : :
279 [ # # ]: 0 : if (ipv6_spec && ipv6_mask) {
280 : : input = &outer_input_set;
281 : :
282 [ # # ]: 0 : if (ipv6_mask->hdr.payload_len) {
283 : 0 : rte_flow_error_set(error, EINVAL,
284 : : RTE_FLOW_ERROR_TYPE_ITEM,
285 : : item, "Invalid IPv6 mask");
286 : 0 : return -rte_errno;
287 : : }
288 : :
289 [ # # ]: 0 : for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
290 [ # # ]: 0 : if (ipv6_mask->hdr.src_addr.a[j]) {
291 : 0 : *input |= IAVF_INSET_IPV6_SRC;
292 : 0 : break;
293 : : }
294 : : }
295 [ # # ]: 0 : for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
296 [ # # ]: 0 : if (ipv6_mask->hdr.dst_addr.a[j]) {
297 : 0 : *input |= IAVF_INSET_IPV6_DST;
298 : 0 : break;
299 : : }
300 : : }
301 : :
302 [ # # ]: 0 : for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
303 [ # # ]: 0 : if (ipv6_mask->hdr.src_addr.a[j])
304 : 0 : input_set_byte++;
305 : :
306 [ # # ]: 0 : if (ipv6_mask->hdr.dst_addr.a[j])
307 : 0 : input_set_byte++;
308 : : }
309 : :
310 [ # # ]: 0 : if (ipv6_mask->hdr.proto) {
311 : 0 : *input |= IAVF_INSET_IPV6_NEXT_HDR;
312 : 0 : input_set_byte++;
313 : : }
314 [ # # ]: 0 : if (ipv6_mask->hdr.hop_limits) {
315 : 0 : *input |= IAVF_INSET_IPV6_HOP_LIMIT;
316 : 0 : input_set_byte++;
317 : : }
318 [ # # ]: 0 : if (ipv6_mask->hdr.vtc_flow &
319 : : rte_cpu_to_be_32(RTE_IPV6_HDR_TC_MASK)) {
320 : 0 : *input |= IAVF_INSET_IPV6_TC;
321 : 0 : input_set_byte += 4;
322 : : }
323 : :
324 : 0 : memcpy(hdr->buffer_spec, &ipv6_spec->hdr,
325 : : sizeof(ipv6_spec->hdr));
326 : 0 : memcpy(hdr->buffer_mask, &ipv6_mask->hdr,
327 : : sizeof(ipv6_spec->hdr));
328 : : }
329 : :
330 : 0 : hdrs->count = ++layer;
331 : 0 : break;
332 : : }
333 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
334 : 0 : udp_spec = item->spec;
335 : 0 : udp_mask = item->mask;
336 : :
337 : : hdr = &hdrs->proto_hdr_w_msk[layer];
338 : :
339 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, UDP);
340 : :
341 [ # # ]: 0 : if (udp_spec && udp_mask) {
342 : : input = &outer_input_set;
343 : : /* Check UDP mask and update input set*/
344 [ # # ]: 0 : if (udp_mask->hdr.dgram_len ||
345 [ # # ]: 0 : udp_mask->hdr.dgram_cksum) {
346 : 0 : rte_flow_error_set(error, EINVAL,
347 : : RTE_FLOW_ERROR_TYPE_ITEM,
348 : : item, "Invalid UDP mask");
349 : 0 : return -rte_errno;
350 : : }
351 : :
352 [ # # ]: 0 : if (udp_mask->hdr.src_port) {
353 : 0 : *input |= IAVF_INSET_UDP_SRC_PORT;
354 : 0 : input_set_byte += 2;
355 : : }
356 [ # # ]: 0 : if (udp_mask->hdr.dst_port) {
357 : 0 : *input |= IAVF_INSET_UDP_DST_PORT;
358 : 0 : input_set_byte += 2;
359 : : }
360 : :
361 : 0 : memcpy(hdr->buffer_spec, &udp_spec->hdr,
362 : : sizeof(udp_spec->hdr));
363 : 0 : memcpy(hdr->buffer_mask, &udp_mask->hdr,
364 : : sizeof(udp_mask->hdr));
365 : : }
366 : :
367 : 0 : hdrs->count = ++layer;
368 : 0 : break;
369 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
370 : 0 : tcp_spec = item->spec;
371 : 0 : tcp_mask = item->mask;
372 : :
373 : : hdr = &hdrs->proto_hdr_w_msk[layer];
374 : :
375 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, TCP);
376 : :
377 [ # # ]: 0 : if (tcp_spec && tcp_mask) {
378 : : input = &outer_input_set;
379 : : /* Check TCP mask and update input set */
380 [ # # ]: 0 : if (tcp_mask->hdr.sent_seq ||
381 [ # # ]: 0 : tcp_mask->hdr.recv_ack ||
382 [ # # ]: 0 : tcp_mask->hdr.data_off ||
383 [ # # ]: 0 : tcp_mask->hdr.tcp_flags ||
384 [ # # ]: 0 : tcp_mask->hdr.rx_win ||
385 [ # # ]: 0 : tcp_mask->hdr.cksum ||
386 [ # # ]: 0 : tcp_mask->hdr.tcp_urp) {
387 : 0 : rte_flow_error_set(error, EINVAL,
388 : : RTE_FLOW_ERROR_TYPE_ITEM,
389 : : item, "Invalid TCP mask");
390 : 0 : return -rte_errno;
391 : : }
392 : :
393 [ # # ]: 0 : if (tcp_mask->hdr.src_port) {
394 : 0 : *input |= IAVF_INSET_TCP_SRC_PORT;
395 : 0 : input_set_byte += 2;
396 : : }
397 [ # # ]: 0 : if (tcp_mask->hdr.dst_port) {
398 : 0 : *input |= IAVF_INSET_TCP_DST_PORT;
399 : 0 : input_set_byte += 2;
400 : : }
401 : :
402 : 0 : memcpy(hdr->buffer_spec, &tcp_spec->hdr,
403 : : sizeof(tcp_spec->hdr));
404 : 0 : memcpy(hdr->buffer_mask, &tcp_mask->hdr,
405 : : sizeof(tcp_mask->hdr));
406 : : }
407 : :
408 : 0 : hdrs->count = ++layer;
409 : 0 : break;
410 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
411 : 0 : vlan_spec = item->spec;
412 : 0 : vlan_mask = item->mask;
413 : :
414 : : hdr = &hdrs->proto_hdr_w_msk[layer];
415 : :
416 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, S_VLAN);
417 : :
418 [ # # ]: 0 : if (vlan_spec && vlan_mask) {
419 : : input = &outer_input_set;
420 : :
421 : 0 : *input |= IAVF_INSET_VLAN_OUTER;
422 : :
423 [ # # ]: 0 : if (vlan_mask->hdr.vlan_tci)
424 : 0 : input_set_byte += 2;
425 : :
426 [ # # ]: 0 : if (vlan_mask->hdr.eth_proto) {
427 : 0 : rte_flow_error_set(error, EINVAL,
428 : : RTE_FLOW_ERROR_TYPE_ITEM,
429 : : item,
430 : : "Invalid VLAN input set.");
431 : 0 : return -rte_errno;
432 : : }
433 : :
434 : 0 : memcpy(hdr->buffer_spec, &vlan_spec->hdr,
435 : : sizeof(vlan_spec->hdr));
436 : 0 : memcpy(hdr->buffer_mask, &vlan_mask->hdr,
437 : : sizeof(vlan_mask->hdr));
438 : : }
439 : :
440 : 0 : hdrs->count = ++layer;
441 : 0 : break;
442 : : case RTE_FLOW_ITEM_TYPE_VOID:
443 : : break;
444 : 0 : default:
445 : 0 : rte_flow_error_set(error, EINVAL,
446 : : RTE_FLOW_ERROR_TYPE_ITEM, pattern,
447 : : "Invalid pattern item.");
448 : 0 : return -rte_errno;
449 : : }
450 : : }
451 : :
452 : 0 : hdrs->count += VIRTCHNL_MAX_NUM_PROTO_HDRS;
453 : :
454 [ # # ]: 0 : if (input_set_byte > MAX_INPUT_SET_BYTE) {
455 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
456 : : item, "too much input set");
457 : 0 : return -rte_errno;
458 : : }
459 : :
460 [ # # # # ]: 0 : if (!outer_input_set || (outer_input_set & ~input_set_mask))
461 : 0 : return -rte_errno;
462 : :
463 : : return 0;
464 : : }
465 : :
466 : : static int
467 : 0 : iavf_fsub_parse_action(struct iavf_adapter *ad,
468 : : const struct rte_flow_action *actions,
469 : : uint32_t priority,
470 : : struct rte_flow_error *error,
471 : : struct iavf_fsub_conf *filter)
472 : : {
473 : : const struct rte_flow_action *action;
474 : : const struct rte_flow_action_ethdev *act_ethdev;
475 : : const struct rte_flow_action_queue *act_q;
476 : : const struct rte_flow_action_rss *act_qgrop;
477 : : struct virtchnl_filter_action *filter_action;
478 : 0 : uint16_t valid_qgrop_number[MAX_QGRP_NUM_TYPE] = {
479 : : 2, 4, 8, 16, 32, 64, 128};
480 : : uint16_t i, num = 0, dest_num = 0, vf_num = 0;
481 : : uint16_t rule_port_id;
482 : :
483 [ # # ]: 0 : for (action = actions; action->type !=
484 : 0 : RTE_FLOW_ACTION_TYPE_END; action++) {
485 [ # # # # : 0 : switch (action->type) {
# ]
486 : : case RTE_FLOW_ACTION_TYPE_VOID:
487 : : break;
488 : :
489 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
490 : 0 : vf_num++;
491 : : filter_action = &filter->sub_fltr.actions.actions[num];
492 : :
493 : 0 : act_ethdev = action->conf;
494 : 0 : rule_port_id = ad->dev_data->port_id;
495 [ # # ]: 0 : if (rule_port_id != act_ethdev->port_id)
496 : 0 : goto error1;
497 : :
498 : 0 : filter->sub_fltr.actions.count = ++num;
499 : 0 : break;
500 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
501 : 0 : dest_num++;
502 : 0 : filter_action = &filter->sub_fltr.actions.actions[num];
503 : :
504 : 0 : act_q = action->conf;
505 [ # # ]: 0 : if (act_q->index >= ad->dev_data->nb_rx_queues)
506 : 0 : goto error2;
507 : :
508 : 0 : filter_action->type = VIRTCHNL_ACTION_QUEUE;
509 : 0 : filter_action->act_conf.queue.index = act_q->index;
510 : 0 : filter->sub_fltr.actions.count = ++num;
511 : 0 : break;
512 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
513 : 0 : dest_num++;
514 : 0 : filter_action = &filter->sub_fltr.actions.actions[num];
515 : :
516 : 0 : act_qgrop = action->conf;
517 [ # # ]: 0 : if (act_qgrop->queue_num <= 1)
518 : 0 : goto error2;
519 : :
520 : 0 : filter_action->type = VIRTCHNL_ACTION_Q_REGION;
521 : 0 : filter_action->act_conf.queue.index =
522 : 0 : act_qgrop->queue[0];
523 [ # # ]: 0 : for (i = 0; i < MAX_QGRP_NUM_TYPE; i++) {
524 : 0 : if (act_qgrop->queue_num ==
525 [ # # ]: 0 : valid_qgrop_number[i])
526 : : break;
527 : : }
528 : :
529 [ # # ]: 0 : if (i == MAX_QGRP_NUM_TYPE)
530 : 0 : goto error2;
531 : :
532 : 0 : if ((act_qgrop->queue[0] + act_qgrop->queue_num) >
533 [ # # ]: 0 : ad->dev_data->nb_rx_queues)
534 : 0 : goto error3;
535 : :
536 [ # # ]: 0 : for (i = 0; i < act_qgrop->queue_num - 1; i++)
537 : 0 : if (act_qgrop->queue[i + 1] !=
538 [ # # ]: 0 : act_qgrop->queue[i] + 1)
539 : 0 : goto error4;
540 : :
541 : 0 : filter_action->act_conf.queue.region = act_qgrop->queue_num;
542 : 0 : filter->sub_fltr.actions.count = ++num;
543 : 0 : break;
544 : 0 : default:
545 : 0 : rte_flow_error_set(error, EINVAL,
546 : : RTE_FLOW_ERROR_TYPE_ACTION,
547 : : actions, "Invalid action type");
548 : 0 : return -rte_errno;
549 : : }
550 : : }
551 : :
552 : : /* 0 denotes lowest priority of recipe and highest priority
553 : : * of rte_flow. Change rte_flow priority into recipe priority.
554 : : */
555 : 0 : filter->sub_fltr.priority = priority;
556 : :
557 [ # # ]: 0 : if (num > VIRTCHNL_MAX_NUM_ACTIONS) {
558 : 0 : rte_flow_error_set(error, EINVAL,
559 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
560 : : "Action numbers exceed the maximum value");
561 : 0 : return -rte_errno;
562 : : }
563 : :
564 [ # # ]: 0 : if (vf_num == 0) {
565 : 0 : rte_flow_error_set(error, EINVAL,
566 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
567 : : "Invalid action, vf action must be added");
568 : 0 : return -rte_errno;
569 : : }
570 : :
571 [ # # ]: 0 : if (dest_num >= 2) {
572 : 0 : rte_flow_error_set(error, EINVAL,
573 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
574 : : "Unsupported action combination");
575 : 0 : return -rte_errno;
576 : : }
577 : :
578 : : return 0;
579 : :
580 : : error1:
581 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
582 : : "Invalid port id");
583 : 0 : return -rte_errno;
584 : :
585 : 0 : error2:
586 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
587 : : "Invalid action type or queue number");
588 : 0 : return -rte_errno;
589 : :
590 : : error3:
591 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
592 : : "Invalid queue region indexes");
593 : 0 : return -rte_errno;
594 : :
595 : : error4:
596 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
597 : : "Discontinuous queue region");
598 : 0 : return -rte_errno;
599 : : }
600 : :
601 : : static int
602 : 0 : iavf_fsub_check_action(const struct rte_flow_action *actions,
603 : : struct rte_flow_error *error)
604 : : {
605 : : const struct rte_flow_action *action;
606 : : enum rte_flow_action_type action_type;
607 : : uint16_t actions_num = 0;
608 : : bool vf_valid = false;
609 : : bool queue_valid = false;
610 : :
611 [ # # ]: 0 : for (action = actions; action->type !=
612 : 0 : RTE_FLOW_ACTION_TYPE_END; action++) {
613 : : action_type = action->type;
614 [ # # # # : 0 : switch (action_type) {
# ]
615 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
616 : : vf_valid = true;
617 : 0 : actions_num++;
618 : 0 : break;
619 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
620 : : case RTE_FLOW_ACTION_TYPE_QUEUE:
621 : : queue_valid = true;
622 : 0 : actions_num++;
623 : 0 : break;
624 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
625 : 0 : actions_num++;
626 : 0 : break;
627 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
628 : 0 : continue;
629 : 0 : default:
630 : 0 : rte_flow_error_set(error, EINVAL,
631 : : RTE_FLOW_ERROR_TYPE_ACTION,
632 : : actions, "Invalid action type");
633 : 0 : return -rte_errno;
634 : : }
635 : : }
636 : :
637 [ # # ]: 0 : if (!((actions_num == 1 && !queue_valid) ||
638 [ # # # # ]: 0 : (actions_num == 2 && vf_valid && queue_valid))) {
639 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
640 : : actions, "Invalid action number");
641 : 0 : return -rte_errno;
642 : : }
643 : :
644 : : return 0;
645 : : }
646 : :
647 : : static int
648 : 0 : iavf_fsub_parse(struct iavf_adapter *ad,
649 : : struct iavf_pattern_match_item *array,
650 : : uint32_t array_len,
651 : : const struct rte_flow_item pattern[],
652 : : const struct rte_flow_action actions[],
653 : : uint32_t priority,
654 : : void **meta,
655 : : struct rte_flow_error *error)
656 : : {
657 : : struct iavf_fsub_conf *filter;
658 : : struct iavf_pattern_match_item *pattern_match_item = NULL;
659 : : int ret = 0;
660 : :
661 : 0 : filter = rte_zmalloc(NULL, sizeof(*filter), 0);
662 [ # # ]: 0 : if (!filter) {
663 : 0 : rte_flow_error_set(error, EINVAL,
664 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
665 : : "No memory for iavf_fsub_conf_ptr");
666 : 0 : return -ENOMEM;
667 : : }
668 : :
669 : : /* search flow subscribe pattern */
670 : 0 : pattern_match_item = iavf_search_pattern_match_item(pattern, array,
671 : : array_len, error);
672 [ # # ]: 0 : if (!pattern_match_item) {
673 : 0 : ret = -rte_errno;
674 : 0 : goto error;
675 : : }
676 : :
677 : : /* parse flow subscribe pattern */
678 : 0 : ret = iavf_fsub_parse_pattern(pattern,
679 : : pattern_match_item->input_set_mask,
680 : : error, filter);
681 [ # # ]: 0 : if (ret)
682 : 0 : goto error;
683 : :
684 : : /* check flow subscribe pattern action */
685 : 0 : ret = iavf_fsub_check_action(actions, error);
686 [ # # ]: 0 : if (ret)
687 : 0 : goto error;
688 : :
689 : : /* parse flow subscribe pattern action */
690 : 0 : ret = iavf_fsub_parse_action((void *)ad, actions, priority,
691 : : error, filter);
692 : :
693 : 0 : error:
694 [ # # ]: 0 : if (!ret && meta)
695 : 0 : *meta = filter;
696 : : else
697 : 0 : rte_free(filter);
698 : :
699 : 0 : rte_free(pattern_match_item);
700 : 0 : return ret;
701 : : }
702 : :
703 : : static int
704 : 0 : iavf_fsub_init(struct iavf_adapter *ad)
705 : : {
706 : : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
707 : : struct iavf_flow_parser *parser;
708 : :
709 [ # # ]: 0 : if (!vf->vf_res)
710 : : return -EINVAL;
711 : :
712 [ # # ]: 0 : if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_FSUB_PF)
713 : : parser = &iavf_fsub_parser;
714 : : else
715 : : return -ENOTSUP;
716 : :
717 : 0 : return iavf_register_parser(parser, ad);
718 : : }
719 : :
720 : : static void
721 : 0 : iavf_fsub_uninit(struct iavf_adapter *ad)
722 : : {
723 : 0 : iavf_unregister_parser(&iavf_fsub_parser, ad);
724 : 0 : }
725 : :
726 : : static struct
727 : : iavf_flow_engine iavf_fsub_engine = {
728 : : .init = iavf_fsub_init,
729 : : .uninit = iavf_fsub_uninit,
730 : : .create = iavf_fsub_create,
731 : : .destroy = iavf_fsub_destroy,
732 : : .validation = iavf_fsub_validation,
733 : : .name = "fsub",
734 : : .type = IAVF_FLOW_ENGINE_FSUB,
735 : : .rule_size = sizeof(struct iavf_fsub_conf),
736 : : };
737 : :
738 : : static struct
739 : : iavf_flow_parser iavf_fsub_parser = {
740 : : .engine = &iavf_fsub_engine,
741 : : .array = iavf_fsub_pattern_list,
742 : : .array_len = RTE_DIM(iavf_fsub_pattern_list),
743 : : .parse_pattern_action = iavf_fsub_parse,
744 : : };
745 : :
746 : 286 : RTE_INIT(iavf_fsub_engine_init)
747 : : {
748 : 286 : iavf_register_flow_engine(&iavf_fsub_engine);
749 : 286 : }
|