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_raw, IAVF_INSET_NONE, IAVF_INSET_NONE},
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 : : rte_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_raw *raw_spec, *raw_mask;
158 : : const struct rte_flow_item_eth *eth_spec, *eth_mask;
159 : : const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
160 : : const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
161 : : const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
162 : : const struct rte_flow_item_udp *udp_spec, *udp_mask;
163 : : const struct rte_flow_item_vlan *vlan_spec, *vlan_mask;
164 : : const struct rte_flow_item *item = pattern;
165 : : struct virtchnl_proto_hdr_w_msk *hdr, *hdr1 = NULL;
166 : : uint64_t outer_input_set = IAVF_INSET_NONE;
167 : : uint64_t *input = NULL;
168 : : uint16_t input_set_byte = 0;
169 : : uint8_t item_num = 0;
170 : : uint32_t layer = 0;
171 : :
172 [ # # ]: 0 : for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
173 [ # # ]: 0 : if (item->last) {
174 : 0 : rte_flow_error_set(error, EINVAL,
175 : : RTE_FLOW_ERROR_TYPE_ITEM,
176 : : item, "Not support range");
177 : 0 : return -rte_errno;
178 : : }
179 : :
180 : : item_type = item->type;
181 : 0 : item_num++;
182 : :
183 [ # # # # : 0 : switch (item_type) {
# # # #
# ]
184 : 0 : case RTE_FLOW_ITEM_TYPE_RAW: {
185 : 0 : raw_spec = item->spec;
186 : 0 : raw_mask = item->mask;
187 : :
188 [ # # ]: 0 : if (!raw_spec || !raw_mask) {
189 : 0 : PMD_DRV_LOG(ERR, "NULL RAW spec/mask");
190 : 0 : rte_flow_error_set(error, EINVAL,
191 : : RTE_FLOW_ERROR_TYPE_ITEM,
192 : : item, "NULL RAW spec/mask");
193 : 0 : return -rte_errno;
194 : : }
195 : :
196 [ # # ]: 0 : if (item_num != 1)
197 : 0 : return -rte_errno;
198 : :
199 [ # # ]: 0 : if (raw_spec->length != raw_mask->length)
200 : 0 : return -rte_errno;
201 : :
202 : : uint16_t pkt_len = 0;
203 : : uint16_t tmp_val = 0;
204 : : uint8_t tmp = 0;
205 : : int i, j;
206 : :
207 : : pkt_len = raw_spec->length;
208 : :
209 [ # # ]: 0 : for (i = 0, j = 0; i < pkt_len; i += 2, j++) {
210 : 0 : tmp = raw_spec->pattern[i];
211 [ # # ]: 0 : if (tmp >= 'a' && tmp <= 'f')
212 : 0 : tmp_val = tmp - 'a' + 10;
213 [ # # ]: 0 : if (tmp >= 'A' && tmp <= 'F')
214 : 0 : tmp_val = tmp - 'A' + 10;
215 [ # # ]: 0 : if (tmp >= '0' && tmp <= '9')
216 : 0 : tmp_val = tmp - '0';
217 : :
218 : 0 : tmp_val *= 16;
219 : 0 : tmp = raw_spec->pattern[i + 1];
220 [ # # ]: 0 : if (tmp >= 'a' && tmp <= 'f')
221 : 0 : tmp_val += (tmp - 'a' + 10);
222 [ # # ]: 0 : if (tmp >= 'A' && tmp <= 'F')
223 : 0 : tmp_val += (tmp - 'A' + 10);
224 [ # # ]: 0 : if (tmp >= '0' && tmp <= '9')
225 : 0 : tmp_val += (tmp - '0');
226 : :
227 : 0 : hdrs->raw.spec[j] = tmp_val;
228 : :
229 : 0 : tmp = raw_mask->pattern[i];
230 [ # # ]: 0 : if (tmp >= 'a' && tmp <= 'f')
231 : 0 : tmp_val = tmp - 'a' + 10;
232 [ # # ]: 0 : if (tmp >= 'A' && tmp <= 'F')
233 : 0 : tmp_val = tmp - 'A' + 10;
234 [ # # ]: 0 : if (tmp >= '0' && tmp <= '9')
235 : 0 : tmp_val = tmp - '0';
236 : :
237 : 0 : tmp_val *= 16;
238 : 0 : tmp = raw_mask->pattern[i + 1];
239 [ # # ]: 0 : if (tmp >= 'a' && tmp <= 'f')
240 : 0 : tmp_val += (tmp - 'a' + 10);
241 [ # # ]: 0 : if (tmp >= 'A' && tmp <= 'F')
242 : 0 : tmp_val += (tmp - 'A' + 10);
243 [ # # ]: 0 : if (tmp >= '0' && tmp <= '9')
244 : 0 : tmp_val += (tmp - '0');
245 : :
246 : 0 : hdrs->raw.mask[j] = tmp_val;
247 : : }
248 : :
249 : 0 : hdrs->raw.pkt_len = pkt_len / 2;
250 : 0 : hdrs->tunnel_level = 0;
251 : 0 : hdrs->count = 0;
252 : 0 : return 0;
253 : : }
254 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
255 : 0 : eth_spec = item->spec;
256 : 0 : eth_mask = item->mask;
257 : :
258 : : hdr1 = &hdrs->proto_hdr_w_msk[layer];
259 : :
260 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, ETH);
261 : :
262 [ # # ]: 0 : if (eth_spec && eth_mask) {
263 : : input = &outer_input_set;
264 : :
265 [ # # ]: 0 : if (!rte_is_zero_ether_addr(ð_mask->hdr.dst_addr)) {
266 : 0 : *input |= IAVF_INSET_DMAC;
267 : 0 : input_set_byte += 6;
268 : : } else {
269 : : /* flow subscribe filter will add dst mac in kernel */
270 : 0 : input_set_byte += 6;
271 : : }
272 : :
273 [ # # ]: 0 : if (!rte_is_zero_ether_addr(ð_mask->hdr.src_addr)) {
274 : 0 : *input |= IAVF_INSET_SMAC;
275 : 0 : input_set_byte += 6;
276 : : }
277 : :
278 [ # # ]: 0 : if (eth_mask->hdr.ether_type) {
279 : 0 : *input |= IAVF_INSET_ETHERTYPE;
280 : 0 : input_set_byte += 2;
281 : : }
282 : :
283 [ # # ]: 0 : rte_memcpy(hdr1->buffer_spec, eth_spec,
284 : : sizeof(struct rte_ether_hdr));
285 [ # # ]: 0 : rte_memcpy(hdr1->buffer_mask, eth_mask,
286 : : sizeof(struct rte_ether_hdr));
287 : : } else {
288 : : /* flow subscribe filter will add dst mac in kernel */
289 : 0 : input_set_byte += 6;
290 : : }
291 : :
292 : 0 : hdrs->count = ++layer;
293 : 0 : break;
294 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
295 : 0 : ipv4_spec = item->spec;
296 : 0 : ipv4_mask = item->mask;
297 : :
298 : : hdr = &hdrs->proto_hdr_w_msk[layer];
299 : :
300 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV4);
301 : :
302 [ # # ]: 0 : if (ipv4_spec && ipv4_mask) {
303 : : input = &outer_input_set;
304 : : /* Check IPv4 mask and update input set */
305 [ # # ]: 0 : if (ipv4_mask->hdr.version_ihl ||
306 [ # # ]: 0 : ipv4_mask->hdr.total_length ||
307 [ # # ]: 0 : ipv4_mask->hdr.packet_id ||
308 [ # # ]: 0 : ipv4_mask->hdr.hdr_checksum) {
309 : 0 : rte_flow_error_set(error, EINVAL,
310 : : RTE_FLOW_ERROR_TYPE_ITEM,
311 : : item, "Invalid IPv4 mask.");
312 : 0 : return -rte_errno;
313 : : }
314 : :
315 [ # # ]: 0 : if (ipv4_mask->hdr.src_addr) {
316 : 0 : *input |= IAVF_INSET_IPV4_SRC;
317 : 0 : input_set_byte += 4;
318 : : }
319 [ # # ]: 0 : if (ipv4_mask->hdr.dst_addr) {
320 : 0 : *input |= IAVF_INSET_IPV4_DST;
321 : 0 : input_set_byte += 4;
322 : : }
323 [ # # ]: 0 : if (ipv4_mask->hdr.time_to_live) {
324 : 0 : *input |= IAVF_INSET_IPV4_TTL;
325 : 0 : input_set_byte++;
326 : : }
327 [ # # ]: 0 : if (ipv4_mask->hdr.next_proto_id) {
328 : 0 : *input |= IAVF_INSET_IPV4_PROTO;
329 : 0 : input_set_byte++;
330 : : }
331 [ # # ]: 0 : if (ipv4_mask->hdr.type_of_service) {
332 : 0 : *input |= IAVF_INSET_IPV4_TOS;
333 : 0 : input_set_byte++;
334 : : }
335 : :
336 [ # # ]: 0 : rte_memcpy(hdr->buffer_spec, &ipv4_spec->hdr,
337 : : sizeof(ipv4_spec->hdr));
338 [ # # ]: 0 : rte_memcpy(hdr->buffer_mask, &ipv4_mask->hdr,
339 : : sizeof(ipv4_spec->hdr));
340 : : }
341 : :
342 : 0 : hdrs->count = ++layer;
343 : 0 : break;
344 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6: {
345 : : int j;
346 : :
347 : 0 : ipv6_spec = item->spec;
348 : 0 : ipv6_mask = item->mask;
349 : :
350 : : hdr = &hdrs->proto_hdr_w_msk[layer];
351 : :
352 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV6);
353 : :
354 [ # # ]: 0 : if (ipv6_spec && ipv6_mask) {
355 : : input = &outer_input_set;
356 : :
357 [ # # ]: 0 : if (ipv6_mask->hdr.payload_len) {
358 : 0 : rte_flow_error_set(error, EINVAL,
359 : : RTE_FLOW_ERROR_TYPE_ITEM,
360 : : item, "Invalid IPv6 mask");
361 : 0 : return -rte_errno;
362 : : }
363 : :
364 [ # # ]: 0 : for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
365 [ # # ]: 0 : if (ipv6_mask->hdr.src_addr.a[j]) {
366 : 0 : *input |= IAVF_INSET_IPV6_SRC;
367 : 0 : break;
368 : : }
369 : : }
370 [ # # ]: 0 : for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
371 [ # # ]: 0 : if (ipv6_mask->hdr.dst_addr.a[j]) {
372 : 0 : *input |= IAVF_INSET_IPV6_DST;
373 : 0 : break;
374 : : }
375 : : }
376 : :
377 [ # # ]: 0 : for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
378 [ # # ]: 0 : if (ipv6_mask->hdr.src_addr.a[j])
379 : 0 : input_set_byte++;
380 : :
381 [ # # ]: 0 : if (ipv6_mask->hdr.dst_addr.a[j])
382 : 0 : input_set_byte++;
383 : : }
384 : :
385 [ # # ]: 0 : if (ipv6_mask->hdr.proto) {
386 : 0 : *input |= IAVF_INSET_IPV6_NEXT_HDR;
387 : 0 : input_set_byte++;
388 : : }
389 [ # # ]: 0 : if (ipv6_mask->hdr.hop_limits) {
390 : 0 : *input |= IAVF_INSET_IPV6_HOP_LIMIT;
391 : 0 : input_set_byte++;
392 : : }
393 [ # # ]: 0 : if (ipv6_mask->hdr.vtc_flow &
394 : : rte_cpu_to_be_32(RTE_IPV6_HDR_TC_MASK)) {
395 : 0 : *input |= IAVF_INSET_IPV6_TC;
396 : 0 : input_set_byte += 4;
397 : : }
398 : :
399 [ # # ]: 0 : rte_memcpy(hdr->buffer_spec, &ipv6_spec->hdr,
400 : : sizeof(ipv6_spec->hdr));
401 [ # # ]: 0 : rte_memcpy(hdr->buffer_mask, &ipv6_mask->hdr,
402 : : sizeof(ipv6_spec->hdr));
403 : : }
404 : :
405 : 0 : hdrs->count = ++layer;
406 : 0 : break;
407 : : }
408 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
409 : 0 : udp_spec = item->spec;
410 : 0 : udp_mask = item->mask;
411 : :
412 : : hdr = &hdrs->proto_hdr_w_msk[layer];
413 : :
414 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, UDP);
415 : :
416 [ # # ]: 0 : if (udp_spec && udp_mask) {
417 : : input = &outer_input_set;
418 : : /* Check UDP mask and update input set*/
419 [ # # ]: 0 : if (udp_mask->hdr.dgram_len ||
420 [ # # ]: 0 : udp_mask->hdr.dgram_cksum) {
421 : 0 : rte_flow_error_set(error, EINVAL,
422 : : RTE_FLOW_ERROR_TYPE_ITEM,
423 : : item, "Invalid UDP mask");
424 : 0 : return -rte_errno;
425 : : }
426 : :
427 [ # # ]: 0 : if (udp_mask->hdr.src_port) {
428 : 0 : *input |= IAVF_INSET_UDP_SRC_PORT;
429 : 0 : input_set_byte += 2;
430 : : }
431 [ # # ]: 0 : if (udp_mask->hdr.dst_port) {
432 : 0 : *input |= IAVF_INSET_UDP_DST_PORT;
433 : 0 : input_set_byte += 2;
434 : : }
435 : :
436 [ # # ]: 0 : rte_memcpy(hdr->buffer_spec, &udp_spec->hdr,
437 : : sizeof(udp_spec->hdr));
438 [ # # ]: 0 : rte_memcpy(hdr->buffer_mask, &udp_mask->hdr,
439 : : sizeof(udp_mask->hdr));
440 : : }
441 : :
442 : 0 : hdrs->count = ++layer;
443 : 0 : break;
444 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
445 : 0 : tcp_spec = item->spec;
446 : 0 : tcp_mask = item->mask;
447 : :
448 : : hdr = &hdrs->proto_hdr_w_msk[layer];
449 : :
450 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, TCP);
451 : :
452 [ # # ]: 0 : if (tcp_spec && tcp_mask) {
453 : : input = &outer_input_set;
454 : : /* Check TCP mask and update input set */
455 [ # # ]: 0 : if (tcp_mask->hdr.sent_seq ||
456 [ # # ]: 0 : tcp_mask->hdr.recv_ack ||
457 [ # # ]: 0 : tcp_mask->hdr.data_off ||
458 [ # # ]: 0 : tcp_mask->hdr.tcp_flags ||
459 [ # # ]: 0 : tcp_mask->hdr.rx_win ||
460 [ # # ]: 0 : tcp_mask->hdr.cksum ||
461 [ # # ]: 0 : tcp_mask->hdr.tcp_urp) {
462 : 0 : rte_flow_error_set(error, EINVAL,
463 : : RTE_FLOW_ERROR_TYPE_ITEM,
464 : : item, "Invalid TCP mask");
465 : 0 : return -rte_errno;
466 : : }
467 : :
468 [ # # ]: 0 : if (tcp_mask->hdr.src_port) {
469 : 0 : *input |= IAVF_INSET_TCP_SRC_PORT;
470 : 0 : input_set_byte += 2;
471 : : }
472 [ # # ]: 0 : if (tcp_mask->hdr.dst_port) {
473 : 0 : *input |= IAVF_INSET_TCP_DST_PORT;
474 : 0 : input_set_byte += 2;
475 : : }
476 : :
477 [ # # ]: 0 : rte_memcpy(hdr->buffer_spec, &tcp_spec->hdr,
478 : : sizeof(tcp_spec->hdr));
479 [ # # ]: 0 : rte_memcpy(hdr->buffer_mask, &tcp_mask->hdr,
480 : : sizeof(tcp_mask->hdr));
481 : : }
482 : :
483 : 0 : hdrs->count = ++layer;
484 : 0 : break;
485 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
486 : 0 : vlan_spec = item->spec;
487 : 0 : vlan_mask = item->mask;
488 : :
489 : : hdr = &hdrs->proto_hdr_w_msk[layer];
490 : :
491 : 0 : VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, S_VLAN);
492 : :
493 [ # # ]: 0 : if (vlan_spec && vlan_mask) {
494 : : input = &outer_input_set;
495 : :
496 : 0 : *input |= IAVF_INSET_VLAN_OUTER;
497 : :
498 [ # # ]: 0 : if (vlan_mask->hdr.vlan_tci)
499 : 0 : input_set_byte += 2;
500 : :
501 [ # # ]: 0 : if (vlan_mask->hdr.eth_proto) {
502 : 0 : rte_flow_error_set(error, EINVAL,
503 : : RTE_FLOW_ERROR_TYPE_ITEM,
504 : : item,
505 : : "Invalid VLAN input set.");
506 : 0 : return -rte_errno;
507 : : }
508 : :
509 [ # # ]: 0 : rte_memcpy(hdr->buffer_spec, &vlan_spec->hdr,
510 : : sizeof(vlan_spec->hdr));
511 [ # # ]: 0 : rte_memcpy(hdr->buffer_mask, &vlan_mask->hdr,
512 : : sizeof(vlan_mask->hdr));
513 : : }
514 : :
515 : 0 : hdrs->count = ++layer;
516 : 0 : break;
517 : : case RTE_FLOW_ITEM_TYPE_VOID:
518 : : break;
519 : 0 : default:
520 : 0 : rte_flow_error_set(error, EINVAL,
521 : : RTE_FLOW_ERROR_TYPE_ITEM, pattern,
522 : : "Invalid pattern item.");
523 : 0 : return -rte_errno;
524 : : }
525 : : }
526 : :
527 : 0 : hdrs->count += VIRTCHNL_MAX_NUM_PROTO_HDRS;
528 : :
529 [ # # ]: 0 : if (input_set_byte > MAX_INPUT_SET_BYTE) {
530 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
531 : : item, "too much input set");
532 : 0 : return -rte_errno;
533 : : }
534 : :
535 [ # # # # ]: 0 : if (!outer_input_set || (outer_input_set & ~input_set_mask))
536 : 0 : return -rte_errno;
537 : :
538 : : return 0;
539 : : }
540 : :
541 : : static int
542 : 0 : iavf_fsub_parse_action(struct iavf_adapter *ad,
543 : : const struct rte_flow_action *actions,
544 : : uint32_t priority,
545 : : struct rte_flow_error *error,
546 : : struct iavf_fsub_conf *filter)
547 : : {
548 : : const struct rte_flow_action *action;
549 : : const struct rte_flow_action_ethdev *act_ethdev;
550 : : const struct rte_flow_action_queue *act_q;
551 : : const struct rte_flow_action_rss *act_qgrop;
552 : : struct virtchnl_filter_action *filter_action;
553 : 0 : uint16_t valid_qgrop_number[MAX_QGRP_NUM_TYPE] = {
554 : : 2, 4, 8, 16, 32, 64, 128};
555 : : uint16_t i, num = 0, dest_num = 0, vf_num = 0;
556 : : uint16_t rule_port_id;
557 : :
558 [ # # ]: 0 : for (action = actions; action->type !=
559 : 0 : RTE_FLOW_ACTION_TYPE_END; action++) {
560 [ # # # # : 0 : switch (action->type) {
# ]
561 : : case RTE_FLOW_ACTION_TYPE_VOID:
562 : : break;
563 : :
564 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
565 : 0 : vf_num++;
566 : : filter_action = &filter->sub_fltr.actions.actions[num];
567 : :
568 : 0 : act_ethdev = action->conf;
569 : 0 : rule_port_id = ad->dev_data->port_id;
570 [ # # ]: 0 : if (rule_port_id != act_ethdev->port_id)
571 : 0 : goto error1;
572 : :
573 : 0 : filter->sub_fltr.actions.count = ++num;
574 : 0 : break;
575 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
576 : 0 : dest_num++;
577 : 0 : filter_action = &filter->sub_fltr.actions.actions[num];
578 : :
579 : 0 : act_q = action->conf;
580 [ # # ]: 0 : if (act_q->index >= ad->dev_data->nb_rx_queues)
581 : 0 : goto error2;
582 : :
583 : 0 : filter_action->type = VIRTCHNL_ACTION_QUEUE;
584 : 0 : filter_action->act_conf.queue.index = act_q->index;
585 : 0 : filter->sub_fltr.actions.count = ++num;
586 : 0 : break;
587 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
588 : 0 : dest_num++;
589 : 0 : filter_action = &filter->sub_fltr.actions.actions[num];
590 : :
591 : 0 : act_qgrop = action->conf;
592 [ # # ]: 0 : if (act_qgrop->queue_num <= 1)
593 : 0 : goto error2;
594 : :
595 : 0 : filter_action->type = VIRTCHNL_ACTION_Q_REGION;
596 : 0 : filter_action->act_conf.queue.index =
597 : 0 : act_qgrop->queue[0];
598 [ # # ]: 0 : for (i = 0; i < MAX_QGRP_NUM_TYPE; i++) {
599 : 0 : if (act_qgrop->queue_num ==
600 [ # # ]: 0 : valid_qgrop_number[i])
601 : : break;
602 : : }
603 : :
604 [ # # ]: 0 : if (i == MAX_QGRP_NUM_TYPE)
605 : 0 : goto error2;
606 : :
607 : 0 : if ((act_qgrop->queue[0] + act_qgrop->queue_num) >
608 [ # # ]: 0 : ad->dev_data->nb_rx_queues)
609 : 0 : goto error3;
610 : :
611 [ # # ]: 0 : for (i = 0; i < act_qgrop->queue_num - 1; i++)
612 : 0 : if (act_qgrop->queue[i + 1] !=
613 [ # # ]: 0 : act_qgrop->queue[i] + 1)
614 : 0 : goto error4;
615 : :
616 : 0 : filter_action->act_conf.queue.region = act_qgrop->queue_num;
617 : 0 : filter->sub_fltr.actions.count = ++num;
618 : 0 : break;
619 : 0 : default:
620 : 0 : rte_flow_error_set(error, EINVAL,
621 : : RTE_FLOW_ERROR_TYPE_ACTION,
622 : : actions, "Invalid action type");
623 : 0 : return -rte_errno;
624 : : }
625 : : }
626 : :
627 : : /* 0 denotes lowest priority of recipe and highest priority
628 : : * of rte_flow. Change rte_flow priority into recipe priority.
629 : : */
630 : 0 : filter->sub_fltr.priority = priority;
631 : :
632 [ # # ]: 0 : if (num > VIRTCHNL_MAX_NUM_ACTIONS) {
633 : 0 : rte_flow_error_set(error, EINVAL,
634 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
635 : : "Action numbers exceed the maximum value");
636 : 0 : return -rte_errno;
637 : : }
638 : :
639 [ # # ]: 0 : if (vf_num == 0) {
640 : 0 : rte_flow_error_set(error, EINVAL,
641 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
642 : : "Invalid action, vf action must be added");
643 : 0 : return -rte_errno;
644 : : }
645 : :
646 [ # # ]: 0 : if (dest_num >= 2) {
647 : 0 : rte_flow_error_set(error, EINVAL,
648 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
649 : : "Unsupported action combination");
650 : 0 : return -rte_errno;
651 : : }
652 : :
653 : : return 0;
654 : :
655 : : error1:
656 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
657 : : "Invalid port id");
658 : 0 : return -rte_errno;
659 : :
660 : 0 : error2:
661 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
662 : : "Invalid action type or queue number");
663 : 0 : return -rte_errno;
664 : :
665 : : error3:
666 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
667 : : "Invalid queue region indexes");
668 : 0 : return -rte_errno;
669 : :
670 : : error4:
671 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions,
672 : : "Discontinuous queue region");
673 : 0 : return -rte_errno;
674 : : }
675 : :
676 : : static int
677 : 0 : iavf_fsub_check_action(const struct rte_flow_action *actions,
678 : : struct rte_flow_error *error)
679 : : {
680 : : const struct rte_flow_action *action;
681 : : enum rte_flow_action_type action_type;
682 : : uint16_t actions_num = 0;
683 : : bool vf_valid = false;
684 : : bool queue_valid = false;
685 : :
686 [ # # ]: 0 : for (action = actions; action->type !=
687 : 0 : RTE_FLOW_ACTION_TYPE_END; action++) {
688 : : action_type = action->type;
689 [ # # # # : 0 : switch (action_type) {
# ]
690 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
691 : : vf_valid = true;
692 : 0 : actions_num++;
693 : 0 : break;
694 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
695 : : case RTE_FLOW_ACTION_TYPE_QUEUE:
696 : : queue_valid = true;
697 : 0 : actions_num++;
698 : 0 : break;
699 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
700 : 0 : actions_num++;
701 : 0 : break;
702 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
703 : 0 : continue;
704 : 0 : default:
705 : 0 : rte_flow_error_set(error, EINVAL,
706 : : RTE_FLOW_ERROR_TYPE_ACTION,
707 : : actions, "Invalid action type");
708 : 0 : return -rte_errno;
709 : : }
710 : : }
711 : :
712 [ # # ]: 0 : if (!((actions_num == 1 && !queue_valid) ||
713 [ # # # # ]: 0 : (actions_num == 2 && vf_valid && queue_valid))) {
714 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
715 : : actions, "Invalid action number");
716 : 0 : return -rte_errno;
717 : : }
718 : :
719 : : return 0;
720 : : }
721 : :
722 : : static int
723 : 0 : iavf_fsub_parse(struct iavf_adapter *ad,
724 : : struct iavf_pattern_match_item *array,
725 : : uint32_t array_len,
726 : : const struct rte_flow_item pattern[],
727 : : const struct rte_flow_action actions[],
728 : : uint32_t priority,
729 : : void **meta,
730 : : struct rte_flow_error *error)
731 : : {
732 : : struct iavf_fsub_conf *filter;
733 : : struct iavf_pattern_match_item *pattern_match_item = NULL;
734 : : int ret = 0;
735 : :
736 : 0 : filter = rte_zmalloc(NULL, sizeof(*filter), 0);
737 [ # # ]: 0 : if (!filter) {
738 : 0 : rte_flow_error_set(error, EINVAL,
739 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
740 : : "No memory for iavf_fsub_conf_ptr");
741 : 0 : return -ENOMEM;
742 : : }
743 : :
744 : : /* search flow subscribe pattern */
745 : 0 : pattern_match_item = iavf_search_pattern_match_item(pattern, array,
746 : : array_len, error);
747 [ # # ]: 0 : if (!pattern_match_item) {
748 : 0 : ret = -rte_errno;
749 : 0 : goto error;
750 : : }
751 : :
752 : : /* parse flow subscribe pattern */
753 : 0 : ret = iavf_fsub_parse_pattern(pattern,
754 : : pattern_match_item->input_set_mask,
755 : : error, filter);
756 [ # # ]: 0 : if (ret)
757 : 0 : goto error;
758 : :
759 : : /* check flow subscribe pattern action */
760 : 0 : ret = iavf_fsub_check_action(actions, error);
761 [ # # ]: 0 : if (ret)
762 : 0 : goto error;
763 : :
764 : : /* parse flow subscribe pattern action */
765 : 0 : ret = iavf_fsub_parse_action((void *)ad, actions, priority,
766 : : error, filter);
767 : :
768 : 0 : error:
769 [ # # ]: 0 : if (!ret && meta)
770 : 0 : *meta = filter;
771 : : else
772 : 0 : rte_free(filter);
773 : :
774 : 0 : rte_free(pattern_match_item);
775 : 0 : return ret;
776 : : }
777 : :
778 : : static int
779 : 0 : iavf_fsub_init(struct iavf_adapter *ad)
780 : : {
781 : : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
782 : : struct iavf_flow_parser *parser;
783 : :
784 [ # # ]: 0 : if (!vf->vf_res)
785 : : return -EINVAL;
786 : :
787 [ # # ]: 0 : if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_FSUB_PF)
788 : : parser = &iavf_fsub_parser;
789 : : else
790 : : return -ENOTSUP;
791 : :
792 : 0 : return iavf_register_parser(parser, ad);
793 : : }
794 : :
795 : : static void
796 : 0 : iavf_fsub_uninit(struct iavf_adapter *ad)
797 : : {
798 : 0 : iavf_unregister_parser(&iavf_fsub_parser, ad);
799 : 0 : }
800 : :
801 : : static struct
802 : : iavf_flow_engine iavf_fsub_engine = {
803 : : .init = iavf_fsub_init,
804 : : .uninit = iavf_fsub_uninit,
805 : : .create = iavf_fsub_create,
806 : : .destroy = iavf_fsub_destroy,
807 : : .validation = iavf_fsub_validation,
808 : : .type = IAVF_FLOW_ENGINE_FSUB,
809 : : };
810 : :
811 : : static struct
812 : : iavf_flow_parser iavf_fsub_parser = {
813 : : .engine = &iavf_fsub_engine,
814 : : .array = iavf_fsub_pattern_list,
815 : : .array_len = RTE_DIM(iavf_fsub_pattern_list),
816 : : .parse_pattern_action = iavf_fsub_parse,
817 : : };
818 : :
819 : 276 : RTE_INIT(iavf_fsub_engine_init)
820 : : {
821 : 276 : iavf_register_flow_engine(&iavf_fsub_engine);
822 : 276 : }
|