xref: /dpdk/app/test-pmd/cmdline_flow.c (revision f86085caab0c6c5dc630b9d6ad20d1c728e7703e)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5 
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include <rte_string_fns.h>
16 #include <rte_common.h>
17 #include <rte_ethdev.h>
18 #include <rte_byteorder.h>
19 #include <cmdline_parse.h>
20 #include <cmdline_parse_etheraddr.h>
21 #include <cmdline_parse_string.h>
22 #include <cmdline_parse_num.h>
23 #include <rte_flow.h>
24 #include <rte_hexdump.h>
25 #include <rte_vxlan.h>
26 #include <rte_gre.h>
27 #include <rte_mpls.h>
28 #include <rte_gtp.h>
29 #include <rte_geneve.h>
30 
31 #include "testpmd.h"
32 
33 /** Parser token indices. */
34 enum index {
35 	/* Special tokens. */
36 	ZERO = 0,
37 	END,
38 	START_SET,
39 	END_SET,
40 
41 	/* Common tokens. */
42 	COMMON_INTEGER,
43 	COMMON_UNSIGNED,
44 	COMMON_PREFIX,
45 	COMMON_BOOLEAN,
46 	COMMON_STRING,
47 	COMMON_HEX,
48 	COMMON_FILE_PATH,
49 	COMMON_MAC_ADDR,
50 	COMMON_IPV4_ADDR,
51 	COMMON_IPV6_ADDR,
52 	COMMON_RULE_ID,
53 	COMMON_PORT_ID,
54 	COMMON_GROUP_ID,
55 	COMMON_PRIORITY_LEVEL,
56 	COMMON_INDIRECT_ACTION_ID,
57 	COMMON_PROFILE_ID,
58 	COMMON_POLICY_ID,
59 	COMMON_FLEX_HANDLE,
60 	COMMON_FLEX_TOKEN,
61 	COMMON_PATTERN_TEMPLATE_ID,
62 	COMMON_ACTIONS_TEMPLATE_ID,
63 	COMMON_TABLE_ID,
64 	COMMON_QUEUE_ID,
65 
66 	/* TOP-level command. */
67 	ADD,
68 
69 	/* Top-level command. */
70 	SET,
71 	/* Sub-leve commands. */
72 	SET_RAW_ENCAP,
73 	SET_RAW_DECAP,
74 	SET_RAW_INDEX,
75 	SET_SAMPLE_ACTIONS,
76 	SET_SAMPLE_INDEX,
77 	SET_IPV6_EXT_REMOVE,
78 	SET_IPV6_EXT_PUSH,
79 	SET_IPV6_EXT_INDEX,
80 
81 	/* Top-level command. */
82 	FLOW,
83 	/* Sub-level commands. */
84 	INFO,
85 	CONFIGURE,
86 	PATTERN_TEMPLATE,
87 	ACTIONS_TEMPLATE,
88 	TABLE,
89 	FLOW_GROUP,
90 	INDIRECT_ACTION,
91 	VALIDATE,
92 	CREATE,
93 	DESTROY,
94 	UPDATE,
95 	FLUSH,
96 	DUMP,
97 	QUERY,
98 	LIST,
99 	AGED,
100 	ISOLATE,
101 	TUNNEL,
102 	FLEX,
103 	QUEUE,
104 	PUSH,
105 	PULL,
106 	HASH,
107 
108 	/* Flex arguments */
109 	FLEX_ITEM_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 	VC_IS_USER_ID,
264 
265 	/* Dump arguments */
266 	DUMP_ALL,
267 	DUMP_ONE,
268 	DUMP_IS_USER_ID,
269 
270 	/* Configure arguments */
271 	CONFIG_QUEUES_NUMBER,
272 	CONFIG_QUEUES_SIZE,
273 	CONFIG_COUNTERS_NUMBER,
274 	CONFIG_AGING_OBJECTS_NUMBER,
275 	CONFIG_METERS_NUMBER,
276 	CONFIG_CONN_TRACK_NUMBER,
277 	CONFIG_QUOTAS_NUMBER,
278 	CONFIG_FLAGS,
279 	CONFIG_HOST_PORT,
280 
281 	/* Indirect action arguments */
282 	INDIRECT_ACTION_CREATE,
283 	INDIRECT_ACTION_LIST_CREATE,
284 	INDIRECT_ACTION_FLOW_CONF_CREATE,
285 	INDIRECT_ACTION_UPDATE,
286 	INDIRECT_ACTION_DESTROY,
287 	INDIRECT_ACTION_QUERY,
288 	INDIRECT_ACTION_QUERY_UPDATE,
289 
290 	/* Indirect action create arguments */
291 	INDIRECT_ACTION_CREATE_ID,
292 	INDIRECT_ACTION_INGRESS,
293 	INDIRECT_ACTION_EGRESS,
294 	INDIRECT_ACTION_TRANSFER,
295 	INDIRECT_ACTION_SPEC,
296 	INDIRECT_ACTION_LIST,
297 	INDIRECT_ACTION_FLOW_CONF,
298 
299 	/* Indirect action destroy arguments */
300 	INDIRECT_ACTION_DESTROY_ID,
301 
302 	/* Indirect action query-and-update arguments */
303 	INDIRECT_ACTION_QU_MODE,
304 	INDIRECT_ACTION_QU_MODE_NAME,
305 
306 	/* Validate/create pattern. */
307 	ITEM_PATTERN,
308 	ITEM_PARAM_IS,
309 	ITEM_PARAM_SPEC,
310 	ITEM_PARAM_LAST,
311 	ITEM_PARAM_MASK,
312 	ITEM_PARAM_PREFIX,
313 	ITEM_NEXT,
314 	ITEM_END,
315 	ITEM_VOID,
316 	ITEM_INVERT,
317 	ITEM_ANY,
318 	ITEM_ANY_NUM,
319 	ITEM_PORT_ID,
320 	ITEM_PORT_ID_ID,
321 	ITEM_MARK,
322 	ITEM_MARK_ID,
323 	ITEM_RAW,
324 	ITEM_RAW_RELATIVE,
325 	ITEM_RAW_SEARCH,
326 	ITEM_RAW_OFFSET,
327 	ITEM_RAW_LIMIT,
328 	ITEM_RAW_PATTERN,
329 	ITEM_RAW_PATTERN_HEX,
330 	ITEM_ETH,
331 	ITEM_ETH_DST,
332 	ITEM_ETH_SRC,
333 	ITEM_ETH_TYPE,
334 	ITEM_ETH_HAS_VLAN,
335 	ITEM_VLAN,
336 	ITEM_VLAN_TCI,
337 	ITEM_VLAN_PCP,
338 	ITEM_VLAN_DEI,
339 	ITEM_VLAN_VID,
340 	ITEM_VLAN_INNER_TYPE,
341 	ITEM_VLAN_HAS_MORE_VLAN,
342 	ITEM_IPV4,
343 	ITEM_IPV4_VER_IHL,
344 	ITEM_IPV4_TOS,
345 	ITEM_IPV4_LENGTH,
346 	ITEM_IPV4_ID,
347 	ITEM_IPV4_FRAGMENT_OFFSET,
348 	ITEM_IPV4_TTL,
349 	ITEM_IPV4_PROTO,
350 	ITEM_IPV4_SRC,
351 	ITEM_IPV4_DST,
352 	ITEM_IPV6,
353 	ITEM_IPV6_TC,
354 	ITEM_IPV6_FLOW,
355 	ITEM_IPV6_LEN,
356 	ITEM_IPV6_PROTO,
357 	ITEM_IPV6_HOP,
358 	ITEM_IPV6_SRC,
359 	ITEM_IPV6_DST,
360 	ITEM_IPV6_HAS_FRAG_EXT,
361 	ITEM_IPV6_ROUTING_EXT,
362 	ITEM_IPV6_ROUTING_EXT_TYPE,
363 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
364 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
365 	ITEM_ICMP,
366 	ITEM_ICMP_TYPE,
367 	ITEM_ICMP_CODE,
368 	ITEM_ICMP_IDENT,
369 	ITEM_ICMP_SEQ,
370 	ITEM_UDP,
371 	ITEM_UDP_SRC,
372 	ITEM_UDP_DST,
373 	ITEM_TCP,
374 	ITEM_TCP_SRC,
375 	ITEM_TCP_DST,
376 	ITEM_TCP_FLAGS,
377 	ITEM_SCTP,
378 	ITEM_SCTP_SRC,
379 	ITEM_SCTP_DST,
380 	ITEM_SCTP_TAG,
381 	ITEM_SCTP_CKSUM,
382 	ITEM_VXLAN,
383 	ITEM_VXLAN_VNI,
384 	ITEM_VXLAN_FLAG_G,
385 	ITEM_VXLAN_FLAG_VER,
386 	ITEM_VXLAN_FLAG_I,
387 	ITEM_VXLAN_FLAG_P,
388 	ITEM_VXLAN_FLAG_B,
389 	ITEM_VXLAN_FLAG_O,
390 	ITEM_VXLAN_FLAG_D,
391 	ITEM_VXLAN_FLAG_A,
392 	ITEM_VXLAN_GBP_ID,
393 	/* Used for "struct rte_vxlan_hdr", GPE Next protocol */
394 	ITEM_VXLAN_GPE_PROTO,
395 	ITEM_VXLAN_FIRST_RSVD,
396 	ITEM_VXLAN_SECND_RSVD,
397 	ITEM_VXLAN_THIRD_RSVD,
398 	ITEM_VXLAN_LAST_RSVD,
399 	ITEM_E_TAG,
400 	ITEM_E_TAG_GRP_ECID_B,
401 	ITEM_NVGRE,
402 	ITEM_NVGRE_TNI,
403 	ITEM_MPLS,
404 	ITEM_MPLS_LABEL,
405 	ITEM_MPLS_TC,
406 	ITEM_MPLS_S,
407 	ITEM_MPLS_TTL,
408 	ITEM_GRE,
409 	ITEM_GRE_PROTO,
410 	ITEM_GRE_C_RSVD0_VER,
411 	ITEM_GRE_C_BIT,
412 	ITEM_GRE_K_BIT,
413 	ITEM_GRE_S_BIT,
414 	ITEM_FUZZY,
415 	ITEM_FUZZY_THRESH,
416 	ITEM_GTP,
417 	ITEM_GTP_FLAGS,
418 	ITEM_GTP_MSG_TYPE,
419 	ITEM_GTP_TEID,
420 	ITEM_GTPC,
421 	ITEM_GTPU,
422 	ITEM_GENEVE,
423 	ITEM_GENEVE_VNI,
424 	ITEM_GENEVE_PROTO,
425 	ITEM_GENEVE_OPTLEN,
426 	ITEM_VXLAN_GPE,
427 	ITEM_VXLAN_GPE_VNI,
428 	/* Used for "struct rte_vxlan_gpe_hdr", deprecated, prefer ITEM_VXLAN_GPE_PROTO */
429 	ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR,
430 	ITEM_VXLAN_GPE_FLAGS,
431 	ITEM_VXLAN_GPE_RSVD0,
432 	ITEM_VXLAN_GPE_RSVD1,
433 	ITEM_ARP_ETH_IPV4,
434 	ITEM_ARP_ETH_IPV4_SHA,
435 	ITEM_ARP_ETH_IPV4_SPA,
436 	ITEM_ARP_ETH_IPV4_THA,
437 	ITEM_ARP_ETH_IPV4_TPA,
438 	ITEM_IPV6_EXT,
439 	ITEM_IPV6_EXT_NEXT_HDR,
440 	ITEM_IPV6_FRAG_EXT,
441 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
442 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
443 	ITEM_IPV6_FRAG_EXT_ID,
444 	ITEM_ICMP6,
445 	ITEM_ICMP6_TYPE,
446 	ITEM_ICMP6_CODE,
447 	ITEM_ICMP6_ECHO_REQUEST,
448 	ITEM_ICMP6_ECHO_REQUEST_ID,
449 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
450 	ITEM_ICMP6_ECHO_REPLY,
451 	ITEM_ICMP6_ECHO_REPLY_ID,
452 	ITEM_ICMP6_ECHO_REPLY_SEQ,
453 	ITEM_ICMP6_ND_NS,
454 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
455 	ITEM_ICMP6_ND_NA,
456 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
457 	ITEM_ICMP6_ND_OPT,
458 	ITEM_ICMP6_ND_OPT_TYPE,
459 	ITEM_ICMP6_ND_OPT_SLA_ETH,
460 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
461 	ITEM_ICMP6_ND_OPT_TLA_ETH,
462 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
463 	ITEM_META,
464 	ITEM_META_DATA,
465 	ITEM_RANDOM,
466 	ITEM_RANDOM_VALUE,
467 	ITEM_GRE_KEY,
468 	ITEM_GRE_KEY_VALUE,
469 	ITEM_GRE_OPTION,
470 	ITEM_GRE_OPTION_CHECKSUM,
471 	ITEM_GRE_OPTION_KEY,
472 	ITEM_GRE_OPTION_SEQUENCE,
473 	ITEM_GTP_PSC,
474 	ITEM_GTP_PSC_QFI,
475 	ITEM_GTP_PSC_PDU_T,
476 	ITEM_PPPOES,
477 	ITEM_PPPOED,
478 	ITEM_PPPOE_SEID,
479 	ITEM_PPPOE_PROTO_ID,
480 	ITEM_HIGIG2,
481 	ITEM_HIGIG2_CLASSIFICATION,
482 	ITEM_HIGIG2_VID,
483 	ITEM_TAG,
484 	ITEM_TAG_DATA,
485 	ITEM_TAG_INDEX,
486 	ITEM_L2TPV3OIP,
487 	ITEM_L2TPV3OIP_SESSION_ID,
488 	ITEM_ESP,
489 	ITEM_ESP_SPI,
490 	ITEM_AH,
491 	ITEM_AH_SPI,
492 	ITEM_PFCP,
493 	ITEM_PFCP_S_FIELD,
494 	ITEM_PFCP_SEID,
495 	ITEM_ECPRI,
496 	ITEM_ECPRI_COMMON,
497 	ITEM_ECPRI_COMMON_TYPE,
498 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
499 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
500 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
501 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
502 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
503 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
504 	ITEM_GENEVE_OPT,
505 	ITEM_GENEVE_OPT_CLASS,
506 	ITEM_GENEVE_OPT_TYPE,
507 	ITEM_GENEVE_OPT_LENGTH,
508 	ITEM_GENEVE_OPT_DATA,
509 	ITEM_INTEGRITY,
510 	ITEM_INTEGRITY_LEVEL,
511 	ITEM_INTEGRITY_VALUE,
512 	ITEM_CONNTRACK,
513 	ITEM_POL_PORT,
514 	ITEM_POL_METER,
515 	ITEM_POL_POLICY,
516 	ITEM_PORT_REPRESENTOR,
517 	ITEM_PORT_REPRESENTOR_PORT_ID,
518 	ITEM_REPRESENTED_PORT,
519 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
520 	ITEM_FLEX,
521 	ITEM_FLEX_ITEM_HANDLE,
522 	ITEM_FLEX_PATTERN_HANDLE,
523 	ITEM_L2TPV2,
524 	ITEM_L2TPV2_TYPE,
525 	ITEM_L2TPV2_TYPE_DATA,
526 	ITEM_L2TPV2_TYPE_DATA_L,
527 	ITEM_L2TPV2_TYPE_DATA_S,
528 	ITEM_L2TPV2_TYPE_DATA_O,
529 	ITEM_L2TPV2_TYPE_DATA_L_S,
530 	ITEM_L2TPV2_TYPE_CTRL,
531 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
532 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
533 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
534 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
535 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
536 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
537 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
538 	ITEM_L2TPV2_MSG_DATA_S_NS,
539 	ITEM_L2TPV2_MSG_DATA_S_NR,
540 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
541 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
542 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
543 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
544 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
545 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
546 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
547 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
548 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
549 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
550 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
551 	ITEM_L2TPV2_MSG_CTRL_NS,
552 	ITEM_L2TPV2_MSG_CTRL_NR,
553 	ITEM_PPP,
554 	ITEM_PPP_ADDR,
555 	ITEM_PPP_CTRL,
556 	ITEM_PPP_PROTO_ID,
557 	ITEM_METER,
558 	ITEM_METER_COLOR,
559 	ITEM_METER_COLOR_NAME,
560 	ITEM_QUOTA,
561 	ITEM_QUOTA_STATE,
562 	ITEM_QUOTA_STATE_NAME,
563 	ITEM_AGGR_AFFINITY,
564 	ITEM_AGGR_AFFINITY_VALUE,
565 	ITEM_TX_QUEUE,
566 	ITEM_TX_QUEUE_VALUE,
567 	ITEM_IB_BTH,
568 	ITEM_IB_BTH_OPCODE,
569 	ITEM_IB_BTH_PKEY,
570 	ITEM_IB_BTH_DST_QPN,
571 	ITEM_IB_BTH_PSN,
572 	ITEM_IPV6_PUSH_REMOVE_EXT,
573 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
574 	ITEM_PTYPE,
575 	ITEM_PTYPE_VALUE,
576 	ITEM_NSH,
577 	ITEM_COMPARE,
578 	ITEM_COMPARE_OP,
579 	ITEM_COMPARE_OP_VALUE,
580 	ITEM_COMPARE_FIELD_A_TYPE,
581 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
582 	ITEM_COMPARE_FIELD_A_LEVEL,
583 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
584 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
585 	ITEM_COMPARE_FIELD_A_TYPE_ID,
586 	ITEM_COMPARE_FIELD_A_CLASS_ID,
587 	ITEM_COMPARE_FIELD_A_OFFSET,
588 	ITEM_COMPARE_FIELD_B_TYPE,
589 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
590 	ITEM_COMPARE_FIELD_B_LEVEL,
591 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
592 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
593 	ITEM_COMPARE_FIELD_B_TYPE_ID,
594 	ITEM_COMPARE_FIELD_B_CLASS_ID,
595 	ITEM_COMPARE_FIELD_B_OFFSET,
596 	ITEM_COMPARE_FIELD_B_VALUE,
597 	ITEM_COMPARE_FIELD_B_POINTER,
598 	ITEM_COMPARE_FIELD_WIDTH,
599 
600 	/* Validate/create actions. */
601 	ACTIONS,
602 	ACTION_NEXT,
603 	ACTION_END,
604 	ACTION_VOID,
605 	ACTION_PASSTHRU,
606 	ACTION_SKIP_CMAN,
607 	ACTION_JUMP,
608 	ACTION_JUMP_GROUP,
609 	ACTION_MARK,
610 	ACTION_MARK_ID,
611 	ACTION_FLAG,
612 	ACTION_QUEUE,
613 	ACTION_QUEUE_INDEX,
614 	ACTION_DROP,
615 	ACTION_COUNT,
616 	ACTION_COUNT_ID,
617 	ACTION_RSS,
618 	ACTION_RSS_FUNC,
619 	ACTION_RSS_LEVEL,
620 	ACTION_RSS_FUNC_DEFAULT,
621 	ACTION_RSS_FUNC_TOEPLITZ,
622 	ACTION_RSS_FUNC_SIMPLE_XOR,
623 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
624 	ACTION_RSS_TYPES,
625 	ACTION_RSS_TYPE,
626 	ACTION_RSS_KEY,
627 	ACTION_RSS_KEY_LEN,
628 	ACTION_RSS_QUEUES,
629 	ACTION_RSS_QUEUE,
630 	ACTION_PF,
631 	ACTION_VF,
632 	ACTION_VF_ORIGINAL,
633 	ACTION_VF_ID,
634 	ACTION_PORT_ID,
635 	ACTION_PORT_ID_ORIGINAL,
636 	ACTION_PORT_ID_ID,
637 	ACTION_METER,
638 	ACTION_METER_COLOR,
639 	ACTION_METER_COLOR_TYPE,
640 	ACTION_METER_COLOR_GREEN,
641 	ACTION_METER_COLOR_YELLOW,
642 	ACTION_METER_COLOR_RED,
643 	ACTION_METER_ID,
644 	ACTION_METER_MARK,
645 	ACTION_METER_PROFILE,
646 	ACTION_METER_PROFILE_ID2PTR,
647 	ACTION_METER_POLICY,
648 	ACTION_METER_POLICY_ID2PTR,
649 	ACTION_METER_COLOR_MODE,
650 	ACTION_METER_STATE,
651 	ACTION_OF_DEC_NW_TTL,
652 	ACTION_OF_POP_VLAN,
653 	ACTION_OF_PUSH_VLAN,
654 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
655 	ACTION_OF_SET_VLAN_VID,
656 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
657 	ACTION_OF_SET_VLAN_PCP,
658 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
659 	ACTION_OF_POP_MPLS,
660 	ACTION_OF_POP_MPLS_ETHERTYPE,
661 	ACTION_OF_PUSH_MPLS,
662 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
663 	ACTION_VXLAN_ENCAP,
664 	ACTION_VXLAN_DECAP,
665 	ACTION_NVGRE_ENCAP,
666 	ACTION_NVGRE_DECAP,
667 	ACTION_L2_ENCAP,
668 	ACTION_L2_DECAP,
669 	ACTION_MPLSOGRE_ENCAP,
670 	ACTION_MPLSOGRE_DECAP,
671 	ACTION_MPLSOUDP_ENCAP,
672 	ACTION_MPLSOUDP_DECAP,
673 	ACTION_SET_IPV4_SRC,
674 	ACTION_SET_IPV4_SRC_IPV4_SRC,
675 	ACTION_SET_IPV4_DST,
676 	ACTION_SET_IPV4_DST_IPV4_DST,
677 	ACTION_SET_IPV6_SRC,
678 	ACTION_SET_IPV6_SRC_IPV6_SRC,
679 	ACTION_SET_IPV6_DST,
680 	ACTION_SET_IPV6_DST_IPV6_DST,
681 	ACTION_SET_TP_SRC,
682 	ACTION_SET_TP_SRC_TP_SRC,
683 	ACTION_SET_TP_DST,
684 	ACTION_SET_TP_DST_TP_DST,
685 	ACTION_MAC_SWAP,
686 	ACTION_DEC_TTL,
687 	ACTION_SET_TTL,
688 	ACTION_SET_TTL_TTL,
689 	ACTION_SET_MAC_SRC,
690 	ACTION_SET_MAC_SRC_MAC_SRC,
691 	ACTION_SET_MAC_DST,
692 	ACTION_SET_MAC_DST_MAC_DST,
693 	ACTION_INC_TCP_SEQ,
694 	ACTION_INC_TCP_SEQ_VALUE,
695 	ACTION_DEC_TCP_SEQ,
696 	ACTION_DEC_TCP_SEQ_VALUE,
697 	ACTION_INC_TCP_ACK,
698 	ACTION_INC_TCP_ACK_VALUE,
699 	ACTION_DEC_TCP_ACK,
700 	ACTION_DEC_TCP_ACK_VALUE,
701 	ACTION_RAW_ENCAP,
702 	ACTION_RAW_DECAP,
703 	ACTION_RAW_ENCAP_SIZE,
704 	ACTION_RAW_ENCAP_INDEX,
705 	ACTION_RAW_ENCAP_INDEX_VALUE,
706 	ACTION_RAW_DECAP_INDEX,
707 	ACTION_RAW_DECAP_INDEX_VALUE,
708 	ACTION_SET_TAG,
709 	ACTION_SET_TAG_DATA,
710 	ACTION_SET_TAG_INDEX,
711 	ACTION_SET_TAG_MASK,
712 	ACTION_SET_META,
713 	ACTION_SET_META_DATA,
714 	ACTION_SET_META_MASK,
715 	ACTION_SET_IPV4_DSCP,
716 	ACTION_SET_IPV4_DSCP_VALUE,
717 	ACTION_SET_IPV6_DSCP,
718 	ACTION_SET_IPV6_DSCP_VALUE,
719 	ACTION_AGE,
720 	ACTION_AGE_TIMEOUT,
721 	ACTION_AGE_UPDATE,
722 	ACTION_AGE_UPDATE_TIMEOUT,
723 	ACTION_AGE_UPDATE_TOUCH,
724 	ACTION_SAMPLE,
725 	ACTION_SAMPLE_RATIO,
726 	ACTION_SAMPLE_INDEX,
727 	ACTION_SAMPLE_INDEX_VALUE,
728 	ACTION_INDIRECT,
729 	ACTION_INDIRECT_LIST,
730 	ACTION_INDIRECT_LIST_HANDLE,
731 	ACTION_INDIRECT_LIST_CONF,
732 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
733 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
734 	ACTION_SHARED_INDIRECT,
735 	INDIRECT_ACTION_PORT,
736 	INDIRECT_ACTION_ID2PTR,
737 	ACTION_MODIFY_FIELD,
738 	ACTION_MODIFY_FIELD_OP,
739 	ACTION_MODIFY_FIELD_OP_VALUE,
740 	ACTION_MODIFY_FIELD_DST_TYPE,
741 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
742 	ACTION_MODIFY_FIELD_DST_LEVEL,
743 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
744 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
745 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
746 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
747 	ACTION_MODIFY_FIELD_DST_OFFSET,
748 	ACTION_MODIFY_FIELD_SRC_TYPE,
749 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
750 	ACTION_MODIFY_FIELD_SRC_LEVEL,
751 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
752 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
753 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
754 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
755 	ACTION_MODIFY_FIELD_SRC_OFFSET,
756 	ACTION_MODIFY_FIELD_SRC_VALUE,
757 	ACTION_MODIFY_FIELD_SRC_POINTER,
758 	ACTION_MODIFY_FIELD_WIDTH,
759 	ACTION_CONNTRACK,
760 	ACTION_CONNTRACK_UPDATE,
761 	ACTION_CONNTRACK_UPDATE_DIR,
762 	ACTION_CONNTRACK_UPDATE_CTX,
763 	ACTION_POL_G,
764 	ACTION_POL_Y,
765 	ACTION_POL_R,
766 	ACTION_PORT_REPRESENTOR,
767 	ACTION_PORT_REPRESENTOR_PORT_ID,
768 	ACTION_REPRESENTED_PORT,
769 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
770 	ACTION_SEND_TO_KERNEL,
771 	ACTION_QUOTA_CREATE,
772 	ACTION_QUOTA_CREATE_LIMIT,
773 	ACTION_QUOTA_CREATE_MODE,
774 	ACTION_QUOTA_CREATE_MODE_NAME,
775 	ACTION_QUOTA_QU,
776 	ACTION_QUOTA_QU_LIMIT,
777 	ACTION_QUOTA_QU_UPDATE_OP,
778 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
779 	ACTION_IPV6_EXT_REMOVE,
780 	ACTION_IPV6_EXT_REMOVE_INDEX,
781 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
782 	ACTION_IPV6_EXT_PUSH,
783 	ACTION_IPV6_EXT_PUSH_INDEX,
784 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
785 	ACTION_NAT64,
786 	ACTION_NAT64_MODE,
787 	ACTION_JUMP_TO_TABLE_INDEX,
788 	ACTION_JUMP_TO_TABLE_INDEX_TABLE,
789 	ACTION_JUMP_TO_TABLE_INDEX_INDEX,
790 };
791 
792 /** Maximum size for pattern in struct rte_flow_item_raw. */
793 #define ITEM_RAW_PATTERN_SIZE 512
794 
795 /** Maximum size for GENEVE option data pattern in bytes. */
796 #define ITEM_GENEVE_OPT_DATA_SIZE 124
797 
798 /** Storage size for struct rte_flow_item_raw including pattern. */
799 #define ITEM_RAW_SIZE \
800 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
801 
802 static const char *const compare_ops[] = {
803 	"eq", "ne", "lt", "le", "gt", "ge", NULL
804 };
805 
806 /** Maximum size for external pattern in struct rte_flow_field_data. */
807 #define FLOW_FIELD_PATTERN_SIZE 32
808 
809 /** Storage size for struct rte_flow_action_modify_field including pattern. */
810 #define ACTION_MODIFY_SIZE \
811 	(sizeof(struct rte_flow_action_modify_field) + \
812 	FLOW_FIELD_PATTERN_SIZE)
813 
814 /** Maximum number of queue indices in struct rte_flow_action_rss. */
815 #define ACTION_RSS_QUEUE_NUM 128
816 
817 /** Storage for struct rte_flow_action_rss including external data. */
818 struct action_rss_data {
819 	struct rte_flow_action_rss conf;
820 	uint8_t key[RSS_HASH_KEY_LENGTH];
821 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
822 };
823 
824 /** Maximum data size in struct rte_flow_action_raw_encap. */
825 #define ACTION_RAW_ENCAP_MAX_DATA 512
826 #define RAW_ENCAP_CONFS_MAX_NUM 8
827 
828 /** Storage for struct rte_flow_action_raw_encap. */
829 struct raw_encap_conf {
830 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
831 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
832 	size_t size;
833 };
834 
835 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
836 
837 /** Storage for struct rte_flow_action_raw_encap including external data. */
838 struct action_raw_encap_data {
839 	struct rte_flow_action_raw_encap conf;
840 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
841 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
842 	uint16_t idx;
843 };
844 
845 /** Storage for struct rte_flow_action_raw_decap. */
846 struct raw_decap_conf {
847 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
848 	size_t size;
849 };
850 
851 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
852 
853 /** Storage for struct rte_flow_action_raw_decap including external data. */
854 struct action_raw_decap_data {
855 	struct rte_flow_action_raw_decap conf;
856 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
857 	uint16_t idx;
858 };
859 
860 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
861 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
862 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
863 
864 /** Storage for struct rte_flow_action_ipv6_ext_push. */
865 struct ipv6_ext_push_conf {
866 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
867 	size_t size;
868 	uint8_t type;
869 };
870 
871 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
872 
873 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
874 struct action_ipv6_ext_push_data {
875 	struct rte_flow_action_ipv6_ext_push conf;
876 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
877 	uint8_t type;
878 	uint16_t idx;
879 };
880 
881 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
882 struct ipv6_ext_remove_conf {
883 	struct rte_flow_action_ipv6_ext_remove conf;
884 	uint8_t type;
885 };
886 
887 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
888 
889 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
890 struct action_ipv6_ext_remove_data {
891 	struct rte_flow_action_ipv6_ext_remove conf;
892 	uint8_t type;
893 	uint16_t idx;
894 };
895 
896 struct vxlan_encap_conf vxlan_encap_conf = {
897 	.select_ipv4 = 1,
898 	.select_vlan = 0,
899 	.select_tos_ttl = 0,
900 	.vni = { 0x00, 0x00, 0x00 },
901 	.udp_src = 0,
902 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
903 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
904 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
905 	.ipv6_src = RTE_IPV6_ADDR_LOOPBACK,
906 	.ipv6_dst = RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 0x1111),
907 	.vlan_tci = 0,
908 	.ip_tos = 0,
909 	.ip_ttl = 255,
910 	.eth_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
911 	.eth_dst = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
912 };
913 
914 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
915 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
916 
917 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
918 struct action_vxlan_encap_data {
919 	struct rte_flow_action_vxlan_encap conf;
920 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
921 	struct rte_flow_item_eth item_eth;
922 	struct rte_flow_item_vlan item_vlan;
923 	union {
924 		struct rte_flow_item_ipv4 item_ipv4;
925 		struct rte_flow_item_ipv6 item_ipv6;
926 	};
927 	struct rte_flow_item_udp item_udp;
928 	struct rte_flow_item_vxlan item_vxlan;
929 };
930 
931 struct nvgre_encap_conf nvgre_encap_conf = {
932 	.select_ipv4 = 1,
933 	.select_vlan = 0,
934 	.tni = { 0x00, 0x00, 0x00 },
935 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
936 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
937 	.ipv6_src = RTE_IPV6_ADDR_LOOPBACK,
938 	.ipv6_dst = RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 0x1111),
939 	.vlan_tci = 0,
940 	.eth_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
941 	.eth_dst = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
942 };
943 
944 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
945 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
946 
947 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
948 struct action_nvgre_encap_data {
949 	struct rte_flow_action_nvgre_encap conf;
950 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
951 	struct rte_flow_item_eth item_eth;
952 	struct rte_flow_item_vlan item_vlan;
953 	union {
954 		struct rte_flow_item_ipv4 item_ipv4;
955 		struct rte_flow_item_ipv6 item_ipv6;
956 	};
957 	struct rte_flow_item_nvgre item_nvgre;
958 };
959 
960 struct l2_encap_conf l2_encap_conf;
961 
962 struct l2_decap_conf l2_decap_conf;
963 
964 struct mplsogre_encap_conf mplsogre_encap_conf;
965 
966 struct mplsogre_decap_conf mplsogre_decap_conf;
967 
968 struct mplsoudp_encap_conf mplsoudp_encap_conf;
969 
970 struct mplsoudp_decap_conf mplsoudp_decap_conf;
971 
972 struct rte_flow_action_conntrack conntrack_context;
973 
974 #define ACTION_SAMPLE_ACTIONS_NUM 10
975 #define RAW_SAMPLE_CONFS_MAX_NUM 8
976 /** Storage for struct rte_flow_action_sample including external data. */
977 struct action_sample_data {
978 	struct rte_flow_action_sample conf;
979 	uint32_t idx;
980 };
981 /** Storage for struct rte_flow_action_sample. */
982 struct raw_sample_conf {
983 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
984 };
985 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
986 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
987 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
988 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
989 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
990 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
991 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
992 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
993 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
994 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
995 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
996 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
997 
998 static const char *const modify_field_ops[] = {
999 	"set", "add", "sub", NULL
1000 };
1001 
1002 static const char *const flow_field_ids[] = {
1003 	"start", "mac_dst", "mac_src",
1004 	"vlan_type", "vlan_id", "mac_type",
1005 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
1006 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
1007 	"tcp_port_src", "tcp_port_dst",
1008 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
1009 	"udp_port_src", "udp_port_dst",
1010 	"vxlan_vni", "geneve_vni", "gtp_teid",
1011 	"tag", "mark", "meta", "pointer", "value",
1012 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
1013 	"ipv6_proto",
1014 	"flex_item",
1015 	"hash_result",
1016 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1017 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1018 	"ipv4_proto",
1019 	"ipv6_flow_label", "ipv6_traffic_class",
1020 	"esp_spi", "esp_seq_num", "esp_proto",
1021 	"random",
1022 	"vxlan_last_rsvd",
1023 	NULL
1024 };
1025 
1026 static const char *const meter_colors[] = {
1027 	"green", "yellow", "red", "all", NULL
1028 };
1029 
1030 static const char *const table_insertion_types[] = {
1031 	"pattern", "index", "index_with_pattern", NULL
1032 };
1033 
1034 static const char *const table_hash_funcs[] = {
1035 	"default", "linear", "crc32", "crc16", NULL
1036 };
1037 
1038 #define RAW_IPSEC_CONFS_MAX_NUM 8
1039 
1040 /** Maximum number of subsequent tokens and arguments on the stack. */
1041 #define CTX_STACK_SIZE 16
1042 
1043 /** Parser context. */
1044 struct context {
1045 	/** Stack of subsequent token lists to process. */
1046 	const enum index *next[CTX_STACK_SIZE];
1047 	/** Arguments for stacked tokens. */
1048 	const void *args[CTX_STACK_SIZE];
1049 	enum index curr; /**< Current token index. */
1050 	enum index prev; /**< Index of the last token seen. */
1051 	int next_num; /**< Number of entries in next[]. */
1052 	int args_num; /**< Number of entries in args[]. */
1053 	uint32_t eol:1; /**< EOL has been detected. */
1054 	uint32_t last:1; /**< No more arguments. */
1055 	portid_t port; /**< Current port ID (for completions). */
1056 	uint32_t objdata; /**< Object-specific data. */
1057 	void *object; /**< Address of current object for relative offsets. */
1058 	void *objmask; /**< Object a full mask must be written to. */
1059 };
1060 
1061 /** Token argument. */
1062 struct arg {
1063 	uint32_t hton:1; /**< Use network byte ordering. */
1064 	uint32_t sign:1; /**< Value is signed. */
1065 	uint32_t bounded:1; /**< Value is bounded. */
1066 	uintmax_t min; /**< Minimum value if bounded. */
1067 	uintmax_t max; /**< Maximum value if bounded. */
1068 	uint32_t offset; /**< Relative offset from ctx->object. */
1069 	uint32_t size; /**< Field size. */
1070 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1071 };
1072 
1073 /** Parser token definition. */
1074 struct token {
1075 	/** Type displayed during completion (defaults to "TOKEN"). */
1076 	const char *type;
1077 	/** Help displayed during completion (defaults to token name). */
1078 	const char *help;
1079 	/** Private data used by parser functions. */
1080 	const void *priv;
1081 	/**
1082 	 * Lists of subsequent tokens to push on the stack. Each call to the
1083 	 * parser consumes the last entry of that stack.
1084 	 */
1085 	const enum index *const *next;
1086 	/** Arguments stack for subsequent tokens that need them. */
1087 	const struct arg *const *args;
1088 	/**
1089 	 * Token-processing callback, returns -1 in case of error, the
1090 	 * length of the matched string otherwise. If NULL, attempts to
1091 	 * match the token name.
1092 	 *
1093 	 * If buf is not NULL, the result should be stored in it according
1094 	 * to context. An error is returned if not large enough.
1095 	 */
1096 	int (*call)(struct context *ctx, const struct token *token,
1097 		    const char *str, unsigned int len,
1098 		    void *buf, unsigned int size);
1099 	/**
1100 	 * Callback that provides possible values for this token, used for
1101 	 * completion. Returns -1 in case of error, the number of possible
1102 	 * values otherwise. If NULL, the token name is used.
1103 	 *
1104 	 * If buf is not NULL, entry index ent is written to buf and the
1105 	 * full length of the entry is returned (same behavior as
1106 	 * snprintf()).
1107 	 */
1108 	int (*comp)(struct context *ctx, const struct token *token,
1109 		    unsigned int ent, char *buf, unsigned int size);
1110 	/** Mandatory token name, no default value. */
1111 	const char *name;
1112 };
1113 
1114 /** Static initializer for the next field. */
1115 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1116 
1117 /** Static initializer for a NEXT() entry. */
1118 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1119 
1120 /** Static initializer for the args field. */
1121 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1122 
1123 /** Static initializer for ARGS() to target a field. */
1124 #define ARGS_ENTRY(s, f) \
1125 	(&(const struct arg){ \
1126 		.offset = offsetof(s, f), \
1127 		.size = sizeof(((s *)0)->f), \
1128 	})
1129 
1130 /** Static initializer for ARGS() to target a bit-field. */
1131 #define ARGS_ENTRY_BF(s, f, b) \
1132 	(&(const struct arg){ \
1133 		.size = sizeof(s), \
1134 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1135 	})
1136 
1137 /** Static initializer for ARGS() to target a field with limits. */
1138 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1139 	(&(const struct arg){ \
1140 		.bounded = 1, \
1141 		.min = (i), \
1142 		.max = (a), \
1143 		.offset = offsetof(s, f), \
1144 		.size = sizeof(((s *)0)->f), \
1145 	})
1146 
1147 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1148 #define ARGS_ENTRY_MASK(s, f, m) \
1149 	(&(const struct arg){ \
1150 		.offset = offsetof(s, f), \
1151 		.size = sizeof(((s *)0)->f), \
1152 		.mask = (const void *)(m), \
1153 	})
1154 
1155 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1156 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1157 	(&(const struct arg){ \
1158 		.hton = 1, \
1159 		.offset = offsetof(s, f), \
1160 		.size = sizeof(((s *)0)->f), \
1161 		.mask = (const void *)(m), \
1162 	})
1163 
1164 /** Static initializer for ARGS() to target a pointer. */
1165 #define ARGS_ENTRY_PTR(s, f) \
1166 	(&(const struct arg){ \
1167 		.size = sizeof(*((s *)0)->f), \
1168 	})
1169 
1170 /** Static initializer for ARGS() with arbitrary offset and size. */
1171 #define ARGS_ENTRY_ARB(o, s) \
1172 	(&(const struct arg){ \
1173 		.offset = (o), \
1174 		.size = (s), \
1175 	})
1176 
1177 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1178 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1179 	(&(const struct arg){ \
1180 		.bounded = 1, \
1181 		.min = (i), \
1182 		.max = (a), \
1183 		.offset = (o), \
1184 		.size = (s), \
1185 	})
1186 
1187 /** Same as ARGS_ENTRY() using network byte ordering. */
1188 #define ARGS_ENTRY_HTON(s, f) \
1189 	(&(const struct arg){ \
1190 		.hton = 1, \
1191 		.offset = offsetof(s, f), \
1192 		.size = sizeof(((s *)0)->f), \
1193 	})
1194 
1195 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1196 #define ARG_ENTRY_HTON(s) \
1197 	(&(const struct arg){ \
1198 		.hton = 1, \
1199 		.offset = 0, \
1200 		.size = sizeof(s), \
1201 	})
1202 
1203 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1204 struct buffer {
1205 	enum index command; /**< Flow command. */
1206 	portid_t port; /**< Affected port ID. */
1207 	queueid_t queue; /** Async queue ID. */
1208 	bool postpone; /** Postpone async operation */
1209 	union {
1210 		struct {
1211 			struct rte_flow_port_attr port_attr;
1212 			uint32_t nb_queue;
1213 			struct rte_flow_queue_attr queue_attr;
1214 		} configure; /**< Configuration arguments. */
1215 		struct {
1216 			uint32_t *template_id;
1217 			uint32_t template_id_n;
1218 		} templ_destroy; /**< Template destroy arguments. */
1219 		struct {
1220 			uint32_t id;
1221 			struct rte_flow_template_table_attr attr;
1222 			uint32_t *pat_templ_id;
1223 			uint32_t pat_templ_id_n;
1224 			uint32_t *act_templ_id;
1225 			uint32_t act_templ_id_n;
1226 		} table; /**< Table arguments. */
1227 		struct {
1228 			uint32_t *table_id;
1229 			uint32_t table_id_n;
1230 		} table_destroy; /**< Template destroy arguments. */
1231 		struct {
1232 			uint32_t *action_id;
1233 			uint32_t action_id_n;
1234 		} ia_destroy; /**< Indirect action destroy arguments. */
1235 		struct {
1236 			uint32_t action_id;
1237 			enum rte_flow_query_update_mode qu_mode;
1238 		} ia; /* Indirect action query arguments */
1239 		struct {
1240 			uint32_t table_id;
1241 			uint32_t pat_templ_id;
1242 			uint32_t rule_id;
1243 			uint32_t act_templ_id;
1244 			struct rte_flow_attr attr;
1245 			struct tunnel_ops tunnel_ops;
1246 			uintptr_t user_id;
1247 			struct rte_flow_item *pattern;
1248 			struct rte_flow_action *actions;
1249 			struct rte_flow_action *masks;
1250 			uint32_t pattern_n;
1251 			uint32_t actions_n;
1252 			uint8_t *data;
1253 			enum rte_flow_encap_hash_field field;
1254 			uint8_t encap_hash;
1255 		} vc; /**< Validate/create arguments. */
1256 		struct {
1257 			uint64_t *rule;
1258 			uint64_t rule_n;
1259 			bool is_user_id;
1260 		} destroy; /**< Destroy arguments. */
1261 		struct {
1262 			char file[128];
1263 			bool mode;
1264 			uint64_t rule;
1265 			bool is_user_id;
1266 		} dump; /**< Dump arguments. */
1267 		struct {
1268 			uint64_t rule;
1269 			struct rte_flow_action action;
1270 			bool is_user_id;
1271 		} query; /**< Query arguments. */
1272 		struct {
1273 			uint32_t *group;
1274 			uint32_t group_n;
1275 		} list; /**< List arguments. */
1276 		struct {
1277 			int set;
1278 		} isolate; /**< Isolated mode arguments. */
1279 		struct {
1280 			int destroy;
1281 		} aged; /**< Aged arguments. */
1282 		struct {
1283 			uint32_t policy_id;
1284 		} policy;/**< Policy arguments. */
1285 		struct {
1286 			uint16_t token;
1287 			uintptr_t uintptr;
1288 			char filename[128];
1289 		} flex; /**< Flex arguments*/
1290 	} args; /**< Command arguments. */
1291 };
1292 
1293 /** Private data for pattern items. */
1294 struct parse_item_priv {
1295 	enum rte_flow_item_type type; /**< Item type. */
1296 	uint32_t size; /**< Size of item specification structure. */
1297 };
1298 
1299 #define PRIV_ITEM(t, s) \
1300 	(&(const struct parse_item_priv){ \
1301 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1302 		.size = s, \
1303 	})
1304 
1305 /** Private data for actions. */
1306 struct parse_action_priv {
1307 	enum rte_flow_action_type type; /**< Action type. */
1308 	uint32_t size; /**< Size of action configuration structure. */
1309 };
1310 
1311 #define PRIV_ACTION(t, s) \
1312 	(&(const struct parse_action_priv){ \
1313 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1314 		.size = s, \
1315 	})
1316 
1317 static const enum index next_flex_item[] = {
1318 	FLEX_ITEM_CREATE,
1319 	FLEX_ITEM_DESTROY,
1320 	ZERO,
1321 };
1322 
1323 static const enum index next_config_attr[] = {
1324 	CONFIG_QUEUES_NUMBER,
1325 	CONFIG_QUEUES_SIZE,
1326 	CONFIG_COUNTERS_NUMBER,
1327 	CONFIG_AGING_OBJECTS_NUMBER,
1328 	CONFIG_METERS_NUMBER,
1329 	CONFIG_CONN_TRACK_NUMBER,
1330 	CONFIG_QUOTAS_NUMBER,
1331 	CONFIG_FLAGS,
1332 	CONFIG_HOST_PORT,
1333 	END,
1334 	ZERO,
1335 };
1336 
1337 static const enum index next_pt_subcmd[] = {
1338 	PATTERN_TEMPLATE_CREATE,
1339 	PATTERN_TEMPLATE_DESTROY,
1340 	ZERO,
1341 };
1342 
1343 static const enum index next_pt_attr[] = {
1344 	PATTERN_TEMPLATE_CREATE_ID,
1345 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1346 	PATTERN_TEMPLATE_INGRESS,
1347 	PATTERN_TEMPLATE_EGRESS,
1348 	PATTERN_TEMPLATE_TRANSFER,
1349 	PATTERN_TEMPLATE_SPEC,
1350 	ZERO,
1351 };
1352 
1353 static const enum index next_pt_destroy_attr[] = {
1354 	PATTERN_TEMPLATE_DESTROY_ID,
1355 	END,
1356 	ZERO,
1357 };
1358 
1359 static const enum index next_at_subcmd[] = {
1360 	ACTIONS_TEMPLATE_CREATE,
1361 	ACTIONS_TEMPLATE_DESTROY,
1362 	ZERO,
1363 };
1364 
1365 static const enum index next_at_attr[] = {
1366 	ACTIONS_TEMPLATE_CREATE_ID,
1367 	ACTIONS_TEMPLATE_INGRESS,
1368 	ACTIONS_TEMPLATE_EGRESS,
1369 	ACTIONS_TEMPLATE_TRANSFER,
1370 	ACTIONS_TEMPLATE_SPEC,
1371 	ZERO,
1372 };
1373 
1374 static const enum index next_at_destroy_attr[] = {
1375 	ACTIONS_TEMPLATE_DESTROY_ID,
1376 	END,
1377 	ZERO,
1378 };
1379 
1380 static const enum index next_group_attr[] = {
1381 	GROUP_INGRESS,
1382 	GROUP_EGRESS,
1383 	GROUP_TRANSFER,
1384 	GROUP_SET_MISS_ACTIONS,
1385 	ZERO,
1386 };
1387 
1388 static const enum index next_table_subcmd[] = {
1389 	TABLE_CREATE,
1390 	TABLE_DESTROY,
1391 	TABLE_RESIZE,
1392 	TABLE_RESIZE_COMPLETE,
1393 	ZERO,
1394 };
1395 
1396 static const enum index next_table_attr[] = {
1397 	TABLE_CREATE_ID,
1398 	TABLE_GROUP,
1399 	TABLE_INSERTION_TYPE,
1400 	TABLE_HASH_FUNC,
1401 	TABLE_PRIORITY,
1402 	TABLE_INGRESS,
1403 	TABLE_EGRESS,
1404 	TABLE_TRANSFER,
1405 	TABLE_TRANSFER_WIRE_ORIG,
1406 	TABLE_TRANSFER_VPORT_ORIG,
1407 	TABLE_RESIZABLE,
1408 	TABLE_RULES_NUMBER,
1409 	TABLE_PATTERN_TEMPLATE,
1410 	TABLE_ACTIONS_TEMPLATE,
1411 	END,
1412 	ZERO,
1413 };
1414 
1415 static const enum index next_table_destroy_attr[] = {
1416 	TABLE_DESTROY_ID,
1417 	END,
1418 	ZERO,
1419 };
1420 
1421 static const enum index next_queue_subcmd[] = {
1422 	QUEUE_CREATE,
1423 	QUEUE_DESTROY,
1424 	QUEUE_FLOW_UPDATE_RESIZED,
1425 	QUEUE_UPDATE,
1426 	QUEUE_AGED,
1427 	QUEUE_INDIRECT_ACTION,
1428 	ZERO,
1429 };
1430 
1431 static const enum index next_queue_destroy_attr[] = {
1432 	QUEUE_DESTROY_ID,
1433 	END,
1434 	ZERO,
1435 };
1436 
1437 static const enum index next_qia_subcmd[] = {
1438 	QUEUE_INDIRECT_ACTION_CREATE,
1439 	QUEUE_INDIRECT_ACTION_UPDATE,
1440 	QUEUE_INDIRECT_ACTION_DESTROY,
1441 	QUEUE_INDIRECT_ACTION_QUERY,
1442 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1443 	ZERO,
1444 };
1445 
1446 static const enum index next_qia_create_attr[] = {
1447 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1448 	QUEUE_INDIRECT_ACTION_INGRESS,
1449 	QUEUE_INDIRECT_ACTION_EGRESS,
1450 	QUEUE_INDIRECT_ACTION_TRANSFER,
1451 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1452 	QUEUE_INDIRECT_ACTION_SPEC,
1453 	QUEUE_INDIRECT_ACTION_LIST,
1454 	ZERO,
1455 };
1456 
1457 static const enum index next_qia_update_attr[] = {
1458 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1459 	QUEUE_INDIRECT_ACTION_SPEC,
1460 	ZERO,
1461 };
1462 
1463 static const enum index next_qia_destroy_attr[] = {
1464 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1465 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1466 	END,
1467 	ZERO,
1468 };
1469 
1470 static const enum index next_qia_query_attr[] = {
1471 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1472 	END,
1473 	ZERO,
1474 };
1475 
1476 static const enum index next_ia_create_attr[] = {
1477 	INDIRECT_ACTION_CREATE_ID,
1478 	INDIRECT_ACTION_INGRESS,
1479 	INDIRECT_ACTION_EGRESS,
1480 	INDIRECT_ACTION_TRANSFER,
1481 	INDIRECT_ACTION_SPEC,
1482 	INDIRECT_ACTION_LIST,
1483 	INDIRECT_ACTION_FLOW_CONF,
1484 	ZERO,
1485 };
1486 
1487 static const enum index next_ia[] = {
1488 	INDIRECT_ACTION_ID2PTR,
1489 	ACTION_NEXT,
1490 	ZERO
1491 };
1492 
1493 static const enum index next_ial[] = {
1494 	ACTION_INDIRECT_LIST_HANDLE,
1495 	ACTION_INDIRECT_LIST_CONF,
1496 	ACTION_NEXT,
1497 	ZERO
1498 };
1499 
1500 static const enum index next_qia_qu_attr[] = {
1501 	QUEUE_INDIRECT_ACTION_QU_MODE,
1502 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1503 	INDIRECT_ACTION_SPEC,
1504 	ZERO
1505 };
1506 
1507 static const enum index next_ia_qu_attr[] = {
1508 	INDIRECT_ACTION_QU_MODE,
1509 	INDIRECT_ACTION_SPEC,
1510 	ZERO
1511 };
1512 
1513 static const enum index next_dump_subcmd[] = {
1514 	DUMP_ALL,
1515 	DUMP_ONE,
1516 	DUMP_IS_USER_ID,
1517 	ZERO,
1518 };
1519 
1520 static const enum index next_ia_subcmd[] = {
1521 	INDIRECT_ACTION_CREATE,
1522 	INDIRECT_ACTION_UPDATE,
1523 	INDIRECT_ACTION_DESTROY,
1524 	INDIRECT_ACTION_QUERY,
1525 	INDIRECT_ACTION_QUERY_UPDATE,
1526 	ZERO,
1527 };
1528 
1529 static const enum index next_vc_attr[] = {
1530 	VC_GROUP,
1531 	VC_PRIORITY,
1532 	VC_INGRESS,
1533 	VC_EGRESS,
1534 	VC_TRANSFER,
1535 	VC_TUNNEL_SET,
1536 	VC_TUNNEL_MATCH,
1537 	VC_USER_ID,
1538 	ITEM_PATTERN,
1539 	ZERO,
1540 };
1541 
1542 static const enum index next_destroy_attr[] = {
1543 	DESTROY_RULE,
1544 	DESTROY_IS_USER_ID,
1545 	END,
1546 	ZERO,
1547 };
1548 
1549 static const enum index next_dump_attr[] = {
1550 	COMMON_FILE_PATH,
1551 	END,
1552 	ZERO,
1553 };
1554 
1555 static const enum index next_query_attr[] = {
1556 	QUERY_IS_USER_ID,
1557 	END,
1558 	ZERO,
1559 };
1560 
1561 static const enum index next_list_attr[] = {
1562 	LIST_GROUP,
1563 	END,
1564 	ZERO,
1565 };
1566 
1567 static const enum index next_aged_attr[] = {
1568 	AGED_DESTROY,
1569 	END,
1570 	ZERO,
1571 };
1572 
1573 static const enum index next_ia_destroy_attr[] = {
1574 	INDIRECT_ACTION_DESTROY_ID,
1575 	END,
1576 	ZERO,
1577 };
1578 
1579 static const enum index next_async_insert_subcmd[] = {
1580 	QUEUE_PATTERN_TEMPLATE,
1581 	QUEUE_RULE_ID,
1582 	ZERO,
1583 };
1584 
1585 static const enum index next_async_pattern_subcmd[] = {
1586 	QUEUE_PATTERN_TEMPLATE,
1587 	QUEUE_ACTIONS_TEMPLATE,
1588 	ZERO,
1589 };
1590 
1591 static const enum index item_param[] = {
1592 	ITEM_PARAM_IS,
1593 	ITEM_PARAM_SPEC,
1594 	ITEM_PARAM_LAST,
1595 	ITEM_PARAM_MASK,
1596 	ITEM_PARAM_PREFIX,
1597 	ZERO,
1598 };
1599 
1600 static const enum index next_item[] = {
1601 	ITEM_END,
1602 	ITEM_VOID,
1603 	ITEM_INVERT,
1604 	ITEM_ANY,
1605 	ITEM_PORT_ID,
1606 	ITEM_MARK,
1607 	ITEM_RAW,
1608 	ITEM_ETH,
1609 	ITEM_VLAN,
1610 	ITEM_IPV4,
1611 	ITEM_IPV6,
1612 	ITEM_ICMP,
1613 	ITEM_UDP,
1614 	ITEM_TCP,
1615 	ITEM_SCTP,
1616 	ITEM_VXLAN,
1617 	ITEM_E_TAG,
1618 	ITEM_NVGRE,
1619 	ITEM_MPLS,
1620 	ITEM_GRE,
1621 	ITEM_FUZZY,
1622 	ITEM_GTP,
1623 	ITEM_GTPC,
1624 	ITEM_GTPU,
1625 	ITEM_GENEVE,
1626 	ITEM_VXLAN_GPE,
1627 	ITEM_ARP_ETH_IPV4,
1628 	ITEM_IPV6_EXT,
1629 	ITEM_IPV6_FRAG_EXT,
1630 	ITEM_IPV6_ROUTING_EXT,
1631 	ITEM_ICMP6,
1632 	ITEM_ICMP6_ECHO_REQUEST,
1633 	ITEM_ICMP6_ECHO_REPLY,
1634 	ITEM_ICMP6_ND_NS,
1635 	ITEM_ICMP6_ND_NA,
1636 	ITEM_ICMP6_ND_OPT,
1637 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1638 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1639 	ITEM_META,
1640 	ITEM_RANDOM,
1641 	ITEM_GRE_KEY,
1642 	ITEM_GRE_OPTION,
1643 	ITEM_GTP_PSC,
1644 	ITEM_PPPOES,
1645 	ITEM_PPPOED,
1646 	ITEM_PPPOE_PROTO_ID,
1647 	ITEM_HIGIG2,
1648 	ITEM_TAG,
1649 	ITEM_L2TPV3OIP,
1650 	ITEM_ESP,
1651 	ITEM_AH,
1652 	ITEM_PFCP,
1653 	ITEM_ECPRI,
1654 	ITEM_GENEVE_OPT,
1655 	ITEM_INTEGRITY,
1656 	ITEM_CONNTRACK,
1657 	ITEM_PORT_REPRESENTOR,
1658 	ITEM_REPRESENTED_PORT,
1659 	ITEM_FLEX,
1660 	ITEM_L2TPV2,
1661 	ITEM_PPP,
1662 	ITEM_METER,
1663 	ITEM_QUOTA,
1664 	ITEM_AGGR_AFFINITY,
1665 	ITEM_TX_QUEUE,
1666 	ITEM_IB_BTH,
1667 	ITEM_PTYPE,
1668 	ITEM_NSH,
1669 	ITEM_COMPARE,
1670 	END_SET,
1671 	ZERO,
1672 };
1673 
1674 static const enum index item_fuzzy[] = {
1675 	ITEM_FUZZY_THRESH,
1676 	ITEM_NEXT,
1677 	ZERO,
1678 };
1679 
1680 static const enum index item_any[] = {
1681 	ITEM_ANY_NUM,
1682 	ITEM_NEXT,
1683 	ZERO,
1684 };
1685 
1686 static const enum index item_port_id[] = {
1687 	ITEM_PORT_ID_ID,
1688 	ITEM_NEXT,
1689 	ZERO,
1690 };
1691 
1692 static const enum index item_mark[] = {
1693 	ITEM_MARK_ID,
1694 	ITEM_NEXT,
1695 	ZERO,
1696 };
1697 
1698 static const enum index item_raw[] = {
1699 	ITEM_RAW_RELATIVE,
1700 	ITEM_RAW_SEARCH,
1701 	ITEM_RAW_OFFSET,
1702 	ITEM_RAW_LIMIT,
1703 	ITEM_RAW_PATTERN,
1704 	ITEM_RAW_PATTERN_HEX,
1705 	ITEM_NEXT,
1706 	ZERO,
1707 };
1708 
1709 static const enum index item_eth[] = {
1710 	ITEM_ETH_DST,
1711 	ITEM_ETH_SRC,
1712 	ITEM_ETH_TYPE,
1713 	ITEM_ETH_HAS_VLAN,
1714 	ITEM_NEXT,
1715 	ZERO,
1716 };
1717 
1718 static const enum index item_vlan[] = {
1719 	ITEM_VLAN_TCI,
1720 	ITEM_VLAN_PCP,
1721 	ITEM_VLAN_DEI,
1722 	ITEM_VLAN_VID,
1723 	ITEM_VLAN_INNER_TYPE,
1724 	ITEM_VLAN_HAS_MORE_VLAN,
1725 	ITEM_NEXT,
1726 	ZERO,
1727 };
1728 
1729 static const enum index item_ipv4[] = {
1730 	ITEM_IPV4_VER_IHL,
1731 	ITEM_IPV4_TOS,
1732 	ITEM_IPV4_LENGTH,
1733 	ITEM_IPV4_ID,
1734 	ITEM_IPV4_FRAGMENT_OFFSET,
1735 	ITEM_IPV4_TTL,
1736 	ITEM_IPV4_PROTO,
1737 	ITEM_IPV4_SRC,
1738 	ITEM_IPV4_DST,
1739 	ITEM_NEXT,
1740 	ZERO,
1741 };
1742 
1743 static const enum index item_ipv6[] = {
1744 	ITEM_IPV6_TC,
1745 	ITEM_IPV6_FLOW,
1746 	ITEM_IPV6_LEN,
1747 	ITEM_IPV6_PROTO,
1748 	ITEM_IPV6_HOP,
1749 	ITEM_IPV6_SRC,
1750 	ITEM_IPV6_DST,
1751 	ITEM_IPV6_HAS_FRAG_EXT,
1752 	ITEM_IPV6_ROUTING_EXT,
1753 	ITEM_NEXT,
1754 	ZERO,
1755 };
1756 
1757 static const enum index item_ipv6_routing_ext[] = {
1758 	ITEM_IPV6_ROUTING_EXT_TYPE,
1759 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1760 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1761 	ITEM_NEXT,
1762 	ZERO,
1763 };
1764 
1765 static const enum index item_icmp[] = {
1766 	ITEM_ICMP_TYPE,
1767 	ITEM_ICMP_CODE,
1768 	ITEM_ICMP_IDENT,
1769 	ITEM_ICMP_SEQ,
1770 	ITEM_NEXT,
1771 	ZERO,
1772 };
1773 
1774 static const enum index item_udp[] = {
1775 	ITEM_UDP_SRC,
1776 	ITEM_UDP_DST,
1777 	ITEM_NEXT,
1778 	ZERO,
1779 };
1780 
1781 static const enum index item_tcp[] = {
1782 	ITEM_TCP_SRC,
1783 	ITEM_TCP_DST,
1784 	ITEM_TCP_FLAGS,
1785 	ITEM_NEXT,
1786 	ZERO,
1787 };
1788 
1789 static const enum index item_sctp[] = {
1790 	ITEM_SCTP_SRC,
1791 	ITEM_SCTP_DST,
1792 	ITEM_SCTP_TAG,
1793 	ITEM_SCTP_CKSUM,
1794 	ITEM_NEXT,
1795 	ZERO,
1796 };
1797 
1798 static const enum index item_vxlan[] = {
1799 	ITEM_VXLAN_VNI,
1800 	ITEM_VXLAN_FLAG_G,
1801 	ITEM_VXLAN_FLAG_VER,
1802 	ITEM_VXLAN_FLAG_I,
1803 	ITEM_VXLAN_FLAG_P,
1804 	ITEM_VXLAN_FLAG_B,
1805 	ITEM_VXLAN_FLAG_O,
1806 	ITEM_VXLAN_FLAG_D,
1807 	ITEM_VXLAN_FLAG_A,
1808 	ITEM_VXLAN_GBP_ID,
1809 	ITEM_VXLAN_GPE_PROTO,
1810 	ITEM_VXLAN_FIRST_RSVD,
1811 	ITEM_VXLAN_SECND_RSVD,
1812 	ITEM_VXLAN_THIRD_RSVD,
1813 	ITEM_VXLAN_LAST_RSVD,
1814 	ITEM_NEXT,
1815 	ZERO,
1816 };
1817 
1818 static const enum index item_e_tag[] = {
1819 	ITEM_E_TAG_GRP_ECID_B,
1820 	ITEM_NEXT,
1821 	ZERO,
1822 };
1823 
1824 static const enum index item_nvgre[] = {
1825 	ITEM_NVGRE_TNI,
1826 	ITEM_NEXT,
1827 	ZERO,
1828 };
1829 
1830 static const enum index item_mpls[] = {
1831 	ITEM_MPLS_LABEL,
1832 	ITEM_MPLS_TC,
1833 	ITEM_MPLS_S,
1834 	ITEM_MPLS_TTL,
1835 	ITEM_NEXT,
1836 	ZERO,
1837 };
1838 
1839 static const enum index item_gre[] = {
1840 	ITEM_GRE_PROTO,
1841 	ITEM_GRE_C_RSVD0_VER,
1842 	ITEM_GRE_C_BIT,
1843 	ITEM_GRE_K_BIT,
1844 	ITEM_GRE_S_BIT,
1845 	ITEM_NEXT,
1846 	ZERO,
1847 };
1848 
1849 static const enum index item_gre_key[] = {
1850 	ITEM_GRE_KEY_VALUE,
1851 	ITEM_NEXT,
1852 	ZERO,
1853 };
1854 
1855 static const enum index item_gre_option[] = {
1856 	ITEM_GRE_OPTION_CHECKSUM,
1857 	ITEM_GRE_OPTION_KEY,
1858 	ITEM_GRE_OPTION_SEQUENCE,
1859 	ITEM_NEXT,
1860 	ZERO,
1861 };
1862 
1863 static const enum index item_gtp[] = {
1864 	ITEM_GTP_FLAGS,
1865 	ITEM_GTP_MSG_TYPE,
1866 	ITEM_GTP_TEID,
1867 	ITEM_NEXT,
1868 	ZERO,
1869 };
1870 
1871 static const enum index item_geneve[] = {
1872 	ITEM_GENEVE_VNI,
1873 	ITEM_GENEVE_PROTO,
1874 	ITEM_GENEVE_OPTLEN,
1875 	ITEM_NEXT,
1876 	ZERO,
1877 };
1878 
1879 static const enum index item_vxlan_gpe[] = {
1880 	ITEM_VXLAN_GPE_VNI,
1881 	ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR,
1882 	ITEM_VXLAN_GPE_FLAGS,
1883 	ITEM_VXLAN_GPE_RSVD0,
1884 	ITEM_VXLAN_GPE_RSVD1,
1885 	ITEM_NEXT,
1886 	ZERO,
1887 };
1888 
1889 static const enum index item_arp_eth_ipv4[] = {
1890 	ITEM_ARP_ETH_IPV4_SHA,
1891 	ITEM_ARP_ETH_IPV4_SPA,
1892 	ITEM_ARP_ETH_IPV4_THA,
1893 	ITEM_ARP_ETH_IPV4_TPA,
1894 	ITEM_NEXT,
1895 	ZERO,
1896 };
1897 
1898 static const enum index item_ipv6_ext[] = {
1899 	ITEM_IPV6_EXT_NEXT_HDR,
1900 	ITEM_NEXT,
1901 	ZERO,
1902 };
1903 
1904 static const enum index item_ipv6_frag_ext[] = {
1905 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1906 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1907 	ITEM_IPV6_FRAG_EXT_ID,
1908 	ITEM_NEXT,
1909 	ZERO,
1910 };
1911 
1912 static const enum index item_icmp6[] = {
1913 	ITEM_ICMP6_TYPE,
1914 	ITEM_ICMP6_CODE,
1915 	ITEM_NEXT,
1916 	ZERO,
1917 };
1918 
1919 static const enum index item_icmp6_echo_request[] = {
1920 	ITEM_ICMP6_ECHO_REQUEST_ID,
1921 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1922 	ITEM_NEXT,
1923 	ZERO,
1924 };
1925 
1926 static const enum index item_icmp6_echo_reply[] = {
1927 	ITEM_ICMP6_ECHO_REPLY_ID,
1928 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1929 	ITEM_NEXT,
1930 	ZERO,
1931 };
1932 
1933 static const enum index item_icmp6_nd_ns[] = {
1934 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1935 	ITEM_NEXT,
1936 	ZERO,
1937 };
1938 
1939 static const enum index item_icmp6_nd_na[] = {
1940 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1941 	ITEM_NEXT,
1942 	ZERO,
1943 };
1944 
1945 static const enum index item_icmp6_nd_opt[] = {
1946 	ITEM_ICMP6_ND_OPT_TYPE,
1947 	ITEM_NEXT,
1948 	ZERO,
1949 };
1950 
1951 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1952 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1953 	ITEM_NEXT,
1954 	ZERO,
1955 };
1956 
1957 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1958 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1959 	ITEM_NEXT,
1960 	ZERO,
1961 };
1962 
1963 static const enum index item_meta[] = {
1964 	ITEM_META_DATA,
1965 	ITEM_NEXT,
1966 	ZERO,
1967 };
1968 
1969 static const enum index item_random[] = {
1970 	ITEM_RANDOM_VALUE,
1971 	ITEM_NEXT,
1972 	ZERO,
1973 };
1974 
1975 static const enum index item_gtp_psc[] = {
1976 	ITEM_GTP_PSC_QFI,
1977 	ITEM_GTP_PSC_PDU_T,
1978 	ITEM_NEXT,
1979 	ZERO,
1980 };
1981 
1982 static const enum index item_pppoed[] = {
1983 	ITEM_PPPOE_SEID,
1984 	ITEM_NEXT,
1985 	ZERO,
1986 };
1987 
1988 static const enum index item_pppoes[] = {
1989 	ITEM_PPPOE_SEID,
1990 	ITEM_NEXT,
1991 	ZERO,
1992 };
1993 
1994 static const enum index item_pppoe_proto_id[] = {
1995 	ITEM_NEXT,
1996 	ZERO,
1997 };
1998 
1999 static const enum index item_higig2[] = {
2000 	ITEM_HIGIG2_CLASSIFICATION,
2001 	ITEM_HIGIG2_VID,
2002 	ITEM_NEXT,
2003 	ZERO,
2004 };
2005 
2006 static const enum index item_esp[] = {
2007 	ITEM_ESP_SPI,
2008 	ITEM_NEXT,
2009 	ZERO,
2010 };
2011 
2012 static const enum index item_ah[] = {
2013 	ITEM_AH_SPI,
2014 	ITEM_NEXT,
2015 	ZERO,
2016 };
2017 
2018 static const enum index item_pfcp[] = {
2019 	ITEM_PFCP_S_FIELD,
2020 	ITEM_PFCP_SEID,
2021 	ITEM_NEXT,
2022 	ZERO,
2023 };
2024 
2025 static const enum index next_set_raw[] = {
2026 	SET_RAW_INDEX,
2027 	ITEM_ETH,
2028 	ZERO,
2029 };
2030 
2031 static const enum index item_tag[] = {
2032 	ITEM_TAG_DATA,
2033 	ITEM_TAG_INDEX,
2034 	ITEM_NEXT,
2035 	ZERO,
2036 };
2037 
2038 static const enum index item_l2tpv3oip[] = {
2039 	ITEM_L2TPV3OIP_SESSION_ID,
2040 	ITEM_NEXT,
2041 	ZERO,
2042 };
2043 
2044 static const enum index item_ecpri[] = {
2045 	ITEM_ECPRI_COMMON,
2046 	ITEM_NEXT,
2047 	ZERO,
2048 };
2049 
2050 static const enum index item_ecpri_common[] = {
2051 	ITEM_ECPRI_COMMON_TYPE,
2052 	ZERO,
2053 };
2054 
2055 static const enum index item_ecpri_common_type[] = {
2056 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2057 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2058 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2059 	ZERO,
2060 };
2061 
2062 static const enum index item_geneve_opt[] = {
2063 	ITEM_GENEVE_OPT_CLASS,
2064 	ITEM_GENEVE_OPT_TYPE,
2065 	ITEM_GENEVE_OPT_LENGTH,
2066 	ITEM_GENEVE_OPT_DATA,
2067 	ITEM_NEXT,
2068 	ZERO,
2069 };
2070 
2071 static const enum index item_integrity[] = {
2072 	ITEM_INTEGRITY_LEVEL,
2073 	ITEM_INTEGRITY_VALUE,
2074 	ZERO,
2075 };
2076 
2077 static const enum index item_integrity_lv[] = {
2078 	ITEM_INTEGRITY_LEVEL,
2079 	ITEM_INTEGRITY_VALUE,
2080 	ITEM_NEXT,
2081 	ZERO,
2082 };
2083 
2084 static const enum index item_port_representor[] = {
2085 	ITEM_PORT_REPRESENTOR_PORT_ID,
2086 	ITEM_NEXT,
2087 	ZERO,
2088 };
2089 
2090 static const enum index item_represented_port[] = {
2091 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2092 	ITEM_NEXT,
2093 	ZERO,
2094 };
2095 
2096 static const enum index item_flex[] = {
2097 	ITEM_FLEX_PATTERN_HANDLE,
2098 	ITEM_FLEX_ITEM_HANDLE,
2099 	ITEM_NEXT,
2100 	ZERO,
2101 };
2102 
2103 static const enum index item_l2tpv2[] = {
2104 	ITEM_L2TPV2_TYPE,
2105 	ITEM_NEXT,
2106 	ZERO,
2107 };
2108 
2109 static const enum index item_l2tpv2_type[] = {
2110 	ITEM_L2TPV2_TYPE_DATA,
2111 	ITEM_L2TPV2_TYPE_DATA_L,
2112 	ITEM_L2TPV2_TYPE_DATA_S,
2113 	ITEM_L2TPV2_TYPE_DATA_O,
2114 	ITEM_L2TPV2_TYPE_DATA_L_S,
2115 	ITEM_L2TPV2_TYPE_CTRL,
2116 	ZERO,
2117 };
2118 
2119 static const enum index item_l2tpv2_type_data[] = {
2120 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2121 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2122 	ITEM_NEXT,
2123 	ZERO,
2124 };
2125 
2126 static const enum index item_l2tpv2_type_data_l[] = {
2127 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2128 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2129 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2130 	ITEM_NEXT,
2131 	ZERO,
2132 };
2133 
2134 static const enum index item_l2tpv2_type_data_s[] = {
2135 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2136 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2137 	ITEM_L2TPV2_MSG_DATA_S_NS,
2138 	ITEM_L2TPV2_MSG_DATA_S_NR,
2139 	ITEM_NEXT,
2140 	ZERO,
2141 };
2142 
2143 static const enum index item_l2tpv2_type_data_o[] = {
2144 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2145 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2146 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2147 	ITEM_NEXT,
2148 	ZERO,
2149 };
2150 
2151 static const enum index item_l2tpv2_type_data_l_s[] = {
2152 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2153 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2154 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2155 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2156 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2157 	ITEM_NEXT,
2158 	ZERO,
2159 };
2160 
2161 static const enum index item_l2tpv2_type_ctrl[] = {
2162 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2163 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2164 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2165 	ITEM_L2TPV2_MSG_CTRL_NS,
2166 	ITEM_L2TPV2_MSG_CTRL_NR,
2167 	ITEM_NEXT,
2168 	ZERO,
2169 };
2170 
2171 static const enum index item_ppp[] = {
2172 	ITEM_PPP_ADDR,
2173 	ITEM_PPP_CTRL,
2174 	ITEM_PPP_PROTO_ID,
2175 	ITEM_NEXT,
2176 	ZERO,
2177 };
2178 
2179 static const enum index item_meter[] = {
2180 	ITEM_METER_COLOR,
2181 	ITEM_NEXT,
2182 	ZERO,
2183 };
2184 
2185 static const enum index item_quota[] = {
2186 	ITEM_QUOTA_STATE,
2187 	ITEM_NEXT,
2188 	ZERO,
2189 };
2190 
2191 static const enum index item_aggr_affinity[] = {
2192 	ITEM_AGGR_AFFINITY_VALUE,
2193 	ITEM_NEXT,
2194 	ZERO,
2195 };
2196 
2197 static const enum index item_tx_queue[] = {
2198 	ITEM_TX_QUEUE_VALUE,
2199 	ITEM_NEXT,
2200 	ZERO,
2201 };
2202 
2203 static const enum index item_ib_bth[] = {
2204 	ITEM_IB_BTH_OPCODE,
2205 	ITEM_IB_BTH_PKEY,
2206 	ITEM_IB_BTH_DST_QPN,
2207 	ITEM_IB_BTH_PSN,
2208 	ITEM_NEXT,
2209 	ZERO,
2210 };
2211 
2212 static const enum index item_ptype[] = {
2213 	ITEM_PTYPE_VALUE,
2214 	ITEM_NEXT,
2215 	ZERO,
2216 };
2217 
2218 static const enum index item_nsh[] = {
2219 	ITEM_NEXT,
2220 	ZERO,
2221 };
2222 
2223 static const enum index item_compare_field[] = {
2224 	ITEM_COMPARE_OP,
2225 	ITEM_COMPARE_FIELD_A_TYPE,
2226 	ITEM_COMPARE_FIELD_B_TYPE,
2227 	ITEM_NEXT,
2228 	ZERO,
2229 };
2230 
2231 static const enum index compare_field_a[] = {
2232 	ITEM_COMPARE_FIELD_A_TYPE,
2233 	ITEM_COMPARE_FIELD_A_LEVEL,
2234 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2235 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2236 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2237 	ITEM_COMPARE_FIELD_A_OFFSET,
2238 	ITEM_COMPARE_FIELD_B_TYPE,
2239 	ZERO,
2240 };
2241 
2242 static const enum index compare_field_b[] = {
2243 	ITEM_COMPARE_FIELD_B_TYPE,
2244 	ITEM_COMPARE_FIELD_B_LEVEL,
2245 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2246 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2247 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2248 	ITEM_COMPARE_FIELD_B_OFFSET,
2249 	ITEM_COMPARE_FIELD_B_VALUE,
2250 	ITEM_COMPARE_FIELD_B_POINTER,
2251 	ITEM_COMPARE_FIELD_WIDTH,
2252 	ZERO,
2253 };
2254 
2255 static const enum index next_action[] = {
2256 	ACTION_END,
2257 	ACTION_VOID,
2258 	ACTION_PASSTHRU,
2259 	ACTION_SKIP_CMAN,
2260 	ACTION_JUMP,
2261 	ACTION_MARK,
2262 	ACTION_FLAG,
2263 	ACTION_QUEUE,
2264 	ACTION_DROP,
2265 	ACTION_COUNT,
2266 	ACTION_RSS,
2267 	ACTION_PF,
2268 	ACTION_VF,
2269 	ACTION_PORT_ID,
2270 	ACTION_METER,
2271 	ACTION_METER_COLOR,
2272 	ACTION_METER_MARK,
2273 	ACTION_OF_DEC_NW_TTL,
2274 	ACTION_OF_POP_VLAN,
2275 	ACTION_OF_PUSH_VLAN,
2276 	ACTION_OF_SET_VLAN_VID,
2277 	ACTION_OF_SET_VLAN_PCP,
2278 	ACTION_OF_POP_MPLS,
2279 	ACTION_OF_PUSH_MPLS,
2280 	ACTION_VXLAN_ENCAP,
2281 	ACTION_VXLAN_DECAP,
2282 	ACTION_NVGRE_ENCAP,
2283 	ACTION_NVGRE_DECAP,
2284 	ACTION_L2_ENCAP,
2285 	ACTION_L2_DECAP,
2286 	ACTION_MPLSOGRE_ENCAP,
2287 	ACTION_MPLSOGRE_DECAP,
2288 	ACTION_MPLSOUDP_ENCAP,
2289 	ACTION_MPLSOUDP_DECAP,
2290 	ACTION_SET_IPV4_SRC,
2291 	ACTION_SET_IPV4_DST,
2292 	ACTION_SET_IPV6_SRC,
2293 	ACTION_SET_IPV6_DST,
2294 	ACTION_SET_TP_SRC,
2295 	ACTION_SET_TP_DST,
2296 	ACTION_MAC_SWAP,
2297 	ACTION_DEC_TTL,
2298 	ACTION_SET_TTL,
2299 	ACTION_SET_MAC_SRC,
2300 	ACTION_SET_MAC_DST,
2301 	ACTION_INC_TCP_SEQ,
2302 	ACTION_DEC_TCP_SEQ,
2303 	ACTION_INC_TCP_ACK,
2304 	ACTION_DEC_TCP_ACK,
2305 	ACTION_RAW_ENCAP,
2306 	ACTION_RAW_DECAP,
2307 	ACTION_SET_TAG,
2308 	ACTION_SET_META,
2309 	ACTION_SET_IPV4_DSCP,
2310 	ACTION_SET_IPV6_DSCP,
2311 	ACTION_AGE,
2312 	ACTION_AGE_UPDATE,
2313 	ACTION_SAMPLE,
2314 	ACTION_INDIRECT,
2315 	ACTION_INDIRECT_LIST,
2316 	ACTION_SHARED_INDIRECT,
2317 	ACTION_MODIFY_FIELD,
2318 	ACTION_CONNTRACK,
2319 	ACTION_CONNTRACK_UPDATE,
2320 	ACTION_PORT_REPRESENTOR,
2321 	ACTION_REPRESENTED_PORT,
2322 	ACTION_SEND_TO_KERNEL,
2323 	ACTION_QUOTA_CREATE,
2324 	ACTION_QUOTA_QU,
2325 	ACTION_IPV6_EXT_REMOVE,
2326 	ACTION_IPV6_EXT_PUSH,
2327 	ACTION_NAT64,
2328 	ACTION_JUMP_TO_TABLE_INDEX,
2329 	ZERO,
2330 };
2331 
2332 static const enum index action_quota_create[] = {
2333 	ACTION_QUOTA_CREATE_LIMIT,
2334 	ACTION_QUOTA_CREATE_MODE,
2335 	ACTION_NEXT,
2336 	ZERO
2337 };
2338 
2339 static const enum index action_quota_update[] = {
2340 	ACTION_QUOTA_QU_LIMIT,
2341 	ACTION_QUOTA_QU_UPDATE_OP,
2342 	ACTION_NEXT,
2343 	ZERO
2344 };
2345 
2346 static const enum index action_mark[] = {
2347 	ACTION_MARK_ID,
2348 	ACTION_NEXT,
2349 	ZERO,
2350 };
2351 
2352 static const enum index action_queue[] = {
2353 	ACTION_QUEUE_INDEX,
2354 	ACTION_NEXT,
2355 	ZERO,
2356 };
2357 
2358 static const enum index action_count[] = {
2359 	ACTION_COUNT_ID,
2360 	ACTION_NEXT,
2361 	ZERO,
2362 };
2363 
2364 static const enum index action_rss[] = {
2365 	ACTION_RSS_FUNC,
2366 	ACTION_RSS_LEVEL,
2367 	ACTION_RSS_TYPES,
2368 	ACTION_RSS_KEY,
2369 	ACTION_RSS_KEY_LEN,
2370 	ACTION_RSS_QUEUES,
2371 	ACTION_NEXT,
2372 	ZERO,
2373 };
2374 
2375 static const enum index action_vf[] = {
2376 	ACTION_VF_ORIGINAL,
2377 	ACTION_VF_ID,
2378 	ACTION_NEXT,
2379 	ZERO,
2380 };
2381 
2382 static const enum index action_port_id[] = {
2383 	ACTION_PORT_ID_ORIGINAL,
2384 	ACTION_PORT_ID_ID,
2385 	ACTION_NEXT,
2386 	ZERO,
2387 };
2388 
2389 static const enum index action_meter[] = {
2390 	ACTION_METER_ID,
2391 	ACTION_NEXT,
2392 	ZERO,
2393 };
2394 
2395 static const enum index action_meter_color[] = {
2396 	ACTION_METER_COLOR_TYPE,
2397 	ACTION_NEXT,
2398 	ZERO,
2399 };
2400 
2401 static const enum index action_meter_mark[] = {
2402 	ACTION_METER_PROFILE,
2403 	ACTION_METER_POLICY,
2404 	ACTION_METER_COLOR_MODE,
2405 	ACTION_METER_STATE,
2406 	ACTION_NEXT,
2407 	ZERO,
2408 };
2409 
2410 static const enum index action_of_push_vlan[] = {
2411 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2412 	ACTION_NEXT,
2413 	ZERO,
2414 };
2415 
2416 static const enum index action_of_set_vlan_vid[] = {
2417 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2418 	ACTION_NEXT,
2419 	ZERO,
2420 };
2421 
2422 static const enum index action_of_set_vlan_pcp[] = {
2423 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2424 	ACTION_NEXT,
2425 	ZERO,
2426 };
2427 
2428 static const enum index action_of_pop_mpls[] = {
2429 	ACTION_OF_POP_MPLS_ETHERTYPE,
2430 	ACTION_NEXT,
2431 	ZERO,
2432 };
2433 
2434 static const enum index action_of_push_mpls[] = {
2435 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2436 	ACTION_NEXT,
2437 	ZERO,
2438 };
2439 
2440 static const enum index action_set_ipv4_src[] = {
2441 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2442 	ACTION_NEXT,
2443 	ZERO,
2444 };
2445 
2446 static const enum index action_set_mac_src[] = {
2447 	ACTION_SET_MAC_SRC_MAC_SRC,
2448 	ACTION_NEXT,
2449 	ZERO,
2450 };
2451 
2452 static const enum index action_set_ipv4_dst[] = {
2453 	ACTION_SET_IPV4_DST_IPV4_DST,
2454 	ACTION_NEXT,
2455 	ZERO,
2456 };
2457 
2458 static const enum index action_set_ipv6_src[] = {
2459 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2460 	ACTION_NEXT,
2461 	ZERO,
2462 };
2463 
2464 static const enum index action_set_ipv6_dst[] = {
2465 	ACTION_SET_IPV6_DST_IPV6_DST,
2466 	ACTION_NEXT,
2467 	ZERO,
2468 };
2469 
2470 static const enum index action_set_tp_src[] = {
2471 	ACTION_SET_TP_SRC_TP_SRC,
2472 	ACTION_NEXT,
2473 	ZERO,
2474 };
2475 
2476 static const enum index action_set_tp_dst[] = {
2477 	ACTION_SET_TP_DST_TP_DST,
2478 	ACTION_NEXT,
2479 	ZERO,
2480 };
2481 
2482 static const enum index action_set_ttl[] = {
2483 	ACTION_SET_TTL_TTL,
2484 	ACTION_NEXT,
2485 	ZERO,
2486 };
2487 
2488 static const enum index action_jump[] = {
2489 	ACTION_JUMP_GROUP,
2490 	ACTION_NEXT,
2491 	ZERO,
2492 };
2493 
2494 static const enum index action_set_mac_dst[] = {
2495 	ACTION_SET_MAC_DST_MAC_DST,
2496 	ACTION_NEXT,
2497 	ZERO,
2498 };
2499 
2500 static const enum index action_inc_tcp_seq[] = {
2501 	ACTION_INC_TCP_SEQ_VALUE,
2502 	ACTION_NEXT,
2503 	ZERO,
2504 };
2505 
2506 static const enum index action_dec_tcp_seq[] = {
2507 	ACTION_DEC_TCP_SEQ_VALUE,
2508 	ACTION_NEXT,
2509 	ZERO,
2510 };
2511 
2512 static const enum index action_inc_tcp_ack[] = {
2513 	ACTION_INC_TCP_ACK_VALUE,
2514 	ACTION_NEXT,
2515 	ZERO,
2516 };
2517 
2518 static const enum index action_dec_tcp_ack[] = {
2519 	ACTION_DEC_TCP_ACK_VALUE,
2520 	ACTION_NEXT,
2521 	ZERO,
2522 };
2523 
2524 static const enum index action_raw_encap[] = {
2525 	ACTION_RAW_ENCAP_SIZE,
2526 	ACTION_RAW_ENCAP_INDEX,
2527 	ACTION_NEXT,
2528 	ZERO,
2529 };
2530 
2531 static const enum index action_raw_decap[] = {
2532 	ACTION_RAW_DECAP_INDEX,
2533 	ACTION_NEXT,
2534 	ZERO,
2535 };
2536 
2537 static const enum index action_ipv6_ext_remove[] = {
2538 	ACTION_IPV6_EXT_REMOVE_INDEX,
2539 	ACTION_NEXT,
2540 	ZERO,
2541 };
2542 
2543 static const enum index action_ipv6_ext_push[] = {
2544 	ACTION_IPV6_EXT_PUSH_INDEX,
2545 	ACTION_NEXT,
2546 	ZERO,
2547 };
2548 
2549 static const enum index action_set_tag[] = {
2550 	ACTION_SET_TAG_DATA,
2551 	ACTION_SET_TAG_INDEX,
2552 	ACTION_SET_TAG_MASK,
2553 	ACTION_NEXT,
2554 	ZERO,
2555 };
2556 
2557 static const enum index action_set_meta[] = {
2558 	ACTION_SET_META_DATA,
2559 	ACTION_SET_META_MASK,
2560 	ACTION_NEXT,
2561 	ZERO,
2562 };
2563 
2564 static const enum index action_set_ipv4_dscp[] = {
2565 	ACTION_SET_IPV4_DSCP_VALUE,
2566 	ACTION_NEXT,
2567 	ZERO,
2568 };
2569 
2570 static const enum index action_set_ipv6_dscp[] = {
2571 	ACTION_SET_IPV6_DSCP_VALUE,
2572 	ACTION_NEXT,
2573 	ZERO,
2574 };
2575 
2576 static const enum index action_age[] = {
2577 	ACTION_AGE,
2578 	ACTION_AGE_TIMEOUT,
2579 	ACTION_NEXT,
2580 	ZERO,
2581 };
2582 
2583 static const enum index action_age_update[] = {
2584 	ACTION_AGE_UPDATE,
2585 	ACTION_AGE_UPDATE_TIMEOUT,
2586 	ACTION_AGE_UPDATE_TOUCH,
2587 	ACTION_NEXT,
2588 	ZERO,
2589 };
2590 
2591 static const enum index action_sample[] = {
2592 	ACTION_SAMPLE,
2593 	ACTION_SAMPLE_RATIO,
2594 	ACTION_SAMPLE_INDEX,
2595 	ACTION_NEXT,
2596 	ZERO,
2597 };
2598 
2599 static const enum index next_action_sample[] = {
2600 	ACTION_QUEUE,
2601 	ACTION_RSS,
2602 	ACTION_MARK,
2603 	ACTION_COUNT,
2604 	ACTION_PORT_ID,
2605 	ACTION_RAW_ENCAP,
2606 	ACTION_VXLAN_ENCAP,
2607 	ACTION_NVGRE_ENCAP,
2608 	ACTION_REPRESENTED_PORT,
2609 	ACTION_PORT_REPRESENTOR,
2610 	ACTION_NEXT,
2611 	ZERO,
2612 };
2613 
2614 static const enum index item_ipv6_push_ext[] = {
2615 	ITEM_IPV6_PUSH_REMOVE_EXT,
2616 	ZERO,
2617 };
2618 
2619 static const enum index item_ipv6_push_ext_type[] = {
2620 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2621 	ZERO,
2622 };
2623 
2624 static const enum index item_ipv6_push_ext_header[] = {
2625 	ITEM_IPV6_ROUTING_EXT,
2626 	ITEM_NEXT,
2627 	ZERO,
2628 };
2629 
2630 static const enum index action_modify_field_dst[] = {
2631 	ACTION_MODIFY_FIELD_DST_LEVEL,
2632 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2633 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2634 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2635 	ACTION_MODIFY_FIELD_DST_OFFSET,
2636 	ACTION_MODIFY_FIELD_SRC_TYPE,
2637 	ZERO,
2638 };
2639 
2640 static const enum index action_modify_field_src[] = {
2641 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2642 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2643 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2644 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2645 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2646 	ACTION_MODIFY_FIELD_SRC_VALUE,
2647 	ACTION_MODIFY_FIELD_SRC_POINTER,
2648 	ACTION_MODIFY_FIELD_WIDTH,
2649 	ZERO,
2650 };
2651 
2652 static const enum index action_update_conntrack[] = {
2653 	ACTION_CONNTRACK_UPDATE_DIR,
2654 	ACTION_CONNTRACK_UPDATE_CTX,
2655 	ACTION_NEXT,
2656 	ZERO,
2657 };
2658 
2659 static const enum index action_port_representor[] = {
2660 	ACTION_PORT_REPRESENTOR_PORT_ID,
2661 	ACTION_NEXT,
2662 	ZERO,
2663 };
2664 
2665 static const enum index action_represented_port[] = {
2666 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2667 	ACTION_NEXT,
2668 	ZERO,
2669 };
2670 
2671 static const enum index action_nat64[] = {
2672 	ACTION_NAT64_MODE,
2673 	ACTION_NEXT,
2674 	ZERO,
2675 };
2676 
2677 static const enum index next_hash_subcmd[] = {
2678 	HASH_CALC_TABLE,
2679 	HASH_CALC_ENCAP,
2680 	ZERO,
2681 };
2682 
2683 static const enum index next_hash_encap_dest_subcmd[] = {
2684 	ENCAP_HASH_FIELD_SRC_PORT,
2685 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2686 	ZERO,
2687 };
2688 
2689 static const enum index action_jump_to_table_index[] = {
2690 	ACTION_JUMP_TO_TABLE_INDEX_TABLE,
2691 	ACTION_JUMP_TO_TABLE_INDEX_INDEX,
2692 	ACTION_NEXT,
2693 	ZERO,
2694 };
2695 
2696 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2697 				     const char *, unsigned int,
2698 				     void *, unsigned int);
2699 static int parse_set_sample_action(struct context *, const struct token *,
2700 				   const char *, unsigned int,
2701 				   void *, unsigned int);
2702 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2703 				     const char *, unsigned int,
2704 				     void *, unsigned int);
2705 static int parse_set_init(struct context *, const struct token *,
2706 			  const char *, unsigned int,
2707 			  void *, unsigned int);
2708 static int
2709 parse_flex_handle(struct context *, const struct token *,
2710 		  const char *, unsigned int, void *, unsigned int);
2711 static int parse_init(struct context *, const struct token *,
2712 		      const char *, unsigned int,
2713 		      void *, unsigned int);
2714 static int parse_vc(struct context *, const struct token *,
2715 		    const char *, unsigned int,
2716 		    void *, unsigned int);
2717 static int parse_vc_spec(struct context *, const struct token *,
2718 			 const char *, unsigned int, void *, unsigned int);
2719 static int parse_vc_conf(struct context *, const struct token *,
2720 			 const char *, unsigned int, void *, unsigned int);
2721 static int parse_vc_conf_timeout(struct context *, const struct token *,
2722 				 const char *, unsigned int, void *,
2723 				 unsigned int);
2724 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2725 				    const char *, unsigned int,
2726 				    void *, unsigned int);
2727 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2728 				    const char *, unsigned int,
2729 				    void *, unsigned int);
2730 static int parse_vc_action_meter_color_type(struct context *,
2731 					const struct token *,
2732 					const char *, unsigned int, void *,
2733 					unsigned int);
2734 static int parse_vc_action_rss(struct context *, const struct token *,
2735 			       const char *, unsigned int, void *,
2736 			       unsigned int);
2737 static int parse_vc_action_rss_func(struct context *, const struct token *,
2738 				    const char *, unsigned int, void *,
2739 				    unsigned int);
2740 static int parse_vc_action_rss_type(struct context *, const struct token *,
2741 				    const char *, unsigned int, void *,
2742 				    unsigned int);
2743 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2744 				     const char *, unsigned int, void *,
2745 				     unsigned int);
2746 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2747 				       const char *, unsigned int, void *,
2748 				       unsigned int);
2749 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2750 				       const char *, unsigned int, void *,
2751 				       unsigned int);
2752 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2753 				    const char *, unsigned int, void *,
2754 				    unsigned int);
2755 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2756 				    const char *, unsigned int, void *,
2757 				    unsigned int);
2758 static int parse_vc_action_mplsogre_encap(struct context *,
2759 					  const struct token *, const char *,
2760 					  unsigned int, void *, unsigned int);
2761 static int parse_vc_action_mplsogre_decap(struct context *,
2762 					  const struct token *, const char *,
2763 					  unsigned int, void *, unsigned int);
2764 static int parse_vc_action_mplsoudp_encap(struct context *,
2765 					  const struct token *, const char *,
2766 					  unsigned int, void *, unsigned int);
2767 static int parse_vc_action_mplsoudp_decap(struct context *,
2768 					  const struct token *, const char *,
2769 					  unsigned int, void *, unsigned int);
2770 static int parse_vc_action_raw_encap(struct context *,
2771 				     const struct token *, const char *,
2772 				     unsigned int, void *, unsigned int);
2773 static int parse_vc_action_raw_decap(struct context *,
2774 				     const struct token *, const char *,
2775 				     unsigned int, void *, unsigned int);
2776 static int parse_vc_action_raw_encap_index(struct context *,
2777 					   const struct token *, const char *,
2778 					   unsigned int, void *, unsigned int);
2779 static int parse_vc_action_raw_decap_index(struct context *,
2780 					   const struct token *, const char *,
2781 					   unsigned int, void *, unsigned int);
2782 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2783 					   const char *str, unsigned int len, void *buf,
2784 					   unsigned int size);
2785 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2786 						 const struct token *token,
2787 						 const char *str, unsigned int len,
2788 						 void *buf,
2789 						 unsigned int size);
2790 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2791 					 const char *str, unsigned int len, void *buf,
2792 					 unsigned int size);
2793 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2794 					       const struct token *token,
2795 					       const char *str, unsigned int len,
2796 					       void *buf,
2797 					       unsigned int size);
2798 static int parse_vc_action_set_meta(struct context *ctx,
2799 				    const struct token *token, const char *str,
2800 				    unsigned int len, void *buf,
2801 					unsigned int size);
2802 static int parse_vc_action_sample(struct context *ctx,
2803 				    const struct token *token, const char *str,
2804 				    unsigned int len, void *buf,
2805 				    unsigned int size);
2806 static int
2807 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2808 				const char *str, unsigned int len, void *buf,
2809 				unsigned int size);
2810 static int
2811 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2812 				const char *str, unsigned int len, void *buf,
2813 				unsigned int size);
2814 static int
2815 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2816 				const char *str, unsigned int len, void *buf,
2817 				unsigned int size);
2818 static int
2819 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2820 				const char *str, unsigned int len, void *buf,
2821 				unsigned int size);
2822 static int
2823 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2824 			 const char *str, unsigned int len, void *buf,
2825 			 unsigned int size);
2826 static int parse_destroy(struct context *, const struct token *,
2827 			 const char *, unsigned int,
2828 			 void *, unsigned int);
2829 static int parse_flush(struct context *, const struct token *,
2830 		       const char *, unsigned int,
2831 		       void *, unsigned int);
2832 static int parse_dump(struct context *, const struct token *,
2833 		      const char *, unsigned int,
2834 		      void *, unsigned int);
2835 static int parse_query(struct context *, const struct token *,
2836 		       const char *, unsigned int,
2837 		       void *, unsigned int);
2838 static int parse_action(struct context *, const struct token *,
2839 			const char *, unsigned int,
2840 			void *, unsigned int);
2841 static int parse_list(struct context *, const struct token *,
2842 		      const char *, unsigned int,
2843 		      void *, unsigned int);
2844 static int parse_aged(struct context *, const struct token *,
2845 		      const char *, unsigned int,
2846 		      void *, unsigned int);
2847 static int parse_isolate(struct context *, const struct token *,
2848 			 const char *, unsigned int,
2849 			 void *, unsigned int);
2850 static int parse_configure(struct context *, const struct token *,
2851 			   const char *, unsigned int,
2852 			   void *, unsigned int);
2853 static int parse_template(struct context *, const struct token *,
2854 			  const char *, unsigned int,
2855 			  void *, unsigned int);
2856 static int parse_template_destroy(struct context *, const struct token *,
2857 				  const char *, unsigned int,
2858 				  void *, unsigned int);
2859 static int parse_table(struct context *, const struct token *,
2860 		       const char *, unsigned int, void *, unsigned int);
2861 static int parse_table_destroy(struct context *, const struct token *,
2862 			       const char *, unsigned int,
2863 			       void *, unsigned int);
2864 static int parse_qo(struct context *, const struct token *,
2865 		    const char *, unsigned int,
2866 		    void *, unsigned int);
2867 static int parse_qo_destroy(struct context *, const struct token *,
2868 			    const char *, unsigned int,
2869 			    void *, unsigned int);
2870 static int parse_qia(struct context *, const struct token *,
2871 		     const char *, unsigned int,
2872 		     void *, unsigned int);
2873 static int parse_qia_destroy(struct context *, const struct token *,
2874 			     const char *, unsigned int,
2875 			     void *, unsigned int);
2876 static int parse_push(struct context *, const struct token *,
2877 		      const char *, unsigned int,
2878 		      void *, unsigned int);
2879 static int parse_pull(struct context *, const struct token *,
2880 		      const char *, unsigned int,
2881 		      void *, unsigned int);
2882 static int parse_group(struct context *, const struct token *,
2883 		       const char *, unsigned int,
2884 		       void *, unsigned int);
2885 static int parse_hash(struct context *, const struct token *,
2886 		      const char *, unsigned int,
2887 		      void *, unsigned int);
2888 static int parse_tunnel(struct context *, const struct token *,
2889 			const char *, unsigned int,
2890 			void *, unsigned int);
2891 static int parse_flex(struct context *, const struct token *,
2892 		      const char *, unsigned int, void *, unsigned int);
2893 static int parse_int(struct context *, const struct token *,
2894 		     const char *, unsigned int,
2895 		     void *, unsigned int);
2896 static int parse_prefix(struct context *, const struct token *,
2897 			const char *, unsigned int,
2898 			void *, unsigned int);
2899 static int parse_boolean(struct context *, const struct token *,
2900 			 const char *, unsigned int,
2901 			 void *, unsigned int);
2902 static int parse_string(struct context *, const struct token *,
2903 			const char *, unsigned int,
2904 			void *, unsigned int);
2905 static int parse_hex(struct context *ctx, const struct token *token,
2906 			const char *str, unsigned int len,
2907 			void *buf, unsigned int size);
2908 static int parse_string0(struct context *, const struct token *,
2909 			const char *, unsigned int,
2910 			void *, unsigned int);
2911 static int parse_mac_addr(struct context *, const struct token *,
2912 			  const char *, unsigned int,
2913 			  void *, unsigned int);
2914 static int parse_ipv4_addr(struct context *, const struct token *,
2915 			   const char *, unsigned int,
2916 			   void *, unsigned int);
2917 static int parse_ipv6_addr(struct context *, const struct token *,
2918 			   const char *, unsigned int,
2919 			   void *, unsigned int);
2920 static int parse_port(struct context *, const struct token *,
2921 		      const char *, unsigned int,
2922 		      void *, unsigned int);
2923 static int parse_ia(struct context *, const struct token *,
2924 		    const char *, unsigned int,
2925 		    void *, unsigned int);
2926 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2927 			    const char *str, unsigned int len,
2928 			    void *buf, unsigned int size);
2929 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2930 			   const char *str, unsigned int len, void *buf,
2931 			   unsigned int size);
2932 
2933 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2934 			       const char *str, unsigned int len, void *buf,
2935 			       unsigned int size);
2936 static int parse_ia_port(struct context *ctx, const struct token *token,
2937 			 const char *str, unsigned int len, void *buf,
2938 			 unsigned int size);
2939 static int parse_mp(struct context *, const struct token *,
2940 		    const char *, unsigned int,
2941 		    void *, unsigned int);
2942 static int parse_meter_profile_id2ptr(struct context *ctx,
2943 				      const struct token *token,
2944 				      const char *str, unsigned int len,
2945 				      void *buf, unsigned int size);
2946 static int parse_meter_policy_id2ptr(struct context *ctx,
2947 				     const struct token *token,
2948 				     const char *str, unsigned int len,
2949 				     void *buf, unsigned int size);
2950 static int parse_meter_color(struct context *ctx, const struct token *token,
2951 			     const char *str, unsigned int len, void *buf,
2952 			     unsigned int size);
2953 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2954 				      const char *str, unsigned int len, void *buf,
2955 				      unsigned int size);
2956 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2957 				 const char *str, unsigned int len, void *buf,
2958 				 unsigned int size);
2959 static int
2960 parse_quota_state_name(struct context *ctx, const struct token *token,
2961 		       const char *str, unsigned int len, void *buf,
2962 		       unsigned int size);
2963 static int
2964 parse_quota_mode_name(struct context *ctx, const struct token *token,
2965 		      const char *str, unsigned int len, void *buf,
2966 		      unsigned int size);
2967 static int
2968 parse_quota_update_name(struct context *ctx, const struct token *token,
2969 			const char *str, unsigned int len, void *buf,
2970 			unsigned int size);
2971 static int
2972 parse_qu_mode_name(struct context *ctx, const struct token *token,
2973 		   const char *str, unsigned int len, void *buf,
2974 		   unsigned int size);
2975 static int comp_none(struct context *, const struct token *,
2976 		     unsigned int, char *, unsigned int);
2977 static int comp_boolean(struct context *, const struct token *,
2978 			unsigned int, char *, unsigned int);
2979 static int comp_action(struct context *, const struct token *,
2980 		       unsigned int, char *, unsigned int);
2981 static int comp_port(struct context *, const struct token *,
2982 		     unsigned int, char *, unsigned int);
2983 static int comp_rule_id(struct context *, const struct token *,
2984 			unsigned int, char *, unsigned int);
2985 static int comp_vc_action_rss_type(struct context *, const struct token *,
2986 				   unsigned int, char *, unsigned int);
2987 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2988 				    unsigned int, char *, unsigned int);
2989 static int comp_set_raw_index(struct context *, const struct token *,
2990 			      unsigned int, char *, unsigned int);
2991 static int comp_set_sample_index(struct context *, const struct token *,
2992 			      unsigned int, char *, unsigned int);
2993 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2994 				   unsigned int ent, char *buf, unsigned int size);
2995 static int comp_set_modify_field_op(struct context *, const struct token *,
2996 			      unsigned int, char *, unsigned int);
2997 static int comp_set_modify_field_id(struct context *, const struct token *,
2998 			      unsigned int, char *, unsigned int);
2999 static int comp_pattern_template_id(struct context *, const struct token *,
3000 				    unsigned int, char *, unsigned int);
3001 static int comp_actions_template_id(struct context *, const struct token *,
3002 				    unsigned int, char *, unsigned int);
3003 static int comp_table_id(struct context *, const struct token *,
3004 			 unsigned int, char *, unsigned int);
3005 static int comp_queue_id(struct context *, const struct token *,
3006 			 unsigned int, char *, unsigned int);
3007 static int comp_meter_color(struct context *, const struct token *,
3008 			    unsigned int, char *, unsigned int);
3009 static int comp_insertion_table_type(struct context *, const struct token *,
3010 				     unsigned int, char *, unsigned int);
3011 static int comp_hash_table_type(struct context *, const struct token *,
3012 				unsigned int, char *, unsigned int);
3013 static int
3014 comp_quota_state_name(struct context *ctx, const struct token *token,
3015 		      unsigned int ent, char *buf, unsigned int size);
3016 static int
3017 comp_quota_mode_name(struct context *ctx, const struct token *token,
3018 		     unsigned int ent, char *buf, unsigned int size);
3019 static int
3020 comp_quota_update_name(struct context *ctx, const struct token *token,
3021 		       unsigned int ent, char *buf, unsigned int size);
3022 static int
3023 comp_qu_mode_name(struct context *ctx, const struct token *token,
3024 		  unsigned int ent, char *buf, unsigned int size);
3025 static int
3026 comp_set_compare_field_id(struct context *ctx, const struct token *token,
3027 			  unsigned int ent, char *buf, unsigned int size);
3028 static int
3029 comp_set_compare_op(struct context *ctx, const struct token *token,
3030 		    unsigned int ent, char *buf, unsigned int size);
3031 static int
3032 parse_vc_compare_op(struct context *ctx, const struct token *token,
3033 			 const char *str, unsigned int len, void *buf,
3034 			 unsigned int size);
3035 static int
3036 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
3037 			  const char *str, unsigned int len, void *buf,
3038 			  unsigned int size);
3039 static int
3040 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
3041 			     const char *str, unsigned int len, void *buf,
3042 			     unsigned int size);
3043 
3044 struct indlst_conf {
3045 	uint32_t id;
3046 	uint32_t conf_num;
3047 	struct rte_flow_action *actions;
3048 	const void **conf;
3049 	SLIST_ENTRY(indlst_conf) next;
3050 };
3051 
3052 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3053 
3054 /** Token definitions. */
3055 static const struct token token_list[] = {
3056 	/* Special tokens. */
3057 	[ZERO] = {
3058 		.name = "ZERO",
3059 		.help = "null entry, abused as the entry point",
3060 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3061 	},
3062 	[END] = {
3063 		.name = "",
3064 		.type = "RETURN",
3065 		.help = "command may end here",
3066 	},
3067 	[START_SET] = {
3068 		.name = "START_SET",
3069 		.help = "null entry, abused as the entry point for set",
3070 		.next = NEXT(NEXT_ENTRY(SET)),
3071 	},
3072 	[END_SET] = {
3073 		.name = "end_set",
3074 		.type = "RETURN",
3075 		.help = "set command may end here",
3076 	},
3077 	/* Common tokens. */
3078 	[COMMON_INTEGER] = {
3079 		.name = "{int}",
3080 		.type = "INTEGER",
3081 		.help = "integer value",
3082 		.call = parse_int,
3083 		.comp = comp_none,
3084 	},
3085 	[COMMON_UNSIGNED] = {
3086 		.name = "{unsigned}",
3087 		.type = "UNSIGNED",
3088 		.help = "unsigned integer value",
3089 		.call = parse_int,
3090 		.comp = comp_none,
3091 	},
3092 	[COMMON_PREFIX] = {
3093 		.name = "{prefix}",
3094 		.type = "PREFIX",
3095 		.help = "prefix length for bit-mask",
3096 		.call = parse_prefix,
3097 		.comp = comp_none,
3098 	},
3099 	[COMMON_BOOLEAN] = {
3100 		.name = "{boolean}",
3101 		.type = "BOOLEAN",
3102 		.help = "any boolean value",
3103 		.call = parse_boolean,
3104 		.comp = comp_boolean,
3105 	},
3106 	[COMMON_STRING] = {
3107 		.name = "{string}",
3108 		.type = "STRING",
3109 		.help = "fixed string",
3110 		.call = parse_string,
3111 		.comp = comp_none,
3112 	},
3113 	[COMMON_HEX] = {
3114 		.name = "{hex}",
3115 		.type = "HEX",
3116 		.help = "fixed string",
3117 		.call = parse_hex,
3118 	},
3119 	[COMMON_FILE_PATH] = {
3120 		.name = "{file path}",
3121 		.type = "STRING",
3122 		.help = "file path",
3123 		.call = parse_string0,
3124 		.comp = comp_none,
3125 	},
3126 	[COMMON_MAC_ADDR] = {
3127 		.name = "{MAC address}",
3128 		.type = "MAC-48",
3129 		.help = "standard MAC address notation",
3130 		.call = parse_mac_addr,
3131 		.comp = comp_none,
3132 	},
3133 	[COMMON_IPV4_ADDR] = {
3134 		.name = "{IPv4 address}",
3135 		.type = "IPV4 ADDRESS",
3136 		.help = "standard IPv4 address notation",
3137 		.call = parse_ipv4_addr,
3138 		.comp = comp_none,
3139 	},
3140 	[COMMON_IPV6_ADDR] = {
3141 		.name = "{IPv6 address}",
3142 		.type = "IPV6 ADDRESS",
3143 		.help = "standard IPv6 address notation",
3144 		.call = parse_ipv6_addr,
3145 		.comp = comp_none,
3146 	},
3147 	[COMMON_RULE_ID] = {
3148 		.name = "{rule id}",
3149 		.type = "RULE ID",
3150 		.help = "rule identifier",
3151 		.call = parse_int,
3152 		.comp = comp_rule_id,
3153 	},
3154 	[COMMON_PORT_ID] = {
3155 		.name = "{port_id}",
3156 		.type = "PORT ID",
3157 		.help = "port identifier",
3158 		.call = parse_port,
3159 		.comp = comp_port,
3160 	},
3161 	[COMMON_GROUP_ID] = {
3162 		.name = "{group_id}",
3163 		.type = "GROUP ID",
3164 		.help = "group identifier",
3165 		.call = parse_int,
3166 		.comp = comp_none,
3167 	},
3168 	[COMMON_PRIORITY_LEVEL] = {
3169 		.name = "{level}",
3170 		.type = "PRIORITY",
3171 		.help = "priority level",
3172 		.call = parse_int,
3173 		.comp = comp_none,
3174 	},
3175 	[COMMON_INDIRECT_ACTION_ID] = {
3176 		.name = "{indirect_action_id}",
3177 		.type = "INDIRECT_ACTION_ID",
3178 		.help = "indirect action id",
3179 		.call = parse_int,
3180 		.comp = comp_none,
3181 	},
3182 	[COMMON_PROFILE_ID] = {
3183 		.name = "{profile_id}",
3184 		.type = "PROFILE_ID",
3185 		.help = "profile id",
3186 		.call = parse_int,
3187 		.comp = comp_none,
3188 	},
3189 	[COMMON_POLICY_ID] = {
3190 		.name = "{policy_id}",
3191 		.type = "POLICY_ID",
3192 		.help = "policy id",
3193 		.call = parse_int,
3194 		.comp = comp_none,
3195 	},
3196 	[COMMON_FLEX_TOKEN] = {
3197 		.name = "{flex token}",
3198 		.type = "flex token",
3199 		.help = "flex token",
3200 		.call = parse_int,
3201 		.comp = comp_none,
3202 	},
3203 	[COMMON_FLEX_HANDLE] = {
3204 		.name = "{flex handle}",
3205 		.type = "FLEX HANDLE",
3206 		.help = "fill flex item data",
3207 		.call = parse_flex_handle,
3208 		.comp = comp_none,
3209 	},
3210 	[COMMON_PATTERN_TEMPLATE_ID] = {
3211 		.name = "{pattern_template_id}",
3212 		.type = "PATTERN_TEMPLATE_ID",
3213 		.help = "pattern template id",
3214 		.call = parse_int,
3215 		.comp = comp_pattern_template_id,
3216 	},
3217 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3218 		.name = "{actions_template_id}",
3219 		.type = "ACTIONS_TEMPLATE_ID",
3220 		.help = "actions template id",
3221 		.call = parse_int,
3222 		.comp = comp_actions_template_id,
3223 	},
3224 	[COMMON_TABLE_ID] = {
3225 		.name = "{table_id}",
3226 		.type = "TABLE_ID",
3227 		.help = "table id",
3228 		.call = parse_int,
3229 		.comp = comp_table_id,
3230 	},
3231 	[COMMON_QUEUE_ID] = {
3232 		.name = "{queue_id}",
3233 		.type = "QUEUE_ID",
3234 		.help = "queue id",
3235 		.call = parse_int,
3236 		.comp = comp_queue_id,
3237 	},
3238 	/* Top-level command. */
3239 	[FLOW] = {
3240 		.name = "flow",
3241 		.type = "{command} {port_id} [{arg} [...]]",
3242 		.help = "manage ingress/egress flow rules",
3243 		.next = NEXT(NEXT_ENTRY
3244 			     (INFO,
3245 			      CONFIGURE,
3246 			      PATTERN_TEMPLATE,
3247 			      ACTIONS_TEMPLATE,
3248 			      TABLE,
3249 			      FLOW_GROUP,
3250 			      INDIRECT_ACTION,
3251 			      VALIDATE,
3252 			      CREATE,
3253 			      DESTROY,
3254 			      UPDATE,
3255 			      FLUSH,
3256 			      DUMP,
3257 			      LIST,
3258 			      AGED,
3259 			      QUERY,
3260 			      ISOLATE,
3261 			      TUNNEL,
3262 			      FLEX,
3263 			      QUEUE,
3264 			      PUSH,
3265 			      PULL,
3266 			      HASH)),
3267 		.call = parse_init,
3268 	},
3269 	/* Top-level command. */
3270 	[INFO] = {
3271 		.name = "info",
3272 		.help = "get information about flow engine",
3273 		.next = NEXT(NEXT_ENTRY(END),
3274 			     NEXT_ENTRY(COMMON_PORT_ID)),
3275 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3276 		.call = parse_configure,
3277 	},
3278 	/* Top-level command. */
3279 	[CONFIGURE] = {
3280 		.name = "configure",
3281 		.help = "configure flow engine",
3282 		.next = NEXT(next_config_attr,
3283 			     NEXT_ENTRY(COMMON_PORT_ID)),
3284 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3285 		.call = parse_configure,
3286 	},
3287 	/* Configure arguments. */
3288 	[CONFIG_QUEUES_NUMBER] = {
3289 		.name = "queues_number",
3290 		.help = "number of queues",
3291 		.next = NEXT(next_config_attr,
3292 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3293 		.args = ARGS(ARGS_ENTRY(struct buffer,
3294 					args.configure.nb_queue)),
3295 	},
3296 	[CONFIG_QUEUES_SIZE] = {
3297 		.name = "queues_size",
3298 		.help = "number of elements in queues",
3299 		.next = NEXT(next_config_attr,
3300 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3301 		.args = ARGS(ARGS_ENTRY(struct buffer,
3302 					args.configure.queue_attr.size)),
3303 	},
3304 	[CONFIG_COUNTERS_NUMBER] = {
3305 		.name = "counters_number",
3306 		.help = "number of counters",
3307 		.next = NEXT(next_config_attr,
3308 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3309 		.args = ARGS(ARGS_ENTRY(struct buffer,
3310 					args.configure.port_attr.nb_counters)),
3311 	},
3312 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3313 		.name = "aging_counters_number",
3314 		.help = "number of aging objects",
3315 		.next = NEXT(next_config_attr,
3316 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3317 		.args = ARGS(ARGS_ENTRY(struct buffer,
3318 					args.configure.port_attr.nb_aging_objects)),
3319 	},
3320 	[CONFIG_QUOTAS_NUMBER] = {
3321 		.name = "quotas_number",
3322 		.help = "number of quotas",
3323 		.next = NEXT(next_config_attr,
3324 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3325 		.args = ARGS(ARGS_ENTRY(struct buffer,
3326 				     args.configure.port_attr.nb_quotas)),
3327 	},
3328 	[CONFIG_METERS_NUMBER] = {
3329 		.name = "meters_number",
3330 		.help = "number of meters",
3331 		.next = NEXT(next_config_attr,
3332 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3333 		.args = ARGS(ARGS_ENTRY(struct buffer,
3334 					args.configure.port_attr.nb_meters)),
3335 	},
3336 	[CONFIG_CONN_TRACK_NUMBER] = {
3337 		.name = "conn_tracks_number",
3338 		.help = "number of connection trackings",
3339 		.next = NEXT(next_config_attr,
3340 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3341 		.args = ARGS(ARGS_ENTRY(struct buffer,
3342 					args.configure.port_attr.nb_conn_tracks)),
3343 	},
3344 	[CONFIG_FLAGS] = {
3345 		.name = "flags",
3346 		.help = "configuration flags",
3347 		.next = NEXT(next_config_attr,
3348 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3349 		.args = ARGS(ARGS_ENTRY(struct buffer,
3350 					args.configure.port_attr.flags)),
3351 	},
3352 	[CONFIG_HOST_PORT] = {
3353 		.name = "host_port",
3354 		.help = "host port for shared objects",
3355 		.next = NEXT(next_config_attr,
3356 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3357 		.args = ARGS(ARGS_ENTRY(struct buffer,
3358 					args.configure.port_attr.host_port_id)),
3359 	},
3360 	/* Top-level command. */
3361 	[PATTERN_TEMPLATE] = {
3362 		.name = "pattern_template",
3363 		.type = "{command} {port_id} [{arg} [...]]",
3364 		.help = "manage pattern templates",
3365 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3366 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3367 		.call = parse_template,
3368 	},
3369 	/* Sub-level commands. */
3370 	[PATTERN_TEMPLATE_CREATE] = {
3371 		.name = "create",
3372 		.help = "create pattern template",
3373 		.next = NEXT(next_pt_attr),
3374 		.call = parse_template,
3375 	},
3376 	[PATTERN_TEMPLATE_DESTROY] = {
3377 		.name = "destroy",
3378 		.help = "destroy pattern template",
3379 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3380 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3381 		.call = parse_template_destroy,
3382 	},
3383 	/* Pattern template arguments. */
3384 	[PATTERN_TEMPLATE_CREATE_ID] = {
3385 		.name = "pattern_template_id",
3386 		.help = "specify a pattern template id to create",
3387 		.next = NEXT(next_pt_attr,
3388 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3389 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3390 	},
3391 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3392 		.name = "pattern_template",
3393 		.help = "specify a pattern template id to destroy",
3394 		.next = NEXT(next_pt_destroy_attr,
3395 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3396 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3397 					    args.templ_destroy.template_id)),
3398 		.call = parse_template_destroy,
3399 	},
3400 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3401 		.name = "relaxed",
3402 		.help = "is matching relaxed",
3403 		.next = NEXT(next_pt_attr,
3404 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3405 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3406 			     args.vc.attr.reserved, 1)),
3407 	},
3408 	[PATTERN_TEMPLATE_INGRESS] = {
3409 		.name = "ingress",
3410 		.help = "attribute pattern to ingress",
3411 		.next = NEXT(next_pt_attr),
3412 		.call = parse_template,
3413 	},
3414 	[PATTERN_TEMPLATE_EGRESS] = {
3415 		.name = "egress",
3416 		.help = "attribute pattern to egress",
3417 		.next = NEXT(next_pt_attr),
3418 		.call = parse_template,
3419 	},
3420 	[PATTERN_TEMPLATE_TRANSFER] = {
3421 		.name = "transfer",
3422 		.help = "attribute pattern to transfer",
3423 		.next = NEXT(next_pt_attr),
3424 		.call = parse_template,
3425 	},
3426 	[PATTERN_TEMPLATE_SPEC] = {
3427 		.name = "template",
3428 		.help = "specify item to create pattern template",
3429 		.next = NEXT(next_item),
3430 	},
3431 	/* Top-level command. */
3432 	[ACTIONS_TEMPLATE] = {
3433 		.name = "actions_template",
3434 		.type = "{command} {port_id} [{arg} [...]]",
3435 		.help = "manage actions templates",
3436 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3437 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3438 		.call = parse_template,
3439 	},
3440 	/* Sub-level commands. */
3441 	[ACTIONS_TEMPLATE_CREATE] = {
3442 		.name = "create",
3443 		.help = "create actions template",
3444 		.next = NEXT(next_at_attr),
3445 		.call = parse_template,
3446 	},
3447 	[ACTIONS_TEMPLATE_DESTROY] = {
3448 		.name = "destroy",
3449 		.help = "destroy actions template",
3450 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3451 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3452 		.call = parse_template_destroy,
3453 	},
3454 	/* Actions template arguments. */
3455 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3456 		.name = "actions_template_id",
3457 		.help = "specify an actions template id to create",
3458 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3459 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3460 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3461 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3462 	},
3463 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3464 		.name = "actions_template",
3465 		.help = "specify an actions template id to destroy",
3466 		.next = NEXT(next_at_destroy_attr,
3467 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3468 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3469 					    args.templ_destroy.template_id)),
3470 		.call = parse_template_destroy,
3471 	},
3472 	[ACTIONS_TEMPLATE_INGRESS] = {
3473 		.name = "ingress",
3474 		.help = "attribute actions to ingress",
3475 		.next = NEXT(next_at_attr),
3476 		.call = parse_template,
3477 	},
3478 	[ACTIONS_TEMPLATE_EGRESS] = {
3479 		.name = "egress",
3480 		.help = "attribute actions to egress",
3481 		.next = NEXT(next_at_attr),
3482 		.call = parse_template,
3483 	},
3484 	[ACTIONS_TEMPLATE_TRANSFER] = {
3485 		.name = "transfer",
3486 		.help = "attribute actions to transfer",
3487 		.next = NEXT(next_at_attr),
3488 		.call = parse_template,
3489 	},
3490 	[ACTIONS_TEMPLATE_SPEC] = {
3491 		.name = "template",
3492 		.help = "specify action to create actions template",
3493 		.next = NEXT(next_action),
3494 		.call = parse_template,
3495 	},
3496 	[ACTIONS_TEMPLATE_MASK] = {
3497 		.name = "mask",
3498 		.help = "specify action mask to create actions template",
3499 		.next = NEXT(next_action),
3500 		.call = parse_template,
3501 	},
3502 	/* Top-level command. */
3503 	[TABLE] = {
3504 		.name = "template_table",
3505 		.type = "{command} {port_id} [{arg} [...]]",
3506 		.help = "manage template tables",
3507 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3508 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3509 		.call = parse_table,
3510 	},
3511 	/* Sub-level commands. */
3512 	[TABLE_CREATE] = {
3513 		.name = "create",
3514 		.help = "create template table",
3515 		.next = NEXT(next_table_attr),
3516 		.call = parse_table,
3517 	},
3518 	[TABLE_DESTROY] = {
3519 		.name = "destroy",
3520 		.help = "destroy template table",
3521 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3522 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3523 		.call = parse_table_destroy,
3524 	},
3525 	[TABLE_RESIZE] = {
3526 		.name = "resize",
3527 		.help = "resize template table",
3528 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3529 		.call = parse_table
3530 	},
3531 	[TABLE_RESIZE_COMPLETE] = {
3532 		.name = "resize_complete",
3533 		.help = "complete table resize",
3534 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3535 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3536 		.call = parse_table_destroy,
3537 	},
3538 	/* Table  arguments. */
3539 	[TABLE_CREATE_ID] = {
3540 		.name = "table_id",
3541 		.help = "specify table id to create",
3542 		.next = NEXT(next_table_attr,
3543 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3544 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3545 	},
3546 	[TABLE_DESTROY_ID] = {
3547 		.name = "table",
3548 		.help = "table id",
3549 		.next = NEXT(next_table_destroy_attr,
3550 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3551 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3552 					    args.table_destroy.table_id)),
3553 		.call = parse_table_destroy,
3554 	},
3555 	[TABLE_RESIZE_ID] = {
3556 		.name = "table_resize_id",
3557 		.help = "table resize id",
3558 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3559 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3560 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3561 		.call = parse_table
3562 	},
3563 	[TABLE_RESIZE_RULES_NUMBER] = {
3564 		.name = "table_resize_rules_num",
3565 		.help = "table resize rules number",
3566 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3567 		.args = ARGS(ARGS_ENTRY(struct buffer,
3568 					args.table.attr.nb_flows)),
3569 		.call = parse_table
3570 	},
3571 	[TABLE_INSERTION_TYPE] = {
3572 		.name = "insertion_type",
3573 		.help = "specify insertion type",
3574 		.next = NEXT(next_table_attr,
3575 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3576 		.args = ARGS(ARGS_ENTRY(struct buffer,
3577 					args.table.attr.insertion_type)),
3578 	},
3579 	[TABLE_INSERTION_TYPE_NAME] = {
3580 		.name = "insertion_type_name",
3581 		.help = "insertion type name",
3582 		.call = parse_insertion_table_type,
3583 		.comp = comp_insertion_table_type,
3584 	},
3585 	[TABLE_HASH_FUNC] = {
3586 		.name = "hash_func",
3587 		.help = "specify hash calculation function",
3588 		.next = NEXT(next_table_attr,
3589 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3590 		.args = ARGS(ARGS_ENTRY(struct buffer,
3591 					args.table.attr.hash_func)),
3592 	},
3593 	[TABLE_HASH_FUNC_NAME] = {
3594 		.name = "hash_func_name",
3595 		.help = "hash calculation function name",
3596 		.call = parse_hash_table_type,
3597 		.comp = comp_hash_table_type,
3598 	},
3599 	[TABLE_GROUP] = {
3600 		.name = "group",
3601 		.help = "specify a group",
3602 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3603 		.args = ARGS(ARGS_ENTRY(struct buffer,
3604 					args.table.attr.flow_attr.group)),
3605 	},
3606 	[TABLE_PRIORITY] = {
3607 		.name = "priority",
3608 		.help = "specify a priority level",
3609 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3610 		.args = ARGS(ARGS_ENTRY(struct buffer,
3611 					args.table.attr.flow_attr.priority)),
3612 	},
3613 	[TABLE_EGRESS] = {
3614 		.name = "egress",
3615 		.help = "affect rule to egress",
3616 		.next = NEXT(next_table_attr),
3617 		.call = parse_table,
3618 	},
3619 	[TABLE_INGRESS] = {
3620 		.name = "ingress",
3621 		.help = "affect rule to ingress",
3622 		.next = NEXT(next_table_attr),
3623 		.call = parse_table,
3624 	},
3625 	[TABLE_TRANSFER] = {
3626 		.name = "transfer",
3627 		.help = "affect rule to transfer",
3628 		.next = NEXT(next_table_attr),
3629 		.call = parse_table,
3630 	},
3631 	[TABLE_TRANSFER_WIRE_ORIG] = {
3632 		.name = "wire_orig",
3633 		.help = "affect rule direction to transfer",
3634 		.next = NEXT(next_table_attr),
3635 		.call = parse_table,
3636 	},
3637 	[TABLE_TRANSFER_VPORT_ORIG] = {
3638 		.name = "vport_orig",
3639 		.help = "affect rule direction to transfer",
3640 		.next = NEXT(next_table_attr),
3641 		.call = parse_table,
3642 	},
3643 	[TABLE_RESIZABLE] = {
3644 		.name = "resizable",
3645 		.help = "set resizable attribute",
3646 		.next = NEXT(next_table_attr),
3647 		.call = parse_table,
3648 	},
3649 	[TABLE_RULES_NUMBER] = {
3650 		.name = "rules_number",
3651 		.help = "number of rules in table",
3652 		.next = NEXT(next_table_attr,
3653 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3654 		.args = ARGS(ARGS_ENTRY(struct buffer,
3655 					args.table.attr.nb_flows)),
3656 		.call = parse_table,
3657 	},
3658 	[TABLE_PATTERN_TEMPLATE] = {
3659 		.name = "pattern_template",
3660 		.help = "specify pattern template id",
3661 		.next = NEXT(next_table_attr,
3662 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3663 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3664 					    args.table.pat_templ_id)),
3665 		.call = parse_table,
3666 	},
3667 	[TABLE_ACTIONS_TEMPLATE] = {
3668 		.name = "actions_template",
3669 		.help = "specify actions template id",
3670 		.next = NEXT(next_table_attr,
3671 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3672 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3673 					    args.table.act_templ_id)),
3674 		.call = parse_table,
3675 	},
3676 	/* Top-level command. */
3677 	[FLOW_GROUP] = {
3678 		.name = "group",
3679 		.help = "manage flow groups",
3680 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3681 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3682 		.call = parse_group,
3683 	},
3684 	/* Sub-level commands. */
3685 	[GROUP_SET_MISS_ACTIONS] = {
3686 		.name = "set_miss_actions",
3687 		.help = "set group miss actions",
3688 		.next = NEXT(next_action),
3689 		.call = parse_group,
3690 	},
3691 	/* Group arguments */
3692 	[GROUP_ID]	= {
3693 		.name = "group_id",
3694 		.help = "group id",
3695 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3696 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3697 	},
3698 	[GROUP_INGRESS] = {
3699 		.name = "ingress",
3700 		.help = "group ingress attr",
3701 		.next = NEXT(next_group_attr),
3702 		.call = parse_group,
3703 	},
3704 	[GROUP_EGRESS] = {
3705 		.name = "egress",
3706 		.help = "group egress attr",
3707 		.next = NEXT(next_group_attr),
3708 		.call = parse_group,
3709 	},
3710 	[GROUP_TRANSFER] = {
3711 		.name = "transfer",
3712 		.help = "group transfer attr",
3713 		.next = NEXT(next_group_attr),
3714 		.call = parse_group,
3715 	},
3716 	/* Top-level command. */
3717 	[QUEUE] = {
3718 		.name = "queue",
3719 		.help = "queue a flow rule operation",
3720 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3721 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3722 		.call = parse_qo,
3723 	},
3724 	/* Sub-level commands. */
3725 	[QUEUE_CREATE] = {
3726 		.name = "create",
3727 		.help = "create a flow rule",
3728 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3729 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3730 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3731 		.call = parse_qo,
3732 	},
3733 	[QUEUE_DESTROY] = {
3734 		.name = "destroy",
3735 		.help = "destroy a flow rule",
3736 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_POSTPONE),
3737 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3738 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3739 		.call = parse_qo_destroy,
3740 	},
3741 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3742 		.name = "update_resized",
3743 		.help = "update a flow after table resize",
3744 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3745 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3746 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3747 		.call = parse_qo_destroy,
3748 	},
3749 	[QUEUE_UPDATE] = {
3750 		.name = "update",
3751 		.help = "update a flow rule",
3752 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3753 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3754 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3755 		.call = parse_qo,
3756 	},
3757 	[QUEUE_AGED] = {
3758 		.name = "aged",
3759 		.help = "list and destroy aged flows",
3760 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3761 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3762 		.call = parse_aged,
3763 	},
3764 	[QUEUE_INDIRECT_ACTION] = {
3765 		.name = "indirect_action",
3766 		.help = "queue indirect actions",
3767 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3768 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3769 		.call = parse_qia,
3770 	},
3771 	/* Queue  arguments. */
3772 	[QUEUE_TEMPLATE_TABLE] = {
3773 		.name = "template_table",
3774 		.help = "specify table id",
3775 		.next = NEXT(next_async_insert_subcmd,
3776 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3777 		.args = ARGS(ARGS_ENTRY(struct buffer,
3778 					args.vc.table_id)),
3779 		.call = parse_qo,
3780 	},
3781 	[QUEUE_PATTERN_TEMPLATE] = {
3782 		.name = "pattern_template",
3783 		.help = "specify pattern template index",
3784 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3785 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3786 		.args = ARGS(ARGS_ENTRY(struct buffer,
3787 					args.vc.pat_templ_id)),
3788 		.call = parse_qo,
3789 	},
3790 	[QUEUE_ACTIONS_TEMPLATE] = {
3791 		.name = "actions_template",
3792 		.help = "specify actions template index",
3793 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3794 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3795 		.args = ARGS(ARGS_ENTRY(struct buffer,
3796 					args.vc.act_templ_id)),
3797 		.call = parse_qo,
3798 	},
3799 	[QUEUE_RULE_ID] = {
3800 		.name = "rule_index",
3801 		.help = "specify flow rule index",
3802 		.next = NEXT(next_async_pattern_subcmd,
3803 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3804 		.args = ARGS(ARGS_ENTRY(struct buffer,
3805 					args.vc.rule_id)),
3806 		.call = parse_qo,
3807 	},
3808 	[QUEUE_CREATE_POSTPONE] = {
3809 		.name = "postpone",
3810 		.help = "postpone create operation",
3811 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3812 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3813 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3814 		.call = parse_qo,
3815 	},
3816 	[QUEUE_DESTROY_POSTPONE] = {
3817 		.name = "postpone",
3818 		.help = "postpone destroy operation",
3819 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3820 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3821 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3822 		.call = parse_qo_destroy,
3823 	},
3824 	[QUEUE_DESTROY_ID] = {
3825 		.name = "rule",
3826 		.help = "specify rule id to destroy",
3827 		.next = NEXT(next_queue_destroy_attr,
3828 			NEXT_ENTRY(COMMON_UNSIGNED)),
3829 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3830 					    args.destroy.rule)),
3831 		.call = parse_qo_destroy,
3832 	},
3833 	[QUEUE_UPDATE_ID] = {
3834 		.name = "rule",
3835 		.help = "specify rule id to update",
3836 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3837 			NEXT_ENTRY(COMMON_UNSIGNED)),
3838 		.args = ARGS(ARGS_ENTRY(struct buffer,
3839 				     args.vc.rule_id)),
3840 		.call = parse_qo,
3841 	},
3842 	/* Queue indirect action arguments */
3843 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3844 		.name = "create",
3845 		.help = "create indirect action",
3846 		.next = NEXT(next_qia_create_attr),
3847 		.call = parse_qia,
3848 	},
3849 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3850 		.name = "update",
3851 		.help = "update indirect action",
3852 		.next = NEXT(next_qia_update_attr,
3853 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3854 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3855 		.call = parse_qia,
3856 	},
3857 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3858 		.name = "destroy",
3859 		.help = "destroy indirect action",
3860 		.next = NEXT(next_qia_destroy_attr),
3861 		.call = parse_qia_destroy,
3862 	},
3863 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3864 		.name = "query",
3865 		.help = "query indirect action",
3866 		.next = NEXT(next_qia_query_attr,
3867 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3868 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3869 		.call = parse_qia,
3870 	},
3871 	/* Indirect action destroy arguments. */
3872 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3873 		.name = "postpone",
3874 		.help = "postpone destroy operation",
3875 		.next = NEXT(next_qia_destroy_attr,
3876 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3877 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3878 	},
3879 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3880 		.name = "action_id",
3881 		.help = "specify a indirect action id to destroy",
3882 		.next = NEXT(next_qia_destroy_attr,
3883 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3884 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3885 					    args.ia_destroy.action_id)),
3886 		.call = parse_qia_destroy,
3887 	},
3888 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3889 		.name = "query_update",
3890 		.help = "indirect query [and|or] update action",
3891 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3892 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3893 		.call = parse_qia
3894 	},
3895 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3896 		.name = "mode",
3897 		.help = "indirect query [and|or] update action",
3898 		.next = NEXT(next_qia_qu_attr,
3899 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3900 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3901 		.call = parse_qia
3902 	},
3903 	/* Indirect action update arguments. */
3904 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3905 		.name = "postpone",
3906 		.help = "postpone update operation",
3907 		.next = NEXT(next_qia_update_attr,
3908 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3909 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3910 	},
3911 	/* Indirect action update arguments. */
3912 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3913 		.name = "postpone",
3914 		.help = "postpone query operation",
3915 		.next = NEXT(next_qia_query_attr,
3916 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3917 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3918 	},
3919 	/* Indirect action create arguments. */
3920 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3921 		.name = "action_id",
3922 		.help = "specify a indirect action id to create",
3923 		.next = NEXT(next_qia_create_attr,
3924 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3925 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3926 	},
3927 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3928 		.name = "ingress",
3929 		.help = "affect rule to ingress",
3930 		.next = NEXT(next_qia_create_attr),
3931 		.call = parse_qia,
3932 	},
3933 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3934 		.name = "egress",
3935 		.help = "affect rule to egress",
3936 		.next = NEXT(next_qia_create_attr),
3937 		.call = parse_qia,
3938 	},
3939 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3940 		.name = "transfer",
3941 		.help = "affect rule to transfer",
3942 		.next = NEXT(next_qia_create_attr),
3943 		.call = parse_qia,
3944 	},
3945 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3946 		.name = "postpone",
3947 		.help = "postpone create operation",
3948 		.next = NEXT(next_qia_create_attr,
3949 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3950 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3951 	},
3952 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3953 		.name = "action",
3954 		.help = "specify action to create indirect handle",
3955 		.next = NEXT(next_action),
3956 	},
3957 	[QUEUE_INDIRECT_ACTION_LIST] = {
3958 		.name = "list",
3959 		.help = "specify actions for indirect handle list",
3960 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3961 		.call = parse_qia,
3962 	},
3963 	/* Top-level command. */
3964 	[PUSH] = {
3965 		.name = "push",
3966 		.help = "push enqueued operations",
3967 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3968 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3969 		.call = parse_push,
3970 	},
3971 	/* Sub-level commands. */
3972 	[PUSH_QUEUE] = {
3973 		.name = "queue",
3974 		.help = "specify queue id",
3975 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3976 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3977 	},
3978 	/* Top-level command. */
3979 	[PULL] = {
3980 		.name = "pull",
3981 		.help = "pull flow operations results",
3982 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3983 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3984 		.call = parse_pull,
3985 	},
3986 	/* Sub-level commands. */
3987 	[PULL_QUEUE] = {
3988 		.name = "queue",
3989 		.help = "specify queue id",
3990 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3991 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3992 	},
3993 	/* Top-level command. */
3994 	[HASH] = {
3995 		.name = "hash",
3996 		.help = "calculate hash for a given pattern in a given template table",
3997 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3998 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3999 		.call = parse_hash,
4000 	},
4001 	/* Sub-level commands. */
4002 	[HASH_CALC_TABLE] = {
4003 		.name = "template_table",
4004 		.help = "specify table id",
4005 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
4006 			     NEXT_ENTRY(COMMON_TABLE_ID)),
4007 		.args = ARGS(ARGS_ENTRY(struct buffer,
4008 					args.vc.table_id)),
4009 		.call = parse_hash,
4010 	},
4011 	[HASH_CALC_ENCAP] = {
4012 		.name = "encap",
4013 		.help = "calculates encap hash",
4014 		.next = NEXT(next_hash_encap_dest_subcmd),
4015 		.call = parse_hash,
4016 	},
4017 	[HASH_CALC_PATTERN_INDEX] = {
4018 		.name = "pattern_template",
4019 		.help = "specify pattern template id",
4020 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
4021 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4022 		.args = ARGS(ARGS_ENTRY(struct buffer,
4023 					args.vc.pat_templ_id)),
4024 		.call = parse_hash,
4025 	},
4026 	[ENCAP_HASH_FIELD_SRC_PORT] = {
4027 		.name = "hash_field_sport",
4028 		.help = "the encap hash field is src port",
4029 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4030 		.call = parse_hash,
4031 	},
4032 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
4033 		.name = "hash_field_flow_id",
4034 		.help = "the encap hash field is NVGRE flow id",
4035 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4036 		.call = parse_hash,
4037 	},
4038 	/* Top-level command. */
4039 	[INDIRECT_ACTION] = {
4040 		.name = "indirect_action",
4041 		.type = "{command} {port_id} [{arg} [...]]",
4042 		.help = "manage indirect actions",
4043 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4044 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4045 		.call = parse_ia,
4046 	},
4047 	/* Sub-level commands. */
4048 	[INDIRECT_ACTION_CREATE] = {
4049 		.name = "create",
4050 		.help = "create indirect action",
4051 		.next = NEXT(next_ia_create_attr),
4052 		.call = parse_ia,
4053 	},
4054 	[INDIRECT_ACTION_UPDATE] = {
4055 		.name = "update",
4056 		.help = "update indirect action",
4057 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4058 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4059 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4060 		.call = parse_ia,
4061 	},
4062 	[INDIRECT_ACTION_DESTROY] = {
4063 		.name = "destroy",
4064 		.help = "destroy indirect action",
4065 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4066 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4067 		.call = parse_ia_destroy,
4068 	},
4069 	[INDIRECT_ACTION_QUERY] = {
4070 		.name = "query",
4071 		.help = "query indirect action",
4072 		.next = NEXT(NEXT_ENTRY(END),
4073 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4074 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4075 		.call = parse_ia,
4076 	},
4077 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4078 		.name = "query_update",
4079 		.help = "query [and|or] update",
4080 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4081 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4082 		.call = parse_ia
4083 	},
4084 	[INDIRECT_ACTION_QU_MODE] = {
4085 		.name = "mode",
4086 		.help = "query_update mode",
4087 		.next = NEXT(next_ia_qu_attr,
4088 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4089 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4090 		.call = parse_ia,
4091 	},
4092 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4093 		.name = "mode_name",
4094 		.help = "query-update mode name",
4095 		.call = parse_qu_mode_name,
4096 		.comp = comp_qu_mode_name,
4097 	},
4098 	[VALIDATE] = {
4099 		.name = "validate",
4100 		.help = "check whether a flow rule can be created",
4101 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4102 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4103 		.call = parse_vc,
4104 	},
4105 	[CREATE] = {
4106 		.name = "create",
4107 		.help = "create a flow rule",
4108 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4109 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4110 		.call = parse_vc,
4111 	},
4112 	[DESTROY] = {
4113 		.name = "destroy",
4114 		.help = "destroy specific flow rules",
4115 		.next = NEXT(next_destroy_attr,
4116 			     NEXT_ENTRY(COMMON_PORT_ID)),
4117 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4118 		.call = parse_destroy,
4119 	},
4120 	[UPDATE] = {
4121 		.name = "update",
4122 		.help = "update a flow rule with new actions",
4123 		.next = NEXT(NEXT_ENTRY(VC_IS_USER_ID, END),
4124 			     NEXT_ENTRY(ACTIONS),
4125 			     NEXT_ENTRY(COMMON_RULE_ID),
4126 			     NEXT_ENTRY(COMMON_PORT_ID)),
4127 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.rule_id),
4128 			     ARGS_ENTRY(struct buffer, port)),
4129 		.call = parse_vc,
4130 	},
4131 	[FLUSH] = {
4132 		.name = "flush",
4133 		.help = "destroy all flow rules",
4134 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4135 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4136 		.call = parse_flush,
4137 	},
4138 	[DUMP] = {
4139 		.name = "dump",
4140 		.help = "dump single/all flow rules to file",
4141 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4142 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4143 		.call = parse_dump,
4144 	},
4145 	[QUERY] = {
4146 		.name = "query",
4147 		.help = "query an existing flow rule",
4148 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4149 			     NEXT_ENTRY(COMMON_RULE_ID),
4150 			     NEXT_ENTRY(COMMON_PORT_ID)),
4151 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4152 			     ARGS_ENTRY(struct buffer, args.query.rule),
4153 			     ARGS_ENTRY(struct buffer, port)),
4154 		.call = parse_query,
4155 	},
4156 	[LIST] = {
4157 		.name = "list",
4158 		.help = "list existing flow rules",
4159 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4160 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4161 		.call = parse_list,
4162 	},
4163 	[AGED] = {
4164 		.name = "aged",
4165 		.help = "list and destroy aged flows",
4166 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4167 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4168 		.call = parse_aged,
4169 	},
4170 	[ISOLATE] = {
4171 		.name = "isolate",
4172 		.help = "restrict ingress traffic to the defined flow rules",
4173 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4174 			     NEXT_ENTRY(COMMON_PORT_ID)),
4175 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4176 			     ARGS_ENTRY(struct buffer, port)),
4177 		.call = parse_isolate,
4178 	},
4179 	[FLEX] = {
4180 		.name = "flex_item",
4181 		.help = "flex item API",
4182 		.next = NEXT(next_flex_item),
4183 		.call = parse_flex,
4184 	},
4185 	[FLEX_ITEM_CREATE] = {
4186 		.name = "create",
4187 		.help = "flex item create",
4188 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4189 			     ARGS_ENTRY(struct buffer, args.flex.token),
4190 			     ARGS_ENTRY(struct buffer, port)),
4191 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4192 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4193 			     NEXT_ENTRY(COMMON_PORT_ID)),
4194 		.call = parse_flex
4195 	},
4196 	[FLEX_ITEM_DESTROY] = {
4197 		.name = "destroy",
4198 		.help = "flex item destroy",
4199 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4200 			     ARGS_ENTRY(struct buffer, port)),
4201 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4202 			     NEXT_ENTRY(COMMON_PORT_ID)),
4203 		.call = parse_flex
4204 	},
4205 	[TUNNEL] = {
4206 		.name = "tunnel",
4207 		.help = "new tunnel API",
4208 		.next = NEXT(NEXT_ENTRY
4209 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4210 		.call = parse_tunnel,
4211 	},
4212 	/* Tunnel arguments. */
4213 	[TUNNEL_CREATE] = {
4214 		.name = "create",
4215 		.help = "create new tunnel object",
4216 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4217 			     NEXT_ENTRY(COMMON_PORT_ID)),
4218 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4219 		.call = parse_tunnel,
4220 	},
4221 	[TUNNEL_CREATE_TYPE] = {
4222 		.name = "type",
4223 		.help = "create new tunnel",
4224 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4225 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4226 		.call = parse_tunnel,
4227 	},
4228 	[TUNNEL_DESTROY] = {
4229 		.name = "destroy",
4230 		.help = "destroy tunnel",
4231 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4232 			     NEXT_ENTRY(COMMON_PORT_ID)),
4233 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4234 		.call = parse_tunnel,
4235 	},
4236 	[TUNNEL_DESTROY_ID] = {
4237 		.name = "id",
4238 		.help = "tunnel identifier to destroy",
4239 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4240 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4241 		.call = parse_tunnel,
4242 	},
4243 	[TUNNEL_LIST] = {
4244 		.name = "list",
4245 		.help = "list existing tunnels",
4246 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4247 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4248 		.call = parse_tunnel,
4249 	},
4250 	/* Destroy arguments. */
4251 	[DESTROY_RULE] = {
4252 		.name = "rule",
4253 		.help = "specify a rule identifier",
4254 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4255 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4256 		.call = parse_destroy,
4257 	},
4258 	[DESTROY_IS_USER_ID] = {
4259 		.name = "user_id",
4260 		.help = "rule identifier is user-id",
4261 		.next = NEXT(next_destroy_attr),
4262 		.call = parse_destroy,
4263 	},
4264 	/* Dump arguments. */
4265 	[DUMP_ALL] = {
4266 		.name = "all",
4267 		.help = "dump all",
4268 		.next = NEXT(next_dump_attr),
4269 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4270 		.call = parse_dump,
4271 	},
4272 	[DUMP_ONE] = {
4273 		.name = "rule",
4274 		.help = "dump one rule",
4275 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4276 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4277 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4278 		.call = parse_dump,
4279 	},
4280 	[DUMP_IS_USER_ID] = {
4281 		.name = "user_id",
4282 		.help = "rule identifier is user-id",
4283 		.next = NEXT(next_dump_subcmd),
4284 		.call = parse_dump,
4285 	},
4286 	/* Query arguments. */
4287 	[QUERY_ACTION] = {
4288 		.name = "{action}",
4289 		.type = "ACTION",
4290 		.help = "action to query, must be part of the rule",
4291 		.call = parse_action,
4292 		.comp = comp_action,
4293 	},
4294 	[QUERY_IS_USER_ID] = {
4295 		.name = "user_id",
4296 		.help = "rule identifier is user-id",
4297 		.next = NEXT(next_query_attr),
4298 		.call = parse_query,
4299 	},
4300 	/* List arguments. */
4301 	[LIST_GROUP] = {
4302 		.name = "group",
4303 		.help = "specify a group",
4304 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4305 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4306 		.call = parse_list,
4307 	},
4308 	[AGED_DESTROY] = {
4309 		.name = "destroy",
4310 		.help = "specify aged flows need be destroyed",
4311 		.call = parse_aged,
4312 		.comp = comp_none,
4313 	},
4314 	/* Validate/create attributes. */
4315 	[VC_GROUP] = {
4316 		.name = "group",
4317 		.help = "specify a group",
4318 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4319 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4320 		.call = parse_vc,
4321 	},
4322 	[VC_PRIORITY] = {
4323 		.name = "priority",
4324 		.help = "specify a priority level",
4325 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4326 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4327 		.call = parse_vc,
4328 	},
4329 	[VC_INGRESS] = {
4330 		.name = "ingress",
4331 		.help = "affect rule to ingress",
4332 		.next = NEXT(next_vc_attr),
4333 		.call = parse_vc,
4334 	},
4335 	[VC_EGRESS] = {
4336 		.name = "egress",
4337 		.help = "affect rule to egress",
4338 		.next = NEXT(next_vc_attr),
4339 		.call = parse_vc,
4340 	},
4341 	[VC_TRANSFER] = {
4342 		.name = "transfer",
4343 		.help = "apply rule directly to endpoints found in pattern",
4344 		.next = NEXT(next_vc_attr),
4345 		.call = parse_vc,
4346 	},
4347 	[VC_TUNNEL_SET] = {
4348 		.name = "tunnel_set",
4349 		.help = "tunnel steer rule",
4350 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4351 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4352 		.call = parse_vc,
4353 	},
4354 	[VC_TUNNEL_MATCH] = {
4355 		.name = "tunnel_match",
4356 		.help = "tunnel match rule",
4357 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4358 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4359 		.call = parse_vc,
4360 	},
4361 	[VC_USER_ID] = {
4362 		.name = "user_id",
4363 		.help = "specify a user id to create",
4364 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4365 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4366 		.call = parse_vc,
4367 	},
4368 	[VC_IS_USER_ID] = {
4369 		.name = "user_id",
4370 		.help = "rule identifier is user-id",
4371 		.call = parse_vc,
4372 	},
4373 	/* Validate/create pattern. */
4374 	[ITEM_PATTERN] = {
4375 		.name = "pattern",
4376 		.help = "submit a list of pattern items",
4377 		.next = NEXT(next_item),
4378 		.call = parse_vc,
4379 	},
4380 	[ITEM_PARAM_IS] = {
4381 		.name = "is",
4382 		.help = "match value perfectly (with full bit-mask)",
4383 		.call = parse_vc_spec,
4384 	},
4385 	[ITEM_PARAM_SPEC] = {
4386 		.name = "spec",
4387 		.help = "match value according to configured bit-mask",
4388 		.call = parse_vc_spec,
4389 	},
4390 	[ITEM_PARAM_LAST] = {
4391 		.name = "last",
4392 		.help = "specify upper bound to establish a range",
4393 		.call = parse_vc_spec,
4394 	},
4395 	[ITEM_PARAM_MASK] = {
4396 		.name = "mask",
4397 		.help = "specify bit-mask with relevant bits set to one",
4398 		.call = parse_vc_spec,
4399 	},
4400 	[ITEM_PARAM_PREFIX] = {
4401 		.name = "prefix",
4402 		.help = "generate bit-mask from a prefix length",
4403 		.call = parse_vc_spec,
4404 	},
4405 	[ITEM_NEXT] = {
4406 		.name = "/",
4407 		.help = "specify next pattern item",
4408 		.next = NEXT(next_item),
4409 	},
4410 	[ITEM_END] = {
4411 		.name = "end",
4412 		.help = "end list of pattern items",
4413 		.priv = PRIV_ITEM(END, 0),
4414 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4415 		.call = parse_vc,
4416 	},
4417 	[ITEM_VOID] = {
4418 		.name = "void",
4419 		.help = "no-op pattern item",
4420 		.priv = PRIV_ITEM(VOID, 0),
4421 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4422 		.call = parse_vc,
4423 	},
4424 	[ITEM_INVERT] = {
4425 		.name = "invert",
4426 		.help = "perform actions when pattern does not match",
4427 		.priv = PRIV_ITEM(INVERT, 0),
4428 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4429 		.call = parse_vc,
4430 	},
4431 	[ITEM_ANY] = {
4432 		.name = "any",
4433 		.help = "match any protocol for the current layer",
4434 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4435 		.next = NEXT(item_any),
4436 		.call = parse_vc,
4437 	},
4438 	[ITEM_ANY_NUM] = {
4439 		.name = "num",
4440 		.help = "number of layers covered",
4441 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4442 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4443 	},
4444 	[ITEM_PORT_ID] = {
4445 		.name = "port_id",
4446 		.help = "match traffic from/to a given DPDK port ID",
4447 		.priv = PRIV_ITEM(PORT_ID,
4448 				  sizeof(struct rte_flow_item_port_id)),
4449 		.next = NEXT(item_port_id),
4450 		.call = parse_vc,
4451 	},
4452 	[ITEM_PORT_ID_ID] = {
4453 		.name = "id",
4454 		.help = "DPDK port ID",
4455 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4456 			     item_param),
4457 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4458 	},
4459 	[ITEM_MARK] = {
4460 		.name = "mark",
4461 		.help = "match traffic against value set in previously matched rule",
4462 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4463 		.next = NEXT(item_mark),
4464 		.call = parse_vc,
4465 	},
4466 	[ITEM_MARK_ID] = {
4467 		.name = "id",
4468 		.help = "Integer value to match against",
4469 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4470 			     item_param),
4471 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4472 	},
4473 	[ITEM_RAW] = {
4474 		.name = "raw",
4475 		.help = "match an arbitrary byte string",
4476 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4477 		.next = NEXT(item_raw),
4478 		.call = parse_vc,
4479 	},
4480 	[ITEM_RAW_RELATIVE] = {
4481 		.name = "relative",
4482 		.help = "look for pattern after the previous item",
4483 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4484 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4485 					   relative, 1)),
4486 	},
4487 	[ITEM_RAW_SEARCH] = {
4488 		.name = "search",
4489 		.help = "search pattern from offset (see also limit)",
4490 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4491 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4492 					   search, 1)),
4493 	},
4494 	[ITEM_RAW_OFFSET] = {
4495 		.name = "offset",
4496 		.help = "absolute or relative offset for pattern",
4497 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4498 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4499 	},
4500 	[ITEM_RAW_LIMIT] = {
4501 		.name = "limit",
4502 		.help = "search area limit for start of pattern",
4503 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4504 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4505 	},
4506 	[ITEM_RAW_PATTERN] = {
4507 		.name = "pattern",
4508 		.help = "byte string to look for",
4509 		.next = NEXT(item_raw,
4510 			     NEXT_ENTRY(COMMON_STRING),
4511 			     NEXT_ENTRY(ITEM_PARAM_IS,
4512 					ITEM_PARAM_SPEC,
4513 					ITEM_PARAM_MASK)),
4514 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4515 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4516 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4517 					    ITEM_RAW_PATTERN_SIZE)),
4518 	},
4519 	[ITEM_RAW_PATTERN_HEX] = {
4520 		.name = "pattern_hex",
4521 		.help = "hex string to look for",
4522 		.next = NEXT(item_raw,
4523 			     NEXT_ENTRY(COMMON_HEX),
4524 			     NEXT_ENTRY(ITEM_PARAM_IS,
4525 					ITEM_PARAM_SPEC,
4526 					ITEM_PARAM_MASK)),
4527 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4528 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4529 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4530 					    ITEM_RAW_PATTERN_SIZE)),
4531 	},
4532 	[ITEM_ETH] = {
4533 		.name = "eth",
4534 		.help = "match Ethernet header",
4535 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4536 		.next = NEXT(item_eth),
4537 		.call = parse_vc,
4538 	},
4539 	[ITEM_ETH_DST] = {
4540 		.name = "dst",
4541 		.help = "destination MAC",
4542 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4543 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4544 	},
4545 	[ITEM_ETH_SRC] = {
4546 		.name = "src",
4547 		.help = "source MAC",
4548 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4549 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4550 	},
4551 	[ITEM_ETH_TYPE] = {
4552 		.name = "type",
4553 		.help = "EtherType",
4554 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4555 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4556 	},
4557 	[ITEM_ETH_HAS_VLAN] = {
4558 		.name = "has_vlan",
4559 		.help = "packet header contains VLAN",
4560 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4561 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4562 					   has_vlan, 1)),
4563 	},
4564 	[ITEM_VLAN] = {
4565 		.name = "vlan",
4566 		.help = "match 802.1Q/ad VLAN tag",
4567 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4568 		.next = NEXT(item_vlan),
4569 		.call = parse_vc,
4570 	},
4571 	[ITEM_VLAN_TCI] = {
4572 		.name = "tci",
4573 		.help = "tag control information",
4574 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4575 			     item_param),
4576 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4577 	},
4578 	[ITEM_VLAN_PCP] = {
4579 		.name = "pcp",
4580 		.help = "priority code point",
4581 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4582 			     item_param),
4583 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4584 						  hdr.vlan_tci, "\xe0\x00")),
4585 	},
4586 	[ITEM_VLAN_DEI] = {
4587 		.name = "dei",
4588 		.help = "drop eligible indicator",
4589 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4590 			     item_param),
4591 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4592 						  hdr.vlan_tci, "\x10\x00")),
4593 	},
4594 	[ITEM_VLAN_VID] = {
4595 		.name = "vid",
4596 		.help = "VLAN identifier",
4597 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4598 			     item_param),
4599 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4600 						  hdr.vlan_tci, "\x0f\xff")),
4601 	},
4602 	[ITEM_VLAN_INNER_TYPE] = {
4603 		.name = "inner_type",
4604 		.help = "inner EtherType",
4605 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4606 			     item_param),
4607 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4608 					     hdr.eth_proto)),
4609 	},
4610 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4611 		.name = "has_more_vlan",
4612 		.help = "packet header contains another VLAN",
4613 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4614 			     item_param),
4615 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4616 					   has_more_vlan, 1)),
4617 	},
4618 	[ITEM_IPV4] = {
4619 		.name = "ipv4",
4620 		.help = "match IPv4 header",
4621 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4622 		.next = NEXT(item_ipv4),
4623 		.call = parse_vc,
4624 	},
4625 	[ITEM_IPV4_VER_IHL] = {
4626 		.name = "version_ihl",
4627 		.help = "match header length",
4628 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4629 			     item_param),
4630 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4631 				     hdr.version_ihl)),
4632 	},
4633 	[ITEM_IPV4_TOS] = {
4634 		.name = "tos",
4635 		.help = "type of service",
4636 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4637 			     item_param),
4638 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4639 					     hdr.type_of_service)),
4640 	},
4641 	[ITEM_IPV4_LENGTH] = {
4642 		.name = "length",
4643 		.help = "total length",
4644 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4645 			     item_param),
4646 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4647 					     hdr.total_length)),
4648 	},
4649 	[ITEM_IPV4_ID] = {
4650 		.name = "packet_id",
4651 		.help = "fragment packet id",
4652 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4653 			     item_param),
4654 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4655 					     hdr.packet_id)),
4656 	},
4657 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4658 		.name = "fragment_offset",
4659 		.help = "fragmentation flags and fragment offset",
4660 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4661 			     item_param),
4662 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4663 					     hdr.fragment_offset)),
4664 	},
4665 	[ITEM_IPV4_TTL] = {
4666 		.name = "ttl",
4667 		.help = "time to live",
4668 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4669 			     item_param),
4670 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4671 					     hdr.time_to_live)),
4672 	},
4673 	[ITEM_IPV4_PROTO] = {
4674 		.name = "proto",
4675 		.help = "next protocol ID",
4676 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4677 			     item_param),
4678 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4679 					     hdr.next_proto_id)),
4680 	},
4681 	[ITEM_IPV4_SRC] = {
4682 		.name = "src",
4683 		.help = "source address",
4684 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4685 			     item_param),
4686 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4687 					     hdr.src_addr)),
4688 	},
4689 	[ITEM_IPV4_DST] = {
4690 		.name = "dst",
4691 		.help = "destination address",
4692 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4693 			     item_param),
4694 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4695 					     hdr.dst_addr)),
4696 	},
4697 	[ITEM_IPV6] = {
4698 		.name = "ipv6",
4699 		.help = "match IPv6 header",
4700 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4701 		.next = NEXT(item_ipv6),
4702 		.call = parse_vc,
4703 	},
4704 	[ITEM_IPV6_TC] = {
4705 		.name = "tc",
4706 		.help = "traffic class",
4707 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4708 			     item_param),
4709 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4710 						  hdr.vtc_flow,
4711 						  "\x0f\xf0\x00\x00")),
4712 	},
4713 	[ITEM_IPV6_FLOW] = {
4714 		.name = "flow",
4715 		.help = "flow label",
4716 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4717 			     item_param),
4718 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4719 						  hdr.vtc_flow,
4720 						  "\x00\x0f\xff\xff")),
4721 	},
4722 	[ITEM_IPV6_LEN] = {
4723 		.name = "length",
4724 		.help = "payload length",
4725 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4726 			     item_param),
4727 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4728 					     hdr.payload_len)),
4729 	},
4730 	[ITEM_IPV6_PROTO] = {
4731 		.name = "proto",
4732 		.help = "protocol (next header)",
4733 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4734 			     item_param),
4735 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4736 					     hdr.proto)),
4737 	},
4738 	[ITEM_IPV6_HOP] = {
4739 		.name = "hop",
4740 		.help = "hop limit",
4741 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4742 			     item_param),
4743 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4744 					     hdr.hop_limits)),
4745 	},
4746 	[ITEM_IPV6_SRC] = {
4747 		.name = "src",
4748 		.help = "source address",
4749 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4750 			     item_param),
4751 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4752 					     hdr.src_addr)),
4753 	},
4754 	[ITEM_IPV6_DST] = {
4755 		.name = "dst",
4756 		.help = "destination address",
4757 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4758 			     item_param),
4759 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4760 					     hdr.dst_addr)),
4761 	},
4762 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4763 		.name = "has_frag_ext",
4764 		.help = "fragment packet attribute",
4765 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4766 			     item_param),
4767 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4768 					   has_frag_ext, 1)),
4769 	},
4770 	[ITEM_IPV6_ROUTING_EXT] = {
4771 		.name = "ipv6_routing_ext",
4772 		.help = "match IPv6 routing extension header",
4773 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4774 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4775 		.next = NEXT(item_ipv6_routing_ext),
4776 		.call = parse_vc,
4777 	},
4778 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4779 		.name = "ext_type",
4780 		.help = "match IPv6 routing extension header type",
4781 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4782 			     item_param),
4783 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4784 					     hdr.type)),
4785 	},
4786 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4787 		.name = "ext_next_hdr",
4788 		.help = "match IPv6 routing extension header next header type",
4789 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4790 			     item_param),
4791 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4792 					     hdr.next_hdr)),
4793 	},
4794 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4795 		.name = "ext_seg_left",
4796 		.help = "match IPv6 routing extension header segment left",
4797 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4798 			     item_param),
4799 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4800 					     hdr.segments_left)),
4801 	},
4802 	[ITEM_ICMP] = {
4803 		.name = "icmp",
4804 		.help = "match ICMP header",
4805 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4806 		.next = NEXT(item_icmp),
4807 		.call = parse_vc,
4808 	},
4809 	[ITEM_ICMP_TYPE] = {
4810 		.name = "type",
4811 		.help = "ICMP packet type",
4812 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4813 			     item_param),
4814 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4815 					     hdr.icmp_type)),
4816 	},
4817 	[ITEM_ICMP_CODE] = {
4818 		.name = "code",
4819 		.help = "ICMP packet code",
4820 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4821 			     item_param),
4822 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4823 					     hdr.icmp_code)),
4824 	},
4825 	[ITEM_ICMP_IDENT] = {
4826 		.name = "ident",
4827 		.help = "ICMP packet identifier",
4828 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4829 			     item_param),
4830 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4831 					     hdr.icmp_ident)),
4832 	},
4833 	[ITEM_ICMP_SEQ] = {
4834 		.name = "seq",
4835 		.help = "ICMP packet sequence number",
4836 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4837 			     item_param),
4838 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4839 					     hdr.icmp_seq_nb)),
4840 	},
4841 	[ITEM_UDP] = {
4842 		.name = "udp",
4843 		.help = "match UDP header",
4844 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4845 		.next = NEXT(item_udp),
4846 		.call = parse_vc,
4847 	},
4848 	[ITEM_UDP_SRC] = {
4849 		.name = "src",
4850 		.help = "UDP source port",
4851 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4852 			     item_param),
4853 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4854 					     hdr.src_port)),
4855 	},
4856 	[ITEM_UDP_DST] = {
4857 		.name = "dst",
4858 		.help = "UDP destination port",
4859 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4860 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4861 					     hdr.dst_port)),
4862 	},
4863 	[ITEM_TCP] = {
4864 		.name = "tcp",
4865 		.help = "match TCP header",
4866 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4867 		.next = NEXT(item_tcp),
4868 		.call = parse_vc,
4869 	},
4870 	[ITEM_TCP_SRC] = {
4871 		.name = "src",
4872 		.help = "TCP source port",
4873 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4874 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4875 					     hdr.src_port)),
4876 	},
4877 	[ITEM_TCP_DST] = {
4878 		.name = "dst",
4879 		.help = "TCP destination port",
4880 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4881 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4882 					     hdr.dst_port)),
4883 	},
4884 	[ITEM_TCP_FLAGS] = {
4885 		.name = "flags",
4886 		.help = "TCP flags",
4887 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4888 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4889 					     hdr.tcp_flags)),
4890 	},
4891 	[ITEM_SCTP] = {
4892 		.name = "sctp",
4893 		.help = "match SCTP header",
4894 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4895 		.next = NEXT(item_sctp),
4896 		.call = parse_vc,
4897 	},
4898 	[ITEM_SCTP_SRC] = {
4899 		.name = "src",
4900 		.help = "SCTP source port",
4901 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4902 			     item_param),
4903 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4904 					     hdr.src_port)),
4905 	},
4906 	[ITEM_SCTP_DST] = {
4907 		.name = "dst",
4908 		.help = "SCTP destination port",
4909 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4910 			     item_param),
4911 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4912 					     hdr.dst_port)),
4913 	},
4914 	[ITEM_SCTP_TAG] = {
4915 		.name = "tag",
4916 		.help = "validation tag",
4917 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4918 			     item_param),
4919 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4920 					     hdr.tag)),
4921 	},
4922 	[ITEM_SCTP_CKSUM] = {
4923 		.name = "cksum",
4924 		.help = "checksum",
4925 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4926 			     item_param),
4927 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4928 					     hdr.cksum)),
4929 	},
4930 	[ITEM_VXLAN] = {
4931 		.name = "vxlan",
4932 		.help = "match VXLAN header",
4933 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4934 		.next = NEXT(item_vxlan),
4935 		.call = parse_vc,
4936 	},
4937 	[ITEM_VXLAN_VNI] = {
4938 		.name = "vni",
4939 		.help = "VXLAN identifier",
4940 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4941 			     item_param),
4942 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4943 	},
4944 	[ITEM_VXLAN_FLAG_G] = {
4945 		.name = "flag_g",
4946 		.help = "VXLAN GBP bit",
4947 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4948 			     item_param),
4949 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4950 					   hdr.flag_g, 1)),
4951 	},
4952 	[ITEM_VXLAN_FLAG_VER] = {
4953 		.name = "flag_ver",
4954 		.help = "VXLAN GPE version",
4955 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4956 			     item_param),
4957 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4958 					   hdr.flag_ver, 2)),
4959 	},
4960 	[ITEM_VXLAN_FLAG_I] = {
4961 		.name = "flag_i",
4962 		.help = "VXLAN Instance bit",
4963 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4964 			     item_param),
4965 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4966 					   hdr.flag_i, 1)),
4967 	},
4968 	[ITEM_VXLAN_FLAG_P] = {
4969 		.name = "flag_p",
4970 		.help = "VXLAN GPE Next Protocol bit",
4971 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4972 			     item_param),
4973 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4974 					   hdr.flag_p, 1)),
4975 	},
4976 	[ITEM_VXLAN_FLAG_B] = {
4977 		.name = "flag_b",
4978 		.help = "VXLAN GPE Ingress-Replicated BUM",
4979 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4980 			     item_param),
4981 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4982 					   hdr.flag_b, 1)),
4983 	},
4984 	[ITEM_VXLAN_FLAG_O] = {
4985 		.name = "flag_o",
4986 		.help = "VXLAN GPE OAM Packet bit",
4987 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4988 			     item_param),
4989 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4990 					   hdr.flag_o, 1)),
4991 	},
4992 	[ITEM_VXLAN_FLAG_D] = {
4993 		.name = "flag_d",
4994 		.help = "VXLAN GBP Don't Learn bit",
4995 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4996 			     item_param),
4997 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4998 					   hdr.flag_d, 1)),
4999 	},
5000 	[ITEM_VXLAN_FLAG_A] = {
5001 		.name = "flag_a",
5002 		.help = "VXLAN GBP Applied bit",
5003 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5004 			     item_param),
5005 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
5006 					   hdr.flag_a, 1)),
5007 	},
5008 	[ITEM_VXLAN_GBP_ID] = {
5009 		.name = "group_policy_id",
5010 		.help = "VXLAN GBP ID",
5011 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5012 			     item_param),
5013 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5014 					     hdr.policy_id)),
5015 	},
5016 	[ITEM_VXLAN_GPE_PROTO] = {
5017 		.name = "protocol",
5018 		.help = "VXLAN GPE next protocol",
5019 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5020 			     item_param),
5021 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5022 					     hdr.proto)),
5023 	},
5024 	[ITEM_VXLAN_FIRST_RSVD] = {
5025 		.name = "first_rsvd",
5026 		.help = "VXLAN rsvd0 first byte",
5027 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5028 			     item_param),
5029 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5030 					     hdr.rsvd0[0])),
5031 	},
5032 	[ITEM_VXLAN_SECND_RSVD] = {
5033 		.name = "second_rsvd",
5034 		.help = "VXLAN rsvd0 second byte",
5035 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5036 			     item_param),
5037 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5038 					     hdr.rsvd0[1])),
5039 	},
5040 	[ITEM_VXLAN_THIRD_RSVD] = {
5041 		.name = "third_rsvd",
5042 		.help = "VXLAN rsvd0 third byte",
5043 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5044 			     item_param),
5045 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5046 					     hdr.rsvd0[2])),
5047 	},
5048 	[ITEM_VXLAN_LAST_RSVD] = {
5049 		.name = "last_rsvd",
5050 		.help = "VXLAN last reserved byte",
5051 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5052 			     item_param),
5053 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5054 					     hdr.last_rsvd)),
5055 	},
5056 	[ITEM_E_TAG] = {
5057 		.name = "e_tag",
5058 		.help = "match E-Tag header",
5059 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
5060 		.next = NEXT(item_e_tag),
5061 		.call = parse_vc,
5062 	},
5063 	[ITEM_E_TAG_GRP_ECID_B] = {
5064 		.name = "grp_ecid_b",
5065 		.help = "GRP and E-CID base",
5066 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5067 			     item_param),
5068 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
5069 						  rsvd_grp_ecid_b,
5070 						  "\x3f\xff")),
5071 	},
5072 	[ITEM_NVGRE] = {
5073 		.name = "nvgre",
5074 		.help = "match NVGRE header",
5075 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
5076 		.next = NEXT(item_nvgre),
5077 		.call = parse_vc,
5078 	},
5079 	[ITEM_NVGRE_TNI] = {
5080 		.name = "tni",
5081 		.help = "virtual subnet ID",
5082 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
5083 			     item_param),
5084 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
5085 	},
5086 	[ITEM_MPLS] = {
5087 		.name = "mpls",
5088 		.help = "match MPLS header",
5089 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
5090 		.next = NEXT(item_mpls),
5091 		.call = parse_vc,
5092 	},
5093 	[ITEM_MPLS_LABEL] = {
5094 		.name = "label",
5095 		.help = "MPLS label",
5096 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5097 			     item_param),
5098 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5099 						  label_tc_s,
5100 						  "\xff\xff\xf0")),
5101 	},
5102 	[ITEM_MPLS_TC] = {
5103 		.name = "tc",
5104 		.help = "MPLS Traffic Class",
5105 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5106 			     item_param),
5107 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5108 						  label_tc_s,
5109 						  "\x00\x00\x0e")),
5110 	},
5111 	[ITEM_MPLS_S] = {
5112 		.name = "s",
5113 		.help = "MPLS Bottom-of-Stack",
5114 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5115 			     item_param),
5116 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5117 						  label_tc_s,
5118 						  "\x00\x00\x01")),
5119 	},
5120 	[ITEM_MPLS_TTL] = {
5121 		.name = "ttl",
5122 		.help = "MPLS Time-to-Live",
5123 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5124 			     item_param),
5125 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
5126 	},
5127 	[ITEM_GRE] = {
5128 		.name = "gre",
5129 		.help = "match GRE header",
5130 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
5131 		.next = NEXT(item_gre),
5132 		.call = parse_vc,
5133 	},
5134 	[ITEM_GRE_PROTO] = {
5135 		.name = "protocol",
5136 		.help = "GRE protocol type",
5137 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5138 			     item_param),
5139 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5140 					     protocol)),
5141 	},
5142 	[ITEM_GRE_C_RSVD0_VER] = {
5143 		.name = "c_rsvd0_ver",
5144 		.help =
5145 			"checksum (1b), undefined (1b), key bit (1b),"
5146 			" sequence number (1b), reserved 0 (9b),"
5147 			" version (3b)",
5148 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5149 			     item_param),
5150 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5151 					     c_rsvd0_ver)),
5152 	},
5153 	[ITEM_GRE_C_BIT] = {
5154 		.name = "c_bit",
5155 		.help = "checksum bit (C)",
5156 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5157 			     item_param),
5158 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5159 						  c_rsvd0_ver,
5160 						  "\x80\x00\x00\x00")),
5161 	},
5162 	[ITEM_GRE_S_BIT] = {
5163 		.name = "s_bit",
5164 		.help = "sequence number bit (S)",
5165 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5166 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5167 						  c_rsvd0_ver,
5168 						  "\x10\x00\x00\x00")),
5169 	},
5170 	[ITEM_GRE_K_BIT] = {
5171 		.name = "k_bit",
5172 		.help = "key bit (K)",
5173 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5174 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5175 						  c_rsvd0_ver,
5176 						  "\x20\x00\x00\x00")),
5177 	},
5178 	[ITEM_FUZZY] = {
5179 		.name = "fuzzy",
5180 		.help = "fuzzy pattern match, expect faster than default",
5181 		.priv = PRIV_ITEM(FUZZY,
5182 				sizeof(struct rte_flow_item_fuzzy)),
5183 		.next = NEXT(item_fuzzy),
5184 		.call = parse_vc,
5185 	},
5186 	[ITEM_FUZZY_THRESH] = {
5187 		.name = "thresh",
5188 		.help = "match accuracy threshold",
5189 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5190 			     item_param),
5191 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5192 					thresh)),
5193 	},
5194 	[ITEM_GTP] = {
5195 		.name = "gtp",
5196 		.help = "match GTP header",
5197 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5198 		.next = NEXT(item_gtp),
5199 		.call = parse_vc,
5200 	},
5201 	[ITEM_GTP_FLAGS] = {
5202 		.name = "v_pt_rsv_flags",
5203 		.help = "GTP flags",
5204 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5205 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5206 					hdr.gtp_hdr_info)),
5207 	},
5208 	[ITEM_GTP_MSG_TYPE] = {
5209 		.name = "msg_type",
5210 		.help = "GTP message type",
5211 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5212 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5213 	},
5214 	[ITEM_GTP_TEID] = {
5215 		.name = "teid",
5216 		.help = "tunnel endpoint identifier",
5217 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5218 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5219 	},
5220 	[ITEM_GTPC] = {
5221 		.name = "gtpc",
5222 		.help = "match GTP header",
5223 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5224 		.next = NEXT(item_gtp),
5225 		.call = parse_vc,
5226 	},
5227 	[ITEM_GTPU] = {
5228 		.name = "gtpu",
5229 		.help = "match GTP header",
5230 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5231 		.next = NEXT(item_gtp),
5232 		.call = parse_vc,
5233 	},
5234 	[ITEM_GENEVE] = {
5235 		.name = "geneve",
5236 		.help = "match GENEVE header",
5237 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5238 		.next = NEXT(item_geneve),
5239 		.call = parse_vc,
5240 	},
5241 	[ITEM_GENEVE_VNI] = {
5242 		.name = "vni",
5243 		.help = "virtual network identifier",
5244 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5245 			     item_param),
5246 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5247 	},
5248 	[ITEM_GENEVE_PROTO] = {
5249 		.name = "protocol",
5250 		.help = "GENEVE protocol type",
5251 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5252 			     item_param),
5253 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5254 					     protocol)),
5255 	},
5256 	[ITEM_GENEVE_OPTLEN] = {
5257 		.name = "optlen",
5258 		.help = "GENEVE options length in dwords",
5259 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5260 			     item_param),
5261 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5262 						  ver_opt_len_o_c_rsvd0,
5263 						  "\x3f\x00")),
5264 	},
5265 	[ITEM_VXLAN_GPE] = {
5266 		.name = "vxlan-gpe",
5267 		.help = "match VXLAN-GPE header",
5268 		.priv = PRIV_ITEM(VXLAN_GPE,
5269 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5270 		.next = NEXT(item_vxlan_gpe),
5271 		.call = parse_vc,
5272 	},
5273 	[ITEM_VXLAN_GPE_VNI] = {
5274 		.name = "vni",
5275 		.help = "VXLAN-GPE identifier",
5276 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5277 			     item_param),
5278 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5279 					     hdr.vni)),
5280 	},
5281 	[ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR] = {
5282 		.name = "protocol",
5283 		.help = "VXLAN-GPE next protocol",
5284 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5285 			     item_param),
5286 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5287 					     protocol)),
5288 	},
5289 	[ITEM_VXLAN_GPE_FLAGS] = {
5290 		.name = "flags",
5291 		.help = "VXLAN-GPE flags",
5292 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5293 			     item_param),
5294 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5295 					     flags)),
5296 	},
5297 	[ITEM_VXLAN_GPE_RSVD0] = {
5298 		.name = "rsvd0",
5299 		.help = "VXLAN-GPE rsvd0",
5300 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5301 			     item_param),
5302 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5303 					     rsvd0)),
5304 	},
5305 	[ITEM_VXLAN_GPE_RSVD1] = {
5306 		.name = "rsvd1",
5307 		.help = "VXLAN-GPE rsvd1",
5308 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5309 			     item_param),
5310 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5311 					     rsvd1)),
5312 	},
5313 	[ITEM_ARP_ETH_IPV4] = {
5314 		.name = "arp_eth_ipv4",
5315 		.help = "match ARP header for Ethernet/IPv4",
5316 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5317 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5318 		.next = NEXT(item_arp_eth_ipv4),
5319 		.call = parse_vc,
5320 	},
5321 	[ITEM_ARP_ETH_IPV4_SHA] = {
5322 		.name = "sha",
5323 		.help = "sender hardware address",
5324 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5325 			     item_param),
5326 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5327 					     hdr.arp_data.arp_sha)),
5328 	},
5329 	[ITEM_ARP_ETH_IPV4_SPA] = {
5330 		.name = "spa",
5331 		.help = "sender IPv4 address",
5332 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5333 			     item_param),
5334 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5335 					     hdr.arp_data.arp_sip)),
5336 	},
5337 	[ITEM_ARP_ETH_IPV4_THA] = {
5338 		.name = "tha",
5339 		.help = "target hardware address",
5340 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5341 			     item_param),
5342 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5343 					     hdr.arp_data.arp_tha)),
5344 	},
5345 	[ITEM_ARP_ETH_IPV4_TPA] = {
5346 		.name = "tpa",
5347 		.help = "target IPv4 address",
5348 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5349 			     item_param),
5350 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5351 					     hdr.arp_data.arp_tip)),
5352 	},
5353 	[ITEM_IPV6_EXT] = {
5354 		.name = "ipv6_ext",
5355 		.help = "match presence of any IPv6 extension header",
5356 		.priv = PRIV_ITEM(IPV6_EXT,
5357 				  sizeof(struct rte_flow_item_ipv6_ext)),
5358 		.next = NEXT(item_ipv6_ext),
5359 		.call = parse_vc,
5360 	},
5361 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5362 		.name = "next_hdr",
5363 		.help = "next header",
5364 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5365 			     item_param),
5366 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5367 					     next_hdr)),
5368 	},
5369 	[ITEM_IPV6_FRAG_EXT] = {
5370 		.name = "ipv6_frag_ext",
5371 		.help = "match presence of IPv6 fragment extension header",
5372 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5373 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5374 		.next = NEXT(item_ipv6_frag_ext),
5375 		.call = parse_vc,
5376 	},
5377 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5378 		.name = "next_hdr",
5379 		.help = "next header",
5380 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5381 			     item_param),
5382 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5383 					hdr.next_header)),
5384 	},
5385 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5386 		.name = "frag_data",
5387 		.help = "fragment flags and offset",
5388 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5389 			     item_param),
5390 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5391 					     hdr.frag_data)),
5392 	},
5393 	[ITEM_IPV6_FRAG_EXT_ID] = {
5394 		.name = "packet_id",
5395 		.help = "fragment packet id",
5396 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5397 			     item_param),
5398 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5399 					     hdr.id)),
5400 	},
5401 	[ITEM_ICMP6] = {
5402 		.name = "icmp6",
5403 		.help = "match any ICMPv6 header",
5404 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5405 		.next = NEXT(item_icmp6),
5406 		.call = parse_vc,
5407 	},
5408 	[ITEM_ICMP6_TYPE] = {
5409 		.name = "type",
5410 		.help = "ICMPv6 type",
5411 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5412 			     item_param),
5413 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5414 					     type)),
5415 	},
5416 	[ITEM_ICMP6_CODE] = {
5417 		.name = "code",
5418 		.help = "ICMPv6 code",
5419 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5420 			     item_param),
5421 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5422 					     code)),
5423 	},
5424 	[ITEM_ICMP6_ECHO_REQUEST] = {
5425 		.name = "icmp6_echo_request",
5426 		.help = "match ICMPv6 echo request",
5427 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5428 				  sizeof(struct rte_flow_item_icmp6_echo)),
5429 		.next = NEXT(item_icmp6_echo_request),
5430 		.call = parse_vc,
5431 	},
5432 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5433 		.name = "ident",
5434 		.help = "ICMPv6 echo request identifier",
5435 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5436 			     item_param),
5437 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5438 					     hdr.identifier)),
5439 	},
5440 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5441 		.name = "seq",
5442 		.help = "ICMPv6 echo request sequence",
5443 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5444 			     item_param),
5445 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5446 					     hdr.sequence)),
5447 	},
5448 	[ITEM_ICMP6_ECHO_REPLY] = {
5449 		.name = "icmp6_echo_reply",
5450 		.help = "match ICMPv6 echo reply",
5451 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5452 				  sizeof(struct rte_flow_item_icmp6_echo)),
5453 		.next = NEXT(item_icmp6_echo_reply),
5454 		.call = parse_vc,
5455 	},
5456 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5457 		.name = "ident",
5458 		.help = "ICMPv6 echo reply identifier",
5459 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5460 			     item_param),
5461 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5462 					     hdr.identifier)),
5463 	},
5464 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5465 		.name = "seq",
5466 		.help = "ICMPv6 echo reply sequence",
5467 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5468 			     item_param),
5469 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5470 					     hdr.sequence)),
5471 	},
5472 	[ITEM_ICMP6_ND_NS] = {
5473 		.name = "icmp6_nd_ns",
5474 		.help = "match ICMPv6 neighbor discovery solicitation",
5475 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5476 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5477 		.next = NEXT(item_icmp6_nd_ns),
5478 		.call = parse_vc,
5479 	},
5480 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5481 		.name = "target_addr",
5482 		.help = "target address",
5483 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5484 			     item_param),
5485 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5486 					     target_addr)),
5487 	},
5488 	[ITEM_ICMP6_ND_NA] = {
5489 		.name = "icmp6_nd_na",
5490 		.help = "match ICMPv6 neighbor discovery advertisement",
5491 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5492 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5493 		.next = NEXT(item_icmp6_nd_na),
5494 		.call = parse_vc,
5495 	},
5496 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5497 		.name = "target_addr",
5498 		.help = "target address",
5499 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5500 			     item_param),
5501 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5502 					     target_addr)),
5503 	},
5504 	[ITEM_ICMP6_ND_OPT] = {
5505 		.name = "icmp6_nd_opt",
5506 		.help = "match presence of any ICMPv6 neighbor discovery"
5507 			" option",
5508 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5509 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5510 		.next = NEXT(item_icmp6_nd_opt),
5511 		.call = parse_vc,
5512 	},
5513 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5514 		.name = "type",
5515 		.help = "ND option type",
5516 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5517 			     item_param),
5518 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5519 					     type)),
5520 	},
5521 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5522 		.name = "icmp6_nd_opt_sla_eth",
5523 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5524 			" link-layer address option",
5525 		.priv = PRIV_ITEM
5526 			(ICMP6_ND_OPT_SLA_ETH,
5527 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5528 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5529 		.call = parse_vc,
5530 	},
5531 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5532 		.name = "sla",
5533 		.help = "source Ethernet LLA",
5534 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5535 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5536 		.args = ARGS(ARGS_ENTRY_HTON
5537 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5538 	},
5539 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5540 		.name = "icmp6_nd_opt_tla_eth",
5541 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5542 			" link-layer address option",
5543 		.priv = PRIV_ITEM
5544 			(ICMP6_ND_OPT_TLA_ETH,
5545 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5546 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5547 		.call = parse_vc,
5548 	},
5549 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5550 		.name = "tla",
5551 		.help = "target Ethernet LLA",
5552 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5553 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5554 		.args = ARGS(ARGS_ENTRY_HTON
5555 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5556 	},
5557 	[ITEM_META] = {
5558 		.name = "meta",
5559 		.help = "match metadata header",
5560 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5561 		.next = NEXT(item_meta),
5562 		.call = parse_vc,
5563 	},
5564 	[ITEM_META_DATA] = {
5565 		.name = "data",
5566 		.help = "metadata value",
5567 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5568 			     item_param),
5569 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5570 					     data, "\xff\xff\xff\xff")),
5571 	},
5572 	[ITEM_RANDOM] = {
5573 		.name = "random",
5574 		.help = "match random value",
5575 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5576 		.next = NEXT(item_random),
5577 		.call = parse_vc,
5578 	},
5579 	[ITEM_RANDOM_VALUE] = {
5580 		.name = "value",
5581 		.help = "random value",
5582 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5583 			     item_param),
5584 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5585 					     value, "\xff\xff")),
5586 	},
5587 	[ITEM_GRE_KEY] = {
5588 		.name = "gre_key",
5589 		.help = "match GRE key",
5590 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5591 		.next = NEXT(item_gre_key),
5592 		.call = parse_vc,
5593 	},
5594 	[ITEM_GRE_KEY_VALUE] = {
5595 		.name = "value",
5596 		.help = "key value",
5597 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5598 			     item_param),
5599 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5600 	},
5601 	[ITEM_GRE_OPTION] = {
5602 		.name = "gre_option",
5603 		.help = "match GRE optional fields",
5604 		.priv = PRIV_ITEM(GRE_OPTION,
5605 				  sizeof(struct rte_flow_item_gre_opt)),
5606 		.next = NEXT(item_gre_option),
5607 		.call = parse_vc,
5608 	},
5609 	[ITEM_GRE_OPTION_CHECKSUM] = {
5610 		.name = "checksum",
5611 		.help = "match GRE checksum",
5612 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5613 			     item_param),
5614 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5615 					     checksum_rsvd.checksum)),
5616 	},
5617 	[ITEM_GRE_OPTION_KEY] = {
5618 		.name = "key",
5619 		.help = "match GRE key",
5620 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5621 			     item_param),
5622 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5623 					     key.key)),
5624 	},
5625 	[ITEM_GRE_OPTION_SEQUENCE] = {
5626 		.name = "sequence",
5627 		.help = "match GRE sequence",
5628 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5629 			     item_param),
5630 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5631 					     sequence.sequence)),
5632 	},
5633 	[ITEM_GTP_PSC] = {
5634 		.name = "gtp_psc",
5635 		.help = "match GTP extension header with type 0x85",
5636 		.priv = PRIV_ITEM(GTP_PSC,
5637 				sizeof(struct rte_flow_item_gtp_psc)),
5638 		.next = NEXT(item_gtp_psc),
5639 		.call = parse_vc,
5640 	},
5641 	[ITEM_GTP_PSC_QFI] = {
5642 		.name = "qfi",
5643 		.help = "QoS flow identifier",
5644 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5645 			     item_param),
5646 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5647 					hdr.qfi, 6)),
5648 	},
5649 	[ITEM_GTP_PSC_PDU_T] = {
5650 		.name = "pdu_t",
5651 		.help = "PDU type",
5652 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5653 			     item_param),
5654 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5655 					hdr.type, 4)),
5656 	},
5657 	[ITEM_PPPOES] = {
5658 		.name = "pppoes",
5659 		.help = "match PPPoE session header",
5660 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5661 		.next = NEXT(item_pppoes),
5662 		.call = parse_vc,
5663 	},
5664 	[ITEM_PPPOED] = {
5665 		.name = "pppoed",
5666 		.help = "match PPPoE discovery header",
5667 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5668 		.next = NEXT(item_pppoed),
5669 		.call = parse_vc,
5670 	},
5671 	[ITEM_PPPOE_SEID] = {
5672 		.name = "seid",
5673 		.help = "session identifier",
5674 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5675 			     item_param),
5676 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5677 					session_id)),
5678 	},
5679 	[ITEM_PPPOE_PROTO_ID] = {
5680 		.name = "pppoe_proto_id",
5681 		.help = "match PPPoE session protocol identifier",
5682 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5683 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5684 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5685 			     item_param),
5686 		.args = ARGS(ARGS_ENTRY_HTON
5687 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5688 		.call = parse_vc,
5689 	},
5690 	[ITEM_HIGIG2] = {
5691 		.name = "higig2",
5692 		.help = "matches higig2 header",
5693 		.priv = PRIV_ITEM(HIGIG2,
5694 				sizeof(struct rte_flow_item_higig2_hdr)),
5695 		.next = NEXT(item_higig2),
5696 		.call = parse_vc,
5697 	},
5698 	[ITEM_HIGIG2_CLASSIFICATION] = {
5699 		.name = "classification",
5700 		.help = "matches classification of higig2 header",
5701 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5702 			     item_param),
5703 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5704 					hdr.ppt1.classification)),
5705 	},
5706 	[ITEM_HIGIG2_VID] = {
5707 		.name = "vid",
5708 		.help = "matches vid of higig2 header",
5709 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5710 			     item_param),
5711 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5712 					hdr.ppt1.vid)),
5713 	},
5714 	[ITEM_TAG] = {
5715 		.name = "tag",
5716 		.help = "match tag value",
5717 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5718 		.next = NEXT(item_tag),
5719 		.call = parse_vc,
5720 	},
5721 	[ITEM_TAG_DATA] = {
5722 		.name = "data",
5723 		.help = "tag value to match",
5724 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5725 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5726 	},
5727 	[ITEM_TAG_INDEX] = {
5728 		.name = "index",
5729 		.help = "index of tag array to match",
5730 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5731 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5732 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5733 	},
5734 	[ITEM_L2TPV3OIP] = {
5735 		.name = "l2tpv3oip",
5736 		.help = "match L2TPv3 over IP header",
5737 		.priv = PRIV_ITEM(L2TPV3OIP,
5738 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5739 		.next = NEXT(item_l2tpv3oip),
5740 		.call = parse_vc,
5741 	},
5742 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5743 		.name = "session_id",
5744 		.help = "session identifier",
5745 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5746 			     item_param),
5747 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5748 					     session_id)),
5749 	},
5750 	[ITEM_ESP] = {
5751 		.name = "esp",
5752 		.help = "match ESP header",
5753 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5754 		.next = NEXT(item_esp),
5755 		.call = parse_vc,
5756 	},
5757 	[ITEM_ESP_SPI] = {
5758 		.name = "spi",
5759 		.help = "security policy index",
5760 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5761 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5762 				hdr.spi)),
5763 	},
5764 	[ITEM_AH] = {
5765 		.name = "ah",
5766 		.help = "match AH header",
5767 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5768 		.next = NEXT(item_ah),
5769 		.call = parse_vc,
5770 	},
5771 	[ITEM_AH_SPI] = {
5772 		.name = "spi",
5773 		.help = "security parameters index",
5774 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5775 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5776 	},
5777 	[ITEM_PFCP] = {
5778 		.name = "pfcp",
5779 		.help = "match pfcp header",
5780 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5781 		.next = NEXT(item_pfcp),
5782 		.call = parse_vc,
5783 	},
5784 	[ITEM_PFCP_S_FIELD] = {
5785 		.name = "s_field",
5786 		.help = "S field",
5787 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5788 			     item_param),
5789 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5790 				s_field)),
5791 	},
5792 	[ITEM_PFCP_SEID] = {
5793 		.name = "seid",
5794 		.help = "session endpoint identifier",
5795 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5796 			     item_param),
5797 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5798 	},
5799 	[ITEM_ECPRI] = {
5800 		.name = "ecpri",
5801 		.help = "match eCPRI header",
5802 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5803 		.next = NEXT(item_ecpri),
5804 		.call = parse_vc,
5805 	},
5806 	[ITEM_ECPRI_COMMON] = {
5807 		.name = "common",
5808 		.help = "eCPRI common header",
5809 		.next = NEXT(item_ecpri_common),
5810 	},
5811 	[ITEM_ECPRI_COMMON_TYPE] = {
5812 		.name = "type",
5813 		.help = "type of common header",
5814 		.next = NEXT(item_ecpri_common_type),
5815 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5816 	},
5817 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5818 		.name = "iq_data",
5819 		.help = "Type #0: IQ Data",
5820 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5821 					ITEM_NEXT)),
5822 		.call = parse_vc_item_ecpri_type,
5823 	},
5824 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5825 		.name = "pc_id",
5826 		.help = "Physical Channel ID",
5827 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5828 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5829 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5830 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5831 				hdr.type0.pc_id)),
5832 	},
5833 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5834 		.name = "rtc_ctrl",
5835 		.help = "Type #2: Real-Time Control Data",
5836 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5837 					ITEM_NEXT)),
5838 		.call = parse_vc_item_ecpri_type,
5839 	},
5840 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5841 		.name = "rtc_id",
5842 		.help = "Real-Time Control Data ID",
5843 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5844 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5845 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5846 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5847 				hdr.type2.rtc_id)),
5848 	},
5849 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5850 		.name = "delay_measure",
5851 		.help = "Type #5: One-Way Delay Measurement",
5852 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5853 					ITEM_NEXT)),
5854 		.call = parse_vc_item_ecpri_type,
5855 	},
5856 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5857 		.name = "msr_id",
5858 		.help = "Measurement ID",
5859 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5860 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5861 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5862 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5863 				hdr.type5.msr_id)),
5864 	},
5865 	[ITEM_GENEVE_OPT] = {
5866 		.name = "geneve-opt",
5867 		.help = "GENEVE header option",
5868 		.priv = PRIV_ITEM(GENEVE_OPT,
5869 				  sizeof(struct rte_flow_item_geneve_opt) +
5870 				  ITEM_GENEVE_OPT_DATA_SIZE),
5871 		.next = NEXT(item_geneve_opt),
5872 		.call = parse_vc,
5873 	},
5874 	[ITEM_GENEVE_OPT_CLASS]	= {
5875 		.name = "class",
5876 		.help = "GENEVE option class",
5877 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5878 			     item_param),
5879 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5880 					     option_class)),
5881 	},
5882 	[ITEM_GENEVE_OPT_TYPE] = {
5883 		.name = "type",
5884 		.help = "GENEVE option type",
5885 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5886 			     item_param),
5887 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5888 					option_type)),
5889 	},
5890 	[ITEM_GENEVE_OPT_LENGTH] = {
5891 		.name = "length",
5892 		.help = "GENEVE option data length (in 32b words)",
5893 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5894 			     item_param),
5895 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5896 				struct rte_flow_item_geneve_opt, option_len,
5897 				0, 31)),
5898 	},
5899 	[ITEM_GENEVE_OPT_DATA] = {
5900 		.name = "data",
5901 		.help = "GENEVE option data pattern",
5902 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5903 			     item_param),
5904 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5905 			     ARGS_ENTRY_ARB(0, 0),
5906 			     ARGS_ENTRY_ARB
5907 				(sizeof(struct rte_flow_item_geneve_opt),
5908 				ITEM_GENEVE_OPT_DATA_SIZE)),
5909 	},
5910 	[ITEM_INTEGRITY] = {
5911 		.name = "integrity",
5912 		.help = "match packet integrity",
5913 		.priv = PRIV_ITEM(INTEGRITY,
5914 				  sizeof(struct rte_flow_item_integrity)),
5915 		.next = NEXT(item_integrity),
5916 		.call = parse_vc,
5917 	},
5918 	[ITEM_INTEGRITY_LEVEL] = {
5919 		.name = "level",
5920 		.help = "integrity level",
5921 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5922 			     item_param),
5923 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5924 	},
5925 	[ITEM_INTEGRITY_VALUE] = {
5926 		.name = "value",
5927 		.help = "integrity value",
5928 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5929 			     item_param),
5930 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5931 	},
5932 	[ITEM_CONNTRACK] = {
5933 		.name = "conntrack",
5934 		.help = "conntrack state",
5935 		.priv = PRIV_ITEM(CONNTRACK,
5936 				  sizeof(struct rte_flow_item_conntrack)),
5937 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5938 			     item_param),
5939 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5940 		.call = parse_vc,
5941 	},
5942 	[ITEM_PORT_REPRESENTOR] = {
5943 		.name = "port_representor",
5944 		.help = "match traffic entering the embedded switch from the given ethdev",
5945 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5946 				  sizeof(struct rte_flow_item_ethdev)),
5947 		.next = NEXT(item_port_representor),
5948 		.call = parse_vc,
5949 	},
5950 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5951 		.name = "port_id",
5952 		.help = "ethdev port ID",
5953 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5954 			     item_param),
5955 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5956 	},
5957 	[ITEM_REPRESENTED_PORT] = {
5958 		.name = "represented_port",
5959 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5960 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5961 				  sizeof(struct rte_flow_item_ethdev)),
5962 		.next = NEXT(item_represented_port),
5963 		.call = parse_vc,
5964 	},
5965 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5966 		.name = "ethdev_port_id",
5967 		.help = "ethdev port ID",
5968 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5969 			     item_param),
5970 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5971 	},
5972 	[ITEM_FLEX] = {
5973 		.name = "flex",
5974 		.help = "match flex header",
5975 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5976 		.next = NEXT(item_flex),
5977 		.call = parse_vc,
5978 	},
5979 	[ITEM_FLEX_ITEM_HANDLE] = {
5980 		.name = "item",
5981 		.help = "flex item handle",
5982 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5983 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5984 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5985 	},
5986 	[ITEM_FLEX_PATTERN_HANDLE] = {
5987 		.name = "pattern",
5988 		.help = "flex pattern handle",
5989 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5990 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5991 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5992 	},
5993 	[ITEM_L2TPV2] = {
5994 		.name = "l2tpv2",
5995 		.help = "match L2TPv2 header",
5996 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5997 		.next = NEXT(item_l2tpv2),
5998 		.call = parse_vc,
5999 	},
6000 	[ITEM_L2TPV2_TYPE] = {
6001 		.name = "type",
6002 		.help = "type of l2tpv2",
6003 		.next = NEXT(item_l2tpv2_type),
6004 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
6005 	},
6006 	[ITEM_L2TPV2_TYPE_DATA] = {
6007 		.name = "data",
6008 		.help = "Type #7: data message without any options",
6009 		.next = NEXT(item_l2tpv2_type_data),
6010 		.call = parse_vc_item_l2tpv2_type,
6011 	},
6012 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
6013 		.name = "tunnel_id",
6014 		.help = "tunnel identifier",
6015 		.next = NEXT(item_l2tpv2_type_data,
6016 			     NEXT_ENTRY(COMMON_UNSIGNED),
6017 			     item_param),
6018 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6019 					     hdr.type7.tunnel_id)),
6020 	},
6021 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
6022 		.name = "session_id",
6023 		.help = "session identifier",
6024 		.next = NEXT(item_l2tpv2_type_data,
6025 			     NEXT_ENTRY(COMMON_UNSIGNED),
6026 			     item_param),
6027 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6028 					     hdr.type7.session_id)),
6029 	},
6030 	[ITEM_L2TPV2_TYPE_DATA_L] = {
6031 		.name = "data_l",
6032 		.help = "Type #6: data message with length option",
6033 		.next = NEXT(item_l2tpv2_type_data_l),
6034 		.call = parse_vc_item_l2tpv2_type,
6035 	},
6036 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
6037 		.name = "length",
6038 		.help = "message length",
6039 		.next = NEXT(item_l2tpv2_type_data_l,
6040 			     NEXT_ENTRY(COMMON_UNSIGNED),
6041 			     item_param),
6042 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6043 					     hdr.type6.length)),
6044 	},
6045 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
6046 		.name = "tunnel_id",
6047 		.help = "tunnel identifier",
6048 		.next = NEXT(item_l2tpv2_type_data_l,
6049 			     NEXT_ENTRY(COMMON_UNSIGNED),
6050 			     item_param),
6051 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6052 					     hdr.type6.tunnel_id)),
6053 	},
6054 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
6055 		.name = "session_id",
6056 		.help = "session identifier",
6057 		.next = NEXT(item_l2tpv2_type_data_l,
6058 			     NEXT_ENTRY(COMMON_UNSIGNED),
6059 			     item_param),
6060 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6061 					     hdr.type6.session_id)),
6062 	},
6063 	[ITEM_L2TPV2_TYPE_DATA_S] = {
6064 		.name = "data_s",
6065 		.help = "Type #5: data message with ns, nr option",
6066 		.next = NEXT(item_l2tpv2_type_data_s),
6067 		.call = parse_vc_item_l2tpv2_type,
6068 	},
6069 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
6070 		.name = "tunnel_id",
6071 		.help = "tunnel identifier",
6072 		.next = NEXT(item_l2tpv2_type_data_s,
6073 			     NEXT_ENTRY(COMMON_UNSIGNED),
6074 			     item_param),
6075 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6076 					     hdr.type5.tunnel_id)),
6077 	},
6078 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
6079 		.name = "session_id",
6080 		.help = "session identifier",
6081 		.next = NEXT(item_l2tpv2_type_data_s,
6082 			     NEXT_ENTRY(COMMON_UNSIGNED),
6083 			     item_param),
6084 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6085 					     hdr.type5.session_id)),
6086 	},
6087 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
6088 		.name = "ns",
6089 		.help = "sequence number for message",
6090 		.next = NEXT(item_l2tpv2_type_data_s,
6091 			     NEXT_ENTRY(COMMON_UNSIGNED),
6092 			     item_param),
6093 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6094 					     hdr.type5.ns)),
6095 	},
6096 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
6097 		.name = "nr",
6098 		.help = "sequence number for next receive message",
6099 		.next = NEXT(item_l2tpv2_type_data_s,
6100 			     NEXT_ENTRY(COMMON_UNSIGNED),
6101 			     item_param),
6102 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6103 					     hdr.type5.nr)),
6104 	},
6105 	[ITEM_L2TPV2_TYPE_DATA_O] = {
6106 		.name = "data_o",
6107 		.help = "Type #4: data message with offset option",
6108 		.next = NEXT(item_l2tpv2_type_data_o),
6109 		.call = parse_vc_item_l2tpv2_type,
6110 	},
6111 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
6112 		.name = "tunnel_id",
6113 		.help = "tunnel identifier",
6114 		.next = NEXT(item_l2tpv2_type_data_o,
6115 			     NEXT_ENTRY(COMMON_UNSIGNED),
6116 			     item_param),
6117 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6118 					     hdr.type4.tunnel_id)),
6119 	},
6120 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
6121 		.name = "session_id",
6122 		.help = "session identifier",
6123 		.next = NEXT(item_l2tpv2_type_data_o,
6124 			     NEXT_ENTRY(COMMON_UNSIGNED),
6125 			     item_param),
6126 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6127 					     hdr.type5.session_id)),
6128 	},
6129 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
6130 		.name = "offset_size",
6131 		.help = "the size of offset padding",
6132 		.next = NEXT(item_l2tpv2_type_data_o,
6133 			     NEXT_ENTRY(COMMON_UNSIGNED),
6134 			     item_param),
6135 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6136 					     hdr.type4.offset_size)),
6137 	},
6138 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6139 		.name = "data_l_s",
6140 		.help = "Type #3: data message contains length, ns, nr "
6141 			"options",
6142 		.next = NEXT(item_l2tpv2_type_data_l_s),
6143 		.call = parse_vc_item_l2tpv2_type,
6144 	},
6145 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6146 		.name = "length",
6147 		.help = "message length",
6148 		.next = NEXT(item_l2tpv2_type_data_l_s,
6149 			     NEXT_ENTRY(COMMON_UNSIGNED),
6150 			     item_param),
6151 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6152 					     hdr.type3.length)),
6153 	},
6154 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6155 		.name = "tunnel_id",
6156 		.help = "tunnel identifier",
6157 		.next = NEXT(item_l2tpv2_type_data_l_s,
6158 			     NEXT_ENTRY(COMMON_UNSIGNED),
6159 			     item_param),
6160 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6161 					     hdr.type3.tunnel_id)),
6162 	},
6163 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6164 		.name = "session_id",
6165 		.help = "session identifier",
6166 		.next = NEXT(item_l2tpv2_type_data_l_s,
6167 			     NEXT_ENTRY(COMMON_UNSIGNED),
6168 			     item_param),
6169 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6170 					     hdr.type3.session_id)),
6171 	},
6172 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6173 		.name = "ns",
6174 		.help = "sequence number for message",
6175 		.next = NEXT(item_l2tpv2_type_data_l_s,
6176 			     NEXT_ENTRY(COMMON_UNSIGNED),
6177 			     item_param),
6178 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6179 					     hdr.type3.ns)),
6180 	},
6181 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6182 		.name = "nr",
6183 		.help = "sequence number for next receive message",
6184 		.next = NEXT(item_l2tpv2_type_data_l_s,
6185 			     NEXT_ENTRY(COMMON_UNSIGNED),
6186 			     item_param),
6187 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6188 					     hdr.type3.nr)),
6189 	},
6190 	[ITEM_L2TPV2_TYPE_CTRL] = {
6191 		.name = "control",
6192 		.help = "Type #3: conrtol message contains length, ns, nr "
6193 			"options",
6194 		.next = NEXT(item_l2tpv2_type_ctrl),
6195 		.call = parse_vc_item_l2tpv2_type,
6196 	},
6197 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6198 		.name = "length",
6199 		.help = "message length",
6200 		.next = NEXT(item_l2tpv2_type_ctrl,
6201 			     NEXT_ENTRY(COMMON_UNSIGNED),
6202 			     item_param),
6203 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6204 					     hdr.type3.length)),
6205 	},
6206 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6207 		.name = "tunnel_id",
6208 		.help = "tunnel identifier",
6209 		.next = NEXT(item_l2tpv2_type_ctrl,
6210 			     NEXT_ENTRY(COMMON_UNSIGNED),
6211 			     item_param),
6212 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6213 					     hdr.type3.tunnel_id)),
6214 	},
6215 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6216 		.name = "session_id",
6217 		.help = "session identifier",
6218 		.next = NEXT(item_l2tpv2_type_ctrl,
6219 			     NEXT_ENTRY(COMMON_UNSIGNED),
6220 			     item_param),
6221 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6222 					     hdr.type3.session_id)),
6223 	},
6224 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6225 		.name = "ns",
6226 		.help = "sequence number for message",
6227 		.next = NEXT(item_l2tpv2_type_ctrl,
6228 			     NEXT_ENTRY(COMMON_UNSIGNED),
6229 			     item_param),
6230 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6231 					     hdr.type3.ns)),
6232 	},
6233 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6234 		.name = "nr",
6235 		.help = "sequence number for next receive message",
6236 		.next = NEXT(item_l2tpv2_type_ctrl,
6237 			     NEXT_ENTRY(COMMON_UNSIGNED),
6238 			     item_param),
6239 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6240 					     hdr.type3.nr)),
6241 	},
6242 	[ITEM_PPP] = {
6243 		.name = "ppp",
6244 		.help = "match PPP header",
6245 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6246 		.next = NEXT(item_ppp),
6247 		.call = parse_vc,
6248 	},
6249 	[ITEM_PPP_ADDR] = {
6250 		.name = "addr",
6251 		.help = "PPP address",
6252 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6253 			     item_param),
6254 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6255 	},
6256 	[ITEM_PPP_CTRL] = {
6257 		.name = "ctrl",
6258 		.help = "PPP control",
6259 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6260 			     item_param),
6261 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6262 	},
6263 	[ITEM_PPP_PROTO_ID] = {
6264 		.name = "proto_id",
6265 		.help = "PPP protocol identifier",
6266 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6267 			     item_param),
6268 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6269 					hdr.proto_id)),
6270 	},
6271 	[ITEM_METER] = {
6272 		.name = "meter",
6273 		.help = "match meter color",
6274 		.priv = PRIV_ITEM(METER_COLOR,
6275 				  sizeof(struct rte_flow_item_meter_color)),
6276 		.next = NEXT(item_meter),
6277 		.call = parse_vc,
6278 	},
6279 	[ITEM_METER_COLOR] = {
6280 		.name = "color",
6281 		.help = "meter color",
6282 		.next = NEXT(item_meter,
6283 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6284 			     item_param),
6285 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6286 					color)),
6287 	},
6288 	[ITEM_METER_COLOR_NAME] = {
6289 		.name = "color_name",
6290 		.help = "meter color name",
6291 		.call = parse_meter_color,
6292 		.comp = comp_meter_color,
6293 	},
6294 	[ITEM_QUOTA] = {
6295 		.name = "quota",
6296 		.help = "match quota",
6297 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6298 		.next = NEXT(item_quota),
6299 		.call = parse_vc
6300 	},
6301 	[ITEM_QUOTA_STATE] = {
6302 		.name = "quota_state",
6303 		.help = "quota state",
6304 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6305 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6306 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6307 	},
6308 	[ITEM_QUOTA_STATE_NAME] = {
6309 		.name = "state_name",
6310 		.help = "quota state name",
6311 		.call = parse_quota_state_name,
6312 		.comp = comp_quota_state_name
6313 	},
6314 	[ITEM_IB_BTH] = {
6315 		.name = "ib_bth",
6316 		.help = "match ib bth fields",
6317 		.priv = PRIV_ITEM(IB_BTH,
6318 				  sizeof(struct rte_flow_item_ib_bth)),
6319 		.next = NEXT(item_ib_bth),
6320 		.call = parse_vc,
6321 	},
6322 	[ITEM_IB_BTH_OPCODE] = {
6323 		.name = "opcode",
6324 		.help = "match ib bth opcode",
6325 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6326 				 item_param),
6327 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6328 						 hdr.opcode)),
6329 	},
6330 	[ITEM_IB_BTH_PKEY] = {
6331 		.name = "pkey",
6332 		.help = "partition key",
6333 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6334 				 item_param),
6335 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6336 						 hdr.pkey)),
6337 	},
6338 	[ITEM_IB_BTH_DST_QPN] = {
6339 		.name = "dst_qp",
6340 		.help = "destination qp",
6341 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6342 				 item_param),
6343 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6344 						 hdr.dst_qp)),
6345 	},
6346 	[ITEM_IB_BTH_PSN] = {
6347 		.name = "psn",
6348 		.help = "packet sequence number",
6349 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6350 				 item_param),
6351 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6352 						 hdr.psn)),
6353 	},
6354 	[ITEM_PTYPE] = {
6355 		.name = "ptype",
6356 		.help = "match L2/L3/L4 and tunnel information",
6357 		.priv = PRIV_ITEM(PTYPE,
6358 				  sizeof(struct rte_flow_item_ptype)),
6359 		.next = NEXT(item_ptype),
6360 		.call = parse_vc,
6361 	},
6362 	[ITEM_PTYPE_VALUE] = {
6363 		.name = "packet_type",
6364 		.help = "packet type as defined in rte_mbuf_ptype",
6365 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6366 			     item_param),
6367 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6368 	},
6369 	[ITEM_NSH] = {
6370 		.name = "nsh",
6371 		.help = "match NSH header",
6372 		.priv = PRIV_ITEM(NSH,
6373 				  sizeof(struct rte_flow_item_nsh)),
6374 		.next = NEXT(item_nsh),
6375 		.call = parse_vc,
6376 	},
6377 	[ITEM_COMPARE] = {
6378 		.name = "compare",
6379 		.help = "match with the comparison result",
6380 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6381 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6382 		.call = parse_vc,
6383 	},
6384 	[ITEM_COMPARE_OP] = {
6385 		.name = "op",
6386 		.help = "operation type",
6387 		.next = NEXT(item_compare_field,
6388 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6389 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6390 	},
6391 	[ITEM_COMPARE_OP_VALUE] = {
6392 		.name = "{operation}",
6393 		.help = "operation type value",
6394 		.call = parse_vc_compare_op,
6395 		.comp = comp_set_compare_op,
6396 	},
6397 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6398 		.name = "a_type",
6399 		.help = "compared field type",
6400 		.next = NEXT(compare_field_a,
6401 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6402 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6403 	},
6404 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6405 		.name = "{a_type}",
6406 		.help = "compared field type value",
6407 		.call = parse_vc_compare_field_id,
6408 		.comp = comp_set_compare_field_id,
6409 	},
6410 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6411 		.name = "a_level",
6412 		.help = "compared field level",
6413 		.next = NEXT(compare_field_a,
6414 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6415 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6416 	},
6417 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6418 		.name = "{a_level}",
6419 		.help = "compared field level value",
6420 		.call = parse_vc_compare_field_level,
6421 		.comp = comp_none,
6422 	},
6423 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6424 		.name = "a_tag_index",
6425 		.help = "compared field tag array",
6426 		.next = NEXT(compare_field_a,
6427 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6428 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6429 					a.tag_index)),
6430 	},
6431 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6432 		.name = "a_type_id",
6433 		.help = "compared field type ID",
6434 		.next = NEXT(compare_field_a,
6435 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6436 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6437 					a.type)),
6438 	},
6439 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6440 		.name = "a_class",
6441 		.help = "compared field class ID",
6442 		.next = NEXT(compare_field_a,
6443 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6444 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6445 					     a.class_id)),
6446 	},
6447 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6448 		.name = "a_offset",
6449 		.help = "compared field bit offset",
6450 		.next = NEXT(compare_field_a,
6451 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6452 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6453 					a.offset)),
6454 	},
6455 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6456 		.name = "b_type",
6457 		.help = "comparator field type",
6458 		.next = NEXT(compare_field_b,
6459 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6460 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6461 					b.field)),
6462 	},
6463 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6464 		.name = "{b_type}",
6465 		.help = "comparator field type value",
6466 		.call = parse_vc_compare_field_id,
6467 		.comp = comp_set_compare_field_id,
6468 	},
6469 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6470 		.name = "b_level",
6471 		.help = "comparator field level",
6472 		.next = NEXT(compare_field_b,
6473 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6474 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6475 					b.level)),
6476 	},
6477 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6478 		.name = "{b_level}",
6479 		.help = "comparator field level value",
6480 		.call = parse_vc_compare_field_level,
6481 		.comp = comp_none,
6482 	},
6483 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6484 		.name = "b_tag_index",
6485 		.help = "comparator field tag array",
6486 		.next = NEXT(compare_field_b,
6487 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6488 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6489 					b.tag_index)),
6490 	},
6491 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6492 		.name = "b_type_id",
6493 		.help = "comparator field type ID",
6494 		.next = NEXT(compare_field_b,
6495 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6496 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6497 					b.type)),
6498 	},
6499 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6500 		.name = "b_class",
6501 		.help = "comparator field class ID",
6502 		.next = NEXT(compare_field_b,
6503 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6504 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6505 					     b.class_id)),
6506 	},
6507 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6508 		.name = "b_offset",
6509 		.help = "comparator field bit offset",
6510 		.next = NEXT(compare_field_b,
6511 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6512 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6513 					b.offset)),
6514 	},
6515 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6516 		.name = "b_value",
6517 		.help = "comparator immediate value",
6518 		.next = NEXT(compare_field_b,
6519 			     NEXT_ENTRY(COMMON_HEX), item_param),
6520 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6521 			     ARGS_ENTRY_ARB(0, 0),
6522 			     ARGS_ENTRY(struct rte_flow_item_compare,
6523 					b.value)),
6524 	},
6525 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6526 		.name = "b_ptr",
6527 		.help = "pointer to comparator immediate value",
6528 		.next = NEXT(compare_field_b,
6529 			     NEXT_ENTRY(COMMON_HEX), item_param),
6530 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6531 					b.pvalue),
6532 			     ARGS_ENTRY_ARB(0, 0),
6533 			     ARGS_ENTRY_ARB
6534 				(sizeof(struct rte_flow_item_compare),
6535 				 FLOW_FIELD_PATTERN_SIZE)),
6536 	},
6537 	[ITEM_COMPARE_FIELD_WIDTH] = {
6538 		.name = "width",
6539 		.help = "number of bits to compare",
6540 		.next = NEXT(item_compare_field,
6541 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6542 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6543 					width)),
6544 	},
6545 
6546 	/* Validate/create actions. */
6547 	[ACTIONS] = {
6548 		.name = "actions",
6549 		.help = "submit a list of associated actions",
6550 		.next = NEXT(next_action),
6551 		.call = parse_vc,
6552 	},
6553 	[ACTION_NEXT] = {
6554 		.name = "/",
6555 		.help = "specify next action",
6556 		.next = NEXT(next_action),
6557 	},
6558 	[ACTION_END] = {
6559 		.name = "end",
6560 		.help = "end list of actions",
6561 		.priv = PRIV_ACTION(END, 0),
6562 		.call = parse_vc,
6563 	},
6564 	[ACTION_VOID] = {
6565 		.name = "void",
6566 		.help = "no-op action",
6567 		.priv = PRIV_ACTION(VOID, 0),
6568 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6569 		.call = parse_vc,
6570 	},
6571 	[ACTION_PASSTHRU] = {
6572 		.name = "passthru",
6573 		.help = "let subsequent rule process matched packets",
6574 		.priv = PRIV_ACTION(PASSTHRU, 0),
6575 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6576 		.call = parse_vc,
6577 	},
6578 	[ACTION_SKIP_CMAN] = {
6579 		.name = "skip_cman",
6580 		.help = "bypass cman on received packets",
6581 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6582 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6583 		.call = parse_vc,
6584 	},
6585 	[ACTION_JUMP] = {
6586 		.name = "jump",
6587 		.help = "redirect traffic to a given group",
6588 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6589 		.next = NEXT(action_jump),
6590 		.call = parse_vc,
6591 	},
6592 	[ACTION_JUMP_GROUP] = {
6593 		.name = "group",
6594 		.help = "group to redirect traffic to",
6595 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6596 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6597 		.call = parse_vc_conf,
6598 	},
6599 	[ACTION_MARK] = {
6600 		.name = "mark",
6601 		.help = "attach 32 bit value to packets",
6602 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6603 		.next = NEXT(action_mark),
6604 		.call = parse_vc,
6605 	},
6606 	[ACTION_MARK_ID] = {
6607 		.name = "id",
6608 		.help = "32 bit value to return with packets",
6609 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6610 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6611 		.call = parse_vc_conf,
6612 	},
6613 	[ACTION_FLAG] = {
6614 		.name = "flag",
6615 		.help = "flag packets",
6616 		.priv = PRIV_ACTION(FLAG, 0),
6617 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6618 		.call = parse_vc,
6619 	},
6620 	[ACTION_QUEUE] = {
6621 		.name = "queue",
6622 		.help = "assign packets to a given queue index",
6623 		.priv = PRIV_ACTION(QUEUE,
6624 				    sizeof(struct rte_flow_action_queue)),
6625 		.next = NEXT(action_queue),
6626 		.call = parse_vc,
6627 	},
6628 	[ACTION_QUEUE_INDEX] = {
6629 		.name = "index",
6630 		.help = "queue index to use",
6631 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6632 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6633 		.call = parse_vc_conf,
6634 	},
6635 	[ACTION_DROP] = {
6636 		.name = "drop",
6637 		.help = "drop packets (note: passthru has priority)",
6638 		.priv = PRIV_ACTION(DROP, 0),
6639 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6640 		.call = parse_vc,
6641 	},
6642 	[ACTION_COUNT] = {
6643 		.name = "count",
6644 		.help = "enable counters for this rule",
6645 		.priv = PRIV_ACTION(COUNT,
6646 				    sizeof(struct rte_flow_action_count)),
6647 		.next = NEXT(action_count),
6648 		.call = parse_vc,
6649 	},
6650 	[ACTION_COUNT_ID] = {
6651 		.name = "identifier",
6652 		.help = "counter identifier to use",
6653 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6654 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6655 		.call = parse_vc_conf,
6656 	},
6657 	[ACTION_RSS] = {
6658 		.name = "rss",
6659 		.help = "spread packets among several queues",
6660 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6661 		.next = NEXT(action_rss),
6662 		.call = parse_vc_action_rss,
6663 	},
6664 	[ACTION_RSS_FUNC] = {
6665 		.name = "func",
6666 		.help = "RSS hash function to apply",
6667 		.next = NEXT(action_rss,
6668 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6669 					ACTION_RSS_FUNC_TOEPLITZ,
6670 					ACTION_RSS_FUNC_SIMPLE_XOR,
6671 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6672 	},
6673 	[ACTION_RSS_FUNC_DEFAULT] = {
6674 		.name = "default",
6675 		.help = "default hash function",
6676 		.call = parse_vc_action_rss_func,
6677 	},
6678 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6679 		.name = "toeplitz",
6680 		.help = "Toeplitz hash function",
6681 		.call = parse_vc_action_rss_func,
6682 	},
6683 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6684 		.name = "simple_xor",
6685 		.help = "simple XOR hash function",
6686 		.call = parse_vc_action_rss_func,
6687 	},
6688 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6689 		.name = "symmetric_toeplitz",
6690 		.help = "Symmetric Toeplitz hash function",
6691 		.call = parse_vc_action_rss_func,
6692 	},
6693 	[ACTION_RSS_LEVEL] = {
6694 		.name = "level",
6695 		.help = "encapsulation level for \"types\"",
6696 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6697 		.args = ARGS(ARGS_ENTRY_ARB
6698 			     (offsetof(struct action_rss_data, conf) +
6699 			      offsetof(struct rte_flow_action_rss, level),
6700 			      sizeof(((struct rte_flow_action_rss *)0)->
6701 				     level))),
6702 	},
6703 	[ACTION_RSS_TYPES] = {
6704 		.name = "types",
6705 		.help = "specific RSS hash types",
6706 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6707 	},
6708 	[ACTION_RSS_TYPE] = {
6709 		.name = "{type}",
6710 		.help = "RSS hash type",
6711 		.call = parse_vc_action_rss_type,
6712 		.comp = comp_vc_action_rss_type,
6713 	},
6714 	[ACTION_RSS_KEY] = {
6715 		.name = "key",
6716 		.help = "RSS hash key",
6717 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6718 		.args = ARGS(ARGS_ENTRY_ARB
6719 			     (offsetof(struct action_rss_data, conf) +
6720 			      offsetof(struct rte_flow_action_rss, key),
6721 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6722 			     ARGS_ENTRY_ARB
6723 			     (offsetof(struct action_rss_data, conf) +
6724 			      offsetof(struct rte_flow_action_rss, key_len),
6725 			      sizeof(((struct rte_flow_action_rss *)0)->
6726 				     key_len)),
6727 			     ARGS_ENTRY(struct action_rss_data, key)),
6728 	},
6729 	[ACTION_RSS_KEY_LEN] = {
6730 		.name = "key_len",
6731 		.help = "RSS hash key length in bytes",
6732 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6733 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6734 			     (offsetof(struct action_rss_data, conf) +
6735 			      offsetof(struct rte_flow_action_rss, key_len),
6736 			      sizeof(((struct rte_flow_action_rss *)0)->
6737 				     key_len),
6738 			      0,
6739 			      RSS_HASH_KEY_LENGTH)),
6740 	},
6741 	[ACTION_RSS_QUEUES] = {
6742 		.name = "queues",
6743 		.help = "queue indices to use",
6744 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6745 		.call = parse_vc_conf,
6746 	},
6747 	[ACTION_RSS_QUEUE] = {
6748 		.name = "{queue}",
6749 		.help = "queue index",
6750 		.call = parse_vc_action_rss_queue,
6751 		.comp = comp_vc_action_rss_queue,
6752 	},
6753 	[ACTION_PF] = {
6754 		.name = "pf",
6755 		.help = "direct traffic to physical function",
6756 		.priv = PRIV_ACTION(PF, 0),
6757 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6758 		.call = parse_vc,
6759 	},
6760 	[ACTION_VF] = {
6761 		.name = "vf",
6762 		.help = "direct traffic to a virtual function ID",
6763 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6764 		.next = NEXT(action_vf),
6765 		.call = parse_vc,
6766 	},
6767 	[ACTION_VF_ORIGINAL] = {
6768 		.name = "original",
6769 		.help = "use original VF ID if possible",
6770 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6771 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6772 					   original, 1)),
6773 		.call = parse_vc_conf,
6774 	},
6775 	[ACTION_VF_ID] = {
6776 		.name = "id",
6777 		.help = "VF ID",
6778 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6779 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6780 		.call = parse_vc_conf,
6781 	},
6782 	[ACTION_PORT_ID] = {
6783 		.name = "port_id",
6784 		.help = "direct matching traffic to a given DPDK port ID",
6785 		.priv = PRIV_ACTION(PORT_ID,
6786 				    sizeof(struct rte_flow_action_port_id)),
6787 		.next = NEXT(action_port_id),
6788 		.call = parse_vc,
6789 	},
6790 	[ACTION_PORT_ID_ORIGINAL] = {
6791 		.name = "original",
6792 		.help = "use original DPDK port ID if possible",
6793 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6794 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6795 					   original, 1)),
6796 		.call = parse_vc_conf,
6797 	},
6798 	[ACTION_PORT_ID_ID] = {
6799 		.name = "id",
6800 		.help = "DPDK port ID",
6801 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6802 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6803 		.call = parse_vc_conf,
6804 	},
6805 	[ACTION_METER] = {
6806 		.name = "meter",
6807 		.help = "meter the directed packets at given id",
6808 		.priv = PRIV_ACTION(METER,
6809 				    sizeof(struct rte_flow_action_meter)),
6810 		.next = NEXT(action_meter),
6811 		.call = parse_vc,
6812 	},
6813 	[ACTION_METER_COLOR] = {
6814 		.name = "color",
6815 		.help = "meter color for the packets",
6816 		.priv = PRIV_ACTION(METER_COLOR,
6817 				sizeof(struct rte_flow_action_meter_color)),
6818 		.next = NEXT(action_meter_color),
6819 		.call = parse_vc,
6820 	},
6821 	[ACTION_METER_COLOR_TYPE] = {
6822 		.name = "type",
6823 		.help = "specific meter color",
6824 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6825 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6826 					ACTION_METER_COLOR_YELLOW,
6827 					ACTION_METER_COLOR_RED)),
6828 	},
6829 	[ACTION_METER_COLOR_GREEN] = {
6830 		.name = "green",
6831 		.help = "meter color green",
6832 		.call = parse_vc_action_meter_color_type,
6833 	},
6834 	[ACTION_METER_COLOR_YELLOW] = {
6835 		.name = "yellow",
6836 		.help = "meter color yellow",
6837 		.call = parse_vc_action_meter_color_type,
6838 	},
6839 	[ACTION_METER_COLOR_RED] = {
6840 		.name = "red",
6841 		.help = "meter color red",
6842 		.call = parse_vc_action_meter_color_type,
6843 	},
6844 	[ACTION_METER_ID] = {
6845 		.name = "mtr_id",
6846 		.help = "meter id to use",
6847 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6848 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6849 		.call = parse_vc_conf,
6850 	},
6851 	[ACTION_METER_MARK] = {
6852 		.name = "meter_mark",
6853 		.help = "meter the directed packets using profile and policy",
6854 		.priv = PRIV_ACTION(METER_MARK,
6855 				    sizeof(struct rte_flow_action_meter_mark)),
6856 		.next = NEXT(action_meter_mark),
6857 		.call = parse_vc,
6858 	},
6859 	[ACTION_METER_PROFILE] = {
6860 		.name = "mtr_profile",
6861 		.help = "meter profile id to use",
6862 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6863 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6864 	},
6865 	[ACTION_METER_PROFILE_ID2PTR] = {
6866 		.name = "{mtr_profile_id}",
6867 		.type = "PROFILE_ID",
6868 		.help = "meter profile id",
6869 		.next = NEXT(action_meter_mark),
6870 		.call = parse_meter_profile_id2ptr,
6871 		.comp = comp_none,
6872 	},
6873 	[ACTION_METER_POLICY] = {
6874 		.name = "mtr_policy",
6875 		.help = "meter policy id to use",
6876 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6877 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6878 	},
6879 	[ACTION_METER_POLICY_ID2PTR] = {
6880 		.name = "{mtr_policy_id}",
6881 		.type = "POLICY_ID",
6882 		.help = "meter policy id",
6883 		.next = NEXT(action_meter_mark),
6884 		.call = parse_meter_policy_id2ptr,
6885 		.comp = comp_none,
6886 	},
6887 	[ACTION_METER_COLOR_MODE] = {
6888 		.name = "mtr_color_mode",
6889 		.help = "meter color awareness mode",
6890 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6891 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6892 		.call = parse_vc_conf,
6893 	},
6894 	[ACTION_METER_STATE] = {
6895 		.name = "mtr_state",
6896 		.help = "meter state",
6897 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6898 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6899 		.call = parse_vc_conf,
6900 	},
6901 	[ACTION_OF_DEC_NW_TTL] = {
6902 		.name = "of_dec_nw_ttl",
6903 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6904 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6905 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6906 		.call = parse_vc,
6907 	},
6908 	[ACTION_OF_POP_VLAN] = {
6909 		.name = "of_pop_vlan",
6910 		.help = "OpenFlow's OFPAT_POP_VLAN",
6911 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6912 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6913 		.call = parse_vc,
6914 	},
6915 	[ACTION_OF_PUSH_VLAN] = {
6916 		.name = "of_push_vlan",
6917 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6918 		.priv = PRIV_ACTION
6919 			(OF_PUSH_VLAN,
6920 			 sizeof(struct rte_flow_action_of_push_vlan)),
6921 		.next = NEXT(action_of_push_vlan),
6922 		.call = parse_vc,
6923 	},
6924 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6925 		.name = "ethertype",
6926 		.help = "EtherType",
6927 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6928 		.args = ARGS(ARGS_ENTRY_HTON
6929 			     (struct rte_flow_action_of_push_vlan,
6930 			      ethertype)),
6931 		.call = parse_vc_conf,
6932 	},
6933 	[ACTION_OF_SET_VLAN_VID] = {
6934 		.name = "of_set_vlan_vid",
6935 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6936 		.priv = PRIV_ACTION
6937 			(OF_SET_VLAN_VID,
6938 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6939 		.next = NEXT(action_of_set_vlan_vid),
6940 		.call = parse_vc,
6941 	},
6942 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6943 		.name = "vlan_vid",
6944 		.help = "VLAN id",
6945 		.next = NEXT(action_of_set_vlan_vid,
6946 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6947 		.args = ARGS(ARGS_ENTRY_HTON
6948 			     (struct rte_flow_action_of_set_vlan_vid,
6949 			      vlan_vid)),
6950 		.call = parse_vc_conf,
6951 	},
6952 	[ACTION_OF_SET_VLAN_PCP] = {
6953 		.name = "of_set_vlan_pcp",
6954 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6955 		.priv = PRIV_ACTION
6956 			(OF_SET_VLAN_PCP,
6957 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6958 		.next = NEXT(action_of_set_vlan_pcp),
6959 		.call = parse_vc,
6960 	},
6961 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6962 		.name = "vlan_pcp",
6963 		.help = "VLAN priority",
6964 		.next = NEXT(action_of_set_vlan_pcp,
6965 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6966 		.args = ARGS(ARGS_ENTRY_HTON
6967 			     (struct rte_flow_action_of_set_vlan_pcp,
6968 			      vlan_pcp)),
6969 		.call = parse_vc_conf,
6970 	},
6971 	[ACTION_OF_POP_MPLS] = {
6972 		.name = "of_pop_mpls",
6973 		.help = "OpenFlow's OFPAT_POP_MPLS",
6974 		.priv = PRIV_ACTION(OF_POP_MPLS,
6975 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6976 		.next = NEXT(action_of_pop_mpls),
6977 		.call = parse_vc,
6978 	},
6979 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6980 		.name = "ethertype",
6981 		.help = "EtherType",
6982 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6983 		.args = ARGS(ARGS_ENTRY_HTON
6984 			     (struct rte_flow_action_of_pop_mpls,
6985 			      ethertype)),
6986 		.call = parse_vc_conf,
6987 	},
6988 	[ACTION_OF_PUSH_MPLS] = {
6989 		.name = "of_push_mpls",
6990 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6991 		.priv = PRIV_ACTION
6992 			(OF_PUSH_MPLS,
6993 			 sizeof(struct rte_flow_action_of_push_mpls)),
6994 		.next = NEXT(action_of_push_mpls),
6995 		.call = parse_vc,
6996 	},
6997 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6998 		.name = "ethertype",
6999 		.help = "EtherType",
7000 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
7001 		.args = ARGS(ARGS_ENTRY_HTON
7002 			     (struct rte_flow_action_of_push_mpls,
7003 			      ethertype)),
7004 		.call = parse_vc_conf,
7005 	},
7006 	[ACTION_VXLAN_ENCAP] = {
7007 		.name = "vxlan_encap",
7008 		.help = "VXLAN encapsulation, uses configuration set by \"set"
7009 			" vxlan\"",
7010 		.priv = PRIV_ACTION(VXLAN_ENCAP,
7011 				    sizeof(struct action_vxlan_encap_data)),
7012 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7013 		.call = parse_vc_action_vxlan_encap,
7014 	},
7015 	[ACTION_VXLAN_DECAP] = {
7016 		.name = "vxlan_decap",
7017 		.help = "Performs a decapsulation action by stripping all"
7018 			" headers of the VXLAN tunnel network overlay from the"
7019 			" matched flow.",
7020 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
7021 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7022 		.call = parse_vc,
7023 	},
7024 	[ACTION_NVGRE_ENCAP] = {
7025 		.name = "nvgre_encap",
7026 		.help = "NVGRE encapsulation, uses configuration set by \"set"
7027 			" nvgre\"",
7028 		.priv = PRIV_ACTION(NVGRE_ENCAP,
7029 				    sizeof(struct action_nvgre_encap_data)),
7030 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7031 		.call = parse_vc_action_nvgre_encap,
7032 	},
7033 	[ACTION_NVGRE_DECAP] = {
7034 		.name = "nvgre_decap",
7035 		.help = "Performs a decapsulation action by stripping all"
7036 			" headers of the NVGRE tunnel network overlay from the"
7037 			" matched flow.",
7038 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
7039 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7040 		.call = parse_vc,
7041 	},
7042 	[ACTION_L2_ENCAP] = {
7043 		.name = "l2_encap",
7044 		.help = "l2 encap, uses configuration set by"
7045 			" \"set l2_encap\"",
7046 		.priv = PRIV_ACTION(RAW_ENCAP,
7047 				    sizeof(struct action_raw_encap_data)),
7048 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7049 		.call = parse_vc_action_l2_encap,
7050 	},
7051 	[ACTION_L2_DECAP] = {
7052 		.name = "l2_decap",
7053 		.help = "l2 decap, uses configuration set by"
7054 			" \"set l2_decap\"",
7055 		.priv = PRIV_ACTION(RAW_DECAP,
7056 				    sizeof(struct action_raw_decap_data)),
7057 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7058 		.call = parse_vc_action_l2_decap,
7059 	},
7060 	[ACTION_MPLSOGRE_ENCAP] = {
7061 		.name = "mplsogre_encap",
7062 		.help = "mplsogre encapsulation, uses configuration set by"
7063 			" \"set mplsogre_encap\"",
7064 		.priv = PRIV_ACTION(RAW_ENCAP,
7065 				    sizeof(struct action_raw_encap_data)),
7066 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7067 		.call = parse_vc_action_mplsogre_encap,
7068 	},
7069 	[ACTION_MPLSOGRE_DECAP] = {
7070 		.name = "mplsogre_decap",
7071 		.help = "mplsogre decapsulation, uses configuration set by"
7072 			" \"set mplsogre_decap\"",
7073 		.priv = PRIV_ACTION(RAW_DECAP,
7074 				    sizeof(struct action_raw_decap_data)),
7075 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7076 		.call = parse_vc_action_mplsogre_decap,
7077 	},
7078 	[ACTION_MPLSOUDP_ENCAP] = {
7079 		.name = "mplsoudp_encap",
7080 		.help = "mplsoudp encapsulation, uses configuration set by"
7081 			" \"set mplsoudp_encap\"",
7082 		.priv = PRIV_ACTION(RAW_ENCAP,
7083 				    sizeof(struct action_raw_encap_data)),
7084 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7085 		.call = parse_vc_action_mplsoudp_encap,
7086 	},
7087 	[ACTION_MPLSOUDP_DECAP] = {
7088 		.name = "mplsoudp_decap",
7089 		.help = "mplsoudp decapsulation, uses configuration set by"
7090 			" \"set mplsoudp_decap\"",
7091 		.priv = PRIV_ACTION(RAW_DECAP,
7092 				    sizeof(struct action_raw_decap_data)),
7093 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7094 		.call = parse_vc_action_mplsoudp_decap,
7095 	},
7096 	[ACTION_SET_IPV4_SRC] = {
7097 		.name = "set_ipv4_src",
7098 		.help = "Set a new IPv4 source address in the outermost"
7099 			" IPv4 header",
7100 		.priv = PRIV_ACTION(SET_IPV4_SRC,
7101 			sizeof(struct rte_flow_action_set_ipv4)),
7102 		.next = NEXT(action_set_ipv4_src),
7103 		.call = parse_vc,
7104 	},
7105 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
7106 		.name = "ipv4_addr",
7107 		.help = "new IPv4 source address to set",
7108 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7109 		.args = ARGS(ARGS_ENTRY_HTON
7110 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7111 		.call = parse_vc_conf,
7112 	},
7113 	[ACTION_SET_IPV4_DST] = {
7114 		.name = "set_ipv4_dst",
7115 		.help = "Set a new IPv4 destination address in the outermost"
7116 			" IPv4 header",
7117 		.priv = PRIV_ACTION(SET_IPV4_DST,
7118 			sizeof(struct rte_flow_action_set_ipv4)),
7119 		.next = NEXT(action_set_ipv4_dst),
7120 		.call = parse_vc,
7121 	},
7122 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
7123 		.name = "ipv4_addr",
7124 		.help = "new IPv4 destination address to set",
7125 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7126 		.args = ARGS(ARGS_ENTRY_HTON
7127 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7128 		.call = parse_vc_conf,
7129 	},
7130 	[ACTION_SET_IPV6_SRC] = {
7131 		.name = "set_ipv6_src",
7132 		.help = "Set a new IPv6 source address in the outermost"
7133 			" IPv6 header",
7134 		.priv = PRIV_ACTION(SET_IPV6_SRC,
7135 			sizeof(struct rte_flow_action_set_ipv6)),
7136 		.next = NEXT(action_set_ipv6_src),
7137 		.call = parse_vc,
7138 	},
7139 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7140 		.name = "ipv6_addr",
7141 		.help = "new IPv6 source address to set",
7142 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7143 		.args = ARGS(ARGS_ENTRY_HTON
7144 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7145 		.call = parse_vc_conf,
7146 	},
7147 	[ACTION_SET_IPV6_DST] = {
7148 		.name = "set_ipv6_dst",
7149 		.help = "Set a new IPv6 destination address in the outermost"
7150 			" IPv6 header",
7151 		.priv = PRIV_ACTION(SET_IPV6_DST,
7152 			sizeof(struct rte_flow_action_set_ipv6)),
7153 		.next = NEXT(action_set_ipv6_dst),
7154 		.call = parse_vc,
7155 	},
7156 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7157 		.name = "ipv6_addr",
7158 		.help = "new IPv6 destination address to set",
7159 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7160 		.args = ARGS(ARGS_ENTRY_HTON
7161 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7162 		.call = parse_vc_conf,
7163 	},
7164 	[ACTION_SET_TP_SRC] = {
7165 		.name = "set_tp_src",
7166 		.help = "set a new source port number in the outermost"
7167 			" TCP/UDP header",
7168 		.priv = PRIV_ACTION(SET_TP_SRC,
7169 			sizeof(struct rte_flow_action_set_tp)),
7170 		.next = NEXT(action_set_tp_src),
7171 		.call = parse_vc,
7172 	},
7173 	[ACTION_SET_TP_SRC_TP_SRC] = {
7174 		.name = "port",
7175 		.help = "new source port number to set",
7176 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7177 		.args = ARGS(ARGS_ENTRY_HTON
7178 			     (struct rte_flow_action_set_tp, port)),
7179 		.call = parse_vc_conf,
7180 	},
7181 	[ACTION_SET_TP_DST] = {
7182 		.name = "set_tp_dst",
7183 		.help = "set a new destination port number in the outermost"
7184 			" TCP/UDP header",
7185 		.priv = PRIV_ACTION(SET_TP_DST,
7186 			sizeof(struct rte_flow_action_set_tp)),
7187 		.next = NEXT(action_set_tp_dst),
7188 		.call = parse_vc,
7189 	},
7190 	[ACTION_SET_TP_DST_TP_DST] = {
7191 		.name = "port",
7192 		.help = "new destination port number to set",
7193 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7194 		.args = ARGS(ARGS_ENTRY_HTON
7195 			     (struct rte_flow_action_set_tp, port)),
7196 		.call = parse_vc_conf,
7197 	},
7198 	[ACTION_MAC_SWAP] = {
7199 		.name = "mac_swap",
7200 		.help = "Swap the source and destination MAC addresses"
7201 			" in the outermost Ethernet header",
7202 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7203 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7204 		.call = parse_vc,
7205 	},
7206 	[ACTION_DEC_TTL] = {
7207 		.name = "dec_ttl",
7208 		.help = "decrease network TTL if available",
7209 		.priv = PRIV_ACTION(DEC_TTL, 0),
7210 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7211 		.call = parse_vc,
7212 	},
7213 	[ACTION_SET_TTL] = {
7214 		.name = "set_ttl",
7215 		.help = "set ttl value",
7216 		.priv = PRIV_ACTION(SET_TTL,
7217 			sizeof(struct rte_flow_action_set_ttl)),
7218 		.next = NEXT(action_set_ttl),
7219 		.call = parse_vc,
7220 	},
7221 	[ACTION_SET_TTL_TTL] = {
7222 		.name = "ttl_value",
7223 		.help = "new ttl value to set",
7224 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7225 		.args = ARGS(ARGS_ENTRY_HTON
7226 			     (struct rte_flow_action_set_ttl, ttl_value)),
7227 		.call = parse_vc_conf,
7228 	},
7229 	[ACTION_SET_MAC_SRC] = {
7230 		.name = "set_mac_src",
7231 		.help = "set source mac address",
7232 		.priv = PRIV_ACTION(SET_MAC_SRC,
7233 			sizeof(struct rte_flow_action_set_mac)),
7234 		.next = NEXT(action_set_mac_src),
7235 		.call = parse_vc,
7236 	},
7237 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7238 		.name = "mac_addr",
7239 		.help = "new source mac address",
7240 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7241 		.args = ARGS(ARGS_ENTRY_HTON
7242 			     (struct rte_flow_action_set_mac, mac_addr)),
7243 		.call = parse_vc_conf,
7244 	},
7245 	[ACTION_SET_MAC_DST] = {
7246 		.name = "set_mac_dst",
7247 		.help = "set destination mac address",
7248 		.priv = PRIV_ACTION(SET_MAC_DST,
7249 			sizeof(struct rte_flow_action_set_mac)),
7250 		.next = NEXT(action_set_mac_dst),
7251 		.call = parse_vc,
7252 	},
7253 	[ACTION_SET_MAC_DST_MAC_DST] = {
7254 		.name = "mac_addr",
7255 		.help = "new destination mac address to set",
7256 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7257 		.args = ARGS(ARGS_ENTRY_HTON
7258 			     (struct rte_flow_action_set_mac, mac_addr)),
7259 		.call = parse_vc_conf,
7260 	},
7261 	[ACTION_INC_TCP_SEQ] = {
7262 		.name = "inc_tcp_seq",
7263 		.help = "increase TCP sequence number",
7264 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7265 		.next = NEXT(action_inc_tcp_seq),
7266 		.call = parse_vc,
7267 	},
7268 	[ACTION_INC_TCP_SEQ_VALUE] = {
7269 		.name = "value",
7270 		.help = "the value to increase TCP sequence number by",
7271 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7272 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7273 		.call = parse_vc_conf,
7274 	},
7275 	[ACTION_DEC_TCP_SEQ] = {
7276 		.name = "dec_tcp_seq",
7277 		.help = "decrease TCP sequence number",
7278 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7279 		.next = NEXT(action_dec_tcp_seq),
7280 		.call = parse_vc,
7281 	},
7282 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7283 		.name = "value",
7284 		.help = "the value to decrease TCP sequence number by",
7285 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7286 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7287 		.call = parse_vc_conf,
7288 	},
7289 	[ACTION_INC_TCP_ACK] = {
7290 		.name = "inc_tcp_ack",
7291 		.help = "increase TCP acknowledgment number",
7292 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7293 		.next = NEXT(action_inc_tcp_ack),
7294 		.call = parse_vc,
7295 	},
7296 	[ACTION_INC_TCP_ACK_VALUE] = {
7297 		.name = "value",
7298 		.help = "the value to increase TCP acknowledgment number by",
7299 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7300 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7301 		.call = parse_vc_conf,
7302 	},
7303 	[ACTION_DEC_TCP_ACK] = {
7304 		.name = "dec_tcp_ack",
7305 		.help = "decrease TCP acknowledgment number",
7306 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7307 		.next = NEXT(action_dec_tcp_ack),
7308 		.call = parse_vc,
7309 	},
7310 	[ACTION_DEC_TCP_ACK_VALUE] = {
7311 		.name = "value",
7312 		.help = "the value to decrease TCP acknowledgment number by",
7313 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7314 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7315 		.call = parse_vc_conf,
7316 	},
7317 	[ACTION_RAW_ENCAP] = {
7318 		.name = "raw_encap",
7319 		.help = "encapsulation data, defined by set raw_encap",
7320 		.priv = PRIV_ACTION(RAW_ENCAP,
7321 			sizeof(struct action_raw_encap_data)),
7322 		.next = NEXT(action_raw_encap),
7323 		.call = parse_vc_action_raw_encap,
7324 	},
7325 	[ACTION_RAW_ENCAP_SIZE] = {
7326 		.name = "size",
7327 		.help = "raw encap size",
7328 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7329 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7330 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7331 		.call = parse_vc_conf,
7332 	},
7333 	[ACTION_RAW_ENCAP_INDEX] = {
7334 		.name = "index",
7335 		.help = "the index of raw_encap_confs",
7336 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7337 	},
7338 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7339 		.name = "{index}",
7340 		.type = "UNSIGNED",
7341 		.help = "unsigned integer value",
7342 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7343 		.call = parse_vc_action_raw_encap_index,
7344 		.comp = comp_set_raw_index,
7345 	},
7346 	[ACTION_RAW_DECAP] = {
7347 		.name = "raw_decap",
7348 		.help = "decapsulation data, defined by set raw_encap",
7349 		.priv = PRIV_ACTION(RAW_DECAP,
7350 			sizeof(struct action_raw_decap_data)),
7351 		.next = NEXT(action_raw_decap),
7352 		.call = parse_vc_action_raw_decap,
7353 	},
7354 	[ACTION_RAW_DECAP_INDEX] = {
7355 		.name = "index",
7356 		.help = "the index of raw_encap_confs",
7357 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7358 	},
7359 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7360 		.name = "{index}",
7361 		.type = "UNSIGNED",
7362 		.help = "unsigned integer value",
7363 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7364 		.call = parse_vc_action_raw_decap_index,
7365 		.comp = comp_set_raw_index,
7366 	},
7367 	[ACTION_MODIFY_FIELD] = {
7368 		.name = "modify_field",
7369 		.help = "modify destination field with data from source field",
7370 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7371 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7372 		.call = parse_vc,
7373 	},
7374 	[ACTION_MODIFY_FIELD_OP] = {
7375 		.name = "op",
7376 		.help = "operation type",
7377 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7378 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7379 		.call = parse_vc_conf,
7380 	},
7381 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7382 		.name = "{operation}",
7383 		.help = "operation type value",
7384 		.call = parse_vc_modify_field_op,
7385 		.comp = comp_set_modify_field_op,
7386 	},
7387 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7388 		.name = "dst_type",
7389 		.help = "destination field type",
7390 		.next = NEXT(action_modify_field_dst,
7391 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7392 		.call = parse_vc_conf,
7393 	},
7394 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7395 		.name = "{dst_type}",
7396 		.help = "destination field type value",
7397 		.call = parse_vc_modify_field_id,
7398 		.comp = comp_set_modify_field_id,
7399 	},
7400 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7401 		.name = "dst_level",
7402 		.help = "destination field level",
7403 		.next = NEXT(action_modify_field_dst,
7404 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7405 		.call = parse_vc_conf,
7406 	},
7407 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7408 		.name = "{dst_level}",
7409 		.help = "destination field level value",
7410 		.call = parse_vc_modify_field_level,
7411 		.comp = comp_none,
7412 	},
7413 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7414 		.name = "dst_tag_index",
7415 		.help = "destination field tag array",
7416 		.next = NEXT(action_modify_field_dst,
7417 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7418 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7419 					dst.tag_index)),
7420 		.call = parse_vc_conf,
7421 	},
7422 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7423 		.name = "dst_type_id",
7424 		.help = "destination field type ID",
7425 		.next = NEXT(action_modify_field_dst,
7426 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7427 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7428 					dst.type)),
7429 		.call = parse_vc_conf,
7430 	},
7431 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7432 		.name = "dst_class",
7433 		.help = "destination field class ID",
7434 		.next = NEXT(action_modify_field_dst,
7435 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7436 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7437 					     dst.class_id)),
7438 		.call = parse_vc_conf,
7439 	},
7440 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7441 		.name = "dst_offset",
7442 		.help = "destination field bit offset",
7443 		.next = NEXT(action_modify_field_dst,
7444 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7445 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7446 					dst.offset)),
7447 		.call = parse_vc_conf,
7448 	},
7449 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7450 		.name = "src_type",
7451 		.help = "source field type",
7452 		.next = NEXT(action_modify_field_src,
7453 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7454 		.call = parse_vc_conf,
7455 	},
7456 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7457 		.name = "{src_type}",
7458 		.help = "source field type value",
7459 		.call = parse_vc_modify_field_id,
7460 		.comp = comp_set_modify_field_id,
7461 	},
7462 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7463 		.name = "src_level",
7464 		.help = "source field level",
7465 		.next = NEXT(action_modify_field_src,
7466 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7467 		.call = parse_vc_conf,
7468 	},
7469 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7470 		.name = "{src_level}",
7471 		.help = "source field level value",
7472 		.call = parse_vc_modify_field_level,
7473 		.comp = comp_none,
7474 	},
7475 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7476 		.name = "src_tag_index",
7477 		.help = "source field tag array",
7478 		.next = NEXT(action_modify_field_src,
7479 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7480 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7481 					src.tag_index)),
7482 		.call = parse_vc_conf,
7483 	},
7484 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7485 		.name = "src_type_id",
7486 		.help = "source field type ID",
7487 		.next = NEXT(action_modify_field_src,
7488 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7489 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7490 					src.type)),
7491 		.call = parse_vc_conf,
7492 	},
7493 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7494 		.name = "src_class",
7495 		.help = "source field class ID",
7496 		.next = NEXT(action_modify_field_src,
7497 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7498 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7499 					     src.class_id)),
7500 		.call = parse_vc_conf,
7501 	},
7502 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7503 		.name = "src_offset",
7504 		.help = "source field bit offset",
7505 		.next = NEXT(action_modify_field_src,
7506 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7507 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7508 					src.offset)),
7509 		.call = parse_vc_conf,
7510 	},
7511 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7512 		.name = "src_value",
7513 		.help = "source immediate value",
7514 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7515 			     NEXT_ENTRY(COMMON_HEX)),
7516 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7517 			     ARGS_ENTRY_ARB(0, 0),
7518 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7519 					src.value)),
7520 		.call = parse_vc_conf,
7521 	},
7522 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7523 		.name = "src_ptr",
7524 		.help = "pointer to source immediate value",
7525 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7526 			     NEXT_ENTRY(COMMON_HEX)),
7527 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7528 					src.pvalue),
7529 			     ARGS_ENTRY_ARB(0, 0),
7530 			     ARGS_ENTRY_ARB
7531 				(sizeof(struct rte_flow_action_modify_field),
7532 				 FLOW_FIELD_PATTERN_SIZE)),
7533 		.call = parse_vc_conf,
7534 	},
7535 	[ACTION_MODIFY_FIELD_WIDTH] = {
7536 		.name = "width",
7537 		.help = "number of bits to copy",
7538 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7539 			NEXT_ENTRY(COMMON_UNSIGNED)),
7540 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7541 					width)),
7542 		.call = parse_vc_conf,
7543 	},
7544 	[ACTION_SEND_TO_KERNEL] = {
7545 		.name = "send_to_kernel",
7546 		.help = "send packets to kernel",
7547 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7548 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7549 		.call = parse_vc,
7550 	},
7551 	[ACTION_IPV6_EXT_REMOVE] = {
7552 		.name = "ipv6_ext_remove",
7553 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7554 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7555 			sizeof(struct action_ipv6_ext_remove_data)),
7556 		.next = NEXT(action_ipv6_ext_remove),
7557 		.call = parse_vc_action_ipv6_ext_remove,
7558 	},
7559 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7560 		.name = "index",
7561 		.help = "the index of ipv6_ext_remove",
7562 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7563 	},
7564 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7565 		.name = "{index}",
7566 		.type = "UNSIGNED",
7567 		.help = "unsigned integer value",
7568 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7569 		.call = parse_vc_action_ipv6_ext_remove_index,
7570 		.comp = comp_set_ipv6_ext_index,
7571 	},
7572 	[ACTION_IPV6_EXT_PUSH] = {
7573 		.name = "ipv6_ext_push",
7574 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7575 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7576 			sizeof(struct action_ipv6_ext_push_data)),
7577 		.next = NEXT(action_ipv6_ext_push),
7578 		.call = parse_vc_action_ipv6_ext_push,
7579 	},
7580 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7581 		.name = "index",
7582 		.help = "the index of ipv6_ext_push",
7583 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7584 	},
7585 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7586 		.name = "{index}",
7587 		.type = "UNSIGNED",
7588 		.help = "unsigned integer value",
7589 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7590 		.call = parse_vc_action_ipv6_ext_push_index,
7591 		.comp = comp_set_ipv6_ext_index,
7592 	},
7593 	[ACTION_NAT64] = {
7594 		.name = "nat64",
7595 		.help = "NAT64 IP headers translation",
7596 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7597 		.next = NEXT(action_nat64),
7598 		.call = parse_vc,
7599 	},
7600 	[ACTION_NAT64_MODE] = {
7601 		.name = "type",
7602 		.help = "NAT64 translation type",
7603 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7604 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7605 		.call = parse_vc_conf,
7606 	},
7607 	[ACTION_JUMP_TO_TABLE_INDEX] = {
7608 		.name = "jump_to_table_index",
7609 		.help = "Jump to table index",
7610 		.priv = PRIV_ACTION(JUMP_TO_TABLE_INDEX,
7611 				    sizeof(struct rte_flow_action_jump_to_table_index)),
7612 		.next = NEXT(action_jump_to_table_index),
7613 		.call = parse_vc,
7614 	},
7615 	[ACTION_JUMP_TO_TABLE_INDEX_TABLE] = {
7616 		.name = "table",
7617 		.help = "table to redirect traffic to",
7618 		.next = NEXT(action_jump_to_table_index, NEXT_ENTRY(COMMON_UNSIGNED)),
7619 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump_to_table_index, table)),
7620 		.call = parse_vc_conf,
7621 	},
7622 	[ACTION_JUMP_TO_TABLE_INDEX_INDEX] = {
7623 		.name = "index",
7624 		.help = "rule index to redirect traffic to",
7625 		.next = NEXT(action_jump_to_table_index, NEXT_ENTRY(COMMON_UNSIGNED)),
7626 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump_to_table_index, index)),
7627 		.call = parse_vc_conf,
7628 	},
7629 
7630 	/* Top level command. */
7631 	[SET] = {
7632 		.name = "set",
7633 		.help = "set raw encap/decap/sample data",
7634 		.type = "set raw_encap|raw_decap <index> <pattern>"
7635 				" or set sample_actions <index> <action>",
7636 		.next = NEXT(NEXT_ENTRY
7637 			     (SET_RAW_ENCAP,
7638 			      SET_RAW_DECAP,
7639 			      SET_SAMPLE_ACTIONS,
7640 			      SET_IPV6_EXT_REMOVE,
7641 			      SET_IPV6_EXT_PUSH)),
7642 		.call = parse_set_init,
7643 	},
7644 	/* Sub-level commands. */
7645 	[SET_RAW_ENCAP] = {
7646 		.name = "raw_encap",
7647 		.help = "set raw encap data",
7648 		.next = NEXT(next_set_raw),
7649 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7650 				(offsetof(struct buffer, port),
7651 				 sizeof(((struct buffer *)0)->port),
7652 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7653 		.call = parse_set_raw_encap_decap,
7654 	},
7655 	[SET_RAW_DECAP] = {
7656 		.name = "raw_decap",
7657 		.help = "set raw decap data",
7658 		.next = NEXT(next_set_raw),
7659 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7660 				(offsetof(struct buffer, port),
7661 				 sizeof(((struct buffer *)0)->port),
7662 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7663 		.call = parse_set_raw_encap_decap,
7664 	},
7665 	[SET_RAW_INDEX] = {
7666 		.name = "{index}",
7667 		.type = "COMMON_UNSIGNED",
7668 		.help = "index of raw_encap/raw_decap data",
7669 		.next = NEXT(next_item),
7670 		.call = parse_port,
7671 	},
7672 	[SET_SAMPLE_INDEX] = {
7673 		.name = "{index}",
7674 		.type = "UNSIGNED",
7675 		.help = "index of sample actions",
7676 		.next = NEXT(next_action_sample),
7677 		.call = parse_port,
7678 	},
7679 	[SET_SAMPLE_ACTIONS] = {
7680 		.name = "sample_actions",
7681 		.help = "set sample actions list",
7682 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7683 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7684 				(offsetof(struct buffer, port),
7685 				 sizeof(((struct buffer *)0)->port),
7686 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7687 		.call = parse_set_sample_action,
7688 	},
7689 	[SET_IPV6_EXT_PUSH] = {
7690 		.name = "ipv6_ext_push",
7691 		.help = "set IPv6 extension header",
7692 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7693 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7694 				(offsetof(struct buffer, port),
7695 				 sizeof(((struct buffer *)0)->port),
7696 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7697 		.call = parse_set_ipv6_ext_action,
7698 	},
7699 	[SET_IPV6_EXT_REMOVE] = {
7700 		.name = "ipv6_ext_remove",
7701 		.help = "set IPv6 extension header",
7702 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7703 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7704 				(offsetof(struct buffer, port),
7705 				 sizeof(((struct buffer *)0)->port),
7706 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7707 		.call = parse_set_ipv6_ext_action,
7708 	},
7709 	[SET_IPV6_EXT_INDEX] = {
7710 		.name = "{index}",
7711 		.type = "UNSIGNED",
7712 		.help = "index of ipv6 extension push/remove actions",
7713 		.next = NEXT(item_ipv6_push_ext),
7714 		.call = parse_port,
7715 	},
7716 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7717 		.name = "ipv6_ext",
7718 		.help = "set IPv6 extension header",
7719 		.priv = PRIV_ITEM(IPV6_EXT,
7720 				  sizeof(struct rte_flow_item_ipv6_ext)),
7721 		.next = NEXT(item_ipv6_push_ext_type),
7722 		.call = parse_vc,
7723 	},
7724 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7725 		.name = "type",
7726 		.help = "set IPv6 extension type",
7727 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7728 					     next_hdr)),
7729 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7730 			     item_param),
7731 	},
7732 	[ACTION_SET_TAG] = {
7733 		.name = "set_tag",
7734 		.help = "set tag",
7735 		.priv = PRIV_ACTION(SET_TAG,
7736 			sizeof(struct rte_flow_action_set_tag)),
7737 		.next = NEXT(action_set_tag),
7738 		.call = parse_vc,
7739 	},
7740 	[ACTION_SET_TAG_INDEX] = {
7741 		.name = "index",
7742 		.help = "index of tag array",
7743 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7744 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7745 		.call = parse_vc_conf,
7746 	},
7747 	[ACTION_SET_TAG_DATA] = {
7748 		.name = "data",
7749 		.help = "tag value",
7750 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7751 		.args = ARGS(ARGS_ENTRY
7752 			     (struct rte_flow_action_set_tag, data)),
7753 		.call = parse_vc_conf,
7754 	},
7755 	[ACTION_SET_TAG_MASK] = {
7756 		.name = "mask",
7757 		.help = "mask for tag value",
7758 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7759 		.args = ARGS(ARGS_ENTRY
7760 			     (struct rte_flow_action_set_tag, mask)),
7761 		.call = parse_vc_conf,
7762 	},
7763 	[ACTION_SET_META] = {
7764 		.name = "set_meta",
7765 		.help = "set metadata",
7766 		.priv = PRIV_ACTION(SET_META,
7767 			sizeof(struct rte_flow_action_set_meta)),
7768 		.next = NEXT(action_set_meta),
7769 		.call = parse_vc_action_set_meta,
7770 	},
7771 	[ACTION_SET_META_DATA] = {
7772 		.name = "data",
7773 		.help = "metadata value",
7774 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7775 		.args = ARGS(ARGS_ENTRY
7776 			     (struct rte_flow_action_set_meta, data)),
7777 		.call = parse_vc_conf,
7778 	},
7779 	[ACTION_SET_META_MASK] = {
7780 		.name = "mask",
7781 		.help = "mask for metadata value",
7782 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7783 		.args = ARGS(ARGS_ENTRY
7784 			     (struct rte_flow_action_set_meta, mask)),
7785 		.call = parse_vc_conf,
7786 	},
7787 	[ACTION_SET_IPV4_DSCP] = {
7788 		.name = "set_ipv4_dscp",
7789 		.help = "set DSCP value",
7790 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7791 			sizeof(struct rte_flow_action_set_dscp)),
7792 		.next = NEXT(action_set_ipv4_dscp),
7793 		.call = parse_vc,
7794 	},
7795 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7796 		.name = "dscp_value",
7797 		.help = "new IPv4 DSCP value to set",
7798 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7799 		.args = ARGS(ARGS_ENTRY
7800 			     (struct rte_flow_action_set_dscp, dscp)),
7801 		.call = parse_vc_conf,
7802 	},
7803 	[ACTION_SET_IPV6_DSCP] = {
7804 		.name = "set_ipv6_dscp",
7805 		.help = "set DSCP value",
7806 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7807 			sizeof(struct rte_flow_action_set_dscp)),
7808 		.next = NEXT(action_set_ipv6_dscp),
7809 		.call = parse_vc,
7810 	},
7811 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7812 		.name = "dscp_value",
7813 		.help = "new IPv6 DSCP value to set",
7814 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7815 		.args = ARGS(ARGS_ENTRY
7816 			     (struct rte_flow_action_set_dscp, dscp)),
7817 		.call = parse_vc_conf,
7818 	},
7819 	[ACTION_AGE] = {
7820 		.name = "age",
7821 		.help = "set a specific metadata header",
7822 		.next = NEXT(action_age),
7823 		.priv = PRIV_ACTION(AGE,
7824 			sizeof(struct rte_flow_action_age)),
7825 		.call = parse_vc,
7826 	},
7827 	[ACTION_AGE_TIMEOUT] = {
7828 		.name = "timeout",
7829 		.help = "flow age timeout value",
7830 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7831 					   timeout, 24)),
7832 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7833 		.call = parse_vc_conf,
7834 	},
7835 	[ACTION_AGE_UPDATE] = {
7836 		.name = "age_update",
7837 		.help = "update aging parameter",
7838 		.next = NEXT(action_age_update),
7839 		.priv = PRIV_ACTION(AGE,
7840 				    sizeof(struct rte_flow_update_age)),
7841 		.call = parse_vc,
7842 	},
7843 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7844 		.name = "timeout",
7845 		.help = "age timeout update value",
7846 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7847 					   timeout, 24)),
7848 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7849 		.call = parse_vc_conf_timeout,
7850 	},
7851 	[ACTION_AGE_UPDATE_TOUCH] = {
7852 		.name = "touch",
7853 		.help = "this flow is touched",
7854 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7855 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7856 					   touch, 1)),
7857 		.call = parse_vc_conf,
7858 	},
7859 	[ACTION_SAMPLE] = {
7860 		.name = "sample",
7861 		.help = "set a sample action",
7862 		.next = NEXT(action_sample),
7863 		.priv = PRIV_ACTION(SAMPLE,
7864 			sizeof(struct action_sample_data)),
7865 		.call = parse_vc_action_sample,
7866 	},
7867 	[ACTION_SAMPLE_RATIO] = {
7868 		.name = "ratio",
7869 		.help = "flow sample ratio value",
7870 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7871 		.args = ARGS(ARGS_ENTRY_ARB
7872 			     (offsetof(struct action_sample_data, conf) +
7873 			      offsetof(struct rte_flow_action_sample, ratio),
7874 			      sizeof(((struct rte_flow_action_sample *)0)->
7875 				     ratio))),
7876 	},
7877 	[ACTION_SAMPLE_INDEX] = {
7878 		.name = "index",
7879 		.help = "the index of sample actions list",
7880 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7881 	},
7882 	[ACTION_SAMPLE_INDEX_VALUE] = {
7883 		.name = "{index}",
7884 		.type = "COMMON_UNSIGNED",
7885 		.help = "unsigned integer value",
7886 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7887 		.call = parse_vc_action_sample_index,
7888 		.comp = comp_set_sample_index,
7889 	},
7890 	[ACTION_CONNTRACK] = {
7891 		.name = "conntrack",
7892 		.help = "create a conntrack object",
7893 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7894 		.priv = PRIV_ACTION(CONNTRACK,
7895 				    sizeof(struct rte_flow_action_conntrack)),
7896 		.call = parse_vc,
7897 	},
7898 	[ACTION_CONNTRACK_UPDATE] = {
7899 		.name = "conntrack_update",
7900 		.help = "update a conntrack object",
7901 		.next = NEXT(action_update_conntrack),
7902 		.priv = PRIV_ACTION(CONNTRACK,
7903 				    sizeof(struct rte_flow_modify_conntrack)),
7904 		.call = parse_vc,
7905 	},
7906 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7907 		.name = "dir",
7908 		.help = "update a conntrack object direction",
7909 		.next = NEXT(action_update_conntrack),
7910 		.call = parse_vc_action_conntrack_update,
7911 	},
7912 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7913 		.name = "ctx",
7914 		.help = "update a conntrack object context",
7915 		.next = NEXT(action_update_conntrack),
7916 		.call = parse_vc_action_conntrack_update,
7917 	},
7918 	[ACTION_PORT_REPRESENTOR] = {
7919 		.name = "port_representor",
7920 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7921 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7922 				    sizeof(struct rte_flow_action_ethdev)),
7923 		.next = NEXT(action_port_representor),
7924 		.call = parse_vc,
7925 	},
7926 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7927 		.name = "port_id",
7928 		.help = "ethdev port ID",
7929 		.next = NEXT(action_port_representor,
7930 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7931 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7932 					port_id)),
7933 		.call = parse_vc_conf,
7934 	},
7935 	[ACTION_REPRESENTED_PORT] = {
7936 		.name = "represented_port",
7937 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7938 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7939 				sizeof(struct rte_flow_action_ethdev)),
7940 		.next = NEXT(action_represented_port),
7941 		.call = parse_vc,
7942 	},
7943 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7944 		.name = "ethdev_port_id",
7945 		.help = "ethdev port ID",
7946 		.next = NEXT(action_represented_port,
7947 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7948 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7949 					port_id)),
7950 		.call = parse_vc_conf,
7951 	},
7952 	/* Indirect action destroy arguments. */
7953 	[INDIRECT_ACTION_DESTROY_ID] = {
7954 		.name = "action_id",
7955 		.help = "specify a indirect action id to destroy",
7956 		.next = NEXT(next_ia_destroy_attr,
7957 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7958 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7959 					    args.ia_destroy.action_id)),
7960 		.call = parse_ia_destroy,
7961 	},
7962 	/* Indirect action create arguments. */
7963 	[INDIRECT_ACTION_CREATE_ID] = {
7964 		.name = "action_id",
7965 		.help = "specify a indirect action id to create",
7966 		.next = NEXT(next_ia_create_attr,
7967 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7968 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7969 	},
7970 	[ACTION_INDIRECT] = {
7971 		.name = "indirect",
7972 		.help = "apply indirect action by id",
7973 		.priv = PRIV_ACTION(INDIRECT, 0),
7974 		.next = NEXT(next_ia),
7975 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7976 		.call = parse_vc,
7977 	},
7978 	[ACTION_INDIRECT_LIST] = {
7979 		.name = "indirect_list",
7980 		.help = "apply indirect list action by id",
7981 		.priv = PRIV_ACTION(INDIRECT_LIST,
7982 				    sizeof(struct
7983 					   rte_flow_action_indirect_list)),
7984 		.next = NEXT(next_ial),
7985 		.call = parse_vc,
7986 	},
7987 	[ACTION_INDIRECT_LIST_HANDLE] = {
7988 		.name = "handle",
7989 		.help = "indirect list handle",
7990 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7991 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7992 	},
7993 	[ACTION_INDIRECT_LIST_CONF] = {
7994 		.name = "conf",
7995 		.help = "indirect list configuration",
7996 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7997 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7998 	},
7999 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
8000 		.type = "UNSIGNED",
8001 		.help = "unsigned integer value",
8002 		.call = parse_indlst_id2ptr,
8003 		.comp = comp_none,
8004 	},
8005 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
8006 		.type = "UNSIGNED",
8007 		.help = "unsigned integer value",
8008 		.call = parse_indlst_id2ptr,
8009 		.comp = comp_none,
8010 	},
8011 	[ACTION_SHARED_INDIRECT] = {
8012 		.name = "shared_indirect",
8013 		.help = "apply indirect action by id and port",
8014 		.priv = PRIV_ACTION(INDIRECT, 0),
8015 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
8016 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
8017 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
8018 		.call = parse_vc,
8019 	},
8020 	[INDIRECT_ACTION_PORT] = {
8021 		.name = "{indirect_action_port}",
8022 		.type = "INDIRECT_ACTION_PORT",
8023 		.help = "indirect action port",
8024 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
8025 		.call = parse_ia_port,
8026 		.comp = comp_none,
8027 	},
8028 	[INDIRECT_ACTION_ID2PTR] = {
8029 		.name = "{action_id}",
8030 		.type = "INDIRECT_ACTION_ID",
8031 		.help = "indirect action id",
8032 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
8033 		.call = parse_ia_id2ptr,
8034 		.comp = comp_none,
8035 	},
8036 	[INDIRECT_ACTION_INGRESS] = {
8037 		.name = "ingress",
8038 		.help = "affect rule to ingress",
8039 		.next = NEXT(next_ia_create_attr),
8040 		.call = parse_ia,
8041 	},
8042 	[INDIRECT_ACTION_EGRESS] = {
8043 		.name = "egress",
8044 		.help = "affect rule to egress",
8045 		.next = NEXT(next_ia_create_attr),
8046 		.call = parse_ia,
8047 	},
8048 	[INDIRECT_ACTION_TRANSFER] = {
8049 		.name = "transfer",
8050 		.help = "affect rule to transfer",
8051 		.next = NEXT(next_ia_create_attr),
8052 		.call = parse_ia,
8053 	},
8054 	[INDIRECT_ACTION_SPEC] = {
8055 		.name = "action",
8056 		.help = "specify action to create indirect handle",
8057 		.next = NEXT(next_action),
8058 	},
8059 	[INDIRECT_ACTION_LIST] = {
8060 		.name = "list",
8061 		.help = "specify actions for indirect handle list",
8062 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8063 		.call = parse_ia,
8064 	},
8065 	[INDIRECT_ACTION_FLOW_CONF] = {
8066 		.name = "flow_conf",
8067 		.help = "specify actions configuration for indirect handle list",
8068 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8069 		.call = parse_ia,
8070 	},
8071 	[ACTION_POL_G] = {
8072 		.name = "g_actions",
8073 		.help = "submit a list of associated actions for green",
8074 		.next = NEXT(next_action),
8075 		.call = parse_mp,
8076 	},
8077 	[ACTION_POL_Y] = {
8078 		.name = "y_actions",
8079 		.help = "submit a list of associated actions for yellow",
8080 		.next = NEXT(next_action),
8081 	},
8082 	[ACTION_POL_R] = {
8083 		.name = "r_actions",
8084 		.help = "submit a list of associated actions for red",
8085 		.next = NEXT(next_action),
8086 	},
8087 	[ACTION_QUOTA_CREATE] = {
8088 		.name = "quota_create",
8089 		.help = "create quota action",
8090 		.priv = PRIV_ACTION(QUOTA,
8091 				    sizeof(struct rte_flow_action_quota)),
8092 		.next = NEXT(action_quota_create),
8093 		.call = parse_vc
8094 	},
8095 	[ACTION_QUOTA_CREATE_LIMIT] = {
8096 		.name = "limit",
8097 		.help = "quota limit",
8098 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
8099 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
8100 		.call = parse_vc_conf
8101 	},
8102 	[ACTION_QUOTA_CREATE_MODE] = {
8103 		.name = "mode",
8104 		.help = "quota mode",
8105 		.next = NEXT(action_quota_create,
8106 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
8107 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
8108 		.call = parse_vc_conf
8109 	},
8110 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
8111 		.name = "mode_name",
8112 		.help = "quota mode name",
8113 		.call = parse_quota_mode_name,
8114 		.comp = comp_quota_mode_name
8115 	},
8116 	[ACTION_QUOTA_QU] = {
8117 		.name = "quota_update",
8118 		.help = "update quota action",
8119 		.priv = PRIV_ACTION(QUOTA,
8120 				    sizeof(struct rte_flow_update_quota)),
8121 		.next = NEXT(action_quota_update),
8122 		.call = parse_vc
8123 	},
8124 	[ACTION_QUOTA_QU_LIMIT] = {
8125 		.name = "limit",
8126 		.help = "quota limit",
8127 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
8128 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
8129 		.call = parse_vc_conf
8130 	},
8131 	[ACTION_QUOTA_QU_UPDATE_OP] = {
8132 		.name = "update_op",
8133 		.help = "query update op SET|ADD",
8134 		.next = NEXT(action_quota_update,
8135 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
8136 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
8137 		.call = parse_vc_conf
8138 	},
8139 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
8140 		.name = "update_op_name",
8141 		.help = "quota update op name",
8142 		.call = parse_quota_update_name,
8143 		.comp = comp_quota_update_name
8144 	},
8145 
8146 	/* Top-level command. */
8147 	[ADD] = {
8148 		.name = "add",
8149 		.type = "port meter policy {port_id} {arg}",
8150 		.help = "add port meter policy",
8151 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
8152 		.call = parse_init,
8153 	},
8154 	/* Sub-level commands. */
8155 	[ITEM_POL_PORT] = {
8156 		.name = "port",
8157 		.help = "add port meter policy",
8158 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
8159 	},
8160 	[ITEM_POL_METER] = {
8161 		.name = "meter",
8162 		.help = "add port meter policy",
8163 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8164 	},
8165 	[ITEM_POL_POLICY] = {
8166 		.name = "policy",
8167 		.help = "add port meter policy",
8168 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8169 				NEXT_ENTRY(ACTION_POL_Y),
8170 				NEXT_ENTRY(ACTION_POL_G),
8171 				NEXT_ENTRY(COMMON_POLICY_ID),
8172 				NEXT_ENTRY(COMMON_PORT_ID)),
8173 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8174 				ARGS_ENTRY(struct buffer, port)),
8175 		.call = parse_mp,
8176 	},
8177 	[ITEM_AGGR_AFFINITY] = {
8178 		.name = "aggr_affinity",
8179 		.help = "match on the aggregated port receiving the packets",
8180 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8181 				  sizeof(struct rte_flow_item_aggr_affinity)),
8182 		.next = NEXT(item_aggr_affinity),
8183 		.call = parse_vc,
8184 	},
8185 	[ITEM_AGGR_AFFINITY_VALUE] = {
8186 		.name = "affinity",
8187 		.help = "aggregated affinity value",
8188 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8189 			     item_param),
8190 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8191 					affinity)),
8192 	},
8193 	[ITEM_TX_QUEUE] = {
8194 		.name = "tx_queue",
8195 		.help = "match on the tx queue of send packet",
8196 		.priv = PRIV_ITEM(TX_QUEUE,
8197 				  sizeof(struct rte_flow_item_tx_queue)),
8198 		.next = NEXT(item_tx_queue),
8199 		.call = parse_vc,
8200 	},
8201 	[ITEM_TX_QUEUE_VALUE] = {
8202 		.name = "tx_queue_value",
8203 		.help = "tx queue value",
8204 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8205 			     item_param),
8206 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8207 					tx_queue)),
8208 	},
8209 };
8210 
8211 /** Remove and return last entry from argument stack. */
8212 static const struct arg *
8213 pop_args(struct context *ctx)
8214 {
8215 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8216 }
8217 
8218 /** Add entry on top of the argument stack. */
8219 static int
8220 push_args(struct context *ctx, const struct arg *arg)
8221 {
8222 	if (ctx->args_num == CTX_STACK_SIZE)
8223 		return -1;
8224 	ctx->args[ctx->args_num++] = arg;
8225 	return 0;
8226 }
8227 
8228 /** Spread value into buffer according to bit-mask. */
8229 static size_t
8230 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8231 {
8232 	uint32_t i = arg->size;
8233 	uint32_t end = 0;
8234 	int sub = 1;
8235 	int add = 0;
8236 	size_t len = 0;
8237 
8238 	if (!arg->mask)
8239 		return 0;
8240 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8241 	if (!arg->hton) {
8242 		i = 0;
8243 		end = arg->size;
8244 		sub = 0;
8245 		add = 1;
8246 	}
8247 #endif
8248 	while (i != end) {
8249 		unsigned int shift = 0;
8250 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8251 
8252 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8253 			if (!(arg->mask[i] & (1 << shift)))
8254 				continue;
8255 			++len;
8256 			if (!dst)
8257 				continue;
8258 			*buf &= ~(1 << shift);
8259 			*buf |= (val & 1) << shift;
8260 			val >>= 1;
8261 		}
8262 		i += add;
8263 	}
8264 	return len;
8265 }
8266 
8267 /** Compare a string with a partial one of a given length. */
8268 static int
8269 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8270 {
8271 	int r = strncmp(full, partial, partial_len);
8272 
8273 	if (r)
8274 		return r;
8275 	if (strlen(full) <= partial_len)
8276 		return 0;
8277 	return full[partial_len];
8278 }
8279 
8280 /**
8281  * Parse a prefix length and generate a bit-mask.
8282  *
8283  * Last argument (ctx->args) is retrieved to determine mask size, storage
8284  * location and whether the result must use network byte ordering.
8285  */
8286 static int
8287 parse_prefix(struct context *ctx, const struct token *token,
8288 	     const char *str, unsigned int len,
8289 	     void *buf, unsigned int size)
8290 {
8291 	const struct arg *arg = pop_args(ctx);
8292 	static const uint8_t conv[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0,
8293 					0xf8, 0xfc, 0xfe, 0xff };
8294 	char *end;
8295 	uintmax_t u;
8296 	unsigned int bytes;
8297 	unsigned int extra;
8298 
8299 	(void)token;
8300 	/* Argument is expected. */
8301 	if (!arg)
8302 		return -1;
8303 	errno = 0;
8304 	u = strtoumax(str, &end, 0);
8305 	if (errno || (size_t)(end - str) != len)
8306 		goto error;
8307 	if (arg->mask) {
8308 		uintmax_t v = 0;
8309 
8310 		extra = arg_entry_bf_fill(NULL, 0, arg);
8311 		if (u > extra)
8312 			goto error;
8313 		if (!ctx->object)
8314 			return len;
8315 		extra -= u;
8316 		while (u--)
8317 			(v <<= 1, v |= 1);
8318 		v <<= extra;
8319 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8320 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8321 			goto error;
8322 		return len;
8323 	}
8324 	bytes = u / 8;
8325 	extra = u % 8;
8326 	size = arg->size;
8327 	if (bytes > size || bytes + !!extra > size)
8328 		goto error;
8329 	if (!ctx->object)
8330 		return len;
8331 	buf = (uint8_t *)ctx->object + arg->offset;
8332 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8333 	if (!arg->hton) {
8334 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8335 		memset(buf, 0x00, size - bytes);
8336 		if (extra)
8337 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8338 	} else
8339 #endif
8340 	{
8341 		memset(buf, 0xff, bytes);
8342 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8343 		if (extra)
8344 			((uint8_t *)buf)[bytes] = conv[extra];
8345 	}
8346 	if (ctx->objmask)
8347 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8348 	return len;
8349 error:
8350 	push_args(ctx, arg);
8351 	return -1;
8352 }
8353 
8354 /** Default parsing function for token name matching. */
8355 static int
8356 parse_default(struct context *ctx, const struct token *token,
8357 	      const char *str, unsigned int len,
8358 	      void *buf, unsigned int size)
8359 {
8360 	(void)ctx;
8361 	(void)buf;
8362 	(void)size;
8363 	if (strcmp_partial(token->name, str, len))
8364 		return -1;
8365 	return len;
8366 }
8367 
8368 /** Parse flow command, initialize output buffer for subsequent tokens. */
8369 static int
8370 parse_init(struct context *ctx, const struct token *token,
8371 	   const char *str, unsigned int len,
8372 	   void *buf, unsigned int size)
8373 {
8374 	struct buffer *out = buf;
8375 
8376 	/* Token name must match. */
8377 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8378 		return -1;
8379 	/* Nothing else to do if there is no buffer. */
8380 	if (!out)
8381 		return len;
8382 	/* Make sure buffer is large enough. */
8383 	if (size < sizeof(*out))
8384 		return -1;
8385 	/* Initialize buffer. */
8386 	memset(out, 0x00, sizeof(*out));
8387 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8388 	ctx->objdata = 0;
8389 	ctx->object = out;
8390 	ctx->objmask = NULL;
8391 	return len;
8392 }
8393 
8394 /** Parse tokens for indirect action commands. */
8395 static int
8396 parse_ia(struct context *ctx, const struct token *token,
8397 	 const char *str, unsigned int len,
8398 	 void *buf, unsigned int size)
8399 {
8400 	struct buffer *out = buf;
8401 
8402 	/* Token name must match. */
8403 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8404 		return -1;
8405 	/* Nothing else to do if there is no buffer. */
8406 	if (!out)
8407 		return len;
8408 	if (!out->command) {
8409 		if (ctx->curr != INDIRECT_ACTION)
8410 			return -1;
8411 		if (sizeof(*out) > size)
8412 			return -1;
8413 		out->command = ctx->curr;
8414 		ctx->objdata = 0;
8415 		ctx->object = out;
8416 		ctx->objmask = NULL;
8417 		out->args.vc.data = (uint8_t *)out + size;
8418 		return len;
8419 	}
8420 	switch (ctx->curr) {
8421 	case INDIRECT_ACTION_CREATE:
8422 	case INDIRECT_ACTION_UPDATE:
8423 	case INDIRECT_ACTION_QUERY_UPDATE:
8424 		out->args.vc.actions =
8425 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8426 					       sizeof(double));
8427 		out->args.vc.attr.group = UINT32_MAX;
8428 		/* fallthrough */
8429 	case INDIRECT_ACTION_QUERY:
8430 		out->command = ctx->curr;
8431 		ctx->objdata = 0;
8432 		ctx->object = out;
8433 		ctx->objmask = NULL;
8434 		return len;
8435 	case INDIRECT_ACTION_EGRESS:
8436 		out->args.vc.attr.egress = 1;
8437 		return len;
8438 	case INDIRECT_ACTION_INGRESS:
8439 		out->args.vc.attr.ingress = 1;
8440 		return len;
8441 	case INDIRECT_ACTION_TRANSFER:
8442 		out->args.vc.attr.transfer = 1;
8443 		return len;
8444 	case INDIRECT_ACTION_QU_MODE:
8445 		return len;
8446 	case INDIRECT_ACTION_LIST:
8447 		out->command = INDIRECT_ACTION_LIST_CREATE;
8448 		return len;
8449 	case INDIRECT_ACTION_FLOW_CONF:
8450 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8451 		return len;
8452 	default:
8453 		return -1;
8454 	}
8455 }
8456 
8457 
8458 /** Parse tokens for indirect action destroy command. */
8459 static int
8460 parse_ia_destroy(struct context *ctx, const struct token *token,
8461 		 const char *str, unsigned int len,
8462 		 void *buf, unsigned int size)
8463 {
8464 	struct buffer *out = buf;
8465 	uint32_t *action_id;
8466 
8467 	/* Token name must match. */
8468 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8469 		return -1;
8470 	/* Nothing else to do if there is no buffer. */
8471 	if (!out)
8472 		return len;
8473 	if (!out->command || out->command == INDIRECT_ACTION) {
8474 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8475 			return -1;
8476 		if (sizeof(*out) > size)
8477 			return -1;
8478 		out->command = ctx->curr;
8479 		ctx->objdata = 0;
8480 		ctx->object = out;
8481 		ctx->objmask = NULL;
8482 		out->args.ia_destroy.action_id =
8483 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8484 					       sizeof(double));
8485 		return len;
8486 	}
8487 	action_id = out->args.ia_destroy.action_id
8488 		    + out->args.ia_destroy.action_id_n++;
8489 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8490 		return -1;
8491 	ctx->objdata = 0;
8492 	ctx->object = action_id;
8493 	ctx->objmask = NULL;
8494 	return len;
8495 }
8496 
8497 /** Parse tokens for indirect action commands. */
8498 static int
8499 parse_qia(struct context *ctx, const struct token *token,
8500 	  const char *str, unsigned int len,
8501 	  void *buf, unsigned int size)
8502 {
8503 	struct buffer *out = buf;
8504 
8505 	/* Token name must match. */
8506 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8507 		return -1;
8508 	/* Nothing else to do if there is no buffer. */
8509 	if (!out)
8510 		return len;
8511 	if (!out->command) {
8512 		if (ctx->curr != QUEUE)
8513 			return -1;
8514 		if (sizeof(*out) > size)
8515 			return -1;
8516 		out->args.vc.data = (uint8_t *)out + size;
8517 		return len;
8518 	}
8519 	switch (ctx->curr) {
8520 	case QUEUE_INDIRECT_ACTION:
8521 		return len;
8522 	case QUEUE_INDIRECT_ACTION_CREATE:
8523 	case QUEUE_INDIRECT_ACTION_UPDATE:
8524 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8525 		out->args.vc.actions =
8526 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8527 					       sizeof(double));
8528 		out->args.vc.attr.group = UINT32_MAX;
8529 		/* fallthrough */
8530 	case QUEUE_INDIRECT_ACTION_QUERY:
8531 		out->command = ctx->curr;
8532 		ctx->objdata = 0;
8533 		ctx->object = out;
8534 		ctx->objmask = NULL;
8535 		return len;
8536 	case QUEUE_INDIRECT_ACTION_EGRESS:
8537 		out->args.vc.attr.egress = 1;
8538 		return len;
8539 	case QUEUE_INDIRECT_ACTION_INGRESS:
8540 		out->args.vc.attr.ingress = 1;
8541 		return len;
8542 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8543 		out->args.vc.attr.transfer = 1;
8544 		return len;
8545 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8546 		return len;
8547 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8548 		return len;
8549 	case QUEUE_INDIRECT_ACTION_LIST:
8550 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8551 		return len;
8552 	default:
8553 		return -1;
8554 	}
8555 }
8556 
8557 /** Parse tokens for indirect action destroy command. */
8558 static int
8559 parse_qia_destroy(struct context *ctx, const struct token *token,
8560 		  const char *str, unsigned int len,
8561 		  void *buf, unsigned int size)
8562 {
8563 	struct buffer *out = buf;
8564 	uint32_t *action_id;
8565 
8566 	/* Token name must match. */
8567 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8568 		return -1;
8569 	/* Nothing else to do if there is no buffer. */
8570 	if (!out)
8571 		return len;
8572 	if (!out->command || out->command == QUEUE) {
8573 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8574 			return -1;
8575 		if (sizeof(*out) > size)
8576 			return -1;
8577 		out->command = ctx->curr;
8578 		ctx->objdata = 0;
8579 		ctx->object = out;
8580 		ctx->objmask = NULL;
8581 		out->args.ia_destroy.action_id =
8582 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8583 					       sizeof(double));
8584 		return len;
8585 	}
8586 	switch (ctx->curr) {
8587 	case QUEUE_INDIRECT_ACTION:
8588 		out->command = ctx->curr;
8589 		ctx->objdata = 0;
8590 		ctx->object = out;
8591 		ctx->objmask = NULL;
8592 		return len;
8593 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8594 		action_id = out->args.ia_destroy.action_id
8595 				+ out->args.ia_destroy.action_id_n++;
8596 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8597 			return -1;
8598 		ctx->objdata = 0;
8599 		ctx->object = action_id;
8600 		ctx->objmask = NULL;
8601 		return len;
8602 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8603 		return len;
8604 	default:
8605 		return -1;
8606 	}
8607 }
8608 
8609 /** Parse tokens for meter policy action commands. */
8610 static int
8611 parse_mp(struct context *ctx, const struct token *token,
8612 	const char *str, unsigned int len,
8613 	void *buf, unsigned int size)
8614 {
8615 	struct buffer *out = buf;
8616 
8617 	/* Token name must match. */
8618 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8619 		return -1;
8620 	/* Nothing else to do if there is no buffer. */
8621 	if (!out)
8622 		return len;
8623 	if (!out->command) {
8624 		if (ctx->curr != ITEM_POL_POLICY)
8625 			return -1;
8626 		if (sizeof(*out) > size)
8627 			return -1;
8628 		out->command = ctx->curr;
8629 		ctx->objdata = 0;
8630 		ctx->object = out;
8631 		ctx->objmask = NULL;
8632 		out->args.vc.data = (uint8_t *)out + size;
8633 		return len;
8634 	}
8635 	switch (ctx->curr) {
8636 	case ACTION_POL_G:
8637 		out->args.vc.actions =
8638 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8639 					sizeof(double));
8640 		out->command = ctx->curr;
8641 		ctx->objdata = 0;
8642 		ctx->object = out;
8643 		ctx->objmask = NULL;
8644 		return len;
8645 	default:
8646 		return -1;
8647 	}
8648 }
8649 
8650 /** Parse tokens for validate/create commands. */
8651 static int
8652 parse_vc(struct context *ctx, const struct token *token,
8653 	 const char *str, unsigned int len,
8654 	 void *buf, unsigned int size)
8655 {
8656 	struct buffer *out = buf;
8657 	uint8_t *data;
8658 	uint32_t data_size;
8659 
8660 	/* Token name must match. */
8661 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8662 		return -1;
8663 	/* Nothing else to do if there is no buffer. */
8664 	if (!out)
8665 		return len;
8666 	if (!out->command) {
8667 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8668 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8669 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8670 		    ctx->curr != UPDATE)
8671 			return -1;
8672 		if (ctx->curr == UPDATE)
8673 			out->args.vc.pattern =
8674 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8675 						       sizeof(double));
8676 		if (sizeof(*out) > size)
8677 			return -1;
8678 		out->command = ctx->curr;
8679 		ctx->objdata = 0;
8680 		ctx->object = out;
8681 		ctx->objmask = NULL;
8682 		out->args.vc.data = (uint8_t *)out + size;
8683 		return len;
8684 	}
8685 	ctx->objdata = 0;
8686 	switch (ctx->curr) {
8687 	default:
8688 		ctx->object = &out->args.vc.attr;
8689 		break;
8690 	case VC_TUNNEL_SET:
8691 	case VC_TUNNEL_MATCH:
8692 		ctx->object = &out->args.vc.tunnel_ops;
8693 		break;
8694 	case VC_USER_ID:
8695 		ctx->object = out;
8696 		break;
8697 	}
8698 	ctx->objmask = NULL;
8699 	switch (ctx->curr) {
8700 	case VC_GROUP:
8701 	case VC_PRIORITY:
8702 	case VC_USER_ID:
8703 		return len;
8704 	case VC_TUNNEL_SET:
8705 		out->args.vc.tunnel_ops.enabled = 1;
8706 		out->args.vc.tunnel_ops.actions = 1;
8707 		return len;
8708 	case VC_TUNNEL_MATCH:
8709 		out->args.vc.tunnel_ops.enabled = 1;
8710 		out->args.vc.tunnel_ops.items = 1;
8711 		return len;
8712 	case VC_INGRESS:
8713 		out->args.vc.attr.ingress = 1;
8714 		return len;
8715 	case VC_EGRESS:
8716 		out->args.vc.attr.egress = 1;
8717 		return len;
8718 	case VC_TRANSFER:
8719 		out->args.vc.attr.transfer = 1;
8720 		return len;
8721 	case ITEM_PATTERN:
8722 		out->args.vc.pattern =
8723 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8724 					       sizeof(double));
8725 		ctx->object = out->args.vc.pattern;
8726 		ctx->objmask = NULL;
8727 		return len;
8728 	case ITEM_END:
8729 		if ((out->command == VALIDATE || out->command == CREATE) &&
8730 		    ctx->last)
8731 			return -1;
8732 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8733 		    !ctx->last)
8734 			return -1;
8735 		break;
8736 	case ACTIONS:
8737 		out->args.vc.actions = out->args.vc.pattern ?
8738 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8739 					       (out->args.vc.pattern +
8740 						out->args.vc.pattern_n),
8741 					       sizeof(double)) :
8742 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8743 					       sizeof(double));
8744 		ctx->object = out->args.vc.actions;
8745 		ctx->objmask = NULL;
8746 		return len;
8747 	case VC_IS_USER_ID:
8748 		out->args.vc.user_id = true;
8749 		return len;
8750 	default:
8751 		if (!token->priv)
8752 			return -1;
8753 		break;
8754 	}
8755 	if (!out->args.vc.actions) {
8756 		const struct parse_item_priv *priv = token->priv;
8757 		struct rte_flow_item *item =
8758 			out->args.vc.pattern + out->args.vc.pattern_n;
8759 
8760 		data_size = priv->size * 3; /* spec, last, mask */
8761 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8762 					       (out->args.vc.data - data_size),
8763 					       sizeof(double));
8764 		if ((uint8_t *)item + sizeof(*item) > data)
8765 			return -1;
8766 		*item = (struct rte_flow_item){
8767 			.type = priv->type,
8768 		};
8769 		++out->args.vc.pattern_n;
8770 		ctx->object = item;
8771 		ctx->objmask = NULL;
8772 	} else {
8773 		const struct parse_action_priv *priv = token->priv;
8774 		struct rte_flow_action *action =
8775 			out->args.vc.actions + out->args.vc.actions_n;
8776 
8777 		data_size = priv->size; /* configuration */
8778 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8779 					       (out->args.vc.data - data_size),
8780 					       sizeof(double));
8781 		if ((uint8_t *)action + sizeof(*action) > data)
8782 			return -1;
8783 		*action = (struct rte_flow_action){
8784 			.type = priv->type,
8785 			.conf = data_size ? data : NULL,
8786 		};
8787 		++out->args.vc.actions_n;
8788 		ctx->object = action;
8789 		ctx->objmask = NULL;
8790 	}
8791 	memset(data, 0, data_size);
8792 	out->args.vc.data = data;
8793 	ctx->objdata = data_size;
8794 	return len;
8795 }
8796 
8797 /** Parse pattern item parameter type. */
8798 static int
8799 parse_vc_spec(struct context *ctx, const struct token *token,
8800 	      const char *str, unsigned int len,
8801 	      void *buf, unsigned int size)
8802 {
8803 	struct buffer *out = buf;
8804 	struct rte_flow_item *item;
8805 	uint32_t data_size;
8806 	int index;
8807 	int objmask = 0;
8808 
8809 	(void)size;
8810 	/* Token name must match. */
8811 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8812 		return -1;
8813 	/* Parse parameter types. */
8814 	switch (ctx->curr) {
8815 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8816 
8817 	case ITEM_PARAM_IS:
8818 		index = 0;
8819 		objmask = 1;
8820 		break;
8821 	case ITEM_PARAM_SPEC:
8822 		index = 0;
8823 		break;
8824 	case ITEM_PARAM_LAST:
8825 		index = 1;
8826 		break;
8827 	case ITEM_PARAM_PREFIX:
8828 		/* Modify next token to expect a prefix. */
8829 		if (ctx->next_num < 2)
8830 			return -1;
8831 		ctx->next[ctx->next_num - 2] = prefix;
8832 		/* Fall through. */
8833 	case ITEM_PARAM_MASK:
8834 		index = 2;
8835 		break;
8836 	default:
8837 		return -1;
8838 	}
8839 	/* Nothing else to do if there is no buffer. */
8840 	if (!out)
8841 		return len;
8842 	if (!out->args.vc.pattern_n)
8843 		return -1;
8844 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8845 	data_size = ctx->objdata / 3; /* spec, last, mask */
8846 	/* Point to selected object. */
8847 	ctx->object = out->args.vc.data + (data_size * index);
8848 	if (objmask) {
8849 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8850 		item->mask = ctx->objmask;
8851 	} else
8852 		ctx->objmask = NULL;
8853 	/* Update relevant item pointer. */
8854 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8855 		ctx->object;
8856 	return len;
8857 }
8858 
8859 /** Parse action configuration field. */
8860 static int
8861 parse_vc_conf(struct context *ctx, const struct token *token,
8862 	      const char *str, unsigned int len,
8863 	      void *buf, unsigned int size)
8864 {
8865 	struct buffer *out = buf;
8866 
8867 	(void)size;
8868 	/* Token name must match. */
8869 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8870 		return -1;
8871 	/* Nothing else to do if there is no buffer. */
8872 	if (!out)
8873 		return len;
8874 	/* Point to selected object. */
8875 	ctx->object = out->args.vc.data;
8876 	ctx->objmask = NULL;
8877 	return len;
8878 }
8879 
8880 /** Parse action configuration field. */
8881 static int
8882 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8883 		      const char *str, unsigned int len,
8884 		      void *buf, unsigned int size)
8885 {
8886 	struct buffer *out = buf;
8887 	struct rte_flow_update_age *update;
8888 
8889 	(void)size;
8890 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8891 		return -1;
8892 	/* Token name must match. */
8893 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8894 		return -1;
8895 	/* Nothing else to do if there is no buffer. */
8896 	if (!out)
8897 		return len;
8898 	/* Point to selected object. */
8899 	ctx->object = out->args.vc.data;
8900 	ctx->objmask = NULL;
8901 	/* Update the timeout is valid. */
8902 	update = (struct rte_flow_update_age *)out->args.vc.data;
8903 	update->timeout_valid = 1;
8904 	return len;
8905 }
8906 
8907 /** Parse eCPRI common header type field. */
8908 static int
8909 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8910 			 const char *str, unsigned int len,
8911 			 void *buf, unsigned int size)
8912 {
8913 	struct rte_flow_item_ecpri *ecpri;
8914 	struct rte_flow_item_ecpri *ecpri_mask;
8915 	struct rte_flow_item *item;
8916 	uint32_t data_size;
8917 	uint8_t msg_type;
8918 	struct buffer *out = buf;
8919 	const struct arg *arg;
8920 
8921 	(void)size;
8922 	/* Token name must match. */
8923 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8924 		return -1;
8925 	switch (ctx->curr) {
8926 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8927 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8928 		break;
8929 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8930 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8931 		break;
8932 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8933 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8934 		break;
8935 	default:
8936 		return -1;
8937 	}
8938 	if (!ctx->object)
8939 		return len;
8940 	arg = pop_args(ctx);
8941 	if (!arg)
8942 		return -1;
8943 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8944 	ecpri->hdr.common.type = msg_type;
8945 	data_size = ctx->objdata / 3; /* spec, last, mask */
8946 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8947 						    (data_size * 2));
8948 	ecpri_mask->hdr.common.type = 0xFF;
8949 	if (arg->hton) {
8950 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8951 		ecpri_mask->hdr.common.u32 =
8952 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8953 	}
8954 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8955 	item->spec = ecpri;
8956 	item->mask = ecpri_mask;
8957 	return len;
8958 }
8959 
8960 /** Parse L2TPv2 common header type field. */
8961 static int
8962 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8963 			 const char *str, unsigned int len,
8964 			 void *buf, unsigned int size)
8965 {
8966 	struct rte_flow_item_l2tpv2 *l2tpv2;
8967 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8968 	struct rte_flow_item *item;
8969 	uint32_t data_size;
8970 	uint16_t msg_type = 0;
8971 	struct buffer *out = buf;
8972 	const struct arg *arg;
8973 
8974 	(void)size;
8975 	/* Token name must match. */
8976 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8977 		return -1;
8978 	switch (ctx->curr) {
8979 	case ITEM_L2TPV2_TYPE_DATA:
8980 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8981 		break;
8982 	case ITEM_L2TPV2_TYPE_DATA_L:
8983 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8984 		break;
8985 	case ITEM_L2TPV2_TYPE_DATA_S:
8986 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8987 		break;
8988 	case ITEM_L2TPV2_TYPE_DATA_O:
8989 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8990 		break;
8991 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8992 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8993 		break;
8994 	case ITEM_L2TPV2_TYPE_CTRL:
8995 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8996 		break;
8997 	default:
8998 		return -1;
8999 	}
9000 	if (!ctx->object)
9001 		return len;
9002 	arg = pop_args(ctx);
9003 	if (!arg)
9004 		return -1;
9005 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
9006 	l2tpv2->hdr.common.flags_version |= msg_type;
9007 	data_size = ctx->objdata / 3; /* spec, last, mask */
9008 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
9009 						    (data_size * 2));
9010 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
9011 	if (arg->hton) {
9012 		l2tpv2->hdr.common.flags_version =
9013 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
9014 		l2tpv2_mask->hdr.common.flags_version =
9015 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
9016 	}
9017 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
9018 	item->spec = l2tpv2;
9019 	item->mask = l2tpv2_mask;
9020 	return len;
9021 }
9022 
9023 /** Parse operation for compare match item. */
9024 static int
9025 parse_vc_compare_op(struct context *ctx, const struct token *token,
9026 			 const char *str, unsigned int len, void *buf,
9027 			 unsigned int size)
9028 {
9029 	struct rte_flow_item_compare *compare_item;
9030 	unsigned int i;
9031 
9032 	(void)token;
9033 	(void)buf;
9034 	(void)size;
9035 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
9036 		return -1;
9037 	for (i = 0; compare_ops[i]; ++i)
9038 		if (!strcmp_partial(compare_ops[i], str, len))
9039 			break;
9040 	if (!compare_ops[i])
9041 		return -1;
9042 	if (!ctx->object)
9043 		return len;
9044 	compare_item = ctx->object;
9045 	compare_item->operation = (enum rte_flow_item_compare_op)i;
9046 	return len;
9047 }
9048 
9049 /** Parse id for compare match item. */
9050 static int
9051 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
9052 			  const char *str, unsigned int len, void *buf,
9053 			  unsigned int size)
9054 {
9055 	struct rte_flow_item_compare *compare_item;
9056 	unsigned int i;
9057 
9058 	(void)token;
9059 	(void)buf;
9060 	(void)size;
9061 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
9062 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
9063 		return -1;
9064 	for (i = 0; flow_field_ids[i]; ++i)
9065 		if (!strcmp_partial(flow_field_ids[i], str, len))
9066 			break;
9067 	if (!flow_field_ids[i])
9068 		return -1;
9069 	if (!ctx->object)
9070 		return len;
9071 	compare_item = ctx->object;
9072 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
9073 		compare_item->a.field = (enum rte_flow_field_id)i;
9074 	else
9075 		compare_item->b.field = (enum rte_flow_field_id)i;
9076 	return len;
9077 }
9078 
9079 /** Parse level for compare match item. */
9080 static int
9081 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
9082 			     const char *str, unsigned int len, void *buf,
9083 			     unsigned int size)
9084 {
9085 	struct rte_flow_item_compare *compare_item;
9086 	struct flex_item *fp = NULL;
9087 	uint32_t val;
9088 	struct buffer *out = buf;
9089 	char *end;
9090 
9091 	(void)token;
9092 	(void)size;
9093 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9094 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
9095 		return -1;
9096 	if (!ctx->object)
9097 		return len;
9098 	compare_item = ctx->object;
9099 	errno = 0;
9100 	val = strtoumax(str, &end, 0);
9101 	if (errno || (size_t)(end - str) != len)
9102 		return -1;
9103 	/* No need to validate action template mask value */
9104 	if (out->args.vc.masks) {
9105 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
9106 			compare_item->a.level = val;
9107 		else
9108 			compare_item->b.level = val;
9109 		return len;
9110 	}
9111 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9112 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9113 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
9114 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9115 		if (val >= FLEX_MAX_PARSERS_NUM) {
9116 			printf("Bad flex item handle\n");
9117 			return -1;
9118 		}
9119 		fp = flex_items[ctx->port][val];
9120 		if (!fp) {
9121 			printf("Bad flex item handle\n");
9122 			return -1;
9123 		}
9124 	}
9125 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
9126 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
9127 			compare_item->a.level = val;
9128 		else
9129 			compare_item->a.flex_handle = fp->flex_handle;
9130 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
9131 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
9132 			compare_item->b.level = val;
9133 		else
9134 			compare_item->b.flex_handle = fp->flex_handle;
9135 	}
9136 	return len;
9137 }
9138 
9139 /** Parse meter color action type. */
9140 static int
9141 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
9142 				const char *str, unsigned int len,
9143 				void *buf, unsigned int size)
9144 {
9145 	struct rte_flow_action *action_data;
9146 	struct rte_flow_action_meter_color *conf;
9147 	enum rte_color color;
9148 
9149 	(void)buf;
9150 	(void)size;
9151 	/* Token name must match. */
9152 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9153 		return -1;
9154 	switch (ctx->curr) {
9155 	case ACTION_METER_COLOR_GREEN:
9156 		color = RTE_COLOR_GREEN;
9157 	break;
9158 	case ACTION_METER_COLOR_YELLOW:
9159 		color = RTE_COLOR_YELLOW;
9160 	break;
9161 	case ACTION_METER_COLOR_RED:
9162 		color = RTE_COLOR_RED;
9163 	break;
9164 	default:
9165 		return -1;
9166 	}
9167 
9168 	if (!ctx->object)
9169 		return len;
9170 	action_data = ctx->object;
9171 	conf = (struct rte_flow_action_meter_color *)
9172 					(uintptr_t)(action_data->conf);
9173 	conf->color = color;
9174 	return len;
9175 }
9176 
9177 /** Parse RSS action. */
9178 static int
9179 parse_vc_action_rss(struct context *ctx, const struct token *token,
9180 		    const char *str, unsigned int len,
9181 		    void *buf, unsigned int size)
9182 {
9183 	struct buffer *out = buf;
9184 	struct rte_flow_action *action;
9185 	struct action_rss_data *action_rss_data;
9186 	unsigned int i;
9187 	int ret;
9188 
9189 	ret = parse_vc(ctx, token, str, len, buf, size);
9190 	if (ret < 0)
9191 		return ret;
9192 	/* Nothing else to do if there is no buffer. */
9193 	if (!out)
9194 		return ret;
9195 	if (!out->args.vc.actions_n)
9196 		return -1;
9197 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9198 	/* Point to selected object. */
9199 	ctx->object = out->args.vc.data;
9200 	ctx->objmask = NULL;
9201 	/* Set up default configuration. */
9202 	action_rss_data = ctx->object;
9203 	*action_rss_data = (struct action_rss_data){
9204 		.conf = (struct rte_flow_action_rss){
9205 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9206 			.level = 0,
9207 			.types = rss_hf,
9208 			.key_len = 0,
9209 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9210 			.key = NULL,
9211 			.queue = action_rss_data->queue,
9212 		},
9213 		.queue = { 0 },
9214 	};
9215 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9216 		action_rss_data->queue[i] = i;
9217 	action->conf = &action_rss_data->conf;
9218 	return ret;
9219 }
9220 
9221 /**
9222  * Parse func field for RSS action.
9223  *
9224  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9225  * ACTION_RSS_FUNC_* index that called this function.
9226  */
9227 static int
9228 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9229 			 const char *str, unsigned int len,
9230 			 void *buf, unsigned int size)
9231 {
9232 	struct action_rss_data *action_rss_data;
9233 	enum rte_eth_hash_function func;
9234 
9235 	(void)buf;
9236 	(void)size;
9237 	/* Token name must match. */
9238 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9239 		return -1;
9240 	switch (ctx->curr) {
9241 	case ACTION_RSS_FUNC_DEFAULT:
9242 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9243 		break;
9244 	case ACTION_RSS_FUNC_TOEPLITZ:
9245 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9246 		break;
9247 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9248 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9249 		break;
9250 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9251 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9252 		break;
9253 	default:
9254 		return -1;
9255 	}
9256 	if (!ctx->object)
9257 		return len;
9258 	action_rss_data = ctx->object;
9259 	action_rss_data->conf.func = func;
9260 	return len;
9261 }
9262 
9263 /**
9264  * Parse type field for RSS action.
9265  *
9266  * Valid tokens are type field names and the "end" token.
9267  */
9268 static int
9269 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9270 			  const char *str, unsigned int len,
9271 			  void *buf, unsigned int size)
9272 {
9273 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9274 	struct action_rss_data *action_rss_data;
9275 	unsigned int i;
9276 
9277 	(void)token;
9278 	(void)buf;
9279 	(void)size;
9280 	if (ctx->curr != ACTION_RSS_TYPE)
9281 		return -1;
9282 	if (!(ctx->objdata >> 16) && ctx->object) {
9283 		action_rss_data = ctx->object;
9284 		action_rss_data->conf.types = 0;
9285 	}
9286 	if (!strcmp_partial("end", str, len)) {
9287 		ctx->objdata &= 0xffff;
9288 		return len;
9289 	}
9290 	for (i = 0; rss_type_table[i].str; ++i)
9291 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9292 			break;
9293 	if (!rss_type_table[i].str)
9294 		return -1;
9295 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9296 	/* Repeat token. */
9297 	if (ctx->next_num == RTE_DIM(ctx->next))
9298 		return -1;
9299 	ctx->next[ctx->next_num++] = next;
9300 	if (!ctx->object)
9301 		return len;
9302 	action_rss_data = ctx->object;
9303 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9304 	return len;
9305 }
9306 
9307 /**
9308  * Parse queue field for RSS action.
9309  *
9310  * Valid tokens are queue indices and the "end" token.
9311  */
9312 static int
9313 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9314 			  const char *str, unsigned int len,
9315 			  void *buf, unsigned int size)
9316 {
9317 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9318 	struct action_rss_data *action_rss_data;
9319 	const struct arg *arg;
9320 	int ret;
9321 	int i;
9322 
9323 	(void)token;
9324 	(void)buf;
9325 	(void)size;
9326 	if (ctx->curr != ACTION_RSS_QUEUE)
9327 		return -1;
9328 	i = ctx->objdata >> 16;
9329 	if (!strcmp_partial("end", str, len)) {
9330 		ctx->objdata &= 0xffff;
9331 		goto end;
9332 	}
9333 	if (i >= ACTION_RSS_QUEUE_NUM)
9334 		return -1;
9335 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9336 			     i * sizeof(action_rss_data->queue[i]),
9337 			     sizeof(action_rss_data->queue[i]));
9338 	if (push_args(ctx, arg))
9339 		return -1;
9340 	ret = parse_int(ctx, token, str, len, NULL, 0);
9341 	if (ret < 0) {
9342 		pop_args(ctx);
9343 		return -1;
9344 	}
9345 	++i;
9346 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9347 	/* Repeat token. */
9348 	if (ctx->next_num == RTE_DIM(ctx->next))
9349 		return -1;
9350 	ctx->next[ctx->next_num++] = next;
9351 end:
9352 	if (!ctx->object)
9353 		return len;
9354 	action_rss_data = ctx->object;
9355 	action_rss_data->conf.queue_num = i;
9356 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9357 	return len;
9358 }
9359 
9360 /** Setup VXLAN encap configuration. */
9361 static int
9362 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9363 {
9364 	/* Set up default configuration. */
9365 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9366 		.conf = (struct rte_flow_action_vxlan_encap){
9367 			.definition = action_vxlan_encap_data->items,
9368 		},
9369 		.items = {
9370 			{
9371 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9372 				.spec = &action_vxlan_encap_data->item_eth,
9373 				.mask = &rte_flow_item_eth_mask,
9374 			},
9375 			{
9376 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9377 				.spec = &action_vxlan_encap_data->item_vlan,
9378 				.mask = &rte_flow_item_vlan_mask,
9379 			},
9380 			{
9381 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9382 				.spec = &action_vxlan_encap_data->item_ipv4,
9383 				.mask = &rte_flow_item_ipv4_mask,
9384 			},
9385 			{
9386 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9387 				.spec = &action_vxlan_encap_data->item_udp,
9388 				.mask = &rte_flow_item_udp_mask,
9389 			},
9390 			{
9391 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9392 				.spec = &action_vxlan_encap_data->item_vxlan,
9393 				.mask = &rte_flow_item_vxlan_mask,
9394 			},
9395 			{
9396 				.type = RTE_FLOW_ITEM_TYPE_END,
9397 			},
9398 		},
9399 		.item_eth.hdr.ether_type = 0,
9400 		.item_vlan = {
9401 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9402 			.hdr.eth_proto = 0,
9403 		},
9404 		.item_ipv4.hdr = {
9405 			.src_addr = vxlan_encap_conf.ipv4_src,
9406 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9407 		},
9408 		.item_udp.hdr = {
9409 			.src_port = vxlan_encap_conf.udp_src,
9410 			.dst_port = vxlan_encap_conf.udp_dst,
9411 		},
9412 		.item_vxlan.hdr.flags = 0,
9413 	};
9414 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9415 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9416 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9417 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9418 	if (!vxlan_encap_conf.select_ipv4) {
9419 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9420 		       &vxlan_encap_conf.ipv6_src,
9421 		       sizeof(vxlan_encap_conf.ipv6_src));
9422 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9423 		       &vxlan_encap_conf.ipv6_dst,
9424 		       sizeof(vxlan_encap_conf.ipv6_dst));
9425 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9426 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9427 			.spec = &action_vxlan_encap_data->item_ipv6,
9428 			.mask = &rte_flow_item_ipv6_mask,
9429 		};
9430 	}
9431 	if (!vxlan_encap_conf.select_vlan)
9432 		action_vxlan_encap_data->items[1].type =
9433 			RTE_FLOW_ITEM_TYPE_VOID;
9434 	if (vxlan_encap_conf.select_tos_ttl) {
9435 		if (vxlan_encap_conf.select_ipv4) {
9436 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9437 
9438 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9439 			       sizeof(ipv4_mask_tos));
9440 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9441 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9442 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9443 					vxlan_encap_conf.ip_tos;
9444 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9445 					vxlan_encap_conf.ip_ttl;
9446 			action_vxlan_encap_data->items[2].mask =
9447 							&ipv4_mask_tos;
9448 		} else {
9449 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9450 
9451 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9452 			       sizeof(ipv6_mask_tos));
9453 			ipv6_mask_tos.hdr.vtc_flow |=
9454 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9455 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9456 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9457 				rte_cpu_to_be_32
9458 					((uint32_t)vxlan_encap_conf.ip_tos <<
9459 					 RTE_IPV6_HDR_TC_SHIFT);
9460 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9461 					vxlan_encap_conf.ip_ttl;
9462 			action_vxlan_encap_data->items[2].mask =
9463 							&ipv6_mask_tos;
9464 		}
9465 	}
9466 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9467 	       RTE_DIM(vxlan_encap_conf.vni));
9468 	return 0;
9469 }
9470 
9471 /** Parse VXLAN encap action. */
9472 static int
9473 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9474 			    const char *str, unsigned int len,
9475 			    void *buf, unsigned int size)
9476 {
9477 	struct buffer *out = buf;
9478 	struct rte_flow_action *action;
9479 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9480 	int ret;
9481 
9482 	ret = parse_vc(ctx, token, str, len, buf, size);
9483 	if (ret < 0)
9484 		return ret;
9485 	/* Nothing else to do if there is no buffer. */
9486 	if (!out)
9487 		return ret;
9488 	if (!out->args.vc.actions_n)
9489 		return -1;
9490 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9491 	/* Point to selected object. */
9492 	ctx->object = out->args.vc.data;
9493 	ctx->objmask = NULL;
9494 	action_vxlan_encap_data = ctx->object;
9495 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9496 	action->conf = &action_vxlan_encap_data->conf;
9497 	return ret;
9498 }
9499 
9500 /** Setup NVGRE encap configuration. */
9501 static int
9502 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9503 {
9504 	/* Set up default configuration. */
9505 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9506 		.conf = (struct rte_flow_action_nvgre_encap){
9507 			.definition = action_nvgre_encap_data->items,
9508 		},
9509 		.items = {
9510 			{
9511 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9512 				.spec = &action_nvgre_encap_data->item_eth,
9513 				.mask = &rte_flow_item_eth_mask,
9514 			},
9515 			{
9516 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9517 				.spec = &action_nvgre_encap_data->item_vlan,
9518 				.mask = &rte_flow_item_vlan_mask,
9519 			},
9520 			{
9521 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9522 				.spec = &action_nvgre_encap_data->item_ipv4,
9523 				.mask = &rte_flow_item_ipv4_mask,
9524 			},
9525 			{
9526 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9527 				.spec = &action_nvgre_encap_data->item_nvgre,
9528 				.mask = &rte_flow_item_nvgre_mask,
9529 			},
9530 			{
9531 				.type = RTE_FLOW_ITEM_TYPE_END,
9532 			},
9533 		},
9534 		.item_eth.hdr.ether_type = 0,
9535 		.item_vlan = {
9536 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9537 			.hdr.eth_proto = 0,
9538 		},
9539 		.item_ipv4.hdr = {
9540 		       .src_addr = nvgre_encap_conf.ipv4_src,
9541 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9542 		},
9543 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9544 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9545 		.item_nvgre.flow_id = 0,
9546 	};
9547 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9548 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9549 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9550 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9551 	if (!nvgre_encap_conf.select_ipv4) {
9552 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9553 		       &nvgre_encap_conf.ipv6_src,
9554 		       sizeof(nvgre_encap_conf.ipv6_src));
9555 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9556 		       &nvgre_encap_conf.ipv6_dst,
9557 		       sizeof(nvgre_encap_conf.ipv6_dst));
9558 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9559 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9560 			.spec = &action_nvgre_encap_data->item_ipv6,
9561 			.mask = &rte_flow_item_ipv6_mask,
9562 		};
9563 	}
9564 	if (!nvgre_encap_conf.select_vlan)
9565 		action_nvgre_encap_data->items[1].type =
9566 			RTE_FLOW_ITEM_TYPE_VOID;
9567 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9568 	       RTE_DIM(nvgre_encap_conf.tni));
9569 	return 0;
9570 }
9571 
9572 /** Parse NVGRE encap action. */
9573 static int
9574 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9575 			    const char *str, unsigned int len,
9576 			    void *buf, unsigned int size)
9577 {
9578 	struct buffer *out = buf;
9579 	struct rte_flow_action *action;
9580 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9581 	int ret;
9582 
9583 	ret = parse_vc(ctx, token, str, len, buf, size);
9584 	if (ret < 0)
9585 		return ret;
9586 	/* Nothing else to do if there is no buffer. */
9587 	if (!out)
9588 		return ret;
9589 	if (!out->args.vc.actions_n)
9590 		return -1;
9591 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9592 	/* Point to selected object. */
9593 	ctx->object = out->args.vc.data;
9594 	ctx->objmask = NULL;
9595 	action_nvgre_encap_data = ctx->object;
9596 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9597 	action->conf = &action_nvgre_encap_data->conf;
9598 	return ret;
9599 }
9600 
9601 /** Parse l2 encap action. */
9602 static int
9603 parse_vc_action_l2_encap(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_encap_data *action_encap_data;
9610 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9611 	struct rte_flow_item_vlan vlan = {
9612 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9613 		.hdr.eth_proto = 0,
9614 	};
9615 	uint8_t *header;
9616 	int ret;
9617 
9618 	ret = parse_vc(ctx, token, str, len, buf, size);
9619 	if (ret < 0)
9620 		return ret;
9621 	/* Nothing else to do if there is no buffer. */
9622 	if (!out)
9623 		return ret;
9624 	if (!out->args.vc.actions_n)
9625 		return -1;
9626 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9627 	/* Point to selected object. */
9628 	ctx->object = out->args.vc.data;
9629 	ctx->objmask = NULL;
9630 	/* Copy the headers to the buffer. */
9631 	action_encap_data = ctx->object;
9632 	*action_encap_data = (struct action_raw_encap_data) {
9633 		.conf = (struct rte_flow_action_raw_encap){
9634 			.data = action_encap_data->data,
9635 		},
9636 		.data = {},
9637 	};
9638 	header = action_encap_data->data;
9639 	if (l2_encap_conf.select_vlan)
9640 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9641 	else if (l2_encap_conf.select_ipv4)
9642 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9643 	else
9644 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9645 	memcpy(eth.hdr.dst_addr.addr_bytes,
9646 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9647 	memcpy(eth.hdr.src_addr.addr_bytes,
9648 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9649 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9650 	header += sizeof(struct rte_ether_hdr);
9651 	if (l2_encap_conf.select_vlan) {
9652 		if (l2_encap_conf.select_ipv4)
9653 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9654 		else
9655 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9656 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9657 		header += sizeof(struct rte_vlan_hdr);
9658 	}
9659 	action_encap_data->conf.size = header -
9660 		action_encap_data->data;
9661 	action->conf = &action_encap_data->conf;
9662 	return ret;
9663 }
9664 
9665 /** Parse l2 decap action. */
9666 static int
9667 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9668 			 const char *str, unsigned int len,
9669 			 void *buf, unsigned int size)
9670 {
9671 	struct buffer *out = buf;
9672 	struct rte_flow_action *action;
9673 	struct action_raw_decap_data *action_decap_data;
9674 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9675 	struct rte_flow_item_vlan vlan = {
9676 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9677 		.hdr.eth_proto = 0,
9678 	};
9679 	uint8_t *header;
9680 	int ret;
9681 
9682 	ret = parse_vc(ctx, token, str, len, buf, size);
9683 	if (ret < 0)
9684 		return ret;
9685 	/* Nothing else to do if there is no buffer. */
9686 	if (!out)
9687 		return ret;
9688 	if (!out->args.vc.actions_n)
9689 		return -1;
9690 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9691 	/* Point to selected object. */
9692 	ctx->object = out->args.vc.data;
9693 	ctx->objmask = NULL;
9694 	/* Copy the headers to the buffer. */
9695 	action_decap_data = ctx->object;
9696 	*action_decap_data = (struct action_raw_decap_data) {
9697 		.conf = (struct rte_flow_action_raw_decap){
9698 			.data = action_decap_data->data,
9699 		},
9700 		.data = {},
9701 	};
9702 	header = action_decap_data->data;
9703 	if (l2_decap_conf.select_vlan)
9704 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9705 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9706 	header += sizeof(struct rte_ether_hdr);
9707 	if (l2_decap_conf.select_vlan) {
9708 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9709 		header += sizeof(struct rte_vlan_hdr);
9710 	}
9711 	action_decap_data->conf.size = header -
9712 		action_decap_data->data;
9713 	action->conf = &action_decap_data->conf;
9714 	return ret;
9715 }
9716 
9717 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9718 
9719 /** Parse MPLSOGRE encap action. */
9720 static int
9721 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9722 			       const char *str, unsigned int len,
9723 			       void *buf, unsigned int size)
9724 {
9725 	struct buffer *out = buf;
9726 	struct rte_flow_action *action;
9727 	struct action_raw_encap_data *action_encap_data;
9728 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9729 	struct rte_flow_item_vlan vlan = {
9730 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9731 		.hdr.eth_proto = 0,
9732 	};
9733 	struct rte_flow_item_ipv4 ipv4 = {
9734 		.hdr =  {
9735 			.src_addr = mplsogre_encap_conf.ipv4_src,
9736 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9737 			.next_proto_id = IPPROTO_GRE,
9738 			.version_ihl = RTE_IPV4_VHL_DEF,
9739 			.time_to_live = IPDEFTTL,
9740 		},
9741 	};
9742 	struct rte_flow_item_ipv6 ipv6 = {
9743 		.hdr =  {
9744 			.proto = IPPROTO_GRE,
9745 			.hop_limits = IPDEFTTL,
9746 		},
9747 	};
9748 	struct rte_flow_item_gre gre = {
9749 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9750 	};
9751 	struct rte_flow_item_mpls mpls = {
9752 		.ttl = 0,
9753 	};
9754 	uint8_t *header;
9755 	int ret;
9756 
9757 	ret = parse_vc(ctx, token, str, len, buf, size);
9758 	if (ret < 0)
9759 		return ret;
9760 	/* Nothing else to do if there is no buffer. */
9761 	if (!out)
9762 		return ret;
9763 	if (!out->args.vc.actions_n)
9764 		return -1;
9765 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9766 	/* Point to selected object. */
9767 	ctx->object = out->args.vc.data;
9768 	ctx->objmask = NULL;
9769 	/* Copy the headers to the buffer. */
9770 	action_encap_data = ctx->object;
9771 	*action_encap_data = (struct action_raw_encap_data) {
9772 		.conf = (struct rte_flow_action_raw_encap){
9773 			.data = action_encap_data->data,
9774 		},
9775 		.data = {},
9776 		.preserve = {},
9777 	};
9778 	header = action_encap_data->data;
9779 	if (mplsogre_encap_conf.select_vlan)
9780 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9781 	else if (mplsogre_encap_conf.select_ipv4)
9782 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9783 	else
9784 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9785 	memcpy(eth.hdr.dst_addr.addr_bytes,
9786 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9787 	memcpy(eth.hdr.src_addr.addr_bytes,
9788 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9789 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9790 	header += sizeof(struct rte_ether_hdr);
9791 	if (mplsogre_encap_conf.select_vlan) {
9792 		if (mplsogre_encap_conf.select_ipv4)
9793 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9794 		else
9795 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9796 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9797 		header += sizeof(struct rte_vlan_hdr);
9798 	}
9799 	if (mplsogre_encap_conf.select_ipv4) {
9800 		memcpy(header, &ipv4, sizeof(ipv4));
9801 		header += sizeof(ipv4);
9802 	} else {
9803 		memcpy(&ipv6.hdr.src_addr,
9804 		       &mplsogre_encap_conf.ipv6_src,
9805 		       sizeof(mplsogre_encap_conf.ipv6_src));
9806 		memcpy(&ipv6.hdr.dst_addr,
9807 		       &mplsogre_encap_conf.ipv6_dst,
9808 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9809 		memcpy(header, &ipv6, sizeof(ipv6));
9810 		header += sizeof(ipv6);
9811 	}
9812 	memcpy(header, &gre, sizeof(gre));
9813 	header += sizeof(gre);
9814 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9815 	       RTE_DIM(mplsogre_encap_conf.label));
9816 	mpls.label_tc_s[2] |= 0x1;
9817 	memcpy(header, &mpls, sizeof(mpls));
9818 	header += sizeof(mpls);
9819 	action_encap_data->conf.size = header -
9820 		action_encap_data->data;
9821 	action->conf = &action_encap_data->conf;
9822 	return ret;
9823 }
9824 
9825 /** Parse MPLSOGRE decap action. */
9826 static int
9827 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9828 			       const char *str, unsigned int len,
9829 			       void *buf, unsigned int size)
9830 {
9831 	struct buffer *out = buf;
9832 	struct rte_flow_action *action;
9833 	struct action_raw_decap_data *action_decap_data;
9834 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9835 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9836 	struct rte_flow_item_ipv4 ipv4 = {
9837 		.hdr =  {
9838 			.next_proto_id = IPPROTO_GRE,
9839 		},
9840 	};
9841 	struct rte_flow_item_ipv6 ipv6 = {
9842 		.hdr =  {
9843 			.proto = IPPROTO_GRE,
9844 		},
9845 	};
9846 	struct rte_flow_item_gre gre = {
9847 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9848 	};
9849 	struct rte_flow_item_mpls mpls;
9850 	uint8_t *header;
9851 	int ret;
9852 
9853 	ret = parse_vc(ctx, token, str, len, buf, size);
9854 	if (ret < 0)
9855 		return ret;
9856 	/* Nothing else to do if there is no buffer. */
9857 	if (!out)
9858 		return ret;
9859 	if (!out->args.vc.actions_n)
9860 		return -1;
9861 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9862 	/* Point to selected object. */
9863 	ctx->object = out->args.vc.data;
9864 	ctx->objmask = NULL;
9865 	/* Copy the headers to the buffer. */
9866 	action_decap_data = ctx->object;
9867 	*action_decap_data = (struct action_raw_decap_data) {
9868 		.conf = (struct rte_flow_action_raw_decap){
9869 			.data = action_decap_data->data,
9870 		},
9871 		.data = {},
9872 	};
9873 	header = action_decap_data->data;
9874 	if (mplsogre_decap_conf.select_vlan)
9875 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9876 	else if (mplsogre_encap_conf.select_ipv4)
9877 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9878 	else
9879 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9880 	memcpy(eth.hdr.dst_addr.addr_bytes,
9881 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9882 	memcpy(eth.hdr.src_addr.addr_bytes,
9883 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9884 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9885 	header += sizeof(struct rte_ether_hdr);
9886 	if (mplsogre_encap_conf.select_vlan) {
9887 		if (mplsogre_encap_conf.select_ipv4)
9888 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9889 		else
9890 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9891 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9892 		header += sizeof(struct rte_vlan_hdr);
9893 	}
9894 	if (mplsogre_encap_conf.select_ipv4) {
9895 		memcpy(header, &ipv4, sizeof(ipv4));
9896 		header += sizeof(ipv4);
9897 	} else {
9898 		memcpy(header, &ipv6, sizeof(ipv6));
9899 		header += sizeof(ipv6);
9900 	}
9901 	memcpy(header, &gre, sizeof(gre));
9902 	header += sizeof(gre);
9903 	memset(&mpls, 0, sizeof(mpls));
9904 	memcpy(header, &mpls, sizeof(mpls));
9905 	header += sizeof(mpls);
9906 	action_decap_data->conf.size = header -
9907 		action_decap_data->data;
9908 	action->conf = &action_decap_data->conf;
9909 	return ret;
9910 }
9911 
9912 /** Parse MPLSOUDP encap action. */
9913 static int
9914 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9915 			       const char *str, unsigned int len,
9916 			       void *buf, unsigned int size)
9917 {
9918 	struct buffer *out = buf;
9919 	struct rte_flow_action *action;
9920 	struct action_raw_encap_data *action_encap_data;
9921 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9922 	struct rte_flow_item_vlan vlan = {
9923 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9924 		.hdr.eth_proto = 0,
9925 	};
9926 	struct rte_flow_item_ipv4 ipv4 = {
9927 		.hdr =  {
9928 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9929 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9930 			.next_proto_id = IPPROTO_UDP,
9931 			.version_ihl = RTE_IPV4_VHL_DEF,
9932 			.time_to_live = IPDEFTTL,
9933 		},
9934 	};
9935 	struct rte_flow_item_ipv6 ipv6 = {
9936 		.hdr =  {
9937 			.proto = IPPROTO_UDP,
9938 			.hop_limits = IPDEFTTL,
9939 		},
9940 	};
9941 	struct rte_flow_item_udp udp = {
9942 		.hdr = {
9943 			.src_port = mplsoudp_encap_conf.udp_src,
9944 			.dst_port = mplsoudp_encap_conf.udp_dst,
9945 		},
9946 	};
9947 	struct rte_flow_item_mpls mpls;
9948 	uint8_t *header;
9949 	int ret;
9950 
9951 	ret = parse_vc(ctx, token, str, len, buf, size);
9952 	if (ret < 0)
9953 		return ret;
9954 	/* Nothing else to do if there is no buffer. */
9955 	if (!out)
9956 		return ret;
9957 	if (!out->args.vc.actions_n)
9958 		return -1;
9959 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9960 	/* Point to selected object. */
9961 	ctx->object = out->args.vc.data;
9962 	ctx->objmask = NULL;
9963 	/* Copy the headers to the buffer. */
9964 	action_encap_data = ctx->object;
9965 	*action_encap_data = (struct action_raw_encap_data) {
9966 		.conf = (struct rte_flow_action_raw_encap){
9967 			.data = action_encap_data->data,
9968 		},
9969 		.data = {},
9970 		.preserve = {},
9971 	};
9972 	header = action_encap_data->data;
9973 	if (mplsoudp_encap_conf.select_vlan)
9974 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9975 	else if (mplsoudp_encap_conf.select_ipv4)
9976 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9977 	else
9978 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9979 	memcpy(eth.hdr.dst_addr.addr_bytes,
9980 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9981 	memcpy(eth.hdr.src_addr.addr_bytes,
9982 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9983 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9984 	header += sizeof(struct rte_ether_hdr);
9985 	if (mplsoudp_encap_conf.select_vlan) {
9986 		if (mplsoudp_encap_conf.select_ipv4)
9987 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9988 		else
9989 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9990 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9991 		header += sizeof(struct rte_vlan_hdr);
9992 	}
9993 	if (mplsoudp_encap_conf.select_ipv4) {
9994 		memcpy(header, &ipv4, sizeof(ipv4));
9995 		header += sizeof(ipv4);
9996 	} else {
9997 		memcpy(&ipv6.hdr.src_addr,
9998 		       &mplsoudp_encap_conf.ipv6_src,
9999 		       sizeof(mplsoudp_encap_conf.ipv6_src));
10000 		memcpy(&ipv6.hdr.dst_addr,
10001 		       &mplsoudp_encap_conf.ipv6_dst,
10002 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
10003 		memcpy(header, &ipv6, sizeof(ipv6));
10004 		header += sizeof(ipv6);
10005 	}
10006 	memcpy(header, &udp, sizeof(udp));
10007 	header += sizeof(udp);
10008 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
10009 	       RTE_DIM(mplsoudp_encap_conf.label));
10010 	mpls.label_tc_s[2] |= 0x1;
10011 	memcpy(header, &mpls, sizeof(mpls));
10012 	header += sizeof(mpls);
10013 	action_encap_data->conf.size = header -
10014 		action_encap_data->data;
10015 	action->conf = &action_encap_data->conf;
10016 	return ret;
10017 }
10018 
10019 /** Parse MPLSOUDP decap action. */
10020 static int
10021 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
10022 			       const char *str, unsigned int len,
10023 			       void *buf, unsigned int size)
10024 {
10025 	struct buffer *out = buf;
10026 	struct rte_flow_action *action;
10027 	struct action_raw_decap_data *action_decap_data;
10028 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
10029 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
10030 	struct rte_flow_item_ipv4 ipv4 = {
10031 		.hdr =  {
10032 			.next_proto_id = IPPROTO_UDP,
10033 		},
10034 	};
10035 	struct rte_flow_item_ipv6 ipv6 = {
10036 		.hdr =  {
10037 			.proto = IPPROTO_UDP,
10038 		},
10039 	};
10040 	struct rte_flow_item_udp udp = {
10041 		.hdr = {
10042 			.dst_port = rte_cpu_to_be_16(6635),
10043 		},
10044 	};
10045 	struct rte_flow_item_mpls mpls;
10046 	uint8_t *header;
10047 	int ret;
10048 
10049 	ret = parse_vc(ctx, token, str, len, buf, size);
10050 	if (ret < 0)
10051 		return ret;
10052 	/* Nothing else to do if there is no buffer. */
10053 	if (!out)
10054 		return ret;
10055 	if (!out->args.vc.actions_n)
10056 		return -1;
10057 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10058 	/* Point to selected object. */
10059 	ctx->object = out->args.vc.data;
10060 	ctx->objmask = NULL;
10061 	/* Copy the headers to the buffer. */
10062 	action_decap_data = ctx->object;
10063 	*action_decap_data = (struct action_raw_decap_data) {
10064 		.conf = (struct rte_flow_action_raw_decap){
10065 			.data = action_decap_data->data,
10066 		},
10067 		.data = {},
10068 	};
10069 	header = action_decap_data->data;
10070 	if (mplsoudp_decap_conf.select_vlan)
10071 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
10072 	else if (mplsoudp_encap_conf.select_ipv4)
10073 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10074 	else
10075 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10076 	memcpy(eth.hdr.dst_addr.addr_bytes,
10077 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
10078 	memcpy(eth.hdr.src_addr.addr_bytes,
10079 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
10080 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
10081 	header += sizeof(struct rte_ether_hdr);
10082 	if (mplsoudp_encap_conf.select_vlan) {
10083 		if (mplsoudp_encap_conf.select_ipv4)
10084 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10085 		else
10086 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10087 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
10088 		header += sizeof(struct rte_vlan_hdr);
10089 	}
10090 	if (mplsoudp_encap_conf.select_ipv4) {
10091 		memcpy(header, &ipv4, sizeof(ipv4));
10092 		header += sizeof(ipv4);
10093 	} else {
10094 		memcpy(header, &ipv6, sizeof(ipv6));
10095 		header += sizeof(ipv6);
10096 	}
10097 	memcpy(header, &udp, sizeof(udp));
10098 	header += sizeof(udp);
10099 	memset(&mpls, 0, sizeof(mpls));
10100 	memcpy(header, &mpls, sizeof(mpls));
10101 	header += sizeof(mpls);
10102 	action_decap_data->conf.size = header -
10103 		action_decap_data->data;
10104 	action->conf = &action_decap_data->conf;
10105 	return ret;
10106 }
10107 
10108 static int
10109 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
10110 				const char *str, unsigned int len, void *buf,
10111 				unsigned int size)
10112 {
10113 	struct action_raw_decap_data *action_raw_decap_data;
10114 	struct rte_flow_action *action;
10115 	const struct arg *arg;
10116 	struct buffer *out = buf;
10117 	int ret;
10118 	uint16_t idx;
10119 
10120 	RTE_SET_USED(token);
10121 	RTE_SET_USED(buf);
10122 	RTE_SET_USED(size);
10123 	arg = ARGS_ENTRY_ARB_BOUNDED
10124 		(offsetof(struct action_raw_decap_data, idx),
10125 		 sizeof(((struct action_raw_decap_data *)0)->idx),
10126 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10127 	if (push_args(ctx, arg))
10128 		return -1;
10129 	ret = parse_int(ctx, token, str, len, NULL, 0);
10130 	if (ret < 0) {
10131 		pop_args(ctx);
10132 		return -1;
10133 	}
10134 	if (!ctx->object)
10135 		return len;
10136 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10137 	action_raw_decap_data = ctx->object;
10138 	idx = action_raw_decap_data->idx;
10139 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
10140 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
10141 	action->conf = &action_raw_decap_data->conf;
10142 	return len;
10143 }
10144 
10145 
10146 static int
10147 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
10148 				const char *str, unsigned int len, void *buf,
10149 				unsigned int size)
10150 {
10151 	struct action_raw_encap_data *action_raw_encap_data;
10152 	struct rte_flow_action *action;
10153 	const struct arg *arg;
10154 	struct buffer *out = buf;
10155 	int ret;
10156 	uint16_t idx;
10157 
10158 	RTE_SET_USED(token);
10159 	RTE_SET_USED(buf);
10160 	RTE_SET_USED(size);
10161 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
10162 		return -1;
10163 	arg = ARGS_ENTRY_ARB_BOUNDED
10164 		(offsetof(struct action_raw_encap_data, idx),
10165 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10166 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10167 	if (push_args(ctx, arg))
10168 		return -1;
10169 	ret = parse_int(ctx, token, str, len, NULL, 0);
10170 	if (ret < 0) {
10171 		pop_args(ctx);
10172 		return -1;
10173 	}
10174 	if (!ctx->object)
10175 		return len;
10176 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10177 	action_raw_encap_data = ctx->object;
10178 	idx = action_raw_encap_data->idx;
10179 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10180 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10181 	action_raw_encap_data->conf.preserve = NULL;
10182 	action->conf = &action_raw_encap_data->conf;
10183 	return len;
10184 }
10185 
10186 static int
10187 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10188 			  const char *str, unsigned int len, void *buf,
10189 			  unsigned int size)
10190 {
10191 	struct buffer *out = buf;
10192 	int ret;
10193 
10194 	ret = parse_vc(ctx, token, str, len, buf, size);
10195 	if (ret < 0)
10196 		return ret;
10197 	/* Nothing else to do if there is no buffer. */
10198 	if (!out)
10199 		return ret;
10200 	if (!out->args.vc.actions_n)
10201 		return -1;
10202 	/* Point to selected object. */
10203 	ctx->object = out->args.vc.data;
10204 	ctx->objmask = NULL;
10205 	return ret;
10206 }
10207 
10208 static int
10209 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10210 			  const char *str, unsigned int len, void *buf,
10211 			  unsigned int size)
10212 {
10213 	struct buffer *out = buf;
10214 	struct rte_flow_action *action;
10215 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10216 	int ret;
10217 
10218 	ret = parse_vc(ctx, token, str, len, buf, size);
10219 	if (ret < 0)
10220 		return ret;
10221 	/* Nothing else to do if there is no buffer. */
10222 	if (!out)
10223 		return ret;
10224 	if (!out->args.vc.actions_n)
10225 		return -1;
10226 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10227 	/* Point to selected object. */
10228 	ctx->object = out->args.vc.data;
10229 	ctx->objmask = NULL;
10230 	/* Copy the headers to the buffer. */
10231 	action_raw_decap_data = ctx->object;
10232 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10233 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10234 	action->conf = &action_raw_decap_data->conf;
10235 	return ret;
10236 }
10237 
10238 static int
10239 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10240 				const char *str, unsigned int len, void *buf,
10241 				unsigned int size)
10242 {
10243 	struct buffer *out = buf;
10244 	struct rte_flow_action *action;
10245 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10246 	int ret;
10247 
10248 	ret = parse_vc(ctx, token, str, len, buf, size);
10249 	if (ret < 0)
10250 		return ret;
10251 	/* Nothing else to do if there is no buffer. */
10252 	if (!out)
10253 		return ret;
10254 	if (!out->args.vc.actions_n)
10255 		return -1;
10256 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10257 	/* Point to selected object. */
10258 	ctx->object = out->args.vc.data;
10259 	ctx->objmask = NULL;
10260 	/* Copy the headers to the buffer. */
10261 	ipv6_ext_remove_data = ctx->object;
10262 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10263 	action->conf = &ipv6_ext_remove_data->conf;
10264 	return ret;
10265 }
10266 
10267 static int
10268 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10269 				      const char *str, unsigned int len, void *buf,
10270 				      unsigned int size)
10271 {
10272 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10273 	struct rte_flow_action *action;
10274 	const struct arg *arg;
10275 	struct buffer *out = buf;
10276 	int ret;
10277 	uint16_t idx;
10278 
10279 	RTE_SET_USED(token);
10280 	RTE_SET_USED(buf);
10281 	RTE_SET_USED(size);
10282 	arg = ARGS_ENTRY_ARB_BOUNDED
10283 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10284 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10285 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10286 	if (push_args(ctx, arg))
10287 		return -1;
10288 	ret = parse_int(ctx, token, str, len, NULL, 0);
10289 	if (ret < 0) {
10290 		pop_args(ctx);
10291 		return -1;
10292 	}
10293 	if (!ctx->object)
10294 		return len;
10295 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10296 	action_ipv6_ext_remove_data = ctx->object;
10297 	idx = action_ipv6_ext_remove_data->idx;
10298 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10299 	action->conf = &action_ipv6_ext_remove_data->conf;
10300 	return len;
10301 }
10302 
10303 static int
10304 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10305 			      const char *str, unsigned int len, void *buf,
10306 			      unsigned int size)
10307 {
10308 	struct buffer *out = buf;
10309 	struct rte_flow_action *action;
10310 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10311 	int ret;
10312 
10313 	ret = parse_vc(ctx, token, str, len, buf, size);
10314 	if (ret < 0)
10315 		return ret;
10316 	/* Nothing else to do if there is no buffer. */
10317 	if (!out)
10318 		return ret;
10319 	if (!out->args.vc.actions_n)
10320 		return -1;
10321 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10322 	/* Point to selected object. */
10323 	ctx->object = out->args.vc.data;
10324 	ctx->objmask = NULL;
10325 	/* Copy the headers to the buffer. */
10326 	ipv6_ext_push_data = ctx->object;
10327 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10328 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10329 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10330 	action->conf = &ipv6_ext_push_data->conf;
10331 	return ret;
10332 }
10333 
10334 static int
10335 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10336 				    const char *str, unsigned int len, void *buf,
10337 				    unsigned int size)
10338 {
10339 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10340 	struct rte_flow_action *action;
10341 	const struct arg *arg;
10342 	struct buffer *out = buf;
10343 	int ret;
10344 	uint16_t idx;
10345 
10346 	RTE_SET_USED(token);
10347 	RTE_SET_USED(buf);
10348 	RTE_SET_USED(size);
10349 	arg = ARGS_ENTRY_ARB_BOUNDED
10350 		(offsetof(struct action_ipv6_ext_push_data, idx),
10351 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10352 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10353 	if (push_args(ctx, arg))
10354 		return -1;
10355 	ret = parse_int(ctx, token, str, len, NULL, 0);
10356 	if (ret < 0) {
10357 		pop_args(ctx);
10358 		return -1;
10359 	}
10360 	if (!ctx->object)
10361 		return len;
10362 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10363 	action_ipv6_ext_push_data = ctx->object;
10364 	idx = action_ipv6_ext_push_data->idx;
10365 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10366 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10367 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10368 	action->conf = &action_ipv6_ext_push_data->conf;
10369 	return len;
10370 }
10371 
10372 static int
10373 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10374 			 const char *str, unsigned int len, void *buf,
10375 			 unsigned int size)
10376 {
10377 	int ret;
10378 
10379 	ret = parse_vc(ctx, token, str, len, buf, size);
10380 	if (ret < 0)
10381 		return ret;
10382 	ret = rte_flow_dynf_metadata_register();
10383 	if (ret < 0)
10384 		return -1;
10385 	return len;
10386 }
10387 
10388 static int
10389 parse_vc_action_sample(struct context *ctx, const struct token *token,
10390 			 const char *str, unsigned int len, void *buf,
10391 			 unsigned int size)
10392 {
10393 	struct buffer *out = buf;
10394 	struct rte_flow_action *action;
10395 	struct action_sample_data *action_sample_data = NULL;
10396 	static struct rte_flow_action end_action = {
10397 		RTE_FLOW_ACTION_TYPE_END, 0
10398 	};
10399 	int ret;
10400 
10401 	ret = parse_vc(ctx, token, str, len, buf, size);
10402 	if (ret < 0)
10403 		return ret;
10404 	/* Nothing else to do if there is no buffer. */
10405 	if (!out)
10406 		return ret;
10407 	if (!out->args.vc.actions_n)
10408 		return -1;
10409 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10410 	/* Point to selected object. */
10411 	ctx->object = out->args.vc.data;
10412 	ctx->objmask = NULL;
10413 	/* Copy the headers to the buffer. */
10414 	action_sample_data = ctx->object;
10415 	action_sample_data->conf.actions = &end_action;
10416 	action->conf = &action_sample_data->conf;
10417 	return ret;
10418 }
10419 
10420 static int
10421 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10422 				const char *str, unsigned int len, void *buf,
10423 				unsigned int size)
10424 {
10425 	struct action_sample_data *action_sample_data;
10426 	struct rte_flow_action *action;
10427 	const struct arg *arg;
10428 	struct buffer *out = buf;
10429 	int ret;
10430 	uint16_t idx;
10431 
10432 	RTE_SET_USED(token);
10433 	RTE_SET_USED(buf);
10434 	RTE_SET_USED(size);
10435 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10436 		return -1;
10437 	arg = ARGS_ENTRY_ARB_BOUNDED
10438 		(offsetof(struct action_sample_data, idx),
10439 		 sizeof(((struct action_sample_data *)0)->idx),
10440 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10441 	if (push_args(ctx, arg))
10442 		return -1;
10443 	ret = parse_int(ctx, token, str, len, NULL, 0);
10444 	if (ret < 0) {
10445 		pop_args(ctx);
10446 		return -1;
10447 	}
10448 	if (!ctx->object)
10449 		return len;
10450 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10451 	action_sample_data = ctx->object;
10452 	idx = action_sample_data->idx;
10453 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10454 	action->conf = &action_sample_data->conf;
10455 	return len;
10456 }
10457 
10458 /** Parse operation for modify_field command. */
10459 static int
10460 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10461 			 const char *str, unsigned int len, void *buf,
10462 			 unsigned int size)
10463 {
10464 	struct rte_flow_action_modify_field *action_modify_field;
10465 	unsigned int i;
10466 
10467 	(void)token;
10468 	(void)buf;
10469 	(void)size;
10470 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10471 		return -1;
10472 	for (i = 0; modify_field_ops[i]; ++i)
10473 		if (!strcmp_partial(modify_field_ops[i], str, len))
10474 			break;
10475 	if (!modify_field_ops[i])
10476 		return -1;
10477 	if (!ctx->object)
10478 		return len;
10479 	action_modify_field = ctx->object;
10480 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10481 	return len;
10482 }
10483 
10484 /** Parse id for modify_field command. */
10485 static int
10486 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10487 			 const char *str, unsigned int len, void *buf,
10488 			 unsigned int size)
10489 {
10490 	struct rte_flow_action_modify_field *action_modify_field;
10491 	unsigned int i;
10492 
10493 	(void)token;
10494 	(void)buf;
10495 	(void)size;
10496 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10497 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10498 		return -1;
10499 	for (i = 0; flow_field_ids[i]; ++i)
10500 		if (!strcmp_partial(flow_field_ids[i], str, len))
10501 			break;
10502 	if (!flow_field_ids[i])
10503 		return -1;
10504 	if (!ctx->object)
10505 		return len;
10506 	action_modify_field = ctx->object;
10507 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10508 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10509 	else
10510 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10511 	return len;
10512 }
10513 
10514 /** Parse level for modify_field command. */
10515 static int
10516 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10517 			 const char *str, unsigned int len, void *buf,
10518 			 unsigned int size)
10519 {
10520 	struct rte_flow_action_modify_field *action;
10521 	struct flex_item *fp = NULL;
10522 	uint32_t val;
10523 	struct buffer *out = buf;
10524 	char *end;
10525 
10526 	(void)token;
10527 	(void)size;
10528 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10529 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10530 		return -1;
10531 	if (!ctx->object)
10532 		return len;
10533 	action = ctx->object;
10534 	errno = 0;
10535 	val = strtoumax(str, &end, 0);
10536 	if (errno || (size_t)(end - str) != len)
10537 		return -1;
10538 	/* No need to validate action template mask value */
10539 	if (out->args.vc.masks) {
10540 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10541 			action->dst.level = val;
10542 		else
10543 			action->src.level = val;
10544 		return len;
10545 	}
10546 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10547 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10548 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10549 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10550 		if (val >= FLEX_MAX_PARSERS_NUM) {
10551 			printf("Bad flex item handle\n");
10552 			return -1;
10553 		}
10554 		fp = flex_items[ctx->port][val];
10555 		if (!fp) {
10556 			printf("Bad flex item handle\n");
10557 			return -1;
10558 		}
10559 	}
10560 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10561 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10562 			action->dst.level = val;
10563 		else
10564 			action->dst.flex_handle = fp->flex_handle;
10565 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10566 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10567 			action->src.level = val;
10568 		else
10569 			action->src.flex_handle = fp->flex_handle;
10570 	}
10571 	return len;
10572 }
10573 
10574 /** Parse the conntrack update, not a rte_flow_action. */
10575 static int
10576 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10577 			 const char *str, unsigned int len, void *buf,
10578 			 unsigned int size)
10579 {
10580 	struct buffer *out = buf;
10581 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10582 
10583 	(void)size;
10584 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10585 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10586 		return -1;
10587 	/* Token name must match. */
10588 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10589 		return -1;
10590 	/* Nothing else to do if there is no buffer. */
10591 	if (!out)
10592 		return len;
10593 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10594 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10595 		ct_modify->new_ct.is_original_dir =
10596 				conntrack_context.is_original_dir;
10597 		ct_modify->direction = 1;
10598 	} else {
10599 		uint32_t old_dir;
10600 
10601 		old_dir = ct_modify->new_ct.is_original_dir;
10602 		memcpy(&ct_modify->new_ct, &conntrack_context,
10603 		       sizeof(conntrack_context));
10604 		ct_modify->new_ct.is_original_dir = old_dir;
10605 		ct_modify->state = 1;
10606 	}
10607 	return len;
10608 }
10609 
10610 /** Parse tokens for destroy command. */
10611 static int
10612 parse_destroy(struct context *ctx, const struct token *token,
10613 	      const char *str, unsigned int len,
10614 	      void *buf, unsigned int size)
10615 {
10616 	struct buffer *out = buf;
10617 
10618 	/* Token name must match. */
10619 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10620 		return -1;
10621 	/* Nothing else to do if there is no buffer. */
10622 	if (!out)
10623 		return len;
10624 	if (!out->command) {
10625 		if (ctx->curr != DESTROY)
10626 			return -1;
10627 		if (sizeof(*out) > size)
10628 			return -1;
10629 		out->command = ctx->curr;
10630 		ctx->objdata = 0;
10631 		ctx->object = out;
10632 		ctx->objmask = NULL;
10633 		out->args.destroy.rule =
10634 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10635 					       sizeof(double));
10636 		return len;
10637 	}
10638 	if (ctx->curr == DESTROY_IS_USER_ID) {
10639 		out->args.destroy.is_user_id = true;
10640 		return len;
10641 	}
10642 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10643 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10644 		return -1;
10645 	ctx->objdata = 0;
10646 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10647 	ctx->objmask = NULL;
10648 	return len;
10649 }
10650 
10651 /** Parse tokens for flush command. */
10652 static int
10653 parse_flush(struct context *ctx, const struct token *token,
10654 	    const char *str, unsigned int len,
10655 	    void *buf, unsigned int size)
10656 {
10657 	struct buffer *out = buf;
10658 
10659 	/* Token name must match. */
10660 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10661 		return -1;
10662 	/* Nothing else to do if there is no buffer. */
10663 	if (!out)
10664 		return len;
10665 	if (!out->command) {
10666 		if (ctx->curr != FLUSH)
10667 			return -1;
10668 		if (sizeof(*out) > size)
10669 			return -1;
10670 		out->command = ctx->curr;
10671 		ctx->objdata = 0;
10672 		ctx->object = out;
10673 		ctx->objmask = NULL;
10674 	}
10675 	return len;
10676 }
10677 
10678 /** Parse tokens for dump command. */
10679 static int
10680 parse_dump(struct context *ctx, const struct token *token,
10681 	    const char *str, unsigned int len,
10682 	    void *buf, unsigned int size)
10683 {
10684 	struct buffer *out = buf;
10685 
10686 	/* Token name must match. */
10687 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10688 		return -1;
10689 	/* Nothing else to do if there is no buffer. */
10690 	if (!out)
10691 		return len;
10692 	if (!out->command) {
10693 		if (ctx->curr != DUMP)
10694 			return -1;
10695 		if (sizeof(*out) > size)
10696 			return -1;
10697 		out->command = ctx->curr;
10698 		ctx->objdata = 0;
10699 		ctx->object = out;
10700 		ctx->objmask = NULL;
10701 		return len;
10702 	}
10703 	switch (ctx->curr) {
10704 	case DUMP_ALL:
10705 	case DUMP_ONE:
10706 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10707 		out->command = ctx->curr;
10708 		ctx->objdata = 0;
10709 		ctx->object = out;
10710 		ctx->objmask = NULL;
10711 		return len;
10712 	case DUMP_IS_USER_ID:
10713 		out->args.dump.is_user_id = true;
10714 		return len;
10715 	default:
10716 		return -1;
10717 	}
10718 }
10719 
10720 /** Parse tokens for query command. */
10721 static int
10722 parse_query(struct context *ctx, const struct token *token,
10723 	    const char *str, unsigned int len,
10724 	    void *buf, unsigned int size)
10725 {
10726 	struct buffer *out = buf;
10727 
10728 	/* Token name must match. */
10729 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10730 		return -1;
10731 	/* Nothing else to do if there is no buffer. */
10732 	if (!out)
10733 		return len;
10734 	if (!out->command) {
10735 		if (ctx->curr != QUERY)
10736 			return -1;
10737 		if (sizeof(*out) > size)
10738 			return -1;
10739 		out->command = ctx->curr;
10740 		ctx->objdata = 0;
10741 		ctx->object = out;
10742 		ctx->objmask = NULL;
10743 	}
10744 	if (ctx->curr == QUERY_IS_USER_ID) {
10745 		out->args.query.is_user_id = true;
10746 		return len;
10747 	}
10748 	return len;
10749 }
10750 
10751 /** Parse action names. */
10752 static int
10753 parse_action(struct context *ctx, const struct token *token,
10754 	     const char *str, unsigned int len,
10755 	     void *buf, unsigned int size)
10756 {
10757 	struct buffer *out = buf;
10758 	const struct arg *arg = pop_args(ctx);
10759 	unsigned int i;
10760 
10761 	(void)size;
10762 	/* Argument is expected. */
10763 	if (!arg)
10764 		return -1;
10765 	/* Parse action name. */
10766 	for (i = 0; next_action[i]; ++i) {
10767 		const struct parse_action_priv *priv;
10768 
10769 		token = &token_list[next_action[i]];
10770 		if (strcmp_partial(token->name, str, len))
10771 			continue;
10772 		priv = token->priv;
10773 		if (!priv)
10774 			goto error;
10775 		if (out)
10776 			memcpy((uint8_t *)ctx->object + arg->offset,
10777 			       &priv->type,
10778 			       arg->size);
10779 		return len;
10780 	}
10781 error:
10782 	push_args(ctx, arg);
10783 	return -1;
10784 }
10785 
10786 /** Parse tokens for list command. */
10787 static int
10788 parse_list(struct context *ctx, const struct token *token,
10789 	   const char *str, unsigned int len,
10790 	   void *buf, unsigned int size)
10791 {
10792 	struct buffer *out = buf;
10793 
10794 	/* Token name must match. */
10795 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10796 		return -1;
10797 	/* Nothing else to do if there is no buffer. */
10798 	if (!out)
10799 		return len;
10800 	if (!out->command) {
10801 		if (ctx->curr != LIST)
10802 			return -1;
10803 		if (sizeof(*out) > size)
10804 			return -1;
10805 		out->command = ctx->curr;
10806 		ctx->objdata = 0;
10807 		ctx->object = out;
10808 		ctx->objmask = NULL;
10809 		out->args.list.group =
10810 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10811 					       sizeof(double));
10812 		return len;
10813 	}
10814 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10815 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10816 		return -1;
10817 	ctx->objdata = 0;
10818 	ctx->object = out->args.list.group + out->args.list.group_n++;
10819 	ctx->objmask = NULL;
10820 	return len;
10821 }
10822 
10823 /** Parse tokens for list all aged flows command. */
10824 static int
10825 parse_aged(struct context *ctx, const struct token *token,
10826 	   const char *str, unsigned int len,
10827 	   void *buf, unsigned int size)
10828 {
10829 	struct buffer *out = buf;
10830 
10831 	/* Token name must match. */
10832 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10833 		return -1;
10834 	/* Nothing else to do if there is no buffer. */
10835 	if (!out)
10836 		return len;
10837 	if (!out->command || out->command == QUEUE) {
10838 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10839 			return -1;
10840 		if (sizeof(*out) > size)
10841 			return -1;
10842 		out->command = ctx->curr;
10843 		ctx->objdata = 0;
10844 		ctx->object = out;
10845 		ctx->objmask = NULL;
10846 	}
10847 	if (ctx->curr == AGED_DESTROY)
10848 		out->args.aged.destroy = 1;
10849 	return len;
10850 }
10851 
10852 /** Parse tokens for isolate command. */
10853 static int
10854 parse_isolate(struct context *ctx, const struct token *token,
10855 	      const char *str, unsigned int len,
10856 	      void *buf, unsigned int size)
10857 {
10858 	struct buffer *out = buf;
10859 
10860 	/* Token name must match. */
10861 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10862 		return -1;
10863 	/* Nothing else to do if there is no buffer. */
10864 	if (!out)
10865 		return len;
10866 	if (!out->command) {
10867 		if (ctx->curr != ISOLATE)
10868 			return -1;
10869 		if (sizeof(*out) > size)
10870 			return -1;
10871 		out->command = ctx->curr;
10872 		ctx->objdata = 0;
10873 		ctx->object = out;
10874 		ctx->objmask = NULL;
10875 	}
10876 	return len;
10877 }
10878 
10879 /** Parse tokens for info/configure command. */
10880 static int
10881 parse_configure(struct context *ctx, const struct token *token,
10882 		const char *str, unsigned int len,
10883 		void *buf, unsigned int size)
10884 {
10885 	struct buffer *out = buf;
10886 
10887 	/* Token name must match. */
10888 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10889 		return -1;
10890 	/* Nothing else to do if there is no buffer. */
10891 	if (!out)
10892 		return len;
10893 	if (!out->command) {
10894 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10895 			return -1;
10896 		if (sizeof(*out) > size)
10897 			return -1;
10898 		out->command = ctx->curr;
10899 		ctx->objdata = 0;
10900 		ctx->object = out;
10901 		ctx->objmask = NULL;
10902 	}
10903 	return len;
10904 }
10905 
10906 /** Parse tokens for template create command. */
10907 static int
10908 parse_template(struct context *ctx, const struct token *token,
10909 	       const char *str, unsigned int len,
10910 	       void *buf, unsigned int size)
10911 {
10912 	struct buffer *out = buf;
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) {
10921 		if (ctx->curr != PATTERN_TEMPLATE &&
10922 		    ctx->curr != ACTIONS_TEMPLATE)
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.vc.data = (uint8_t *)out + size;
10931 		return len;
10932 	}
10933 	switch (ctx->curr) {
10934 	case PATTERN_TEMPLATE_CREATE:
10935 		out->args.vc.pattern =
10936 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10937 					       sizeof(double));
10938 		out->args.vc.pat_templ_id = UINT32_MAX;
10939 		out->command = ctx->curr;
10940 		ctx->objdata = 0;
10941 		ctx->object = out;
10942 		ctx->objmask = NULL;
10943 		return len;
10944 	case PATTERN_TEMPLATE_EGRESS:
10945 		out->args.vc.attr.egress = 1;
10946 		return len;
10947 	case PATTERN_TEMPLATE_INGRESS:
10948 		out->args.vc.attr.ingress = 1;
10949 		return len;
10950 	case PATTERN_TEMPLATE_TRANSFER:
10951 		out->args.vc.attr.transfer = 1;
10952 		return len;
10953 	case ACTIONS_TEMPLATE_CREATE:
10954 		out->args.vc.act_templ_id = UINT32_MAX;
10955 		out->command = ctx->curr;
10956 		ctx->objdata = 0;
10957 		ctx->object = out;
10958 		ctx->objmask = NULL;
10959 		return len;
10960 	case ACTIONS_TEMPLATE_SPEC:
10961 		out->args.vc.actions =
10962 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10963 					       sizeof(double));
10964 		ctx->object = out->args.vc.actions;
10965 		ctx->objmask = NULL;
10966 		return len;
10967 	case ACTIONS_TEMPLATE_MASK:
10968 		out->args.vc.masks =
10969 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10970 					       (out->args.vc.actions +
10971 						out->args.vc.actions_n),
10972 					       sizeof(double));
10973 		ctx->object = out->args.vc.masks;
10974 		ctx->objmask = NULL;
10975 		return len;
10976 	case ACTIONS_TEMPLATE_EGRESS:
10977 		out->args.vc.attr.egress = 1;
10978 		return len;
10979 	case ACTIONS_TEMPLATE_INGRESS:
10980 		out->args.vc.attr.ingress = 1;
10981 		return len;
10982 	case ACTIONS_TEMPLATE_TRANSFER:
10983 		out->args.vc.attr.transfer = 1;
10984 		return len;
10985 	default:
10986 		return -1;
10987 	}
10988 }
10989 
10990 /** Parse tokens for template destroy command. */
10991 static int
10992 parse_template_destroy(struct context *ctx, const struct token *token,
10993 		       const char *str, unsigned int len,
10994 		       void *buf, unsigned int size)
10995 {
10996 	struct buffer *out = buf;
10997 	uint32_t *template_id;
10998 
10999 	/* Token name must match. */
11000 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11001 		return -1;
11002 	/* Nothing else to do if there is no buffer. */
11003 	if (!out)
11004 		return len;
11005 	if (!out->command ||
11006 		out->command == PATTERN_TEMPLATE ||
11007 		out->command == ACTIONS_TEMPLATE) {
11008 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
11009 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
11010 			return -1;
11011 		if (sizeof(*out) > size)
11012 			return -1;
11013 		out->command = ctx->curr;
11014 		ctx->objdata = 0;
11015 		ctx->object = out;
11016 		ctx->objmask = NULL;
11017 		out->args.templ_destroy.template_id =
11018 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11019 					       sizeof(double));
11020 		return len;
11021 	}
11022 	template_id = out->args.templ_destroy.template_id
11023 		    + out->args.templ_destroy.template_id_n++;
11024 	if ((uint8_t *)template_id > (uint8_t *)out + size)
11025 		return -1;
11026 	ctx->objdata = 0;
11027 	ctx->object = template_id;
11028 	ctx->objmask = NULL;
11029 	return len;
11030 }
11031 
11032 /** Parse tokens for table create command. */
11033 static int
11034 parse_table(struct context *ctx, const struct token *token,
11035 	    const char *str, unsigned int len,
11036 	    void *buf, unsigned int size)
11037 {
11038 	struct buffer *out = buf;
11039 	uint32_t *template_id;
11040 
11041 	/* Token name must match. */
11042 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11043 		return -1;
11044 	/* Nothing else to do if there is no buffer. */
11045 	if (!out)
11046 		return len;
11047 	if (!out->command) {
11048 		if (ctx->curr != TABLE)
11049 			return -1;
11050 		if (sizeof(*out) > size)
11051 			return -1;
11052 		out->command = ctx->curr;
11053 		ctx->objdata = 0;
11054 		ctx->object = out;
11055 		ctx->objmask = NULL;
11056 		return len;
11057 	}
11058 	switch (ctx->curr) {
11059 	case TABLE_CREATE:
11060 	case TABLE_RESIZE:
11061 		out->command = ctx->curr;
11062 		ctx->objdata = 0;
11063 		ctx->object = out;
11064 		ctx->objmask = NULL;
11065 		out->args.table.id = UINT32_MAX;
11066 		return len;
11067 	case TABLE_PATTERN_TEMPLATE:
11068 		out->args.table.pat_templ_id =
11069 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11070 					       sizeof(double));
11071 		template_id = out->args.table.pat_templ_id
11072 				+ out->args.table.pat_templ_id_n++;
11073 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11074 			return -1;
11075 		ctx->objdata = 0;
11076 		ctx->object = template_id;
11077 		ctx->objmask = NULL;
11078 		return len;
11079 	case TABLE_ACTIONS_TEMPLATE:
11080 		out->args.table.act_templ_id =
11081 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11082 					       (out->args.table.pat_templ_id +
11083 						out->args.table.pat_templ_id_n),
11084 					       sizeof(double));
11085 		template_id = out->args.table.act_templ_id
11086 				+ out->args.table.act_templ_id_n++;
11087 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11088 			return -1;
11089 		ctx->objdata = 0;
11090 		ctx->object = template_id;
11091 		ctx->objmask = NULL;
11092 		return len;
11093 	case TABLE_INGRESS:
11094 		out->args.table.attr.flow_attr.ingress = 1;
11095 		return len;
11096 	case TABLE_EGRESS:
11097 		out->args.table.attr.flow_attr.egress = 1;
11098 		return len;
11099 	case TABLE_TRANSFER:
11100 		out->args.table.attr.flow_attr.transfer = 1;
11101 		return len;
11102 	case TABLE_TRANSFER_WIRE_ORIG:
11103 		if (!out->args.table.attr.flow_attr.transfer)
11104 			return -1;
11105 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
11106 		return len;
11107 	case TABLE_TRANSFER_VPORT_ORIG:
11108 		if (!out->args.table.attr.flow_attr.transfer)
11109 			return -1;
11110 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
11111 		return len;
11112 	case TABLE_RESIZABLE:
11113 		out->args.table.attr.specialize |=
11114 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
11115 		return len;
11116 	case TABLE_RULES_NUMBER:
11117 		ctx->objdata = 0;
11118 		ctx->object = out;
11119 		ctx->objmask = NULL;
11120 		return len;
11121 	case TABLE_RESIZE_ID:
11122 	case TABLE_RESIZE_RULES_NUMBER:
11123 		return len;
11124 	default:
11125 		return -1;
11126 	}
11127 }
11128 
11129 /** Parse tokens for table destroy command. */
11130 static int
11131 parse_table_destroy(struct context *ctx, const struct token *token,
11132 		    const char *str, unsigned int len,
11133 		    void *buf, unsigned int size)
11134 {
11135 	struct buffer *out = buf;
11136 	uint32_t *table_id;
11137 
11138 	/* Token name must match. */
11139 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11140 		return -1;
11141 	/* Nothing else to do if there is no buffer. */
11142 	if (!out)
11143 		return len;
11144 	if (!out->command || out->command == TABLE) {
11145 		if (ctx->curr != TABLE_DESTROY &&
11146 		    ctx->curr != TABLE_RESIZE_COMPLETE)
11147 			return -1;
11148 		if (sizeof(*out) > size)
11149 			return -1;
11150 		out->command = ctx->curr;
11151 		ctx->objdata = 0;
11152 		ctx->object = out;
11153 		ctx->objmask = NULL;
11154 		out->args.table_destroy.table_id =
11155 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11156 					       sizeof(double));
11157 		return len;
11158 	}
11159 	table_id = out->args.table_destroy.table_id
11160 		    + out->args.table_destroy.table_id_n++;
11161 	if ((uint8_t *)table_id > (uint8_t *)out + size)
11162 		return -1;
11163 	ctx->objdata = 0;
11164 	ctx->object = table_id;
11165 	ctx->objmask = NULL;
11166 	return len;
11167 }
11168 
11169 /** Parse tokens for queue create commands. */
11170 static int
11171 parse_qo(struct context *ctx, const struct token *token,
11172 	 const char *str, unsigned int len,
11173 	 void *buf, unsigned int size)
11174 {
11175 	struct buffer *out = buf;
11176 
11177 	/* Token name must match. */
11178 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11179 		return -1;
11180 	/* Nothing else to do if there is no buffer. */
11181 	if (!out)
11182 		return len;
11183 	if (!out->command) {
11184 		if (ctx->curr != QUEUE)
11185 			return -1;
11186 		if (sizeof(*out) > size)
11187 			return -1;
11188 		out->command = ctx->curr;
11189 		ctx->objdata = 0;
11190 		ctx->object = out;
11191 		ctx->objmask = NULL;
11192 		out->args.vc.data = (uint8_t *)out + size;
11193 		return len;
11194 	}
11195 	switch (ctx->curr) {
11196 	case QUEUE_CREATE:
11197 	case QUEUE_UPDATE:
11198 		out->command = ctx->curr;
11199 		ctx->objdata = 0;
11200 		ctx->object = out;
11201 		ctx->objmask = NULL;
11202 		out->args.vc.rule_id = UINT32_MAX;
11203 		return len;
11204 	case QUEUE_TEMPLATE_TABLE:
11205 	case QUEUE_PATTERN_TEMPLATE:
11206 	case QUEUE_ACTIONS_TEMPLATE:
11207 	case QUEUE_CREATE_POSTPONE:
11208 	case QUEUE_RULE_ID:
11209 	case QUEUE_UPDATE_ID:
11210 		return len;
11211 	case ITEM_PATTERN:
11212 		out->args.vc.pattern =
11213 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11214 					       sizeof(double));
11215 		ctx->object = out->args.vc.pattern;
11216 		ctx->objmask = NULL;
11217 		return len;
11218 	case ACTIONS:
11219 		out->args.vc.actions =
11220 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11221 					       (out->args.vc.pattern +
11222 						out->args.vc.pattern_n),
11223 					       sizeof(double));
11224 		ctx->object = out->args.vc.actions;
11225 		ctx->objmask = NULL;
11226 		return len;
11227 	default:
11228 		return -1;
11229 	}
11230 }
11231 
11232 /** Parse tokens for queue destroy command. */
11233 static int
11234 parse_qo_destroy(struct context *ctx, const struct token *token,
11235 		 const char *str, unsigned int len,
11236 		 void *buf, unsigned int size)
11237 {
11238 	struct buffer *out = buf;
11239 	uint64_t *flow_id;
11240 
11241 	/* Token name must match. */
11242 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11243 		return -1;
11244 	/* Nothing else to do if there is no buffer. */
11245 	if (!out)
11246 		return len;
11247 	if (!out->command || out->command == QUEUE) {
11248 		if (ctx->curr != QUEUE_DESTROY &&
11249 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11250 			return -1;
11251 		if (sizeof(*out) > size)
11252 			return -1;
11253 		out->command = ctx->curr;
11254 		ctx->objdata = 0;
11255 		ctx->object = out;
11256 		ctx->objmask = NULL;
11257 		out->args.destroy.rule =
11258 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11259 					       sizeof(double));
11260 		return len;
11261 	}
11262 	switch (ctx->curr) {
11263 	case QUEUE_DESTROY_ID:
11264 		flow_id = out->args.destroy.rule
11265 				+ out->args.destroy.rule_n++;
11266 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11267 			return -1;
11268 		ctx->objdata = 0;
11269 		ctx->object = flow_id;
11270 		ctx->objmask = NULL;
11271 		return len;
11272 	case QUEUE_DESTROY_POSTPONE:
11273 		return len;
11274 	default:
11275 		return -1;
11276 	}
11277 }
11278 
11279 /** Parse tokens for push queue command. */
11280 static int
11281 parse_push(struct context *ctx, const struct token *token,
11282 	   const char *str, unsigned int len,
11283 	   void *buf, unsigned int size)
11284 {
11285 	struct buffer *out = buf;
11286 
11287 	/* Token name must match. */
11288 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11289 		return -1;
11290 	/* Nothing else to do if there is no buffer. */
11291 	if (!out)
11292 		return len;
11293 	if (!out->command) {
11294 		if (ctx->curr != PUSH)
11295 			return -1;
11296 		if (sizeof(*out) > size)
11297 			return -1;
11298 		out->command = ctx->curr;
11299 		ctx->objdata = 0;
11300 		ctx->object = out;
11301 		ctx->objmask = NULL;
11302 		out->args.vc.data = (uint8_t *)out + size;
11303 	}
11304 	return len;
11305 }
11306 
11307 /** Parse tokens for pull command. */
11308 static int
11309 parse_pull(struct context *ctx, const struct token *token,
11310 	   const char *str, unsigned int len,
11311 	   void *buf, unsigned int size)
11312 {
11313 	struct buffer *out = buf;
11314 
11315 	/* Token name must match. */
11316 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11317 		return -1;
11318 	/* Nothing else to do if there is no buffer. */
11319 	if (!out)
11320 		return len;
11321 	if (!out->command) {
11322 		if (ctx->curr != PULL)
11323 			return -1;
11324 		if (sizeof(*out) > size)
11325 			return -1;
11326 		out->command = ctx->curr;
11327 		ctx->objdata = 0;
11328 		ctx->object = out;
11329 		ctx->objmask = NULL;
11330 		out->args.vc.data = (uint8_t *)out + size;
11331 	}
11332 	return len;
11333 }
11334 
11335 /** Parse tokens for hash calculation commands. */
11336 static int
11337 parse_hash(struct context *ctx, const struct token *token,
11338 	 const char *str, unsigned int len,
11339 	 void *buf, unsigned int size)
11340 {
11341 	struct buffer *out = buf;
11342 
11343 	/* Token name must match. */
11344 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11345 		return -1;
11346 	/* Nothing else to do if there is no buffer. */
11347 	if (!out)
11348 		return len;
11349 	if (!out->command) {
11350 		if (ctx->curr != HASH)
11351 			return -1;
11352 		if (sizeof(*out) > size)
11353 			return -1;
11354 		out->command = ctx->curr;
11355 		ctx->objdata = 0;
11356 		ctx->object = out;
11357 		ctx->objmask = NULL;
11358 		out->args.vc.data = (uint8_t *)out + size;
11359 		return len;
11360 	}
11361 	switch (ctx->curr) {
11362 	case HASH_CALC_TABLE:
11363 	case HASH_CALC_PATTERN_INDEX:
11364 		return len;
11365 	case ITEM_PATTERN:
11366 		out->args.vc.pattern =
11367 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11368 					       sizeof(double));
11369 		ctx->object = out->args.vc.pattern;
11370 		ctx->objmask = NULL;
11371 		return len;
11372 	case HASH_CALC_ENCAP:
11373 		out->args.vc.encap_hash = 1;
11374 		return len;
11375 	case ENCAP_HASH_FIELD_SRC_PORT:
11376 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11377 		return len;
11378 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11379 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11380 		return len;
11381 	default:
11382 		return -1;
11383 	}
11384 }
11385 
11386 static int
11387 parse_group(struct context *ctx, const struct token *token,
11388 	    const char *str, unsigned int len,
11389 	    void *buf, unsigned int size)
11390 {
11391 	struct buffer *out = buf;
11392 
11393 	/* Token name must match. */
11394 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11395 		return -1;
11396 	/* Nothing else to do if there is no buffer. */
11397 	if (!out)
11398 		return len;
11399 	if (!out->command) {
11400 		if (ctx->curr != FLOW_GROUP)
11401 			return -1;
11402 		if (sizeof(*out) > size)
11403 			return -1;
11404 		out->command = ctx->curr;
11405 		ctx->objdata = 0;
11406 		ctx->object = out;
11407 		ctx->objmask = NULL;
11408 		out->args.vc.data = (uint8_t *)out + size;
11409 		return len;
11410 	}
11411 	switch (ctx->curr) {
11412 	case GROUP_INGRESS:
11413 		out->args.vc.attr.ingress = 1;
11414 		return len;
11415 	case GROUP_EGRESS:
11416 		out->args.vc.attr.egress = 1;
11417 		return len;
11418 	case GROUP_TRANSFER:
11419 		out->args.vc.attr.transfer = 1;
11420 		return len;
11421 	case GROUP_SET_MISS_ACTIONS:
11422 		out->command = ctx->curr;
11423 		ctx->objdata = 0;
11424 		ctx->object = out;
11425 		ctx->objmask = NULL;
11426 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11427 							       sizeof(double));
11428 		return len;
11429 	default:
11430 		return -1;
11431 	}
11432 }
11433 
11434 static int
11435 parse_flex(struct context *ctx, const struct token *token,
11436 	     const char *str, unsigned int len,
11437 	     void *buf, unsigned int size)
11438 {
11439 	struct buffer *out = buf;
11440 
11441 	/* Token name must match. */
11442 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11443 		return -1;
11444 	/* Nothing else to do if there is no buffer. */
11445 	if (!out)
11446 		return len;
11447 	if (out->command == ZERO) {
11448 		if (ctx->curr != FLEX)
11449 			return -1;
11450 		if (sizeof(*out) > size)
11451 			return -1;
11452 		out->command = ctx->curr;
11453 		ctx->objdata = 0;
11454 		ctx->object = out;
11455 		ctx->objmask = NULL;
11456 	} else {
11457 		switch (ctx->curr) {
11458 		default:
11459 			break;
11460 		case FLEX_ITEM_CREATE:
11461 		case FLEX_ITEM_DESTROY:
11462 			out->command = ctx->curr;
11463 			break;
11464 		}
11465 	}
11466 
11467 	return len;
11468 }
11469 
11470 static int
11471 parse_tunnel(struct context *ctx, const struct token *token,
11472 	     const char *str, unsigned int len,
11473 	     void *buf, unsigned int size)
11474 {
11475 	struct buffer *out = buf;
11476 
11477 	/* Token name must match. */
11478 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11479 		return -1;
11480 	/* Nothing else to do if there is no buffer. */
11481 	if (!out)
11482 		return len;
11483 	if (!out->command) {
11484 		if (ctx->curr != TUNNEL)
11485 			return -1;
11486 		if (sizeof(*out) > size)
11487 			return -1;
11488 		out->command = ctx->curr;
11489 		ctx->objdata = 0;
11490 		ctx->object = out;
11491 		ctx->objmask = NULL;
11492 	} else {
11493 		switch (ctx->curr) {
11494 		default:
11495 			break;
11496 		case TUNNEL_CREATE:
11497 		case TUNNEL_DESTROY:
11498 		case TUNNEL_LIST:
11499 			out->command = ctx->curr;
11500 			break;
11501 		case TUNNEL_CREATE_TYPE:
11502 		case TUNNEL_DESTROY_ID:
11503 			ctx->object = &out->args.vc.tunnel_ops;
11504 			break;
11505 		}
11506 	}
11507 
11508 	return len;
11509 }
11510 
11511 /**
11512  * Parse signed/unsigned integers 8 to 64-bit long.
11513  *
11514  * Last argument (ctx->args) is retrieved to determine integer type and
11515  * storage location.
11516  */
11517 static int
11518 parse_int(struct context *ctx, const struct token *token,
11519 	  const char *str, unsigned int len,
11520 	  void *buf, unsigned int size)
11521 {
11522 	const struct arg *arg = pop_args(ctx);
11523 	uintmax_t u;
11524 	char *end;
11525 
11526 	(void)token;
11527 	/* Argument is expected. */
11528 	if (!arg)
11529 		return -1;
11530 	errno = 0;
11531 	u = arg->sign ?
11532 		(uintmax_t)strtoimax(str, &end, 0) :
11533 		strtoumax(str, &end, 0);
11534 	if (errno || (size_t)(end - str) != len)
11535 		goto error;
11536 	if (arg->bounded &&
11537 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11538 			    (intmax_t)u > (intmax_t)arg->max)) ||
11539 	     (!arg->sign && (u < arg->min || u > arg->max))))
11540 		goto error;
11541 	if (!ctx->object)
11542 		return len;
11543 	if (arg->mask) {
11544 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11545 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11546 			goto error;
11547 		return len;
11548 	}
11549 	buf = (uint8_t *)ctx->object + arg->offset;
11550 	size = arg->size;
11551 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11552 		return -1;
11553 objmask:
11554 	switch (size) {
11555 	case sizeof(uint8_t):
11556 		*(uint8_t *)buf = u;
11557 		break;
11558 	case sizeof(uint16_t):
11559 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11560 		break;
11561 	case sizeof(uint8_t [3]):
11562 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11563 		if (!arg->hton) {
11564 			((uint8_t *)buf)[0] = u;
11565 			((uint8_t *)buf)[1] = u >> 8;
11566 			((uint8_t *)buf)[2] = u >> 16;
11567 			break;
11568 		}
11569 #endif
11570 		((uint8_t *)buf)[0] = u >> 16;
11571 		((uint8_t *)buf)[1] = u >> 8;
11572 		((uint8_t *)buf)[2] = u;
11573 		break;
11574 	case sizeof(uint32_t):
11575 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11576 		break;
11577 	case sizeof(uint64_t):
11578 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11579 		break;
11580 	default:
11581 		goto error;
11582 	}
11583 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11584 		u = -1;
11585 		buf = (uint8_t *)ctx->objmask + arg->offset;
11586 		goto objmask;
11587 	}
11588 	return len;
11589 error:
11590 	push_args(ctx, arg);
11591 	return -1;
11592 }
11593 
11594 /**
11595  * Parse a string.
11596  *
11597  * Three arguments (ctx->args) are retrieved from the stack to store data,
11598  * its actual length and address (in that order).
11599  */
11600 static int
11601 parse_string(struct context *ctx, const struct token *token,
11602 	     const char *str, unsigned int len,
11603 	     void *buf, unsigned int size)
11604 {
11605 	const struct arg *arg_data = pop_args(ctx);
11606 	const struct arg *arg_len = pop_args(ctx);
11607 	const struct arg *arg_addr = pop_args(ctx);
11608 	char tmp[16]; /* Ought to be enough. */
11609 	int ret;
11610 
11611 	/* Arguments are expected. */
11612 	if (!arg_data)
11613 		return -1;
11614 	if (!arg_len) {
11615 		push_args(ctx, arg_data);
11616 		return -1;
11617 	}
11618 	if (!arg_addr) {
11619 		push_args(ctx, arg_len);
11620 		push_args(ctx, arg_data);
11621 		return -1;
11622 	}
11623 	size = arg_data->size;
11624 	/* Bit-mask fill is not supported. */
11625 	if (arg_data->mask || size < len)
11626 		goto error;
11627 	if (!ctx->object)
11628 		return len;
11629 	/* Let parse_int() fill length information first. */
11630 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11631 	if (ret < 0)
11632 		goto error;
11633 	push_args(ctx, arg_len);
11634 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11635 	if (ret < 0) {
11636 		pop_args(ctx);
11637 		goto error;
11638 	}
11639 	buf = (uint8_t *)ctx->object + arg_data->offset;
11640 	/* Output buffer is not necessarily NUL-terminated. */
11641 	memcpy(buf, str, len);
11642 	memset((uint8_t *)buf + len, 0x00, size - len);
11643 	if (ctx->objmask)
11644 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11645 	/* Save address if requested. */
11646 	if (arg_addr->size) {
11647 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11648 		       (void *[]){
11649 			(uint8_t *)ctx->object + arg_data->offset
11650 		       },
11651 		       arg_addr->size);
11652 		if (ctx->objmask)
11653 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11654 			       (void *[]){
11655 				(uint8_t *)ctx->objmask + arg_data->offset
11656 			       },
11657 			       arg_addr->size);
11658 	}
11659 	return len;
11660 error:
11661 	push_args(ctx, arg_addr);
11662 	push_args(ctx, arg_len);
11663 	push_args(ctx, arg_data);
11664 	return -1;
11665 }
11666 
11667 static int
11668 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11669 {
11670 	const uint8_t *head = dst;
11671 	uint32_t left;
11672 
11673 	if (*size == 0)
11674 		return -1;
11675 
11676 	left = *size;
11677 
11678 	/* Convert chars to bytes */
11679 	while (left) {
11680 		char tmp[3], *end = tmp;
11681 		uint32_t read_lim = left & 1 ? 1 : 2;
11682 
11683 		snprintf(tmp, read_lim + 1, "%s", src);
11684 		*dst = strtoul(tmp, &end, 16);
11685 		if (*end) {
11686 			*dst = 0;
11687 			*size = (uint32_t)(dst - head);
11688 			return -1;
11689 		}
11690 		left -= read_lim;
11691 		src += read_lim;
11692 		dst++;
11693 	}
11694 	*dst = 0;
11695 	*size = (uint32_t)(dst - head);
11696 	return 0;
11697 }
11698 
11699 static int
11700 parse_hex(struct context *ctx, const struct token *token,
11701 		const char *str, unsigned int len,
11702 		void *buf, unsigned int size)
11703 {
11704 	const struct arg *arg_data = pop_args(ctx);
11705 	const struct arg *arg_len = pop_args(ctx);
11706 	const struct arg *arg_addr = pop_args(ctx);
11707 	char tmp[16]; /* Ought to be enough. */
11708 	int ret;
11709 	unsigned int hexlen = len;
11710 	unsigned int length = 256;
11711 	uint8_t hex_tmp[length];
11712 
11713 	/* Arguments are expected. */
11714 	if (!arg_data)
11715 		return -1;
11716 	if (!arg_len) {
11717 		push_args(ctx, arg_data);
11718 		return -1;
11719 	}
11720 	if (!arg_addr) {
11721 		push_args(ctx, arg_len);
11722 		push_args(ctx, arg_data);
11723 		return -1;
11724 	}
11725 	size = arg_data->size;
11726 	/* Bit-mask fill is not supported. */
11727 	if (arg_data->mask)
11728 		goto error;
11729 	if (!ctx->object)
11730 		return len;
11731 
11732 	/* translate bytes string to array. */
11733 	if (str[0] == '0' && ((str[1] == 'x') ||
11734 			(str[1] == 'X'))) {
11735 		str += 2;
11736 		hexlen -= 2;
11737 	}
11738 	if (hexlen > length)
11739 		goto error;
11740 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11741 	if (ret < 0)
11742 		goto error;
11743 	/* Check the converted binary fits into data buffer. */
11744 	if (hexlen > size)
11745 		goto error;
11746 	/* Let parse_int() fill length information first. */
11747 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11748 	if (ret < 0)
11749 		goto error;
11750 	/* Save length if requested. */
11751 	if (arg_len->size) {
11752 		push_args(ctx, arg_len);
11753 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11754 		if (ret < 0) {
11755 			pop_args(ctx);
11756 			goto error;
11757 		}
11758 	}
11759 	buf = (uint8_t *)ctx->object + arg_data->offset;
11760 	/* Output buffer is not necessarily NUL-terminated. */
11761 	memcpy(buf, hex_tmp, hexlen);
11762 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11763 	if (ctx->objmask)
11764 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11765 					0xff, hexlen);
11766 	/* Save address if requested. */
11767 	if (arg_addr->size) {
11768 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11769 		       (void *[]){
11770 			(uint8_t *)ctx->object + arg_data->offset
11771 		       },
11772 		       arg_addr->size);
11773 		if (ctx->objmask)
11774 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11775 			       (void *[]){
11776 				(uint8_t *)ctx->objmask + arg_data->offset
11777 			       },
11778 			       arg_addr->size);
11779 	}
11780 	return len;
11781 error:
11782 	push_args(ctx, arg_addr);
11783 	push_args(ctx, arg_len);
11784 	push_args(ctx, arg_data);
11785 	return -1;
11786 
11787 }
11788 
11789 /**
11790  * Parse a zero-ended string.
11791  */
11792 static int
11793 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11794 	     const char *str, unsigned int len,
11795 	     void *buf, unsigned int size)
11796 {
11797 	const struct arg *arg_data = pop_args(ctx);
11798 
11799 	/* Arguments are expected. */
11800 	if (!arg_data)
11801 		return -1;
11802 	size = arg_data->size;
11803 	/* Bit-mask fill is not supported. */
11804 	if (arg_data->mask || size < len + 1)
11805 		goto error;
11806 	if (!ctx->object)
11807 		return len;
11808 	buf = (uint8_t *)ctx->object + arg_data->offset;
11809 	strncpy(buf, str, len);
11810 	if (ctx->objmask)
11811 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11812 	return len;
11813 error:
11814 	push_args(ctx, arg_data);
11815 	return -1;
11816 }
11817 
11818 /**
11819  * Parse a MAC address.
11820  *
11821  * Last argument (ctx->args) is retrieved to determine storage size and
11822  * location.
11823  */
11824 static int
11825 parse_mac_addr(struct context *ctx, const struct token *token,
11826 	       const char *str, unsigned int len,
11827 	       void *buf, unsigned int size)
11828 {
11829 	const struct arg *arg = pop_args(ctx);
11830 	struct rte_ether_addr tmp;
11831 	int ret;
11832 
11833 	(void)token;
11834 	/* Argument is expected. */
11835 	if (!arg)
11836 		return -1;
11837 	size = arg->size;
11838 	/* Bit-mask fill is not supported. */
11839 	if (arg->mask || size != sizeof(tmp))
11840 		goto error;
11841 	/* Only network endian is supported. */
11842 	if (!arg->hton)
11843 		goto error;
11844 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11845 	if (ret < 0 || (unsigned int)ret != len)
11846 		goto error;
11847 	if (!ctx->object)
11848 		return len;
11849 	buf = (uint8_t *)ctx->object + arg->offset;
11850 	memcpy(buf, &tmp, size);
11851 	if (ctx->objmask)
11852 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11853 	return len;
11854 error:
11855 	push_args(ctx, arg);
11856 	return -1;
11857 }
11858 
11859 /**
11860  * Parse an IPv4 address.
11861  *
11862  * Last argument (ctx->args) is retrieved to determine storage size and
11863  * location.
11864  */
11865 static int
11866 parse_ipv4_addr(struct context *ctx, const struct token *token,
11867 		const char *str, unsigned int len,
11868 		void *buf, unsigned int size)
11869 {
11870 	const struct arg *arg = pop_args(ctx);
11871 	char str2[len + 1];
11872 	struct in_addr tmp;
11873 	int ret;
11874 
11875 	/* Argument is expected. */
11876 	if (!arg)
11877 		return -1;
11878 	size = arg->size;
11879 	/* Bit-mask fill is not supported. */
11880 	if (arg->mask || size != sizeof(tmp))
11881 		goto error;
11882 	/* Only network endian is supported. */
11883 	if (!arg->hton)
11884 		goto error;
11885 	memcpy(str2, str, len);
11886 	str2[len] = '\0';
11887 	ret = inet_pton(AF_INET, str2, &tmp);
11888 	if (ret != 1) {
11889 		/* Attempt integer parsing. */
11890 		push_args(ctx, arg);
11891 		return parse_int(ctx, token, str, len, buf, size);
11892 	}
11893 	if (!ctx->object)
11894 		return len;
11895 	buf = (uint8_t *)ctx->object + arg->offset;
11896 	memcpy(buf, &tmp, size);
11897 	if (ctx->objmask)
11898 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11899 	return len;
11900 error:
11901 	push_args(ctx, arg);
11902 	return -1;
11903 }
11904 
11905 /**
11906  * Parse an IPv6 address.
11907  *
11908  * Last argument (ctx->args) is retrieved to determine storage size and
11909  * location.
11910  */
11911 static int
11912 parse_ipv6_addr(struct context *ctx, const struct token *token,
11913 		const char *str, unsigned int len,
11914 		void *buf, unsigned int size)
11915 {
11916 	const struct arg *arg = pop_args(ctx);
11917 	char str2[len + 1];
11918 	struct rte_ipv6_addr tmp;
11919 	int ret;
11920 
11921 	(void)token;
11922 	/* Argument is expected. */
11923 	if (!arg)
11924 		return -1;
11925 	size = arg->size;
11926 	/* Bit-mask fill is not supported. */
11927 	if (arg->mask || size != sizeof(tmp))
11928 		goto error;
11929 	/* Only network endian is supported. */
11930 	if (!arg->hton)
11931 		goto error;
11932 	memcpy(str2, str, len);
11933 	str2[len] = '\0';
11934 	ret = inet_pton(AF_INET6, str2, &tmp);
11935 	if (ret != 1)
11936 		goto error;
11937 	if (!ctx->object)
11938 		return len;
11939 	buf = (uint8_t *)ctx->object + arg->offset;
11940 	memcpy(buf, &tmp, size);
11941 	if (ctx->objmask)
11942 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11943 	return len;
11944 error:
11945 	push_args(ctx, arg);
11946 	return -1;
11947 }
11948 
11949 /** Boolean values (even indices stand for false). */
11950 static const char *const boolean_name[] = {
11951 	"0", "1",
11952 	"false", "true",
11953 	"no", "yes",
11954 	"N", "Y",
11955 	"off", "on",
11956 	NULL,
11957 };
11958 
11959 /**
11960  * Parse a boolean value.
11961  *
11962  * Last argument (ctx->args) is retrieved to determine storage size and
11963  * location.
11964  */
11965 static int
11966 parse_boolean(struct context *ctx, const struct token *token,
11967 	      const char *str, unsigned int len,
11968 	      void *buf, unsigned int size)
11969 {
11970 	const struct arg *arg = pop_args(ctx);
11971 	unsigned int i;
11972 	int ret;
11973 
11974 	/* Argument is expected. */
11975 	if (!arg)
11976 		return -1;
11977 	for (i = 0; boolean_name[i]; ++i)
11978 		if (!strcmp_partial(boolean_name[i], str, len))
11979 			break;
11980 	/* Process token as integer. */
11981 	if (boolean_name[i])
11982 		str = i & 1 ? "1" : "0";
11983 	push_args(ctx, arg);
11984 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11985 	return ret > 0 ? (int)len : ret;
11986 }
11987 
11988 /** Parse port and update context. */
11989 static int
11990 parse_port(struct context *ctx, const struct token *token,
11991 	   const char *str, unsigned int len,
11992 	   void *buf, unsigned int size)
11993 {
11994 	struct buffer *out = &(struct buffer){ .port = 0 };
11995 	int ret;
11996 
11997 	if (buf)
11998 		out = buf;
11999 	else {
12000 		ctx->objdata = 0;
12001 		ctx->object = out;
12002 		ctx->objmask = NULL;
12003 		size = sizeof(*out);
12004 	}
12005 	ret = parse_int(ctx, token, str, len, out, size);
12006 	if (ret >= 0)
12007 		ctx->port = out->port;
12008 	if (!buf)
12009 		ctx->object = NULL;
12010 	return ret;
12011 }
12012 
12013 /** Parse tokens for shared indirect actions. */
12014 static int
12015 parse_ia_port(struct context *ctx, const struct token *token,
12016 	      const char *str, unsigned int len,
12017 	      void *buf, unsigned int size)
12018 {
12019 	struct rte_flow_action *action = ctx->object;
12020 	uint32_t id;
12021 	int ret;
12022 
12023 	(void)buf;
12024 	(void)size;
12025 	ctx->objdata = 0;
12026 	ctx->object = &id;
12027 	ctx->objmask = NULL;
12028 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12029 	ctx->object = action;
12030 	if (ret != (int)len)
12031 		return ret;
12032 	/* set indirect action */
12033 	if (action)
12034 		action->conf = (void *)(uintptr_t)id;
12035 	return ret;
12036 }
12037 
12038 static int
12039 parse_ia_id2ptr(struct context *ctx, const struct token *token,
12040 		const char *str, unsigned int len,
12041 		void *buf, unsigned int size)
12042 {
12043 	struct rte_flow_action *action = ctx->object;
12044 	uint32_t id;
12045 	int ret;
12046 
12047 	(void)buf;
12048 	(void)size;
12049 	ctx->objdata = 0;
12050 	ctx->object = &id;
12051 	ctx->objmask = NULL;
12052 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12053 	ctx->object = action;
12054 	if (ret != (int)len)
12055 		return ret;
12056 	/* set indirect action */
12057 	if (action) {
12058 		portid_t port_id = ctx->port;
12059 		if (ctx->prev == INDIRECT_ACTION_PORT)
12060 			port_id = (portid_t)(uintptr_t)action->conf;
12061 		action->conf = port_action_handle_get_by_id(port_id, id);
12062 		ret = (action->conf) ? ret : -1;
12063 	}
12064 	return ret;
12065 }
12066 
12067 static int
12068 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
12069 		    const char *str, unsigned int len,
12070 		    __rte_unused void *buf, __rte_unused unsigned int size)
12071 {
12072 	struct rte_flow_action *action = ctx->object;
12073 	struct rte_flow_action_indirect_list *action_conf;
12074 	const struct indlst_conf *indlst_conf;
12075 	uint32_t id;
12076 	int ret;
12077 
12078 	ctx->objdata = 0;
12079 	ctx->object = &id;
12080 	ctx->objmask = NULL;
12081 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12082 	ctx->object = action;
12083 	if (ret != (int)len)
12084 		return ret;
12085 
12086 	/* set handle and conf */
12087 	if (action) {
12088 		action_conf = (void *)(uintptr_t)action->conf;
12089 		action_conf->conf = NULL;
12090 		switch (ctx->curr) {
12091 		case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
12092 		action_conf->handle = (typeof(action_conf->handle))
12093 					port_action_handle_get_by_id(ctx->port, id);
12094 			if (!action_conf->handle) {
12095 				printf("no indirect list handle for id %u\n", id);
12096 				return -1;
12097 			}
12098 			break;
12099 		case INDIRECT_LIST_ACTION_ID2PTR_CONF:
12100 			indlst_conf = indirect_action_list_conf_get(id);
12101 			if (!indlst_conf)
12102 				return -1;
12103 			action_conf->conf = (const void **)indlst_conf->conf;
12104 			break;
12105 		default:
12106 			break;
12107 		}
12108 	}
12109 	return ret;
12110 }
12111 
12112 static int
12113 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
12114 		const char *str, unsigned int len,
12115 		void *buf, unsigned int size)
12116 {
12117 	struct rte_flow_action *action = ctx->object;
12118 	struct rte_flow_action_meter_mark *meter;
12119 	struct rte_flow_meter_profile *profile = NULL;
12120 	uint32_t id = 0;
12121 	int ret;
12122 
12123 	(void)buf;
12124 	(void)size;
12125 	ctx->objdata = 0;
12126 	ctx->object = &id;
12127 	ctx->objmask = NULL;
12128 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12129 	ctx->object = action;
12130 	if (ret != (int)len)
12131 		return ret;
12132 	/* set meter profile */
12133 	if (action) {
12134 		meter = (struct rte_flow_action_meter_mark *)
12135 			(uintptr_t)(action->conf);
12136 		profile = port_meter_profile_get_by_id(ctx->port, id);
12137 		meter->profile = profile;
12138 		ret = (profile) ? ret : -1;
12139 	}
12140 	return ret;
12141 }
12142 
12143 static int
12144 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
12145 		const char *str, unsigned int len,
12146 		void *buf, unsigned int size)
12147 {
12148 	struct rte_flow_action *action = ctx->object;
12149 	struct rte_flow_action_meter_mark *meter;
12150 	struct rte_flow_meter_policy *policy = NULL;
12151 	uint32_t id = 0;
12152 	int ret;
12153 
12154 	(void)buf;
12155 	(void)size;
12156 	ctx->objdata = 0;
12157 	ctx->object = &id;
12158 	ctx->objmask = NULL;
12159 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12160 	ctx->object = action;
12161 	if (ret != (int)len)
12162 		return ret;
12163 	/* set meter policy */
12164 	if (action) {
12165 		meter = (struct rte_flow_action_meter_mark *)
12166 			(uintptr_t)(action->conf);
12167 		policy = port_meter_policy_get_by_id(ctx->port, id);
12168 		meter->policy = policy;
12169 		ret = (policy) ? ret : -1;
12170 	}
12171 	return ret;
12172 }
12173 
12174 /** Parse set command, initialize output buffer for subsequent tokens. */
12175 static int
12176 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12177 			  const char *str, unsigned int len,
12178 			  void *buf, unsigned int size)
12179 {
12180 	struct buffer *out = buf;
12181 
12182 	/* Token name must match. */
12183 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12184 		return -1;
12185 	/* Nothing else to do if there is no buffer. */
12186 	if (!out)
12187 		return len;
12188 	/* Make sure buffer is large enough. */
12189 	if (size < sizeof(*out))
12190 		return -1;
12191 	ctx->objdata = 0;
12192 	ctx->objmask = NULL;
12193 	ctx->object = out;
12194 	if (!out->command)
12195 		return -1;
12196 	out->command = ctx->curr;
12197 	/* For encap/decap we need is pattern */
12198 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12199 						       sizeof(double));
12200 	return len;
12201 }
12202 
12203 /** Parse set command, initialize output buffer for subsequent tokens. */
12204 static int
12205 parse_set_sample_action(struct context *ctx, const struct token *token,
12206 			  const char *str, unsigned int len,
12207 			  void *buf, unsigned int size)
12208 {
12209 	struct buffer *out = buf;
12210 
12211 	/* Token name must match. */
12212 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12213 		return -1;
12214 	/* Nothing else to do if there is no buffer. */
12215 	if (!out)
12216 		return len;
12217 	/* Make sure buffer is large enough. */
12218 	if (size < sizeof(*out))
12219 		return -1;
12220 	ctx->objdata = 0;
12221 	ctx->objmask = NULL;
12222 	ctx->object = out;
12223 	if (!out->command)
12224 		return -1;
12225 	out->command = ctx->curr;
12226 	/* For sampler we need is actions */
12227 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12228 						       sizeof(double));
12229 	return len;
12230 }
12231 
12232 /** Parse set command, initialize output buffer for subsequent tokens. */
12233 static int
12234 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12235 			  const char *str, unsigned int len,
12236 			  void *buf, unsigned int size)
12237 {
12238 	struct buffer *out = buf;
12239 
12240 	/* Token name must match. */
12241 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12242 		return -1;
12243 	/* Nothing else to do if there is no buffer. */
12244 	if (!out)
12245 		return len;
12246 	/* Make sure buffer is large enough. */
12247 	if (size < sizeof(*out))
12248 		return -1;
12249 	ctx->objdata = 0;
12250 	ctx->objmask = NULL;
12251 	ctx->object = out;
12252 	if (!out->command)
12253 		return -1;
12254 	out->command = ctx->curr;
12255 	/* For ipv6_ext_push/remove we need is pattern */
12256 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12257 						       sizeof(double));
12258 	return len;
12259 }
12260 
12261 /**
12262  * Parse set raw_encap/raw_decap command,
12263  * initialize output buffer for subsequent tokens.
12264  */
12265 static int
12266 parse_set_init(struct context *ctx, const struct token *token,
12267 	       const char *str, unsigned int len,
12268 	       void *buf, unsigned int size)
12269 {
12270 	struct buffer *out = buf;
12271 
12272 	/* Token name must match. */
12273 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12274 		return -1;
12275 	/* Nothing else to do if there is no buffer. */
12276 	if (!out)
12277 		return len;
12278 	/* Make sure buffer is large enough. */
12279 	if (size < sizeof(*out))
12280 		return -1;
12281 	/* Initialize buffer. */
12282 	memset(out, 0x00, sizeof(*out));
12283 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12284 	ctx->objdata = 0;
12285 	ctx->object = out;
12286 	ctx->objmask = NULL;
12287 	if (!out->command) {
12288 		if (ctx->curr != SET)
12289 			return -1;
12290 		if (sizeof(*out) > size)
12291 			return -1;
12292 		out->command = ctx->curr;
12293 		out->args.vc.data = (uint8_t *)out + size;
12294 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12295 						       sizeof(double));
12296 	}
12297 	return len;
12298 }
12299 
12300 /*
12301  * Replace testpmd handles in a flex flow item with real values.
12302  */
12303 static int
12304 parse_flex_handle(struct context *ctx, const struct token *token,
12305 		  const char *str, unsigned int len,
12306 		  void *buf, unsigned int size)
12307 {
12308 	struct rte_flow_item_flex *spec, *mask;
12309 	const struct rte_flow_item_flex *src_spec, *src_mask;
12310 	const struct arg *arg = pop_args(ctx);
12311 	uint32_t offset;
12312 	uint16_t handle;
12313 	int ret;
12314 
12315 	if (!arg) {
12316 		printf("Bad environment\n");
12317 		return -1;
12318 	}
12319 	offset = arg->offset;
12320 	push_args(ctx, arg);
12321 	ret = parse_int(ctx, token, str, len, buf, size);
12322 	if (ret <= 0 || !ctx->object)
12323 		return ret;
12324 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12325 		printf("Bad port\n");
12326 		return -1;
12327 	}
12328 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12329 		const struct flex_item *fp;
12330 		spec = ctx->object;
12331 		handle = (uint16_t)(uintptr_t)spec->handle;
12332 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12333 			printf("Bad flex item handle\n");
12334 			return -1;
12335 		}
12336 		fp = flex_items[ctx->port][handle];
12337 		if (!fp) {
12338 			printf("Bad flex item handle\n");
12339 			return -1;
12340 		}
12341 		spec->handle = fp->flex_handle;
12342 		mask = spec + 2; /* spec, last, mask */
12343 		mask->handle = fp->flex_handle;
12344 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12345 		handle = (uint16_t)(uintptr_t)
12346 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12347 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12348 			printf("Bad pattern handle\n");
12349 			return -1;
12350 		}
12351 		src_spec = &flex_patterns[handle].spec;
12352 		src_mask = &flex_patterns[handle].mask;
12353 		spec = ctx->object;
12354 		mask = spec + 2; /* spec, last, mask */
12355 		/* fill flow rule spec and mask parameters */
12356 		spec->length = src_spec->length;
12357 		spec->pattern = src_spec->pattern;
12358 		mask->length = src_mask->length;
12359 		mask->pattern = src_mask->pattern;
12360 	} else {
12361 		printf("Bad arguments - unknown flex item offset\n");
12362 		return -1;
12363 	}
12364 	return ret;
12365 }
12366 
12367 /** Parse Meter color name */
12368 static int
12369 parse_meter_color(struct context *ctx, const struct token *token,
12370 		  const char *str, unsigned int len, void *buf,
12371 		  unsigned int size)
12372 {
12373 	struct rte_flow_item_meter_color *meter_color;
12374 	unsigned int i;
12375 
12376 	(void)token;
12377 	(void)buf;
12378 	(void)size;
12379 	for (i = 0; meter_colors[i]; ++i)
12380 		if (!strcmp_partial(meter_colors[i], str, len))
12381 			break;
12382 	if (!meter_colors[i])
12383 		return -1;
12384 	if (!ctx->object)
12385 		return len;
12386 	meter_color = ctx->object;
12387 	meter_color->color = (enum rte_color)i;
12388 	return len;
12389 }
12390 
12391 /** Parse Insertion Table Type name */
12392 static int
12393 parse_insertion_table_type(struct context *ctx, const struct token *token,
12394 			   const char *str, unsigned int len, void *buf,
12395 			   unsigned int size)
12396 {
12397 	const struct arg *arg = pop_args(ctx);
12398 	unsigned int i;
12399 	char tmp[2];
12400 	int ret;
12401 
12402 	(void)size;
12403 	/* Argument is expected. */
12404 	if (!arg)
12405 		return -1;
12406 	for (i = 0; table_insertion_types[i]; ++i)
12407 		if (!strcmp_partial(table_insertion_types[i], str, len))
12408 			break;
12409 	if (!table_insertion_types[i])
12410 		return -1;
12411 	push_args(ctx, arg);
12412 	snprintf(tmp, sizeof(tmp), "%u", i);
12413 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12414 	return ret > 0 ? (int)len : ret;
12415 }
12416 
12417 /** Parse Hash Calculation Table Type name */
12418 static int
12419 parse_hash_table_type(struct context *ctx, const struct token *token,
12420 		      const char *str, unsigned int len, void *buf,
12421 		      unsigned int size)
12422 {
12423 	const struct arg *arg = pop_args(ctx);
12424 	unsigned int i;
12425 	char tmp[2];
12426 	int ret;
12427 
12428 	(void)size;
12429 	/* Argument is expected. */
12430 	if (!arg)
12431 		return -1;
12432 	for (i = 0; table_hash_funcs[i]; ++i)
12433 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12434 			break;
12435 	if (!table_hash_funcs[i])
12436 		return -1;
12437 	push_args(ctx, arg);
12438 	snprintf(tmp, sizeof(tmp), "%u", i);
12439 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12440 	return ret > 0 ? (int)len : ret;
12441 }
12442 
12443 static int
12444 parse_name_to_index(struct context *ctx, const struct token *token,
12445 		    const char *str, unsigned int len, void *buf,
12446 		    unsigned int size,
12447 		    const char *const names[], size_t names_size, uint32_t *dst)
12448 {
12449 	int ret;
12450 	uint32_t i;
12451 
12452 	RTE_SET_USED(token);
12453 	RTE_SET_USED(buf);
12454 	RTE_SET_USED(size);
12455 	if (!ctx->object)
12456 		return len;
12457 	for (i = 0; i < names_size; i++) {
12458 		if (!names[i])
12459 			continue;
12460 		ret = strcmp_partial(names[i], str,
12461 				     RTE_MIN(len, strlen(names[i])));
12462 		if (!ret) {
12463 			*dst = i;
12464 			return len;
12465 		}
12466 	}
12467 	return -1;
12468 }
12469 
12470 static const char *const quota_mode_names[] = {
12471 	NULL,
12472 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12473 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12474 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12475 };
12476 
12477 static const char *const quota_state_names[] = {
12478 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12479 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12480 };
12481 
12482 static const char *const quota_update_names[] = {
12483 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12484 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12485 };
12486 
12487 static const char *const query_update_mode_names[] = {
12488 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12489 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12490 };
12491 
12492 static int
12493 parse_quota_state_name(struct context *ctx, const struct token *token,
12494 		       const char *str, unsigned int len, void *buf,
12495 		       unsigned int size)
12496 {
12497 	struct rte_flow_item_quota *quota = ctx->object;
12498 
12499 	return parse_name_to_index(ctx, token, str, len, buf, size,
12500 				   quota_state_names,
12501 				   RTE_DIM(quota_state_names),
12502 				   (uint32_t *)&quota->state);
12503 }
12504 
12505 static int
12506 parse_quota_mode_name(struct context *ctx, const struct token *token,
12507 		      const char *str, unsigned int len, void *buf,
12508 		      unsigned int size)
12509 {
12510 	struct rte_flow_action_quota *quota = ctx->object;
12511 
12512 	return parse_name_to_index(ctx, token, str, len, buf, size,
12513 				   quota_mode_names,
12514 				   RTE_DIM(quota_mode_names),
12515 				   (uint32_t *)&quota->mode);
12516 }
12517 
12518 static int
12519 parse_quota_update_name(struct context *ctx, const struct token *token,
12520 			const char *str, unsigned int len, void *buf,
12521 			unsigned int size)
12522 {
12523 	struct rte_flow_update_quota *update = ctx->object;
12524 
12525 	return parse_name_to_index(ctx, token, str, len, buf, size,
12526 				   quota_update_names,
12527 				   RTE_DIM(quota_update_names),
12528 				   (uint32_t *)&update->op);
12529 }
12530 
12531 static int
12532 parse_qu_mode_name(struct context *ctx, const struct token *token,
12533 		   const char *str, unsigned int len, void *buf,
12534 		   unsigned int size)
12535 {
12536 	struct buffer *out = ctx->object;
12537 
12538 	return parse_name_to_index(ctx, token, str, len, buf, size,
12539 				   query_update_mode_names,
12540 				   RTE_DIM(query_update_mode_names),
12541 				   (uint32_t *)&out->args.ia.qu_mode);
12542 }
12543 
12544 /** No completion. */
12545 static int
12546 comp_none(struct context *ctx, const struct token *token,
12547 	  unsigned int ent, char *buf, unsigned int size)
12548 {
12549 	(void)ctx;
12550 	(void)token;
12551 	(void)ent;
12552 	(void)buf;
12553 	(void)size;
12554 	return 0;
12555 }
12556 
12557 /** Complete boolean values. */
12558 static int
12559 comp_boolean(struct context *ctx, const struct token *token,
12560 	     unsigned int ent, char *buf, unsigned int size)
12561 {
12562 	unsigned int i;
12563 
12564 	(void)ctx;
12565 	(void)token;
12566 	for (i = 0; boolean_name[i]; ++i)
12567 		if (buf && i == ent)
12568 			return strlcpy(buf, boolean_name[i], size);
12569 	if (buf)
12570 		return -1;
12571 	return i;
12572 }
12573 
12574 /** Complete action names. */
12575 static int
12576 comp_action(struct context *ctx, const struct token *token,
12577 	    unsigned int ent, char *buf, unsigned int size)
12578 {
12579 	unsigned int i;
12580 
12581 	(void)ctx;
12582 	(void)token;
12583 	for (i = 0; next_action[i]; ++i)
12584 		if (buf && i == ent)
12585 			return strlcpy(buf, token_list[next_action[i]].name,
12586 				       size);
12587 	if (buf)
12588 		return -1;
12589 	return i;
12590 }
12591 
12592 /** Complete available ports. */
12593 static int
12594 comp_port(struct context *ctx, const struct token *token,
12595 	  unsigned int ent, char *buf, unsigned int size)
12596 {
12597 	unsigned int i = 0;
12598 	portid_t p;
12599 
12600 	(void)ctx;
12601 	(void)token;
12602 	RTE_ETH_FOREACH_DEV(p) {
12603 		if (buf && i == ent)
12604 			return snprintf(buf, size, "%u", p);
12605 		++i;
12606 	}
12607 	if (buf)
12608 		return -1;
12609 	return i;
12610 }
12611 
12612 /** Complete available rule IDs. */
12613 static int
12614 comp_rule_id(struct context *ctx, const struct token *token,
12615 	     unsigned int ent, char *buf, unsigned int size)
12616 {
12617 	unsigned int i = 0;
12618 	struct rte_port *port;
12619 	struct port_flow *pf;
12620 
12621 	(void)token;
12622 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12623 	    ctx->port == (portid_t)RTE_PORT_ALL)
12624 		return -1;
12625 	port = &ports[ctx->port];
12626 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12627 		if (buf && i == ent)
12628 			return snprintf(buf, size, "%"PRIu64, pf->id);
12629 		++i;
12630 	}
12631 	if (buf)
12632 		return -1;
12633 	return i;
12634 }
12635 
12636 /** Complete operation for compare match item. */
12637 static int
12638 comp_set_compare_op(struct context *ctx, const struct token *token,
12639 		    unsigned int ent, char *buf, unsigned int size)
12640 {
12641 	RTE_SET_USED(ctx);
12642 	RTE_SET_USED(token);
12643 	if (!buf)
12644 		return RTE_DIM(compare_ops);
12645 	if (ent < RTE_DIM(compare_ops) - 1)
12646 		return strlcpy(buf, compare_ops[ent], size);
12647 	return -1;
12648 }
12649 
12650 /** Complete field id for compare match item. */
12651 static int
12652 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12653 			  unsigned int ent, char *buf, unsigned int size)
12654 {
12655 	const char *name;
12656 
12657 	RTE_SET_USED(token);
12658 	if (!buf)
12659 		return RTE_DIM(flow_field_ids);
12660 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12661 		return -1;
12662 	name = flow_field_ids[ent];
12663 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12664 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12665 		return strlcpy(buf, name, size);
12666 	return -1;
12667 }
12668 
12669 /** Complete type field for RSS action. */
12670 static int
12671 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12672 			unsigned int ent, char *buf, unsigned int size)
12673 {
12674 	unsigned int i;
12675 
12676 	(void)ctx;
12677 	(void)token;
12678 	for (i = 0; rss_type_table[i].str; ++i)
12679 		;
12680 	if (!buf)
12681 		return i + 1;
12682 	if (ent < i)
12683 		return strlcpy(buf, rss_type_table[ent].str, size);
12684 	if (ent == i)
12685 		return snprintf(buf, size, "end");
12686 	return -1;
12687 }
12688 
12689 /** Complete queue field for RSS action. */
12690 static int
12691 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12692 			 unsigned int ent, char *buf, unsigned int size)
12693 {
12694 	(void)ctx;
12695 	(void)token;
12696 	if (!buf)
12697 		return nb_rxq + 1;
12698 	if (ent < nb_rxq)
12699 		return snprintf(buf, size, "%u", ent);
12700 	if (ent == nb_rxq)
12701 		return snprintf(buf, size, "end");
12702 	return -1;
12703 }
12704 
12705 /** Complete index number for set raw_encap/raw_decap commands. */
12706 static int
12707 comp_set_raw_index(struct context *ctx, const struct token *token,
12708 		   unsigned int ent, char *buf, unsigned int size)
12709 {
12710 	uint16_t idx = 0;
12711 	uint16_t nb = 0;
12712 
12713 	RTE_SET_USED(ctx);
12714 	RTE_SET_USED(token);
12715 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12716 		if (buf && idx == ent)
12717 			return snprintf(buf, size, "%u", idx);
12718 		++nb;
12719 	}
12720 	return nb;
12721 }
12722 
12723 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12724 static int
12725 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12726 			unsigned int ent, char *buf, unsigned int size)
12727 {
12728 	uint16_t idx = 0;
12729 	uint16_t nb = 0;
12730 
12731 	RTE_SET_USED(ctx);
12732 	RTE_SET_USED(token);
12733 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12734 		if (buf && idx == ent)
12735 			return snprintf(buf, size, "%u", idx);
12736 		++nb;
12737 	}
12738 	return nb;
12739 }
12740 
12741 /** Complete index number for set raw_encap/raw_decap commands. */
12742 static int
12743 comp_set_sample_index(struct context *ctx, const struct token *token,
12744 		   unsigned int ent, char *buf, unsigned int size)
12745 {
12746 	uint16_t idx = 0;
12747 	uint16_t nb = 0;
12748 
12749 	RTE_SET_USED(ctx);
12750 	RTE_SET_USED(token);
12751 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12752 		if (buf && idx == ent)
12753 			return snprintf(buf, size, "%u", idx);
12754 		++nb;
12755 	}
12756 	return nb;
12757 }
12758 
12759 /** Complete operation for modify_field command. */
12760 static int
12761 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12762 		   unsigned int ent, char *buf, unsigned int size)
12763 {
12764 	RTE_SET_USED(ctx);
12765 	RTE_SET_USED(token);
12766 	if (!buf)
12767 		return RTE_DIM(modify_field_ops);
12768 	if (ent < RTE_DIM(modify_field_ops) - 1)
12769 		return strlcpy(buf, modify_field_ops[ent], size);
12770 	return -1;
12771 }
12772 
12773 /** Complete field id for modify_field command. */
12774 static int
12775 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12776 		   unsigned int ent, char *buf, unsigned int size)
12777 {
12778 	const char *name;
12779 
12780 	RTE_SET_USED(token);
12781 	if (!buf)
12782 		return RTE_DIM(flow_field_ids);
12783 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12784 		return -1;
12785 	name = flow_field_ids[ent];
12786 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12787 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12788 		return strlcpy(buf, name, size);
12789 	return -1;
12790 }
12791 
12792 /** Complete available pattern template IDs. */
12793 static int
12794 comp_pattern_template_id(struct context *ctx, const struct token *token,
12795 			 unsigned int ent, char *buf, unsigned int size)
12796 {
12797 	unsigned int i = 0;
12798 	struct rte_port *port;
12799 	struct port_template *pt;
12800 
12801 	(void)token;
12802 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12803 	    ctx->port == (portid_t)RTE_PORT_ALL)
12804 		return -1;
12805 	port = &ports[ctx->port];
12806 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12807 		if (buf && i == ent)
12808 			return snprintf(buf, size, "%u", pt->id);
12809 		++i;
12810 	}
12811 	if (buf)
12812 		return -1;
12813 	return i;
12814 }
12815 
12816 /** Complete available actions template IDs. */
12817 static int
12818 comp_actions_template_id(struct context *ctx, const struct token *token,
12819 			 unsigned int ent, char *buf, unsigned int size)
12820 {
12821 	unsigned int i = 0;
12822 	struct rte_port *port;
12823 	struct port_template *pt;
12824 
12825 	(void)token;
12826 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12827 	    ctx->port == (portid_t)RTE_PORT_ALL)
12828 		return -1;
12829 	port = &ports[ctx->port];
12830 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12831 		if (buf && i == ent)
12832 			return snprintf(buf, size, "%u", pt->id);
12833 		++i;
12834 	}
12835 	if (buf)
12836 		return -1;
12837 	return i;
12838 }
12839 
12840 /** Complete available table IDs. */
12841 static int
12842 comp_table_id(struct context *ctx, const struct token *token,
12843 	      unsigned int ent, char *buf, unsigned int size)
12844 {
12845 	unsigned int i = 0;
12846 	struct rte_port *port;
12847 	struct port_table *pt;
12848 
12849 	(void)token;
12850 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12851 	    ctx->port == (portid_t)RTE_PORT_ALL)
12852 		return -1;
12853 	port = &ports[ctx->port];
12854 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12855 		if (buf && i == ent)
12856 			return snprintf(buf, size, "%u", pt->id);
12857 		++i;
12858 	}
12859 	if (buf)
12860 		return -1;
12861 	return i;
12862 }
12863 
12864 /** Complete available queue IDs. */
12865 static int
12866 comp_queue_id(struct context *ctx, const struct token *token,
12867 	      unsigned int ent, char *buf, unsigned int size)
12868 {
12869 	unsigned int i = 0;
12870 	struct rte_port *port;
12871 
12872 	(void)token;
12873 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12874 	    ctx->port == (portid_t)RTE_PORT_ALL)
12875 		return -1;
12876 	port = &ports[ctx->port];
12877 	for (i = 0; i < port->queue_nb; i++) {
12878 		if (buf && i == ent)
12879 			return snprintf(buf, size, "%u", i);
12880 	}
12881 	if (buf)
12882 		return -1;
12883 	return i;
12884 }
12885 
12886 static int
12887 comp_names_to_index(struct context *ctx, const struct token *token,
12888 		    unsigned int ent, char *buf, unsigned int size,
12889 		    const char *const names[], size_t names_size)
12890 {
12891 	RTE_SET_USED(ctx);
12892 	RTE_SET_USED(token);
12893 	if (!buf)
12894 		return names_size;
12895 	if (ent < names_size && names[ent] != NULL)
12896 		return rte_strscpy(buf, names[ent], size);
12897 	return -1;
12898 
12899 }
12900 
12901 /** Complete available Meter colors. */
12902 static int
12903 comp_meter_color(struct context *ctx, const struct token *token,
12904 		 unsigned int ent, char *buf, unsigned int size)
12905 {
12906 	RTE_SET_USED(ctx);
12907 	RTE_SET_USED(token);
12908 	if (!buf)
12909 		return RTE_DIM(meter_colors);
12910 	if (ent < RTE_DIM(meter_colors) - 1)
12911 		return strlcpy(buf, meter_colors[ent], size);
12912 	return -1;
12913 }
12914 
12915 /** Complete available Insertion Table types. */
12916 static int
12917 comp_insertion_table_type(struct context *ctx, const struct token *token,
12918 			  unsigned int ent, char *buf, unsigned int size)
12919 {
12920 	RTE_SET_USED(ctx);
12921 	RTE_SET_USED(token);
12922 	if (!buf)
12923 		return RTE_DIM(table_insertion_types);
12924 	if (ent < RTE_DIM(table_insertion_types) - 1)
12925 		return rte_strscpy(buf, table_insertion_types[ent], size);
12926 	return -1;
12927 }
12928 
12929 /** Complete available Hash Calculation Table types. */
12930 static int
12931 comp_hash_table_type(struct context *ctx, const struct token *token,
12932 		     unsigned int ent, char *buf, unsigned int size)
12933 {
12934 	RTE_SET_USED(ctx);
12935 	RTE_SET_USED(token);
12936 	if (!buf)
12937 		return RTE_DIM(table_hash_funcs);
12938 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12939 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12940 	return -1;
12941 }
12942 
12943 static int
12944 comp_quota_state_name(struct context *ctx, const struct token *token,
12945 		      unsigned int ent, char *buf, unsigned int size)
12946 {
12947 	return comp_names_to_index(ctx, token, ent, buf, size,
12948 				   quota_state_names,
12949 				   RTE_DIM(quota_state_names));
12950 }
12951 
12952 static int
12953 comp_quota_mode_name(struct context *ctx, const struct token *token,
12954 		     unsigned int ent, char *buf, unsigned int size)
12955 {
12956 	return comp_names_to_index(ctx, token, ent, buf, size,
12957 				   quota_mode_names,
12958 				   RTE_DIM(quota_mode_names));
12959 }
12960 
12961 static int
12962 comp_quota_update_name(struct context *ctx, const struct token *token,
12963 		       unsigned int ent, char *buf, unsigned int size)
12964 {
12965 	return comp_names_to_index(ctx, token, ent, buf, size,
12966 				   quota_update_names,
12967 				   RTE_DIM(quota_update_names));
12968 }
12969 
12970 static int
12971 comp_qu_mode_name(struct context *ctx, const struct token *token,
12972 		  unsigned int ent, char *buf, unsigned int size)
12973 {
12974 	return comp_names_to_index(ctx, token, ent, buf, size,
12975 				   query_update_mode_names,
12976 				   RTE_DIM(query_update_mode_names));
12977 }
12978 
12979 /** Internal context. */
12980 static struct context cmd_flow_context;
12981 
12982 /** Global parser instance (cmdline API). */
12983 cmdline_parse_inst_t cmd_flow;
12984 cmdline_parse_inst_t cmd_set_raw;
12985 
12986 /** Initialize context. */
12987 static void
12988 cmd_flow_context_init(struct context *ctx)
12989 {
12990 	/* A full memset() is not necessary. */
12991 	ctx->curr = ZERO;
12992 	ctx->prev = ZERO;
12993 	ctx->next_num = 0;
12994 	ctx->args_num = 0;
12995 	ctx->eol = 0;
12996 	ctx->last = 0;
12997 	ctx->port = 0;
12998 	ctx->objdata = 0;
12999 	ctx->object = NULL;
13000 	ctx->objmask = NULL;
13001 }
13002 
13003 /** Parse a token (cmdline API). */
13004 static int
13005 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
13006 	       unsigned int size)
13007 {
13008 	struct context *ctx = &cmd_flow_context;
13009 	const struct token *token;
13010 	const enum index *list;
13011 	int len;
13012 	int i;
13013 
13014 	(void)hdr;
13015 	token = &token_list[ctx->curr];
13016 	/* Check argument length. */
13017 	ctx->eol = 0;
13018 	ctx->last = 1;
13019 	for (len = 0; src[len]; ++len)
13020 		if (src[len] == '#' || isspace(src[len]))
13021 			break;
13022 	if (!len)
13023 		return -1;
13024 	/* Last argument and EOL detection. */
13025 	for (i = len; src[i]; ++i)
13026 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
13027 			break;
13028 		else if (!isspace(src[i])) {
13029 			ctx->last = 0;
13030 			break;
13031 		}
13032 	for (; src[i]; ++i)
13033 		if (src[i] == '\r' || src[i] == '\n') {
13034 			ctx->eol = 1;
13035 			break;
13036 		}
13037 	/* Initialize context if necessary. */
13038 	if (!ctx->next_num) {
13039 		if (!token->next)
13040 			return 0;
13041 		ctx->next[ctx->next_num++] = token->next[0];
13042 	}
13043 	/* Process argument through candidates. */
13044 	ctx->prev = ctx->curr;
13045 	list = ctx->next[ctx->next_num - 1];
13046 	for (i = 0; list[i]; ++i) {
13047 		const struct token *next = &token_list[list[i]];
13048 		int tmp;
13049 
13050 		ctx->curr = list[i];
13051 		if (next->call)
13052 			tmp = next->call(ctx, next, src, len, result, size);
13053 		else
13054 			tmp = parse_default(ctx, next, src, len, result, size);
13055 		if (tmp == -1 || tmp != len)
13056 			continue;
13057 		token = next;
13058 		break;
13059 	}
13060 	if (!list[i])
13061 		return -1;
13062 	--ctx->next_num;
13063 	/* Push subsequent tokens if any. */
13064 	if (token->next)
13065 		for (i = 0; token->next[i]; ++i) {
13066 			if (ctx->next_num == RTE_DIM(ctx->next))
13067 				return -1;
13068 			ctx->next[ctx->next_num++] = token->next[i];
13069 		}
13070 	/* Push arguments if any. */
13071 	if (token->args)
13072 		for (i = 0; token->args[i]; ++i) {
13073 			if (ctx->args_num == RTE_DIM(ctx->args))
13074 				return -1;
13075 			ctx->args[ctx->args_num++] = token->args[i];
13076 		}
13077 	return len;
13078 }
13079 
13080 int
13081 flow_parse(const char *src, void *result, unsigned int size,
13082 	   struct rte_flow_attr **attr,
13083 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
13084 {
13085 	int ret;
13086 	struct context saved_flow_ctx = cmd_flow_context;
13087 
13088 	cmd_flow_context_init(&cmd_flow_context);
13089 	do {
13090 		ret = cmd_flow_parse(NULL, src, result, size);
13091 		if (ret > 0) {
13092 			src += ret;
13093 			while (isspace(*src))
13094 				src++;
13095 		}
13096 	} while (ret > 0 && strlen(src));
13097 	cmd_flow_context = saved_flow_ctx;
13098 	*attr = &((struct buffer *)result)->args.vc.attr;
13099 	*pattern = ((struct buffer *)result)->args.vc.pattern;
13100 	*actions = ((struct buffer *)result)->args.vc.actions;
13101 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
13102 }
13103 
13104 /** Return number of completion entries (cmdline API). */
13105 static int
13106 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
13107 {
13108 	struct context *ctx = &cmd_flow_context;
13109 	const struct token *token = &token_list[ctx->curr];
13110 	const enum index *list;
13111 	int i;
13112 
13113 	(void)hdr;
13114 	/* Count number of tokens in current list. */
13115 	if (ctx->next_num)
13116 		list = ctx->next[ctx->next_num - 1];
13117 	else
13118 		list = token->next[0];
13119 	for (i = 0; list[i]; ++i)
13120 		;
13121 	if (!i)
13122 		return 0;
13123 	/*
13124 	 * If there is a single token, use its completion callback, otherwise
13125 	 * return the number of entries.
13126 	 */
13127 	token = &token_list[list[0]];
13128 	if (i == 1 && token->comp) {
13129 		/* Save index for cmd_flow_get_help(). */
13130 		ctx->prev = list[0];
13131 		return token->comp(ctx, token, 0, NULL, 0);
13132 	}
13133 	return i;
13134 }
13135 
13136 /** Return a completion entry (cmdline API). */
13137 static int
13138 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
13139 			  char *dst, unsigned int size)
13140 {
13141 	struct context *ctx = &cmd_flow_context;
13142 	const struct token *token = &token_list[ctx->curr];
13143 	const enum index *list;
13144 	int i;
13145 
13146 	(void)hdr;
13147 	/* Count number of tokens in current list. */
13148 	if (ctx->next_num)
13149 		list = ctx->next[ctx->next_num - 1];
13150 	else
13151 		list = token->next[0];
13152 	for (i = 0; list[i]; ++i)
13153 		;
13154 	if (!i)
13155 		return -1;
13156 	/* If there is a single token, use its completion callback. */
13157 	token = &token_list[list[0]];
13158 	if (i == 1 && token->comp) {
13159 		/* Save index for cmd_flow_get_help(). */
13160 		ctx->prev = list[0];
13161 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
13162 	}
13163 	/* Otherwise make sure the index is valid and use defaults. */
13164 	if (index >= i)
13165 		return -1;
13166 	token = &token_list[list[index]];
13167 	strlcpy(dst, token->name, size);
13168 	/* Save index for cmd_flow_get_help(). */
13169 	ctx->prev = list[index];
13170 	return 0;
13171 }
13172 
13173 /** Populate help strings for current token (cmdline API). */
13174 static int
13175 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13176 {
13177 	struct context *ctx = &cmd_flow_context;
13178 	const struct token *token = &token_list[ctx->prev];
13179 
13180 	(void)hdr;
13181 	if (!size)
13182 		return -1;
13183 	/* Set token type and update global help with details. */
13184 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13185 	if (token->help)
13186 		cmd_flow.help_str = token->help;
13187 	else
13188 		cmd_flow.help_str = token->name;
13189 	return 0;
13190 }
13191 
13192 /** Token definition template (cmdline API). */
13193 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13194 	.ops = &(struct cmdline_token_ops){
13195 		.parse = cmd_flow_parse,
13196 		.complete_get_nb = cmd_flow_complete_get_nb,
13197 		.complete_get_elt = cmd_flow_complete_get_elt,
13198 		.get_help = cmd_flow_get_help,
13199 	},
13200 	.offset = 0,
13201 };
13202 
13203 /** Populate the next dynamic token. */
13204 static void
13205 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13206 	     cmdline_parse_token_hdr_t **hdr_inst)
13207 {
13208 	struct context *ctx = &cmd_flow_context;
13209 
13210 	/* Always reinitialize context before requesting the first token. */
13211 	if (!(hdr_inst - cmd_flow.tokens))
13212 		cmd_flow_context_init(ctx);
13213 	/* Return NULL when no more tokens are expected. */
13214 	if (!ctx->next_num && ctx->curr) {
13215 		*hdr = NULL;
13216 		return;
13217 	}
13218 	/* Determine if command should end here. */
13219 	if (ctx->eol && ctx->last && ctx->next_num) {
13220 		const enum index *list = ctx->next[ctx->next_num - 1];
13221 		int i;
13222 
13223 		for (i = 0; list[i]; ++i) {
13224 			if (list[i] != END)
13225 				continue;
13226 			*hdr = NULL;
13227 			return;
13228 		}
13229 	}
13230 	*hdr = &cmd_flow_token_hdr;
13231 }
13232 
13233 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13234 	SLIST_HEAD_INITIALIZER();
13235 
13236 static void
13237 indirect_action_flow_conf_create(const struct buffer *in)
13238 {
13239 	int len, ret;
13240 	uint32_t i;
13241 	struct indlst_conf *indlst_conf = NULL;
13242 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13243 	struct rte_flow_action *src = in->args.vc.actions;
13244 
13245 	if (!in->args.vc.actions_n)
13246 		goto end;
13247 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13248 	if (len <= 0)
13249 		goto end;
13250 	len = RTE_ALIGN(len, 16);
13251 
13252 	indlst_conf = calloc(1, base + len +
13253 			     in->args.vc.actions_n * sizeof(uintptr_t));
13254 	if (!indlst_conf)
13255 		goto end;
13256 	indlst_conf->id = in->args.vc.attr.group;
13257 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13258 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13259 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13260 			    len, src, NULL);
13261 	if (ret <= 0) {
13262 		free(indlst_conf);
13263 		indlst_conf = NULL;
13264 		goto end;
13265 	}
13266 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13267 	for (i = 0; i < indlst_conf->conf_num; i++)
13268 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13269 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13270 end:
13271 	if (indlst_conf)
13272 		printf("created indirect action list configuration %u\n",
13273 		       in->args.vc.attr.group);
13274 	else
13275 		printf("cannot create indirect action list configuration %u\n",
13276 		       in->args.vc.attr.group);
13277 }
13278 
13279 static const struct indlst_conf *
13280 indirect_action_list_conf_get(uint32_t conf_id)
13281 {
13282 	const struct indlst_conf *conf;
13283 
13284 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13285 		if (conf->id == conf_id)
13286 			return conf;
13287 	}
13288 	return NULL;
13289 }
13290 
13291 /** Dispatch parsed buffer to function calls. */
13292 static void
13293 cmd_flow_parsed(const struct buffer *in)
13294 {
13295 	switch (in->command) {
13296 	case INFO:
13297 		port_flow_get_info(in->port);
13298 		break;
13299 	case CONFIGURE:
13300 		port_flow_configure(in->port,
13301 				    &in->args.configure.port_attr,
13302 				    in->args.configure.nb_queue,
13303 				    &in->args.configure.queue_attr);
13304 		break;
13305 	case PATTERN_TEMPLATE_CREATE:
13306 		port_flow_pattern_template_create(in->port,
13307 				in->args.vc.pat_templ_id,
13308 				&((const struct rte_flow_pattern_template_attr) {
13309 					.relaxed_matching = in->args.vc.attr.reserved,
13310 					.ingress = in->args.vc.attr.ingress,
13311 					.egress = in->args.vc.attr.egress,
13312 					.transfer = in->args.vc.attr.transfer,
13313 				}),
13314 				in->args.vc.pattern);
13315 		break;
13316 	case PATTERN_TEMPLATE_DESTROY:
13317 		port_flow_pattern_template_destroy(in->port,
13318 				in->args.templ_destroy.template_id_n,
13319 				in->args.templ_destroy.template_id);
13320 		break;
13321 	case ACTIONS_TEMPLATE_CREATE:
13322 		port_flow_actions_template_create(in->port,
13323 				in->args.vc.act_templ_id,
13324 				&((const struct rte_flow_actions_template_attr) {
13325 					.ingress = in->args.vc.attr.ingress,
13326 					.egress = in->args.vc.attr.egress,
13327 					.transfer = in->args.vc.attr.transfer,
13328 				}),
13329 				in->args.vc.actions,
13330 				in->args.vc.masks);
13331 		break;
13332 	case ACTIONS_TEMPLATE_DESTROY:
13333 		port_flow_actions_template_destroy(in->port,
13334 				in->args.templ_destroy.template_id_n,
13335 				in->args.templ_destroy.template_id);
13336 		break;
13337 	case TABLE_CREATE:
13338 		port_flow_template_table_create(in->port, in->args.table.id,
13339 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13340 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13341 			in->args.table.act_templ_id);
13342 		break;
13343 	case TABLE_DESTROY:
13344 		port_flow_template_table_destroy(in->port,
13345 					in->args.table_destroy.table_id_n,
13346 					in->args.table_destroy.table_id);
13347 		break;
13348 	case TABLE_RESIZE_COMPLETE:
13349 		port_flow_template_table_resize_complete
13350 			(in->port, in->args.table_destroy.table_id[0]);
13351 		break;
13352 	case GROUP_SET_MISS_ACTIONS:
13353 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13354 						  in->args.vc.actions);
13355 		break;
13356 	case TABLE_RESIZE:
13357 		port_flow_template_table_resize(in->port, in->args.table.id,
13358 						in->args.table.attr.nb_flows);
13359 		break;
13360 	case QUEUE_CREATE:
13361 		port_queue_flow_create(in->port, in->queue, in->postpone,
13362 			in->args.vc.table_id, in->args.vc.rule_id,
13363 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13364 			in->args.vc.pattern, in->args.vc.actions);
13365 		break;
13366 	case QUEUE_DESTROY:
13367 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13368 					in->args.destroy.rule_n,
13369 					in->args.destroy.rule);
13370 		break;
13371 	case QUEUE_FLOW_UPDATE_RESIZED:
13372 		port_queue_flow_update_resized(in->port, in->queue,
13373 					       in->postpone,
13374 					       in->args.destroy.rule[0]);
13375 		break;
13376 	case QUEUE_UPDATE:
13377 		port_queue_flow_update(in->port, in->queue, in->postpone,
13378 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13379 				in->args.vc.actions);
13380 		break;
13381 	case PUSH:
13382 		port_queue_flow_push(in->port, in->queue);
13383 		break;
13384 	case PULL:
13385 		port_queue_flow_pull(in->port, in->queue);
13386 		break;
13387 	case HASH:
13388 		if (!in->args.vc.encap_hash)
13389 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13390 					    in->args.vc.pat_templ_id,
13391 					    in->args.vc.pattern);
13392 		else
13393 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13394 						  in->args.vc.pattern);
13395 		break;
13396 	case QUEUE_AGED:
13397 		port_queue_flow_aged(in->port, in->queue,
13398 				     in->args.aged.destroy);
13399 		break;
13400 	case QUEUE_INDIRECT_ACTION_CREATE:
13401 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13402 		port_queue_action_handle_create(
13403 				in->port, in->queue, in->postpone,
13404 				in->args.vc.attr.group,
13405 				in->command == QUEUE_INDIRECT_ACTION_LIST_CREATE,
13406 				&((const struct rte_flow_indir_action_conf) {
13407 					.ingress = in->args.vc.attr.ingress,
13408 					.egress = in->args.vc.attr.egress,
13409 					.transfer = in->args.vc.attr.transfer,
13410 				}),
13411 				in->args.vc.actions);
13412 		break;
13413 	case QUEUE_INDIRECT_ACTION_DESTROY:
13414 		port_queue_action_handle_destroy(in->port,
13415 					   in->queue, in->postpone,
13416 					   in->args.ia_destroy.action_id_n,
13417 					   in->args.ia_destroy.action_id);
13418 		break;
13419 	case QUEUE_INDIRECT_ACTION_UPDATE:
13420 		port_queue_action_handle_update(in->port,
13421 						in->queue, in->postpone,
13422 						in->args.vc.attr.group,
13423 						in->args.vc.actions);
13424 		break;
13425 	case QUEUE_INDIRECT_ACTION_QUERY:
13426 		port_queue_action_handle_query(in->port,
13427 					       in->queue, in->postpone,
13428 					       in->args.ia.action_id);
13429 		break;
13430 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13431 		port_queue_action_handle_query_update(in->port, in->queue,
13432 						      in->postpone,
13433 						      in->args.ia.action_id,
13434 						      in->args.ia.qu_mode,
13435 						      in->args.vc.actions);
13436 		break;
13437 	case INDIRECT_ACTION_CREATE:
13438 	case INDIRECT_ACTION_LIST_CREATE:
13439 		port_action_handle_create(
13440 				in->port, in->args.vc.attr.group,
13441 				in->command == INDIRECT_ACTION_LIST_CREATE,
13442 				&((const struct rte_flow_indir_action_conf) {
13443 					.ingress = in->args.vc.attr.ingress,
13444 					.egress = in->args.vc.attr.egress,
13445 					.transfer = in->args.vc.attr.transfer,
13446 				}),
13447 				in->args.vc.actions);
13448 		break;
13449 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13450 		indirect_action_flow_conf_create(in);
13451 		break;
13452 	case INDIRECT_ACTION_DESTROY:
13453 		port_action_handle_destroy(in->port,
13454 					   in->args.ia_destroy.action_id_n,
13455 					   in->args.ia_destroy.action_id);
13456 		break;
13457 	case INDIRECT_ACTION_UPDATE:
13458 		port_action_handle_update(in->port, in->args.vc.attr.group,
13459 					  in->args.vc.actions);
13460 		break;
13461 	case INDIRECT_ACTION_QUERY:
13462 		port_action_handle_query(in->port, in->args.ia.action_id);
13463 		break;
13464 	case INDIRECT_ACTION_QUERY_UPDATE:
13465 		port_action_handle_query_update(in->port,
13466 						in->args.ia.action_id,
13467 						in->args.ia.qu_mode,
13468 						in->args.vc.actions);
13469 		break;
13470 	case VALIDATE:
13471 		port_flow_validate(in->port, &in->args.vc.attr,
13472 				   in->args.vc.pattern, in->args.vc.actions,
13473 				   &in->args.vc.tunnel_ops);
13474 		break;
13475 	case CREATE:
13476 		port_flow_create(in->port, &in->args.vc.attr,
13477 				 in->args.vc.pattern, in->args.vc.actions,
13478 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13479 		break;
13480 	case DESTROY:
13481 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13482 				  in->args.destroy.rule,
13483 				  in->args.destroy.is_user_id);
13484 		break;
13485 	case UPDATE:
13486 		port_flow_update(in->port, in->args.vc.rule_id,
13487 				 in->args.vc.actions, in->args.vc.user_id);
13488 		break;
13489 	case FLUSH:
13490 		port_flow_flush(in->port);
13491 		break;
13492 	case DUMP_ONE:
13493 	case DUMP_ALL:
13494 		port_flow_dump(in->port, in->args.dump.mode,
13495 				in->args.dump.rule, in->args.dump.file,
13496 				in->args.dump.is_user_id);
13497 		break;
13498 	case QUERY:
13499 		port_flow_query(in->port, in->args.query.rule,
13500 				&in->args.query.action,
13501 				in->args.query.is_user_id);
13502 		break;
13503 	case LIST:
13504 		port_flow_list(in->port, in->args.list.group_n,
13505 			       in->args.list.group);
13506 		break;
13507 	case ISOLATE:
13508 		port_flow_isolate(in->port, in->args.isolate.set);
13509 		break;
13510 	case AGED:
13511 		port_flow_aged(in->port, in->args.aged.destroy);
13512 		break;
13513 	case TUNNEL_CREATE:
13514 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13515 		break;
13516 	case TUNNEL_DESTROY:
13517 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13518 		break;
13519 	case TUNNEL_LIST:
13520 		port_flow_tunnel_list(in->port);
13521 		break;
13522 	case ACTION_POL_G:
13523 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13524 					in->args.vc.actions);
13525 		break;
13526 	case FLEX_ITEM_CREATE:
13527 		flex_item_create(in->port, in->args.flex.token,
13528 				 in->args.flex.filename);
13529 		break;
13530 	case FLEX_ITEM_DESTROY:
13531 		flex_item_destroy(in->port, in->args.flex.token);
13532 		break;
13533 	default:
13534 		break;
13535 	}
13536 	fflush(stdout);
13537 }
13538 
13539 /** Token generator and output processing callback (cmdline API). */
13540 static void
13541 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13542 {
13543 	if (cl == NULL)
13544 		cmd_flow_tok(arg0, arg2);
13545 	else
13546 		cmd_flow_parsed(arg0);
13547 }
13548 
13549 /** Global parser instance (cmdline API). */
13550 cmdline_parse_inst_t cmd_flow = {
13551 	.f = cmd_flow_cb,
13552 	.data = NULL, /**< Unused. */
13553 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13554 	.tokens = {
13555 		NULL,
13556 	}, /**< Tokens are returned by cmd_flow_tok(). */
13557 };
13558 
13559 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13560 
13561 static void
13562 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13563 {
13564 	struct rte_ipv4_hdr *ipv4;
13565 	struct rte_ether_hdr *eth;
13566 	struct rte_ipv6_hdr *ipv6;
13567 	struct rte_vxlan_hdr *vxlan;
13568 	struct rte_vxlan_gpe_hdr *gpe;
13569 	struct rte_flow_item_nvgre *nvgre;
13570 	uint32_t ipv6_vtc_flow;
13571 
13572 	switch (item->type) {
13573 	case RTE_FLOW_ITEM_TYPE_ETH:
13574 		eth = (struct rte_ether_hdr *)buf;
13575 		if (next_proto)
13576 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13577 		break;
13578 	case RTE_FLOW_ITEM_TYPE_IPV4:
13579 		ipv4 = (struct rte_ipv4_hdr *)buf;
13580 		if (!ipv4->version_ihl)
13581 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13582 		if (next_proto && ipv4->next_proto_id == 0)
13583 			ipv4->next_proto_id = (uint8_t)next_proto;
13584 		break;
13585 	case RTE_FLOW_ITEM_TYPE_IPV6:
13586 		ipv6 = (struct rte_ipv6_hdr *)buf;
13587 		if (next_proto && ipv6->proto == 0)
13588 			ipv6->proto = (uint8_t)next_proto;
13589 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13590 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13591 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13592 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13593 		break;
13594 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13595 		vxlan = (struct rte_vxlan_hdr *)buf;
13596 		vxlan->vx_flags = 0x08;
13597 		break;
13598 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13599 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13600 		gpe->vx_flags = 0x0C;
13601 		break;
13602 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13603 		nvgre = (struct rte_flow_item_nvgre *)buf;
13604 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13605 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13606 		break;
13607 	default:
13608 		break;
13609 	}
13610 }
13611 
13612 /** Helper of get item's default mask. */
13613 static const void *
13614 flow_item_default_mask(const struct rte_flow_item *item)
13615 {
13616 	const void *mask = NULL;
13617 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13618 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13619 		.hdr = {
13620 			.next_hdr = 0xff,
13621 			.type = 0xff,
13622 			.segments_left = 0xff,
13623 		},
13624 	};
13625 
13626 	switch (item->type) {
13627 	case RTE_FLOW_ITEM_TYPE_ANY:
13628 		mask = &rte_flow_item_any_mask;
13629 		break;
13630 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13631 		mask = &rte_flow_item_port_id_mask;
13632 		break;
13633 	case RTE_FLOW_ITEM_TYPE_RAW:
13634 		mask = &rte_flow_item_raw_mask;
13635 		break;
13636 	case RTE_FLOW_ITEM_TYPE_ETH:
13637 		mask = &rte_flow_item_eth_mask;
13638 		break;
13639 	case RTE_FLOW_ITEM_TYPE_VLAN:
13640 		mask = &rte_flow_item_vlan_mask;
13641 		break;
13642 	case RTE_FLOW_ITEM_TYPE_IPV4:
13643 		mask = &rte_flow_item_ipv4_mask;
13644 		break;
13645 	case RTE_FLOW_ITEM_TYPE_IPV6:
13646 		mask = &rte_flow_item_ipv6_mask;
13647 		break;
13648 	case RTE_FLOW_ITEM_TYPE_ICMP:
13649 		mask = &rte_flow_item_icmp_mask;
13650 		break;
13651 	case RTE_FLOW_ITEM_TYPE_UDP:
13652 		mask = &rte_flow_item_udp_mask;
13653 		break;
13654 	case RTE_FLOW_ITEM_TYPE_TCP:
13655 		mask = &rte_flow_item_tcp_mask;
13656 		break;
13657 	case RTE_FLOW_ITEM_TYPE_SCTP:
13658 		mask = &rte_flow_item_sctp_mask;
13659 		break;
13660 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13661 		mask = &rte_flow_item_vxlan_mask;
13662 		break;
13663 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13664 		mask = &rte_flow_item_vxlan_gpe_mask;
13665 		break;
13666 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13667 		mask = &rte_flow_item_e_tag_mask;
13668 		break;
13669 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13670 		mask = &rte_flow_item_nvgre_mask;
13671 		break;
13672 	case RTE_FLOW_ITEM_TYPE_MPLS:
13673 		mask = &rte_flow_item_mpls_mask;
13674 		break;
13675 	case RTE_FLOW_ITEM_TYPE_GRE:
13676 		mask = &rte_flow_item_gre_mask;
13677 		break;
13678 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13679 		mask = &gre_key_default_mask;
13680 		break;
13681 	case RTE_FLOW_ITEM_TYPE_META:
13682 		mask = &rte_flow_item_meta_mask;
13683 		break;
13684 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13685 		mask = &rte_flow_item_random_mask;
13686 		break;
13687 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13688 		mask = &rte_flow_item_fuzzy_mask;
13689 		break;
13690 	case RTE_FLOW_ITEM_TYPE_GTP:
13691 		mask = &rte_flow_item_gtp_mask;
13692 		break;
13693 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13694 		mask = &rte_flow_item_gtp_psc_mask;
13695 		break;
13696 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13697 		mask = &rte_flow_item_geneve_mask;
13698 		break;
13699 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13700 		mask = &rte_flow_item_geneve_opt_mask;
13701 		break;
13702 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13703 		mask = &rte_flow_item_pppoe_proto_id_mask;
13704 		break;
13705 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13706 		mask = &rte_flow_item_l2tpv3oip_mask;
13707 		break;
13708 	case RTE_FLOW_ITEM_TYPE_ESP:
13709 		mask = &rte_flow_item_esp_mask;
13710 		break;
13711 	case RTE_FLOW_ITEM_TYPE_AH:
13712 		mask = &rte_flow_item_ah_mask;
13713 		break;
13714 	case RTE_FLOW_ITEM_TYPE_PFCP:
13715 		mask = &rte_flow_item_pfcp_mask;
13716 		break;
13717 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13718 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13719 		mask = &rte_flow_item_ethdev_mask;
13720 		break;
13721 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13722 		mask = &rte_flow_item_l2tpv2_mask;
13723 		break;
13724 	case RTE_FLOW_ITEM_TYPE_PPP:
13725 		mask = &rte_flow_item_ppp_mask;
13726 		break;
13727 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13728 		mask = &rte_flow_item_meter_color_mask;
13729 		break;
13730 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13731 		mask = &ipv6_routing_ext_default_mask;
13732 		break;
13733 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13734 		mask = &rte_flow_item_aggr_affinity_mask;
13735 		break;
13736 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13737 		mask = &rte_flow_item_tx_queue_mask;
13738 		break;
13739 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13740 		mask = &rte_flow_item_ib_bth_mask;
13741 		break;
13742 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13743 		mask = &rte_flow_item_ptype_mask;
13744 		break;
13745 	default:
13746 		break;
13747 	}
13748 	return mask;
13749 }
13750 
13751 /** Dispatch parsed buffer to function calls. */
13752 static void
13753 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13754 {
13755 	uint32_t n = in->args.vc.pattern_n;
13756 	int i = 0;
13757 	struct rte_flow_item *item = NULL;
13758 	size_t size = 0;
13759 	uint8_t *data = NULL;
13760 	uint8_t *type = NULL;
13761 	size_t *total_size = NULL;
13762 	uint16_t idx = in->port; /* We borrow port field as index */
13763 	struct rte_flow_item_ipv6_routing_ext *ext;
13764 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13765 
13766 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13767 		   in->command == SET_IPV6_EXT_REMOVE);
13768 
13769 	if (in->command == SET_IPV6_EXT_REMOVE) {
13770 		if (n != 1 || in->args.vc.pattern->type !=
13771 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13772 			fprintf(stderr, "Error - Not supported item\n");
13773 			return;
13774 		}
13775 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13776 		item = in->args.vc.pattern;
13777 		ipv6_ext = item->spec;
13778 		*type = ipv6_ext->next_hdr;
13779 		return;
13780 	}
13781 
13782 	total_size = &ipv6_ext_push_confs[idx].size;
13783 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13784 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13785 
13786 	*total_size = 0;
13787 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13788 	for (i = n - 1 ; i >= 0; --i) {
13789 		item = in->args.vc.pattern + i;
13790 		switch (item->type) {
13791 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13792 			ipv6_ext = item->spec;
13793 			*type = ipv6_ext->next_hdr;
13794 			break;
13795 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13796 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13797 			if (!ext->hdr.hdr_len) {
13798 				size = sizeof(struct rte_ipv6_routing_ext) +
13799 				(ext->hdr.segments_left << 4);
13800 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13801 				/* Indicate no TLV once SRH. */
13802 				if (ext->hdr.type == 4)
13803 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13804 			} else {
13805 				size = sizeof(struct rte_ipv6_routing_ext) +
13806 				(ext->hdr.hdr_len << 3);
13807 			}
13808 			*total_size += size;
13809 			memcpy(data, ext, size);
13810 			break;
13811 		default:
13812 			fprintf(stderr, "Error - Not supported item\n");
13813 			goto error;
13814 		}
13815 	}
13816 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13817 	return;
13818 error:
13819 	*total_size = 0;
13820 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13821 }
13822 
13823 /** Dispatch parsed buffer to function calls. */
13824 static void
13825 cmd_set_raw_parsed_sample(const struct buffer *in)
13826 {
13827 	uint32_t n = in->args.vc.actions_n;
13828 	uint32_t i = 0;
13829 	struct rte_flow_action *action = NULL;
13830 	struct rte_flow_action *data = NULL;
13831 	const struct rte_flow_action_rss *rss = NULL;
13832 	size_t size = 0;
13833 	uint16_t idx = in->port; /* We borrow port field as index */
13834 	uint32_t max_size = sizeof(struct rte_flow_action) *
13835 						ACTION_SAMPLE_ACTIONS_NUM;
13836 
13837 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13838 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13839 	memset(data, 0x00, max_size);
13840 	for (; i <= n - 1; i++) {
13841 		action = in->args.vc.actions + i;
13842 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13843 			break;
13844 		switch (action->type) {
13845 		case RTE_FLOW_ACTION_TYPE_MARK:
13846 			size = sizeof(struct rte_flow_action_mark);
13847 			rte_memcpy(&sample_mark[idx],
13848 				(const void *)action->conf, size);
13849 			action->conf = &sample_mark[idx];
13850 			break;
13851 		case RTE_FLOW_ACTION_TYPE_COUNT:
13852 			size = sizeof(struct rte_flow_action_count);
13853 			rte_memcpy(&sample_count[idx],
13854 				(const void *)action->conf, size);
13855 			action->conf = &sample_count[idx];
13856 			break;
13857 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13858 			size = sizeof(struct rte_flow_action_queue);
13859 			rte_memcpy(&sample_queue[idx],
13860 				(const void *)action->conf, size);
13861 			action->conf = &sample_queue[idx];
13862 			break;
13863 		case RTE_FLOW_ACTION_TYPE_RSS:
13864 			size = sizeof(struct rte_flow_action_rss);
13865 			rss = action->conf;
13866 			rte_memcpy(&sample_rss_data[idx].conf,
13867 				   (const void *)rss, size);
13868 			if (rss->key_len && rss->key) {
13869 				sample_rss_data[idx].conf.key =
13870 						sample_rss_data[idx].key;
13871 				rte_memcpy((void *)((uintptr_t)
13872 					   sample_rss_data[idx].conf.key),
13873 					   (const void *)rss->key,
13874 					   sizeof(uint8_t) * rss->key_len);
13875 			}
13876 			if (rss->queue_num && rss->queue) {
13877 				sample_rss_data[idx].conf.queue =
13878 						sample_rss_data[idx].queue;
13879 				rte_memcpy((void *)((uintptr_t)
13880 					   sample_rss_data[idx].conf.queue),
13881 					   (const void *)rss->queue,
13882 					   sizeof(uint16_t) * rss->queue_num);
13883 			}
13884 			action->conf = &sample_rss_data[idx].conf;
13885 			break;
13886 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13887 			size = sizeof(struct rte_flow_action_raw_encap);
13888 			rte_memcpy(&sample_encap[idx],
13889 				(const void *)action->conf, size);
13890 			action->conf = &sample_encap[idx];
13891 			break;
13892 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13893 			size = sizeof(struct rte_flow_action_port_id);
13894 			rte_memcpy(&sample_port_id[idx],
13895 				(const void *)action->conf, size);
13896 			action->conf = &sample_port_id[idx];
13897 			break;
13898 		case RTE_FLOW_ACTION_TYPE_PF:
13899 			break;
13900 		case RTE_FLOW_ACTION_TYPE_VF:
13901 			size = sizeof(struct rte_flow_action_vf);
13902 			rte_memcpy(&sample_vf[idx],
13903 					(const void *)action->conf, size);
13904 			action->conf = &sample_vf[idx];
13905 			break;
13906 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13907 			size = sizeof(struct rte_flow_action_vxlan_encap);
13908 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13909 			action->conf = &sample_vxlan_encap[idx].conf;
13910 			break;
13911 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13912 			size = sizeof(struct rte_flow_action_nvgre_encap);
13913 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13914 			action->conf = &sample_nvgre_encap[idx];
13915 			break;
13916 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13917 			size = sizeof(struct rte_flow_action_ethdev);
13918 			rte_memcpy(&sample_port_representor[idx],
13919 					(const void *)action->conf, size);
13920 			action->conf = &sample_port_representor[idx];
13921 			break;
13922 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13923 			size = sizeof(struct rte_flow_action_ethdev);
13924 			rte_memcpy(&sample_represented_port[idx],
13925 					(const void *)action->conf, size);
13926 			action->conf = &sample_represented_port[idx];
13927 			break;
13928 		default:
13929 			fprintf(stderr, "Error - Not supported action\n");
13930 			return;
13931 		}
13932 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13933 		data++;
13934 	}
13935 }
13936 
13937 /** Dispatch parsed buffer to function calls. */
13938 static void
13939 cmd_set_raw_parsed(const struct buffer *in)
13940 {
13941 	uint32_t n = in->args.vc.pattern_n;
13942 	int i = 0;
13943 	struct rte_flow_item *item = NULL;
13944 	size_t size = 0;
13945 	uint8_t *data = NULL;
13946 	uint8_t *data_tail = NULL;
13947 	size_t *total_size = NULL;
13948 	uint16_t upper_layer = 0;
13949 	uint16_t proto = 0;
13950 	uint16_t idx = in->port; /* We borrow port field as index */
13951 	int gtp_psc = -1; /* GTP PSC option index. */
13952 	const void *src_spec;
13953 
13954 	if (in->command == SET_SAMPLE_ACTIONS)
13955 		return cmd_set_raw_parsed_sample(in);
13956 	else if (in->command == SET_IPV6_EXT_PUSH ||
13957 		 in->command == SET_IPV6_EXT_REMOVE)
13958 		return cmd_set_ipv6_ext_parsed(in);
13959 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13960 		   in->command == SET_RAW_DECAP);
13961 	if (in->command == SET_RAW_ENCAP) {
13962 		total_size = &raw_encap_confs[idx].size;
13963 		data = (uint8_t *)&raw_encap_confs[idx].data;
13964 	} else {
13965 		total_size = &raw_decap_confs[idx].size;
13966 		data = (uint8_t *)&raw_decap_confs[idx].data;
13967 	}
13968 	*total_size = 0;
13969 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13970 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13971 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13972 	for (i = n - 1 ; i >= 0; --i) {
13973 		const struct rte_flow_item_gtp *gtp;
13974 		const struct rte_flow_item_geneve_opt *opt;
13975 		struct rte_flow_item_ipv6_routing_ext *ext;
13976 
13977 		item = in->args.vc.pattern + i;
13978 		if (item->spec == NULL)
13979 			item->spec = flow_item_default_mask(item);
13980 		src_spec = item->spec;
13981 		switch (item->type) {
13982 		case RTE_FLOW_ITEM_TYPE_ETH:
13983 			size = sizeof(struct rte_ether_hdr);
13984 			break;
13985 		case RTE_FLOW_ITEM_TYPE_VLAN:
13986 			size = sizeof(struct rte_vlan_hdr);
13987 			proto = RTE_ETHER_TYPE_VLAN;
13988 			break;
13989 		case RTE_FLOW_ITEM_TYPE_IPV4:
13990 			size = sizeof(struct rte_ipv4_hdr);
13991 			proto = RTE_ETHER_TYPE_IPV4;
13992 			break;
13993 		case RTE_FLOW_ITEM_TYPE_IPV6:
13994 			size = sizeof(struct rte_ipv6_hdr);
13995 			proto = RTE_ETHER_TYPE_IPV6;
13996 			break;
13997 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13998 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13999 			if (!ext->hdr.hdr_len) {
14000 				size = sizeof(struct rte_ipv6_routing_ext) +
14001 					(ext->hdr.segments_left << 4);
14002 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
14003 				/* SRv6 without TLV. */
14004 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
14005 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
14006 			} else {
14007 				size = sizeof(struct rte_ipv6_routing_ext) +
14008 					(ext->hdr.hdr_len << 3);
14009 			}
14010 			proto = IPPROTO_ROUTING;
14011 			break;
14012 		case RTE_FLOW_ITEM_TYPE_UDP:
14013 			size = sizeof(struct rte_udp_hdr);
14014 			proto = 0x11;
14015 			break;
14016 		case RTE_FLOW_ITEM_TYPE_TCP:
14017 			size = sizeof(struct rte_tcp_hdr);
14018 			proto = 0x06;
14019 			break;
14020 		case RTE_FLOW_ITEM_TYPE_VXLAN:
14021 			size = sizeof(struct rte_vxlan_hdr);
14022 			break;
14023 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
14024 			size = sizeof(struct rte_vxlan_gpe_hdr);
14025 			break;
14026 		case RTE_FLOW_ITEM_TYPE_GRE:
14027 			size = sizeof(struct rte_gre_hdr);
14028 			proto = 0x2F;
14029 			break;
14030 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
14031 			size = sizeof(rte_be32_t);
14032 			proto = 0x0;
14033 			break;
14034 		case RTE_FLOW_ITEM_TYPE_MPLS:
14035 			size = sizeof(struct rte_mpls_hdr);
14036 			proto = 0x0;
14037 			break;
14038 		case RTE_FLOW_ITEM_TYPE_NVGRE:
14039 			size = sizeof(struct rte_flow_item_nvgre);
14040 			proto = 0x2F;
14041 			break;
14042 		case RTE_FLOW_ITEM_TYPE_GENEVE:
14043 			size = sizeof(struct rte_geneve_hdr);
14044 			break;
14045 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
14046 			opt = (const struct rte_flow_item_geneve_opt *)
14047 								item->spec;
14048 			size = offsetof(struct rte_flow_item_geneve_opt,
14049 					option_len) + sizeof(uint8_t);
14050 			if (opt->option_len && opt->data) {
14051 				*total_size += opt->option_len *
14052 					       sizeof(uint32_t);
14053 				rte_memcpy(data_tail - (*total_size),
14054 					   opt->data,
14055 					   opt->option_len * sizeof(uint32_t));
14056 			}
14057 			break;
14058 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
14059 			size = sizeof(rte_be32_t);
14060 			proto = 0x73;
14061 			break;
14062 		case RTE_FLOW_ITEM_TYPE_ESP:
14063 			size = sizeof(struct rte_esp_hdr);
14064 			proto = 0x32;
14065 			break;
14066 		case RTE_FLOW_ITEM_TYPE_AH:
14067 			size = sizeof(struct rte_flow_item_ah);
14068 			proto = 0x33;
14069 			break;
14070 		case RTE_FLOW_ITEM_TYPE_GTP:
14071 			if (gtp_psc < 0) {
14072 				size = sizeof(struct rte_gtp_hdr);
14073 				break;
14074 			}
14075 			if (gtp_psc != i + 1) {
14076 				fprintf(stderr,
14077 					"Error - GTP PSC does not follow GTP\n");
14078 				goto error;
14079 			}
14080 			gtp = item->spec;
14081 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
14082 				/* Only E flag should be set. */
14083 				fprintf(stderr,
14084 					"Error - GTP unsupported flags\n");
14085 				goto error;
14086 			} else {
14087 				struct rte_gtp_hdr_ext_word ext_word = {
14088 					.next_ext = 0x85
14089 				};
14090 
14091 				/* We have to add GTP header extra word. */
14092 				*total_size += sizeof(ext_word);
14093 				rte_memcpy(data_tail - (*total_size),
14094 					   &ext_word, sizeof(ext_word));
14095 			}
14096 			size = sizeof(struct rte_gtp_hdr);
14097 			break;
14098 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
14099 			if (gtp_psc >= 0) {
14100 				fprintf(stderr,
14101 					"Error - Multiple GTP PSC items\n");
14102 				goto error;
14103 			} else {
14104 				const struct rte_flow_item_gtp_psc
14105 					*opt = item->spec;
14106 				struct rte_gtp_psc_generic_hdr *hdr;
14107 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
14108 							 sizeof(int32_t));
14109 
14110 				*total_size += hdr_size;
14111 				hdr = (typeof(hdr))(data_tail - (*total_size));
14112 				memset(hdr, 0, hdr_size);
14113 				*hdr = opt->hdr;
14114 				hdr->ext_hdr_len = 1;
14115 				gtp_psc = i;
14116 				size = 0;
14117 			}
14118 			break;
14119 		case RTE_FLOW_ITEM_TYPE_PFCP:
14120 			size = sizeof(struct rte_flow_item_pfcp);
14121 			break;
14122 		case RTE_FLOW_ITEM_TYPE_FLEX:
14123 			if (item->spec != NULL) {
14124 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
14125 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
14126 			} else {
14127 				size = 0;
14128 				src_spec = NULL;
14129 			}
14130 			break;
14131 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
14132 			size = 0;
14133 			if (item->spec) {
14134 				const struct rte_flow_item_gre_opt
14135 					*opt = item->spec;
14136 				if (opt->checksum_rsvd.checksum) {
14137 					*total_size +=
14138 						sizeof(opt->checksum_rsvd);
14139 					rte_memcpy(data_tail - (*total_size),
14140 						   &opt->checksum_rsvd,
14141 						   sizeof(opt->checksum_rsvd));
14142 				}
14143 				if (opt->key.key) {
14144 					*total_size += sizeof(opt->key.key);
14145 					rte_memcpy(data_tail - (*total_size),
14146 						   &opt->key.key,
14147 						   sizeof(opt->key.key));
14148 				}
14149 				if (opt->sequence.sequence) {
14150 					*total_size += sizeof(opt->sequence.sequence);
14151 					rte_memcpy(data_tail - (*total_size),
14152 						   &opt->sequence.sequence,
14153 						   sizeof(opt->sequence.sequence));
14154 				}
14155 			}
14156 			proto = 0x2F;
14157 			break;
14158 		default:
14159 			fprintf(stderr, "Error - Not supported item\n");
14160 			goto error;
14161 		}
14162 		if (size) {
14163 			*total_size += size;
14164 			rte_memcpy(data_tail - (*total_size), src_spec, size);
14165 			/* update some fields which cannot be set by cmdline */
14166 			update_fields((data_tail - (*total_size)), item,
14167 				      upper_layer);
14168 			upper_layer = proto;
14169 		}
14170 	}
14171 	if (verbose_level & 0x1)
14172 		printf("total data size is %zu\n", (*total_size));
14173 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14174 	memmove(data, (data_tail - (*total_size)), *total_size);
14175 	return;
14176 
14177 error:
14178 	*total_size = 0;
14179 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14180 }
14181 
14182 /** Populate help strings for current token (cmdline API). */
14183 static int
14184 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14185 		     unsigned int size)
14186 {
14187 	struct context *ctx = &cmd_flow_context;
14188 	const struct token *token = &token_list[ctx->prev];
14189 
14190 	(void)hdr;
14191 	if (!size)
14192 		return -1;
14193 	/* Set token type and update global help with details. */
14194 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14195 	if (token->help)
14196 		cmd_set_raw.help_str = token->help;
14197 	else
14198 		cmd_set_raw.help_str = token->name;
14199 	return 0;
14200 }
14201 
14202 /** Token definition template (cmdline API). */
14203 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14204 	.ops = &(struct cmdline_token_ops){
14205 		.parse = cmd_flow_parse,
14206 		.complete_get_nb = cmd_flow_complete_get_nb,
14207 		.complete_get_elt = cmd_flow_complete_get_elt,
14208 		.get_help = cmd_set_raw_get_help,
14209 	},
14210 	.offset = 0,
14211 };
14212 
14213 /** Populate the next dynamic token. */
14214 static void
14215 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14216 	     cmdline_parse_token_hdr_t **hdr_inst)
14217 {
14218 	struct context *ctx = &cmd_flow_context;
14219 
14220 	/* Always reinitialize context before requesting the first token. */
14221 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14222 		cmd_flow_context_init(ctx);
14223 		ctx->curr = START_SET;
14224 	}
14225 	/* Return NULL when no more tokens are expected. */
14226 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14227 		*hdr = NULL;
14228 		return;
14229 	}
14230 	/* Determine if command should end here. */
14231 	if (ctx->eol && ctx->last && ctx->next_num) {
14232 		const enum index *list = ctx->next[ctx->next_num - 1];
14233 		int i;
14234 
14235 		for (i = 0; list[i]; ++i) {
14236 			if (list[i] != END)
14237 				continue;
14238 			*hdr = NULL;
14239 			return;
14240 		}
14241 	}
14242 	*hdr = &cmd_set_raw_token_hdr;
14243 }
14244 
14245 /** Token generator and output processing callback (cmdline API). */
14246 static void
14247 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14248 {
14249 	if (cl == NULL)
14250 		cmd_set_raw_tok(arg0, arg2);
14251 	else
14252 		cmd_set_raw_parsed(arg0);
14253 }
14254 
14255 /** Global parser instance (cmdline API). */
14256 cmdline_parse_inst_t cmd_set_raw = {
14257 	.f = cmd_set_raw_cb,
14258 	.data = NULL, /**< Unused. */
14259 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14260 	.tokens = {
14261 		NULL,
14262 	}, /**< Tokens are returned by cmd_flow_tok(). */
14263 };
14264 
14265 /* *** display raw_encap/raw_decap buf */
14266 struct cmd_show_set_raw_result {
14267 	cmdline_fixed_string_t cmd_show;
14268 	cmdline_fixed_string_t cmd_what;
14269 	cmdline_fixed_string_t cmd_all;
14270 	uint16_t cmd_index;
14271 };
14272 
14273 static void
14274 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14275 {
14276 	struct cmd_show_set_raw_result *res = parsed_result;
14277 	uint16_t index = res->cmd_index;
14278 	uint8_t all = 0;
14279 	uint8_t *raw_data = NULL;
14280 	size_t raw_size = 0;
14281 	char title[16] = {0};
14282 
14283 	RTE_SET_USED(cl);
14284 	RTE_SET_USED(data);
14285 	if (!strcmp(res->cmd_all, "all")) {
14286 		all = 1;
14287 		index = 0;
14288 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14289 		fprintf(stderr, "index should be 0-%u\n",
14290 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14291 		return;
14292 	}
14293 	do {
14294 		if (!strcmp(res->cmd_what, "raw_encap")) {
14295 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14296 			raw_size = raw_encap_confs[index].size;
14297 			snprintf(title, 16, "\nindex: %u", index);
14298 			rte_hexdump(stdout, title, raw_data, raw_size);
14299 		} else {
14300 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14301 			raw_size = raw_decap_confs[index].size;
14302 			snprintf(title, 16, "\nindex: %u", index);
14303 			rte_hexdump(stdout, title, raw_data, raw_size);
14304 		}
14305 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14306 }
14307 
14308 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14309 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14310 			cmd_show, "show");
14311 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14312 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14313 			cmd_what, "raw_encap#raw_decap");
14314 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14315 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14316 			cmd_index, RTE_UINT16);
14317 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14318 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14319 			cmd_all, "all");
14320 cmdline_parse_inst_t cmd_show_set_raw = {
14321 	.f = cmd_show_set_raw_parsed,
14322 	.data = NULL,
14323 	.help_str = "show <raw_encap|raw_decap> <index>",
14324 	.tokens = {
14325 		(void *)&cmd_show_set_raw_cmd_show,
14326 		(void *)&cmd_show_set_raw_cmd_what,
14327 		(void *)&cmd_show_set_raw_cmd_index,
14328 		NULL,
14329 	},
14330 };
14331 cmdline_parse_inst_t cmd_show_set_raw_all = {
14332 	.f = cmd_show_set_raw_parsed,
14333 	.data = NULL,
14334 	.help_str = "show <raw_encap|raw_decap> all",
14335 	.tokens = {
14336 		(void *)&cmd_show_set_raw_cmd_show,
14337 		(void *)&cmd_show_set_raw_cmd_what,
14338 		(void *)&cmd_show_set_raw_cmd_all,
14339 		NULL,
14340 	},
14341 };
14342