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