xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 99231e480b69e2e722ae976c69e0c5dd4b37122a)
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_ARP_ETH_IPV4,
415 	ITEM_ARP_ETH_IPV4_SHA,
416 	ITEM_ARP_ETH_IPV4_SPA,
417 	ITEM_ARP_ETH_IPV4_THA,
418 	ITEM_ARP_ETH_IPV4_TPA,
419 	ITEM_IPV6_EXT,
420 	ITEM_IPV6_EXT_NEXT_HDR,
421 	ITEM_IPV6_FRAG_EXT,
422 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
423 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
424 	ITEM_IPV6_FRAG_EXT_ID,
425 	ITEM_ICMP6,
426 	ITEM_ICMP6_TYPE,
427 	ITEM_ICMP6_CODE,
428 	ITEM_ICMP6_ECHO_REQUEST,
429 	ITEM_ICMP6_ECHO_REQUEST_ID,
430 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
431 	ITEM_ICMP6_ECHO_REPLY,
432 	ITEM_ICMP6_ECHO_REPLY_ID,
433 	ITEM_ICMP6_ECHO_REPLY_SEQ,
434 	ITEM_ICMP6_ND_NS,
435 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
436 	ITEM_ICMP6_ND_NA,
437 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
438 	ITEM_ICMP6_ND_OPT,
439 	ITEM_ICMP6_ND_OPT_TYPE,
440 	ITEM_ICMP6_ND_OPT_SLA_ETH,
441 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
442 	ITEM_ICMP6_ND_OPT_TLA_ETH,
443 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
444 	ITEM_META,
445 	ITEM_META_DATA,
446 	ITEM_RANDOM,
447 	ITEM_RANDOM_VALUE,
448 	ITEM_GRE_KEY,
449 	ITEM_GRE_KEY_VALUE,
450 	ITEM_GRE_OPTION,
451 	ITEM_GRE_OPTION_CHECKSUM,
452 	ITEM_GRE_OPTION_KEY,
453 	ITEM_GRE_OPTION_SEQUENCE,
454 	ITEM_GTP_PSC,
455 	ITEM_GTP_PSC_QFI,
456 	ITEM_GTP_PSC_PDU_T,
457 	ITEM_PPPOES,
458 	ITEM_PPPOED,
459 	ITEM_PPPOE_SEID,
460 	ITEM_PPPOE_PROTO_ID,
461 	ITEM_HIGIG2,
462 	ITEM_HIGIG2_CLASSIFICATION,
463 	ITEM_HIGIG2_VID,
464 	ITEM_TAG,
465 	ITEM_TAG_DATA,
466 	ITEM_TAG_INDEX,
467 	ITEM_L2TPV3OIP,
468 	ITEM_L2TPV3OIP_SESSION_ID,
469 	ITEM_ESP,
470 	ITEM_ESP_SPI,
471 	ITEM_AH,
472 	ITEM_AH_SPI,
473 	ITEM_PFCP,
474 	ITEM_PFCP_S_FIELD,
475 	ITEM_PFCP_SEID,
476 	ITEM_ECPRI,
477 	ITEM_ECPRI_COMMON,
478 	ITEM_ECPRI_COMMON_TYPE,
479 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
480 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
481 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
482 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
483 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
484 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
485 	ITEM_GENEVE_OPT,
486 	ITEM_GENEVE_OPT_CLASS,
487 	ITEM_GENEVE_OPT_TYPE,
488 	ITEM_GENEVE_OPT_LENGTH,
489 	ITEM_GENEVE_OPT_DATA,
490 	ITEM_INTEGRITY,
491 	ITEM_INTEGRITY_LEVEL,
492 	ITEM_INTEGRITY_VALUE,
493 	ITEM_CONNTRACK,
494 	ITEM_POL_PORT,
495 	ITEM_POL_METER,
496 	ITEM_POL_POLICY,
497 	ITEM_PORT_REPRESENTOR,
498 	ITEM_PORT_REPRESENTOR_PORT_ID,
499 	ITEM_REPRESENTED_PORT,
500 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
501 	ITEM_FLEX,
502 	ITEM_FLEX_ITEM_HANDLE,
503 	ITEM_FLEX_PATTERN_HANDLE,
504 	ITEM_L2TPV2,
505 	ITEM_L2TPV2_TYPE,
506 	ITEM_L2TPV2_TYPE_DATA,
507 	ITEM_L2TPV2_TYPE_DATA_L,
508 	ITEM_L2TPV2_TYPE_DATA_S,
509 	ITEM_L2TPV2_TYPE_DATA_O,
510 	ITEM_L2TPV2_TYPE_DATA_L_S,
511 	ITEM_L2TPV2_TYPE_CTRL,
512 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
513 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
514 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
515 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
516 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
517 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
518 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
519 	ITEM_L2TPV2_MSG_DATA_S_NS,
520 	ITEM_L2TPV2_MSG_DATA_S_NR,
521 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
522 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
523 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
524 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
525 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
526 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
527 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
528 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
529 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
530 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
531 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
532 	ITEM_L2TPV2_MSG_CTRL_NS,
533 	ITEM_L2TPV2_MSG_CTRL_NR,
534 	ITEM_PPP,
535 	ITEM_PPP_ADDR,
536 	ITEM_PPP_CTRL,
537 	ITEM_PPP_PROTO_ID,
538 	ITEM_METER,
539 	ITEM_METER_COLOR,
540 	ITEM_METER_COLOR_NAME,
541 	ITEM_QUOTA,
542 	ITEM_QUOTA_STATE,
543 	ITEM_QUOTA_STATE_NAME,
544 	ITEM_AGGR_AFFINITY,
545 	ITEM_AGGR_AFFINITY_VALUE,
546 	ITEM_TX_QUEUE,
547 	ITEM_TX_QUEUE_VALUE,
548 	ITEM_IB_BTH,
549 	ITEM_IB_BTH_OPCODE,
550 	ITEM_IB_BTH_PKEY,
551 	ITEM_IB_BTH_DST_QPN,
552 	ITEM_IB_BTH_PSN,
553 	ITEM_IPV6_PUSH_REMOVE_EXT,
554 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
555 	ITEM_PTYPE,
556 	ITEM_PTYPE_VALUE,
557 	ITEM_NSH,
558 	ITEM_COMPARE,
559 	ITEM_COMPARE_OP,
560 	ITEM_COMPARE_OP_VALUE,
561 	ITEM_COMPARE_FIELD_A_TYPE,
562 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
563 	ITEM_COMPARE_FIELD_A_LEVEL,
564 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
565 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
566 	ITEM_COMPARE_FIELD_A_TYPE_ID,
567 	ITEM_COMPARE_FIELD_A_CLASS_ID,
568 	ITEM_COMPARE_FIELD_A_OFFSET,
569 	ITEM_COMPARE_FIELD_B_TYPE,
570 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
571 	ITEM_COMPARE_FIELD_B_LEVEL,
572 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
573 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
574 	ITEM_COMPARE_FIELD_B_TYPE_ID,
575 	ITEM_COMPARE_FIELD_B_CLASS_ID,
576 	ITEM_COMPARE_FIELD_B_OFFSET,
577 	ITEM_COMPARE_FIELD_B_VALUE,
578 	ITEM_COMPARE_FIELD_B_POINTER,
579 	ITEM_COMPARE_FIELD_WIDTH,
580 
581 	/* Validate/create actions. */
582 	ACTIONS,
583 	ACTION_NEXT,
584 	ACTION_END,
585 	ACTION_VOID,
586 	ACTION_PASSTHRU,
587 	ACTION_SKIP_CMAN,
588 	ACTION_JUMP,
589 	ACTION_JUMP_GROUP,
590 	ACTION_MARK,
591 	ACTION_MARK_ID,
592 	ACTION_FLAG,
593 	ACTION_QUEUE,
594 	ACTION_QUEUE_INDEX,
595 	ACTION_DROP,
596 	ACTION_COUNT,
597 	ACTION_COUNT_ID,
598 	ACTION_RSS,
599 	ACTION_RSS_FUNC,
600 	ACTION_RSS_LEVEL,
601 	ACTION_RSS_FUNC_DEFAULT,
602 	ACTION_RSS_FUNC_TOEPLITZ,
603 	ACTION_RSS_FUNC_SIMPLE_XOR,
604 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
605 	ACTION_RSS_TYPES,
606 	ACTION_RSS_TYPE,
607 	ACTION_RSS_KEY,
608 	ACTION_RSS_KEY_LEN,
609 	ACTION_RSS_QUEUES,
610 	ACTION_RSS_QUEUE,
611 	ACTION_PF,
612 	ACTION_VF,
613 	ACTION_VF_ORIGINAL,
614 	ACTION_VF_ID,
615 	ACTION_PORT_ID,
616 	ACTION_PORT_ID_ORIGINAL,
617 	ACTION_PORT_ID_ID,
618 	ACTION_METER,
619 	ACTION_METER_COLOR,
620 	ACTION_METER_COLOR_TYPE,
621 	ACTION_METER_COLOR_GREEN,
622 	ACTION_METER_COLOR_YELLOW,
623 	ACTION_METER_COLOR_RED,
624 	ACTION_METER_ID,
625 	ACTION_METER_MARK,
626 	ACTION_METER_PROFILE,
627 	ACTION_METER_PROFILE_ID2PTR,
628 	ACTION_METER_POLICY,
629 	ACTION_METER_POLICY_ID2PTR,
630 	ACTION_METER_COLOR_MODE,
631 	ACTION_METER_STATE,
632 	ACTION_OF_DEC_NW_TTL,
633 	ACTION_OF_POP_VLAN,
634 	ACTION_OF_PUSH_VLAN,
635 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
636 	ACTION_OF_SET_VLAN_VID,
637 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
638 	ACTION_OF_SET_VLAN_PCP,
639 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
640 	ACTION_OF_POP_MPLS,
641 	ACTION_OF_POP_MPLS_ETHERTYPE,
642 	ACTION_OF_PUSH_MPLS,
643 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
644 	ACTION_VXLAN_ENCAP,
645 	ACTION_VXLAN_DECAP,
646 	ACTION_NVGRE_ENCAP,
647 	ACTION_NVGRE_DECAP,
648 	ACTION_L2_ENCAP,
649 	ACTION_L2_DECAP,
650 	ACTION_MPLSOGRE_ENCAP,
651 	ACTION_MPLSOGRE_DECAP,
652 	ACTION_MPLSOUDP_ENCAP,
653 	ACTION_MPLSOUDP_DECAP,
654 	ACTION_SET_IPV4_SRC,
655 	ACTION_SET_IPV4_SRC_IPV4_SRC,
656 	ACTION_SET_IPV4_DST,
657 	ACTION_SET_IPV4_DST_IPV4_DST,
658 	ACTION_SET_IPV6_SRC,
659 	ACTION_SET_IPV6_SRC_IPV6_SRC,
660 	ACTION_SET_IPV6_DST,
661 	ACTION_SET_IPV6_DST_IPV6_DST,
662 	ACTION_SET_TP_SRC,
663 	ACTION_SET_TP_SRC_TP_SRC,
664 	ACTION_SET_TP_DST,
665 	ACTION_SET_TP_DST_TP_DST,
666 	ACTION_MAC_SWAP,
667 	ACTION_DEC_TTL,
668 	ACTION_SET_TTL,
669 	ACTION_SET_TTL_TTL,
670 	ACTION_SET_MAC_SRC,
671 	ACTION_SET_MAC_SRC_MAC_SRC,
672 	ACTION_SET_MAC_DST,
673 	ACTION_SET_MAC_DST_MAC_DST,
674 	ACTION_INC_TCP_SEQ,
675 	ACTION_INC_TCP_SEQ_VALUE,
676 	ACTION_DEC_TCP_SEQ,
677 	ACTION_DEC_TCP_SEQ_VALUE,
678 	ACTION_INC_TCP_ACK,
679 	ACTION_INC_TCP_ACK_VALUE,
680 	ACTION_DEC_TCP_ACK,
681 	ACTION_DEC_TCP_ACK_VALUE,
682 	ACTION_RAW_ENCAP,
683 	ACTION_RAW_DECAP,
684 	ACTION_RAW_ENCAP_SIZE,
685 	ACTION_RAW_ENCAP_INDEX,
686 	ACTION_RAW_ENCAP_INDEX_VALUE,
687 	ACTION_RAW_DECAP_INDEX,
688 	ACTION_RAW_DECAP_INDEX_VALUE,
689 	ACTION_SET_TAG,
690 	ACTION_SET_TAG_DATA,
691 	ACTION_SET_TAG_INDEX,
692 	ACTION_SET_TAG_MASK,
693 	ACTION_SET_META,
694 	ACTION_SET_META_DATA,
695 	ACTION_SET_META_MASK,
696 	ACTION_SET_IPV4_DSCP,
697 	ACTION_SET_IPV4_DSCP_VALUE,
698 	ACTION_SET_IPV6_DSCP,
699 	ACTION_SET_IPV6_DSCP_VALUE,
700 	ACTION_AGE,
701 	ACTION_AGE_TIMEOUT,
702 	ACTION_AGE_UPDATE,
703 	ACTION_AGE_UPDATE_TIMEOUT,
704 	ACTION_AGE_UPDATE_TOUCH,
705 	ACTION_SAMPLE,
706 	ACTION_SAMPLE_RATIO,
707 	ACTION_SAMPLE_INDEX,
708 	ACTION_SAMPLE_INDEX_VALUE,
709 	ACTION_INDIRECT,
710 	ACTION_INDIRECT_LIST,
711 	ACTION_INDIRECT_LIST_HANDLE,
712 	ACTION_INDIRECT_LIST_CONF,
713 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
714 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
715 	ACTION_SHARED_INDIRECT,
716 	INDIRECT_ACTION_PORT,
717 	INDIRECT_ACTION_ID2PTR,
718 	ACTION_MODIFY_FIELD,
719 	ACTION_MODIFY_FIELD_OP,
720 	ACTION_MODIFY_FIELD_OP_VALUE,
721 	ACTION_MODIFY_FIELD_DST_TYPE,
722 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
723 	ACTION_MODIFY_FIELD_DST_LEVEL,
724 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
725 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
726 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
727 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
728 	ACTION_MODIFY_FIELD_DST_OFFSET,
729 	ACTION_MODIFY_FIELD_SRC_TYPE,
730 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
731 	ACTION_MODIFY_FIELD_SRC_LEVEL,
732 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
733 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
734 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
735 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
736 	ACTION_MODIFY_FIELD_SRC_OFFSET,
737 	ACTION_MODIFY_FIELD_SRC_VALUE,
738 	ACTION_MODIFY_FIELD_SRC_POINTER,
739 	ACTION_MODIFY_FIELD_WIDTH,
740 	ACTION_CONNTRACK,
741 	ACTION_CONNTRACK_UPDATE,
742 	ACTION_CONNTRACK_UPDATE_DIR,
743 	ACTION_CONNTRACK_UPDATE_CTX,
744 	ACTION_POL_G,
745 	ACTION_POL_Y,
746 	ACTION_POL_R,
747 	ACTION_PORT_REPRESENTOR,
748 	ACTION_PORT_REPRESENTOR_PORT_ID,
749 	ACTION_REPRESENTED_PORT,
750 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
751 	ACTION_SEND_TO_KERNEL,
752 	ACTION_QUOTA_CREATE,
753 	ACTION_QUOTA_CREATE_LIMIT,
754 	ACTION_QUOTA_CREATE_MODE,
755 	ACTION_QUOTA_CREATE_MODE_NAME,
756 	ACTION_QUOTA_QU,
757 	ACTION_QUOTA_QU_LIMIT,
758 	ACTION_QUOTA_QU_UPDATE_OP,
759 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
760 	ACTION_IPV6_EXT_REMOVE,
761 	ACTION_IPV6_EXT_REMOVE_INDEX,
762 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
763 	ACTION_IPV6_EXT_PUSH,
764 	ACTION_IPV6_EXT_PUSH_INDEX,
765 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
766 	ACTION_NAT64,
767 	ACTION_NAT64_MODE,
768 };
769 
770 /** Maximum size for pattern in struct rte_flow_item_raw. */
771 #define ITEM_RAW_PATTERN_SIZE 512
772 
773 /** Maximum size for GENEVE option data pattern in bytes. */
774 #define ITEM_GENEVE_OPT_DATA_SIZE 124
775 
776 /** Storage size for struct rte_flow_item_raw including pattern. */
777 #define ITEM_RAW_SIZE \
778 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
779 
780 static const char *const compare_ops[] = {
781 	"eq", "ne", "lt", "le", "gt", "ge", NULL
782 };
783 
784 /** Maximum size for external pattern in struct rte_flow_field_data. */
785 #define FLOW_FIELD_PATTERN_SIZE 32
786 
787 /** Storage size for struct rte_flow_action_modify_field including pattern. */
788 #define ACTION_MODIFY_SIZE \
789 	(sizeof(struct rte_flow_action_modify_field) + \
790 	FLOW_FIELD_PATTERN_SIZE)
791 
792 /** Maximum number of queue indices in struct rte_flow_action_rss. */
793 #define ACTION_RSS_QUEUE_NUM 128
794 
795 /** Storage for struct rte_flow_action_rss including external data. */
796 struct action_rss_data {
797 	struct rte_flow_action_rss conf;
798 	uint8_t key[RSS_HASH_KEY_LENGTH];
799 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
800 };
801 
802 /** Maximum data size in struct rte_flow_action_raw_encap. */
803 #define ACTION_RAW_ENCAP_MAX_DATA 512
804 #define RAW_ENCAP_CONFS_MAX_NUM 8
805 
806 /** Storage for struct rte_flow_action_raw_encap. */
807 struct raw_encap_conf {
808 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
809 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
810 	size_t size;
811 };
812 
813 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
814 
815 /** Storage for struct rte_flow_action_raw_encap including external data. */
816 struct action_raw_encap_data {
817 	struct rte_flow_action_raw_encap conf;
818 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
819 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
820 	uint16_t idx;
821 };
822 
823 /** Storage for struct rte_flow_action_raw_decap. */
824 struct raw_decap_conf {
825 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
826 	size_t size;
827 };
828 
829 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
830 
831 /** Storage for struct rte_flow_action_raw_decap including external data. */
832 struct action_raw_decap_data {
833 	struct rte_flow_action_raw_decap conf;
834 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
835 	uint16_t idx;
836 };
837 
838 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
839 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
840 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
841 
842 /** Storage for struct rte_flow_action_ipv6_ext_push. */
843 struct ipv6_ext_push_conf {
844 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
845 	size_t size;
846 	uint8_t type;
847 };
848 
849 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
850 
851 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
852 struct action_ipv6_ext_push_data {
853 	struct rte_flow_action_ipv6_ext_push conf;
854 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
855 	uint8_t type;
856 	uint16_t idx;
857 };
858 
859 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
860 struct ipv6_ext_remove_conf {
861 	struct rte_flow_action_ipv6_ext_remove conf;
862 	uint8_t type;
863 };
864 
865 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
866 
867 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
868 struct action_ipv6_ext_remove_data {
869 	struct rte_flow_action_ipv6_ext_remove conf;
870 	uint8_t type;
871 	uint16_t idx;
872 };
873 
874 struct vxlan_encap_conf vxlan_encap_conf = {
875 	.select_ipv4 = 1,
876 	.select_vlan = 0,
877 	.select_tos_ttl = 0,
878 	.vni = "\x00\x00\x00",
879 	.udp_src = 0,
880 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
881 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
882 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
883 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
884 		"\x00\x00\x00\x00\x00\x00\x00\x01",
885 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
886 		"\x00\x00\x00\x00\x00\x00\x11\x11",
887 	.vlan_tci = 0,
888 	.ip_tos = 0,
889 	.ip_ttl = 255,
890 	.eth_src = "\x00\x00\x00\x00\x00\x00",
891 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
892 };
893 
894 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
895 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
896 
897 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
898 struct action_vxlan_encap_data {
899 	struct rte_flow_action_vxlan_encap conf;
900 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
901 	struct rte_flow_item_eth item_eth;
902 	struct rte_flow_item_vlan item_vlan;
903 	union {
904 		struct rte_flow_item_ipv4 item_ipv4;
905 		struct rte_flow_item_ipv6 item_ipv6;
906 	};
907 	struct rte_flow_item_udp item_udp;
908 	struct rte_flow_item_vxlan item_vxlan;
909 };
910 
911 struct nvgre_encap_conf nvgre_encap_conf = {
912 	.select_ipv4 = 1,
913 	.select_vlan = 0,
914 	.tni = "\x00\x00\x00",
915 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
916 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
917 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
918 		"\x00\x00\x00\x00\x00\x00\x00\x01",
919 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
920 		"\x00\x00\x00\x00\x00\x00\x11\x11",
921 	.vlan_tci = 0,
922 	.eth_src = "\x00\x00\x00\x00\x00\x00",
923 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
924 };
925 
926 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
927 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
928 
929 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
930 struct action_nvgre_encap_data {
931 	struct rte_flow_action_nvgre_encap conf;
932 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
933 	struct rte_flow_item_eth item_eth;
934 	struct rte_flow_item_vlan item_vlan;
935 	union {
936 		struct rte_flow_item_ipv4 item_ipv4;
937 		struct rte_flow_item_ipv6 item_ipv6;
938 	};
939 	struct rte_flow_item_nvgre item_nvgre;
940 };
941 
942 struct l2_encap_conf l2_encap_conf;
943 
944 struct l2_decap_conf l2_decap_conf;
945 
946 struct mplsogre_encap_conf mplsogre_encap_conf;
947 
948 struct mplsogre_decap_conf mplsogre_decap_conf;
949 
950 struct mplsoudp_encap_conf mplsoudp_encap_conf;
951 
952 struct mplsoudp_decap_conf mplsoudp_decap_conf;
953 
954 struct rte_flow_action_conntrack conntrack_context;
955 
956 #define ACTION_SAMPLE_ACTIONS_NUM 10
957 #define RAW_SAMPLE_CONFS_MAX_NUM 8
958 /** Storage for struct rte_flow_action_sample including external data. */
959 struct action_sample_data {
960 	struct rte_flow_action_sample conf;
961 	uint32_t idx;
962 };
963 /** Storage for struct rte_flow_action_sample. */
964 struct raw_sample_conf {
965 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
966 };
967 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
968 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
969 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
970 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
971 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
972 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
973 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
974 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
975 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
976 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
977 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
978 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
979 
980 static const char *const modify_field_ops[] = {
981 	"set", "add", "sub", NULL
982 };
983 
984 static const char *const flow_field_ids[] = {
985 	"start", "mac_dst", "mac_src",
986 	"vlan_type", "vlan_id", "mac_type",
987 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
988 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
989 	"tcp_port_src", "tcp_port_dst",
990 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
991 	"udp_port_src", "udp_port_dst",
992 	"vxlan_vni", "geneve_vni", "gtp_teid",
993 	"tag", "mark", "meta", "pointer", "value",
994 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
995 	"ipv6_proto",
996 	"flex_item",
997 	"hash_result",
998 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
999 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1000 	"random",
1001 	NULL
1002 };
1003 
1004 static const char *const meter_colors[] = {
1005 	"green", "yellow", "red", "all", NULL
1006 };
1007 
1008 static const char *const table_insertion_types[] = {
1009 	"pattern", "index", NULL
1010 };
1011 
1012 static const char *const table_hash_funcs[] = {
1013 	"default", "linear", "crc32", "crc16", NULL
1014 };
1015 
1016 #define RAW_IPSEC_CONFS_MAX_NUM 8
1017 
1018 /** Maximum number of subsequent tokens and arguments on the stack. */
1019 #define CTX_STACK_SIZE 16
1020 
1021 /** Parser context. */
1022 struct context {
1023 	/** Stack of subsequent token lists to process. */
1024 	const enum index *next[CTX_STACK_SIZE];
1025 	/** Arguments for stacked tokens. */
1026 	const void *args[CTX_STACK_SIZE];
1027 	enum index curr; /**< Current token index. */
1028 	enum index prev; /**< Index of the last token seen. */
1029 	int next_num; /**< Number of entries in next[]. */
1030 	int args_num; /**< Number of entries in args[]. */
1031 	uint32_t eol:1; /**< EOL has been detected. */
1032 	uint32_t last:1; /**< No more arguments. */
1033 	portid_t port; /**< Current port ID (for completions). */
1034 	uint32_t objdata; /**< Object-specific data. */
1035 	void *object; /**< Address of current object for relative offsets. */
1036 	void *objmask; /**< Object a full mask must be written to. */
1037 };
1038 
1039 /** Token argument. */
1040 struct arg {
1041 	uint32_t hton:1; /**< Use network byte ordering. */
1042 	uint32_t sign:1; /**< Value is signed. */
1043 	uint32_t bounded:1; /**< Value is bounded. */
1044 	uintmax_t min; /**< Minimum value if bounded. */
1045 	uintmax_t max; /**< Maximum value if bounded. */
1046 	uint32_t offset; /**< Relative offset from ctx->object. */
1047 	uint32_t size; /**< Field size. */
1048 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1049 };
1050 
1051 /** Parser token definition. */
1052 struct token {
1053 	/** Type displayed during completion (defaults to "TOKEN"). */
1054 	const char *type;
1055 	/** Help displayed during completion (defaults to token name). */
1056 	const char *help;
1057 	/** Private data used by parser functions. */
1058 	const void *priv;
1059 	/**
1060 	 * Lists of subsequent tokens to push on the stack. Each call to the
1061 	 * parser consumes the last entry of that stack.
1062 	 */
1063 	const enum index *const *next;
1064 	/** Arguments stack for subsequent tokens that need them. */
1065 	const struct arg *const *args;
1066 	/**
1067 	 * Token-processing callback, returns -1 in case of error, the
1068 	 * length of the matched string otherwise. If NULL, attempts to
1069 	 * match the token name.
1070 	 *
1071 	 * If buf is not NULL, the result should be stored in it according
1072 	 * to context. An error is returned if not large enough.
1073 	 */
1074 	int (*call)(struct context *ctx, const struct token *token,
1075 		    const char *str, unsigned int len,
1076 		    void *buf, unsigned int size);
1077 	/**
1078 	 * Callback that provides possible values for this token, used for
1079 	 * completion. Returns -1 in case of error, the number of possible
1080 	 * values otherwise. If NULL, the token name is used.
1081 	 *
1082 	 * If buf is not NULL, entry index ent is written to buf and the
1083 	 * full length of the entry is returned (same behavior as
1084 	 * snprintf()).
1085 	 */
1086 	int (*comp)(struct context *ctx, const struct token *token,
1087 		    unsigned int ent, char *buf, unsigned int size);
1088 	/** Mandatory token name, no default value. */
1089 	const char *name;
1090 };
1091 
1092 /** Static initializer for the next field. */
1093 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1094 
1095 /** Static initializer for a NEXT() entry. */
1096 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1097 
1098 /** Static initializer for the args field. */
1099 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1100 
1101 /** Static initializer for ARGS() to target a field. */
1102 #define ARGS_ENTRY(s, f) \
1103 	(&(const struct arg){ \
1104 		.offset = offsetof(s, f), \
1105 		.size = sizeof(((s *)0)->f), \
1106 	})
1107 
1108 /** Static initializer for ARGS() to target a bit-field. */
1109 #define ARGS_ENTRY_BF(s, f, b) \
1110 	(&(const struct arg){ \
1111 		.size = sizeof(s), \
1112 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1113 	})
1114 
1115 /** Static initializer for ARGS() to target a field with limits. */
1116 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1117 	(&(const struct arg){ \
1118 		.bounded = 1, \
1119 		.min = (i), \
1120 		.max = (a), \
1121 		.offset = offsetof(s, f), \
1122 		.size = sizeof(((s *)0)->f), \
1123 	})
1124 
1125 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1126 #define ARGS_ENTRY_MASK(s, f, m) \
1127 	(&(const struct arg){ \
1128 		.offset = offsetof(s, f), \
1129 		.size = sizeof(((s *)0)->f), \
1130 		.mask = (const void *)(m), \
1131 	})
1132 
1133 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1134 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1135 	(&(const struct arg){ \
1136 		.hton = 1, \
1137 		.offset = offsetof(s, f), \
1138 		.size = sizeof(((s *)0)->f), \
1139 		.mask = (const void *)(m), \
1140 	})
1141 
1142 /** Static initializer for ARGS() to target a pointer. */
1143 #define ARGS_ENTRY_PTR(s, f) \
1144 	(&(const struct arg){ \
1145 		.size = sizeof(*((s *)0)->f), \
1146 	})
1147 
1148 /** Static initializer for ARGS() with arbitrary offset and size. */
1149 #define ARGS_ENTRY_ARB(o, s) \
1150 	(&(const struct arg){ \
1151 		.offset = (o), \
1152 		.size = (s), \
1153 	})
1154 
1155 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1156 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1157 	(&(const struct arg){ \
1158 		.bounded = 1, \
1159 		.min = (i), \
1160 		.max = (a), \
1161 		.offset = (o), \
1162 		.size = (s), \
1163 	})
1164 
1165 /** Same as ARGS_ENTRY() using network byte ordering. */
1166 #define ARGS_ENTRY_HTON(s, f) \
1167 	(&(const struct arg){ \
1168 		.hton = 1, \
1169 		.offset = offsetof(s, f), \
1170 		.size = sizeof(((s *)0)->f), \
1171 	})
1172 
1173 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1174 #define ARG_ENTRY_HTON(s) \
1175 	(&(const struct arg){ \
1176 		.hton = 1, \
1177 		.offset = 0, \
1178 		.size = sizeof(s), \
1179 	})
1180 
1181 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1182 struct buffer {
1183 	enum index command; /**< Flow command. */
1184 	portid_t port; /**< Affected port ID. */
1185 	queueid_t queue; /** Async queue ID. */
1186 	bool postpone; /** Postpone async operation */
1187 	union {
1188 		struct {
1189 			struct rte_flow_port_attr port_attr;
1190 			uint32_t nb_queue;
1191 			struct rte_flow_queue_attr queue_attr;
1192 		} configure; /**< Configuration arguments. */
1193 		struct {
1194 			uint32_t *template_id;
1195 			uint32_t template_id_n;
1196 		} templ_destroy; /**< Template destroy arguments. */
1197 		struct {
1198 			uint32_t id;
1199 			struct rte_flow_template_table_attr attr;
1200 			uint32_t *pat_templ_id;
1201 			uint32_t pat_templ_id_n;
1202 			uint32_t *act_templ_id;
1203 			uint32_t act_templ_id_n;
1204 		} table; /**< Table arguments. */
1205 		struct {
1206 			uint32_t *table_id;
1207 			uint32_t table_id_n;
1208 		} table_destroy; /**< Template destroy arguments. */
1209 		struct {
1210 			uint32_t *action_id;
1211 			uint32_t action_id_n;
1212 		} ia_destroy; /**< Indirect action destroy arguments. */
1213 		struct {
1214 			uint32_t action_id;
1215 			enum rte_flow_query_update_mode qu_mode;
1216 		} ia; /* Indirect action query arguments */
1217 		struct {
1218 			uint32_t table_id;
1219 			uint32_t pat_templ_id;
1220 			uint32_t rule_id;
1221 			uint32_t act_templ_id;
1222 			struct rte_flow_attr attr;
1223 			struct tunnel_ops tunnel_ops;
1224 			uintptr_t user_id;
1225 			struct rte_flow_item *pattern;
1226 			struct rte_flow_action *actions;
1227 			struct rte_flow_action *masks;
1228 			uint32_t pattern_n;
1229 			uint32_t actions_n;
1230 			uint8_t *data;
1231 			enum rte_flow_encap_hash_field field;
1232 			uint8_t encap_hash;
1233 		} vc; /**< Validate/create arguments. */
1234 		struct {
1235 			uint64_t *rule;
1236 			uint64_t rule_n;
1237 			bool is_user_id;
1238 		} destroy; /**< Destroy arguments. */
1239 		struct {
1240 			char file[128];
1241 			bool mode;
1242 			uint64_t rule;
1243 			bool is_user_id;
1244 		} dump; /**< Dump arguments. */
1245 		struct {
1246 			uint64_t rule;
1247 			struct rte_flow_action action;
1248 			bool is_user_id;
1249 		} query; /**< Query arguments. */
1250 		struct {
1251 			uint32_t *group;
1252 			uint32_t group_n;
1253 		} list; /**< List arguments. */
1254 		struct {
1255 			int set;
1256 		} isolate; /**< Isolated mode arguments. */
1257 		struct {
1258 			int destroy;
1259 		} aged; /**< Aged arguments. */
1260 		struct {
1261 			uint32_t policy_id;
1262 		} policy;/**< Policy arguments. */
1263 		struct {
1264 			uint16_t token;
1265 			uintptr_t uintptr;
1266 			char filename[128];
1267 		} flex; /**< Flex arguments*/
1268 	} args; /**< Command arguments. */
1269 };
1270 
1271 /** Private data for pattern items. */
1272 struct parse_item_priv {
1273 	enum rte_flow_item_type type; /**< Item type. */
1274 	uint32_t size; /**< Size of item specification structure. */
1275 };
1276 
1277 #define PRIV_ITEM(t, s) \
1278 	(&(const struct parse_item_priv){ \
1279 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1280 		.size = s, \
1281 	})
1282 
1283 /** Private data for actions. */
1284 struct parse_action_priv {
1285 	enum rte_flow_action_type type; /**< Action type. */
1286 	uint32_t size; /**< Size of action configuration structure. */
1287 };
1288 
1289 #define PRIV_ACTION(t, s) \
1290 	(&(const struct parse_action_priv){ \
1291 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1292 		.size = s, \
1293 	})
1294 
1295 static const enum index next_flex_item[] = {
1296 	FLEX_ITEM_INIT,
1297 	FLEX_ITEM_CREATE,
1298 	FLEX_ITEM_DESTROY,
1299 	ZERO,
1300 };
1301 
1302 static const enum index next_config_attr[] = {
1303 	CONFIG_QUEUES_NUMBER,
1304 	CONFIG_QUEUES_SIZE,
1305 	CONFIG_COUNTERS_NUMBER,
1306 	CONFIG_AGING_OBJECTS_NUMBER,
1307 	CONFIG_METERS_NUMBER,
1308 	CONFIG_CONN_TRACK_NUMBER,
1309 	CONFIG_QUOTAS_NUMBER,
1310 	CONFIG_FLAGS,
1311 	CONFIG_HOST_PORT,
1312 	END,
1313 	ZERO,
1314 };
1315 
1316 static const enum index next_pt_subcmd[] = {
1317 	PATTERN_TEMPLATE_CREATE,
1318 	PATTERN_TEMPLATE_DESTROY,
1319 	ZERO,
1320 };
1321 
1322 static const enum index next_pt_attr[] = {
1323 	PATTERN_TEMPLATE_CREATE_ID,
1324 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1325 	PATTERN_TEMPLATE_INGRESS,
1326 	PATTERN_TEMPLATE_EGRESS,
1327 	PATTERN_TEMPLATE_TRANSFER,
1328 	PATTERN_TEMPLATE_SPEC,
1329 	ZERO,
1330 };
1331 
1332 static const enum index next_pt_destroy_attr[] = {
1333 	PATTERN_TEMPLATE_DESTROY_ID,
1334 	END,
1335 	ZERO,
1336 };
1337 
1338 static const enum index next_at_subcmd[] = {
1339 	ACTIONS_TEMPLATE_CREATE,
1340 	ACTIONS_TEMPLATE_DESTROY,
1341 	ZERO,
1342 };
1343 
1344 static const enum index next_at_attr[] = {
1345 	ACTIONS_TEMPLATE_CREATE_ID,
1346 	ACTIONS_TEMPLATE_INGRESS,
1347 	ACTIONS_TEMPLATE_EGRESS,
1348 	ACTIONS_TEMPLATE_TRANSFER,
1349 	ACTIONS_TEMPLATE_SPEC,
1350 	ZERO,
1351 };
1352 
1353 static const enum index next_at_destroy_attr[] = {
1354 	ACTIONS_TEMPLATE_DESTROY_ID,
1355 	END,
1356 	ZERO,
1357 };
1358 
1359 static const enum index next_group_attr[] = {
1360 	GROUP_INGRESS,
1361 	GROUP_EGRESS,
1362 	GROUP_TRANSFER,
1363 	GROUP_SET_MISS_ACTIONS,
1364 	ZERO,
1365 };
1366 
1367 static const enum index next_table_subcmd[] = {
1368 	TABLE_CREATE,
1369 	TABLE_DESTROY,
1370 	TABLE_RESIZE,
1371 	TABLE_RESIZE_COMPLETE,
1372 	ZERO,
1373 };
1374 
1375 static const enum index next_table_attr[] = {
1376 	TABLE_CREATE_ID,
1377 	TABLE_GROUP,
1378 	TABLE_INSERTION_TYPE,
1379 	TABLE_HASH_FUNC,
1380 	TABLE_PRIORITY,
1381 	TABLE_INGRESS,
1382 	TABLE_EGRESS,
1383 	TABLE_TRANSFER,
1384 	TABLE_TRANSFER_WIRE_ORIG,
1385 	TABLE_TRANSFER_VPORT_ORIG,
1386 	TABLE_RESIZABLE,
1387 	TABLE_RULES_NUMBER,
1388 	TABLE_PATTERN_TEMPLATE,
1389 	TABLE_ACTIONS_TEMPLATE,
1390 	END,
1391 	ZERO,
1392 };
1393 
1394 static const enum index next_table_destroy_attr[] = {
1395 	TABLE_DESTROY_ID,
1396 	END,
1397 	ZERO,
1398 };
1399 
1400 static const enum index next_queue_subcmd[] = {
1401 	QUEUE_CREATE,
1402 	QUEUE_DESTROY,
1403 	QUEUE_FLOW_UPDATE_RESIZED,
1404 	QUEUE_UPDATE,
1405 	QUEUE_AGED,
1406 	QUEUE_INDIRECT_ACTION,
1407 	ZERO,
1408 };
1409 
1410 static const enum index next_queue_destroy_attr[] = {
1411 	QUEUE_DESTROY_ID,
1412 	END,
1413 	ZERO,
1414 };
1415 
1416 static const enum index next_qia_subcmd[] = {
1417 	QUEUE_INDIRECT_ACTION_CREATE,
1418 	QUEUE_INDIRECT_ACTION_UPDATE,
1419 	QUEUE_INDIRECT_ACTION_DESTROY,
1420 	QUEUE_INDIRECT_ACTION_QUERY,
1421 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1422 	ZERO,
1423 };
1424 
1425 static const enum index next_qia_create_attr[] = {
1426 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1427 	QUEUE_INDIRECT_ACTION_INGRESS,
1428 	QUEUE_INDIRECT_ACTION_EGRESS,
1429 	QUEUE_INDIRECT_ACTION_TRANSFER,
1430 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1431 	QUEUE_INDIRECT_ACTION_SPEC,
1432 	QUEUE_INDIRECT_ACTION_LIST,
1433 	ZERO,
1434 };
1435 
1436 static const enum index next_qia_update_attr[] = {
1437 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1438 	QUEUE_INDIRECT_ACTION_SPEC,
1439 	ZERO,
1440 };
1441 
1442 static const enum index next_qia_destroy_attr[] = {
1443 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1444 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1445 	END,
1446 	ZERO,
1447 };
1448 
1449 static const enum index next_qia_query_attr[] = {
1450 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1451 	END,
1452 	ZERO,
1453 };
1454 
1455 static const enum index next_ia_create_attr[] = {
1456 	INDIRECT_ACTION_CREATE_ID,
1457 	INDIRECT_ACTION_INGRESS,
1458 	INDIRECT_ACTION_EGRESS,
1459 	INDIRECT_ACTION_TRANSFER,
1460 	INDIRECT_ACTION_SPEC,
1461 	INDIRECT_ACTION_LIST,
1462 	INDIRECT_ACTION_FLOW_CONF,
1463 	ZERO,
1464 };
1465 
1466 static const enum index next_ia[] = {
1467 	INDIRECT_ACTION_ID2PTR,
1468 	ACTION_NEXT,
1469 	ZERO
1470 };
1471 
1472 static const enum index next_ial[] = {
1473 	ACTION_INDIRECT_LIST_HANDLE,
1474 	ACTION_INDIRECT_LIST_CONF,
1475 	ACTION_NEXT,
1476 	ZERO
1477 };
1478 
1479 static const enum index next_qia_qu_attr[] = {
1480 	QUEUE_INDIRECT_ACTION_QU_MODE,
1481 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1482 	INDIRECT_ACTION_SPEC,
1483 	ZERO
1484 };
1485 
1486 static const enum index next_ia_qu_attr[] = {
1487 	INDIRECT_ACTION_QU_MODE,
1488 	INDIRECT_ACTION_SPEC,
1489 	ZERO
1490 };
1491 
1492 static const enum index next_dump_subcmd[] = {
1493 	DUMP_ALL,
1494 	DUMP_ONE,
1495 	DUMP_IS_USER_ID,
1496 	ZERO,
1497 };
1498 
1499 static const enum index next_ia_subcmd[] = {
1500 	INDIRECT_ACTION_CREATE,
1501 	INDIRECT_ACTION_UPDATE,
1502 	INDIRECT_ACTION_DESTROY,
1503 	INDIRECT_ACTION_QUERY,
1504 	INDIRECT_ACTION_QUERY_UPDATE,
1505 	ZERO,
1506 };
1507 
1508 static const enum index next_vc_attr[] = {
1509 	VC_GROUP,
1510 	VC_PRIORITY,
1511 	VC_INGRESS,
1512 	VC_EGRESS,
1513 	VC_TRANSFER,
1514 	VC_TUNNEL_SET,
1515 	VC_TUNNEL_MATCH,
1516 	VC_USER_ID,
1517 	ITEM_PATTERN,
1518 	ZERO,
1519 };
1520 
1521 static const enum index next_destroy_attr[] = {
1522 	DESTROY_RULE,
1523 	DESTROY_IS_USER_ID,
1524 	END,
1525 	ZERO,
1526 };
1527 
1528 static const enum index next_dump_attr[] = {
1529 	COMMON_FILE_PATH,
1530 	END,
1531 	ZERO,
1532 };
1533 
1534 static const enum index next_query_attr[] = {
1535 	QUERY_IS_USER_ID,
1536 	END,
1537 	ZERO,
1538 };
1539 
1540 static const enum index next_list_attr[] = {
1541 	LIST_GROUP,
1542 	END,
1543 	ZERO,
1544 };
1545 
1546 static const enum index next_aged_attr[] = {
1547 	AGED_DESTROY,
1548 	END,
1549 	ZERO,
1550 };
1551 
1552 static const enum index next_ia_destroy_attr[] = {
1553 	INDIRECT_ACTION_DESTROY_ID,
1554 	END,
1555 	ZERO,
1556 };
1557 
1558 static const enum index next_async_insert_subcmd[] = {
1559 	QUEUE_PATTERN_TEMPLATE,
1560 	QUEUE_RULE_ID,
1561 	ZERO,
1562 };
1563 
1564 static const enum index item_param[] = {
1565 	ITEM_PARAM_IS,
1566 	ITEM_PARAM_SPEC,
1567 	ITEM_PARAM_LAST,
1568 	ITEM_PARAM_MASK,
1569 	ITEM_PARAM_PREFIX,
1570 	ZERO,
1571 };
1572 
1573 static const enum index next_item[] = {
1574 	ITEM_END,
1575 	ITEM_VOID,
1576 	ITEM_INVERT,
1577 	ITEM_ANY,
1578 	ITEM_PORT_ID,
1579 	ITEM_MARK,
1580 	ITEM_RAW,
1581 	ITEM_ETH,
1582 	ITEM_VLAN,
1583 	ITEM_IPV4,
1584 	ITEM_IPV6,
1585 	ITEM_ICMP,
1586 	ITEM_UDP,
1587 	ITEM_TCP,
1588 	ITEM_SCTP,
1589 	ITEM_VXLAN,
1590 	ITEM_E_TAG,
1591 	ITEM_NVGRE,
1592 	ITEM_MPLS,
1593 	ITEM_GRE,
1594 	ITEM_FUZZY,
1595 	ITEM_GTP,
1596 	ITEM_GTPC,
1597 	ITEM_GTPU,
1598 	ITEM_GENEVE,
1599 	ITEM_VXLAN_GPE,
1600 	ITEM_ARP_ETH_IPV4,
1601 	ITEM_IPV6_EXT,
1602 	ITEM_IPV6_FRAG_EXT,
1603 	ITEM_IPV6_ROUTING_EXT,
1604 	ITEM_ICMP6,
1605 	ITEM_ICMP6_ECHO_REQUEST,
1606 	ITEM_ICMP6_ECHO_REPLY,
1607 	ITEM_ICMP6_ND_NS,
1608 	ITEM_ICMP6_ND_NA,
1609 	ITEM_ICMP6_ND_OPT,
1610 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1611 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1612 	ITEM_META,
1613 	ITEM_RANDOM,
1614 	ITEM_GRE_KEY,
1615 	ITEM_GRE_OPTION,
1616 	ITEM_GTP_PSC,
1617 	ITEM_PPPOES,
1618 	ITEM_PPPOED,
1619 	ITEM_PPPOE_PROTO_ID,
1620 	ITEM_HIGIG2,
1621 	ITEM_TAG,
1622 	ITEM_L2TPV3OIP,
1623 	ITEM_ESP,
1624 	ITEM_AH,
1625 	ITEM_PFCP,
1626 	ITEM_ECPRI,
1627 	ITEM_GENEVE_OPT,
1628 	ITEM_INTEGRITY,
1629 	ITEM_CONNTRACK,
1630 	ITEM_PORT_REPRESENTOR,
1631 	ITEM_REPRESENTED_PORT,
1632 	ITEM_FLEX,
1633 	ITEM_L2TPV2,
1634 	ITEM_PPP,
1635 	ITEM_METER,
1636 	ITEM_QUOTA,
1637 	ITEM_AGGR_AFFINITY,
1638 	ITEM_TX_QUEUE,
1639 	ITEM_IB_BTH,
1640 	ITEM_PTYPE,
1641 	ITEM_NSH,
1642 	ITEM_COMPARE,
1643 	END_SET,
1644 	ZERO,
1645 };
1646 
1647 static const enum index item_fuzzy[] = {
1648 	ITEM_FUZZY_THRESH,
1649 	ITEM_NEXT,
1650 	ZERO,
1651 };
1652 
1653 static const enum index item_any[] = {
1654 	ITEM_ANY_NUM,
1655 	ITEM_NEXT,
1656 	ZERO,
1657 };
1658 
1659 static const enum index item_port_id[] = {
1660 	ITEM_PORT_ID_ID,
1661 	ITEM_NEXT,
1662 	ZERO,
1663 };
1664 
1665 static const enum index item_mark[] = {
1666 	ITEM_MARK_ID,
1667 	ITEM_NEXT,
1668 	ZERO,
1669 };
1670 
1671 static const enum index item_raw[] = {
1672 	ITEM_RAW_RELATIVE,
1673 	ITEM_RAW_SEARCH,
1674 	ITEM_RAW_OFFSET,
1675 	ITEM_RAW_LIMIT,
1676 	ITEM_RAW_PATTERN,
1677 	ITEM_RAW_PATTERN_HEX,
1678 	ITEM_NEXT,
1679 	ZERO,
1680 };
1681 
1682 static const enum index item_eth[] = {
1683 	ITEM_ETH_DST,
1684 	ITEM_ETH_SRC,
1685 	ITEM_ETH_TYPE,
1686 	ITEM_ETH_HAS_VLAN,
1687 	ITEM_NEXT,
1688 	ZERO,
1689 };
1690 
1691 static const enum index item_vlan[] = {
1692 	ITEM_VLAN_TCI,
1693 	ITEM_VLAN_PCP,
1694 	ITEM_VLAN_DEI,
1695 	ITEM_VLAN_VID,
1696 	ITEM_VLAN_INNER_TYPE,
1697 	ITEM_VLAN_HAS_MORE_VLAN,
1698 	ITEM_NEXT,
1699 	ZERO,
1700 };
1701 
1702 static const enum index item_ipv4[] = {
1703 	ITEM_IPV4_VER_IHL,
1704 	ITEM_IPV4_TOS,
1705 	ITEM_IPV4_LENGTH,
1706 	ITEM_IPV4_ID,
1707 	ITEM_IPV4_FRAGMENT_OFFSET,
1708 	ITEM_IPV4_TTL,
1709 	ITEM_IPV4_PROTO,
1710 	ITEM_IPV4_SRC,
1711 	ITEM_IPV4_DST,
1712 	ITEM_NEXT,
1713 	ZERO,
1714 };
1715 
1716 static const enum index item_ipv6[] = {
1717 	ITEM_IPV6_TC,
1718 	ITEM_IPV6_FLOW,
1719 	ITEM_IPV6_LEN,
1720 	ITEM_IPV6_PROTO,
1721 	ITEM_IPV6_HOP,
1722 	ITEM_IPV6_SRC,
1723 	ITEM_IPV6_DST,
1724 	ITEM_IPV6_HAS_FRAG_EXT,
1725 	ITEM_IPV6_ROUTING_EXT,
1726 	ITEM_NEXT,
1727 	ZERO,
1728 };
1729 
1730 static const enum index item_ipv6_routing_ext[] = {
1731 	ITEM_IPV6_ROUTING_EXT_TYPE,
1732 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1733 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1734 	ITEM_NEXT,
1735 	ZERO,
1736 };
1737 
1738 static const enum index item_icmp[] = {
1739 	ITEM_ICMP_TYPE,
1740 	ITEM_ICMP_CODE,
1741 	ITEM_ICMP_IDENT,
1742 	ITEM_ICMP_SEQ,
1743 	ITEM_NEXT,
1744 	ZERO,
1745 };
1746 
1747 static const enum index item_udp[] = {
1748 	ITEM_UDP_SRC,
1749 	ITEM_UDP_DST,
1750 	ITEM_NEXT,
1751 	ZERO,
1752 };
1753 
1754 static const enum index item_tcp[] = {
1755 	ITEM_TCP_SRC,
1756 	ITEM_TCP_DST,
1757 	ITEM_TCP_FLAGS,
1758 	ITEM_NEXT,
1759 	ZERO,
1760 };
1761 
1762 static const enum index item_sctp[] = {
1763 	ITEM_SCTP_SRC,
1764 	ITEM_SCTP_DST,
1765 	ITEM_SCTP_TAG,
1766 	ITEM_SCTP_CKSUM,
1767 	ITEM_NEXT,
1768 	ZERO,
1769 };
1770 
1771 static const enum index item_vxlan[] = {
1772 	ITEM_VXLAN_VNI,
1773 	ITEM_VXLAN_LAST_RSVD,
1774 	ITEM_NEXT,
1775 	ZERO,
1776 };
1777 
1778 static const enum index item_e_tag[] = {
1779 	ITEM_E_TAG_GRP_ECID_B,
1780 	ITEM_NEXT,
1781 	ZERO,
1782 };
1783 
1784 static const enum index item_nvgre[] = {
1785 	ITEM_NVGRE_TNI,
1786 	ITEM_NEXT,
1787 	ZERO,
1788 };
1789 
1790 static const enum index item_mpls[] = {
1791 	ITEM_MPLS_LABEL,
1792 	ITEM_MPLS_TC,
1793 	ITEM_MPLS_S,
1794 	ITEM_MPLS_TTL,
1795 	ITEM_NEXT,
1796 	ZERO,
1797 };
1798 
1799 static const enum index item_gre[] = {
1800 	ITEM_GRE_PROTO,
1801 	ITEM_GRE_C_RSVD0_VER,
1802 	ITEM_GRE_C_BIT,
1803 	ITEM_GRE_K_BIT,
1804 	ITEM_GRE_S_BIT,
1805 	ITEM_NEXT,
1806 	ZERO,
1807 };
1808 
1809 static const enum index item_gre_key[] = {
1810 	ITEM_GRE_KEY_VALUE,
1811 	ITEM_NEXT,
1812 	ZERO,
1813 };
1814 
1815 static const enum index item_gre_option[] = {
1816 	ITEM_GRE_OPTION_CHECKSUM,
1817 	ITEM_GRE_OPTION_KEY,
1818 	ITEM_GRE_OPTION_SEQUENCE,
1819 	ITEM_NEXT,
1820 	ZERO,
1821 };
1822 
1823 static const enum index item_gtp[] = {
1824 	ITEM_GTP_FLAGS,
1825 	ITEM_GTP_MSG_TYPE,
1826 	ITEM_GTP_TEID,
1827 	ITEM_NEXT,
1828 	ZERO,
1829 };
1830 
1831 static const enum index item_geneve[] = {
1832 	ITEM_GENEVE_VNI,
1833 	ITEM_GENEVE_PROTO,
1834 	ITEM_GENEVE_OPTLEN,
1835 	ITEM_NEXT,
1836 	ZERO,
1837 };
1838 
1839 static const enum index item_vxlan_gpe[] = {
1840 	ITEM_VXLAN_GPE_VNI,
1841 	ITEM_VXLAN_GPE_PROTO,
1842 	ITEM_NEXT,
1843 	ZERO,
1844 };
1845 
1846 static const enum index item_arp_eth_ipv4[] = {
1847 	ITEM_ARP_ETH_IPV4_SHA,
1848 	ITEM_ARP_ETH_IPV4_SPA,
1849 	ITEM_ARP_ETH_IPV4_THA,
1850 	ITEM_ARP_ETH_IPV4_TPA,
1851 	ITEM_NEXT,
1852 	ZERO,
1853 };
1854 
1855 static const enum index item_ipv6_ext[] = {
1856 	ITEM_IPV6_EXT_NEXT_HDR,
1857 	ITEM_NEXT,
1858 	ZERO,
1859 };
1860 
1861 static const enum index item_ipv6_frag_ext[] = {
1862 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1863 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1864 	ITEM_IPV6_FRAG_EXT_ID,
1865 	ITEM_NEXT,
1866 	ZERO,
1867 };
1868 
1869 static const enum index item_icmp6[] = {
1870 	ITEM_ICMP6_TYPE,
1871 	ITEM_ICMP6_CODE,
1872 	ITEM_NEXT,
1873 	ZERO,
1874 };
1875 
1876 static const enum index item_icmp6_echo_request[] = {
1877 	ITEM_ICMP6_ECHO_REQUEST_ID,
1878 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1879 	ITEM_NEXT,
1880 	ZERO,
1881 };
1882 
1883 static const enum index item_icmp6_echo_reply[] = {
1884 	ITEM_ICMP6_ECHO_REPLY_ID,
1885 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1886 	ITEM_NEXT,
1887 	ZERO,
1888 };
1889 
1890 static const enum index item_icmp6_nd_ns[] = {
1891 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1892 	ITEM_NEXT,
1893 	ZERO,
1894 };
1895 
1896 static const enum index item_icmp6_nd_na[] = {
1897 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1898 	ITEM_NEXT,
1899 	ZERO,
1900 };
1901 
1902 static const enum index item_icmp6_nd_opt[] = {
1903 	ITEM_ICMP6_ND_OPT_TYPE,
1904 	ITEM_NEXT,
1905 	ZERO,
1906 };
1907 
1908 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1909 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1910 	ITEM_NEXT,
1911 	ZERO,
1912 };
1913 
1914 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1915 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1916 	ITEM_NEXT,
1917 	ZERO,
1918 };
1919 
1920 static const enum index item_meta[] = {
1921 	ITEM_META_DATA,
1922 	ITEM_NEXT,
1923 	ZERO,
1924 };
1925 
1926 static const enum index item_random[] = {
1927 	ITEM_RANDOM_VALUE,
1928 	ITEM_NEXT,
1929 	ZERO,
1930 };
1931 
1932 static const enum index item_gtp_psc[] = {
1933 	ITEM_GTP_PSC_QFI,
1934 	ITEM_GTP_PSC_PDU_T,
1935 	ITEM_NEXT,
1936 	ZERO,
1937 };
1938 
1939 static const enum index item_pppoed[] = {
1940 	ITEM_PPPOE_SEID,
1941 	ITEM_NEXT,
1942 	ZERO,
1943 };
1944 
1945 static const enum index item_pppoes[] = {
1946 	ITEM_PPPOE_SEID,
1947 	ITEM_NEXT,
1948 	ZERO,
1949 };
1950 
1951 static const enum index item_pppoe_proto_id[] = {
1952 	ITEM_NEXT,
1953 	ZERO,
1954 };
1955 
1956 static const enum index item_higig2[] = {
1957 	ITEM_HIGIG2_CLASSIFICATION,
1958 	ITEM_HIGIG2_VID,
1959 	ITEM_NEXT,
1960 	ZERO,
1961 };
1962 
1963 static const enum index item_esp[] = {
1964 	ITEM_ESP_SPI,
1965 	ITEM_NEXT,
1966 	ZERO,
1967 };
1968 
1969 static const enum index item_ah[] = {
1970 	ITEM_AH_SPI,
1971 	ITEM_NEXT,
1972 	ZERO,
1973 };
1974 
1975 static const enum index item_pfcp[] = {
1976 	ITEM_PFCP_S_FIELD,
1977 	ITEM_PFCP_SEID,
1978 	ITEM_NEXT,
1979 	ZERO,
1980 };
1981 
1982 static const enum index next_set_raw[] = {
1983 	SET_RAW_INDEX,
1984 	ITEM_ETH,
1985 	ZERO,
1986 };
1987 
1988 static const enum index item_tag[] = {
1989 	ITEM_TAG_DATA,
1990 	ITEM_TAG_INDEX,
1991 	ITEM_NEXT,
1992 	ZERO,
1993 };
1994 
1995 static const enum index item_l2tpv3oip[] = {
1996 	ITEM_L2TPV3OIP_SESSION_ID,
1997 	ITEM_NEXT,
1998 	ZERO,
1999 };
2000 
2001 static const enum index item_ecpri[] = {
2002 	ITEM_ECPRI_COMMON,
2003 	ITEM_NEXT,
2004 	ZERO,
2005 };
2006 
2007 static const enum index item_ecpri_common[] = {
2008 	ITEM_ECPRI_COMMON_TYPE,
2009 	ZERO,
2010 };
2011 
2012 static const enum index item_ecpri_common_type[] = {
2013 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2014 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2015 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2016 	ZERO,
2017 };
2018 
2019 static const enum index item_geneve_opt[] = {
2020 	ITEM_GENEVE_OPT_CLASS,
2021 	ITEM_GENEVE_OPT_TYPE,
2022 	ITEM_GENEVE_OPT_LENGTH,
2023 	ITEM_GENEVE_OPT_DATA,
2024 	ITEM_NEXT,
2025 	ZERO,
2026 };
2027 
2028 static const enum index item_integrity[] = {
2029 	ITEM_INTEGRITY_LEVEL,
2030 	ITEM_INTEGRITY_VALUE,
2031 	ZERO,
2032 };
2033 
2034 static const enum index item_integrity_lv[] = {
2035 	ITEM_INTEGRITY_LEVEL,
2036 	ITEM_INTEGRITY_VALUE,
2037 	ITEM_NEXT,
2038 	ZERO,
2039 };
2040 
2041 static const enum index item_port_representor[] = {
2042 	ITEM_PORT_REPRESENTOR_PORT_ID,
2043 	ITEM_NEXT,
2044 	ZERO,
2045 };
2046 
2047 static const enum index item_represented_port[] = {
2048 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2049 	ITEM_NEXT,
2050 	ZERO,
2051 };
2052 
2053 static const enum index item_flex[] = {
2054 	ITEM_FLEX_PATTERN_HANDLE,
2055 	ITEM_FLEX_ITEM_HANDLE,
2056 	ITEM_NEXT,
2057 	ZERO,
2058 };
2059 
2060 static const enum index item_l2tpv2[] = {
2061 	ITEM_L2TPV2_TYPE,
2062 	ITEM_NEXT,
2063 	ZERO,
2064 };
2065 
2066 static const enum index item_l2tpv2_type[] = {
2067 	ITEM_L2TPV2_TYPE_DATA,
2068 	ITEM_L2TPV2_TYPE_DATA_L,
2069 	ITEM_L2TPV2_TYPE_DATA_S,
2070 	ITEM_L2TPV2_TYPE_DATA_O,
2071 	ITEM_L2TPV2_TYPE_DATA_L_S,
2072 	ITEM_L2TPV2_TYPE_CTRL,
2073 	ZERO,
2074 };
2075 
2076 static const enum index item_l2tpv2_type_data[] = {
2077 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2078 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2079 	ITEM_NEXT,
2080 	ZERO,
2081 };
2082 
2083 static const enum index item_l2tpv2_type_data_l[] = {
2084 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2085 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2086 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2087 	ITEM_NEXT,
2088 	ZERO,
2089 };
2090 
2091 static const enum index item_l2tpv2_type_data_s[] = {
2092 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2093 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2094 	ITEM_L2TPV2_MSG_DATA_S_NS,
2095 	ITEM_L2TPV2_MSG_DATA_S_NR,
2096 	ITEM_NEXT,
2097 	ZERO,
2098 };
2099 
2100 static const enum index item_l2tpv2_type_data_o[] = {
2101 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2102 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2103 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2104 	ITEM_NEXT,
2105 	ZERO,
2106 };
2107 
2108 static const enum index item_l2tpv2_type_data_l_s[] = {
2109 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2110 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2111 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2112 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2113 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2114 	ITEM_NEXT,
2115 	ZERO,
2116 };
2117 
2118 static const enum index item_l2tpv2_type_ctrl[] = {
2119 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2120 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2121 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2122 	ITEM_L2TPV2_MSG_CTRL_NS,
2123 	ITEM_L2TPV2_MSG_CTRL_NR,
2124 	ITEM_NEXT,
2125 	ZERO,
2126 };
2127 
2128 static const enum index item_ppp[] = {
2129 	ITEM_PPP_ADDR,
2130 	ITEM_PPP_CTRL,
2131 	ITEM_PPP_PROTO_ID,
2132 	ITEM_NEXT,
2133 	ZERO,
2134 };
2135 
2136 static const enum index item_meter[] = {
2137 	ITEM_METER_COLOR,
2138 	ITEM_NEXT,
2139 	ZERO,
2140 };
2141 
2142 static const enum index item_quota[] = {
2143 	ITEM_QUOTA_STATE,
2144 	ITEM_NEXT,
2145 	ZERO,
2146 };
2147 
2148 static const enum index item_aggr_affinity[] = {
2149 	ITEM_AGGR_AFFINITY_VALUE,
2150 	ITEM_NEXT,
2151 	ZERO,
2152 };
2153 
2154 static const enum index item_tx_queue[] = {
2155 	ITEM_TX_QUEUE_VALUE,
2156 	ITEM_NEXT,
2157 	ZERO,
2158 };
2159 
2160 static const enum index item_ib_bth[] = {
2161 	ITEM_IB_BTH_OPCODE,
2162 	ITEM_IB_BTH_PKEY,
2163 	ITEM_IB_BTH_DST_QPN,
2164 	ITEM_IB_BTH_PSN,
2165 	ITEM_NEXT,
2166 	ZERO,
2167 };
2168 
2169 static const enum index item_ptype[] = {
2170 	ITEM_PTYPE_VALUE,
2171 	ITEM_NEXT,
2172 	ZERO,
2173 };
2174 
2175 static const enum index item_nsh[] = {
2176 	ITEM_NEXT,
2177 	ZERO,
2178 };
2179 
2180 static const enum index item_compare_field[] = {
2181 	ITEM_COMPARE_OP,
2182 	ITEM_COMPARE_FIELD_A_TYPE,
2183 	ITEM_COMPARE_FIELD_B_TYPE,
2184 	ITEM_NEXT,
2185 	ZERO,
2186 };
2187 
2188 static const enum index compare_field_a[] = {
2189 	ITEM_COMPARE_FIELD_A_TYPE,
2190 	ITEM_COMPARE_FIELD_A_LEVEL,
2191 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2192 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2193 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2194 	ITEM_COMPARE_FIELD_A_OFFSET,
2195 	ITEM_COMPARE_FIELD_B_TYPE,
2196 	ZERO,
2197 };
2198 
2199 static const enum index compare_field_b[] = {
2200 	ITEM_COMPARE_FIELD_B_TYPE,
2201 	ITEM_COMPARE_FIELD_B_LEVEL,
2202 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2203 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2204 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2205 	ITEM_COMPARE_FIELD_B_OFFSET,
2206 	ITEM_COMPARE_FIELD_B_VALUE,
2207 	ITEM_COMPARE_FIELD_B_POINTER,
2208 	ITEM_COMPARE_FIELD_WIDTH,
2209 	ZERO,
2210 };
2211 
2212 static const enum index next_action[] = {
2213 	ACTION_END,
2214 	ACTION_VOID,
2215 	ACTION_PASSTHRU,
2216 	ACTION_SKIP_CMAN,
2217 	ACTION_JUMP,
2218 	ACTION_MARK,
2219 	ACTION_FLAG,
2220 	ACTION_QUEUE,
2221 	ACTION_DROP,
2222 	ACTION_COUNT,
2223 	ACTION_RSS,
2224 	ACTION_PF,
2225 	ACTION_VF,
2226 	ACTION_PORT_ID,
2227 	ACTION_METER,
2228 	ACTION_METER_COLOR,
2229 	ACTION_METER_MARK,
2230 	ACTION_OF_DEC_NW_TTL,
2231 	ACTION_OF_POP_VLAN,
2232 	ACTION_OF_PUSH_VLAN,
2233 	ACTION_OF_SET_VLAN_VID,
2234 	ACTION_OF_SET_VLAN_PCP,
2235 	ACTION_OF_POP_MPLS,
2236 	ACTION_OF_PUSH_MPLS,
2237 	ACTION_VXLAN_ENCAP,
2238 	ACTION_VXLAN_DECAP,
2239 	ACTION_NVGRE_ENCAP,
2240 	ACTION_NVGRE_DECAP,
2241 	ACTION_L2_ENCAP,
2242 	ACTION_L2_DECAP,
2243 	ACTION_MPLSOGRE_ENCAP,
2244 	ACTION_MPLSOGRE_DECAP,
2245 	ACTION_MPLSOUDP_ENCAP,
2246 	ACTION_MPLSOUDP_DECAP,
2247 	ACTION_SET_IPV4_SRC,
2248 	ACTION_SET_IPV4_DST,
2249 	ACTION_SET_IPV6_SRC,
2250 	ACTION_SET_IPV6_DST,
2251 	ACTION_SET_TP_SRC,
2252 	ACTION_SET_TP_DST,
2253 	ACTION_MAC_SWAP,
2254 	ACTION_DEC_TTL,
2255 	ACTION_SET_TTL,
2256 	ACTION_SET_MAC_SRC,
2257 	ACTION_SET_MAC_DST,
2258 	ACTION_INC_TCP_SEQ,
2259 	ACTION_DEC_TCP_SEQ,
2260 	ACTION_INC_TCP_ACK,
2261 	ACTION_DEC_TCP_ACK,
2262 	ACTION_RAW_ENCAP,
2263 	ACTION_RAW_DECAP,
2264 	ACTION_SET_TAG,
2265 	ACTION_SET_META,
2266 	ACTION_SET_IPV4_DSCP,
2267 	ACTION_SET_IPV6_DSCP,
2268 	ACTION_AGE,
2269 	ACTION_AGE_UPDATE,
2270 	ACTION_SAMPLE,
2271 	ACTION_INDIRECT,
2272 	ACTION_INDIRECT_LIST,
2273 	ACTION_SHARED_INDIRECT,
2274 	ACTION_MODIFY_FIELD,
2275 	ACTION_CONNTRACK,
2276 	ACTION_CONNTRACK_UPDATE,
2277 	ACTION_PORT_REPRESENTOR,
2278 	ACTION_REPRESENTED_PORT,
2279 	ACTION_SEND_TO_KERNEL,
2280 	ACTION_QUOTA_CREATE,
2281 	ACTION_QUOTA_QU,
2282 	ACTION_IPV6_EXT_REMOVE,
2283 	ACTION_IPV6_EXT_PUSH,
2284 	ACTION_NAT64,
2285 	ZERO,
2286 };
2287 
2288 static const enum index action_quota_create[] = {
2289 	ACTION_QUOTA_CREATE_LIMIT,
2290 	ACTION_QUOTA_CREATE_MODE,
2291 	ACTION_NEXT,
2292 	ZERO
2293 };
2294 
2295 static const enum index action_quota_update[] = {
2296 	ACTION_QUOTA_QU_LIMIT,
2297 	ACTION_QUOTA_QU_UPDATE_OP,
2298 	ACTION_NEXT,
2299 	ZERO
2300 };
2301 
2302 static const enum index action_mark[] = {
2303 	ACTION_MARK_ID,
2304 	ACTION_NEXT,
2305 	ZERO,
2306 };
2307 
2308 static const enum index action_queue[] = {
2309 	ACTION_QUEUE_INDEX,
2310 	ACTION_NEXT,
2311 	ZERO,
2312 };
2313 
2314 static const enum index action_count[] = {
2315 	ACTION_COUNT_ID,
2316 	ACTION_NEXT,
2317 	ZERO,
2318 };
2319 
2320 static const enum index action_rss[] = {
2321 	ACTION_RSS_FUNC,
2322 	ACTION_RSS_LEVEL,
2323 	ACTION_RSS_TYPES,
2324 	ACTION_RSS_KEY,
2325 	ACTION_RSS_KEY_LEN,
2326 	ACTION_RSS_QUEUES,
2327 	ACTION_NEXT,
2328 	ZERO,
2329 };
2330 
2331 static const enum index action_vf[] = {
2332 	ACTION_VF_ORIGINAL,
2333 	ACTION_VF_ID,
2334 	ACTION_NEXT,
2335 	ZERO,
2336 };
2337 
2338 static const enum index action_port_id[] = {
2339 	ACTION_PORT_ID_ORIGINAL,
2340 	ACTION_PORT_ID_ID,
2341 	ACTION_NEXT,
2342 	ZERO,
2343 };
2344 
2345 static const enum index action_meter[] = {
2346 	ACTION_METER_ID,
2347 	ACTION_NEXT,
2348 	ZERO,
2349 };
2350 
2351 static const enum index action_meter_color[] = {
2352 	ACTION_METER_COLOR_TYPE,
2353 	ACTION_NEXT,
2354 	ZERO,
2355 };
2356 
2357 static const enum index action_meter_mark[] = {
2358 	ACTION_METER_PROFILE,
2359 	ACTION_METER_POLICY,
2360 	ACTION_METER_COLOR_MODE,
2361 	ACTION_METER_STATE,
2362 	ACTION_NEXT,
2363 	ZERO,
2364 };
2365 
2366 static const enum index action_of_push_vlan[] = {
2367 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2368 	ACTION_NEXT,
2369 	ZERO,
2370 };
2371 
2372 static const enum index action_of_set_vlan_vid[] = {
2373 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2374 	ACTION_NEXT,
2375 	ZERO,
2376 };
2377 
2378 static const enum index action_of_set_vlan_pcp[] = {
2379 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2380 	ACTION_NEXT,
2381 	ZERO,
2382 };
2383 
2384 static const enum index action_of_pop_mpls[] = {
2385 	ACTION_OF_POP_MPLS_ETHERTYPE,
2386 	ACTION_NEXT,
2387 	ZERO,
2388 };
2389 
2390 static const enum index action_of_push_mpls[] = {
2391 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2392 	ACTION_NEXT,
2393 	ZERO,
2394 };
2395 
2396 static const enum index action_set_ipv4_src[] = {
2397 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2398 	ACTION_NEXT,
2399 	ZERO,
2400 };
2401 
2402 static const enum index action_set_mac_src[] = {
2403 	ACTION_SET_MAC_SRC_MAC_SRC,
2404 	ACTION_NEXT,
2405 	ZERO,
2406 };
2407 
2408 static const enum index action_set_ipv4_dst[] = {
2409 	ACTION_SET_IPV4_DST_IPV4_DST,
2410 	ACTION_NEXT,
2411 	ZERO,
2412 };
2413 
2414 static const enum index action_set_ipv6_src[] = {
2415 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2416 	ACTION_NEXT,
2417 	ZERO,
2418 };
2419 
2420 static const enum index action_set_ipv6_dst[] = {
2421 	ACTION_SET_IPV6_DST_IPV6_DST,
2422 	ACTION_NEXT,
2423 	ZERO,
2424 };
2425 
2426 static const enum index action_set_tp_src[] = {
2427 	ACTION_SET_TP_SRC_TP_SRC,
2428 	ACTION_NEXT,
2429 	ZERO,
2430 };
2431 
2432 static const enum index action_set_tp_dst[] = {
2433 	ACTION_SET_TP_DST_TP_DST,
2434 	ACTION_NEXT,
2435 	ZERO,
2436 };
2437 
2438 static const enum index action_set_ttl[] = {
2439 	ACTION_SET_TTL_TTL,
2440 	ACTION_NEXT,
2441 	ZERO,
2442 };
2443 
2444 static const enum index action_jump[] = {
2445 	ACTION_JUMP_GROUP,
2446 	ACTION_NEXT,
2447 	ZERO,
2448 };
2449 
2450 static const enum index action_set_mac_dst[] = {
2451 	ACTION_SET_MAC_DST_MAC_DST,
2452 	ACTION_NEXT,
2453 	ZERO,
2454 };
2455 
2456 static const enum index action_inc_tcp_seq[] = {
2457 	ACTION_INC_TCP_SEQ_VALUE,
2458 	ACTION_NEXT,
2459 	ZERO,
2460 };
2461 
2462 static const enum index action_dec_tcp_seq[] = {
2463 	ACTION_DEC_TCP_SEQ_VALUE,
2464 	ACTION_NEXT,
2465 	ZERO,
2466 };
2467 
2468 static const enum index action_inc_tcp_ack[] = {
2469 	ACTION_INC_TCP_ACK_VALUE,
2470 	ACTION_NEXT,
2471 	ZERO,
2472 };
2473 
2474 static const enum index action_dec_tcp_ack[] = {
2475 	ACTION_DEC_TCP_ACK_VALUE,
2476 	ACTION_NEXT,
2477 	ZERO,
2478 };
2479 
2480 static const enum index action_raw_encap[] = {
2481 	ACTION_RAW_ENCAP_SIZE,
2482 	ACTION_RAW_ENCAP_INDEX,
2483 	ACTION_NEXT,
2484 	ZERO,
2485 };
2486 
2487 static const enum index action_raw_decap[] = {
2488 	ACTION_RAW_DECAP_INDEX,
2489 	ACTION_NEXT,
2490 	ZERO,
2491 };
2492 
2493 static const enum index action_ipv6_ext_remove[] = {
2494 	ACTION_IPV6_EXT_REMOVE_INDEX,
2495 	ACTION_NEXT,
2496 	ZERO,
2497 };
2498 
2499 static const enum index action_ipv6_ext_push[] = {
2500 	ACTION_IPV6_EXT_PUSH_INDEX,
2501 	ACTION_NEXT,
2502 	ZERO,
2503 };
2504 
2505 static const enum index action_set_tag[] = {
2506 	ACTION_SET_TAG_DATA,
2507 	ACTION_SET_TAG_INDEX,
2508 	ACTION_SET_TAG_MASK,
2509 	ACTION_NEXT,
2510 	ZERO,
2511 };
2512 
2513 static const enum index action_set_meta[] = {
2514 	ACTION_SET_META_DATA,
2515 	ACTION_SET_META_MASK,
2516 	ACTION_NEXT,
2517 	ZERO,
2518 };
2519 
2520 static const enum index action_set_ipv4_dscp[] = {
2521 	ACTION_SET_IPV4_DSCP_VALUE,
2522 	ACTION_NEXT,
2523 	ZERO,
2524 };
2525 
2526 static const enum index action_set_ipv6_dscp[] = {
2527 	ACTION_SET_IPV6_DSCP_VALUE,
2528 	ACTION_NEXT,
2529 	ZERO,
2530 };
2531 
2532 static const enum index action_age[] = {
2533 	ACTION_AGE,
2534 	ACTION_AGE_TIMEOUT,
2535 	ACTION_NEXT,
2536 	ZERO,
2537 };
2538 
2539 static const enum index action_age_update[] = {
2540 	ACTION_AGE_UPDATE,
2541 	ACTION_AGE_UPDATE_TIMEOUT,
2542 	ACTION_AGE_UPDATE_TOUCH,
2543 	ACTION_NEXT,
2544 	ZERO,
2545 };
2546 
2547 static const enum index action_sample[] = {
2548 	ACTION_SAMPLE,
2549 	ACTION_SAMPLE_RATIO,
2550 	ACTION_SAMPLE_INDEX,
2551 	ACTION_NEXT,
2552 	ZERO,
2553 };
2554 
2555 static const enum index next_action_sample[] = {
2556 	ACTION_QUEUE,
2557 	ACTION_RSS,
2558 	ACTION_MARK,
2559 	ACTION_COUNT,
2560 	ACTION_PORT_ID,
2561 	ACTION_RAW_ENCAP,
2562 	ACTION_VXLAN_ENCAP,
2563 	ACTION_NVGRE_ENCAP,
2564 	ACTION_REPRESENTED_PORT,
2565 	ACTION_PORT_REPRESENTOR,
2566 	ACTION_NEXT,
2567 	ZERO,
2568 };
2569 
2570 static const enum index item_ipv6_push_ext[] = {
2571 	ITEM_IPV6_PUSH_REMOVE_EXT,
2572 	ZERO,
2573 };
2574 
2575 static const enum index item_ipv6_push_ext_type[] = {
2576 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2577 	ZERO,
2578 };
2579 
2580 static const enum index item_ipv6_push_ext_header[] = {
2581 	ITEM_IPV6_ROUTING_EXT,
2582 	ITEM_NEXT,
2583 	ZERO,
2584 };
2585 
2586 static const enum index action_modify_field_dst[] = {
2587 	ACTION_MODIFY_FIELD_DST_LEVEL,
2588 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2589 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2590 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2591 	ACTION_MODIFY_FIELD_DST_OFFSET,
2592 	ACTION_MODIFY_FIELD_SRC_TYPE,
2593 	ZERO,
2594 };
2595 
2596 static const enum index action_modify_field_src[] = {
2597 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2598 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2599 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2600 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2601 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2602 	ACTION_MODIFY_FIELD_SRC_VALUE,
2603 	ACTION_MODIFY_FIELD_SRC_POINTER,
2604 	ACTION_MODIFY_FIELD_WIDTH,
2605 	ZERO,
2606 };
2607 
2608 static const enum index action_update_conntrack[] = {
2609 	ACTION_CONNTRACK_UPDATE_DIR,
2610 	ACTION_CONNTRACK_UPDATE_CTX,
2611 	ACTION_NEXT,
2612 	ZERO,
2613 };
2614 
2615 static const enum index action_port_representor[] = {
2616 	ACTION_PORT_REPRESENTOR_PORT_ID,
2617 	ACTION_NEXT,
2618 	ZERO,
2619 };
2620 
2621 static const enum index action_represented_port[] = {
2622 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2623 	ACTION_NEXT,
2624 	ZERO,
2625 };
2626 
2627 static const enum index action_nat64[] = {
2628 	ACTION_NAT64_MODE,
2629 	ACTION_NEXT,
2630 	ZERO,
2631 };
2632 
2633 static const enum index next_hash_subcmd[] = {
2634 	HASH_CALC_TABLE,
2635 	HASH_CALC_ENCAP,
2636 	ZERO,
2637 };
2638 
2639 static const enum index next_hash_encap_dest_subcmd[] = {
2640 	ENCAP_HASH_FIELD_SRC_PORT,
2641 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2642 	ZERO,
2643 };
2644 
2645 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2646 				     const char *, unsigned int,
2647 				     void *, unsigned int);
2648 static int parse_set_sample_action(struct context *, const struct token *,
2649 				   const char *, unsigned int,
2650 				   void *, unsigned int);
2651 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2652 				     const char *, unsigned int,
2653 				     void *, unsigned int);
2654 static int parse_set_init(struct context *, const struct token *,
2655 			  const char *, unsigned int,
2656 			  void *, unsigned int);
2657 static int
2658 parse_flex_handle(struct context *, const struct token *,
2659 		  const char *, unsigned int, void *, unsigned int);
2660 static int parse_init(struct context *, const struct token *,
2661 		      const char *, unsigned int,
2662 		      void *, unsigned int);
2663 static int parse_vc(struct context *, const struct token *,
2664 		    const char *, unsigned int,
2665 		    void *, unsigned int);
2666 static int parse_vc_spec(struct context *, const struct token *,
2667 			 const char *, unsigned int, void *, unsigned int);
2668 static int parse_vc_conf(struct context *, const struct token *,
2669 			 const char *, unsigned int, void *, unsigned int);
2670 static int parse_vc_conf_timeout(struct context *, const struct token *,
2671 				 const char *, unsigned int, void *,
2672 				 unsigned int);
2673 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2674 				    const char *, unsigned int,
2675 				    void *, unsigned int);
2676 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2677 				    const char *, unsigned int,
2678 				    void *, unsigned int);
2679 static int parse_vc_action_meter_color_type(struct context *,
2680 					const struct token *,
2681 					const char *, unsigned int, void *,
2682 					unsigned int);
2683 static int parse_vc_action_rss(struct context *, const struct token *,
2684 			       const char *, unsigned int, void *,
2685 			       unsigned int);
2686 static int parse_vc_action_rss_func(struct context *, const struct token *,
2687 				    const char *, unsigned int, void *,
2688 				    unsigned int);
2689 static int parse_vc_action_rss_type(struct context *, const struct token *,
2690 				    const char *, unsigned int, void *,
2691 				    unsigned int);
2692 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2693 				     const char *, unsigned int, void *,
2694 				     unsigned int);
2695 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2696 				       const char *, unsigned int, void *,
2697 				       unsigned int);
2698 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2699 				       const char *, unsigned int, void *,
2700 				       unsigned int);
2701 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2702 				    const char *, unsigned int, void *,
2703 				    unsigned int);
2704 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2705 				    const char *, unsigned int, void *,
2706 				    unsigned int);
2707 static int parse_vc_action_mplsogre_encap(struct context *,
2708 					  const struct token *, const char *,
2709 					  unsigned int, void *, unsigned int);
2710 static int parse_vc_action_mplsogre_decap(struct context *,
2711 					  const struct token *, const char *,
2712 					  unsigned int, void *, unsigned int);
2713 static int parse_vc_action_mplsoudp_encap(struct context *,
2714 					  const struct token *, const char *,
2715 					  unsigned int, void *, unsigned int);
2716 static int parse_vc_action_mplsoudp_decap(struct context *,
2717 					  const struct token *, const char *,
2718 					  unsigned int, void *, unsigned int);
2719 static int parse_vc_action_raw_encap(struct context *,
2720 				     const struct token *, const char *,
2721 				     unsigned int, void *, unsigned int);
2722 static int parse_vc_action_raw_decap(struct context *,
2723 				     const struct token *, const char *,
2724 				     unsigned int, void *, unsigned int);
2725 static int parse_vc_action_raw_encap_index(struct context *,
2726 					   const struct token *, const char *,
2727 					   unsigned int, void *, unsigned int);
2728 static int parse_vc_action_raw_decap_index(struct context *,
2729 					   const struct token *, const char *,
2730 					   unsigned int, void *, unsigned int);
2731 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2732 					   const char *str, unsigned int len, void *buf,
2733 					   unsigned int size);
2734 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2735 						 const struct token *token,
2736 						 const char *str, unsigned int len,
2737 						 void *buf,
2738 						 unsigned int size);
2739 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2740 					 const char *str, unsigned int len, void *buf,
2741 					 unsigned int size);
2742 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2743 					       const struct token *token,
2744 					       const char *str, unsigned int len,
2745 					       void *buf,
2746 					       unsigned int size);
2747 static int parse_vc_action_set_meta(struct context *ctx,
2748 				    const struct token *token, const char *str,
2749 				    unsigned int len, void *buf,
2750 					unsigned int size);
2751 static int parse_vc_action_sample(struct context *ctx,
2752 				    const struct token *token, const char *str,
2753 				    unsigned int len, void *buf,
2754 				    unsigned int size);
2755 static int
2756 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2757 				const char *str, unsigned int len, void *buf,
2758 				unsigned int size);
2759 static int
2760 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2761 				const char *str, unsigned int len, void *buf,
2762 				unsigned int size);
2763 static int
2764 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2765 				const char *str, unsigned int len, void *buf,
2766 				unsigned int size);
2767 static int
2768 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2769 				const char *str, unsigned int len, void *buf,
2770 				unsigned int size);
2771 static int
2772 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2773 			 const char *str, unsigned int len, void *buf,
2774 			 unsigned int size);
2775 static int parse_destroy(struct context *, const struct token *,
2776 			 const char *, unsigned int,
2777 			 void *, unsigned int);
2778 static int parse_flush(struct context *, const struct token *,
2779 		       const char *, unsigned int,
2780 		       void *, unsigned int);
2781 static int parse_dump(struct context *, const struct token *,
2782 		      const char *, unsigned int,
2783 		      void *, unsigned int);
2784 static int parse_query(struct context *, const struct token *,
2785 		       const char *, unsigned int,
2786 		       void *, unsigned int);
2787 static int parse_action(struct context *, const struct token *,
2788 			const char *, unsigned int,
2789 			void *, unsigned int);
2790 static int parse_list(struct context *, const struct token *,
2791 		      const char *, unsigned int,
2792 		      void *, unsigned int);
2793 static int parse_aged(struct context *, const struct token *,
2794 		      const char *, unsigned int,
2795 		      void *, unsigned int);
2796 static int parse_isolate(struct context *, const struct token *,
2797 			 const char *, unsigned int,
2798 			 void *, unsigned int);
2799 static int parse_configure(struct context *, const struct token *,
2800 			   const char *, unsigned int,
2801 			   void *, unsigned int);
2802 static int parse_template(struct context *, const struct token *,
2803 			  const char *, unsigned int,
2804 			  void *, unsigned int);
2805 static int parse_template_destroy(struct context *, const struct token *,
2806 				  const char *, unsigned int,
2807 				  void *, unsigned int);
2808 static int parse_table(struct context *, const struct token *,
2809 		       const char *, unsigned int, void *, unsigned int);
2810 static int parse_table_destroy(struct context *, const struct token *,
2811 			       const char *, unsigned int,
2812 			       void *, unsigned int);
2813 static int parse_qo(struct context *, const struct token *,
2814 		    const char *, unsigned int,
2815 		    void *, unsigned int);
2816 static int parse_qo_destroy(struct context *, const struct token *,
2817 			    const char *, unsigned int,
2818 			    void *, unsigned int);
2819 static int parse_qia(struct context *, const struct token *,
2820 		     const char *, unsigned int,
2821 		     void *, unsigned int);
2822 static int parse_qia_destroy(struct context *, const struct token *,
2823 			     const char *, unsigned int,
2824 			     void *, unsigned int);
2825 static int parse_push(struct context *, const struct token *,
2826 		      const char *, unsigned int,
2827 		      void *, unsigned int);
2828 static int parse_pull(struct context *, const struct token *,
2829 		      const char *, unsigned int,
2830 		      void *, unsigned int);
2831 static int parse_group(struct context *, const struct token *,
2832 		       const char *, unsigned int,
2833 		       void *, unsigned int);
2834 static int parse_hash(struct context *, const struct token *,
2835 		      const char *, unsigned int,
2836 		      void *, unsigned int);
2837 static int parse_tunnel(struct context *, const struct token *,
2838 			const char *, unsigned int,
2839 			void *, unsigned int);
2840 static int parse_flex(struct context *, const struct token *,
2841 		      const char *, unsigned int, void *, unsigned int);
2842 static int parse_int(struct context *, const struct token *,
2843 		     const char *, unsigned int,
2844 		     void *, unsigned int);
2845 static int parse_prefix(struct context *, const struct token *,
2846 			const char *, unsigned int,
2847 			void *, unsigned int);
2848 static int parse_boolean(struct context *, const struct token *,
2849 			 const char *, unsigned int,
2850 			 void *, unsigned int);
2851 static int parse_string(struct context *, const struct token *,
2852 			const char *, unsigned int,
2853 			void *, unsigned int);
2854 static int parse_hex(struct context *ctx, const struct token *token,
2855 			const char *str, unsigned int len,
2856 			void *buf, unsigned int size);
2857 static int parse_string0(struct context *, const struct token *,
2858 			const char *, unsigned int,
2859 			void *, unsigned int);
2860 static int parse_mac_addr(struct context *, const struct token *,
2861 			  const char *, unsigned int,
2862 			  void *, unsigned int);
2863 static int parse_ipv4_addr(struct context *, const struct token *,
2864 			   const char *, unsigned int,
2865 			   void *, unsigned int);
2866 static int parse_ipv6_addr(struct context *, const struct token *,
2867 			   const char *, unsigned int,
2868 			   void *, unsigned int);
2869 static int parse_port(struct context *, const struct token *,
2870 		      const char *, unsigned int,
2871 		      void *, unsigned int);
2872 static int parse_ia(struct context *, const struct token *,
2873 		    const char *, unsigned int,
2874 		    void *, unsigned int);
2875 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2876 			    const char *str, unsigned int len,
2877 			    void *buf, unsigned int size);
2878 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2879 			   const char *str, unsigned int len, void *buf,
2880 			   unsigned int size);
2881 
2882 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2883 			       const char *str, unsigned int len, void *buf,
2884 			       unsigned int size);
2885 static int parse_ia_port(struct context *ctx, const struct token *token,
2886 			 const char *str, unsigned int len, void *buf,
2887 			 unsigned int size);
2888 static int parse_mp(struct context *, const struct token *,
2889 		    const char *, unsigned int,
2890 		    void *, unsigned int);
2891 static int parse_meter_profile_id2ptr(struct context *ctx,
2892 				      const struct token *token,
2893 				      const char *str, unsigned int len,
2894 				      void *buf, unsigned int size);
2895 static int parse_meter_policy_id2ptr(struct context *ctx,
2896 				     const struct token *token,
2897 				     const char *str, unsigned int len,
2898 				     void *buf, unsigned int size);
2899 static int parse_meter_color(struct context *ctx, const struct token *token,
2900 			     const char *str, unsigned int len, void *buf,
2901 			     unsigned int size);
2902 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2903 				      const char *str, unsigned int len, void *buf,
2904 				      unsigned int size);
2905 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2906 				 const char *str, unsigned int len, void *buf,
2907 				 unsigned int size);
2908 static int
2909 parse_quota_state_name(struct context *ctx, const struct token *token,
2910 		       const char *str, unsigned int len, void *buf,
2911 		       unsigned int size);
2912 static int
2913 parse_quota_mode_name(struct context *ctx, const struct token *token,
2914 		      const char *str, unsigned int len, void *buf,
2915 		      unsigned int size);
2916 static int
2917 parse_quota_update_name(struct context *ctx, const struct token *token,
2918 			const char *str, unsigned int len, void *buf,
2919 			unsigned int size);
2920 static int
2921 parse_qu_mode_name(struct context *ctx, const struct token *token,
2922 		   const char *str, unsigned int len, void *buf,
2923 		   unsigned int size);
2924 static int comp_none(struct context *, const struct token *,
2925 		     unsigned int, char *, unsigned int);
2926 static int comp_boolean(struct context *, const struct token *,
2927 			unsigned int, char *, unsigned int);
2928 static int comp_action(struct context *, const struct token *,
2929 		       unsigned int, char *, unsigned int);
2930 static int comp_port(struct context *, const struct token *,
2931 		     unsigned int, char *, unsigned int);
2932 static int comp_rule_id(struct context *, const struct token *,
2933 			unsigned int, char *, unsigned int);
2934 static int comp_vc_action_rss_type(struct context *, const struct token *,
2935 				   unsigned int, char *, unsigned int);
2936 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2937 				    unsigned int, char *, unsigned int);
2938 static int comp_set_raw_index(struct context *, const struct token *,
2939 			      unsigned int, char *, unsigned int);
2940 static int comp_set_sample_index(struct context *, const struct token *,
2941 			      unsigned int, char *, unsigned int);
2942 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2943 				   unsigned int ent, char *buf, unsigned int size);
2944 static int comp_set_modify_field_op(struct context *, const struct token *,
2945 			      unsigned int, char *, unsigned int);
2946 static int comp_set_modify_field_id(struct context *, const struct token *,
2947 			      unsigned int, char *, unsigned int);
2948 static int comp_pattern_template_id(struct context *, const struct token *,
2949 				    unsigned int, char *, unsigned int);
2950 static int comp_actions_template_id(struct context *, const struct token *,
2951 				    unsigned int, char *, unsigned int);
2952 static int comp_table_id(struct context *, const struct token *,
2953 			 unsigned int, char *, unsigned int);
2954 static int comp_queue_id(struct context *, const struct token *,
2955 			 unsigned int, char *, unsigned int);
2956 static int comp_meter_color(struct context *, const struct token *,
2957 			    unsigned int, char *, unsigned int);
2958 static int comp_insertion_table_type(struct context *, const struct token *,
2959 				     unsigned int, char *, unsigned int);
2960 static int comp_hash_table_type(struct context *, const struct token *,
2961 				unsigned int, char *, unsigned int);
2962 static int
2963 comp_quota_state_name(struct context *ctx, const struct token *token,
2964 		      unsigned int ent, char *buf, unsigned int size);
2965 static int
2966 comp_quota_mode_name(struct context *ctx, const struct token *token,
2967 		     unsigned int ent, char *buf, unsigned int size);
2968 static int
2969 comp_quota_update_name(struct context *ctx, const struct token *token,
2970 		       unsigned int ent, char *buf, unsigned int size);
2971 static int
2972 comp_qu_mode_name(struct context *ctx, const struct token *token,
2973 		  unsigned int ent, char *buf, unsigned int size);
2974 static int
2975 comp_set_compare_field_id(struct context *ctx, const struct token *token,
2976 			  unsigned int ent, char *buf, unsigned int size);
2977 static int
2978 comp_set_compare_op(struct context *ctx, const struct token *token,
2979 		    unsigned int ent, char *buf, unsigned int size);
2980 static int
2981 parse_vc_compare_op(struct context *ctx, const struct token *token,
2982 			 const char *str, unsigned int len, void *buf,
2983 			 unsigned int size);
2984 static int
2985 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
2986 			  const char *str, unsigned int len, void *buf,
2987 			  unsigned int size);
2988 static int
2989 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
2990 			     const char *str, unsigned int len, void *buf,
2991 			     unsigned int size);
2992 
2993 struct indlst_conf {
2994 	uint32_t id;
2995 	uint32_t conf_num;
2996 	struct rte_flow_action *actions;
2997 	const void **conf;
2998 	SLIST_ENTRY(indlst_conf) next;
2999 };
3000 
3001 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3002 
3003 /** Token definitions. */
3004 static const struct token token_list[] = {
3005 	/* Special tokens. */
3006 	[ZERO] = {
3007 		.name = "ZERO",
3008 		.help = "null entry, abused as the entry point",
3009 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3010 	},
3011 	[END] = {
3012 		.name = "",
3013 		.type = "RETURN",
3014 		.help = "command may end here",
3015 	},
3016 	[START_SET] = {
3017 		.name = "START_SET",
3018 		.help = "null entry, abused as the entry point for set",
3019 		.next = NEXT(NEXT_ENTRY(SET)),
3020 	},
3021 	[END_SET] = {
3022 		.name = "end_set",
3023 		.type = "RETURN",
3024 		.help = "set command may end here",
3025 	},
3026 	/* Common tokens. */
3027 	[COMMON_INTEGER] = {
3028 		.name = "{int}",
3029 		.type = "INTEGER",
3030 		.help = "integer value",
3031 		.call = parse_int,
3032 		.comp = comp_none,
3033 	},
3034 	[COMMON_UNSIGNED] = {
3035 		.name = "{unsigned}",
3036 		.type = "UNSIGNED",
3037 		.help = "unsigned integer value",
3038 		.call = parse_int,
3039 		.comp = comp_none,
3040 	},
3041 	[COMMON_PREFIX] = {
3042 		.name = "{prefix}",
3043 		.type = "PREFIX",
3044 		.help = "prefix length for bit-mask",
3045 		.call = parse_prefix,
3046 		.comp = comp_none,
3047 	},
3048 	[COMMON_BOOLEAN] = {
3049 		.name = "{boolean}",
3050 		.type = "BOOLEAN",
3051 		.help = "any boolean value",
3052 		.call = parse_boolean,
3053 		.comp = comp_boolean,
3054 	},
3055 	[COMMON_STRING] = {
3056 		.name = "{string}",
3057 		.type = "STRING",
3058 		.help = "fixed string",
3059 		.call = parse_string,
3060 		.comp = comp_none,
3061 	},
3062 	[COMMON_HEX] = {
3063 		.name = "{hex}",
3064 		.type = "HEX",
3065 		.help = "fixed string",
3066 		.call = parse_hex,
3067 	},
3068 	[COMMON_FILE_PATH] = {
3069 		.name = "{file path}",
3070 		.type = "STRING",
3071 		.help = "file path",
3072 		.call = parse_string0,
3073 		.comp = comp_none,
3074 	},
3075 	[COMMON_MAC_ADDR] = {
3076 		.name = "{MAC address}",
3077 		.type = "MAC-48",
3078 		.help = "standard MAC address notation",
3079 		.call = parse_mac_addr,
3080 		.comp = comp_none,
3081 	},
3082 	[COMMON_IPV4_ADDR] = {
3083 		.name = "{IPv4 address}",
3084 		.type = "IPV4 ADDRESS",
3085 		.help = "standard IPv4 address notation",
3086 		.call = parse_ipv4_addr,
3087 		.comp = comp_none,
3088 	},
3089 	[COMMON_IPV6_ADDR] = {
3090 		.name = "{IPv6 address}",
3091 		.type = "IPV6 ADDRESS",
3092 		.help = "standard IPv6 address notation",
3093 		.call = parse_ipv6_addr,
3094 		.comp = comp_none,
3095 	},
3096 	[COMMON_RULE_ID] = {
3097 		.name = "{rule id}",
3098 		.type = "RULE ID",
3099 		.help = "rule identifier",
3100 		.call = parse_int,
3101 		.comp = comp_rule_id,
3102 	},
3103 	[COMMON_PORT_ID] = {
3104 		.name = "{port_id}",
3105 		.type = "PORT ID",
3106 		.help = "port identifier",
3107 		.call = parse_port,
3108 		.comp = comp_port,
3109 	},
3110 	[COMMON_GROUP_ID] = {
3111 		.name = "{group_id}",
3112 		.type = "GROUP ID",
3113 		.help = "group identifier",
3114 		.call = parse_int,
3115 		.comp = comp_none,
3116 	},
3117 	[COMMON_PRIORITY_LEVEL] = {
3118 		.name = "{level}",
3119 		.type = "PRIORITY",
3120 		.help = "priority level",
3121 		.call = parse_int,
3122 		.comp = comp_none,
3123 	},
3124 	[COMMON_INDIRECT_ACTION_ID] = {
3125 		.name = "{indirect_action_id}",
3126 		.type = "INDIRECT_ACTION_ID",
3127 		.help = "indirect action id",
3128 		.call = parse_int,
3129 		.comp = comp_none,
3130 	},
3131 	[COMMON_PROFILE_ID] = {
3132 		.name = "{profile_id}",
3133 		.type = "PROFILE_ID",
3134 		.help = "profile id",
3135 		.call = parse_int,
3136 		.comp = comp_none,
3137 	},
3138 	[COMMON_POLICY_ID] = {
3139 		.name = "{policy_id}",
3140 		.type = "POLICY_ID",
3141 		.help = "policy id",
3142 		.call = parse_int,
3143 		.comp = comp_none,
3144 	},
3145 	[COMMON_FLEX_TOKEN] = {
3146 		.name = "{flex token}",
3147 		.type = "flex token",
3148 		.help = "flex token",
3149 		.call = parse_int,
3150 		.comp = comp_none,
3151 	},
3152 	[COMMON_FLEX_HANDLE] = {
3153 		.name = "{flex handle}",
3154 		.type = "FLEX HANDLE",
3155 		.help = "fill flex item data",
3156 		.call = parse_flex_handle,
3157 		.comp = comp_none,
3158 	},
3159 	[COMMON_PATTERN_TEMPLATE_ID] = {
3160 		.name = "{pattern_template_id}",
3161 		.type = "PATTERN_TEMPLATE_ID",
3162 		.help = "pattern template id",
3163 		.call = parse_int,
3164 		.comp = comp_pattern_template_id,
3165 	},
3166 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3167 		.name = "{actions_template_id}",
3168 		.type = "ACTIONS_TEMPLATE_ID",
3169 		.help = "actions template id",
3170 		.call = parse_int,
3171 		.comp = comp_actions_template_id,
3172 	},
3173 	[COMMON_TABLE_ID] = {
3174 		.name = "{table_id}",
3175 		.type = "TABLE_ID",
3176 		.help = "table id",
3177 		.call = parse_int,
3178 		.comp = comp_table_id,
3179 	},
3180 	[COMMON_QUEUE_ID] = {
3181 		.name = "{queue_id}",
3182 		.type = "QUEUE_ID",
3183 		.help = "queue id",
3184 		.call = parse_int,
3185 		.comp = comp_queue_id,
3186 	},
3187 	/* Top-level command. */
3188 	[FLOW] = {
3189 		.name = "flow",
3190 		.type = "{command} {port_id} [{arg} [...]]",
3191 		.help = "manage ingress/egress flow rules",
3192 		.next = NEXT(NEXT_ENTRY
3193 			     (INFO,
3194 			      CONFIGURE,
3195 			      PATTERN_TEMPLATE,
3196 			      ACTIONS_TEMPLATE,
3197 			      TABLE,
3198 			      FLOW_GROUP,
3199 			      INDIRECT_ACTION,
3200 			      VALIDATE,
3201 			      CREATE,
3202 			      DESTROY,
3203 			      FLUSH,
3204 			      DUMP,
3205 			      LIST,
3206 			      AGED,
3207 			      QUERY,
3208 			      ISOLATE,
3209 			      TUNNEL,
3210 			      FLEX,
3211 			      QUEUE,
3212 			      PUSH,
3213 			      PULL,
3214 			      HASH)),
3215 		.call = parse_init,
3216 	},
3217 	/* Top-level command. */
3218 	[INFO] = {
3219 		.name = "info",
3220 		.help = "get information about flow engine",
3221 		.next = NEXT(NEXT_ENTRY(END),
3222 			     NEXT_ENTRY(COMMON_PORT_ID)),
3223 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3224 		.call = parse_configure,
3225 	},
3226 	/* Top-level command. */
3227 	[CONFIGURE] = {
3228 		.name = "configure",
3229 		.help = "configure flow engine",
3230 		.next = NEXT(next_config_attr,
3231 			     NEXT_ENTRY(COMMON_PORT_ID)),
3232 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3233 		.call = parse_configure,
3234 	},
3235 	/* Configure arguments. */
3236 	[CONFIG_QUEUES_NUMBER] = {
3237 		.name = "queues_number",
3238 		.help = "number of queues",
3239 		.next = NEXT(next_config_attr,
3240 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3241 		.args = ARGS(ARGS_ENTRY(struct buffer,
3242 					args.configure.nb_queue)),
3243 	},
3244 	[CONFIG_QUEUES_SIZE] = {
3245 		.name = "queues_size",
3246 		.help = "number of elements in queues",
3247 		.next = NEXT(next_config_attr,
3248 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3249 		.args = ARGS(ARGS_ENTRY(struct buffer,
3250 					args.configure.queue_attr.size)),
3251 	},
3252 	[CONFIG_COUNTERS_NUMBER] = {
3253 		.name = "counters_number",
3254 		.help = "number of counters",
3255 		.next = NEXT(next_config_attr,
3256 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3257 		.args = ARGS(ARGS_ENTRY(struct buffer,
3258 					args.configure.port_attr.nb_counters)),
3259 	},
3260 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3261 		.name = "aging_counters_number",
3262 		.help = "number of aging objects",
3263 		.next = NEXT(next_config_attr,
3264 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3265 		.args = ARGS(ARGS_ENTRY(struct buffer,
3266 					args.configure.port_attr.nb_aging_objects)),
3267 	},
3268 	[CONFIG_QUOTAS_NUMBER] = {
3269 		.name = "quotas_number",
3270 		.help = "number of quotas",
3271 		.next = NEXT(next_config_attr,
3272 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3273 		.args = ARGS(ARGS_ENTRY(struct buffer,
3274 				     args.configure.port_attr.nb_quotas)),
3275 	},
3276 	[CONFIG_METERS_NUMBER] = {
3277 		.name = "meters_number",
3278 		.help = "number of meters",
3279 		.next = NEXT(next_config_attr,
3280 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3281 		.args = ARGS(ARGS_ENTRY(struct buffer,
3282 					args.configure.port_attr.nb_meters)),
3283 	},
3284 	[CONFIG_CONN_TRACK_NUMBER] = {
3285 		.name = "conn_tracks_number",
3286 		.help = "number of connection trackings",
3287 		.next = NEXT(next_config_attr,
3288 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3289 		.args = ARGS(ARGS_ENTRY(struct buffer,
3290 					args.configure.port_attr.nb_conn_tracks)),
3291 	},
3292 	[CONFIG_FLAGS] = {
3293 		.name = "flags",
3294 		.help = "configuration flags",
3295 		.next = NEXT(next_config_attr,
3296 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3297 		.args = ARGS(ARGS_ENTRY(struct buffer,
3298 					args.configure.port_attr.flags)),
3299 	},
3300 	[CONFIG_HOST_PORT] = {
3301 		.name = "host_port",
3302 		.help = "host port for shared objects",
3303 		.next = NEXT(next_config_attr,
3304 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3305 		.args = ARGS(ARGS_ENTRY(struct buffer,
3306 					args.configure.port_attr.host_port_id)),
3307 	},
3308 	/* Top-level command. */
3309 	[PATTERN_TEMPLATE] = {
3310 		.name = "pattern_template",
3311 		.type = "{command} {port_id} [{arg} [...]]",
3312 		.help = "manage pattern templates",
3313 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3314 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3315 		.call = parse_template,
3316 	},
3317 	/* Sub-level commands. */
3318 	[PATTERN_TEMPLATE_CREATE] = {
3319 		.name = "create",
3320 		.help = "create pattern template",
3321 		.next = NEXT(next_pt_attr),
3322 		.call = parse_template,
3323 	},
3324 	[PATTERN_TEMPLATE_DESTROY] = {
3325 		.name = "destroy",
3326 		.help = "destroy pattern template",
3327 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3328 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3329 		.call = parse_template_destroy,
3330 	},
3331 	/* Pattern template arguments. */
3332 	[PATTERN_TEMPLATE_CREATE_ID] = {
3333 		.name = "pattern_template_id",
3334 		.help = "specify a pattern template id to create",
3335 		.next = NEXT(next_pt_attr,
3336 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3337 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3338 	},
3339 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3340 		.name = "pattern_template",
3341 		.help = "specify a pattern template id to destroy",
3342 		.next = NEXT(next_pt_destroy_attr,
3343 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3344 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3345 					    args.templ_destroy.template_id)),
3346 		.call = parse_template_destroy,
3347 	},
3348 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3349 		.name = "relaxed",
3350 		.help = "is matching relaxed",
3351 		.next = NEXT(next_pt_attr,
3352 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3353 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3354 			     args.vc.attr.reserved, 1)),
3355 	},
3356 	[PATTERN_TEMPLATE_INGRESS] = {
3357 		.name = "ingress",
3358 		.help = "attribute pattern to ingress",
3359 		.next = NEXT(next_pt_attr),
3360 		.call = parse_template,
3361 	},
3362 	[PATTERN_TEMPLATE_EGRESS] = {
3363 		.name = "egress",
3364 		.help = "attribute pattern to egress",
3365 		.next = NEXT(next_pt_attr),
3366 		.call = parse_template,
3367 	},
3368 	[PATTERN_TEMPLATE_TRANSFER] = {
3369 		.name = "transfer",
3370 		.help = "attribute pattern to transfer",
3371 		.next = NEXT(next_pt_attr),
3372 		.call = parse_template,
3373 	},
3374 	[PATTERN_TEMPLATE_SPEC] = {
3375 		.name = "template",
3376 		.help = "specify item to create pattern template",
3377 		.next = NEXT(next_item),
3378 	},
3379 	/* Top-level command. */
3380 	[ACTIONS_TEMPLATE] = {
3381 		.name = "actions_template",
3382 		.type = "{command} {port_id} [{arg} [...]]",
3383 		.help = "manage actions templates",
3384 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3385 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3386 		.call = parse_template,
3387 	},
3388 	/* Sub-level commands. */
3389 	[ACTIONS_TEMPLATE_CREATE] = {
3390 		.name = "create",
3391 		.help = "create actions template",
3392 		.next = NEXT(next_at_attr),
3393 		.call = parse_template,
3394 	},
3395 	[ACTIONS_TEMPLATE_DESTROY] = {
3396 		.name = "destroy",
3397 		.help = "destroy actions template",
3398 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3399 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3400 		.call = parse_template_destroy,
3401 	},
3402 	/* Actions template arguments. */
3403 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3404 		.name = "actions_template_id",
3405 		.help = "specify an actions template id to create",
3406 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3407 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3408 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3409 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3410 	},
3411 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3412 		.name = "actions_template",
3413 		.help = "specify an actions template id to destroy",
3414 		.next = NEXT(next_at_destroy_attr,
3415 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3416 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3417 					    args.templ_destroy.template_id)),
3418 		.call = parse_template_destroy,
3419 	},
3420 	[ACTIONS_TEMPLATE_INGRESS] = {
3421 		.name = "ingress",
3422 		.help = "attribute actions to ingress",
3423 		.next = NEXT(next_at_attr),
3424 		.call = parse_template,
3425 	},
3426 	[ACTIONS_TEMPLATE_EGRESS] = {
3427 		.name = "egress",
3428 		.help = "attribute actions to egress",
3429 		.next = NEXT(next_at_attr),
3430 		.call = parse_template,
3431 	},
3432 	[ACTIONS_TEMPLATE_TRANSFER] = {
3433 		.name = "transfer",
3434 		.help = "attribute actions to transfer",
3435 		.next = NEXT(next_at_attr),
3436 		.call = parse_template,
3437 	},
3438 	[ACTIONS_TEMPLATE_SPEC] = {
3439 		.name = "template",
3440 		.help = "specify action to create actions template",
3441 		.next = NEXT(next_action),
3442 		.call = parse_template,
3443 	},
3444 	[ACTIONS_TEMPLATE_MASK] = {
3445 		.name = "mask",
3446 		.help = "specify action mask to create actions template",
3447 		.next = NEXT(next_action),
3448 		.call = parse_template,
3449 	},
3450 	/* Top-level command. */
3451 	[TABLE] = {
3452 		.name = "template_table",
3453 		.type = "{command} {port_id} [{arg} [...]]",
3454 		.help = "manage template tables",
3455 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3456 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3457 		.call = parse_table,
3458 	},
3459 	/* Sub-level commands. */
3460 	[TABLE_CREATE] = {
3461 		.name = "create",
3462 		.help = "create template table",
3463 		.next = NEXT(next_table_attr),
3464 		.call = parse_table,
3465 	},
3466 	[TABLE_DESTROY] = {
3467 		.name = "destroy",
3468 		.help = "destroy template table",
3469 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3470 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3471 		.call = parse_table_destroy,
3472 	},
3473 	[TABLE_RESIZE] = {
3474 		.name = "resize",
3475 		.help = "resize template table",
3476 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3477 		.call = parse_table
3478 	},
3479 	[TABLE_RESIZE_COMPLETE] = {
3480 		.name = "resize_complete",
3481 		.help = "complete table resize",
3482 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3483 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3484 		.call = parse_table_destroy,
3485 	},
3486 	/* Table  arguments. */
3487 	[TABLE_CREATE_ID] = {
3488 		.name = "table_id",
3489 		.help = "specify table id to create",
3490 		.next = NEXT(next_table_attr,
3491 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3492 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3493 	},
3494 	[TABLE_DESTROY_ID] = {
3495 		.name = "table",
3496 		.help = "table id",
3497 		.next = NEXT(next_table_destroy_attr,
3498 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3499 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3500 					    args.table_destroy.table_id)),
3501 		.call = parse_table_destroy,
3502 	},
3503 	[TABLE_RESIZE_ID] = {
3504 		.name = "table_resize_id",
3505 		.help = "table resize id",
3506 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3507 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3508 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3509 		.call = parse_table
3510 	},
3511 	[TABLE_RESIZE_RULES_NUMBER] = {
3512 		.name = "table_resize_rules_num",
3513 		.help = "table resize rules number",
3514 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3515 		.args = ARGS(ARGS_ENTRY(struct buffer,
3516 					args.table.attr.nb_flows)),
3517 		.call = parse_table
3518 	},
3519 	[TABLE_INSERTION_TYPE] = {
3520 		.name = "insertion_type",
3521 		.help = "specify insertion type",
3522 		.next = NEXT(next_table_attr,
3523 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3524 		.args = ARGS(ARGS_ENTRY(struct buffer,
3525 					args.table.attr.insertion_type)),
3526 	},
3527 	[TABLE_INSERTION_TYPE_NAME] = {
3528 		.name = "insertion_type_name",
3529 		.help = "insertion type name",
3530 		.call = parse_insertion_table_type,
3531 		.comp = comp_insertion_table_type,
3532 	},
3533 	[TABLE_HASH_FUNC] = {
3534 		.name = "hash_func",
3535 		.help = "specify hash calculation function",
3536 		.next = NEXT(next_table_attr,
3537 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3538 		.args = ARGS(ARGS_ENTRY(struct buffer,
3539 					args.table.attr.hash_func)),
3540 	},
3541 	[TABLE_HASH_FUNC_NAME] = {
3542 		.name = "hash_func_name",
3543 		.help = "hash calculation function name",
3544 		.call = parse_hash_table_type,
3545 		.comp = comp_hash_table_type,
3546 	},
3547 	[TABLE_GROUP] = {
3548 		.name = "group",
3549 		.help = "specify a group",
3550 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3551 		.args = ARGS(ARGS_ENTRY(struct buffer,
3552 					args.table.attr.flow_attr.group)),
3553 	},
3554 	[TABLE_PRIORITY] = {
3555 		.name = "priority",
3556 		.help = "specify a priority level",
3557 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3558 		.args = ARGS(ARGS_ENTRY(struct buffer,
3559 					args.table.attr.flow_attr.priority)),
3560 	},
3561 	[TABLE_EGRESS] = {
3562 		.name = "egress",
3563 		.help = "affect rule to egress",
3564 		.next = NEXT(next_table_attr),
3565 		.call = parse_table,
3566 	},
3567 	[TABLE_INGRESS] = {
3568 		.name = "ingress",
3569 		.help = "affect rule to ingress",
3570 		.next = NEXT(next_table_attr),
3571 		.call = parse_table,
3572 	},
3573 	[TABLE_TRANSFER] = {
3574 		.name = "transfer",
3575 		.help = "affect rule to transfer",
3576 		.next = NEXT(next_table_attr),
3577 		.call = parse_table,
3578 	},
3579 	[TABLE_TRANSFER_WIRE_ORIG] = {
3580 		.name = "wire_orig",
3581 		.help = "affect rule direction to transfer",
3582 		.next = NEXT(next_table_attr),
3583 		.call = parse_table,
3584 	},
3585 	[TABLE_TRANSFER_VPORT_ORIG] = {
3586 		.name = "vport_orig",
3587 		.help = "affect rule direction to transfer",
3588 		.next = NEXT(next_table_attr),
3589 		.call = parse_table,
3590 	},
3591 	[TABLE_RESIZABLE] = {
3592 		.name = "resizable",
3593 		.help = "set resizable attribute",
3594 		.next = NEXT(next_table_attr),
3595 		.call = parse_table,
3596 	},
3597 	[TABLE_RULES_NUMBER] = {
3598 		.name = "rules_number",
3599 		.help = "number of rules in table",
3600 		.next = NEXT(next_table_attr,
3601 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3602 		.args = ARGS(ARGS_ENTRY(struct buffer,
3603 					args.table.attr.nb_flows)),
3604 		.call = parse_table,
3605 	},
3606 	[TABLE_PATTERN_TEMPLATE] = {
3607 		.name = "pattern_template",
3608 		.help = "specify pattern template id",
3609 		.next = NEXT(next_table_attr,
3610 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3611 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3612 					    args.table.pat_templ_id)),
3613 		.call = parse_table,
3614 	},
3615 	[TABLE_ACTIONS_TEMPLATE] = {
3616 		.name = "actions_template",
3617 		.help = "specify actions template id",
3618 		.next = NEXT(next_table_attr,
3619 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3620 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3621 					    args.table.act_templ_id)),
3622 		.call = parse_table,
3623 	},
3624 	/* Top-level command. */
3625 	[FLOW_GROUP] = {
3626 		.name = "group",
3627 		.help = "manage flow groups",
3628 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3629 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3630 		.call = parse_group,
3631 	},
3632 	/* Sub-level commands. */
3633 	[GROUP_SET_MISS_ACTIONS] = {
3634 		.name = "set_miss_actions",
3635 		.help = "set group miss actions",
3636 		.next = NEXT(next_action),
3637 		.call = parse_group,
3638 	},
3639 	/* Group arguments */
3640 	[GROUP_ID]	= {
3641 		.name = "group_id",
3642 		.help = "group id",
3643 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3644 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3645 	},
3646 	[GROUP_INGRESS] = {
3647 		.name = "ingress",
3648 		.help = "group ingress attr",
3649 		.next = NEXT(next_group_attr),
3650 		.call = parse_group,
3651 	},
3652 	[GROUP_EGRESS] = {
3653 		.name = "egress",
3654 		.help = "group egress attr",
3655 		.next = NEXT(next_group_attr),
3656 		.call = parse_group,
3657 	},
3658 	[GROUP_TRANSFER] = {
3659 		.name = "transfer",
3660 		.help = "group transfer attr",
3661 		.next = NEXT(next_group_attr),
3662 		.call = parse_group,
3663 	},
3664 	/* Top-level command. */
3665 	[QUEUE] = {
3666 		.name = "queue",
3667 		.help = "queue a flow rule operation",
3668 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3669 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3670 		.call = parse_qo,
3671 	},
3672 	/* Sub-level commands. */
3673 	[QUEUE_CREATE] = {
3674 		.name = "create",
3675 		.help = "create a flow rule",
3676 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3677 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3678 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3679 		.call = parse_qo,
3680 	},
3681 	[QUEUE_DESTROY] = {
3682 		.name = "destroy",
3683 		.help = "destroy a flow rule",
3684 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3685 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3686 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3687 		.call = parse_qo_destroy,
3688 	},
3689 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3690 		.name = "update_resized",
3691 		.help = "update a flow after table resize",
3692 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3693 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3694 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3695 		.call = parse_qo_destroy,
3696 	},
3697 	[QUEUE_UPDATE] = {
3698 		.name = "update",
3699 		.help = "update a flow rule",
3700 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3701 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3702 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3703 		.call = parse_qo,
3704 	},
3705 	[QUEUE_AGED] = {
3706 		.name = "aged",
3707 		.help = "list and destroy aged flows",
3708 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3709 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3710 		.call = parse_aged,
3711 	},
3712 	[QUEUE_INDIRECT_ACTION] = {
3713 		.name = "indirect_action",
3714 		.help = "queue indirect actions",
3715 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3716 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3717 		.call = parse_qia,
3718 	},
3719 	/* Queue  arguments. */
3720 	[QUEUE_TEMPLATE_TABLE] = {
3721 		.name = "template_table",
3722 		.help = "specify table id",
3723 		.next = NEXT(next_async_insert_subcmd,
3724 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3725 		.args = ARGS(ARGS_ENTRY(struct buffer,
3726 					args.vc.table_id)),
3727 		.call = parse_qo,
3728 	},
3729 	[QUEUE_PATTERN_TEMPLATE] = {
3730 		.name = "pattern_template",
3731 		.help = "specify pattern template index",
3732 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3733 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3734 		.args = ARGS(ARGS_ENTRY(struct buffer,
3735 					args.vc.pat_templ_id)),
3736 		.call = parse_qo,
3737 	},
3738 	[QUEUE_ACTIONS_TEMPLATE] = {
3739 		.name = "actions_template",
3740 		.help = "specify actions template index",
3741 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3742 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3743 		.args = ARGS(ARGS_ENTRY(struct buffer,
3744 					args.vc.act_templ_id)),
3745 		.call = parse_qo,
3746 	},
3747 	[QUEUE_RULE_ID] = {
3748 		.name = "rule_index",
3749 		.help = "specify flow rule index",
3750 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3751 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3752 		.args = ARGS(ARGS_ENTRY(struct buffer,
3753 					args.vc.rule_id)),
3754 		.call = parse_qo,
3755 	},
3756 	[QUEUE_CREATE_POSTPONE] = {
3757 		.name = "postpone",
3758 		.help = "postpone create operation",
3759 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3760 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3761 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3762 		.call = parse_qo,
3763 	},
3764 	[QUEUE_DESTROY_POSTPONE] = {
3765 		.name = "postpone",
3766 		.help = "postpone destroy operation",
3767 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3768 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3769 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3770 		.call = parse_qo_destroy,
3771 	},
3772 	[QUEUE_DESTROY_ID] = {
3773 		.name = "rule",
3774 		.help = "specify rule id to destroy",
3775 		.next = NEXT(next_queue_destroy_attr,
3776 			NEXT_ENTRY(COMMON_UNSIGNED)),
3777 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3778 					    args.destroy.rule)),
3779 		.call = parse_qo_destroy,
3780 	},
3781 	[QUEUE_UPDATE_ID] = {
3782 		.name = "rule",
3783 		.help = "specify rule id to update",
3784 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3785 			NEXT_ENTRY(COMMON_UNSIGNED)),
3786 		.args = ARGS(ARGS_ENTRY(struct buffer,
3787 				     args.vc.rule_id)),
3788 		.call = parse_qo,
3789 	},
3790 	/* Queue indirect action arguments */
3791 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3792 		.name = "create",
3793 		.help = "create indirect action",
3794 		.next = NEXT(next_qia_create_attr),
3795 		.call = parse_qia,
3796 	},
3797 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3798 		.name = "update",
3799 		.help = "update indirect action",
3800 		.next = NEXT(next_qia_update_attr,
3801 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3802 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3803 		.call = parse_qia,
3804 	},
3805 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3806 		.name = "destroy",
3807 		.help = "destroy indirect action",
3808 		.next = NEXT(next_qia_destroy_attr),
3809 		.call = parse_qia_destroy,
3810 	},
3811 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3812 		.name = "query",
3813 		.help = "query indirect action",
3814 		.next = NEXT(next_qia_query_attr,
3815 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3816 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3817 		.call = parse_qia,
3818 	},
3819 	/* Indirect action destroy arguments. */
3820 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3821 		.name = "postpone",
3822 		.help = "postpone destroy operation",
3823 		.next = NEXT(next_qia_destroy_attr,
3824 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3825 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3826 	},
3827 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3828 		.name = "action_id",
3829 		.help = "specify a indirect action id to destroy",
3830 		.next = NEXT(next_qia_destroy_attr,
3831 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3832 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3833 					    args.ia_destroy.action_id)),
3834 		.call = parse_qia_destroy,
3835 	},
3836 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3837 		.name = "query_update",
3838 		.help = "indirect query [and|or] update action",
3839 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3840 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3841 		.call = parse_qia
3842 	},
3843 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3844 		.name = "mode",
3845 		.help = "indirect query [and|or] update action",
3846 		.next = NEXT(next_qia_qu_attr,
3847 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3848 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3849 		.call = parse_qia
3850 	},
3851 	/* Indirect action update arguments. */
3852 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3853 		.name = "postpone",
3854 		.help = "postpone update operation",
3855 		.next = NEXT(next_qia_update_attr,
3856 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3857 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3858 	},
3859 	/* Indirect action update arguments. */
3860 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3861 		.name = "postpone",
3862 		.help = "postpone query operation",
3863 		.next = NEXT(next_qia_query_attr,
3864 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3865 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3866 	},
3867 	/* Indirect action create arguments. */
3868 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3869 		.name = "action_id",
3870 		.help = "specify a indirect action id to create",
3871 		.next = NEXT(next_qia_create_attr,
3872 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3873 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3874 	},
3875 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3876 		.name = "ingress",
3877 		.help = "affect rule to ingress",
3878 		.next = NEXT(next_qia_create_attr),
3879 		.call = parse_qia,
3880 	},
3881 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3882 		.name = "egress",
3883 		.help = "affect rule to egress",
3884 		.next = NEXT(next_qia_create_attr),
3885 		.call = parse_qia,
3886 	},
3887 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3888 		.name = "transfer",
3889 		.help = "affect rule to transfer",
3890 		.next = NEXT(next_qia_create_attr),
3891 		.call = parse_qia,
3892 	},
3893 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3894 		.name = "postpone",
3895 		.help = "postpone create operation",
3896 		.next = NEXT(next_qia_create_attr,
3897 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3898 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3899 	},
3900 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3901 		.name = "action",
3902 		.help = "specify action to create indirect handle",
3903 		.next = NEXT(next_action),
3904 	},
3905 	[QUEUE_INDIRECT_ACTION_LIST] = {
3906 		.name = "list",
3907 		.help = "specify actions for indirect handle list",
3908 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3909 		.call = parse_qia,
3910 	},
3911 	/* Top-level command. */
3912 	[PUSH] = {
3913 		.name = "push",
3914 		.help = "push enqueued operations",
3915 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3916 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3917 		.call = parse_push,
3918 	},
3919 	/* Sub-level commands. */
3920 	[PUSH_QUEUE] = {
3921 		.name = "queue",
3922 		.help = "specify queue id",
3923 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3924 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3925 	},
3926 	/* Top-level command. */
3927 	[PULL] = {
3928 		.name = "pull",
3929 		.help = "pull flow operations results",
3930 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3931 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3932 		.call = parse_pull,
3933 	},
3934 	/* Sub-level commands. */
3935 	[PULL_QUEUE] = {
3936 		.name = "queue",
3937 		.help = "specify queue id",
3938 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3939 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3940 	},
3941 	/* Top-level command. */
3942 	[HASH] = {
3943 		.name = "hash",
3944 		.help = "calculate hash for a given pattern in a given template table",
3945 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3946 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3947 		.call = parse_hash,
3948 	},
3949 	/* Sub-level commands. */
3950 	[HASH_CALC_TABLE] = {
3951 		.name = "template_table",
3952 		.help = "specify table id",
3953 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3954 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3955 		.args = ARGS(ARGS_ENTRY(struct buffer,
3956 					args.vc.table_id)),
3957 		.call = parse_hash,
3958 	},
3959 	[HASH_CALC_ENCAP] = {
3960 		.name = "encap",
3961 		.help = "calculates encap hash",
3962 		.next = NEXT(next_hash_encap_dest_subcmd),
3963 		.call = parse_hash,
3964 	},
3965 	[HASH_CALC_PATTERN_INDEX] = {
3966 		.name = "pattern_template",
3967 		.help = "specify pattern template id",
3968 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3969 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3970 		.args = ARGS(ARGS_ENTRY(struct buffer,
3971 					args.vc.pat_templ_id)),
3972 		.call = parse_hash,
3973 	},
3974 	[ENCAP_HASH_FIELD_SRC_PORT] = {
3975 		.name = "hash_field_sport",
3976 		.help = "the encap hash field is src port",
3977 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3978 		.call = parse_hash,
3979 	},
3980 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
3981 		.name = "hash_field_flow_id",
3982 		.help = "the encap hash field is NVGRE flow id",
3983 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3984 		.call = parse_hash,
3985 	},
3986 	/* Top-level command. */
3987 	[INDIRECT_ACTION] = {
3988 		.name = "indirect_action",
3989 		.type = "{command} {port_id} [{arg} [...]]",
3990 		.help = "manage indirect actions",
3991 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3992 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3993 		.call = parse_ia,
3994 	},
3995 	/* Sub-level commands. */
3996 	[INDIRECT_ACTION_CREATE] = {
3997 		.name = "create",
3998 		.help = "create indirect action",
3999 		.next = NEXT(next_ia_create_attr),
4000 		.call = parse_ia,
4001 	},
4002 	[INDIRECT_ACTION_UPDATE] = {
4003 		.name = "update",
4004 		.help = "update indirect action",
4005 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4006 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4007 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4008 		.call = parse_ia,
4009 	},
4010 	[INDIRECT_ACTION_DESTROY] = {
4011 		.name = "destroy",
4012 		.help = "destroy indirect action",
4013 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4014 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4015 		.call = parse_ia_destroy,
4016 	},
4017 	[INDIRECT_ACTION_QUERY] = {
4018 		.name = "query",
4019 		.help = "query indirect action",
4020 		.next = NEXT(NEXT_ENTRY(END),
4021 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4022 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4023 		.call = parse_ia,
4024 	},
4025 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4026 		.name = "query_update",
4027 		.help = "query [and|or] update",
4028 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4029 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4030 		.call = parse_ia
4031 	},
4032 	[INDIRECT_ACTION_QU_MODE] = {
4033 		.name = "mode",
4034 		.help = "query_update mode",
4035 		.next = NEXT(next_ia_qu_attr,
4036 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4037 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4038 		.call = parse_ia,
4039 	},
4040 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4041 		.name = "mode_name",
4042 		.help = "query-update mode name",
4043 		.call = parse_qu_mode_name,
4044 		.comp = comp_qu_mode_name,
4045 	},
4046 	[VALIDATE] = {
4047 		.name = "validate",
4048 		.help = "check whether a flow rule can be created",
4049 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4050 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4051 		.call = parse_vc,
4052 	},
4053 	[CREATE] = {
4054 		.name = "create",
4055 		.help = "create a flow rule",
4056 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4057 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4058 		.call = parse_vc,
4059 	},
4060 	[DESTROY] = {
4061 		.name = "destroy",
4062 		.help = "destroy specific flow rules",
4063 		.next = NEXT(next_destroy_attr,
4064 			     NEXT_ENTRY(COMMON_PORT_ID)),
4065 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4066 		.call = parse_destroy,
4067 	},
4068 	[FLUSH] = {
4069 		.name = "flush",
4070 		.help = "destroy all flow rules",
4071 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4072 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4073 		.call = parse_flush,
4074 	},
4075 	[DUMP] = {
4076 		.name = "dump",
4077 		.help = "dump single/all flow rules to file",
4078 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4079 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4080 		.call = parse_dump,
4081 	},
4082 	[QUERY] = {
4083 		.name = "query",
4084 		.help = "query an existing flow rule",
4085 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4086 			     NEXT_ENTRY(COMMON_RULE_ID),
4087 			     NEXT_ENTRY(COMMON_PORT_ID)),
4088 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4089 			     ARGS_ENTRY(struct buffer, args.query.rule),
4090 			     ARGS_ENTRY(struct buffer, port)),
4091 		.call = parse_query,
4092 	},
4093 	[LIST] = {
4094 		.name = "list",
4095 		.help = "list existing flow rules",
4096 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4097 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4098 		.call = parse_list,
4099 	},
4100 	[AGED] = {
4101 		.name = "aged",
4102 		.help = "list and destroy aged flows",
4103 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4104 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4105 		.call = parse_aged,
4106 	},
4107 	[ISOLATE] = {
4108 		.name = "isolate",
4109 		.help = "restrict ingress traffic to the defined flow rules",
4110 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4111 			     NEXT_ENTRY(COMMON_PORT_ID)),
4112 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4113 			     ARGS_ENTRY(struct buffer, port)),
4114 		.call = parse_isolate,
4115 	},
4116 	[FLEX] = {
4117 		.name = "flex_item",
4118 		.help = "flex item API",
4119 		.next = NEXT(next_flex_item),
4120 		.call = parse_flex,
4121 	},
4122 	[FLEX_ITEM_INIT] = {
4123 		.name = "init",
4124 		.help = "flex item init",
4125 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4126 			     ARGS_ENTRY(struct buffer, port)),
4127 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4128 			     NEXT_ENTRY(COMMON_PORT_ID)),
4129 		.call = parse_flex
4130 	},
4131 	[FLEX_ITEM_CREATE] = {
4132 		.name = "create",
4133 		.help = "flex item create",
4134 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4135 			     ARGS_ENTRY(struct buffer, args.flex.token),
4136 			     ARGS_ENTRY(struct buffer, port)),
4137 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4138 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4139 			     NEXT_ENTRY(COMMON_PORT_ID)),
4140 		.call = parse_flex
4141 	},
4142 	[FLEX_ITEM_DESTROY] = {
4143 		.name = "destroy",
4144 		.help = "flex item destroy",
4145 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4146 			     ARGS_ENTRY(struct buffer, port)),
4147 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4148 			     NEXT_ENTRY(COMMON_PORT_ID)),
4149 		.call = parse_flex
4150 	},
4151 	[TUNNEL] = {
4152 		.name = "tunnel",
4153 		.help = "new tunnel API",
4154 		.next = NEXT(NEXT_ENTRY
4155 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4156 		.call = parse_tunnel,
4157 	},
4158 	/* Tunnel arguments. */
4159 	[TUNNEL_CREATE] = {
4160 		.name = "create",
4161 		.help = "create new tunnel object",
4162 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4163 			     NEXT_ENTRY(COMMON_PORT_ID)),
4164 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4165 		.call = parse_tunnel,
4166 	},
4167 	[TUNNEL_CREATE_TYPE] = {
4168 		.name = "type",
4169 		.help = "create new tunnel",
4170 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4171 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4172 		.call = parse_tunnel,
4173 	},
4174 	[TUNNEL_DESTROY] = {
4175 		.name = "destroy",
4176 		.help = "destroy tunnel",
4177 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4178 			     NEXT_ENTRY(COMMON_PORT_ID)),
4179 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4180 		.call = parse_tunnel,
4181 	},
4182 	[TUNNEL_DESTROY_ID] = {
4183 		.name = "id",
4184 		.help = "tunnel identifier to destroy",
4185 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4186 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4187 		.call = parse_tunnel,
4188 	},
4189 	[TUNNEL_LIST] = {
4190 		.name = "list",
4191 		.help = "list existing tunnels",
4192 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4193 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4194 		.call = parse_tunnel,
4195 	},
4196 	/* Destroy arguments. */
4197 	[DESTROY_RULE] = {
4198 		.name = "rule",
4199 		.help = "specify a rule identifier",
4200 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4201 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4202 		.call = parse_destroy,
4203 	},
4204 	[DESTROY_IS_USER_ID] = {
4205 		.name = "user_id",
4206 		.help = "rule identifier is user-id",
4207 		.next = NEXT(next_destroy_attr),
4208 		.call = parse_destroy,
4209 	},
4210 	/* Dump arguments. */
4211 	[DUMP_ALL] = {
4212 		.name = "all",
4213 		.help = "dump all",
4214 		.next = NEXT(next_dump_attr),
4215 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4216 		.call = parse_dump,
4217 	},
4218 	[DUMP_ONE] = {
4219 		.name = "rule",
4220 		.help = "dump one rule",
4221 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4222 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4223 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4224 		.call = parse_dump,
4225 	},
4226 	[DUMP_IS_USER_ID] = {
4227 		.name = "user_id",
4228 		.help = "rule identifier is user-id",
4229 		.next = NEXT(next_dump_subcmd),
4230 		.call = parse_dump,
4231 	},
4232 	/* Query arguments. */
4233 	[QUERY_ACTION] = {
4234 		.name = "{action}",
4235 		.type = "ACTION",
4236 		.help = "action to query, must be part of the rule",
4237 		.call = parse_action,
4238 		.comp = comp_action,
4239 	},
4240 	[QUERY_IS_USER_ID] = {
4241 		.name = "user_id",
4242 		.help = "rule identifier is user-id",
4243 		.next = NEXT(next_query_attr),
4244 		.call = parse_query,
4245 	},
4246 	/* List arguments. */
4247 	[LIST_GROUP] = {
4248 		.name = "group",
4249 		.help = "specify a group",
4250 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4251 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4252 		.call = parse_list,
4253 	},
4254 	[AGED_DESTROY] = {
4255 		.name = "destroy",
4256 		.help = "specify aged flows need be destroyed",
4257 		.call = parse_aged,
4258 		.comp = comp_none,
4259 	},
4260 	/* Validate/create attributes. */
4261 	[VC_GROUP] = {
4262 		.name = "group",
4263 		.help = "specify a group",
4264 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4265 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4266 		.call = parse_vc,
4267 	},
4268 	[VC_PRIORITY] = {
4269 		.name = "priority",
4270 		.help = "specify a priority level",
4271 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4272 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4273 		.call = parse_vc,
4274 	},
4275 	[VC_INGRESS] = {
4276 		.name = "ingress",
4277 		.help = "affect rule to ingress",
4278 		.next = NEXT(next_vc_attr),
4279 		.call = parse_vc,
4280 	},
4281 	[VC_EGRESS] = {
4282 		.name = "egress",
4283 		.help = "affect rule to egress",
4284 		.next = NEXT(next_vc_attr),
4285 		.call = parse_vc,
4286 	},
4287 	[VC_TRANSFER] = {
4288 		.name = "transfer",
4289 		.help = "apply rule directly to endpoints found in pattern",
4290 		.next = NEXT(next_vc_attr),
4291 		.call = parse_vc,
4292 	},
4293 	[VC_TUNNEL_SET] = {
4294 		.name = "tunnel_set",
4295 		.help = "tunnel steer rule",
4296 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4297 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4298 		.call = parse_vc,
4299 	},
4300 	[VC_TUNNEL_MATCH] = {
4301 		.name = "tunnel_match",
4302 		.help = "tunnel match rule",
4303 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4304 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4305 		.call = parse_vc,
4306 	},
4307 	[VC_USER_ID] = {
4308 		.name = "user_id",
4309 		.help = "specify a user id to create",
4310 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4311 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4312 		.call = parse_vc,
4313 	},
4314 	/* Validate/create pattern. */
4315 	[ITEM_PATTERN] = {
4316 		.name = "pattern",
4317 		.help = "submit a list of pattern items",
4318 		.next = NEXT(next_item),
4319 		.call = parse_vc,
4320 	},
4321 	[ITEM_PARAM_IS] = {
4322 		.name = "is",
4323 		.help = "match value perfectly (with full bit-mask)",
4324 		.call = parse_vc_spec,
4325 	},
4326 	[ITEM_PARAM_SPEC] = {
4327 		.name = "spec",
4328 		.help = "match value according to configured bit-mask",
4329 		.call = parse_vc_spec,
4330 	},
4331 	[ITEM_PARAM_LAST] = {
4332 		.name = "last",
4333 		.help = "specify upper bound to establish a range",
4334 		.call = parse_vc_spec,
4335 	},
4336 	[ITEM_PARAM_MASK] = {
4337 		.name = "mask",
4338 		.help = "specify bit-mask with relevant bits set to one",
4339 		.call = parse_vc_spec,
4340 	},
4341 	[ITEM_PARAM_PREFIX] = {
4342 		.name = "prefix",
4343 		.help = "generate bit-mask from a prefix length",
4344 		.call = parse_vc_spec,
4345 	},
4346 	[ITEM_NEXT] = {
4347 		.name = "/",
4348 		.help = "specify next pattern item",
4349 		.next = NEXT(next_item),
4350 	},
4351 	[ITEM_END] = {
4352 		.name = "end",
4353 		.help = "end list of pattern items",
4354 		.priv = PRIV_ITEM(END, 0),
4355 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4356 		.call = parse_vc,
4357 	},
4358 	[ITEM_VOID] = {
4359 		.name = "void",
4360 		.help = "no-op pattern item",
4361 		.priv = PRIV_ITEM(VOID, 0),
4362 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4363 		.call = parse_vc,
4364 	},
4365 	[ITEM_INVERT] = {
4366 		.name = "invert",
4367 		.help = "perform actions when pattern does not match",
4368 		.priv = PRIV_ITEM(INVERT, 0),
4369 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4370 		.call = parse_vc,
4371 	},
4372 	[ITEM_ANY] = {
4373 		.name = "any",
4374 		.help = "match any protocol for the current layer",
4375 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4376 		.next = NEXT(item_any),
4377 		.call = parse_vc,
4378 	},
4379 	[ITEM_ANY_NUM] = {
4380 		.name = "num",
4381 		.help = "number of layers covered",
4382 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4383 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4384 	},
4385 	[ITEM_PORT_ID] = {
4386 		.name = "port_id",
4387 		.help = "match traffic from/to a given DPDK port ID",
4388 		.priv = PRIV_ITEM(PORT_ID,
4389 				  sizeof(struct rte_flow_item_port_id)),
4390 		.next = NEXT(item_port_id),
4391 		.call = parse_vc,
4392 	},
4393 	[ITEM_PORT_ID_ID] = {
4394 		.name = "id",
4395 		.help = "DPDK port ID",
4396 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4397 			     item_param),
4398 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4399 	},
4400 	[ITEM_MARK] = {
4401 		.name = "mark",
4402 		.help = "match traffic against value set in previously matched rule",
4403 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4404 		.next = NEXT(item_mark),
4405 		.call = parse_vc,
4406 	},
4407 	[ITEM_MARK_ID] = {
4408 		.name = "id",
4409 		.help = "Integer value to match against",
4410 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4411 			     item_param),
4412 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4413 	},
4414 	[ITEM_RAW] = {
4415 		.name = "raw",
4416 		.help = "match an arbitrary byte string",
4417 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4418 		.next = NEXT(item_raw),
4419 		.call = parse_vc,
4420 	},
4421 	[ITEM_RAW_RELATIVE] = {
4422 		.name = "relative",
4423 		.help = "look for pattern after the previous item",
4424 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4425 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4426 					   relative, 1)),
4427 	},
4428 	[ITEM_RAW_SEARCH] = {
4429 		.name = "search",
4430 		.help = "search pattern from offset (see also limit)",
4431 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4432 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4433 					   search, 1)),
4434 	},
4435 	[ITEM_RAW_OFFSET] = {
4436 		.name = "offset",
4437 		.help = "absolute or relative offset for pattern",
4438 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4439 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4440 	},
4441 	[ITEM_RAW_LIMIT] = {
4442 		.name = "limit",
4443 		.help = "search area limit for start of pattern",
4444 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4445 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4446 	},
4447 	[ITEM_RAW_PATTERN] = {
4448 		.name = "pattern",
4449 		.help = "byte string to look for",
4450 		.next = NEXT(item_raw,
4451 			     NEXT_ENTRY(COMMON_STRING),
4452 			     NEXT_ENTRY(ITEM_PARAM_IS,
4453 					ITEM_PARAM_SPEC,
4454 					ITEM_PARAM_MASK)),
4455 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4456 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4457 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4458 					    ITEM_RAW_PATTERN_SIZE)),
4459 	},
4460 	[ITEM_RAW_PATTERN_HEX] = {
4461 		.name = "pattern_hex",
4462 		.help = "hex string to look for",
4463 		.next = NEXT(item_raw,
4464 			     NEXT_ENTRY(COMMON_HEX),
4465 			     NEXT_ENTRY(ITEM_PARAM_IS,
4466 					ITEM_PARAM_SPEC,
4467 					ITEM_PARAM_MASK)),
4468 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4469 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4470 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4471 					    ITEM_RAW_PATTERN_SIZE)),
4472 	},
4473 	[ITEM_ETH] = {
4474 		.name = "eth",
4475 		.help = "match Ethernet header",
4476 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4477 		.next = NEXT(item_eth),
4478 		.call = parse_vc,
4479 	},
4480 	[ITEM_ETH_DST] = {
4481 		.name = "dst",
4482 		.help = "destination MAC",
4483 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4484 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4485 	},
4486 	[ITEM_ETH_SRC] = {
4487 		.name = "src",
4488 		.help = "source MAC",
4489 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4490 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4491 	},
4492 	[ITEM_ETH_TYPE] = {
4493 		.name = "type",
4494 		.help = "EtherType",
4495 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4496 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4497 	},
4498 	[ITEM_ETH_HAS_VLAN] = {
4499 		.name = "has_vlan",
4500 		.help = "packet header contains VLAN",
4501 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4502 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4503 					   has_vlan, 1)),
4504 	},
4505 	[ITEM_VLAN] = {
4506 		.name = "vlan",
4507 		.help = "match 802.1Q/ad VLAN tag",
4508 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4509 		.next = NEXT(item_vlan),
4510 		.call = parse_vc,
4511 	},
4512 	[ITEM_VLAN_TCI] = {
4513 		.name = "tci",
4514 		.help = "tag control information",
4515 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4516 			     item_param),
4517 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4518 	},
4519 	[ITEM_VLAN_PCP] = {
4520 		.name = "pcp",
4521 		.help = "priority code point",
4522 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4523 			     item_param),
4524 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4525 						  hdr.vlan_tci, "\xe0\x00")),
4526 	},
4527 	[ITEM_VLAN_DEI] = {
4528 		.name = "dei",
4529 		.help = "drop eligible indicator",
4530 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4531 			     item_param),
4532 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4533 						  hdr.vlan_tci, "\x10\x00")),
4534 	},
4535 	[ITEM_VLAN_VID] = {
4536 		.name = "vid",
4537 		.help = "VLAN identifier",
4538 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4539 			     item_param),
4540 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4541 						  hdr.vlan_tci, "\x0f\xff")),
4542 	},
4543 	[ITEM_VLAN_INNER_TYPE] = {
4544 		.name = "inner_type",
4545 		.help = "inner EtherType",
4546 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4547 			     item_param),
4548 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4549 					     hdr.eth_proto)),
4550 	},
4551 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4552 		.name = "has_more_vlan",
4553 		.help = "packet header contains another VLAN",
4554 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4555 			     item_param),
4556 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4557 					   has_more_vlan, 1)),
4558 	},
4559 	[ITEM_IPV4] = {
4560 		.name = "ipv4",
4561 		.help = "match IPv4 header",
4562 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4563 		.next = NEXT(item_ipv4),
4564 		.call = parse_vc,
4565 	},
4566 	[ITEM_IPV4_VER_IHL] = {
4567 		.name = "version_ihl",
4568 		.help = "match header length",
4569 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4570 			     item_param),
4571 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4572 				     hdr.version_ihl)),
4573 	},
4574 	[ITEM_IPV4_TOS] = {
4575 		.name = "tos",
4576 		.help = "type of service",
4577 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4578 			     item_param),
4579 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4580 					     hdr.type_of_service)),
4581 	},
4582 	[ITEM_IPV4_LENGTH] = {
4583 		.name = "length",
4584 		.help = "total length",
4585 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4586 			     item_param),
4587 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4588 					     hdr.total_length)),
4589 	},
4590 	[ITEM_IPV4_ID] = {
4591 		.name = "packet_id",
4592 		.help = "fragment packet id",
4593 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4594 			     item_param),
4595 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4596 					     hdr.packet_id)),
4597 	},
4598 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4599 		.name = "fragment_offset",
4600 		.help = "fragmentation flags and fragment offset",
4601 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4602 			     item_param),
4603 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4604 					     hdr.fragment_offset)),
4605 	},
4606 	[ITEM_IPV4_TTL] = {
4607 		.name = "ttl",
4608 		.help = "time to live",
4609 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4610 			     item_param),
4611 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4612 					     hdr.time_to_live)),
4613 	},
4614 	[ITEM_IPV4_PROTO] = {
4615 		.name = "proto",
4616 		.help = "next protocol ID",
4617 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4618 			     item_param),
4619 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4620 					     hdr.next_proto_id)),
4621 	},
4622 	[ITEM_IPV4_SRC] = {
4623 		.name = "src",
4624 		.help = "source address",
4625 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4626 			     item_param),
4627 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4628 					     hdr.src_addr)),
4629 	},
4630 	[ITEM_IPV4_DST] = {
4631 		.name = "dst",
4632 		.help = "destination address",
4633 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4634 			     item_param),
4635 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4636 					     hdr.dst_addr)),
4637 	},
4638 	[ITEM_IPV6] = {
4639 		.name = "ipv6",
4640 		.help = "match IPv6 header",
4641 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4642 		.next = NEXT(item_ipv6),
4643 		.call = parse_vc,
4644 	},
4645 	[ITEM_IPV6_TC] = {
4646 		.name = "tc",
4647 		.help = "traffic class",
4648 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4649 			     item_param),
4650 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4651 						  hdr.vtc_flow,
4652 						  "\x0f\xf0\x00\x00")),
4653 	},
4654 	[ITEM_IPV6_FLOW] = {
4655 		.name = "flow",
4656 		.help = "flow label",
4657 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4658 			     item_param),
4659 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4660 						  hdr.vtc_flow,
4661 						  "\x00\x0f\xff\xff")),
4662 	},
4663 	[ITEM_IPV6_LEN] = {
4664 		.name = "length",
4665 		.help = "payload length",
4666 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4667 			     item_param),
4668 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4669 					     hdr.payload_len)),
4670 	},
4671 	[ITEM_IPV6_PROTO] = {
4672 		.name = "proto",
4673 		.help = "protocol (next header)",
4674 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4675 			     item_param),
4676 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4677 					     hdr.proto)),
4678 	},
4679 	[ITEM_IPV6_HOP] = {
4680 		.name = "hop",
4681 		.help = "hop limit",
4682 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4683 			     item_param),
4684 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4685 					     hdr.hop_limits)),
4686 	},
4687 	[ITEM_IPV6_SRC] = {
4688 		.name = "src",
4689 		.help = "source address",
4690 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4691 			     item_param),
4692 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4693 					     hdr.src_addr)),
4694 	},
4695 	[ITEM_IPV6_DST] = {
4696 		.name = "dst",
4697 		.help = "destination address",
4698 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4699 			     item_param),
4700 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4701 					     hdr.dst_addr)),
4702 	},
4703 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4704 		.name = "has_frag_ext",
4705 		.help = "fragment packet attribute",
4706 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4707 			     item_param),
4708 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4709 					   has_frag_ext, 1)),
4710 	},
4711 	[ITEM_IPV6_ROUTING_EXT] = {
4712 		.name = "ipv6_routing_ext",
4713 		.help = "match IPv6 routing extension header",
4714 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4715 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4716 		.next = NEXT(item_ipv6_routing_ext),
4717 		.call = parse_vc,
4718 	},
4719 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4720 		.name = "ext_type",
4721 		.help = "match IPv6 routing extension header type",
4722 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4723 			     item_param),
4724 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4725 					     hdr.type)),
4726 	},
4727 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4728 		.name = "ext_next_hdr",
4729 		.help = "match IPv6 routing extension header next header type",
4730 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4731 			     item_param),
4732 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4733 					     hdr.next_hdr)),
4734 	},
4735 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4736 		.name = "ext_seg_left",
4737 		.help = "match IPv6 routing extension header segment left",
4738 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4739 			     item_param),
4740 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4741 					     hdr.segments_left)),
4742 	},
4743 	[ITEM_ICMP] = {
4744 		.name = "icmp",
4745 		.help = "match ICMP header",
4746 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4747 		.next = NEXT(item_icmp),
4748 		.call = parse_vc,
4749 	},
4750 	[ITEM_ICMP_TYPE] = {
4751 		.name = "type",
4752 		.help = "ICMP packet type",
4753 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4754 			     item_param),
4755 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4756 					     hdr.icmp_type)),
4757 	},
4758 	[ITEM_ICMP_CODE] = {
4759 		.name = "code",
4760 		.help = "ICMP packet code",
4761 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4762 			     item_param),
4763 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4764 					     hdr.icmp_code)),
4765 	},
4766 	[ITEM_ICMP_IDENT] = {
4767 		.name = "ident",
4768 		.help = "ICMP packet identifier",
4769 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4770 			     item_param),
4771 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4772 					     hdr.icmp_ident)),
4773 	},
4774 	[ITEM_ICMP_SEQ] = {
4775 		.name = "seq",
4776 		.help = "ICMP packet sequence number",
4777 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4778 			     item_param),
4779 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4780 					     hdr.icmp_seq_nb)),
4781 	},
4782 	[ITEM_UDP] = {
4783 		.name = "udp",
4784 		.help = "match UDP header",
4785 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4786 		.next = NEXT(item_udp),
4787 		.call = parse_vc,
4788 	},
4789 	[ITEM_UDP_SRC] = {
4790 		.name = "src",
4791 		.help = "UDP source port",
4792 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4793 			     item_param),
4794 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4795 					     hdr.src_port)),
4796 	},
4797 	[ITEM_UDP_DST] = {
4798 		.name = "dst",
4799 		.help = "UDP destination port",
4800 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4801 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4802 					     hdr.dst_port)),
4803 	},
4804 	[ITEM_TCP] = {
4805 		.name = "tcp",
4806 		.help = "match TCP header",
4807 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4808 		.next = NEXT(item_tcp),
4809 		.call = parse_vc,
4810 	},
4811 	[ITEM_TCP_SRC] = {
4812 		.name = "src",
4813 		.help = "TCP source port",
4814 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4815 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4816 					     hdr.src_port)),
4817 	},
4818 	[ITEM_TCP_DST] = {
4819 		.name = "dst",
4820 		.help = "TCP destination port",
4821 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4822 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4823 					     hdr.dst_port)),
4824 	},
4825 	[ITEM_TCP_FLAGS] = {
4826 		.name = "flags",
4827 		.help = "TCP flags",
4828 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4829 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4830 					     hdr.tcp_flags)),
4831 	},
4832 	[ITEM_SCTP] = {
4833 		.name = "sctp",
4834 		.help = "match SCTP header",
4835 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4836 		.next = NEXT(item_sctp),
4837 		.call = parse_vc,
4838 	},
4839 	[ITEM_SCTP_SRC] = {
4840 		.name = "src",
4841 		.help = "SCTP source port",
4842 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4843 			     item_param),
4844 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4845 					     hdr.src_port)),
4846 	},
4847 	[ITEM_SCTP_DST] = {
4848 		.name = "dst",
4849 		.help = "SCTP destination port",
4850 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4851 			     item_param),
4852 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4853 					     hdr.dst_port)),
4854 	},
4855 	[ITEM_SCTP_TAG] = {
4856 		.name = "tag",
4857 		.help = "validation tag",
4858 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4859 			     item_param),
4860 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4861 					     hdr.tag)),
4862 	},
4863 	[ITEM_SCTP_CKSUM] = {
4864 		.name = "cksum",
4865 		.help = "checksum",
4866 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4867 			     item_param),
4868 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4869 					     hdr.cksum)),
4870 	},
4871 	[ITEM_VXLAN] = {
4872 		.name = "vxlan",
4873 		.help = "match VXLAN header",
4874 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4875 		.next = NEXT(item_vxlan),
4876 		.call = parse_vc,
4877 	},
4878 	[ITEM_VXLAN_VNI] = {
4879 		.name = "vni",
4880 		.help = "VXLAN identifier",
4881 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4882 			     item_param),
4883 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4884 	},
4885 	[ITEM_VXLAN_LAST_RSVD] = {
4886 		.name = "last_rsvd",
4887 		.help = "VXLAN last reserved bits",
4888 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4889 			     item_param),
4890 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4891 					     hdr.rsvd1)),
4892 	},
4893 	[ITEM_E_TAG] = {
4894 		.name = "e_tag",
4895 		.help = "match E-Tag header",
4896 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4897 		.next = NEXT(item_e_tag),
4898 		.call = parse_vc,
4899 	},
4900 	[ITEM_E_TAG_GRP_ECID_B] = {
4901 		.name = "grp_ecid_b",
4902 		.help = "GRP and E-CID base",
4903 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4904 			     item_param),
4905 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4906 						  rsvd_grp_ecid_b,
4907 						  "\x3f\xff")),
4908 	},
4909 	[ITEM_NVGRE] = {
4910 		.name = "nvgre",
4911 		.help = "match NVGRE header",
4912 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4913 		.next = NEXT(item_nvgre),
4914 		.call = parse_vc,
4915 	},
4916 	[ITEM_NVGRE_TNI] = {
4917 		.name = "tni",
4918 		.help = "virtual subnet ID",
4919 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4920 			     item_param),
4921 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4922 	},
4923 	[ITEM_MPLS] = {
4924 		.name = "mpls",
4925 		.help = "match MPLS header",
4926 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4927 		.next = NEXT(item_mpls),
4928 		.call = parse_vc,
4929 	},
4930 	[ITEM_MPLS_LABEL] = {
4931 		.name = "label",
4932 		.help = "MPLS label",
4933 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4934 			     item_param),
4935 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4936 						  label_tc_s,
4937 						  "\xff\xff\xf0")),
4938 	},
4939 	[ITEM_MPLS_TC] = {
4940 		.name = "tc",
4941 		.help = "MPLS Traffic Class",
4942 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4943 			     item_param),
4944 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4945 						  label_tc_s,
4946 						  "\x00\x00\x0e")),
4947 	},
4948 	[ITEM_MPLS_S] = {
4949 		.name = "s",
4950 		.help = "MPLS Bottom-of-Stack",
4951 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4952 			     item_param),
4953 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4954 						  label_tc_s,
4955 						  "\x00\x00\x01")),
4956 	},
4957 	[ITEM_MPLS_TTL] = {
4958 		.name = "ttl",
4959 		.help = "MPLS Time-to-Live",
4960 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4961 			     item_param),
4962 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
4963 	},
4964 	[ITEM_GRE] = {
4965 		.name = "gre",
4966 		.help = "match GRE header",
4967 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4968 		.next = NEXT(item_gre),
4969 		.call = parse_vc,
4970 	},
4971 	[ITEM_GRE_PROTO] = {
4972 		.name = "protocol",
4973 		.help = "GRE protocol type",
4974 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4975 			     item_param),
4976 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4977 					     protocol)),
4978 	},
4979 	[ITEM_GRE_C_RSVD0_VER] = {
4980 		.name = "c_rsvd0_ver",
4981 		.help =
4982 			"checksum (1b), undefined (1b), key bit (1b),"
4983 			" sequence number (1b), reserved 0 (9b),"
4984 			" version (3b)",
4985 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4986 			     item_param),
4987 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4988 					     c_rsvd0_ver)),
4989 	},
4990 	[ITEM_GRE_C_BIT] = {
4991 		.name = "c_bit",
4992 		.help = "checksum bit (C)",
4993 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
4994 			     item_param),
4995 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4996 						  c_rsvd0_ver,
4997 						  "\x80\x00\x00\x00")),
4998 	},
4999 	[ITEM_GRE_S_BIT] = {
5000 		.name = "s_bit",
5001 		.help = "sequence number bit (S)",
5002 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5003 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5004 						  c_rsvd0_ver,
5005 						  "\x10\x00\x00\x00")),
5006 	},
5007 	[ITEM_GRE_K_BIT] = {
5008 		.name = "k_bit",
5009 		.help = "key bit (K)",
5010 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5011 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5012 						  c_rsvd0_ver,
5013 						  "\x20\x00\x00\x00")),
5014 	},
5015 	[ITEM_FUZZY] = {
5016 		.name = "fuzzy",
5017 		.help = "fuzzy pattern match, expect faster than default",
5018 		.priv = PRIV_ITEM(FUZZY,
5019 				sizeof(struct rte_flow_item_fuzzy)),
5020 		.next = NEXT(item_fuzzy),
5021 		.call = parse_vc,
5022 	},
5023 	[ITEM_FUZZY_THRESH] = {
5024 		.name = "thresh",
5025 		.help = "match accuracy threshold",
5026 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5027 			     item_param),
5028 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5029 					thresh)),
5030 	},
5031 	[ITEM_GTP] = {
5032 		.name = "gtp",
5033 		.help = "match GTP header",
5034 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5035 		.next = NEXT(item_gtp),
5036 		.call = parse_vc,
5037 	},
5038 	[ITEM_GTP_FLAGS] = {
5039 		.name = "v_pt_rsv_flags",
5040 		.help = "GTP flags",
5041 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5042 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5043 					hdr.gtp_hdr_info)),
5044 	},
5045 	[ITEM_GTP_MSG_TYPE] = {
5046 		.name = "msg_type",
5047 		.help = "GTP message type",
5048 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5049 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5050 	},
5051 	[ITEM_GTP_TEID] = {
5052 		.name = "teid",
5053 		.help = "tunnel endpoint identifier",
5054 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5055 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5056 	},
5057 	[ITEM_GTPC] = {
5058 		.name = "gtpc",
5059 		.help = "match GTP header",
5060 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5061 		.next = NEXT(item_gtp),
5062 		.call = parse_vc,
5063 	},
5064 	[ITEM_GTPU] = {
5065 		.name = "gtpu",
5066 		.help = "match GTP header",
5067 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5068 		.next = NEXT(item_gtp),
5069 		.call = parse_vc,
5070 	},
5071 	[ITEM_GENEVE] = {
5072 		.name = "geneve",
5073 		.help = "match GENEVE header",
5074 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5075 		.next = NEXT(item_geneve),
5076 		.call = parse_vc,
5077 	},
5078 	[ITEM_GENEVE_VNI] = {
5079 		.name = "vni",
5080 		.help = "virtual network identifier",
5081 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5082 			     item_param),
5083 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5084 	},
5085 	[ITEM_GENEVE_PROTO] = {
5086 		.name = "protocol",
5087 		.help = "GENEVE protocol type",
5088 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5089 			     item_param),
5090 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5091 					     protocol)),
5092 	},
5093 	[ITEM_GENEVE_OPTLEN] = {
5094 		.name = "optlen",
5095 		.help = "GENEVE options length in dwords",
5096 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5097 			     item_param),
5098 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5099 						  ver_opt_len_o_c_rsvd0,
5100 						  "\x3f\x00")),
5101 	},
5102 	[ITEM_VXLAN_GPE] = {
5103 		.name = "vxlan-gpe",
5104 		.help = "match VXLAN-GPE header",
5105 		.priv = PRIV_ITEM(VXLAN_GPE,
5106 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5107 		.next = NEXT(item_vxlan_gpe),
5108 		.call = parse_vc,
5109 	},
5110 	[ITEM_VXLAN_GPE_VNI] = {
5111 		.name = "vni",
5112 		.help = "VXLAN-GPE identifier",
5113 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5114 			     item_param),
5115 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5116 					     hdr.vni)),
5117 	},
5118 	[ITEM_VXLAN_GPE_PROTO] = {
5119 		.name = "protocol",
5120 		.help = "VXLAN-GPE next protocol",
5121 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5122 			     item_param),
5123 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5124 					     protocol)),
5125 	},
5126 	[ITEM_ARP_ETH_IPV4] = {
5127 		.name = "arp_eth_ipv4",
5128 		.help = "match ARP header for Ethernet/IPv4",
5129 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5130 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5131 		.next = NEXT(item_arp_eth_ipv4),
5132 		.call = parse_vc,
5133 	},
5134 	[ITEM_ARP_ETH_IPV4_SHA] = {
5135 		.name = "sha",
5136 		.help = "sender hardware address",
5137 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5138 			     item_param),
5139 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5140 					     hdr.arp_data.arp_sha)),
5141 	},
5142 	[ITEM_ARP_ETH_IPV4_SPA] = {
5143 		.name = "spa",
5144 		.help = "sender IPv4 address",
5145 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5146 			     item_param),
5147 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5148 					     hdr.arp_data.arp_sip)),
5149 	},
5150 	[ITEM_ARP_ETH_IPV4_THA] = {
5151 		.name = "tha",
5152 		.help = "target hardware address",
5153 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5154 			     item_param),
5155 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5156 					     hdr.arp_data.arp_tha)),
5157 	},
5158 	[ITEM_ARP_ETH_IPV4_TPA] = {
5159 		.name = "tpa",
5160 		.help = "target IPv4 address",
5161 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5162 			     item_param),
5163 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5164 					     hdr.arp_data.arp_tip)),
5165 	},
5166 	[ITEM_IPV6_EXT] = {
5167 		.name = "ipv6_ext",
5168 		.help = "match presence of any IPv6 extension header",
5169 		.priv = PRIV_ITEM(IPV6_EXT,
5170 				  sizeof(struct rte_flow_item_ipv6_ext)),
5171 		.next = NEXT(item_ipv6_ext),
5172 		.call = parse_vc,
5173 	},
5174 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5175 		.name = "next_hdr",
5176 		.help = "next header",
5177 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5178 			     item_param),
5179 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5180 					     next_hdr)),
5181 	},
5182 	[ITEM_IPV6_FRAG_EXT] = {
5183 		.name = "ipv6_frag_ext",
5184 		.help = "match presence of IPv6 fragment extension header",
5185 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5186 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5187 		.next = NEXT(item_ipv6_frag_ext),
5188 		.call = parse_vc,
5189 	},
5190 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5191 		.name = "next_hdr",
5192 		.help = "next header",
5193 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5194 			     item_param),
5195 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5196 					hdr.next_header)),
5197 	},
5198 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5199 		.name = "frag_data",
5200 		.help = "fragment flags and offset",
5201 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5202 			     item_param),
5203 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5204 					     hdr.frag_data)),
5205 	},
5206 	[ITEM_IPV6_FRAG_EXT_ID] = {
5207 		.name = "packet_id",
5208 		.help = "fragment packet id",
5209 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5210 			     item_param),
5211 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5212 					     hdr.id)),
5213 	},
5214 	[ITEM_ICMP6] = {
5215 		.name = "icmp6",
5216 		.help = "match any ICMPv6 header",
5217 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5218 		.next = NEXT(item_icmp6),
5219 		.call = parse_vc,
5220 	},
5221 	[ITEM_ICMP6_TYPE] = {
5222 		.name = "type",
5223 		.help = "ICMPv6 type",
5224 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5225 			     item_param),
5226 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5227 					     type)),
5228 	},
5229 	[ITEM_ICMP6_CODE] = {
5230 		.name = "code",
5231 		.help = "ICMPv6 code",
5232 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5233 			     item_param),
5234 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5235 					     code)),
5236 	},
5237 	[ITEM_ICMP6_ECHO_REQUEST] = {
5238 		.name = "icmp6_echo_request",
5239 		.help = "match ICMPv6 echo request",
5240 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5241 				  sizeof(struct rte_flow_item_icmp6_echo)),
5242 		.next = NEXT(item_icmp6_echo_request),
5243 		.call = parse_vc,
5244 	},
5245 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5246 		.name = "ident",
5247 		.help = "ICMPv6 echo request identifier",
5248 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5249 			     item_param),
5250 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5251 					     hdr.identifier)),
5252 	},
5253 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5254 		.name = "seq",
5255 		.help = "ICMPv6 echo request sequence",
5256 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5257 			     item_param),
5258 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5259 					     hdr.sequence)),
5260 	},
5261 	[ITEM_ICMP6_ECHO_REPLY] = {
5262 		.name = "icmp6_echo_reply",
5263 		.help = "match ICMPv6 echo reply",
5264 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5265 				  sizeof(struct rte_flow_item_icmp6_echo)),
5266 		.next = NEXT(item_icmp6_echo_reply),
5267 		.call = parse_vc,
5268 	},
5269 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5270 		.name = "ident",
5271 		.help = "ICMPv6 echo reply identifier",
5272 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5273 			     item_param),
5274 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5275 					     hdr.identifier)),
5276 	},
5277 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5278 		.name = "seq",
5279 		.help = "ICMPv6 echo reply sequence",
5280 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5281 			     item_param),
5282 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5283 					     hdr.sequence)),
5284 	},
5285 	[ITEM_ICMP6_ND_NS] = {
5286 		.name = "icmp6_nd_ns",
5287 		.help = "match ICMPv6 neighbor discovery solicitation",
5288 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5289 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5290 		.next = NEXT(item_icmp6_nd_ns),
5291 		.call = parse_vc,
5292 	},
5293 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5294 		.name = "target_addr",
5295 		.help = "target address",
5296 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5297 			     item_param),
5298 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5299 					     target_addr)),
5300 	},
5301 	[ITEM_ICMP6_ND_NA] = {
5302 		.name = "icmp6_nd_na",
5303 		.help = "match ICMPv6 neighbor discovery advertisement",
5304 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5305 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5306 		.next = NEXT(item_icmp6_nd_na),
5307 		.call = parse_vc,
5308 	},
5309 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5310 		.name = "target_addr",
5311 		.help = "target address",
5312 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5313 			     item_param),
5314 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5315 					     target_addr)),
5316 	},
5317 	[ITEM_ICMP6_ND_OPT] = {
5318 		.name = "icmp6_nd_opt",
5319 		.help = "match presence of any ICMPv6 neighbor discovery"
5320 			" option",
5321 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5322 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5323 		.next = NEXT(item_icmp6_nd_opt),
5324 		.call = parse_vc,
5325 	},
5326 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5327 		.name = "type",
5328 		.help = "ND option type",
5329 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5330 			     item_param),
5331 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5332 					     type)),
5333 	},
5334 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5335 		.name = "icmp6_nd_opt_sla_eth",
5336 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5337 			" link-layer address option",
5338 		.priv = PRIV_ITEM
5339 			(ICMP6_ND_OPT_SLA_ETH,
5340 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5341 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5342 		.call = parse_vc,
5343 	},
5344 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5345 		.name = "sla",
5346 		.help = "source Ethernet LLA",
5347 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5348 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5349 		.args = ARGS(ARGS_ENTRY_HTON
5350 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5351 	},
5352 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5353 		.name = "icmp6_nd_opt_tla_eth",
5354 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5355 			" link-layer address option",
5356 		.priv = PRIV_ITEM
5357 			(ICMP6_ND_OPT_TLA_ETH,
5358 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5359 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5360 		.call = parse_vc,
5361 	},
5362 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5363 		.name = "tla",
5364 		.help = "target Ethernet LLA",
5365 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5366 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5367 		.args = ARGS(ARGS_ENTRY_HTON
5368 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5369 	},
5370 	[ITEM_META] = {
5371 		.name = "meta",
5372 		.help = "match metadata header",
5373 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5374 		.next = NEXT(item_meta),
5375 		.call = parse_vc,
5376 	},
5377 	[ITEM_META_DATA] = {
5378 		.name = "data",
5379 		.help = "metadata value",
5380 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5381 			     item_param),
5382 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5383 					     data, "\xff\xff\xff\xff")),
5384 	},
5385 	[ITEM_RANDOM] = {
5386 		.name = "random",
5387 		.help = "match random value",
5388 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5389 		.next = NEXT(item_random),
5390 		.call = parse_vc,
5391 	},
5392 	[ITEM_RANDOM_VALUE] = {
5393 		.name = "value",
5394 		.help = "random value",
5395 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5396 			     item_param),
5397 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5398 					     value, "\xff\xff")),
5399 	},
5400 	[ITEM_GRE_KEY] = {
5401 		.name = "gre_key",
5402 		.help = "match GRE key",
5403 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5404 		.next = NEXT(item_gre_key),
5405 		.call = parse_vc,
5406 	},
5407 	[ITEM_GRE_KEY_VALUE] = {
5408 		.name = "value",
5409 		.help = "key value",
5410 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5411 			     item_param),
5412 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5413 	},
5414 	[ITEM_GRE_OPTION] = {
5415 		.name = "gre_option",
5416 		.help = "match GRE optional fields",
5417 		.priv = PRIV_ITEM(GRE_OPTION,
5418 				  sizeof(struct rte_flow_item_gre_opt)),
5419 		.next = NEXT(item_gre_option),
5420 		.call = parse_vc,
5421 	},
5422 	[ITEM_GRE_OPTION_CHECKSUM] = {
5423 		.name = "checksum",
5424 		.help = "match GRE checksum",
5425 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5426 			     item_param),
5427 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5428 					     checksum_rsvd.checksum)),
5429 	},
5430 	[ITEM_GRE_OPTION_KEY] = {
5431 		.name = "key",
5432 		.help = "match GRE key",
5433 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5434 			     item_param),
5435 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5436 					     key.key)),
5437 	},
5438 	[ITEM_GRE_OPTION_SEQUENCE] = {
5439 		.name = "sequence",
5440 		.help = "match GRE sequence",
5441 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5442 			     item_param),
5443 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5444 					     sequence.sequence)),
5445 	},
5446 	[ITEM_GTP_PSC] = {
5447 		.name = "gtp_psc",
5448 		.help = "match GTP extension header with type 0x85",
5449 		.priv = PRIV_ITEM(GTP_PSC,
5450 				sizeof(struct rte_flow_item_gtp_psc)),
5451 		.next = NEXT(item_gtp_psc),
5452 		.call = parse_vc,
5453 	},
5454 	[ITEM_GTP_PSC_QFI] = {
5455 		.name = "qfi",
5456 		.help = "QoS flow identifier",
5457 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5458 			     item_param),
5459 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5460 					hdr.qfi, 6)),
5461 	},
5462 	[ITEM_GTP_PSC_PDU_T] = {
5463 		.name = "pdu_t",
5464 		.help = "PDU type",
5465 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5466 			     item_param),
5467 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5468 					hdr.type, 4)),
5469 	},
5470 	[ITEM_PPPOES] = {
5471 		.name = "pppoes",
5472 		.help = "match PPPoE session header",
5473 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5474 		.next = NEXT(item_pppoes),
5475 		.call = parse_vc,
5476 	},
5477 	[ITEM_PPPOED] = {
5478 		.name = "pppoed",
5479 		.help = "match PPPoE discovery header",
5480 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5481 		.next = NEXT(item_pppoed),
5482 		.call = parse_vc,
5483 	},
5484 	[ITEM_PPPOE_SEID] = {
5485 		.name = "seid",
5486 		.help = "session identifier",
5487 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5488 			     item_param),
5489 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5490 					session_id)),
5491 	},
5492 	[ITEM_PPPOE_PROTO_ID] = {
5493 		.name = "pppoe_proto_id",
5494 		.help = "match PPPoE session protocol identifier",
5495 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5496 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5497 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5498 			     item_param),
5499 		.args = ARGS(ARGS_ENTRY_HTON
5500 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5501 		.call = parse_vc,
5502 	},
5503 	[ITEM_HIGIG2] = {
5504 		.name = "higig2",
5505 		.help = "matches higig2 header",
5506 		.priv = PRIV_ITEM(HIGIG2,
5507 				sizeof(struct rte_flow_item_higig2_hdr)),
5508 		.next = NEXT(item_higig2),
5509 		.call = parse_vc,
5510 	},
5511 	[ITEM_HIGIG2_CLASSIFICATION] = {
5512 		.name = "classification",
5513 		.help = "matches classification of higig2 header",
5514 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5515 			     item_param),
5516 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5517 					hdr.ppt1.classification)),
5518 	},
5519 	[ITEM_HIGIG2_VID] = {
5520 		.name = "vid",
5521 		.help = "matches vid of higig2 header",
5522 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5523 			     item_param),
5524 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5525 					hdr.ppt1.vid)),
5526 	},
5527 	[ITEM_TAG] = {
5528 		.name = "tag",
5529 		.help = "match tag value",
5530 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5531 		.next = NEXT(item_tag),
5532 		.call = parse_vc,
5533 	},
5534 	[ITEM_TAG_DATA] = {
5535 		.name = "data",
5536 		.help = "tag value to match",
5537 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5538 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5539 	},
5540 	[ITEM_TAG_INDEX] = {
5541 		.name = "index",
5542 		.help = "index of tag array to match",
5543 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5544 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5545 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5546 	},
5547 	[ITEM_L2TPV3OIP] = {
5548 		.name = "l2tpv3oip",
5549 		.help = "match L2TPv3 over IP header",
5550 		.priv = PRIV_ITEM(L2TPV3OIP,
5551 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5552 		.next = NEXT(item_l2tpv3oip),
5553 		.call = parse_vc,
5554 	},
5555 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5556 		.name = "session_id",
5557 		.help = "session identifier",
5558 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5559 			     item_param),
5560 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5561 					     session_id)),
5562 	},
5563 	[ITEM_ESP] = {
5564 		.name = "esp",
5565 		.help = "match ESP header",
5566 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5567 		.next = NEXT(item_esp),
5568 		.call = parse_vc,
5569 	},
5570 	[ITEM_ESP_SPI] = {
5571 		.name = "spi",
5572 		.help = "security policy index",
5573 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5574 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5575 				hdr.spi)),
5576 	},
5577 	[ITEM_AH] = {
5578 		.name = "ah",
5579 		.help = "match AH header",
5580 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5581 		.next = NEXT(item_ah),
5582 		.call = parse_vc,
5583 	},
5584 	[ITEM_AH_SPI] = {
5585 		.name = "spi",
5586 		.help = "security parameters index",
5587 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5588 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5589 	},
5590 	[ITEM_PFCP] = {
5591 		.name = "pfcp",
5592 		.help = "match pfcp header",
5593 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5594 		.next = NEXT(item_pfcp),
5595 		.call = parse_vc,
5596 	},
5597 	[ITEM_PFCP_S_FIELD] = {
5598 		.name = "s_field",
5599 		.help = "S field",
5600 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5601 			     item_param),
5602 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5603 				s_field)),
5604 	},
5605 	[ITEM_PFCP_SEID] = {
5606 		.name = "seid",
5607 		.help = "session endpoint identifier",
5608 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5609 			     item_param),
5610 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5611 	},
5612 	[ITEM_ECPRI] = {
5613 		.name = "ecpri",
5614 		.help = "match eCPRI header",
5615 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5616 		.next = NEXT(item_ecpri),
5617 		.call = parse_vc,
5618 	},
5619 	[ITEM_ECPRI_COMMON] = {
5620 		.name = "common",
5621 		.help = "eCPRI common header",
5622 		.next = NEXT(item_ecpri_common),
5623 	},
5624 	[ITEM_ECPRI_COMMON_TYPE] = {
5625 		.name = "type",
5626 		.help = "type of common header",
5627 		.next = NEXT(item_ecpri_common_type),
5628 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5629 	},
5630 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5631 		.name = "iq_data",
5632 		.help = "Type #0: IQ Data",
5633 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5634 					ITEM_NEXT)),
5635 		.call = parse_vc_item_ecpri_type,
5636 	},
5637 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5638 		.name = "pc_id",
5639 		.help = "Physical Channel ID",
5640 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5641 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5642 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5643 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5644 				hdr.type0.pc_id)),
5645 	},
5646 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5647 		.name = "rtc_ctrl",
5648 		.help = "Type #2: Real-Time Control Data",
5649 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5650 					ITEM_NEXT)),
5651 		.call = parse_vc_item_ecpri_type,
5652 	},
5653 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5654 		.name = "rtc_id",
5655 		.help = "Real-Time Control Data ID",
5656 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5657 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5658 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5659 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5660 				hdr.type2.rtc_id)),
5661 	},
5662 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5663 		.name = "delay_measure",
5664 		.help = "Type #5: One-Way Delay Measurement",
5665 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5666 					ITEM_NEXT)),
5667 		.call = parse_vc_item_ecpri_type,
5668 	},
5669 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5670 		.name = "msr_id",
5671 		.help = "Measurement ID",
5672 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5673 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5674 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5675 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5676 				hdr.type5.msr_id)),
5677 	},
5678 	[ITEM_GENEVE_OPT] = {
5679 		.name = "geneve-opt",
5680 		.help = "GENEVE header option",
5681 		.priv = PRIV_ITEM(GENEVE_OPT,
5682 				  sizeof(struct rte_flow_item_geneve_opt) +
5683 				  ITEM_GENEVE_OPT_DATA_SIZE),
5684 		.next = NEXT(item_geneve_opt),
5685 		.call = parse_vc,
5686 	},
5687 	[ITEM_GENEVE_OPT_CLASS]	= {
5688 		.name = "class",
5689 		.help = "GENEVE option class",
5690 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5691 			     item_param),
5692 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5693 					     option_class)),
5694 	},
5695 	[ITEM_GENEVE_OPT_TYPE] = {
5696 		.name = "type",
5697 		.help = "GENEVE option type",
5698 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5699 			     item_param),
5700 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5701 					option_type)),
5702 	},
5703 	[ITEM_GENEVE_OPT_LENGTH] = {
5704 		.name = "length",
5705 		.help = "GENEVE option data length (in 32b words)",
5706 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5707 			     item_param),
5708 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5709 				struct rte_flow_item_geneve_opt, option_len,
5710 				0, 31)),
5711 	},
5712 	[ITEM_GENEVE_OPT_DATA] = {
5713 		.name = "data",
5714 		.help = "GENEVE option data pattern",
5715 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5716 			     item_param),
5717 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5718 			     ARGS_ENTRY_ARB(0, 0),
5719 			     ARGS_ENTRY_ARB
5720 				(sizeof(struct rte_flow_item_geneve_opt),
5721 				ITEM_GENEVE_OPT_DATA_SIZE)),
5722 	},
5723 	[ITEM_INTEGRITY] = {
5724 		.name = "integrity",
5725 		.help = "match packet integrity",
5726 		.priv = PRIV_ITEM(INTEGRITY,
5727 				  sizeof(struct rte_flow_item_integrity)),
5728 		.next = NEXT(item_integrity),
5729 		.call = parse_vc,
5730 	},
5731 	[ITEM_INTEGRITY_LEVEL] = {
5732 		.name = "level",
5733 		.help = "integrity level",
5734 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5735 			     item_param),
5736 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5737 	},
5738 	[ITEM_INTEGRITY_VALUE] = {
5739 		.name = "value",
5740 		.help = "integrity value",
5741 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5742 			     item_param),
5743 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5744 	},
5745 	[ITEM_CONNTRACK] = {
5746 		.name = "conntrack",
5747 		.help = "conntrack state",
5748 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5749 			     item_param),
5750 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5751 	},
5752 	[ITEM_PORT_REPRESENTOR] = {
5753 		.name = "port_representor",
5754 		.help = "match traffic entering the embedded switch from the given ethdev",
5755 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5756 				  sizeof(struct rte_flow_item_ethdev)),
5757 		.next = NEXT(item_port_representor),
5758 		.call = parse_vc,
5759 	},
5760 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5761 		.name = "port_id",
5762 		.help = "ethdev port ID",
5763 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5764 			     item_param),
5765 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5766 	},
5767 	[ITEM_REPRESENTED_PORT] = {
5768 		.name = "represented_port",
5769 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5770 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5771 				  sizeof(struct rte_flow_item_ethdev)),
5772 		.next = NEXT(item_represented_port),
5773 		.call = parse_vc,
5774 	},
5775 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5776 		.name = "ethdev_port_id",
5777 		.help = "ethdev port ID",
5778 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5779 			     item_param),
5780 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5781 	},
5782 	[ITEM_FLEX] = {
5783 		.name = "flex",
5784 		.help = "match flex header",
5785 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5786 		.next = NEXT(item_flex),
5787 		.call = parse_vc,
5788 	},
5789 	[ITEM_FLEX_ITEM_HANDLE] = {
5790 		.name = "item",
5791 		.help = "flex item handle",
5792 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5793 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5794 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5795 	},
5796 	[ITEM_FLEX_PATTERN_HANDLE] = {
5797 		.name = "pattern",
5798 		.help = "flex pattern handle",
5799 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5800 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5801 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5802 	},
5803 	[ITEM_L2TPV2] = {
5804 		.name = "l2tpv2",
5805 		.help = "match L2TPv2 header",
5806 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5807 		.next = NEXT(item_l2tpv2),
5808 		.call = parse_vc,
5809 	},
5810 	[ITEM_L2TPV2_TYPE] = {
5811 		.name = "type",
5812 		.help = "type of l2tpv2",
5813 		.next = NEXT(item_l2tpv2_type),
5814 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5815 	},
5816 	[ITEM_L2TPV2_TYPE_DATA] = {
5817 		.name = "data",
5818 		.help = "Type #7: data message without any options",
5819 		.next = NEXT(item_l2tpv2_type_data),
5820 		.call = parse_vc_item_l2tpv2_type,
5821 	},
5822 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5823 		.name = "tunnel_id",
5824 		.help = "tunnel identifier",
5825 		.next = NEXT(item_l2tpv2_type_data,
5826 			     NEXT_ENTRY(COMMON_UNSIGNED),
5827 			     item_param),
5828 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5829 					     hdr.type7.tunnel_id)),
5830 	},
5831 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5832 		.name = "session_id",
5833 		.help = "session identifier",
5834 		.next = NEXT(item_l2tpv2_type_data,
5835 			     NEXT_ENTRY(COMMON_UNSIGNED),
5836 			     item_param),
5837 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5838 					     hdr.type7.session_id)),
5839 	},
5840 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5841 		.name = "data_l",
5842 		.help = "Type #6: data message with length option",
5843 		.next = NEXT(item_l2tpv2_type_data_l),
5844 		.call = parse_vc_item_l2tpv2_type,
5845 	},
5846 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5847 		.name = "length",
5848 		.help = "message length",
5849 		.next = NEXT(item_l2tpv2_type_data_l,
5850 			     NEXT_ENTRY(COMMON_UNSIGNED),
5851 			     item_param),
5852 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5853 					     hdr.type6.length)),
5854 	},
5855 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5856 		.name = "tunnel_id",
5857 		.help = "tunnel identifier",
5858 		.next = NEXT(item_l2tpv2_type_data_l,
5859 			     NEXT_ENTRY(COMMON_UNSIGNED),
5860 			     item_param),
5861 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5862 					     hdr.type6.tunnel_id)),
5863 	},
5864 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5865 		.name = "session_id",
5866 		.help = "session identifier",
5867 		.next = NEXT(item_l2tpv2_type_data_l,
5868 			     NEXT_ENTRY(COMMON_UNSIGNED),
5869 			     item_param),
5870 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5871 					     hdr.type6.session_id)),
5872 	},
5873 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5874 		.name = "data_s",
5875 		.help = "Type #5: data message with ns, nr option",
5876 		.next = NEXT(item_l2tpv2_type_data_s),
5877 		.call = parse_vc_item_l2tpv2_type,
5878 	},
5879 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5880 		.name = "tunnel_id",
5881 		.help = "tunnel identifier",
5882 		.next = NEXT(item_l2tpv2_type_data_s,
5883 			     NEXT_ENTRY(COMMON_UNSIGNED),
5884 			     item_param),
5885 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5886 					     hdr.type5.tunnel_id)),
5887 	},
5888 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5889 		.name = "session_id",
5890 		.help = "session identifier",
5891 		.next = NEXT(item_l2tpv2_type_data_s,
5892 			     NEXT_ENTRY(COMMON_UNSIGNED),
5893 			     item_param),
5894 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5895 					     hdr.type5.session_id)),
5896 	},
5897 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5898 		.name = "ns",
5899 		.help = "sequence number for message",
5900 		.next = NEXT(item_l2tpv2_type_data_s,
5901 			     NEXT_ENTRY(COMMON_UNSIGNED),
5902 			     item_param),
5903 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5904 					     hdr.type5.ns)),
5905 	},
5906 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5907 		.name = "nr",
5908 		.help = "sequence number for next receive message",
5909 		.next = NEXT(item_l2tpv2_type_data_s,
5910 			     NEXT_ENTRY(COMMON_UNSIGNED),
5911 			     item_param),
5912 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5913 					     hdr.type5.nr)),
5914 	},
5915 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5916 		.name = "data_o",
5917 		.help = "Type #4: data message with offset option",
5918 		.next = NEXT(item_l2tpv2_type_data_o),
5919 		.call = parse_vc_item_l2tpv2_type,
5920 	},
5921 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5922 		.name = "tunnel_id",
5923 		.help = "tunnel identifier",
5924 		.next = NEXT(item_l2tpv2_type_data_o,
5925 			     NEXT_ENTRY(COMMON_UNSIGNED),
5926 			     item_param),
5927 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5928 					     hdr.type4.tunnel_id)),
5929 	},
5930 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5931 		.name = "session_id",
5932 		.help = "session identifier",
5933 		.next = NEXT(item_l2tpv2_type_data_o,
5934 			     NEXT_ENTRY(COMMON_UNSIGNED),
5935 			     item_param),
5936 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5937 					     hdr.type5.session_id)),
5938 	},
5939 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
5940 		.name = "offset_size",
5941 		.help = "the size of offset padding",
5942 		.next = NEXT(item_l2tpv2_type_data_o,
5943 			     NEXT_ENTRY(COMMON_UNSIGNED),
5944 			     item_param),
5945 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5946 					     hdr.type4.offset_size)),
5947 	},
5948 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
5949 		.name = "data_l_s",
5950 		.help = "Type #3: data message contains length, ns, nr "
5951 			"options",
5952 		.next = NEXT(item_l2tpv2_type_data_l_s),
5953 		.call = parse_vc_item_l2tpv2_type,
5954 	},
5955 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
5956 		.name = "length",
5957 		.help = "message length",
5958 		.next = NEXT(item_l2tpv2_type_data_l_s,
5959 			     NEXT_ENTRY(COMMON_UNSIGNED),
5960 			     item_param),
5961 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5962 					     hdr.type3.length)),
5963 	},
5964 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
5965 		.name = "tunnel_id",
5966 		.help = "tunnel identifier",
5967 		.next = NEXT(item_l2tpv2_type_data_l_s,
5968 			     NEXT_ENTRY(COMMON_UNSIGNED),
5969 			     item_param),
5970 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5971 					     hdr.type3.tunnel_id)),
5972 	},
5973 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
5974 		.name = "session_id",
5975 		.help = "session identifier",
5976 		.next = NEXT(item_l2tpv2_type_data_l_s,
5977 			     NEXT_ENTRY(COMMON_UNSIGNED),
5978 			     item_param),
5979 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5980 					     hdr.type3.session_id)),
5981 	},
5982 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
5983 		.name = "ns",
5984 		.help = "sequence number for message",
5985 		.next = NEXT(item_l2tpv2_type_data_l_s,
5986 			     NEXT_ENTRY(COMMON_UNSIGNED),
5987 			     item_param),
5988 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5989 					     hdr.type3.ns)),
5990 	},
5991 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
5992 		.name = "nr",
5993 		.help = "sequence number for next receive message",
5994 		.next = NEXT(item_l2tpv2_type_data_l_s,
5995 			     NEXT_ENTRY(COMMON_UNSIGNED),
5996 			     item_param),
5997 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5998 					     hdr.type3.nr)),
5999 	},
6000 	[ITEM_L2TPV2_TYPE_CTRL] = {
6001 		.name = "control",
6002 		.help = "Type #3: conrtol message contains length, ns, nr "
6003 			"options",
6004 		.next = NEXT(item_l2tpv2_type_ctrl),
6005 		.call = parse_vc_item_l2tpv2_type,
6006 	},
6007 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6008 		.name = "length",
6009 		.help = "message length",
6010 		.next = NEXT(item_l2tpv2_type_ctrl,
6011 			     NEXT_ENTRY(COMMON_UNSIGNED),
6012 			     item_param),
6013 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6014 					     hdr.type3.length)),
6015 	},
6016 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6017 		.name = "tunnel_id",
6018 		.help = "tunnel identifier",
6019 		.next = NEXT(item_l2tpv2_type_ctrl,
6020 			     NEXT_ENTRY(COMMON_UNSIGNED),
6021 			     item_param),
6022 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6023 					     hdr.type3.tunnel_id)),
6024 	},
6025 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6026 		.name = "session_id",
6027 		.help = "session identifier",
6028 		.next = NEXT(item_l2tpv2_type_ctrl,
6029 			     NEXT_ENTRY(COMMON_UNSIGNED),
6030 			     item_param),
6031 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6032 					     hdr.type3.session_id)),
6033 	},
6034 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6035 		.name = "ns",
6036 		.help = "sequence number for message",
6037 		.next = NEXT(item_l2tpv2_type_ctrl,
6038 			     NEXT_ENTRY(COMMON_UNSIGNED),
6039 			     item_param),
6040 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6041 					     hdr.type3.ns)),
6042 	},
6043 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6044 		.name = "nr",
6045 		.help = "sequence number for next receive message",
6046 		.next = NEXT(item_l2tpv2_type_ctrl,
6047 			     NEXT_ENTRY(COMMON_UNSIGNED),
6048 			     item_param),
6049 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6050 					     hdr.type3.nr)),
6051 	},
6052 	[ITEM_PPP] = {
6053 		.name = "ppp",
6054 		.help = "match PPP header",
6055 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6056 		.next = NEXT(item_ppp),
6057 		.call = parse_vc,
6058 	},
6059 	[ITEM_PPP_ADDR] = {
6060 		.name = "addr",
6061 		.help = "PPP address",
6062 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6063 			     item_param),
6064 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6065 	},
6066 	[ITEM_PPP_CTRL] = {
6067 		.name = "ctrl",
6068 		.help = "PPP control",
6069 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6070 			     item_param),
6071 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6072 	},
6073 	[ITEM_PPP_PROTO_ID] = {
6074 		.name = "proto_id",
6075 		.help = "PPP protocol identifier",
6076 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6077 			     item_param),
6078 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6079 					hdr.proto_id)),
6080 	},
6081 	[ITEM_METER] = {
6082 		.name = "meter",
6083 		.help = "match meter color",
6084 		.priv = PRIV_ITEM(METER_COLOR,
6085 				  sizeof(struct rte_flow_item_meter_color)),
6086 		.next = NEXT(item_meter),
6087 		.call = parse_vc,
6088 	},
6089 	[ITEM_METER_COLOR] = {
6090 		.name = "color",
6091 		.help = "meter color",
6092 		.next = NEXT(item_meter,
6093 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6094 			     item_param),
6095 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6096 					color)),
6097 	},
6098 	[ITEM_METER_COLOR_NAME] = {
6099 		.name = "color_name",
6100 		.help = "meter color name",
6101 		.call = parse_meter_color,
6102 		.comp = comp_meter_color,
6103 	},
6104 	[ITEM_QUOTA] = {
6105 		.name = "quota",
6106 		.help = "match quota",
6107 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6108 		.next = NEXT(item_quota),
6109 		.call = parse_vc
6110 	},
6111 	[ITEM_QUOTA_STATE] = {
6112 		.name = "quota_state",
6113 		.help = "quota state",
6114 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6115 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6116 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6117 	},
6118 	[ITEM_QUOTA_STATE_NAME] = {
6119 		.name = "state_name",
6120 		.help = "quota state name",
6121 		.call = parse_quota_state_name,
6122 		.comp = comp_quota_state_name
6123 	},
6124 	[ITEM_IB_BTH] = {
6125 		.name = "ib_bth",
6126 		.help = "match ib bth fields",
6127 		.priv = PRIV_ITEM(IB_BTH,
6128 				  sizeof(struct rte_flow_item_ib_bth)),
6129 		.next = NEXT(item_ib_bth),
6130 		.call = parse_vc,
6131 	},
6132 	[ITEM_IB_BTH_OPCODE] = {
6133 		.name = "opcode",
6134 		.help = "match ib bth opcode",
6135 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6136 				 item_param),
6137 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6138 						 hdr.opcode)),
6139 	},
6140 	[ITEM_IB_BTH_PKEY] = {
6141 		.name = "pkey",
6142 		.help = "partition key",
6143 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6144 				 item_param),
6145 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6146 						 hdr.pkey)),
6147 	},
6148 	[ITEM_IB_BTH_DST_QPN] = {
6149 		.name = "dst_qp",
6150 		.help = "destination qp",
6151 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6152 				 item_param),
6153 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6154 						 hdr.dst_qp)),
6155 	},
6156 	[ITEM_IB_BTH_PSN] = {
6157 		.name = "psn",
6158 		.help = "packet sequence number",
6159 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6160 				 item_param),
6161 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6162 						 hdr.psn)),
6163 	},
6164 	[ITEM_PTYPE] = {
6165 		.name = "ptype",
6166 		.help = "match L2/L3/L4 and tunnel information",
6167 		.priv = PRIV_ITEM(PTYPE,
6168 				  sizeof(struct rte_flow_item_ptype)),
6169 		.next = NEXT(item_ptype),
6170 		.call = parse_vc,
6171 	},
6172 	[ITEM_PTYPE_VALUE] = {
6173 		.name = "packet_type",
6174 		.help = "packet type as defined in rte_mbuf_ptype",
6175 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6176 			     item_param),
6177 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6178 	},
6179 	[ITEM_NSH] = {
6180 		.name = "nsh",
6181 		.help = "match NSH header",
6182 		.priv = PRIV_ITEM(NSH,
6183 				  sizeof(struct rte_flow_item_nsh)),
6184 		.next = NEXT(item_nsh),
6185 		.call = parse_vc,
6186 	},
6187 	[ITEM_COMPARE] = {
6188 		.name = "compare",
6189 		.help = "match with the comparison result",
6190 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6191 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6192 		.call = parse_vc,
6193 	},
6194 	[ITEM_COMPARE_OP] = {
6195 		.name = "op",
6196 		.help = "operation type",
6197 		.next = NEXT(item_compare_field,
6198 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6199 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6200 	},
6201 	[ITEM_COMPARE_OP_VALUE] = {
6202 		.name = "{operation}",
6203 		.help = "operation type value",
6204 		.call = parse_vc_compare_op,
6205 		.comp = comp_set_compare_op,
6206 	},
6207 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6208 		.name = "a_type",
6209 		.help = "compared field type",
6210 		.next = NEXT(compare_field_a,
6211 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6212 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6213 	},
6214 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6215 		.name = "{a_type}",
6216 		.help = "compared field type value",
6217 		.call = parse_vc_compare_field_id,
6218 		.comp = comp_set_compare_field_id,
6219 	},
6220 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6221 		.name = "a_level",
6222 		.help = "compared field level",
6223 		.next = NEXT(compare_field_a,
6224 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6225 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6226 	},
6227 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6228 		.name = "{a_level}",
6229 		.help = "compared field level value",
6230 		.call = parse_vc_compare_field_level,
6231 		.comp = comp_none,
6232 	},
6233 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6234 		.name = "a_tag_index",
6235 		.help = "compared field tag array",
6236 		.next = NEXT(compare_field_a,
6237 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6238 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6239 					a.tag_index)),
6240 	},
6241 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6242 		.name = "a_type_id",
6243 		.help = "compared field type ID",
6244 		.next = NEXT(compare_field_a,
6245 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6246 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6247 					a.type)),
6248 	},
6249 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6250 		.name = "a_class",
6251 		.help = "compared field class ID",
6252 		.next = NEXT(compare_field_a,
6253 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6254 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6255 					     a.class_id)),
6256 	},
6257 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6258 		.name = "a_offset",
6259 		.help = "compared field bit offset",
6260 		.next = NEXT(compare_field_a,
6261 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6262 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6263 					a.offset)),
6264 	},
6265 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6266 		.name = "b_type",
6267 		.help = "comparator field type",
6268 		.next = NEXT(compare_field_b,
6269 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6270 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6271 					b.field)),
6272 	},
6273 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6274 		.name = "{b_type}",
6275 		.help = "comparator field type value",
6276 		.call = parse_vc_compare_field_id,
6277 		.comp = comp_set_compare_field_id,
6278 	},
6279 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6280 		.name = "b_level",
6281 		.help = "comparator field level",
6282 		.next = NEXT(compare_field_b,
6283 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6284 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6285 					b.level)),
6286 	},
6287 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6288 		.name = "{b_level}",
6289 		.help = "comparator field level value",
6290 		.call = parse_vc_compare_field_level,
6291 		.comp = comp_none,
6292 	},
6293 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6294 		.name = "b_tag_index",
6295 		.help = "comparator field tag array",
6296 		.next = NEXT(compare_field_b,
6297 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6298 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6299 					b.tag_index)),
6300 	},
6301 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6302 		.name = "b_type_id",
6303 		.help = "comparator field type ID",
6304 		.next = NEXT(compare_field_b,
6305 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6306 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6307 					b.type)),
6308 	},
6309 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6310 		.name = "b_class",
6311 		.help = "comparator field class ID",
6312 		.next = NEXT(compare_field_b,
6313 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6314 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6315 					     b.class_id)),
6316 	},
6317 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6318 		.name = "b_offset",
6319 		.help = "comparator field bit offset",
6320 		.next = NEXT(compare_field_b,
6321 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6322 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6323 					b.offset)),
6324 	},
6325 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6326 		.name = "b_value",
6327 		.help = "comparator immediate value",
6328 		.next = NEXT(compare_field_b,
6329 			     NEXT_ENTRY(COMMON_HEX), item_param),
6330 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6331 			     ARGS_ENTRY_ARB(0, 0),
6332 			     ARGS_ENTRY(struct rte_flow_item_compare,
6333 					b.value)),
6334 	},
6335 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6336 		.name = "b_ptr",
6337 		.help = "pointer to comparator immediate value",
6338 		.next = NEXT(compare_field_b,
6339 			     NEXT_ENTRY(COMMON_HEX), item_param),
6340 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6341 					b.pvalue),
6342 			     ARGS_ENTRY_ARB(0, 0),
6343 			     ARGS_ENTRY_ARB
6344 				(sizeof(struct rte_flow_item_compare),
6345 				 FLOW_FIELD_PATTERN_SIZE)),
6346 	},
6347 	[ITEM_COMPARE_FIELD_WIDTH] = {
6348 		.name = "width",
6349 		.help = "number of bits to compare",
6350 		.next = NEXT(item_compare_field,
6351 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6352 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6353 					width)),
6354 	},
6355 
6356 	/* Validate/create actions. */
6357 	[ACTIONS] = {
6358 		.name = "actions",
6359 		.help = "submit a list of associated actions",
6360 		.next = NEXT(next_action),
6361 		.call = parse_vc,
6362 	},
6363 	[ACTION_NEXT] = {
6364 		.name = "/",
6365 		.help = "specify next action",
6366 		.next = NEXT(next_action),
6367 	},
6368 	[ACTION_END] = {
6369 		.name = "end",
6370 		.help = "end list of actions",
6371 		.priv = PRIV_ACTION(END, 0),
6372 		.call = parse_vc,
6373 	},
6374 	[ACTION_VOID] = {
6375 		.name = "void",
6376 		.help = "no-op action",
6377 		.priv = PRIV_ACTION(VOID, 0),
6378 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6379 		.call = parse_vc,
6380 	},
6381 	[ACTION_PASSTHRU] = {
6382 		.name = "passthru",
6383 		.help = "let subsequent rule process matched packets",
6384 		.priv = PRIV_ACTION(PASSTHRU, 0),
6385 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6386 		.call = parse_vc,
6387 	},
6388 	[ACTION_SKIP_CMAN] = {
6389 		.name = "skip_cman",
6390 		.help = "bypass cman on received packets",
6391 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6392 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6393 		.call = parse_vc,
6394 	},
6395 	[ACTION_JUMP] = {
6396 		.name = "jump",
6397 		.help = "redirect traffic to a given group",
6398 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6399 		.next = NEXT(action_jump),
6400 		.call = parse_vc,
6401 	},
6402 	[ACTION_JUMP_GROUP] = {
6403 		.name = "group",
6404 		.help = "group to redirect traffic to",
6405 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6406 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6407 		.call = parse_vc_conf,
6408 	},
6409 	[ACTION_MARK] = {
6410 		.name = "mark",
6411 		.help = "attach 32 bit value to packets",
6412 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6413 		.next = NEXT(action_mark),
6414 		.call = parse_vc,
6415 	},
6416 	[ACTION_MARK_ID] = {
6417 		.name = "id",
6418 		.help = "32 bit value to return with packets",
6419 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6420 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6421 		.call = parse_vc_conf,
6422 	},
6423 	[ACTION_FLAG] = {
6424 		.name = "flag",
6425 		.help = "flag packets",
6426 		.priv = PRIV_ACTION(FLAG, 0),
6427 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6428 		.call = parse_vc,
6429 	},
6430 	[ACTION_QUEUE] = {
6431 		.name = "queue",
6432 		.help = "assign packets to a given queue index",
6433 		.priv = PRIV_ACTION(QUEUE,
6434 				    sizeof(struct rte_flow_action_queue)),
6435 		.next = NEXT(action_queue),
6436 		.call = parse_vc,
6437 	},
6438 	[ACTION_QUEUE_INDEX] = {
6439 		.name = "index",
6440 		.help = "queue index to use",
6441 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6442 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6443 		.call = parse_vc_conf,
6444 	},
6445 	[ACTION_DROP] = {
6446 		.name = "drop",
6447 		.help = "drop packets (note: passthru has priority)",
6448 		.priv = PRIV_ACTION(DROP, 0),
6449 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6450 		.call = parse_vc,
6451 	},
6452 	[ACTION_COUNT] = {
6453 		.name = "count",
6454 		.help = "enable counters for this rule",
6455 		.priv = PRIV_ACTION(COUNT,
6456 				    sizeof(struct rte_flow_action_count)),
6457 		.next = NEXT(action_count),
6458 		.call = parse_vc,
6459 	},
6460 	[ACTION_COUNT_ID] = {
6461 		.name = "identifier",
6462 		.help = "counter identifier to use",
6463 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6464 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6465 		.call = parse_vc_conf,
6466 	},
6467 	[ACTION_RSS] = {
6468 		.name = "rss",
6469 		.help = "spread packets among several queues",
6470 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6471 		.next = NEXT(action_rss),
6472 		.call = parse_vc_action_rss,
6473 	},
6474 	[ACTION_RSS_FUNC] = {
6475 		.name = "func",
6476 		.help = "RSS hash function to apply",
6477 		.next = NEXT(action_rss,
6478 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6479 					ACTION_RSS_FUNC_TOEPLITZ,
6480 					ACTION_RSS_FUNC_SIMPLE_XOR,
6481 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6482 	},
6483 	[ACTION_RSS_FUNC_DEFAULT] = {
6484 		.name = "default",
6485 		.help = "default hash function",
6486 		.call = parse_vc_action_rss_func,
6487 	},
6488 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6489 		.name = "toeplitz",
6490 		.help = "Toeplitz hash function",
6491 		.call = parse_vc_action_rss_func,
6492 	},
6493 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6494 		.name = "simple_xor",
6495 		.help = "simple XOR hash function",
6496 		.call = parse_vc_action_rss_func,
6497 	},
6498 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6499 		.name = "symmetric_toeplitz",
6500 		.help = "Symmetric Toeplitz hash function",
6501 		.call = parse_vc_action_rss_func,
6502 	},
6503 	[ACTION_RSS_LEVEL] = {
6504 		.name = "level",
6505 		.help = "encapsulation level for \"types\"",
6506 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6507 		.args = ARGS(ARGS_ENTRY_ARB
6508 			     (offsetof(struct action_rss_data, conf) +
6509 			      offsetof(struct rte_flow_action_rss, level),
6510 			      sizeof(((struct rte_flow_action_rss *)0)->
6511 				     level))),
6512 	},
6513 	[ACTION_RSS_TYPES] = {
6514 		.name = "types",
6515 		.help = "specific RSS hash types",
6516 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6517 	},
6518 	[ACTION_RSS_TYPE] = {
6519 		.name = "{type}",
6520 		.help = "RSS hash type",
6521 		.call = parse_vc_action_rss_type,
6522 		.comp = comp_vc_action_rss_type,
6523 	},
6524 	[ACTION_RSS_KEY] = {
6525 		.name = "key",
6526 		.help = "RSS hash key",
6527 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6528 		.args = ARGS(ARGS_ENTRY_ARB
6529 			     (offsetof(struct action_rss_data, conf) +
6530 			      offsetof(struct rte_flow_action_rss, key),
6531 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6532 			     ARGS_ENTRY_ARB
6533 			     (offsetof(struct action_rss_data, conf) +
6534 			      offsetof(struct rte_flow_action_rss, key_len),
6535 			      sizeof(((struct rte_flow_action_rss *)0)->
6536 				     key_len)),
6537 			     ARGS_ENTRY(struct action_rss_data, key)),
6538 	},
6539 	[ACTION_RSS_KEY_LEN] = {
6540 		.name = "key_len",
6541 		.help = "RSS hash key length in bytes",
6542 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6543 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6544 			     (offsetof(struct action_rss_data, conf) +
6545 			      offsetof(struct rte_flow_action_rss, key_len),
6546 			      sizeof(((struct rte_flow_action_rss *)0)->
6547 				     key_len),
6548 			      0,
6549 			      RSS_HASH_KEY_LENGTH)),
6550 	},
6551 	[ACTION_RSS_QUEUES] = {
6552 		.name = "queues",
6553 		.help = "queue indices to use",
6554 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6555 		.call = parse_vc_conf,
6556 	},
6557 	[ACTION_RSS_QUEUE] = {
6558 		.name = "{queue}",
6559 		.help = "queue index",
6560 		.call = parse_vc_action_rss_queue,
6561 		.comp = comp_vc_action_rss_queue,
6562 	},
6563 	[ACTION_PF] = {
6564 		.name = "pf",
6565 		.help = "direct traffic to physical function",
6566 		.priv = PRIV_ACTION(PF, 0),
6567 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6568 		.call = parse_vc,
6569 	},
6570 	[ACTION_VF] = {
6571 		.name = "vf",
6572 		.help = "direct traffic to a virtual function ID",
6573 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6574 		.next = NEXT(action_vf),
6575 		.call = parse_vc,
6576 	},
6577 	[ACTION_VF_ORIGINAL] = {
6578 		.name = "original",
6579 		.help = "use original VF ID if possible",
6580 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6581 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6582 					   original, 1)),
6583 		.call = parse_vc_conf,
6584 	},
6585 	[ACTION_VF_ID] = {
6586 		.name = "id",
6587 		.help = "VF ID",
6588 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6589 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6590 		.call = parse_vc_conf,
6591 	},
6592 	[ACTION_PORT_ID] = {
6593 		.name = "port_id",
6594 		.help = "direct matching traffic to a given DPDK port ID",
6595 		.priv = PRIV_ACTION(PORT_ID,
6596 				    sizeof(struct rte_flow_action_port_id)),
6597 		.next = NEXT(action_port_id),
6598 		.call = parse_vc,
6599 	},
6600 	[ACTION_PORT_ID_ORIGINAL] = {
6601 		.name = "original",
6602 		.help = "use original DPDK port ID if possible",
6603 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6604 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6605 					   original, 1)),
6606 		.call = parse_vc_conf,
6607 	},
6608 	[ACTION_PORT_ID_ID] = {
6609 		.name = "id",
6610 		.help = "DPDK port ID",
6611 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6612 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6613 		.call = parse_vc_conf,
6614 	},
6615 	[ACTION_METER] = {
6616 		.name = "meter",
6617 		.help = "meter the directed packets at given id",
6618 		.priv = PRIV_ACTION(METER,
6619 				    sizeof(struct rte_flow_action_meter)),
6620 		.next = NEXT(action_meter),
6621 		.call = parse_vc,
6622 	},
6623 	[ACTION_METER_COLOR] = {
6624 		.name = "color",
6625 		.help = "meter color for the packets",
6626 		.priv = PRIV_ACTION(METER_COLOR,
6627 				sizeof(struct rte_flow_action_meter_color)),
6628 		.next = NEXT(action_meter_color),
6629 		.call = parse_vc,
6630 	},
6631 	[ACTION_METER_COLOR_TYPE] = {
6632 		.name = "type",
6633 		.help = "specific meter color",
6634 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6635 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6636 					ACTION_METER_COLOR_YELLOW,
6637 					ACTION_METER_COLOR_RED)),
6638 	},
6639 	[ACTION_METER_COLOR_GREEN] = {
6640 		.name = "green",
6641 		.help = "meter color green",
6642 		.call = parse_vc_action_meter_color_type,
6643 	},
6644 	[ACTION_METER_COLOR_YELLOW] = {
6645 		.name = "yellow",
6646 		.help = "meter color yellow",
6647 		.call = parse_vc_action_meter_color_type,
6648 	},
6649 	[ACTION_METER_COLOR_RED] = {
6650 		.name = "red",
6651 		.help = "meter color red",
6652 		.call = parse_vc_action_meter_color_type,
6653 	},
6654 	[ACTION_METER_ID] = {
6655 		.name = "mtr_id",
6656 		.help = "meter id to use",
6657 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6658 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6659 		.call = parse_vc_conf,
6660 	},
6661 	[ACTION_METER_MARK] = {
6662 		.name = "meter_mark",
6663 		.help = "meter the directed packets using profile and policy",
6664 		.priv = PRIV_ACTION(METER_MARK,
6665 				    sizeof(struct rte_flow_action_meter_mark)),
6666 		.next = NEXT(action_meter_mark),
6667 		.call = parse_vc,
6668 	},
6669 	[ACTION_METER_PROFILE] = {
6670 		.name = "mtr_profile",
6671 		.help = "meter profile id to use",
6672 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6673 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6674 	},
6675 	[ACTION_METER_PROFILE_ID2PTR] = {
6676 		.name = "{mtr_profile_id}",
6677 		.type = "PROFILE_ID",
6678 		.help = "meter profile id",
6679 		.next = NEXT(action_meter_mark),
6680 		.call = parse_meter_profile_id2ptr,
6681 		.comp = comp_none,
6682 	},
6683 	[ACTION_METER_POLICY] = {
6684 		.name = "mtr_policy",
6685 		.help = "meter policy id to use",
6686 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6687 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6688 	},
6689 	[ACTION_METER_POLICY_ID2PTR] = {
6690 		.name = "{mtr_policy_id}",
6691 		.type = "POLICY_ID",
6692 		.help = "meter policy id",
6693 		.next = NEXT(action_meter_mark),
6694 		.call = parse_meter_policy_id2ptr,
6695 		.comp = comp_none,
6696 	},
6697 	[ACTION_METER_COLOR_MODE] = {
6698 		.name = "mtr_color_mode",
6699 		.help = "meter color awareness mode",
6700 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6701 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6702 		.call = parse_vc_conf,
6703 	},
6704 	[ACTION_METER_STATE] = {
6705 		.name = "mtr_state",
6706 		.help = "meter state",
6707 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6708 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6709 		.call = parse_vc_conf,
6710 	},
6711 	[ACTION_OF_DEC_NW_TTL] = {
6712 		.name = "of_dec_nw_ttl",
6713 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6714 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6715 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6716 		.call = parse_vc,
6717 	},
6718 	[ACTION_OF_POP_VLAN] = {
6719 		.name = "of_pop_vlan",
6720 		.help = "OpenFlow's OFPAT_POP_VLAN",
6721 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6722 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6723 		.call = parse_vc,
6724 	},
6725 	[ACTION_OF_PUSH_VLAN] = {
6726 		.name = "of_push_vlan",
6727 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6728 		.priv = PRIV_ACTION
6729 			(OF_PUSH_VLAN,
6730 			 sizeof(struct rte_flow_action_of_push_vlan)),
6731 		.next = NEXT(action_of_push_vlan),
6732 		.call = parse_vc,
6733 	},
6734 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6735 		.name = "ethertype",
6736 		.help = "EtherType",
6737 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6738 		.args = ARGS(ARGS_ENTRY_HTON
6739 			     (struct rte_flow_action_of_push_vlan,
6740 			      ethertype)),
6741 		.call = parse_vc_conf,
6742 	},
6743 	[ACTION_OF_SET_VLAN_VID] = {
6744 		.name = "of_set_vlan_vid",
6745 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6746 		.priv = PRIV_ACTION
6747 			(OF_SET_VLAN_VID,
6748 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6749 		.next = NEXT(action_of_set_vlan_vid),
6750 		.call = parse_vc,
6751 	},
6752 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6753 		.name = "vlan_vid",
6754 		.help = "VLAN id",
6755 		.next = NEXT(action_of_set_vlan_vid,
6756 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6757 		.args = ARGS(ARGS_ENTRY_HTON
6758 			     (struct rte_flow_action_of_set_vlan_vid,
6759 			      vlan_vid)),
6760 		.call = parse_vc_conf,
6761 	},
6762 	[ACTION_OF_SET_VLAN_PCP] = {
6763 		.name = "of_set_vlan_pcp",
6764 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6765 		.priv = PRIV_ACTION
6766 			(OF_SET_VLAN_PCP,
6767 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6768 		.next = NEXT(action_of_set_vlan_pcp),
6769 		.call = parse_vc,
6770 	},
6771 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6772 		.name = "vlan_pcp",
6773 		.help = "VLAN priority",
6774 		.next = NEXT(action_of_set_vlan_pcp,
6775 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6776 		.args = ARGS(ARGS_ENTRY_HTON
6777 			     (struct rte_flow_action_of_set_vlan_pcp,
6778 			      vlan_pcp)),
6779 		.call = parse_vc_conf,
6780 	},
6781 	[ACTION_OF_POP_MPLS] = {
6782 		.name = "of_pop_mpls",
6783 		.help = "OpenFlow's OFPAT_POP_MPLS",
6784 		.priv = PRIV_ACTION(OF_POP_MPLS,
6785 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6786 		.next = NEXT(action_of_pop_mpls),
6787 		.call = parse_vc,
6788 	},
6789 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6790 		.name = "ethertype",
6791 		.help = "EtherType",
6792 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6793 		.args = ARGS(ARGS_ENTRY_HTON
6794 			     (struct rte_flow_action_of_pop_mpls,
6795 			      ethertype)),
6796 		.call = parse_vc_conf,
6797 	},
6798 	[ACTION_OF_PUSH_MPLS] = {
6799 		.name = "of_push_mpls",
6800 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6801 		.priv = PRIV_ACTION
6802 			(OF_PUSH_MPLS,
6803 			 sizeof(struct rte_flow_action_of_push_mpls)),
6804 		.next = NEXT(action_of_push_mpls),
6805 		.call = parse_vc,
6806 	},
6807 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6808 		.name = "ethertype",
6809 		.help = "EtherType",
6810 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6811 		.args = ARGS(ARGS_ENTRY_HTON
6812 			     (struct rte_flow_action_of_push_mpls,
6813 			      ethertype)),
6814 		.call = parse_vc_conf,
6815 	},
6816 	[ACTION_VXLAN_ENCAP] = {
6817 		.name = "vxlan_encap",
6818 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6819 			" vxlan\"",
6820 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6821 				    sizeof(struct action_vxlan_encap_data)),
6822 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6823 		.call = parse_vc_action_vxlan_encap,
6824 	},
6825 	[ACTION_VXLAN_DECAP] = {
6826 		.name = "vxlan_decap",
6827 		.help = "Performs a decapsulation action by stripping all"
6828 			" headers of the VXLAN tunnel network overlay from the"
6829 			" matched flow.",
6830 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6831 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6832 		.call = parse_vc,
6833 	},
6834 	[ACTION_NVGRE_ENCAP] = {
6835 		.name = "nvgre_encap",
6836 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6837 			" nvgre\"",
6838 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6839 				    sizeof(struct action_nvgre_encap_data)),
6840 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6841 		.call = parse_vc_action_nvgre_encap,
6842 	},
6843 	[ACTION_NVGRE_DECAP] = {
6844 		.name = "nvgre_decap",
6845 		.help = "Performs a decapsulation action by stripping all"
6846 			" headers of the NVGRE tunnel network overlay from the"
6847 			" matched flow.",
6848 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6849 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6850 		.call = parse_vc,
6851 	},
6852 	[ACTION_L2_ENCAP] = {
6853 		.name = "l2_encap",
6854 		.help = "l2 encap, uses configuration set by"
6855 			" \"set l2_encap\"",
6856 		.priv = PRIV_ACTION(RAW_ENCAP,
6857 				    sizeof(struct action_raw_encap_data)),
6858 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6859 		.call = parse_vc_action_l2_encap,
6860 	},
6861 	[ACTION_L2_DECAP] = {
6862 		.name = "l2_decap",
6863 		.help = "l2 decap, uses configuration set by"
6864 			" \"set l2_decap\"",
6865 		.priv = PRIV_ACTION(RAW_DECAP,
6866 				    sizeof(struct action_raw_decap_data)),
6867 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6868 		.call = parse_vc_action_l2_decap,
6869 	},
6870 	[ACTION_MPLSOGRE_ENCAP] = {
6871 		.name = "mplsogre_encap",
6872 		.help = "mplsogre encapsulation, uses configuration set by"
6873 			" \"set mplsogre_encap\"",
6874 		.priv = PRIV_ACTION(RAW_ENCAP,
6875 				    sizeof(struct action_raw_encap_data)),
6876 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6877 		.call = parse_vc_action_mplsogre_encap,
6878 	},
6879 	[ACTION_MPLSOGRE_DECAP] = {
6880 		.name = "mplsogre_decap",
6881 		.help = "mplsogre decapsulation, uses configuration set by"
6882 			" \"set mplsogre_decap\"",
6883 		.priv = PRIV_ACTION(RAW_DECAP,
6884 				    sizeof(struct action_raw_decap_data)),
6885 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6886 		.call = parse_vc_action_mplsogre_decap,
6887 	},
6888 	[ACTION_MPLSOUDP_ENCAP] = {
6889 		.name = "mplsoudp_encap",
6890 		.help = "mplsoudp encapsulation, uses configuration set by"
6891 			" \"set mplsoudp_encap\"",
6892 		.priv = PRIV_ACTION(RAW_ENCAP,
6893 				    sizeof(struct action_raw_encap_data)),
6894 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6895 		.call = parse_vc_action_mplsoudp_encap,
6896 	},
6897 	[ACTION_MPLSOUDP_DECAP] = {
6898 		.name = "mplsoudp_decap",
6899 		.help = "mplsoudp decapsulation, uses configuration set by"
6900 			" \"set mplsoudp_decap\"",
6901 		.priv = PRIV_ACTION(RAW_DECAP,
6902 				    sizeof(struct action_raw_decap_data)),
6903 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6904 		.call = parse_vc_action_mplsoudp_decap,
6905 	},
6906 	[ACTION_SET_IPV4_SRC] = {
6907 		.name = "set_ipv4_src",
6908 		.help = "Set a new IPv4 source address in the outermost"
6909 			" IPv4 header",
6910 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6911 			sizeof(struct rte_flow_action_set_ipv4)),
6912 		.next = NEXT(action_set_ipv4_src),
6913 		.call = parse_vc,
6914 	},
6915 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6916 		.name = "ipv4_addr",
6917 		.help = "new IPv4 source address to set",
6918 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6919 		.args = ARGS(ARGS_ENTRY_HTON
6920 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6921 		.call = parse_vc_conf,
6922 	},
6923 	[ACTION_SET_IPV4_DST] = {
6924 		.name = "set_ipv4_dst",
6925 		.help = "Set a new IPv4 destination address in the outermost"
6926 			" IPv4 header",
6927 		.priv = PRIV_ACTION(SET_IPV4_DST,
6928 			sizeof(struct rte_flow_action_set_ipv4)),
6929 		.next = NEXT(action_set_ipv4_dst),
6930 		.call = parse_vc,
6931 	},
6932 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6933 		.name = "ipv4_addr",
6934 		.help = "new IPv4 destination address to set",
6935 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6936 		.args = ARGS(ARGS_ENTRY_HTON
6937 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6938 		.call = parse_vc_conf,
6939 	},
6940 	[ACTION_SET_IPV6_SRC] = {
6941 		.name = "set_ipv6_src",
6942 		.help = "Set a new IPv6 source address in the outermost"
6943 			" IPv6 header",
6944 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6945 			sizeof(struct rte_flow_action_set_ipv6)),
6946 		.next = NEXT(action_set_ipv6_src),
6947 		.call = parse_vc,
6948 	},
6949 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
6950 		.name = "ipv6_addr",
6951 		.help = "new IPv6 source address to set",
6952 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6953 		.args = ARGS(ARGS_ENTRY_HTON
6954 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6955 		.call = parse_vc_conf,
6956 	},
6957 	[ACTION_SET_IPV6_DST] = {
6958 		.name = "set_ipv6_dst",
6959 		.help = "Set a new IPv6 destination address in the outermost"
6960 			" IPv6 header",
6961 		.priv = PRIV_ACTION(SET_IPV6_DST,
6962 			sizeof(struct rte_flow_action_set_ipv6)),
6963 		.next = NEXT(action_set_ipv6_dst),
6964 		.call = parse_vc,
6965 	},
6966 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
6967 		.name = "ipv6_addr",
6968 		.help = "new IPv6 destination address to set",
6969 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6970 		.args = ARGS(ARGS_ENTRY_HTON
6971 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6972 		.call = parse_vc_conf,
6973 	},
6974 	[ACTION_SET_TP_SRC] = {
6975 		.name = "set_tp_src",
6976 		.help = "set a new source port number in the outermost"
6977 			" TCP/UDP header",
6978 		.priv = PRIV_ACTION(SET_TP_SRC,
6979 			sizeof(struct rte_flow_action_set_tp)),
6980 		.next = NEXT(action_set_tp_src),
6981 		.call = parse_vc,
6982 	},
6983 	[ACTION_SET_TP_SRC_TP_SRC] = {
6984 		.name = "port",
6985 		.help = "new source port number to set",
6986 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
6987 		.args = ARGS(ARGS_ENTRY_HTON
6988 			     (struct rte_flow_action_set_tp, port)),
6989 		.call = parse_vc_conf,
6990 	},
6991 	[ACTION_SET_TP_DST] = {
6992 		.name = "set_tp_dst",
6993 		.help = "set a new destination port number in the outermost"
6994 			" TCP/UDP header",
6995 		.priv = PRIV_ACTION(SET_TP_DST,
6996 			sizeof(struct rte_flow_action_set_tp)),
6997 		.next = NEXT(action_set_tp_dst),
6998 		.call = parse_vc,
6999 	},
7000 	[ACTION_SET_TP_DST_TP_DST] = {
7001 		.name = "port",
7002 		.help = "new destination port number to set",
7003 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7004 		.args = ARGS(ARGS_ENTRY_HTON
7005 			     (struct rte_flow_action_set_tp, port)),
7006 		.call = parse_vc_conf,
7007 	},
7008 	[ACTION_MAC_SWAP] = {
7009 		.name = "mac_swap",
7010 		.help = "Swap the source and destination MAC addresses"
7011 			" in the outermost Ethernet header",
7012 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7013 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7014 		.call = parse_vc,
7015 	},
7016 	[ACTION_DEC_TTL] = {
7017 		.name = "dec_ttl",
7018 		.help = "decrease network TTL if available",
7019 		.priv = PRIV_ACTION(DEC_TTL, 0),
7020 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7021 		.call = parse_vc,
7022 	},
7023 	[ACTION_SET_TTL] = {
7024 		.name = "set_ttl",
7025 		.help = "set ttl value",
7026 		.priv = PRIV_ACTION(SET_TTL,
7027 			sizeof(struct rte_flow_action_set_ttl)),
7028 		.next = NEXT(action_set_ttl),
7029 		.call = parse_vc,
7030 	},
7031 	[ACTION_SET_TTL_TTL] = {
7032 		.name = "ttl_value",
7033 		.help = "new ttl value to set",
7034 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7035 		.args = ARGS(ARGS_ENTRY_HTON
7036 			     (struct rte_flow_action_set_ttl, ttl_value)),
7037 		.call = parse_vc_conf,
7038 	},
7039 	[ACTION_SET_MAC_SRC] = {
7040 		.name = "set_mac_src",
7041 		.help = "set source mac address",
7042 		.priv = PRIV_ACTION(SET_MAC_SRC,
7043 			sizeof(struct rte_flow_action_set_mac)),
7044 		.next = NEXT(action_set_mac_src),
7045 		.call = parse_vc,
7046 	},
7047 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7048 		.name = "mac_addr",
7049 		.help = "new source mac address",
7050 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7051 		.args = ARGS(ARGS_ENTRY_HTON
7052 			     (struct rte_flow_action_set_mac, mac_addr)),
7053 		.call = parse_vc_conf,
7054 	},
7055 	[ACTION_SET_MAC_DST] = {
7056 		.name = "set_mac_dst",
7057 		.help = "set destination mac address",
7058 		.priv = PRIV_ACTION(SET_MAC_DST,
7059 			sizeof(struct rte_flow_action_set_mac)),
7060 		.next = NEXT(action_set_mac_dst),
7061 		.call = parse_vc,
7062 	},
7063 	[ACTION_SET_MAC_DST_MAC_DST] = {
7064 		.name = "mac_addr",
7065 		.help = "new destination mac address to set",
7066 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7067 		.args = ARGS(ARGS_ENTRY_HTON
7068 			     (struct rte_flow_action_set_mac, mac_addr)),
7069 		.call = parse_vc_conf,
7070 	},
7071 	[ACTION_INC_TCP_SEQ] = {
7072 		.name = "inc_tcp_seq",
7073 		.help = "increase TCP sequence number",
7074 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7075 		.next = NEXT(action_inc_tcp_seq),
7076 		.call = parse_vc,
7077 	},
7078 	[ACTION_INC_TCP_SEQ_VALUE] = {
7079 		.name = "value",
7080 		.help = "the value to increase TCP sequence number by",
7081 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7082 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7083 		.call = parse_vc_conf,
7084 	},
7085 	[ACTION_DEC_TCP_SEQ] = {
7086 		.name = "dec_tcp_seq",
7087 		.help = "decrease TCP sequence number",
7088 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7089 		.next = NEXT(action_dec_tcp_seq),
7090 		.call = parse_vc,
7091 	},
7092 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7093 		.name = "value",
7094 		.help = "the value to decrease TCP sequence number by",
7095 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7096 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7097 		.call = parse_vc_conf,
7098 	},
7099 	[ACTION_INC_TCP_ACK] = {
7100 		.name = "inc_tcp_ack",
7101 		.help = "increase TCP acknowledgment number",
7102 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7103 		.next = NEXT(action_inc_tcp_ack),
7104 		.call = parse_vc,
7105 	},
7106 	[ACTION_INC_TCP_ACK_VALUE] = {
7107 		.name = "value",
7108 		.help = "the value to increase TCP acknowledgment number by",
7109 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7110 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7111 		.call = parse_vc_conf,
7112 	},
7113 	[ACTION_DEC_TCP_ACK] = {
7114 		.name = "dec_tcp_ack",
7115 		.help = "decrease TCP acknowledgment number",
7116 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7117 		.next = NEXT(action_dec_tcp_ack),
7118 		.call = parse_vc,
7119 	},
7120 	[ACTION_DEC_TCP_ACK_VALUE] = {
7121 		.name = "value",
7122 		.help = "the value to decrease TCP acknowledgment number by",
7123 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7124 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7125 		.call = parse_vc_conf,
7126 	},
7127 	[ACTION_RAW_ENCAP] = {
7128 		.name = "raw_encap",
7129 		.help = "encapsulation data, defined by set raw_encap",
7130 		.priv = PRIV_ACTION(RAW_ENCAP,
7131 			sizeof(struct action_raw_encap_data)),
7132 		.next = NEXT(action_raw_encap),
7133 		.call = parse_vc_action_raw_encap,
7134 	},
7135 	[ACTION_RAW_ENCAP_SIZE] = {
7136 		.name = "size",
7137 		.help = "raw encap size",
7138 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7139 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7140 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7141 		.call = parse_vc_conf,
7142 	},
7143 	[ACTION_RAW_ENCAP_INDEX] = {
7144 		.name = "index",
7145 		.help = "the index of raw_encap_confs",
7146 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7147 	},
7148 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7149 		.name = "{index}",
7150 		.type = "UNSIGNED",
7151 		.help = "unsigned integer value",
7152 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7153 		.call = parse_vc_action_raw_encap_index,
7154 		.comp = comp_set_raw_index,
7155 	},
7156 	[ACTION_RAW_DECAP] = {
7157 		.name = "raw_decap",
7158 		.help = "decapsulation data, defined by set raw_encap",
7159 		.priv = PRIV_ACTION(RAW_DECAP,
7160 			sizeof(struct action_raw_decap_data)),
7161 		.next = NEXT(action_raw_decap),
7162 		.call = parse_vc_action_raw_decap,
7163 	},
7164 	[ACTION_RAW_DECAP_INDEX] = {
7165 		.name = "index",
7166 		.help = "the index of raw_encap_confs",
7167 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7168 	},
7169 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7170 		.name = "{index}",
7171 		.type = "UNSIGNED",
7172 		.help = "unsigned integer value",
7173 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7174 		.call = parse_vc_action_raw_decap_index,
7175 		.comp = comp_set_raw_index,
7176 	},
7177 	[ACTION_MODIFY_FIELD] = {
7178 		.name = "modify_field",
7179 		.help = "modify destination field with data from source field",
7180 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7181 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7182 		.call = parse_vc,
7183 	},
7184 	[ACTION_MODIFY_FIELD_OP] = {
7185 		.name = "op",
7186 		.help = "operation type",
7187 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7188 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7189 		.call = parse_vc_conf,
7190 	},
7191 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7192 		.name = "{operation}",
7193 		.help = "operation type value",
7194 		.call = parse_vc_modify_field_op,
7195 		.comp = comp_set_modify_field_op,
7196 	},
7197 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7198 		.name = "dst_type",
7199 		.help = "destination field type",
7200 		.next = NEXT(action_modify_field_dst,
7201 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7202 		.call = parse_vc_conf,
7203 	},
7204 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7205 		.name = "{dst_type}",
7206 		.help = "destination field type value",
7207 		.call = parse_vc_modify_field_id,
7208 		.comp = comp_set_modify_field_id,
7209 	},
7210 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7211 		.name = "dst_level",
7212 		.help = "destination field level",
7213 		.next = NEXT(action_modify_field_dst,
7214 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7215 		.call = parse_vc_conf,
7216 	},
7217 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7218 		.name = "{dst_level}",
7219 		.help = "destination field level value",
7220 		.call = parse_vc_modify_field_level,
7221 		.comp = comp_none,
7222 	},
7223 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7224 		.name = "dst_tag_index",
7225 		.help = "destination field tag array",
7226 		.next = NEXT(action_modify_field_dst,
7227 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7228 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7229 					dst.tag_index)),
7230 		.call = parse_vc_conf,
7231 	},
7232 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7233 		.name = "dst_type_id",
7234 		.help = "destination field type ID",
7235 		.next = NEXT(action_modify_field_dst,
7236 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7237 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7238 					dst.type)),
7239 		.call = parse_vc_conf,
7240 	},
7241 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7242 		.name = "dst_class",
7243 		.help = "destination field class ID",
7244 		.next = NEXT(action_modify_field_dst,
7245 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7246 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7247 					     dst.class_id)),
7248 		.call = parse_vc_conf,
7249 	},
7250 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7251 		.name = "dst_offset",
7252 		.help = "destination field bit offset",
7253 		.next = NEXT(action_modify_field_dst,
7254 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7255 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7256 					dst.offset)),
7257 		.call = parse_vc_conf,
7258 	},
7259 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7260 		.name = "src_type",
7261 		.help = "source field type",
7262 		.next = NEXT(action_modify_field_src,
7263 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7264 		.call = parse_vc_conf,
7265 	},
7266 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7267 		.name = "{src_type}",
7268 		.help = "source field type value",
7269 		.call = parse_vc_modify_field_id,
7270 		.comp = comp_set_modify_field_id,
7271 	},
7272 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7273 		.name = "src_level",
7274 		.help = "source field level",
7275 		.next = NEXT(action_modify_field_src,
7276 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7277 		.call = parse_vc_conf,
7278 	},
7279 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7280 		.name = "{src_level}",
7281 		.help = "source field level value",
7282 		.call = parse_vc_modify_field_level,
7283 		.comp = comp_none,
7284 	},
7285 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7286 		.name = "stc_tag_index",
7287 		.help = "source field tag array",
7288 		.next = NEXT(action_modify_field_src,
7289 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7290 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7291 					src.tag_index)),
7292 		.call = parse_vc_conf,
7293 	},
7294 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7295 		.name = "src_type_id",
7296 		.help = "source field type ID",
7297 		.next = NEXT(action_modify_field_src,
7298 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7299 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7300 					src.type)),
7301 		.call = parse_vc_conf,
7302 	},
7303 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7304 		.name = "src_class",
7305 		.help = "source field class ID",
7306 		.next = NEXT(action_modify_field_src,
7307 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7308 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7309 					     src.class_id)),
7310 		.call = parse_vc_conf,
7311 	},
7312 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7313 		.name = "src_offset",
7314 		.help = "source field bit offset",
7315 		.next = NEXT(action_modify_field_src,
7316 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7317 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7318 					src.offset)),
7319 		.call = parse_vc_conf,
7320 	},
7321 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7322 		.name = "src_value",
7323 		.help = "source immediate value",
7324 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7325 			     NEXT_ENTRY(COMMON_HEX)),
7326 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7327 			     ARGS_ENTRY_ARB(0, 0),
7328 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7329 					src.value)),
7330 		.call = parse_vc_conf,
7331 	},
7332 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7333 		.name = "src_ptr",
7334 		.help = "pointer to source immediate value",
7335 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7336 			     NEXT_ENTRY(COMMON_HEX)),
7337 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7338 					src.pvalue),
7339 			     ARGS_ENTRY_ARB(0, 0),
7340 			     ARGS_ENTRY_ARB
7341 				(sizeof(struct rte_flow_action_modify_field),
7342 				 FLOW_FIELD_PATTERN_SIZE)),
7343 		.call = parse_vc_conf,
7344 	},
7345 	[ACTION_MODIFY_FIELD_WIDTH] = {
7346 		.name = "width",
7347 		.help = "number of bits to copy",
7348 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7349 			NEXT_ENTRY(COMMON_UNSIGNED)),
7350 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7351 					width)),
7352 		.call = parse_vc_conf,
7353 	},
7354 	[ACTION_SEND_TO_KERNEL] = {
7355 		.name = "send_to_kernel",
7356 		.help = "send packets to kernel",
7357 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7358 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7359 		.call = parse_vc,
7360 	},
7361 	[ACTION_IPV6_EXT_REMOVE] = {
7362 		.name = "ipv6_ext_remove",
7363 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7364 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7365 			sizeof(struct action_ipv6_ext_remove_data)),
7366 		.next = NEXT(action_ipv6_ext_remove),
7367 		.call = parse_vc_action_ipv6_ext_remove,
7368 	},
7369 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7370 		.name = "index",
7371 		.help = "the index of ipv6_ext_remove",
7372 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7373 	},
7374 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7375 		.name = "{index}",
7376 		.type = "UNSIGNED",
7377 		.help = "unsigned integer value",
7378 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7379 		.call = parse_vc_action_ipv6_ext_remove_index,
7380 		.comp = comp_set_ipv6_ext_index,
7381 	},
7382 	[ACTION_IPV6_EXT_PUSH] = {
7383 		.name = "ipv6_ext_push",
7384 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7385 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7386 			sizeof(struct action_ipv6_ext_push_data)),
7387 		.next = NEXT(action_ipv6_ext_push),
7388 		.call = parse_vc_action_ipv6_ext_push,
7389 	},
7390 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7391 		.name = "index",
7392 		.help = "the index of ipv6_ext_push",
7393 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7394 	},
7395 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7396 		.name = "{index}",
7397 		.type = "UNSIGNED",
7398 		.help = "unsigned integer value",
7399 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7400 		.call = parse_vc_action_ipv6_ext_push_index,
7401 		.comp = comp_set_ipv6_ext_index,
7402 	},
7403 	[ACTION_NAT64] = {
7404 		.name = "nat64",
7405 		.help = "NAT64 IP headers translation",
7406 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7407 		.next = NEXT(action_nat64),
7408 		.call = parse_vc,
7409 	},
7410 	[ACTION_NAT64_MODE] = {
7411 		.name = "type",
7412 		.help = "NAT64 translation type",
7413 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7414 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7415 		.call = parse_vc_conf,
7416 	},
7417 	/* Top level command. */
7418 	[SET] = {
7419 		.name = "set",
7420 		.help = "set raw encap/decap/sample data",
7421 		.type = "set raw_encap|raw_decap <index> <pattern>"
7422 				" or set sample_actions <index> <action>",
7423 		.next = NEXT(NEXT_ENTRY
7424 			     (SET_RAW_ENCAP,
7425 			      SET_RAW_DECAP,
7426 			      SET_SAMPLE_ACTIONS,
7427 			      SET_IPV6_EXT_REMOVE,
7428 			      SET_IPV6_EXT_PUSH)),
7429 		.call = parse_set_init,
7430 	},
7431 	/* Sub-level commands. */
7432 	[SET_RAW_ENCAP] = {
7433 		.name = "raw_encap",
7434 		.help = "set raw encap data",
7435 		.next = NEXT(next_set_raw),
7436 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7437 				(offsetof(struct buffer, port),
7438 				 sizeof(((struct buffer *)0)->port),
7439 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7440 		.call = parse_set_raw_encap_decap,
7441 	},
7442 	[SET_RAW_DECAP] = {
7443 		.name = "raw_decap",
7444 		.help = "set raw decap 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_INDEX] = {
7453 		.name = "{index}",
7454 		.type = "COMMON_UNSIGNED",
7455 		.help = "index of raw_encap/raw_decap data",
7456 		.next = NEXT(next_item),
7457 		.call = parse_port,
7458 	},
7459 	[SET_SAMPLE_INDEX] = {
7460 		.name = "{index}",
7461 		.type = "UNSIGNED",
7462 		.help = "index of sample actions",
7463 		.next = NEXT(next_action_sample),
7464 		.call = parse_port,
7465 	},
7466 	[SET_SAMPLE_ACTIONS] = {
7467 		.name = "sample_actions",
7468 		.help = "set sample actions list",
7469 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7470 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7471 				(offsetof(struct buffer, port),
7472 				 sizeof(((struct buffer *)0)->port),
7473 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7474 		.call = parse_set_sample_action,
7475 	},
7476 	[SET_IPV6_EXT_PUSH] = {
7477 		.name = "ipv6_ext_push",
7478 		.help = "set IPv6 extension header",
7479 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7480 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7481 				(offsetof(struct buffer, port),
7482 				 sizeof(((struct buffer *)0)->port),
7483 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7484 		.call = parse_set_ipv6_ext_action,
7485 	},
7486 	[SET_IPV6_EXT_REMOVE] = {
7487 		.name = "ipv6_ext_remove",
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_INDEX] = {
7497 		.name = "{index}",
7498 		.type = "UNSIGNED",
7499 		.help = "index of ipv6 extension push/remove actions",
7500 		.next = NEXT(item_ipv6_push_ext),
7501 		.call = parse_port,
7502 	},
7503 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7504 		.name = "ipv6_ext",
7505 		.help = "set IPv6 extension header",
7506 		.priv = PRIV_ITEM(IPV6_EXT,
7507 				  sizeof(struct rte_flow_item_ipv6_ext)),
7508 		.next = NEXT(item_ipv6_push_ext_type),
7509 		.call = parse_vc,
7510 	},
7511 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7512 		.name = "type",
7513 		.help = "set IPv6 extension type",
7514 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7515 					     next_hdr)),
7516 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7517 			     item_param),
7518 	},
7519 	[ACTION_SET_TAG] = {
7520 		.name = "set_tag",
7521 		.help = "set tag",
7522 		.priv = PRIV_ACTION(SET_TAG,
7523 			sizeof(struct rte_flow_action_set_tag)),
7524 		.next = NEXT(action_set_tag),
7525 		.call = parse_vc,
7526 	},
7527 	[ACTION_SET_TAG_INDEX] = {
7528 		.name = "index",
7529 		.help = "index of tag array",
7530 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7531 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7532 		.call = parse_vc_conf,
7533 	},
7534 	[ACTION_SET_TAG_DATA] = {
7535 		.name = "data",
7536 		.help = "tag value",
7537 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7538 		.args = ARGS(ARGS_ENTRY
7539 			     (struct rte_flow_action_set_tag, data)),
7540 		.call = parse_vc_conf,
7541 	},
7542 	[ACTION_SET_TAG_MASK] = {
7543 		.name = "mask",
7544 		.help = "mask for tag value",
7545 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7546 		.args = ARGS(ARGS_ENTRY
7547 			     (struct rte_flow_action_set_tag, mask)),
7548 		.call = parse_vc_conf,
7549 	},
7550 	[ACTION_SET_META] = {
7551 		.name = "set_meta",
7552 		.help = "set metadata",
7553 		.priv = PRIV_ACTION(SET_META,
7554 			sizeof(struct rte_flow_action_set_meta)),
7555 		.next = NEXT(action_set_meta),
7556 		.call = parse_vc_action_set_meta,
7557 	},
7558 	[ACTION_SET_META_DATA] = {
7559 		.name = "data",
7560 		.help = "metadata value",
7561 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7562 		.args = ARGS(ARGS_ENTRY
7563 			     (struct rte_flow_action_set_meta, data)),
7564 		.call = parse_vc_conf,
7565 	},
7566 	[ACTION_SET_META_MASK] = {
7567 		.name = "mask",
7568 		.help = "mask for metadata value",
7569 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7570 		.args = ARGS(ARGS_ENTRY
7571 			     (struct rte_flow_action_set_meta, mask)),
7572 		.call = parse_vc_conf,
7573 	},
7574 	[ACTION_SET_IPV4_DSCP] = {
7575 		.name = "set_ipv4_dscp",
7576 		.help = "set DSCP value",
7577 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7578 			sizeof(struct rte_flow_action_set_dscp)),
7579 		.next = NEXT(action_set_ipv4_dscp),
7580 		.call = parse_vc,
7581 	},
7582 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7583 		.name = "dscp_value",
7584 		.help = "new IPv4 DSCP value to set",
7585 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7586 		.args = ARGS(ARGS_ENTRY
7587 			     (struct rte_flow_action_set_dscp, dscp)),
7588 		.call = parse_vc_conf,
7589 	},
7590 	[ACTION_SET_IPV6_DSCP] = {
7591 		.name = "set_ipv6_dscp",
7592 		.help = "set DSCP value",
7593 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7594 			sizeof(struct rte_flow_action_set_dscp)),
7595 		.next = NEXT(action_set_ipv6_dscp),
7596 		.call = parse_vc,
7597 	},
7598 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7599 		.name = "dscp_value",
7600 		.help = "new IPv6 DSCP value to set",
7601 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7602 		.args = ARGS(ARGS_ENTRY
7603 			     (struct rte_flow_action_set_dscp, dscp)),
7604 		.call = parse_vc_conf,
7605 	},
7606 	[ACTION_AGE] = {
7607 		.name = "age",
7608 		.help = "set a specific metadata header",
7609 		.next = NEXT(action_age),
7610 		.priv = PRIV_ACTION(AGE,
7611 			sizeof(struct rte_flow_action_age)),
7612 		.call = parse_vc,
7613 	},
7614 	[ACTION_AGE_TIMEOUT] = {
7615 		.name = "timeout",
7616 		.help = "flow age timeout value",
7617 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7618 					   timeout, 24)),
7619 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7620 		.call = parse_vc_conf,
7621 	},
7622 	[ACTION_AGE_UPDATE] = {
7623 		.name = "age_update",
7624 		.help = "update aging parameter",
7625 		.next = NEXT(action_age_update),
7626 		.priv = PRIV_ACTION(AGE,
7627 				    sizeof(struct rte_flow_update_age)),
7628 		.call = parse_vc,
7629 	},
7630 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7631 		.name = "timeout",
7632 		.help = "age timeout update value",
7633 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7634 					   timeout, 24)),
7635 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7636 		.call = parse_vc_conf_timeout,
7637 	},
7638 	[ACTION_AGE_UPDATE_TOUCH] = {
7639 		.name = "touch",
7640 		.help = "this flow is touched",
7641 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7642 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7643 					   touch, 1)),
7644 		.call = parse_vc_conf,
7645 	},
7646 	[ACTION_SAMPLE] = {
7647 		.name = "sample",
7648 		.help = "set a sample action",
7649 		.next = NEXT(action_sample),
7650 		.priv = PRIV_ACTION(SAMPLE,
7651 			sizeof(struct action_sample_data)),
7652 		.call = parse_vc_action_sample,
7653 	},
7654 	[ACTION_SAMPLE_RATIO] = {
7655 		.name = "ratio",
7656 		.help = "flow sample ratio value",
7657 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7658 		.args = ARGS(ARGS_ENTRY_ARB
7659 			     (offsetof(struct action_sample_data, conf) +
7660 			      offsetof(struct rte_flow_action_sample, ratio),
7661 			      sizeof(((struct rte_flow_action_sample *)0)->
7662 				     ratio))),
7663 	},
7664 	[ACTION_SAMPLE_INDEX] = {
7665 		.name = "index",
7666 		.help = "the index of sample actions list",
7667 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7668 	},
7669 	[ACTION_SAMPLE_INDEX_VALUE] = {
7670 		.name = "{index}",
7671 		.type = "COMMON_UNSIGNED",
7672 		.help = "unsigned integer value",
7673 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7674 		.call = parse_vc_action_sample_index,
7675 		.comp = comp_set_sample_index,
7676 	},
7677 	[ACTION_CONNTRACK] = {
7678 		.name = "conntrack",
7679 		.help = "create a conntrack object",
7680 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7681 		.priv = PRIV_ACTION(CONNTRACK,
7682 				    sizeof(struct rte_flow_action_conntrack)),
7683 		.call = parse_vc,
7684 	},
7685 	[ACTION_CONNTRACK_UPDATE] = {
7686 		.name = "conntrack_update",
7687 		.help = "update a conntrack object",
7688 		.next = NEXT(action_update_conntrack),
7689 		.priv = PRIV_ACTION(CONNTRACK,
7690 				    sizeof(struct rte_flow_modify_conntrack)),
7691 		.call = parse_vc,
7692 	},
7693 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7694 		.name = "dir",
7695 		.help = "update a conntrack object direction",
7696 		.next = NEXT(action_update_conntrack),
7697 		.call = parse_vc_action_conntrack_update,
7698 	},
7699 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7700 		.name = "ctx",
7701 		.help = "update a conntrack object context",
7702 		.next = NEXT(action_update_conntrack),
7703 		.call = parse_vc_action_conntrack_update,
7704 	},
7705 	[ACTION_PORT_REPRESENTOR] = {
7706 		.name = "port_representor",
7707 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7708 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7709 				    sizeof(struct rte_flow_action_ethdev)),
7710 		.next = NEXT(action_port_representor),
7711 		.call = parse_vc,
7712 	},
7713 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7714 		.name = "port_id",
7715 		.help = "ethdev port ID",
7716 		.next = NEXT(action_port_representor,
7717 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7718 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7719 					port_id)),
7720 		.call = parse_vc_conf,
7721 	},
7722 	[ACTION_REPRESENTED_PORT] = {
7723 		.name = "represented_port",
7724 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7725 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7726 				sizeof(struct rte_flow_action_ethdev)),
7727 		.next = NEXT(action_represented_port),
7728 		.call = parse_vc,
7729 	},
7730 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7731 		.name = "ethdev_port_id",
7732 		.help = "ethdev port ID",
7733 		.next = NEXT(action_represented_port,
7734 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7735 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7736 					port_id)),
7737 		.call = parse_vc_conf,
7738 	},
7739 	/* Indirect action destroy arguments. */
7740 	[INDIRECT_ACTION_DESTROY_ID] = {
7741 		.name = "action_id",
7742 		.help = "specify a indirect action id to destroy",
7743 		.next = NEXT(next_ia_destroy_attr,
7744 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7745 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7746 					    args.ia_destroy.action_id)),
7747 		.call = parse_ia_destroy,
7748 	},
7749 	/* Indirect action create arguments. */
7750 	[INDIRECT_ACTION_CREATE_ID] = {
7751 		.name = "action_id",
7752 		.help = "specify a indirect action id to create",
7753 		.next = NEXT(next_ia_create_attr,
7754 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7755 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7756 	},
7757 	[ACTION_INDIRECT] = {
7758 		.name = "indirect",
7759 		.help = "apply indirect action by id",
7760 		.priv = PRIV_ACTION(INDIRECT, 0),
7761 		.next = NEXT(next_ia),
7762 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7763 		.call = parse_vc,
7764 	},
7765 	[ACTION_INDIRECT_LIST] = {
7766 		.name = "indirect_list",
7767 		.help = "apply indirect list action by id",
7768 		.priv = PRIV_ACTION(INDIRECT_LIST,
7769 				    sizeof(struct
7770 					   rte_flow_action_indirect_list)),
7771 		.next = NEXT(next_ial),
7772 		.call = parse_vc,
7773 	},
7774 	[ACTION_INDIRECT_LIST_HANDLE] = {
7775 		.name = "handle",
7776 		.help = "indirect list handle",
7777 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7778 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7779 	},
7780 	[ACTION_INDIRECT_LIST_CONF] = {
7781 		.name = "conf",
7782 		.help = "indirect list configuration",
7783 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7784 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7785 	},
7786 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7787 		.type = "UNSIGNED",
7788 		.help = "unsigned integer value",
7789 		.call = parse_indlst_id2ptr,
7790 	},
7791 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7792 		.type = "UNSIGNED",
7793 		.help = "unsigned integer value",
7794 		.call = parse_indlst_id2ptr,
7795 	},
7796 	[ACTION_SHARED_INDIRECT] = {
7797 		.name = "shared_indirect",
7798 		.help = "apply indirect action by id and port",
7799 		.priv = PRIV_ACTION(INDIRECT, 0),
7800 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7801 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7802 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7803 		.call = parse_vc,
7804 	},
7805 	[INDIRECT_ACTION_PORT] = {
7806 		.name = "{indirect_action_port}",
7807 		.type = "INDIRECT_ACTION_PORT",
7808 		.help = "indirect action port",
7809 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7810 		.call = parse_ia_port,
7811 		.comp = comp_none,
7812 	},
7813 	[INDIRECT_ACTION_ID2PTR] = {
7814 		.name = "{action_id}",
7815 		.type = "INDIRECT_ACTION_ID",
7816 		.help = "indirect action id",
7817 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7818 		.call = parse_ia_id2ptr,
7819 		.comp = comp_none,
7820 	},
7821 	[INDIRECT_ACTION_INGRESS] = {
7822 		.name = "ingress",
7823 		.help = "affect rule to ingress",
7824 		.next = NEXT(next_ia_create_attr),
7825 		.call = parse_ia,
7826 	},
7827 	[INDIRECT_ACTION_EGRESS] = {
7828 		.name = "egress",
7829 		.help = "affect rule to egress",
7830 		.next = NEXT(next_ia_create_attr),
7831 		.call = parse_ia,
7832 	},
7833 	[INDIRECT_ACTION_TRANSFER] = {
7834 		.name = "transfer",
7835 		.help = "affect rule to transfer",
7836 		.next = NEXT(next_ia_create_attr),
7837 		.call = parse_ia,
7838 	},
7839 	[INDIRECT_ACTION_SPEC] = {
7840 		.name = "action",
7841 		.help = "specify action to create indirect handle",
7842 		.next = NEXT(next_action),
7843 	},
7844 	[INDIRECT_ACTION_LIST] = {
7845 		.name = "list",
7846 		.help = "specify actions for indirect handle list",
7847 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7848 		.call = parse_ia,
7849 	},
7850 	[INDIRECT_ACTION_FLOW_CONF] = {
7851 		.name = "flow_conf",
7852 		.help = "specify actions configuration for indirect handle list",
7853 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7854 		.call = parse_ia,
7855 	},
7856 	[ACTION_POL_G] = {
7857 		.name = "g_actions",
7858 		.help = "submit a list of associated actions for green",
7859 		.next = NEXT(next_action),
7860 		.call = parse_mp,
7861 	},
7862 	[ACTION_POL_Y] = {
7863 		.name = "y_actions",
7864 		.help = "submit a list of associated actions for yellow",
7865 		.next = NEXT(next_action),
7866 	},
7867 	[ACTION_POL_R] = {
7868 		.name = "r_actions",
7869 		.help = "submit a list of associated actions for red",
7870 		.next = NEXT(next_action),
7871 	},
7872 	[ACTION_QUOTA_CREATE] = {
7873 		.name = "quota_create",
7874 		.help = "create quota action",
7875 		.priv = PRIV_ACTION(QUOTA,
7876 				    sizeof(struct rte_flow_action_quota)),
7877 		.next = NEXT(action_quota_create),
7878 		.call = parse_vc
7879 	},
7880 	[ACTION_QUOTA_CREATE_LIMIT] = {
7881 		.name = "limit",
7882 		.help = "quota limit",
7883 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
7884 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
7885 		.call = parse_vc_conf
7886 	},
7887 	[ACTION_QUOTA_CREATE_MODE] = {
7888 		.name = "mode",
7889 		.help = "quota mode",
7890 		.next = NEXT(action_quota_create,
7891 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
7892 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
7893 		.call = parse_vc_conf
7894 	},
7895 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
7896 		.name = "mode_name",
7897 		.help = "quota mode name",
7898 		.call = parse_quota_mode_name,
7899 		.comp = comp_quota_mode_name
7900 	},
7901 	[ACTION_QUOTA_QU] = {
7902 		.name = "quota_update",
7903 		.help = "update quota action",
7904 		.priv = PRIV_ACTION(QUOTA,
7905 				    sizeof(struct rte_flow_update_quota)),
7906 		.next = NEXT(action_quota_update),
7907 		.call = parse_vc
7908 	},
7909 	[ACTION_QUOTA_QU_LIMIT] = {
7910 		.name = "limit",
7911 		.help = "quota limit",
7912 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7913 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
7914 		.call = parse_vc_conf
7915 	},
7916 	[ACTION_QUOTA_QU_UPDATE_OP] = {
7917 		.name = "update_op",
7918 		.help = "query update op SET|ADD",
7919 		.next = NEXT(action_quota_update,
7920 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
7921 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
7922 		.call = parse_vc_conf
7923 	},
7924 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
7925 		.name = "update_op_name",
7926 		.help = "quota update op name",
7927 		.call = parse_quota_update_name,
7928 		.comp = comp_quota_update_name
7929 	},
7930 
7931 	/* Top-level command. */
7932 	[ADD] = {
7933 		.name = "add",
7934 		.type = "port meter policy {port_id} {arg}",
7935 		.help = "add port meter policy",
7936 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
7937 		.call = parse_init,
7938 	},
7939 	/* Sub-level commands. */
7940 	[ITEM_POL_PORT] = {
7941 		.name = "port",
7942 		.help = "add port meter policy",
7943 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
7944 	},
7945 	[ITEM_POL_METER] = {
7946 		.name = "meter",
7947 		.help = "add port meter policy",
7948 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
7949 	},
7950 	[ITEM_POL_POLICY] = {
7951 		.name = "policy",
7952 		.help = "add port meter policy",
7953 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
7954 				NEXT_ENTRY(ACTION_POL_Y),
7955 				NEXT_ENTRY(ACTION_POL_G),
7956 				NEXT_ENTRY(COMMON_POLICY_ID),
7957 				NEXT_ENTRY(COMMON_PORT_ID)),
7958 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
7959 				ARGS_ENTRY(struct buffer, port)),
7960 		.call = parse_mp,
7961 	},
7962 	[ITEM_AGGR_AFFINITY] = {
7963 		.name = "aggr_affinity",
7964 		.help = "match on the aggregated port receiving the packets",
7965 		.priv = PRIV_ITEM(AGGR_AFFINITY,
7966 				  sizeof(struct rte_flow_item_aggr_affinity)),
7967 		.next = NEXT(item_aggr_affinity),
7968 		.call = parse_vc,
7969 	},
7970 	[ITEM_AGGR_AFFINITY_VALUE] = {
7971 		.name = "affinity",
7972 		.help = "aggregated affinity value",
7973 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
7974 			     item_param),
7975 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
7976 					affinity)),
7977 	},
7978 	[ITEM_TX_QUEUE] = {
7979 		.name = "tx_queue",
7980 		.help = "match on the tx queue of send packet",
7981 		.priv = PRIV_ITEM(TX_QUEUE,
7982 				  sizeof(struct rte_flow_item_tx_queue)),
7983 		.next = NEXT(item_tx_queue),
7984 		.call = parse_vc,
7985 	},
7986 	[ITEM_TX_QUEUE_VALUE] = {
7987 		.name = "tx_queue_value",
7988 		.help = "tx queue value",
7989 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
7990 			     item_param),
7991 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
7992 					tx_queue)),
7993 	},
7994 };
7995 
7996 /** Remove and return last entry from argument stack. */
7997 static const struct arg *
7998 pop_args(struct context *ctx)
7999 {
8000 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8001 }
8002 
8003 /** Add entry on top of the argument stack. */
8004 static int
8005 push_args(struct context *ctx, const struct arg *arg)
8006 {
8007 	if (ctx->args_num == CTX_STACK_SIZE)
8008 		return -1;
8009 	ctx->args[ctx->args_num++] = arg;
8010 	return 0;
8011 }
8012 
8013 /** Spread value into buffer according to bit-mask. */
8014 static size_t
8015 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8016 {
8017 	uint32_t i = arg->size;
8018 	uint32_t end = 0;
8019 	int sub = 1;
8020 	int add = 0;
8021 	size_t len = 0;
8022 
8023 	if (!arg->mask)
8024 		return 0;
8025 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8026 	if (!arg->hton) {
8027 		i = 0;
8028 		end = arg->size;
8029 		sub = 0;
8030 		add = 1;
8031 	}
8032 #endif
8033 	while (i != end) {
8034 		unsigned int shift = 0;
8035 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8036 
8037 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8038 			if (!(arg->mask[i] & (1 << shift)))
8039 				continue;
8040 			++len;
8041 			if (!dst)
8042 				continue;
8043 			*buf &= ~(1 << shift);
8044 			*buf |= (val & 1) << shift;
8045 			val >>= 1;
8046 		}
8047 		i += add;
8048 	}
8049 	return len;
8050 }
8051 
8052 /** Compare a string with a partial one of a given length. */
8053 static int
8054 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8055 {
8056 	int r = strncmp(full, partial, partial_len);
8057 
8058 	if (r)
8059 		return r;
8060 	if (strlen(full) <= partial_len)
8061 		return 0;
8062 	return full[partial_len];
8063 }
8064 
8065 /**
8066  * Parse a prefix length and generate a bit-mask.
8067  *
8068  * Last argument (ctx->args) is retrieved to determine mask size, storage
8069  * location and whether the result must use network byte ordering.
8070  */
8071 static int
8072 parse_prefix(struct context *ctx, const struct token *token,
8073 	     const char *str, unsigned int len,
8074 	     void *buf, unsigned int size)
8075 {
8076 	const struct arg *arg = pop_args(ctx);
8077 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8078 	char *end;
8079 	uintmax_t u;
8080 	unsigned int bytes;
8081 	unsigned int extra;
8082 
8083 	(void)token;
8084 	/* Argument is expected. */
8085 	if (!arg)
8086 		return -1;
8087 	errno = 0;
8088 	u = strtoumax(str, &end, 0);
8089 	if (errno || (size_t)(end - str) != len)
8090 		goto error;
8091 	if (arg->mask) {
8092 		uintmax_t v = 0;
8093 
8094 		extra = arg_entry_bf_fill(NULL, 0, arg);
8095 		if (u > extra)
8096 			goto error;
8097 		if (!ctx->object)
8098 			return len;
8099 		extra -= u;
8100 		while (u--)
8101 			(v <<= 1, v |= 1);
8102 		v <<= extra;
8103 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8104 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8105 			goto error;
8106 		return len;
8107 	}
8108 	bytes = u / 8;
8109 	extra = u % 8;
8110 	size = arg->size;
8111 	if (bytes > size || bytes + !!extra > size)
8112 		goto error;
8113 	if (!ctx->object)
8114 		return len;
8115 	buf = (uint8_t *)ctx->object + arg->offset;
8116 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8117 	if (!arg->hton) {
8118 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8119 		memset(buf, 0x00, size - bytes);
8120 		if (extra)
8121 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8122 	} else
8123 #endif
8124 	{
8125 		memset(buf, 0xff, bytes);
8126 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8127 		if (extra)
8128 			((uint8_t *)buf)[bytes] = conv[extra];
8129 	}
8130 	if (ctx->objmask)
8131 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8132 	return len;
8133 error:
8134 	push_args(ctx, arg);
8135 	return -1;
8136 }
8137 
8138 /** Default parsing function for token name matching. */
8139 static int
8140 parse_default(struct context *ctx, const struct token *token,
8141 	      const char *str, unsigned int len,
8142 	      void *buf, unsigned int size)
8143 {
8144 	(void)ctx;
8145 	(void)buf;
8146 	(void)size;
8147 	if (strcmp_partial(token->name, str, len))
8148 		return -1;
8149 	return len;
8150 }
8151 
8152 /** Parse flow command, initialize output buffer for subsequent tokens. */
8153 static int
8154 parse_init(struct context *ctx, const struct token *token,
8155 	   const char *str, unsigned int len,
8156 	   void *buf, unsigned int size)
8157 {
8158 	struct buffer *out = buf;
8159 
8160 	/* Token name must match. */
8161 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8162 		return -1;
8163 	/* Nothing else to do if there is no buffer. */
8164 	if (!out)
8165 		return len;
8166 	/* Make sure buffer is large enough. */
8167 	if (size < sizeof(*out))
8168 		return -1;
8169 	/* Initialize buffer. */
8170 	memset(out, 0x00, sizeof(*out));
8171 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8172 	ctx->objdata = 0;
8173 	ctx->object = out;
8174 	ctx->objmask = NULL;
8175 	return len;
8176 }
8177 
8178 /** Parse tokens for indirect action commands. */
8179 static int
8180 parse_ia(struct context *ctx, const struct token *token,
8181 	 const char *str, unsigned int len,
8182 	 void *buf, unsigned int size)
8183 {
8184 	struct buffer *out = buf;
8185 
8186 	/* Token name must match. */
8187 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8188 		return -1;
8189 	/* Nothing else to do if there is no buffer. */
8190 	if (!out)
8191 		return len;
8192 	if (!out->command) {
8193 		if (ctx->curr != INDIRECT_ACTION)
8194 			return -1;
8195 		if (sizeof(*out) > size)
8196 			return -1;
8197 		out->command = ctx->curr;
8198 		ctx->objdata = 0;
8199 		ctx->object = out;
8200 		ctx->objmask = NULL;
8201 		out->args.vc.data = (uint8_t *)out + size;
8202 		return len;
8203 	}
8204 	switch (ctx->curr) {
8205 	case INDIRECT_ACTION_CREATE:
8206 	case INDIRECT_ACTION_UPDATE:
8207 	case INDIRECT_ACTION_QUERY_UPDATE:
8208 		out->args.vc.actions =
8209 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8210 					       sizeof(double));
8211 		out->args.vc.attr.group = UINT32_MAX;
8212 		/* fallthrough */
8213 	case INDIRECT_ACTION_QUERY:
8214 		out->command = ctx->curr;
8215 		ctx->objdata = 0;
8216 		ctx->object = out;
8217 		ctx->objmask = NULL;
8218 		return len;
8219 	case INDIRECT_ACTION_EGRESS:
8220 		out->args.vc.attr.egress = 1;
8221 		return len;
8222 	case INDIRECT_ACTION_INGRESS:
8223 		out->args.vc.attr.ingress = 1;
8224 		return len;
8225 	case INDIRECT_ACTION_TRANSFER:
8226 		out->args.vc.attr.transfer = 1;
8227 		return len;
8228 	case INDIRECT_ACTION_QU_MODE:
8229 		return len;
8230 	case INDIRECT_ACTION_LIST:
8231 		out->command = INDIRECT_ACTION_LIST_CREATE;
8232 		return len;
8233 	case INDIRECT_ACTION_FLOW_CONF:
8234 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8235 		return len;
8236 	default:
8237 		return -1;
8238 	}
8239 }
8240 
8241 
8242 /** Parse tokens for indirect action destroy command. */
8243 static int
8244 parse_ia_destroy(struct context *ctx, const struct token *token,
8245 		 const char *str, unsigned int len,
8246 		 void *buf, unsigned int size)
8247 {
8248 	struct buffer *out = buf;
8249 	uint32_t *action_id;
8250 
8251 	/* Token name must match. */
8252 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8253 		return -1;
8254 	/* Nothing else to do if there is no buffer. */
8255 	if (!out)
8256 		return len;
8257 	if (!out->command || out->command == INDIRECT_ACTION) {
8258 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8259 			return -1;
8260 		if (sizeof(*out) > size)
8261 			return -1;
8262 		out->command = ctx->curr;
8263 		ctx->objdata = 0;
8264 		ctx->object = out;
8265 		ctx->objmask = NULL;
8266 		out->args.ia_destroy.action_id =
8267 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8268 					       sizeof(double));
8269 		return len;
8270 	}
8271 	action_id = out->args.ia_destroy.action_id
8272 		    + out->args.ia_destroy.action_id_n++;
8273 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8274 		return -1;
8275 	ctx->objdata = 0;
8276 	ctx->object = action_id;
8277 	ctx->objmask = NULL;
8278 	return len;
8279 }
8280 
8281 /** Parse tokens for indirect action commands. */
8282 static int
8283 parse_qia(struct context *ctx, const struct token *token,
8284 	  const char *str, unsigned int len,
8285 	  void *buf, unsigned int size)
8286 {
8287 	struct buffer *out = buf;
8288 
8289 	/* Token name must match. */
8290 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8291 		return -1;
8292 	/* Nothing else to do if there is no buffer. */
8293 	if (!out)
8294 		return len;
8295 	if (!out->command) {
8296 		if (ctx->curr != QUEUE)
8297 			return -1;
8298 		if (sizeof(*out) > size)
8299 			return -1;
8300 		out->args.vc.data = (uint8_t *)out + size;
8301 		return len;
8302 	}
8303 	switch (ctx->curr) {
8304 	case QUEUE_INDIRECT_ACTION:
8305 		return len;
8306 	case QUEUE_INDIRECT_ACTION_CREATE:
8307 	case QUEUE_INDIRECT_ACTION_UPDATE:
8308 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8309 		out->args.vc.actions =
8310 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8311 					       sizeof(double));
8312 		out->args.vc.attr.group = UINT32_MAX;
8313 		/* fallthrough */
8314 	case QUEUE_INDIRECT_ACTION_QUERY:
8315 		out->command = ctx->curr;
8316 		ctx->objdata = 0;
8317 		ctx->object = out;
8318 		ctx->objmask = NULL;
8319 		return len;
8320 	case QUEUE_INDIRECT_ACTION_EGRESS:
8321 		out->args.vc.attr.egress = 1;
8322 		return len;
8323 	case QUEUE_INDIRECT_ACTION_INGRESS:
8324 		out->args.vc.attr.ingress = 1;
8325 		return len;
8326 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8327 		out->args.vc.attr.transfer = 1;
8328 		return len;
8329 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8330 		return len;
8331 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8332 		return len;
8333 	case QUEUE_INDIRECT_ACTION_LIST:
8334 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8335 		return len;
8336 	default:
8337 		return -1;
8338 	}
8339 }
8340 
8341 /** Parse tokens for indirect action destroy command. */
8342 static int
8343 parse_qia_destroy(struct context *ctx, const struct token *token,
8344 		  const char *str, unsigned int len,
8345 		  void *buf, unsigned int size)
8346 {
8347 	struct buffer *out = buf;
8348 	uint32_t *action_id;
8349 
8350 	/* Token name must match. */
8351 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8352 		return -1;
8353 	/* Nothing else to do if there is no buffer. */
8354 	if (!out)
8355 		return len;
8356 	if (!out->command || out->command == QUEUE) {
8357 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8358 			return -1;
8359 		if (sizeof(*out) > size)
8360 			return -1;
8361 		out->command = ctx->curr;
8362 		ctx->objdata = 0;
8363 		ctx->object = out;
8364 		ctx->objmask = NULL;
8365 		out->args.ia_destroy.action_id =
8366 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8367 					       sizeof(double));
8368 		return len;
8369 	}
8370 	switch (ctx->curr) {
8371 	case QUEUE_INDIRECT_ACTION:
8372 		out->command = ctx->curr;
8373 		ctx->objdata = 0;
8374 		ctx->object = out;
8375 		ctx->objmask = NULL;
8376 		return len;
8377 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8378 		action_id = out->args.ia_destroy.action_id
8379 				+ out->args.ia_destroy.action_id_n++;
8380 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8381 			return -1;
8382 		ctx->objdata = 0;
8383 		ctx->object = action_id;
8384 		ctx->objmask = NULL;
8385 		return len;
8386 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8387 		return len;
8388 	default:
8389 		return -1;
8390 	}
8391 }
8392 
8393 /** Parse tokens for meter policy action commands. */
8394 static int
8395 parse_mp(struct context *ctx, const struct token *token,
8396 	const char *str, unsigned int len,
8397 	void *buf, unsigned int size)
8398 {
8399 	struct buffer *out = buf;
8400 
8401 	/* Token name must match. */
8402 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8403 		return -1;
8404 	/* Nothing else to do if there is no buffer. */
8405 	if (!out)
8406 		return len;
8407 	if (!out->command) {
8408 		if (ctx->curr != ITEM_POL_POLICY)
8409 			return -1;
8410 		if (sizeof(*out) > size)
8411 			return -1;
8412 		out->command = ctx->curr;
8413 		ctx->objdata = 0;
8414 		ctx->object = out;
8415 		ctx->objmask = NULL;
8416 		out->args.vc.data = (uint8_t *)out + size;
8417 		return len;
8418 	}
8419 	switch (ctx->curr) {
8420 	case ACTION_POL_G:
8421 		out->args.vc.actions =
8422 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8423 					sizeof(double));
8424 		out->command = ctx->curr;
8425 		ctx->objdata = 0;
8426 		ctx->object = out;
8427 		ctx->objmask = NULL;
8428 		return len;
8429 	default:
8430 		return -1;
8431 	}
8432 }
8433 
8434 /** Parse tokens for validate/create commands. */
8435 static int
8436 parse_vc(struct context *ctx, const struct token *token,
8437 	 const char *str, unsigned int len,
8438 	 void *buf, unsigned int size)
8439 {
8440 	struct buffer *out = buf;
8441 	uint8_t *data;
8442 	uint32_t data_size;
8443 
8444 	/* Token name must match. */
8445 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8446 		return -1;
8447 	/* Nothing else to do if there is no buffer. */
8448 	if (!out)
8449 		return len;
8450 	if (!out->command) {
8451 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8452 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8453 		    ctx->curr != ACTIONS_TEMPLATE_CREATE)
8454 			return -1;
8455 		if (sizeof(*out) > size)
8456 			return -1;
8457 		out->command = ctx->curr;
8458 		ctx->objdata = 0;
8459 		ctx->object = out;
8460 		ctx->objmask = NULL;
8461 		out->args.vc.data = (uint8_t *)out + size;
8462 		return len;
8463 	}
8464 	ctx->objdata = 0;
8465 	switch (ctx->curr) {
8466 	default:
8467 		ctx->object = &out->args.vc.attr;
8468 		break;
8469 	case VC_TUNNEL_SET:
8470 	case VC_TUNNEL_MATCH:
8471 		ctx->object = &out->args.vc.tunnel_ops;
8472 		break;
8473 	case VC_USER_ID:
8474 		ctx->object = out;
8475 		break;
8476 	}
8477 	ctx->objmask = NULL;
8478 	switch (ctx->curr) {
8479 	case VC_GROUP:
8480 	case VC_PRIORITY:
8481 	case VC_USER_ID:
8482 		return len;
8483 	case VC_TUNNEL_SET:
8484 		out->args.vc.tunnel_ops.enabled = 1;
8485 		out->args.vc.tunnel_ops.actions = 1;
8486 		return len;
8487 	case VC_TUNNEL_MATCH:
8488 		out->args.vc.tunnel_ops.enabled = 1;
8489 		out->args.vc.tunnel_ops.items = 1;
8490 		return len;
8491 	case VC_INGRESS:
8492 		out->args.vc.attr.ingress = 1;
8493 		return len;
8494 	case VC_EGRESS:
8495 		out->args.vc.attr.egress = 1;
8496 		return len;
8497 	case VC_TRANSFER:
8498 		out->args.vc.attr.transfer = 1;
8499 		return len;
8500 	case ITEM_PATTERN:
8501 		out->args.vc.pattern =
8502 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8503 					       sizeof(double));
8504 		ctx->object = out->args.vc.pattern;
8505 		ctx->objmask = NULL;
8506 		return len;
8507 	case ITEM_END:
8508 		if ((out->command == VALIDATE || out->command == CREATE) &&
8509 		    ctx->last)
8510 			return -1;
8511 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8512 		    !ctx->last)
8513 			return -1;
8514 		break;
8515 	case ACTIONS:
8516 		out->args.vc.actions = out->args.vc.pattern ?
8517 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8518 					       (out->args.vc.pattern +
8519 						out->args.vc.pattern_n),
8520 					       sizeof(double)) :
8521 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8522 					       sizeof(double));
8523 		ctx->object = out->args.vc.actions;
8524 		ctx->objmask = NULL;
8525 		return len;
8526 	default:
8527 		if (!token->priv)
8528 			return -1;
8529 		break;
8530 	}
8531 	if (!out->args.vc.actions) {
8532 		const struct parse_item_priv *priv = token->priv;
8533 		struct rte_flow_item *item =
8534 			out->args.vc.pattern + out->args.vc.pattern_n;
8535 
8536 		data_size = priv->size * 3; /* spec, last, mask */
8537 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8538 					       (out->args.vc.data - data_size),
8539 					       sizeof(double));
8540 		if ((uint8_t *)item + sizeof(*item) > data)
8541 			return -1;
8542 		*item = (struct rte_flow_item){
8543 			.type = priv->type,
8544 		};
8545 		++out->args.vc.pattern_n;
8546 		ctx->object = item;
8547 		ctx->objmask = NULL;
8548 	} else {
8549 		const struct parse_action_priv *priv = token->priv;
8550 		struct rte_flow_action *action =
8551 			out->args.vc.actions + out->args.vc.actions_n;
8552 
8553 		data_size = priv->size; /* configuration */
8554 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8555 					       (out->args.vc.data - data_size),
8556 					       sizeof(double));
8557 		if ((uint8_t *)action + sizeof(*action) > data)
8558 			return -1;
8559 		*action = (struct rte_flow_action){
8560 			.type = priv->type,
8561 			.conf = data_size ? data : NULL,
8562 		};
8563 		++out->args.vc.actions_n;
8564 		ctx->object = action;
8565 		ctx->objmask = NULL;
8566 	}
8567 	memset(data, 0, data_size);
8568 	out->args.vc.data = data;
8569 	ctx->objdata = data_size;
8570 	return len;
8571 }
8572 
8573 /** Parse pattern item parameter type. */
8574 static int
8575 parse_vc_spec(struct context *ctx, const struct token *token,
8576 	      const char *str, unsigned int len,
8577 	      void *buf, unsigned int size)
8578 {
8579 	struct buffer *out = buf;
8580 	struct rte_flow_item *item;
8581 	uint32_t data_size;
8582 	int index;
8583 	int objmask = 0;
8584 
8585 	(void)size;
8586 	/* Token name must match. */
8587 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8588 		return -1;
8589 	/* Parse parameter types. */
8590 	switch (ctx->curr) {
8591 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8592 
8593 	case ITEM_PARAM_IS:
8594 		index = 0;
8595 		objmask = 1;
8596 		break;
8597 	case ITEM_PARAM_SPEC:
8598 		index = 0;
8599 		break;
8600 	case ITEM_PARAM_LAST:
8601 		index = 1;
8602 		break;
8603 	case ITEM_PARAM_PREFIX:
8604 		/* Modify next token to expect a prefix. */
8605 		if (ctx->next_num < 2)
8606 			return -1;
8607 		ctx->next[ctx->next_num - 2] = prefix;
8608 		/* Fall through. */
8609 	case ITEM_PARAM_MASK:
8610 		index = 2;
8611 		break;
8612 	default:
8613 		return -1;
8614 	}
8615 	/* Nothing else to do if there is no buffer. */
8616 	if (!out)
8617 		return len;
8618 	if (!out->args.vc.pattern_n)
8619 		return -1;
8620 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8621 	data_size = ctx->objdata / 3; /* spec, last, mask */
8622 	/* Point to selected object. */
8623 	ctx->object = out->args.vc.data + (data_size * index);
8624 	if (objmask) {
8625 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8626 		item->mask = ctx->objmask;
8627 	} else
8628 		ctx->objmask = NULL;
8629 	/* Update relevant item pointer. */
8630 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8631 		ctx->object;
8632 	return len;
8633 }
8634 
8635 /** Parse action configuration field. */
8636 static int
8637 parse_vc_conf(struct context *ctx, const struct token *token,
8638 	      const char *str, unsigned int len,
8639 	      void *buf, unsigned int size)
8640 {
8641 	struct buffer *out = buf;
8642 
8643 	(void)size;
8644 	/* Token name must match. */
8645 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8646 		return -1;
8647 	/* Nothing else to do if there is no buffer. */
8648 	if (!out)
8649 		return len;
8650 	/* Point to selected object. */
8651 	ctx->object = out->args.vc.data;
8652 	ctx->objmask = NULL;
8653 	return len;
8654 }
8655 
8656 /** Parse action configuration field. */
8657 static int
8658 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8659 		      const char *str, unsigned int len,
8660 		      void *buf, unsigned int size)
8661 {
8662 	struct buffer *out = buf;
8663 	struct rte_flow_update_age *update;
8664 
8665 	(void)size;
8666 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8667 		return -1;
8668 	/* Token name must match. */
8669 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8670 		return -1;
8671 	/* Nothing else to do if there is no buffer. */
8672 	if (!out)
8673 		return len;
8674 	/* Point to selected object. */
8675 	ctx->object = out->args.vc.data;
8676 	ctx->objmask = NULL;
8677 	/* Update the timeout is valid. */
8678 	update = (struct rte_flow_update_age *)out->args.vc.data;
8679 	update->timeout_valid = 1;
8680 	return len;
8681 }
8682 
8683 /** Parse eCPRI common header type field. */
8684 static int
8685 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8686 			 const char *str, unsigned int len,
8687 			 void *buf, unsigned int size)
8688 {
8689 	struct rte_flow_item_ecpri *ecpri;
8690 	struct rte_flow_item_ecpri *ecpri_mask;
8691 	struct rte_flow_item *item;
8692 	uint32_t data_size;
8693 	uint8_t msg_type;
8694 	struct buffer *out = buf;
8695 	const struct arg *arg;
8696 
8697 	(void)size;
8698 	/* Token name must match. */
8699 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8700 		return -1;
8701 	switch (ctx->curr) {
8702 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8703 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8704 		break;
8705 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8706 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8707 		break;
8708 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8709 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8710 		break;
8711 	default:
8712 		return -1;
8713 	}
8714 	if (!ctx->object)
8715 		return len;
8716 	arg = pop_args(ctx);
8717 	if (!arg)
8718 		return -1;
8719 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8720 	ecpri->hdr.common.type = msg_type;
8721 	data_size = ctx->objdata / 3; /* spec, last, mask */
8722 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8723 						    (data_size * 2));
8724 	ecpri_mask->hdr.common.type = 0xFF;
8725 	if (arg->hton) {
8726 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8727 		ecpri_mask->hdr.common.u32 =
8728 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8729 	}
8730 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8731 	item->spec = ecpri;
8732 	item->mask = ecpri_mask;
8733 	return len;
8734 }
8735 
8736 /** Parse L2TPv2 common header type field. */
8737 static int
8738 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8739 			 const char *str, unsigned int len,
8740 			 void *buf, unsigned int size)
8741 {
8742 	struct rte_flow_item_l2tpv2 *l2tpv2;
8743 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8744 	struct rte_flow_item *item;
8745 	uint32_t data_size;
8746 	uint16_t msg_type = 0;
8747 	struct buffer *out = buf;
8748 	const struct arg *arg;
8749 
8750 	(void)size;
8751 	/* Token name must match. */
8752 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8753 		return -1;
8754 	switch (ctx->curr) {
8755 	case ITEM_L2TPV2_TYPE_DATA:
8756 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8757 		break;
8758 	case ITEM_L2TPV2_TYPE_DATA_L:
8759 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8760 		break;
8761 	case ITEM_L2TPV2_TYPE_DATA_S:
8762 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8763 		break;
8764 	case ITEM_L2TPV2_TYPE_DATA_O:
8765 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8766 		break;
8767 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8768 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8769 		break;
8770 	case ITEM_L2TPV2_TYPE_CTRL:
8771 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8772 		break;
8773 	default:
8774 		return -1;
8775 	}
8776 	if (!ctx->object)
8777 		return len;
8778 	arg = pop_args(ctx);
8779 	if (!arg)
8780 		return -1;
8781 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8782 	l2tpv2->hdr.common.flags_version |= msg_type;
8783 	data_size = ctx->objdata / 3; /* spec, last, mask */
8784 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8785 						    (data_size * 2));
8786 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8787 	if (arg->hton) {
8788 		l2tpv2->hdr.common.flags_version =
8789 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8790 		l2tpv2_mask->hdr.common.flags_version =
8791 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8792 	}
8793 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8794 	item->spec = l2tpv2;
8795 	item->mask = l2tpv2_mask;
8796 	return len;
8797 }
8798 
8799 /** Parse operation for compare match item. */
8800 static int
8801 parse_vc_compare_op(struct context *ctx, const struct token *token,
8802 			 const char *str, unsigned int len, void *buf,
8803 			 unsigned int size)
8804 {
8805 	struct rte_flow_item_compare *compare_item;
8806 	unsigned int i;
8807 
8808 	(void)token;
8809 	(void)buf;
8810 	(void)size;
8811 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8812 		return -1;
8813 	for (i = 0; compare_ops[i]; ++i)
8814 		if (!strcmp_partial(compare_ops[i], str, len))
8815 			break;
8816 	if (!compare_ops[i])
8817 		return -1;
8818 	if (!ctx->object)
8819 		return len;
8820 	compare_item = ctx->object;
8821 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8822 	return len;
8823 }
8824 
8825 /** Parse id for compare match item. */
8826 static int
8827 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8828 			  const char *str, unsigned int len, void *buf,
8829 			  unsigned int size)
8830 {
8831 	struct rte_flow_item_compare *compare_item;
8832 	unsigned int i;
8833 
8834 	(void)token;
8835 	(void)buf;
8836 	(void)size;
8837 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8838 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8839 		return -1;
8840 	for (i = 0; flow_field_ids[i]; ++i)
8841 		if (!strcmp_partial(flow_field_ids[i], str, len))
8842 			break;
8843 	if (!flow_field_ids[i])
8844 		return -1;
8845 	if (!ctx->object)
8846 		return len;
8847 	compare_item = ctx->object;
8848 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8849 		compare_item->a.field = (enum rte_flow_field_id)i;
8850 	else
8851 		compare_item->b.field = (enum rte_flow_field_id)i;
8852 	return len;
8853 }
8854 
8855 /** Parse level for compare match item. */
8856 static int
8857 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8858 			     const char *str, unsigned int len, void *buf,
8859 			     unsigned int size)
8860 {
8861 	struct rte_flow_item_compare *compare_item;
8862 	struct flex_item *fp = NULL;
8863 	uint32_t val;
8864 	struct buffer *out = buf;
8865 	char *end;
8866 
8867 	(void)token;
8868 	(void)size;
8869 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8870 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
8871 		return -1;
8872 	if (!ctx->object)
8873 		return len;
8874 	compare_item = ctx->object;
8875 	errno = 0;
8876 	val = strtoumax(str, &end, 0);
8877 	if (errno || (size_t)(end - str) != len)
8878 		return -1;
8879 	/* No need to validate action template mask value */
8880 	if (out->args.vc.masks) {
8881 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
8882 			compare_item->a.level = val;
8883 		else
8884 			compare_item->b.level = val;
8885 		return len;
8886 	}
8887 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8888 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
8889 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
8890 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
8891 		if (val >= FLEX_MAX_PARSERS_NUM) {
8892 			printf("Bad flex item handle\n");
8893 			return -1;
8894 		}
8895 		fp = flex_items[ctx->port][val];
8896 		if (!fp) {
8897 			printf("Bad flex item handle\n");
8898 			return -1;
8899 		}
8900 	}
8901 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
8902 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
8903 			compare_item->a.level = val;
8904 		else
8905 			compare_item->a.flex_handle = fp->flex_handle;
8906 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
8907 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
8908 			compare_item->b.level = val;
8909 		else
8910 			compare_item->b.flex_handle = fp->flex_handle;
8911 	}
8912 	return len;
8913 }
8914 
8915 /** Parse meter color action type. */
8916 static int
8917 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
8918 				const char *str, unsigned int len,
8919 				void *buf, unsigned int size)
8920 {
8921 	struct rte_flow_action *action_data;
8922 	struct rte_flow_action_meter_color *conf;
8923 	enum rte_color color;
8924 
8925 	(void)buf;
8926 	(void)size;
8927 	/* Token name must match. */
8928 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8929 		return -1;
8930 	switch (ctx->curr) {
8931 	case ACTION_METER_COLOR_GREEN:
8932 		color = RTE_COLOR_GREEN;
8933 	break;
8934 	case ACTION_METER_COLOR_YELLOW:
8935 		color = RTE_COLOR_YELLOW;
8936 	break;
8937 	case ACTION_METER_COLOR_RED:
8938 		color = RTE_COLOR_RED;
8939 	break;
8940 	default:
8941 		return -1;
8942 	}
8943 
8944 	if (!ctx->object)
8945 		return len;
8946 	action_data = ctx->object;
8947 	conf = (struct rte_flow_action_meter_color *)
8948 					(uintptr_t)(action_data->conf);
8949 	conf->color = color;
8950 	return len;
8951 }
8952 
8953 /** Parse RSS action. */
8954 static int
8955 parse_vc_action_rss(struct context *ctx, const struct token *token,
8956 		    const char *str, unsigned int len,
8957 		    void *buf, unsigned int size)
8958 {
8959 	struct buffer *out = buf;
8960 	struct rte_flow_action *action;
8961 	struct action_rss_data *action_rss_data;
8962 	unsigned int i;
8963 	int ret;
8964 
8965 	ret = parse_vc(ctx, token, str, len, buf, size);
8966 	if (ret < 0)
8967 		return ret;
8968 	/* Nothing else to do if there is no buffer. */
8969 	if (!out)
8970 		return ret;
8971 	if (!out->args.vc.actions_n)
8972 		return -1;
8973 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8974 	/* Point to selected object. */
8975 	ctx->object = out->args.vc.data;
8976 	ctx->objmask = NULL;
8977 	/* Set up default configuration. */
8978 	action_rss_data = ctx->object;
8979 	*action_rss_data = (struct action_rss_data){
8980 		.conf = (struct rte_flow_action_rss){
8981 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
8982 			.level = 0,
8983 			.types = rss_hf,
8984 			.key_len = 0,
8985 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
8986 			.key = NULL,
8987 			.queue = action_rss_data->queue,
8988 		},
8989 		.queue = { 0 },
8990 	};
8991 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
8992 		action_rss_data->queue[i] = i;
8993 	action->conf = &action_rss_data->conf;
8994 	return ret;
8995 }
8996 
8997 /**
8998  * Parse func field for RSS action.
8999  *
9000  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9001  * ACTION_RSS_FUNC_* index that called this function.
9002  */
9003 static int
9004 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9005 			 const char *str, unsigned int len,
9006 			 void *buf, unsigned int size)
9007 {
9008 	struct action_rss_data *action_rss_data;
9009 	enum rte_eth_hash_function func;
9010 
9011 	(void)buf;
9012 	(void)size;
9013 	/* Token name must match. */
9014 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9015 		return -1;
9016 	switch (ctx->curr) {
9017 	case ACTION_RSS_FUNC_DEFAULT:
9018 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9019 		break;
9020 	case ACTION_RSS_FUNC_TOEPLITZ:
9021 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9022 		break;
9023 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9024 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9025 		break;
9026 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9027 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9028 		break;
9029 	default:
9030 		return -1;
9031 	}
9032 	if (!ctx->object)
9033 		return len;
9034 	action_rss_data = ctx->object;
9035 	action_rss_data->conf.func = func;
9036 	return len;
9037 }
9038 
9039 /**
9040  * Parse type field for RSS action.
9041  *
9042  * Valid tokens are type field names and the "end" token.
9043  */
9044 static int
9045 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9046 			  const char *str, unsigned int len,
9047 			  void *buf, unsigned int size)
9048 {
9049 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9050 	struct action_rss_data *action_rss_data;
9051 	unsigned int i;
9052 
9053 	(void)token;
9054 	(void)buf;
9055 	(void)size;
9056 	if (ctx->curr != ACTION_RSS_TYPE)
9057 		return -1;
9058 	if (!(ctx->objdata >> 16) && ctx->object) {
9059 		action_rss_data = ctx->object;
9060 		action_rss_data->conf.types = 0;
9061 	}
9062 	if (!strcmp_partial("end", str, len)) {
9063 		ctx->objdata &= 0xffff;
9064 		return len;
9065 	}
9066 	for (i = 0; rss_type_table[i].str; ++i)
9067 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9068 			break;
9069 	if (!rss_type_table[i].str)
9070 		return -1;
9071 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9072 	/* Repeat token. */
9073 	if (ctx->next_num == RTE_DIM(ctx->next))
9074 		return -1;
9075 	ctx->next[ctx->next_num++] = next;
9076 	if (!ctx->object)
9077 		return len;
9078 	action_rss_data = ctx->object;
9079 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9080 	return len;
9081 }
9082 
9083 /**
9084  * Parse queue field for RSS action.
9085  *
9086  * Valid tokens are queue indices and the "end" token.
9087  */
9088 static int
9089 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9090 			  const char *str, unsigned int len,
9091 			  void *buf, unsigned int size)
9092 {
9093 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9094 	struct action_rss_data *action_rss_data;
9095 	const struct arg *arg;
9096 	int ret;
9097 	int i;
9098 
9099 	(void)token;
9100 	(void)buf;
9101 	(void)size;
9102 	if (ctx->curr != ACTION_RSS_QUEUE)
9103 		return -1;
9104 	i = ctx->objdata >> 16;
9105 	if (!strcmp_partial("end", str, len)) {
9106 		ctx->objdata &= 0xffff;
9107 		goto end;
9108 	}
9109 	if (i >= ACTION_RSS_QUEUE_NUM)
9110 		return -1;
9111 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9112 			     i * sizeof(action_rss_data->queue[i]),
9113 			     sizeof(action_rss_data->queue[i]));
9114 	if (push_args(ctx, arg))
9115 		return -1;
9116 	ret = parse_int(ctx, token, str, len, NULL, 0);
9117 	if (ret < 0) {
9118 		pop_args(ctx);
9119 		return -1;
9120 	}
9121 	++i;
9122 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9123 	/* Repeat token. */
9124 	if (ctx->next_num == RTE_DIM(ctx->next))
9125 		return -1;
9126 	ctx->next[ctx->next_num++] = next;
9127 end:
9128 	if (!ctx->object)
9129 		return len;
9130 	action_rss_data = ctx->object;
9131 	action_rss_data->conf.queue_num = i;
9132 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9133 	return len;
9134 }
9135 
9136 /** Setup VXLAN encap configuration. */
9137 static int
9138 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9139 {
9140 	/* Set up default configuration. */
9141 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9142 		.conf = (struct rte_flow_action_vxlan_encap){
9143 			.definition = action_vxlan_encap_data->items,
9144 		},
9145 		.items = {
9146 			{
9147 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9148 				.spec = &action_vxlan_encap_data->item_eth,
9149 				.mask = &rte_flow_item_eth_mask,
9150 			},
9151 			{
9152 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9153 				.spec = &action_vxlan_encap_data->item_vlan,
9154 				.mask = &rte_flow_item_vlan_mask,
9155 			},
9156 			{
9157 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9158 				.spec = &action_vxlan_encap_data->item_ipv4,
9159 				.mask = &rte_flow_item_ipv4_mask,
9160 			},
9161 			{
9162 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9163 				.spec = &action_vxlan_encap_data->item_udp,
9164 				.mask = &rte_flow_item_udp_mask,
9165 			},
9166 			{
9167 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9168 				.spec = &action_vxlan_encap_data->item_vxlan,
9169 				.mask = &rte_flow_item_vxlan_mask,
9170 			},
9171 			{
9172 				.type = RTE_FLOW_ITEM_TYPE_END,
9173 			},
9174 		},
9175 		.item_eth.hdr.ether_type = 0,
9176 		.item_vlan = {
9177 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9178 			.hdr.eth_proto = 0,
9179 		},
9180 		.item_ipv4.hdr = {
9181 			.src_addr = vxlan_encap_conf.ipv4_src,
9182 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9183 		},
9184 		.item_udp.hdr = {
9185 			.src_port = vxlan_encap_conf.udp_src,
9186 			.dst_port = vxlan_encap_conf.udp_dst,
9187 		},
9188 		.item_vxlan.hdr.flags = 0,
9189 	};
9190 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9191 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9192 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9193 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9194 	if (!vxlan_encap_conf.select_ipv4) {
9195 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9196 		       &vxlan_encap_conf.ipv6_src,
9197 		       sizeof(vxlan_encap_conf.ipv6_src));
9198 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9199 		       &vxlan_encap_conf.ipv6_dst,
9200 		       sizeof(vxlan_encap_conf.ipv6_dst));
9201 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9202 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9203 			.spec = &action_vxlan_encap_data->item_ipv6,
9204 			.mask = &rte_flow_item_ipv6_mask,
9205 		};
9206 	}
9207 	if (!vxlan_encap_conf.select_vlan)
9208 		action_vxlan_encap_data->items[1].type =
9209 			RTE_FLOW_ITEM_TYPE_VOID;
9210 	if (vxlan_encap_conf.select_tos_ttl) {
9211 		if (vxlan_encap_conf.select_ipv4) {
9212 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9213 
9214 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9215 			       sizeof(ipv4_mask_tos));
9216 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9217 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9218 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9219 					vxlan_encap_conf.ip_tos;
9220 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9221 					vxlan_encap_conf.ip_ttl;
9222 			action_vxlan_encap_data->items[2].mask =
9223 							&ipv4_mask_tos;
9224 		} else {
9225 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9226 
9227 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9228 			       sizeof(ipv6_mask_tos));
9229 			ipv6_mask_tos.hdr.vtc_flow |=
9230 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9231 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9232 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9233 				rte_cpu_to_be_32
9234 					((uint32_t)vxlan_encap_conf.ip_tos <<
9235 					 RTE_IPV6_HDR_TC_SHIFT);
9236 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9237 					vxlan_encap_conf.ip_ttl;
9238 			action_vxlan_encap_data->items[2].mask =
9239 							&ipv6_mask_tos;
9240 		}
9241 	}
9242 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9243 	       RTE_DIM(vxlan_encap_conf.vni));
9244 	return 0;
9245 }
9246 
9247 /** Parse VXLAN encap action. */
9248 static int
9249 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9250 			    const char *str, unsigned int len,
9251 			    void *buf, unsigned int size)
9252 {
9253 	struct buffer *out = buf;
9254 	struct rte_flow_action *action;
9255 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9256 	int ret;
9257 
9258 	ret = parse_vc(ctx, token, str, len, buf, size);
9259 	if (ret < 0)
9260 		return ret;
9261 	/* Nothing else to do if there is no buffer. */
9262 	if (!out)
9263 		return ret;
9264 	if (!out->args.vc.actions_n)
9265 		return -1;
9266 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9267 	/* Point to selected object. */
9268 	ctx->object = out->args.vc.data;
9269 	ctx->objmask = NULL;
9270 	action_vxlan_encap_data = ctx->object;
9271 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9272 	action->conf = &action_vxlan_encap_data->conf;
9273 	return ret;
9274 }
9275 
9276 /** Setup NVGRE encap configuration. */
9277 static int
9278 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9279 {
9280 	/* Set up default configuration. */
9281 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9282 		.conf = (struct rte_flow_action_nvgre_encap){
9283 			.definition = action_nvgre_encap_data->items,
9284 		},
9285 		.items = {
9286 			{
9287 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9288 				.spec = &action_nvgre_encap_data->item_eth,
9289 				.mask = &rte_flow_item_eth_mask,
9290 			},
9291 			{
9292 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9293 				.spec = &action_nvgre_encap_data->item_vlan,
9294 				.mask = &rte_flow_item_vlan_mask,
9295 			},
9296 			{
9297 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9298 				.spec = &action_nvgre_encap_data->item_ipv4,
9299 				.mask = &rte_flow_item_ipv4_mask,
9300 			},
9301 			{
9302 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9303 				.spec = &action_nvgre_encap_data->item_nvgre,
9304 				.mask = &rte_flow_item_nvgre_mask,
9305 			},
9306 			{
9307 				.type = RTE_FLOW_ITEM_TYPE_END,
9308 			},
9309 		},
9310 		.item_eth.hdr.ether_type = 0,
9311 		.item_vlan = {
9312 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9313 			.hdr.eth_proto = 0,
9314 		},
9315 		.item_ipv4.hdr = {
9316 		       .src_addr = nvgre_encap_conf.ipv4_src,
9317 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9318 		},
9319 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9320 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9321 		.item_nvgre.flow_id = 0,
9322 	};
9323 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9324 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9325 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9326 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9327 	if (!nvgre_encap_conf.select_ipv4) {
9328 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9329 		       &nvgre_encap_conf.ipv6_src,
9330 		       sizeof(nvgre_encap_conf.ipv6_src));
9331 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9332 		       &nvgre_encap_conf.ipv6_dst,
9333 		       sizeof(nvgre_encap_conf.ipv6_dst));
9334 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9335 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9336 			.spec = &action_nvgre_encap_data->item_ipv6,
9337 			.mask = &rte_flow_item_ipv6_mask,
9338 		};
9339 	}
9340 	if (!nvgre_encap_conf.select_vlan)
9341 		action_nvgre_encap_data->items[1].type =
9342 			RTE_FLOW_ITEM_TYPE_VOID;
9343 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9344 	       RTE_DIM(nvgre_encap_conf.tni));
9345 	return 0;
9346 }
9347 
9348 /** Parse NVGRE encap action. */
9349 static int
9350 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9351 			    const char *str, unsigned int len,
9352 			    void *buf, unsigned int size)
9353 {
9354 	struct buffer *out = buf;
9355 	struct rte_flow_action *action;
9356 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9357 	int ret;
9358 
9359 	ret = parse_vc(ctx, token, str, len, buf, size);
9360 	if (ret < 0)
9361 		return ret;
9362 	/* Nothing else to do if there is no buffer. */
9363 	if (!out)
9364 		return ret;
9365 	if (!out->args.vc.actions_n)
9366 		return -1;
9367 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9368 	/* Point to selected object. */
9369 	ctx->object = out->args.vc.data;
9370 	ctx->objmask = NULL;
9371 	action_nvgre_encap_data = ctx->object;
9372 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9373 	action->conf = &action_nvgre_encap_data->conf;
9374 	return ret;
9375 }
9376 
9377 /** Parse l2 encap action. */
9378 static int
9379 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9380 			 const char *str, unsigned int len,
9381 			 void *buf, unsigned int size)
9382 {
9383 	struct buffer *out = buf;
9384 	struct rte_flow_action *action;
9385 	struct action_raw_encap_data *action_encap_data;
9386 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9387 	struct rte_flow_item_vlan vlan = {
9388 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9389 		.hdr.eth_proto = 0,
9390 	};
9391 	uint8_t *header;
9392 	int ret;
9393 
9394 	ret = parse_vc(ctx, token, str, len, buf, size);
9395 	if (ret < 0)
9396 		return ret;
9397 	/* Nothing else to do if there is no buffer. */
9398 	if (!out)
9399 		return ret;
9400 	if (!out->args.vc.actions_n)
9401 		return -1;
9402 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9403 	/* Point to selected object. */
9404 	ctx->object = out->args.vc.data;
9405 	ctx->objmask = NULL;
9406 	/* Copy the headers to the buffer. */
9407 	action_encap_data = ctx->object;
9408 	*action_encap_data = (struct action_raw_encap_data) {
9409 		.conf = (struct rte_flow_action_raw_encap){
9410 			.data = action_encap_data->data,
9411 		},
9412 		.data = {},
9413 	};
9414 	header = action_encap_data->data;
9415 	if (l2_encap_conf.select_vlan)
9416 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9417 	else if (l2_encap_conf.select_ipv4)
9418 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9419 	else
9420 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9421 	memcpy(eth.hdr.dst_addr.addr_bytes,
9422 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9423 	memcpy(eth.hdr.src_addr.addr_bytes,
9424 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9425 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9426 	header += sizeof(struct rte_ether_hdr);
9427 	if (l2_encap_conf.select_vlan) {
9428 		if (l2_encap_conf.select_ipv4)
9429 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9430 		else
9431 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9432 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9433 		header += sizeof(struct rte_vlan_hdr);
9434 	}
9435 	action_encap_data->conf.size = header -
9436 		action_encap_data->data;
9437 	action->conf = &action_encap_data->conf;
9438 	return ret;
9439 }
9440 
9441 /** Parse l2 decap action. */
9442 static int
9443 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9444 			 const char *str, unsigned int len,
9445 			 void *buf, unsigned int size)
9446 {
9447 	struct buffer *out = buf;
9448 	struct rte_flow_action *action;
9449 	struct action_raw_decap_data *action_decap_data;
9450 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9451 	struct rte_flow_item_vlan vlan = {
9452 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9453 		.hdr.eth_proto = 0,
9454 	};
9455 	uint8_t *header;
9456 	int ret;
9457 
9458 	ret = parse_vc(ctx, token, str, len, buf, size);
9459 	if (ret < 0)
9460 		return ret;
9461 	/* Nothing else to do if there is no buffer. */
9462 	if (!out)
9463 		return ret;
9464 	if (!out->args.vc.actions_n)
9465 		return -1;
9466 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9467 	/* Point to selected object. */
9468 	ctx->object = out->args.vc.data;
9469 	ctx->objmask = NULL;
9470 	/* Copy the headers to the buffer. */
9471 	action_decap_data = ctx->object;
9472 	*action_decap_data = (struct action_raw_decap_data) {
9473 		.conf = (struct rte_flow_action_raw_decap){
9474 			.data = action_decap_data->data,
9475 		},
9476 		.data = {},
9477 	};
9478 	header = action_decap_data->data;
9479 	if (l2_decap_conf.select_vlan)
9480 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9481 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9482 	header += sizeof(struct rte_ether_hdr);
9483 	if (l2_decap_conf.select_vlan) {
9484 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9485 		header += sizeof(struct rte_vlan_hdr);
9486 	}
9487 	action_decap_data->conf.size = header -
9488 		action_decap_data->data;
9489 	action->conf = &action_decap_data->conf;
9490 	return ret;
9491 }
9492 
9493 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9494 
9495 /** Parse MPLSOGRE encap action. */
9496 static int
9497 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9498 			       const char *str, unsigned int len,
9499 			       void *buf, unsigned int size)
9500 {
9501 	struct buffer *out = buf;
9502 	struct rte_flow_action *action;
9503 	struct action_raw_encap_data *action_encap_data;
9504 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9505 	struct rte_flow_item_vlan vlan = {
9506 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9507 		.hdr.eth_proto = 0,
9508 	};
9509 	struct rte_flow_item_ipv4 ipv4 = {
9510 		.hdr =  {
9511 			.src_addr = mplsogre_encap_conf.ipv4_src,
9512 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9513 			.next_proto_id = IPPROTO_GRE,
9514 			.version_ihl = RTE_IPV4_VHL_DEF,
9515 			.time_to_live = IPDEFTTL,
9516 		},
9517 	};
9518 	struct rte_flow_item_ipv6 ipv6 = {
9519 		.hdr =  {
9520 			.proto = IPPROTO_GRE,
9521 			.hop_limits = IPDEFTTL,
9522 		},
9523 	};
9524 	struct rte_flow_item_gre gre = {
9525 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9526 	};
9527 	struct rte_flow_item_mpls mpls = {
9528 		.ttl = 0,
9529 	};
9530 	uint8_t *header;
9531 	int ret;
9532 
9533 	ret = parse_vc(ctx, token, str, len, buf, size);
9534 	if (ret < 0)
9535 		return ret;
9536 	/* Nothing else to do if there is no buffer. */
9537 	if (!out)
9538 		return ret;
9539 	if (!out->args.vc.actions_n)
9540 		return -1;
9541 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9542 	/* Point to selected object. */
9543 	ctx->object = out->args.vc.data;
9544 	ctx->objmask = NULL;
9545 	/* Copy the headers to the buffer. */
9546 	action_encap_data = ctx->object;
9547 	*action_encap_data = (struct action_raw_encap_data) {
9548 		.conf = (struct rte_flow_action_raw_encap){
9549 			.data = action_encap_data->data,
9550 		},
9551 		.data = {},
9552 		.preserve = {},
9553 	};
9554 	header = action_encap_data->data;
9555 	if (mplsogre_encap_conf.select_vlan)
9556 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9557 	else if (mplsogre_encap_conf.select_ipv4)
9558 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9559 	else
9560 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9561 	memcpy(eth.hdr.dst_addr.addr_bytes,
9562 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9563 	memcpy(eth.hdr.src_addr.addr_bytes,
9564 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9565 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9566 	header += sizeof(struct rte_ether_hdr);
9567 	if (mplsogre_encap_conf.select_vlan) {
9568 		if (mplsogre_encap_conf.select_ipv4)
9569 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9570 		else
9571 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9572 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9573 		header += sizeof(struct rte_vlan_hdr);
9574 	}
9575 	if (mplsogre_encap_conf.select_ipv4) {
9576 		memcpy(header, &ipv4, sizeof(ipv4));
9577 		header += sizeof(ipv4);
9578 	} else {
9579 		memcpy(&ipv6.hdr.src_addr,
9580 		       &mplsogre_encap_conf.ipv6_src,
9581 		       sizeof(mplsogre_encap_conf.ipv6_src));
9582 		memcpy(&ipv6.hdr.dst_addr,
9583 		       &mplsogre_encap_conf.ipv6_dst,
9584 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9585 		memcpy(header, &ipv6, sizeof(ipv6));
9586 		header += sizeof(ipv6);
9587 	}
9588 	memcpy(header, &gre, sizeof(gre));
9589 	header += sizeof(gre);
9590 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9591 	       RTE_DIM(mplsogre_encap_conf.label));
9592 	mpls.label_tc_s[2] |= 0x1;
9593 	memcpy(header, &mpls, sizeof(mpls));
9594 	header += sizeof(mpls);
9595 	action_encap_data->conf.size = header -
9596 		action_encap_data->data;
9597 	action->conf = &action_encap_data->conf;
9598 	return ret;
9599 }
9600 
9601 /** Parse MPLSOGRE decap action. */
9602 static int
9603 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9604 			       const char *str, unsigned int len,
9605 			       void *buf, unsigned int size)
9606 {
9607 	struct buffer *out = buf;
9608 	struct rte_flow_action *action;
9609 	struct action_raw_decap_data *action_decap_data;
9610 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9611 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9612 	struct rte_flow_item_ipv4 ipv4 = {
9613 		.hdr =  {
9614 			.next_proto_id = IPPROTO_GRE,
9615 		},
9616 	};
9617 	struct rte_flow_item_ipv6 ipv6 = {
9618 		.hdr =  {
9619 			.proto = IPPROTO_GRE,
9620 		},
9621 	};
9622 	struct rte_flow_item_gre gre = {
9623 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9624 	};
9625 	struct rte_flow_item_mpls mpls;
9626 	uint8_t *header;
9627 	int ret;
9628 
9629 	ret = parse_vc(ctx, token, str, len, buf, size);
9630 	if (ret < 0)
9631 		return ret;
9632 	/* Nothing else to do if there is no buffer. */
9633 	if (!out)
9634 		return ret;
9635 	if (!out->args.vc.actions_n)
9636 		return -1;
9637 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9638 	/* Point to selected object. */
9639 	ctx->object = out->args.vc.data;
9640 	ctx->objmask = NULL;
9641 	/* Copy the headers to the buffer. */
9642 	action_decap_data = ctx->object;
9643 	*action_decap_data = (struct action_raw_decap_data) {
9644 		.conf = (struct rte_flow_action_raw_decap){
9645 			.data = action_decap_data->data,
9646 		},
9647 		.data = {},
9648 	};
9649 	header = action_decap_data->data;
9650 	if (mplsogre_decap_conf.select_vlan)
9651 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9652 	else if (mplsogre_encap_conf.select_ipv4)
9653 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9654 	else
9655 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9656 	memcpy(eth.hdr.dst_addr.addr_bytes,
9657 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9658 	memcpy(eth.hdr.src_addr.addr_bytes,
9659 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9660 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9661 	header += sizeof(struct rte_ether_hdr);
9662 	if (mplsogre_encap_conf.select_vlan) {
9663 		if (mplsogre_encap_conf.select_ipv4)
9664 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9665 		else
9666 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9667 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9668 		header += sizeof(struct rte_vlan_hdr);
9669 	}
9670 	if (mplsogre_encap_conf.select_ipv4) {
9671 		memcpy(header, &ipv4, sizeof(ipv4));
9672 		header += sizeof(ipv4);
9673 	} else {
9674 		memcpy(header, &ipv6, sizeof(ipv6));
9675 		header += sizeof(ipv6);
9676 	}
9677 	memcpy(header, &gre, sizeof(gre));
9678 	header += sizeof(gre);
9679 	memset(&mpls, 0, sizeof(mpls));
9680 	memcpy(header, &mpls, sizeof(mpls));
9681 	header += sizeof(mpls);
9682 	action_decap_data->conf.size = header -
9683 		action_decap_data->data;
9684 	action->conf = &action_decap_data->conf;
9685 	return ret;
9686 }
9687 
9688 /** Parse MPLSOUDP encap action. */
9689 static int
9690 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9691 			       const char *str, unsigned int len,
9692 			       void *buf, unsigned int size)
9693 {
9694 	struct buffer *out = buf;
9695 	struct rte_flow_action *action;
9696 	struct action_raw_encap_data *action_encap_data;
9697 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9698 	struct rte_flow_item_vlan vlan = {
9699 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9700 		.hdr.eth_proto = 0,
9701 	};
9702 	struct rte_flow_item_ipv4 ipv4 = {
9703 		.hdr =  {
9704 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9705 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9706 			.next_proto_id = IPPROTO_UDP,
9707 			.version_ihl = RTE_IPV4_VHL_DEF,
9708 			.time_to_live = IPDEFTTL,
9709 		},
9710 	};
9711 	struct rte_flow_item_ipv6 ipv6 = {
9712 		.hdr =  {
9713 			.proto = IPPROTO_UDP,
9714 			.hop_limits = IPDEFTTL,
9715 		},
9716 	};
9717 	struct rte_flow_item_udp udp = {
9718 		.hdr = {
9719 			.src_port = mplsoudp_encap_conf.udp_src,
9720 			.dst_port = mplsoudp_encap_conf.udp_dst,
9721 		},
9722 	};
9723 	struct rte_flow_item_mpls mpls;
9724 	uint8_t *header;
9725 	int ret;
9726 
9727 	ret = parse_vc(ctx, token, str, len, buf, size);
9728 	if (ret < 0)
9729 		return ret;
9730 	/* Nothing else to do if there is no buffer. */
9731 	if (!out)
9732 		return ret;
9733 	if (!out->args.vc.actions_n)
9734 		return -1;
9735 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9736 	/* Point to selected object. */
9737 	ctx->object = out->args.vc.data;
9738 	ctx->objmask = NULL;
9739 	/* Copy the headers to the buffer. */
9740 	action_encap_data = ctx->object;
9741 	*action_encap_data = (struct action_raw_encap_data) {
9742 		.conf = (struct rte_flow_action_raw_encap){
9743 			.data = action_encap_data->data,
9744 		},
9745 		.data = {},
9746 		.preserve = {},
9747 	};
9748 	header = action_encap_data->data;
9749 	if (mplsoudp_encap_conf.select_vlan)
9750 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9751 	else if (mplsoudp_encap_conf.select_ipv4)
9752 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9753 	else
9754 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9755 	memcpy(eth.hdr.dst_addr.addr_bytes,
9756 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9757 	memcpy(eth.hdr.src_addr.addr_bytes,
9758 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9759 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9760 	header += sizeof(struct rte_ether_hdr);
9761 	if (mplsoudp_encap_conf.select_vlan) {
9762 		if (mplsoudp_encap_conf.select_ipv4)
9763 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9764 		else
9765 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9766 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9767 		header += sizeof(struct rte_vlan_hdr);
9768 	}
9769 	if (mplsoudp_encap_conf.select_ipv4) {
9770 		memcpy(header, &ipv4, sizeof(ipv4));
9771 		header += sizeof(ipv4);
9772 	} else {
9773 		memcpy(&ipv6.hdr.src_addr,
9774 		       &mplsoudp_encap_conf.ipv6_src,
9775 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9776 		memcpy(&ipv6.hdr.dst_addr,
9777 		       &mplsoudp_encap_conf.ipv6_dst,
9778 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9779 		memcpy(header, &ipv6, sizeof(ipv6));
9780 		header += sizeof(ipv6);
9781 	}
9782 	memcpy(header, &udp, sizeof(udp));
9783 	header += sizeof(udp);
9784 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9785 	       RTE_DIM(mplsoudp_encap_conf.label));
9786 	mpls.label_tc_s[2] |= 0x1;
9787 	memcpy(header, &mpls, sizeof(mpls));
9788 	header += sizeof(mpls);
9789 	action_encap_data->conf.size = header -
9790 		action_encap_data->data;
9791 	action->conf = &action_encap_data->conf;
9792 	return ret;
9793 }
9794 
9795 /** Parse MPLSOUDP decap action. */
9796 static int
9797 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9798 			       const char *str, unsigned int len,
9799 			       void *buf, unsigned int size)
9800 {
9801 	struct buffer *out = buf;
9802 	struct rte_flow_action *action;
9803 	struct action_raw_decap_data *action_decap_data;
9804 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9805 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9806 	struct rte_flow_item_ipv4 ipv4 = {
9807 		.hdr =  {
9808 			.next_proto_id = IPPROTO_UDP,
9809 		},
9810 	};
9811 	struct rte_flow_item_ipv6 ipv6 = {
9812 		.hdr =  {
9813 			.proto = IPPROTO_UDP,
9814 		},
9815 	};
9816 	struct rte_flow_item_udp udp = {
9817 		.hdr = {
9818 			.dst_port = rte_cpu_to_be_16(6635),
9819 		},
9820 	};
9821 	struct rte_flow_item_mpls mpls;
9822 	uint8_t *header;
9823 	int ret;
9824 
9825 	ret = parse_vc(ctx, token, str, len, buf, size);
9826 	if (ret < 0)
9827 		return ret;
9828 	/* Nothing else to do if there is no buffer. */
9829 	if (!out)
9830 		return ret;
9831 	if (!out->args.vc.actions_n)
9832 		return -1;
9833 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9834 	/* Point to selected object. */
9835 	ctx->object = out->args.vc.data;
9836 	ctx->objmask = NULL;
9837 	/* Copy the headers to the buffer. */
9838 	action_decap_data = ctx->object;
9839 	*action_decap_data = (struct action_raw_decap_data) {
9840 		.conf = (struct rte_flow_action_raw_decap){
9841 			.data = action_decap_data->data,
9842 		},
9843 		.data = {},
9844 	};
9845 	header = action_decap_data->data;
9846 	if (mplsoudp_decap_conf.select_vlan)
9847 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9848 	else if (mplsoudp_encap_conf.select_ipv4)
9849 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9850 	else
9851 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9852 	memcpy(eth.hdr.dst_addr.addr_bytes,
9853 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9854 	memcpy(eth.hdr.src_addr.addr_bytes,
9855 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9856 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9857 	header += sizeof(struct rte_ether_hdr);
9858 	if (mplsoudp_encap_conf.select_vlan) {
9859 		if (mplsoudp_encap_conf.select_ipv4)
9860 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9861 		else
9862 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9863 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9864 		header += sizeof(struct rte_vlan_hdr);
9865 	}
9866 	if (mplsoudp_encap_conf.select_ipv4) {
9867 		memcpy(header, &ipv4, sizeof(ipv4));
9868 		header += sizeof(ipv4);
9869 	} else {
9870 		memcpy(header, &ipv6, sizeof(ipv6));
9871 		header += sizeof(ipv6);
9872 	}
9873 	memcpy(header, &udp, sizeof(udp));
9874 	header += sizeof(udp);
9875 	memset(&mpls, 0, sizeof(mpls));
9876 	memcpy(header, &mpls, sizeof(mpls));
9877 	header += sizeof(mpls);
9878 	action_decap_data->conf.size = header -
9879 		action_decap_data->data;
9880 	action->conf = &action_decap_data->conf;
9881 	return ret;
9882 }
9883 
9884 static int
9885 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
9886 				const char *str, unsigned int len, void *buf,
9887 				unsigned int size)
9888 {
9889 	struct action_raw_decap_data *action_raw_decap_data;
9890 	struct rte_flow_action *action;
9891 	const struct arg *arg;
9892 	struct buffer *out = buf;
9893 	int ret;
9894 	uint16_t idx;
9895 
9896 	RTE_SET_USED(token);
9897 	RTE_SET_USED(buf);
9898 	RTE_SET_USED(size);
9899 	arg = ARGS_ENTRY_ARB_BOUNDED
9900 		(offsetof(struct action_raw_decap_data, idx),
9901 		 sizeof(((struct action_raw_decap_data *)0)->idx),
9902 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9903 	if (push_args(ctx, arg))
9904 		return -1;
9905 	ret = parse_int(ctx, token, str, len, NULL, 0);
9906 	if (ret < 0) {
9907 		pop_args(ctx);
9908 		return -1;
9909 	}
9910 	if (!ctx->object)
9911 		return len;
9912 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9913 	action_raw_decap_data = ctx->object;
9914 	idx = action_raw_decap_data->idx;
9915 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
9916 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
9917 	action->conf = &action_raw_decap_data->conf;
9918 	return len;
9919 }
9920 
9921 
9922 static int
9923 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
9924 				const char *str, unsigned int len, void *buf,
9925 				unsigned int size)
9926 {
9927 	struct action_raw_encap_data *action_raw_encap_data;
9928 	struct rte_flow_action *action;
9929 	const struct arg *arg;
9930 	struct buffer *out = buf;
9931 	int ret;
9932 	uint16_t idx;
9933 
9934 	RTE_SET_USED(token);
9935 	RTE_SET_USED(buf);
9936 	RTE_SET_USED(size);
9937 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
9938 		return -1;
9939 	arg = ARGS_ENTRY_ARB_BOUNDED
9940 		(offsetof(struct action_raw_encap_data, idx),
9941 		 sizeof(((struct action_raw_encap_data *)0)->idx),
9942 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9943 	if (push_args(ctx, arg))
9944 		return -1;
9945 	ret = parse_int(ctx, token, str, len, NULL, 0);
9946 	if (ret < 0) {
9947 		pop_args(ctx);
9948 		return -1;
9949 	}
9950 	if (!ctx->object)
9951 		return len;
9952 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9953 	action_raw_encap_data = ctx->object;
9954 	idx = action_raw_encap_data->idx;
9955 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
9956 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
9957 	action_raw_encap_data->conf.preserve = NULL;
9958 	action->conf = &action_raw_encap_data->conf;
9959 	return len;
9960 }
9961 
9962 static int
9963 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
9964 			  const char *str, unsigned int len, void *buf,
9965 			  unsigned int size)
9966 {
9967 	struct buffer *out = buf;
9968 	int ret;
9969 
9970 	ret = parse_vc(ctx, token, str, len, buf, size);
9971 	if (ret < 0)
9972 		return ret;
9973 	/* Nothing else to do if there is no buffer. */
9974 	if (!out)
9975 		return ret;
9976 	if (!out->args.vc.actions_n)
9977 		return -1;
9978 	/* Point to selected object. */
9979 	ctx->object = out->args.vc.data;
9980 	ctx->objmask = NULL;
9981 	return ret;
9982 }
9983 
9984 static int
9985 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
9986 			  const char *str, unsigned int len, void *buf,
9987 			  unsigned int size)
9988 {
9989 	struct buffer *out = buf;
9990 	struct rte_flow_action *action;
9991 	struct action_raw_decap_data *action_raw_decap_data = NULL;
9992 	int ret;
9993 
9994 	ret = parse_vc(ctx, token, str, len, buf, size);
9995 	if (ret < 0)
9996 		return ret;
9997 	/* Nothing else to do if there is no buffer. */
9998 	if (!out)
9999 		return ret;
10000 	if (!out->args.vc.actions_n)
10001 		return -1;
10002 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10003 	/* Point to selected object. */
10004 	ctx->object = out->args.vc.data;
10005 	ctx->objmask = NULL;
10006 	/* Copy the headers to the buffer. */
10007 	action_raw_decap_data = ctx->object;
10008 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10009 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10010 	action->conf = &action_raw_decap_data->conf;
10011 	return ret;
10012 }
10013 
10014 static int
10015 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10016 				const char *str, unsigned int len, void *buf,
10017 				unsigned int size)
10018 {
10019 	struct buffer *out = buf;
10020 	struct rte_flow_action *action;
10021 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10022 	int ret;
10023 
10024 	ret = parse_vc(ctx, token, str, len, buf, size);
10025 	if (ret < 0)
10026 		return ret;
10027 	/* Nothing else to do if there is no buffer. */
10028 	if (!out)
10029 		return ret;
10030 	if (!out->args.vc.actions_n)
10031 		return -1;
10032 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10033 	/* Point to selected object. */
10034 	ctx->object = out->args.vc.data;
10035 	ctx->objmask = NULL;
10036 	/* Copy the headers to the buffer. */
10037 	ipv6_ext_remove_data = ctx->object;
10038 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10039 	action->conf = &ipv6_ext_remove_data->conf;
10040 	return ret;
10041 }
10042 
10043 static int
10044 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10045 				      const char *str, unsigned int len, void *buf,
10046 				      unsigned int size)
10047 {
10048 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10049 	struct rte_flow_action *action;
10050 	const struct arg *arg;
10051 	struct buffer *out = buf;
10052 	int ret;
10053 	uint16_t idx;
10054 
10055 	RTE_SET_USED(token);
10056 	RTE_SET_USED(buf);
10057 	RTE_SET_USED(size);
10058 	arg = ARGS_ENTRY_ARB_BOUNDED
10059 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10060 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10061 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10062 	if (push_args(ctx, arg))
10063 		return -1;
10064 	ret = parse_int(ctx, token, str, len, NULL, 0);
10065 	if (ret < 0) {
10066 		pop_args(ctx);
10067 		return -1;
10068 	}
10069 	if (!ctx->object)
10070 		return len;
10071 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10072 	action_ipv6_ext_remove_data = ctx->object;
10073 	idx = action_ipv6_ext_remove_data->idx;
10074 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10075 	action->conf = &action_ipv6_ext_remove_data->conf;
10076 	return len;
10077 }
10078 
10079 static int
10080 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10081 			      const char *str, unsigned int len, void *buf,
10082 			      unsigned int size)
10083 {
10084 	struct buffer *out = buf;
10085 	struct rte_flow_action *action;
10086 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10087 	int ret;
10088 
10089 	ret = parse_vc(ctx, token, str, len, buf, size);
10090 	if (ret < 0)
10091 		return ret;
10092 	/* Nothing else to do if there is no buffer. */
10093 	if (!out)
10094 		return ret;
10095 	if (!out->args.vc.actions_n)
10096 		return -1;
10097 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10098 	/* Point to selected object. */
10099 	ctx->object = out->args.vc.data;
10100 	ctx->objmask = NULL;
10101 	/* Copy the headers to the buffer. */
10102 	ipv6_ext_push_data = ctx->object;
10103 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10104 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10105 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10106 	action->conf = &ipv6_ext_push_data->conf;
10107 	return ret;
10108 }
10109 
10110 static int
10111 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10112 				    const char *str, unsigned int len, void *buf,
10113 				    unsigned int size)
10114 {
10115 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10116 	struct rte_flow_action *action;
10117 	const struct arg *arg;
10118 	struct buffer *out = buf;
10119 	int ret;
10120 	uint16_t idx;
10121 
10122 	RTE_SET_USED(token);
10123 	RTE_SET_USED(buf);
10124 	RTE_SET_USED(size);
10125 	arg = ARGS_ENTRY_ARB_BOUNDED
10126 		(offsetof(struct action_ipv6_ext_push_data, idx),
10127 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10128 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10129 	if (push_args(ctx, arg))
10130 		return -1;
10131 	ret = parse_int(ctx, token, str, len, NULL, 0);
10132 	if (ret < 0) {
10133 		pop_args(ctx);
10134 		return -1;
10135 	}
10136 	if (!ctx->object)
10137 		return len;
10138 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10139 	action_ipv6_ext_push_data = ctx->object;
10140 	idx = action_ipv6_ext_push_data->idx;
10141 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10142 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10143 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10144 	action->conf = &action_ipv6_ext_push_data->conf;
10145 	return len;
10146 }
10147 
10148 static int
10149 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10150 			 const char *str, unsigned int len, void *buf,
10151 			 unsigned int size)
10152 {
10153 	int ret;
10154 
10155 	ret = parse_vc(ctx, token, str, len, buf, size);
10156 	if (ret < 0)
10157 		return ret;
10158 	ret = rte_flow_dynf_metadata_register();
10159 	if (ret < 0)
10160 		return -1;
10161 	return len;
10162 }
10163 
10164 static int
10165 parse_vc_action_sample(struct context *ctx, const struct token *token,
10166 			 const char *str, unsigned int len, void *buf,
10167 			 unsigned int size)
10168 {
10169 	struct buffer *out = buf;
10170 	struct rte_flow_action *action;
10171 	struct action_sample_data *action_sample_data = NULL;
10172 	static struct rte_flow_action end_action = {
10173 		RTE_FLOW_ACTION_TYPE_END, 0
10174 	};
10175 	int ret;
10176 
10177 	ret = parse_vc(ctx, token, str, len, buf, size);
10178 	if (ret < 0)
10179 		return ret;
10180 	/* Nothing else to do if there is no buffer. */
10181 	if (!out)
10182 		return ret;
10183 	if (!out->args.vc.actions_n)
10184 		return -1;
10185 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10186 	/* Point to selected object. */
10187 	ctx->object = out->args.vc.data;
10188 	ctx->objmask = NULL;
10189 	/* Copy the headers to the buffer. */
10190 	action_sample_data = ctx->object;
10191 	action_sample_data->conf.actions = &end_action;
10192 	action->conf = &action_sample_data->conf;
10193 	return ret;
10194 }
10195 
10196 static int
10197 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10198 				const char *str, unsigned int len, void *buf,
10199 				unsigned int size)
10200 {
10201 	struct action_sample_data *action_sample_data;
10202 	struct rte_flow_action *action;
10203 	const struct arg *arg;
10204 	struct buffer *out = buf;
10205 	int ret;
10206 	uint16_t idx;
10207 
10208 	RTE_SET_USED(token);
10209 	RTE_SET_USED(buf);
10210 	RTE_SET_USED(size);
10211 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10212 		return -1;
10213 	arg = ARGS_ENTRY_ARB_BOUNDED
10214 		(offsetof(struct action_sample_data, idx),
10215 		 sizeof(((struct action_sample_data *)0)->idx),
10216 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10217 	if (push_args(ctx, arg))
10218 		return -1;
10219 	ret = parse_int(ctx, token, str, len, NULL, 0);
10220 	if (ret < 0) {
10221 		pop_args(ctx);
10222 		return -1;
10223 	}
10224 	if (!ctx->object)
10225 		return len;
10226 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10227 	action_sample_data = ctx->object;
10228 	idx = action_sample_data->idx;
10229 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10230 	action->conf = &action_sample_data->conf;
10231 	return len;
10232 }
10233 
10234 /** Parse operation for modify_field command. */
10235 static int
10236 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10237 			 const char *str, unsigned int len, void *buf,
10238 			 unsigned int size)
10239 {
10240 	struct rte_flow_action_modify_field *action_modify_field;
10241 	unsigned int i;
10242 
10243 	(void)token;
10244 	(void)buf;
10245 	(void)size;
10246 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10247 		return -1;
10248 	for (i = 0; modify_field_ops[i]; ++i)
10249 		if (!strcmp_partial(modify_field_ops[i], str, len))
10250 			break;
10251 	if (!modify_field_ops[i])
10252 		return -1;
10253 	if (!ctx->object)
10254 		return len;
10255 	action_modify_field = ctx->object;
10256 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10257 	return len;
10258 }
10259 
10260 /** Parse id for modify_field command. */
10261 static int
10262 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10263 			 const char *str, unsigned int len, void *buf,
10264 			 unsigned int size)
10265 {
10266 	struct rte_flow_action_modify_field *action_modify_field;
10267 	unsigned int i;
10268 
10269 	(void)token;
10270 	(void)buf;
10271 	(void)size;
10272 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10273 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10274 		return -1;
10275 	for (i = 0; flow_field_ids[i]; ++i)
10276 		if (!strcmp_partial(flow_field_ids[i], str, len))
10277 			break;
10278 	if (!flow_field_ids[i])
10279 		return -1;
10280 	if (!ctx->object)
10281 		return len;
10282 	action_modify_field = ctx->object;
10283 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10284 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10285 	else
10286 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10287 	return len;
10288 }
10289 
10290 /** Parse level for modify_field command. */
10291 static int
10292 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10293 			 const char *str, unsigned int len, void *buf,
10294 			 unsigned int size)
10295 {
10296 	struct rte_flow_action_modify_field *action;
10297 	struct flex_item *fp = NULL;
10298 	uint32_t val;
10299 	struct buffer *out = buf;
10300 	char *end;
10301 
10302 	(void)token;
10303 	(void)size;
10304 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10305 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10306 		return -1;
10307 	if (!ctx->object)
10308 		return len;
10309 	action = ctx->object;
10310 	errno = 0;
10311 	val = strtoumax(str, &end, 0);
10312 	if (errno || (size_t)(end - str) != len)
10313 		return -1;
10314 	/* No need to validate action template mask value */
10315 	if (out->args.vc.masks) {
10316 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10317 			action->dst.level = val;
10318 		else
10319 			action->src.level = val;
10320 		return len;
10321 	}
10322 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10323 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10324 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10325 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10326 		if (val >= FLEX_MAX_PARSERS_NUM) {
10327 			printf("Bad flex item handle\n");
10328 			return -1;
10329 		}
10330 		fp = flex_items[ctx->port][val];
10331 		if (!fp) {
10332 			printf("Bad flex item handle\n");
10333 			return -1;
10334 		}
10335 	}
10336 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10337 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10338 			action->dst.level = val;
10339 		else
10340 			action->dst.flex_handle = fp->flex_handle;
10341 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10342 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10343 			action->src.level = val;
10344 		else
10345 			action->src.flex_handle = fp->flex_handle;
10346 	}
10347 	return len;
10348 }
10349 
10350 /** Parse the conntrack update, not a rte_flow_action. */
10351 static int
10352 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10353 			 const char *str, unsigned int len, void *buf,
10354 			 unsigned int size)
10355 {
10356 	struct buffer *out = buf;
10357 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10358 
10359 	(void)size;
10360 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10361 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10362 		return -1;
10363 	/* Token name must match. */
10364 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10365 		return -1;
10366 	/* Nothing else to do if there is no buffer. */
10367 	if (!out)
10368 		return len;
10369 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10370 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10371 		ct_modify->new_ct.is_original_dir =
10372 				conntrack_context.is_original_dir;
10373 		ct_modify->direction = 1;
10374 	} else {
10375 		uint32_t old_dir;
10376 
10377 		old_dir = ct_modify->new_ct.is_original_dir;
10378 		memcpy(&ct_modify->new_ct, &conntrack_context,
10379 		       sizeof(conntrack_context));
10380 		ct_modify->new_ct.is_original_dir = old_dir;
10381 		ct_modify->state = 1;
10382 	}
10383 	return len;
10384 }
10385 
10386 /** Parse tokens for destroy command. */
10387 static int
10388 parse_destroy(struct context *ctx, const struct token *token,
10389 	      const char *str, unsigned int len,
10390 	      void *buf, unsigned int size)
10391 {
10392 	struct buffer *out = buf;
10393 
10394 	/* Token name must match. */
10395 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10396 		return -1;
10397 	/* Nothing else to do if there is no buffer. */
10398 	if (!out)
10399 		return len;
10400 	if (!out->command) {
10401 		if (ctx->curr != DESTROY)
10402 			return -1;
10403 		if (sizeof(*out) > size)
10404 			return -1;
10405 		out->command = ctx->curr;
10406 		ctx->objdata = 0;
10407 		ctx->object = out;
10408 		ctx->objmask = NULL;
10409 		out->args.destroy.rule =
10410 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10411 					       sizeof(double));
10412 		return len;
10413 	}
10414 	if (ctx->curr == DESTROY_IS_USER_ID) {
10415 		out->args.destroy.is_user_id = true;
10416 		return len;
10417 	}
10418 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10419 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10420 		return -1;
10421 	ctx->objdata = 0;
10422 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10423 	ctx->objmask = NULL;
10424 	return len;
10425 }
10426 
10427 /** Parse tokens for flush command. */
10428 static int
10429 parse_flush(struct context *ctx, const struct token *token,
10430 	    const char *str, unsigned int len,
10431 	    void *buf, unsigned int size)
10432 {
10433 	struct buffer *out = buf;
10434 
10435 	/* Token name must match. */
10436 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10437 		return -1;
10438 	/* Nothing else to do if there is no buffer. */
10439 	if (!out)
10440 		return len;
10441 	if (!out->command) {
10442 		if (ctx->curr != FLUSH)
10443 			return -1;
10444 		if (sizeof(*out) > size)
10445 			return -1;
10446 		out->command = ctx->curr;
10447 		ctx->objdata = 0;
10448 		ctx->object = out;
10449 		ctx->objmask = NULL;
10450 	}
10451 	return len;
10452 }
10453 
10454 /** Parse tokens for dump command. */
10455 static int
10456 parse_dump(struct context *ctx, const struct token *token,
10457 	    const char *str, unsigned int len,
10458 	    void *buf, unsigned int size)
10459 {
10460 	struct buffer *out = buf;
10461 
10462 	/* Token name must match. */
10463 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10464 		return -1;
10465 	/* Nothing else to do if there is no buffer. */
10466 	if (!out)
10467 		return len;
10468 	if (!out->command) {
10469 		if (ctx->curr != DUMP)
10470 			return -1;
10471 		if (sizeof(*out) > size)
10472 			return -1;
10473 		out->command = ctx->curr;
10474 		ctx->objdata = 0;
10475 		ctx->object = out;
10476 		ctx->objmask = NULL;
10477 		return len;
10478 	}
10479 	switch (ctx->curr) {
10480 	case DUMP_ALL:
10481 	case DUMP_ONE:
10482 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10483 		out->command = ctx->curr;
10484 		ctx->objdata = 0;
10485 		ctx->object = out;
10486 		ctx->objmask = NULL;
10487 		return len;
10488 	case DUMP_IS_USER_ID:
10489 		out->args.dump.is_user_id = true;
10490 		return len;
10491 	default:
10492 		return -1;
10493 	}
10494 }
10495 
10496 /** Parse tokens for query command. */
10497 static int
10498 parse_query(struct context *ctx, const struct token *token,
10499 	    const char *str, unsigned int len,
10500 	    void *buf, unsigned int size)
10501 {
10502 	struct buffer *out = buf;
10503 
10504 	/* Token name must match. */
10505 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10506 		return -1;
10507 	/* Nothing else to do if there is no buffer. */
10508 	if (!out)
10509 		return len;
10510 	if (!out->command) {
10511 		if (ctx->curr != QUERY)
10512 			return -1;
10513 		if (sizeof(*out) > size)
10514 			return -1;
10515 		out->command = ctx->curr;
10516 		ctx->objdata = 0;
10517 		ctx->object = out;
10518 		ctx->objmask = NULL;
10519 	}
10520 	if (ctx->curr == QUERY_IS_USER_ID) {
10521 		out->args.query.is_user_id = true;
10522 		return len;
10523 	}
10524 	return len;
10525 }
10526 
10527 /** Parse action names. */
10528 static int
10529 parse_action(struct context *ctx, const struct token *token,
10530 	     const char *str, unsigned int len,
10531 	     void *buf, unsigned int size)
10532 {
10533 	struct buffer *out = buf;
10534 	const struct arg *arg = pop_args(ctx);
10535 	unsigned int i;
10536 
10537 	(void)size;
10538 	/* Argument is expected. */
10539 	if (!arg)
10540 		return -1;
10541 	/* Parse action name. */
10542 	for (i = 0; next_action[i]; ++i) {
10543 		const struct parse_action_priv *priv;
10544 
10545 		token = &token_list[next_action[i]];
10546 		if (strcmp_partial(token->name, str, len))
10547 			continue;
10548 		priv = token->priv;
10549 		if (!priv)
10550 			goto error;
10551 		if (out)
10552 			memcpy((uint8_t *)ctx->object + arg->offset,
10553 			       &priv->type,
10554 			       arg->size);
10555 		return len;
10556 	}
10557 error:
10558 	push_args(ctx, arg);
10559 	return -1;
10560 }
10561 
10562 /** Parse tokens for list command. */
10563 static int
10564 parse_list(struct context *ctx, const struct token *token,
10565 	   const char *str, unsigned int len,
10566 	   void *buf, unsigned int size)
10567 {
10568 	struct buffer *out = buf;
10569 
10570 	/* Token name must match. */
10571 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10572 		return -1;
10573 	/* Nothing else to do if there is no buffer. */
10574 	if (!out)
10575 		return len;
10576 	if (!out->command) {
10577 		if (ctx->curr != LIST)
10578 			return -1;
10579 		if (sizeof(*out) > size)
10580 			return -1;
10581 		out->command = ctx->curr;
10582 		ctx->objdata = 0;
10583 		ctx->object = out;
10584 		ctx->objmask = NULL;
10585 		out->args.list.group =
10586 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10587 					       sizeof(double));
10588 		return len;
10589 	}
10590 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10591 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10592 		return -1;
10593 	ctx->objdata = 0;
10594 	ctx->object = out->args.list.group + out->args.list.group_n++;
10595 	ctx->objmask = NULL;
10596 	return len;
10597 }
10598 
10599 /** Parse tokens for list all aged flows command. */
10600 static int
10601 parse_aged(struct context *ctx, const struct token *token,
10602 	   const char *str, unsigned int len,
10603 	   void *buf, unsigned int size)
10604 {
10605 	struct buffer *out = buf;
10606 
10607 	/* Token name must match. */
10608 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10609 		return -1;
10610 	/* Nothing else to do if there is no buffer. */
10611 	if (!out)
10612 		return len;
10613 	if (!out->command || out->command == QUEUE) {
10614 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10615 			return -1;
10616 		if (sizeof(*out) > size)
10617 			return -1;
10618 		out->command = ctx->curr;
10619 		ctx->objdata = 0;
10620 		ctx->object = out;
10621 		ctx->objmask = NULL;
10622 	}
10623 	if (ctx->curr == AGED_DESTROY)
10624 		out->args.aged.destroy = 1;
10625 	return len;
10626 }
10627 
10628 /** Parse tokens for isolate command. */
10629 static int
10630 parse_isolate(struct context *ctx, const struct token *token,
10631 	      const char *str, unsigned int len,
10632 	      void *buf, unsigned int size)
10633 {
10634 	struct buffer *out = buf;
10635 
10636 	/* Token name must match. */
10637 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10638 		return -1;
10639 	/* Nothing else to do if there is no buffer. */
10640 	if (!out)
10641 		return len;
10642 	if (!out->command) {
10643 		if (ctx->curr != ISOLATE)
10644 			return -1;
10645 		if (sizeof(*out) > size)
10646 			return -1;
10647 		out->command = ctx->curr;
10648 		ctx->objdata = 0;
10649 		ctx->object = out;
10650 		ctx->objmask = NULL;
10651 	}
10652 	return len;
10653 }
10654 
10655 /** Parse tokens for info/configure command. */
10656 static int
10657 parse_configure(struct context *ctx, const struct token *token,
10658 		const char *str, unsigned int len,
10659 		void *buf, unsigned int size)
10660 {
10661 	struct buffer *out = buf;
10662 
10663 	/* Token name must match. */
10664 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10665 		return -1;
10666 	/* Nothing else to do if there is no buffer. */
10667 	if (!out)
10668 		return len;
10669 	if (!out->command) {
10670 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10671 			return -1;
10672 		if (sizeof(*out) > size)
10673 			return -1;
10674 		out->command = ctx->curr;
10675 		ctx->objdata = 0;
10676 		ctx->object = out;
10677 		ctx->objmask = NULL;
10678 	}
10679 	return len;
10680 }
10681 
10682 /** Parse tokens for template create command. */
10683 static int
10684 parse_template(struct context *ctx, const struct token *token,
10685 	       const char *str, unsigned int len,
10686 	       void *buf, unsigned int size)
10687 {
10688 	struct buffer *out = buf;
10689 
10690 	/* Token name must match. */
10691 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10692 		return -1;
10693 	/* Nothing else to do if there is no buffer. */
10694 	if (!out)
10695 		return len;
10696 	if (!out->command) {
10697 		if (ctx->curr != PATTERN_TEMPLATE &&
10698 		    ctx->curr != ACTIONS_TEMPLATE)
10699 			return -1;
10700 		if (sizeof(*out) > size)
10701 			return -1;
10702 		out->command = ctx->curr;
10703 		ctx->objdata = 0;
10704 		ctx->object = out;
10705 		ctx->objmask = NULL;
10706 		out->args.vc.data = (uint8_t *)out + size;
10707 		return len;
10708 	}
10709 	switch (ctx->curr) {
10710 	case PATTERN_TEMPLATE_CREATE:
10711 		out->args.vc.pattern =
10712 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10713 					       sizeof(double));
10714 		out->args.vc.pat_templ_id = UINT32_MAX;
10715 		out->command = ctx->curr;
10716 		ctx->objdata = 0;
10717 		ctx->object = out;
10718 		ctx->objmask = NULL;
10719 		return len;
10720 	case PATTERN_TEMPLATE_EGRESS:
10721 		out->args.vc.attr.egress = 1;
10722 		return len;
10723 	case PATTERN_TEMPLATE_INGRESS:
10724 		out->args.vc.attr.ingress = 1;
10725 		return len;
10726 	case PATTERN_TEMPLATE_TRANSFER:
10727 		out->args.vc.attr.transfer = 1;
10728 		return len;
10729 	case ACTIONS_TEMPLATE_CREATE:
10730 		out->args.vc.act_templ_id = UINT32_MAX;
10731 		out->command = ctx->curr;
10732 		ctx->objdata = 0;
10733 		ctx->object = out;
10734 		ctx->objmask = NULL;
10735 		return len;
10736 	case ACTIONS_TEMPLATE_SPEC:
10737 		out->args.vc.actions =
10738 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10739 					       sizeof(double));
10740 		ctx->object = out->args.vc.actions;
10741 		ctx->objmask = NULL;
10742 		return len;
10743 	case ACTIONS_TEMPLATE_MASK:
10744 		out->args.vc.masks =
10745 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10746 					       (out->args.vc.actions +
10747 						out->args.vc.actions_n),
10748 					       sizeof(double));
10749 		ctx->object = out->args.vc.masks;
10750 		ctx->objmask = NULL;
10751 		return len;
10752 	case ACTIONS_TEMPLATE_EGRESS:
10753 		out->args.vc.attr.egress = 1;
10754 		return len;
10755 	case ACTIONS_TEMPLATE_INGRESS:
10756 		out->args.vc.attr.ingress = 1;
10757 		return len;
10758 	case ACTIONS_TEMPLATE_TRANSFER:
10759 		out->args.vc.attr.transfer = 1;
10760 		return len;
10761 	default:
10762 		return -1;
10763 	}
10764 }
10765 
10766 /** Parse tokens for template destroy command. */
10767 static int
10768 parse_template_destroy(struct context *ctx, const struct token *token,
10769 		       const char *str, unsigned int len,
10770 		       void *buf, unsigned int size)
10771 {
10772 	struct buffer *out = buf;
10773 	uint32_t *template_id;
10774 
10775 	/* Token name must match. */
10776 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10777 		return -1;
10778 	/* Nothing else to do if there is no buffer. */
10779 	if (!out)
10780 		return len;
10781 	if (!out->command ||
10782 		out->command == PATTERN_TEMPLATE ||
10783 		out->command == ACTIONS_TEMPLATE) {
10784 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10785 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10786 			return -1;
10787 		if (sizeof(*out) > size)
10788 			return -1;
10789 		out->command = ctx->curr;
10790 		ctx->objdata = 0;
10791 		ctx->object = out;
10792 		ctx->objmask = NULL;
10793 		out->args.templ_destroy.template_id =
10794 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10795 					       sizeof(double));
10796 		return len;
10797 	}
10798 	template_id = out->args.templ_destroy.template_id
10799 		    + out->args.templ_destroy.template_id_n++;
10800 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10801 		return -1;
10802 	ctx->objdata = 0;
10803 	ctx->object = template_id;
10804 	ctx->objmask = NULL;
10805 	return len;
10806 }
10807 
10808 /** Parse tokens for table create command. */
10809 static int
10810 parse_table(struct context *ctx, const struct token *token,
10811 	    const char *str, unsigned int len,
10812 	    void *buf, unsigned int size)
10813 {
10814 	struct buffer *out = buf;
10815 	uint32_t *template_id;
10816 
10817 	/* Token name must match. */
10818 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10819 		return -1;
10820 	/* Nothing else to do if there is no buffer. */
10821 	if (!out)
10822 		return len;
10823 	if (!out->command) {
10824 		if (ctx->curr != TABLE)
10825 			return -1;
10826 		if (sizeof(*out) > size)
10827 			return -1;
10828 		out->command = ctx->curr;
10829 		ctx->objdata = 0;
10830 		ctx->object = out;
10831 		ctx->objmask = NULL;
10832 		return len;
10833 	}
10834 	switch (ctx->curr) {
10835 	case TABLE_CREATE:
10836 	case TABLE_RESIZE:
10837 		out->command = ctx->curr;
10838 		ctx->objdata = 0;
10839 		ctx->object = out;
10840 		ctx->objmask = NULL;
10841 		out->args.table.id = UINT32_MAX;
10842 		return len;
10843 	case TABLE_PATTERN_TEMPLATE:
10844 		out->args.table.pat_templ_id =
10845 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10846 					       sizeof(double));
10847 		template_id = out->args.table.pat_templ_id
10848 				+ out->args.table.pat_templ_id_n++;
10849 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10850 			return -1;
10851 		ctx->objdata = 0;
10852 		ctx->object = template_id;
10853 		ctx->objmask = NULL;
10854 		return len;
10855 	case TABLE_ACTIONS_TEMPLATE:
10856 		out->args.table.act_templ_id =
10857 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10858 					       (out->args.table.pat_templ_id +
10859 						out->args.table.pat_templ_id_n),
10860 					       sizeof(double));
10861 		template_id = out->args.table.act_templ_id
10862 				+ out->args.table.act_templ_id_n++;
10863 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10864 			return -1;
10865 		ctx->objdata = 0;
10866 		ctx->object = template_id;
10867 		ctx->objmask = NULL;
10868 		return len;
10869 	case TABLE_INGRESS:
10870 		out->args.table.attr.flow_attr.ingress = 1;
10871 		return len;
10872 	case TABLE_EGRESS:
10873 		out->args.table.attr.flow_attr.egress = 1;
10874 		return len;
10875 	case TABLE_TRANSFER:
10876 		out->args.table.attr.flow_attr.transfer = 1;
10877 		return len;
10878 	case TABLE_TRANSFER_WIRE_ORIG:
10879 		if (!out->args.table.attr.flow_attr.transfer)
10880 			return -1;
10881 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
10882 		return len;
10883 	case TABLE_TRANSFER_VPORT_ORIG:
10884 		if (!out->args.table.attr.flow_attr.transfer)
10885 			return -1;
10886 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
10887 		return len;
10888 	case TABLE_RESIZABLE:
10889 		out->args.table.attr.specialize |=
10890 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
10891 		return len;
10892 	case TABLE_RULES_NUMBER:
10893 		ctx->objdata = 0;
10894 		ctx->object = out;
10895 		ctx->objmask = NULL;
10896 		return len;
10897 	case TABLE_RESIZE_ID:
10898 	case TABLE_RESIZE_RULES_NUMBER:
10899 		return len;
10900 	default:
10901 		return -1;
10902 	}
10903 }
10904 
10905 /** Parse tokens for table destroy command. */
10906 static int
10907 parse_table_destroy(struct context *ctx, const struct token *token,
10908 		    const char *str, unsigned int len,
10909 		    void *buf, unsigned int size)
10910 {
10911 	struct buffer *out = buf;
10912 	uint32_t *table_id;
10913 
10914 	/* Token name must match. */
10915 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10916 		return -1;
10917 	/* Nothing else to do if there is no buffer. */
10918 	if (!out)
10919 		return len;
10920 	if (!out->command || out->command == TABLE) {
10921 		if (ctx->curr != TABLE_DESTROY &&
10922 		    ctx->curr != TABLE_RESIZE_COMPLETE)
10923 			return -1;
10924 		if (sizeof(*out) > size)
10925 			return -1;
10926 		out->command = ctx->curr;
10927 		ctx->objdata = 0;
10928 		ctx->object = out;
10929 		ctx->objmask = NULL;
10930 		out->args.table_destroy.table_id =
10931 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10932 					       sizeof(double));
10933 		return len;
10934 	}
10935 	table_id = out->args.table_destroy.table_id
10936 		    + out->args.table_destroy.table_id_n++;
10937 	if ((uint8_t *)table_id > (uint8_t *)out + size)
10938 		return -1;
10939 	ctx->objdata = 0;
10940 	ctx->object = table_id;
10941 	ctx->objmask = NULL;
10942 	return len;
10943 }
10944 
10945 /** Parse tokens for queue create commands. */
10946 static int
10947 parse_qo(struct context *ctx, const struct token *token,
10948 	 const char *str, unsigned int len,
10949 	 void *buf, unsigned int size)
10950 {
10951 	struct buffer *out = buf;
10952 
10953 	/* Token name must match. */
10954 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10955 		return -1;
10956 	/* Nothing else to do if there is no buffer. */
10957 	if (!out)
10958 		return len;
10959 	if (!out->command) {
10960 		if (ctx->curr != QUEUE)
10961 			return -1;
10962 		if (sizeof(*out) > size)
10963 			return -1;
10964 		out->command = ctx->curr;
10965 		ctx->objdata = 0;
10966 		ctx->object = out;
10967 		ctx->objmask = NULL;
10968 		out->args.vc.data = (uint8_t *)out + size;
10969 		return len;
10970 	}
10971 	switch (ctx->curr) {
10972 	case QUEUE_CREATE:
10973 	case QUEUE_UPDATE:
10974 		out->command = ctx->curr;
10975 		ctx->objdata = 0;
10976 		ctx->object = out;
10977 		ctx->objmask = NULL;
10978 		out->args.vc.rule_id = UINT32_MAX;
10979 		return len;
10980 	case QUEUE_TEMPLATE_TABLE:
10981 	case QUEUE_PATTERN_TEMPLATE:
10982 	case QUEUE_ACTIONS_TEMPLATE:
10983 	case QUEUE_CREATE_POSTPONE:
10984 	case QUEUE_RULE_ID:
10985 	case QUEUE_UPDATE_ID:
10986 		return len;
10987 	case ITEM_PATTERN:
10988 		out->args.vc.pattern =
10989 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10990 					       sizeof(double));
10991 		ctx->object = out->args.vc.pattern;
10992 		ctx->objmask = NULL;
10993 		return len;
10994 	case ACTIONS:
10995 		out->args.vc.actions =
10996 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10997 					       (out->args.vc.pattern +
10998 						out->args.vc.pattern_n),
10999 					       sizeof(double));
11000 		ctx->object = out->args.vc.actions;
11001 		ctx->objmask = NULL;
11002 		return len;
11003 	default:
11004 		return -1;
11005 	}
11006 }
11007 
11008 /** Parse tokens for queue destroy command. */
11009 static int
11010 parse_qo_destroy(struct context *ctx, const struct token *token,
11011 		 const char *str, unsigned int len,
11012 		 void *buf, unsigned int size)
11013 {
11014 	struct buffer *out = buf;
11015 	uint64_t *flow_id;
11016 
11017 	/* Token name must match. */
11018 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11019 		return -1;
11020 	/* Nothing else to do if there is no buffer. */
11021 	if (!out)
11022 		return len;
11023 	if (!out->command || out->command == QUEUE) {
11024 		if (ctx->curr != QUEUE_DESTROY &&
11025 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11026 			return -1;
11027 		if (sizeof(*out) > size)
11028 			return -1;
11029 		out->command = ctx->curr;
11030 		ctx->objdata = 0;
11031 		ctx->object = out;
11032 		ctx->objmask = NULL;
11033 		out->args.destroy.rule =
11034 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11035 					       sizeof(double));
11036 		return len;
11037 	}
11038 	switch (ctx->curr) {
11039 	case QUEUE_DESTROY_ID:
11040 		flow_id = out->args.destroy.rule
11041 				+ out->args.destroy.rule_n++;
11042 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11043 			return -1;
11044 		ctx->objdata = 0;
11045 		ctx->object = flow_id;
11046 		ctx->objmask = NULL;
11047 		return len;
11048 	case QUEUE_DESTROY_POSTPONE:
11049 		return len;
11050 	default:
11051 		return -1;
11052 	}
11053 }
11054 
11055 /** Parse tokens for push queue command. */
11056 static int
11057 parse_push(struct context *ctx, const struct token *token,
11058 	   const char *str, unsigned int len,
11059 	   void *buf, unsigned int size)
11060 {
11061 	struct buffer *out = buf;
11062 
11063 	/* Token name must match. */
11064 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11065 		return -1;
11066 	/* Nothing else to do if there is no buffer. */
11067 	if (!out)
11068 		return len;
11069 	if (!out->command) {
11070 		if (ctx->curr != PUSH)
11071 			return -1;
11072 		if (sizeof(*out) > size)
11073 			return -1;
11074 		out->command = ctx->curr;
11075 		ctx->objdata = 0;
11076 		ctx->object = out;
11077 		ctx->objmask = NULL;
11078 		out->args.vc.data = (uint8_t *)out + size;
11079 	}
11080 	return len;
11081 }
11082 
11083 /** Parse tokens for pull command. */
11084 static int
11085 parse_pull(struct context *ctx, const struct token *token,
11086 	   const char *str, unsigned int len,
11087 	   void *buf, unsigned int size)
11088 {
11089 	struct buffer *out = buf;
11090 
11091 	/* Token name must match. */
11092 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11093 		return -1;
11094 	/* Nothing else to do if there is no buffer. */
11095 	if (!out)
11096 		return len;
11097 	if (!out->command) {
11098 		if (ctx->curr != PULL)
11099 			return -1;
11100 		if (sizeof(*out) > size)
11101 			return -1;
11102 		out->command = ctx->curr;
11103 		ctx->objdata = 0;
11104 		ctx->object = out;
11105 		ctx->objmask = NULL;
11106 		out->args.vc.data = (uint8_t *)out + size;
11107 	}
11108 	return len;
11109 }
11110 
11111 /** Parse tokens for hash calculation commands. */
11112 static int
11113 parse_hash(struct context *ctx, const struct token *token,
11114 	 const char *str, unsigned int len,
11115 	 void *buf, unsigned int size)
11116 {
11117 	struct buffer *out = buf;
11118 
11119 	/* Token name must match. */
11120 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11121 		return -1;
11122 	/* Nothing else to do if there is no buffer. */
11123 	if (!out)
11124 		return len;
11125 	if (!out->command) {
11126 		if (ctx->curr != HASH)
11127 			return -1;
11128 		if (sizeof(*out) > size)
11129 			return -1;
11130 		out->command = ctx->curr;
11131 		ctx->objdata = 0;
11132 		ctx->object = out;
11133 		ctx->objmask = NULL;
11134 		out->args.vc.data = (uint8_t *)out + size;
11135 		return len;
11136 	}
11137 	switch (ctx->curr) {
11138 	case HASH_CALC_TABLE:
11139 	case HASH_CALC_PATTERN_INDEX:
11140 		return len;
11141 	case ITEM_PATTERN:
11142 		out->args.vc.pattern =
11143 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11144 					       sizeof(double));
11145 		ctx->object = out->args.vc.pattern;
11146 		ctx->objmask = NULL;
11147 		return len;
11148 	case HASH_CALC_ENCAP:
11149 		out->args.vc.encap_hash = 1;
11150 		return len;
11151 	case ENCAP_HASH_FIELD_SRC_PORT:
11152 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11153 		return len;
11154 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11155 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11156 		return len;
11157 	default:
11158 		return -1;
11159 	}
11160 }
11161 
11162 static int
11163 parse_group(struct context *ctx, const struct token *token,
11164 	    const char *str, unsigned int len,
11165 	    void *buf, unsigned int size)
11166 {
11167 	struct buffer *out = buf;
11168 
11169 	/* Token name must match. */
11170 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11171 		return -1;
11172 	/* Nothing else to do if there is no buffer. */
11173 	if (!out)
11174 		return len;
11175 	if (!out->command) {
11176 		if (ctx->curr != FLOW_GROUP)
11177 			return -1;
11178 		if (sizeof(*out) > size)
11179 			return -1;
11180 		out->command = ctx->curr;
11181 		ctx->objdata = 0;
11182 		ctx->object = out;
11183 		ctx->objmask = NULL;
11184 		out->args.vc.data = (uint8_t *)out + size;
11185 		return len;
11186 	}
11187 	switch (ctx->curr) {
11188 	case GROUP_INGRESS:
11189 		out->args.vc.attr.ingress = 1;
11190 		return len;
11191 	case GROUP_EGRESS:
11192 		out->args.vc.attr.egress = 1;
11193 		return len;
11194 	case GROUP_TRANSFER:
11195 		out->args.vc.attr.transfer = 1;
11196 		return len;
11197 	case GROUP_SET_MISS_ACTIONS:
11198 		out->command = ctx->curr;
11199 		ctx->objdata = 0;
11200 		ctx->object = out;
11201 		ctx->objmask = NULL;
11202 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11203 							       sizeof(double));
11204 		return len;
11205 	default:
11206 		return -1;
11207 	}
11208 }
11209 
11210 static int
11211 parse_flex(struct context *ctx, const struct token *token,
11212 	     const char *str, unsigned int len,
11213 	     void *buf, unsigned int size)
11214 {
11215 	struct buffer *out = buf;
11216 
11217 	/* Token name must match. */
11218 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11219 		return -1;
11220 	/* Nothing else to do if there is no buffer. */
11221 	if (!out)
11222 		return len;
11223 	if (out->command == ZERO) {
11224 		if (ctx->curr != FLEX)
11225 			return -1;
11226 		if (sizeof(*out) > size)
11227 			return -1;
11228 		out->command = ctx->curr;
11229 		ctx->objdata = 0;
11230 		ctx->object = out;
11231 		ctx->objmask = NULL;
11232 	} else {
11233 		switch (ctx->curr) {
11234 		default:
11235 			break;
11236 		case FLEX_ITEM_INIT:
11237 		case FLEX_ITEM_CREATE:
11238 		case FLEX_ITEM_DESTROY:
11239 			out->command = ctx->curr;
11240 			break;
11241 		}
11242 	}
11243 
11244 	return len;
11245 }
11246 
11247 static int
11248 parse_tunnel(struct context *ctx, const struct token *token,
11249 	     const char *str, unsigned int len,
11250 	     void *buf, unsigned int size)
11251 {
11252 	struct buffer *out = buf;
11253 
11254 	/* Token name must match. */
11255 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11256 		return -1;
11257 	/* Nothing else to do if there is no buffer. */
11258 	if (!out)
11259 		return len;
11260 	if (!out->command) {
11261 		if (ctx->curr != TUNNEL)
11262 			return -1;
11263 		if (sizeof(*out) > size)
11264 			return -1;
11265 		out->command = ctx->curr;
11266 		ctx->objdata = 0;
11267 		ctx->object = out;
11268 		ctx->objmask = NULL;
11269 	} else {
11270 		switch (ctx->curr) {
11271 		default:
11272 			break;
11273 		case TUNNEL_CREATE:
11274 		case TUNNEL_DESTROY:
11275 		case TUNNEL_LIST:
11276 			out->command = ctx->curr;
11277 			break;
11278 		case TUNNEL_CREATE_TYPE:
11279 		case TUNNEL_DESTROY_ID:
11280 			ctx->object = &out->args.vc.tunnel_ops;
11281 			break;
11282 		}
11283 	}
11284 
11285 	return len;
11286 }
11287 
11288 /**
11289  * Parse signed/unsigned integers 8 to 64-bit long.
11290  *
11291  * Last argument (ctx->args) is retrieved to determine integer type and
11292  * storage location.
11293  */
11294 static int
11295 parse_int(struct context *ctx, const struct token *token,
11296 	  const char *str, unsigned int len,
11297 	  void *buf, unsigned int size)
11298 {
11299 	const struct arg *arg = pop_args(ctx);
11300 	uintmax_t u;
11301 	char *end;
11302 
11303 	(void)token;
11304 	/* Argument is expected. */
11305 	if (!arg)
11306 		return -1;
11307 	errno = 0;
11308 	u = arg->sign ?
11309 		(uintmax_t)strtoimax(str, &end, 0) :
11310 		strtoumax(str, &end, 0);
11311 	if (errno || (size_t)(end - str) != len)
11312 		goto error;
11313 	if (arg->bounded &&
11314 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11315 			    (intmax_t)u > (intmax_t)arg->max)) ||
11316 	     (!arg->sign && (u < arg->min || u > arg->max))))
11317 		goto error;
11318 	if (!ctx->object)
11319 		return len;
11320 	if (arg->mask) {
11321 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11322 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11323 			goto error;
11324 		return len;
11325 	}
11326 	buf = (uint8_t *)ctx->object + arg->offset;
11327 	size = arg->size;
11328 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11329 		return -1;
11330 objmask:
11331 	switch (size) {
11332 	case sizeof(uint8_t):
11333 		*(uint8_t *)buf = u;
11334 		break;
11335 	case sizeof(uint16_t):
11336 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11337 		break;
11338 	case sizeof(uint8_t [3]):
11339 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11340 		if (!arg->hton) {
11341 			((uint8_t *)buf)[0] = u;
11342 			((uint8_t *)buf)[1] = u >> 8;
11343 			((uint8_t *)buf)[2] = u >> 16;
11344 			break;
11345 		}
11346 #endif
11347 		((uint8_t *)buf)[0] = u >> 16;
11348 		((uint8_t *)buf)[1] = u >> 8;
11349 		((uint8_t *)buf)[2] = u;
11350 		break;
11351 	case sizeof(uint32_t):
11352 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11353 		break;
11354 	case sizeof(uint64_t):
11355 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11356 		break;
11357 	default:
11358 		goto error;
11359 	}
11360 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11361 		u = -1;
11362 		buf = (uint8_t *)ctx->objmask + arg->offset;
11363 		goto objmask;
11364 	}
11365 	return len;
11366 error:
11367 	push_args(ctx, arg);
11368 	return -1;
11369 }
11370 
11371 /**
11372  * Parse a string.
11373  *
11374  * Three arguments (ctx->args) are retrieved from the stack to store data,
11375  * its actual length and address (in that order).
11376  */
11377 static int
11378 parse_string(struct context *ctx, const struct token *token,
11379 	     const char *str, unsigned int len,
11380 	     void *buf, unsigned int size)
11381 {
11382 	const struct arg *arg_data = pop_args(ctx);
11383 	const struct arg *arg_len = pop_args(ctx);
11384 	const struct arg *arg_addr = pop_args(ctx);
11385 	char tmp[16]; /* Ought to be enough. */
11386 	int ret;
11387 
11388 	/* Arguments are expected. */
11389 	if (!arg_data)
11390 		return -1;
11391 	if (!arg_len) {
11392 		push_args(ctx, arg_data);
11393 		return -1;
11394 	}
11395 	if (!arg_addr) {
11396 		push_args(ctx, arg_len);
11397 		push_args(ctx, arg_data);
11398 		return -1;
11399 	}
11400 	size = arg_data->size;
11401 	/* Bit-mask fill is not supported. */
11402 	if (arg_data->mask || size < len)
11403 		goto error;
11404 	if (!ctx->object)
11405 		return len;
11406 	/* Let parse_int() fill length information first. */
11407 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11408 	if (ret < 0)
11409 		goto error;
11410 	push_args(ctx, arg_len);
11411 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11412 	if (ret < 0) {
11413 		pop_args(ctx);
11414 		goto error;
11415 	}
11416 	buf = (uint8_t *)ctx->object + arg_data->offset;
11417 	/* Output buffer is not necessarily NUL-terminated. */
11418 	memcpy(buf, str, len);
11419 	memset((uint8_t *)buf + len, 0x00, size - len);
11420 	if (ctx->objmask)
11421 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11422 	/* Save address if requested. */
11423 	if (arg_addr->size) {
11424 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11425 		       (void *[]){
11426 			(uint8_t *)ctx->object + arg_data->offset
11427 		       },
11428 		       arg_addr->size);
11429 		if (ctx->objmask)
11430 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11431 			       (void *[]){
11432 				(uint8_t *)ctx->objmask + arg_data->offset
11433 			       },
11434 			       arg_addr->size);
11435 	}
11436 	return len;
11437 error:
11438 	push_args(ctx, arg_addr);
11439 	push_args(ctx, arg_len);
11440 	push_args(ctx, arg_data);
11441 	return -1;
11442 }
11443 
11444 static int
11445 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11446 {
11447 	const uint8_t *head = dst;
11448 	uint32_t left;
11449 
11450 	if (*size == 0)
11451 		return -1;
11452 
11453 	left = *size;
11454 
11455 	/* Convert chars to bytes */
11456 	while (left) {
11457 		char tmp[3], *end = tmp;
11458 		uint32_t read_lim = left & 1 ? 1 : 2;
11459 
11460 		snprintf(tmp, read_lim + 1, "%s", src);
11461 		*dst = strtoul(tmp, &end, 16);
11462 		if (*end) {
11463 			*dst = 0;
11464 			*size = (uint32_t)(dst - head);
11465 			return -1;
11466 		}
11467 		left -= read_lim;
11468 		src += read_lim;
11469 		dst++;
11470 	}
11471 	*dst = 0;
11472 	*size = (uint32_t)(dst - head);
11473 	return 0;
11474 }
11475 
11476 static int
11477 parse_hex(struct context *ctx, const struct token *token,
11478 		const char *str, unsigned int len,
11479 		void *buf, unsigned int size)
11480 {
11481 	const struct arg *arg_data = pop_args(ctx);
11482 	const struct arg *arg_len = pop_args(ctx);
11483 	const struct arg *arg_addr = pop_args(ctx);
11484 	char tmp[16]; /* Ought to be enough. */
11485 	int ret;
11486 	unsigned int hexlen = len;
11487 	unsigned int length = 256;
11488 	uint8_t hex_tmp[length];
11489 
11490 	/* Arguments are expected. */
11491 	if (!arg_data)
11492 		return -1;
11493 	if (!arg_len) {
11494 		push_args(ctx, arg_data);
11495 		return -1;
11496 	}
11497 	if (!arg_addr) {
11498 		push_args(ctx, arg_len);
11499 		push_args(ctx, arg_data);
11500 		return -1;
11501 	}
11502 	size = arg_data->size;
11503 	/* Bit-mask fill is not supported. */
11504 	if (arg_data->mask)
11505 		goto error;
11506 	if (!ctx->object)
11507 		return len;
11508 
11509 	/* translate bytes string to array. */
11510 	if (str[0] == '0' && ((str[1] == 'x') ||
11511 			(str[1] == 'X'))) {
11512 		str += 2;
11513 		hexlen -= 2;
11514 	}
11515 	if (hexlen > length)
11516 		goto error;
11517 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11518 	if (ret < 0)
11519 		goto error;
11520 	/* Check the converted binary fits into data buffer. */
11521 	if (hexlen > size)
11522 		goto error;
11523 	/* Let parse_int() fill length information first. */
11524 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11525 	if (ret < 0)
11526 		goto error;
11527 	/* Save length if requested. */
11528 	if (arg_len->size) {
11529 		push_args(ctx, arg_len);
11530 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11531 		if (ret < 0) {
11532 			pop_args(ctx);
11533 			goto error;
11534 		}
11535 	}
11536 	buf = (uint8_t *)ctx->object + arg_data->offset;
11537 	/* Output buffer is not necessarily NUL-terminated. */
11538 	memcpy(buf, hex_tmp, hexlen);
11539 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11540 	if (ctx->objmask)
11541 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11542 					0xff, hexlen);
11543 	/* Save address if requested. */
11544 	if (arg_addr->size) {
11545 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11546 		       (void *[]){
11547 			(uint8_t *)ctx->object + arg_data->offset
11548 		       },
11549 		       arg_addr->size);
11550 		if (ctx->objmask)
11551 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11552 			       (void *[]){
11553 				(uint8_t *)ctx->objmask + arg_data->offset
11554 			       },
11555 			       arg_addr->size);
11556 	}
11557 	return len;
11558 error:
11559 	push_args(ctx, arg_addr);
11560 	push_args(ctx, arg_len);
11561 	push_args(ctx, arg_data);
11562 	return -1;
11563 
11564 }
11565 
11566 /**
11567  * Parse a zero-ended string.
11568  */
11569 static int
11570 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11571 	     const char *str, unsigned int len,
11572 	     void *buf, unsigned int size)
11573 {
11574 	const struct arg *arg_data = pop_args(ctx);
11575 
11576 	/* Arguments are expected. */
11577 	if (!arg_data)
11578 		return -1;
11579 	size = arg_data->size;
11580 	/* Bit-mask fill is not supported. */
11581 	if (arg_data->mask || size < len + 1)
11582 		goto error;
11583 	if (!ctx->object)
11584 		return len;
11585 	buf = (uint8_t *)ctx->object + arg_data->offset;
11586 	strncpy(buf, str, len);
11587 	if (ctx->objmask)
11588 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11589 	return len;
11590 error:
11591 	push_args(ctx, arg_data);
11592 	return -1;
11593 }
11594 
11595 /**
11596  * Parse a MAC address.
11597  *
11598  * Last argument (ctx->args) is retrieved to determine storage size and
11599  * location.
11600  */
11601 static int
11602 parse_mac_addr(struct context *ctx, const struct token *token,
11603 	       const char *str, unsigned int len,
11604 	       void *buf, unsigned int size)
11605 {
11606 	const struct arg *arg = pop_args(ctx);
11607 	struct rte_ether_addr tmp;
11608 	int ret;
11609 
11610 	(void)token;
11611 	/* Argument is expected. */
11612 	if (!arg)
11613 		return -1;
11614 	size = arg->size;
11615 	/* Bit-mask fill is not supported. */
11616 	if (arg->mask || size != sizeof(tmp))
11617 		goto error;
11618 	/* Only network endian is supported. */
11619 	if (!arg->hton)
11620 		goto error;
11621 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11622 	if (ret < 0 || (unsigned int)ret != len)
11623 		goto error;
11624 	if (!ctx->object)
11625 		return len;
11626 	buf = (uint8_t *)ctx->object + arg->offset;
11627 	memcpy(buf, &tmp, size);
11628 	if (ctx->objmask)
11629 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11630 	return len;
11631 error:
11632 	push_args(ctx, arg);
11633 	return -1;
11634 }
11635 
11636 /**
11637  * Parse an IPv4 address.
11638  *
11639  * Last argument (ctx->args) is retrieved to determine storage size and
11640  * location.
11641  */
11642 static int
11643 parse_ipv4_addr(struct context *ctx, const struct token *token,
11644 		const char *str, unsigned int len,
11645 		void *buf, unsigned int size)
11646 {
11647 	const struct arg *arg = pop_args(ctx);
11648 	char str2[len + 1];
11649 	struct in_addr tmp;
11650 	int ret;
11651 
11652 	/* Argument is expected. */
11653 	if (!arg)
11654 		return -1;
11655 	size = arg->size;
11656 	/* Bit-mask fill is not supported. */
11657 	if (arg->mask || size != sizeof(tmp))
11658 		goto error;
11659 	/* Only network endian is supported. */
11660 	if (!arg->hton)
11661 		goto error;
11662 	memcpy(str2, str, len);
11663 	str2[len] = '\0';
11664 	ret = inet_pton(AF_INET, str2, &tmp);
11665 	if (ret != 1) {
11666 		/* Attempt integer parsing. */
11667 		push_args(ctx, arg);
11668 		return parse_int(ctx, token, str, len, buf, size);
11669 	}
11670 	if (!ctx->object)
11671 		return len;
11672 	buf = (uint8_t *)ctx->object + arg->offset;
11673 	memcpy(buf, &tmp, size);
11674 	if (ctx->objmask)
11675 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11676 	return len;
11677 error:
11678 	push_args(ctx, arg);
11679 	return -1;
11680 }
11681 
11682 /**
11683  * Parse an IPv6 address.
11684  *
11685  * Last argument (ctx->args) is retrieved to determine storage size and
11686  * location.
11687  */
11688 static int
11689 parse_ipv6_addr(struct context *ctx, const struct token *token,
11690 		const char *str, unsigned int len,
11691 		void *buf, unsigned int size)
11692 {
11693 	const struct arg *arg = pop_args(ctx);
11694 	char str2[len + 1];
11695 	struct in6_addr tmp;
11696 	int ret;
11697 
11698 	(void)token;
11699 	/* Argument is expected. */
11700 	if (!arg)
11701 		return -1;
11702 	size = arg->size;
11703 	/* Bit-mask fill is not supported. */
11704 	if (arg->mask || size != sizeof(tmp))
11705 		goto error;
11706 	/* Only network endian is supported. */
11707 	if (!arg->hton)
11708 		goto error;
11709 	memcpy(str2, str, len);
11710 	str2[len] = '\0';
11711 	ret = inet_pton(AF_INET6, str2, &tmp);
11712 	if (ret != 1)
11713 		goto error;
11714 	if (!ctx->object)
11715 		return len;
11716 	buf = (uint8_t *)ctx->object + arg->offset;
11717 	memcpy(buf, &tmp, size);
11718 	if (ctx->objmask)
11719 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11720 	return len;
11721 error:
11722 	push_args(ctx, arg);
11723 	return -1;
11724 }
11725 
11726 /** Boolean values (even indices stand for false). */
11727 static const char *const boolean_name[] = {
11728 	"0", "1",
11729 	"false", "true",
11730 	"no", "yes",
11731 	"N", "Y",
11732 	"off", "on",
11733 	NULL,
11734 };
11735 
11736 /**
11737  * Parse a boolean value.
11738  *
11739  * Last argument (ctx->args) is retrieved to determine storage size and
11740  * location.
11741  */
11742 static int
11743 parse_boolean(struct context *ctx, const struct token *token,
11744 	      const char *str, unsigned int len,
11745 	      void *buf, unsigned int size)
11746 {
11747 	const struct arg *arg = pop_args(ctx);
11748 	unsigned int i;
11749 	int ret;
11750 
11751 	/* Argument is expected. */
11752 	if (!arg)
11753 		return -1;
11754 	for (i = 0; boolean_name[i]; ++i)
11755 		if (!strcmp_partial(boolean_name[i], str, len))
11756 			break;
11757 	/* Process token as integer. */
11758 	if (boolean_name[i])
11759 		str = i & 1 ? "1" : "0";
11760 	push_args(ctx, arg);
11761 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11762 	return ret > 0 ? (int)len : ret;
11763 }
11764 
11765 /** Parse port and update context. */
11766 static int
11767 parse_port(struct context *ctx, const struct token *token,
11768 	   const char *str, unsigned int len,
11769 	   void *buf, unsigned int size)
11770 {
11771 	struct buffer *out = &(struct buffer){ .port = 0 };
11772 	int ret;
11773 
11774 	if (buf)
11775 		out = buf;
11776 	else {
11777 		ctx->objdata = 0;
11778 		ctx->object = out;
11779 		ctx->objmask = NULL;
11780 		size = sizeof(*out);
11781 	}
11782 	ret = parse_int(ctx, token, str, len, out, size);
11783 	if (ret >= 0)
11784 		ctx->port = out->port;
11785 	if (!buf)
11786 		ctx->object = NULL;
11787 	return ret;
11788 }
11789 
11790 /** Parse tokens for shared indirect actions. */
11791 static int
11792 parse_ia_port(struct context *ctx, const struct token *token,
11793 	      const char *str, unsigned int len,
11794 	      void *buf, unsigned int size)
11795 {
11796 	struct rte_flow_action *action = ctx->object;
11797 	uint32_t id;
11798 	int ret;
11799 
11800 	(void)buf;
11801 	(void)size;
11802 	ctx->objdata = 0;
11803 	ctx->object = &id;
11804 	ctx->objmask = NULL;
11805 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11806 	ctx->object = action;
11807 	if (ret != (int)len)
11808 		return ret;
11809 	/* set indirect action */
11810 	if (action)
11811 		action->conf = (void *)(uintptr_t)id;
11812 	return ret;
11813 }
11814 
11815 static int
11816 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11817 		const char *str, unsigned int len,
11818 		void *buf, unsigned int size)
11819 {
11820 	struct rte_flow_action *action = ctx->object;
11821 	uint32_t id;
11822 	int ret;
11823 
11824 	(void)buf;
11825 	(void)size;
11826 	ctx->objdata = 0;
11827 	ctx->object = &id;
11828 	ctx->objmask = NULL;
11829 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11830 	ctx->object = action;
11831 	if (ret != (int)len)
11832 		return ret;
11833 	/* set indirect action */
11834 	if (action) {
11835 		portid_t port_id = ctx->port;
11836 		if (ctx->prev == INDIRECT_ACTION_PORT)
11837 			port_id = (portid_t)(uintptr_t)action->conf;
11838 		action->conf = port_action_handle_get_by_id(port_id, id);
11839 		ret = (action->conf) ? ret : -1;
11840 	}
11841 	return ret;
11842 }
11843 
11844 static int
11845 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11846 		    const char *str, unsigned int len,
11847 		    __rte_unused void *buf, __rte_unused unsigned int size)
11848 {
11849 	struct rte_flow_action *action = ctx->object;
11850 	struct rte_flow_action_indirect_list *action_conf;
11851 	const struct indlst_conf *indlst_conf;
11852 	uint32_t id;
11853 	int ret;
11854 
11855 	if (!action)
11856 		return -1;
11857 	ctx->objdata = 0;
11858 	ctx->object = &id;
11859 	ctx->objmask = NULL;
11860 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11861 	if (ret != (int)len)
11862 		return ret;
11863 	ctx->object = action;
11864 	action_conf = (void *)(uintptr_t)action->conf;
11865 	action_conf->conf = NULL;
11866 	switch (ctx->curr) {
11867 	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
11868 	action_conf->handle = (typeof(action_conf->handle))
11869 				port_action_handle_get_by_id(ctx->port, id);
11870 		if (!action_conf->handle) {
11871 			printf("no indirect list handle for id %u\n", id);
11872 			return -1;
11873 		}
11874 		break;
11875 	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
11876 		indlst_conf = indirect_action_list_conf_get(id);
11877 		if (!indlst_conf)
11878 			return -1;
11879 		action_conf->conf = (const void **)indlst_conf->conf;
11880 		break;
11881 	default:
11882 		break;
11883 	}
11884 	return ret;
11885 }
11886 
11887 static int
11888 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
11889 		const char *str, unsigned int len,
11890 		void *buf, unsigned int size)
11891 {
11892 	struct rte_flow_action *action = ctx->object;
11893 	struct rte_flow_action_meter_mark *meter;
11894 	struct rte_flow_meter_profile *profile = NULL;
11895 	uint32_t id = 0;
11896 	int ret;
11897 
11898 	(void)buf;
11899 	(void)size;
11900 	ctx->objdata = 0;
11901 	ctx->object = &id;
11902 	ctx->objmask = NULL;
11903 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11904 	ctx->object = action;
11905 	if (ret != (int)len)
11906 		return ret;
11907 	/* set meter profile */
11908 	if (action) {
11909 		meter = (struct rte_flow_action_meter_mark *)
11910 			(uintptr_t)(action->conf);
11911 		profile = port_meter_profile_get_by_id(ctx->port, id);
11912 		meter->profile = profile;
11913 		ret = (profile) ? ret : -1;
11914 	}
11915 	return ret;
11916 }
11917 
11918 static int
11919 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
11920 		const char *str, unsigned int len,
11921 		void *buf, unsigned int size)
11922 {
11923 	struct rte_flow_action *action = ctx->object;
11924 	struct rte_flow_action_meter_mark *meter;
11925 	struct rte_flow_meter_policy *policy = NULL;
11926 	uint32_t id = 0;
11927 	int ret;
11928 
11929 	(void)buf;
11930 	(void)size;
11931 	ctx->objdata = 0;
11932 	ctx->object = &id;
11933 	ctx->objmask = NULL;
11934 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11935 	ctx->object = action;
11936 	if (ret != (int)len)
11937 		return ret;
11938 	/* set meter policy */
11939 	if (action) {
11940 		meter = (struct rte_flow_action_meter_mark *)
11941 			(uintptr_t)(action->conf);
11942 		policy = port_meter_policy_get_by_id(ctx->port, id);
11943 		meter->policy = policy;
11944 		ret = (policy) ? ret : -1;
11945 	}
11946 	return ret;
11947 }
11948 
11949 /** Parse set command, initialize output buffer for subsequent tokens. */
11950 static int
11951 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
11952 			  const char *str, unsigned int len,
11953 			  void *buf, unsigned int size)
11954 {
11955 	struct buffer *out = buf;
11956 
11957 	/* Token name must match. */
11958 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11959 		return -1;
11960 	/* Nothing else to do if there is no buffer. */
11961 	if (!out)
11962 		return len;
11963 	/* Make sure buffer is large enough. */
11964 	if (size < sizeof(*out))
11965 		return -1;
11966 	ctx->objdata = 0;
11967 	ctx->objmask = NULL;
11968 	ctx->object = out;
11969 	if (!out->command)
11970 		return -1;
11971 	out->command = ctx->curr;
11972 	/* For encap/decap we need is pattern */
11973 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11974 						       sizeof(double));
11975 	return len;
11976 }
11977 
11978 /** Parse set command, initialize output buffer for subsequent tokens. */
11979 static int
11980 parse_set_sample_action(struct context *ctx, const struct token *token,
11981 			  const char *str, unsigned int len,
11982 			  void *buf, unsigned int size)
11983 {
11984 	struct buffer *out = buf;
11985 
11986 	/* Token name must match. */
11987 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11988 		return -1;
11989 	/* Nothing else to do if there is no buffer. */
11990 	if (!out)
11991 		return len;
11992 	/* Make sure buffer is large enough. */
11993 	if (size < sizeof(*out))
11994 		return -1;
11995 	ctx->objdata = 0;
11996 	ctx->objmask = NULL;
11997 	ctx->object = out;
11998 	if (!out->command)
11999 		return -1;
12000 	out->command = ctx->curr;
12001 	/* For sampler we need is actions */
12002 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12003 						       sizeof(double));
12004 	return len;
12005 }
12006 
12007 /** Parse set command, initialize output buffer for subsequent tokens. */
12008 static int
12009 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12010 			  const char *str, unsigned int len,
12011 			  void *buf, unsigned int size)
12012 {
12013 	struct buffer *out = buf;
12014 
12015 	/* Token name must match. */
12016 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12017 		return -1;
12018 	/* Nothing else to do if there is no buffer. */
12019 	if (!out)
12020 		return len;
12021 	/* Make sure buffer is large enough. */
12022 	if (size < sizeof(*out))
12023 		return -1;
12024 	ctx->objdata = 0;
12025 	ctx->objmask = NULL;
12026 	ctx->object = out;
12027 	if (!out->command)
12028 		return -1;
12029 	out->command = ctx->curr;
12030 	/* For ipv6_ext_push/remove we need is pattern */
12031 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12032 						       sizeof(double));
12033 	return len;
12034 }
12035 
12036 /**
12037  * Parse set raw_encap/raw_decap command,
12038  * initialize output buffer for subsequent tokens.
12039  */
12040 static int
12041 parse_set_init(struct context *ctx, const struct token *token,
12042 	       const char *str, unsigned int len,
12043 	       void *buf, unsigned int size)
12044 {
12045 	struct buffer *out = buf;
12046 
12047 	/* Token name must match. */
12048 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12049 		return -1;
12050 	/* Nothing else to do if there is no buffer. */
12051 	if (!out)
12052 		return len;
12053 	/* Make sure buffer is large enough. */
12054 	if (size < sizeof(*out))
12055 		return -1;
12056 	/* Initialize buffer. */
12057 	memset(out, 0x00, sizeof(*out));
12058 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12059 	ctx->objdata = 0;
12060 	ctx->object = out;
12061 	ctx->objmask = NULL;
12062 	if (!out->command) {
12063 		if (ctx->curr != SET)
12064 			return -1;
12065 		if (sizeof(*out) > size)
12066 			return -1;
12067 		out->command = ctx->curr;
12068 		out->args.vc.data = (uint8_t *)out + size;
12069 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12070 						       sizeof(double));
12071 	}
12072 	return len;
12073 }
12074 
12075 /*
12076  * Replace testpmd handles in a flex flow item with real values.
12077  */
12078 static int
12079 parse_flex_handle(struct context *ctx, const struct token *token,
12080 		  const char *str, unsigned int len,
12081 		  void *buf, unsigned int size)
12082 {
12083 	struct rte_flow_item_flex *spec, *mask;
12084 	const struct rte_flow_item_flex *src_spec, *src_mask;
12085 	const struct arg *arg = pop_args(ctx);
12086 	uint32_t offset;
12087 	uint16_t handle;
12088 	int ret;
12089 
12090 	if (!arg) {
12091 		printf("Bad environment\n");
12092 		return -1;
12093 	}
12094 	offset = arg->offset;
12095 	push_args(ctx, arg);
12096 	ret = parse_int(ctx, token, str, len, buf, size);
12097 	if (ret <= 0 || !ctx->object)
12098 		return ret;
12099 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12100 		printf("Bad port\n");
12101 		return -1;
12102 	}
12103 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12104 		const struct flex_item *fp;
12105 		spec = ctx->object;
12106 		handle = (uint16_t)(uintptr_t)spec->handle;
12107 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12108 			printf("Bad flex item handle\n");
12109 			return -1;
12110 		}
12111 		fp = flex_items[ctx->port][handle];
12112 		if (!fp) {
12113 			printf("Bad flex item handle\n");
12114 			return -1;
12115 		}
12116 		spec->handle = fp->flex_handle;
12117 		mask = spec + 2; /* spec, last, mask */
12118 		mask->handle = fp->flex_handle;
12119 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12120 		handle = (uint16_t)(uintptr_t)
12121 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12122 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12123 			printf("Bad pattern handle\n");
12124 			return -1;
12125 		}
12126 		src_spec = &flex_patterns[handle].spec;
12127 		src_mask = &flex_patterns[handle].mask;
12128 		spec = ctx->object;
12129 		mask = spec + 2; /* spec, last, mask */
12130 		/* fill flow rule spec and mask parameters */
12131 		spec->length = src_spec->length;
12132 		spec->pattern = src_spec->pattern;
12133 		mask->length = src_mask->length;
12134 		mask->pattern = src_mask->pattern;
12135 	} else {
12136 		printf("Bad arguments - unknown flex item offset\n");
12137 		return -1;
12138 	}
12139 	return ret;
12140 }
12141 
12142 /** Parse Meter color name */
12143 static int
12144 parse_meter_color(struct context *ctx, const struct token *token,
12145 		  const char *str, unsigned int len, void *buf,
12146 		  unsigned int size)
12147 {
12148 	struct rte_flow_item_meter_color *meter_color;
12149 	unsigned int i;
12150 
12151 	(void)token;
12152 	(void)buf;
12153 	(void)size;
12154 	for (i = 0; meter_colors[i]; ++i)
12155 		if (!strcmp_partial(meter_colors[i], str, len))
12156 			break;
12157 	if (!meter_colors[i])
12158 		return -1;
12159 	if (!ctx->object)
12160 		return len;
12161 	meter_color = ctx->object;
12162 	meter_color->color = (enum rte_color)i;
12163 	return len;
12164 }
12165 
12166 /** Parse Insertion Table Type name */
12167 static int
12168 parse_insertion_table_type(struct context *ctx, const struct token *token,
12169 			   const char *str, unsigned int len, void *buf,
12170 			   unsigned int size)
12171 {
12172 	const struct arg *arg = pop_args(ctx);
12173 	unsigned int i;
12174 	char tmp[2];
12175 	int ret;
12176 
12177 	(void)size;
12178 	/* Argument is expected. */
12179 	if (!arg)
12180 		return -1;
12181 	for (i = 0; table_insertion_types[i]; ++i)
12182 		if (!strcmp_partial(table_insertion_types[i], str, len))
12183 			break;
12184 	if (!table_insertion_types[i])
12185 		return -1;
12186 	push_args(ctx, arg);
12187 	snprintf(tmp, sizeof(tmp), "%u", i);
12188 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12189 	return ret > 0 ? (int)len : ret;
12190 }
12191 
12192 /** Parse Hash Calculation Table Type name */
12193 static int
12194 parse_hash_table_type(struct context *ctx, const struct token *token,
12195 		      const char *str, unsigned int len, void *buf,
12196 		      unsigned int size)
12197 {
12198 	const struct arg *arg = pop_args(ctx);
12199 	unsigned int i;
12200 	char tmp[2];
12201 	int ret;
12202 
12203 	(void)size;
12204 	/* Argument is expected. */
12205 	if (!arg)
12206 		return -1;
12207 	for (i = 0; table_hash_funcs[i]; ++i)
12208 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12209 			break;
12210 	if (!table_hash_funcs[i])
12211 		return -1;
12212 	push_args(ctx, arg);
12213 	snprintf(tmp, sizeof(tmp), "%u", i);
12214 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12215 	return ret > 0 ? (int)len : ret;
12216 }
12217 
12218 static int
12219 parse_name_to_index(struct context *ctx, const struct token *token,
12220 		    const char *str, unsigned int len, void *buf,
12221 		    unsigned int size,
12222 		    const char *const names[], size_t names_size, uint32_t *dst)
12223 {
12224 	int ret;
12225 	uint32_t i;
12226 
12227 	RTE_SET_USED(token);
12228 	RTE_SET_USED(buf);
12229 	RTE_SET_USED(size);
12230 	if (!ctx->object)
12231 		return len;
12232 	for (i = 0; i < names_size; i++) {
12233 		if (!names[i])
12234 			continue;
12235 		ret = strcmp_partial(names[i], str,
12236 				     RTE_MIN(len, strlen(names[i])));
12237 		if (!ret) {
12238 			*dst = i;
12239 			return len;
12240 		}
12241 	}
12242 	return -1;
12243 }
12244 
12245 static const char *const quota_mode_names[] = {
12246 	NULL,
12247 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12248 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12249 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12250 };
12251 
12252 static const char *const quota_state_names[] = {
12253 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12254 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12255 };
12256 
12257 static const char *const quota_update_names[] = {
12258 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12259 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12260 };
12261 
12262 static const char *const query_update_mode_names[] = {
12263 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12264 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12265 };
12266 
12267 static int
12268 parse_quota_state_name(struct context *ctx, const struct token *token,
12269 		       const char *str, unsigned int len, void *buf,
12270 		       unsigned int size)
12271 {
12272 	struct rte_flow_item_quota *quota = ctx->object;
12273 
12274 	return parse_name_to_index(ctx, token, str, len, buf, size,
12275 				   quota_state_names,
12276 				   RTE_DIM(quota_state_names),
12277 				   (uint32_t *)&quota->state);
12278 }
12279 
12280 static int
12281 parse_quota_mode_name(struct context *ctx, const struct token *token,
12282 		      const char *str, unsigned int len, void *buf,
12283 		      unsigned int size)
12284 {
12285 	struct rte_flow_action_quota *quota = ctx->object;
12286 
12287 	return parse_name_to_index(ctx, token, str, len, buf, size,
12288 				   quota_mode_names,
12289 				   RTE_DIM(quota_mode_names),
12290 				   (uint32_t *)&quota->mode);
12291 }
12292 
12293 static int
12294 parse_quota_update_name(struct context *ctx, const struct token *token,
12295 			const char *str, unsigned int len, void *buf,
12296 			unsigned int size)
12297 {
12298 	struct rte_flow_update_quota *update = ctx->object;
12299 
12300 	return parse_name_to_index(ctx, token, str, len, buf, size,
12301 				   quota_update_names,
12302 				   RTE_DIM(quota_update_names),
12303 				   (uint32_t *)&update->op);
12304 }
12305 
12306 static int
12307 parse_qu_mode_name(struct context *ctx, const struct token *token,
12308 		   const char *str, unsigned int len, void *buf,
12309 		   unsigned int size)
12310 {
12311 	struct buffer *out = ctx->object;
12312 
12313 	return parse_name_to_index(ctx, token, str, len, buf, size,
12314 				   query_update_mode_names,
12315 				   RTE_DIM(query_update_mode_names),
12316 				   (uint32_t *)&out->args.ia.qu_mode);
12317 }
12318 
12319 /** No completion. */
12320 static int
12321 comp_none(struct context *ctx, const struct token *token,
12322 	  unsigned int ent, char *buf, unsigned int size)
12323 {
12324 	(void)ctx;
12325 	(void)token;
12326 	(void)ent;
12327 	(void)buf;
12328 	(void)size;
12329 	return 0;
12330 }
12331 
12332 /** Complete boolean values. */
12333 static int
12334 comp_boolean(struct context *ctx, const struct token *token,
12335 	     unsigned int ent, char *buf, unsigned int size)
12336 {
12337 	unsigned int i;
12338 
12339 	(void)ctx;
12340 	(void)token;
12341 	for (i = 0; boolean_name[i]; ++i)
12342 		if (buf && i == ent)
12343 			return strlcpy(buf, boolean_name[i], size);
12344 	if (buf)
12345 		return -1;
12346 	return i;
12347 }
12348 
12349 /** Complete action names. */
12350 static int
12351 comp_action(struct context *ctx, const struct token *token,
12352 	    unsigned int ent, char *buf, unsigned int size)
12353 {
12354 	unsigned int i;
12355 
12356 	(void)ctx;
12357 	(void)token;
12358 	for (i = 0; next_action[i]; ++i)
12359 		if (buf && i == ent)
12360 			return strlcpy(buf, token_list[next_action[i]].name,
12361 				       size);
12362 	if (buf)
12363 		return -1;
12364 	return i;
12365 }
12366 
12367 /** Complete available ports. */
12368 static int
12369 comp_port(struct context *ctx, const struct token *token,
12370 	  unsigned int ent, char *buf, unsigned int size)
12371 {
12372 	unsigned int i = 0;
12373 	portid_t p;
12374 
12375 	(void)ctx;
12376 	(void)token;
12377 	RTE_ETH_FOREACH_DEV(p) {
12378 		if (buf && i == ent)
12379 			return snprintf(buf, size, "%u", p);
12380 		++i;
12381 	}
12382 	if (buf)
12383 		return -1;
12384 	return i;
12385 }
12386 
12387 /** Complete available rule IDs. */
12388 static int
12389 comp_rule_id(struct context *ctx, const struct token *token,
12390 	     unsigned int ent, char *buf, unsigned int size)
12391 {
12392 	unsigned int i = 0;
12393 	struct rte_port *port;
12394 	struct port_flow *pf;
12395 
12396 	(void)token;
12397 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12398 	    ctx->port == (portid_t)RTE_PORT_ALL)
12399 		return -1;
12400 	port = &ports[ctx->port];
12401 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12402 		if (buf && i == ent)
12403 			return snprintf(buf, size, "%"PRIu64, pf->id);
12404 		++i;
12405 	}
12406 	if (buf)
12407 		return -1;
12408 	return i;
12409 }
12410 
12411 /** Complete operation for compare match item. */
12412 static int
12413 comp_set_compare_op(struct context *ctx, const struct token *token,
12414 		    unsigned int ent, char *buf, unsigned int size)
12415 {
12416 	RTE_SET_USED(ctx);
12417 	RTE_SET_USED(token);
12418 	if (!buf)
12419 		return RTE_DIM(compare_ops);
12420 	if (ent < RTE_DIM(compare_ops) - 1)
12421 		return strlcpy(buf, compare_ops[ent], size);
12422 	return -1;
12423 }
12424 
12425 /** Complete field id for compare match item. */
12426 static int
12427 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12428 			  unsigned int ent, char *buf, unsigned int size)
12429 {
12430 	const char *name;
12431 
12432 	RTE_SET_USED(token);
12433 	if (!buf)
12434 		return RTE_DIM(flow_field_ids);
12435 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12436 		return -1;
12437 	name = flow_field_ids[ent];
12438 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12439 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12440 		return strlcpy(buf, name, size);
12441 	return -1;
12442 }
12443 
12444 /** Complete type field for RSS action. */
12445 static int
12446 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12447 			unsigned int ent, char *buf, unsigned int size)
12448 {
12449 	unsigned int i;
12450 
12451 	(void)ctx;
12452 	(void)token;
12453 	for (i = 0; rss_type_table[i].str; ++i)
12454 		;
12455 	if (!buf)
12456 		return i + 1;
12457 	if (ent < i)
12458 		return strlcpy(buf, rss_type_table[ent].str, size);
12459 	if (ent == i)
12460 		return snprintf(buf, size, "end");
12461 	return -1;
12462 }
12463 
12464 /** Complete queue field for RSS action. */
12465 static int
12466 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12467 			 unsigned int ent, char *buf, unsigned int size)
12468 {
12469 	(void)ctx;
12470 	(void)token;
12471 	if (!buf)
12472 		return nb_rxq + 1;
12473 	if (ent < nb_rxq)
12474 		return snprintf(buf, size, "%u", ent);
12475 	if (ent == nb_rxq)
12476 		return snprintf(buf, size, "end");
12477 	return -1;
12478 }
12479 
12480 /** Complete index number for set raw_encap/raw_decap commands. */
12481 static int
12482 comp_set_raw_index(struct context *ctx, const struct token *token,
12483 		   unsigned int ent, char *buf, unsigned int size)
12484 {
12485 	uint16_t idx = 0;
12486 	uint16_t nb = 0;
12487 
12488 	RTE_SET_USED(ctx);
12489 	RTE_SET_USED(token);
12490 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12491 		if (buf && idx == ent)
12492 			return snprintf(buf, size, "%u", idx);
12493 		++nb;
12494 	}
12495 	return nb;
12496 }
12497 
12498 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12499 static int
12500 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12501 			unsigned int ent, char *buf, unsigned int size)
12502 {
12503 	uint16_t idx = 0;
12504 	uint16_t nb = 0;
12505 
12506 	RTE_SET_USED(ctx);
12507 	RTE_SET_USED(token);
12508 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12509 		if (buf && idx == ent)
12510 			return snprintf(buf, size, "%u", idx);
12511 		++nb;
12512 	}
12513 	return nb;
12514 }
12515 
12516 /** Complete index number for set raw_encap/raw_decap commands. */
12517 static int
12518 comp_set_sample_index(struct context *ctx, const struct token *token,
12519 		   unsigned int ent, char *buf, unsigned int size)
12520 {
12521 	uint16_t idx = 0;
12522 	uint16_t nb = 0;
12523 
12524 	RTE_SET_USED(ctx);
12525 	RTE_SET_USED(token);
12526 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12527 		if (buf && idx == ent)
12528 			return snprintf(buf, size, "%u", idx);
12529 		++nb;
12530 	}
12531 	return nb;
12532 }
12533 
12534 /** Complete operation for modify_field command. */
12535 static int
12536 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12537 		   unsigned int ent, char *buf, unsigned int size)
12538 {
12539 	RTE_SET_USED(ctx);
12540 	RTE_SET_USED(token);
12541 	if (!buf)
12542 		return RTE_DIM(modify_field_ops);
12543 	if (ent < RTE_DIM(modify_field_ops) - 1)
12544 		return strlcpy(buf, modify_field_ops[ent], size);
12545 	return -1;
12546 }
12547 
12548 /** Complete field id for modify_field command. */
12549 static int
12550 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12551 		   unsigned int ent, char *buf, unsigned int size)
12552 {
12553 	const char *name;
12554 
12555 	RTE_SET_USED(token);
12556 	if (!buf)
12557 		return RTE_DIM(flow_field_ids);
12558 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12559 		return -1;
12560 	name = flow_field_ids[ent];
12561 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12562 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12563 		return strlcpy(buf, name, size);
12564 	return -1;
12565 }
12566 
12567 /** Complete available pattern template IDs. */
12568 static int
12569 comp_pattern_template_id(struct context *ctx, const struct token *token,
12570 			 unsigned int ent, char *buf, unsigned int size)
12571 {
12572 	unsigned int i = 0;
12573 	struct rte_port *port;
12574 	struct port_template *pt;
12575 
12576 	(void)token;
12577 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12578 	    ctx->port == (portid_t)RTE_PORT_ALL)
12579 		return -1;
12580 	port = &ports[ctx->port];
12581 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12582 		if (buf && i == ent)
12583 			return snprintf(buf, size, "%u", pt->id);
12584 		++i;
12585 	}
12586 	if (buf)
12587 		return -1;
12588 	return i;
12589 }
12590 
12591 /** Complete available actions template IDs. */
12592 static int
12593 comp_actions_template_id(struct context *ctx, const struct token *token,
12594 			 unsigned int ent, char *buf, unsigned int size)
12595 {
12596 	unsigned int i = 0;
12597 	struct rte_port *port;
12598 	struct port_template *pt;
12599 
12600 	(void)token;
12601 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12602 	    ctx->port == (portid_t)RTE_PORT_ALL)
12603 		return -1;
12604 	port = &ports[ctx->port];
12605 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12606 		if (buf && i == ent)
12607 			return snprintf(buf, size, "%u", pt->id);
12608 		++i;
12609 	}
12610 	if (buf)
12611 		return -1;
12612 	return i;
12613 }
12614 
12615 /** Complete available table IDs. */
12616 static int
12617 comp_table_id(struct context *ctx, const struct token *token,
12618 	      unsigned int ent, char *buf, unsigned int size)
12619 {
12620 	unsigned int i = 0;
12621 	struct rte_port *port;
12622 	struct port_table *pt;
12623 
12624 	(void)token;
12625 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12626 	    ctx->port == (portid_t)RTE_PORT_ALL)
12627 		return -1;
12628 	port = &ports[ctx->port];
12629 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12630 		if (buf && i == ent)
12631 			return snprintf(buf, size, "%u", pt->id);
12632 		++i;
12633 	}
12634 	if (buf)
12635 		return -1;
12636 	return i;
12637 }
12638 
12639 /** Complete available queue IDs. */
12640 static int
12641 comp_queue_id(struct context *ctx, const struct token *token,
12642 	      unsigned int ent, char *buf, unsigned int size)
12643 {
12644 	unsigned int i = 0;
12645 	struct rte_port *port;
12646 
12647 	(void)token;
12648 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12649 	    ctx->port == (portid_t)RTE_PORT_ALL)
12650 		return -1;
12651 	port = &ports[ctx->port];
12652 	for (i = 0; i < port->queue_nb; i++) {
12653 		if (buf && i == ent)
12654 			return snprintf(buf, size, "%u", i);
12655 	}
12656 	if (buf)
12657 		return -1;
12658 	return i;
12659 }
12660 
12661 static int
12662 comp_names_to_index(struct context *ctx, const struct token *token,
12663 		    unsigned int ent, char *buf, unsigned int size,
12664 		    const char *const names[], size_t names_size)
12665 {
12666 	RTE_SET_USED(ctx);
12667 	RTE_SET_USED(token);
12668 	if (!buf)
12669 		return names_size;
12670 	if (names[ent] && ent < names_size)
12671 		return rte_strscpy(buf, names[ent], size);
12672 	return -1;
12673 
12674 }
12675 
12676 /** Complete available Meter colors. */
12677 static int
12678 comp_meter_color(struct context *ctx, const struct token *token,
12679 		 unsigned int ent, char *buf, unsigned int size)
12680 {
12681 	RTE_SET_USED(ctx);
12682 	RTE_SET_USED(token);
12683 	if (!buf)
12684 		return RTE_DIM(meter_colors);
12685 	if (ent < RTE_DIM(meter_colors) - 1)
12686 		return strlcpy(buf, meter_colors[ent], size);
12687 	return -1;
12688 }
12689 
12690 /** Complete available Insertion Table types. */
12691 static int
12692 comp_insertion_table_type(struct context *ctx, const struct token *token,
12693 			  unsigned int ent, char *buf, unsigned int size)
12694 {
12695 	RTE_SET_USED(ctx);
12696 	RTE_SET_USED(token);
12697 	if (!buf)
12698 		return RTE_DIM(table_insertion_types);
12699 	if (ent < RTE_DIM(table_insertion_types) - 1)
12700 		return rte_strscpy(buf, table_insertion_types[ent], size);
12701 	return -1;
12702 }
12703 
12704 /** Complete available Hash Calculation Table types. */
12705 static int
12706 comp_hash_table_type(struct context *ctx, const struct token *token,
12707 		     unsigned int ent, char *buf, unsigned int size)
12708 {
12709 	RTE_SET_USED(ctx);
12710 	RTE_SET_USED(token);
12711 	if (!buf)
12712 		return RTE_DIM(table_hash_funcs);
12713 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12714 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12715 	return -1;
12716 }
12717 
12718 static int
12719 comp_quota_state_name(struct context *ctx, const struct token *token,
12720 		      unsigned int ent, char *buf, unsigned int size)
12721 {
12722 	return comp_names_to_index(ctx, token, ent, buf, size,
12723 				   quota_state_names,
12724 				   RTE_DIM(quota_state_names));
12725 }
12726 
12727 static int
12728 comp_quota_mode_name(struct context *ctx, const struct token *token,
12729 		     unsigned int ent, char *buf, unsigned int size)
12730 {
12731 	return comp_names_to_index(ctx, token, ent, buf, size,
12732 				   quota_mode_names,
12733 				   RTE_DIM(quota_mode_names));
12734 }
12735 
12736 static int
12737 comp_quota_update_name(struct context *ctx, const struct token *token,
12738 		       unsigned int ent, char *buf, unsigned int size)
12739 {
12740 	return comp_names_to_index(ctx, token, ent, buf, size,
12741 				   quota_update_names,
12742 				   RTE_DIM(quota_update_names));
12743 }
12744 
12745 static int
12746 comp_qu_mode_name(struct context *ctx, const struct token *token,
12747 		  unsigned int ent, char *buf, unsigned int size)
12748 {
12749 	return comp_names_to_index(ctx, token, ent, buf, size,
12750 				   query_update_mode_names,
12751 				   RTE_DIM(query_update_mode_names));
12752 }
12753 
12754 /** Internal context. */
12755 static struct context cmd_flow_context;
12756 
12757 /** Global parser instance (cmdline API). */
12758 cmdline_parse_inst_t cmd_flow;
12759 cmdline_parse_inst_t cmd_set_raw;
12760 
12761 /** Initialize context. */
12762 static void
12763 cmd_flow_context_init(struct context *ctx)
12764 {
12765 	/* A full memset() is not necessary. */
12766 	ctx->curr = ZERO;
12767 	ctx->prev = ZERO;
12768 	ctx->next_num = 0;
12769 	ctx->args_num = 0;
12770 	ctx->eol = 0;
12771 	ctx->last = 0;
12772 	ctx->port = 0;
12773 	ctx->objdata = 0;
12774 	ctx->object = NULL;
12775 	ctx->objmask = NULL;
12776 }
12777 
12778 /** Parse a token (cmdline API). */
12779 static int
12780 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12781 	       unsigned int size)
12782 {
12783 	struct context *ctx = &cmd_flow_context;
12784 	const struct token *token;
12785 	const enum index *list;
12786 	int len;
12787 	int i;
12788 
12789 	(void)hdr;
12790 	token = &token_list[ctx->curr];
12791 	/* Check argument length. */
12792 	ctx->eol = 0;
12793 	ctx->last = 1;
12794 	for (len = 0; src[len]; ++len)
12795 		if (src[len] == '#' || isspace(src[len]))
12796 			break;
12797 	if (!len)
12798 		return -1;
12799 	/* Last argument and EOL detection. */
12800 	for (i = len; src[i]; ++i)
12801 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12802 			break;
12803 		else if (!isspace(src[i])) {
12804 			ctx->last = 0;
12805 			break;
12806 		}
12807 	for (; src[i]; ++i)
12808 		if (src[i] == '\r' || src[i] == '\n') {
12809 			ctx->eol = 1;
12810 			break;
12811 		}
12812 	/* Initialize context if necessary. */
12813 	if (!ctx->next_num) {
12814 		if (!token->next)
12815 			return 0;
12816 		ctx->next[ctx->next_num++] = token->next[0];
12817 	}
12818 	/* Process argument through candidates. */
12819 	ctx->prev = ctx->curr;
12820 	list = ctx->next[ctx->next_num - 1];
12821 	for (i = 0; list[i]; ++i) {
12822 		const struct token *next = &token_list[list[i]];
12823 		int tmp;
12824 
12825 		ctx->curr = list[i];
12826 		if (next->call)
12827 			tmp = next->call(ctx, next, src, len, result, size);
12828 		else
12829 			tmp = parse_default(ctx, next, src, len, result, size);
12830 		if (tmp == -1 || tmp != len)
12831 			continue;
12832 		token = next;
12833 		break;
12834 	}
12835 	if (!list[i])
12836 		return -1;
12837 	--ctx->next_num;
12838 	/* Push subsequent tokens if any. */
12839 	if (token->next)
12840 		for (i = 0; token->next[i]; ++i) {
12841 			if (ctx->next_num == RTE_DIM(ctx->next))
12842 				return -1;
12843 			ctx->next[ctx->next_num++] = token->next[i];
12844 		}
12845 	/* Push arguments if any. */
12846 	if (token->args)
12847 		for (i = 0; token->args[i]; ++i) {
12848 			if (ctx->args_num == RTE_DIM(ctx->args))
12849 				return -1;
12850 			ctx->args[ctx->args_num++] = token->args[i];
12851 		}
12852 	return len;
12853 }
12854 
12855 int
12856 flow_parse(const char *src, void *result, unsigned int size,
12857 	   struct rte_flow_attr **attr,
12858 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12859 {
12860 	int ret;
12861 	struct context saved_flow_ctx = cmd_flow_context;
12862 
12863 	cmd_flow_context_init(&cmd_flow_context);
12864 	do {
12865 		ret = cmd_flow_parse(NULL, src, result, size);
12866 		if (ret > 0) {
12867 			src += ret;
12868 			while (isspace(*src))
12869 				src++;
12870 		}
12871 	} while (ret > 0 && strlen(src));
12872 	cmd_flow_context = saved_flow_ctx;
12873 	*attr = &((struct buffer *)result)->args.vc.attr;
12874 	*pattern = ((struct buffer *)result)->args.vc.pattern;
12875 	*actions = ((struct buffer *)result)->args.vc.actions;
12876 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
12877 }
12878 
12879 /** Return number of completion entries (cmdline API). */
12880 static int
12881 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
12882 {
12883 	struct context *ctx = &cmd_flow_context;
12884 	const struct token *token = &token_list[ctx->curr];
12885 	const enum index *list;
12886 	int i;
12887 
12888 	(void)hdr;
12889 	/* Count number of tokens in current list. */
12890 	if (ctx->next_num)
12891 		list = ctx->next[ctx->next_num - 1];
12892 	else
12893 		list = token->next[0];
12894 	for (i = 0; list[i]; ++i)
12895 		;
12896 	if (!i)
12897 		return 0;
12898 	/*
12899 	 * If there is a single token, use its completion callback, otherwise
12900 	 * return the number of entries.
12901 	 */
12902 	token = &token_list[list[0]];
12903 	if (i == 1 && token->comp) {
12904 		/* Save index for cmd_flow_get_help(). */
12905 		ctx->prev = list[0];
12906 		return token->comp(ctx, token, 0, NULL, 0);
12907 	}
12908 	return i;
12909 }
12910 
12911 /** Return a completion entry (cmdline API). */
12912 static int
12913 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
12914 			  char *dst, unsigned int size)
12915 {
12916 	struct context *ctx = &cmd_flow_context;
12917 	const struct token *token = &token_list[ctx->curr];
12918 	const enum index *list;
12919 	int i;
12920 
12921 	(void)hdr;
12922 	/* Count number of tokens in current list. */
12923 	if (ctx->next_num)
12924 		list = ctx->next[ctx->next_num - 1];
12925 	else
12926 		list = token->next[0];
12927 	for (i = 0; list[i]; ++i)
12928 		;
12929 	if (!i)
12930 		return -1;
12931 	/* If there is a single token, use its completion callback. */
12932 	token = &token_list[list[0]];
12933 	if (i == 1 && token->comp) {
12934 		/* Save index for cmd_flow_get_help(). */
12935 		ctx->prev = list[0];
12936 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
12937 	}
12938 	/* Otherwise make sure the index is valid and use defaults. */
12939 	if (index >= i)
12940 		return -1;
12941 	token = &token_list[list[index]];
12942 	strlcpy(dst, token->name, size);
12943 	/* Save index for cmd_flow_get_help(). */
12944 	ctx->prev = list[index];
12945 	return 0;
12946 }
12947 
12948 /** Populate help strings for current token (cmdline API). */
12949 static int
12950 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
12951 {
12952 	struct context *ctx = &cmd_flow_context;
12953 	const struct token *token = &token_list[ctx->prev];
12954 
12955 	(void)hdr;
12956 	if (!size)
12957 		return -1;
12958 	/* Set token type and update global help with details. */
12959 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
12960 	if (token->help)
12961 		cmd_flow.help_str = token->help;
12962 	else
12963 		cmd_flow.help_str = token->name;
12964 	return 0;
12965 }
12966 
12967 /** Token definition template (cmdline API). */
12968 static struct cmdline_token_hdr cmd_flow_token_hdr = {
12969 	.ops = &(struct cmdline_token_ops){
12970 		.parse = cmd_flow_parse,
12971 		.complete_get_nb = cmd_flow_complete_get_nb,
12972 		.complete_get_elt = cmd_flow_complete_get_elt,
12973 		.get_help = cmd_flow_get_help,
12974 	},
12975 	.offset = 0,
12976 };
12977 
12978 /** Populate the next dynamic token. */
12979 static void
12980 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
12981 	     cmdline_parse_token_hdr_t **hdr_inst)
12982 {
12983 	struct context *ctx = &cmd_flow_context;
12984 
12985 	/* Always reinitialize context before requesting the first token. */
12986 	if (!(hdr_inst - cmd_flow.tokens))
12987 		cmd_flow_context_init(ctx);
12988 	/* Return NULL when no more tokens are expected. */
12989 	if (!ctx->next_num && ctx->curr) {
12990 		*hdr = NULL;
12991 		return;
12992 	}
12993 	/* Determine if command should end here. */
12994 	if (ctx->eol && ctx->last && ctx->next_num) {
12995 		const enum index *list = ctx->next[ctx->next_num - 1];
12996 		int i;
12997 
12998 		for (i = 0; list[i]; ++i) {
12999 			if (list[i] != END)
13000 				continue;
13001 			*hdr = NULL;
13002 			return;
13003 		}
13004 	}
13005 	*hdr = &cmd_flow_token_hdr;
13006 }
13007 
13008 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13009 	SLIST_HEAD_INITIALIZER();
13010 
13011 static void
13012 indirect_action_flow_conf_create(const struct buffer *in)
13013 {
13014 	int len, ret;
13015 	uint32_t i;
13016 	struct indlst_conf *indlst_conf = NULL;
13017 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13018 	struct rte_flow_action *src = in->args.vc.actions;
13019 
13020 	if (!in->args.vc.actions_n)
13021 		goto end;
13022 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13023 	if (len <= 0)
13024 		goto end;
13025 	len = RTE_ALIGN(len, 16);
13026 
13027 	indlst_conf = calloc(1, base + len +
13028 			     in->args.vc.actions_n * sizeof(uintptr_t));
13029 	if (!indlst_conf)
13030 		goto end;
13031 	indlst_conf->id = in->args.vc.attr.group;
13032 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13033 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13034 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13035 			    len, src, NULL);
13036 	if (ret <= 0) {
13037 		free(indlst_conf);
13038 		indlst_conf = NULL;
13039 		goto end;
13040 	}
13041 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13042 	for (i = 0; i < indlst_conf->conf_num; i++)
13043 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13044 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13045 end:
13046 	if (indlst_conf)
13047 		printf("created indirect action list configuration %u\n",
13048 		       in->args.vc.attr.group);
13049 	else
13050 		printf("cannot create indirect action list configuration %u\n",
13051 		       in->args.vc.attr.group);
13052 }
13053 
13054 static const struct indlst_conf *
13055 indirect_action_list_conf_get(uint32_t conf_id)
13056 {
13057 	const struct indlst_conf *conf;
13058 
13059 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13060 		if (conf->id == conf_id)
13061 			return conf;
13062 	}
13063 	return NULL;
13064 }
13065 
13066 /** Dispatch parsed buffer to function calls. */
13067 static void
13068 cmd_flow_parsed(const struct buffer *in)
13069 {
13070 	switch (in->command) {
13071 	case INFO:
13072 		port_flow_get_info(in->port);
13073 		break;
13074 	case CONFIGURE:
13075 		port_flow_configure(in->port,
13076 				    &in->args.configure.port_attr,
13077 				    in->args.configure.nb_queue,
13078 				    &in->args.configure.queue_attr);
13079 		break;
13080 	case PATTERN_TEMPLATE_CREATE:
13081 		port_flow_pattern_template_create(in->port,
13082 				in->args.vc.pat_templ_id,
13083 				&((const struct rte_flow_pattern_template_attr) {
13084 					.relaxed_matching = in->args.vc.attr.reserved,
13085 					.ingress = in->args.vc.attr.ingress,
13086 					.egress = in->args.vc.attr.egress,
13087 					.transfer = in->args.vc.attr.transfer,
13088 				}),
13089 				in->args.vc.pattern);
13090 		break;
13091 	case PATTERN_TEMPLATE_DESTROY:
13092 		port_flow_pattern_template_destroy(in->port,
13093 				in->args.templ_destroy.template_id_n,
13094 				in->args.templ_destroy.template_id);
13095 		break;
13096 	case ACTIONS_TEMPLATE_CREATE:
13097 		port_flow_actions_template_create(in->port,
13098 				in->args.vc.act_templ_id,
13099 				&((const struct rte_flow_actions_template_attr) {
13100 					.ingress = in->args.vc.attr.ingress,
13101 					.egress = in->args.vc.attr.egress,
13102 					.transfer = in->args.vc.attr.transfer,
13103 				}),
13104 				in->args.vc.actions,
13105 				in->args.vc.masks);
13106 		break;
13107 	case ACTIONS_TEMPLATE_DESTROY:
13108 		port_flow_actions_template_destroy(in->port,
13109 				in->args.templ_destroy.template_id_n,
13110 				in->args.templ_destroy.template_id);
13111 		break;
13112 	case TABLE_CREATE:
13113 		port_flow_template_table_create(in->port, in->args.table.id,
13114 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13115 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13116 			in->args.table.act_templ_id);
13117 		break;
13118 	case TABLE_DESTROY:
13119 		port_flow_template_table_destroy(in->port,
13120 					in->args.table_destroy.table_id_n,
13121 					in->args.table_destroy.table_id);
13122 		break;
13123 	case TABLE_RESIZE_COMPLETE:
13124 		port_flow_template_table_resize_complete
13125 			(in->port, in->args.table_destroy.table_id[0]);
13126 		break;
13127 	case GROUP_SET_MISS_ACTIONS:
13128 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13129 						  in->args.vc.actions);
13130 		break;
13131 	case TABLE_RESIZE:
13132 		port_flow_template_table_resize(in->port, in->args.table.id,
13133 						in->args.table.attr.nb_flows);
13134 		break;
13135 	case QUEUE_CREATE:
13136 		port_queue_flow_create(in->port, in->queue, in->postpone,
13137 			in->args.vc.table_id, in->args.vc.rule_id,
13138 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13139 			in->args.vc.pattern, in->args.vc.actions);
13140 		break;
13141 	case QUEUE_DESTROY:
13142 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13143 					in->args.destroy.rule_n,
13144 					in->args.destroy.rule);
13145 		break;
13146 	case QUEUE_FLOW_UPDATE_RESIZED:
13147 		port_queue_flow_update_resized(in->port, in->queue,
13148 					       in->postpone,
13149 					       in->args.destroy.rule[0]);
13150 		break;
13151 	case QUEUE_UPDATE:
13152 		port_queue_flow_update(in->port, in->queue, in->postpone,
13153 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13154 				in->args.vc.actions);
13155 		break;
13156 	case PUSH:
13157 		port_queue_flow_push(in->port, in->queue);
13158 		break;
13159 	case PULL:
13160 		port_queue_flow_pull(in->port, in->queue);
13161 		break;
13162 	case HASH:
13163 		if (!in->args.vc.encap_hash)
13164 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13165 					    in->args.vc.pat_templ_id,
13166 					    in->args.vc.pattern);
13167 		else
13168 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13169 						  in->args.vc.pattern);
13170 		break;
13171 	case QUEUE_AGED:
13172 		port_queue_flow_aged(in->port, in->queue,
13173 				     in->args.aged.destroy);
13174 		break;
13175 	case QUEUE_INDIRECT_ACTION_CREATE:
13176 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13177 		port_queue_action_handle_create(
13178 				in->port, in->queue, in->postpone,
13179 				in->args.vc.attr.group,
13180 				&((const struct rte_flow_indir_action_conf) {
13181 					.ingress = in->args.vc.attr.ingress,
13182 					.egress = in->args.vc.attr.egress,
13183 					.transfer = in->args.vc.attr.transfer,
13184 				}),
13185 				in->args.vc.actions);
13186 		break;
13187 	case QUEUE_INDIRECT_ACTION_DESTROY:
13188 		port_queue_action_handle_destroy(in->port,
13189 					   in->queue, in->postpone,
13190 					   in->args.ia_destroy.action_id_n,
13191 					   in->args.ia_destroy.action_id);
13192 		break;
13193 	case QUEUE_INDIRECT_ACTION_UPDATE:
13194 		port_queue_action_handle_update(in->port,
13195 						in->queue, in->postpone,
13196 						in->args.vc.attr.group,
13197 						in->args.vc.actions);
13198 		break;
13199 	case QUEUE_INDIRECT_ACTION_QUERY:
13200 		port_queue_action_handle_query(in->port,
13201 					       in->queue, in->postpone,
13202 					       in->args.ia.action_id);
13203 		break;
13204 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13205 		port_queue_action_handle_query_update(in->port, in->queue,
13206 						      in->postpone,
13207 						      in->args.ia.action_id,
13208 						      in->args.ia.qu_mode,
13209 						      in->args.vc.actions);
13210 		break;
13211 	case INDIRECT_ACTION_CREATE:
13212 	case INDIRECT_ACTION_LIST_CREATE:
13213 		port_action_handle_create(
13214 				in->port, in->args.vc.attr.group,
13215 				in->command == INDIRECT_ACTION_LIST_CREATE,
13216 				&((const struct rte_flow_indir_action_conf) {
13217 					.ingress = in->args.vc.attr.ingress,
13218 					.egress = in->args.vc.attr.egress,
13219 					.transfer = in->args.vc.attr.transfer,
13220 				}),
13221 				in->args.vc.actions);
13222 		break;
13223 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13224 		indirect_action_flow_conf_create(in);
13225 		break;
13226 	case INDIRECT_ACTION_DESTROY:
13227 		port_action_handle_destroy(in->port,
13228 					   in->args.ia_destroy.action_id_n,
13229 					   in->args.ia_destroy.action_id);
13230 		break;
13231 	case INDIRECT_ACTION_UPDATE:
13232 		port_action_handle_update(in->port, in->args.vc.attr.group,
13233 					  in->args.vc.actions);
13234 		break;
13235 	case INDIRECT_ACTION_QUERY:
13236 		port_action_handle_query(in->port, in->args.ia.action_id);
13237 		break;
13238 	case INDIRECT_ACTION_QUERY_UPDATE:
13239 		port_action_handle_query_update(in->port,
13240 						in->args.ia.action_id,
13241 						in->args.ia.qu_mode,
13242 						in->args.vc.actions);
13243 		break;
13244 	case VALIDATE:
13245 		port_flow_validate(in->port, &in->args.vc.attr,
13246 				   in->args.vc.pattern, in->args.vc.actions,
13247 				   &in->args.vc.tunnel_ops);
13248 		break;
13249 	case CREATE:
13250 		port_flow_create(in->port, &in->args.vc.attr,
13251 				 in->args.vc.pattern, in->args.vc.actions,
13252 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13253 		break;
13254 	case DESTROY:
13255 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13256 				  in->args.destroy.rule,
13257 				  in->args.destroy.is_user_id);
13258 		break;
13259 	case FLUSH:
13260 		port_flow_flush(in->port);
13261 		break;
13262 	case DUMP_ONE:
13263 	case DUMP_ALL:
13264 		port_flow_dump(in->port, in->args.dump.mode,
13265 				in->args.dump.rule, in->args.dump.file,
13266 				in->args.dump.is_user_id);
13267 		break;
13268 	case QUERY:
13269 		port_flow_query(in->port, in->args.query.rule,
13270 				&in->args.query.action,
13271 				in->args.query.is_user_id);
13272 		break;
13273 	case LIST:
13274 		port_flow_list(in->port, in->args.list.group_n,
13275 			       in->args.list.group);
13276 		break;
13277 	case ISOLATE:
13278 		port_flow_isolate(in->port, in->args.isolate.set);
13279 		break;
13280 	case AGED:
13281 		port_flow_aged(in->port, in->args.aged.destroy);
13282 		break;
13283 	case TUNNEL_CREATE:
13284 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13285 		break;
13286 	case TUNNEL_DESTROY:
13287 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13288 		break;
13289 	case TUNNEL_LIST:
13290 		port_flow_tunnel_list(in->port);
13291 		break;
13292 	case ACTION_POL_G:
13293 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13294 					in->args.vc.actions);
13295 		break;
13296 	case FLEX_ITEM_CREATE:
13297 		flex_item_create(in->port, in->args.flex.token,
13298 				 in->args.flex.filename);
13299 		break;
13300 	case FLEX_ITEM_DESTROY:
13301 		flex_item_destroy(in->port, in->args.flex.token);
13302 		break;
13303 	default:
13304 		break;
13305 	}
13306 	fflush(stdout);
13307 }
13308 
13309 /** Token generator and output processing callback (cmdline API). */
13310 static void
13311 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13312 {
13313 	if (cl == NULL)
13314 		cmd_flow_tok(arg0, arg2);
13315 	else
13316 		cmd_flow_parsed(arg0);
13317 }
13318 
13319 /** Global parser instance (cmdline API). */
13320 cmdline_parse_inst_t cmd_flow = {
13321 	.f = cmd_flow_cb,
13322 	.data = NULL, /**< Unused. */
13323 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13324 	.tokens = {
13325 		NULL,
13326 	}, /**< Tokens are returned by cmd_flow_tok(). */
13327 };
13328 
13329 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13330 
13331 static void
13332 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13333 {
13334 	struct rte_ipv4_hdr *ipv4;
13335 	struct rte_ether_hdr *eth;
13336 	struct rte_ipv6_hdr *ipv6;
13337 	struct rte_vxlan_hdr *vxlan;
13338 	struct rte_vxlan_gpe_hdr *gpe;
13339 	struct rte_flow_item_nvgre *nvgre;
13340 	uint32_t ipv6_vtc_flow;
13341 
13342 	switch (item->type) {
13343 	case RTE_FLOW_ITEM_TYPE_ETH:
13344 		eth = (struct rte_ether_hdr *)buf;
13345 		if (next_proto)
13346 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13347 		break;
13348 	case RTE_FLOW_ITEM_TYPE_IPV4:
13349 		ipv4 = (struct rte_ipv4_hdr *)buf;
13350 		if (!ipv4->version_ihl)
13351 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13352 		if (next_proto && ipv4->next_proto_id == 0)
13353 			ipv4->next_proto_id = (uint8_t)next_proto;
13354 		break;
13355 	case RTE_FLOW_ITEM_TYPE_IPV6:
13356 		ipv6 = (struct rte_ipv6_hdr *)buf;
13357 		if (next_proto && ipv6->proto == 0)
13358 			ipv6->proto = (uint8_t)next_proto;
13359 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13360 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13361 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13362 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13363 		break;
13364 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13365 		vxlan = (struct rte_vxlan_hdr *)buf;
13366 		vxlan->vx_flags = 0x08;
13367 		break;
13368 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13369 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13370 		gpe->vx_flags = 0x0C;
13371 		break;
13372 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13373 		nvgre = (struct rte_flow_item_nvgre *)buf;
13374 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13375 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13376 		break;
13377 	default:
13378 		break;
13379 	}
13380 }
13381 
13382 /** Helper of get item's default mask. */
13383 static const void *
13384 flow_item_default_mask(const struct rte_flow_item *item)
13385 {
13386 	const void *mask = NULL;
13387 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13388 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13389 		.hdr = {
13390 			.next_hdr = 0xff,
13391 			.type = 0xff,
13392 			.segments_left = 0xff,
13393 		},
13394 	};
13395 
13396 	switch (item->type) {
13397 	case RTE_FLOW_ITEM_TYPE_ANY:
13398 		mask = &rte_flow_item_any_mask;
13399 		break;
13400 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13401 		mask = &rte_flow_item_port_id_mask;
13402 		break;
13403 	case RTE_FLOW_ITEM_TYPE_RAW:
13404 		mask = &rte_flow_item_raw_mask;
13405 		break;
13406 	case RTE_FLOW_ITEM_TYPE_ETH:
13407 		mask = &rte_flow_item_eth_mask;
13408 		break;
13409 	case RTE_FLOW_ITEM_TYPE_VLAN:
13410 		mask = &rte_flow_item_vlan_mask;
13411 		break;
13412 	case RTE_FLOW_ITEM_TYPE_IPV4:
13413 		mask = &rte_flow_item_ipv4_mask;
13414 		break;
13415 	case RTE_FLOW_ITEM_TYPE_IPV6:
13416 		mask = &rte_flow_item_ipv6_mask;
13417 		break;
13418 	case RTE_FLOW_ITEM_TYPE_ICMP:
13419 		mask = &rte_flow_item_icmp_mask;
13420 		break;
13421 	case RTE_FLOW_ITEM_TYPE_UDP:
13422 		mask = &rte_flow_item_udp_mask;
13423 		break;
13424 	case RTE_FLOW_ITEM_TYPE_TCP:
13425 		mask = &rte_flow_item_tcp_mask;
13426 		break;
13427 	case RTE_FLOW_ITEM_TYPE_SCTP:
13428 		mask = &rte_flow_item_sctp_mask;
13429 		break;
13430 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13431 		mask = &rte_flow_item_vxlan_mask;
13432 		break;
13433 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13434 		mask = &rte_flow_item_vxlan_gpe_mask;
13435 		break;
13436 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13437 		mask = &rte_flow_item_e_tag_mask;
13438 		break;
13439 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13440 		mask = &rte_flow_item_nvgre_mask;
13441 		break;
13442 	case RTE_FLOW_ITEM_TYPE_MPLS:
13443 		mask = &rte_flow_item_mpls_mask;
13444 		break;
13445 	case RTE_FLOW_ITEM_TYPE_GRE:
13446 		mask = &rte_flow_item_gre_mask;
13447 		break;
13448 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13449 		mask = &gre_key_default_mask;
13450 		break;
13451 	case RTE_FLOW_ITEM_TYPE_META:
13452 		mask = &rte_flow_item_meta_mask;
13453 		break;
13454 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13455 		mask = &rte_flow_item_random_mask;
13456 		break;
13457 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13458 		mask = &rte_flow_item_fuzzy_mask;
13459 		break;
13460 	case RTE_FLOW_ITEM_TYPE_GTP:
13461 		mask = &rte_flow_item_gtp_mask;
13462 		break;
13463 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13464 		mask = &rte_flow_item_gtp_psc_mask;
13465 		break;
13466 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13467 		mask = &rte_flow_item_geneve_mask;
13468 		break;
13469 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13470 		mask = &rte_flow_item_geneve_opt_mask;
13471 		break;
13472 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13473 		mask = &rte_flow_item_pppoe_proto_id_mask;
13474 		break;
13475 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13476 		mask = &rte_flow_item_l2tpv3oip_mask;
13477 		break;
13478 	case RTE_FLOW_ITEM_TYPE_ESP:
13479 		mask = &rte_flow_item_esp_mask;
13480 		break;
13481 	case RTE_FLOW_ITEM_TYPE_AH:
13482 		mask = &rte_flow_item_ah_mask;
13483 		break;
13484 	case RTE_FLOW_ITEM_TYPE_PFCP:
13485 		mask = &rte_flow_item_pfcp_mask;
13486 		break;
13487 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13488 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13489 		mask = &rte_flow_item_ethdev_mask;
13490 		break;
13491 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13492 		mask = &rte_flow_item_l2tpv2_mask;
13493 		break;
13494 	case RTE_FLOW_ITEM_TYPE_PPP:
13495 		mask = &rte_flow_item_ppp_mask;
13496 		break;
13497 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13498 		mask = &rte_flow_item_meter_color_mask;
13499 		break;
13500 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13501 		mask = &ipv6_routing_ext_default_mask;
13502 		break;
13503 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13504 		mask = &rte_flow_item_aggr_affinity_mask;
13505 		break;
13506 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13507 		mask = &rte_flow_item_tx_queue_mask;
13508 		break;
13509 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13510 		mask = &rte_flow_item_ib_bth_mask;
13511 		break;
13512 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13513 		mask = &rte_flow_item_ptype_mask;
13514 		break;
13515 	default:
13516 		break;
13517 	}
13518 	return mask;
13519 }
13520 
13521 /** Dispatch parsed buffer to function calls. */
13522 static void
13523 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13524 {
13525 	uint32_t n = in->args.vc.pattern_n;
13526 	int i = 0;
13527 	struct rte_flow_item *item = NULL;
13528 	size_t size = 0;
13529 	uint8_t *data = NULL;
13530 	uint8_t *type = NULL;
13531 	size_t *total_size = NULL;
13532 	uint16_t idx = in->port; /* We borrow port field as index */
13533 	struct rte_flow_item_ipv6_routing_ext *ext;
13534 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13535 
13536 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13537 		   in->command == SET_IPV6_EXT_REMOVE);
13538 
13539 	if (in->command == SET_IPV6_EXT_REMOVE) {
13540 		if (n != 1 || in->args.vc.pattern->type !=
13541 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13542 			fprintf(stderr, "Error - Not supported item\n");
13543 			return;
13544 		}
13545 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13546 		item = in->args.vc.pattern;
13547 		ipv6_ext = item->spec;
13548 		*type = ipv6_ext->next_hdr;
13549 		return;
13550 	}
13551 
13552 	total_size = &ipv6_ext_push_confs[idx].size;
13553 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13554 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13555 
13556 	*total_size = 0;
13557 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13558 	for (i = n - 1 ; i >= 0; --i) {
13559 		item = in->args.vc.pattern + i;
13560 		switch (item->type) {
13561 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13562 			ipv6_ext = item->spec;
13563 			*type = ipv6_ext->next_hdr;
13564 			break;
13565 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13566 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13567 			if (!ext->hdr.hdr_len) {
13568 				size = sizeof(struct rte_ipv6_routing_ext) +
13569 				(ext->hdr.segments_left << 4);
13570 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13571 				/* Indicate no TLV once SRH. */
13572 				if (ext->hdr.type == 4)
13573 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13574 			} else {
13575 				size = sizeof(struct rte_ipv6_routing_ext) +
13576 				(ext->hdr.hdr_len << 3);
13577 			}
13578 			*total_size += size;
13579 			memcpy(data, ext, size);
13580 			break;
13581 		default:
13582 			fprintf(stderr, "Error - Not supported item\n");
13583 			goto error;
13584 		}
13585 	}
13586 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13587 	return;
13588 error:
13589 	*total_size = 0;
13590 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13591 }
13592 
13593 /** Dispatch parsed buffer to function calls. */
13594 static void
13595 cmd_set_raw_parsed_sample(const struct buffer *in)
13596 {
13597 	uint32_t n = in->args.vc.actions_n;
13598 	uint32_t i = 0;
13599 	struct rte_flow_action *action = NULL;
13600 	struct rte_flow_action *data = NULL;
13601 	const struct rte_flow_action_rss *rss = NULL;
13602 	size_t size = 0;
13603 	uint16_t idx = in->port; /* We borrow port field as index */
13604 	uint32_t max_size = sizeof(struct rte_flow_action) *
13605 						ACTION_SAMPLE_ACTIONS_NUM;
13606 
13607 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13608 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13609 	memset(data, 0x00, max_size);
13610 	for (; i <= n - 1; i++) {
13611 		action = in->args.vc.actions + i;
13612 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13613 			break;
13614 		switch (action->type) {
13615 		case RTE_FLOW_ACTION_TYPE_MARK:
13616 			size = sizeof(struct rte_flow_action_mark);
13617 			rte_memcpy(&sample_mark[idx],
13618 				(const void *)action->conf, size);
13619 			action->conf = &sample_mark[idx];
13620 			break;
13621 		case RTE_FLOW_ACTION_TYPE_COUNT:
13622 			size = sizeof(struct rte_flow_action_count);
13623 			rte_memcpy(&sample_count[idx],
13624 				(const void *)action->conf, size);
13625 			action->conf = &sample_count[idx];
13626 			break;
13627 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13628 			size = sizeof(struct rte_flow_action_queue);
13629 			rte_memcpy(&sample_queue[idx],
13630 				(const void *)action->conf, size);
13631 			action->conf = &sample_queue[idx];
13632 			break;
13633 		case RTE_FLOW_ACTION_TYPE_RSS:
13634 			size = sizeof(struct rte_flow_action_rss);
13635 			rss = action->conf;
13636 			rte_memcpy(&sample_rss_data[idx].conf,
13637 				   (const void *)rss, size);
13638 			if (rss->key_len && rss->key) {
13639 				sample_rss_data[idx].conf.key =
13640 						sample_rss_data[idx].key;
13641 				rte_memcpy((void *)((uintptr_t)
13642 					   sample_rss_data[idx].conf.key),
13643 					   (const void *)rss->key,
13644 					   sizeof(uint8_t) * rss->key_len);
13645 			}
13646 			if (rss->queue_num && rss->queue) {
13647 				sample_rss_data[idx].conf.queue =
13648 						sample_rss_data[idx].queue;
13649 				rte_memcpy((void *)((uintptr_t)
13650 					   sample_rss_data[idx].conf.queue),
13651 					   (const void *)rss->queue,
13652 					   sizeof(uint16_t) * rss->queue_num);
13653 			}
13654 			action->conf = &sample_rss_data[idx].conf;
13655 			break;
13656 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13657 			size = sizeof(struct rte_flow_action_raw_encap);
13658 			rte_memcpy(&sample_encap[idx],
13659 				(const void *)action->conf, size);
13660 			action->conf = &sample_encap[idx];
13661 			break;
13662 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13663 			size = sizeof(struct rte_flow_action_port_id);
13664 			rte_memcpy(&sample_port_id[idx],
13665 				(const void *)action->conf, size);
13666 			action->conf = &sample_port_id[idx];
13667 			break;
13668 		case RTE_FLOW_ACTION_TYPE_PF:
13669 			break;
13670 		case RTE_FLOW_ACTION_TYPE_VF:
13671 			size = sizeof(struct rte_flow_action_vf);
13672 			rte_memcpy(&sample_vf[idx],
13673 					(const void *)action->conf, size);
13674 			action->conf = &sample_vf[idx];
13675 			break;
13676 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13677 			size = sizeof(struct rte_flow_action_vxlan_encap);
13678 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13679 			action->conf = &sample_vxlan_encap[idx].conf;
13680 			break;
13681 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13682 			size = sizeof(struct rte_flow_action_nvgre_encap);
13683 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13684 			action->conf = &sample_nvgre_encap[idx];
13685 			break;
13686 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13687 			size = sizeof(struct rte_flow_action_ethdev);
13688 			rte_memcpy(&sample_port_representor[idx],
13689 					(const void *)action->conf, size);
13690 			action->conf = &sample_port_representor[idx];
13691 			break;
13692 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13693 			size = sizeof(struct rte_flow_action_ethdev);
13694 			rte_memcpy(&sample_represented_port[idx],
13695 					(const void *)action->conf, size);
13696 			action->conf = &sample_represented_port[idx];
13697 			break;
13698 		default:
13699 			fprintf(stderr, "Error - Not supported action\n");
13700 			return;
13701 		}
13702 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13703 		data++;
13704 	}
13705 }
13706 
13707 /** Dispatch parsed buffer to function calls. */
13708 static void
13709 cmd_set_raw_parsed(const struct buffer *in)
13710 {
13711 	uint32_t n = in->args.vc.pattern_n;
13712 	int i = 0;
13713 	struct rte_flow_item *item = NULL;
13714 	size_t size = 0;
13715 	uint8_t *data = NULL;
13716 	uint8_t *data_tail = NULL;
13717 	size_t *total_size = NULL;
13718 	uint16_t upper_layer = 0;
13719 	uint16_t proto = 0;
13720 	uint16_t idx = in->port; /* We borrow port field as index */
13721 	int gtp_psc = -1; /* GTP PSC option index. */
13722 	const void *src_spec;
13723 
13724 	if (in->command == SET_SAMPLE_ACTIONS)
13725 		return cmd_set_raw_parsed_sample(in);
13726 	else if (in->command == SET_IPV6_EXT_PUSH ||
13727 		 in->command == SET_IPV6_EXT_REMOVE)
13728 		return cmd_set_ipv6_ext_parsed(in);
13729 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13730 		   in->command == SET_RAW_DECAP);
13731 	if (in->command == SET_RAW_ENCAP) {
13732 		total_size = &raw_encap_confs[idx].size;
13733 		data = (uint8_t *)&raw_encap_confs[idx].data;
13734 	} else {
13735 		total_size = &raw_decap_confs[idx].size;
13736 		data = (uint8_t *)&raw_decap_confs[idx].data;
13737 	}
13738 	*total_size = 0;
13739 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13740 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13741 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13742 	for (i = n - 1 ; i >= 0; --i) {
13743 		const struct rte_flow_item_gtp *gtp;
13744 		const struct rte_flow_item_geneve_opt *opt;
13745 		struct rte_flow_item_ipv6_routing_ext *ext;
13746 
13747 		item = in->args.vc.pattern + i;
13748 		if (item->spec == NULL)
13749 			item->spec = flow_item_default_mask(item);
13750 		src_spec = item->spec;
13751 		switch (item->type) {
13752 		case RTE_FLOW_ITEM_TYPE_ETH:
13753 			size = sizeof(struct rte_ether_hdr);
13754 			break;
13755 		case RTE_FLOW_ITEM_TYPE_VLAN:
13756 			size = sizeof(struct rte_vlan_hdr);
13757 			proto = RTE_ETHER_TYPE_VLAN;
13758 			break;
13759 		case RTE_FLOW_ITEM_TYPE_IPV4:
13760 			size = sizeof(struct rte_ipv4_hdr);
13761 			proto = RTE_ETHER_TYPE_IPV4;
13762 			break;
13763 		case RTE_FLOW_ITEM_TYPE_IPV6:
13764 			size = sizeof(struct rte_ipv6_hdr);
13765 			proto = RTE_ETHER_TYPE_IPV6;
13766 			break;
13767 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13768 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13769 			if (!ext->hdr.hdr_len) {
13770 				size = sizeof(struct rte_ipv6_routing_ext) +
13771 					(ext->hdr.segments_left << 4);
13772 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13773 				/* SRv6 without TLV. */
13774 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13775 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13776 			} else {
13777 				size = sizeof(struct rte_ipv6_routing_ext) +
13778 					(ext->hdr.hdr_len << 3);
13779 			}
13780 			proto = IPPROTO_ROUTING;
13781 			break;
13782 		case RTE_FLOW_ITEM_TYPE_UDP:
13783 			size = sizeof(struct rte_udp_hdr);
13784 			proto = 0x11;
13785 			break;
13786 		case RTE_FLOW_ITEM_TYPE_TCP:
13787 			size = sizeof(struct rte_tcp_hdr);
13788 			proto = 0x06;
13789 			break;
13790 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13791 			size = sizeof(struct rte_vxlan_hdr);
13792 			break;
13793 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13794 			size = sizeof(struct rte_vxlan_gpe_hdr);
13795 			break;
13796 		case RTE_FLOW_ITEM_TYPE_GRE:
13797 			size = sizeof(struct rte_gre_hdr);
13798 			proto = 0x2F;
13799 			break;
13800 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13801 			size = sizeof(rte_be32_t);
13802 			proto = 0x0;
13803 			break;
13804 		case RTE_FLOW_ITEM_TYPE_MPLS:
13805 			size = sizeof(struct rte_mpls_hdr);
13806 			proto = 0x0;
13807 			break;
13808 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13809 			size = sizeof(struct rte_flow_item_nvgre);
13810 			proto = 0x2F;
13811 			break;
13812 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13813 			size = sizeof(struct rte_geneve_hdr);
13814 			break;
13815 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13816 			opt = (const struct rte_flow_item_geneve_opt *)
13817 								item->spec;
13818 			size = offsetof(struct rte_flow_item_geneve_opt,
13819 					option_len) + sizeof(uint8_t);
13820 			if (opt->option_len && opt->data) {
13821 				*total_size += opt->option_len *
13822 					       sizeof(uint32_t);
13823 				rte_memcpy(data_tail - (*total_size),
13824 					   opt->data,
13825 					   opt->option_len * sizeof(uint32_t));
13826 			}
13827 			break;
13828 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13829 			size = sizeof(rte_be32_t);
13830 			proto = 0x73;
13831 			break;
13832 		case RTE_FLOW_ITEM_TYPE_ESP:
13833 			size = sizeof(struct rte_esp_hdr);
13834 			proto = 0x32;
13835 			break;
13836 		case RTE_FLOW_ITEM_TYPE_AH:
13837 			size = sizeof(struct rte_flow_item_ah);
13838 			proto = 0x33;
13839 			break;
13840 		case RTE_FLOW_ITEM_TYPE_GTP:
13841 			if (gtp_psc < 0) {
13842 				size = sizeof(struct rte_gtp_hdr);
13843 				break;
13844 			}
13845 			if (gtp_psc != i + 1) {
13846 				fprintf(stderr,
13847 					"Error - GTP PSC does not follow GTP\n");
13848 				goto error;
13849 			}
13850 			gtp = item->spec;
13851 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13852 				/* Only E flag should be set. */
13853 				fprintf(stderr,
13854 					"Error - GTP unsupported flags\n");
13855 				goto error;
13856 			} else {
13857 				struct rte_gtp_hdr_ext_word ext_word = {
13858 					.next_ext = 0x85
13859 				};
13860 
13861 				/* We have to add GTP header extra word. */
13862 				*total_size += sizeof(ext_word);
13863 				rte_memcpy(data_tail - (*total_size),
13864 					   &ext_word, sizeof(ext_word));
13865 			}
13866 			size = sizeof(struct rte_gtp_hdr);
13867 			break;
13868 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13869 			if (gtp_psc >= 0) {
13870 				fprintf(stderr,
13871 					"Error - Multiple GTP PSC items\n");
13872 				goto error;
13873 			} else {
13874 				const struct rte_flow_item_gtp_psc
13875 					*opt = item->spec;
13876 				struct rte_gtp_psc_generic_hdr *hdr;
13877 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
13878 							 sizeof(int32_t));
13879 
13880 				*total_size += hdr_size;
13881 				hdr = (typeof(hdr))(data_tail - (*total_size));
13882 				memset(hdr, 0, hdr_size);
13883 				*hdr = opt->hdr;
13884 				hdr->ext_hdr_len = 1;
13885 				gtp_psc = i;
13886 				size = 0;
13887 			}
13888 			break;
13889 		case RTE_FLOW_ITEM_TYPE_PFCP:
13890 			size = sizeof(struct rte_flow_item_pfcp);
13891 			break;
13892 		case RTE_FLOW_ITEM_TYPE_FLEX:
13893 			if (item->spec != NULL) {
13894 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
13895 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
13896 			} else {
13897 				size = 0;
13898 				src_spec = NULL;
13899 			}
13900 			break;
13901 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
13902 			size = 0;
13903 			if (item->spec) {
13904 				const struct rte_flow_item_gre_opt
13905 					*opt = item->spec;
13906 				if (opt->checksum_rsvd.checksum) {
13907 					*total_size +=
13908 						sizeof(opt->checksum_rsvd);
13909 					rte_memcpy(data_tail - (*total_size),
13910 						   &opt->checksum_rsvd,
13911 						   sizeof(opt->checksum_rsvd));
13912 				}
13913 				if (opt->key.key) {
13914 					*total_size += sizeof(opt->key.key);
13915 					rte_memcpy(data_tail - (*total_size),
13916 						   &opt->key.key,
13917 						   sizeof(opt->key.key));
13918 				}
13919 				if (opt->sequence.sequence) {
13920 					*total_size += sizeof(opt->sequence.sequence);
13921 					rte_memcpy(data_tail - (*total_size),
13922 						   &opt->sequence.sequence,
13923 						   sizeof(opt->sequence.sequence));
13924 				}
13925 			}
13926 			proto = 0x2F;
13927 			break;
13928 		default:
13929 			fprintf(stderr, "Error - Not supported item\n");
13930 			goto error;
13931 		}
13932 		if (size) {
13933 			*total_size += size;
13934 			rte_memcpy(data_tail - (*total_size), src_spec, size);
13935 			/* update some fields which cannot be set by cmdline */
13936 			update_fields((data_tail - (*total_size)), item,
13937 				      upper_layer);
13938 			upper_layer = proto;
13939 		}
13940 	}
13941 	if (verbose_level & 0x1)
13942 		printf("total data size is %zu\n", (*total_size));
13943 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
13944 	memmove(data, (data_tail - (*total_size)), *total_size);
13945 	return;
13946 
13947 error:
13948 	*total_size = 0;
13949 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13950 }
13951 
13952 /** Populate help strings for current token (cmdline API). */
13953 static int
13954 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
13955 		     unsigned int size)
13956 {
13957 	struct context *ctx = &cmd_flow_context;
13958 	const struct token *token = &token_list[ctx->prev];
13959 
13960 	(void)hdr;
13961 	if (!size)
13962 		return -1;
13963 	/* Set token type and update global help with details. */
13964 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
13965 	if (token->help)
13966 		cmd_set_raw.help_str = token->help;
13967 	else
13968 		cmd_set_raw.help_str = token->name;
13969 	return 0;
13970 }
13971 
13972 /** Token definition template (cmdline API). */
13973 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
13974 	.ops = &(struct cmdline_token_ops){
13975 		.parse = cmd_flow_parse,
13976 		.complete_get_nb = cmd_flow_complete_get_nb,
13977 		.complete_get_elt = cmd_flow_complete_get_elt,
13978 		.get_help = cmd_set_raw_get_help,
13979 	},
13980 	.offset = 0,
13981 };
13982 
13983 /** Populate the next dynamic token. */
13984 static void
13985 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
13986 	     cmdline_parse_token_hdr_t **hdr_inst)
13987 {
13988 	struct context *ctx = &cmd_flow_context;
13989 
13990 	/* Always reinitialize context before requesting the first token. */
13991 	if (!(hdr_inst - cmd_set_raw.tokens)) {
13992 		cmd_flow_context_init(ctx);
13993 		ctx->curr = START_SET;
13994 	}
13995 	/* Return NULL when no more tokens are expected. */
13996 	if (!ctx->next_num && (ctx->curr != START_SET)) {
13997 		*hdr = NULL;
13998 		return;
13999 	}
14000 	/* Determine if command should end here. */
14001 	if (ctx->eol && ctx->last && ctx->next_num) {
14002 		const enum index *list = ctx->next[ctx->next_num - 1];
14003 		int i;
14004 
14005 		for (i = 0; list[i]; ++i) {
14006 			if (list[i] != END)
14007 				continue;
14008 			*hdr = NULL;
14009 			return;
14010 		}
14011 	}
14012 	*hdr = &cmd_set_raw_token_hdr;
14013 }
14014 
14015 /** Token generator and output processing callback (cmdline API). */
14016 static void
14017 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14018 {
14019 	if (cl == NULL)
14020 		cmd_set_raw_tok(arg0, arg2);
14021 	else
14022 		cmd_set_raw_parsed(arg0);
14023 }
14024 
14025 /** Global parser instance (cmdline API). */
14026 cmdline_parse_inst_t cmd_set_raw = {
14027 	.f = cmd_set_raw_cb,
14028 	.data = NULL, /**< Unused. */
14029 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14030 	.tokens = {
14031 		NULL,
14032 	}, /**< Tokens are returned by cmd_flow_tok(). */
14033 };
14034 
14035 /* *** display raw_encap/raw_decap buf */
14036 struct cmd_show_set_raw_result {
14037 	cmdline_fixed_string_t cmd_show;
14038 	cmdline_fixed_string_t cmd_what;
14039 	cmdline_fixed_string_t cmd_all;
14040 	uint16_t cmd_index;
14041 };
14042 
14043 static void
14044 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14045 {
14046 	struct cmd_show_set_raw_result *res = parsed_result;
14047 	uint16_t index = res->cmd_index;
14048 	uint8_t all = 0;
14049 	uint8_t *raw_data = NULL;
14050 	size_t raw_size = 0;
14051 	char title[16] = {0};
14052 
14053 	RTE_SET_USED(cl);
14054 	RTE_SET_USED(data);
14055 	if (!strcmp(res->cmd_all, "all")) {
14056 		all = 1;
14057 		index = 0;
14058 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14059 		fprintf(stderr, "index should be 0-%u\n",
14060 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14061 		return;
14062 	}
14063 	do {
14064 		if (!strcmp(res->cmd_what, "raw_encap")) {
14065 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14066 			raw_size = raw_encap_confs[index].size;
14067 			snprintf(title, 16, "\nindex: %u", index);
14068 			rte_hexdump(stdout, title, raw_data, raw_size);
14069 		} else {
14070 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14071 			raw_size = raw_decap_confs[index].size;
14072 			snprintf(title, 16, "\nindex: %u", index);
14073 			rte_hexdump(stdout, title, raw_data, raw_size);
14074 		}
14075 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14076 }
14077 
14078 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14079 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14080 			cmd_show, "show");
14081 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14082 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14083 			cmd_what, "raw_encap#raw_decap");
14084 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14085 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14086 			cmd_index, RTE_UINT16);
14087 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14088 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14089 			cmd_all, "all");
14090 cmdline_parse_inst_t cmd_show_set_raw = {
14091 	.f = cmd_show_set_raw_parsed,
14092 	.data = NULL,
14093 	.help_str = "show <raw_encap|raw_decap> <index>",
14094 	.tokens = {
14095 		(void *)&cmd_show_set_raw_cmd_show,
14096 		(void *)&cmd_show_set_raw_cmd_what,
14097 		(void *)&cmd_show_set_raw_cmd_index,
14098 		NULL,
14099 	},
14100 };
14101 cmdline_parse_inst_t cmd_show_set_raw_all = {
14102 	.f = cmd_show_set_raw_parsed,
14103 	.data = NULL,
14104 	.help_str = "show <raw_encap|raw_decap> all",
14105 	.tokens = {
14106 		(void *)&cmd_show_set_raw_cmd_show,
14107 		(void *)&cmd_show_set_raw_cmd_what,
14108 		(void *)&cmd_show_set_raw_cmd_all,
14109 		NULL,
14110 	},
14111 };
14112