xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 92e68d9c97730ede6539d8f4c5748065aae96134)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5 
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include <rte_string_fns.h>
16 #include <rte_common.h>
17 #include <rte_ethdev.h>
18 #include <rte_byteorder.h>
19 #include <cmdline_parse.h>
20 #include <cmdline_parse_etheraddr.h>
21 #include <cmdline_parse_string.h>
22 #include <cmdline_parse_num.h>
23 #include <rte_flow.h>
24 #include <rte_hexdump.h>
25 #include <rte_vxlan.h>
26 #include <rte_gre.h>
27 #include <rte_mpls.h>
28 #include <rte_gtp.h>
29 #include <rte_geneve.h>
30 
31 #include "testpmd.h"
32 
33 /** Parser token indices. */
34 enum index {
35 	/* Special tokens. */
36 	ZERO = 0,
37 	END,
38 	START_SET,
39 	END_SET,
40 
41 	/* Common tokens. */
42 	COMMON_INTEGER,
43 	COMMON_UNSIGNED,
44 	COMMON_PREFIX,
45 	COMMON_BOOLEAN,
46 	COMMON_STRING,
47 	COMMON_HEX,
48 	COMMON_FILE_PATH,
49 	COMMON_MAC_ADDR,
50 	COMMON_IPV4_ADDR,
51 	COMMON_IPV6_ADDR,
52 	COMMON_RULE_ID,
53 	COMMON_PORT_ID,
54 	COMMON_GROUP_ID,
55 	COMMON_PRIORITY_LEVEL,
56 	COMMON_INDIRECT_ACTION_ID,
57 	COMMON_PROFILE_ID,
58 	COMMON_POLICY_ID,
59 	COMMON_FLEX_HANDLE,
60 	COMMON_FLEX_TOKEN,
61 	COMMON_PATTERN_TEMPLATE_ID,
62 	COMMON_ACTIONS_TEMPLATE_ID,
63 	COMMON_TABLE_ID,
64 	COMMON_QUEUE_ID,
65 
66 	/* TOP-level command. */
67 	ADD,
68 
69 	/* Top-level command. */
70 	SET,
71 	/* Sub-leve commands. */
72 	SET_RAW_ENCAP,
73 	SET_RAW_DECAP,
74 	SET_RAW_INDEX,
75 	SET_SAMPLE_ACTIONS,
76 	SET_SAMPLE_INDEX,
77 	SET_IPV6_EXT_REMOVE,
78 	SET_IPV6_EXT_PUSH,
79 	SET_IPV6_EXT_INDEX,
80 
81 	/* Top-level command. */
82 	FLOW,
83 	/* Sub-level commands. */
84 	INFO,
85 	CONFIGURE,
86 	PATTERN_TEMPLATE,
87 	ACTIONS_TEMPLATE,
88 	TABLE,
89 	FLOW_GROUP,
90 	INDIRECT_ACTION,
91 	VALIDATE,
92 	CREATE,
93 	DESTROY,
94 	UPDATE,
95 	FLUSH,
96 	DUMP,
97 	QUERY,
98 	LIST,
99 	AGED,
100 	ISOLATE,
101 	TUNNEL,
102 	FLEX,
103 	QUEUE,
104 	PUSH,
105 	PULL,
106 	HASH,
107 
108 	/* Flex arguments */
109 	FLEX_ITEM_INIT,
110 	FLEX_ITEM_CREATE,
111 	FLEX_ITEM_DESTROY,
112 
113 	/* Pattern template arguments. */
114 	PATTERN_TEMPLATE_CREATE,
115 	PATTERN_TEMPLATE_DESTROY,
116 	PATTERN_TEMPLATE_CREATE_ID,
117 	PATTERN_TEMPLATE_DESTROY_ID,
118 	PATTERN_TEMPLATE_RELAXED_MATCHING,
119 	PATTERN_TEMPLATE_INGRESS,
120 	PATTERN_TEMPLATE_EGRESS,
121 	PATTERN_TEMPLATE_TRANSFER,
122 	PATTERN_TEMPLATE_SPEC,
123 
124 	/* Actions template arguments. */
125 	ACTIONS_TEMPLATE_CREATE,
126 	ACTIONS_TEMPLATE_DESTROY,
127 	ACTIONS_TEMPLATE_CREATE_ID,
128 	ACTIONS_TEMPLATE_DESTROY_ID,
129 	ACTIONS_TEMPLATE_INGRESS,
130 	ACTIONS_TEMPLATE_EGRESS,
131 	ACTIONS_TEMPLATE_TRANSFER,
132 	ACTIONS_TEMPLATE_SPEC,
133 	ACTIONS_TEMPLATE_MASK,
134 
135 	/* Queue arguments. */
136 	QUEUE_CREATE,
137 	QUEUE_DESTROY,
138 	QUEUE_FLOW_UPDATE_RESIZED,
139 	QUEUE_UPDATE,
140 	QUEUE_AGED,
141 	QUEUE_INDIRECT_ACTION,
142 
143 	/* Queue create arguments. */
144 	QUEUE_CREATE_POSTPONE,
145 	QUEUE_TEMPLATE_TABLE,
146 	QUEUE_PATTERN_TEMPLATE,
147 	QUEUE_ACTIONS_TEMPLATE,
148 	QUEUE_RULE_ID,
149 
150 	/* Queue destroy arguments. */
151 	QUEUE_DESTROY_ID,
152 	QUEUE_DESTROY_POSTPONE,
153 
154 	/* Queue update arguments. */
155 	QUEUE_UPDATE_ID,
156 
157 	/* Queue indirect action arguments */
158 	QUEUE_INDIRECT_ACTION_CREATE,
159 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
160 	QUEUE_INDIRECT_ACTION_UPDATE,
161 	QUEUE_INDIRECT_ACTION_DESTROY,
162 	QUEUE_INDIRECT_ACTION_QUERY,
163 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
164 
165 	/* Queue indirect action create arguments */
166 	QUEUE_INDIRECT_ACTION_CREATE_ID,
167 	QUEUE_INDIRECT_ACTION_INGRESS,
168 	QUEUE_INDIRECT_ACTION_EGRESS,
169 	QUEUE_INDIRECT_ACTION_TRANSFER,
170 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
171 	QUEUE_INDIRECT_ACTION_SPEC,
172 	QUEUE_INDIRECT_ACTION_LIST,
173 
174 	/* Queue indirect action update arguments */
175 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
176 
177 	/* Queue indirect action destroy arguments */
178 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
179 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
180 
181 	/* Queue indirect action query arguments */
182 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
183 
184 	/* Queue indirect action query_update arguments */
185 	QUEUE_INDIRECT_ACTION_QU_MODE,
186 
187 	/* Push arguments. */
188 	PUSH_QUEUE,
189 
190 	/* Pull arguments. */
191 	PULL_QUEUE,
192 
193 	/* Table arguments. */
194 	TABLE_CREATE,
195 	TABLE_DESTROY,
196 	TABLE_RESIZE,
197 	TABLE_RESIZE_COMPLETE,
198 	TABLE_CREATE_ID,
199 	TABLE_DESTROY_ID,
200 	TABLE_RESIZE_ID,
201 	TABLE_RESIZE_RULES_NUMBER,
202 	TABLE_INSERTION_TYPE,
203 	TABLE_INSERTION_TYPE_NAME,
204 	TABLE_HASH_FUNC,
205 	TABLE_HASH_FUNC_NAME,
206 	TABLE_GROUP,
207 	TABLE_PRIORITY,
208 	TABLE_INGRESS,
209 	TABLE_EGRESS,
210 	TABLE_TRANSFER,
211 	TABLE_TRANSFER_WIRE_ORIG,
212 	TABLE_TRANSFER_VPORT_ORIG,
213 	TABLE_RESIZABLE,
214 	TABLE_RULES_NUMBER,
215 	TABLE_PATTERN_TEMPLATE,
216 	TABLE_ACTIONS_TEMPLATE,
217 
218 	/* Group arguments */
219 	GROUP_ID,
220 	GROUP_INGRESS,
221 	GROUP_EGRESS,
222 	GROUP_TRANSFER,
223 	GROUP_SET_MISS_ACTIONS,
224 
225 	/* Hash calculation arguments. */
226 	HASH_CALC_TABLE,
227 	HASH_CALC_PATTERN_INDEX,
228 	HASH_CALC_PATTERN,
229 	HASH_CALC_ENCAP,
230 	HASH_CALC_DEST,
231 	ENCAP_HASH_FIELD_SRC_PORT,
232 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
233 
234 	/* Tunnel arguments. */
235 	TUNNEL_CREATE,
236 	TUNNEL_CREATE_TYPE,
237 	TUNNEL_LIST,
238 	TUNNEL_DESTROY,
239 	TUNNEL_DESTROY_ID,
240 
241 	/* Destroy arguments. */
242 	DESTROY_RULE,
243 	DESTROY_IS_USER_ID,
244 
245 	/* Query arguments. */
246 	QUERY_ACTION,
247 	QUERY_IS_USER_ID,
248 
249 	/* List arguments. */
250 	LIST_GROUP,
251 
252 	/* Destroy aged flow arguments. */
253 	AGED_DESTROY,
254 
255 	/* Validate/create arguments. */
256 	VC_GROUP,
257 	VC_PRIORITY,
258 	VC_INGRESS,
259 	VC_EGRESS,
260 	VC_TRANSFER,
261 	VC_TUNNEL_SET,
262 	VC_TUNNEL_MATCH,
263 	VC_USER_ID,
264 	VC_IS_USER_ID,
265 
266 	/* Dump arguments */
267 	DUMP_ALL,
268 	DUMP_ONE,
269 	DUMP_IS_USER_ID,
270 
271 	/* Configure arguments */
272 	CONFIG_QUEUES_NUMBER,
273 	CONFIG_QUEUES_SIZE,
274 	CONFIG_COUNTERS_NUMBER,
275 	CONFIG_AGING_OBJECTS_NUMBER,
276 	CONFIG_METERS_NUMBER,
277 	CONFIG_CONN_TRACK_NUMBER,
278 	CONFIG_QUOTAS_NUMBER,
279 	CONFIG_FLAGS,
280 	CONFIG_HOST_PORT,
281 
282 	/* Indirect action arguments */
283 	INDIRECT_ACTION_CREATE,
284 	INDIRECT_ACTION_LIST_CREATE,
285 	INDIRECT_ACTION_FLOW_CONF_CREATE,
286 	INDIRECT_ACTION_UPDATE,
287 	INDIRECT_ACTION_DESTROY,
288 	INDIRECT_ACTION_QUERY,
289 	INDIRECT_ACTION_QUERY_UPDATE,
290 
291 	/* Indirect action create arguments */
292 	INDIRECT_ACTION_CREATE_ID,
293 	INDIRECT_ACTION_INGRESS,
294 	INDIRECT_ACTION_EGRESS,
295 	INDIRECT_ACTION_TRANSFER,
296 	INDIRECT_ACTION_SPEC,
297 	INDIRECT_ACTION_LIST,
298 	INDIRECT_ACTION_FLOW_CONF,
299 
300 	/* Indirect action destroy arguments */
301 	INDIRECT_ACTION_DESTROY_ID,
302 
303 	/* Indirect action query-and-update arguments */
304 	INDIRECT_ACTION_QU_MODE,
305 	INDIRECT_ACTION_QU_MODE_NAME,
306 
307 	/* Validate/create pattern. */
308 	ITEM_PATTERN,
309 	ITEM_PARAM_IS,
310 	ITEM_PARAM_SPEC,
311 	ITEM_PARAM_LAST,
312 	ITEM_PARAM_MASK,
313 	ITEM_PARAM_PREFIX,
314 	ITEM_NEXT,
315 	ITEM_END,
316 	ITEM_VOID,
317 	ITEM_INVERT,
318 	ITEM_ANY,
319 	ITEM_ANY_NUM,
320 	ITEM_PORT_ID,
321 	ITEM_PORT_ID_ID,
322 	ITEM_MARK,
323 	ITEM_MARK_ID,
324 	ITEM_RAW,
325 	ITEM_RAW_RELATIVE,
326 	ITEM_RAW_SEARCH,
327 	ITEM_RAW_OFFSET,
328 	ITEM_RAW_LIMIT,
329 	ITEM_RAW_PATTERN,
330 	ITEM_RAW_PATTERN_HEX,
331 	ITEM_ETH,
332 	ITEM_ETH_DST,
333 	ITEM_ETH_SRC,
334 	ITEM_ETH_TYPE,
335 	ITEM_ETH_HAS_VLAN,
336 	ITEM_VLAN,
337 	ITEM_VLAN_TCI,
338 	ITEM_VLAN_PCP,
339 	ITEM_VLAN_DEI,
340 	ITEM_VLAN_VID,
341 	ITEM_VLAN_INNER_TYPE,
342 	ITEM_VLAN_HAS_MORE_VLAN,
343 	ITEM_IPV4,
344 	ITEM_IPV4_VER_IHL,
345 	ITEM_IPV4_TOS,
346 	ITEM_IPV4_LENGTH,
347 	ITEM_IPV4_ID,
348 	ITEM_IPV4_FRAGMENT_OFFSET,
349 	ITEM_IPV4_TTL,
350 	ITEM_IPV4_PROTO,
351 	ITEM_IPV4_SRC,
352 	ITEM_IPV4_DST,
353 	ITEM_IPV6,
354 	ITEM_IPV6_TC,
355 	ITEM_IPV6_FLOW,
356 	ITEM_IPV6_LEN,
357 	ITEM_IPV6_PROTO,
358 	ITEM_IPV6_HOP,
359 	ITEM_IPV6_SRC,
360 	ITEM_IPV6_DST,
361 	ITEM_IPV6_HAS_FRAG_EXT,
362 	ITEM_IPV6_ROUTING_EXT,
363 	ITEM_IPV6_ROUTING_EXT_TYPE,
364 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
365 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
366 	ITEM_ICMP,
367 	ITEM_ICMP_TYPE,
368 	ITEM_ICMP_CODE,
369 	ITEM_ICMP_IDENT,
370 	ITEM_ICMP_SEQ,
371 	ITEM_UDP,
372 	ITEM_UDP_SRC,
373 	ITEM_UDP_DST,
374 	ITEM_TCP,
375 	ITEM_TCP_SRC,
376 	ITEM_TCP_DST,
377 	ITEM_TCP_FLAGS,
378 	ITEM_SCTP,
379 	ITEM_SCTP_SRC,
380 	ITEM_SCTP_DST,
381 	ITEM_SCTP_TAG,
382 	ITEM_SCTP_CKSUM,
383 	ITEM_VXLAN,
384 	ITEM_VXLAN_VNI,
385 	ITEM_VXLAN_LAST_RSVD,
386 	ITEM_E_TAG,
387 	ITEM_E_TAG_GRP_ECID_B,
388 	ITEM_NVGRE,
389 	ITEM_NVGRE_TNI,
390 	ITEM_MPLS,
391 	ITEM_MPLS_LABEL,
392 	ITEM_MPLS_TC,
393 	ITEM_MPLS_S,
394 	ITEM_MPLS_TTL,
395 	ITEM_GRE,
396 	ITEM_GRE_PROTO,
397 	ITEM_GRE_C_RSVD0_VER,
398 	ITEM_GRE_C_BIT,
399 	ITEM_GRE_K_BIT,
400 	ITEM_GRE_S_BIT,
401 	ITEM_FUZZY,
402 	ITEM_FUZZY_THRESH,
403 	ITEM_GTP,
404 	ITEM_GTP_FLAGS,
405 	ITEM_GTP_MSG_TYPE,
406 	ITEM_GTP_TEID,
407 	ITEM_GTPC,
408 	ITEM_GTPU,
409 	ITEM_GENEVE,
410 	ITEM_GENEVE_VNI,
411 	ITEM_GENEVE_PROTO,
412 	ITEM_GENEVE_OPTLEN,
413 	ITEM_VXLAN_GPE,
414 	ITEM_VXLAN_GPE_VNI,
415 	ITEM_VXLAN_GPE_PROTO,
416 	ITEM_VXLAN_GPE_FLAGS,
417 	ITEM_VXLAN_GPE_RSVD0,
418 	ITEM_VXLAN_GPE_RSVD1,
419 	ITEM_ARP_ETH_IPV4,
420 	ITEM_ARP_ETH_IPV4_SHA,
421 	ITEM_ARP_ETH_IPV4_SPA,
422 	ITEM_ARP_ETH_IPV4_THA,
423 	ITEM_ARP_ETH_IPV4_TPA,
424 	ITEM_IPV6_EXT,
425 	ITEM_IPV6_EXT_NEXT_HDR,
426 	ITEM_IPV6_FRAG_EXT,
427 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
428 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
429 	ITEM_IPV6_FRAG_EXT_ID,
430 	ITEM_ICMP6,
431 	ITEM_ICMP6_TYPE,
432 	ITEM_ICMP6_CODE,
433 	ITEM_ICMP6_ECHO_REQUEST,
434 	ITEM_ICMP6_ECHO_REQUEST_ID,
435 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
436 	ITEM_ICMP6_ECHO_REPLY,
437 	ITEM_ICMP6_ECHO_REPLY_ID,
438 	ITEM_ICMP6_ECHO_REPLY_SEQ,
439 	ITEM_ICMP6_ND_NS,
440 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
441 	ITEM_ICMP6_ND_NA,
442 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
443 	ITEM_ICMP6_ND_OPT,
444 	ITEM_ICMP6_ND_OPT_TYPE,
445 	ITEM_ICMP6_ND_OPT_SLA_ETH,
446 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
447 	ITEM_ICMP6_ND_OPT_TLA_ETH,
448 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
449 	ITEM_META,
450 	ITEM_META_DATA,
451 	ITEM_RANDOM,
452 	ITEM_RANDOM_VALUE,
453 	ITEM_GRE_KEY,
454 	ITEM_GRE_KEY_VALUE,
455 	ITEM_GRE_OPTION,
456 	ITEM_GRE_OPTION_CHECKSUM,
457 	ITEM_GRE_OPTION_KEY,
458 	ITEM_GRE_OPTION_SEQUENCE,
459 	ITEM_GTP_PSC,
460 	ITEM_GTP_PSC_QFI,
461 	ITEM_GTP_PSC_PDU_T,
462 	ITEM_PPPOES,
463 	ITEM_PPPOED,
464 	ITEM_PPPOE_SEID,
465 	ITEM_PPPOE_PROTO_ID,
466 	ITEM_HIGIG2,
467 	ITEM_HIGIG2_CLASSIFICATION,
468 	ITEM_HIGIG2_VID,
469 	ITEM_TAG,
470 	ITEM_TAG_DATA,
471 	ITEM_TAG_INDEX,
472 	ITEM_L2TPV3OIP,
473 	ITEM_L2TPV3OIP_SESSION_ID,
474 	ITEM_ESP,
475 	ITEM_ESP_SPI,
476 	ITEM_AH,
477 	ITEM_AH_SPI,
478 	ITEM_PFCP,
479 	ITEM_PFCP_S_FIELD,
480 	ITEM_PFCP_SEID,
481 	ITEM_ECPRI,
482 	ITEM_ECPRI_COMMON,
483 	ITEM_ECPRI_COMMON_TYPE,
484 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
485 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
486 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
487 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
488 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
489 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
490 	ITEM_GENEVE_OPT,
491 	ITEM_GENEVE_OPT_CLASS,
492 	ITEM_GENEVE_OPT_TYPE,
493 	ITEM_GENEVE_OPT_LENGTH,
494 	ITEM_GENEVE_OPT_DATA,
495 	ITEM_INTEGRITY,
496 	ITEM_INTEGRITY_LEVEL,
497 	ITEM_INTEGRITY_VALUE,
498 	ITEM_CONNTRACK,
499 	ITEM_POL_PORT,
500 	ITEM_POL_METER,
501 	ITEM_POL_POLICY,
502 	ITEM_PORT_REPRESENTOR,
503 	ITEM_PORT_REPRESENTOR_PORT_ID,
504 	ITEM_REPRESENTED_PORT,
505 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
506 	ITEM_FLEX,
507 	ITEM_FLEX_ITEM_HANDLE,
508 	ITEM_FLEX_PATTERN_HANDLE,
509 	ITEM_L2TPV2,
510 	ITEM_L2TPV2_TYPE,
511 	ITEM_L2TPV2_TYPE_DATA,
512 	ITEM_L2TPV2_TYPE_DATA_L,
513 	ITEM_L2TPV2_TYPE_DATA_S,
514 	ITEM_L2TPV2_TYPE_DATA_O,
515 	ITEM_L2TPV2_TYPE_DATA_L_S,
516 	ITEM_L2TPV2_TYPE_CTRL,
517 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
518 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
519 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
520 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
521 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
522 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
523 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
524 	ITEM_L2TPV2_MSG_DATA_S_NS,
525 	ITEM_L2TPV2_MSG_DATA_S_NR,
526 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
527 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
528 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
529 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
530 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
531 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
532 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
533 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
534 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
535 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
536 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
537 	ITEM_L2TPV2_MSG_CTRL_NS,
538 	ITEM_L2TPV2_MSG_CTRL_NR,
539 	ITEM_PPP,
540 	ITEM_PPP_ADDR,
541 	ITEM_PPP_CTRL,
542 	ITEM_PPP_PROTO_ID,
543 	ITEM_METER,
544 	ITEM_METER_COLOR,
545 	ITEM_METER_COLOR_NAME,
546 	ITEM_QUOTA,
547 	ITEM_QUOTA_STATE,
548 	ITEM_QUOTA_STATE_NAME,
549 	ITEM_AGGR_AFFINITY,
550 	ITEM_AGGR_AFFINITY_VALUE,
551 	ITEM_TX_QUEUE,
552 	ITEM_TX_QUEUE_VALUE,
553 	ITEM_IB_BTH,
554 	ITEM_IB_BTH_OPCODE,
555 	ITEM_IB_BTH_PKEY,
556 	ITEM_IB_BTH_DST_QPN,
557 	ITEM_IB_BTH_PSN,
558 	ITEM_IPV6_PUSH_REMOVE_EXT,
559 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
560 	ITEM_PTYPE,
561 	ITEM_PTYPE_VALUE,
562 	ITEM_NSH,
563 	ITEM_COMPARE,
564 	ITEM_COMPARE_OP,
565 	ITEM_COMPARE_OP_VALUE,
566 	ITEM_COMPARE_FIELD_A_TYPE,
567 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
568 	ITEM_COMPARE_FIELD_A_LEVEL,
569 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
570 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
571 	ITEM_COMPARE_FIELD_A_TYPE_ID,
572 	ITEM_COMPARE_FIELD_A_CLASS_ID,
573 	ITEM_COMPARE_FIELD_A_OFFSET,
574 	ITEM_COMPARE_FIELD_B_TYPE,
575 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
576 	ITEM_COMPARE_FIELD_B_LEVEL,
577 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
578 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
579 	ITEM_COMPARE_FIELD_B_TYPE_ID,
580 	ITEM_COMPARE_FIELD_B_CLASS_ID,
581 	ITEM_COMPARE_FIELD_B_OFFSET,
582 	ITEM_COMPARE_FIELD_B_VALUE,
583 	ITEM_COMPARE_FIELD_B_POINTER,
584 	ITEM_COMPARE_FIELD_WIDTH,
585 
586 	/* Validate/create actions. */
587 	ACTIONS,
588 	ACTION_NEXT,
589 	ACTION_END,
590 	ACTION_VOID,
591 	ACTION_PASSTHRU,
592 	ACTION_SKIP_CMAN,
593 	ACTION_JUMP,
594 	ACTION_JUMP_GROUP,
595 	ACTION_MARK,
596 	ACTION_MARK_ID,
597 	ACTION_FLAG,
598 	ACTION_QUEUE,
599 	ACTION_QUEUE_INDEX,
600 	ACTION_DROP,
601 	ACTION_COUNT,
602 	ACTION_COUNT_ID,
603 	ACTION_RSS,
604 	ACTION_RSS_FUNC,
605 	ACTION_RSS_LEVEL,
606 	ACTION_RSS_FUNC_DEFAULT,
607 	ACTION_RSS_FUNC_TOEPLITZ,
608 	ACTION_RSS_FUNC_SIMPLE_XOR,
609 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
610 	ACTION_RSS_TYPES,
611 	ACTION_RSS_TYPE,
612 	ACTION_RSS_KEY,
613 	ACTION_RSS_KEY_LEN,
614 	ACTION_RSS_QUEUES,
615 	ACTION_RSS_QUEUE,
616 	ACTION_PF,
617 	ACTION_VF,
618 	ACTION_VF_ORIGINAL,
619 	ACTION_VF_ID,
620 	ACTION_PORT_ID,
621 	ACTION_PORT_ID_ORIGINAL,
622 	ACTION_PORT_ID_ID,
623 	ACTION_METER,
624 	ACTION_METER_COLOR,
625 	ACTION_METER_COLOR_TYPE,
626 	ACTION_METER_COLOR_GREEN,
627 	ACTION_METER_COLOR_YELLOW,
628 	ACTION_METER_COLOR_RED,
629 	ACTION_METER_ID,
630 	ACTION_METER_MARK,
631 	ACTION_METER_PROFILE,
632 	ACTION_METER_PROFILE_ID2PTR,
633 	ACTION_METER_POLICY,
634 	ACTION_METER_POLICY_ID2PTR,
635 	ACTION_METER_COLOR_MODE,
636 	ACTION_METER_STATE,
637 	ACTION_OF_DEC_NW_TTL,
638 	ACTION_OF_POP_VLAN,
639 	ACTION_OF_PUSH_VLAN,
640 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
641 	ACTION_OF_SET_VLAN_VID,
642 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
643 	ACTION_OF_SET_VLAN_PCP,
644 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
645 	ACTION_OF_POP_MPLS,
646 	ACTION_OF_POP_MPLS_ETHERTYPE,
647 	ACTION_OF_PUSH_MPLS,
648 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
649 	ACTION_VXLAN_ENCAP,
650 	ACTION_VXLAN_DECAP,
651 	ACTION_NVGRE_ENCAP,
652 	ACTION_NVGRE_DECAP,
653 	ACTION_L2_ENCAP,
654 	ACTION_L2_DECAP,
655 	ACTION_MPLSOGRE_ENCAP,
656 	ACTION_MPLSOGRE_DECAP,
657 	ACTION_MPLSOUDP_ENCAP,
658 	ACTION_MPLSOUDP_DECAP,
659 	ACTION_SET_IPV4_SRC,
660 	ACTION_SET_IPV4_SRC_IPV4_SRC,
661 	ACTION_SET_IPV4_DST,
662 	ACTION_SET_IPV4_DST_IPV4_DST,
663 	ACTION_SET_IPV6_SRC,
664 	ACTION_SET_IPV6_SRC_IPV6_SRC,
665 	ACTION_SET_IPV6_DST,
666 	ACTION_SET_IPV6_DST_IPV6_DST,
667 	ACTION_SET_TP_SRC,
668 	ACTION_SET_TP_SRC_TP_SRC,
669 	ACTION_SET_TP_DST,
670 	ACTION_SET_TP_DST_TP_DST,
671 	ACTION_MAC_SWAP,
672 	ACTION_DEC_TTL,
673 	ACTION_SET_TTL,
674 	ACTION_SET_TTL_TTL,
675 	ACTION_SET_MAC_SRC,
676 	ACTION_SET_MAC_SRC_MAC_SRC,
677 	ACTION_SET_MAC_DST,
678 	ACTION_SET_MAC_DST_MAC_DST,
679 	ACTION_INC_TCP_SEQ,
680 	ACTION_INC_TCP_SEQ_VALUE,
681 	ACTION_DEC_TCP_SEQ,
682 	ACTION_DEC_TCP_SEQ_VALUE,
683 	ACTION_INC_TCP_ACK,
684 	ACTION_INC_TCP_ACK_VALUE,
685 	ACTION_DEC_TCP_ACK,
686 	ACTION_DEC_TCP_ACK_VALUE,
687 	ACTION_RAW_ENCAP,
688 	ACTION_RAW_DECAP,
689 	ACTION_RAW_ENCAP_SIZE,
690 	ACTION_RAW_ENCAP_INDEX,
691 	ACTION_RAW_ENCAP_INDEX_VALUE,
692 	ACTION_RAW_DECAP_INDEX,
693 	ACTION_RAW_DECAP_INDEX_VALUE,
694 	ACTION_SET_TAG,
695 	ACTION_SET_TAG_DATA,
696 	ACTION_SET_TAG_INDEX,
697 	ACTION_SET_TAG_MASK,
698 	ACTION_SET_META,
699 	ACTION_SET_META_DATA,
700 	ACTION_SET_META_MASK,
701 	ACTION_SET_IPV4_DSCP,
702 	ACTION_SET_IPV4_DSCP_VALUE,
703 	ACTION_SET_IPV6_DSCP,
704 	ACTION_SET_IPV6_DSCP_VALUE,
705 	ACTION_AGE,
706 	ACTION_AGE_TIMEOUT,
707 	ACTION_AGE_UPDATE,
708 	ACTION_AGE_UPDATE_TIMEOUT,
709 	ACTION_AGE_UPDATE_TOUCH,
710 	ACTION_SAMPLE,
711 	ACTION_SAMPLE_RATIO,
712 	ACTION_SAMPLE_INDEX,
713 	ACTION_SAMPLE_INDEX_VALUE,
714 	ACTION_INDIRECT,
715 	ACTION_INDIRECT_LIST,
716 	ACTION_INDIRECT_LIST_HANDLE,
717 	ACTION_INDIRECT_LIST_CONF,
718 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
719 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
720 	ACTION_SHARED_INDIRECT,
721 	INDIRECT_ACTION_PORT,
722 	INDIRECT_ACTION_ID2PTR,
723 	ACTION_MODIFY_FIELD,
724 	ACTION_MODIFY_FIELD_OP,
725 	ACTION_MODIFY_FIELD_OP_VALUE,
726 	ACTION_MODIFY_FIELD_DST_TYPE,
727 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
728 	ACTION_MODIFY_FIELD_DST_LEVEL,
729 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
730 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
731 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
732 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
733 	ACTION_MODIFY_FIELD_DST_OFFSET,
734 	ACTION_MODIFY_FIELD_SRC_TYPE,
735 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
736 	ACTION_MODIFY_FIELD_SRC_LEVEL,
737 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
738 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
739 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
740 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
741 	ACTION_MODIFY_FIELD_SRC_OFFSET,
742 	ACTION_MODIFY_FIELD_SRC_VALUE,
743 	ACTION_MODIFY_FIELD_SRC_POINTER,
744 	ACTION_MODIFY_FIELD_WIDTH,
745 	ACTION_CONNTRACK,
746 	ACTION_CONNTRACK_UPDATE,
747 	ACTION_CONNTRACK_UPDATE_DIR,
748 	ACTION_CONNTRACK_UPDATE_CTX,
749 	ACTION_POL_G,
750 	ACTION_POL_Y,
751 	ACTION_POL_R,
752 	ACTION_PORT_REPRESENTOR,
753 	ACTION_PORT_REPRESENTOR_PORT_ID,
754 	ACTION_REPRESENTED_PORT,
755 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
756 	ACTION_SEND_TO_KERNEL,
757 	ACTION_QUOTA_CREATE,
758 	ACTION_QUOTA_CREATE_LIMIT,
759 	ACTION_QUOTA_CREATE_MODE,
760 	ACTION_QUOTA_CREATE_MODE_NAME,
761 	ACTION_QUOTA_QU,
762 	ACTION_QUOTA_QU_LIMIT,
763 	ACTION_QUOTA_QU_UPDATE_OP,
764 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
765 	ACTION_IPV6_EXT_REMOVE,
766 	ACTION_IPV6_EXT_REMOVE_INDEX,
767 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
768 	ACTION_IPV6_EXT_PUSH,
769 	ACTION_IPV6_EXT_PUSH_INDEX,
770 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
771 	ACTION_NAT64,
772 	ACTION_NAT64_MODE,
773 };
774 
775 /** Maximum size for pattern in struct rte_flow_item_raw. */
776 #define ITEM_RAW_PATTERN_SIZE 512
777 
778 /** Maximum size for GENEVE option data pattern in bytes. */
779 #define ITEM_GENEVE_OPT_DATA_SIZE 124
780 
781 /** Storage size for struct rte_flow_item_raw including pattern. */
782 #define ITEM_RAW_SIZE \
783 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
784 
785 static const char *const compare_ops[] = {
786 	"eq", "ne", "lt", "le", "gt", "ge", NULL
787 };
788 
789 /** Maximum size for external pattern in struct rte_flow_field_data. */
790 #define FLOW_FIELD_PATTERN_SIZE 32
791 
792 /** Storage size for struct rte_flow_action_modify_field including pattern. */
793 #define ACTION_MODIFY_SIZE \
794 	(sizeof(struct rte_flow_action_modify_field) + \
795 	FLOW_FIELD_PATTERN_SIZE)
796 
797 /** Maximum number of queue indices in struct rte_flow_action_rss. */
798 #define ACTION_RSS_QUEUE_NUM 128
799 
800 /** Storage for struct rte_flow_action_rss including external data. */
801 struct action_rss_data {
802 	struct rte_flow_action_rss conf;
803 	uint8_t key[RSS_HASH_KEY_LENGTH];
804 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
805 };
806 
807 /** Maximum data size in struct rte_flow_action_raw_encap. */
808 #define ACTION_RAW_ENCAP_MAX_DATA 512
809 #define RAW_ENCAP_CONFS_MAX_NUM 8
810 
811 /** Storage for struct rte_flow_action_raw_encap. */
812 struct raw_encap_conf {
813 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
814 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
815 	size_t size;
816 };
817 
818 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
819 
820 /** Storage for struct rte_flow_action_raw_encap including external data. */
821 struct action_raw_encap_data {
822 	struct rte_flow_action_raw_encap conf;
823 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
824 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
825 	uint16_t idx;
826 };
827 
828 /** Storage for struct rte_flow_action_raw_decap. */
829 struct raw_decap_conf {
830 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
831 	size_t size;
832 };
833 
834 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
835 
836 /** Storage for struct rte_flow_action_raw_decap including external data. */
837 struct action_raw_decap_data {
838 	struct rte_flow_action_raw_decap conf;
839 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
840 	uint16_t idx;
841 };
842 
843 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
844 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
845 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
846 
847 /** Storage for struct rte_flow_action_ipv6_ext_push. */
848 struct ipv6_ext_push_conf {
849 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
850 	size_t size;
851 	uint8_t type;
852 };
853 
854 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
855 
856 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
857 struct action_ipv6_ext_push_data {
858 	struct rte_flow_action_ipv6_ext_push conf;
859 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
860 	uint8_t type;
861 	uint16_t idx;
862 };
863 
864 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
865 struct ipv6_ext_remove_conf {
866 	struct rte_flow_action_ipv6_ext_remove conf;
867 	uint8_t type;
868 };
869 
870 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
871 
872 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
873 struct action_ipv6_ext_remove_data {
874 	struct rte_flow_action_ipv6_ext_remove conf;
875 	uint8_t type;
876 	uint16_t idx;
877 };
878 
879 struct vxlan_encap_conf vxlan_encap_conf = {
880 	.select_ipv4 = 1,
881 	.select_vlan = 0,
882 	.select_tos_ttl = 0,
883 	.vni = "\x00\x00\x00",
884 	.udp_src = 0,
885 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
886 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
887 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
888 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
889 		"\x00\x00\x00\x00\x00\x00\x00\x01",
890 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
891 		"\x00\x00\x00\x00\x00\x00\x11\x11",
892 	.vlan_tci = 0,
893 	.ip_tos = 0,
894 	.ip_ttl = 255,
895 	.eth_src = "\x00\x00\x00\x00\x00\x00",
896 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
897 };
898 
899 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
900 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
901 
902 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
903 struct action_vxlan_encap_data {
904 	struct rte_flow_action_vxlan_encap conf;
905 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
906 	struct rte_flow_item_eth item_eth;
907 	struct rte_flow_item_vlan item_vlan;
908 	union {
909 		struct rte_flow_item_ipv4 item_ipv4;
910 		struct rte_flow_item_ipv6 item_ipv6;
911 	};
912 	struct rte_flow_item_udp item_udp;
913 	struct rte_flow_item_vxlan item_vxlan;
914 };
915 
916 struct nvgre_encap_conf nvgre_encap_conf = {
917 	.select_ipv4 = 1,
918 	.select_vlan = 0,
919 	.tni = "\x00\x00\x00",
920 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
921 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
922 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
923 		"\x00\x00\x00\x00\x00\x00\x00\x01",
924 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
925 		"\x00\x00\x00\x00\x00\x00\x11\x11",
926 	.vlan_tci = 0,
927 	.eth_src = "\x00\x00\x00\x00\x00\x00",
928 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
929 };
930 
931 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
932 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
933 
934 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
935 struct action_nvgre_encap_data {
936 	struct rte_flow_action_nvgre_encap conf;
937 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
938 	struct rte_flow_item_eth item_eth;
939 	struct rte_flow_item_vlan item_vlan;
940 	union {
941 		struct rte_flow_item_ipv4 item_ipv4;
942 		struct rte_flow_item_ipv6 item_ipv6;
943 	};
944 	struct rte_flow_item_nvgre item_nvgre;
945 };
946 
947 struct l2_encap_conf l2_encap_conf;
948 
949 struct l2_decap_conf l2_decap_conf;
950 
951 struct mplsogre_encap_conf mplsogre_encap_conf;
952 
953 struct mplsogre_decap_conf mplsogre_decap_conf;
954 
955 struct mplsoudp_encap_conf mplsoudp_encap_conf;
956 
957 struct mplsoudp_decap_conf mplsoudp_decap_conf;
958 
959 struct rte_flow_action_conntrack conntrack_context;
960 
961 #define ACTION_SAMPLE_ACTIONS_NUM 10
962 #define RAW_SAMPLE_CONFS_MAX_NUM 8
963 /** Storage for struct rte_flow_action_sample including external data. */
964 struct action_sample_data {
965 	struct rte_flow_action_sample conf;
966 	uint32_t idx;
967 };
968 /** Storage for struct rte_flow_action_sample. */
969 struct raw_sample_conf {
970 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
971 };
972 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
973 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
974 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
975 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
976 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
977 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
978 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
979 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
980 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
981 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
982 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
983 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
984 
985 static const char *const modify_field_ops[] = {
986 	"set", "add", "sub", NULL
987 };
988 
989 static const char *const flow_field_ids[] = {
990 	"start", "mac_dst", "mac_src",
991 	"vlan_type", "vlan_id", "mac_type",
992 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
993 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
994 	"tcp_port_src", "tcp_port_dst",
995 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
996 	"udp_port_src", "udp_port_dst",
997 	"vxlan_vni", "geneve_vni", "gtp_teid",
998 	"tag", "mark", "meta", "pointer", "value",
999 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
1000 	"ipv6_proto",
1001 	"flex_item",
1002 	"hash_result",
1003 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1004 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1005 	"random",
1006 	"ipv4_proto",
1007 	"esp_spi", "esp_seq_num", "esp_proto",
1008 	"ipv6_flow_label", "ipv6_traffic_class",
1009 	NULL
1010 };
1011 
1012 static const char *const meter_colors[] = {
1013 	"green", "yellow", "red", "all", NULL
1014 };
1015 
1016 static const char *const table_insertion_types[] = {
1017 	"pattern", "index", NULL
1018 };
1019 
1020 static const char *const table_hash_funcs[] = {
1021 	"default", "linear", "crc32", "crc16", NULL
1022 };
1023 
1024 #define RAW_IPSEC_CONFS_MAX_NUM 8
1025 
1026 /** Maximum number of subsequent tokens and arguments on the stack. */
1027 #define CTX_STACK_SIZE 16
1028 
1029 /** Parser context. */
1030 struct context {
1031 	/** Stack of subsequent token lists to process. */
1032 	const enum index *next[CTX_STACK_SIZE];
1033 	/** Arguments for stacked tokens. */
1034 	const void *args[CTX_STACK_SIZE];
1035 	enum index curr; /**< Current token index. */
1036 	enum index prev; /**< Index of the last token seen. */
1037 	int next_num; /**< Number of entries in next[]. */
1038 	int args_num; /**< Number of entries in args[]. */
1039 	uint32_t eol:1; /**< EOL has been detected. */
1040 	uint32_t last:1; /**< No more arguments. */
1041 	portid_t port; /**< Current port ID (for completions). */
1042 	uint32_t objdata; /**< Object-specific data. */
1043 	void *object; /**< Address of current object for relative offsets. */
1044 	void *objmask; /**< Object a full mask must be written to. */
1045 };
1046 
1047 /** Token argument. */
1048 struct arg {
1049 	uint32_t hton:1; /**< Use network byte ordering. */
1050 	uint32_t sign:1; /**< Value is signed. */
1051 	uint32_t bounded:1; /**< Value is bounded. */
1052 	uintmax_t min; /**< Minimum value if bounded. */
1053 	uintmax_t max; /**< Maximum value if bounded. */
1054 	uint32_t offset; /**< Relative offset from ctx->object. */
1055 	uint32_t size; /**< Field size. */
1056 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1057 };
1058 
1059 /** Parser token definition. */
1060 struct token {
1061 	/** Type displayed during completion (defaults to "TOKEN"). */
1062 	const char *type;
1063 	/** Help displayed during completion (defaults to token name). */
1064 	const char *help;
1065 	/** Private data used by parser functions. */
1066 	const void *priv;
1067 	/**
1068 	 * Lists of subsequent tokens to push on the stack. Each call to the
1069 	 * parser consumes the last entry of that stack.
1070 	 */
1071 	const enum index *const *next;
1072 	/** Arguments stack for subsequent tokens that need them. */
1073 	const struct arg *const *args;
1074 	/**
1075 	 * Token-processing callback, returns -1 in case of error, the
1076 	 * length of the matched string otherwise. If NULL, attempts to
1077 	 * match the token name.
1078 	 *
1079 	 * If buf is not NULL, the result should be stored in it according
1080 	 * to context. An error is returned if not large enough.
1081 	 */
1082 	int (*call)(struct context *ctx, const struct token *token,
1083 		    const char *str, unsigned int len,
1084 		    void *buf, unsigned int size);
1085 	/**
1086 	 * Callback that provides possible values for this token, used for
1087 	 * completion. Returns -1 in case of error, the number of possible
1088 	 * values otherwise. If NULL, the token name is used.
1089 	 *
1090 	 * If buf is not NULL, entry index ent is written to buf and the
1091 	 * full length of the entry is returned (same behavior as
1092 	 * snprintf()).
1093 	 */
1094 	int (*comp)(struct context *ctx, const struct token *token,
1095 		    unsigned int ent, char *buf, unsigned int size);
1096 	/** Mandatory token name, no default value. */
1097 	const char *name;
1098 };
1099 
1100 /** Static initializer for the next field. */
1101 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1102 
1103 /** Static initializer for a NEXT() entry. */
1104 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1105 
1106 /** Static initializer for the args field. */
1107 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1108 
1109 /** Static initializer for ARGS() to target a field. */
1110 #define ARGS_ENTRY(s, f) \
1111 	(&(const struct arg){ \
1112 		.offset = offsetof(s, f), \
1113 		.size = sizeof(((s *)0)->f), \
1114 	})
1115 
1116 /** Static initializer for ARGS() to target a bit-field. */
1117 #define ARGS_ENTRY_BF(s, f, b) \
1118 	(&(const struct arg){ \
1119 		.size = sizeof(s), \
1120 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1121 	})
1122 
1123 /** Static initializer for ARGS() to target a field with limits. */
1124 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1125 	(&(const struct arg){ \
1126 		.bounded = 1, \
1127 		.min = (i), \
1128 		.max = (a), \
1129 		.offset = offsetof(s, f), \
1130 		.size = sizeof(((s *)0)->f), \
1131 	})
1132 
1133 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1134 #define ARGS_ENTRY_MASK(s, f, m) \
1135 	(&(const struct arg){ \
1136 		.offset = offsetof(s, f), \
1137 		.size = sizeof(((s *)0)->f), \
1138 		.mask = (const void *)(m), \
1139 	})
1140 
1141 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1142 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1143 	(&(const struct arg){ \
1144 		.hton = 1, \
1145 		.offset = offsetof(s, f), \
1146 		.size = sizeof(((s *)0)->f), \
1147 		.mask = (const void *)(m), \
1148 	})
1149 
1150 /** Static initializer for ARGS() to target a pointer. */
1151 #define ARGS_ENTRY_PTR(s, f) \
1152 	(&(const struct arg){ \
1153 		.size = sizeof(*((s *)0)->f), \
1154 	})
1155 
1156 /** Static initializer for ARGS() with arbitrary offset and size. */
1157 #define ARGS_ENTRY_ARB(o, s) \
1158 	(&(const struct arg){ \
1159 		.offset = (o), \
1160 		.size = (s), \
1161 	})
1162 
1163 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1164 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1165 	(&(const struct arg){ \
1166 		.bounded = 1, \
1167 		.min = (i), \
1168 		.max = (a), \
1169 		.offset = (o), \
1170 		.size = (s), \
1171 	})
1172 
1173 /** Same as ARGS_ENTRY() using network byte ordering. */
1174 #define ARGS_ENTRY_HTON(s, f) \
1175 	(&(const struct arg){ \
1176 		.hton = 1, \
1177 		.offset = offsetof(s, f), \
1178 		.size = sizeof(((s *)0)->f), \
1179 	})
1180 
1181 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1182 #define ARG_ENTRY_HTON(s) \
1183 	(&(const struct arg){ \
1184 		.hton = 1, \
1185 		.offset = 0, \
1186 		.size = sizeof(s), \
1187 	})
1188 
1189 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1190 struct buffer {
1191 	enum index command; /**< Flow command. */
1192 	portid_t port; /**< Affected port ID. */
1193 	queueid_t queue; /** Async queue ID. */
1194 	bool postpone; /** Postpone async operation */
1195 	union {
1196 		struct {
1197 			struct rte_flow_port_attr port_attr;
1198 			uint32_t nb_queue;
1199 			struct rte_flow_queue_attr queue_attr;
1200 		} configure; /**< Configuration arguments. */
1201 		struct {
1202 			uint32_t *template_id;
1203 			uint32_t template_id_n;
1204 		} templ_destroy; /**< Template destroy arguments. */
1205 		struct {
1206 			uint32_t id;
1207 			struct rte_flow_template_table_attr attr;
1208 			uint32_t *pat_templ_id;
1209 			uint32_t pat_templ_id_n;
1210 			uint32_t *act_templ_id;
1211 			uint32_t act_templ_id_n;
1212 		} table; /**< Table arguments. */
1213 		struct {
1214 			uint32_t *table_id;
1215 			uint32_t table_id_n;
1216 		} table_destroy; /**< Template destroy arguments. */
1217 		struct {
1218 			uint32_t *action_id;
1219 			uint32_t action_id_n;
1220 		} ia_destroy; /**< Indirect action destroy arguments. */
1221 		struct {
1222 			uint32_t action_id;
1223 			enum rte_flow_query_update_mode qu_mode;
1224 		} ia; /* Indirect action query arguments */
1225 		struct {
1226 			uint32_t table_id;
1227 			uint32_t pat_templ_id;
1228 			uint32_t rule_id;
1229 			uint32_t act_templ_id;
1230 			struct rte_flow_attr attr;
1231 			struct tunnel_ops tunnel_ops;
1232 			uintptr_t user_id;
1233 			struct rte_flow_item *pattern;
1234 			struct rte_flow_action *actions;
1235 			struct rte_flow_action *masks;
1236 			uint32_t pattern_n;
1237 			uint32_t actions_n;
1238 			uint8_t *data;
1239 			enum rte_flow_encap_hash_field field;
1240 			uint8_t encap_hash;
1241 		} vc; /**< Validate/create arguments. */
1242 		struct {
1243 			uint64_t *rule;
1244 			uint64_t rule_n;
1245 			bool is_user_id;
1246 		} destroy; /**< Destroy arguments. */
1247 		struct {
1248 			char file[128];
1249 			bool mode;
1250 			uint64_t rule;
1251 			bool is_user_id;
1252 		} dump; /**< Dump arguments. */
1253 		struct {
1254 			uint64_t rule;
1255 			struct rte_flow_action action;
1256 			bool is_user_id;
1257 		} query; /**< Query arguments. */
1258 		struct {
1259 			uint32_t *group;
1260 			uint32_t group_n;
1261 		} list; /**< List arguments. */
1262 		struct {
1263 			int set;
1264 		} isolate; /**< Isolated mode arguments. */
1265 		struct {
1266 			int destroy;
1267 		} aged; /**< Aged arguments. */
1268 		struct {
1269 			uint32_t policy_id;
1270 		} policy;/**< Policy arguments. */
1271 		struct {
1272 			uint16_t token;
1273 			uintptr_t uintptr;
1274 			char filename[128];
1275 		} flex; /**< Flex arguments*/
1276 	} args; /**< Command arguments. */
1277 };
1278 
1279 /** Private data for pattern items. */
1280 struct parse_item_priv {
1281 	enum rte_flow_item_type type; /**< Item type. */
1282 	uint32_t size; /**< Size of item specification structure. */
1283 };
1284 
1285 #define PRIV_ITEM(t, s) \
1286 	(&(const struct parse_item_priv){ \
1287 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1288 		.size = s, \
1289 	})
1290 
1291 /** Private data for actions. */
1292 struct parse_action_priv {
1293 	enum rte_flow_action_type type; /**< Action type. */
1294 	uint32_t size; /**< Size of action configuration structure. */
1295 };
1296 
1297 #define PRIV_ACTION(t, s) \
1298 	(&(const struct parse_action_priv){ \
1299 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1300 		.size = s, \
1301 	})
1302 
1303 static const enum index next_flex_item[] = {
1304 	FLEX_ITEM_INIT,
1305 	FLEX_ITEM_CREATE,
1306 	FLEX_ITEM_DESTROY,
1307 	ZERO,
1308 };
1309 
1310 static const enum index next_config_attr[] = {
1311 	CONFIG_QUEUES_NUMBER,
1312 	CONFIG_QUEUES_SIZE,
1313 	CONFIG_COUNTERS_NUMBER,
1314 	CONFIG_AGING_OBJECTS_NUMBER,
1315 	CONFIG_METERS_NUMBER,
1316 	CONFIG_CONN_TRACK_NUMBER,
1317 	CONFIG_QUOTAS_NUMBER,
1318 	CONFIG_FLAGS,
1319 	CONFIG_HOST_PORT,
1320 	END,
1321 	ZERO,
1322 };
1323 
1324 static const enum index next_pt_subcmd[] = {
1325 	PATTERN_TEMPLATE_CREATE,
1326 	PATTERN_TEMPLATE_DESTROY,
1327 	ZERO,
1328 };
1329 
1330 static const enum index next_pt_attr[] = {
1331 	PATTERN_TEMPLATE_CREATE_ID,
1332 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1333 	PATTERN_TEMPLATE_INGRESS,
1334 	PATTERN_TEMPLATE_EGRESS,
1335 	PATTERN_TEMPLATE_TRANSFER,
1336 	PATTERN_TEMPLATE_SPEC,
1337 	ZERO,
1338 };
1339 
1340 static const enum index next_pt_destroy_attr[] = {
1341 	PATTERN_TEMPLATE_DESTROY_ID,
1342 	END,
1343 	ZERO,
1344 };
1345 
1346 static const enum index next_at_subcmd[] = {
1347 	ACTIONS_TEMPLATE_CREATE,
1348 	ACTIONS_TEMPLATE_DESTROY,
1349 	ZERO,
1350 };
1351 
1352 static const enum index next_at_attr[] = {
1353 	ACTIONS_TEMPLATE_CREATE_ID,
1354 	ACTIONS_TEMPLATE_INGRESS,
1355 	ACTIONS_TEMPLATE_EGRESS,
1356 	ACTIONS_TEMPLATE_TRANSFER,
1357 	ACTIONS_TEMPLATE_SPEC,
1358 	ZERO,
1359 };
1360 
1361 static const enum index next_at_destroy_attr[] = {
1362 	ACTIONS_TEMPLATE_DESTROY_ID,
1363 	END,
1364 	ZERO,
1365 };
1366 
1367 static const enum index next_group_attr[] = {
1368 	GROUP_INGRESS,
1369 	GROUP_EGRESS,
1370 	GROUP_TRANSFER,
1371 	GROUP_SET_MISS_ACTIONS,
1372 	ZERO,
1373 };
1374 
1375 static const enum index next_table_subcmd[] = {
1376 	TABLE_CREATE,
1377 	TABLE_DESTROY,
1378 	TABLE_RESIZE,
1379 	TABLE_RESIZE_COMPLETE,
1380 	ZERO,
1381 };
1382 
1383 static const enum index next_table_attr[] = {
1384 	TABLE_CREATE_ID,
1385 	TABLE_GROUP,
1386 	TABLE_INSERTION_TYPE,
1387 	TABLE_HASH_FUNC,
1388 	TABLE_PRIORITY,
1389 	TABLE_INGRESS,
1390 	TABLE_EGRESS,
1391 	TABLE_TRANSFER,
1392 	TABLE_TRANSFER_WIRE_ORIG,
1393 	TABLE_TRANSFER_VPORT_ORIG,
1394 	TABLE_RESIZABLE,
1395 	TABLE_RULES_NUMBER,
1396 	TABLE_PATTERN_TEMPLATE,
1397 	TABLE_ACTIONS_TEMPLATE,
1398 	END,
1399 	ZERO,
1400 };
1401 
1402 static const enum index next_table_destroy_attr[] = {
1403 	TABLE_DESTROY_ID,
1404 	END,
1405 	ZERO,
1406 };
1407 
1408 static const enum index next_queue_subcmd[] = {
1409 	QUEUE_CREATE,
1410 	QUEUE_DESTROY,
1411 	QUEUE_FLOW_UPDATE_RESIZED,
1412 	QUEUE_UPDATE,
1413 	QUEUE_AGED,
1414 	QUEUE_INDIRECT_ACTION,
1415 	ZERO,
1416 };
1417 
1418 static const enum index next_queue_destroy_attr[] = {
1419 	QUEUE_DESTROY_ID,
1420 	END,
1421 	ZERO,
1422 };
1423 
1424 static const enum index next_qia_subcmd[] = {
1425 	QUEUE_INDIRECT_ACTION_CREATE,
1426 	QUEUE_INDIRECT_ACTION_UPDATE,
1427 	QUEUE_INDIRECT_ACTION_DESTROY,
1428 	QUEUE_INDIRECT_ACTION_QUERY,
1429 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1430 	ZERO,
1431 };
1432 
1433 static const enum index next_qia_create_attr[] = {
1434 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1435 	QUEUE_INDIRECT_ACTION_INGRESS,
1436 	QUEUE_INDIRECT_ACTION_EGRESS,
1437 	QUEUE_INDIRECT_ACTION_TRANSFER,
1438 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1439 	QUEUE_INDIRECT_ACTION_SPEC,
1440 	QUEUE_INDIRECT_ACTION_LIST,
1441 	ZERO,
1442 };
1443 
1444 static const enum index next_qia_update_attr[] = {
1445 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1446 	QUEUE_INDIRECT_ACTION_SPEC,
1447 	ZERO,
1448 };
1449 
1450 static const enum index next_qia_destroy_attr[] = {
1451 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1452 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1453 	END,
1454 	ZERO,
1455 };
1456 
1457 static const enum index next_qia_query_attr[] = {
1458 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1459 	END,
1460 	ZERO,
1461 };
1462 
1463 static const enum index next_ia_create_attr[] = {
1464 	INDIRECT_ACTION_CREATE_ID,
1465 	INDIRECT_ACTION_INGRESS,
1466 	INDIRECT_ACTION_EGRESS,
1467 	INDIRECT_ACTION_TRANSFER,
1468 	INDIRECT_ACTION_SPEC,
1469 	INDIRECT_ACTION_LIST,
1470 	INDIRECT_ACTION_FLOW_CONF,
1471 	ZERO,
1472 };
1473 
1474 static const enum index next_ia[] = {
1475 	INDIRECT_ACTION_ID2PTR,
1476 	ACTION_NEXT,
1477 	ZERO
1478 };
1479 
1480 static const enum index next_ial[] = {
1481 	ACTION_INDIRECT_LIST_HANDLE,
1482 	ACTION_INDIRECT_LIST_CONF,
1483 	ACTION_NEXT,
1484 	ZERO
1485 };
1486 
1487 static const enum index next_qia_qu_attr[] = {
1488 	QUEUE_INDIRECT_ACTION_QU_MODE,
1489 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1490 	INDIRECT_ACTION_SPEC,
1491 	ZERO
1492 };
1493 
1494 static const enum index next_ia_qu_attr[] = {
1495 	INDIRECT_ACTION_QU_MODE,
1496 	INDIRECT_ACTION_SPEC,
1497 	ZERO
1498 };
1499 
1500 static const enum index next_dump_subcmd[] = {
1501 	DUMP_ALL,
1502 	DUMP_ONE,
1503 	DUMP_IS_USER_ID,
1504 	ZERO,
1505 };
1506 
1507 static const enum index next_ia_subcmd[] = {
1508 	INDIRECT_ACTION_CREATE,
1509 	INDIRECT_ACTION_UPDATE,
1510 	INDIRECT_ACTION_DESTROY,
1511 	INDIRECT_ACTION_QUERY,
1512 	INDIRECT_ACTION_QUERY_UPDATE,
1513 	ZERO,
1514 };
1515 
1516 static const enum index next_vc_attr[] = {
1517 	VC_GROUP,
1518 	VC_PRIORITY,
1519 	VC_INGRESS,
1520 	VC_EGRESS,
1521 	VC_TRANSFER,
1522 	VC_TUNNEL_SET,
1523 	VC_TUNNEL_MATCH,
1524 	VC_USER_ID,
1525 	ITEM_PATTERN,
1526 	ZERO,
1527 };
1528 
1529 static const enum index next_destroy_attr[] = {
1530 	DESTROY_RULE,
1531 	DESTROY_IS_USER_ID,
1532 	END,
1533 	ZERO,
1534 };
1535 
1536 static const enum index next_dump_attr[] = {
1537 	COMMON_FILE_PATH,
1538 	END,
1539 	ZERO,
1540 };
1541 
1542 static const enum index next_query_attr[] = {
1543 	QUERY_IS_USER_ID,
1544 	END,
1545 	ZERO,
1546 };
1547 
1548 static const enum index next_list_attr[] = {
1549 	LIST_GROUP,
1550 	END,
1551 	ZERO,
1552 };
1553 
1554 static const enum index next_aged_attr[] = {
1555 	AGED_DESTROY,
1556 	END,
1557 	ZERO,
1558 };
1559 
1560 static const enum index next_ia_destroy_attr[] = {
1561 	INDIRECT_ACTION_DESTROY_ID,
1562 	END,
1563 	ZERO,
1564 };
1565 
1566 static const enum index next_async_insert_subcmd[] = {
1567 	QUEUE_PATTERN_TEMPLATE,
1568 	QUEUE_RULE_ID,
1569 	ZERO,
1570 };
1571 
1572 static const enum index item_param[] = {
1573 	ITEM_PARAM_IS,
1574 	ITEM_PARAM_SPEC,
1575 	ITEM_PARAM_LAST,
1576 	ITEM_PARAM_MASK,
1577 	ITEM_PARAM_PREFIX,
1578 	ZERO,
1579 };
1580 
1581 static const enum index next_item[] = {
1582 	ITEM_END,
1583 	ITEM_VOID,
1584 	ITEM_INVERT,
1585 	ITEM_ANY,
1586 	ITEM_PORT_ID,
1587 	ITEM_MARK,
1588 	ITEM_RAW,
1589 	ITEM_ETH,
1590 	ITEM_VLAN,
1591 	ITEM_IPV4,
1592 	ITEM_IPV6,
1593 	ITEM_ICMP,
1594 	ITEM_UDP,
1595 	ITEM_TCP,
1596 	ITEM_SCTP,
1597 	ITEM_VXLAN,
1598 	ITEM_E_TAG,
1599 	ITEM_NVGRE,
1600 	ITEM_MPLS,
1601 	ITEM_GRE,
1602 	ITEM_FUZZY,
1603 	ITEM_GTP,
1604 	ITEM_GTPC,
1605 	ITEM_GTPU,
1606 	ITEM_GENEVE,
1607 	ITEM_VXLAN_GPE,
1608 	ITEM_ARP_ETH_IPV4,
1609 	ITEM_IPV6_EXT,
1610 	ITEM_IPV6_FRAG_EXT,
1611 	ITEM_IPV6_ROUTING_EXT,
1612 	ITEM_ICMP6,
1613 	ITEM_ICMP6_ECHO_REQUEST,
1614 	ITEM_ICMP6_ECHO_REPLY,
1615 	ITEM_ICMP6_ND_NS,
1616 	ITEM_ICMP6_ND_NA,
1617 	ITEM_ICMP6_ND_OPT,
1618 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1619 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1620 	ITEM_META,
1621 	ITEM_RANDOM,
1622 	ITEM_GRE_KEY,
1623 	ITEM_GRE_OPTION,
1624 	ITEM_GTP_PSC,
1625 	ITEM_PPPOES,
1626 	ITEM_PPPOED,
1627 	ITEM_PPPOE_PROTO_ID,
1628 	ITEM_HIGIG2,
1629 	ITEM_TAG,
1630 	ITEM_L2TPV3OIP,
1631 	ITEM_ESP,
1632 	ITEM_AH,
1633 	ITEM_PFCP,
1634 	ITEM_ECPRI,
1635 	ITEM_GENEVE_OPT,
1636 	ITEM_INTEGRITY,
1637 	ITEM_CONNTRACK,
1638 	ITEM_PORT_REPRESENTOR,
1639 	ITEM_REPRESENTED_PORT,
1640 	ITEM_FLEX,
1641 	ITEM_L2TPV2,
1642 	ITEM_PPP,
1643 	ITEM_METER,
1644 	ITEM_QUOTA,
1645 	ITEM_AGGR_AFFINITY,
1646 	ITEM_TX_QUEUE,
1647 	ITEM_IB_BTH,
1648 	ITEM_PTYPE,
1649 	ITEM_NSH,
1650 	ITEM_COMPARE,
1651 	END_SET,
1652 	ZERO,
1653 };
1654 
1655 static const enum index item_fuzzy[] = {
1656 	ITEM_FUZZY_THRESH,
1657 	ITEM_NEXT,
1658 	ZERO,
1659 };
1660 
1661 static const enum index item_any[] = {
1662 	ITEM_ANY_NUM,
1663 	ITEM_NEXT,
1664 	ZERO,
1665 };
1666 
1667 static const enum index item_port_id[] = {
1668 	ITEM_PORT_ID_ID,
1669 	ITEM_NEXT,
1670 	ZERO,
1671 };
1672 
1673 static const enum index item_mark[] = {
1674 	ITEM_MARK_ID,
1675 	ITEM_NEXT,
1676 	ZERO,
1677 };
1678 
1679 static const enum index item_raw[] = {
1680 	ITEM_RAW_RELATIVE,
1681 	ITEM_RAW_SEARCH,
1682 	ITEM_RAW_OFFSET,
1683 	ITEM_RAW_LIMIT,
1684 	ITEM_RAW_PATTERN,
1685 	ITEM_RAW_PATTERN_HEX,
1686 	ITEM_NEXT,
1687 	ZERO,
1688 };
1689 
1690 static const enum index item_eth[] = {
1691 	ITEM_ETH_DST,
1692 	ITEM_ETH_SRC,
1693 	ITEM_ETH_TYPE,
1694 	ITEM_ETH_HAS_VLAN,
1695 	ITEM_NEXT,
1696 	ZERO,
1697 };
1698 
1699 static const enum index item_vlan[] = {
1700 	ITEM_VLAN_TCI,
1701 	ITEM_VLAN_PCP,
1702 	ITEM_VLAN_DEI,
1703 	ITEM_VLAN_VID,
1704 	ITEM_VLAN_INNER_TYPE,
1705 	ITEM_VLAN_HAS_MORE_VLAN,
1706 	ITEM_NEXT,
1707 	ZERO,
1708 };
1709 
1710 static const enum index item_ipv4[] = {
1711 	ITEM_IPV4_VER_IHL,
1712 	ITEM_IPV4_TOS,
1713 	ITEM_IPV4_LENGTH,
1714 	ITEM_IPV4_ID,
1715 	ITEM_IPV4_FRAGMENT_OFFSET,
1716 	ITEM_IPV4_TTL,
1717 	ITEM_IPV4_PROTO,
1718 	ITEM_IPV4_SRC,
1719 	ITEM_IPV4_DST,
1720 	ITEM_NEXT,
1721 	ZERO,
1722 };
1723 
1724 static const enum index item_ipv6[] = {
1725 	ITEM_IPV6_TC,
1726 	ITEM_IPV6_FLOW,
1727 	ITEM_IPV6_LEN,
1728 	ITEM_IPV6_PROTO,
1729 	ITEM_IPV6_HOP,
1730 	ITEM_IPV6_SRC,
1731 	ITEM_IPV6_DST,
1732 	ITEM_IPV6_HAS_FRAG_EXT,
1733 	ITEM_IPV6_ROUTING_EXT,
1734 	ITEM_NEXT,
1735 	ZERO,
1736 };
1737 
1738 static const enum index item_ipv6_routing_ext[] = {
1739 	ITEM_IPV6_ROUTING_EXT_TYPE,
1740 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1741 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1742 	ITEM_NEXT,
1743 	ZERO,
1744 };
1745 
1746 static const enum index item_icmp[] = {
1747 	ITEM_ICMP_TYPE,
1748 	ITEM_ICMP_CODE,
1749 	ITEM_ICMP_IDENT,
1750 	ITEM_ICMP_SEQ,
1751 	ITEM_NEXT,
1752 	ZERO,
1753 };
1754 
1755 static const enum index item_udp[] = {
1756 	ITEM_UDP_SRC,
1757 	ITEM_UDP_DST,
1758 	ITEM_NEXT,
1759 	ZERO,
1760 };
1761 
1762 static const enum index item_tcp[] = {
1763 	ITEM_TCP_SRC,
1764 	ITEM_TCP_DST,
1765 	ITEM_TCP_FLAGS,
1766 	ITEM_NEXT,
1767 	ZERO,
1768 };
1769 
1770 static const enum index item_sctp[] = {
1771 	ITEM_SCTP_SRC,
1772 	ITEM_SCTP_DST,
1773 	ITEM_SCTP_TAG,
1774 	ITEM_SCTP_CKSUM,
1775 	ITEM_NEXT,
1776 	ZERO,
1777 };
1778 
1779 static const enum index item_vxlan[] = {
1780 	ITEM_VXLAN_VNI,
1781 	ITEM_VXLAN_LAST_RSVD,
1782 	ITEM_NEXT,
1783 	ZERO,
1784 };
1785 
1786 static const enum index item_e_tag[] = {
1787 	ITEM_E_TAG_GRP_ECID_B,
1788 	ITEM_NEXT,
1789 	ZERO,
1790 };
1791 
1792 static const enum index item_nvgre[] = {
1793 	ITEM_NVGRE_TNI,
1794 	ITEM_NEXT,
1795 	ZERO,
1796 };
1797 
1798 static const enum index item_mpls[] = {
1799 	ITEM_MPLS_LABEL,
1800 	ITEM_MPLS_TC,
1801 	ITEM_MPLS_S,
1802 	ITEM_MPLS_TTL,
1803 	ITEM_NEXT,
1804 	ZERO,
1805 };
1806 
1807 static const enum index item_gre[] = {
1808 	ITEM_GRE_PROTO,
1809 	ITEM_GRE_C_RSVD0_VER,
1810 	ITEM_GRE_C_BIT,
1811 	ITEM_GRE_K_BIT,
1812 	ITEM_GRE_S_BIT,
1813 	ITEM_NEXT,
1814 	ZERO,
1815 };
1816 
1817 static const enum index item_gre_key[] = {
1818 	ITEM_GRE_KEY_VALUE,
1819 	ITEM_NEXT,
1820 	ZERO,
1821 };
1822 
1823 static const enum index item_gre_option[] = {
1824 	ITEM_GRE_OPTION_CHECKSUM,
1825 	ITEM_GRE_OPTION_KEY,
1826 	ITEM_GRE_OPTION_SEQUENCE,
1827 	ITEM_NEXT,
1828 	ZERO,
1829 };
1830 
1831 static const enum index item_gtp[] = {
1832 	ITEM_GTP_FLAGS,
1833 	ITEM_GTP_MSG_TYPE,
1834 	ITEM_GTP_TEID,
1835 	ITEM_NEXT,
1836 	ZERO,
1837 };
1838 
1839 static const enum index item_geneve[] = {
1840 	ITEM_GENEVE_VNI,
1841 	ITEM_GENEVE_PROTO,
1842 	ITEM_GENEVE_OPTLEN,
1843 	ITEM_NEXT,
1844 	ZERO,
1845 };
1846 
1847 static const enum index item_vxlan_gpe[] = {
1848 	ITEM_VXLAN_GPE_VNI,
1849 	ITEM_VXLAN_GPE_PROTO,
1850 	ITEM_VXLAN_GPE_FLAGS,
1851 	ITEM_VXLAN_GPE_RSVD0,
1852 	ITEM_VXLAN_GPE_RSVD1,
1853 	ITEM_NEXT,
1854 	ZERO,
1855 };
1856 
1857 static const enum index item_arp_eth_ipv4[] = {
1858 	ITEM_ARP_ETH_IPV4_SHA,
1859 	ITEM_ARP_ETH_IPV4_SPA,
1860 	ITEM_ARP_ETH_IPV4_THA,
1861 	ITEM_ARP_ETH_IPV4_TPA,
1862 	ITEM_NEXT,
1863 	ZERO,
1864 };
1865 
1866 static const enum index item_ipv6_ext[] = {
1867 	ITEM_IPV6_EXT_NEXT_HDR,
1868 	ITEM_NEXT,
1869 	ZERO,
1870 };
1871 
1872 static const enum index item_ipv6_frag_ext[] = {
1873 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1874 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1875 	ITEM_IPV6_FRAG_EXT_ID,
1876 	ITEM_NEXT,
1877 	ZERO,
1878 };
1879 
1880 static const enum index item_icmp6[] = {
1881 	ITEM_ICMP6_TYPE,
1882 	ITEM_ICMP6_CODE,
1883 	ITEM_NEXT,
1884 	ZERO,
1885 };
1886 
1887 static const enum index item_icmp6_echo_request[] = {
1888 	ITEM_ICMP6_ECHO_REQUEST_ID,
1889 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1890 	ITEM_NEXT,
1891 	ZERO,
1892 };
1893 
1894 static const enum index item_icmp6_echo_reply[] = {
1895 	ITEM_ICMP6_ECHO_REPLY_ID,
1896 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1897 	ITEM_NEXT,
1898 	ZERO,
1899 };
1900 
1901 static const enum index item_icmp6_nd_ns[] = {
1902 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1903 	ITEM_NEXT,
1904 	ZERO,
1905 };
1906 
1907 static const enum index item_icmp6_nd_na[] = {
1908 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1909 	ITEM_NEXT,
1910 	ZERO,
1911 };
1912 
1913 static const enum index item_icmp6_nd_opt[] = {
1914 	ITEM_ICMP6_ND_OPT_TYPE,
1915 	ITEM_NEXT,
1916 	ZERO,
1917 };
1918 
1919 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1920 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1921 	ITEM_NEXT,
1922 	ZERO,
1923 };
1924 
1925 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1926 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1927 	ITEM_NEXT,
1928 	ZERO,
1929 };
1930 
1931 static const enum index item_meta[] = {
1932 	ITEM_META_DATA,
1933 	ITEM_NEXT,
1934 	ZERO,
1935 };
1936 
1937 static const enum index item_random[] = {
1938 	ITEM_RANDOM_VALUE,
1939 	ITEM_NEXT,
1940 	ZERO,
1941 };
1942 
1943 static const enum index item_gtp_psc[] = {
1944 	ITEM_GTP_PSC_QFI,
1945 	ITEM_GTP_PSC_PDU_T,
1946 	ITEM_NEXT,
1947 	ZERO,
1948 };
1949 
1950 static const enum index item_pppoed[] = {
1951 	ITEM_PPPOE_SEID,
1952 	ITEM_NEXT,
1953 	ZERO,
1954 };
1955 
1956 static const enum index item_pppoes[] = {
1957 	ITEM_PPPOE_SEID,
1958 	ITEM_NEXT,
1959 	ZERO,
1960 };
1961 
1962 static const enum index item_pppoe_proto_id[] = {
1963 	ITEM_NEXT,
1964 	ZERO,
1965 };
1966 
1967 static const enum index item_higig2[] = {
1968 	ITEM_HIGIG2_CLASSIFICATION,
1969 	ITEM_HIGIG2_VID,
1970 	ITEM_NEXT,
1971 	ZERO,
1972 };
1973 
1974 static const enum index item_esp[] = {
1975 	ITEM_ESP_SPI,
1976 	ITEM_NEXT,
1977 	ZERO,
1978 };
1979 
1980 static const enum index item_ah[] = {
1981 	ITEM_AH_SPI,
1982 	ITEM_NEXT,
1983 	ZERO,
1984 };
1985 
1986 static const enum index item_pfcp[] = {
1987 	ITEM_PFCP_S_FIELD,
1988 	ITEM_PFCP_SEID,
1989 	ITEM_NEXT,
1990 	ZERO,
1991 };
1992 
1993 static const enum index next_set_raw[] = {
1994 	SET_RAW_INDEX,
1995 	ITEM_ETH,
1996 	ZERO,
1997 };
1998 
1999 static const enum index item_tag[] = {
2000 	ITEM_TAG_DATA,
2001 	ITEM_TAG_INDEX,
2002 	ITEM_NEXT,
2003 	ZERO,
2004 };
2005 
2006 static const enum index item_l2tpv3oip[] = {
2007 	ITEM_L2TPV3OIP_SESSION_ID,
2008 	ITEM_NEXT,
2009 	ZERO,
2010 };
2011 
2012 static const enum index item_ecpri[] = {
2013 	ITEM_ECPRI_COMMON,
2014 	ITEM_NEXT,
2015 	ZERO,
2016 };
2017 
2018 static const enum index item_ecpri_common[] = {
2019 	ITEM_ECPRI_COMMON_TYPE,
2020 	ZERO,
2021 };
2022 
2023 static const enum index item_ecpri_common_type[] = {
2024 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2025 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2026 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2027 	ZERO,
2028 };
2029 
2030 static const enum index item_geneve_opt[] = {
2031 	ITEM_GENEVE_OPT_CLASS,
2032 	ITEM_GENEVE_OPT_TYPE,
2033 	ITEM_GENEVE_OPT_LENGTH,
2034 	ITEM_GENEVE_OPT_DATA,
2035 	ITEM_NEXT,
2036 	ZERO,
2037 };
2038 
2039 static const enum index item_integrity[] = {
2040 	ITEM_INTEGRITY_LEVEL,
2041 	ITEM_INTEGRITY_VALUE,
2042 	ZERO,
2043 };
2044 
2045 static const enum index item_integrity_lv[] = {
2046 	ITEM_INTEGRITY_LEVEL,
2047 	ITEM_INTEGRITY_VALUE,
2048 	ITEM_NEXT,
2049 	ZERO,
2050 };
2051 
2052 static const enum index item_port_representor[] = {
2053 	ITEM_PORT_REPRESENTOR_PORT_ID,
2054 	ITEM_NEXT,
2055 	ZERO,
2056 };
2057 
2058 static const enum index item_represented_port[] = {
2059 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2060 	ITEM_NEXT,
2061 	ZERO,
2062 };
2063 
2064 static const enum index item_flex[] = {
2065 	ITEM_FLEX_PATTERN_HANDLE,
2066 	ITEM_FLEX_ITEM_HANDLE,
2067 	ITEM_NEXT,
2068 	ZERO,
2069 };
2070 
2071 static const enum index item_l2tpv2[] = {
2072 	ITEM_L2TPV2_TYPE,
2073 	ITEM_NEXT,
2074 	ZERO,
2075 };
2076 
2077 static const enum index item_l2tpv2_type[] = {
2078 	ITEM_L2TPV2_TYPE_DATA,
2079 	ITEM_L2TPV2_TYPE_DATA_L,
2080 	ITEM_L2TPV2_TYPE_DATA_S,
2081 	ITEM_L2TPV2_TYPE_DATA_O,
2082 	ITEM_L2TPV2_TYPE_DATA_L_S,
2083 	ITEM_L2TPV2_TYPE_CTRL,
2084 	ZERO,
2085 };
2086 
2087 static const enum index item_l2tpv2_type_data[] = {
2088 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2089 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2090 	ITEM_NEXT,
2091 	ZERO,
2092 };
2093 
2094 static const enum index item_l2tpv2_type_data_l[] = {
2095 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2096 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2097 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2098 	ITEM_NEXT,
2099 	ZERO,
2100 };
2101 
2102 static const enum index item_l2tpv2_type_data_s[] = {
2103 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2104 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2105 	ITEM_L2TPV2_MSG_DATA_S_NS,
2106 	ITEM_L2TPV2_MSG_DATA_S_NR,
2107 	ITEM_NEXT,
2108 	ZERO,
2109 };
2110 
2111 static const enum index item_l2tpv2_type_data_o[] = {
2112 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2113 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2114 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2115 	ITEM_NEXT,
2116 	ZERO,
2117 };
2118 
2119 static const enum index item_l2tpv2_type_data_l_s[] = {
2120 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2121 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2122 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2123 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2124 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2125 	ITEM_NEXT,
2126 	ZERO,
2127 };
2128 
2129 static const enum index item_l2tpv2_type_ctrl[] = {
2130 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2131 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2132 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2133 	ITEM_L2TPV2_MSG_CTRL_NS,
2134 	ITEM_L2TPV2_MSG_CTRL_NR,
2135 	ITEM_NEXT,
2136 	ZERO,
2137 };
2138 
2139 static const enum index item_ppp[] = {
2140 	ITEM_PPP_ADDR,
2141 	ITEM_PPP_CTRL,
2142 	ITEM_PPP_PROTO_ID,
2143 	ITEM_NEXT,
2144 	ZERO,
2145 };
2146 
2147 static const enum index item_meter[] = {
2148 	ITEM_METER_COLOR,
2149 	ITEM_NEXT,
2150 	ZERO,
2151 };
2152 
2153 static const enum index item_quota[] = {
2154 	ITEM_QUOTA_STATE,
2155 	ITEM_NEXT,
2156 	ZERO,
2157 };
2158 
2159 static const enum index item_aggr_affinity[] = {
2160 	ITEM_AGGR_AFFINITY_VALUE,
2161 	ITEM_NEXT,
2162 	ZERO,
2163 };
2164 
2165 static const enum index item_tx_queue[] = {
2166 	ITEM_TX_QUEUE_VALUE,
2167 	ITEM_NEXT,
2168 	ZERO,
2169 };
2170 
2171 static const enum index item_ib_bth[] = {
2172 	ITEM_IB_BTH_OPCODE,
2173 	ITEM_IB_BTH_PKEY,
2174 	ITEM_IB_BTH_DST_QPN,
2175 	ITEM_IB_BTH_PSN,
2176 	ITEM_NEXT,
2177 	ZERO,
2178 };
2179 
2180 static const enum index item_ptype[] = {
2181 	ITEM_PTYPE_VALUE,
2182 	ITEM_NEXT,
2183 	ZERO,
2184 };
2185 
2186 static const enum index item_nsh[] = {
2187 	ITEM_NEXT,
2188 	ZERO,
2189 };
2190 
2191 static const enum index item_compare_field[] = {
2192 	ITEM_COMPARE_OP,
2193 	ITEM_COMPARE_FIELD_A_TYPE,
2194 	ITEM_COMPARE_FIELD_B_TYPE,
2195 	ITEM_NEXT,
2196 	ZERO,
2197 };
2198 
2199 static const enum index compare_field_a[] = {
2200 	ITEM_COMPARE_FIELD_A_TYPE,
2201 	ITEM_COMPARE_FIELD_A_LEVEL,
2202 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2203 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2204 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2205 	ITEM_COMPARE_FIELD_A_OFFSET,
2206 	ITEM_COMPARE_FIELD_B_TYPE,
2207 	ZERO,
2208 };
2209 
2210 static const enum index compare_field_b[] = {
2211 	ITEM_COMPARE_FIELD_B_TYPE,
2212 	ITEM_COMPARE_FIELD_B_LEVEL,
2213 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2214 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2215 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2216 	ITEM_COMPARE_FIELD_B_OFFSET,
2217 	ITEM_COMPARE_FIELD_B_VALUE,
2218 	ITEM_COMPARE_FIELD_B_POINTER,
2219 	ITEM_COMPARE_FIELD_WIDTH,
2220 	ZERO,
2221 };
2222 
2223 static const enum index next_action[] = {
2224 	ACTION_END,
2225 	ACTION_VOID,
2226 	ACTION_PASSTHRU,
2227 	ACTION_SKIP_CMAN,
2228 	ACTION_JUMP,
2229 	ACTION_MARK,
2230 	ACTION_FLAG,
2231 	ACTION_QUEUE,
2232 	ACTION_DROP,
2233 	ACTION_COUNT,
2234 	ACTION_RSS,
2235 	ACTION_PF,
2236 	ACTION_VF,
2237 	ACTION_PORT_ID,
2238 	ACTION_METER,
2239 	ACTION_METER_COLOR,
2240 	ACTION_METER_MARK,
2241 	ACTION_OF_DEC_NW_TTL,
2242 	ACTION_OF_POP_VLAN,
2243 	ACTION_OF_PUSH_VLAN,
2244 	ACTION_OF_SET_VLAN_VID,
2245 	ACTION_OF_SET_VLAN_PCP,
2246 	ACTION_OF_POP_MPLS,
2247 	ACTION_OF_PUSH_MPLS,
2248 	ACTION_VXLAN_ENCAP,
2249 	ACTION_VXLAN_DECAP,
2250 	ACTION_NVGRE_ENCAP,
2251 	ACTION_NVGRE_DECAP,
2252 	ACTION_L2_ENCAP,
2253 	ACTION_L2_DECAP,
2254 	ACTION_MPLSOGRE_ENCAP,
2255 	ACTION_MPLSOGRE_DECAP,
2256 	ACTION_MPLSOUDP_ENCAP,
2257 	ACTION_MPLSOUDP_DECAP,
2258 	ACTION_SET_IPV4_SRC,
2259 	ACTION_SET_IPV4_DST,
2260 	ACTION_SET_IPV6_SRC,
2261 	ACTION_SET_IPV6_DST,
2262 	ACTION_SET_TP_SRC,
2263 	ACTION_SET_TP_DST,
2264 	ACTION_MAC_SWAP,
2265 	ACTION_DEC_TTL,
2266 	ACTION_SET_TTL,
2267 	ACTION_SET_MAC_SRC,
2268 	ACTION_SET_MAC_DST,
2269 	ACTION_INC_TCP_SEQ,
2270 	ACTION_DEC_TCP_SEQ,
2271 	ACTION_INC_TCP_ACK,
2272 	ACTION_DEC_TCP_ACK,
2273 	ACTION_RAW_ENCAP,
2274 	ACTION_RAW_DECAP,
2275 	ACTION_SET_TAG,
2276 	ACTION_SET_META,
2277 	ACTION_SET_IPV4_DSCP,
2278 	ACTION_SET_IPV6_DSCP,
2279 	ACTION_AGE,
2280 	ACTION_AGE_UPDATE,
2281 	ACTION_SAMPLE,
2282 	ACTION_INDIRECT,
2283 	ACTION_INDIRECT_LIST,
2284 	ACTION_SHARED_INDIRECT,
2285 	ACTION_MODIFY_FIELD,
2286 	ACTION_CONNTRACK,
2287 	ACTION_CONNTRACK_UPDATE,
2288 	ACTION_PORT_REPRESENTOR,
2289 	ACTION_REPRESENTED_PORT,
2290 	ACTION_SEND_TO_KERNEL,
2291 	ACTION_QUOTA_CREATE,
2292 	ACTION_QUOTA_QU,
2293 	ACTION_IPV6_EXT_REMOVE,
2294 	ACTION_IPV6_EXT_PUSH,
2295 	ACTION_NAT64,
2296 	ZERO,
2297 };
2298 
2299 static const enum index action_quota_create[] = {
2300 	ACTION_QUOTA_CREATE_LIMIT,
2301 	ACTION_QUOTA_CREATE_MODE,
2302 	ACTION_NEXT,
2303 	ZERO
2304 };
2305 
2306 static const enum index action_quota_update[] = {
2307 	ACTION_QUOTA_QU_LIMIT,
2308 	ACTION_QUOTA_QU_UPDATE_OP,
2309 	ACTION_NEXT,
2310 	ZERO
2311 };
2312 
2313 static const enum index action_mark[] = {
2314 	ACTION_MARK_ID,
2315 	ACTION_NEXT,
2316 	ZERO,
2317 };
2318 
2319 static const enum index action_queue[] = {
2320 	ACTION_QUEUE_INDEX,
2321 	ACTION_NEXT,
2322 	ZERO,
2323 };
2324 
2325 static const enum index action_count[] = {
2326 	ACTION_COUNT_ID,
2327 	ACTION_NEXT,
2328 	ZERO,
2329 };
2330 
2331 static const enum index action_rss[] = {
2332 	ACTION_RSS_FUNC,
2333 	ACTION_RSS_LEVEL,
2334 	ACTION_RSS_TYPES,
2335 	ACTION_RSS_KEY,
2336 	ACTION_RSS_KEY_LEN,
2337 	ACTION_RSS_QUEUES,
2338 	ACTION_NEXT,
2339 	ZERO,
2340 };
2341 
2342 static const enum index action_vf[] = {
2343 	ACTION_VF_ORIGINAL,
2344 	ACTION_VF_ID,
2345 	ACTION_NEXT,
2346 	ZERO,
2347 };
2348 
2349 static const enum index action_port_id[] = {
2350 	ACTION_PORT_ID_ORIGINAL,
2351 	ACTION_PORT_ID_ID,
2352 	ACTION_NEXT,
2353 	ZERO,
2354 };
2355 
2356 static const enum index action_meter[] = {
2357 	ACTION_METER_ID,
2358 	ACTION_NEXT,
2359 	ZERO,
2360 };
2361 
2362 static const enum index action_meter_color[] = {
2363 	ACTION_METER_COLOR_TYPE,
2364 	ACTION_NEXT,
2365 	ZERO,
2366 };
2367 
2368 static const enum index action_meter_mark[] = {
2369 	ACTION_METER_PROFILE,
2370 	ACTION_METER_POLICY,
2371 	ACTION_METER_COLOR_MODE,
2372 	ACTION_METER_STATE,
2373 	ACTION_NEXT,
2374 	ZERO,
2375 };
2376 
2377 static const enum index action_of_push_vlan[] = {
2378 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2379 	ACTION_NEXT,
2380 	ZERO,
2381 };
2382 
2383 static const enum index action_of_set_vlan_vid[] = {
2384 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2385 	ACTION_NEXT,
2386 	ZERO,
2387 };
2388 
2389 static const enum index action_of_set_vlan_pcp[] = {
2390 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2391 	ACTION_NEXT,
2392 	ZERO,
2393 };
2394 
2395 static const enum index action_of_pop_mpls[] = {
2396 	ACTION_OF_POP_MPLS_ETHERTYPE,
2397 	ACTION_NEXT,
2398 	ZERO,
2399 };
2400 
2401 static const enum index action_of_push_mpls[] = {
2402 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2403 	ACTION_NEXT,
2404 	ZERO,
2405 };
2406 
2407 static const enum index action_set_ipv4_src[] = {
2408 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2409 	ACTION_NEXT,
2410 	ZERO,
2411 };
2412 
2413 static const enum index action_set_mac_src[] = {
2414 	ACTION_SET_MAC_SRC_MAC_SRC,
2415 	ACTION_NEXT,
2416 	ZERO,
2417 };
2418 
2419 static const enum index action_set_ipv4_dst[] = {
2420 	ACTION_SET_IPV4_DST_IPV4_DST,
2421 	ACTION_NEXT,
2422 	ZERO,
2423 };
2424 
2425 static const enum index action_set_ipv6_src[] = {
2426 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2427 	ACTION_NEXT,
2428 	ZERO,
2429 };
2430 
2431 static const enum index action_set_ipv6_dst[] = {
2432 	ACTION_SET_IPV6_DST_IPV6_DST,
2433 	ACTION_NEXT,
2434 	ZERO,
2435 };
2436 
2437 static const enum index action_set_tp_src[] = {
2438 	ACTION_SET_TP_SRC_TP_SRC,
2439 	ACTION_NEXT,
2440 	ZERO,
2441 };
2442 
2443 static const enum index action_set_tp_dst[] = {
2444 	ACTION_SET_TP_DST_TP_DST,
2445 	ACTION_NEXT,
2446 	ZERO,
2447 };
2448 
2449 static const enum index action_set_ttl[] = {
2450 	ACTION_SET_TTL_TTL,
2451 	ACTION_NEXT,
2452 	ZERO,
2453 };
2454 
2455 static const enum index action_jump[] = {
2456 	ACTION_JUMP_GROUP,
2457 	ACTION_NEXT,
2458 	ZERO,
2459 };
2460 
2461 static const enum index action_set_mac_dst[] = {
2462 	ACTION_SET_MAC_DST_MAC_DST,
2463 	ACTION_NEXT,
2464 	ZERO,
2465 };
2466 
2467 static const enum index action_inc_tcp_seq[] = {
2468 	ACTION_INC_TCP_SEQ_VALUE,
2469 	ACTION_NEXT,
2470 	ZERO,
2471 };
2472 
2473 static const enum index action_dec_tcp_seq[] = {
2474 	ACTION_DEC_TCP_SEQ_VALUE,
2475 	ACTION_NEXT,
2476 	ZERO,
2477 };
2478 
2479 static const enum index action_inc_tcp_ack[] = {
2480 	ACTION_INC_TCP_ACK_VALUE,
2481 	ACTION_NEXT,
2482 	ZERO,
2483 };
2484 
2485 static const enum index action_dec_tcp_ack[] = {
2486 	ACTION_DEC_TCP_ACK_VALUE,
2487 	ACTION_NEXT,
2488 	ZERO,
2489 };
2490 
2491 static const enum index action_raw_encap[] = {
2492 	ACTION_RAW_ENCAP_SIZE,
2493 	ACTION_RAW_ENCAP_INDEX,
2494 	ACTION_NEXT,
2495 	ZERO,
2496 };
2497 
2498 static const enum index action_raw_decap[] = {
2499 	ACTION_RAW_DECAP_INDEX,
2500 	ACTION_NEXT,
2501 	ZERO,
2502 };
2503 
2504 static const enum index action_ipv6_ext_remove[] = {
2505 	ACTION_IPV6_EXT_REMOVE_INDEX,
2506 	ACTION_NEXT,
2507 	ZERO,
2508 };
2509 
2510 static const enum index action_ipv6_ext_push[] = {
2511 	ACTION_IPV6_EXT_PUSH_INDEX,
2512 	ACTION_NEXT,
2513 	ZERO,
2514 };
2515 
2516 static const enum index action_set_tag[] = {
2517 	ACTION_SET_TAG_DATA,
2518 	ACTION_SET_TAG_INDEX,
2519 	ACTION_SET_TAG_MASK,
2520 	ACTION_NEXT,
2521 	ZERO,
2522 };
2523 
2524 static const enum index action_set_meta[] = {
2525 	ACTION_SET_META_DATA,
2526 	ACTION_SET_META_MASK,
2527 	ACTION_NEXT,
2528 	ZERO,
2529 };
2530 
2531 static const enum index action_set_ipv4_dscp[] = {
2532 	ACTION_SET_IPV4_DSCP_VALUE,
2533 	ACTION_NEXT,
2534 	ZERO,
2535 };
2536 
2537 static const enum index action_set_ipv6_dscp[] = {
2538 	ACTION_SET_IPV6_DSCP_VALUE,
2539 	ACTION_NEXT,
2540 	ZERO,
2541 };
2542 
2543 static const enum index action_age[] = {
2544 	ACTION_AGE,
2545 	ACTION_AGE_TIMEOUT,
2546 	ACTION_NEXT,
2547 	ZERO,
2548 };
2549 
2550 static const enum index action_age_update[] = {
2551 	ACTION_AGE_UPDATE,
2552 	ACTION_AGE_UPDATE_TIMEOUT,
2553 	ACTION_AGE_UPDATE_TOUCH,
2554 	ACTION_NEXT,
2555 	ZERO,
2556 };
2557 
2558 static const enum index action_sample[] = {
2559 	ACTION_SAMPLE,
2560 	ACTION_SAMPLE_RATIO,
2561 	ACTION_SAMPLE_INDEX,
2562 	ACTION_NEXT,
2563 	ZERO,
2564 };
2565 
2566 static const enum index next_action_sample[] = {
2567 	ACTION_QUEUE,
2568 	ACTION_RSS,
2569 	ACTION_MARK,
2570 	ACTION_COUNT,
2571 	ACTION_PORT_ID,
2572 	ACTION_RAW_ENCAP,
2573 	ACTION_VXLAN_ENCAP,
2574 	ACTION_NVGRE_ENCAP,
2575 	ACTION_REPRESENTED_PORT,
2576 	ACTION_PORT_REPRESENTOR,
2577 	ACTION_NEXT,
2578 	ZERO,
2579 };
2580 
2581 static const enum index item_ipv6_push_ext[] = {
2582 	ITEM_IPV6_PUSH_REMOVE_EXT,
2583 	ZERO,
2584 };
2585 
2586 static const enum index item_ipv6_push_ext_type[] = {
2587 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2588 	ZERO,
2589 };
2590 
2591 static const enum index item_ipv6_push_ext_header[] = {
2592 	ITEM_IPV6_ROUTING_EXT,
2593 	ITEM_NEXT,
2594 	ZERO,
2595 };
2596 
2597 static const enum index action_modify_field_dst[] = {
2598 	ACTION_MODIFY_FIELD_DST_LEVEL,
2599 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2600 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2601 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2602 	ACTION_MODIFY_FIELD_DST_OFFSET,
2603 	ACTION_MODIFY_FIELD_SRC_TYPE,
2604 	ZERO,
2605 };
2606 
2607 static const enum index action_modify_field_src[] = {
2608 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2609 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2610 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2611 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2612 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2613 	ACTION_MODIFY_FIELD_SRC_VALUE,
2614 	ACTION_MODIFY_FIELD_SRC_POINTER,
2615 	ACTION_MODIFY_FIELD_WIDTH,
2616 	ZERO,
2617 };
2618 
2619 static const enum index action_update_conntrack[] = {
2620 	ACTION_CONNTRACK_UPDATE_DIR,
2621 	ACTION_CONNTRACK_UPDATE_CTX,
2622 	ACTION_NEXT,
2623 	ZERO,
2624 };
2625 
2626 static const enum index action_port_representor[] = {
2627 	ACTION_PORT_REPRESENTOR_PORT_ID,
2628 	ACTION_NEXT,
2629 	ZERO,
2630 };
2631 
2632 static const enum index action_represented_port[] = {
2633 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2634 	ACTION_NEXT,
2635 	ZERO,
2636 };
2637 
2638 static const enum index action_nat64[] = {
2639 	ACTION_NAT64_MODE,
2640 	ACTION_NEXT,
2641 	ZERO,
2642 };
2643 
2644 static const enum index next_hash_subcmd[] = {
2645 	HASH_CALC_TABLE,
2646 	HASH_CALC_ENCAP,
2647 	ZERO,
2648 };
2649 
2650 static const enum index next_hash_encap_dest_subcmd[] = {
2651 	ENCAP_HASH_FIELD_SRC_PORT,
2652 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2653 	ZERO,
2654 };
2655 
2656 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2657 				     const char *, unsigned int,
2658 				     void *, unsigned int);
2659 static int parse_set_sample_action(struct context *, const struct token *,
2660 				   const char *, unsigned int,
2661 				   void *, unsigned int);
2662 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2663 				     const char *, unsigned int,
2664 				     void *, unsigned int);
2665 static int parse_set_init(struct context *, const struct token *,
2666 			  const char *, unsigned int,
2667 			  void *, unsigned int);
2668 static int
2669 parse_flex_handle(struct context *, const struct token *,
2670 		  const char *, unsigned int, void *, unsigned int);
2671 static int parse_init(struct context *, const struct token *,
2672 		      const char *, unsigned int,
2673 		      void *, unsigned int);
2674 static int parse_vc(struct context *, const struct token *,
2675 		    const char *, unsigned int,
2676 		    void *, unsigned int);
2677 static int parse_vc_spec(struct context *, const struct token *,
2678 			 const char *, unsigned int, void *, unsigned int);
2679 static int parse_vc_conf(struct context *, const struct token *,
2680 			 const char *, unsigned int, void *, unsigned int);
2681 static int parse_vc_conf_timeout(struct context *, const struct token *,
2682 				 const char *, unsigned int, void *,
2683 				 unsigned int);
2684 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2685 				    const char *, unsigned int,
2686 				    void *, unsigned int);
2687 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2688 				    const char *, unsigned int,
2689 				    void *, unsigned int);
2690 static int parse_vc_action_meter_color_type(struct context *,
2691 					const struct token *,
2692 					const char *, unsigned int, void *,
2693 					unsigned int);
2694 static int parse_vc_action_rss(struct context *, const struct token *,
2695 			       const char *, unsigned int, void *,
2696 			       unsigned int);
2697 static int parse_vc_action_rss_func(struct context *, const struct token *,
2698 				    const char *, unsigned int, void *,
2699 				    unsigned int);
2700 static int parse_vc_action_rss_type(struct context *, const struct token *,
2701 				    const char *, unsigned int, void *,
2702 				    unsigned int);
2703 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2704 				     const char *, unsigned int, void *,
2705 				     unsigned int);
2706 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2707 				       const char *, unsigned int, void *,
2708 				       unsigned int);
2709 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2710 				       const char *, unsigned int, void *,
2711 				       unsigned int);
2712 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2713 				    const char *, unsigned int, void *,
2714 				    unsigned int);
2715 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2716 				    const char *, unsigned int, void *,
2717 				    unsigned int);
2718 static int parse_vc_action_mplsogre_encap(struct context *,
2719 					  const struct token *, const char *,
2720 					  unsigned int, void *, unsigned int);
2721 static int parse_vc_action_mplsogre_decap(struct context *,
2722 					  const struct token *, const char *,
2723 					  unsigned int, void *, unsigned int);
2724 static int parse_vc_action_mplsoudp_encap(struct context *,
2725 					  const struct token *, const char *,
2726 					  unsigned int, void *, unsigned int);
2727 static int parse_vc_action_mplsoudp_decap(struct context *,
2728 					  const struct token *, const char *,
2729 					  unsigned int, void *, unsigned int);
2730 static int parse_vc_action_raw_encap(struct context *,
2731 				     const struct token *, const char *,
2732 				     unsigned int, void *, unsigned int);
2733 static int parse_vc_action_raw_decap(struct context *,
2734 				     const struct token *, const char *,
2735 				     unsigned int, void *, unsigned int);
2736 static int parse_vc_action_raw_encap_index(struct context *,
2737 					   const struct token *, const char *,
2738 					   unsigned int, void *, unsigned int);
2739 static int parse_vc_action_raw_decap_index(struct context *,
2740 					   const struct token *, const char *,
2741 					   unsigned int, void *, unsigned int);
2742 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2743 					   const char *str, unsigned int len, void *buf,
2744 					   unsigned int size);
2745 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2746 						 const struct token *token,
2747 						 const char *str, unsigned int len,
2748 						 void *buf,
2749 						 unsigned int size);
2750 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2751 					 const char *str, unsigned int len, void *buf,
2752 					 unsigned int size);
2753 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2754 					       const struct token *token,
2755 					       const char *str, unsigned int len,
2756 					       void *buf,
2757 					       unsigned int size);
2758 static int parse_vc_action_set_meta(struct context *ctx,
2759 				    const struct token *token, const char *str,
2760 				    unsigned int len, void *buf,
2761 					unsigned int size);
2762 static int parse_vc_action_sample(struct context *ctx,
2763 				    const struct token *token, const char *str,
2764 				    unsigned int len, void *buf,
2765 				    unsigned int size);
2766 static int
2767 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2768 				const char *str, unsigned int len, void *buf,
2769 				unsigned int size);
2770 static int
2771 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2772 				const char *str, unsigned int len, void *buf,
2773 				unsigned int size);
2774 static int
2775 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2776 				const char *str, unsigned int len, void *buf,
2777 				unsigned int size);
2778 static int
2779 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2780 				const char *str, unsigned int len, void *buf,
2781 				unsigned int size);
2782 static int
2783 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2784 			 const char *str, unsigned int len, void *buf,
2785 			 unsigned int size);
2786 static int parse_destroy(struct context *, const struct token *,
2787 			 const char *, unsigned int,
2788 			 void *, unsigned int);
2789 static int parse_flush(struct context *, const struct token *,
2790 		       const char *, unsigned int,
2791 		       void *, unsigned int);
2792 static int parse_dump(struct context *, const struct token *,
2793 		      const char *, unsigned int,
2794 		      void *, unsigned int);
2795 static int parse_query(struct context *, const struct token *,
2796 		       const char *, unsigned int,
2797 		       void *, unsigned int);
2798 static int parse_action(struct context *, const struct token *,
2799 			const char *, unsigned int,
2800 			void *, unsigned int);
2801 static int parse_list(struct context *, const struct token *,
2802 		      const char *, unsigned int,
2803 		      void *, unsigned int);
2804 static int parse_aged(struct context *, const struct token *,
2805 		      const char *, unsigned int,
2806 		      void *, unsigned int);
2807 static int parse_isolate(struct context *, const struct token *,
2808 			 const char *, unsigned int,
2809 			 void *, unsigned int);
2810 static int parse_configure(struct context *, const struct token *,
2811 			   const char *, unsigned int,
2812 			   void *, unsigned int);
2813 static int parse_template(struct context *, const struct token *,
2814 			  const char *, unsigned int,
2815 			  void *, unsigned int);
2816 static int parse_template_destroy(struct context *, const struct token *,
2817 				  const char *, unsigned int,
2818 				  void *, unsigned int);
2819 static int parse_table(struct context *, const struct token *,
2820 		       const char *, unsigned int, void *, unsigned int);
2821 static int parse_table_destroy(struct context *, const struct token *,
2822 			       const char *, unsigned int,
2823 			       void *, unsigned int);
2824 static int parse_qo(struct context *, const struct token *,
2825 		    const char *, unsigned int,
2826 		    void *, unsigned int);
2827 static int parse_qo_destroy(struct context *, const struct token *,
2828 			    const char *, unsigned int,
2829 			    void *, unsigned int);
2830 static int parse_qia(struct context *, const struct token *,
2831 		     const char *, unsigned int,
2832 		     void *, unsigned int);
2833 static int parse_qia_destroy(struct context *, const struct token *,
2834 			     const char *, unsigned int,
2835 			     void *, unsigned int);
2836 static int parse_push(struct context *, const struct token *,
2837 		      const char *, unsigned int,
2838 		      void *, unsigned int);
2839 static int parse_pull(struct context *, const struct token *,
2840 		      const char *, unsigned int,
2841 		      void *, unsigned int);
2842 static int parse_group(struct context *, const struct token *,
2843 		       const char *, unsigned int,
2844 		       void *, unsigned int);
2845 static int parse_hash(struct context *, const struct token *,
2846 		      const char *, unsigned int,
2847 		      void *, unsigned int);
2848 static int parse_tunnel(struct context *, const struct token *,
2849 			const char *, unsigned int,
2850 			void *, unsigned int);
2851 static int parse_flex(struct context *, const struct token *,
2852 		      const char *, unsigned int, void *, unsigned int);
2853 static int parse_int(struct context *, const struct token *,
2854 		     const char *, unsigned int,
2855 		     void *, unsigned int);
2856 static int parse_prefix(struct context *, const struct token *,
2857 			const char *, unsigned int,
2858 			void *, unsigned int);
2859 static int parse_boolean(struct context *, const struct token *,
2860 			 const char *, unsigned int,
2861 			 void *, unsigned int);
2862 static int parse_string(struct context *, const struct token *,
2863 			const char *, unsigned int,
2864 			void *, unsigned int);
2865 static int parse_hex(struct context *ctx, const struct token *token,
2866 			const char *str, unsigned int len,
2867 			void *buf, unsigned int size);
2868 static int parse_string0(struct context *, const struct token *,
2869 			const char *, unsigned int,
2870 			void *, unsigned int);
2871 static int parse_mac_addr(struct context *, const struct token *,
2872 			  const char *, unsigned int,
2873 			  void *, unsigned int);
2874 static int parse_ipv4_addr(struct context *, const struct token *,
2875 			   const char *, unsigned int,
2876 			   void *, unsigned int);
2877 static int parse_ipv6_addr(struct context *, const struct token *,
2878 			   const char *, unsigned int,
2879 			   void *, unsigned int);
2880 static int parse_port(struct context *, const struct token *,
2881 		      const char *, unsigned int,
2882 		      void *, unsigned int);
2883 static int parse_ia(struct context *, const struct token *,
2884 		    const char *, unsigned int,
2885 		    void *, unsigned int);
2886 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2887 			    const char *str, unsigned int len,
2888 			    void *buf, unsigned int size);
2889 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2890 			   const char *str, unsigned int len, void *buf,
2891 			   unsigned int size);
2892 
2893 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2894 			       const char *str, unsigned int len, void *buf,
2895 			       unsigned int size);
2896 static int parse_ia_port(struct context *ctx, const struct token *token,
2897 			 const char *str, unsigned int len, void *buf,
2898 			 unsigned int size);
2899 static int parse_mp(struct context *, const struct token *,
2900 		    const char *, unsigned int,
2901 		    void *, unsigned int);
2902 static int parse_meter_profile_id2ptr(struct context *ctx,
2903 				      const struct token *token,
2904 				      const char *str, unsigned int len,
2905 				      void *buf, unsigned int size);
2906 static int parse_meter_policy_id2ptr(struct context *ctx,
2907 				     const struct token *token,
2908 				     const char *str, unsigned int len,
2909 				     void *buf, unsigned int size);
2910 static int parse_meter_color(struct context *ctx, const struct token *token,
2911 			     const char *str, unsigned int len, void *buf,
2912 			     unsigned int size);
2913 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2914 				      const char *str, unsigned int len, void *buf,
2915 				      unsigned int size);
2916 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2917 				 const char *str, unsigned int len, void *buf,
2918 				 unsigned int size);
2919 static int
2920 parse_quota_state_name(struct context *ctx, const struct token *token,
2921 		       const char *str, unsigned int len, void *buf,
2922 		       unsigned int size);
2923 static int
2924 parse_quota_mode_name(struct context *ctx, const struct token *token,
2925 		      const char *str, unsigned int len, void *buf,
2926 		      unsigned int size);
2927 static int
2928 parse_quota_update_name(struct context *ctx, const struct token *token,
2929 			const char *str, unsigned int len, void *buf,
2930 			unsigned int size);
2931 static int
2932 parse_qu_mode_name(struct context *ctx, const struct token *token,
2933 		   const char *str, unsigned int len, void *buf,
2934 		   unsigned int size);
2935 static int comp_none(struct context *, const struct token *,
2936 		     unsigned int, char *, unsigned int);
2937 static int comp_boolean(struct context *, const struct token *,
2938 			unsigned int, char *, unsigned int);
2939 static int comp_action(struct context *, const struct token *,
2940 		       unsigned int, char *, unsigned int);
2941 static int comp_port(struct context *, const struct token *,
2942 		     unsigned int, char *, unsigned int);
2943 static int comp_rule_id(struct context *, const struct token *,
2944 			unsigned int, char *, unsigned int);
2945 static int comp_vc_action_rss_type(struct context *, const struct token *,
2946 				   unsigned int, char *, unsigned int);
2947 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2948 				    unsigned int, char *, unsigned int);
2949 static int comp_set_raw_index(struct context *, const struct token *,
2950 			      unsigned int, char *, unsigned int);
2951 static int comp_set_sample_index(struct context *, const struct token *,
2952 			      unsigned int, char *, unsigned int);
2953 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2954 				   unsigned int ent, char *buf, unsigned int size);
2955 static int comp_set_modify_field_op(struct context *, const struct token *,
2956 			      unsigned int, char *, unsigned int);
2957 static int comp_set_modify_field_id(struct context *, const struct token *,
2958 			      unsigned int, char *, unsigned int);
2959 static int comp_pattern_template_id(struct context *, const struct token *,
2960 				    unsigned int, char *, unsigned int);
2961 static int comp_actions_template_id(struct context *, const struct token *,
2962 				    unsigned int, char *, unsigned int);
2963 static int comp_table_id(struct context *, const struct token *,
2964 			 unsigned int, char *, unsigned int);
2965 static int comp_queue_id(struct context *, const struct token *,
2966 			 unsigned int, char *, unsigned int);
2967 static int comp_meter_color(struct context *, const struct token *,
2968 			    unsigned int, char *, unsigned int);
2969 static int comp_insertion_table_type(struct context *, const struct token *,
2970 				     unsigned int, char *, unsigned int);
2971 static int comp_hash_table_type(struct context *, const struct token *,
2972 				unsigned int, char *, unsigned int);
2973 static int
2974 comp_quota_state_name(struct context *ctx, const struct token *token,
2975 		      unsigned int ent, char *buf, unsigned int size);
2976 static int
2977 comp_quota_mode_name(struct context *ctx, const struct token *token,
2978 		     unsigned int ent, char *buf, unsigned int size);
2979 static int
2980 comp_quota_update_name(struct context *ctx, const struct token *token,
2981 		       unsigned int ent, char *buf, unsigned int size);
2982 static int
2983 comp_qu_mode_name(struct context *ctx, const struct token *token,
2984 		  unsigned int ent, char *buf, unsigned int size);
2985 static int
2986 comp_set_compare_field_id(struct context *ctx, const struct token *token,
2987 			  unsigned int ent, char *buf, unsigned int size);
2988 static int
2989 comp_set_compare_op(struct context *ctx, const struct token *token,
2990 		    unsigned int ent, char *buf, unsigned int size);
2991 static int
2992 parse_vc_compare_op(struct context *ctx, const struct token *token,
2993 			 const char *str, unsigned int len, void *buf,
2994 			 unsigned int size);
2995 static int
2996 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
2997 			  const char *str, unsigned int len, void *buf,
2998 			  unsigned int size);
2999 static int
3000 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
3001 			     const char *str, unsigned int len, void *buf,
3002 			     unsigned int size);
3003 
3004 struct indlst_conf {
3005 	uint32_t id;
3006 	uint32_t conf_num;
3007 	struct rte_flow_action *actions;
3008 	const void **conf;
3009 	SLIST_ENTRY(indlst_conf) next;
3010 };
3011 
3012 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3013 
3014 /** Token definitions. */
3015 static const struct token token_list[] = {
3016 	/* Special tokens. */
3017 	[ZERO] = {
3018 		.name = "ZERO",
3019 		.help = "null entry, abused as the entry point",
3020 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3021 	},
3022 	[END] = {
3023 		.name = "",
3024 		.type = "RETURN",
3025 		.help = "command may end here",
3026 	},
3027 	[START_SET] = {
3028 		.name = "START_SET",
3029 		.help = "null entry, abused as the entry point for set",
3030 		.next = NEXT(NEXT_ENTRY(SET)),
3031 	},
3032 	[END_SET] = {
3033 		.name = "end_set",
3034 		.type = "RETURN",
3035 		.help = "set command may end here",
3036 	},
3037 	/* Common tokens. */
3038 	[COMMON_INTEGER] = {
3039 		.name = "{int}",
3040 		.type = "INTEGER",
3041 		.help = "integer value",
3042 		.call = parse_int,
3043 		.comp = comp_none,
3044 	},
3045 	[COMMON_UNSIGNED] = {
3046 		.name = "{unsigned}",
3047 		.type = "UNSIGNED",
3048 		.help = "unsigned integer value",
3049 		.call = parse_int,
3050 		.comp = comp_none,
3051 	},
3052 	[COMMON_PREFIX] = {
3053 		.name = "{prefix}",
3054 		.type = "PREFIX",
3055 		.help = "prefix length for bit-mask",
3056 		.call = parse_prefix,
3057 		.comp = comp_none,
3058 	},
3059 	[COMMON_BOOLEAN] = {
3060 		.name = "{boolean}",
3061 		.type = "BOOLEAN",
3062 		.help = "any boolean value",
3063 		.call = parse_boolean,
3064 		.comp = comp_boolean,
3065 	},
3066 	[COMMON_STRING] = {
3067 		.name = "{string}",
3068 		.type = "STRING",
3069 		.help = "fixed string",
3070 		.call = parse_string,
3071 		.comp = comp_none,
3072 	},
3073 	[COMMON_HEX] = {
3074 		.name = "{hex}",
3075 		.type = "HEX",
3076 		.help = "fixed string",
3077 		.call = parse_hex,
3078 	},
3079 	[COMMON_FILE_PATH] = {
3080 		.name = "{file path}",
3081 		.type = "STRING",
3082 		.help = "file path",
3083 		.call = parse_string0,
3084 		.comp = comp_none,
3085 	},
3086 	[COMMON_MAC_ADDR] = {
3087 		.name = "{MAC address}",
3088 		.type = "MAC-48",
3089 		.help = "standard MAC address notation",
3090 		.call = parse_mac_addr,
3091 		.comp = comp_none,
3092 	},
3093 	[COMMON_IPV4_ADDR] = {
3094 		.name = "{IPv4 address}",
3095 		.type = "IPV4 ADDRESS",
3096 		.help = "standard IPv4 address notation",
3097 		.call = parse_ipv4_addr,
3098 		.comp = comp_none,
3099 	},
3100 	[COMMON_IPV6_ADDR] = {
3101 		.name = "{IPv6 address}",
3102 		.type = "IPV6 ADDRESS",
3103 		.help = "standard IPv6 address notation",
3104 		.call = parse_ipv6_addr,
3105 		.comp = comp_none,
3106 	},
3107 	[COMMON_RULE_ID] = {
3108 		.name = "{rule id}",
3109 		.type = "RULE ID",
3110 		.help = "rule identifier",
3111 		.call = parse_int,
3112 		.comp = comp_rule_id,
3113 	},
3114 	[COMMON_PORT_ID] = {
3115 		.name = "{port_id}",
3116 		.type = "PORT ID",
3117 		.help = "port identifier",
3118 		.call = parse_port,
3119 		.comp = comp_port,
3120 	},
3121 	[COMMON_GROUP_ID] = {
3122 		.name = "{group_id}",
3123 		.type = "GROUP ID",
3124 		.help = "group identifier",
3125 		.call = parse_int,
3126 		.comp = comp_none,
3127 	},
3128 	[COMMON_PRIORITY_LEVEL] = {
3129 		.name = "{level}",
3130 		.type = "PRIORITY",
3131 		.help = "priority level",
3132 		.call = parse_int,
3133 		.comp = comp_none,
3134 	},
3135 	[COMMON_INDIRECT_ACTION_ID] = {
3136 		.name = "{indirect_action_id}",
3137 		.type = "INDIRECT_ACTION_ID",
3138 		.help = "indirect action id",
3139 		.call = parse_int,
3140 		.comp = comp_none,
3141 	},
3142 	[COMMON_PROFILE_ID] = {
3143 		.name = "{profile_id}",
3144 		.type = "PROFILE_ID",
3145 		.help = "profile id",
3146 		.call = parse_int,
3147 		.comp = comp_none,
3148 	},
3149 	[COMMON_POLICY_ID] = {
3150 		.name = "{policy_id}",
3151 		.type = "POLICY_ID",
3152 		.help = "policy id",
3153 		.call = parse_int,
3154 		.comp = comp_none,
3155 	},
3156 	[COMMON_FLEX_TOKEN] = {
3157 		.name = "{flex token}",
3158 		.type = "flex token",
3159 		.help = "flex token",
3160 		.call = parse_int,
3161 		.comp = comp_none,
3162 	},
3163 	[COMMON_FLEX_HANDLE] = {
3164 		.name = "{flex handle}",
3165 		.type = "FLEX HANDLE",
3166 		.help = "fill flex item data",
3167 		.call = parse_flex_handle,
3168 		.comp = comp_none,
3169 	},
3170 	[COMMON_PATTERN_TEMPLATE_ID] = {
3171 		.name = "{pattern_template_id}",
3172 		.type = "PATTERN_TEMPLATE_ID",
3173 		.help = "pattern template id",
3174 		.call = parse_int,
3175 		.comp = comp_pattern_template_id,
3176 	},
3177 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3178 		.name = "{actions_template_id}",
3179 		.type = "ACTIONS_TEMPLATE_ID",
3180 		.help = "actions template id",
3181 		.call = parse_int,
3182 		.comp = comp_actions_template_id,
3183 	},
3184 	[COMMON_TABLE_ID] = {
3185 		.name = "{table_id}",
3186 		.type = "TABLE_ID",
3187 		.help = "table id",
3188 		.call = parse_int,
3189 		.comp = comp_table_id,
3190 	},
3191 	[COMMON_QUEUE_ID] = {
3192 		.name = "{queue_id}",
3193 		.type = "QUEUE_ID",
3194 		.help = "queue id",
3195 		.call = parse_int,
3196 		.comp = comp_queue_id,
3197 	},
3198 	/* Top-level command. */
3199 	[FLOW] = {
3200 		.name = "flow",
3201 		.type = "{command} {port_id} [{arg} [...]]",
3202 		.help = "manage ingress/egress flow rules",
3203 		.next = NEXT(NEXT_ENTRY
3204 			     (INFO,
3205 			      CONFIGURE,
3206 			      PATTERN_TEMPLATE,
3207 			      ACTIONS_TEMPLATE,
3208 			      TABLE,
3209 			      FLOW_GROUP,
3210 			      INDIRECT_ACTION,
3211 			      VALIDATE,
3212 			      CREATE,
3213 			      DESTROY,
3214 			      UPDATE,
3215 			      FLUSH,
3216 			      DUMP,
3217 			      LIST,
3218 			      AGED,
3219 			      QUERY,
3220 			      ISOLATE,
3221 			      TUNNEL,
3222 			      FLEX,
3223 			      QUEUE,
3224 			      PUSH,
3225 			      PULL,
3226 			      HASH)),
3227 		.call = parse_init,
3228 	},
3229 	/* Top-level command. */
3230 	[INFO] = {
3231 		.name = "info",
3232 		.help = "get information about flow engine",
3233 		.next = NEXT(NEXT_ENTRY(END),
3234 			     NEXT_ENTRY(COMMON_PORT_ID)),
3235 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3236 		.call = parse_configure,
3237 	},
3238 	/* Top-level command. */
3239 	[CONFIGURE] = {
3240 		.name = "configure",
3241 		.help = "configure flow engine",
3242 		.next = NEXT(next_config_attr,
3243 			     NEXT_ENTRY(COMMON_PORT_ID)),
3244 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3245 		.call = parse_configure,
3246 	},
3247 	/* Configure arguments. */
3248 	[CONFIG_QUEUES_NUMBER] = {
3249 		.name = "queues_number",
3250 		.help = "number of queues",
3251 		.next = NEXT(next_config_attr,
3252 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3253 		.args = ARGS(ARGS_ENTRY(struct buffer,
3254 					args.configure.nb_queue)),
3255 	},
3256 	[CONFIG_QUEUES_SIZE] = {
3257 		.name = "queues_size",
3258 		.help = "number of elements in queues",
3259 		.next = NEXT(next_config_attr,
3260 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3261 		.args = ARGS(ARGS_ENTRY(struct buffer,
3262 					args.configure.queue_attr.size)),
3263 	},
3264 	[CONFIG_COUNTERS_NUMBER] = {
3265 		.name = "counters_number",
3266 		.help = "number of counters",
3267 		.next = NEXT(next_config_attr,
3268 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3269 		.args = ARGS(ARGS_ENTRY(struct buffer,
3270 					args.configure.port_attr.nb_counters)),
3271 	},
3272 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3273 		.name = "aging_counters_number",
3274 		.help = "number of aging objects",
3275 		.next = NEXT(next_config_attr,
3276 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3277 		.args = ARGS(ARGS_ENTRY(struct buffer,
3278 					args.configure.port_attr.nb_aging_objects)),
3279 	},
3280 	[CONFIG_QUOTAS_NUMBER] = {
3281 		.name = "quotas_number",
3282 		.help = "number of quotas",
3283 		.next = NEXT(next_config_attr,
3284 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3285 		.args = ARGS(ARGS_ENTRY(struct buffer,
3286 				     args.configure.port_attr.nb_quotas)),
3287 	},
3288 	[CONFIG_METERS_NUMBER] = {
3289 		.name = "meters_number",
3290 		.help = "number of meters",
3291 		.next = NEXT(next_config_attr,
3292 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3293 		.args = ARGS(ARGS_ENTRY(struct buffer,
3294 					args.configure.port_attr.nb_meters)),
3295 	},
3296 	[CONFIG_CONN_TRACK_NUMBER] = {
3297 		.name = "conn_tracks_number",
3298 		.help = "number of connection trackings",
3299 		.next = NEXT(next_config_attr,
3300 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3301 		.args = ARGS(ARGS_ENTRY(struct buffer,
3302 					args.configure.port_attr.nb_conn_tracks)),
3303 	},
3304 	[CONFIG_FLAGS] = {
3305 		.name = "flags",
3306 		.help = "configuration flags",
3307 		.next = NEXT(next_config_attr,
3308 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3309 		.args = ARGS(ARGS_ENTRY(struct buffer,
3310 					args.configure.port_attr.flags)),
3311 	},
3312 	[CONFIG_HOST_PORT] = {
3313 		.name = "host_port",
3314 		.help = "host port for shared objects",
3315 		.next = NEXT(next_config_attr,
3316 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3317 		.args = ARGS(ARGS_ENTRY(struct buffer,
3318 					args.configure.port_attr.host_port_id)),
3319 	},
3320 	/* Top-level command. */
3321 	[PATTERN_TEMPLATE] = {
3322 		.name = "pattern_template",
3323 		.type = "{command} {port_id} [{arg} [...]]",
3324 		.help = "manage pattern templates",
3325 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3326 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3327 		.call = parse_template,
3328 	},
3329 	/* Sub-level commands. */
3330 	[PATTERN_TEMPLATE_CREATE] = {
3331 		.name = "create",
3332 		.help = "create pattern template",
3333 		.next = NEXT(next_pt_attr),
3334 		.call = parse_template,
3335 	},
3336 	[PATTERN_TEMPLATE_DESTROY] = {
3337 		.name = "destroy",
3338 		.help = "destroy pattern template",
3339 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3340 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3341 		.call = parse_template_destroy,
3342 	},
3343 	/* Pattern template arguments. */
3344 	[PATTERN_TEMPLATE_CREATE_ID] = {
3345 		.name = "pattern_template_id",
3346 		.help = "specify a pattern template id to create",
3347 		.next = NEXT(next_pt_attr,
3348 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3349 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3350 	},
3351 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3352 		.name = "pattern_template",
3353 		.help = "specify a pattern template id to destroy",
3354 		.next = NEXT(next_pt_destroy_attr,
3355 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3356 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3357 					    args.templ_destroy.template_id)),
3358 		.call = parse_template_destroy,
3359 	},
3360 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3361 		.name = "relaxed",
3362 		.help = "is matching relaxed",
3363 		.next = NEXT(next_pt_attr,
3364 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3365 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3366 			     args.vc.attr.reserved, 1)),
3367 	},
3368 	[PATTERN_TEMPLATE_INGRESS] = {
3369 		.name = "ingress",
3370 		.help = "attribute pattern to ingress",
3371 		.next = NEXT(next_pt_attr),
3372 		.call = parse_template,
3373 	},
3374 	[PATTERN_TEMPLATE_EGRESS] = {
3375 		.name = "egress",
3376 		.help = "attribute pattern to egress",
3377 		.next = NEXT(next_pt_attr),
3378 		.call = parse_template,
3379 	},
3380 	[PATTERN_TEMPLATE_TRANSFER] = {
3381 		.name = "transfer",
3382 		.help = "attribute pattern to transfer",
3383 		.next = NEXT(next_pt_attr),
3384 		.call = parse_template,
3385 	},
3386 	[PATTERN_TEMPLATE_SPEC] = {
3387 		.name = "template",
3388 		.help = "specify item to create pattern template",
3389 		.next = NEXT(next_item),
3390 	},
3391 	/* Top-level command. */
3392 	[ACTIONS_TEMPLATE] = {
3393 		.name = "actions_template",
3394 		.type = "{command} {port_id} [{arg} [...]]",
3395 		.help = "manage actions templates",
3396 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3397 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3398 		.call = parse_template,
3399 	},
3400 	/* Sub-level commands. */
3401 	[ACTIONS_TEMPLATE_CREATE] = {
3402 		.name = "create",
3403 		.help = "create actions template",
3404 		.next = NEXT(next_at_attr),
3405 		.call = parse_template,
3406 	},
3407 	[ACTIONS_TEMPLATE_DESTROY] = {
3408 		.name = "destroy",
3409 		.help = "destroy actions template",
3410 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3411 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3412 		.call = parse_template_destroy,
3413 	},
3414 	/* Actions template arguments. */
3415 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3416 		.name = "actions_template_id",
3417 		.help = "specify an actions template id to create",
3418 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3419 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3420 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3421 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3422 	},
3423 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3424 		.name = "actions_template",
3425 		.help = "specify an actions template id to destroy",
3426 		.next = NEXT(next_at_destroy_attr,
3427 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3428 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3429 					    args.templ_destroy.template_id)),
3430 		.call = parse_template_destroy,
3431 	},
3432 	[ACTIONS_TEMPLATE_INGRESS] = {
3433 		.name = "ingress",
3434 		.help = "attribute actions to ingress",
3435 		.next = NEXT(next_at_attr),
3436 		.call = parse_template,
3437 	},
3438 	[ACTIONS_TEMPLATE_EGRESS] = {
3439 		.name = "egress",
3440 		.help = "attribute actions to egress",
3441 		.next = NEXT(next_at_attr),
3442 		.call = parse_template,
3443 	},
3444 	[ACTIONS_TEMPLATE_TRANSFER] = {
3445 		.name = "transfer",
3446 		.help = "attribute actions to transfer",
3447 		.next = NEXT(next_at_attr),
3448 		.call = parse_template,
3449 	},
3450 	[ACTIONS_TEMPLATE_SPEC] = {
3451 		.name = "template",
3452 		.help = "specify action to create actions template",
3453 		.next = NEXT(next_action),
3454 		.call = parse_template,
3455 	},
3456 	[ACTIONS_TEMPLATE_MASK] = {
3457 		.name = "mask",
3458 		.help = "specify action mask to create actions template",
3459 		.next = NEXT(next_action),
3460 		.call = parse_template,
3461 	},
3462 	/* Top-level command. */
3463 	[TABLE] = {
3464 		.name = "template_table",
3465 		.type = "{command} {port_id} [{arg} [...]]",
3466 		.help = "manage template tables",
3467 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3468 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3469 		.call = parse_table,
3470 	},
3471 	/* Sub-level commands. */
3472 	[TABLE_CREATE] = {
3473 		.name = "create",
3474 		.help = "create template table",
3475 		.next = NEXT(next_table_attr),
3476 		.call = parse_table,
3477 	},
3478 	[TABLE_DESTROY] = {
3479 		.name = "destroy",
3480 		.help = "destroy template table",
3481 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3482 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3483 		.call = parse_table_destroy,
3484 	},
3485 	[TABLE_RESIZE] = {
3486 		.name = "resize",
3487 		.help = "resize template table",
3488 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3489 		.call = parse_table
3490 	},
3491 	[TABLE_RESIZE_COMPLETE] = {
3492 		.name = "resize_complete",
3493 		.help = "complete table resize",
3494 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3495 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3496 		.call = parse_table_destroy,
3497 	},
3498 	/* Table  arguments. */
3499 	[TABLE_CREATE_ID] = {
3500 		.name = "table_id",
3501 		.help = "specify table id to create",
3502 		.next = NEXT(next_table_attr,
3503 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3504 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3505 	},
3506 	[TABLE_DESTROY_ID] = {
3507 		.name = "table",
3508 		.help = "table id",
3509 		.next = NEXT(next_table_destroy_attr,
3510 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3511 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3512 					    args.table_destroy.table_id)),
3513 		.call = parse_table_destroy,
3514 	},
3515 	[TABLE_RESIZE_ID] = {
3516 		.name = "table_resize_id",
3517 		.help = "table resize id",
3518 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3519 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3520 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3521 		.call = parse_table
3522 	},
3523 	[TABLE_RESIZE_RULES_NUMBER] = {
3524 		.name = "table_resize_rules_num",
3525 		.help = "table resize rules number",
3526 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3527 		.args = ARGS(ARGS_ENTRY(struct buffer,
3528 					args.table.attr.nb_flows)),
3529 		.call = parse_table
3530 	},
3531 	[TABLE_INSERTION_TYPE] = {
3532 		.name = "insertion_type",
3533 		.help = "specify insertion type",
3534 		.next = NEXT(next_table_attr,
3535 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3536 		.args = ARGS(ARGS_ENTRY(struct buffer,
3537 					args.table.attr.insertion_type)),
3538 	},
3539 	[TABLE_INSERTION_TYPE_NAME] = {
3540 		.name = "insertion_type_name",
3541 		.help = "insertion type name",
3542 		.call = parse_insertion_table_type,
3543 		.comp = comp_insertion_table_type,
3544 	},
3545 	[TABLE_HASH_FUNC] = {
3546 		.name = "hash_func",
3547 		.help = "specify hash calculation function",
3548 		.next = NEXT(next_table_attr,
3549 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3550 		.args = ARGS(ARGS_ENTRY(struct buffer,
3551 					args.table.attr.hash_func)),
3552 	},
3553 	[TABLE_HASH_FUNC_NAME] = {
3554 		.name = "hash_func_name",
3555 		.help = "hash calculation function name",
3556 		.call = parse_hash_table_type,
3557 		.comp = comp_hash_table_type,
3558 	},
3559 	[TABLE_GROUP] = {
3560 		.name = "group",
3561 		.help = "specify a group",
3562 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3563 		.args = ARGS(ARGS_ENTRY(struct buffer,
3564 					args.table.attr.flow_attr.group)),
3565 	},
3566 	[TABLE_PRIORITY] = {
3567 		.name = "priority",
3568 		.help = "specify a priority level",
3569 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3570 		.args = ARGS(ARGS_ENTRY(struct buffer,
3571 					args.table.attr.flow_attr.priority)),
3572 	},
3573 	[TABLE_EGRESS] = {
3574 		.name = "egress",
3575 		.help = "affect rule to egress",
3576 		.next = NEXT(next_table_attr),
3577 		.call = parse_table,
3578 	},
3579 	[TABLE_INGRESS] = {
3580 		.name = "ingress",
3581 		.help = "affect rule to ingress",
3582 		.next = NEXT(next_table_attr),
3583 		.call = parse_table,
3584 	},
3585 	[TABLE_TRANSFER] = {
3586 		.name = "transfer",
3587 		.help = "affect rule to transfer",
3588 		.next = NEXT(next_table_attr),
3589 		.call = parse_table,
3590 	},
3591 	[TABLE_TRANSFER_WIRE_ORIG] = {
3592 		.name = "wire_orig",
3593 		.help = "affect rule direction to transfer",
3594 		.next = NEXT(next_table_attr),
3595 		.call = parse_table,
3596 	},
3597 	[TABLE_TRANSFER_VPORT_ORIG] = {
3598 		.name = "vport_orig",
3599 		.help = "affect rule direction to transfer",
3600 		.next = NEXT(next_table_attr),
3601 		.call = parse_table,
3602 	},
3603 	[TABLE_RESIZABLE] = {
3604 		.name = "resizable",
3605 		.help = "set resizable attribute",
3606 		.next = NEXT(next_table_attr),
3607 		.call = parse_table,
3608 	},
3609 	[TABLE_RULES_NUMBER] = {
3610 		.name = "rules_number",
3611 		.help = "number of rules in table",
3612 		.next = NEXT(next_table_attr,
3613 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3614 		.args = ARGS(ARGS_ENTRY(struct buffer,
3615 					args.table.attr.nb_flows)),
3616 		.call = parse_table,
3617 	},
3618 	[TABLE_PATTERN_TEMPLATE] = {
3619 		.name = "pattern_template",
3620 		.help = "specify pattern template id",
3621 		.next = NEXT(next_table_attr,
3622 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3623 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3624 					    args.table.pat_templ_id)),
3625 		.call = parse_table,
3626 	},
3627 	[TABLE_ACTIONS_TEMPLATE] = {
3628 		.name = "actions_template",
3629 		.help = "specify actions template id",
3630 		.next = NEXT(next_table_attr,
3631 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3632 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3633 					    args.table.act_templ_id)),
3634 		.call = parse_table,
3635 	},
3636 	/* Top-level command. */
3637 	[FLOW_GROUP] = {
3638 		.name = "group",
3639 		.help = "manage flow groups",
3640 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3641 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3642 		.call = parse_group,
3643 	},
3644 	/* Sub-level commands. */
3645 	[GROUP_SET_MISS_ACTIONS] = {
3646 		.name = "set_miss_actions",
3647 		.help = "set group miss actions",
3648 		.next = NEXT(next_action),
3649 		.call = parse_group,
3650 	},
3651 	/* Group arguments */
3652 	[GROUP_ID]	= {
3653 		.name = "group_id",
3654 		.help = "group id",
3655 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3656 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3657 	},
3658 	[GROUP_INGRESS] = {
3659 		.name = "ingress",
3660 		.help = "group ingress attr",
3661 		.next = NEXT(next_group_attr),
3662 		.call = parse_group,
3663 	},
3664 	[GROUP_EGRESS] = {
3665 		.name = "egress",
3666 		.help = "group egress attr",
3667 		.next = NEXT(next_group_attr),
3668 		.call = parse_group,
3669 	},
3670 	[GROUP_TRANSFER] = {
3671 		.name = "transfer",
3672 		.help = "group transfer attr",
3673 		.next = NEXT(next_group_attr),
3674 		.call = parse_group,
3675 	},
3676 	/* Top-level command. */
3677 	[QUEUE] = {
3678 		.name = "queue",
3679 		.help = "queue a flow rule operation",
3680 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3681 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3682 		.call = parse_qo,
3683 	},
3684 	/* Sub-level commands. */
3685 	[QUEUE_CREATE] = {
3686 		.name = "create",
3687 		.help = "create a flow rule",
3688 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3689 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3690 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3691 		.call = parse_qo,
3692 	},
3693 	[QUEUE_DESTROY] = {
3694 		.name = "destroy",
3695 		.help = "destroy a flow rule",
3696 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3697 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3698 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3699 		.call = parse_qo_destroy,
3700 	},
3701 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3702 		.name = "update_resized",
3703 		.help = "update a flow after table resize",
3704 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3705 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3706 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3707 		.call = parse_qo_destroy,
3708 	},
3709 	[QUEUE_UPDATE] = {
3710 		.name = "update",
3711 		.help = "update a flow rule",
3712 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3713 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3714 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3715 		.call = parse_qo,
3716 	},
3717 	[QUEUE_AGED] = {
3718 		.name = "aged",
3719 		.help = "list and destroy aged flows",
3720 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3721 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3722 		.call = parse_aged,
3723 	},
3724 	[QUEUE_INDIRECT_ACTION] = {
3725 		.name = "indirect_action",
3726 		.help = "queue indirect actions",
3727 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3728 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3729 		.call = parse_qia,
3730 	},
3731 	/* Queue  arguments. */
3732 	[QUEUE_TEMPLATE_TABLE] = {
3733 		.name = "template_table",
3734 		.help = "specify table id",
3735 		.next = NEXT(next_async_insert_subcmd,
3736 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3737 		.args = ARGS(ARGS_ENTRY(struct buffer,
3738 					args.vc.table_id)),
3739 		.call = parse_qo,
3740 	},
3741 	[QUEUE_PATTERN_TEMPLATE] = {
3742 		.name = "pattern_template",
3743 		.help = "specify pattern template index",
3744 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3745 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3746 		.args = ARGS(ARGS_ENTRY(struct buffer,
3747 					args.vc.pat_templ_id)),
3748 		.call = parse_qo,
3749 	},
3750 	[QUEUE_ACTIONS_TEMPLATE] = {
3751 		.name = "actions_template",
3752 		.help = "specify actions template index",
3753 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3754 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3755 		.args = ARGS(ARGS_ENTRY(struct buffer,
3756 					args.vc.act_templ_id)),
3757 		.call = parse_qo,
3758 	},
3759 	[QUEUE_RULE_ID] = {
3760 		.name = "rule_index",
3761 		.help = "specify flow rule index",
3762 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3763 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3764 		.args = ARGS(ARGS_ENTRY(struct buffer,
3765 					args.vc.rule_id)),
3766 		.call = parse_qo,
3767 	},
3768 	[QUEUE_CREATE_POSTPONE] = {
3769 		.name = "postpone",
3770 		.help = "postpone create operation",
3771 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3772 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3773 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3774 		.call = parse_qo,
3775 	},
3776 	[QUEUE_DESTROY_POSTPONE] = {
3777 		.name = "postpone",
3778 		.help = "postpone destroy operation",
3779 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3780 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3781 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3782 		.call = parse_qo_destroy,
3783 	},
3784 	[QUEUE_DESTROY_ID] = {
3785 		.name = "rule",
3786 		.help = "specify rule id to destroy",
3787 		.next = NEXT(next_queue_destroy_attr,
3788 			NEXT_ENTRY(COMMON_UNSIGNED)),
3789 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3790 					    args.destroy.rule)),
3791 		.call = parse_qo_destroy,
3792 	},
3793 	[QUEUE_UPDATE_ID] = {
3794 		.name = "rule",
3795 		.help = "specify rule id to update",
3796 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3797 			NEXT_ENTRY(COMMON_UNSIGNED)),
3798 		.args = ARGS(ARGS_ENTRY(struct buffer,
3799 				     args.vc.rule_id)),
3800 		.call = parse_qo,
3801 	},
3802 	/* Queue indirect action arguments */
3803 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3804 		.name = "create",
3805 		.help = "create indirect action",
3806 		.next = NEXT(next_qia_create_attr),
3807 		.call = parse_qia,
3808 	},
3809 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3810 		.name = "update",
3811 		.help = "update indirect action",
3812 		.next = NEXT(next_qia_update_attr,
3813 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3814 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3815 		.call = parse_qia,
3816 	},
3817 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3818 		.name = "destroy",
3819 		.help = "destroy indirect action",
3820 		.next = NEXT(next_qia_destroy_attr),
3821 		.call = parse_qia_destroy,
3822 	},
3823 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3824 		.name = "query",
3825 		.help = "query indirect action",
3826 		.next = NEXT(next_qia_query_attr,
3827 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3828 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3829 		.call = parse_qia,
3830 	},
3831 	/* Indirect action destroy arguments. */
3832 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3833 		.name = "postpone",
3834 		.help = "postpone destroy operation",
3835 		.next = NEXT(next_qia_destroy_attr,
3836 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3837 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3838 	},
3839 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3840 		.name = "action_id",
3841 		.help = "specify a indirect action id to destroy",
3842 		.next = NEXT(next_qia_destroy_attr,
3843 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3844 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3845 					    args.ia_destroy.action_id)),
3846 		.call = parse_qia_destroy,
3847 	},
3848 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3849 		.name = "query_update",
3850 		.help = "indirect query [and|or] update action",
3851 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3852 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3853 		.call = parse_qia
3854 	},
3855 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3856 		.name = "mode",
3857 		.help = "indirect query [and|or] update action",
3858 		.next = NEXT(next_qia_qu_attr,
3859 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3860 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3861 		.call = parse_qia
3862 	},
3863 	/* Indirect action update arguments. */
3864 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3865 		.name = "postpone",
3866 		.help = "postpone update operation",
3867 		.next = NEXT(next_qia_update_attr,
3868 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3869 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3870 	},
3871 	/* Indirect action update arguments. */
3872 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3873 		.name = "postpone",
3874 		.help = "postpone query operation",
3875 		.next = NEXT(next_qia_query_attr,
3876 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3877 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3878 	},
3879 	/* Indirect action create arguments. */
3880 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3881 		.name = "action_id",
3882 		.help = "specify a indirect action id to create",
3883 		.next = NEXT(next_qia_create_attr,
3884 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3885 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3886 	},
3887 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3888 		.name = "ingress",
3889 		.help = "affect rule to ingress",
3890 		.next = NEXT(next_qia_create_attr),
3891 		.call = parse_qia,
3892 	},
3893 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3894 		.name = "egress",
3895 		.help = "affect rule to egress",
3896 		.next = NEXT(next_qia_create_attr),
3897 		.call = parse_qia,
3898 	},
3899 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3900 		.name = "transfer",
3901 		.help = "affect rule to transfer",
3902 		.next = NEXT(next_qia_create_attr),
3903 		.call = parse_qia,
3904 	},
3905 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3906 		.name = "postpone",
3907 		.help = "postpone create operation",
3908 		.next = NEXT(next_qia_create_attr,
3909 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3910 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3911 	},
3912 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3913 		.name = "action",
3914 		.help = "specify action to create indirect handle",
3915 		.next = NEXT(next_action),
3916 	},
3917 	[QUEUE_INDIRECT_ACTION_LIST] = {
3918 		.name = "list",
3919 		.help = "specify actions for indirect handle list",
3920 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3921 		.call = parse_qia,
3922 	},
3923 	/* Top-level command. */
3924 	[PUSH] = {
3925 		.name = "push",
3926 		.help = "push enqueued operations",
3927 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3928 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3929 		.call = parse_push,
3930 	},
3931 	/* Sub-level commands. */
3932 	[PUSH_QUEUE] = {
3933 		.name = "queue",
3934 		.help = "specify queue id",
3935 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3936 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3937 	},
3938 	/* Top-level command. */
3939 	[PULL] = {
3940 		.name = "pull",
3941 		.help = "pull flow operations results",
3942 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3943 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3944 		.call = parse_pull,
3945 	},
3946 	/* Sub-level commands. */
3947 	[PULL_QUEUE] = {
3948 		.name = "queue",
3949 		.help = "specify queue id",
3950 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3951 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3952 	},
3953 	/* Top-level command. */
3954 	[HASH] = {
3955 		.name = "hash",
3956 		.help = "calculate hash for a given pattern in a given template table",
3957 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3958 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3959 		.call = parse_hash,
3960 	},
3961 	/* Sub-level commands. */
3962 	[HASH_CALC_TABLE] = {
3963 		.name = "template_table",
3964 		.help = "specify table id",
3965 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3966 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3967 		.args = ARGS(ARGS_ENTRY(struct buffer,
3968 					args.vc.table_id)),
3969 		.call = parse_hash,
3970 	},
3971 	[HASH_CALC_ENCAP] = {
3972 		.name = "encap",
3973 		.help = "calculates encap hash",
3974 		.next = NEXT(next_hash_encap_dest_subcmd),
3975 		.call = parse_hash,
3976 	},
3977 	[HASH_CALC_PATTERN_INDEX] = {
3978 		.name = "pattern_template",
3979 		.help = "specify pattern template id",
3980 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3981 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3982 		.args = ARGS(ARGS_ENTRY(struct buffer,
3983 					args.vc.pat_templ_id)),
3984 		.call = parse_hash,
3985 	},
3986 	[ENCAP_HASH_FIELD_SRC_PORT] = {
3987 		.name = "hash_field_sport",
3988 		.help = "the encap hash field is src port",
3989 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3990 		.call = parse_hash,
3991 	},
3992 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
3993 		.name = "hash_field_flow_id",
3994 		.help = "the encap hash field is NVGRE flow id",
3995 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3996 		.call = parse_hash,
3997 	},
3998 	/* Top-level command. */
3999 	[INDIRECT_ACTION] = {
4000 		.name = "indirect_action",
4001 		.type = "{command} {port_id} [{arg} [...]]",
4002 		.help = "manage indirect actions",
4003 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4004 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4005 		.call = parse_ia,
4006 	},
4007 	/* Sub-level commands. */
4008 	[INDIRECT_ACTION_CREATE] = {
4009 		.name = "create",
4010 		.help = "create indirect action",
4011 		.next = NEXT(next_ia_create_attr),
4012 		.call = parse_ia,
4013 	},
4014 	[INDIRECT_ACTION_UPDATE] = {
4015 		.name = "update",
4016 		.help = "update indirect action",
4017 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4018 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4019 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4020 		.call = parse_ia,
4021 	},
4022 	[INDIRECT_ACTION_DESTROY] = {
4023 		.name = "destroy",
4024 		.help = "destroy indirect action",
4025 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4026 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4027 		.call = parse_ia_destroy,
4028 	},
4029 	[INDIRECT_ACTION_QUERY] = {
4030 		.name = "query",
4031 		.help = "query indirect action",
4032 		.next = NEXT(NEXT_ENTRY(END),
4033 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4034 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4035 		.call = parse_ia,
4036 	},
4037 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4038 		.name = "query_update",
4039 		.help = "query [and|or] update",
4040 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4041 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4042 		.call = parse_ia
4043 	},
4044 	[INDIRECT_ACTION_QU_MODE] = {
4045 		.name = "mode",
4046 		.help = "query_update mode",
4047 		.next = NEXT(next_ia_qu_attr,
4048 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4049 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4050 		.call = parse_ia,
4051 	},
4052 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4053 		.name = "mode_name",
4054 		.help = "query-update mode name",
4055 		.call = parse_qu_mode_name,
4056 		.comp = comp_qu_mode_name,
4057 	},
4058 	[VALIDATE] = {
4059 		.name = "validate",
4060 		.help = "check whether a flow rule can be created",
4061 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4062 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4063 		.call = parse_vc,
4064 	},
4065 	[CREATE] = {
4066 		.name = "create",
4067 		.help = "create a flow rule",
4068 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4069 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4070 		.call = parse_vc,
4071 	},
4072 	[DESTROY] = {
4073 		.name = "destroy",
4074 		.help = "destroy specific flow rules",
4075 		.next = NEXT(next_destroy_attr,
4076 			     NEXT_ENTRY(COMMON_PORT_ID)),
4077 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4078 		.call = parse_destroy,
4079 	},
4080 	[UPDATE] = {
4081 		.name = "update",
4082 		.help = "update a flow rule with new actions",
4083 		.next = NEXT(NEXT_ENTRY(VC_IS_USER_ID, END),
4084 			     NEXT_ENTRY(ACTIONS),
4085 			     NEXT_ENTRY(COMMON_RULE_ID),
4086 			     NEXT_ENTRY(COMMON_PORT_ID)),
4087 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.rule_id),
4088 			     ARGS_ENTRY(struct buffer, port)),
4089 		.call = parse_vc,
4090 	},
4091 	[FLUSH] = {
4092 		.name = "flush",
4093 		.help = "destroy all flow rules",
4094 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4095 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4096 		.call = parse_flush,
4097 	},
4098 	[DUMP] = {
4099 		.name = "dump",
4100 		.help = "dump single/all flow rules to file",
4101 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4102 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4103 		.call = parse_dump,
4104 	},
4105 	[QUERY] = {
4106 		.name = "query",
4107 		.help = "query an existing flow rule",
4108 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4109 			     NEXT_ENTRY(COMMON_RULE_ID),
4110 			     NEXT_ENTRY(COMMON_PORT_ID)),
4111 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4112 			     ARGS_ENTRY(struct buffer, args.query.rule),
4113 			     ARGS_ENTRY(struct buffer, port)),
4114 		.call = parse_query,
4115 	},
4116 	[LIST] = {
4117 		.name = "list",
4118 		.help = "list existing flow rules",
4119 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4120 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4121 		.call = parse_list,
4122 	},
4123 	[AGED] = {
4124 		.name = "aged",
4125 		.help = "list and destroy aged flows",
4126 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4127 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4128 		.call = parse_aged,
4129 	},
4130 	[ISOLATE] = {
4131 		.name = "isolate",
4132 		.help = "restrict ingress traffic to the defined flow rules",
4133 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4134 			     NEXT_ENTRY(COMMON_PORT_ID)),
4135 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4136 			     ARGS_ENTRY(struct buffer, port)),
4137 		.call = parse_isolate,
4138 	},
4139 	[FLEX] = {
4140 		.name = "flex_item",
4141 		.help = "flex item API",
4142 		.next = NEXT(next_flex_item),
4143 		.call = parse_flex,
4144 	},
4145 	[FLEX_ITEM_INIT] = {
4146 		.name = "init",
4147 		.help = "flex item init",
4148 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4149 			     ARGS_ENTRY(struct buffer, port)),
4150 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4151 			     NEXT_ENTRY(COMMON_PORT_ID)),
4152 		.call = parse_flex
4153 	},
4154 	[FLEX_ITEM_CREATE] = {
4155 		.name = "create",
4156 		.help = "flex item create",
4157 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4158 			     ARGS_ENTRY(struct buffer, args.flex.token),
4159 			     ARGS_ENTRY(struct buffer, port)),
4160 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4161 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4162 			     NEXT_ENTRY(COMMON_PORT_ID)),
4163 		.call = parse_flex
4164 	},
4165 	[FLEX_ITEM_DESTROY] = {
4166 		.name = "destroy",
4167 		.help = "flex item destroy",
4168 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4169 			     ARGS_ENTRY(struct buffer, port)),
4170 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4171 			     NEXT_ENTRY(COMMON_PORT_ID)),
4172 		.call = parse_flex
4173 	},
4174 	[TUNNEL] = {
4175 		.name = "tunnel",
4176 		.help = "new tunnel API",
4177 		.next = NEXT(NEXT_ENTRY
4178 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4179 		.call = parse_tunnel,
4180 	},
4181 	/* Tunnel arguments. */
4182 	[TUNNEL_CREATE] = {
4183 		.name = "create",
4184 		.help = "create new tunnel object",
4185 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4186 			     NEXT_ENTRY(COMMON_PORT_ID)),
4187 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4188 		.call = parse_tunnel,
4189 	},
4190 	[TUNNEL_CREATE_TYPE] = {
4191 		.name = "type",
4192 		.help = "create new tunnel",
4193 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4194 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4195 		.call = parse_tunnel,
4196 	},
4197 	[TUNNEL_DESTROY] = {
4198 		.name = "destroy",
4199 		.help = "destroy tunnel",
4200 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4201 			     NEXT_ENTRY(COMMON_PORT_ID)),
4202 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4203 		.call = parse_tunnel,
4204 	},
4205 	[TUNNEL_DESTROY_ID] = {
4206 		.name = "id",
4207 		.help = "tunnel identifier to destroy",
4208 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4209 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4210 		.call = parse_tunnel,
4211 	},
4212 	[TUNNEL_LIST] = {
4213 		.name = "list",
4214 		.help = "list existing tunnels",
4215 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4216 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4217 		.call = parse_tunnel,
4218 	},
4219 	/* Destroy arguments. */
4220 	[DESTROY_RULE] = {
4221 		.name = "rule",
4222 		.help = "specify a rule identifier",
4223 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4224 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4225 		.call = parse_destroy,
4226 	},
4227 	[DESTROY_IS_USER_ID] = {
4228 		.name = "user_id",
4229 		.help = "rule identifier is user-id",
4230 		.next = NEXT(next_destroy_attr),
4231 		.call = parse_destroy,
4232 	},
4233 	/* Dump arguments. */
4234 	[DUMP_ALL] = {
4235 		.name = "all",
4236 		.help = "dump all",
4237 		.next = NEXT(next_dump_attr),
4238 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4239 		.call = parse_dump,
4240 	},
4241 	[DUMP_ONE] = {
4242 		.name = "rule",
4243 		.help = "dump one rule",
4244 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4245 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4246 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4247 		.call = parse_dump,
4248 	},
4249 	[DUMP_IS_USER_ID] = {
4250 		.name = "user_id",
4251 		.help = "rule identifier is user-id",
4252 		.next = NEXT(next_dump_subcmd),
4253 		.call = parse_dump,
4254 	},
4255 	/* Query arguments. */
4256 	[QUERY_ACTION] = {
4257 		.name = "{action}",
4258 		.type = "ACTION",
4259 		.help = "action to query, must be part of the rule",
4260 		.call = parse_action,
4261 		.comp = comp_action,
4262 	},
4263 	[QUERY_IS_USER_ID] = {
4264 		.name = "user_id",
4265 		.help = "rule identifier is user-id",
4266 		.next = NEXT(next_query_attr),
4267 		.call = parse_query,
4268 	},
4269 	/* List arguments. */
4270 	[LIST_GROUP] = {
4271 		.name = "group",
4272 		.help = "specify a group",
4273 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4274 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4275 		.call = parse_list,
4276 	},
4277 	[AGED_DESTROY] = {
4278 		.name = "destroy",
4279 		.help = "specify aged flows need be destroyed",
4280 		.call = parse_aged,
4281 		.comp = comp_none,
4282 	},
4283 	/* Validate/create attributes. */
4284 	[VC_GROUP] = {
4285 		.name = "group",
4286 		.help = "specify a group",
4287 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4288 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4289 		.call = parse_vc,
4290 	},
4291 	[VC_PRIORITY] = {
4292 		.name = "priority",
4293 		.help = "specify a priority level",
4294 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4295 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4296 		.call = parse_vc,
4297 	},
4298 	[VC_INGRESS] = {
4299 		.name = "ingress",
4300 		.help = "affect rule to ingress",
4301 		.next = NEXT(next_vc_attr),
4302 		.call = parse_vc,
4303 	},
4304 	[VC_EGRESS] = {
4305 		.name = "egress",
4306 		.help = "affect rule to egress",
4307 		.next = NEXT(next_vc_attr),
4308 		.call = parse_vc,
4309 	},
4310 	[VC_TRANSFER] = {
4311 		.name = "transfer",
4312 		.help = "apply rule directly to endpoints found in pattern",
4313 		.next = NEXT(next_vc_attr),
4314 		.call = parse_vc,
4315 	},
4316 	[VC_TUNNEL_SET] = {
4317 		.name = "tunnel_set",
4318 		.help = "tunnel steer rule",
4319 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4320 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4321 		.call = parse_vc,
4322 	},
4323 	[VC_TUNNEL_MATCH] = {
4324 		.name = "tunnel_match",
4325 		.help = "tunnel match rule",
4326 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4327 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4328 		.call = parse_vc,
4329 	},
4330 	[VC_USER_ID] = {
4331 		.name = "user_id",
4332 		.help = "specify a user id to create",
4333 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4334 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4335 		.call = parse_vc,
4336 	},
4337 	[VC_IS_USER_ID] = {
4338 		.name = "user_id",
4339 		.help = "rule identifier is user-id",
4340 		.call = parse_vc,
4341 	},
4342 	/* Validate/create pattern. */
4343 	[ITEM_PATTERN] = {
4344 		.name = "pattern",
4345 		.help = "submit a list of pattern items",
4346 		.next = NEXT(next_item),
4347 		.call = parse_vc,
4348 	},
4349 	[ITEM_PARAM_IS] = {
4350 		.name = "is",
4351 		.help = "match value perfectly (with full bit-mask)",
4352 		.call = parse_vc_spec,
4353 	},
4354 	[ITEM_PARAM_SPEC] = {
4355 		.name = "spec",
4356 		.help = "match value according to configured bit-mask",
4357 		.call = parse_vc_spec,
4358 	},
4359 	[ITEM_PARAM_LAST] = {
4360 		.name = "last",
4361 		.help = "specify upper bound to establish a range",
4362 		.call = parse_vc_spec,
4363 	},
4364 	[ITEM_PARAM_MASK] = {
4365 		.name = "mask",
4366 		.help = "specify bit-mask with relevant bits set to one",
4367 		.call = parse_vc_spec,
4368 	},
4369 	[ITEM_PARAM_PREFIX] = {
4370 		.name = "prefix",
4371 		.help = "generate bit-mask from a prefix length",
4372 		.call = parse_vc_spec,
4373 	},
4374 	[ITEM_NEXT] = {
4375 		.name = "/",
4376 		.help = "specify next pattern item",
4377 		.next = NEXT(next_item),
4378 	},
4379 	[ITEM_END] = {
4380 		.name = "end",
4381 		.help = "end list of pattern items",
4382 		.priv = PRIV_ITEM(END, 0),
4383 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4384 		.call = parse_vc,
4385 	},
4386 	[ITEM_VOID] = {
4387 		.name = "void",
4388 		.help = "no-op pattern item",
4389 		.priv = PRIV_ITEM(VOID, 0),
4390 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4391 		.call = parse_vc,
4392 	},
4393 	[ITEM_INVERT] = {
4394 		.name = "invert",
4395 		.help = "perform actions when pattern does not match",
4396 		.priv = PRIV_ITEM(INVERT, 0),
4397 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4398 		.call = parse_vc,
4399 	},
4400 	[ITEM_ANY] = {
4401 		.name = "any",
4402 		.help = "match any protocol for the current layer",
4403 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4404 		.next = NEXT(item_any),
4405 		.call = parse_vc,
4406 	},
4407 	[ITEM_ANY_NUM] = {
4408 		.name = "num",
4409 		.help = "number of layers covered",
4410 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4411 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4412 	},
4413 	[ITEM_PORT_ID] = {
4414 		.name = "port_id",
4415 		.help = "match traffic from/to a given DPDK port ID",
4416 		.priv = PRIV_ITEM(PORT_ID,
4417 				  sizeof(struct rte_flow_item_port_id)),
4418 		.next = NEXT(item_port_id),
4419 		.call = parse_vc,
4420 	},
4421 	[ITEM_PORT_ID_ID] = {
4422 		.name = "id",
4423 		.help = "DPDK port ID",
4424 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4425 			     item_param),
4426 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4427 	},
4428 	[ITEM_MARK] = {
4429 		.name = "mark",
4430 		.help = "match traffic against value set in previously matched rule",
4431 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4432 		.next = NEXT(item_mark),
4433 		.call = parse_vc,
4434 	},
4435 	[ITEM_MARK_ID] = {
4436 		.name = "id",
4437 		.help = "Integer value to match against",
4438 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4439 			     item_param),
4440 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4441 	},
4442 	[ITEM_RAW] = {
4443 		.name = "raw",
4444 		.help = "match an arbitrary byte string",
4445 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4446 		.next = NEXT(item_raw),
4447 		.call = parse_vc,
4448 	},
4449 	[ITEM_RAW_RELATIVE] = {
4450 		.name = "relative",
4451 		.help = "look for pattern after the previous item",
4452 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4453 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4454 					   relative, 1)),
4455 	},
4456 	[ITEM_RAW_SEARCH] = {
4457 		.name = "search",
4458 		.help = "search pattern from offset (see also limit)",
4459 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4460 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4461 					   search, 1)),
4462 	},
4463 	[ITEM_RAW_OFFSET] = {
4464 		.name = "offset",
4465 		.help = "absolute or relative offset for pattern",
4466 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4467 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4468 	},
4469 	[ITEM_RAW_LIMIT] = {
4470 		.name = "limit",
4471 		.help = "search area limit for start of pattern",
4472 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4473 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4474 	},
4475 	[ITEM_RAW_PATTERN] = {
4476 		.name = "pattern",
4477 		.help = "byte string to look for",
4478 		.next = NEXT(item_raw,
4479 			     NEXT_ENTRY(COMMON_STRING),
4480 			     NEXT_ENTRY(ITEM_PARAM_IS,
4481 					ITEM_PARAM_SPEC,
4482 					ITEM_PARAM_MASK)),
4483 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4484 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4485 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4486 					    ITEM_RAW_PATTERN_SIZE)),
4487 	},
4488 	[ITEM_RAW_PATTERN_HEX] = {
4489 		.name = "pattern_hex",
4490 		.help = "hex string to look for",
4491 		.next = NEXT(item_raw,
4492 			     NEXT_ENTRY(COMMON_HEX),
4493 			     NEXT_ENTRY(ITEM_PARAM_IS,
4494 					ITEM_PARAM_SPEC,
4495 					ITEM_PARAM_MASK)),
4496 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4497 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4498 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4499 					    ITEM_RAW_PATTERN_SIZE)),
4500 	},
4501 	[ITEM_ETH] = {
4502 		.name = "eth",
4503 		.help = "match Ethernet header",
4504 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4505 		.next = NEXT(item_eth),
4506 		.call = parse_vc,
4507 	},
4508 	[ITEM_ETH_DST] = {
4509 		.name = "dst",
4510 		.help = "destination MAC",
4511 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4512 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4513 	},
4514 	[ITEM_ETH_SRC] = {
4515 		.name = "src",
4516 		.help = "source MAC",
4517 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4518 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4519 	},
4520 	[ITEM_ETH_TYPE] = {
4521 		.name = "type",
4522 		.help = "EtherType",
4523 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4524 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4525 	},
4526 	[ITEM_ETH_HAS_VLAN] = {
4527 		.name = "has_vlan",
4528 		.help = "packet header contains VLAN",
4529 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4530 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4531 					   has_vlan, 1)),
4532 	},
4533 	[ITEM_VLAN] = {
4534 		.name = "vlan",
4535 		.help = "match 802.1Q/ad VLAN tag",
4536 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4537 		.next = NEXT(item_vlan),
4538 		.call = parse_vc,
4539 	},
4540 	[ITEM_VLAN_TCI] = {
4541 		.name = "tci",
4542 		.help = "tag control information",
4543 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4544 			     item_param),
4545 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4546 	},
4547 	[ITEM_VLAN_PCP] = {
4548 		.name = "pcp",
4549 		.help = "priority code point",
4550 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4551 			     item_param),
4552 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4553 						  hdr.vlan_tci, "\xe0\x00")),
4554 	},
4555 	[ITEM_VLAN_DEI] = {
4556 		.name = "dei",
4557 		.help = "drop eligible indicator",
4558 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4559 			     item_param),
4560 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4561 						  hdr.vlan_tci, "\x10\x00")),
4562 	},
4563 	[ITEM_VLAN_VID] = {
4564 		.name = "vid",
4565 		.help = "VLAN identifier",
4566 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4567 			     item_param),
4568 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4569 						  hdr.vlan_tci, "\x0f\xff")),
4570 	},
4571 	[ITEM_VLAN_INNER_TYPE] = {
4572 		.name = "inner_type",
4573 		.help = "inner EtherType",
4574 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4575 			     item_param),
4576 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4577 					     hdr.eth_proto)),
4578 	},
4579 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4580 		.name = "has_more_vlan",
4581 		.help = "packet header contains another VLAN",
4582 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4583 			     item_param),
4584 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4585 					   has_more_vlan, 1)),
4586 	},
4587 	[ITEM_IPV4] = {
4588 		.name = "ipv4",
4589 		.help = "match IPv4 header",
4590 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4591 		.next = NEXT(item_ipv4),
4592 		.call = parse_vc,
4593 	},
4594 	[ITEM_IPV4_VER_IHL] = {
4595 		.name = "version_ihl",
4596 		.help = "match header length",
4597 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4598 			     item_param),
4599 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4600 				     hdr.version_ihl)),
4601 	},
4602 	[ITEM_IPV4_TOS] = {
4603 		.name = "tos",
4604 		.help = "type of service",
4605 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4606 			     item_param),
4607 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4608 					     hdr.type_of_service)),
4609 	},
4610 	[ITEM_IPV4_LENGTH] = {
4611 		.name = "length",
4612 		.help = "total length",
4613 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4614 			     item_param),
4615 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4616 					     hdr.total_length)),
4617 	},
4618 	[ITEM_IPV4_ID] = {
4619 		.name = "packet_id",
4620 		.help = "fragment packet id",
4621 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4622 			     item_param),
4623 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4624 					     hdr.packet_id)),
4625 	},
4626 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4627 		.name = "fragment_offset",
4628 		.help = "fragmentation flags and fragment offset",
4629 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4630 			     item_param),
4631 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4632 					     hdr.fragment_offset)),
4633 	},
4634 	[ITEM_IPV4_TTL] = {
4635 		.name = "ttl",
4636 		.help = "time to live",
4637 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4638 			     item_param),
4639 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4640 					     hdr.time_to_live)),
4641 	},
4642 	[ITEM_IPV4_PROTO] = {
4643 		.name = "proto",
4644 		.help = "next protocol ID",
4645 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4646 			     item_param),
4647 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4648 					     hdr.next_proto_id)),
4649 	},
4650 	[ITEM_IPV4_SRC] = {
4651 		.name = "src",
4652 		.help = "source address",
4653 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4654 			     item_param),
4655 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4656 					     hdr.src_addr)),
4657 	},
4658 	[ITEM_IPV4_DST] = {
4659 		.name = "dst",
4660 		.help = "destination address",
4661 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4662 			     item_param),
4663 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4664 					     hdr.dst_addr)),
4665 	},
4666 	[ITEM_IPV6] = {
4667 		.name = "ipv6",
4668 		.help = "match IPv6 header",
4669 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4670 		.next = NEXT(item_ipv6),
4671 		.call = parse_vc,
4672 	},
4673 	[ITEM_IPV6_TC] = {
4674 		.name = "tc",
4675 		.help = "traffic class",
4676 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4677 			     item_param),
4678 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4679 						  hdr.vtc_flow,
4680 						  "\x0f\xf0\x00\x00")),
4681 	},
4682 	[ITEM_IPV6_FLOW] = {
4683 		.name = "flow",
4684 		.help = "flow label",
4685 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4686 			     item_param),
4687 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4688 						  hdr.vtc_flow,
4689 						  "\x00\x0f\xff\xff")),
4690 	},
4691 	[ITEM_IPV6_LEN] = {
4692 		.name = "length",
4693 		.help = "payload length",
4694 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4695 			     item_param),
4696 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4697 					     hdr.payload_len)),
4698 	},
4699 	[ITEM_IPV6_PROTO] = {
4700 		.name = "proto",
4701 		.help = "protocol (next header)",
4702 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4703 			     item_param),
4704 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4705 					     hdr.proto)),
4706 	},
4707 	[ITEM_IPV6_HOP] = {
4708 		.name = "hop",
4709 		.help = "hop limit",
4710 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4711 			     item_param),
4712 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4713 					     hdr.hop_limits)),
4714 	},
4715 	[ITEM_IPV6_SRC] = {
4716 		.name = "src",
4717 		.help = "source address",
4718 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4719 			     item_param),
4720 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4721 					     hdr.src_addr)),
4722 	},
4723 	[ITEM_IPV6_DST] = {
4724 		.name = "dst",
4725 		.help = "destination address",
4726 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4727 			     item_param),
4728 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4729 					     hdr.dst_addr)),
4730 	},
4731 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4732 		.name = "has_frag_ext",
4733 		.help = "fragment packet attribute",
4734 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4735 			     item_param),
4736 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4737 					   has_frag_ext, 1)),
4738 	},
4739 	[ITEM_IPV6_ROUTING_EXT] = {
4740 		.name = "ipv6_routing_ext",
4741 		.help = "match IPv6 routing extension header",
4742 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4743 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4744 		.next = NEXT(item_ipv6_routing_ext),
4745 		.call = parse_vc,
4746 	},
4747 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4748 		.name = "ext_type",
4749 		.help = "match IPv6 routing extension header type",
4750 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4751 			     item_param),
4752 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4753 					     hdr.type)),
4754 	},
4755 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4756 		.name = "ext_next_hdr",
4757 		.help = "match IPv6 routing extension header next header type",
4758 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4759 			     item_param),
4760 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4761 					     hdr.next_hdr)),
4762 	},
4763 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4764 		.name = "ext_seg_left",
4765 		.help = "match IPv6 routing extension header segment left",
4766 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4767 			     item_param),
4768 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4769 					     hdr.segments_left)),
4770 	},
4771 	[ITEM_ICMP] = {
4772 		.name = "icmp",
4773 		.help = "match ICMP header",
4774 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4775 		.next = NEXT(item_icmp),
4776 		.call = parse_vc,
4777 	},
4778 	[ITEM_ICMP_TYPE] = {
4779 		.name = "type",
4780 		.help = "ICMP packet type",
4781 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4782 			     item_param),
4783 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4784 					     hdr.icmp_type)),
4785 	},
4786 	[ITEM_ICMP_CODE] = {
4787 		.name = "code",
4788 		.help = "ICMP packet code",
4789 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4790 			     item_param),
4791 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4792 					     hdr.icmp_code)),
4793 	},
4794 	[ITEM_ICMP_IDENT] = {
4795 		.name = "ident",
4796 		.help = "ICMP packet identifier",
4797 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4798 			     item_param),
4799 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4800 					     hdr.icmp_ident)),
4801 	},
4802 	[ITEM_ICMP_SEQ] = {
4803 		.name = "seq",
4804 		.help = "ICMP packet sequence number",
4805 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4806 			     item_param),
4807 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4808 					     hdr.icmp_seq_nb)),
4809 	},
4810 	[ITEM_UDP] = {
4811 		.name = "udp",
4812 		.help = "match UDP header",
4813 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4814 		.next = NEXT(item_udp),
4815 		.call = parse_vc,
4816 	},
4817 	[ITEM_UDP_SRC] = {
4818 		.name = "src",
4819 		.help = "UDP source port",
4820 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4821 			     item_param),
4822 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4823 					     hdr.src_port)),
4824 	},
4825 	[ITEM_UDP_DST] = {
4826 		.name = "dst",
4827 		.help = "UDP destination port",
4828 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4829 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4830 					     hdr.dst_port)),
4831 	},
4832 	[ITEM_TCP] = {
4833 		.name = "tcp",
4834 		.help = "match TCP header",
4835 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4836 		.next = NEXT(item_tcp),
4837 		.call = parse_vc,
4838 	},
4839 	[ITEM_TCP_SRC] = {
4840 		.name = "src",
4841 		.help = "TCP source port",
4842 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4843 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4844 					     hdr.src_port)),
4845 	},
4846 	[ITEM_TCP_DST] = {
4847 		.name = "dst",
4848 		.help = "TCP destination port",
4849 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4850 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4851 					     hdr.dst_port)),
4852 	},
4853 	[ITEM_TCP_FLAGS] = {
4854 		.name = "flags",
4855 		.help = "TCP flags",
4856 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4857 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4858 					     hdr.tcp_flags)),
4859 	},
4860 	[ITEM_SCTP] = {
4861 		.name = "sctp",
4862 		.help = "match SCTP header",
4863 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4864 		.next = NEXT(item_sctp),
4865 		.call = parse_vc,
4866 	},
4867 	[ITEM_SCTP_SRC] = {
4868 		.name = "src",
4869 		.help = "SCTP source port",
4870 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4871 			     item_param),
4872 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4873 					     hdr.src_port)),
4874 	},
4875 	[ITEM_SCTP_DST] = {
4876 		.name = "dst",
4877 		.help = "SCTP destination port",
4878 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4879 			     item_param),
4880 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4881 					     hdr.dst_port)),
4882 	},
4883 	[ITEM_SCTP_TAG] = {
4884 		.name = "tag",
4885 		.help = "validation tag",
4886 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4887 			     item_param),
4888 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4889 					     hdr.tag)),
4890 	},
4891 	[ITEM_SCTP_CKSUM] = {
4892 		.name = "cksum",
4893 		.help = "checksum",
4894 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4895 			     item_param),
4896 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4897 					     hdr.cksum)),
4898 	},
4899 	[ITEM_VXLAN] = {
4900 		.name = "vxlan",
4901 		.help = "match VXLAN header",
4902 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4903 		.next = NEXT(item_vxlan),
4904 		.call = parse_vc,
4905 	},
4906 	[ITEM_VXLAN_VNI] = {
4907 		.name = "vni",
4908 		.help = "VXLAN identifier",
4909 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4910 			     item_param),
4911 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4912 	},
4913 	[ITEM_VXLAN_LAST_RSVD] = {
4914 		.name = "last_rsvd",
4915 		.help = "VXLAN last reserved bits",
4916 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4917 			     item_param),
4918 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4919 					     hdr.rsvd1)),
4920 	},
4921 	[ITEM_E_TAG] = {
4922 		.name = "e_tag",
4923 		.help = "match E-Tag header",
4924 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4925 		.next = NEXT(item_e_tag),
4926 		.call = parse_vc,
4927 	},
4928 	[ITEM_E_TAG_GRP_ECID_B] = {
4929 		.name = "grp_ecid_b",
4930 		.help = "GRP and E-CID base",
4931 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4932 			     item_param),
4933 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4934 						  rsvd_grp_ecid_b,
4935 						  "\x3f\xff")),
4936 	},
4937 	[ITEM_NVGRE] = {
4938 		.name = "nvgre",
4939 		.help = "match NVGRE header",
4940 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4941 		.next = NEXT(item_nvgre),
4942 		.call = parse_vc,
4943 	},
4944 	[ITEM_NVGRE_TNI] = {
4945 		.name = "tni",
4946 		.help = "virtual subnet ID",
4947 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4948 			     item_param),
4949 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4950 	},
4951 	[ITEM_MPLS] = {
4952 		.name = "mpls",
4953 		.help = "match MPLS header",
4954 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4955 		.next = NEXT(item_mpls),
4956 		.call = parse_vc,
4957 	},
4958 	[ITEM_MPLS_LABEL] = {
4959 		.name = "label",
4960 		.help = "MPLS label",
4961 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4962 			     item_param),
4963 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4964 						  label_tc_s,
4965 						  "\xff\xff\xf0")),
4966 	},
4967 	[ITEM_MPLS_TC] = {
4968 		.name = "tc",
4969 		.help = "MPLS Traffic Class",
4970 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4971 			     item_param),
4972 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4973 						  label_tc_s,
4974 						  "\x00\x00\x0e")),
4975 	},
4976 	[ITEM_MPLS_S] = {
4977 		.name = "s",
4978 		.help = "MPLS Bottom-of-Stack",
4979 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4980 			     item_param),
4981 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4982 						  label_tc_s,
4983 						  "\x00\x00\x01")),
4984 	},
4985 	[ITEM_MPLS_TTL] = {
4986 		.name = "ttl",
4987 		.help = "MPLS Time-to-Live",
4988 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4989 			     item_param),
4990 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
4991 	},
4992 	[ITEM_GRE] = {
4993 		.name = "gre",
4994 		.help = "match GRE header",
4995 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4996 		.next = NEXT(item_gre),
4997 		.call = parse_vc,
4998 	},
4999 	[ITEM_GRE_PROTO] = {
5000 		.name = "protocol",
5001 		.help = "GRE protocol type",
5002 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5003 			     item_param),
5004 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5005 					     protocol)),
5006 	},
5007 	[ITEM_GRE_C_RSVD0_VER] = {
5008 		.name = "c_rsvd0_ver",
5009 		.help =
5010 			"checksum (1b), undefined (1b), key bit (1b),"
5011 			" sequence number (1b), reserved 0 (9b),"
5012 			" version (3b)",
5013 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5014 			     item_param),
5015 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5016 					     c_rsvd0_ver)),
5017 	},
5018 	[ITEM_GRE_C_BIT] = {
5019 		.name = "c_bit",
5020 		.help = "checksum bit (C)",
5021 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5022 			     item_param),
5023 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5024 						  c_rsvd0_ver,
5025 						  "\x80\x00\x00\x00")),
5026 	},
5027 	[ITEM_GRE_S_BIT] = {
5028 		.name = "s_bit",
5029 		.help = "sequence number bit (S)",
5030 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5031 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5032 						  c_rsvd0_ver,
5033 						  "\x10\x00\x00\x00")),
5034 	},
5035 	[ITEM_GRE_K_BIT] = {
5036 		.name = "k_bit",
5037 		.help = "key bit (K)",
5038 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5039 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5040 						  c_rsvd0_ver,
5041 						  "\x20\x00\x00\x00")),
5042 	},
5043 	[ITEM_FUZZY] = {
5044 		.name = "fuzzy",
5045 		.help = "fuzzy pattern match, expect faster than default",
5046 		.priv = PRIV_ITEM(FUZZY,
5047 				sizeof(struct rte_flow_item_fuzzy)),
5048 		.next = NEXT(item_fuzzy),
5049 		.call = parse_vc,
5050 	},
5051 	[ITEM_FUZZY_THRESH] = {
5052 		.name = "thresh",
5053 		.help = "match accuracy threshold",
5054 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5055 			     item_param),
5056 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5057 					thresh)),
5058 	},
5059 	[ITEM_GTP] = {
5060 		.name = "gtp",
5061 		.help = "match GTP header",
5062 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5063 		.next = NEXT(item_gtp),
5064 		.call = parse_vc,
5065 	},
5066 	[ITEM_GTP_FLAGS] = {
5067 		.name = "v_pt_rsv_flags",
5068 		.help = "GTP flags",
5069 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5070 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5071 					hdr.gtp_hdr_info)),
5072 	},
5073 	[ITEM_GTP_MSG_TYPE] = {
5074 		.name = "msg_type",
5075 		.help = "GTP message type",
5076 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5077 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5078 	},
5079 	[ITEM_GTP_TEID] = {
5080 		.name = "teid",
5081 		.help = "tunnel endpoint identifier",
5082 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5083 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5084 	},
5085 	[ITEM_GTPC] = {
5086 		.name = "gtpc",
5087 		.help = "match GTP header",
5088 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5089 		.next = NEXT(item_gtp),
5090 		.call = parse_vc,
5091 	},
5092 	[ITEM_GTPU] = {
5093 		.name = "gtpu",
5094 		.help = "match GTP header",
5095 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5096 		.next = NEXT(item_gtp),
5097 		.call = parse_vc,
5098 	},
5099 	[ITEM_GENEVE] = {
5100 		.name = "geneve",
5101 		.help = "match GENEVE header",
5102 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5103 		.next = NEXT(item_geneve),
5104 		.call = parse_vc,
5105 	},
5106 	[ITEM_GENEVE_VNI] = {
5107 		.name = "vni",
5108 		.help = "virtual network identifier",
5109 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5110 			     item_param),
5111 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5112 	},
5113 	[ITEM_GENEVE_PROTO] = {
5114 		.name = "protocol",
5115 		.help = "GENEVE protocol type",
5116 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5117 			     item_param),
5118 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5119 					     protocol)),
5120 	},
5121 	[ITEM_GENEVE_OPTLEN] = {
5122 		.name = "optlen",
5123 		.help = "GENEVE options length in dwords",
5124 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5125 			     item_param),
5126 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5127 						  ver_opt_len_o_c_rsvd0,
5128 						  "\x3f\x00")),
5129 	},
5130 	[ITEM_VXLAN_GPE] = {
5131 		.name = "vxlan-gpe",
5132 		.help = "match VXLAN-GPE header",
5133 		.priv = PRIV_ITEM(VXLAN_GPE,
5134 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5135 		.next = NEXT(item_vxlan_gpe),
5136 		.call = parse_vc,
5137 	},
5138 	[ITEM_VXLAN_GPE_VNI] = {
5139 		.name = "vni",
5140 		.help = "VXLAN-GPE identifier",
5141 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5142 			     item_param),
5143 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5144 					     hdr.vni)),
5145 	},
5146 	[ITEM_VXLAN_GPE_PROTO] = {
5147 		.name = "protocol",
5148 		.help = "VXLAN-GPE next protocol",
5149 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5150 			     item_param),
5151 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5152 					     protocol)),
5153 	},
5154 	[ITEM_VXLAN_GPE_FLAGS] = {
5155 		.name = "flags",
5156 		.help = "VXLAN-GPE flags",
5157 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5158 			     item_param),
5159 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5160 					     flags)),
5161 	},
5162 	[ITEM_VXLAN_GPE_RSVD0] = {
5163 		.name = "rsvd0",
5164 		.help = "VXLAN-GPE rsvd0",
5165 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5166 			     item_param),
5167 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5168 					     rsvd0)),
5169 	},
5170 	[ITEM_VXLAN_GPE_RSVD1] = {
5171 		.name = "rsvd1",
5172 		.help = "VXLAN-GPE rsvd1",
5173 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5174 			     item_param),
5175 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5176 					     rsvd1)),
5177 	},
5178 	[ITEM_ARP_ETH_IPV4] = {
5179 		.name = "arp_eth_ipv4",
5180 		.help = "match ARP header for Ethernet/IPv4",
5181 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5182 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5183 		.next = NEXT(item_arp_eth_ipv4),
5184 		.call = parse_vc,
5185 	},
5186 	[ITEM_ARP_ETH_IPV4_SHA] = {
5187 		.name = "sha",
5188 		.help = "sender hardware address",
5189 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5190 			     item_param),
5191 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5192 					     hdr.arp_data.arp_sha)),
5193 	},
5194 	[ITEM_ARP_ETH_IPV4_SPA] = {
5195 		.name = "spa",
5196 		.help = "sender IPv4 address",
5197 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5198 			     item_param),
5199 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5200 					     hdr.arp_data.arp_sip)),
5201 	},
5202 	[ITEM_ARP_ETH_IPV4_THA] = {
5203 		.name = "tha",
5204 		.help = "target hardware address",
5205 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5206 			     item_param),
5207 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5208 					     hdr.arp_data.arp_tha)),
5209 	},
5210 	[ITEM_ARP_ETH_IPV4_TPA] = {
5211 		.name = "tpa",
5212 		.help = "target IPv4 address",
5213 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5214 			     item_param),
5215 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5216 					     hdr.arp_data.arp_tip)),
5217 	},
5218 	[ITEM_IPV6_EXT] = {
5219 		.name = "ipv6_ext",
5220 		.help = "match presence of any IPv6 extension header",
5221 		.priv = PRIV_ITEM(IPV6_EXT,
5222 				  sizeof(struct rte_flow_item_ipv6_ext)),
5223 		.next = NEXT(item_ipv6_ext),
5224 		.call = parse_vc,
5225 	},
5226 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5227 		.name = "next_hdr",
5228 		.help = "next header",
5229 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5230 			     item_param),
5231 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5232 					     next_hdr)),
5233 	},
5234 	[ITEM_IPV6_FRAG_EXT] = {
5235 		.name = "ipv6_frag_ext",
5236 		.help = "match presence of IPv6 fragment extension header",
5237 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5238 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5239 		.next = NEXT(item_ipv6_frag_ext),
5240 		.call = parse_vc,
5241 	},
5242 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5243 		.name = "next_hdr",
5244 		.help = "next header",
5245 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5246 			     item_param),
5247 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5248 					hdr.next_header)),
5249 	},
5250 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5251 		.name = "frag_data",
5252 		.help = "fragment flags and offset",
5253 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5254 			     item_param),
5255 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5256 					     hdr.frag_data)),
5257 	},
5258 	[ITEM_IPV6_FRAG_EXT_ID] = {
5259 		.name = "packet_id",
5260 		.help = "fragment packet id",
5261 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5262 			     item_param),
5263 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5264 					     hdr.id)),
5265 	},
5266 	[ITEM_ICMP6] = {
5267 		.name = "icmp6",
5268 		.help = "match any ICMPv6 header",
5269 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5270 		.next = NEXT(item_icmp6),
5271 		.call = parse_vc,
5272 	},
5273 	[ITEM_ICMP6_TYPE] = {
5274 		.name = "type",
5275 		.help = "ICMPv6 type",
5276 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5277 			     item_param),
5278 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5279 					     type)),
5280 	},
5281 	[ITEM_ICMP6_CODE] = {
5282 		.name = "code",
5283 		.help = "ICMPv6 code",
5284 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5285 			     item_param),
5286 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5287 					     code)),
5288 	},
5289 	[ITEM_ICMP6_ECHO_REQUEST] = {
5290 		.name = "icmp6_echo_request",
5291 		.help = "match ICMPv6 echo request",
5292 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5293 				  sizeof(struct rte_flow_item_icmp6_echo)),
5294 		.next = NEXT(item_icmp6_echo_request),
5295 		.call = parse_vc,
5296 	},
5297 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5298 		.name = "ident",
5299 		.help = "ICMPv6 echo request identifier",
5300 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5301 			     item_param),
5302 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5303 					     hdr.identifier)),
5304 	},
5305 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5306 		.name = "seq",
5307 		.help = "ICMPv6 echo request sequence",
5308 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5309 			     item_param),
5310 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5311 					     hdr.sequence)),
5312 	},
5313 	[ITEM_ICMP6_ECHO_REPLY] = {
5314 		.name = "icmp6_echo_reply",
5315 		.help = "match ICMPv6 echo reply",
5316 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5317 				  sizeof(struct rte_flow_item_icmp6_echo)),
5318 		.next = NEXT(item_icmp6_echo_reply),
5319 		.call = parse_vc,
5320 	},
5321 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5322 		.name = "ident",
5323 		.help = "ICMPv6 echo reply identifier",
5324 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5325 			     item_param),
5326 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5327 					     hdr.identifier)),
5328 	},
5329 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5330 		.name = "seq",
5331 		.help = "ICMPv6 echo reply sequence",
5332 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5333 			     item_param),
5334 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5335 					     hdr.sequence)),
5336 	},
5337 	[ITEM_ICMP6_ND_NS] = {
5338 		.name = "icmp6_nd_ns",
5339 		.help = "match ICMPv6 neighbor discovery solicitation",
5340 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5341 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5342 		.next = NEXT(item_icmp6_nd_ns),
5343 		.call = parse_vc,
5344 	},
5345 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5346 		.name = "target_addr",
5347 		.help = "target address",
5348 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5349 			     item_param),
5350 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5351 					     target_addr)),
5352 	},
5353 	[ITEM_ICMP6_ND_NA] = {
5354 		.name = "icmp6_nd_na",
5355 		.help = "match ICMPv6 neighbor discovery advertisement",
5356 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5357 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5358 		.next = NEXT(item_icmp6_nd_na),
5359 		.call = parse_vc,
5360 	},
5361 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5362 		.name = "target_addr",
5363 		.help = "target address",
5364 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5365 			     item_param),
5366 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5367 					     target_addr)),
5368 	},
5369 	[ITEM_ICMP6_ND_OPT] = {
5370 		.name = "icmp6_nd_opt",
5371 		.help = "match presence of any ICMPv6 neighbor discovery"
5372 			" option",
5373 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5374 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5375 		.next = NEXT(item_icmp6_nd_opt),
5376 		.call = parse_vc,
5377 	},
5378 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5379 		.name = "type",
5380 		.help = "ND option type",
5381 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5382 			     item_param),
5383 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5384 					     type)),
5385 	},
5386 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5387 		.name = "icmp6_nd_opt_sla_eth",
5388 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5389 			" link-layer address option",
5390 		.priv = PRIV_ITEM
5391 			(ICMP6_ND_OPT_SLA_ETH,
5392 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5393 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5394 		.call = parse_vc,
5395 	},
5396 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5397 		.name = "sla",
5398 		.help = "source Ethernet LLA",
5399 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5400 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5401 		.args = ARGS(ARGS_ENTRY_HTON
5402 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5403 	},
5404 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5405 		.name = "icmp6_nd_opt_tla_eth",
5406 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5407 			" link-layer address option",
5408 		.priv = PRIV_ITEM
5409 			(ICMP6_ND_OPT_TLA_ETH,
5410 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5411 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5412 		.call = parse_vc,
5413 	},
5414 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5415 		.name = "tla",
5416 		.help = "target Ethernet LLA",
5417 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5418 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5419 		.args = ARGS(ARGS_ENTRY_HTON
5420 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5421 	},
5422 	[ITEM_META] = {
5423 		.name = "meta",
5424 		.help = "match metadata header",
5425 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5426 		.next = NEXT(item_meta),
5427 		.call = parse_vc,
5428 	},
5429 	[ITEM_META_DATA] = {
5430 		.name = "data",
5431 		.help = "metadata value",
5432 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5433 			     item_param),
5434 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5435 					     data, "\xff\xff\xff\xff")),
5436 	},
5437 	[ITEM_RANDOM] = {
5438 		.name = "random",
5439 		.help = "match random value",
5440 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5441 		.next = NEXT(item_random),
5442 		.call = parse_vc,
5443 	},
5444 	[ITEM_RANDOM_VALUE] = {
5445 		.name = "value",
5446 		.help = "random value",
5447 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5448 			     item_param),
5449 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5450 					     value, "\xff\xff")),
5451 	},
5452 	[ITEM_GRE_KEY] = {
5453 		.name = "gre_key",
5454 		.help = "match GRE key",
5455 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5456 		.next = NEXT(item_gre_key),
5457 		.call = parse_vc,
5458 	},
5459 	[ITEM_GRE_KEY_VALUE] = {
5460 		.name = "value",
5461 		.help = "key value",
5462 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5463 			     item_param),
5464 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5465 	},
5466 	[ITEM_GRE_OPTION] = {
5467 		.name = "gre_option",
5468 		.help = "match GRE optional fields",
5469 		.priv = PRIV_ITEM(GRE_OPTION,
5470 				  sizeof(struct rte_flow_item_gre_opt)),
5471 		.next = NEXT(item_gre_option),
5472 		.call = parse_vc,
5473 	},
5474 	[ITEM_GRE_OPTION_CHECKSUM] = {
5475 		.name = "checksum",
5476 		.help = "match GRE checksum",
5477 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5478 			     item_param),
5479 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5480 					     checksum_rsvd.checksum)),
5481 	},
5482 	[ITEM_GRE_OPTION_KEY] = {
5483 		.name = "key",
5484 		.help = "match GRE key",
5485 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5486 			     item_param),
5487 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5488 					     key.key)),
5489 	},
5490 	[ITEM_GRE_OPTION_SEQUENCE] = {
5491 		.name = "sequence",
5492 		.help = "match GRE sequence",
5493 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5494 			     item_param),
5495 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5496 					     sequence.sequence)),
5497 	},
5498 	[ITEM_GTP_PSC] = {
5499 		.name = "gtp_psc",
5500 		.help = "match GTP extension header with type 0x85",
5501 		.priv = PRIV_ITEM(GTP_PSC,
5502 				sizeof(struct rte_flow_item_gtp_psc)),
5503 		.next = NEXT(item_gtp_psc),
5504 		.call = parse_vc,
5505 	},
5506 	[ITEM_GTP_PSC_QFI] = {
5507 		.name = "qfi",
5508 		.help = "QoS flow identifier",
5509 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5510 			     item_param),
5511 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5512 					hdr.qfi, 6)),
5513 	},
5514 	[ITEM_GTP_PSC_PDU_T] = {
5515 		.name = "pdu_t",
5516 		.help = "PDU type",
5517 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5518 			     item_param),
5519 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5520 					hdr.type, 4)),
5521 	},
5522 	[ITEM_PPPOES] = {
5523 		.name = "pppoes",
5524 		.help = "match PPPoE session header",
5525 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5526 		.next = NEXT(item_pppoes),
5527 		.call = parse_vc,
5528 	},
5529 	[ITEM_PPPOED] = {
5530 		.name = "pppoed",
5531 		.help = "match PPPoE discovery header",
5532 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5533 		.next = NEXT(item_pppoed),
5534 		.call = parse_vc,
5535 	},
5536 	[ITEM_PPPOE_SEID] = {
5537 		.name = "seid",
5538 		.help = "session identifier",
5539 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5540 			     item_param),
5541 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5542 					session_id)),
5543 	},
5544 	[ITEM_PPPOE_PROTO_ID] = {
5545 		.name = "pppoe_proto_id",
5546 		.help = "match PPPoE session protocol identifier",
5547 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5548 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5549 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5550 			     item_param),
5551 		.args = ARGS(ARGS_ENTRY_HTON
5552 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5553 		.call = parse_vc,
5554 	},
5555 	[ITEM_HIGIG2] = {
5556 		.name = "higig2",
5557 		.help = "matches higig2 header",
5558 		.priv = PRIV_ITEM(HIGIG2,
5559 				sizeof(struct rte_flow_item_higig2_hdr)),
5560 		.next = NEXT(item_higig2),
5561 		.call = parse_vc,
5562 	},
5563 	[ITEM_HIGIG2_CLASSIFICATION] = {
5564 		.name = "classification",
5565 		.help = "matches classification of higig2 header",
5566 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5567 			     item_param),
5568 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5569 					hdr.ppt1.classification)),
5570 	},
5571 	[ITEM_HIGIG2_VID] = {
5572 		.name = "vid",
5573 		.help = "matches vid of higig2 header",
5574 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5575 			     item_param),
5576 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5577 					hdr.ppt1.vid)),
5578 	},
5579 	[ITEM_TAG] = {
5580 		.name = "tag",
5581 		.help = "match tag value",
5582 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5583 		.next = NEXT(item_tag),
5584 		.call = parse_vc,
5585 	},
5586 	[ITEM_TAG_DATA] = {
5587 		.name = "data",
5588 		.help = "tag value to match",
5589 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5590 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5591 	},
5592 	[ITEM_TAG_INDEX] = {
5593 		.name = "index",
5594 		.help = "index of tag array to match",
5595 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5596 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5597 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5598 	},
5599 	[ITEM_L2TPV3OIP] = {
5600 		.name = "l2tpv3oip",
5601 		.help = "match L2TPv3 over IP header",
5602 		.priv = PRIV_ITEM(L2TPV3OIP,
5603 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5604 		.next = NEXT(item_l2tpv3oip),
5605 		.call = parse_vc,
5606 	},
5607 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5608 		.name = "session_id",
5609 		.help = "session identifier",
5610 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5611 			     item_param),
5612 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5613 					     session_id)),
5614 	},
5615 	[ITEM_ESP] = {
5616 		.name = "esp",
5617 		.help = "match ESP header",
5618 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5619 		.next = NEXT(item_esp),
5620 		.call = parse_vc,
5621 	},
5622 	[ITEM_ESP_SPI] = {
5623 		.name = "spi",
5624 		.help = "security policy index",
5625 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5626 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5627 				hdr.spi)),
5628 	},
5629 	[ITEM_AH] = {
5630 		.name = "ah",
5631 		.help = "match AH header",
5632 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5633 		.next = NEXT(item_ah),
5634 		.call = parse_vc,
5635 	},
5636 	[ITEM_AH_SPI] = {
5637 		.name = "spi",
5638 		.help = "security parameters index",
5639 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5640 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5641 	},
5642 	[ITEM_PFCP] = {
5643 		.name = "pfcp",
5644 		.help = "match pfcp header",
5645 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5646 		.next = NEXT(item_pfcp),
5647 		.call = parse_vc,
5648 	},
5649 	[ITEM_PFCP_S_FIELD] = {
5650 		.name = "s_field",
5651 		.help = "S field",
5652 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5653 			     item_param),
5654 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5655 				s_field)),
5656 	},
5657 	[ITEM_PFCP_SEID] = {
5658 		.name = "seid",
5659 		.help = "session endpoint identifier",
5660 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5661 			     item_param),
5662 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5663 	},
5664 	[ITEM_ECPRI] = {
5665 		.name = "ecpri",
5666 		.help = "match eCPRI header",
5667 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5668 		.next = NEXT(item_ecpri),
5669 		.call = parse_vc,
5670 	},
5671 	[ITEM_ECPRI_COMMON] = {
5672 		.name = "common",
5673 		.help = "eCPRI common header",
5674 		.next = NEXT(item_ecpri_common),
5675 	},
5676 	[ITEM_ECPRI_COMMON_TYPE] = {
5677 		.name = "type",
5678 		.help = "type of common header",
5679 		.next = NEXT(item_ecpri_common_type),
5680 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5681 	},
5682 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5683 		.name = "iq_data",
5684 		.help = "Type #0: IQ Data",
5685 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5686 					ITEM_NEXT)),
5687 		.call = parse_vc_item_ecpri_type,
5688 	},
5689 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5690 		.name = "pc_id",
5691 		.help = "Physical Channel ID",
5692 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5693 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5694 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5695 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5696 				hdr.type0.pc_id)),
5697 	},
5698 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5699 		.name = "rtc_ctrl",
5700 		.help = "Type #2: Real-Time Control Data",
5701 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5702 					ITEM_NEXT)),
5703 		.call = parse_vc_item_ecpri_type,
5704 	},
5705 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5706 		.name = "rtc_id",
5707 		.help = "Real-Time Control Data ID",
5708 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5709 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5710 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5711 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5712 				hdr.type2.rtc_id)),
5713 	},
5714 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5715 		.name = "delay_measure",
5716 		.help = "Type #5: One-Way Delay Measurement",
5717 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5718 					ITEM_NEXT)),
5719 		.call = parse_vc_item_ecpri_type,
5720 	},
5721 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5722 		.name = "msr_id",
5723 		.help = "Measurement ID",
5724 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5725 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5726 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5727 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5728 				hdr.type5.msr_id)),
5729 	},
5730 	[ITEM_GENEVE_OPT] = {
5731 		.name = "geneve-opt",
5732 		.help = "GENEVE header option",
5733 		.priv = PRIV_ITEM(GENEVE_OPT,
5734 				  sizeof(struct rte_flow_item_geneve_opt) +
5735 				  ITEM_GENEVE_OPT_DATA_SIZE),
5736 		.next = NEXT(item_geneve_opt),
5737 		.call = parse_vc,
5738 	},
5739 	[ITEM_GENEVE_OPT_CLASS]	= {
5740 		.name = "class",
5741 		.help = "GENEVE option class",
5742 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5743 			     item_param),
5744 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5745 					     option_class)),
5746 	},
5747 	[ITEM_GENEVE_OPT_TYPE] = {
5748 		.name = "type",
5749 		.help = "GENEVE option type",
5750 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5751 			     item_param),
5752 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5753 					option_type)),
5754 	},
5755 	[ITEM_GENEVE_OPT_LENGTH] = {
5756 		.name = "length",
5757 		.help = "GENEVE option data length (in 32b words)",
5758 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5759 			     item_param),
5760 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5761 				struct rte_flow_item_geneve_opt, option_len,
5762 				0, 31)),
5763 	},
5764 	[ITEM_GENEVE_OPT_DATA] = {
5765 		.name = "data",
5766 		.help = "GENEVE option data pattern",
5767 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5768 			     item_param),
5769 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5770 			     ARGS_ENTRY_ARB(0, 0),
5771 			     ARGS_ENTRY_ARB
5772 				(sizeof(struct rte_flow_item_geneve_opt),
5773 				ITEM_GENEVE_OPT_DATA_SIZE)),
5774 	},
5775 	[ITEM_INTEGRITY] = {
5776 		.name = "integrity",
5777 		.help = "match packet integrity",
5778 		.priv = PRIV_ITEM(INTEGRITY,
5779 				  sizeof(struct rte_flow_item_integrity)),
5780 		.next = NEXT(item_integrity),
5781 		.call = parse_vc,
5782 	},
5783 	[ITEM_INTEGRITY_LEVEL] = {
5784 		.name = "level",
5785 		.help = "integrity level",
5786 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5787 			     item_param),
5788 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5789 	},
5790 	[ITEM_INTEGRITY_VALUE] = {
5791 		.name = "value",
5792 		.help = "integrity value",
5793 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5794 			     item_param),
5795 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5796 	},
5797 	[ITEM_CONNTRACK] = {
5798 		.name = "conntrack",
5799 		.help = "conntrack state",
5800 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5801 			     item_param),
5802 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5803 	},
5804 	[ITEM_PORT_REPRESENTOR] = {
5805 		.name = "port_representor",
5806 		.help = "match traffic entering the embedded switch from the given ethdev",
5807 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5808 				  sizeof(struct rte_flow_item_ethdev)),
5809 		.next = NEXT(item_port_representor),
5810 		.call = parse_vc,
5811 	},
5812 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5813 		.name = "port_id",
5814 		.help = "ethdev port ID",
5815 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5816 			     item_param),
5817 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5818 	},
5819 	[ITEM_REPRESENTED_PORT] = {
5820 		.name = "represented_port",
5821 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5822 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5823 				  sizeof(struct rte_flow_item_ethdev)),
5824 		.next = NEXT(item_represented_port),
5825 		.call = parse_vc,
5826 	},
5827 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5828 		.name = "ethdev_port_id",
5829 		.help = "ethdev port ID",
5830 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5831 			     item_param),
5832 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5833 	},
5834 	[ITEM_FLEX] = {
5835 		.name = "flex",
5836 		.help = "match flex header",
5837 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5838 		.next = NEXT(item_flex),
5839 		.call = parse_vc,
5840 	},
5841 	[ITEM_FLEX_ITEM_HANDLE] = {
5842 		.name = "item",
5843 		.help = "flex item handle",
5844 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5845 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5846 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5847 	},
5848 	[ITEM_FLEX_PATTERN_HANDLE] = {
5849 		.name = "pattern",
5850 		.help = "flex pattern handle",
5851 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5852 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5853 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5854 	},
5855 	[ITEM_L2TPV2] = {
5856 		.name = "l2tpv2",
5857 		.help = "match L2TPv2 header",
5858 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5859 		.next = NEXT(item_l2tpv2),
5860 		.call = parse_vc,
5861 	},
5862 	[ITEM_L2TPV2_TYPE] = {
5863 		.name = "type",
5864 		.help = "type of l2tpv2",
5865 		.next = NEXT(item_l2tpv2_type),
5866 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5867 	},
5868 	[ITEM_L2TPV2_TYPE_DATA] = {
5869 		.name = "data",
5870 		.help = "Type #7: data message without any options",
5871 		.next = NEXT(item_l2tpv2_type_data),
5872 		.call = parse_vc_item_l2tpv2_type,
5873 	},
5874 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5875 		.name = "tunnel_id",
5876 		.help = "tunnel identifier",
5877 		.next = NEXT(item_l2tpv2_type_data,
5878 			     NEXT_ENTRY(COMMON_UNSIGNED),
5879 			     item_param),
5880 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5881 					     hdr.type7.tunnel_id)),
5882 	},
5883 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5884 		.name = "session_id",
5885 		.help = "session identifier",
5886 		.next = NEXT(item_l2tpv2_type_data,
5887 			     NEXT_ENTRY(COMMON_UNSIGNED),
5888 			     item_param),
5889 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5890 					     hdr.type7.session_id)),
5891 	},
5892 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5893 		.name = "data_l",
5894 		.help = "Type #6: data message with length option",
5895 		.next = NEXT(item_l2tpv2_type_data_l),
5896 		.call = parse_vc_item_l2tpv2_type,
5897 	},
5898 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5899 		.name = "length",
5900 		.help = "message length",
5901 		.next = NEXT(item_l2tpv2_type_data_l,
5902 			     NEXT_ENTRY(COMMON_UNSIGNED),
5903 			     item_param),
5904 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5905 					     hdr.type6.length)),
5906 	},
5907 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5908 		.name = "tunnel_id",
5909 		.help = "tunnel identifier",
5910 		.next = NEXT(item_l2tpv2_type_data_l,
5911 			     NEXT_ENTRY(COMMON_UNSIGNED),
5912 			     item_param),
5913 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5914 					     hdr.type6.tunnel_id)),
5915 	},
5916 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5917 		.name = "session_id",
5918 		.help = "session identifier",
5919 		.next = NEXT(item_l2tpv2_type_data_l,
5920 			     NEXT_ENTRY(COMMON_UNSIGNED),
5921 			     item_param),
5922 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5923 					     hdr.type6.session_id)),
5924 	},
5925 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5926 		.name = "data_s",
5927 		.help = "Type #5: data message with ns, nr option",
5928 		.next = NEXT(item_l2tpv2_type_data_s),
5929 		.call = parse_vc_item_l2tpv2_type,
5930 	},
5931 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5932 		.name = "tunnel_id",
5933 		.help = "tunnel identifier",
5934 		.next = NEXT(item_l2tpv2_type_data_s,
5935 			     NEXT_ENTRY(COMMON_UNSIGNED),
5936 			     item_param),
5937 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5938 					     hdr.type5.tunnel_id)),
5939 	},
5940 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5941 		.name = "session_id",
5942 		.help = "session identifier",
5943 		.next = NEXT(item_l2tpv2_type_data_s,
5944 			     NEXT_ENTRY(COMMON_UNSIGNED),
5945 			     item_param),
5946 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5947 					     hdr.type5.session_id)),
5948 	},
5949 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5950 		.name = "ns",
5951 		.help = "sequence number for message",
5952 		.next = NEXT(item_l2tpv2_type_data_s,
5953 			     NEXT_ENTRY(COMMON_UNSIGNED),
5954 			     item_param),
5955 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5956 					     hdr.type5.ns)),
5957 	},
5958 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5959 		.name = "nr",
5960 		.help = "sequence number for next receive message",
5961 		.next = NEXT(item_l2tpv2_type_data_s,
5962 			     NEXT_ENTRY(COMMON_UNSIGNED),
5963 			     item_param),
5964 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5965 					     hdr.type5.nr)),
5966 	},
5967 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5968 		.name = "data_o",
5969 		.help = "Type #4: data message with offset option",
5970 		.next = NEXT(item_l2tpv2_type_data_o),
5971 		.call = parse_vc_item_l2tpv2_type,
5972 	},
5973 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5974 		.name = "tunnel_id",
5975 		.help = "tunnel identifier",
5976 		.next = NEXT(item_l2tpv2_type_data_o,
5977 			     NEXT_ENTRY(COMMON_UNSIGNED),
5978 			     item_param),
5979 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5980 					     hdr.type4.tunnel_id)),
5981 	},
5982 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5983 		.name = "session_id",
5984 		.help = "session identifier",
5985 		.next = NEXT(item_l2tpv2_type_data_o,
5986 			     NEXT_ENTRY(COMMON_UNSIGNED),
5987 			     item_param),
5988 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5989 					     hdr.type5.session_id)),
5990 	},
5991 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
5992 		.name = "offset_size",
5993 		.help = "the size of offset padding",
5994 		.next = NEXT(item_l2tpv2_type_data_o,
5995 			     NEXT_ENTRY(COMMON_UNSIGNED),
5996 			     item_param),
5997 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5998 					     hdr.type4.offset_size)),
5999 	},
6000 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6001 		.name = "data_l_s",
6002 		.help = "Type #3: data message contains length, ns, nr "
6003 			"options",
6004 		.next = NEXT(item_l2tpv2_type_data_l_s),
6005 		.call = parse_vc_item_l2tpv2_type,
6006 	},
6007 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6008 		.name = "length",
6009 		.help = "message length",
6010 		.next = NEXT(item_l2tpv2_type_data_l_s,
6011 			     NEXT_ENTRY(COMMON_UNSIGNED),
6012 			     item_param),
6013 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6014 					     hdr.type3.length)),
6015 	},
6016 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6017 		.name = "tunnel_id",
6018 		.help = "tunnel identifier",
6019 		.next = NEXT(item_l2tpv2_type_data_l_s,
6020 			     NEXT_ENTRY(COMMON_UNSIGNED),
6021 			     item_param),
6022 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6023 					     hdr.type3.tunnel_id)),
6024 	},
6025 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6026 		.name = "session_id",
6027 		.help = "session identifier",
6028 		.next = NEXT(item_l2tpv2_type_data_l_s,
6029 			     NEXT_ENTRY(COMMON_UNSIGNED),
6030 			     item_param),
6031 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6032 					     hdr.type3.session_id)),
6033 	},
6034 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6035 		.name = "ns",
6036 		.help = "sequence number for message",
6037 		.next = NEXT(item_l2tpv2_type_data_l_s,
6038 			     NEXT_ENTRY(COMMON_UNSIGNED),
6039 			     item_param),
6040 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6041 					     hdr.type3.ns)),
6042 	},
6043 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6044 		.name = "nr",
6045 		.help = "sequence number for next receive message",
6046 		.next = NEXT(item_l2tpv2_type_data_l_s,
6047 			     NEXT_ENTRY(COMMON_UNSIGNED),
6048 			     item_param),
6049 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6050 					     hdr.type3.nr)),
6051 	},
6052 	[ITEM_L2TPV2_TYPE_CTRL] = {
6053 		.name = "control",
6054 		.help = "Type #3: conrtol message contains length, ns, nr "
6055 			"options",
6056 		.next = NEXT(item_l2tpv2_type_ctrl),
6057 		.call = parse_vc_item_l2tpv2_type,
6058 	},
6059 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6060 		.name = "length",
6061 		.help = "message length",
6062 		.next = NEXT(item_l2tpv2_type_ctrl,
6063 			     NEXT_ENTRY(COMMON_UNSIGNED),
6064 			     item_param),
6065 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6066 					     hdr.type3.length)),
6067 	},
6068 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6069 		.name = "tunnel_id",
6070 		.help = "tunnel identifier",
6071 		.next = NEXT(item_l2tpv2_type_ctrl,
6072 			     NEXT_ENTRY(COMMON_UNSIGNED),
6073 			     item_param),
6074 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6075 					     hdr.type3.tunnel_id)),
6076 	},
6077 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6078 		.name = "session_id",
6079 		.help = "session identifier",
6080 		.next = NEXT(item_l2tpv2_type_ctrl,
6081 			     NEXT_ENTRY(COMMON_UNSIGNED),
6082 			     item_param),
6083 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6084 					     hdr.type3.session_id)),
6085 	},
6086 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6087 		.name = "ns",
6088 		.help = "sequence number for message",
6089 		.next = NEXT(item_l2tpv2_type_ctrl,
6090 			     NEXT_ENTRY(COMMON_UNSIGNED),
6091 			     item_param),
6092 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6093 					     hdr.type3.ns)),
6094 	},
6095 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6096 		.name = "nr",
6097 		.help = "sequence number for next receive message",
6098 		.next = NEXT(item_l2tpv2_type_ctrl,
6099 			     NEXT_ENTRY(COMMON_UNSIGNED),
6100 			     item_param),
6101 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6102 					     hdr.type3.nr)),
6103 	},
6104 	[ITEM_PPP] = {
6105 		.name = "ppp",
6106 		.help = "match PPP header",
6107 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6108 		.next = NEXT(item_ppp),
6109 		.call = parse_vc,
6110 	},
6111 	[ITEM_PPP_ADDR] = {
6112 		.name = "addr",
6113 		.help = "PPP address",
6114 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6115 			     item_param),
6116 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6117 	},
6118 	[ITEM_PPP_CTRL] = {
6119 		.name = "ctrl",
6120 		.help = "PPP control",
6121 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6122 			     item_param),
6123 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6124 	},
6125 	[ITEM_PPP_PROTO_ID] = {
6126 		.name = "proto_id",
6127 		.help = "PPP protocol identifier",
6128 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6129 			     item_param),
6130 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6131 					hdr.proto_id)),
6132 	},
6133 	[ITEM_METER] = {
6134 		.name = "meter",
6135 		.help = "match meter color",
6136 		.priv = PRIV_ITEM(METER_COLOR,
6137 				  sizeof(struct rte_flow_item_meter_color)),
6138 		.next = NEXT(item_meter),
6139 		.call = parse_vc,
6140 	},
6141 	[ITEM_METER_COLOR] = {
6142 		.name = "color",
6143 		.help = "meter color",
6144 		.next = NEXT(item_meter,
6145 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6146 			     item_param),
6147 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6148 					color)),
6149 	},
6150 	[ITEM_METER_COLOR_NAME] = {
6151 		.name = "color_name",
6152 		.help = "meter color name",
6153 		.call = parse_meter_color,
6154 		.comp = comp_meter_color,
6155 	},
6156 	[ITEM_QUOTA] = {
6157 		.name = "quota",
6158 		.help = "match quota",
6159 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6160 		.next = NEXT(item_quota),
6161 		.call = parse_vc
6162 	},
6163 	[ITEM_QUOTA_STATE] = {
6164 		.name = "quota_state",
6165 		.help = "quota state",
6166 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6167 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6168 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6169 	},
6170 	[ITEM_QUOTA_STATE_NAME] = {
6171 		.name = "state_name",
6172 		.help = "quota state name",
6173 		.call = parse_quota_state_name,
6174 		.comp = comp_quota_state_name
6175 	},
6176 	[ITEM_IB_BTH] = {
6177 		.name = "ib_bth",
6178 		.help = "match ib bth fields",
6179 		.priv = PRIV_ITEM(IB_BTH,
6180 				  sizeof(struct rte_flow_item_ib_bth)),
6181 		.next = NEXT(item_ib_bth),
6182 		.call = parse_vc,
6183 	},
6184 	[ITEM_IB_BTH_OPCODE] = {
6185 		.name = "opcode",
6186 		.help = "match ib bth opcode",
6187 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6188 				 item_param),
6189 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6190 						 hdr.opcode)),
6191 	},
6192 	[ITEM_IB_BTH_PKEY] = {
6193 		.name = "pkey",
6194 		.help = "partition key",
6195 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6196 				 item_param),
6197 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6198 						 hdr.pkey)),
6199 	},
6200 	[ITEM_IB_BTH_DST_QPN] = {
6201 		.name = "dst_qp",
6202 		.help = "destination qp",
6203 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6204 				 item_param),
6205 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6206 						 hdr.dst_qp)),
6207 	},
6208 	[ITEM_IB_BTH_PSN] = {
6209 		.name = "psn",
6210 		.help = "packet sequence number",
6211 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6212 				 item_param),
6213 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6214 						 hdr.psn)),
6215 	},
6216 	[ITEM_PTYPE] = {
6217 		.name = "ptype",
6218 		.help = "match L2/L3/L4 and tunnel information",
6219 		.priv = PRIV_ITEM(PTYPE,
6220 				  sizeof(struct rte_flow_item_ptype)),
6221 		.next = NEXT(item_ptype),
6222 		.call = parse_vc,
6223 	},
6224 	[ITEM_PTYPE_VALUE] = {
6225 		.name = "packet_type",
6226 		.help = "packet type as defined in rte_mbuf_ptype",
6227 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6228 			     item_param),
6229 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6230 	},
6231 	[ITEM_NSH] = {
6232 		.name = "nsh",
6233 		.help = "match NSH header",
6234 		.priv = PRIV_ITEM(NSH,
6235 				  sizeof(struct rte_flow_item_nsh)),
6236 		.next = NEXT(item_nsh),
6237 		.call = parse_vc,
6238 	},
6239 	[ITEM_COMPARE] = {
6240 		.name = "compare",
6241 		.help = "match with the comparison result",
6242 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6243 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6244 		.call = parse_vc,
6245 	},
6246 	[ITEM_COMPARE_OP] = {
6247 		.name = "op",
6248 		.help = "operation type",
6249 		.next = NEXT(item_compare_field,
6250 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6251 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6252 	},
6253 	[ITEM_COMPARE_OP_VALUE] = {
6254 		.name = "{operation}",
6255 		.help = "operation type value",
6256 		.call = parse_vc_compare_op,
6257 		.comp = comp_set_compare_op,
6258 	},
6259 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6260 		.name = "a_type",
6261 		.help = "compared field type",
6262 		.next = NEXT(compare_field_a,
6263 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6264 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6265 	},
6266 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6267 		.name = "{a_type}",
6268 		.help = "compared field type value",
6269 		.call = parse_vc_compare_field_id,
6270 		.comp = comp_set_compare_field_id,
6271 	},
6272 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6273 		.name = "a_level",
6274 		.help = "compared field level",
6275 		.next = NEXT(compare_field_a,
6276 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6277 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6278 	},
6279 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6280 		.name = "{a_level}",
6281 		.help = "compared field level value",
6282 		.call = parse_vc_compare_field_level,
6283 		.comp = comp_none,
6284 	},
6285 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6286 		.name = "a_tag_index",
6287 		.help = "compared field tag array",
6288 		.next = NEXT(compare_field_a,
6289 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6290 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6291 					a.tag_index)),
6292 	},
6293 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6294 		.name = "a_type_id",
6295 		.help = "compared field type ID",
6296 		.next = NEXT(compare_field_a,
6297 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6298 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6299 					a.type)),
6300 	},
6301 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6302 		.name = "a_class",
6303 		.help = "compared field class ID",
6304 		.next = NEXT(compare_field_a,
6305 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6306 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6307 					     a.class_id)),
6308 	},
6309 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6310 		.name = "a_offset",
6311 		.help = "compared field bit offset",
6312 		.next = NEXT(compare_field_a,
6313 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6314 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6315 					a.offset)),
6316 	},
6317 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6318 		.name = "b_type",
6319 		.help = "comparator field type",
6320 		.next = NEXT(compare_field_b,
6321 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6322 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6323 					b.field)),
6324 	},
6325 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6326 		.name = "{b_type}",
6327 		.help = "comparator field type value",
6328 		.call = parse_vc_compare_field_id,
6329 		.comp = comp_set_compare_field_id,
6330 	},
6331 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6332 		.name = "b_level",
6333 		.help = "comparator field level",
6334 		.next = NEXT(compare_field_b,
6335 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6336 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6337 					b.level)),
6338 	},
6339 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6340 		.name = "{b_level}",
6341 		.help = "comparator field level value",
6342 		.call = parse_vc_compare_field_level,
6343 		.comp = comp_none,
6344 	},
6345 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6346 		.name = "b_tag_index",
6347 		.help = "comparator field tag array",
6348 		.next = NEXT(compare_field_b,
6349 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6350 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6351 					b.tag_index)),
6352 	},
6353 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6354 		.name = "b_type_id",
6355 		.help = "comparator field type ID",
6356 		.next = NEXT(compare_field_b,
6357 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6358 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6359 					b.type)),
6360 	},
6361 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6362 		.name = "b_class",
6363 		.help = "comparator field class ID",
6364 		.next = NEXT(compare_field_b,
6365 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6366 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6367 					     b.class_id)),
6368 	},
6369 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6370 		.name = "b_offset",
6371 		.help = "comparator field bit offset",
6372 		.next = NEXT(compare_field_b,
6373 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6374 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6375 					b.offset)),
6376 	},
6377 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6378 		.name = "b_value",
6379 		.help = "comparator immediate value",
6380 		.next = NEXT(compare_field_b,
6381 			     NEXT_ENTRY(COMMON_HEX), item_param),
6382 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6383 			     ARGS_ENTRY_ARB(0, 0),
6384 			     ARGS_ENTRY(struct rte_flow_item_compare,
6385 					b.value)),
6386 	},
6387 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6388 		.name = "b_ptr",
6389 		.help = "pointer to comparator immediate value",
6390 		.next = NEXT(compare_field_b,
6391 			     NEXT_ENTRY(COMMON_HEX), item_param),
6392 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6393 					b.pvalue),
6394 			     ARGS_ENTRY_ARB(0, 0),
6395 			     ARGS_ENTRY_ARB
6396 				(sizeof(struct rte_flow_item_compare),
6397 				 FLOW_FIELD_PATTERN_SIZE)),
6398 	},
6399 	[ITEM_COMPARE_FIELD_WIDTH] = {
6400 		.name = "width",
6401 		.help = "number of bits to compare",
6402 		.next = NEXT(item_compare_field,
6403 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6404 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6405 					width)),
6406 	},
6407 
6408 	/* Validate/create actions. */
6409 	[ACTIONS] = {
6410 		.name = "actions",
6411 		.help = "submit a list of associated actions",
6412 		.next = NEXT(next_action),
6413 		.call = parse_vc,
6414 	},
6415 	[ACTION_NEXT] = {
6416 		.name = "/",
6417 		.help = "specify next action",
6418 		.next = NEXT(next_action),
6419 	},
6420 	[ACTION_END] = {
6421 		.name = "end",
6422 		.help = "end list of actions",
6423 		.priv = PRIV_ACTION(END, 0),
6424 		.call = parse_vc,
6425 	},
6426 	[ACTION_VOID] = {
6427 		.name = "void",
6428 		.help = "no-op action",
6429 		.priv = PRIV_ACTION(VOID, 0),
6430 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6431 		.call = parse_vc,
6432 	},
6433 	[ACTION_PASSTHRU] = {
6434 		.name = "passthru",
6435 		.help = "let subsequent rule process matched packets",
6436 		.priv = PRIV_ACTION(PASSTHRU, 0),
6437 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6438 		.call = parse_vc,
6439 	},
6440 	[ACTION_SKIP_CMAN] = {
6441 		.name = "skip_cman",
6442 		.help = "bypass cman on received packets",
6443 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6444 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6445 		.call = parse_vc,
6446 	},
6447 	[ACTION_JUMP] = {
6448 		.name = "jump",
6449 		.help = "redirect traffic to a given group",
6450 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6451 		.next = NEXT(action_jump),
6452 		.call = parse_vc,
6453 	},
6454 	[ACTION_JUMP_GROUP] = {
6455 		.name = "group",
6456 		.help = "group to redirect traffic to",
6457 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6458 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6459 		.call = parse_vc_conf,
6460 	},
6461 	[ACTION_MARK] = {
6462 		.name = "mark",
6463 		.help = "attach 32 bit value to packets",
6464 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6465 		.next = NEXT(action_mark),
6466 		.call = parse_vc,
6467 	},
6468 	[ACTION_MARK_ID] = {
6469 		.name = "id",
6470 		.help = "32 bit value to return with packets",
6471 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6472 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6473 		.call = parse_vc_conf,
6474 	},
6475 	[ACTION_FLAG] = {
6476 		.name = "flag",
6477 		.help = "flag packets",
6478 		.priv = PRIV_ACTION(FLAG, 0),
6479 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6480 		.call = parse_vc,
6481 	},
6482 	[ACTION_QUEUE] = {
6483 		.name = "queue",
6484 		.help = "assign packets to a given queue index",
6485 		.priv = PRIV_ACTION(QUEUE,
6486 				    sizeof(struct rte_flow_action_queue)),
6487 		.next = NEXT(action_queue),
6488 		.call = parse_vc,
6489 	},
6490 	[ACTION_QUEUE_INDEX] = {
6491 		.name = "index",
6492 		.help = "queue index to use",
6493 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6494 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6495 		.call = parse_vc_conf,
6496 	},
6497 	[ACTION_DROP] = {
6498 		.name = "drop",
6499 		.help = "drop packets (note: passthru has priority)",
6500 		.priv = PRIV_ACTION(DROP, 0),
6501 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6502 		.call = parse_vc,
6503 	},
6504 	[ACTION_COUNT] = {
6505 		.name = "count",
6506 		.help = "enable counters for this rule",
6507 		.priv = PRIV_ACTION(COUNT,
6508 				    sizeof(struct rte_flow_action_count)),
6509 		.next = NEXT(action_count),
6510 		.call = parse_vc,
6511 	},
6512 	[ACTION_COUNT_ID] = {
6513 		.name = "identifier",
6514 		.help = "counter identifier to use",
6515 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6516 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6517 		.call = parse_vc_conf,
6518 	},
6519 	[ACTION_RSS] = {
6520 		.name = "rss",
6521 		.help = "spread packets among several queues",
6522 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6523 		.next = NEXT(action_rss),
6524 		.call = parse_vc_action_rss,
6525 	},
6526 	[ACTION_RSS_FUNC] = {
6527 		.name = "func",
6528 		.help = "RSS hash function to apply",
6529 		.next = NEXT(action_rss,
6530 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6531 					ACTION_RSS_FUNC_TOEPLITZ,
6532 					ACTION_RSS_FUNC_SIMPLE_XOR,
6533 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6534 	},
6535 	[ACTION_RSS_FUNC_DEFAULT] = {
6536 		.name = "default",
6537 		.help = "default hash function",
6538 		.call = parse_vc_action_rss_func,
6539 	},
6540 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6541 		.name = "toeplitz",
6542 		.help = "Toeplitz hash function",
6543 		.call = parse_vc_action_rss_func,
6544 	},
6545 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6546 		.name = "simple_xor",
6547 		.help = "simple XOR hash function",
6548 		.call = parse_vc_action_rss_func,
6549 	},
6550 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6551 		.name = "symmetric_toeplitz",
6552 		.help = "Symmetric Toeplitz hash function",
6553 		.call = parse_vc_action_rss_func,
6554 	},
6555 	[ACTION_RSS_LEVEL] = {
6556 		.name = "level",
6557 		.help = "encapsulation level for \"types\"",
6558 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6559 		.args = ARGS(ARGS_ENTRY_ARB
6560 			     (offsetof(struct action_rss_data, conf) +
6561 			      offsetof(struct rte_flow_action_rss, level),
6562 			      sizeof(((struct rte_flow_action_rss *)0)->
6563 				     level))),
6564 	},
6565 	[ACTION_RSS_TYPES] = {
6566 		.name = "types",
6567 		.help = "specific RSS hash types",
6568 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6569 	},
6570 	[ACTION_RSS_TYPE] = {
6571 		.name = "{type}",
6572 		.help = "RSS hash type",
6573 		.call = parse_vc_action_rss_type,
6574 		.comp = comp_vc_action_rss_type,
6575 	},
6576 	[ACTION_RSS_KEY] = {
6577 		.name = "key",
6578 		.help = "RSS hash key",
6579 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6580 		.args = ARGS(ARGS_ENTRY_ARB
6581 			     (offsetof(struct action_rss_data, conf) +
6582 			      offsetof(struct rte_flow_action_rss, key),
6583 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6584 			     ARGS_ENTRY_ARB
6585 			     (offsetof(struct action_rss_data, conf) +
6586 			      offsetof(struct rte_flow_action_rss, key_len),
6587 			      sizeof(((struct rte_flow_action_rss *)0)->
6588 				     key_len)),
6589 			     ARGS_ENTRY(struct action_rss_data, key)),
6590 	},
6591 	[ACTION_RSS_KEY_LEN] = {
6592 		.name = "key_len",
6593 		.help = "RSS hash key length in bytes",
6594 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6595 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6596 			     (offsetof(struct action_rss_data, conf) +
6597 			      offsetof(struct rte_flow_action_rss, key_len),
6598 			      sizeof(((struct rte_flow_action_rss *)0)->
6599 				     key_len),
6600 			      0,
6601 			      RSS_HASH_KEY_LENGTH)),
6602 	},
6603 	[ACTION_RSS_QUEUES] = {
6604 		.name = "queues",
6605 		.help = "queue indices to use",
6606 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6607 		.call = parse_vc_conf,
6608 	},
6609 	[ACTION_RSS_QUEUE] = {
6610 		.name = "{queue}",
6611 		.help = "queue index",
6612 		.call = parse_vc_action_rss_queue,
6613 		.comp = comp_vc_action_rss_queue,
6614 	},
6615 	[ACTION_PF] = {
6616 		.name = "pf",
6617 		.help = "direct traffic to physical function",
6618 		.priv = PRIV_ACTION(PF, 0),
6619 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6620 		.call = parse_vc,
6621 	},
6622 	[ACTION_VF] = {
6623 		.name = "vf",
6624 		.help = "direct traffic to a virtual function ID",
6625 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6626 		.next = NEXT(action_vf),
6627 		.call = parse_vc,
6628 	},
6629 	[ACTION_VF_ORIGINAL] = {
6630 		.name = "original",
6631 		.help = "use original VF ID if possible",
6632 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6633 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6634 					   original, 1)),
6635 		.call = parse_vc_conf,
6636 	},
6637 	[ACTION_VF_ID] = {
6638 		.name = "id",
6639 		.help = "VF ID",
6640 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6641 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6642 		.call = parse_vc_conf,
6643 	},
6644 	[ACTION_PORT_ID] = {
6645 		.name = "port_id",
6646 		.help = "direct matching traffic to a given DPDK port ID",
6647 		.priv = PRIV_ACTION(PORT_ID,
6648 				    sizeof(struct rte_flow_action_port_id)),
6649 		.next = NEXT(action_port_id),
6650 		.call = parse_vc,
6651 	},
6652 	[ACTION_PORT_ID_ORIGINAL] = {
6653 		.name = "original",
6654 		.help = "use original DPDK port ID if possible",
6655 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6656 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6657 					   original, 1)),
6658 		.call = parse_vc_conf,
6659 	},
6660 	[ACTION_PORT_ID_ID] = {
6661 		.name = "id",
6662 		.help = "DPDK port ID",
6663 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6664 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6665 		.call = parse_vc_conf,
6666 	},
6667 	[ACTION_METER] = {
6668 		.name = "meter",
6669 		.help = "meter the directed packets at given id",
6670 		.priv = PRIV_ACTION(METER,
6671 				    sizeof(struct rte_flow_action_meter)),
6672 		.next = NEXT(action_meter),
6673 		.call = parse_vc,
6674 	},
6675 	[ACTION_METER_COLOR] = {
6676 		.name = "color",
6677 		.help = "meter color for the packets",
6678 		.priv = PRIV_ACTION(METER_COLOR,
6679 				sizeof(struct rte_flow_action_meter_color)),
6680 		.next = NEXT(action_meter_color),
6681 		.call = parse_vc,
6682 	},
6683 	[ACTION_METER_COLOR_TYPE] = {
6684 		.name = "type",
6685 		.help = "specific meter color",
6686 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6687 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6688 					ACTION_METER_COLOR_YELLOW,
6689 					ACTION_METER_COLOR_RED)),
6690 	},
6691 	[ACTION_METER_COLOR_GREEN] = {
6692 		.name = "green",
6693 		.help = "meter color green",
6694 		.call = parse_vc_action_meter_color_type,
6695 	},
6696 	[ACTION_METER_COLOR_YELLOW] = {
6697 		.name = "yellow",
6698 		.help = "meter color yellow",
6699 		.call = parse_vc_action_meter_color_type,
6700 	},
6701 	[ACTION_METER_COLOR_RED] = {
6702 		.name = "red",
6703 		.help = "meter color red",
6704 		.call = parse_vc_action_meter_color_type,
6705 	},
6706 	[ACTION_METER_ID] = {
6707 		.name = "mtr_id",
6708 		.help = "meter id to use",
6709 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6710 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6711 		.call = parse_vc_conf,
6712 	},
6713 	[ACTION_METER_MARK] = {
6714 		.name = "meter_mark",
6715 		.help = "meter the directed packets using profile and policy",
6716 		.priv = PRIV_ACTION(METER_MARK,
6717 				    sizeof(struct rte_flow_action_meter_mark)),
6718 		.next = NEXT(action_meter_mark),
6719 		.call = parse_vc,
6720 	},
6721 	[ACTION_METER_PROFILE] = {
6722 		.name = "mtr_profile",
6723 		.help = "meter profile id to use",
6724 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6725 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6726 	},
6727 	[ACTION_METER_PROFILE_ID2PTR] = {
6728 		.name = "{mtr_profile_id}",
6729 		.type = "PROFILE_ID",
6730 		.help = "meter profile id",
6731 		.next = NEXT(action_meter_mark),
6732 		.call = parse_meter_profile_id2ptr,
6733 		.comp = comp_none,
6734 	},
6735 	[ACTION_METER_POLICY] = {
6736 		.name = "mtr_policy",
6737 		.help = "meter policy id to use",
6738 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6739 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6740 	},
6741 	[ACTION_METER_POLICY_ID2PTR] = {
6742 		.name = "{mtr_policy_id}",
6743 		.type = "POLICY_ID",
6744 		.help = "meter policy id",
6745 		.next = NEXT(action_meter_mark),
6746 		.call = parse_meter_policy_id2ptr,
6747 		.comp = comp_none,
6748 	},
6749 	[ACTION_METER_COLOR_MODE] = {
6750 		.name = "mtr_color_mode",
6751 		.help = "meter color awareness mode",
6752 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6753 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6754 		.call = parse_vc_conf,
6755 	},
6756 	[ACTION_METER_STATE] = {
6757 		.name = "mtr_state",
6758 		.help = "meter state",
6759 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6760 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6761 		.call = parse_vc_conf,
6762 	},
6763 	[ACTION_OF_DEC_NW_TTL] = {
6764 		.name = "of_dec_nw_ttl",
6765 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6766 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6767 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6768 		.call = parse_vc,
6769 	},
6770 	[ACTION_OF_POP_VLAN] = {
6771 		.name = "of_pop_vlan",
6772 		.help = "OpenFlow's OFPAT_POP_VLAN",
6773 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6774 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6775 		.call = parse_vc,
6776 	},
6777 	[ACTION_OF_PUSH_VLAN] = {
6778 		.name = "of_push_vlan",
6779 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6780 		.priv = PRIV_ACTION
6781 			(OF_PUSH_VLAN,
6782 			 sizeof(struct rte_flow_action_of_push_vlan)),
6783 		.next = NEXT(action_of_push_vlan),
6784 		.call = parse_vc,
6785 	},
6786 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6787 		.name = "ethertype",
6788 		.help = "EtherType",
6789 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6790 		.args = ARGS(ARGS_ENTRY_HTON
6791 			     (struct rte_flow_action_of_push_vlan,
6792 			      ethertype)),
6793 		.call = parse_vc_conf,
6794 	},
6795 	[ACTION_OF_SET_VLAN_VID] = {
6796 		.name = "of_set_vlan_vid",
6797 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6798 		.priv = PRIV_ACTION
6799 			(OF_SET_VLAN_VID,
6800 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6801 		.next = NEXT(action_of_set_vlan_vid),
6802 		.call = parse_vc,
6803 	},
6804 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6805 		.name = "vlan_vid",
6806 		.help = "VLAN id",
6807 		.next = NEXT(action_of_set_vlan_vid,
6808 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6809 		.args = ARGS(ARGS_ENTRY_HTON
6810 			     (struct rte_flow_action_of_set_vlan_vid,
6811 			      vlan_vid)),
6812 		.call = parse_vc_conf,
6813 	},
6814 	[ACTION_OF_SET_VLAN_PCP] = {
6815 		.name = "of_set_vlan_pcp",
6816 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6817 		.priv = PRIV_ACTION
6818 			(OF_SET_VLAN_PCP,
6819 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6820 		.next = NEXT(action_of_set_vlan_pcp),
6821 		.call = parse_vc,
6822 	},
6823 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6824 		.name = "vlan_pcp",
6825 		.help = "VLAN priority",
6826 		.next = NEXT(action_of_set_vlan_pcp,
6827 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6828 		.args = ARGS(ARGS_ENTRY_HTON
6829 			     (struct rte_flow_action_of_set_vlan_pcp,
6830 			      vlan_pcp)),
6831 		.call = parse_vc_conf,
6832 	},
6833 	[ACTION_OF_POP_MPLS] = {
6834 		.name = "of_pop_mpls",
6835 		.help = "OpenFlow's OFPAT_POP_MPLS",
6836 		.priv = PRIV_ACTION(OF_POP_MPLS,
6837 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6838 		.next = NEXT(action_of_pop_mpls),
6839 		.call = parse_vc,
6840 	},
6841 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6842 		.name = "ethertype",
6843 		.help = "EtherType",
6844 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6845 		.args = ARGS(ARGS_ENTRY_HTON
6846 			     (struct rte_flow_action_of_pop_mpls,
6847 			      ethertype)),
6848 		.call = parse_vc_conf,
6849 	},
6850 	[ACTION_OF_PUSH_MPLS] = {
6851 		.name = "of_push_mpls",
6852 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6853 		.priv = PRIV_ACTION
6854 			(OF_PUSH_MPLS,
6855 			 sizeof(struct rte_flow_action_of_push_mpls)),
6856 		.next = NEXT(action_of_push_mpls),
6857 		.call = parse_vc,
6858 	},
6859 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6860 		.name = "ethertype",
6861 		.help = "EtherType",
6862 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6863 		.args = ARGS(ARGS_ENTRY_HTON
6864 			     (struct rte_flow_action_of_push_mpls,
6865 			      ethertype)),
6866 		.call = parse_vc_conf,
6867 	},
6868 	[ACTION_VXLAN_ENCAP] = {
6869 		.name = "vxlan_encap",
6870 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6871 			" vxlan\"",
6872 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6873 				    sizeof(struct action_vxlan_encap_data)),
6874 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6875 		.call = parse_vc_action_vxlan_encap,
6876 	},
6877 	[ACTION_VXLAN_DECAP] = {
6878 		.name = "vxlan_decap",
6879 		.help = "Performs a decapsulation action by stripping all"
6880 			" headers of the VXLAN tunnel network overlay from the"
6881 			" matched flow.",
6882 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6883 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6884 		.call = parse_vc,
6885 	},
6886 	[ACTION_NVGRE_ENCAP] = {
6887 		.name = "nvgre_encap",
6888 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6889 			" nvgre\"",
6890 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6891 				    sizeof(struct action_nvgre_encap_data)),
6892 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6893 		.call = parse_vc_action_nvgre_encap,
6894 	},
6895 	[ACTION_NVGRE_DECAP] = {
6896 		.name = "nvgre_decap",
6897 		.help = "Performs a decapsulation action by stripping all"
6898 			" headers of the NVGRE tunnel network overlay from the"
6899 			" matched flow.",
6900 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6901 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6902 		.call = parse_vc,
6903 	},
6904 	[ACTION_L2_ENCAP] = {
6905 		.name = "l2_encap",
6906 		.help = "l2 encap, uses configuration set by"
6907 			" \"set l2_encap\"",
6908 		.priv = PRIV_ACTION(RAW_ENCAP,
6909 				    sizeof(struct action_raw_encap_data)),
6910 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6911 		.call = parse_vc_action_l2_encap,
6912 	},
6913 	[ACTION_L2_DECAP] = {
6914 		.name = "l2_decap",
6915 		.help = "l2 decap, uses configuration set by"
6916 			" \"set l2_decap\"",
6917 		.priv = PRIV_ACTION(RAW_DECAP,
6918 				    sizeof(struct action_raw_decap_data)),
6919 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6920 		.call = parse_vc_action_l2_decap,
6921 	},
6922 	[ACTION_MPLSOGRE_ENCAP] = {
6923 		.name = "mplsogre_encap",
6924 		.help = "mplsogre encapsulation, uses configuration set by"
6925 			" \"set mplsogre_encap\"",
6926 		.priv = PRIV_ACTION(RAW_ENCAP,
6927 				    sizeof(struct action_raw_encap_data)),
6928 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6929 		.call = parse_vc_action_mplsogre_encap,
6930 	},
6931 	[ACTION_MPLSOGRE_DECAP] = {
6932 		.name = "mplsogre_decap",
6933 		.help = "mplsogre decapsulation, uses configuration set by"
6934 			" \"set mplsogre_decap\"",
6935 		.priv = PRIV_ACTION(RAW_DECAP,
6936 				    sizeof(struct action_raw_decap_data)),
6937 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6938 		.call = parse_vc_action_mplsogre_decap,
6939 	},
6940 	[ACTION_MPLSOUDP_ENCAP] = {
6941 		.name = "mplsoudp_encap",
6942 		.help = "mplsoudp encapsulation, uses configuration set by"
6943 			" \"set mplsoudp_encap\"",
6944 		.priv = PRIV_ACTION(RAW_ENCAP,
6945 				    sizeof(struct action_raw_encap_data)),
6946 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6947 		.call = parse_vc_action_mplsoudp_encap,
6948 	},
6949 	[ACTION_MPLSOUDP_DECAP] = {
6950 		.name = "mplsoudp_decap",
6951 		.help = "mplsoudp decapsulation, uses configuration set by"
6952 			" \"set mplsoudp_decap\"",
6953 		.priv = PRIV_ACTION(RAW_DECAP,
6954 				    sizeof(struct action_raw_decap_data)),
6955 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6956 		.call = parse_vc_action_mplsoudp_decap,
6957 	},
6958 	[ACTION_SET_IPV4_SRC] = {
6959 		.name = "set_ipv4_src",
6960 		.help = "Set a new IPv4 source address in the outermost"
6961 			" IPv4 header",
6962 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6963 			sizeof(struct rte_flow_action_set_ipv4)),
6964 		.next = NEXT(action_set_ipv4_src),
6965 		.call = parse_vc,
6966 	},
6967 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6968 		.name = "ipv4_addr",
6969 		.help = "new IPv4 source address to set",
6970 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6971 		.args = ARGS(ARGS_ENTRY_HTON
6972 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6973 		.call = parse_vc_conf,
6974 	},
6975 	[ACTION_SET_IPV4_DST] = {
6976 		.name = "set_ipv4_dst",
6977 		.help = "Set a new IPv4 destination address in the outermost"
6978 			" IPv4 header",
6979 		.priv = PRIV_ACTION(SET_IPV4_DST,
6980 			sizeof(struct rte_flow_action_set_ipv4)),
6981 		.next = NEXT(action_set_ipv4_dst),
6982 		.call = parse_vc,
6983 	},
6984 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6985 		.name = "ipv4_addr",
6986 		.help = "new IPv4 destination address to set",
6987 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6988 		.args = ARGS(ARGS_ENTRY_HTON
6989 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6990 		.call = parse_vc_conf,
6991 	},
6992 	[ACTION_SET_IPV6_SRC] = {
6993 		.name = "set_ipv6_src",
6994 		.help = "Set a new IPv6 source address in the outermost"
6995 			" IPv6 header",
6996 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6997 			sizeof(struct rte_flow_action_set_ipv6)),
6998 		.next = NEXT(action_set_ipv6_src),
6999 		.call = parse_vc,
7000 	},
7001 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7002 		.name = "ipv6_addr",
7003 		.help = "new IPv6 source address to set",
7004 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7005 		.args = ARGS(ARGS_ENTRY_HTON
7006 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7007 		.call = parse_vc_conf,
7008 	},
7009 	[ACTION_SET_IPV6_DST] = {
7010 		.name = "set_ipv6_dst",
7011 		.help = "Set a new IPv6 destination address in the outermost"
7012 			" IPv6 header",
7013 		.priv = PRIV_ACTION(SET_IPV6_DST,
7014 			sizeof(struct rte_flow_action_set_ipv6)),
7015 		.next = NEXT(action_set_ipv6_dst),
7016 		.call = parse_vc,
7017 	},
7018 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7019 		.name = "ipv6_addr",
7020 		.help = "new IPv6 destination address to set",
7021 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7022 		.args = ARGS(ARGS_ENTRY_HTON
7023 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7024 		.call = parse_vc_conf,
7025 	},
7026 	[ACTION_SET_TP_SRC] = {
7027 		.name = "set_tp_src",
7028 		.help = "set a new source port number in the outermost"
7029 			" TCP/UDP header",
7030 		.priv = PRIV_ACTION(SET_TP_SRC,
7031 			sizeof(struct rte_flow_action_set_tp)),
7032 		.next = NEXT(action_set_tp_src),
7033 		.call = parse_vc,
7034 	},
7035 	[ACTION_SET_TP_SRC_TP_SRC] = {
7036 		.name = "port",
7037 		.help = "new source port number to set",
7038 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7039 		.args = ARGS(ARGS_ENTRY_HTON
7040 			     (struct rte_flow_action_set_tp, port)),
7041 		.call = parse_vc_conf,
7042 	},
7043 	[ACTION_SET_TP_DST] = {
7044 		.name = "set_tp_dst",
7045 		.help = "set a new destination port number in the outermost"
7046 			" TCP/UDP header",
7047 		.priv = PRIV_ACTION(SET_TP_DST,
7048 			sizeof(struct rte_flow_action_set_tp)),
7049 		.next = NEXT(action_set_tp_dst),
7050 		.call = parse_vc,
7051 	},
7052 	[ACTION_SET_TP_DST_TP_DST] = {
7053 		.name = "port",
7054 		.help = "new destination port number to set",
7055 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7056 		.args = ARGS(ARGS_ENTRY_HTON
7057 			     (struct rte_flow_action_set_tp, port)),
7058 		.call = parse_vc_conf,
7059 	},
7060 	[ACTION_MAC_SWAP] = {
7061 		.name = "mac_swap",
7062 		.help = "Swap the source and destination MAC addresses"
7063 			" in the outermost Ethernet header",
7064 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7065 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7066 		.call = parse_vc,
7067 	},
7068 	[ACTION_DEC_TTL] = {
7069 		.name = "dec_ttl",
7070 		.help = "decrease network TTL if available",
7071 		.priv = PRIV_ACTION(DEC_TTL, 0),
7072 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7073 		.call = parse_vc,
7074 	},
7075 	[ACTION_SET_TTL] = {
7076 		.name = "set_ttl",
7077 		.help = "set ttl value",
7078 		.priv = PRIV_ACTION(SET_TTL,
7079 			sizeof(struct rte_flow_action_set_ttl)),
7080 		.next = NEXT(action_set_ttl),
7081 		.call = parse_vc,
7082 	},
7083 	[ACTION_SET_TTL_TTL] = {
7084 		.name = "ttl_value",
7085 		.help = "new ttl value to set",
7086 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7087 		.args = ARGS(ARGS_ENTRY_HTON
7088 			     (struct rte_flow_action_set_ttl, ttl_value)),
7089 		.call = parse_vc_conf,
7090 	},
7091 	[ACTION_SET_MAC_SRC] = {
7092 		.name = "set_mac_src",
7093 		.help = "set source mac address",
7094 		.priv = PRIV_ACTION(SET_MAC_SRC,
7095 			sizeof(struct rte_flow_action_set_mac)),
7096 		.next = NEXT(action_set_mac_src),
7097 		.call = parse_vc,
7098 	},
7099 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7100 		.name = "mac_addr",
7101 		.help = "new source mac address",
7102 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7103 		.args = ARGS(ARGS_ENTRY_HTON
7104 			     (struct rte_flow_action_set_mac, mac_addr)),
7105 		.call = parse_vc_conf,
7106 	},
7107 	[ACTION_SET_MAC_DST] = {
7108 		.name = "set_mac_dst",
7109 		.help = "set destination mac address",
7110 		.priv = PRIV_ACTION(SET_MAC_DST,
7111 			sizeof(struct rte_flow_action_set_mac)),
7112 		.next = NEXT(action_set_mac_dst),
7113 		.call = parse_vc,
7114 	},
7115 	[ACTION_SET_MAC_DST_MAC_DST] = {
7116 		.name = "mac_addr",
7117 		.help = "new destination mac address to set",
7118 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7119 		.args = ARGS(ARGS_ENTRY_HTON
7120 			     (struct rte_flow_action_set_mac, mac_addr)),
7121 		.call = parse_vc_conf,
7122 	},
7123 	[ACTION_INC_TCP_SEQ] = {
7124 		.name = "inc_tcp_seq",
7125 		.help = "increase TCP sequence number",
7126 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7127 		.next = NEXT(action_inc_tcp_seq),
7128 		.call = parse_vc,
7129 	},
7130 	[ACTION_INC_TCP_SEQ_VALUE] = {
7131 		.name = "value",
7132 		.help = "the value to increase TCP sequence number by",
7133 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7134 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7135 		.call = parse_vc_conf,
7136 	},
7137 	[ACTION_DEC_TCP_SEQ] = {
7138 		.name = "dec_tcp_seq",
7139 		.help = "decrease TCP sequence number",
7140 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7141 		.next = NEXT(action_dec_tcp_seq),
7142 		.call = parse_vc,
7143 	},
7144 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7145 		.name = "value",
7146 		.help = "the value to decrease TCP sequence number by",
7147 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7148 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7149 		.call = parse_vc_conf,
7150 	},
7151 	[ACTION_INC_TCP_ACK] = {
7152 		.name = "inc_tcp_ack",
7153 		.help = "increase TCP acknowledgment number",
7154 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7155 		.next = NEXT(action_inc_tcp_ack),
7156 		.call = parse_vc,
7157 	},
7158 	[ACTION_INC_TCP_ACK_VALUE] = {
7159 		.name = "value",
7160 		.help = "the value to increase TCP acknowledgment number by",
7161 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7162 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7163 		.call = parse_vc_conf,
7164 	},
7165 	[ACTION_DEC_TCP_ACK] = {
7166 		.name = "dec_tcp_ack",
7167 		.help = "decrease TCP acknowledgment number",
7168 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7169 		.next = NEXT(action_dec_tcp_ack),
7170 		.call = parse_vc,
7171 	},
7172 	[ACTION_DEC_TCP_ACK_VALUE] = {
7173 		.name = "value",
7174 		.help = "the value to decrease TCP acknowledgment number by",
7175 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7176 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7177 		.call = parse_vc_conf,
7178 	},
7179 	[ACTION_RAW_ENCAP] = {
7180 		.name = "raw_encap",
7181 		.help = "encapsulation data, defined by set raw_encap",
7182 		.priv = PRIV_ACTION(RAW_ENCAP,
7183 			sizeof(struct action_raw_encap_data)),
7184 		.next = NEXT(action_raw_encap),
7185 		.call = parse_vc_action_raw_encap,
7186 	},
7187 	[ACTION_RAW_ENCAP_SIZE] = {
7188 		.name = "size",
7189 		.help = "raw encap size",
7190 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7191 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7192 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7193 		.call = parse_vc_conf,
7194 	},
7195 	[ACTION_RAW_ENCAP_INDEX] = {
7196 		.name = "index",
7197 		.help = "the index of raw_encap_confs",
7198 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7199 	},
7200 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7201 		.name = "{index}",
7202 		.type = "UNSIGNED",
7203 		.help = "unsigned integer value",
7204 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7205 		.call = parse_vc_action_raw_encap_index,
7206 		.comp = comp_set_raw_index,
7207 	},
7208 	[ACTION_RAW_DECAP] = {
7209 		.name = "raw_decap",
7210 		.help = "decapsulation data, defined by set raw_encap",
7211 		.priv = PRIV_ACTION(RAW_DECAP,
7212 			sizeof(struct action_raw_decap_data)),
7213 		.next = NEXT(action_raw_decap),
7214 		.call = parse_vc_action_raw_decap,
7215 	},
7216 	[ACTION_RAW_DECAP_INDEX] = {
7217 		.name = "index",
7218 		.help = "the index of raw_encap_confs",
7219 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7220 	},
7221 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7222 		.name = "{index}",
7223 		.type = "UNSIGNED",
7224 		.help = "unsigned integer value",
7225 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7226 		.call = parse_vc_action_raw_decap_index,
7227 		.comp = comp_set_raw_index,
7228 	},
7229 	[ACTION_MODIFY_FIELD] = {
7230 		.name = "modify_field",
7231 		.help = "modify destination field with data from source field",
7232 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7233 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7234 		.call = parse_vc,
7235 	},
7236 	[ACTION_MODIFY_FIELD_OP] = {
7237 		.name = "op",
7238 		.help = "operation type",
7239 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7240 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7241 		.call = parse_vc_conf,
7242 	},
7243 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7244 		.name = "{operation}",
7245 		.help = "operation type value",
7246 		.call = parse_vc_modify_field_op,
7247 		.comp = comp_set_modify_field_op,
7248 	},
7249 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7250 		.name = "dst_type",
7251 		.help = "destination field type",
7252 		.next = NEXT(action_modify_field_dst,
7253 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7254 		.call = parse_vc_conf,
7255 	},
7256 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7257 		.name = "{dst_type}",
7258 		.help = "destination field type value",
7259 		.call = parse_vc_modify_field_id,
7260 		.comp = comp_set_modify_field_id,
7261 	},
7262 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7263 		.name = "dst_level",
7264 		.help = "destination field level",
7265 		.next = NEXT(action_modify_field_dst,
7266 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7267 		.call = parse_vc_conf,
7268 	},
7269 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7270 		.name = "{dst_level}",
7271 		.help = "destination field level value",
7272 		.call = parse_vc_modify_field_level,
7273 		.comp = comp_none,
7274 	},
7275 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7276 		.name = "dst_tag_index",
7277 		.help = "destination field tag array",
7278 		.next = NEXT(action_modify_field_dst,
7279 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7280 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7281 					dst.tag_index)),
7282 		.call = parse_vc_conf,
7283 	},
7284 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7285 		.name = "dst_type_id",
7286 		.help = "destination field type ID",
7287 		.next = NEXT(action_modify_field_dst,
7288 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7289 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7290 					dst.type)),
7291 		.call = parse_vc_conf,
7292 	},
7293 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7294 		.name = "dst_class",
7295 		.help = "destination field class ID",
7296 		.next = NEXT(action_modify_field_dst,
7297 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7298 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7299 					     dst.class_id)),
7300 		.call = parse_vc_conf,
7301 	},
7302 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7303 		.name = "dst_offset",
7304 		.help = "destination field bit offset",
7305 		.next = NEXT(action_modify_field_dst,
7306 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7307 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7308 					dst.offset)),
7309 		.call = parse_vc_conf,
7310 	},
7311 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7312 		.name = "src_type",
7313 		.help = "source field type",
7314 		.next = NEXT(action_modify_field_src,
7315 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7316 		.call = parse_vc_conf,
7317 	},
7318 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7319 		.name = "{src_type}",
7320 		.help = "source field type value",
7321 		.call = parse_vc_modify_field_id,
7322 		.comp = comp_set_modify_field_id,
7323 	},
7324 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7325 		.name = "src_level",
7326 		.help = "source field level",
7327 		.next = NEXT(action_modify_field_src,
7328 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7329 		.call = parse_vc_conf,
7330 	},
7331 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7332 		.name = "{src_level}",
7333 		.help = "source field level value",
7334 		.call = parse_vc_modify_field_level,
7335 		.comp = comp_none,
7336 	},
7337 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7338 		.name = "src_tag_index",
7339 		.help = "source field tag array",
7340 		.next = NEXT(action_modify_field_src,
7341 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7342 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7343 					src.tag_index)),
7344 		.call = parse_vc_conf,
7345 	},
7346 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7347 		.name = "src_type_id",
7348 		.help = "source field type ID",
7349 		.next = NEXT(action_modify_field_src,
7350 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7351 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7352 					src.type)),
7353 		.call = parse_vc_conf,
7354 	},
7355 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7356 		.name = "src_class",
7357 		.help = "source field class ID",
7358 		.next = NEXT(action_modify_field_src,
7359 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7360 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7361 					     src.class_id)),
7362 		.call = parse_vc_conf,
7363 	},
7364 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7365 		.name = "src_offset",
7366 		.help = "source field bit offset",
7367 		.next = NEXT(action_modify_field_src,
7368 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7369 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7370 					src.offset)),
7371 		.call = parse_vc_conf,
7372 	},
7373 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7374 		.name = "src_value",
7375 		.help = "source immediate value",
7376 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7377 			     NEXT_ENTRY(COMMON_HEX)),
7378 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7379 			     ARGS_ENTRY_ARB(0, 0),
7380 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7381 					src.value)),
7382 		.call = parse_vc_conf,
7383 	},
7384 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7385 		.name = "src_ptr",
7386 		.help = "pointer to source immediate value",
7387 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7388 			     NEXT_ENTRY(COMMON_HEX)),
7389 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7390 					src.pvalue),
7391 			     ARGS_ENTRY_ARB(0, 0),
7392 			     ARGS_ENTRY_ARB
7393 				(sizeof(struct rte_flow_action_modify_field),
7394 				 FLOW_FIELD_PATTERN_SIZE)),
7395 		.call = parse_vc_conf,
7396 	},
7397 	[ACTION_MODIFY_FIELD_WIDTH] = {
7398 		.name = "width",
7399 		.help = "number of bits to copy",
7400 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7401 			NEXT_ENTRY(COMMON_UNSIGNED)),
7402 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7403 					width)),
7404 		.call = parse_vc_conf,
7405 	},
7406 	[ACTION_SEND_TO_KERNEL] = {
7407 		.name = "send_to_kernel",
7408 		.help = "send packets to kernel",
7409 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7410 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7411 		.call = parse_vc,
7412 	},
7413 	[ACTION_IPV6_EXT_REMOVE] = {
7414 		.name = "ipv6_ext_remove",
7415 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7416 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7417 			sizeof(struct action_ipv6_ext_remove_data)),
7418 		.next = NEXT(action_ipv6_ext_remove),
7419 		.call = parse_vc_action_ipv6_ext_remove,
7420 	},
7421 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7422 		.name = "index",
7423 		.help = "the index of ipv6_ext_remove",
7424 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7425 	},
7426 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7427 		.name = "{index}",
7428 		.type = "UNSIGNED",
7429 		.help = "unsigned integer value",
7430 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7431 		.call = parse_vc_action_ipv6_ext_remove_index,
7432 		.comp = comp_set_ipv6_ext_index,
7433 	},
7434 	[ACTION_IPV6_EXT_PUSH] = {
7435 		.name = "ipv6_ext_push",
7436 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7437 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7438 			sizeof(struct action_ipv6_ext_push_data)),
7439 		.next = NEXT(action_ipv6_ext_push),
7440 		.call = parse_vc_action_ipv6_ext_push,
7441 	},
7442 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7443 		.name = "index",
7444 		.help = "the index of ipv6_ext_push",
7445 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7446 	},
7447 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7448 		.name = "{index}",
7449 		.type = "UNSIGNED",
7450 		.help = "unsigned integer value",
7451 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7452 		.call = parse_vc_action_ipv6_ext_push_index,
7453 		.comp = comp_set_ipv6_ext_index,
7454 	},
7455 	[ACTION_NAT64] = {
7456 		.name = "nat64",
7457 		.help = "NAT64 IP headers translation",
7458 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7459 		.next = NEXT(action_nat64),
7460 		.call = parse_vc,
7461 	},
7462 	[ACTION_NAT64_MODE] = {
7463 		.name = "type",
7464 		.help = "NAT64 translation type",
7465 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7466 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7467 		.call = parse_vc_conf,
7468 	},
7469 	/* Top level command. */
7470 	[SET] = {
7471 		.name = "set",
7472 		.help = "set raw encap/decap/sample data",
7473 		.type = "set raw_encap|raw_decap <index> <pattern>"
7474 				" or set sample_actions <index> <action>",
7475 		.next = NEXT(NEXT_ENTRY
7476 			     (SET_RAW_ENCAP,
7477 			      SET_RAW_DECAP,
7478 			      SET_SAMPLE_ACTIONS,
7479 			      SET_IPV6_EXT_REMOVE,
7480 			      SET_IPV6_EXT_PUSH)),
7481 		.call = parse_set_init,
7482 	},
7483 	/* Sub-level commands. */
7484 	[SET_RAW_ENCAP] = {
7485 		.name = "raw_encap",
7486 		.help = "set raw encap data",
7487 		.next = NEXT(next_set_raw),
7488 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7489 				(offsetof(struct buffer, port),
7490 				 sizeof(((struct buffer *)0)->port),
7491 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7492 		.call = parse_set_raw_encap_decap,
7493 	},
7494 	[SET_RAW_DECAP] = {
7495 		.name = "raw_decap",
7496 		.help = "set raw decap data",
7497 		.next = NEXT(next_set_raw),
7498 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7499 				(offsetof(struct buffer, port),
7500 				 sizeof(((struct buffer *)0)->port),
7501 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7502 		.call = parse_set_raw_encap_decap,
7503 	},
7504 	[SET_RAW_INDEX] = {
7505 		.name = "{index}",
7506 		.type = "COMMON_UNSIGNED",
7507 		.help = "index of raw_encap/raw_decap data",
7508 		.next = NEXT(next_item),
7509 		.call = parse_port,
7510 	},
7511 	[SET_SAMPLE_INDEX] = {
7512 		.name = "{index}",
7513 		.type = "UNSIGNED",
7514 		.help = "index of sample actions",
7515 		.next = NEXT(next_action_sample),
7516 		.call = parse_port,
7517 	},
7518 	[SET_SAMPLE_ACTIONS] = {
7519 		.name = "sample_actions",
7520 		.help = "set sample actions list",
7521 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7522 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7523 				(offsetof(struct buffer, port),
7524 				 sizeof(((struct buffer *)0)->port),
7525 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7526 		.call = parse_set_sample_action,
7527 	},
7528 	[SET_IPV6_EXT_PUSH] = {
7529 		.name = "ipv6_ext_push",
7530 		.help = "set IPv6 extension header",
7531 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7532 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7533 				(offsetof(struct buffer, port),
7534 				 sizeof(((struct buffer *)0)->port),
7535 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7536 		.call = parse_set_ipv6_ext_action,
7537 	},
7538 	[SET_IPV6_EXT_REMOVE] = {
7539 		.name = "ipv6_ext_remove",
7540 		.help = "set IPv6 extension header",
7541 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7542 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7543 				(offsetof(struct buffer, port),
7544 				 sizeof(((struct buffer *)0)->port),
7545 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7546 		.call = parse_set_ipv6_ext_action,
7547 	},
7548 	[SET_IPV6_EXT_INDEX] = {
7549 		.name = "{index}",
7550 		.type = "UNSIGNED",
7551 		.help = "index of ipv6 extension push/remove actions",
7552 		.next = NEXT(item_ipv6_push_ext),
7553 		.call = parse_port,
7554 	},
7555 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7556 		.name = "ipv6_ext",
7557 		.help = "set IPv6 extension header",
7558 		.priv = PRIV_ITEM(IPV6_EXT,
7559 				  sizeof(struct rte_flow_item_ipv6_ext)),
7560 		.next = NEXT(item_ipv6_push_ext_type),
7561 		.call = parse_vc,
7562 	},
7563 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7564 		.name = "type",
7565 		.help = "set IPv6 extension type",
7566 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7567 					     next_hdr)),
7568 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7569 			     item_param),
7570 	},
7571 	[ACTION_SET_TAG] = {
7572 		.name = "set_tag",
7573 		.help = "set tag",
7574 		.priv = PRIV_ACTION(SET_TAG,
7575 			sizeof(struct rte_flow_action_set_tag)),
7576 		.next = NEXT(action_set_tag),
7577 		.call = parse_vc,
7578 	},
7579 	[ACTION_SET_TAG_INDEX] = {
7580 		.name = "index",
7581 		.help = "index of tag array",
7582 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7583 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7584 		.call = parse_vc_conf,
7585 	},
7586 	[ACTION_SET_TAG_DATA] = {
7587 		.name = "data",
7588 		.help = "tag value",
7589 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7590 		.args = ARGS(ARGS_ENTRY
7591 			     (struct rte_flow_action_set_tag, data)),
7592 		.call = parse_vc_conf,
7593 	},
7594 	[ACTION_SET_TAG_MASK] = {
7595 		.name = "mask",
7596 		.help = "mask for tag value",
7597 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7598 		.args = ARGS(ARGS_ENTRY
7599 			     (struct rte_flow_action_set_tag, mask)),
7600 		.call = parse_vc_conf,
7601 	},
7602 	[ACTION_SET_META] = {
7603 		.name = "set_meta",
7604 		.help = "set metadata",
7605 		.priv = PRIV_ACTION(SET_META,
7606 			sizeof(struct rte_flow_action_set_meta)),
7607 		.next = NEXT(action_set_meta),
7608 		.call = parse_vc_action_set_meta,
7609 	},
7610 	[ACTION_SET_META_DATA] = {
7611 		.name = "data",
7612 		.help = "metadata value",
7613 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7614 		.args = ARGS(ARGS_ENTRY
7615 			     (struct rte_flow_action_set_meta, data)),
7616 		.call = parse_vc_conf,
7617 	},
7618 	[ACTION_SET_META_MASK] = {
7619 		.name = "mask",
7620 		.help = "mask for metadata value",
7621 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7622 		.args = ARGS(ARGS_ENTRY
7623 			     (struct rte_flow_action_set_meta, mask)),
7624 		.call = parse_vc_conf,
7625 	},
7626 	[ACTION_SET_IPV4_DSCP] = {
7627 		.name = "set_ipv4_dscp",
7628 		.help = "set DSCP value",
7629 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7630 			sizeof(struct rte_flow_action_set_dscp)),
7631 		.next = NEXT(action_set_ipv4_dscp),
7632 		.call = parse_vc,
7633 	},
7634 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7635 		.name = "dscp_value",
7636 		.help = "new IPv4 DSCP value to set",
7637 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7638 		.args = ARGS(ARGS_ENTRY
7639 			     (struct rte_flow_action_set_dscp, dscp)),
7640 		.call = parse_vc_conf,
7641 	},
7642 	[ACTION_SET_IPV6_DSCP] = {
7643 		.name = "set_ipv6_dscp",
7644 		.help = "set DSCP value",
7645 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7646 			sizeof(struct rte_flow_action_set_dscp)),
7647 		.next = NEXT(action_set_ipv6_dscp),
7648 		.call = parse_vc,
7649 	},
7650 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7651 		.name = "dscp_value",
7652 		.help = "new IPv6 DSCP value to set",
7653 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7654 		.args = ARGS(ARGS_ENTRY
7655 			     (struct rte_flow_action_set_dscp, dscp)),
7656 		.call = parse_vc_conf,
7657 	},
7658 	[ACTION_AGE] = {
7659 		.name = "age",
7660 		.help = "set a specific metadata header",
7661 		.next = NEXT(action_age),
7662 		.priv = PRIV_ACTION(AGE,
7663 			sizeof(struct rte_flow_action_age)),
7664 		.call = parse_vc,
7665 	},
7666 	[ACTION_AGE_TIMEOUT] = {
7667 		.name = "timeout",
7668 		.help = "flow age timeout value",
7669 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7670 					   timeout, 24)),
7671 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7672 		.call = parse_vc_conf,
7673 	},
7674 	[ACTION_AGE_UPDATE] = {
7675 		.name = "age_update",
7676 		.help = "update aging parameter",
7677 		.next = NEXT(action_age_update),
7678 		.priv = PRIV_ACTION(AGE,
7679 				    sizeof(struct rte_flow_update_age)),
7680 		.call = parse_vc,
7681 	},
7682 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7683 		.name = "timeout",
7684 		.help = "age timeout update value",
7685 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7686 					   timeout, 24)),
7687 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7688 		.call = parse_vc_conf_timeout,
7689 	},
7690 	[ACTION_AGE_UPDATE_TOUCH] = {
7691 		.name = "touch",
7692 		.help = "this flow is touched",
7693 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7694 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7695 					   touch, 1)),
7696 		.call = parse_vc_conf,
7697 	},
7698 	[ACTION_SAMPLE] = {
7699 		.name = "sample",
7700 		.help = "set a sample action",
7701 		.next = NEXT(action_sample),
7702 		.priv = PRIV_ACTION(SAMPLE,
7703 			sizeof(struct action_sample_data)),
7704 		.call = parse_vc_action_sample,
7705 	},
7706 	[ACTION_SAMPLE_RATIO] = {
7707 		.name = "ratio",
7708 		.help = "flow sample ratio value",
7709 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7710 		.args = ARGS(ARGS_ENTRY_ARB
7711 			     (offsetof(struct action_sample_data, conf) +
7712 			      offsetof(struct rte_flow_action_sample, ratio),
7713 			      sizeof(((struct rte_flow_action_sample *)0)->
7714 				     ratio))),
7715 	},
7716 	[ACTION_SAMPLE_INDEX] = {
7717 		.name = "index",
7718 		.help = "the index of sample actions list",
7719 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7720 	},
7721 	[ACTION_SAMPLE_INDEX_VALUE] = {
7722 		.name = "{index}",
7723 		.type = "COMMON_UNSIGNED",
7724 		.help = "unsigned integer value",
7725 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7726 		.call = parse_vc_action_sample_index,
7727 		.comp = comp_set_sample_index,
7728 	},
7729 	[ACTION_CONNTRACK] = {
7730 		.name = "conntrack",
7731 		.help = "create a conntrack object",
7732 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7733 		.priv = PRIV_ACTION(CONNTRACK,
7734 				    sizeof(struct rte_flow_action_conntrack)),
7735 		.call = parse_vc,
7736 	},
7737 	[ACTION_CONNTRACK_UPDATE] = {
7738 		.name = "conntrack_update",
7739 		.help = "update a conntrack object",
7740 		.next = NEXT(action_update_conntrack),
7741 		.priv = PRIV_ACTION(CONNTRACK,
7742 				    sizeof(struct rte_flow_modify_conntrack)),
7743 		.call = parse_vc,
7744 	},
7745 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7746 		.name = "dir",
7747 		.help = "update a conntrack object direction",
7748 		.next = NEXT(action_update_conntrack),
7749 		.call = parse_vc_action_conntrack_update,
7750 	},
7751 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7752 		.name = "ctx",
7753 		.help = "update a conntrack object context",
7754 		.next = NEXT(action_update_conntrack),
7755 		.call = parse_vc_action_conntrack_update,
7756 	},
7757 	[ACTION_PORT_REPRESENTOR] = {
7758 		.name = "port_representor",
7759 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7760 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7761 				    sizeof(struct rte_flow_action_ethdev)),
7762 		.next = NEXT(action_port_representor),
7763 		.call = parse_vc,
7764 	},
7765 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7766 		.name = "port_id",
7767 		.help = "ethdev port ID",
7768 		.next = NEXT(action_port_representor,
7769 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7770 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7771 					port_id)),
7772 		.call = parse_vc_conf,
7773 	},
7774 	[ACTION_REPRESENTED_PORT] = {
7775 		.name = "represented_port",
7776 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7777 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7778 				sizeof(struct rte_flow_action_ethdev)),
7779 		.next = NEXT(action_represented_port),
7780 		.call = parse_vc,
7781 	},
7782 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7783 		.name = "ethdev_port_id",
7784 		.help = "ethdev port ID",
7785 		.next = NEXT(action_represented_port,
7786 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7787 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7788 					port_id)),
7789 		.call = parse_vc_conf,
7790 	},
7791 	/* Indirect action destroy arguments. */
7792 	[INDIRECT_ACTION_DESTROY_ID] = {
7793 		.name = "action_id",
7794 		.help = "specify a indirect action id to destroy",
7795 		.next = NEXT(next_ia_destroy_attr,
7796 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7797 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7798 					    args.ia_destroy.action_id)),
7799 		.call = parse_ia_destroy,
7800 	},
7801 	/* Indirect action create arguments. */
7802 	[INDIRECT_ACTION_CREATE_ID] = {
7803 		.name = "action_id",
7804 		.help = "specify a indirect action id to create",
7805 		.next = NEXT(next_ia_create_attr,
7806 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7807 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7808 	},
7809 	[ACTION_INDIRECT] = {
7810 		.name = "indirect",
7811 		.help = "apply indirect action by id",
7812 		.priv = PRIV_ACTION(INDIRECT, 0),
7813 		.next = NEXT(next_ia),
7814 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7815 		.call = parse_vc,
7816 	},
7817 	[ACTION_INDIRECT_LIST] = {
7818 		.name = "indirect_list",
7819 		.help = "apply indirect list action by id",
7820 		.priv = PRIV_ACTION(INDIRECT_LIST,
7821 				    sizeof(struct
7822 					   rte_flow_action_indirect_list)),
7823 		.next = NEXT(next_ial),
7824 		.call = parse_vc,
7825 	},
7826 	[ACTION_INDIRECT_LIST_HANDLE] = {
7827 		.name = "handle",
7828 		.help = "indirect list handle",
7829 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7830 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7831 	},
7832 	[ACTION_INDIRECT_LIST_CONF] = {
7833 		.name = "conf",
7834 		.help = "indirect list configuration",
7835 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7836 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7837 	},
7838 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7839 		.type = "UNSIGNED",
7840 		.help = "unsigned integer value",
7841 		.call = parse_indlst_id2ptr,
7842 		.comp = comp_none,
7843 	},
7844 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7845 		.type = "UNSIGNED",
7846 		.help = "unsigned integer value",
7847 		.call = parse_indlst_id2ptr,
7848 		.comp = comp_none,
7849 	},
7850 	[ACTION_SHARED_INDIRECT] = {
7851 		.name = "shared_indirect",
7852 		.help = "apply indirect action by id and port",
7853 		.priv = PRIV_ACTION(INDIRECT, 0),
7854 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7855 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7856 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7857 		.call = parse_vc,
7858 	},
7859 	[INDIRECT_ACTION_PORT] = {
7860 		.name = "{indirect_action_port}",
7861 		.type = "INDIRECT_ACTION_PORT",
7862 		.help = "indirect action port",
7863 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7864 		.call = parse_ia_port,
7865 		.comp = comp_none,
7866 	},
7867 	[INDIRECT_ACTION_ID2PTR] = {
7868 		.name = "{action_id}",
7869 		.type = "INDIRECT_ACTION_ID",
7870 		.help = "indirect action id",
7871 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7872 		.call = parse_ia_id2ptr,
7873 		.comp = comp_none,
7874 	},
7875 	[INDIRECT_ACTION_INGRESS] = {
7876 		.name = "ingress",
7877 		.help = "affect rule to ingress",
7878 		.next = NEXT(next_ia_create_attr),
7879 		.call = parse_ia,
7880 	},
7881 	[INDIRECT_ACTION_EGRESS] = {
7882 		.name = "egress",
7883 		.help = "affect rule to egress",
7884 		.next = NEXT(next_ia_create_attr),
7885 		.call = parse_ia,
7886 	},
7887 	[INDIRECT_ACTION_TRANSFER] = {
7888 		.name = "transfer",
7889 		.help = "affect rule to transfer",
7890 		.next = NEXT(next_ia_create_attr),
7891 		.call = parse_ia,
7892 	},
7893 	[INDIRECT_ACTION_SPEC] = {
7894 		.name = "action",
7895 		.help = "specify action to create indirect handle",
7896 		.next = NEXT(next_action),
7897 	},
7898 	[INDIRECT_ACTION_LIST] = {
7899 		.name = "list",
7900 		.help = "specify actions for indirect handle list",
7901 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7902 		.call = parse_ia,
7903 	},
7904 	[INDIRECT_ACTION_FLOW_CONF] = {
7905 		.name = "flow_conf",
7906 		.help = "specify actions configuration for indirect handle list",
7907 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7908 		.call = parse_ia,
7909 	},
7910 	[ACTION_POL_G] = {
7911 		.name = "g_actions",
7912 		.help = "submit a list of associated actions for green",
7913 		.next = NEXT(next_action),
7914 		.call = parse_mp,
7915 	},
7916 	[ACTION_POL_Y] = {
7917 		.name = "y_actions",
7918 		.help = "submit a list of associated actions for yellow",
7919 		.next = NEXT(next_action),
7920 	},
7921 	[ACTION_POL_R] = {
7922 		.name = "r_actions",
7923 		.help = "submit a list of associated actions for red",
7924 		.next = NEXT(next_action),
7925 	},
7926 	[ACTION_QUOTA_CREATE] = {
7927 		.name = "quota_create",
7928 		.help = "create quota action",
7929 		.priv = PRIV_ACTION(QUOTA,
7930 				    sizeof(struct rte_flow_action_quota)),
7931 		.next = NEXT(action_quota_create),
7932 		.call = parse_vc
7933 	},
7934 	[ACTION_QUOTA_CREATE_LIMIT] = {
7935 		.name = "limit",
7936 		.help = "quota limit",
7937 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
7938 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
7939 		.call = parse_vc_conf
7940 	},
7941 	[ACTION_QUOTA_CREATE_MODE] = {
7942 		.name = "mode",
7943 		.help = "quota mode",
7944 		.next = NEXT(action_quota_create,
7945 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
7946 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
7947 		.call = parse_vc_conf
7948 	},
7949 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
7950 		.name = "mode_name",
7951 		.help = "quota mode name",
7952 		.call = parse_quota_mode_name,
7953 		.comp = comp_quota_mode_name
7954 	},
7955 	[ACTION_QUOTA_QU] = {
7956 		.name = "quota_update",
7957 		.help = "update quota action",
7958 		.priv = PRIV_ACTION(QUOTA,
7959 				    sizeof(struct rte_flow_update_quota)),
7960 		.next = NEXT(action_quota_update),
7961 		.call = parse_vc
7962 	},
7963 	[ACTION_QUOTA_QU_LIMIT] = {
7964 		.name = "limit",
7965 		.help = "quota limit",
7966 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7967 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
7968 		.call = parse_vc_conf
7969 	},
7970 	[ACTION_QUOTA_QU_UPDATE_OP] = {
7971 		.name = "update_op",
7972 		.help = "query update op SET|ADD",
7973 		.next = NEXT(action_quota_update,
7974 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
7975 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
7976 		.call = parse_vc_conf
7977 	},
7978 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
7979 		.name = "update_op_name",
7980 		.help = "quota update op name",
7981 		.call = parse_quota_update_name,
7982 		.comp = comp_quota_update_name
7983 	},
7984 
7985 	/* Top-level command. */
7986 	[ADD] = {
7987 		.name = "add",
7988 		.type = "port meter policy {port_id} {arg}",
7989 		.help = "add port meter policy",
7990 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
7991 		.call = parse_init,
7992 	},
7993 	/* Sub-level commands. */
7994 	[ITEM_POL_PORT] = {
7995 		.name = "port",
7996 		.help = "add port meter policy",
7997 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
7998 	},
7999 	[ITEM_POL_METER] = {
8000 		.name = "meter",
8001 		.help = "add port meter policy",
8002 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8003 	},
8004 	[ITEM_POL_POLICY] = {
8005 		.name = "policy",
8006 		.help = "add port meter policy",
8007 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8008 				NEXT_ENTRY(ACTION_POL_Y),
8009 				NEXT_ENTRY(ACTION_POL_G),
8010 				NEXT_ENTRY(COMMON_POLICY_ID),
8011 				NEXT_ENTRY(COMMON_PORT_ID)),
8012 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8013 				ARGS_ENTRY(struct buffer, port)),
8014 		.call = parse_mp,
8015 	},
8016 	[ITEM_AGGR_AFFINITY] = {
8017 		.name = "aggr_affinity",
8018 		.help = "match on the aggregated port receiving the packets",
8019 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8020 				  sizeof(struct rte_flow_item_aggr_affinity)),
8021 		.next = NEXT(item_aggr_affinity),
8022 		.call = parse_vc,
8023 	},
8024 	[ITEM_AGGR_AFFINITY_VALUE] = {
8025 		.name = "affinity",
8026 		.help = "aggregated affinity value",
8027 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8028 			     item_param),
8029 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8030 					affinity)),
8031 	},
8032 	[ITEM_TX_QUEUE] = {
8033 		.name = "tx_queue",
8034 		.help = "match on the tx queue of send packet",
8035 		.priv = PRIV_ITEM(TX_QUEUE,
8036 				  sizeof(struct rte_flow_item_tx_queue)),
8037 		.next = NEXT(item_tx_queue),
8038 		.call = parse_vc,
8039 	},
8040 	[ITEM_TX_QUEUE_VALUE] = {
8041 		.name = "tx_queue_value",
8042 		.help = "tx queue value",
8043 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8044 			     item_param),
8045 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8046 					tx_queue)),
8047 	},
8048 };
8049 
8050 /** Remove and return last entry from argument stack. */
8051 static const struct arg *
8052 pop_args(struct context *ctx)
8053 {
8054 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8055 }
8056 
8057 /** Add entry on top of the argument stack. */
8058 static int
8059 push_args(struct context *ctx, const struct arg *arg)
8060 {
8061 	if (ctx->args_num == CTX_STACK_SIZE)
8062 		return -1;
8063 	ctx->args[ctx->args_num++] = arg;
8064 	return 0;
8065 }
8066 
8067 /** Spread value into buffer according to bit-mask. */
8068 static size_t
8069 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8070 {
8071 	uint32_t i = arg->size;
8072 	uint32_t end = 0;
8073 	int sub = 1;
8074 	int add = 0;
8075 	size_t len = 0;
8076 
8077 	if (!arg->mask)
8078 		return 0;
8079 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8080 	if (!arg->hton) {
8081 		i = 0;
8082 		end = arg->size;
8083 		sub = 0;
8084 		add = 1;
8085 	}
8086 #endif
8087 	while (i != end) {
8088 		unsigned int shift = 0;
8089 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8090 
8091 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8092 			if (!(arg->mask[i] & (1 << shift)))
8093 				continue;
8094 			++len;
8095 			if (!dst)
8096 				continue;
8097 			*buf &= ~(1 << shift);
8098 			*buf |= (val & 1) << shift;
8099 			val >>= 1;
8100 		}
8101 		i += add;
8102 	}
8103 	return len;
8104 }
8105 
8106 /** Compare a string with a partial one of a given length. */
8107 static int
8108 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8109 {
8110 	int r = strncmp(full, partial, partial_len);
8111 
8112 	if (r)
8113 		return r;
8114 	if (strlen(full) <= partial_len)
8115 		return 0;
8116 	return full[partial_len];
8117 }
8118 
8119 /**
8120  * Parse a prefix length and generate a bit-mask.
8121  *
8122  * Last argument (ctx->args) is retrieved to determine mask size, storage
8123  * location and whether the result must use network byte ordering.
8124  */
8125 static int
8126 parse_prefix(struct context *ctx, const struct token *token,
8127 	     const char *str, unsigned int len,
8128 	     void *buf, unsigned int size)
8129 {
8130 	const struct arg *arg = pop_args(ctx);
8131 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8132 	char *end;
8133 	uintmax_t u;
8134 	unsigned int bytes;
8135 	unsigned int extra;
8136 
8137 	(void)token;
8138 	/* Argument is expected. */
8139 	if (!arg)
8140 		return -1;
8141 	errno = 0;
8142 	u = strtoumax(str, &end, 0);
8143 	if (errno || (size_t)(end - str) != len)
8144 		goto error;
8145 	if (arg->mask) {
8146 		uintmax_t v = 0;
8147 
8148 		extra = arg_entry_bf_fill(NULL, 0, arg);
8149 		if (u > extra)
8150 			goto error;
8151 		if (!ctx->object)
8152 			return len;
8153 		extra -= u;
8154 		while (u--)
8155 			(v <<= 1, v |= 1);
8156 		v <<= extra;
8157 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8158 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8159 			goto error;
8160 		return len;
8161 	}
8162 	bytes = u / 8;
8163 	extra = u % 8;
8164 	size = arg->size;
8165 	if (bytes > size || bytes + !!extra > size)
8166 		goto error;
8167 	if (!ctx->object)
8168 		return len;
8169 	buf = (uint8_t *)ctx->object + arg->offset;
8170 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8171 	if (!arg->hton) {
8172 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8173 		memset(buf, 0x00, size - bytes);
8174 		if (extra)
8175 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8176 	} else
8177 #endif
8178 	{
8179 		memset(buf, 0xff, bytes);
8180 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8181 		if (extra)
8182 			((uint8_t *)buf)[bytes] = conv[extra];
8183 	}
8184 	if (ctx->objmask)
8185 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8186 	return len;
8187 error:
8188 	push_args(ctx, arg);
8189 	return -1;
8190 }
8191 
8192 /** Default parsing function for token name matching. */
8193 static int
8194 parse_default(struct context *ctx, const struct token *token,
8195 	      const char *str, unsigned int len,
8196 	      void *buf, unsigned int size)
8197 {
8198 	(void)ctx;
8199 	(void)buf;
8200 	(void)size;
8201 	if (strcmp_partial(token->name, str, len))
8202 		return -1;
8203 	return len;
8204 }
8205 
8206 /** Parse flow command, initialize output buffer for subsequent tokens. */
8207 static int
8208 parse_init(struct context *ctx, const struct token *token,
8209 	   const char *str, unsigned int len,
8210 	   void *buf, unsigned int size)
8211 {
8212 	struct buffer *out = buf;
8213 
8214 	/* Token name must match. */
8215 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8216 		return -1;
8217 	/* Nothing else to do if there is no buffer. */
8218 	if (!out)
8219 		return len;
8220 	/* Make sure buffer is large enough. */
8221 	if (size < sizeof(*out))
8222 		return -1;
8223 	/* Initialize buffer. */
8224 	memset(out, 0x00, sizeof(*out));
8225 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8226 	ctx->objdata = 0;
8227 	ctx->object = out;
8228 	ctx->objmask = NULL;
8229 	return len;
8230 }
8231 
8232 /** Parse tokens for indirect action commands. */
8233 static int
8234 parse_ia(struct context *ctx, const struct token *token,
8235 	 const char *str, unsigned int len,
8236 	 void *buf, unsigned int size)
8237 {
8238 	struct buffer *out = buf;
8239 
8240 	/* Token name must match. */
8241 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8242 		return -1;
8243 	/* Nothing else to do if there is no buffer. */
8244 	if (!out)
8245 		return len;
8246 	if (!out->command) {
8247 		if (ctx->curr != INDIRECT_ACTION)
8248 			return -1;
8249 		if (sizeof(*out) > size)
8250 			return -1;
8251 		out->command = ctx->curr;
8252 		ctx->objdata = 0;
8253 		ctx->object = out;
8254 		ctx->objmask = NULL;
8255 		out->args.vc.data = (uint8_t *)out + size;
8256 		return len;
8257 	}
8258 	switch (ctx->curr) {
8259 	case INDIRECT_ACTION_CREATE:
8260 	case INDIRECT_ACTION_UPDATE:
8261 	case INDIRECT_ACTION_QUERY_UPDATE:
8262 		out->args.vc.actions =
8263 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8264 					       sizeof(double));
8265 		out->args.vc.attr.group = UINT32_MAX;
8266 		/* fallthrough */
8267 	case INDIRECT_ACTION_QUERY:
8268 		out->command = ctx->curr;
8269 		ctx->objdata = 0;
8270 		ctx->object = out;
8271 		ctx->objmask = NULL;
8272 		return len;
8273 	case INDIRECT_ACTION_EGRESS:
8274 		out->args.vc.attr.egress = 1;
8275 		return len;
8276 	case INDIRECT_ACTION_INGRESS:
8277 		out->args.vc.attr.ingress = 1;
8278 		return len;
8279 	case INDIRECT_ACTION_TRANSFER:
8280 		out->args.vc.attr.transfer = 1;
8281 		return len;
8282 	case INDIRECT_ACTION_QU_MODE:
8283 		return len;
8284 	case INDIRECT_ACTION_LIST:
8285 		out->command = INDIRECT_ACTION_LIST_CREATE;
8286 		return len;
8287 	case INDIRECT_ACTION_FLOW_CONF:
8288 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8289 		return len;
8290 	default:
8291 		return -1;
8292 	}
8293 }
8294 
8295 
8296 /** Parse tokens for indirect action destroy command. */
8297 static int
8298 parse_ia_destroy(struct context *ctx, const struct token *token,
8299 		 const char *str, unsigned int len,
8300 		 void *buf, unsigned int size)
8301 {
8302 	struct buffer *out = buf;
8303 	uint32_t *action_id;
8304 
8305 	/* Token name must match. */
8306 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8307 		return -1;
8308 	/* Nothing else to do if there is no buffer. */
8309 	if (!out)
8310 		return len;
8311 	if (!out->command || out->command == INDIRECT_ACTION) {
8312 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8313 			return -1;
8314 		if (sizeof(*out) > size)
8315 			return -1;
8316 		out->command = ctx->curr;
8317 		ctx->objdata = 0;
8318 		ctx->object = out;
8319 		ctx->objmask = NULL;
8320 		out->args.ia_destroy.action_id =
8321 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8322 					       sizeof(double));
8323 		return len;
8324 	}
8325 	action_id = out->args.ia_destroy.action_id
8326 		    + out->args.ia_destroy.action_id_n++;
8327 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8328 		return -1;
8329 	ctx->objdata = 0;
8330 	ctx->object = action_id;
8331 	ctx->objmask = NULL;
8332 	return len;
8333 }
8334 
8335 /** Parse tokens for indirect action commands. */
8336 static int
8337 parse_qia(struct context *ctx, const struct token *token,
8338 	  const char *str, unsigned int len,
8339 	  void *buf, unsigned int size)
8340 {
8341 	struct buffer *out = buf;
8342 
8343 	/* Token name must match. */
8344 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8345 		return -1;
8346 	/* Nothing else to do if there is no buffer. */
8347 	if (!out)
8348 		return len;
8349 	if (!out->command) {
8350 		if (ctx->curr != QUEUE)
8351 			return -1;
8352 		if (sizeof(*out) > size)
8353 			return -1;
8354 		out->args.vc.data = (uint8_t *)out + size;
8355 		return len;
8356 	}
8357 	switch (ctx->curr) {
8358 	case QUEUE_INDIRECT_ACTION:
8359 		return len;
8360 	case QUEUE_INDIRECT_ACTION_CREATE:
8361 	case QUEUE_INDIRECT_ACTION_UPDATE:
8362 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8363 		out->args.vc.actions =
8364 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8365 					       sizeof(double));
8366 		out->args.vc.attr.group = UINT32_MAX;
8367 		/* fallthrough */
8368 	case QUEUE_INDIRECT_ACTION_QUERY:
8369 		out->command = ctx->curr;
8370 		ctx->objdata = 0;
8371 		ctx->object = out;
8372 		ctx->objmask = NULL;
8373 		return len;
8374 	case QUEUE_INDIRECT_ACTION_EGRESS:
8375 		out->args.vc.attr.egress = 1;
8376 		return len;
8377 	case QUEUE_INDIRECT_ACTION_INGRESS:
8378 		out->args.vc.attr.ingress = 1;
8379 		return len;
8380 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8381 		out->args.vc.attr.transfer = 1;
8382 		return len;
8383 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8384 		return len;
8385 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8386 		return len;
8387 	case QUEUE_INDIRECT_ACTION_LIST:
8388 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8389 		return len;
8390 	default:
8391 		return -1;
8392 	}
8393 }
8394 
8395 /** Parse tokens for indirect action destroy command. */
8396 static int
8397 parse_qia_destroy(struct context *ctx, const struct token *token,
8398 		  const char *str, unsigned int len,
8399 		  void *buf, unsigned int size)
8400 {
8401 	struct buffer *out = buf;
8402 	uint32_t *action_id;
8403 
8404 	/* Token name must match. */
8405 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8406 		return -1;
8407 	/* Nothing else to do if there is no buffer. */
8408 	if (!out)
8409 		return len;
8410 	if (!out->command || out->command == QUEUE) {
8411 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8412 			return -1;
8413 		if (sizeof(*out) > size)
8414 			return -1;
8415 		out->command = ctx->curr;
8416 		ctx->objdata = 0;
8417 		ctx->object = out;
8418 		ctx->objmask = NULL;
8419 		out->args.ia_destroy.action_id =
8420 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8421 					       sizeof(double));
8422 		return len;
8423 	}
8424 	switch (ctx->curr) {
8425 	case QUEUE_INDIRECT_ACTION:
8426 		out->command = ctx->curr;
8427 		ctx->objdata = 0;
8428 		ctx->object = out;
8429 		ctx->objmask = NULL;
8430 		return len;
8431 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8432 		action_id = out->args.ia_destroy.action_id
8433 				+ out->args.ia_destroy.action_id_n++;
8434 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8435 			return -1;
8436 		ctx->objdata = 0;
8437 		ctx->object = action_id;
8438 		ctx->objmask = NULL;
8439 		return len;
8440 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8441 		return len;
8442 	default:
8443 		return -1;
8444 	}
8445 }
8446 
8447 /** Parse tokens for meter policy action commands. */
8448 static int
8449 parse_mp(struct context *ctx, const struct token *token,
8450 	const char *str, unsigned int len,
8451 	void *buf, unsigned int size)
8452 {
8453 	struct buffer *out = buf;
8454 
8455 	/* Token name must match. */
8456 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8457 		return -1;
8458 	/* Nothing else to do if there is no buffer. */
8459 	if (!out)
8460 		return len;
8461 	if (!out->command) {
8462 		if (ctx->curr != ITEM_POL_POLICY)
8463 			return -1;
8464 		if (sizeof(*out) > size)
8465 			return -1;
8466 		out->command = ctx->curr;
8467 		ctx->objdata = 0;
8468 		ctx->object = out;
8469 		ctx->objmask = NULL;
8470 		out->args.vc.data = (uint8_t *)out + size;
8471 		return len;
8472 	}
8473 	switch (ctx->curr) {
8474 	case ACTION_POL_G:
8475 		out->args.vc.actions =
8476 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8477 					sizeof(double));
8478 		out->command = ctx->curr;
8479 		ctx->objdata = 0;
8480 		ctx->object = out;
8481 		ctx->objmask = NULL;
8482 		return len;
8483 	default:
8484 		return -1;
8485 	}
8486 }
8487 
8488 /** Parse tokens for validate/create commands. */
8489 static int
8490 parse_vc(struct context *ctx, const struct token *token,
8491 	 const char *str, unsigned int len,
8492 	 void *buf, unsigned int size)
8493 {
8494 	struct buffer *out = buf;
8495 	uint8_t *data;
8496 	uint32_t data_size;
8497 
8498 	/* Token name must match. */
8499 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8500 		return -1;
8501 	/* Nothing else to do if there is no buffer. */
8502 	if (!out)
8503 		return len;
8504 	if (!out->command) {
8505 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8506 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8507 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8508 		    ctx->curr != UPDATE)
8509 			return -1;
8510 		if (ctx->curr == UPDATE)
8511 			out->args.vc.pattern =
8512 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8513 						       sizeof(double));
8514 		if (sizeof(*out) > size)
8515 			return -1;
8516 		out->command = ctx->curr;
8517 		ctx->objdata = 0;
8518 		ctx->object = out;
8519 		ctx->objmask = NULL;
8520 		out->args.vc.data = (uint8_t *)out + size;
8521 		return len;
8522 	}
8523 	ctx->objdata = 0;
8524 	switch (ctx->curr) {
8525 	default:
8526 		ctx->object = &out->args.vc.attr;
8527 		break;
8528 	case VC_TUNNEL_SET:
8529 	case VC_TUNNEL_MATCH:
8530 		ctx->object = &out->args.vc.tunnel_ops;
8531 		break;
8532 	case VC_USER_ID:
8533 		ctx->object = out;
8534 		break;
8535 	}
8536 	ctx->objmask = NULL;
8537 	switch (ctx->curr) {
8538 	case VC_GROUP:
8539 	case VC_PRIORITY:
8540 	case VC_USER_ID:
8541 		return len;
8542 	case VC_TUNNEL_SET:
8543 		out->args.vc.tunnel_ops.enabled = 1;
8544 		out->args.vc.tunnel_ops.actions = 1;
8545 		return len;
8546 	case VC_TUNNEL_MATCH:
8547 		out->args.vc.tunnel_ops.enabled = 1;
8548 		out->args.vc.tunnel_ops.items = 1;
8549 		return len;
8550 	case VC_INGRESS:
8551 		out->args.vc.attr.ingress = 1;
8552 		return len;
8553 	case VC_EGRESS:
8554 		out->args.vc.attr.egress = 1;
8555 		return len;
8556 	case VC_TRANSFER:
8557 		out->args.vc.attr.transfer = 1;
8558 		return len;
8559 	case ITEM_PATTERN:
8560 		out->args.vc.pattern =
8561 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8562 					       sizeof(double));
8563 		ctx->object = out->args.vc.pattern;
8564 		ctx->objmask = NULL;
8565 		return len;
8566 	case ITEM_END:
8567 		if ((out->command == VALIDATE || out->command == CREATE) &&
8568 		    ctx->last)
8569 			return -1;
8570 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8571 		    !ctx->last)
8572 			return -1;
8573 		break;
8574 	case ACTIONS:
8575 		out->args.vc.actions = out->args.vc.pattern ?
8576 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8577 					       (out->args.vc.pattern +
8578 						out->args.vc.pattern_n),
8579 					       sizeof(double)) :
8580 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8581 					       sizeof(double));
8582 		ctx->object = out->args.vc.actions;
8583 		ctx->objmask = NULL;
8584 		return len;
8585 	case VC_IS_USER_ID:
8586 		out->args.vc.user_id = true;
8587 		return len;
8588 	default:
8589 		if (!token->priv)
8590 			return -1;
8591 		break;
8592 	}
8593 	if (!out->args.vc.actions) {
8594 		const struct parse_item_priv *priv = token->priv;
8595 		struct rte_flow_item *item =
8596 			out->args.vc.pattern + out->args.vc.pattern_n;
8597 
8598 		data_size = priv->size * 3; /* spec, last, mask */
8599 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8600 					       (out->args.vc.data - data_size),
8601 					       sizeof(double));
8602 		if ((uint8_t *)item + sizeof(*item) > data)
8603 			return -1;
8604 		*item = (struct rte_flow_item){
8605 			.type = priv->type,
8606 		};
8607 		++out->args.vc.pattern_n;
8608 		ctx->object = item;
8609 		ctx->objmask = NULL;
8610 	} else {
8611 		const struct parse_action_priv *priv = token->priv;
8612 		struct rte_flow_action *action =
8613 			out->args.vc.actions + out->args.vc.actions_n;
8614 
8615 		data_size = priv->size; /* configuration */
8616 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8617 					       (out->args.vc.data - data_size),
8618 					       sizeof(double));
8619 		if ((uint8_t *)action + sizeof(*action) > data)
8620 			return -1;
8621 		*action = (struct rte_flow_action){
8622 			.type = priv->type,
8623 			.conf = data_size ? data : NULL,
8624 		};
8625 		++out->args.vc.actions_n;
8626 		ctx->object = action;
8627 		ctx->objmask = NULL;
8628 	}
8629 	memset(data, 0, data_size);
8630 	out->args.vc.data = data;
8631 	ctx->objdata = data_size;
8632 	return len;
8633 }
8634 
8635 /** Parse pattern item parameter type. */
8636 static int
8637 parse_vc_spec(struct context *ctx, const struct token *token,
8638 	      const char *str, unsigned int len,
8639 	      void *buf, unsigned int size)
8640 {
8641 	struct buffer *out = buf;
8642 	struct rte_flow_item *item;
8643 	uint32_t data_size;
8644 	int index;
8645 	int objmask = 0;
8646 
8647 	(void)size;
8648 	/* Token name must match. */
8649 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8650 		return -1;
8651 	/* Parse parameter types. */
8652 	switch (ctx->curr) {
8653 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8654 
8655 	case ITEM_PARAM_IS:
8656 		index = 0;
8657 		objmask = 1;
8658 		break;
8659 	case ITEM_PARAM_SPEC:
8660 		index = 0;
8661 		break;
8662 	case ITEM_PARAM_LAST:
8663 		index = 1;
8664 		break;
8665 	case ITEM_PARAM_PREFIX:
8666 		/* Modify next token to expect a prefix. */
8667 		if (ctx->next_num < 2)
8668 			return -1;
8669 		ctx->next[ctx->next_num - 2] = prefix;
8670 		/* Fall through. */
8671 	case ITEM_PARAM_MASK:
8672 		index = 2;
8673 		break;
8674 	default:
8675 		return -1;
8676 	}
8677 	/* Nothing else to do if there is no buffer. */
8678 	if (!out)
8679 		return len;
8680 	if (!out->args.vc.pattern_n)
8681 		return -1;
8682 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8683 	data_size = ctx->objdata / 3; /* spec, last, mask */
8684 	/* Point to selected object. */
8685 	ctx->object = out->args.vc.data + (data_size * index);
8686 	if (objmask) {
8687 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8688 		item->mask = ctx->objmask;
8689 	} else
8690 		ctx->objmask = NULL;
8691 	/* Update relevant item pointer. */
8692 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8693 		ctx->object;
8694 	return len;
8695 }
8696 
8697 /** Parse action configuration field. */
8698 static int
8699 parse_vc_conf(struct context *ctx, const struct token *token,
8700 	      const char *str, unsigned int len,
8701 	      void *buf, unsigned int size)
8702 {
8703 	struct buffer *out = buf;
8704 
8705 	(void)size;
8706 	/* Token name must match. */
8707 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8708 		return -1;
8709 	/* Nothing else to do if there is no buffer. */
8710 	if (!out)
8711 		return len;
8712 	/* Point to selected object. */
8713 	ctx->object = out->args.vc.data;
8714 	ctx->objmask = NULL;
8715 	return len;
8716 }
8717 
8718 /** Parse action configuration field. */
8719 static int
8720 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8721 		      const char *str, unsigned int len,
8722 		      void *buf, unsigned int size)
8723 {
8724 	struct buffer *out = buf;
8725 	struct rte_flow_update_age *update;
8726 
8727 	(void)size;
8728 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8729 		return -1;
8730 	/* Token name must match. */
8731 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8732 		return -1;
8733 	/* Nothing else to do if there is no buffer. */
8734 	if (!out)
8735 		return len;
8736 	/* Point to selected object. */
8737 	ctx->object = out->args.vc.data;
8738 	ctx->objmask = NULL;
8739 	/* Update the timeout is valid. */
8740 	update = (struct rte_flow_update_age *)out->args.vc.data;
8741 	update->timeout_valid = 1;
8742 	return len;
8743 }
8744 
8745 /** Parse eCPRI common header type field. */
8746 static int
8747 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8748 			 const char *str, unsigned int len,
8749 			 void *buf, unsigned int size)
8750 {
8751 	struct rte_flow_item_ecpri *ecpri;
8752 	struct rte_flow_item_ecpri *ecpri_mask;
8753 	struct rte_flow_item *item;
8754 	uint32_t data_size;
8755 	uint8_t msg_type;
8756 	struct buffer *out = buf;
8757 	const struct arg *arg;
8758 
8759 	(void)size;
8760 	/* Token name must match. */
8761 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8762 		return -1;
8763 	switch (ctx->curr) {
8764 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8765 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8766 		break;
8767 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8768 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8769 		break;
8770 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8771 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8772 		break;
8773 	default:
8774 		return -1;
8775 	}
8776 	if (!ctx->object)
8777 		return len;
8778 	arg = pop_args(ctx);
8779 	if (!arg)
8780 		return -1;
8781 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8782 	ecpri->hdr.common.type = msg_type;
8783 	data_size = ctx->objdata / 3; /* spec, last, mask */
8784 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8785 						    (data_size * 2));
8786 	ecpri_mask->hdr.common.type = 0xFF;
8787 	if (arg->hton) {
8788 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8789 		ecpri_mask->hdr.common.u32 =
8790 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8791 	}
8792 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8793 	item->spec = ecpri;
8794 	item->mask = ecpri_mask;
8795 	return len;
8796 }
8797 
8798 /** Parse L2TPv2 common header type field. */
8799 static int
8800 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8801 			 const char *str, unsigned int len,
8802 			 void *buf, unsigned int size)
8803 {
8804 	struct rte_flow_item_l2tpv2 *l2tpv2;
8805 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8806 	struct rte_flow_item *item;
8807 	uint32_t data_size;
8808 	uint16_t msg_type = 0;
8809 	struct buffer *out = buf;
8810 	const struct arg *arg;
8811 
8812 	(void)size;
8813 	/* Token name must match. */
8814 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8815 		return -1;
8816 	switch (ctx->curr) {
8817 	case ITEM_L2TPV2_TYPE_DATA:
8818 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8819 		break;
8820 	case ITEM_L2TPV2_TYPE_DATA_L:
8821 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8822 		break;
8823 	case ITEM_L2TPV2_TYPE_DATA_S:
8824 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8825 		break;
8826 	case ITEM_L2TPV2_TYPE_DATA_O:
8827 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8828 		break;
8829 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8830 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8831 		break;
8832 	case ITEM_L2TPV2_TYPE_CTRL:
8833 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8834 		break;
8835 	default:
8836 		return -1;
8837 	}
8838 	if (!ctx->object)
8839 		return len;
8840 	arg = pop_args(ctx);
8841 	if (!arg)
8842 		return -1;
8843 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8844 	l2tpv2->hdr.common.flags_version |= msg_type;
8845 	data_size = ctx->objdata / 3; /* spec, last, mask */
8846 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8847 						    (data_size * 2));
8848 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8849 	if (arg->hton) {
8850 		l2tpv2->hdr.common.flags_version =
8851 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8852 		l2tpv2_mask->hdr.common.flags_version =
8853 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8854 	}
8855 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8856 	item->spec = l2tpv2;
8857 	item->mask = l2tpv2_mask;
8858 	return len;
8859 }
8860 
8861 /** Parse operation for compare match item. */
8862 static int
8863 parse_vc_compare_op(struct context *ctx, const struct token *token,
8864 			 const char *str, unsigned int len, void *buf,
8865 			 unsigned int size)
8866 {
8867 	struct rte_flow_item_compare *compare_item;
8868 	unsigned int i;
8869 
8870 	(void)token;
8871 	(void)buf;
8872 	(void)size;
8873 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8874 		return -1;
8875 	for (i = 0; compare_ops[i]; ++i)
8876 		if (!strcmp_partial(compare_ops[i], str, len))
8877 			break;
8878 	if (!compare_ops[i])
8879 		return -1;
8880 	if (!ctx->object)
8881 		return len;
8882 	compare_item = ctx->object;
8883 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8884 	return len;
8885 }
8886 
8887 /** Parse id for compare match item. */
8888 static int
8889 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8890 			  const char *str, unsigned int len, void *buf,
8891 			  unsigned int size)
8892 {
8893 	struct rte_flow_item_compare *compare_item;
8894 	unsigned int i;
8895 
8896 	(void)token;
8897 	(void)buf;
8898 	(void)size;
8899 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8900 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8901 		return -1;
8902 	for (i = 0; flow_field_ids[i]; ++i)
8903 		if (!strcmp_partial(flow_field_ids[i], str, len))
8904 			break;
8905 	if (!flow_field_ids[i])
8906 		return -1;
8907 	if (!ctx->object)
8908 		return len;
8909 	compare_item = ctx->object;
8910 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8911 		compare_item->a.field = (enum rte_flow_field_id)i;
8912 	else
8913 		compare_item->b.field = (enum rte_flow_field_id)i;
8914 	return len;
8915 }
8916 
8917 /** Parse level for compare match item. */
8918 static int
8919 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8920 			     const char *str, unsigned int len, void *buf,
8921 			     unsigned int size)
8922 {
8923 	struct rte_flow_item_compare *compare_item;
8924 	struct flex_item *fp = NULL;
8925 	uint32_t val;
8926 	struct buffer *out = buf;
8927 	char *end;
8928 
8929 	(void)token;
8930 	(void)size;
8931 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8932 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
8933 		return -1;
8934 	if (!ctx->object)
8935 		return len;
8936 	compare_item = ctx->object;
8937 	errno = 0;
8938 	val = strtoumax(str, &end, 0);
8939 	if (errno || (size_t)(end - str) != len)
8940 		return -1;
8941 	/* No need to validate action template mask value */
8942 	if (out->args.vc.masks) {
8943 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
8944 			compare_item->a.level = val;
8945 		else
8946 			compare_item->b.level = val;
8947 		return len;
8948 	}
8949 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8950 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
8951 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
8952 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
8953 		if (val >= FLEX_MAX_PARSERS_NUM) {
8954 			printf("Bad flex item handle\n");
8955 			return -1;
8956 		}
8957 		fp = flex_items[ctx->port][val];
8958 		if (!fp) {
8959 			printf("Bad flex item handle\n");
8960 			return -1;
8961 		}
8962 	}
8963 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
8964 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
8965 			compare_item->a.level = val;
8966 		else
8967 			compare_item->a.flex_handle = fp->flex_handle;
8968 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
8969 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
8970 			compare_item->b.level = val;
8971 		else
8972 			compare_item->b.flex_handle = fp->flex_handle;
8973 	}
8974 	return len;
8975 }
8976 
8977 /** Parse meter color action type. */
8978 static int
8979 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
8980 				const char *str, unsigned int len,
8981 				void *buf, unsigned int size)
8982 {
8983 	struct rte_flow_action *action_data;
8984 	struct rte_flow_action_meter_color *conf;
8985 	enum rte_color color;
8986 
8987 	(void)buf;
8988 	(void)size;
8989 	/* Token name must match. */
8990 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8991 		return -1;
8992 	switch (ctx->curr) {
8993 	case ACTION_METER_COLOR_GREEN:
8994 		color = RTE_COLOR_GREEN;
8995 	break;
8996 	case ACTION_METER_COLOR_YELLOW:
8997 		color = RTE_COLOR_YELLOW;
8998 	break;
8999 	case ACTION_METER_COLOR_RED:
9000 		color = RTE_COLOR_RED;
9001 	break;
9002 	default:
9003 		return -1;
9004 	}
9005 
9006 	if (!ctx->object)
9007 		return len;
9008 	action_data = ctx->object;
9009 	conf = (struct rte_flow_action_meter_color *)
9010 					(uintptr_t)(action_data->conf);
9011 	conf->color = color;
9012 	return len;
9013 }
9014 
9015 /** Parse RSS action. */
9016 static int
9017 parse_vc_action_rss(struct context *ctx, const struct token *token,
9018 		    const char *str, unsigned int len,
9019 		    void *buf, unsigned int size)
9020 {
9021 	struct buffer *out = buf;
9022 	struct rte_flow_action *action;
9023 	struct action_rss_data *action_rss_data;
9024 	unsigned int i;
9025 	int ret;
9026 
9027 	ret = parse_vc(ctx, token, str, len, buf, size);
9028 	if (ret < 0)
9029 		return ret;
9030 	/* Nothing else to do if there is no buffer. */
9031 	if (!out)
9032 		return ret;
9033 	if (!out->args.vc.actions_n)
9034 		return -1;
9035 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9036 	/* Point to selected object. */
9037 	ctx->object = out->args.vc.data;
9038 	ctx->objmask = NULL;
9039 	/* Set up default configuration. */
9040 	action_rss_data = ctx->object;
9041 	*action_rss_data = (struct action_rss_data){
9042 		.conf = (struct rte_flow_action_rss){
9043 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9044 			.level = 0,
9045 			.types = rss_hf,
9046 			.key_len = 0,
9047 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9048 			.key = NULL,
9049 			.queue = action_rss_data->queue,
9050 		},
9051 		.queue = { 0 },
9052 	};
9053 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9054 		action_rss_data->queue[i] = i;
9055 	action->conf = &action_rss_data->conf;
9056 	return ret;
9057 }
9058 
9059 /**
9060  * Parse func field for RSS action.
9061  *
9062  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9063  * ACTION_RSS_FUNC_* index that called this function.
9064  */
9065 static int
9066 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9067 			 const char *str, unsigned int len,
9068 			 void *buf, unsigned int size)
9069 {
9070 	struct action_rss_data *action_rss_data;
9071 	enum rte_eth_hash_function func;
9072 
9073 	(void)buf;
9074 	(void)size;
9075 	/* Token name must match. */
9076 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9077 		return -1;
9078 	switch (ctx->curr) {
9079 	case ACTION_RSS_FUNC_DEFAULT:
9080 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9081 		break;
9082 	case ACTION_RSS_FUNC_TOEPLITZ:
9083 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9084 		break;
9085 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9086 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9087 		break;
9088 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9089 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9090 		break;
9091 	default:
9092 		return -1;
9093 	}
9094 	if (!ctx->object)
9095 		return len;
9096 	action_rss_data = ctx->object;
9097 	action_rss_data->conf.func = func;
9098 	return len;
9099 }
9100 
9101 /**
9102  * Parse type field for RSS action.
9103  *
9104  * Valid tokens are type field names and the "end" token.
9105  */
9106 static int
9107 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9108 			  const char *str, unsigned int len,
9109 			  void *buf, unsigned int size)
9110 {
9111 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9112 	struct action_rss_data *action_rss_data;
9113 	unsigned int i;
9114 
9115 	(void)token;
9116 	(void)buf;
9117 	(void)size;
9118 	if (ctx->curr != ACTION_RSS_TYPE)
9119 		return -1;
9120 	if (!(ctx->objdata >> 16) && ctx->object) {
9121 		action_rss_data = ctx->object;
9122 		action_rss_data->conf.types = 0;
9123 	}
9124 	if (!strcmp_partial("end", str, len)) {
9125 		ctx->objdata &= 0xffff;
9126 		return len;
9127 	}
9128 	for (i = 0; rss_type_table[i].str; ++i)
9129 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9130 			break;
9131 	if (!rss_type_table[i].str)
9132 		return -1;
9133 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9134 	/* Repeat token. */
9135 	if (ctx->next_num == RTE_DIM(ctx->next))
9136 		return -1;
9137 	ctx->next[ctx->next_num++] = next;
9138 	if (!ctx->object)
9139 		return len;
9140 	action_rss_data = ctx->object;
9141 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9142 	return len;
9143 }
9144 
9145 /**
9146  * Parse queue field for RSS action.
9147  *
9148  * Valid tokens are queue indices and the "end" token.
9149  */
9150 static int
9151 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9152 			  const char *str, unsigned int len,
9153 			  void *buf, unsigned int size)
9154 {
9155 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9156 	struct action_rss_data *action_rss_data;
9157 	const struct arg *arg;
9158 	int ret;
9159 	int i;
9160 
9161 	(void)token;
9162 	(void)buf;
9163 	(void)size;
9164 	if (ctx->curr != ACTION_RSS_QUEUE)
9165 		return -1;
9166 	i = ctx->objdata >> 16;
9167 	if (!strcmp_partial("end", str, len)) {
9168 		ctx->objdata &= 0xffff;
9169 		goto end;
9170 	}
9171 	if (i >= ACTION_RSS_QUEUE_NUM)
9172 		return -1;
9173 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9174 			     i * sizeof(action_rss_data->queue[i]),
9175 			     sizeof(action_rss_data->queue[i]));
9176 	if (push_args(ctx, arg))
9177 		return -1;
9178 	ret = parse_int(ctx, token, str, len, NULL, 0);
9179 	if (ret < 0) {
9180 		pop_args(ctx);
9181 		return -1;
9182 	}
9183 	++i;
9184 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9185 	/* Repeat token. */
9186 	if (ctx->next_num == RTE_DIM(ctx->next))
9187 		return -1;
9188 	ctx->next[ctx->next_num++] = next;
9189 end:
9190 	if (!ctx->object)
9191 		return len;
9192 	action_rss_data = ctx->object;
9193 	action_rss_data->conf.queue_num = i;
9194 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9195 	return len;
9196 }
9197 
9198 /** Setup VXLAN encap configuration. */
9199 static int
9200 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9201 {
9202 	/* Set up default configuration. */
9203 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9204 		.conf = (struct rte_flow_action_vxlan_encap){
9205 			.definition = action_vxlan_encap_data->items,
9206 		},
9207 		.items = {
9208 			{
9209 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9210 				.spec = &action_vxlan_encap_data->item_eth,
9211 				.mask = &rte_flow_item_eth_mask,
9212 			},
9213 			{
9214 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9215 				.spec = &action_vxlan_encap_data->item_vlan,
9216 				.mask = &rte_flow_item_vlan_mask,
9217 			},
9218 			{
9219 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9220 				.spec = &action_vxlan_encap_data->item_ipv4,
9221 				.mask = &rte_flow_item_ipv4_mask,
9222 			},
9223 			{
9224 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9225 				.spec = &action_vxlan_encap_data->item_udp,
9226 				.mask = &rte_flow_item_udp_mask,
9227 			},
9228 			{
9229 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9230 				.spec = &action_vxlan_encap_data->item_vxlan,
9231 				.mask = &rte_flow_item_vxlan_mask,
9232 			},
9233 			{
9234 				.type = RTE_FLOW_ITEM_TYPE_END,
9235 			},
9236 		},
9237 		.item_eth.hdr.ether_type = 0,
9238 		.item_vlan = {
9239 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9240 			.hdr.eth_proto = 0,
9241 		},
9242 		.item_ipv4.hdr = {
9243 			.src_addr = vxlan_encap_conf.ipv4_src,
9244 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9245 		},
9246 		.item_udp.hdr = {
9247 			.src_port = vxlan_encap_conf.udp_src,
9248 			.dst_port = vxlan_encap_conf.udp_dst,
9249 		},
9250 		.item_vxlan.hdr.flags = 0,
9251 	};
9252 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9253 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9254 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9255 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9256 	if (!vxlan_encap_conf.select_ipv4) {
9257 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9258 		       &vxlan_encap_conf.ipv6_src,
9259 		       sizeof(vxlan_encap_conf.ipv6_src));
9260 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9261 		       &vxlan_encap_conf.ipv6_dst,
9262 		       sizeof(vxlan_encap_conf.ipv6_dst));
9263 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9264 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9265 			.spec = &action_vxlan_encap_data->item_ipv6,
9266 			.mask = &rte_flow_item_ipv6_mask,
9267 		};
9268 	}
9269 	if (!vxlan_encap_conf.select_vlan)
9270 		action_vxlan_encap_data->items[1].type =
9271 			RTE_FLOW_ITEM_TYPE_VOID;
9272 	if (vxlan_encap_conf.select_tos_ttl) {
9273 		if (vxlan_encap_conf.select_ipv4) {
9274 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9275 
9276 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9277 			       sizeof(ipv4_mask_tos));
9278 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9279 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9280 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9281 					vxlan_encap_conf.ip_tos;
9282 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9283 					vxlan_encap_conf.ip_ttl;
9284 			action_vxlan_encap_data->items[2].mask =
9285 							&ipv4_mask_tos;
9286 		} else {
9287 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9288 
9289 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9290 			       sizeof(ipv6_mask_tos));
9291 			ipv6_mask_tos.hdr.vtc_flow |=
9292 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9293 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9294 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9295 				rte_cpu_to_be_32
9296 					((uint32_t)vxlan_encap_conf.ip_tos <<
9297 					 RTE_IPV6_HDR_TC_SHIFT);
9298 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9299 					vxlan_encap_conf.ip_ttl;
9300 			action_vxlan_encap_data->items[2].mask =
9301 							&ipv6_mask_tos;
9302 		}
9303 	}
9304 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9305 	       RTE_DIM(vxlan_encap_conf.vni));
9306 	return 0;
9307 }
9308 
9309 /** Parse VXLAN encap action. */
9310 static int
9311 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9312 			    const char *str, unsigned int len,
9313 			    void *buf, unsigned int size)
9314 {
9315 	struct buffer *out = buf;
9316 	struct rte_flow_action *action;
9317 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9318 	int ret;
9319 
9320 	ret = parse_vc(ctx, token, str, len, buf, size);
9321 	if (ret < 0)
9322 		return ret;
9323 	/* Nothing else to do if there is no buffer. */
9324 	if (!out)
9325 		return ret;
9326 	if (!out->args.vc.actions_n)
9327 		return -1;
9328 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9329 	/* Point to selected object. */
9330 	ctx->object = out->args.vc.data;
9331 	ctx->objmask = NULL;
9332 	action_vxlan_encap_data = ctx->object;
9333 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9334 	action->conf = &action_vxlan_encap_data->conf;
9335 	return ret;
9336 }
9337 
9338 /** Setup NVGRE encap configuration. */
9339 static int
9340 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9341 {
9342 	/* Set up default configuration. */
9343 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9344 		.conf = (struct rte_flow_action_nvgre_encap){
9345 			.definition = action_nvgre_encap_data->items,
9346 		},
9347 		.items = {
9348 			{
9349 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9350 				.spec = &action_nvgre_encap_data->item_eth,
9351 				.mask = &rte_flow_item_eth_mask,
9352 			},
9353 			{
9354 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9355 				.spec = &action_nvgre_encap_data->item_vlan,
9356 				.mask = &rte_flow_item_vlan_mask,
9357 			},
9358 			{
9359 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9360 				.spec = &action_nvgre_encap_data->item_ipv4,
9361 				.mask = &rte_flow_item_ipv4_mask,
9362 			},
9363 			{
9364 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9365 				.spec = &action_nvgre_encap_data->item_nvgre,
9366 				.mask = &rte_flow_item_nvgre_mask,
9367 			},
9368 			{
9369 				.type = RTE_FLOW_ITEM_TYPE_END,
9370 			},
9371 		},
9372 		.item_eth.hdr.ether_type = 0,
9373 		.item_vlan = {
9374 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9375 			.hdr.eth_proto = 0,
9376 		},
9377 		.item_ipv4.hdr = {
9378 		       .src_addr = nvgre_encap_conf.ipv4_src,
9379 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9380 		},
9381 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9382 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9383 		.item_nvgre.flow_id = 0,
9384 	};
9385 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9386 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9387 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9388 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9389 	if (!nvgre_encap_conf.select_ipv4) {
9390 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9391 		       &nvgre_encap_conf.ipv6_src,
9392 		       sizeof(nvgre_encap_conf.ipv6_src));
9393 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9394 		       &nvgre_encap_conf.ipv6_dst,
9395 		       sizeof(nvgre_encap_conf.ipv6_dst));
9396 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9397 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9398 			.spec = &action_nvgre_encap_data->item_ipv6,
9399 			.mask = &rte_flow_item_ipv6_mask,
9400 		};
9401 	}
9402 	if (!nvgre_encap_conf.select_vlan)
9403 		action_nvgre_encap_data->items[1].type =
9404 			RTE_FLOW_ITEM_TYPE_VOID;
9405 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9406 	       RTE_DIM(nvgre_encap_conf.tni));
9407 	return 0;
9408 }
9409 
9410 /** Parse NVGRE encap action. */
9411 static int
9412 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9413 			    const char *str, unsigned int len,
9414 			    void *buf, unsigned int size)
9415 {
9416 	struct buffer *out = buf;
9417 	struct rte_flow_action *action;
9418 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9419 	int ret;
9420 
9421 	ret = parse_vc(ctx, token, str, len, buf, size);
9422 	if (ret < 0)
9423 		return ret;
9424 	/* Nothing else to do if there is no buffer. */
9425 	if (!out)
9426 		return ret;
9427 	if (!out->args.vc.actions_n)
9428 		return -1;
9429 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9430 	/* Point to selected object. */
9431 	ctx->object = out->args.vc.data;
9432 	ctx->objmask = NULL;
9433 	action_nvgre_encap_data = ctx->object;
9434 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9435 	action->conf = &action_nvgre_encap_data->conf;
9436 	return ret;
9437 }
9438 
9439 /** Parse l2 encap action. */
9440 static int
9441 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9442 			 const char *str, unsigned int len,
9443 			 void *buf, unsigned int size)
9444 {
9445 	struct buffer *out = buf;
9446 	struct rte_flow_action *action;
9447 	struct action_raw_encap_data *action_encap_data;
9448 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9449 	struct rte_flow_item_vlan vlan = {
9450 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9451 		.hdr.eth_proto = 0,
9452 	};
9453 	uint8_t *header;
9454 	int ret;
9455 
9456 	ret = parse_vc(ctx, token, str, len, buf, size);
9457 	if (ret < 0)
9458 		return ret;
9459 	/* Nothing else to do if there is no buffer. */
9460 	if (!out)
9461 		return ret;
9462 	if (!out->args.vc.actions_n)
9463 		return -1;
9464 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9465 	/* Point to selected object. */
9466 	ctx->object = out->args.vc.data;
9467 	ctx->objmask = NULL;
9468 	/* Copy the headers to the buffer. */
9469 	action_encap_data = ctx->object;
9470 	*action_encap_data = (struct action_raw_encap_data) {
9471 		.conf = (struct rte_flow_action_raw_encap){
9472 			.data = action_encap_data->data,
9473 		},
9474 		.data = {},
9475 	};
9476 	header = action_encap_data->data;
9477 	if (l2_encap_conf.select_vlan)
9478 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9479 	else if (l2_encap_conf.select_ipv4)
9480 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9481 	else
9482 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9483 	memcpy(eth.hdr.dst_addr.addr_bytes,
9484 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9485 	memcpy(eth.hdr.src_addr.addr_bytes,
9486 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9487 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9488 	header += sizeof(struct rte_ether_hdr);
9489 	if (l2_encap_conf.select_vlan) {
9490 		if (l2_encap_conf.select_ipv4)
9491 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9492 		else
9493 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9494 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9495 		header += sizeof(struct rte_vlan_hdr);
9496 	}
9497 	action_encap_data->conf.size = header -
9498 		action_encap_data->data;
9499 	action->conf = &action_encap_data->conf;
9500 	return ret;
9501 }
9502 
9503 /** Parse l2 decap action. */
9504 static int
9505 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9506 			 const char *str, unsigned int len,
9507 			 void *buf, unsigned int size)
9508 {
9509 	struct buffer *out = buf;
9510 	struct rte_flow_action *action;
9511 	struct action_raw_decap_data *action_decap_data;
9512 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9513 	struct rte_flow_item_vlan vlan = {
9514 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9515 		.hdr.eth_proto = 0,
9516 	};
9517 	uint8_t *header;
9518 	int ret;
9519 
9520 	ret = parse_vc(ctx, token, str, len, buf, size);
9521 	if (ret < 0)
9522 		return ret;
9523 	/* Nothing else to do if there is no buffer. */
9524 	if (!out)
9525 		return ret;
9526 	if (!out->args.vc.actions_n)
9527 		return -1;
9528 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9529 	/* Point to selected object. */
9530 	ctx->object = out->args.vc.data;
9531 	ctx->objmask = NULL;
9532 	/* Copy the headers to the buffer. */
9533 	action_decap_data = ctx->object;
9534 	*action_decap_data = (struct action_raw_decap_data) {
9535 		.conf = (struct rte_flow_action_raw_decap){
9536 			.data = action_decap_data->data,
9537 		},
9538 		.data = {},
9539 	};
9540 	header = action_decap_data->data;
9541 	if (l2_decap_conf.select_vlan)
9542 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9543 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9544 	header += sizeof(struct rte_ether_hdr);
9545 	if (l2_decap_conf.select_vlan) {
9546 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9547 		header += sizeof(struct rte_vlan_hdr);
9548 	}
9549 	action_decap_data->conf.size = header -
9550 		action_decap_data->data;
9551 	action->conf = &action_decap_data->conf;
9552 	return ret;
9553 }
9554 
9555 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9556 
9557 /** Parse MPLSOGRE encap action. */
9558 static int
9559 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9560 			       const char *str, unsigned int len,
9561 			       void *buf, unsigned int size)
9562 {
9563 	struct buffer *out = buf;
9564 	struct rte_flow_action *action;
9565 	struct action_raw_encap_data *action_encap_data;
9566 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9567 	struct rte_flow_item_vlan vlan = {
9568 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9569 		.hdr.eth_proto = 0,
9570 	};
9571 	struct rte_flow_item_ipv4 ipv4 = {
9572 		.hdr =  {
9573 			.src_addr = mplsogre_encap_conf.ipv4_src,
9574 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9575 			.next_proto_id = IPPROTO_GRE,
9576 			.version_ihl = RTE_IPV4_VHL_DEF,
9577 			.time_to_live = IPDEFTTL,
9578 		},
9579 	};
9580 	struct rte_flow_item_ipv6 ipv6 = {
9581 		.hdr =  {
9582 			.proto = IPPROTO_GRE,
9583 			.hop_limits = IPDEFTTL,
9584 		},
9585 	};
9586 	struct rte_flow_item_gre gre = {
9587 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9588 	};
9589 	struct rte_flow_item_mpls mpls = {
9590 		.ttl = 0,
9591 	};
9592 	uint8_t *header;
9593 	int ret;
9594 
9595 	ret = parse_vc(ctx, token, str, len, buf, size);
9596 	if (ret < 0)
9597 		return ret;
9598 	/* Nothing else to do if there is no buffer. */
9599 	if (!out)
9600 		return ret;
9601 	if (!out->args.vc.actions_n)
9602 		return -1;
9603 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9604 	/* Point to selected object. */
9605 	ctx->object = out->args.vc.data;
9606 	ctx->objmask = NULL;
9607 	/* Copy the headers to the buffer. */
9608 	action_encap_data = ctx->object;
9609 	*action_encap_data = (struct action_raw_encap_data) {
9610 		.conf = (struct rte_flow_action_raw_encap){
9611 			.data = action_encap_data->data,
9612 		},
9613 		.data = {},
9614 		.preserve = {},
9615 	};
9616 	header = action_encap_data->data;
9617 	if (mplsogre_encap_conf.select_vlan)
9618 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9619 	else if (mplsogre_encap_conf.select_ipv4)
9620 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9621 	else
9622 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9623 	memcpy(eth.hdr.dst_addr.addr_bytes,
9624 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9625 	memcpy(eth.hdr.src_addr.addr_bytes,
9626 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9627 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9628 	header += sizeof(struct rte_ether_hdr);
9629 	if (mplsogre_encap_conf.select_vlan) {
9630 		if (mplsogre_encap_conf.select_ipv4)
9631 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9632 		else
9633 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9634 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9635 		header += sizeof(struct rte_vlan_hdr);
9636 	}
9637 	if (mplsogre_encap_conf.select_ipv4) {
9638 		memcpy(header, &ipv4, sizeof(ipv4));
9639 		header += sizeof(ipv4);
9640 	} else {
9641 		memcpy(&ipv6.hdr.src_addr,
9642 		       &mplsogre_encap_conf.ipv6_src,
9643 		       sizeof(mplsogre_encap_conf.ipv6_src));
9644 		memcpy(&ipv6.hdr.dst_addr,
9645 		       &mplsogre_encap_conf.ipv6_dst,
9646 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9647 		memcpy(header, &ipv6, sizeof(ipv6));
9648 		header += sizeof(ipv6);
9649 	}
9650 	memcpy(header, &gre, sizeof(gre));
9651 	header += sizeof(gre);
9652 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9653 	       RTE_DIM(mplsogre_encap_conf.label));
9654 	mpls.label_tc_s[2] |= 0x1;
9655 	memcpy(header, &mpls, sizeof(mpls));
9656 	header += sizeof(mpls);
9657 	action_encap_data->conf.size = header -
9658 		action_encap_data->data;
9659 	action->conf = &action_encap_data->conf;
9660 	return ret;
9661 }
9662 
9663 /** Parse MPLSOGRE decap action. */
9664 static int
9665 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9666 			       const char *str, unsigned int len,
9667 			       void *buf, unsigned int size)
9668 {
9669 	struct buffer *out = buf;
9670 	struct rte_flow_action *action;
9671 	struct action_raw_decap_data *action_decap_data;
9672 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9673 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9674 	struct rte_flow_item_ipv4 ipv4 = {
9675 		.hdr =  {
9676 			.next_proto_id = IPPROTO_GRE,
9677 		},
9678 	};
9679 	struct rte_flow_item_ipv6 ipv6 = {
9680 		.hdr =  {
9681 			.proto = IPPROTO_GRE,
9682 		},
9683 	};
9684 	struct rte_flow_item_gre gre = {
9685 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9686 	};
9687 	struct rte_flow_item_mpls mpls;
9688 	uint8_t *header;
9689 	int ret;
9690 
9691 	ret = parse_vc(ctx, token, str, len, buf, size);
9692 	if (ret < 0)
9693 		return ret;
9694 	/* Nothing else to do if there is no buffer. */
9695 	if (!out)
9696 		return ret;
9697 	if (!out->args.vc.actions_n)
9698 		return -1;
9699 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9700 	/* Point to selected object. */
9701 	ctx->object = out->args.vc.data;
9702 	ctx->objmask = NULL;
9703 	/* Copy the headers to the buffer. */
9704 	action_decap_data = ctx->object;
9705 	*action_decap_data = (struct action_raw_decap_data) {
9706 		.conf = (struct rte_flow_action_raw_decap){
9707 			.data = action_decap_data->data,
9708 		},
9709 		.data = {},
9710 	};
9711 	header = action_decap_data->data;
9712 	if (mplsogre_decap_conf.select_vlan)
9713 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9714 	else if (mplsogre_encap_conf.select_ipv4)
9715 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9716 	else
9717 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9718 	memcpy(eth.hdr.dst_addr.addr_bytes,
9719 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9720 	memcpy(eth.hdr.src_addr.addr_bytes,
9721 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9722 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9723 	header += sizeof(struct rte_ether_hdr);
9724 	if (mplsogre_encap_conf.select_vlan) {
9725 		if (mplsogre_encap_conf.select_ipv4)
9726 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9727 		else
9728 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9729 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9730 		header += sizeof(struct rte_vlan_hdr);
9731 	}
9732 	if (mplsogre_encap_conf.select_ipv4) {
9733 		memcpy(header, &ipv4, sizeof(ipv4));
9734 		header += sizeof(ipv4);
9735 	} else {
9736 		memcpy(header, &ipv6, sizeof(ipv6));
9737 		header += sizeof(ipv6);
9738 	}
9739 	memcpy(header, &gre, sizeof(gre));
9740 	header += sizeof(gre);
9741 	memset(&mpls, 0, sizeof(mpls));
9742 	memcpy(header, &mpls, sizeof(mpls));
9743 	header += sizeof(mpls);
9744 	action_decap_data->conf.size = header -
9745 		action_decap_data->data;
9746 	action->conf = &action_decap_data->conf;
9747 	return ret;
9748 }
9749 
9750 /** Parse MPLSOUDP encap action. */
9751 static int
9752 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9753 			       const char *str, unsigned int len,
9754 			       void *buf, unsigned int size)
9755 {
9756 	struct buffer *out = buf;
9757 	struct rte_flow_action *action;
9758 	struct action_raw_encap_data *action_encap_data;
9759 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9760 	struct rte_flow_item_vlan vlan = {
9761 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9762 		.hdr.eth_proto = 0,
9763 	};
9764 	struct rte_flow_item_ipv4 ipv4 = {
9765 		.hdr =  {
9766 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9767 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9768 			.next_proto_id = IPPROTO_UDP,
9769 			.version_ihl = RTE_IPV4_VHL_DEF,
9770 			.time_to_live = IPDEFTTL,
9771 		},
9772 	};
9773 	struct rte_flow_item_ipv6 ipv6 = {
9774 		.hdr =  {
9775 			.proto = IPPROTO_UDP,
9776 			.hop_limits = IPDEFTTL,
9777 		},
9778 	};
9779 	struct rte_flow_item_udp udp = {
9780 		.hdr = {
9781 			.src_port = mplsoudp_encap_conf.udp_src,
9782 			.dst_port = mplsoudp_encap_conf.udp_dst,
9783 		},
9784 	};
9785 	struct rte_flow_item_mpls mpls;
9786 	uint8_t *header;
9787 	int ret;
9788 
9789 	ret = parse_vc(ctx, token, str, len, buf, size);
9790 	if (ret < 0)
9791 		return ret;
9792 	/* Nothing else to do if there is no buffer. */
9793 	if (!out)
9794 		return ret;
9795 	if (!out->args.vc.actions_n)
9796 		return -1;
9797 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9798 	/* Point to selected object. */
9799 	ctx->object = out->args.vc.data;
9800 	ctx->objmask = NULL;
9801 	/* Copy the headers to the buffer. */
9802 	action_encap_data = ctx->object;
9803 	*action_encap_data = (struct action_raw_encap_data) {
9804 		.conf = (struct rte_flow_action_raw_encap){
9805 			.data = action_encap_data->data,
9806 		},
9807 		.data = {},
9808 		.preserve = {},
9809 	};
9810 	header = action_encap_data->data;
9811 	if (mplsoudp_encap_conf.select_vlan)
9812 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9813 	else if (mplsoudp_encap_conf.select_ipv4)
9814 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9815 	else
9816 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9817 	memcpy(eth.hdr.dst_addr.addr_bytes,
9818 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9819 	memcpy(eth.hdr.src_addr.addr_bytes,
9820 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9821 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9822 	header += sizeof(struct rte_ether_hdr);
9823 	if (mplsoudp_encap_conf.select_vlan) {
9824 		if (mplsoudp_encap_conf.select_ipv4)
9825 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9826 		else
9827 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9828 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9829 		header += sizeof(struct rte_vlan_hdr);
9830 	}
9831 	if (mplsoudp_encap_conf.select_ipv4) {
9832 		memcpy(header, &ipv4, sizeof(ipv4));
9833 		header += sizeof(ipv4);
9834 	} else {
9835 		memcpy(&ipv6.hdr.src_addr,
9836 		       &mplsoudp_encap_conf.ipv6_src,
9837 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9838 		memcpy(&ipv6.hdr.dst_addr,
9839 		       &mplsoudp_encap_conf.ipv6_dst,
9840 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9841 		memcpy(header, &ipv6, sizeof(ipv6));
9842 		header += sizeof(ipv6);
9843 	}
9844 	memcpy(header, &udp, sizeof(udp));
9845 	header += sizeof(udp);
9846 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9847 	       RTE_DIM(mplsoudp_encap_conf.label));
9848 	mpls.label_tc_s[2] |= 0x1;
9849 	memcpy(header, &mpls, sizeof(mpls));
9850 	header += sizeof(mpls);
9851 	action_encap_data->conf.size = header -
9852 		action_encap_data->data;
9853 	action->conf = &action_encap_data->conf;
9854 	return ret;
9855 }
9856 
9857 /** Parse MPLSOUDP decap action. */
9858 static int
9859 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9860 			       const char *str, unsigned int len,
9861 			       void *buf, unsigned int size)
9862 {
9863 	struct buffer *out = buf;
9864 	struct rte_flow_action *action;
9865 	struct action_raw_decap_data *action_decap_data;
9866 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9867 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9868 	struct rte_flow_item_ipv4 ipv4 = {
9869 		.hdr =  {
9870 			.next_proto_id = IPPROTO_UDP,
9871 		},
9872 	};
9873 	struct rte_flow_item_ipv6 ipv6 = {
9874 		.hdr =  {
9875 			.proto = IPPROTO_UDP,
9876 		},
9877 	};
9878 	struct rte_flow_item_udp udp = {
9879 		.hdr = {
9880 			.dst_port = rte_cpu_to_be_16(6635),
9881 		},
9882 	};
9883 	struct rte_flow_item_mpls mpls;
9884 	uint8_t *header;
9885 	int ret;
9886 
9887 	ret = parse_vc(ctx, token, str, len, buf, size);
9888 	if (ret < 0)
9889 		return ret;
9890 	/* Nothing else to do if there is no buffer. */
9891 	if (!out)
9892 		return ret;
9893 	if (!out->args.vc.actions_n)
9894 		return -1;
9895 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9896 	/* Point to selected object. */
9897 	ctx->object = out->args.vc.data;
9898 	ctx->objmask = NULL;
9899 	/* Copy the headers to the buffer. */
9900 	action_decap_data = ctx->object;
9901 	*action_decap_data = (struct action_raw_decap_data) {
9902 		.conf = (struct rte_flow_action_raw_decap){
9903 			.data = action_decap_data->data,
9904 		},
9905 		.data = {},
9906 	};
9907 	header = action_decap_data->data;
9908 	if (mplsoudp_decap_conf.select_vlan)
9909 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9910 	else if (mplsoudp_encap_conf.select_ipv4)
9911 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9912 	else
9913 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9914 	memcpy(eth.hdr.dst_addr.addr_bytes,
9915 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9916 	memcpy(eth.hdr.src_addr.addr_bytes,
9917 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9918 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9919 	header += sizeof(struct rte_ether_hdr);
9920 	if (mplsoudp_encap_conf.select_vlan) {
9921 		if (mplsoudp_encap_conf.select_ipv4)
9922 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9923 		else
9924 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9925 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9926 		header += sizeof(struct rte_vlan_hdr);
9927 	}
9928 	if (mplsoudp_encap_conf.select_ipv4) {
9929 		memcpy(header, &ipv4, sizeof(ipv4));
9930 		header += sizeof(ipv4);
9931 	} else {
9932 		memcpy(header, &ipv6, sizeof(ipv6));
9933 		header += sizeof(ipv6);
9934 	}
9935 	memcpy(header, &udp, sizeof(udp));
9936 	header += sizeof(udp);
9937 	memset(&mpls, 0, sizeof(mpls));
9938 	memcpy(header, &mpls, sizeof(mpls));
9939 	header += sizeof(mpls);
9940 	action_decap_data->conf.size = header -
9941 		action_decap_data->data;
9942 	action->conf = &action_decap_data->conf;
9943 	return ret;
9944 }
9945 
9946 static int
9947 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
9948 				const char *str, unsigned int len, void *buf,
9949 				unsigned int size)
9950 {
9951 	struct action_raw_decap_data *action_raw_decap_data;
9952 	struct rte_flow_action *action;
9953 	const struct arg *arg;
9954 	struct buffer *out = buf;
9955 	int ret;
9956 	uint16_t idx;
9957 
9958 	RTE_SET_USED(token);
9959 	RTE_SET_USED(buf);
9960 	RTE_SET_USED(size);
9961 	arg = ARGS_ENTRY_ARB_BOUNDED
9962 		(offsetof(struct action_raw_decap_data, idx),
9963 		 sizeof(((struct action_raw_decap_data *)0)->idx),
9964 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9965 	if (push_args(ctx, arg))
9966 		return -1;
9967 	ret = parse_int(ctx, token, str, len, NULL, 0);
9968 	if (ret < 0) {
9969 		pop_args(ctx);
9970 		return -1;
9971 	}
9972 	if (!ctx->object)
9973 		return len;
9974 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9975 	action_raw_decap_data = ctx->object;
9976 	idx = action_raw_decap_data->idx;
9977 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
9978 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
9979 	action->conf = &action_raw_decap_data->conf;
9980 	return len;
9981 }
9982 
9983 
9984 static int
9985 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
9986 				const char *str, unsigned int len, void *buf,
9987 				unsigned int size)
9988 {
9989 	struct action_raw_encap_data *action_raw_encap_data;
9990 	struct rte_flow_action *action;
9991 	const struct arg *arg;
9992 	struct buffer *out = buf;
9993 	int ret;
9994 	uint16_t idx;
9995 
9996 	RTE_SET_USED(token);
9997 	RTE_SET_USED(buf);
9998 	RTE_SET_USED(size);
9999 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
10000 		return -1;
10001 	arg = ARGS_ENTRY_ARB_BOUNDED
10002 		(offsetof(struct action_raw_encap_data, idx),
10003 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10004 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10005 	if (push_args(ctx, arg))
10006 		return -1;
10007 	ret = parse_int(ctx, token, str, len, NULL, 0);
10008 	if (ret < 0) {
10009 		pop_args(ctx);
10010 		return -1;
10011 	}
10012 	if (!ctx->object)
10013 		return len;
10014 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10015 	action_raw_encap_data = ctx->object;
10016 	idx = action_raw_encap_data->idx;
10017 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10018 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10019 	action_raw_encap_data->conf.preserve = NULL;
10020 	action->conf = &action_raw_encap_data->conf;
10021 	return len;
10022 }
10023 
10024 static int
10025 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10026 			  const char *str, unsigned int len, void *buf,
10027 			  unsigned int size)
10028 {
10029 	struct buffer *out = buf;
10030 	int ret;
10031 
10032 	ret = parse_vc(ctx, token, str, len, buf, size);
10033 	if (ret < 0)
10034 		return ret;
10035 	/* Nothing else to do if there is no buffer. */
10036 	if (!out)
10037 		return ret;
10038 	if (!out->args.vc.actions_n)
10039 		return -1;
10040 	/* Point to selected object. */
10041 	ctx->object = out->args.vc.data;
10042 	ctx->objmask = NULL;
10043 	return ret;
10044 }
10045 
10046 static int
10047 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10048 			  const char *str, unsigned int len, void *buf,
10049 			  unsigned int size)
10050 {
10051 	struct buffer *out = buf;
10052 	struct rte_flow_action *action;
10053 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10054 	int ret;
10055 
10056 	ret = parse_vc(ctx, token, str, len, buf, size);
10057 	if (ret < 0)
10058 		return ret;
10059 	/* Nothing else to do if there is no buffer. */
10060 	if (!out)
10061 		return ret;
10062 	if (!out->args.vc.actions_n)
10063 		return -1;
10064 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10065 	/* Point to selected object. */
10066 	ctx->object = out->args.vc.data;
10067 	ctx->objmask = NULL;
10068 	/* Copy the headers to the buffer. */
10069 	action_raw_decap_data = ctx->object;
10070 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10071 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10072 	action->conf = &action_raw_decap_data->conf;
10073 	return ret;
10074 }
10075 
10076 static int
10077 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10078 				const char *str, unsigned int len, void *buf,
10079 				unsigned int size)
10080 {
10081 	struct buffer *out = buf;
10082 	struct rte_flow_action *action;
10083 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10084 	int ret;
10085 
10086 	ret = parse_vc(ctx, token, str, len, buf, size);
10087 	if (ret < 0)
10088 		return ret;
10089 	/* Nothing else to do if there is no buffer. */
10090 	if (!out)
10091 		return ret;
10092 	if (!out->args.vc.actions_n)
10093 		return -1;
10094 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10095 	/* Point to selected object. */
10096 	ctx->object = out->args.vc.data;
10097 	ctx->objmask = NULL;
10098 	/* Copy the headers to the buffer. */
10099 	ipv6_ext_remove_data = ctx->object;
10100 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10101 	action->conf = &ipv6_ext_remove_data->conf;
10102 	return ret;
10103 }
10104 
10105 static int
10106 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10107 				      const char *str, unsigned int len, void *buf,
10108 				      unsigned int size)
10109 {
10110 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10111 	struct rte_flow_action *action;
10112 	const struct arg *arg;
10113 	struct buffer *out = buf;
10114 	int ret;
10115 	uint16_t idx;
10116 
10117 	RTE_SET_USED(token);
10118 	RTE_SET_USED(buf);
10119 	RTE_SET_USED(size);
10120 	arg = ARGS_ENTRY_ARB_BOUNDED
10121 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10122 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10123 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10124 	if (push_args(ctx, arg))
10125 		return -1;
10126 	ret = parse_int(ctx, token, str, len, NULL, 0);
10127 	if (ret < 0) {
10128 		pop_args(ctx);
10129 		return -1;
10130 	}
10131 	if (!ctx->object)
10132 		return len;
10133 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10134 	action_ipv6_ext_remove_data = ctx->object;
10135 	idx = action_ipv6_ext_remove_data->idx;
10136 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10137 	action->conf = &action_ipv6_ext_remove_data->conf;
10138 	return len;
10139 }
10140 
10141 static int
10142 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10143 			      const char *str, unsigned int len, void *buf,
10144 			      unsigned int size)
10145 {
10146 	struct buffer *out = buf;
10147 	struct rte_flow_action *action;
10148 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10149 	int ret;
10150 
10151 	ret = parse_vc(ctx, token, str, len, buf, size);
10152 	if (ret < 0)
10153 		return ret;
10154 	/* Nothing else to do if there is no buffer. */
10155 	if (!out)
10156 		return ret;
10157 	if (!out->args.vc.actions_n)
10158 		return -1;
10159 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10160 	/* Point to selected object. */
10161 	ctx->object = out->args.vc.data;
10162 	ctx->objmask = NULL;
10163 	/* Copy the headers to the buffer. */
10164 	ipv6_ext_push_data = ctx->object;
10165 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10166 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10167 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10168 	action->conf = &ipv6_ext_push_data->conf;
10169 	return ret;
10170 }
10171 
10172 static int
10173 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10174 				    const char *str, unsigned int len, void *buf,
10175 				    unsigned int size)
10176 {
10177 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10178 	struct rte_flow_action *action;
10179 	const struct arg *arg;
10180 	struct buffer *out = buf;
10181 	int ret;
10182 	uint16_t idx;
10183 
10184 	RTE_SET_USED(token);
10185 	RTE_SET_USED(buf);
10186 	RTE_SET_USED(size);
10187 	arg = ARGS_ENTRY_ARB_BOUNDED
10188 		(offsetof(struct action_ipv6_ext_push_data, idx),
10189 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10190 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10191 	if (push_args(ctx, arg))
10192 		return -1;
10193 	ret = parse_int(ctx, token, str, len, NULL, 0);
10194 	if (ret < 0) {
10195 		pop_args(ctx);
10196 		return -1;
10197 	}
10198 	if (!ctx->object)
10199 		return len;
10200 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10201 	action_ipv6_ext_push_data = ctx->object;
10202 	idx = action_ipv6_ext_push_data->idx;
10203 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10204 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10205 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10206 	action->conf = &action_ipv6_ext_push_data->conf;
10207 	return len;
10208 }
10209 
10210 static int
10211 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10212 			 const char *str, unsigned int len, void *buf,
10213 			 unsigned int size)
10214 {
10215 	int ret;
10216 
10217 	ret = parse_vc(ctx, token, str, len, buf, size);
10218 	if (ret < 0)
10219 		return ret;
10220 	ret = rte_flow_dynf_metadata_register();
10221 	if (ret < 0)
10222 		return -1;
10223 	return len;
10224 }
10225 
10226 static int
10227 parse_vc_action_sample(struct context *ctx, const struct token *token,
10228 			 const char *str, unsigned int len, void *buf,
10229 			 unsigned int size)
10230 {
10231 	struct buffer *out = buf;
10232 	struct rte_flow_action *action;
10233 	struct action_sample_data *action_sample_data = NULL;
10234 	static struct rte_flow_action end_action = {
10235 		RTE_FLOW_ACTION_TYPE_END, 0
10236 	};
10237 	int ret;
10238 
10239 	ret = parse_vc(ctx, token, str, len, buf, size);
10240 	if (ret < 0)
10241 		return ret;
10242 	/* Nothing else to do if there is no buffer. */
10243 	if (!out)
10244 		return ret;
10245 	if (!out->args.vc.actions_n)
10246 		return -1;
10247 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10248 	/* Point to selected object. */
10249 	ctx->object = out->args.vc.data;
10250 	ctx->objmask = NULL;
10251 	/* Copy the headers to the buffer. */
10252 	action_sample_data = ctx->object;
10253 	action_sample_data->conf.actions = &end_action;
10254 	action->conf = &action_sample_data->conf;
10255 	return ret;
10256 }
10257 
10258 static int
10259 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10260 				const char *str, unsigned int len, void *buf,
10261 				unsigned int size)
10262 {
10263 	struct action_sample_data *action_sample_data;
10264 	struct rte_flow_action *action;
10265 	const struct arg *arg;
10266 	struct buffer *out = buf;
10267 	int ret;
10268 	uint16_t idx;
10269 
10270 	RTE_SET_USED(token);
10271 	RTE_SET_USED(buf);
10272 	RTE_SET_USED(size);
10273 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10274 		return -1;
10275 	arg = ARGS_ENTRY_ARB_BOUNDED
10276 		(offsetof(struct action_sample_data, idx),
10277 		 sizeof(((struct action_sample_data *)0)->idx),
10278 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10279 	if (push_args(ctx, arg))
10280 		return -1;
10281 	ret = parse_int(ctx, token, str, len, NULL, 0);
10282 	if (ret < 0) {
10283 		pop_args(ctx);
10284 		return -1;
10285 	}
10286 	if (!ctx->object)
10287 		return len;
10288 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10289 	action_sample_data = ctx->object;
10290 	idx = action_sample_data->idx;
10291 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10292 	action->conf = &action_sample_data->conf;
10293 	return len;
10294 }
10295 
10296 /** Parse operation for modify_field command. */
10297 static int
10298 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10299 			 const char *str, unsigned int len, void *buf,
10300 			 unsigned int size)
10301 {
10302 	struct rte_flow_action_modify_field *action_modify_field;
10303 	unsigned int i;
10304 
10305 	(void)token;
10306 	(void)buf;
10307 	(void)size;
10308 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10309 		return -1;
10310 	for (i = 0; modify_field_ops[i]; ++i)
10311 		if (!strcmp_partial(modify_field_ops[i], str, len))
10312 			break;
10313 	if (!modify_field_ops[i])
10314 		return -1;
10315 	if (!ctx->object)
10316 		return len;
10317 	action_modify_field = ctx->object;
10318 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10319 	return len;
10320 }
10321 
10322 /** Parse id for modify_field command. */
10323 static int
10324 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10325 			 const char *str, unsigned int len, void *buf,
10326 			 unsigned int size)
10327 {
10328 	struct rte_flow_action_modify_field *action_modify_field;
10329 	unsigned int i;
10330 
10331 	(void)token;
10332 	(void)buf;
10333 	(void)size;
10334 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10335 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10336 		return -1;
10337 	for (i = 0; flow_field_ids[i]; ++i)
10338 		if (!strcmp_partial(flow_field_ids[i], str, len))
10339 			break;
10340 	if (!flow_field_ids[i])
10341 		return -1;
10342 	if (!ctx->object)
10343 		return len;
10344 	action_modify_field = ctx->object;
10345 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10346 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10347 	else
10348 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10349 	return len;
10350 }
10351 
10352 /** Parse level for modify_field command. */
10353 static int
10354 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10355 			 const char *str, unsigned int len, void *buf,
10356 			 unsigned int size)
10357 {
10358 	struct rte_flow_action_modify_field *action;
10359 	struct flex_item *fp = NULL;
10360 	uint32_t val;
10361 	struct buffer *out = buf;
10362 	char *end;
10363 
10364 	(void)token;
10365 	(void)size;
10366 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10367 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10368 		return -1;
10369 	if (!ctx->object)
10370 		return len;
10371 	action = ctx->object;
10372 	errno = 0;
10373 	val = strtoumax(str, &end, 0);
10374 	if (errno || (size_t)(end - str) != len)
10375 		return -1;
10376 	/* No need to validate action template mask value */
10377 	if (out->args.vc.masks) {
10378 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10379 			action->dst.level = val;
10380 		else
10381 			action->src.level = val;
10382 		return len;
10383 	}
10384 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10385 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10386 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10387 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10388 		if (val >= FLEX_MAX_PARSERS_NUM) {
10389 			printf("Bad flex item handle\n");
10390 			return -1;
10391 		}
10392 		fp = flex_items[ctx->port][val];
10393 		if (!fp) {
10394 			printf("Bad flex item handle\n");
10395 			return -1;
10396 		}
10397 	}
10398 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10399 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10400 			action->dst.level = val;
10401 		else
10402 			action->dst.flex_handle = fp->flex_handle;
10403 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10404 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10405 			action->src.level = val;
10406 		else
10407 			action->src.flex_handle = fp->flex_handle;
10408 	}
10409 	return len;
10410 }
10411 
10412 /** Parse the conntrack update, not a rte_flow_action. */
10413 static int
10414 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10415 			 const char *str, unsigned int len, void *buf,
10416 			 unsigned int size)
10417 {
10418 	struct buffer *out = buf;
10419 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10420 
10421 	(void)size;
10422 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10423 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10424 		return -1;
10425 	/* Token name must match. */
10426 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10427 		return -1;
10428 	/* Nothing else to do if there is no buffer. */
10429 	if (!out)
10430 		return len;
10431 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10432 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10433 		ct_modify->new_ct.is_original_dir =
10434 				conntrack_context.is_original_dir;
10435 		ct_modify->direction = 1;
10436 	} else {
10437 		uint32_t old_dir;
10438 
10439 		old_dir = ct_modify->new_ct.is_original_dir;
10440 		memcpy(&ct_modify->new_ct, &conntrack_context,
10441 		       sizeof(conntrack_context));
10442 		ct_modify->new_ct.is_original_dir = old_dir;
10443 		ct_modify->state = 1;
10444 	}
10445 	return len;
10446 }
10447 
10448 /** Parse tokens for destroy command. */
10449 static int
10450 parse_destroy(struct context *ctx, const struct token *token,
10451 	      const char *str, unsigned int len,
10452 	      void *buf, unsigned int size)
10453 {
10454 	struct buffer *out = buf;
10455 
10456 	/* Token name must match. */
10457 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10458 		return -1;
10459 	/* Nothing else to do if there is no buffer. */
10460 	if (!out)
10461 		return len;
10462 	if (!out->command) {
10463 		if (ctx->curr != DESTROY)
10464 			return -1;
10465 		if (sizeof(*out) > size)
10466 			return -1;
10467 		out->command = ctx->curr;
10468 		ctx->objdata = 0;
10469 		ctx->object = out;
10470 		ctx->objmask = NULL;
10471 		out->args.destroy.rule =
10472 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10473 					       sizeof(double));
10474 		return len;
10475 	}
10476 	if (ctx->curr == DESTROY_IS_USER_ID) {
10477 		out->args.destroy.is_user_id = true;
10478 		return len;
10479 	}
10480 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10481 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10482 		return -1;
10483 	ctx->objdata = 0;
10484 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10485 	ctx->objmask = NULL;
10486 	return len;
10487 }
10488 
10489 /** Parse tokens for flush command. */
10490 static int
10491 parse_flush(struct context *ctx, const struct token *token,
10492 	    const char *str, unsigned int len,
10493 	    void *buf, unsigned int size)
10494 {
10495 	struct buffer *out = buf;
10496 
10497 	/* Token name must match. */
10498 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10499 		return -1;
10500 	/* Nothing else to do if there is no buffer. */
10501 	if (!out)
10502 		return len;
10503 	if (!out->command) {
10504 		if (ctx->curr != FLUSH)
10505 			return -1;
10506 		if (sizeof(*out) > size)
10507 			return -1;
10508 		out->command = ctx->curr;
10509 		ctx->objdata = 0;
10510 		ctx->object = out;
10511 		ctx->objmask = NULL;
10512 	}
10513 	return len;
10514 }
10515 
10516 /** Parse tokens for dump command. */
10517 static int
10518 parse_dump(struct context *ctx, const struct token *token,
10519 	    const char *str, unsigned int len,
10520 	    void *buf, unsigned int size)
10521 {
10522 	struct buffer *out = buf;
10523 
10524 	/* Token name must match. */
10525 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10526 		return -1;
10527 	/* Nothing else to do if there is no buffer. */
10528 	if (!out)
10529 		return len;
10530 	if (!out->command) {
10531 		if (ctx->curr != DUMP)
10532 			return -1;
10533 		if (sizeof(*out) > size)
10534 			return -1;
10535 		out->command = ctx->curr;
10536 		ctx->objdata = 0;
10537 		ctx->object = out;
10538 		ctx->objmask = NULL;
10539 		return len;
10540 	}
10541 	switch (ctx->curr) {
10542 	case DUMP_ALL:
10543 	case DUMP_ONE:
10544 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10545 		out->command = ctx->curr;
10546 		ctx->objdata = 0;
10547 		ctx->object = out;
10548 		ctx->objmask = NULL;
10549 		return len;
10550 	case DUMP_IS_USER_ID:
10551 		out->args.dump.is_user_id = true;
10552 		return len;
10553 	default:
10554 		return -1;
10555 	}
10556 }
10557 
10558 /** Parse tokens for query command. */
10559 static int
10560 parse_query(struct context *ctx, const struct token *token,
10561 	    const char *str, unsigned int len,
10562 	    void *buf, unsigned int size)
10563 {
10564 	struct buffer *out = buf;
10565 
10566 	/* Token name must match. */
10567 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10568 		return -1;
10569 	/* Nothing else to do if there is no buffer. */
10570 	if (!out)
10571 		return len;
10572 	if (!out->command) {
10573 		if (ctx->curr != QUERY)
10574 			return -1;
10575 		if (sizeof(*out) > size)
10576 			return -1;
10577 		out->command = ctx->curr;
10578 		ctx->objdata = 0;
10579 		ctx->object = out;
10580 		ctx->objmask = NULL;
10581 	}
10582 	if (ctx->curr == QUERY_IS_USER_ID) {
10583 		out->args.query.is_user_id = true;
10584 		return len;
10585 	}
10586 	return len;
10587 }
10588 
10589 /** Parse action names. */
10590 static int
10591 parse_action(struct context *ctx, const struct token *token,
10592 	     const char *str, unsigned int len,
10593 	     void *buf, unsigned int size)
10594 {
10595 	struct buffer *out = buf;
10596 	const struct arg *arg = pop_args(ctx);
10597 	unsigned int i;
10598 
10599 	(void)size;
10600 	/* Argument is expected. */
10601 	if (!arg)
10602 		return -1;
10603 	/* Parse action name. */
10604 	for (i = 0; next_action[i]; ++i) {
10605 		const struct parse_action_priv *priv;
10606 
10607 		token = &token_list[next_action[i]];
10608 		if (strcmp_partial(token->name, str, len))
10609 			continue;
10610 		priv = token->priv;
10611 		if (!priv)
10612 			goto error;
10613 		if (out)
10614 			memcpy((uint8_t *)ctx->object + arg->offset,
10615 			       &priv->type,
10616 			       arg->size);
10617 		return len;
10618 	}
10619 error:
10620 	push_args(ctx, arg);
10621 	return -1;
10622 }
10623 
10624 /** Parse tokens for list command. */
10625 static int
10626 parse_list(struct context *ctx, const struct token *token,
10627 	   const char *str, unsigned int len,
10628 	   void *buf, unsigned int size)
10629 {
10630 	struct buffer *out = buf;
10631 
10632 	/* Token name must match. */
10633 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10634 		return -1;
10635 	/* Nothing else to do if there is no buffer. */
10636 	if (!out)
10637 		return len;
10638 	if (!out->command) {
10639 		if (ctx->curr != LIST)
10640 			return -1;
10641 		if (sizeof(*out) > size)
10642 			return -1;
10643 		out->command = ctx->curr;
10644 		ctx->objdata = 0;
10645 		ctx->object = out;
10646 		ctx->objmask = NULL;
10647 		out->args.list.group =
10648 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10649 					       sizeof(double));
10650 		return len;
10651 	}
10652 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10653 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10654 		return -1;
10655 	ctx->objdata = 0;
10656 	ctx->object = out->args.list.group + out->args.list.group_n++;
10657 	ctx->objmask = NULL;
10658 	return len;
10659 }
10660 
10661 /** Parse tokens for list all aged flows command. */
10662 static int
10663 parse_aged(struct context *ctx, const struct token *token,
10664 	   const char *str, unsigned int len,
10665 	   void *buf, unsigned int size)
10666 {
10667 	struct buffer *out = buf;
10668 
10669 	/* Token name must match. */
10670 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10671 		return -1;
10672 	/* Nothing else to do if there is no buffer. */
10673 	if (!out)
10674 		return len;
10675 	if (!out->command || out->command == QUEUE) {
10676 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10677 			return -1;
10678 		if (sizeof(*out) > size)
10679 			return -1;
10680 		out->command = ctx->curr;
10681 		ctx->objdata = 0;
10682 		ctx->object = out;
10683 		ctx->objmask = NULL;
10684 	}
10685 	if (ctx->curr == AGED_DESTROY)
10686 		out->args.aged.destroy = 1;
10687 	return len;
10688 }
10689 
10690 /** Parse tokens for isolate command. */
10691 static int
10692 parse_isolate(struct context *ctx, const struct token *token,
10693 	      const char *str, unsigned int len,
10694 	      void *buf, unsigned int size)
10695 {
10696 	struct buffer *out = buf;
10697 
10698 	/* Token name must match. */
10699 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10700 		return -1;
10701 	/* Nothing else to do if there is no buffer. */
10702 	if (!out)
10703 		return len;
10704 	if (!out->command) {
10705 		if (ctx->curr != ISOLATE)
10706 			return -1;
10707 		if (sizeof(*out) > size)
10708 			return -1;
10709 		out->command = ctx->curr;
10710 		ctx->objdata = 0;
10711 		ctx->object = out;
10712 		ctx->objmask = NULL;
10713 	}
10714 	return len;
10715 }
10716 
10717 /** Parse tokens for info/configure command. */
10718 static int
10719 parse_configure(struct context *ctx, const struct token *token,
10720 		const char *str, unsigned int len,
10721 		void *buf, unsigned int size)
10722 {
10723 	struct buffer *out = buf;
10724 
10725 	/* Token name must match. */
10726 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10727 		return -1;
10728 	/* Nothing else to do if there is no buffer. */
10729 	if (!out)
10730 		return len;
10731 	if (!out->command) {
10732 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10733 			return -1;
10734 		if (sizeof(*out) > size)
10735 			return -1;
10736 		out->command = ctx->curr;
10737 		ctx->objdata = 0;
10738 		ctx->object = out;
10739 		ctx->objmask = NULL;
10740 	}
10741 	return len;
10742 }
10743 
10744 /** Parse tokens for template create command. */
10745 static int
10746 parse_template(struct context *ctx, const struct token *token,
10747 	       const char *str, unsigned int len,
10748 	       void *buf, unsigned int size)
10749 {
10750 	struct buffer *out = buf;
10751 
10752 	/* Token name must match. */
10753 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10754 		return -1;
10755 	/* Nothing else to do if there is no buffer. */
10756 	if (!out)
10757 		return len;
10758 	if (!out->command) {
10759 		if (ctx->curr != PATTERN_TEMPLATE &&
10760 		    ctx->curr != ACTIONS_TEMPLATE)
10761 			return -1;
10762 		if (sizeof(*out) > size)
10763 			return -1;
10764 		out->command = ctx->curr;
10765 		ctx->objdata = 0;
10766 		ctx->object = out;
10767 		ctx->objmask = NULL;
10768 		out->args.vc.data = (uint8_t *)out + size;
10769 		return len;
10770 	}
10771 	switch (ctx->curr) {
10772 	case PATTERN_TEMPLATE_CREATE:
10773 		out->args.vc.pattern =
10774 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10775 					       sizeof(double));
10776 		out->args.vc.pat_templ_id = UINT32_MAX;
10777 		out->command = ctx->curr;
10778 		ctx->objdata = 0;
10779 		ctx->object = out;
10780 		ctx->objmask = NULL;
10781 		return len;
10782 	case PATTERN_TEMPLATE_EGRESS:
10783 		out->args.vc.attr.egress = 1;
10784 		return len;
10785 	case PATTERN_TEMPLATE_INGRESS:
10786 		out->args.vc.attr.ingress = 1;
10787 		return len;
10788 	case PATTERN_TEMPLATE_TRANSFER:
10789 		out->args.vc.attr.transfer = 1;
10790 		return len;
10791 	case ACTIONS_TEMPLATE_CREATE:
10792 		out->args.vc.act_templ_id = UINT32_MAX;
10793 		out->command = ctx->curr;
10794 		ctx->objdata = 0;
10795 		ctx->object = out;
10796 		ctx->objmask = NULL;
10797 		return len;
10798 	case ACTIONS_TEMPLATE_SPEC:
10799 		out->args.vc.actions =
10800 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10801 					       sizeof(double));
10802 		ctx->object = out->args.vc.actions;
10803 		ctx->objmask = NULL;
10804 		return len;
10805 	case ACTIONS_TEMPLATE_MASK:
10806 		out->args.vc.masks =
10807 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10808 					       (out->args.vc.actions +
10809 						out->args.vc.actions_n),
10810 					       sizeof(double));
10811 		ctx->object = out->args.vc.masks;
10812 		ctx->objmask = NULL;
10813 		return len;
10814 	case ACTIONS_TEMPLATE_EGRESS:
10815 		out->args.vc.attr.egress = 1;
10816 		return len;
10817 	case ACTIONS_TEMPLATE_INGRESS:
10818 		out->args.vc.attr.ingress = 1;
10819 		return len;
10820 	case ACTIONS_TEMPLATE_TRANSFER:
10821 		out->args.vc.attr.transfer = 1;
10822 		return len;
10823 	default:
10824 		return -1;
10825 	}
10826 }
10827 
10828 /** Parse tokens for template destroy command. */
10829 static int
10830 parse_template_destroy(struct context *ctx, const struct token *token,
10831 		       const char *str, unsigned int len,
10832 		       void *buf, unsigned int size)
10833 {
10834 	struct buffer *out = buf;
10835 	uint32_t *template_id;
10836 
10837 	/* Token name must match. */
10838 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10839 		return -1;
10840 	/* Nothing else to do if there is no buffer. */
10841 	if (!out)
10842 		return len;
10843 	if (!out->command ||
10844 		out->command == PATTERN_TEMPLATE ||
10845 		out->command == ACTIONS_TEMPLATE) {
10846 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10847 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10848 			return -1;
10849 		if (sizeof(*out) > size)
10850 			return -1;
10851 		out->command = ctx->curr;
10852 		ctx->objdata = 0;
10853 		ctx->object = out;
10854 		ctx->objmask = NULL;
10855 		out->args.templ_destroy.template_id =
10856 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10857 					       sizeof(double));
10858 		return len;
10859 	}
10860 	template_id = out->args.templ_destroy.template_id
10861 		    + out->args.templ_destroy.template_id_n++;
10862 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10863 		return -1;
10864 	ctx->objdata = 0;
10865 	ctx->object = template_id;
10866 	ctx->objmask = NULL;
10867 	return len;
10868 }
10869 
10870 /** Parse tokens for table create command. */
10871 static int
10872 parse_table(struct context *ctx, const struct token *token,
10873 	    const char *str, unsigned int len,
10874 	    void *buf, unsigned int size)
10875 {
10876 	struct buffer *out = buf;
10877 	uint32_t *template_id;
10878 
10879 	/* Token name must match. */
10880 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10881 		return -1;
10882 	/* Nothing else to do if there is no buffer. */
10883 	if (!out)
10884 		return len;
10885 	if (!out->command) {
10886 		if (ctx->curr != TABLE)
10887 			return -1;
10888 		if (sizeof(*out) > size)
10889 			return -1;
10890 		out->command = ctx->curr;
10891 		ctx->objdata = 0;
10892 		ctx->object = out;
10893 		ctx->objmask = NULL;
10894 		return len;
10895 	}
10896 	switch (ctx->curr) {
10897 	case TABLE_CREATE:
10898 	case TABLE_RESIZE:
10899 		out->command = ctx->curr;
10900 		ctx->objdata = 0;
10901 		ctx->object = out;
10902 		ctx->objmask = NULL;
10903 		out->args.table.id = UINT32_MAX;
10904 		return len;
10905 	case TABLE_PATTERN_TEMPLATE:
10906 		out->args.table.pat_templ_id =
10907 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10908 					       sizeof(double));
10909 		template_id = out->args.table.pat_templ_id
10910 				+ out->args.table.pat_templ_id_n++;
10911 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10912 			return -1;
10913 		ctx->objdata = 0;
10914 		ctx->object = template_id;
10915 		ctx->objmask = NULL;
10916 		return len;
10917 	case TABLE_ACTIONS_TEMPLATE:
10918 		out->args.table.act_templ_id =
10919 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10920 					       (out->args.table.pat_templ_id +
10921 						out->args.table.pat_templ_id_n),
10922 					       sizeof(double));
10923 		template_id = out->args.table.act_templ_id
10924 				+ out->args.table.act_templ_id_n++;
10925 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10926 			return -1;
10927 		ctx->objdata = 0;
10928 		ctx->object = template_id;
10929 		ctx->objmask = NULL;
10930 		return len;
10931 	case TABLE_INGRESS:
10932 		out->args.table.attr.flow_attr.ingress = 1;
10933 		return len;
10934 	case TABLE_EGRESS:
10935 		out->args.table.attr.flow_attr.egress = 1;
10936 		return len;
10937 	case TABLE_TRANSFER:
10938 		out->args.table.attr.flow_attr.transfer = 1;
10939 		return len;
10940 	case TABLE_TRANSFER_WIRE_ORIG:
10941 		if (!out->args.table.attr.flow_attr.transfer)
10942 			return -1;
10943 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
10944 		return len;
10945 	case TABLE_TRANSFER_VPORT_ORIG:
10946 		if (!out->args.table.attr.flow_attr.transfer)
10947 			return -1;
10948 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
10949 		return len;
10950 	case TABLE_RESIZABLE:
10951 		out->args.table.attr.specialize |=
10952 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
10953 		return len;
10954 	case TABLE_RULES_NUMBER:
10955 		ctx->objdata = 0;
10956 		ctx->object = out;
10957 		ctx->objmask = NULL;
10958 		return len;
10959 	case TABLE_RESIZE_ID:
10960 	case TABLE_RESIZE_RULES_NUMBER:
10961 		return len;
10962 	default:
10963 		return -1;
10964 	}
10965 }
10966 
10967 /** Parse tokens for table destroy command. */
10968 static int
10969 parse_table_destroy(struct context *ctx, const struct token *token,
10970 		    const char *str, unsigned int len,
10971 		    void *buf, unsigned int size)
10972 {
10973 	struct buffer *out = buf;
10974 	uint32_t *table_id;
10975 
10976 	/* Token name must match. */
10977 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10978 		return -1;
10979 	/* Nothing else to do if there is no buffer. */
10980 	if (!out)
10981 		return len;
10982 	if (!out->command || out->command == TABLE) {
10983 		if (ctx->curr != TABLE_DESTROY &&
10984 		    ctx->curr != TABLE_RESIZE_COMPLETE)
10985 			return -1;
10986 		if (sizeof(*out) > size)
10987 			return -1;
10988 		out->command = ctx->curr;
10989 		ctx->objdata = 0;
10990 		ctx->object = out;
10991 		ctx->objmask = NULL;
10992 		out->args.table_destroy.table_id =
10993 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10994 					       sizeof(double));
10995 		return len;
10996 	}
10997 	table_id = out->args.table_destroy.table_id
10998 		    + out->args.table_destroy.table_id_n++;
10999 	if ((uint8_t *)table_id > (uint8_t *)out + size)
11000 		return -1;
11001 	ctx->objdata = 0;
11002 	ctx->object = table_id;
11003 	ctx->objmask = NULL;
11004 	return len;
11005 }
11006 
11007 /** Parse tokens for queue create commands. */
11008 static int
11009 parse_qo(struct context *ctx, const struct token *token,
11010 	 const char *str, unsigned int len,
11011 	 void *buf, unsigned int size)
11012 {
11013 	struct buffer *out = buf;
11014 
11015 	/* Token name must match. */
11016 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11017 		return -1;
11018 	/* Nothing else to do if there is no buffer. */
11019 	if (!out)
11020 		return len;
11021 	if (!out->command) {
11022 		if (ctx->curr != QUEUE)
11023 			return -1;
11024 		if (sizeof(*out) > size)
11025 			return -1;
11026 		out->command = ctx->curr;
11027 		ctx->objdata = 0;
11028 		ctx->object = out;
11029 		ctx->objmask = NULL;
11030 		out->args.vc.data = (uint8_t *)out + size;
11031 		return len;
11032 	}
11033 	switch (ctx->curr) {
11034 	case QUEUE_CREATE:
11035 	case QUEUE_UPDATE:
11036 		out->command = ctx->curr;
11037 		ctx->objdata = 0;
11038 		ctx->object = out;
11039 		ctx->objmask = NULL;
11040 		out->args.vc.rule_id = UINT32_MAX;
11041 		return len;
11042 	case QUEUE_TEMPLATE_TABLE:
11043 	case QUEUE_PATTERN_TEMPLATE:
11044 	case QUEUE_ACTIONS_TEMPLATE:
11045 	case QUEUE_CREATE_POSTPONE:
11046 	case QUEUE_RULE_ID:
11047 	case QUEUE_UPDATE_ID:
11048 		return len;
11049 	case ITEM_PATTERN:
11050 		out->args.vc.pattern =
11051 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11052 					       sizeof(double));
11053 		ctx->object = out->args.vc.pattern;
11054 		ctx->objmask = NULL;
11055 		return len;
11056 	case ACTIONS:
11057 		out->args.vc.actions =
11058 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11059 					       (out->args.vc.pattern +
11060 						out->args.vc.pattern_n),
11061 					       sizeof(double));
11062 		ctx->object = out->args.vc.actions;
11063 		ctx->objmask = NULL;
11064 		return len;
11065 	default:
11066 		return -1;
11067 	}
11068 }
11069 
11070 /** Parse tokens for queue destroy command. */
11071 static int
11072 parse_qo_destroy(struct context *ctx, const struct token *token,
11073 		 const char *str, unsigned int len,
11074 		 void *buf, unsigned int size)
11075 {
11076 	struct buffer *out = buf;
11077 	uint64_t *flow_id;
11078 
11079 	/* Token name must match. */
11080 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11081 		return -1;
11082 	/* Nothing else to do if there is no buffer. */
11083 	if (!out)
11084 		return len;
11085 	if (!out->command || out->command == QUEUE) {
11086 		if (ctx->curr != QUEUE_DESTROY &&
11087 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11088 			return -1;
11089 		if (sizeof(*out) > size)
11090 			return -1;
11091 		out->command = ctx->curr;
11092 		ctx->objdata = 0;
11093 		ctx->object = out;
11094 		ctx->objmask = NULL;
11095 		out->args.destroy.rule =
11096 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11097 					       sizeof(double));
11098 		return len;
11099 	}
11100 	switch (ctx->curr) {
11101 	case QUEUE_DESTROY_ID:
11102 		flow_id = out->args.destroy.rule
11103 				+ out->args.destroy.rule_n++;
11104 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11105 			return -1;
11106 		ctx->objdata = 0;
11107 		ctx->object = flow_id;
11108 		ctx->objmask = NULL;
11109 		return len;
11110 	case QUEUE_DESTROY_POSTPONE:
11111 		return len;
11112 	default:
11113 		return -1;
11114 	}
11115 }
11116 
11117 /** Parse tokens for push queue command. */
11118 static int
11119 parse_push(struct context *ctx, const struct token *token,
11120 	   const char *str, unsigned int len,
11121 	   void *buf, unsigned int size)
11122 {
11123 	struct buffer *out = buf;
11124 
11125 	/* Token name must match. */
11126 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11127 		return -1;
11128 	/* Nothing else to do if there is no buffer. */
11129 	if (!out)
11130 		return len;
11131 	if (!out->command) {
11132 		if (ctx->curr != PUSH)
11133 			return -1;
11134 		if (sizeof(*out) > size)
11135 			return -1;
11136 		out->command = ctx->curr;
11137 		ctx->objdata = 0;
11138 		ctx->object = out;
11139 		ctx->objmask = NULL;
11140 		out->args.vc.data = (uint8_t *)out + size;
11141 	}
11142 	return len;
11143 }
11144 
11145 /** Parse tokens for pull command. */
11146 static int
11147 parse_pull(struct context *ctx, const struct token *token,
11148 	   const char *str, unsigned int len,
11149 	   void *buf, unsigned int size)
11150 {
11151 	struct buffer *out = buf;
11152 
11153 	/* Token name must match. */
11154 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11155 		return -1;
11156 	/* Nothing else to do if there is no buffer. */
11157 	if (!out)
11158 		return len;
11159 	if (!out->command) {
11160 		if (ctx->curr != PULL)
11161 			return -1;
11162 		if (sizeof(*out) > size)
11163 			return -1;
11164 		out->command = ctx->curr;
11165 		ctx->objdata = 0;
11166 		ctx->object = out;
11167 		ctx->objmask = NULL;
11168 		out->args.vc.data = (uint8_t *)out + size;
11169 	}
11170 	return len;
11171 }
11172 
11173 /** Parse tokens for hash calculation commands. */
11174 static int
11175 parse_hash(struct context *ctx, const struct token *token,
11176 	 const char *str, unsigned int len,
11177 	 void *buf, unsigned int size)
11178 {
11179 	struct buffer *out = buf;
11180 
11181 	/* Token name must match. */
11182 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11183 		return -1;
11184 	/* Nothing else to do if there is no buffer. */
11185 	if (!out)
11186 		return len;
11187 	if (!out->command) {
11188 		if (ctx->curr != HASH)
11189 			return -1;
11190 		if (sizeof(*out) > size)
11191 			return -1;
11192 		out->command = ctx->curr;
11193 		ctx->objdata = 0;
11194 		ctx->object = out;
11195 		ctx->objmask = NULL;
11196 		out->args.vc.data = (uint8_t *)out + size;
11197 		return len;
11198 	}
11199 	switch (ctx->curr) {
11200 	case HASH_CALC_TABLE:
11201 	case HASH_CALC_PATTERN_INDEX:
11202 		return len;
11203 	case ITEM_PATTERN:
11204 		out->args.vc.pattern =
11205 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11206 					       sizeof(double));
11207 		ctx->object = out->args.vc.pattern;
11208 		ctx->objmask = NULL;
11209 		return len;
11210 	case HASH_CALC_ENCAP:
11211 		out->args.vc.encap_hash = 1;
11212 		return len;
11213 	case ENCAP_HASH_FIELD_SRC_PORT:
11214 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11215 		return len;
11216 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11217 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11218 		return len;
11219 	default:
11220 		return -1;
11221 	}
11222 }
11223 
11224 static int
11225 parse_group(struct context *ctx, const struct token *token,
11226 	    const char *str, unsigned int len,
11227 	    void *buf, unsigned int size)
11228 {
11229 	struct buffer *out = buf;
11230 
11231 	/* Token name must match. */
11232 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11233 		return -1;
11234 	/* Nothing else to do if there is no buffer. */
11235 	if (!out)
11236 		return len;
11237 	if (!out->command) {
11238 		if (ctx->curr != FLOW_GROUP)
11239 			return -1;
11240 		if (sizeof(*out) > size)
11241 			return -1;
11242 		out->command = ctx->curr;
11243 		ctx->objdata = 0;
11244 		ctx->object = out;
11245 		ctx->objmask = NULL;
11246 		out->args.vc.data = (uint8_t *)out + size;
11247 		return len;
11248 	}
11249 	switch (ctx->curr) {
11250 	case GROUP_INGRESS:
11251 		out->args.vc.attr.ingress = 1;
11252 		return len;
11253 	case GROUP_EGRESS:
11254 		out->args.vc.attr.egress = 1;
11255 		return len;
11256 	case GROUP_TRANSFER:
11257 		out->args.vc.attr.transfer = 1;
11258 		return len;
11259 	case GROUP_SET_MISS_ACTIONS:
11260 		out->command = ctx->curr;
11261 		ctx->objdata = 0;
11262 		ctx->object = out;
11263 		ctx->objmask = NULL;
11264 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11265 							       sizeof(double));
11266 		return len;
11267 	default:
11268 		return -1;
11269 	}
11270 }
11271 
11272 static int
11273 parse_flex(struct context *ctx, const struct token *token,
11274 	     const char *str, unsigned int len,
11275 	     void *buf, unsigned int size)
11276 {
11277 	struct buffer *out = buf;
11278 
11279 	/* Token name must match. */
11280 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11281 		return -1;
11282 	/* Nothing else to do if there is no buffer. */
11283 	if (!out)
11284 		return len;
11285 	if (out->command == ZERO) {
11286 		if (ctx->curr != FLEX)
11287 			return -1;
11288 		if (sizeof(*out) > size)
11289 			return -1;
11290 		out->command = ctx->curr;
11291 		ctx->objdata = 0;
11292 		ctx->object = out;
11293 		ctx->objmask = NULL;
11294 	} else {
11295 		switch (ctx->curr) {
11296 		default:
11297 			break;
11298 		case FLEX_ITEM_INIT:
11299 		case FLEX_ITEM_CREATE:
11300 		case FLEX_ITEM_DESTROY:
11301 			out->command = ctx->curr;
11302 			break;
11303 		}
11304 	}
11305 
11306 	return len;
11307 }
11308 
11309 static int
11310 parse_tunnel(struct context *ctx, const struct token *token,
11311 	     const char *str, unsigned int len,
11312 	     void *buf, unsigned int size)
11313 {
11314 	struct buffer *out = buf;
11315 
11316 	/* Token name must match. */
11317 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11318 		return -1;
11319 	/* Nothing else to do if there is no buffer. */
11320 	if (!out)
11321 		return len;
11322 	if (!out->command) {
11323 		if (ctx->curr != TUNNEL)
11324 			return -1;
11325 		if (sizeof(*out) > size)
11326 			return -1;
11327 		out->command = ctx->curr;
11328 		ctx->objdata = 0;
11329 		ctx->object = out;
11330 		ctx->objmask = NULL;
11331 	} else {
11332 		switch (ctx->curr) {
11333 		default:
11334 			break;
11335 		case TUNNEL_CREATE:
11336 		case TUNNEL_DESTROY:
11337 		case TUNNEL_LIST:
11338 			out->command = ctx->curr;
11339 			break;
11340 		case TUNNEL_CREATE_TYPE:
11341 		case TUNNEL_DESTROY_ID:
11342 			ctx->object = &out->args.vc.tunnel_ops;
11343 			break;
11344 		}
11345 	}
11346 
11347 	return len;
11348 }
11349 
11350 /**
11351  * Parse signed/unsigned integers 8 to 64-bit long.
11352  *
11353  * Last argument (ctx->args) is retrieved to determine integer type and
11354  * storage location.
11355  */
11356 static int
11357 parse_int(struct context *ctx, const struct token *token,
11358 	  const char *str, unsigned int len,
11359 	  void *buf, unsigned int size)
11360 {
11361 	const struct arg *arg = pop_args(ctx);
11362 	uintmax_t u;
11363 	char *end;
11364 
11365 	(void)token;
11366 	/* Argument is expected. */
11367 	if (!arg)
11368 		return -1;
11369 	errno = 0;
11370 	u = arg->sign ?
11371 		(uintmax_t)strtoimax(str, &end, 0) :
11372 		strtoumax(str, &end, 0);
11373 	if (errno || (size_t)(end - str) != len)
11374 		goto error;
11375 	if (arg->bounded &&
11376 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11377 			    (intmax_t)u > (intmax_t)arg->max)) ||
11378 	     (!arg->sign && (u < arg->min || u > arg->max))))
11379 		goto error;
11380 	if (!ctx->object)
11381 		return len;
11382 	if (arg->mask) {
11383 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11384 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11385 			goto error;
11386 		return len;
11387 	}
11388 	buf = (uint8_t *)ctx->object + arg->offset;
11389 	size = arg->size;
11390 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11391 		return -1;
11392 objmask:
11393 	switch (size) {
11394 	case sizeof(uint8_t):
11395 		*(uint8_t *)buf = u;
11396 		break;
11397 	case sizeof(uint16_t):
11398 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11399 		break;
11400 	case sizeof(uint8_t [3]):
11401 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11402 		if (!arg->hton) {
11403 			((uint8_t *)buf)[0] = u;
11404 			((uint8_t *)buf)[1] = u >> 8;
11405 			((uint8_t *)buf)[2] = u >> 16;
11406 			break;
11407 		}
11408 #endif
11409 		((uint8_t *)buf)[0] = u >> 16;
11410 		((uint8_t *)buf)[1] = u >> 8;
11411 		((uint8_t *)buf)[2] = u;
11412 		break;
11413 	case sizeof(uint32_t):
11414 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11415 		break;
11416 	case sizeof(uint64_t):
11417 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11418 		break;
11419 	default:
11420 		goto error;
11421 	}
11422 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11423 		u = -1;
11424 		buf = (uint8_t *)ctx->objmask + arg->offset;
11425 		goto objmask;
11426 	}
11427 	return len;
11428 error:
11429 	push_args(ctx, arg);
11430 	return -1;
11431 }
11432 
11433 /**
11434  * Parse a string.
11435  *
11436  * Three arguments (ctx->args) are retrieved from the stack to store data,
11437  * its actual length and address (in that order).
11438  */
11439 static int
11440 parse_string(struct context *ctx, const struct token *token,
11441 	     const char *str, unsigned int len,
11442 	     void *buf, unsigned int size)
11443 {
11444 	const struct arg *arg_data = pop_args(ctx);
11445 	const struct arg *arg_len = pop_args(ctx);
11446 	const struct arg *arg_addr = pop_args(ctx);
11447 	char tmp[16]; /* Ought to be enough. */
11448 	int ret;
11449 
11450 	/* Arguments are expected. */
11451 	if (!arg_data)
11452 		return -1;
11453 	if (!arg_len) {
11454 		push_args(ctx, arg_data);
11455 		return -1;
11456 	}
11457 	if (!arg_addr) {
11458 		push_args(ctx, arg_len);
11459 		push_args(ctx, arg_data);
11460 		return -1;
11461 	}
11462 	size = arg_data->size;
11463 	/* Bit-mask fill is not supported. */
11464 	if (arg_data->mask || size < len)
11465 		goto error;
11466 	if (!ctx->object)
11467 		return len;
11468 	/* Let parse_int() fill length information first. */
11469 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11470 	if (ret < 0)
11471 		goto error;
11472 	push_args(ctx, arg_len);
11473 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11474 	if (ret < 0) {
11475 		pop_args(ctx);
11476 		goto error;
11477 	}
11478 	buf = (uint8_t *)ctx->object + arg_data->offset;
11479 	/* Output buffer is not necessarily NUL-terminated. */
11480 	memcpy(buf, str, len);
11481 	memset((uint8_t *)buf + len, 0x00, size - len);
11482 	if (ctx->objmask)
11483 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11484 	/* Save address if requested. */
11485 	if (arg_addr->size) {
11486 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11487 		       (void *[]){
11488 			(uint8_t *)ctx->object + arg_data->offset
11489 		       },
11490 		       arg_addr->size);
11491 		if (ctx->objmask)
11492 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11493 			       (void *[]){
11494 				(uint8_t *)ctx->objmask + arg_data->offset
11495 			       },
11496 			       arg_addr->size);
11497 	}
11498 	return len;
11499 error:
11500 	push_args(ctx, arg_addr);
11501 	push_args(ctx, arg_len);
11502 	push_args(ctx, arg_data);
11503 	return -1;
11504 }
11505 
11506 static int
11507 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11508 {
11509 	const uint8_t *head = dst;
11510 	uint32_t left;
11511 
11512 	if (*size == 0)
11513 		return -1;
11514 
11515 	left = *size;
11516 
11517 	/* Convert chars to bytes */
11518 	while (left) {
11519 		char tmp[3], *end = tmp;
11520 		uint32_t read_lim = left & 1 ? 1 : 2;
11521 
11522 		snprintf(tmp, read_lim + 1, "%s", src);
11523 		*dst = strtoul(tmp, &end, 16);
11524 		if (*end) {
11525 			*dst = 0;
11526 			*size = (uint32_t)(dst - head);
11527 			return -1;
11528 		}
11529 		left -= read_lim;
11530 		src += read_lim;
11531 		dst++;
11532 	}
11533 	*dst = 0;
11534 	*size = (uint32_t)(dst - head);
11535 	return 0;
11536 }
11537 
11538 static int
11539 parse_hex(struct context *ctx, const struct token *token,
11540 		const char *str, unsigned int len,
11541 		void *buf, unsigned int size)
11542 {
11543 	const struct arg *arg_data = pop_args(ctx);
11544 	const struct arg *arg_len = pop_args(ctx);
11545 	const struct arg *arg_addr = pop_args(ctx);
11546 	char tmp[16]; /* Ought to be enough. */
11547 	int ret;
11548 	unsigned int hexlen = len;
11549 	unsigned int length = 256;
11550 	uint8_t hex_tmp[length];
11551 
11552 	/* Arguments are expected. */
11553 	if (!arg_data)
11554 		return -1;
11555 	if (!arg_len) {
11556 		push_args(ctx, arg_data);
11557 		return -1;
11558 	}
11559 	if (!arg_addr) {
11560 		push_args(ctx, arg_len);
11561 		push_args(ctx, arg_data);
11562 		return -1;
11563 	}
11564 	size = arg_data->size;
11565 	/* Bit-mask fill is not supported. */
11566 	if (arg_data->mask)
11567 		goto error;
11568 	if (!ctx->object)
11569 		return len;
11570 
11571 	/* translate bytes string to array. */
11572 	if (str[0] == '0' && ((str[1] == 'x') ||
11573 			(str[1] == 'X'))) {
11574 		str += 2;
11575 		hexlen -= 2;
11576 	}
11577 	if (hexlen > length)
11578 		goto error;
11579 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11580 	if (ret < 0)
11581 		goto error;
11582 	/* Check the converted binary fits into data buffer. */
11583 	if (hexlen > size)
11584 		goto error;
11585 	/* Let parse_int() fill length information first. */
11586 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11587 	if (ret < 0)
11588 		goto error;
11589 	/* Save length if requested. */
11590 	if (arg_len->size) {
11591 		push_args(ctx, arg_len);
11592 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11593 		if (ret < 0) {
11594 			pop_args(ctx);
11595 			goto error;
11596 		}
11597 	}
11598 	buf = (uint8_t *)ctx->object + arg_data->offset;
11599 	/* Output buffer is not necessarily NUL-terminated. */
11600 	memcpy(buf, hex_tmp, hexlen);
11601 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11602 	if (ctx->objmask)
11603 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11604 					0xff, hexlen);
11605 	/* Save address if requested. */
11606 	if (arg_addr->size) {
11607 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11608 		       (void *[]){
11609 			(uint8_t *)ctx->object + arg_data->offset
11610 		       },
11611 		       arg_addr->size);
11612 		if (ctx->objmask)
11613 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11614 			       (void *[]){
11615 				(uint8_t *)ctx->objmask + arg_data->offset
11616 			       },
11617 			       arg_addr->size);
11618 	}
11619 	return len;
11620 error:
11621 	push_args(ctx, arg_addr);
11622 	push_args(ctx, arg_len);
11623 	push_args(ctx, arg_data);
11624 	return -1;
11625 
11626 }
11627 
11628 /**
11629  * Parse a zero-ended string.
11630  */
11631 static int
11632 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11633 	     const char *str, unsigned int len,
11634 	     void *buf, unsigned int size)
11635 {
11636 	const struct arg *arg_data = pop_args(ctx);
11637 
11638 	/* Arguments are expected. */
11639 	if (!arg_data)
11640 		return -1;
11641 	size = arg_data->size;
11642 	/* Bit-mask fill is not supported. */
11643 	if (arg_data->mask || size < len + 1)
11644 		goto error;
11645 	if (!ctx->object)
11646 		return len;
11647 	buf = (uint8_t *)ctx->object + arg_data->offset;
11648 	strncpy(buf, str, len);
11649 	if (ctx->objmask)
11650 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11651 	return len;
11652 error:
11653 	push_args(ctx, arg_data);
11654 	return -1;
11655 }
11656 
11657 /**
11658  * Parse a MAC address.
11659  *
11660  * Last argument (ctx->args) is retrieved to determine storage size and
11661  * location.
11662  */
11663 static int
11664 parse_mac_addr(struct context *ctx, const struct token *token,
11665 	       const char *str, unsigned int len,
11666 	       void *buf, unsigned int size)
11667 {
11668 	const struct arg *arg = pop_args(ctx);
11669 	struct rte_ether_addr tmp;
11670 	int ret;
11671 
11672 	(void)token;
11673 	/* Argument is expected. */
11674 	if (!arg)
11675 		return -1;
11676 	size = arg->size;
11677 	/* Bit-mask fill is not supported. */
11678 	if (arg->mask || size != sizeof(tmp))
11679 		goto error;
11680 	/* Only network endian is supported. */
11681 	if (!arg->hton)
11682 		goto error;
11683 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11684 	if (ret < 0 || (unsigned int)ret != len)
11685 		goto error;
11686 	if (!ctx->object)
11687 		return len;
11688 	buf = (uint8_t *)ctx->object + arg->offset;
11689 	memcpy(buf, &tmp, size);
11690 	if (ctx->objmask)
11691 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11692 	return len;
11693 error:
11694 	push_args(ctx, arg);
11695 	return -1;
11696 }
11697 
11698 /**
11699  * Parse an IPv4 address.
11700  *
11701  * Last argument (ctx->args) is retrieved to determine storage size and
11702  * location.
11703  */
11704 static int
11705 parse_ipv4_addr(struct context *ctx, const struct token *token,
11706 		const char *str, unsigned int len,
11707 		void *buf, unsigned int size)
11708 {
11709 	const struct arg *arg = pop_args(ctx);
11710 	char str2[len + 1];
11711 	struct in_addr tmp;
11712 	int ret;
11713 
11714 	/* Argument is expected. */
11715 	if (!arg)
11716 		return -1;
11717 	size = arg->size;
11718 	/* Bit-mask fill is not supported. */
11719 	if (arg->mask || size != sizeof(tmp))
11720 		goto error;
11721 	/* Only network endian is supported. */
11722 	if (!arg->hton)
11723 		goto error;
11724 	memcpy(str2, str, len);
11725 	str2[len] = '\0';
11726 	ret = inet_pton(AF_INET, str2, &tmp);
11727 	if (ret != 1) {
11728 		/* Attempt integer parsing. */
11729 		push_args(ctx, arg);
11730 		return parse_int(ctx, token, str, len, buf, size);
11731 	}
11732 	if (!ctx->object)
11733 		return len;
11734 	buf = (uint8_t *)ctx->object + arg->offset;
11735 	memcpy(buf, &tmp, size);
11736 	if (ctx->objmask)
11737 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11738 	return len;
11739 error:
11740 	push_args(ctx, arg);
11741 	return -1;
11742 }
11743 
11744 /**
11745  * Parse an IPv6 address.
11746  *
11747  * Last argument (ctx->args) is retrieved to determine storage size and
11748  * location.
11749  */
11750 static int
11751 parse_ipv6_addr(struct context *ctx, const struct token *token,
11752 		const char *str, unsigned int len,
11753 		void *buf, unsigned int size)
11754 {
11755 	const struct arg *arg = pop_args(ctx);
11756 	char str2[len + 1];
11757 	struct in6_addr tmp;
11758 	int ret;
11759 
11760 	(void)token;
11761 	/* Argument is expected. */
11762 	if (!arg)
11763 		return -1;
11764 	size = arg->size;
11765 	/* Bit-mask fill is not supported. */
11766 	if (arg->mask || size != sizeof(tmp))
11767 		goto error;
11768 	/* Only network endian is supported. */
11769 	if (!arg->hton)
11770 		goto error;
11771 	memcpy(str2, str, len);
11772 	str2[len] = '\0';
11773 	ret = inet_pton(AF_INET6, str2, &tmp);
11774 	if (ret != 1)
11775 		goto error;
11776 	if (!ctx->object)
11777 		return len;
11778 	buf = (uint8_t *)ctx->object + arg->offset;
11779 	memcpy(buf, &tmp, size);
11780 	if (ctx->objmask)
11781 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11782 	return len;
11783 error:
11784 	push_args(ctx, arg);
11785 	return -1;
11786 }
11787 
11788 /** Boolean values (even indices stand for false). */
11789 static const char *const boolean_name[] = {
11790 	"0", "1",
11791 	"false", "true",
11792 	"no", "yes",
11793 	"N", "Y",
11794 	"off", "on",
11795 	NULL,
11796 };
11797 
11798 /**
11799  * Parse a boolean value.
11800  *
11801  * Last argument (ctx->args) is retrieved to determine storage size and
11802  * location.
11803  */
11804 static int
11805 parse_boolean(struct context *ctx, const struct token *token,
11806 	      const char *str, unsigned int len,
11807 	      void *buf, unsigned int size)
11808 {
11809 	const struct arg *arg = pop_args(ctx);
11810 	unsigned int i;
11811 	int ret;
11812 
11813 	/* Argument is expected. */
11814 	if (!arg)
11815 		return -1;
11816 	for (i = 0; boolean_name[i]; ++i)
11817 		if (!strcmp_partial(boolean_name[i], str, len))
11818 			break;
11819 	/* Process token as integer. */
11820 	if (boolean_name[i])
11821 		str = i & 1 ? "1" : "0";
11822 	push_args(ctx, arg);
11823 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11824 	return ret > 0 ? (int)len : ret;
11825 }
11826 
11827 /** Parse port and update context. */
11828 static int
11829 parse_port(struct context *ctx, const struct token *token,
11830 	   const char *str, unsigned int len,
11831 	   void *buf, unsigned int size)
11832 {
11833 	struct buffer *out = &(struct buffer){ .port = 0 };
11834 	int ret;
11835 
11836 	if (buf)
11837 		out = buf;
11838 	else {
11839 		ctx->objdata = 0;
11840 		ctx->object = out;
11841 		ctx->objmask = NULL;
11842 		size = sizeof(*out);
11843 	}
11844 	ret = parse_int(ctx, token, str, len, out, size);
11845 	if (ret >= 0)
11846 		ctx->port = out->port;
11847 	if (!buf)
11848 		ctx->object = NULL;
11849 	return ret;
11850 }
11851 
11852 /** Parse tokens for shared indirect actions. */
11853 static int
11854 parse_ia_port(struct context *ctx, const struct token *token,
11855 	      const char *str, unsigned int len,
11856 	      void *buf, unsigned int size)
11857 {
11858 	struct rte_flow_action *action = ctx->object;
11859 	uint32_t id;
11860 	int ret;
11861 
11862 	(void)buf;
11863 	(void)size;
11864 	ctx->objdata = 0;
11865 	ctx->object = &id;
11866 	ctx->objmask = NULL;
11867 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11868 	ctx->object = action;
11869 	if (ret != (int)len)
11870 		return ret;
11871 	/* set indirect action */
11872 	if (action)
11873 		action->conf = (void *)(uintptr_t)id;
11874 	return ret;
11875 }
11876 
11877 static int
11878 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11879 		const char *str, unsigned int len,
11880 		void *buf, unsigned int size)
11881 {
11882 	struct rte_flow_action *action = ctx->object;
11883 	uint32_t id;
11884 	int ret;
11885 
11886 	(void)buf;
11887 	(void)size;
11888 	ctx->objdata = 0;
11889 	ctx->object = &id;
11890 	ctx->objmask = NULL;
11891 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11892 	ctx->object = action;
11893 	if (ret != (int)len)
11894 		return ret;
11895 	/* set indirect action */
11896 	if (action) {
11897 		portid_t port_id = ctx->port;
11898 		if (ctx->prev == INDIRECT_ACTION_PORT)
11899 			port_id = (portid_t)(uintptr_t)action->conf;
11900 		action->conf = port_action_handle_get_by_id(port_id, id);
11901 		ret = (action->conf) ? ret : -1;
11902 	}
11903 	return ret;
11904 }
11905 
11906 static int
11907 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11908 		    const char *str, unsigned int len,
11909 		    __rte_unused void *buf, __rte_unused unsigned int size)
11910 {
11911 	struct rte_flow_action *action = ctx->object;
11912 	struct rte_flow_action_indirect_list *action_conf;
11913 	const struct indlst_conf *indlst_conf;
11914 	uint32_t id;
11915 	int ret;
11916 
11917 	ctx->objdata = 0;
11918 	ctx->object = &id;
11919 	ctx->objmask = NULL;
11920 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11921 	ctx->object = action;
11922 	if (ret != (int)len)
11923 		return ret;
11924 
11925 	/* set handle and conf */
11926 	if (action) {
11927 		action_conf = (void *)(uintptr_t)action->conf;
11928 		action_conf->conf = NULL;
11929 		switch (ctx->curr) {
11930 		case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
11931 		action_conf->handle = (typeof(action_conf->handle))
11932 					port_action_handle_get_by_id(ctx->port, id);
11933 			if (!action_conf->handle) {
11934 				printf("no indirect list handle for id %u\n", id);
11935 				return -1;
11936 			}
11937 			break;
11938 		case INDIRECT_LIST_ACTION_ID2PTR_CONF:
11939 			indlst_conf = indirect_action_list_conf_get(id);
11940 			if (!indlst_conf)
11941 				return -1;
11942 			action_conf->conf = (const void **)indlst_conf->conf;
11943 			break;
11944 		default:
11945 			break;
11946 		}
11947 	}
11948 	return ret;
11949 }
11950 
11951 static int
11952 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
11953 		const char *str, unsigned int len,
11954 		void *buf, unsigned int size)
11955 {
11956 	struct rte_flow_action *action = ctx->object;
11957 	struct rte_flow_action_meter_mark *meter;
11958 	struct rte_flow_meter_profile *profile = NULL;
11959 	uint32_t id = 0;
11960 	int ret;
11961 
11962 	(void)buf;
11963 	(void)size;
11964 	ctx->objdata = 0;
11965 	ctx->object = &id;
11966 	ctx->objmask = NULL;
11967 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11968 	ctx->object = action;
11969 	if (ret != (int)len)
11970 		return ret;
11971 	/* set meter profile */
11972 	if (action) {
11973 		meter = (struct rte_flow_action_meter_mark *)
11974 			(uintptr_t)(action->conf);
11975 		profile = port_meter_profile_get_by_id(ctx->port, id);
11976 		meter->profile = profile;
11977 		ret = (profile) ? ret : -1;
11978 	}
11979 	return ret;
11980 }
11981 
11982 static int
11983 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
11984 		const char *str, unsigned int len,
11985 		void *buf, unsigned int size)
11986 {
11987 	struct rte_flow_action *action = ctx->object;
11988 	struct rte_flow_action_meter_mark *meter;
11989 	struct rte_flow_meter_policy *policy = NULL;
11990 	uint32_t id = 0;
11991 	int ret;
11992 
11993 	(void)buf;
11994 	(void)size;
11995 	ctx->objdata = 0;
11996 	ctx->object = &id;
11997 	ctx->objmask = NULL;
11998 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11999 	ctx->object = action;
12000 	if (ret != (int)len)
12001 		return ret;
12002 	/* set meter policy */
12003 	if (action) {
12004 		meter = (struct rte_flow_action_meter_mark *)
12005 			(uintptr_t)(action->conf);
12006 		policy = port_meter_policy_get_by_id(ctx->port, id);
12007 		meter->policy = policy;
12008 		ret = (policy) ? ret : -1;
12009 	}
12010 	return ret;
12011 }
12012 
12013 /** Parse set command, initialize output buffer for subsequent tokens. */
12014 static int
12015 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12016 			  const char *str, unsigned int len,
12017 			  void *buf, unsigned int size)
12018 {
12019 	struct buffer *out = buf;
12020 
12021 	/* Token name must match. */
12022 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12023 		return -1;
12024 	/* Nothing else to do if there is no buffer. */
12025 	if (!out)
12026 		return len;
12027 	/* Make sure buffer is large enough. */
12028 	if (size < sizeof(*out))
12029 		return -1;
12030 	ctx->objdata = 0;
12031 	ctx->objmask = NULL;
12032 	ctx->object = out;
12033 	if (!out->command)
12034 		return -1;
12035 	out->command = ctx->curr;
12036 	/* For encap/decap we need is pattern */
12037 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12038 						       sizeof(double));
12039 	return len;
12040 }
12041 
12042 /** Parse set command, initialize output buffer for subsequent tokens. */
12043 static int
12044 parse_set_sample_action(struct context *ctx, const struct token *token,
12045 			  const char *str, unsigned int len,
12046 			  void *buf, unsigned int size)
12047 {
12048 	struct buffer *out = buf;
12049 
12050 	/* Token name must match. */
12051 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12052 		return -1;
12053 	/* Nothing else to do if there is no buffer. */
12054 	if (!out)
12055 		return len;
12056 	/* Make sure buffer is large enough. */
12057 	if (size < sizeof(*out))
12058 		return -1;
12059 	ctx->objdata = 0;
12060 	ctx->objmask = NULL;
12061 	ctx->object = out;
12062 	if (!out->command)
12063 		return -1;
12064 	out->command = ctx->curr;
12065 	/* For sampler we need is actions */
12066 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12067 						       sizeof(double));
12068 	return len;
12069 }
12070 
12071 /** Parse set command, initialize output buffer for subsequent tokens. */
12072 static int
12073 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12074 			  const char *str, unsigned int len,
12075 			  void *buf, unsigned int size)
12076 {
12077 	struct buffer *out = buf;
12078 
12079 	/* Token name must match. */
12080 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12081 		return -1;
12082 	/* Nothing else to do if there is no buffer. */
12083 	if (!out)
12084 		return len;
12085 	/* Make sure buffer is large enough. */
12086 	if (size < sizeof(*out))
12087 		return -1;
12088 	ctx->objdata = 0;
12089 	ctx->objmask = NULL;
12090 	ctx->object = out;
12091 	if (!out->command)
12092 		return -1;
12093 	out->command = ctx->curr;
12094 	/* For ipv6_ext_push/remove we need is pattern */
12095 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12096 						       sizeof(double));
12097 	return len;
12098 }
12099 
12100 /**
12101  * Parse set raw_encap/raw_decap command,
12102  * initialize output buffer for subsequent tokens.
12103  */
12104 static int
12105 parse_set_init(struct context *ctx, const struct token *token,
12106 	       const char *str, unsigned int len,
12107 	       void *buf, unsigned int size)
12108 {
12109 	struct buffer *out = buf;
12110 
12111 	/* Token name must match. */
12112 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12113 		return -1;
12114 	/* Nothing else to do if there is no buffer. */
12115 	if (!out)
12116 		return len;
12117 	/* Make sure buffer is large enough. */
12118 	if (size < sizeof(*out))
12119 		return -1;
12120 	/* Initialize buffer. */
12121 	memset(out, 0x00, sizeof(*out));
12122 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12123 	ctx->objdata = 0;
12124 	ctx->object = out;
12125 	ctx->objmask = NULL;
12126 	if (!out->command) {
12127 		if (ctx->curr != SET)
12128 			return -1;
12129 		if (sizeof(*out) > size)
12130 			return -1;
12131 		out->command = ctx->curr;
12132 		out->args.vc.data = (uint8_t *)out + size;
12133 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12134 						       sizeof(double));
12135 	}
12136 	return len;
12137 }
12138 
12139 /*
12140  * Replace testpmd handles in a flex flow item with real values.
12141  */
12142 static int
12143 parse_flex_handle(struct context *ctx, const struct token *token,
12144 		  const char *str, unsigned int len,
12145 		  void *buf, unsigned int size)
12146 {
12147 	struct rte_flow_item_flex *spec, *mask;
12148 	const struct rte_flow_item_flex *src_spec, *src_mask;
12149 	const struct arg *arg = pop_args(ctx);
12150 	uint32_t offset;
12151 	uint16_t handle;
12152 	int ret;
12153 
12154 	if (!arg) {
12155 		printf("Bad environment\n");
12156 		return -1;
12157 	}
12158 	offset = arg->offset;
12159 	push_args(ctx, arg);
12160 	ret = parse_int(ctx, token, str, len, buf, size);
12161 	if (ret <= 0 || !ctx->object)
12162 		return ret;
12163 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12164 		printf("Bad port\n");
12165 		return -1;
12166 	}
12167 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12168 		const struct flex_item *fp;
12169 		spec = ctx->object;
12170 		handle = (uint16_t)(uintptr_t)spec->handle;
12171 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12172 			printf("Bad flex item handle\n");
12173 			return -1;
12174 		}
12175 		fp = flex_items[ctx->port][handle];
12176 		if (!fp) {
12177 			printf("Bad flex item handle\n");
12178 			return -1;
12179 		}
12180 		spec->handle = fp->flex_handle;
12181 		mask = spec + 2; /* spec, last, mask */
12182 		mask->handle = fp->flex_handle;
12183 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12184 		handle = (uint16_t)(uintptr_t)
12185 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12186 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12187 			printf("Bad pattern handle\n");
12188 			return -1;
12189 		}
12190 		src_spec = &flex_patterns[handle].spec;
12191 		src_mask = &flex_patterns[handle].mask;
12192 		spec = ctx->object;
12193 		mask = spec + 2; /* spec, last, mask */
12194 		/* fill flow rule spec and mask parameters */
12195 		spec->length = src_spec->length;
12196 		spec->pattern = src_spec->pattern;
12197 		mask->length = src_mask->length;
12198 		mask->pattern = src_mask->pattern;
12199 	} else {
12200 		printf("Bad arguments - unknown flex item offset\n");
12201 		return -1;
12202 	}
12203 	return ret;
12204 }
12205 
12206 /** Parse Meter color name */
12207 static int
12208 parse_meter_color(struct context *ctx, const struct token *token,
12209 		  const char *str, unsigned int len, void *buf,
12210 		  unsigned int size)
12211 {
12212 	struct rte_flow_item_meter_color *meter_color;
12213 	unsigned int i;
12214 
12215 	(void)token;
12216 	(void)buf;
12217 	(void)size;
12218 	for (i = 0; meter_colors[i]; ++i)
12219 		if (!strcmp_partial(meter_colors[i], str, len))
12220 			break;
12221 	if (!meter_colors[i])
12222 		return -1;
12223 	if (!ctx->object)
12224 		return len;
12225 	meter_color = ctx->object;
12226 	meter_color->color = (enum rte_color)i;
12227 	return len;
12228 }
12229 
12230 /** Parse Insertion Table Type name */
12231 static int
12232 parse_insertion_table_type(struct context *ctx, const struct token *token,
12233 			   const char *str, unsigned int len, void *buf,
12234 			   unsigned int size)
12235 {
12236 	const struct arg *arg = pop_args(ctx);
12237 	unsigned int i;
12238 	char tmp[2];
12239 	int ret;
12240 
12241 	(void)size;
12242 	/* Argument is expected. */
12243 	if (!arg)
12244 		return -1;
12245 	for (i = 0; table_insertion_types[i]; ++i)
12246 		if (!strcmp_partial(table_insertion_types[i], str, len))
12247 			break;
12248 	if (!table_insertion_types[i])
12249 		return -1;
12250 	push_args(ctx, arg);
12251 	snprintf(tmp, sizeof(tmp), "%u", i);
12252 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12253 	return ret > 0 ? (int)len : ret;
12254 }
12255 
12256 /** Parse Hash Calculation Table Type name */
12257 static int
12258 parse_hash_table_type(struct context *ctx, const struct token *token,
12259 		      const char *str, unsigned int len, void *buf,
12260 		      unsigned int size)
12261 {
12262 	const struct arg *arg = pop_args(ctx);
12263 	unsigned int i;
12264 	char tmp[2];
12265 	int ret;
12266 
12267 	(void)size;
12268 	/* Argument is expected. */
12269 	if (!arg)
12270 		return -1;
12271 	for (i = 0; table_hash_funcs[i]; ++i)
12272 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12273 			break;
12274 	if (!table_hash_funcs[i])
12275 		return -1;
12276 	push_args(ctx, arg);
12277 	snprintf(tmp, sizeof(tmp), "%u", i);
12278 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12279 	return ret > 0 ? (int)len : ret;
12280 }
12281 
12282 static int
12283 parse_name_to_index(struct context *ctx, const struct token *token,
12284 		    const char *str, unsigned int len, void *buf,
12285 		    unsigned int size,
12286 		    const char *const names[], size_t names_size, uint32_t *dst)
12287 {
12288 	int ret;
12289 	uint32_t i;
12290 
12291 	RTE_SET_USED(token);
12292 	RTE_SET_USED(buf);
12293 	RTE_SET_USED(size);
12294 	if (!ctx->object)
12295 		return len;
12296 	for (i = 0; i < names_size; i++) {
12297 		if (!names[i])
12298 			continue;
12299 		ret = strcmp_partial(names[i], str,
12300 				     RTE_MIN(len, strlen(names[i])));
12301 		if (!ret) {
12302 			*dst = i;
12303 			return len;
12304 		}
12305 	}
12306 	return -1;
12307 }
12308 
12309 static const char *const quota_mode_names[] = {
12310 	NULL,
12311 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12312 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12313 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12314 };
12315 
12316 static const char *const quota_state_names[] = {
12317 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12318 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12319 };
12320 
12321 static const char *const quota_update_names[] = {
12322 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12323 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12324 };
12325 
12326 static const char *const query_update_mode_names[] = {
12327 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12328 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12329 };
12330 
12331 static int
12332 parse_quota_state_name(struct context *ctx, const struct token *token,
12333 		       const char *str, unsigned int len, void *buf,
12334 		       unsigned int size)
12335 {
12336 	struct rte_flow_item_quota *quota = ctx->object;
12337 
12338 	return parse_name_to_index(ctx, token, str, len, buf, size,
12339 				   quota_state_names,
12340 				   RTE_DIM(quota_state_names),
12341 				   (uint32_t *)&quota->state);
12342 }
12343 
12344 static int
12345 parse_quota_mode_name(struct context *ctx, const struct token *token,
12346 		      const char *str, unsigned int len, void *buf,
12347 		      unsigned int size)
12348 {
12349 	struct rte_flow_action_quota *quota = ctx->object;
12350 
12351 	return parse_name_to_index(ctx, token, str, len, buf, size,
12352 				   quota_mode_names,
12353 				   RTE_DIM(quota_mode_names),
12354 				   (uint32_t *)&quota->mode);
12355 }
12356 
12357 static int
12358 parse_quota_update_name(struct context *ctx, const struct token *token,
12359 			const char *str, unsigned int len, void *buf,
12360 			unsigned int size)
12361 {
12362 	struct rte_flow_update_quota *update = ctx->object;
12363 
12364 	return parse_name_to_index(ctx, token, str, len, buf, size,
12365 				   quota_update_names,
12366 				   RTE_DIM(quota_update_names),
12367 				   (uint32_t *)&update->op);
12368 }
12369 
12370 static int
12371 parse_qu_mode_name(struct context *ctx, const struct token *token,
12372 		   const char *str, unsigned int len, void *buf,
12373 		   unsigned int size)
12374 {
12375 	struct buffer *out = ctx->object;
12376 
12377 	return parse_name_to_index(ctx, token, str, len, buf, size,
12378 				   query_update_mode_names,
12379 				   RTE_DIM(query_update_mode_names),
12380 				   (uint32_t *)&out->args.ia.qu_mode);
12381 }
12382 
12383 /** No completion. */
12384 static int
12385 comp_none(struct context *ctx, const struct token *token,
12386 	  unsigned int ent, char *buf, unsigned int size)
12387 {
12388 	(void)ctx;
12389 	(void)token;
12390 	(void)ent;
12391 	(void)buf;
12392 	(void)size;
12393 	return 0;
12394 }
12395 
12396 /** Complete boolean values. */
12397 static int
12398 comp_boolean(struct context *ctx, const struct token *token,
12399 	     unsigned int ent, char *buf, unsigned int size)
12400 {
12401 	unsigned int i;
12402 
12403 	(void)ctx;
12404 	(void)token;
12405 	for (i = 0; boolean_name[i]; ++i)
12406 		if (buf && i == ent)
12407 			return strlcpy(buf, boolean_name[i], size);
12408 	if (buf)
12409 		return -1;
12410 	return i;
12411 }
12412 
12413 /** Complete action names. */
12414 static int
12415 comp_action(struct context *ctx, const struct token *token,
12416 	    unsigned int ent, char *buf, unsigned int size)
12417 {
12418 	unsigned int i;
12419 
12420 	(void)ctx;
12421 	(void)token;
12422 	for (i = 0; next_action[i]; ++i)
12423 		if (buf && i == ent)
12424 			return strlcpy(buf, token_list[next_action[i]].name,
12425 				       size);
12426 	if (buf)
12427 		return -1;
12428 	return i;
12429 }
12430 
12431 /** Complete available ports. */
12432 static int
12433 comp_port(struct context *ctx, const struct token *token,
12434 	  unsigned int ent, char *buf, unsigned int size)
12435 {
12436 	unsigned int i = 0;
12437 	portid_t p;
12438 
12439 	(void)ctx;
12440 	(void)token;
12441 	RTE_ETH_FOREACH_DEV(p) {
12442 		if (buf && i == ent)
12443 			return snprintf(buf, size, "%u", p);
12444 		++i;
12445 	}
12446 	if (buf)
12447 		return -1;
12448 	return i;
12449 }
12450 
12451 /** Complete available rule IDs. */
12452 static int
12453 comp_rule_id(struct context *ctx, const struct token *token,
12454 	     unsigned int ent, char *buf, unsigned int size)
12455 {
12456 	unsigned int i = 0;
12457 	struct rte_port *port;
12458 	struct port_flow *pf;
12459 
12460 	(void)token;
12461 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12462 	    ctx->port == (portid_t)RTE_PORT_ALL)
12463 		return -1;
12464 	port = &ports[ctx->port];
12465 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12466 		if (buf && i == ent)
12467 			return snprintf(buf, size, "%"PRIu64, pf->id);
12468 		++i;
12469 	}
12470 	if (buf)
12471 		return -1;
12472 	return i;
12473 }
12474 
12475 /** Complete operation for compare match item. */
12476 static int
12477 comp_set_compare_op(struct context *ctx, const struct token *token,
12478 		    unsigned int ent, char *buf, unsigned int size)
12479 {
12480 	RTE_SET_USED(ctx);
12481 	RTE_SET_USED(token);
12482 	if (!buf)
12483 		return RTE_DIM(compare_ops);
12484 	if (ent < RTE_DIM(compare_ops) - 1)
12485 		return strlcpy(buf, compare_ops[ent], size);
12486 	return -1;
12487 }
12488 
12489 /** Complete field id for compare match item. */
12490 static int
12491 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12492 			  unsigned int ent, char *buf, unsigned int size)
12493 {
12494 	const char *name;
12495 
12496 	RTE_SET_USED(token);
12497 	if (!buf)
12498 		return RTE_DIM(flow_field_ids);
12499 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12500 		return -1;
12501 	name = flow_field_ids[ent];
12502 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12503 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12504 		return strlcpy(buf, name, size);
12505 	return -1;
12506 }
12507 
12508 /** Complete type field for RSS action. */
12509 static int
12510 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12511 			unsigned int ent, char *buf, unsigned int size)
12512 {
12513 	unsigned int i;
12514 
12515 	(void)ctx;
12516 	(void)token;
12517 	for (i = 0; rss_type_table[i].str; ++i)
12518 		;
12519 	if (!buf)
12520 		return i + 1;
12521 	if (ent < i)
12522 		return strlcpy(buf, rss_type_table[ent].str, size);
12523 	if (ent == i)
12524 		return snprintf(buf, size, "end");
12525 	return -1;
12526 }
12527 
12528 /** Complete queue field for RSS action. */
12529 static int
12530 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12531 			 unsigned int ent, char *buf, unsigned int size)
12532 {
12533 	(void)ctx;
12534 	(void)token;
12535 	if (!buf)
12536 		return nb_rxq + 1;
12537 	if (ent < nb_rxq)
12538 		return snprintf(buf, size, "%u", ent);
12539 	if (ent == nb_rxq)
12540 		return snprintf(buf, size, "end");
12541 	return -1;
12542 }
12543 
12544 /** Complete index number for set raw_encap/raw_decap commands. */
12545 static int
12546 comp_set_raw_index(struct context *ctx, const struct token *token,
12547 		   unsigned int ent, char *buf, unsigned int size)
12548 {
12549 	uint16_t idx = 0;
12550 	uint16_t nb = 0;
12551 
12552 	RTE_SET_USED(ctx);
12553 	RTE_SET_USED(token);
12554 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12555 		if (buf && idx == ent)
12556 			return snprintf(buf, size, "%u", idx);
12557 		++nb;
12558 	}
12559 	return nb;
12560 }
12561 
12562 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12563 static int
12564 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12565 			unsigned int ent, char *buf, unsigned int size)
12566 {
12567 	uint16_t idx = 0;
12568 	uint16_t nb = 0;
12569 
12570 	RTE_SET_USED(ctx);
12571 	RTE_SET_USED(token);
12572 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12573 		if (buf && idx == ent)
12574 			return snprintf(buf, size, "%u", idx);
12575 		++nb;
12576 	}
12577 	return nb;
12578 }
12579 
12580 /** Complete index number for set raw_encap/raw_decap commands. */
12581 static int
12582 comp_set_sample_index(struct context *ctx, const struct token *token,
12583 		   unsigned int ent, char *buf, unsigned int size)
12584 {
12585 	uint16_t idx = 0;
12586 	uint16_t nb = 0;
12587 
12588 	RTE_SET_USED(ctx);
12589 	RTE_SET_USED(token);
12590 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12591 		if (buf && idx == ent)
12592 			return snprintf(buf, size, "%u", idx);
12593 		++nb;
12594 	}
12595 	return nb;
12596 }
12597 
12598 /** Complete operation for modify_field command. */
12599 static int
12600 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12601 		   unsigned int ent, char *buf, unsigned int size)
12602 {
12603 	RTE_SET_USED(ctx);
12604 	RTE_SET_USED(token);
12605 	if (!buf)
12606 		return RTE_DIM(modify_field_ops);
12607 	if (ent < RTE_DIM(modify_field_ops) - 1)
12608 		return strlcpy(buf, modify_field_ops[ent], size);
12609 	return -1;
12610 }
12611 
12612 /** Complete field id for modify_field command. */
12613 static int
12614 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12615 		   unsigned int ent, char *buf, unsigned int size)
12616 {
12617 	const char *name;
12618 
12619 	RTE_SET_USED(token);
12620 	if (!buf)
12621 		return RTE_DIM(flow_field_ids);
12622 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12623 		return -1;
12624 	name = flow_field_ids[ent];
12625 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12626 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12627 		return strlcpy(buf, name, size);
12628 	return -1;
12629 }
12630 
12631 /** Complete available pattern template IDs. */
12632 static int
12633 comp_pattern_template_id(struct context *ctx, const struct token *token,
12634 			 unsigned int ent, char *buf, unsigned int size)
12635 {
12636 	unsigned int i = 0;
12637 	struct rte_port *port;
12638 	struct port_template *pt;
12639 
12640 	(void)token;
12641 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12642 	    ctx->port == (portid_t)RTE_PORT_ALL)
12643 		return -1;
12644 	port = &ports[ctx->port];
12645 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12646 		if (buf && i == ent)
12647 			return snprintf(buf, size, "%u", pt->id);
12648 		++i;
12649 	}
12650 	if (buf)
12651 		return -1;
12652 	return i;
12653 }
12654 
12655 /** Complete available actions template IDs. */
12656 static int
12657 comp_actions_template_id(struct context *ctx, const struct token *token,
12658 			 unsigned int ent, char *buf, unsigned int size)
12659 {
12660 	unsigned int i = 0;
12661 	struct rte_port *port;
12662 	struct port_template *pt;
12663 
12664 	(void)token;
12665 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12666 	    ctx->port == (portid_t)RTE_PORT_ALL)
12667 		return -1;
12668 	port = &ports[ctx->port];
12669 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12670 		if (buf && i == ent)
12671 			return snprintf(buf, size, "%u", pt->id);
12672 		++i;
12673 	}
12674 	if (buf)
12675 		return -1;
12676 	return i;
12677 }
12678 
12679 /** Complete available table IDs. */
12680 static int
12681 comp_table_id(struct context *ctx, const struct token *token,
12682 	      unsigned int ent, char *buf, unsigned int size)
12683 {
12684 	unsigned int i = 0;
12685 	struct rte_port *port;
12686 	struct port_table *pt;
12687 
12688 	(void)token;
12689 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12690 	    ctx->port == (portid_t)RTE_PORT_ALL)
12691 		return -1;
12692 	port = &ports[ctx->port];
12693 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12694 		if (buf && i == ent)
12695 			return snprintf(buf, size, "%u", pt->id);
12696 		++i;
12697 	}
12698 	if (buf)
12699 		return -1;
12700 	return i;
12701 }
12702 
12703 /** Complete available queue IDs. */
12704 static int
12705 comp_queue_id(struct context *ctx, const struct token *token,
12706 	      unsigned int ent, char *buf, unsigned int size)
12707 {
12708 	unsigned int i = 0;
12709 	struct rte_port *port;
12710 
12711 	(void)token;
12712 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12713 	    ctx->port == (portid_t)RTE_PORT_ALL)
12714 		return -1;
12715 	port = &ports[ctx->port];
12716 	for (i = 0; i < port->queue_nb; i++) {
12717 		if (buf && i == ent)
12718 			return snprintf(buf, size, "%u", i);
12719 	}
12720 	if (buf)
12721 		return -1;
12722 	return i;
12723 }
12724 
12725 static int
12726 comp_names_to_index(struct context *ctx, const struct token *token,
12727 		    unsigned int ent, char *buf, unsigned int size,
12728 		    const char *const names[], size_t names_size)
12729 {
12730 	RTE_SET_USED(ctx);
12731 	RTE_SET_USED(token);
12732 	if (!buf)
12733 		return names_size;
12734 	if (names[ent] && ent < names_size)
12735 		return rte_strscpy(buf, names[ent], size);
12736 	return -1;
12737 
12738 }
12739 
12740 /** Complete available Meter colors. */
12741 static int
12742 comp_meter_color(struct context *ctx, const struct token *token,
12743 		 unsigned int ent, char *buf, unsigned int size)
12744 {
12745 	RTE_SET_USED(ctx);
12746 	RTE_SET_USED(token);
12747 	if (!buf)
12748 		return RTE_DIM(meter_colors);
12749 	if (ent < RTE_DIM(meter_colors) - 1)
12750 		return strlcpy(buf, meter_colors[ent], size);
12751 	return -1;
12752 }
12753 
12754 /** Complete available Insertion Table types. */
12755 static int
12756 comp_insertion_table_type(struct context *ctx, const struct token *token,
12757 			  unsigned int ent, char *buf, unsigned int size)
12758 {
12759 	RTE_SET_USED(ctx);
12760 	RTE_SET_USED(token);
12761 	if (!buf)
12762 		return RTE_DIM(table_insertion_types);
12763 	if (ent < RTE_DIM(table_insertion_types) - 1)
12764 		return rte_strscpy(buf, table_insertion_types[ent], size);
12765 	return -1;
12766 }
12767 
12768 /** Complete available Hash Calculation Table types. */
12769 static int
12770 comp_hash_table_type(struct context *ctx, const struct token *token,
12771 		     unsigned int ent, char *buf, unsigned int size)
12772 {
12773 	RTE_SET_USED(ctx);
12774 	RTE_SET_USED(token);
12775 	if (!buf)
12776 		return RTE_DIM(table_hash_funcs);
12777 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12778 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12779 	return -1;
12780 }
12781 
12782 static int
12783 comp_quota_state_name(struct context *ctx, const struct token *token,
12784 		      unsigned int ent, char *buf, unsigned int size)
12785 {
12786 	return comp_names_to_index(ctx, token, ent, buf, size,
12787 				   quota_state_names,
12788 				   RTE_DIM(quota_state_names));
12789 }
12790 
12791 static int
12792 comp_quota_mode_name(struct context *ctx, const struct token *token,
12793 		     unsigned int ent, char *buf, unsigned int size)
12794 {
12795 	return comp_names_to_index(ctx, token, ent, buf, size,
12796 				   quota_mode_names,
12797 				   RTE_DIM(quota_mode_names));
12798 }
12799 
12800 static int
12801 comp_quota_update_name(struct context *ctx, const struct token *token,
12802 		       unsigned int ent, char *buf, unsigned int size)
12803 {
12804 	return comp_names_to_index(ctx, token, ent, buf, size,
12805 				   quota_update_names,
12806 				   RTE_DIM(quota_update_names));
12807 }
12808 
12809 static int
12810 comp_qu_mode_name(struct context *ctx, const struct token *token,
12811 		  unsigned int ent, char *buf, unsigned int size)
12812 {
12813 	return comp_names_to_index(ctx, token, ent, buf, size,
12814 				   query_update_mode_names,
12815 				   RTE_DIM(query_update_mode_names));
12816 }
12817 
12818 /** Internal context. */
12819 static struct context cmd_flow_context;
12820 
12821 /** Global parser instance (cmdline API). */
12822 cmdline_parse_inst_t cmd_flow;
12823 cmdline_parse_inst_t cmd_set_raw;
12824 
12825 /** Initialize context. */
12826 static void
12827 cmd_flow_context_init(struct context *ctx)
12828 {
12829 	/* A full memset() is not necessary. */
12830 	ctx->curr = ZERO;
12831 	ctx->prev = ZERO;
12832 	ctx->next_num = 0;
12833 	ctx->args_num = 0;
12834 	ctx->eol = 0;
12835 	ctx->last = 0;
12836 	ctx->port = 0;
12837 	ctx->objdata = 0;
12838 	ctx->object = NULL;
12839 	ctx->objmask = NULL;
12840 }
12841 
12842 /** Parse a token (cmdline API). */
12843 static int
12844 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12845 	       unsigned int size)
12846 {
12847 	struct context *ctx = &cmd_flow_context;
12848 	const struct token *token;
12849 	const enum index *list;
12850 	int len;
12851 	int i;
12852 
12853 	(void)hdr;
12854 	token = &token_list[ctx->curr];
12855 	/* Check argument length. */
12856 	ctx->eol = 0;
12857 	ctx->last = 1;
12858 	for (len = 0; src[len]; ++len)
12859 		if (src[len] == '#' || isspace(src[len]))
12860 			break;
12861 	if (!len)
12862 		return -1;
12863 	/* Last argument and EOL detection. */
12864 	for (i = len; src[i]; ++i)
12865 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12866 			break;
12867 		else if (!isspace(src[i])) {
12868 			ctx->last = 0;
12869 			break;
12870 		}
12871 	for (; src[i]; ++i)
12872 		if (src[i] == '\r' || src[i] == '\n') {
12873 			ctx->eol = 1;
12874 			break;
12875 		}
12876 	/* Initialize context if necessary. */
12877 	if (!ctx->next_num) {
12878 		if (!token->next)
12879 			return 0;
12880 		ctx->next[ctx->next_num++] = token->next[0];
12881 	}
12882 	/* Process argument through candidates. */
12883 	ctx->prev = ctx->curr;
12884 	list = ctx->next[ctx->next_num - 1];
12885 	for (i = 0; list[i]; ++i) {
12886 		const struct token *next = &token_list[list[i]];
12887 		int tmp;
12888 
12889 		ctx->curr = list[i];
12890 		if (next->call)
12891 			tmp = next->call(ctx, next, src, len, result, size);
12892 		else
12893 			tmp = parse_default(ctx, next, src, len, result, size);
12894 		if (tmp == -1 || tmp != len)
12895 			continue;
12896 		token = next;
12897 		break;
12898 	}
12899 	if (!list[i])
12900 		return -1;
12901 	--ctx->next_num;
12902 	/* Push subsequent tokens if any. */
12903 	if (token->next)
12904 		for (i = 0; token->next[i]; ++i) {
12905 			if (ctx->next_num == RTE_DIM(ctx->next))
12906 				return -1;
12907 			ctx->next[ctx->next_num++] = token->next[i];
12908 		}
12909 	/* Push arguments if any. */
12910 	if (token->args)
12911 		for (i = 0; token->args[i]; ++i) {
12912 			if (ctx->args_num == RTE_DIM(ctx->args))
12913 				return -1;
12914 			ctx->args[ctx->args_num++] = token->args[i];
12915 		}
12916 	return len;
12917 }
12918 
12919 int
12920 flow_parse(const char *src, void *result, unsigned int size,
12921 	   struct rte_flow_attr **attr,
12922 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12923 {
12924 	int ret;
12925 	struct context saved_flow_ctx = cmd_flow_context;
12926 
12927 	cmd_flow_context_init(&cmd_flow_context);
12928 	do {
12929 		ret = cmd_flow_parse(NULL, src, result, size);
12930 		if (ret > 0) {
12931 			src += ret;
12932 			while (isspace(*src))
12933 				src++;
12934 		}
12935 	} while (ret > 0 && strlen(src));
12936 	cmd_flow_context = saved_flow_ctx;
12937 	*attr = &((struct buffer *)result)->args.vc.attr;
12938 	*pattern = ((struct buffer *)result)->args.vc.pattern;
12939 	*actions = ((struct buffer *)result)->args.vc.actions;
12940 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
12941 }
12942 
12943 /** Return number of completion entries (cmdline API). */
12944 static int
12945 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
12946 {
12947 	struct context *ctx = &cmd_flow_context;
12948 	const struct token *token = &token_list[ctx->curr];
12949 	const enum index *list;
12950 	int i;
12951 
12952 	(void)hdr;
12953 	/* Count number of tokens in current list. */
12954 	if (ctx->next_num)
12955 		list = ctx->next[ctx->next_num - 1];
12956 	else
12957 		list = token->next[0];
12958 	for (i = 0; list[i]; ++i)
12959 		;
12960 	if (!i)
12961 		return 0;
12962 	/*
12963 	 * If there is a single token, use its completion callback, otherwise
12964 	 * return the number of entries.
12965 	 */
12966 	token = &token_list[list[0]];
12967 	if (i == 1 && token->comp) {
12968 		/* Save index for cmd_flow_get_help(). */
12969 		ctx->prev = list[0];
12970 		return token->comp(ctx, token, 0, NULL, 0);
12971 	}
12972 	return i;
12973 }
12974 
12975 /** Return a completion entry (cmdline API). */
12976 static int
12977 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
12978 			  char *dst, unsigned int size)
12979 {
12980 	struct context *ctx = &cmd_flow_context;
12981 	const struct token *token = &token_list[ctx->curr];
12982 	const enum index *list;
12983 	int i;
12984 
12985 	(void)hdr;
12986 	/* Count number of tokens in current list. */
12987 	if (ctx->next_num)
12988 		list = ctx->next[ctx->next_num - 1];
12989 	else
12990 		list = token->next[0];
12991 	for (i = 0; list[i]; ++i)
12992 		;
12993 	if (!i)
12994 		return -1;
12995 	/* If there is a single token, use its completion callback. */
12996 	token = &token_list[list[0]];
12997 	if (i == 1 && token->comp) {
12998 		/* Save index for cmd_flow_get_help(). */
12999 		ctx->prev = list[0];
13000 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
13001 	}
13002 	/* Otherwise make sure the index is valid and use defaults. */
13003 	if (index >= i)
13004 		return -1;
13005 	token = &token_list[list[index]];
13006 	strlcpy(dst, token->name, size);
13007 	/* Save index for cmd_flow_get_help(). */
13008 	ctx->prev = list[index];
13009 	return 0;
13010 }
13011 
13012 /** Populate help strings for current token (cmdline API). */
13013 static int
13014 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13015 {
13016 	struct context *ctx = &cmd_flow_context;
13017 	const struct token *token = &token_list[ctx->prev];
13018 
13019 	(void)hdr;
13020 	if (!size)
13021 		return -1;
13022 	/* Set token type and update global help with details. */
13023 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13024 	if (token->help)
13025 		cmd_flow.help_str = token->help;
13026 	else
13027 		cmd_flow.help_str = token->name;
13028 	return 0;
13029 }
13030 
13031 /** Token definition template (cmdline API). */
13032 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13033 	.ops = &(struct cmdline_token_ops){
13034 		.parse = cmd_flow_parse,
13035 		.complete_get_nb = cmd_flow_complete_get_nb,
13036 		.complete_get_elt = cmd_flow_complete_get_elt,
13037 		.get_help = cmd_flow_get_help,
13038 	},
13039 	.offset = 0,
13040 };
13041 
13042 /** Populate the next dynamic token. */
13043 static void
13044 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13045 	     cmdline_parse_token_hdr_t **hdr_inst)
13046 {
13047 	struct context *ctx = &cmd_flow_context;
13048 
13049 	/* Always reinitialize context before requesting the first token. */
13050 	if (!(hdr_inst - cmd_flow.tokens))
13051 		cmd_flow_context_init(ctx);
13052 	/* Return NULL when no more tokens are expected. */
13053 	if (!ctx->next_num && ctx->curr) {
13054 		*hdr = NULL;
13055 		return;
13056 	}
13057 	/* Determine if command should end here. */
13058 	if (ctx->eol && ctx->last && ctx->next_num) {
13059 		const enum index *list = ctx->next[ctx->next_num - 1];
13060 		int i;
13061 
13062 		for (i = 0; list[i]; ++i) {
13063 			if (list[i] != END)
13064 				continue;
13065 			*hdr = NULL;
13066 			return;
13067 		}
13068 	}
13069 	*hdr = &cmd_flow_token_hdr;
13070 }
13071 
13072 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13073 	SLIST_HEAD_INITIALIZER();
13074 
13075 static void
13076 indirect_action_flow_conf_create(const struct buffer *in)
13077 {
13078 	int len, ret;
13079 	uint32_t i;
13080 	struct indlst_conf *indlst_conf = NULL;
13081 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13082 	struct rte_flow_action *src = in->args.vc.actions;
13083 
13084 	if (!in->args.vc.actions_n)
13085 		goto end;
13086 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13087 	if (len <= 0)
13088 		goto end;
13089 	len = RTE_ALIGN(len, 16);
13090 
13091 	indlst_conf = calloc(1, base + len +
13092 			     in->args.vc.actions_n * sizeof(uintptr_t));
13093 	if (!indlst_conf)
13094 		goto end;
13095 	indlst_conf->id = in->args.vc.attr.group;
13096 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13097 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13098 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13099 			    len, src, NULL);
13100 	if (ret <= 0) {
13101 		free(indlst_conf);
13102 		indlst_conf = NULL;
13103 		goto end;
13104 	}
13105 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13106 	for (i = 0; i < indlst_conf->conf_num; i++)
13107 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13108 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13109 end:
13110 	if (indlst_conf)
13111 		printf("created indirect action list configuration %u\n",
13112 		       in->args.vc.attr.group);
13113 	else
13114 		printf("cannot create indirect action list configuration %u\n",
13115 		       in->args.vc.attr.group);
13116 }
13117 
13118 static const struct indlst_conf *
13119 indirect_action_list_conf_get(uint32_t conf_id)
13120 {
13121 	const struct indlst_conf *conf;
13122 
13123 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13124 		if (conf->id == conf_id)
13125 			return conf;
13126 	}
13127 	return NULL;
13128 }
13129 
13130 /** Dispatch parsed buffer to function calls. */
13131 static void
13132 cmd_flow_parsed(const struct buffer *in)
13133 {
13134 	switch (in->command) {
13135 	case INFO:
13136 		port_flow_get_info(in->port);
13137 		break;
13138 	case CONFIGURE:
13139 		port_flow_configure(in->port,
13140 				    &in->args.configure.port_attr,
13141 				    in->args.configure.nb_queue,
13142 				    &in->args.configure.queue_attr);
13143 		break;
13144 	case PATTERN_TEMPLATE_CREATE:
13145 		port_flow_pattern_template_create(in->port,
13146 				in->args.vc.pat_templ_id,
13147 				&((const struct rte_flow_pattern_template_attr) {
13148 					.relaxed_matching = in->args.vc.attr.reserved,
13149 					.ingress = in->args.vc.attr.ingress,
13150 					.egress = in->args.vc.attr.egress,
13151 					.transfer = in->args.vc.attr.transfer,
13152 				}),
13153 				in->args.vc.pattern);
13154 		break;
13155 	case PATTERN_TEMPLATE_DESTROY:
13156 		port_flow_pattern_template_destroy(in->port,
13157 				in->args.templ_destroy.template_id_n,
13158 				in->args.templ_destroy.template_id);
13159 		break;
13160 	case ACTIONS_TEMPLATE_CREATE:
13161 		port_flow_actions_template_create(in->port,
13162 				in->args.vc.act_templ_id,
13163 				&((const struct rte_flow_actions_template_attr) {
13164 					.ingress = in->args.vc.attr.ingress,
13165 					.egress = in->args.vc.attr.egress,
13166 					.transfer = in->args.vc.attr.transfer,
13167 				}),
13168 				in->args.vc.actions,
13169 				in->args.vc.masks);
13170 		break;
13171 	case ACTIONS_TEMPLATE_DESTROY:
13172 		port_flow_actions_template_destroy(in->port,
13173 				in->args.templ_destroy.template_id_n,
13174 				in->args.templ_destroy.template_id);
13175 		break;
13176 	case TABLE_CREATE:
13177 		port_flow_template_table_create(in->port, in->args.table.id,
13178 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13179 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13180 			in->args.table.act_templ_id);
13181 		break;
13182 	case TABLE_DESTROY:
13183 		port_flow_template_table_destroy(in->port,
13184 					in->args.table_destroy.table_id_n,
13185 					in->args.table_destroy.table_id);
13186 		break;
13187 	case TABLE_RESIZE_COMPLETE:
13188 		port_flow_template_table_resize_complete
13189 			(in->port, in->args.table_destroy.table_id[0]);
13190 		break;
13191 	case GROUP_SET_MISS_ACTIONS:
13192 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13193 						  in->args.vc.actions);
13194 		break;
13195 	case TABLE_RESIZE:
13196 		port_flow_template_table_resize(in->port, in->args.table.id,
13197 						in->args.table.attr.nb_flows);
13198 		break;
13199 	case QUEUE_CREATE:
13200 		port_queue_flow_create(in->port, in->queue, in->postpone,
13201 			in->args.vc.table_id, in->args.vc.rule_id,
13202 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13203 			in->args.vc.pattern, in->args.vc.actions);
13204 		break;
13205 	case QUEUE_DESTROY:
13206 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13207 					in->args.destroy.rule_n,
13208 					in->args.destroy.rule);
13209 		break;
13210 	case QUEUE_FLOW_UPDATE_RESIZED:
13211 		port_queue_flow_update_resized(in->port, in->queue,
13212 					       in->postpone,
13213 					       in->args.destroy.rule[0]);
13214 		break;
13215 	case QUEUE_UPDATE:
13216 		port_queue_flow_update(in->port, in->queue, in->postpone,
13217 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13218 				in->args.vc.actions);
13219 		break;
13220 	case PUSH:
13221 		port_queue_flow_push(in->port, in->queue);
13222 		break;
13223 	case PULL:
13224 		port_queue_flow_pull(in->port, in->queue);
13225 		break;
13226 	case HASH:
13227 		if (!in->args.vc.encap_hash)
13228 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13229 					    in->args.vc.pat_templ_id,
13230 					    in->args.vc.pattern);
13231 		else
13232 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13233 						  in->args.vc.pattern);
13234 		break;
13235 	case QUEUE_AGED:
13236 		port_queue_flow_aged(in->port, in->queue,
13237 				     in->args.aged.destroy);
13238 		break;
13239 	case QUEUE_INDIRECT_ACTION_CREATE:
13240 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13241 		port_queue_action_handle_create(
13242 				in->port, in->queue, in->postpone,
13243 				in->args.vc.attr.group,
13244 				in->command == QUEUE_INDIRECT_ACTION_LIST_CREATE,
13245 				&((const struct rte_flow_indir_action_conf) {
13246 					.ingress = in->args.vc.attr.ingress,
13247 					.egress = in->args.vc.attr.egress,
13248 					.transfer = in->args.vc.attr.transfer,
13249 				}),
13250 				in->args.vc.actions);
13251 		break;
13252 	case QUEUE_INDIRECT_ACTION_DESTROY:
13253 		port_queue_action_handle_destroy(in->port,
13254 					   in->queue, in->postpone,
13255 					   in->args.ia_destroy.action_id_n,
13256 					   in->args.ia_destroy.action_id);
13257 		break;
13258 	case QUEUE_INDIRECT_ACTION_UPDATE:
13259 		port_queue_action_handle_update(in->port,
13260 						in->queue, in->postpone,
13261 						in->args.vc.attr.group,
13262 						in->args.vc.actions);
13263 		break;
13264 	case QUEUE_INDIRECT_ACTION_QUERY:
13265 		port_queue_action_handle_query(in->port,
13266 					       in->queue, in->postpone,
13267 					       in->args.ia.action_id);
13268 		break;
13269 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13270 		port_queue_action_handle_query_update(in->port, in->queue,
13271 						      in->postpone,
13272 						      in->args.ia.action_id,
13273 						      in->args.ia.qu_mode,
13274 						      in->args.vc.actions);
13275 		break;
13276 	case INDIRECT_ACTION_CREATE:
13277 	case INDIRECT_ACTION_LIST_CREATE:
13278 		port_action_handle_create(
13279 				in->port, in->args.vc.attr.group,
13280 				in->command == INDIRECT_ACTION_LIST_CREATE,
13281 				&((const struct rte_flow_indir_action_conf) {
13282 					.ingress = in->args.vc.attr.ingress,
13283 					.egress = in->args.vc.attr.egress,
13284 					.transfer = in->args.vc.attr.transfer,
13285 				}),
13286 				in->args.vc.actions);
13287 		break;
13288 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13289 		indirect_action_flow_conf_create(in);
13290 		break;
13291 	case INDIRECT_ACTION_DESTROY:
13292 		port_action_handle_destroy(in->port,
13293 					   in->args.ia_destroy.action_id_n,
13294 					   in->args.ia_destroy.action_id);
13295 		break;
13296 	case INDIRECT_ACTION_UPDATE:
13297 		port_action_handle_update(in->port, in->args.vc.attr.group,
13298 					  in->args.vc.actions);
13299 		break;
13300 	case INDIRECT_ACTION_QUERY:
13301 		port_action_handle_query(in->port, in->args.ia.action_id);
13302 		break;
13303 	case INDIRECT_ACTION_QUERY_UPDATE:
13304 		port_action_handle_query_update(in->port,
13305 						in->args.ia.action_id,
13306 						in->args.ia.qu_mode,
13307 						in->args.vc.actions);
13308 		break;
13309 	case VALIDATE:
13310 		port_flow_validate(in->port, &in->args.vc.attr,
13311 				   in->args.vc.pattern, in->args.vc.actions,
13312 				   &in->args.vc.tunnel_ops);
13313 		break;
13314 	case CREATE:
13315 		port_flow_create(in->port, &in->args.vc.attr,
13316 				 in->args.vc.pattern, in->args.vc.actions,
13317 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13318 		break;
13319 	case DESTROY:
13320 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13321 				  in->args.destroy.rule,
13322 				  in->args.destroy.is_user_id);
13323 		break;
13324 	case UPDATE:
13325 		port_flow_update(in->port, in->args.vc.rule_id,
13326 				 in->args.vc.actions, in->args.vc.user_id);
13327 		break;
13328 	case FLUSH:
13329 		port_flow_flush(in->port);
13330 		break;
13331 	case DUMP_ONE:
13332 	case DUMP_ALL:
13333 		port_flow_dump(in->port, in->args.dump.mode,
13334 				in->args.dump.rule, in->args.dump.file,
13335 				in->args.dump.is_user_id);
13336 		break;
13337 	case QUERY:
13338 		port_flow_query(in->port, in->args.query.rule,
13339 				&in->args.query.action,
13340 				in->args.query.is_user_id);
13341 		break;
13342 	case LIST:
13343 		port_flow_list(in->port, in->args.list.group_n,
13344 			       in->args.list.group);
13345 		break;
13346 	case ISOLATE:
13347 		port_flow_isolate(in->port, in->args.isolate.set);
13348 		break;
13349 	case AGED:
13350 		port_flow_aged(in->port, in->args.aged.destroy);
13351 		break;
13352 	case TUNNEL_CREATE:
13353 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13354 		break;
13355 	case TUNNEL_DESTROY:
13356 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13357 		break;
13358 	case TUNNEL_LIST:
13359 		port_flow_tunnel_list(in->port);
13360 		break;
13361 	case ACTION_POL_G:
13362 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13363 					in->args.vc.actions);
13364 		break;
13365 	case FLEX_ITEM_CREATE:
13366 		flex_item_create(in->port, in->args.flex.token,
13367 				 in->args.flex.filename);
13368 		break;
13369 	case FLEX_ITEM_DESTROY:
13370 		flex_item_destroy(in->port, in->args.flex.token);
13371 		break;
13372 	default:
13373 		break;
13374 	}
13375 	fflush(stdout);
13376 }
13377 
13378 /** Token generator and output processing callback (cmdline API). */
13379 static void
13380 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13381 {
13382 	if (cl == NULL)
13383 		cmd_flow_tok(arg0, arg2);
13384 	else
13385 		cmd_flow_parsed(arg0);
13386 }
13387 
13388 /** Global parser instance (cmdline API). */
13389 cmdline_parse_inst_t cmd_flow = {
13390 	.f = cmd_flow_cb,
13391 	.data = NULL, /**< Unused. */
13392 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13393 	.tokens = {
13394 		NULL,
13395 	}, /**< Tokens are returned by cmd_flow_tok(). */
13396 };
13397 
13398 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13399 
13400 static void
13401 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13402 {
13403 	struct rte_ipv4_hdr *ipv4;
13404 	struct rte_ether_hdr *eth;
13405 	struct rte_ipv6_hdr *ipv6;
13406 	struct rte_vxlan_hdr *vxlan;
13407 	struct rte_vxlan_gpe_hdr *gpe;
13408 	struct rte_flow_item_nvgre *nvgre;
13409 	uint32_t ipv6_vtc_flow;
13410 
13411 	switch (item->type) {
13412 	case RTE_FLOW_ITEM_TYPE_ETH:
13413 		eth = (struct rte_ether_hdr *)buf;
13414 		if (next_proto)
13415 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13416 		break;
13417 	case RTE_FLOW_ITEM_TYPE_IPV4:
13418 		ipv4 = (struct rte_ipv4_hdr *)buf;
13419 		if (!ipv4->version_ihl)
13420 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13421 		if (next_proto && ipv4->next_proto_id == 0)
13422 			ipv4->next_proto_id = (uint8_t)next_proto;
13423 		break;
13424 	case RTE_FLOW_ITEM_TYPE_IPV6:
13425 		ipv6 = (struct rte_ipv6_hdr *)buf;
13426 		if (next_proto && ipv6->proto == 0)
13427 			ipv6->proto = (uint8_t)next_proto;
13428 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13429 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13430 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13431 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13432 		break;
13433 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13434 		vxlan = (struct rte_vxlan_hdr *)buf;
13435 		vxlan->vx_flags = 0x08;
13436 		break;
13437 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13438 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13439 		gpe->vx_flags = 0x0C;
13440 		break;
13441 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13442 		nvgre = (struct rte_flow_item_nvgre *)buf;
13443 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13444 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13445 		break;
13446 	default:
13447 		break;
13448 	}
13449 }
13450 
13451 /** Helper of get item's default mask. */
13452 static const void *
13453 flow_item_default_mask(const struct rte_flow_item *item)
13454 {
13455 	const void *mask = NULL;
13456 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13457 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13458 		.hdr = {
13459 			.next_hdr = 0xff,
13460 			.type = 0xff,
13461 			.segments_left = 0xff,
13462 		},
13463 	};
13464 
13465 	switch (item->type) {
13466 	case RTE_FLOW_ITEM_TYPE_ANY:
13467 		mask = &rte_flow_item_any_mask;
13468 		break;
13469 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13470 		mask = &rte_flow_item_port_id_mask;
13471 		break;
13472 	case RTE_FLOW_ITEM_TYPE_RAW:
13473 		mask = &rte_flow_item_raw_mask;
13474 		break;
13475 	case RTE_FLOW_ITEM_TYPE_ETH:
13476 		mask = &rte_flow_item_eth_mask;
13477 		break;
13478 	case RTE_FLOW_ITEM_TYPE_VLAN:
13479 		mask = &rte_flow_item_vlan_mask;
13480 		break;
13481 	case RTE_FLOW_ITEM_TYPE_IPV4:
13482 		mask = &rte_flow_item_ipv4_mask;
13483 		break;
13484 	case RTE_FLOW_ITEM_TYPE_IPV6:
13485 		mask = &rte_flow_item_ipv6_mask;
13486 		break;
13487 	case RTE_FLOW_ITEM_TYPE_ICMP:
13488 		mask = &rte_flow_item_icmp_mask;
13489 		break;
13490 	case RTE_FLOW_ITEM_TYPE_UDP:
13491 		mask = &rte_flow_item_udp_mask;
13492 		break;
13493 	case RTE_FLOW_ITEM_TYPE_TCP:
13494 		mask = &rte_flow_item_tcp_mask;
13495 		break;
13496 	case RTE_FLOW_ITEM_TYPE_SCTP:
13497 		mask = &rte_flow_item_sctp_mask;
13498 		break;
13499 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13500 		mask = &rte_flow_item_vxlan_mask;
13501 		break;
13502 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13503 		mask = &rte_flow_item_vxlan_gpe_mask;
13504 		break;
13505 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13506 		mask = &rte_flow_item_e_tag_mask;
13507 		break;
13508 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13509 		mask = &rte_flow_item_nvgre_mask;
13510 		break;
13511 	case RTE_FLOW_ITEM_TYPE_MPLS:
13512 		mask = &rte_flow_item_mpls_mask;
13513 		break;
13514 	case RTE_FLOW_ITEM_TYPE_GRE:
13515 		mask = &rte_flow_item_gre_mask;
13516 		break;
13517 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13518 		mask = &gre_key_default_mask;
13519 		break;
13520 	case RTE_FLOW_ITEM_TYPE_META:
13521 		mask = &rte_flow_item_meta_mask;
13522 		break;
13523 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13524 		mask = &rte_flow_item_random_mask;
13525 		break;
13526 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13527 		mask = &rte_flow_item_fuzzy_mask;
13528 		break;
13529 	case RTE_FLOW_ITEM_TYPE_GTP:
13530 		mask = &rte_flow_item_gtp_mask;
13531 		break;
13532 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13533 		mask = &rte_flow_item_gtp_psc_mask;
13534 		break;
13535 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13536 		mask = &rte_flow_item_geneve_mask;
13537 		break;
13538 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13539 		mask = &rte_flow_item_geneve_opt_mask;
13540 		break;
13541 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13542 		mask = &rte_flow_item_pppoe_proto_id_mask;
13543 		break;
13544 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13545 		mask = &rte_flow_item_l2tpv3oip_mask;
13546 		break;
13547 	case RTE_FLOW_ITEM_TYPE_ESP:
13548 		mask = &rte_flow_item_esp_mask;
13549 		break;
13550 	case RTE_FLOW_ITEM_TYPE_AH:
13551 		mask = &rte_flow_item_ah_mask;
13552 		break;
13553 	case RTE_FLOW_ITEM_TYPE_PFCP:
13554 		mask = &rte_flow_item_pfcp_mask;
13555 		break;
13556 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13557 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13558 		mask = &rte_flow_item_ethdev_mask;
13559 		break;
13560 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13561 		mask = &rte_flow_item_l2tpv2_mask;
13562 		break;
13563 	case RTE_FLOW_ITEM_TYPE_PPP:
13564 		mask = &rte_flow_item_ppp_mask;
13565 		break;
13566 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13567 		mask = &rte_flow_item_meter_color_mask;
13568 		break;
13569 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13570 		mask = &ipv6_routing_ext_default_mask;
13571 		break;
13572 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13573 		mask = &rte_flow_item_aggr_affinity_mask;
13574 		break;
13575 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13576 		mask = &rte_flow_item_tx_queue_mask;
13577 		break;
13578 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13579 		mask = &rte_flow_item_ib_bth_mask;
13580 		break;
13581 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13582 		mask = &rte_flow_item_ptype_mask;
13583 		break;
13584 	default:
13585 		break;
13586 	}
13587 	return mask;
13588 }
13589 
13590 /** Dispatch parsed buffer to function calls. */
13591 static void
13592 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13593 {
13594 	uint32_t n = in->args.vc.pattern_n;
13595 	int i = 0;
13596 	struct rte_flow_item *item = NULL;
13597 	size_t size = 0;
13598 	uint8_t *data = NULL;
13599 	uint8_t *type = NULL;
13600 	size_t *total_size = NULL;
13601 	uint16_t idx = in->port; /* We borrow port field as index */
13602 	struct rte_flow_item_ipv6_routing_ext *ext;
13603 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13604 
13605 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13606 		   in->command == SET_IPV6_EXT_REMOVE);
13607 
13608 	if (in->command == SET_IPV6_EXT_REMOVE) {
13609 		if (n != 1 || in->args.vc.pattern->type !=
13610 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13611 			fprintf(stderr, "Error - Not supported item\n");
13612 			return;
13613 		}
13614 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13615 		item = in->args.vc.pattern;
13616 		ipv6_ext = item->spec;
13617 		*type = ipv6_ext->next_hdr;
13618 		return;
13619 	}
13620 
13621 	total_size = &ipv6_ext_push_confs[idx].size;
13622 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13623 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13624 
13625 	*total_size = 0;
13626 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13627 	for (i = n - 1 ; i >= 0; --i) {
13628 		item = in->args.vc.pattern + i;
13629 		switch (item->type) {
13630 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13631 			ipv6_ext = item->spec;
13632 			*type = ipv6_ext->next_hdr;
13633 			break;
13634 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13635 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13636 			if (!ext->hdr.hdr_len) {
13637 				size = sizeof(struct rte_ipv6_routing_ext) +
13638 				(ext->hdr.segments_left << 4);
13639 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13640 				/* Indicate no TLV once SRH. */
13641 				if (ext->hdr.type == 4)
13642 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13643 			} else {
13644 				size = sizeof(struct rte_ipv6_routing_ext) +
13645 				(ext->hdr.hdr_len << 3);
13646 			}
13647 			*total_size += size;
13648 			memcpy(data, ext, size);
13649 			break;
13650 		default:
13651 			fprintf(stderr, "Error - Not supported item\n");
13652 			goto error;
13653 		}
13654 	}
13655 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13656 	return;
13657 error:
13658 	*total_size = 0;
13659 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13660 }
13661 
13662 /** Dispatch parsed buffer to function calls. */
13663 static void
13664 cmd_set_raw_parsed_sample(const struct buffer *in)
13665 {
13666 	uint32_t n = in->args.vc.actions_n;
13667 	uint32_t i = 0;
13668 	struct rte_flow_action *action = NULL;
13669 	struct rte_flow_action *data = NULL;
13670 	const struct rte_flow_action_rss *rss = NULL;
13671 	size_t size = 0;
13672 	uint16_t idx = in->port; /* We borrow port field as index */
13673 	uint32_t max_size = sizeof(struct rte_flow_action) *
13674 						ACTION_SAMPLE_ACTIONS_NUM;
13675 
13676 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13677 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13678 	memset(data, 0x00, max_size);
13679 	for (; i <= n - 1; i++) {
13680 		action = in->args.vc.actions + i;
13681 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13682 			break;
13683 		switch (action->type) {
13684 		case RTE_FLOW_ACTION_TYPE_MARK:
13685 			size = sizeof(struct rte_flow_action_mark);
13686 			rte_memcpy(&sample_mark[idx],
13687 				(const void *)action->conf, size);
13688 			action->conf = &sample_mark[idx];
13689 			break;
13690 		case RTE_FLOW_ACTION_TYPE_COUNT:
13691 			size = sizeof(struct rte_flow_action_count);
13692 			rte_memcpy(&sample_count[idx],
13693 				(const void *)action->conf, size);
13694 			action->conf = &sample_count[idx];
13695 			break;
13696 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13697 			size = sizeof(struct rte_flow_action_queue);
13698 			rte_memcpy(&sample_queue[idx],
13699 				(const void *)action->conf, size);
13700 			action->conf = &sample_queue[idx];
13701 			break;
13702 		case RTE_FLOW_ACTION_TYPE_RSS:
13703 			size = sizeof(struct rte_flow_action_rss);
13704 			rss = action->conf;
13705 			rte_memcpy(&sample_rss_data[idx].conf,
13706 				   (const void *)rss, size);
13707 			if (rss->key_len && rss->key) {
13708 				sample_rss_data[idx].conf.key =
13709 						sample_rss_data[idx].key;
13710 				rte_memcpy((void *)((uintptr_t)
13711 					   sample_rss_data[idx].conf.key),
13712 					   (const void *)rss->key,
13713 					   sizeof(uint8_t) * rss->key_len);
13714 			}
13715 			if (rss->queue_num && rss->queue) {
13716 				sample_rss_data[idx].conf.queue =
13717 						sample_rss_data[idx].queue;
13718 				rte_memcpy((void *)((uintptr_t)
13719 					   sample_rss_data[idx].conf.queue),
13720 					   (const void *)rss->queue,
13721 					   sizeof(uint16_t) * rss->queue_num);
13722 			}
13723 			action->conf = &sample_rss_data[idx].conf;
13724 			break;
13725 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13726 			size = sizeof(struct rte_flow_action_raw_encap);
13727 			rte_memcpy(&sample_encap[idx],
13728 				(const void *)action->conf, size);
13729 			action->conf = &sample_encap[idx];
13730 			break;
13731 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13732 			size = sizeof(struct rte_flow_action_port_id);
13733 			rte_memcpy(&sample_port_id[idx],
13734 				(const void *)action->conf, size);
13735 			action->conf = &sample_port_id[idx];
13736 			break;
13737 		case RTE_FLOW_ACTION_TYPE_PF:
13738 			break;
13739 		case RTE_FLOW_ACTION_TYPE_VF:
13740 			size = sizeof(struct rte_flow_action_vf);
13741 			rte_memcpy(&sample_vf[idx],
13742 					(const void *)action->conf, size);
13743 			action->conf = &sample_vf[idx];
13744 			break;
13745 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13746 			size = sizeof(struct rte_flow_action_vxlan_encap);
13747 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13748 			action->conf = &sample_vxlan_encap[idx].conf;
13749 			break;
13750 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13751 			size = sizeof(struct rte_flow_action_nvgre_encap);
13752 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13753 			action->conf = &sample_nvgre_encap[idx];
13754 			break;
13755 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13756 			size = sizeof(struct rte_flow_action_ethdev);
13757 			rte_memcpy(&sample_port_representor[idx],
13758 					(const void *)action->conf, size);
13759 			action->conf = &sample_port_representor[idx];
13760 			break;
13761 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13762 			size = sizeof(struct rte_flow_action_ethdev);
13763 			rte_memcpy(&sample_represented_port[idx],
13764 					(const void *)action->conf, size);
13765 			action->conf = &sample_represented_port[idx];
13766 			break;
13767 		default:
13768 			fprintf(stderr, "Error - Not supported action\n");
13769 			return;
13770 		}
13771 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13772 		data++;
13773 	}
13774 }
13775 
13776 /** Dispatch parsed buffer to function calls. */
13777 static void
13778 cmd_set_raw_parsed(const struct buffer *in)
13779 {
13780 	uint32_t n = in->args.vc.pattern_n;
13781 	int i = 0;
13782 	struct rte_flow_item *item = NULL;
13783 	size_t size = 0;
13784 	uint8_t *data = NULL;
13785 	uint8_t *data_tail = NULL;
13786 	size_t *total_size = NULL;
13787 	uint16_t upper_layer = 0;
13788 	uint16_t proto = 0;
13789 	uint16_t idx = in->port; /* We borrow port field as index */
13790 	int gtp_psc = -1; /* GTP PSC option index. */
13791 	const void *src_spec;
13792 
13793 	if (in->command == SET_SAMPLE_ACTIONS)
13794 		return cmd_set_raw_parsed_sample(in);
13795 	else if (in->command == SET_IPV6_EXT_PUSH ||
13796 		 in->command == SET_IPV6_EXT_REMOVE)
13797 		return cmd_set_ipv6_ext_parsed(in);
13798 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13799 		   in->command == SET_RAW_DECAP);
13800 	if (in->command == SET_RAW_ENCAP) {
13801 		total_size = &raw_encap_confs[idx].size;
13802 		data = (uint8_t *)&raw_encap_confs[idx].data;
13803 	} else {
13804 		total_size = &raw_decap_confs[idx].size;
13805 		data = (uint8_t *)&raw_decap_confs[idx].data;
13806 	}
13807 	*total_size = 0;
13808 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13809 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13810 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13811 	for (i = n - 1 ; i >= 0; --i) {
13812 		const struct rte_flow_item_gtp *gtp;
13813 		const struct rte_flow_item_geneve_opt *opt;
13814 		struct rte_flow_item_ipv6_routing_ext *ext;
13815 
13816 		item = in->args.vc.pattern + i;
13817 		if (item->spec == NULL)
13818 			item->spec = flow_item_default_mask(item);
13819 		src_spec = item->spec;
13820 		switch (item->type) {
13821 		case RTE_FLOW_ITEM_TYPE_ETH:
13822 			size = sizeof(struct rte_ether_hdr);
13823 			break;
13824 		case RTE_FLOW_ITEM_TYPE_VLAN:
13825 			size = sizeof(struct rte_vlan_hdr);
13826 			proto = RTE_ETHER_TYPE_VLAN;
13827 			break;
13828 		case RTE_FLOW_ITEM_TYPE_IPV4:
13829 			size = sizeof(struct rte_ipv4_hdr);
13830 			proto = RTE_ETHER_TYPE_IPV4;
13831 			break;
13832 		case RTE_FLOW_ITEM_TYPE_IPV6:
13833 			size = sizeof(struct rte_ipv6_hdr);
13834 			proto = RTE_ETHER_TYPE_IPV6;
13835 			break;
13836 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13837 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13838 			if (!ext->hdr.hdr_len) {
13839 				size = sizeof(struct rte_ipv6_routing_ext) +
13840 					(ext->hdr.segments_left << 4);
13841 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13842 				/* SRv6 without TLV. */
13843 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13844 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13845 			} else {
13846 				size = sizeof(struct rte_ipv6_routing_ext) +
13847 					(ext->hdr.hdr_len << 3);
13848 			}
13849 			proto = IPPROTO_ROUTING;
13850 			break;
13851 		case RTE_FLOW_ITEM_TYPE_UDP:
13852 			size = sizeof(struct rte_udp_hdr);
13853 			proto = 0x11;
13854 			break;
13855 		case RTE_FLOW_ITEM_TYPE_TCP:
13856 			size = sizeof(struct rte_tcp_hdr);
13857 			proto = 0x06;
13858 			break;
13859 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13860 			size = sizeof(struct rte_vxlan_hdr);
13861 			break;
13862 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13863 			size = sizeof(struct rte_vxlan_gpe_hdr);
13864 			break;
13865 		case RTE_FLOW_ITEM_TYPE_GRE:
13866 			size = sizeof(struct rte_gre_hdr);
13867 			proto = 0x2F;
13868 			break;
13869 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13870 			size = sizeof(rte_be32_t);
13871 			proto = 0x0;
13872 			break;
13873 		case RTE_FLOW_ITEM_TYPE_MPLS:
13874 			size = sizeof(struct rte_mpls_hdr);
13875 			proto = 0x0;
13876 			break;
13877 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13878 			size = sizeof(struct rte_flow_item_nvgre);
13879 			proto = 0x2F;
13880 			break;
13881 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13882 			size = sizeof(struct rte_geneve_hdr);
13883 			break;
13884 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13885 			opt = (const struct rte_flow_item_geneve_opt *)
13886 								item->spec;
13887 			size = offsetof(struct rte_flow_item_geneve_opt,
13888 					option_len) + sizeof(uint8_t);
13889 			if (opt->option_len && opt->data) {
13890 				*total_size += opt->option_len *
13891 					       sizeof(uint32_t);
13892 				rte_memcpy(data_tail - (*total_size),
13893 					   opt->data,
13894 					   opt->option_len * sizeof(uint32_t));
13895 			}
13896 			break;
13897 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13898 			size = sizeof(rte_be32_t);
13899 			proto = 0x73;
13900 			break;
13901 		case RTE_FLOW_ITEM_TYPE_ESP:
13902 			size = sizeof(struct rte_esp_hdr);
13903 			proto = 0x32;
13904 			break;
13905 		case RTE_FLOW_ITEM_TYPE_AH:
13906 			size = sizeof(struct rte_flow_item_ah);
13907 			proto = 0x33;
13908 			break;
13909 		case RTE_FLOW_ITEM_TYPE_GTP:
13910 			if (gtp_psc < 0) {
13911 				size = sizeof(struct rte_gtp_hdr);
13912 				break;
13913 			}
13914 			if (gtp_psc != i + 1) {
13915 				fprintf(stderr,
13916 					"Error - GTP PSC does not follow GTP\n");
13917 				goto error;
13918 			}
13919 			gtp = item->spec;
13920 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13921 				/* Only E flag should be set. */
13922 				fprintf(stderr,
13923 					"Error - GTP unsupported flags\n");
13924 				goto error;
13925 			} else {
13926 				struct rte_gtp_hdr_ext_word ext_word = {
13927 					.next_ext = 0x85
13928 				};
13929 
13930 				/* We have to add GTP header extra word. */
13931 				*total_size += sizeof(ext_word);
13932 				rte_memcpy(data_tail - (*total_size),
13933 					   &ext_word, sizeof(ext_word));
13934 			}
13935 			size = sizeof(struct rte_gtp_hdr);
13936 			break;
13937 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13938 			if (gtp_psc >= 0) {
13939 				fprintf(stderr,
13940 					"Error - Multiple GTP PSC items\n");
13941 				goto error;
13942 			} else {
13943 				const struct rte_flow_item_gtp_psc
13944 					*opt = item->spec;
13945 				struct rte_gtp_psc_generic_hdr *hdr;
13946 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
13947 							 sizeof(int32_t));
13948 
13949 				*total_size += hdr_size;
13950 				hdr = (typeof(hdr))(data_tail - (*total_size));
13951 				memset(hdr, 0, hdr_size);
13952 				*hdr = opt->hdr;
13953 				hdr->ext_hdr_len = 1;
13954 				gtp_psc = i;
13955 				size = 0;
13956 			}
13957 			break;
13958 		case RTE_FLOW_ITEM_TYPE_PFCP:
13959 			size = sizeof(struct rte_flow_item_pfcp);
13960 			break;
13961 		case RTE_FLOW_ITEM_TYPE_FLEX:
13962 			if (item->spec != NULL) {
13963 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
13964 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
13965 			} else {
13966 				size = 0;
13967 				src_spec = NULL;
13968 			}
13969 			break;
13970 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
13971 			size = 0;
13972 			if (item->spec) {
13973 				const struct rte_flow_item_gre_opt
13974 					*opt = item->spec;
13975 				if (opt->checksum_rsvd.checksum) {
13976 					*total_size +=
13977 						sizeof(opt->checksum_rsvd);
13978 					rte_memcpy(data_tail - (*total_size),
13979 						   &opt->checksum_rsvd,
13980 						   sizeof(opt->checksum_rsvd));
13981 				}
13982 				if (opt->key.key) {
13983 					*total_size += sizeof(opt->key.key);
13984 					rte_memcpy(data_tail - (*total_size),
13985 						   &opt->key.key,
13986 						   sizeof(opt->key.key));
13987 				}
13988 				if (opt->sequence.sequence) {
13989 					*total_size += sizeof(opt->sequence.sequence);
13990 					rte_memcpy(data_tail - (*total_size),
13991 						   &opt->sequence.sequence,
13992 						   sizeof(opt->sequence.sequence));
13993 				}
13994 			}
13995 			proto = 0x2F;
13996 			break;
13997 		default:
13998 			fprintf(stderr, "Error - Not supported item\n");
13999 			goto error;
14000 		}
14001 		if (size) {
14002 			*total_size += size;
14003 			rte_memcpy(data_tail - (*total_size), src_spec, size);
14004 			/* update some fields which cannot be set by cmdline */
14005 			update_fields((data_tail - (*total_size)), item,
14006 				      upper_layer);
14007 			upper_layer = proto;
14008 		}
14009 	}
14010 	if (verbose_level & 0x1)
14011 		printf("total data size is %zu\n", (*total_size));
14012 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14013 	memmove(data, (data_tail - (*total_size)), *total_size);
14014 	return;
14015 
14016 error:
14017 	*total_size = 0;
14018 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14019 }
14020 
14021 /** Populate help strings for current token (cmdline API). */
14022 static int
14023 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14024 		     unsigned int size)
14025 {
14026 	struct context *ctx = &cmd_flow_context;
14027 	const struct token *token = &token_list[ctx->prev];
14028 
14029 	(void)hdr;
14030 	if (!size)
14031 		return -1;
14032 	/* Set token type and update global help with details. */
14033 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14034 	if (token->help)
14035 		cmd_set_raw.help_str = token->help;
14036 	else
14037 		cmd_set_raw.help_str = token->name;
14038 	return 0;
14039 }
14040 
14041 /** Token definition template (cmdline API). */
14042 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14043 	.ops = &(struct cmdline_token_ops){
14044 		.parse = cmd_flow_parse,
14045 		.complete_get_nb = cmd_flow_complete_get_nb,
14046 		.complete_get_elt = cmd_flow_complete_get_elt,
14047 		.get_help = cmd_set_raw_get_help,
14048 	},
14049 	.offset = 0,
14050 };
14051 
14052 /** Populate the next dynamic token. */
14053 static void
14054 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14055 	     cmdline_parse_token_hdr_t **hdr_inst)
14056 {
14057 	struct context *ctx = &cmd_flow_context;
14058 
14059 	/* Always reinitialize context before requesting the first token. */
14060 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14061 		cmd_flow_context_init(ctx);
14062 		ctx->curr = START_SET;
14063 	}
14064 	/* Return NULL when no more tokens are expected. */
14065 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14066 		*hdr = NULL;
14067 		return;
14068 	}
14069 	/* Determine if command should end here. */
14070 	if (ctx->eol && ctx->last && ctx->next_num) {
14071 		const enum index *list = ctx->next[ctx->next_num - 1];
14072 		int i;
14073 
14074 		for (i = 0; list[i]; ++i) {
14075 			if (list[i] != END)
14076 				continue;
14077 			*hdr = NULL;
14078 			return;
14079 		}
14080 	}
14081 	*hdr = &cmd_set_raw_token_hdr;
14082 }
14083 
14084 /** Token generator and output processing callback (cmdline API). */
14085 static void
14086 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14087 {
14088 	if (cl == NULL)
14089 		cmd_set_raw_tok(arg0, arg2);
14090 	else
14091 		cmd_set_raw_parsed(arg0);
14092 }
14093 
14094 /** Global parser instance (cmdline API). */
14095 cmdline_parse_inst_t cmd_set_raw = {
14096 	.f = cmd_set_raw_cb,
14097 	.data = NULL, /**< Unused. */
14098 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14099 	.tokens = {
14100 		NULL,
14101 	}, /**< Tokens are returned by cmd_flow_tok(). */
14102 };
14103 
14104 /* *** display raw_encap/raw_decap buf */
14105 struct cmd_show_set_raw_result {
14106 	cmdline_fixed_string_t cmd_show;
14107 	cmdline_fixed_string_t cmd_what;
14108 	cmdline_fixed_string_t cmd_all;
14109 	uint16_t cmd_index;
14110 };
14111 
14112 static void
14113 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14114 {
14115 	struct cmd_show_set_raw_result *res = parsed_result;
14116 	uint16_t index = res->cmd_index;
14117 	uint8_t all = 0;
14118 	uint8_t *raw_data = NULL;
14119 	size_t raw_size = 0;
14120 	char title[16] = {0};
14121 
14122 	RTE_SET_USED(cl);
14123 	RTE_SET_USED(data);
14124 	if (!strcmp(res->cmd_all, "all")) {
14125 		all = 1;
14126 		index = 0;
14127 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14128 		fprintf(stderr, "index should be 0-%u\n",
14129 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14130 		return;
14131 	}
14132 	do {
14133 		if (!strcmp(res->cmd_what, "raw_encap")) {
14134 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14135 			raw_size = raw_encap_confs[index].size;
14136 			snprintf(title, 16, "\nindex: %u", index);
14137 			rte_hexdump(stdout, title, raw_data, raw_size);
14138 		} else {
14139 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14140 			raw_size = raw_decap_confs[index].size;
14141 			snprintf(title, 16, "\nindex: %u", index);
14142 			rte_hexdump(stdout, title, raw_data, raw_size);
14143 		}
14144 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14145 }
14146 
14147 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14148 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14149 			cmd_show, "show");
14150 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14151 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14152 			cmd_what, "raw_encap#raw_decap");
14153 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14154 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14155 			cmd_index, RTE_UINT16);
14156 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14157 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14158 			cmd_all, "all");
14159 cmdline_parse_inst_t cmd_show_set_raw = {
14160 	.f = cmd_show_set_raw_parsed,
14161 	.data = NULL,
14162 	.help_str = "show <raw_encap|raw_decap> <index>",
14163 	.tokens = {
14164 		(void *)&cmd_show_set_raw_cmd_show,
14165 		(void *)&cmd_show_set_raw_cmd_what,
14166 		(void *)&cmd_show_set_raw_cmd_index,
14167 		NULL,
14168 	},
14169 };
14170 cmdline_parse_inst_t cmd_show_set_raw_all = {
14171 	.f = cmd_show_set_raw_parsed,
14172 	.data = NULL,
14173 	.help_str = "show <raw_encap|raw_decap> all",
14174 	.tokens = {
14175 		(void *)&cmd_show_set_raw_cmd_show,
14176 		(void *)&cmd_show_set_raw_cmd_what,
14177 		(void *)&cmd_show_set_raw_cmd_all,
14178 		NULL,
14179 	},
14180 };
14181