xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 2d9c7e56e52ceb2e14b5134dcd9673dd227e3072)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5 
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include <rte_string_fns.h>
16 #include <rte_common.h>
17 #include <rte_ethdev.h>
18 #include <rte_byteorder.h>
19 #include <cmdline_parse.h>
20 #include <cmdline_parse_etheraddr.h>
21 #include <cmdline_parse_string.h>
22 #include <cmdline_parse_num.h>
23 #include <rte_flow.h>
24 #include <rte_hexdump.h>
25 #include <rte_vxlan.h>
26 #include <rte_gre.h>
27 #include <rte_mpls.h>
28 #include <rte_gtp.h>
29 #include <rte_geneve.h>
30 
31 #include "testpmd.h"
32 
33 /** Parser token indices. */
34 enum index {
35 	/* Special tokens. */
36 	ZERO = 0,
37 	END,
38 	START_SET,
39 	END_SET,
40 
41 	/* Common tokens. */
42 	COMMON_INTEGER,
43 	COMMON_UNSIGNED,
44 	COMMON_PREFIX,
45 	COMMON_BOOLEAN,
46 	COMMON_STRING,
47 	COMMON_HEX,
48 	COMMON_FILE_PATH,
49 	COMMON_MAC_ADDR,
50 	COMMON_IPV4_ADDR,
51 	COMMON_IPV6_ADDR,
52 	COMMON_RULE_ID,
53 	COMMON_PORT_ID,
54 	COMMON_GROUP_ID,
55 	COMMON_PRIORITY_LEVEL,
56 	COMMON_INDIRECT_ACTION_ID,
57 	COMMON_PROFILE_ID,
58 	COMMON_POLICY_ID,
59 	COMMON_FLEX_HANDLE,
60 	COMMON_FLEX_TOKEN,
61 	COMMON_PATTERN_TEMPLATE_ID,
62 	COMMON_ACTIONS_TEMPLATE_ID,
63 	COMMON_TABLE_ID,
64 	COMMON_QUEUE_ID,
65 
66 	/* TOP-level command. */
67 	ADD,
68 
69 	/* Top-level command. */
70 	SET,
71 	/* Sub-leve commands. */
72 	SET_RAW_ENCAP,
73 	SET_RAW_DECAP,
74 	SET_RAW_INDEX,
75 	SET_SAMPLE_ACTIONS,
76 	SET_SAMPLE_INDEX,
77 	SET_IPV6_EXT_REMOVE,
78 	SET_IPV6_EXT_PUSH,
79 	SET_IPV6_EXT_INDEX,
80 
81 	/* Top-level command. */
82 	FLOW,
83 	/* Sub-level commands. */
84 	INFO,
85 	CONFIGURE,
86 	PATTERN_TEMPLATE,
87 	ACTIONS_TEMPLATE,
88 	TABLE,
89 	FLOW_GROUP,
90 	INDIRECT_ACTION,
91 	VALIDATE,
92 	CREATE,
93 	DESTROY,
94 	UPDATE,
95 	FLUSH,
96 	DUMP,
97 	QUERY,
98 	LIST,
99 	AGED,
100 	ISOLATE,
101 	TUNNEL,
102 	FLEX,
103 	QUEUE,
104 	PUSH,
105 	PULL,
106 	HASH,
107 
108 	/* Flex arguments */
109 	FLEX_ITEM_INIT,
110 	FLEX_ITEM_CREATE,
111 	FLEX_ITEM_DESTROY,
112 
113 	/* Pattern template arguments. */
114 	PATTERN_TEMPLATE_CREATE,
115 	PATTERN_TEMPLATE_DESTROY,
116 	PATTERN_TEMPLATE_CREATE_ID,
117 	PATTERN_TEMPLATE_DESTROY_ID,
118 	PATTERN_TEMPLATE_RELAXED_MATCHING,
119 	PATTERN_TEMPLATE_INGRESS,
120 	PATTERN_TEMPLATE_EGRESS,
121 	PATTERN_TEMPLATE_TRANSFER,
122 	PATTERN_TEMPLATE_SPEC,
123 
124 	/* Actions template arguments. */
125 	ACTIONS_TEMPLATE_CREATE,
126 	ACTIONS_TEMPLATE_DESTROY,
127 	ACTIONS_TEMPLATE_CREATE_ID,
128 	ACTIONS_TEMPLATE_DESTROY_ID,
129 	ACTIONS_TEMPLATE_INGRESS,
130 	ACTIONS_TEMPLATE_EGRESS,
131 	ACTIONS_TEMPLATE_TRANSFER,
132 	ACTIONS_TEMPLATE_SPEC,
133 	ACTIONS_TEMPLATE_MASK,
134 
135 	/* Queue arguments. */
136 	QUEUE_CREATE,
137 	QUEUE_DESTROY,
138 	QUEUE_FLOW_UPDATE_RESIZED,
139 	QUEUE_UPDATE,
140 	QUEUE_AGED,
141 	QUEUE_INDIRECT_ACTION,
142 
143 	/* Queue create arguments. */
144 	QUEUE_CREATE_POSTPONE,
145 	QUEUE_TEMPLATE_TABLE,
146 	QUEUE_PATTERN_TEMPLATE,
147 	QUEUE_ACTIONS_TEMPLATE,
148 	QUEUE_RULE_ID,
149 
150 	/* Queue destroy arguments. */
151 	QUEUE_DESTROY_ID,
152 	QUEUE_DESTROY_POSTPONE,
153 
154 	/* Queue update arguments. */
155 	QUEUE_UPDATE_ID,
156 
157 	/* Queue indirect action arguments */
158 	QUEUE_INDIRECT_ACTION_CREATE,
159 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
160 	QUEUE_INDIRECT_ACTION_UPDATE,
161 	QUEUE_INDIRECT_ACTION_DESTROY,
162 	QUEUE_INDIRECT_ACTION_QUERY,
163 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
164 
165 	/* Queue indirect action create arguments */
166 	QUEUE_INDIRECT_ACTION_CREATE_ID,
167 	QUEUE_INDIRECT_ACTION_INGRESS,
168 	QUEUE_INDIRECT_ACTION_EGRESS,
169 	QUEUE_INDIRECT_ACTION_TRANSFER,
170 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
171 	QUEUE_INDIRECT_ACTION_SPEC,
172 	QUEUE_INDIRECT_ACTION_LIST,
173 
174 	/* Queue indirect action update arguments */
175 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
176 
177 	/* Queue indirect action destroy arguments */
178 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
179 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
180 
181 	/* Queue indirect action query arguments */
182 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
183 
184 	/* Queue indirect action query_update arguments */
185 	QUEUE_INDIRECT_ACTION_QU_MODE,
186 
187 	/* Push arguments. */
188 	PUSH_QUEUE,
189 
190 	/* Pull arguments. */
191 	PULL_QUEUE,
192 
193 	/* Table arguments. */
194 	TABLE_CREATE,
195 	TABLE_DESTROY,
196 	TABLE_RESIZE,
197 	TABLE_RESIZE_COMPLETE,
198 	TABLE_CREATE_ID,
199 	TABLE_DESTROY_ID,
200 	TABLE_RESIZE_ID,
201 	TABLE_RESIZE_RULES_NUMBER,
202 	TABLE_INSERTION_TYPE,
203 	TABLE_INSERTION_TYPE_NAME,
204 	TABLE_HASH_FUNC,
205 	TABLE_HASH_FUNC_NAME,
206 	TABLE_GROUP,
207 	TABLE_PRIORITY,
208 	TABLE_INGRESS,
209 	TABLE_EGRESS,
210 	TABLE_TRANSFER,
211 	TABLE_TRANSFER_WIRE_ORIG,
212 	TABLE_TRANSFER_VPORT_ORIG,
213 	TABLE_RESIZABLE,
214 	TABLE_RULES_NUMBER,
215 	TABLE_PATTERN_TEMPLATE,
216 	TABLE_ACTIONS_TEMPLATE,
217 
218 	/* Group arguments */
219 	GROUP_ID,
220 	GROUP_INGRESS,
221 	GROUP_EGRESS,
222 	GROUP_TRANSFER,
223 	GROUP_SET_MISS_ACTIONS,
224 
225 	/* Hash calculation arguments. */
226 	HASH_CALC_TABLE,
227 	HASH_CALC_PATTERN_INDEX,
228 	HASH_CALC_PATTERN,
229 	HASH_CALC_ENCAP,
230 	HASH_CALC_DEST,
231 	ENCAP_HASH_FIELD_SRC_PORT,
232 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
233 
234 	/* Tunnel arguments. */
235 	TUNNEL_CREATE,
236 	TUNNEL_CREATE_TYPE,
237 	TUNNEL_LIST,
238 	TUNNEL_DESTROY,
239 	TUNNEL_DESTROY_ID,
240 
241 	/* Destroy arguments. */
242 	DESTROY_RULE,
243 	DESTROY_IS_USER_ID,
244 
245 	/* Query arguments. */
246 	QUERY_ACTION,
247 	QUERY_IS_USER_ID,
248 
249 	/* List arguments. */
250 	LIST_GROUP,
251 
252 	/* Destroy aged flow arguments. */
253 	AGED_DESTROY,
254 
255 	/* Validate/create arguments. */
256 	VC_GROUP,
257 	VC_PRIORITY,
258 	VC_INGRESS,
259 	VC_EGRESS,
260 	VC_TRANSFER,
261 	VC_TUNNEL_SET,
262 	VC_TUNNEL_MATCH,
263 	VC_USER_ID,
264 	VC_IS_USER_ID,
265 
266 	/* Dump arguments */
267 	DUMP_ALL,
268 	DUMP_ONE,
269 	DUMP_IS_USER_ID,
270 
271 	/* Configure arguments */
272 	CONFIG_QUEUES_NUMBER,
273 	CONFIG_QUEUES_SIZE,
274 	CONFIG_COUNTERS_NUMBER,
275 	CONFIG_AGING_OBJECTS_NUMBER,
276 	CONFIG_METERS_NUMBER,
277 	CONFIG_CONN_TRACK_NUMBER,
278 	CONFIG_QUOTAS_NUMBER,
279 	CONFIG_FLAGS,
280 	CONFIG_HOST_PORT,
281 
282 	/* Indirect action arguments */
283 	INDIRECT_ACTION_CREATE,
284 	INDIRECT_ACTION_LIST_CREATE,
285 	INDIRECT_ACTION_FLOW_CONF_CREATE,
286 	INDIRECT_ACTION_UPDATE,
287 	INDIRECT_ACTION_DESTROY,
288 	INDIRECT_ACTION_QUERY,
289 	INDIRECT_ACTION_QUERY_UPDATE,
290 
291 	/* Indirect action create arguments */
292 	INDIRECT_ACTION_CREATE_ID,
293 	INDIRECT_ACTION_INGRESS,
294 	INDIRECT_ACTION_EGRESS,
295 	INDIRECT_ACTION_TRANSFER,
296 	INDIRECT_ACTION_SPEC,
297 	INDIRECT_ACTION_LIST,
298 	INDIRECT_ACTION_FLOW_CONF,
299 
300 	/* Indirect action destroy arguments */
301 	INDIRECT_ACTION_DESTROY_ID,
302 
303 	/* Indirect action query-and-update arguments */
304 	INDIRECT_ACTION_QU_MODE,
305 	INDIRECT_ACTION_QU_MODE_NAME,
306 
307 	/* Validate/create pattern. */
308 	ITEM_PATTERN,
309 	ITEM_PARAM_IS,
310 	ITEM_PARAM_SPEC,
311 	ITEM_PARAM_LAST,
312 	ITEM_PARAM_MASK,
313 	ITEM_PARAM_PREFIX,
314 	ITEM_NEXT,
315 	ITEM_END,
316 	ITEM_VOID,
317 	ITEM_INVERT,
318 	ITEM_ANY,
319 	ITEM_ANY_NUM,
320 	ITEM_PORT_ID,
321 	ITEM_PORT_ID_ID,
322 	ITEM_MARK,
323 	ITEM_MARK_ID,
324 	ITEM_RAW,
325 	ITEM_RAW_RELATIVE,
326 	ITEM_RAW_SEARCH,
327 	ITEM_RAW_OFFSET,
328 	ITEM_RAW_LIMIT,
329 	ITEM_RAW_PATTERN,
330 	ITEM_RAW_PATTERN_HEX,
331 	ITEM_ETH,
332 	ITEM_ETH_DST,
333 	ITEM_ETH_SRC,
334 	ITEM_ETH_TYPE,
335 	ITEM_ETH_HAS_VLAN,
336 	ITEM_VLAN,
337 	ITEM_VLAN_TCI,
338 	ITEM_VLAN_PCP,
339 	ITEM_VLAN_DEI,
340 	ITEM_VLAN_VID,
341 	ITEM_VLAN_INNER_TYPE,
342 	ITEM_VLAN_HAS_MORE_VLAN,
343 	ITEM_IPV4,
344 	ITEM_IPV4_VER_IHL,
345 	ITEM_IPV4_TOS,
346 	ITEM_IPV4_LENGTH,
347 	ITEM_IPV4_ID,
348 	ITEM_IPV4_FRAGMENT_OFFSET,
349 	ITEM_IPV4_TTL,
350 	ITEM_IPV4_PROTO,
351 	ITEM_IPV4_SRC,
352 	ITEM_IPV4_DST,
353 	ITEM_IPV6,
354 	ITEM_IPV6_TC,
355 	ITEM_IPV6_FLOW,
356 	ITEM_IPV6_LEN,
357 	ITEM_IPV6_PROTO,
358 	ITEM_IPV6_HOP,
359 	ITEM_IPV6_SRC,
360 	ITEM_IPV6_DST,
361 	ITEM_IPV6_HAS_FRAG_EXT,
362 	ITEM_IPV6_ROUTING_EXT,
363 	ITEM_IPV6_ROUTING_EXT_TYPE,
364 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
365 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
366 	ITEM_ICMP,
367 	ITEM_ICMP_TYPE,
368 	ITEM_ICMP_CODE,
369 	ITEM_ICMP_IDENT,
370 	ITEM_ICMP_SEQ,
371 	ITEM_UDP,
372 	ITEM_UDP_SRC,
373 	ITEM_UDP_DST,
374 	ITEM_TCP,
375 	ITEM_TCP_SRC,
376 	ITEM_TCP_DST,
377 	ITEM_TCP_FLAGS,
378 	ITEM_SCTP,
379 	ITEM_SCTP_SRC,
380 	ITEM_SCTP_DST,
381 	ITEM_SCTP_TAG,
382 	ITEM_SCTP_CKSUM,
383 	ITEM_VXLAN,
384 	ITEM_VXLAN_VNI,
385 	ITEM_VXLAN_LAST_RSVD,
386 	ITEM_E_TAG,
387 	ITEM_E_TAG_GRP_ECID_B,
388 	ITEM_NVGRE,
389 	ITEM_NVGRE_TNI,
390 	ITEM_MPLS,
391 	ITEM_MPLS_LABEL,
392 	ITEM_MPLS_TC,
393 	ITEM_MPLS_S,
394 	ITEM_MPLS_TTL,
395 	ITEM_GRE,
396 	ITEM_GRE_PROTO,
397 	ITEM_GRE_C_RSVD0_VER,
398 	ITEM_GRE_C_BIT,
399 	ITEM_GRE_K_BIT,
400 	ITEM_GRE_S_BIT,
401 	ITEM_FUZZY,
402 	ITEM_FUZZY_THRESH,
403 	ITEM_GTP,
404 	ITEM_GTP_FLAGS,
405 	ITEM_GTP_MSG_TYPE,
406 	ITEM_GTP_TEID,
407 	ITEM_GTPC,
408 	ITEM_GTPU,
409 	ITEM_GENEVE,
410 	ITEM_GENEVE_VNI,
411 	ITEM_GENEVE_PROTO,
412 	ITEM_GENEVE_OPTLEN,
413 	ITEM_VXLAN_GPE,
414 	ITEM_VXLAN_GPE_VNI,
415 	ITEM_VXLAN_GPE_PROTO,
416 	ITEM_VXLAN_GPE_FLAGS,
417 	ITEM_VXLAN_GPE_RSVD0,
418 	ITEM_VXLAN_GPE_RSVD1,
419 	ITEM_ARP_ETH_IPV4,
420 	ITEM_ARP_ETH_IPV4_SHA,
421 	ITEM_ARP_ETH_IPV4_SPA,
422 	ITEM_ARP_ETH_IPV4_THA,
423 	ITEM_ARP_ETH_IPV4_TPA,
424 	ITEM_IPV6_EXT,
425 	ITEM_IPV6_EXT_NEXT_HDR,
426 	ITEM_IPV6_FRAG_EXT,
427 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
428 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
429 	ITEM_IPV6_FRAG_EXT_ID,
430 	ITEM_ICMP6,
431 	ITEM_ICMP6_TYPE,
432 	ITEM_ICMP6_CODE,
433 	ITEM_ICMP6_ECHO_REQUEST,
434 	ITEM_ICMP6_ECHO_REQUEST_ID,
435 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
436 	ITEM_ICMP6_ECHO_REPLY,
437 	ITEM_ICMP6_ECHO_REPLY_ID,
438 	ITEM_ICMP6_ECHO_REPLY_SEQ,
439 	ITEM_ICMP6_ND_NS,
440 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
441 	ITEM_ICMP6_ND_NA,
442 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
443 	ITEM_ICMP6_ND_OPT,
444 	ITEM_ICMP6_ND_OPT_TYPE,
445 	ITEM_ICMP6_ND_OPT_SLA_ETH,
446 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
447 	ITEM_ICMP6_ND_OPT_TLA_ETH,
448 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
449 	ITEM_META,
450 	ITEM_META_DATA,
451 	ITEM_RANDOM,
452 	ITEM_RANDOM_VALUE,
453 	ITEM_GRE_KEY,
454 	ITEM_GRE_KEY_VALUE,
455 	ITEM_GRE_OPTION,
456 	ITEM_GRE_OPTION_CHECKSUM,
457 	ITEM_GRE_OPTION_KEY,
458 	ITEM_GRE_OPTION_SEQUENCE,
459 	ITEM_GTP_PSC,
460 	ITEM_GTP_PSC_QFI,
461 	ITEM_GTP_PSC_PDU_T,
462 	ITEM_PPPOES,
463 	ITEM_PPPOED,
464 	ITEM_PPPOE_SEID,
465 	ITEM_PPPOE_PROTO_ID,
466 	ITEM_HIGIG2,
467 	ITEM_HIGIG2_CLASSIFICATION,
468 	ITEM_HIGIG2_VID,
469 	ITEM_TAG,
470 	ITEM_TAG_DATA,
471 	ITEM_TAG_INDEX,
472 	ITEM_L2TPV3OIP,
473 	ITEM_L2TPV3OIP_SESSION_ID,
474 	ITEM_ESP,
475 	ITEM_ESP_SPI,
476 	ITEM_AH,
477 	ITEM_AH_SPI,
478 	ITEM_PFCP,
479 	ITEM_PFCP_S_FIELD,
480 	ITEM_PFCP_SEID,
481 	ITEM_ECPRI,
482 	ITEM_ECPRI_COMMON,
483 	ITEM_ECPRI_COMMON_TYPE,
484 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
485 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
486 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
487 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
488 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
489 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
490 	ITEM_GENEVE_OPT,
491 	ITEM_GENEVE_OPT_CLASS,
492 	ITEM_GENEVE_OPT_TYPE,
493 	ITEM_GENEVE_OPT_LENGTH,
494 	ITEM_GENEVE_OPT_DATA,
495 	ITEM_INTEGRITY,
496 	ITEM_INTEGRITY_LEVEL,
497 	ITEM_INTEGRITY_VALUE,
498 	ITEM_CONNTRACK,
499 	ITEM_POL_PORT,
500 	ITEM_POL_METER,
501 	ITEM_POL_POLICY,
502 	ITEM_PORT_REPRESENTOR,
503 	ITEM_PORT_REPRESENTOR_PORT_ID,
504 	ITEM_REPRESENTED_PORT,
505 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
506 	ITEM_FLEX,
507 	ITEM_FLEX_ITEM_HANDLE,
508 	ITEM_FLEX_PATTERN_HANDLE,
509 	ITEM_L2TPV2,
510 	ITEM_L2TPV2_TYPE,
511 	ITEM_L2TPV2_TYPE_DATA,
512 	ITEM_L2TPV2_TYPE_DATA_L,
513 	ITEM_L2TPV2_TYPE_DATA_S,
514 	ITEM_L2TPV2_TYPE_DATA_O,
515 	ITEM_L2TPV2_TYPE_DATA_L_S,
516 	ITEM_L2TPV2_TYPE_CTRL,
517 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
518 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
519 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
520 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
521 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
522 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
523 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
524 	ITEM_L2TPV2_MSG_DATA_S_NS,
525 	ITEM_L2TPV2_MSG_DATA_S_NR,
526 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
527 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
528 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
529 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
530 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
531 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
532 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
533 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
534 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
535 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
536 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
537 	ITEM_L2TPV2_MSG_CTRL_NS,
538 	ITEM_L2TPV2_MSG_CTRL_NR,
539 	ITEM_PPP,
540 	ITEM_PPP_ADDR,
541 	ITEM_PPP_CTRL,
542 	ITEM_PPP_PROTO_ID,
543 	ITEM_METER,
544 	ITEM_METER_COLOR,
545 	ITEM_METER_COLOR_NAME,
546 	ITEM_QUOTA,
547 	ITEM_QUOTA_STATE,
548 	ITEM_QUOTA_STATE_NAME,
549 	ITEM_AGGR_AFFINITY,
550 	ITEM_AGGR_AFFINITY_VALUE,
551 	ITEM_TX_QUEUE,
552 	ITEM_TX_QUEUE_VALUE,
553 	ITEM_IB_BTH,
554 	ITEM_IB_BTH_OPCODE,
555 	ITEM_IB_BTH_PKEY,
556 	ITEM_IB_BTH_DST_QPN,
557 	ITEM_IB_BTH_PSN,
558 	ITEM_IPV6_PUSH_REMOVE_EXT,
559 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
560 	ITEM_PTYPE,
561 	ITEM_PTYPE_VALUE,
562 	ITEM_NSH,
563 	ITEM_COMPARE,
564 	ITEM_COMPARE_OP,
565 	ITEM_COMPARE_OP_VALUE,
566 	ITEM_COMPARE_FIELD_A_TYPE,
567 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
568 	ITEM_COMPARE_FIELD_A_LEVEL,
569 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
570 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
571 	ITEM_COMPARE_FIELD_A_TYPE_ID,
572 	ITEM_COMPARE_FIELD_A_CLASS_ID,
573 	ITEM_COMPARE_FIELD_A_OFFSET,
574 	ITEM_COMPARE_FIELD_B_TYPE,
575 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
576 	ITEM_COMPARE_FIELD_B_LEVEL,
577 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
578 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
579 	ITEM_COMPARE_FIELD_B_TYPE_ID,
580 	ITEM_COMPARE_FIELD_B_CLASS_ID,
581 	ITEM_COMPARE_FIELD_B_OFFSET,
582 	ITEM_COMPARE_FIELD_B_VALUE,
583 	ITEM_COMPARE_FIELD_B_POINTER,
584 	ITEM_COMPARE_FIELD_WIDTH,
585 
586 	/* Validate/create actions. */
587 	ACTIONS,
588 	ACTION_NEXT,
589 	ACTION_END,
590 	ACTION_VOID,
591 	ACTION_PASSTHRU,
592 	ACTION_SKIP_CMAN,
593 	ACTION_JUMP,
594 	ACTION_JUMP_GROUP,
595 	ACTION_MARK,
596 	ACTION_MARK_ID,
597 	ACTION_FLAG,
598 	ACTION_QUEUE,
599 	ACTION_QUEUE_INDEX,
600 	ACTION_DROP,
601 	ACTION_COUNT,
602 	ACTION_COUNT_ID,
603 	ACTION_RSS,
604 	ACTION_RSS_FUNC,
605 	ACTION_RSS_LEVEL,
606 	ACTION_RSS_FUNC_DEFAULT,
607 	ACTION_RSS_FUNC_TOEPLITZ,
608 	ACTION_RSS_FUNC_SIMPLE_XOR,
609 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
610 	ACTION_RSS_TYPES,
611 	ACTION_RSS_TYPE,
612 	ACTION_RSS_KEY,
613 	ACTION_RSS_KEY_LEN,
614 	ACTION_RSS_QUEUES,
615 	ACTION_RSS_QUEUE,
616 	ACTION_PF,
617 	ACTION_VF,
618 	ACTION_VF_ORIGINAL,
619 	ACTION_VF_ID,
620 	ACTION_PORT_ID,
621 	ACTION_PORT_ID_ORIGINAL,
622 	ACTION_PORT_ID_ID,
623 	ACTION_METER,
624 	ACTION_METER_COLOR,
625 	ACTION_METER_COLOR_TYPE,
626 	ACTION_METER_COLOR_GREEN,
627 	ACTION_METER_COLOR_YELLOW,
628 	ACTION_METER_COLOR_RED,
629 	ACTION_METER_ID,
630 	ACTION_METER_MARK,
631 	ACTION_METER_PROFILE,
632 	ACTION_METER_PROFILE_ID2PTR,
633 	ACTION_METER_POLICY,
634 	ACTION_METER_POLICY_ID2PTR,
635 	ACTION_METER_COLOR_MODE,
636 	ACTION_METER_STATE,
637 	ACTION_OF_DEC_NW_TTL,
638 	ACTION_OF_POP_VLAN,
639 	ACTION_OF_PUSH_VLAN,
640 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
641 	ACTION_OF_SET_VLAN_VID,
642 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
643 	ACTION_OF_SET_VLAN_PCP,
644 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
645 	ACTION_OF_POP_MPLS,
646 	ACTION_OF_POP_MPLS_ETHERTYPE,
647 	ACTION_OF_PUSH_MPLS,
648 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
649 	ACTION_VXLAN_ENCAP,
650 	ACTION_VXLAN_DECAP,
651 	ACTION_NVGRE_ENCAP,
652 	ACTION_NVGRE_DECAP,
653 	ACTION_L2_ENCAP,
654 	ACTION_L2_DECAP,
655 	ACTION_MPLSOGRE_ENCAP,
656 	ACTION_MPLSOGRE_DECAP,
657 	ACTION_MPLSOUDP_ENCAP,
658 	ACTION_MPLSOUDP_DECAP,
659 	ACTION_SET_IPV4_SRC,
660 	ACTION_SET_IPV4_SRC_IPV4_SRC,
661 	ACTION_SET_IPV4_DST,
662 	ACTION_SET_IPV4_DST_IPV4_DST,
663 	ACTION_SET_IPV6_SRC,
664 	ACTION_SET_IPV6_SRC_IPV6_SRC,
665 	ACTION_SET_IPV6_DST,
666 	ACTION_SET_IPV6_DST_IPV6_DST,
667 	ACTION_SET_TP_SRC,
668 	ACTION_SET_TP_SRC_TP_SRC,
669 	ACTION_SET_TP_DST,
670 	ACTION_SET_TP_DST_TP_DST,
671 	ACTION_MAC_SWAP,
672 	ACTION_DEC_TTL,
673 	ACTION_SET_TTL,
674 	ACTION_SET_TTL_TTL,
675 	ACTION_SET_MAC_SRC,
676 	ACTION_SET_MAC_SRC_MAC_SRC,
677 	ACTION_SET_MAC_DST,
678 	ACTION_SET_MAC_DST_MAC_DST,
679 	ACTION_INC_TCP_SEQ,
680 	ACTION_INC_TCP_SEQ_VALUE,
681 	ACTION_DEC_TCP_SEQ,
682 	ACTION_DEC_TCP_SEQ_VALUE,
683 	ACTION_INC_TCP_ACK,
684 	ACTION_INC_TCP_ACK_VALUE,
685 	ACTION_DEC_TCP_ACK,
686 	ACTION_DEC_TCP_ACK_VALUE,
687 	ACTION_RAW_ENCAP,
688 	ACTION_RAW_DECAP,
689 	ACTION_RAW_ENCAP_SIZE,
690 	ACTION_RAW_ENCAP_INDEX,
691 	ACTION_RAW_ENCAP_INDEX_VALUE,
692 	ACTION_RAW_DECAP_INDEX,
693 	ACTION_RAW_DECAP_INDEX_VALUE,
694 	ACTION_SET_TAG,
695 	ACTION_SET_TAG_DATA,
696 	ACTION_SET_TAG_INDEX,
697 	ACTION_SET_TAG_MASK,
698 	ACTION_SET_META,
699 	ACTION_SET_META_DATA,
700 	ACTION_SET_META_MASK,
701 	ACTION_SET_IPV4_DSCP,
702 	ACTION_SET_IPV4_DSCP_VALUE,
703 	ACTION_SET_IPV6_DSCP,
704 	ACTION_SET_IPV6_DSCP_VALUE,
705 	ACTION_AGE,
706 	ACTION_AGE_TIMEOUT,
707 	ACTION_AGE_UPDATE,
708 	ACTION_AGE_UPDATE_TIMEOUT,
709 	ACTION_AGE_UPDATE_TOUCH,
710 	ACTION_SAMPLE,
711 	ACTION_SAMPLE_RATIO,
712 	ACTION_SAMPLE_INDEX,
713 	ACTION_SAMPLE_INDEX_VALUE,
714 	ACTION_INDIRECT,
715 	ACTION_INDIRECT_LIST,
716 	ACTION_INDIRECT_LIST_HANDLE,
717 	ACTION_INDIRECT_LIST_CONF,
718 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
719 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
720 	ACTION_SHARED_INDIRECT,
721 	INDIRECT_ACTION_PORT,
722 	INDIRECT_ACTION_ID2PTR,
723 	ACTION_MODIFY_FIELD,
724 	ACTION_MODIFY_FIELD_OP,
725 	ACTION_MODIFY_FIELD_OP_VALUE,
726 	ACTION_MODIFY_FIELD_DST_TYPE,
727 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
728 	ACTION_MODIFY_FIELD_DST_LEVEL,
729 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
730 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
731 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
732 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
733 	ACTION_MODIFY_FIELD_DST_OFFSET,
734 	ACTION_MODIFY_FIELD_SRC_TYPE,
735 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
736 	ACTION_MODIFY_FIELD_SRC_LEVEL,
737 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
738 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
739 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
740 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
741 	ACTION_MODIFY_FIELD_SRC_OFFSET,
742 	ACTION_MODIFY_FIELD_SRC_VALUE,
743 	ACTION_MODIFY_FIELD_SRC_POINTER,
744 	ACTION_MODIFY_FIELD_WIDTH,
745 	ACTION_CONNTRACK,
746 	ACTION_CONNTRACK_UPDATE,
747 	ACTION_CONNTRACK_UPDATE_DIR,
748 	ACTION_CONNTRACK_UPDATE_CTX,
749 	ACTION_POL_G,
750 	ACTION_POL_Y,
751 	ACTION_POL_R,
752 	ACTION_PORT_REPRESENTOR,
753 	ACTION_PORT_REPRESENTOR_PORT_ID,
754 	ACTION_REPRESENTED_PORT,
755 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
756 	ACTION_SEND_TO_KERNEL,
757 	ACTION_QUOTA_CREATE,
758 	ACTION_QUOTA_CREATE_LIMIT,
759 	ACTION_QUOTA_CREATE_MODE,
760 	ACTION_QUOTA_CREATE_MODE_NAME,
761 	ACTION_QUOTA_QU,
762 	ACTION_QUOTA_QU_LIMIT,
763 	ACTION_QUOTA_QU_UPDATE_OP,
764 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
765 	ACTION_IPV6_EXT_REMOVE,
766 	ACTION_IPV6_EXT_REMOVE_INDEX,
767 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
768 	ACTION_IPV6_EXT_PUSH,
769 	ACTION_IPV6_EXT_PUSH_INDEX,
770 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
771 	ACTION_NAT64,
772 	ACTION_NAT64_MODE,
773 };
774 
775 /** Maximum size for pattern in struct rte_flow_item_raw. */
776 #define ITEM_RAW_PATTERN_SIZE 512
777 
778 /** Maximum size for GENEVE option data pattern in bytes. */
779 #define ITEM_GENEVE_OPT_DATA_SIZE 124
780 
781 /** Storage size for struct rte_flow_item_raw including pattern. */
782 #define ITEM_RAW_SIZE \
783 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
784 
785 static const char *const compare_ops[] = {
786 	"eq", "ne", "lt", "le", "gt", "ge", NULL
787 };
788 
789 /** Maximum size for external pattern in struct rte_flow_field_data. */
790 #define FLOW_FIELD_PATTERN_SIZE 32
791 
792 /** Storage size for struct rte_flow_action_modify_field including pattern. */
793 #define ACTION_MODIFY_SIZE \
794 	(sizeof(struct rte_flow_action_modify_field) + \
795 	FLOW_FIELD_PATTERN_SIZE)
796 
797 /** Maximum number of queue indices in struct rte_flow_action_rss. */
798 #define ACTION_RSS_QUEUE_NUM 128
799 
800 /** Storage for struct rte_flow_action_rss including external data. */
801 struct action_rss_data {
802 	struct rte_flow_action_rss conf;
803 	uint8_t key[RSS_HASH_KEY_LENGTH];
804 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
805 };
806 
807 /** Maximum data size in struct rte_flow_action_raw_encap. */
808 #define ACTION_RAW_ENCAP_MAX_DATA 512
809 #define RAW_ENCAP_CONFS_MAX_NUM 8
810 
811 /** Storage for struct rte_flow_action_raw_encap. */
812 struct raw_encap_conf {
813 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
814 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
815 	size_t size;
816 };
817 
818 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
819 
820 /** Storage for struct rte_flow_action_raw_encap including external data. */
821 struct action_raw_encap_data {
822 	struct rte_flow_action_raw_encap conf;
823 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
824 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
825 	uint16_t idx;
826 };
827 
828 /** Storage for struct rte_flow_action_raw_decap. */
829 struct raw_decap_conf {
830 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
831 	size_t size;
832 };
833 
834 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
835 
836 /** Storage for struct rte_flow_action_raw_decap including external data. */
837 struct action_raw_decap_data {
838 	struct rte_flow_action_raw_decap conf;
839 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
840 	uint16_t idx;
841 };
842 
843 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
844 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
845 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
846 
847 /** Storage for struct rte_flow_action_ipv6_ext_push. */
848 struct ipv6_ext_push_conf {
849 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
850 	size_t size;
851 	uint8_t type;
852 };
853 
854 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
855 
856 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
857 struct action_ipv6_ext_push_data {
858 	struct rte_flow_action_ipv6_ext_push conf;
859 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
860 	uint8_t type;
861 	uint16_t idx;
862 };
863 
864 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
865 struct ipv6_ext_remove_conf {
866 	struct rte_flow_action_ipv6_ext_remove conf;
867 	uint8_t type;
868 };
869 
870 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
871 
872 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
873 struct action_ipv6_ext_remove_data {
874 	struct rte_flow_action_ipv6_ext_remove conf;
875 	uint8_t type;
876 	uint16_t idx;
877 };
878 
879 struct vxlan_encap_conf vxlan_encap_conf = {
880 	.select_ipv4 = 1,
881 	.select_vlan = 0,
882 	.select_tos_ttl = 0,
883 	.vni = "\x00\x00\x00",
884 	.udp_src = 0,
885 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
886 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
887 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
888 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
889 		"\x00\x00\x00\x00\x00\x00\x00\x01",
890 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
891 		"\x00\x00\x00\x00\x00\x00\x11\x11",
892 	.vlan_tci = 0,
893 	.ip_tos = 0,
894 	.ip_ttl = 255,
895 	.eth_src = "\x00\x00\x00\x00\x00\x00",
896 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
897 };
898 
899 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
900 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
901 
902 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
903 struct action_vxlan_encap_data {
904 	struct rte_flow_action_vxlan_encap conf;
905 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
906 	struct rte_flow_item_eth item_eth;
907 	struct rte_flow_item_vlan item_vlan;
908 	union {
909 		struct rte_flow_item_ipv4 item_ipv4;
910 		struct rte_flow_item_ipv6 item_ipv6;
911 	};
912 	struct rte_flow_item_udp item_udp;
913 	struct rte_flow_item_vxlan item_vxlan;
914 };
915 
916 struct nvgre_encap_conf nvgre_encap_conf = {
917 	.select_ipv4 = 1,
918 	.select_vlan = 0,
919 	.tni = "\x00\x00\x00",
920 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
921 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
922 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
923 		"\x00\x00\x00\x00\x00\x00\x00\x01",
924 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
925 		"\x00\x00\x00\x00\x00\x00\x11\x11",
926 	.vlan_tci = 0,
927 	.eth_src = "\x00\x00\x00\x00\x00\x00",
928 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
929 };
930 
931 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
932 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
933 
934 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
935 struct action_nvgre_encap_data {
936 	struct rte_flow_action_nvgre_encap conf;
937 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
938 	struct rte_flow_item_eth item_eth;
939 	struct rte_flow_item_vlan item_vlan;
940 	union {
941 		struct rte_flow_item_ipv4 item_ipv4;
942 		struct rte_flow_item_ipv6 item_ipv6;
943 	};
944 	struct rte_flow_item_nvgre item_nvgre;
945 };
946 
947 struct l2_encap_conf l2_encap_conf;
948 
949 struct l2_decap_conf l2_decap_conf;
950 
951 struct mplsogre_encap_conf mplsogre_encap_conf;
952 
953 struct mplsogre_decap_conf mplsogre_decap_conf;
954 
955 struct mplsoudp_encap_conf mplsoudp_encap_conf;
956 
957 struct mplsoudp_decap_conf mplsoudp_decap_conf;
958 
959 struct rte_flow_action_conntrack conntrack_context;
960 
961 #define ACTION_SAMPLE_ACTIONS_NUM 10
962 #define RAW_SAMPLE_CONFS_MAX_NUM 8
963 /** Storage for struct rte_flow_action_sample including external data. */
964 struct action_sample_data {
965 	struct rte_flow_action_sample conf;
966 	uint32_t idx;
967 };
968 /** Storage for struct rte_flow_action_sample. */
969 struct raw_sample_conf {
970 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
971 };
972 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
973 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
974 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
975 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
976 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
977 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
978 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
979 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
980 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
981 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
982 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
983 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
984 
985 static const char *const modify_field_ops[] = {
986 	"set", "add", "sub", NULL
987 };
988 
989 static const char *const flow_field_ids[] = {
990 	"start", "mac_dst", "mac_src",
991 	"vlan_type", "vlan_id", "mac_type",
992 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
993 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
994 	"tcp_port_src", "tcp_port_dst",
995 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
996 	"udp_port_src", "udp_port_dst",
997 	"vxlan_vni", "geneve_vni", "gtp_teid",
998 	"tag", "mark", "meta", "pointer", "value",
999 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
1000 	"ipv6_proto",
1001 	"flex_item",
1002 	"hash_result",
1003 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1004 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1005 	"random",
1006 	"ipv4_proto",
1007 	"esp_spi", "esp_seq_num", "esp_proto",
1008 	"ipv6_flow_label", "ipv6_traffic_class",
1009 	NULL
1010 };
1011 
1012 static const char *const meter_colors[] = {
1013 	"green", "yellow", "red", "all", NULL
1014 };
1015 
1016 static const char *const table_insertion_types[] = {
1017 	"pattern", "index", NULL
1018 };
1019 
1020 static const char *const table_hash_funcs[] = {
1021 	"default", "linear", "crc32", "crc16", NULL
1022 };
1023 
1024 #define RAW_IPSEC_CONFS_MAX_NUM 8
1025 
1026 /** Maximum number of subsequent tokens and arguments on the stack. */
1027 #define CTX_STACK_SIZE 16
1028 
1029 /** Parser context. */
1030 struct context {
1031 	/** Stack of subsequent token lists to process. */
1032 	const enum index *next[CTX_STACK_SIZE];
1033 	/** Arguments for stacked tokens. */
1034 	const void *args[CTX_STACK_SIZE];
1035 	enum index curr; /**< Current token index. */
1036 	enum index prev; /**< Index of the last token seen. */
1037 	int next_num; /**< Number of entries in next[]. */
1038 	int args_num; /**< Number of entries in args[]. */
1039 	uint32_t eol:1; /**< EOL has been detected. */
1040 	uint32_t last:1; /**< No more arguments. */
1041 	portid_t port; /**< Current port ID (for completions). */
1042 	uint32_t objdata; /**< Object-specific data. */
1043 	void *object; /**< Address of current object for relative offsets. */
1044 	void *objmask; /**< Object a full mask must be written to. */
1045 };
1046 
1047 /** Token argument. */
1048 struct arg {
1049 	uint32_t hton:1; /**< Use network byte ordering. */
1050 	uint32_t sign:1; /**< Value is signed. */
1051 	uint32_t bounded:1; /**< Value is bounded. */
1052 	uintmax_t min; /**< Minimum value if bounded. */
1053 	uintmax_t max; /**< Maximum value if bounded. */
1054 	uint32_t offset; /**< Relative offset from ctx->object. */
1055 	uint32_t size; /**< Field size. */
1056 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1057 };
1058 
1059 /** Parser token definition. */
1060 struct token {
1061 	/** Type displayed during completion (defaults to "TOKEN"). */
1062 	const char *type;
1063 	/** Help displayed during completion (defaults to token name). */
1064 	const char *help;
1065 	/** Private data used by parser functions. */
1066 	const void *priv;
1067 	/**
1068 	 * Lists of subsequent tokens to push on the stack. Each call to the
1069 	 * parser consumes the last entry of that stack.
1070 	 */
1071 	const enum index *const *next;
1072 	/** Arguments stack for subsequent tokens that need them. */
1073 	const struct arg *const *args;
1074 	/**
1075 	 * Token-processing callback, returns -1 in case of error, the
1076 	 * length of the matched string otherwise. If NULL, attempts to
1077 	 * match the token name.
1078 	 *
1079 	 * If buf is not NULL, the result should be stored in it according
1080 	 * to context. An error is returned if not large enough.
1081 	 */
1082 	int (*call)(struct context *ctx, const struct token *token,
1083 		    const char *str, unsigned int len,
1084 		    void *buf, unsigned int size);
1085 	/**
1086 	 * Callback that provides possible values for this token, used for
1087 	 * completion. Returns -1 in case of error, the number of possible
1088 	 * values otherwise. If NULL, the token name is used.
1089 	 *
1090 	 * If buf is not NULL, entry index ent is written to buf and the
1091 	 * full length of the entry is returned (same behavior as
1092 	 * snprintf()).
1093 	 */
1094 	int (*comp)(struct context *ctx, const struct token *token,
1095 		    unsigned int ent, char *buf, unsigned int size);
1096 	/** Mandatory token name, no default value. */
1097 	const char *name;
1098 };
1099 
1100 /** Static initializer for the next field. */
1101 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1102 
1103 /** Static initializer for a NEXT() entry. */
1104 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1105 
1106 /** Static initializer for the args field. */
1107 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1108 
1109 /** Static initializer for ARGS() to target a field. */
1110 #define ARGS_ENTRY(s, f) \
1111 	(&(const struct arg){ \
1112 		.offset = offsetof(s, f), \
1113 		.size = sizeof(((s *)0)->f), \
1114 	})
1115 
1116 /** Static initializer for ARGS() to target a bit-field. */
1117 #define ARGS_ENTRY_BF(s, f, b) \
1118 	(&(const struct arg){ \
1119 		.size = sizeof(s), \
1120 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1121 	})
1122 
1123 /** Static initializer for ARGS() to target a field with limits. */
1124 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1125 	(&(const struct arg){ \
1126 		.bounded = 1, \
1127 		.min = (i), \
1128 		.max = (a), \
1129 		.offset = offsetof(s, f), \
1130 		.size = sizeof(((s *)0)->f), \
1131 	})
1132 
1133 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1134 #define ARGS_ENTRY_MASK(s, f, m) \
1135 	(&(const struct arg){ \
1136 		.offset = offsetof(s, f), \
1137 		.size = sizeof(((s *)0)->f), \
1138 		.mask = (const void *)(m), \
1139 	})
1140 
1141 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1142 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1143 	(&(const struct arg){ \
1144 		.hton = 1, \
1145 		.offset = offsetof(s, f), \
1146 		.size = sizeof(((s *)0)->f), \
1147 		.mask = (const void *)(m), \
1148 	})
1149 
1150 /** Static initializer for ARGS() to target a pointer. */
1151 #define ARGS_ENTRY_PTR(s, f) \
1152 	(&(const struct arg){ \
1153 		.size = sizeof(*((s *)0)->f), \
1154 	})
1155 
1156 /** Static initializer for ARGS() with arbitrary offset and size. */
1157 #define ARGS_ENTRY_ARB(o, s) \
1158 	(&(const struct arg){ \
1159 		.offset = (o), \
1160 		.size = (s), \
1161 	})
1162 
1163 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1164 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1165 	(&(const struct arg){ \
1166 		.bounded = 1, \
1167 		.min = (i), \
1168 		.max = (a), \
1169 		.offset = (o), \
1170 		.size = (s), \
1171 	})
1172 
1173 /** Same as ARGS_ENTRY() using network byte ordering. */
1174 #define ARGS_ENTRY_HTON(s, f) \
1175 	(&(const struct arg){ \
1176 		.hton = 1, \
1177 		.offset = offsetof(s, f), \
1178 		.size = sizeof(((s *)0)->f), \
1179 	})
1180 
1181 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1182 #define ARG_ENTRY_HTON(s) \
1183 	(&(const struct arg){ \
1184 		.hton = 1, \
1185 		.offset = 0, \
1186 		.size = sizeof(s), \
1187 	})
1188 
1189 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1190 struct buffer {
1191 	enum index command; /**< Flow command. */
1192 	portid_t port; /**< Affected port ID. */
1193 	queueid_t queue; /** Async queue ID. */
1194 	bool postpone; /** Postpone async operation */
1195 	union {
1196 		struct {
1197 			struct rte_flow_port_attr port_attr;
1198 			uint32_t nb_queue;
1199 			struct rte_flow_queue_attr queue_attr;
1200 		} configure; /**< Configuration arguments. */
1201 		struct {
1202 			uint32_t *template_id;
1203 			uint32_t template_id_n;
1204 		} templ_destroy; /**< Template destroy arguments. */
1205 		struct {
1206 			uint32_t id;
1207 			struct rte_flow_template_table_attr attr;
1208 			uint32_t *pat_templ_id;
1209 			uint32_t pat_templ_id_n;
1210 			uint32_t *act_templ_id;
1211 			uint32_t act_templ_id_n;
1212 		} table; /**< Table arguments. */
1213 		struct {
1214 			uint32_t *table_id;
1215 			uint32_t table_id_n;
1216 		} table_destroy; /**< Template destroy arguments. */
1217 		struct {
1218 			uint32_t *action_id;
1219 			uint32_t action_id_n;
1220 		} ia_destroy; /**< Indirect action destroy arguments. */
1221 		struct {
1222 			uint32_t action_id;
1223 			enum rte_flow_query_update_mode qu_mode;
1224 		} ia; /* Indirect action query arguments */
1225 		struct {
1226 			uint32_t table_id;
1227 			uint32_t pat_templ_id;
1228 			uint32_t rule_id;
1229 			uint32_t act_templ_id;
1230 			struct rte_flow_attr attr;
1231 			struct tunnel_ops tunnel_ops;
1232 			uintptr_t user_id;
1233 			struct rte_flow_item *pattern;
1234 			struct rte_flow_action *actions;
1235 			struct rte_flow_action *masks;
1236 			uint32_t pattern_n;
1237 			uint32_t actions_n;
1238 			uint8_t *data;
1239 			enum rte_flow_encap_hash_field field;
1240 			uint8_t encap_hash;
1241 		} vc; /**< Validate/create arguments. */
1242 		struct {
1243 			uint64_t *rule;
1244 			uint64_t rule_n;
1245 			bool is_user_id;
1246 		} destroy; /**< Destroy arguments. */
1247 		struct {
1248 			char file[128];
1249 			bool mode;
1250 			uint64_t rule;
1251 			bool is_user_id;
1252 		} dump; /**< Dump arguments. */
1253 		struct {
1254 			uint64_t rule;
1255 			struct rte_flow_action action;
1256 			bool is_user_id;
1257 		} query; /**< Query arguments. */
1258 		struct {
1259 			uint32_t *group;
1260 			uint32_t group_n;
1261 		} list; /**< List arguments. */
1262 		struct {
1263 			int set;
1264 		} isolate; /**< Isolated mode arguments. */
1265 		struct {
1266 			int destroy;
1267 		} aged; /**< Aged arguments. */
1268 		struct {
1269 			uint32_t policy_id;
1270 		} policy;/**< Policy arguments. */
1271 		struct {
1272 			uint16_t token;
1273 			uintptr_t uintptr;
1274 			char filename[128];
1275 		} flex; /**< Flex arguments*/
1276 	} args; /**< Command arguments. */
1277 };
1278 
1279 /** Private data for pattern items. */
1280 struct parse_item_priv {
1281 	enum rte_flow_item_type type; /**< Item type. */
1282 	uint32_t size; /**< Size of item specification structure. */
1283 };
1284 
1285 #define PRIV_ITEM(t, s) \
1286 	(&(const struct parse_item_priv){ \
1287 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1288 		.size = s, \
1289 	})
1290 
1291 /** Private data for actions. */
1292 struct parse_action_priv {
1293 	enum rte_flow_action_type type; /**< Action type. */
1294 	uint32_t size; /**< Size of action configuration structure. */
1295 };
1296 
1297 #define PRIV_ACTION(t, s) \
1298 	(&(const struct parse_action_priv){ \
1299 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1300 		.size = s, \
1301 	})
1302 
1303 static const enum index next_flex_item[] = {
1304 	FLEX_ITEM_INIT,
1305 	FLEX_ITEM_CREATE,
1306 	FLEX_ITEM_DESTROY,
1307 	ZERO,
1308 };
1309 
1310 static const enum index next_config_attr[] = {
1311 	CONFIG_QUEUES_NUMBER,
1312 	CONFIG_QUEUES_SIZE,
1313 	CONFIG_COUNTERS_NUMBER,
1314 	CONFIG_AGING_OBJECTS_NUMBER,
1315 	CONFIG_METERS_NUMBER,
1316 	CONFIG_CONN_TRACK_NUMBER,
1317 	CONFIG_QUOTAS_NUMBER,
1318 	CONFIG_FLAGS,
1319 	CONFIG_HOST_PORT,
1320 	END,
1321 	ZERO,
1322 };
1323 
1324 static const enum index next_pt_subcmd[] = {
1325 	PATTERN_TEMPLATE_CREATE,
1326 	PATTERN_TEMPLATE_DESTROY,
1327 	ZERO,
1328 };
1329 
1330 static const enum index next_pt_attr[] = {
1331 	PATTERN_TEMPLATE_CREATE_ID,
1332 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1333 	PATTERN_TEMPLATE_INGRESS,
1334 	PATTERN_TEMPLATE_EGRESS,
1335 	PATTERN_TEMPLATE_TRANSFER,
1336 	PATTERN_TEMPLATE_SPEC,
1337 	ZERO,
1338 };
1339 
1340 static const enum index next_pt_destroy_attr[] = {
1341 	PATTERN_TEMPLATE_DESTROY_ID,
1342 	END,
1343 	ZERO,
1344 };
1345 
1346 static const enum index next_at_subcmd[] = {
1347 	ACTIONS_TEMPLATE_CREATE,
1348 	ACTIONS_TEMPLATE_DESTROY,
1349 	ZERO,
1350 };
1351 
1352 static const enum index next_at_attr[] = {
1353 	ACTIONS_TEMPLATE_CREATE_ID,
1354 	ACTIONS_TEMPLATE_INGRESS,
1355 	ACTIONS_TEMPLATE_EGRESS,
1356 	ACTIONS_TEMPLATE_TRANSFER,
1357 	ACTIONS_TEMPLATE_SPEC,
1358 	ZERO,
1359 };
1360 
1361 static const enum index next_at_destroy_attr[] = {
1362 	ACTIONS_TEMPLATE_DESTROY_ID,
1363 	END,
1364 	ZERO,
1365 };
1366 
1367 static const enum index next_group_attr[] = {
1368 	GROUP_INGRESS,
1369 	GROUP_EGRESS,
1370 	GROUP_TRANSFER,
1371 	GROUP_SET_MISS_ACTIONS,
1372 	ZERO,
1373 };
1374 
1375 static const enum index next_table_subcmd[] = {
1376 	TABLE_CREATE,
1377 	TABLE_DESTROY,
1378 	TABLE_RESIZE,
1379 	TABLE_RESIZE_COMPLETE,
1380 	ZERO,
1381 };
1382 
1383 static const enum index next_table_attr[] = {
1384 	TABLE_CREATE_ID,
1385 	TABLE_GROUP,
1386 	TABLE_INSERTION_TYPE,
1387 	TABLE_HASH_FUNC,
1388 	TABLE_PRIORITY,
1389 	TABLE_INGRESS,
1390 	TABLE_EGRESS,
1391 	TABLE_TRANSFER,
1392 	TABLE_TRANSFER_WIRE_ORIG,
1393 	TABLE_TRANSFER_VPORT_ORIG,
1394 	TABLE_RESIZABLE,
1395 	TABLE_RULES_NUMBER,
1396 	TABLE_PATTERN_TEMPLATE,
1397 	TABLE_ACTIONS_TEMPLATE,
1398 	END,
1399 	ZERO,
1400 };
1401 
1402 static const enum index next_table_destroy_attr[] = {
1403 	TABLE_DESTROY_ID,
1404 	END,
1405 	ZERO,
1406 };
1407 
1408 static const enum index next_queue_subcmd[] = {
1409 	QUEUE_CREATE,
1410 	QUEUE_DESTROY,
1411 	QUEUE_FLOW_UPDATE_RESIZED,
1412 	QUEUE_UPDATE,
1413 	QUEUE_AGED,
1414 	QUEUE_INDIRECT_ACTION,
1415 	ZERO,
1416 };
1417 
1418 static const enum index next_queue_destroy_attr[] = {
1419 	QUEUE_DESTROY_ID,
1420 	END,
1421 	ZERO,
1422 };
1423 
1424 static const enum index next_qia_subcmd[] = {
1425 	QUEUE_INDIRECT_ACTION_CREATE,
1426 	QUEUE_INDIRECT_ACTION_UPDATE,
1427 	QUEUE_INDIRECT_ACTION_DESTROY,
1428 	QUEUE_INDIRECT_ACTION_QUERY,
1429 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1430 	ZERO,
1431 };
1432 
1433 static const enum index next_qia_create_attr[] = {
1434 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1435 	QUEUE_INDIRECT_ACTION_INGRESS,
1436 	QUEUE_INDIRECT_ACTION_EGRESS,
1437 	QUEUE_INDIRECT_ACTION_TRANSFER,
1438 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1439 	QUEUE_INDIRECT_ACTION_SPEC,
1440 	QUEUE_INDIRECT_ACTION_LIST,
1441 	ZERO,
1442 };
1443 
1444 static const enum index next_qia_update_attr[] = {
1445 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1446 	QUEUE_INDIRECT_ACTION_SPEC,
1447 	ZERO,
1448 };
1449 
1450 static const enum index next_qia_destroy_attr[] = {
1451 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1452 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1453 	END,
1454 	ZERO,
1455 };
1456 
1457 static const enum index next_qia_query_attr[] = {
1458 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1459 	END,
1460 	ZERO,
1461 };
1462 
1463 static const enum index next_ia_create_attr[] = {
1464 	INDIRECT_ACTION_CREATE_ID,
1465 	INDIRECT_ACTION_INGRESS,
1466 	INDIRECT_ACTION_EGRESS,
1467 	INDIRECT_ACTION_TRANSFER,
1468 	INDIRECT_ACTION_SPEC,
1469 	INDIRECT_ACTION_LIST,
1470 	INDIRECT_ACTION_FLOW_CONF,
1471 	ZERO,
1472 };
1473 
1474 static const enum index next_ia[] = {
1475 	INDIRECT_ACTION_ID2PTR,
1476 	ACTION_NEXT,
1477 	ZERO
1478 };
1479 
1480 static const enum index next_ial[] = {
1481 	ACTION_INDIRECT_LIST_HANDLE,
1482 	ACTION_INDIRECT_LIST_CONF,
1483 	ACTION_NEXT,
1484 	ZERO
1485 };
1486 
1487 static const enum index next_qia_qu_attr[] = {
1488 	QUEUE_INDIRECT_ACTION_QU_MODE,
1489 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1490 	INDIRECT_ACTION_SPEC,
1491 	ZERO
1492 };
1493 
1494 static const enum index next_ia_qu_attr[] = {
1495 	INDIRECT_ACTION_QU_MODE,
1496 	INDIRECT_ACTION_SPEC,
1497 	ZERO
1498 };
1499 
1500 static const enum index next_dump_subcmd[] = {
1501 	DUMP_ALL,
1502 	DUMP_ONE,
1503 	DUMP_IS_USER_ID,
1504 	ZERO,
1505 };
1506 
1507 static const enum index next_ia_subcmd[] = {
1508 	INDIRECT_ACTION_CREATE,
1509 	INDIRECT_ACTION_UPDATE,
1510 	INDIRECT_ACTION_DESTROY,
1511 	INDIRECT_ACTION_QUERY,
1512 	INDIRECT_ACTION_QUERY_UPDATE,
1513 	ZERO,
1514 };
1515 
1516 static const enum index next_vc_attr[] = {
1517 	VC_GROUP,
1518 	VC_PRIORITY,
1519 	VC_INGRESS,
1520 	VC_EGRESS,
1521 	VC_TRANSFER,
1522 	VC_TUNNEL_SET,
1523 	VC_TUNNEL_MATCH,
1524 	VC_USER_ID,
1525 	ITEM_PATTERN,
1526 	ZERO,
1527 };
1528 
1529 static const enum index next_destroy_attr[] = {
1530 	DESTROY_RULE,
1531 	DESTROY_IS_USER_ID,
1532 	END,
1533 	ZERO,
1534 };
1535 
1536 static const enum index next_dump_attr[] = {
1537 	COMMON_FILE_PATH,
1538 	END,
1539 	ZERO,
1540 };
1541 
1542 static const enum index next_query_attr[] = {
1543 	QUERY_IS_USER_ID,
1544 	END,
1545 	ZERO,
1546 };
1547 
1548 static const enum index next_list_attr[] = {
1549 	LIST_GROUP,
1550 	END,
1551 	ZERO,
1552 };
1553 
1554 static const enum index next_aged_attr[] = {
1555 	AGED_DESTROY,
1556 	END,
1557 	ZERO,
1558 };
1559 
1560 static const enum index next_ia_destroy_attr[] = {
1561 	INDIRECT_ACTION_DESTROY_ID,
1562 	END,
1563 	ZERO,
1564 };
1565 
1566 static const enum index next_async_insert_subcmd[] = {
1567 	QUEUE_PATTERN_TEMPLATE,
1568 	QUEUE_RULE_ID,
1569 	ZERO,
1570 };
1571 
1572 static const enum index item_param[] = {
1573 	ITEM_PARAM_IS,
1574 	ITEM_PARAM_SPEC,
1575 	ITEM_PARAM_LAST,
1576 	ITEM_PARAM_MASK,
1577 	ITEM_PARAM_PREFIX,
1578 	ZERO,
1579 };
1580 
1581 static const enum index next_item[] = {
1582 	ITEM_END,
1583 	ITEM_VOID,
1584 	ITEM_INVERT,
1585 	ITEM_ANY,
1586 	ITEM_PORT_ID,
1587 	ITEM_MARK,
1588 	ITEM_RAW,
1589 	ITEM_ETH,
1590 	ITEM_VLAN,
1591 	ITEM_IPV4,
1592 	ITEM_IPV6,
1593 	ITEM_ICMP,
1594 	ITEM_UDP,
1595 	ITEM_TCP,
1596 	ITEM_SCTP,
1597 	ITEM_VXLAN,
1598 	ITEM_E_TAG,
1599 	ITEM_NVGRE,
1600 	ITEM_MPLS,
1601 	ITEM_GRE,
1602 	ITEM_FUZZY,
1603 	ITEM_GTP,
1604 	ITEM_GTPC,
1605 	ITEM_GTPU,
1606 	ITEM_GENEVE,
1607 	ITEM_VXLAN_GPE,
1608 	ITEM_ARP_ETH_IPV4,
1609 	ITEM_IPV6_EXT,
1610 	ITEM_IPV6_FRAG_EXT,
1611 	ITEM_IPV6_ROUTING_EXT,
1612 	ITEM_ICMP6,
1613 	ITEM_ICMP6_ECHO_REQUEST,
1614 	ITEM_ICMP6_ECHO_REPLY,
1615 	ITEM_ICMP6_ND_NS,
1616 	ITEM_ICMP6_ND_NA,
1617 	ITEM_ICMP6_ND_OPT,
1618 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1619 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1620 	ITEM_META,
1621 	ITEM_RANDOM,
1622 	ITEM_GRE_KEY,
1623 	ITEM_GRE_OPTION,
1624 	ITEM_GTP_PSC,
1625 	ITEM_PPPOES,
1626 	ITEM_PPPOED,
1627 	ITEM_PPPOE_PROTO_ID,
1628 	ITEM_HIGIG2,
1629 	ITEM_TAG,
1630 	ITEM_L2TPV3OIP,
1631 	ITEM_ESP,
1632 	ITEM_AH,
1633 	ITEM_PFCP,
1634 	ITEM_ECPRI,
1635 	ITEM_GENEVE_OPT,
1636 	ITEM_INTEGRITY,
1637 	ITEM_CONNTRACK,
1638 	ITEM_PORT_REPRESENTOR,
1639 	ITEM_REPRESENTED_PORT,
1640 	ITEM_FLEX,
1641 	ITEM_L2TPV2,
1642 	ITEM_PPP,
1643 	ITEM_METER,
1644 	ITEM_QUOTA,
1645 	ITEM_AGGR_AFFINITY,
1646 	ITEM_TX_QUEUE,
1647 	ITEM_IB_BTH,
1648 	ITEM_PTYPE,
1649 	ITEM_NSH,
1650 	ITEM_COMPARE,
1651 	END_SET,
1652 	ZERO,
1653 };
1654 
1655 static const enum index item_fuzzy[] = {
1656 	ITEM_FUZZY_THRESH,
1657 	ITEM_NEXT,
1658 	ZERO,
1659 };
1660 
1661 static const enum index item_any[] = {
1662 	ITEM_ANY_NUM,
1663 	ITEM_NEXT,
1664 	ZERO,
1665 };
1666 
1667 static const enum index item_port_id[] = {
1668 	ITEM_PORT_ID_ID,
1669 	ITEM_NEXT,
1670 	ZERO,
1671 };
1672 
1673 static const enum index item_mark[] = {
1674 	ITEM_MARK_ID,
1675 	ITEM_NEXT,
1676 	ZERO,
1677 };
1678 
1679 static const enum index item_raw[] = {
1680 	ITEM_RAW_RELATIVE,
1681 	ITEM_RAW_SEARCH,
1682 	ITEM_RAW_OFFSET,
1683 	ITEM_RAW_LIMIT,
1684 	ITEM_RAW_PATTERN,
1685 	ITEM_RAW_PATTERN_HEX,
1686 	ITEM_NEXT,
1687 	ZERO,
1688 };
1689 
1690 static const enum index item_eth[] = {
1691 	ITEM_ETH_DST,
1692 	ITEM_ETH_SRC,
1693 	ITEM_ETH_TYPE,
1694 	ITEM_ETH_HAS_VLAN,
1695 	ITEM_NEXT,
1696 	ZERO,
1697 };
1698 
1699 static const enum index item_vlan[] = {
1700 	ITEM_VLAN_TCI,
1701 	ITEM_VLAN_PCP,
1702 	ITEM_VLAN_DEI,
1703 	ITEM_VLAN_VID,
1704 	ITEM_VLAN_INNER_TYPE,
1705 	ITEM_VLAN_HAS_MORE_VLAN,
1706 	ITEM_NEXT,
1707 	ZERO,
1708 };
1709 
1710 static const enum index item_ipv4[] = {
1711 	ITEM_IPV4_VER_IHL,
1712 	ITEM_IPV4_TOS,
1713 	ITEM_IPV4_LENGTH,
1714 	ITEM_IPV4_ID,
1715 	ITEM_IPV4_FRAGMENT_OFFSET,
1716 	ITEM_IPV4_TTL,
1717 	ITEM_IPV4_PROTO,
1718 	ITEM_IPV4_SRC,
1719 	ITEM_IPV4_DST,
1720 	ITEM_NEXT,
1721 	ZERO,
1722 };
1723 
1724 static const enum index item_ipv6[] = {
1725 	ITEM_IPV6_TC,
1726 	ITEM_IPV6_FLOW,
1727 	ITEM_IPV6_LEN,
1728 	ITEM_IPV6_PROTO,
1729 	ITEM_IPV6_HOP,
1730 	ITEM_IPV6_SRC,
1731 	ITEM_IPV6_DST,
1732 	ITEM_IPV6_HAS_FRAG_EXT,
1733 	ITEM_IPV6_ROUTING_EXT,
1734 	ITEM_NEXT,
1735 	ZERO,
1736 };
1737 
1738 static const enum index item_ipv6_routing_ext[] = {
1739 	ITEM_IPV6_ROUTING_EXT_TYPE,
1740 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1741 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1742 	ITEM_NEXT,
1743 	ZERO,
1744 };
1745 
1746 static const enum index item_icmp[] = {
1747 	ITEM_ICMP_TYPE,
1748 	ITEM_ICMP_CODE,
1749 	ITEM_ICMP_IDENT,
1750 	ITEM_ICMP_SEQ,
1751 	ITEM_NEXT,
1752 	ZERO,
1753 };
1754 
1755 static const enum index item_udp[] = {
1756 	ITEM_UDP_SRC,
1757 	ITEM_UDP_DST,
1758 	ITEM_NEXT,
1759 	ZERO,
1760 };
1761 
1762 static const enum index item_tcp[] = {
1763 	ITEM_TCP_SRC,
1764 	ITEM_TCP_DST,
1765 	ITEM_TCP_FLAGS,
1766 	ITEM_NEXT,
1767 	ZERO,
1768 };
1769 
1770 static const enum index item_sctp[] = {
1771 	ITEM_SCTP_SRC,
1772 	ITEM_SCTP_DST,
1773 	ITEM_SCTP_TAG,
1774 	ITEM_SCTP_CKSUM,
1775 	ITEM_NEXT,
1776 	ZERO,
1777 };
1778 
1779 static const enum index item_vxlan[] = {
1780 	ITEM_VXLAN_VNI,
1781 	ITEM_VXLAN_LAST_RSVD,
1782 	ITEM_NEXT,
1783 	ZERO,
1784 };
1785 
1786 static const enum index item_e_tag[] = {
1787 	ITEM_E_TAG_GRP_ECID_B,
1788 	ITEM_NEXT,
1789 	ZERO,
1790 };
1791 
1792 static const enum index item_nvgre[] = {
1793 	ITEM_NVGRE_TNI,
1794 	ITEM_NEXT,
1795 	ZERO,
1796 };
1797 
1798 static const enum index item_mpls[] = {
1799 	ITEM_MPLS_LABEL,
1800 	ITEM_MPLS_TC,
1801 	ITEM_MPLS_S,
1802 	ITEM_MPLS_TTL,
1803 	ITEM_NEXT,
1804 	ZERO,
1805 };
1806 
1807 static const enum index item_gre[] = {
1808 	ITEM_GRE_PROTO,
1809 	ITEM_GRE_C_RSVD0_VER,
1810 	ITEM_GRE_C_BIT,
1811 	ITEM_GRE_K_BIT,
1812 	ITEM_GRE_S_BIT,
1813 	ITEM_NEXT,
1814 	ZERO,
1815 };
1816 
1817 static const enum index item_gre_key[] = {
1818 	ITEM_GRE_KEY_VALUE,
1819 	ITEM_NEXT,
1820 	ZERO,
1821 };
1822 
1823 static const enum index item_gre_option[] = {
1824 	ITEM_GRE_OPTION_CHECKSUM,
1825 	ITEM_GRE_OPTION_KEY,
1826 	ITEM_GRE_OPTION_SEQUENCE,
1827 	ITEM_NEXT,
1828 	ZERO,
1829 };
1830 
1831 static const enum index item_gtp[] = {
1832 	ITEM_GTP_FLAGS,
1833 	ITEM_GTP_MSG_TYPE,
1834 	ITEM_GTP_TEID,
1835 	ITEM_NEXT,
1836 	ZERO,
1837 };
1838 
1839 static const enum index item_geneve[] = {
1840 	ITEM_GENEVE_VNI,
1841 	ITEM_GENEVE_PROTO,
1842 	ITEM_GENEVE_OPTLEN,
1843 	ITEM_NEXT,
1844 	ZERO,
1845 };
1846 
1847 static const enum index item_vxlan_gpe[] = {
1848 	ITEM_VXLAN_GPE_VNI,
1849 	ITEM_VXLAN_GPE_PROTO,
1850 	ITEM_VXLAN_GPE_FLAGS,
1851 	ITEM_VXLAN_GPE_RSVD0,
1852 	ITEM_VXLAN_GPE_RSVD1,
1853 	ITEM_NEXT,
1854 	ZERO,
1855 };
1856 
1857 static const enum index item_arp_eth_ipv4[] = {
1858 	ITEM_ARP_ETH_IPV4_SHA,
1859 	ITEM_ARP_ETH_IPV4_SPA,
1860 	ITEM_ARP_ETH_IPV4_THA,
1861 	ITEM_ARP_ETH_IPV4_TPA,
1862 	ITEM_NEXT,
1863 	ZERO,
1864 };
1865 
1866 static const enum index item_ipv6_ext[] = {
1867 	ITEM_IPV6_EXT_NEXT_HDR,
1868 	ITEM_NEXT,
1869 	ZERO,
1870 };
1871 
1872 static const enum index item_ipv6_frag_ext[] = {
1873 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1874 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1875 	ITEM_IPV6_FRAG_EXT_ID,
1876 	ITEM_NEXT,
1877 	ZERO,
1878 };
1879 
1880 static const enum index item_icmp6[] = {
1881 	ITEM_ICMP6_TYPE,
1882 	ITEM_ICMP6_CODE,
1883 	ITEM_NEXT,
1884 	ZERO,
1885 };
1886 
1887 static const enum index item_icmp6_echo_request[] = {
1888 	ITEM_ICMP6_ECHO_REQUEST_ID,
1889 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1890 	ITEM_NEXT,
1891 	ZERO,
1892 };
1893 
1894 static const enum index item_icmp6_echo_reply[] = {
1895 	ITEM_ICMP6_ECHO_REPLY_ID,
1896 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1897 	ITEM_NEXT,
1898 	ZERO,
1899 };
1900 
1901 static const enum index item_icmp6_nd_ns[] = {
1902 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1903 	ITEM_NEXT,
1904 	ZERO,
1905 };
1906 
1907 static const enum index item_icmp6_nd_na[] = {
1908 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1909 	ITEM_NEXT,
1910 	ZERO,
1911 };
1912 
1913 static const enum index item_icmp6_nd_opt[] = {
1914 	ITEM_ICMP6_ND_OPT_TYPE,
1915 	ITEM_NEXT,
1916 	ZERO,
1917 };
1918 
1919 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1920 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1921 	ITEM_NEXT,
1922 	ZERO,
1923 };
1924 
1925 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1926 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1927 	ITEM_NEXT,
1928 	ZERO,
1929 };
1930 
1931 static const enum index item_meta[] = {
1932 	ITEM_META_DATA,
1933 	ITEM_NEXT,
1934 	ZERO,
1935 };
1936 
1937 static const enum index item_random[] = {
1938 	ITEM_RANDOM_VALUE,
1939 	ITEM_NEXT,
1940 	ZERO,
1941 };
1942 
1943 static const enum index item_gtp_psc[] = {
1944 	ITEM_GTP_PSC_QFI,
1945 	ITEM_GTP_PSC_PDU_T,
1946 	ITEM_NEXT,
1947 	ZERO,
1948 };
1949 
1950 static const enum index item_pppoed[] = {
1951 	ITEM_PPPOE_SEID,
1952 	ITEM_NEXT,
1953 	ZERO,
1954 };
1955 
1956 static const enum index item_pppoes[] = {
1957 	ITEM_PPPOE_SEID,
1958 	ITEM_NEXT,
1959 	ZERO,
1960 };
1961 
1962 static const enum index item_pppoe_proto_id[] = {
1963 	ITEM_NEXT,
1964 	ZERO,
1965 };
1966 
1967 static const enum index item_higig2[] = {
1968 	ITEM_HIGIG2_CLASSIFICATION,
1969 	ITEM_HIGIG2_VID,
1970 	ITEM_NEXT,
1971 	ZERO,
1972 };
1973 
1974 static const enum index item_esp[] = {
1975 	ITEM_ESP_SPI,
1976 	ITEM_NEXT,
1977 	ZERO,
1978 };
1979 
1980 static const enum index item_ah[] = {
1981 	ITEM_AH_SPI,
1982 	ITEM_NEXT,
1983 	ZERO,
1984 };
1985 
1986 static const enum index item_pfcp[] = {
1987 	ITEM_PFCP_S_FIELD,
1988 	ITEM_PFCP_SEID,
1989 	ITEM_NEXT,
1990 	ZERO,
1991 };
1992 
1993 static const enum index next_set_raw[] = {
1994 	SET_RAW_INDEX,
1995 	ITEM_ETH,
1996 	ZERO,
1997 };
1998 
1999 static const enum index item_tag[] = {
2000 	ITEM_TAG_DATA,
2001 	ITEM_TAG_INDEX,
2002 	ITEM_NEXT,
2003 	ZERO,
2004 };
2005 
2006 static const enum index item_l2tpv3oip[] = {
2007 	ITEM_L2TPV3OIP_SESSION_ID,
2008 	ITEM_NEXT,
2009 	ZERO,
2010 };
2011 
2012 static const enum index item_ecpri[] = {
2013 	ITEM_ECPRI_COMMON,
2014 	ITEM_NEXT,
2015 	ZERO,
2016 };
2017 
2018 static const enum index item_ecpri_common[] = {
2019 	ITEM_ECPRI_COMMON_TYPE,
2020 	ZERO,
2021 };
2022 
2023 static const enum index item_ecpri_common_type[] = {
2024 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2025 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2026 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2027 	ZERO,
2028 };
2029 
2030 static const enum index item_geneve_opt[] = {
2031 	ITEM_GENEVE_OPT_CLASS,
2032 	ITEM_GENEVE_OPT_TYPE,
2033 	ITEM_GENEVE_OPT_LENGTH,
2034 	ITEM_GENEVE_OPT_DATA,
2035 	ITEM_NEXT,
2036 	ZERO,
2037 };
2038 
2039 static const enum index item_integrity[] = {
2040 	ITEM_INTEGRITY_LEVEL,
2041 	ITEM_INTEGRITY_VALUE,
2042 	ZERO,
2043 };
2044 
2045 static const enum index item_integrity_lv[] = {
2046 	ITEM_INTEGRITY_LEVEL,
2047 	ITEM_INTEGRITY_VALUE,
2048 	ITEM_NEXT,
2049 	ZERO,
2050 };
2051 
2052 static const enum index item_port_representor[] = {
2053 	ITEM_PORT_REPRESENTOR_PORT_ID,
2054 	ITEM_NEXT,
2055 	ZERO,
2056 };
2057 
2058 static const enum index item_represented_port[] = {
2059 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2060 	ITEM_NEXT,
2061 	ZERO,
2062 };
2063 
2064 static const enum index item_flex[] = {
2065 	ITEM_FLEX_PATTERN_HANDLE,
2066 	ITEM_FLEX_ITEM_HANDLE,
2067 	ITEM_NEXT,
2068 	ZERO,
2069 };
2070 
2071 static const enum index item_l2tpv2[] = {
2072 	ITEM_L2TPV2_TYPE,
2073 	ITEM_NEXT,
2074 	ZERO,
2075 };
2076 
2077 static const enum index item_l2tpv2_type[] = {
2078 	ITEM_L2TPV2_TYPE_DATA,
2079 	ITEM_L2TPV2_TYPE_DATA_L,
2080 	ITEM_L2TPV2_TYPE_DATA_S,
2081 	ITEM_L2TPV2_TYPE_DATA_O,
2082 	ITEM_L2TPV2_TYPE_DATA_L_S,
2083 	ITEM_L2TPV2_TYPE_CTRL,
2084 	ZERO,
2085 };
2086 
2087 static const enum index item_l2tpv2_type_data[] = {
2088 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2089 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2090 	ITEM_NEXT,
2091 	ZERO,
2092 };
2093 
2094 static const enum index item_l2tpv2_type_data_l[] = {
2095 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2096 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2097 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2098 	ITEM_NEXT,
2099 	ZERO,
2100 };
2101 
2102 static const enum index item_l2tpv2_type_data_s[] = {
2103 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2104 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2105 	ITEM_L2TPV2_MSG_DATA_S_NS,
2106 	ITEM_L2TPV2_MSG_DATA_S_NR,
2107 	ITEM_NEXT,
2108 	ZERO,
2109 };
2110 
2111 static const enum index item_l2tpv2_type_data_o[] = {
2112 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2113 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2114 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2115 	ITEM_NEXT,
2116 	ZERO,
2117 };
2118 
2119 static const enum index item_l2tpv2_type_data_l_s[] = {
2120 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2121 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2122 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2123 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2124 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2125 	ITEM_NEXT,
2126 	ZERO,
2127 };
2128 
2129 static const enum index item_l2tpv2_type_ctrl[] = {
2130 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2131 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2132 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2133 	ITEM_L2TPV2_MSG_CTRL_NS,
2134 	ITEM_L2TPV2_MSG_CTRL_NR,
2135 	ITEM_NEXT,
2136 	ZERO,
2137 };
2138 
2139 static const enum index item_ppp[] = {
2140 	ITEM_PPP_ADDR,
2141 	ITEM_PPP_CTRL,
2142 	ITEM_PPP_PROTO_ID,
2143 	ITEM_NEXT,
2144 	ZERO,
2145 };
2146 
2147 static const enum index item_meter[] = {
2148 	ITEM_METER_COLOR,
2149 	ITEM_NEXT,
2150 	ZERO,
2151 };
2152 
2153 static const enum index item_quota[] = {
2154 	ITEM_QUOTA_STATE,
2155 	ITEM_NEXT,
2156 	ZERO,
2157 };
2158 
2159 static const enum index item_aggr_affinity[] = {
2160 	ITEM_AGGR_AFFINITY_VALUE,
2161 	ITEM_NEXT,
2162 	ZERO,
2163 };
2164 
2165 static const enum index item_tx_queue[] = {
2166 	ITEM_TX_QUEUE_VALUE,
2167 	ITEM_NEXT,
2168 	ZERO,
2169 };
2170 
2171 static const enum index item_ib_bth[] = {
2172 	ITEM_IB_BTH_OPCODE,
2173 	ITEM_IB_BTH_PKEY,
2174 	ITEM_IB_BTH_DST_QPN,
2175 	ITEM_IB_BTH_PSN,
2176 	ITEM_NEXT,
2177 	ZERO,
2178 };
2179 
2180 static const enum index item_ptype[] = {
2181 	ITEM_PTYPE_VALUE,
2182 	ITEM_NEXT,
2183 	ZERO,
2184 };
2185 
2186 static const enum index item_nsh[] = {
2187 	ITEM_NEXT,
2188 	ZERO,
2189 };
2190 
2191 static const enum index item_compare_field[] = {
2192 	ITEM_COMPARE_OP,
2193 	ITEM_COMPARE_FIELD_A_TYPE,
2194 	ITEM_COMPARE_FIELD_B_TYPE,
2195 	ITEM_NEXT,
2196 	ZERO,
2197 };
2198 
2199 static const enum index compare_field_a[] = {
2200 	ITEM_COMPARE_FIELD_A_TYPE,
2201 	ITEM_COMPARE_FIELD_A_LEVEL,
2202 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2203 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2204 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2205 	ITEM_COMPARE_FIELD_A_OFFSET,
2206 	ITEM_COMPARE_FIELD_B_TYPE,
2207 	ZERO,
2208 };
2209 
2210 static const enum index compare_field_b[] = {
2211 	ITEM_COMPARE_FIELD_B_TYPE,
2212 	ITEM_COMPARE_FIELD_B_LEVEL,
2213 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2214 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2215 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2216 	ITEM_COMPARE_FIELD_B_OFFSET,
2217 	ITEM_COMPARE_FIELD_B_VALUE,
2218 	ITEM_COMPARE_FIELD_B_POINTER,
2219 	ITEM_COMPARE_FIELD_WIDTH,
2220 	ZERO,
2221 };
2222 
2223 static const enum index next_action[] = {
2224 	ACTION_END,
2225 	ACTION_VOID,
2226 	ACTION_PASSTHRU,
2227 	ACTION_SKIP_CMAN,
2228 	ACTION_JUMP,
2229 	ACTION_MARK,
2230 	ACTION_FLAG,
2231 	ACTION_QUEUE,
2232 	ACTION_DROP,
2233 	ACTION_COUNT,
2234 	ACTION_RSS,
2235 	ACTION_PF,
2236 	ACTION_VF,
2237 	ACTION_PORT_ID,
2238 	ACTION_METER,
2239 	ACTION_METER_COLOR,
2240 	ACTION_METER_MARK,
2241 	ACTION_OF_DEC_NW_TTL,
2242 	ACTION_OF_POP_VLAN,
2243 	ACTION_OF_PUSH_VLAN,
2244 	ACTION_OF_SET_VLAN_VID,
2245 	ACTION_OF_SET_VLAN_PCP,
2246 	ACTION_OF_POP_MPLS,
2247 	ACTION_OF_PUSH_MPLS,
2248 	ACTION_VXLAN_ENCAP,
2249 	ACTION_VXLAN_DECAP,
2250 	ACTION_NVGRE_ENCAP,
2251 	ACTION_NVGRE_DECAP,
2252 	ACTION_L2_ENCAP,
2253 	ACTION_L2_DECAP,
2254 	ACTION_MPLSOGRE_ENCAP,
2255 	ACTION_MPLSOGRE_DECAP,
2256 	ACTION_MPLSOUDP_ENCAP,
2257 	ACTION_MPLSOUDP_DECAP,
2258 	ACTION_SET_IPV4_SRC,
2259 	ACTION_SET_IPV4_DST,
2260 	ACTION_SET_IPV6_SRC,
2261 	ACTION_SET_IPV6_DST,
2262 	ACTION_SET_TP_SRC,
2263 	ACTION_SET_TP_DST,
2264 	ACTION_MAC_SWAP,
2265 	ACTION_DEC_TTL,
2266 	ACTION_SET_TTL,
2267 	ACTION_SET_MAC_SRC,
2268 	ACTION_SET_MAC_DST,
2269 	ACTION_INC_TCP_SEQ,
2270 	ACTION_DEC_TCP_SEQ,
2271 	ACTION_INC_TCP_ACK,
2272 	ACTION_DEC_TCP_ACK,
2273 	ACTION_RAW_ENCAP,
2274 	ACTION_RAW_DECAP,
2275 	ACTION_SET_TAG,
2276 	ACTION_SET_META,
2277 	ACTION_SET_IPV4_DSCP,
2278 	ACTION_SET_IPV6_DSCP,
2279 	ACTION_AGE,
2280 	ACTION_AGE_UPDATE,
2281 	ACTION_SAMPLE,
2282 	ACTION_INDIRECT,
2283 	ACTION_INDIRECT_LIST,
2284 	ACTION_SHARED_INDIRECT,
2285 	ACTION_MODIFY_FIELD,
2286 	ACTION_CONNTRACK,
2287 	ACTION_CONNTRACK_UPDATE,
2288 	ACTION_PORT_REPRESENTOR,
2289 	ACTION_REPRESENTED_PORT,
2290 	ACTION_SEND_TO_KERNEL,
2291 	ACTION_QUOTA_CREATE,
2292 	ACTION_QUOTA_QU,
2293 	ACTION_IPV6_EXT_REMOVE,
2294 	ACTION_IPV6_EXT_PUSH,
2295 	ACTION_NAT64,
2296 	ZERO,
2297 };
2298 
2299 static const enum index action_quota_create[] = {
2300 	ACTION_QUOTA_CREATE_LIMIT,
2301 	ACTION_QUOTA_CREATE_MODE,
2302 	ACTION_NEXT,
2303 	ZERO
2304 };
2305 
2306 static const enum index action_quota_update[] = {
2307 	ACTION_QUOTA_QU_LIMIT,
2308 	ACTION_QUOTA_QU_UPDATE_OP,
2309 	ACTION_NEXT,
2310 	ZERO
2311 };
2312 
2313 static const enum index action_mark[] = {
2314 	ACTION_MARK_ID,
2315 	ACTION_NEXT,
2316 	ZERO,
2317 };
2318 
2319 static const enum index action_queue[] = {
2320 	ACTION_QUEUE_INDEX,
2321 	ACTION_NEXT,
2322 	ZERO,
2323 };
2324 
2325 static const enum index action_count[] = {
2326 	ACTION_COUNT_ID,
2327 	ACTION_NEXT,
2328 	ZERO,
2329 };
2330 
2331 static const enum index action_rss[] = {
2332 	ACTION_RSS_FUNC,
2333 	ACTION_RSS_LEVEL,
2334 	ACTION_RSS_TYPES,
2335 	ACTION_RSS_KEY,
2336 	ACTION_RSS_KEY_LEN,
2337 	ACTION_RSS_QUEUES,
2338 	ACTION_NEXT,
2339 	ZERO,
2340 };
2341 
2342 static const enum index action_vf[] = {
2343 	ACTION_VF_ORIGINAL,
2344 	ACTION_VF_ID,
2345 	ACTION_NEXT,
2346 	ZERO,
2347 };
2348 
2349 static const enum index action_port_id[] = {
2350 	ACTION_PORT_ID_ORIGINAL,
2351 	ACTION_PORT_ID_ID,
2352 	ACTION_NEXT,
2353 	ZERO,
2354 };
2355 
2356 static const enum index action_meter[] = {
2357 	ACTION_METER_ID,
2358 	ACTION_NEXT,
2359 	ZERO,
2360 };
2361 
2362 static const enum index action_meter_color[] = {
2363 	ACTION_METER_COLOR_TYPE,
2364 	ACTION_NEXT,
2365 	ZERO,
2366 };
2367 
2368 static const enum index action_meter_mark[] = {
2369 	ACTION_METER_PROFILE,
2370 	ACTION_METER_POLICY,
2371 	ACTION_METER_COLOR_MODE,
2372 	ACTION_METER_STATE,
2373 	ACTION_NEXT,
2374 	ZERO,
2375 };
2376 
2377 static const enum index action_of_push_vlan[] = {
2378 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2379 	ACTION_NEXT,
2380 	ZERO,
2381 };
2382 
2383 static const enum index action_of_set_vlan_vid[] = {
2384 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2385 	ACTION_NEXT,
2386 	ZERO,
2387 };
2388 
2389 static const enum index action_of_set_vlan_pcp[] = {
2390 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2391 	ACTION_NEXT,
2392 	ZERO,
2393 };
2394 
2395 static const enum index action_of_pop_mpls[] = {
2396 	ACTION_OF_POP_MPLS_ETHERTYPE,
2397 	ACTION_NEXT,
2398 	ZERO,
2399 };
2400 
2401 static const enum index action_of_push_mpls[] = {
2402 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2403 	ACTION_NEXT,
2404 	ZERO,
2405 };
2406 
2407 static const enum index action_set_ipv4_src[] = {
2408 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2409 	ACTION_NEXT,
2410 	ZERO,
2411 };
2412 
2413 static const enum index action_set_mac_src[] = {
2414 	ACTION_SET_MAC_SRC_MAC_SRC,
2415 	ACTION_NEXT,
2416 	ZERO,
2417 };
2418 
2419 static const enum index action_set_ipv4_dst[] = {
2420 	ACTION_SET_IPV4_DST_IPV4_DST,
2421 	ACTION_NEXT,
2422 	ZERO,
2423 };
2424 
2425 static const enum index action_set_ipv6_src[] = {
2426 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2427 	ACTION_NEXT,
2428 	ZERO,
2429 };
2430 
2431 static const enum index action_set_ipv6_dst[] = {
2432 	ACTION_SET_IPV6_DST_IPV6_DST,
2433 	ACTION_NEXT,
2434 	ZERO,
2435 };
2436 
2437 static const enum index action_set_tp_src[] = {
2438 	ACTION_SET_TP_SRC_TP_SRC,
2439 	ACTION_NEXT,
2440 	ZERO,
2441 };
2442 
2443 static const enum index action_set_tp_dst[] = {
2444 	ACTION_SET_TP_DST_TP_DST,
2445 	ACTION_NEXT,
2446 	ZERO,
2447 };
2448 
2449 static const enum index action_set_ttl[] = {
2450 	ACTION_SET_TTL_TTL,
2451 	ACTION_NEXT,
2452 	ZERO,
2453 };
2454 
2455 static const enum index action_jump[] = {
2456 	ACTION_JUMP_GROUP,
2457 	ACTION_NEXT,
2458 	ZERO,
2459 };
2460 
2461 static const enum index action_set_mac_dst[] = {
2462 	ACTION_SET_MAC_DST_MAC_DST,
2463 	ACTION_NEXT,
2464 	ZERO,
2465 };
2466 
2467 static const enum index action_inc_tcp_seq[] = {
2468 	ACTION_INC_TCP_SEQ_VALUE,
2469 	ACTION_NEXT,
2470 	ZERO,
2471 };
2472 
2473 static const enum index action_dec_tcp_seq[] = {
2474 	ACTION_DEC_TCP_SEQ_VALUE,
2475 	ACTION_NEXT,
2476 	ZERO,
2477 };
2478 
2479 static const enum index action_inc_tcp_ack[] = {
2480 	ACTION_INC_TCP_ACK_VALUE,
2481 	ACTION_NEXT,
2482 	ZERO,
2483 };
2484 
2485 static const enum index action_dec_tcp_ack[] = {
2486 	ACTION_DEC_TCP_ACK_VALUE,
2487 	ACTION_NEXT,
2488 	ZERO,
2489 };
2490 
2491 static const enum index action_raw_encap[] = {
2492 	ACTION_RAW_ENCAP_SIZE,
2493 	ACTION_RAW_ENCAP_INDEX,
2494 	ACTION_NEXT,
2495 	ZERO,
2496 };
2497 
2498 static const enum index action_raw_decap[] = {
2499 	ACTION_RAW_DECAP_INDEX,
2500 	ACTION_NEXT,
2501 	ZERO,
2502 };
2503 
2504 static const enum index action_ipv6_ext_remove[] = {
2505 	ACTION_IPV6_EXT_REMOVE_INDEX,
2506 	ACTION_NEXT,
2507 	ZERO,
2508 };
2509 
2510 static const enum index action_ipv6_ext_push[] = {
2511 	ACTION_IPV6_EXT_PUSH_INDEX,
2512 	ACTION_NEXT,
2513 	ZERO,
2514 };
2515 
2516 static const enum index action_set_tag[] = {
2517 	ACTION_SET_TAG_DATA,
2518 	ACTION_SET_TAG_INDEX,
2519 	ACTION_SET_TAG_MASK,
2520 	ACTION_NEXT,
2521 	ZERO,
2522 };
2523 
2524 static const enum index action_set_meta[] = {
2525 	ACTION_SET_META_DATA,
2526 	ACTION_SET_META_MASK,
2527 	ACTION_NEXT,
2528 	ZERO,
2529 };
2530 
2531 static const enum index action_set_ipv4_dscp[] = {
2532 	ACTION_SET_IPV4_DSCP_VALUE,
2533 	ACTION_NEXT,
2534 	ZERO,
2535 };
2536 
2537 static const enum index action_set_ipv6_dscp[] = {
2538 	ACTION_SET_IPV6_DSCP_VALUE,
2539 	ACTION_NEXT,
2540 	ZERO,
2541 };
2542 
2543 static const enum index action_age[] = {
2544 	ACTION_AGE,
2545 	ACTION_AGE_TIMEOUT,
2546 	ACTION_NEXT,
2547 	ZERO,
2548 };
2549 
2550 static const enum index action_age_update[] = {
2551 	ACTION_AGE_UPDATE,
2552 	ACTION_AGE_UPDATE_TIMEOUT,
2553 	ACTION_AGE_UPDATE_TOUCH,
2554 	ACTION_NEXT,
2555 	ZERO,
2556 };
2557 
2558 static const enum index action_sample[] = {
2559 	ACTION_SAMPLE,
2560 	ACTION_SAMPLE_RATIO,
2561 	ACTION_SAMPLE_INDEX,
2562 	ACTION_NEXT,
2563 	ZERO,
2564 };
2565 
2566 static const enum index next_action_sample[] = {
2567 	ACTION_QUEUE,
2568 	ACTION_RSS,
2569 	ACTION_MARK,
2570 	ACTION_COUNT,
2571 	ACTION_PORT_ID,
2572 	ACTION_RAW_ENCAP,
2573 	ACTION_VXLAN_ENCAP,
2574 	ACTION_NVGRE_ENCAP,
2575 	ACTION_REPRESENTED_PORT,
2576 	ACTION_PORT_REPRESENTOR,
2577 	ACTION_NEXT,
2578 	ZERO,
2579 };
2580 
2581 static const enum index item_ipv6_push_ext[] = {
2582 	ITEM_IPV6_PUSH_REMOVE_EXT,
2583 	ZERO,
2584 };
2585 
2586 static const enum index item_ipv6_push_ext_type[] = {
2587 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2588 	ZERO,
2589 };
2590 
2591 static const enum index item_ipv6_push_ext_header[] = {
2592 	ITEM_IPV6_ROUTING_EXT,
2593 	ITEM_NEXT,
2594 	ZERO,
2595 };
2596 
2597 static const enum index action_modify_field_dst[] = {
2598 	ACTION_MODIFY_FIELD_DST_LEVEL,
2599 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2600 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2601 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2602 	ACTION_MODIFY_FIELD_DST_OFFSET,
2603 	ACTION_MODIFY_FIELD_SRC_TYPE,
2604 	ZERO,
2605 };
2606 
2607 static const enum index action_modify_field_src[] = {
2608 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2609 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2610 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2611 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2612 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2613 	ACTION_MODIFY_FIELD_SRC_VALUE,
2614 	ACTION_MODIFY_FIELD_SRC_POINTER,
2615 	ACTION_MODIFY_FIELD_WIDTH,
2616 	ZERO,
2617 };
2618 
2619 static const enum index action_update_conntrack[] = {
2620 	ACTION_CONNTRACK_UPDATE_DIR,
2621 	ACTION_CONNTRACK_UPDATE_CTX,
2622 	ACTION_NEXT,
2623 	ZERO,
2624 };
2625 
2626 static const enum index action_port_representor[] = {
2627 	ACTION_PORT_REPRESENTOR_PORT_ID,
2628 	ACTION_NEXT,
2629 	ZERO,
2630 };
2631 
2632 static const enum index action_represented_port[] = {
2633 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2634 	ACTION_NEXT,
2635 	ZERO,
2636 };
2637 
2638 static const enum index action_nat64[] = {
2639 	ACTION_NAT64_MODE,
2640 	ACTION_NEXT,
2641 	ZERO,
2642 };
2643 
2644 static const enum index next_hash_subcmd[] = {
2645 	HASH_CALC_TABLE,
2646 	HASH_CALC_ENCAP,
2647 	ZERO,
2648 };
2649 
2650 static const enum index next_hash_encap_dest_subcmd[] = {
2651 	ENCAP_HASH_FIELD_SRC_PORT,
2652 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2653 	ZERO,
2654 };
2655 
2656 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2657 				     const char *, unsigned int,
2658 				     void *, unsigned int);
2659 static int parse_set_sample_action(struct context *, const struct token *,
2660 				   const char *, unsigned int,
2661 				   void *, unsigned int);
2662 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2663 				     const char *, unsigned int,
2664 				     void *, unsigned int);
2665 static int parse_set_init(struct context *, const struct token *,
2666 			  const char *, unsigned int,
2667 			  void *, unsigned int);
2668 static int
2669 parse_flex_handle(struct context *, const struct token *,
2670 		  const char *, unsigned int, void *, unsigned int);
2671 static int parse_init(struct context *, const struct token *,
2672 		      const char *, unsigned int,
2673 		      void *, unsigned int);
2674 static int parse_vc(struct context *, const struct token *,
2675 		    const char *, unsigned int,
2676 		    void *, unsigned int);
2677 static int parse_vc_spec(struct context *, const struct token *,
2678 			 const char *, unsigned int, void *, unsigned int);
2679 static int parse_vc_conf(struct context *, const struct token *,
2680 			 const char *, unsigned int, void *, unsigned int);
2681 static int parse_vc_conf_timeout(struct context *, const struct token *,
2682 				 const char *, unsigned int, void *,
2683 				 unsigned int);
2684 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2685 				    const char *, unsigned int,
2686 				    void *, unsigned int);
2687 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2688 				    const char *, unsigned int,
2689 				    void *, unsigned int);
2690 static int parse_vc_action_meter_color_type(struct context *,
2691 					const struct token *,
2692 					const char *, unsigned int, void *,
2693 					unsigned int);
2694 static int parse_vc_action_rss(struct context *, const struct token *,
2695 			       const char *, unsigned int, void *,
2696 			       unsigned int);
2697 static int parse_vc_action_rss_func(struct context *, const struct token *,
2698 				    const char *, unsigned int, void *,
2699 				    unsigned int);
2700 static int parse_vc_action_rss_type(struct context *, const struct token *,
2701 				    const char *, unsigned int, void *,
2702 				    unsigned int);
2703 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2704 				     const char *, unsigned int, void *,
2705 				     unsigned int);
2706 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2707 				       const char *, unsigned int, void *,
2708 				       unsigned int);
2709 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2710 				       const char *, unsigned int, void *,
2711 				       unsigned int);
2712 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2713 				    const char *, unsigned int, void *,
2714 				    unsigned int);
2715 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2716 				    const char *, unsigned int, void *,
2717 				    unsigned int);
2718 static int parse_vc_action_mplsogre_encap(struct context *,
2719 					  const struct token *, const char *,
2720 					  unsigned int, void *, unsigned int);
2721 static int parse_vc_action_mplsogre_decap(struct context *,
2722 					  const struct token *, const char *,
2723 					  unsigned int, void *, unsigned int);
2724 static int parse_vc_action_mplsoudp_encap(struct context *,
2725 					  const struct token *, const char *,
2726 					  unsigned int, void *, unsigned int);
2727 static int parse_vc_action_mplsoudp_decap(struct context *,
2728 					  const struct token *, const char *,
2729 					  unsigned int, void *, unsigned int);
2730 static int parse_vc_action_raw_encap(struct context *,
2731 				     const struct token *, const char *,
2732 				     unsigned int, void *, unsigned int);
2733 static int parse_vc_action_raw_decap(struct context *,
2734 				     const struct token *, const char *,
2735 				     unsigned int, void *, unsigned int);
2736 static int parse_vc_action_raw_encap_index(struct context *,
2737 					   const struct token *, const char *,
2738 					   unsigned int, void *, unsigned int);
2739 static int parse_vc_action_raw_decap_index(struct context *,
2740 					   const struct token *, const char *,
2741 					   unsigned int, void *, unsigned int);
2742 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2743 					   const char *str, unsigned int len, void *buf,
2744 					   unsigned int size);
2745 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2746 						 const struct token *token,
2747 						 const char *str, unsigned int len,
2748 						 void *buf,
2749 						 unsigned int size);
2750 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2751 					 const char *str, unsigned int len, void *buf,
2752 					 unsigned int size);
2753 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2754 					       const struct token *token,
2755 					       const char *str, unsigned int len,
2756 					       void *buf,
2757 					       unsigned int size);
2758 static int parse_vc_action_set_meta(struct context *ctx,
2759 				    const struct token *token, const char *str,
2760 				    unsigned int len, void *buf,
2761 					unsigned int size);
2762 static int parse_vc_action_sample(struct context *ctx,
2763 				    const struct token *token, const char *str,
2764 				    unsigned int len, void *buf,
2765 				    unsigned int size);
2766 static int
2767 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2768 				const char *str, unsigned int len, void *buf,
2769 				unsigned int size);
2770 static int
2771 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2772 				const char *str, unsigned int len, void *buf,
2773 				unsigned int size);
2774 static int
2775 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2776 				const char *str, unsigned int len, void *buf,
2777 				unsigned int size);
2778 static int
2779 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2780 				const char *str, unsigned int len, void *buf,
2781 				unsigned int size);
2782 static int
2783 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2784 			 const char *str, unsigned int len, void *buf,
2785 			 unsigned int size);
2786 static int parse_destroy(struct context *, const struct token *,
2787 			 const char *, unsigned int,
2788 			 void *, unsigned int);
2789 static int parse_flush(struct context *, const struct token *,
2790 		       const char *, unsigned int,
2791 		       void *, unsigned int);
2792 static int parse_dump(struct context *, const struct token *,
2793 		      const char *, unsigned int,
2794 		      void *, unsigned int);
2795 static int parse_query(struct context *, const struct token *,
2796 		       const char *, unsigned int,
2797 		       void *, unsigned int);
2798 static int parse_action(struct context *, const struct token *,
2799 			const char *, unsigned int,
2800 			void *, unsigned int);
2801 static int parse_list(struct context *, const struct token *,
2802 		      const char *, unsigned int,
2803 		      void *, unsigned int);
2804 static int parse_aged(struct context *, const struct token *,
2805 		      const char *, unsigned int,
2806 		      void *, unsigned int);
2807 static int parse_isolate(struct context *, const struct token *,
2808 			 const char *, unsigned int,
2809 			 void *, unsigned int);
2810 static int parse_configure(struct context *, const struct token *,
2811 			   const char *, unsigned int,
2812 			   void *, unsigned int);
2813 static int parse_template(struct context *, const struct token *,
2814 			  const char *, unsigned int,
2815 			  void *, unsigned int);
2816 static int parse_template_destroy(struct context *, const struct token *,
2817 				  const char *, unsigned int,
2818 				  void *, unsigned int);
2819 static int parse_table(struct context *, const struct token *,
2820 		       const char *, unsigned int, void *, unsigned int);
2821 static int parse_table_destroy(struct context *, const struct token *,
2822 			       const char *, unsigned int,
2823 			       void *, unsigned int);
2824 static int parse_qo(struct context *, const struct token *,
2825 		    const char *, unsigned int,
2826 		    void *, unsigned int);
2827 static int parse_qo_destroy(struct context *, const struct token *,
2828 			    const char *, unsigned int,
2829 			    void *, unsigned int);
2830 static int parse_qia(struct context *, const struct token *,
2831 		     const char *, unsigned int,
2832 		     void *, unsigned int);
2833 static int parse_qia_destroy(struct context *, const struct token *,
2834 			     const char *, unsigned int,
2835 			     void *, unsigned int);
2836 static int parse_push(struct context *, const struct token *,
2837 		      const char *, unsigned int,
2838 		      void *, unsigned int);
2839 static int parse_pull(struct context *, const struct token *,
2840 		      const char *, unsigned int,
2841 		      void *, unsigned int);
2842 static int parse_group(struct context *, const struct token *,
2843 		       const char *, unsigned int,
2844 		       void *, unsigned int);
2845 static int parse_hash(struct context *, const struct token *,
2846 		      const char *, unsigned int,
2847 		      void *, unsigned int);
2848 static int parse_tunnel(struct context *, const struct token *,
2849 			const char *, unsigned int,
2850 			void *, unsigned int);
2851 static int parse_flex(struct context *, const struct token *,
2852 		      const char *, unsigned int, void *, unsigned int);
2853 static int parse_int(struct context *, const struct token *,
2854 		     const char *, unsigned int,
2855 		     void *, unsigned int);
2856 static int parse_prefix(struct context *, const struct token *,
2857 			const char *, unsigned int,
2858 			void *, unsigned int);
2859 static int parse_boolean(struct context *, const struct token *,
2860 			 const char *, unsigned int,
2861 			 void *, unsigned int);
2862 static int parse_string(struct context *, const struct token *,
2863 			const char *, unsigned int,
2864 			void *, unsigned int);
2865 static int parse_hex(struct context *ctx, const struct token *token,
2866 			const char *str, unsigned int len,
2867 			void *buf, unsigned int size);
2868 static int parse_string0(struct context *, const struct token *,
2869 			const char *, unsigned int,
2870 			void *, unsigned int);
2871 static int parse_mac_addr(struct context *, const struct token *,
2872 			  const char *, unsigned int,
2873 			  void *, unsigned int);
2874 static int parse_ipv4_addr(struct context *, const struct token *,
2875 			   const char *, unsigned int,
2876 			   void *, unsigned int);
2877 static int parse_ipv6_addr(struct context *, const struct token *,
2878 			   const char *, unsigned int,
2879 			   void *, unsigned int);
2880 static int parse_port(struct context *, const struct token *,
2881 		      const char *, unsigned int,
2882 		      void *, unsigned int);
2883 static int parse_ia(struct context *, const struct token *,
2884 		    const char *, unsigned int,
2885 		    void *, unsigned int);
2886 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2887 			    const char *str, unsigned int len,
2888 			    void *buf, unsigned int size);
2889 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2890 			   const char *str, unsigned int len, void *buf,
2891 			   unsigned int size);
2892 
2893 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2894 			       const char *str, unsigned int len, void *buf,
2895 			       unsigned int size);
2896 static int parse_ia_port(struct context *ctx, const struct token *token,
2897 			 const char *str, unsigned int len, void *buf,
2898 			 unsigned int size);
2899 static int parse_mp(struct context *, const struct token *,
2900 		    const char *, unsigned int,
2901 		    void *, unsigned int);
2902 static int parse_meter_profile_id2ptr(struct context *ctx,
2903 				      const struct token *token,
2904 				      const char *str, unsigned int len,
2905 				      void *buf, unsigned int size);
2906 static int parse_meter_policy_id2ptr(struct context *ctx,
2907 				     const struct token *token,
2908 				     const char *str, unsigned int len,
2909 				     void *buf, unsigned int size);
2910 static int parse_meter_color(struct context *ctx, const struct token *token,
2911 			     const char *str, unsigned int len, void *buf,
2912 			     unsigned int size);
2913 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2914 				      const char *str, unsigned int len, void *buf,
2915 				      unsigned int size);
2916 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2917 				 const char *str, unsigned int len, void *buf,
2918 				 unsigned int size);
2919 static int
2920 parse_quota_state_name(struct context *ctx, const struct token *token,
2921 		       const char *str, unsigned int len, void *buf,
2922 		       unsigned int size);
2923 static int
2924 parse_quota_mode_name(struct context *ctx, const struct token *token,
2925 		      const char *str, unsigned int len, void *buf,
2926 		      unsigned int size);
2927 static int
2928 parse_quota_update_name(struct context *ctx, const struct token *token,
2929 			const char *str, unsigned int len, void *buf,
2930 			unsigned int size);
2931 static int
2932 parse_qu_mode_name(struct context *ctx, const struct token *token,
2933 		   const char *str, unsigned int len, void *buf,
2934 		   unsigned int size);
2935 static int comp_none(struct context *, const struct token *,
2936 		     unsigned int, char *, unsigned int);
2937 static int comp_boolean(struct context *, const struct token *,
2938 			unsigned int, char *, unsigned int);
2939 static int comp_action(struct context *, const struct token *,
2940 		       unsigned int, char *, unsigned int);
2941 static int comp_port(struct context *, const struct token *,
2942 		     unsigned int, char *, unsigned int);
2943 static int comp_rule_id(struct context *, const struct token *,
2944 			unsigned int, char *, unsigned int);
2945 static int comp_vc_action_rss_type(struct context *, const struct token *,
2946 				   unsigned int, char *, unsigned int);
2947 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2948 				    unsigned int, char *, unsigned int);
2949 static int comp_set_raw_index(struct context *, const struct token *,
2950 			      unsigned int, char *, unsigned int);
2951 static int comp_set_sample_index(struct context *, const struct token *,
2952 			      unsigned int, char *, unsigned int);
2953 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2954 				   unsigned int ent, char *buf, unsigned int size);
2955 static int comp_set_modify_field_op(struct context *, const struct token *,
2956 			      unsigned int, char *, unsigned int);
2957 static int comp_set_modify_field_id(struct context *, const struct token *,
2958 			      unsigned int, char *, unsigned int);
2959 static int comp_pattern_template_id(struct context *, const struct token *,
2960 				    unsigned int, char *, unsigned int);
2961 static int comp_actions_template_id(struct context *, const struct token *,
2962 				    unsigned int, char *, unsigned int);
2963 static int comp_table_id(struct context *, const struct token *,
2964 			 unsigned int, char *, unsigned int);
2965 static int comp_queue_id(struct context *, const struct token *,
2966 			 unsigned int, char *, unsigned int);
2967 static int comp_meter_color(struct context *, const struct token *,
2968 			    unsigned int, char *, unsigned int);
2969 static int comp_insertion_table_type(struct context *, const struct token *,
2970 				     unsigned int, char *, unsigned int);
2971 static int comp_hash_table_type(struct context *, const struct token *,
2972 				unsigned int, char *, unsigned int);
2973 static int
2974 comp_quota_state_name(struct context *ctx, const struct token *token,
2975 		      unsigned int ent, char *buf, unsigned int size);
2976 static int
2977 comp_quota_mode_name(struct context *ctx, const struct token *token,
2978 		     unsigned int ent, char *buf, unsigned int size);
2979 static int
2980 comp_quota_update_name(struct context *ctx, const struct token *token,
2981 		       unsigned int ent, char *buf, unsigned int size);
2982 static int
2983 comp_qu_mode_name(struct context *ctx, const struct token *token,
2984 		  unsigned int ent, char *buf, unsigned int size);
2985 static int
2986 comp_set_compare_field_id(struct context *ctx, const struct token *token,
2987 			  unsigned int ent, char *buf, unsigned int size);
2988 static int
2989 comp_set_compare_op(struct context *ctx, const struct token *token,
2990 		    unsigned int ent, char *buf, unsigned int size);
2991 static int
2992 parse_vc_compare_op(struct context *ctx, const struct token *token,
2993 			 const char *str, unsigned int len, void *buf,
2994 			 unsigned int size);
2995 static int
2996 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
2997 			  const char *str, unsigned int len, void *buf,
2998 			  unsigned int size);
2999 static int
3000 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
3001 			     const char *str, unsigned int len, void *buf,
3002 			     unsigned int size);
3003 
3004 struct indlst_conf {
3005 	uint32_t id;
3006 	uint32_t conf_num;
3007 	struct rte_flow_action *actions;
3008 	const void **conf;
3009 	SLIST_ENTRY(indlst_conf) next;
3010 };
3011 
3012 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3013 
3014 /** Token definitions. */
3015 static const struct token token_list[] = {
3016 	/* Special tokens. */
3017 	[ZERO] = {
3018 		.name = "ZERO",
3019 		.help = "null entry, abused as the entry point",
3020 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3021 	},
3022 	[END] = {
3023 		.name = "",
3024 		.type = "RETURN",
3025 		.help = "command may end here",
3026 	},
3027 	[START_SET] = {
3028 		.name = "START_SET",
3029 		.help = "null entry, abused as the entry point for set",
3030 		.next = NEXT(NEXT_ENTRY(SET)),
3031 	},
3032 	[END_SET] = {
3033 		.name = "end_set",
3034 		.type = "RETURN",
3035 		.help = "set command may end here",
3036 	},
3037 	/* Common tokens. */
3038 	[COMMON_INTEGER] = {
3039 		.name = "{int}",
3040 		.type = "INTEGER",
3041 		.help = "integer value",
3042 		.call = parse_int,
3043 		.comp = comp_none,
3044 	},
3045 	[COMMON_UNSIGNED] = {
3046 		.name = "{unsigned}",
3047 		.type = "UNSIGNED",
3048 		.help = "unsigned integer value",
3049 		.call = parse_int,
3050 		.comp = comp_none,
3051 	},
3052 	[COMMON_PREFIX] = {
3053 		.name = "{prefix}",
3054 		.type = "PREFIX",
3055 		.help = "prefix length for bit-mask",
3056 		.call = parse_prefix,
3057 		.comp = comp_none,
3058 	},
3059 	[COMMON_BOOLEAN] = {
3060 		.name = "{boolean}",
3061 		.type = "BOOLEAN",
3062 		.help = "any boolean value",
3063 		.call = parse_boolean,
3064 		.comp = comp_boolean,
3065 	},
3066 	[COMMON_STRING] = {
3067 		.name = "{string}",
3068 		.type = "STRING",
3069 		.help = "fixed string",
3070 		.call = parse_string,
3071 		.comp = comp_none,
3072 	},
3073 	[COMMON_HEX] = {
3074 		.name = "{hex}",
3075 		.type = "HEX",
3076 		.help = "fixed string",
3077 		.call = parse_hex,
3078 	},
3079 	[COMMON_FILE_PATH] = {
3080 		.name = "{file path}",
3081 		.type = "STRING",
3082 		.help = "file path",
3083 		.call = parse_string0,
3084 		.comp = comp_none,
3085 	},
3086 	[COMMON_MAC_ADDR] = {
3087 		.name = "{MAC address}",
3088 		.type = "MAC-48",
3089 		.help = "standard MAC address notation",
3090 		.call = parse_mac_addr,
3091 		.comp = comp_none,
3092 	},
3093 	[COMMON_IPV4_ADDR] = {
3094 		.name = "{IPv4 address}",
3095 		.type = "IPV4 ADDRESS",
3096 		.help = "standard IPv4 address notation",
3097 		.call = parse_ipv4_addr,
3098 		.comp = comp_none,
3099 	},
3100 	[COMMON_IPV6_ADDR] = {
3101 		.name = "{IPv6 address}",
3102 		.type = "IPV6 ADDRESS",
3103 		.help = "standard IPv6 address notation",
3104 		.call = parse_ipv6_addr,
3105 		.comp = comp_none,
3106 	},
3107 	[COMMON_RULE_ID] = {
3108 		.name = "{rule id}",
3109 		.type = "RULE ID",
3110 		.help = "rule identifier",
3111 		.call = parse_int,
3112 		.comp = comp_rule_id,
3113 	},
3114 	[COMMON_PORT_ID] = {
3115 		.name = "{port_id}",
3116 		.type = "PORT ID",
3117 		.help = "port identifier",
3118 		.call = parse_port,
3119 		.comp = comp_port,
3120 	},
3121 	[COMMON_GROUP_ID] = {
3122 		.name = "{group_id}",
3123 		.type = "GROUP ID",
3124 		.help = "group identifier",
3125 		.call = parse_int,
3126 		.comp = comp_none,
3127 	},
3128 	[COMMON_PRIORITY_LEVEL] = {
3129 		.name = "{level}",
3130 		.type = "PRIORITY",
3131 		.help = "priority level",
3132 		.call = parse_int,
3133 		.comp = comp_none,
3134 	},
3135 	[COMMON_INDIRECT_ACTION_ID] = {
3136 		.name = "{indirect_action_id}",
3137 		.type = "INDIRECT_ACTION_ID",
3138 		.help = "indirect action id",
3139 		.call = parse_int,
3140 		.comp = comp_none,
3141 	},
3142 	[COMMON_PROFILE_ID] = {
3143 		.name = "{profile_id}",
3144 		.type = "PROFILE_ID",
3145 		.help = "profile id",
3146 		.call = parse_int,
3147 		.comp = comp_none,
3148 	},
3149 	[COMMON_POLICY_ID] = {
3150 		.name = "{policy_id}",
3151 		.type = "POLICY_ID",
3152 		.help = "policy id",
3153 		.call = parse_int,
3154 		.comp = comp_none,
3155 	},
3156 	[COMMON_FLEX_TOKEN] = {
3157 		.name = "{flex token}",
3158 		.type = "flex token",
3159 		.help = "flex token",
3160 		.call = parse_int,
3161 		.comp = comp_none,
3162 	},
3163 	[COMMON_FLEX_HANDLE] = {
3164 		.name = "{flex handle}",
3165 		.type = "FLEX HANDLE",
3166 		.help = "fill flex item data",
3167 		.call = parse_flex_handle,
3168 		.comp = comp_none,
3169 	},
3170 	[COMMON_PATTERN_TEMPLATE_ID] = {
3171 		.name = "{pattern_template_id}",
3172 		.type = "PATTERN_TEMPLATE_ID",
3173 		.help = "pattern template id",
3174 		.call = parse_int,
3175 		.comp = comp_pattern_template_id,
3176 	},
3177 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3178 		.name = "{actions_template_id}",
3179 		.type = "ACTIONS_TEMPLATE_ID",
3180 		.help = "actions template id",
3181 		.call = parse_int,
3182 		.comp = comp_actions_template_id,
3183 	},
3184 	[COMMON_TABLE_ID] = {
3185 		.name = "{table_id}",
3186 		.type = "TABLE_ID",
3187 		.help = "table id",
3188 		.call = parse_int,
3189 		.comp = comp_table_id,
3190 	},
3191 	[COMMON_QUEUE_ID] = {
3192 		.name = "{queue_id}",
3193 		.type = "QUEUE_ID",
3194 		.help = "queue id",
3195 		.call = parse_int,
3196 		.comp = comp_queue_id,
3197 	},
3198 	/* Top-level command. */
3199 	[FLOW] = {
3200 		.name = "flow",
3201 		.type = "{command} {port_id} [{arg} [...]]",
3202 		.help = "manage ingress/egress flow rules",
3203 		.next = NEXT(NEXT_ENTRY
3204 			     (INFO,
3205 			      CONFIGURE,
3206 			      PATTERN_TEMPLATE,
3207 			      ACTIONS_TEMPLATE,
3208 			      TABLE,
3209 			      FLOW_GROUP,
3210 			      INDIRECT_ACTION,
3211 			      VALIDATE,
3212 			      CREATE,
3213 			      DESTROY,
3214 			      UPDATE,
3215 			      FLUSH,
3216 			      DUMP,
3217 			      LIST,
3218 			      AGED,
3219 			      QUERY,
3220 			      ISOLATE,
3221 			      TUNNEL,
3222 			      FLEX,
3223 			      QUEUE,
3224 			      PUSH,
3225 			      PULL,
3226 			      HASH)),
3227 		.call = parse_init,
3228 	},
3229 	/* Top-level command. */
3230 	[INFO] = {
3231 		.name = "info",
3232 		.help = "get information about flow engine",
3233 		.next = NEXT(NEXT_ENTRY(END),
3234 			     NEXT_ENTRY(COMMON_PORT_ID)),
3235 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3236 		.call = parse_configure,
3237 	},
3238 	/* Top-level command. */
3239 	[CONFIGURE] = {
3240 		.name = "configure",
3241 		.help = "configure flow engine",
3242 		.next = NEXT(next_config_attr,
3243 			     NEXT_ENTRY(COMMON_PORT_ID)),
3244 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3245 		.call = parse_configure,
3246 	},
3247 	/* Configure arguments. */
3248 	[CONFIG_QUEUES_NUMBER] = {
3249 		.name = "queues_number",
3250 		.help = "number of queues",
3251 		.next = NEXT(next_config_attr,
3252 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3253 		.args = ARGS(ARGS_ENTRY(struct buffer,
3254 					args.configure.nb_queue)),
3255 	},
3256 	[CONFIG_QUEUES_SIZE] = {
3257 		.name = "queues_size",
3258 		.help = "number of elements in queues",
3259 		.next = NEXT(next_config_attr,
3260 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3261 		.args = ARGS(ARGS_ENTRY(struct buffer,
3262 					args.configure.queue_attr.size)),
3263 	},
3264 	[CONFIG_COUNTERS_NUMBER] = {
3265 		.name = "counters_number",
3266 		.help = "number of counters",
3267 		.next = NEXT(next_config_attr,
3268 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3269 		.args = ARGS(ARGS_ENTRY(struct buffer,
3270 					args.configure.port_attr.nb_counters)),
3271 	},
3272 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3273 		.name = "aging_counters_number",
3274 		.help = "number of aging objects",
3275 		.next = NEXT(next_config_attr,
3276 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3277 		.args = ARGS(ARGS_ENTRY(struct buffer,
3278 					args.configure.port_attr.nb_aging_objects)),
3279 	},
3280 	[CONFIG_QUOTAS_NUMBER] = {
3281 		.name = "quotas_number",
3282 		.help = "number of quotas",
3283 		.next = NEXT(next_config_attr,
3284 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3285 		.args = ARGS(ARGS_ENTRY(struct buffer,
3286 				     args.configure.port_attr.nb_quotas)),
3287 	},
3288 	[CONFIG_METERS_NUMBER] = {
3289 		.name = "meters_number",
3290 		.help = "number of meters",
3291 		.next = NEXT(next_config_attr,
3292 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3293 		.args = ARGS(ARGS_ENTRY(struct buffer,
3294 					args.configure.port_attr.nb_meters)),
3295 	},
3296 	[CONFIG_CONN_TRACK_NUMBER] = {
3297 		.name = "conn_tracks_number",
3298 		.help = "number of connection trackings",
3299 		.next = NEXT(next_config_attr,
3300 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3301 		.args = ARGS(ARGS_ENTRY(struct buffer,
3302 					args.configure.port_attr.nb_conn_tracks)),
3303 	},
3304 	[CONFIG_FLAGS] = {
3305 		.name = "flags",
3306 		.help = "configuration flags",
3307 		.next = NEXT(next_config_attr,
3308 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3309 		.args = ARGS(ARGS_ENTRY(struct buffer,
3310 					args.configure.port_attr.flags)),
3311 	},
3312 	[CONFIG_HOST_PORT] = {
3313 		.name = "host_port",
3314 		.help = "host port for shared objects",
3315 		.next = NEXT(next_config_attr,
3316 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3317 		.args = ARGS(ARGS_ENTRY(struct buffer,
3318 					args.configure.port_attr.host_port_id)),
3319 	},
3320 	/* Top-level command. */
3321 	[PATTERN_TEMPLATE] = {
3322 		.name = "pattern_template",
3323 		.type = "{command} {port_id} [{arg} [...]]",
3324 		.help = "manage pattern templates",
3325 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3326 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3327 		.call = parse_template,
3328 	},
3329 	/* Sub-level commands. */
3330 	[PATTERN_TEMPLATE_CREATE] = {
3331 		.name = "create",
3332 		.help = "create pattern template",
3333 		.next = NEXT(next_pt_attr),
3334 		.call = parse_template,
3335 	},
3336 	[PATTERN_TEMPLATE_DESTROY] = {
3337 		.name = "destroy",
3338 		.help = "destroy pattern template",
3339 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3340 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3341 		.call = parse_template_destroy,
3342 	},
3343 	/* Pattern template arguments. */
3344 	[PATTERN_TEMPLATE_CREATE_ID] = {
3345 		.name = "pattern_template_id",
3346 		.help = "specify a pattern template id to create",
3347 		.next = NEXT(next_pt_attr,
3348 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3349 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3350 	},
3351 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3352 		.name = "pattern_template",
3353 		.help = "specify a pattern template id to destroy",
3354 		.next = NEXT(next_pt_destroy_attr,
3355 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3356 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3357 					    args.templ_destroy.template_id)),
3358 		.call = parse_template_destroy,
3359 	},
3360 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3361 		.name = "relaxed",
3362 		.help = "is matching relaxed",
3363 		.next = NEXT(next_pt_attr,
3364 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3365 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3366 			     args.vc.attr.reserved, 1)),
3367 	},
3368 	[PATTERN_TEMPLATE_INGRESS] = {
3369 		.name = "ingress",
3370 		.help = "attribute pattern to ingress",
3371 		.next = NEXT(next_pt_attr),
3372 		.call = parse_template,
3373 	},
3374 	[PATTERN_TEMPLATE_EGRESS] = {
3375 		.name = "egress",
3376 		.help = "attribute pattern to egress",
3377 		.next = NEXT(next_pt_attr),
3378 		.call = parse_template,
3379 	},
3380 	[PATTERN_TEMPLATE_TRANSFER] = {
3381 		.name = "transfer",
3382 		.help = "attribute pattern to transfer",
3383 		.next = NEXT(next_pt_attr),
3384 		.call = parse_template,
3385 	},
3386 	[PATTERN_TEMPLATE_SPEC] = {
3387 		.name = "template",
3388 		.help = "specify item to create pattern template",
3389 		.next = NEXT(next_item),
3390 	},
3391 	/* Top-level command. */
3392 	[ACTIONS_TEMPLATE] = {
3393 		.name = "actions_template",
3394 		.type = "{command} {port_id} [{arg} [...]]",
3395 		.help = "manage actions templates",
3396 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3397 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3398 		.call = parse_template,
3399 	},
3400 	/* Sub-level commands. */
3401 	[ACTIONS_TEMPLATE_CREATE] = {
3402 		.name = "create",
3403 		.help = "create actions template",
3404 		.next = NEXT(next_at_attr),
3405 		.call = parse_template,
3406 	},
3407 	[ACTIONS_TEMPLATE_DESTROY] = {
3408 		.name = "destroy",
3409 		.help = "destroy actions template",
3410 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3411 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3412 		.call = parse_template_destroy,
3413 	},
3414 	/* Actions template arguments. */
3415 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3416 		.name = "actions_template_id",
3417 		.help = "specify an actions template id to create",
3418 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3419 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3420 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3421 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3422 	},
3423 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3424 		.name = "actions_template",
3425 		.help = "specify an actions template id to destroy",
3426 		.next = NEXT(next_at_destroy_attr,
3427 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3428 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3429 					    args.templ_destroy.template_id)),
3430 		.call = parse_template_destroy,
3431 	},
3432 	[ACTIONS_TEMPLATE_INGRESS] = {
3433 		.name = "ingress",
3434 		.help = "attribute actions to ingress",
3435 		.next = NEXT(next_at_attr),
3436 		.call = parse_template,
3437 	},
3438 	[ACTIONS_TEMPLATE_EGRESS] = {
3439 		.name = "egress",
3440 		.help = "attribute actions to egress",
3441 		.next = NEXT(next_at_attr),
3442 		.call = parse_template,
3443 	},
3444 	[ACTIONS_TEMPLATE_TRANSFER] = {
3445 		.name = "transfer",
3446 		.help = "attribute actions to transfer",
3447 		.next = NEXT(next_at_attr),
3448 		.call = parse_template,
3449 	},
3450 	[ACTIONS_TEMPLATE_SPEC] = {
3451 		.name = "template",
3452 		.help = "specify action to create actions template",
3453 		.next = NEXT(next_action),
3454 		.call = parse_template,
3455 	},
3456 	[ACTIONS_TEMPLATE_MASK] = {
3457 		.name = "mask",
3458 		.help = "specify action mask to create actions template",
3459 		.next = NEXT(next_action),
3460 		.call = parse_template,
3461 	},
3462 	/* Top-level command. */
3463 	[TABLE] = {
3464 		.name = "template_table",
3465 		.type = "{command} {port_id} [{arg} [...]]",
3466 		.help = "manage template tables",
3467 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3468 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3469 		.call = parse_table,
3470 	},
3471 	/* Sub-level commands. */
3472 	[TABLE_CREATE] = {
3473 		.name = "create",
3474 		.help = "create template table",
3475 		.next = NEXT(next_table_attr),
3476 		.call = parse_table,
3477 	},
3478 	[TABLE_DESTROY] = {
3479 		.name = "destroy",
3480 		.help = "destroy template table",
3481 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3482 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3483 		.call = parse_table_destroy,
3484 	},
3485 	[TABLE_RESIZE] = {
3486 		.name = "resize",
3487 		.help = "resize template table",
3488 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3489 		.call = parse_table
3490 	},
3491 	[TABLE_RESIZE_COMPLETE] = {
3492 		.name = "resize_complete",
3493 		.help = "complete table resize",
3494 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3495 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3496 		.call = parse_table_destroy,
3497 	},
3498 	/* Table  arguments. */
3499 	[TABLE_CREATE_ID] = {
3500 		.name = "table_id",
3501 		.help = "specify table id to create",
3502 		.next = NEXT(next_table_attr,
3503 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3504 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3505 	},
3506 	[TABLE_DESTROY_ID] = {
3507 		.name = "table",
3508 		.help = "table id",
3509 		.next = NEXT(next_table_destroy_attr,
3510 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3511 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3512 					    args.table_destroy.table_id)),
3513 		.call = parse_table_destroy,
3514 	},
3515 	[TABLE_RESIZE_ID] = {
3516 		.name = "table_resize_id",
3517 		.help = "table resize id",
3518 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3519 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3520 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3521 		.call = parse_table
3522 	},
3523 	[TABLE_RESIZE_RULES_NUMBER] = {
3524 		.name = "table_resize_rules_num",
3525 		.help = "table resize rules number",
3526 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3527 		.args = ARGS(ARGS_ENTRY(struct buffer,
3528 					args.table.attr.nb_flows)),
3529 		.call = parse_table
3530 	},
3531 	[TABLE_INSERTION_TYPE] = {
3532 		.name = "insertion_type",
3533 		.help = "specify insertion type",
3534 		.next = NEXT(next_table_attr,
3535 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3536 		.args = ARGS(ARGS_ENTRY(struct buffer,
3537 					args.table.attr.insertion_type)),
3538 	},
3539 	[TABLE_INSERTION_TYPE_NAME] = {
3540 		.name = "insertion_type_name",
3541 		.help = "insertion type name",
3542 		.call = parse_insertion_table_type,
3543 		.comp = comp_insertion_table_type,
3544 	},
3545 	[TABLE_HASH_FUNC] = {
3546 		.name = "hash_func",
3547 		.help = "specify hash calculation function",
3548 		.next = NEXT(next_table_attr,
3549 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3550 		.args = ARGS(ARGS_ENTRY(struct buffer,
3551 					args.table.attr.hash_func)),
3552 	},
3553 	[TABLE_HASH_FUNC_NAME] = {
3554 		.name = "hash_func_name",
3555 		.help = "hash calculation function name",
3556 		.call = parse_hash_table_type,
3557 		.comp = comp_hash_table_type,
3558 	},
3559 	[TABLE_GROUP] = {
3560 		.name = "group",
3561 		.help = "specify a group",
3562 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3563 		.args = ARGS(ARGS_ENTRY(struct buffer,
3564 					args.table.attr.flow_attr.group)),
3565 	},
3566 	[TABLE_PRIORITY] = {
3567 		.name = "priority",
3568 		.help = "specify a priority level",
3569 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3570 		.args = ARGS(ARGS_ENTRY(struct buffer,
3571 					args.table.attr.flow_attr.priority)),
3572 	},
3573 	[TABLE_EGRESS] = {
3574 		.name = "egress",
3575 		.help = "affect rule to egress",
3576 		.next = NEXT(next_table_attr),
3577 		.call = parse_table,
3578 	},
3579 	[TABLE_INGRESS] = {
3580 		.name = "ingress",
3581 		.help = "affect rule to ingress",
3582 		.next = NEXT(next_table_attr),
3583 		.call = parse_table,
3584 	},
3585 	[TABLE_TRANSFER] = {
3586 		.name = "transfer",
3587 		.help = "affect rule to transfer",
3588 		.next = NEXT(next_table_attr),
3589 		.call = parse_table,
3590 	},
3591 	[TABLE_TRANSFER_WIRE_ORIG] = {
3592 		.name = "wire_orig",
3593 		.help = "affect rule direction to transfer",
3594 		.next = NEXT(next_table_attr),
3595 		.call = parse_table,
3596 	},
3597 	[TABLE_TRANSFER_VPORT_ORIG] = {
3598 		.name = "vport_orig",
3599 		.help = "affect rule direction to transfer",
3600 		.next = NEXT(next_table_attr),
3601 		.call = parse_table,
3602 	},
3603 	[TABLE_RESIZABLE] = {
3604 		.name = "resizable",
3605 		.help = "set resizable attribute",
3606 		.next = NEXT(next_table_attr),
3607 		.call = parse_table,
3608 	},
3609 	[TABLE_RULES_NUMBER] = {
3610 		.name = "rules_number",
3611 		.help = "number of rules in table",
3612 		.next = NEXT(next_table_attr,
3613 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3614 		.args = ARGS(ARGS_ENTRY(struct buffer,
3615 					args.table.attr.nb_flows)),
3616 		.call = parse_table,
3617 	},
3618 	[TABLE_PATTERN_TEMPLATE] = {
3619 		.name = "pattern_template",
3620 		.help = "specify pattern template id",
3621 		.next = NEXT(next_table_attr,
3622 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3623 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3624 					    args.table.pat_templ_id)),
3625 		.call = parse_table,
3626 	},
3627 	[TABLE_ACTIONS_TEMPLATE] = {
3628 		.name = "actions_template",
3629 		.help = "specify actions template id",
3630 		.next = NEXT(next_table_attr,
3631 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3632 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3633 					    args.table.act_templ_id)),
3634 		.call = parse_table,
3635 	},
3636 	/* Top-level command. */
3637 	[FLOW_GROUP] = {
3638 		.name = "group",
3639 		.help = "manage flow groups",
3640 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3641 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3642 		.call = parse_group,
3643 	},
3644 	/* Sub-level commands. */
3645 	[GROUP_SET_MISS_ACTIONS] = {
3646 		.name = "set_miss_actions",
3647 		.help = "set group miss actions",
3648 		.next = NEXT(next_action),
3649 		.call = parse_group,
3650 	},
3651 	/* Group arguments */
3652 	[GROUP_ID]	= {
3653 		.name = "group_id",
3654 		.help = "group id",
3655 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3656 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3657 	},
3658 	[GROUP_INGRESS] = {
3659 		.name = "ingress",
3660 		.help = "group ingress attr",
3661 		.next = NEXT(next_group_attr),
3662 		.call = parse_group,
3663 	},
3664 	[GROUP_EGRESS] = {
3665 		.name = "egress",
3666 		.help = "group egress attr",
3667 		.next = NEXT(next_group_attr),
3668 		.call = parse_group,
3669 	},
3670 	[GROUP_TRANSFER] = {
3671 		.name = "transfer",
3672 		.help = "group transfer attr",
3673 		.next = NEXT(next_group_attr),
3674 		.call = parse_group,
3675 	},
3676 	/* Top-level command. */
3677 	[QUEUE] = {
3678 		.name = "queue",
3679 		.help = "queue a flow rule operation",
3680 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3681 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3682 		.call = parse_qo,
3683 	},
3684 	/* Sub-level commands. */
3685 	[QUEUE_CREATE] = {
3686 		.name = "create",
3687 		.help = "create a flow rule",
3688 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3689 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3690 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3691 		.call = parse_qo,
3692 	},
3693 	[QUEUE_DESTROY] = {
3694 		.name = "destroy",
3695 		.help = "destroy a flow rule",
3696 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3697 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3698 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3699 		.call = parse_qo_destroy,
3700 	},
3701 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3702 		.name = "update_resized",
3703 		.help = "update a flow after table resize",
3704 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3705 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3706 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3707 		.call = parse_qo_destroy,
3708 	},
3709 	[QUEUE_UPDATE] = {
3710 		.name = "update",
3711 		.help = "update a flow rule",
3712 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3713 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3714 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3715 		.call = parse_qo,
3716 	},
3717 	[QUEUE_AGED] = {
3718 		.name = "aged",
3719 		.help = "list and destroy aged flows",
3720 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3721 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3722 		.call = parse_aged,
3723 	},
3724 	[QUEUE_INDIRECT_ACTION] = {
3725 		.name = "indirect_action",
3726 		.help = "queue indirect actions",
3727 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3728 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3729 		.call = parse_qia,
3730 	},
3731 	/* Queue  arguments. */
3732 	[QUEUE_TEMPLATE_TABLE] = {
3733 		.name = "template_table",
3734 		.help = "specify table id",
3735 		.next = NEXT(next_async_insert_subcmd,
3736 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3737 		.args = ARGS(ARGS_ENTRY(struct buffer,
3738 					args.vc.table_id)),
3739 		.call = parse_qo,
3740 	},
3741 	[QUEUE_PATTERN_TEMPLATE] = {
3742 		.name = "pattern_template",
3743 		.help = "specify pattern template index",
3744 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3745 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3746 		.args = ARGS(ARGS_ENTRY(struct buffer,
3747 					args.vc.pat_templ_id)),
3748 		.call = parse_qo,
3749 	},
3750 	[QUEUE_ACTIONS_TEMPLATE] = {
3751 		.name = "actions_template",
3752 		.help = "specify actions template index",
3753 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3754 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3755 		.args = ARGS(ARGS_ENTRY(struct buffer,
3756 					args.vc.act_templ_id)),
3757 		.call = parse_qo,
3758 	},
3759 	[QUEUE_RULE_ID] = {
3760 		.name = "rule_index",
3761 		.help = "specify flow rule index",
3762 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3763 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3764 		.args = ARGS(ARGS_ENTRY(struct buffer,
3765 					args.vc.rule_id)),
3766 		.call = parse_qo,
3767 	},
3768 	[QUEUE_CREATE_POSTPONE] = {
3769 		.name = "postpone",
3770 		.help = "postpone create operation",
3771 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3772 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3773 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3774 		.call = parse_qo,
3775 	},
3776 	[QUEUE_DESTROY_POSTPONE] = {
3777 		.name = "postpone",
3778 		.help = "postpone destroy operation",
3779 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3780 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3781 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3782 		.call = parse_qo_destroy,
3783 	},
3784 	[QUEUE_DESTROY_ID] = {
3785 		.name = "rule",
3786 		.help = "specify rule id to destroy",
3787 		.next = NEXT(next_queue_destroy_attr,
3788 			NEXT_ENTRY(COMMON_UNSIGNED)),
3789 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3790 					    args.destroy.rule)),
3791 		.call = parse_qo_destroy,
3792 	},
3793 	[QUEUE_UPDATE_ID] = {
3794 		.name = "rule",
3795 		.help = "specify rule id to update",
3796 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3797 			NEXT_ENTRY(COMMON_UNSIGNED)),
3798 		.args = ARGS(ARGS_ENTRY(struct buffer,
3799 				     args.vc.rule_id)),
3800 		.call = parse_qo,
3801 	},
3802 	/* Queue indirect action arguments */
3803 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3804 		.name = "create",
3805 		.help = "create indirect action",
3806 		.next = NEXT(next_qia_create_attr),
3807 		.call = parse_qia,
3808 	},
3809 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3810 		.name = "update",
3811 		.help = "update indirect action",
3812 		.next = NEXT(next_qia_update_attr,
3813 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3814 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3815 		.call = parse_qia,
3816 	},
3817 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3818 		.name = "destroy",
3819 		.help = "destroy indirect action",
3820 		.next = NEXT(next_qia_destroy_attr),
3821 		.call = parse_qia_destroy,
3822 	},
3823 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3824 		.name = "query",
3825 		.help = "query indirect action",
3826 		.next = NEXT(next_qia_query_attr,
3827 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3828 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3829 		.call = parse_qia,
3830 	},
3831 	/* Indirect action destroy arguments. */
3832 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3833 		.name = "postpone",
3834 		.help = "postpone destroy operation",
3835 		.next = NEXT(next_qia_destroy_attr,
3836 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3837 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3838 	},
3839 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3840 		.name = "action_id",
3841 		.help = "specify a indirect action id to destroy",
3842 		.next = NEXT(next_qia_destroy_attr,
3843 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3844 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3845 					    args.ia_destroy.action_id)),
3846 		.call = parse_qia_destroy,
3847 	},
3848 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3849 		.name = "query_update",
3850 		.help = "indirect query [and|or] update action",
3851 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3852 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3853 		.call = parse_qia
3854 	},
3855 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3856 		.name = "mode",
3857 		.help = "indirect query [and|or] update action",
3858 		.next = NEXT(next_qia_qu_attr,
3859 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3860 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3861 		.call = parse_qia
3862 	},
3863 	/* Indirect action update arguments. */
3864 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3865 		.name = "postpone",
3866 		.help = "postpone update operation",
3867 		.next = NEXT(next_qia_update_attr,
3868 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3869 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3870 	},
3871 	/* Indirect action update arguments. */
3872 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3873 		.name = "postpone",
3874 		.help = "postpone query operation",
3875 		.next = NEXT(next_qia_query_attr,
3876 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3877 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3878 	},
3879 	/* Indirect action create arguments. */
3880 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3881 		.name = "action_id",
3882 		.help = "specify a indirect action id to create",
3883 		.next = NEXT(next_qia_create_attr,
3884 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3885 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3886 	},
3887 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3888 		.name = "ingress",
3889 		.help = "affect rule to ingress",
3890 		.next = NEXT(next_qia_create_attr),
3891 		.call = parse_qia,
3892 	},
3893 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3894 		.name = "egress",
3895 		.help = "affect rule to egress",
3896 		.next = NEXT(next_qia_create_attr),
3897 		.call = parse_qia,
3898 	},
3899 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3900 		.name = "transfer",
3901 		.help = "affect rule to transfer",
3902 		.next = NEXT(next_qia_create_attr),
3903 		.call = parse_qia,
3904 	},
3905 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3906 		.name = "postpone",
3907 		.help = "postpone create operation",
3908 		.next = NEXT(next_qia_create_attr,
3909 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3910 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3911 	},
3912 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3913 		.name = "action",
3914 		.help = "specify action to create indirect handle",
3915 		.next = NEXT(next_action),
3916 	},
3917 	[QUEUE_INDIRECT_ACTION_LIST] = {
3918 		.name = "list",
3919 		.help = "specify actions for indirect handle list",
3920 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3921 		.call = parse_qia,
3922 	},
3923 	/* Top-level command. */
3924 	[PUSH] = {
3925 		.name = "push",
3926 		.help = "push enqueued operations",
3927 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3928 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3929 		.call = parse_push,
3930 	},
3931 	/* Sub-level commands. */
3932 	[PUSH_QUEUE] = {
3933 		.name = "queue",
3934 		.help = "specify queue id",
3935 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3936 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3937 	},
3938 	/* Top-level command. */
3939 	[PULL] = {
3940 		.name = "pull",
3941 		.help = "pull flow operations results",
3942 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3943 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3944 		.call = parse_pull,
3945 	},
3946 	/* Sub-level commands. */
3947 	[PULL_QUEUE] = {
3948 		.name = "queue",
3949 		.help = "specify queue id",
3950 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3951 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3952 	},
3953 	/* Top-level command. */
3954 	[HASH] = {
3955 		.name = "hash",
3956 		.help = "calculate hash for a given pattern in a given template table",
3957 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3958 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3959 		.call = parse_hash,
3960 	},
3961 	/* Sub-level commands. */
3962 	[HASH_CALC_TABLE] = {
3963 		.name = "template_table",
3964 		.help = "specify table id",
3965 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
3966 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3967 		.args = ARGS(ARGS_ENTRY(struct buffer,
3968 					args.vc.table_id)),
3969 		.call = parse_hash,
3970 	},
3971 	[HASH_CALC_ENCAP] = {
3972 		.name = "encap",
3973 		.help = "calculates encap hash",
3974 		.next = NEXT(next_hash_encap_dest_subcmd),
3975 		.call = parse_hash,
3976 	},
3977 	[HASH_CALC_PATTERN_INDEX] = {
3978 		.name = "pattern_template",
3979 		.help = "specify pattern template id",
3980 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3981 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3982 		.args = ARGS(ARGS_ENTRY(struct buffer,
3983 					args.vc.pat_templ_id)),
3984 		.call = parse_hash,
3985 	},
3986 	[ENCAP_HASH_FIELD_SRC_PORT] = {
3987 		.name = "hash_field_sport",
3988 		.help = "the encap hash field is src port",
3989 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3990 		.call = parse_hash,
3991 	},
3992 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
3993 		.name = "hash_field_flow_id",
3994 		.help = "the encap hash field is NVGRE flow id",
3995 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
3996 		.call = parse_hash,
3997 	},
3998 	/* Top-level command. */
3999 	[INDIRECT_ACTION] = {
4000 		.name = "indirect_action",
4001 		.type = "{command} {port_id} [{arg} [...]]",
4002 		.help = "manage indirect actions",
4003 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4004 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4005 		.call = parse_ia,
4006 	},
4007 	/* Sub-level commands. */
4008 	[INDIRECT_ACTION_CREATE] = {
4009 		.name = "create",
4010 		.help = "create indirect action",
4011 		.next = NEXT(next_ia_create_attr),
4012 		.call = parse_ia,
4013 	},
4014 	[INDIRECT_ACTION_UPDATE] = {
4015 		.name = "update",
4016 		.help = "update indirect action",
4017 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4018 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4019 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4020 		.call = parse_ia,
4021 	},
4022 	[INDIRECT_ACTION_DESTROY] = {
4023 		.name = "destroy",
4024 		.help = "destroy indirect action",
4025 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4026 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4027 		.call = parse_ia_destroy,
4028 	},
4029 	[INDIRECT_ACTION_QUERY] = {
4030 		.name = "query",
4031 		.help = "query indirect action",
4032 		.next = NEXT(NEXT_ENTRY(END),
4033 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4034 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4035 		.call = parse_ia,
4036 	},
4037 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4038 		.name = "query_update",
4039 		.help = "query [and|or] update",
4040 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4041 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4042 		.call = parse_ia
4043 	},
4044 	[INDIRECT_ACTION_QU_MODE] = {
4045 		.name = "mode",
4046 		.help = "query_update mode",
4047 		.next = NEXT(next_ia_qu_attr,
4048 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4049 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4050 		.call = parse_ia,
4051 	},
4052 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4053 		.name = "mode_name",
4054 		.help = "query-update mode name",
4055 		.call = parse_qu_mode_name,
4056 		.comp = comp_qu_mode_name,
4057 	},
4058 	[VALIDATE] = {
4059 		.name = "validate",
4060 		.help = "check whether a flow rule can be created",
4061 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4062 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4063 		.call = parse_vc,
4064 	},
4065 	[CREATE] = {
4066 		.name = "create",
4067 		.help = "create a flow rule",
4068 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4069 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4070 		.call = parse_vc,
4071 	},
4072 	[DESTROY] = {
4073 		.name = "destroy",
4074 		.help = "destroy specific flow rules",
4075 		.next = NEXT(next_destroy_attr,
4076 			     NEXT_ENTRY(COMMON_PORT_ID)),
4077 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4078 		.call = parse_destroy,
4079 	},
4080 	[UPDATE] = {
4081 		.name = "update",
4082 		.help = "update a flow rule with new actions",
4083 		.next = NEXT(NEXT_ENTRY(VC_IS_USER_ID, END),
4084 			     NEXT_ENTRY(ACTIONS),
4085 			     NEXT_ENTRY(COMMON_RULE_ID),
4086 			     NEXT_ENTRY(COMMON_PORT_ID)),
4087 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.rule_id),
4088 			     ARGS_ENTRY(struct buffer, port)),
4089 		.call = parse_vc,
4090 	},
4091 	[FLUSH] = {
4092 		.name = "flush",
4093 		.help = "destroy all flow rules",
4094 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4095 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4096 		.call = parse_flush,
4097 	},
4098 	[DUMP] = {
4099 		.name = "dump",
4100 		.help = "dump single/all flow rules to file",
4101 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4102 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4103 		.call = parse_dump,
4104 	},
4105 	[QUERY] = {
4106 		.name = "query",
4107 		.help = "query an existing flow rule",
4108 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4109 			     NEXT_ENTRY(COMMON_RULE_ID),
4110 			     NEXT_ENTRY(COMMON_PORT_ID)),
4111 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4112 			     ARGS_ENTRY(struct buffer, args.query.rule),
4113 			     ARGS_ENTRY(struct buffer, port)),
4114 		.call = parse_query,
4115 	},
4116 	[LIST] = {
4117 		.name = "list",
4118 		.help = "list existing flow rules",
4119 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4120 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4121 		.call = parse_list,
4122 	},
4123 	[AGED] = {
4124 		.name = "aged",
4125 		.help = "list and destroy aged flows",
4126 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4127 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4128 		.call = parse_aged,
4129 	},
4130 	[ISOLATE] = {
4131 		.name = "isolate",
4132 		.help = "restrict ingress traffic to the defined flow rules",
4133 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4134 			     NEXT_ENTRY(COMMON_PORT_ID)),
4135 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4136 			     ARGS_ENTRY(struct buffer, port)),
4137 		.call = parse_isolate,
4138 	},
4139 	[FLEX] = {
4140 		.name = "flex_item",
4141 		.help = "flex item API",
4142 		.next = NEXT(next_flex_item),
4143 		.call = parse_flex,
4144 	},
4145 	[FLEX_ITEM_INIT] = {
4146 		.name = "init",
4147 		.help = "flex item init",
4148 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4149 			     ARGS_ENTRY(struct buffer, port)),
4150 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4151 			     NEXT_ENTRY(COMMON_PORT_ID)),
4152 		.call = parse_flex
4153 	},
4154 	[FLEX_ITEM_CREATE] = {
4155 		.name = "create",
4156 		.help = "flex item create",
4157 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4158 			     ARGS_ENTRY(struct buffer, args.flex.token),
4159 			     ARGS_ENTRY(struct buffer, port)),
4160 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4161 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4162 			     NEXT_ENTRY(COMMON_PORT_ID)),
4163 		.call = parse_flex
4164 	},
4165 	[FLEX_ITEM_DESTROY] = {
4166 		.name = "destroy",
4167 		.help = "flex item destroy",
4168 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4169 			     ARGS_ENTRY(struct buffer, port)),
4170 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4171 			     NEXT_ENTRY(COMMON_PORT_ID)),
4172 		.call = parse_flex
4173 	},
4174 	[TUNNEL] = {
4175 		.name = "tunnel",
4176 		.help = "new tunnel API",
4177 		.next = NEXT(NEXT_ENTRY
4178 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4179 		.call = parse_tunnel,
4180 	},
4181 	/* Tunnel arguments. */
4182 	[TUNNEL_CREATE] = {
4183 		.name = "create",
4184 		.help = "create new tunnel object",
4185 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4186 			     NEXT_ENTRY(COMMON_PORT_ID)),
4187 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4188 		.call = parse_tunnel,
4189 	},
4190 	[TUNNEL_CREATE_TYPE] = {
4191 		.name = "type",
4192 		.help = "create new tunnel",
4193 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4194 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4195 		.call = parse_tunnel,
4196 	},
4197 	[TUNNEL_DESTROY] = {
4198 		.name = "destroy",
4199 		.help = "destroy tunnel",
4200 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4201 			     NEXT_ENTRY(COMMON_PORT_ID)),
4202 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4203 		.call = parse_tunnel,
4204 	},
4205 	[TUNNEL_DESTROY_ID] = {
4206 		.name = "id",
4207 		.help = "tunnel identifier to destroy",
4208 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4209 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4210 		.call = parse_tunnel,
4211 	},
4212 	[TUNNEL_LIST] = {
4213 		.name = "list",
4214 		.help = "list existing tunnels",
4215 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4216 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4217 		.call = parse_tunnel,
4218 	},
4219 	/* Destroy arguments. */
4220 	[DESTROY_RULE] = {
4221 		.name = "rule",
4222 		.help = "specify a rule identifier",
4223 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4224 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4225 		.call = parse_destroy,
4226 	},
4227 	[DESTROY_IS_USER_ID] = {
4228 		.name = "user_id",
4229 		.help = "rule identifier is user-id",
4230 		.next = NEXT(next_destroy_attr),
4231 		.call = parse_destroy,
4232 	},
4233 	/* Dump arguments. */
4234 	[DUMP_ALL] = {
4235 		.name = "all",
4236 		.help = "dump all",
4237 		.next = NEXT(next_dump_attr),
4238 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4239 		.call = parse_dump,
4240 	},
4241 	[DUMP_ONE] = {
4242 		.name = "rule",
4243 		.help = "dump one rule",
4244 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4245 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4246 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4247 		.call = parse_dump,
4248 	},
4249 	[DUMP_IS_USER_ID] = {
4250 		.name = "user_id",
4251 		.help = "rule identifier is user-id",
4252 		.next = NEXT(next_dump_subcmd),
4253 		.call = parse_dump,
4254 	},
4255 	/* Query arguments. */
4256 	[QUERY_ACTION] = {
4257 		.name = "{action}",
4258 		.type = "ACTION",
4259 		.help = "action to query, must be part of the rule",
4260 		.call = parse_action,
4261 		.comp = comp_action,
4262 	},
4263 	[QUERY_IS_USER_ID] = {
4264 		.name = "user_id",
4265 		.help = "rule identifier is user-id",
4266 		.next = NEXT(next_query_attr),
4267 		.call = parse_query,
4268 	},
4269 	/* List arguments. */
4270 	[LIST_GROUP] = {
4271 		.name = "group",
4272 		.help = "specify a group",
4273 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4274 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4275 		.call = parse_list,
4276 	},
4277 	[AGED_DESTROY] = {
4278 		.name = "destroy",
4279 		.help = "specify aged flows need be destroyed",
4280 		.call = parse_aged,
4281 		.comp = comp_none,
4282 	},
4283 	/* Validate/create attributes. */
4284 	[VC_GROUP] = {
4285 		.name = "group",
4286 		.help = "specify a group",
4287 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4288 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4289 		.call = parse_vc,
4290 	},
4291 	[VC_PRIORITY] = {
4292 		.name = "priority",
4293 		.help = "specify a priority level",
4294 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4295 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4296 		.call = parse_vc,
4297 	},
4298 	[VC_INGRESS] = {
4299 		.name = "ingress",
4300 		.help = "affect rule to ingress",
4301 		.next = NEXT(next_vc_attr),
4302 		.call = parse_vc,
4303 	},
4304 	[VC_EGRESS] = {
4305 		.name = "egress",
4306 		.help = "affect rule to egress",
4307 		.next = NEXT(next_vc_attr),
4308 		.call = parse_vc,
4309 	},
4310 	[VC_TRANSFER] = {
4311 		.name = "transfer",
4312 		.help = "apply rule directly to endpoints found in pattern",
4313 		.next = NEXT(next_vc_attr),
4314 		.call = parse_vc,
4315 	},
4316 	[VC_TUNNEL_SET] = {
4317 		.name = "tunnel_set",
4318 		.help = "tunnel steer rule",
4319 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4320 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4321 		.call = parse_vc,
4322 	},
4323 	[VC_TUNNEL_MATCH] = {
4324 		.name = "tunnel_match",
4325 		.help = "tunnel match rule",
4326 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4327 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4328 		.call = parse_vc,
4329 	},
4330 	[VC_USER_ID] = {
4331 		.name = "user_id",
4332 		.help = "specify a user id to create",
4333 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4334 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4335 		.call = parse_vc,
4336 	},
4337 	[VC_IS_USER_ID] = {
4338 		.name = "user_id",
4339 		.help = "rule identifier is user-id",
4340 		.call = parse_vc,
4341 	},
4342 	/* Validate/create pattern. */
4343 	[ITEM_PATTERN] = {
4344 		.name = "pattern",
4345 		.help = "submit a list of pattern items",
4346 		.next = NEXT(next_item),
4347 		.call = parse_vc,
4348 	},
4349 	[ITEM_PARAM_IS] = {
4350 		.name = "is",
4351 		.help = "match value perfectly (with full bit-mask)",
4352 		.call = parse_vc_spec,
4353 	},
4354 	[ITEM_PARAM_SPEC] = {
4355 		.name = "spec",
4356 		.help = "match value according to configured bit-mask",
4357 		.call = parse_vc_spec,
4358 	},
4359 	[ITEM_PARAM_LAST] = {
4360 		.name = "last",
4361 		.help = "specify upper bound to establish a range",
4362 		.call = parse_vc_spec,
4363 	},
4364 	[ITEM_PARAM_MASK] = {
4365 		.name = "mask",
4366 		.help = "specify bit-mask with relevant bits set to one",
4367 		.call = parse_vc_spec,
4368 	},
4369 	[ITEM_PARAM_PREFIX] = {
4370 		.name = "prefix",
4371 		.help = "generate bit-mask from a prefix length",
4372 		.call = parse_vc_spec,
4373 	},
4374 	[ITEM_NEXT] = {
4375 		.name = "/",
4376 		.help = "specify next pattern item",
4377 		.next = NEXT(next_item),
4378 	},
4379 	[ITEM_END] = {
4380 		.name = "end",
4381 		.help = "end list of pattern items",
4382 		.priv = PRIV_ITEM(END, 0),
4383 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4384 		.call = parse_vc,
4385 	},
4386 	[ITEM_VOID] = {
4387 		.name = "void",
4388 		.help = "no-op pattern item",
4389 		.priv = PRIV_ITEM(VOID, 0),
4390 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4391 		.call = parse_vc,
4392 	},
4393 	[ITEM_INVERT] = {
4394 		.name = "invert",
4395 		.help = "perform actions when pattern does not match",
4396 		.priv = PRIV_ITEM(INVERT, 0),
4397 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4398 		.call = parse_vc,
4399 	},
4400 	[ITEM_ANY] = {
4401 		.name = "any",
4402 		.help = "match any protocol for the current layer",
4403 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4404 		.next = NEXT(item_any),
4405 		.call = parse_vc,
4406 	},
4407 	[ITEM_ANY_NUM] = {
4408 		.name = "num",
4409 		.help = "number of layers covered",
4410 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4411 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4412 	},
4413 	[ITEM_PORT_ID] = {
4414 		.name = "port_id",
4415 		.help = "match traffic from/to a given DPDK port ID",
4416 		.priv = PRIV_ITEM(PORT_ID,
4417 				  sizeof(struct rte_flow_item_port_id)),
4418 		.next = NEXT(item_port_id),
4419 		.call = parse_vc,
4420 	},
4421 	[ITEM_PORT_ID_ID] = {
4422 		.name = "id",
4423 		.help = "DPDK port ID",
4424 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4425 			     item_param),
4426 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4427 	},
4428 	[ITEM_MARK] = {
4429 		.name = "mark",
4430 		.help = "match traffic against value set in previously matched rule",
4431 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4432 		.next = NEXT(item_mark),
4433 		.call = parse_vc,
4434 	},
4435 	[ITEM_MARK_ID] = {
4436 		.name = "id",
4437 		.help = "Integer value to match against",
4438 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4439 			     item_param),
4440 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4441 	},
4442 	[ITEM_RAW] = {
4443 		.name = "raw",
4444 		.help = "match an arbitrary byte string",
4445 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4446 		.next = NEXT(item_raw),
4447 		.call = parse_vc,
4448 	},
4449 	[ITEM_RAW_RELATIVE] = {
4450 		.name = "relative",
4451 		.help = "look for pattern after the previous item",
4452 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4453 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4454 					   relative, 1)),
4455 	},
4456 	[ITEM_RAW_SEARCH] = {
4457 		.name = "search",
4458 		.help = "search pattern from offset (see also limit)",
4459 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4460 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4461 					   search, 1)),
4462 	},
4463 	[ITEM_RAW_OFFSET] = {
4464 		.name = "offset",
4465 		.help = "absolute or relative offset for pattern",
4466 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4467 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4468 	},
4469 	[ITEM_RAW_LIMIT] = {
4470 		.name = "limit",
4471 		.help = "search area limit for start of pattern",
4472 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4473 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4474 	},
4475 	[ITEM_RAW_PATTERN] = {
4476 		.name = "pattern",
4477 		.help = "byte string to look for",
4478 		.next = NEXT(item_raw,
4479 			     NEXT_ENTRY(COMMON_STRING),
4480 			     NEXT_ENTRY(ITEM_PARAM_IS,
4481 					ITEM_PARAM_SPEC,
4482 					ITEM_PARAM_MASK)),
4483 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4484 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4485 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4486 					    ITEM_RAW_PATTERN_SIZE)),
4487 	},
4488 	[ITEM_RAW_PATTERN_HEX] = {
4489 		.name = "pattern_hex",
4490 		.help = "hex string to look for",
4491 		.next = NEXT(item_raw,
4492 			     NEXT_ENTRY(COMMON_HEX),
4493 			     NEXT_ENTRY(ITEM_PARAM_IS,
4494 					ITEM_PARAM_SPEC,
4495 					ITEM_PARAM_MASK)),
4496 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4497 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4498 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4499 					    ITEM_RAW_PATTERN_SIZE)),
4500 	},
4501 	[ITEM_ETH] = {
4502 		.name = "eth",
4503 		.help = "match Ethernet header",
4504 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4505 		.next = NEXT(item_eth),
4506 		.call = parse_vc,
4507 	},
4508 	[ITEM_ETH_DST] = {
4509 		.name = "dst",
4510 		.help = "destination MAC",
4511 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4512 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4513 	},
4514 	[ITEM_ETH_SRC] = {
4515 		.name = "src",
4516 		.help = "source MAC",
4517 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4518 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4519 	},
4520 	[ITEM_ETH_TYPE] = {
4521 		.name = "type",
4522 		.help = "EtherType",
4523 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4524 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4525 	},
4526 	[ITEM_ETH_HAS_VLAN] = {
4527 		.name = "has_vlan",
4528 		.help = "packet header contains VLAN",
4529 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4530 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4531 					   has_vlan, 1)),
4532 	},
4533 	[ITEM_VLAN] = {
4534 		.name = "vlan",
4535 		.help = "match 802.1Q/ad VLAN tag",
4536 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4537 		.next = NEXT(item_vlan),
4538 		.call = parse_vc,
4539 	},
4540 	[ITEM_VLAN_TCI] = {
4541 		.name = "tci",
4542 		.help = "tag control information",
4543 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4544 			     item_param),
4545 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4546 	},
4547 	[ITEM_VLAN_PCP] = {
4548 		.name = "pcp",
4549 		.help = "priority code point",
4550 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4551 			     item_param),
4552 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4553 						  hdr.vlan_tci, "\xe0\x00")),
4554 	},
4555 	[ITEM_VLAN_DEI] = {
4556 		.name = "dei",
4557 		.help = "drop eligible indicator",
4558 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4559 			     item_param),
4560 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4561 						  hdr.vlan_tci, "\x10\x00")),
4562 	},
4563 	[ITEM_VLAN_VID] = {
4564 		.name = "vid",
4565 		.help = "VLAN identifier",
4566 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4567 			     item_param),
4568 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4569 						  hdr.vlan_tci, "\x0f\xff")),
4570 	},
4571 	[ITEM_VLAN_INNER_TYPE] = {
4572 		.name = "inner_type",
4573 		.help = "inner EtherType",
4574 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4575 			     item_param),
4576 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4577 					     hdr.eth_proto)),
4578 	},
4579 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4580 		.name = "has_more_vlan",
4581 		.help = "packet header contains another VLAN",
4582 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4583 			     item_param),
4584 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4585 					   has_more_vlan, 1)),
4586 	},
4587 	[ITEM_IPV4] = {
4588 		.name = "ipv4",
4589 		.help = "match IPv4 header",
4590 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4591 		.next = NEXT(item_ipv4),
4592 		.call = parse_vc,
4593 	},
4594 	[ITEM_IPV4_VER_IHL] = {
4595 		.name = "version_ihl",
4596 		.help = "match header length",
4597 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4598 			     item_param),
4599 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4600 				     hdr.version_ihl)),
4601 	},
4602 	[ITEM_IPV4_TOS] = {
4603 		.name = "tos",
4604 		.help = "type of service",
4605 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4606 			     item_param),
4607 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4608 					     hdr.type_of_service)),
4609 	},
4610 	[ITEM_IPV4_LENGTH] = {
4611 		.name = "length",
4612 		.help = "total length",
4613 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4614 			     item_param),
4615 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4616 					     hdr.total_length)),
4617 	},
4618 	[ITEM_IPV4_ID] = {
4619 		.name = "packet_id",
4620 		.help = "fragment packet id",
4621 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4622 			     item_param),
4623 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4624 					     hdr.packet_id)),
4625 	},
4626 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4627 		.name = "fragment_offset",
4628 		.help = "fragmentation flags and fragment offset",
4629 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4630 			     item_param),
4631 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4632 					     hdr.fragment_offset)),
4633 	},
4634 	[ITEM_IPV4_TTL] = {
4635 		.name = "ttl",
4636 		.help = "time to live",
4637 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4638 			     item_param),
4639 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4640 					     hdr.time_to_live)),
4641 	},
4642 	[ITEM_IPV4_PROTO] = {
4643 		.name = "proto",
4644 		.help = "next protocol ID",
4645 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4646 			     item_param),
4647 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4648 					     hdr.next_proto_id)),
4649 	},
4650 	[ITEM_IPV4_SRC] = {
4651 		.name = "src",
4652 		.help = "source address",
4653 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4654 			     item_param),
4655 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4656 					     hdr.src_addr)),
4657 	},
4658 	[ITEM_IPV4_DST] = {
4659 		.name = "dst",
4660 		.help = "destination address",
4661 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4662 			     item_param),
4663 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4664 					     hdr.dst_addr)),
4665 	},
4666 	[ITEM_IPV6] = {
4667 		.name = "ipv6",
4668 		.help = "match IPv6 header",
4669 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4670 		.next = NEXT(item_ipv6),
4671 		.call = parse_vc,
4672 	},
4673 	[ITEM_IPV6_TC] = {
4674 		.name = "tc",
4675 		.help = "traffic class",
4676 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4677 			     item_param),
4678 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4679 						  hdr.vtc_flow,
4680 						  "\x0f\xf0\x00\x00")),
4681 	},
4682 	[ITEM_IPV6_FLOW] = {
4683 		.name = "flow",
4684 		.help = "flow label",
4685 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4686 			     item_param),
4687 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4688 						  hdr.vtc_flow,
4689 						  "\x00\x0f\xff\xff")),
4690 	},
4691 	[ITEM_IPV6_LEN] = {
4692 		.name = "length",
4693 		.help = "payload length",
4694 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4695 			     item_param),
4696 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4697 					     hdr.payload_len)),
4698 	},
4699 	[ITEM_IPV6_PROTO] = {
4700 		.name = "proto",
4701 		.help = "protocol (next header)",
4702 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4703 			     item_param),
4704 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4705 					     hdr.proto)),
4706 	},
4707 	[ITEM_IPV6_HOP] = {
4708 		.name = "hop",
4709 		.help = "hop limit",
4710 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4711 			     item_param),
4712 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4713 					     hdr.hop_limits)),
4714 	},
4715 	[ITEM_IPV6_SRC] = {
4716 		.name = "src",
4717 		.help = "source address",
4718 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4719 			     item_param),
4720 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4721 					     hdr.src_addr)),
4722 	},
4723 	[ITEM_IPV6_DST] = {
4724 		.name = "dst",
4725 		.help = "destination address",
4726 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4727 			     item_param),
4728 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4729 					     hdr.dst_addr)),
4730 	},
4731 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4732 		.name = "has_frag_ext",
4733 		.help = "fragment packet attribute",
4734 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4735 			     item_param),
4736 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4737 					   has_frag_ext, 1)),
4738 	},
4739 	[ITEM_IPV6_ROUTING_EXT] = {
4740 		.name = "ipv6_routing_ext",
4741 		.help = "match IPv6 routing extension header",
4742 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4743 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4744 		.next = NEXT(item_ipv6_routing_ext),
4745 		.call = parse_vc,
4746 	},
4747 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4748 		.name = "ext_type",
4749 		.help = "match IPv6 routing extension header type",
4750 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4751 			     item_param),
4752 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4753 					     hdr.type)),
4754 	},
4755 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4756 		.name = "ext_next_hdr",
4757 		.help = "match IPv6 routing extension header next header type",
4758 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4759 			     item_param),
4760 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4761 					     hdr.next_hdr)),
4762 	},
4763 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4764 		.name = "ext_seg_left",
4765 		.help = "match IPv6 routing extension header segment left",
4766 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4767 			     item_param),
4768 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4769 					     hdr.segments_left)),
4770 	},
4771 	[ITEM_ICMP] = {
4772 		.name = "icmp",
4773 		.help = "match ICMP header",
4774 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4775 		.next = NEXT(item_icmp),
4776 		.call = parse_vc,
4777 	},
4778 	[ITEM_ICMP_TYPE] = {
4779 		.name = "type",
4780 		.help = "ICMP packet type",
4781 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4782 			     item_param),
4783 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4784 					     hdr.icmp_type)),
4785 	},
4786 	[ITEM_ICMP_CODE] = {
4787 		.name = "code",
4788 		.help = "ICMP packet code",
4789 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4790 			     item_param),
4791 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4792 					     hdr.icmp_code)),
4793 	},
4794 	[ITEM_ICMP_IDENT] = {
4795 		.name = "ident",
4796 		.help = "ICMP packet identifier",
4797 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4798 			     item_param),
4799 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4800 					     hdr.icmp_ident)),
4801 	},
4802 	[ITEM_ICMP_SEQ] = {
4803 		.name = "seq",
4804 		.help = "ICMP packet sequence number",
4805 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4806 			     item_param),
4807 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4808 					     hdr.icmp_seq_nb)),
4809 	},
4810 	[ITEM_UDP] = {
4811 		.name = "udp",
4812 		.help = "match UDP header",
4813 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4814 		.next = NEXT(item_udp),
4815 		.call = parse_vc,
4816 	},
4817 	[ITEM_UDP_SRC] = {
4818 		.name = "src",
4819 		.help = "UDP source port",
4820 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4821 			     item_param),
4822 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4823 					     hdr.src_port)),
4824 	},
4825 	[ITEM_UDP_DST] = {
4826 		.name = "dst",
4827 		.help = "UDP destination port",
4828 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4829 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4830 					     hdr.dst_port)),
4831 	},
4832 	[ITEM_TCP] = {
4833 		.name = "tcp",
4834 		.help = "match TCP header",
4835 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4836 		.next = NEXT(item_tcp),
4837 		.call = parse_vc,
4838 	},
4839 	[ITEM_TCP_SRC] = {
4840 		.name = "src",
4841 		.help = "TCP source port",
4842 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4843 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4844 					     hdr.src_port)),
4845 	},
4846 	[ITEM_TCP_DST] = {
4847 		.name = "dst",
4848 		.help = "TCP destination port",
4849 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4850 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4851 					     hdr.dst_port)),
4852 	},
4853 	[ITEM_TCP_FLAGS] = {
4854 		.name = "flags",
4855 		.help = "TCP flags",
4856 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4857 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4858 					     hdr.tcp_flags)),
4859 	},
4860 	[ITEM_SCTP] = {
4861 		.name = "sctp",
4862 		.help = "match SCTP header",
4863 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4864 		.next = NEXT(item_sctp),
4865 		.call = parse_vc,
4866 	},
4867 	[ITEM_SCTP_SRC] = {
4868 		.name = "src",
4869 		.help = "SCTP source port",
4870 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4871 			     item_param),
4872 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4873 					     hdr.src_port)),
4874 	},
4875 	[ITEM_SCTP_DST] = {
4876 		.name = "dst",
4877 		.help = "SCTP destination port",
4878 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4879 			     item_param),
4880 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4881 					     hdr.dst_port)),
4882 	},
4883 	[ITEM_SCTP_TAG] = {
4884 		.name = "tag",
4885 		.help = "validation tag",
4886 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4887 			     item_param),
4888 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4889 					     hdr.tag)),
4890 	},
4891 	[ITEM_SCTP_CKSUM] = {
4892 		.name = "cksum",
4893 		.help = "checksum",
4894 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4895 			     item_param),
4896 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4897 					     hdr.cksum)),
4898 	},
4899 	[ITEM_VXLAN] = {
4900 		.name = "vxlan",
4901 		.help = "match VXLAN header",
4902 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4903 		.next = NEXT(item_vxlan),
4904 		.call = parse_vc,
4905 	},
4906 	[ITEM_VXLAN_VNI] = {
4907 		.name = "vni",
4908 		.help = "VXLAN identifier",
4909 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4910 			     item_param),
4911 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4912 	},
4913 	[ITEM_VXLAN_LAST_RSVD] = {
4914 		.name = "last_rsvd",
4915 		.help = "VXLAN last reserved bits",
4916 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4917 			     item_param),
4918 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4919 					     hdr.rsvd1)),
4920 	},
4921 	[ITEM_E_TAG] = {
4922 		.name = "e_tag",
4923 		.help = "match E-Tag header",
4924 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4925 		.next = NEXT(item_e_tag),
4926 		.call = parse_vc,
4927 	},
4928 	[ITEM_E_TAG_GRP_ECID_B] = {
4929 		.name = "grp_ecid_b",
4930 		.help = "GRP and E-CID base",
4931 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4932 			     item_param),
4933 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4934 						  rsvd_grp_ecid_b,
4935 						  "\x3f\xff")),
4936 	},
4937 	[ITEM_NVGRE] = {
4938 		.name = "nvgre",
4939 		.help = "match NVGRE header",
4940 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4941 		.next = NEXT(item_nvgre),
4942 		.call = parse_vc,
4943 	},
4944 	[ITEM_NVGRE_TNI] = {
4945 		.name = "tni",
4946 		.help = "virtual subnet ID",
4947 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4948 			     item_param),
4949 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4950 	},
4951 	[ITEM_MPLS] = {
4952 		.name = "mpls",
4953 		.help = "match MPLS header",
4954 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4955 		.next = NEXT(item_mpls),
4956 		.call = parse_vc,
4957 	},
4958 	[ITEM_MPLS_LABEL] = {
4959 		.name = "label",
4960 		.help = "MPLS label",
4961 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4962 			     item_param),
4963 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4964 						  label_tc_s,
4965 						  "\xff\xff\xf0")),
4966 	},
4967 	[ITEM_MPLS_TC] = {
4968 		.name = "tc",
4969 		.help = "MPLS Traffic Class",
4970 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4971 			     item_param),
4972 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4973 						  label_tc_s,
4974 						  "\x00\x00\x0e")),
4975 	},
4976 	[ITEM_MPLS_S] = {
4977 		.name = "s",
4978 		.help = "MPLS Bottom-of-Stack",
4979 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4980 			     item_param),
4981 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4982 						  label_tc_s,
4983 						  "\x00\x00\x01")),
4984 	},
4985 	[ITEM_MPLS_TTL] = {
4986 		.name = "ttl",
4987 		.help = "MPLS Time-to-Live",
4988 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4989 			     item_param),
4990 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
4991 	},
4992 	[ITEM_GRE] = {
4993 		.name = "gre",
4994 		.help = "match GRE header",
4995 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4996 		.next = NEXT(item_gre),
4997 		.call = parse_vc,
4998 	},
4999 	[ITEM_GRE_PROTO] = {
5000 		.name = "protocol",
5001 		.help = "GRE protocol type",
5002 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5003 			     item_param),
5004 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5005 					     protocol)),
5006 	},
5007 	[ITEM_GRE_C_RSVD0_VER] = {
5008 		.name = "c_rsvd0_ver",
5009 		.help =
5010 			"checksum (1b), undefined (1b), key bit (1b),"
5011 			" sequence number (1b), reserved 0 (9b),"
5012 			" version (3b)",
5013 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5014 			     item_param),
5015 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5016 					     c_rsvd0_ver)),
5017 	},
5018 	[ITEM_GRE_C_BIT] = {
5019 		.name = "c_bit",
5020 		.help = "checksum bit (C)",
5021 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5022 			     item_param),
5023 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5024 						  c_rsvd0_ver,
5025 						  "\x80\x00\x00\x00")),
5026 	},
5027 	[ITEM_GRE_S_BIT] = {
5028 		.name = "s_bit",
5029 		.help = "sequence number bit (S)",
5030 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5031 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5032 						  c_rsvd0_ver,
5033 						  "\x10\x00\x00\x00")),
5034 	},
5035 	[ITEM_GRE_K_BIT] = {
5036 		.name = "k_bit",
5037 		.help = "key bit (K)",
5038 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5039 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5040 						  c_rsvd0_ver,
5041 						  "\x20\x00\x00\x00")),
5042 	},
5043 	[ITEM_FUZZY] = {
5044 		.name = "fuzzy",
5045 		.help = "fuzzy pattern match, expect faster than default",
5046 		.priv = PRIV_ITEM(FUZZY,
5047 				sizeof(struct rte_flow_item_fuzzy)),
5048 		.next = NEXT(item_fuzzy),
5049 		.call = parse_vc,
5050 	},
5051 	[ITEM_FUZZY_THRESH] = {
5052 		.name = "thresh",
5053 		.help = "match accuracy threshold",
5054 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5055 			     item_param),
5056 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5057 					thresh)),
5058 	},
5059 	[ITEM_GTP] = {
5060 		.name = "gtp",
5061 		.help = "match GTP header",
5062 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5063 		.next = NEXT(item_gtp),
5064 		.call = parse_vc,
5065 	},
5066 	[ITEM_GTP_FLAGS] = {
5067 		.name = "v_pt_rsv_flags",
5068 		.help = "GTP flags",
5069 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5070 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5071 					hdr.gtp_hdr_info)),
5072 	},
5073 	[ITEM_GTP_MSG_TYPE] = {
5074 		.name = "msg_type",
5075 		.help = "GTP message type",
5076 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5077 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5078 	},
5079 	[ITEM_GTP_TEID] = {
5080 		.name = "teid",
5081 		.help = "tunnel endpoint identifier",
5082 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5083 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5084 	},
5085 	[ITEM_GTPC] = {
5086 		.name = "gtpc",
5087 		.help = "match GTP header",
5088 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5089 		.next = NEXT(item_gtp),
5090 		.call = parse_vc,
5091 	},
5092 	[ITEM_GTPU] = {
5093 		.name = "gtpu",
5094 		.help = "match GTP header",
5095 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5096 		.next = NEXT(item_gtp),
5097 		.call = parse_vc,
5098 	},
5099 	[ITEM_GENEVE] = {
5100 		.name = "geneve",
5101 		.help = "match GENEVE header",
5102 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5103 		.next = NEXT(item_geneve),
5104 		.call = parse_vc,
5105 	},
5106 	[ITEM_GENEVE_VNI] = {
5107 		.name = "vni",
5108 		.help = "virtual network identifier",
5109 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5110 			     item_param),
5111 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5112 	},
5113 	[ITEM_GENEVE_PROTO] = {
5114 		.name = "protocol",
5115 		.help = "GENEVE protocol type",
5116 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5117 			     item_param),
5118 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5119 					     protocol)),
5120 	},
5121 	[ITEM_GENEVE_OPTLEN] = {
5122 		.name = "optlen",
5123 		.help = "GENEVE options length in dwords",
5124 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5125 			     item_param),
5126 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5127 						  ver_opt_len_o_c_rsvd0,
5128 						  "\x3f\x00")),
5129 	},
5130 	[ITEM_VXLAN_GPE] = {
5131 		.name = "vxlan-gpe",
5132 		.help = "match VXLAN-GPE header",
5133 		.priv = PRIV_ITEM(VXLAN_GPE,
5134 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5135 		.next = NEXT(item_vxlan_gpe),
5136 		.call = parse_vc,
5137 	},
5138 	[ITEM_VXLAN_GPE_VNI] = {
5139 		.name = "vni",
5140 		.help = "VXLAN-GPE identifier",
5141 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5142 			     item_param),
5143 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5144 					     hdr.vni)),
5145 	},
5146 	[ITEM_VXLAN_GPE_PROTO] = {
5147 		.name = "protocol",
5148 		.help = "VXLAN-GPE next protocol",
5149 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5150 			     item_param),
5151 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5152 					     protocol)),
5153 	},
5154 	[ITEM_VXLAN_GPE_FLAGS] = {
5155 		.name = "flags",
5156 		.help = "VXLAN-GPE flags",
5157 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5158 			     item_param),
5159 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5160 					     flags)),
5161 	},
5162 	[ITEM_VXLAN_GPE_RSVD0] = {
5163 		.name = "rsvd0",
5164 		.help = "VXLAN-GPE rsvd0",
5165 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5166 			     item_param),
5167 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5168 					     rsvd0)),
5169 	},
5170 	[ITEM_VXLAN_GPE_RSVD1] = {
5171 		.name = "rsvd1",
5172 		.help = "VXLAN-GPE rsvd1",
5173 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5174 			     item_param),
5175 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5176 					     rsvd1)),
5177 	},
5178 	[ITEM_ARP_ETH_IPV4] = {
5179 		.name = "arp_eth_ipv4",
5180 		.help = "match ARP header for Ethernet/IPv4",
5181 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5182 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5183 		.next = NEXT(item_arp_eth_ipv4),
5184 		.call = parse_vc,
5185 	},
5186 	[ITEM_ARP_ETH_IPV4_SHA] = {
5187 		.name = "sha",
5188 		.help = "sender hardware address",
5189 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5190 			     item_param),
5191 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5192 					     hdr.arp_data.arp_sha)),
5193 	},
5194 	[ITEM_ARP_ETH_IPV4_SPA] = {
5195 		.name = "spa",
5196 		.help = "sender IPv4 address",
5197 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5198 			     item_param),
5199 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5200 					     hdr.arp_data.arp_sip)),
5201 	},
5202 	[ITEM_ARP_ETH_IPV4_THA] = {
5203 		.name = "tha",
5204 		.help = "target hardware address",
5205 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5206 			     item_param),
5207 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5208 					     hdr.arp_data.arp_tha)),
5209 	},
5210 	[ITEM_ARP_ETH_IPV4_TPA] = {
5211 		.name = "tpa",
5212 		.help = "target IPv4 address",
5213 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5214 			     item_param),
5215 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5216 					     hdr.arp_data.arp_tip)),
5217 	},
5218 	[ITEM_IPV6_EXT] = {
5219 		.name = "ipv6_ext",
5220 		.help = "match presence of any IPv6 extension header",
5221 		.priv = PRIV_ITEM(IPV6_EXT,
5222 				  sizeof(struct rte_flow_item_ipv6_ext)),
5223 		.next = NEXT(item_ipv6_ext),
5224 		.call = parse_vc,
5225 	},
5226 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5227 		.name = "next_hdr",
5228 		.help = "next header",
5229 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5230 			     item_param),
5231 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5232 					     next_hdr)),
5233 	},
5234 	[ITEM_IPV6_FRAG_EXT] = {
5235 		.name = "ipv6_frag_ext",
5236 		.help = "match presence of IPv6 fragment extension header",
5237 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5238 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5239 		.next = NEXT(item_ipv6_frag_ext),
5240 		.call = parse_vc,
5241 	},
5242 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5243 		.name = "next_hdr",
5244 		.help = "next header",
5245 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5246 			     item_param),
5247 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5248 					hdr.next_header)),
5249 	},
5250 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5251 		.name = "frag_data",
5252 		.help = "fragment flags and offset",
5253 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5254 			     item_param),
5255 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5256 					     hdr.frag_data)),
5257 	},
5258 	[ITEM_IPV6_FRAG_EXT_ID] = {
5259 		.name = "packet_id",
5260 		.help = "fragment packet id",
5261 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5262 			     item_param),
5263 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5264 					     hdr.id)),
5265 	},
5266 	[ITEM_ICMP6] = {
5267 		.name = "icmp6",
5268 		.help = "match any ICMPv6 header",
5269 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5270 		.next = NEXT(item_icmp6),
5271 		.call = parse_vc,
5272 	},
5273 	[ITEM_ICMP6_TYPE] = {
5274 		.name = "type",
5275 		.help = "ICMPv6 type",
5276 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5277 			     item_param),
5278 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5279 					     type)),
5280 	},
5281 	[ITEM_ICMP6_CODE] = {
5282 		.name = "code",
5283 		.help = "ICMPv6 code",
5284 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5285 			     item_param),
5286 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5287 					     code)),
5288 	},
5289 	[ITEM_ICMP6_ECHO_REQUEST] = {
5290 		.name = "icmp6_echo_request",
5291 		.help = "match ICMPv6 echo request",
5292 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5293 				  sizeof(struct rte_flow_item_icmp6_echo)),
5294 		.next = NEXT(item_icmp6_echo_request),
5295 		.call = parse_vc,
5296 	},
5297 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5298 		.name = "ident",
5299 		.help = "ICMPv6 echo request identifier",
5300 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5301 			     item_param),
5302 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5303 					     hdr.identifier)),
5304 	},
5305 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5306 		.name = "seq",
5307 		.help = "ICMPv6 echo request sequence",
5308 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5309 			     item_param),
5310 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5311 					     hdr.sequence)),
5312 	},
5313 	[ITEM_ICMP6_ECHO_REPLY] = {
5314 		.name = "icmp6_echo_reply",
5315 		.help = "match ICMPv6 echo reply",
5316 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5317 				  sizeof(struct rte_flow_item_icmp6_echo)),
5318 		.next = NEXT(item_icmp6_echo_reply),
5319 		.call = parse_vc,
5320 	},
5321 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5322 		.name = "ident",
5323 		.help = "ICMPv6 echo reply identifier",
5324 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5325 			     item_param),
5326 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5327 					     hdr.identifier)),
5328 	},
5329 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5330 		.name = "seq",
5331 		.help = "ICMPv6 echo reply sequence",
5332 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5333 			     item_param),
5334 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5335 					     hdr.sequence)),
5336 	},
5337 	[ITEM_ICMP6_ND_NS] = {
5338 		.name = "icmp6_nd_ns",
5339 		.help = "match ICMPv6 neighbor discovery solicitation",
5340 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5341 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5342 		.next = NEXT(item_icmp6_nd_ns),
5343 		.call = parse_vc,
5344 	},
5345 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5346 		.name = "target_addr",
5347 		.help = "target address",
5348 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5349 			     item_param),
5350 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5351 					     target_addr)),
5352 	},
5353 	[ITEM_ICMP6_ND_NA] = {
5354 		.name = "icmp6_nd_na",
5355 		.help = "match ICMPv6 neighbor discovery advertisement",
5356 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5357 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5358 		.next = NEXT(item_icmp6_nd_na),
5359 		.call = parse_vc,
5360 	},
5361 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5362 		.name = "target_addr",
5363 		.help = "target address",
5364 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5365 			     item_param),
5366 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5367 					     target_addr)),
5368 	},
5369 	[ITEM_ICMP6_ND_OPT] = {
5370 		.name = "icmp6_nd_opt",
5371 		.help = "match presence of any ICMPv6 neighbor discovery"
5372 			" option",
5373 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5374 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5375 		.next = NEXT(item_icmp6_nd_opt),
5376 		.call = parse_vc,
5377 	},
5378 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5379 		.name = "type",
5380 		.help = "ND option type",
5381 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5382 			     item_param),
5383 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5384 					     type)),
5385 	},
5386 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5387 		.name = "icmp6_nd_opt_sla_eth",
5388 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5389 			" link-layer address option",
5390 		.priv = PRIV_ITEM
5391 			(ICMP6_ND_OPT_SLA_ETH,
5392 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5393 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5394 		.call = parse_vc,
5395 	},
5396 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5397 		.name = "sla",
5398 		.help = "source Ethernet LLA",
5399 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5400 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5401 		.args = ARGS(ARGS_ENTRY_HTON
5402 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5403 	},
5404 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5405 		.name = "icmp6_nd_opt_tla_eth",
5406 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5407 			" link-layer address option",
5408 		.priv = PRIV_ITEM
5409 			(ICMP6_ND_OPT_TLA_ETH,
5410 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5411 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5412 		.call = parse_vc,
5413 	},
5414 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5415 		.name = "tla",
5416 		.help = "target Ethernet LLA",
5417 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5418 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5419 		.args = ARGS(ARGS_ENTRY_HTON
5420 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5421 	},
5422 	[ITEM_META] = {
5423 		.name = "meta",
5424 		.help = "match metadata header",
5425 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5426 		.next = NEXT(item_meta),
5427 		.call = parse_vc,
5428 	},
5429 	[ITEM_META_DATA] = {
5430 		.name = "data",
5431 		.help = "metadata value",
5432 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5433 			     item_param),
5434 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5435 					     data, "\xff\xff\xff\xff")),
5436 	},
5437 	[ITEM_RANDOM] = {
5438 		.name = "random",
5439 		.help = "match random value",
5440 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5441 		.next = NEXT(item_random),
5442 		.call = parse_vc,
5443 	},
5444 	[ITEM_RANDOM_VALUE] = {
5445 		.name = "value",
5446 		.help = "random value",
5447 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5448 			     item_param),
5449 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5450 					     value, "\xff\xff")),
5451 	},
5452 	[ITEM_GRE_KEY] = {
5453 		.name = "gre_key",
5454 		.help = "match GRE key",
5455 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5456 		.next = NEXT(item_gre_key),
5457 		.call = parse_vc,
5458 	},
5459 	[ITEM_GRE_KEY_VALUE] = {
5460 		.name = "value",
5461 		.help = "key value",
5462 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5463 			     item_param),
5464 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5465 	},
5466 	[ITEM_GRE_OPTION] = {
5467 		.name = "gre_option",
5468 		.help = "match GRE optional fields",
5469 		.priv = PRIV_ITEM(GRE_OPTION,
5470 				  sizeof(struct rte_flow_item_gre_opt)),
5471 		.next = NEXT(item_gre_option),
5472 		.call = parse_vc,
5473 	},
5474 	[ITEM_GRE_OPTION_CHECKSUM] = {
5475 		.name = "checksum",
5476 		.help = "match GRE checksum",
5477 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5478 			     item_param),
5479 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5480 					     checksum_rsvd.checksum)),
5481 	},
5482 	[ITEM_GRE_OPTION_KEY] = {
5483 		.name = "key",
5484 		.help = "match GRE key",
5485 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5486 			     item_param),
5487 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5488 					     key.key)),
5489 	},
5490 	[ITEM_GRE_OPTION_SEQUENCE] = {
5491 		.name = "sequence",
5492 		.help = "match GRE sequence",
5493 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5494 			     item_param),
5495 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5496 					     sequence.sequence)),
5497 	},
5498 	[ITEM_GTP_PSC] = {
5499 		.name = "gtp_psc",
5500 		.help = "match GTP extension header with type 0x85",
5501 		.priv = PRIV_ITEM(GTP_PSC,
5502 				sizeof(struct rte_flow_item_gtp_psc)),
5503 		.next = NEXT(item_gtp_psc),
5504 		.call = parse_vc,
5505 	},
5506 	[ITEM_GTP_PSC_QFI] = {
5507 		.name = "qfi",
5508 		.help = "QoS flow identifier",
5509 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5510 			     item_param),
5511 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5512 					hdr.qfi, 6)),
5513 	},
5514 	[ITEM_GTP_PSC_PDU_T] = {
5515 		.name = "pdu_t",
5516 		.help = "PDU type",
5517 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5518 			     item_param),
5519 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5520 					hdr.type, 4)),
5521 	},
5522 	[ITEM_PPPOES] = {
5523 		.name = "pppoes",
5524 		.help = "match PPPoE session header",
5525 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5526 		.next = NEXT(item_pppoes),
5527 		.call = parse_vc,
5528 	},
5529 	[ITEM_PPPOED] = {
5530 		.name = "pppoed",
5531 		.help = "match PPPoE discovery header",
5532 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5533 		.next = NEXT(item_pppoed),
5534 		.call = parse_vc,
5535 	},
5536 	[ITEM_PPPOE_SEID] = {
5537 		.name = "seid",
5538 		.help = "session identifier",
5539 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5540 			     item_param),
5541 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5542 					session_id)),
5543 	},
5544 	[ITEM_PPPOE_PROTO_ID] = {
5545 		.name = "pppoe_proto_id",
5546 		.help = "match PPPoE session protocol identifier",
5547 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5548 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5549 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5550 			     item_param),
5551 		.args = ARGS(ARGS_ENTRY_HTON
5552 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5553 		.call = parse_vc,
5554 	},
5555 	[ITEM_HIGIG2] = {
5556 		.name = "higig2",
5557 		.help = "matches higig2 header",
5558 		.priv = PRIV_ITEM(HIGIG2,
5559 				sizeof(struct rte_flow_item_higig2_hdr)),
5560 		.next = NEXT(item_higig2),
5561 		.call = parse_vc,
5562 	},
5563 	[ITEM_HIGIG2_CLASSIFICATION] = {
5564 		.name = "classification",
5565 		.help = "matches classification of higig2 header",
5566 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5567 			     item_param),
5568 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5569 					hdr.ppt1.classification)),
5570 	},
5571 	[ITEM_HIGIG2_VID] = {
5572 		.name = "vid",
5573 		.help = "matches vid of higig2 header",
5574 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5575 			     item_param),
5576 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5577 					hdr.ppt1.vid)),
5578 	},
5579 	[ITEM_TAG] = {
5580 		.name = "tag",
5581 		.help = "match tag value",
5582 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5583 		.next = NEXT(item_tag),
5584 		.call = parse_vc,
5585 	},
5586 	[ITEM_TAG_DATA] = {
5587 		.name = "data",
5588 		.help = "tag value to match",
5589 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5590 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5591 	},
5592 	[ITEM_TAG_INDEX] = {
5593 		.name = "index",
5594 		.help = "index of tag array to match",
5595 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5596 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5597 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5598 	},
5599 	[ITEM_L2TPV3OIP] = {
5600 		.name = "l2tpv3oip",
5601 		.help = "match L2TPv3 over IP header",
5602 		.priv = PRIV_ITEM(L2TPV3OIP,
5603 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5604 		.next = NEXT(item_l2tpv3oip),
5605 		.call = parse_vc,
5606 	},
5607 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5608 		.name = "session_id",
5609 		.help = "session identifier",
5610 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5611 			     item_param),
5612 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5613 					     session_id)),
5614 	},
5615 	[ITEM_ESP] = {
5616 		.name = "esp",
5617 		.help = "match ESP header",
5618 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5619 		.next = NEXT(item_esp),
5620 		.call = parse_vc,
5621 	},
5622 	[ITEM_ESP_SPI] = {
5623 		.name = "spi",
5624 		.help = "security policy index",
5625 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5626 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5627 				hdr.spi)),
5628 	},
5629 	[ITEM_AH] = {
5630 		.name = "ah",
5631 		.help = "match AH header",
5632 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5633 		.next = NEXT(item_ah),
5634 		.call = parse_vc,
5635 	},
5636 	[ITEM_AH_SPI] = {
5637 		.name = "spi",
5638 		.help = "security parameters index",
5639 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5640 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5641 	},
5642 	[ITEM_PFCP] = {
5643 		.name = "pfcp",
5644 		.help = "match pfcp header",
5645 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5646 		.next = NEXT(item_pfcp),
5647 		.call = parse_vc,
5648 	},
5649 	[ITEM_PFCP_S_FIELD] = {
5650 		.name = "s_field",
5651 		.help = "S field",
5652 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5653 			     item_param),
5654 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5655 				s_field)),
5656 	},
5657 	[ITEM_PFCP_SEID] = {
5658 		.name = "seid",
5659 		.help = "session endpoint identifier",
5660 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5661 			     item_param),
5662 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5663 	},
5664 	[ITEM_ECPRI] = {
5665 		.name = "ecpri",
5666 		.help = "match eCPRI header",
5667 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5668 		.next = NEXT(item_ecpri),
5669 		.call = parse_vc,
5670 	},
5671 	[ITEM_ECPRI_COMMON] = {
5672 		.name = "common",
5673 		.help = "eCPRI common header",
5674 		.next = NEXT(item_ecpri_common),
5675 	},
5676 	[ITEM_ECPRI_COMMON_TYPE] = {
5677 		.name = "type",
5678 		.help = "type of common header",
5679 		.next = NEXT(item_ecpri_common_type),
5680 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5681 	},
5682 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5683 		.name = "iq_data",
5684 		.help = "Type #0: IQ Data",
5685 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5686 					ITEM_NEXT)),
5687 		.call = parse_vc_item_ecpri_type,
5688 	},
5689 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5690 		.name = "pc_id",
5691 		.help = "Physical Channel ID",
5692 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5693 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5694 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5695 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5696 				hdr.type0.pc_id)),
5697 	},
5698 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5699 		.name = "rtc_ctrl",
5700 		.help = "Type #2: Real-Time Control Data",
5701 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5702 					ITEM_NEXT)),
5703 		.call = parse_vc_item_ecpri_type,
5704 	},
5705 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5706 		.name = "rtc_id",
5707 		.help = "Real-Time Control Data ID",
5708 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5709 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5710 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5711 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5712 				hdr.type2.rtc_id)),
5713 	},
5714 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5715 		.name = "delay_measure",
5716 		.help = "Type #5: One-Way Delay Measurement",
5717 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5718 					ITEM_NEXT)),
5719 		.call = parse_vc_item_ecpri_type,
5720 	},
5721 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5722 		.name = "msr_id",
5723 		.help = "Measurement ID",
5724 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5725 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5726 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5727 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5728 				hdr.type5.msr_id)),
5729 	},
5730 	[ITEM_GENEVE_OPT] = {
5731 		.name = "geneve-opt",
5732 		.help = "GENEVE header option",
5733 		.priv = PRIV_ITEM(GENEVE_OPT,
5734 				  sizeof(struct rte_flow_item_geneve_opt) +
5735 				  ITEM_GENEVE_OPT_DATA_SIZE),
5736 		.next = NEXT(item_geneve_opt),
5737 		.call = parse_vc,
5738 	},
5739 	[ITEM_GENEVE_OPT_CLASS]	= {
5740 		.name = "class",
5741 		.help = "GENEVE option class",
5742 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5743 			     item_param),
5744 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5745 					     option_class)),
5746 	},
5747 	[ITEM_GENEVE_OPT_TYPE] = {
5748 		.name = "type",
5749 		.help = "GENEVE option type",
5750 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5751 			     item_param),
5752 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5753 					option_type)),
5754 	},
5755 	[ITEM_GENEVE_OPT_LENGTH] = {
5756 		.name = "length",
5757 		.help = "GENEVE option data length (in 32b words)",
5758 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5759 			     item_param),
5760 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5761 				struct rte_flow_item_geneve_opt, option_len,
5762 				0, 31)),
5763 	},
5764 	[ITEM_GENEVE_OPT_DATA] = {
5765 		.name = "data",
5766 		.help = "GENEVE option data pattern",
5767 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5768 			     item_param),
5769 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5770 			     ARGS_ENTRY_ARB(0, 0),
5771 			     ARGS_ENTRY_ARB
5772 				(sizeof(struct rte_flow_item_geneve_opt),
5773 				ITEM_GENEVE_OPT_DATA_SIZE)),
5774 	},
5775 	[ITEM_INTEGRITY] = {
5776 		.name = "integrity",
5777 		.help = "match packet integrity",
5778 		.priv = PRIV_ITEM(INTEGRITY,
5779 				  sizeof(struct rte_flow_item_integrity)),
5780 		.next = NEXT(item_integrity),
5781 		.call = parse_vc,
5782 	},
5783 	[ITEM_INTEGRITY_LEVEL] = {
5784 		.name = "level",
5785 		.help = "integrity level",
5786 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5787 			     item_param),
5788 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5789 	},
5790 	[ITEM_INTEGRITY_VALUE] = {
5791 		.name = "value",
5792 		.help = "integrity value",
5793 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5794 			     item_param),
5795 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5796 	},
5797 	[ITEM_CONNTRACK] = {
5798 		.name = "conntrack",
5799 		.help = "conntrack state",
5800 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5801 			     item_param),
5802 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5803 	},
5804 	[ITEM_PORT_REPRESENTOR] = {
5805 		.name = "port_representor",
5806 		.help = "match traffic entering the embedded switch from the given ethdev",
5807 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5808 				  sizeof(struct rte_flow_item_ethdev)),
5809 		.next = NEXT(item_port_representor),
5810 		.call = parse_vc,
5811 	},
5812 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5813 		.name = "port_id",
5814 		.help = "ethdev port ID",
5815 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5816 			     item_param),
5817 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5818 	},
5819 	[ITEM_REPRESENTED_PORT] = {
5820 		.name = "represented_port",
5821 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5822 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5823 				  sizeof(struct rte_flow_item_ethdev)),
5824 		.next = NEXT(item_represented_port),
5825 		.call = parse_vc,
5826 	},
5827 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5828 		.name = "ethdev_port_id",
5829 		.help = "ethdev port ID",
5830 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5831 			     item_param),
5832 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5833 	},
5834 	[ITEM_FLEX] = {
5835 		.name = "flex",
5836 		.help = "match flex header",
5837 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5838 		.next = NEXT(item_flex),
5839 		.call = parse_vc,
5840 	},
5841 	[ITEM_FLEX_ITEM_HANDLE] = {
5842 		.name = "item",
5843 		.help = "flex item handle",
5844 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5845 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5846 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5847 	},
5848 	[ITEM_FLEX_PATTERN_HANDLE] = {
5849 		.name = "pattern",
5850 		.help = "flex pattern handle",
5851 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5852 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5853 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5854 	},
5855 	[ITEM_L2TPV2] = {
5856 		.name = "l2tpv2",
5857 		.help = "match L2TPv2 header",
5858 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5859 		.next = NEXT(item_l2tpv2),
5860 		.call = parse_vc,
5861 	},
5862 	[ITEM_L2TPV2_TYPE] = {
5863 		.name = "type",
5864 		.help = "type of l2tpv2",
5865 		.next = NEXT(item_l2tpv2_type),
5866 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5867 	},
5868 	[ITEM_L2TPV2_TYPE_DATA] = {
5869 		.name = "data",
5870 		.help = "Type #7: data message without any options",
5871 		.next = NEXT(item_l2tpv2_type_data),
5872 		.call = parse_vc_item_l2tpv2_type,
5873 	},
5874 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5875 		.name = "tunnel_id",
5876 		.help = "tunnel identifier",
5877 		.next = NEXT(item_l2tpv2_type_data,
5878 			     NEXT_ENTRY(COMMON_UNSIGNED),
5879 			     item_param),
5880 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5881 					     hdr.type7.tunnel_id)),
5882 	},
5883 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5884 		.name = "session_id",
5885 		.help = "session identifier",
5886 		.next = NEXT(item_l2tpv2_type_data,
5887 			     NEXT_ENTRY(COMMON_UNSIGNED),
5888 			     item_param),
5889 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5890 					     hdr.type7.session_id)),
5891 	},
5892 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5893 		.name = "data_l",
5894 		.help = "Type #6: data message with length option",
5895 		.next = NEXT(item_l2tpv2_type_data_l),
5896 		.call = parse_vc_item_l2tpv2_type,
5897 	},
5898 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5899 		.name = "length",
5900 		.help = "message length",
5901 		.next = NEXT(item_l2tpv2_type_data_l,
5902 			     NEXT_ENTRY(COMMON_UNSIGNED),
5903 			     item_param),
5904 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5905 					     hdr.type6.length)),
5906 	},
5907 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5908 		.name = "tunnel_id",
5909 		.help = "tunnel identifier",
5910 		.next = NEXT(item_l2tpv2_type_data_l,
5911 			     NEXT_ENTRY(COMMON_UNSIGNED),
5912 			     item_param),
5913 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5914 					     hdr.type6.tunnel_id)),
5915 	},
5916 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5917 		.name = "session_id",
5918 		.help = "session identifier",
5919 		.next = NEXT(item_l2tpv2_type_data_l,
5920 			     NEXT_ENTRY(COMMON_UNSIGNED),
5921 			     item_param),
5922 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5923 					     hdr.type6.session_id)),
5924 	},
5925 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5926 		.name = "data_s",
5927 		.help = "Type #5: data message with ns, nr option",
5928 		.next = NEXT(item_l2tpv2_type_data_s),
5929 		.call = parse_vc_item_l2tpv2_type,
5930 	},
5931 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5932 		.name = "tunnel_id",
5933 		.help = "tunnel identifier",
5934 		.next = NEXT(item_l2tpv2_type_data_s,
5935 			     NEXT_ENTRY(COMMON_UNSIGNED),
5936 			     item_param),
5937 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5938 					     hdr.type5.tunnel_id)),
5939 	},
5940 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5941 		.name = "session_id",
5942 		.help = "session identifier",
5943 		.next = NEXT(item_l2tpv2_type_data_s,
5944 			     NEXT_ENTRY(COMMON_UNSIGNED),
5945 			     item_param),
5946 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5947 					     hdr.type5.session_id)),
5948 	},
5949 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5950 		.name = "ns",
5951 		.help = "sequence number for message",
5952 		.next = NEXT(item_l2tpv2_type_data_s,
5953 			     NEXT_ENTRY(COMMON_UNSIGNED),
5954 			     item_param),
5955 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5956 					     hdr.type5.ns)),
5957 	},
5958 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5959 		.name = "nr",
5960 		.help = "sequence number for next receive message",
5961 		.next = NEXT(item_l2tpv2_type_data_s,
5962 			     NEXT_ENTRY(COMMON_UNSIGNED),
5963 			     item_param),
5964 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5965 					     hdr.type5.nr)),
5966 	},
5967 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5968 		.name = "data_o",
5969 		.help = "Type #4: data message with offset option",
5970 		.next = NEXT(item_l2tpv2_type_data_o),
5971 		.call = parse_vc_item_l2tpv2_type,
5972 	},
5973 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5974 		.name = "tunnel_id",
5975 		.help = "tunnel identifier",
5976 		.next = NEXT(item_l2tpv2_type_data_o,
5977 			     NEXT_ENTRY(COMMON_UNSIGNED),
5978 			     item_param),
5979 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5980 					     hdr.type4.tunnel_id)),
5981 	},
5982 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5983 		.name = "session_id",
5984 		.help = "session identifier",
5985 		.next = NEXT(item_l2tpv2_type_data_o,
5986 			     NEXT_ENTRY(COMMON_UNSIGNED),
5987 			     item_param),
5988 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5989 					     hdr.type5.session_id)),
5990 	},
5991 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
5992 		.name = "offset_size",
5993 		.help = "the size of offset padding",
5994 		.next = NEXT(item_l2tpv2_type_data_o,
5995 			     NEXT_ENTRY(COMMON_UNSIGNED),
5996 			     item_param),
5997 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5998 					     hdr.type4.offset_size)),
5999 	},
6000 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6001 		.name = "data_l_s",
6002 		.help = "Type #3: data message contains length, ns, nr "
6003 			"options",
6004 		.next = NEXT(item_l2tpv2_type_data_l_s),
6005 		.call = parse_vc_item_l2tpv2_type,
6006 	},
6007 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6008 		.name = "length",
6009 		.help = "message length",
6010 		.next = NEXT(item_l2tpv2_type_data_l_s,
6011 			     NEXT_ENTRY(COMMON_UNSIGNED),
6012 			     item_param),
6013 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6014 					     hdr.type3.length)),
6015 	},
6016 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6017 		.name = "tunnel_id",
6018 		.help = "tunnel identifier",
6019 		.next = NEXT(item_l2tpv2_type_data_l_s,
6020 			     NEXT_ENTRY(COMMON_UNSIGNED),
6021 			     item_param),
6022 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6023 					     hdr.type3.tunnel_id)),
6024 	},
6025 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6026 		.name = "session_id",
6027 		.help = "session identifier",
6028 		.next = NEXT(item_l2tpv2_type_data_l_s,
6029 			     NEXT_ENTRY(COMMON_UNSIGNED),
6030 			     item_param),
6031 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6032 					     hdr.type3.session_id)),
6033 	},
6034 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6035 		.name = "ns",
6036 		.help = "sequence number for message",
6037 		.next = NEXT(item_l2tpv2_type_data_l_s,
6038 			     NEXT_ENTRY(COMMON_UNSIGNED),
6039 			     item_param),
6040 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6041 					     hdr.type3.ns)),
6042 	},
6043 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6044 		.name = "nr",
6045 		.help = "sequence number for next receive message",
6046 		.next = NEXT(item_l2tpv2_type_data_l_s,
6047 			     NEXT_ENTRY(COMMON_UNSIGNED),
6048 			     item_param),
6049 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6050 					     hdr.type3.nr)),
6051 	},
6052 	[ITEM_L2TPV2_TYPE_CTRL] = {
6053 		.name = "control",
6054 		.help = "Type #3: conrtol message contains length, ns, nr "
6055 			"options",
6056 		.next = NEXT(item_l2tpv2_type_ctrl),
6057 		.call = parse_vc_item_l2tpv2_type,
6058 	},
6059 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6060 		.name = "length",
6061 		.help = "message length",
6062 		.next = NEXT(item_l2tpv2_type_ctrl,
6063 			     NEXT_ENTRY(COMMON_UNSIGNED),
6064 			     item_param),
6065 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6066 					     hdr.type3.length)),
6067 	},
6068 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6069 		.name = "tunnel_id",
6070 		.help = "tunnel identifier",
6071 		.next = NEXT(item_l2tpv2_type_ctrl,
6072 			     NEXT_ENTRY(COMMON_UNSIGNED),
6073 			     item_param),
6074 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6075 					     hdr.type3.tunnel_id)),
6076 	},
6077 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6078 		.name = "session_id",
6079 		.help = "session identifier",
6080 		.next = NEXT(item_l2tpv2_type_ctrl,
6081 			     NEXT_ENTRY(COMMON_UNSIGNED),
6082 			     item_param),
6083 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6084 					     hdr.type3.session_id)),
6085 	},
6086 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6087 		.name = "ns",
6088 		.help = "sequence number for message",
6089 		.next = NEXT(item_l2tpv2_type_ctrl,
6090 			     NEXT_ENTRY(COMMON_UNSIGNED),
6091 			     item_param),
6092 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6093 					     hdr.type3.ns)),
6094 	},
6095 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6096 		.name = "nr",
6097 		.help = "sequence number for next receive message",
6098 		.next = NEXT(item_l2tpv2_type_ctrl,
6099 			     NEXT_ENTRY(COMMON_UNSIGNED),
6100 			     item_param),
6101 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6102 					     hdr.type3.nr)),
6103 	},
6104 	[ITEM_PPP] = {
6105 		.name = "ppp",
6106 		.help = "match PPP header",
6107 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6108 		.next = NEXT(item_ppp),
6109 		.call = parse_vc,
6110 	},
6111 	[ITEM_PPP_ADDR] = {
6112 		.name = "addr",
6113 		.help = "PPP address",
6114 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6115 			     item_param),
6116 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6117 	},
6118 	[ITEM_PPP_CTRL] = {
6119 		.name = "ctrl",
6120 		.help = "PPP control",
6121 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6122 			     item_param),
6123 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6124 	},
6125 	[ITEM_PPP_PROTO_ID] = {
6126 		.name = "proto_id",
6127 		.help = "PPP protocol identifier",
6128 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6129 			     item_param),
6130 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6131 					hdr.proto_id)),
6132 	},
6133 	[ITEM_METER] = {
6134 		.name = "meter",
6135 		.help = "match meter color",
6136 		.priv = PRIV_ITEM(METER_COLOR,
6137 				  sizeof(struct rte_flow_item_meter_color)),
6138 		.next = NEXT(item_meter),
6139 		.call = parse_vc,
6140 	},
6141 	[ITEM_METER_COLOR] = {
6142 		.name = "color",
6143 		.help = "meter color",
6144 		.next = NEXT(item_meter,
6145 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6146 			     item_param),
6147 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6148 					color)),
6149 	},
6150 	[ITEM_METER_COLOR_NAME] = {
6151 		.name = "color_name",
6152 		.help = "meter color name",
6153 		.call = parse_meter_color,
6154 		.comp = comp_meter_color,
6155 	},
6156 	[ITEM_QUOTA] = {
6157 		.name = "quota",
6158 		.help = "match quota",
6159 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6160 		.next = NEXT(item_quota),
6161 		.call = parse_vc
6162 	},
6163 	[ITEM_QUOTA_STATE] = {
6164 		.name = "quota_state",
6165 		.help = "quota state",
6166 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6167 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6168 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6169 	},
6170 	[ITEM_QUOTA_STATE_NAME] = {
6171 		.name = "state_name",
6172 		.help = "quota state name",
6173 		.call = parse_quota_state_name,
6174 		.comp = comp_quota_state_name
6175 	},
6176 	[ITEM_IB_BTH] = {
6177 		.name = "ib_bth",
6178 		.help = "match ib bth fields",
6179 		.priv = PRIV_ITEM(IB_BTH,
6180 				  sizeof(struct rte_flow_item_ib_bth)),
6181 		.next = NEXT(item_ib_bth),
6182 		.call = parse_vc,
6183 	},
6184 	[ITEM_IB_BTH_OPCODE] = {
6185 		.name = "opcode",
6186 		.help = "match ib bth opcode",
6187 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6188 				 item_param),
6189 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6190 						 hdr.opcode)),
6191 	},
6192 	[ITEM_IB_BTH_PKEY] = {
6193 		.name = "pkey",
6194 		.help = "partition key",
6195 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6196 				 item_param),
6197 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6198 						 hdr.pkey)),
6199 	},
6200 	[ITEM_IB_BTH_DST_QPN] = {
6201 		.name = "dst_qp",
6202 		.help = "destination qp",
6203 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6204 				 item_param),
6205 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6206 						 hdr.dst_qp)),
6207 	},
6208 	[ITEM_IB_BTH_PSN] = {
6209 		.name = "psn",
6210 		.help = "packet sequence number",
6211 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6212 				 item_param),
6213 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6214 						 hdr.psn)),
6215 	},
6216 	[ITEM_PTYPE] = {
6217 		.name = "ptype",
6218 		.help = "match L2/L3/L4 and tunnel information",
6219 		.priv = PRIV_ITEM(PTYPE,
6220 				  sizeof(struct rte_flow_item_ptype)),
6221 		.next = NEXT(item_ptype),
6222 		.call = parse_vc,
6223 	},
6224 	[ITEM_PTYPE_VALUE] = {
6225 		.name = "packet_type",
6226 		.help = "packet type as defined in rte_mbuf_ptype",
6227 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6228 			     item_param),
6229 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6230 	},
6231 	[ITEM_NSH] = {
6232 		.name = "nsh",
6233 		.help = "match NSH header",
6234 		.priv = PRIV_ITEM(NSH,
6235 				  sizeof(struct rte_flow_item_nsh)),
6236 		.next = NEXT(item_nsh),
6237 		.call = parse_vc,
6238 	},
6239 	[ITEM_COMPARE] = {
6240 		.name = "compare",
6241 		.help = "match with the comparison result",
6242 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6243 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6244 		.call = parse_vc,
6245 	},
6246 	[ITEM_COMPARE_OP] = {
6247 		.name = "op",
6248 		.help = "operation type",
6249 		.next = NEXT(item_compare_field,
6250 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6251 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6252 	},
6253 	[ITEM_COMPARE_OP_VALUE] = {
6254 		.name = "{operation}",
6255 		.help = "operation type value",
6256 		.call = parse_vc_compare_op,
6257 		.comp = comp_set_compare_op,
6258 	},
6259 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6260 		.name = "a_type",
6261 		.help = "compared field type",
6262 		.next = NEXT(compare_field_a,
6263 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6264 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6265 	},
6266 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6267 		.name = "{a_type}",
6268 		.help = "compared field type value",
6269 		.call = parse_vc_compare_field_id,
6270 		.comp = comp_set_compare_field_id,
6271 	},
6272 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6273 		.name = "a_level",
6274 		.help = "compared field level",
6275 		.next = NEXT(compare_field_a,
6276 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6277 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6278 	},
6279 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6280 		.name = "{a_level}",
6281 		.help = "compared field level value",
6282 		.call = parse_vc_compare_field_level,
6283 		.comp = comp_none,
6284 	},
6285 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6286 		.name = "a_tag_index",
6287 		.help = "compared field tag array",
6288 		.next = NEXT(compare_field_a,
6289 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6290 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6291 					a.tag_index)),
6292 	},
6293 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6294 		.name = "a_type_id",
6295 		.help = "compared field type ID",
6296 		.next = NEXT(compare_field_a,
6297 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6298 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6299 					a.type)),
6300 	},
6301 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6302 		.name = "a_class",
6303 		.help = "compared field class ID",
6304 		.next = NEXT(compare_field_a,
6305 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6306 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6307 					     a.class_id)),
6308 	},
6309 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6310 		.name = "a_offset",
6311 		.help = "compared field bit offset",
6312 		.next = NEXT(compare_field_a,
6313 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6314 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6315 					a.offset)),
6316 	},
6317 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6318 		.name = "b_type",
6319 		.help = "comparator field type",
6320 		.next = NEXT(compare_field_b,
6321 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6322 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6323 					b.field)),
6324 	},
6325 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6326 		.name = "{b_type}",
6327 		.help = "comparator field type value",
6328 		.call = parse_vc_compare_field_id,
6329 		.comp = comp_set_compare_field_id,
6330 	},
6331 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6332 		.name = "b_level",
6333 		.help = "comparator field level",
6334 		.next = NEXT(compare_field_b,
6335 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6336 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6337 					b.level)),
6338 	},
6339 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6340 		.name = "{b_level}",
6341 		.help = "comparator field level value",
6342 		.call = parse_vc_compare_field_level,
6343 		.comp = comp_none,
6344 	},
6345 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6346 		.name = "b_tag_index",
6347 		.help = "comparator field tag array",
6348 		.next = NEXT(compare_field_b,
6349 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6350 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6351 					b.tag_index)),
6352 	},
6353 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6354 		.name = "b_type_id",
6355 		.help = "comparator field type ID",
6356 		.next = NEXT(compare_field_b,
6357 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6358 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6359 					b.type)),
6360 	},
6361 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6362 		.name = "b_class",
6363 		.help = "comparator field class ID",
6364 		.next = NEXT(compare_field_b,
6365 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6366 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6367 					     b.class_id)),
6368 	},
6369 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6370 		.name = "b_offset",
6371 		.help = "comparator field bit offset",
6372 		.next = NEXT(compare_field_b,
6373 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6374 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6375 					b.offset)),
6376 	},
6377 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6378 		.name = "b_value",
6379 		.help = "comparator immediate value",
6380 		.next = NEXT(compare_field_b,
6381 			     NEXT_ENTRY(COMMON_HEX), item_param),
6382 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6383 			     ARGS_ENTRY_ARB(0, 0),
6384 			     ARGS_ENTRY(struct rte_flow_item_compare,
6385 					b.value)),
6386 	},
6387 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6388 		.name = "b_ptr",
6389 		.help = "pointer to comparator immediate value",
6390 		.next = NEXT(compare_field_b,
6391 			     NEXT_ENTRY(COMMON_HEX), item_param),
6392 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6393 					b.pvalue),
6394 			     ARGS_ENTRY_ARB(0, 0),
6395 			     ARGS_ENTRY_ARB
6396 				(sizeof(struct rte_flow_item_compare),
6397 				 FLOW_FIELD_PATTERN_SIZE)),
6398 	},
6399 	[ITEM_COMPARE_FIELD_WIDTH] = {
6400 		.name = "width",
6401 		.help = "number of bits to compare",
6402 		.next = NEXT(item_compare_field,
6403 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6404 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6405 					width)),
6406 	},
6407 
6408 	/* Validate/create actions. */
6409 	[ACTIONS] = {
6410 		.name = "actions",
6411 		.help = "submit a list of associated actions",
6412 		.next = NEXT(next_action),
6413 		.call = parse_vc,
6414 	},
6415 	[ACTION_NEXT] = {
6416 		.name = "/",
6417 		.help = "specify next action",
6418 		.next = NEXT(next_action),
6419 	},
6420 	[ACTION_END] = {
6421 		.name = "end",
6422 		.help = "end list of actions",
6423 		.priv = PRIV_ACTION(END, 0),
6424 		.call = parse_vc,
6425 	},
6426 	[ACTION_VOID] = {
6427 		.name = "void",
6428 		.help = "no-op action",
6429 		.priv = PRIV_ACTION(VOID, 0),
6430 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6431 		.call = parse_vc,
6432 	},
6433 	[ACTION_PASSTHRU] = {
6434 		.name = "passthru",
6435 		.help = "let subsequent rule process matched packets",
6436 		.priv = PRIV_ACTION(PASSTHRU, 0),
6437 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6438 		.call = parse_vc,
6439 	},
6440 	[ACTION_SKIP_CMAN] = {
6441 		.name = "skip_cman",
6442 		.help = "bypass cman on received packets",
6443 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6444 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6445 		.call = parse_vc,
6446 	},
6447 	[ACTION_JUMP] = {
6448 		.name = "jump",
6449 		.help = "redirect traffic to a given group",
6450 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6451 		.next = NEXT(action_jump),
6452 		.call = parse_vc,
6453 	},
6454 	[ACTION_JUMP_GROUP] = {
6455 		.name = "group",
6456 		.help = "group to redirect traffic to",
6457 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6458 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6459 		.call = parse_vc_conf,
6460 	},
6461 	[ACTION_MARK] = {
6462 		.name = "mark",
6463 		.help = "attach 32 bit value to packets",
6464 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6465 		.next = NEXT(action_mark),
6466 		.call = parse_vc,
6467 	},
6468 	[ACTION_MARK_ID] = {
6469 		.name = "id",
6470 		.help = "32 bit value to return with packets",
6471 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6472 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6473 		.call = parse_vc_conf,
6474 	},
6475 	[ACTION_FLAG] = {
6476 		.name = "flag",
6477 		.help = "flag packets",
6478 		.priv = PRIV_ACTION(FLAG, 0),
6479 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6480 		.call = parse_vc,
6481 	},
6482 	[ACTION_QUEUE] = {
6483 		.name = "queue",
6484 		.help = "assign packets to a given queue index",
6485 		.priv = PRIV_ACTION(QUEUE,
6486 				    sizeof(struct rte_flow_action_queue)),
6487 		.next = NEXT(action_queue),
6488 		.call = parse_vc,
6489 	},
6490 	[ACTION_QUEUE_INDEX] = {
6491 		.name = "index",
6492 		.help = "queue index to use",
6493 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6494 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6495 		.call = parse_vc_conf,
6496 	},
6497 	[ACTION_DROP] = {
6498 		.name = "drop",
6499 		.help = "drop packets (note: passthru has priority)",
6500 		.priv = PRIV_ACTION(DROP, 0),
6501 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6502 		.call = parse_vc,
6503 	},
6504 	[ACTION_COUNT] = {
6505 		.name = "count",
6506 		.help = "enable counters for this rule",
6507 		.priv = PRIV_ACTION(COUNT,
6508 				    sizeof(struct rte_flow_action_count)),
6509 		.next = NEXT(action_count),
6510 		.call = parse_vc,
6511 	},
6512 	[ACTION_COUNT_ID] = {
6513 		.name = "identifier",
6514 		.help = "counter identifier to use",
6515 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6516 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6517 		.call = parse_vc_conf,
6518 	},
6519 	[ACTION_RSS] = {
6520 		.name = "rss",
6521 		.help = "spread packets among several queues",
6522 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6523 		.next = NEXT(action_rss),
6524 		.call = parse_vc_action_rss,
6525 	},
6526 	[ACTION_RSS_FUNC] = {
6527 		.name = "func",
6528 		.help = "RSS hash function to apply",
6529 		.next = NEXT(action_rss,
6530 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6531 					ACTION_RSS_FUNC_TOEPLITZ,
6532 					ACTION_RSS_FUNC_SIMPLE_XOR,
6533 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6534 	},
6535 	[ACTION_RSS_FUNC_DEFAULT] = {
6536 		.name = "default",
6537 		.help = "default hash function",
6538 		.call = parse_vc_action_rss_func,
6539 	},
6540 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6541 		.name = "toeplitz",
6542 		.help = "Toeplitz hash function",
6543 		.call = parse_vc_action_rss_func,
6544 	},
6545 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6546 		.name = "simple_xor",
6547 		.help = "simple XOR hash function",
6548 		.call = parse_vc_action_rss_func,
6549 	},
6550 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6551 		.name = "symmetric_toeplitz",
6552 		.help = "Symmetric Toeplitz hash function",
6553 		.call = parse_vc_action_rss_func,
6554 	},
6555 	[ACTION_RSS_LEVEL] = {
6556 		.name = "level",
6557 		.help = "encapsulation level for \"types\"",
6558 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6559 		.args = ARGS(ARGS_ENTRY_ARB
6560 			     (offsetof(struct action_rss_data, conf) +
6561 			      offsetof(struct rte_flow_action_rss, level),
6562 			      sizeof(((struct rte_flow_action_rss *)0)->
6563 				     level))),
6564 	},
6565 	[ACTION_RSS_TYPES] = {
6566 		.name = "types",
6567 		.help = "specific RSS hash types",
6568 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6569 	},
6570 	[ACTION_RSS_TYPE] = {
6571 		.name = "{type}",
6572 		.help = "RSS hash type",
6573 		.call = parse_vc_action_rss_type,
6574 		.comp = comp_vc_action_rss_type,
6575 	},
6576 	[ACTION_RSS_KEY] = {
6577 		.name = "key",
6578 		.help = "RSS hash key",
6579 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6580 		.args = ARGS(ARGS_ENTRY_ARB
6581 			     (offsetof(struct action_rss_data, conf) +
6582 			      offsetof(struct rte_flow_action_rss, key),
6583 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6584 			     ARGS_ENTRY_ARB
6585 			     (offsetof(struct action_rss_data, conf) +
6586 			      offsetof(struct rte_flow_action_rss, key_len),
6587 			      sizeof(((struct rte_flow_action_rss *)0)->
6588 				     key_len)),
6589 			     ARGS_ENTRY(struct action_rss_data, key)),
6590 	},
6591 	[ACTION_RSS_KEY_LEN] = {
6592 		.name = "key_len",
6593 		.help = "RSS hash key length in bytes",
6594 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6595 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6596 			     (offsetof(struct action_rss_data, conf) +
6597 			      offsetof(struct rte_flow_action_rss, key_len),
6598 			      sizeof(((struct rte_flow_action_rss *)0)->
6599 				     key_len),
6600 			      0,
6601 			      RSS_HASH_KEY_LENGTH)),
6602 	},
6603 	[ACTION_RSS_QUEUES] = {
6604 		.name = "queues",
6605 		.help = "queue indices to use",
6606 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6607 		.call = parse_vc_conf,
6608 	},
6609 	[ACTION_RSS_QUEUE] = {
6610 		.name = "{queue}",
6611 		.help = "queue index",
6612 		.call = parse_vc_action_rss_queue,
6613 		.comp = comp_vc_action_rss_queue,
6614 	},
6615 	[ACTION_PF] = {
6616 		.name = "pf",
6617 		.help = "direct traffic to physical function",
6618 		.priv = PRIV_ACTION(PF, 0),
6619 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6620 		.call = parse_vc,
6621 	},
6622 	[ACTION_VF] = {
6623 		.name = "vf",
6624 		.help = "direct traffic to a virtual function ID",
6625 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6626 		.next = NEXT(action_vf),
6627 		.call = parse_vc,
6628 	},
6629 	[ACTION_VF_ORIGINAL] = {
6630 		.name = "original",
6631 		.help = "use original VF ID if possible",
6632 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6633 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6634 					   original, 1)),
6635 		.call = parse_vc_conf,
6636 	},
6637 	[ACTION_VF_ID] = {
6638 		.name = "id",
6639 		.help = "VF ID",
6640 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6641 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6642 		.call = parse_vc_conf,
6643 	},
6644 	[ACTION_PORT_ID] = {
6645 		.name = "port_id",
6646 		.help = "direct matching traffic to a given DPDK port ID",
6647 		.priv = PRIV_ACTION(PORT_ID,
6648 				    sizeof(struct rte_flow_action_port_id)),
6649 		.next = NEXT(action_port_id),
6650 		.call = parse_vc,
6651 	},
6652 	[ACTION_PORT_ID_ORIGINAL] = {
6653 		.name = "original",
6654 		.help = "use original DPDK port ID if possible",
6655 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6656 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6657 					   original, 1)),
6658 		.call = parse_vc_conf,
6659 	},
6660 	[ACTION_PORT_ID_ID] = {
6661 		.name = "id",
6662 		.help = "DPDK port ID",
6663 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6664 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6665 		.call = parse_vc_conf,
6666 	},
6667 	[ACTION_METER] = {
6668 		.name = "meter",
6669 		.help = "meter the directed packets at given id",
6670 		.priv = PRIV_ACTION(METER,
6671 				    sizeof(struct rte_flow_action_meter)),
6672 		.next = NEXT(action_meter),
6673 		.call = parse_vc,
6674 	},
6675 	[ACTION_METER_COLOR] = {
6676 		.name = "color",
6677 		.help = "meter color for the packets",
6678 		.priv = PRIV_ACTION(METER_COLOR,
6679 				sizeof(struct rte_flow_action_meter_color)),
6680 		.next = NEXT(action_meter_color),
6681 		.call = parse_vc,
6682 	},
6683 	[ACTION_METER_COLOR_TYPE] = {
6684 		.name = "type",
6685 		.help = "specific meter color",
6686 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6687 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6688 					ACTION_METER_COLOR_YELLOW,
6689 					ACTION_METER_COLOR_RED)),
6690 	},
6691 	[ACTION_METER_COLOR_GREEN] = {
6692 		.name = "green",
6693 		.help = "meter color green",
6694 		.call = parse_vc_action_meter_color_type,
6695 	},
6696 	[ACTION_METER_COLOR_YELLOW] = {
6697 		.name = "yellow",
6698 		.help = "meter color yellow",
6699 		.call = parse_vc_action_meter_color_type,
6700 	},
6701 	[ACTION_METER_COLOR_RED] = {
6702 		.name = "red",
6703 		.help = "meter color red",
6704 		.call = parse_vc_action_meter_color_type,
6705 	},
6706 	[ACTION_METER_ID] = {
6707 		.name = "mtr_id",
6708 		.help = "meter id to use",
6709 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6710 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6711 		.call = parse_vc_conf,
6712 	},
6713 	[ACTION_METER_MARK] = {
6714 		.name = "meter_mark",
6715 		.help = "meter the directed packets using profile and policy",
6716 		.priv = PRIV_ACTION(METER_MARK,
6717 				    sizeof(struct rte_flow_action_meter_mark)),
6718 		.next = NEXT(action_meter_mark),
6719 		.call = parse_vc,
6720 	},
6721 	[ACTION_METER_PROFILE] = {
6722 		.name = "mtr_profile",
6723 		.help = "meter profile id to use",
6724 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6725 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6726 	},
6727 	[ACTION_METER_PROFILE_ID2PTR] = {
6728 		.name = "{mtr_profile_id}",
6729 		.type = "PROFILE_ID",
6730 		.help = "meter profile id",
6731 		.next = NEXT(action_meter_mark),
6732 		.call = parse_meter_profile_id2ptr,
6733 		.comp = comp_none,
6734 	},
6735 	[ACTION_METER_POLICY] = {
6736 		.name = "mtr_policy",
6737 		.help = "meter policy id to use",
6738 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6739 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6740 	},
6741 	[ACTION_METER_POLICY_ID2PTR] = {
6742 		.name = "{mtr_policy_id}",
6743 		.type = "POLICY_ID",
6744 		.help = "meter policy id",
6745 		.next = NEXT(action_meter_mark),
6746 		.call = parse_meter_policy_id2ptr,
6747 		.comp = comp_none,
6748 	},
6749 	[ACTION_METER_COLOR_MODE] = {
6750 		.name = "mtr_color_mode",
6751 		.help = "meter color awareness mode",
6752 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6753 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6754 		.call = parse_vc_conf,
6755 	},
6756 	[ACTION_METER_STATE] = {
6757 		.name = "mtr_state",
6758 		.help = "meter state",
6759 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6760 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6761 		.call = parse_vc_conf,
6762 	},
6763 	[ACTION_OF_DEC_NW_TTL] = {
6764 		.name = "of_dec_nw_ttl",
6765 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6766 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6767 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6768 		.call = parse_vc,
6769 	},
6770 	[ACTION_OF_POP_VLAN] = {
6771 		.name = "of_pop_vlan",
6772 		.help = "OpenFlow's OFPAT_POP_VLAN",
6773 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6774 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6775 		.call = parse_vc,
6776 	},
6777 	[ACTION_OF_PUSH_VLAN] = {
6778 		.name = "of_push_vlan",
6779 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6780 		.priv = PRIV_ACTION
6781 			(OF_PUSH_VLAN,
6782 			 sizeof(struct rte_flow_action_of_push_vlan)),
6783 		.next = NEXT(action_of_push_vlan),
6784 		.call = parse_vc,
6785 	},
6786 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6787 		.name = "ethertype",
6788 		.help = "EtherType",
6789 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6790 		.args = ARGS(ARGS_ENTRY_HTON
6791 			     (struct rte_flow_action_of_push_vlan,
6792 			      ethertype)),
6793 		.call = parse_vc_conf,
6794 	},
6795 	[ACTION_OF_SET_VLAN_VID] = {
6796 		.name = "of_set_vlan_vid",
6797 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6798 		.priv = PRIV_ACTION
6799 			(OF_SET_VLAN_VID,
6800 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6801 		.next = NEXT(action_of_set_vlan_vid),
6802 		.call = parse_vc,
6803 	},
6804 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6805 		.name = "vlan_vid",
6806 		.help = "VLAN id",
6807 		.next = NEXT(action_of_set_vlan_vid,
6808 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6809 		.args = ARGS(ARGS_ENTRY_HTON
6810 			     (struct rte_flow_action_of_set_vlan_vid,
6811 			      vlan_vid)),
6812 		.call = parse_vc_conf,
6813 	},
6814 	[ACTION_OF_SET_VLAN_PCP] = {
6815 		.name = "of_set_vlan_pcp",
6816 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6817 		.priv = PRIV_ACTION
6818 			(OF_SET_VLAN_PCP,
6819 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6820 		.next = NEXT(action_of_set_vlan_pcp),
6821 		.call = parse_vc,
6822 	},
6823 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6824 		.name = "vlan_pcp",
6825 		.help = "VLAN priority",
6826 		.next = NEXT(action_of_set_vlan_pcp,
6827 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6828 		.args = ARGS(ARGS_ENTRY_HTON
6829 			     (struct rte_flow_action_of_set_vlan_pcp,
6830 			      vlan_pcp)),
6831 		.call = parse_vc_conf,
6832 	},
6833 	[ACTION_OF_POP_MPLS] = {
6834 		.name = "of_pop_mpls",
6835 		.help = "OpenFlow's OFPAT_POP_MPLS",
6836 		.priv = PRIV_ACTION(OF_POP_MPLS,
6837 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6838 		.next = NEXT(action_of_pop_mpls),
6839 		.call = parse_vc,
6840 	},
6841 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6842 		.name = "ethertype",
6843 		.help = "EtherType",
6844 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6845 		.args = ARGS(ARGS_ENTRY_HTON
6846 			     (struct rte_flow_action_of_pop_mpls,
6847 			      ethertype)),
6848 		.call = parse_vc_conf,
6849 	},
6850 	[ACTION_OF_PUSH_MPLS] = {
6851 		.name = "of_push_mpls",
6852 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6853 		.priv = PRIV_ACTION
6854 			(OF_PUSH_MPLS,
6855 			 sizeof(struct rte_flow_action_of_push_mpls)),
6856 		.next = NEXT(action_of_push_mpls),
6857 		.call = parse_vc,
6858 	},
6859 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6860 		.name = "ethertype",
6861 		.help = "EtherType",
6862 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6863 		.args = ARGS(ARGS_ENTRY_HTON
6864 			     (struct rte_flow_action_of_push_mpls,
6865 			      ethertype)),
6866 		.call = parse_vc_conf,
6867 	},
6868 	[ACTION_VXLAN_ENCAP] = {
6869 		.name = "vxlan_encap",
6870 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6871 			" vxlan\"",
6872 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6873 				    sizeof(struct action_vxlan_encap_data)),
6874 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6875 		.call = parse_vc_action_vxlan_encap,
6876 	},
6877 	[ACTION_VXLAN_DECAP] = {
6878 		.name = "vxlan_decap",
6879 		.help = "Performs a decapsulation action by stripping all"
6880 			" headers of the VXLAN tunnel network overlay from the"
6881 			" matched flow.",
6882 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6883 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6884 		.call = parse_vc,
6885 	},
6886 	[ACTION_NVGRE_ENCAP] = {
6887 		.name = "nvgre_encap",
6888 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6889 			" nvgre\"",
6890 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6891 				    sizeof(struct action_nvgre_encap_data)),
6892 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6893 		.call = parse_vc_action_nvgre_encap,
6894 	},
6895 	[ACTION_NVGRE_DECAP] = {
6896 		.name = "nvgre_decap",
6897 		.help = "Performs a decapsulation action by stripping all"
6898 			" headers of the NVGRE tunnel network overlay from the"
6899 			" matched flow.",
6900 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6901 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6902 		.call = parse_vc,
6903 	},
6904 	[ACTION_L2_ENCAP] = {
6905 		.name = "l2_encap",
6906 		.help = "l2 encap, uses configuration set by"
6907 			" \"set l2_encap\"",
6908 		.priv = PRIV_ACTION(RAW_ENCAP,
6909 				    sizeof(struct action_raw_encap_data)),
6910 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6911 		.call = parse_vc_action_l2_encap,
6912 	},
6913 	[ACTION_L2_DECAP] = {
6914 		.name = "l2_decap",
6915 		.help = "l2 decap, uses configuration set by"
6916 			" \"set l2_decap\"",
6917 		.priv = PRIV_ACTION(RAW_DECAP,
6918 				    sizeof(struct action_raw_decap_data)),
6919 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6920 		.call = parse_vc_action_l2_decap,
6921 	},
6922 	[ACTION_MPLSOGRE_ENCAP] = {
6923 		.name = "mplsogre_encap",
6924 		.help = "mplsogre encapsulation, uses configuration set by"
6925 			" \"set mplsogre_encap\"",
6926 		.priv = PRIV_ACTION(RAW_ENCAP,
6927 				    sizeof(struct action_raw_encap_data)),
6928 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6929 		.call = parse_vc_action_mplsogre_encap,
6930 	},
6931 	[ACTION_MPLSOGRE_DECAP] = {
6932 		.name = "mplsogre_decap",
6933 		.help = "mplsogre decapsulation, uses configuration set by"
6934 			" \"set mplsogre_decap\"",
6935 		.priv = PRIV_ACTION(RAW_DECAP,
6936 				    sizeof(struct action_raw_decap_data)),
6937 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6938 		.call = parse_vc_action_mplsogre_decap,
6939 	},
6940 	[ACTION_MPLSOUDP_ENCAP] = {
6941 		.name = "mplsoudp_encap",
6942 		.help = "mplsoudp encapsulation, uses configuration set by"
6943 			" \"set mplsoudp_encap\"",
6944 		.priv = PRIV_ACTION(RAW_ENCAP,
6945 				    sizeof(struct action_raw_encap_data)),
6946 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6947 		.call = parse_vc_action_mplsoudp_encap,
6948 	},
6949 	[ACTION_MPLSOUDP_DECAP] = {
6950 		.name = "mplsoudp_decap",
6951 		.help = "mplsoudp decapsulation, uses configuration set by"
6952 			" \"set mplsoudp_decap\"",
6953 		.priv = PRIV_ACTION(RAW_DECAP,
6954 				    sizeof(struct action_raw_decap_data)),
6955 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6956 		.call = parse_vc_action_mplsoudp_decap,
6957 	},
6958 	[ACTION_SET_IPV4_SRC] = {
6959 		.name = "set_ipv4_src",
6960 		.help = "Set a new IPv4 source address in the outermost"
6961 			" IPv4 header",
6962 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6963 			sizeof(struct rte_flow_action_set_ipv4)),
6964 		.next = NEXT(action_set_ipv4_src),
6965 		.call = parse_vc,
6966 	},
6967 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6968 		.name = "ipv4_addr",
6969 		.help = "new IPv4 source address to set",
6970 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6971 		.args = ARGS(ARGS_ENTRY_HTON
6972 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6973 		.call = parse_vc_conf,
6974 	},
6975 	[ACTION_SET_IPV4_DST] = {
6976 		.name = "set_ipv4_dst",
6977 		.help = "Set a new IPv4 destination address in the outermost"
6978 			" IPv4 header",
6979 		.priv = PRIV_ACTION(SET_IPV4_DST,
6980 			sizeof(struct rte_flow_action_set_ipv4)),
6981 		.next = NEXT(action_set_ipv4_dst),
6982 		.call = parse_vc,
6983 	},
6984 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6985 		.name = "ipv4_addr",
6986 		.help = "new IPv4 destination address to set",
6987 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6988 		.args = ARGS(ARGS_ENTRY_HTON
6989 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6990 		.call = parse_vc_conf,
6991 	},
6992 	[ACTION_SET_IPV6_SRC] = {
6993 		.name = "set_ipv6_src",
6994 		.help = "Set a new IPv6 source address in the outermost"
6995 			" IPv6 header",
6996 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6997 			sizeof(struct rte_flow_action_set_ipv6)),
6998 		.next = NEXT(action_set_ipv6_src),
6999 		.call = parse_vc,
7000 	},
7001 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7002 		.name = "ipv6_addr",
7003 		.help = "new IPv6 source address to set",
7004 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7005 		.args = ARGS(ARGS_ENTRY_HTON
7006 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7007 		.call = parse_vc_conf,
7008 	},
7009 	[ACTION_SET_IPV6_DST] = {
7010 		.name = "set_ipv6_dst",
7011 		.help = "Set a new IPv6 destination address in the outermost"
7012 			" IPv6 header",
7013 		.priv = PRIV_ACTION(SET_IPV6_DST,
7014 			sizeof(struct rte_flow_action_set_ipv6)),
7015 		.next = NEXT(action_set_ipv6_dst),
7016 		.call = parse_vc,
7017 	},
7018 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7019 		.name = "ipv6_addr",
7020 		.help = "new IPv6 destination address to set",
7021 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7022 		.args = ARGS(ARGS_ENTRY_HTON
7023 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7024 		.call = parse_vc_conf,
7025 	},
7026 	[ACTION_SET_TP_SRC] = {
7027 		.name = "set_tp_src",
7028 		.help = "set a new source port number in the outermost"
7029 			" TCP/UDP header",
7030 		.priv = PRIV_ACTION(SET_TP_SRC,
7031 			sizeof(struct rte_flow_action_set_tp)),
7032 		.next = NEXT(action_set_tp_src),
7033 		.call = parse_vc,
7034 	},
7035 	[ACTION_SET_TP_SRC_TP_SRC] = {
7036 		.name = "port",
7037 		.help = "new source port number to set",
7038 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7039 		.args = ARGS(ARGS_ENTRY_HTON
7040 			     (struct rte_flow_action_set_tp, port)),
7041 		.call = parse_vc_conf,
7042 	},
7043 	[ACTION_SET_TP_DST] = {
7044 		.name = "set_tp_dst",
7045 		.help = "set a new destination port number in the outermost"
7046 			" TCP/UDP header",
7047 		.priv = PRIV_ACTION(SET_TP_DST,
7048 			sizeof(struct rte_flow_action_set_tp)),
7049 		.next = NEXT(action_set_tp_dst),
7050 		.call = parse_vc,
7051 	},
7052 	[ACTION_SET_TP_DST_TP_DST] = {
7053 		.name = "port",
7054 		.help = "new destination port number to set",
7055 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7056 		.args = ARGS(ARGS_ENTRY_HTON
7057 			     (struct rte_flow_action_set_tp, port)),
7058 		.call = parse_vc_conf,
7059 	},
7060 	[ACTION_MAC_SWAP] = {
7061 		.name = "mac_swap",
7062 		.help = "Swap the source and destination MAC addresses"
7063 			" in the outermost Ethernet header",
7064 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7065 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7066 		.call = parse_vc,
7067 	},
7068 	[ACTION_DEC_TTL] = {
7069 		.name = "dec_ttl",
7070 		.help = "decrease network TTL if available",
7071 		.priv = PRIV_ACTION(DEC_TTL, 0),
7072 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7073 		.call = parse_vc,
7074 	},
7075 	[ACTION_SET_TTL] = {
7076 		.name = "set_ttl",
7077 		.help = "set ttl value",
7078 		.priv = PRIV_ACTION(SET_TTL,
7079 			sizeof(struct rte_flow_action_set_ttl)),
7080 		.next = NEXT(action_set_ttl),
7081 		.call = parse_vc,
7082 	},
7083 	[ACTION_SET_TTL_TTL] = {
7084 		.name = "ttl_value",
7085 		.help = "new ttl value to set",
7086 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7087 		.args = ARGS(ARGS_ENTRY_HTON
7088 			     (struct rte_flow_action_set_ttl, ttl_value)),
7089 		.call = parse_vc_conf,
7090 	},
7091 	[ACTION_SET_MAC_SRC] = {
7092 		.name = "set_mac_src",
7093 		.help = "set source mac address",
7094 		.priv = PRIV_ACTION(SET_MAC_SRC,
7095 			sizeof(struct rte_flow_action_set_mac)),
7096 		.next = NEXT(action_set_mac_src),
7097 		.call = parse_vc,
7098 	},
7099 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7100 		.name = "mac_addr",
7101 		.help = "new source mac address",
7102 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7103 		.args = ARGS(ARGS_ENTRY_HTON
7104 			     (struct rte_flow_action_set_mac, mac_addr)),
7105 		.call = parse_vc_conf,
7106 	},
7107 	[ACTION_SET_MAC_DST] = {
7108 		.name = "set_mac_dst",
7109 		.help = "set destination mac address",
7110 		.priv = PRIV_ACTION(SET_MAC_DST,
7111 			sizeof(struct rte_flow_action_set_mac)),
7112 		.next = NEXT(action_set_mac_dst),
7113 		.call = parse_vc,
7114 	},
7115 	[ACTION_SET_MAC_DST_MAC_DST] = {
7116 		.name = "mac_addr",
7117 		.help = "new destination mac address to set",
7118 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7119 		.args = ARGS(ARGS_ENTRY_HTON
7120 			     (struct rte_flow_action_set_mac, mac_addr)),
7121 		.call = parse_vc_conf,
7122 	},
7123 	[ACTION_INC_TCP_SEQ] = {
7124 		.name = "inc_tcp_seq",
7125 		.help = "increase TCP sequence number",
7126 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7127 		.next = NEXT(action_inc_tcp_seq),
7128 		.call = parse_vc,
7129 	},
7130 	[ACTION_INC_TCP_SEQ_VALUE] = {
7131 		.name = "value",
7132 		.help = "the value to increase TCP sequence number by",
7133 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7134 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7135 		.call = parse_vc_conf,
7136 	},
7137 	[ACTION_DEC_TCP_SEQ] = {
7138 		.name = "dec_tcp_seq",
7139 		.help = "decrease TCP sequence number",
7140 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7141 		.next = NEXT(action_dec_tcp_seq),
7142 		.call = parse_vc,
7143 	},
7144 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7145 		.name = "value",
7146 		.help = "the value to decrease TCP sequence number by",
7147 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7148 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7149 		.call = parse_vc_conf,
7150 	},
7151 	[ACTION_INC_TCP_ACK] = {
7152 		.name = "inc_tcp_ack",
7153 		.help = "increase TCP acknowledgment number",
7154 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7155 		.next = NEXT(action_inc_tcp_ack),
7156 		.call = parse_vc,
7157 	},
7158 	[ACTION_INC_TCP_ACK_VALUE] = {
7159 		.name = "value",
7160 		.help = "the value to increase TCP acknowledgment number by",
7161 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7162 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7163 		.call = parse_vc_conf,
7164 	},
7165 	[ACTION_DEC_TCP_ACK] = {
7166 		.name = "dec_tcp_ack",
7167 		.help = "decrease TCP acknowledgment number",
7168 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7169 		.next = NEXT(action_dec_tcp_ack),
7170 		.call = parse_vc,
7171 	},
7172 	[ACTION_DEC_TCP_ACK_VALUE] = {
7173 		.name = "value",
7174 		.help = "the value to decrease TCP acknowledgment number by",
7175 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7176 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7177 		.call = parse_vc_conf,
7178 	},
7179 	[ACTION_RAW_ENCAP] = {
7180 		.name = "raw_encap",
7181 		.help = "encapsulation data, defined by set raw_encap",
7182 		.priv = PRIV_ACTION(RAW_ENCAP,
7183 			sizeof(struct action_raw_encap_data)),
7184 		.next = NEXT(action_raw_encap),
7185 		.call = parse_vc_action_raw_encap,
7186 	},
7187 	[ACTION_RAW_ENCAP_SIZE] = {
7188 		.name = "size",
7189 		.help = "raw encap size",
7190 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7191 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7192 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7193 		.call = parse_vc_conf,
7194 	},
7195 	[ACTION_RAW_ENCAP_INDEX] = {
7196 		.name = "index",
7197 		.help = "the index of raw_encap_confs",
7198 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7199 	},
7200 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7201 		.name = "{index}",
7202 		.type = "UNSIGNED",
7203 		.help = "unsigned integer value",
7204 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7205 		.call = parse_vc_action_raw_encap_index,
7206 		.comp = comp_set_raw_index,
7207 	},
7208 	[ACTION_RAW_DECAP] = {
7209 		.name = "raw_decap",
7210 		.help = "decapsulation data, defined by set raw_encap",
7211 		.priv = PRIV_ACTION(RAW_DECAP,
7212 			sizeof(struct action_raw_decap_data)),
7213 		.next = NEXT(action_raw_decap),
7214 		.call = parse_vc_action_raw_decap,
7215 	},
7216 	[ACTION_RAW_DECAP_INDEX] = {
7217 		.name = "index",
7218 		.help = "the index of raw_encap_confs",
7219 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7220 	},
7221 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7222 		.name = "{index}",
7223 		.type = "UNSIGNED",
7224 		.help = "unsigned integer value",
7225 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7226 		.call = parse_vc_action_raw_decap_index,
7227 		.comp = comp_set_raw_index,
7228 	},
7229 	[ACTION_MODIFY_FIELD] = {
7230 		.name = "modify_field",
7231 		.help = "modify destination field with data from source field",
7232 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7233 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7234 		.call = parse_vc,
7235 	},
7236 	[ACTION_MODIFY_FIELD_OP] = {
7237 		.name = "op",
7238 		.help = "operation type",
7239 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7240 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7241 		.call = parse_vc_conf,
7242 	},
7243 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7244 		.name = "{operation}",
7245 		.help = "operation type value",
7246 		.call = parse_vc_modify_field_op,
7247 		.comp = comp_set_modify_field_op,
7248 	},
7249 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7250 		.name = "dst_type",
7251 		.help = "destination field type",
7252 		.next = NEXT(action_modify_field_dst,
7253 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7254 		.call = parse_vc_conf,
7255 	},
7256 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7257 		.name = "{dst_type}",
7258 		.help = "destination field type value",
7259 		.call = parse_vc_modify_field_id,
7260 		.comp = comp_set_modify_field_id,
7261 	},
7262 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7263 		.name = "dst_level",
7264 		.help = "destination field level",
7265 		.next = NEXT(action_modify_field_dst,
7266 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7267 		.call = parse_vc_conf,
7268 	},
7269 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7270 		.name = "{dst_level}",
7271 		.help = "destination field level value",
7272 		.call = parse_vc_modify_field_level,
7273 		.comp = comp_none,
7274 	},
7275 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7276 		.name = "dst_tag_index",
7277 		.help = "destination field tag array",
7278 		.next = NEXT(action_modify_field_dst,
7279 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7280 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7281 					dst.tag_index)),
7282 		.call = parse_vc_conf,
7283 	},
7284 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7285 		.name = "dst_type_id",
7286 		.help = "destination field type ID",
7287 		.next = NEXT(action_modify_field_dst,
7288 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7289 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7290 					dst.type)),
7291 		.call = parse_vc_conf,
7292 	},
7293 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7294 		.name = "dst_class",
7295 		.help = "destination field class ID",
7296 		.next = NEXT(action_modify_field_dst,
7297 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7298 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7299 					     dst.class_id)),
7300 		.call = parse_vc_conf,
7301 	},
7302 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7303 		.name = "dst_offset",
7304 		.help = "destination field bit offset",
7305 		.next = NEXT(action_modify_field_dst,
7306 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7307 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7308 					dst.offset)),
7309 		.call = parse_vc_conf,
7310 	},
7311 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7312 		.name = "src_type",
7313 		.help = "source field type",
7314 		.next = NEXT(action_modify_field_src,
7315 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7316 		.call = parse_vc_conf,
7317 	},
7318 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7319 		.name = "{src_type}",
7320 		.help = "source field type value",
7321 		.call = parse_vc_modify_field_id,
7322 		.comp = comp_set_modify_field_id,
7323 	},
7324 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7325 		.name = "src_level",
7326 		.help = "source field level",
7327 		.next = NEXT(action_modify_field_src,
7328 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7329 		.call = parse_vc_conf,
7330 	},
7331 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7332 		.name = "{src_level}",
7333 		.help = "source field level value",
7334 		.call = parse_vc_modify_field_level,
7335 		.comp = comp_none,
7336 	},
7337 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7338 		.name = "src_tag_index",
7339 		.help = "source field tag array",
7340 		.next = NEXT(action_modify_field_src,
7341 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7342 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7343 					src.tag_index)),
7344 		.call = parse_vc_conf,
7345 	},
7346 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7347 		.name = "src_type_id",
7348 		.help = "source field type ID",
7349 		.next = NEXT(action_modify_field_src,
7350 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7351 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7352 					src.type)),
7353 		.call = parse_vc_conf,
7354 	},
7355 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7356 		.name = "src_class",
7357 		.help = "source field class ID",
7358 		.next = NEXT(action_modify_field_src,
7359 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7360 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7361 					     src.class_id)),
7362 		.call = parse_vc_conf,
7363 	},
7364 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7365 		.name = "src_offset",
7366 		.help = "source field bit offset",
7367 		.next = NEXT(action_modify_field_src,
7368 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7369 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7370 					src.offset)),
7371 		.call = parse_vc_conf,
7372 	},
7373 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7374 		.name = "src_value",
7375 		.help = "source immediate value",
7376 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7377 			     NEXT_ENTRY(COMMON_HEX)),
7378 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7379 			     ARGS_ENTRY_ARB(0, 0),
7380 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7381 					src.value)),
7382 		.call = parse_vc_conf,
7383 	},
7384 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7385 		.name = "src_ptr",
7386 		.help = "pointer to source immediate value",
7387 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7388 			     NEXT_ENTRY(COMMON_HEX)),
7389 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7390 					src.pvalue),
7391 			     ARGS_ENTRY_ARB(0, 0),
7392 			     ARGS_ENTRY_ARB
7393 				(sizeof(struct rte_flow_action_modify_field),
7394 				 FLOW_FIELD_PATTERN_SIZE)),
7395 		.call = parse_vc_conf,
7396 	},
7397 	[ACTION_MODIFY_FIELD_WIDTH] = {
7398 		.name = "width",
7399 		.help = "number of bits to copy",
7400 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7401 			NEXT_ENTRY(COMMON_UNSIGNED)),
7402 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7403 					width)),
7404 		.call = parse_vc_conf,
7405 	},
7406 	[ACTION_SEND_TO_KERNEL] = {
7407 		.name = "send_to_kernel",
7408 		.help = "send packets to kernel",
7409 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7410 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7411 		.call = parse_vc,
7412 	},
7413 	[ACTION_IPV6_EXT_REMOVE] = {
7414 		.name = "ipv6_ext_remove",
7415 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7416 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7417 			sizeof(struct action_ipv6_ext_remove_data)),
7418 		.next = NEXT(action_ipv6_ext_remove),
7419 		.call = parse_vc_action_ipv6_ext_remove,
7420 	},
7421 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7422 		.name = "index",
7423 		.help = "the index of ipv6_ext_remove",
7424 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7425 	},
7426 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7427 		.name = "{index}",
7428 		.type = "UNSIGNED",
7429 		.help = "unsigned integer value",
7430 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7431 		.call = parse_vc_action_ipv6_ext_remove_index,
7432 		.comp = comp_set_ipv6_ext_index,
7433 	},
7434 	[ACTION_IPV6_EXT_PUSH] = {
7435 		.name = "ipv6_ext_push",
7436 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7437 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7438 			sizeof(struct action_ipv6_ext_push_data)),
7439 		.next = NEXT(action_ipv6_ext_push),
7440 		.call = parse_vc_action_ipv6_ext_push,
7441 	},
7442 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7443 		.name = "index",
7444 		.help = "the index of ipv6_ext_push",
7445 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7446 	},
7447 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7448 		.name = "{index}",
7449 		.type = "UNSIGNED",
7450 		.help = "unsigned integer value",
7451 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7452 		.call = parse_vc_action_ipv6_ext_push_index,
7453 		.comp = comp_set_ipv6_ext_index,
7454 	},
7455 	[ACTION_NAT64] = {
7456 		.name = "nat64",
7457 		.help = "NAT64 IP headers translation",
7458 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7459 		.next = NEXT(action_nat64),
7460 		.call = parse_vc,
7461 	},
7462 	[ACTION_NAT64_MODE] = {
7463 		.name = "type",
7464 		.help = "NAT64 translation type",
7465 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7466 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7467 		.call = parse_vc_conf,
7468 	},
7469 	/* Top level command. */
7470 	[SET] = {
7471 		.name = "set",
7472 		.help = "set raw encap/decap/sample data",
7473 		.type = "set raw_encap|raw_decap <index> <pattern>"
7474 				" or set sample_actions <index> <action>",
7475 		.next = NEXT(NEXT_ENTRY
7476 			     (SET_RAW_ENCAP,
7477 			      SET_RAW_DECAP,
7478 			      SET_SAMPLE_ACTIONS,
7479 			      SET_IPV6_EXT_REMOVE,
7480 			      SET_IPV6_EXT_PUSH)),
7481 		.call = parse_set_init,
7482 	},
7483 	/* Sub-level commands. */
7484 	[SET_RAW_ENCAP] = {
7485 		.name = "raw_encap",
7486 		.help = "set raw encap data",
7487 		.next = NEXT(next_set_raw),
7488 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7489 				(offsetof(struct buffer, port),
7490 				 sizeof(((struct buffer *)0)->port),
7491 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7492 		.call = parse_set_raw_encap_decap,
7493 	},
7494 	[SET_RAW_DECAP] = {
7495 		.name = "raw_decap",
7496 		.help = "set raw decap data",
7497 		.next = NEXT(next_set_raw),
7498 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7499 				(offsetof(struct buffer, port),
7500 				 sizeof(((struct buffer *)0)->port),
7501 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7502 		.call = parse_set_raw_encap_decap,
7503 	},
7504 	[SET_RAW_INDEX] = {
7505 		.name = "{index}",
7506 		.type = "COMMON_UNSIGNED",
7507 		.help = "index of raw_encap/raw_decap data",
7508 		.next = NEXT(next_item),
7509 		.call = parse_port,
7510 	},
7511 	[SET_SAMPLE_INDEX] = {
7512 		.name = "{index}",
7513 		.type = "UNSIGNED",
7514 		.help = "index of sample actions",
7515 		.next = NEXT(next_action_sample),
7516 		.call = parse_port,
7517 	},
7518 	[SET_SAMPLE_ACTIONS] = {
7519 		.name = "sample_actions",
7520 		.help = "set sample actions list",
7521 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7522 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7523 				(offsetof(struct buffer, port),
7524 				 sizeof(((struct buffer *)0)->port),
7525 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7526 		.call = parse_set_sample_action,
7527 	},
7528 	[SET_IPV6_EXT_PUSH] = {
7529 		.name = "ipv6_ext_push",
7530 		.help = "set IPv6 extension header",
7531 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7532 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7533 				(offsetof(struct buffer, port),
7534 				 sizeof(((struct buffer *)0)->port),
7535 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7536 		.call = parse_set_ipv6_ext_action,
7537 	},
7538 	[SET_IPV6_EXT_REMOVE] = {
7539 		.name = "ipv6_ext_remove",
7540 		.help = "set IPv6 extension header",
7541 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7542 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7543 				(offsetof(struct buffer, port),
7544 				 sizeof(((struct buffer *)0)->port),
7545 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7546 		.call = parse_set_ipv6_ext_action,
7547 	},
7548 	[SET_IPV6_EXT_INDEX] = {
7549 		.name = "{index}",
7550 		.type = "UNSIGNED",
7551 		.help = "index of ipv6 extension push/remove actions",
7552 		.next = NEXT(item_ipv6_push_ext),
7553 		.call = parse_port,
7554 	},
7555 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7556 		.name = "ipv6_ext",
7557 		.help = "set IPv6 extension header",
7558 		.priv = PRIV_ITEM(IPV6_EXT,
7559 				  sizeof(struct rte_flow_item_ipv6_ext)),
7560 		.next = NEXT(item_ipv6_push_ext_type),
7561 		.call = parse_vc,
7562 	},
7563 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7564 		.name = "type",
7565 		.help = "set IPv6 extension type",
7566 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7567 					     next_hdr)),
7568 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7569 			     item_param),
7570 	},
7571 	[ACTION_SET_TAG] = {
7572 		.name = "set_tag",
7573 		.help = "set tag",
7574 		.priv = PRIV_ACTION(SET_TAG,
7575 			sizeof(struct rte_flow_action_set_tag)),
7576 		.next = NEXT(action_set_tag),
7577 		.call = parse_vc,
7578 	},
7579 	[ACTION_SET_TAG_INDEX] = {
7580 		.name = "index",
7581 		.help = "index of tag array",
7582 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7583 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7584 		.call = parse_vc_conf,
7585 	},
7586 	[ACTION_SET_TAG_DATA] = {
7587 		.name = "data",
7588 		.help = "tag value",
7589 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7590 		.args = ARGS(ARGS_ENTRY
7591 			     (struct rte_flow_action_set_tag, data)),
7592 		.call = parse_vc_conf,
7593 	},
7594 	[ACTION_SET_TAG_MASK] = {
7595 		.name = "mask",
7596 		.help = "mask for tag value",
7597 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7598 		.args = ARGS(ARGS_ENTRY
7599 			     (struct rte_flow_action_set_tag, mask)),
7600 		.call = parse_vc_conf,
7601 	},
7602 	[ACTION_SET_META] = {
7603 		.name = "set_meta",
7604 		.help = "set metadata",
7605 		.priv = PRIV_ACTION(SET_META,
7606 			sizeof(struct rte_flow_action_set_meta)),
7607 		.next = NEXT(action_set_meta),
7608 		.call = parse_vc_action_set_meta,
7609 	},
7610 	[ACTION_SET_META_DATA] = {
7611 		.name = "data",
7612 		.help = "metadata value",
7613 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7614 		.args = ARGS(ARGS_ENTRY
7615 			     (struct rte_flow_action_set_meta, data)),
7616 		.call = parse_vc_conf,
7617 	},
7618 	[ACTION_SET_META_MASK] = {
7619 		.name = "mask",
7620 		.help = "mask for metadata value",
7621 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7622 		.args = ARGS(ARGS_ENTRY
7623 			     (struct rte_flow_action_set_meta, mask)),
7624 		.call = parse_vc_conf,
7625 	},
7626 	[ACTION_SET_IPV4_DSCP] = {
7627 		.name = "set_ipv4_dscp",
7628 		.help = "set DSCP value",
7629 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7630 			sizeof(struct rte_flow_action_set_dscp)),
7631 		.next = NEXT(action_set_ipv4_dscp),
7632 		.call = parse_vc,
7633 	},
7634 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7635 		.name = "dscp_value",
7636 		.help = "new IPv4 DSCP value to set",
7637 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7638 		.args = ARGS(ARGS_ENTRY
7639 			     (struct rte_flow_action_set_dscp, dscp)),
7640 		.call = parse_vc_conf,
7641 	},
7642 	[ACTION_SET_IPV6_DSCP] = {
7643 		.name = "set_ipv6_dscp",
7644 		.help = "set DSCP value",
7645 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7646 			sizeof(struct rte_flow_action_set_dscp)),
7647 		.next = NEXT(action_set_ipv6_dscp),
7648 		.call = parse_vc,
7649 	},
7650 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7651 		.name = "dscp_value",
7652 		.help = "new IPv6 DSCP value to set",
7653 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7654 		.args = ARGS(ARGS_ENTRY
7655 			     (struct rte_flow_action_set_dscp, dscp)),
7656 		.call = parse_vc_conf,
7657 	},
7658 	[ACTION_AGE] = {
7659 		.name = "age",
7660 		.help = "set a specific metadata header",
7661 		.next = NEXT(action_age),
7662 		.priv = PRIV_ACTION(AGE,
7663 			sizeof(struct rte_flow_action_age)),
7664 		.call = parse_vc,
7665 	},
7666 	[ACTION_AGE_TIMEOUT] = {
7667 		.name = "timeout",
7668 		.help = "flow age timeout value",
7669 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7670 					   timeout, 24)),
7671 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7672 		.call = parse_vc_conf,
7673 	},
7674 	[ACTION_AGE_UPDATE] = {
7675 		.name = "age_update",
7676 		.help = "update aging parameter",
7677 		.next = NEXT(action_age_update),
7678 		.priv = PRIV_ACTION(AGE,
7679 				    sizeof(struct rte_flow_update_age)),
7680 		.call = parse_vc,
7681 	},
7682 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7683 		.name = "timeout",
7684 		.help = "age timeout update value",
7685 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7686 					   timeout, 24)),
7687 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7688 		.call = parse_vc_conf_timeout,
7689 	},
7690 	[ACTION_AGE_UPDATE_TOUCH] = {
7691 		.name = "touch",
7692 		.help = "this flow is touched",
7693 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7694 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7695 					   touch, 1)),
7696 		.call = parse_vc_conf,
7697 	},
7698 	[ACTION_SAMPLE] = {
7699 		.name = "sample",
7700 		.help = "set a sample action",
7701 		.next = NEXT(action_sample),
7702 		.priv = PRIV_ACTION(SAMPLE,
7703 			sizeof(struct action_sample_data)),
7704 		.call = parse_vc_action_sample,
7705 	},
7706 	[ACTION_SAMPLE_RATIO] = {
7707 		.name = "ratio",
7708 		.help = "flow sample ratio value",
7709 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7710 		.args = ARGS(ARGS_ENTRY_ARB
7711 			     (offsetof(struct action_sample_data, conf) +
7712 			      offsetof(struct rte_flow_action_sample, ratio),
7713 			      sizeof(((struct rte_flow_action_sample *)0)->
7714 				     ratio))),
7715 	},
7716 	[ACTION_SAMPLE_INDEX] = {
7717 		.name = "index",
7718 		.help = "the index of sample actions list",
7719 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7720 	},
7721 	[ACTION_SAMPLE_INDEX_VALUE] = {
7722 		.name = "{index}",
7723 		.type = "COMMON_UNSIGNED",
7724 		.help = "unsigned integer value",
7725 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7726 		.call = parse_vc_action_sample_index,
7727 		.comp = comp_set_sample_index,
7728 	},
7729 	[ACTION_CONNTRACK] = {
7730 		.name = "conntrack",
7731 		.help = "create a conntrack object",
7732 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7733 		.priv = PRIV_ACTION(CONNTRACK,
7734 				    sizeof(struct rte_flow_action_conntrack)),
7735 		.call = parse_vc,
7736 	},
7737 	[ACTION_CONNTRACK_UPDATE] = {
7738 		.name = "conntrack_update",
7739 		.help = "update a conntrack object",
7740 		.next = NEXT(action_update_conntrack),
7741 		.priv = PRIV_ACTION(CONNTRACK,
7742 				    sizeof(struct rte_flow_modify_conntrack)),
7743 		.call = parse_vc,
7744 	},
7745 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7746 		.name = "dir",
7747 		.help = "update a conntrack object direction",
7748 		.next = NEXT(action_update_conntrack),
7749 		.call = parse_vc_action_conntrack_update,
7750 	},
7751 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7752 		.name = "ctx",
7753 		.help = "update a conntrack object context",
7754 		.next = NEXT(action_update_conntrack),
7755 		.call = parse_vc_action_conntrack_update,
7756 	},
7757 	[ACTION_PORT_REPRESENTOR] = {
7758 		.name = "port_representor",
7759 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7760 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7761 				    sizeof(struct rte_flow_action_ethdev)),
7762 		.next = NEXT(action_port_representor),
7763 		.call = parse_vc,
7764 	},
7765 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7766 		.name = "port_id",
7767 		.help = "ethdev port ID",
7768 		.next = NEXT(action_port_representor,
7769 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7770 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7771 					port_id)),
7772 		.call = parse_vc_conf,
7773 	},
7774 	[ACTION_REPRESENTED_PORT] = {
7775 		.name = "represented_port",
7776 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7777 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7778 				sizeof(struct rte_flow_action_ethdev)),
7779 		.next = NEXT(action_represented_port),
7780 		.call = parse_vc,
7781 	},
7782 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7783 		.name = "ethdev_port_id",
7784 		.help = "ethdev port ID",
7785 		.next = NEXT(action_represented_port,
7786 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7787 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7788 					port_id)),
7789 		.call = parse_vc_conf,
7790 	},
7791 	/* Indirect action destroy arguments. */
7792 	[INDIRECT_ACTION_DESTROY_ID] = {
7793 		.name = "action_id",
7794 		.help = "specify a indirect action id to destroy",
7795 		.next = NEXT(next_ia_destroy_attr,
7796 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7797 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7798 					    args.ia_destroy.action_id)),
7799 		.call = parse_ia_destroy,
7800 	},
7801 	/* Indirect action create arguments. */
7802 	[INDIRECT_ACTION_CREATE_ID] = {
7803 		.name = "action_id",
7804 		.help = "specify a indirect action id to create",
7805 		.next = NEXT(next_ia_create_attr,
7806 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7807 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7808 	},
7809 	[ACTION_INDIRECT] = {
7810 		.name = "indirect",
7811 		.help = "apply indirect action by id",
7812 		.priv = PRIV_ACTION(INDIRECT, 0),
7813 		.next = NEXT(next_ia),
7814 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7815 		.call = parse_vc,
7816 	},
7817 	[ACTION_INDIRECT_LIST] = {
7818 		.name = "indirect_list",
7819 		.help = "apply indirect list action by id",
7820 		.priv = PRIV_ACTION(INDIRECT_LIST,
7821 				    sizeof(struct
7822 					   rte_flow_action_indirect_list)),
7823 		.next = NEXT(next_ial),
7824 		.call = parse_vc,
7825 	},
7826 	[ACTION_INDIRECT_LIST_HANDLE] = {
7827 		.name = "handle",
7828 		.help = "indirect list handle",
7829 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7830 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7831 	},
7832 	[ACTION_INDIRECT_LIST_CONF] = {
7833 		.name = "conf",
7834 		.help = "indirect list configuration",
7835 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
7836 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7837 	},
7838 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
7839 		.type = "UNSIGNED",
7840 		.help = "unsigned integer value",
7841 		.call = parse_indlst_id2ptr,
7842 	},
7843 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
7844 		.type = "UNSIGNED",
7845 		.help = "unsigned integer value",
7846 		.call = parse_indlst_id2ptr,
7847 	},
7848 	[ACTION_SHARED_INDIRECT] = {
7849 		.name = "shared_indirect",
7850 		.help = "apply indirect action by id and port",
7851 		.priv = PRIV_ACTION(INDIRECT, 0),
7852 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
7853 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
7854 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7855 		.call = parse_vc,
7856 	},
7857 	[INDIRECT_ACTION_PORT] = {
7858 		.name = "{indirect_action_port}",
7859 		.type = "INDIRECT_ACTION_PORT",
7860 		.help = "indirect action port",
7861 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
7862 		.call = parse_ia_port,
7863 		.comp = comp_none,
7864 	},
7865 	[INDIRECT_ACTION_ID2PTR] = {
7866 		.name = "{action_id}",
7867 		.type = "INDIRECT_ACTION_ID",
7868 		.help = "indirect action id",
7869 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7870 		.call = parse_ia_id2ptr,
7871 		.comp = comp_none,
7872 	},
7873 	[INDIRECT_ACTION_INGRESS] = {
7874 		.name = "ingress",
7875 		.help = "affect rule to ingress",
7876 		.next = NEXT(next_ia_create_attr),
7877 		.call = parse_ia,
7878 	},
7879 	[INDIRECT_ACTION_EGRESS] = {
7880 		.name = "egress",
7881 		.help = "affect rule to egress",
7882 		.next = NEXT(next_ia_create_attr),
7883 		.call = parse_ia,
7884 	},
7885 	[INDIRECT_ACTION_TRANSFER] = {
7886 		.name = "transfer",
7887 		.help = "affect rule to transfer",
7888 		.next = NEXT(next_ia_create_attr),
7889 		.call = parse_ia,
7890 	},
7891 	[INDIRECT_ACTION_SPEC] = {
7892 		.name = "action",
7893 		.help = "specify action to create indirect handle",
7894 		.next = NEXT(next_action),
7895 	},
7896 	[INDIRECT_ACTION_LIST] = {
7897 		.name = "list",
7898 		.help = "specify actions for indirect handle list",
7899 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7900 		.call = parse_ia,
7901 	},
7902 	[INDIRECT_ACTION_FLOW_CONF] = {
7903 		.name = "flow_conf",
7904 		.help = "specify actions configuration for indirect handle list",
7905 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
7906 		.call = parse_ia,
7907 	},
7908 	[ACTION_POL_G] = {
7909 		.name = "g_actions",
7910 		.help = "submit a list of associated actions for green",
7911 		.next = NEXT(next_action),
7912 		.call = parse_mp,
7913 	},
7914 	[ACTION_POL_Y] = {
7915 		.name = "y_actions",
7916 		.help = "submit a list of associated actions for yellow",
7917 		.next = NEXT(next_action),
7918 	},
7919 	[ACTION_POL_R] = {
7920 		.name = "r_actions",
7921 		.help = "submit a list of associated actions for red",
7922 		.next = NEXT(next_action),
7923 	},
7924 	[ACTION_QUOTA_CREATE] = {
7925 		.name = "quota_create",
7926 		.help = "create quota action",
7927 		.priv = PRIV_ACTION(QUOTA,
7928 				    sizeof(struct rte_flow_action_quota)),
7929 		.next = NEXT(action_quota_create),
7930 		.call = parse_vc
7931 	},
7932 	[ACTION_QUOTA_CREATE_LIMIT] = {
7933 		.name = "limit",
7934 		.help = "quota limit",
7935 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
7936 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
7937 		.call = parse_vc_conf
7938 	},
7939 	[ACTION_QUOTA_CREATE_MODE] = {
7940 		.name = "mode",
7941 		.help = "quota mode",
7942 		.next = NEXT(action_quota_create,
7943 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
7944 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
7945 		.call = parse_vc_conf
7946 	},
7947 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
7948 		.name = "mode_name",
7949 		.help = "quota mode name",
7950 		.call = parse_quota_mode_name,
7951 		.comp = comp_quota_mode_name
7952 	},
7953 	[ACTION_QUOTA_QU] = {
7954 		.name = "quota_update",
7955 		.help = "update quota action",
7956 		.priv = PRIV_ACTION(QUOTA,
7957 				    sizeof(struct rte_flow_update_quota)),
7958 		.next = NEXT(action_quota_update),
7959 		.call = parse_vc
7960 	},
7961 	[ACTION_QUOTA_QU_LIMIT] = {
7962 		.name = "limit",
7963 		.help = "quota limit",
7964 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7965 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
7966 		.call = parse_vc_conf
7967 	},
7968 	[ACTION_QUOTA_QU_UPDATE_OP] = {
7969 		.name = "update_op",
7970 		.help = "query update op SET|ADD",
7971 		.next = NEXT(action_quota_update,
7972 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
7973 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
7974 		.call = parse_vc_conf
7975 	},
7976 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
7977 		.name = "update_op_name",
7978 		.help = "quota update op name",
7979 		.call = parse_quota_update_name,
7980 		.comp = comp_quota_update_name
7981 	},
7982 
7983 	/* Top-level command. */
7984 	[ADD] = {
7985 		.name = "add",
7986 		.type = "port meter policy {port_id} {arg}",
7987 		.help = "add port meter policy",
7988 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
7989 		.call = parse_init,
7990 	},
7991 	/* Sub-level commands. */
7992 	[ITEM_POL_PORT] = {
7993 		.name = "port",
7994 		.help = "add port meter policy",
7995 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
7996 	},
7997 	[ITEM_POL_METER] = {
7998 		.name = "meter",
7999 		.help = "add port meter policy",
8000 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8001 	},
8002 	[ITEM_POL_POLICY] = {
8003 		.name = "policy",
8004 		.help = "add port meter policy",
8005 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8006 				NEXT_ENTRY(ACTION_POL_Y),
8007 				NEXT_ENTRY(ACTION_POL_G),
8008 				NEXT_ENTRY(COMMON_POLICY_ID),
8009 				NEXT_ENTRY(COMMON_PORT_ID)),
8010 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8011 				ARGS_ENTRY(struct buffer, port)),
8012 		.call = parse_mp,
8013 	},
8014 	[ITEM_AGGR_AFFINITY] = {
8015 		.name = "aggr_affinity",
8016 		.help = "match on the aggregated port receiving the packets",
8017 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8018 				  sizeof(struct rte_flow_item_aggr_affinity)),
8019 		.next = NEXT(item_aggr_affinity),
8020 		.call = parse_vc,
8021 	},
8022 	[ITEM_AGGR_AFFINITY_VALUE] = {
8023 		.name = "affinity",
8024 		.help = "aggregated affinity value",
8025 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8026 			     item_param),
8027 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8028 					affinity)),
8029 	},
8030 	[ITEM_TX_QUEUE] = {
8031 		.name = "tx_queue",
8032 		.help = "match on the tx queue of send packet",
8033 		.priv = PRIV_ITEM(TX_QUEUE,
8034 				  sizeof(struct rte_flow_item_tx_queue)),
8035 		.next = NEXT(item_tx_queue),
8036 		.call = parse_vc,
8037 	},
8038 	[ITEM_TX_QUEUE_VALUE] = {
8039 		.name = "tx_queue_value",
8040 		.help = "tx queue value",
8041 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8042 			     item_param),
8043 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8044 					tx_queue)),
8045 	},
8046 };
8047 
8048 /** Remove and return last entry from argument stack. */
8049 static const struct arg *
8050 pop_args(struct context *ctx)
8051 {
8052 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8053 }
8054 
8055 /** Add entry on top of the argument stack. */
8056 static int
8057 push_args(struct context *ctx, const struct arg *arg)
8058 {
8059 	if (ctx->args_num == CTX_STACK_SIZE)
8060 		return -1;
8061 	ctx->args[ctx->args_num++] = arg;
8062 	return 0;
8063 }
8064 
8065 /** Spread value into buffer according to bit-mask. */
8066 static size_t
8067 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8068 {
8069 	uint32_t i = arg->size;
8070 	uint32_t end = 0;
8071 	int sub = 1;
8072 	int add = 0;
8073 	size_t len = 0;
8074 
8075 	if (!arg->mask)
8076 		return 0;
8077 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8078 	if (!arg->hton) {
8079 		i = 0;
8080 		end = arg->size;
8081 		sub = 0;
8082 		add = 1;
8083 	}
8084 #endif
8085 	while (i != end) {
8086 		unsigned int shift = 0;
8087 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8088 
8089 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8090 			if (!(arg->mask[i] & (1 << shift)))
8091 				continue;
8092 			++len;
8093 			if (!dst)
8094 				continue;
8095 			*buf &= ~(1 << shift);
8096 			*buf |= (val & 1) << shift;
8097 			val >>= 1;
8098 		}
8099 		i += add;
8100 	}
8101 	return len;
8102 }
8103 
8104 /** Compare a string with a partial one of a given length. */
8105 static int
8106 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8107 {
8108 	int r = strncmp(full, partial, partial_len);
8109 
8110 	if (r)
8111 		return r;
8112 	if (strlen(full) <= partial_len)
8113 		return 0;
8114 	return full[partial_len];
8115 }
8116 
8117 /**
8118  * Parse a prefix length and generate a bit-mask.
8119  *
8120  * Last argument (ctx->args) is retrieved to determine mask size, storage
8121  * location and whether the result must use network byte ordering.
8122  */
8123 static int
8124 parse_prefix(struct context *ctx, const struct token *token,
8125 	     const char *str, unsigned int len,
8126 	     void *buf, unsigned int size)
8127 {
8128 	const struct arg *arg = pop_args(ctx);
8129 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
8130 	char *end;
8131 	uintmax_t u;
8132 	unsigned int bytes;
8133 	unsigned int extra;
8134 
8135 	(void)token;
8136 	/* Argument is expected. */
8137 	if (!arg)
8138 		return -1;
8139 	errno = 0;
8140 	u = strtoumax(str, &end, 0);
8141 	if (errno || (size_t)(end - str) != len)
8142 		goto error;
8143 	if (arg->mask) {
8144 		uintmax_t v = 0;
8145 
8146 		extra = arg_entry_bf_fill(NULL, 0, arg);
8147 		if (u > extra)
8148 			goto error;
8149 		if (!ctx->object)
8150 			return len;
8151 		extra -= u;
8152 		while (u--)
8153 			(v <<= 1, v |= 1);
8154 		v <<= extra;
8155 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8156 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8157 			goto error;
8158 		return len;
8159 	}
8160 	bytes = u / 8;
8161 	extra = u % 8;
8162 	size = arg->size;
8163 	if (bytes > size || bytes + !!extra > size)
8164 		goto error;
8165 	if (!ctx->object)
8166 		return len;
8167 	buf = (uint8_t *)ctx->object + arg->offset;
8168 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8169 	if (!arg->hton) {
8170 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8171 		memset(buf, 0x00, size - bytes);
8172 		if (extra)
8173 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8174 	} else
8175 #endif
8176 	{
8177 		memset(buf, 0xff, bytes);
8178 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8179 		if (extra)
8180 			((uint8_t *)buf)[bytes] = conv[extra];
8181 	}
8182 	if (ctx->objmask)
8183 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8184 	return len;
8185 error:
8186 	push_args(ctx, arg);
8187 	return -1;
8188 }
8189 
8190 /** Default parsing function for token name matching. */
8191 static int
8192 parse_default(struct context *ctx, const struct token *token,
8193 	      const char *str, unsigned int len,
8194 	      void *buf, unsigned int size)
8195 {
8196 	(void)ctx;
8197 	(void)buf;
8198 	(void)size;
8199 	if (strcmp_partial(token->name, str, len))
8200 		return -1;
8201 	return len;
8202 }
8203 
8204 /** Parse flow command, initialize output buffer for subsequent tokens. */
8205 static int
8206 parse_init(struct context *ctx, const struct token *token,
8207 	   const char *str, unsigned int len,
8208 	   void *buf, unsigned int size)
8209 {
8210 	struct buffer *out = buf;
8211 
8212 	/* Token name must match. */
8213 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8214 		return -1;
8215 	/* Nothing else to do if there is no buffer. */
8216 	if (!out)
8217 		return len;
8218 	/* Make sure buffer is large enough. */
8219 	if (size < sizeof(*out))
8220 		return -1;
8221 	/* Initialize buffer. */
8222 	memset(out, 0x00, sizeof(*out));
8223 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8224 	ctx->objdata = 0;
8225 	ctx->object = out;
8226 	ctx->objmask = NULL;
8227 	return len;
8228 }
8229 
8230 /** Parse tokens for indirect action commands. */
8231 static int
8232 parse_ia(struct context *ctx, const struct token *token,
8233 	 const char *str, unsigned int len,
8234 	 void *buf, unsigned int size)
8235 {
8236 	struct buffer *out = buf;
8237 
8238 	/* Token name must match. */
8239 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8240 		return -1;
8241 	/* Nothing else to do if there is no buffer. */
8242 	if (!out)
8243 		return len;
8244 	if (!out->command) {
8245 		if (ctx->curr != INDIRECT_ACTION)
8246 			return -1;
8247 		if (sizeof(*out) > size)
8248 			return -1;
8249 		out->command = ctx->curr;
8250 		ctx->objdata = 0;
8251 		ctx->object = out;
8252 		ctx->objmask = NULL;
8253 		out->args.vc.data = (uint8_t *)out + size;
8254 		return len;
8255 	}
8256 	switch (ctx->curr) {
8257 	case INDIRECT_ACTION_CREATE:
8258 	case INDIRECT_ACTION_UPDATE:
8259 	case INDIRECT_ACTION_QUERY_UPDATE:
8260 		out->args.vc.actions =
8261 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8262 					       sizeof(double));
8263 		out->args.vc.attr.group = UINT32_MAX;
8264 		/* fallthrough */
8265 	case INDIRECT_ACTION_QUERY:
8266 		out->command = ctx->curr;
8267 		ctx->objdata = 0;
8268 		ctx->object = out;
8269 		ctx->objmask = NULL;
8270 		return len;
8271 	case INDIRECT_ACTION_EGRESS:
8272 		out->args.vc.attr.egress = 1;
8273 		return len;
8274 	case INDIRECT_ACTION_INGRESS:
8275 		out->args.vc.attr.ingress = 1;
8276 		return len;
8277 	case INDIRECT_ACTION_TRANSFER:
8278 		out->args.vc.attr.transfer = 1;
8279 		return len;
8280 	case INDIRECT_ACTION_QU_MODE:
8281 		return len;
8282 	case INDIRECT_ACTION_LIST:
8283 		out->command = INDIRECT_ACTION_LIST_CREATE;
8284 		return len;
8285 	case INDIRECT_ACTION_FLOW_CONF:
8286 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8287 		return len;
8288 	default:
8289 		return -1;
8290 	}
8291 }
8292 
8293 
8294 /** Parse tokens for indirect action destroy command. */
8295 static int
8296 parse_ia_destroy(struct context *ctx, const struct token *token,
8297 		 const char *str, unsigned int len,
8298 		 void *buf, unsigned int size)
8299 {
8300 	struct buffer *out = buf;
8301 	uint32_t *action_id;
8302 
8303 	/* Token name must match. */
8304 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8305 		return -1;
8306 	/* Nothing else to do if there is no buffer. */
8307 	if (!out)
8308 		return len;
8309 	if (!out->command || out->command == INDIRECT_ACTION) {
8310 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8311 			return -1;
8312 		if (sizeof(*out) > size)
8313 			return -1;
8314 		out->command = ctx->curr;
8315 		ctx->objdata = 0;
8316 		ctx->object = out;
8317 		ctx->objmask = NULL;
8318 		out->args.ia_destroy.action_id =
8319 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8320 					       sizeof(double));
8321 		return len;
8322 	}
8323 	action_id = out->args.ia_destroy.action_id
8324 		    + out->args.ia_destroy.action_id_n++;
8325 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8326 		return -1;
8327 	ctx->objdata = 0;
8328 	ctx->object = action_id;
8329 	ctx->objmask = NULL;
8330 	return len;
8331 }
8332 
8333 /** Parse tokens for indirect action commands. */
8334 static int
8335 parse_qia(struct context *ctx, const struct token *token,
8336 	  const char *str, unsigned int len,
8337 	  void *buf, unsigned int size)
8338 {
8339 	struct buffer *out = buf;
8340 
8341 	/* Token name must match. */
8342 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8343 		return -1;
8344 	/* Nothing else to do if there is no buffer. */
8345 	if (!out)
8346 		return len;
8347 	if (!out->command) {
8348 		if (ctx->curr != QUEUE)
8349 			return -1;
8350 		if (sizeof(*out) > size)
8351 			return -1;
8352 		out->args.vc.data = (uint8_t *)out + size;
8353 		return len;
8354 	}
8355 	switch (ctx->curr) {
8356 	case QUEUE_INDIRECT_ACTION:
8357 		return len;
8358 	case QUEUE_INDIRECT_ACTION_CREATE:
8359 	case QUEUE_INDIRECT_ACTION_UPDATE:
8360 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8361 		out->args.vc.actions =
8362 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8363 					       sizeof(double));
8364 		out->args.vc.attr.group = UINT32_MAX;
8365 		/* fallthrough */
8366 	case QUEUE_INDIRECT_ACTION_QUERY:
8367 		out->command = ctx->curr;
8368 		ctx->objdata = 0;
8369 		ctx->object = out;
8370 		ctx->objmask = NULL;
8371 		return len;
8372 	case QUEUE_INDIRECT_ACTION_EGRESS:
8373 		out->args.vc.attr.egress = 1;
8374 		return len;
8375 	case QUEUE_INDIRECT_ACTION_INGRESS:
8376 		out->args.vc.attr.ingress = 1;
8377 		return len;
8378 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8379 		out->args.vc.attr.transfer = 1;
8380 		return len;
8381 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8382 		return len;
8383 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8384 		return len;
8385 	case QUEUE_INDIRECT_ACTION_LIST:
8386 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8387 		return len;
8388 	default:
8389 		return -1;
8390 	}
8391 }
8392 
8393 /** Parse tokens for indirect action destroy command. */
8394 static int
8395 parse_qia_destroy(struct context *ctx, const struct token *token,
8396 		  const char *str, unsigned int len,
8397 		  void *buf, unsigned int size)
8398 {
8399 	struct buffer *out = buf;
8400 	uint32_t *action_id;
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 || out->command == QUEUE) {
8409 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
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.ia_destroy.action_id =
8418 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8419 					       sizeof(double));
8420 		return len;
8421 	}
8422 	switch (ctx->curr) {
8423 	case QUEUE_INDIRECT_ACTION:
8424 		out->command = ctx->curr;
8425 		ctx->objdata = 0;
8426 		ctx->object = out;
8427 		ctx->objmask = NULL;
8428 		return len;
8429 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8430 		action_id = out->args.ia_destroy.action_id
8431 				+ out->args.ia_destroy.action_id_n++;
8432 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8433 			return -1;
8434 		ctx->objdata = 0;
8435 		ctx->object = action_id;
8436 		ctx->objmask = NULL;
8437 		return len;
8438 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8439 		return len;
8440 	default:
8441 		return -1;
8442 	}
8443 }
8444 
8445 /** Parse tokens for meter policy action commands. */
8446 static int
8447 parse_mp(struct context *ctx, const struct token *token,
8448 	const char *str, unsigned int len,
8449 	void *buf, unsigned int size)
8450 {
8451 	struct buffer *out = buf;
8452 
8453 	/* Token name must match. */
8454 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8455 		return -1;
8456 	/* Nothing else to do if there is no buffer. */
8457 	if (!out)
8458 		return len;
8459 	if (!out->command) {
8460 		if (ctx->curr != ITEM_POL_POLICY)
8461 			return -1;
8462 		if (sizeof(*out) > size)
8463 			return -1;
8464 		out->command = ctx->curr;
8465 		ctx->objdata = 0;
8466 		ctx->object = out;
8467 		ctx->objmask = NULL;
8468 		out->args.vc.data = (uint8_t *)out + size;
8469 		return len;
8470 	}
8471 	switch (ctx->curr) {
8472 	case ACTION_POL_G:
8473 		out->args.vc.actions =
8474 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8475 					sizeof(double));
8476 		out->command = ctx->curr;
8477 		ctx->objdata = 0;
8478 		ctx->object = out;
8479 		ctx->objmask = NULL;
8480 		return len;
8481 	default:
8482 		return -1;
8483 	}
8484 }
8485 
8486 /** Parse tokens for validate/create commands. */
8487 static int
8488 parse_vc(struct context *ctx, const struct token *token,
8489 	 const char *str, unsigned int len,
8490 	 void *buf, unsigned int size)
8491 {
8492 	struct buffer *out = buf;
8493 	uint8_t *data;
8494 	uint32_t data_size;
8495 
8496 	/* Token name must match. */
8497 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8498 		return -1;
8499 	/* Nothing else to do if there is no buffer. */
8500 	if (!out)
8501 		return len;
8502 	if (!out->command) {
8503 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8504 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8505 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8506 		    ctx->curr != UPDATE)
8507 			return -1;
8508 		if (ctx->curr == UPDATE)
8509 			out->args.vc.pattern =
8510 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8511 						       sizeof(double));
8512 		if (sizeof(*out) > size)
8513 			return -1;
8514 		out->command = ctx->curr;
8515 		ctx->objdata = 0;
8516 		ctx->object = out;
8517 		ctx->objmask = NULL;
8518 		out->args.vc.data = (uint8_t *)out + size;
8519 		return len;
8520 	}
8521 	ctx->objdata = 0;
8522 	switch (ctx->curr) {
8523 	default:
8524 		ctx->object = &out->args.vc.attr;
8525 		break;
8526 	case VC_TUNNEL_SET:
8527 	case VC_TUNNEL_MATCH:
8528 		ctx->object = &out->args.vc.tunnel_ops;
8529 		break;
8530 	case VC_USER_ID:
8531 		ctx->object = out;
8532 		break;
8533 	}
8534 	ctx->objmask = NULL;
8535 	switch (ctx->curr) {
8536 	case VC_GROUP:
8537 	case VC_PRIORITY:
8538 	case VC_USER_ID:
8539 		return len;
8540 	case VC_TUNNEL_SET:
8541 		out->args.vc.tunnel_ops.enabled = 1;
8542 		out->args.vc.tunnel_ops.actions = 1;
8543 		return len;
8544 	case VC_TUNNEL_MATCH:
8545 		out->args.vc.tunnel_ops.enabled = 1;
8546 		out->args.vc.tunnel_ops.items = 1;
8547 		return len;
8548 	case VC_INGRESS:
8549 		out->args.vc.attr.ingress = 1;
8550 		return len;
8551 	case VC_EGRESS:
8552 		out->args.vc.attr.egress = 1;
8553 		return len;
8554 	case VC_TRANSFER:
8555 		out->args.vc.attr.transfer = 1;
8556 		return len;
8557 	case ITEM_PATTERN:
8558 		out->args.vc.pattern =
8559 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8560 					       sizeof(double));
8561 		ctx->object = out->args.vc.pattern;
8562 		ctx->objmask = NULL;
8563 		return len;
8564 	case ITEM_END:
8565 		if ((out->command == VALIDATE || out->command == CREATE) &&
8566 		    ctx->last)
8567 			return -1;
8568 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8569 		    !ctx->last)
8570 			return -1;
8571 		break;
8572 	case ACTIONS:
8573 		out->args.vc.actions = out->args.vc.pattern ?
8574 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8575 					       (out->args.vc.pattern +
8576 						out->args.vc.pattern_n),
8577 					       sizeof(double)) :
8578 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8579 					       sizeof(double));
8580 		ctx->object = out->args.vc.actions;
8581 		ctx->objmask = NULL;
8582 		return len;
8583 	case VC_IS_USER_ID:
8584 		out->args.vc.user_id = true;
8585 		return len;
8586 	default:
8587 		if (!token->priv)
8588 			return -1;
8589 		break;
8590 	}
8591 	if (!out->args.vc.actions) {
8592 		const struct parse_item_priv *priv = token->priv;
8593 		struct rte_flow_item *item =
8594 			out->args.vc.pattern + out->args.vc.pattern_n;
8595 
8596 		data_size = priv->size * 3; /* spec, last, mask */
8597 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8598 					       (out->args.vc.data - data_size),
8599 					       sizeof(double));
8600 		if ((uint8_t *)item + sizeof(*item) > data)
8601 			return -1;
8602 		*item = (struct rte_flow_item){
8603 			.type = priv->type,
8604 		};
8605 		++out->args.vc.pattern_n;
8606 		ctx->object = item;
8607 		ctx->objmask = NULL;
8608 	} else {
8609 		const struct parse_action_priv *priv = token->priv;
8610 		struct rte_flow_action *action =
8611 			out->args.vc.actions + out->args.vc.actions_n;
8612 
8613 		data_size = priv->size; /* configuration */
8614 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8615 					       (out->args.vc.data - data_size),
8616 					       sizeof(double));
8617 		if ((uint8_t *)action + sizeof(*action) > data)
8618 			return -1;
8619 		*action = (struct rte_flow_action){
8620 			.type = priv->type,
8621 			.conf = data_size ? data : NULL,
8622 		};
8623 		++out->args.vc.actions_n;
8624 		ctx->object = action;
8625 		ctx->objmask = NULL;
8626 	}
8627 	memset(data, 0, data_size);
8628 	out->args.vc.data = data;
8629 	ctx->objdata = data_size;
8630 	return len;
8631 }
8632 
8633 /** Parse pattern item parameter type. */
8634 static int
8635 parse_vc_spec(struct context *ctx, const struct token *token,
8636 	      const char *str, unsigned int len,
8637 	      void *buf, unsigned int size)
8638 {
8639 	struct buffer *out = buf;
8640 	struct rte_flow_item *item;
8641 	uint32_t data_size;
8642 	int index;
8643 	int objmask = 0;
8644 
8645 	(void)size;
8646 	/* Token name must match. */
8647 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8648 		return -1;
8649 	/* Parse parameter types. */
8650 	switch (ctx->curr) {
8651 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8652 
8653 	case ITEM_PARAM_IS:
8654 		index = 0;
8655 		objmask = 1;
8656 		break;
8657 	case ITEM_PARAM_SPEC:
8658 		index = 0;
8659 		break;
8660 	case ITEM_PARAM_LAST:
8661 		index = 1;
8662 		break;
8663 	case ITEM_PARAM_PREFIX:
8664 		/* Modify next token to expect a prefix. */
8665 		if (ctx->next_num < 2)
8666 			return -1;
8667 		ctx->next[ctx->next_num - 2] = prefix;
8668 		/* Fall through. */
8669 	case ITEM_PARAM_MASK:
8670 		index = 2;
8671 		break;
8672 	default:
8673 		return -1;
8674 	}
8675 	/* Nothing else to do if there is no buffer. */
8676 	if (!out)
8677 		return len;
8678 	if (!out->args.vc.pattern_n)
8679 		return -1;
8680 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8681 	data_size = ctx->objdata / 3; /* spec, last, mask */
8682 	/* Point to selected object. */
8683 	ctx->object = out->args.vc.data + (data_size * index);
8684 	if (objmask) {
8685 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8686 		item->mask = ctx->objmask;
8687 	} else
8688 		ctx->objmask = NULL;
8689 	/* Update relevant item pointer. */
8690 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8691 		ctx->object;
8692 	return len;
8693 }
8694 
8695 /** Parse action configuration field. */
8696 static int
8697 parse_vc_conf(struct context *ctx, const struct token *token,
8698 	      const char *str, unsigned int len,
8699 	      void *buf, unsigned int size)
8700 {
8701 	struct buffer *out = buf;
8702 
8703 	(void)size;
8704 	/* Token name must match. */
8705 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8706 		return -1;
8707 	/* Nothing else to do if there is no buffer. */
8708 	if (!out)
8709 		return len;
8710 	/* Point to selected object. */
8711 	ctx->object = out->args.vc.data;
8712 	ctx->objmask = NULL;
8713 	return len;
8714 }
8715 
8716 /** Parse action configuration field. */
8717 static int
8718 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8719 		      const char *str, unsigned int len,
8720 		      void *buf, unsigned int size)
8721 {
8722 	struct buffer *out = buf;
8723 	struct rte_flow_update_age *update;
8724 
8725 	(void)size;
8726 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8727 		return -1;
8728 	/* Token name must match. */
8729 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8730 		return -1;
8731 	/* Nothing else to do if there is no buffer. */
8732 	if (!out)
8733 		return len;
8734 	/* Point to selected object. */
8735 	ctx->object = out->args.vc.data;
8736 	ctx->objmask = NULL;
8737 	/* Update the timeout is valid. */
8738 	update = (struct rte_flow_update_age *)out->args.vc.data;
8739 	update->timeout_valid = 1;
8740 	return len;
8741 }
8742 
8743 /** Parse eCPRI common header type field. */
8744 static int
8745 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8746 			 const char *str, unsigned int len,
8747 			 void *buf, unsigned int size)
8748 {
8749 	struct rte_flow_item_ecpri *ecpri;
8750 	struct rte_flow_item_ecpri *ecpri_mask;
8751 	struct rte_flow_item *item;
8752 	uint32_t data_size;
8753 	uint8_t msg_type;
8754 	struct buffer *out = buf;
8755 	const struct arg *arg;
8756 
8757 	(void)size;
8758 	/* Token name must match. */
8759 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8760 		return -1;
8761 	switch (ctx->curr) {
8762 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8763 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8764 		break;
8765 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8766 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8767 		break;
8768 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8769 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8770 		break;
8771 	default:
8772 		return -1;
8773 	}
8774 	if (!ctx->object)
8775 		return len;
8776 	arg = pop_args(ctx);
8777 	if (!arg)
8778 		return -1;
8779 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8780 	ecpri->hdr.common.type = msg_type;
8781 	data_size = ctx->objdata / 3; /* spec, last, mask */
8782 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8783 						    (data_size * 2));
8784 	ecpri_mask->hdr.common.type = 0xFF;
8785 	if (arg->hton) {
8786 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8787 		ecpri_mask->hdr.common.u32 =
8788 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8789 	}
8790 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8791 	item->spec = ecpri;
8792 	item->mask = ecpri_mask;
8793 	return len;
8794 }
8795 
8796 /** Parse L2TPv2 common header type field. */
8797 static int
8798 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8799 			 const char *str, unsigned int len,
8800 			 void *buf, unsigned int size)
8801 {
8802 	struct rte_flow_item_l2tpv2 *l2tpv2;
8803 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8804 	struct rte_flow_item *item;
8805 	uint32_t data_size;
8806 	uint16_t msg_type = 0;
8807 	struct buffer *out = buf;
8808 	const struct arg *arg;
8809 
8810 	(void)size;
8811 	/* Token name must match. */
8812 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8813 		return -1;
8814 	switch (ctx->curr) {
8815 	case ITEM_L2TPV2_TYPE_DATA:
8816 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8817 		break;
8818 	case ITEM_L2TPV2_TYPE_DATA_L:
8819 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8820 		break;
8821 	case ITEM_L2TPV2_TYPE_DATA_S:
8822 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8823 		break;
8824 	case ITEM_L2TPV2_TYPE_DATA_O:
8825 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8826 		break;
8827 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8828 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8829 		break;
8830 	case ITEM_L2TPV2_TYPE_CTRL:
8831 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
8832 		break;
8833 	default:
8834 		return -1;
8835 	}
8836 	if (!ctx->object)
8837 		return len;
8838 	arg = pop_args(ctx);
8839 	if (!arg)
8840 		return -1;
8841 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
8842 	l2tpv2->hdr.common.flags_version |= msg_type;
8843 	data_size = ctx->objdata / 3; /* spec, last, mask */
8844 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
8845 						    (data_size * 2));
8846 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
8847 	if (arg->hton) {
8848 		l2tpv2->hdr.common.flags_version =
8849 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
8850 		l2tpv2_mask->hdr.common.flags_version =
8851 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
8852 	}
8853 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8854 	item->spec = l2tpv2;
8855 	item->mask = l2tpv2_mask;
8856 	return len;
8857 }
8858 
8859 /** Parse operation for compare match item. */
8860 static int
8861 parse_vc_compare_op(struct context *ctx, const struct token *token,
8862 			 const char *str, unsigned int len, void *buf,
8863 			 unsigned int size)
8864 {
8865 	struct rte_flow_item_compare *compare_item;
8866 	unsigned int i;
8867 
8868 	(void)token;
8869 	(void)buf;
8870 	(void)size;
8871 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
8872 		return -1;
8873 	for (i = 0; compare_ops[i]; ++i)
8874 		if (!strcmp_partial(compare_ops[i], str, len))
8875 			break;
8876 	if (!compare_ops[i])
8877 		return -1;
8878 	if (!ctx->object)
8879 		return len;
8880 	compare_item = ctx->object;
8881 	compare_item->operation = (enum rte_flow_item_compare_op)i;
8882 	return len;
8883 }
8884 
8885 /** Parse id for compare match item. */
8886 static int
8887 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
8888 			  const char *str, unsigned int len, void *buf,
8889 			  unsigned int size)
8890 {
8891 	struct rte_flow_item_compare *compare_item;
8892 	unsigned int i;
8893 
8894 	(void)token;
8895 	(void)buf;
8896 	(void)size;
8897 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
8898 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
8899 		return -1;
8900 	for (i = 0; flow_field_ids[i]; ++i)
8901 		if (!strcmp_partial(flow_field_ids[i], str, len))
8902 			break;
8903 	if (!flow_field_ids[i])
8904 		return -1;
8905 	if (!ctx->object)
8906 		return len;
8907 	compare_item = ctx->object;
8908 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
8909 		compare_item->a.field = (enum rte_flow_field_id)i;
8910 	else
8911 		compare_item->b.field = (enum rte_flow_field_id)i;
8912 	return len;
8913 }
8914 
8915 /** Parse level for compare match item. */
8916 static int
8917 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
8918 			     const char *str, unsigned int len, void *buf,
8919 			     unsigned int size)
8920 {
8921 	struct rte_flow_item_compare *compare_item;
8922 	struct flex_item *fp = NULL;
8923 	uint32_t val;
8924 	struct buffer *out = buf;
8925 	char *end;
8926 
8927 	(void)token;
8928 	(void)size;
8929 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8930 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
8931 		return -1;
8932 	if (!ctx->object)
8933 		return len;
8934 	compare_item = ctx->object;
8935 	errno = 0;
8936 	val = strtoumax(str, &end, 0);
8937 	if (errno || (size_t)(end - str) != len)
8938 		return -1;
8939 	/* No need to validate action template mask value */
8940 	if (out->args.vc.masks) {
8941 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
8942 			compare_item->a.level = val;
8943 		else
8944 			compare_item->b.level = val;
8945 		return len;
8946 	}
8947 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
8948 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
8949 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
8950 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
8951 		if (val >= FLEX_MAX_PARSERS_NUM) {
8952 			printf("Bad flex item handle\n");
8953 			return -1;
8954 		}
8955 		fp = flex_items[ctx->port][val];
8956 		if (!fp) {
8957 			printf("Bad flex item handle\n");
8958 			return -1;
8959 		}
8960 	}
8961 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
8962 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
8963 			compare_item->a.level = val;
8964 		else
8965 			compare_item->a.flex_handle = fp->flex_handle;
8966 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
8967 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
8968 			compare_item->b.level = val;
8969 		else
8970 			compare_item->b.flex_handle = fp->flex_handle;
8971 	}
8972 	return len;
8973 }
8974 
8975 /** Parse meter color action type. */
8976 static int
8977 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
8978 				const char *str, unsigned int len,
8979 				void *buf, unsigned int size)
8980 {
8981 	struct rte_flow_action *action_data;
8982 	struct rte_flow_action_meter_color *conf;
8983 	enum rte_color color;
8984 
8985 	(void)buf;
8986 	(void)size;
8987 	/* Token name must match. */
8988 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8989 		return -1;
8990 	switch (ctx->curr) {
8991 	case ACTION_METER_COLOR_GREEN:
8992 		color = RTE_COLOR_GREEN;
8993 	break;
8994 	case ACTION_METER_COLOR_YELLOW:
8995 		color = RTE_COLOR_YELLOW;
8996 	break;
8997 	case ACTION_METER_COLOR_RED:
8998 		color = RTE_COLOR_RED;
8999 	break;
9000 	default:
9001 		return -1;
9002 	}
9003 
9004 	if (!ctx->object)
9005 		return len;
9006 	action_data = ctx->object;
9007 	conf = (struct rte_flow_action_meter_color *)
9008 					(uintptr_t)(action_data->conf);
9009 	conf->color = color;
9010 	return len;
9011 }
9012 
9013 /** Parse RSS action. */
9014 static int
9015 parse_vc_action_rss(struct context *ctx, const struct token *token,
9016 		    const char *str, unsigned int len,
9017 		    void *buf, unsigned int size)
9018 {
9019 	struct buffer *out = buf;
9020 	struct rte_flow_action *action;
9021 	struct action_rss_data *action_rss_data;
9022 	unsigned int i;
9023 	int ret;
9024 
9025 	ret = parse_vc(ctx, token, str, len, buf, size);
9026 	if (ret < 0)
9027 		return ret;
9028 	/* Nothing else to do if there is no buffer. */
9029 	if (!out)
9030 		return ret;
9031 	if (!out->args.vc.actions_n)
9032 		return -1;
9033 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9034 	/* Point to selected object. */
9035 	ctx->object = out->args.vc.data;
9036 	ctx->objmask = NULL;
9037 	/* Set up default configuration. */
9038 	action_rss_data = ctx->object;
9039 	*action_rss_data = (struct action_rss_data){
9040 		.conf = (struct rte_flow_action_rss){
9041 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9042 			.level = 0,
9043 			.types = rss_hf,
9044 			.key_len = 0,
9045 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9046 			.key = NULL,
9047 			.queue = action_rss_data->queue,
9048 		},
9049 		.queue = { 0 },
9050 	};
9051 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9052 		action_rss_data->queue[i] = i;
9053 	action->conf = &action_rss_data->conf;
9054 	return ret;
9055 }
9056 
9057 /**
9058  * Parse func field for RSS action.
9059  *
9060  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9061  * ACTION_RSS_FUNC_* index that called this function.
9062  */
9063 static int
9064 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9065 			 const char *str, unsigned int len,
9066 			 void *buf, unsigned int size)
9067 {
9068 	struct action_rss_data *action_rss_data;
9069 	enum rte_eth_hash_function func;
9070 
9071 	(void)buf;
9072 	(void)size;
9073 	/* Token name must match. */
9074 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9075 		return -1;
9076 	switch (ctx->curr) {
9077 	case ACTION_RSS_FUNC_DEFAULT:
9078 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9079 		break;
9080 	case ACTION_RSS_FUNC_TOEPLITZ:
9081 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9082 		break;
9083 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9084 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9085 		break;
9086 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9087 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9088 		break;
9089 	default:
9090 		return -1;
9091 	}
9092 	if (!ctx->object)
9093 		return len;
9094 	action_rss_data = ctx->object;
9095 	action_rss_data->conf.func = func;
9096 	return len;
9097 }
9098 
9099 /**
9100  * Parse type field for RSS action.
9101  *
9102  * Valid tokens are type field names and the "end" token.
9103  */
9104 static int
9105 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9106 			  const char *str, unsigned int len,
9107 			  void *buf, unsigned int size)
9108 {
9109 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9110 	struct action_rss_data *action_rss_data;
9111 	unsigned int i;
9112 
9113 	(void)token;
9114 	(void)buf;
9115 	(void)size;
9116 	if (ctx->curr != ACTION_RSS_TYPE)
9117 		return -1;
9118 	if (!(ctx->objdata >> 16) && ctx->object) {
9119 		action_rss_data = ctx->object;
9120 		action_rss_data->conf.types = 0;
9121 	}
9122 	if (!strcmp_partial("end", str, len)) {
9123 		ctx->objdata &= 0xffff;
9124 		return len;
9125 	}
9126 	for (i = 0; rss_type_table[i].str; ++i)
9127 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9128 			break;
9129 	if (!rss_type_table[i].str)
9130 		return -1;
9131 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9132 	/* Repeat token. */
9133 	if (ctx->next_num == RTE_DIM(ctx->next))
9134 		return -1;
9135 	ctx->next[ctx->next_num++] = next;
9136 	if (!ctx->object)
9137 		return len;
9138 	action_rss_data = ctx->object;
9139 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9140 	return len;
9141 }
9142 
9143 /**
9144  * Parse queue field for RSS action.
9145  *
9146  * Valid tokens are queue indices and the "end" token.
9147  */
9148 static int
9149 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9150 			  const char *str, unsigned int len,
9151 			  void *buf, unsigned int size)
9152 {
9153 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9154 	struct action_rss_data *action_rss_data;
9155 	const struct arg *arg;
9156 	int ret;
9157 	int i;
9158 
9159 	(void)token;
9160 	(void)buf;
9161 	(void)size;
9162 	if (ctx->curr != ACTION_RSS_QUEUE)
9163 		return -1;
9164 	i = ctx->objdata >> 16;
9165 	if (!strcmp_partial("end", str, len)) {
9166 		ctx->objdata &= 0xffff;
9167 		goto end;
9168 	}
9169 	if (i >= ACTION_RSS_QUEUE_NUM)
9170 		return -1;
9171 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9172 			     i * sizeof(action_rss_data->queue[i]),
9173 			     sizeof(action_rss_data->queue[i]));
9174 	if (push_args(ctx, arg))
9175 		return -1;
9176 	ret = parse_int(ctx, token, str, len, NULL, 0);
9177 	if (ret < 0) {
9178 		pop_args(ctx);
9179 		return -1;
9180 	}
9181 	++i;
9182 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9183 	/* Repeat token. */
9184 	if (ctx->next_num == RTE_DIM(ctx->next))
9185 		return -1;
9186 	ctx->next[ctx->next_num++] = next;
9187 end:
9188 	if (!ctx->object)
9189 		return len;
9190 	action_rss_data = ctx->object;
9191 	action_rss_data->conf.queue_num = i;
9192 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9193 	return len;
9194 }
9195 
9196 /** Setup VXLAN encap configuration. */
9197 static int
9198 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9199 {
9200 	/* Set up default configuration. */
9201 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9202 		.conf = (struct rte_flow_action_vxlan_encap){
9203 			.definition = action_vxlan_encap_data->items,
9204 		},
9205 		.items = {
9206 			{
9207 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9208 				.spec = &action_vxlan_encap_data->item_eth,
9209 				.mask = &rte_flow_item_eth_mask,
9210 			},
9211 			{
9212 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9213 				.spec = &action_vxlan_encap_data->item_vlan,
9214 				.mask = &rte_flow_item_vlan_mask,
9215 			},
9216 			{
9217 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9218 				.spec = &action_vxlan_encap_data->item_ipv4,
9219 				.mask = &rte_flow_item_ipv4_mask,
9220 			},
9221 			{
9222 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9223 				.spec = &action_vxlan_encap_data->item_udp,
9224 				.mask = &rte_flow_item_udp_mask,
9225 			},
9226 			{
9227 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9228 				.spec = &action_vxlan_encap_data->item_vxlan,
9229 				.mask = &rte_flow_item_vxlan_mask,
9230 			},
9231 			{
9232 				.type = RTE_FLOW_ITEM_TYPE_END,
9233 			},
9234 		},
9235 		.item_eth.hdr.ether_type = 0,
9236 		.item_vlan = {
9237 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9238 			.hdr.eth_proto = 0,
9239 		},
9240 		.item_ipv4.hdr = {
9241 			.src_addr = vxlan_encap_conf.ipv4_src,
9242 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9243 		},
9244 		.item_udp.hdr = {
9245 			.src_port = vxlan_encap_conf.udp_src,
9246 			.dst_port = vxlan_encap_conf.udp_dst,
9247 		},
9248 		.item_vxlan.hdr.flags = 0,
9249 	};
9250 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9251 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9252 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9253 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9254 	if (!vxlan_encap_conf.select_ipv4) {
9255 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9256 		       &vxlan_encap_conf.ipv6_src,
9257 		       sizeof(vxlan_encap_conf.ipv6_src));
9258 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9259 		       &vxlan_encap_conf.ipv6_dst,
9260 		       sizeof(vxlan_encap_conf.ipv6_dst));
9261 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9262 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9263 			.spec = &action_vxlan_encap_data->item_ipv6,
9264 			.mask = &rte_flow_item_ipv6_mask,
9265 		};
9266 	}
9267 	if (!vxlan_encap_conf.select_vlan)
9268 		action_vxlan_encap_data->items[1].type =
9269 			RTE_FLOW_ITEM_TYPE_VOID;
9270 	if (vxlan_encap_conf.select_tos_ttl) {
9271 		if (vxlan_encap_conf.select_ipv4) {
9272 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9273 
9274 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9275 			       sizeof(ipv4_mask_tos));
9276 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9277 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9278 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9279 					vxlan_encap_conf.ip_tos;
9280 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9281 					vxlan_encap_conf.ip_ttl;
9282 			action_vxlan_encap_data->items[2].mask =
9283 							&ipv4_mask_tos;
9284 		} else {
9285 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9286 
9287 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9288 			       sizeof(ipv6_mask_tos));
9289 			ipv6_mask_tos.hdr.vtc_flow |=
9290 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9291 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9292 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9293 				rte_cpu_to_be_32
9294 					((uint32_t)vxlan_encap_conf.ip_tos <<
9295 					 RTE_IPV6_HDR_TC_SHIFT);
9296 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9297 					vxlan_encap_conf.ip_ttl;
9298 			action_vxlan_encap_data->items[2].mask =
9299 							&ipv6_mask_tos;
9300 		}
9301 	}
9302 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9303 	       RTE_DIM(vxlan_encap_conf.vni));
9304 	return 0;
9305 }
9306 
9307 /** Parse VXLAN encap action. */
9308 static int
9309 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9310 			    const char *str, unsigned int len,
9311 			    void *buf, unsigned int size)
9312 {
9313 	struct buffer *out = buf;
9314 	struct rte_flow_action *action;
9315 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9316 	int ret;
9317 
9318 	ret = parse_vc(ctx, token, str, len, buf, size);
9319 	if (ret < 0)
9320 		return ret;
9321 	/* Nothing else to do if there is no buffer. */
9322 	if (!out)
9323 		return ret;
9324 	if (!out->args.vc.actions_n)
9325 		return -1;
9326 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9327 	/* Point to selected object. */
9328 	ctx->object = out->args.vc.data;
9329 	ctx->objmask = NULL;
9330 	action_vxlan_encap_data = ctx->object;
9331 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9332 	action->conf = &action_vxlan_encap_data->conf;
9333 	return ret;
9334 }
9335 
9336 /** Setup NVGRE encap configuration. */
9337 static int
9338 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9339 {
9340 	/* Set up default configuration. */
9341 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9342 		.conf = (struct rte_flow_action_nvgre_encap){
9343 			.definition = action_nvgre_encap_data->items,
9344 		},
9345 		.items = {
9346 			{
9347 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9348 				.spec = &action_nvgre_encap_data->item_eth,
9349 				.mask = &rte_flow_item_eth_mask,
9350 			},
9351 			{
9352 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9353 				.spec = &action_nvgre_encap_data->item_vlan,
9354 				.mask = &rte_flow_item_vlan_mask,
9355 			},
9356 			{
9357 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9358 				.spec = &action_nvgre_encap_data->item_ipv4,
9359 				.mask = &rte_flow_item_ipv4_mask,
9360 			},
9361 			{
9362 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9363 				.spec = &action_nvgre_encap_data->item_nvgre,
9364 				.mask = &rte_flow_item_nvgre_mask,
9365 			},
9366 			{
9367 				.type = RTE_FLOW_ITEM_TYPE_END,
9368 			},
9369 		},
9370 		.item_eth.hdr.ether_type = 0,
9371 		.item_vlan = {
9372 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9373 			.hdr.eth_proto = 0,
9374 		},
9375 		.item_ipv4.hdr = {
9376 		       .src_addr = nvgre_encap_conf.ipv4_src,
9377 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9378 		},
9379 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9380 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9381 		.item_nvgre.flow_id = 0,
9382 	};
9383 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9384 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9385 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9386 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9387 	if (!nvgre_encap_conf.select_ipv4) {
9388 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9389 		       &nvgre_encap_conf.ipv6_src,
9390 		       sizeof(nvgre_encap_conf.ipv6_src));
9391 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9392 		       &nvgre_encap_conf.ipv6_dst,
9393 		       sizeof(nvgre_encap_conf.ipv6_dst));
9394 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9395 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9396 			.spec = &action_nvgre_encap_data->item_ipv6,
9397 			.mask = &rte_flow_item_ipv6_mask,
9398 		};
9399 	}
9400 	if (!nvgre_encap_conf.select_vlan)
9401 		action_nvgre_encap_data->items[1].type =
9402 			RTE_FLOW_ITEM_TYPE_VOID;
9403 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9404 	       RTE_DIM(nvgre_encap_conf.tni));
9405 	return 0;
9406 }
9407 
9408 /** Parse NVGRE encap action. */
9409 static int
9410 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9411 			    const char *str, unsigned int len,
9412 			    void *buf, unsigned int size)
9413 {
9414 	struct buffer *out = buf;
9415 	struct rte_flow_action *action;
9416 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9417 	int ret;
9418 
9419 	ret = parse_vc(ctx, token, str, len, buf, size);
9420 	if (ret < 0)
9421 		return ret;
9422 	/* Nothing else to do if there is no buffer. */
9423 	if (!out)
9424 		return ret;
9425 	if (!out->args.vc.actions_n)
9426 		return -1;
9427 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9428 	/* Point to selected object. */
9429 	ctx->object = out->args.vc.data;
9430 	ctx->objmask = NULL;
9431 	action_nvgre_encap_data = ctx->object;
9432 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9433 	action->conf = &action_nvgre_encap_data->conf;
9434 	return ret;
9435 }
9436 
9437 /** Parse l2 encap action. */
9438 static int
9439 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9440 			 const char *str, unsigned int len,
9441 			 void *buf, unsigned int size)
9442 {
9443 	struct buffer *out = buf;
9444 	struct rte_flow_action *action;
9445 	struct action_raw_encap_data *action_encap_data;
9446 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9447 	struct rte_flow_item_vlan vlan = {
9448 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9449 		.hdr.eth_proto = 0,
9450 	};
9451 	uint8_t *header;
9452 	int ret;
9453 
9454 	ret = parse_vc(ctx, token, str, len, buf, size);
9455 	if (ret < 0)
9456 		return ret;
9457 	/* Nothing else to do if there is no buffer. */
9458 	if (!out)
9459 		return ret;
9460 	if (!out->args.vc.actions_n)
9461 		return -1;
9462 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9463 	/* Point to selected object. */
9464 	ctx->object = out->args.vc.data;
9465 	ctx->objmask = NULL;
9466 	/* Copy the headers to the buffer. */
9467 	action_encap_data = ctx->object;
9468 	*action_encap_data = (struct action_raw_encap_data) {
9469 		.conf = (struct rte_flow_action_raw_encap){
9470 			.data = action_encap_data->data,
9471 		},
9472 		.data = {},
9473 	};
9474 	header = action_encap_data->data;
9475 	if (l2_encap_conf.select_vlan)
9476 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9477 	else if (l2_encap_conf.select_ipv4)
9478 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9479 	else
9480 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9481 	memcpy(eth.hdr.dst_addr.addr_bytes,
9482 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9483 	memcpy(eth.hdr.src_addr.addr_bytes,
9484 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9485 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9486 	header += sizeof(struct rte_ether_hdr);
9487 	if (l2_encap_conf.select_vlan) {
9488 		if (l2_encap_conf.select_ipv4)
9489 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9490 		else
9491 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9492 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9493 		header += sizeof(struct rte_vlan_hdr);
9494 	}
9495 	action_encap_data->conf.size = header -
9496 		action_encap_data->data;
9497 	action->conf = &action_encap_data->conf;
9498 	return ret;
9499 }
9500 
9501 /** Parse l2 decap action. */
9502 static int
9503 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9504 			 const char *str, unsigned int len,
9505 			 void *buf, unsigned int size)
9506 {
9507 	struct buffer *out = buf;
9508 	struct rte_flow_action *action;
9509 	struct action_raw_decap_data *action_decap_data;
9510 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9511 	struct rte_flow_item_vlan vlan = {
9512 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9513 		.hdr.eth_proto = 0,
9514 	};
9515 	uint8_t *header;
9516 	int ret;
9517 
9518 	ret = parse_vc(ctx, token, str, len, buf, size);
9519 	if (ret < 0)
9520 		return ret;
9521 	/* Nothing else to do if there is no buffer. */
9522 	if (!out)
9523 		return ret;
9524 	if (!out->args.vc.actions_n)
9525 		return -1;
9526 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9527 	/* Point to selected object. */
9528 	ctx->object = out->args.vc.data;
9529 	ctx->objmask = NULL;
9530 	/* Copy the headers to the buffer. */
9531 	action_decap_data = ctx->object;
9532 	*action_decap_data = (struct action_raw_decap_data) {
9533 		.conf = (struct rte_flow_action_raw_decap){
9534 			.data = action_decap_data->data,
9535 		},
9536 		.data = {},
9537 	};
9538 	header = action_decap_data->data;
9539 	if (l2_decap_conf.select_vlan)
9540 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9541 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9542 	header += sizeof(struct rte_ether_hdr);
9543 	if (l2_decap_conf.select_vlan) {
9544 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9545 		header += sizeof(struct rte_vlan_hdr);
9546 	}
9547 	action_decap_data->conf.size = header -
9548 		action_decap_data->data;
9549 	action->conf = &action_decap_data->conf;
9550 	return ret;
9551 }
9552 
9553 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9554 
9555 /** Parse MPLSOGRE encap action. */
9556 static int
9557 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9558 			       const char *str, unsigned int len,
9559 			       void *buf, unsigned int size)
9560 {
9561 	struct buffer *out = buf;
9562 	struct rte_flow_action *action;
9563 	struct action_raw_encap_data *action_encap_data;
9564 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9565 	struct rte_flow_item_vlan vlan = {
9566 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9567 		.hdr.eth_proto = 0,
9568 	};
9569 	struct rte_flow_item_ipv4 ipv4 = {
9570 		.hdr =  {
9571 			.src_addr = mplsogre_encap_conf.ipv4_src,
9572 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9573 			.next_proto_id = IPPROTO_GRE,
9574 			.version_ihl = RTE_IPV4_VHL_DEF,
9575 			.time_to_live = IPDEFTTL,
9576 		},
9577 	};
9578 	struct rte_flow_item_ipv6 ipv6 = {
9579 		.hdr =  {
9580 			.proto = IPPROTO_GRE,
9581 			.hop_limits = IPDEFTTL,
9582 		},
9583 	};
9584 	struct rte_flow_item_gre gre = {
9585 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9586 	};
9587 	struct rte_flow_item_mpls mpls = {
9588 		.ttl = 0,
9589 	};
9590 	uint8_t *header;
9591 	int ret;
9592 
9593 	ret = parse_vc(ctx, token, str, len, buf, size);
9594 	if (ret < 0)
9595 		return ret;
9596 	/* Nothing else to do if there is no buffer. */
9597 	if (!out)
9598 		return ret;
9599 	if (!out->args.vc.actions_n)
9600 		return -1;
9601 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9602 	/* Point to selected object. */
9603 	ctx->object = out->args.vc.data;
9604 	ctx->objmask = NULL;
9605 	/* Copy the headers to the buffer. */
9606 	action_encap_data = ctx->object;
9607 	*action_encap_data = (struct action_raw_encap_data) {
9608 		.conf = (struct rte_flow_action_raw_encap){
9609 			.data = action_encap_data->data,
9610 		},
9611 		.data = {},
9612 		.preserve = {},
9613 	};
9614 	header = action_encap_data->data;
9615 	if (mplsogre_encap_conf.select_vlan)
9616 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9617 	else if (mplsogre_encap_conf.select_ipv4)
9618 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9619 	else
9620 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9621 	memcpy(eth.hdr.dst_addr.addr_bytes,
9622 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9623 	memcpy(eth.hdr.src_addr.addr_bytes,
9624 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9625 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9626 	header += sizeof(struct rte_ether_hdr);
9627 	if (mplsogre_encap_conf.select_vlan) {
9628 		if (mplsogre_encap_conf.select_ipv4)
9629 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9630 		else
9631 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9632 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9633 		header += sizeof(struct rte_vlan_hdr);
9634 	}
9635 	if (mplsogre_encap_conf.select_ipv4) {
9636 		memcpy(header, &ipv4, sizeof(ipv4));
9637 		header += sizeof(ipv4);
9638 	} else {
9639 		memcpy(&ipv6.hdr.src_addr,
9640 		       &mplsogre_encap_conf.ipv6_src,
9641 		       sizeof(mplsogre_encap_conf.ipv6_src));
9642 		memcpy(&ipv6.hdr.dst_addr,
9643 		       &mplsogre_encap_conf.ipv6_dst,
9644 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9645 		memcpy(header, &ipv6, sizeof(ipv6));
9646 		header += sizeof(ipv6);
9647 	}
9648 	memcpy(header, &gre, sizeof(gre));
9649 	header += sizeof(gre);
9650 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9651 	       RTE_DIM(mplsogre_encap_conf.label));
9652 	mpls.label_tc_s[2] |= 0x1;
9653 	memcpy(header, &mpls, sizeof(mpls));
9654 	header += sizeof(mpls);
9655 	action_encap_data->conf.size = header -
9656 		action_encap_data->data;
9657 	action->conf = &action_encap_data->conf;
9658 	return ret;
9659 }
9660 
9661 /** Parse MPLSOGRE decap action. */
9662 static int
9663 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9664 			       const char *str, unsigned int len,
9665 			       void *buf, unsigned int size)
9666 {
9667 	struct buffer *out = buf;
9668 	struct rte_flow_action *action;
9669 	struct action_raw_decap_data *action_decap_data;
9670 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9671 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9672 	struct rte_flow_item_ipv4 ipv4 = {
9673 		.hdr =  {
9674 			.next_proto_id = IPPROTO_GRE,
9675 		},
9676 	};
9677 	struct rte_flow_item_ipv6 ipv6 = {
9678 		.hdr =  {
9679 			.proto = IPPROTO_GRE,
9680 		},
9681 	};
9682 	struct rte_flow_item_gre gre = {
9683 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9684 	};
9685 	struct rte_flow_item_mpls mpls;
9686 	uint8_t *header;
9687 	int ret;
9688 
9689 	ret = parse_vc(ctx, token, str, len, buf, size);
9690 	if (ret < 0)
9691 		return ret;
9692 	/* Nothing else to do if there is no buffer. */
9693 	if (!out)
9694 		return ret;
9695 	if (!out->args.vc.actions_n)
9696 		return -1;
9697 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9698 	/* Point to selected object. */
9699 	ctx->object = out->args.vc.data;
9700 	ctx->objmask = NULL;
9701 	/* Copy the headers to the buffer. */
9702 	action_decap_data = ctx->object;
9703 	*action_decap_data = (struct action_raw_decap_data) {
9704 		.conf = (struct rte_flow_action_raw_decap){
9705 			.data = action_decap_data->data,
9706 		},
9707 		.data = {},
9708 	};
9709 	header = action_decap_data->data;
9710 	if (mplsogre_decap_conf.select_vlan)
9711 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9712 	else if (mplsogre_encap_conf.select_ipv4)
9713 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9714 	else
9715 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9716 	memcpy(eth.hdr.dst_addr.addr_bytes,
9717 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9718 	memcpy(eth.hdr.src_addr.addr_bytes,
9719 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9720 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9721 	header += sizeof(struct rte_ether_hdr);
9722 	if (mplsogre_encap_conf.select_vlan) {
9723 		if (mplsogre_encap_conf.select_ipv4)
9724 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9725 		else
9726 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9727 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9728 		header += sizeof(struct rte_vlan_hdr);
9729 	}
9730 	if (mplsogre_encap_conf.select_ipv4) {
9731 		memcpy(header, &ipv4, sizeof(ipv4));
9732 		header += sizeof(ipv4);
9733 	} else {
9734 		memcpy(header, &ipv6, sizeof(ipv6));
9735 		header += sizeof(ipv6);
9736 	}
9737 	memcpy(header, &gre, sizeof(gre));
9738 	header += sizeof(gre);
9739 	memset(&mpls, 0, sizeof(mpls));
9740 	memcpy(header, &mpls, sizeof(mpls));
9741 	header += sizeof(mpls);
9742 	action_decap_data->conf.size = header -
9743 		action_decap_data->data;
9744 	action->conf = &action_decap_data->conf;
9745 	return ret;
9746 }
9747 
9748 /** Parse MPLSOUDP encap action. */
9749 static int
9750 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9751 			       const char *str, unsigned int len,
9752 			       void *buf, unsigned int size)
9753 {
9754 	struct buffer *out = buf;
9755 	struct rte_flow_action *action;
9756 	struct action_raw_encap_data *action_encap_data;
9757 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9758 	struct rte_flow_item_vlan vlan = {
9759 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9760 		.hdr.eth_proto = 0,
9761 	};
9762 	struct rte_flow_item_ipv4 ipv4 = {
9763 		.hdr =  {
9764 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9765 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9766 			.next_proto_id = IPPROTO_UDP,
9767 			.version_ihl = RTE_IPV4_VHL_DEF,
9768 			.time_to_live = IPDEFTTL,
9769 		},
9770 	};
9771 	struct rte_flow_item_ipv6 ipv6 = {
9772 		.hdr =  {
9773 			.proto = IPPROTO_UDP,
9774 			.hop_limits = IPDEFTTL,
9775 		},
9776 	};
9777 	struct rte_flow_item_udp udp = {
9778 		.hdr = {
9779 			.src_port = mplsoudp_encap_conf.udp_src,
9780 			.dst_port = mplsoudp_encap_conf.udp_dst,
9781 		},
9782 	};
9783 	struct rte_flow_item_mpls mpls;
9784 	uint8_t *header;
9785 	int ret;
9786 
9787 	ret = parse_vc(ctx, token, str, len, buf, size);
9788 	if (ret < 0)
9789 		return ret;
9790 	/* Nothing else to do if there is no buffer. */
9791 	if (!out)
9792 		return ret;
9793 	if (!out->args.vc.actions_n)
9794 		return -1;
9795 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9796 	/* Point to selected object. */
9797 	ctx->object = out->args.vc.data;
9798 	ctx->objmask = NULL;
9799 	/* Copy the headers to the buffer. */
9800 	action_encap_data = ctx->object;
9801 	*action_encap_data = (struct action_raw_encap_data) {
9802 		.conf = (struct rte_flow_action_raw_encap){
9803 			.data = action_encap_data->data,
9804 		},
9805 		.data = {},
9806 		.preserve = {},
9807 	};
9808 	header = action_encap_data->data;
9809 	if (mplsoudp_encap_conf.select_vlan)
9810 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9811 	else if (mplsoudp_encap_conf.select_ipv4)
9812 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9813 	else
9814 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9815 	memcpy(eth.hdr.dst_addr.addr_bytes,
9816 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9817 	memcpy(eth.hdr.src_addr.addr_bytes,
9818 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9819 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9820 	header += sizeof(struct rte_ether_hdr);
9821 	if (mplsoudp_encap_conf.select_vlan) {
9822 		if (mplsoudp_encap_conf.select_ipv4)
9823 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9824 		else
9825 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9826 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9827 		header += sizeof(struct rte_vlan_hdr);
9828 	}
9829 	if (mplsoudp_encap_conf.select_ipv4) {
9830 		memcpy(header, &ipv4, sizeof(ipv4));
9831 		header += sizeof(ipv4);
9832 	} else {
9833 		memcpy(&ipv6.hdr.src_addr,
9834 		       &mplsoudp_encap_conf.ipv6_src,
9835 		       sizeof(mplsoudp_encap_conf.ipv6_src));
9836 		memcpy(&ipv6.hdr.dst_addr,
9837 		       &mplsoudp_encap_conf.ipv6_dst,
9838 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
9839 		memcpy(header, &ipv6, sizeof(ipv6));
9840 		header += sizeof(ipv6);
9841 	}
9842 	memcpy(header, &udp, sizeof(udp));
9843 	header += sizeof(udp);
9844 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
9845 	       RTE_DIM(mplsoudp_encap_conf.label));
9846 	mpls.label_tc_s[2] |= 0x1;
9847 	memcpy(header, &mpls, sizeof(mpls));
9848 	header += sizeof(mpls);
9849 	action_encap_data->conf.size = header -
9850 		action_encap_data->data;
9851 	action->conf = &action_encap_data->conf;
9852 	return ret;
9853 }
9854 
9855 /** Parse MPLSOUDP decap action. */
9856 static int
9857 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
9858 			       const char *str, unsigned int len,
9859 			       void *buf, unsigned int size)
9860 {
9861 	struct buffer *out = buf;
9862 	struct rte_flow_action *action;
9863 	struct action_raw_decap_data *action_decap_data;
9864 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9865 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9866 	struct rte_flow_item_ipv4 ipv4 = {
9867 		.hdr =  {
9868 			.next_proto_id = IPPROTO_UDP,
9869 		},
9870 	};
9871 	struct rte_flow_item_ipv6 ipv6 = {
9872 		.hdr =  {
9873 			.proto = IPPROTO_UDP,
9874 		},
9875 	};
9876 	struct rte_flow_item_udp udp = {
9877 		.hdr = {
9878 			.dst_port = rte_cpu_to_be_16(6635),
9879 		},
9880 	};
9881 	struct rte_flow_item_mpls mpls;
9882 	uint8_t *header;
9883 	int ret;
9884 
9885 	ret = parse_vc(ctx, token, str, len, buf, size);
9886 	if (ret < 0)
9887 		return ret;
9888 	/* Nothing else to do if there is no buffer. */
9889 	if (!out)
9890 		return ret;
9891 	if (!out->args.vc.actions_n)
9892 		return -1;
9893 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9894 	/* Point to selected object. */
9895 	ctx->object = out->args.vc.data;
9896 	ctx->objmask = NULL;
9897 	/* Copy the headers to the buffer. */
9898 	action_decap_data = ctx->object;
9899 	*action_decap_data = (struct action_raw_decap_data) {
9900 		.conf = (struct rte_flow_action_raw_decap){
9901 			.data = action_decap_data->data,
9902 		},
9903 		.data = {},
9904 	};
9905 	header = action_decap_data->data;
9906 	if (mplsoudp_decap_conf.select_vlan)
9907 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9908 	else if (mplsoudp_encap_conf.select_ipv4)
9909 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9910 	else
9911 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9912 	memcpy(eth.hdr.dst_addr.addr_bytes,
9913 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9914 	memcpy(eth.hdr.src_addr.addr_bytes,
9915 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9916 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9917 	header += sizeof(struct rte_ether_hdr);
9918 	if (mplsoudp_encap_conf.select_vlan) {
9919 		if (mplsoudp_encap_conf.select_ipv4)
9920 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9921 		else
9922 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9923 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9924 		header += sizeof(struct rte_vlan_hdr);
9925 	}
9926 	if (mplsoudp_encap_conf.select_ipv4) {
9927 		memcpy(header, &ipv4, sizeof(ipv4));
9928 		header += sizeof(ipv4);
9929 	} else {
9930 		memcpy(header, &ipv6, sizeof(ipv6));
9931 		header += sizeof(ipv6);
9932 	}
9933 	memcpy(header, &udp, sizeof(udp));
9934 	header += sizeof(udp);
9935 	memset(&mpls, 0, sizeof(mpls));
9936 	memcpy(header, &mpls, sizeof(mpls));
9937 	header += sizeof(mpls);
9938 	action_decap_data->conf.size = header -
9939 		action_decap_data->data;
9940 	action->conf = &action_decap_data->conf;
9941 	return ret;
9942 }
9943 
9944 static int
9945 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
9946 				const char *str, unsigned int len, void *buf,
9947 				unsigned int size)
9948 {
9949 	struct action_raw_decap_data *action_raw_decap_data;
9950 	struct rte_flow_action *action;
9951 	const struct arg *arg;
9952 	struct buffer *out = buf;
9953 	int ret;
9954 	uint16_t idx;
9955 
9956 	RTE_SET_USED(token);
9957 	RTE_SET_USED(buf);
9958 	RTE_SET_USED(size);
9959 	arg = ARGS_ENTRY_ARB_BOUNDED
9960 		(offsetof(struct action_raw_decap_data, idx),
9961 		 sizeof(((struct action_raw_decap_data *)0)->idx),
9962 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
9963 	if (push_args(ctx, arg))
9964 		return -1;
9965 	ret = parse_int(ctx, token, str, len, NULL, 0);
9966 	if (ret < 0) {
9967 		pop_args(ctx);
9968 		return -1;
9969 	}
9970 	if (!ctx->object)
9971 		return len;
9972 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9973 	action_raw_decap_data = ctx->object;
9974 	idx = action_raw_decap_data->idx;
9975 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
9976 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
9977 	action->conf = &action_raw_decap_data->conf;
9978 	return len;
9979 }
9980 
9981 
9982 static int
9983 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
9984 				const char *str, unsigned int len, void *buf,
9985 				unsigned int size)
9986 {
9987 	struct action_raw_encap_data *action_raw_encap_data;
9988 	struct rte_flow_action *action;
9989 	const struct arg *arg;
9990 	struct buffer *out = buf;
9991 	int ret;
9992 	uint16_t idx;
9993 
9994 	RTE_SET_USED(token);
9995 	RTE_SET_USED(buf);
9996 	RTE_SET_USED(size);
9997 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
9998 		return -1;
9999 	arg = ARGS_ENTRY_ARB_BOUNDED
10000 		(offsetof(struct action_raw_encap_data, idx),
10001 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10002 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10003 	if (push_args(ctx, arg))
10004 		return -1;
10005 	ret = parse_int(ctx, token, str, len, NULL, 0);
10006 	if (ret < 0) {
10007 		pop_args(ctx);
10008 		return -1;
10009 	}
10010 	if (!ctx->object)
10011 		return len;
10012 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10013 	action_raw_encap_data = ctx->object;
10014 	idx = action_raw_encap_data->idx;
10015 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10016 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10017 	action_raw_encap_data->conf.preserve = NULL;
10018 	action->conf = &action_raw_encap_data->conf;
10019 	return len;
10020 }
10021 
10022 static int
10023 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10024 			  const char *str, unsigned int len, void *buf,
10025 			  unsigned int size)
10026 {
10027 	struct buffer *out = buf;
10028 	int ret;
10029 
10030 	ret = parse_vc(ctx, token, str, len, buf, size);
10031 	if (ret < 0)
10032 		return ret;
10033 	/* Nothing else to do if there is no buffer. */
10034 	if (!out)
10035 		return ret;
10036 	if (!out->args.vc.actions_n)
10037 		return -1;
10038 	/* Point to selected object. */
10039 	ctx->object = out->args.vc.data;
10040 	ctx->objmask = NULL;
10041 	return ret;
10042 }
10043 
10044 static int
10045 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10046 			  const char *str, unsigned int len, void *buf,
10047 			  unsigned int size)
10048 {
10049 	struct buffer *out = buf;
10050 	struct rte_flow_action *action;
10051 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10052 	int ret;
10053 
10054 	ret = parse_vc(ctx, token, str, len, buf, size);
10055 	if (ret < 0)
10056 		return ret;
10057 	/* Nothing else to do if there is no buffer. */
10058 	if (!out)
10059 		return ret;
10060 	if (!out->args.vc.actions_n)
10061 		return -1;
10062 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10063 	/* Point to selected object. */
10064 	ctx->object = out->args.vc.data;
10065 	ctx->objmask = NULL;
10066 	/* Copy the headers to the buffer. */
10067 	action_raw_decap_data = ctx->object;
10068 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10069 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10070 	action->conf = &action_raw_decap_data->conf;
10071 	return ret;
10072 }
10073 
10074 static int
10075 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10076 				const char *str, unsigned int len, void *buf,
10077 				unsigned int size)
10078 {
10079 	struct buffer *out = buf;
10080 	struct rte_flow_action *action;
10081 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10082 	int ret;
10083 
10084 	ret = parse_vc(ctx, token, str, len, buf, size);
10085 	if (ret < 0)
10086 		return ret;
10087 	/* Nothing else to do if there is no buffer. */
10088 	if (!out)
10089 		return ret;
10090 	if (!out->args.vc.actions_n)
10091 		return -1;
10092 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10093 	/* Point to selected object. */
10094 	ctx->object = out->args.vc.data;
10095 	ctx->objmask = NULL;
10096 	/* Copy the headers to the buffer. */
10097 	ipv6_ext_remove_data = ctx->object;
10098 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10099 	action->conf = &ipv6_ext_remove_data->conf;
10100 	return ret;
10101 }
10102 
10103 static int
10104 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10105 				      const char *str, unsigned int len, void *buf,
10106 				      unsigned int size)
10107 {
10108 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10109 	struct rte_flow_action *action;
10110 	const struct arg *arg;
10111 	struct buffer *out = buf;
10112 	int ret;
10113 	uint16_t idx;
10114 
10115 	RTE_SET_USED(token);
10116 	RTE_SET_USED(buf);
10117 	RTE_SET_USED(size);
10118 	arg = ARGS_ENTRY_ARB_BOUNDED
10119 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10120 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10121 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10122 	if (push_args(ctx, arg))
10123 		return -1;
10124 	ret = parse_int(ctx, token, str, len, NULL, 0);
10125 	if (ret < 0) {
10126 		pop_args(ctx);
10127 		return -1;
10128 	}
10129 	if (!ctx->object)
10130 		return len;
10131 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10132 	action_ipv6_ext_remove_data = ctx->object;
10133 	idx = action_ipv6_ext_remove_data->idx;
10134 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10135 	action->conf = &action_ipv6_ext_remove_data->conf;
10136 	return len;
10137 }
10138 
10139 static int
10140 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10141 			      const char *str, unsigned int len, void *buf,
10142 			      unsigned int size)
10143 {
10144 	struct buffer *out = buf;
10145 	struct rte_flow_action *action;
10146 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10147 	int ret;
10148 
10149 	ret = parse_vc(ctx, token, str, len, buf, size);
10150 	if (ret < 0)
10151 		return ret;
10152 	/* Nothing else to do if there is no buffer. */
10153 	if (!out)
10154 		return ret;
10155 	if (!out->args.vc.actions_n)
10156 		return -1;
10157 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10158 	/* Point to selected object. */
10159 	ctx->object = out->args.vc.data;
10160 	ctx->objmask = NULL;
10161 	/* Copy the headers to the buffer. */
10162 	ipv6_ext_push_data = ctx->object;
10163 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10164 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10165 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10166 	action->conf = &ipv6_ext_push_data->conf;
10167 	return ret;
10168 }
10169 
10170 static int
10171 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10172 				    const char *str, unsigned int len, void *buf,
10173 				    unsigned int size)
10174 {
10175 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10176 	struct rte_flow_action *action;
10177 	const struct arg *arg;
10178 	struct buffer *out = buf;
10179 	int ret;
10180 	uint16_t idx;
10181 
10182 	RTE_SET_USED(token);
10183 	RTE_SET_USED(buf);
10184 	RTE_SET_USED(size);
10185 	arg = ARGS_ENTRY_ARB_BOUNDED
10186 		(offsetof(struct action_ipv6_ext_push_data, idx),
10187 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10188 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10189 	if (push_args(ctx, arg))
10190 		return -1;
10191 	ret = parse_int(ctx, token, str, len, NULL, 0);
10192 	if (ret < 0) {
10193 		pop_args(ctx);
10194 		return -1;
10195 	}
10196 	if (!ctx->object)
10197 		return len;
10198 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10199 	action_ipv6_ext_push_data = ctx->object;
10200 	idx = action_ipv6_ext_push_data->idx;
10201 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10202 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10203 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10204 	action->conf = &action_ipv6_ext_push_data->conf;
10205 	return len;
10206 }
10207 
10208 static int
10209 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10210 			 const char *str, unsigned int len, void *buf,
10211 			 unsigned int size)
10212 {
10213 	int ret;
10214 
10215 	ret = parse_vc(ctx, token, str, len, buf, size);
10216 	if (ret < 0)
10217 		return ret;
10218 	ret = rte_flow_dynf_metadata_register();
10219 	if (ret < 0)
10220 		return -1;
10221 	return len;
10222 }
10223 
10224 static int
10225 parse_vc_action_sample(struct context *ctx, const struct token *token,
10226 			 const char *str, unsigned int len, void *buf,
10227 			 unsigned int size)
10228 {
10229 	struct buffer *out = buf;
10230 	struct rte_flow_action *action;
10231 	struct action_sample_data *action_sample_data = NULL;
10232 	static struct rte_flow_action end_action = {
10233 		RTE_FLOW_ACTION_TYPE_END, 0
10234 	};
10235 	int ret;
10236 
10237 	ret = parse_vc(ctx, token, str, len, buf, size);
10238 	if (ret < 0)
10239 		return ret;
10240 	/* Nothing else to do if there is no buffer. */
10241 	if (!out)
10242 		return ret;
10243 	if (!out->args.vc.actions_n)
10244 		return -1;
10245 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10246 	/* Point to selected object. */
10247 	ctx->object = out->args.vc.data;
10248 	ctx->objmask = NULL;
10249 	/* Copy the headers to the buffer. */
10250 	action_sample_data = ctx->object;
10251 	action_sample_data->conf.actions = &end_action;
10252 	action->conf = &action_sample_data->conf;
10253 	return ret;
10254 }
10255 
10256 static int
10257 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10258 				const char *str, unsigned int len, void *buf,
10259 				unsigned int size)
10260 {
10261 	struct action_sample_data *action_sample_data;
10262 	struct rte_flow_action *action;
10263 	const struct arg *arg;
10264 	struct buffer *out = buf;
10265 	int ret;
10266 	uint16_t idx;
10267 
10268 	RTE_SET_USED(token);
10269 	RTE_SET_USED(buf);
10270 	RTE_SET_USED(size);
10271 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10272 		return -1;
10273 	arg = ARGS_ENTRY_ARB_BOUNDED
10274 		(offsetof(struct action_sample_data, idx),
10275 		 sizeof(((struct action_sample_data *)0)->idx),
10276 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10277 	if (push_args(ctx, arg))
10278 		return -1;
10279 	ret = parse_int(ctx, token, str, len, NULL, 0);
10280 	if (ret < 0) {
10281 		pop_args(ctx);
10282 		return -1;
10283 	}
10284 	if (!ctx->object)
10285 		return len;
10286 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10287 	action_sample_data = ctx->object;
10288 	idx = action_sample_data->idx;
10289 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10290 	action->conf = &action_sample_data->conf;
10291 	return len;
10292 }
10293 
10294 /** Parse operation for modify_field command. */
10295 static int
10296 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10297 			 const char *str, unsigned int len, void *buf,
10298 			 unsigned int size)
10299 {
10300 	struct rte_flow_action_modify_field *action_modify_field;
10301 	unsigned int i;
10302 
10303 	(void)token;
10304 	(void)buf;
10305 	(void)size;
10306 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10307 		return -1;
10308 	for (i = 0; modify_field_ops[i]; ++i)
10309 		if (!strcmp_partial(modify_field_ops[i], str, len))
10310 			break;
10311 	if (!modify_field_ops[i])
10312 		return -1;
10313 	if (!ctx->object)
10314 		return len;
10315 	action_modify_field = ctx->object;
10316 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10317 	return len;
10318 }
10319 
10320 /** Parse id for modify_field command. */
10321 static int
10322 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10323 			 const char *str, unsigned int len, void *buf,
10324 			 unsigned int size)
10325 {
10326 	struct rte_flow_action_modify_field *action_modify_field;
10327 	unsigned int i;
10328 
10329 	(void)token;
10330 	(void)buf;
10331 	(void)size;
10332 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10333 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10334 		return -1;
10335 	for (i = 0; flow_field_ids[i]; ++i)
10336 		if (!strcmp_partial(flow_field_ids[i], str, len))
10337 			break;
10338 	if (!flow_field_ids[i])
10339 		return -1;
10340 	if (!ctx->object)
10341 		return len;
10342 	action_modify_field = ctx->object;
10343 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10344 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10345 	else
10346 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10347 	return len;
10348 }
10349 
10350 /** Parse level for modify_field command. */
10351 static int
10352 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10353 			 const char *str, unsigned int len, void *buf,
10354 			 unsigned int size)
10355 {
10356 	struct rte_flow_action_modify_field *action;
10357 	struct flex_item *fp = NULL;
10358 	uint32_t val;
10359 	struct buffer *out = buf;
10360 	char *end;
10361 
10362 	(void)token;
10363 	(void)size;
10364 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10365 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10366 		return -1;
10367 	if (!ctx->object)
10368 		return len;
10369 	action = ctx->object;
10370 	errno = 0;
10371 	val = strtoumax(str, &end, 0);
10372 	if (errno || (size_t)(end - str) != len)
10373 		return -1;
10374 	/* No need to validate action template mask value */
10375 	if (out->args.vc.masks) {
10376 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10377 			action->dst.level = val;
10378 		else
10379 			action->src.level = val;
10380 		return len;
10381 	}
10382 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10383 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10384 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10385 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10386 		if (val >= FLEX_MAX_PARSERS_NUM) {
10387 			printf("Bad flex item handle\n");
10388 			return -1;
10389 		}
10390 		fp = flex_items[ctx->port][val];
10391 		if (!fp) {
10392 			printf("Bad flex item handle\n");
10393 			return -1;
10394 		}
10395 	}
10396 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10397 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10398 			action->dst.level = val;
10399 		else
10400 			action->dst.flex_handle = fp->flex_handle;
10401 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10402 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10403 			action->src.level = val;
10404 		else
10405 			action->src.flex_handle = fp->flex_handle;
10406 	}
10407 	return len;
10408 }
10409 
10410 /** Parse the conntrack update, not a rte_flow_action. */
10411 static int
10412 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10413 			 const char *str, unsigned int len, void *buf,
10414 			 unsigned int size)
10415 {
10416 	struct buffer *out = buf;
10417 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10418 
10419 	(void)size;
10420 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10421 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10422 		return -1;
10423 	/* Token name must match. */
10424 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10425 		return -1;
10426 	/* Nothing else to do if there is no buffer. */
10427 	if (!out)
10428 		return len;
10429 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10430 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10431 		ct_modify->new_ct.is_original_dir =
10432 				conntrack_context.is_original_dir;
10433 		ct_modify->direction = 1;
10434 	} else {
10435 		uint32_t old_dir;
10436 
10437 		old_dir = ct_modify->new_ct.is_original_dir;
10438 		memcpy(&ct_modify->new_ct, &conntrack_context,
10439 		       sizeof(conntrack_context));
10440 		ct_modify->new_ct.is_original_dir = old_dir;
10441 		ct_modify->state = 1;
10442 	}
10443 	return len;
10444 }
10445 
10446 /** Parse tokens for destroy command. */
10447 static int
10448 parse_destroy(struct context *ctx, const struct token *token,
10449 	      const char *str, unsigned int len,
10450 	      void *buf, unsigned int size)
10451 {
10452 	struct buffer *out = buf;
10453 
10454 	/* Token name must match. */
10455 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10456 		return -1;
10457 	/* Nothing else to do if there is no buffer. */
10458 	if (!out)
10459 		return len;
10460 	if (!out->command) {
10461 		if (ctx->curr != DESTROY)
10462 			return -1;
10463 		if (sizeof(*out) > size)
10464 			return -1;
10465 		out->command = ctx->curr;
10466 		ctx->objdata = 0;
10467 		ctx->object = out;
10468 		ctx->objmask = NULL;
10469 		out->args.destroy.rule =
10470 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10471 					       sizeof(double));
10472 		return len;
10473 	}
10474 	if (ctx->curr == DESTROY_IS_USER_ID) {
10475 		out->args.destroy.is_user_id = true;
10476 		return len;
10477 	}
10478 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10479 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10480 		return -1;
10481 	ctx->objdata = 0;
10482 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10483 	ctx->objmask = NULL;
10484 	return len;
10485 }
10486 
10487 /** Parse tokens for flush command. */
10488 static int
10489 parse_flush(struct context *ctx, const struct token *token,
10490 	    const char *str, unsigned int len,
10491 	    void *buf, unsigned int size)
10492 {
10493 	struct buffer *out = buf;
10494 
10495 	/* Token name must match. */
10496 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10497 		return -1;
10498 	/* Nothing else to do if there is no buffer. */
10499 	if (!out)
10500 		return len;
10501 	if (!out->command) {
10502 		if (ctx->curr != FLUSH)
10503 			return -1;
10504 		if (sizeof(*out) > size)
10505 			return -1;
10506 		out->command = ctx->curr;
10507 		ctx->objdata = 0;
10508 		ctx->object = out;
10509 		ctx->objmask = NULL;
10510 	}
10511 	return len;
10512 }
10513 
10514 /** Parse tokens for dump command. */
10515 static int
10516 parse_dump(struct context *ctx, const struct token *token,
10517 	    const char *str, unsigned int len,
10518 	    void *buf, unsigned int size)
10519 {
10520 	struct buffer *out = buf;
10521 
10522 	/* Token name must match. */
10523 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10524 		return -1;
10525 	/* Nothing else to do if there is no buffer. */
10526 	if (!out)
10527 		return len;
10528 	if (!out->command) {
10529 		if (ctx->curr != DUMP)
10530 			return -1;
10531 		if (sizeof(*out) > size)
10532 			return -1;
10533 		out->command = ctx->curr;
10534 		ctx->objdata = 0;
10535 		ctx->object = out;
10536 		ctx->objmask = NULL;
10537 		return len;
10538 	}
10539 	switch (ctx->curr) {
10540 	case DUMP_ALL:
10541 	case DUMP_ONE:
10542 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10543 		out->command = ctx->curr;
10544 		ctx->objdata = 0;
10545 		ctx->object = out;
10546 		ctx->objmask = NULL;
10547 		return len;
10548 	case DUMP_IS_USER_ID:
10549 		out->args.dump.is_user_id = true;
10550 		return len;
10551 	default:
10552 		return -1;
10553 	}
10554 }
10555 
10556 /** Parse tokens for query command. */
10557 static int
10558 parse_query(struct context *ctx, const struct token *token,
10559 	    const char *str, unsigned int len,
10560 	    void *buf, unsigned int size)
10561 {
10562 	struct buffer *out = buf;
10563 
10564 	/* Token name must match. */
10565 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10566 		return -1;
10567 	/* Nothing else to do if there is no buffer. */
10568 	if (!out)
10569 		return len;
10570 	if (!out->command) {
10571 		if (ctx->curr != QUERY)
10572 			return -1;
10573 		if (sizeof(*out) > size)
10574 			return -1;
10575 		out->command = ctx->curr;
10576 		ctx->objdata = 0;
10577 		ctx->object = out;
10578 		ctx->objmask = NULL;
10579 	}
10580 	if (ctx->curr == QUERY_IS_USER_ID) {
10581 		out->args.query.is_user_id = true;
10582 		return len;
10583 	}
10584 	return len;
10585 }
10586 
10587 /** Parse action names. */
10588 static int
10589 parse_action(struct context *ctx, const struct token *token,
10590 	     const char *str, unsigned int len,
10591 	     void *buf, unsigned int size)
10592 {
10593 	struct buffer *out = buf;
10594 	const struct arg *arg = pop_args(ctx);
10595 	unsigned int i;
10596 
10597 	(void)size;
10598 	/* Argument is expected. */
10599 	if (!arg)
10600 		return -1;
10601 	/* Parse action name. */
10602 	for (i = 0; next_action[i]; ++i) {
10603 		const struct parse_action_priv *priv;
10604 
10605 		token = &token_list[next_action[i]];
10606 		if (strcmp_partial(token->name, str, len))
10607 			continue;
10608 		priv = token->priv;
10609 		if (!priv)
10610 			goto error;
10611 		if (out)
10612 			memcpy((uint8_t *)ctx->object + arg->offset,
10613 			       &priv->type,
10614 			       arg->size);
10615 		return len;
10616 	}
10617 error:
10618 	push_args(ctx, arg);
10619 	return -1;
10620 }
10621 
10622 /** Parse tokens for list command. */
10623 static int
10624 parse_list(struct context *ctx, const struct token *token,
10625 	   const char *str, unsigned int len,
10626 	   void *buf, unsigned int size)
10627 {
10628 	struct buffer *out = buf;
10629 
10630 	/* Token name must match. */
10631 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10632 		return -1;
10633 	/* Nothing else to do if there is no buffer. */
10634 	if (!out)
10635 		return len;
10636 	if (!out->command) {
10637 		if (ctx->curr != LIST)
10638 			return -1;
10639 		if (sizeof(*out) > size)
10640 			return -1;
10641 		out->command = ctx->curr;
10642 		ctx->objdata = 0;
10643 		ctx->object = out;
10644 		ctx->objmask = NULL;
10645 		out->args.list.group =
10646 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10647 					       sizeof(double));
10648 		return len;
10649 	}
10650 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10651 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10652 		return -1;
10653 	ctx->objdata = 0;
10654 	ctx->object = out->args.list.group + out->args.list.group_n++;
10655 	ctx->objmask = NULL;
10656 	return len;
10657 }
10658 
10659 /** Parse tokens for list all aged flows command. */
10660 static int
10661 parse_aged(struct context *ctx, const struct token *token,
10662 	   const char *str, unsigned int len,
10663 	   void *buf, unsigned int size)
10664 {
10665 	struct buffer *out = buf;
10666 
10667 	/* Token name must match. */
10668 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10669 		return -1;
10670 	/* Nothing else to do if there is no buffer. */
10671 	if (!out)
10672 		return len;
10673 	if (!out->command || out->command == QUEUE) {
10674 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10675 			return -1;
10676 		if (sizeof(*out) > size)
10677 			return -1;
10678 		out->command = ctx->curr;
10679 		ctx->objdata = 0;
10680 		ctx->object = out;
10681 		ctx->objmask = NULL;
10682 	}
10683 	if (ctx->curr == AGED_DESTROY)
10684 		out->args.aged.destroy = 1;
10685 	return len;
10686 }
10687 
10688 /** Parse tokens for isolate command. */
10689 static int
10690 parse_isolate(struct context *ctx, const struct token *token,
10691 	      const char *str, unsigned int len,
10692 	      void *buf, unsigned int size)
10693 {
10694 	struct buffer *out = buf;
10695 
10696 	/* Token name must match. */
10697 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10698 		return -1;
10699 	/* Nothing else to do if there is no buffer. */
10700 	if (!out)
10701 		return len;
10702 	if (!out->command) {
10703 		if (ctx->curr != ISOLATE)
10704 			return -1;
10705 		if (sizeof(*out) > size)
10706 			return -1;
10707 		out->command = ctx->curr;
10708 		ctx->objdata = 0;
10709 		ctx->object = out;
10710 		ctx->objmask = NULL;
10711 	}
10712 	return len;
10713 }
10714 
10715 /** Parse tokens for info/configure command. */
10716 static int
10717 parse_configure(struct context *ctx, const struct token *token,
10718 		const char *str, unsigned int len,
10719 		void *buf, unsigned int size)
10720 {
10721 	struct buffer *out = buf;
10722 
10723 	/* Token name must match. */
10724 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10725 		return -1;
10726 	/* Nothing else to do if there is no buffer. */
10727 	if (!out)
10728 		return len;
10729 	if (!out->command) {
10730 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10731 			return -1;
10732 		if (sizeof(*out) > size)
10733 			return -1;
10734 		out->command = ctx->curr;
10735 		ctx->objdata = 0;
10736 		ctx->object = out;
10737 		ctx->objmask = NULL;
10738 	}
10739 	return len;
10740 }
10741 
10742 /** Parse tokens for template create command. */
10743 static int
10744 parse_template(struct context *ctx, const struct token *token,
10745 	       const char *str, unsigned int len,
10746 	       void *buf, unsigned int size)
10747 {
10748 	struct buffer *out = buf;
10749 
10750 	/* Token name must match. */
10751 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10752 		return -1;
10753 	/* Nothing else to do if there is no buffer. */
10754 	if (!out)
10755 		return len;
10756 	if (!out->command) {
10757 		if (ctx->curr != PATTERN_TEMPLATE &&
10758 		    ctx->curr != ACTIONS_TEMPLATE)
10759 			return -1;
10760 		if (sizeof(*out) > size)
10761 			return -1;
10762 		out->command = ctx->curr;
10763 		ctx->objdata = 0;
10764 		ctx->object = out;
10765 		ctx->objmask = NULL;
10766 		out->args.vc.data = (uint8_t *)out + size;
10767 		return len;
10768 	}
10769 	switch (ctx->curr) {
10770 	case PATTERN_TEMPLATE_CREATE:
10771 		out->args.vc.pattern =
10772 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10773 					       sizeof(double));
10774 		out->args.vc.pat_templ_id = UINT32_MAX;
10775 		out->command = ctx->curr;
10776 		ctx->objdata = 0;
10777 		ctx->object = out;
10778 		ctx->objmask = NULL;
10779 		return len;
10780 	case PATTERN_TEMPLATE_EGRESS:
10781 		out->args.vc.attr.egress = 1;
10782 		return len;
10783 	case PATTERN_TEMPLATE_INGRESS:
10784 		out->args.vc.attr.ingress = 1;
10785 		return len;
10786 	case PATTERN_TEMPLATE_TRANSFER:
10787 		out->args.vc.attr.transfer = 1;
10788 		return len;
10789 	case ACTIONS_TEMPLATE_CREATE:
10790 		out->args.vc.act_templ_id = UINT32_MAX;
10791 		out->command = ctx->curr;
10792 		ctx->objdata = 0;
10793 		ctx->object = out;
10794 		ctx->objmask = NULL;
10795 		return len;
10796 	case ACTIONS_TEMPLATE_SPEC:
10797 		out->args.vc.actions =
10798 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10799 					       sizeof(double));
10800 		ctx->object = out->args.vc.actions;
10801 		ctx->objmask = NULL;
10802 		return len;
10803 	case ACTIONS_TEMPLATE_MASK:
10804 		out->args.vc.masks =
10805 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10806 					       (out->args.vc.actions +
10807 						out->args.vc.actions_n),
10808 					       sizeof(double));
10809 		ctx->object = out->args.vc.masks;
10810 		ctx->objmask = NULL;
10811 		return len;
10812 	case ACTIONS_TEMPLATE_EGRESS:
10813 		out->args.vc.attr.egress = 1;
10814 		return len;
10815 	case ACTIONS_TEMPLATE_INGRESS:
10816 		out->args.vc.attr.ingress = 1;
10817 		return len;
10818 	case ACTIONS_TEMPLATE_TRANSFER:
10819 		out->args.vc.attr.transfer = 1;
10820 		return len;
10821 	default:
10822 		return -1;
10823 	}
10824 }
10825 
10826 /** Parse tokens for template destroy command. */
10827 static int
10828 parse_template_destroy(struct context *ctx, const struct token *token,
10829 		       const char *str, unsigned int len,
10830 		       void *buf, unsigned int size)
10831 {
10832 	struct buffer *out = buf;
10833 	uint32_t *template_id;
10834 
10835 	/* Token name must match. */
10836 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10837 		return -1;
10838 	/* Nothing else to do if there is no buffer. */
10839 	if (!out)
10840 		return len;
10841 	if (!out->command ||
10842 		out->command == PATTERN_TEMPLATE ||
10843 		out->command == ACTIONS_TEMPLATE) {
10844 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
10845 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
10846 			return -1;
10847 		if (sizeof(*out) > size)
10848 			return -1;
10849 		out->command = ctx->curr;
10850 		ctx->objdata = 0;
10851 		ctx->object = out;
10852 		ctx->objmask = NULL;
10853 		out->args.templ_destroy.template_id =
10854 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10855 					       sizeof(double));
10856 		return len;
10857 	}
10858 	template_id = out->args.templ_destroy.template_id
10859 		    + out->args.templ_destroy.template_id_n++;
10860 	if ((uint8_t *)template_id > (uint8_t *)out + size)
10861 		return -1;
10862 	ctx->objdata = 0;
10863 	ctx->object = template_id;
10864 	ctx->objmask = NULL;
10865 	return len;
10866 }
10867 
10868 /** Parse tokens for table create command. */
10869 static int
10870 parse_table(struct context *ctx, const struct token *token,
10871 	    const char *str, unsigned int len,
10872 	    void *buf, unsigned int size)
10873 {
10874 	struct buffer *out = buf;
10875 	uint32_t *template_id;
10876 
10877 	/* Token name must match. */
10878 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10879 		return -1;
10880 	/* Nothing else to do if there is no buffer. */
10881 	if (!out)
10882 		return len;
10883 	if (!out->command) {
10884 		if (ctx->curr != TABLE)
10885 			return -1;
10886 		if (sizeof(*out) > size)
10887 			return -1;
10888 		out->command = ctx->curr;
10889 		ctx->objdata = 0;
10890 		ctx->object = out;
10891 		ctx->objmask = NULL;
10892 		return len;
10893 	}
10894 	switch (ctx->curr) {
10895 	case TABLE_CREATE:
10896 	case TABLE_RESIZE:
10897 		out->command = ctx->curr;
10898 		ctx->objdata = 0;
10899 		ctx->object = out;
10900 		ctx->objmask = NULL;
10901 		out->args.table.id = UINT32_MAX;
10902 		return len;
10903 	case TABLE_PATTERN_TEMPLATE:
10904 		out->args.table.pat_templ_id =
10905 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10906 					       sizeof(double));
10907 		template_id = out->args.table.pat_templ_id
10908 				+ out->args.table.pat_templ_id_n++;
10909 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10910 			return -1;
10911 		ctx->objdata = 0;
10912 		ctx->object = template_id;
10913 		ctx->objmask = NULL;
10914 		return len;
10915 	case TABLE_ACTIONS_TEMPLATE:
10916 		out->args.table.act_templ_id =
10917 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10918 					       (out->args.table.pat_templ_id +
10919 						out->args.table.pat_templ_id_n),
10920 					       sizeof(double));
10921 		template_id = out->args.table.act_templ_id
10922 				+ out->args.table.act_templ_id_n++;
10923 		if ((uint8_t *)template_id > (uint8_t *)out + size)
10924 			return -1;
10925 		ctx->objdata = 0;
10926 		ctx->object = template_id;
10927 		ctx->objmask = NULL;
10928 		return len;
10929 	case TABLE_INGRESS:
10930 		out->args.table.attr.flow_attr.ingress = 1;
10931 		return len;
10932 	case TABLE_EGRESS:
10933 		out->args.table.attr.flow_attr.egress = 1;
10934 		return len;
10935 	case TABLE_TRANSFER:
10936 		out->args.table.attr.flow_attr.transfer = 1;
10937 		return len;
10938 	case TABLE_TRANSFER_WIRE_ORIG:
10939 		if (!out->args.table.attr.flow_attr.transfer)
10940 			return -1;
10941 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
10942 		return len;
10943 	case TABLE_TRANSFER_VPORT_ORIG:
10944 		if (!out->args.table.attr.flow_attr.transfer)
10945 			return -1;
10946 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
10947 		return len;
10948 	case TABLE_RESIZABLE:
10949 		out->args.table.attr.specialize |=
10950 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
10951 		return len;
10952 	case TABLE_RULES_NUMBER:
10953 		ctx->objdata = 0;
10954 		ctx->object = out;
10955 		ctx->objmask = NULL;
10956 		return len;
10957 	case TABLE_RESIZE_ID:
10958 	case TABLE_RESIZE_RULES_NUMBER:
10959 		return len;
10960 	default:
10961 		return -1;
10962 	}
10963 }
10964 
10965 /** Parse tokens for table destroy command. */
10966 static int
10967 parse_table_destroy(struct context *ctx, const struct token *token,
10968 		    const char *str, unsigned int len,
10969 		    void *buf, unsigned int size)
10970 {
10971 	struct buffer *out = buf;
10972 	uint32_t *table_id;
10973 
10974 	/* Token name must match. */
10975 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10976 		return -1;
10977 	/* Nothing else to do if there is no buffer. */
10978 	if (!out)
10979 		return len;
10980 	if (!out->command || out->command == TABLE) {
10981 		if (ctx->curr != TABLE_DESTROY &&
10982 		    ctx->curr != TABLE_RESIZE_COMPLETE)
10983 			return -1;
10984 		if (sizeof(*out) > size)
10985 			return -1;
10986 		out->command = ctx->curr;
10987 		ctx->objdata = 0;
10988 		ctx->object = out;
10989 		ctx->objmask = NULL;
10990 		out->args.table_destroy.table_id =
10991 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10992 					       sizeof(double));
10993 		return len;
10994 	}
10995 	table_id = out->args.table_destroy.table_id
10996 		    + out->args.table_destroy.table_id_n++;
10997 	if ((uint8_t *)table_id > (uint8_t *)out + size)
10998 		return -1;
10999 	ctx->objdata = 0;
11000 	ctx->object = table_id;
11001 	ctx->objmask = NULL;
11002 	return len;
11003 }
11004 
11005 /** Parse tokens for queue create commands. */
11006 static int
11007 parse_qo(struct context *ctx, const struct token *token,
11008 	 const char *str, unsigned int len,
11009 	 void *buf, unsigned int size)
11010 {
11011 	struct buffer *out = buf;
11012 
11013 	/* Token name must match. */
11014 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11015 		return -1;
11016 	/* Nothing else to do if there is no buffer. */
11017 	if (!out)
11018 		return len;
11019 	if (!out->command) {
11020 		if (ctx->curr != QUEUE)
11021 			return -1;
11022 		if (sizeof(*out) > size)
11023 			return -1;
11024 		out->command = ctx->curr;
11025 		ctx->objdata = 0;
11026 		ctx->object = out;
11027 		ctx->objmask = NULL;
11028 		out->args.vc.data = (uint8_t *)out + size;
11029 		return len;
11030 	}
11031 	switch (ctx->curr) {
11032 	case QUEUE_CREATE:
11033 	case QUEUE_UPDATE:
11034 		out->command = ctx->curr;
11035 		ctx->objdata = 0;
11036 		ctx->object = out;
11037 		ctx->objmask = NULL;
11038 		out->args.vc.rule_id = UINT32_MAX;
11039 		return len;
11040 	case QUEUE_TEMPLATE_TABLE:
11041 	case QUEUE_PATTERN_TEMPLATE:
11042 	case QUEUE_ACTIONS_TEMPLATE:
11043 	case QUEUE_CREATE_POSTPONE:
11044 	case QUEUE_RULE_ID:
11045 	case QUEUE_UPDATE_ID:
11046 		return len;
11047 	case ITEM_PATTERN:
11048 		out->args.vc.pattern =
11049 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11050 					       sizeof(double));
11051 		ctx->object = out->args.vc.pattern;
11052 		ctx->objmask = NULL;
11053 		return len;
11054 	case ACTIONS:
11055 		out->args.vc.actions =
11056 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11057 					       (out->args.vc.pattern +
11058 						out->args.vc.pattern_n),
11059 					       sizeof(double));
11060 		ctx->object = out->args.vc.actions;
11061 		ctx->objmask = NULL;
11062 		return len;
11063 	default:
11064 		return -1;
11065 	}
11066 }
11067 
11068 /** Parse tokens for queue destroy command. */
11069 static int
11070 parse_qo_destroy(struct context *ctx, const struct token *token,
11071 		 const char *str, unsigned int len,
11072 		 void *buf, unsigned int size)
11073 {
11074 	struct buffer *out = buf;
11075 	uint64_t *flow_id;
11076 
11077 	/* Token name must match. */
11078 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11079 		return -1;
11080 	/* Nothing else to do if there is no buffer. */
11081 	if (!out)
11082 		return len;
11083 	if (!out->command || out->command == QUEUE) {
11084 		if (ctx->curr != QUEUE_DESTROY &&
11085 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11086 			return -1;
11087 		if (sizeof(*out) > size)
11088 			return -1;
11089 		out->command = ctx->curr;
11090 		ctx->objdata = 0;
11091 		ctx->object = out;
11092 		ctx->objmask = NULL;
11093 		out->args.destroy.rule =
11094 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11095 					       sizeof(double));
11096 		return len;
11097 	}
11098 	switch (ctx->curr) {
11099 	case QUEUE_DESTROY_ID:
11100 		flow_id = out->args.destroy.rule
11101 				+ out->args.destroy.rule_n++;
11102 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11103 			return -1;
11104 		ctx->objdata = 0;
11105 		ctx->object = flow_id;
11106 		ctx->objmask = NULL;
11107 		return len;
11108 	case QUEUE_DESTROY_POSTPONE:
11109 		return len;
11110 	default:
11111 		return -1;
11112 	}
11113 }
11114 
11115 /** Parse tokens for push queue command. */
11116 static int
11117 parse_push(struct context *ctx, const struct token *token,
11118 	   const char *str, unsigned int len,
11119 	   void *buf, unsigned int size)
11120 {
11121 	struct buffer *out = buf;
11122 
11123 	/* Token name must match. */
11124 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11125 		return -1;
11126 	/* Nothing else to do if there is no buffer. */
11127 	if (!out)
11128 		return len;
11129 	if (!out->command) {
11130 		if (ctx->curr != PUSH)
11131 			return -1;
11132 		if (sizeof(*out) > size)
11133 			return -1;
11134 		out->command = ctx->curr;
11135 		ctx->objdata = 0;
11136 		ctx->object = out;
11137 		ctx->objmask = NULL;
11138 		out->args.vc.data = (uint8_t *)out + size;
11139 	}
11140 	return len;
11141 }
11142 
11143 /** Parse tokens for pull command. */
11144 static int
11145 parse_pull(struct context *ctx, const struct token *token,
11146 	   const char *str, unsigned int len,
11147 	   void *buf, unsigned int size)
11148 {
11149 	struct buffer *out = buf;
11150 
11151 	/* Token name must match. */
11152 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11153 		return -1;
11154 	/* Nothing else to do if there is no buffer. */
11155 	if (!out)
11156 		return len;
11157 	if (!out->command) {
11158 		if (ctx->curr != PULL)
11159 			return -1;
11160 		if (sizeof(*out) > size)
11161 			return -1;
11162 		out->command = ctx->curr;
11163 		ctx->objdata = 0;
11164 		ctx->object = out;
11165 		ctx->objmask = NULL;
11166 		out->args.vc.data = (uint8_t *)out + size;
11167 	}
11168 	return len;
11169 }
11170 
11171 /** Parse tokens for hash calculation commands. */
11172 static int
11173 parse_hash(struct context *ctx, const struct token *token,
11174 	 const char *str, unsigned int len,
11175 	 void *buf, unsigned int size)
11176 {
11177 	struct buffer *out = buf;
11178 
11179 	/* Token name must match. */
11180 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11181 		return -1;
11182 	/* Nothing else to do if there is no buffer. */
11183 	if (!out)
11184 		return len;
11185 	if (!out->command) {
11186 		if (ctx->curr != HASH)
11187 			return -1;
11188 		if (sizeof(*out) > size)
11189 			return -1;
11190 		out->command = ctx->curr;
11191 		ctx->objdata = 0;
11192 		ctx->object = out;
11193 		ctx->objmask = NULL;
11194 		out->args.vc.data = (uint8_t *)out + size;
11195 		return len;
11196 	}
11197 	switch (ctx->curr) {
11198 	case HASH_CALC_TABLE:
11199 	case HASH_CALC_PATTERN_INDEX:
11200 		return len;
11201 	case ITEM_PATTERN:
11202 		out->args.vc.pattern =
11203 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11204 					       sizeof(double));
11205 		ctx->object = out->args.vc.pattern;
11206 		ctx->objmask = NULL;
11207 		return len;
11208 	case HASH_CALC_ENCAP:
11209 		out->args.vc.encap_hash = 1;
11210 		return len;
11211 	case ENCAP_HASH_FIELD_SRC_PORT:
11212 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11213 		return len;
11214 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11215 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11216 		return len;
11217 	default:
11218 		return -1;
11219 	}
11220 }
11221 
11222 static int
11223 parse_group(struct context *ctx, const struct token *token,
11224 	    const char *str, unsigned int len,
11225 	    void *buf, unsigned int size)
11226 {
11227 	struct buffer *out = buf;
11228 
11229 	/* Token name must match. */
11230 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11231 		return -1;
11232 	/* Nothing else to do if there is no buffer. */
11233 	if (!out)
11234 		return len;
11235 	if (!out->command) {
11236 		if (ctx->curr != FLOW_GROUP)
11237 			return -1;
11238 		if (sizeof(*out) > size)
11239 			return -1;
11240 		out->command = ctx->curr;
11241 		ctx->objdata = 0;
11242 		ctx->object = out;
11243 		ctx->objmask = NULL;
11244 		out->args.vc.data = (uint8_t *)out + size;
11245 		return len;
11246 	}
11247 	switch (ctx->curr) {
11248 	case GROUP_INGRESS:
11249 		out->args.vc.attr.ingress = 1;
11250 		return len;
11251 	case GROUP_EGRESS:
11252 		out->args.vc.attr.egress = 1;
11253 		return len;
11254 	case GROUP_TRANSFER:
11255 		out->args.vc.attr.transfer = 1;
11256 		return len;
11257 	case GROUP_SET_MISS_ACTIONS:
11258 		out->command = ctx->curr;
11259 		ctx->objdata = 0;
11260 		ctx->object = out;
11261 		ctx->objmask = NULL;
11262 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11263 							       sizeof(double));
11264 		return len;
11265 	default:
11266 		return -1;
11267 	}
11268 }
11269 
11270 static int
11271 parse_flex(struct context *ctx, const struct token *token,
11272 	     const char *str, unsigned int len,
11273 	     void *buf, unsigned int size)
11274 {
11275 	struct buffer *out = buf;
11276 
11277 	/* Token name must match. */
11278 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11279 		return -1;
11280 	/* Nothing else to do if there is no buffer. */
11281 	if (!out)
11282 		return len;
11283 	if (out->command == ZERO) {
11284 		if (ctx->curr != FLEX)
11285 			return -1;
11286 		if (sizeof(*out) > size)
11287 			return -1;
11288 		out->command = ctx->curr;
11289 		ctx->objdata = 0;
11290 		ctx->object = out;
11291 		ctx->objmask = NULL;
11292 	} else {
11293 		switch (ctx->curr) {
11294 		default:
11295 			break;
11296 		case FLEX_ITEM_INIT:
11297 		case FLEX_ITEM_CREATE:
11298 		case FLEX_ITEM_DESTROY:
11299 			out->command = ctx->curr;
11300 			break;
11301 		}
11302 	}
11303 
11304 	return len;
11305 }
11306 
11307 static int
11308 parse_tunnel(struct context *ctx, const struct token *token,
11309 	     const char *str, unsigned int len,
11310 	     void *buf, unsigned int size)
11311 {
11312 	struct buffer *out = buf;
11313 
11314 	/* Token name must match. */
11315 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11316 		return -1;
11317 	/* Nothing else to do if there is no buffer. */
11318 	if (!out)
11319 		return len;
11320 	if (!out->command) {
11321 		if (ctx->curr != TUNNEL)
11322 			return -1;
11323 		if (sizeof(*out) > size)
11324 			return -1;
11325 		out->command = ctx->curr;
11326 		ctx->objdata = 0;
11327 		ctx->object = out;
11328 		ctx->objmask = NULL;
11329 	} else {
11330 		switch (ctx->curr) {
11331 		default:
11332 			break;
11333 		case TUNNEL_CREATE:
11334 		case TUNNEL_DESTROY:
11335 		case TUNNEL_LIST:
11336 			out->command = ctx->curr;
11337 			break;
11338 		case TUNNEL_CREATE_TYPE:
11339 		case TUNNEL_DESTROY_ID:
11340 			ctx->object = &out->args.vc.tunnel_ops;
11341 			break;
11342 		}
11343 	}
11344 
11345 	return len;
11346 }
11347 
11348 /**
11349  * Parse signed/unsigned integers 8 to 64-bit long.
11350  *
11351  * Last argument (ctx->args) is retrieved to determine integer type and
11352  * storage location.
11353  */
11354 static int
11355 parse_int(struct context *ctx, const struct token *token,
11356 	  const char *str, unsigned int len,
11357 	  void *buf, unsigned int size)
11358 {
11359 	const struct arg *arg = pop_args(ctx);
11360 	uintmax_t u;
11361 	char *end;
11362 
11363 	(void)token;
11364 	/* Argument is expected. */
11365 	if (!arg)
11366 		return -1;
11367 	errno = 0;
11368 	u = arg->sign ?
11369 		(uintmax_t)strtoimax(str, &end, 0) :
11370 		strtoumax(str, &end, 0);
11371 	if (errno || (size_t)(end - str) != len)
11372 		goto error;
11373 	if (arg->bounded &&
11374 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11375 			    (intmax_t)u > (intmax_t)arg->max)) ||
11376 	     (!arg->sign && (u < arg->min || u > arg->max))))
11377 		goto error;
11378 	if (!ctx->object)
11379 		return len;
11380 	if (arg->mask) {
11381 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11382 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11383 			goto error;
11384 		return len;
11385 	}
11386 	buf = (uint8_t *)ctx->object + arg->offset;
11387 	size = arg->size;
11388 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11389 		return -1;
11390 objmask:
11391 	switch (size) {
11392 	case sizeof(uint8_t):
11393 		*(uint8_t *)buf = u;
11394 		break;
11395 	case sizeof(uint16_t):
11396 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11397 		break;
11398 	case sizeof(uint8_t [3]):
11399 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11400 		if (!arg->hton) {
11401 			((uint8_t *)buf)[0] = u;
11402 			((uint8_t *)buf)[1] = u >> 8;
11403 			((uint8_t *)buf)[2] = u >> 16;
11404 			break;
11405 		}
11406 #endif
11407 		((uint8_t *)buf)[0] = u >> 16;
11408 		((uint8_t *)buf)[1] = u >> 8;
11409 		((uint8_t *)buf)[2] = u;
11410 		break;
11411 	case sizeof(uint32_t):
11412 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11413 		break;
11414 	case sizeof(uint64_t):
11415 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11416 		break;
11417 	default:
11418 		goto error;
11419 	}
11420 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11421 		u = -1;
11422 		buf = (uint8_t *)ctx->objmask + arg->offset;
11423 		goto objmask;
11424 	}
11425 	return len;
11426 error:
11427 	push_args(ctx, arg);
11428 	return -1;
11429 }
11430 
11431 /**
11432  * Parse a string.
11433  *
11434  * Three arguments (ctx->args) are retrieved from the stack to store data,
11435  * its actual length and address (in that order).
11436  */
11437 static int
11438 parse_string(struct context *ctx, const struct token *token,
11439 	     const char *str, unsigned int len,
11440 	     void *buf, unsigned int size)
11441 {
11442 	const struct arg *arg_data = pop_args(ctx);
11443 	const struct arg *arg_len = pop_args(ctx);
11444 	const struct arg *arg_addr = pop_args(ctx);
11445 	char tmp[16]; /* Ought to be enough. */
11446 	int ret;
11447 
11448 	/* Arguments are expected. */
11449 	if (!arg_data)
11450 		return -1;
11451 	if (!arg_len) {
11452 		push_args(ctx, arg_data);
11453 		return -1;
11454 	}
11455 	if (!arg_addr) {
11456 		push_args(ctx, arg_len);
11457 		push_args(ctx, arg_data);
11458 		return -1;
11459 	}
11460 	size = arg_data->size;
11461 	/* Bit-mask fill is not supported. */
11462 	if (arg_data->mask || size < len)
11463 		goto error;
11464 	if (!ctx->object)
11465 		return len;
11466 	/* Let parse_int() fill length information first. */
11467 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11468 	if (ret < 0)
11469 		goto error;
11470 	push_args(ctx, arg_len);
11471 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11472 	if (ret < 0) {
11473 		pop_args(ctx);
11474 		goto error;
11475 	}
11476 	buf = (uint8_t *)ctx->object + arg_data->offset;
11477 	/* Output buffer is not necessarily NUL-terminated. */
11478 	memcpy(buf, str, len);
11479 	memset((uint8_t *)buf + len, 0x00, size - len);
11480 	if (ctx->objmask)
11481 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11482 	/* Save address if requested. */
11483 	if (arg_addr->size) {
11484 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11485 		       (void *[]){
11486 			(uint8_t *)ctx->object + arg_data->offset
11487 		       },
11488 		       arg_addr->size);
11489 		if (ctx->objmask)
11490 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11491 			       (void *[]){
11492 				(uint8_t *)ctx->objmask + arg_data->offset
11493 			       },
11494 			       arg_addr->size);
11495 	}
11496 	return len;
11497 error:
11498 	push_args(ctx, arg_addr);
11499 	push_args(ctx, arg_len);
11500 	push_args(ctx, arg_data);
11501 	return -1;
11502 }
11503 
11504 static int
11505 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11506 {
11507 	const uint8_t *head = dst;
11508 	uint32_t left;
11509 
11510 	if (*size == 0)
11511 		return -1;
11512 
11513 	left = *size;
11514 
11515 	/* Convert chars to bytes */
11516 	while (left) {
11517 		char tmp[3], *end = tmp;
11518 		uint32_t read_lim = left & 1 ? 1 : 2;
11519 
11520 		snprintf(tmp, read_lim + 1, "%s", src);
11521 		*dst = strtoul(tmp, &end, 16);
11522 		if (*end) {
11523 			*dst = 0;
11524 			*size = (uint32_t)(dst - head);
11525 			return -1;
11526 		}
11527 		left -= read_lim;
11528 		src += read_lim;
11529 		dst++;
11530 	}
11531 	*dst = 0;
11532 	*size = (uint32_t)(dst - head);
11533 	return 0;
11534 }
11535 
11536 static int
11537 parse_hex(struct context *ctx, const struct token *token,
11538 		const char *str, unsigned int len,
11539 		void *buf, unsigned int size)
11540 {
11541 	const struct arg *arg_data = pop_args(ctx);
11542 	const struct arg *arg_len = pop_args(ctx);
11543 	const struct arg *arg_addr = pop_args(ctx);
11544 	char tmp[16]; /* Ought to be enough. */
11545 	int ret;
11546 	unsigned int hexlen = len;
11547 	unsigned int length = 256;
11548 	uint8_t hex_tmp[length];
11549 
11550 	/* Arguments are expected. */
11551 	if (!arg_data)
11552 		return -1;
11553 	if (!arg_len) {
11554 		push_args(ctx, arg_data);
11555 		return -1;
11556 	}
11557 	if (!arg_addr) {
11558 		push_args(ctx, arg_len);
11559 		push_args(ctx, arg_data);
11560 		return -1;
11561 	}
11562 	size = arg_data->size;
11563 	/* Bit-mask fill is not supported. */
11564 	if (arg_data->mask)
11565 		goto error;
11566 	if (!ctx->object)
11567 		return len;
11568 
11569 	/* translate bytes string to array. */
11570 	if (str[0] == '0' && ((str[1] == 'x') ||
11571 			(str[1] == 'X'))) {
11572 		str += 2;
11573 		hexlen -= 2;
11574 	}
11575 	if (hexlen > length)
11576 		goto error;
11577 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11578 	if (ret < 0)
11579 		goto error;
11580 	/* Check the converted binary fits into data buffer. */
11581 	if (hexlen > size)
11582 		goto error;
11583 	/* Let parse_int() fill length information first. */
11584 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11585 	if (ret < 0)
11586 		goto error;
11587 	/* Save length if requested. */
11588 	if (arg_len->size) {
11589 		push_args(ctx, arg_len);
11590 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11591 		if (ret < 0) {
11592 			pop_args(ctx);
11593 			goto error;
11594 		}
11595 	}
11596 	buf = (uint8_t *)ctx->object + arg_data->offset;
11597 	/* Output buffer is not necessarily NUL-terminated. */
11598 	memcpy(buf, hex_tmp, hexlen);
11599 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11600 	if (ctx->objmask)
11601 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11602 					0xff, hexlen);
11603 	/* Save address if requested. */
11604 	if (arg_addr->size) {
11605 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11606 		       (void *[]){
11607 			(uint8_t *)ctx->object + arg_data->offset
11608 		       },
11609 		       arg_addr->size);
11610 		if (ctx->objmask)
11611 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11612 			       (void *[]){
11613 				(uint8_t *)ctx->objmask + arg_data->offset
11614 			       },
11615 			       arg_addr->size);
11616 	}
11617 	return len;
11618 error:
11619 	push_args(ctx, arg_addr);
11620 	push_args(ctx, arg_len);
11621 	push_args(ctx, arg_data);
11622 	return -1;
11623 
11624 }
11625 
11626 /**
11627  * Parse a zero-ended string.
11628  */
11629 static int
11630 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11631 	     const char *str, unsigned int len,
11632 	     void *buf, unsigned int size)
11633 {
11634 	const struct arg *arg_data = pop_args(ctx);
11635 
11636 	/* Arguments are expected. */
11637 	if (!arg_data)
11638 		return -1;
11639 	size = arg_data->size;
11640 	/* Bit-mask fill is not supported. */
11641 	if (arg_data->mask || size < len + 1)
11642 		goto error;
11643 	if (!ctx->object)
11644 		return len;
11645 	buf = (uint8_t *)ctx->object + arg_data->offset;
11646 	strncpy(buf, str, len);
11647 	if (ctx->objmask)
11648 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11649 	return len;
11650 error:
11651 	push_args(ctx, arg_data);
11652 	return -1;
11653 }
11654 
11655 /**
11656  * Parse a MAC address.
11657  *
11658  * Last argument (ctx->args) is retrieved to determine storage size and
11659  * location.
11660  */
11661 static int
11662 parse_mac_addr(struct context *ctx, const struct token *token,
11663 	       const char *str, unsigned int len,
11664 	       void *buf, unsigned int size)
11665 {
11666 	const struct arg *arg = pop_args(ctx);
11667 	struct rte_ether_addr tmp;
11668 	int ret;
11669 
11670 	(void)token;
11671 	/* Argument is expected. */
11672 	if (!arg)
11673 		return -1;
11674 	size = arg->size;
11675 	/* Bit-mask fill is not supported. */
11676 	if (arg->mask || size != sizeof(tmp))
11677 		goto error;
11678 	/* Only network endian is supported. */
11679 	if (!arg->hton)
11680 		goto error;
11681 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11682 	if (ret < 0 || (unsigned int)ret != len)
11683 		goto error;
11684 	if (!ctx->object)
11685 		return len;
11686 	buf = (uint8_t *)ctx->object + arg->offset;
11687 	memcpy(buf, &tmp, size);
11688 	if (ctx->objmask)
11689 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11690 	return len;
11691 error:
11692 	push_args(ctx, arg);
11693 	return -1;
11694 }
11695 
11696 /**
11697  * Parse an IPv4 address.
11698  *
11699  * Last argument (ctx->args) is retrieved to determine storage size and
11700  * location.
11701  */
11702 static int
11703 parse_ipv4_addr(struct context *ctx, const struct token *token,
11704 		const char *str, unsigned int len,
11705 		void *buf, unsigned int size)
11706 {
11707 	const struct arg *arg = pop_args(ctx);
11708 	char str2[len + 1];
11709 	struct in_addr tmp;
11710 	int ret;
11711 
11712 	/* Argument is expected. */
11713 	if (!arg)
11714 		return -1;
11715 	size = arg->size;
11716 	/* Bit-mask fill is not supported. */
11717 	if (arg->mask || size != sizeof(tmp))
11718 		goto error;
11719 	/* Only network endian is supported. */
11720 	if (!arg->hton)
11721 		goto error;
11722 	memcpy(str2, str, len);
11723 	str2[len] = '\0';
11724 	ret = inet_pton(AF_INET, str2, &tmp);
11725 	if (ret != 1) {
11726 		/* Attempt integer parsing. */
11727 		push_args(ctx, arg);
11728 		return parse_int(ctx, token, str, len, buf, size);
11729 	}
11730 	if (!ctx->object)
11731 		return len;
11732 	buf = (uint8_t *)ctx->object + arg->offset;
11733 	memcpy(buf, &tmp, size);
11734 	if (ctx->objmask)
11735 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11736 	return len;
11737 error:
11738 	push_args(ctx, arg);
11739 	return -1;
11740 }
11741 
11742 /**
11743  * Parse an IPv6 address.
11744  *
11745  * Last argument (ctx->args) is retrieved to determine storage size and
11746  * location.
11747  */
11748 static int
11749 parse_ipv6_addr(struct context *ctx, const struct token *token,
11750 		const char *str, unsigned int len,
11751 		void *buf, unsigned int size)
11752 {
11753 	const struct arg *arg = pop_args(ctx);
11754 	char str2[len + 1];
11755 	struct in6_addr tmp;
11756 	int ret;
11757 
11758 	(void)token;
11759 	/* Argument is expected. */
11760 	if (!arg)
11761 		return -1;
11762 	size = arg->size;
11763 	/* Bit-mask fill is not supported. */
11764 	if (arg->mask || size != sizeof(tmp))
11765 		goto error;
11766 	/* Only network endian is supported. */
11767 	if (!arg->hton)
11768 		goto error;
11769 	memcpy(str2, str, len);
11770 	str2[len] = '\0';
11771 	ret = inet_pton(AF_INET6, str2, &tmp);
11772 	if (ret != 1)
11773 		goto error;
11774 	if (!ctx->object)
11775 		return len;
11776 	buf = (uint8_t *)ctx->object + arg->offset;
11777 	memcpy(buf, &tmp, size);
11778 	if (ctx->objmask)
11779 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11780 	return len;
11781 error:
11782 	push_args(ctx, arg);
11783 	return -1;
11784 }
11785 
11786 /** Boolean values (even indices stand for false). */
11787 static const char *const boolean_name[] = {
11788 	"0", "1",
11789 	"false", "true",
11790 	"no", "yes",
11791 	"N", "Y",
11792 	"off", "on",
11793 	NULL,
11794 };
11795 
11796 /**
11797  * Parse a boolean value.
11798  *
11799  * Last argument (ctx->args) is retrieved to determine storage size and
11800  * location.
11801  */
11802 static int
11803 parse_boolean(struct context *ctx, const struct token *token,
11804 	      const char *str, unsigned int len,
11805 	      void *buf, unsigned int size)
11806 {
11807 	const struct arg *arg = pop_args(ctx);
11808 	unsigned int i;
11809 	int ret;
11810 
11811 	/* Argument is expected. */
11812 	if (!arg)
11813 		return -1;
11814 	for (i = 0; boolean_name[i]; ++i)
11815 		if (!strcmp_partial(boolean_name[i], str, len))
11816 			break;
11817 	/* Process token as integer. */
11818 	if (boolean_name[i])
11819 		str = i & 1 ? "1" : "0";
11820 	push_args(ctx, arg);
11821 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11822 	return ret > 0 ? (int)len : ret;
11823 }
11824 
11825 /** Parse port and update context. */
11826 static int
11827 parse_port(struct context *ctx, const struct token *token,
11828 	   const char *str, unsigned int len,
11829 	   void *buf, unsigned int size)
11830 {
11831 	struct buffer *out = &(struct buffer){ .port = 0 };
11832 	int ret;
11833 
11834 	if (buf)
11835 		out = buf;
11836 	else {
11837 		ctx->objdata = 0;
11838 		ctx->object = out;
11839 		ctx->objmask = NULL;
11840 		size = sizeof(*out);
11841 	}
11842 	ret = parse_int(ctx, token, str, len, out, size);
11843 	if (ret >= 0)
11844 		ctx->port = out->port;
11845 	if (!buf)
11846 		ctx->object = NULL;
11847 	return ret;
11848 }
11849 
11850 /** Parse tokens for shared indirect actions. */
11851 static int
11852 parse_ia_port(struct context *ctx, const struct token *token,
11853 	      const char *str, unsigned int len,
11854 	      void *buf, unsigned int size)
11855 {
11856 	struct rte_flow_action *action = ctx->object;
11857 	uint32_t id;
11858 	int ret;
11859 
11860 	(void)buf;
11861 	(void)size;
11862 	ctx->objdata = 0;
11863 	ctx->object = &id;
11864 	ctx->objmask = NULL;
11865 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11866 	ctx->object = action;
11867 	if (ret != (int)len)
11868 		return ret;
11869 	/* set indirect action */
11870 	if (action)
11871 		action->conf = (void *)(uintptr_t)id;
11872 	return ret;
11873 }
11874 
11875 static int
11876 parse_ia_id2ptr(struct context *ctx, const struct token *token,
11877 		const char *str, unsigned int len,
11878 		void *buf, unsigned int size)
11879 {
11880 	struct rte_flow_action *action = ctx->object;
11881 	uint32_t id;
11882 	int ret;
11883 
11884 	(void)buf;
11885 	(void)size;
11886 	ctx->objdata = 0;
11887 	ctx->object = &id;
11888 	ctx->objmask = NULL;
11889 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11890 	ctx->object = action;
11891 	if (ret != (int)len)
11892 		return ret;
11893 	/* set indirect action */
11894 	if (action) {
11895 		portid_t port_id = ctx->port;
11896 		if (ctx->prev == INDIRECT_ACTION_PORT)
11897 			port_id = (portid_t)(uintptr_t)action->conf;
11898 		action->conf = port_action_handle_get_by_id(port_id, id);
11899 		ret = (action->conf) ? ret : -1;
11900 	}
11901 	return ret;
11902 }
11903 
11904 static int
11905 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
11906 		    const char *str, unsigned int len,
11907 		    __rte_unused void *buf, __rte_unused unsigned int size)
11908 {
11909 	struct rte_flow_action *action = ctx->object;
11910 	struct rte_flow_action_indirect_list *action_conf;
11911 	const struct indlst_conf *indlst_conf;
11912 	uint32_t id;
11913 	int ret;
11914 
11915 	if (!action)
11916 		return -1;
11917 	ctx->objdata = 0;
11918 	ctx->object = &id;
11919 	ctx->objmask = NULL;
11920 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11921 	if (ret != (int)len)
11922 		return ret;
11923 	ctx->object = action;
11924 	action_conf = (void *)(uintptr_t)action->conf;
11925 	action_conf->conf = NULL;
11926 	switch (ctx->curr) {
11927 	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
11928 	action_conf->handle = (typeof(action_conf->handle))
11929 				port_action_handle_get_by_id(ctx->port, id);
11930 		if (!action_conf->handle) {
11931 			printf("no indirect list handle for id %u\n", id);
11932 			return -1;
11933 		}
11934 		break;
11935 	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
11936 		indlst_conf = indirect_action_list_conf_get(id);
11937 		if (!indlst_conf)
11938 			return -1;
11939 		action_conf->conf = (const void **)indlst_conf->conf;
11940 		break;
11941 	default:
11942 		break;
11943 	}
11944 	return ret;
11945 }
11946 
11947 static int
11948 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
11949 		const char *str, unsigned int len,
11950 		void *buf, unsigned int size)
11951 {
11952 	struct rte_flow_action *action = ctx->object;
11953 	struct rte_flow_action_meter_mark *meter;
11954 	struct rte_flow_meter_profile *profile = NULL;
11955 	uint32_t id = 0;
11956 	int ret;
11957 
11958 	(void)buf;
11959 	(void)size;
11960 	ctx->objdata = 0;
11961 	ctx->object = &id;
11962 	ctx->objmask = NULL;
11963 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11964 	ctx->object = action;
11965 	if (ret != (int)len)
11966 		return ret;
11967 	/* set meter profile */
11968 	if (action) {
11969 		meter = (struct rte_flow_action_meter_mark *)
11970 			(uintptr_t)(action->conf);
11971 		profile = port_meter_profile_get_by_id(ctx->port, id);
11972 		meter->profile = profile;
11973 		ret = (profile) ? ret : -1;
11974 	}
11975 	return ret;
11976 }
11977 
11978 static int
11979 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
11980 		const char *str, unsigned int len,
11981 		void *buf, unsigned int size)
11982 {
11983 	struct rte_flow_action *action = ctx->object;
11984 	struct rte_flow_action_meter_mark *meter;
11985 	struct rte_flow_meter_policy *policy = NULL;
11986 	uint32_t id = 0;
11987 	int ret;
11988 
11989 	(void)buf;
11990 	(void)size;
11991 	ctx->objdata = 0;
11992 	ctx->object = &id;
11993 	ctx->objmask = NULL;
11994 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
11995 	ctx->object = action;
11996 	if (ret != (int)len)
11997 		return ret;
11998 	/* set meter policy */
11999 	if (action) {
12000 		meter = (struct rte_flow_action_meter_mark *)
12001 			(uintptr_t)(action->conf);
12002 		policy = port_meter_policy_get_by_id(ctx->port, id);
12003 		meter->policy = policy;
12004 		ret = (policy) ? ret : -1;
12005 	}
12006 	return ret;
12007 }
12008 
12009 /** Parse set command, initialize output buffer for subsequent tokens. */
12010 static int
12011 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12012 			  const char *str, unsigned int len,
12013 			  void *buf, unsigned int size)
12014 {
12015 	struct buffer *out = buf;
12016 
12017 	/* Token name must match. */
12018 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12019 		return -1;
12020 	/* Nothing else to do if there is no buffer. */
12021 	if (!out)
12022 		return len;
12023 	/* Make sure buffer is large enough. */
12024 	if (size < sizeof(*out))
12025 		return -1;
12026 	ctx->objdata = 0;
12027 	ctx->objmask = NULL;
12028 	ctx->object = out;
12029 	if (!out->command)
12030 		return -1;
12031 	out->command = ctx->curr;
12032 	/* For encap/decap we need is pattern */
12033 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12034 						       sizeof(double));
12035 	return len;
12036 }
12037 
12038 /** Parse set command, initialize output buffer for subsequent tokens. */
12039 static int
12040 parse_set_sample_action(struct context *ctx, const struct token *token,
12041 			  const char *str, unsigned int len,
12042 			  void *buf, unsigned int size)
12043 {
12044 	struct buffer *out = buf;
12045 
12046 	/* Token name must match. */
12047 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12048 		return -1;
12049 	/* Nothing else to do if there is no buffer. */
12050 	if (!out)
12051 		return len;
12052 	/* Make sure buffer is large enough. */
12053 	if (size < sizeof(*out))
12054 		return -1;
12055 	ctx->objdata = 0;
12056 	ctx->objmask = NULL;
12057 	ctx->object = out;
12058 	if (!out->command)
12059 		return -1;
12060 	out->command = ctx->curr;
12061 	/* For sampler we need is actions */
12062 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12063 						       sizeof(double));
12064 	return len;
12065 }
12066 
12067 /** Parse set command, initialize output buffer for subsequent tokens. */
12068 static int
12069 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12070 			  const char *str, unsigned int len,
12071 			  void *buf, unsigned int size)
12072 {
12073 	struct buffer *out = buf;
12074 
12075 	/* Token name must match. */
12076 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12077 		return -1;
12078 	/* Nothing else to do if there is no buffer. */
12079 	if (!out)
12080 		return len;
12081 	/* Make sure buffer is large enough. */
12082 	if (size < sizeof(*out))
12083 		return -1;
12084 	ctx->objdata = 0;
12085 	ctx->objmask = NULL;
12086 	ctx->object = out;
12087 	if (!out->command)
12088 		return -1;
12089 	out->command = ctx->curr;
12090 	/* For ipv6_ext_push/remove we need is pattern */
12091 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12092 						       sizeof(double));
12093 	return len;
12094 }
12095 
12096 /**
12097  * Parse set raw_encap/raw_decap command,
12098  * initialize output buffer for subsequent tokens.
12099  */
12100 static int
12101 parse_set_init(struct context *ctx, const struct token *token,
12102 	       const char *str, unsigned int len,
12103 	       void *buf, unsigned int size)
12104 {
12105 	struct buffer *out = buf;
12106 
12107 	/* Token name must match. */
12108 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12109 		return -1;
12110 	/* Nothing else to do if there is no buffer. */
12111 	if (!out)
12112 		return len;
12113 	/* Make sure buffer is large enough. */
12114 	if (size < sizeof(*out))
12115 		return -1;
12116 	/* Initialize buffer. */
12117 	memset(out, 0x00, sizeof(*out));
12118 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12119 	ctx->objdata = 0;
12120 	ctx->object = out;
12121 	ctx->objmask = NULL;
12122 	if (!out->command) {
12123 		if (ctx->curr != SET)
12124 			return -1;
12125 		if (sizeof(*out) > size)
12126 			return -1;
12127 		out->command = ctx->curr;
12128 		out->args.vc.data = (uint8_t *)out + size;
12129 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12130 						       sizeof(double));
12131 	}
12132 	return len;
12133 }
12134 
12135 /*
12136  * Replace testpmd handles in a flex flow item with real values.
12137  */
12138 static int
12139 parse_flex_handle(struct context *ctx, const struct token *token,
12140 		  const char *str, unsigned int len,
12141 		  void *buf, unsigned int size)
12142 {
12143 	struct rte_flow_item_flex *spec, *mask;
12144 	const struct rte_flow_item_flex *src_spec, *src_mask;
12145 	const struct arg *arg = pop_args(ctx);
12146 	uint32_t offset;
12147 	uint16_t handle;
12148 	int ret;
12149 
12150 	if (!arg) {
12151 		printf("Bad environment\n");
12152 		return -1;
12153 	}
12154 	offset = arg->offset;
12155 	push_args(ctx, arg);
12156 	ret = parse_int(ctx, token, str, len, buf, size);
12157 	if (ret <= 0 || !ctx->object)
12158 		return ret;
12159 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12160 		printf("Bad port\n");
12161 		return -1;
12162 	}
12163 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12164 		const struct flex_item *fp;
12165 		spec = ctx->object;
12166 		handle = (uint16_t)(uintptr_t)spec->handle;
12167 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12168 			printf("Bad flex item handle\n");
12169 			return -1;
12170 		}
12171 		fp = flex_items[ctx->port][handle];
12172 		if (!fp) {
12173 			printf("Bad flex item handle\n");
12174 			return -1;
12175 		}
12176 		spec->handle = fp->flex_handle;
12177 		mask = spec + 2; /* spec, last, mask */
12178 		mask->handle = fp->flex_handle;
12179 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12180 		handle = (uint16_t)(uintptr_t)
12181 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12182 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12183 			printf("Bad pattern handle\n");
12184 			return -1;
12185 		}
12186 		src_spec = &flex_patterns[handle].spec;
12187 		src_mask = &flex_patterns[handle].mask;
12188 		spec = ctx->object;
12189 		mask = spec + 2; /* spec, last, mask */
12190 		/* fill flow rule spec and mask parameters */
12191 		spec->length = src_spec->length;
12192 		spec->pattern = src_spec->pattern;
12193 		mask->length = src_mask->length;
12194 		mask->pattern = src_mask->pattern;
12195 	} else {
12196 		printf("Bad arguments - unknown flex item offset\n");
12197 		return -1;
12198 	}
12199 	return ret;
12200 }
12201 
12202 /** Parse Meter color name */
12203 static int
12204 parse_meter_color(struct context *ctx, const struct token *token,
12205 		  const char *str, unsigned int len, void *buf,
12206 		  unsigned int size)
12207 {
12208 	struct rte_flow_item_meter_color *meter_color;
12209 	unsigned int i;
12210 
12211 	(void)token;
12212 	(void)buf;
12213 	(void)size;
12214 	for (i = 0; meter_colors[i]; ++i)
12215 		if (!strcmp_partial(meter_colors[i], str, len))
12216 			break;
12217 	if (!meter_colors[i])
12218 		return -1;
12219 	if (!ctx->object)
12220 		return len;
12221 	meter_color = ctx->object;
12222 	meter_color->color = (enum rte_color)i;
12223 	return len;
12224 }
12225 
12226 /** Parse Insertion Table Type name */
12227 static int
12228 parse_insertion_table_type(struct context *ctx, const struct token *token,
12229 			   const char *str, unsigned int len, void *buf,
12230 			   unsigned int size)
12231 {
12232 	const struct arg *arg = pop_args(ctx);
12233 	unsigned int i;
12234 	char tmp[2];
12235 	int ret;
12236 
12237 	(void)size;
12238 	/* Argument is expected. */
12239 	if (!arg)
12240 		return -1;
12241 	for (i = 0; table_insertion_types[i]; ++i)
12242 		if (!strcmp_partial(table_insertion_types[i], str, len))
12243 			break;
12244 	if (!table_insertion_types[i])
12245 		return -1;
12246 	push_args(ctx, arg);
12247 	snprintf(tmp, sizeof(tmp), "%u", i);
12248 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12249 	return ret > 0 ? (int)len : ret;
12250 }
12251 
12252 /** Parse Hash Calculation Table Type name */
12253 static int
12254 parse_hash_table_type(struct context *ctx, const struct token *token,
12255 		      const char *str, unsigned int len, void *buf,
12256 		      unsigned int size)
12257 {
12258 	const struct arg *arg = pop_args(ctx);
12259 	unsigned int i;
12260 	char tmp[2];
12261 	int ret;
12262 
12263 	(void)size;
12264 	/* Argument is expected. */
12265 	if (!arg)
12266 		return -1;
12267 	for (i = 0; table_hash_funcs[i]; ++i)
12268 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12269 			break;
12270 	if (!table_hash_funcs[i])
12271 		return -1;
12272 	push_args(ctx, arg);
12273 	snprintf(tmp, sizeof(tmp), "%u", i);
12274 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12275 	return ret > 0 ? (int)len : ret;
12276 }
12277 
12278 static int
12279 parse_name_to_index(struct context *ctx, const struct token *token,
12280 		    const char *str, unsigned int len, void *buf,
12281 		    unsigned int size,
12282 		    const char *const names[], size_t names_size, uint32_t *dst)
12283 {
12284 	int ret;
12285 	uint32_t i;
12286 
12287 	RTE_SET_USED(token);
12288 	RTE_SET_USED(buf);
12289 	RTE_SET_USED(size);
12290 	if (!ctx->object)
12291 		return len;
12292 	for (i = 0; i < names_size; i++) {
12293 		if (!names[i])
12294 			continue;
12295 		ret = strcmp_partial(names[i], str,
12296 				     RTE_MIN(len, strlen(names[i])));
12297 		if (!ret) {
12298 			*dst = i;
12299 			return len;
12300 		}
12301 	}
12302 	return -1;
12303 }
12304 
12305 static const char *const quota_mode_names[] = {
12306 	NULL,
12307 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12308 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12309 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12310 };
12311 
12312 static const char *const quota_state_names[] = {
12313 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12314 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12315 };
12316 
12317 static const char *const quota_update_names[] = {
12318 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12319 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12320 };
12321 
12322 static const char *const query_update_mode_names[] = {
12323 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12324 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12325 };
12326 
12327 static int
12328 parse_quota_state_name(struct context *ctx, const struct token *token,
12329 		       const char *str, unsigned int len, void *buf,
12330 		       unsigned int size)
12331 {
12332 	struct rte_flow_item_quota *quota = ctx->object;
12333 
12334 	return parse_name_to_index(ctx, token, str, len, buf, size,
12335 				   quota_state_names,
12336 				   RTE_DIM(quota_state_names),
12337 				   (uint32_t *)&quota->state);
12338 }
12339 
12340 static int
12341 parse_quota_mode_name(struct context *ctx, const struct token *token,
12342 		      const char *str, unsigned int len, void *buf,
12343 		      unsigned int size)
12344 {
12345 	struct rte_flow_action_quota *quota = ctx->object;
12346 
12347 	return parse_name_to_index(ctx, token, str, len, buf, size,
12348 				   quota_mode_names,
12349 				   RTE_DIM(quota_mode_names),
12350 				   (uint32_t *)&quota->mode);
12351 }
12352 
12353 static int
12354 parse_quota_update_name(struct context *ctx, const struct token *token,
12355 			const char *str, unsigned int len, void *buf,
12356 			unsigned int size)
12357 {
12358 	struct rte_flow_update_quota *update = ctx->object;
12359 
12360 	return parse_name_to_index(ctx, token, str, len, buf, size,
12361 				   quota_update_names,
12362 				   RTE_DIM(quota_update_names),
12363 				   (uint32_t *)&update->op);
12364 }
12365 
12366 static int
12367 parse_qu_mode_name(struct context *ctx, const struct token *token,
12368 		   const char *str, unsigned int len, void *buf,
12369 		   unsigned int size)
12370 {
12371 	struct buffer *out = ctx->object;
12372 
12373 	return parse_name_to_index(ctx, token, str, len, buf, size,
12374 				   query_update_mode_names,
12375 				   RTE_DIM(query_update_mode_names),
12376 				   (uint32_t *)&out->args.ia.qu_mode);
12377 }
12378 
12379 /** No completion. */
12380 static int
12381 comp_none(struct context *ctx, const struct token *token,
12382 	  unsigned int ent, char *buf, unsigned int size)
12383 {
12384 	(void)ctx;
12385 	(void)token;
12386 	(void)ent;
12387 	(void)buf;
12388 	(void)size;
12389 	return 0;
12390 }
12391 
12392 /** Complete boolean values. */
12393 static int
12394 comp_boolean(struct context *ctx, const struct token *token,
12395 	     unsigned int ent, char *buf, unsigned int size)
12396 {
12397 	unsigned int i;
12398 
12399 	(void)ctx;
12400 	(void)token;
12401 	for (i = 0; boolean_name[i]; ++i)
12402 		if (buf && i == ent)
12403 			return strlcpy(buf, boolean_name[i], size);
12404 	if (buf)
12405 		return -1;
12406 	return i;
12407 }
12408 
12409 /** Complete action names. */
12410 static int
12411 comp_action(struct context *ctx, const struct token *token,
12412 	    unsigned int ent, char *buf, unsigned int size)
12413 {
12414 	unsigned int i;
12415 
12416 	(void)ctx;
12417 	(void)token;
12418 	for (i = 0; next_action[i]; ++i)
12419 		if (buf && i == ent)
12420 			return strlcpy(buf, token_list[next_action[i]].name,
12421 				       size);
12422 	if (buf)
12423 		return -1;
12424 	return i;
12425 }
12426 
12427 /** Complete available ports. */
12428 static int
12429 comp_port(struct context *ctx, const struct token *token,
12430 	  unsigned int ent, char *buf, unsigned int size)
12431 {
12432 	unsigned int i = 0;
12433 	portid_t p;
12434 
12435 	(void)ctx;
12436 	(void)token;
12437 	RTE_ETH_FOREACH_DEV(p) {
12438 		if (buf && i == ent)
12439 			return snprintf(buf, size, "%u", p);
12440 		++i;
12441 	}
12442 	if (buf)
12443 		return -1;
12444 	return i;
12445 }
12446 
12447 /** Complete available rule IDs. */
12448 static int
12449 comp_rule_id(struct context *ctx, const struct token *token,
12450 	     unsigned int ent, char *buf, unsigned int size)
12451 {
12452 	unsigned int i = 0;
12453 	struct rte_port *port;
12454 	struct port_flow *pf;
12455 
12456 	(void)token;
12457 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12458 	    ctx->port == (portid_t)RTE_PORT_ALL)
12459 		return -1;
12460 	port = &ports[ctx->port];
12461 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12462 		if (buf && i == ent)
12463 			return snprintf(buf, size, "%"PRIu64, pf->id);
12464 		++i;
12465 	}
12466 	if (buf)
12467 		return -1;
12468 	return i;
12469 }
12470 
12471 /** Complete operation for compare match item. */
12472 static int
12473 comp_set_compare_op(struct context *ctx, const struct token *token,
12474 		    unsigned int ent, char *buf, unsigned int size)
12475 {
12476 	RTE_SET_USED(ctx);
12477 	RTE_SET_USED(token);
12478 	if (!buf)
12479 		return RTE_DIM(compare_ops);
12480 	if (ent < RTE_DIM(compare_ops) - 1)
12481 		return strlcpy(buf, compare_ops[ent], size);
12482 	return -1;
12483 }
12484 
12485 /** Complete field id for compare match item. */
12486 static int
12487 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12488 			  unsigned int ent, char *buf, unsigned int size)
12489 {
12490 	const char *name;
12491 
12492 	RTE_SET_USED(token);
12493 	if (!buf)
12494 		return RTE_DIM(flow_field_ids);
12495 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12496 		return -1;
12497 	name = flow_field_ids[ent];
12498 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12499 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12500 		return strlcpy(buf, name, size);
12501 	return -1;
12502 }
12503 
12504 /** Complete type field for RSS action. */
12505 static int
12506 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12507 			unsigned int ent, char *buf, unsigned int size)
12508 {
12509 	unsigned int i;
12510 
12511 	(void)ctx;
12512 	(void)token;
12513 	for (i = 0; rss_type_table[i].str; ++i)
12514 		;
12515 	if (!buf)
12516 		return i + 1;
12517 	if (ent < i)
12518 		return strlcpy(buf, rss_type_table[ent].str, size);
12519 	if (ent == i)
12520 		return snprintf(buf, size, "end");
12521 	return -1;
12522 }
12523 
12524 /** Complete queue field for RSS action. */
12525 static int
12526 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12527 			 unsigned int ent, char *buf, unsigned int size)
12528 {
12529 	(void)ctx;
12530 	(void)token;
12531 	if (!buf)
12532 		return nb_rxq + 1;
12533 	if (ent < nb_rxq)
12534 		return snprintf(buf, size, "%u", ent);
12535 	if (ent == nb_rxq)
12536 		return snprintf(buf, size, "end");
12537 	return -1;
12538 }
12539 
12540 /** Complete index number for set raw_encap/raw_decap commands. */
12541 static int
12542 comp_set_raw_index(struct context *ctx, const struct token *token,
12543 		   unsigned int ent, char *buf, unsigned int size)
12544 {
12545 	uint16_t idx = 0;
12546 	uint16_t nb = 0;
12547 
12548 	RTE_SET_USED(ctx);
12549 	RTE_SET_USED(token);
12550 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12551 		if (buf && idx == ent)
12552 			return snprintf(buf, size, "%u", idx);
12553 		++nb;
12554 	}
12555 	return nb;
12556 }
12557 
12558 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12559 static int
12560 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12561 			unsigned int ent, char *buf, unsigned int size)
12562 {
12563 	uint16_t idx = 0;
12564 	uint16_t nb = 0;
12565 
12566 	RTE_SET_USED(ctx);
12567 	RTE_SET_USED(token);
12568 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12569 		if (buf && idx == ent)
12570 			return snprintf(buf, size, "%u", idx);
12571 		++nb;
12572 	}
12573 	return nb;
12574 }
12575 
12576 /** Complete index number for set raw_encap/raw_decap commands. */
12577 static int
12578 comp_set_sample_index(struct context *ctx, const struct token *token,
12579 		   unsigned int ent, char *buf, unsigned int size)
12580 {
12581 	uint16_t idx = 0;
12582 	uint16_t nb = 0;
12583 
12584 	RTE_SET_USED(ctx);
12585 	RTE_SET_USED(token);
12586 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12587 		if (buf && idx == ent)
12588 			return snprintf(buf, size, "%u", idx);
12589 		++nb;
12590 	}
12591 	return nb;
12592 }
12593 
12594 /** Complete operation for modify_field command. */
12595 static int
12596 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12597 		   unsigned int ent, char *buf, unsigned int size)
12598 {
12599 	RTE_SET_USED(ctx);
12600 	RTE_SET_USED(token);
12601 	if (!buf)
12602 		return RTE_DIM(modify_field_ops);
12603 	if (ent < RTE_DIM(modify_field_ops) - 1)
12604 		return strlcpy(buf, modify_field_ops[ent], size);
12605 	return -1;
12606 }
12607 
12608 /** Complete field id for modify_field command. */
12609 static int
12610 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12611 		   unsigned int ent, char *buf, unsigned int size)
12612 {
12613 	const char *name;
12614 
12615 	RTE_SET_USED(token);
12616 	if (!buf)
12617 		return RTE_DIM(flow_field_ids);
12618 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12619 		return -1;
12620 	name = flow_field_ids[ent];
12621 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12622 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12623 		return strlcpy(buf, name, size);
12624 	return -1;
12625 }
12626 
12627 /** Complete available pattern template IDs. */
12628 static int
12629 comp_pattern_template_id(struct context *ctx, const struct token *token,
12630 			 unsigned int ent, char *buf, unsigned int size)
12631 {
12632 	unsigned int i = 0;
12633 	struct rte_port *port;
12634 	struct port_template *pt;
12635 
12636 	(void)token;
12637 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12638 	    ctx->port == (portid_t)RTE_PORT_ALL)
12639 		return -1;
12640 	port = &ports[ctx->port];
12641 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12642 		if (buf && i == ent)
12643 			return snprintf(buf, size, "%u", pt->id);
12644 		++i;
12645 	}
12646 	if (buf)
12647 		return -1;
12648 	return i;
12649 }
12650 
12651 /** Complete available actions template IDs. */
12652 static int
12653 comp_actions_template_id(struct context *ctx, const struct token *token,
12654 			 unsigned int ent, char *buf, unsigned int size)
12655 {
12656 	unsigned int i = 0;
12657 	struct rte_port *port;
12658 	struct port_template *pt;
12659 
12660 	(void)token;
12661 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12662 	    ctx->port == (portid_t)RTE_PORT_ALL)
12663 		return -1;
12664 	port = &ports[ctx->port];
12665 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12666 		if (buf && i == ent)
12667 			return snprintf(buf, size, "%u", pt->id);
12668 		++i;
12669 	}
12670 	if (buf)
12671 		return -1;
12672 	return i;
12673 }
12674 
12675 /** Complete available table IDs. */
12676 static int
12677 comp_table_id(struct context *ctx, const struct token *token,
12678 	      unsigned int ent, char *buf, unsigned int size)
12679 {
12680 	unsigned int i = 0;
12681 	struct rte_port *port;
12682 	struct port_table *pt;
12683 
12684 	(void)token;
12685 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12686 	    ctx->port == (portid_t)RTE_PORT_ALL)
12687 		return -1;
12688 	port = &ports[ctx->port];
12689 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12690 		if (buf && i == ent)
12691 			return snprintf(buf, size, "%u", pt->id);
12692 		++i;
12693 	}
12694 	if (buf)
12695 		return -1;
12696 	return i;
12697 }
12698 
12699 /** Complete available queue IDs. */
12700 static int
12701 comp_queue_id(struct context *ctx, const struct token *token,
12702 	      unsigned int ent, char *buf, unsigned int size)
12703 {
12704 	unsigned int i = 0;
12705 	struct rte_port *port;
12706 
12707 	(void)token;
12708 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12709 	    ctx->port == (portid_t)RTE_PORT_ALL)
12710 		return -1;
12711 	port = &ports[ctx->port];
12712 	for (i = 0; i < port->queue_nb; i++) {
12713 		if (buf && i == ent)
12714 			return snprintf(buf, size, "%u", i);
12715 	}
12716 	if (buf)
12717 		return -1;
12718 	return i;
12719 }
12720 
12721 static int
12722 comp_names_to_index(struct context *ctx, const struct token *token,
12723 		    unsigned int ent, char *buf, unsigned int size,
12724 		    const char *const names[], size_t names_size)
12725 {
12726 	RTE_SET_USED(ctx);
12727 	RTE_SET_USED(token);
12728 	if (!buf)
12729 		return names_size;
12730 	if (names[ent] && ent < names_size)
12731 		return rte_strscpy(buf, names[ent], size);
12732 	return -1;
12733 
12734 }
12735 
12736 /** Complete available Meter colors. */
12737 static int
12738 comp_meter_color(struct context *ctx, const struct token *token,
12739 		 unsigned int ent, char *buf, unsigned int size)
12740 {
12741 	RTE_SET_USED(ctx);
12742 	RTE_SET_USED(token);
12743 	if (!buf)
12744 		return RTE_DIM(meter_colors);
12745 	if (ent < RTE_DIM(meter_colors) - 1)
12746 		return strlcpy(buf, meter_colors[ent], size);
12747 	return -1;
12748 }
12749 
12750 /** Complete available Insertion Table types. */
12751 static int
12752 comp_insertion_table_type(struct context *ctx, const struct token *token,
12753 			  unsigned int ent, char *buf, unsigned int size)
12754 {
12755 	RTE_SET_USED(ctx);
12756 	RTE_SET_USED(token);
12757 	if (!buf)
12758 		return RTE_DIM(table_insertion_types);
12759 	if (ent < RTE_DIM(table_insertion_types) - 1)
12760 		return rte_strscpy(buf, table_insertion_types[ent], size);
12761 	return -1;
12762 }
12763 
12764 /** Complete available Hash Calculation Table types. */
12765 static int
12766 comp_hash_table_type(struct context *ctx, const struct token *token,
12767 		     unsigned int ent, char *buf, unsigned int size)
12768 {
12769 	RTE_SET_USED(ctx);
12770 	RTE_SET_USED(token);
12771 	if (!buf)
12772 		return RTE_DIM(table_hash_funcs);
12773 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12774 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12775 	return -1;
12776 }
12777 
12778 static int
12779 comp_quota_state_name(struct context *ctx, const struct token *token,
12780 		      unsigned int ent, char *buf, unsigned int size)
12781 {
12782 	return comp_names_to_index(ctx, token, ent, buf, size,
12783 				   quota_state_names,
12784 				   RTE_DIM(quota_state_names));
12785 }
12786 
12787 static int
12788 comp_quota_mode_name(struct context *ctx, const struct token *token,
12789 		     unsigned int ent, char *buf, unsigned int size)
12790 {
12791 	return comp_names_to_index(ctx, token, ent, buf, size,
12792 				   quota_mode_names,
12793 				   RTE_DIM(quota_mode_names));
12794 }
12795 
12796 static int
12797 comp_quota_update_name(struct context *ctx, const struct token *token,
12798 		       unsigned int ent, char *buf, unsigned int size)
12799 {
12800 	return comp_names_to_index(ctx, token, ent, buf, size,
12801 				   quota_update_names,
12802 				   RTE_DIM(quota_update_names));
12803 }
12804 
12805 static int
12806 comp_qu_mode_name(struct context *ctx, const struct token *token,
12807 		  unsigned int ent, char *buf, unsigned int size)
12808 {
12809 	return comp_names_to_index(ctx, token, ent, buf, size,
12810 				   query_update_mode_names,
12811 				   RTE_DIM(query_update_mode_names));
12812 }
12813 
12814 /** Internal context. */
12815 static struct context cmd_flow_context;
12816 
12817 /** Global parser instance (cmdline API). */
12818 cmdline_parse_inst_t cmd_flow;
12819 cmdline_parse_inst_t cmd_set_raw;
12820 
12821 /** Initialize context. */
12822 static void
12823 cmd_flow_context_init(struct context *ctx)
12824 {
12825 	/* A full memset() is not necessary. */
12826 	ctx->curr = ZERO;
12827 	ctx->prev = ZERO;
12828 	ctx->next_num = 0;
12829 	ctx->args_num = 0;
12830 	ctx->eol = 0;
12831 	ctx->last = 0;
12832 	ctx->port = 0;
12833 	ctx->objdata = 0;
12834 	ctx->object = NULL;
12835 	ctx->objmask = NULL;
12836 }
12837 
12838 /** Parse a token (cmdline API). */
12839 static int
12840 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
12841 	       unsigned int size)
12842 {
12843 	struct context *ctx = &cmd_flow_context;
12844 	const struct token *token;
12845 	const enum index *list;
12846 	int len;
12847 	int i;
12848 
12849 	(void)hdr;
12850 	token = &token_list[ctx->curr];
12851 	/* Check argument length. */
12852 	ctx->eol = 0;
12853 	ctx->last = 1;
12854 	for (len = 0; src[len]; ++len)
12855 		if (src[len] == '#' || isspace(src[len]))
12856 			break;
12857 	if (!len)
12858 		return -1;
12859 	/* Last argument and EOL detection. */
12860 	for (i = len; src[i]; ++i)
12861 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
12862 			break;
12863 		else if (!isspace(src[i])) {
12864 			ctx->last = 0;
12865 			break;
12866 		}
12867 	for (; src[i]; ++i)
12868 		if (src[i] == '\r' || src[i] == '\n') {
12869 			ctx->eol = 1;
12870 			break;
12871 		}
12872 	/* Initialize context if necessary. */
12873 	if (!ctx->next_num) {
12874 		if (!token->next)
12875 			return 0;
12876 		ctx->next[ctx->next_num++] = token->next[0];
12877 	}
12878 	/* Process argument through candidates. */
12879 	ctx->prev = ctx->curr;
12880 	list = ctx->next[ctx->next_num - 1];
12881 	for (i = 0; list[i]; ++i) {
12882 		const struct token *next = &token_list[list[i]];
12883 		int tmp;
12884 
12885 		ctx->curr = list[i];
12886 		if (next->call)
12887 			tmp = next->call(ctx, next, src, len, result, size);
12888 		else
12889 			tmp = parse_default(ctx, next, src, len, result, size);
12890 		if (tmp == -1 || tmp != len)
12891 			continue;
12892 		token = next;
12893 		break;
12894 	}
12895 	if (!list[i])
12896 		return -1;
12897 	--ctx->next_num;
12898 	/* Push subsequent tokens if any. */
12899 	if (token->next)
12900 		for (i = 0; token->next[i]; ++i) {
12901 			if (ctx->next_num == RTE_DIM(ctx->next))
12902 				return -1;
12903 			ctx->next[ctx->next_num++] = token->next[i];
12904 		}
12905 	/* Push arguments if any. */
12906 	if (token->args)
12907 		for (i = 0; token->args[i]; ++i) {
12908 			if (ctx->args_num == RTE_DIM(ctx->args))
12909 				return -1;
12910 			ctx->args[ctx->args_num++] = token->args[i];
12911 		}
12912 	return len;
12913 }
12914 
12915 int
12916 flow_parse(const char *src, void *result, unsigned int size,
12917 	   struct rte_flow_attr **attr,
12918 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
12919 {
12920 	int ret;
12921 	struct context saved_flow_ctx = cmd_flow_context;
12922 
12923 	cmd_flow_context_init(&cmd_flow_context);
12924 	do {
12925 		ret = cmd_flow_parse(NULL, src, result, size);
12926 		if (ret > 0) {
12927 			src += ret;
12928 			while (isspace(*src))
12929 				src++;
12930 		}
12931 	} while (ret > 0 && strlen(src));
12932 	cmd_flow_context = saved_flow_ctx;
12933 	*attr = &((struct buffer *)result)->args.vc.attr;
12934 	*pattern = ((struct buffer *)result)->args.vc.pattern;
12935 	*actions = ((struct buffer *)result)->args.vc.actions;
12936 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
12937 }
12938 
12939 /** Return number of completion entries (cmdline API). */
12940 static int
12941 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
12942 {
12943 	struct context *ctx = &cmd_flow_context;
12944 	const struct token *token = &token_list[ctx->curr];
12945 	const enum index *list;
12946 	int i;
12947 
12948 	(void)hdr;
12949 	/* Count number of tokens in current list. */
12950 	if (ctx->next_num)
12951 		list = ctx->next[ctx->next_num - 1];
12952 	else
12953 		list = token->next[0];
12954 	for (i = 0; list[i]; ++i)
12955 		;
12956 	if (!i)
12957 		return 0;
12958 	/*
12959 	 * If there is a single token, use its completion callback, otherwise
12960 	 * return the number of entries.
12961 	 */
12962 	token = &token_list[list[0]];
12963 	if (i == 1 && token->comp) {
12964 		/* Save index for cmd_flow_get_help(). */
12965 		ctx->prev = list[0];
12966 		return token->comp(ctx, token, 0, NULL, 0);
12967 	}
12968 	return i;
12969 }
12970 
12971 /** Return a completion entry (cmdline API). */
12972 static int
12973 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
12974 			  char *dst, unsigned int size)
12975 {
12976 	struct context *ctx = &cmd_flow_context;
12977 	const struct token *token = &token_list[ctx->curr];
12978 	const enum index *list;
12979 	int i;
12980 
12981 	(void)hdr;
12982 	/* Count number of tokens in current list. */
12983 	if (ctx->next_num)
12984 		list = ctx->next[ctx->next_num - 1];
12985 	else
12986 		list = token->next[0];
12987 	for (i = 0; list[i]; ++i)
12988 		;
12989 	if (!i)
12990 		return -1;
12991 	/* If there is a single token, use its completion callback. */
12992 	token = &token_list[list[0]];
12993 	if (i == 1 && token->comp) {
12994 		/* Save index for cmd_flow_get_help(). */
12995 		ctx->prev = list[0];
12996 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
12997 	}
12998 	/* Otherwise make sure the index is valid and use defaults. */
12999 	if (index >= i)
13000 		return -1;
13001 	token = &token_list[list[index]];
13002 	strlcpy(dst, token->name, size);
13003 	/* Save index for cmd_flow_get_help(). */
13004 	ctx->prev = list[index];
13005 	return 0;
13006 }
13007 
13008 /** Populate help strings for current token (cmdline API). */
13009 static int
13010 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13011 {
13012 	struct context *ctx = &cmd_flow_context;
13013 	const struct token *token = &token_list[ctx->prev];
13014 
13015 	(void)hdr;
13016 	if (!size)
13017 		return -1;
13018 	/* Set token type and update global help with details. */
13019 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13020 	if (token->help)
13021 		cmd_flow.help_str = token->help;
13022 	else
13023 		cmd_flow.help_str = token->name;
13024 	return 0;
13025 }
13026 
13027 /** Token definition template (cmdline API). */
13028 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13029 	.ops = &(struct cmdline_token_ops){
13030 		.parse = cmd_flow_parse,
13031 		.complete_get_nb = cmd_flow_complete_get_nb,
13032 		.complete_get_elt = cmd_flow_complete_get_elt,
13033 		.get_help = cmd_flow_get_help,
13034 	},
13035 	.offset = 0,
13036 };
13037 
13038 /** Populate the next dynamic token. */
13039 static void
13040 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13041 	     cmdline_parse_token_hdr_t **hdr_inst)
13042 {
13043 	struct context *ctx = &cmd_flow_context;
13044 
13045 	/* Always reinitialize context before requesting the first token. */
13046 	if (!(hdr_inst - cmd_flow.tokens))
13047 		cmd_flow_context_init(ctx);
13048 	/* Return NULL when no more tokens are expected. */
13049 	if (!ctx->next_num && ctx->curr) {
13050 		*hdr = NULL;
13051 		return;
13052 	}
13053 	/* Determine if command should end here. */
13054 	if (ctx->eol && ctx->last && ctx->next_num) {
13055 		const enum index *list = ctx->next[ctx->next_num - 1];
13056 		int i;
13057 
13058 		for (i = 0; list[i]; ++i) {
13059 			if (list[i] != END)
13060 				continue;
13061 			*hdr = NULL;
13062 			return;
13063 		}
13064 	}
13065 	*hdr = &cmd_flow_token_hdr;
13066 }
13067 
13068 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13069 	SLIST_HEAD_INITIALIZER();
13070 
13071 static void
13072 indirect_action_flow_conf_create(const struct buffer *in)
13073 {
13074 	int len, ret;
13075 	uint32_t i;
13076 	struct indlst_conf *indlst_conf = NULL;
13077 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13078 	struct rte_flow_action *src = in->args.vc.actions;
13079 
13080 	if (!in->args.vc.actions_n)
13081 		goto end;
13082 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13083 	if (len <= 0)
13084 		goto end;
13085 	len = RTE_ALIGN(len, 16);
13086 
13087 	indlst_conf = calloc(1, base + len +
13088 			     in->args.vc.actions_n * sizeof(uintptr_t));
13089 	if (!indlst_conf)
13090 		goto end;
13091 	indlst_conf->id = in->args.vc.attr.group;
13092 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13093 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13094 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13095 			    len, src, NULL);
13096 	if (ret <= 0) {
13097 		free(indlst_conf);
13098 		indlst_conf = NULL;
13099 		goto end;
13100 	}
13101 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13102 	for (i = 0; i < indlst_conf->conf_num; i++)
13103 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13104 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13105 end:
13106 	if (indlst_conf)
13107 		printf("created indirect action list configuration %u\n",
13108 		       in->args.vc.attr.group);
13109 	else
13110 		printf("cannot create indirect action list configuration %u\n",
13111 		       in->args.vc.attr.group);
13112 }
13113 
13114 static const struct indlst_conf *
13115 indirect_action_list_conf_get(uint32_t conf_id)
13116 {
13117 	const struct indlst_conf *conf;
13118 
13119 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13120 		if (conf->id == conf_id)
13121 			return conf;
13122 	}
13123 	return NULL;
13124 }
13125 
13126 /** Dispatch parsed buffer to function calls. */
13127 static void
13128 cmd_flow_parsed(const struct buffer *in)
13129 {
13130 	switch (in->command) {
13131 	case INFO:
13132 		port_flow_get_info(in->port);
13133 		break;
13134 	case CONFIGURE:
13135 		port_flow_configure(in->port,
13136 				    &in->args.configure.port_attr,
13137 				    in->args.configure.nb_queue,
13138 				    &in->args.configure.queue_attr);
13139 		break;
13140 	case PATTERN_TEMPLATE_CREATE:
13141 		port_flow_pattern_template_create(in->port,
13142 				in->args.vc.pat_templ_id,
13143 				&((const struct rte_flow_pattern_template_attr) {
13144 					.relaxed_matching = in->args.vc.attr.reserved,
13145 					.ingress = in->args.vc.attr.ingress,
13146 					.egress = in->args.vc.attr.egress,
13147 					.transfer = in->args.vc.attr.transfer,
13148 				}),
13149 				in->args.vc.pattern);
13150 		break;
13151 	case PATTERN_TEMPLATE_DESTROY:
13152 		port_flow_pattern_template_destroy(in->port,
13153 				in->args.templ_destroy.template_id_n,
13154 				in->args.templ_destroy.template_id);
13155 		break;
13156 	case ACTIONS_TEMPLATE_CREATE:
13157 		port_flow_actions_template_create(in->port,
13158 				in->args.vc.act_templ_id,
13159 				&((const struct rte_flow_actions_template_attr) {
13160 					.ingress = in->args.vc.attr.ingress,
13161 					.egress = in->args.vc.attr.egress,
13162 					.transfer = in->args.vc.attr.transfer,
13163 				}),
13164 				in->args.vc.actions,
13165 				in->args.vc.masks);
13166 		break;
13167 	case ACTIONS_TEMPLATE_DESTROY:
13168 		port_flow_actions_template_destroy(in->port,
13169 				in->args.templ_destroy.template_id_n,
13170 				in->args.templ_destroy.template_id);
13171 		break;
13172 	case TABLE_CREATE:
13173 		port_flow_template_table_create(in->port, in->args.table.id,
13174 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13175 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13176 			in->args.table.act_templ_id);
13177 		break;
13178 	case TABLE_DESTROY:
13179 		port_flow_template_table_destroy(in->port,
13180 					in->args.table_destroy.table_id_n,
13181 					in->args.table_destroy.table_id);
13182 		break;
13183 	case TABLE_RESIZE_COMPLETE:
13184 		port_flow_template_table_resize_complete
13185 			(in->port, in->args.table_destroy.table_id[0]);
13186 		break;
13187 	case GROUP_SET_MISS_ACTIONS:
13188 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13189 						  in->args.vc.actions);
13190 		break;
13191 	case TABLE_RESIZE:
13192 		port_flow_template_table_resize(in->port, in->args.table.id,
13193 						in->args.table.attr.nb_flows);
13194 		break;
13195 	case QUEUE_CREATE:
13196 		port_queue_flow_create(in->port, in->queue, in->postpone,
13197 			in->args.vc.table_id, in->args.vc.rule_id,
13198 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13199 			in->args.vc.pattern, in->args.vc.actions);
13200 		break;
13201 	case QUEUE_DESTROY:
13202 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13203 					in->args.destroy.rule_n,
13204 					in->args.destroy.rule);
13205 		break;
13206 	case QUEUE_FLOW_UPDATE_RESIZED:
13207 		port_queue_flow_update_resized(in->port, in->queue,
13208 					       in->postpone,
13209 					       in->args.destroy.rule[0]);
13210 		break;
13211 	case QUEUE_UPDATE:
13212 		port_queue_flow_update(in->port, in->queue, in->postpone,
13213 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13214 				in->args.vc.actions);
13215 		break;
13216 	case PUSH:
13217 		port_queue_flow_push(in->port, in->queue);
13218 		break;
13219 	case PULL:
13220 		port_queue_flow_pull(in->port, in->queue);
13221 		break;
13222 	case HASH:
13223 		if (!in->args.vc.encap_hash)
13224 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13225 					    in->args.vc.pat_templ_id,
13226 					    in->args.vc.pattern);
13227 		else
13228 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13229 						  in->args.vc.pattern);
13230 		break;
13231 	case QUEUE_AGED:
13232 		port_queue_flow_aged(in->port, in->queue,
13233 				     in->args.aged.destroy);
13234 		break;
13235 	case QUEUE_INDIRECT_ACTION_CREATE:
13236 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13237 		port_queue_action_handle_create(
13238 				in->port, in->queue, in->postpone,
13239 				in->args.vc.attr.group,
13240 				&((const struct rte_flow_indir_action_conf) {
13241 					.ingress = in->args.vc.attr.ingress,
13242 					.egress = in->args.vc.attr.egress,
13243 					.transfer = in->args.vc.attr.transfer,
13244 				}),
13245 				in->args.vc.actions);
13246 		break;
13247 	case QUEUE_INDIRECT_ACTION_DESTROY:
13248 		port_queue_action_handle_destroy(in->port,
13249 					   in->queue, in->postpone,
13250 					   in->args.ia_destroy.action_id_n,
13251 					   in->args.ia_destroy.action_id);
13252 		break;
13253 	case QUEUE_INDIRECT_ACTION_UPDATE:
13254 		port_queue_action_handle_update(in->port,
13255 						in->queue, in->postpone,
13256 						in->args.vc.attr.group,
13257 						in->args.vc.actions);
13258 		break;
13259 	case QUEUE_INDIRECT_ACTION_QUERY:
13260 		port_queue_action_handle_query(in->port,
13261 					       in->queue, in->postpone,
13262 					       in->args.ia.action_id);
13263 		break;
13264 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13265 		port_queue_action_handle_query_update(in->port, in->queue,
13266 						      in->postpone,
13267 						      in->args.ia.action_id,
13268 						      in->args.ia.qu_mode,
13269 						      in->args.vc.actions);
13270 		break;
13271 	case INDIRECT_ACTION_CREATE:
13272 	case INDIRECT_ACTION_LIST_CREATE:
13273 		port_action_handle_create(
13274 				in->port, in->args.vc.attr.group,
13275 				in->command == INDIRECT_ACTION_LIST_CREATE,
13276 				&((const struct rte_flow_indir_action_conf) {
13277 					.ingress = in->args.vc.attr.ingress,
13278 					.egress = in->args.vc.attr.egress,
13279 					.transfer = in->args.vc.attr.transfer,
13280 				}),
13281 				in->args.vc.actions);
13282 		break;
13283 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13284 		indirect_action_flow_conf_create(in);
13285 		break;
13286 	case INDIRECT_ACTION_DESTROY:
13287 		port_action_handle_destroy(in->port,
13288 					   in->args.ia_destroy.action_id_n,
13289 					   in->args.ia_destroy.action_id);
13290 		break;
13291 	case INDIRECT_ACTION_UPDATE:
13292 		port_action_handle_update(in->port, in->args.vc.attr.group,
13293 					  in->args.vc.actions);
13294 		break;
13295 	case INDIRECT_ACTION_QUERY:
13296 		port_action_handle_query(in->port, in->args.ia.action_id);
13297 		break;
13298 	case INDIRECT_ACTION_QUERY_UPDATE:
13299 		port_action_handle_query_update(in->port,
13300 						in->args.ia.action_id,
13301 						in->args.ia.qu_mode,
13302 						in->args.vc.actions);
13303 		break;
13304 	case VALIDATE:
13305 		port_flow_validate(in->port, &in->args.vc.attr,
13306 				   in->args.vc.pattern, in->args.vc.actions,
13307 				   &in->args.vc.tunnel_ops);
13308 		break;
13309 	case CREATE:
13310 		port_flow_create(in->port, &in->args.vc.attr,
13311 				 in->args.vc.pattern, in->args.vc.actions,
13312 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13313 		break;
13314 	case DESTROY:
13315 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13316 				  in->args.destroy.rule,
13317 				  in->args.destroy.is_user_id);
13318 		break;
13319 	case UPDATE:
13320 		port_flow_update(in->port, in->args.vc.rule_id,
13321 				 in->args.vc.actions, in->args.vc.user_id);
13322 		break;
13323 	case FLUSH:
13324 		port_flow_flush(in->port);
13325 		break;
13326 	case DUMP_ONE:
13327 	case DUMP_ALL:
13328 		port_flow_dump(in->port, in->args.dump.mode,
13329 				in->args.dump.rule, in->args.dump.file,
13330 				in->args.dump.is_user_id);
13331 		break;
13332 	case QUERY:
13333 		port_flow_query(in->port, in->args.query.rule,
13334 				&in->args.query.action,
13335 				in->args.query.is_user_id);
13336 		break;
13337 	case LIST:
13338 		port_flow_list(in->port, in->args.list.group_n,
13339 			       in->args.list.group);
13340 		break;
13341 	case ISOLATE:
13342 		port_flow_isolate(in->port, in->args.isolate.set);
13343 		break;
13344 	case AGED:
13345 		port_flow_aged(in->port, in->args.aged.destroy);
13346 		break;
13347 	case TUNNEL_CREATE:
13348 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13349 		break;
13350 	case TUNNEL_DESTROY:
13351 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13352 		break;
13353 	case TUNNEL_LIST:
13354 		port_flow_tunnel_list(in->port);
13355 		break;
13356 	case ACTION_POL_G:
13357 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13358 					in->args.vc.actions);
13359 		break;
13360 	case FLEX_ITEM_CREATE:
13361 		flex_item_create(in->port, in->args.flex.token,
13362 				 in->args.flex.filename);
13363 		break;
13364 	case FLEX_ITEM_DESTROY:
13365 		flex_item_destroy(in->port, in->args.flex.token);
13366 		break;
13367 	default:
13368 		break;
13369 	}
13370 	fflush(stdout);
13371 }
13372 
13373 /** Token generator and output processing callback (cmdline API). */
13374 static void
13375 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13376 {
13377 	if (cl == NULL)
13378 		cmd_flow_tok(arg0, arg2);
13379 	else
13380 		cmd_flow_parsed(arg0);
13381 }
13382 
13383 /** Global parser instance (cmdline API). */
13384 cmdline_parse_inst_t cmd_flow = {
13385 	.f = cmd_flow_cb,
13386 	.data = NULL, /**< Unused. */
13387 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13388 	.tokens = {
13389 		NULL,
13390 	}, /**< Tokens are returned by cmd_flow_tok(). */
13391 };
13392 
13393 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13394 
13395 static void
13396 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13397 {
13398 	struct rte_ipv4_hdr *ipv4;
13399 	struct rte_ether_hdr *eth;
13400 	struct rte_ipv6_hdr *ipv6;
13401 	struct rte_vxlan_hdr *vxlan;
13402 	struct rte_vxlan_gpe_hdr *gpe;
13403 	struct rte_flow_item_nvgre *nvgre;
13404 	uint32_t ipv6_vtc_flow;
13405 
13406 	switch (item->type) {
13407 	case RTE_FLOW_ITEM_TYPE_ETH:
13408 		eth = (struct rte_ether_hdr *)buf;
13409 		if (next_proto)
13410 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13411 		break;
13412 	case RTE_FLOW_ITEM_TYPE_IPV4:
13413 		ipv4 = (struct rte_ipv4_hdr *)buf;
13414 		if (!ipv4->version_ihl)
13415 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13416 		if (next_proto && ipv4->next_proto_id == 0)
13417 			ipv4->next_proto_id = (uint8_t)next_proto;
13418 		break;
13419 	case RTE_FLOW_ITEM_TYPE_IPV6:
13420 		ipv6 = (struct rte_ipv6_hdr *)buf;
13421 		if (next_proto && ipv6->proto == 0)
13422 			ipv6->proto = (uint8_t)next_proto;
13423 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13424 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13425 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13426 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13427 		break;
13428 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13429 		vxlan = (struct rte_vxlan_hdr *)buf;
13430 		vxlan->vx_flags = 0x08;
13431 		break;
13432 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13433 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13434 		gpe->vx_flags = 0x0C;
13435 		break;
13436 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13437 		nvgre = (struct rte_flow_item_nvgre *)buf;
13438 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13439 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13440 		break;
13441 	default:
13442 		break;
13443 	}
13444 }
13445 
13446 /** Helper of get item's default mask. */
13447 static const void *
13448 flow_item_default_mask(const struct rte_flow_item *item)
13449 {
13450 	const void *mask = NULL;
13451 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13452 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13453 		.hdr = {
13454 			.next_hdr = 0xff,
13455 			.type = 0xff,
13456 			.segments_left = 0xff,
13457 		},
13458 	};
13459 
13460 	switch (item->type) {
13461 	case RTE_FLOW_ITEM_TYPE_ANY:
13462 		mask = &rte_flow_item_any_mask;
13463 		break;
13464 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13465 		mask = &rte_flow_item_port_id_mask;
13466 		break;
13467 	case RTE_FLOW_ITEM_TYPE_RAW:
13468 		mask = &rte_flow_item_raw_mask;
13469 		break;
13470 	case RTE_FLOW_ITEM_TYPE_ETH:
13471 		mask = &rte_flow_item_eth_mask;
13472 		break;
13473 	case RTE_FLOW_ITEM_TYPE_VLAN:
13474 		mask = &rte_flow_item_vlan_mask;
13475 		break;
13476 	case RTE_FLOW_ITEM_TYPE_IPV4:
13477 		mask = &rte_flow_item_ipv4_mask;
13478 		break;
13479 	case RTE_FLOW_ITEM_TYPE_IPV6:
13480 		mask = &rte_flow_item_ipv6_mask;
13481 		break;
13482 	case RTE_FLOW_ITEM_TYPE_ICMP:
13483 		mask = &rte_flow_item_icmp_mask;
13484 		break;
13485 	case RTE_FLOW_ITEM_TYPE_UDP:
13486 		mask = &rte_flow_item_udp_mask;
13487 		break;
13488 	case RTE_FLOW_ITEM_TYPE_TCP:
13489 		mask = &rte_flow_item_tcp_mask;
13490 		break;
13491 	case RTE_FLOW_ITEM_TYPE_SCTP:
13492 		mask = &rte_flow_item_sctp_mask;
13493 		break;
13494 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13495 		mask = &rte_flow_item_vxlan_mask;
13496 		break;
13497 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13498 		mask = &rte_flow_item_vxlan_gpe_mask;
13499 		break;
13500 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13501 		mask = &rte_flow_item_e_tag_mask;
13502 		break;
13503 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13504 		mask = &rte_flow_item_nvgre_mask;
13505 		break;
13506 	case RTE_FLOW_ITEM_TYPE_MPLS:
13507 		mask = &rte_flow_item_mpls_mask;
13508 		break;
13509 	case RTE_FLOW_ITEM_TYPE_GRE:
13510 		mask = &rte_flow_item_gre_mask;
13511 		break;
13512 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13513 		mask = &gre_key_default_mask;
13514 		break;
13515 	case RTE_FLOW_ITEM_TYPE_META:
13516 		mask = &rte_flow_item_meta_mask;
13517 		break;
13518 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13519 		mask = &rte_flow_item_random_mask;
13520 		break;
13521 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13522 		mask = &rte_flow_item_fuzzy_mask;
13523 		break;
13524 	case RTE_FLOW_ITEM_TYPE_GTP:
13525 		mask = &rte_flow_item_gtp_mask;
13526 		break;
13527 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13528 		mask = &rte_flow_item_gtp_psc_mask;
13529 		break;
13530 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13531 		mask = &rte_flow_item_geneve_mask;
13532 		break;
13533 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13534 		mask = &rte_flow_item_geneve_opt_mask;
13535 		break;
13536 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13537 		mask = &rte_flow_item_pppoe_proto_id_mask;
13538 		break;
13539 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13540 		mask = &rte_flow_item_l2tpv3oip_mask;
13541 		break;
13542 	case RTE_FLOW_ITEM_TYPE_ESP:
13543 		mask = &rte_flow_item_esp_mask;
13544 		break;
13545 	case RTE_FLOW_ITEM_TYPE_AH:
13546 		mask = &rte_flow_item_ah_mask;
13547 		break;
13548 	case RTE_FLOW_ITEM_TYPE_PFCP:
13549 		mask = &rte_flow_item_pfcp_mask;
13550 		break;
13551 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13552 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13553 		mask = &rte_flow_item_ethdev_mask;
13554 		break;
13555 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13556 		mask = &rte_flow_item_l2tpv2_mask;
13557 		break;
13558 	case RTE_FLOW_ITEM_TYPE_PPP:
13559 		mask = &rte_flow_item_ppp_mask;
13560 		break;
13561 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13562 		mask = &rte_flow_item_meter_color_mask;
13563 		break;
13564 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13565 		mask = &ipv6_routing_ext_default_mask;
13566 		break;
13567 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13568 		mask = &rte_flow_item_aggr_affinity_mask;
13569 		break;
13570 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13571 		mask = &rte_flow_item_tx_queue_mask;
13572 		break;
13573 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13574 		mask = &rte_flow_item_ib_bth_mask;
13575 		break;
13576 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13577 		mask = &rte_flow_item_ptype_mask;
13578 		break;
13579 	default:
13580 		break;
13581 	}
13582 	return mask;
13583 }
13584 
13585 /** Dispatch parsed buffer to function calls. */
13586 static void
13587 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13588 {
13589 	uint32_t n = in->args.vc.pattern_n;
13590 	int i = 0;
13591 	struct rte_flow_item *item = NULL;
13592 	size_t size = 0;
13593 	uint8_t *data = NULL;
13594 	uint8_t *type = NULL;
13595 	size_t *total_size = NULL;
13596 	uint16_t idx = in->port; /* We borrow port field as index */
13597 	struct rte_flow_item_ipv6_routing_ext *ext;
13598 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13599 
13600 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13601 		   in->command == SET_IPV6_EXT_REMOVE);
13602 
13603 	if (in->command == SET_IPV6_EXT_REMOVE) {
13604 		if (n != 1 || in->args.vc.pattern->type !=
13605 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13606 			fprintf(stderr, "Error - Not supported item\n");
13607 			return;
13608 		}
13609 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13610 		item = in->args.vc.pattern;
13611 		ipv6_ext = item->spec;
13612 		*type = ipv6_ext->next_hdr;
13613 		return;
13614 	}
13615 
13616 	total_size = &ipv6_ext_push_confs[idx].size;
13617 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13618 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13619 
13620 	*total_size = 0;
13621 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13622 	for (i = n - 1 ; i >= 0; --i) {
13623 		item = in->args.vc.pattern + i;
13624 		switch (item->type) {
13625 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13626 			ipv6_ext = item->spec;
13627 			*type = ipv6_ext->next_hdr;
13628 			break;
13629 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13630 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13631 			if (!ext->hdr.hdr_len) {
13632 				size = sizeof(struct rte_ipv6_routing_ext) +
13633 				(ext->hdr.segments_left << 4);
13634 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13635 				/* Indicate no TLV once SRH. */
13636 				if (ext->hdr.type == 4)
13637 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13638 			} else {
13639 				size = sizeof(struct rte_ipv6_routing_ext) +
13640 				(ext->hdr.hdr_len << 3);
13641 			}
13642 			*total_size += size;
13643 			memcpy(data, ext, size);
13644 			break;
13645 		default:
13646 			fprintf(stderr, "Error - Not supported item\n");
13647 			goto error;
13648 		}
13649 	}
13650 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13651 	return;
13652 error:
13653 	*total_size = 0;
13654 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13655 }
13656 
13657 /** Dispatch parsed buffer to function calls. */
13658 static void
13659 cmd_set_raw_parsed_sample(const struct buffer *in)
13660 {
13661 	uint32_t n = in->args.vc.actions_n;
13662 	uint32_t i = 0;
13663 	struct rte_flow_action *action = NULL;
13664 	struct rte_flow_action *data = NULL;
13665 	const struct rte_flow_action_rss *rss = NULL;
13666 	size_t size = 0;
13667 	uint16_t idx = in->port; /* We borrow port field as index */
13668 	uint32_t max_size = sizeof(struct rte_flow_action) *
13669 						ACTION_SAMPLE_ACTIONS_NUM;
13670 
13671 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13672 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13673 	memset(data, 0x00, max_size);
13674 	for (; i <= n - 1; i++) {
13675 		action = in->args.vc.actions + i;
13676 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13677 			break;
13678 		switch (action->type) {
13679 		case RTE_FLOW_ACTION_TYPE_MARK:
13680 			size = sizeof(struct rte_flow_action_mark);
13681 			rte_memcpy(&sample_mark[idx],
13682 				(const void *)action->conf, size);
13683 			action->conf = &sample_mark[idx];
13684 			break;
13685 		case RTE_FLOW_ACTION_TYPE_COUNT:
13686 			size = sizeof(struct rte_flow_action_count);
13687 			rte_memcpy(&sample_count[idx],
13688 				(const void *)action->conf, size);
13689 			action->conf = &sample_count[idx];
13690 			break;
13691 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13692 			size = sizeof(struct rte_flow_action_queue);
13693 			rte_memcpy(&sample_queue[idx],
13694 				(const void *)action->conf, size);
13695 			action->conf = &sample_queue[idx];
13696 			break;
13697 		case RTE_FLOW_ACTION_TYPE_RSS:
13698 			size = sizeof(struct rte_flow_action_rss);
13699 			rss = action->conf;
13700 			rte_memcpy(&sample_rss_data[idx].conf,
13701 				   (const void *)rss, size);
13702 			if (rss->key_len && rss->key) {
13703 				sample_rss_data[idx].conf.key =
13704 						sample_rss_data[idx].key;
13705 				rte_memcpy((void *)((uintptr_t)
13706 					   sample_rss_data[idx].conf.key),
13707 					   (const void *)rss->key,
13708 					   sizeof(uint8_t) * rss->key_len);
13709 			}
13710 			if (rss->queue_num && rss->queue) {
13711 				sample_rss_data[idx].conf.queue =
13712 						sample_rss_data[idx].queue;
13713 				rte_memcpy((void *)((uintptr_t)
13714 					   sample_rss_data[idx].conf.queue),
13715 					   (const void *)rss->queue,
13716 					   sizeof(uint16_t) * rss->queue_num);
13717 			}
13718 			action->conf = &sample_rss_data[idx].conf;
13719 			break;
13720 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13721 			size = sizeof(struct rte_flow_action_raw_encap);
13722 			rte_memcpy(&sample_encap[idx],
13723 				(const void *)action->conf, size);
13724 			action->conf = &sample_encap[idx];
13725 			break;
13726 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13727 			size = sizeof(struct rte_flow_action_port_id);
13728 			rte_memcpy(&sample_port_id[idx],
13729 				(const void *)action->conf, size);
13730 			action->conf = &sample_port_id[idx];
13731 			break;
13732 		case RTE_FLOW_ACTION_TYPE_PF:
13733 			break;
13734 		case RTE_FLOW_ACTION_TYPE_VF:
13735 			size = sizeof(struct rte_flow_action_vf);
13736 			rte_memcpy(&sample_vf[idx],
13737 					(const void *)action->conf, size);
13738 			action->conf = &sample_vf[idx];
13739 			break;
13740 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13741 			size = sizeof(struct rte_flow_action_vxlan_encap);
13742 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13743 			action->conf = &sample_vxlan_encap[idx].conf;
13744 			break;
13745 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13746 			size = sizeof(struct rte_flow_action_nvgre_encap);
13747 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13748 			action->conf = &sample_nvgre_encap[idx];
13749 			break;
13750 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13751 			size = sizeof(struct rte_flow_action_ethdev);
13752 			rte_memcpy(&sample_port_representor[idx],
13753 					(const void *)action->conf, size);
13754 			action->conf = &sample_port_representor[idx];
13755 			break;
13756 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13757 			size = sizeof(struct rte_flow_action_ethdev);
13758 			rte_memcpy(&sample_represented_port[idx],
13759 					(const void *)action->conf, size);
13760 			action->conf = &sample_represented_port[idx];
13761 			break;
13762 		default:
13763 			fprintf(stderr, "Error - Not supported action\n");
13764 			return;
13765 		}
13766 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13767 		data++;
13768 	}
13769 }
13770 
13771 /** Dispatch parsed buffer to function calls. */
13772 static void
13773 cmd_set_raw_parsed(const struct buffer *in)
13774 {
13775 	uint32_t n = in->args.vc.pattern_n;
13776 	int i = 0;
13777 	struct rte_flow_item *item = NULL;
13778 	size_t size = 0;
13779 	uint8_t *data = NULL;
13780 	uint8_t *data_tail = NULL;
13781 	size_t *total_size = NULL;
13782 	uint16_t upper_layer = 0;
13783 	uint16_t proto = 0;
13784 	uint16_t idx = in->port; /* We borrow port field as index */
13785 	int gtp_psc = -1; /* GTP PSC option index. */
13786 	const void *src_spec;
13787 
13788 	if (in->command == SET_SAMPLE_ACTIONS)
13789 		return cmd_set_raw_parsed_sample(in);
13790 	else if (in->command == SET_IPV6_EXT_PUSH ||
13791 		 in->command == SET_IPV6_EXT_REMOVE)
13792 		return cmd_set_ipv6_ext_parsed(in);
13793 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13794 		   in->command == SET_RAW_DECAP);
13795 	if (in->command == SET_RAW_ENCAP) {
13796 		total_size = &raw_encap_confs[idx].size;
13797 		data = (uint8_t *)&raw_encap_confs[idx].data;
13798 	} else {
13799 		total_size = &raw_decap_confs[idx].size;
13800 		data = (uint8_t *)&raw_decap_confs[idx].data;
13801 	}
13802 	*total_size = 0;
13803 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13804 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13805 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13806 	for (i = n - 1 ; i >= 0; --i) {
13807 		const struct rte_flow_item_gtp *gtp;
13808 		const struct rte_flow_item_geneve_opt *opt;
13809 		struct rte_flow_item_ipv6_routing_ext *ext;
13810 
13811 		item = in->args.vc.pattern + i;
13812 		if (item->spec == NULL)
13813 			item->spec = flow_item_default_mask(item);
13814 		src_spec = item->spec;
13815 		switch (item->type) {
13816 		case RTE_FLOW_ITEM_TYPE_ETH:
13817 			size = sizeof(struct rte_ether_hdr);
13818 			break;
13819 		case RTE_FLOW_ITEM_TYPE_VLAN:
13820 			size = sizeof(struct rte_vlan_hdr);
13821 			proto = RTE_ETHER_TYPE_VLAN;
13822 			break;
13823 		case RTE_FLOW_ITEM_TYPE_IPV4:
13824 			size = sizeof(struct rte_ipv4_hdr);
13825 			proto = RTE_ETHER_TYPE_IPV4;
13826 			break;
13827 		case RTE_FLOW_ITEM_TYPE_IPV6:
13828 			size = sizeof(struct rte_ipv6_hdr);
13829 			proto = RTE_ETHER_TYPE_IPV6;
13830 			break;
13831 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13832 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13833 			if (!ext->hdr.hdr_len) {
13834 				size = sizeof(struct rte_ipv6_routing_ext) +
13835 					(ext->hdr.segments_left << 4);
13836 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13837 				/* SRv6 without TLV. */
13838 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
13839 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13840 			} else {
13841 				size = sizeof(struct rte_ipv6_routing_ext) +
13842 					(ext->hdr.hdr_len << 3);
13843 			}
13844 			proto = IPPROTO_ROUTING;
13845 			break;
13846 		case RTE_FLOW_ITEM_TYPE_UDP:
13847 			size = sizeof(struct rte_udp_hdr);
13848 			proto = 0x11;
13849 			break;
13850 		case RTE_FLOW_ITEM_TYPE_TCP:
13851 			size = sizeof(struct rte_tcp_hdr);
13852 			proto = 0x06;
13853 			break;
13854 		case RTE_FLOW_ITEM_TYPE_VXLAN:
13855 			size = sizeof(struct rte_vxlan_hdr);
13856 			break;
13857 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13858 			size = sizeof(struct rte_vxlan_gpe_hdr);
13859 			break;
13860 		case RTE_FLOW_ITEM_TYPE_GRE:
13861 			size = sizeof(struct rte_gre_hdr);
13862 			proto = 0x2F;
13863 			break;
13864 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13865 			size = sizeof(rte_be32_t);
13866 			proto = 0x0;
13867 			break;
13868 		case RTE_FLOW_ITEM_TYPE_MPLS:
13869 			size = sizeof(struct rte_mpls_hdr);
13870 			proto = 0x0;
13871 			break;
13872 		case RTE_FLOW_ITEM_TYPE_NVGRE:
13873 			size = sizeof(struct rte_flow_item_nvgre);
13874 			proto = 0x2F;
13875 			break;
13876 		case RTE_FLOW_ITEM_TYPE_GENEVE:
13877 			size = sizeof(struct rte_geneve_hdr);
13878 			break;
13879 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13880 			opt = (const struct rte_flow_item_geneve_opt *)
13881 								item->spec;
13882 			size = offsetof(struct rte_flow_item_geneve_opt,
13883 					option_len) + sizeof(uint8_t);
13884 			if (opt->option_len && opt->data) {
13885 				*total_size += opt->option_len *
13886 					       sizeof(uint32_t);
13887 				rte_memcpy(data_tail - (*total_size),
13888 					   opt->data,
13889 					   opt->option_len * sizeof(uint32_t));
13890 			}
13891 			break;
13892 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13893 			size = sizeof(rte_be32_t);
13894 			proto = 0x73;
13895 			break;
13896 		case RTE_FLOW_ITEM_TYPE_ESP:
13897 			size = sizeof(struct rte_esp_hdr);
13898 			proto = 0x32;
13899 			break;
13900 		case RTE_FLOW_ITEM_TYPE_AH:
13901 			size = sizeof(struct rte_flow_item_ah);
13902 			proto = 0x33;
13903 			break;
13904 		case RTE_FLOW_ITEM_TYPE_GTP:
13905 			if (gtp_psc < 0) {
13906 				size = sizeof(struct rte_gtp_hdr);
13907 				break;
13908 			}
13909 			if (gtp_psc != i + 1) {
13910 				fprintf(stderr,
13911 					"Error - GTP PSC does not follow GTP\n");
13912 				goto error;
13913 			}
13914 			gtp = item->spec;
13915 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
13916 				/* Only E flag should be set. */
13917 				fprintf(stderr,
13918 					"Error - GTP unsupported flags\n");
13919 				goto error;
13920 			} else {
13921 				struct rte_gtp_hdr_ext_word ext_word = {
13922 					.next_ext = 0x85
13923 				};
13924 
13925 				/* We have to add GTP header extra word. */
13926 				*total_size += sizeof(ext_word);
13927 				rte_memcpy(data_tail - (*total_size),
13928 					   &ext_word, sizeof(ext_word));
13929 			}
13930 			size = sizeof(struct rte_gtp_hdr);
13931 			break;
13932 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13933 			if (gtp_psc >= 0) {
13934 				fprintf(stderr,
13935 					"Error - Multiple GTP PSC items\n");
13936 				goto error;
13937 			} else {
13938 				const struct rte_flow_item_gtp_psc
13939 					*opt = item->spec;
13940 				struct rte_gtp_psc_generic_hdr *hdr;
13941 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
13942 							 sizeof(int32_t));
13943 
13944 				*total_size += hdr_size;
13945 				hdr = (typeof(hdr))(data_tail - (*total_size));
13946 				memset(hdr, 0, hdr_size);
13947 				*hdr = opt->hdr;
13948 				hdr->ext_hdr_len = 1;
13949 				gtp_psc = i;
13950 				size = 0;
13951 			}
13952 			break;
13953 		case RTE_FLOW_ITEM_TYPE_PFCP:
13954 			size = sizeof(struct rte_flow_item_pfcp);
13955 			break;
13956 		case RTE_FLOW_ITEM_TYPE_FLEX:
13957 			if (item->spec != NULL) {
13958 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
13959 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
13960 			} else {
13961 				size = 0;
13962 				src_spec = NULL;
13963 			}
13964 			break;
13965 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
13966 			size = 0;
13967 			if (item->spec) {
13968 				const struct rte_flow_item_gre_opt
13969 					*opt = item->spec;
13970 				if (opt->checksum_rsvd.checksum) {
13971 					*total_size +=
13972 						sizeof(opt->checksum_rsvd);
13973 					rte_memcpy(data_tail - (*total_size),
13974 						   &opt->checksum_rsvd,
13975 						   sizeof(opt->checksum_rsvd));
13976 				}
13977 				if (opt->key.key) {
13978 					*total_size += sizeof(opt->key.key);
13979 					rte_memcpy(data_tail - (*total_size),
13980 						   &opt->key.key,
13981 						   sizeof(opt->key.key));
13982 				}
13983 				if (opt->sequence.sequence) {
13984 					*total_size += sizeof(opt->sequence.sequence);
13985 					rte_memcpy(data_tail - (*total_size),
13986 						   &opt->sequence.sequence,
13987 						   sizeof(opt->sequence.sequence));
13988 				}
13989 			}
13990 			proto = 0x2F;
13991 			break;
13992 		default:
13993 			fprintf(stderr, "Error - Not supported item\n");
13994 			goto error;
13995 		}
13996 		if (size) {
13997 			*total_size += size;
13998 			rte_memcpy(data_tail - (*total_size), src_spec, size);
13999 			/* update some fields which cannot be set by cmdline */
14000 			update_fields((data_tail - (*total_size)), item,
14001 				      upper_layer);
14002 			upper_layer = proto;
14003 		}
14004 	}
14005 	if (verbose_level & 0x1)
14006 		printf("total data size is %zu\n", (*total_size));
14007 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14008 	memmove(data, (data_tail - (*total_size)), *total_size);
14009 	return;
14010 
14011 error:
14012 	*total_size = 0;
14013 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14014 }
14015 
14016 /** Populate help strings for current token (cmdline API). */
14017 static int
14018 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14019 		     unsigned int size)
14020 {
14021 	struct context *ctx = &cmd_flow_context;
14022 	const struct token *token = &token_list[ctx->prev];
14023 
14024 	(void)hdr;
14025 	if (!size)
14026 		return -1;
14027 	/* Set token type and update global help with details. */
14028 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14029 	if (token->help)
14030 		cmd_set_raw.help_str = token->help;
14031 	else
14032 		cmd_set_raw.help_str = token->name;
14033 	return 0;
14034 }
14035 
14036 /** Token definition template (cmdline API). */
14037 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14038 	.ops = &(struct cmdline_token_ops){
14039 		.parse = cmd_flow_parse,
14040 		.complete_get_nb = cmd_flow_complete_get_nb,
14041 		.complete_get_elt = cmd_flow_complete_get_elt,
14042 		.get_help = cmd_set_raw_get_help,
14043 	},
14044 	.offset = 0,
14045 };
14046 
14047 /** Populate the next dynamic token. */
14048 static void
14049 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14050 	     cmdline_parse_token_hdr_t **hdr_inst)
14051 {
14052 	struct context *ctx = &cmd_flow_context;
14053 
14054 	/* Always reinitialize context before requesting the first token. */
14055 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14056 		cmd_flow_context_init(ctx);
14057 		ctx->curr = START_SET;
14058 	}
14059 	/* Return NULL when no more tokens are expected. */
14060 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14061 		*hdr = NULL;
14062 		return;
14063 	}
14064 	/* Determine if command should end here. */
14065 	if (ctx->eol && ctx->last && ctx->next_num) {
14066 		const enum index *list = ctx->next[ctx->next_num - 1];
14067 		int i;
14068 
14069 		for (i = 0; list[i]; ++i) {
14070 			if (list[i] != END)
14071 				continue;
14072 			*hdr = NULL;
14073 			return;
14074 		}
14075 	}
14076 	*hdr = &cmd_set_raw_token_hdr;
14077 }
14078 
14079 /** Token generator and output processing callback (cmdline API). */
14080 static void
14081 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14082 {
14083 	if (cl == NULL)
14084 		cmd_set_raw_tok(arg0, arg2);
14085 	else
14086 		cmd_set_raw_parsed(arg0);
14087 }
14088 
14089 /** Global parser instance (cmdline API). */
14090 cmdline_parse_inst_t cmd_set_raw = {
14091 	.f = cmd_set_raw_cb,
14092 	.data = NULL, /**< Unused. */
14093 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14094 	.tokens = {
14095 		NULL,
14096 	}, /**< Tokens are returned by cmd_flow_tok(). */
14097 };
14098 
14099 /* *** display raw_encap/raw_decap buf */
14100 struct cmd_show_set_raw_result {
14101 	cmdline_fixed_string_t cmd_show;
14102 	cmdline_fixed_string_t cmd_what;
14103 	cmdline_fixed_string_t cmd_all;
14104 	uint16_t cmd_index;
14105 };
14106 
14107 static void
14108 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14109 {
14110 	struct cmd_show_set_raw_result *res = parsed_result;
14111 	uint16_t index = res->cmd_index;
14112 	uint8_t all = 0;
14113 	uint8_t *raw_data = NULL;
14114 	size_t raw_size = 0;
14115 	char title[16] = {0};
14116 
14117 	RTE_SET_USED(cl);
14118 	RTE_SET_USED(data);
14119 	if (!strcmp(res->cmd_all, "all")) {
14120 		all = 1;
14121 		index = 0;
14122 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14123 		fprintf(stderr, "index should be 0-%u\n",
14124 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14125 		return;
14126 	}
14127 	do {
14128 		if (!strcmp(res->cmd_what, "raw_encap")) {
14129 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14130 			raw_size = raw_encap_confs[index].size;
14131 			snprintf(title, 16, "\nindex: %u", index);
14132 			rte_hexdump(stdout, title, raw_data, raw_size);
14133 		} else {
14134 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14135 			raw_size = raw_decap_confs[index].size;
14136 			snprintf(title, 16, "\nindex: %u", index);
14137 			rte_hexdump(stdout, title, raw_data, raw_size);
14138 		}
14139 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14140 }
14141 
14142 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14143 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14144 			cmd_show, "show");
14145 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14146 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14147 			cmd_what, "raw_encap#raw_decap");
14148 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14149 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14150 			cmd_index, RTE_UINT16);
14151 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14152 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14153 			cmd_all, "all");
14154 cmdline_parse_inst_t cmd_show_set_raw = {
14155 	.f = cmd_show_set_raw_parsed,
14156 	.data = NULL,
14157 	.help_str = "show <raw_encap|raw_decap> <index>",
14158 	.tokens = {
14159 		(void *)&cmd_show_set_raw_cmd_show,
14160 		(void *)&cmd_show_set_raw_cmd_what,
14161 		(void *)&cmd_show_set_raw_cmd_index,
14162 		NULL,
14163 	},
14164 };
14165 cmdline_parse_inst_t cmd_show_set_raw_all = {
14166 	.f = cmd_show_set_raw_parsed,
14167 	.data = NULL,
14168 	.help_str = "show <raw_encap|raw_decap> all",
14169 	.tokens = {
14170 		(void *)&cmd_show_set_raw_cmd_show,
14171 		(void *)&cmd_show_set_raw_cmd_what,
14172 		(void *)&cmd_show_set_raw_cmd_all,
14173 		NULL,
14174 	},
14175 };
14176