xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 20313fa7e99b650befa633049b0ffa0496a7d19f)
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 	FLUSH,
95 	DUMP,
96 	QUERY,
97 	LIST,
98 	AGED,
99 	ISOLATE,
100 	TUNNEL,
101 	FLEX,
102 	QUEUE,
103 	PUSH,
104 	PULL,
105 	HASH,
106 
107 	/* Flex arguments */
108 	FLEX_ITEM_INIT,
109 	FLEX_ITEM_CREATE,
110 	FLEX_ITEM_DESTROY,
111 
112 	/* Pattern template arguments. */
113 	PATTERN_TEMPLATE_CREATE,
114 	PATTERN_TEMPLATE_DESTROY,
115 	PATTERN_TEMPLATE_CREATE_ID,
116 	PATTERN_TEMPLATE_DESTROY_ID,
117 	PATTERN_TEMPLATE_RELAXED_MATCHING,
118 	PATTERN_TEMPLATE_INGRESS,
119 	PATTERN_TEMPLATE_EGRESS,
120 	PATTERN_TEMPLATE_TRANSFER,
121 	PATTERN_TEMPLATE_SPEC,
122 
123 	/* Actions template arguments. */
124 	ACTIONS_TEMPLATE_CREATE,
125 	ACTIONS_TEMPLATE_DESTROY,
126 	ACTIONS_TEMPLATE_CREATE_ID,
127 	ACTIONS_TEMPLATE_DESTROY_ID,
128 	ACTIONS_TEMPLATE_INGRESS,
129 	ACTIONS_TEMPLATE_EGRESS,
130 	ACTIONS_TEMPLATE_TRANSFER,
131 	ACTIONS_TEMPLATE_SPEC,
132 	ACTIONS_TEMPLATE_MASK,
133 
134 	/* Queue arguments. */
135 	QUEUE_CREATE,
136 	QUEUE_DESTROY,
137 	QUEUE_FLOW_UPDATE_RESIZED,
138 	QUEUE_UPDATE,
139 	QUEUE_AGED,
140 	QUEUE_INDIRECT_ACTION,
141 
142 	/* Queue create arguments. */
143 	QUEUE_CREATE_POSTPONE,
144 	QUEUE_TEMPLATE_TABLE,
145 	QUEUE_PATTERN_TEMPLATE,
146 	QUEUE_ACTIONS_TEMPLATE,
147 	QUEUE_RULE_ID,
148 
149 	/* Queue destroy arguments. */
150 	QUEUE_DESTROY_ID,
151 	QUEUE_DESTROY_POSTPONE,
152 
153 	/* Queue update arguments. */
154 	QUEUE_UPDATE_ID,
155 
156 	/* Queue indirect action arguments */
157 	QUEUE_INDIRECT_ACTION_CREATE,
158 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
159 	QUEUE_INDIRECT_ACTION_UPDATE,
160 	QUEUE_INDIRECT_ACTION_DESTROY,
161 	QUEUE_INDIRECT_ACTION_QUERY,
162 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
163 
164 	/* Queue indirect action create arguments */
165 	QUEUE_INDIRECT_ACTION_CREATE_ID,
166 	QUEUE_INDIRECT_ACTION_INGRESS,
167 	QUEUE_INDIRECT_ACTION_EGRESS,
168 	QUEUE_INDIRECT_ACTION_TRANSFER,
169 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
170 	QUEUE_INDIRECT_ACTION_SPEC,
171 	QUEUE_INDIRECT_ACTION_LIST,
172 
173 	/* Queue indirect action update arguments */
174 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
175 
176 	/* Queue indirect action destroy arguments */
177 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
178 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
179 
180 	/* Queue indirect action query arguments */
181 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
182 
183 	/* Queue indirect action query_update arguments */
184 	QUEUE_INDIRECT_ACTION_QU_MODE,
185 
186 	/* Push arguments. */
187 	PUSH_QUEUE,
188 
189 	/* Pull arguments. */
190 	PULL_QUEUE,
191 
192 	/* Table arguments. */
193 	TABLE_CREATE,
194 	TABLE_DESTROY,
195 	TABLE_RESIZE,
196 	TABLE_RESIZE_COMPLETE,
197 	TABLE_CREATE_ID,
198 	TABLE_DESTROY_ID,
199 	TABLE_RESIZE_ID,
200 	TABLE_RESIZE_RULES_NUMBER,
201 	TABLE_INSERTION_TYPE,
202 	TABLE_INSERTION_TYPE_NAME,
203 	TABLE_HASH_FUNC,
204 	TABLE_HASH_FUNC_NAME,
205 	TABLE_GROUP,
206 	TABLE_PRIORITY,
207 	TABLE_INGRESS,
208 	TABLE_EGRESS,
209 	TABLE_TRANSFER,
210 	TABLE_TRANSFER_WIRE_ORIG,
211 	TABLE_TRANSFER_VPORT_ORIG,
212 	TABLE_RESIZABLE,
213 	TABLE_RULES_NUMBER,
214 	TABLE_PATTERN_TEMPLATE,
215 	TABLE_ACTIONS_TEMPLATE,
216 
217 	/* Group arguments */
218 	GROUP_ID,
219 	GROUP_INGRESS,
220 	GROUP_EGRESS,
221 	GROUP_TRANSFER,
222 	GROUP_SET_MISS_ACTIONS,
223 
224 	/* Hash calculation arguments. */
225 	HASH_CALC_TABLE,
226 	HASH_CALC_PATTERN_INDEX,
227 	HASH_CALC_PATTERN,
228 	HASH_CALC_ENCAP,
229 	HASH_CALC_DEST,
230 	ENCAP_HASH_FIELD_SRC_PORT,
231 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
232 
233 	/* Tunnel arguments. */
234 	TUNNEL_CREATE,
235 	TUNNEL_CREATE_TYPE,
236 	TUNNEL_LIST,
237 	TUNNEL_DESTROY,
238 	TUNNEL_DESTROY_ID,
239 
240 	/* Destroy arguments. */
241 	DESTROY_RULE,
242 	DESTROY_IS_USER_ID,
243 
244 	/* Query arguments. */
245 	QUERY_ACTION,
246 	QUERY_IS_USER_ID,
247 
248 	/* List arguments. */
249 	LIST_GROUP,
250 
251 	/* Destroy aged flow arguments. */
252 	AGED_DESTROY,
253 
254 	/* Validate/create arguments. */
255 	VC_GROUP,
256 	VC_PRIORITY,
257 	VC_INGRESS,
258 	VC_EGRESS,
259 	VC_TRANSFER,
260 	VC_TUNNEL_SET,
261 	VC_TUNNEL_MATCH,
262 	VC_USER_ID,
263 
264 	/* Dump arguments */
265 	DUMP_ALL,
266 	DUMP_ONE,
267 	DUMP_IS_USER_ID,
268 
269 	/* Configure arguments */
270 	CONFIG_QUEUES_NUMBER,
271 	CONFIG_QUEUES_SIZE,
272 	CONFIG_COUNTERS_NUMBER,
273 	CONFIG_AGING_OBJECTS_NUMBER,
274 	CONFIG_METERS_NUMBER,
275 	CONFIG_CONN_TRACK_NUMBER,
276 	CONFIG_QUOTAS_NUMBER,
277 	CONFIG_FLAGS,
278 	CONFIG_HOST_PORT,
279 
280 	/* Indirect action arguments */
281 	INDIRECT_ACTION_CREATE,
282 	INDIRECT_ACTION_LIST_CREATE,
283 	INDIRECT_ACTION_FLOW_CONF_CREATE,
284 	INDIRECT_ACTION_UPDATE,
285 	INDIRECT_ACTION_DESTROY,
286 	INDIRECT_ACTION_QUERY,
287 	INDIRECT_ACTION_QUERY_UPDATE,
288 
289 	/* Indirect action create arguments */
290 	INDIRECT_ACTION_CREATE_ID,
291 	INDIRECT_ACTION_INGRESS,
292 	INDIRECT_ACTION_EGRESS,
293 	INDIRECT_ACTION_TRANSFER,
294 	INDIRECT_ACTION_SPEC,
295 	INDIRECT_ACTION_LIST,
296 	INDIRECT_ACTION_FLOW_CONF,
297 
298 	/* Indirect action destroy arguments */
299 	INDIRECT_ACTION_DESTROY_ID,
300 
301 	/* Indirect action query-and-update arguments */
302 	INDIRECT_ACTION_QU_MODE,
303 	INDIRECT_ACTION_QU_MODE_NAME,
304 
305 	/* Validate/create pattern. */
306 	ITEM_PATTERN,
307 	ITEM_PARAM_IS,
308 	ITEM_PARAM_SPEC,
309 	ITEM_PARAM_LAST,
310 	ITEM_PARAM_MASK,
311 	ITEM_PARAM_PREFIX,
312 	ITEM_NEXT,
313 	ITEM_END,
314 	ITEM_VOID,
315 	ITEM_INVERT,
316 	ITEM_ANY,
317 	ITEM_ANY_NUM,
318 	ITEM_PORT_ID,
319 	ITEM_PORT_ID_ID,
320 	ITEM_MARK,
321 	ITEM_MARK_ID,
322 	ITEM_RAW,
323 	ITEM_RAW_RELATIVE,
324 	ITEM_RAW_SEARCH,
325 	ITEM_RAW_OFFSET,
326 	ITEM_RAW_LIMIT,
327 	ITEM_RAW_PATTERN,
328 	ITEM_RAW_PATTERN_HEX,
329 	ITEM_ETH,
330 	ITEM_ETH_DST,
331 	ITEM_ETH_SRC,
332 	ITEM_ETH_TYPE,
333 	ITEM_ETH_HAS_VLAN,
334 	ITEM_VLAN,
335 	ITEM_VLAN_TCI,
336 	ITEM_VLAN_PCP,
337 	ITEM_VLAN_DEI,
338 	ITEM_VLAN_VID,
339 	ITEM_VLAN_INNER_TYPE,
340 	ITEM_VLAN_HAS_MORE_VLAN,
341 	ITEM_IPV4,
342 	ITEM_IPV4_VER_IHL,
343 	ITEM_IPV4_TOS,
344 	ITEM_IPV4_LENGTH,
345 	ITEM_IPV4_ID,
346 	ITEM_IPV4_FRAGMENT_OFFSET,
347 	ITEM_IPV4_TTL,
348 	ITEM_IPV4_PROTO,
349 	ITEM_IPV4_SRC,
350 	ITEM_IPV4_DST,
351 	ITEM_IPV6,
352 	ITEM_IPV6_TC,
353 	ITEM_IPV6_FLOW,
354 	ITEM_IPV6_LEN,
355 	ITEM_IPV6_PROTO,
356 	ITEM_IPV6_HOP,
357 	ITEM_IPV6_SRC,
358 	ITEM_IPV6_DST,
359 	ITEM_IPV6_HAS_FRAG_EXT,
360 	ITEM_IPV6_ROUTING_EXT,
361 	ITEM_IPV6_ROUTING_EXT_TYPE,
362 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
363 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
364 	ITEM_ICMP,
365 	ITEM_ICMP_TYPE,
366 	ITEM_ICMP_CODE,
367 	ITEM_ICMP_IDENT,
368 	ITEM_ICMP_SEQ,
369 	ITEM_UDP,
370 	ITEM_UDP_SRC,
371 	ITEM_UDP_DST,
372 	ITEM_TCP,
373 	ITEM_TCP_SRC,
374 	ITEM_TCP_DST,
375 	ITEM_TCP_FLAGS,
376 	ITEM_SCTP,
377 	ITEM_SCTP_SRC,
378 	ITEM_SCTP_DST,
379 	ITEM_SCTP_TAG,
380 	ITEM_SCTP_CKSUM,
381 	ITEM_VXLAN,
382 	ITEM_VXLAN_VNI,
383 	ITEM_VXLAN_LAST_RSVD,
384 	ITEM_E_TAG,
385 	ITEM_E_TAG_GRP_ECID_B,
386 	ITEM_NVGRE,
387 	ITEM_NVGRE_TNI,
388 	ITEM_MPLS,
389 	ITEM_MPLS_LABEL,
390 	ITEM_MPLS_TC,
391 	ITEM_MPLS_S,
392 	ITEM_MPLS_TTL,
393 	ITEM_GRE,
394 	ITEM_GRE_PROTO,
395 	ITEM_GRE_C_RSVD0_VER,
396 	ITEM_GRE_C_BIT,
397 	ITEM_GRE_K_BIT,
398 	ITEM_GRE_S_BIT,
399 	ITEM_FUZZY,
400 	ITEM_FUZZY_THRESH,
401 	ITEM_GTP,
402 	ITEM_GTP_FLAGS,
403 	ITEM_GTP_MSG_TYPE,
404 	ITEM_GTP_TEID,
405 	ITEM_GTPC,
406 	ITEM_GTPU,
407 	ITEM_GENEVE,
408 	ITEM_GENEVE_VNI,
409 	ITEM_GENEVE_PROTO,
410 	ITEM_GENEVE_OPTLEN,
411 	ITEM_VXLAN_GPE,
412 	ITEM_VXLAN_GPE_VNI,
413 	ITEM_VXLAN_GPE_PROTO,
414 	ITEM_VXLAN_GPE_FLAGS,
415 	ITEM_ARP_ETH_IPV4,
416 	ITEM_ARP_ETH_IPV4_SHA,
417 	ITEM_ARP_ETH_IPV4_SPA,
418 	ITEM_ARP_ETH_IPV4_THA,
419 	ITEM_ARP_ETH_IPV4_TPA,
420 	ITEM_IPV6_EXT,
421 	ITEM_IPV6_EXT_NEXT_HDR,
422 	ITEM_IPV6_FRAG_EXT,
423 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
424 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
425 	ITEM_IPV6_FRAG_EXT_ID,
426 	ITEM_ICMP6,
427 	ITEM_ICMP6_TYPE,
428 	ITEM_ICMP6_CODE,
429 	ITEM_ICMP6_ECHO_REQUEST,
430 	ITEM_ICMP6_ECHO_REQUEST_ID,
431 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
432 	ITEM_ICMP6_ECHO_REPLY,
433 	ITEM_ICMP6_ECHO_REPLY_ID,
434 	ITEM_ICMP6_ECHO_REPLY_SEQ,
435 	ITEM_ICMP6_ND_NS,
436 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
437 	ITEM_ICMP6_ND_NA,
438 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
439 	ITEM_ICMP6_ND_OPT,
440 	ITEM_ICMP6_ND_OPT_TYPE,
441 	ITEM_ICMP6_ND_OPT_SLA_ETH,
442 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
443 	ITEM_ICMP6_ND_OPT_TLA_ETH,
444 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
445 	ITEM_META,
446 	ITEM_META_DATA,
447 	ITEM_RANDOM,
448 	ITEM_RANDOM_VALUE,
449 	ITEM_GRE_KEY,
450 	ITEM_GRE_KEY_VALUE,
451 	ITEM_GRE_OPTION,
452 	ITEM_GRE_OPTION_CHECKSUM,
453 	ITEM_GRE_OPTION_KEY,
454 	ITEM_GRE_OPTION_SEQUENCE,
455 	ITEM_GTP_PSC,
456 	ITEM_GTP_PSC_QFI,
457 	ITEM_GTP_PSC_PDU_T,
458 	ITEM_PPPOES,
459 	ITEM_PPPOED,
460 	ITEM_PPPOE_SEID,
461 	ITEM_PPPOE_PROTO_ID,
462 	ITEM_HIGIG2,
463 	ITEM_HIGIG2_CLASSIFICATION,
464 	ITEM_HIGIG2_VID,
465 	ITEM_TAG,
466 	ITEM_TAG_DATA,
467 	ITEM_TAG_INDEX,
468 	ITEM_L2TPV3OIP,
469 	ITEM_L2TPV3OIP_SESSION_ID,
470 	ITEM_ESP,
471 	ITEM_ESP_SPI,
472 	ITEM_AH,
473 	ITEM_AH_SPI,
474 	ITEM_PFCP,
475 	ITEM_PFCP_S_FIELD,
476 	ITEM_PFCP_SEID,
477 	ITEM_ECPRI,
478 	ITEM_ECPRI_COMMON,
479 	ITEM_ECPRI_COMMON_TYPE,
480 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
481 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
482 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
483 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
484 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
485 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
486 	ITEM_GENEVE_OPT,
487 	ITEM_GENEVE_OPT_CLASS,
488 	ITEM_GENEVE_OPT_TYPE,
489 	ITEM_GENEVE_OPT_LENGTH,
490 	ITEM_GENEVE_OPT_DATA,
491 	ITEM_INTEGRITY,
492 	ITEM_INTEGRITY_LEVEL,
493 	ITEM_INTEGRITY_VALUE,
494 	ITEM_CONNTRACK,
495 	ITEM_POL_PORT,
496 	ITEM_POL_METER,
497 	ITEM_POL_POLICY,
498 	ITEM_PORT_REPRESENTOR,
499 	ITEM_PORT_REPRESENTOR_PORT_ID,
500 	ITEM_REPRESENTED_PORT,
501 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
502 	ITEM_FLEX,
503 	ITEM_FLEX_ITEM_HANDLE,
504 	ITEM_FLEX_PATTERN_HANDLE,
505 	ITEM_L2TPV2,
506 	ITEM_L2TPV2_TYPE,
507 	ITEM_L2TPV2_TYPE_DATA,
508 	ITEM_L2TPV2_TYPE_DATA_L,
509 	ITEM_L2TPV2_TYPE_DATA_S,
510 	ITEM_L2TPV2_TYPE_DATA_O,
511 	ITEM_L2TPV2_TYPE_DATA_L_S,
512 	ITEM_L2TPV2_TYPE_CTRL,
513 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
514 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
515 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
516 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
517 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
518 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
519 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
520 	ITEM_L2TPV2_MSG_DATA_S_NS,
521 	ITEM_L2TPV2_MSG_DATA_S_NR,
522 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
523 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
524 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
525 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
526 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
527 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
528 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
529 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
530 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
531 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
532 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
533 	ITEM_L2TPV2_MSG_CTRL_NS,
534 	ITEM_L2TPV2_MSG_CTRL_NR,
535 	ITEM_PPP,
536 	ITEM_PPP_ADDR,
537 	ITEM_PPP_CTRL,
538 	ITEM_PPP_PROTO_ID,
539 	ITEM_METER,
540 	ITEM_METER_COLOR,
541 	ITEM_METER_COLOR_NAME,
542 	ITEM_QUOTA,
543 	ITEM_QUOTA_STATE,
544 	ITEM_QUOTA_STATE_NAME,
545 	ITEM_AGGR_AFFINITY,
546 	ITEM_AGGR_AFFINITY_VALUE,
547 	ITEM_TX_QUEUE,
548 	ITEM_TX_QUEUE_VALUE,
549 	ITEM_IB_BTH,
550 	ITEM_IB_BTH_OPCODE,
551 	ITEM_IB_BTH_PKEY,
552 	ITEM_IB_BTH_DST_QPN,
553 	ITEM_IB_BTH_PSN,
554 	ITEM_IPV6_PUSH_REMOVE_EXT,
555 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
556 	ITEM_PTYPE,
557 	ITEM_PTYPE_VALUE,
558 	ITEM_NSH,
559 	ITEM_COMPARE,
560 	ITEM_COMPARE_OP,
561 	ITEM_COMPARE_OP_VALUE,
562 	ITEM_COMPARE_FIELD_A_TYPE,
563 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
564 	ITEM_COMPARE_FIELD_A_LEVEL,
565 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
566 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
567 	ITEM_COMPARE_FIELD_A_TYPE_ID,
568 	ITEM_COMPARE_FIELD_A_CLASS_ID,
569 	ITEM_COMPARE_FIELD_A_OFFSET,
570 	ITEM_COMPARE_FIELD_B_TYPE,
571 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
572 	ITEM_COMPARE_FIELD_B_LEVEL,
573 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
574 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
575 	ITEM_COMPARE_FIELD_B_TYPE_ID,
576 	ITEM_COMPARE_FIELD_B_CLASS_ID,
577 	ITEM_COMPARE_FIELD_B_OFFSET,
578 	ITEM_COMPARE_FIELD_B_VALUE,
579 	ITEM_COMPARE_FIELD_B_POINTER,
580 	ITEM_COMPARE_FIELD_WIDTH,
581 
582 	/* Validate/create actions. */
583 	ACTIONS,
584 	ACTION_NEXT,
585 	ACTION_END,
586 	ACTION_VOID,
587 	ACTION_PASSTHRU,
588 	ACTION_SKIP_CMAN,
589 	ACTION_JUMP,
590 	ACTION_JUMP_GROUP,
591 	ACTION_MARK,
592 	ACTION_MARK_ID,
593 	ACTION_FLAG,
594 	ACTION_QUEUE,
595 	ACTION_QUEUE_INDEX,
596 	ACTION_DROP,
597 	ACTION_COUNT,
598 	ACTION_COUNT_ID,
599 	ACTION_RSS,
600 	ACTION_RSS_FUNC,
601 	ACTION_RSS_LEVEL,
602 	ACTION_RSS_FUNC_DEFAULT,
603 	ACTION_RSS_FUNC_TOEPLITZ,
604 	ACTION_RSS_FUNC_SIMPLE_XOR,
605 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
606 	ACTION_RSS_TYPES,
607 	ACTION_RSS_TYPE,
608 	ACTION_RSS_KEY,
609 	ACTION_RSS_KEY_LEN,
610 	ACTION_RSS_QUEUES,
611 	ACTION_RSS_QUEUE,
612 	ACTION_PF,
613 	ACTION_VF,
614 	ACTION_VF_ORIGINAL,
615 	ACTION_VF_ID,
616 	ACTION_PORT_ID,
617 	ACTION_PORT_ID_ORIGINAL,
618 	ACTION_PORT_ID_ID,
619 	ACTION_METER,
620 	ACTION_METER_COLOR,
621 	ACTION_METER_COLOR_TYPE,
622 	ACTION_METER_COLOR_GREEN,
623 	ACTION_METER_COLOR_YELLOW,
624 	ACTION_METER_COLOR_RED,
625 	ACTION_METER_ID,
626 	ACTION_METER_MARK,
627 	ACTION_METER_PROFILE,
628 	ACTION_METER_PROFILE_ID2PTR,
629 	ACTION_METER_POLICY,
630 	ACTION_METER_POLICY_ID2PTR,
631 	ACTION_METER_COLOR_MODE,
632 	ACTION_METER_STATE,
633 	ACTION_OF_DEC_NW_TTL,
634 	ACTION_OF_POP_VLAN,
635 	ACTION_OF_PUSH_VLAN,
636 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
637 	ACTION_OF_SET_VLAN_VID,
638 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
639 	ACTION_OF_SET_VLAN_PCP,
640 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
641 	ACTION_OF_POP_MPLS,
642 	ACTION_OF_POP_MPLS_ETHERTYPE,
643 	ACTION_OF_PUSH_MPLS,
644 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
645 	ACTION_VXLAN_ENCAP,
646 	ACTION_VXLAN_DECAP,
647 	ACTION_NVGRE_ENCAP,
648 	ACTION_NVGRE_DECAP,
649 	ACTION_L2_ENCAP,
650 	ACTION_L2_DECAP,
651 	ACTION_MPLSOGRE_ENCAP,
652 	ACTION_MPLSOGRE_DECAP,
653 	ACTION_MPLSOUDP_ENCAP,
654 	ACTION_MPLSOUDP_DECAP,
655 	ACTION_SET_IPV4_SRC,
656 	ACTION_SET_IPV4_SRC_IPV4_SRC,
657 	ACTION_SET_IPV4_DST,
658 	ACTION_SET_IPV4_DST_IPV4_DST,
659 	ACTION_SET_IPV6_SRC,
660 	ACTION_SET_IPV6_SRC_IPV6_SRC,
661 	ACTION_SET_IPV6_DST,
662 	ACTION_SET_IPV6_DST_IPV6_DST,
663 	ACTION_SET_TP_SRC,
664 	ACTION_SET_TP_SRC_TP_SRC,
665 	ACTION_SET_TP_DST,
666 	ACTION_SET_TP_DST_TP_DST,
667 	ACTION_MAC_SWAP,
668 	ACTION_DEC_TTL,
669 	ACTION_SET_TTL,
670 	ACTION_SET_TTL_TTL,
671 	ACTION_SET_MAC_SRC,
672 	ACTION_SET_MAC_SRC_MAC_SRC,
673 	ACTION_SET_MAC_DST,
674 	ACTION_SET_MAC_DST_MAC_DST,
675 	ACTION_INC_TCP_SEQ,
676 	ACTION_INC_TCP_SEQ_VALUE,
677 	ACTION_DEC_TCP_SEQ,
678 	ACTION_DEC_TCP_SEQ_VALUE,
679 	ACTION_INC_TCP_ACK,
680 	ACTION_INC_TCP_ACK_VALUE,
681 	ACTION_DEC_TCP_ACK,
682 	ACTION_DEC_TCP_ACK_VALUE,
683 	ACTION_RAW_ENCAP,
684 	ACTION_RAW_DECAP,
685 	ACTION_RAW_ENCAP_SIZE,
686 	ACTION_RAW_ENCAP_INDEX,
687 	ACTION_RAW_ENCAP_INDEX_VALUE,
688 	ACTION_RAW_DECAP_INDEX,
689 	ACTION_RAW_DECAP_INDEX_VALUE,
690 	ACTION_SET_TAG,
691 	ACTION_SET_TAG_DATA,
692 	ACTION_SET_TAG_INDEX,
693 	ACTION_SET_TAG_MASK,
694 	ACTION_SET_META,
695 	ACTION_SET_META_DATA,
696 	ACTION_SET_META_MASK,
697 	ACTION_SET_IPV4_DSCP,
698 	ACTION_SET_IPV4_DSCP_VALUE,
699 	ACTION_SET_IPV6_DSCP,
700 	ACTION_SET_IPV6_DSCP_VALUE,
701 	ACTION_AGE,
702 	ACTION_AGE_TIMEOUT,
703 	ACTION_AGE_UPDATE,
704 	ACTION_AGE_UPDATE_TIMEOUT,
705 	ACTION_AGE_UPDATE_TOUCH,
706 	ACTION_SAMPLE,
707 	ACTION_SAMPLE_RATIO,
708 	ACTION_SAMPLE_INDEX,
709 	ACTION_SAMPLE_INDEX_VALUE,
710 	ACTION_INDIRECT,
711 	ACTION_INDIRECT_LIST,
712 	ACTION_INDIRECT_LIST_HANDLE,
713 	ACTION_INDIRECT_LIST_CONF,
714 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
715 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
716 	ACTION_SHARED_INDIRECT,
717 	INDIRECT_ACTION_PORT,
718 	INDIRECT_ACTION_ID2PTR,
719 	ACTION_MODIFY_FIELD,
720 	ACTION_MODIFY_FIELD_OP,
721 	ACTION_MODIFY_FIELD_OP_VALUE,
722 	ACTION_MODIFY_FIELD_DST_TYPE,
723 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
724 	ACTION_MODIFY_FIELD_DST_LEVEL,
725 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
726 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
727 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
728 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
729 	ACTION_MODIFY_FIELD_DST_OFFSET,
730 	ACTION_MODIFY_FIELD_SRC_TYPE,
731 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
732 	ACTION_MODIFY_FIELD_SRC_LEVEL,
733 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
734 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
735 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
736 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
737 	ACTION_MODIFY_FIELD_SRC_OFFSET,
738 	ACTION_MODIFY_FIELD_SRC_VALUE,
739 	ACTION_MODIFY_FIELD_SRC_POINTER,
740 	ACTION_MODIFY_FIELD_WIDTH,
741 	ACTION_CONNTRACK,
742 	ACTION_CONNTRACK_UPDATE,
743 	ACTION_CONNTRACK_UPDATE_DIR,
744 	ACTION_CONNTRACK_UPDATE_CTX,
745 	ACTION_POL_G,
746 	ACTION_POL_Y,
747 	ACTION_POL_R,
748 	ACTION_PORT_REPRESENTOR,
749 	ACTION_PORT_REPRESENTOR_PORT_ID,
750 	ACTION_REPRESENTED_PORT,
751 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
752 	ACTION_SEND_TO_KERNEL,
753 	ACTION_QUOTA_CREATE,
754 	ACTION_QUOTA_CREATE_LIMIT,
755 	ACTION_QUOTA_CREATE_MODE,
756 	ACTION_QUOTA_CREATE_MODE_NAME,
757 	ACTION_QUOTA_QU,
758 	ACTION_QUOTA_QU_LIMIT,
759 	ACTION_QUOTA_QU_UPDATE_OP,
760 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
761 	ACTION_IPV6_EXT_REMOVE,
762 	ACTION_IPV6_EXT_REMOVE_INDEX,
763 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
764 	ACTION_IPV6_EXT_PUSH,
765 	ACTION_IPV6_EXT_PUSH_INDEX,
766 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
767 	ACTION_NAT64,
768 	ACTION_NAT64_MODE,
769 };
770 
771 /** Maximum size for pattern in struct rte_flow_item_raw. */
772 #define ITEM_RAW_PATTERN_SIZE 512
773 
774 /** Maximum size for GENEVE option data pattern in bytes. */
775 #define ITEM_GENEVE_OPT_DATA_SIZE 124
776 
777 /** Storage size for struct rte_flow_item_raw including pattern. */
778 #define ITEM_RAW_SIZE \
779 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
780 
781 static const char *const compare_ops[] = {
782 	"eq", "ne", "lt", "le", "gt", "ge", NULL
783 };
784 
785 /** Maximum size for external pattern in struct rte_flow_field_data. */
786 #define FLOW_FIELD_PATTERN_SIZE 32
787 
788 /** Storage size for struct rte_flow_action_modify_field including pattern. */
789 #define ACTION_MODIFY_SIZE \
790 	(sizeof(struct rte_flow_action_modify_field) + \
791 	FLOW_FIELD_PATTERN_SIZE)
792 
793 /** Maximum number of queue indices in struct rte_flow_action_rss. */
794 #define ACTION_RSS_QUEUE_NUM 128
795 
796 /** Storage for struct rte_flow_action_rss including external data. */
797 struct action_rss_data {
798 	struct rte_flow_action_rss conf;
799 	uint8_t key[RSS_HASH_KEY_LENGTH];
800 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
801 };
802 
803 /** Maximum data size in struct rte_flow_action_raw_encap. */
804 #define ACTION_RAW_ENCAP_MAX_DATA 512
805 #define RAW_ENCAP_CONFS_MAX_NUM 8
806 
807 /** Storage for struct rte_flow_action_raw_encap. */
808 struct raw_encap_conf {
809 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
810 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
811 	size_t size;
812 };
813 
814 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
815 
816 /** Storage for struct rte_flow_action_raw_encap including external data. */
817 struct action_raw_encap_data {
818 	struct rte_flow_action_raw_encap conf;
819 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
820 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
821 	uint16_t idx;
822 };
823 
824 /** Storage for struct rte_flow_action_raw_decap. */
825 struct raw_decap_conf {
826 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
827 	size_t size;
828 };
829 
830 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
831 
832 /** Storage for struct rte_flow_action_raw_decap including external data. */
833 struct action_raw_decap_data {
834 	struct rte_flow_action_raw_decap conf;
835 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
836 	uint16_t idx;
837 };
838 
839 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
840 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
841 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
842 
843 /** Storage for struct rte_flow_action_ipv6_ext_push. */
844 struct ipv6_ext_push_conf {
845 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
846 	size_t size;
847 	uint8_t type;
848 };
849 
850 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
851 
852 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
853 struct action_ipv6_ext_push_data {
854 	struct rte_flow_action_ipv6_ext_push conf;
855 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
856 	uint8_t type;
857 	uint16_t idx;
858 };
859 
860 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
861 struct ipv6_ext_remove_conf {
862 	struct rte_flow_action_ipv6_ext_remove conf;
863 	uint8_t type;
864 };
865 
866 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
867 
868 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
869 struct action_ipv6_ext_remove_data {
870 	struct rte_flow_action_ipv6_ext_remove conf;
871 	uint8_t type;
872 	uint16_t idx;
873 };
874 
875 struct vxlan_encap_conf vxlan_encap_conf = {
876 	.select_ipv4 = 1,
877 	.select_vlan = 0,
878 	.select_tos_ttl = 0,
879 	.vni = "\x00\x00\x00",
880 	.udp_src = 0,
881 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
882 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
883 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
884 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
885 		"\x00\x00\x00\x00\x00\x00\x00\x01",
886 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
887 		"\x00\x00\x00\x00\x00\x00\x11\x11",
888 	.vlan_tci = 0,
889 	.ip_tos = 0,
890 	.ip_ttl = 255,
891 	.eth_src = "\x00\x00\x00\x00\x00\x00",
892 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
893 };
894 
895 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
896 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
897 
898 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
899 struct action_vxlan_encap_data {
900 	struct rte_flow_action_vxlan_encap conf;
901 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
902 	struct rte_flow_item_eth item_eth;
903 	struct rte_flow_item_vlan item_vlan;
904 	union {
905 		struct rte_flow_item_ipv4 item_ipv4;
906 		struct rte_flow_item_ipv6 item_ipv6;
907 	};
908 	struct rte_flow_item_udp item_udp;
909 	struct rte_flow_item_vxlan item_vxlan;
910 };
911 
912 struct nvgre_encap_conf nvgre_encap_conf = {
913 	.select_ipv4 = 1,
914 	.select_vlan = 0,
915 	.tni = "\x00\x00\x00",
916 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
917 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
918 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
919 		"\x00\x00\x00\x00\x00\x00\x00\x01",
920 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
921 		"\x00\x00\x00\x00\x00\x00\x11\x11",
922 	.vlan_tci = 0,
923 	.eth_src = "\x00\x00\x00\x00\x00\x00",
924 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
925 };
926 
927 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
928 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
929 
930 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
931 struct action_nvgre_encap_data {
932 	struct rte_flow_action_nvgre_encap conf;
933 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
934 	struct rte_flow_item_eth item_eth;
935 	struct rte_flow_item_vlan item_vlan;
936 	union {
937 		struct rte_flow_item_ipv4 item_ipv4;
938 		struct rte_flow_item_ipv6 item_ipv6;
939 	};
940 	struct rte_flow_item_nvgre item_nvgre;
941 };
942 
943 struct l2_encap_conf l2_encap_conf;
944 
945 struct l2_decap_conf l2_decap_conf;
946 
947 struct mplsogre_encap_conf mplsogre_encap_conf;
948 
949 struct mplsogre_decap_conf mplsogre_decap_conf;
950 
951 struct mplsoudp_encap_conf mplsoudp_encap_conf;
952 
953 struct mplsoudp_decap_conf mplsoudp_decap_conf;
954 
955 struct rte_flow_action_conntrack conntrack_context;
956 
957 #define ACTION_SAMPLE_ACTIONS_NUM 10
958 #define RAW_SAMPLE_CONFS_MAX_NUM 8
959 /** Storage for struct rte_flow_action_sample including external data. */
960 struct action_sample_data {
961 	struct rte_flow_action_sample conf;
962 	uint32_t idx;
963 };
964 /** Storage for struct rte_flow_action_sample. */
965 struct raw_sample_conf {
966 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
967 };
968 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
969 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
970 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
971 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
972 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
973 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
974 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
975 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
976 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
977 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
978 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
979 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
980 
981 static const char *const modify_field_ops[] = {
982 	"set", "add", "sub", NULL
983 };
984 
985 static const char *const flow_field_ids[] = {
986 	"start", "mac_dst", "mac_src",
987 	"vlan_type", "vlan_id", "mac_type",
988 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
989 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
990 	"tcp_port_src", "tcp_port_dst",
991 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
992 	"udp_port_src", "udp_port_dst",
993 	"vxlan_vni", "geneve_vni", "gtp_teid",
994 	"tag", "mark", "meta", "pointer", "value",
995 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
996 	"ipv6_proto",
997 	"flex_item",
998 	"hash_result",
999 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1000 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1001 	"random",
1002 	NULL
1003 };
1004 
1005 static const char *const meter_colors[] = {
1006 	"green", "yellow", "red", "all", NULL
1007 };
1008 
1009 static const char *const table_insertion_types[] = {
1010 	"pattern", "index", NULL
1011 };
1012 
1013 static const char *const table_hash_funcs[] = {
1014 	"default", "linear", "crc32", "crc16", NULL
1015 };
1016 
1017 #define RAW_IPSEC_CONFS_MAX_NUM 8
1018 
1019 /** Maximum number of subsequent tokens and arguments on the stack. */
1020 #define CTX_STACK_SIZE 16
1021 
1022 /** Parser context. */
1023 struct context {
1024 	/** Stack of subsequent token lists to process. */
1025 	const enum index *next[CTX_STACK_SIZE];
1026 	/** Arguments for stacked tokens. */
1027 	const void *args[CTX_STACK_SIZE];
1028 	enum index curr; /**< Current token index. */
1029 	enum index prev; /**< Index of the last token seen. */
1030 	int next_num; /**< Number of entries in next[]. */
1031 	int args_num; /**< Number of entries in args[]. */
1032 	uint32_t eol:1; /**< EOL has been detected. */
1033 	uint32_t last:1; /**< No more arguments. */
1034 	portid_t port; /**< Current port ID (for completions). */
1035 	uint32_t objdata; /**< Object-specific data. */
1036 	void *object; /**< Address of current object for relative offsets. */
1037 	void *objmask; /**< Object a full mask must be written to. */
1038 };
1039 
1040 /** Token argument. */
1041 struct arg {
1042 	uint32_t hton:1; /**< Use network byte ordering. */
1043 	uint32_t sign:1; /**< Value is signed. */
1044 	uint32_t bounded:1; /**< Value is bounded. */
1045 	uintmax_t min; /**< Minimum value if bounded. */
1046 	uintmax_t max; /**< Maximum value if bounded. */
1047 	uint32_t offset; /**< Relative offset from ctx->object. */
1048 	uint32_t size; /**< Field size. */
1049 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1050 };
1051 
1052 /** Parser token definition. */
1053 struct token {
1054 	/** Type displayed during completion (defaults to "TOKEN"). */
1055 	const char *type;
1056 	/** Help displayed during completion (defaults to token name). */
1057 	const char *help;
1058 	/** Private data used by parser functions. */
1059 	const void *priv;
1060 	/**
1061 	 * Lists of subsequent tokens to push on the stack. Each call to the
1062 	 * parser consumes the last entry of that stack.
1063 	 */
1064 	const enum index *const *next;
1065 	/** Arguments stack for subsequent tokens that need them. */
1066 	const struct arg *const *args;
1067 	/**
1068 	 * Token-processing callback, returns -1 in case of error, the
1069 	 * length of the matched string otherwise. If NULL, attempts to
1070 	 * match the token name.
1071 	 *
1072 	 * If buf is not NULL, the result should be stored in it according
1073 	 * to context. An error is returned if not large enough.
1074 	 */
1075 	int (*call)(struct context *ctx, const struct token *token,
1076 		    const char *str, unsigned int len,
1077 		    void *buf, unsigned int size);
1078 	/**
1079 	 * Callback that provides possible values for this token, used for
1080 	 * completion. Returns -1 in case of error, the number of possible
1081 	 * values otherwise. If NULL, the token name is used.
1082 	 *
1083 	 * If buf is not NULL, entry index ent is written to buf and the
1084 	 * full length of the entry is returned (same behavior as
1085 	 * snprintf()).
1086 	 */
1087 	int (*comp)(struct context *ctx, const struct token *token,
1088 		    unsigned int ent, char *buf, unsigned int size);
1089 	/** Mandatory token name, no default value. */
1090 	const char *name;
1091 };
1092 
1093 /** Static initializer for the next field. */
1094 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1095 
1096 /** Static initializer for a NEXT() entry. */
1097 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1098 
1099 /** Static initializer for the args field. */
1100 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1101 
1102 /** Static initializer for ARGS() to target a field. */
1103 #define ARGS_ENTRY(s, f) \
1104 	(&(const struct arg){ \
1105 		.offset = offsetof(s, f), \
1106 		.size = sizeof(((s *)0)->f), \
1107 	})
1108 
1109 /** Static initializer for ARGS() to target a bit-field. */
1110 #define ARGS_ENTRY_BF(s, f, b) \
1111 	(&(const struct arg){ \
1112 		.size = sizeof(s), \
1113 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1114 	})
1115 
1116 /** Static initializer for ARGS() to target a field with limits. */
1117 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1118 	(&(const struct arg){ \
1119 		.bounded = 1, \
1120 		.min = (i), \
1121 		.max = (a), \
1122 		.offset = offsetof(s, f), \
1123 		.size = sizeof(((s *)0)->f), \
1124 	})
1125 
1126 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1127 #define ARGS_ENTRY_MASK(s, f, m) \
1128 	(&(const struct arg){ \
1129 		.offset = offsetof(s, f), \
1130 		.size = sizeof(((s *)0)->f), \
1131 		.mask = (const void *)(m), \
1132 	})
1133 
1134 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1135 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1136 	(&(const struct arg){ \
1137 		.hton = 1, \
1138 		.offset = offsetof(s, f), \
1139 		.size = sizeof(((s *)0)->f), \
1140 		.mask = (const void *)(m), \
1141 	})
1142 
1143 /** Static initializer for ARGS() to target a pointer. */
1144 #define ARGS_ENTRY_PTR(s, f) \
1145 	(&(const struct arg){ \
1146 		.size = sizeof(*((s *)0)->f), \
1147 	})
1148 
1149 /** Static initializer for ARGS() with arbitrary offset and size. */
1150 #define ARGS_ENTRY_ARB(o, s) \
1151 	(&(const struct arg){ \
1152 		.offset = (o), \
1153 		.size = (s), \
1154 	})
1155 
1156 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1157 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1158 	(&(const struct arg){ \
1159 		.bounded = 1, \
1160 		.min = (i), \
1161 		.max = (a), \
1162 		.offset = (o), \
1163 		.size = (s), \
1164 	})
1165 
1166 /** Same as ARGS_ENTRY() using network byte ordering. */
1167 #define ARGS_ENTRY_HTON(s, f) \
1168 	(&(const struct arg){ \
1169 		.hton = 1, \
1170 		.offset = offsetof(s, f), \
1171 		.size = sizeof(((s *)0)->f), \
1172 	})
1173 
1174 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1175 #define ARG_ENTRY_HTON(s) \
1176 	(&(const struct arg){ \
1177 		.hton = 1, \
1178 		.offset = 0, \
1179 		.size = sizeof(s), \
1180 	})
1181 
1182 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1183 struct buffer {
1184 	enum index command; /**< Flow command. */
1185 	portid_t port; /**< Affected port ID. */
1186 	queueid_t queue; /** Async queue ID. */
1187 	bool postpone; /** Postpone async operation */
1188 	union {
1189 		struct {
1190 			struct rte_flow_port_attr port_attr;
1191 			uint32_t nb_queue;
1192 			struct rte_flow_queue_attr queue_attr;
1193 		} configure; /**< Configuration arguments. */
1194 		struct {
1195 			uint32_t *template_id;
1196 			uint32_t template_id_n;
1197 		} templ_destroy; /**< Template destroy arguments. */
1198 		struct {
1199 			uint32_t id;
1200 			struct rte_flow_template_table_attr attr;
1201 			uint32_t *pat_templ_id;
1202 			uint32_t pat_templ_id_n;
1203 			uint32_t *act_templ_id;
1204 			uint32_t act_templ_id_n;
1205 		} table; /**< Table arguments. */
1206 		struct {
1207 			uint32_t *table_id;
1208 			uint32_t table_id_n;
1209 		} table_destroy; /**< Template destroy arguments. */
1210 		struct {
1211 			uint32_t *action_id;
1212 			uint32_t action_id_n;
1213 		} ia_destroy; /**< Indirect action destroy arguments. */
1214 		struct {
1215 			uint32_t action_id;
1216 			enum rte_flow_query_update_mode qu_mode;
1217 		} ia; /* Indirect action query arguments */
1218 		struct {
1219 			uint32_t table_id;
1220 			uint32_t pat_templ_id;
1221 			uint32_t rule_id;
1222 			uint32_t act_templ_id;
1223 			struct rte_flow_attr attr;
1224 			struct tunnel_ops tunnel_ops;
1225 			uintptr_t user_id;
1226 			struct rte_flow_item *pattern;
1227 			struct rte_flow_action *actions;
1228 			struct rte_flow_action *masks;
1229 			uint32_t pattern_n;
1230 			uint32_t actions_n;
1231 			uint8_t *data;
1232 			enum rte_flow_encap_hash_field field;
1233 			uint8_t encap_hash;
1234 		} vc; /**< Validate/create arguments. */
1235 		struct {
1236 			uint64_t *rule;
1237 			uint64_t rule_n;
1238 			bool is_user_id;
1239 		} destroy; /**< Destroy arguments. */
1240 		struct {
1241 			char file[128];
1242 			bool mode;
1243 			uint64_t rule;
1244 			bool is_user_id;
1245 		} dump; /**< Dump arguments. */
1246 		struct {
1247 			uint64_t rule;
1248 			struct rte_flow_action action;
1249 			bool is_user_id;
1250 		} query; /**< Query arguments. */
1251 		struct {
1252 			uint32_t *group;
1253 			uint32_t group_n;
1254 		} list; /**< List arguments. */
1255 		struct {
1256 			int set;
1257 		} isolate; /**< Isolated mode arguments. */
1258 		struct {
1259 			int destroy;
1260 		} aged; /**< Aged arguments. */
1261 		struct {
1262 			uint32_t policy_id;
1263 		} policy;/**< Policy arguments. */
1264 		struct {
1265 			uint16_t token;
1266 			uintptr_t uintptr;
1267 			char filename[128];
1268 		} flex; /**< Flex arguments*/
1269 	} args; /**< Command arguments. */
1270 };
1271 
1272 /** Private data for pattern items. */
1273 struct parse_item_priv {
1274 	enum rte_flow_item_type type; /**< Item type. */
1275 	uint32_t size; /**< Size of item specification structure. */
1276 };
1277 
1278 #define PRIV_ITEM(t, s) \
1279 	(&(const struct parse_item_priv){ \
1280 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1281 		.size = s, \
1282 	})
1283 
1284 /** Private data for actions. */
1285 struct parse_action_priv {
1286 	enum rte_flow_action_type type; /**< Action type. */
1287 	uint32_t size; /**< Size of action configuration structure. */
1288 };
1289 
1290 #define PRIV_ACTION(t, s) \
1291 	(&(const struct parse_action_priv){ \
1292 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1293 		.size = s, \
1294 	})
1295 
1296 static const enum index next_flex_item[] = {
1297 	FLEX_ITEM_INIT,
1298 	FLEX_ITEM_CREATE,
1299 	FLEX_ITEM_DESTROY,
1300 	ZERO,
1301 };
1302 
1303 static const enum index next_config_attr[] = {
1304 	CONFIG_QUEUES_NUMBER,
1305 	CONFIG_QUEUES_SIZE,
1306 	CONFIG_COUNTERS_NUMBER,
1307 	CONFIG_AGING_OBJECTS_NUMBER,
1308 	CONFIG_METERS_NUMBER,
1309 	CONFIG_CONN_TRACK_NUMBER,
1310 	CONFIG_QUOTAS_NUMBER,
1311 	CONFIG_FLAGS,
1312 	CONFIG_HOST_PORT,
1313 	END,
1314 	ZERO,
1315 };
1316 
1317 static const enum index next_pt_subcmd[] = {
1318 	PATTERN_TEMPLATE_CREATE,
1319 	PATTERN_TEMPLATE_DESTROY,
1320 	ZERO,
1321 };
1322 
1323 static const enum index next_pt_attr[] = {
1324 	PATTERN_TEMPLATE_CREATE_ID,
1325 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1326 	PATTERN_TEMPLATE_INGRESS,
1327 	PATTERN_TEMPLATE_EGRESS,
1328 	PATTERN_TEMPLATE_TRANSFER,
1329 	PATTERN_TEMPLATE_SPEC,
1330 	ZERO,
1331 };
1332 
1333 static const enum index next_pt_destroy_attr[] = {
1334 	PATTERN_TEMPLATE_DESTROY_ID,
1335 	END,
1336 	ZERO,
1337 };
1338 
1339 static const enum index next_at_subcmd[] = {
1340 	ACTIONS_TEMPLATE_CREATE,
1341 	ACTIONS_TEMPLATE_DESTROY,
1342 	ZERO,
1343 };
1344 
1345 static const enum index next_at_attr[] = {
1346 	ACTIONS_TEMPLATE_CREATE_ID,
1347 	ACTIONS_TEMPLATE_INGRESS,
1348 	ACTIONS_TEMPLATE_EGRESS,
1349 	ACTIONS_TEMPLATE_TRANSFER,
1350 	ACTIONS_TEMPLATE_SPEC,
1351 	ZERO,
1352 };
1353 
1354 static const enum index next_at_destroy_attr[] = {
1355 	ACTIONS_TEMPLATE_DESTROY_ID,
1356 	END,
1357 	ZERO,
1358 };
1359 
1360 static const enum index next_group_attr[] = {
1361 	GROUP_INGRESS,
1362 	GROUP_EGRESS,
1363 	GROUP_TRANSFER,
1364 	GROUP_SET_MISS_ACTIONS,
1365 	ZERO,
1366 };
1367 
1368 static const enum index next_table_subcmd[] = {
1369 	TABLE_CREATE,
1370 	TABLE_DESTROY,
1371 	TABLE_RESIZE,
1372 	TABLE_RESIZE_COMPLETE,
1373 	ZERO,
1374 };
1375 
1376 static const enum index next_table_attr[] = {
1377 	TABLE_CREATE_ID,
1378 	TABLE_GROUP,
1379 	TABLE_INSERTION_TYPE,
1380 	TABLE_HASH_FUNC,
1381 	TABLE_PRIORITY,
1382 	TABLE_INGRESS,
1383 	TABLE_EGRESS,
1384 	TABLE_TRANSFER,
1385 	TABLE_TRANSFER_WIRE_ORIG,
1386 	TABLE_TRANSFER_VPORT_ORIG,
1387 	TABLE_RESIZABLE,
1388 	TABLE_RULES_NUMBER,
1389 	TABLE_PATTERN_TEMPLATE,
1390 	TABLE_ACTIONS_TEMPLATE,
1391 	END,
1392 	ZERO,
1393 };
1394 
1395 static const enum index next_table_destroy_attr[] = {
1396 	TABLE_DESTROY_ID,
1397 	END,
1398 	ZERO,
1399 };
1400 
1401 static const enum index next_queue_subcmd[] = {
1402 	QUEUE_CREATE,
1403 	QUEUE_DESTROY,
1404 	QUEUE_FLOW_UPDATE_RESIZED,
1405 	QUEUE_UPDATE,
1406 	QUEUE_AGED,
1407 	QUEUE_INDIRECT_ACTION,
1408 	ZERO,
1409 };
1410 
1411 static const enum index next_queue_destroy_attr[] = {
1412 	QUEUE_DESTROY_ID,
1413 	END,
1414 	ZERO,
1415 };
1416 
1417 static const enum index next_qia_subcmd[] = {
1418 	QUEUE_INDIRECT_ACTION_CREATE,
1419 	QUEUE_INDIRECT_ACTION_UPDATE,
1420 	QUEUE_INDIRECT_ACTION_DESTROY,
1421 	QUEUE_INDIRECT_ACTION_QUERY,
1422 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1423 	ZERO,
1424 };
1425 
1426 static const enum index next_qia_create_attr[] = {
1427 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1428 	QUEUE_INDIRECT_ACTION_INGRESS,
1429 	QUEUE_INDIRECT_ACTION_EGRESS,
1430 	QUEUE_INDIRECT_ACTION_TRANSFER,
1431 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1432 	QUEUE_INDIRECT_ACTION_SPEC,
1433 	QUEUE_INDIRECT_ACTION_LIST,
1434 	ZERO,
1435 };
1436 
1437 static const enum index next_qia_update_attr[] = {
1438 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1439 	QUEUE_INDIRECT_ACTION_SPEC,
1440 	ZERO,
1441 };
1442 
1443 static const enum index next_qia_destroy_attr[] = {
1444 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1445 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1446 	END,
1447 	ZERO,
1448 };
1449 
1450 static const enum index next_qia_query_attr[] = {
1451 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1452 	END,
1453 	ZERO,
1454 };
1455 
1456 static const enum index next_ia_create_attr[] = {
1457 	INDIRECT_ACTION_CREATE_ID,
1458 	INDIRECT_ACTION_INGRESS,
1459 	INDIRECT_ACTION_EGRESS,
1460 	INDIRECT_ACTION_TRANSFER,
1461 	INDIRECT_ACTION_SPEC,
1462 	INDIRECT_ACTION_LIST,
1463 	INDIRECT_ACTION_FLOW_CONF,
1464 	ZERO,
1465 };
1466 
1467 static const enum index next_ia[] = {
1468 	INDIRECT_ACTION_ID2PTR,
1469 	ACTION_NEXT,
1470 	ZERO
1471 };
1472 
1473 static const enum index next_ial[] = {
1474 	ACTION_INDIRECT_LIST_HANDLE,
1475 	ACTION_INDIRECT_LIST_CONF,
1476 	ACTION_NEXT,
1477 	ZERO
1478 };
1479 
1480 static const enum index next_qia_qu_attr[] = {
1481 	QUEUE_INDIRECT_ACTION_QU_MODE,
1482 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1483 	INDIRECT_ACTION_SPEC,
1484 	ZERO
1485 };
1486 
1487 static const enum index next_ia_qu_attr[] = {
1488 	INDIRECT_ACTION_QU_MODE,
1489 	INDIRECT_ACTION_SPEC,
1490 	ZERO
1491 };
1492 
1493 static const enum index next_dump_subcmd[] = {
1494 	DUMP_ALL,
1495 	DUMP_ONE,
1496 	DUMP_IS_USER_ID,
1497 	ZERO,
1498 };
1499 
1500 static const enum index next_ia_subcmd[] = {
1501 	INDIRECT_ACTION_CREATE,
1502 	INDIRECT_ACTION_UPDATE,
1503 	INDIRECT_ACTION_DESTROY,
1504 	INDIRECT_ACTION_QUERY,
1505 	INDIRECT_ACTION_QUERY_UPDATE,
1506 	ZERO,
1507 };
1508 
1509 static const enum index next_vc_attr[] = {
1510 	VC_GROUP,
1511 	VC_PRIORITY,
1512 	VC_INGRESS,
1513 	VC_EGRESS,
1514 	VC_TRANSFER,
1515 	VC_TUNNEL_SET,
1516 	VC_TUNNEL_MATCH,
1517 	VC_USER_ID,
1518 	ITEM_PATTERN,
1519 	ZERO,
1520 };
1521 
1522 static const enum index next_destroy_attr[] = {
1523 	DESTROY_RULE,
1524 	DESTROY_IS_USER_ID,
1525 	END,
1526 	ZERO,
1527 };
1528 
1529 static const enum index next_dump_attr[] = {
1530 	COMMON_FILE_PATH,
1531 	END,
1532 	ZERO,
1533 };
1534 
1535 static const enum index next_query_attr[] = {
1536 	QUERY_IS_USER_ID,
1537 	END,
1538 	ZERO,
1539 };
1540 
1541 static const enum index next_list_attr[] = {
1542 	LIST_GROUP,
1543 	END,
1544 	ZERO,
1545 };
1546 
1547 static const enum index next_aged_attr[] = {
1548 	AGED_DESTROY,
1549 	END,
1550 	ZERO,
1551 };
1552 
1553 static const enum index next_ia_destroy_attr[] = {
1554 	INDIRECT_ACTION_DESTROY_ID,
1555 	END,
1556 	ZERO,
1557 };
1558 
1559 static const enum index next_async_insert_subcmd[] = {
1560 	QUEUE_PATTERN_TEMPLATE,
1561 	QUEUE_RULE_ID,
1562 	ZERO,
1563 };
1564 
1565 static const enum index item_param[] = {
1566 	ITEM_PARAM_IS,
1567 	ITEM_PARAM_SPEC,
1568 	ITEM_PARAM_LAST,
1569 	ITEM_PARAM_MASK,
1570 	ITEM_PARAM_PREFIX,
1571 	ZERO,
1572 };
1573 
1574 static const enum index next_item[] = {
1575 	ITEM_END,
1576 	ITEM_VOID,
1577 	ITEM_INVERT,
1578 	ITEM_ANY,
1579 	ITEM_PORT_ID,
1580 	ITEM_MARK,
1581 	ITEM_RAW,
1582 	ITEM_ETH,
1583 	ITEM_VLAN,
1584 	ITEM_IPV4,
1585 	ITEM_IPV6,
1586 	ITEM_ICMP,
1587 	ITEM_UDP,
1588 	ITEM_TCP,
1589 	ITEM_SCTP,
1590 	ITEM_VXLAN,
1591 	ITEM_E_TAG,
1592 	ITEM_NVGRE,
1593 	ITEM_MPLS,
1594 	ITEM_GRE,
1595 	ITEM_FUZZY,
1596 	ITEM_GTP,
1597 	ITEM_GTPC,
1598 	ITEM_GTPU,
1599 	ITEM_GENEVE,
1600 	ITEM_VXLAN_GPE,
1601 	ITEM_ARP_ETH_IPV4,
1602 	ITEM_IPV6_EXT,
1603 	ITEM_IPV6_FRAG_EXT,
1604 	ITEM_IPV6_ROUTING_EXT,
1605 	ITEM_ICMP6,
1606 	ITEM_ICMP6_ECHO_REQUEST,
1607 	ITEM_ICMP6_ECHO_REPLY,
1608 	ITEM_ICMP6_ND_NS,
1609 	ITEM_ICMP6_ND_NA,
1610 	ITEM_ICMP6_ND_OPT,
1611 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1612 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1613 	ITEM_META,
1614 	ITEM_RANDOM,
1615 	ITEM_GRE_KEY,
1616 	ITEM_GRE_OPTION,
1617 	ITEM_GTP_PSC,
1618 	ITEM_PPPOES,
1619 	ITEM_PPPOED,
1620 	ITEM_PPPOE_PROTO_ID,
1621 	ITEM_HIGIG2,
1622 	ITEM_TAG,
1623 	ITEM_L2TPV3OIP,
1624 	ITEM_ESP,
1625 	ITEM_AH,
1626 	ITEM_PFCP,
1627 	ITEM_ECPRI,
1628 	ITEM_GENEVE_OPT,
1629 	ITEM_INTEGRITY,
1630 	ITEM_CONNTRACK,
1631 	ITEM_PORT_REPRESENTOR,
1632 	ITEM_REPRESENTED_PORT,
1633 	ITEM_FLEX,
1634 	ITEM_L2TPV2,
1635 	ITEM_PPP,
1636 	ITEM_METER,
1637 	ITEM_QUOTA,
1638 	ITEM_AGGR_AFFINITY,
1639 	ITEM_TX_QUEUE,
1640 	ITEM_IB_BTH,
1641 	ITEM_PTYPE,
1642 	ITEM_NSH,
1643 	ITEM_COMPARE,
1644 	END_SET,
1645 	ZERO,
1646 };
1647 
1648 static const enum index item_fuzzy[] = {
1649 	ITEM_FUZZY_THRESH,
1650 	ITEM_NEXT,
1651 	ZERO,
1652 };
1653 
1654 static const enum index item_any[] = {
1655 	ITEM_ANY_NUM,
1656 	ITEM_NEXT,
1657 	ZERO,
1658 };
1659 
1660 static const enum index item_port_id[] = {
1661 	ITEM_PORT_ID_ID,
1662 	ITEM_NEXT,
1663 	ZERO,
1664 };
1665 
1666 static const enum index item_mark[] = {
1667 	ITEM_MARK_ID,
1668 	ITEM_NEXT,
1669 	ZERO,
1670 };
1671 
1672 static const enum index item_raw[] = {
1673 	ITEM_RAW_RELATIVE,
1674 	ITEM_RAW_SEARCH,
1675 	ITEM_RAW_OFFSET,
1676 	ITEM_RAW_LIMIT,
1677 	ITEM_RAW_PATTERN,
1678 	ITEM_RAW_PATTERN_HEX,
1679 	ITEM_NEXT,
1680 	ZERO,
1681 };
1682 
1683 static const enum index item_eth[] = {
1684 	ITEM_ETH_DST,
1685 	ITEM_ETH_SRC,
1686 	ITEM_ETH_TYPE,
1687 	ITEM_ETH_HAS_VLAN,
1688 	ITEM_NEXT,
1689 	ZERO,
1690 };
1691 
1692 static const enum index item_vlan[] = {
1693 	ITEM_VLAN_TCI,
1694 	ITEM_VLAN_PCP,
1695 	ITEM_VLAN_DEI,
1696 	ITEM_VLAN_VID,
1697 	ITEM_VLAN_INNER_TYPE,
1698 	ITEM_VLAN_HAS_MORE_VLAN,
1699 	ITEM_NEXT,
1700 	ZERO,
1701 };
1702 
1703 static const enum index item_ipv4[] = {
1704 	ITEM_IPV4_VER_IHL,
1705 	ITEM_IPV4_TOS,
1706 	ITEM_IPV4_LENGTH,
1707 	ITEM_IPV4_ID,
1708 	ITEM_IPV4_FRAGMENT_OFFSET,
1709 	ITEM_IPV4_TTL,
1710 	ITEM_IPV4_PROTO,
1711 	ITEM_IPV4_SRC,
1712 	ITEM_IPV4_DST,
1713 	ITEM_NEXT,
1714 	ZERO,
1715 };
1716 
1717 static const enum index item_ipv6[] = {
1718 	ITEM_IPV6_TC,
1719 	ITEM_IPV6_FLOW,
1720 	ITEM_IPV6_LEN,
1721 	ITEM_IPV6_PROTO,
1722 	ITEM_IPV6_HOP,
1723 	ITEM_IPV6_SRC,
1724 	ITEM_IPV6_DST,
1725 	ITEM_IPV6_HAS_FRAG_EXT,
1726 	ITEM_IPV6_ROUTING_EXT,
1727 	ITEM_NEXT,
1728 	ZERO,
1729 };
1730 
1731 static const enum index item_ipv6_routing_ext[] = {
1732 	ITEM_IPV6_ROUTING_EXT_TYPE,
1733 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1734 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1735 	ITEM_NEXT,
1736 	ZERO,
1737 };
1738 
1739 static const enum index item_icmp[] = {
1740 	ITEM_ICMP_TYPE,
1741 	ITEM_ICMP_CODE,
1742 	ITEM_ICMP_IDENT,
1743 	ITEM_ICMP_SEQ,
1744 	ITEM_NEXT,
1745 	ZERO,
1746 };
1747 
1748 static const enum index item_udp[] = {
1749 	ITEM_UDP_SRC,
1750 	ITEM_UDP_DST,
1751 	ITEM_NEXT,
1752 	ZERO,
1753 };
1754 
1755 static const enum index item_tcp[] = {
1756 	ITEM_TCP_SRC,
1757 	ITEM_TCP_DST,
1758 	ITEM_TCP_FLAGS,
1759 	ITEM_NEXT,
1760 	ZERO,
1761 };
1762 
1763 static const enum index item_sctp[] = {
1764 	ITEM_SCTP_SRC,
1765 	ITEM_SCTP_DST,
1766 	ITEM_SCTP_TAG,
1767 	ITEM_SCTP_CKSUM,
1768 	ITEM_NEXT,
1769 	ZERO,
1770 };
1771 
1772 static const enum index item_vxlan[] = {
1773 	ITEM_VXLAN_VNI,
1774 	ITEM_VXLAN_LAST_RSVD,
1775 	ITEM_NEXT,
1776 	ZERO,
1777 };
1778 
1779 static const enum index item_e_tag[] = {
1780 	ITEM_E_TAG_GRP_ECID_B,
1781 	ITEM_NEXT,
1782 	ZERO,
1783 };
1784 
1785 static const enum index item_nvgre[] = {
1786 	ITEM_NVGRE_TNI,
1787 	ITEM_NEXT,
1788 	ZERO,
1789 };
1790 
1791 static const enum index item_mpls[] = {
1792 	ITEM_MPLS_LABEL,
1793 	ITEM_MPLS_TC,
1794 	ITEM_MPLS_S,
1795 	ITEM_MPLS_TTL,
1796 	ITEM_NEXT,
1797 	ZERO,
1798 };
1799 
1800 static const enum index item_gre[] = {
1801 	ITEM_GRE_PROTO,
1802 	ITEM_GRE_C_RSVD0_VER,
1803 	ITEM_GRE_C_BIT,
1804 	ITEM_GRE_K_BIT,
1805 	ITEM_GRE_S_BIT,
1806 	ITEM_NEXT,
1807 	ZERO,
1808 };
1809 
1810 static const enum index item_gre_key[] = {
1811 	ITEM_GRE_KEY_VALUE,
1812 	ITEM_NEXT,
1813 	ZERO,
1814 };
1815 
1816 static const enum index item_gre_option[] = {
1817 	ITEM_GRE_OPTION_CHECKSUM,
1818 	ITEM_GRE_OPTION_KEY,
1819 	ITEM_GRE_OPTION_SEQUENCE,
1820 	ITEM_NEXT,
1821 	ZERO,
1822 };
1823 
1824 static const enum index item_gtp[] = {
1825 	ITEM_GTP_FLAGS,
1826 	ITEM_GTP_MSG_TYPE,
1827 	ITEM_GTP_TEID,
1828 	ITEM_NEXT,
1829 	ZERO,
1830 };
1831 
1832 static const enum index item_geneve[] = {
1833 	ITEM_GENEVE_VNI,
1834 	ITEM_GENEVE_PROTO,
1835 	ITEM_GENEVE_OPTLEN,
1836 	ITEM_NEXT,
1837 	ZERO,
1838 };
1839 
1840 static const enum index item_vxlan_gpe[] = {
1841 	ITEM_VXLAN_GPE_VNI,
1842 	ITEM_VXLAN_GPE_PROTO,
1843 	ITEM_VXLAN_GPE_FLAGS,
1844 	ITEM_NEXT,
1845 	ZERO,
1846 };
1847 
1848 static const enum index item_arp_eth_ipv4[] = {
1849 	ITEM_ARP_ETH_IPV4_SHA,
1850 	ITEM_ARP_ETH_IPV4_SPA,
1851 	ITEM_ARP_ETH_IPV4_THA,
1852 	ITEM_ARP_ETH_IPV4_TPA,
1853 	ITEM_NEXT,
1854 	ZERO,
1855 };
1856 
1857 static const enum index item_ipv6_ext[] = {
1858 	ITEM_IPV6_EXT_NEXT_HDR,
1859 	ITEM_NEXT,
1860 	ZERO,
1861 };
1862 
1863 static const enum index item_ipv6_frag_ext[] = {
1864 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1865 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1866 	ITEM_IPV6_FRAG_EXT_ID,
1867 	ITEM_NEXT,
1868 	ZERO,
1869 };
1870 
1871 static const enum index item_icmp6[] = {
1872 	ITEM_ICMP6_TYPE,
1873 	ITEM_ICMP6_CODE,
1874 	ITEM_NEXT,
1875 	ZERO,
1876 };
1877 
1878 static const enum index item_icmp6_echo_request[] = {
1879 	ITEM_ICMP6_ECHO_REQUEST_ID,
1880 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1881 	ITEM_NEXT,
1882 	ZERO,
1883 };
1884 
1885 static const enum index item_icmp6_echo_reply[] = {
1886 	ITEM_ICMP6_ECHO_REPLY_ID,
1887 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1888 	ITEM_NEXT,
1889 	ZERO,
1890 };
1891 
1892 static const enum index item_icmp6_nd_ns[] = {
1893 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1894 	ITEM_NEXT,
1895 	ZERO,
1896 };
1897 
1898 static const enum index item_icmp6_nd_na[] = {
1899 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1900 	ITEM_NEXT,
1901 	ZERO,
1902 };
1903 
1904 static const enum index item_icmp6_nd_opt[] = {
1905 	ITEM_ICMP6_ND_OPT_TYPE,
1906 	ITEM_NEXT,
1907 	ZERO,
1908 };
1909 
1910 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1911 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1912 	ITEM_NEXT,
1913 	ZERO,
1914 };
1915 
1916 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1917 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1918 	ITEM_NEXT,
1919 	ZERO,
1920 };
1921 
1922 static const enum index item_meta[] = {
1923 	ITEM_META_DATA,
1924 	ITEM_NEXT,
1925 	ZERO,
1926 };
1927 
1928 static const enum index item_random[] = {
1929 	ITEM_RANDOM_VALUE,
1930 	ITEM_NEXT,
1931 	ZERO,
1932 };
1933 
1934 static const enum index item_gtp_psc[] = {
1935 	ITEM_GTP_PSC_QFI,
1936 	ITEM_GTP_PSC_PDU_T,
1937 	ITEM_NEXT,
1938 	ZERO,
1939 };
1940 
1941 static const enum index item_pppoed[] = {
1942 	ITEM_PPPOE_SEID,
1943 	ITEM_NEXT,
1944 	ZERO,
1945 };
1946 
1947 static const enum index item_pppoes[] = {
1948 	ITEM_PPPOE_SEID,
1949 	ITEM_NEXT,
1950 	ZERO,
1951 };
1952 
1953 static const enum index item_pppoe_proto_id[] = {
1954 	ITEM_NEXT,
1955 	ZERO,
1956 };
1957 
1958 static const enum index item_higig2[] = {
1959 	ITEM_HIGIG2_CLASSIFICATION,
1960 	ITEM_HIGIG2_VID,
1961 	ITEM_NEXT,
1962 	ZERO,
1963 };
1964 
1965 static const enum index item_esp[] = {
1966 	ITEM_ESP_SPI,
1967 	ITEM_NEXT,
1968 	ZERO,
1969 };
1970 
1971 static const enum index item_ah[] = {
1972 	ITEM_AH_SPI,
1973 	ITEM_NEXT,
1974 	ZERO,
1975 };
1976 
1977 static const enum index item_pfcp[] = {
1978 	ITEM_PFCP_S_FIELD,
1979 	ITEM_PFCP_SEID,
1980 	ITEM_NEXT,
1981 	ZERO,
1982 };
1983 
1984 static const enum index next_set_raw[] = {
1985 	SET_RAW_INDEX,
1986 	ITEM_ETH,
1987 	ZERO,
1988 };
1989 
1990 static const enum index item_tag[] = {
1991 	ITEM_TAG_DATA,
1992 	ITEM_TAG_INDEX,
1993 	ITEM_NEXT,
1994 	ZERO,
1995 };
1996 
1997 static const enum index item_l2tpv3oip[] = {
1998 	ITEM_L2TPV3OIP_SESSION_ID,
1999 	ITEM_NEXT,
2000 	ZERO,
2001 };
2002 
2003 static const enum index item_ecpri[] = {
2004 	ITEM_ECPRI_COMMON,
2005 	ITEM_NEXT,
2006 	ZERO,
2007 };
2008 
2009 static const enum index item_ecpri_common[] = {
2010 	ITEM_ECPRI_COMMON_TYPE,
2011 	ZERO,
2012 };
2013 
2014 static const enum index item_ecpri_common_type[] = {
2015 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2016 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2017 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2018 	ZERO,
2019 };
2020 
2021 static const enum index item_geneve_opt[] = {
2022 	ITEM_GENEVE_OPT_CLASS,
2023 	ITEM_GENEVE_OPT_TYPE,
2024 	ITEM_GENEVE_OPT_LENGTH,
2025 	ITEM_GENEVE_OPT_DATA,
2026 	ITEM_NEXT,
2027 	ZERO,
2028 };
2029 
2030 static const enum index item_integrity[] = {
2031 	ITEM_INTEGRITY_LEVEL,
2032 	ITEM_INTEGRITY_VALUE,
2033 	ZERO,
2034 };
2035 
2036 static const enum index item_integrity_lv[] = {
2037 	ITEM_INTEGRITY_LEVEL,
2038 	ITEM_INTEGRITY_VALUE,
2039 	ITEM_NEXT,
2040 	ZERO,
2041 };
2042 
2043 static const enum index item_port_representor[] = {
2044 	ITEM_PORT_REPRESENTOR_PORT_ID,
2045 	ITEM_NEXT,
2046 	ZERO,
2047 };
2048 
2049 static const enum index item_represented_port[] = {
2050 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2051 	ITEM_NEXT,
2052 	ZERO,
2053 };
2054 
2055 static const enum index item_flex[] = {
2056 	ITEM_FLEX_PATTERN_HANDLE,
2057 	ITEM_FLEX_ITEM_HANDLE,
2058 	ITEM_NEXT,
2059 	ZERO,
2060 };
2061 
2062 static const enum index item_l2tpv2[] = {
2063 	ITEM_L2TPV2_TYPE,
2064 	ITEM_NEXT,
2065 	ZERO,
2066 };
2067 
2068 static const enum index item_l2tpv2_type[] = {
2069 	ITEM_L2TPV2_TYPE_DATA,
2070 	ITEM_L2TPV2_TYPE_DATA_L,
2071 	ITEM_L2TPV2_TYPE_DATA_S,
2072 	ITEM_L2TPV2_TYPE_DATA_O,
2073 	ITEM_L2TPV2_TYPE_DATA_L_S,
2074 	ITEM_L2TPV2_TYPE_CTRL,
2075 	ZERO,
2076 };
2077 
2078 static const enum index item_l2tpv2_type_data[] = {
2079 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2080 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2081 	ITEM_NEXT,
2082 	ZERO,
2083 };
2084 
2085 static const enum index item_l2tpv2_type_data_l[] = {
2086 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2087 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2088 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2089 	ITEM_NEXT,
2090 	ZERO,
2091 };
2092 
2093 static const enum index item_l2tpv2_type_data_s[] = {
2094 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2095 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2096 	ITEM_L2TPV2_MSG_DATA_S_NS,
2097 	ITEM_L2TPV2_MSG_DATA_S_NR,
2098 	ITEM_NEXT,
2099 	ZERO,
2100 };
2101 
2102 static const enum index item_l2tpv2_type_data_o[] = {
2103 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2104 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2105 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2106 	ITEM_NEXT,
2107 	ZERO,
2108 };
2109 
2110 static const enum index item_l2tpv2_type_data_l_s[] = {
2111 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2112 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2113 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2114 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2115 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2116 	ITEM_NEXT,
2117 	ZERO,
2118 };
2119 
2120 static const enum index item_l2tpv2_type_ctrl[] = {
2121 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2122 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2123 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2124 	ITEM_L2TPV2_MSG_CTRL_NS,
2125 	ITEM_L2TPV2_MSG_CTRL_NR,
2126 	ITEM_NEXT,
2127 	ZERO,
2128 };
2129 
2130 static const enum index item_ppp[] = {
2131 	ITEM_PPP_ADDR,
2132 	ITEM_PPP_CTRL,
2133 	ITEM_PPP_PROTO_ID,
2134 	ITEM_NEXT,
2135 	ZERO,
2136 };
2137 
2138 static const enum index item_meter[] = {
2139 	ITEM_METER_COLOR,
2140 	ITEM_NEXT,
2141 	ZERO,
2142 };
2143 
2144 static const enum index item_quota[] = {
2145 	ITEM_QUOTA_STATE,
2146 	ITEM_NEXT,
2147 	ZERO,
2148 };
2149 
2150 static const enum index item_aggr_affinity[] = {
2151 	ITEM_AGGR_AFFINITY_VALUE,
2152 	ITEM_NEXT,
2153 	ZERO,
2154 };
2155 
2156 static const enum index item_tx_queue[] = {
2157 	ITEM_TX_QUEUE_VALUE,
2158 	ITEM_NEXT,
2159 	ZERO,
2160 };
2161 
2162 static const enum index item_ib_bth[] = {
2163 	ITEM_IB_BTH_OPCODE,
2164 	ITEM_IB_BTH_PKEY,
2165 	ITEM_IB_BTH_DST_QPN,
2166 	ITEM_IB_BTH_PSN,
2167 	ITEM_NEXT,
2168 	ZERO,
2169 };
2170 
2171 static const enum index item_ptype[] = {
2172 	ITEM_PTYPE_VALUE,
2173 	ITEM_NEXT,
2174 	ZERO,
2175 };
2176 
2177 static const enum index item_nsh[] = {
2178 	ITEM_NEXT,
2179 	ZERO,
2180 };
2181 
2182 static const enum index item_compare_field[] = {
2183 	ITEM_COMPARE_OP,
2184 	ITEM_COMPARE_FIELD_A_TYPE,
2185 	ITEM_COMPARE_FIELD_B_TYPE,
2186 	ITEM_NEXT,
2187 	ZERO,
2188 };
2189 
2190 static const enum index compare_field_a[] = {
2191 	ITEM_COMPARE_FIELD_A_TYPE,
2192 	ITEM_COMPARE_FIELD_A_LEVEL,
2193 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2194 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2195 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2196 	ITEM_COMPARE_FIELD_A_OFFSET,
2197 	ITEM_COMPARE_FIELD_B_TYPE,
2198 	ZERO,
2199 };
2200 
2201 static const enum index compare_field_b[] = {
2202 	ITEM_COMPARE_FIELD_B_TYPE,
2203 	ITEM_COMPARE_FIELD_B_LEVEL,
2204 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2205 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2206 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2207 	ITEM_COMPARE_FIELD_B_OFFSET,
2208 	ITEM_COMPARE_FIELD_B_VALUE,
2209 	ITEM_COMPARE_FIELD_B_POINTER,
2210 	ITEM_COMPARE_FIELD_WIDTH,
2211 	ZERO,
2212 };
2213 
2214 static const enum index next_action[] = {
2215 	ACTION_END,
2216 	ACTION_VOID,
2217 	ACTION_PASSTHRU,
2218 	ACTION_SKIP_CMAN,
2219 	ACTION_JUMP,
2220 	ACTION_MARK,
2221 	ACTION_FLAG,
2222 	ACTION_QUEUE,
2223 	ACTION_DROP,
2224 	ACTION_COUNT,
2225 	ACTION_RSS,
2226 	ACTION_PF,
2227 	ACTION_VF,
2228 	ACTION_PORT_ID,
2229 	ACTION_METER,
2230 	ACTION_METER_COLOR,
2231 	ACTION_METER_MARK,
2232 	ACTION_OF_DEC_NW_TTL,
2233 	ACTION_OF_POP_VLAN,
2234 	ACTION_OF_PUSH_VLAN,
2235 	ACTION_OF_SET_VLAN_VID,
2236 	ACTION_OF_SET_VLAN_PCP,
2237 	ACTION_OF_POP_MPLS,
2238 	ACTION_OF_PUSH_MPLS,
2239 	ACTION_VXLAN_ENCAP,
2240 	ACTION_VXLAN_DECAP,
2241 	ACTION_NVGRE_ENCAP,
2242 	ACTION_NVGRE_DECAP,
2243 	ACTION_L2_ENCAP,
2244 	ACTION_L2_DECAP,
2245 	ACTION_MPLSOGRE_ENCAP,
2246 	ACTION_MPLSOGRE_DECAP,
2247 	ACTION_MPLSOUDP_ENCAP,
2248 	ACTION_MPLSOUDP_DECAP,
2249 	ACTION_SET_IPV4_SRC,
2250 	ACTION_SET_IPV4_DST,
2251 	ACTION_SET_IPV6_SRC,
2252 	ACTION_SET_IPV6_DST,
2253 	ACTION_SET_TP_SRC,
2254 	ACTION_SET_TP_DST,
2255 	ACTION_MAC_SWAP,
2256 	ACTION_DEC_TTL,
2257 	ACTION_SET_TTL,
2258 	ACTION_SET_MAC_SRC,
2259 	ACTION_SET_MAC_DST,
2260 	ACTION_INC_TCP_SEQ,
2261 	ACTION_DEC_TCP_SEQ,
2262 	ACTION_INC_TCP_ACK,
2263 	ACTION_DEC_TCP_ACK,
2264 	ACTION_RAW_ENCAP,
2265 	ACTION_RAW_DECAP,
2266 	ACTION_SET_TAG,
2267 	ACTION_SET_META,
2268 	ACTION_SET_IPV4_DSCP,
2269 	ACTION_SET_IPV6_DSCP,
2270 	ACTION_AGE,
2271 	ACTION_AGE_UPDATE,
2272 	ACTION_SAMPLE,
2273 	ACTION_INDIRECT,
2274 	ACTION_INDIRECT_LIST,
2275 	ACTION_SHARED_INDIRECT,
2276 	ACTION_MODIFY_FIELD,
2277 	ACTION_CONNTRACK,
2278 	ACTION_CONNTRACK_UPDATE,
2279 	ACTION_PORT_REPRESENTOR,
2280 	ACTION_REPRESENTED_PORT,
2281 	ACTION_SEND_TO_KERNEL,
2282 	ACTION_QUOTA_CREATE,
2283 	ACTION_QUOTA_QU,
2284 	ACTION_IPV6_EXT_REMOVE,
2285 	ACTION_IPV6_EXT_PUSH,
2286 	ACTION_NAT64,
2287 	ZERO,
2288 };
2289 
2290 static const enum index action_quota_create[] = {
2291 	ACTION_QUOTA_CREATE_LIMIT,
2292 	ACTION_QUOTA_CREATE_MODE,
2293 	ACTION_NEXT,
2294 	ZERO
2295 };
2296 
2297 static const enum index action_quota_update[] = {
2298 	ACTION_QUOTA_QU_LIMIT,
2299 	ACTION_QUOTA_QU_UPDATE_OP,
2300 	ACTION_NEXT,
2301 	ZERO
2302 };
2303 
2304 static const enum index action_mark[] = {
2305 	ACTION_MARK_ID,
2306 	ACTION_NEXT,
2307 	ZERO,
2308 };
2309 
2310 static const enum index action_queue[] = {
2311 	ACTION_QUEUE_INDEX,
2312 	ACTION_NEXT,
2313 	ZERO,
2314 };
2315 
2316 static const enum index action_count[] = {
2317 	ACTION_COUNT_ID,
2318 	ACTION_NEXT,
2319 	ZERO,
2320 };
2321 
2322 static const enum index action_rss[] = {
2323 	ACTION_RSS_FUNC,
2324 	ACTION_RSS_LEVEL,
2325 	ACTION_RSS_TYPES,
2326 	ACTION_RSS_KEY,
2327 	ACTION_RSS_KEY_LEN,
2328 	ACTION_RSS_QUEUES,
2329 	ACTION_NEXT,
2330 	ZERO,
2331 };
2332 
2333 static const enum index action_vf[] = {
2334 	ACTION_VF_ORIGINAL,
2335 	ACTION_VF_ID,
2336 	ACTION_NEXT,
2337 	ZERO,
2338 };
2339 
2340 static const enum index action_port_id[] = {
2341 	ACTION_PORT_ID_ORIGINAL,
2342 	ACTION_PORT_ID_ID,
2343 	ACTION_NEXT,
2344 	ZERO,
2345 };
2346 
2347 static const enum index action_meter[] = {
2348 	ACTION_METER_ID,
2349 	ACTION_NEXT,
2350 	ZERO,
2351 };
2352 
2353 static const enum index action_meter_color[] = {
2354 	ACTION_METER_COLOR_TYPE,
2355 	ACTION_NEXT,
2356 	ZERO,
2357 };
2358 
2359 static const enum index action_meter_mark[] = {
2360 	ACTION_METER_PROFILE,
2361 	ACTION_METER_POLICY,
2362 	ACTION_METER_COLOR_MODE,
2363 	ACTION_METER_STATE,
2364 	ACTION_NEXT,
2365 	ZERO,
2366 };
2367 
2368 static const enum index action_of_push_vlan[] = {
2369 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2370 	ACTION_NEXT,
2371 	ZERO,
2372 };
2373 
2374 static const enum index action_of_set_vlan_vid[] = {
2375 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2376 	ACTION_NEXT,
2377 	ZERO,
2378 };
2379 
2380 static const enum index action_of_set_vlan_pcp[] = {
2381 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2382 	ACTION_NEXT,
2383 	ZERO,
2384 };
2385 
2386 static const enum index action_of_pop_mpls[] = {
2387 	ACTION_OF_POP_MPLS_ETHERTYPE,
2388 	ACTION_NEXT,
2389 	ZERO,
2390 };
2391 
2392 static const enum index action_of_push_mpls[] = {
2393 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2394 	ACTION_NEXT,
2395 	ZERO,
2396 };
2397 
2398 static const enum index action_set_ipv4_src[] = {
2399 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2400 	ACTION_NEXT,
2401 	ZERO,
2402 };
2403 
2404 static const enum index action_set_mac_src[] = {
2405 	ACTION_SET_MAC_SRC_MAC_SRC,
2406 	ACTION_NEXT,
2407 	ZERO,
2408 };
2409 
2410 static const enum index action_set_ipv4_dst[] = {
2411 	ACTION_SET_IPV4_DST_IPV4_DST,
2412 	ACTION_NEXT,
2413 	ZERO,
2414 };
2415 
2416 static const enum index action_set_ipv6_src[] = {
2417 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2418 	ACTION_NEXT,
2419 	ZERO,
2420 };
2421 
2422 static const enum index action_set_ipv6_dst[] = {
2423 	ACTION_SET_IPV6_DST_IPV6_DST,
2424 	ACTION_NEXT,
2425 	ZERO,
2426 };
2427 
2428 static const enum index action_set_tp_src[] = {
2429 	ACTION_SET_TP_SRC_TP_SRC,
2430 	ACTION_NEXT,
2431 	ZERO,
2432 };
2433 
2434 static const enum index action_set_tp_dst[] = {
2435 	ACTION_SET_TP_DST_TP_DST,
2436 	ACTION_NEXT,
2437 	ZERO,
2438 };
2439 
2440 static const enum index action_set_ttl[] = {
2441 	ACTION_SET_TTL_TTL,
2442 	ACTION_NEXT,
2443 	ZERO,
2444 };
2445 
2446 static const enum index action_jump[] = {
2447 	ACTION_JUMP_GROUP,
2448 	ACTION_NEXT,
2449 	ZERO,
2450 };
2451 
2452 static const enum index action_set_mac_dst[] = {
2453 	ACTION_SET_MAC_DST_MAC_DST,
2454 	ACTION_NEXT,
2455 	ZERO,
2456 };
2457 
2458 static const enum index action_inc_tcp_seq[] = {
2459 	ACTION_INC_TCP_SEQ_VALUE,
2460 	ACTION_NEXT,
2461 	ZERO,
2462 };
2463 
2464 static const enum index action_dec_tcp_seq[] = {
2465 	ACTION_DEC_TCP_SEQ_VALUE,
2466 	ACTION_NEXT,
2467 	ZERO,
2468 };
2469 
2470 static const enum index action_inc_tcp_ack[] = {
2471 	ACTION_INC_TCP_ACK_VALUE,
2472 	ACTION_NEXT,
2473 	ZERO,
2474 };
2475 
2476 static const enum index action_dec_tcp_ack[] = {
2477 	ACTION_DEC_TCP_ACK_VALUE,
2478 	ACTION_NEXT,
2479 	ZERO,
2480 };
2481 
2482 static const enum index action_raw_encap[] = {
2483 	ACTION_RAW_ENCAP_SIZE,
2484 	ACTION_RAW_ENCAP_INDEX,
2485 	ACTION_NEXT,
2486 	ZERO,
2487 };
2488 
2489 static const enum index action_raw_decap[] = {
2490 	ACTION_RAW_DECAP_INDEX,
2491 	ACTION_NEXT,
2492 	ZERO,
2493 };
2494 
2495 static const enum index action_ipv6_ext_remove[] = {
2496 	ACTION_IPV6_EXT_REMOVE_INDEX,
2497 	ACTION_NEXT,
2498 	ZERO,
2499 };
2500 
2501 static const enum index action_ipv6_ext_push[] = {
2502 	ACTION_IPV6_EXT_PUSH_INDEX,
2503 	ACTION_NEXT,
2504 	ZERO,
2505 };
2506 
2507 static const enum index action_set_tag[] = {
2508 	ACTION_SET_TAG_DATA,
2509 	ACTION_SET_TAG_INDEX,
2510 	ACTION_SET_TAG_MASK,
2511 	ACTION_NEXT,
2512 	ZERO,
2513 };
2514 
2515 static const enum index action_set_meta[] = {
2516 	ACTION_SET_META_DATA,
2517 	ACTION_SET_META_MASK,
2518 	ACTION_NEXT,
2519 	ZERO,
2520 };
2521 
2522 static const enum index action_set_ipv4_dscp[] = {
2523 	ACTION_SET_IPV4_DSCP_VALUE,
2524 	ACTION_NEXT,
2525 	ZERO,
2526 };
2527 
2528 static const enum index action_set_ipv6_dscp[] = {
2529 	ACTION_SET_IPV6_DSCP_VALUE,
2530 	ACTION_NEXT,
2531 	ZERO,
2532 };
2533 
2534 static const enum index action_age[] = {
2535 	ACTION_AGE,
2536 	ACTION_AGE_TIMEOUT,
2537 	ACTION_NEXT,
2538 	ZERO,
2539 };
2540 
2541 static const enum index action_age_update[] = {
2542 	ACTION_AGE_UPDATE,
2543 	ACTION_AGE_UPDATE_TIMEOUT,
2544 	ACTION_AGE_UPDATE_TOUCH,
2545 	ACTION_NEXT,
2546 	ZERO,
2547 };
2548 
2549 static const enum index action_sample[] = {
2550 	ACTION_SAMPLE,
2551 	ACTION_SAMPLE_RATIO,
2552 	ACTION_SAMPLE_INDEX,
2553 	ACTION_NEXT,
2554 	ZERO,
2555 };
2556 
2557 static const enum index next_action_sample[] = {
2558 	ACTION_QUEUE,
2559 	ACTION_RSS,
2560 	ACTION_MARK,
2561 	ACTION_COUNT,
2562 	ACTION_PORT_ID,
2563 	ACTION_RAW_ENCAP,
2564 	ACTION_VXLAN_ENCAP,
2565 	ACTION_NVGRE_ENCAP,
2566 	ACTION_REPRESENTED_PORT,
2567 	ACTION_PORT_REPRESENTOR,
2568 	ACTION_NEXT,
2569 	ZERO,
2570 };
2571 
2572 static const enum index item_ipv6_push_ext[] = {
2573 	ITEM_IPV6_PUSH_REMOVE_EXT,
2574 	ZERO,
2575 };
2576 
2577 static const enum index item_ipv6_push_ext_type[] = {
2578 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2579 	ZERO,
2580 };
2581 
2582 static const enum index item_ipv6_push_ext_header[] = {
2583 	ITEM_IPV6_ROUTING_EXT,
2584 	ITEM_NEXT,
2585 	ZERO,
2586 };
2587 
2588 static const enum index action_modify_field_dst[] = {
2589 	ACTION_MODIFY_FIELD_DST_LEVEL,
2590 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2591 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2592 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2593 	ACTION_MODIFY_FIELD_DST_OFFSET,
2594 	ACTION_MODIFY_FIELD_SRC_TYPE,
2595 	ZERO,
2596 };
2597 
2598 static const enum index action_modify_field_src[] = {
2599 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2600 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2601 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2602 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2603 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2604 	ACTION_MODIFY_FIELD_SRC_VALUE,
2605 	ACTION_MODIFY_FIELD_SRC_POINTER,
2606 	ACTION_MODIFY_FIELD_WIDTH,
2607 	ZERO,
2608 };
2609 
2610 static const enum index action_update_conntrack[] = {
2611 	ACTION_CONNTRACK_UPDATE_DIR,
2612 	ACTION_CONNTRACK_UPDATE_CTX,
2613 	ACTION_NEXT,
2614 	ZERO,
2615 };
2616 
2617 static const enum index action_port_representor[] = {
2618 	ACTION_PORT_REPRESENTOR_PORT_ID,
2619 	ACTION_NEXT,
2620 	ZERO,
2621 };
2622 
2623 static const enum index action_represented_port[] = {
2624 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2625 	ACTION_NEXT,
2626 	ZERO,
2627 };
2628 
2629 static const enum index action_nat64[] = {
2630 	ACTION_NAT64_MODE,
2631 	ACTION_NEXT,
2632 	ZERO,
2633 };
2634 
2635 static const enum index next_hash_subcmd[] = {
2636 	HASH_CALC_TABLE,
2637 	HASH_CALC_ENCAP,
2638 	ZERO,
2639 };
2640 
2641 static const enum index next_hash_encap_dest_subcmd[] = {
2642 	ENCAP_HASH_FIELD_SRC_PORT,
2643 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2644 	ZERO,
2645 };
2646 
2647 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2648 				     const char *, unsigned int,
2649 				     void *, unsigned int);
2650 static int parse_set_sample_action(struct context *, const struct token *,
2651 				   const char *, unsigned int,
2652 				   void *, unsigned int);
2653 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2654 				     const char *, unsigned int,
2655 				     void *, unsigned int);
2656 static int parse_set_init(struct context *, const struct token *,
2657 			  const char *, unsigned int,
2658 			  void *, unsigned int);
2659 static int
2660 parse_flex_handle(struct context *, const struct token *,
2661 		  const char *, unsigned int, void *, unsigned int);
2662 static int parse_init(struct context *, const struct token *,
2663 		      const char *, unsigned int,
2664 		      void *, unsigned int);
2665 static int parse_vc(struct context *, const struct token *,
2666 		    const char *, unsigned int,
2667 		    void *, unsigned int);
2668 static int parse_vc_spec(struct context *, const struct token *,
2669 			 const char *, unsigned int, void *, unsigned int);
2670 static int parse_vc_conf(struct context *, const struct token *,
2671 			 const char *, unsigned int, void *, unsigned int);
2672 static int parse_vc_conf_timeout(struct context *, const struct token *,
2673 				 const char *, unsigned int, void *,
2674 				 unsigned int);
2675 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2676 				    const char *, unsigned int,
2677 				    void *, unsigned int);
2678 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2679 				    const char *, unsigned int,
2680 				    void *, unsigned int);
2681 static int parse_vc_action_meter_color_type(struct context *,
2682 					const struct token *,
2683 					const char *, unsigned int, void *,
2684 					unsigned int);
2685 static int parse_vc_action_rss(struct context *, const struct token *,
2686 			       const char *, unsigned int, void *,
2687 			       unsigned int);
2688 static int parse_vc_action_rss_func(struct context *, const struct token *,
2689 				    const char *, unsigned int, void *,
2690 				    unsigned int);
2691 static int parse_vc_action_rss_type(struct context *, const struct token *,
2692 				    const char *, unsigned int, void *,
2693 				    unsigned int);
2694 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2695 				     const char *, unsigned int, void *,
2696 				     unsigned int);
2697 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2698 				       const char *, unsigned int, void *,
2699 				       unsigned int);
2700 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2701 				       const char *, unsigned int, void *,
2702 				       unsigned int);
2703 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2704 				    const char *, unsigned int, void *,
2705 				    unsigned int);
2706 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2707 				    const char *, unsigned int, void *,
2708 				    unsigned int);
2709 static int parse_vc_action_mplsogre_encap(struct context *,
2710 					  const struct token *, const char *,
2711 					  unsigned int, void *, unsigned int);
2712 static int parse_vc_action_mplsogre_decap(struct context *,
2713 					  const struct token *, const char *,
2714 					  unsigned int, void *, unsigned int);
2715 static int parse_vc_action_mplsoudp_encap(struct context *,
2716 					  const struct token *, const char *,
2717 					  unsigned int, void *, unsigned int);
2718 static int parse_vc_action_mplsoudp_decap(struct context *,
2719 					  const struct token *, const char *,
2720 					  unsigned int, void *, unsigned int);
2721 static int parse_vc_action_raw_encap(struct context *,
2722 				     const struct token *, const char *,
2723 				     unsigned int, void *, unsigned int);
2724 static int parse_vc_action_raw_decap(struct context *,
2725 				     const struct token *, const char *,
2726 				     unsigned int, void *, unsigned int);
2727 static int parse_vc_action_raw_encap_index(struct context *,
2728 					   const struct token *, const char *,
2729 					   unsigned int, void *, unsigned int);
2730 static int parse_vc_action_raw_decap_index(struct context *,
2731 					   const struct token *, const char *,
2732 					   unsigned int, void *, unsigned int);
2733 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2734 					   const char *str, unsigned int len, void *buf,
2735 					   unsigned int size);
2736 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2737 						 const struct token *token,
2738 						 const char *str, unsigned int len,
2739 						 void *buf,
2740 						 unsigned int size);
2741 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2742 					 const char *str, unsigned int len, void *buf,
2743 					 unsigned int size);
2744 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2745 					       const struct token *token,
2746 					       const char *str, unsigned int len,
2747 					       void *buf,
2748 					       unsigned int size);
2749 static int parse_vc_action_set_meta(struct context *ctx,
2750 				    const struct token *token, const char *str,
2751 				    unsigned int len, void *buf,
2752 					unsigned int size);
2753 static int parse_vc_action_sample(struct context *ctx,
2754 				    const struct token *token, const char *str,
2755 				    unsigned int len, void *buf,
2756 				    unsigned int size);
2757 static int
2758 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2759 				const char *str, unsigned int len, void *buf,
2760 				unsigned int size);
2761 static int
2762 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2763 				const char *str, unsigned int len, void *buf,
2764 				unsigned int size);
2765 static int
2766 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2767 				const char *str, unsigned int len, void *buf,
2768 				unsigned int size);
2769 static int
2770 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2771 				const char *str, unsigned int len, void *buf,
2772 				unsigned int size);
2773 static int
2774 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2775 			 const char *str, unsigned int len, void *buf,
2776 			 unsigned int size);
2777 static int parse_destroy(struct context *, const struct token *,
2778 			 const char *, unsigned int,
2779 			 void *, unsigned int);
2780 static int parse_flush(struct context *, const struct token *,
2781 		       const char *, unsigned int,
2782 		       void *, unsigned int);
2783 static int parse_dump(struct context *, const struct token *,
2784 		      const char *, unsigned int,
2785 		      void *, unsigned int);
2786 static int parse_query(struct context *, const struct token *,
2787 		       const char *, unsigned int,
2788 		       void *, unsigned int);
2789 static int parse_action(struct context *, const struct token *,
2790 			const char *, unsigned int,
2791 			void *, unsigned int);
2792 static int parse_list(struct context *, const struct token *,
2793 		      const char *, unsigned int,
2794 		      void *, unsigned int);
2795 static int parse_aged(struct context *, const struct token *,
2796 		      const char *, unsigned int,
2797 		      void *, unsigned int);
2798 static int parse_isolate(struct context *, const struct token *,
2799 			 const char *, unsigned int,
2800 			 void *, unsigned int);
2801 static int parse_configure(struct context *, const struct token *,
2802 			   const char *, unsigned int,
2803 			   void *, unsigned int);
2804 static int parse_template(struct context *, const struct token *,
2805 			  const char *, unsigned int,
2806 			  void *, unsigned int);
2807 static int parse_template_destroy(struct context *, const struct token *,
2808 				  const char *, unsigned int,
2809 				  void *, unsigned int);
2810 static int parse_table(struct context *, const struct token *,
2811 		       const char *, unsigned int, void *, unsigned int);
2812 static int parse_table_destroy(struct context *, const struct token *,
2813 			       const char *, unsigned int,
2814 			       void *, unsigned int);
2815 static int parse_qo(struct context *, const struct token *,
2816 		    const char *, unsigned int,
2817 		    void *, unsigned int);
2818 static int parse_qo_destroy(struct context *, const struct token *,
2819 			    const char *, unsigned int,
2820 			    void *, unsigned int);
2821 static int parse_qia(struct context *, const struct token *,
2822 		     const char *, unsigned int,
2823 		     void *, unsigned int);
2824 static int parse_qia_destroy(struct context *, const struct token *,
2825 			     const char *, unsigned int,
2826 			     void *, unsigned int);
2827 static int parse_push(struct context *, const struct token *,
2828 		      const char *, unsigned int,
2829 		      void *, unsigned int);
2830 static int parse_pull(struct context *, const struct token *,
2831 		      const char *, unsigned int,
2832 		      void *, unsigned int);
2833 static int parse_group(struct context *, const struct token *,
2834 		       const char *, unsigned int,
2835 		       void *, unsigned int);
2836 static int parse_hash(struct context *, const struct token *,
2837 		      const char *, unsigned int,
2838 		      void *, unsigned int);
2839 static int parse_tunnel(struct context *, const struct token *,
2840 			const char *, unsigned int,
2841 			void *, unsigned int);
2842 static int parse_flex(struct context *, const struct token *,
2843 		      const char *, unsigned int, void *, unsigned int);
2844 static int parse_int(struct context *, const struct token *,
2845 		     const char *, unsigned int,
2846 		     void *, unsigned int);
2847 static int parse_prefix(struct context *, const struct token *,
2848 			const char *, unsigned int,
2849 			void *, unsigned int);
2850 static int parse_boolean(struct context *, const struct token *,
2851 			 const char *, unsigned int,
2852 			 void *, unsigned int);
2853 static int parse_string(struct context *, const struct token *,
2854 			const char *, unsigned int,
2855 			void *, unsigned int);
2856 static int parse_hex(struct context *ctx, const struct token *token,
2857 			const char *str, unsigned int len,
2858 			void *buf, unsigned int size);
2859 static int parse_string0(struct context *, const struct token *,
2860 			const char *, unsigned int,
2861 			void *, unsigned int);
2862 static int parse_mac_addr(struct context *, const struct token *,
2863 			  const char *, unsigned int,
2864 			  void *, unsigned int);
2865 static int parse_ipv4_addr(struct context *, const struct token *,
2866 			   const char *, unsigned int,
2867 			   void *, unsigned int);
2868 static int parse_ipv6_addr(struct context *, const struct token *,
2869 			   const char *, unsigned int,
2870 			   void *, unsigned int);
2871 static int parse_port(struct context *, const struct token *,
2872 		      const char *, unsigned int,
2873 		      void *, unsigned int);
2874 static int parse_ia(struct context *, const struct token *,
2875 		    const char *, unsigned int,
2876 		    void *, unsigned int);
2877 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2878 			    const char *str, unsigned int len,
2879 			    void *buf, unsigned int size);
2880 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2881 			   const char *str, unsigned int len, void *buf,
2882 			   unsigned int size);
2883 
2884 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2885 			       const char *str, unsigned int len, void *buf,
2886 			       unsigned int size);
2887 static int parse_ia_port(struct context *ctx, const struct token *token,
2888 			 const char *str, unsigned int len, void *buf,
2889 			 unsigned int size);
2890 static int parse_mp(struct context *, const struct token *,
2891 		    const char *, unsigned int,
2892 		    void *, unsigned int);
2893 static int parse_meter_profile_id2ptr(struct context *ctx,
2894 				      const struct token *token,
2895 				      const char *str, unsigned int len,
2896 				      void *buf, unsigned int size);
2897 static int parse_meter_policy_id2ptr(struct context *ctx,
2898 				     const struct token *token,
2899 				     const char *str, unsigned int len,
2900 				     void *buf, unsigned int size);
2901 static int parse_meter_color(struct context *ctx, const struct token *token,
2902 			     const char *str, unsigned int len, void *buf,
2903 			     unsigned int size);
2904 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2905 				      const char *str, unsigned int len, void *buf,
2906 				      unsigned int size);
2907 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2908 				 const char *str, unsigned int len, void *buf,
2909 				 unsigned int size);
2910 static int
2911 parse_quota_state_name(struct context *ctx, const struct token *token,
2912 		       const char *str, unsigned int len, void *buf,
2913 		       unsigned int size);
2914 static int
2915 parse_quota_mode_name(struct context *ctx, const struct token *token,
2916 		      const char *str, unsigned int len, void *buf,
2917 		      unsigned int size);
2918 static int
2919 parse_quota_update_name(struct context *ctx, const struct token *token,
2920 			const char *str, unsigned int len, void *buf,
2921 			unsigned int size);
2922 static int
2923 parse_qu_mode_name(struct context *ctx, const struct token *token,
2924 		   const char *str, unsigned int len, void *buf,
2925 		   unsigned int size);
2926 static int comp_none(struct context *, const struct token *,
2927 		     unsigned int, char *, unsigned int);
2928 static int comp_boolean(struct context *, const struct token *,
2929 			unsigned int, char *, unsigned int);
2930 static int comp_action(struct context *, const struct token *,
2931 		       unsigned int, char *, unsigned int);
2932 static int comp_port(struct context *, const struct token *,
2933 		     unsigned int, char *, unsigned int);
2934 static int comp_rule_id(struct context *, const struct token *,
2935 			unsigned int, char *, unsigned int);
2936 static int comp_vc_action_rss_type(struct context *, const struct token *,
2937 				   unsigned int, char *, unsigned int);
2938 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2939 				    unsigned int, char *, unsigned int);
2940 static int comp_set_raw_index(struct context *, const struct token *,
2941 			      unsigned int, char *, unsigned int);
2942 static int comp_set_sample_index(struct context *, const struct token *,
2943 			      unsigned int, char *, unsigned int);
2944 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2945 				   unsigned int ent, char *buf, unsigned int size);
2946 static int comp_set_modify_field_op(struct context *, const struct token *,
2947 			      unsigned int, char *, unsigned int);
2948 static int comp_set_modify_field_id(struct context *, const struct token *,
2949 			      unsigned int, char *, unsigned int);
2950 static int comp_pattern_template_id(struct context *, const struct token *,
2951 				    unsigned int, char *, unsigned int);
2952 static int comp_actions_template_id(struct context *, const struct token *,
2953 				    unsigned int, char *, unsigned int);
2954 static int comp_table_id(struct context *, const struct token *,
2955 			 unsigned int, char *, unsigned int);
2956 static int comp_queue_id(struct context *, const struct token *,
2957 			 unsigned int, char *, unsigned int);
2958 static int comp_meter_color(struct context *, const struct token *,
2959 			    unsigned int, char *, unsigned int);
2960 static int comp_insertion_table_type(struct context *, const struct token *,
2961 				     unsigned int, char *, unsigned int);
2962 static int comp_hash_table_type(struct context *, const struct token *,
2963 				unsigned int, char *, unsigned int);
2964 static int
2965 comp_quota_state_name(struct context *ctx, const struct token *token,
2966 		      unsigned int ent, char *buf, unsigned int size);
2967 static int
2968 comp_quota_mode_name(struct context *ctx, const struct token *token,
2969 		     unsigned int ent, char *buf, unsigned int size);
2970 static int
2971 comp_quota_update_name(struct context *ctx, const struct token *token,
2972 		       unsigned int ent, char *buf, unsigned int size);
2973 static int
2974 comp_qu_mode_name(struct context *ctx, const struct token *token,
2975 		  unsigned int ent, char *buf, unsigned int size);
2976 static int
2977 comp_set_compare_field_id(struct context *ctx, const struct token *token,
2978 			  unsigned int ent, char *buf, unsigned int size);
2979 static int
2980 comp_set_compare_op(struct context *ctx, const struct token *token,
2981 		    unsigned int ent, char *buf, unsigned int size);
2982 static int
2983 parse_vc_compare_op(struct context *ctx, const struct token *token,
2984 			 const char *str, unsigned int len, void *buf,
2985 			 unsigned int size);
2986 static int
2987 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
2988 			  const char *str, unsigned int len, void *buf,
2989 			  unsigned int size);
2990 static int
2991 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
2992 			     const char *str, unsigned int len, void *buf,
2993 			     unsigned int size);
2994 
2995 struct indlst_conf {
2996 	uint32_t id;
2997 	uint32_t conf_num;
2998 	struct rte_flow_action *actions;
2999 	const void **conf;
3000 	SLIST_ENTRY(indlst_conf) next;
3001 };
3002 
3003 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3004 
3005 /** Token definitions. */
3006 static const struct token token_list[] = {
3007 	/* Special tokens. */
3008 	[ZERO] = {
3009 		.name = "ZERO",
3010 		.help = "null entry, abused as the entry point",
3011 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3012 	},
3013 	[END] = {
3014 		.name = "",
3015 		.type = "RETURN",
3016 		.help = "command may end here",
3017 	},
3018 	[START_SET] = {
3019 		.name = "START_SET",
3020 		.help = "null entry, abused as the entry point for set",
3021 		.next = NEXT(NEXT_ENTRY(SET)),
3022 	},
3023 	[END_SET] = {
3024 		.name = "end_set",
3025 		.type = "RETURN",
3026 		.help = "set command may end here",
3027 	},
3028 	/* Common tokens. */
3029 	[COMMON_INTEGER] = {
3030 		.name = "{int}",
3031 		.type = "INTEGER",
3032 		.help = "integer value",
3033 		.call = parse_int,
3034 		.comp = comp_none,
3035 	},
3036 	[COMMON_UNSIGNED] = {
3037 		.name = "{unsigned}",
3038 		.type = "UNSIGNED",
3039 		.help = "unsigned integer value",
3040 		.call = parse_int,
3041 		.comp = comp_none,
3042 	},
3043 	[COMMON_PREFIX] = {
3044 		.name = "{prefix}",
3045 		.type = "PREFIX",
3046 		.help = "prefix length for bit-mask",
3047 		.call = parse_prefix,
3048 		.comp = comp_none,
3049 	},
3050 	[COMMON_BOOLEAN] = {
3051 		.name = "{boolean}",
3052 		.type = "BOOLEAN",
3053 		.help = "any boolean value",
3054 		.call = parse_boolean,
3055 		.comp = comp_boolean,
3056 	},
3057 	[COMMON_STRING] = {
3058 		.name = "{string}",
3059 		.type = "STRING",
3060 		.help = "fixed string",
3061 		.call = parse_string,
3062 		.comp = comp_none,
3063 	},
3064 	[COMMON_HEX] = {
3065 		.name = "{hex}",
3066 		.type = "HEX",
3067 		.help = "fixed string",
3068 		.call = parse_hex,
3069 	},
3070 	[COMMON_FILE_PATH] = {
3071 		.name = "{file path}",
3072 		.type = "STRING",
3073 		.help = "file path",
3074 		.call = parse_string0,
3075 		.comp = comp_none,
3076 	},
3077 	[COMMON_MAC_ADDR] = {
3078 		.name = "{MAC address}",
3079 		.type = "MAC-48",
3080 		.help = "standard MAC address notation",
3081 		.call = parse_mac_addr,
3082 		.comp = comp_none,
3083 	},
3084 	[COMMON_IPV4_ADDR] = {
3085 		.name = "{IPv4 address}",
3086 		.type = "IPV4 ADDRESS",
3087 		.help = "standard IPv4 address notation",
3088 		.call = parse_ipv4_addr,
3089 		.comp = comp_none,
3090 	},
3091 	[COMMON_IPV6_ADDR] = {
3092 		.name = "{IPv6 address}",
3093 		.type = "IPV6 ADDRESS",
3094 		.help = "standard IPv6 address notation",
3095 		.call = parse_ipv6_addr,
3096 		.comp = comp_none,
3097 	},
3098 	[COMMON_RULE_ID] = {
3099 		.name = "{rule id}",
3100 		.type = "RULE ID",
3101 		.help = "rule identifier",
3102 		.call = parse_int,
3103 		.comp = comp_rule_id,
3104 	},
3105 	[COMMON_PORT_ID] = {
3106 		.name = "{port_id}",
3107 		.type = "PORT ID",
3108 		.help = "port identifier",
3109 		.call = parse_port,
3110 		.comp = comp_port,
3111 	},
3112 	[COMMON_GROUP_ID] = {
3113 		.name = "{group_id}",
3114 		.type = "GROUP ID",
3115 		.help = "group identifier",
3116 		.call = parse_int,
3117 		.comp = comp_none,
3118 	},
3119 	[COMMON_PRIORITY_LEVEL] = {
3120 		.name = "{level}",
3121 		.type = "PRIORITY",
3122 		.help = "priority level",
3123 		.call = parse_int,
3124 		.comp = comp_none,
3125 	},
3126 	[COMMON_INDIRECT_ACTION_ID] = {
3127 		.name = "{indirect_action_id}",
3128 		.type = "INDIRECT_ACTION_ID",
3129 		.help = "indirect action id",
3130 		.call = parse_int,
3131 		.comp = comp_none,
3132 	},
3133 	[COMMON_PROFILE_ID] = {
3134 		.name = "{profile_id}",
3135 		.type = "PROFILE_ID",
3136 		.help = "profile id",
3137 		.call = parse_int,
3138 		.comp = comp_none,
3139 	},
3140 	[COMMON_POLICY_ID] = {
3141 		.name = "{policy_id}",
3142 		.type = "POLICY_ID",
3143 		.help = "policy id",
3144 		.call = parse_int,
3145 		.comp = comp_none,
3146 	},
3147 	[COMMON_FLEX_TOKEN] = {
3148 		.name = "{flex token}",
3149 		.type = "flex token",
3150 		.help = "flex token",
3151 		.call = parse_int,
3152 		.comp = comp_none,
3153 	},
3154 	[COMMON_FLEX_HANDLE] = {
3155 		.name = "{flex handle}",
3156 		.type = "FLEX HANDLE",
3157 		.help = "fill flex item data",
3158 		.call = parse_flex_handle,
3159 		.comp = comp_none,
3160 	},
3161 	[COMMON_PATTERN_TEMPLATE_ID] = {
3162 		.name = "{pattern_template_id}",
3163 		.type = "PATTERN_TEMPLATE_ID",
3164 		.help = "pattern template id",
3165 		.call = parse_int,
3166 		.comp = comp_pattern_template_id,
3167 	},
3168 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3169 		.name = "{actions_template_id}",
3170 		.type = "ACTIONS_TEMPLATE_ID",
3171 		.help = "actions template id",
3172 		.call = parse_int,
3173 		.comp = comp_actions_template_id,
3174 	},
3175 	[COMMON_TABLE_ID] = {
3176 		.name = "{table_id}",
3177 		.type = "TABLE_ID",
3178 		.help = "table id",
3179 		.call = parse_int,
3180 		.comp = comp_table_id,
3181 	},
3182 	[COMMON_QUEUE_ID] = {
3183 		.name = "{queue_id}",
3184 		.type = "QUEUE_ID",
3185 		.help = "queue id",
3186 		.call = parse_int,
3187 		.comp = comp_queue_id,
3188 	},
3189 	/* Top-level command. */
3190 	[FLOW] = {
3191 		.name = "flow",
3192 		.type = "{command} {port_id} [{arg} [...]]",
3193 		.help = "manage ingress/egress flow rules",
3194 		.next = NEXT(NEXT_ENTRY
3195 			     (INFO,
3196 			      CONFIGURE,
3197 			      PATTERN_TEMPLATE,
3198 			      ACTIONS_TEMPLATE,
3199 			      TABLE,
3200 			      FLOW_GROUP,
3201 			      INDIRECT_ACTION,
3202 			      VALIDATE,
3203 			      CREATE,
3204 			      DESTROY,
3205 			      FLUSH,
3206 			      DUMP,
3207 			      LIST,
3208 			      AGED,
3209 			      QUERY,
3210 			      ISOLATE,
3211 			      TUNNEL,
3212 			      FLEX,
3213 			      QUEUE,
3214 			      PUSH,
3215 			      PULL,
3216 			      HASH)),
3217 		.call = parse_init,
3218 	},
3219 	/* Top-level command. */
3220 	[INFO] = {
3221 		.name = "info",
3222 		.help = "get information about flow engine",
3223 		.next = NEXT(NEXT_ENTRY(END),
3224 			     NEXT_ENTRY(COMMON_PORT_ID)),
3225 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3226 		.call = parse_configure,
3227 	},
3228 	/* Top-level command. */
3229 	[CONFIGURE] = {
3230 		.name = "configure",
3231 		.help = "configure flow engine",
3232 		.next = NEXT(next_config_attr,
3233 			     NEXT_ENTRY(COMMON_PORT_ID)),
3234 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3235 		.call = parse_configure,
3236 	},
3237 	/* Configure arguments. */
3238 	[CONFIG_QUEUES_NUMBER] = {
3239 		.name = "queues_number",
3240 		.help = "number of queues",
3241 		.next = NEXT(next_config_attr,
3242 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3243 		.args = ARGS(ARGS_ENTRY(struct buffer,
3244 					args.configure.nb_queue)),
3245 	},
3246 	[CONFIG_QUEUES_SIZE] = {
3247 		.name = "queues_size",
3248 		.help = "number of elements in queues",
3249 		.next = NEXT(next_config_attr,
3250 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3251 		.args = ARGS(ARGS_ENTRY(struct buffer,
3252 					args.configure.queue_attr.size)),
3253 	},
3254 	[CONFIG_COUNTERS_NUMBER] = {
3255 		.name = "counters_number",
3256 		.help = "number of counters",
3257 		.next = NEXT(next_config_attr,
3258 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3259 		.args = ARGS(ARGS_ENTRY(struct buffer,
3260 					args.configure.port_attr.nb_counters)),
3261 	},
3262 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3263 		.name = "aging_counters_number",
3264 		.help = "number of aging objects",
3265 		.next = NEXT(next_config_attr,
3266 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3267 		.args = ARGS(ARGS_ENTRY(struct buffer,
3268 					args.configure.port_attr.nb_aging_objects)),
3269 	},
3270 	[CONFIG_QUOTAS_NUMBER] = {
3271 		.name = "quotas_number",
3272 		.help = "number of quotas",
3273 		.next = NEXT(next_config_attr,
3274 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3275 		.args = ARGS(ARGS_ENTRY(struct buffer,
3276 				     args.configure.port_attr.nb_quotas)),
3277 	},
3278 	[CONFIG_METERS_NUMBER] = {
3279 		.name = "meters_number",
3280 		.help = "number of meters",
3281 		.next = NEXT(next_config_attr,
3282 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3283 		.args = ARGS(ARGS_ENTRY(struct buffer,
3284 					args.configure.port_attr.nb_meters)),
3285 	},
3286 	[CONFIG_CONN_TRACK_NUMBER] = {
3287 		.name = "conn_tracks_number",
3288 		.help = "number of connection trackings",
3289 		.next = NEXT(next_config_attr,
3290 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3291 		.args = ARGS(ARGS_ENTRY(struct buffer,
3292 					args.configure.port_attr.nb_conn_tracks)),
3293 	},
3294 	[CONFIG_FLAGS] = {
3295 		.name = "flags",
3296 		.help = "configuration flags",
3297 		.next = NEXT(next_config_attr,
3298 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3299 		.args = ARGS(ARGS_ENTRY(struct buffer,
3300 					args.configure.port_attr.flags)),
3301 	},
3302 	[CONFIG_HOST_PORT] = {
3303 		.name = "host_port",
3304 		.help = "host port for shared objects",
3305 		.next = NEXT(next_config_attr,
3306 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3307 		.args = ARGS(ARGS_ENTRY(struct buffer,
3308 					args.configure.port_attr.host_port_id)),
3309 	},
3310 	/* Top-level command. */
3311 	[PATTERN_TEMPLATE] = {
3312 		.name = "pattern_template",
3313 		.type = "{command} {port_id} [{arg} [...]]",
3314 		.help = "manage pattern templates",
3315 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3316 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3317 		.call = parse_template,
3318 	},
3319 	/* Sub-level commands. */
3320 	[PATTERN_TEMPLATE_CREATE] = {
3321 		.name = "create",
3322 		.help = "create pattern template",
3323 		.next = NEXT(next_pt_attr),
3324 		.call = parse_template,
3325 	},
3326 	[PATTERN_TEMPLATE_DESTROY] = {
3327 		.name = "destroy",
3328 		.help = "destroy pattern template",
3329 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3330 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3331 		.call = parse_template_destroy,
3332 	},
3333 	/* Pattern template arguments. */
3334 	[PATTERN_TEMPLATE_CREATE_ID] = {
3335 		.name = "pattern_template_id",
3336 		.help = "specify a pattern template id to create",
3337 		.next = NEXT(next_pt_attr,
3338 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3339 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3340 	},
3341 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3342 		.name = "pattern_template",
3343 		.help = "specify a pattern template id to destroy",
3344 		.next = NEXT(next_pt_destroy_attr,
3345 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3346 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3347 					    args.templ_destroy.template_id)),
3348 		.call = parse_template_destroy,
3349 	},
3350 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3351 		.name = "relaxed",
3352 		.help = "is matching relaxed",
3353 		.next = NEXT(next_pt_attr,
3354 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3355 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3356 			     args.vc.attr.reserved, 1)),
3357 	},
3358 	[PATTERN_TEMPLATE_INGRESS] = {
3359 		.name = "ingress",
3360 		.help = "attribute pattern to ingress",
3361 		.next = NEXT(next_pt_attr),
3362 		.call = parse_template,
3363 	},
3364 	[PATTERN_TEMPLATE_EGRESS] = {
3365 		.name = "egress",
3366 		.help = "attribute pattern to egress",
3367 		.next = NEXT(next_pt_attr),
3368 		.call = parse_template,
3369 	},
3370 	[PATTERN_TEMPLATE_TRANSFER] = {
3371 		.name = "transfer",
3372 		.help = "attribute pattern to transfer",
3373 		.next = NEXT(next_pt_attr),
3374 		.call = parse_template,
3375 	},
3376 	[PATTERN_TEMPLATE_SPEC] = {
3377 		.name = "template",
3378 		.help = "specify item to create pattern template",
3379 		.next = NEXT(next_item),
3380 	},
3381 	/* Top-level command. */
3382 	[ACTIONS_TEMPLATE] = {
3383 		.name = "actions_template",
3384 		.type = "{command} {port_id} [{arg} [...]]",
3385 		.help = "manage actions templates",
3386 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3387 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3388 		.call = parse_template,
3389 	},
3390 	/* Sub-level commands. */
3391 	[ACTIONS_TEMPLATE_CREATE] = {
3392 		.name = "create",
3393 		.help = "create actions template",
3394 		.next = NEXT(next_at_attr),
3395 		.call = parse_template,
3396 	},
3397 	[ACTIONS_TEMPLATE_DESTROY] = {
3398 		.name = "destroy",
3399 		.help = "destroy actions template",
3400 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3401 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3402 		.call = parse_template_destroy,
3403 	},
3404 	/* Actions template arguments. */
3405 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3406 		.name = "actions_template_id",
3407 		.help = "specify an actions template id to create",
3408 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3409 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3410 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3411 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3412 	},
3413 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3414 		.name = "actions_template",
3415 		.help = "specify an actions template id to destroy",
3416 		.next = NEXT(next_at_destroy_attr,
3417 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3418 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3419 					    args.templ_destroy.template_id)),
3420 		.call = parse_template_destroy,
3421 	},
3422 	[ACTIONS_TEMPLATE_INGRESS] = {
3423 		.name = "ingress",
3424 		.help = "attribute actions to ingress",
3425 		.next = NEXT(next_at_attr),
3426 		.call = parse_template,
3427 	},
3428 	[ACTIONS_TEMPLATE_EGRESS] = {
3429 		.name = "egress",
3430 		.help = "attribute actions to egress",
3431 		.next = NEXT(next_at_attr),
3432 		.call = parse_template,
3433 	},
3434 	[ACTIONS_TEMPLATE_TRANSFER] = {
3435 		.name = "transfer",
3436 		.help = "attribute actions to transfer",
3437 		.next = NEXT(next_at_attr),
3438 		.call = parse_template,
3439 	},
3440 	[ACTIONS_TEMPLATE_SPEC] = {
3441 		.name = "template",
3442 		.help = "specify action to create actions template",
3443 		.next = NEXT(next_action),
3444 		.call = parse_template,
3445 	},
3446 	[ACTIONS_TEMPLATE_MASK] = {
3447 		.name = "mask",
3448 		.help = "specify action mask to create actions template",
3449 		.next = NEXT(next_action),
3450 		.call = parse_template,
3451 	},
3452 	/* Top-level command. */
3453 	[TABLE] = {
3454 		.name = "template_table",
3455 		.type = "{command} {port_id} [{arg} [...]]",
3456 		.help = "manage template tables",
3457 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3458 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3459 		.call = parse_table,
3460 	},
3461 	/* Sub-level commands. */
3462 	[TABLE_CREATE] = {
3463 		.name = "create",
3464 		.help = "create template table",
3465 		.next = NEXT(next_table_attr),
3466 		.call = parse_table,
3467 	},
3468 	[TABLE_DESTROY] = {
3469 		.name = "destroy",
3470 		.help = "destroy template table",
3471 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3472 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3473 		.call = parse_table_destroy,
3474 	},
3475 	[TABLE_RESIZE] = {
3476 		.name = "resize",
3477 		.help = "resize template table",
3478 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3479 		.call = parse_table
3480 	},
3481 	[TABLE_RESIZE_COMPLETE] = {
3482 		.name = "resize_complete",
3483 		.help = "complete table resize",
3484 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3485 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3486 		.call = parse_table_destroy,
3487 	},
3488 	/* Table  arguments. */
3489 	[TABLE_CREATE_ID] = {
3490 		.name = "table_id",
3491 		.help = "specify table id to create",
3492 		.next = NEXT(next_table_attr,
3493 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3494 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3495 	},
3496 	[TABLE_DESTROY_ID] = {
3497 		.name = "table",
3498 		.help = "table id",
3499 		.next = NEXT(next_table_destroy_attr,
3500 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3501 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3502 					    args.table_destroy.table_id)),
3503 		.call = parse_table_destroy,
3504 	},
3505 	[TABLE_RESIZE_ID] = {
3506 		.name = "table_resize_id",
3507 		.help = "table resize id",
3508 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3509 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3510 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3511 		.call = parse_table
3512 	},
3513 	[TABLE_RESIZE_RULES_NUMBER] = {
3514 		.name = "table_resize_rules_num",
3515 		.help = "table resize rules number",
3516 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3517 		.args = ARGS(ARGS_ENTRY(struct buffer,
3518 					args.table.attr.nb_flows)),
3519 		.call = parse_table
3520 	},
3521 	[TABLE_INSERTION_TYPE] = {
3522 		.name = "insertion_type",
3523 		.help = "specify insertion type",
3524 		.next = NEXT(next_table_attr,
3525 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3526 		.args = ARGS(ARGS_ENTRY(struct buffer,
3527 					args.table.attr.insertion_type)),
3528 	},
3529 	[TABLE_INSERTION_TYPE_NAME] = {
3530 		.name = "insertion_type_name",
3531 		.help = "insertion type name",
3532 		.call = parse_insertion_table_type,
3533 		.comp = comp_insertion_table_type,
3534 	},
3535 	[TABLE_HASH_FUNC] = {
3536 		.name = "hash_func",
3537 		.help = "specify hash calculation function",
3538 		.next = NEXT(next_table_attr,
3539 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3540 		.args = ARGS(ARGS_ENTRY(struct buffer,
3541 					args.table.attr.hash_func)),
3542 	},
3543 	[TABLE_HASH_FUNC_NAME] = {
3544 		.name = "hash_func_name",
3545 		.help = "hash calculation function name",
3546 		.call = parse_hash_table_type,
3547 		.comp = comp_hash_table_type,
3548 	},
3549 	[TABLE_GROUP] = {
3550 		.name = "group",
3551 		.help = "specify a group",
3552 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3553 		.args = ARGS(ARGS_ENTRY(struct buffer,
3554 					args.table.attr.flow_attr.group)),
3555 	},
3556 	[TABLE_PRIORITY] = {
3557 		.name = "priority",
3558 		.help = "specify a priority level",
3559 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3560 		.args = ARGS(ARGS_ENTRY(struct buffer,
3561 					args.table.attr.flow_attr.priority)),
3562 	},
3563 	[TABLE_EGRESS] = {
3564 		.name = "egress",
3565 		.help = "affect rule to egress",
3566 		.next = NEXT(next_table_attr),
3567 		.call = parse_table,
3568 	},
3569 	[TABLE_INGRESS] = {
3570 		.name = "ingress",
3571 		.help = "affect rule to ingress",
3572 		.next = NEXT(next_table_attr),
3573 		.call = parse_table,
3574 	},
3575 	[TABLE_TRANSFER] = {
3576 		.name = "transfer",
3577 		.help = "affect rule to transfer",
3578 		.next = NEXT(next_table_attr),
3579 		.call = parse_table,
3580 	},
3581 	[TABLE_TRANSFER_WIRE_ORIG] = {
3582 		.name = "wire_orig",
3583 		.help = "affect rule direction to transfer",
3584 		.next = NEXT(next_table_attr),
3585 		.call = parse_table,
3586 	},
3587 	[TABLE_TRANSFER_VPORT_ORIG] = {
3588 		.name = "vport_orig",
3589 		.help = "affect rule direction to transfer",
3590 		.next = NEXT(next_table_attr),
3591 		.call = parse_table,
3592 	},
3593 	[TABLE_RESIZABLE] = {
3594 		.name = "resizable",
3595 		.help = "set resizable attribute",
3596 		.next = NEXT(next_table_attr),
3597 		.call = parse_table,
3598 	},
3599 	[TABLE_RULES_NUMBER] = {
3600 		.name = "rules_number",
3601 		.help = "number of rules in table",
3602 		.next = NEXT(next_table_attr,
3603 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3604 		.args = ARGS(ARGS_ENTRY(struct buffer,
3605 					args.table.attr.nb_flows)),
3606 		.call = parse_table,
3607 	},
3608 	[TABLE_PATTERN_TEMPLATE] = {
3609 		.name = "pattern_template",
3610 		.help = "specify pattern template id",
3611 		.next = NEXT(next_table_attr,
3612 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3613 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3614 					    args.table.pat_templ_id)),
3615 		.call = parse_table,
3616 	},
3617 	[TABLE_ACTIONS_TEMPLATE] = {
3618 		.name = "actions_template",
3619 		.help = "specify actions template id",
3620 		.next = NEXT(next_table_attr,
3621 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3622 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3623 					    args.table.act_templ_id)),
3624 		.call = parse_table,
3625 	},
3626 	/* Top-level command. */
3627 	[FLOW_GROUP] = {
3628 		.name = "group",
3629 		.help = "manage flow groups",
3630 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3631 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3632 		.call = parse_group,
3633 	},
3634 	/* Sub-level commands. */
3635 	[GROUP_SET_MISS_ACTIONS] = {
3636 		.name = "set_miss_actions",
3637 		.help = "set group miss actions",
3638 		.next = NEXT(next_action),
3639 		.call = parse_group,
3640 	},
3641 	/* Group arguments */
3642 	[GROUP_ID]	= {
3643 		.name = "group_id",
3644 		.help = "group id",
3645 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3646 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3647 	},
3648 	[GROUP_INGRESS] = {
3649 		.name = "ingress",
3650 		.help = "group ingress attr",
3651 		.next = NEXT(next_group_attr),
3652 		.call = parse_group,
3653 	},
3654 	[GROUP_EGRESS] = {
3655 		.name = "egress",
3656 		.help = "group egress attr",
3657 		.next = NEXT(next_group_attr),
3658 		.call = parse_group,
3659 	},
3660 	[GROUP_TRANSFER] = {
3661 		.name = "transfer",
3662 		.help = "group transfer attr",
3663 		.next = NEXT(next_group_attr),
3664 		.call = parse_group,
3665 	},
3666 	/* Top-level command. */
3667 	[QUEUE] = {
3668 		.name = "queue",
3669 		.help = "queue a flow rule operation",
3670 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3671 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3672 		.call = parse_qo,
3673 	},
3674 	/* Sub-level commands. */
3675 	[QUEUE_CREATE] = {
3676 		.name = "create",
3677 		.help = "create a flow rule",
3678 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3679 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3680 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3681 		.call = parse_qo,
3682 	},
3683 	[QUEUE_DESTROY] = {
3684 		.name = "destroy",
3685 		.help = "destroy a flow rule",
3686 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3687 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3688 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3689 		.call = parse_qo_destroy,
3690 	},
3691 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3692 		.name = "update_resized",
3693 		.help = "update a flow after table resize",
3694 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3695 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3696 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3697 		.call = parse_qo_destroy,
3698 	},
3699 	[QUEUE_UPDATE] = {
3700 		.name = "update",
3701 		.help = "update a flow rule",
3702 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3703 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3704 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3705 		.call = parse_qo,
3706 	},
3707 	[QUEUE_AGED] = {
3708 		.name = "aged",
3709 		.help = "list and destroy aged flows",
3710 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3711 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3712 		.call = parse_aged,
3713 	},
3714 	[QUEUE_INDIRECT_ACTION] = {
3715 		.name = "indirect_action",
3716 		.help = "queue indirect actions",
3717 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3718 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3719 		.call = parse_qia,
3720 	},
3721 	/* Queue  arguments. */
3722 	[QUEUE_TEMPLATE_TABLE] = {
3723 		.name = "template_table",
3724 		.help = "specify table id",
3725 		.next = NEXT(next_async_insert_subcmd,
3726 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3727 		.args = ARGS(ARGS_ENTRY(struct buffer,
3728 					args.vc.table_id)),
3729 		.call = parse_qo,
3730 	},
3731 	[QUEUE_PATTERN_TEMPLATE] = {
3732 		.name = "pattern_template",
3733 		.help = "specify pattern template index",
3734 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3735 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3736 		.args = ARGS(ARGS_ENTRY(struct buffer,
3737 					args.vc.pat_templ_id)),
3738 		.call = parse_qo,
3739 	},
3740 	[QUEUE_ACTIONS_TEMPLATE] = {
3741 		.name = "actions_template",
3742 		.help = "specify actions template index",
3743 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3744 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3745 		.args = ARGS(ARGS_ENTRY(struct buffer,
3746 					args.vc.act_templ_id)),
3747 		.call = parse_qo,
3748 	},
3749 	[QUEUE_RULE_ID] = {
3750 		.name = "rule_index",
3751 		.help = "specify flow rule index",
3752 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3753 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3754 		.args = ARGS(ARGS_ENTRY(struct buffer,
3755 					args.vc.rule_id)),
3756 		.call = parse_qo,
3757 	},
3758 	[QUEUE_CREATE_POSTPONE] = {
3759 		.name = "postpone",
3760 		.help = "postpone create operation",
3761 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3762 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3763 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3764 		.call = parse_qo,
3765 	},
3766 	[QUEUE_DESTROY_POSTPONE] = {
3767 		.name = "postpone",
3768 		.help = "postpone destroy operation",
3769 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3770 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3771 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3772 		.call = parse_qo_destroy,
3773 	},
3774 	[QUEUE_DESTROY_ID] = {
3775 		.name = "rule",
3776 		.help = "specify rule id to destroy",
3777 		.next = NEXT(next_queue_destroy_attr,
3778 			NEXT_ENTRY(COMMON_UNSIGNED)),
3779 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3780 					    args.destroy.rule)),
3781 		.call = parse_qo_destroy,
3782 	},
3783 	[QUEUE_UPDATE_ID] = {
3784 		.name = "rule",
3785 		.help = "specify rule id to update",
3786 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3787 			NEXT_ENTRY(COMMON_UNSIGNED)),
3788 		.args = ARGS(ARGS_ENTRY(struct buffer,
3789 				     args.vc.rule_id)),
3790 		.call = parse_qo,
3791 	},
3792 	/* Queue indirect action arguments */
3793 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3794 		.name = "create",
3795 		.help = "create indirect action",
3796 		.next = NEXT(next_qia_create_attr),
3797 		.call = parse_qia,
3798 	},
3799 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3800 		.name = "update",
3801 		.help = "update indirect action",
3802 		.next = NEXT(next_qia_update_attr,
3803 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3804 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3805 		.call = parse_qia,
3806 	},
3807 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3808 		.name = "destroy",
3809 		.help = "destroy indirect action",
3810 		.next = NEXT(next_qia_destroy_attr),
3811 		.call = parse_qia_destroy,
3812 	},
3813 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3814 		.name = "query",
3815 		.help = "query indirect action",
3816 		.next = NEXT(next_qia_query_attr,
3817 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3818 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3819 		.call = parse_qia,
3820 	},
3821 	/* Indirect action destroy arguments. */
3822 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3823 		.name = "postpone",
3824 		.help = "postpone destroy operation",
3825 		.next = NEXT(next_qia_destroy_attr,
3826 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3827 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3828 	},
3829 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3830 		.name = "action_id",
3831 		.help = "specify a indirect action id to destroy",
3832 		.next = NEXT(next_qia_destroy_attr,
3833 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3834 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3835 					    args.ia_destroy.action_id)),
3836 		.call = parse_qia_destroy,
3837 	},
3838 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3839 		.name = "query_update",
3840 		.help = "indirect query [and|or] update action",
3841 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3842 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3843 		.call = parse_qia
3844 	},
3845 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3846 		.name = "mode",
3847 		.help = "indirect query [and|or] update action",
3848 		.next = NEXT(next_qia_qu_attr,
3849 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3850 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3851 		.call = parse_qia
3852 	},
3853 	/* Indirect action update arguments. */
3854 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3855 		.name = "postpone",
3856 		.help = "postpone update operation",
3857 		.next = NEXT(next_qia_update_attr,
3858 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3859 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3860 	},
3861 	/* Indirect action update arguments. */
3862 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3863 		.name = "postpone",
3864 		.help = "postpone query operation",
3865 		.next = NEXT(next_qia_query_attr,
3866 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3867 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3868 	},
3869 	/* Indirect action create arguments. */
3870 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3871 		.name = "action_id",
3872 		.help = "specify a indirect action id to create",
3873 		.next = NEXT(next_qia_create_attr,
3874 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3875 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3876 	},
3877 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3878 		.name = "ingress",
3879 		.help = "affect rule to ingress",
3880 		.next = NEXT(next_qia_create_attr),
3881 		.call = parse_qia,
3882 	},
3883 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3884 		.name = "egress",
3885 		.help = "affect rule to egress",
3886 		.next = NEXT(next_qia_create_attr),
3887 		.call = parse_qia,
3888 	},
3889 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3890 		.name = "transfer",
3891 		.help = "affect rule to transfer",
3892 		.next = NEXT(next_qia_create_attr),
3893 		.call = parse_qia,
3894 	},
3895 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3896 		.name = "postpone",
3897 		.help = "postpone create operation",
3898 		.next = NEXT(next_qia_create_attr,
3899 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3900 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3901 	},
3902 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3903 		.name = "action",
3904 		.help = "specify action to create indirect handle",
3905 		.next = NEXT(next_action),
3906 	},
3907 	[QUEUE_INDIRECT_ACTION_LIST] = {
3908 		.name = "list",
3909 		.help = "specify actions for indirect handle list",
3910 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3911 		.call = parse_qia,
3912 	},
3913 	/* Top-level command. */
3914 	[PUSH] = {
3915 		.name = "push",
3916 		.help = "push enqueued operations",
3917 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3918 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3919 		.call = parse_push,
3920 	},
3921 	/* Sub-level commands. */
3922 	[PUSH_QUEUE] = {
3923 		.name = "queue",
3924 		.help = "specify queue id",
3925 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3926 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3927 	},
3928 	/* Top-level command. */
3929 	[PULL] = {
3930 		.name = "pull",
3931 		.help = "pull flow operations results",
3932 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3933 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3934 		.call = parse_pull,
3935 	},
3936 	/* Sub-level commands. */
3937 	[PULL_QUEUE] = {
3938 		.name = "queue",
3939 		.help = "specify queue id",
3940 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3941 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3942 	},
3943 	/* Top-level command. */
3944 	[HASH] = {
3945 		.name = "hash",
3946 		.help = "calculate hash for a given pattern in a given template table",
3947 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3948 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3949 		.call = parse_hash,
3950 	},
3951 	/* Sub-level commands. */
3952 	[HASH_CALC_TABLE] = {
3953 		.name = "template_table",
3954 		.help = "specify table id",
3955 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3956 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3957 		.args = ARGS(ARGS_ENTRY(struct buffer,
3958 					args.vc.table_id)),
3959 		.call = parse_hash,
3960 	},
3961 	[HASH_CALC_ENCAP] = {
3962 		.name = "encap",
3963 		.help = "calculates encap hash",
3964 		.next = NEXT(next_hash_encap_dest_subcmd),
3965 		.call = parse_hash,
3966 	},
3967 	[HASH_CALC_PATTERN_INDEX] = {
3968 		.name = "pattern_template",
3969 		.help = "specify pattern template id",
3970 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3971 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3972 		.args = ARGS(ARGS_ENTRY(struct buffer,
3973 					args.vc.pat_templ_id)),
3974 		.call = parse_hash,
3975 	},
3976 	[ENCAP_HASH_FIELD_SRC_PORT] = {
3977 		.name = "hash_field_sport",
3978 		.help = "the encap hash field is src port",
3979 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3980 		.call = parse_hash,
3981 	},
3982 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
3983 		.name = "hash_field_flow_id",
3984 		.help = "the encap hash field is NVGRE flow id",
3985 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3986 		.call = parse_hash,
3987 	},
3988 	/* Top-level command. */
3989 	[INDIRECT_ACTION] = {
3990 		.name = "indirect_action",
3991 		.type = "{command} {port_id} [{arg} [...]]",
3992 		.help = "manage indirect actions",
3993 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3994 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3995 		.call = parse_ia,
3996 	},
3997 	/* Sub-level commands. */
3998 	[INDIRECT_ACTION_CREATE] = {
3999 		.name = "create",
4000 		.help = "create indirect action",
4001 		.next = NEXT(next_ia_create_attr),
4002 		.call = parse_ia,
4003 	},
4004 	[INDIRECT_ACTION_UPDATE] = {
4005 		.name = "update",
4006 		.help = "update indirect action",
4007 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4008 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4009 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4010 		.call = parse_ia,
4011 	},
4012 	[INDIRECT_ACTION_DESTROY] = {
4013 		.name = "destroy",
4014 		.help = "destroy indirect action",
4015 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4016 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4017 		.call = parse_ia_destroy,
4018 	},
4019 	[INDIRECT_ACTION_QUERY] = {
4020 		.name = "query",
4021 		.help = "query indirect action",
4022 		.next = NEXT(NEXT_ENTRY(END),
4023 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4024 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4025 		.call = parse_ia,
4026 	},
4027 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4028 		.name = "query_update",
4029 		.help = "query [and|or] update",
4030 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4031 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4032 		.call = parse_ia
4033 	},
4034 	[INDIRECT_ACTION_QU_MODE] = {
4035 		.name = "mode",
4036 		.help = "query_update mode",
4037 		.next = NEXT(next_ia_qu_attr,
4038 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4039 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4040 		.call = parse_ia,
4041 	},
4042 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4043 		.name = "mode_name",
4044 		.help = "query-update mode name",
4045 		.call = parse_qu_mode_name,
4046 		.comp = comp_qu_mode_name,
4047 	},
4048 	[VALIDATE] = {
4049 		.name = "validate",
4050 		.help = "check whether a flow rule can be created",
4051 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4052 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4053 		.call = parse_vc,
4054 	},
4055 	[CREATE] = {
4056 		.name = "create",
4057 		.help = "create a flow rule",
4058 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4059 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4060 		.call = parse_vc,
4061 	},
4062 	[DESTROY] = {
4063 		.name = "destroy",
4064 		.help = "destroy specific flow rules",
4065 		.next = NEXT(next_destroy_attr,
4066 			     NEXT_ENTRY(COMMON_PORT_ID)),
4067 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4068 		.call = parse_destroy,
4069 	},
4070 	[FLUSH] = {
4071 		.name = "flush",
4072 		.help = "destroy all flow rules",
4073 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4074 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4075 		.call = parse_flush,
4076 	},
4077 	[DUMP] = {
4078 		.name = "dump",
4079 		.help = "dump single/all flow rules to file",
4080 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4081 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4082 		.call = parse_dump,
4083 	},
4084 	[QUERY] = {
4085 		.name = "query",
4086 		.help = "query an existing flow rule",
4087 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4088 			     NEXT_ENTRY(COMMON_RULE_ID),
4089 			     NEXT_ENTRY(COMMON_PORT_ID)),
4090 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4091 			     ARGS_ENTRY(struct buffer, args.query.rule),
4092 			     ARGS_ENTRY(struct buffer, port)),
4093 		.call = parse_query,
4094 	},
4095 	[LIST] = {
4096 		.name = "list",
4097 		.help = "list existing flow rules",
4098 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4099 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4100 		.call = parse_list,
4101 	},
4102 	[AGED] = {
4103 		.name = "aged",
4104 		.help = "list and destroy aged flows",
4105 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4106 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4107 		.call = parse_aged,
4108 	},
4109 	[ISOLATE] = {
4110 		.name = "isolate",
4111 		.help = "restrict ingress traffic to the defined flow rules",
4112 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4113 			     NEXT_ENTRY(COMMON_PORT_ID)),
4114 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4115 			     ARGS_ENTRY(struct buffer, port)),
4116 		.call = parse_isolate,
4117 	},
4118 	[FLEX] = {
4119 		.name = "flex_item",
4120 		.help = "flex item API",
4121 		.next = NEXT(next_flex_item),
4122 		.call = parse_flex,
4123 	},
4124 	[FLEX_ITEM_INIT] = {
4125 		.name = "init",
4126 		.help = "flex item init",
4127 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4128 			     ARGS_ENTRY(struct buffer, port)),
4129 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4130 			     NEXT_ENTRY(COMMON_PORT_ID)),
4131 		.call = parse_flex
4132 	},
4133 	[FLEX_ITEM_CREATE] = {
4134 		.name = "create",
4135 		.help = "flex item create",
4136 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4137 			     ARGS_ENTRY(struct buffer, args.flex.token),
4138 			     ARGS_ENTRY(struct buffer, port)),
4139 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4140 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4141 			     NEXT_ENTRY(COMMON_PORT_ID)),
4142 		.call = parse_flex
4143 	},
4144 	[FLEX_ITEM_DESTROY] = {
4145 		.name = "destroy",
4146 		.help = "flex item destroy",
4147 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4148 			     ARGS_ENTRY(struct buffer, port)),
4149 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4150 			     NEXT_ENTRY(COMMON_PORT_ID)),
4151 		.call = parse_flex
4152 	},
4153 	[TUNNEL] = {
4154 		.name = "tunnel",
4155 		.help = "new tunnel API",
4156 		.next = NEXT(NEXT_ENTRY
4157 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4158 		.call = parse_tunnel,
4159 	},
4160 	/* Tunnel arguments. */
4161 	[TUNNEL_CREATE] = {
4162 		.name = "create",
4163 		.help = "create new tunnel object",
4164 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4165 			     NEXT_ENTRY(COMMON_PORT_ID)),
4166 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4167 		.call = parse_tunnel,
4168 	},
4169 	[TUNNEL_CREATE_TYPE] = {
4170 		.name = "type",
4171 		.help = "create new tunnel",
4172 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4173 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4174 		.call = parse_tunnel,
4175 	},
4176 	[TUNNEL_DESTROY] = {
4177 		.name = "destroy",
4178 		.help = "destroy tunnel",
4179 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4180 			     NEXT_ENTRY(COMMON_PORT_ID)),
4181 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4182 		.call = parse_tunnel,
4183 	},
4184 	[TUNNEL_DESTROY_ID] = {
4185 		.name = "id",
4186 		.help = "tunnel identifier to destroy",
4187 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4188 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4189 		.call = parse_tunnel,
4190 	},
4191 	[TUNNEL_LIST] = {
4192 		.name = "list",
4193 		.help = "list existing tunnels",
4194 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4195 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4196 		.call = parse_tunnel,
4197 	},
4198 	/* Destroy arguments. */
4199 	[DESTROY_RULE] = {
4200 		.name = "rule",
4201 		.help = "specify a rule identifier",
4202 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4203 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4204 		.call = parse_destroy,
4205 	},
4206 	[DESTROY_IS_USER_ID] = {
4207 		.name = "user_id",
4208 		.help = "rule identifier is user-id",
4209 		.next = NEXT(next_destroy_attr),
4210 		.call = parse_destroy,
4211 	},
4212 	/* Dump arguments. */
4213 	[DUMP_ALL] = {
4214 		.name = "all",
4215 		.help = "dump all",
4216 		.next = NEXT(next_dump_attr),
4217 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4218 		.call = parse_dump,
4219 	},
4220 	[DUMP_ONE] = {
4221 		.name = "rule",
4222 		.help = "dump one rule",
4223 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4224 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4225 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4226 		.call = parse_dump,
4227 	},
4228 	[DUMP_IS_USER_ID] = {
4229 		.name = "user_id",
4230 		.help = "rule identifier is user-id",
4231 		.next = NEXT(next_dump_subcmd),
4232 		.call = parse_dump,
4233 	},
4234 	/* Query arguments. */
4235 	[QUERY_ACTION] = {
4236 		.name = "{action}",
4237 		.type = "ACTION",
4238 		.help = "action to query, must be part of the rule",
4239 		.call = parse_action,
4240 		.comp = comp_action,
4241 	},
4242 	[QUERY_IS_USER_ID] = {
4243 		.name = "user_id",
4244 		.help = "rule identifier is user-id",
4245 		.next = NEXT(next_query_attr),
4246 		.call = parse_query,
4247 	},
4248 	/* List arguments. */
4249 	[LIST_GROUP] = {
4250 		.name = "group",
4251 		.help = "specify a group",
4252 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4253 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4254 		.call = parse_list,
4255 	},
4256 	[AGED_DESTROY] = {
4257 		.name = "destroy",
4258 		.help = "specify aged flows need be destroyed",
4259 		.call = parse_aged,
4260 		.comp = comp_none,
4261 	},
4262 	/* Validate/create attributes. */
4263 	[VC_GROUP] = {
4264 		.name = "group",
4265 		.help = "specify a group",
4266 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4267 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4268 		.call = parse_vc,
4269 	},
4270 	[VC_PRIORITY] = {
4271 		.name = "priority",
4272 		.help = "specify a priority level",
4273 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4274 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4275 		.call = parse_vc,
4276 	},
4277 	[VC_INGRESS] = {
4278 		.name = "ingress",
4279 		.help = "affect rule to ingress",
4280 		.next = NEXT(next_vc_attr),
4281 		.call = parse_vc,
4282 	},
4283 	[VC_EGRESS] = {
4284 		.name = "egress",
4285 		.help = "affect rule to egress",
4286 		.next = NEXT(next_vc_attr),
4287 		.call = parse_vc,
4288 	},
4289 	[VC_TRANSFER] = {
4290 		.name = "transfer",
4291 		.help = "apply rule directly to endpoints found in pattern",
4292 		.next = NEXT(next_vc_attr),
4293 		.call = parse_vc,
4294 	},
4295 	[VC_TUNNEL_SET] = {
4296 		.name = "tunnel_set",
4297 		.help = "tunnel steer rule",
4298 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4299 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4300 		.call = parse_vc,
4301 	},
4302 	[VC_TUNNEL_MATCH] = {
4303 		.name = "tunnel_match",
4304 		.help = "tunnel match rule",
4305 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4306 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4307 		.call = parse_vc,
4308 	},
4309 	[VC_USER_ID] = {
4310 		.name = "user_id",
4311 		.help = "specify a user id to create",
4312 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4313 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4314 		.call = parse_vc,
4315 	},
4316 	/* Validate/create pattern. */
4317 	[ITEM_PATTERN] = {
4318 		.name = "pattern",
4319 		.help = "submit a list of pattern items",
4320 		.next = NEXT(next_item),
4321 		.call = parse_vc,
4322 	},
4323 	[ITEM_PARAM_IS] = {
4324 		.name = "is",
4325 		.help = "match value perfectly (with full bit-mask)",
4326 		.call = parse_vc_spec,
4327 	},
4328 	[ITEM_PARAM_SPEC] = {
4329 		.name = "spec",
4330 		.help = "match value according to configured bit-mask",
4331 		.call = parse_vc_spec,
4332 	},
4333 	[ITEM_PARAM_LAST] = {
4334 		.name = "last",
4335 		.help = "specify upper bound to establish a range",
4336 		.call = parse_vc_spec,
4337 	},
4338 	[ITEM_PARAM_MASK] = {
4339 		.name = "mask",
4340 		.help = "specify bit-mask with relevant bits set to one",
4341 		.call = parse_vc_spec,
4342 	},
4343 	[ITEM_PARAM_PREFIX] = {
4344 		.name = "prefix",
4345 		.help = "generate bit-mask from a prefix length",
4346 		.call = parse_vc_spec,
4347 	},
4348 	[ITEM_NEXT] = {
4349 		.name = "/",
4350 		.help = "specify next pattern item",
4351 		.next = NEXT(next_item),
4352 	},
4353 	[ITEM_END] = {
4354 		.name = "end",
4355 		.help = "end list of pattern items",
4356 		.priv = PRIV_ITEM(END, 0),
4357 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4358 		.call = parse_vc,
4359 	},
4360 	[ITEM_VOID] = {
4361 		.name = "void",
4362 		.help = "no-op pattern item",
4363 		.priv = PRIV_ITEM(VOID, 0),
4364 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4365 		.call = parse_vc,
4366 	},
4367 	[ITEM_INVERT] = {
4368 		.name = "invert",
4369 		.help = "perform actions when pattern does not match",
4370 		.priv = PRIV_ITEM(INVERT, 0),
4371 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4372 		.call = parse_vc,
4373 	},
4374 	[ITEM_ANY] = {
4375 		.name = "any",
4376 		.help = "match any protocol for the current layer",
4377 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4378 		.next = NEXT(item_any),
4379 		.call = parse_vc,
4380 	},
4381 	[ITEM_ANY_NUM] = {
4382 		.name = "num",
4383 		.help = "number of layers covered",
4384 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4385 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4386 	},
4387 	[ITEM_PORT_ID] = {
4388 		.name = "port_id",
4389 		.help = "match traffic from/to a given DPDK port ID",
4390 		.priv = PRIV_ITEM(PORT_ID,
4391 				  sizeof(struct rte_flow_item_port_id)),
4392 		.next = NEXT(item_port_id),
4393 		.call = parse_vc,
4394 	},
4395 	[ITEM_PORT_ID_ID] = {
4396 		.name = "id",
4397 		.help = "DPDK port ID",
4398 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4399 			     item_param),
4400 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4401 	},
4402 	[ITEM_MARK] = {
4403 		.name = "mark",
4404 		.help = "match traffic against value set in previously matched rule",
4405 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4406 		.next = NEXT(item_mark),
4407 		.call = parse_vc,
4408 	},
4409 	[ITEM_MARK_ID] = {
4410 		.name = "id",
4411 		.help = "Integer value to match against",
4412 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4413 			     item_param),
4414 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4415 	},
4416 	[ITEM_RAW] = {
4417 		.name = "raw",
4418 		.help = "match an arbitrary byte string",
4419 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4420 		.next = NEXT(item_raw),
4421 		.call = parse_vc,
4422 	},
4423 	[ITEM_RAW_RELATIVE] = {
4424 		.name = "relative",
4425 		.help = "look for pattern after the previous item",
4426 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4427 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4428 					   relative, 1)),
4429 	},
4430 	[ITEM_RAW_SEARCH] = {
4431 		.name = "search",
4432 		.help = "search pattern from offset (see also limit)",
4433 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4434 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4435 					   search, 1)),
4436 	},
4437 	[ITEM_RAW_OFFSET] = {
4438 		.name = "offset",
4439 		.help = "absolute or relative offset for pattern",
4440 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4441 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4442 	},
4443 	[ITEM_RAW_LIMIT] = {
4444 		.name = "limit",
4445 		.help = "search area limit for start of pattern",
4446 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4447 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4448 	},
4449 	[ITEM_RAW_PATTERN] = {
4450 		.name = "pattern",
4451 		.help = "byte string to look for",
4452 		.next = NEXT(item_raw,
4453 			     NEXT_ENTRY(COMMON_STRING),
4454 			     NEXT_ENTRY(ITEM_PARAM_IS,
4455 					ITEM_PARAM_SPEC,
4456 					ITEM_PARAM_MASK)),
4457 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4458 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4459 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4460 					    ITEM_RAW_PATTERN_SIZE)),
4461 	},
4462 	[ITEM_RAW_PATTERN_HEX] = {
4463 		.name = "pattern_hex",
4464 		.help = "hex string to look for",
4465 		.next = NEXT(item_raw,
4466 			     NEXT_ENTRY(COMMON_HEX),
4467 			     NEXT_ENTRY(ITEM_PARAM_IS,
4468 					ITEM_PARAM_SPEC,
4469 					ITEM_PARAM_MASK)),
4470 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4471 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4472 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4473 					    ITEM_RAW_PATTERN_SIZE)),
4474 	},
4475 	[ITEM_ETH] = {
4476 		.name = "eth",
4477 		.help = "match Ethernet header",
4478 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4479 		.next = NEXT(item_eth),
4480 		.call = parse_vc,
4481 	},
4482 	[ITEM_ETH_DST] = {
4483 		.name = "dst",
4484 		.help = "destination MAC",
4485 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4486 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4487 	},
4488 	[ITEM_ETH_SRC] = {
4489 		.name = "src",
4490 		.help = "source MAC",
4491 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4492 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4493 	},
4494 	[ITEM_ETH_TYPE] = {
4495 		.name = "type",
4496 		.help = "EtherType",
4497 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4498 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4499 	},
4500 	[ITEM_ETH_HAS_VLAN] = {
4501 		.name = "has_vlan",
4502 		.help = "packet header contains VLAN",
4503 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4504 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4505 					   has_vlan, 1)),
4506 	},
4507 	[ITEM_VLAN] = {
4508 		.name = "vlan",
4509 		.help = "match 802.1Q/ad VLAN tag",
4510 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4511 		.next = NEXT(item_vlan),
4512 		.call = parse_vc,
4513 	},
4514 	[ITEM_VLAN_TCI] = {
4515 		.name = "tci",
4516 		.help = "tag control information",
4517 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4518 			     item_param),
4519 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4520 	},
4521 	[ITEM_VLAN_PCP] = {
4522 		.name = "pcp",
4523 		.help = "priority code point",
4524 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4525 			     item_param),
4526 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4527 						  hdr.vlan_tci, "\xe0\x00")),
4528 	},
4529 	[ITEM_VLAN_DEI] = {
4530 		.name = "dei",
4531 		.help = "drop eligible indicator",
4532 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4533 			     item_param),
4534 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4535 						  hdr.vlan_tci, "\x10\x00")),
4536 	},
4537 	[ITEM_VLAN_VID] = {
4538 		.name = "vid",
4539 		.help = "VLAN identifier",
4540 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4541 			     item_param),
4542 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4543 						  hdr.vlan_tci, "\x0f\xff")),
4544 	},
4545 	[ITEM_VLAN_INNER_TYPE] = {
4546 		.name = "inner_type",
4547 		.help = "inner EtherType",
4548 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4549 			     item_param),
4550 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4551 					     hdr.eth_proto)),
4552 	},
4553 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4554 		.name = "has_more_vlan",
4555 		.help = "packet header contains another VLAN",
4556 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4557 			     item_param),
4558 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4559 					   has_more_vlan, 1)),
4560 	},
4561 	[ITEM_IPV4] = {
4562 		.name = "ipv4",
4563 		.help = "match IPv4 header",
4564 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4565 		.next = NEXT(item_ipv4),
4566 		.call = parse_vc,
4567 	},
4568 	[ITEM_IPV4_VER_IHL] = {
4569 		.name = "version_ihl",
4570 		.help = "match header length",
4571 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4572 			     item_param),
4573 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4574 				     hdr.version_ihl)),
4575 	},
4576 	[ITEM_IPV4_TOS] = {
4577 		.name = "tos",
4578 		.help = "type of service",
4579 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4580 			     item_param),
4581 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4582 					     hdr.type_of_service)),
4583 	},
4584 	[ITEM_IPV4_LENGTH] = {
4585 		.name = "length",
4586 		.help = "total length",
4587 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4588 			     item_param),
4589 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4590 					     hdr.total_length)),
4591 	},
4592 	[ITEM_IPV4_ID] = {
4593 		.name = "packet_id",
4594 		.help = "fragment packet id",
4595 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4596 			     item_param),
4597 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4598 					     hdr.packet_id)),
4599 	},
4600 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4601 		.name = "fragment_offset",
4602 		.help = "fragmentation flags and fragment offset",
4603 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4604 			     item_param),
4605 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4606 					     hdr.fragment_offset)),
4607 	},
4608 	[ITEM_IPV4_TTL] = {
4609 		.name = "ttl",
4610 		.help = "time to live",
4611 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4612 			     item_param),
4613 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4614 					     hdr.time_to_live)),
4615 	},
4616 	[ITEM_IPV4_PROTO] = {
4617 		.name = "proto",
4618 		.help = "next protocol ID",
4619 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4620 			     item_param),
4621 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4622 					     hdr.next_proto_id)),
4623 	},
4624 	[ITEM_IPV4_SRC] = {
4625 		.name = "src",
4626 		.help = "source address",
4627 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4628 			     item_param),
4629 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4630 					     hdr.src_addr)),
4631 	},
4632 	[ITEM_IPV4_DST] = {
4633 		.name = "dst",
4634 		.help = "destination address",
4635 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4636 			     item_param),
4637 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4638 					     hdr.dst_addr)),
4639 	},
4640 	[ITEM_IPV6] = {
4641 		.name = "ipv6",
4642 		.help = "match IPv6 header",
4643 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4644 		.next = NEXT(item_ipv6),
4645 		.call = parse_vc,
4646 	},
4647 	[ITEM_IPV6_TC] = {
4648 		.name = "tc",
4649 		.help = "traffic class",
4650 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4651 			     item_param),
4652 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4653 						  hdr.vtc_flow,
4654 						  "\x0f\xf0\x00\x00")),
4655 	},
4656 	[ITEM_IPV6_FLOW] = {
4657 		.name = "flow",
4658 		.help = "flow label",
4659 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4660 			     item_param),
4661 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4662 						  hdr.vtc_flow,
4663 						  "\x00\x0f\xff\xff")),
4664 	},
4665 	[ITEM_IPV6_LEN] = {
4666 		.name = "length",
4667 		.help = "payload length",
4668 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4669 			     item_param),
4670 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4671 					     hdr.payload_len)),
4672 	},
4673 	[ITEM_IPV6_PROTO] = {
4674 		.name = "proto",
4675 		.help = "protocol (next header)",
4676 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4677 			     item_param),
4678 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4679 					     hdr.proto)),
4680 	},
4681 	[ITEM_IPV6_HOP] = {
4682 		.name = "hop",
4683 		.help = "hop limit",
4684 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4685 			     item_param),
4686 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4687 					     hdr.hop_limits)),
4688 	},
4689 	[ITEM_IPV6_SRC] = {
4690 		.name = "src",
4691 		.help = "source address",
4692 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4693 			     item_param),
4694 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4695 					     hdr.src_addr)),
4696 	},
4697 	[ITEM_IPV6_DST] = {
4698 		.name = "dst",
4699 		.help = "destination address",
4700 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4701 			     item_param),
4702 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4703 					     hdr.dst_addr)),
4704 	},
4705 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4706 		.name = "has_frag_ext",
4707 		.help = "fragment packet attribute",
4708 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4709 			     item_param),
4710 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4711 					   has_frag_ext, 1)),
4712 	},
4713 	[ITEM_IPV6_ROUTING_EXT] = {
4714 		.name = "ipv6_routing_ext",
4715 		.help = "match IPv6 routing extension header",
4716 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4717 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4718 		.next = NEXT(item_ipv6_routing_ext),
4719 		.call = parse_vc,
4720 	},
4721 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4722 		.name = "ext_type",
4723 		.help = "match IPv6 routing extension header type",
4724 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4725 			     item_param),
4726 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4727 					     hdr.type)),
4728 	},
4729 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4730 		.name = "ext_next_hdr",
4731 		.help = "match IPv6 routing extension header next header type",
4732 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4733 			     item_param),
4734 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4735 					     hdr.next_hdr)),
4736 	},
4737 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4738 		.name = "ext_seg_left",
4739 		.help = "match IPv6 routing extension header segment left",
4740 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4741 			     item_param),
4742 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4743 					     hdr.segments_left)),
4744 	},
4745 	[ITEM_ICMP] = {
4746 		.name = "icmp",
4747 		.help = "match ICMP header",
4748 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4749 		.next = NEXT(item_icmp),
4750 		.call = parse_vc,
4751 	},
4752 	[ITEM_ICMP_TYPE] = {
4753 		.name = "type",
4754 		.help = "ICMP packet type",
4755 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4756 			     item_param),
4757 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4758 					     hdr.icmp_type)),
4759 	},
4760 	[ITEM_ICMP_CODE] = {
4761 		.name = "code",
4762 		.help = "ICMP packet code",
4763 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4764 			     item_param),
4765 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4766 					     hdr.icmp_code)),
4767 	},
4768 	[ITEM_ICMP_IDENT] = {
4769 		.name = "ident",
4770 		.help = "ICMP packet identifier",
4771 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4772 			     item_param),
4773 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4774 					     hdr.icmp_ident)),
4775 	},
4776 	[ITEM_ICMP_SEQ] = {
4777 		.name = "seq",
4778 		.help = "ICMP packet sequence number",
4779 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4780 			     item_param),
4781 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4782 					     hdr.icmp_seq_nb)),
4783 	},
4784 	[ITEM_UDP] = {
4785 		.name = "udp",
4786 		.help = "match UDP header",
4787 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4788 		.next = NEXT(item_udp),
4789 		.call = parse_vc,
4790 	},
4791 	[ITEM_UDP_SRC] = {
4792 		.name = "src",
4793 		.help = "UDP source port",
4794 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4795 			     item_param),
4796 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4797 					     hdr.src_port)),
4798 	},
4799 	[ITEM_UDP_DST] = {
4800 		.name = "dst",
4801 		.help = "UDP destination port",
4802 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4803 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4804 					     hdr.dst_port)),
4805 	},
4806 	[ITEM_TCP] = {
4807 		.name = "tcp",
4808 		.help = "match TCP header",
4809 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4810 		.next = NEXT(item_tcp),
4811 		.call = parse_vc,
4812 	},
4813 	[ITEM_TCP_SRC] = {
4814 		.name = "src",
4815 		.help = "TCP source port",
4816 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4817 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4818 					     hdr.src_port)),
4819 	},
4820 	[ITEM_TCP_DST] = {
4821 		.name = "dst",
4822 		.help = "TCP destination port",
4823 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4824 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4825 					     hdr.dst_port)),
4826 	},
4827 	[ITEM_TCP_FLAGS] = {
4828 		.name = "flags",
4829 		.help = "TCP flags",
4830 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4831 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4832 					     hdr.tcp_flags)),
4833 	},
4834 	[ITEM_SCTP] = {
4835 		.name = "sctp",
4836 		.help = "match SCTP header",
4837 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4838 		.next = NEXT(item_sctp),
4839 		.call = parse_vc,
4840 	},
4841 	[ITEM_SCTP_SRC] = {
4842 		.name = "src",
4843 		.help = "SCTP source port",
4844 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4845 			     item_param),
4846 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4847 					     hdr.src_port)),
4848 	},
4849 	[ITEM_SCTP_DST] = {
4850 		.name = "dst",
4851 		.help = "SCTP destination port",
4852 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4853 			     item_param),
4854 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4855 					     hdr.dst_port)),
4856 	},
4857 	[ITEM_SCTP_TAG] = {
4858 		.name = "tag",
4859 		.help = "validation tag",
4860 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4861 			     item_param),
4862 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4863 					     hdr.tag)),
4864 	},
4865 	[ITEM_SCTP_CKSUM] = {
4866 		.name = "cksum",
4867 		.help = "checksum",
4868 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4869 			     item_param),
4870 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4871 					     hdr.cksum)),
4872 	},
4873 	[ITEM_VXLAN] = {
4874 		.name = "vxlan",
4875 		.help = "match VXLAN header",
4876 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4877 		.next = NEXT(item_vxlan),
4878 		.call = parse_vc,
4879 	},
4880 	[ITEM_VXLAN_VNI] = {
4881 		.name = "vni",
4882 		.help = "VXLAN identifier",
4883 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4884 			     item_param),
4885 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4886 	},
4887 	[ITEM_VXLAN_LAST_RSVD] = {
4888 		.name = "last_rsvd",
4889 		.help = "VXLAN last reserved bits",
4890 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4891 			     item_param),
4892 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4893 					     hdr.rsvd1)),
4894 	},
4895 	[ITEM_E_TAG] = {
4896 		.name = "e_tag",
4897 		.help = "match E-Tag header",
4898 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4899 		.next = NEXT(item_e_tag),
4900 		.call = parse_vc,
4901 	},
4902 	[ITEM_E_TAG_GRP_ECID_B] = {
4903 		.name = "grp_ecid_b",
4904 		.help = "GRP and E-CID base",
4905 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4906 			     item_param),
4907 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4908 						  rsvd_grp_ecid_b,
4909 						  "\x3f\xff")),
4910 	},
4911 	[ITEM_NVGRE] = {
4912 		.name = "nvgre",
4913 		.help = "match NVGRE header",
4914 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4915 		.next = NEXT(item_nvgre),
4916 		.call = parse_vc,
4917 	},
4918 	[ITEM_NVGRE_TNI] = {
4919 		.name = "tni",
4920 		.help = "virtual subnet ID",
4921 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4922 			     item_param),
4923 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4924 	},
4925 	[ITEM_MPLS] = {
4926 		.name = "mpls",
4927 		.help = "match MPLS header",
4928 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4929 		.next = NEXT(item_mpls),
4930 		.call = parse_vc,
4931 	},
4932 	[ITEM_MPLS_LABEL] = {
4933 		.name = "label",
4934 		.help = "MPLS label",
4935 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4936 			     item_param),
4937 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4938 						  label_tc_s,
4939 						  "\xff\xff\xf0")),
4940 	},
4941 	[ITEM_MPLS_TC] = {
4942 		.name = "tc",
4943 		.help = "MPLS Traffic Class",
4944 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4945 			     item_param),
4946 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4947 						  label_tc_s,
4948 						  "\x00\x00\x0e")),
4949 	},
4950 	[ITEM_MPLS_S] = {
4951 		.name = "s",
4952 		.help = "MPLS Bottom-of-Stack",
4953 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4954 			     item_param),
4955 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4956 						  label_tc_s,
4957 						  "\x00\x00\x01")),
4958 	},
4959 	[ITEM_MPLS_TTL] = {
4960 		.name = "ttl",
4961 		.help = "MPLS Time-to-Live",
4962 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4963 			     item_param),
4964 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
4965 	},
4966 	[ITEM_GRE] = {
4967 		.name = "gre",
4968 		.help = "match GRE header",
4969 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4970 		.next = NEXT(item_gre),
4971 		.call = parse_vc,
4972 	},
4973 	[ITEM_GRE_PROTO] = {
4974 		.name = "protocol",
4975 		.help = "GRE protocol type",
4976 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4977 			     item_param),
4978 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4979 					     protocol)),
4980 	},
4981 	[ITEM_GRE_C_RSVD0_VER] = {
4982 		.name = "c_rsvd0_ver",
4983 		.help =
4984 			"checksum (1b), undefined (1b), key bit (1b),"
4985 			" sequence number (1b), reserved 0 (9b),"
4986 			" version (3b)",
4987 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4988 			     item_param),
4989 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4990 					     c_rsvd0_ver)),
4991 	},
4992 	[ITEM_GRE_C_BIT] = {
4993 		.name = "c_bit",
4994 		.help = "checksum bit (C)",
4995 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
4996 			     item_param),
4997 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4998 						  c_rsvd0_ver,
4999 						  "\x80\x00\x00\x00")),
5000 	},
5001 	[ITEM_GRE_S_BIT] = {
5002 		.name = "s_bit",
5003 		.help = "sequence number bit (S)",
5004 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5005 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5006 						  c_rsvd0_ver,
5007 						  "\x10\x00\x00\x00")),
5008 	},
5009 	[ITEM_GRE_K_BIT] = {
5010 		.name = "k_bit",
5011 		.help = "key bit (K)",
5012 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5013 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5014 						  c_rsvd0_ver,
5015 						  "\x20\x00\x00\x00")),
5016 	},
5017 	[ITEM_FUZZY] = {
5018 		.name = "fuzzy",
5019 		.help = "fuzzy pattern match, expect faster than default",
5020 		.priv = PRIV_ITEM(FUZZY,
5021 				sizeof(struct rte_flow_item_fuzzy)),
5022 		.next = NEXT(item_fuzzy),
5023 		.call = parse_vc,
5024 	},
5025 	[ITEM_FUZZY_THRESH] = {
5026 		.name = "thresh",
5027 		.help = "match accuracy threshold",
5028 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5029 			     item_param),
5030 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5031 					thresh)),
5032 	},
5033 	[ITEM_GTP] = {
5034 		.name = "gtp",
5035 		.help = "match GTP header",
5036 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5037 		.next = NEXT(item_gtp),
5038 		.call = parse_vc,
5039 	},
5040 	[ITEM_GTP_FLAGS] = {
5041 		.name = "v_pt_rsv_flags",
5042 		.help = "GTP flags",
5043 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5044 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5045 					hdr.gtp_hdr_info)),
5046 	},
5047 	[ITEM_GTP_MSG_TYPE] = {
5048 		.name = "msg_type",
5049 		.help = "GTP message type",
5050 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5051 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5052 	},
5053 	[ITEM_GTP_TEID] = {
5054 		.name = "teid",
5055 		.help = "tunnel endpoint identifier",
5056 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5057 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5058 	},
5059 	[ITEM_GTPC] = {
5060 		.name = "gtpc",
5061 		.help = "match GTP header",
5062 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5063 		.next = NEXT(item_gtp),
5064 		.call = parse_vc,
5065 	},
5066 	[ITEM_GTPU] = {
5067 		.name = "gtpu",
5068 		.help = "match GTP header",
5069 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5070 		.next = NEXT(item_gtp),
5071 		.call = parse_vc,
5072 	},
5073 	[ITEM_GENEVE] = {
5074 		.name = "geneve",
5075 		.help = "match GENEVE header",
5076 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5077 		.next = NEXT(item_geneve),
5078 		.call = parse_vc,
5079 	},
5080 	[ITEM_GENEVE_VNI] = {
5081 		.name = "vni",
5082 		.help = "virtual network identifier",
5083 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5084 			     item_param),
5085 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5086 	},
5087 	[ITEM_GENEVE_PROTO] = {
5088 		.name = "protocol",
5089 		.help = "GENEVE protocol type",
5090 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5091 			     item_param),
5092 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5093 					     protocol)),
5094 	},
5095 	[ITEM_GENEVE_OPTLEN] = {
5096 		.name = "optlen",
5097 		.help = "GENEVE options length in dwords",
5098 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5099 			     item_param),
5100 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5101 						  ver_opt_len_o_c_rsvd0,
5102 						  "\x3f\x00")),
5103 	},
5104 	[ITEM_VXLAN_GPE] = {
5105 		.name = "vxlan-gpe",
5106 		.help = "match VXLAN-GPE header",
5107 		.priv = PRIV_ITEM(VXLAN_GPE,
5108 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5109 		.next = NEXT(item_vxlan_gpe),
5110 		.call = parse_vc,
5111 	},
5112 	[ITEM_VXLAN_GPE_VNI] = {
5113 		.name = "vni",
5114 		.help = "VXLAN-GPE identifier",
5115 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5116 			     item_param),
5117 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5118 					     hdr.vni)),
5119 	},
5120 	[ITEM_VXLAN_GPE_PROTO] = {
5121 		.name = "protocol",
5122 		.help = "VXLAN-GPE next protocol",
5123 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5124 			     item_param),
5125 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5126 					     protocol)),
5127 	},
5128 	[ITEM_VXLAN_GPE_FLAGS] = {
5129 		.name = "flags",
5130 		.help = "VXLAN-GPE flags",
5131 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5132 			     item_param),
5133 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5134 					     flags)),
5135 	},
5136 	[ITEM_ARP_ETH_IPV4] = {
5137 		.name = "arp_eth_ipv4",
5138 		.help = "match ARP header for Ethernet/IPv4",
5139 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5140 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5141 		.next = NEXT(item_arp_eth_ipv4),
5142 		.call = parse_vc,
5143 	},
5144 	[ITEM_ARP_ETH_IPV4_SHA] = {
5145 		.name = "sha",
5146 		.help = "sender hardware address",
5147 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5148 			     item_param),
5149 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5150 					     hdr.arp_data.arp_sha)),
5151 	},
5152 	[ITEM_ARP_ETH_IPV4_SPA] = {
5153 		.name = "spa",
5154 		.help = "sender IPv4 address",
5155 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5156 			     item_param),
5157 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5158 					     hdr.arp_data.arp_sip)),
5159 	},
5160 	[ITEM_ARP_ETH_IPV4_THA] = {
5161 		.name = "tha",
5162 		.help = "target hardware address",
5163 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5164 			     item_param),
5165 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5166 					     hdr.arp_data.arp_tha)),
5167 	},
5168 	[ITEM_ARP_ETH_IPV4_TPA] = {
5169 		.name = "tpa",
5170 		.help = "target IPv4 address",
5171 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5172 			     item_param),
5173 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5174 					     hdr.arp_data.arp_tip)),
5175 	},
5176 	[ITEM_IPV6_EXT] = {
5177 		.name = "ipv6_ext",
5178 		.help = "match presence of any IPv6 extension header",
5179 		.priv = PRIV_ITEM(IPV6_EXT,
5180 				  sizeof(struct rte_flow_item_ipv6_ext)),
5181 		.next = NEXT(item_ipv6_ext),
5182 		.call = parse_vc,
5183 	},
5184 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5185 		.name = "next_hdr",
5186 		.help = "next header",
5187 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5188 			     item_param),
5189 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5190 					     next_hdr)),
5191 	},
5192 	[ITEM_IPV6_FRAG_EXT] = {
5193 		.name = "ipv6_frag_ext",
5194 		.help = "match presence of IPv6 fragment extension header",
5195 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5196 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5197 		.next = NEXT(item_ipv6_frag_ext),
5198 		.call = parse_vc,
5199 	},
5200 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5201 		.name = "next_hdr",
5202 		.help = "next header",
5203 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5204 			     item_param),
5205 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5206 					hdr.next_header)),
5207 	},
5208 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5209 		.name = "frag_data",
5210 		.help = "fragment flags and offset",
5211 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5212 			     item_param),
5213 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5214 					     hdr.frag_data)),
5215 	},
5216 	[ITEM_IPV6_FRAG_EXT_ID] = {
5217 		.name = "packet_id",
5218 		.help = "fragment packet id",
5219 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5220 			     item_param),
5221 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5222 					     hdr.id)),
5223 	},
5224 	[ITEM_ICMP6] = {
5225 		.name = "icmp6",
5226 		.help = "match any ICMPv6 header",
5227 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5228 		.next = NEXT(item_icmp6),
5229 		.call = parse_vc,
5230 	},
5231 	[ITEM_ICMP6_TYPE] = {
5232 		.name = "type",
5233 		.help = "ICMPv6 type",
5234 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5235 			     item_param),
5236 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5237 					     type)),
5238 	},
5239 	[ITEM_ICMP6_CODE] = {
5240 		.name = "code",
5241 		.help = "ICMPv6 code",
5242 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5243 			     item_param),
5244 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5245 					     code)),
5246 	},
5247 	[ITEM_ICMP6_ECHO_REQUEST] = {
5248 		.name = "icmp6_echo_request",
5249 		.help = "match ICMPv6 echo request",
5250 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5251 				  sizeof(struct rte_flow_item_icmp6_echo)),
5252 		.next = NEXT(item_icmp6_echo_request),
5253 		.call = parse_vc,
5254 	},
5255 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5256 		.name = "ident",
5257 		.help = "ICMPv6 echo request identifier",
5258 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5259 			     item_param),
5260 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5261 					     hdr.identifier)),
5262 	},
5263 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5264 		.name = "seq",
5265 		.help = "ICMPv6 echo request sequence",
5266 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5267 			     item_param),
5268 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5269 					     hdr.sequence)),
5270 	},
5271 	[ITEM_ICMP6_ECHO_REPLY] = {
5272 		.name = "icmp6_echo_reply",
5273 		.help = "match ICMPv6 echo reply",
5274 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5275 				  sizeof(struct rte_flow_item_icmp6_echo)),
5276 		.next = NEXT(item_icmp6_echo_reply),
5277 		.call = parse_vc,
5278 	},
5279 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5280 		.name = "ident",
5281 		.help = "ICMPv6 echo reply identifier",
5282 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5283 			     item_param),
5284 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5285 					     hdr.identifier)),
5286 	},
5287 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5288 		.name = "seq",
5289 		.help = "ICMPv6 echo reply sequence",
5290 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5291 			     item_param),
5292 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5293 					     hdr.sequence)),
5294 	},
5295 	[ITEM_ICMP6_ND_NS] = {
5296 		.name = "icmp6_nd_ns",
5297 		.help = "match ICMPv6 neighbor discovery solicitation",
5298 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5299 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5300 		.next = NEXT(item_icmp6_nd_ns),
5301 		.call = parse_vc,
5302 	},
5303 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5304 		.name = "target_addr",
5305 		.help = "target address",
5306 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5307 			     item_param),
5308 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5309 					     target_addr)),
5310 	},
5311 	[ITEM_ICMP6_ND_NA] = {
5312 		.name = "icmp6_nd_na",
5313 		.help = "match ICMPv6 neighbor discovery advertisement",
5314 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5315 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5316 		.next = NEXT(item_icmp6_nd_na),
5317 		.call = parse_vc,
5318 	},
5319 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5320 		.name = "target_addr",
5321 		.help = "target address",
5322 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5323 			     item_param),
5324 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5325 					     target_addr)),
5326 	},
5327 	[ITEM_ICMP6_ND_OPT] = {
5328 		.name = "icmp6_nd_opt",
5329 		.help = "match presence of any ICMPv6 neighbor discovery"
5330 			" option",
5331 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5332 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5333 		.next = NEXT(item_icmp6_nd_opt),
5334 		.call = parse_vc,
5335 	},
5336 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5337 		.name = "type",
5338 		.help = "ND option type",
5339 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5340 			     item_param),
5341 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5342 					     type)),
5343 	},
5344 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5345 		.name = "icmp6_nd_opt_sla_eth",
5346 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5347 			" link-layer address option",
5348 		.priv = PRIV_ITEM
5349 			(ICMP6_ND_OPT_SLA_ETH,
5350 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5351 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5352 		.call = parse_vc,
5353 	},
5354 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5355 		.name = "sla",
5356 		.help = "source Ethernet LLA",
5357 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5358 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5359 		.args = ARGS(ARGS_ENTRY_HTON
5360 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5361 	},
5362 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5363 		.name = "icmp6_nd_opt_tla_eth",
5364 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5365 			" link-layer address option",
5366 		.priv = PRIV_ITEM
5367 			(ICMP6_ND_OPT_TLA_ETH,
5368 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5369 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5370 		.call = parse_vc,
5371 	},
5372 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5373 		.name = "tla",
5374 		.help = "target Ethernet LLA",
5375 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5376 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5377 		.args = ARGS(ARGS_ENTRY_HTON
5378 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5379 	},
5380 	[ITEM_META] = {
5381 		.name = "meta",
5382 		.help = "match metadata header",
5383 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5384 		.next = NEXT(item_meta),
5385 		.call = parse_vc,
5386 	},
5387 	[ITEM_META_DATA] = {
5388 		.name = "data",
5389 		.help = "metadata value",
5390 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5391 			     item_param),
5392 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5393 					     data, "\xff\xff\xff\xff")),
5394 	},
5395 	[ITEM_RANDOM] = {
5396 		.name = "random",
5397 		.help = "match random value",
5398 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5399 		.next = NEXT(item_random),
5400 		.call = parse_vc,
5401 	},
5402 	[ITEM_RANDOM_VALUE] = {
5403 		.name = "value",
5404 		.help = "random value",
5405 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5406 			     item_param),
5407 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5408 					     value, "\xff\xff")),
5409 	},
5410 	[ITEM_GRE_KEY] = {
5411 		.name = "gre_key",
5412 		.help = "match GRE key",
5413 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5414 		.next = NEXT(item_gre_key),
5415 		.call = parse_vc,
5416 	},
5417 	[ITEM_GRE_KEY_VALUE] = {
5418 		.name = "value",
5419 		.help = "key value",
5420 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5421 			     item_param),
5422 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5423 	},
5424 	[ITEM_GRE_OPTION] = {
5425 		.name = "gre_option",
5426 		.help = "match GRE optional fields",
5427 		.priv = PRIV_ITEM(GRE_OPTION,
5428 				  sizeof(struct rte_flow_item_gre_opt)),
5429 		.next = NEXT(item_gre_option),
5430 		.call = parse_vc,
5431 	},
5432 	[ITEM_GRE_OPTION_CHECKSUM] = {
5433 		.name = "checksum",
5434 		.help = "match GRE checksum",
5435 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5436 			     item_param),
5437 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5438 					     checksum_rsvd.checksum)),
5439 	},
5440 	[ITEM_GRE_OPTION_KEY] = {
5441 		.name = "key",
5442 		.help = "match GRE key",
5443 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5444 			     item_param),
5445 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5446 					     key.key)),
5447 	},
5448 	[ITEM_GRE_OPTION_SEQUENCE] = {
5449 		.name = "sequence",
5450 		.help = "match GRE sequence",
5451 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5452 			     item_param),
5453 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5454 					     sequence.sequence)),
5455 	},
5456 	[ITEM_GTP_PSC] = {
5457 		.name = "gtp_psc",
5458 		.help = "match GTP extension header with type 0x85",
5459 		.priv = PRIV_ITEM(GTP_PSC,
5460 				sizeof(struct rte_flow_item_gtp_psc)),
5461 		.next = NEXT(item_gtp_psc),
5462 		.call = parse_vc,
5463 	},
5464 	[ITEM_GTP_PSC_QFI] = {
5465 		.name = "qfi",
5466 		.help = "QoS flow identifier",
5467 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5468 			     item_param),
5469 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5470 					hdr.qfi, 6)),
5471 	},
5472 	[ITEM_GTP_PSC_PDU_T] = {
5473 		.name = "pdu_t",
5474 		.help = "PDU type",
5475 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5476 			     item_param),
5477 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5478 					hdr.type, 4)),
5479 	},
5480 	[ITEM_PPPOES] = {
5481 		.name = "pppoes",
5482 		.help = "match PPPoE session header",
5483 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5484 		.next = NEXT(item_pppoes),
5485 		.call = parse_vc,
5486 	},
5487 	[ITEM_PPPOED] = {
5488 		.name = "pppoed",
5489 		.help = "match PPPoE discovery header",
5490 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5491 		.next = NEXT(item_pppoed),
5492 		.call = parse_vc,
5493 	},
5494 	[ITEM_PPPOE_SEID] = {
5495 		.name = "seid",
5496 		.help = "session identifier",
5497 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5498 			     item_param),
5499 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5500 					session_id)),
5501 	},
5502 	[ITEM_PPPOE_PROTO_ID] = {
5503 		.name = "pppoe_proto_id",
5504 		.help = "match PPPoE session protocol identifier",
5505 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5506 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5507 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5508 			     item_param),
5509 		.args = ARGS(ARGS_ENTRY_HTON
5510 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5511 		.call = parse_vc,
5512 	},
5513 	[ITEM_HIGIG2] = {
5514 		.name = "higig2",
5515 		.help = "matches higig2 header",
5516 		.priv = PRIV_ITEM(HIGIG2,
5517 				sizeof(struct rte_flow_item_higig2_hdr)),
5518 		.next = NEXT(item_higig2),
5519 		.call = parse_vc,
5520 	},
5521 	[ITEM_HIGIG2_CLASSIFICATION] = {
5522 		.name = "classification",
5523 		.help = "matches classification of higig2 header",
5524 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5525 			     item_param),
5526 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5527 					hdr.ppt1.classification)),
5528 	},
5529 	[ITEM_HIGIG2_VID] = {
5530 		.name = "vid",
5531 		.help = "matches vid of higig2 header",
5532 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5533 			     item_param),
5534 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5535 					hdr.ppt1.vid)),
5536 	},
5537 	[ITEM_TAG] = {
5538 		.name = "tag",
5539 		.help = "match tag value",
5540 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5541 		.next = NEXT(item_tag),
5542 		.call = parse_vc,
5543 	},
5544 	[ITEM_TAG_DATA] = {
5545 		.name = "data",
5546 		.help = "tag value to match",
5547 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5548 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5549 	},
5550 	[ITEM_TAG_INDEX] = {
5551 		.name = "index",
5552 		.help = "index of tag array to match",
5553 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5554 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5555 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5556 	},
5557 	[ITEM_L2TPV3OIP] = {
5558 		.name = "l2tpv3oip",
5559 		.help = "match L2TPv3 over IP header",
5560 		.priv = PRIV_ITEM(L2TPV3OIP,
5561 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5562 		.next = NEXT(item_l2tpv3oip),
5563 		.call = parse_vc,
5564 	},
5565 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5566 		.name = "session_id",
5567 		.help = "session identifier",
5568 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5569 			     item_param),
5570 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5571 					     session_id)),
5572 	},
5573 	[ITEM_ESP] = {
5574 		.name = "esp",
5575 		.help = "match ESP header",
5576 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5577 		.next = NEXT(item_esp),
5578 		.call = parse_vc,
5579 	},
5580 	[ITEM_ESP_SPI] = {
5581 		.name = "spi",
5582 		.help = "security policy index",
5583 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5584 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5585 				hdr.spi)),
5586 	},
5587 	[ITEM_AH] = {
5588 		.name = "ah",
5589 		.help = "match AH header",
5590 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5591 		.next = NEXT(item_ah),
5592 		.call = parse_vc,
5593 	},
5594 	[ITEM_AH_SPI] = {
5595 		.name = "spi",
5596 		.help = "security parameters index",
5597 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5598 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5599 	},
5600 	[ITEM_PFCP] = {
5601 		.name = "pfcp",
5602 		.help = "match pfcp header",
5603 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5604 		.next = NEXT(item_pfcp),
5605 		.call = parse_vc,
5606 	},
5607 	[ITEM_PFCP_S_FIELD] = {
5608 		.name = "s_field",
5609 		.help = "S field",
5610 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5611 			     item_param),
5612 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5613 				s_field)),
5614 	},
5615 	[ITEM_PFCP_SEID] = {
5616 		.name = "seid",
5617 		.help = "session endpoint identifier",
5618 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5619 			     item_param),
5620 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5621 	},
5622 	[ITEM_ECPRI] = {
5623 		.name = "ecpri",
5624 		.help = "match eCPRI header",
5625 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5626 		.next = NEXT(item_ecpri),
5627 		.call = parse_vc,
5628 	},
5629 	[ITEM_ECPRI_COMMON] = {
5630 		.name = "common",
5631 		.help = "eCPRI common header",
5632 		.next = NEXT(item_ecpri_common),
5633 	},
5634 	[ITEM_ECPRI_COMMON_TYPE] = {
5635 		.name = "type",
5636 		.help = "type of common header",
5637 		.next = NEXT(item_ecpri_common_type),
5638 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5639 	},
5640 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5641 		.name = "iq_data",
5642 		.help = "Type #0: IQ Data",
5643 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5644 					ITEM_NEXT)),
5645 		.call = parse_vc_item_ecpri_type,
5646 	},
5647 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5648 		.name = "pc_id",
5649 		.help = "Physical Channel ID",
5650 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5651 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5652 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5653 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5654 				hdr.type0.pc_id)),
5655 	},
5656 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5657 		.name = "rtc_ctrl",
5658 		.help = "Type #2: Real-Time Control Data",
5659 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5660 					ITEM_NEXT)),
5661 		.call = parse_vc_item_ecpri_type,
5662 	},
5663 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5664 		.name = "rtc_id",
5665 		.help = "Real-Time Control Data ID",
5666 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5667 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5668 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5669 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5670 				hdr.type2.rtc_id)),
5671 	},
5672 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5673 		.name = "delay_measure",
5674 		.help = "Type #5: One-Way Delay Measurement",
5675 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5676 					ITEM_NEXT)),
5677 		.call = parse_vc_item_ecpri_type,
5678 	},
5679 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5680 		.name = "msr_id",
5681 		.help = "Measurement ID",
5682 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5683 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5684 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5685 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5686 				hdr.type5.msr_id)),
5687 	},
5688 	[ITEM_GENEVE_OPT] = {
5689 		.name = "geneve-opt",
5690 		.help = "GENEVE header option",
5691 		.priv = PRIV_ITEM(GENEVE_OPT,
5692 				  sizeof(struct rte_flow_item_geneve_opt) +
5693 				  ITEM_GENEVE_OPT_DATA_SIZE),
5694 		.next = NEXT(item_geneve_opt),
5695 		.call = parse_vc,
5696 	},
5697 	[ITEM_GENEVE_OPT_CLASS]	= {
5698 		.name = "class",
5699 		.help = "GENEVE option class",
5700 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5701 			     item_param),
5702 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5703 					     option_class)),
5704 	},
5705 	[ITEM_GENEVE_OPT_TYPE] = {
5706 		.name = "type",
5707 		.help = "GENEVE option type",
5708 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5709 			     item_param),
5710 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5711 					option_type)),
5712 	},
5713 	[ITEM_GENEVE_OPT_LENGTH] = {
5714 		.name = "length",
5715 		.help = "GENEVE option data length (in 32b words)",
5716 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5717 			     item_param),
5718 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5719 				struct rte_flow_item_geneve_opt, option_len,
5720 				0, 31)),
5721 	},
5722 	[ITEM_GENEVE_OPT_DATA] = {
5723 		.name = "data",
5724 		.help = "GENEVE option data pattern",
5725 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5726 			     item_param),
5727 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5728 			     ARGS_ENTRY_ARB(0, 0),
5729 			     ARGS_ENTRY_ARB
5730 				(sizeof(struct rte_flow_item_geneve_opt),
5731 				ITEM_GENEVE_OPT_DATA_SIZE)),
5732 	},
5733 	[ITEM_INTEGRITY] = {
5734 		.name = "integrity",
5735 		.help = "match packet integrity",
5736 		.priv = PRIV_ITEM(INTEGRITY,
5737 				  sizeof(struct rte_flow_item_integrity)),
5738 		.next = NEXT(item_integrity),
5739 		.call = parse_vc,
5740 	},
5741 	[ITEM_INTEGRITY_LEVEL] = {
5742 		.name = "level",
5743 		.help = "integrity level",
5744 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5745 			     item_param),
5746 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5747 	},
5748 	[ITEM_INTEGRITY_VALUE] = {
5749 		.name = "value",
5750 		.help = "integrity value",
5751 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5752 			     item_param),
5753 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5754 	},
5755 	[ITEM_CONNTRACK] = {
5756 		.name = "conntrack",
5757 		.help = "conntrack state",
5758 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5759 			     item_param),
5760 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5761 	},
5762 	[ITEM_PORT_REPRESENTOR] = {
5763 		.name = "port_representor",
5764 		.help = "match traffic entering the embedded switch from the given ethdev",
5765 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5766 				  sizeof(struct rte_flow_item_ethdev)),
5767 		.next = NEXT(item_port_representor),
5768 		.call = parse_vc,
5769 	},
5770 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5771 		.name = "port_id",
5772 		.help = "ethdev port ID",
5773 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5774 			     item_param),
5775 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5776 	},
5777 	[ITEM_REPRESENTED_PORT] = {
5778 		.name = "represented_port",
5779 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5780 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5781 				  sizeof(struct rte_flow_item_ethdev)),
5782 		.next = NEXT(item_represented_port),
5783 		.call = parse_vc,
5784 	},
5785 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5786 		.name = "ethdev_port_id",
5787 		.help = "ethdev port ID",
5788 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5789 			     item_param),
5790 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5791 	},
5792 	[ITEM_FLEX] = {
5793 		.name = "flex",
5794 		.help = "match flex header",
5795 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5796 		.next = NEXT(item_flex),
5797 		.call = parse_vc,
5798 	},
5799 	[ITEM_FLEX_ITEM_HANDLE] = {
5800 		.name = "item",
5801 		.help = "flex item handle",
5802 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5803 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5804 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5805 	},
5806 	[ITEM_FLEX_PATTERN_HANDLE] = {
5807 		.name = "pattern",
5808 		.help = "flex pattern handle",
5809 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5810 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5811 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5812 	},
5813 	[ITEM_L2TPV2] = {
5814 		.name = "l2tpv2",
5815 		.help = "match L2TPv2 header",
5816 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5817 		.next = NEXT(item_l2tpv2),
5818 		.call = parse_vc,
5819 	},
5820 	[ITEM_L2TPV2_TYPE] = {
5821 		.name = "type",
5822 		.help = "type of l2tpv2",
5823 		.next = NEXT(item_l2tpv2_type),
5824 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5825 	},
5826 	[ITEM_L2TPV2_TYPE_DATA] = {
5827 		.name = "data",
5828 		.help = "Type #7: data message without any options",
5829 		.next = NEXT(item_l2tpv2_type_data),
5830 		.call = parse_vc_item_l2tpv2_type,
5831 	},
5832 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5833 		.name = "tunnel_id",
5834 		.help = "tunnel identifier",
5835 		.next = NEXT(item_l2tpv2_type_data,
5836 			     NEXT_ENTRY(COMMON_UNSIGNED),
5837 			     item_param),
5838 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5839 					     hdr.type7.tunnel_id)),
5840 	},
5841 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5842 		.name = "session_id",
5843 		.help = "session identifier",
5844 		.next = NEXT(item_l2tpv2_type_data,
5845 			     NEXT_ENTRY(COMMON_UNSIGNED),
5846 			     item_param),
5847 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5848 					     hdr.type7.session_id)),
5849 	},
5850 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5851 		.name = "data_l",
5852 		.help = "Type #6: data message with length option",
5853 		.next = NEXT(item_l2tpv2_type_data_l),
5854 		.call = parse_vc_item_l2tpv2_type,
5855 	},
5856 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5857 		.name = "length",
5858 		.help = "message length",
5859 		.next = NEXT(item_l2tpv2_type_data_l,
5860 			     NEXT_ENTRY(COMMON_UNSIGNED),
5861 			     item_param),
5862 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5863 					     hdr.type6.length)),
5864 	},
5865 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5866 		.name = "tunnel_id",
5867 		.help = "tunnel identifier",
5868 		.next = NEXT(item_l2tpv2_type_data_l,
5869 			     NEXT_ENTRY(COMMON_UNSIGNED),
5870 			     item_param),
5871 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5872 					     hdr.type6.tunnel_id)),
5873 	},
5874 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5875 		.name = "session_id",
5876 		.help = "session identifier",
5877 		.next = NEXT(item_l2tpv2_type_data_l,
5878 			     NEXT_ENTRY(COMMON_UNSIGNED),
5879 			     item_param),
5880 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5881 					     hdr.type6.session_id)),
5882 	},
5883 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5884 		.name = "data_s",
5885 		.help = "Type #5: data message with ns, nr option",
5886 		.next = NEXT(item_l2tpv2_type_data_s),
5887 		.call = parse_vc_item_l2tpv2_type,
5888 	},
5889 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5890 		.name = "tunnel_id",
5891 		.help = "tunnel identifier",
5892 		.next = NEXT(item_l2tpv2_type_data_s,
5893 			     NEXT_ENTRY(COMMON_UNSIGNED),
5894 			     item_param),
5895 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5896 					     hdr.type5.tunnel_id)),
5897 	},
5898 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5899 		.name = "session_id",
5900 		.help = "session identifier",
5901 		.next = NEXT(item_l2tpv2_type_data_s,
5902 			     NEXT_ENTRY(COMMON_UNSIGNED),
5903 			     item_param),
5904 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5905 					     hdr.type5.session_id)),
5906 	},
5907 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5908 		.name = "ns",
5909 		.help = "sequence number for message",
5910 		.next = NEXT(item_l2tpv2_type_data_s,
5911 			     NEXT_ENTRY(COMMON_UNSIGNED),
5912 			     item_param),
5913 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5914 					     hdr.type5.ns)),
5915 	},
5916 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5917 		.name = "nr",
5918 		.help = "sequence number for next receive message",
5919 		.next = NEXT(item_l2tpv2_type_data_s,
5920 			     NEXT_ENTRY(COMMON_UNSIGNED),
5921 			     item_param),
5922 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5923 					     hdr.type5.nr)),
5924 	},
5925 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5926 		.name = "data_o",
5927 		.help = "Type #4: data message with offset option",
5928 		.next = NEXT(item_l2tpv2_type_data_o),
5929 		.call = parse_vc_item_l2tpv2_type,
5930 	},
5931 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5932 		.name = "tunnel_id",
5933 		.help = "tunnel identifier",
5934 		.next = NEXT(item_l2tpv2_type_data_o,
5935 			     NEXT_ENTRY(COMMON_UNSIGNED),
5936 			     item_param),
5937 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5938 					     hdr.type4.tunnel_id)),
5939 	},
5940 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5941 		.name = "session_id",
5942 		.help = "session identifier",
5943 		.next = NEXT(item_l2tpv2_type_data_o,
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_O_OFFSET] = {
5950 		.name = "offset_size",
5951 		.help = "the size of offset padding",
5952 		.next = NEXT(item_l2tpv2_type_data_o,
5953 			     NEXT_ENTRY(COMMON_UNSIGNED),
5954 			     item_param),
5955 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5956 					     hdr.type4.offset_size)),
5957 	},
5958 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
5959 		.name = "data_l_s",
5960 		.help = "Type #3: data message contains length, ns, nr "
5961 			"options",
5962 		.next = NEXT(item_l2tpv2_type_data_l_s),
5963 		.call = parse_vc_item_l2tpv2_type,
5964 	},
5965 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
5966 		.name = "length",
5967 		.help = "message length",
5968 		.next = NEXT(item_l2tpv2_type_data_l_s,
5969 			     NEXT_ENTRY(COMMON_UNSIGNED),
5970 			     item_param),
5971 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5972 					     hdr.type3.length)),
5973 	},
5974 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
5975 		.name = "tunnel_id",
5976 		.help = "tunnel identifier",
5977 		.next = NEXT(item_l2tpv2_type_data_l_s,
5978 			     NEXT_ENTRY(COMMON_UNSIGNED),
5979 			     item_param),
5980 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5981 					     hdr.type3.tunnel_id)),
5982 	},
5983 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
5984 		.name = "session_id",
5985 		.help = "session identifier",
5986 		.next = NEXT(item_l2tpv2_type_data_l_s,
5987 			     NEXT_ENTRY(COMMON_UNSIGNED),
5988 			     item_param),
5989 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5990 					     hdr.type3.session_id)),
5991 	},
5992 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
5993 		.name = "ns",
5994 		.help = "sequence number for message",
5995 		.next = NEXT(item_l2tpv2_type_data_l_s,
5996 			     NEXT_ENTRY(COMMON_UNSIGNED),
5997 			     item_param),
5998 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5999 					     hdr.type3.ns)),
6000 	},
6001 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6002 		.name = "nr",
6003 		.help = "sequence number for next receive message",
6004 		.next = NEXT(item_l2tpv2_type_data_l_s,
6005 			     NEXT_ENTRY(COMMON_UNSIGNED),
6006 			     item_param),
6007 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6008 					     hdr.type3.nr)),
6009 	},
6010 	[ITEM_L2TPV2_TYPE_CTRL] = {
6011 		.name = "control",
6012 		.help = "Type #3: conrtol message contains length, ns, nr "
6013 			"options",
6014 		.next = NEXT(item_l2tpv2_type_ctrl),
6015 		.call = parse_vc_item_l2tpv2_type,
6016 	},
6017 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6018 		.name = "length",
6019 		.help = "message length",
6020 		.next = NEXT(item_l2tpv2_type_ctrl,
6021 			     NEXT_ENTRY(COMMON_UNSIGNED),
6022 			     item_param),
6023 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6024 					     hdr.type3.length)),
6025 	},
6026 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6027 		.name = "tunnel_id",
6028 		.help = "tunnel identifier",
6029 		.next = NEXT(item_l2tpv2_type_ctrl,
6030 			     NEXT_ENTRY(COMMON_UNSIGNED),
6031 			     item_param),
6032 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6033 					     hdr.type3.tunnel_id)),
6034 	},
6035 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6036 		.name = "session_id",
6037 		.help = "session identifier",
6038 		.next = NEXT(item_l2tpv2_type_ctrl,
6039 			     NEXT_ENTRY(COMMON_UNSIGNED),
6040 			     item_param),
6041 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6042 					     hdr.type3.session_id)),
6043 	},
6044 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6045 		.name = "ns",
6046 		.help = "sequence number for message",
6047 		.next = NEXT(item_l2tpv2_type_ctrl,
6048 			     NEXT_ENTRY(COMMON_UNSIGNED),
6049 			     item_param),
6050 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6051 					     hdr.type3.ns)),
6052 	},
6053 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6054 		.name = "nr",
6055 		.help = "sequence number for next receive message",
6056 		.next = NEXT(item_l2tpv2_type_ctrl,
6057 			     NEXT_ENTRY(COMMON_UNSIGNED),
6058 			     item_param),
6059 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6060 					     hdr.type3.nr)),
6061 	},
6062 	[ITEM_PPP] = {
6063 		.name = "ppp",
6064 		.help = "match PPP header",
6065 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6066 		.next = NEXT(item_ppp),
6067 		.call = parse_vc,
6068 	},
6069 	[ITEM_PPP_ADDR] = {
6070 		.name = "addr",
6071 		.help = "PPP address",
6072 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6073 			     item_param),
6074 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6075 	},
6076 	[ITEM_PPP_CTRL] = {
6077 		.name = "ctrl",
6078 		.help = "PPP control",
6079 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6080 			     item_param),
6081 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6082 	},
6083 	[ITEM_PPP_PROTO_ID] = {
6084 		.name = "proto_id",
6085 		.help = "PPP protocol identifier",
6086 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6087 			     item_param),
6088 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6089 					hdr.proto_id)),
6090 	},
6091 	[ITEM_METER] = {
6092 		.name = "meter",
6093 		.help = "match meter color",
6094 		.priv = PRIV_ITEM(METER_COLOR,
6095 				  sizeof(struct rte_flow_item_meter_color)),
6096 		.next = NEXT(item_meter),
6097 		.call = parse_vc,
6098 	},
6099 	[ITEM_METER_COLOR] = {
6100 		.name = "color",
6101 		.help = "meter color",
6102 		.next = NEXT(item_meter,
6103 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6104 			     item_param),
6105 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6106 					color)),
6107 	},
6108 	[ITEM_METER_COLOR_NAME] = {
6109 		.name = "color_name",
6110 		.help = "meter color name",
6111 		.call = parse_meter_color,
6112 		.comp = comp_meter_color,
6113 	},
6114 	[ITEM_QUOTA] = {
6115 		.name = "quota",
6116 		.help = "match quota",
6117 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6118 		.next = NEXT(item_quota),
6119 		.call = parse_vc
6120 	},
6121 	[ITEM_QUOTA_STATE] = {
6122 		.name = "quota_state",
6123 		.help = "quota state",
6124 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6125 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6126 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6127 	},
6128 	[ITEM_QUOTA_STATE_NAME] = {
6129 		.name = "state_name",
6130 		.help = "quota state name",
6131 		.call = parse_quota_state_name,
6132 		.comp = comp_quota_state_name
6133 	},
6134 	[ITEM_IB_BTH] = {
6135 		.name = "ib_bth",
6136 		.help = "match ib bth fields",
6137 		.priv = PRIV_ITEM(IB_BTH,
6138 				  sizeof(struct rte_flow_item_ib_bth)),
6139 		.next = NEXT(item_ib_bth),
6140 		.call = parse_vc,
6141 	},
6142 	[ITEM_IB_BTH_OPCODE] = {
6143 		.name = "opcode",
6144 		.help = "match ib bth opcode",
6145 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6146 				 item_param),
6147 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6148 						 hdr.opcode)),
6149 	},
6150 	[ITEM_IB_BTH_PKEY] = {
6151 		.name = "pkey",
6152 		.help = "partition key",
6153 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6154 				 item_param),
6155 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6156 						 hdr.pkey)),
6157 	},
6158 	[ITEM_IB_BTH_DST_QPN] = {
6159 		.name = "dst_qp",
6160 		.help = "destination qp",
6161 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6162 				 item_param),
6163 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6164 						 hdr.dst_qp)),
6165 	},
6166 	[ITEM_IB_BTH_PSN] = {
6167 		.name = "psn",
6168 		.help = "packet sequence number",
6169 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6170 				 item_param),
6171 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6172 						 hdr.psn)),
6173 	},
6174 	[ITEM_PTYPE] = {
6175 		.name = "ptype",
6176 		.help = "match L2/L3/L4 and tunnel information",
6177 		.priv = PRIV_ITEM(PTYPE,
6178 				  sizeof(struct rte_flow_item_ptype)),
6179 		.next = NEXT(item_ptype),
6180 		.call = parse_vc,
6181 	},
6182 	[ITEM_PTYPE_VALUE] = {
6183 		.name = "packet_type",
6184 		.help = "packet type as defined in rte_mbuf_ptype",
6185 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6186 			     item_param),
6187 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6188 	},
6189 	[ITEM_NSH] = {
6190 		.name = "nsh",
6191 		.help = "match NSH header",
6192 		.priv = PRIV_ITEM(NSH,
6193 				  sizeof(struct rte_flow_item_nsh)),
6194 		.next = NEXT(item_nsh),
6195 		.call = parse_vc,
6196 	},
6197 	[ITEM_COMPARE] = {
6198 		.name = "compare",
6199 		.help = "match with the comparison result",
6200 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6201 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6202 		.call = parse_vc,
6203 	},
6204 	[ITEM_COMPARE_OP] = {
6205 		.name = "op",
6206 		.help = "operation type",
6207 		.next = NEXT(item_compare_field,
6208 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6209 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6210 	},
6211 	[ITEM_COMPARE_OP_VALUE] = {
6212 		.name = "{operation}",
6213 		.help = "operation type value",
6214 		.call = parse_vc_compare_op,
6215 		.comp = comp_set_compare_op,
6216 	},
6217 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6218 		.name = "a_type",
6219 		.help = "compared field type",
6220 		.next = NEXT(compare_field_a,
6221 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6222 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6223 	},
6224 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6225 		.name = "{a_type}",
6226 		.help = "compared field type value",
6227 		.call = parse_vc_compare_field_id,
6228 		.comp = comp_set_compare_field_id,
6229 	},
6230 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6231 		.name = "a_level",
6232 		.help = "compared field level",
6233 		.next = NEXT(compare_field_a,
6234 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6235 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6236 	},
6237 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6238 		.name = "{a_level}",
6239 		.help = "compared field level value",
6240 		.call = parse_vc_compare_field_level,
6241 		.comp = comp_none,
6242 	},
6243 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6244 		.name = "a_tag_index",
6245 		.help = "compared field tag array",
6246 		.next = NEXT(compare_field_a,
6247 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6248 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6249 					a.tag_index)),
6250 	},
6251 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6252 		.name = "a_type_id",
6253 		.help = "compared field type ID",
6254 		.next = NEXT(compare_field_a,
6255 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6256 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6257 					a.type)),
6258 	},
6259 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6260 		.name = "a_class",
6261 		.help = "compared field class ID",
6262 		.next = NEXT(compare_field_a,
6263 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6264 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6265 					     a.class_id)),
6266 	},
6267 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6268 		.name = "a_offset",
6269 		.help = "compared field bit offset",
6270 		.next = NEXT(compare_field_a,
6271 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6272 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6273 					a.offset)),
6274 	},
6275 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6276 		.name = "b_type",
6277 		.help = "comparator field type",
6278 		.next = NEXT(compare_field_b,
6279 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6280 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6281 					b.field)),
6282 	},
6283 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6284 		.name = "{b_type}",
6285 		.help = "comparator field type value",
6286 		.call = parse_vc_compare_field_id,
6287 		.comp = comp_set_compare_field_id,
6288 	},
6289 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6290 		.name = "b_level",
6291 		.help = "comparator field level",
6292 		.next = NEXT(compare_field_b,
6293 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6294 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6295 					b.level)),
6296 	},
6297 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6298 		.name = "{b_level}",
6299 		.help = "comparator field level value",
6300 		.call = parse_vc_compare_field_level,
6301 		.comp = comp_none,
6302 	},
6303 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6304 		.name = "b_tag_index",
6305 		.help = "comparator field tag array",
6306 		.next = NEXT(compare_field_b,
6307 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6308 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6309 					b.tag_index)),
6310 	},
6311 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6312 		.name = "b_type_id",
6313 		.help = "comparator field type ID",
6314 		.next = NEXT(compare_field_b,
6315 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6316 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6317 					b.type)),
6318 	},
6319 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6320 		.name = "b_class",
6321 		.help = "comparator field class ID",
6322 		.next = NEXT(compare_field_b,
6323 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6324 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6325 					     b.class_id)),
6326 	},
6327 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6328 		.name = "b_offset",
6329 		.help = "comparator field bit offset",
6330 		.next = NEXT(compare_field_b,
6331 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6332 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6333 					b.offset)),
6334 	},
6335 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6336 		.name = "b_value",
6337 		.help = "comparator immediate value",
6338 		.next = NEXT(compare_field_b,
6339 			     NEXT_ENTRY(COMMON_HEX), item_param),
6340 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6341 			     ARGS_ENTRY_ARB(0, 0),
6342 			     ARGS_ENTRY(struct rte_flow_item_compare,
6343 					b.value)),
6344 	},
6345 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6346 		.name = "b_ptr",
6347 		.help = "pointer to comparator immediate value",
6348 		.next = NEXT(compare_field_b,
6349 			     NEXT_ENTRY(COMMON_HEX), item_param),
6350 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6351 					b.pvalue),
6352 			     ARGS_ENTRY_ARB(0, 0),
6353 			     ARGS_ENTRY_ARB
6354 				(sizeof(struct rte_flow_item_compare),
6355 				 FLOW_FIELD_PATTERN_SIZE)),
6356 	},
6357 	[ITEM_COMPARE_FIELD_WIDTH] = {
6358 		.name = "width",
6359 		.help = "number of bits to compare",
6360 		.next = NEXT(item_compare_field,
6361 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6362 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6363 					width)),
6364 	},
6365 
6366 	/* Validate/create actions. */
6367 	[ACTIONS] = {
6368 		.name = "actions",
6369 		.help = "submit a list of associated actions",
6370 		.next = NEXT(next_action),
6371 		.call = parse_vc,
6372 	},
6373 	[ACTION_NEXT] = {
6374 		.name = "/",
6375 		.help = "specify next action",
6376 		.next = NEXT(next_action),
6377 	},
6378 	[ACTION_END] = {
6379 		.name = "end",
6380 		.help = "end list of actions",
6381 		.priv = PRIV_ACTION(END, 0),
6382 		.call = parse_vc,
6383 	},
6384 	[ACTION_VOID] = {
6385 		.name = "void",
6386 		.help = "no-op action",
6387 		.priv = PRIV_ACTION(VOID, 0),
6388 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6389 		.call = parse_vc,
6390 	},
6391 	[ACTION_PASSTHRU] = {
6392 		.name = "passthru",
6393 		.help = "let subsequent rule process matched packets",
6394 		.priv = PRIV_ACTION(PASSTHRU, 0),
6395 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6396 		.call = parse_vc,
6397 	},
6398 	[ACTION_SKIP_CMAN] = {
6399 		.name = "skip_cman",
6400 		.help = "bypass cman on received packets",
6401 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6402 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6403 		.call = parse_vc,
6404 	},
6405 	[ACTION_JUMP] = {
6406 		.name = "jump",
6407 		.help = "redirect traffic to a given group",
6408 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6409 		.next = NEXT(action_jump),
6410 		.call = parse_vc,
6411 	},
6412 	[ACTION_JUMP_GROUP] = {
6413 		.name = "group",
6414 		.help = "group to redirect traffic to",
6415 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6416 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6417 		.call = parse_vc_conf,
6418 	},
6419 	[ACTION_MARK] = {
6420 		.name = "mark",
6421 		.help = "attach 32 bit value to packets",
6422 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6423 		.next = NEXT(action_mark),
6424 		.call = parse_vc,
6425 	},
6426 	[ACTION_MARK_ID] = {
6427 		.name = "id",
6428 		.help = "32 bit value to return with packets",
6429 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6430 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6431 		.call = parse_vc_conf,
6432 	},
6433 	[ACTION_FLAG] = {
6434 		.name = "flag",
6435 		.help = "flag packets",
6436 		.priv = PRIV_ACTION(FLAG, 0),
6437 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6438 		.call = parse_vc,
6439 	},
6440 	[ACTION_QUEUE] = {
6441 		.name = "queue",
6442 		.help = "assign packets to a given queue index",
6443 		.priv = PRIV_ACTION(QUEUE,
6444 				    sizeof(struct rte_flow_action_queue)),
6445 		.next = NEXT(action_queue),
6446 		.call = parse_vc,
6447 	},
6448 	[ACTION_QUEUE_INDEX] = {
6449 		.name = "index",
6450 		.help = "queue index to use",
6451 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6452 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6453 		.call = parse_vc_conf,
6454 	},
6455 	[ACTION_DROP] = {
6456 		.name = "drop",
6457 		.help = "drop packets (note: passthru has priority)",
6458 		.priv = PRIV_ACTION(DROP, 0),
6459 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6460 		.call = parse_vc,
6461 	},
6462 	[ACTION_COUNT] = {
6463 		.name = "count",
6464 		.help = "enable counters for this rule",
6465 		.priv = PRIV_ACTION(COUNT,
6466 				    sizeof(struct rte_flow_action_count)),
6467 		.next = NEXT(action_count),
6468 		.call = parse_vc,
6469 	},
6470 	[ACTION_COUNT_ID] = {
6471 		.name = "identifier",
6472 		.help = "counter identifier to use",
6473 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6474 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6475 		.call = parse_vc_conf,
6476 	},
6477 	[ACTION_RSS] = {
6478 		.name = "rss",
6479 		.help = "spread packets among several queues",
6480 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6481 		.next = NEXT(action_rss),
6482 		.call = parse_vc_action_rss,
6483 	},
6484 	[ACTION_RSS_FUNC] = {
6485 		.name = "func",
6486 		.help = "RSS hash function to apply",
6487 		.next = NEXT(action_rss,
6488 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6489 					ACTION_RSS_FUNC_TOEPLITZ,
6490 					ACTION_RSS_FUNC_SIMPLE_XOR,
6491 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6492 	},
6493 	[ACTION_RSS_FUNC_DEFAULT] = {
6494 		.name = "default",
6495 		.help = "default hash function",
6496 		.call = parse_vc_action_rss_func,
6497 	},
6498 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6499 		.name = "toeplitz",
6500 		.help = "Toeplitz hash function",
6501 		.call = parse_vc_action_rss_func,
6502 	},
6503 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6504 		.name = "simple_xor",
6505 		.help = "simple XOR hash function",
6506 		.call = parse_vc_action_rss_func,
6507 	},
6508 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6509 		.name = "symmetric_toeplitz",
6510 		.help = "Symmetric Toeplitz hash function",
6511 		.call = parse_vc_action_rss_func,
6512 	},
6513 	[ACTION_RSS_LEVEL] = {
6514 		.name = "level",
6515 		.help = "encapsulation level for \"types\"",
6516 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6517 		.args = ARGS(ARGS_ENTRY_ARB
6518 			     (offsetof(struct action_rss_data, conf) +
6519 			      offsetof(struct rte_flow_action_rss, level),
6520 			      sizeof(((struct rte_flow_action_rss *)0)->
6521 				     level))),
6522 	},
6523 	[ACTION_RSS_TYPES] = {
6524 		.name = "types",
6525 		.help = "specific RSS hash types",
6526 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6527 	},
6528 	[ACTION_RSS_TYPE] = {
6529 		.name = "{type}",
6530 		.help = "RSS hash type",
6531 		.call = parse_vc_action_rss_type,
6532 		.comp = comp_vc_action_rss_type,
6533 	},
6534 	[ACTION_RSS_KEY] = {
6535 		.name = "key",
6536 		.help = "RSS hash key",
6537 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6538 		.args = ARGS(ARGS_ENTRY_ARB
6539 			     (offsetof(struct action_rss_data, conf) +
6540 			      offsetof(struct rte_flow_action_rss, key),
6541 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6542 			     ARGS_ENTRY_ARB
6543 			     (offsetof(struct action_rss_data, conf) +
6544 			      offsetof(struct rte_flow_action_rss, key_len),
6545 			      sizeof(((struct rte_flow_action_rss *)0)->
6546 				     key_len)),
6547 			     ARGS_ENTRY(struct action_rss_data, key)),
6548 	},
6549 	[ACTION_RSS_KEY_LEN] = {
6550 		.name = "key_len",
6551 		.help = "RSS hash key length in bytes",
6552 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6553 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6554 			     (offsetof(struct action_rss_data, conf) +
6555 			      offsetof(struct rte_flow_action_rss, key_len),
6556 			      sizeof(((struct rte_flow_action_rss *)0)->
6557 				     key_len),
6558 			      0,
6559 			      RSS_HASH_KEY_LENGTH)),
6560 	},
6561 	[ACTION_RSS_QUEUES] = {
6562 		.name = "queues",
6563 		.help = "queue indices to use",
6564 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6565 		.call = parse_vc_conf,
6566 	},
6567 	[ACTION_RSS_QUEUE] = {
6568 		.name = "{queue}",
6569 		.help = "queue index",
6570 		.call = parse_vc_action_rss_queue,
6571 		.comp = comp_vc_action_rss_queue,
6572 	},
6573 	[ACTION_PF] = {
6574 		.name = "pf",
6575 		.help = "direct traffic to physical function",
6576 		.priv = PRIV_ACTION(PF, 0),
6577 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6578 		.call = parse_vc,
6579 	},
6580 	[ACTION_VF] = {
6581 		.name = "vf",
6582 		.help = "direct traffic to a virtual function ID",
6583 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6584 		.next = NEXT(action_vf),
6585 		.call = parse_vc,
6586 	},
6587 	[ACTION_VF_ORIGINAL] = {
6588 		.name = "original",
6589 		.help = "use original VF ID if possible",
6590 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6591 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6592 					   original, 1)),
6593 		.call = parse_vc_conf,
6594 	},
6595 	[ACTION_VF_ID] = {
6596 		.name = "id",
6597 		.help = "VF ID",
6598 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6599 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6600 		.call = parse_vc_conf,
6601 	},
6602 	[ACTION_PORT_ID] = {
6603 		.name = "port_id",
6604 		.help = "direct matching traffic to a given DPDK port ID",
6605 		.priv = PRIV_ACTION(PORT_ID,
6606 				    sizeof(struct rte_flow_action_port_id)),
6607 		.next = NEXT(action_port_id),
6608 		.call = parse_vc,
6609 	},
6610 	[ACTION_PORT_ID_ORIGINAL] = {
6611 		.name = "original",
6612 		.help = "use original DPDK port ID if possible",
6613 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6614 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6615 					   original, 1)),
6616 		.call = parse_vc_conf,
6617 	},
6618 	[ACTION_PORT_ID_ID] = {
6619 		.name = "id",
6620 		.help = "DPDK port ID",
6621 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6622 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6623 		.call = parse_vc_conf,
6624 	},
6625 	[ACTION_METER] = {
6626 		.name = "meter",
6627 		.help = "meter the directed packets at given id",
6628 		.priv = PRIV_ACTION(METER,
6629 				    sizeof(struct rte_flow_action_meter)),
6630 		.next = NEXT(action_meter),
6631 		.call = parse_vc,
6632 	},
6633 	[ACTION_METER_COLOR] = {
6634 		.name = "color",
6635 		.help = "meter color for the packets",
6636 		.priv = PRIV_ACTION(METER_COLOR,
6637 				sizeof(struct rte_flow_action_meter_color)),
6638 		.next = NEXT(action_meter_color),
6639 		.call = parse_vc,
6640 	},
6641 	[ACTION_METER_COLOR_TYPE] = {
6642 		.name = "type",
6643 		.help = "specific meter color",
6644 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6645 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6646 					ACTION_METER_COLOR_YELLOW,
6647 					ACTION_METER_COLOR_RED)),
6648 	},
6649 	[ACTION_METER_COLOR_GREEN] = {
6650 		.name = "green",
6651 		.help = "meter color green",
6652 		.call = parse_vc_action_meter_color_type,
6653 	},
6654 	[ACTION_METER_COLOR_YELLOW] = {
6655 		.name = "yellow",
6656 		.help = "meter color yellow",
6657 		.call = parse_vc_action_meter_color_type,
6658 	},
6659 	[ACTION_METER_COLOR_RED] = {
6660 		.name = "red",
6661 		.help = "meter color red",
6662 		.call = parse_vc_action_meter_color_type,
6663 	},
6664 	[ACTION_METER_ID] = {
6665 		.name = "mtr_id",
6666 		.help = "meter id to use",
6667 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6668 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6669 		.call = parse_vc_conf,
6670 	},
6671 	[ACTION_METER_MARK] = {
6672 		.name = "meter_mark",
6673 		.help = "meter the directed packets using profile and policy",
6674 		.priv = PRIV_ACTION(METER_MARK,
6675 				    sizeof(struct rte_flow_action_meter_mark)),
6676 		.next = NEXT(action_meter_mark),
6677 		.call = parse_vc,
6678 	},
6679 	[ACTION_METER_PROFILE] = {
6680 		.name = "mtr_profile",
6681 		.help = "meter profile id to use",
6682 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6683 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6684 	},
6685 	[ACTION_METER_PROFILE_ID2PTR] = {
6686 		.name = "{mtr_profile_id}",
6687 		.type = "PROFILE_ID",
6688 		.help = "meter profile id",
6689 		.next = NEXT(action_meter_mark),
6690 		.call = parse_meter_profile_id2ptr,
6691 		.comp = comp_none,
6692 	},
6693 	[ACTION_METER_POLICY] = {
6694 		.name = "mtr_policy",
6695 		.help = "meter policy id to use",
6696 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6697 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6698 	},
6699 	[ACTION_METER_POLICY_ID2PTR] = {
6700 		.name = "{mtr_policy_id}",
6701 		.type = "POLICY_ID",
6702 		.help = "meter policy id",
6703 		.next = NEXT(action_meter_mark),
6704 		.call = parse_meter_policy_id2ptr,
6705 		.comp = comp_none,
6706 	},
6707 	[ACTION_METER_COLOR_MODE] = {
6708 		.name = "mtr_color_mode",
6709 		.help = "meter color awareness mode",
6710 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6711 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6712 		.call = parse_vc_conf,
6713 	},
6714 	[ACTION_METER_STATE] = {
6715 		.name = "mtr_state",
6716 		.help = "meter state",
6717 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6718 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6719 		.call = parse_vc_conf,
6720 	},
6721 	[ACTION_OF_DEC_NW_TTL] = {
6722 		.name = "of_dec_nw_ttl",
6723 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6724 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6725 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6726 		.call = parse_vc,
6727 	},
6728 	[ACTION_OF_POP_VLAN] = {
6729 		.name = "of_pop_vlan",
6730 		.help = "OpenFlow's OFPAT_POP_VLAN",
6731 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6732 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6733 		.call = parse_vc,
6734 	},
6735 	[ACTION_OF_PUSH_VLAN] = {
6736 		.name = "of_push_vlan",
6737 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6738 		.priv = PRIV_ACTION
6739 			(OF_PUSH_VLAN,
6740 			 sizeof(struct rte_flow_action_of_push_vlan)),
6741 		.next = NEXT(action_of_push_vlan),
6742 		.call = parse_vc,
6743 	},
6744 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6745 		.name = "ethertype",
6746 		.help = "EtherType",
6747 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6748 		.args = ARGS(ARGS_ENTRY_HTON
6749 			     (struct rte_flow_action_of_push_vlan,
6750 			      ethertype)),
6751 		.call = parse_vc_conf,
6752 	},
6753 	[ACTION_OF_SET_VLAN_VID] = {
6754 		.name = "of_set_vlan_vid",
6755 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6756 		.priv = PRIV_ACTION
6757 			(OF_SET_VLAN_VID,
6758 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6759 		.next = NEXT(action_of_set_vlan_vid),
6760 		.call = parse_vc,
6761 	},
6762 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6763 		.name = "vlan_vid",
6764 		.help = "VLAN id",
6765 		.next = NEXT(action_of_set_vlan_vid,
6766 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6767 		.args = ARGS(ARGS_ENTRY_HTON
6768 			     (struct rte_flow_action_of_set_vlan_vid,
6769 			      vlan_vid)),
6770 		.call = parse_vc_conf,
6771 	},
6772 	[ACTION_OF_SET_VLAN_PCP] = {
6773 		.name = "of_set_vlan_pcp",
6774 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6775 		.priv = PRIV_ACTION
6776 			(OF_SET_VLAN_PCP,
6777 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6778 		.next = NEXT(action_of_set_vlan_pcp),
6779 		.call = parse_vc,
6780 	},
6781 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6782 		.name = "vlan_pcp",
6783 		.help = "VLAN priority",
6784 		.next = NEXT(action_of_set_vlan_pcp,
6785 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6786 		.args = ARGS(ARGS_ENTRY_HTON
6787 			     (struct rte_flow_action_of_set_vlan_pcp,
6788 			      vlan_pcp)),
6789 		.call = parse_vc_conf,
6790 	},
6791 	[ACTION_OF_POP_MPLS] = {
6792 		.name = "of_pop_mpls",
6793 		.help = "OpenFlow's OFPAT_POP_MPLS",
6794 		.priv = PRIV_ACTION(OF_POP_MPLS,
6795 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6796 		.next = NEXT(action_of_pop_mpls),
6797 		.call = parse_vc,
6798 	},
6799 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6800 		.name = "ethertype",
6801 		.help = "EtherType",
6802 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6803 		.args = ARGS(ARGS_ENTRY_HTON
6804 			     (struct rte_flow_action_of_pop_mpls,
6805 			      ethertype)),
6806 		.call = parse_vc_conf,
6807 	},
6808 	[ACTION_OF_PUSH_MPLS] = {
6809 		.name = "of_push_mpls",
6810 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6811 		.priv = PRIV_ACTION
6812 			(OF_PUSH_MPLS,
6813 			 sizeof(struct rte_flow_action_of_push_mpls)),
6814 		.next = NEXT(action_of_push_mpls),
6815 		.call = parse_vc,
6816 	},
6817 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6818 		.name = "ethertype",
6819 		.help = "EtherType",
6820 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6821 		.args = ARGS(ARGS_ENTRY_HTON
6822 			     (struct rte_flow_action_of_push_mpls,
6823 			      ethertype)),
6824 		.call = parse_vc_conf,
6825 	},
6826 	[ACTION_VXLAN_ENCAP] = {
6827 		.name = "vxlan_encap",
6828 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6829 			" vxlan\"",
6830 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6831 				    sizeof(struct action_vxlan_encap_data)),
6832 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6833 		.call = parse_vc_action_vxlan_encap,
6834 	},
6835 	[ACTION_VXLAN_DECAP] = {
6836 		.name = "vxlan_decap",
6837 		.help = "Performs a decapsulation action by stripping all"
6838 			" headers of the VXLAN tunnel network overlay from the"
6839 			" matched flow.",
6840 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6841 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6842 		.call = parse_vc,
6843 	},
6844 	[ACTION_NVGRE_ENCAP] = {
6845 		.name = "nvgre_encap",
6846 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6847 			" nvgre\"",
6848 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6849 				    sizeof(struct action_nvgre_encap_data)),
6850 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6851 		.call = parse_vc_action_nvgre_encap,
6852 	},
6853 	[ACTION_NVGRE_DECAP] = {
6854 		.name = "nvgre_decap",
6855 		.help = "Performs a decapsulation action by stripping all"
6856 			" headers of the NVGRE tunnel network overlay from the"
6857 			" matched flow.",
6858 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6859 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6860 		.call = parse_vc,
6861 	},
6862 	[ACTION_L2_ENCAP] = {
6863 		.name = "l2_encap",
6864 		.help = "l2 encap, uses configuration set by"
6865 			" \"set l2_encap\"",
6866 		.priv = PRIV_ACTION(RAW_ENCAP,
6867 				    sizeof(struct action_raw_encap_data)),
6868 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6869 		.call = parse_vc_action_l2_encap,
6870 	},
6871 	[ACTION_L2_DECAP] = {
6872 		.name = "l2_decap",
6873 		.help = "l2 decap, uses configuration set by"
6874 			" \"set l2_decap\"",
6875 		.priv = PRIV_ACTION(RAW_DECAP,
6876 				    sizeof(struct action_raw_decap_data)),
6877 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6878 		.call = parse_vc_action_l2_decap,
6879 	},
6880 	[ACTION_MPLSOGRE_ENCAP] = {
6881 		.name = "mplsogre_encap",
6882 		.help = "mplsogre encapsulation, uses configuration set by"
6883 			" \"set mplsogre_encap\"",
6884 		.priv = PRIV_ACTION(RAW_ENCAP,
6885 				    sizeof(struct action_raw_encap_data)),
6886 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6887 		.call = parse_vc_action_mplsogre_encap,
6888 	},
6889 	[ACTION_MPLSOGRE_DECAP] = {
6890 		.name = "mplsogre_decap",
6891 		.help = "mplsogre decapsulation, uses configuration set by"
6892 			" \"set mplsogre_decap\"",
6893 		.priv = PRIV_ACTION(RAW_DECAP,
6894 				    sizeof(struct action_raw_decap_data)),
6895 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6896 		.call = parse_vc_action_mplsogre_decap,
6897 	},
6898 	[ACTION_MPLSOUDP_ENCAP] = {
6899 		.name = "mplsoudp_encap",
6900 		.help = "mplsoudp encapsulation, uses configuration set by"
6901 			" \"set mplsoudp_encap\"",
6902 		.priv = PRIV_ACTION(RAW_ENCAP,
6903 				    sizeof(struct action_raw_encap_data)),
6904 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6905 		.call = parse_vc_action_mplsoudp_encap,
6906 	},
6907 	[ACTION_MPLSOUDP_DECAP] = {
6908 		.name = "mplsoudp_decap",
6909 		.help = "mplsoudp decapsulation, uses configuration set by"
6910 			" \"set mplsoudp_decap\"",
6911 		.priv = PRIV_ACTION(RAW_DECAP,
6912 				    sizeof(struct action_raw_decap_data)),
6913 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6914 		.call = parse_vc_action_mplsoudp_decap,
6915 	},
6916 	[ACTION_SET_IPV4_SRC] = {
6917 		.name = "set_ipv4_src",
6918 		.help = "Set a new IPv4 source address in the outermost"
6919 			" IPv4 header",
6920 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6921 			sizeof(struct rte_flow_action_set_ipv4)),
6922 		.next = NEXT(action_set_ipv4_src),
6923 		.call = parse_vc,
6924 	},
6925 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6926 		.name = "ipv4_addr",
6927 		.help = "new IPv4 source address to set",
6928 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6929 		.args = ARGS(ARGS_ENTRY_HTON
6930 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6931 		.call = parse_vc_conf,
6932 	},
6933 	[ACTION_SET_IPV4_DST] = {
6934 		.name = "set_ipv4_dst",
6935 		.help = "Set a new IPv4 destination address in the outermost"
6936 			" IPv4 header",
6937 		.priv = PRIV_ACTION(SET_IPV4_DST,
6938 			sizeof(struct rte_flow_action_set_ipv4)),
6939 		.next = NEXT(action_set_ipv4_dst),
6940 		.call = parse_vc,
6941 	},
6942 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6943 		.name = "ipv4_addr",
6944 		.help = "new IPv4 destination address to set",
6945 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6946 		.args = ARGS(ARGS_ENTRY_HTON
6947 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6948 		.call = parse_vc_conf,
6949 	},
6950 	[ACTION_SET_IPV6_SRC] = {
6951 		.name = "set_ipv6_src",
6952 		.help = "Set a new IPv6 source address in the outermost"
6953 			" IPv6 header",
6954 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6955 			sizeof(struct rte_flow_action_set_ipv6)),
6956 		.next = NEXT(action_set_ipv6_src),
6957 		.call = parse_vc,
6958 	},
6959 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
6960 		.name = "ipv6_addr",
6961 		.help = "new IPv6 source address to set",
6962 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6963 		.args = ARGS(ARGS_ENTRY_HTON
6964 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6965 		.call = parse_vc_conf,
6966 	},
6967 	[ACTION_SET_IPV6_DST] = {
6968 		.name = "set_ipv6_dst",
6969 		.help = "Set a new IPv6 destination address in the outermost"
6970 			" IPv6 header",
6971 		.priv = PRIV_ACTION(SET_IPV6_DST,
6972 			sizeof(struct rte_flow_action_set_ipv6)),
6973 		.next = NEXT(action_set_ipv6_dst),
6974 		.call = parse_vc,
6975 	},
6976 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
6977 		.name = "ipv6_addr",
6978 		.help = "new IPv6 destination address to set",
6979 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6980 		.args = ARGS(ARGS_ENTRY_HTON
6981 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6982 		.call = parse_vc_conf,
6983 	},
6984 	[ACTION_SET_TP_SRC] = {
6985 		.name = "set_tp_src",
6986 		.help = "set a new source port number in the outermost"
6987 			" TCP/UDP header",
6988 		.priv = PRIV_ACTION(SET_TP_SRC,
6989 			sizeof(struct rte_flow_action_set_tp)),
6990 		.next = NEXT(action_set_tp_src),
6991 		.call = parse_vc,
6992 	},
6993 	[ACTION_SET_TP_SRC_TP_SRC] = {
6994 		.name = "port",
6995 		.help = "new source port number to set",
6996 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
6997 		.args = ARGS(ARGS_ENTRY_HTON
6998 			     (struct rte_flow_action_set_tp, port)),
6999 		.call = parse_vc_conf,
7000 	},
7001 	[ACTION_SET_TP_DST] = {
7002 		.name = "set_tp_dst",
7003 		.help = "set a new destination port number in the outermost"
7004 			" TCP/UDP header",
7005 		.priv = PRIV_ACTION(SET_TP_DST,
7006 			sizeof(struct rte_flow_action_set_tp)),
7007 		.next = NEXT(action_set_tp_dst),
7008 		.call = parse_vc,
7009 	},
7010 	[ACTION_SET_TP_DST_TP_DST] = {
7011 		.name = "port",
7012 		.help = "new destination port number to set",
7013 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7014 		.args = ARGS(ARGS_ENTRY_HTON
7015 			     (struct rte_flow_action_set_tp, port)),
7016 		.call = parse_vc_conf,
7017 	},
7018 	[ACTION_MAC_SWAP] = {
7019 		.name = "mac_swap",
7020 		.help = "Swap the source and destination MAC addresses"
7021 			" in the outermost Ethernet header",
7022 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7023 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7024 		.call = parse_vc,
7025 	},
7026 	[ACTION_DEC_TTL] = {
7027 		.name = "dec_ttl",
7028 		.help = "decrease network TTL if available",
7029 		.priv = PRIV_ACTION(DEC_TTL, 0),
7030 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7031 		.call = parse_vc,
7032 	},
7033 	[ACTION_SET_TTL] = {
7034 		.name = "set_ttl",
7035 		.help = "set ttl value",
7036 		.priv = PRIV_ACTION(SET_TTL,
7037 			sizeof(struct rte_flow_action_set_ttl)),
7038 		.next = NEXT(action_set_ttl),
7039 		.call = parse_vc,
7040 	},
7041 	[ACTION_SET_TTL_TTL] = {
7042 		.name = "ttl_value",
7043 		.help = "new ttl value to set",
7044 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7045 		.args = ARGS(ARGS_ENTRY_HTON
7046 			     (struct rte_flow_action_set_ttl, ttl_value)),
7047 		.call = parse_vc_conf,
7048 	},
7049 	[ACTION_SET_MAC_SRC] = {
7050 		.name = "set_mac_src",
7051 		.help = "set source mac address",
7052 		.priv = PRIV_ACTION(SET_MAC_SRC,
7053 			sizeof(struct rte_flow_action_set_mac)),
7054 		.next = NEXT(action_set_mac_src),
7055 		.call = parse_vc,
7056 	},
7057 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7058 		.name = "mac_addr",
7059 		.help = "new source mac address",
7060 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7061 		.args = ARGS(ARGS_ENTRY_HTON
7062 			     (struct rte_flow_action_set_mac, mac_addr)),
7063 		.call = parse_vc_conf,
7064 	},
7065 	[ACTION_SET_MAC_DST] = {
7066 		.name = "set_mac_dst",
7067 		.help = "set destination mac address",
7068 		.priv = PRIV_ACTION(SET_MAC_DST,
7069 			sizeof(struct rte_flow_action_set_mac)),
7070 		.next = NEXT(action_set_mac_dst),
7071 		.call = parse_vc,
7072 	},
7073 	[ACTION_SET_MAC_DST_MAC_DST] = {
7074 		.name = "mac_addr",
7075 		.help = "new destination mac address to set",
7076 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7077 		.args = ARGS(ARGS_ENTRY_HTON
7078 			     (struct rte_flow_action_set_mac, mac_addr)),
7079 		.call = parse_vc_conf,
7080 	},
7081 	[ACTION_INC_TCP_SEQ] = {
7082 		.name = "inc_tcp_seq",
7083 		.help = "increase TCP sequence number",
7084 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7085 		.next = NEXT(action_inc_tcp_seq),
7086 		.call = parse_vc,
7087 	},
7088 	[ACTION_INC_TCP_SEQ_VALUE] = {
7089 		.name = "value",
7090 		.help = "the value to increase TCP sequence number by",
7091 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7092 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7093 		.call = parse_vc_conf,
7094 	},
7095 	[ACTION_DEC_TCP_SEQ] = {
7096 		.name = "dec_tcp_seq",
7097 		.help = "decrease TCP sequence number",
7098 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7099 		.next = NEXT(action_dec_tcp_seq),
7100 		.call = parse_vc,
7101 	},
7102 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7103 		.name = "value",
7104 		.help = "the value to decrease TCP sequence number by",
7105 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7106 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7107 		.call = parse_vc_conf,
7108 	},
7109 	[ACTION_INC_TCP_ACK] = {
7110 		.name = "inc_tcp_ack",
7111 		.help = "increase TCP acknowledgment number",
7112 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7113 		.next = NEXT(action_inc_tcp_ack),
7114 		.call = parse_vc,
7115 	},
7116 	[ACTION_INC_TCP_ACK_VALUE] = {
7117 		.name = "value",
7118 		.help = "the value to increase TCP acknowledgment number by",
7119 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7120 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7121 		.call = parse_vc_conf,
7122 	},
7123 	[ACTION_DEC_TCP_ACK] = {
7124 		.name = "dec_tcp_ack",
7125 		.help = "decrease TCP acknowledgment number",
7126 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7127 		.next = NEXT(action_dec_tcp_ack),
7128 		.call = parse_vc,
7129 	},
7130 	[ACTION_DEC_TCP_ACK_VALUE] = {
7131 		.name = "value",
7132 		.help = "the value to decrease TCP acknowledgment number by",
7133 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7134 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7135 		.call = parse_vc_conf,
7136 	},
7137 	[ACTION_RAW_ENCAP] = {
7138 		.name = "raw_encap",
7139 		.help = "encapsulation data, defined by set raw_encap",
7140 		.priv = PRIV_ACTION(RAW_ENCAP,
7141 			sizeof(struct action_raw_encap_data)),
7142 		.next = NEXT(action_raw_encap),
7143 		.call = parse_vc_action_raw_encap,
7144 	},
7145 	[ACTION_RAW_ENCAP_SIZE] = {
7146 		.name = "size",
7147 		.help = "raw encap size",
7148 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7149 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7150 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7151 		.call = parse_vc_conf,
7152 	},
7153 	[ACTION_RAW_ENCAP_INDEX] = {
7154 		.name = "index",
7155 		.help = "the index of raw_encap_confs",
7156 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7157 	},
7158 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7159 		.name = "{index}",
7160 		.type = "UNSIGNED",
7161 		.help = "unsigned integer value",
7162 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7163 		.call = parse_vc_action_raw_encap_index,
7164 		.comp = comp_set_raw_index,
7165 	},
7166 	[ACTION_RAW_DECAP] = {
7167 		.name = "raw_decap",
7168 		.help = "decapsulation data, defined by set raw_encap",
7169 		.priv = PRIV_ACTION(RAW_DECAP,
7170 			sizeof(struct action_raw_decap_data)),
7171 		.next = NEXT(action_raw_decap),
7172 		.call = parse_vc_action_raw_decap,
7173 	},
7174 	[ACTION_RAW_DECAP_INDEX] = {
7175 		.name = "index",
7176 		.help = "the index of raw_encap_confs",
7177 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7178 	},
7179 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7180 		.name = "{index}",
7181 		.type = "UNSIGNED",
7182 		.help = "unsigned integer value",
7183 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7184 		.call = parse_vc_action_raw_decap_index,
7185 		.comp = comp_set_raw_index,
7186 	},
7187 	[ACTION_MODIFY_FIELD] = {
7188 		.name = "modify_field",
7189 		.help = "modify destination field with data from source field",
7190 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7191 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7192 		.call = parse_vc,
7193 	},
7194 	[ACTION_MODIFY_FIELD_OP] = {
7195 		.name = "op",
7196 		.help = "operation type",
7197 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7198 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7199 		.call = parse_vc_conf,
7200 	},
7201 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7202 		.name = "{operation}",
7203 		.help = "operation type value",
7204 		.call = parse_vc_modify_field_op,
7205 		.comp = comp_set_modify_field_op,
7206 	},
7207 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7208 		.name = "dst_type",
7209 		.help = "destination field type",
7210 		.next = NEXT(action_modify_field_dst,
7211 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7212 		.call = parse_vc_conf,
7213 	},
7214 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7215 		.name = "{dst_type}",
7216 		.help = "destination field type value",
7217 		.call = parse_vc_modify_field_id,
7218 		.comp = comp_set_modify_field_id,
7219 	},
7220 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7221 		.name = "dst_level",
7222 		.help = "destination field level",
7223 		.next = NEXT(action_modify_field_dst,
7224 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7225 		.call = parse_vc_conf,
7226 	},
7227 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7228 		.name = "{dst_level}",
7229 		.help = "destination field level value",
7230 		.call = parse_vc_modify_field_level,
7231 		.comp = comp_none,
7232 	},
7233 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7234 		.name = "dst_tag_index",
7235 		.help = "destination field tag array",
7236 		.next = NEXT(action_modify_field_dst,
7237 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7238 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7239 					dst.tag_index)),
7240 		.call = parse_vc_conf,
7241 	},
7242 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7243 		.name = "dst_type_id",
7244 		.help = "destination field type ID",
7245 		.next = NEXT(action_modify_field_dst,
7246 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7247 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7248 					dst.type)),
7249 		.call = parse_vc_conf,
7250 	},
7251 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7252 		.name = "dst_class",
7253 		.help = "destination field class ID",
7254 		.next = NEXT(action_modify_field_dst,
7255 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7256 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7257 					     dst.class_id)),
7258 		.call = parse_vc_conf,
7259 	},
7260 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7261 		.name = "dst_offset",
7262 		.help = "destination field bit offset",
7263 		.next = NEXT(action_modify_field_dst,
7264 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7265 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7266 					dst.offset)),
7267 		.call = parse_vc_conf,
7268 	},
7269 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7270 		.name = "src_type",
7271 		.help = "source field type",
7272 		.next = NEXT(action_modify_field_src,
7273 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7274 		.call = parse_vc_conf,
7275 	},
7276 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7277 		.name = "{src_type}",
7278 		.help = "source field type value",
7279 		.call = parse_vc_modify_field_id,
7280 		.comp = comp_set_modify_field_id,
7281 	},
7282 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7283 		.name = "src_level",
7284 		.help = "source field level",
7285 		.next = NEXT(action_modify_field_src,
7286 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7287 		.call = parse_vc_conf,
7288 	},
7289 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7290 		.name = "{src_level}",
7291 		.help = "source field level value",
7292 		.call = parse_vc_modify_field_level,
7293 		.comp = comp_none,
7294 	},
7295 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7296 		.name = "stc_tag_index",
7297 		.help = "source field tag array",
7298 		.next = NEXT(action_modify_field_src,
7299 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7300 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7301 					src.tag_index)),
7302 		.call = parse_vc_conf,
7303 	},
7304 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7305 		.name = "src_type_id",
7306 		.help = "source field type ID",
7307 		.next = NEXT(action_modify_field_src,
7308 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7309 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7310 					src.type)),
7311 		.call = parse_vc_conf,
7312 	},
7313 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7314 		.name = "src_class",
7315 		.help = "source field class ID",
7316 		.next = NEXT(action_modify_field_src,
7317 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7318 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7319 					     src.class_id)),
7320 		.call = parse_vc_conf,
7321 	},
7322 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7323 		.name = "src_offset",
7324 		.help = "source field bit offset",
7325 		.next = NEXT(action_modify_field_src,
7326 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7327 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7328 					src.offset)),
7329 		.call = parse_vc_conf,
7330 	},
7331 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7332 		.name = "src_value",
7333 		.help = "source immediate value",
7334 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7335 			     NEXT_ENTRY(COMMON_HEX)),
7336 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7337 			     ARGS_ENTRY_ARB(0, 0),
7338 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7339 					src.value)),
7340 		.call = parse_vc_conf,
7341 	},
7342 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7343 		.name = "src_ptr",
7344 		.help = "pointer to source immediate value",
7345 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7346 			     NEXT_ENTRY(COMMON_HEX)),
7347 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7348 					src.pvalue),
7349 			     ARGS_ENTRY_ARB(0, 0),
7350 			     ARGS_ENTRY_ARB
7351 				(sizeof(struct rte_flow_action_modify_field),
7352 				 FLOW_FIELD_PATTERN_SIZE)),
7353 		.call = parse_vc_conf,
7354 	},
7355 	[ACTION_MODIFY_FIELD_WIDTH] = {
7356 		.name = "width",
7357 		.help = "number of bits to copy",
7358 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7359 			NEXT_ENTRY(COMMON_UNSIGNED)),
7360 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7361 					width)),
7362 		.call = parse_vc_conf,
7363 	},
7364 	[ACTION_SEND_TO_KERNEL] = {
7365 		.name = "send_to_kernel",
7366 		.help = "send packets to kernel",
7367 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7368 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7369 		.call = parse_vc,
7370 	},
7371 	[ACTION_IPV6_EXT_REMOVE] = {
7372 		.name = "ipv6_ext_remove",
7373 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7374 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7375 			sizeof(struct action_ipv6_ext_remove_data)),
7376 		.next = NEXT(action_ipv6_ext_remove),
7377 		.call = parse_vc_action_ipv6_ext_remove,
7378 	},
7379 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7380 		.name = "index",
7381 		.help = "the index of ipv6_ext_remove",
7382 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7383 	},
7384 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7385 		.name = "{index}",
7386 		.type = "UNSIGNED",
7387 		.help = "unsigned integer value",
7388 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7389 		.call = parse_vc_action_ipv6_ext_remove_index,
7390 		.comp = comp_set_ipv6_ext_index,
7391 	},
7392 	[ACTION_IPV6_EXT_PUSH] = {
7393 		.name = "ipv6_ext_push",
7394 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7395 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7396 			sizeof(struct action_ipv6_ext_push_data)),
7397 		.next = NEXT(action_ipv6_ext_push),
7398 		.call = parse_vc_action_ipv6_ext_push,
7399 	},
7400 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7401 		.name = "index",
7402 		.help = "the index of ipv6_ext_push",
7403 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7404 	},
7405 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7406 		.name = "{index}",
7407 		.type = "UNSIGNED",
7408 		.help = "unsigned integer value",
7409 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7410 		.call = parse_vc_action_ipv6_ext_push_index,
7411 		.comp = comp_set_ipv6_ext_index,
7412 	},
7413 	[ACTION_NAT64] = {
7414 		.name = "nat64",
7415 		.help = "NAT64 IP headers translation",
7416 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7417 		.next = NEXT(action_nat64),
7418 		.call = parse_vc,
7419 	},
7420 	[ACTION_NAT64_MODE] = {
7421 		.name = "type",
7422 		.help = "NAT64 translation type",
7423 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7424 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7425 		.call = parse_vc_conf,
7426 	},
7427 	/* Top level command. */
7428 	[SET] = {
7429 		.name = "set",
7430 		.help = "set raw encap/decap/sample data",
7431 		.type = "set raw_encap|raw_decap <index> <pattern>"
7432 				" or set sample_actions <index> <action>",
7433 		.next = NEXT(NEXT_ENTRY
7434 			     (SET_RAW_ENCAP,
7435 			      SET_RAW_DECAP,
7436 			      SET_SAMPLE_ACTIONS,
7437 			      SET_IPV6_EXT_REMOVE,
7438 			      SET_IPV6_EXT_PUSH)),
7439 		.call = parse_set_init,
7440 	},
7441 	/* Sub-level commands. */
7442 	[SET_RAW_ENCAP] = {
7443 		.name = "raw_encap",
7444 		.help = "set raw encap data",
7445 		.next = NEXT(next_set_raw),
7446 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7447 				(offsetof(struct buffer, port),
7448 				 sizeof(((struct buffer *)0)->port),
7449 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7450 		.call = parse_set_raw_encap_decap,
7451 	},
7452 	[SET_RAW_DECAP] = {
7453 		.name = "raw_decap",
7454 		.help = "set raw decap data",
7455 		.next = NEXT(next_set_raw),
7456 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7457 				(offsetof(struct buffer, port),
7458 				 sizeof(((struct buffer *)0)->port),
7459 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7460 		.call = parse_set_raw_encap_decap,
7461 	},
7462 	[SET_RAW_INDEX] = {
7463 		.name = "{index}",
7464 		.type = "COMMON_UNSIGNED",
7465 		.help = "index of raw_encap/raw_decap data",
7466 		.next = NEXT(next_item),
7467 		.call = parse_port,
7468 	},
7469 	[SET_SAMPLE_INDEX] = {
7470 		.name = "{index}",
7471 		.type = "UNSIGNED",
7472 		.help = "index of sample actions",
7473 		.next = NEXT(next_action_sample),
7474 		.call = parse_port,
7475 	},
7476 	[SET_SAMPLE_ACTIONS] = {
7477 		.name = "sample_actions",
7478 		.help = "set sample actions list",
7479 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7480 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7481 				(offsetof(struct buffer, port),
7482 				 sizeof(((struct buffer *)0)->port),
7483 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7484 		.call = parse_set_sample_action,
7485 	},
7486 	[SET_IPV6_EXT_PUSH] = {
7487 		.name = "ipv6_ext_push",
7488 		.help = "set IPv6 extension header",
7489 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7490 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7491 				(offsetof(struct buffer, port),
7492 				 sizeof(((struct buffer *)0)->port),
7493 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7494 		.call = parse_set_ipv6_ext_action,
7495 	},
7496 	[SET_IPV6_EXT_REMOVE] = {
7497 		.name = "ipv6_ext_remove",
7498 		.help = "set IPv6 extension header",
7499 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7500 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7501 				(offsetof(struct buffer, port),
7502 				 sizeof(((struct buffer *)0)->port),
7503 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7504 		.call = parse_set_ipv6_ext_action,
7505 	},
7506 	[SET_IPV6_EXT_INDEX] = {
7507 		.name = "{index}",
7508 		.type = "UNSIGNED",
7509 		.help = "index of ipv6 extension push/remove actions",
7510 		.next = NEXT(item_ipv6_push_ext),
7511 		.call = parse_port,
7512 	},
7513 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7514 		.name = "ipv6_ext",
7515 		.help = "set IPv6 extension header",
7516 		.priv = PRIV_ITEM(IPV6_EXT,
7517 				  sizeof(struct rte_flow_item_ipv6_ext)),
7518 		.next = NEXT(item_ipv6_push_ext_type),
7519 		.call = parse_vc,
7520 	},
7521 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7522 		.name = "type",
7523 		.help = "set IPv6 extension type",
7524 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7525 					     next_hdr)),
7526 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7527 			     item_param),
7528 	},
7529 	[ACTION_SET_TAG] = {
7530 		.name = "set_tag",
7531 		.help = "set tag",
7532 		.priv = PRIV_ACTION(SET_TAG,
7533 			sizeof(struct rte_flow_action_set_tag)),
7534 		.next = NEXT(action_set_tag),
7535 		.call = parse_vc,
7536 	},
7537 	[ACTION_SET_TAG_INDEX] = {
7538 		.name = "index",
7539 		.help = "index of tag array",
7540 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7541 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7542 		.call = parse_vc_conf,
7543 	},
7544 	[ACTION_SET_TAG_DATA] = {
7545 		.name = "data",
7546 		.help = "tag value",
7547 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7548 		.args = ARGS(ARGS_ENTRY
7549 			     (struct rte_flow_action_set_tag, data)),
7550 		.call = parse_vc_conf,
7551 	},
7552 	[ACTION_SET_TAG_MASK] = {
7553 		.name = "mask",
7554 		.help = "mask for tag value",
7555 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7556 		.args = ARGS(ARGS_ENTRY
7557 			     (struct rte_flow_action_set_tag, mask)),
7558 		.call = parse_vc_conf,
7559 	},
7560 	[ACTION_SET_META] = {
7561 		.name = "set_meta",
7562 		.help = "set metadata",
7563 		.priv = PRIV_ACTION(SET_META,
7564 			sizeof(struct rte_flow_action_set_meta)),
7565 		.next = NEXT(action_set_meta),
7566 		.call = parse_vc_action_set_meta,
7567 	},
7568 	[ACTION_SET_META_DATA] = {
7569 		.name = "data",
7570 		.help = "metadata value",
7571 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7572 		.args = ARGS(ARGS_ENTRY
7573 			     (struct rte_flow_action_set_meta, data)),
7574 		.call = parse_vc_conf,
7575 	},
7576 	[ACTION_SET_META_MASK] = {
7577 		.name = "mask",
7578 		.help = "mask for metadata value",
7579 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7580 		.args = ARGS(ARGS_ENTRY
7581 			     (struct rte_flow_action_set_meta, mask)),
7582 		.call = parse_vc_conf,
7583 	},
7584 	[ACTION_SET_IPV4_DSCP] = {
7585 		.name = "set_ipv4_dscp",
7586 		.help = "set DSCP value",
7587 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7588 			sizeof(struct rte_flow_action_set_dscp)),
7589 		.next = NEXT(action_set_ipv4_dscp),
7590 		.call = parse_vc,
7591 	},
7592 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7593 		.name = "dscp_value",
7594 		.help = "new IPv4 DSCP value to set",
7595 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7596 		.args = ARGS(ARGS_ENTRY
7597 			     (struct rte_flow_action_set_dscp, dscp)),
7598 		.call = parse_vc_conf,
7599 	},
7600 	[ACTION_SET_IPV6_DSCP] = {
7601 		.name = "set_ipv6_dscp",
7602 		.help = "set DSCP value",
7603 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7604 			sizeof(struct rte_flow_action_set_dscp)),
7605 		.next = NEXT(action_set_ipv6_dscp),
7606 		.call = parse_vc,
7607 	},
7608 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7609 		.name = "dscp_value",
7610 		.help = "new IPv6 DSCP value to set",
7611 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7612 		.args = ARGS(ARGS_ENTRY
7613 			     (struct rte_flow_action_set_dscp, dscp)),
7614 		.call = parse_vc_conf,
7615 	},
7616 	[ACTION_AGE] = {
7617 		.name = "age",
7618 		.help = "set a specific metadata header",
7619 		.next = NEXT(action_age),
7620 		.priv = PRIV_ACTION(AGE,
7621 			sizeof(struct rte_flow_action_age)),
7622 		.call = parse_vc,
7623 	},
7624 	[ACTION_AGE_TIMEOUT] = {
7625 		.name = "timeout",
7626 		.help = "flow age timeout value",
7627 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7628 					   timeout, 24)),
7629 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7630 		.call = parse_vc_conf,
7631 	},
7632 	[ACTION_AGE_UPDATE] = {
7633 		.name = "age_update",
7634 		.help = "update aging parameter",
7635 		.next = NEXT(action_age_update),
7636 		.priv = PRIV_ACTION(AGE,
7637 				    sizeof(struct rte_flow_update_age)),
7638 		.call = parse_vc,
7639 	},
7640 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7641 		.name = "timeout",
7642 		.help = "age timeout update value",
7643 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7644 					   timeout, 24)),
7645 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7646 		.call = parse_vc_conf_timeout,
7647 	},
7648 	[ACTION_AGE_UPDATE_TOUCH] = {
7649 		.name = "touch",
7650 		.help = "this flow is touched",
7651 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7652 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7653 					   touch, 1)),
7654 		.call = parse_vc_conf,
7655 	},
7656 	[ACTION_SAMPLE] = {
7657 		.name = "sample",
7658 		.help = "set a sample action",
7659 		.next = NEXT(action_sample),
7660 		.priv = PRIV_ACTION(SAMPLE,
7661 			sizeof(struct action_sample_data)),
7662 		.call = parse_vc_action_sample,
7663 	},
7664 	[ACTION_SAMPLE_RATIO] = {
7665 		.name = "ratio",
7666 		.help = "flow sample ratio value",
7667 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7668 		.args = ARGS(ARGS_ENTRY_ARB
7669 			     (offsetof(struct action_sample_data, conf) +
7670 			      offsetof(struct rte_flow_action_sample, ratio),
7671 			      sizeof(((struct rte_flow_action_sample *)0)->
7672 				     ratio))),
7673 	},
7674 	[ACTION_SAMPLE_INDEX] = {
7675 		.name = "index",
7676 		.help = "the index of sample actions list",
7677 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7678 	},
7679 	[ACTION_SAMPLE_INDEX_VALUE] = {
7680 		.name = "{index}",
7681 		.type = "COMMON_UNSIGNED",
7682 		.help = "unsigned integer value",
7683 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7684 		.call = parse_vc_action_sample_index,
7685 		.comp = comp_set_sample_index,
7686 	},
7687 	[ACTION_CONNTRACK] = {
7688 		.name = "conntrack",
7689 		.help = "create a conntrack object",
7690 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7691 		.priv = PRIV_ACTION(CONNTRACK,
7692 				    sizeof(struct rte_flow_action_conntrack)),
7693 		.call = parse_vc,
7694 	},
7695 	[ACTION_CONNTRACK_UPDATE] = {
7696 		.name = "conntrack_update",
7697 		.help = "update a conntrack object",
7698 		.next = NEXT(action_update_conntrack),
7699 		.priv = PRIV_ACTION(CONNTRACK,
7700 				    sizeof(struct rte_flow_modify_conntrack)),
7701 		.call = parse_vc,
7702 	},
7703 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7704 		.name = "dir",
7705 		.help = "update a conntrack object direction",
7706 		.next = NEXT(action_update_conntrack),
7707 		.call = parse_vc_action_conntrack_update,
7708 	},
7709 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7710 		.name = "ctx",
7711 		.help = "update a conntrack object context",
7712 		.next = NEXT(action_update_conntrack),
7713 		.call = parse_vc_action_conntrack_update,
7714 	},
7715 	[ACTION_PORT_REPRESENTOR] = {
7716 		.name = "port_representor",
7717 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7718 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7719 				    sizeof(struct rte_flow_action_ethdev)),
7720 		.next = NEXT(action_port_representor),
7721 		.call = parse_vc,
7722 	},
7723 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7724 		.name = "port_id",
7725 		.help = "ethdev port ID",
7726 		.next = NEXT(action_port_representor,
7727 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7728 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7729 					port_id)),
7730 		.call = parse_vc_conf,
7731 	},
7732 	[ACTION_REPRESENTED_PORT] = {
7733 		.name = "represented_port",
7734 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7735 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7736 				sizeof(struct rte_flow_action_ethdev)),
7737 		.next = NEXT(action_represented_port),
7738 		.call = parse_vc,
7739 	},
7740 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7741 		.name = "ethdev_port_id",
7742 		.help = "ethdev port ID",
7743 		.next = NEXT(action_represented_port,
7744 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7745 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7746 					port_id)),
7747 		.call = parse_vc_conf,
7748 	},
7749 	/* Indirect action destroy arguments. */
7750 	[INDIRECT_ACTION_DESTROY_ID] = {
7751 		.name = "action_id",
7752 		.help = "specify a indirect action id to destroy",
7753 		.next = NEXT(next_ia_destroy_attr,
7754 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7755 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7756 					    args.ia_destroy.action_id)),
7757 		.call = parse_ia_destroy,
7758 	},
7759 	/* Indirect action create arguments. */
7760 	[INDIRECT_ACTION_CREATE_ID] = {
7761 		.name = "action_id",
7762 		.help = "specify a indirect action id to create",
7763 		.next = NEXT(next_ia_create_attr,
7764 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7765 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7766 	},
7767 	[ACTION_INDIRECT] = {
7768 		.name = "indirect",
7769 		.help = "apply indirect action by id",
7770 		.priv = PRIV_ACTION(INDIRECT, 0),
7771 		.next = NEXT(next_ia),
7772 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7773 		.call = parse_vc,
7774 	},
7775 	[ACTION_INDIRECT_LIST] = {
7776 		.name = "indirect_list",
7777 		.help = "apply indirect list action by id",
7778 		.priv = PRIV_ACTION(INDIRECT_LIST,
7779 				    sizeof(struct
7780 					   rte_flow_action_indirect_list)),
7781 		.next = NEXT(next_ial),
7782 		.call = parse_vc,
7783 	},
7784 	[ACTION_INDIRECT_LIST_HANDLE] = {
7785 		.name = "handle",
7786 		.help = "indirect list handle",
7787 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7788 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7789 	},
7790 	[ACTION_INDIRECT_LIST_CONF] = {
7791 		.name = "conf",
7792 		.help = "indirect list configuration",
7793 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7794 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7795 	},
7796 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7797 		.type = "UNSIGNED",
7798 		.help = "unsigned integer value",
7799 		.call = parse_indlst_id2ptr,
7800 	},
7801 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7802 		.type = "UNSIGNED",
7803 		.help = "unsigned integer value",
7804 		.call = parse_indlst_id2ptr,
7805 	},
7806 	[ACTION_SHARED_INDIRECT] = {
7807 		.name = "shared_indirect",
7808 		.help = "apply indirect action by id and port",
7809 		.priv = PRIV_ACTION(INDIRECT, 0),
7810 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7811 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7812 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7813 		.call = parse_vc,
7814 	},
7815 	[INDIRECT_ACTION_PORT] = {
7816 		.name = "{indirect_action_port}",
7817 		.type = "INDIRECT_ACTION_PORT",
7818 		.help = "indirect action port",
7819 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7820 		.call = parse_ia_port,
7821 		.comp = comp_none,
7822 	},
7823 	[INDIRECT_ACTION_ID2PTR] = {
7824 		.name = "{action_id}",
7825 		.type = "INDIRECT_ACTION_ID",
7826 		.help = "indirect action id",
7827 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7828 		.call = parse_ia_id2ptr,
7829 		.comp = comp_none,
7830 	},
7831 	[INDIRECT_ACTION_INGRESS] = {
7832 		.name = "ingress",
7833 		.help = "affect rule to ingress",
7834 		.next = NEXT(next_ia_create_attr),
7835 		.call = parse_ia,
7836 	},
7837 	[INDIRECT_ACTION_EGRESS] = {
7838 		.name = "egress",
7839 		.help = "affect rule to egress",
7840 		.next = NEXT(next_ia_create_attr),
7841 		.call = parse_ia,
7842 	},
7843 	[INDIRECT_ACTION_TRANSFER] = {
7844 		.name = "transfer",
7845 		.help = "affect rule to transfer",
7846 		.next = NEXT(next_ia_create_attr),
7847 		.call = parse_ia,
7848 	},
7849 	[INDIRECT_ACTION_SPEC] = {
7850 		.name = "action",
7851 		.help = "specify action to create indirect handle",
7852 		.next = NEXT(next_action),
7853 	},
7854 	[INDIRECT_ACTION_LIST] = {
7855 		.name = "list",
7856 		.help = "specify actions for indirect handle list",
7857 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7858 		.call = parse_ia,
7859 	},
7860 	[INDIRECT_ACTION_FLOW_CONF] = {
7861 		.name = "flow_conf",
7862 		.help = "specify actions configuration for indirect handle list",
7863 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7864 		.call = parse_ia,
7865 	},
7866 	[ACTION_POL_G] = {
7867 		.name = "g_actions",
7868 		.help = "submit a list of associated actions for green",
7869 		.next = NEXT(next_action),
7870 		.call = parse_mp,
7871 	},
7872 	[ACTION_POL_Y] = {
7873 		.name = "y_actions",
7874 		.help = "submit a list of associated actions for yellow",
7875 		.next = NEXT(next_action),
7876 	},
7877 	[ACTION_POL_R] = {
7878 		.name = "r_actions",
7879 		.help = "submit a list of associated actions for red",
7880 		.next = NEXT(next_action),
7881 	},
7882 	[ACTION_QUOTA_CREATE] = {
7883 		.name = "quota_create",
7884 		.help = "create quota action",
7885 		.priv = PRIV_ACTION(QUOTA,
7886 				    sizeof(struct rte_flow_action_quota)),
7887 		.next = NEXT(action_quota_create),
7888 		.call = parse_vc
7889 	},
7890 	[ACTION_QUOTA_CREATE_LIMIT] = {
7891 		.name = "limit",
7892 		.help = "quota limit",
7893 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
7894 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
7895 		.call = parse_vc_conf
7896 	},
7897 	[ACTION_QUOTA_CREATE_MODE] = {
7898 		.name = "mode",
7899 		.help = "quota mode",
7900 		.next = NEXT(action_quota_create,
7901 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
7902 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
7903 		.call = parse_vc_conf
7904 	},
7905 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
7906 		.name = "mode_name",
7907 		.help = "quota mode name",
7908 		.call = parse_quota_mode_name,
7909 		.comp = comp_quota_mode_name
7910 	},
7911 	[ACTION_QUOTA_QU] = {
7912 		.name = "quota_update",
7913 		.help = "update quota action",
7914 		.priv = PRIV_ACTION(QUOTA,
7915 				    sizeof(struct rte_flow_update_quota)),
7916 		.next = NEXT(action_quota_update),
7917 		.call = parse_vc
7918 	},
7919 	[ACTION_QUOTA_QU_LIMIT] = {
7920 		.name = "limit",
7921 		.help = "quota limit",
7922 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7923 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
7924 		.call = parse_vc_conf
7925 	},
7926 	[ACTION_QUOTA_QU_UPDATE_OP] = {
7927 		.name = "update_op",
7928 		.help = "query update op SET|ADD",
7929 		.next = NEXT(action_quota_update,
7930 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
7931 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
7932 		.call = parse_vc_conf
7933 	},
7934 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
7935 		.name = "update_op_name",
7936 		.help = "quota update op name",
7937 		.call = parse_quota_update_name,
7938 		.comp = comp_quota_update_name
7939 	},
7940 
7941 	/* Top-level command. */
7942 	[ADD] = {
7943 		.name = "add",
7944 		.type = "port meter policy {port_id} {arg}",
7945 		.help = "add port meter policy",
7946 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
7947 		.call = parse_init,
7948 	},
7949 	/* Sub-level commands. */
7950 	[ITEM_POL_PORT] = {
7951 		.name = "port",
7952 		.help = "add port meter policy",
7953 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
7954 	},
7955 	[ITEM_POL_METER] = {
7956 		.name = "meter",
7957 		.help = "add port meter policy",
7958 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
7959 	},
7960 	[ITEM_POL_POLICY] = {
7961 		.name = "policy",
7962 		.help = "add port meter policy",
7963 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
7964 				NEXT_ENTRY(ACTION_POL_Y),
7965 				NEXT_ENTRY(ACTION_POL_G),
7966 				NEXT_ENTRY(COMMON_POLICY_ID),
7967 				NEXT_ENTRY(COMMON_PORT_ID)),
7968 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
7969 				ARGS_ENTRY(struct buffer, port)),
7970 		.call = parse_mp,
7971 	},
7972 	[ITEM_AGGR_AFFINITY] = {
7973 		.name = "aggr_affinity",
7974 		.help = "match on the aggregated port receiving the packets",
7975 		.priv = PRIV_ITEM(AGGR_AFFINITY,
7976 				  sizeof(struct rte_flow_item_aggr_affinity)),
7977 		.next = NEXT(item_aggr_affinity),
7978 		.call = parse_vc,
7979 	},
7980 	[ITEM_AGGR_AFFINITY_VALUE] = {
7981 		.name = "affinity",
7982 		.help = "aggregated affinity value",
7983 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
7984 			     item_param),
7985 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
7986 					affinity)),
7987 	},
7988 	[ITEM_TX_QUEUE] = {
7989 		.name = "tx_queue",
7990 		.help = "match on the tx queue of send packet",
7991 		.priv = PRIV_ITEM(TX_QUEUE,
7992 				  sizeof(struct rte_flow_item_tx_queue)),
7993 		.next = NEXT(item_tx_queue),
7994 		.call = parse_vc,
7995 	},
7996 	[ITEM_TX_QUEUE_VALUE] = {
7997 		.name = "tx_queue_value",
7998 		.help = "tx queue value",
7999 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8000 			     item_param),
8001 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8002 					tx_queue)),
8003 	},
8004 };
8005 
8006 /** Remove and return last entry from argument stack. */
8007 static const struct arg *
8008 pop_args(struct context *ctx)
8009 {
8010 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8011 }
8012 
8013 /** Add entry on top of the argument stack. */
8014 static int
8015 push_args(struct context *ctx, const struct arg *arg)
8016 {
8017 	if (ctx->args_num == CTX_STACK_SIZE)
8018 		return -1;
8019 	ctx->args[ctx->args_num++] = arg;
8020 	return 0;
8021 }
8022 
8023 /** Spread value into buffer according to bit-mask. */
8024 static size_t
8025 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8026 {
8027 	uint32_t i = arg->size;
8028 	uint32_t end = 0;
8029 	int sub = 1;
8030 	int add = 0;
8031 	size_t len = 0;
8032 
8033 	if (!arg->mask)
8034 		return 0;
8035 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8036 	if (!arg->hton) {
8037 		i = 0;
8038 		end = arg->size;
8039 		sub = 0;
8040 		add = 1;
8041 	}
8042 #endif
8043 	while (i != end) {
8044 		unsigned int shift = 0;
8045 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8046 
8047 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8048 			if (!(arg->mask[i] & (1 << shift)))
8049 				continue;
8050 			++len;
8051 			if (!dst)
8052 				continue;
8053 			*buf &= ~(1 << shift);
8054 			*buf |= (val & 1) << shift;
8055 			val >>= 1;
8056 		}
8057 		i += add;
8058 	}
8059 	return len;
8060 }
8061 
8062 /** Compare a string with a partial one of a given length. */
8063 static int
8064 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8065 {
8066 	int r = strncmp(full, partial, partial_len);
8067 
8068 	if (r)
8069 		return r;
8070 	if (strlen(full) <= partial_len)
8071 		return 0;
8072 	return full[partial_len];
8073 }
8074 
8075 /**
8076  * Parse a prefix length and generate a bit-mask.
8077  *
8078  * Last argument (ctx->args) is retrieved to determine mask size, storage
8079  * location and whether the result must use network byte ordering.
8080  */
8081 static int
8082 parse_prefix(struct context *ctx, const struct token *token,
8083 	     const char *str, unsigned int len,
8084 	     void *buf, unsigned int size)
8085 {
8086 	const struct arg *arg = pop_args(ctx);
8087 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8088 	char *end;
8089 	uintmax_t u;
8090 	unsigned int bytes;
8091 	unsigned int extra;
8092 
8093 	(void)token;
8094 	/* Argument is expected. */
8095 	if (!arg)
8096 		return -1;
8097 	errno = 0;
8098 	u = strtoumax(str, &end, 0);
8099 	if (errno || (size_t)(end - str) != len)
8100 		goto error;
8101 	if (arg->mask) {
8102 		uintmax_t v = 0;
8103 
8104 		extra = arg_entry_bf_fill(NULL, 0, arg);
8105 		if (u > extra)
8106 			goto error;
8107 		if (!ctx->object)
8108 			return len;
8109 		extra -= u;
8110 		while (u--)
8111 			(v <<= 1, v |= 1);
8112 		v <<= extra;
8113 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8114 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8115 			goto error;
8116 		return len;
8117 	}
8118 	bytes = u / 8;
8119 	extra = u % 8;
8120 	size = arg->size;
8121 	if (bytes > size || bytes + !!extra > size)
8122 		goto error;
8123 	if (!ctx->object)
8124 		return len;
8125 	buf = (uint8_t *)ctx->object + arg->offset;
8126 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8127 	if (!arg->hton) {
8128 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8129 		memset(buf, 0x00, size - bytes);
8130 		if (extra)
8131 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8132 	} else
8133 #endif
8134 	{
8135 		memset(buf, 0xff, bytes);
8136 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8137 		if (extra)
8138 			((uint8_t *)buf)[bytes] = conv[extra];
8139 	}
8140 	if (ctx->objmask)
8141 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8142 	return len;
8143 error:
8144 	push_args(ctx, arg);
8145 	return -1;
8146 }
8147 
8148 /** Default parsing function for token name matching. */
8149 static int
8150 parse_default(struct context *ctx, const struct token *token,
8151 	      const char *str, unsigned int len,
8152 	      void *buf, unsigned int size)
8153 {
8154 	(void)ctx;
8155 	(void)buf;
8156 	(void)size;
8157 	if (strcmp_partial(token->name, str, len))
8158 		return -1;
8159 	return len;
8160 }
8161 
8162 /** Parse flow command, initialize output buffer for subsequent tokens. */
8163 static int
8164 parse_init(struct context *ctx, const struct token *token,
8165 	   const char *str, unsigned int len,
8166 	   void *buf, unsigned int size)
8167 {
8168 	struct buffer *out = buf;
8169 
8170 	/* Token name must match. */
8171 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8172 		return -1;
8173 	/* Nothing else to do if there is no buffer. */
8174 	if (!out)
8175 		return len;
8176 	/* Make sure buffer is large enough. */
8177 	if (size < sizeof(*out))
8178 		return -1;
8179 	/* Initialize buffer. */
8180 	memset(out, 0x00, sizeof(*out));
8181 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8182 	ctx->objdata = 0;
8183 	ctx->object = out;
8184 	ctx->objmask = NULL;
8185 	return len;
8186 }
8187 
8188 /** Parse tokens for indirect action commands. */
8189 static int
8190 parse_ia(struct context *ctx, const struct token *token,
8191 	 const char *str, unsigned int len,
8192 	 void *buf, unsigned int size)
8193 {
8194 	struct buffer *out = buf;
8195 
8196 	/* Token name must match. */
8197 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8198 		return -1;
8199 	/* Nothing else to do if there is no buffer. */
8200 	if (!out)
8201 		return len;
8202 	if (!out->command) {
8203 		if (ctx->curr != INDIRECT_ACTION)
8204 			return -1;
8205 		if (sizeof(*out) > size)
8206 			return -1;
8207 		out->command = ctx->curr;
8208 		ctx->objdata = 0;
8209 		ctx->object = out;
8210 		ctx->objmask = NULL;
8211 		out->args.vc.data = (uint8_t *)out + size;
8212 		return len;
8213 	}
8214 	switch (ctx->curr) {
8215 	case INDIRECT_ACTION_CREATE:
8216 	case INDIRECT_ACTION_UPDATE:
8217 	case INDIRECT_ACTION_QUERY_UPDATE:
8218 		out->args.vc.actions =
8219 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8220 					       sizeof(double));
8221 		out->args.vc.attr.group = UINT32_MAX;
8222 		/* fallthrough */
8223 	case INDIRECT_ACTION_QUERY:
8224 		out->command = ctx->curr;
8225 		ctx->objdata = 0;
8226 		ctx->object = out;
8227 		ctx->objmask = NULL;
8228 		return len;
8229 	case INDIRECT_ACTION_EGRESS:
8230 		out->args.vc.attr.egress = 1;
8231 		return len;
8232 	case INDIRECT_ACTION_INGRESS:
8233 		out->args.vc.attr.ingress = 1;
8234 		return len;
8235 	case INDIRECT_ACTION_TRANSFER:
8236 		out->args.vc.attr.transfer = 1;
8237 		return len;
8238 	case INDIRECT_ACTION_QU_MODE:
8239 		return len;
8240 	case INDIRECT_ACTION_LIST:
8241 		out->command = INDIRECT_ACTION_LIST_CREATE;
8242 		return len;
8243 	case INDIRECT_ACTION_FLOW_CONF:
8244 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8245 		return len;
8246 	default:
8247 		return -1;
8248 	}
8249 }
8250 
8251 
8252 /** Parse tokens for indirect action destroy command. */
8253 static int
8254 parse_ia_destroy(struct context *ctx, const struct token *token,
8255 		 const char *str, unsigned int len,
8256 		 void *buf, unsigned int size)
8257 {
8258 	struct buffer *out = buf;
8259 	uint32_t *action_id;
8260 
8261 	/* Token name must match. */
8262 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8263 		return -1;
8264 	/* Nothing else to do if there is no buffer. */
8265 	if (!out)
8266 		return len;
8267 	if (!out->command || out->command == INDIRECT_ACTION) {
8268 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8269 			return -1;
8270 		if (sizeof(*out) > size)
8271 			return -1;
8272 		out->command = ctx->curr;
8273 		ctx->objdata = 0;
8274 		ctx->object = out;
8275 		ctx->objmask = NULL;
8276 		out->args.ia_destroy.action_id =
8277 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8278 					       sizeof(double));
8279 		return len;
8280 	}
8281 	action_id = out->args.ia_destroy.action_id
8282 		    + out->args.ia_destroy.action_id_n++;
8283 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8284 		return -1;
8285 	ctx->objdata = 0;
8286 	ctx->object = action_id;
8287 	ctx->objmask = NULL;
8288 	return len;
8289 }
8290 
8291 /** Parse tokens for indirect action commands. */
8292 static int
8293 parse_qia(struct context *ctx, const struct token *token,
8294 	  const char *str, unsigned int len,
8295 	  void *buf, unsigned int size)
8296 {
8297 	struct buffer *out = buf;
8298 
8299 	/* Token name must match. */
8300 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8301 		return -1;
8302 	/* Nothing else to do if there is no buffer. */
8303 	if (!out)
8304 		return len;
8305 	if (!out->command) {
8306 		if (ctx->curr != QUEUE)
8307 			return -1;
8308 		if (sizeof(*out) > size)
8309 			return -1;
8310 		out->args.vc.data = (uint8_t *)out + size;
8311 		return len;
8312 	}
8313 	switch (ctx->curr) {
8314 	case QUEUE_INDIRECT_ACTION:
8315 		return len;
8316 	case QUEUE_INDIRECT_ACTION_CREATE:
8317 	case QUEUE_INDIRECT_ACTION_UPDATE:
8318 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8319 		out->args.vc.actions =
8320 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8321 					       sizeof(double));
8322 		out->args.vc.attr.group = UINT32_MAX;
8323 		/* fallthrough */
8324 	case QUEUE_INDIRECT_ACTION_QUERY:
8325 		out->command = ctx->curr;
8326 		ctx->objdata = 0;
8327 		ctx->object = out;
8328 		ctx->objmask = NULL;
8329 		return len;
8330 	case QUEUE_INDIRECT_ACTION_EGRESS:
8331 		out->args.vc.attr.egress = 1;
8332 		return len;
8333 	case QUEUE_INDIRECT_ACTION_INGRESS:
8334 		out->args.vc.attr.ingress = 1;
8335 		return len;
8336 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8337 		out->args.vc.attr.transfer = 1;
8338 		return len;
8339 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8340 		return len;
8341 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8342 		return len;
8343 	case QUEUE_INDIRECT_ACTION_LIST:
8344 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8345 		return len;
8346 	default:
8347 		return -1;
8348 	}
8349 }
8350 
8351 /** Parse tokens for indirect action destroy command. */
8352 static int
8353 parse_qia_destroy(struct context *ctx, const struct token *token,
8354 		  const char *str, unsigned int len,
8355 		  void *buf, unsigned int size)
8356 {
8357 	struct buffer *out = buf;
8358 	uint32_t *action_id;
8359 
8360 	/* Token name must match. */
8361 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8362 		return -1;
8363 	/* Nothing else to do if there is no buffer. */
8364 	if (!out)
8365 		return len;
8366 	if (!out->command || out->command == QUEUE) {
8367 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8368 			return -1;
8369 		if (sizeof(*out) > size)
8370 			return -1;
8371 		out->command = ctx->curr;
8372 		ctx->objdata = 0;
8373 		ctx->object = out;
8374 		ctx->objmask = NULL;
8375 		out->args.ia_destroy.action_id =
8376 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8377 					       sizeof(double));
8378 		return len;
8379 	}
8380 	switch (ctx->curr) {
8381 	case QUEUE_INDIRECT_ACTION:
8382 		out->command = ctx->curr;
8383 		ctx->objdata = 0;
8384 		ctx->object = out;
8385 		ctx->objmask = NULL;
8386 		return len;
8387 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8388 		action_id = out->args.ia_destroy.action_id
8389 				+ out->args.ia_destroy.action_id_n++;
8390 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8391 			return -1;
8392 		ctx->objdata = 0;
8393 		ctx->object = action_id;
8394 		ctx->objmask = NULL;
8395 		return len;
8396 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8397 		return len;
8398 	default:
8399 		return -1;
8400 	}
8401 }
8402 
8403 /** Parse tokens for meter policy action commands. */
8404 static int
8405 parse_mp(struct context *ctx, const struct token *token,
8406 	const char *str, unsigned int len,
8407 	void *buf, unsigned int size)
8408 {
8409 	struct buffer *out = buf;
8410 
8411 	/* Token name must match. */
8412 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8413 		return -1;
8414 	/* Nothing else to do if there is no buffer. */
8415 	if (!out)
8416 		return len;
8417 	if (!out->command) {
8418 		if (ctx->curr != ITEM_POL_POLICY)
8419 			return -1;
8420 		if (sizeof(*out) > size)
8421 			return -1;
8422 		out->command = ctx->curr;
8423 		ctx->objdata = 0;
8424 		ctx->object = out;
8425 		ctx->objmask = NULL;
8426 		out->args.vc.data = (uint8_t *)out + size;
8427 		return len;
8428 	}
8429 	switch (ctx->curr) {
8430 	case ACTION_POL_G:
8431 		out->args.vc.actions =
8432 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8433 					sizeof(double));
8434 		out->command = ctx->curr;
8435 		ctx->objdata = 0;
8436 		ctx->object = out;
8437 		ctx->objmask = NULL;
8438 		return len;
8439 	default:
8440 		return -1;
8441 	}
8442 }
8443 
8444 /** Parse tokens for validate/create commands. */
8445 static int
8446 parse_vc(struct context *ctx, const struct token *token,
8447 	 const char *str, unsigned int len,
8448 	 void *buf, unsigned int size)
8449 {
8450 	struct buffer *out = buf;
8451 	uint8_t *data;
8452 	uint32_t data_size;
8453 
8454 	/* Token name must match. */
8455 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8456 		return -1;
8457 	/* Nothing else to do if there is no buffer. */
8458 	if (!out)
8459 		return len;
8460 	if (!out->command) {
8461 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8462 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8463 		    ctx->curr != ACTIONS_TEMPLATE_CREATE)
8464 			return -1;
8465 		if (sizeof(*out) > size)
8466 			return -1;
8467 		out->command = ctx->curr;
8468 		ctx->objdata = 0;
8469 		ctx->object = out;
8470 		ctx->objmask = NULL;
8471 		out->args.vc.data = (uint8_t *)out + size;
8472 		return len;
8473 	}
8474 	ctx->objdata = 0;
8475 	switch (ctx->curr) {
8476 	default:
8477 		ctx->object = &out->args.vc.attr;
8478 		break;
8479 	case VC_TUNNEL_SET:
8480 	case VC_TUNNEL_MATCH:
8481 		ctx->object = &out->args.vc.tunnel_ops;
8482 		break;
8483 	case VC_USER_ID:
8484 		ctx->object = out;
8485 		break;
8486 	}
8487 	ctx->objmask = NULL;
8488 	switch (ctx->curr) {
8489 	case VC_GROUP:
8490 	case VC_PRIORITY:
8491 	case VC_USER_ID:
8492 		return len;
8493 	case VC_TUNNEL_SET:
8494 		out->args.vc.tunnel_ops.enabled = 1;
8495 		out->args.vc.tunnel_ops.actions = 1;
8496 		return len;
8497 	case VC_TUNNEL_MATCH:
8498 		out->args.vc.tunnel_ops.enabled = 1;
8499 		out->args.vc.tunnel_ops.items = 1;
8500 		return len;
8501 	case VC_INGRESS:
8502 		out->args.vc.attr.ingress = 1;
8503 		return len;
8504 	case VC_EGRESS:
8505 		out->args.vc.attr.egress = 1;
8506 		return len;
8507 	case VC_TRANSFER:
8508 		out->args.vc.attr.transfer = 1;
8509 		return len;
8510 	case ITEM_PATTERN:
8511 		out->args.vc.pattern =
8512 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8513 					       sizeof(double));
8514 		ctx->object = out->args.vc.pattern;
8515 		ctx->objmask = NULL;
8516 		return len;
8517 	case ITEM_END:
8518 		if ((out->command == VALIDATE || out->command == CREATE) &&
8519 		    ctx->last)
8520 			return -1;
8521 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8522 		    !ctx->last)
8523 			return -1;
8524 		break;
8525 	case ACTIONS:
8526 		out->args.vc.actions = out->args.vc.pattern ?
8527 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8528 					       (out->args.vc.pattern +
8529 						out->args.vc.pattern_n),
8530 					       sizeof(double)) :
8531 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8532 					       sizeof(double));
8533 		ctx->object = out->args.vc.actions;
8534 		ctx->objmask = NULL;
8535 		return len;
8536 	default:
8537 		if (!token->priv)
8538 			return -1;
8539 		break;
8540 	}
8541 	if (!out->args.vc.actions) {
8542 		const struct parse_item_priv *priv = token->priv;
8543 		struct rte_flow_item *item =
8544 			out->args.vc.pattern + out->args.vc.pattern_n;
8545 
8546 		data_size = priv->size * 3; /* spec, last, mask */
8547 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8548 					       (out->args.vc.data - data_size),
8549 					       sizeof(double));
8550 		if ((uint8_t *)item + sizeof(*item) > data)
8551 			return -1;
8552 		*item = (struct rte_flow_item){
8553 			.type = priv->type,
8554 		};
8555 		++out->args.vc.pattern_n;
8556 		ctx->object = item;
8557 		ctx->objmask = NULL;
8558 	} else {
8559 		const struct parse_action_priv *priv = token->priv;
8560 		struct rte_flow_action *action =
8561 			out->args.vc.actions + out->args.vc.actions_n;
8562 
8563 		data_size = priv->size; /* configuration */
8564 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8565 					       (out->args.vc.data - data_size),
8566 					       sizeof(double));
8567 		if ((uint8_t *)action + sizeof(*action) > data)
8568 			return -1;
8569 		*action = (struct rte_flow_action){
8570 			.type = priv->type,
8571 			.conf = data_size ? data : NULL,
8572 		};
8573 		++out->args.vc.actions_n;
8574 		ctx->object = action;
8575 		ctx->objmask = NULL;
8576 	}
8577 	memset(data, 0, data_size);
8578 	out->args.vc.data = data;
8579 	ctx->objdata = data_size;
8580 	return len;
8581 }
8582 
8583 /** Parse pattern item parameter type. */
8584 static int
8585 parse_vc_spec(struct context *ctx, const struct token *token,
8586 	      const char *str, unsigned int len,
8587 	      void *buf, unsigned int size)
8588 {
8589 	struct buffer *out = buf;
8590 	struct rte_flow_item *item;
8591 	uint32_t data_size;
8592 	int index;
8593 	int objmask = 0;
8594 
8595 	(void)size;
8596 	/* Token name must match. */
8597 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8598 		return -1;
8599 	/* Parse parameter types. */
8600 	switch (ctx->curr) {
8601 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8602 
8603 	case ITEM_PARAM_IS:
8604 		index = 0;
8605 		objmask = 1;
8606 		break;
8607 	case ITEM_PARAM_SPEC:
8608 		index = 0;
8609 		break;
8610 	case ITEM_PARAM_LAST:
8611 		index = 1;
8612 		break;
8613 	case ITEM_PARAM_PREFIX:
8614 		/* Modify next token to expect a prefix. */
8615 		if (ctx->next_num < 2)
8616 			return -1;
8617 		ctx->next[ctx->next_num - 2] = prefix;
8618 		/* Fall through. */
8619 	case ITEM_PARAM_MASK:
8620 		index = 2;
8621 		break;
8622 	default:
8623 		return -1;
8624 	}
8625 	/* Nothing else to do if there is no buffer. */
8626 	if (!out)
8627 		return len;
8628 	if (!out->args.vc.pattern_n)
8629 		return -1;
8630 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8631 	data_size = ctx->objdata / 3; /* spec, last, mask */
8632 	/* Point to selected object. */
8633 	ctx->object = out->args.vc.data + (data_size * index);
8634 	if (objmask) {
8635 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8636 		item->mask = ctx->objmask;
8637 	} else
8638 		ctx->objmask = NULL;
8639 	/* Update relevant item pointer. */
8640 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8641 		ctx->object;
8642 	return len;
8643 }
8644 
8645 /** Parse action configuration field. */
8646 static int
8647 parse_vc_conf(struct context *ctx, const struct token *token,
8648 	      const char *str, unsigned int len,
8649 	      void *buf, unsigned int size)
8650 {
8651 	struct buffer *out = buf;
8652 
8653 	(void)size;
8654 	/* Token name must match. */
8655 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8656 		return -1;
8657 	/* Nothing else to do if there is no buffer. */
8658 	if (!out)
8659 		return len;
8660 	/* Point to selected object. */
8661 	ctx->object = out->args.vc.data;
8662 	ctx->objmask = NULL;
8663 	return len;
8664 }
8665 
8666 /** Parse action configuration field. */
8667 static int
8668 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8669 		      const char *str, unsigned int len,
8670 		      void *buf, unsigned int size)
8671 {
8672 	struct buffer *out = buf;
8673 	struct rte_flow_update_age *update;
8674 
8675 	(void)size;
8676 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8677 		return -1;
8678 	/* Token name must match. */
8679 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8680 		return -1;
8681 	/* Nothing else to do if there is no buffer. */
8682 	if (!out)
8683 		return len;
8684 	/* Point to selected object. */
8685 	ctx->object = out->args.vc.data;
8686 	ctx->objmask = NULL;
8687 	/* Update the timeout is valid. */
8688 	update = (struct rte_flow_update_age *)out->args.vc.data;
8689 	update->timeout_valid = 1;
8690 	return len;
8691 }
8692 
8693 /** Parse eCPRI common header type field. */
8694 static int
8695 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8696 			 const char *str, unsigned int len,
8697 			 void *buf, unsigned int size)
8698 {
8699 	struct rte_flow_item_ecpri *ecpri;
8700 	struct rte_flow_item_ecpri *ecpri_mask;
8701 	struct rte_flow_item *item;
8702 	uint32_t data_size;
8703 	uint8_t msg_type;
8704 	struct buffer *out = buf;
8705 	const struct arg *arg;
8706 
8707 	(void)size;
8708 	/* Token name must match. */
8709 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8710 		return -1;
8711 	switch (ctx->curr) {
8712 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8713 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8714 		break;
8715 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8716 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8717 		break;
8718 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8719 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8720 		break;
8721 	default:
8722 		return -1;
8723 	}
8724 	if (!ctx->object)
8725 		return len;
8726 	arg = pop_args(ctx);
8727 	if (!arg)
8728 		return -1;
8729 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8730 	ecpri->hdr.common.type = msg_type;
8731 	data_size = ctx->objdata / 3; /* spec, last, mask */
8732 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8733 						    (data_size * 2));
8734 	ecpri_mask->hdr.common.type = 0xFF;
8735 	if (arg->hton) {
8736 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8737 		ecpri_mask->hdr.common.u32 =
8738 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8739 	}
8740 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8741 	item->spec = ecpri;
8742 	item->mask = ecpri_mask;
8743 	return len;
8744 }
8745 
8746 /** Parse L2TPv2 common header type field. */
8747 static int
8748 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8749 			 const char *str, unsigned int len,
8750 			 void *buf, unsigned int size)
8751 {
8752 	struct rte_flow_item_l2tpv2 *l2tpv2;
8753 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8754 	struct rte_flow_item *item;
8755 	uint32_t data_size;
8756 	uint16_t msg_type = 0;
8757 	struct buffer *out = buf;
8758 	const struct arg *arg;
8759 
8760 	(void)size;
8761 	/* Token name must match. */
8762 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8763 		return -1;
8764 	switch (ctx->curr) {
8765 	case ITEM_L2TPV2_TYPE_DATA:
8766 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8767 		break;
8768 	case ITEM_L2TPV2_TYPE_DATA_L:
8769 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8770 		break;
8771 	case ITEM_L2TPV2_TYPE_DATA_S:
8772 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8773 		break;
8774 	case ITEM_L2TPV2_TYPE_DATA_O:
8775 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8776 		break;
8777 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8778 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8779 		break;
8780 	case ITEM_L2TPV2_TYPE_CTRL:
8781 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8782 		break;
8783 	default:
8784 		return -1;
8785 	}
8786 	if (!ctx->object)
8787 		return len;
8788 	arg = pop_args(ctx);
8789 	if (!arg)
8790 		return -1;
8791 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8792 	l2tpv2->hdr.common.flags_version |= msg_type;
8793 	data_size = ctx->objdata / 3; /* spec, last, mask */
8794 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8795 						    (data_size * 2));
8796 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8797 	if (arg->hton) {
8798 		l2tpv2->hdr.common.flags_version =
8799 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8800 		l2tpv2_mask->hdr.common.flags_version =
8801 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8802 	}
8803 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8804 	item->spec = l2tpv2;
8805 	item->mask = l2tpv2_mask;
8806 	return len;
8807 }
8808 
8809 /** Parse operation for compare match item. */
8810 static int
8811 parse_vc_compare_op(struct context *ctx, const struct token *token,
8812 			 const char *str, unsigned int len, void *buf,
8813 			 unsigned int size)
8814 {
8815 	struct rte_flow_item_compare *compare_item;
8816 	unsigned int i;
8817 
8818 	(void)token;
8819 	(void)buf;
8820 	(void)size;
8821 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8822 		return -1;
8823 	for (i = 0; compare_ops[i]; ++i)
8824 		if (!strcmp_partial(compare_ops[i], str, len))
8825 			break;
8826 	if (!compare_ops[i])
8827 		return -1;
8828 	if (!ctx->object)
8829 		return len;
8830 	compare_item = ctx->object;
8831 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8832 	return len;
8833 }
8834 
8835 /** Parse id for compare match item. */
8836 static int
8837 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8838 			  const char *str, unsigned int len, void *buf,
8839 			  unsigned int size)
8840 {
8841 	struct rte_flow_item_compare *compare_item;
8842 	unsigned int i;
8843 
8844 	(void)token;
8845 	(void)buf;
8846 	(void)size;
8847 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8848 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8849 		return -1;
8850 	for (i = 0; flow_field_ids[i]; ++i)
8851 		if (!strcmp_partial(flow_field_ids[i], str, len))
8852 			break;
8853 	if (!flow_field_ids[i])
8854 		return -1;
8855 	if (!ctx->object)
8856 		return len;
8857 	compare_item = ctx->object;
8858 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8859 		compare_item->a.field = (enum rte_flow_field_id)i;
8860 	else
8861 		compare_item->b.field = (enum rte_flow_field_id)i;
8862 	return len;
8863 }
8864 
8865 /** Parse level for compare match item. */
8866 static int
8867 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8868 			     const char *str, unsigned int len, void *buf,
8869 			     unsigned int size)
8870 {
8871 	struct rte_flow_item_compare *compare_item;
8872 	struct flex_item *fp = NULL;
8873 	uint32_t val;
8874 	struct buffer *out = buf;
8875 	char *end;
8876 
8877 	(void)token;
8878 	(void)size;
8879 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8880 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
8881 		return -1;
8882 	if (!ctx->object)
8883 		return len;
8884 	compare_item = ctx->object;
8885 	errno = 0;
8886 	val = strtoumax(str, &end, 0);
8887 	if (errno || (size_t)(end - str) != len)
8888 		return -1;
8889 	/* No need to validate action template mask value */
8890 	if (out->args.vc.masks) {
8891 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
8892 			compare_item->a.level = val;
8893 		else
8894 			compare_item->b.level = val;
8895 		return len;
8896 	}
8897 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8898 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
8899 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
8900 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
8901 		if (val >= FLEX_MAX_PARSERS_NUM) {
8902 			printf("Bad flex item handle\n");
8903 			return -1;
8904 		}
8905 		fp = flex_items[ctx->port][val];
8906 		if (!fp) {
8907 			printf("Bad flex item handle\n");
8908 			return -1;
8909 		}
8910 	}
8911 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
8912 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
8913 			compare_item->a.level = val;
8914 		else
8915 			compare_item->a.flex_handle = fp->flex_handle;
8916 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
8917 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
8918 			compare_item->b.level = val;
8919 		else
8920 			compare_item->b.flex_handle = fp->flex_handle;
8921 	}
8922 	return len;
8923 }
8924 
8925 /** Parse meter color action type. */
8926 static int
8927 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
8928 				const char *str, unsigned int len,
8929 				void *buf, unsigned int size)
8930 {
8931 	struct rte_flow_action *action_data;
8932 	struct rte_flow_action_meter_color *conf;
8933 	enum rte_color color;
8934 
8935 	(void)buf;
8936 	(void)size;
8937 	/* Token name must match. */
8938 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8939 		return -1;
8940 	switch (ctx->curr) {
8941 	case ACTION_METER_COLOR_GREEN:
8942 		color = RTE_COLOR_GREEN;
8943 	break;
8944 	case ACTION_METER_COLOR_YELLOW:
8945 		color = RTE_COLOR_YELLOW;
8946 	break;
8947 	case ACTION_METER_COLOR_RED:
8948 		color = RTE_COLOR_RED;
8949 	break;
8950 	default:
8951 		return -1;
8952 	}
8953 
8954 	if (!ctx->object)
8955 		return len;
8956 	action_data = ctx->object;
8957 	conf = (struct rte_flow_action_meter_color *)
8958 					(uintptr_t)(action_data->conf);
8959 	conf->color = color;
8960 	return len;
8961 }
8962 
8963 /** Parse RSS action. */
8964 static int
8965 parse_vc_action_rss(struct context *ctx, const struct token *token,
8966 		    const char *str, unsigned int len,
8967 		    void *buf, unsigned int size)
8968 {
8969 	struct buffer *out = buf;
8970 	struct rte_flow_action *action;
8971 	struct action_rss_data *action_rss_data;
8972 	unsigned int i;
8973 	int ret;
8974 
8975 	ret = parse_vc(ctx, token, str, len, buf, size);
8976 	if (ret < 0)
8977 		return ret;
8978 	/* Nothing else to do if there is no buffer. */
8979 	if (!out)
8980 		return ret;
8981 	if (!out->args.vc.actions_n)
8982 		return -1;
8983 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8984 	/* Point to selected object. */
8985 	ctx->object = out->args.vc.data;
8986 	ctx->objmask = NULL;
8987 	/* Set up default configuration. */
8988 	action_rss_data = ctx->object;
8989 	*action_rss_data = (struct action_rss_data){
8990 		.conf = (struct rte_flow_action_rss){
8991 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
8992 			.level = 0,
8993 			.types = rss_hf,
8994 			.key_len = 0,
8995 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
8996 			.key = NULL,
8997 			.queue = action_rss_data->queue,
8998 		},
8999 		.queue = { 0 },
9000 	};
9001 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9002 		action_rss_data->queue[i] = i;
9003 	action->conf = &action_rss_data->conf;
9004 	return ret;
9005 }
9006 
9007 /**
9008  * Parse func field for RSS action.
9009  *
9010  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9011  * ACTION_RSS_FUNC_* index that called this function.
9012  */
9013 static int
9014 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9015 			 const char *str, unsigned int len,
9016 			 void *buf, unsigned int size)
9017 {
9018 	struct action_rss_data *action_rss_data;
9019 	enum rte_eth_hash_function func;
9020 
9021 	(void)buf;
9022 	(void)size;
9023 	/* Token name must match. */
9024 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9025 		return -1;
9026 	switch (ctx->curr) {
9027 	case ACTION_RSS_FUNC_DEFAULT:
9028 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9029 		break;
9030 	case ACTION_RSS_FUNC_TOEPLITZ:
9031 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9032 		break;
9033 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9034 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9035 		break;
9036 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9037 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9038 		break;
9039 	default:
9040 		return -1;
9041 	}
9042 	if (!ctx->object)
9043 		return len;
9044 	action_rss_data = ctx->object;
9045 	action_rss_data->conf.func = func;
9046 	return len;
9047 }
9048 
9049 /**
9050  * Parse type field for RSS action.
9051  *
9052  * Valid tokens are type field names and the "end" token.
9053  */
9054 static int
9055 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9056 			  const char *str, unsigned int len,
9057 			  void *buf, unsigned int size)
9058 {
9059 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9060 	struct action_rss_data *action_rss_data;
9061 	unsigned int i;
9062 
9063 	(void)token;
9064 	(void)buf;
9065 	(void)size;
9066 	if (ctx->curr != ACTION_RSS_TYPE)
9067 		return -1;
9068 	if (!(ctx->objdata >> 16) && ctx->object) {
9069 		action_rss_data = ctx->object;
9070 		action_rss_data->conf.types = 0;
9071 	}
9072 	if (!strcmp_partial("end", str, len)) {
9073 		ctx->objdata &= 0xffff;
9074 		return len;
9075 	}
9076 	for (i = 0; rss_type_table[i].str; ++i)
9077 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9078 			break;
9079 	if (!rss_type_table[i].str)
9080 		return -1;
9081 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9082 	/* Repeat token. */
9083 	if (ctx->next_num == RTE_DIM(ctx->next))
9084 		return -1;
9085 	ctx->next[ctx->next_num++] = next;
9086 	if (!ctx->object)
9087 		return len;
9088 	action_rss_data = ctx->object;
9089 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9090 	return len;
9091 }
9092 
9093 /**
9094  * Parse queue field for RSS action.
9095  *
9096  * Valid tokens are queue indices and the "end" token.
9097  */
9098 static int
9099 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9100 			  const char *str, unsigned int len,
9101 			  void *buf, unsigned int size)
9102 {
9103 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9104 	struct action_rss_data *action_rss_data;
9105 	const struct arg *arg;
9106 	int ret;
9107 	int i;
9108 
9109 	(void)token;
9110 	(void)buf;
9111 	(void)size;
9112 	if (ctx->curr != ACTION_RSS_QUEUE)
9113 		return -1;
9114 	i = ctx->objdata >> 16;
9115 	if (!strcmp_partial("end", str, len)) {
9116 		ctx->objdata &= 0xffff;
9117 		goto end;
9118 	}
9119 	if (i >= ACTION_RSS_QUEUE_NUM)
9120 		return -1;
9121 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9122 			     i * sizeof(action_rss_data->queue[i]),
9123 			     sizeof(action_rss_data->queue[i]));
9124 	if (push_args(ctx, arg))
9125 		return -1;
9126 	ret = parse_int(ctx, token, str, len, NULL, 0);
9127 	if (ret < 0) {
9128 		pop_args(ctx);
9129 		return -1;
9130 	}
9131 	++i;
9132 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9133 	/* Repeat token. */
9134 	if (ctx->next_num == RTE_DIM(ctx->next))
9135 		return -1;
9136 	ctx->next[ctx->next_num++] = next;
9137 end:
9138 	if (!ctx->object)
9139 		return len;
9140 	action_rss_data = ctx->object;
9141 	action_rss_data->conf.queue_num = i;
9142 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9143 	return len;
9144 }
9145 
9146 /** Setup VXLAN encap configuration. */
9147 static int
9148 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9149 {
9150 	/* Set up default configuration. */
9151 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9152 		.conf = (struct rte_flow_action_vxlan_encap){
9153 			.definition = action_vxlan_encap_data->items,
9154 		},
9155 		.items = {
9156 			{
9157 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9158 				.spec = &action_vxlan_encap_data->item_eth,
9159 				.mask = &rte_flow_item_eth_mask,
9160 			},
9161 			{
9162 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9163 				.spec = &action_vxlan_encap_data->item_vlan,
9164 				.mask = &rte_flow_item_vlan_mask,
9165 			},
9166 			{
9167 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9168 				.spec = &action_vxlan_encap_data->item_ipv4,
9169 				.mask = &rte_flow_item_ipv4_mask,
9170 			},
9171 			{
9172 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9173 				.spec = &action_vxlan_encap_data->item_udp,
9174 				.mask = &rte_flow_item_udp_mask,
9175 			},
9176 			{
9177 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9178 				.spec = &action_vxlan_encap_data->item_vxlan,
9179 				.mask = &rte_flow_item_vxlan_mask,
9180 			},
9181 			{
9182 				.type = RTE_FLOW_ITEM_TYPE_END,
9183 			},
9184 		},
9185 		.item_eth.hdr.ether_type = 0,
9186 		.item_vlan = {
9187 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9188 			.hdr.eth_proto = 0,
9189 		},
9190 		.item_ipv4.hdr = {
9191 			.src_addr = vxlan_encap_conf.ipv4_src,
9192 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9193 		},
9194 		.item_udp.hdr = {
9195 			.src_port = vxlan_encap_conf.udp_src,
9196 			.dst_port = vxlan_encap_conf.udp_dst,
9197 		},
9198 		.item_vxlan.hdr.flags = 0,
9199 	};
9200 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9201 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9202 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9203 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9204 	if (!vxlan_encap_conf.select_ipv4) {
9205 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9206 		       &vxlan_encap_conf.ipv6_src,
9207 		       sizeof(vxlan_encap_conf.ipv6_src));
9208 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9209 		       &vxlan_encap_conf.ipv6_dst,
9210 		       sizeof(vxlan_encap_conf.ipv6_dst));
9211 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9212 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9213 			.spec = &action_vxlan_encap_data->item_ipv6,
9214 			.mask = &rte_flow_item_ipv6_mask,
9215 		};
9216 	}
9217 	if (!vxlan_encap_conf.select_vlan)
9218 		action_vxlan_encap_data->items[1].type =
9219 			RTE_FLOW_ITEM_TYPE_VOID;
9220 	if (vxlan_encap_conf.select_tos_ttl) {
9221 		if (vxlan_encap_conf.select_ipv4) {
9222 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9223 
9224 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9225 			       sizeof(ipv4_mask_tos));
9226 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9227 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9228 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9229 					vxlan_encap_conf.ip_tos;
9230 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9231 					vxlan_encap_conf.ip_ttl;
9232 			action_vxlan_encap_data->items[2].mask =
9233 							&ipv4_mask_tos;
9234 		} else {
9235 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9236 
9237 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9238 			       sizeof(ipv6_mask_tos));
9239 			ipv6_mask_tos.hdr.vtc_flow |=
9240 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9241 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9242 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9243 				rte_cpu_to_be_32
9244 					((uint32_t)vxlan_encap_conf.ip_tos <<
9245 					 RTE_IPV6_HDR_TC_SHIFT);
9246 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9247 					vxlan_encap_conf.ip_ttl;
9248 			action_vxlan_encap_data->items[2].mask =
9249 							&ipv6_mask_tos;
9250 		}
9251 	}
9252 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9253 	       RTE_DIM(vxlan_encap_conf.vni));
9254 	return 0;
9255 }
9256 
9257 /** Parse VXLAN encap action. */
9258 static int
9259 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9260 			    const char *str, unsigned int len,
9261 			    void *buf, unsigned int size)
9262 {
9263 	struct buffer *out = buf;
9264 	struct rte_flow_action *action;
9265 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9266 	int ret;
9267 
9268 	ret = parse_vc(ctx, token, str, len, buf, size);
9269 	if (ret < 0)
9270 		return ret;
9271 	/* Nothing else to do if there is no buffer. */
9272 	if (!out)
9273 		return ret;
9274 	if (!out->args.vc.actions_n)
9275 		return -1;
9276 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9277 	/* Point to selected object. */
9278 	ctx->object = out->args.vc.data;
9279 	ctx->objmask = NULL;
9280 	action_vxlan_encap_data = ctx->object;
9281 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9282 	action->conf = &action_vxlan_encap_data->conf;
9283 	return ret;
9284 }
9285 
9286 /** Setup NVGRE encap configuration. */
9287 static int
9288 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9289 {
9290 	/* Set up default configuration. */
9291 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9292 		.conf = (struct rte_flow_action_nvgre_encap){
9293 			.definition = action_nvgre_encap_data->items,
9294 		},
9295 		.items = {
9296 			{
9297 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9298 				.spec = &action_nvgre_encap_data->item_eth,
9299 				.mask = &rte_flow_item_eth_mask,
9300 			},
9301 			{
9302 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9303 				.spec = &action_nvgre_encap_data->item_vlan,
9304 				.mask = &rte_flow_item_vlan_mask,
9305 			},
9306 			{
9307 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9308 				.spec = &action_nvgre_encap_data->item_ipv4,
9309 				.mask = &rte_flow_item_ipv4_mask,
9310 			},
9311 			{
9312 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9313 				.spec = &action_nvgre_encap_data->item_nvgre,
9314 				.mask = &rte_flow_item_nvgre_mask,
9315 			},
9316 			{
9317 				.type = RTE_FLOW_ITEM_TYPE_END,
9318 			},
9319 		},
9320 		.item_eth.hdr.ether_type = 0,
9321 		.item_vlan = {
9322 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9323 			.hdr.eth_proto = 0,
9324 		},
9325 		.item_ipv4.hdr = {
9326 		       .src_addr = nvgre_encap_conf.ipv4_src,
9327 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9328 		},
9329 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9330 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9331 		.item_nvgre.flow_id = 0,
9332 	};
9333 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9334 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9335 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9336 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9337 	if (!nvgre_encap_conf.select_ipv4) {
9338 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9339 		       &nvgre_encap_conf.ipv6_src,
9340 		       sizeof(nvgre_encap_conf.ipv6_src));
9341 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9342 		       &nvgre_encap_conf.ipv6_dst,
9343 		       sizeof(nvgre_encap_conf.ipv6_dst));
9344 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9345 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9346 			.spec = &action_nvgre_encap_data->item_ipv6,
9347 			.mask = &rte_flow_item_ipv6_mask,
9348 		};
9349 	}
9350 	if (!nvgre_encap_conf.select_vlan)
9351 		action_nvgre_encap_data->items[1].type =
9352 			RTE_FLOW_ITEM_TYPE_VOID;
9353 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9354 	       RTE_DIM(nvgre_encap_conf.tni));
9355 	return 0;
9356 }
9357 
9358 /** Parse NVGRE encap action. */
9359 static int
9360 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9361 			    const char *str, unsigned int len,
9362 			    void *buf, unsigned int size)
9363 {
9364 	struct buffer *out = buf;
9365 	struct rte_flow_action *action;
9366 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9367 	int ret;
9368 
9369 	ret = parse_vc(ctx, token, str, len, buf, size);
9370 	if (ret < 0)
9371 		return ret;
9372 	/* Nothing else to do if there is no buffer. */
9373 	if (!out)
9374 		return ret;
9375 	if (!out->args.vc.actions_n)
9376 		return -1;
9377 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9378 	/* Point to selected object. */
9379 	ctx->object = out->args.vc.data;
9380 	ctx->objmask = NULL;
9381 	action_nvgre_encap_data = ctx->object;
9382 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9383 	action->conf = &action_nvgre_encap_data->conf;
9384 	return ret;
9385 }
9386 
9387 /** Parse l2 encap action. */
9388 static int
9389 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9390 			 const char *str, unsigned int len,
9391 			 void *buf, unsigned int size)
9392 {
9393 	struct buffer *out = buf;
9394 	struct rte_flow_action *action;
9395 	struct action_raw_encap_data *action_encap_data;
9396 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9397 	struct rte_flow_item_vlan vlan = {
9398 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9399 		.hdr.eth_proto = 0,
9400 	};
9401 	uint8_t *header;
9402 	int ret;
9403 
9404 	ret = parse_vc(ctx, token, str, len, buf, size);
9405 	if (ret < 0)
9406 		return ret;
9407 	/* Nothing else to do if there is no buffer. */
9408 	if (!out)
9409 		return ret;
9410 	if (!out->args.vc.actions_n)
9411 		return -1;
9412 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9413 	/* Point to selected object. */
9414 	ctx->object = out->args.vc.data;
9415 	ctx->objmask = NULL;
9416 	/* Copy the headers to the buffer. */
9417 	action_encap_data = ctx->object;
9418 	*action_encap_data = (struct action_raw_encap_data) {
9419 		.conf = (struct rte_flow_action_raw_encap){
9420 			.data = action_encap_data->data,
9421 		},
9422 		.data = {},
9423 	};
9424 	header = action_encap_data->data;
9425 	if (l2_encap_conf.select_vlan)
9426 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9427 	else if (l2_encap_conf.select_ipv4)
9428 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9429 	else
9430 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9431 	memcpy(eth.hdr.dst_addr.addr_bytes,
9432 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9433 	memcpy(eth.hdr.src_addr.addr_bytes,
9434 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9435 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9436 	header += sizeof(struct rte_ether_hdr);
9437 	if (l2_encap_conf.select_vlan) {
9438 		if (l2_encap_conf.select_ipv4)
9439 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9440 		else
9441 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9442 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9443 		header += sizeof(struct rte_vlan_hdr);
9444 	}
9445 	action_encap_data->conf.size = header -
9446 		action_encap_data->data;
9447 	action->conf = &action_encap_data->conf;
9448 	return ret;
9449 }
9450 
9451 /** Parse l2 decap action. */
9452 static int
9453 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9454 			 const char *str, unsigned int len,
9455 			 void *buf, unsigned int size)
9456 {
9457 	struct buffer *out = buf;
9458 	struct rte_flow_action *action;
9459 	struct action_raw_decap_data *action_decap_data;
9460 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9461 	struct rte_flow_item_vlan vlan = {
9462 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9463 		.hdr.eth_proto = 0,
9464 	};
9465 	uint8_t *header;
9466 	int ret;
9467 
9468 	ret = parse_vc(ctx, token, str, len, buf, size);
9469 	if (ret < 0)
9470 		return ret;
9471 	/* Nothing else to do if there is no buffer. */
9472 	if (!out)
9473 		return ret;
9474 	if (!out->args.vc.actions_n)
9475 		return -1;
9476 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9477 	/* Point to selected object. */
9478 	ctx->object = out->args.vc.data;
9479 	ctx->objmask = NULL;
9480 	/* Copy the headers to the buffer. */
9481 	action_decap_data = ctx->object;
9482 	*action_decap_data = (struct action_raw_decap_data) {
9483 		.conf = (struct rte_flow_action_raw_decap){
9484 			.data = action_decap_data->data,
9485 		},
9486 		.data = {},
9487 	};
9488 	header = action_decap_data->data;
9489 	if (l2_decap_conf.select_vlan)
9490 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9491 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9492 	header += sizeof(struct rte_ether_hdr);
9493 	if (l2_decap_conf.select_vlan) {
9494 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9495 		header += sizeof(struct rte_vlan_hdr);
9496 	}
9497 	action_decap_data->conf.size = header -
9498 		action_decap_data->data;
9499 	action->conf = &action_decap_data->conf;
9500 	return ret;
9501 }
9502 
9503 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9504 
9505 /** Parse MPLSOGRE encap action. */
9506 static int
9507 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9508 			       const char *str, unsigned int len,
9509 			       void *buf, unsigned int size)
9510 {
9511 	struct buffer *out = buf;
9512 	struct rte_flow_action *action;
9513 	struct action_raw_encap_data *action_encap_data;
9514 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9515 	struct rte_flow_item_vlan vlan = {
9516 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9517 		.hdr.eth_proto = 0,
9518 	};
9519 	struct rte_flow_item_ipv4 ipv4 = {
9520 		.hdr =  {
9521 			.src_addr = mplsogre_encap_conf.ipv4_src,
9522 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9523 			.next_proto_id = IPPROTO_GRE,
9524 			.version_ihl = RTE_IPV4_VHL_DEF,
9525 			.time_to_live = IPDEFTTL,
9526 		},
9527 	};
9528 	struct rte_flow_item_ipv6 ipv6 = {
9529 		.hdr =  {
9530 			.proto = IPPROTO_GRE,
9531 			.hop_limits = IPDEFTTL,
9532 		},
9533 	};
9534 	struct rte_flow_item_gre gre = {
9535 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9536 	};
9537 	struct rte_flow_item_mpls mpls = {
9538 		.ttl = 0,
9539 	};
9540 	uint8_t *header;
9541 	int ret;
9542 
9543 	ret = parse_vc(ctx, token, str, len, buf, size);
9544 	if (ret < 0)
9545 		return ret;
9546 	/* Nothing else to do if there is no buffer. */
9547 	if (!out)
9548 		return ret;
9549 	if (!out->args.vc.actions_n)
9550 		return -1;
9551 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9552 	/* Point to selected object. */
9553 	ctx->object = out->args.vc.data;
9554 	ctx->objmask = NULL;
9555 	/* Copy the headers to the buffer. */
9556 	action_encap_data = ctx->object;
9557 	*action_encap_data = (struct action_raw_encap_data) {
9558 		.conf = (struct rte_flow_action_raw_encap){
9559 			.data = action_encap_data->data,
9560 		},
9561 		.data = {},
9562 		.preserve = {},
9563 	};
9564 	header = action_encap_data->data;
9565 	if (mplsogre_encap_conf.select_vlan)
9566 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9567 	else if (mplsogre_encap_conf.select_ipv4)
9568 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9569 	else
9570 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9571 	memcpy(eth.hdr.dst_addr.addr_bytes,
9572 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9573 	memcpy(eth.hdr.src_addr.addr_bytes,
9574 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9575 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9576 	header += sizeof(struct rte_ether_hdr);
9577 	if (mplsogre_encap_conf.select_vlan) {
9578 		if (mplsogre_encap_conf.select_ipv4)
9579 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9580 		else
9581 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9582 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9583 		header += sizeof(struct rte_vlan_hdr);
9584 	}
9585 	if (mplsogre_encap_conf.select_ipv4) {
9586 		memcpy(header, &ipv4, sizeof(ipv4));
9587 		header += sizeof(ipv4);
9588 	} else {
9589 		memcpy(&ipv6.hdr.src_addr,
9590 		       &mplsogre_encap_conf.ipv6_src,
9591 		       sizeof(mplsogre_encap_conf.ipv6_src));
9592 		memcpy(&ipv6.hdr.dst_addr,
9593 		       &mplsogre_encap_conf.ipv6_dst,
9594 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9595 		memcpy(header, &ipv6, sizeof(ipv6));
9596 		header += sizeof(ipv6);
9597 	}
9598 	memcpy(header, &gre, sizeof(gre));
9599 	header += sizeof(gre);
9600 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9601 	       RTE_DIM(mplsogre_encap_conf.label));
9602 	mpls.label_tc_s[2] |= 0x1;
9603 	memcpy(header, &mpls, sizeof(mpls));
9604 	header += sizeof(mpls);
9605 	action_encap_data->conf.size = header -
9606 		action_encap_data->data;
9607 	action->conf = &action_encap_data->conf;
9608 	return ret;
9609 }
9610 
9611 /** Parse MPLSOGRE decap action. */
9612 static int
9613 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9614 			       const char *str, unsigned int len,
9615 			       void *buf, unsigned int size)
9616 {
9617 	struct buffer *out = buf;
9618 	struct rte_flow_action *action;
9619 	struct action_raw_decap_data *action_decap_data;
9620 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9621 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9622 	struct rte_flow_item_ipv4 ipv4 = {
9623 		.hdr =  {
9624 			.next_proto_id = IPPROTO_GRE,
9625 		},
9626 	};
9627 	struct rte_flow_item_ipv6 ipv6 = {
9628 		.hdr =  {
9629 			.proto = IPPROTO_GRE,
9630 		},
9631 	};
9632 	struct rte_flow_item_gre gre = {
9633 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9634 	};
9635 	struct rte_flow_item_mpls mpls;
9636 	uint8_t *header;
9637 	int ret;
9638 
9639 	ret = parse_vc(ctx, token, str, len, buf, size);
9640 	if (ret < 0)
9641 		return ret;
9642 	/* Nothing else to do if there is no buffer. */
9643 	if (!out)
9644 		return ret;
9645 	if (!out->args.vc.actions_n)
9646 		return -1;
9647 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9648 	/* Point to selected object. */
9649 	ctx->object = out->args.vc.data;
9650 	ctx->objmask = NULL;
9651 	/* Copy the headers to the buffer. */
9652 	action_decap_data = ctx->object;
9653 	*action_decap_data = (struct action_raw_decap_data) {
9654 		.conf = (struct rte_flow_action_raw_decap){
9655 			.data = action_decap_data->data,
9656 		},
9657 		.data = {},
9658 	};
9659 	header = action_decap_data->data;
9660 	if (mplsogre_decap_conf.select_vlan)
9661 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9662 	else if (mplsogre_encap_conf.select_ipv4)
9663 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9664 	else
9665 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9666 	memcpy(eth.hdr.dst_addr.addr_bytes,
9667 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9668 	memcpy(eth.hdr.src_addr.addr_bytes,
9669 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9670 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9671 	header += sizeof(struct rte_ether_hdr);
9672 	if (mplsogre_encap_conf.select_vlan) {
9673 		if (mplsogre_encap_conf.select_ipv4)
9674 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9675 		else
9676 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9677 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9678 		header += sizeof(struct rte_vlan_hdr);
9679 	}
9680 	if (mplsogre_encap_conf.select_ipv4) {
9681 		memcpy(header, &ipv4, sizeof(ipv4));
9682 		header += sizeof(ipv4);
9683 	} else {
9684 		memcpy(header, &ipv6, sizeof(ipv6));
9685 		header += sizeof(ipv6);
9686 	}
9687 	memcpy(header, &gre, sizeof(gre));
9688 	header += sizeof(gre);
9689 	memset(&mpls, 0, sizeof(mpls));
9690 	memcpy(header, &mpls, sizeof(mpls));
9691 	header += sizeof(mpls);
9692 	action_decap_data->conf.size = header -
9693 		action_decap_data->data;
9694 	action->conf = &action_decap_data->conf;
9695 	return ret;
9696 }
9697 
9698 /** Parse MPLSOUDP encap action. */
9699 static int
9700 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9701 			       const char *str, unsigned int len,
9702 			       void *buf, unsigned int size)
9703 {
9704 	struct buffer *out = buf;
9705 	struct rte_flow_action *action;
9706 	struct action_raw_encap_data *action_encap_data;
9707 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9708 	struct rte_flow_item_vlan vlan = {
9709 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9710 		.hdr.eth_proto = 0,
9711 	};
9712 	struct rte_flow_item_ipv4 ipv4 = {
9713 		.hdr =  {
9714 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9715 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9716 			.next_proto_id = IPPROTO_UDP,
9717 			.version_ihl = RTE_IPV4_VHL_DEF,
9718 			.time_to_live = IPDEFTTL,
9719 		},
9720 	};
9721 	struct rte_flow_item_ipv6 ipv6 = {
9722 		.hdr =  {
9723 			.proto = IPPROTO_UDP,
9724 			.hop_limits = IPDEFTTL,
9725 		},
9726 	};
9727 	struct rte_flow_item_udp udp = {
9728 		.hdr = {
9729 			.src_port = mplsoudp_encap_conf.udp_src,
9730 			.dst_port = mplsoudp_encap_conf.udp_dst,
9731 		},
9732 	};
9733 	struct rte_flow_item_mpls mpls;
9734 	uint8_t *header;
9735 	int ret;
9736 
9737 	ret = parse_vc(ctx, token, str, len, buf, size);
9738 	if (ret < 0)
9739 		return ret;
9740 	/* Nothing else to do if there is no buffer. */
9741 	if (!out)
9742 		return ret;
9743 	if (!out->args.vc.actions_n)
9744 		return -1;
9745 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9746 	/* Point to selected object. */
9747 	ctx->object = out->args.vc.data;
9748 	ctx->objmask = NULL;
9749 	/* Copy the headers to the buffer. */
9750 	action_encap_data = ctx->object;
9751 	*action_encap_data = (struct action_raw_encap_data) {
9752 		.conf = (struct rte_flow_action_raw_encap){
9753 			.data = action_encap_data->data,
9754 		},
9755 		.data = {},
9756 		.preserve = {},
9757 	};
9758 	header = action_encap_data->data;
9759 	if (mplsoudp_encap_conf.select_vlan)
9760 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9761 	else if (mplsoudp_encap_conf.select_ipv4)
9762 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9763 	else
9764 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9765 	memcpy(eth.hdr.dst_addr.addr_bytes,
9766 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9767 	memcpy(eth.hdr.src_addr.addr_bytes,
9768 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9769 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9770 	header += sizeof(struct rte_ether_hdr);
9771 	if (mplsoudp_encap_conf.select_vlan) {
9772 		if (mplsoudp_encap_conf.select_ipv4)
9773 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9774 		else
9775 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9776 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9777 		header += sizeof(struct rte_vlan_hdr);
9778 	}
9779 	if (mplsoudp_encap_conf.select_ipv4) {
9780 		memcpy(header, &ipv4, sizeof(ipv4));
9781 		header += sizeof(ipv4);
9782 	} else {
9783 		memcpy(&ipv6.hdr.src_addr,
9784 		       &mplsoudp_encap_conf.ipv6_src,
9785 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9786 		memcpy(&ipv6.hdr.dst_addr,
9787 		       &mplsoudp_encap_conf.ipv6_dst,
9788 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9789 		memcpy(header, &ipv6, sizeof(ipv6));
9790 		header += sizeof(ipv6);
9791 	}
9792 	memcpy(header, &udp, sizeof(udp));
9793 	header += sizeof(udp);
9794 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9795 	       RTE_DIM(mplsoudp_encap_conf.label));
9796 	mpls.label_tc_s[2] |= 0x1;
9797 	memcpy(header, &mpls, sizeof(mpls));
9798 	header += sizeof(mpls);
9799 	action_encap_data->conf.size = header -
9800 		action_encap_data->data;
9801 	action->conf = &action_encap_data->conf;
9802 	return ret;
9803 }
9804 
9805 /** Parse MPLSOUDP decap action. */
9806 static int
9807 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9808 			       const char *str, unsigned int len,
9809 			       void *buf, unsigned int size)
9810 {
9811 	struct buffer *out = buf;
9812 	struct rte_flow_action *action;
9813 	struct action_raw_decap_data *action_decap_data;
9814 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9815 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9816 	struct rte_flow_item_ipv4 ipv4 = {
9817 		.hdr =  {
9818 			.next_proto_id = IPPROTO_UDP,
9819 		},
9820 	};
9821 	struct rte_flow_item_ipv6 ipv6 = {
9822 		.hdr =  {
9823 			.proto = IPPROTO_UDP,
9824 		},
9825 	};
9826 	struct rte_flow_item_udp udp = {
9827 		.hdr = {
9828 			.dst_port = rte_cpu_to_be_16(6635),
9829 		},
9830 	};
9831 	struct rte_flow_item_mpls mpls;
9832 	uint8_t *header;
9833 	int ret;
9834 
9835 	ret = parse_vc(ctx, token, str, len, buf, size);
9836 	if (ret < 0)
9837 		return ret;
9838 	/* Nothing else to do if there is no buffer. */
9839 	if (!out)
9840 		return ret;
9841 	if (!out->args.vc.actions_n)
9842 		return -1;
9843 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9844 	/* Point to selected object. */
9845 	ctx->object = out->args.vc.data;
9846 	ctx->objmask = NULL;
9847 	/* Copy the headers to the buffer. */
9848 	action_decap_data = ctx->object;
9849 	*action_decap_data = (struct action_raw_decap_data) {
9850 		.conf = (struct rte_flow_action_raw_decap){
9851 			.data = action_decap_data->data,
9852 		},
9853 		.data = {},
9854 	};
9855 	header = action_decap_data->data;
9856 	if (mplsoudp_decap_conf.select_vlan)
9857 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9858 	else if (mplsoudp_encap_conf.select_ipv4)
9859 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9860 	else
9861 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9862 	memcpy(eth.hdr.dst_addr.addr_bytes,
9863 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9864 	memcpy(eth.hdr.src_addr.addr_bytes,
9865 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9866 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9867 	header += sizeof(struct rte_ether_hdr);
9868 	if (mplsoudp_encap_conf.select_vlan) {
9869 		if (mplsoudp_encap_conf.select_ipv4)
9870 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9871 		else
9872 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9873 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9874 		header += sizeof(struct rte_vlan_hdr);
9875 	}
9876 	if (mplsoudp_encap_conf.select_ipv4) {
9877 		memcpy(header, &ipv4, sizeof(ipv4));
9878 		header += sizeof(ipv4);
9879 	} else {
9880 		memcpy(header, &ipv6, sizeof(ipv6));
9881 		header += sizeof(ipv6);
9882 	}
9883 	memcpy(header, &udp, sizeof(udp));
9884 	header += sizeof(udp);
9885 	memset(&mpls, 0, sizeof(mpls));
9886 	memcpy(header, &mpls, sizeof(mpls));
9887 	header += sizeof(mpls);
9888 	action_decap_data->conf.size = header -
9889 		action_decap_data->data;
9890 	action->conf = &action_decap_data->conf;
9891 	return ret;
9892 }
9893 
9894 static int
9895 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
9896 				const char *str, unsigned int len, void *buf,
9897 				unsigned int size)
9898 {
9899 	struct action_raw_decap_data *action_raw_decap_data;
9900 	struct rte_flow_action *action;
9901 	const struct arg *arg;
9902 	struct buffer *out = buf;
9903 	int ret;
9904 	uint16_t idx;
9905 
9906 	RTE_SET_USED(token);
9907 	RTE_SET_USED(buf);
9908 	RTE_SET_USED(size);
9909 	arg = ARGS_ENTRY_ARB_BOUNDED
9910 		(offsetof(struct action_raw_decap_data, idx),
9911 		 sizeof(((struct action_raw_decap_data *)0)->idx),
9912 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9913 	if (push_args(ctx, arg))
9914 		return -1;
9915 	ret = parse_int(ctx, token, str, len, NULL, 0);
9916 	if (ret < 0) {
9917 		pop_args(ctx);
9918 		return -1;
9919 	}
9920 	if (!ctx->object)
9921 		return len;
9922 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9923 	action_raw_decap_data = ctx->object;
9924 	idx = action_raw_decap_data->idx;
9925 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
9926 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
9927 	action->conf = &action_raw_decap_data->conf;
9928 	return len;
9929 }
9930 
9931 
9932 static int
9933 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
9934 				const char *str, unsigned int len, void *buf,
9935 				unsigned int size)
9936 {
9937 	struct action_raw_encap_data *action_raw_encap_data;
9938 	struct rte_flow_action *action;
9939 	const struct arg *arg;
9940 	struct buffer *out = buf;
9941 	int ret;
9942 	uint16_t idx;
9943 
9944 	RTE_SET_USED(token);
9945 	RTE_SET_USED(buf);
9946 	RTE_SET_USED(size);
9947 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
9948 		return -1;
9949 	arg = ARGS_ENTRY_ARB_BOUNDED
9950 		(offsetof(struct action_raw_encap_data, idx),
9951 		 sizeof(((struct action_raw_encap_data *)0)->idx),
9952 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9953 	if (push_args(ctx, arg))
9954 		return -1;
9955 	ret = parse_int(ctx, token, str, len, NULL, 0);
9956 	if (ret < 0) {
9957 		pop_args(ctx);
9958 		return -1;
9959 	}
9960 	if (!ctx->object)
9961 		return len;
9962 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9963 	action_raw_encap_data = ctx->object;
9964 	idx = action_raw_encap_data->idx;
9965 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
9966 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
9967 	action_raw_encap_data->conf.preserve = NULL;
9968 	action->conf = &action_raw_encap_data->conf;
9969 	return len;
9970 }
9971 
9972 static int
9973 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
9974 			  const char *str, unsigned int len, void *buf,
9975 			  unsigned int size)
9976 {
9977 	struct buffer *out = buf;
9978 	int ret;
9979 
9980 	ret = parse_vc(ctx, token, str, len, buf, size);
9981 	if (ret < 0)
9982 		return ret;
9983 	/* Nothing else to do if there is no buffer. */
9984 	if (!out)
9985 		return ret;
9986 	if (!out->args.vc.actions_n)
9987 		return -1;
9988 	/* Point to selected object. */
9989 	ctx->object = out->args.vc.data;
9990 	ctx->objmask = NULL;
9991 	return ret;
9992 }
9993 
9994 static int
9995 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
9996 			  const char *str, unsigned int len, void *buf,
9997 			  unsigned int size)
9998 {
9999 	struct buffer *out = buf;
10000 	struct rte_flow_action *action;
10001 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10002 	int ret;
10003 
10004 	ret = parse_vc(ctx, token, str, len, buf, size);
10005 	if (ret < 0)
10006 		return ret;
10007 	/* Nothing else to do if there is no buffer. */
10008 	if (!out)
10009 		return ret;
10010 	if (!out->args.vc.actions_n)
10011 		return -1;
10012 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10013 	/* Point to selected object. */
10014 	ctx->object = out->args.vc.data;
10015 	ctx->objmask = NULL;
10016 	/* Copy the headers to the buffer. */
10017 	action_raw_decap_data = ctx->object;
10018 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10019 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10020 	action->conf = &action_raw_decap_data->conf;
10021 	return ret;
10022 }
10023 
10024 static int
10025 parse_vc_action_ipv6_ext_remove(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 	struct rte_flow_action *action;
10031 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10032 	int ret;
10033 
10034 	ret = parse_vc(ctx, token, str, len, buf, size);
10035 	if (ret < 0)
10036 		return ret;
10037 	/* Nothing else to do if there is no buffer. */
10038 	if (!out)
10039 		return ret;
10040 	if (!out->args.vc.actions_n)
10041 		return -1;
10042 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10043 	/* Point to selected object. */
10044 	ctx->object = out->args.vc.data;
10045 	ctx->objmask = NULL;
10046 	/* Copy the headers to the buffer. */
10047 	ipv6_ext_remove_data = ctx->object;
10048 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10049 	action->conf = &ipv6_ext_remove_data->conf;
10050 	return ret;
10051 }
10052 
10053 static int
10054 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10055 				      const char *str, unsigned int len, void *buf,
10056 				      unsigned int size)
10057 {
10058 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10059 	struct rte_flow_action *action;
10060 	const struct arg *arg;
10061 	struct buffer *out = buf;
10062 	int ret;
10063 	uint16_t idx;
10064 
10065 	RTE_SET_USED(token);
10066 	RTE_SET_USED(buf);
10067 	RTE_SET_USED(size);
10068 	arg = ARGS_ENTRY_ARB_BOUNDED
10069 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10070 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10071 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10072 	if (push_args(ctx, arg))
10073 		return -1;
10074 	ret = parse_int(ctx, token, str, len, NULL, 0);
10075 	if (ret < 0) {
10076 		pop_args(ctx);
10077 		return -1;
10078 	}
10079 	if (!ctx->object)
10080 		return len;
10081 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10082 	action_ipv6_ext_remove_data = ctx->object;
10083 	idx = action_ipv6_ext_remove_data->idx;
10084 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10085 	action->conf = &action_ipv6_ext_remove_data->conf;
10086 	return len;
10087 }
10088 
10089 static int
10090 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10091 			      const char *str, unsigned int len, void *buf,
10092 			      unsigned int size)
10093 {
10094 	struct buffer *out = buf;
10095 	struct rte_flow_action *action;
10096 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10097 	int ret;
10098 
10099 	ret = parse_vc(ctx, token, str, len, buf, size);
10100 	if (ret < 0)
10101 		return ret;
10102 	/* Nothing else to do if there is no buffer. */
10103 	if (!out)
10104 		return ret;
10105 	if (!out->args.vc.actions_n)
10106 		return -1;
10107 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10108 	/* Point to selected object. */
10109 	ctx->object = out->args.vc.data;
10110 	ctx->objmask = NULL;
10111 	/* Copy the headers to the buffer. */
10112 	ipv6_ext_push_data = ctx->object;
10113 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10114 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10115 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10116 	action->conf = &ipv6_ext_push_data->conf;
10117 	return ret;
10118 }
10119 
10120 static int
10121 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10122 				    const char *str, unsigned int len, void *buf,
10123 				    unsigned int size)
10124 {
10125 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10126 	struct rte_flow_action *action;
10127 	const struct arg *arg;
10128 	struct buffer *out = buf;
10129 	int ret;
10130 	uint16_t idx;
10131 
10132 	RTE_SET_USED(token);
10133 	RTE_SET_USED(buf);
10134 	RTE_SET_USED(size);
10135 	arg = ARGS_ENTRY_ARB_BOUNDED
10136 		(offsetof(struct action_ipv6_ext_push_data, idx),
10137 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10138 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10139 	if (push_args(ctx, arg))
10140 		return -1;
10141 	ret = parse_int(ctx, token, str, len, NULL, 0);
10142 	if (ret < 0) {
10143 		pop_args(ctx);
10144 		return -1;
10145 	}
10146 	if (!ctx->object)
10147 		return len;
10148 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10149 	action_ipv6_ext_push_data = ctx->object;
10150 	idx = action_ipv6_ext_push_data->idx;
10151 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10152 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10153 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10154 	action->conf = &action_ipv6_ext_push_data->conf;
10155 	return len;
10156 }
10157 
10158 static int
10159 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10160 			 const char *str, unsigned int len, void *buf,
10161 			 unsigned int size)
10162 {
10163 	int ret;
10164 
10165 	ret = parse_vc(ctx, token, str, len, buf, size);
10166 	if (ret < 0)
10167 		return ret;
10168 	ret = rte_flow_dynf_metadata_register();
10169 	if (ret < 0)
10170 		return -1;
10171 	return len;
10172 }
10173 
10174 static int
10175 parse_vc_action_sample(struct context *ctx, const struct token *token,
10176 			 const char *str, unsigned int len, void *buf,
10177 			 unsigned int size)
10178 {
10179 	struct buffer *out = buf;
10180 	struct rte_flow_action *action;
10181 	struct action_sample_data *action_sample_data = NULL;
10182 	static struct rte_flow_action end_action = {
10183 		RTE_FLOW_ACTION_TYPE_END, 0
10184 	};
10185 	int ret;
10186 
10187 	ret = parse_vc(ctx, token, str, len, buf, size);
10188 	if (ret < 0)
10189 		return ret;
10190 	/* Nothing else to do if there is no buffer. */
10191 	if (!out)
10192 		return ret;
10193 	if (!out->args.vc.actions_n)
10194 		return -1;
10195 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10196 	/* Point to selected object. */
10197 	ctx->object = out->args.vc.data;
10198 	ctx->objmask = NULL;
10199 	/* Copy the headers to the buffer. */
10200 	action_sample_data = ctx->object;
10201 	action_sample_data->conf.actions = &end_action;
10202 	action->conf = &action_sample_data->conf;
10203 	return ret;
10204 }
10205 
10206 static int
10207 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10208 				const char *str, unsigned int len, void *buf,
10209 				unsigned int size)
10210 {
10211 	struct action_sample_data *action_sample_data;
10212 	struct rte_flow_action *action;
10213 	const struct arg *arg;
10214 	struct buffer *out = buf;
10215 	int ret;
10216 	uint16_t idx;
10217 
10218 	RTE_SET_USED(token);
10219 	RTE_SET_USED(buf);
10220 	RTE_SET_USED(size);
10221 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10222 		return -1;
10223 	arg = ARGS_ENTRY_ARB_BOUNDED
10224 		(offsetof(struct action_sample_data, idx),
10225 		 sizeof(((struct action_sample_data *)0)->idx),
10226 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10227 	if (push_args(ctx, arg))
10228 		return -1;
10229 	ret = parse_int(ctx, token, str, len, NULL, 0);
10230 	if (ret < 0) {
10231 		pop_args(ctx);
10232 		return -1;
10233 	}
10234 	if (!ctx->object)
10235 		return len;
10236 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10237 	action_sample_data = ctx->object;
10238 	idx = action_sample_data->idx;
10239 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10240 	action->conf = &action_sample_data->conf;
10241 	return len;
10242 }
10243 
10244 /** Parse operation for modify_field command. */
10245 static int
10246 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10247 			 const char *str, unsigned int len, void *buf,
10248 			 unsigned int size)
10249 {
10250 	struct rte_flow_action_modify_field *action_modify_field;
10251 	unsigned int i;
10252 
10253 	(void)token;
10254 	(void)buf;
10255 	(void)size;
10256 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10257 		return -1;
10258 	for (i = 0; modify_field_ops[i]; ++i)
10259 		if (!strcmp_partial(modify_field_ops[i], str, len))
10260 			break;
10261 	if (!modify_field_ops[i])
10262 		return -1;
10263 	if (!ctx->object)
10264 		return len;
10265 	action_modify_field = ctx->object;
10266 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10267 	return len;
10268 }
10269 
10270 /** Parse id for modify_field command. */
10271 static int
10272 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10273 			 const char *str, unsigned int len, void *buf,
10274 			 unsigned int size)
10275 {
10276 	struct rte_flow_action_modify_field *action_modify_field;
10277 	unsigned int i;
10278 
10279 	(void)token;
10280 	(void)buf;
10281 	(void)size;
10282 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10283 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10284 		return -1;
10285 	for (i = 0; flow_field_ids[i]; ++i)
10286 		if (!strcmp_partial(flow_field_ids[i], str, len))
10287 			break;
10288 	if (!flow_field_ids[i])
10289 		return -1;
10290 	if (!ctx->object)
10291 		return len;
10292 	action_modify_field = ctx->object;
10293 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10294 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10295 	else
10296 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10297 	return len;
10298 }
10299 
10300 /** Parse level for modify_field command. */
10301 static int
10302 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10303 			 const char *str, unsigned int len, void *buf,
10304 			 unsigned int size)
10305 {
10306 	struct rte_flow_action_modify_field *action;
10307 	struct flex_item *fp = NULL;
10308 	uint32_t val;
10309 	struct buffer *out = buf;
10310 	char *end;
10311 
10312 	(void)token;
10313 	(void)size;
10314 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10315 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10316 		return -1;
10317 	if (!ctx->object)
10318 		return len;
10319 	action = ctx->object;
10320 	errno = 0;
10321 	val = strtoumax(str, &end, 0);
10322 	if (errno || (size_t)(end - str) != len)
10323 		return -1;
10324 	/* No need to validate action template mask value */
10325 	if (out->args.vc.masks) {
10326 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10327 			action->dst.level = val;
10328 		else
10329 			action->src.level = val;
10330 		return len;
10331 	}
10332 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10333 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10334 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10335 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10336 		if (val >= FLEX_MAX_PARSERS_NUM) {
10337 			printf("Bad flex item handle\n");
10338 			return -1;
10339 		}
10340 		fp = flex_items[ctx->port][val];
10341 		if (!fp) {
10342 			printf("Bad flex item handle\n");
10343 			return -1;
10344 		}
10345 	}
10346 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10347 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10348 			action->dst.level = val;
10349 		else
10350 			action->dst.flex_handle = fp->flex_handle;
10351 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10352 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10353 			action->src.level = val;
10354 		else
10355 			action->src.flex_handle = fp->flex_handle;
10356 	}
10357 	return len;
10358 }
10359 
10360 /** Parse the conntrack update, not a rte_flow_action. */
10361 static int
10362 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10363 			 const char *str, unsigned int len, void *buf,
10364 			 unsigned int size)
10365 {
10366 	struct buffer *out = buf;
10367 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10368 
10369 	(void)size;
10370 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10371 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10372 		return -1;
10373 	/* Token name must match. */
10374 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10375 		return -1;
10376 	/* Nothing else to do if there is no buffer. */
10377 	if (!out)
10378 		return len;
10379 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10380 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10381 		ct_modify->new_ct.is_original_dir =
10382 				conntrack_context.is_original_dir;
10383 		ct_modify->direction = 1;
10384 	} else {
10385 		uint32_t old_dir;
10386 
10387 		old_dir = ct_modify->new_ct.is_original_dir;
10388 		memcpy(&ct_modify->new_ct, &conntrack_context,
10389 		       sizeof(conntrack_context));
10390 		ct_modify->new_ct.is_original_dir = old_dir;
10391 		ct_modify->state = 1;
10392 	}
10393 	return len;
10394 }
10395 
10396 /** Parse tokens for destroy command. */
10397 static int
10398 parse_destroy(struct context *ctx, const struct token *token,
10399 	      const char *str, unsigned int len,
10400 	      void *buf, unsigned int size)
10401 {
10402 	struct buffer *out = buf;
10403 
10404 	/* Token name must match. */
10405 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10406 		return -1;
10407 	/* Nothing else to do if there is no buffer. */
10408 	if (!out)
10409 		return len;
10410 	if (!out->command) {
10411 		if (ctx->curr != DESTROY)
10412 			return -1;
10413 		if (sizeof(*out) > size)
10414 			return -1;
10415 		out->command = ctx->curr;
10416 		ctx->objdata = 0;
10417 		ctx->object = out;
10418 		ctx->objmask = NULL;
10419 		out->args.destroy.rule =
10420 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10421 					       sizeof(double));
10422 		return len;
10423 	}
10424 	if (ctx->curr == DESTROY_IS_USER_ID) {
10425 		out->args.destroy.is_user_id = true;
10426 		return len;
10427 	}
10428 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10429 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10430 		return -1;
10431 	ctx->objdata = 0;
10432 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10433 	ctx->objmask = NULL;
10434 	return len;
10435 }
10436 
10437 /** Parse tokens for flush command. */
10438 static int
10439 parse_flush(struct context *ctx, const struct token *token,
10440 	    const char *str, unsigned int len,
10441 	    void *buf, unsigned int size)
10442 {
10443 	struct buffer *out = buf;
10444 
10445 	/* Token name must match. */
10446 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10447 		return -1;
10448 	/* Nothing else to do if there is no buffer. */
10449 	if (!out)
10450 		return len;
10451 	if (!out->command) {
10452 		if (ctx->curr != FLUSH)
10453 			return -1;
10454 		if (sizeof(*out) > size)
10455 			return -1;
10456 		out->command = ctx->curr;
10457 		ctx->objdata = 0;
10458 		ctx->object = out;
10459 		ctx->objmask = NULL;
10460 	}
10461 	return len;
10462 }
10463 
10464 /** Parse tokens for dump command. */
10465 static int
10466 parse_dump(struct context *ctx, const struct token *token,
10467 	    const char *str, unsigned int len,
10468 	    void *buf, unsigned int size)
10469 {
10470 	struct buffer *out = buf;
10471 
10472 	/* Token name must match. */
10473 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10474 		return -1;
10475 	/* Nothing else to do if there is no buffer. */
10476 	if (!out)
10477 		return len;
10478 	if (!out->command) {
10479 		if (ctx->curr != DUMP)
10480 			return -1;
10481 		if (sizeof(*out) > size)
10482 			return -1;
10483 		out->command = ctx->curr;
10484 		ctx->objdata = 0;
10485 		ctx->object = out;
10486 		ctx->objmask = NULL;
10487 		return len;
10488 	}
10489 	switch (ctx->curr) {
10490 	case DUMP_ALL:
10491 	case DUMP_ONE:
10492 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10493 		out->command = ctx->curr;
10494 		ctx->objdata = 0;
10495 		ctx->object = out;
10496 		ctx->objmask = NULL;
10497 		return len;
10498 	case DUMP_IS_USER_ID:
10499 		out->args.dump.is_user_id = true;
10500 		return len;
10501 	default:
10502 		return -1;
10503 	}
10504 }
10505 
10506 /** Parse tokens for query command. */
10507 static int
10508 parse_query(struct context *ctx, const struct token *token,
10509 	    const char *str, unsigned int len,
10510 	    void *buf, unsigned int size)
10511 {
10512 	struct buffer *out = buf;
10513 
10514 	/* Token name must match. */
10515 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10516 		return -1;
10517 	/* Nothing else to do if there is no buffer. */
10518 	if (!out)
10519 		return len;
10520 	if (!out->command) {
10521 		if (ctx->curr != QUERY)
10522 			return -1;
10523 		if (sizeof(*out) > size)
10524 			return -1;
10525 		out->command = ctx->curr;
10526 		ctx->objdata = 0;
10527 		ctx->object = out;
10528 		ctx->objmask = NULL;
10529 	}
10530 	if (ctx->curr == QUERY_IS_USER_ID) {
10531 		out->args.query.is_user_id = true;
10532 		return len;
10533 	}
10534 	return len;
10535 }
10536 
10537 /** Parse action names. */
10538 static int
10539 parse_action(struct context *ctx, const struct token *token,
10540 	     const char *str, unsigned int len,
10541 	     void *buf, unsigned int size)
10542 {
10543 	struct buffer *out = buf;
10544 	const struct arg *arg = pop_args(ctx);
10545 	unsigned int i;
10546 
10547 	(void)size;
10548 	/* Argument is expected. */
10549 	if (!arg)
10550 		return -1;
10551 	/* Parse action name. */
10552 	for (i = 0; next_action[i]; ++i) {
10553 		const struct parse_action_priv *priv;
10554 
10555 		token = &token_list[next_action[i]];
10556 		if (strcmp_partial(token->name, str, len))
10557 			continue;
10558 		priv = token->priv;
10559 		if (!priv)
10560 			goto error;
10561 		if (out)
10562 			memcpy((uint8_t *)ctx->object + arg->offset,
10563 			       &priv->type,
10564 			       arg->size);
10565 		return len;
10566 	}
10567 error:
10568 	push_args(ctx, arg);
10569 	return -1;
10570 }
10571 
10572 /** Parse tokens for list command. */
10573 static int
10574 parse_list(struct context *ctx, const struct token *token,
10575 	   const char *str, unsigned int len,
10576 	   void *buf, unsigned int size)
10577 {
10578 	struct buffer *out = buf;
10579 
10580 	/* Token name must match. */
10581 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10582 		return -1;
10583 	/* Nothing else to do if there is no buffer. */
10584 	if (!out)
10585 		return len;
10586 	if (!out->command) {
10587 		if (ctx->curr != LIST)
10588 			return -1;
10589 		if (sizeof(*out) > size)
10590 			return -1;
10591 		out->command = ctx->curr;
10592 		ctx->objdata = 0;
10593 		ctx->object = out;
10594 		ctx->objmask = NULL;
10595 		out->args.list.group =
10596 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10597 					       sizeof(double));
10598 		return len;
10599 	}
10600 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10601 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10602 		return -1;
10603 	ctx->objdata = 0;
10604 	ctx->object = out->args.list.group + out->args.list.group_n++;
10605 	ctx->objmask = NULL;
10606 	return len;
10607 }
10608 
10609 /** Parse tokens for list all aged flows command. */
10610 static int
10611 parse_aged(struct context *ctx, const struct token *token,
10612 	   const char *str, unsigned int len,
10613 	   void *buf, unsigned int size)
10614 {
10615 	struct buffer *out = buf;
10616 
10617 	/* Token name must match. */
10618 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10619 		return -1;
10620 	/* Nothing else to do if there is no buffer. */
10621 	if (!out)
10622 		return len;
10623 	if (!out->command || out->command == QUEUE) {
10624 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10625 			return -1;
10626 		if (sizeof(*out) > size)
10627 			return -1;
10628 		out->command = ctx->curr;
10629 		ctx->objdata = 0;
10630 		ctx->object = out;
10631 		ctx->objmask = NULL;
10632 	}
10633 	if (ctx->curr == AGED_DESTROY)
10634 		out->args.aged.destroy = 1;
10635 	return len;
10636 }
10637 
10638 /** Parse tokens for isolate command. */
10639 static int
10640 parse_isolate(struct context *ctx, const struct token *token,
10641 	      const char *str, unsigned int len,
10642 	      void *buf, unsigned int size)
10643 {
10644 	struct buffer *out = buf;
10645 
10646 	/* Token name must match. */
10647 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10648 		return -1;
10649 	/* Nothing else to do if there is no buffer. */
10650 	if (!out)
10651 		return len;
10652 	if (!out->command) {
10653 		if (ctx->curr != ISOLATE)
10654 			return -1;
10655 		if (sizeof(*out) > size)
10656 			return -1;
10657 		out->command = ctx->curr;
10658 		ctx->objdata = 0;
10659 		ctx->object = out;
10660 		ctx->objmask = NULL;
10661 	}
10662 	return len;
10663 }
10664 
10665 /** Parse tokens for info/configure command. */
10666 static int
10667 parse_configure(struct context *ctx, const struct token *token,
10668 		const char *str, unsigned int len,
10669 		void *buf, unsigned int size)
10670 {
10671 	struct buffer *out = buf;
10672 
10673 	/* Token name must match. */
10674 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10675 		return -1;
10676 	/* Nothing else to do if there is no buffer. */
10677 	if (!out)
10678 		return len;
10679 	if (!out->command) {
10680 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10681 			return -1;
10682 		if (sizeof(*out) > size)
10683 			return -1;
10684 		out->command = ctx->curr;
10685 		ctx->objdata = 0;
10686 		ctx->object = out;
10687 		ctx->objmask = NULL;
10688 	}
10689 	return len;
10690 }
10691 
10692 /** Parse tokens for template create command. */
10693 static int
10694 parse_template(struct context *ctx, const struct token *token,
10695 	       const char *str, unsigned int len,
10696 	       void *buf, unsigned int size)
10697 {
10698 	struct buffer *out = buf;
10699 
10700 	/* Token name must match. */
10701 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10702 		return -1;
10703 	/* Nothing else to do if there is no buffer. */
10704 	if (!out)
10705 		return len;
10706 	if (!out->command) {
10707 		if (ctx->curr != PATTERN_TEMPLATE &&
10708 		    ctx->curr != ACTIONS_TEMPLATE)
10709 			return -1;
10710 		if (sizeof(*out) > size)
10711 			return -1;
10712 		out->command = ctx->curr;
10713 		ctx->objdata = 0;
10714 		ctx->object = out;
10715 		ctx->objmask = NULL;
10716 		out->args.vc.data = (uint8_t *)out + size;
10717 		return len;
10718 	}
10719 	switch (ctx->curr) {
10720 	case PATTERN_TEMPLATE_CREATE:
10721 		out->args.vc.pattern =
10722 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10723 					       sizeof(double));
10724 		out->args.vc.pat_templ_id = UINT32_MAX;
10725 		out->command = ctx->curr;
10726 		ctx->objdata = 0;
10727 		ctx->object = out;
10728 		ctx->objmask = NULL;
10729 		return len;
10730 	case PATTERN_TEMPLATE_EGRESS:
10731 		out->args.vc.attr.egress = 1;
10732 		return len;
10733 	case PATTERN_TEMPLATE_INGRESS:
10734 		out->args.vc.attr.ingress = 1;
10735 		return len;
10736 	case PATTERN_TEMPLATE_TRANSFER:
10737 		out->args.vc.attr.transfer = 1;
10738 		return len;
10739 	case ACTIONS_TEMPLATE_CREATE:
10740 		out->args.vc.act_templ_id = UINT32_MAX;
10741 		out->command = ctx->curr;
10742 		ctx->objdata = 0;
10743 		ctx->object = out;
10744 		ctx->objmask = NULL;
10745 		return len;
10746 	case ACTIONS_TEMPLATE_SPEC:
10747 		out->args.vc.actions =
10748 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10749 					       sizeof(double));
10750 		ctx->object = out->args.vc.actions;
10751 		ctx->objmask = NULL;
10752 		return len;
10753 	case ACTIONS_TEMPLATE_MASK:
10754 		out->args.vc.masks =
10755 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10756 					       (out->args.vc.actions +
10757 						out->args.vc.actions_n),
10758 					       sizeof(double));
10759 		ctx->object = out->args.vc.masks;
10760 		ctx->objmask = NULL;
10761 		return len;
10762 	case ACTIONS_TEMPLATE_EGRESS:
10763 		out->args.vc.attr.egress = 1;
10764 		return len;
10765 	case ACTIONS_TEMPLATE_INGRESS:
10766 		out->args.vc.attr.ingress = 1;
10767 		return len;
10768 	case ACTIONS_TEMPLATE_TRANSFER:
10769 		out->args.vc.attr.transfer = 1;
10770 		return len;
10771 	default:
10772 		return -1;
10773 	}
10774 }
10775 
10776 /** Parse tokens for template destroy command. */
10777 static int
10778 parse_template_destroy(struct context *ctx, const struct token *token,
10779 		       const char *str, unsigned int len,
10780 		       void *buf, unsigned int size)
10781 {
10782 	struct buffer *out = buf;
10783 	uint32_t *template_id;
10784 
10785 	/* Token name must match. */
10786 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10787 		return -1;
10788 	/* Nothing else to do if there is no buffer. */
10789 	if (!out)
10790 		return len;
10791 	if (!out->command ||
10792 		out->command == PATTERN_TEMPLATE ||
10793 		out->command == ACTIONS_TEMPLATE) {
10794 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10795 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10796 			return -1;
10797 		if (sizeof(*out) > size)
10798 			return -1;
10799 		out->command = ctx->curr;
10800 		ctx->objdata = 0;
10801 		ctx->object = out;
10802 		ctx->objmask = NULL;
10803 		out->args.templ_destroy.template_id =
10804 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10805 					       sizeof(double));
10806 		return len;
10807 	}
10808 	template_id = out->args.templ_destroy.template_id
10809 		    + out->args.templ_destroy.template_id_n++;
10810 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10811 		return -1;
10812 	ctx->objdata = 0;
10813 	ctx->object = template_id;
10814 	ctx->objmask = NULL;
10815 	return len;
10816 }
10817 
10818 /** Parse tokens for table create command. */
10819 static int
10820 parse_table(struct context *ctx, const struct token *token,
10821 	    const char *str, unsigned int len,
10822 	    void *buf, unsigned int size)
10823 {
10824 	struct buffer *out = buf;
10825 	uint32_t *template_id;
10826 
10827 	/* Token name must match. */
10828 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10829 		return -1;
10830 	/* Nothing else to do if there is no buffer. */
10831 	if (!out)
10832 		return len;
10833 	if (!out->command) {
10834 		if (ctx->curr != TABLE)
10835 			return -1;
10836 		if (sizeof(*out) > size)
10837 			return -1;
10838 		out->command = ctx->curr;
10839 		ctx->objdata = 0;
10840 		ctx->object = out;
10841 		ctx->objmask = NULL;
10842 		return len;
10843 	}
10844 	switch (ctx->curr) {
10845 	case TABLE_CREATE:
10846 	case TABLE_RESIZE:
10847 		out->command = ctx->curr;
10848 		ctx->objdata = 0;
10849 		ctx->object = out;
10850 		ctx->objmask = NULL;
10851 		out->args.table.id = UINT32_MAX;
10852 		return len;
10853 	case TABLE_PATTERN_TEMPLATE:
10854 		out->args.table.pat_templ_id =
10855 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10856 					       sizeof(double));
10857 		template_id = out->args.table.pat_templ_id
10858 				+ out->args.table.pat_templ_id_n++;
10859 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10860 			return -1;
10861 		ctx->objdata = 0;
10862 		ctx->object = template_id;
10863 		ctx->objmask = NULL;
10864 		return len;
10865 	case TABLE_ACTIONS_TEMPLATE:
10866 		out->args.table.act_templ_id =
10867 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10868 					       (out->args.table.pat_templ_id +
10869 						out->args.table.pat_templ_id_n),
10870 					       sizeof(double));
10871 		template_id = out->args.table.act_templ_id
10872 				+ out->args.table.act_templ_id_n++;
10873 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10874 			return -1;
10875 		ctx->objdata = 0;
10876 		ctx->object = template_id;
10877 		ctx->objmask = NULL;
10878 		return len;
10879 	case TABLE_INGRESS:
10880 		out->args.table.attr.flow_attr.ingress = 1;
10881 		return len;
10882 	case TABLE_EGRESS:
10883 		out->args.table.attr.flow_attr.egress = 1;
10884 		return len;
10885 	case TABLE_TRANSFER:
10886 		out->args.table.attr.flow_attr.transfer = 1;
10887 		return len;
10888 	case TABLE_TRANSFER_WIRE_ORIG:
10889 		if (!out->args.table.attr.flow_attr.transfer)
10890 			return -1;
10891 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
10892 		return len;
10893 	case TABLE_TRANSFER_VPORT_ORIG:
10894 		if (!out->args.table.attr.flow_attr.transfer)
10895 			return -1;
10896 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
10897 		return len;
10898 	case TABLE_RESIZABLE:
10899 		out->args.table.attr.specialize |=
10900 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
10901 		return len;
10902 	case TABLE_RULES_NUMBER:
10903 		ctx->objdata = 0;
10904 		ctx->object = out;
10905 		ctx->objmask = NULL;
10906 		return len;
10907 	case TABLE_RESIZE_ID:
10908 	case TABLE_RESIZE_RULES_NUMBER:
10909 		return len;
10910 	default:
10911 		return -1;
10912 	}
10913 }
10914 
10915 /** Parse tokens for table destroy command. */
10916 static int
10917 parse_table_destroy(struct context *ctx, const struct token *token,
10918 		    const char *str, unsigned int len,
10919 		    void *buf, unsigned int size)
10920 {
10921 	struct buffer *out = buf;
10922 	uint32_t *table_id;
10923 
10924 	/* Token name must match. */
10925 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10926 		return -1;
10927 	/* Nothing else to do if there is no buffer. */
10928 	if (!out)
10929 		return len;
10930 	if (!out->command || out->command == TABLE) {
10931 		if (ctx->curr != TABLE_DESTROY &&
10932 		    ctx->curr != TABLE_RESIZE_COMPLETE)
10933 			return -1;
10934 		if (sizeof(*out) > size)
10935 			return -1;
10936 		out->command = ctx->curr;
10937 		ctx->objdata = 0;
10938 		ctx->object = out;
10939 		ctx->objmask = NULL;
10940 		out->args.table_destroy.table_id =
10941 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10942 					       sizeof(double));
10943 		return len;
10944 	}
10945 	table_id = out->args.table_destroy.table_id
10946 		    + out->args.table_destroy.table_id_n++;
10947 	if ((uint8_t *)table_id > (uint8_t *)out + size)
10948 		return -1;
10949 	ctx->objdata = 0;
10950 	ctx->object = table_id;
10951 	ctx->objmask = NULL;
10952 	return len;
10953 }
10954 
10955 /** Parse tokens for queue create commands. */
10956 static int
10957 parse_qo(struct context *ctx, const struct token *token,
10958 	 const char *str, unsigned int len,
10959 	 void *buf, unsigned int size)
10960 {
10961 	struct buffer *out = buf;
10962 
10963 	/* Token name must match. */
10964 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10965 		return -1;
10966 	/* Nothing else to do if there is no buffer. */
10967 	if (!out)
10968 		return len;
10969 	if (!out->command) {
10970 		if (ctx->curr != QUEUE)
10971 			return -1;
10972 		if (sizeof(*out) > size)
10973 			return -1;
10974 		out->command = ctx->curr;
10975 		ctx->objdata = 0;
10976 		ctx->object = out;
10977 		ctx->objmask = NULL;
10978 		out->args.vc.data = (uint8_t *)out + size;
10979 		return len;
10980 	}
10981 	switch (ctx->curr) {
10982 	case QUEUE_CREATE:
10983 	case QUEUE_UPDATE:
10984 		out->command = ctx->curr;
10985 		ctx->objdata = 0;
10986 		ctx->object = out;
10987 		ctx->objmask = NULL;
10988 		out->args.vc.rule_id = UINT32_MAX;
10989 		return len;
10990 	case QUEUE_TEMPLATE_TABLE:
10991 	case QUEUE_PATTERN_TEMPLATE:
10992 	case QUEUE_ACTIONS_TEMPLATE:
10993 	case QUEUE_CREATE_POSTPONE:
10994 	case QUEUE_RULE_ID:
10995 	case QUEUE_UPDATE_ID:
10996 		return len;
10997 	case ITEM_PATTERN:
10998 		out->args.vc.pattern =
10999 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11000 					       sizeof(double));
11001 		ctx->object = out->args.vc.pattern;
11002 		ctx->objmask = NULL;
11003 		return len;
11004 	case ACTIONS:
11005 		out->args.vc.actions =
11006 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11007 					       (out->args.vc.pattern +
11008 						out->args.vc.pattern_n),
11009 					       sizeof(double));
11010 		ctx->object = out->args.vc.actions;
11011 		ctx->objmask = NULL;
11012 		return len;
11013 	default:
11014 		return -1;
11015 	}
11016 }
11017 
11018 /** Parse tokens for queue destroy command. */
11019 static int
11020 parse_qo_destroy(struct context *ctx, const struct token *token,
11021 		 const char *str, unsigned int len,
11022 		 void *buf, unsigned int size)
11023 {
11024 	struct buffer *out = buf;
11025 	uint64_t *flow_id;
11026 
11027 	/* Token name must match. */
11028 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11029 		return -1;
11030 	/* Nothing else to do if there is no buffer. */
11031 	if (!out)
11032 		return len;
11033 	if (!out->command || out->command == QUEUE) {
11034 		if (ctx->curr != QUEUE_DESTROY &&
11035 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11036 			return -1;
11037 		if (sizeof(*out) > size)
11038 			return -1;
11039 		out->command = ctx->curr;
11040 		ctx->objdata = 0;
11041 		ctx->object = out;
11042 		ctx->objmask = NULL;
11043 		out->args.destroy.rule =
11044 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11045 					       sizeof(double));
11046 		return len;
11047 	}
11048 	switch (ctx->curr) {
11049 	case QUEUE_DESTROY_ID:
11050 		flow_id = out->args.destroy.rule
11051 				+ out->args.destroy.rule_n++;
11052 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11053 			return -1;
11054 		ctx->objdata = 0;
11055 		ctx->object = flow_id;
11056 		ctx->objmask = NULL;
11057 		return len;
11058 	case QUEUE_DESTROY_POSTPONE:
11059 		return len;
11060 	default:
11061 		return -1;
11062 	}
11063 }
11064 
11065 /** Parse tokens for push queue command. */
11066 static int
11067 parse_push(struct context *ctx, const struct token *token,
11068 	   const char *str, unsigned int len,
11069 	   void *buf, unsigned int size)
11070 {
11071 	struct buffer *out = buf;
11072 
11073 	/* Token name must match. */
11074 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11075 		return -1;
11076 	/* Nothing else to do if there is no buffer. */
11077 	if (!out)
11078 		return len;
11079 	if (!out->command) {
11080 		if (ctx->curr != PUSH)
11081 			return -1;
11082 		if (sizeof(*out) > size)
11083 			return -1;
11084 		out->command = ctx->curr;
11085 		ctx->objdata = 0;
11086 		ctx->object = out;
11087 		ctx->objmask = NULL;
11088 		out->args.vc.data = (uint8_t *)out + size;
11089 	}
11090 	return len;
11091 }
11092 
11093 /** Parse tokens for pull command. */
11094 static int
11095 parse_pull(struct context *ctx, const struct token *token,
11096 	   const char *str, unsigned int len,
11097 	   void *buf, unsigned int size)
11098 {
11099 	struct buffer *out = buf;
11100 
11101 	/* Token name must match. */
11102 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11103 		return -1;
11104 	/* Nothing else to do if there is no buffer. */
11105 	if (!out)
11106 		return len;
11107 	if (!out->command) {
11108 		if (ctx->curr != PULL)
11109 			return -1;
11110 		if (sizeof(*out) > size)
11111 			return -1;
11112 		out->command = ctx->curr;
11113 		ctx->objdata = 0;
11114 		ctx->object = out;
11115 		ctx->objmask = NULL;
11116 		out->args.vc.data = (uint8_t *)out + size;
11117 	}
11118 	return len;
11119 }
11120 
11121 /** Parse tokens for hash calculation commands. */
11122 static int
11123 parse_hash(struct context *ctx, const struct token *token,
11124 	 const char *str, unsigned int len,
11125 	 void *buf, unsigned int size)
11126 {
11127 	struct buffer *out = buf;
11128 
11129 	/* Token name must match. */
11130 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11131 		return -1;
11132 	/* Nothing else to do if there is no buffer. */
11133 	if (!out)
11134 		return len;
11135 	if (!out->command) {
11136 		if (ctx->curr != HASH)
11137 			return -1;
11138 		if (sizeof(*out) > size)
11139 			return -1;
11140 		out->command = ctx->curr;
11141 		ctx->objdata = 0;
11142 		ctx->object = out;
11143 		ctx->objmask = NULL;
11144 		out->args.vc.data = (uint8_t *)out + size;
11145 		return len;
11146 	}
11147 	switch (ctx->curr) {
11148 	case HASH_CALC_TABLE:
11149 	case HASH_CALC_PATTERN_INDEX:
11150 		return len;
11151 	case ITEM_PATTERN:
11152 		out->args.vc.pattern =
11153 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11154 					       sizeof(double));
11155 		ctx->object = out->args.vc.pattern;
11156 		ctx->objmask = NULL;
11157 		return len;
11158 	case HASH_CALC_ENCAP:
11159 		out->args.vc.encap_hash = 1;
11160 		return len;
11161 	case ENCAP_HASH_FIELD_SRC_PORT:
11162 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11163 		return len;
11164 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11165 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11166 		return len;
11167 	default:
11168 		return -1;
11169 	}
11170 }
11171 
11172 static int
11173 parse_group(struct context *ctx, const struct token *token,
11174 	    const char *str, unsigned int len,
11175 	    void *buf, unsigned int size)
11176 {
11177 	struct buffer *out = buf;
11178 
11179 	/* Token name must match. */
11180 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11181 		return -1;
11182 	/* Nothing else to do if there is no buffer. */
11183 	if (!out)
11184 		return len;
11185 	if (!out->command) {
11186 		if (ctx->curr != FLOW_GROUP)
11187 			return -1;
11188 		if (sizeof(*out) > size)
11189 			return -1;
11190 		out->command = ctx->curr;
11191 		ctx->objdata = 0;
11192 		ctx->object = out;
11193 		ctx->objmask = NULL;
11194 		out->args.vc.data = (uint8_t *)out + size;
11195 		return len;
11196 	}
11197 	switch (ctx->curr) {
11198 	case GROUP_INGRESS:
11199 		out->args.vc.attr.ingress = 1;
11200 		return len;
11201 	case GROUP_EGRESS:
11202 		out->args.vc.attr.egress = 1;
11203 		return len;
11204 	case GROUP_TRANSFER:
11205 		out->args.vc.attr.transfer = 1;
11206 		return len;
11207 	case GROUP_SET_MISS_ACTIONS:
11208 		out->command = ctx->curr;
11209 		ctx->objdata = 0;
11210 		ctx->object = out;
11211 		ctx->objmask = NULL;
11212 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11213 							       sizeof(double));
11214 		return len;
11215 	default:
11216 		return -1;
11217 	}
11218 }
11219 
11220 static int
11221 parse_flex(struct context *ctx, const struct token *token,
11222 	     const char *str, unsigned int len,
11223 	     void *buf, unsigned int size)
11224 {
11225 	struct buffer *out = buf;
11226 
11227 	/* Token name must match. */
11228 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11229 		return -1;
11230 	/* Nothing else to do if there is no buffer. */
11231 	if (!out)
11232 		return len;
11233 	if (out->command == ZERO) {
11234 		if (ctx->curr != FLEX)
11235 			return -1;
11236 		if (sizeof(*out) > size)
11237 			return -1;
11238 		out->command = ctx->curr;
11239 		ctx->objdata = 0;
11240 		ctx->object = out;
11241 		ctx->objmask = NULL;
11242 	} else {
11243 		switch (ctx->curr) {
11244 		default:
11245 			break;
11246 		case FLEX_ITEM_INIT:
11247 		case FLEX_ITEM_CREATE:
11248 		case FLEX_ITEM_DESTROY:
11249 			out->command = ctx->curr;
11250 			break;
11251 		}
11252 	}
11253 
11254 	return len;
11255 }
11256 
11257 static int
11258 parse_tunnel(struct context *ctx, const struct token *token,
11259 	     const char *str, unsigned int len,
11260 	     void *buf, unsigned int size)
11261 {
11262 	struct buffer *out = buf;
11263 
11264 	/* Token name must match. */
11265 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11266 		return -1;
11267 	/* Nothing else to do if there is no buffer. */
11268 	if (!out)
11269 		return len;
11270 	if (!out->command) {
11271 		if (ctx->curr != TUNNEL)
11272 			return -1;
11273 		if (sizeof(*out) > size)
11274 			return -1;
11275 		out->command = ctx->curr;
11276 		ctx->objdata = 0;
11277 		ctx->object = out;
11278 		ctx->objmask = NULL;
11279 	} else {
11280 		switch (ctx->curr) {
11281 		default:
11282 			break;
11283 		case TUNNEL_CREATE:
11284 		case TUNNEL_DESTROY:
11285 		case TUNNEL_LIST:
11286 			out->command = ctx->curr;
11287 			break;
11288 		case TUNNEL_CREATE_TYPE:
11289 		case TUNNEL_DESTROY_ID:
11290 			ctx->object = &out->args.vc.tunnel_ops;
11291 			break;
11292 		}
11293 	}
11294 
11295 	return len;
11296 }
11297 
11298 /**
11299  * Parse signed/unsigned integers 8 to 64-bit long.
11300  *
11301  * Last argument (ctx->args) is retrieved to determine integer type and
11302  * storage location.
11303  */
11304 static int
11305 parse_int(struct context *ctx, const struct token *token,
11306 	  const char *str, unsigned int len,
11307 	  void *buf, unsigned int size)
11308 {
11309 	const struct arg *arg = pop_args(ctx);
11310 	uintmax_t u;
11311 	char *end;
11312 
11313 	(void)token;
11314 	/* Argument is expected. */
11315 	if (!arg)
11316 		return -1;
11317 	errno = 0;
11318 	u = arg->sign ?
11319 		(uintmax_t)strtoimax(str, &end, 0) :
11320 		strtoumax(str, &end, 0);
11321 	if (errno || (size_t)(end - str) != len)
11322 		goto error;
11323 	if (arg->bounded &&
11324 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11325 			    (intmax_t)u > (intmax_t)arg->max)) ||
11326 	     (!arg->sign && (u < arg->min || u > arg->max))))
11327 		goto error;
11328 	if (!ctx->object)
11329 		return len;
11330 	if (arg->mask) {
11331 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11332 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11333 			goto error;
11334 		return len;
11335 	}
11336 	buf = (uint8_t *)ctx->object + arg->offset;
11337 	size = arg->size;
11338 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11339 		return -1;
11340 objmask:
11341 	switch (size) {
11342 	case sizeof(uint8_t):
11343 		*(uint8_t *)buf = u;
11344 		break;
11345 	case sizeof(uint16_t):
11346 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11347 		break;
11348 	case sizeof(uint8_t [3]):
11349 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11350 		if (!arg->hton) {
11351 			((uint8_t *)buf)[0] = u;
11352 			((uint8_t *)buf)[1] = u >> 8;
11353 			((uint8_t *)buf)[2] = u >> 16;
11354 			break;
11355 		}
11356 #endif
11357 		((uint8_t *)buf)[0] = u >> 16;
11358 		((uint8_t *)buf)[1] = u >> 8;
11359 		((uint8_t *)buf)[2] = u;
11360 		break;
11361 	case sizeof(uint32_t):
11362 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11363 		break;
11364 	case sizeof(uint64_t):
11365 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11366 		break;
11367 	default:
11368 		goto error;
11369 	}
11370 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11371 		u = -1;
11372 		buf = (uint8_t *)ctx->objmask + arg->offset;
11373 		goto objmask;
11374 	}
11375 	return len;
11376 error:
11377 	push_args(ctx, arg);
11378 	return -1;
11379 }
11380 
11381 /**
11382  * Parse a string.
11383  *
11384  * Three arguments (ctx->args) are retrieved from the stack to store data,
11385  * its actual length and address (in that order).
11386  */
11387 static int
11388 parse_string(struct context *ctx, const struct token *token,
11389 	     const char *str, unsigned int len,
11390 	     void *buf, unsigned int size)
11391 {
11392 	const struct arg *arg_data = pop_args(ctx);
11393 	const struct arg *arg_len = pop_args(ctx);
11394 	const struct arg *arg_addr = pop_args(ctx);
11395 	char tmp[16]; /* Ought to be enough. */
11396 	int ret;
11397 
11398 	/* Arguments are expected. */
11399 	if (!arg_data)
11400 		return -1;
11401 	if (!arg_len) {
11402 		push_args(ctx, arg_data);
11403 		return -1;
11404 	}
11405 	if (!arg_addr) {
11406 		push_args(ctx, arg_len);
11407 		push_args(ctx, arg_data);
11408 		return -1;
11409 	}
11410 	size = arg_data->size;
11411 	/* Bit-mask fill is not supported. */
11412 	if (arg_data->mask || size < len)
11413 		goto error;
11414 	if (!ctx->object)
11415 		return len;
11416 	/* Let parse_int() fill length information first. */
11417 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11418 	if (ret < 0)
11419 		goto error;
11420 	push_args(ctx, arg_len);
11421 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11422 	if (ret < 0) {
11423 		pop_args(ctx);
11424 		goto error;
11425 	}
11426 	buf = (uint8_t *)ctx->object + arg_data->offset;
11427 	/* Output buffer is not necessarily NUL-terminated. */
11428 	memcpy(buf, str, len);
11429 	memset((uint8_t *)buf + len, 0x00, size - len);
11430 	if (ctx->objmask)
11431 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11432 	/* Save address if requested. */
11433 	if (arg_addr->size) {
11434 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11435 		       (void *[]){
11436 			(uint8_t *)ctx->object + arg_data->offset
11437 		       },
11438 		       arg_addr->size);
11439 		if (ctx->objmask)
11440 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11441 			       (void *[]){
11442 				(uint8_t *)ctx->objmask + arg_data->offset
11443 			       },
11444 			       arg_addr->size);
11445 	}
11446 	return len;
11447 error:
11448 	push_args(ctx, arg_addr);
11449 	push_args(ctx, arg_len);
11450 	push_args(ctx, arg_data);
11451 	return -1;
11452 }
11453 
11454 static int
11455 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11456 {
11457 	const uint8_t *head = dst;
11458 	uint32_t left;
11459 
11460 	if (*size == 0)
11461 		return -1;
11462 
11463 	left = *size;
11464 
11465 	/* Convert chars to bytes */
11466 	while (left) {
11467 		char tmp[3], *end = tmp;
11468 		uint32_t read_lim = left & 1 ? 1 : 2;
11469 
11470 		snprintf(tmp, read_lim + 1, "%s", src);
11471 		*dst = strtoul(tmp, &end, 16);
11472 		if (*end) {
11473 			*dst = 0;
11474 			*size = (uint32_t)(dst - head);
11475 			return -1;
11476 		}
11477 		left -= read_lim;
11478 		src += read_lim;
11479 		dst++;
11480 	}
11481 	*dst = 0;
11482 	*size = (uint32_t)(dst - head);
11483 	return 0;
11484 }
11485 
11486 static int
11487 parse_hex(struct context *ctx, const struct token *token,
11488 		const char *str, unsigned int len,
11489 		void *buf, unsigned int size)
11490 {
11491 	const struct arg *arg_data = pop_args(ctx);
11492 	const struct arg *arg_len = pop_args(ctx);
11493 	const struct arg *arg_addr = pop_args(ctx);
11494 	char tmp[16]; /* Ought to be enough. */
11495 	int ret;
11496 	unsigned int hexlen = len;
11497 	unsigned int length = 256;
11498 	uint8_t hex_tmp[length];
11499 
11500 	/* Arguments are expected. */
11501 	if (!arg_data)
11502 		return -1;
11503 	if (!arg_len) {
11504 		push_args(ctx, arg_data);
11505 		return -1;
11506 	}
11507 	if (!arg_addr) {
11508 		push_args(ctx, arg_len);
11509 		push_args(ctx, arg_data);
11510 		return -1;
11511 	}
11512 	size = arg_data->size;
11513 	/* Bit-mask fill is not supported. */
11514 	if (arg_data->mask)
11515 		goto error;
11516 	if (!ctx->object)
11517 		return len;
11518 
11519 	/* translate bytes string to array. */
11520 	if (str[0] == '0' && ((str[1] == 'x') ||
11521 			(str[1] == 'X'))) {
11522 		str += 2;
11523 		hexlen -= 2;
11524 	}
11525 	if (hexlen > length)
11526 		goto error;
11527 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11528 	if (ret < 0)
11529 		goto error;
11530 	/* Check the converted binary fits into data buffer. */
11531 	if (hexlen > size)
11532 		goto error;
11533 	/* Let parse_int() fill length information first. */
11534 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11535 	if (ret < 0)
11536 		goto error;
11537 	/* Save length if requested. */
11538 	if (arg_len->size) {
11539 		push_args(ctx, arg_len);
11540 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11541 		if (ret < 0) {
11542 			pop_args(ctx);
11543 			goto error;
11544 		}
11545 	}
11546 	buf = (uint8_t *)ctx->object + arg_data->offset;
11547 	/* Output buffer is not necessarily NUL-terminated. */
11548 	memcpy(buf, hex_tmp, hexlen);
11549 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11550 	if (ctx->objmask)
11551 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11552 					0xff, hexlen);
11553 	/* Save address if requested. */
11554 	if (arg_addr->size) {
11555 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11556 		       (void *[]){
11557 			(uint8_t *)ctx->object + arg_data->offset
11558 		       },
11559 		       arg_addr->size);
11560 		if (ctx->objmask)
11561 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11562 			       (void *[]){
11563 				(uint8_t *)ctx->objmask + arg_data->offset
11564 			       },
11565 			       arg_addr->size);
11566 	}
11567 	return len;
11568 error:
11569 	push_args(ctx, arg_addr);
11570 	push_args(ctx, arg_len);
11571 	push_args(ctx, arg_data);
11572 	return -1;
11573 
11574 }
11575 
11576 /**
11577  * Parse a zero-ended string.
11578  */
11579 static int
11580 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11581 	     const char *str, unsigned int len,
11582 	     void *buf, unsigned int size)
11583 {
11584 	const struct arg *arg_data = pop_args(ctx);
11585 
11586 	/* Arguments are expected. */
11587 	if (!arg_data)
11588 		return -1;
11589 	size = arg_data->size;
11590 	/* Bit-mask fill is not supported. */
11591 	if (arg_data->mask || size < len + 1)
11592 		goto error;
11593 	if (!ctx->object)
11594 		return len;
11595 	buf = (uint8_t *)ctx->object + arg_data->offset;
11596 	strncpy(buf, str, len);
11597 	if (ctx->objmask)
11598 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11599 	return len;
11600 error:
11601 	push_args(ctx, arg_data);
11602 	return -1;
11603 }
11604 
11605 /**
11606  * Parse a MAC address.
11607  *
11608  * Last argument (ctx->args) is retrieved to determine storage size and
11609  * location.
11610  */
11611 static int
11612 parse_mac_addr(struct context *ctx, const struct token *token,
11613 	       const char *str, unsigned int len,
11614 	       void *buf, unsigned int size)
11615 {
11616 	const struct arg *arg = pop_args(ctx);
11617 	struct rte_ether_addr tmp;
11618 	int ret;
11619 
11620 	(void)token;
11621 	/* Argument is expected. */
11622 	if (!arg)
11623 		return -1;
11624 	size = arg->size;
11625 	/* Bit-mask fill is not supported. */
11626 	if (arg->mask || size != sizeof(tmp))
11627 		goto error;
11628 	/* Only network endian is supported. */
11629 	if (!arg->hton)
11630 		goto error;
11631 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11632 	if (ret < 0 || (unsigned int)ret != len)
11633 		goto error;
11634 	if (!ctx->object)
11635 		return len;
11636 	buf = (uint8_t *)ctx->object + arg->offset;
11637 	memcpy(buf, &tmp, size);
11638 	if (ctx->objmask)
11639 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11640 	return len;
11641 error:
11642 	push_args(ctx, arg);
11643 	return -1;
11644 }
11645 
11646 /**
11647  * Parse an IPv4 address.
11648  *
11649  * Last argument (ctx->args) is retrieved to determine storage size and
11650  * location.
11651  */
11652 static int
11653 parse_ipv4_addr(struct context *ctx, const struct token *token,
11654 		const char *str, unsigned int len,
11655 		void *buf, unsigned int size)
11656 {
11657 	const struct arg *arg = pop_args(ctx);
11658 	char str2[len + 1];
11659 	struct in_addr tmp;
11660 	int ret;
11661 
11662 	/* Argument is expected. */
11663 	if (!arg)
11664 		return -1;
11665 	size = arg->size;
11666 	/* Bit-mask fill is not supported. */
11667 	if (arg->mask || size != sizeof(tmp))
11668 		goto error;
11669 	/* Only network endian is supported. */
11670 	if (!arg->hton)
11671 		goto error;
11672 	memcpy(str2, str, len);
11673 	str2[len] = '\0';
11674 	ret = inet_pton(AF_INET, str2, &tmp);
11675 	if (ret != 1) {
11676 		/* Attempt integer parsing. */
11677 		push_args(ctx, arg);
11678 		return parse_int(ctx, token, str, len, buf, size);
11679 	}
11680 	if (!ctx->object)
11681 		return len;
11682 	buf = (uint8_t *)ctx->object + arg->offset;
11683 	memcpy(buf, &tmp, size);
11684 	if (ctx->objmask)
11685 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11686 	return len;
11687 error:
11688 	push_args(ctx, arg);
11689 	return -1;
11690 }
11691 
11692 /**
11693  * Parse an IPv6 address.
11694  *
11695  * Last argument (ctx->args) is retrieved to determine storage size and
11696  * location.
11697  */
11698 static int
11699 parse_ipv6_addr(struct context *ctx, const struct token *token,
11700 		const char *str, unsigned int len,
11701 		void *buf, unsigned int size)
11702 {
11703 	const struct arg *arg = pop_args(ctx);
11704 	char str2[len + 1];
11705 	struct in6_addr tmp;
11706 	int ret;
11707 
11708 	(void)token;
11709 	/* Argument is expected. */
11710 	if (!arg)
11711 		return -1;
11712 	size = arg->size;
11713 	/* Bit-mask fill is not supported. */
11714 	if (arg->mask || size != sizeof(tmp))
11715 		goto error;
11716 	/* Only network endian is supported. */
11717 	if (!arg->hton)
11718 		goto error;
11719 	memcpy(str2, str, len);
11720 	str2[len] = '\0';
11721 	ret = inet_pton(AF_INET6, str2, &tmp);
11722 	if (ret != 1)
11723 		goto error;
11724 	if (!ctx->object)
11725 		return len;
11726 	buf = (uint8_t *)ctx->object + arg->offset;
11727 	memcpy(buf, &tmp, size);
11728 	if (ctx->objmask)
11729 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11730 	return len;
11731 error:
11732 	push_args(ctx, arg);
11733 	return -1;
11734 }
11735 
11736 /** Boolean values (even indices stand for false). */
11737 static const char *const boolean_name[] = {
11738 	"0", "1",
11739 	"false", "true",
11740 	"no", "yes",
11741 	"N", "Y",
11742 	"off", "on",
11743 	NULL,
11744 };
11745 
11746 /**
11747  * Parse a boolean value.
11748  *
11749  * Last argument (ctx->args) is retrieved to determine storage size and
11750  * location.
11751  */
11752 static int
11753 parse_boolean(struct context *ctx, const struct token *token,
11754 	      const char *str, unsigned int len,
11755 	      void *buf, unsigned int size)
11756 {
11757 	const struct arg *arg = pop_args(ctx);
11758 	unsigned int i;
11759 	int ret;
11760 
11761 	/* Argument is expected. */
11762 	if (!arg)
11763 		return -1;
11764 	for (i = 0; boolean_name[i]; ++i)
11765 		if (!strcmp_partial(boolean_name[i], str, len))
11766 			break;
11767 	/* Process token as integer. */
11768 	if (boolean_name[i])
11769 		str = i & 1 ? "1" : "0";
11770 	push_args(ctx, arg);
11771 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11772 	return ret > 0 ? (int)len : ret;
11773 }
11774 
11775 /** Parse port and update context. */
11776 static int
11777 parse_port(struct context *ctx, const struct token *token,
11778 	   const char *str, unsigned int len,
11779 	   void *buf, unsigned int size)
11780 {
11781 	struct buffer *out = &(struct buffer){ .port = 0 };
11782 	int ret;
11783 
11784 	if (buf)
11785 		out = buf;
11786 	else {
11787 		ctx->objdata = 0;
11788 		ctx->object = out;
11789 		ctx->objmask = NULL;
11790 		size = sizeof(*out);
11791 	}
11792 	ret = parse_int(ctx, token, str, len, out, size);
11793 	if (ret >= 0)
11794 		ctx->port = out->port;
11795 	if (!buf)
11796 		ctx->object = NULL;
11797 	return ret;
11798 }
11799 
11800 /** Parse tokens for shared indirect actions. */
11801 static int
11802 parse_ia_port(struct context *ctx, const struct token *token,
11803 	      const char *str, unsigned int len,
11804 	      void *buf, unsigned int size)
11805 {
11806 	struct rte_flow_action *action = ctx->object;
11807 	uint32_t id;
11808 	int ret;
11809 
11810 	(void)buf;
11811 	(void)size;
11812 	ctx->objdata = 0;
11813 	ctx->object = &id;
11814 	ctx->objmask = NULL;
11815 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11816 	ctx->object = action;
11817 	if (ret != (int)len)
11818 		return ret;
11819 	/* set indirect action */
11820 	if (action)
11821 		action->conf = (void *)(uintptr_t)id;
11822 	return ret;
11823 }
11824 
11825 static int
11826 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11827 		const char *str, unsigned int len,
11828 		void *buf, unsigned int size)
11829 {
11830 	struct rte_flow_action *action = ctx->object;
11831 	uint32_t id;
11832 	int ret;
11833 
11834 	(void)buf;
11835 	(void)size;
11836 	ctx->objdata = 0;
11837 	ctx->object = &id;
11838 	ctx->objmask = NULL;
11839 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11840 	ctx->object = action;
11841 	if (ret != (int)len)
11842 		return ret;
11843 	/* set indirect action */
11844 	if (action) {
11845 		portid_t port_id = ctx->port;
11846 		if (ctx->prev == INDIRECT_ACTION_PORT)
11847 			port_id = (portid_t)(uintptr_t)action->conf;
11848 		action->conf = port_action_handle_get_by_id(port_id, id);
11849 		ret = (action->conf) ? ret : -1;
11850 	}
11851 	return ret;
11852 }
11853 
11854 static int
11855 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11856 		    const char *str, unsigned int len,
11857 		    __rte_unused void *buf, __rte_unused unsigned int size)
11858 {
11859 	struct rte_flow_action *action = ctx->object;
11860 	struct rte_flow_action_indirect_list *action_conf;
11861 	const struct indlst_conf *indlst_conf;
11862 	uint32_t id;
11863 	int ret;
11864 
11865 	if (!action)
11866 		return -1;
11867 	ctx->objdata = 0;
11868 	ctx->object = &id;
11869 	ctx->objmask = NULL;
11870 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11871 	if (ret != (int)len)
11872 		return ret;
11873 	ctx->object = action;
11874 	action_conf = (void *)(uintptr_t)action->conf;
11875 	action_conf->conf = NULL;
11876 	switch (ctx->curr) {
11877 	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
11878 	action_conf->handle = (typeof(action_conf->handle))
11879 				port_action_handle_get_by_id(ctx->port, id);
11880 		if (!action_conf->handle) {
11881 			printf("no indirect list handle for id %u\n", id);
11882 			return -1;
11883 		}
11884 		break;
11885 	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
11886 		indlst_conf = indirect_action_list_conf_get(id);
11887 		if (!indlst_conf)
11888 			return -1;
11889 		action_conf->conf = (const void **)indlst_conf->conf;
11890 		break;
11891 	default:
11892 		break;
11893 	}
11894 	return ret;
11895 }
11896 
11897 static int
11898 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
11899 		const char *str, unsigned int len,
11900 		void *buf, unsigned int size)
11901 {
11902 	struct rte_flow_action *action = ctx->object;
11903 	struct rte_flow_action_meter_mark *meter;
11904 	struct rte_flow_meter_profile *profile = NULL;
11905 	uint32_t id = 0;
11906 	int ret;
11907 
11908 	(void)buf;
11909 	(void)size;
11910 	ctx->objdata = 0;
11911 	ctx->object = &id;
11912 	ctx->objmask = NULL;
11913 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11914 	ctx->object = action;
11915 	if (ret != (int)len)
11916 		return ret;
11917 	/* set meter profile */
11918 	if (action) {
11919 		meter = (struct rte_flow_action_meter_mark *)
11920 			(uintptr_t)(action->conf);
11921 		profile = port_meter_profile_get_by_id(ctx->port, id);
11922 		meter->profile = profile;
11923 		ret = (profile) ? ret : -1;
11924 	}
11925 	return ret;
11926 }
11927 
11928 static int
11929 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
11930 		const char *str, unsigned int len,
11931 		void *buf, unsigned int size)
11932 {
11933 	struct rte_flow_action *action = ctx->object;
11934 	struct rte_flow_action_meter_mark *meter;
11935 	struct rte_flow_meter_policy *policy = NULL;
11936 	uint32_t id = 0;
11937 	int ret;
11938 
11939 	(void)buf;
11940 	(void)size;
11941 	ctx->objdata = 0;
11942 	ctx->object = &id;
11943 	ctx->objmask = NULL;
11944 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11945 	ctx->object = action;
11946 	if (ret != (int)len)
11947 		return ret;
11948 	/* set meter policy */
11949 	if (action) {
11950 		meter = (struct rte_flow_action_meter_mark *)
11951 			(uintptr_t)(action->conf);
11952 		policy = port_meter_policy_get_by_id(ctx->port, id);
11953 		meter->policy = policy;
11954 		ret = (policy) ? ret : -1;
11955 	}
11956 	return ret;
11957 }
11958 
11959 /** Parse set command, initialize output buffer for subsequent tokens. */
11960 static int
11961 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
11962 			  const char *str, unsigned int len,
11963 			  void *buf, unsigned int size)
11964 {
11965 	struct buffer *out = buf;
11966 
11967 	/* Token name must match. */
11968 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11969 		return -1;
11970 	/* Nothing else to do if there is no buffer. */
11971 	if (!out)
11972 		return len;
11973 	/* Make sure buffer is large enough. */
11974 	if (size < sizeof(*out))
11975 		return -1;
11976 	ctx->objdata = 0;
11977 	ctx->objmask = NULL;
11978 	ctx->object = out;
11979 	if (!out->command)
11980 		return -1;
11981 	out->command = ctx->curr;
11982 	/* For encap/decap we need is pattern */
11983 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11984 						       sizeof(double));
11985 	return len;
11986 }
11987 
11988 /** Parse set command, initialize output buffer for subsequent tokens. */
11989 static int
11990 parse_set_sample_action(struct context *ctx, const struct token *token,
11991 			  const char *str, unsigned int len,
11992 			  void *buf, unsigned int size)
11993 {
11994 	struct buffer *out = buf;
11995 
11996 	/* Token name must match. */
11997 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11998 		return -1;
11999 	/* Nothing else to do if there is no buffer. */
12000 	if (!out)
12001 		return len;
12002 	/* Make sure buffer is large enough. */
12003 	if (size < sizeof(*out))
12004 		return -1;
12005 	ctx->objdata = 0;
12006 	ctx->objmask = NULL;
12007 	ctx->object = out;
12008 	if (!out->command)
12009 		return -1;
12010 	out->command = ctx->curr;
12011 	/* For sampler we need is actions */
12012 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12013 						       sizeof(double));
12014 	return len;
12015 }
12016 
12017 /** Parse set command, initialize output buffer for subsequent tokens. */
12018 static int
12019 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12020 			  const char *str, unsigned int len,
12021 			  void *buf, unsigned int size)
12022 {
12023 	struct buffer *out = buf;
12024 
12025 	/* Token name must match. */
12026 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12027 		return -1;
12028 	/* Nothing else to do if there is no buffer. */
12029 	if (!out)
12030 		return len;
12031 	/* Make sure buffer is large enough. */
12032 	if (size < sizeof(*out))
12033 		return -1;
12034 	ctx->objdata = 0;
12035 	ctx->objmask = NULL;
12036 	ctx->object = out;
12037 	if (!out->command)
12038 		return -1;
12039 	out->command = ctx->curr;
12040 	/* For ipv6_ext_push/remove we need is pattern */
12041 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12042 						       sizeof(double));
12043 	return len;
12044 }
12045 
12046 /**
12047  * Parse set raw_encap/raw_decap command,
12048  * initialize output buffer for subsequent tokens.
12049  */
12050 static int
12051 parse_set_init(struct context *ctx, const struct token *token,
12052 	       const char *str, unsigned int len,
12053 	       void *buf, unsigned int size)
12054 {
12055 	struct buffer *out = buf;
12056 
12057 	/* Token name must match. */
12058 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12059 		return -1;
12060 	/* Nothing else to do if there is no buffer. */
12061 	if (!out)
12062 		return len;
12063 	/* Make sure buffer is large enough. */
12064 	if (size < sizeof(*out))
12065 		return -1;
12066 	/* Initialize buffer. */
12067 	memset(out, 0x00, sizeof(*out));
12068 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12069 	ctx->objdata = 0;
12070 	ctx->object = out;
12071 	ctx->objmask = NULL;
12072 	if (!out->command) {
12073 		if (ctx->curr != SET)
12074 			return -1;
12075 		if (sizeof(*out) > size)
12076 			return -1;
12077 		out->command = ctx->curr;
12078 		out->args.vc.data = (uint8_t *)out + size;
12079 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12080 						       sizeof(double));
12081 	}
12082 	return len;
12083 }
12084 
12085 /*
12086  * Replace testpmd handles in a flex flow item with real values.
12087  */
12088 static int
12089 parse_flex_handle(struct context *ctx, const struct token *token,
12090 		  const char *str, unsigned int len,
12091 		  void *buf, unsigned int size)
12092 {
12093 	struct rte_flow_item_flex *spec, *mask;
12094 	const struct rte_flow_item_flex *src_spec, *src_mask;
12095 	const struct arg *arg = pop_args(ctx);
12096 	uint32_t offset;
12097 	uint16_t handle;
12098 	int ret;
12099 
12100 	if (!arg) {
12101 		printf("Bad environment\n");
12102 		return -1;
12103 	}
12104 	offset = arg->offset;
12105 	push_args(ctx, arg);
12106 	ret = parse_int(ctx, token, str, len, buf, size);
12107 	if (ret <= 0 || !ctx->object)
12108 		return ret;
12109 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12110 		printf("Bad port\n");
12111 		return -1;
12112 	}
12113 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12114 		const struct flex_item *fp;
12115 		spec = ctx->object;
12116 		handle = (uint16_t)(uintptr_t)spec->handle;
12117 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12118 			printf("Bad flex item handle\n");
12119 			return -1;
12120 		}
12121 		fp = flex_items[ctx->port][handle];
12122 		if (!fp) {
12123 			printf("Bad flex item handle\n");
12124 			return -1;
12125 		}
12126 		spec->handle = fp->flex_handle;
12127 		mask = spec + 2; /* spec, last, mask */
12128 		mask->handle = fp->flex_handle;
12129 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12130 		handle = (uint16_t)(uintptr_t)
12131 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12132 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12133 			printf("Bad pattern handle\n");
12134 			return -1;
12135 		}
12136 		src_spec = &flex_patterns[handle].spec;
12137 		src_mask = &flex_patterns[handle].mask;
12138 		spec = ctx->object;
12139 		mask = spec + 2; /* spec, last, mask */
12140 		/* fill flow rule spec and mask parameters */
12141 		spec->length = src_spec->length;
12142 		spec->pattern = src_spec->pattern;
12143 		mask->length = src_mask->length;
12144 		mask->pattern = src_mask->pattern;
12145 	} else {
12146 		printf("Bad arguments - unknown flex item offset\n");
12147 		return -1;
12148 	}
12149 	return ret;
12150 }
12151 
12152 /** Parse Meter color name */
12153 static int
12154 parse_meter_color(struct context *ctx, const struct token *token,
12155 		  const char *str, unsigned int len, void *buf,
12156 		  unsigned int size)
12157 {
12158 	struct rte_flow_item_meter_color *meter_color;
12159 	unsigned int i;
12160 
12161 	(void)token;
12162 	(void)buf;
12163 	(void)size;
12164 	for (i = 0; meter_colors[i]; ++i)
12165 		if (!strcmp_partial(meter_colors[i], str, len))
12166 			break;
12167 	if (!meter_colors[i])
12168 		return -1;
12169 	if (!ctx->object)
12170 		return len;
12171 	meter_color = ctx->object;
12172 	meter_color->color = (enum rte_color)i;
12173 	return len;
12174 }
12175 
12176 /** Parse Insertion Table Type name */
12177 static int
12178 parse_insertion_table_type(struct context *ctx, const struct token *token,
12179 			   const char *str, unsigned int len, void *buf,
12180 			   unsigned int size)
12181 {
12182 	const struct arg *arg = pop_args(ctx);
12183 	unsigned int i;
12184 	char tmp[2];
12185 	int ret;
12186 
12187 	(void)size;
12188 	/* Argument is expected. */
12189 	if (!arg)
12190 		return -1;
12191 	for (i = 0; table_insertion_types[i]; ++i)
12192 		if (!strcmp_partial(table_insertion_types[i], str, len))
12193 			break;
12194 	if (!table_insertion_types[i])
12195 		return -1;
12196 	push_args(ctx, arg);
12197 	snprintf(tmp, sizeof(tmp), "%u", i);
12198 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12199 	return ret > 0 ? (int)len : ret;
12200 }
12201 
12202 /** Parse Hash Calculation Table Type name */
12203 static int
12204 parse_hash_table_type(struct context *ctx, const struct token *token,
12205 		      const char *str, unsigned int len, void *buf,
12206 		      unsigned int size)
12207 {
12208 	const struct arg *arg = pop_args(ctx);
12209 	unsigned int i;
12210 	char tmp[2];
12211 	int ret;
12212 
12213 	(void)size;
12214 	/* Argument is expected. */
12215 	if (!arg)
12216 		return -1;
12217 	for (i = 0; table_hash_funcs[i]; ++i)
12218 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12219 			break;
12220 	if (!table_hash_funcs[i])
12221 		return -1;
12222 	push_args(ctx, arg);
12223 	snprintf(tmp, sizeof(tmp), "%u", i);
12224 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12225 	return ret > 0 ? (int)len : ret;
12226 }
12227 
12228 static int
12229 parse_name_to_index(struct context *ctx, const struct token *token,
12230 		    const char *str, unsigned int len, void *buf,
12231 		    unsigned int size,
12232 		    const char *const names[], size_t names_size, uint32_t *dst)
12233 {
12234 	int ret;
12235 	uint32_t i;
12236 
12237 	RTE_SET_USED(token);
12238 	RTE_SET_USED(buf);
12239 	RTE_SET_USED(size);
12240 	if (!ctx->object)
12241 		return len;
12242 	for (i = 0; i < names_size; i++) {
12243 		if (!names[i])
12244 			continue;
12245 		ret = strcmp_partial(names[i], str,
12246 				     RTE_MIN(len, strlen(names[i])));
12247 		if (!ret) {
12248 			*dst = i;
12249 			return len;
12250 		}
12251 	}
12252 	return -1;
12253 }
12254 
12255 static const char *const quota_mode_names[] = {
12256 	NULL,
12257 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12258 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12259 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12260 };
12261 
12262 static const char *const quota_state_names[] = {
12263 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12264 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12265 };
12266 
12267 static const char *const quota_update_names[] = {
12268 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12269 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12270 };
12271 
12272 static const char *const query_update_mode_names[] = {
12273 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12274 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12275 };
12276 
12277 static int
12278 parse_quota_state_name(struct context *ctx, const struct token *token,
12279 		       const char *str, unsigned int len, void *buf,
12280 		       unsigned int size)
12281 {
12282 	struct rte_flow_item_quota *quota = ctx->object;
12283 
12284 	return parse_name_to_index(ctx, token, str, len, buf, size,
12285 				   quota_state_names,
12286 				   RTE_DIM(quota_state_names),
12287 				   (uint32_t *)&quota->state);
12288 }
12289 
12290 static int
12291 parse_quota_mode_name(struct context *ctx, const struct token *token,
12292 		      const char *str, unsigned int len, void *buf,
12293 		      unsigned int size)
12294 {
12295 	struct rte_flow_action_quota *quota = ctx->object;
12296 
12297 	return parse_name_to_index(ctx, token, str, len, buf, size,
12298 				   quota_mode_names,
12299 				   RTE_DIM(quota_mode_names),
12300 				   (uint32_t *)&quota->mode);
12301 }
12302 
12303 static int
12304 parse_quota_update_name(struct context *ctx, const struct token *token,
12305 			const char *str, unsigned int len, void *buf,
12306 			unsigned int size)
12307 {
12308 	struct rte_flow_update_quota *update = ctx->object;
12309 
12310 	return parse_name_to_index(ctx, token, str, len, buf, size,
12311 				   quota_update_names,
12312 				   RTE_DIM(quota_update_names),
12313 				   (uint32_t *)&update->op);
12314 }
12315 
12316 static int
12317 parse_qu_mode_name(struct context *ctx, const struct token *token,
12318 		   const char *str, unsigned int len, void *buf,
12319 		   unsigned int size)
12320 {
12321 	struct buffer *out = ctx->object;
12322 
12323 	return parse_name_to_index(ctx, token, str, len, buf, size,
12324 				   query_update_mode_names,
12325 				   RTE_DIM(query_update_mode_names),
12326 				   (uint32_t *)&out->args.ia.qu_mode);
12327 }
12328 
12329 /** No completion. */
12330 static int
12331 comp_none(struct context *ctx, const struct token *token,
12332 	  unsigned int ent, char *buf, unsigned int size)
12333 {
12334 	(void)ctx;
12335 	(void)token;
12336 	(void)ent;
12337 	(void)buf;
12338 	(void)size;
12339 	return 0;
12340 }
12341 
12342 /** Complete boolean values. */
12343 static int
12344 comp_boolean(struct context *ctx, const struct token *token,
12345 	     unsigned int ent, char *buf, unsigned int size)
12346 {
12347 	unsigned int i;
12348 
12349 	(void)ctx;
12350 	(void)token;
12351 	for (i = 0; boolean_name[i]; ++i)
12352 		if (buf && i == ent)
12353 			return strlcpy(buf, boolean_name[i], size);
12354 	if (buf)
12355 		return -1;
12356 	return i;
12357 }
12358 
12359 /** Complete action names. */
12360 static int
12361 comp_action(struct context *ctx, const struct token *token,
12362 	    unsigned int ent, char *buf, unsigned int size)
12363 {
12364 	unsigned int i;
12365 
12366 	(void)ctx;
12367 	(void)token;
12368 	for (i = 0; next_action[i]; ++i)
12369 		if (buf && i == ent)
12370 			return strlcpy(buf, token_list[next_action[i]].name,
12371 				       size);
12372 	if (buf)
12373 		return -1;
12374 	return i;
12375 }
12376 
12377 /** Complete available ports. */
12378 static int
12379 comp_port(struct context *ctx, const struct token *token,
12380 	  unsigned int ent, char *buf, unsigned int size)
12381 {
12382 	unsigned int i = 0;
12383 	portid_t p;
12384 
12385 	(void)ctx;
12386 	(void)token;
12387 	RTE_ETH_FOREACH_DEV(p) {
12388 		if (buf && i == ent)
12389 			return snprintf(buf, size, "%u", p);
12390 		++i;
12391 	}
12392 	if (buf)
12393 		return -1;
12394 	return i;
12395 }
12396 
12397 /** Complete available rule IDs. */
12398 static int
12399 comp_rule_id(struct context *ctx, const struct token *token,
12400 	     unsigned int ent, char *buf, unsigned int size)
12401 {
12402 	unsigned int i = 0;
12403 	struct rte_port *port;
12404 	struct port_flow *pf;
12405 
12406 	(void)token;
12407 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12408 	    ctx->port == (portid_t)RTE_PORT_ALL)
12409 		return -1;
12410 	port = &ports[ctx->port];
12411 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12412 		if (buf && i == ent)
12413 			return snprintf(buf, size, "%"PRIu64, pf->id);
12414 		++i;
12415 	}
12416 	if (buf)
12417 		return -1;
12418 	return i;
12419 }
12420 
12421 /** Complete operation for compare match item. */
12422 static int
12423 comp_set_compare_op(struct context *ctx, const struct token *token,
12424 		    unsigned int ent, char *buf, unsigned int size)
12425 {
12426 	RTE_SET_USED(ctx);
12427 	RTE_SET_USED(token);
12428 	if (!buf)
12429 		return RTE_DIM(compare_ops);
12430 	if (ent < RTE_DIM(compare_ops) - 1)
12431 		return strlcpy(buf, compare_ops[ent], size);
12432 	return -1;
12433 }
12434 
12435 /** Complete field id for compare match item. */
12436 static int
12437 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12438 			  unsigned int ent, char *buf, unsigned int size)
12439 {
12440 	const char *name;
12441 
12442 	RTE_SET_USED(token);
12443 	if (!buf)
12444 		return RTE_DIM(flow_field_ids);
12445 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12446 		return -1;
12447 	name = flow_field_ids[ent];
12448 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12449 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12450 		return strlcpy(buf, name, size);
12451 	return -1;
12452 }
12453 
12454 /** Complete type field for RSS action. */
12455 static int
12456 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12457 			unsigned int ent, char *buf, unsigned int size)
12458 {
12459 	unsigned int i;
12460 
12461 	(void)ctx;
12462 	(void)token;
12463 	for (i = 0; rss_type_table[i].str; ++i)
12464 		;
12465 	if (!buf)
12466 		return i + 1;
12467 	if (ent < i)
12468 		return strlcpy(buf, rss_type_table[ent].str, size);
12469 	if (ent == i)
12470 		return snprintf(buf, size, "end");
12471 	return -1;
12472 }
12473 
12474 /** Complete queue field for RSS action. */
12475 static int
12476 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12477 			 unsigned int ent, char *buf, unsigned int size)
12478 {
12479 	(void)ctx;
12480 	(void)token;
12481 	if (!buf)
12482 		return nb_rxq + 1;
12483 	if (ent < nb_rxq)
12484 		return snprintf(buf, size, "%u", ent);
12485 	if (ent == nb_rxq)
12486 		return snprintf(buf, size, "end");
12487 	return -1;
12488 }
12489 
12490 /** Complete index number for set raw_encap/raw_decap commands. */
12491 static int
12492 comp_set_raw_index(struct context *ctx, const struct token *token,
12493 		   unsigned int ent, char *buf, unsigned int size)
12494 {
12495 	uint16_t idx = 0;
12496 	uint16_t nb = 0;
12497 
12498 	RTE_SET_USED(ctx);
12499 	RTE_SET_USED(token);
12500 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12501 		if (buf && idx == ent)
12502 			return snprintf(buf, size, "%u", idx);
12503 		++nb;
12504 	}
12505 	return nb;
12506 }
12507 
12508 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12509 static int
12510 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12511 			unsigned int ent, char *buf, unsigned int size)
12512 {
12513 	uint16_t idx = 0;
12514 	uint16_t nb = 0;
12515 
12516 	RTE_SET_USED(ctx);
12517 	RTE_SET_USED(token);
12518 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12519 		if (buf && idx == ent)
12520 			return snprintf(buf, size, "%u", idx);
12521 		++nb;
12522 	}
12523 	return nb;
12524 }
12525 
12526 /** Complete index number for set raw_encap/raw_decap commands. */
12527 static int
12528 comp_set_sample_index(struct context *ctx, const struct token *token,
12529 		   unsigned int ent, char *buf, unsigned int size)
12530 {
12531 	uint16_t idx = 0;
12532 	uint16_t nb = 0;
12533 
12534 	RTE_SET_USED(ctx);
12535 	RTE_SET_USED(token);
12536 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12537 		if (buf && idx == ent)
12538 			return snprintf(buf, size, "%u", idx);
12539 		++nb;
12540 	}
12541 	return nb;
12542 }
12543 
12544 /** Complete operation for modify_field command. */
12545 static int
12546 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12547 		   unsigned int ent, char *buf, unsigned int size)
12548 {
12549 	RTE_SET_USED(ctx);
12550 	RTE_SET_USED(token);
12551 	if (!buf)
12552 		return RTE_DIM(modify_field_ops);
12553 	if (ent < RTE_DIM(modify_field_ops) - 1)
12554 		return strlcpy(buf, modify_field_ops[ent], size);
12555 	return -1;
12556 }
12557 
12558 /** Complete field id for modify_field command. */
12559 static int
12560 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12561 		   unsigned int ent, char *buf, unsigned int size)
12562 {
12563 	const char *name;
12564 
12565 	RTE_SET_USED(token);
12566 	if (!buf)
12567 		return RTE_DIM(flow_field_ids);
12568 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12569 		return -1;
12570 	name = flow_field_ids[ent];
12571 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12572 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12573 		return strlcpy(buf, name, size);
12574 	return -1;
12575 }
12576 
12577 /** Complete available pattern template IDs. */
12578 static int
12579 comp_pattern_template_id(struct context *ctx, const struct token *token,
12580 			 unsigned int ent, char *buf, unsigned int size)
12581 {
12582 	unsigned int i = 0;
12583 	struct rte_port *port;
12584 	struct port_template *pt;
12585 
12586 	(void)token;
12587 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12588 	    ctx->port == (portid_t)RTE_PORT_ALL)
12589 		return -1;
12590 	port = &ports[ctx->port];
12591 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12592 		if (buf && i == ent)
12593 			return snprintf(buf, size, "%u", pt->id);
12594 		++i;
12595 	}
12596 	if (buf)
12597 		return -1;
12598 	return i;
12599 }
12600 
12601 /** Complete available actions template IDs. */
12602 static int
12603 comp_actions_template_id(struct context *ctx, const struct token *token,
12604 			 unsigned int ent, char *buf, unsigned int size)
12605 {
12606 	unsigned int i = 0;
12607 	struct rte_port *port;
12608 	struct port_template *pt;
12609 
12610 	(void)token;
12611 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12612 	    ctx->port == (portid_t)RTE_PORT_ALL)
12613 		return -1;
12614 	port = &ports[ctx->port];
12615 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12616 		if (buf && i == ent)
12617 			return snprintf(buf, size, "%u", pt->id);
12618 		++i;
12619 	}
12620 	if (buf)
12621 		return -1;
12622 	return i;
12623 }
12624 
12625 /** Complete available table IDs. */
12626 static int
12627 comp_table_id(struct context *ctx, const struct token *token,
12628 	      unsigned int ent, char *buf, unsigned int size)
12629 {
12630 	unsigned int i = 0;
12631 	struct rte_port *port;
12632 	struct port_table *pt;
12633 
12634 	(void)token;
12635 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12636 	    ctx->port == (portid_t)RTE_PORT_ALL)
12637 		return -1;
12638 	port = &ports[ctx->port];
12639 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12640 		if (buf && i == ent)
12641 			return snprintf(buf, size, "%u", pt->id);
12642 		++i;
12643 	}
12644 	if (buf)
12645 		return -1;
12646 	return i;
12647 }
12648 
12649 /** Complete available queue IDs. */
12650 static int
12651 comp_queue_id(struct context *ctx, const struct token *token,
12652 	      unsigned int ent, char *buf, unsigned int size)
12653 {
12654 	unsigned int i = 0;
12655 	struct rte_port *port;
12656 
12657 	(void)token;
12658 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12659 	    ctx->port == (portid_t)RTE_PORT_ALL)
12660 		return -1;
12661 	port = &ports[ctx->port];
12662 	for (i = 0; i < port->queue_nb; i++) {
12663 		if (buf && i == ent)
12664 			return snprintf(buf, size, "%u", i);
12665 	}
12666 	if (buf)
12667 		return -1;
12668 	return i;
12669 }
12670 
12671 static int
12672 comp_names_to_index(struct context *ctx, const struct token *token,
12673 		    unsigned int ent, char *buf, unsigned int size,
12674 		    const char *const names[], size_t names_size)
12675 {
12676 	RTE_SET_USED(ctx);
12677 	RTE_SET_USED(token);
12678 	if (!buf)
12679 		return names_size;
12680 	if (names[ent] && ent < names_size)
12681 		return rte_strscpy(buf, names[ent], size);
12682 	return -1;
12683 
12684 }
12685 
12686 /** Complete available Meter colors. */
12687 static int
12688 comp_meter_color(struct context *ctx, const struct token *token,
12689 		 unsigned int ent, char *buf, unsigned int size)
12690 {
12691 	RTE_SET_USED(ctx);
12692 	RTE_SET_USED(token);
12693 	if (!buf)
12694 		return RTE_DIM(meter_colors);
12695 	if (ent < RTE_DIM(meter_colors) - 1)
12696 		return strlcpy(buf, meter_colors[ent], size);
12697 	return -1;
12698 }
12699 
12700 /** Complete available Insertion Table types. */
12701 static int
12702 comp_insertion_table_type(struct context *ctx, const struct token *token,
12703 			  unsigned int ent, char *buf, unsigned int size)
12704 {
12705 	RTE_SET_USED(ctx);
12706 	RTE_SET_USED(token);
12707 	if (!buf)
12708 		return RTE_DIM(table_insertion_types);
12709 	if (ent < RTE_DIM(table_insertion_types) - 1)
12710 		return rte_strscpy(buf, table_insertion_types[ent], size);
12711 	return -1;
12712 }
12713 
12714 /** Complete available Hash Calculation Table types. */
12715 static int
12716 comp_hash_table_type(struct context *ctx, const struct token *token,
12717 		     unsigned int ent, char *buf, unsigned int size)
12718 {
12719 	RTE_SET_USED(ctx);
12720 	RTE_SET_USED(token);
12721 	if (!buf)
12722 		return RTE_DIM(table_hash_funcs);
12723 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12724 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12725 	return -1;
12726 }
12727 
12728 static int
12729 comp_quota_state_name(struct context *ctx, const struct token *token,
12730 		      unsigned int ent, char *buf, unsigned int size)
12731 {
12732 	return comp_names_to_index(ctx, token, ent, buf, size,
12733 				   quota_state_names,
12734 				   RTE_DIM(quota_state_names));
12735 }
12736 
12737 static int
12738 comp_quota_mode_name(struct context *ctx, const struct token *token,
12739 		     unsigned int ent, char *buf, unsigned int size)
12740 {
12741 	return comp_names_to_index(ctx, token, ent, buf, size,
12742 				   quota_mode_names,
12743 				   RTE_DIM(quota_mode_names));
12744 }
12745 
12746 static int
12747 comp_quota_update_name(struct context *ctx, const struct token *token,
12748 		       unsigned int ent, char *buf, unsigned int size)
12749 {
12750 	return comp_names_to_index(ctx, token, ent, buf, size,
12751 				   quota_update_names,
12752 				   RTE_DIM(quota_update_names));
12753 }
12754 
12755 static int
12756 comp_qu_mode_name(struct context *ctx, const struct token *token,
12757 		  unsigned int ent, char *buf, unsigned int size)
12758 {
12759 	return comp_names_to_index(ctx, token, ent, buf, size,
12760 				   query_update_mode_names,
12761 				   RTE_DIM(query_update_mode_names));
12762 }
12763 
12764 /** Internal context. */
12765 static struct context cmd_flow_context;
12766 
12767 /** Global parser instance (cmdline API). */
12768 cmdline_parse_inst_t cmd_flow;
12769 cmdline_parse_inst_t cmd_set_raw;
12770 
12771 /** Initialize context. */
12772 static void
12773 cmd_flow_context_init(struct context *ctx)
12774 {
12775 	/* A full memset() is not necessary. */
12776 	ctx->curr = ZERO;
12777 	ctx->prev = ZERO;
12778 	ctx->next_num = 0;
12779 	ctx->args_num = 0;
12780 	ctx->eol = 0;
12781 	ctx->last = 0;
12782 	ctx->port = 0;
12783 	ctx->objdata = 0;
12784 	ctx->object = NULL;
12785 	ctx->objmask = NULL;
12786 }
12787 
12788 /** Parse a token (cmdline API). */
12789 static int
12790 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12791 	       unsigned int size)
12792 {
12793 	struct context *ctx = &cmd_flow_context;
12794 	const struct token *token;
12795 	const enum index *list;
12796 	int len;
12797 	int i;
12798 
12799 	(void)hdr;
12800 	token = &token_list[ctx->curr];
12801 	/* Check argument length. */
12802 	ctx->eol = 0;
12803 	ctx->last = 1;
12804 	for (len = 0; src[len]; ++len)
12805 		if (src[len] == '#' || isspace(src[len]))
12806 			break;
12807 	if (!len)
12808 		return -1;
12809 	/* Last argument and EOL detection. */
12810 	for (i = len; src[i]; ++i)
12811 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12812 			break;
12813 		else if (!isspace(src[i])) {
12814 			ctx->last = 0;
12815 			break;
12816 		}
12817 	for (; src[i]; ++i)
12818 		if (src[i] == '\r' || src[i] == '\n') {
12819 			ctx->eol = 1;
12820 			break;
12821 		}
12822 	/* Initialize context if necessary. */
12823 	if (!ctx->next_num) {
12824 		if (!token->next)
12825 			return 0;
12826 		ctx->next[ctx->next_num++] = token->next[0];
12827 	}
12828 	/* Process argument through candidates. */
12829 	ctx->prev = ctx->curr;
12830 	list = ctx->next[ctx->next_num - 1];
12831 	for (i = 0; list[i]; ++i) {
12832 		const struct token *next = &token_list[list[i]];
12833 		int tmp;
12834 
12835 		ctx->curr = list[i];
12836 		if (next->call)
12837 			tmp = next->call(ctx, next, src, len, result, size);
12838 		else
12839 			tmp = parse_default(ctx, next, src, len, result, size);
12840 		if (tmp == -1 || tmp != len)
12841 			continue;
12842 		token = next;
12843 		break;
12844 	}
12845 	if (!list[i])
12846 		return -1;
12847 	--ctx->next_num;
12848 	/* Push subsequent tokens if any. */
12849 	if (token->next)
12850 		for (i = 0; token->next[i]; ++i) {
12851 			if (ctx->next_num == RTE_DIM(ctx->next))
12852 				return -1;
12853 			ctx->next[ctx->next_num++] = token->next[i];
12854 		}
12855 	/* Push arguments if any. */
12856 	if (token->args)
12857 		for (i = 0; token->args[i]; ++i) {
12858 			if (ctx->args_num == RTE_DIM(ctx->args))
12859 				return -1;
12860 			ctx->args[ctx->args_num++] = token->args[i];
12861 		}
12862 	return len;
12863 }
12864 
12865 int
12866 flow_parse(const char *src, void *result, unsigned int size,
12867 	   struct rte_flow_attr **attr,
12868 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12869 {
12870 	int ret;
12871 	struct context saved_flow_ctx = cmd_flow_context;
12872 
12873 	cmd_flow_context_init(&cmd_flow_context);
12874 	do {
12875 		ret = cmd_flow_parse(NULL, src, result, size);
12876 		if (ret > 0) {
12877 			src += ret;
12878 			while (isspace(*src))
12879 				src++;
12880 		}
12881 	} while (ret > 0 && strlen(src));
12882 	cmd_flow_context = saved_flow_ctx;
12883 	*attr = &((struct buffer *)result)->args.vc.attr;
12884 	*pattern = ((struct buffer *)result)->args.vc.pattern;
12885 	*actions = ((struct buffer *)result)->args.vc.actions;
12886 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
12887 }
12888 
12889 /** Return number of completion entries (cmdline API). */
12890 static int
12891 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
12892 {
12893 	struct context *ctx = &cmd_flow_context;
12894 	const struct token *token = &token_list[ctx->curr];
12895 	const enum index *list;
12896 	int i;
12897 
12898 	(void)hdr;
12899 	/* Count number of tokens in current list. */
12900 	if (ctx->next_num)
12901 		list = ctx->next[ctx->next_num - 1];
12902 	else
12903 		list = token->next[0];
12904 	for (i = 0; list[i]; ++i)
12905 		;
12906 	if (!i)
12907 		return 0;
12908 	/*
12909 	 * If there is a single token, use its completion callback, otherwise
12910 	 * return the number of entries.
12911 	 */
12912 	token = &token_list[list[0]];
12913 	if (i == 1 && token->comp) {
12914 		/* Save index for cmd_flow_get_help(). */
12915 		ctx->prev = list[0];
12916 		return token->comp(ctx, token, 0, NULL, 0);
12917 	}
12918 	return i;
12919 }
12920 
12921 /** Return a completion entry (cmdline API). */
12922 static int
12923 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
12924 			  char *dst, unsigned int size)
12925 {
12926 	struct context *ctx = &cmd_flow_context;
12927 	const struct token *token = &token_list[ctx->curr];
12928 	const enum index *list;
12929 	int i;
12930 
12931 	(void)hdr;
12932 	/* Count number of tokens in current list. */
12933 	if (ctx->next_num)
12934 		list = ctx->next[ctx->next_num - 1];
12935 	else
12936 		list = token->next[0];
12937 	for (i = 0; list[i]; ++i)
12938 		;
12939 	if (!i)
12940 		return -1;
12941 	/* If there is a single token, use its completion callback. */
12942 	token = &token_list[list[0]];
12943 	if (i == 1 && token->comp) {
12944 		/* Save index for cmd_flow_get_help(). */
12945 		ctx->prev = list[0];
12946 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
12947 	}
12948 	/* Otherwise make sure the index is valid and use defaults. */
12949 	if (index >= i)
12950 		return -1;
12951 	token = &token_list[list[index]];
12952 	strlcpy(dst, token->name, size);
12953 	/* Save index for cmd_flow_get_help(). */
12954 	ctx->prev = list[index];
12955 	return 0;
12956 }
12957 
12958 /** Populate help strings for current token (cmdline API). */
12959 static int
12960 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
12961 {
12962 	struct context *ctx = &cmd_flow_context;
12963 	const struct token *token = &token_list[ctx->prev];
12964 
12965 	(void)hdr;
12966 	if (!size)
12967 		return -1;
12968 	/* Set token type and update global help with details. */
12969 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
12970 	if (token->help)
12971 		cmd_flow.help_str = token->help;
12972 	else
12973 		cmd_flow.help_str = token->name;
12974 	return 0;
12975 }
12976 
12977 /** Token definition template (cmdline API). */
12978 static struct cmdline_token_hdr cmd_flow_token_hdr = {
12979 	.ops = &(struct cmdline_token_ops){
12980 		.parse = cmd_flow_parse,
12981 		.complete_get_nb = cmd_flow_complete_get_nb,
12982 		.complete_get_elt = cmd_flow_complete_get_elt,
12983 		.get_help = cmd_flow_get_help,
12984 	},
12985 	.offset = 0,
12986 };
12987 
12988 /** Populate the next dynamic token. */
12989 static void
12990 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
12991 	     cmdline_parse_token_hdr_t **hdr_inst)
12992 {
12993 	struct context *ctx = &cmd_flow_context;
12994 
12995 	/* Always reinitialize context before requesting the first token. */
12996 	if (!(hdr_inst - cmd_flow.tokens))
12997 		cmd_flow_context_init(ctx);
12998 	/* Return NULL when no more tokens are expected. */
12999 	if (!ctx->next_num && ctx->curr) {
13000 		*hdr = NULL;
13001 		return;
13002 	}
13003 	/* Determine if command should end here. */
13004 	if (ctx->eol && ctx->last && ctx->next_num) {
13005 		const enum index *list = ctx->next[ctx->next_num - 1];
13006 		int i;
13007 
13008 		for (i = 0; list[i]; ++i) {
13009 			if (list[i] != END)
13010 				continue;
13011 			*hdr = NULL;
13012 			return;
13013 		}
13014 	}
13015 	*hdr = &cmd_flow_token_hdr;
13016 }
13017 
13018 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13019 	SLIST_HEAD_INITIALIZER();
13020 
13021 static void
13022 indirect_action_flow_conf_create(const struct buffer *in)
13023 {
13024 	int len, ret;
13025 	uint32_t i;
13026 	struct indlst_conf *indlst_conf = NULL;
13027 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13028 	struct rte_flow_action *src = in->args.vc.actions;
13029 
13030 	if (!in->args.vc.actions_n)
13031 		goto end;
13032 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13033 	if (len <= 0)
13034 		goto end;
13035 	len = RTE_ALIGN(len, 16);
13036 
13037 	indlst_conf = calloc(1, base + len +
13038 			     in->args.vc.actions_n * sizeof(uintptr_t));
13039 	if (!indlst_conf)
13040 		goto end;
13041 	indlst_conf->id = in->args.vc.attr.group;
13042 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13043 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13044 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13045 			    len, src, NULL);
13046 	if (ret <= 0) {
13047 		free(indlst_conf);
13048 		indlst_conf = NULL;
13049 		goto end;
13050 	}
13051 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13052 	for (i = 0; i < indlst_conf->conf_num; i++)
13053 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13054 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13055 end:
13056 	if (indlst_conf)
13057 		printf("created indirect action list configuration %u\n",
13058 		       in->args.vc.attr.group);
13059 	else
13060 		printf("cannot create indirect action list configuration %u\n",
13061 		       in->args.vc.attr.group);
13062 }
13063 
13064 static const struct indlst_conf *
13065 indirect_action_list_conf_get(uint32_t conf_id)
13066 {
13067 	const struct indlst_conf *conf;
13068 
13069 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13070 		if (conf->id == conf_id)
13071 			return conf;
13072 	}
13073 	return NULL;
13074 }
13075 
13076 /** Dispatch parsed buffer to function calls. */
13077 static void
13078 cmd_flow_parsed(const struct buffer *in)
13079 {
13080 	switch (in->command) {
13081 	case INFO:
13082 		port_flow_get_info(in->port);
13083 		break;
13084 	case CONFIGURE:
13085 		port_flow_configure(in->port,
13086 				    &in->args.configure.port_attr,
13087 				    in->args.configure.nb_queue,
13088 				    &in->args.configure.queue_attr);
13089 		break;
13090 	case PATTERN_TEMPLATE_CREATE:
13091 		port_flow_pattern_template_create(in->port,
13092 				in->args.vc.pat_templ_id,
13093 				&((const struct rte_flow_pattern_template_attr) {
13094 					.relaxed_matching = in->args.vc.attr.reserved,
13095 					.ingress = in->args.vc.attr.ingress,
13096 					.egress = in->args.vc.attr.egress,
13097 					.transfer = in->args.vc.attr.transfer,
13098 				}),
13099 				in->args.vc.pattern);
13100 		break;
13101 	case PATTERN_TEMPLATE_DESTROY:
13102 		port_flow_pattern_template_destroy(in->port,
13103 				in->args.templ_destroy.template_id_n,
13104 				in->args.templ_destroy.template_id);
13105 		break;
13106 	case ACTIONS_TEMPLATE_CREATE:
13107 		port_flow_actions_template_create(in->port,
13108 				in->args.vc.act_templ_id,
13109 				&((const struct rte_flow_actions_template_attr) {
13110 					.ingress = in->args.vc.attr.ingress,
13111 					.egress = in->args.vc.attr.egress,
13112 					.transfer = in->args.vc.attr.transfer,
13113 				}),
13114 				in->args.vc.actions,
13115 				in->args.vc.masks);
13116 		break;
13117 	case ACTIONS_TEMPLATE_DESTROY:
13118 		port_flow_actions_template_destroy(in->port,
13119 				in->args.templ_destroy.template_id_n,
13120 				in->args.templ_destroy.template_id);
13121 		break;
13122 	case TABLE_CREATE:
13123 		port_flow_template_table_create(in->port, in->args.table.id,
13124 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13125 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13126 			in->args.table.act_templ_id);
13127 		break;
13128 	case TABLE_DESTROY:
13129 		port_flow_template_table_destroy(in->port,
13130 					in->args.table_destroy.table_id_n,
13131 					in->args.table_destroy.table_id);
13132 		break;
13133 	case TABLE_RESIZE_COMPLETE:
13134 		port_flow_template_table_resize_complete
13135 			(in->port, in->args.table_destroy.table_id[0]);
13136 		break;
13137 	case GROUP_SET_MISS_ACTIONS:
13138 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13139 						  in->args.vc.actions);
13140 		break;
13141 	case TABLE_RESIZE:
13142 		port_flow_template_table_resize(in->port, in->args.table.id,
13143 						in->args.table.attr.nb_flows);
13144 		break;
13145 	case QUEUE_CREATE:
13146 		port_queue_flow_create(in->port, in->queue, in->postpone,
13147 			in->args.vc.table_id, in->args.vc.rule_id,
13148 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13149 			in->args.vc.pattern, in->args.vc.actions);
13150 		break;
13151 	case QUEUE_DESTROY:
13152 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13153 					in->args.destroy.rule_n,
13154 					in->args.destroy.rule);
13155 		break;
13156 	case QUEUE_FLOW_UPDATE_RESIZED:
13157 		port_queue_flow_update_resized(in->port, in->queue,
13158 					       in->postpone,
13159 					       in->args.destroy.rule[0]);
13160 		break;
13161 	case QUEUE_UPDATE:
13162 		port_queue_flow_update(in->port, in->queue, in->postpone,
13163 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13164 				in->args.vc.actions);
13165 		break;
13166 	case PUSH:
13167 		port_queue_flow_push(in->port, in->queue);
13168 		break;
13169 	case PULL:
13170 		port_queue_flow_pull(in->port, in->queue);
13171 		break;
13172 	case HASH:
13173 		if (!in->args.vc.encap_hash)
13174 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13175 					    in->args.vc.pat_templ_id,
13176 					    in->args.vc.pattern);
13177 		else
13178 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13179 						  in->args.vc.pattern);
13180 		break;
13181 	case QUEUE_AGED:
13182 		port_queue_flow_aged(in->port, in->queue,
13183 				     in->args.aged.destroy);
13184 		break;
13185 	case QUEUE_INDIRECT_ACTION_CREATE:
13186 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13187 		port_queue_action_handle_create(
13188 				in->port, in->queue, in->postpone,
13189 				in->args.vc.attr.group,
13190 				&((const struct rte_flow_indir_action_conf) {
13191 					.ingress = in->args.vc.attr.ingress,
13192 					.egress = in->args.vc.attr.egress,
13193 					.transfer = in->args.vc.attr.transfer,
13194 				}),
13195 				in->args.vc.actions);
13196 		break;
13197 	case QUEUE_INDIRECT_ACTION_DESTROY:
13198 		port_queue_action_handle_destroy(in->port,
13199 					   in->queue, in->postpone,
13200 					   in->args.ia_destroy.action_id_n,
13201 					   in->args.ia_destroy.action_id);
13202 		break;
13203 	case QUEUE_INDIRECT_ACTION_UPDATE:
13204 		port_queue_action_handle_update(in->port,
13205 						in->queue, in->postpone,
13206 						in->args.vc.attr.group,
13207 						in->args.vc.actions);
13208 		break;
13209 	case QUEUE_INDIRECT_ACTION_QUERY:
13210 		port_queue_action_handle_query(in->port,
13211 					       in->queue, in->postpone,
13212 					       in->args.ia.action_id);
13213 		break;
13214 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13215 		port_queue_action_handle_query_update(in->port, in->queue,
13216 						      in->postpone,
13217 						      in->args.ia.action_id,
13218 						      in->args.ia.qu_mode,
13219 						      in->args.vc.actions);
13220 		break;
13221 	case INDIRECT_ACTION_CREATE:
13222 	case INDIRECT_ACTION_LIST_CREATE:
13223 		port_action_handle_create(
13224 				in->port, in->args.vc.attr.group,
13225 				in->command == INDIRECT_ACTION_LIST_CREATE,
13226 				&((const struct rte_flow_indir_action_conf) {
13227 					.ingress = in->args.vc.attr.ingress,
13228 					.egress = in->args.vc.attr.egress,
13229 					.transfer = in->args.vc.attr.transfer,
13230 				}),
13231 				in->args.vc.actions);
13232 		break;
13233 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13234 		indirect_action_flow_conf_create(in);
13235 		break;
13236 	case INDIRECT_ACTION_DESTROY:
13237 		port_action_handle_destroy(in->port,
13238 					   in->args.ia_destroy.action_id_n,
13239 					   in->args.ia_destroy.action_id);
13240 		break;
13241 	case INDIRECT_ACTION_UPDATE:
13242 		port_action_handle_update(in->port, in->args.vc.attr.group,
13243 					  in->args.vc.actions);
13244 		break;
13245 	case INDIRECT_ACTION_QUERY:
13246 		port_action_handle_query(in->port, in->args.ia.action_id);
13247 		break;
13248 	case INDIRECT_ACTION_QUERY_UPDATE:
13249 		port_action_handle_query_update(in->port,
13250 						in->args.ia.action_id,
13251 						in->args.ia.qu_mode,
13252 						in->args.vc.actions);
13253 		break;
13254 	case VALIDATE:
13255 		port_flow_validate(in->port, &in->args.vc.attr,
13256 				   in->args.vc.pattern, in->args.vc.actions,
13257 				   &in->args.vc.tunnel_ops);
13258 		break;
13259 	case CREATE:
13260 		port_flow_create(in->port, &in->args.vc.attr,
13261 				 in->args.vc.pattern, in->args.vc.actions,
13262 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13263 		break;
13264 	case DESTROY:
13265 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13266 				  in->args.destroy.rule,
13267 				  in->args.destroy.is_user_id);
13268 		break;
13269 	case FLUSH:
13270 		port_flow_flush(in->port);
13271 		break;
13272 	case DUMP_ONE:
13273 	case DUMP_ALL:
13274 		port_flow_dump(in->port, in->args.dump.mode,
13275 				in->args.dump.rule, in->args.dump.file,
13276 				in->args.dump.is_user_id);
13277 		break;
13278 	case QUERY:
13279 		port_flow_query(in->port, in->args.query.rule,
13280 				&in->args.query.action,
13281 				in->args.query.is_user_id);
13282 		break;
13283 	case LIST:
13284 		port_flow_list(in->port, in->args.list.group_n,
13285 			       in->args.list.group);
13286 		break;
13287 	case ISOLATE:
13288 		port_flow_isolate(in->port, in->args.isolate.set);
13289 		break;
13290 	case AGED:
13291 		port_flow_aged(in->port, in->args.aged.destroy);
13292 		break;
13293 	case TUNNEL_CREATE:
13294 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13295 		break;
13296 	case TUNNEL_DESTROY:
13297 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13298 		break;
13299 	case TUNNEL_LIST:
13300 		port_flow_tunnel_list(in->port);
13301 		break;
13302 	case ACTION_POL_G:
13303 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13304 					in->args.vc.actions);
13305 		break;
13306 	case FLEX_ITEM_CREATE:
13307 		flex_item_create(in->port, in->args.flex.token,
13308 				 in->args.flex.filename);
13309 		break;
13310 	case FLEX_ITEM_DESTROY:
13311 		flex_item_destroy(in->port, in->args.flex.token);
13312 		break;
13313 	default:
13314 		break;
13315 	}
13316 	fflush(stdout);
13317 }
13318 
13319 /** Token generator and output processing callback (cmdline API). */
13320 static void
13321 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13322 {
13323 	if (cl == NULL)
13324 		cmd_flow_tok(arg0, arg2);
13325 	else
13326 		cmd_flow_parsed(arg0);
13327 }
13328 
13329 /** Global parser instance (cmdline API). */
13330 cmdline_parse_inst_t cmd_flow = {
13331 	.f = cmd_flow_cb,
13332 	.data = NULL, /**< Unused. */
13333 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13334 	.tokens = {
13335 		NULL,
13336 	}, /**< Tokens are returned by cmd_flow_tok(). */
13337 };
13338 
13339 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13340 
13341 static void
13342 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13343 {
13344 	struct rte_ipv4_hdr *ipv4;
13345 	struct rte_ether_hdr *eth;
13346 	struct rte_ipv6_hdr *ipv6;
13347 	struct rte_vxlan_hdr *vxlan;
13348 	struct rte_vxlan_gpe_hdr *gpe;
13349 	struct rte_flow_item_nvgre *nvgre;
13350 	uint32_t ipv6_vtc_flow;
13351 
13352 	switch (item->type) {
13353 	case RTE_FLOW_ITEM_TYPE_ETH:
13354 		eth = (struct rte_ether_hdr *)buf;
13355 		if (next_proto)
13356 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13357 		break;
13358 	case RTE_FLOW_ITEM_TYPE_IPV4:
13359 		ipv4 = (struct rte_ipv4_hdr *)buf;
13360 		if (!ipv4->version_ihl)
13361 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13362 		if (next_proto && ipv4->next_proto_id == 0)
13363 			ipv4->next_proto_id = (uint8_t)next_proto;
13364 		break;
13365 	case RTE_FLOW_ITEM_TYPE_IPV6:
13366 		ipv6 = (struct rte_ipv6_hdr *)buf;
13367 		if (next_proto && ipv6->proto == 0)
13368 			ipv6->proto = (uint8_t)next_proto;
13369 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13370 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13371 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13372 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13373 		break;
13374 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13375 		vxlan = (struct rte_vxlan_hdr *)buf;
13376 		vxlan->vx_flags = 0x08;
13377 		break;
13378 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13379 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13380 		gpe->vx_flags = 0x0C;
13381 		break;
13382 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13383 		nvgre = (struct rte_flow_item_nvgre *)buf;
13384 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13385 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13386 		break;
13387 	default:
13388 		break;
13389 	}
13390 }
13391 
13392 /** Helper of get item's default mask. */
13393 static const void *
13394 flow_item_default_mask(const struct rte_flow_item *item)
13395 {
13396 	const void *mask = NULL;
13397 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13398 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13399 		.hdr = {
13400 			.next_hdr = 0xff,
13401 			.type = 0xff,
13402 			.segments_left = 0xff,
13403 		},
13404 	};
13405 
13406 	switch (item->type) {
13407 	case RTE_FLOW_ITEM_TYPE_ANY:
13408 		mask = &rte_flow_item_any_mask;
13409 		break;
13410 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13411 		mask = &rte_flow_item_port_id_mask;
13412 		break;
13413 	case RTE_FLOW_ITEM_TYPE_RAW:
13414 		mask = &rte_flow_item_raw_mask;
13415 		break;
13416 	case RTE_FLOW_ITEM_TYPE_ETH:
13417 		mask = &rte_flow_item_eth_mask;
13418 		break;
13419 	case RTE_FLOW_ITEM_TYPE_VLAN:
13420 		mask = &rte_flow_item_vlan_mask;
13421 		break;
13422 	case RTE_FLOW_ITEM_TYPE_IPV4:
13423 		mask = &rte_flow_item_ipv4_mask;
13424 		break;
13425 	case RTE_FLOW_ITEM_TYPE_IPV6:
13426 		mask = &rte_flow_item_ipv6_mask;
13427 		break;
13428 	case RTE_FLOW_ITEM_TYPE_ICMP:
13429 		mask = &rte_flow_item_icmp_mask;
13430 		break;
13431 	case RTE_FLOW_ITEM_TYPE_UDP:
13432 		mask = &rte_flow_item_udp_mask;
13433 		break;
13434 	case RTE_FLOW_ITEM_TYPE_TCP:
13435 		mask = &rte_flow_item_tcp_mask;
13436 		break;
13437 	case RTE_FLOW_ITEM_TYPE_SCTP:
13438 		mask = &rte_flow_item_sctp_mask;
13439 		break;
13440 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13441 		mask = &rte_flow_item_vxlan_mask;
13442 		break;
13443 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13444 		mask = &rte_flow_item_vxlan_gpe_mask;
13445 		break;
13446 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13447 		mask = &rte_flow_item_e_tag_mask;
13448 		break;
13449 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13450 		mask = &rte_flow_item_nvgre_mask;
13451 		break;
13452 	case RTE_FLOW_ITEM_TYPE_MPLS:
13453 		mask = &rte_flow_item_mpls_mask;
13454 		break;
13455 	case RTE_FLOW_ITEM_TYPE_GRE:
13456 		mask = &rte_flow_item_gre_mask;
13457 		break;
13458 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13459 		mask = &gre_key_default_mask;
13460 		break;
13461 	case RTE_FLOW_ITEM_TYPE_META:
13462 		mask = &rte_flow_item_meta_mask;
13463 		break;
13464 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13465 		mask = &rte_flow_item_random_mask;
13466 		break;
13467 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13468 		mask = &rte_flow_item_fuzzy_mask;
13469 		break;
13470 	case RTE_FLOW_ITEM_TYPE_GTP:
13471 		mask = &rte_flow_item_gtp_mask;
13472 		break;
13473 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13474 		mask = &rte_flow_item_gtp_psc_mask;
13475 		break;
13476 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13477 		mask = &rte_flow_item_geneve_mask;
13478 		break;
13479 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13480 		mask = &rte_flow_item_geneve_opt_mask;
13481 		break;
13482 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13483 		mask = &rte_flow_item_pppoe_proto_id_mask;
13484 		break;
13485 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13486 		mask = &rte_flow_item_l2tpv3oip_mask;
13487 		break;
13488 	case RTE_FLOW_ITEM_TYPE_ESP:
13489 		mask = &rte_flow_item_esp_mask;
13490 		break;
13491 	case RTE_FLOW_ITEM_TYPE_AH:
13492 		mask = &rte_flow_item_ah_mask;
13493 		break;
13494 	case RTE_FLOW_ITEM_TYPE_PFCP:
13495 		mask = &rte_flow_item_pfcp_mask;
13496 		break;
13497 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13498 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13499 		mask = &rte_flow_item_ethdev_mask;
13500 		break;
13501 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13502 		mask = &rte_flow_item_l2tpv2_mask;
13503 		break;
13504 	case RTE_FLOW_ITEM_TYPE_PPP:
13505 		mask = &rte_flow_item_ppp_mask;
13506 		break;
13507 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13508 		mask = &rte_flow_item_meter_color_mask;
13509 		break;
13510 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13511 		mask = &ipv6_routing_ext_default_mask;
13512 		break;
13513 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13514 		mask = &rte_flow_item_aggr_affinity_mask;
13515 		break;
13516 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13517 		mask = &rte_flow_item_tx_queue_mask;
13518 		break;
13519 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13520 		mask = &rte_flow_item_ib_bth_mask;
13521 		break;
13522 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13523 		mask = &rte_flow_item_ptype_mask;
13524 		break;
13525 	default:
13526 		break;
13527 	}
13528 	return mask;
13529 }
13530 
13531 /** Dispatch parsed buffer to function calls. */
13532 static void
13533 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13534 {
13535 	uint32_t n = in->args.vc.pattern_n;
13536 	int i = 0;
13537 	struct rte_flow_item *item = NULL;
13538 	size_t size = 0;
13539 	uint8_t *data = NULL;
13540 	uint8_t *type = NULL;
13541 	size_t *total_size = NULL;
13542 	uint16_t idx = in->port; /* We borrow port field as index */
13543 	struct rte_flow_item_ipv6_routing_ext *ext;
13544 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13545 
13546 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13547 		   in->command == SET_IPV6_EXT_REMOVE);
13548 
13549 	if (in->command == SET_IPV6_EXT_REMOVE) {
13550 		if (n != 1 || in->args.vc.pattern->type !=
13551 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13552 			fprintf(stderr, "Error - Not supported item\n");
13553 			return;
13554 		}
13555 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13556 		item = in->args.vc.pattern;
13557 		ipv6_ext = item->spec;
13558 		*type = ipv6_ext->next_hdr;
13559 		return;
13560 	}
13561 
13562 	total_size = &ipv6_ext_push_confs[idx].size;
13563 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13564 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13565 
13566 	*total_size = 0;
13567 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13568 	for (i = n - 1 ; i >= 0; --i) {
13569 		item = in->args.vc.pattern + i;
13570 		switch (item->type) {
13571 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13572 			ipv6_ext = item->spec;
13573 			*type = ipv6_ext->next_hdr;
13574 			break;
13575 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13576 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13577 			if (!ext->hdr.hdr_len) {
13578 				size = sizeof(struct rte_ipv6_routing_ext) +
13579 				(ext->hdr.segments_left << 4);
13580 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13581 				/* Indicate no TLV once SRH. */
13582 				if (ext->hdr.type == 4)
13583 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13584 			} else {
13585 				size = sizeof(struct rte_ipv6_routing_ext) +
13586 				(ext->hdr.hdr_len << 3);
13587 			}
13588 			*total_size += size;
13589 			memcpy(data, ext, size);
13590 			break;
13591 		default:
13592 			fprintf(stderr, "Error - Not supported item\n");
13593 			goto error;
13594 		}
13595 	}
13596 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13597 	return;
13598 error:
13599 	*total_size = 0;
13600 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13601 }
13602 
13603 /** Dispatch parsed buffer to function calls. */
13604 static void
13605 cmd_set_raw_parsed_sample(const struct buffer *in)
13606 {
13607 	uint32_t n = in->args.vc.actions_n;
13608 	uint32_t i = 0;
13609 	struct rte_flow_action *action = NULL;
13610 	struct rte_flow_action *data = NULL;
13611 	const struct rte_flow_action_rss *rss = NULL;
13612 	size_t size = 0;
13613 	uint16_t idx = in->port; /* We borrow port field as index */
13614 	uint32_t max_size = sizeof(struct rte_flow_action) *
13615 						ACTION_SAMPLE_ACTIONS_NUM;
13616 
13617 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13618 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13619 	memset(data, 0x00, max_size);
13620 	for (; i <= n - 1; i++) {
13621 		action = in->args.vc.actions + i;
13622 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13623 			break;
13624 		switch (action->type) {
13625 		case RTE_FLOW_ACTION_TYPE_MARK:
13626 			size = sizeof(struct rte_flow_action_mark);
13627 			rte_memcpy(&sample_mark[idx],
13628 				(const void *)action->conf, size);
13629 			action->conf = &sample_mark[idx];
13630 			break;
13631 		case RTE_FLOW_ACTION_TYPE_COUNT:
13632 			size = sizeof(struct rte_flow_action_count);
13633 			rte_memcpy(&sample_count[idx],
13634 				(const void *)action->conf, size);
13635 			action->conf = &sample_count[idx];
13636 			break;
13637 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13638 			size = sizeof(struct rte_flow_action_queue);
13639 			rte_memcpy(&sample_queue[idx],
13640 				(const void *)action->conf, size);
13641 			action->conf = &sample_queue[idx];
13642 			break;
13643 		case RTE_FLOW_ACTION_TYPE_RSS:
13644 			size = sizeof(struct rte_flow_action_rss);
13645 			rss = action->conf;
13646 			rte_memcpy(&sample_rss_data[idx].conf,
13647 				   (const void *)rss, size);
13648 			if (rss->key_len && rss->key) {
13649 				sample_rss_data[idx].conf.key =
13650 						sample_rss_data[idx].key;
13651 				rte_memcpy((void *)((uintptr_t)
13652 					   sample_rss_data[idx].conf.key),
13653 					   (const void *)rss->key,
13654 					   sizeof(uint8_t) * rss->key_len);
13655 			}
13656 			if (rss->queue_num && rss->queue) {
13657 				sample_rss_data[idx].conf.queue =
13658 						sample_rss_data[idx].queue;
13659 				rte_memcpy((void *)((uintptr_t)
13660 					   sample_rss_data[idx].conf.queue),
13661 					   (const void *)rss->queue,
13662 					   sizeof(uint16_t) * rss->queue_num);
13663 			}
13664 			action->conf = &sample_rss_data[idx].conf;
13665 			break;
13666 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13667 			size = sizeof(struct rte_flow_action_raw_encap);
13668 			rte_memcpy(&sample_encap[idx],
13669 				(const void *)action->conf, size);
13670 			action->conf = &sample_encap[idx];
13671 			break;
13672 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13673 			size = sizeof(struct rte_flow_action_port_id);
13674 			rte_memcpy(&sample_port_id[idx],
13675 				(const void *)action->conf, size);
13676 			action->conf = &sample_port_id[idx];
13677 			break;
13678 		case RTE_FLOW_ACTION_TYPE_PF:
13679 			break;
13680 		case RTE_FLOW_ACTION_TYPE_VF:
13681 			size = sizeof(struct rte_flow_action_vf);
13682 			rte_memcpy(&sample_vf[idx],
13683 					(const void *)action->conf, size);
13684 			action->conf = &sample_vf[idx];
13685 			break;
13686 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13687 			size = sizeof(struct rte_flow_action_vxlan_encap);
13688 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13689 			action->conf = &sample_vxlan_encap[idx].conf;
13690 			break;
13691 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13692 			size = sizeof(struct rte_flow_action_nvgre_encap);
13693 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13694 			action->conf = &sample_nvgre_encap[idx];
13695 			break;
13696 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13697 			size = sizeof(struct rte_flow_action_ethdev);
13698 			rte_memcpy(&sample_port_representor[idx],
13699 					(const void *)action->conf, size);
13700 			action->conf = &sample_port_representor[idx];
13701 			break;
13702 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13703 			size = sizeof(struct rte_flow_action_ethdev);
13704 			rte_memcpy(&sample_represented_port[idx],
13705 					(const void *)action->conf, size);
13706 			action->conf = &sample_represented_port[idx];
13707 			break;
13708 		default:
13709 			fprintf(stderr, "Error - Not supported action\n");
13710 			return;
13711 		}
13712 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13713 		data++;
13714 	}
13715 }
13716 
13717 /** Dispatch parsed buffer to function calls. */
13718 static void
13719 cmd_set_raw_parsed(const struct buffer *in)
13720 {
13721 	uint32_t n = in->args.vc.pattern_n;
13722 	int i = 0;
13723 	struct rte_flow_item *item = NULL;
13724 	size_t size = 0;
13725 	uint8_t *data = NULL;
13726 	uint8_t *data_tail = NULL;
13727 	size_t *total_size = NULL;
13728 	uint16_t upper_layer = 0;
13729 	uint16_t proto = 0;
13730 	uint16_t idx = in->port; /* We borrow port field as index */
13731 	int gtp_psc = -1; /* GTP PSC option index. */
13732 	const void *src_spec;
13733 
13734 	if (in->command == SET_SAMPLE_ACTIONS)
13735 		return cmd_set_raw_parsed_sample(in);
13736 	else if (in->command == SET_IPV6_EXT_PUSH ||
13737 		 in->command == SET_IPV6_EXT_REMOVE)
13738 		return cmd_set_ipv6_ext_parsed(in);
13739 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13740 		   in->command == SET_RAW_DECAP);
13741 	if (in->command == SET_RAW_ENCAP) {
13742 		total_size = &raw_encap_confs[idx].size;
13743 		data = (uint8_t *)&raw_encap_confs[idx].data;
13744 	} else {
13745 		total_size = &raw_decap_confs[idx].size;
13746 		data = (uint8_t *)&raw_decap_confs[idx].data;
13747 	}
13748 	*total_size = 0;
13749 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13750 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13751 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13752 	for (i = n - 1 ; i >= 0; --i) {
13753 		const struct rte_flow_item_gtp *gtp;
13754 		const struct rte_flow_item_geneve_opt *opt;
13755 		struct rte_flow_item_ipv6_routing_ext *ext;
13756 
13757 		item = in->args.vc.pattern + i;
13758 		if (item->spec == NULL)
13759 			item->spec = flow_item_default_mask(item);
13760 		src_spec = item->spec;
13761 		switch (item->type) {
13762 		case RTE_FLOW_ITEM_TYPE_ETH:
13763 			size = sizeof(struct rte_ether_hdr);
13764 			break;
13765 		case RTE_FLOW_ITEM_TYPE_VLAN:
13766 			size = sizeof(struct rte_vlan_hdr);
13767 			proto = RTE_ETHER_TYPE_VLAN;
13768 			break;
13769 		case RTE_FLOW_ITEM_TYPE_IPV4:
13770 			size = sizeof(struct rte_ipv4_hdr);
13771 			proto = RTE_ETHER_TYPE_IPV4;
13772 			break;
13773 		case RTE_FLOW_ITEM_TYPE_IPV6:
13774 			size = sizeof(struct rte_ipv6_hdr);
13775 			proto = RTE_ETHER_TYPE_IPV6;
13776 			break;
13777 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13778 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13779 			if (!ext->hdr.hdr_len) {
13780 				size = sizeof(struct rte_ipv6_routing_ext) +
13781 					(ext->hdr.segments_left << 4);
13782 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13783 				/* SRv6 without TLV. */
13784 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13785 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13786 			} else {
13787 				size = sizeof(struct rte_ipv6_routing_ext) +
13788 					(ext->hdr.hdr_len << 3);
13789 			}
13790 			proto = IPPROTO_ROUTING;
13791 			break;
13792 		case RTE_FLOW_ITEM_TYPE_UDP:
13793 			size = sizeof(struct rte_udp_hdr);
13794 			proto = 0x11;
13795 			break;
13796 		case RTE_FLOW_ITEM_TYPE_TCP:
13797 			size = sizeof(struct rte_tcp_hdr);
13798 			proto = 0x06;
13799 			break;
13800 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13801 			size = sizeof(struct rte_vxlan_hdr);
13802 			break;
13803 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13804 			size = sizeof(struct rte_vxlan_gpe_hdr);
13805 			break;
13806 		case RTE_FLOW_ITEM_TYPE_GRE:
13807 			size = sizeof(struct rte_gre_hdr);
13808 			proto = 0x2F;
13809 			break;
13810 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13811 			size = sizeof(rte_be32_t);
13812 			proto = 0x0;
13813 			break;
13814 		case RTE_FLOW_ITEM_TYPE_MPLS:
13815 			size = sizeof(struct rte_mpls_hdr);
13816 			proto = 0x0;
13817 			break;
13818 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13819 			size = sizeof(struct rte_flow_item_nvgre);
13820 			proto = 0x2F;
13821 			break;
13822 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13823 			size = sizeof(struct rte_geneve_hdr);
13824 			break;
13825 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13826 			opt = (const struct rte_flow_item_geneve_opt *)
13827 								item->spec;
13828 			size = offsetof(struct rte_flow_item_geneve_opt,
13829 					option_len) + sizeof(uint8_t);
13830 			if (opt->option_len && opt->data) {
13831 				*total_size += opt->option_len *
13832 					       sizeof(uint32_t);
13833 				rte_memcpy(data_tail - (*total_size),
13834 					   opt->data,
13835 					   opt->option_len * sizeof(uint32_t));
13836 			}
13837 			break;
13838 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13839 			size = sizeof(rte_be32_t);
13840 			proto = 0x73;
13841 			break;
13842 		case RTE_FLOW_ITEM_TYPE_ESP:
13843 			size = sizeof(struct rte_esp_hdr);
13844 			proto = 0x32;
13845 			break;
13846 		case RTE_FLOW_ITEM_TYPE_AH:
13847 			size = sizeof(struct rte_flow_item_ah);
13848 			proto = 0x33;
13849 			break;
13850 		case RTE_FLOW_ITEM_TYPE_GTP:
13851 			if (gtp_psc < 0) {
13852 				size = sizeof(struct rte_gtp_hdr);
13853 				break;
13854 			}
13855 			if (gtp_psc != i + 1) {
13856 				fprintf(stderr,
13857 					"Error - GTP PSC does not follow GTP\n");
13858 				goto error;
13859 			}
13860 			gtp = item->spec;
13861 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13862 				/* Only E flag should be set. */
13863 				fprintf(stderr,
13864 					"Error - GTP unsupported flags\n");
13865 				goto error;
13866 			} else {
13867 				struct rte_gtp_hdr_ext_word ext_word = {
13868 					.next_ext = 0x85
13869 				};
13870 
13871 				/* We have to add GTP header extra word. */
13872 				*total_size += sizeof(ext_word);
13873 				rte_memcpy(data_tail - (*total_size),
13874 					   &ext_word, sizeof(ext_word));
13875 			}
13876 			size = sizeof(struct rte_gtp_hdr);
13877 			break;
13878 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13879 			if (gtp_psc >= 0) {
13880 				fprintf(stderr,
13881 					"Error - Multiple GTP PSC items\n");
13882 				goto error;
13883 			} else {
13884 				const struct rte_flow_item_gtp_psc
13885 					*opt = item->spec;
13886 				struct rte_gtp_psc_generic_hdr *hdr;
13887 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
13888 							 sizeof(int32_t));
13889 
13890 				*total_size += hdr_size;
13891 				hdr = (typeof(hdr))(data_tail - (*total_size));
13892 				memset(hdr, 0, hdr_size);
13893 				*hdr = opt->hdr;
13894 				hdr->ext_hdr_len = 1;
13895 				gtp_psc = i;
13896 				size = 0;
13897 			}
13898 			break;
13899 		case RTE_FLOW_ITEM_TYPE_PFCP:
13900 			size = sizeof(struct rte_flow_item_pfcp);
13901 			break;
13902 		case RTE_FLOW_ITEM_TYPE_FLEX:
13903 			if (item->spec != NULL) {
13904 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
13905 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
13906 			} else {
13907 				size = 0;
13908 				src_spec = NULL;
13909 			}
13910 			break;
13911 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
13912 			size = 0;
13913 			if (item->spec) {
13914 				const struct rte_flow_item_gre_opt
13915 					*opt = item->spec;
13916 				if (opt->checksum_rsvd.checksum) {
13917 					*total_size +=
13918 						sizeof(opt->checksum_rsvd);
13919 					rte_memcpy(data_tail - (*total_size),
13920 						   &opt->checksum_rsvd,
13921 						   sizeof(opt->checksum_rsvd));
13922 				}
13923 				if (opt->key.key) {
13924 					*total_size += sizeof(opt->key.key);
13925 					rte_memcpy(data_tail - (*total_size),
13926 						   &opt->key.key,
13927 						   sizeof(opt->key.key));
13928 				}
13929 				if (opt->sequence.sequence) {
13930 					*total_size += sizeof(opt->sequence.sequence);
13931 					rte_memcpy(data_tail - (*total_size),
13932 						   &opt->sequence.sequence,
13933 						   sizeof(opt->sequence.sequence));
13934 				}
13935 			}
13936 			proto = 0x2F;
13937 			break;
13938 		default:
13939 			fprintf(stderr, "Error - Not supported item\n");
13940 			goto error;
13941 		}
13942 		if (size) {
13943 			*total_size += size;
13944 			rte_memcpy(data_tail - (*total_size), src_spec, size);
13945 			/* update some fields which cannot be set by cmdline */
13946 			update_fields((data_tail - (*total_size)), item,
13947 				      upper_layer);
13948 			upper_layer = proto;
13949 		}
13950 	}
13951 	if (verbose_level & 0x1)
13952 		printf("total data size is %zu\n", (*total_size));
13953 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
13954 	memmove(data, (data_tail - (*total_size)), *total_size);
13955 	return;
13956 
13957 error:
13958 	*total_size = 0;
13959 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13960 }
13961 
13962 /** Populate help strings for current token (cmdline API). */
13963 static int
13964 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
13965 		     unsigned int size)
13966 {
13967 	struct context *ctx = &cmd_flow_context;
13968 	const struct token *token = &token_list[ctx->prev];
13969 
13970 	(void)hdr;
13971 	if (!size)
13972 		return -1;
13973 	/* Set token type and update global help with details. */
13974 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
13975 	if (token->help)
13976 		cmd_set_raw.help_str = token->help;
13977 	else
13978 		cmd_set_raw.help_str = token->name;
13979 	return 0;
13980 }
13981 
13982 /** Token definition template (cmdline API). */
13983 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
13984 	.ops = &(struct cmdline_token_ops){
13985 		.parse = cmd_flow_parse,
13986 		.complete_get_nb = cmd_flow_complete_get_nb,
13987 		.complete_get_elt = cmd_flow_complete_get_elt,
13988 		.get_help = cmd_set_raw_get_help,
13989 	},
13990 	.offset = 0,
13991 };
13992 
13993 /** Populate the next dynamic token. */
13994 static void
13995 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
13996 	     cmdline_parse_token_hdr_t **hdr_inst)
13997 {
13998 	struct context *ctx = &cmd_flow_context;
13999 
14000 	/* Always reinitialize context before requesting the first token. */
14001 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14002 		cmd_flow_context_init(ctx);
14003 		ctx->curr = START_SET;
14004 	}
14005 	/* Return NULL when no more tokens are expected. */
14006 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14007 		*hdr = NULL;
14008 		return;
14009 	}
14010 	/* Determine if command should end here. */
14011 	if (ctx->eol && ctx->last && ctx->next_num) {
14012 		const enum index *list = ctx->next[ctx->next_num - 1];
14013 		int i;
14014 
14015 		for (i = 0; list[i]; ++i) {
14016 			if (list[i] != END)
14017 				continue;
14018 			*hdr = NULL;
14019 			return;
14020 		}
14021 	}
14022 	*hdr = &cmd_set_raw_token_hdr;
14023 }
14024 
14025 /** Token generator and output processing callback (cmdline API). */
14026 static void
14027 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14028 {
14029 	if (cl == NULL)
14030 		cmd_set_raw_tok(arg0, arg2);
14031 	else
14032 		cmd_set_raw_parsed(arg0);
14033 }
14034 
14035 /** Global parser instance (cmdline API). */
14036 cmdline_parse_inst_t cmd_set_raw = {
14037 	.f = cmd_set_raw_cb,
14038 	.data = NULL, /**< Unused. */
14039 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14040 	.tokens = {
14041 		NULL,
14042 	}, /**< Tokens are returned by cmd_flow_tok(). */
14043 };
14044 
14045 /* *** display raw_encap/raw_decap buf */
14046 struct cmd_show_set_raw_result {
14047 	cmdline_fixed_string_t cmd_show;
14048 	cmdline_fixed_string_t cmd_what;
14049 	cmdline_fixed_string_t cmd_all;
14050 	uint16_t cmd_index;
14051 };
14052 
14053 static void
14054 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14055 {
14056 	struct cmd_show_set_raw_result *res = parsed_result;
14057 	uint16_t index = res->cmd_index;
14058 	uint8_t all = 0;
14059 	uint8_t *raw_data = NULL;
14060 	size_t raw_size = 0;
14061 	char title[16] = {0};
14062 
14063 	RTE_SET_USED(cl);
14064 	RTE_SET_USED(data);
14065 	if (!strcmp(res->cmd_all, "all")) {
14066 		all = 1;
14067 		index = 0;
14068 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14069 		fprintf(stderr, "index should be 0-%u\n",
14070 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14071 		return;
14072 	}
14073 	do {
14074 		if (!strcmp(res->cmd_what, "raw_encap")) {
14075 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14076 			raw_size = raw_encap_confs[index].size;
14077 			snprintf(title, 16, "\nindex: %u", index);
14078 			rte_hexdump(stdout, title, raw_data, raw_size);
14079 		} else {
14080 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14081 			raw_size = raw_decap_confs[index].size;
14082 			snprintf(title, 16, "\nindex: %u", index);
14083 			rte_hexdump(stdout, title, raw_data, raw_size);
14084 		}
14085 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14086 }
14087 
14088 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14089 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14090 			cmd_show, "show");
14091 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14092 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14093 			cmd_what, "raw_encap#raw_decap");
14094 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14095 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14096 			cmd_index, RTE_UINT16);
14097 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14098 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14099 			cmd_all, "all");
14100 cmdline_parse_inst_t cmd_show_set_raw = {
14101 	.f = cmd_show_set_raw_parsed,
14102 	.data = NULL,
14103 	.help_str = "show <raw_encap|raw_decap> <index>",
14104 	.tokens = {
14105 		(void *)&cmd_show_set_raw_cmd_show,
14106 		(void *)&cmd_show_set_raw_cmd_what,
14107 		(void *)&cmd_show_set_raw_cmd_index,
14108 		NULL,
14109 	},
14110 };
14111 cmdline_parse_inst_t cmd_show_set_raw_all = {
14112 	.f = cmd_show_set_raw_parsed,
14113 	.data = NULL,
14114 	.help_str = "show <raw_encap|raw_decap> all",
14115 	.tokens = {
14116 		(void *)&cmd_show_set_raw_cmd_show,
14117 		(void *)&cmd_show_set_raw_cmd_what,
14118 		(void *)&cmd_show_set_raw_cmd_all,
14119 		NULL,
14120 	},
14121 };
14122