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