1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2018-2020 NXP
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
13 #include <rte_ethdev.h>
14 #include <rte_log.h>
15 #include <rte_malloc.h>
16 #include <rte_flow_driver.h>
17 #include <rte_tailq.h>
18
19 #include <fsl_dpni.h>
20 #include <fsl_dpkg.h>
21
22 #include <dpaa2_ethdev.h>
23 #include <dpaa2_pmd_logs.h>
24
25 /* Workaround to discriminate the UDP/TCP/SCTP
26 * with next protocol of l3.
27 * MC/WRIOP are not able to identify
28 * the l4 protocol with l4 ports.
29 */
30 int mc_l4_port_identification;
31
32 static char *dpaa2_flow_control_log;
33 static int dpaa2_flow_miss_flow_id =
34 DPNI_FS_MISS_DROP;
35
36 #define FIXED_ENTRY_SIZE 54
37
38 enum flow_rule_ipaddr_type {
39 FLOW_NONE_IPADDR,
40 FLOW_IPV4_ADDR,
41 FLOW_IPV6_ADDR
42 };
43
44 struct flow_rule_ipaddr {
45 enum flow_rule_ipaddr_type ipaddr_type;
46 int qos_ipsrc_offset;
47 int qos_ipdst_offset;
48 int fs_ipsrc_offset;
49 int fs_ipdst_offset;
50 };
51
52 struct rte_flow {
53 LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
54 struct dpni_rule_cfg qos_rule;
55 struct dpni_rule_cfg fs_rule;
56 uint8_t qos_real_key_size;
57 uint8_t fs_real_key_size;
58 uint8_t tc_id; /** Traffic Class ID. */
59 uint8_t tc_index; /** index within this Traffic Class. */
60 enum rte_flow_action_type action;
61 /* Special for IP address to specify the offset
62 * in key/mask.
63 */
64 struct flow_rule_ipaddr ipaddr_rule;
65 struct dpni_fs_action_cfg action_cfg;
66 };
67
68 static const
69 enum rte_flow_item_type dpaa2_supported_pattern_type[] = {
70 RTE_FLOW_ITEM_TYPE_END,
71 RTE_FLOW_ITEM_TYPE_ETH,
72 RTE_FLOW_ITEM_TYPE_VLAN,
73 RTE_FLOW_ITEM_TYPE_IPV4,
74 RTE_FLOW_ITEM_TYPE_IPV6,
75 RTE_FLOW_ITEM_TYPE_ICMP,
76 RTE_FLOW_ITEM_TYPE_UDP,
77 RTE_FLOW_ITEM_TYPE_TCP,
78 RTE_FLOW_ITEM_TYPE_SCTP,
79 RTE_FLOW_ITEM_TYPE_GRE,
80 };
81
82 static const
83 enum rte_flow_action_type dpaa2_supported_action_type[] = {
84 RTE_FLOW_ACTION_TYPE_END,
85 RTE_FLOW_ACTION_TYPE_QUEUE,
86 RTE_FLOW_ACTION_TYPE_RSS
87 };
88
89 /* Max of enum rte_flow_item_type + 1, for both IPv4 and IPv6*/
90 #define DPAA2_FLOW_ITEM_TYPE_GENERIC_IP (RTE_FLOW_ITEM_TYPE_META + 1)
91
92 enum rte_filter_type dpaa2_filter_type = RTE_ETH_FILTER_NONE;
93
94 #ifndef __cplusplus
95 static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = {
96 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
97 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
98 .type = RTE_BE16(0xffff),
99 };
100
101 static const struct rte_flow_item_vlan dpaa2_flow_item_vlan_mask = {
102 .tci = RTE_BE16(0xffff),
103 };
104
105 static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = {
106 .hdr.src_addr = RTE_BE32(0xffffffff),
107 .hdr.dst_addr = RTE_BE32(0xffffffff),
108 .hdr.next_proto_id = 0xff,
109 };
110
111 static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = {
112 .hdr = {
113 .src_addr =
114 "\xff\xff\xff\xff\xff\xff\xff\xff"
115 "\xff\xff\xff\xff\xff\xff\xff\xff",
116 .dst_addr =
117 "\xff\xff\xff\xff\xff\xff\xff\xff"
118 "\xff\xff\xff\xff\xff\xff\xff\xff",
119 .proto = 0xff
120 },
121 };
122
123 static const struct rte_flow_item_icmp dpaa2_flow_item_icmp_mask = {
124 .hdr.icmp_type = 0xff,
125 .hdr.icmp_code = 0xff,
126 };
127
128 static const struct rte_flow_item_udp dpaa2_flow_item_udp_mask = {
129 .hdr = {
130 .src_port = RTE_BE16(0xffff),
131 .dst_port = RTE_BE16(0xffff),
132 },
133 };
134
135 static const struct rte_flow_item_tcp dpaa2_flow_item_tcp_mask = {
136 .hdr = {
137 .src_port = RTE_BE16(0xffff),
138 .dst_port = RTE_BE16(0xffff),
139 },
140 };
141
142 static const struct rte_flow_item_sctp dpaa2_flow_item_sctp_mask = {
143 .hdr = {
144 .src_port = RTE_BE16(0xffff),
145 .dst_port = RTE_BE16(0xffff),
146 },
147 };
148
149 static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = {
150 .protocol = RTE_BE16(0xffff),
151 };
152
153 #endif
154
dpaa2_prot_field_string(enum net_prot prot,uint32_t field,char * string)155 static inline void dpaa2_prot_field_string(
156 enum net_prot prot, uint32_t field,
157 char *string)
158 {
159 if (!dpaa2_flow_control_log)
160 return;
161
162 if (prot == NET_PROT_ETH) {
163 strcpy(string, "eth");
164 if (field == NH_FLD_ETH_DA)
165 strcat(string, ".dst");
166 else if (field == NH_FLD_ETH_SA)
167 strcat(string, ".src");
168 else if (field == NH_FLD_ETH_TYPE)
169 strcat(string, ".type");
170 else
171 strcat(string, ".unknown field");
172 } else if (prot == NET_PROT_VLAN) {
173 strcpy(string, "vlan");
174 if (field == NH_FLD_VLAN_TCI)
175 strcat(string, ".tci");
176 else
177 strcat(string, ".unknown field");
178 } else if (prot == NET_PROT_IP) {
179 strcpy(string, "ip");
180 if (field == NH_FLD_IP_SRC)
181 strcat(string, ".src");
182 else if (field == NH_FLD_IP_DST)
183 strcat(string, ".dst");
184 else if (field == NH_FLD_IP_PROTO)
185 strcat(string, ".proto");
186 else
187 strcat(string, ".unknown field");
188 } else if (prot == NET_PROT_TCP) {
189 strcpy(string, "tcp");
190 if (field == NH_FLD_TCP_PORT_SRC)
191 strcat(string, ".src");
192 else if (field == NH_FLD_TCP_PORT_DST)
193 strcat(string, ".dst");
194 else
195 strcat(string, ".unknown field");
196 } else if (prot == NET_PROT_UDP) {
197 strcpy(string, "udp");
198 if (field == NH_FLD_UDP_PORT_SRC)
199 strcat(string, ".src");
200 else if (field == NH_FLD_UDP_PORT_DST)
201 strcat(string, ".dst");
202 else
203 strcat(string, ".unknown field");
204 } else if (prot == NET_PROT_ICMP) {
205 strcpy(string, "icmp");
206 if (field == NH_FLD_ICMP_TYPE)
207 strcat(string, ".type");
208 else if (field == NH_FLD_ICMP_CODE)
209 strcat(string, ".code");
210 else
211 strcat(string, ".unknown field");
212 } else if (prot == NET_PROT_SCTP) {
213 strcpy(string, "sctp");
214 if (field == NH_FLD_SCTP_PORT_SRC)
215 strcat(string, ".src");
216 else if (field == NH_FLD_SCTP_PORT_DST)
217 strcat(string, ".dst");
218 else
219 strcat(string, ".unknown field");
220 } else if (prot == NET_PROT_GRE) {
221 strcpy(string, "gre");
222 if (field == NH_FLD_GRE_TYPE)
223 strcat(string, ".type");
224 else
225 strcat(string, ".unknown field");
226 } else {
227 strcpy(string, "unknown protocol");
228 }
229 }
230
dpaa2_flow_qos_table_extracts_log(const struct dpaa2_dev_priv * priv)231 static inline void dpaa2_flow_qos_table_extracts_log(
232 const struct dpaa2_dev_priv *priv)
233 {
234 int idx;
235 char string[32];
236
237 if (!dpaa2_flow_control_log)
238 return;
239
240 printf("Setup QoS table: number of extracts: %d\r\n",
241 priv->extract.qos_key_extract.dpkg.num_extracts);
242 for (idx = 0; idx < priv->extract.qos_key_extract.dpkg.num_extracts;
243 idx++) {
244 dpaa2_prot_field_string(priv->extract.qos_key_extract.dpkg
245 .extracts[idx].extract.from_hdr.prot,
246 priv->extract.qos_key_extract.dpkg.extracts[idx]
247 .extract.from_hdr.field,
248 string);
249 printf("%s", string);
250 if ((idx + 1) < priv->extract.qos_key_extract.dpkg.num_extracts)
251 printf(" / ");
252 }
253 printf("\r\n");
254 }
255
dpaa2_flow_fs_table_extracts_log(const struct dpaa2_dev_priv * priv,int tc_id)256 static inline void dpaa2_flow_fs_table_extracts_log(
257 const struct dpaa2_dev_priv *priv, int tc_id)
258 {
259 int idx;
260 char string[32];
261
262 if (!dpaa2_flow_control_log)
263 return;
264
265 printf("Setup FS table: number of extracts of TC[%d]: %d\r\n",
266 tc_id, priv->extract.tc_key_extract[tc_id]
267 .dpkg.num_extracts);
268 for (idx = 0; idx < priv->extract.tc_key_extract[tc_id]
269 .dpkg.num_extracts; idx++) {
270 dpaa2_prot_field_string(priv->extract.tc_key_extract[tc_id]
271 .dpkg.extracts[idx].extract.from_hdr.prot,
272 priv->extract.tc_key_extract[tc_id].dpkg.extracts[idx]
273 .extract.from_hdr.field,
274 string);
275 printf("%s", string);
276 if ((idx + 1) < priv->extract.tc_key_extract[tc_id]
277 .dpkg.num_extracts)
278 printf(" / ");
279 }
280 printf("\r\n");
281 }
282
dpaa2_flow_qos_entry_log(const char * log_info,const struct rte_flow * flow,int qos_index)283 static inline void dpaa2_flow_qos_entry_log(
284 const char *log_info, const struct rte_flow *flow, int qos_index)
285 {
286 int idx;
287 uint8_t *key, *mask;
288
289 if (!dpaa2_flow_control_log)
290 return;
291
292 printf("\r\n%s QoS entry[%d] for TC[%d], extracts size is %d\r\n",
293 log_info, qos_index, flow->tc_id, flow->qos_real_key_size);
294
295 key = (uint8_t *)(size_t)flow->qos_rule.key_iova;
296 mask = (uint8_t *)(size_t)flow->qos_rule.mask_iova;
297
298 printf("key:\r\n");
299 for (idx = 0; idx < flow->qos_real_key_size; idx++)
300 printf("%02x ", key[idx]);
301
302 printf("\r\nmask:\r\n");
303 for (idx = 0; idx < flow->qos_real_key_size; idx++)
304 printf("%02x ", mask[idx]);
305
306 printf("\r\n%s QoS ipsrc: %d, ipdst: %d\r\n", log_info,
307 flow->ipaddr_rule.qos_ipsrc_offset,
308 flow->ipaddr_rule.qos_ipdst_offset);
309 }
310
dpaa2_flow_fs_entry_log(const char * log_info,const struct rte_flow * flow)311 static inline void dpaa2_flow_fs_entry_log(
312 const char *log_info, const struct rte_flow *flow)
313 {
314 int idx;
315 uint8_t *key, *mask;
316
317 if (!dpaa2_flow_control_log)
318 return;
319
320 printf("\r\n%s FS/TC entry[%d] of TC[%d], extracts size is %d\r\n",
321 log_info, flow->tc_index, flow->tc_id, flow->fs_real_key_size);
322
323 key = (uint8_t *)(size_t)flow->fs_rule.key_iova;
324 mask = (uint8_t *)(size_t)flow->fs_rule.mask_iova;
325
326 printf("key:\r\n");
327 for (idx = 0; idx < flow->fs_real_key_size; idx++)
328 printf("%02x ", key[idx]);
329
330 printf("\r\nmask:\r\n");
331 for (idx = 0; idx < flow->fs_real_key_size; idx++)
332 printf("%02x ", mask[idx]);
333
334 printf("\r\n%s FS ipsrc: %d, ipdst: %d\r\n", log_info,
335 flow->ipaddr_rule.fs_ipsrc_offset,
336 flow->ipaddr_rule.fs_ipdst_offset);
337 }
338
dpaa2_flow_extract_key_set(struct dpaa2_key_info * key_info,int index,uint8_t size)339 static inline void dpaa2_flow_extract_key_set(
340 struct dpaa2_key_info *key_info, int index, uint8_t size)
341 {
342 key_info->key_size[index] = size;
343 if (index > 0) {
344 key_info->key_offset[index] =
345 key_info->key_offset[index - 1] +
346 key_info->key_size[index - 1];
347 } else {
348 key_info->key_offset[index] = 0;
349 }
350 key_info->key_total_size += size;
351 }
352
dpaa2_flow_extract_add(struct dpaa2_key_extract * key_extract,enum net_prot prot,uint32_t field,uint8_t field_size)353 static int dpaa2_flow_extract_add(
354 struct dpaa2_key_extract *key_extract,
355 enum net_prot prot,
356 uint32_t field, uint8_t field_size)
357 {
358 int index, ip_src = -1, ip_dst = -1;
359 struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
360 struct dpaa2_key_info *key_info = &key_extract->key_info;
361
362 if (dpkg->num_extracts >=
363 DPKG_MAX_NUM_OF_EXTRACTS) {
364 DPAA2_PMD_WARN("Number of extracts overflows");
365 return -1;
366 }
367 /* Before reorder, the IP SRC and IP DST are already last
368 * extract(s).
369 */
370 for (index = 0; index < dpkg->num_extracts; index++) {
371 if (dpkg->extracts[index].extract.from_hdr.prot ==
372 NET_PROT_IP) {
373 if (dpkg->extracts[index].extract.from_hdr.field ==
374 NH_FLD_IP_SRC) {
375 ip_src = index;
376 }
377 if (dpkg->extracts[index].extract.from_hdr.field ==
378 NH_FLD_IP_DST) {
379 ip_dst = index;
380 }
381 }
382 }
383
384 if (ip_src >= 0)
385 RTE_ASSERT((ip_src + 2) >= dpkg->num_extracts);
386
387 if (ip_dst >= 0)
388 RTE_ASSERT((ip_dst + 2) >= dpkg->num_extracts);
389
390 if (prot == NET_PROT_IP &&
391 (field == NH_FLD_IP_SRC ||
392 field == NH_FLD_IP_DST)) {
393 index = dpkg->num_extracts;
394 } else {
395 if (ip_src >= 0 && ip_dst >= 0)
396 index = dpkg->num_extracts - 2;
397 else if (ip_src >= 0 || ip_dst >= 0)
398 index = dpkg->num_extracts - 1;
399 else
400 index = dpkg->num_extracts;
401 }
402
403 dpkg->extracts[index].type = DPKG_EXTRACT_FROM_HDR;
404 dpkg->extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
405 dpkg->extracts[index].extract.from_hdr.prot = prot;
406 dpkg->extracts[index].extract.from_hdr.field = field;
407 if (prot == NET_PROT_IP &&
408 (field == NH_FLD_IP_SRC ||
409 field == NH_FLD_IP_DST)) {
410 dpaa2_flow_extract_key_set(key_info, index, 0);
411 } else {
412 dpaa2_flow_extract_key_set(key_info, index, field_size);
413 }
414
415 if (prot == NET_PROT_IP) {
416 if (field == NH_FLD_IP_SRC) {
417 if (key_info->ipv4_dst_offset >= 0) {
418 key_info->ipv4_src_offset =
419 key_info->ipv4_dst_offset +
420 NH_FLD_IPV4_ADDR_SIZE;
421 } else {
422 key_info->ipv4_src_offset =
423 key_info->key_offset[index - 1] +
424 key_info->key_size[index - 1];
425 }
426 if (key_info->ipv6_dst_offset >= 0) {
427 key_info->ipv6_src_offset =
428 key_info->ipv6_dst_offset +
429 NH_FLD_IPV6_ADDR_SIZE;
430 } else {
431 key_info->ipv6_src_offset =
432 key_info->key_offset[index - 1] +
433 key_info->key_size[index - 1];
434 }
435 } else if (field == NH_FLD_IP_DST) {
436 if (key_info->ipv4_src_offset >= 0) {
437 key_info->ipv4_dst_offset =
438 key_info->ipv4_src_offset +
439 NH_FLD_IPV4_ADDR_SIZE;
440 } else {
441 key_info->ipv4_dst_offset =
442 key_info->key_offset[index - 1] +
443 key_info->key_size[index - 1];
444 }
445 if (key_info->ipv6_src_offset >= 0) {
446 key_info->ipv6_dst_offset =
447 key_info->ipv6_src_offset +
448 NH_FLD_IPV6_ADDR_SIZE;
449 } else {
450 key_info->ipv6_dst_offset =
451 key_info->key_offset[index - 1] +
452 key_info->key_size[index - 1];
453 }
454 }
455 }
456
457 if (index == dpkg->num_extracts) {
458 dpkg->num_extracts++;
459 return 0;
460 }
461
462 if (ip_src >= 0) {
463 ip_src++;
464 dpkg->extracts[ip_src].type =
465 DPKG_EXTRACT_FROM_HDR;
466 dpkg->extracts[ip_src].extract.from_hdr.type =
467 DPKG_FULL_FIELD;
468 dpkg->extracts[ip_src].extract.from_hdr.prot =
469 NET_PROT_IP;
470 dpkg->extracts[ip_src].extract.from_hdr.field =
471 NH_FLD_IP_SRC;
472 dpaa2_flow_extract_key_set(key_info, ip_src, 0);
473 key_info->ipv4_src_offset += field_size;
474 key_info->ipv6_src_offset += field_size;
475 }
476 if (ip_dst >= 0) {
477 ip_dst++;
478 dpkg->extracts[ip_dst].type =
479 DPKG_EXTRACT_FROM_HDR;
480 dpkg->extracts[ip_dst].extract.from_hdr.type =
481 DPKG_FULL_FIELD;
482 dpkg->extracts[ip_dst].extract.from_hdr.prot =
483 NET_PROT_IP;
484 dpkg->extracts[ip_dst].extract.from_hdr.field =
485 NH_FLD_IP_DST;
486 dpaa2_flow_extract_key_set(key_info, ip_dst, 0);
487 key_info->ipv4_dst_offset += field_size;
488 key_info->ipv6_dst_offset += field_size;
489 }
490
491 dpkg->num_extracts++;
492
493 return 0;
494 }
495
dpaa2_flow_extract_add_raw(struct dpaa2_key_extract * key_extract,int size)496 static int dpaa2_flow_extract_add_raw(struct dpaa2_key_extract *key_extract,
497 int size)
498 {
499 struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
500 struct dpaa2_key_info *key_info = &key_extract->key_info;
501 int last_extract_size, index;
502
503 if (dpkg->num_extracts != 0 && dpkg->extracts[0].type !=
504 DPKG_EXTRACT_FROM_DATA) {
505 DPAA2_PMD_WARN("RAW extract cannot be combined with others");
506 return -1;
507 }
508
509 last_extract_size = (size % DPAA2_FLOW_MAX_KEY_SIZE);
510 dpkg->num_extracts = (size / DPAA2_FLOW_MAX_KEY_SIZE);
511 if (last_extract_size)
512 dpkg->num_extracts++;
513 else
514 last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE;
515
516 for (index = 0; index < dpkg->num_extracts; index++) {
517 dpkg->extracts[index].type = DPKG_EXTRACT_FROM_DATA;
518 if (index == dpkg->num_extracts - 1)
519 dpkg->extracts[index].extract.from_data.size =
520 last_extract_size;
521 else
522 dpkg->extracts[index].extract.from_data.size =
523 DPAA2_FLOW_MAX_KEY_SIZE;
524 dpkg->extracts[index].extract.from_data.offset =
525 DPAA2_FLOW_MAX_KEY_SIZE * index;
526 }
527
528 key_info->key_total_size = size;
529 return 0;
530 }
531
532 /* Protocol discrimination.
533 * Discriminate IPv4/IPv6/vLan by Eth type.
534 * Discriminate UDP/TCP/ICMP by next proto of IP.
535 */
536 static inline int
dpaa2_flow_proto_discrimination_extract(struct dpaa2_key_extract * key_extract,enum rte_flow_item_type type)537 dpaa2_flow_proto_discrimination_extract(
538 struct dpaa2_key_extract *key_extract,
539 enum rte_flow_item_type type)
540 {
541 if (type == RTE_FLOW_ITEM_TYPE_ETH) {
542 return dpaa2_flow_extract_add(
543 key_extract, NET_PROT_ETH,
544 NH_FLD_ETH_TYPE,
545 sizeof(rte_be16_t));
546 } else if (type == (enum rte_flow_item_type)
547 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {
548 return dpaa2_flow_extract_add(
549 key_extract, NET_PROT_IP,
550 NH_FLD_IP_PROTO,
551 NH_FLD_IP_PROTO_SIZE);
552 }
553
554 return -1;
555 }
556
dpaa2_flow_extract_search(struct dpkg_profile_cfg * dpkg,enum net_prot prot,uint32_t field)557 static inline int dpaa2_flow_extract_search(
558 struct dpkg_profile_cfg *dpkg,
559 enum net_prot prot, uint32_t field)
560 {
561 int i;
562
563 for (i = 0; i < dpkg->num_extracts; i++) {
564 if (dpkg->extracts[i].extract.from_hdr.prot == prot &&
565 dpkg->extracts[i].extract.from_hdr.field == field) {
566 return i;
567 }
568 }
569
570 return -1;
571 }
572
dpaa2_flow_extract_key_offset(struct dpaa2_key_extract * key_extract,enum net_prot prot,uint32_t field)573 static inline int dpaa2_flow_extract_key_offset(
574 struct dpaa2_key_extract *key_extract,
575 enum net_prot prot, uint32_t field)
576 {
577 int i;
578 struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
579 struct dpaa2_key_info *key_info = &key_extract->key_info;
580
581 if (prot == NET_PROT_IPV4 ||
582 prot == NET_PROT_IPV6)
583 i = dpaa2_flow_extract_search(dpkg, NET_PROT_IP, field);
584 else
585 i = dpaa2_flow_extract_search(dpkg, prot, field);
586
587 if (i >= 0) {
588 if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_SRC)
589 return key_info->ipv4_src_offset;
590 else if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_DST)
591 return key_info->ipv4_dst_offset;
592 else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_SRC)
593 return key_info->ipv6_src_offset;
594 else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_DST)
595 return key_info->ipv6_dst_offset;
596 else
597 return key_info->key_offset[i];
598 } else {
599 return -1;
600 }
601 }
602
603 struct proto_discrimination {
604 enum rte_flow_item_type type;
605 union {
606 rte_be16_t eth_type;
607 uint8_t ip_proto;
608 };
609 };
610
611 static int
dpaa2_flow_proto_discrimination_rule(struct dpaa2_dev_priv * priv,struct rte_flow * flow,struct proto_discrimination proto,int group)612 dpaa2_flow_proto_discrimination_rule(
613 struct dpaa2_dev_priv *priv, struct rte_flow *flow,
614 struct proto_discrimination proto, int group)
615 {
616 enum net_prot prot;
617 uint32_t field;
618 int offset;
619 size_t key_iova;
620 size_t mask_iova;
621 rte_be16_t eth_type;
622 uint8_t ip_proto;
623
624 if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
625 prot = NET_PROT_ETH;
626 field = NH_FLD_ETH_TYPE;
627 } else if (proto.type == DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {
628 prot = NET_PROT_IP;
629 field = NH_FLD_IP_PROTO;
630 } else {
631 DPAA2_PMD_ERR(
632 "Only Eth and IP support to discriminate next proto.");
633 return -1;
634 }
635
636 offset = dpaa2_flow_extract_key_offset(&priv->extract.qos_key_extract,
637 prot, field);
638 if (offset < 0) {
639 DPAA2_PMD_ERR("QoS prot %d field %d extract failed",
640 prot, field);
641 return -1;
642 }
643 key_iova = flow->qos_rule.key_iova + offset;
644 mask_iova = flow->qos_rule.mask_iova + offset;
645 if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
646 eth_type = proto.eth_type;
647 memcpy((void *)key_iova, (const void *)(ð_type),
648 sizeof(rte_be16_t));
649 eth_type = 0xffff;
650 memcpy((void *)mask_iova, (const void *)(ð_type),
651 sizeof(rte_be16_t));
652 } else {
653 ip_proto = proto.ip_proto;
654 memcpy((void *)key_iova, (const void *)(&ip_proto),
655 sizeof(uint8_t));
656 ip_proto = 0xff;
657 memcpy((void *)mask_iova, (const void *)(&ip_proto),
658 sizeof(uint8_t));
659 }
660
661 offset = dpaa2_flow_extract_key_offset(
662 &priv->extract.tc_key_extract[group],
663 prot, field);
664 if (offset < 0) {
665 DPAA2_PMD_ERR("FS prot %d field %d extract failed",
666 prot, field);
667 return -1;
668 }
669 key_iova = flow->fs_rule.key_iova + offset;
670 mask_iova = flow->fs_rule.mask_iova + offset;
671
672 if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
673 eth_type = proto.eth_type;
674 memcpy((void *)key_iova, (const void *)(ð_type),
675 sizeof(rte_be16_t));
676 eth_type = 0xffff;
677 memcpy((void *)mask_iova, (const void *)(ð_type),
678 sizeof(rte_be16_t));
679 } else {
680 ip_proto = proto.ip_proto;
681 memcpy((void *)key_iova, (const void *)(&ip_proto),
682 sizeof(uint8_t));
683 ip_proto = 0xff;
684 memcpy((void *)mask_iova, (const void *)(&ip_proto),
685 sizeof(uint8_t));
686 }
687
688 return 0;
689 }
690
691 static inline int
dpaa2_flow_rule_data_set(struct dpaa2_key_extract * key_extract,struct dpni_rule_cfg * rule,enum net_prot prot,uint32_t field,const void * key,const void * mask,int size)692 dpaa2_flow_rule_data_set(
693 struct dpaa2_key_extract *key_extract,
694 struct dpni_rule_cfg *rule,
695 enum net_prot prot, uint32_t field,
696 const void *key, const void *mask, int size)
697 {
698 int offset = dpaa2_flow_extract_key_offset(key_extract,
699 prot, field);
700
701 if (offset < 0) {
702 DPAA2_PMD_ERR("prot %d, field %d extract failed",
703 prot, field);
704 return -1;
705 }
706
707 memcpy((void *)(size_t)(rule->key_iova + offset), key, size);
708 memcpy((void *)(size_t)(rule->mask_iova + offset), mask, size);
709
710 return 0;
711 }
712
713 static inline int
dpaa2_flow_rule_data_set_raw(struct dpni_rule_cfg * rule,const void * key,const void * mask,int size)714 dpaa2_flow_rule_data_set_raw(struct dpni_rule_cfg *rule,
715 const void *key, const void *mask, int size)
716 {
717 int offset = 0;
718
719 memcpy((void *)(size_t)(rule->key_iova + offset), key, size);
720 memcpy((void *)(size_t)(rule->mask_iova + offset), mask, size);
721
722 return 0;
723 }
724
725 static inline int
_dpaa2_flow_rule_move_ipaddr_tail(struct dpaa2_key_extract * key_extract,struct dpni_rule_cfg * rule,int src_offset,uint32_t field,bool ipv4)726 _dpaa2_flow_rule_move_ipaddr_tail(
727 struct dpaa2_key_extract *key_extract,
728 struct dpni_rule_cfg *rule, int src_offset,
729 uint32_t field, bool ipv4)
730 {
731 size_t key_src;
732 size_t mask_src;
733 size_t key_dst;
734 size_t mask_dst;
735 int dst_offset, len;
736 enum net_prot prot;
737 char tmp[NH_FLD_IPV6_ADDR_SIZE];
738
739 if (field != NH_FLD_IP_SRC &&
740 field != NH_FLD_IP_DST) {
741 DPAA2_PMD_ERR("Field of IP addr reorder must be IP SRC/DST");
742 return -1;
743 }
744 if (ipv4)
745 prot = NET_PROT_IPV4;
746 else
747 prot = NET_PROT_IPV6;
748 dst_offset = dpaa2_flow_extract_key_offset(key_extract,
749 prot, field);
750 if (dst_offset < 0) {
751 DPAA2_PMD_ERR("Field %d reorder extract failed", field);
752 return -1;
753 }
754 key_src = rule->key_iova + src_offset;
755 mask_src = rule->mask_iova + src_offset;
756 key_dst = rule->key_iova + dst_offset;
757 mask_dst = rule->mask_iova + dst_offset;
758 if (ipv4)
759 len = sizeof(rte_be32_t);
760 else
761 len = NH_FLD_IPV6_ADDR_SIZE;
762
763 memcpy(tmp, (char *)key_src, len);
764 memset((char *)key_src, 0, len);
765 memcpy((char *)key_dst, tmp, len);
766
767 memcpy(tmp, (char *)mask_src, len);
768 memset((char *)mask_src, 0, len);
769 memcpy((char *)mask_dst, tmp, len);
770
771 return 0;
772 }
773
774 static inline int
dpaa2_flow_rule_move_ipaddr_tail(struct rte_flow * flow,struct dpaa2_dev_priv * priv,int fs_group)775 dpaa2_flow_rule_move_ipaddr_tail(
776 struct rte_flow *flow, struct dpaa2_dev_priv *priv,
777 int fs_group)
778 {
779 int ret;
780 enum net_prot prot;
781
782 if (flow->ipaddr_rule.ipaddr_type == FLOW_NONE_IPADDR)
783 return 0;
784
785 if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR)
786 prot = NET_PROT_IPV4;
787 else
788 prot = NET_PROT_IPV6;
789
790 if (flow->ipaddr_rule.qos_ipsrc_offset >= 0) {
791 ret = _dpaa2_flow_rule_move_ipaddr_tail(
792 &priv->extract.qos_key_extract,
793 &flow->qos_rule,
794 flow->ipaddr_rule.qos_ipsrc_offset,
795 NH_FLD_IP_SRC, prot == NET_PROT_IPV4);
796 if (ret) {
797 DPAA2_PMD_ERR("QoS src address reorder failed");
798 return -1;
799 }
800 flow->ipaddr_rule.qos_ipsrc_offset =
801 dpaa2_flow_extract_key_offset(
802 &priv->extract.qos_key_extract,
803 prot, NH_FLD_IP_SRC);
804 }
805
806 if (flow->ipaddr_rule.qos_ipdst_offset >= 0) {
807 ret = _dpaa2_flow_rule_move_ipaddr_tail(
808 &priv->extract.qos_key_extract,
809 &flow->qos_rule,
810 flow->ipaddr_rule.qos_ipdst_offset,
811 NH_FLD_IP_DST, prot == NET_PROT_IPV4);
812 if (ret) {
813 DPAA2_PMD_ERR("QoS dst address reorder failed");
814 return -1;
815 }
816 flow->ipaddr_rule.qos_ipdst_offset =
817 dpaa2_flow_extract_key_offset(
818 &priv->extract.qos_key_extract,
819 prot, NH_FLD_IP_DST);
820 }
821
822 if (flow->ipaddr_rule.fs_ipsrc_offset >= 0) {
823 ret = _dpaa2_flow_rule_move_ipaddr_tail(
824 &priv->extract.tc_key_extract[fs_group],
825 &flow->fs_rule,
826 flow->ipaddr_rule.fs_ipsrc_offset,
827 NH_FLD_IP_SRC, prot == NET_PROT_IPV4);
828 if (ret) {
829 DPAA2_PMD_ERR("FS src address reorder failed");
830 return -1;
831 }
832 flow->ipaddr_rule.fs_ipsrc_offset =
833 dpaa2_flow_extract_key_offset(
834 &priv->extract.tc_key_extract[fs_group],
835 prot, NH_FLD_IP_SRC);
836 }
837 if (flow->ipaddr_rule.fs_ipdst_offset >= 0) {
838 ret = _dpaa2_flow_rule_move_ipaddr_tail(
839 &priv->extract.tc_key_extract[fs_group],
840 &flow->fs_rule,
841 flow->ipaddr_rule.fs_ipdst_offset,
842 NH_FLD_IP_DST, prot == NET_PROT_IPV4);
843 if (ret) {
844 DPAA2_PMD_ERR("FS dst address reorder failed");
845 return -1;
846 }
847 flow->ipaddr_rule.fs_ipdst_offset =
848 dpaa2_flow_extract_key_offset(
849 &priv->extract.tc_key_extract[fs_group],
850 prot, NH_FLD_IP_DST);
851 }
852
853 return 0;
854 }
855
856 static int
dpaa2_flow_extract_support(const uint8_t * mask_src,enum rte_flow_item_type type)857 dpaa2_flow_extract_support(
858 const uint8_t *mask_src,
859 enum rte_flow_item_type type)
860 {
861 char mask[64];
862 int i, size = 0;
863 const char *mask_support = 0;
864
865 switch (type) {
866 case RTE_FLOW_ITEM_TYPE_ETH:
867 mask_support = (const char *)&dpaa2_flow_item_eth_mask;
868 size = sizeof(struct rte_flow_item_eth);
869 break;
870 case RTE_FLOW_ITEM_TYPE_VLAN:
871 mask_support = (const char *)&dpaa2_flow_item_vlan_mask;
872 size = sizeof(struct rte_flow_item_vlan);
873 break;
874 case RTE_FLOW_ITEM_TYPE_IPV4:
875 mask_support = (const char *)&dpaa2_flow_item_ipv4_mask;
876 size = sizeof(struct rte_flow_item_ipv4);
877 break;
878 case RTE_FLOW_ITEM_TYPE_IPV6:
879 mask_support = (const char *)&dpaa2_flow_item_ipv6_mask;
880 size = sizeof(struct rte_flow_item_ipv6);
881 break;
882 case RTE_FLOW_ITEM_TYPE_ICMP:
883 mask_support = (const char *)&dpaa2_flow_item_icmp_mask;
884 size = sizeof(struct rte_flow_item_icmp);
885 break;
886 case RTE_FLOW_ITEM_TYPE_UDP:
887 mask_support = (const char *)&dpaa2_flow_item_udp_mask;
888 size = sizeof(struct rte_flow_item_udp);
889 break;
890 case RTE_FLOW_ITEM_TYPE_TCP:
891 mask_support = (const char *)&dpaa2_flow_item_tcp_mask;
892 size = sizeof(struct rte_flow_item_tcp);
893 break;
894 case RTE_FLOW_ITEM_TYPE_SCTP:
895 mask_support = (const char *)&dpaa2_flow_item_sctp_mask;
896 size = sizeof(struct rte_flow_item_sctp);
897 break;
898 case RTE_FLOW_ITEM_TYPE_GRE:
899 mask_support = (const char *)&dpaa2_flow_item_gre_mask;
900 size = sizeof(struct rte_flow_item_gre);
901 break;
902 default:
903 return -1;
904 }
905
906 memcpy(mask, mask_support, size);
907
908 for (i = 0; i < size; i++)
909 mask[i] = (mask[i] | mask_src[i]);
910
911 if (memcmp(mask, mask_support, size))
912 return -1;
913
914 return 0;
915 }
916
917 static int
dpaa2_configure_flow_eth(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)918 dpaa2_configure_flow_eth(struct rte_flow *flow,
919 struct rte_eth_dev *dev,
920 const struct rte_flow_attr *attr,
921 const struct rte_flow_item *pattern,
922 const struct rte_flow_action actions[] __rte_unused,
923 struct rte_flow_error *error __rte_unused,
924 int *device_configured)
925 {
926 int index, ret;
927 int local_cfg = 0;
928 uint32_t group;
929 const struct rte_flow_item_eth *spec, *mask;
930
931 /* TODO: Currently upper bound of range parameter is not implemented */
932 const struct rte_flow_item_eth *last __rte_unused;
933 struct dpaa2_dev_priv *priv = dev->data->dev_private;
934 const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0};
935
936 group = attr->group;
937
938 /* Parse pattern list to get the matching parameters */
939 spec = (const struct rte_flow_item_eth *)pattern->spec;
940 last = (const struct rte_flow_item_eth *)pattern->last;
941 mask = (const struct rte_flow_item_eth *)
942 (pattern->mask ? pattern->mask : &dpaa2_flow_item_eth_mask);
943 if (!spec) {
944 /* Don't care any field of eth header,
945 * only care eth protocol.
946 */
947 DPAA2_PMD_WARN("No pattern spec for Eth flow, just skip");
948 return 0;
949 }
950
951 /* Get traffic class index and flow id to be configured */
952 flow->tc_id = group;
953 flow->tc_index = attr->priority;
954
955 if (dpaa2_flow_extract_support((const uint8_t *)mask,
956 RTE_FLOW_ITEM_TYPE_ETH)) {
957 DPAA2_PMD_WARN("Extract field(s) of ethernet not support.");
958
959 return -1;
960 }
961
962 if (memcmp((const char *)&mask->src, zero_cmp, RTE_ETHER_ADDR_LEN)) {
963 index = dpaa2_flow_extract_search(
964 &priv->extract.qos_key_extract.dpkg,
965 NET_PROT_ETH, NH_FLD_ETH_SA);
966 if (index < 0) {
967 ret = dpaa2_flow_extract_add(
968 &priv->extract.qos_key_extract,
969 NET_PROT_ETH, NH_FLD_ETH_SA,
970 RTE_ETHER_ADDR_LEN);
971 if (ret) {
972 DPAA2_PMD_ERR("QoS Extract add ETH_SA failed.");
973
974 return -1;
975 }
976 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
977 }
978 index = dpaa2_flow_extract_search(
979 &priv->extract.tc_key_extract[group].dpkg,
980 NET_PROT_ETH, NH_FLD_ETH_SA);
981 if (index < 0) {
982 ret = dpaa2_flow_extract_add(
983 &priv->extract.tc_key_extract[group],
984 NET_PROT_ETH, NH_FLD_ETH_SA,
985 RTE_ETHER_ADDR_LEN);
986 if (ret) {
987 DPAA2_PMD_ERR("FS Extract add ETH_SA failed.");
988 return -1;
989 }
990 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
991 }
992
993 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
994 if (ret) {
995 DPAA2_PMD_ERR(
996 "Move ipaddr before ETH_SA rule set failed");
997 return -1;
998 }
999
1000 ret = dpaa2_flow_rule_data_set(
1001 &priv->extract.qos_key_extract,
1002 &flow->qos_rule,
1003 NET_PROT_ETH,
1004 NH_FLD_ETH_SA,
1005 &spec->src.addr_bytes,
1006 &mask->src.addr_bytes,
1007 sizeof(struct rte_ether_addr));
1008 if (ret) {
1009 DPAA2_PMD_ERR("QoS NH_FLD_ETH_SA rule data set failed");
1010 return -1;
1011 }
1012
1013 ret = dpaa2_flow_rule_data_set(
1014 &priv->extract.tc_key_extract[group],
1015 &flow->fs_rule,
1016 NET_PROT_ETH,
1017 NH_FLD_ETH_SA,
1018 &spec->src.addr_bytes,
1019 &mask->src.addr_bytes,
1020 sizeof(struct rte_ether_addr));
1021 if (ret) {
1022 DPAA2_PMD_ERR("FS NH_FLD_ETH_SA rule data set failed");
1023 return -1;
1024 }
1025 }
1026
1027 if (memcmp((const char *)&mask->dst, zero_cmp, RTE_ETHER_ADDR_LEN)) {
1028 index = dpaa2_flow_extract_search(
1029 &priv->extract.qos_key_extract.dpkg,
1030 NET_PROT_ETH, NH_FLD_ETH_DA);
1031 if (index < 0) {
1032 ret = dpaa2_flow_extract_add(
1033 &priv->extract.qos_key_extract,
1034 NET_PROT_ETH, NH_FLD_ETH_DA,
1035 RTE_ETHER_ADDR_LEN);
1036 if (ret) {
1037 DPAA2_PMD_ERR("QoS Extract add ETH_DA failed.");
1038
1039 return -1;
1040 }
1041 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1042 }
1043
1044 index = dpaa2_flow_extract_search(
1045 &priv->extract.tc_key_extract[group].dpkg,
1046 NET_PROT_ETH, NH_FLD_ETH_DA);
1047 if (index < 0) {
1048 ret = dpaa2_flow_extract_add(
1049 &priv->extract.tc_key_extract[group],
1050 NET_PROT_ETH, NH_FLD_ETH_DA,
1051 RTE_ETHER_ADDR_LEN);
1052 if (ret) {
1053 DPAA2_PMD_ERR("FS Extract add ETH_DA failed.");
1054
1055 return -1;
1056 }
1057 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1058 }
1059
1060 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1061 if (ret) {
1062 DPAA2_PMD_ERR(
1063 "Move ipaddr before ETH DA rule set failed");
1064 return -1;
1065 }
1066
1067 ret = dpaa2_flow_rule_data_set(
1068 &priv->extract.qos_key_extract,
1069 &flow->qos_rule,
1070 NET_PROT_ETH,
1071 NH_FLD_ETH_DA,
1072 &spec->dst.addr_bytes,
1073 &mask->dst.addr_bytes,
1074 sizeof(struct rte_ether_addr));
1075 if (ret) {
1076 DPAA2_PMD_ERR("QoS NH_FLD_ETH_DA rule data set failed");
1077 return -1;
1078 }
1079
1080 ret = dpaa2_flow_rule_data_set(
1081 &priv->extract.tc_key_extract[group],
1082 &flow->fs_rule,
1083 NET_PROT_ETH,
1084 NH_FLD_ETH_DA,
1085 &spec->dst.addr_bytes,
1086 &mask->dst.addr_bytes,
1087 sizeof(struct rte_ether_addr));
1088 if (ret) {
1089 DPAA2_PMD_ERR("FS NH_FLD_ETH_DA rule data set failed");
1090 return -1;
1091 }
1092 }
1093
1094 if (memcmp((const char *)&mask->type, zero_cmp, sizeof(rte_be16_t))) {
1095 index = dpaa2_flow_extract_search(
1096 &priv->extract.qos_key_extract.dpkg,
1097 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1098 if (index < 0) {
1099 ret = dpaa2_flow_extract_add(
1100 &priv->extract.qos_key_extract,
1101 NET_PROT_ETH, NH_FLD_ETH_TYPE,
1102 RTE_ETHER_TYPE_LEN);
1103 if (ret) {
1104 DPAA2_PMD_ERR("QoS Extract add ETH_TYPE failed.");
1105
1106 return -1;
1107 }
1108 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1109 }
1110 index = dpaa2_flow_extract_search(
1111 &priv->extract.tc_key_extract[group].dpkg,
1112 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1113 if (index < 0) {
1114 ret = dpaa2_flow_extract_add(
1115 &priv->extract.tc_key_extract[group],
1116 NET_PROT_ETH, NH_FLD_ETH_TYPE,
1117 RTE_ETHER_TYPE_LEN);
1118 if (ret) {
1119 DPAA2_PMD_ERR("FS Extract add ETH_TYPE failed.");
1120
1121 return -1;
1122 }
1123 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1124 }
1125
1126 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1127 if (ret) {
1128 DPAA2_PMD_ERR(
1129 "Move ipaddr before ETH TYPE rule set failed");
1130 return -1;
1131 }
1132
1133 ret = dpaa2_flow_rule_data_set(
1134 &priv->extract.qos_key_extract,
1135 &flow->qos_rule,
1136 NET_PROT_ETH,
1137 NH_FLD_ETH_TYPE,
1138 &spec->type,
1139 &mask->type,
1140 sizeof(rte_be16_t));
1141 if (ret) {
1142 DPAA2_PMD_ERR("QoS NH_FLD_ETH_TYPE rule data set failed");
1143 return -1;
1144 }
1145
1146 ret = dpaa2_flow_rule_data_set(
1147 &priv->extract.tc_key_extract[group],
1148 &flow->fs_rule,
1149 NET_PROT_ETH,
1150 NH_FLD_ETH_TYPE,
1151 &spec->type,
1152 &mask->type,
1153 sizeof(rte_be16_t));
1154 if (ret) {
1155 DPAA2_PMD_ERR("FS NH_FLD_ETH_TYPE rule data set failed");
1156 return -1;
1157 }
1158 }
1159
1160 (*device_configured) |= local_cfg;
1161
1162 return 0;
1163 }
1164
1165 static int
dpaa2_configure_flow_vlan(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)1166 dpaa2_configure_flow_vlan(struct rte_flow *flow,
1167 struct rte_eth_dev *dev,
1168 const struct rte_flow_attr *attr,
1169 const struct rte_flow_item *pattern,
1170 const struct rte_flow_action actions[] __rte_unused,
1171 struct rte_flow_error *error __rte_unused,
1172 int *device_configured)
1173 {
1174 int index, ret;
1175 int local_cfg = 0;
1176 uint32_t group;
1177 const struct rte_flow_item_vlan *spec, *mask;
1178
1179 const struct rte_flow_item_vlan *last __rte_unused;
1180 struct dpaa2_dev_priv *priv = dev->data->dev_private;
1181
1182 group = attr->group;
1183
1184 /* Parse pattern list to get the matching parameters */
1185 spec = (const struct rte_flow_item_vlan *)pattern->spec;
1186 last = (const struct rte_flow_item_vlan *)pattern->last;
1187 mask = (const struct rte_flow_item_vlan *)
1188 (pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask);
1189
1190 /* Get traffic class index and flow id to be configured */
1191 flow->tc_id = group;
1192 flow->tc_index = attr->priority;
1193
1194 if (!spec) {
1195 /* Don't care any field of vlan header,
1196 * only care vlan protocol.
1197 */
1198 /* Eth type is actually used for vLan classification.
1199 */
1200 struct proto_discrimination proto;
1201
1202 index = dpaa2_flow_extract_search(
1203 &priv->extract.qos_key_extract.dpkg,
1204 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1205 if (index < 0) {
1206 ret = dpaa2_flow_proto_discrimination_extract(
1207 &priv->extract.qos_key_extract,
1208 RTE_FLOW_ITEM_TYPE_ETH);
1209 if (ret) {
1210 DPAA2_PMD_ERR(
1211 "QoS Ext ETH_TYPE to discriminate vLan failed");
1212
1213 return -1;
1214 }
1215 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1216 }
1217
1218 index = dpaa2_flow_extract_search(
1219 &priv->extract.tc_key_extract[group].dpkg,
1220 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1221 if (index < 0) {
1222 ret = dpaa2_flow_proto_discrimination_extract(
1223 &priv->extract.tc_key_extract[group],
1224 RTE_FLOW_ITEM_TYPE_ETH);
1225 if (ret) {
1226 DPAA2_PMD_ERR(
1227 "FS Ext ETH_TYPE to discriminate vLan failed.");
1228
1229 return -1;
1230 }
1231 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1232 }
1233
1234 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1235 if (ret) {
1236 DPAA2_PMD_ERR(
1237 "Move ipaddr before vLan discrimination set failed");
1238 return -1;
1239 }
1240
1241 proto.type = RTE_FLOW_ITEM_TYPE_ETH;
1242 proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
1243 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
1244 proto, group);
1245 if (ret) {
1246 DPAA2_PMD_ERR("vLan discrimination rule set failed");
1247 return -1;
1248 }
1249
1250 (*device_configured) |= local_cfg;
1251
1252 return 0;
1253 }
1254
1255 if (dpaa2_flow_extract_support((const uint8_t *)mask,
1256 RTE_FLOW_ITEM_TYPE_VLAN)) {
1257 DPAA2_PMD_WARN("Extract field(s) of vlan not support.");
1258
1259 return -1;
1260 }
1261
1262 if (!mask->tci)
1263 return 0;
1264
1265 index = dpaa2_flow_extract_search(
1266 &priv->extract.qos_key_extract.dpkg,
1267 NET_PROT_VLAN, NH_FLD_VLAN_TCI);
1268 if (index < 0) {
1269 ret = dpaa2_flow_extract_add(
1270 &priv->extract.qos_key_extract,
1271 NET_PROT_VLAN,
1272 NH_FLD_VLAN_TCI,
1273 sizeof(rte_be16_t));
1274 if (ret) {
1275 DPAA2_PMD_ERR("QoS Extract add VLAN_TCI failed.");
1276
1277 return -1;
1278 }
1279 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1280 }
1281
1282 index = dpaa2_flow_extract_search(
1283 &priv->extract.tc_key_extract[group].dpkg,
1284 NET_PROT_VLAN, NH_FLD_VLAN_TCI);
1285 if (index < 0) {
1286 ret = dpaa2_flow_extract_add(
1287 &priv->extract.tc_key_extract[group],
1288 NET_PROT_VLAN,
1289 NH_FLD_VLAN_TCI,
1290 sizeof(rte_be16_t));
1291 if (ret) {
1292 DPAA2_PMD_ERR("FS Extract add VLAN_TCI failed.");
1293
1294 return -1;
1295 }
1296 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1297 }
1298
1299 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1300 if (ret) {
1301 DPAA2_PMD_ERR(
1302 "Move ipaddr before VLAN TCI rule set failed");
1303 return -1;
1304 }
1305
1306 ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,
1307 &flow->qos_rule,
1308 NET_PROT_VLAN,
1309 NH_FLD_VLAN_TCI,
1310 &spec->tci,
1311 &mask->tci,
1312 sizeof(rte_be16_t));
1313 if (ret) {
1314 DPAA2_PMD_ERR("QoS NH_FLD_VLAN_TCI rule data set failed");
1315 return -1;
1316 }
1317
1318 ret = dpaa2_flow_rule_data_set(
1319 &priv->extract.tc_key_extract[group],
1320 &flow->fs_rule,
1321 NET_PROT_VLAN,
1322 NH_FLD_VLAN_TCI,
1323 &spec->tci,
1324 &mask->tci,
1325 sizeof(rte_be16_t));
1326 if (ret) {
1327 DPAA2_PMD_ERR("FS NH_FLD_VLAN_TCI rule data set failed");
1328 return -1;
1329 }
1330
1331 (*device_configured) |= local_cfg;
1332
1333 return 0;
1334 }
1335
1336 static int
dpaa2_configure_flow_ip_discrimation(struct dpaa2_dev_priv * priv,struct rte_flow * flow,const struct rte_flow_item * pattern,int * local_cfg,int * device_configured,uint32_t group)1337 dpaa2_configure_flow_ip_discrimation(
1338 struct dpaa2_dev_priv *priv, struct rte_flow *flow,
1339 const struct rte_flow_item *pattern,
1340 int *local_cfg, int *device_configured,
1341 uint32_t group)
1342 {
1343 int index, ret;
1344 struct proto_discrimination proto;
1345
1346 index = dpaa2_flow_extract_search(
1347 &priv->extract.qos_key_extract.dpkg,
1348 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1349 if (index < 0) {
1350 ret = dpaa2_flow_proto_discrimination_extract(
1351 &priv->extract.qos_key_extract,
1352 RTE_FLOW_ITEM_TYPE_ETH);
1353 if (ret) {
1354 DPAA2_PMD_ERR(
1355 "QoS Extract ETH_TYPE to discriminate IP failed.");
1356 return -1;
1357 }
1358 (*local_cfg) |= DPAA2_QOS_TABLE_RECONFIGURE;
1359 }
1360
1361 index = dpaa2_flow_extract_search(
1362 &priv->extract.tc_key_extract[group].dpkg,
1363 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1364 if (index < 0) {
1365 ret = dpaa2_flow_proto_discrimination_extract(
1366 &priv->extract.tc_key_extract[group],
1367 RTE_FLOW_ITEM_TYPE_ETH);
1368 if (ret) {
1369 DPAA2_PMD_ERR(
1370 "FS Extract ETH_TYPE to discriminate IP failed.");
1371 return -1;
1372 }
1373 (*local_cfg) |= DPAA2_FS_TABLE_RECONFIGURE;
1374 }
1375
1376 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1377 if (ret) {
1378 DPAA2_PMD_ERR(
1379 "Move ipaddr before IP discrimination set failed");
1380 return -1;
1381 }
1382
1383 proto.type = RTE_FLOW_ITEM_TYPE_ETH;
1384 if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4)
1385 proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
1386 else
1387 proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
1388 ret = dpaa2_flow_proto_discrimination_rule(priv, flow, proto, group);
1389 if (ret) {
1390 DPAA2_PMD_ERR("IP discrimination rule set failed");
1391 return -1;
1392 }
1393
1394 (*device_configured) |= (*local_cfg);
1395
1396 return 0;
1397 }
1398
1399
1400 static int
dpaa2_configure_flow_generic_ip(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)1401 dpaa2_configure_flow_generic_ip(
1402 struct rte_flow *flow,
1403 struct rte_eth_dev *dev,
1404 const struct rte_flow_attr *attr,
1405 const struct rte_flow_item *pattern,
1406 const struct rte_flow_action actions[] __rte_unused,
1407 struct rte_flow_error *error __rte_unused,
1408 int *device_configured)
1409 {
1410 int index, ret;
1411 int local_cfg = 0;
1412 uint32_t group;
1413 const struct rte_flow_item_ipv4 *spec_ipv4 = 0,
1414 *mask_ipv4 = 0;
1415 const struct rte_flow_item_ipv6 *spec_ipv6 = 0,
1416 *mask_ipv6 = 0;
1417 const void *key, *mask;
1418 enum net_prot prot;
1419
1420 struct dpaa2_dev_priv *priv = dev->data->dev_private;
1421 const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0};
1422 int size;
1423
1424 group = attr->group;
1425
1426 /* Parse pattern list to get the matching parameters */
1427 if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4) {
1428 spec_ipv4 = (const struct rte_flow_item_ipv4 *)pattern->spec;
1429 mask_ipv4 = (const struct rte_flow_item_ipv4 *)
1430 (pattern->mask ? pattern->mask :
1431 &dpaa2_flow_item_ipv4_mask);
1432 } else {
1433 spec_ipv6 = (const struct rte_flow_item_ipv6 *)pattern->spec;
1434 mask_ipv6 = (const struct rte_flow_item_ipv6 *)
1435 (pattern->mask ? pattern->mask :
1436 &dpaa2_flow_item_ipv6_mask);
1437 }
1438
1439 /* Get traffic class index and flow id to be configured */
1440 flow->tc_id = group;
1441 flow->tc_index = attr->priority;
1442
1443 ret = dpaa2_configure_flow_ip_discrimation(priv,
1444 flow, pattern, &local_cfg,
1445 device_configured, group);
1446 if (ret) {
1447 DPAA2_PMD_ERR("IP discrimation failed!");
1448 return -1;
1449 }
1450
1451 if (!spec_ipv4 && !spec_ipv6)
1452 return 0;
1453
1454 if (mask_ipv4) {
1455 if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv4,
1456 RTE_FLOW_ITEM_TYPE_IPV4)) {
1457 DPAA2_PMD_WARN("Extract field(s) of IPv4 not support.");
1458
1459 return -1;
1460 }
1461 }
1462
1463 if (mask_ipv6) {
1464 if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv6,
1465 RTE_FLOW_ITEM_TYPE_IPV6)) {
1466 DPAA2_PMD_WARN("Extract field(s) of IPv6 not support.");
1467
1468 return -1;
1469 }
1470 }
1471
1472 if (mask_ipv4 && (mask_ipv4->hdr.src_addr ||
1473 mask_ipv4->hdr.dst_addr)) {
1474 flow->ipaddr_rule.ipaddr_type = FLOW_IPV4_ADDR;
1475 } else if (mask_ipv6 &&
1476 (memcmp((const char *)mask_ipv6->hdr.src_addr,
1477 zero_cmp, NH_FLD_IPV6_ADDR_SIZE) ||
1478 memcmp((const char *)mask_ipv6->hdr.dst_addr,
1479 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
1480 flow->ipaddr_rule.ipaddr_type = FLOW_IPV6_ADDR;
1481 }
1482
1483 if ((mask_ipv4 && mask_ipv4->hdr.src_addr) ||
1484 (mask_ipv6 &&
1485 memcmp((const char *)mask_ipv6->hdr.src_addr,
1486 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
1487 index = dpaa2_flow_extract_search(
1488 &priv->extract.qos_key_extract.dpkg,
1489 NET_PROT_IP, NH_FLD_IP_SRC);
1490 if (index < 0) {
1491 ret = dpaa2_flow_extract_add(
1492 &priv->extract.qos_key_extract,
1493 NET_PROT_IP,
1494 NH_FLD_IP_SRC,
1495 0);
1496 if (ret) {
1497 DPAA2_PMD_ERR("QoS Extract add IP_SRC failed.");
1498
1499 return -1;
1500 }
1501 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1502 }
1503
1504 index = dpaa2_flow_extract_search(
1505 &priv->extract.tc_key_extract[group].dpkg,
1506 NET_PROT_IP, NH_FLD_IP_SRC);
1507 if (index < 0) {
1508 ret = dpaa2_flow_extract_add(
1509 &priv->extract.tc_key_extract[group],
1510 NET_PROT_IP,
1511 NH_FLD_IP_SRC,
1512 0);
1513 if (ret) {
1514 DPAA2_PMD_ERR("FS Extract add IP_SRC failed.");
1515
1516 return -1;
1517 }
1518 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1519 }
1520
1521 if (spec_ipv4)
1522 key = &spec_ipv4->hdr.src_addr;
1523 else
1524 key = &spec_ipv6->hdr.src_addr[0];
1525 if (mask_ipv4) {
1526 mask = &mask_ipv4->hdr.src_addr;
1527 size = NH_FLD_IPV4_ADDR_SIZE;
1528 prot = NET_PROT_IPV4;
1529 } else {
1530 mask = &mask_ipv6->hdr.src_addr[0];
1531 size = NH_FLD_IPV6_ADDR_SIZE;
1532 prot = NET_PROT_IPV6;
1533 }
1534
1535 ret = dpaa2_flow_rule_data_set(
1536 &priv->extract.qos_key_extract,
1537 &flow->qos_rule,
1538 prot, NH_FLD_IP_SRC,
1539 key, mask, size);
1540 if (ret) {
1541 DPAA2_PMD_ERR("QoS NH_FLD_IP_SRC rule data set failed");
1542 return -1;
1543 }
1544
1545 ret = dpaa2_flow_rule_data_set(
1546 &priv->extract.tc_key_extract[group],
1547 &flow->fs_rule,
1548 prot, NH_FLD_IP_SRC,
1549 key, mask, size);
1550 if (ret) {
1551 DPAA2_PMD_ERR("FS NH_FLD_IP_SRC rule data set failed");
1552 return -1;
1553 }
1554
1555 flow->ipaddr_rule.qos_ipsrc_offset =
1556 dpaa2_flow_extract_key_offset(
1557 &priv->extract.qos_key_extract,
1558 prot, NH_FLD_IP_SRC);
1559 flow->ipaddr_rule.fs_ipsrc_offset =
1560 dpaa2_flow_extract_key_offset(
1561 &priv->extract.tc_key_extract[group],
1562 prot, NH_FLD_IP_SRC);
1563 }
1564
1565 if ((mask_ipv4 && mask_ipv4->hdr.dst_addr) ||
1566 (mask_ipv6 &&
1567 memcmp((const char *)mask_ipv6->hdr.dst_addr,
1568 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
1569 index = dpaa2_flow_extract_search(
1570 &priv->extract.qos_key_extract.dpkg,
1571 NET_PROT_IP, NH_FLD_IP_DST);
1572 if (index < 0) {
1573 if (mask_ipv4)
1574 size = NH_FLD_IPV4_ADDR_SIZE;
1575 else
1576 size = NH_FLD_IPV6_ADDR_SIZE;
1577 ret = dpaa2_flow_extract_add(
1578 &priv->extract.qos_key_extract,
1579 NET_PROT_IP,
1580 NH_FLD_IP_DST,
1581 size);
1582 if (ret) {
1583 DPAA2_PMD_ERR("QoS Extract add IP_DST failed.");
1584
1585 return -1;
1586 }
1587 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1588 }
1589
1590 index = dpaa2_flow_extract_search(
1591 &priv->extract.tc_key_extract[group].dpkg,
1592 NET_PROT_IP, NH_FLD_IP_DST);
1593 if (index < 0) {
1594 if (mask_ipv4)
1595 size = NH_FLD_IPV4_ADDR_SIZE;
1596 else
1597 size = NH_FLD_IPV6_ADDR_SIZE;
1598 ret = dpaa2_flow_extract_add(
1599 &priv->extract.tc_key_extract[group],
1600 NET_PROT_IP,
1601 NH_FLD_IP_DST,
1602 size);
1603 if (ret) {
1604 DPAA2_PMD_ERR("FS Extract add IP_DST failed.");
1605
1606 return -1;
1607 }
1608 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1609 }
1610
1611 if (spec_ipv4)
1612 key = &spec_ipv4->hdr.dst_addr;
1613 else
1614 key = spec_ipv6->hdr.dst_addr;
1615 if (mask_ipv4) {
1616 mask = &mask_ipv4->hdr.dst_addr;
1617 size = NH_FLD_IPV4_ADDR_SIZE;
1618 prot = NET_PROT_IPV4;
1619 } else {
1620 mask = &mask_ipv6->hdr.dst_addr[0];
1621 size = NH_FLD_IPV6_ADDR_SIZE;
1622 prot = NET_PROT_IPV6;
1623 }
1624
1625 ret = dpaa2_flow_rule_data_set(
1626 &priv->extract.qos_key_extract,
1627 &flow->qos_rule,
1628 prot, NH_FLD_IP_DST,
1629 key, mask, size);
1630 if (ret) {
1631 DPAA2_PMD_ERR("QoS NH_FLD_IP_DST rule data set failed");
1632 return -1;
1633 }
1634
1635 ret = dpaa2_flow_rule_data_set(
1636 &priv->extract.tc_key_extract[group],
1637 &flow->fs_rule,
1638 prot, NH_FLD_IP_DST,
1639 key, mask, size);
1640 if (ret) {
1641 DPAA2_PMD_ERR("FS NH_FLD_IP_DST rule data set failed");
1642 return -1;
1643 }
1644 flow->ipaddr_rule.qos_ipdst_offset =
1645 dpaa2_flow_extract_key_offset(
1646 &priv->extract.qos_key_extract,
1647 prot, NH_FLD_IP_DST);
1648 flow->ipaddr_rule.fs_ipdst_offset =
1649 dpaa2_flow_extract_key_offset(
1650 &priv->extract.tc_key_extract[group],
1651 prot, NH_FLD_IP_DST);
1652 }
1653
1654 if ((mask_ipv4 && mask_ipv4->hdr.next_proto_id) ||
1655 (mask_ipv6 && mask_ipv6->hdr.proto)) {
1656 index = dpaa2_flow_extract_search(
1657 &priv->extract.qos_key_extract.dpkg,
1658 NET_PROT_IP, NH_FLD_IP_PROTO);
1659 if (index < 0) {
1660 ret = dpaa2_flow_extract_add(
1661 &priv->extract.qos_key_extract,
1662 NET_PROT_IP,
1663 NH_FLD_IP_PROTO,
1664 NH_FLD_IP_PROTO_SIZE);
1665 if (ret) {
1666 DPAA2_PMD_ERR("QoS Extract add IP_DST failed.");
1667
1668 return -1;
1669 }
1670 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1671 }
1672
1673 index = dpaa2_flow_extract_search(
1674 &priv->extract.tc_key_extract[group].dpkg,
1675 NET_PROT_IP, NH_FLD_IP_PROTO);
1676 if (index < 0) {
1677 ret = dpaa2_flow_extract_add(
1678 &priv->extract.tc_key_extract[group],
1679 NET_PROT_IP,
1680 NH_FLD_IP_PROTO,
1681 NH_FLD_IP_PROTO_SIZE);
1682 if (ret) {
1683 DPAA2_PMD_ERR("FS Extract add IP_DST failed.");
1684
1685 return -1;
1686 }
1687 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1688 }
1689
1690 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1691 if (ret) {
1692 DPAA2_PMD_ERR(
1693 "Move ipaddr after NH_FLD_IP_PROTO rule set failed");
1694 return -1;
1695 }
1696
1697 if (spec_ipv4)
1698 key = &spec_ipv4->hdr.next_proto_id;
1699 else
1700 key = &spec_ipv6->hdr.proto;
1701 if (mask_ipv4)
1702 mask = &mask_ipv4->hdr.next_proto_id;
1703 else
1704 mask = &mask_ipv6->hdr.proto;
1705
1706 ret = dpaa2_flow_rule_data_set(
1707 &priv->extract.qos_key_extract,
1708 &flow->qos_rule,
1709 NET_PROT_IP,
1710 NH_FLD_IP_PROTO,
1711 key, mask, NH_FLD_IP_PROTO_SIZE);
1712 if (ret) {
1713 DPAA2_PMD_ERR("QoS NH_FLD_IP_PROTO rule data set failed");
1714 return -1;
1715 }
1716
1717 ret = dpaa2_flow_rule_data_set(
1718 &priv->extract.tc_key_extract[group],
1719 &flow->fs_rule,
1720 NET_PROT_IP,
1721 NH_FLD_IP_PROTO,
1722 key, mask, NH_FLD_IP_PROTO_SIZE);
1723 if (ret) {
1724 DPAA2_PMD_ERR("FS NH_FLD_IP_PROTO rule data set failed");
1725 return -1;
1726 }
1727 }
1728
1729 (*device_configured) |= local_cfg;
1730
1731 return 0;
1732 }
1733
1734 static int
dpaa2_configure_flow_icmp(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)1735 dpaa2_configure_flow_icmp(struct rte_flow *flow,
1736 struct rte_eth_dev *dev,
1737 const struct rte_flow_attr *attr,
1738 const struct rte_flow_item *pattern,
1739 const struct rte_flow_action actions[] __rte_unused,
1740 struct rte_flow_error *error __rte_unused,
1741 int *device_configured)
1742 {
1743 int index, ret;
1744 int local_cfg = 0;
1745 uint32_t group;
1746 const struct rte_flow_item_icmp *spec, *mask;
1747
1748 const struct rte_flow_item_icmp *last __rte_unused;
1749 struct dpaa2_dev_priv *priv = dev->data->dev_private;
1750
1751 group = attr->group;
1752
1753 /* Parse pattern list to get the matching parameters */
1754 spec = (const struct rte_flow_item_icmp *)pattern->spec;
1755 last = (const struct rte_flow_item_icmp *)pattern->last;
1756 mask = (const struct rte_flow_item_icmp *)
1757 (pattern->mask ? pattern->mask : &dpaa2_flow_item_icmp_mask);
1758
1759 /* Get traffic class index and flow id to be configured */
1760 flow->tc_id = group;
1761 flow->tc_index = attr->priority;
1762
1763 if (!spec) {
1764 /* Don't care any field of ICMP header,
1765 * only care ICMP protocol.
1766 * Example: flow create 0 ingress pattern icmp /
1767 */
1768 /* Next proto of Generical IP is actually used
1769 * for ICMP identification.
1770 */
1771 struct proto_discrimination proto;
1772
1773 index = dpaa2_flow_extract_search(
1774 &priv->extract.qos_key_extract.dpkg,
1775 NET_PROT_IP, NH_FLD_IP_PROTO);
1776 if (index < 0) {
1777 ret = dpaa2_flow_proto_discrimination_extract(
1778 &priv->extract.qos_key_extract,
1779 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
1780 if (ret) {
1781 DPAA2_PMD_ERR(
1782 "QoS Extract IP protocol to discriminate ICMP failed.");
1783
1784 return -1;
1785 }
1786 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1787 }
1788
1789 index = dpaa2_flow_extract_search(
1790 &priv->extract.tc_key_extract[group].dpkg,
1791 NET_PROT_IP, NH_FLD_IP_PROTO);
1792 if (index < 0) {
1793 ret = dpaa2_flow_proto_discrimination_extract(
1794 &priv->extract.tc_key_extract[group],
1795 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
1796 if (ret) {
1797 DPAA2_PMD_ERR(
1798 "FS Extract IP protocol to discriminate ICMP failed.");
1799
1800 return -1;
1801 }
1802 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1803 }
1804
1805 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1806 if (ret) {
1807 DPAA2_PMD_ERR(
1808 "Move IP addr before ICMP discrimination set failed");
1809 return -1;
1810 }
1811
1812 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
1813 proto.ip_proto = IPPROTO_ICMP;
1814 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
1815 proto, group);
1816 if (ret) {
1817 DPAA2_PMD_ERR("ICMP discrimination rule set failed");
1818 return -1;
1819 }
1820
1821 (*device_configured) |= local_cfg;
1822
1823 return 0;
1824 }
1825
1826 if (dpaa2_flow_extract_support((const uint8_t *)mask,
1827 RTE_FLOW_ITEM_TYPE_ICMP)) {
1828 DPAA2_PMD_WARN("Extract field(s) of ICMP not support.");
1829
1830 return -1;
1831 }
1832
1833 if (mask->hdr.icmp_type) {
1834 index = dpaa2_flow_extract_search(
1835 &priv->extract.qos_key_extract.dpkg,
1836 NET_PROT_ICMP, NH_FLD_ICMP_TYPE);
1837 if (index < 0) {
1838 ret = dpaa2_flow_extract_add(
1839 &priv->extract.qos_key_extract,
1840 NET_PROT_ICMP,
1841 NH_FLD_ICMP_TYPE,
1842 NH_FLD_ICMP_TYPE_SIZE);
1843 if (ret) {
1844 DPAA2_PMD_ERR("QoS Extract add ICMP_TYPE failed.");
1845
1846 return -1;
1847 }
1848 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1849 }
1850
1851 index = dpaa2_flow_extract_search(
1852 &priv->extract.tc_key_extract[group].dpkg,
1853 NET_PROT_ICMP, NH_FLD_ICMP_TYPE);
1854 if (index < 0) {
1855 ret = dpaa2_flow_extract_add(
1856 &priv->extract.tc_key_extract[group],
1857 NET_PROT_ICMP,
1858 NH_FLD_ICMP_TYPE,
1859 NH_FLD_ICMP_TYPE_SIZE);
1860 if (ret) {
1861 DPAA2_PMD_ERR("FS Extract add ICMP_TYPE failed.");
1862
1863 return -1;
1864 }
1865 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1866 }
1867
1868 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1869 if (ret) {
1870 DPAA2_PMD_ERR(
1871 "Move ipaddr before ICMP TYPE set failed");
1872 return -1;
1873 }
1874
1875 ret = dpaa2_flow_rule_data_set(
1876 &priv->extract.qos_key_extract,
1877 &flow->qos_rule,
1878 NET_PROT_ICMP,
1879 NH_FLD_ICMP_TYPE,
1880 &spec->hdr.icmp_type,
1881 &mask->hdr.icmp_type,
1882 NH_FLD_ICMP_TYPE_SIZE);
1883 if (ret) {
1884 DPAA2_PMD_ERR("QoS NH_FLD_ICMP_TYPE rule data set failed");
1885 return -1;
1886 }
1887
1888 ret = dpaa2_flow_rule_data_set(
1889 &priv->extract.tc_key_extract[group],
1890 &flow->fs_rule,
1891 NET_PROT_ICMP,
1892 NH_FLD_ICMP_TYPE,
1893 &spec->hdr.icmp_type,
1894 &mask->hdr.icmp_type,
1895 NH_FLD_ICMP_TYPE_SIZE);
1896 if (ret) {
1897 DPAA2_PMD_ERR("FS NH_FLD_ICMP_TYPE rule data set failed");
1898 return -1;
1899 }
1900 }
1901
1902 if (mask->hdr.icmp_code) {
1903 index = dpaa2_flow_extract_search(
1904 &priv->extract.qos_key_extract.dpkg,
1905 NET_PROT_ICMP, NH_FLD_ICMP_CODE);
1906 if (index < 0) {
1907 ret = dpaa2_flow_extract_add(
1908 &priv->extract.qos_key_extract,
1909 NET_PROT_ICMP,
1910 NH_FLD_ICMP_CODE,
1911 NH_FLD_ICMP_CODE_SIZE);
1912 if (ret) {
1913 DPAA2_PMD_ERR("QoS Extract add ICMP_CODE failed.");
1914
1915 return -1;
1916 }
1917 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1918 }
1919
1920 index = dpaa2_flow_extract_search(
1921 &priv->extract.tc_key_extract[group].dpkg,
1922 NET_PROT_ICMP, NH_FLD_ICMP_CODE);
1923 if (index < 0) {
1924 ret = dpaa2_flow_extract_add(
1925 &priv->extract.tc_key_extract[group],
1926 NET_PROT_ICMP,
1927 NH_FLD_ICMP_CODE,
1928 NH_FLD_ICMP_CODE_SIZE);
1929 if (ret) {
1930 DPAA2_PMD_ERR("FS Extract add ICMP_CODE failed.");
1931
1932 return -1;
1933 }
1934 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1935 }
1936
1937 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1938 if (ret) {
1939 DPAA2_PMD_ERR(
1940 "Move ipaddr after ICMP CODE set failed");
1941 return -1;
1942 }
1943
1944 ret = dpaa2_flow_rule_data_set(
1945 &priv->extract.qos_key_extract,
1946 &flow->qos_rule,
1947 NET_PROT_ICMP,
1948 NH_FLD_ICMP_CODE,
1949 &spec->hdr.icmp_code,
1950 &mask->hdr.icmp_code,
1951 NH_FLD_ICMP_CODE_SIZE);
1952 if (ret) {
1953 DPAA2_PMD_ERR("QoS NH_FLD_ICMP_CODE rule data set failed");
1954 return -1;
1955 }
1956
1957 ret = dpaa2_flow_rule_data_set(
1958 &priv->extract.tc_key_extract[group],
1959 &flow->fs_rule,
1960 NET_PROT_ICMP,
1961 NH_FLD_ICMP_CODE,
1962 &spec->hdr.icmp_code,
1963 &mask->hdr.icmp_code,
1964 NH_FLD_ICMP_CODE_SIZE);
1965 if (ret) {
1966 DPAA2_PMD_ERR("FS NH_FLD_ICMP_CODE rule data set failed");
1967 return -1;
1968 }
1969 }
1970
1971 (*device_configured) |= local_cfg;
1972
1973 return 0;
1974 }
1975
1976 static int
dpaa2_configure_flow_udp(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)1977 dpaa2_configure_flow_udp(struct rte_flow *flow,
1978 struct rte_eth_dev *dev,
1979 const struct rte_flow_attr *attr,
1980 const struct rte_flow_item *pattern,
1981 const struct rte_flow_action actions[] __rte_unused,
1982 struct rte_flow_error *error __rte_unused,
1983 int *device_configured)
1984 {
1985 int index, ret;
1986 int local_cfg = 0;
1987 uint32_t group;
1988 const struct rte_flow_item_udp *spec, *mask;
1989
1990 const struct rte_flow_item_udp *last __rte_unused;
1991 struct dpaa2_dev_priv *priv = dev->data->dev_private;
1992
1993 group = attr->group;
1994
1995 /* Parse pattern list to get the matching parameters */
1996 spec = (const struct rte_flow_item_udp *)pattern->spec;
1997 last = (const struct rte_flow_item_udp *)pattern->last;
1998 mask = (const struct rte_flow_item_udp *)
1999 (pattern->mask ? pattern->mask : &dpaa2_flow_item_udp_mask);
2000
2001 /* Get traffic class index and flow id to be configured */
2002 flow->tc_id = group;
2003 flow->tc_index = attr->priority;
2004
2005 if (!spec || !mc_l4_port_identification) {
2006 struct proto_discrimination proto;
2007
2008 index = dpaa2_flow_extract_search(
2009 &priv->extract.qos_key_extract.dpkg,
2010 NET_PROT_IP, NH_FLD_IP_PROTO);
2011 if (index < 0) {
2012 ret = dpaa2_flow_proto_discrimination_extract(
2013 &priv->extract.qos_key_extract,
2014 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2015 if (ret) {
2016 DPAA2_PMD_ERR(
2017 "QoS Extract IP protocol to discriminate UDP failed.");
2018
2019 return -1;
2020 }
2021 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2022 }
2023
2024 index = dpaa2_flow_extract_search(
2025 &priv->extract.tc_key_extract[group].dpkg,
2026 NET_PROT_IP, NH_FLD_IP_PROTO);
2027 if (index < 0) {
2028 ret = dpaa2_flow_proto_discrimination_extract(
2029 &priv->extract.tc_key_extract[group],
2030 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2031 if (ret) {
2032 DPAA2_PMD_ERR(
2033 "FS Extract IP protocol to discriminate UDP failed.");
2034
2035 return -1;
2036 }
2037 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2038 }
2039
2040 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2041 if (ret) {
2042 DPAA2_PMD_ERR(
2043 "Move IP addr before UDP discrimination set failed");
2044 return -1;
2045 }
2046
2047 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
2048 proto.ip_proto = IPPROTO_UDP;
2049 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
2050 proto, group);
2051 if (ret) {
2052 DPAA2_PMD_ERR("UDP discrimination rule set failed");
2053 return -1;
2054 }
2055
2056 (*device_configured) |= local_cfg;
2057
2058 if (!spec)
2059 return 0;
2060 }
2061
2062 if (dpaa2_flow_extract_support((const uint8_t *)mask,
2063 RTE_FLOW_ITEM_TYPE_UDP)) {
2064 DPAA2_PMD_WARN("Extract field(s) of UDP not support.");
2065
2066 return -1;
2067 }
2068
2069 if (mask->hdr.src_port) {
2070 index = dpaa2_flow_extract_search(
2071 &priv->extract.qos_key_extract.dpkg,
2072 NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
2073 if (index < 0) {
2074 ret = dpaa2_flow_extract_add(
2075 &priv->extract.qos_key_extract,
2076 NET_PROT_UDP,
2077 NH_FLD_UDP_PORT_SRC,
2078 NH_FLD_UDP_PORT_SIZE);
2079 if (ret) {
2080 DPAA2_PMD_ERR("QoS Extract add UDP_SRC failed.");
2081
2082 return -1;
2083 }
2084 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2085 }
2086
2087 index = dpaa2_flow_extract_search(
2088 &priv->extract.tc_key_extract[group].dpkg,
2089 NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
2090 if (index < 0) {
2091 ret = dpaa2_flow_extract_add(
2092 &priv->extract.tc_key_extract[group],
2093 NET_PROT_UDP,
2094 NH_FLD_UDP_PORT_SRC,
2095 NH_FLD_UDP_PORT_SIZE);
2096 if (ret) {
2097 DPAA2_PMD_ERR("FS Extract add UDP_SRC failed.");
2098
2099 return -1;
2100 }
2101 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2102 }
2103
2104 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2105 if (ret) {
2106 DPAA2_PMD_ERR(
2107 "Move ipaddr before UDP_PORT_SRC set failed");
2108 return -1;
2109 }
2110
2111 ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,
2112 &flow->qos_rule,
2113 NET_PROT_UDP,
2114 NH_FLD_UDP_PORT_SRC,
2115 &spec->hdr.src_port,
2116 &mask->hdr.src_port,
2117 NH_FLD_UDP_PORT_SIZE);
2118 if (ret) {
2119 DPAA2_PMD_ERR(
2120 "QoS NH_FLD_UDP_PORT_SRC rule data set failed");
2121 return -1;
2122 }
2123
2124 ret = dpaa2_flow_rule_data_set(
2125 &priv->extract.tc_key_extract[group],
2126 &flow->fs_rule,
2127 NET_PROT_UDP,
2128 NH_FLD_UDP_PORT_SRC,
2129 &spec->hdr.src_port,
2130 &mask->hdr.src_port,
2131 NH_FLD_UDP_PORT_SIZE);
2132 if (ret) {
2133 DPAA2_PMD_ERR(
2134 "FS NH_FLD_UDP_PORT_SRC rule data set failed");
2135 return -1;
2136 }
2137 }
2138
2139 if (mask->hdr.dst_port) {
2140 index = dpaa2_flow_extract_search(
2141 &priv->extract.qos_key_extract.dpkg,
2142 NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
2143 if (index < 0) {
2144 ret = dpaa2_flow_extract_add(
2145 &priv->extract.qos_key_extract,
2146 NET_PROT_UDP,
2147 NH_FLD_UDP_PORT_DST,
2148 NH_FLD_UDP_PORT_SIZE);
2149 if (ret) {
2150 DPAA2_PMD_ERR("QoS Extract add UDP_DST failed.");
2151
2152 return -1;
2153 }
2154 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2155 }
2156
2157 index = dpaa2_flow_extract_search(
2158 &priv->extract.tc_key_extract[group].dpkg,
2159 NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
2160 if (index < 0) {
2161 ret = dpaa2_flow_extract_add(
2162 &priv->extract.tc_key_extract[group],
2163 NET_PROT_UDP,
2164 NH_FLD_UDP_PORT_DST,
2165 NH_FLD_UDP_PORT_SIZE);
2166 if (ret) {
2167 DPAA2_PMD_ERR("FS Extract add UDP_DST failed.");
2168
2169 return -1;
2170 }
2171 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2172 }
2173
2174 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2175 if (ret) {
2176 DPAA2_PMD_ERR(
2177 "Move ipaddr before UDP_PORT_DST set failed");
2178 return -1;
2179 }
2180
2181 ret = dpaa2_flow_rule_data_set(
2182 &priv->extract.qos_key_extract,
2183 &flow->qos_rule,
2184 NET_PROT_UDP,
2185 NH_FLD_UDP_PORT_DST,
2186 &spec->hdr.dst_port,
2187 &mask->hdr.dst_port,
2188 NH_FLD_UDP_PORT_SIZE);
2189 if (ret) {
2190 DPAA2_PMD_ERR(
2191 "QoS NH_FLD_UDP_PORT_DST rule data set failed");
2192 return -1;
2193 }
2194
2195 ret = dpaa2_flow_rule_data_set(
2196 &priv->extract.tc_key_extract[group],
2197 &flow->fs_rule,
2198 NET_PROT_UDP,
2199 NH_FLD_UDP_PORT_DST,
2200 &spec->hdr.dst_port,
2201 &mask->hdr.dst_port,
2202 NH_FLD_UDP_PORT_SIZE);
2203 if (ret) {
2204 DPAA2_PMD_ERR(
2205 "FS NH_FLD_UDP_PORT_DST rule data set failed");
2206 return -1;
2207 }
2208 }
2209
2210 (*device_configured) |= local_cfg;
2211
2212 return 0;
2213 }
2214
2215 static int
dpaa2_configure_flow_tcp(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)2216 dpaa2_configure_flow_tcp(struct rte_flow *flow,
2217 struct rte_eth_dev *dev,
2218 const struct rte_flow_attr *attr,
2219 const struct rte_flow_item *pattern,
2220 const struct rte_flow_action actions[] __rte_unused,
2221 struct rte_flow_error *error __rte_unused,
2222 int *device_configured)
2223 {
2224 int index, ret;
2225 int local_cfg = 0;
2226 uint32_t group;
2227 const struct rte_flow_item_tcp *spec, *mask;
2228
2229 const struct rte_flow_item_tcp *last __rte_unused;
2230 struct dpaa2_dev_priv *priv = dev->data->dev_private;
2231
2232 group = attr->group;
2233
2234 /* Parse pattern list to get the matching parameters */
2235 spec = (const struct rte_flow_item_tcp *)pattern->spec;
2236 last = (const struct rte_flow_item_tcp *)pattern->last;
2237 mask = (const struct rte_flow_item_tcp *)
2238 (pattern->mask ? pattern->mask : &dpaa2_flow_item_tcp_mask);
2239
2240 /* Get traffic class index and flow id to be configured */
2241 flow->tc_id = group;
2242 flow->tc_index = attr->priority;
2243
2244 if (!spec || !mc_l4_port_identification) {
2245 struct proto_discrimination proto;
2246
2247 index = dpaa2_flow_extract_search(
2248 &priv->extract.qos_key_extract.dpkg,
2249 NET_PROT_IP, NH_FLD_IP_PROTO);
2250 if (index < 0) {
2251 ret = dpaa2_flow_proto_discrimination_extract(
2252 &priv->extract.qos_key_extract,
2253 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2254 if (ret) {
2255 DPAA2_PMD_ERR(
2256 "QoS Extract IP protocol to discriminate TCP failed.");
2257
2258 return -1;
2259 }
2260 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2261 }
2262
2263 index = dpaa2_flow_extract_search(
2264 &priv->extract.tc_key_extract[group].dpkg,
2265 NET_PROT_IP, NH_FLD_IP_PROTO);
2266 if (index < 0) {
2267 ret = dpaa2_flow_proto_discrimination_extract(
2268 &priv->extract.tc_key_extract[group],
2269 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2270 if (ret) {
2271 DPAA2_PMD_ERR(
2272 "FS Extract IP protocol to discriminate TCP failed.");
2273
2274 return -1;
2275 }
2276 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2277 }
2278
2279 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2280 if (ret) {
2281 DPAA2_PMD_ERR(
2282 "Move IP addr before TCP discrimination set failed");
2283 return -1;
2284 }
2285
2286 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
2287 proto.ip_proto = IPPROTO_TCP;
2288 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
2289 proto, group);
2290 if (ret) {
2291 DPAA2_PMD_ERR("TCP discrimination rule set failed");
2292 return -1;
2293 }
2294
2295 (*device_configured) |= local_cfg;
2296
2297 if (!spec)
2298 return 0;
2299 }
2300
2301 if (dpaa2_flow_extract_support((const uint8_t *)mask,
2302 RTE_FLOW_ITEM_TYPE_TCP)) {
2303 DPAA2_PMD_WARN("Extract field(s) of TCP not support.");
2304
2305 return -1;
2306 }
2307
2308 if (mask->hdr.src_port) {
2309 index = dpaa2_flow_extract_search(
2310 &priv->extract.qos_key_extract.dpkg,
2311 NET_PROT_TCP, NH_FLD_TCP_PORT_SRC);
2312 if (index < 0) {
2313 ret = dpaa2_flow_extract_add(
2314 &priv->extract.qos_key_extract,
2315 NET_PROT_TCP,
2316 NH_FLD_TCP_PORT_SRC,
2317 NH_FLD_TCP_PORT_SIZE);
2318 if (ret) {
2319 DPAA2_PMD_ERR("QoS Extract add TCP_SRC failed.");
2320
2321 return -1;
2322 }
2323 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2324 }
2325
2326 index = dpaa2_flow_extract_search(
2327 &priv->extract.tc_key_extract[group].dpkg,
2328 NET_PROT_TCP, NH_FLD_TCP_PORT_SRC);
2329 if (index < 0) {
2330 ret = dpaa2_flow_extract_add(
2331 &priv->extract.tc_key_extract[group],
2332 NET_PROT_TCP,
2333 NH_FLD_TCP_PORT_SRC,
2334 NH_FLD_TCP_PORT_SIZE);
2335 if (ret) {
2336 DPAA2_PMD_ERR("FS Extract add TCP_SRC failed.");
2337
2338 return -1;
2339 }
2340 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2341 }
2342
2343 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2344 if (ret) {
2345 DPAA2_PMD_ERR(
2346 "Move ipaddr before TCP_PORT_SRC set failed");
2347 return -1;
2348 }
2349
2350 ret = dpaa2_flow_rule_data_set(
2351 &priv->extract.qos_key_extract,
2352 &flow->qos_rule,
2353 NET_PROT_TCP,
2354 NH_FLD_TCP_PORT_SRC,
2355 &spec->hdr.src_port,
2356 &mask->hdr.src_port,
2357 NH_FLD_TCP_PORT_SIZE);
2358 if (ret) {
2359 DPAA2_PMD_ERR(
2360 "QoS NH_FLD_TCP_PORT_SRC rule data set failed");
2361 return -1;
2362 }
2363
2364 ret = dpaa2_flow_rule_data_set(
2365 &priv->extract.tc_key_extract[group],
2366 &flow->fs_rule,
2367 NET_PROT_TCP,
2368 NH_FLD_TCP_PORT_SRC,
2369 &spec->hdr.src_port,
2370 &mask->hdr.src_port,
2371 NH_FLD_TCP_PORT_SIZE);
2372 if (ret) {
2373 DPAA2_PMD_ERR(
2374 "FS NH_FLD_TCP_PORT_SRC rule data set failed");
2375 return -1;
2376 }
2377 }
2378
2379 if (mask->hdr.dst_port) {
2380 index = dpaa2_flow_extract_search(
2381 &priv->extract.qos_key_extract.dpkg,
2382 NET_PROT_TCP, NH_FLD_TCP_PORT_DST);
2383 if (index < 0) {
2384 ret = dpaa2_flow_extract_add(
2385 &priv->extract.qos_key_extract,
2386 NET_PROT_TCP,
2387 NH_FLD_TCP_PORT_DST,
2388 NH_FLD_TCP_PORT_SIZE);
2389 if (ret) {
2390 DPAA2_PMD_ERR("QoS Extract add TCP_DST failed.");
2391
2392 return -1;
2393 }
2394 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2395 }
2396
2397 index = dpaa2_flow_extract_search(
2398 &priv->extract.tc_key_extract[group].dpkg,
2399 NET_PROT_TCP, NH_FLD_TCP_PORT_DST);
2400 if (index < 0) {
2401 ret = dpaa2_flow_extract_add(
2402 &priv->extract.tc_key_extract[group],
2403 NET_PROT_TCP,
2404 NH_FLD_TCP_PORT_DST,
2405 NH_FLD_TCP_PORT_SIZE);
2406 if (ret) {
2407 DPAA2_PMD_ERR("FS Extract add TCP_DST failed.");
2408
2409 return -1;
2410 }
2411 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2412 }
2413
2414 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2415 if (ret) {
2416 DPAA2_PMD_ERR(
2417 "Move ipaddr before TCP_PORT_DST set failed");
2418 return -1;
2419 }
2420
2421 ret = dpaa2_flow_rule_data_set(
2422 &priv->extract.qos_key_extract,
2423 &flow->qos_rule,
2424 NET_PROT_TCP,
2425 NH_FLD_TCP_PORT_DST,
2426 &spec->hdr.dst_port,
2427 &mask->hdr.dst_port,
2428 NH_FLD_TCP_PORT_SIZE);
2429 if (ret) {
2430 DPAA2_PMD_ERR(
2431 "QoS NH_FLD_TCP_PORT_DST rule data set failed");
2432 return -1;
2433 }
2434
2435 ret = dpaa2_flow_rule_data_set(
2436 &priv->extract.tc_key_extract[group],
2437 &flow->fs_rule,
2438 NET_PROT_TCP,
2439 NH_FLD_TCP_PORT_DST,
2440 &spec->hdr.dst_port,
2441 &mask->hdr.dst_port,
2442 NH_FLD_TCP_PORT_SIZE);
2443 if (ret) {
2444 DPAA2_PMD_ERR(
2445 "FS NH_FLD_TCP_PORT_DST rule data set failed");
2446 return -1;
2447 }
2448 }
2449
2450 (*device_configured) |= local_cfg;
2451
2452 return 0;
2453 }
2454
2455 static int
dpaa2_configure_flow_sctp(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)2456 dpaa2_configure_flow_sctp(struct rte_flow *flow,
2457 struct rte_eth_dev *dev,
2458 const struct rte_flow_attr *attr,
2459 const struct rte_flow_item *pattern,
2460 const struct rte_flow_action actions[] __rte_unused,
2461 struct rte_flow_error *error __rte_unused,
2462 int *device_configured)
2463 {
2464 int index, ret;
2465 int local_cfg = 0;
2466 uint32_t group;
2467 const struct rte_flow_item_sctp *spec, *mask;
2468
2469 const struct rte_flow_item_sctp *last __rte_unused;
2470 struct dpaa2_dev_priv *priv = dev->data->dev_private;
2471
2472 group = attr->group;
2473
2474 /* Parse pattern list to get the matching parameters */
2475 spec = (const struct rte_flow_item_sctp *)pattern->spec;
2476 last = (const struct rte_flow_item_sctp *)pattern->last;
2477 mask = (const struct rte_flow_item_sctp *)
2478 (pattern->mask ? pattern->mask :
2479 &dpaa2_flow_item_sctp_mask);
2480
2481 /* Get traffic class index and flow id to be configured */
2482 flow->tc_id = group;
2483 flow->tc_index = attr->priority;
2484
2485 if (!spec || !mc_l4_port_identification) {
2486 struct proto_discrimination proto;
2487
2488 index = dpaa2_flow_extract_search(
2489 &priv->extract.qos_key_extract.dpkg,
2490 NET_PROT_IP, NH_FLD_IP_PROTO);
2491 if (index < 0) {
2492 ret = dpaa2_flow_proto_discrimination_extract(
2493 &priv->extract.qos_key_extract,
2494 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2495 if (ret) {
2496 DPAA2_PMD_ERR(
2497 "QoS Extract IP protocol to discriminate SCTP failed.");
2498
2499 return -1;
2500 }
2501 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2502 }
2503
2504 index = dpaa2_flow_extract_search(
2505 &priv->extract.tc_key_extract[group].dpkg,
2506 NET_PROT_IP, NH_FLD_IP_PROTO);
2507 if (index < 0) {
2508 ret = dpaa2_flow_proto_discrimination_extract(
2509 &priv->extract.tc_key_extract[group],
2510 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2511 if (ret) {
2512 DPAA2_PMD_ERR(
2513 "FS Extract IP protocol to discriminate SCTP failed.");
2514
2515 return -1;
2516 }
2517 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2518 }
2519
2520 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2521 if (ret) {
2522 DPAA2_PMD_ERR(
2523 "Move ipaddr before SCTP discrimination set failed");
2524 return -1;
2525 }
2526
2527 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
2528 proto.ip_proto = IPPROTO_SCTP;
2529 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
2530 proto, group);
2531 if (ret) {
2532 DPAA2_PMD_ERR("SCTP discrimination rule set failed");
2533 return -1;
2534 }
2535
2536 (*device_configured) |= local_cfg;
2537
2538 if (!spec)
2539 return 0;
2540 }
2541
2542 if (dpaa2_flow_extract_support((const uint8_t *)mask,
2543 RTE_FLOW_ITEM_TYPE_SCTP)) {
2544 DPAA2_PMD_WARN("Extract field(s) of SCTP not support.");
2545
2546 return -1;
2547 }
2548
2549 if (mask->hdr.src_port) {
2550 index = dpaa2_flow_extract_search(
2551 &priv->extract.qos_key_extract.dpkg,
2552 NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);
2553 if (index < 0) {
2554 ret = dpaa2_flow_extract_add(
2555 &priv->extract.qos_key_extract,
2556 NET_PROT_SCTP,
2557 NH_FLD_SCTP_PORT_SRC,
2558 NH_FLD_SCTP_PORT_SIZE);
2559 if (ret) {
2560 DPAA2_PMD_ERR("QoS Extract add SCTP_SRC failed.");
2561
2562 return -1;
2563 }
2564 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2565 }
2566
2567 index = dpaa2_flow_extract_search(
2568 &priv->extract.tc_key_extract[group].dpkg,
2569 NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);
2570 if (index < 0) {
2571 ret = dpaa2_flow_extract_add(
2572 &priv->extract.tc_key_extract[group],
2573 NET_PROT_SCTP,
2574 NH_FLD_SCTP_PORT_SRC,
2575 NH_FLD_SCTP_PORT_SIZE);
2576 if (ret) {
2577 DPAA2_PMD_ERR("FS Extract add SCTP_SRC failed.");
2578
2579 return -1;
2580 }
2581 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2582 }
2583
2584 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2585 if (ret) {
2586 DPAA2_PMD_ERR(
2587 "Move ipaddr before SCTP_PORT_SRC set failed");
2588 return -1;
2589 }
2590
2591 ret = dpaa2_flow_rule_data_set(
2592 &priv->extract.qos_key_extract,
2593 &flow->qos_rule,
2594 NET_PROT_SCTP,
2595 NH_FLD_SCTP_PORT_SRC,
2596 &spec->hdr.src_port,
2597 &mask->hdr.src_port,
2598 NH_FLD_SCTP_PORT_SIZE);
2599 if (ret) {
2600 DPAA2_PMD_ERR(
2601 "QoS NH_FLD_SCTP_PORT_SRC rule data set failed");
2602 return -1;
2603 }
2604
2605 ret = dpaa2_flow_rule_data_set(
2606 &priv->extract.tc_key_extract[group],
2607 &flow->fs_rule,
2608 NET_PROT_SCTP,
2609 NH_FLD_SCTP_PORT_SRC,
2610 &spec->hdr.src_port,
2611 &mask->hdr.src_port,
2612 NH_FLD_SCTP_PORT_SIZE);
2613 if (ret) {
2614 DPAA2_PMD_ERR(
2615 "FS NH_FLD_SCTP_PORT_SRC rule data set failed");
2616 return -1;
2617 }
2618 }
2619
2620 if (mask->hdr.dst_port) {
2621 index = dpaa2_flow_extract_search(
2622 &priv->extract.qos_key_extract.dpkg,
2623 NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);
2624 if (index < 0) {
2625 ret = dpaa2_flow_extract_add(
2626 &priv->extract.qos_key_extract,
2627 NET_PROT_SCTP,
2628 NH_FLD_SCTP_PORT_DST,
2629 NH_FLD_SCTP_PORT_SIZE);
2630 if (ret) {
2631 DPAA2_PMD_ERR("QoS Extract add SCTP_DST failed.");
2632
2633 return -1;
2634 }
2635 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2636 }
2637
2638 index = dpaa2_flow_extract_search(
2639 &priv->extract.tc_key_extract[group].dpkg,
2640 NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);
2641 if (index < 0) {
2642 ret = dpaa2_flow_extract_add(
2643 &priv->extract.tc_key_extract[group],
2644 NET_PROT_SCTP,
2645 NH_FLD_SCTP_PORT_DST,
2646 NH_FLD_SCTP_PORT_SIZE);
2647 if (ret) {
2648 DPAA2_PMD_ERR("FS Extract add SCTP_DST failed.");
2649
2650 return -1;
2651 }
2652 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2653 }
2654
2655 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2656 if (ret) {
2657 DPAA2_PMD_ERR(
2658 "Move ipaddr before SCTP_PORT_DST set failed");
2659 return -1;
2660 }
2661
2662 ret = dpaa2_flow_rule_data_set(
2663 &priv->extract.qos_key_extract,
2664 &flow->qos_rule,
2665 NET_PROT_SCTP,
2666 NH_FLD_SCTP_PORT_DST,
2667 &spec->hdr.dst_port,
2668 &mask->hdr.dst_port,
2669 NH_FLD_SCTP_PORT_SIZE);
2670 if (ret) {
2671 DPAA2_PMD_ERR(
2672 "QoS NH_FLD_SCTP_PORT_DST rule data set failed");
2673 return -1;
2674 }
2675
2676 ret = dpaa2_flow_rule_data_set(
2677 &priv->extract.tc_key_extract[group],
2678 &flow->fs_rule,
2679 NET_PROT_SCTP,
2680 NH_FLD_SCTP_PORT_DST,
2681 &spec->hdr.dst_port,
2682 &mask->hdr.dst_port,
2683 NH_FLD_SCTP_PORT_SIZE);
2684 if (ret) {
2685 DPAA2_PMD_ERR(
2686 "FS NH_FLD_SCTP_PORT_DST rule data set failed");
2687 return -1;
2688 }
2689 }
2690
2691 (*device_configured) |= local_cfg;
2692
2693 return 0;
2694 }
2695
2696 static int
dpaa2_configure_flow_gre(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)2697 dpaa2_configure_flow_gre(struct rte_flow *flow,
2698 struct rte_eth_dev *dev,
2699 const struct rte_flow_attr *attr,
2700 const struct rte_flow_item *pattern,
2701 const struct rte_flow_action actions[] __rte_unused,
2702 struct rte_flow_error *error __rte_unused,
2703 int *device_configured)
2704 {
2705 int index, ret;
2706 int local_cfg = 0;
2707 uint32_t group;
2708 const struct rte_flow_item_gre *spec, *mask;
2709
2710 const struct rte_flow_item_gre *last __rte_unused;
2711 struct dpaa2_dev_priv *priv = dev->data->dev_private;
2712
2713 group = attr->group;
2714
2715 /* Parse pattern list to get the matching parameters */
2716 spec = (const struct rte_flow_item_gre *)pattern->spec;
2717 last = (const struct rte_flow_item_gre *)pattern->last;
2718 mask = (const struct rte_flow_item_gre *)
2719 (pattern->mask ? pattern->mask : &dpaa2_flow_item_gre_mask);
2720
2721 /* Get traffic class index and flow id to be configured */
2722 flow->tc_id = group;
2723 flow->tc_index = attr->priority;
2724
2725 if (!spec) {
2726 struct proto_discrimination proto;
2727
2728 index = dpaa2_flow_extract_search(
2729 &priv->extract.qos_key_extract.dpkg,
2730 NET_PROT_IP, NH_FLD_IP_PROTO);
2731 if (index < 0) {
2732 ret = dpaa2_flow_proto_discrimination_extract(
2733 &priv->extract.qos_key_extract,
2734 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2735 if (ret) {
2736 DPAA2_PMD_ERR(
2737 "QoS Extract IP protocol to discriminate GRE failed.");
2738
2739 return -1;
2740 }
2741 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2742 }
2743
2744 index = dpaa2_flow_extract_search(
2745 &priv->extract.tc_key_extract[group].dpkg,
2746 NET_PROT_IP, NH_FLD_IP_PROTO);
2747 if (index < 0) {
2748 ret = dpaa2_flow_proto_discrimination_extract(
2749 &priv->extract.tc_key_extract[group],
2750 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2751 if (ret) {
2752 DPAA2_PMD_ERR(
2753 "FS Extract IP protocol to discriminate GRE failed.");
2754
2755 return -1;
2756 }
2757 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2758 }
2759
2760 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2761 if (ret) {
2762 DPAA2_PMD_ERR(
2763 "Move IP addr before GRE discrimination set failed");
2764 return -1;
2765 }
2766
2767 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
2768 proto.ip_proto = IPPROTO_GRE;
2769 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
2770 proto, group);
2771 if (ret) {
2772 DPAA2_PMD_ERR("GRE discrimination rule set failed");
2773 return -1;
2774 }
2775
2776 (*device_configured) |= local_cfg;
2777
2778 return 0;
2779 }
2780
2781 if (dpaa2_flow_extract_support((const uint8_t *)mask,
2782 RTE_FLOW_ITEM_TYPE_GRE)) {
2783 DPAA2_PMD_WARN("Extract field(s) of GRE not support.");
2784
2785 return -1;
2786 }
2787
2788 if (!mask->protocol)
2789 return 0;
2790
2791 index = dpaa2_flow_extract_search(
2792 &priv->extract.qos_key_extract.dpkg,
2793 NET_PROT_GRE, NH_FLD_GRE_TYPE);
2794 if (index < 0) {
2795 ret = dpaa2_flow_extract_add(
2796 &priv->extract.qos_key_extract,
2797 NET_PROT_GRE,
2798 NH_FLD_GRE_TYPE,
2799 sizeof(rte_be16_t));
2800 if (ret) {
2801 DPAA2_PMD_ERR("QoS Extract add GRE_TYPE failed.");
2802
2803 return -1;
2804 }
2805 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2806 }
2807
2808 index = dpaa2_flow_extract_search(
2809 &priv->extract.tc_key_extract[group].dpkg,
2810 NET_PROT_GRE, NH_FLD_GRE_TYPE);
2811 if (index < 0) {
2812 ret = dpaa2_flow_extract_add(
2813 &priv->extract.tc_key_extract[group],
2814 NET_PROT_GRE,
2815 NH_FLD_GRE_TYPE,
2816 sizeof(rte_be16_t));
2817 if (ret) {
2818 DPAA2_PMD_ERR("FS Extract add GRE_TYPE failed.");
2819
2820 return -1;
2821 }
2822 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2823 }
2824
2825 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2826 if (ret) {
2827 DPAA2_PMD_ERR(
2828 "Move ipaddr before GRE_TYPE set failed");
2829 return -1;
2830 }
2831
2832 ret = dpaa2_flow_rule_data_set(
2833 &priv->extract.qos_key_extract,
2834 &flow->qos_rule,
2835 NET_PROT_GRE,
2836 NH_FLD_GRE_TYPE,
2837 &spec->protocol,
2838 &mask->protocol,
2839 sizeof(rte_be16_t));
2840 if (ret) {
2841 DPAA2_PMD_ERR(
2842 "QoS NH_FLD_GRE_TYPE rule data set failed");
2843 return -1;
2844 }
2845
2846 ret = dpaa2_flow_rule_data_set(
2847 &priv->extract.tc_key_extract[group],
2848 &flow->fs_rule,
2849 NET_PROT_GRE,
2850 NH_FLD_GRE_TYPE,
2851 &spec->protocol,
2852 &mask->protocol,
2853 sizeof(rte_be16_t));
2854 if (ret) {
2855 DPAA2_PMD_ERR(
2856 "FS NH_FLD_GRE_TYPE rule data set failed");
2857 return -1;
2858 }
2859
2860 (*device_configured) |= local_cfg;
2861
2862 return 0;
2863 }
2864
2865 static int
dpaa2_configure_flow_raw(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item * pattern,const struct rte_flow_action actions[]__rte_unused,struct rte_flow_error * error __rte_unused,int * device_configured)2866 dpaa2_configure_flow_raw(struct rte_flow *flow,
2867 struct rte_eth_dev *dev,
2868 const struct rte_flow_attr *attr,
2869 const struct rte_flow_item *pattern,
2870 const struct rte_flow_action actions[] __rte_unused,
2871 struct rte_flow_error *error __rte_unused,
2872 int *device_configured)
2873 {
2874 struct dpaa2_dev_priv *priv = dev->data->dev_private;
2875 const struct rte_flow_item_raw *spec = pattern->spec;
2876 const struct rte_flow_item_raw *mask = pattern->mask;
2877 int prev_key_size =
2878 priv->extract.qos_key_extract.key_info.key_total_size;
2879 int local_cfg = 0, ret;
2880 uint32_t group;
2881
2882 /* Need both spec and mask */
2883 if (!spec || !mask) {
2884 DPAA2_PMD_ERR("spec or mask not present.");
2885 return -EINVAL;
2886 }
2887 /* Only supports non-relative with offset 0 */
2888 if (spec->relative || spec->offset != 0 ||
2889 spec->search || spec->limit) {
2890 DPAA2_PMD_ERR("relative and non zero offset not supported.");
2891 return -EINVAL;
2892 }
2893 /* Spec len and mask len should be same */
2894 if (spec->length != mask->length) {
2895 DPAA2_PMD_ERR("Spec len and mask len mismatch.");
2896 return -EINVAL;
2897 }
2898
2899 /* Get traffic class index and flow id to be configured */
2900 group = attr->group;
2901 flow->tc_id = group;
2902 flow->tc_index = attr->priority;
2903
2904 if (prev_key_size <= spec->length) {
2905 ret = dpaa2_flow_extract_add_raw(&priv->extract.qos_key_extract,
2906 spec->length);
2907 if (ret) {
2908 DPAA2_PMD_ERR("QoS Extract RAW add failed.");
2909 return -1;
2910 }
2911 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2912
2913 ret = dpaa2_flow_extract_add_raw(
2914 &priv->extract.tc_key_extract[group],
2915 spec->length);
2916 if (ret) {
2917 DPAA2_PMD_ERR("FS Extract RAW add failed.");
2918 return -1;
2919 }
2920 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2921 }
2922
2923 ret = dpaa2_flow_rule_data_set_raw(&flow->qos_rule, spec->pattern,
2924 mask->pattern, spec->length);
2925 if (ret) {
2926 DPAA2_PMD_ERR("QoS RAW rule data set failed");
2927 return -1;
2928 }
2929
2930 ret = dpaa2_flow_rule_data_set_raw(&flow->fs_rule, spec->pattern,
2931 mask->pattern, spec->length);
2932 if (ret) {
2933 DPAA2_PMD_ERR("FS RAW rule data set failed");
2934 return -1;
2935 }
2936
2937 (*device_configured) |= local_cfg;
2938
2939 return 0;
2940 }
2941
2942 /* The existing QoS/FS entry with IP address(es)
2943 * needs update after
2944 * new extract(s) are inserted before IP
2945 * address(es) extract(s).
2946 */
2947 static int
dpaa2_flow_entry_update(struct dpaa2_dev_priv * priv,uint8_t tc_id)2948 dpaa2_flow_entry_update(
2949 struct dpaa2_dev_priv *priv, uint8_t tc_id)
2950 {
2951 struct rte_flow *curr = LIST_FIRST(&priv->flows);
2952 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
2953 int ret;
2954 int qos_ipsrc_offset = -1, qos_ipdst_offset = -1;
2955 int fs_ipsrc_offset = -1, fs_ipdst_offset = -1;
2956 struct dpaa2_key_extract *qos_key_extract =
2957 &priv->extract.qos_key_extract;
2958 struct dpaa2_key_extract *tc_key_extract =
2959 &priv->extract.tc_key_extract[tc_id];
2960 char ipsrc_key[NH_FLD_IPV6_ADDR_SIZE];
2961 char ipdst_key[NH_FLD_IPV6_ADDR_SIZE];
2962 char ipsrc_mask[NH_FLD_IPV6_ADDR_SIZE];
2963 char ipdst_mask[NH_FLD_IPV6_ADDR_SIZE];
2964 int extend = -1, extend1, size = -1;
2965 uint16_t qos_index;
2966
2967 while (curr) {
2968 if (curr->ipaddr_rule.ipaddr_type ==
2969 FLOW_NONE_IPADDR) {
2970 curr = LIST_NEXT(curr, next);
2971 continue;
2972 }
2973
2974 if (curr->ipaddr_rule.ipaddr_type ==
2975 FLOW_IPV4_ADDR) {
2976 qos_ipsrc_offset =
2977 qos_key_extract->key_info.ipv4_src_offset;
2978 qos_ipdst_offset =
2979 qos_key_extract->key_info.ipv4_dst_offset;
2980 fs_ipsrc_offset =
2981 tc_key_extract->key_info.ipv4_src_offset;
2982 fs_ipdst_offset =
2983 tc_key_extract->key_info.ipv4_dst_offset;
2984 size = NH_FLD_IPV4_ADDR_SIZE;
2985 } else {
2986 qos_ipsrc_offset =
2987 qos_key_extract->key_info.ipv6_src_offset;
2988 qos_ipdst_offset =
2989 qos_key_extract->key_info.ipv6_dst_offset;
2990 fs_ipsrc_offset =
2991 tc_key_extract->key_info.ipv6_src_offset;
2992 fs_ipdst_offset =
2993 tc_key_extract->key_info.ipv6_dst_offset;
2994 size = NH_FLD_IPV6_ADDR_SIZE;
2995 }
2996
2997 qos_index = curr->tc_id * priv->fs_entries +
2998 curr->tc_index;
2999
3000 dpaa2_flow_qos_entry_log("Before update", curr, qos_index);
3001
3002 if (priv->num_rx_tc > 1) {
3003 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
3004 priv->token, &curr->qos_rule);
3005 if (ret) {
3006 DPAA2_PMD_ERR("Qos entry remove failed.");
3007 return -1;
3008 }
3009 }
3010
3011 extend = -1;
3012
3013 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
3014 RTE_ASSERT(qos_ipsrc_offset >=
3015 curr->ipaddr_rule.qos_ipsrc_offset);
3016 extend1 = qos_ipsrc_offset -
3017 curr->ipaddr_rule.qos_ipsrc_offset;
3018 if (extend >= 0)
3019 RTE_ASSERT(extend == extend1);
3020 else
3021 extend = extend1;
3022
3023 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
3024 (size == NH_FLD_IPV6_ADDR_SIZE));
3025
3026 memcpy(ipsrc_key,
3027 (char *)(size_t)curr->qos_rule.key_iova +
3028 curr->ipaddr_rule.qos_ipsrc_offset,
3029 size);
3030 memset((char *)(size_t)curr->qos_rule.key_iova +
3031 curr->ipaddr_rule.qos_ipsrc_offset,
3032 0, size);
3033
3034 memcpy(ipsrc_mask,
3035 (char *)(size_t)curr->qos_rule.mask_iova +
3036 curr->ipaddr_rule.qos_ipsrc_offset,
3037 size);
3038 memset((char *)(size_t)curr->qos_rule.mask_iova +
3039 curr->ipaddr_rule.qos_ipsrc_offset,
3040 0, size);
3041
3042 curr->ipaddr_rule.qos_ipsrc_offset = qos_ipsrc_offset;
3043 }
3044
3045 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
3046 RTE_ASSERT(qos_ipdst_offset >=
3047 curr->ipaddr_rule.qos_ipdst_offset);
3048 extend1 = qos_ipdst_offset -
3049 curr->ipaddr_rule.qos_ipdst_offset;
3050 if (extend >= 0)
3051 RTE_ASSERT(extend == extend1);
3052 else
3053 extend = extend1;
3054
3055 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
3056 (size == NH_FLD_IPV6_ADDR_SIZE));
3057
3058 memcpy(ipdst_key,
3059 (char *)(size_t)curr->qos_rule.key_iova +
3060 curr->ipaddr_rule.qos_ipdst_offset,
3061 size);
3062 memset((char *)(size_t)curr->qos_rule.key_iova +
3063 curr->ipaddr_rule.qos_ipdst_offset,
3064 0, size);
3065
3066 memcpy(ipdst_mask,
3067 (char *)(size_t)curr->qos_rule.mask_iova +
3068 curr->ipaddr_rule.qos_ipdst_offset,
3069 size);
3070 memset((char *)(size_t)curr->qos_rule.mask_iova +
3071 curr->ipaddr_rule.qos_ipdst_offset,
3072 0, size);
3073
3074 curr->ipaddr_rule.qos_ipdst_offset = qos_ipdst_offset;
3075 }
3076
3077 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
3078 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
3079 (size == NH_FLD_IPV6_ADDR_SIZE));
3080 memcpy((char *)(size_t)curr->qos_rule.key_iova +
3081 curr->ipaddr_rule.qos_ipsrc_offset,
3082 ipsrc_key,
3083 size);
3084 memcpy((char *)(size_t)curr->qos_rule.mask_iova +
3085 curr->ipaddr_rule.qos_ipsrc_offset,
3086 ipsrc_mask,
3087 size);
3088 }
3089 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
3090 RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
3091 (size == NH_FLD_IPV6_ADDR_SIZE));
3092 memcpy((char *)(size_t)curr->qos_rule.key_iova +
3093 curr->ipaddr_rule.qos_ipdst_offset,
3094 ipdst_key,
3095 size);
3096 memcpy((char *)(size_t)curr->qos_rule.mask_iova +
3097 curr->ipaddr_rule.qos_ipdst_offset,
3098 ipdst_mask,
3099 size);
3100 }
3101
3102 if (extend >= 0)
3103 curr->qos_real_key_size += extend;
3104
3105 curr->qos_rule.key_size = FIXED_ENTRY_SIZE;
3106
3107 dpaa2_flow_qos_entry_log("Start update", curr, qos_index);
3108
3109 if (priv->num_rx_tc > 1) {
3110 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
3111 priv->token, &curr->qos_rule,
3112 curr->tc_id, qos_index,
3113 0, 0);
3114 if (ret) {
3115 DPAA2_PMD_ERR("Qos entry update failed.");
3116 return -1;
3117 }
3118 }
3119
3120 if (curr->action != RTE_FLOW_ACTION_TYPE_QUEUE) {
3121 curr = LIST_NEXT(curr, next);
3122 continue;
3123 }
3124
3125 dpaa2_flow_fs_entry_log("Before update", curr);
3126 extend = -1;
3127
3128 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW,
3129 priv->token, curr->tc_id, &curr->fs_rule);
3130 if (ret) {
3131 DPAA2_PMD_ERR("FS entry remove failed.");
3132 return -1;
3133 }
3134
3135 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0 &&
3136 tc_id == curr->tc_id) {
3137 RTE_ASSERT(fs_ipsrc_offset >=
3138 curr->ipaddr_rule.fs_ipsrc_offset);
3139 extend1 = fs_ipsrc_offset -
3140 curr->ipaddr_rule.fs_ipsrc_offset;
3141 if (extend >= 0)
3142 RTE_ASSERT(extend == extend1);
3143 else
3144 extend = extend1;
3145
3146 memcpy(ipsrc_key,
3147 (char *)(size_t)curr->fs_rule.key_iova +
3148 curr->ipaddr_rule.fs_ipsrc_offset,
3149 size);
3150 memset((char *)(size_t)curr->fs_rule.key_iova +
3151 curr->ipaddr_rule.fs_ipsrc_offset,
3152 0, size);
3153
3154 memcpy(ipsrc_mask,
3155 (char *)(size_t)curr->fs_rule.mask_iova +
3156 curr->ipaddr_rule.fs_ipsrc_offset,
3157 size);
3158 memset((char *)(size_t)curr->fs_rule.mask_iova +
3159 curr->ipaddr_rule.fs_ipsrc_offset,
3160 0, size);
3161
3162 curr->ipaddr_rule.fs_ipsrc_offset = fs_ipsrc_offset;
3163 }
3164
3165 if (curr->ipaddr_rule.fs_ipdst_offset >= 0 &&
3166 tc_id == curr->tc_id) {
3167 RTE_ASSERT(fs_ipdst_offset >=
3168 curr->ipaddr_rule.fs_ipdst_offset);
3169 extend1 = fs_ipdst_offset -
3170 curr->ipaddr_rule.fs_ipdst_offset;
3171 if (extend >= 0)
3172 RTE_ASSERT(extend == extend1);
3173 else
3174 extend = extend1;
3175
3176 memcpy(ipdst_key,
3177 (char *)(size_t)curr->fs_rule.key_iova +
3178 curr->ipaddr_rule.fs_ipdst_offset,
3179 size);
3180 memset((char *)(size_t)curr->fs_rule.key_iova +
3181 curr->ipaddr_rule.fs_ipdst_offset,
3182 0, size);
3183
3184 memcpy(ipdst_mask,
3185 (char *)(size_t)curr->fs_rule.mask_iova +
3186 curr->ipaddr_rule.fs_ipdst_offset,
3187 size);
3188 memset((char *)(size_t)curr->fs_rule.mask_iova +
3189 curr->ipaddr_rule.fs_ipdst_offset,
3190 0, size);
3191
3192 curr->ipaddr_rule.fs_ipdst_offset = fs_ipdst_offset;
3193 }
3194
3195 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0) {
3196 memcpy((char *)(size_t)curr->fs_rule.key_iova +
3197 curr->ipaddr_rule.fs_ipsrc_offset,
3198 ipsrc_key,
3199 size);
3200 memcpy((char *)(size_t)curr->fs_rule.mask_iova +
3201 curr->ipaddr_rule.fs_ipsrc_offset,
3202 ipsrc_mask,
3203 size);
3204 }
3205 if (curr->ipaddr_rule.fs_ipdst_offset >= 0) {
3206 memcpy((char *)(size_t)curr->fs_rule.key_iova +
3207 curr->ipaddr_rule.fs_ipdst_offset,
3208 ipdst_key,
3209 size);
3210 memcpy((char *)(size_t)curr->fs_rule.mask_iova +
3211 curr->ipaddr_rule.fs_ipdst_offset,
3212 ipdst_mask,
3213 size);
3214 }
3215
3216 if (extend >= 0)
3217 curr->fs_real_key_size += extend;
3218 curr->fs_rule.key_size = FIXED_ENTRY_SIZE;
3219
3220 dpaa2_flow_fs_entry_log("Start update", curr);
3221
3222 ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
3223 priv->token, curr->tc_id, curr->tc_index,
3224 &curr->fs_rule, &curr->action_cfg);
3225 if (ret) {
3226 DPAA2_PMD_ERR("FS entry update failed.");
3227 return -1;
3228 }
3229
3230 curr = LIST_NEXT(curr, next);
3231 }
3232
3233 return 0;
3234 }
3235
3236 static inline int
dpaa2_flow_verify_attr(struct dpaa2_dev_priv * priv,const struct rte_flow_attr * attr)3237 dpaa2_flow_verify_attr(
3238 struct dpaa2_dev_priv *priv,
3239 const struct rte_flow_attr *attr)
3240 {
3241 struct rte_flow *curr = LIST_FIRST(&priv->flows);
3242
3243 while (curr) {
3244 if (curr->tc_id == attr->group &&
3245 curr->tc_index == attr->priority) {
3246 DPAA2_PMD_ERR(
3247 "Flow with group %d and priority %d already exists.",
3248 attr->group, attr->priority);
3249
3250 return -1;
3251 }
3252 curr = LIST_NEXT(curr, next);
3253 }
3254
3255 return 0;
3256 }
3257
3258 static inline int
dpaa2_flow_verify_action(struct dpaa2_dev_priv * priv,const struct rte_flow_attr * attr,const struct rte_flow_action actions[])3259 dpaa2_flow_verify_action(
3260 struct dpaa2_dev_priv *priv,
3261 const struct rte_flow_attr *attr,
3262 const struct rte_flow_action actions[])
3263 {
3264 int end_of_list = 0, i, j = 0;
3265 const struct rte_flow_action_queue *dest_queue;
3266 const struct rte_flow_action_rss *rss_conf;
3267 struct dpaa2_queue *rxq;
3268
3269 while (!end_of_list) {
3270 switch (actions[j].type) {
3271 case RTE_FLOW_ACTION_TYPE_QUEUE:
3272 dest_queue = (const struct rte_flow_action_queue *)
3273 (actions[j].conf);
3274 rxq = priv->rx_vq[dest_queue->index];
3275 if (attr->group != rxq->tc_index) {
3276 DPAA2_PMD_ERR(
3277 "RXQ[%d] does not belong to the group %d",
3278 dest_queue->index, attr->group);
3279
3280 return -1;
3281 }
3282 break;
3283 case RTE_FLOW_ACTION_TYPE_RSS:
3284 rss_conf = (const struct rte_flow_action_rss *)
3285 (actions[j].conf);
3286 if (rss_conf->queue_num > priv->dist_queues) {
3287 DPAA2_PMD_ERR(
3288 "RSS number exceeds the distrbution size");
3289 return -ENOTSUP;
3290 }
3291 for (i = 0; i < (int)rss_conf->queue_num; i++) {
3292 if (rss_conf->queue[i] >= priv->nb_rx_queues) {
3293 DPAA2_PMD_ERR(
3294 "RSS queue index exceeds the number of RXQs");
3295 return -ENOTSUP;
3296 }
3297 rxq = priv->rx_vq[rss_conf->queue[i]];
3298 if (rxq->tc_index != attr->group) {
3299 DPAA2_PMD_ERR(
3300 "Queue/Group combination are not supported\n");
3301 return -ENOTSUP;
3302 }
3303 }
3304
3305 break;
3306 case RTE_FLOW_ACTION_TYPE_END:
3307 end_of_list = 1;
3308 break;
3309 default:
3310 DPAA2_PMD_ERR("Invalid action type");
3311 return -ENOTSUP;
3312 }
3313 j++;
3314 }
3315
3316 return 0;
3317 }
3318
3319 static int
dpaa2_generic_flow_set(struct rte_flow * flow,struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item pattern[],const struct rte_flow_action actions[],struct rte_flow_error * error)3320 dpaa2_generic_flow_set(struct rte_flow *flow,
3321 struct rte_eth_dev *dev,
3322 const struct rte_flow_attr *attr,
3323 const struct rte_flow_item pattern[],
3324 const struct rte_flow_action actions[],
3325 struct rte_flow_error *error)
3326 {
3327 const struct rte_flow_action_queue *dest_queue;
3328 const struct rte_flow_action_rss *rss_conf;
3329 int is_keycfg_configured = 0, end_of_list = 0;
3330 int ret = 0, i = 0, j = 0;
3331 struct dpni_rx_dist_cfg tc_cfg;
3332 struct dpni_qos_tbl_cfg qos_cfg;
3333 struct dpni_fs_action_cfg action;
3334 struct dpaa2_dev_priv *priv = dev->data->dev_private;
3335 struct dpaa2_queue *rxq;
3336 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
3337 size_t param;
3338 struct rte_flow *curr = LIST_FIRST(&priv->flows);
3339 uint16_t qos_index;
3340
3341 ret = dpaa2_flow_verify_attr(priv, attr);
3342 if (ret)
3343 return ret;
3344
3345 ret = dpaa2_flow_verify_action(priv, attr, actions);
3346 if (ret)
3347 return ret;
3348
3349 /* Parse pattern list to get the matching parameters */
3350 while (!end_of_list) {
3351 switch (pattern[i].type) {
3352 case RTE_FLOW_ITEM_TYPE_ETH:
3353 ret = dpaa2_configure_flow_eth(flow,
3354 dev, attr, &pattern[i], actions, error,
3355 &is_keycfg_configured);
3356 if (ret) {
3357 DPAA2_PMD_ERR("ETH flow configuration failed!");
3358 return ret;
3359 }
3360 break;
3361 case RTE_FLOW_ITEM_TYPE_VLAN:
3362 ret = dpaa2_configure_flow_vlan(flow,
3363 dev, attr, &pattern[i], actions, error,
3364 &is_keycfg_configured);
3365 if (ret) {
3366 DPAA2_PMD_ERR("vLan flow configuration failed!");
3367 return ret;
3368 }
3369 break;
3370 case RTE_FLOW_ITEM_TYPE_IPV4:
3371 case RTE_FLOW_ITEM_TYPE_IPV6:
3372 ret = dpaa2_configure_flow_generic_ip(flow,
3373 dev, attr, &pattern[i], actions, error,
3374 &is_keycfg_configured);
3375 if (ret) {
3376 DPAA2_PMD_ERR("IP flow configuration failed!");
3377 return ret;
3378 }
3379 break;
3380 case RTE_FLOW_ITEM_TYPE_ICMP:
3381 ret = dpaa2_configure_flow_icmp(flow,
3382 dev, attr, &pattern[i], actions, error,
3383 &is_keycfg_configured);
3384 if (ret) {
3385 DPAA2_PMD_ERR("ICMP flow configuration failed!");
3386 return ret;
3387 }
3388 break;
3389 case RTE_FLOW_ITEM_TYPE_UDP:
3390 ret = dpaa2_configure_flow_udp(flow,
3391 dev, attr, &pattern[i], actions, error,
3392 &is_keycfg_configured);
3393 if (ret) {
3394 DPAA2_PMD_ERR("UDP flow configuration failed!");
3395 return ret;
3396 }
3397 break;
3398 case RTE_FLOW_ITEM_TYPE_TCP:
3399 ret = dpaa2_configure_flow_tcp(flow,
3400 dev, attr, &pattern[i], actions, error,
3401 &is_keycfg_configured);
3402 if (ret) {
3403 DPAA2_PMD_ERR("TCP flow configuration failed!");
3404 return ret;
3405 }
3406 break;
3407 case RTE_FLOW_ITEM_TYPE_SCTP:
3408 ret = dpaa2_configure_flow_sctp(flow,
3409 dev, attr, &pattern[i], actions, error,
3410 &is_keycfg_configured);
3411 if (ret) {
3412 DPAA2_PMD_ERR("SCTP flow configuration failed!");
3413 return ret;
3414 }
3415 break;
3416 case RTE_FLOW_ITEM_TYPE_GRE:
3417 ret = dpaa2_configure_flow_gre(flow,
3418 dev, attr, &pattern[i], actions, error,
3419 &is_keycfg_configured);
3420 if (ret) {
3421 DPAA2_PMD_ERR("GRE flow configuration failed!");
3422 return ret;
3423 }
3424 break;
3425 case RTE_FLOW_ITEM_TYPE_RAW:
3426 ret = dpaa2_configure_flow_raw(flow,
3427 dev, attr, &pattern[i],
3428 actions, error,
3429 &is_keycfg_configured);
3430 if (ret) {
3431 DPAA2_PMD_ERR("RAW flow configuration failed!");
3432 return ret;
3433 }
3434 break;
3435 case RTE_FLOW_ITEM_TYPE_END:
3436 end_of_list = 1;
3437 break; /*End of List*/
3438 default:
3439 DPAA2_PMD_ERR("Invalid action type");
3440 ret = -ENOTSUP;
3441 break;
3442 }
3443 i++;
3444 }
3445
3446 /* Let's parse action on matching traffic */
3447 end_of_list = 0;
3448 while (!end_of_list) {
3449 switch (actions[j].type) {
3450 case RTE_FLOW_ACTION_TYPE_QUEUE:
3451 dest_queue =
3452 (const struct rte_flow_action_queue *)(actions[j].conf);
3453 rxq = priv->rx_vq[dest_queue->index];
3454 flow->action = RTE_FLOW_ACTION_TYPE_QUEUE;
3455 memset(&action, 0, sizeof(struct dpni_fs_action_cfg));
3456 action.flow_id = rxq->flow_id;
3457
3458 /* Configure FS table first*/
3459 if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {
3460 dpaa2_flow_fs_table_extracts_log(priv, flow->tc_id);
3461 if (dpkg_prepare_key_cfg(
3462 &priv->extract.tc_key_extract[flow->tc_id].dpkg,
3463 (uint8_t *)(size_t)priv->extract
3464 .tc_extract_param[flow->tc_id]) < 0) {
3465 DPAA2_PMD_ERR(
3466 "Unable to prepare extract parameters");
3467 return -1;
3468 }
3469
3470 memset(&tc_cfg, 0,
3471 sizeof(struct dpni_rx_dist_cfg));
3472 tc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc;
3473 tc_cfg.key_cfg_iova =
3474 (uint64_t)priv->extract.tc_extract_param[flow->tc_id];
3475 tc_cfg.tc = flow->tc_id;
3476 tc_cfg.enable = false;
3477 ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW,
3478 priv->token, &tc_cfg);
3479 if (ret < 0) {
3480 DPAA2_PMD_ERR(
3481 "TC hash cannot be disabled.(%d)",
3482 ret);
3483 return -1;
3484 }
3485 tc_cfg.enable = true;
3486 tc_cfg.fs_miss_flow_id =
3487 dpaa2_flow_miss_flow_id;
3488 ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW,
3489 priv->token, &tc_cfg);
3490 if (ret < 0) {
3491 DPAA2_PMD_ERR(
3492 "TC distribution cannot be configured.(%d)",
3493 ret);
3494 return -1;
3495 }
3496 }
3497
3498 /* Configure QoS table then.*/
3499 if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
3500 dpaa2_flow_qos_table_extracts_log(priv);
3501 if (dpkg_prepare_key_cfg(
3502 &priv->extract.qos_key_extract.dpkg,
3503 (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
3504 DPAA2_PMD_ERR(
3505 "Unable to prepare extract parameters");
3506 return -1;
3507 }
3508
3509 memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg));
3510 qos_cfg.discard_on_miss = false;
3511 qos_cfg.default_tc = 0;
3512 qos_cfg.keep_entries = true;
3513 qos_cfg.key_cfg_iova =
3514 (size_t)priv->extract.qos_extract_param;
3515 /* QoS table is effecitive for multiple TCs.*/
3516 if (priv->num_rx_tc > 1) {
3517 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
3518 priv->token, &qos_cfg);
3519 if (ret < 0) {
3520 DPAA2_PMD_ERR(
3521 "RSS QoS table can not be configured(%d)\n",
3522 ret);
3523 return -1;
3524 }
3525 }
3526 }
3527
3528 flow->qos_real_key_size = priv->extract
3529 .qos_key_extract.key_info.key_total_size;
3530 if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR) {
3531 if (flow->ipaddr_rule.qos_ipdst_offset >=
3532 flow->ipaddr_rule.qos_ipsrc_offset) {
3533 flow->qos_real_key_size =
3534 flow->ipaddr_rule.qos_ipdst_offset +
3535 NH_FLD_IPV4_ADDR_SIZE;
3536 } else {
3537 flow->qos_real_key_size =
3538 flow->ipaddr_rule.qos_ipsrc_offset +
3539 NH_FLD_IPV4_ADDR_SIZE;
3540 }
3541 } else if (flow->ipaddr_rule.ipaddr_type ==
3542 FLOW_IPV6_ADDR) {
3543 if (flow->ipaddr_rule.qos_ipdst_offset >=
3544 flow->ipaddr_rule.qos_ipsrc_offset) {
3545 flow->qos_real_key_size =
3546 flow->ipaddr_rule.qos_ipdst_offset +
3547 NH_FLD_IPV6_ADDR_SIZE;
3548 } else {
3549 flow->qos_real_key_size =
3550 flow->ipaddr_rule.qos_ipsrc_offset +
3551 NH_FLD_IPV6_ADDR_SIZE;
3552 }
3553 }
3554
3555 /* QoS entry added is only effective for multiple TCs.*/
3556 if (priv->num_rx_tc > 1) {
3557 qos_index = flow->tc_id * priv->fs_entries +
3558 flow->tc_index;
3559 if (qos_index >= priv->qos_entries) {
3560 DPAA2_PMD_ERR("QoS table with %d entries full",
3561 priv->qos_entries);
3562 return -1;
3563 }
3564 flow->qos_rule.key_size = FIXED_ENTRY_SIZE;
3565
3566 dpaa2_flow_qos_entry_log("Start add", flow, qos_index);
3567
3568 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
3569 priv->token, &flow->qos_rule,
3570 flow->tc_id, qos_index,
3571 0, 0);
3572 if (ret < 0) {
3573 DPAA2_PMD_ERR(
3574 "Error in addnig entry to QoS table(%d)", ret);
3575 return ret;
3576 }
3577 }
3578
3579 if (flow->tc_index >= priv->fs_entries) {
3580 DPAA2_PMD_ERR("FS table with %d entries full",
3581 priv->fs_entries);
3582 return -1;
3583 }
3584
3585 flow->fs_real_key_size =
3586 priv->extract.tc_key_extract[flow->tc_id]
3587 .key_info.key_total_size;
3588
3589 if (flow->ipaddr_rule.ipaddr_type ==
3590 FLOW_IPV4_ADDR) {
3591 if (flow->ipaddr_rule.fs_ipdst_offset >=
3592 flow->ipaddr_rule.fs_ipsrc_offset) {
3593 flow->fs_real_key_size =
3594 flow->ipaddr_rule.fs_ipdst_offset +
3595 NH_FLD_IPV4_ADDR_SIZE;
3596 } else {
3597 flow->fs_real_key_size =
3598 flow->ipaddr_rule.fs_ipsrc_offset +
3599 NH_FLD_IPV4_ADDR_SIZE;
3600 }
3601 } else if (flow->ipaddr_rule.ipaddr_type ==
3602 FLOW_IPV6_ADDR) {
3603 if (flow->ipaddr_rule.fs_ipdst_offset >=
3604 flow->ipaddr_rule.fs_ipsrc_offset) {
3605 flow->fs_real_key_size =
3606 flow->ipaddr_rule.fs_ipdst_offset +
3607 NH_FLD_IPV6_ADDR_SIZE;
3608 } else {
3609 flow->fs_real_key_size =
3610 flow->ipaddr_rule.fs_ipsrc_offset +
3611 NH_FLD_IPV6_ADDR_SIZE;
3612 }
3613 }
3614
3615 flow->fs_rule.key_size = FIXED_ENTRY_SIZE;
3616
3617 dpaa2_flow_fs_entry_log("Start add", flow);
3618
3619 ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token,
3620 flow->tc_id, flow->tc_index,
3621 &flow->fs_rule, &action);
3622 if (ret < 0) {
3623 DPAA2_PMD_ERR(
3624 "Error in adding entry to FS table(%d)", ret);
3625 return ret;
3626 }
3627 memcpy(&flow->action_cfg, &action,
3628 sizeof(struct dpni_fs_action_cfg));
3629 break;
3630 case RTE_FLOW_ACTION_TYPE_RSS:
3631 rss_conf = (const struct rte_flow_action_rss *)(actions[j].conf);
3632
3633 flow->action = RTE_FLOW_ACTION_TYPE_RSS;
3634 ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types,
3635 &priv->extract.tc_key_extract[flow->tc_id].dpkg);
3636 if (ret < 0) {
3637 DPAA2_PMD_ERR(
3638 "unable to set flow distribution.please check queue config\n");
3639 return ret;
3640 }
3641
3642 /* Allocate DMA'ble memory to write the rules */
3643 param = (size_t)rte_malloc(NULL, 256, 64);
3644 if (!param) {
3645 DPAA2_PMD_ERR("Memory allocation failure\n");
3646 return -1;
3647 }
3648
3649 if (dpkg_prepare_key_cfg(
3650 &priv->extract.tc_key_extract[flow->tc_id].dpkg,
3651 (uint8_t *)param) < 0) {
3652 DPAA2_PMD_ERR(
3653 "Unable to prepare extract parameters");
3654 rte_free((void *)param);
3655 return -1;
3656 }
3657
3658 memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
3659 tc_cfg.dist_size = rss_conf->queue_num;
3660 tc_cfg.key_cfg_iova = (size_t)param;
3661 tc_cfg.enable = true;
3662 tc_cfg.tc = flow->tc_id;
3663 ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW,
3664 priv->token, &tc_cfg);
3665 if (ret < 0) {
3666 DPAA2_PMD_ERR(
3667 "RSS TC table cannot be configured: %d\n",
3668 ret);
3669 rte_free((void *)param);
3670 return -1;
3671 }
3672
3673 rte_free((void *)param);
3674 if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
3675 if (dpkg_prepare_key_cfg(
3676 &priv->extract.qos_key_extract.dpkg,
3677 (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
3678 DPAA2_PMD_ERR(
3679 "Unable to prepare extract parameters");
3680 return -1;
3681 }
3682 memset(&qos_cfg, 0,
3683 sizeof(struct dpni_qos_tbl_cfg));
3684 qos_cfg.discard_on_miss = true;
3685 qos_cfg.keep_entries = true;
3686 qos_cfg.key_cfg_iova =
3687 (size_t)priv->extract.qos_extract_param;
3688 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
3689 priv->token, &qos_cfg);
3690 if (ret < 0) {
3691 DPAA2_PMD_ERR(
3692 "RSS QoS dist can't be configured-%d\n",
3693 ret);
3694 return -1;
3695 }
3696 }
3697
3698 /* Add Rule into QoS table */
3699 qos_index = flow->tc_id * priv->fs_entries +
3700 flow->tc_index;
3701 if (qos_index >= priv->qos_entries) {
3702 DPAA2_PMD_ERR("QoS table with %d entries full",
3703 priv->qos_entries);
3704 return -1;
3705 }
3706
3707 flow->qos_real_key_size =
3708 priv->extract.qos_key_extract.key_info.key_total_size;
3709 flow->qos_rule.key_size = FIXED_ENTRY_SIZE;
3710 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token,
3711 &flow->qos_rule, flow->tc_id,
3712 qos_index, 0, 0);
3713 if (ret < 0) {
3714 DPAA2_PMD_ERR(
3715 "Error in entry addition in QoS table(%d)",
3716 ret);
3717 return ret;
3718 }
3719 break;
3720 case RTE_FLOW_ACTION_TYPE_END:
3721 end_of_list = 1;
3722 break;
3723 default:
3724 DPAA2_PMD_ERR("Invalid action type");
3725 ret = -ENOTSUP;
3726 break;
3727 }
3728 j++;
3729 }
3730
3731 if (!ret) {
3732 if (is_keycfg_configured &
3733 (DPAA2_QOS_TABLE_RECONFIGURE |
3734 DPAA2_FS_TABLE_RECONFIGURE)) {
3735 ret = dpaa2_flow_entry_update(priv, flow->tc_id);
3736 if (ret) {
3737 DPAA2_PMD_ERR("Flow entry update failed.");
3738
3739 return -1;
3740 }
3741 }
3742 /* New rules are inserted. */
3743 if (!curr) {
3744 LIST_INSERT_HEAD(&priv->flows, flow, next);
3745 } else {
3746 while (LIST_NEXT(curr, next))
3747 curr = LIST_NEXT(curr, next);
3748 LIST_INSERT_AFTER(curr, flow, next);
3749 }
3750 }
3751 return ret;
3752 }
3753
3754 static inline int
dpaa2_dev_verify_attr(struct dpni_attr * dpni_attr,const struct rte_flow_attr * attr)3755 dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr,
3756 const struct rte_flow_attr *attr)
3757 {
3758 int ret = 0;
3759
3760 if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) {
3761 DPAA2_PMD_ERR("Priority group is out of range\n");
3762 ret = -ENOTSUP;
3763 }
3764 if (unlikely(attr->priority >= dpni_attr->fs_entries)) {
3765 DPAA2_PMD_ERR("Priority within the group is out of range\n");
3766 ret = -ENOTSUP;
3767 }
3768 if (unlikely(attr->egress)) {
3769 DPAA2_PMD_ERR(
3770 "Flow configuration is not supported on egress side\n");
3771 ret = -ENOTSUP;
3772 }
3773 if (unlikely(!attr->ingress)) {
3774 DPAA2_PMD_ERR("Ingress flag must be configured\n");
3775 ret = -EINVAL;
3776 }
3777 return ret;
3778 }
3779
3780 static inline int
dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[])3781 dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[])
3782 {
3783 unsigned int i, j, is_found = 0;
3784 int ret = 0;
3785
3786 for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
3787 for (i = 0; i < RTE_DIM(dpaa2_supported_pattern_type); i++) {
3788 if (dpaa2_supported_pattern_type[i]
3789 == pattern[j].type) {
3790 is_found = 1;
3791 break;
3792 }
3793 }
3794 if (!is_found) {
3795 ret = -ENOTSUP;
3796 break;
3797 }
3798 }
3799 /* Lets verify other combinations of given pattern rules */
3800 for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
3801 if (!pattern[j].spec) {
3802 ret = -EINVAL;
3803 break;
3804 }
3805 }
3806
3807 return ret;
3808 }
3809
3810 static inline int
dpaa2_dev_verify_actions(const struct rte_flow_action actions[])3811 dpaa2_dev_verify_actions(const struct rte_flow_action actions[])
3812 {
3813 unsigned int i, j, is_found = 0;
3814 int ret = 0;
3815
3816 for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
3817 for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) {
3818 if (dpaa2_supported_action_type[i] == actions[j].type) {
3819 is_found = 1;
3820 break;
3821 }
3822 }
3823 if (!is_found) {
3824 ret = -ENOTSUP;
3825 break;
3826 }
3827 }
3828 for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
3829 if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP &&
3830 !actions[j].conf)
3831 ret = -EINVAL;
3832 }
3833 return ret;
3834 }
3835
3836 static
dpaa2_flow_validate(struct rte_eth_dev * dev,const struct rte_flow_attr * flow_attr,const struct rte_flow_item pattern[],const struct rte_flow_action actions[],struct rte_flow_error * error)3837 int dpaa2_flow_validate(struct rte_eth_dev *dev,
3838 const struct rte_flow_attr *flow_attr,
3839 const struct rte_flow_item pattern[],
3840 const struct rte_flow_action actions[],
3841 struct rte_flow_error *error)
3842 {
3843 struct dpaa2_dev_priv *priv = dev->data->dev_private;
3844 struct dpni_attr dpni_attr;
3845 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
3846 uint16_t token = priv->token;
3847 int ret = 0;
3848
3849 memset(&dpni_attr, 0, sizeof(struct dpni_attr));
3850 ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr);
3851 if (ret < 0) {
3852 DPAA2_PMD_ERR(
3853 "Failure to get dpni@%p attribute, err code %d\n",
3854 dpni, ret);
3855 rte_flow_error_set(error, EPERM,
3856 RTE_FLOW_ERROR_TYPE_ATTR,
3857 flow_attr, "invalid");
3858 return ret;
3859 }
3860
3861 /* Verify input attributes */
3862 ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr);
3863 if (ret < 0) {
3864 DPAA2_PMD_ERR(
3865 "Invalid attributes are given\n");
3866 rte_flow_error_set(error, EPERM,
3867 RTE_FLOW_ERROR_TYPE_ATTR,
3868 flow_attr, "invalid");
3869 goto not_valid_params;
3870 }
3871 /* Verify input pattern list */
3872 ret = dpaa2_dev_verify_patterns(pattern);
3873 if (ret < 0) {
3874 DPAA2_PMD_ERR(
3875 "Invalid pattern list is given\n");
3876 rte_flow_error_set(error, EPERM,
3877 RTE_FLOW_ERROR_TYPE_ITEM,
3878 pattern, "invalid");
3879 goto not_valid_params;
3880 }
3881 /* Verify input action list */
3882 ret = dpaa2_dev_verify_actions(actions);
3883 if (ret < 0) {
3884 DPAA2_PMD_ERR(
3885 "Invalid action list is given\n");
3886 rte_flow_error_set(error, EPERM,
3887 RTE_FLOW_ERROR_TYPE_ACTION,
3888 actions, "invalid");
3889 goto not_valid_params;
3890 }
3891 not_valid_params:
3892 return ret;
3893 }
3894
3895 static
dpaa2_flow_create(struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item pattern[],const struct rte_flow_action actions[],struct rte_flow_error * error)3896 struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev,
3897 const struct rte_flow_attr *attr,
3898 const struct rte_flow_item pattern[],
3899 const struct rte_flow_action actions[],
3900 struct rte_flow_error *error)
3901 {
3902 struct rte_flow *flow = NULL;
3903 size_t key_iova = 0, mask_iova = 0;
3904 int ret;
3905
3906 dpaa2_flow_control_log =
3907 getenv("DPAA2_FLOW_CONTROL_LOG");
3908
3909 if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) {
3910 struct dpaa2_dev_priv *priv = dev->data->dev_private;
3911
3912 dpaa2_flow_miss_flow_id =
3913 atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW"));
3914 if (dpaa2_flow_miss_flow_id >= priv->dist_queues) {
3915 DPAA2_PMD_ERR(
3916 "The missed flow ID %d exceeds the max flow ID %d",
3917 dpaa2_flow_miss_flow_id,
3918 priv->dist_queues - 1);
3919 return NULL;
3920 }
3921 }
3922
3923 flow = rte_zmalloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE);
3924 if (!flow) {
3925 DPAA2_PMD_ERR("Failure to allocate memory for flow");
3926 goto mem_failure;
3927 }
3928 /* Allocate DMA'ble memory to write the rules */
3929 key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3930 if (!key_iova) {
3931 DPAA2_PMD_ERR(
3932 "Memory allocation failure for rule configuration\n");
3933 goto mem_failure;
3934 }
3935 mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3936 if (!mask_iova) {
3937 DPAA2_PMD_ERR(
3938 "Memory allocation failure for rule configuration\n");
3939 goto mem_failure;
3940 }
3941
3942 flow->qos_rule.key_iova = key_iova;
3943 flow->qos_rule.mask_iova = mask_iova;
3944
3945 /* Allocate DMA'ble memory to write the rules */
3946 key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3947 if (!key_iova) {
3948 DPAA2_PMD_ERR(
3949 "Memory allocation failure for rule configuration\n");
3950 goto mem_failure;
3951 }
3952 mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3953 if (!mask_iova) {
3954 DPAA2_PMD_ERR(
3955 "Memory allocation failure for rule configuration\n");
3956 goto mem_failure;
3957 }
3958
3959 flow->fs_rule.key_iova = key_iova;
3960 flow->fs_rule.mask_iova = mask_iova;
3961
3962 flow->ipaddr_rule.ipaddr_type = FLOW_NONE_IPADDR;
3963 flow->ipaddr_rule.qos_ipsrc_offset =
3964 IP_ADDRESS_OFFSET_INVALID;
3965 flow->ipaddr_rule.qos_ipdst_offset =
3966 IP_ADDRESS_OFFSET_INVALID;
3967 flow->ipaddr_rule.fs_ipsrc_offset =
3968 IP_ADDRESS_OFFSET_INVALID;
3969 flow->ipaddr_rule.fs_ipdst_offset =
3970 IP_ADDRESS_OFFSET_INVALID;
3971
3972 switch (dpaa2_filter_type) {
3973 case RTE_ETH_FILTER_GENERIC:
3974 ret = dpaa2_generic_flow_set(flow, dev, attr, pattern,
3975 actions, error);
3976 if (ret < 0) {
3977 if (error->type > RTE_FLOW_ERROR_TYPE_ACTION)
3978 rte_flow_error_set(error, EPERM,
3979 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3980 attr, "unknown");
3981 DPAA2_PMD_ERR(
3982 "Failure to create flow, return code (%d)", ret);
3983 goto creation_error;
3984 }
3985 break;
3986 default:
3987 DPAA2_PMD_ERR("Filter type (%d) not supported",
3988 dpaa2_filter_type);
3989 break;
3990 }
3991
3992 return flow;
3993 mem_failure:
3994 rte_flow_error_set(error, EPERM,
3995 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3996 NULL, "memory alloc");
3997 creation_error:
3998 rte_free((void *)flow);
3999 rte_free((void *)key_iova);
4000 rte_free((void *)mask_iova);
4001
4002 return NULL;
4003 }
4004
4005 static
dpaa2_flow_destroy(struct rte_eth_dev * dev,struct rte_flow * flow,struct rte_flow_error * error)4006 int dpaa2_flow_destroy(struct rte_eth_dev *dev,
4007 struct rte_flow *flow,
4008 struct rte_flow_error *error)
4009 {
4010 int ret = 0;
4011 struct dpaa2_dev_priv *priv = dev->data->dev_private;
4012 struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
4013
4014 switch (flow->action) {
4015 case RTE_FLOW_ACTION_TYPE_QUEUE:
4016 if (priv->num_rx_tc > 1) {
4017 /* Remove entry from QoS table first */
4018 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
4019 &flow->qos_rule);
4020 if (ret < 0) {
4021 DPAA2_PMD_ERR(
4022 "Error in removing entry from QoS table(%d)", ret);
4023 goto error;
4024 }
4025 }
4026
4027 /* Then remove entry from FS table */
4028 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,
4029 flow->tc_id, &flow->fs_rule);
4030 if (ret < 0) {
4031 DPAA2_PMD_ERR(
4032 "Error in removing entry from FS table(%d)", ret);
4033 goto error;
4034 }
4035 break;
4036 case RTE_FLOW_ACTION_TYPE_RSS:
4037 if (priv->num_rx_tc > 1) {
4038 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
4039 &flow->qos_rule);
4040 if (ret < 0) {
4041 DPAA2_PMD_ERR(
4042 "Error in entry addition in QoS table(%d)", ret);
4043 goto error;
4044 }
4045 }
4046 break;
4047 default:
4048 DPAA2_PMD_ERR(
4049 "Action type (%d) is not supported", flow->action);
4050 ret = -ENOTSUP;
4051 break;
4052 }
4053
4054 LIST_REMOVE(flow, next);
4055 rte_free((void *)(size_t)flow->qos_rule.key_iova);
4056 rte_free((void *)(size_t)flow->qos_rule.mask_iova);
4057 rte_free((void *)(size_t)flow->fs_rule.key_iova);
4058 rte_free((void *)(size_t)flow->fs_rule.mask_iova);
4059 /* Now free the flow */
4060 rte_free(flow);
4061
4062 error:
4063 if (ret)
4064 rte_flow_error_set(error, EPERM,
4065 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
4066 NULL, "unknown");
4067 return ret;
4068 }
4069
4070 /**
4071 * Destroy user-configured flow rules.
4072 *
4073 * This function skips internal flows rules.
4074 *
4075 * @see rte_flow_flush()
4076 * @see rte_flow_ops
4077 */
4078 static int
dpaa2_flow_flush(struct rte_eth_dev * dev,struct rte_flow_error * error)4079 dpaa2_flow_flush(struct rte_eth_dev *dev,
4080 struct rte_flow_error *error)
4081 {
4082 struct dpaa2_dev_priv *priv = dev->data->dev_private;
4083 struct rte_flow *flow = LIST_FIRST(&priv->flows);
4084
4085 while (flow) {
4086 struct rte_flow *next = LIST_NEXT(flow, next);
4087
4088 dpaa2_flow_destroy(dev, flow, error);
4089 flow = next;
4090 }
4091 return 0;
4092 }
4093
4094 static int
dpaa2_flow_query(struct rte_eth_dev * dev __rte_unused,struct rte_flow * flow __rte_unused,const struct rte_flow_action * actions __rte_unused,void * data __rte_unused,struct rte_flow_error * error __rte_unused)4095 dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
4096 struct rte_flow *flow __rte_unused,
4097 const struct rte_flow_action *actions __rte_unused,
4098 void *data __rte_unused,
4099 struct rte_flow_error *error __rte_unused)
4100 {
4101 return 0;
4102 }
4103
4104 /**
4105 * Clean up all flow rules.
4106 *
4107 * Unlike dpaa2_flow_flush(), this function takes care of all remaining flow
4108 * rules regardless of whether they are internal or user-configured.
4109 *
4110 * @param priv
4111 * Pointer to private structure.
4112 */
4113 void
dpaa2_flow_clean(struct rte_eth_dev * dev)4114 dpaa2_flow_clean(struct rte_eth_dev *dev)
4115 {
4116 struct rte_flow *flow;
4117 struct dpaa2_dev_priv *priv = dev->data->dev_private;
4118
4119 while ((flow = LIST_FIRST(&priv->flows)))
4120 dpaa2_flow_destroy(dev, flow, NULL);
4121 }
4122
4123 const struct rte_flow_ops dpaa2_flow_ops = {
4124 .create = dpaa2_flow_create,
4125 .validate = dpaa2_flow_validate,
4126 .destroy = dpaa2_flow_destroy,
4127 .flush = dpaa2_flow_flush,
4128 .query = dpaa2_flow_query,
4129 };
4130