xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 89b5642d0d45c22c0ceab57efe3fab3b49ff4324)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5 
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <ctype.h>
13 #include <string.h>
14 
15 #include <rte_string_fns.h>
16 #include <rte_common.h>
17 #include <rte_ethdev.h>
18 #include <rte_byteorder.h>
19 #include <cmdline_parse.h>
20 #include <cmdline_parse_etheraddr.h>
21 #include <cmdline_parse_string.h>
22 #include <cmdline_parse_num.h>
23 #include <rte_flow.h>
24 #include <rte_hexdump.h>
25 #include <rte_vxlan.h>
26 #include <rte_gre.h>
27 #include <rte_mpls.h>
28 #include <rte_gtp.h>
29 #include <rte_geneve.h>
30 
31 #include "testpmd.h"
32 
33 /** Parser token indices. */
34 enum index {
35 	/* Special tokens. */
36 	ZERO = 0,
37 	END,
38 	START_SET,
39 	END_SET,
40 
41 	/* Common tokens. */
42 	COMMON_INTEGER,
43 	COMMON_UNSIGNED,
44 	COMMON_PREFIX,
45 	COMMON_BOOLEAN,
46 	COMMON_STRING,
47 	COMMON_HEX,
48 	COMMON_FILE_PATH,
49 	COMMON_MAC_ADDR,
50 	COMMON_IPV4_ADDR,
51 	COMMON_IPV6_ADDR,
52 	COMMON_RULE_ID,
53 	COMMON_PORT_ID,
54 	COMMON_GROUP_ID,
55 	COMMON_PRIORITY_LEVEL,
56 	COMMON_INDIRECT_ACTION_ID,
57 	COMMON_PROFILE_ID,
58 	COMMON_POLICY_ID,
59 	COMMON_FLEX_HANDLE,
60 	COMMON_FLEX_TOKEN,
61 	COMMON_PATTERN_TEMPLATE_ID,
62 	COMMON_ACTIONS_TEMPLATE_ID,
63 	COMMON_TABLE_ID,
64 	COMMON_QUEUE_ID,
65 
66 	/* TOP-level command. */
67 	ADD,
68 
69 	/* Top-level command. */
70 	SET,
71 	/* Sub-leve commands. */
72 	SET_RAW_ENCAP,
73 	SET_RAW_DECAP,
74 	SET_RAW_INDEX,
75 	SET_SAMPLE_ACTIONS,
76 	SET_SAMPLE_INDEX,
77 	SET_IPV6_EXT_REMOVE,
78 	SET_IPV6_EXT_PUSH,
79 	SET_IPV6_EXT_INDEX,
80 
81 	/* Top-level command. */
82 	FLOW,
83 	/* Sub-level commands. */
84 	INFO,
85 	CONFIGURE,
86 	PATTERN_TEMPLATE,
87 	ACTIONS_TEMPLATE,
88 	TABLE,
89 	FLOW_GROUP,
90 	INDIRECT_ACTION,
91 	VALIDATE,
92 	CREATE,
93 	DESTROY,
94 	UPDATE,
95 	FLUSH,
96 	DUMP,
97 	QUERY,
98 	LIST,
99 	AGED,
100 	ISOLATE,
101 	TUNNEL,
102 	FLEX,
103 	QUEUE,
104 	PUSH,
105 	PULL,
106 	HASH,
107 
108 	/* Flex arguments */
109 	FLEX_ITEM_CREATE,
110 	FLEX_ITEM_DESTROY,
111 
112 	/* Pattern template arguments. */
113 	PATTERN_TEMPLATE_CREATE,
114 	PATTERN_TEMPLATE_DESTROY,
115 	PATTERN_TEMPLATE_CREATE_ID,
116 	PATTERN_TEMPLATE_DESTROY_ID,
117 	PATTERN_TEMPLATE_RELAXED_MATCHING,
118 	PATTERN_TEMPLATE_INGRESS,
119 	PATTERN_TEMPLATE_EGRESS,
120 	PATTERN_TEMPLATE_TRANSFER,
121 	PATTERN_TEMPLATE_SPEC,
122 
123 	/* Actions template arguments. */
124 	ACTIONS_TEMPLATE_CREATE,
125 	ACTIONS_TEMPLATE_DESTROY,
126 	ACTIONS_TEMPLATE_CREATE_ID,
127 	ACTIONS_TEMPLATE_DESTROY_ID,
128 	ACTIONS_TEMPLATE_INGRESS,
129 	ACTIONS_TEMPLATE_EGRESS,
130 	ACTIONS_TEMPLATE_TRANSFER,
131 	ACTIONS_TEMPLATE_SPEC,
132 	ACTIONS_TEMPLATE_MASK,
133 
134 	/* Queue arguments. */
135 	QUEUE_CREATE,
136 	QUEUE_DESTROY,
137 	QUEUE_FLOW_UPDATE_RESIZED,
138 	QUEUE_UPDATE,
139 	QUEUE_AGED,
140 	QUEUE_INDIRECT_ACTION,
141 
142 	/* Queue create arguments. */
143 	QUEUE_CREATE_POSTPONE,
144 	QUEUE_TEMPLATE_TABLE,
145 	QUEUE_PATTERN_TEMPLATE,
146 	QUEUE_ACTIONS_TEMPLATE,
147 	QUEUE_RULE_ID,
148 
149 	/* Queue destroy arguments. */
150 	QUEUE_DESTROY_ID,
151 	QUEUE_DESTROY_POSTPONE,
152 
153 	/* Queue update arguments. */
154 	QUEUE_UPDATE_ID,
155 
156 	/* Queue indirect action arguments */
157 	QUEUE_INDIRECT_ACTION_CREATE,
158 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
159 	QUEUE_INDIRECT_ACTION_UPDATE,
160 	QUEUE_INDIRECT_ACTION_DESTROY,
161 	QUEUE_INDIRECT_ACTION_QUERY,
162 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
163 
164 	/* Queue indirect action create arguments */
165 	QUEUE_INDIRECT_ACTION_CREATE_ID,
166 	QUEUE_INDIRECT_ACTION_INGRESS,
167 	QUEUE_INDIRECT_ACTION_EGRESS,
168 	QUEUE_INDIRECT_ACTION_TRANSFER,
169 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
170 	QUEUE_INDIRECT_ACTION_SPEC,
171 	QUEUE_INDIRECT_ACTION_LIST,
172 
173 	/* Queue indirect action update arguments */
174 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
175 
176 	/* Queue indirect action destroy arguments */
177 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
178 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
179 
180 	/* Queue indirect action query arguments */
181 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
182 
183 	/* Queue indirect action query_update arguments */
184 	QUEUE_INDIRECT_ACTION_QU_MODE,
185 
186 	/* Push arguments. */
187 	PUSH_QUEUE,
188 
189 	/* Pull arguments. */
190 	PULL_QUEUE,
191 
192 	/* Table arguments. */
193 	TABLE_CREATE,
194 	TABLE_DESTROY,
195 	TABLE_RESIZE,
196 	TABLE_RESIZE_COMPLETE,
197 	TABLE_CREATE_ID,
198 	TABLE_DESTROY_ID,
199 	TABLE_RESIZE_ID,
200 	TABLE_RESIZE_RULES_NUMBER,
201 	TABLE_INSERTION_TYPE,
202 	TABLE_INSERTION_TYPE_NAME,
203 	TABLE_HASH_FUNC,
204 	TABLE_HASH_FUNC_NAME,
205 	TABLE_GROUP,
206 	TABLE_PRIORITY,
207 	TABLE_INGRESS,
208 	TABLE_EGRESS,
209 	TABLE_TRANSFER,
210 	TABLE_TRANSFER_WIRE_ORIG,
211 	TABLE_TRANSFER_VPORT_ORIG,
212 	TABLE_RESIZABLE,
213 	TABLE_RULES_NUMBER,
214 	TABLE_PATTERN_TEMPLATE,
215 	TABLE_ACTIONS_TEMPLATE,
216 
217 	/* Group arguments */
218 	GROUP_ID,
219 	GROUP_INGRESS,
220 	GROUP_EGRESS,
221 	GROUP_TRANSFER,
222 	GROUP_SET_MISS_ACTIONS,
223 
224 	/* Hash calculation arguments. */
225 	HASH_CALC_TABLE,
226 	HASH_CALC_PATTERN_INDEX,
227 	HASH_CALC_PATTERN,
228 	HASH_CALC_ENCAP,
229 	HASH_CALC_DEST,
230 	ENCAP_HASH_FIELD_SRC_PORT,
231 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
232 
233 	/* Tunnel arguments. */
234 	TUNNEL_CREATE,
235 	TUNNEL_CREATE_TYPE,
236 	TUNNEL_LIST,
237 	TUNNEL_DESTROY,
238 	TUNNEL_DESTROY_ID,
239 
240 	/* Destroy arguments. */
241 	DESTROY_RULE,
242 	DESTROY_IS_USER_ID,
243 
244 	/* Query arguments. */
245 	QUERY_ACTION,
246 	QUERY_IS_USER_ID,
247 
248 	/* List arguments. */
249 	LIST_GROUP,
250 
251 	/* Destroy aged flow arguments. */
252 	AGED_DESTROY,
253 
254 	/* Validate/create arguments. */
255 	VC_GROUP,
256 	VC_PRIORITY,
257 	VC_INGRESS,
258 	VC_EGRESS,
259 	VC_TRANSFER,
260 	VC_TUNNEL_SET,
261 	VC_TUNNEL_MATCH,
262 	VC_USER_ID,
263 	VC_IS_USER_ID,
264 
265 	/* Dump arguments */
266 	DUMP_ALL,
267 	DUMP_ONE,
268 	DUMP_IS_USER_ID,
269 
270 	/* Configure arguments */
271 	CONFIG_QUEUES_NUMBER,
272 	CONFIG_QUEUES_SIZE,
273 	CONFIG_COUNTERS_NUMBER,
274 	CONFIG_AGING_OBJECTS_NUMBER,
275 	CONFIG_METERS_NUMBER,
276 	CONFIG_CONN_TRACK_NUMBER,
277 	CONFIG_QUOTAS_NUMBER,
278 	CONFIG_FLAGS,
279 	CONFIG_HOST_PORT,
280 
281 	/* Indirect action arguments */
282 	INDIRECT_ACTION_CREATE,
283 	INDIRECT_ACTION_LIST_CREATE,
284 	INDIRECT_ACTION_FLOW_CONF_CREATE,
285 	INDIRECT_ACTION_UPDATE,
286 	INDIRECT_ACTION_DESTROY,
287 	INDIRECT_ACTION_QUERY,
288 	INDIRECT_ACTION_QUERY_UPDATE,
289 
290 	/* Indirect action create arguments */
291 	INDIRECT_ACTION_CREATE_ID,
292 	INDIRECT_ACTION_INGRESS,
293 	INDIRECT_ACTION_EGRESS,
294 	INDIRECT_ACTION_TRANSFER,
295 	INDIRECT_ACTION_SPEC,
296 	INDIRECT_ACTION_LIST,
297 	INDIRECT_ACTION_FLOW_CONF,
298 
299 	/* Indirect action destroy arguments */
300 	INDIRECT_ACTION_DESTROY_ID,
301 
302 	/* Indirect action query-and-update arguments */
303 	INDIRECT_ACTION_QU_MODE,
304 	INDIRECT_ACTION_QU_MODE_NAME,
305 
306 	/* Validate/create pattern. */
307 	ITEM_PATTERN,
308 	ITEM_PARAM_IS,
309 	ITEM_PARAM_SPEC,
310 	ITEM_PARAM_LAST,
311 	ITEM_PARAM_MASK,
312 	ITEM_PARAM_PREFIX,
313 	ITEM_NEXT,
314 	ITEM_END,
315 	ITEM_VOID,
316 	ITEM_INVERT,
317 	ITEM_ANY,
318 	ITEM_ANY_NUM,
319 	ITEM_PORT_ID,
320 	ITEM_PORT_ID_ID,
321 	ITEM_MARK,
322 	ITEM_MARK_ID,
323 	ITEM_RAW,
324 	ITEM_RAW_RELATIVE,
325 	ITEM_RAW_SEARCH,
326 	ITEM_RAW_OFFSET,
327 	ITEM_RAW_LIMIT,
328 	ITEM_RAW_PATTERN,
329 	ITEM_RAW_PATTERN_HEX,
330 	ITEM_ETH,
331 	ITEM_ETH_DST,
332 	ITEM_ETH_SRC,
333 	ITEM_ETH_TYPE,
334 	ITEM_ETH_HAS_VLAN,
335 	ITEM_VLAN,
336 	ITEM_VLAN_TCI,
337 	ITEM_VLAN_PCP,
338 	ITEM_VLAN_DEI,
339 	ITEM_VLAN_VID,
340 	ITEM_VLAN_INNER_TYPE,
341 	ITEM_VLAN_HAS_MORE_VLAN,
342 	ITEM_IPV4,
343 	ITEM_IPV4_VER_IHL,
344 	ITEM_IPV4_TOS,
345 	ITEM_IPV4_LENGTH,
346 	ITEM_IPV4_ID,
347 	ITEM_IPV4_FRAGMENT_OFFSET,
348 	ITEM_IPV4_TTL,
349 	ITEM_IPV4_PROTO,
350 	ITEM_IPV4_SRC,
351 	ITEM_IPV4_DST,
352 	ITEM_IPV6,
353 	ITEM_IPV6_TC,
354 	ITEM_IPV6_FLOW,
355 	ITEM_IPV6_LEN,
356 	ITEM_IPV6_PROTO,
357 	ITEM_IPV6_HOP,
358 	ITEM_IPV6_SRC,
359 	ITEM_IPV6_DST,
360 	ITEM_IPV6_HAS_FRAG_EXT,
361 	ITEM_IPV6_ROUTING_EXT,
362 	ITEM_IPV6_ROUTING_EXT_TYPE,
363 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
364 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
365 	ITEM_ICMP,
366 	ITEM_ICMP_TYPE,
367 	ITEM_ICMP_CODE,
368 	ITEM_ICMP_IDENT,
369 	ITEM_ICMP_SEQ,
370 	ITEM_UDP,
371 	ITEM_UDP_SRC,
372 	ITEM_UDP_DST,
373 	ITEM_TCP,
374 	ITEM_TCP_SRC,
375 	ITEM_TCP_DST,
376 	ITEM_TCP_FLAGS,
377 	ITEM_SCTP,
378 	ITEM_SCTP_SRC,
379 	ITEM_SCTP_DST,
380 	ITEM_SCTP_TAG,
381 	ITEM_SCTP_CKSUM,
382 	ITEM_VXLAN,
383 	ITEM_VXLAN_VNI,
384 	ITEM_VXLAN_FLAG_G,
385 	ITEM_VXLAN_FLAG_VER,
386 	ITEM_VXLAN_FLAG_I,
387 	ITEM_VXLAN_FLAG_P,
388 	ITEM_VXLAN_FLAG_B,
389 	ITEM_VXLAN_FLAG_O,
390 	ITEM_VXLAN_FLAG_D,
391 	ITEM_VXLAN_FLAG_A,
392 	ITEM_VXLAN_GBP_ID,
393 	/* Used for "struct rte_vxlan_hdr", GPE Next protocol */
394 	ITEM_VXLAN_GPE_PROTO,
395 	ITEM_VXLAN_FIRST_RSVD,
396 	ITEM_VXLAN_SECND_RSVD,
397 	ITEM_VXLAN_THIRD_RSVD,
398 	ITEM_VXLAN_LAST_RSVD,
399 	ITEM_E_TAG,
400 	ITEM_E_TAG_GRP_ECID_B,
401 	ITEM_NVGRE,
402 	ITEM_NVGRE_TNI,
403 	ITEM_MPLS,
404 	ITEM_MPLS_LABEL,
405 	ITEM_MPLS_TC,
406 	ITEM_MPLS_S,
407 	ITEM_MPLS_TTL,
408 	ITEM_GRE,
409 	ITEM_GRE_PROTO,
410 	ITEM_GRE_C_RSVD0_VER,
411 	ITEM_GRE_C_BIT,
412 	ITEM_GRE_K_BIT,
413 	ITEM_GRE_S_BIT,
414 	ITEM_FUZZY,
415 	ITEM_FUZZY_THRESH,
416 	ITEM_GTP,
417 	ITEM_GTP_FLAGS,
418 	ITEM_GTP_MSG_TYPE,
419 	ITEM_GTP_TEID,
420 	ITEM_GTPC,
421 	ITEM_GTPU,
422 	ITEM_GENEVE,
423 	ITEM_GENEVE_VNI,
424 	ITEM_GENEVE_PROTO,
425 	ITEM_GENEVE_OPTLEN,
426 	ITEM_VXLAN_GPE,
427 	ITEM_VXLAN_GPE_VNI,
428 	/* Used for "struct rte_vxlan_gpe_hdr", deprecated, prefer ITEM_VXLAN_GPE_PROTO */
429 	ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR,
430 	ITEM_VXLAN_GPE_FLAGS,
431 	ITEM_VXLAN_GPE_RSVD0,
432 	ITEM_VXLAN_GPE_RSVD1,
433 	ITEM_ARP_ETH_IPV4,
434 	ITEM_ARP_ETH_IPV4_SHA,
435 	ITEM_ARP_ETH_IPV4_SPA,
436 	ITEM_ARP_ETH_IPV4_THA,
437 	ITEM_ARP_ETH_IPV4_TPA,
438 	ITEM_IPV6_EXT,
439 	ITEM_IPV6_EXT_NEXT_HDR,
440 	ITEM_IPV6_FRAG_EXT,
441 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
442 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
443 	ITEM_IPV6_FRAG_EXT_ID,
444 	ITEM_ICMP6,
445 	ITEM_ICMP6_TYPE,
446 	ITEM_ICMP6_CODE,
447 	ITEM_ICMP6_ECHO_REQUEST,
448 	ITEM_ICMP6_ECHO_REQUEST_ID,
449 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
450 	ITEM_ICMP6_ECHO_REPLY,
451 	ITEM_ICMP6_ECHO_REPLY_ID,
452 	ITEM_ICMP6_ECHO_REPLY_SEQ,
453 	ITEM_ICMP6_ND_NS,
454 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
455 	ITEM_ICMP6_ND_NA,
456 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
457 	ITEM_ICMP6_ND_OPT,
458 	ITEM_ICMP6_ND_OPT_TYPE,
459 	ITEM_ICMP6_ND_OPT_SLA_ETH,
460 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
461 	ITEM_ICMP6_ND_OPT_TLA_ETH,
462 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
463 	ITEM_META,
464 	ITEM_META_DATA,
465 	ITEM_RANDOM,
466 	ITEM_RANDOM_VALUE,
467 	ITEM_GRE_KEY,
468 	ITEM_GRE_KEY_VALUE,
469 	ITEM_GRE_OPTION,
470 	ITEM_GRE_OPTION_CHECKSUM,
471 	ITEM_GRE_OPTION_KEY,
472 	ITEM_GRE_OPTION_SEQUENCE,
473 	ITEM_GTP_PSC,
474 	ITEM_GTP_PSC_QFI,
475 	ITEM_GTP_PSC_PDU_T,
476 	ITEM_PPPOES,
477 	ITEM_PPPOED,
478 	ITEM_PPPOE_SEID,
479 	ITEM_PPPOE_PROTO_ID,
480 	ITEM_HIGIG2,
481 	ITEM_HIGIG2_CLASSIFICATION,
482 	ITEM_HIGIG2_VID,
483 	ITEM_TAG,
484 	ITEM_TAG_DATA,
485 	ITEM_TAG_INDEX,
486 	ITEM_L2TPV3OIP,
487 	ITEM_L2TPV3OIP_SESSION_ID,
488 	ITEM_ESP,
489 	ITEM_ESP_SPI,
490 	ITEM_AH,
491 	ITEM_AH_SPI,
492 	ITEM_PFCP,
493 	ITEM_PFCP_S_FIELD,
494 	ITEM_PFCP_SEID,
495 	ITEM_ECPRI,
496 	ITEM_ECPRI_COMMON,
497 	ITEM_ECPRI_COMMON_TYPE,
498 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
499 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
500 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
501 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
502 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
503 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
504 	ITEM_GENEVE_OPT,
505 	ITEM_GENEVE_OPT_CLASS,
506 	ITEM_GENEVE_OPT_TYPE,
507 	ITEM_GENEVE_OPT_LENGTH,
508 	ITEM_GENEVE_OPT_DATA,
509 	ITEM_INTEGRITY,
510 	ITEM_INTEGRITY_LEVEL,
511 	ITEM_INTEGRITY_VALUE,
512 	ITEM_CONNTRACK,
513 	ITEM_POL_PORT,
514 	ITEM_POL_METER,
515 	ITEM_POL_POLICY,
516 	ITEM_PORT_REPRESENTOR,
517 	ITEM_PORT_REPRESENTOR_PORT_ID,
518 	ITEM_REPRESENTED_PORT,
519 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
520 	ITEM_FLEX,
521 	ITEM_FLEX_ITEM_HANDLE,
522 	ITEM_FLEX_PATTERN_HANDLE,
523 	ITEM_L2TPV2,
524 	ITEM_L2TPV2_TYPE,
525 	ITEM_L2TPV2_TYPE_DATA,
526 	ITEM_L2TPV2_TYPE_DATA_L,
527 	ITEM_L2TPV2_TYPE_DATA_S,
528 	ITEM_L2TPV2_TYPE_DATA_O,
529 	ITEM_L2TPV2_TYPE_DATA_L_S,
530 	ITEM_L2TPV2_TYPE_CTRL,
531 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
532 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
533 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
534 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
535 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
536 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
537 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
538 	ITEM_L2TPV2_MSG_DATA_S_NS,
539 	ITEM_L2TPV2_MSG_DATA_S_NR,
540 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
541 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
542 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
543 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
544 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
545 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
546 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
547 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
548 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
549 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
550 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
551 	ITEM_L2TPV2_MSG_CTRL_NS,
552 	ITEM_L2TPV2_MSG_CTRL_NR,
553 	ITEM_PPP,
554 	ITEM_PPP_ADDR,
555 	ITEM_PPP_CTRL,
556 	ITEM_PPP_PROTO_ID,
557 	ITEM_METER,
558 	ITEM_METER_COLOR,
559 	ITEM_METER_COLOR_NAME,
560 	ITEM_QUOTA,
561 	ITEM_QUOTA_STATE,
562 	ITEM_QUOTA_STATE_NAME,
563 	ITEM_AGGR_AFFINITY,
564 	ITEM_AGGR_AFFINITY_VALUE,
565 	ITEM_TX_QUEUE,
566 	ITEM_TX_QUEUE_VALUE,
567 	ITEM_IB_BTH,
568 	ITEM_IB_BTH_OPCODE,
569 	ITEM_IB_BTH_PKEY,
570 	ITEM_IB_BTH_DST_QPN,
571 	ITEM_IB_BTH_PSN,
572 	ITEM_IPV6_PUSH_REMOVE_EXT,
573 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
574 	ITEM_PTYPE,
575 	ITEM_PTYPE_VALUE,
576 	ITEM_NSH,
577 	ITEM_COMPARE,
578 	ITEM_COMPARE_OP,
579 	ITEM_COMPARE_OP_VALUE,
580 	ITEM_COMPARE_FIELD_A_TYPE,
581 	ITEM_COMPARE_FIELD_A_TYPE_VALUE,
582 	ITEM_COMPARE_FIELD_A_LEVEL,
583 	ITEM_COMPARE_FIELD_A_LEVEL_VALUE,
584 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
585 	ITEM_COMPARE_FIELD_A_TYPE_ID,
586 	ITEM_COMPARE_FIELD_A_CLASS_ID,
587 	ITEM_COMPARE_FIELD_A_OFFSET,
588 	ITEM_COMPARE_FIELD_B_TYPE,
589 	ITEM_COMPARE_FIELD_B_TYPE_VALUE,
590 	ITEM_COMPARE_FIELD_B_LEVEL,
591 	ITEM_COMPARE_FIELD_B_LEVEL_VALUE,
592 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
593 	ITEM_COMPARE_FIELD_B_TYPE_ID,
594 	ITEM_COMPARE_FIELD_B_CLASS_ID,
595 	ITEM_COMPARE_FIELD_B_OFFSET,
596 	ITEM_COMPARE_FIELD_B_VALUE,
597 	ITEM_COMPARE_FIELD_B_POINTER,
598 	ITEM_COMPARE_FIELD_WIDTH,
599 
600 	/* Validate/create actions. */
601 	ACTIONS,
602 	ACTION_NEXT,
603 	ACTION_END,
604 	ACTION_VOID,
605 	ACTION_PASSTHRU,
606 	ACTION_SKIP_CMAN,
607 	ACTION_JUMP,
608 	ACTION_JUMP_GROUP,
609 	ACTION_MARK,
610 	ACTION_MARK_ID,
611 	ACTION_FLAG,
612 	ACTION_QUEUE,
613 	ACTION_QUEUE_INDEX,
614 	ACTION_DROP,
615 	ACTION_COUNT,
616 	ACTION_COUNT_ID,
617 	ACTION_RSS,
618 	ACTION_RSS_FUNC,
619 	ACTION_RSS_LEVEL,
620 	ACTION_RSS_FUNC_DEFAULT,
621 	ACTION_RSS_FUNC_TOEPLITZ,
622 	ACTION_RSS_FUNC_SIMPLE_XOR,
623 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
624 	ACTION_RSS_TYPES,
625 	ACTION_RSS_TYPE,
626 	ACTION_RSS_KEY,
627 	ACTION_RSS_KEY_LEN,
628 	ACTION_RSS_QUEUES,
629 	ACTION_RSS_QUEUE,
630 	ACTION_PF,
631 	ACTION_VF,
632 	ACTION_VF_ORIGINAL,
633 	ACTION_VF_ID,
634 	ACTION_PORT_ID,
635 	ACTION_PORT_ID_ORIGINAL,
636 	ACTION_PORT_ID_ID,
637 	ACTION_METER,
638 	ACTION_METER_COLOR,
639 	ACTION_METER_COLOR_TYPE,
640 	ACTION_METER_COLOR_GREEN,
641 	ACTION_METER_COLOR_YELLOW,
642 	ACTION_METER_COLOR_RED,
643 	ACTION_METER_ID,
644 	ACTION_METER_MARK,
645 	ACTION_METER_PROFILE,
646 	ACTION_METER_PROFILE_ID2PTR,
647 	ACTION_METER_POLICY,
648 	ACTION_METER_POLICY_ID2PTR,
649 	ACTION_METER_COLOR_MODE,
650 	ACTION_METER_STATE,
651 	ACTION_OF_DEC_NW_TTL,
652 	ACTION_OF_POP_VLAN,
653 	ACTION_OF_PUSH_VLAN,
654 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
655 	ACTION_OF_SET_VLAN_VID,
656 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
657 	ACTION_OF_SET_VLAN_PCP,
658 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
659 	ACTION_OF_POP_MPLS,
660 	ACTION_OF_POP_MPLS_ETHERTYPE,
661 	ACTION_OF_PUSH_MPLS,
662 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
663 	ACTION_VXLAN_ENCAP,
664 	ACTION_VXLAN_DECAP,
665 	ACTION_NVGRE_ENCAP,
666 	ACTION_NVGRE_DECAP,
667 	ACTION_L2_ENCAP,
668 	ACTION_L2_DECAP,
669 	ACTION_MPLSOGRE_ENCAP,
670 	ACTION_MPLSOGRE_DECAP,
671 	ACTION_MPLSOUDP_ENCAP,
672 	ACTION_MPLSOUDP_DECAP,
673 	ACTION_SET_IPV4_SRC,
674 	ACTION_SET_IPV4_SRC_IPV4_SRC,
675 	ACTION_SET_IPV4_DST,
676 	ACTION_SET_IPV4_DST_IPV4_DST,
677 	ACTION_SET_IPV6_SRC,
678 	ACTION_SET_IPV6_SRC_IPV6_SRC,
679 	ACTION_SET_IPV6_DST,
680 	ACTION_SET_IPV6_DST_IPV6_DST,
681 	ACTION_SET_TP_SRC,
682 	ACTION_SET_TP_SRC_TP_SRC,
683 	ACTION_SET_TP_DST,
684 	ACTION_SET_TP_DST_TP_DST,
685 	ACTION_MAC_SWAP,
686 	ACTION_DEC_TTL,
687 	ACTION_SET_TTL,
688 	ACTION_SET_TTL_TTL,
689 	ACTION_SET_MAC_SRC,
690 	ACTION_SET_MAC_SRC_MAC_SRC,
691 	ACTION_SET_MAC_DST,
692 	ACTION_SET_MAC_DST_MAC_DST,
693 	ACTION_INC_TCP_SEQ,
694 	ACTION_INC_TCP_SEQ_VALUE,
695 	ACTION_DEC_TCP_SEQ,
696 	ACTION_DEC_TCP_SEQ_VALUE,
697 	ACTION_INC_TCP_ACK,
698 	ACTION_INC_TCP_ACK_VALUE,
699 	ACTION_DEC_TCP_ACK,
700 	ACTION_DEC_TCP_ACK_VALUE,
701 	ACTION_RAW_ENCAP,
702 	ACTION_RAW_DECAP,
703 	ACTION_RAW_ENCAP_SIZE,
704 	ACTION_RAW_ENCAP_INDEX,
705 	ACTION_RAW_ENCAP_INDEX_VALUE,
706 	ACTION_RAW_DECAP_INDEX,
707 	ACTION_RAW_DECAP_INDEX_VALUE,
708 	ACTION_SET_TAG,
709 	ACTION_SET_TAG_DATA,
710 	ACTION_SET_TAG_INDEX,
711 	ACTION_SET_TAG_MASK,
712 	ACTION_SET_META,
713 	ACTION_SET_META_DATA,
714 	ACTION_SET_META_MASK,
715 	ACTION_SET_IPV4_DSCP,
716 	ACTION_SET_IPV4_DSCP_VALUE,
717 	ACTION_SET_IPV6_DSCP,
718 	ACTION_SET_IPV6_DSCP_VALUE,
719 	ACTION_AGE,
720 	ACTION_AGE_TIMEOUT,
721 	ACTION_AGE_UPDATE,
722 	ACTION_AGE_UPDATE_TIMEOUT,
723 	ACTION_AGE_UPDATE_TOUCH,
724 	ACTION_SAMPLE,
725 	ACTION_SAMPLE_RATIO,
726 	ACTION_SAMPLE_INDEX,
727 	ACTION_SAMPLE_INDEX_VALUE,
728 	ACTION_INDIRECT,
729 	ACTION_INDIRECT_LIST,
730 	ACTION_INDIRECT_LIST_HANDLE,
731 	ACTION_INDIRECT_LIST_CONF,
732 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
733 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
734 	ACTION_SHARED_INDIRECT,
735 	INDIRECT_ACTION_PORT,
736 	INDIRECT_ACTION_ID2PTR,
737 	ACTION_MODIFY_FIELD,
738 	ACTION_MODIFY_FIELD_OP,
739 	ACTION_MODIFY_FIELD_OP_VALUE,
740 	ACTION_MODIFY_FIELD_DST_TYPE,
741 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
742 	ACTION_MODIFY_FIELD_DST_LEVEL,
743 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
744 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
745 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
746 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
747 	ACTION_MODIFY_FIELD_DST_OFFSET,
748 	ACTION_MODIFY_FIELD_SRC_TYPE,
749 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
750 	ACTION_MODIFY_FIELD_SRC_LEVEL,
751 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
752 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
753 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
754 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
755 	ACTION_MODIFY_FIELD_SRC_OFFSET,
756 	ACTION_MODIFY_FIELD_SRC_VALUE,
757 	ACTION_MODIFY_FIELD_SRC_POINTER,
758 	ACTION_MODIFY_FIELD_WIDTH,
759 	ACTION_CONNTRACK,
760 	ACTION_CONNTRACK_UPDATE,
761 	ACTION_CONNTRACK_UPDATE_DIR,
762 	ACTION_CONNTRACK_UPDATE_CTX,
763 	ACTION_POL_G,
764 	ACTION_POL_Y,
765 	ACTION_POL_R,
766 	ACTION_PORT_REPRESENTOR,
767 	ACTION_PORT_REPRESENTOR_PORT_ID,
768 	ACTION_REPRESENTED_PORT,
769 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
770 	ACTION_SEND_TO_KERNEL,
771 	ACTION_QUOTA_CREATE,
772 	ACTION_QUOTA_CREATE_LIMIT,
773 	ACTION_QUOTA_CREATE_MODE,
774 	ACTION_QUOTA_CREATE_MODE_NAME,
775 	ACTION_QUOTA_QU,
776 	ACTION_QUOTA_QU_LIMIT,
777 	ACTION_QUOTA_QU_UPDATE_OP,
778 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
779 	ACTION_IPV6_EXT_REMOVE,
780 	ACTION_IPV6_EXT_REMOVE_INDEX,
781 	ACTION_IPV6_EXT_REMOVE_INDEX_VALUE,
782 	ACTION_IPV6_EXT_PUSH,
783 	ACTION_IPV6_EXT_PUSH_INDEX,
784 	ACTION_IPV6_EXT_PUSH_INDEX_VALUE,
785 	ACTION_NAT64,
786 	ACTION_NAT64_MODE,
787 	ACTION_JUMP_TO_TABLE_INDEX,
788 	ACTION_JUMP_TO_TABLE_INDEX_TABLE,
789 	ACTION_JUMP_TO_TABLE_INDEX_INDEX,
790 };
791 
792 /** Maximum size for pattern in struct rte_flow_item_raw. */
793 #define ITEM_RAW_PATTERN_SIZE 512
794 
795 /** Maximum size for GENEVE option data pattern in bytes. */
796 #define ITEM_GENEVE_OPT_DATA_SIZE 124
797 
798 /** Storage size for struct rte_flow_item_raw including pattern. */
799 #define ITEM_RAW_SIZE \
800 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
801 
802 static const char *const compare_ops[] = {
803 	"eq", "ne", "lt", "le", "gt", "ge", NULL
804 };
805 
806 /** Maximum size for external pattern in struct rte_flow_field_data. */
807 #define FLOW_FIELD_PATTERN_SIZE 32
808 
809 /** Storage size for struct rte_flow_action_modify_field including pattern. */
810 #define ACTION_MODIFY_SIZE \
811 	(sizeof(struct rte_flow_action_modify_field) + \
812 	FLOW_FIELD_PATTERN_SIZE)
813 
814 /** Maximum number of queue indices in struct rte_flow_action_rss. */
815 #define ACTION_RSS_QUEUE_NUM 128
816 
817 /** Storage for struct rte_flow_action_rss including external data. */
818 struct action_rss_data {
819 	struct rte_flow_action_rss conf;
820 	uint8_t key[RSS_HASH_KEY_LENGTH];
821 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
822 };
823 
824 /** Maximum data size in struct rte_flow_action_raw_encap. */
825 #define ACTION_RAW_ENCAP_MAX_DATA 512
826 #define RAW_ENCAP_CONFS_MAX_NUM 8
827 
828 /** Storage for struct rte_flow_action_raw_encap. */
829 struct raw_encap_conf {
830 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
831 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
832 	size_t size;
833 };
834 
835 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
836 
837 /** Storage for struct rte_flow_action_raw_encap including external data. */
838 struct action_raw_encap_data {
839 	struct rte_flow_action_raw_encap conf;
840 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
841 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
842 	uint16_t idx;
843 };
844 
845 /** Storage for struct rte_flow_action_raw_decap. */
846 struct raw_decap_conf {
847 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
848 	size_t size;
849 };
850 
851 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
852 
853 /** Storage for struct rte_flow_action_raw_decap including external data. */
854 struct action_raw_decap_data {
855 	struct rte_flow_action_raw_decap conf;
856 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
857 	uint16_t idx;
858 };
859 
860 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */
861 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512
862 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8
863 
864 /** Storage for struct rte_flow_action_ipv6_ext_push. */
865 struct ipv6_ext_push_conf {
866 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
867 	size_t size;
868 	uint8_t type;
869 };
870 
871 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
872 
873 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */
874 struct action_ipv6_ext_push_data {
875 	struct rte_flow_action_ipv6_ext_push conf;
876 	uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA];
877 	uint8_t type;
878 	uint16_t idx;
879 };
880 
881 /** Storage for struct rte_flow_action_ipv6_ext_remove. */
882 struct ipv6_ext_remove_conf {
883 	struct rte_flow_action_ipv6_ext_remove conf;
884 	uint8_t type;
885 };
886 
887 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM];
888 
889 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */
890 struct action_ipv6_ext_remove_data {
891 	struct rte_flow_action_ipv6_ext_remove conf;
892 	uint8_t type;
893 	uint16_t idx;
894 };
895 
896 struct vxlan_encap_conf vxlan_encap_conf = {
897 	.select_ipv4 = 1,
898 	.select_vlan = 0,
899 	.select_tos_ttl = 0,
900 	.vni = { 0x00, 0x00, 0x00 },
901 	.udp_src = 0,
902 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
903 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
904 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
905 	.ipv6_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
906 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
907 	.ipv6_dst = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
908 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11 },
909 	.vlan_tci = 0,
910 	.ip_tos = 0,
911 	.ip_ttl = 255,
912 	.eth_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
913 	.eth_dst = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
914 };
915 
916 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
917 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
918 
919 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
920 struct action_vxlan_encap_data {
921 	struct rte_flow_action_vxlan_encap conf;
922 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
923 	struct rte_flow_item_eth item_eth;
924 	struct rte_flow_item_vlan item_vlan;
925 	union {
926 		struct rte_flow_item_ipv4 item_ipv4;
927 		struct rte_flow_item_ipv6 item_ipv6;
928 	};
929 	struct rte_flow_item_udp item_udp;
930 	struct rte_flow_item_vxlan item_vxlan;
931 };
932 
933 struct nvgre_encap_conf nvgre_encap_conf = {
934 	.select_ipv4 = 1,
935 	.select_vlan = 0,
936 	.tni = { 0x00, 0x00, 0x00 },
937 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
938 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
939 	.ipv6_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
940 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
941 	.ipv6_dst = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
942 		      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11 },
943 	.vlan_tci = 0,
944 	.eth_src = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
945 	.eth_dst = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
946 };
947 
948 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
949 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
950 
951 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
952 struct action_nvgre_encap_data {
953 	struct rte_flow_action_nvgre_encap conf;
954 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
955 	struct rte_flow_item_eth item_eth;
956 	struct rte_flow_item_vlan item_vlan;
957 	union {
958 		struct rte_flow_item_ipv4 item_ipv4;
959 		struct rte_flow_item_ipv6 item_ipv6;
960 	};
961 	struct rte_flow_item_nvgre item_nvgre;
962 };
963 
964 struct l2_encap_conf l2_encap_conf;
965 
966 struct l2_decap_conf l2_decap_conf;
967 
968 struct mplsogre_encap_conf mplsogre_encap_conf;
969 
970 struct mplsogre_decap_conf mplsogre_decap_conf;
971 
972 struct mplsoudp_encap_conf mplsoudp_encap_conf;
973 
974 struct mplsoudp_decap_conf mplsoudp_decap_conf;
975 
976 struct rte_flow_action_conntrack conntrack_context;
977 
978 #define ACTION_SAMPLE_ACTIONS_NUM 10
979 #define RAW_SAMPLE_CONFS_MAX_NUM 8
980 /** Storage for struct rte_flow_action_sample including external data. */
981 struct action_sample_data {
982 	struct rte_flow_action_sample conf;
983 	uint32_t idx;
984 };
985 /** Storage for struct rte_flow_action_sample. */
986 struct raw_sample_conf {
987 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
988 };
989 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
990 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
991 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
992 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
993 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
994 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
995 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
996 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
997 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
998 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
999 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
1000 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
1001 
1002 static const char *const modify_field_ops[] = {
1003 	"set", "add", "sub", NULL
1004 };
1005 
1006 static const char *const flow_field_ids[] = {
1007 	"start", "mac_dst", "mac_src",
1008 	"vlan_type", "vlan_id", "mac_type",
1009 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
1010 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
1011 	"tcp_port_src", "tcp_port_dst",
1012 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
1013 	"udp_port_src", "udp_port_dst",
1014 	"vxlan_vni", "geneve_vni", "gtp_teid",
1015 	"tag", "mark", "meta", "pointer", "value",
1016 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
1017 	"ipv6_proto",
1018 	"flex_item",
1019 	"hash_result",
1020 	"geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls",
1021 	"tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len",
1022 	"ipv4_proto",
1023 	"ipv6_flow_label", "ipv6_traffic_class",
1024 	"esp_spi", "esp_seq_num", "esp_proto",
1025 	"random",
1026 	"vxlan_last_rsvd",
1027 	NULL
1028 };
1029 
1030 static const char *const meter_colors[] = {
1031 	"green", "yellow", "red", "all", NULL
1032 };
1033 
1034 static const char *const table_insertion_types[] = {
1035 	"pattern", "index", "index_with_pattern", NULL
1036 };
1037 
1038 static const char *const table_hash_funcs[] = {
1039 	"default", "linear", "crc32", "crc16", NULL
1040 };
1041 
1042 #define RAW_IPSEC_CONFS_MAX_NUM 8
1043 
1044 /** Maximum number of subsequent tokens and arguments on the stack. */
1045 #define CTX_STACK_SIZE 16
1046 
1047 /** Parser context. */
1048 struct context {
1049 	/** Stack of subsequent token lists to process. */
1050 	const enum index *next[CTX_STACK_SIZE];
1051 	/** Arguments for stacked tokens. */
1052 	const void *args[CTX_STACK_SIZE];
1053 	enum index curr; /**< Current token index. */
1054 	enum index prev; /**< Index of the last token seen. */
1055 	int next_num; /**< Number of entries in next[]. */
1056 	int args_num; /**< Number of entries in args[]. */
1057 	uint32_t eol:1; /**< EOL has been detected. */
1058 	uint32_t last:1; /**< No more arguments. */
1059 	portid_t port; /**< Current port ID (for completions). */
1060 	uint32_t objdata; /**< Object-specific data. */
1061 	void *object; /**< Address of current object for relative offsets. */
1062 	void *objmask; /**< Object a full mask must be written to. */
1063 };
1064 
1065 /** Token argument. */
1066 struct arg {
1067 	uint32_t hton:1; /**< Use network byte ordering. */
1068 	uint32_t sign:1; /**< Value is signed. */
1069 	uint32_t bounded:1; /**< Value is bounded. */
1070 	uintmax_t min; /**< Minimum value if bounded. */
1071 	uintmax_t max; /**< Maximum value if bounded. */
1072 	uint32_t offset; /**< Relative offset from ctx->object. */
1073 	uint32_t size; /**< Field size. */
1074 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
1075 };
1076 
1077 /** Parser token definition. */
1078 struct token {
1079 	/** Type displayed during completion (defaults to "TOKEN"). */
1080 	const char *type;
1081 	/** Help displayed during completion (defaults to token name). */
1082 	const char *help;
1083 	/** Private data used by parser functions. */
1084 	const void *priv;
1085 	/**
1086 	 * Lists of subsequent tokens to push on the stack. Each call to the
1087 	 * parser consumes the last entry of that stack.
1088 	 */
1089 	const enum index *const *next;
1090 	/** Arguments stack for subsequent tokens that need them. */
1091 	const struct arg *const *args;
1092 	/**
1093 	 * Token-processing callback, returns -1 in case of error, the
1094 	 * length of the matched string otherwise. If NULL, attempts to
1095 	 * match the token name.
1096 	 *
1097 	 * If buf is not NULL, the result should be stored in it according
1098 	 * to context. An error is returned if not large enough.
1099 	 */
1100 	int (*call)(struct context *ctx, const struct token *token,
1101 		    const char *str, unsigned int len,
1102 		    void *buf, unsigned int size);
1103 	/**
1104 	 * Callback that provides possible values for this token, used for
1105 	 * completion. Returns -1 in case of error, the number of possible
1106 	 * values otherwise. If NULL, the token name is used.
1107 	 *
1108 	 * If buf is not NULL, entry index ent is written to buf and the
1109 	 * full length of the entry is returned (same behavior as
1110 	 * snprintf()).
1111 	 */
1112 	int (*comp)(struct context *ctx, const struct token *token,
1113 		    unsigned int ent, char *buf, unsigned int size);
1114 	/** Mandatory token name, no default value. */
1115 	const char *name;
1116 };
1117 
1118 /** Static initializer for the next field. */
1119 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
1120 
1121 /** Static initializer for a NEXT() entry. */
1122 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
1123 
1124 /** Static initializer for the args field. */
1125 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
1126 
1127 /** Static initializer for ARGS() to target a field. */
1128 #define ARGS_ENTRY(s, f) \
1129 	(&(const struct arg){ \
1130 		.offset = offsetof(s, f), \
1131 		.size = sizeof(((s *)0)->f), \
1132 	})
1133 
1134 /** Static initializer for ARGS() to target a bit-field. */
1135 #define ARGS_ENTRY_BF(s, f, b) \
1136 	(&(const struct arg){ \
1137 		.size = sizeof(s), \
1138 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
1139 	})
1140 
1141 /** Static initializer for ARGS() to target a field with limits. */
1142 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
1143 	(&(const struct arg){ \
1144 		.bounded = 1, \
1145 		.min = (i), \
1146 		.max = (a), \
1147 		.offset = offsetof(s, f), \
1148 		.size = sizeof(((s *)0)->f), \
1149 	})
1150 
1151 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1152 #define ARGS_ENTRY_MASK(s, f, m) \
1153 	(&(const struct arg){ \
1154 		.offset = offsetof(s, f), \
1155 		.size = sizeof(((s *)0)->f), \
1156 		.mask = (const void *)(m), \
1157 	})
1158 
1159 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1160 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1161 	(&(const struct arg){ \
1162 		.hton = 1, \
1163 		.offset = offsetof(s, f), \
1164 		.size = sizeof(((s *)0)->f), \
1165 		.mask = (const void *)(m), \
1166 	})
1167 
1168 /** Static initializer for ARGS() to target a pointer. */
1169 #define ARGS_ENTRY_PTR(s, f) \
1170 	(&(const struct arg){ \
1171 		.size = sizeof(*((s *)0)->f), \
1172 	})
1173 
1174 /** Static initializer for ARGS() with arbitrary offset and size. */
1175 #define ARGS_ENTRY_ARB(o, s) \
1176 	(&(const struct arg){ \
1177 		.offset = (o), \
1178 		.size = (s), \
1179 	})
1180 
1181 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1182 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1183 	(&(const struct arg){ \
1184 		.bounded = 1, \
1185 		.min = (i), \
1186 		.max = (a), \
1187 		.offset = (o), \
1188 		.size = (s), \
1189 	})
1190 
1191 /** Same as ARGS_ENTRY() using network byte ordering. */
1192 #define ARGS_ENTRY_HTON(s, f) \
1193 	(&(const struct arg){ \
1194 		.hton = 1, \
1195 		.offset = offsetof(s, f), \
1196 		.size = sizeof(((s *)0)->f), \
1197 	})
1198 
1199 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1200 #define ARG_ENTRY_HTON(s) \
1201 	(&(const struct arg){ \
1202 		.hton = 1, \
1203 		.offset = 0, \
1204 		.size = sizeof(s), \
1205 	})
1206 
1207 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1208 struct buffer {
1209 	enum index command; /**< Flow command. */
1210 	portid_t port; /**< Affected port ID. */
1211 	queueid_t queue; /** Async queue ID. */
1212 	bool postpone; /** Postpone async operation */
1213 	union {
1214 		struct {
1215 			struct rte_flow_port_attr port_attr;
1216 			uint32_t nb_queue;
1217 			struct rte_flow_queue_attr queue_attr;
1218 		} configure; /**< Configuration arguments. */
1219 		struct {
1220 			uint32_t *template_id;
1221 			uint32_t template_id_n;
1222 		} templ_destroy; /**< Template destroy arguments. */
1223 		struct {
1224 			uint32_t id;
1225 			struct rte_flow_template_table_attr attr;
1226 			uint32_t *pat_templ_id;
1227 			uint32_t pat_templ_id_n;
1228 			uint32_t *act_templ_id;
1229 			uint32_t act_templ_id_n;
1230 		} table; /**< Table arguments. */
1231 		struct {
1232 			uint32_t *table_id;
1233 			uint32_t table_id_n;
1234 		} table_destroy; /**< Template destroy arguments. */
1235 		struct {
1236 			uint32_t *action_id;
1237 			uint32_t action_id_n;
1238 		} ia_destroy; /**< Indirect action destroy arguments. */
1239 		struct {
1240 			uint32_t action_id;
1241 			enum rte_flow_query_update_mode qu_mode;
1242 		} ia; /* Indirect action query arguments */
1243 		struct {
1244 			uint32_t table_id;
1245 			uint32_t pat_templ_id;
1246 			uint32_t rule_id;
1247 			uint32_t act_templ_id;
1248 			struct rte_flow_attr attr;
1249 			struct tunnel_ops tunnel_ops;
1250 			uintptr_t user_id;
1251 			struct rte_flow_item *pattern;
1252 			struct rte_flow_action *actions;
1253 			struct rte_flow_action *masks;
1254 			uint32_t pattern_n;
1255 			uint32_t actions_n;
1256 			uint8_t *data;
1257 			enum rte_flow_encap_hash_field field;
1258 			uint8_t encap_hash;
1259 		} vc; /**< Validate/create arguments. */
1260 		struct {
1261 			uint64_t *rule;
1262 			uint64_t rule_n;
1263 			bool is_user_id;
1264 		} destroy; /**< Destroy arguments. */
1265 		struct {
1266 			char file[128];
1267 			bool mode;
1268 			uint64_t rule;
1269 			bool is_user_id;
1270 		} dump; /**< Dump arguments. */
1271 		struct {
1272 			uint64_t rule;
1273 			struct rte_flow_action action;
1274 			bool is_user_id;
1275 		} query; /**< Query arguments. */
1276 		struct {
1277 			uint32_t *group;
1278 			uint32_t group_n;
1279 		} list; /**< List arguments. */
1280 		struct {
1281 			int set;
1282 		} isolate; /**< Isolated mode arguments. */
1283 		struct {
1284 			int destroy;
1285 		} aged; /**< Aged arguments. */
1286 		struct {
1287 			uint32_t policy_id;
1288 		} policy;/**< Policy arguments. */
1289 		struct {
1290 			uint16_t token;
1291 			uintptr_t uintptr;
1292 			char filename[128];
1293 		} flex; /**< Flex arguments*/
1294 	} args; /**< Command arguments. */
1295 };
1296 
1297 /** Private data for pattern items. */
1298 struct parse_item_priv {
1299 	enum rte_flow_item_type type; /**< Item type. */
1300 	uint32_t size; /**< Size of item specification structure. */
1301 };
1302 
1303 #define PRIV_ITEM(t, s) \
1304 	(&(const struct parse_item_priv){ \
1305 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1306 		.size = s, \
1307 	})
1308 
1309 /** Private data for actions. */
1310 struct parse_action_priv {
1311 	enum rte_flow_action_type type; /**< Action type. */
1312 	uint32_t size; /**< Size of action configuration structure. */
1313 };
1314 
1315 #define PRIV_ACTION(t, s) \
1316 	(&(const struct parse_action_priv){ \
1317 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1318 		.size = s, \
1319 	})
1320 
1321 static const enum index next_flex_item[] = {
1322 	FLEX_ITEM_CREATE,
1323 	FLEX_ITEM_DESTROY,
1324 	ZERO,
1325 };
1326 
1327 static const enum index next_config_attr[] = {
1328 	CONFIG_QUEUES_NUMBER,
1329 	CONFIG_QUEUES_SIZE,
1330 	CONFIG_COUNTERS_NUMBER,
1331 	CONFIG_AGING_OBJECTS_NUMBER,
1332 	CONFIG_METERS_NUMBER,
1333 	CONFIG_CONN_TRACK_NUMBER,
1334 	CONFIG_QUOTAS_NUMBER,
1335 	CONFIG_FLAGS,
1336 	CONFIG_HOST_PORT,
1337 	END,
1338 	ZERO,
1339 };
1340 
1341 static const enum index next_pt_subcmd[] = {
1342 	PATTERN_TEMPLATE_CREATE,
1343 	PATTERN_TEMPLATE_DESTROY,
1344 	ZERO,
1345 };
1346 
1347 static const enum index next_pt_attr[] = {
1348 	PATTERN_TEMPLATE_CREATE_ID,
1349 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1350 	PATTERN_TEMPLATE_INGRESS,
1351 	PATTERN_TEMPLATE_EGRESS,
1352 	PATTERN_TEMPLATE_TRANSFER,
1353 	PATTERN_TEMPLATE_SPEC,
1354 	ZERO,
1355 };
1356 
1357 static const enum index next_pt_destroy_attr[] = {
1358 	PATTERN_TEMPLATE_DESTROY_ID,
1359 	END,
1360 	ZERO,
1361 };
1362 
1363 static const enum index next_at_subcmd[] = {
1364 	ACTIONS_TEMPLATE_CREATE,
1365 	ACTIONS_TEMPLATE_DESTROY,
1366 	ZERO,
1367 };
1368 
1369 static const enum index next_at_attr[] = {
1370 	ACTIONS_TEMPLATE_CREATE_ID,
1371 	ACTIONS_TEMPLATE_INGRESS,
1372 	ACTIONS_TEMPLATE_EGRESS,
1373 	ACTIONS_TEMPLATE_TRANSFER,
1374 	ACTIONS_TEMPLATE_SPEC,
1375 	ZERO,
1376 };
1377 
1378 static const enum index next_at_destroy_attr[] = {
1379 	ACTIONS_TEMPLATE_DESTROY_ID,
1380 	END,
1381 	ZERO,
1382 };
1383 
1384 static const enum index next_group_attr[] = {
1385 	GROUP_INGRESS,
1386 	GROUP_EGRESS,
1387 	GROUP_TRANSFER,
1388 	GROUP_SET_MISS_ACTIONS,
1389 	ZERO,
1390 };
1391 
1392 static const enum index next_table_subcmd[] = {
1393 	TABLE_CREATE,
1394 	TABLE_DESTROY,
1395 	TABLE_RESIZE,
1396 	TABLE_RESIZE_COMPLETE,
1397 	ZERO,
1398 };
1399 
1400 static const enum index next_table_attr[] = {
1401 	TABLE_CREATE_ID,
1402 	TABLE_GROUP,
1403 	TABLE_INSERTION_TYPE,
1404 	TABLE_HASH_FUNC,
1405 	TABLE_PRIORITY,
1406 	TABLE_INGRESS,
1407 	TABLE_EGRESS,
1408 	TABLE_TRANSFER,
1409 	TABLE_TRANSFER_WIRE_ORIG,
1410 	TABLE_TRANSFER_VPORT_ORIG,
1411 	TABLE_RESIZABLE,
1412 	TABLE_RULES_NUMBER,
1413 	TABLE_PATTERN_TEMPLATE,
1414 	TABLE_ACTIONS_TEMPLATE,
1415 	END,
1416 	ZERO,
1417 };
1418 
1419 static const enum index next_table_destroy_attr[] = {
1420 	TABLE_DESTROY_ID,
1421 	END,
1422 	ZERO,
1423 };
1424 
1425 static const enum index next_queue_subcmd[] = {
1426 	QUEUE_CREATE,
1427 	QUEUE_DESTROY,
1428 	QUEUE_FLOW_UPDATE_RESIZED,
1429 	QUEUE_UPDATE,
1430 	QUEUE_AGED,
1431 	QUEUE_INDIRECT_ACTION,
1432 	ZERO,
1433 };
1434 
1435 static const enum index next_queue_destroy_attr[] = {
1436 	QUEUE_DESTROY_ID,
1437 	END,
1438 	ZERO,
1439 };
1440 
1441 static const enum index next_qia_subcmd[] = {
1442 	QUEUE_INDIRECT_ACTION_CREATE,
1443 	QUEUE_INDIRECT_ACTION_UPDATE,
1444 	QUEUE_INDIRECT_ACTION_DESTROY,
1445 	QUEUE_INDIRECT_ACTION_QUERY,
1446 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1447 	ZERO,
1448 };
1449 
1450 static const enum index next_qia_create_attr[] = {
1451 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1452 	QUEUE_INDIRECT_ACTION_INGRESS,
1453 	QUEUE_INDIRECT_ACTION_EGRESS,
1454 	QUEUE_INDIRECT_ACTION_TRANSFER,
1455 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1456 	QUEUE_INDIRECT_ACTION_SPEC,
1457 	QUEUE_INDIRECT_ACTION_LIST,
1458 	ZERO,
1459 };
1460 
1461 static const enum index next_qia_update_attr[] = {
1462 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1463 	QUEUE_INDIRECT_ACTION_SPEC,
1464 	ZERO,
1465 };
1466 
1467 static const enum index next_qia_destroy_attr[] = {
1468 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1469 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1470 	END,
1471 	ZERO,
1472 };
1473 
1474 static const enum index next_qia_query_attr[] = {
1475 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1476 	END,
1477 	ZERO,
1478 };
1479 
1480 static const enum index next_ia_create_attr[] = {
1481 	INDIRECT_ACTION_CREATE_ID,
1482 	INDIRECT_ACTION_INGRESS,
1483 	INDIRECT_ACTION_EGRESS,
1484 	INDIRECT_ACTION_TRANSFER,
1485 	INDIRECT_ACTION_SPEC,
1486 	INDIRECT_ACTION_LIST,
1487 	INDIRECT_ACTION_FLOW_CONF,
1488 	ZERO,
1489 };
1490 
1491 static const enum index next_ia[] = {
1492 	INDIRECT_ACTION_ID2PTR,
1493 	ACTION_NEXT,
1494 	ZERO
1495 };
1496 
1497 static const enum index next_ial[] = {
1498 	ACTION_INDIRECT_LIST_HANDLE,
1499 	ACTION_INDIRECT_LIST_CONF,
1500 	ACTION_NEXT,
1501 	ZERO
1502 };
1503 
1504 static const enum index next_qia_qu_attr[] = {
1505 	QUEUE_INDIRECT_ACTION_QU_MODE,
1506 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1507 	INDIRECT_ACTION_SPEC,
1508 	ZERO
1509 };
1510 
1511 static const enum index next_ia_qu_attr[] = {
1512 	INDIRECT_ACTION_QU_MODE,
1513 	INDIRECT_ACTION_SPEC,
1514 	ZERO
1515 };
1516 
1517 static const enum index next_dump_subcmd[] = {
1518 	DUMP_ALL,
1519 	DUMP_ONE,
1520 	DUMP_IS_USER_ID,
1521 	ZERO,
1522 };
1523 
1524 static const enum index next_ia_subcmd[] = {
1525 	INDIRECT_ACTION_CREATE,
1526 	INDIRECT_ACTION_UPDATE,
1527 	INDIRECT_ACTION_DESTROY,
1528 	INDIRECT_ACTION_QUERY,
1529 	INDIRECT_ACTION_QUERY_UPDATE,
1530 	ZERO,
1531 };
1532 
1533 static const enum index next_vc_attr[] = {
1534 	VC_GROUP,
1535 	VC_PRIORITY,
1536 	VC_INGRESS,
1537 	VC_EGRESS,
1538 	VC_TRANSFER,
1539 	VC_TUNNEL_SET,
1540 	VC_TUNNEL_MATCH,
1541 	VC_USER_ID,
1542 	ITEM_PATTERN,
1543 	ZERO,
1544 };
1545 
1546 static const enum index next_destroy_attr[] = {
1547 	DESTROY_RULE,
1548 	DESTROY_IS_USER_ID,
1549 	END,
1550 	ZERO,
1551 };
1552 
1553 static const enum index next_dump_attr[] = {
1554 	COMMON_FILE_PATH,
1555 	END,
1556 	ZERO,
1557 };
1558 
1559 static const enum index next_query_attr[] = {
1560 	QUERY_IS_USER_ID,
1561 	END,
1562 	ZERO,
1563 };
1564 
1565 static const enum index next_list_attr[] = {
1566 	LIST_GROUP,
1567 	END,
1568 	ZERO,
1569 };
1570 
1571 static const enum index next_aged_attr[] = {
1572 	AGED_DESTROY,
1573 	END,
1574 	ZERO,
1575 };
1576 
1577 static const enum index next_ia_destroy_attr[] = {
1578 	INDIRECT_ACTION_DESTROY_ID,
1579 	END,
1580 	ZERO,
1581 };
1582 
1583 static const enum index next_async_insert_subcmd[] = {
1584 	QUEUE_PATTERN_TEMPLATE,
1585 	QUEUE_RULE_ID,
1586 	ZERO,
1587 };
1588 
1589 static const enum index next_async_pattern_subcmd[] = {
1590 	QUEUE_PATTERN_TEMPLATE,
1591 	QUEUE_ACTIONS_TEMPLATE,
1592 	ZERO,
1593 };
1594 
1595 static const enum index item_param[] = {
1596 	ITEM_PARAM_IS,
1597 	ITEM_PARAM_SPEC,
1598 	ITEM_PARAM_LAST,
1599 	ITEM_PARAM_MASK,
1600 	ITEM_PARAM_PREFIX,
1601 	ZERO,
1602 };
1603 
1604 static const enum index next_item[] = {
1605 	ITEM_END,
1606 	ITEM_VOID,
1607 	ITEM_INVERT,
1608 	ITEM_ANY,
1609 	ITEM_PORT_ID,
1610 	ITEM_MARK,
1611 	ITEM_RAW,
1612 	ITEM_ETH,
1613 	ITEM_VLAN,
1614 	ITEM_IPV4,
1615 	ITEM_IPV6,
1616 	ITEM_ICMP,
1617 	ITEM_UDP,
1618 	ITEM_TCP,
1619 	ITEM_SCTP,
1620 	ITEM_VXLAN,
1621 	ITEM_E_TAG,
1622 	ITEM_NVGRE,
1623 	ITEM_MPLS,
1624 	ITEM_GRE,
1625 	ITEM_FUZZY,
1626 	ITEM_GTP,
1627 	ITEM_GTPC,
1628 	ITEM_GTPU,
1629 	ITEM_GENEVE,
1630 	ITEM_VXLAN_GPE,
1631 	ITEM_ARP_ETH_IPV4,
1632 	ITEM_IPV6_EXT,
1633 	ITEM_IPV6_FRAG_EXT,
1634 	ITEM_IPV6_ROUTING_EXT,
1635 	ITEM_ICMP6,
1636 	ITEM_ICMP6_ECHO_REQUEST,
1637 	ITEM_ICMP6_ECHO_REPLY,
1638 	ITEM_ICMP6_ND_NS,
1639 	ITEM_ICMP6_ND_NA,
1640 	ITEM_ICMP6_ND_OPT,
1641 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1642 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1643 	ITEM_META,
1644 	ITEM_RANDOM,
1645 	ITEM_GRE_KEY,
1646 	ITEM_GRE_OPTION,
1647 	ITEM_GTP_PSC,
1648 	ITEM_PPPOES,
1649 	ITEM_PPPOED,
1650 	ITEM_PPPOE_PROTO_ID,
1651 	ITEM_HIGIG2,
1652 	ITEM_TAG,
1653 	ITEM_L2TPV3OIP,
1654 	ITEM_ESP,
1655 	ITEM_AH,
1656 	ITEM_PFCP,
1657 	ITEM_ECPRI,
1658 	ITEM_GENEVE_OPT,
1659 	ITEM_INTEGRITY,
1660 	ITEM_CONNTRACK,
1661 	ITEM_PORT_REPRESENTOR,
1662 	ITEM_REPRESENTED_PORT,
1663 	ITEM_FLEX,
1664 	ITEM_L2TPV2,
1665 	ITEM_PPP,
1666 	ITEM_METER,
1667 	ITEM_QUOTA,
1668 	ITEM_AGGR_AFFINITY,
1669 	ITEM_TX_QUEUE,
1670 	ITEM_IB_BTH,
1671 	ITEM_PTYPE,
1672 	ITEM_NSH,
1673 	ITEM_COMPARE,
1674 	END_SET,
1675 	ZERO,
1676 };
1677 
1678 static const enum index item_fuzzy[] = {
1679 	ITEM_FUZZY_THRESH,
1680 	ITEM_NEXT,
1681 	ZERO,
1682 };
1683 
1684 static const enum index item_any[] = {
1685 	ITEM_ANY_NUM,
1686 	ITEM_NEXT,
1687 	ZERO,
1688 };
1689 
1690 static const enum index item_port_id[] = {
1691 	ITEM_PORT_ID_ID,
1692 	ITEM_NEXT,
1693 	ZERO,
1694 };
1695 
1696 static const enum index item_mark[] = {
1697 	ITEM_MARK_ID,
1698 	ITEM_NEXT,
1699 	ZERO,
1700 };
1701 
1702 static const enum index item_raw[] = {
1703 	ITEM_RAW_RELATIVE,
1704 	ITEM_RAW_SEARCH,
1705 	ITEM_RAW_OFFSET,
1706 	ITEM_RAW_LIMIT,
1707 	ITEM_RAW_PATTERN,
1708 	ITEM_RAW_PATTERN_HEX,
1709 	ITEM_NEXT,
1710 	ZERO,
1711 };
1712 
1713 static const enum index item_eth[] = {
1714 	ITEM_ETH_DST,
1715 	ITEM_ETH_SRC,
1716 	ITEM_ETH_TYPE,
1717 	ITEM_ETH_HAS_VLAN,
1718 	ITEM_NEXT,
1719 	ZERO,
1720 };
1721 
1722 static const enum index item_vlan[] = {
1723 	ITEM_VLAN_TCI,
1724 	ITEM_VLAN_PCP,
1725 	ITEM_VLAN_DEI,
1726 	ITEM_VLAN_VID,
1727 	ITEM_VLAN_INNER_TYPE,
1728 	ITEM_VLAN_HAS_MORE_VLAN,
1729 	ITEM_NEXT,
1730 	ZERO,
1731 };
1732 
1733 static const enum index item_ipv4[] = {
1734 	ITEM_IPV4_VER_IHL,
1735 	ITEM_IPV4_TOS,
1736 	ITEM_IPV4_LENGTH,
1737 	ITEM_IPV4_ID,
1738 	ITEM_IPV4_FRAGMENT_OFFSET,
1739 	ITEM_IPV4_TTL,
1740 	ITEM_IPV4_PROTO,
1741 	ITEM_IPV4_SRC,
1742 	ITEM_IPV4_DST,
1743 	ITEM_NEXT,
1744 	ZERO,
1745 };
1746 
1747 static const enum index item_ipv6[] = {
1748 	ITEM_IPV6_TC,
1749 	ITEM_IPV6_FLOW,
1750 	ITEM_IPV6_LEN,
1751 	ITEM_IPV6_PROTO,
1752 	ITEM_IPV6_HOP,
1753 	ITEM_IPV6_SRC,
1754 	ITEM_IPV6_DST,
1755 	ITEM_IPV6_HAS_FRAG_EXT,
1756 	ITEM_IPV6_ROUTING_EXT,
1757 	ITEM_NEXT,
1758 	ZERO,
1759 };
1760 
1761 static const enum index item_ipv6_routing_ext[] = {
1762 	ITEM_IPV6_ROUTING_EXT_TYPE,
1763 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1764 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1765 	ITEM_NEXT,
1766 	ZERO,
1767 };
1768 
1769 static const enum index item_icmp[] = {
1770 	ITEM_ICMP_TYPE,
1771 	ITEM_ICMP_CODE,
1772 	ITEM_ICMP_IDENT,
1773 	ITEM_ICMP_SEQ,
1774 	ITEM_NEXT,
1775 	ZERO,
1776 };
1777 
1778 static const enum index item_udp[] = {
1779 	ITEM_UDP_SRC,
1780 	ITEM_UDP_DST,
1781 	ITEM_NEXT,
1782 	ZERO,
1783 };
1784 
1785 static const enum index item_tcp[] = {
1786 	ITEM_TCP_SRC,
1787 	ITEM_TCP_DST,
1788 	ITEM_TCP_FLAGS,
1789 	ITEM_NEXT,
1790 	ZERO,
1791 };
1792 
1793 static const enum index item_sctp[] = {
1794 	ITEM_SCTP_SRC,
1795 	ITEM_SCTP_DST,
1796 	ITEM_SCTP_TAG,
1797 	ITEM_SCTP_CKSUM,
1798 	ITEM_NEXT,
1799 	ZERO,
1800 };
1801 
1802 static const enum index item_vxlan[] = {
1803 	ITEM_VXLAN_VNI,
1804 	ITEM_VXLAN_FLAG_G,
1805 	ITEM_VXLAN_FLAG_VER,
1806 	ITEM_VXLAN_FLAG_I,
1807 	ITEM_VXLAN_FLAG_P,
1808 	ITEM_VXLAN_FLAG_B,
1809 	ITEM_VXLAN_FLAG_O,
1810 	ITEM_VXLAN_FLAG_D,
1811 	ITEM_VXLAN_FLAG_A,
1812 	ITEM_VXLAN_GBP_ID,
1813 	ITEM_VXLAN_GPE_PROTO,
1814 	ITEM_VXLAN_FIRST_RSVD,
1815 	ITEM_VXLAN_SECND_RSVD,
1816 	ITEM_VXLAN_THIRD_RSVD,
1817 	ITEM_VXLAN_LAST_RSVD,
1818 	ITEM_NEXT,
1819 	ZERO,
1820 };
1821 
1822 static const enum index item_e_tag[] = {
1823 	ITEM_E_TAG_GRP_ECID_B,
1824 	ITEM_NEXT,
1825 	ZERO,
1826 };
1827 
1828 static const enum index item_nvgre[] = {
1829 	ITEM_NVGRE_TNI,
1830 	ITEM_NEXT,
1831 	ZERO,
1832 };
1833 
1834 static const enum index item_mpls[] = {
1835 	ITEM_MPLS_LABEL,
1836 	ITEM_MPLS_TC,
1837 	ITEM_MPLS_S,
1838 	ITEM_MPLS_TTL,
1839 	ITEM_NEXT,
1840 	ZERO,
1841 };
1842 
1843 static const enum index item_gre[] = {
1844 	ITEM_GRE_PROTO,
1845 	ITEM_GRE_C_RSVD0_VER,
1846 	ITEM_GRE_C_BIT,
1847 	ITEM_GRE_K_BIT,
1848 	ITEM_GRE_S_BIT,
1849 	ITEM_NEXT,
1850 	ZERO,
1851 };
1852 
1853 static const enum index item_gre_key[] = {
1854 	ITEM_GRE_KEY_VALUE,
1855 	ITEM_NEXT,
1856 	ZERO,
1857 };
1858 
1859 static const enum index item_gre_option[] = {
1860 	ITEM_GRE_OPTION_CHECKSUM,
1861 	ITEM_GRE_OPTION_KEY,
1862 	ITEM_GRE_OPTION_SEQUENCE,
1863 	ITEM_NEXT,
1864 	ZERO,
1865 };
1866 
1867 static const enum index item_gtp[] = {
1868 	ITEM_GTP_FLAGS,
1869 	ITEM_GTP_MSG_TYPE,
1870 	ITEM_GTP_TEID,
1871 	ITEM_NEXT,
1872 	ZERO,
1873 };
1874 
1875 static const enum index item_geneve[] = {
1876 	ITEM_GENEVE_VNI,
1877 	ITEM_GENEVE_PROTO,
1878 	ITEM_GENEVE_OPTLEN,
1879 	ITEM_NEXT,
1880 	ZERO,
1881 };
1882 
1883 static const enum index item_vxlan_gpe[] = {
1884 	ITEM_VXLAN_GPE_VNI,
1885 	ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR,
1886 	ITEM_VXLAN_GPE_FLAGS,
1887 	ITEM_VXLAN_GPE_RSVD0,
1888 	ITEM_VXLAN_GPE_RSVD1,
1889 	ITEM_NEXT,
1890 	ZERO,
1891 };
1892 
1893 static const enum index item_arp_eth_ipv4[] = {
1894 	ITEM_ARP_ETH_IPV4_SHA,
1895 	ITEM_ARP_ETH_IPV4_SPA,
1896 	ITEM_ARP_ETH_IPV4_THA,
1897 	ITEM_ARP_ETH_IPV4_TPA,
1898 	ITEM_NEXT,
1899 	ZERO,
1900 };
1901 
1902 static const enum index item_ipv6_ext[] = {
1903 	ITEM_IPV6_EXT_NEXT_HDR,
1904 	ITEM_NEXT,
1905 	ZERO,
1906 };
1907 
1908 static const enum index item_ipv6_frag_ext[] = {
1909 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1910 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1911 	ITEM_IPV6_FRAG_EXT_ID,
1912 	ITEM_NEXT,
1913 	ZERO,
1914 };
1915 
1916 static const enum index item_icmp6[] = {
1917 	ITEM_ICMP6_TYPE,
1918 	ITEM_ICMP6_CODE,
1919 	ITEM_NEXT,
1920 	ZERO,
1921 };
1922 
1923 static const enum index item_icmp6_echo_request[] = {
1924 	ITEM_ICMP6_ECHO_REQUEST_ID,
1925 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1926 	ITEM_NEXT,
1927 	ZERO,
1928 };
1929 
1930 static const enum index item_icmp6_echo_reply[] = {
1931 	ITEM_ICMP6_ECHO_REPLY_ID,
1932 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1933 	ITEM_NEXT,
1934 	ZERO,
1935 };
1936 
1937 static const enum index item_icmp6_nd_ns[] = {
1938 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1939 	ITEM_NEXT,
1940 	ZERO,
1941 };
1942 
1943 static const enum index item_icmp6_nd_na[] = {
1944 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1945 	ITEM_NEXT,
1946 	ZERO,
1947 };
1948 
1949 static const enum index item_icmp6_nd_opt[] = {
1950 	ITEM_ICMP6_ND_OPT_TYPE,
1951 	ITEM_NEXT,
1952 	ZERO,
1953 };
1954 
1955 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1956 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1957 	ITEM_NEXT,
1958 	ZERO,
1959 };
1960 
1961 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1962 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1963 	ITEM_NEXT,
1964 	ZERO,
1965 };
1966 
1967 static const enum index item_meta[] = {
1968 	ITEM_META_DATA,
1969 	ITEM_NEXT,
1970 	ZERO,
1971 };
1972 
1973 static const enum index item_random[] = {
1974 	ITEM_RANDOM_VALUE,
1975 	ITEM_NEXT,
1976 	ZERO,
1977 };
1978 
1979 static const enum index item_gtp_psc[] = {
1980 	ITEM_GTP_PSC_QFI,
1981 	ITEM_GTP_PSC_PDU_T,
1982 	ITEM_NEXT,
1983 	ZERO,
1984 };
1985 
1986 static const enum index item_pppoed[] = {
1987 	ITEM_PPPOE_SEID,
1988 	ITEM_NEXT,
1989 	ZERO,
1990 };
1991 
1992 static const enum index item_pppoes[] = {
1993 	ITEM_PPPOE_SEID,
1994 	ITEM_NEXT,
1995 	ZERO,
1996 };
1997 
1998 static const enum index item_pppoe_proto_id[] = {
1999 	ITEM_NEXT,
2000 	ZERO,
2001 };
2002 
2003 static const enum index item_higig2[] = {
2004 	ITEM_HIGIG2_CLASSIFICATION,
2005 	ITEM_HIGIG2_VID,
2006 	ITEM_NEXT,
2007 	ZERO,
2008 };
2009 
2010 static const enum index item_esp[] = {
2011 	ITEM_ESP_SPI,
2012 	ITEM_NEXT,
2013 	ZERO,
2014 };
2015 
2016 static const enum index item_ah[] = {
2017 	ITEM_AH_SPI,
2018 	ITEM_NEXT,
2019 	ZERO,
2020 };
2021 
2022 static const enum index item_pfcp[] = {
2023 	ITEM_PFCP_S_FIELD,
2024 	ITEM_PFCP_SEID,
2025 	ITEM_NEXT,
2026 	ZERO,
2027 };
2028 
2029 static const enum index next_set_raw[] = {
2030 	SET_RAW_INDEX,
2031 	ITEM_ETH,
2032 	ZERO,
2033 };
2034 
2035 static const enum index item_tag[] = {
2036 	ITEM_TAG_DATA,
2037 	ITEM_TAG_INDEX,
2038 	ITEM_NEXT,
2039 	ZERO,
2040 };
2041 
2042 static const enum index item_l2tpv3oip[] = {
2043 	ITEM_L2TPV3OIP_SESSION_ID,
2044 	ITEM_NEXT,
2045 	ZERO,
2046 };
2047 
2048 static const enum index item_ecpri[] = {
2049 	ITEM_ECPRI_COMMON,
2050 	ITEM_NEXT,
2051 	ZERO,
2052 };
2053 
2054 static const enum index item_ecpri_common[] = {
2055 	ITEM_ECPRI_COMMON_TYPE,
2056 	ZERO,
2057 };
2058 
2059 static const enum index item_ecpri_common_type[] = {
2060 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
2061 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
2062 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
2063 	ZERO,
2064 };
2065 
2066 static const enum index item_geneve_opt[] = {
2067 	ITEM_GENEVE_OPT_CLASS,
2068 	ITEM_GENEVE_OPT_TYPE,
2069 	ITEM_GENEVE_OPT_LENGTH,
2070 	ITEM_GENEVE_OPT_DATA,
2071 	ITEM_NEXT,
2072 	ZERO,
2073 };
2074 
2075 static const enum index item_integrity[] = {
2076 	ITEM_INTEGRITY_LEVEL,
2077 	ITEM_INTEGRITY_VALUE,
2078 	ZERO,
2079 };
2080 
2081 static const enum index item_integrity_lv[] = {
2082 	ITEM_INTEGRITY_LEVEL,
2083 	ITEM_INTEGRITY_VALUE,
2084 	ITEM_NEXT,
2085 	ZERO,
2086 };
2087 
2088 static const enum index item_port_representor[] = {
2089 	ITEM_PORT_REPRESENTOR_PORT_ID,
2090 	ITEM_NEXT,
2091 	ZERO,
2092 };
2093 
2094 static const enum index item_represented_port[] = {
2095 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
2096 	ITEM_NEXT,
2097 	ZERO,
2098 };
2099 
2100 static const enum index item_flex[] = {
2101 	ITEM_FLEX_PATTERN_HANDLE,
2102 	ITEM_FLEX_ITEM_HANDLE,
2103 	ITEM_NEXT,
2104 	ZERO,
2105 };
2106 
2107 static const enum index item_l2tpv2[] = {
2108 	ITEM_L2TPV2_TYPE,
2109 	ITEM_NEXT,
2110 	ZERO,
2111 };
2112 
2113 static const enum index item_l2tpv2_type[] = {
2114 	ITEM_L2TPV2_TYPE_DATA,
2115 	ITEM_L2TPV2_TYPE_DATA_L,
2116 	ITEM_L2TPV2_TYPE_DATA_S,
2117 	ITEM_L2TPV2_TYPE_DATA_O,
2118 	ITEM_L2TPV2_TYPE_DATA_L_S,
2119 	ITEM_L2TPV2_TYPE_CTRL,
2120 	ZERO,
2121 };
2122 
2123 static const enum index item_l2tpv2_type_data[] = {
2124 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
2125 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
2126 	ITEM_NEXT,
2127 	ZERO,
2128 };
2129 
2130 static const enum index item_l2tpv2_type_data_l[] = {
2131 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
2132 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
2133 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
2134 	ITEM_NEXT,
2135 	ZERO,
2136 };
2137 
2138 static const enum index item_l2tpv2_type_data_s[] = {
2139 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
2140 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
2141 	ITEM_L2TPV2_MSG_DATA_S_NS,
2142 	ITEM_L2TPV2_MSG_DATA_S_NR,
2143 	ITEM_NEXT,
2144 	ZERO,
2145 };
2146 
2147 static const enum index item_l2tpv2_type_data_o[] = {
2148 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
2149 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
2150 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
2151 	ITEM_NEXT,
2152 	ZERO,
2153 };
2154 
2155 static const enum index item_l2tpv2_type_data_l_s[] = {
2156 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
2157 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
2158 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
2159 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
2160 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
2161 	ITEM_NEXT,
2162 	ZERO,
2163 };
2164 
2165 static const enum index item_l2tpv2_type_ctrl[] = {
2166 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
2167 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
2168 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
2169 	ITEM_L2TPV2_MSG_CTRL_NS,
2170 	ITEM_L2TPV2_MSG_CTRL_NR,
2171 	ITEM_NEXT,
2172 	ZERO,
2173 };
2174 
2175 static const enum index item_ppp[] = {
2176 	ITEM_PPP_ADDR,
2177 	ITEM_PPP_CTRL,
2178 	ITEM_PPP_PROTO_ID,
2179 	ITEM_NEXT,
2180 	ZERO,
2181 };
2182 
2183 static const enum index item_meter[] = {
2184 	ITEM_METER_COLOR,
2185 	ITEM_NEXT,
2186 	ZERO,
2187 };
2188 
2189 static const enum index item_quota[] = {
2190 	ITEM_QUOTA_STATE,
2191 	ITEM_NEXT,
2192 	ZERO,
2193 };
2194 
2195 static const enum index item_aggr_affinity[] = {
2196 	ITEM_AGGR_AFFINITY_VALUE,
2197 	ITEM_NEXT,
2198 	ZERO,
2199 };
2200 
2201 static const enum index item_tx_queue[] = {
2202 	ITEM_TX_QUEUE_VALUE,
2203 	ITEM_NEXT,
2204 	ZERO,
2205 };
2206 
2207 static const enum index item_ib_bth[] = {
2208 	ITEM_IB_BTH_OPCODE,
2209 	ITEM_IB_BTH_PKEY,
2210 	ITEM_IB_BTH_DST_QPN,
2211 	ITEM_IB_BTH_PSN,
2212 	ITEM_NEXT,
2213 	ZERO,
2214 };
2215 
2216 static const enum index item_ptype[] = {
2217 	ITEM_PTYPE_VALUE,
2218 	ITEM_NEXT,
2219 	ZERO,
2220 };
2221 
2222 static const enum index item_nsh[] = {
2223 	ITEM_NEXT,
2224 	ZERO,
2225 };
2226 
2227 static const enum index item_compare_field[] = {
2228 	ITEM_COMPARE_OP,
2229 	ITEM_COMPARE_FIELD_A_TYPE,
2230 	ITEM_COMPARE_FIELD_B_TYPE,
2231 	ITEM_NEXT,
2232 	ZERO,
2233 };
2234 
2235 static const enum index compare_field_a[] = {
2236 	ITEM_COMPARE_FIELD_A_TYPE,
2237 	ITEM_COMPARE_FIELD_A_LEVEL,
2238 	ITEM_COMPARE_FIELD_A_TAG_INDEX,
2239 	ITEM_COMPARE_FIELD_A_TYPE_ID,
2240 	ITEM_COMPARE_FIELD_A_CLASS_ID,
2241 	ITEM_COMPARE_FIELD_A_OFFSET,
2242 	ITEM_COMPARE_FIELD_B_TYPE,
2243 	ZERO,
2244 };
2245 
2246 static const enum index compare_field_b[] = {
2247 	ITEM_COMPARE_FIELD_B_TYPE,
2248 	ITEM_COMPARE_FIELD_B_LEVEL,
2249 	ITEM_COMPARE_FIELD_B_TAG_INDEX,
2250 	ITEM_COMPARE_FIELD_B_TYPE_ID,
2251 	ITEM_COMPARE_FIELD_B_CLASS_ID,
2252 	ITEM_COMPARE_FIELD_B_OFFSET,
2253 	ITEM_COMPARE_FIELD_B_VALUE,
2254 	ITEM_COMPARE_FIELD_B_POINTER,
2255 	ITEM_COMPARE_FIELD_WIDTH,
2256 	ZERO,
2257 };
2258 
2259 static const enum index next_action[] = {
2260 	ACTION_END,
2261 	ACTION_VOID,
2262 	ACTION_PASSTHRU,
2263 	ACTION_SKIP_CMAN,
2264 	ACTION_JUMP,
2265 	ACTION_MARK,
2266 	ACTION_FLAG,
2267 	ACTION_QUEUE,
2268 	ACTION_DROP,
2269 	ACTION_COUNT,
2270 	ACTION_RSS,
2271 	ACTION_PF,
2272 	ACTION_VF,
2273 	ACTION_PORT_ID,
2274 	ACTION_METER,
2275 	ACTION_METER_COLOR,
2276 	ACTION_METER_MARK,
2277 	ACTION_OF_DEC_NW_TTL,
2278 	ACTION_OF_POP_VLAN,
2279 	ACTION_OF_PUSH_VLAN,
2280 	ACTION_OF_SET_VLAN_VID,
2281 	ACTION_OF_SET_VLAN_PCP,
2282 	ACTION_OF_POP_MPLS,
2283 	ACTION_OF_PUSH_MPLS,
2284 	ACTION_VXLAN_ENCAP,
2285 	ACTION_VXLAN_DECAP,
2286 	ACTION_NVGRE_ENCAP,
2287 	ACTION_NVGRE_DECAP,
2288 	ACTION_L2_ENCAP,
2289 	ACTION_L2_DECAP,
2290 	ACTION_MPLSOGRE_ENCAP,
2291 	ACTION_MPLSOGRE_DECAP,
2292 	ACTION_MPLSOUDP_ENCAP,
2293 	ACTION_MPLSOUDP_DECAP,
2294 	ACTION_SET_IPV4_SRC,
2295 	ACTION_SET_IPV4_DST,
2296 	ACTION_SET_IPV6_SRC,
2297 	ACTION_SET_IPV6_DST,
2298 	ACTION_SET_TP_SRC,
2299 	ACTION_SET_TP_DST,
2300 	ACTION_MAC_SWAP,
2301 	ACTION_DEC_TTL,
2302 	ACTION_SET_TTL,
2303 	ACTION_SET_MAC_SRC,
2304 	ACTION_SET_MAC_DST,
2305 	ACTION_INC_TCP_SEQ,
2306 	ACTION_DEC_TCP_SEQ,
2307 	ACTION_INC_TCP_ACK,
2308 	ACTION_DEC_TCP_ACK,
2309 	ACTION_RAW_ENCAP,
2310 	ACTION_RAW_DECAP,
2311 	ACTION_SET_TAG,
2312 	ACTION_SET_META,
2313 	ACTION_SET_IPV4_DSCP,
2314 	ACTION_SET_IPV6_DSCP,
2315 	ACTION_AGE,
2316 	ACTION_AGE_UPDATE,
2317 	ACTION_SAMPLE,
2318 	ACTION_INDIRECT,
2319 	ACTION_INDIRECT_LIST,
2320 	ACTION_SHARED_INDIRECT,
2321 	ACTION_MODIFY_FIELD,
2322 	ACTION_CONNTRACK,
2323 	ACTION_CONNTRACK_UPDATE,
2324 	ACTION_PORT_REPRESENTOR,
2325 	ACTION_REPRESENTED_PORT,
2326 	ACTION_SEND_TO_KERNEL,
2327 	ACTION_QUOTA_CREATE,
2328 	ACTION_QUOTA_QU,
2329 	ACTION_IPV6_EXT_REMOVE,
2330 	ACTION_IPV6_EXT_PUSH,
2331 	ACTION_NAT64,
2332 	ACTION_JUMP_TO_TABLE_INDEX,
2333 	ZERO,
2334 };
2335 
2336 static const enum index action_quota_create[] = {
2337 	ACTION_QUOTA_CREATE_LIMIT,
2338 	ACTION_QUOTA_CREATE_MODE,
2339 	ACTION_NEXT,
2340 	ZERO
2341 };
2342 
2343 static const enum index action_quota_update[] = {
2344 	ACTION_QUOTA_QU_LIMIT,
2345 	ACTION_QUOTA_QU_UPDATE_OP,
2346 	ACTION_NEXT,
2347 	ZERO
2348 };
2349 
2350 static const enum index action_mark[] = {
2351 	ACTION_MARK_ID,
2352 	ACTION_NEXT,
2353 	ZERO,
2354 };
2355 
2356 static const enum index action_queue[] = {
2357 	ACTION_QUEUE_INDEX,
2358 	ACTION_NEXT,
2359 	ZERO,
2360 };
2361 
2362 static const enum index action_count[] = {
2363 	ACTION_COUNT_ID,
2364 	ACTION_NEXT,
2365 	ZERO,
2366 };
2367 
2368 static const enum index action_rss[] = {
2369 	ACTION_RSS_FUNC,
2370 	ACTION_RSS_LEVEL,
2371 	ACTION_RSS_TYPES,
2372 	ACTION_RSS_KEY,
2373 	ACTION_RSS_KEY_LEN,
2374 	ACTION_RSS_QUEUES,
2375 	ACTION_NEXT,
2376 	ZERO,
2377 };
2378 
2379 static const enum index action_vf[] = {
2380 	ACTION_VF_ORIGINAL,
2381 	ACTION_VF_ID,
2382 	ACTION_NEXT,
2383 	ZERO,
2384 };
2385 
2386 static const enum index action_port_id[] = {
2387 	ACTION_PORT_ID_ORIGINAL,
2388 	ACTION_PORT_ID_ID,
2389 	ACTION_NEXT,
2390 	ZERO,
2391 };
2392 
2393 static const enum index action_meter[] = {
2394 	ACTION_METER_ID,
2395 	ACTION_NEXT,
2396 	ZERO,
2397 };
2398 
2399 static const enum index action_meter_color[] = {
2400 	ACTION_METER_COLOR_TYPE,
2401 	ACTION_NEXT,
2402 	ZERO,
2403 };
2404 
2405 static const enum index action_meter_mark[] = {
2406 	ACTION_METER_PROFILE,
2407 	ACTION_METER_POLICY,
2408 	ACTION_METER_COLOR_MODE,
2409 	ACTION_METER_STATE,
2410 	ACTION_NEXT,
2411 	ZERO,
2412 };
2413 
2414 static const enum index action_of_push_vlan[] = {
2415 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2416 	ACTION_NEXT,
2417 	ZERO,
2418 };
2419 
2420 static const enum index action_of_set_vlan_vid[] = {
2421 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2422 	ACTION_NEXT,
2423 	ZERO,
2424 };
2425 
2426 static const enum index action_of_set_vlan_pcp[] = {
2427 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2428 	ACTION_NEXT,
2429 	ZERO,
2430 };
2431 
2432 static const enum index action_of_pop_mpls[] = {
2433 	ACTION_OF_POP_MPLS_ETHERTYPE,
2434 	ACTION_NEXT,
2435 	ZERO,
2436 };
2437 
2438 static const enum index action_of_push_mpls[] = {
2439 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2440 	ACTION_NEXT,
2441 	ZERO,
2442 };
2443 
2444 static const enum index action_set_ipv4_src[] = {
2445 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2446 	ACTION_NEXT,
2447 	ZERO,
2448 };
2449 
2450 static const enum index action_set_mac_src[] = {
2451 	ACTION_SET_MAC_SRC_MAC_SRC,
2452 	ACTION_NEXT,
2453 	ZERO,
2454 };
2455 
2456 static const enum index action_set_ipv4_dst[] = {
2457 	ACTION_SET_IPV4_DST_IPV4_DST,
2458 	ACTION_NEXT,
2459 	ZERO,
2460 };
2461 
2462 static const enum index action_set_ipv6_src[] = {
2463 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2464 	ACTION_NEXT,
2465 	ZERO,
2466 };
2467 
2468 static const enum index action_set_ipv6_dst[] = {
2469 	ACTION_SET_IPV6_DST_IPV6_DST,
2470 	ACTION_NEXT,
2471 	ZERO,
2472 };
2473 
2474 static const enum index action_set_tp_src[] = {
2475 	ACTION_SET_TP_SRC_TP_SRC,
2476 	ACTION_NEXT,
2477 	ZERO,
2478 };
2479 
2480 static const enum index action_set_tp_dst[] = {
2481 	ACTION_SET_TP_DST_TP_DST,
2482 	ACTION_NEXT,
2483 	ZERO,
2484 };
2485 
2486 static const enum index action_set_ttl[] = {
2487 	ACTION_SET_TTL_TTL,
2488 	ACTION_NEXT,
2489 	ZERO,
2490 };
2491 
2492 static const enum index action_jump[] = {
2493 	ACTION_JUMP_GROUP,
2494 	ACTION_NEXT,
2495 	ZERO,
2496 };
2497 
2498 static const enum index action_set_mac_dst[] = {
2499 	ACTION_SET_MAC_DST_MAC_DST,
2500 	ACTION_NEXT,
2501 	ZERO,
2502 };
2503 
2504 static const enum index action_inc_tcp_seq[] = {
2505 	ACTION_INC_TCP_SEQ_VALUE,
2506 	ACTION_NEXT,
2507 	ZERO,
2508 };
2509 
2510 static const enum index action_dec_tcp_seq[] = {
2511 	ACTION_DEC_TCP_SEQ_VALUE,
2512 	ACTION_NEXT,
2513 	ZERO,
2514 };
2515 
2516 static const enum index action_inc_tcp_ack[] = {
2517 	ACTION_INC_TCP_ACK_VALUE,
2518 	ACTION_NEXT,
2519 	ZERO,
2520 };
2521 
2522 static const enum index action_dec_tcp_ack[] = {
2523 	ACTION_DEC_TCP_ACK_VALUE,
2524 	ACTION_NEXT,
2525 	ZERO,
2526 };
2527 
2528 static const enum index action_raw_encap[] = {
2529 	ACTION_RAW_ENCAP_SIZE,
2530 	ACTION_RAW_ENCAP_INDEX,
2531 	ACTION_NEXT,
2532 	ZERO,
2533 };
2534 
2535 static const enum index action_raw_decap[] = {
2536 	ACTION_RAW_DECAP_INDEX,
2537 	ACTION_NEXT,
2538 	ZERO,
2539 };
2540 
2541 static const enum index action_ipv6_ext_remove[] = {
2542 	ACTION_IPV6_EXT_REMOVE_INDEX,
2543 	ACTION_NEXT,
2544 	ZERO,
2545 };
2546 
2547 static const enum index action_ipv6_ext_push[] = {
2548 	ACTION_IPV6_EXT_PUSH_INDEX,
2549 	ACTION_NEXT,
2550 	ZERO,
2551 };
2552 
2553 static const enum index action_set_tag[] = {
2554 	ACTION_SET_TAG_DATA,
2555 	ACTION_SET_TAG_INDEX,
2556 	ACTION_SET_TAG_MASK,
2557 	ACTION_NEXT,
2558 	ZERO,
2559 };
2560 
2561 static const enum index action_set_meta[] = {
2562 	ACTION_SET_META_DATA,
2563 	ACTION_SET_META_MASK,
2564 	ACTION_NEXT,
2565 	ZERO,
2566 };
2567 
2568 static const enum index action_set_ipv4_dscp[] = {
2569 	ACTION_SET_IPV4_DSCP_VALUE,
2570 	ACTION_NEXT,
2571 	ZERO,
2572 };
2573 
2574 static const enum index action_set_ipv6_dscp[] = {
2575 	ACTION_SET_IPV6_DSCP_VALUE,
2576 	ACTION_NEXT,
2577 	ZERO,
2578 };
2579 
2580 static const enum index action_age[] = {
2581 	ACTION_AGE,
2582 	ACTION_AGE_TIMEOUT,
2583 	ACTION_NEXT,
2584 	ZERO,
2585 };
2586 
2587 static const enum index action_age_update[] = {
2588 	ACTION_AGE_UPDATE,
2589 	ACTION_AGE_UPDATE_TIMEOUT,
2590 	ACTION_AGE_UPDATE_TOUCH,
2591 	ACTION_NEXT,
2592 	ZERO,
2593 };
2594 
2595 static const enum index action_sample[] = {
2596 	ACTION_SAMPLE,
2597 	ACTION_SAMPLE_RATIO,
2598 	ACTION_SAMPLE_INDEX,
2599 	ACTION_NEXT,
2600 	ZERO,
2601 };
2602 
2603 static const enum index next_action_sample[] = {
2604 	ACTION_QUEUE,
2605 	ACTION_RSS,
2606 	ACTION_MARK,
2607 	ACTION_COUNT,
2608 	ACTION_PORT_ID,
2609 	ACTION_RAW_ENCAP,
2610 	ACTION_VXLAN_ENCAP,
2611 	ACTION_NVGRE_ENCAP,
2612 	ACTION_REPRESENTED_PORT,
2613 	ACTION_PORT_REPRESENTOR,
2614 	ACTION_NEXT,
2615 	ZERO,
2616 };
2617 
2618 static const enum index item_ipv6_push_ext[] = {
2619 	ITEM_IPV6_PUSH_REMOVE_EXT,
2620 	ZERO,
2621 };
2622 
2623 static const enum index item_ipv6_push_ext_type[] = {
2624 	ITEM_IPV6_PUSH_REMOVE_EXT_TYPE,
2625 	ZERO,
2626 };
2627 
2628 static const enum index item_ipv6_push_ext_header[] = {
2629 	ITEM_IPV6_ROUTING_EXT,
2630 	ITEM_NEXT,
2631 	ZERO,
2632 };
2633 
2634 static const enum index action_modify_field_dst[] = {
2635 	ACTION_MODIFY_FIELD_DST_LEVEL,
2636 	ACTION_MODIFY_FIELD_DST_TAG_INDEX,
2637 	ACTION_MODIFY_FIELD_DST_TYPE_ID,
2638 	ACTION_MODIFY_FIELD_DST_CLASS_ID,
2639 	ACTION_MODIFY_FIELD_DST_OFFSET,
2640 	ACTION_MODIFY_FIELD_SRC_TYPE,
2641 	ZERO,
2642 };
2643 
2644 static const enum index action_modify_field_src[] = {
2645 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2646 	ACTION_MODIFY_FIELD_SRC_TAG_INDEX,
2647 	ACTION_MODIFY_FIELD_SRC_TYPE_ID,
2648 	ACTION_MODIFY_FIELD_SRC_CLASS_ID,
2649 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2650 	ACTION_MODIFY_FIELD_SRC_VALUE,
2651 	ACTION_MODIFY_FIELD_SRC_POINTER,
2652 	ACTION_MODIFY_FIELD_WIDTH,
2653 	ZERO,
2654 };
2655 
2656 static const enum index action_update_conntrack[] = {
2657 	ACTION_CONNTRACK_UPDATE_DIR,
2658 	ACTION_CONNTRACK_UPDATE_CTX,
2659 	ACTION_NEXT,
2660 	ZERO,
2661 };
2662 
2663 static const enum index action_port_representor[] = {
2664 	ACTION_PORT_REPRESENTOR_PORT_ID,
2665 	ACTION_NEXT,
2666 	ZERO,
2667 };
2668 
2669 static const enum index action_represented_port[] = {
2670 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2671 	ACTION_NEXT,
2672 	ZERO,
2673 };
2674 
2675 static const enum index action_nat64[] = {
2676 	ACTION_NAT64_MODE,
2677 	ACTION_NEXT,
2678 	ZERO,
2679 };
2680 
2681 static const enum index next_hash_subcmd[] = {
2682 	HASH_CALC_TABLE,
2683 	HASH_CALC_ENCAP,
2684 	ZERO,
2685 };
2686 
2687 static const enum index next_hash_encap_dest_subcmd[] = {
2688 	ENCAP_HASH_FIELD_SRC_PORT,
2689 	ENCAP_HASH_FIELD_GRE_FLOW_ID,
2690 	ZERO,
2691 };
2692 
2693 static const enum index action_jump_to_table_index[] = {
2694 	ACTION_JUMP_TO_TABLE_INDEX_TABLE,
2695 	ACTION_JUMP_TO_TABLE_INDEX_INDEX,
2696 	ACTION_NEXT,
2697 	ZERO,
2698 };
2699 
2700 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2701 				     const char *, unsigned int,
2702 				     void *, unsigned int);
2703 static int parse_set_sample_action(struct context *, const struct token *,
2704 				   const char *, unsigned int,
2705 				   void *, unsigned int);
2706 static int parse_set_ipv6_ext_action(struct context *, const struct token *,
2707 				     const char *, unsigned int,
2708 				     void *, unsigned int);
2709 static int parse_set_init(struct context *, const struct token *,
2710 			  const char *, unsigned int,
2711 			  void *, unsigned int);
2712 static int
2713 parse_flex_handle(struct context *, const struct token *,
2714 		  const char *, unsigned int, void *, unsigned int);
2715 static int parse_init(struct context *, const struct token *,
2716 		      const char *, unsigned int,
2717 		      void *, unsigned int);
2718 static int parse_vc(struct context *, const struct token *,
2719 		    const char *, unsigned int,
2720 		    void *, unsigned int);
2721 static int parse_vc_spec(struct context *, const struct token *,
2722 			 const char *, unsigned int, void *, unsigned int);
2723 static int parse_vc_conf(struct context *, const struct token *,
2724 			 const char *, unsigned int, void *, unsigned int);
2725 static int parse_vc_conf_timeout(struct context *, const struct token *,
2726 				 const char *, unsigned int, void *,
2727 				 unsigned int);
2728 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2729 				    const char *, unsigned int,
2730 				    void *, unsigned int);
2731 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2732 				    const char *, unsigned int,
2733 				    void *, unsigned int);
2734 static int parse_vc_action_meter_color_type(struct context *,
2735 					const struct token *,
2736 					const char *, unsigned int, void *,
2737 					unsigned int);
2738 static int parse_vc_action_rss(struct context *, const struct token *,
2739 			       const char *, unsigned int, void *,
2740 			       unsigned int);
2741 static int parse_vc_action_rss_func(struct context *, const struct token *,
2742 				    const char *, unsigned int, void *,
2743 				    unsigned int);
2744 static int parse_vc_action_rss_type(struct context *, const struct token *,
2745 				    const char *, unsigned int, void *,
2746 				    unsigned int);
2747 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2748 				     const char *, unsigned int, void *,
2749 				     unsigned int);
2750 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2751 				       const char *, unsigned int, void *,
2752 				       unsigned int);
2753 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2754 				       const char *, unsigned int, void *,
2755 				       unsigned int);
2756 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2757 				    const char *, unsigned int, void *,
2758 				    unsigned int);
2759 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2760 				    const char *, unsigned int, void *,
2761 				    unsigned int);
2762 static int parse_vc_action_mplsogre_encap(struct context *,
2763 					  const struct token *, const char *,
2764 					  unsigned int, void *, unsigned int);
2765 static int parse_vc_action_mplsogre_decap(struct context *,
2766 					  const struct token *, const char *,
2767 					  unsigned int, void *, unsigned int);
2768 static int parse_vc_action_mplsoudp_encap(struct context *,
2769 					  const struct token *, const char *,
2770 					  unsigned int, void *, unsigned int);
2771 static int parse_vc_action_mplsoudp_decap(struct context *,
2772 					  const struct token *, const char *,
2773 					  unsigned int, void *, unsigned int);
2774 static int parse_vc_action_raw_encap(struct context *,
2775 				     const struct token *, const char *,
2776 				     unsigned int, void *, unsigned int);
2777 static int parse_vc_action_raw_decap(struct context *,
2778 				     const struct token *, const char *,
2779 				     unsigned int, void *, unsigned int);
2780 static int parse_vc_action_raw_encap_index(struct context *,
2781 					   const struct token *, const char *,
2782 					   unsigned int, void *, unsigned int);
2783 static int parse_vc_action_raw_decap_index(struct context *,
2784 					   const struct token *, const char *,
2785 					   unsigned int, void *, unsigned int);
2786 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
2787 					   const char *str, unsigned int len, void *buf,
2788 					   unsigned int size);
2789 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx,
2790 						 const struct token *token,
2791 						 const char *str, unsigned int len,
2792 						 void *buf,
2793 						 unsigned int size);
2794 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
2795 					 const char *str, unsigned int len, void *buf,
2796 					 unsigned int size);
2797 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx,
2798 					       const struct token *token,
2799 					       const char *str, unsigned int len,
2800 					       void *buf,
2801 					       unsigned int size);
2802 static int parse_vc_action_set_meta(struct context *ctx,
2803 				    const struct token *token, const char *str,
2804 				    unsigned int len, void *buf,
2805 					unsigned int size);
2806 static int parse_vc_action_sample(struct context *ctx,
2807 				    const struct token *token, const char *str,
2808 				    unsigned int len, void *buf,
2809 				    unsigned int size);
2810 static int
2811 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2812 				const char *str, unsigned int len, void *buf,
2813 				unsigned int size);
2814 static int
2815 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2816 				const char *str, unsigned int len, void *buf,
2817 				unsigned int size);
2818 static int
2819 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2820 				const char *str, unsigned int len, void *buf,
2821 				unsigned int size);
2822 static int
2823 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2824 				const char *str, unsigned int len, void *buf,
2825 				unsigned int size);
2826 static int
2827 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2828 			 const char *str, unsigned int len, void *buf,
2829 			 unsigned int size);
2830 static int parse_destroy(struct context *, const struct token *,
2831 			 const char *, unsigned int,
2832 			 void *, unsigned int);
2833 static int parse_flush(struct context *, const struct token *,
2834 		       const char *, unsigned int,
2835 		       void *, unsigned int);
2836 static int parse_dump(struct context *, const struct token *,
2837 		      const char *, unsigned int,
2838 		      void *, unsigned int);
2839 static int parse_query(struct context *, const struct token *,
2840 		       const char *, unsigned int,
2841 		       void *, unsigned int);
2842 static int parse_action(struct context *, const struct token *,
2843 			const char *, unsigned int,
2844 			void *, unsigned int);
2845 static int parse_list(struct context *, const struct token *,
2846 		      const char *, unsigned int,
2847 		      void *, unsigned int);
2848 static int parse_aged(struct context *, const struct token *,
2849 		      const char *, unsigned int,
2850 		      void *, unsigned int);
2851 static int parse_isolate(struct context *, const struct token *,
2852 			 const char *, unsigned int,
2853 			 void *, unsigned int);
2854 static int parse_configure(struct context *, const struct token *,
2855 			   const char *, unsigned int,
2856 			   void *, unsigned int);
2857 static int parse_template(struct context *, const struct token *,
2858 			  const char *, unsigned int,
2859 			  void *, unsigned int);
2860 static int parse_template_destroy(struct context *, const struct token *,
2861 				  const char *, unsigned int,
2862 				  void *, unsigned int);
2863 static int parse_table(struct context *, const struct token *,
2864 		       const char *, unsigned int, void *, unsigned int);
2865 static int parse_table_destroy(struct context *, const struct token *,
2866 			       const char *, unsigned int,
2867 			       void *, unsigned int);
2868 static int parse_qo(struct context *, const struct token *,
2869 		    const char *, unsigned int,
2870 		    void *, unsigned int);
2871 static int parse_qo_destroy(struct context *, const struct token *,
2872 			    const char *, unsigned int,
2873 			    void *, unsigned int);
2874 static int parse_qia(struct context *, const struct token *,
2875 		     const char *, unsigned int,
2876 		     void *, unsigned int);
2877 static int parse_qia_destroy(struct context *, const struct token *,
2878 			     const char *, unsigned int,
2879 			     void *, unsigned int);
2880 static int parse_push(struct context *, const struct token *,
2881 		      const char *, unsigned int,
2882 		      void *, unsigned int);
2883 static int parse_pull(struct context *, const struct token *,
2884 		      const char *, unsigned int,
2885 		      void *, unsigned int);
2886 static int parse_group(struct context *, const struct token *,
2887 		       const char *, unsigned int,
2888 		       void *, unsigned int);
2889 static int parse_hash(struct context *, const struct token *,
2890 		      const char *, unsigned int,
2891 		      void *, unsigned int);
2892 static int parse_tunnel(struct context *, const struct token *,
2893 			const char *, unsigned int,
2894 			void *, unsigned int);
2895 static int parse_flex(struct context *, const struct token *,
2896 		      const char *, unsigned int, void *, unsigned int);
2897 static int parse_int(struct context *, const struct token *,
2898 		     const char *, unsigned int,
2899 		     void *, unsigned int);
2900 static int parse_prefix(struct context *, const struct token *,
2901 			const char *, unsigned int,
2902 			void *, unsigned int);
2903 static int parse_boolean(struct context *, const struct token *,
2904 			 const char *, unsigned int,
2905 			 void *, unsigned int);
2906 static int parse_string(struct context *, const struct token *,
2907 			const char *, unsigned int,
2908 			void *, unsigned int);
2909 static int parse_hex(struct context *ctx, const struct token *token,
2910 			const char *str, unsigned int len,
2911 			void *buf, unsigned int size);
2912 static int parse_string0(struct context *, const struct token *,
2913 			const char *, unsigned int,
2914 			void *, unsigned int);
2915 static int parse_mac_addr(struct context *, const struct token *,
2916 			  const char *, unsigned int,
2917 			  void *, unsigned int);
2918 static int parse_ipv4_addr(struct context *, const struct token *,
2919 			   const char *, unsigned int,
2920 			   void *, unsigned int);
2921 static int parse_ipv6_addr(struct context *, const struct token *,
2922 			   const char *, unsigned int,
2923 			   void *, unsigned int);
2924 static int parse_port(struct context *, const struct token *,
2925 		      const char *, unsigned int,
2926 		      void *, unsigned int);
2927 static int parse_ia(struct context *, const struct token *,
2928 		    const char *, unsigned int,
2929 		    void *, unsigned int);
2930 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2931 			    const char *str, unsigned int len,
2932 			    void *buf, unsigned int size);
2933 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2934 			   const char *str, unsigned int len, void *buf,
2935 			   unsigned int size);
2936 
2937 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2938 			       const char *str, unsigned int len, void *buf,
2939 			       unsigned int size);
2940 static int parse_ia_port(struct context *ctx, const struct token *token,
2941 			 const char *str, unsigned int len, void *buf,
2942 			 unsigned int size);
2943 static int parse_mp(struct context *, const struct token *,
2944 		    const char *, unsigned int,
2945 		    void *, unsigned int);
2946 static int parse_meter_profile_id2ptr(struct context *ctx,
2947 				      const struct token *token,
2948 				      const char *str, unsigned int len,
2949 				      void *buf, unsigned int size);
2950 static int parse_meter_policy_id2ptr(struct context *ctx,
2951 				     const struct token *token,
2952 				     const char *str, unsigned int len,
2953 				     void *buf, unsigned int size);
2954 static int parse_meter_color(struct context *ctx, const struct token *token,
2955 			     const char *str, unsigned int len, void *buf,
2956 			     unsigned int size);
2957 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2958 				      const char *str, unsigned int len, void *buf,
2959 				      unsigned int size);
2960 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2961 				 const char *str, unsigned int len, void *buf,
2962 				 unsigned int size);
2963 static int
2964 parse_quota_state_name(struct context *ctx, const struct token *token,
2965 		       const char *str, unsigned int len, void *buf,
2966 		       unsigned int size);
2967 static int
2968 parse_quota_mode_name(struct context *ctx, const struct token *token,
2969 		      const char *str, unsigned int len, void *buf,
2970 		      unsigned int size);
2971 static int
2972 parse_quota_update_name(struct context *ctx, const struct token *token,
2973 			const char *str, unsigned int len, void *buf,
2974 			unsigned int size);
2975 static int
2976 parse_qu_mode_name(struct context *ctx, const struct token *token,
2977 		   const char *str, unsigned int len, void *buf,
2978 		   unsigned int size);
2979 static int comp_none(struct context *, const struct token *,
2980 		     unsigned int, char *, unsigned int);
2981 static int comp_boolean(struct context *, const struct token *,
2982 			unsigned int, char *, unsigned int);
2983 static int comp_action(struct context *, const struct token *,
2984 		       unsigned int, char *, unsigned int);
2985 static int comp_port(struct context *, const struct token *,
2986 		     unsigned int, char *, unsigned int);
2987 static int comp_rule_id(struct context *, const struct token *,
2988 			unsigned int, char *, unsigned int);
2989 static int comp_vc_action_rss_type(struct context *, const struct token *,
2990 				   unsigned int, char *, unsigned int);
2991 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2992 				    unsigned int, char *, unsigned int);
2993 static int comp_set_raw_index(struct context *, const struct token *,
2994 			      unsigned int, char *, unsigned int);
2995 static int comp_set_sample_index(struct context *, const struct token *,
2996 			      unsigned int, char *, unsigned int);
2997 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
2998 				   unsigned int ent, char *buf, unsigned int size);
2999 static int comp_set_modify_field_op(struct context *, const struct token *,
3000 			      unsigned int, char *, unsigned int);
3001 static int comp_set_modify_field_id(struct context *, const struct token *,
3002 			      unsigned int, char *, unsigned int);
3003 static int comp_pattern_template_id(struct context *, const struct token *,
3004 				    unsigned int, char *, unsigned int);
3005 static int comp_actions_template_id(struct context *, const struct token *,
3006 				    unsigned int, char *, unsigned int);
3007 static int comp_table_id(struct context *, const struct token *,
3008 			 unsigned int, char *, unsigned int);
3009 static int comp_queue_id(struct context *, const struct token *,
3010 			 unsigned int, char *, unsigned int);
3011 static int comp_meter_color(struct context *, const struct token *,
3012 			    unsigned int, char *, unsigned int);
3013 static int comp_insertion_table_type(struct context *, const struct token *,
3014 				     unsigned int, char *, unsigned int);
3015 static int comp_hash_table_type(struct context *, const struct token *,
3016 				unsigned int, char *, unsigned int);
3017 static int
3018 comp_quota_state_name(struct context *ctx, const struct token *token,
3019 		      unsigned int ent, char *buf, unsigned int size);
3020 static int
3021 comp_quota_mode_name(struct context *ctx, const struct token *token,
3022 		     unsigned int ent, char *buf, unsigned int size);
3023 static int
3024 comp_quota_update_name(struct context *ctx, const struct token *token,
3025 		       unsigned int ent, char *buf, unsigned int size);
3026 static int
3027 comp_qu_mode_name(struct context *ctx, const struct token *token,
3028 		  unsigned int ent, char *buf, unsigned int size);
3029 static int
3030 comp_set_compare_field_id(struct context *ctx, const struct token *token,
3031 			  unsigned int ent, char *buf, unsigned int size);
3032 static int
3033 comp_set_compare_op(struct context *ctx, const struct token *token,
3034 		    unsigned int ent, char *buf, unsigned int size);
3035 static int
3036 parse_vc_compare_op(struct context *ctx, const struct token *token,
3037 			 const char *str, unsigned int len, void *buf,
3038 			 unsigned int size);
3039 static int
3040 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
3041 			  const char *str, unsigned int len, void *buf,
3042 			  unsigned int size);
3043 static int
3044 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
3045 			     const char *str, unsigned int len, void *buf,
3046 			     unsigned int size);
3047 
3048 struct indlst_conf {
3049 	uint32_t id;
3050 	uint32_t conf_num;
3051 	struct rte_flow_action *actions;
3052 	const void **conf;
3053 	SLIST_ENTRY(indlst_conf) next;
3054 };
3055 
3056 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
3057 
3058 /** Token definitions. */
3059 static const struct token token_list[] = {
3060 	/* Special tokens. */
3061 	[ZERO] = {
3062 		.name = "ZERO",
3063 		.help = "null entry, abused as the entry point",
3064 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
3065 	},
3066 	[END] = {
3067 		.name = "",
3068 		.type = "RETURN",
3069 		.help = "command may end here",
3070 	},
3071 	[START_SET] = {
3072 		.name = "START_SET",
3073 		.help = "null entry, abused as the entry point for set",
3074 		.next = NEXT(NEXT_ENTRY(SET)),
3075 	},
3076 	[END_SET] = {
3077 		.name = "end_set",
3078 		.type = "RETURN",
3079 		.help = "set command may end here",
3080 	},
3081 	/* Common tokens. */
3082 	[COMMON_INTEGER] = {
3083 		.name = "{int}",
3084 		.type = "INTEGER",
3085 		.help = "integer value",
3086 		.call = parse_int,
3087 		.comp = comp_none,
3088 	},
3089 	[COMMON_UNSIGNED] = {
3090 		.name = "{unsigned}",
3091 		.type = "UNSIGNED",
3092 		.help = "unsigned integer value",
3093 		.call = parse_int,
3094 		.comp = comp_none,
3095 	},
3096 	[COMMON_PREFIX] = {
3097 		.name = "{prefix}",
3098 		.type = "PREFIX",
3099 		.help = "prefix length for bit-mask",
3100 		.call = parse_prefix,
3101 		.comp = comp_none,
3102 	},
3103 	[COMMON_BOOLEAN] = {
3104 		.name = "{boolean}",
3105 		.type = "BOOLEAN",
3106 		.help = "any boolean value",
3107 		.call = parse_boolean,
3108 		.comp = comp_boolean,
3109 	},
3110 	[COMMON_STRING] = {
3111 		.name = "{string}",
3112 		.type = "STRING",
3113 		.help = "fixed string",
3114 		.call = parse_string,
3115 		.comp = comp_none,
3116 	},
3117 	[COMMON_HEX] = {
3118 		.name = "{hex}",
3119 		.type = "HEX",
3120 		.help = "fixed string",
3121 		.call = parse_hex,
3122 	},
3123 	[COMMON_FILE_PATH] = {
3124 		.name = "{file path}",
3125 		.type = "STRING",
3126 		.help = "file path",
3127 		.call = parse_string0,
3128 		.comp = comp_none,
3129 	},
3130 	[COMMON_MAC_ADDR] = {
3131 		.name = "{MAC address}",
3132 		.type = "MAC-48",
3133 		.help = "standard MAC address notation",
3134 		.call = parse_mac_addr,
3135 		.comp = comp_none,
3136 	},
3137 	[COMMON_IPV4_ADDR] = {
3138 		.name = "{IPv4 address}",
3139 		.type = "IPV4 ADDRESS",
3140 		.help = "standard IPv4 address notation",
3141 		.call = parse_ipv4_addr,
3142 		.comp = comp_none,
3143 	},
3144 	[COMMON_IPV6_ADDR] = {
3145 		.name = "{IPv6 address}",
3146 		.type = "IPV6 ADDRESS",
3147 		.help = "standard IPv6 address notation",
3148 		.call = parse_ipv6_addr,
3149 		.comp = comp_none,
3150 	},
3151 	[COMMON_RULE_ID] = {
3152 		.name = "{rule id}",
3153 		.type = "RULE ID",
3154 		.help = "rule identifier",
3155 		.call = parse_int,
3156 		.comp = comp_rule_id,
3157 	},
3158 	[COMMON_PORT_ID] = {
3159 		.name = "{port_id}",
3160 		.type = "PORT ID",
3161 		.help = "port identifier",
3162 		.call = parse_port,
3163 		.comp = comp_port,
3164 	},
3165 	[COMMON_GROUP_ID] = {
3166 		.name = "{group_id}",
3167 		.type = "GROUP ID",
3168 		.help = "group identifier",
3169 		.call = parse_int,
3170 		.comp = comp_none,
3171 	},
3172 	[COMMON_PRIORITY_LEVEL] = {
3173 		.name = "{level}",
3174 		.type = "PRIORITY",
3175 		.help = "priority level",
3176 		.call = parse_int,
3177 		.comp = comp_none,
3178 	},
3179 	[COMMON_INDIRECT_ACTION_ID] = {
3180 		.name = "{indirect_action_id}",
3181 		.type = "INDIRECT_ACTION_ID",
3182 		.help = "indirect action id",
3183 		.call = parse_int,
3184 		.comp = comp_none,
3185 	},
3186 	[COMMON_PROFILE_ID] = {
3187 		.name = "{profile_id}",
3188 		.type = "PROFILE_ID",
3189 		.help = "profile id",
3190 		.call = parse_int,
3191 		.comp = comp_none,
3192 	},
3193 	[COMMON_POLICY_ID] = {
3194 		.name = "{policy_id}",
3195 		.type = "POLICY_ID",
3196 		.help = "policy id",
3197 		.call = parse_int,
3198 		.comp = comp_none,
3199 	},
3200 	[COMMON_FLEX_TOKEN] = {
3201 		.name = "{flex token}",
3202 		.type = "flex token",
3203 		.help = "flex token",
3204 		.call = parse_int,
3205 		.comp = comp_none,
3206 	},
3207 	[COMMON_FLEX_HANDLE] = {
3208 		.name = "{flex handle}",
3209 		.type = "FLEX HANDLE",
3210 		.help = "fill flex item data",
3211 		.call = parse_flex_handle,
3212 		.comp = comp_none,
3213 	},
3214 	[COMMON_PATTERN_TEMPLATE_ID] = {
3215 		.name = "{pattern_template_id}",
3216 		.type = "PATTERN_TEMPLATE_ID",
3217 		.help = "pattern template id",
3218 		.call = parse_int,
3219 		.comp = comp_pattern_template_id,
3220 	},
3221 	[COMMON_ACTIONS_TEMPLATE_ID] = {
3222 		.name = "{actions_template_id}",
3223 		.type = "ACTIONS_TEMPLATE_ID",
3224 		.help = "actions template id",
3225 		.call = parse_int,
3226 		.comp = comp_actions_template_id,
3227 	},
3228 	[COMMON_TABLE_ID] = {
3229 		.name = "{table_id}",
3230 		.type = "TABLE_ID",
3231 		.help = "table id",
3232 		.call = parse_int,
3233 		.comp = comp_table_id,
3234 	},
3235 	[COMMON_QUEUE_ID] = {
3236 		.name = "{queue_id}",
3237 		.type = "QUEUE_ID",
3238 		.help = "queue id",
3239 		.call = parse_int,
3240 		.comp = comp_queue_id,
3241 	},
3242 	/* Top-level command. */
3243 	[FLOW] = {
3244 		.name = "flow",
3245 		.type = "{command} {port_id} [{arg} [...]]",
3246 		.help = "manage ingress/egress flow rules",
3247 		.next = NEXT(NEXT_ENTRY
3248 			     (INFO,
3249 			      CONFIGURE,
3250 			      PATTERN_TEMPLATE,
3251 			      ACTIONS_TEMPLATE,
3252 			      TABLE,
3253 			      FLOW_GROUP,
3254 			      INDIRECT_ACTION,
3255 			      VALIDATE,
3256 			      CREATE,
3257 			      DESTROY,
3258 			      UPDATE,
3259 			      FLUSH,
3260 			      DUMP,
3261 			      LIST,
3262 			      AGED,
3263 			      QUERY,
3264 			      ISOLATE,
3265 			      TUNNEL,
3266 			      FLEX,
3267 			      QUEUE,
3268 			      PUSH,
3269 			      PULL,
3270 			      HASH)),
3271 		.call = parse_init,
3272 	},
3273 	/* Top-level command. */
3274 	[INFO] = {
3275 		.name = "info",
3276 		.help = "get information about flow engine",
3277 		.next = NEXT(NEXT_ENTRY(END),
3278 			     NEXT_ENTRY(COMMON_PORT_ID)),
3279 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3280 		.call = parse_configure,
3281 	},
3282 	/* Top-level command. */
3283 	[CONFIGURE] = {
3284 		.name = "configure",
3285 		.help = "configure flow engine",
3286 		.next = NEXT(next_config_attr,
3287 			     NEXT_ENTRY(COMMON_PORT_ID)),
3288 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3289 		.call = parse_configure,
3290 	},
3291 	/* Configure arguments. */
3292 	[CONFIG_QUEUES_NUMBER] = {
3293 		.name = "queues_number",
3294 		.help = "number of queues",
3295 		.next = NEXT(next_config_attr,
3296 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3297 		.args = ARGS(ARGS_ENTRY(struct buffer,
3298 					args.configure.nb_queue)),
3299 	},
3300 	[CONFIG_QUEUES_SIZE] = {
3301 		.name = "queues_size",
3302 		.help = "number of elements in queues",
3303 		.next = NEXT(next_config_attr,
3304 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3305 		.args = ARGS(ARGS_ENTRY(struct buffer,
3306 					args.configure.queue_attr.size)),
3307 	},
3308 	[CONFIG_COUNTERS_NUMBER] = {
3309 		.name = "counters_number",
3310 		.help = "number of counters",
3311 		.next = NEXT(next_config_attr,
3312 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3313 		.args = ARGS(ARGS_ENTRY(struct buffer,
3314 					args.configure.port_attr.nb_counters)),
3315 	},
3316 	[CONFIG_AGING_OBJECTS_NUMBER] = {
3317 		.name = "aging_counters_number",
3318 		.help = "number of aging objects",
3319 		.next = NEXT(next_config_attr,
3320 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3321 		.args = ARGS(ARGS_ENTRY(struct buffer,
3322 					args.configure.port_attr.nb_aging_objects)),
3323 	},
3324 	[CONFIG_QUOTAS_NUMBER] = {
3325 		.name = "quotas_number",
3326 		.help = "number of quotas",
3327 		.next = NEXT(next_config_attr,
3328 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3329 		.args = ARGS(ARGS_ENTRY(struct buffer,
3330 				     args.configure.port_attr.nb_quotas)),
3331 	},
3332 	[CONFIG_METERS_NUMBER] = {
3333 		.name = "meters_number",
3334 		.help = "number of meters",
3335 		.next = NEXT(next_config_attr,
3336 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3337 		.args = ARGS(ARGS_ENTRY(struct buffer,
3338 					args.configure.port_attr.nb_meters)),
3339 	},
3340 	[CONFIG_CONN_TRACK_NUMBER] = {
3341 		.name = "conn_tracks_number",
3342 		.help = "number of connection trackings",
3343 		.next = NEXT(next_config_attr,
3344 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3345 		.args = ARGS(ARGS_ENTRY(struct buffer,
3346 					args.configure.port_attr.nb_conn_tracks)),
3347 	},
3348 	[CONFIG_FLAGS] = {
3349 		.name = "flags",
3350 		.help = "configuration flags",
3351 		.next = NEXT(next_config_attr,
3352 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3353 		.args = ARGS(ARGS_ENTRY(struct buffer,
3354 					args.configure.port_attr.flags)),
3355 	},
3356 	[CONFIG_HOST_PORT] = {
3357 		.name = "host_port",
3358 		.help = "host port for shared objects",
3359 		.next = NEXT(next_config_attr,
3360 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3361 		.args = ARGS(ARGS_ENTRY(struct buffer,
3362 					args.configure.port_attr.host_port_id)),
3363 	},
3364 	/* Top-level command. */
3365 	[PATTERN_TEMPLATE] = {
3366 		.name = "pattern_template",
3367 		.type = "{command} {port_id} [{arg} [...]]",
3368 		.help = "manage pattern templates",
3369 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3370 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3371 		.call = parse_template,
3372 	},
3373 	/* Sub-level commands. */
3374 	[PATTERN_TEMPLATE_CREATE] = {
3375 		.name = "create",
3376 		.help = "create pattern template",
3377 		.next = NEXT(next_pt_attr),
3378 		.call = parse_template,
3379 	},
3380 	[PATTERN_TEMPLATE_DESTROY] = {
3381 		.name = "destroy",
3382 		.help = "destroy pattern template",
3383 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3384 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3385 		.call = parse_template_destroy,
3386 	},
3387 	/* Pattern template arguments. */
3388 	[PATTERN_TEMPLATE_CREATE_ID] = {
3389 		.name = "pattern_template_id",
3390 		.help = "specify a pattern template id to create",
3391 		.next = NEXT(next_pt_attr,
3392 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3393 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3394 	},
3395 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3396 		.name = "pattern_template",
3397 		.help = "specify a pattern template id to destroy",
3398 		.next = NEXT(next_pt_destroy_attr,
3399 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3400 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3401 					    args.templ_destroy.template_id)),
3402 		.call = parse_template_destroy,
3403 	},
3404 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3405 		.name = "relaxed",
3406 		.help = "is matching relaxed",
3407 		.next = NEXT(next_pt_attr,
3408 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3409 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3410 			     args.vc.attr.reserved, 1)),
3411 	},
3412 	[PATTERN_TEMPLATE_INGRESS] = {
3413 		.name = "ingress",
3414 		.help = "attribute pattern to ingress",
3415 		.next = NEXT(next_pt_attr),
3416 		.call = parse_template,
3417 	},
3418 	[PATTERN_TEMPLATE_EGRESS] = {
3419 		.name = "egress",
3420 		.help = "attribute pattern to egress",
3421 		.next = NEXT(next_pt_attr),
3422 		.call = parse_template,
3423 	},
3424 	[PATTERN_TEMPLATE_TRANSFER] = {
3425 		.name = "transfer",
3426 		.help = "attribute pattern to transfer",
3427 		.next = NEXT(next_pt_attr),
3428 		.call = parse_template,
3429 	},
3430 	[PATTERN_TEMPLATE_SPEC] = {
3431 		.name = "template",
3432 		.help = "specify item to create pattern template",
3433 		.next = NEXT(next_item),
3434 	},
3435 	/* Top-level command. */
3436 	[ACTIONS_TEMPLATE] = {
3437 		.name = "actions_template",
3438 		.type = "{command} {port_id} [{arg} [...]]",
3439 		.help = "manage actions templates",
3440 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3441 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3442 		.call = parse_template,
3443 	},
3444 	/* Sub-level commands. */
3445 	[ACTIONS_TEMPLATE_CREATE] = {
3446 		.name = "create",
3447 		.help = "create actions template",
3448 		.next = NEXT(next_at_attr),
3449 		.call = parse_template,
3450 	},
3451 	[ACTIONS_TEMPLATE_DESTROY] = {
3452 		.name = "destroy",
3453 		.help = "destroy actions template",
3454 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3455 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3456 		.call = parse_template_destroy,
3457 	},
3458 	/* Actions template arguments. */
3459 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3460 		.name = "actions_template_id",
3461 		.help = "specify an actions template id to create",
3462 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3463 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3464 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3465 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3466 	},
3467 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3468 		.name = "actions_template",
3469 		.help = "specify an actions template id to destroy",
3470 		.next = NEXT(next_at_destroy_attr,
3471 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3472 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3473 					    args.templ_destroy.template_id)),
3474 		.call = parse_template_destroy,
3475 	},
3476 	[ACTIONS_TEMPLATE_INGRESS] = {
3477 		.name = "ingress",
3478 		.help = "attribute actions to ingress",
3479 		.next = NEXT(next_at_attr),
3480 		.call = parse_template,
3481 	},
3482 	[ACTIONS_TEMPLATE_EGRESS] = {
3483 		.name = "egress",
3484 		.help = "attribute actions to egress",
3485 		.next = NEXT(next_at_attr),
3486 		.call = parse_template,
3487 	},
3488 	[ACTIONS_TEMPLATE_TRANSFER] = {
3489 		.name = "transfer",
3490 		.help = "attribute actions to transfer",
3491 		.next = NEXT(next_at_attr),
3492 		.call = parse_template,
3493 	},
3494 	[ACTIONS_TEMPLATE_SPEC] = {
3495 		.name = "template",
3496 		.help = "specify action to create actions template",
3497 		.next = NEXT(next_action),
3498 		.call = parse_template,
3499 	},
3500 	[ACTIONS_TEMPLATE_MASK] = {
3501 		.name = "mask",
3502 		.help = "specify action mask to create actions template",
3503 		.next = NEXT(next_action),
3504 		.call = parse_template,
3505 	},
3506 	/* Top-level command. */
3507 	[TABLE] = {
3508 		.name = "template_table",
3509 		.type = "{command} {port_id} [{arg} [...]]",
3510 		.help = "manage template tables",
3511 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3512 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3513 		.call = parse_table,
3514 	},
3515 	/* Sub-level commands. */
3516 	[TABLE_CREATE] = {
3517 		.name = "create",
3518 		.help = "create template table",
3519 		.next = NEXT(next_table_attr),
3520 		.call = parse_table,
3521 	},
3522 	[TABLE_DESTROY] = {
3523 		.name = "destroy",
3524 		.help = "destroy template table",
3525 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3526 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3527 		.call = parse_table_destroy,
3528 	},
3529 	[TABLE_RESIZE] = {
3530 		.name = "resize",
3531 		.help = "resize template table",
3532 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_ID)),
3533 		.call = parse_table
3534 	},
3535 	[TABLE_RESIZE_COMPLETE] = {
3536 		.name = "resize_complete",
3537 		.help = "complete table resize",
3538 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3539 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3540 		.call = parse_table_destroy,
3541 	},
3542 	/* Table  arguments. */
3543 	[TABLE_CREATE_ID] = {
3544 		.name = "table_id",
3545 		.help = "specify table id to create",
3546 		.next = NEXT(next_table_attr,
3547 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3548 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3549 	},
3550 	[TABLE_DESTROY_ID] = {
3551 		.name = "table",
3552 		.help = "table id",
3553 		.next = NEXT(next_table_destroy_attr,
3554 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3555 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3556 					    args.table_destroy.table_id)),
3557 		.call = parse_table_destroy,
3558 	},
3559 	[TABLE_RESIZE_ID] = {
3560 		.name = "table_resize_id",
3561 		.help = "table resize id",
3562 		.next = NEXT(NEXT_ENTRY(TABLE_RESIZE_RULES_NUMBER),
3563 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3564 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3565 		.call = parse_table
3566 	},
3567 	[TABLE_RESIZE_RULES_NUMBER] = {
3568 		.name = "table_resize_rules_num",
3569 		.help = "table resize rules number",
3570 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_UNSIGNED)),
3571 		.args = ARGS(ARGS_ENTRY(struct buffer,
3572 					args.table.attr.nb_flows)),
3573 		.call = parse_table
3574 	},
3575 	[TABLE_INSERTION_TYPE] = {
3576 		.name = "insertion_type",
3577 		.help = "specify insertion type",
3578 		.next = NEXT(next_table_attr,
3579 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3580 		.args = ARGS(ARGS_ENTRY(struct buffer,
3581 					args.table.attr.insertion_type)),
3582 	},
3583 	[TABLE_INSERTION_TYPE_NAME] = {
3584 		.name = "insertion_type_name",
3585 		.help = "insertion type name",
3586 		.call = parse_insertion_table_type,
3587 		.comp = comp_insertion_table_type,
3588 	},
3589 	[TABLE_HASH_FUNC] = {
3590 		.name = "hash_func",
3591 		.help = "specify hash calculation function",
3592 		.next = NEXT(next_table_attr,
3593 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3594 		.args = ARGS(ARGS_ENTRY(struct buffer,
3595 					args.table.attr.hash_func)),
3596 	},
3597 	[TABLE_HASH_FUNC_NAME] = {
3598 		.name = "hash_func_name",
3599 		.help = "hash calculation function name",
3600 		.call = parse_hash_table_type,
3601 		.comp = comp_hash_table_type,
3602 	},
3603 	[TABLE_GROUP] = {
3604 		.name = "group",
3605 		.help = "specify a group",
3606 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3607 		.args = ARGS(ARGS_ENTRY(struct buffer,
3608 					args.table.attr.flow_attr.group)),
3609 	},
3610 	[TABLE_PRIORITY] = {
3611 		.name = "priority",
3612 		.help = "specify a priority level",
3613 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3614 		.args = ARGS(ARGS_ENTRY(struct buffer,
3615 					args.table.attr.flow_attr.priority)),
3616 	},
3617 	[TABLE_EGRESS] = {
3618 		.name = "egress",
3619 		.help = "affect rule to egress",
3620 		.next = NEXT(next_table_attr),
3621 		.call = parse_table,
3622 	},
3623 	[TABLE_INGRESS] = {
3624 		.name = "ingress",
3625 		.help = "affect rule to ingress",
3626 		.next = NEXT(next_table_attr),
3627 		.call = parse_table,
3628 	},
3629 	[TABLE_TRANSFER] = {
3630 		.name = "transfer",
3631 		.help = "affect rule to transfer",
3632 		.next = NEXT(next_table_attr),
3633 		.call = parse_table,
3634 	},
3635 	[TABLE_TRANSFER_WIRE_ORIG] = {
3636 		.name = "wire_orig",
3637 		.help = "affect rule direction to transfer",
3638 		.next = NEXT(next_table_attr),
3639 		.call = parse_table,
3640 	},
3641 	[TABLE_TRANSFER_VPORT_ORIG] = {
3642 		.name = "vport_orig",
3643 		.help = "affect rule direction to transfer",
3644 		.next = NEXT(next_table_attr),
3645 		.call = parse_table,
3646 	},
3647 	[TABLE_RESIZABLE] = {
3648 		.name = "resizable",
3649 		.help = "set resizable attribute",
3650 		.next = NEXT(next_table_attr),
3651 		.call = parse_table,
3652 	},
3653 	[TABLE_RULES_NUMBER] = {
3654 		.name = "rules_number",
3655 		.help = "number of rules in table",
3656 		.next = NEXT(next_table_attr,
3657 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3658 		.args = ARGS(ARGS_ENTRY(struct buffer,
3659 					args.table.attr.nb_flows)),
3660 		.call = parse_table,
3661 	},
3662 	[TABLE_PATTERN_TEMPLATE] = {
3663 		.name = "pattern_template",
3664 		.help = "specify pattern template id",
3665 		.next = NEXT(next_table_attr,
3666 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3667 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3668 					    args.table.pat_templ_id)),
3669 		.call = parse_table,
3670 	},
3671 	[TABLE_ACTIONS_TEMPLATE] = {
3672 		.name = "actions_template",
3673 		.help = "specify actions template id",
3674 		.next = NEXT(next_table_attr,
3675 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3676 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3677 					    args.table.act_templ_id)),
3678 		.call = parse_table,
3679 	},
3680 	/* Top-level command. */
3681 	[FLOW_GROUP] = {
3682 		.name = "group",
3683 		.help = "manage flow groups",
3684 		.next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)),
3685 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3686 		.call = parse_group,
3687 	},
3688 	/* Sub-level commands. */
3689 	[GROUP_SET_MISS_ACTIONS] = {
3690 		.name = "set_miss_actions",
3691 		.help = "set group miss actions",
3692 		.next = NEXT(next_action),
3693 		.call = parse_group,
3694 	},
3695 	/* Group arguments */
3696 	[GROUP_ID]	= {
3697 		.name = "group_id",
3698 		.help = "group id",
3699 		.next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3700 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3701 	},
3702 	[GROUP_INGRESS] = {
3703 		.name = "ingress",
3704 		.help = "group ingress attr",
3705 		.next = NEXT(next_group_attr),
3706 		.call = parse_group,
3707 	},
3708 	[GROUP_EGRESS] = {
3709 		.name = "egress",
3710 		.help = "group egress attr",
3711 		.next = NEXT(next_group_attr),
3712 		.call = parse_group,
3713 	},
3714 	[GROUP_TRANSFER] = {
3715 		.name = "transfer",
3716 		.help = "group transfer attr",
3717 		.next = NEXT(next_group_attr),
3718 		.call = parse_group,
3719 	},
3720 	/* Top-level command. */
3721 	[QUEUE] = {
3722 		.name = "queue",
3723 		.help = "queue a flow rule operation",
3724 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3725 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3726 		.call = parse_qo,
3727 	},
3728 	/* Sub-level commands. */
3729 	[QUEUE_CREATE] = {
3730 		.name = "create",
3731 		.help = "create a flow rule",
3732 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3733 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3734 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3735 		.call = parse_qo,
3736 	},
3737 	[QUEUE_DESTROY] = {
3738 		.name = "destroy",
3739 		.help = "destroy a flow rule",
3740 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_POSTPONE),
3741 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3742 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3743 		.call = parse_qo_destroy,
3744 	},
3745 	[QUEUE_FLOW_UPDATE_RESIZED] = {
3746 		.name = "update_resized",
3747 		.help = "update a flow after table resize",
3748 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3749 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3750 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3751 		.call = parse_qo_destroy,
3752 	},
3753 	[QUEUE_UPDATE] = {
3754 		.name = "update",
3755 		.help = "update a flow rule",
3756 		.next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID),
3757 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3758 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3759 		.call = parse_qo,
3760 	},
3761 	[QUEUE_AGED] = {
3762 		.name = "aged",
3763 		.help = "list and destroy aged flows",
3764 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3765 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3766 		.call = parse_aged,
3767 	},
3768 	[QUEUE_INDIRECT_ACTION] = {
3769 		.name = "indirect_action",
3770 		.help = "queue indirect actions",
3771 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3772 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3773 		.call = parse_qia,
3774 	},
3775 	/* Queue  arguments. */
3776 	[QUEUE_TEMPLATE_TABLE] = {
3777 		.name = "template_table",
3778 		.help = "specify table id",
3779 		.next = NEXT(next_async_insert_subcmd,
3780 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3781 		.args = ARGS(ARGS_ENTRY(struct buffer,
3782 					args.vc.table_id)),
3783 		.call = parse_qo,
3784 	},
3785 	[QUEUE_PATTERN_TEMPLATE] = {
3786 		.name = "pattern_template",
3787 		.help = "specify pattern template index",
3788 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3789 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3790 		.args = ARGS(ARGS_ENTRY(struct buffer,
3791 					args.vc.pat_templ_id)),
3792 		.call = parse_qo,
3793 	},
3794 	[QUEUE_ACTIONS_TEMPLATE] = {
3795 		.name = "actions_template",
3796 		.help = "specify actions template index",
3797 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3798 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3799 		.args = ARGS(ARGS_ENTRY(struct buffer,
3800 					args.vc.act_templ_id)),
3801 		.call = parse_qo,
3802 	},
3803 	[QUEUE_RULE_ID] = {
3804 		.name = "rule_index",
3805 		.help = "specify flow rule index",
3806 		.next = NEXT(next_async_pattern_subcmd,
3807 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3808 		.args = ARGS(ARGS_ENTRY(struct buffer,
3809 					args.vc.rule_id)),
3810 		.call = parse_qo,
3811 	},
3812 	[QUEUE_CREATE_POSTPONE] = {
3813 		.name = "postpone",
3814 		.help = "postpone create operation",
3815 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3816 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3817 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3818 		.call = parse_qo,
3819 	},
3820 	[QUEUE_DESTROY_POSTPONE] = {
3821 		.name = "postpone",
3822 		.help = "postpone destroy operation",
3823 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3824 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3825 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3826 		.call = parse_qo_destroy,
3827 	},
3828 	[QUEUE_DESTROY_ID] = {
3829 		.name = "rule",
3830 		.help = "specify rule id to destroy",
3831 		.next = NEXT(next_queue_destroy_attr,
3832 			NEXT_ENTRY(COMMON_UNSIGNED)),
3833 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3834 					    args.destroy.rule)),
3835 		.call = parse_qo_destroy,
3836 	},
3837 	[QUEUE_UPDATE_ID] = {
3838 		.name = "rule",
3839 		.help = "specify rule id to update",
3840 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3841 			NEXT_ENTRY(COMMON_UNSIGNED)),
3842 		.args = ARGS(ARGS_ENTRY(struct buffer,
3843 				     args.vc.rule_id)),
3844 		.call = parse_qo,
3845 	},
3846 	/* Queue indirect action arguments */
3847 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3848 		.name = "create",
3849 		.help = "create indirect action",
3850 		.next = NEXT(next_qia_create_attr),
3851 		.call = parse_qia,
3852 	},
3853 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3854 		.name = "update",
3855 		.help = "update indirect action",
3856 		.next = NEXT(next_qia_update_attr,
3857 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3858 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3859 		.call = parse_qia,
3860 	},
3861 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3862 		.name = "destroy",
3863 		.help = "destroy indirect action",
3864 		.next = NEXT(next_qia_destroy_attr),
3865 		.call = parse_qia_destroy,
3866 	},
3867 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3868 		.name = "query",
3869 		.help = "query indirect action",
3870 		.next = NEXT(next_qia_query_attr,
3871 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3872 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3873 		.call = parse_qia,
3874 	},
3875 	/* Indirect action destroy arguments. */
3876 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3877 		.name = "postpone",
3878 		.help = "postpone destroy operation",
3879 		.next = NEXT(next_qia_destroy_attr,
3880 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3881 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3882 	},
3883 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3884 		.name = "action_id",
3885 		.help = "specify a indirect action id to destroy",
3886 		.next = NEXT(next_qia_destroy_attr,
3887 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3888 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3889 					    args.ia_destroy.action_id)),
3890 		.call = parse_qia_destroy,
3891 	},
3892 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3893 		.name = "query_update",
3894 		.help = "indirect query [and|or] update action",
3895 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3896 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3897 		.call = parse_qia
3898 	},
3899 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3900 		.name = "mode",
3901 		.help = "indirect query [and|or] update action",
3902 		.next = NEXT(next_qia_qu_attr,
3903 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3904 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3905 		.call = parse_qia
3906 	},
3907 	/* Indirect action update arguments. */
3908 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3909 		.name = "postpone",
3910 		.help = "postpone update operation",
3911 		.next = NEXT(next_qia_update_attr,
3912 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3913 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3914 	},
3915 	/* Indirect action update arguments. */
3916 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3917 		.name = "postpone",
3918 		.help = "postpone query operation",
3919 		.next = NEXT(next_qia_query_attr,
3920 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3921 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3922 	},
3923 	/* Indirect action create arguments. */
3924 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3925 		.name = "action_id",
3926 		.help = "specify a indirect action id to create",
3927 		.next = NEXT(next_qia_create_attr,
3928 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3929 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3930 	},
3931 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3932 		.name = "ingress",
3933 		.help = "affect rule to ingress",
3934 		.next = NEXT(next_qia_create_attr),
3935 		.call = parse_qia,
3936 	},
3937 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3938 		.name = "egress",
3939 		.help = "affect rule to egress",
3940 		.next = NEXT(next_qia_create_attr),
3941 		.call = parse_qia,
3942 	},
3943 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3944 		.name = "transfer",
3945 		.help = "affect rule to transfer",
3946 		.next = NEXT(next_qia_create_attr),
3947 		.call = parse_qia,
3948 	},
3949 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3950 		.name = "postpone",
3951 		.help = "postpone create operation",
3952 		.next = NEXT(next_qia_create_attr,
3953 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3954 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3955 	},
3956 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3957 		.name = "action",
3958 		.help = "specify action to create indirect handle",
3959 		.next = NEXT(next_action),
3960 	},
3961 	[QUEUE_INDIRECT_ACTION_LIST] = {
3962 		.name = "list",
3963 		.help = "specify actions for indirect handle list",
3964 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3965 		.call = parse_qia,
3966 	},
3967 	/* Top-level command. */
3968 	[PUSH] = {
3969 		.name = "push",
3970 		.help = "push enqueued operations",
3971 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3972 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3973 		.call = parse_push,
3974 	},
3975 	/* Sub-level commands. */
3976 	[PUSH_QUEUE] = {
3977 		.name = "queue",
3978 		.help = "specify queue id",
3979 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3980 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3981 	},
3982 	/* Top-level command. */
3983 	[PULL] = {
3984 		.name = "pull",
3985 		.help = "pull flow operations results",
3986 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3987 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3988 		.call = parse_pull,
3989 	},
3990 	/* Sub-level commands. */
3991 	[PULL_QUEUE] = {
3992 		.name = "queue",
3993 		.help = "specify queue id",
3994 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3995 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3996 	},
3997 	/* Top-level command. */
3998 	[HASH] = {
3999 		.name = "hash",
4000 		.help = "calculate hash for a given pattern in a given template table",
4001 		.next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4002 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4003 		.call = parse_hash,
4004 	},
4005 	/* Sub-level commands. */
4006 	[HASH_CALC_TABLE] = {
4007 		.name = "template_table",
4008 		.help = "specify table id",
4009 		.next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX),
4010 			     NEXT_ENTRY(COMMON_TABLE_ID)),
4011 		.args = ARGS(ARGS_ENTRY(struct buffer,
4012 					args.vc.table_id)),
4013 		.call = parse_hash,
4014 	},
4015 	[HASH_CALC_ENCAP] = {
4016 		.name = "encap",
4017 		.help = "calculates encap hash",
4018 		.next = NEXT(next_hash_encap_dest_subcmd),
4019 		.call = parse_hash,
4020 	},
4021 	[HASH_CALC_PATTERN_INDEX] = {
4022 		.name = "pattern_template",
4023 		.help = "specify pattern template id",
4024 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
4025 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4026 		.args = ARGS(ARGS_ENTRY(struct buffer,
4027 					args.vc.pat_templ_id)),
4028 		.call = parse_hash,
4029 	},
4030 	[ENCAP_HASH_FIELD_SRC_PORT] = {
4031 		.name = "hash_field_sport",
4032 		.help = "the encap hash field is src port",
4033 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4034 		.call = parse_hash,
4035 	},
4036 	[ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
4037 		.name = "hash_field_flow_id",
4038 		.help = "the encap hash field is NVGRE flow id",
4039 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
4040 		.call = parse_hash,
4041 	},
4042 	/* Top-level command. */
4043 	[INDIRECT_ACTION] = {
4044 		.name = "indirect_action",
4045 		.type = "{command} {port_id} [{arg} [...]]",
4046 		.help = "manage indirect actions",
4047 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4048 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4049 		.call = parse_ia,
4050 	},
4051 	/* Sub-level commands. */
4052 	[INDIRECT_ACTION_CREATE] = {
4053 		.name = "create",
4054 		.help = "create indirect action",
4055 		.next = NEXT(next_ia_create_attr),
4056 		.call = parse_ia,
4057 	},
4058 	[INDIRECT_ACTION_UPDATE] = {
4059 		.name = "update",
4060 		.help = "update indirect action",
4061 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
4062 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4063 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4064 		.call = parse_ia,
4065 	},
4066 	[INDIRECT_ACTION_DESTROY] = {
4067 		.name = "destroy",
4068 		.help = "destroy indirect action",
4069 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
4070 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4071 		.call = parse_ia_destroy,
4072 	},
4073 	[INDIRECT_ACTION_QUERY] = {
4074 		.name = "query",
4075 		.help = "query indirect action",
4076 		.next = NEXT(NEXT_ENTRY(END),
4077 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4078 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4079 		.call = parse_ia,
4080 	},
4081 	[INDIRECT_ACTION_QUERY_UPDATE] = {
4082 		.name = "query_update",
4083 		.help = "query [and|or] update",
4084 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4085 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
4086 		.call = parse_ia
4087 	},
4088 	[INDIRECT_ACTION_QU_MODE] = {
4089 		.name = "mode",
4090 		.help = "query_update mode",
4091 		.next = NEXT(next_ia_qu_attr,
4092 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
4093 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
4094 		.call = parse_ia,
4095 	},
4096 	[INDIRECT_ACTION_QU_MODE_NAME] = {
4097 		.name = "mode_name",
4098 		.help = "query-update mode name",
4099 		.call = parse_qu_mode_name,
4100 		.comp = comp_qu_mode_name,
4101 	},
4102 	[VALIDATE] = {
4103 		.name = "validate",
4104 		.help = "check whether a flow rule can be created",
4105 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4106 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4107 		.call = parse_vc,
4108 	},
4109 	[CREATE] = {
4110 		.name = "create",
4111 		.help = "create a flow rule",
4112 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4113 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4114 		.call = parse_vc,
4115 	},
4116 	[DESTROY] = {
4117 		.name = "destroy",
4118 		.help = "destroy specific flow rules",
4119 		.next = NEXT(next_destroy_attr,
4120 			     NEXT_ENTRY(COMMON_PORT_ID)),
4121 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4122 		.call = parse_destroy,
4123 	},
4124 	[UPDATE] = {
4125 		.name = "update",
4126 		.help = "update a flow rule with new actions",
4127 		.next = NEXT(NEXT_ENTRY(VC_IS_USER_ID, END),
4128 			     NEXT_ENTRY(ACTIONS),
4129 			     NEXT_ENTRY(COMMON_RULE_ID),
4130 			     NEXT_ENTRY(COMMON_PORT_ID)),
4131 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.rule_id),
4132 			     ARGS_ENTRY(struct buffer, port)),
4133 		.call = parse_vc,
4134 	},
4135 	[FLUSH] = {
4136 		.name = "flush",
4137 		.help = "destroy all flow rules",
4138 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4139 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4140 		.call = parse_flush,
4141 	},
4142 	[DUMP] = {
4143 		.name = "dump",
4144 		.help = "dump single/all flow rules to file",
4145 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
4146 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4147 		.call = parse_dump,
4148 	},
4149 	[QUERY] = {
4150 		.name = "query",
4151 		.help = "query an existing flow rule",
4152 		.next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
4153 			     NEXT_ENTRY(COMMON_RULE_ID),
4154 			     NEXT_ENTRY(COMMON_PORT_ID)),
4155 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
4156 			     ARGS_ENTRY(struct buffer, args.query.rule),
4157 			     ARGS_ENTRY(struct buffer, port)),
4158 		.call = parse_query,
4159 	},
4160 	[LIST] = {
4161 		.name = "list",
4162 		.help = "list existing flow rules",
4163 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4164 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4165 		.call = parse_list,
4166 	},
4167 	[AGED] = {
4168 		.name = "aged",
4169 		.help = "list and destroy aged flows",
4170 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
4171 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4172 		.call = parse_aged,
4173 	},
4174 	[ISOLATE] = {
4175 		.name = "isolate",
4176 		.help = "restrict ingress traffic to the defined flow rules",
4177 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
4178 			     NEXT_ENTRY(COMMON_PORT_ID)),
4179 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
4180 			     ARGS_ENTRY(struct buffer, port)),
4181 		.call = parse_isolate,
4182 	},
4183 	[FLEX] = {
4184 		.name = "flex_item",
4185 		.help = "flex item API",
4186 		.next = NEXT(next_flex_item),
4187 		.call = parse_flex,
4188 	},
4189 	[FLEX_ITEM_CREATE] = {
4190 		.name = "create",
4191 		.help = "flex item create",
4192 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
4193 			     ARGS_ENTRY(struct buffer, args.flex.token),
4194 			     ARGS_ENTRY(struct buffer, port)),
4195 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
4196 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
4197 			     NEXT_ENTRY(COMMON_PORT_ID)),
4198 		.call = parse_flex
4199 	},
4200 	[FLEX_ITEM_DESTROY] = {
4201 		.name = "destroy",
4202 		.help = "flex item destroy",
4203 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
4204 			     ARGS_ENTRY(struct buffer, port)),
4205 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
4206 			     NEXT_ENTRY(COMMON_PORT_ID)),
4207 		.call = parse_flex
4208 	},
4209 	[TUNNEL] = {
4210 		.name = "tunnel",
4211 		.help = "new tunnel API",
4212 		.next = NEXT(NEXT_ENTRY
4213 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
4214 		.call = parse_tunnel,
4215 	},
4216 	/* Tunnel arguments. */
4217 	[TUNNEL_CREATE] = {
4218 		.name = "create",
4219 		.help = "create new tunnel object",
4220 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
4221 			     NEXT_ENTRY(COMMON_PORT_ID)),
4222 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4223 		.call = parse_tunnel,
4224 	},
4225 	[TUNNEL_CREATE_TYPE] = {
4226 		.name = "type",
4227 		.help = "create new tunnel",
4228 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
4229 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
4230 		.call = parse_tunnel,
4231 	},
4232 	[TUNNEL_DESTROY] = {
4233 		.name = "destroy",
4234 		.help = "destroy tunnel",
4235 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
4236 			     NEXT_ENTRY(COMMON_PORT_ID)),
4237 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4238 		.call = parse_tunnel,
4239 	},
4240 	[TUNNEL_DESTROY_ID] = {
4241 		.name = "id",
4242 		.help = "tunnel identifier to destroy",
4243 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
4244 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4245 		.call = parse_tunnel,
4246 	},
4247 	[TUNNEL_LIST] = {
4248 		.name = "list",
4249 		.help = "list existing tunnels",
4250 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
4251 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
4252 		.call = parse_tunnel,
4253 	},
4254 	/* Destroy arguments. */
4255 	[DESTROY_RULE] = {
4256 		.name = "rule",
4257 		.help = "specify a rule identifier",
4258 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4259 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
4260 		.call = parse_destroy,
4261 	},
4262 	[DESTROY_IS_USER_ID] = {
4263 		.name = "user_id",
4264 		.help = "rule identifier is user-id",
4265 		.next = NEXT(next_destroy_attr),
4266 		.call = parse_destroy,
4267 	},
4268 	/* Dump arguments. */
4269 	[DUMP_ALL] = {
4270 		.name = "all",
4271 		.help = "dump all",
4272 		.next = NEXT(next_dump_attr),
4273 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
4274 		.call = parse_dump,
4275 	},
4276 	[DUMP_ONE] = {
4277 		.name = "rule",
4278 		.help = "dump one rule",
4279 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
4280 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
4281 				ARGS_ENTRY(struct buffer, args.dump.rule)),
4282 		.call = parse_dump,
4283 	},
4284 	[DUMP_IS_USER_ID] = {
4285 		.name = "user_id",
4286 		.help = "rule identifier is user-id",
4287 		.next = NEXT(next_dump_subcmd),
4288 		.call = parse_dump,
4289 	},
4290 	/* Query arguments. */
4291 	[QUERY_ACTION] = {
4292 		.name = "{action}",
4293 		.type = "ACTION",
4294 		.help = "action to query, must be part of the rule",
4295 		.call = parse_action,
4296 		.comp = comp_action,
4297 	},
4298 	[QUERY_IS_USER_ID] = {
4299 		.name = "user_id",
4300 		.help = "rule identifier is user-id",
4301 		.next = NEXT(next_query_attr),
4302 		.call = parse_query,
4303 	},
4304 	/* List arguments. */
4305 	[LIST_GROUP] = {
4306 		.name = "group",
4307 		.help = "specify a group",
4308 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4309 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
4310 		.call = parse_list,
4311 	},
4312 	[AGED_DESTROY] = {
4313 		.name = "destroy",
4314 		.help = "specify aged flows need be destroyed",
4315 		.call = parse_aged,
4316 		.comp = comp_none,
4317 	},
4318 	/* Validate/create attributes. */
4319 	[VC_GROUP] = {
4320 		.name = "group",
4321 		.help = "specify a group",
4322 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
4323 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
4324 		.call = parse_vc,
4325 	},
4326 	[VC_PRIORITY] = {
4327 		.name = "priority",
4328 		.help = "specify a priority level",
4329 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
4330 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
4331 		.call = parse_vc,
4332 	},
4333 	[VC_INGRESS] = {
4334 		.name = "ingress",
4335 		.help = "affect rule to ingress",
4336 		.next = NEXT(next_vc_attr),
4337 		.call = parse_vc,
4338 	},
4339 	[VC_EGRESS] = {
4340 		.name = "egress",
4341 		.help = "affect rule to egress",
4342 		.next = NEXT(next_vc_attr),
4343 		.call = parse_vc,
4344 	},
4345 	[VC_TRANSFER] = {
4346 		.name = "transfer",
4347 		.help = "apply rule directly to endpoints found in pattern",
4348 		.next = NEXT(next_vc_attr),
4349 		.call = parse_vc,
4350 	},
4351 	[VC_TUNNEL_SET] = {
4352 		.name = "tunnel_set",
4353 		.help = "tunnel steer rule",
4354 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4355 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4356 		.call = parse_vc,
4357 	},
4358 	[VC_TUNNEL_MATCH] = {
4359 		.name = "tunnel_match",
4360 		.help = "tunnel match rule",
4361 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4362 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
4363 		.call = parse_vc,
4364 	},
4365 	[VC_USER_ID] = {
4366 		.name = "user_id",
4367 		.help = "specify a user id to create",
4368 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
4369 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
4370 		.call = parse_vc,
4371 	},
4372 	[VC_IS_USER_ID] = {
4373 		.name = "user_id",
4374 		.help = "rule identifier is user-id",
4375 		.call = parse_vc,
4376 	},
4377 	/* Validate/create pattern. */
4378 	[ITEM_PATTERN] = {
4379 		.name = "pattern",
4380 		.help = "submit a list of pattern items",
4381 		.next = NEXT(next_item),
4382 		.call = parse_vc,
4383 	},
4384 	[ITEM_PARAM_IS] = {
4385 		.name = "is",
4386 		.help = "match value perfectly (with full bit-mask)",
4387 		.call = parse_vc_spec,
4388 	},
4389 	[ITEM_PARAM_SPEC] = {
4390 		.name = "spec",
4391 		.help = "match value according to configured bit-mask",
4392 		.call = parse_vc_spec,
4393 	},
4394 	[ITEM_PARAM_LAST] = {
4395 		.name = "last",
4396 		.help = "specify upper bound to establish a range",
4397 		.call = parse_vc_spec,
4398 	},
4399 	[ITEM_PARAM_MASK] = {
4400 		.name = "mask",
4401 		.help = "specify bit-mask with relevant bits set to one",
4402 		.call = parse_vc_spec,
4403 	},
4404 	[ITEM_PARAM_PREFIX] = {
4405 		.name = "prefix",
4406 		.help = "generate bit-mask from a prefix length",
4407 		.call = parse_vc_spec,
4408 	},
4409 	[ITEM_NEXT] = {
4410 		.name = "/",
4411 		.help = "specify next pattern item",
4412 		.next = NEXT(next_item),
4413 	},
4414 	[ITEM_END] = {
4415 		.name = "end",
4416 		.help = "end list of pattern items",
4417 		.priv = PRIV_ITEM(END, 0),
4418 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
4419 		.call = parse_vc,
4420 	},
4421 	[ITEM_VOID] = {
4422 		.name = "void",
4423 		.help = "no-op pattern item",
4424 		.priv = PRIV_ITEM(VOID, 0),
4425 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4426 		.call = parse_vc,
4427 	},
4428 	[ITEM_INVERT] = {
4429 		.name = "invert",
4430 		.help = "perform actions when pattern does not match",
4431 		.priv = PRIV_ITEM(INVERT, 0),
4432 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
4433 		.call = parse_vc,
4434 	},
4435 	[ITEM_ANY] = {
4436 		.name = "any",
4437 		.help = "match any protocol for the current layer",
4438 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
4439 		.next = NEXT(item_any),
4440 		.call = parse_vc,
4441 	},
4442 	[ITEM_ANY_NUM] = {
4443 		.name = "num",
4444 		.help = "number of layers covered",
4445 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4446 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
4447 	},
4448 	[ITEM_PORT_ID] = {
4449 		.name = "port_id",
4450 		.help = "match traffic from/to a given DPDK port ID",
4451 		.priv = PRIV_ITEM(PORT_ID,
4452 				  sizeof(struct rte_flow_item_port_id)),
4453 		.next = NEXT(item_port_id),
4454 		.call = parse_vc,
4455 	},
4456 	[ITEM_PORT_ID_ID] = {
4457 		.name = "id",
4458 		.help = "DPDK port ID",
4459 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
4460 			     item_param),
4461 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
4462 	},
4463 	[ITEM_MARK] = {
4464 		.name = "mark",
4465 		.help = "match traffic against value set in previously matched rule",
4466 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
4467 		.next = NEXT(item_mark),
4468 		.call = parse_vc,
4469 	},
4470 	[ITEM_MARK_ID] = {
4471 		.name = "id",
4472 		.help = "Integer value to match against",
4473 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
4474 			     item_param),
4475 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
4476 	},
4477 	[ITEM_RAW] = {
4478 		.name = "raw",
4479 		.help = "match an arbitrary byte string",
4480 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
4481 		.next = NEXT(item_raw),
4482 		.call = parse_vc,
4483 	},
4484 	[ITEM_RAW_RELATIVE] = {
4485 		.name = "relative",
4486 		.help = "look for pattern after the previous item",
4487 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4488 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4489 					   relative, 1)),
4490 	},
4491 	[ITEM_RAW_SEARCH] = {
4492 		.name = "search",
4493 		.help = "search pattern from offset (see also limit)",
4494 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4495 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
4496 					   search, 1)),
4497 	},
4498 	[ITEM_RAW_OFFSET] = {
4499 		.name = "offset",
4500 		.help = "absolute or relative offset for pattern",
4501 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
4502 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
4503 	},
4504 	[ITEM_RAW_LIMIT] = {
4505 		.name = "limit",
4506 		.help = "search area limit for start of pattern",
4507 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4508 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
4509 	},
4510 	[ITEM_RAW_PATTERN] = {
4511 		.name = "pattern",
4512 		.help = "byte string to look for",
4513 		.next = NEXT(item_raw,
4514 			     NEXT_ENTRY(COMMON_STRING),
4515 			     NEXT_ENTRY(ITEM_PARAM_IS,
4516 					ITEM_PARAM_SPEC,
4517 					ITEM_PARAM_MASK)),
4518 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4519 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4520 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4521 					    ITEM_RAW_PATTERN_SIZE)),
4522 	},
4523 	[ITEM_RAW_PATTERN_HEX] = {
4524 		.name = "pattern_hex",
4525 		.help = "hex string to look for",
4526 		.next = NEXT(item_raw,
4527 			     NEXT_ENTRY(COMMON_HEX),
4528 			     NEXT_ENTRY(ITEM_PARAM_IS,
4529 					ITEM_PARAM_SPEC,
4530 					ITEM_PARAM_MASK)),
4531 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
4532 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
4533 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
4534 					    ITEM_RAW_PATTERN_SIZE)),
4535 	},
4536 	[ITEM_ETH] = {
4537 		.name = "eth",
4538 		.help = "match Ethernet header",
4539 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
4540 		.next = NEXT(item_eth),
4541 		.call = parse_vc,
4542 	},
4543 	[ITEM_ETH_DST] = {
4544 		.name = "dst",
4545 		.help = "destination MAC",
4546 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4547 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4548 	},
4549 	[ITEM_ETH_SRC] = {
4550 		.name = "src",
4551 		.help = "source MAC",
4552 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4553 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4554 	},
4555 	[ITEM_ETH_TYPE] = {
4556 		.name = "type",
4557 		.help = "EtherType",
4558 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4559 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4560 	},
4561 	[ITEM_ETH_HAS_VLAN] = {
4562 		.name = "has_vlan",
4563 		.help = "packet header contains VLAN",
4564 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4565 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4566 					   has_vlan, 1)),
4567 	},
4568 	[ITEM_VLAN] = {
4569 		.name = "vlan",
4570 		.help = "match 802.1Q/ad VLAN tag",
4571 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4572 		.next = NEXT(item_vlan),
4573 		.call = parse_vc,
4574 	},
4575 	[ITEM_VLAN_TCI] = {
4576 		.name = "tci",
4577 		.help = "tag control information",
4578 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4579 			     item_param),
4580 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4581 	},
4582 	[ITEM_VLAN_PCP] = {
4583 		.name = "pcp",
4584 		.help = "priority code point",
4585 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4586 			     item_param),
4587 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4588 						  hdr.vlan_tci, "\xe0\x00")),
4589 	},
4590 	[ITEM_VLAN_DEI] = {
4591 		.name = "dei",
4592 		.help = "drop eligible indicator",
4593 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4594 			     item_param),
4595 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4596 						  hdr.vlan_tci, "\x10\x00")),
4597 	},
4598 	[ITEM_VLAN_VID] = {
4599 		.name = "vid",
4600 		.help = "VLAN identifier",
4601 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4602 			     item_param),
4603 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4604 						  hdr.vlan_tci, "\x0f\xff")),
4605 	},
4606 	[ITEM_VLAN_INNER_TYPE] = {
4607 		.name = "inner_type",
4608 		.help = "inner EtherType",
4609 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4610 			     item_param),
4611 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4612 					     hdr.eth_proto)),
4613 	},
4614 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4615 		.name = "has_more_vlan",
4616 		.help = "packet header contains another VLAN",
4617 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4618 			     item_param),
4619 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4620 					   has_more_vlan, 1)),
4621 	},
4622 	[ITEM_IPV4] = {
4623 		.name = "ipv4",
4624 		.help = "match IPv4 header",
4625 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4626 		.next = NEXT(item_ipv4),
4627 		.call = parse_vc,
4628 	},
4629 	[ITEM_IPV4_VER_IHL] = {
4630 		.name = "version_ihl",
4631 		.help = "match header length",
4632 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4633 			     item_param),
4634 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4635 				     hdr.version_ihl)),
4636 	},
4637 	[ITEM_IPV4_TOS] = {
4638 		.name = "tos",
4639 		.help = "type of service",
4640 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4641 			     item_param),
4642 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4643 					     hdr.type_of_service)),
4644 	},
4645 	[ITEM_IPV4_LENGTH] = {
4646 		.name = "length",
4647 		.help = "total length",
4648 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4649 			     item_param),
4650 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4651 					     hdr.total_length)),
4652 	},
4653 	[ITEM_IPV4_ID] = {
4654 		.name = "packet_id",
4655 		.help = "fragment packet id",
4656 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4657 			     item_param),
4658 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4659 					     hdr.packet_id)),
4660 	},
4661 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4662 		.name = "fragment_offset",
4663 		.help = "fragmentation flags and fragment offset",
4664 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4665 			     item_param),
4666 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4667 					     hdr.fragment_offset)),
4668 	},
4669 	[ITEM_IPV4_TTL] = {
4670 		.name = "ttl",
4671 		.help = "time to live",
4672 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4673 			     item_param),
4674 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4675 					     hdr.time_to_live)),
4676 	},
4677 	[ITEM_IPV4_PROTO] = {
4678 		.name = "proto",
4679 		.help = "next protocol ID",
4680 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4681 			     item_param),
4682 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4683 					     hdr.next_proto_id)),
4684 	},
4685 	[ITEM_IPV4_SRC] = {
4686 		.name = "src",
4687 		.help = "source address",
4688 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4689 			     item_param),
4690 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4691 					     hdr.src_addr)),
4692 	},
4693 	[ITEM_IPV4_DST] = {
4694 		.name = "dst",
4695 		.help = "destination address",
4696 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4697 			     item_param),
4698 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4699 					     hdr.dst_addr)),
4700 	},
4701 	[ITEM_IPV6] = {
4702 		.name = "ipv6",
4703 		.help = "match IPv6 header",
4704 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4705 		.next = NEXT(item_ipv6),
4706 		.call = parse_vc,
4707 	},
4708 	[ITEM_IPV6_TC] = {
4709 		.name = "tc",
4710 		.help = "traffic class",
4711 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4712 			     item_param),
4713 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4714 						  hdr.vtc_flow,
4715 						  "\x0f\xf0\x00\x00")),
4716 	},
4717 	[ITEM_IPV6_FLOW] = {
4718 		.name = "flow",
4719 		.help = "flow label",
4720 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4721 			     item_param),
4722 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4723 						  hdr.vtc_flow,
4724 						  "\x00\x0f\xff\xff")),
4725 	},
4726 	[ITEM_IPV6_LEN] = {
4727 		.name = "length",
4728 		.help = "payload length",
4729 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4730 			     item_param),
4731 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4732 					     hdr.payload_len)),
4733 	},
4734 	[ITEM_IPV6_PROTO] = {
4735 		.name = "proto",
4736 		.help = "protocol (next header)",
4737 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4738 			     item_param),
4739 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4740 					     hdr.proto)),
4741 	},
4742 	[ITEM_IPV6_HOP] = {
4743 		.name = "hop",
4744 		.help = "hop limit",
4745 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4746 			     item_param),
4747 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4748 					     hdr.hop_limits)),
4749 	},
4750 	[ITEM_IPV6_SRC] = {
4751 		.name = "src",
4752 		.help = "source address",
4753 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4754 			     item_param),
4755 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4756 					     hdr.src_addr)),
4757 	},
4758 	[ITEM_IPV6_DST] = {
4759 		.name = "dst",
4760 		.help = "destination address",
4761 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4762 			     item_param),
4763 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4764 					     hdr.dst_addr)),
4765 	},
4766 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4767 		.name = "has_frag_ext",
4768 		.help = "fragment packet attribute",
4769 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4770 			     item_param),
4771 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4772 					   has_frag_ext, 1)),
4773 	},
4774 	[ITEM_IPV6_ROUTING_EXT] = {
4775 		.name = "ipv6_routing_ext",
4776 		.help = "match IPv6 routing extension header",
4777 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4778 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4779 		.next = NEXT(item_ipv6_routing_ext),
4780 		.call = parse_vc,
4781 	},
4782 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4783 		.name = "ext_type",
4784 		.help = "match IPv6 routing extension header type",
4785 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4786 			     item_param),
4787 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4788 					     hdr.type)),
4789 	},
4790 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4791 		.name = "ext_next_hdr",
4792 		.help = "match IPv6 routing extension header next header type",
4793 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4794 			     item_param),
4795 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4796 					     hdr.next_hdr)),
4797 	},
4798 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4799 		.name = "ext_seg_left",
4800 		.help = "match IPv6 routing extension header segment left",
4801 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4802 			     item_param),
4803 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4804 					     hdr.segments_left)),
4805 	},
4806 	[ITEM_ICMP] = {
4807 		.name = "icmp",
4808 		.help = "match ICMP header",
4809 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4810 		.next = NEXT(item_icmp),
4811 		.call = parse_vc,
4812 	},
4813 	[ITEM_ICMP_TYPE] = {
4814 		.name = "type",
4815 		.help = "ICMP packet type",
4816 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4817 			     item_param),
4818 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4819 					     hdr.icmp_type)),
4820 	},
4821 	[ITEM_ICMP_CODE] = {
4822 		.name = "code",
4823 		.help = "ICMP packet code",
4824 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4825 			     item_param),
4826 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4827 					     hdr.icmp_code)),
4828 	},
4829 	[ITEM_ICMP_IDENT] = {
4830 		.name = "ident",
4831 		.help = "ICMP packet identifier",
4832 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4833 			     item_param),
4834 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4835 					     hdr.icmp_ident)),
4836 	},
4837 	[ITEM_ICMP_SEQ] = {
4838 		.name = "seq",
4839 		.help = "ICMP packet sequence number",
4840 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4841 			     item_param),
4842 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4843 					     hdr.icmp_seq_nb)),
4844 	},
4845 	[ITEM_UDP] = {
4846 		.name = "udp",
4847 		.help = "match UDP header",
4848 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4849 		.next = NEXT(item_udp),
4850 		.call = parse_vc,
4851 	},
4852 	[ITEM_UDP_SRC] = {
4853 		.name = "src",
4854 		.help = "UDP source port",
4855 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4856 			     item_param),
4857 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4858 					     hdr.src_port)),
4859 	},
4860 	[ITEM_UDP_DST] = {
4861 		.name = "dst",
4862 		.help = "UDP destination port",
4863 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4864 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4865 					     hdr.dst_port)),
4866 	},
4867 	[ITEM_TCP] = {
4868 		.name = "tcp",
4869 		.help = "match TCP header",
4870 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4871 		.next = NEXT(item_tcp),
4872 		.call = parse_vc,
4873 	},
4874 	[ITEM_TCP_SRC] = {
4875 		.name = "src",
4876 		.help = "TCP source port",
4877 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4878 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4879 					     hdr.src_port)),
4880 	},
4881 	[ITEM_TCP_DST] = {
4882 		.name = "dst",
4883 		.help = "TCP destination port",
4884 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4885 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4886 					     hdr.dst_port)),
4887 	},
4888 	[ITEM_TCP_FLAGS] = {
4889 		.name = "flags",
4890 		.help = "TCP flags",
4891 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4892 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4893 					     hdr.tcp_flags)),
4894 	},
4895 	[ITEM_SCTP] = {
4896 		.name = "sctp",
4897 		.help = "match SCTP header",
4898 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4899 		.next = NEXT(item_sctp),
4900 		.call = parse_vc,
4901 	},
4902 	[ITEM_SCTP_SRC] = {
4903 		.name = "src",
4904 		.help = "SCTP source port",
4905 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4906 			     item_param),
4907 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4908 					     hdr.src_port)),
4909 	},
4910 	[ITEM_SCTP_DST] = {
4911 		.name = "dst",
4912 		.help = "SCTP destination port",
4913 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4914 			     item_param),
4915 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4916 					     hdr.dst_port)),
4917 	},
4918 	[ITEM_SCTP_TAG] = {
4919 		.name = "tag",
4920 		.help = "validation tag",
4921 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4922 			     item_param),
4923 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4924 					     hdr.tag)),
4925 	},
4926 	[ITEM_SCTP_CKSUM] = {
4927 		.name = "cksum",
4928 		.help = "checksum",
4929 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4930 			     item_param),
4931 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4932 					     hdr.cksum)),
4933 	},
4934 	[ITEM_VXLAN] = {
4935 		.name = "vxlan",
4936 		.help = "match VXLAN header",
4937 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4938 		.next = NEXT(item_vxlan),
4939 		.call = parse_vc,
4940 	},
4941 	[ITEM_VXLAN_VNI] = {
4942 		.name = "vni",
4943 		.help = "VXLAN identifier",
4944 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4945 			     item_param),
4946 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4947 	},
4948 	[ITEM_VXLAN_FLAG_G] = {
4949 		.name = "flag_g",
4950 		.help = "VXLAN GBP bit",
4951 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4952 			     item_param),
4953 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4954 					   hdr.flag_g, 1)),
4955 	},
4956 	[ITEM_VXLAN_FLAG_VER] = {
4957 		.name = "flag_ver",
4958 		.help = "VXLAN GPE version",
4959 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4960 			     item_param),
4961 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4962 					   hdr.flag_ver, 2)),
4963 	},
4964 	[ITEM_VXLAN_FLAG_I] = {
4965 		.name = "flag_i",
4966 		.help = "VXLAN Instance bit",
4967 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4968 			     item_param),
4969 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4970 					   hdr.flag_i, 1)),
4971 	},
4972 	[ITEM_VXLAN_FLAG_P] = {
4973 		.name = "flag_p",
4974 		.help = "VXLAN GPE Next Protocol bit",
4975 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4976 			     item_param),
4977 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4978 					   hdr.flag_p, 1)),
4979 	},
4980 	[ITEM_VXLAN_FLAG_B] = {
4981 		.name = "flag_b",
4982 		.help = "VXLAN GPE Ingress-Replicated BUM",
4983 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4984 			     item_param),
4985 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4986 					   hdr.flag_b, 1)),
4987 	},
4988 	[ITEM_VXLAN_FLAG_O] = {
4989 		.name = "flag_o",
4990 		.help = "VXLAN GPE OAM Packet bit",
4991 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4992 			     item_param),
4993 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
4994 					   hdr.flag_o, 1)),
4995 	},
4996 	[ITEM_VXLAN_FLAG_D] = {
4997 		.name = "flag_d",
4998 		.help = "VXLAN GBP Don't Learn bit",
4999 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5000 			     item_param),
5001 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
5002 					   hdr.flag_d, 1)),
5003 	},
5004 	[ITEM_VXLAN_FLAG_A] = {
5005 		.name = "flag_a",
5006 		.help = "VXLAN GBP Applied bit",
5007 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5008 			     item_param),
5009 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vxlan,
5010 					   hdr.flag_a, 1)),
5011 	},
5012 	[ITEM_VXLAN_GBP_ID] = {
5013 		.name = "group_policy_id",
5014 		.help = "VXLAN GBP ID",
5015 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5016 			     item_param),
5017 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5018 					     hdr.policy_id)),
5019 	},
5020 	[ITEM_VXLAN_GPE_PROTO] = {
5021 		.name = "protocol",
5022 		.help = "VXLAN GPE next protocol",
5023 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5024 			     item_param),
5025 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5026 					     hdr.proto)),
5027 	},
5028 	[ITEM_VXLAN_FIRST_RSVD] = {
5029 		.name = "first_rsvd",
5030 		.help = "VXLAN rsvd0 first byte",
5031 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5032 			     item_param),
5033 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5034 					     hdr.rsvd0[0])),
5035 	},
5036 	[ITEM_VXLAN_SECND_RSVD] = {
5037 		.name = "second_rsvd",
5038 		.help = "VXLAN rsvd0 second byte",
5039 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5040 			     item_param),
5041 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5042 					     hdr.rsvd0[1])),
5043 	},
5044 	[ITEM_VXLAN_THIRD_RSVD] = {
5045 		.name = "third_rsvd",
5046 		.help = "VXLAN rsvd0 third byte",
5047 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5048 			     item_param),
5049 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5050 					     hdr.rsvd0[2])),
5051 	},
5052 	[ITEM_VXLAN_LAST_RSVD] = {
5053 		.name = "last_rsvd",
5054 		.help = "VXLAN last reserved byte",
5055 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
5056 			     item_param),
5057 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
5058 					     hdr.last_rsvd)),
5059 	},
5060 	[ITEM_E_TAG] = {
5061 		.name = "e_tag",
5062 		.help = "match E-Tag header",
5063 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
5064 		.next = NEXT(item_e_tag),
5065 		.call = parse_vc,
5066 	},
5067 	[ITEM_E_TAG_GRP_ECID_B] = {
5068 		.name = "grp_ecid_b",
5069 		.help = "GRP and E-CID base",
5070 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5071 			     item_param),
5072 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
5073 						  rsvd_grp_ecid_b,
5074 						  "\x3f\xff")),
5075 	},
5076 	[ITEM_NVGRE] = {
5077 		.name = "nvgre",
5078 		.help = "match NVGRE header",
5079 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
5080 		.next = NEXT(item_nvgre),
5081 		.call = parse_vc,
5082 	},
5083 	[ITEM_NVGRE_TNI] = {
5084 		.name = "tni",
5085 		.help = "virtual subnet ID",
5086 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
5087 			     item_param),
5088 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
5089 	},
5090 	[ITEM_MPLS] = {
5091 		.name = "mpls",
5092 		.help = "match MPLS header",
5093 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
5094 		.next = NEXT(item_mpls),
5095 		.call = parse_vc,
5096 	},
5097 	[ITEM_MPLS_LABEL] = {
5098 		.name = "label",
5099 		.help = "MPLS label",
5100 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5101 			     item_param),
5102 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5103 						  label_tc_s,
5104 						  "\xff\xff\xf0")),
5105 	},
5106 	[ITEM_MPLS_TC] = {
5107 		.name = "tc",
5108 		.help = "MPLS Traffic Class",
5109 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5110 			     item_param),
5111 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5112 						  label_tc_s,
5113 						  "\x00\x00\x0e")),
5114 	},
5115 	[ITEM_MPLS_S] = {
5116 		.name = "s",
5117 		.help = "MPLS Bottom-of-Stack",
5118 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5119 			     item_param),
5120 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
5121 						  label_tc_s,
5122 						  "\x00\x00\x01")),
5123 	},
5124 	[ITEM_MPLS_TTL] = {
5125 		.name = "ttl",
5126 		.help = "MPLS Time-to-Live",
5127 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
5128 			     item_param),
5129 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)),
5130 	},
5131 	[ITEM_GRE] = {
5132 		.name = "gre",
5133 		.help = "match GRE header",
5134 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
5135 		.next = NEXT(item_gre),
5136 		.call = parse_vc,
5137 	},
5138 	[ITEM_GRE_PROTO] = {
5139 		.name = "protocol",
5140 		.help = "GRE protocol type",
5141 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5142 			     item_param),
5143 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5144 					     protocol)),
5145 	},
5146 	[ITEM_GRE_C_RSVD0_VER] = {
5147 		.name = "c_rsvd0_ver",
5148 		.help =
5149 			"checksum (1b), undefined (1b), key bit (1b),"
5150 			" sequence number (1b), reserved 0 (9b),"
5151 			" version (3b)",
5152 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
5153 			     item_param),
5154 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
5155 					     c_rsvd0_ver)),
5156 	},
5157 	[ITEM_GRE_C_BIT] = {
5158 		.name = "c_bit",
5159 		.help = "checksum bit (C)",
5160 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
5161 			     item_param),
5162 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5163 						  c_rsvd0_ver,
5164 						  "\x80\x00\x00\x00")),
5165 	},
5166 	[ITEM_GRE_S_BIT] = {
5167 		.name = "s_bit",
5168 		.help = "sequence number bit (S)",
5169 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5170 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5171 						  c_rsvd0_ver,
5172 						  "\x10\x00\x00\x00")),
5173 	},
5174 	[ITEM_GRE_K_BIT] = {
5175 		.name = "k_bit",
5176 		.help = "key bit (K)",
5177 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
5178 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
5179 						  c_rsvd0_ver,
5180 						  "\x20\x00\x00\x00")),
5181 	},
5182 	[ITEM_FUZZY] = {
5183 		.name = "fuzzy",
5184 		.help = "fuzzy pattern match, expect faster than default",
5185 		.priv = PRIV_ITEM(FUZZY,
5186 				sizeof(struct rte_flow_item_fuzzy)),
5187 		.next = NEXT(item_fuzzy),
5188 		.call = parse_vc,
5189 	},
5190 	[ITEM_FUZZY_THRESH] = {
5191 		.name = "thresh",
5192 		.help = "match accuracy threshold",
5193 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
5194 			     item_param),
5195 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
5196 					thresh)),
5197 	},
5198 	[ITEM_GTP] = {
5199 		.name = "gtp",
5200 		.help = "match GTP header",
5201 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
5202 		.next = NEXT(item_gtp),
5203 		.call = parse_vc,
5204 	},
5205 	[ITEM_GTP_FLAGS] = {
5206 		.name = "v_pt_rsv_flags",
5207 		.help = "GTP flags",
5208 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5209 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
5210 					hdr.gtp_hdr_info)),
5211 	},
5212 	[ITEM_GTP_MSG_TYPE] = {
5213 		.name = "msg_type",
5214 		.help = "GTP message type",
5215 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5216 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
5217 	},
5218 	[ITEM_GTP_TEID] = {
5219 		.name = "teid",
5220 		.help = "tunnel endpoint identifier",
5221 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5222 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
5223 	},
5224 	[ITEM_GTPC] = {
5225 		.name = "gtpc",
5226 		.help = "match GTP header",
5227 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
5228 		.next = NEXT(item_gtp),
5229 		.call = parse_vc,
5230 	},
5231 	[ITEM_GTPU] = {
5232 		.name = "gtpu",
5233 		.help = "match GTP header",
5234 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
5235 		.next = NEXT(item_gtp),
5236 		.call = parse_vc,
5237 	},
5238 	[ITEM_GENEVE] = {
5239 		.name = "geneve",
5240 		.help = "match GENEVE header",
5241 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
5242 		.next = NEXT(item_geneve),
5243 		.call = parse_vc,
5244 	},
5245 	[ITEM_GENEVE_VNI] = {
5246 		.name = "vni",
5247 		.help = "virtual network identifier",
5248 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5249 			     item_param),
5250 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
5251 	},
5252 	[ITEM_GENEVE_PROTO] = {
5253 		.name = "protocol",
5254 		.help = "GENEVE protocol type",
5255 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5256 			     item_param),
5257 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
5258 					     protocol)),
5259 	},
5260 	[ITEM_GENEVE_OPTLEN] = {
5261 		.name = "optlen",
5262 		.help = "GENEVE options length in dwords",
5263 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
5264 			     item_param),
5265 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
5266 						  ver_opt_len_o_c_rsvd0,
5267 						  "\x3f\x00")),
5268 	},
5269 	[ITEM_VXLAN_GPE] = {
5270 		.name = "vxlan-gpe",
5271 		.help = "match VXLAN-GPE header",
5272 		.priv = PRIV_ITEM(VXLAN_GPE,
5273 				  sizeof(struct rte_flow_item_vxlan_gpe)),
5274 		.next = NEXT(item_vxlan_gpe),
5275 		.call = parse_vc,
5276 	},
5277 	[ITEM_VXLAN_GPE_VNI] = {
5278 		.name = "vni",
5279 		.help = "VXLAN-GPE identifier",
5280 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5281 			     item_param),
5282 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5283 					     hdr.vni)),
5284 	},
5285 	[ITEM_VXLAN_GPE_PROTO_IN_DEPRECATED_VXLAN_GPE_HDR] = {
5286 		.name = "protocol",
5287 		.help = "VXLAN-GPE next protocol",
5288 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5289 			     item_param),
5290 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5291 					     protocol)),
5292 	},
5293 	[ITEM_VXLAN_GPE_FLAGS] = {
5294 		.name = "flags",
5295 		.help = "VXLAN-GPE flags",
5296 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5297 			     item_param),
5298 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5299 					     flags)),
5300 	},
5301 	[ITEM_VXLAN_GPE_RSVD0] = {
5302 		.name = "rsvd0",
5303 		.help = "VXLAN-GPE rsvd0",
5304 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5305 			     item_param),
5306 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5307 					     rsvd0)),
5308 	},
5309 	[ITEM_VXLAN_GPE_RSVD1] = {
5310 		.name = "rsvd1",
5311 		.help = "VXLAN-GPE rsvd1",
5312 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
5313 			     item_param),
5314 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
5315 					     rsvd1)),
5316 	},
5317 	[ITEM_ARP_ETH_IPV4] = {
5318 		.name = "arp_eth_ipv4",
5319 		.help = "match ARP header for Ethernet/IPv4",
5320 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
5321 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
5322 		.next = NEXT(item_arp_eth_ipv4),
5323 		.call = parse_vc,
5324 	},
5325 	[ITEM_ARP_ETH_IPV4_SHA] = {
5326 		.name = "sha",
5327 		.help = "sender hardware address",
5328 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5329 			     item_param),
5330 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5331 					     hdr.arp_data.arp_sha)),
5332 	},
5333 	[ITEM_ARP_ETH_IPV4_SPA] = {
5334 		.name = "spa",
5335 		.help = "sender IPv4 address",
5336 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5337 			     item_param),
5338 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5339 					     hdr.arp_data.arp_sip)),
5340 	},
5341 	[ITEM_ARP_ETH_IPV4_THA] = {
5342 		.name = "tha",
5343 		.help = "target hardware address",
5344 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
5345 			     item_param),
5346 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5347 					     hdr.arp_data.arp_tha)),
5348 	},
5349 	[ITEM_ARP_ETH_IPV4_TPA] = {
5350 		.name = "tpa",
5351 		.help = "target IPv4 address",
5352 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
5353 			     item_param),
5354 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
5355 					     hdr.arp_data.arp_tip)),
5356 	},
5357 	[ITEM_IPV6_EXT] = {
5358 		.name = "ipv6_ext",
5359 		.help = "match presence of any IPv6 extension header",
5360 		.priv = PRIV_ITEM(IPV6_EXT,
5361 				  sizeof(struct rte_flow_item_ipv6_ext)),
5362 		.next = NEXT(item_ipv6_ext),
5363 		.call = parse_vc,
5364 	},
5365 	[ITEM_IPV6_EXT_NEXT_HDR] = {
5366 		.name = "next_hdr",
5367 		.help = "next header",
5368 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5369 			     item_param),
5370 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
5371 					     next_hdr)),
5372 	},
5373 	[ITEM_IPV6_FRAG_EXT] = {
5374 		.name = "ipv6_frag_ext",
5375 		.help = "match presence of IPv6 fragment extension header",
5376 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
5377 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
5378 		.next = NEXT(item_ipv6_frag_ext),
5379 		.call = parse_vc,
5380 	},
5381 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
5382 		.name = "next_hdr",
5383 		.help = "next header",
5384 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5385 			     item_param),
5386 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
5387 					hdr.next_header)),
5388 	},
5389 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
5390 		.name = "frag_data",
5391 		.help = "fragment flags and offset",
5392 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5393 			     item_param),
5394 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5395 					     hdr.frag_data)),
5396 	},
5397 	[ITEM_IPV6_FRAG_EXT_ID] = {
5398 		.name = "packet_id",
5399 		.help = "fragment packet id",
5400 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
5401 			     item_param),
5402 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
5403 					     hdr.id)),
5404 	},
5405 	[ITEM_ICMP6] = {
5406 		.name = "icmp6",
5407 		.help = "match any ICMPv6 header",
5408 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
5409 		.next = NEXT(item_icmp6),
5410 		.call = parse_vc,
5411 	},
5412 	[ITEM_ICMP6_TYPE] = {
5413 		.name = "type",
5414 		.help = "ICMPv6 type",
5415 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5416 			     item_param),
5417 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5418 					     type)),
5419 	},
5420 	[ITEM_ICMP6_CODE] = {
5421 		.name = "code",
5422 		.help = "ICMPv6 code",
5423 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
5424 			     item_param),
5425 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
5426 					     code)),
5427 	},
5428 	[ITEM_ICMP6_ECHO_REQUEST] = {
5429 		.name = "icmp6_echo_request",
5430 		.help = "match ICMPv6 echo request",
5431 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
5432 				  sizeof(struct rte_flow_item_icmp6_echo)),
5433 		.next = NEXT(item_icmp6_echo_request),
5434 		.call = parse_vc,
5435 	},
5436 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
5437 		.name = "ident",
5438 		.help = "ICMPv6 echo request identifier",
5439 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5440 			     item_param),
5441 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5442 					     hdr.identifier)),
5443 	},
5444 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
5445 		.name = "seq",
5446 		.help = "ICMPv6 echo request sequence",
5447 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
5448 			     item_param),
5449 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5450 					     hdr.sequence)),
5451 	},
5452 	[ITEM_ICMP6_ECHO_REPLY] = {
5453 		.name = "icmp6_echo_reply",
5454 		.help = "match ICMPv6 echo reply",
5455 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
5456 				  sizeof(struct rte_flow_item_icmp6_echo)),
5457 		.next = NEXT(item_icmp6_echo_reply),
5458 		.call = parse_vc,
5459 	},
5460 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
5461 		.name = "ident",
5462 		.help = "ICMPv6 echo reply identifier",
5463 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5464 			     item_param),
5465 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5466 					     hdr.identifier)),
5467 	},
5468 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
5469 		.name = "seq",
5470 		.help = "ICMPv6 echo reply sequence",
5471 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
5472 			     item_param),
5473 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
5474 					     hdr.sequence)),
5475 	},
5476 	[ITEM_ICMP6_ND_NS] = {
5477 		.name = "icmp6_nd_ns",
5478 		.help = "match ICMPv6 neighbor discovery solicitation",
5479 		.priv = PRIV_ITEM(ICMP6_ND_NS,
5480 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
5481 		.next = NEXT(item_icmp6_nd_ns),
5482 		.call = parse_vc,
5483 	},
5484 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
5485 		.name = "target_addr",
5486 		.help = "target address",
5487 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
5488 			     item_param),
5489 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
5490 					     target_addr)),
5491 	},
5492 	[ITEM_ICMP6_ND_NA] = {
5493 		.name = "icmp6_nd_na",
5494 		.help = "match ICMPv6 neighbor discovery advertisement",
5495 		.priv = PRIV_ITEM(ICMP6_ND_NA,
5496 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
5497 		.next = NEXT(item_icmp6_nd_na),
5498 		.call = parse_vc,
5499 	},
5500 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
5501 		.name = "target_addr",
5502 		.help = "target address",
5503 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
5504 			     item_param),
5505 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
5506 					     target_addr)),
5507 	},
5508 	[ITEM_ICMP6_ND_OPT] = {
5509 		.name = "icmp6_nd_opt",
5510 		.help = "match presence of any ICMPv6 neighbor discovery"
5511 			" option",
5512 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
5513 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
5514 		.next = NEXT(item_icmp6_nd_opt),
5515 		.call = parse_vc,
5516 	},
5517 	[ITEM_ICMP6_ND_OPT_TYPE] = {
5518 		.name = "type",
5519 		.help = "ND option type",
5520 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5521 			     item_param),
5522 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
5523 					     type)),
5524 	},
5525 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
5526 		.name = "icmp6_nd_opt_sla_eth",
5527 		.help = "match ICMPv6 neighbor discovery source Ethernet"
5528 			" link-layer address option",
5529 		.priv = PRIV_ITEM
5530 			(ICMP6_ND_OPT_SLA_ETH,
5531 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
5532 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
5533 		.call = parse_vc,
5534 	},
5535 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
5536 		.name = "sla",
5537 		.help = "source Ethernet LLA",
5538 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
5539 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5540 		.args = ARGS(ARGS_ENTRY_HTON
5541 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
5542 	},
5543 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
5544 		.name = "icmp6_nd_opt_tla_eth",
5545 		.help = "match ICMPv6 neighbor discovery target Ethernet"
5546 			" link-layer address option",
5547 		.priv = PRIV_ITEM
5548 			(ICMP6_ND_OPT_TLA_ETH,
5549 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
5550 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
5551 		.call = parse_vc,
5552 	},
5553 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
5554 		.name = "tla",
5555 		.help = "target Ethernet LLA",
5556 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
5557 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
5558 		.args = ARGS(ARGS_ENTRY_HTON
5559 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
5560 	},
5561 	[ITEM_META] = {
5562 		.name = "meta",
5563 		.help = "match metadata header",
5564 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
5565 		.next = NEXT(item_meta),
5566 		.call = parse_vc,
5567 	},
5568 	[ITEM_META_DATA] = {
5569 		.name = "data",
5570 		.help = "metadata value",
5571 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
5572 			     item_param),
5573 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
5574 					     data, "\xff\xff\xff\xff")),
5575 	},
5576 	[ITEM_RANDOM] = {
5577 		.name = "random",
5578 		.help = "match random value",
5579 		.priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)),
5580 		.next = NEXT(item_random),
5581 		.call = parse_vc,
5582 	},
5583 	[ITEM_RANDOM_VALUE] = {
5584 		.name = "value",
5585 		.help = "random value",
5586 		.next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED),
5587 			     item_param),
5588 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random,
5589 					     value, "\xff\xff")),
5590 	},
5591 	[ITEM_GRE_KEY] = {
5592 		.name = "gre_key",
5593 		.help = "match GRE key",
5594 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
5595 		.next = NEXT(item_gre_key),
5596 		.call = parse_vc,
5597 	},
5598 	[ITEM_GRE_KEY_VALUE] = {
5599 		.name = "value",
5600 		.help = "key value",
5601 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
5602 			     item_param),
5603 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
5604 	},
5605 	[ITEM_GRE_OPTION] = {
5606 		.name = "gre_option",
5607 		.help = "match GRE optional fields",
5608 		.priv = PRIV_ITEM(GRE_OPTION,
5609 				  sizeof(struct rte_flow_item_gre_opt)),
5610 		.next = NEXT(item_gre_option),
5611 		.call = parse_vc,
5612 	},
5613 	[ITEM_GRE_OPTION_CHECKSUM] = {
5614 		.name = "checksum",
5615 		.help = "match GRE checksum",
5616 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5617 			     item_param),
5618 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5619 					     checksum_rsvd.checksum)),
5620 	},
5621 	[ITEM_GRE_OPTION_KEY] = {
5622 		.name = "key",
5623 		.help = "match GRE key",
5624 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5625 			     item_param),
5626 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5627 					     key.key)),
5628 	},
5629 	[ITEM_GRE_OPTION_SEQUENCE] = {
5630 		.name = "sequence",
5631 		.help = "match GRE sequence",
5632 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
5633 			     item_param),
5634 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
5635 					     sequence.sequence)),
5636 	},
5637 	[ITEM_GTP_PSC] = {
5638 		.name = "gtp_psc",
5639 		.help = "match GTP extension header with type 0x85",
5640 		.priv = PRIV_ITEM(GTP_PSC,
5641 				sizeof(struct rte_flow_item_gtp_psc)),
5642 		.next = NEXT(item_gtp_psc),
5643 		.call = parse_vc,
5644 	},
5645 	[ITEM_GTP_PSC_QFI] = {
5646 		.name = "qfi",
5647 		.help = "QoS flow identifier",
5648 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5649 			     item_param),
5650 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5651 					hdr.qfi, 6)),
5652 	},
5653 	[ITEM_GTP_PSC_PDU_T] = {
5654 		.name = "pdu_t",
5655 		.help = "PDU type",
5656 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
5657 			     item_param),
5658 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
5659 					hdr.type, 4)),
5660 	},
5661 	[ITEM_PPPOES] = {
5662 		.name = "pppoes",
5663 		.help = "match PPPoE session header",
5664 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
5665 		.next = NEXT(item_pppoes),
5666 		.call = parse_vc,
5667 	},
5668 	[ITEM_PPPOED] = {
5669 		.name = "pppoed",
5670 		.help = "match PPPoE discovery header",
5671 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
5672 		.next = NEXT(item_pppoed),
5673 		.call = parse_vc,
5674 	},
5675 	[ITEM_PPPOE_SEID] = {
5676 		.name = "seid",
5677 		.help = "session identifier",
5678 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
5679 			     item_param),
5680 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
5681 					session_id)),
5682 	},
5683 	[ITEM_PPPOE_PROTO_ID] = {
5684 		.name = "pppoe_proto_id",
5685 		.help = "match PPPoE session protocol identifier",
5686 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
5687 				sizeof(struct rte_flow_item_pppoe_proto_id)),
5688 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
5689 			     item_param),
5690 		.args = ARGS(ARGS_ENTRY_HTON
5691 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
5692 		.call = parse_vc,
5693 	},
5694 	[ITEM_HIGIG2] = {
5695 		.name = "higig2",
5696 		.help = "matches higig2 header",
5697 		.priv = PRIV_ITEM(HIGIG2,
5698 				sizeof(struct rte_flow_item_higig2_hdr)),
5699 		.next = NEXT(item_higig2),
5700 		.call = parse_vc,
5701 	},
5702 	[ITEM_HIGIG2_CLASSIFICATION] = {
5703 		.name = "classification",
5704 		.help = "matches classification of higig2 header",
5705 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5706 			     item_param),
5707 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5708 					hdr.ppt1.classification)),
5709 	},
5710 	[ITEM_HIGIG2_VID] = {
5711 		.name = "vid",
5712 		.help = "matches vid of higig2 header",
5713 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
5714 			     item_param),
5715 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
5716 					hdr.ppt1.vid)),
5717 	},
5718 	[ITEM_TAG] = {
5719 		.name = "tag",
5720 		.help = "match tag value",
5721 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5722 		.next = NEXT(item_tag),
5723 		.call = parse_vc,
5724 	},
5725 	[ITEM_TAG_DATA] = {
5726 		.name = "data",
5727 		.help = "tag value to match",
5728 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5729 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5730 	},
5731 	[ITEM_TAG_INDEX] = {
5732 		.name = "index",
5733 		.help = "index of tag array to match",
5734 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5735 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5736 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5737 	},
5738 	[ITEM_L2TPV3OIP] = {
5739 		.name = "l2tpv3oip",
5740 		.help = "match L2TPv3 over IP header",
5741 		.priv = PRIV_ITEM(L2TPV3OIP,
5742 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5743 		.next = NEXT(item_l2tpv3oip),
5744 		.call = parse_vc,
5745 	},
5746 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5747 		.name = "session_id",
5748 		.help = "session identifier",
5749 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5750 			     item_param),
5751 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5752 					     session_id)),
5753 	},
5754 	[ITEM_ESP] = {
5755 		.name = "esp",
5756 		.help = "match ESP header",
5757 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5758 		.next = NEXT(item_esp),
5759 		.call = parse_vc,
5760 	},
5761 	[ITEM_ESP_SPI] = {
5762 		.name = "spi",
5763 		.help = "security policy index",
5764 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5765 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5766 				hdr.spi)),
5767 	},
5768 	[ITEM_AH] = {
5769 		.name = "ah",
5770 		.help = "match AH header",
5771 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5772 		.next = NEXT(item_ah),
5773 		.call = parse_vc,
5774 	},
5775 	[ITEM_AH_SPI] = {
5776 		.name = "spi",
5777 		.help = "security parameters index",
5778 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5779 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5780 	},
5781 	[ITEM_PFCP] = {
5782 		.name = "pfcp",
5783 		.help = "match pfcp header",
5784 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5785 		.next = NEXT(item_pfcp),
5786 		.call = parse_vc,
5787 	},
5788 	[ITEM_PFCP_S_FIELD] = {
5789 		.name = "s_field",
5790 		.help = "S field",
5791 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5792 			     item_param),
5793 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5794 				s_field)),
5795 	},
5796 	[ITEM_PFCP_SEID] = {
5797 		.name = "seid",
5798 		.help = "session endpoint identifier",
5799 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5800 			     item_param),
5801 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5802 	},
5803 	[ITEM_ECPRI] = {
5804 		.name = "ecpri",
5805 		.help = "match eCPRI header",
5806 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5807 		.next = NEXT(item_ecpri),
5808 		.call = parse_vc,
5809 	},
5810 	[ITEM_ECPRI_COMMON] = {
5811 		.name = "common",
5812 		.help = "eCPRI common header",
5813 		.next = NEXT(item_ecpri_common),
5814 	},
5815 	[ITEM_ECPRI_COMMON_TYPE] = {
5816 		.name = "type",
5817 		.help = "type of common header",
5818 		.next = NEXT(item_ecpri_common_type),
5819 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5820 	},
5821 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5822 		.name = "iq_data",
5823 		.help = "Type #0: IQ Data",
5824 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5825 					ITEM_NEXT)),
5826 		.call = parse_vc_item_ecpri_type,
5827 	},
5828 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5829 		.name = "pc_id",
5830 		.help = "Physical Channel ID",
5831 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5832 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5833 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5834 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5835 				hdr.type0.pc_id)),
5836 	},
5837 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5838 		.name = "rtc_ctrl",
5839 		.help = "Type #2: Real-Time Control Data",
5840 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5841 					ITEM_NEXT)),
5842 		.call = parse_vc_item_ecpri_type,
5843 	},
5844 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5845 		.name = "rtc_id",
5846 		.help = "Real-Time Control Data ID",
5847 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5848 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5849 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5850 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5851 				hdr.type2.rtc_id)),
5852 	},
5853 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5854 		.name = "delay_measure",
5855 		.help = "Type #5: One-Way Delay Measurement",
5856 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5857 					ITEM_NEXT)),
5858 		.call = parse_vc_item_ecpri_type,
5859 	},
5860 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5861 		.name = "msr_id",
5862 		.help = "Measurement ID",
5863 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5864 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5865 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5866 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5867 				hdr.type5.msr_id)),
5868 	},
5869 	[ITEM_GENEVE_OPT] = {
5870 		.name = "geneve-opt",
5871 		.help = "GENEVE header option",
5872 		.priv = PRIV_ITEM(GENEVE_OPT,
5873 				  sizeof(struct rte_flow_item_geneve_opt) +
5874 				  ITEM_GENEVE_OPT_DATA_SIZE),
5875 		.next = NEXT(item_geneve_opt),
5876 		.call = parse_vc,
5877 	},
5878 	[ITEM_GENEVE_OPT_CLASS]	= {
5879 		.name = "class",
5880 		.help = "GENEVE option class",
5881 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5882 			     item_param),
5883 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5884 					     option_class)),
5885 	},
5886 	[ITEM_GENEVE_OPT_TYPE] = {
5887 		.name = "type",
5888 		.help = "GENEVE option type",
5889 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5890 			     item_param),
5891 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5892 					option_type)),
5893 	},
5894 	[ITEM_GENEVE_OPT_LENGTH] = {
5895 		.name = "length",
5896 		.help = "GENEVE option data length (in 32b words)",
5897 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5898 			     item_param),
5899 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5900 				struct rte_flow_item_geneve_opt, option_len,
5901 				0, 31)),
5902 	},
5903 	[ITEM_GENEVE_OPT_DATA] = {
5904 		.name = "data",
5905 		.help = "GENEVE option data pattern",
5906 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5907 			     item_param),
5908 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5909 			     ARGS_ENTRY_ARB(0, 0),
5910 			     ARGS_ENTRY_ARB
5911 				(sizeof(struct rte_flow_item_geneve_opt),
5912 				ITEM_GENEVE_OPT_DATA_SIZE)),
5913 	},
5914 	[ITEM_INTEGRITY] = {
5915 		.name = "integrity",
5916 		.help = "match packet integrity",
5917 		.priv = PRIV_ITEM(INTEGRITY,
5918 				  sizeof(struct rte_flow_item_integrity)),
5919 		.next = NEXT(item_integrity),
5920 		.call = parse_vc,
5921 	},
5922 	[ITEM_INTEGRITY_LEVEL] = {
5923 		.name = "level",
5924 		.help = "integrity level",
5925 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5926 			     item_param),
5927 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5928 	},
5929 	[ITEM_INTEGRITY_VALUE] = {
5930 		.name = "value",
5931 		.help = "integrity value",
5932 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5933 			     item_param),
5934 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5935 	},
5936 	[ITEM_CONNTRACK] = {
5937 		.name = "conntrack",
5938 		.help = "conntrack state",
5939 		.priv = PRIV_ITEM(CONNTRACK,
5940 				  sizeof(struct rte_flow_item_conntrack)),
5941 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5942 			     item_param),
5943 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5944 		.call = parse_vc,
5945 	},
5946 	[ITEM_PORT_REPRESENTOR] = {
5947 		.name = "port_representor",
5948 		.help = "match traffic entering the embedded switch from the given ethdev",
5949 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5950 				  sizeof(struct rte_flow_item_ethdev)),
5951 		.next = NEXT(item_port_representor),
5952 		.call = parse_vc,
5953 	},
5954 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5955 		.name = "port_id",
5956 		.help = "ethdev port ID",
5957 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5958 			     item_param),
5959 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5960 	},
5961 	[ITEM_REPRESENTED_PORT] = {
5962 		.name = "represented_port",
5963 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5964 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5965 				  sizeof(struct rte_flow_item_ethdev)),
5966 		.next = NEXT(item_represented_port),
5967 		.call = parse_vc,
5968 	},
5969 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5970 		.name = "ethdev_port_id",
5971 		.help = "ethdev port ID",
5972 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5973 			     item_param),
5974 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5975 	},
5976 	[ITEM_FLEX] = {
5977 		.name = "flex",
5978 		.help = "match flex header",
5979 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5980 		.next = NEXT(item_flex),
5981 		.call = parse_vc,
5982 	},
5983 	[ITEM_FLEX_ITEM_HANDLE] = {
5984 		.name = "item",
5985 		.help = "flex item handle",
5986 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5987 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5988 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5989 	},
5990 	[ITEM_FLEX_PATTERN_HANDLE] = {
5991 		.name = "pattern",
5992 		.help = "flex pattern handle",
5993 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5994 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5995 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5996 	},
5997 	[ITEM_L2TPV2] = {
5998 		.name = "l2tpv2",
5999 		.help = "match L2TPv2 header",
6000 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
6001 		.next = NEXT(item_l2tpv2),
6002 		.call = parse_vc,
6003 	},
6004 	[ITEM_L2TPV2_TYPE] = {
6005 		.name = "type",
6006 		.help = "type of l2tpv2",
6007 		.next = NEXT(item_l2tpv2_type),
6008 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
6009 	},
6010 	[ITEM_L2TPV2_TYPE_DATA] = {
6011 		.name = "data",
6012 		.help = "Type #7: data message without any options",
6013 		.next = NEXT(item_l2tpv2_type_data),
6014 		.call = parse_vc_item_l2tpv2_type,
6015 	},
6016 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
6017 		.name = "tunnel_id",
6018 		.help = "tunnel identifier",
6019 		.next = NEXT(item_l2tpv2_type_data,
6020 			     NEXT_ENTRY(COMMON_UNSIGNED),
6021 			     item_param),
6022 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6023 					     hdr.type7.tunnel_id)),
6024 	},
6025 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
6026 		.name = "session_id",
6027 		.help = "session identifier",
6028 		.next = NEXT(item_l2tpv2_type_data,
6029 			     NEXT_ENTRY(COMMON_UNSIGNED),
6030 			     item_param),
6031 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6032 					     hdr.type7.session_id)),
6033 	},
6034 	[ITEM_L2TPV2_TYPE_DATA_L] = {
6035 		.name = "data_l",
6036 		.help = "Type #6: data message with length option",
6037 		.next = NEXT(item_l2tpv2_type_data_l),
6038 		.call = parse_vc_item_l2tpv2_type,
6039 	},
6040 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
6041 		.name = "length",
6042 		.help = "message length",
6043 		.next = NEXT(item_l2tpv2_type_data_l,
6044 			     NEXT_ENTRY(COMMON_UNSIGNED),
6045 			     item_param),
6046 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6047 					     hdr.type6.length)),
6048 	},
6049 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
6050 		.name = "tunnel_id",
6051 		.help = "tunnel identifier",
6052 		.next = NEXT(item_l2tpv2_type_data_l,
6053 			     NEXT_ENTRY(COMMON_UNSIGNED),
6054 			     item_param),
6055 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6056 					     hdr.type6.tunnel_id)),
6057 	},
6058 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
6059 		.name = "session_id",
6060 		.help = "session identifier",
6061 		.next = NEXT(item_l2tpv2_type_data_l,
6062 			     NEXT_ENTRY(COMMON_UNSIGNED),
6063 			     item_param),
6064 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6065 					     hdr.type6.session_id)),
6066 	},
6067 	[ITEM_L2TPV2_TYPE_DATA_S] = {
6068 		.name = "data_s",
6069 		.help = "Type #5: data message with ns, nr option",
6070 		.next = NEXT(item_l2tpv2_type_data_s),
6071 		.call = parse_vc_item_l2tpv2_type,
6072 	},
6073 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
6074 		.name = "tunnel_id",
6075 		.help = "tunnel identifier",
6076 		.next = NEXT(item_l2tpv2_type_data_s,
6077 			     NEXT_ENTRY(COMMON_UNSIGNED),
6078 			     item_param),
6079 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6080 					     hdr.type5.tunnel_id)),
6081 	},
6082 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
6083 		.name = "session_id",
6084 		.help = "session identifier",
6085 		.next = NEXT(item_l2tpv2_type_data_s,
6086 			     NEXT_ENTRY(COMMON_UNSIGNED),
6087 			     item_param),
6088 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6089 					     hdr.type5.session_id)),
6090 	},
6091 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
6092 		.name = "ns",
6093 		.help = "sequence number for message",
6094 		.next = NEXT(item_l2tpv2_type_data_s,
6095 			     NEXT_ENTRY(COMMON_UNSIGNED),
6096 			     item_param),
6097 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6098 					     hdr.type5.ns)),
6099 	},
6100 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
6101 		.name = "nr",
6102 		.help = "sequence number for next receive message",
6103 		.next = NEXT(item_l2tpv2_type_data_s,
6104 			     NEXT_ENTRY(COMMON_UNSIGNED),
6105 			     item_param),
6106 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6107 					     hdr.type5.nr)),
6108 	},
6109 	[ITEM_L2TPV2_TYPE_DATA_O] = {
6110 		.name = "data_o",
6111 		.help = "Type #4: data message with offset option",
6112 		.next = NEXT(item_l2tpv2_type_data_o),
6113 		.call = parse_vc_item_l2tpv2_type,
6114 	},
6115 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
6116 		.name = "tunnel_id",
6117 		.help = "tunnel identifier",
6118 		.next = NEXT(item_l2tpv2_type_data_o,
6119 			     NEXT_ENTRY(COMMON_UNSIGNED),
6120 			     item_param),
6121 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6122 					     hdr.type4.tunnel_id)),
6123 	},
6124 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
6125 		.name = "session_id",
6126 		.help = "session identifier",
6127 		.next = NEXT(item_l2tpv2_type_data_o,
6128 			     NEXT_ENTRY(COMMON_UNSIGNED),
6129 			     item_param),
6130 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6131 					     hdr.type5.session_id)),
6132 	},
6133 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
6134 		.name = "offset_size",
6135 		.help = "the size of offset padding",
6136 		.next = NEXT(item_l2tpv2_type_data_o,
6137 			     NEXT_ENTRY(COMMON_UNSIGNED),
6138 			     item_param),
6139 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6140 					     hdr.type4.offset_size)),
6141 	},
6142 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
6143 		.name = "data_l_s",
6144 		.help = "Type #3: data message contains length, ns, nr "
6145 			"options",
6146 		.next = NEXT(item_l2tpv2_type_data_l_s),
6147 		.call = parse_vc_item_l2tpv2_type,
6148 	},
6149 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
6150 		.name = "length",
6151 		.help = "message length",
6152 		.next = NEXT(item_l2tpv2_type_data_l_s,
6153 			     NEXT_ENTRY(COMMON_UNSIGNED),
6154 			     item_param),
6155 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6156 					     hdr.type3.length)),
6157 	},
6158 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
6159 		.name = "tunnel_id",
6160 		.help = "tunnel identifier",
6161 		.next = NEXT(item_l2tpv2_type_data_l_s,
6162 			     NEXT_ENTRY(COMMON_UNSIGNED),
6163 			     item_param),
6164 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6165 					     hdr.type3.tunnel_id)),
6166 	},
6167 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
6168 		.name = "session_id",
6169 		.help = "session identifier",
6170 		.next = NEXT(item_l2tpv2_type_data_l_s,
6171 			     NEXT_ENTRY(COMMON_UNSIGNED),
6172 			     item_param),
6173 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6174 					     hdr.type3.session_id)),
6175 	},
6176 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
6177 		.name = "ns",
6178 		.help = "sequence number for message",
6179 		.next = NEXT(item_l2tpv2_type_data_l_s,
6180 			     NEXT_ENTRY(COMMON_UNSIGNED),
6181 			     item_param),
6182 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6183 					     hdr.type3.ns)),
6184 	},
6185 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
6186 		.name = "nr",
6187 		.help = "sequence number for next receive message",
6188 		.next = NEXT(item_l2tpv2_type_data_l_s,
6189 			     NEXT_ENTRY(COMMON_UNSIGNED),
6190 			     item_param),
6191 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6192 					     hdr.type3.nr)),
6193 	},
6194 	[ITEM_L2TPV2_TYPE_CTRL] = {
6195 		.name = "control",
6196 		.help = "Type #3: conrtol message contains length, ns, nr "
6197 			"options",
6198 		.next = NEXT(item_l2tpv2_type_ctrl),
6199 		.call = parse_vc_item_l2tpv2_type,
6200 	},
6201 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
6202 		.name = "length",
6203 		.help = "message length",
6204 		.next = NEXT(item_l2tpv2_type_ctrl,
6205 			     NEXT_ENTRY(COMMON_UNSIGNED),
6206 			     item_param),
6207 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6208 					     hdr.type3.length)),
6209 	},
6210 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
6211 		.name = "tunnel_id",
6212 		.help = "tunnel identifier",
6213 		.next = NEXT(item_l2tpv2_type_ctrl,
6214 			     NEXT_ENTRY(COMMON_UNSIGNED),
6215 			     item_param),
6216 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6217 					     hdr.type3.tunnel_id)),
6218 	},
6219 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
6220 		.name = "session_id",
6221 		.help = "session identifier",
6222 		.next = NEXT(item_l2tpv2_type_ctrl,
6223 			     NEXT_ENTRY(COMMON_UNSIGNED),
6224 			     item_param),
6225 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6226 					     hdr.type3.session_id)),
6227 	},
6228 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
6229 		.name = "ns",
6230 		.help = "sequence number for message",
6231 		.next = NEXT(item_l2tpv2_type_ctrl,
6232 			     NEXT_ENTRY(COMMON_UNSIGNED),
6233 			     item_param),
6234 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6235 					     hdr.type3.ns)),
6236 	},
6237 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
6238 		.name = "nr",
6239 		.help = "sequence number for next receive message",
6240 		.next = NEXT(item_l2tpv2_type_ctrl,
6241 			     NEXT_ENTRY(COMMON_UNSIGNED),
6242 			     item_param),
6243 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
6244 					     hdr.type3.nr)),
6245 	},
6246 	[ITEM_PPP] = {
6247 		.name = "ppp",
6248 		.help = "match PPP header",
6249 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
6250 		.next = NEXT(item_ppp),
6251 		.call = parse_vc,
6252 	},
6253 	[ITEM_PPP_ADDR] = {
6254 		.name = "addr",
6255 		.help = "PPP address",
6256 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6257 			     item_param),
6258 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
6259 	},
6260 	[ITEM_PPP_CTRL] = {
6261 		.name = "ctrl",
6262 		.help = "PPP control",
6263 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6264 			     item_param),
6265 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
6266 	},
6267 	[ITEM_PPP_PROTO_ID] = {
6268 		.name = "proto_id",
6269 		.help = "PPP protocol identifier",
6270 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
6271 			     item_param),
6272 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
6273 					hdr.proto_id)),
6274 	},
6275 	[ITEM_METER] = {
6276 		.name = "meter",
6277 		.help = "match meter color",
6278 		.priv = PRIV_ITEM(METER_COLOR,
6279 				  sizeof(struct rte_flow_item_meter_color)),
6280 		.next = NEXT(item_meter),
6281 		.call = parse_vc,
6282 	},
6283 	[ITEM_METER_COLOR] = {
6284 		.name = "color",
6285 		.help = "meter color",
6286 		.next = NEXT(item_meter,
6287 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
6288 			     item_param),
6289 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
6290 					color)),
6291 	},
6292 	[ITEM_METER_COLOR_NAME] = {
6293 		.name = "color_name",
6294 		.help = "meter color name",
6295 		.call = parse_meter_color,
6296 		.comp = comp_meter_color,
6297 	},
6298 	[ITEM_QUOTA] = {
6299 		.name = "quota",
6300 		.help = "match quota",
6301 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
6302 		.next = NEXT(item_quota),
6303 		.call = parse_vc
6304 	},
6305 	[ITEM_QUOTA_STATE] = {
6306 		.name = "quota_state",
6307 		.help = "quota state",
6308 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
6309 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
6310 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
6311 	},
6312 	[ITEM_QUOTA_STATE_NAME] = {
6313 		.name = "state_name",
6314 		.help = "quota state name",
6315 		.call = parse_quota_state_name,
6316 		.comp = comp_quota_state_name
6317 	},
6318 	[ITEM_IB_BTH] = {
6319 		.name = "ib_bth",
6320 		.help = "match ib bth fields",
6321 		.priv = PRIV_ITEM(IB_BTH,
6322 				  sizeof(struct rte_flow_item_ib_bth)),
6323 		.next = NEXT(item_ib_bth),
6324 		.call = parse_vc,
6325 	},
6326 	[ITEM_IB_BTH_OPCODE] = {
6327 		.name = "opcode",
6328 		.help = "match ib bth opcode",
6329 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6330 				 item_param),
6331 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6332 						 hdr.opcode)),
6333 	},
6334 	[ITEM_IB_BTH_PKEY] = {
6335 		.name = "pkey",
6336 		.help = "partition key",
6337 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6338 				 item_param),
6339 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6340 						 hdr.pkey)),
6341 	},
6342 	[ITEM_IB_BTH_DST_QPN] = {
6343 		.name = "dst_qp",
6344 		.help = "destination qp",
6345 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6346 				 item_param),
6347 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6348 						 hdr.dst_qp)),
6349 	},
6350 	[ITEM_IB_BTH_PSN] = {
6351 		.name = "psn",
6352 		.help = "packet sequence number",
6353 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
6354 				 item_param),
6355 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
6356 						 hdr.psn)),
6357 	},
6358 	[ITEM_PTYPE] = {
6359 		.name = "ptype",
6360 		.help = "match L2/L3/L4 and tunnel information",
6361 		.priv = PRIV_ITEM(PTYPE,
6362 				  sizeof(struct rte_flow_item_ptype)),
6363 		.next = NEXT(item_ptype),
6364 		.call = parse_vc,
6365 	},
6366 	[ITEM_PTYPE_VALUE] = {
6367 		.name = "packet_type",
6368 		.help = "packet type as defined in rte_mbuf_ptype",
6369 		.next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED),
6370 			     item_param),
6371 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)),
6372 	},
6373 	[ITEM_NSH] = {
6374 		.name = "nsh",
6375 		.help = "match NSH header",
6376 		.priv = PRIV_ITEM(NSH,
6377 				  sizeof(struct rte_flow_item_nsh)),
6378 		.next = NEXT(item_nsh),
6379 		.call = parse_vc,
6380 	},
6381 	[ITEM_COMPARE] = {
6382 		.name = "compare",
6383 		.help = "match with the comparison result",
6384 		.priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)),
6385 		.next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)),
6386 		.call = parse_vc,
6387 	},
6388 	[ITEM_COMPARE_OP] = {
6389 		.name = "op",
6390 		.help = "operation type",
6391 		.next = NEXT(item_compare_field,
6392 			NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param),
6393 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)),
6394 	},
6395 	[ITEM_COMPARE_OP_VALUE] = {
6396 		.name = "{operation}",
6397 		.help = "operation type value",
6398 		.call = parse_vc_compare_op,
6399 		.comp = comp_set_compare_op,
6400 	},
6401 	[ITEM_COMPARE_FIELD_A_TYPE] = {
6402 		.name = "a_type",
6403 		.help = "compared field type",
6404 		.next = NEXT(compare_field_a,
6405 			NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param),
6406 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)),
6407 	},
6408 	[ITEM_COMPARE_FIELD_A_TYPE_VALUE] = {
6409 		.name = "{a_type}",
6410 		.help = "compared field type value",
6411 		.call = parse_vc_compare_field_id,
6412 		.comp = comp_set_compare_field_id,
6413 	},
6414 	[ITEM_COMPARE_FIELD_A_LEVEL] = {
6415 		.name = "a_level",
6416 		.help = "compared field level",
6417 		.next = NEXT(compare_field_a,
6418 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param),
6419 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)),
6420 	},
6421 	[ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = {
6422 		.name = "{a_level}",
6423 		.help = "compared field level value",
6424 		.call = parse_vc_compare_field_level,
6425 		.comp = comp_none,
6426 	},
6427 	[ITEM_COMPARE_FIELD_A_TAG_INDEX] = {
6428 		.name = "a_tag_index",
6429 		.help = "compared field tag array",
6430 		.next = NEXT(compare_field_a,
6431 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6432 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6433 					a.tag_index)),
6434 	},
6435 	[ITEM_COMPARE_FIELD_A_TYPE_ID] = {
6436 		.name = "a_type_id",
6437 		.help = "compared field type ID",
6438 		.next = NEXT(compare_field_a,
6439 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6440 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6441 					a.type)),
6442 	},
6443 	[ITEM_COMPARE_FIELD_A_CLASS_ID] = {
6444 		.name = "a_class",
6445 		.help = "compared field class ID",
6446 		.next = NEXT(compare_field_a,
6447 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6448 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6449 					     a.class_id)),
6450 	},
6451 	[ITEM_COMPARE_FIELD_A_OFFSET] = {
6452 		.name = "a_offset",
6453 		.help = "compared field bit offset",
6454 		.next = NEXT(compare_field_a,
6455 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6456 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6457 					a.offset)),
6458 	},
6459 	[ITEM_COMPARE_FIELD_B_TYPE] = {
6460 		.name = "b_type",
6461 		.help = "comparator field type",
6462 		.next = NEXT(compare_field_b,
6463 			NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param),
6464 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6465 					b.field)),
6466 	},
6467 	[ITEM_COMPARE_FIELD_B_TYPE_VALUE] = {
6468 		.name = "{b_type}",
6469 		.help = "comparator field type value",
6470 		.call = parse_vc_compare_field_id,
6471 		.comp = comp_set_compare_field_id,
6472 	},
6473 	[ITEM_COMPARE_FIELD_B_LEVEL] = {
6474 		.name = "b_level",
6475 		.help = "comparator field level",
6476 		.next = NEXT(compare_field_b,
6477 			     NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param),
6478 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6479 					b.level)),
6480 	},
6481 	[ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = {
6482 		.name = "{b_level}",
6483 		.help = "comparator field level value",
6484 		.call = parse_vc_compare_field_level,
6485 		.comp = comp_none,
6486 	},
6487 	[ITEM_COMPARE_FIELD_B_TAG_INDEX] = {
6488 		.name = "b_tag_index",
6489 		.help = "comparator field tag array",
6490 		.next = NEXT(compare_field_b,
6491 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6492 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6493 					b.tag_index)),
6494 	},
6495 	[ITEM_COMPARE_FIELD_B_TYPE_ID] = {
6496 		.name = "b_type_id",
6497 		.help = "comparator field type ID",
6498 		.next = NEXT(compare_field_b,
6499 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6500 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6501 					b.type)),
6502 	},
6503 	[ITEM_COMPARE_FIELD_B_CLASS_ID] = {
6504 		.name = "b_class",
6505 		.help = "comparator field class ID",
6506 		.next = NEXT(compare_field_b,
6507 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6508 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare,
6509 					     b.class_id)),
6510 	},
6511 	[ITEM_COMPARE_FIELD_B_OFFSET] = {
6512 		.name = "b_offset",
6513 		.help = "comparator field bit offset",
6514 		.next = NEXT(compare_field_b,
6515 			     NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6516 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6517 					b.offset)),
6518 	},
6519 	[ITEM_COMPARE_FIELD_B_VALUE] = {
6520 		.name = "b_value",
6521 		.help = "comparator immediate value",
6522 		.next = NEXT(compare_field_b,
6523 			     NEXT_ENTRY(COMMON_HEX), item_param),
6524 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6525 			     ARGS_ENTRY_ARB(0, 0),
6526 			     ARGS_ENTRY(struct rte_flow_item_compare,
6527 					b.value)),
6528 	},
6529 	[ITEM_COMPARE_FIELD_B_POINTER] = {
6530 		.name = "b_ptr",
6531 		.help = "pointer to comparator immediate value",
6532 		.next = NEXT(compare_field_b,
6533 			     NEXT_ENTRY(COMMON_HEX), item_param),
6534 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6535 					b.pvalue),
6536 			     ARGS_ENTRY_ARB(0, 0),
6537 			     ARGS_ENTRY_ARB
6538 				(sizeof(struct rte_flow_item_compare),
6539 				 FLOW_FIELD_PATTERN_SIZE)),
6540 	},
6541 	[ITEM_COMPARE_FIELD_WIDTH] = {
6542 		.name = "width",
6543 		.help = "number of bits to compare",
6544 		.next = NEXT(item_compare_field,
6545 			NEXT_ENTRY(COMMON_UNSIGNED), item_param),
6546 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare,
6547 					width)),
6548 	},
6549 
6550 	/* Validate/create actions. */
6551 	[ACTIONS] = {
6552 		.name = "actions",
6553 		.help = "submit a list of associated actions",
6554 		.next = NEXT(next_action),
6555 		.call = parse_vc,
6556 	},
6557 	[ACTION_NEXT] = {
6558 		.name = "/",
6559 		.help = "specify next action",
6560 		.next = NEXT(next_action),
6561 	},
6562 	[ACTION_END] = {
6563 		.name = "end",
6564 		.help = "end list of actions",
6565 		.priv = PRIV_ACTION(END, 0),
6566 		.call = parse_vc,
6567 	},
6568 	[ACTION_VOID] = {
6569 		.name = "void",
6570 		.help = "no-op action",
6571 		.priv = PRIV_ACTION(VOID, 0),
6572 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6573 		.call = parse_vc,
6574 	},
6575 	[ACTION_PASSTHRU] = {
6576 		.name = "passthru",
6577 		.help = "let subsequent rule process matched packets",
6578 		.priv = PRIV_ACTION(PASSTHRU, 0),
6579 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6580 		.call = parse_vc,
6581 	},
6582 	[ACTION_SKIP_CMAN] = {
6583 		.name = "skip_cman",
6584 		.help = "bypass cman on received packets",
6585 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
6586 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6587 		.call = parse_vc,
6588 	},
6589 	[ACTION_JUMP] = {
6590 		.name = "jump",
6591 		.help = "redirect traffic to a given group",
6592 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
6593 		.next = NEXT(action_jump),
6594 		.call = parse_vc,
6595 	},
6596 	[ACTION_JUMP_GROUP] = {
6597 		.name = "group",
6598 		.help = "group to redirect traffic to",
6599 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
6600 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
6601 		.call = parse_vc_conf,
6602 	},
6603 	[ACTION_MARK] = {
6604 		.name = "mark",
6605 		.help = "attach 32 bit value to packets",
6606 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
6607 		.next = NEXT(action_mark),
6608 		.call = parse_vc,
6609 	},
6610 	[ACTION_MARK_ID] = {
6611 		.name = "id",
6612 		.help = "32 bit value to return with packets",
6613 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6614 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
6615 		.call = parse_vc_conf,
6616 	},
6617 	[ACTION_FLAG] = {
6618 		.name = "flag",
6619 		.help = "flag packets",
6620 		.priv = PRIV_ACTION(FLAG, 0),
6621 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6622 		.call = parse_vc,
6623 	},
6624 	[ACTION_QUEUE] = {
6625 		.name = "queue",
6626 		.help = "assign packets to a given queue index",
6627 		.priv = PRIV_ACTION(QUEUE,
6628 				    sizeof(struct rte_flow_action_queue)),
6629 		.next = NEXT(action_queue),
6630 		.call = parse_vc,
6631 	},
6632 	[ACTION_QUEUE_INDEX] = {
6633 		.name = "index",
6634 		.help = "queue index to use",
6635 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
6636 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
6637 		.call = parse_vc_conf,
6638 	},
6639 	[ACTION_DROP] = {
6640 		.name = "drop",
6641 		.help = "drop packets (note: passthru has priority)",
6642 		.priv = PRIV_ACTION(DROP, 0),
6643 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6644 		.call = parse_vc,
6645 	},
6646 	[ACTION_COUNT] = {
6647 		.name = "count",
6648 		.help = "enable counters for this rule",
6649 		.priv = PRIV_ACTION(COUNT,
6650 				    sizeof(struct rte_flow_action_count)),
6651 		.next = NEXT(action_count),
6652 		.call = parse_vc,
6653 	},
6654 	[ACTION_COUNT_ID] = {
6655 		.name = "identifier",
6656 		.help = "counter identifier to use",
6657 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
6658 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
6659 		.call = parse_vc_conf,
6660 	},
6661 	[ACTION_RSS] = {
6662 		.name = "rss",
6663 		.help = "spread packets among several queues",
6664 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
6665 		.next = NEXT(action_rss),
6666 		.call = parse_vc_action_rss,
6667 	},
6668 	[ACTION_RSS_FUNC] = {
6669 		.name = "func",
6670 		.help = "RSS hash function to apply",
6671 		.next = NEXT(action_rss,
6672 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
6673 					ACTION_RSS_FUNC_TOEPLITZ,
6674 					ACTION_RSS_FUNC_SIMPLE_XOR,
6675 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
6676 	},
6677 	[ACTION_RSS_FUNC_DEFAULT] = {
6678 		.name = "default",
6679 		.help = "default hash function",
6680 		.call = parse_vc_action_rss_func,
6681 	},
6682 	[ACTION_RSS_FUNC_TOEPLITZ] = {
6683 		.name = "toeplitz",
6684 		.help = "Toeplitz hash function",
6685 		.call = parse_vc_action_rss_func,
6686 	},
6687 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
6688 		.name = "simple_xor",
6689 		.help = "simple XOR hash function",
6690 		.call = parse_vc_action_rss_func,
6691 	},
6692 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
6693 		.name = "symmetric_toeplitz",
6694 		.help = "Symmetric Toeplitz hash function",
6695 		.call = parse_vc_action_rss_func,
6696 	},
6697 	[ACTION_RSS_LEVEL] = {
6698 		.name = "level",
6699 		.help = "encapsulation level for \"types\"",
6700 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6701 		.args = ARGS(ARGS_ENTRY_ARB
6702 			     (offsetof(struct action_rss_data, conf) +
6703 			      offsetof(struct rte_flow_action_rss, level),
6704 			      sizeof(((struct rte_flow_action_rss *)0)->
6705 				     level))),
6706 	},
6707 	[ACTION_RSS_TYPES] = {
6708 		.name = "types",
6709 		.help = "specific RSS hash types",
6710 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
6711 	},
6712 	[ACTION_RSS_TYPE] = {
6713 		.name = "{type}",
6714 		.help = "RSS hash type",
6715 		.call = parse_vc_action_rss_type,
6716 		.comp = comp_vc_action_rss_type,
6717 	},
6718 	[ACTION_RSS_KEY] = {
6719 		.name = "key",
6720 		.help = "RSS hash key",
6721 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
6722 		.args = ARGS(ARGS_ENTRY_ARB
6723 			     (offsetof(struct action_rss_data, conf) +
6724 			      offsetof(struct rte_flow_action_rss, key),
6725 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
6726 			     ARGS_ENTRY_ARB
6727 			     (offsetof(struct action_rss_data, conf) +
6728 			      offsetof(struct rte_flow_action_rss, key_len),
6729 			      sizeof(((struct rte_flow_action_rss *)0)->
6730 				     key_len)),
6731 			     ARGS_ENTRY(struct action_rss_data, key)),
6732 	},
6733 	[ACTION_RSS_KEY_LEN] = {
6734 		.name = "key_len",
6735 		.help = "RSS hash key length in bytes",
6736 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
6737 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6738 			     (offsetof(struct action_rss_data, conf) +
6739 			      offsetof(struct rte_flow_action_rss, key_len),
6740 			      sizeof(((struct rte_flow_action_rss *)0)->
6741 				     key_len),
6742 			      0,
6743 			      RSS_HASH_KEY_LENGTH)),
6744 	},
6745 	[ACTION_RSS_QUEUES] = {
6746 		.name = "queues",
6747 		.help = "queue indices to use",
6748 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
6749 		.call = parse_vc_conf,
6750 	},
6751 	[ACTION_RSS_QUEUE] = {
6752 		.name = "{queue}",
6753 		.help = "queue index",
6754 		.call = parse_vc_action_rss_queue,
6755 		.comp = comp_vc_action_rss_queue,
6756 	},
6757 	[ACTION_PF] = {
6758 		.name = "pf",
6759 		.help = "direct traffic to physical function",
6760 		.priv = PRIV_ACTION(PF, 0),
6761 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6762 		.call = parse_vc,
6763 	},
6764 	[ACTION_VF] = {
6765 		.name = "vf",
6766 		.help = "direct traffic to a virtual function ID",
6767 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
6768 		.next = NEXT(action_vf),
6769 		.call = parse_vc,
6770 	},
6771 	[ACTION_VF_ORIGINAL] = {
6772 		.name = "original",
6773 		.help = "use original VF ID if possible",
6774 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
6775 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
6776 					   original, 1)),
6777 		.call = parse_vc_conf,
6778 	},
6779 	[ACTION_VF_ID] = {
6780 		.name = "id",
6781 		.help = "VF ID",
6782 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
6783 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
6784 		.call = parse_vc_conf,
6785 	},
6786 	[ACTION_PORT_ID] = {
6787 		.name = "port_id",
6788 		.help = "direct matching traffic to a given DPDK port ID",
6789 		.priv = PRIV_ACTION(PORT_ID,
6790 				    sizeof(struct rte_flow_action_port_id)),
6791 		.next = NEXT(action_port_id),
6792 		.call = parse_vc,
6793 	},
6794 	[ACTION_PORT_ID_ORIGINAL] = {
6795 		.name = "original",
6796 		.help = "use original DPDK port ID if possible",
6797 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
6798 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
6799 					   original, 1)),
6800 		.call = parse_vc_conf,
6801 	},
6802 	[ACTION_PORT_ID_ID] = {
6803 		.name = "id",
6804 		.help = "DPDK port ID",
6805 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
6806 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
6807 		.call = parse_vc_conf,
6808 	},
6809 	[ACTION_METER] = {
6810 		.name = "meter",
6811 		.help = "meter the directed packets at given id",
6812 		.priv = PRIV_ACTION(METER,
6813 				    sizeof(struct rte_flow_action_meter)),
6814 		.next = NEXT(action_meter),
6815 		.call = parse_vc,
6816 	},
6817 	[ACTION_METER_COLOR] = {
6818 		.name = "color",
6819 		.help = "meter color for the packets",
6820 		.priv = PRIV_ACTION(METER_COLOR,
6821 				sizeof(struct rte_flow_action_meter_color)),
6822 		.next = NEXT(action_meter_color),
6823 		.call = parse_vc,
6824 	},
6825 	[ACTION_METER_COLOR_TYPE] = {
6826 		.name = "type",
6827 		.help = "specific meter color",
6828 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6829 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
6830 					ACTION_METER_COLOR_YELLOW,
6831 					ACTION_METER_COLOR_RED)),
6832 	},
6833 	[ACTION_METER_COLOR_GREEN] = {
6834 		.name = "green",
6835 		.help = "meter color green",
6836 		.call = parse_vc_action_meter_color_type,
6837 	},
6838 	[ACTION_METER_COLOR_YELLOW] = {
6839 		.name = "yellow",
6840 		.help = "meter color yellow",
6841 		.call = parse_vc_action_meter_color_type,
6842 	},
6843 	[ACTION_METER_COLOR_RED] = {
6844 		.name = "red",
6845 		.help = "meter color red",
6846 		.call = parse_vc_action_meter_color_type,
6847 	},
6848 	[ACTION_METER_ID] = {
6849 		.name = "mtr_id",
6850 		.help = "meter id to use",
6851 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
6852 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
6853 		.call = parse_vc_conf,
6854 	},
6855 	[ACTION_METER_MARK] = {
6856 		.name = "meter_mark",
6857 		.help = "meter the directed packets using profile and policy",
6858 		.priv = PRIV_ACTION(METER_MARK,
6859 				    sizeof(struct rte_flow_action_meter_mark)),
6860 		.next = NEXT(action_meter_mark),
6861 		.call = parse_vc,
6862 	},
6863 	[ACTION_METER_PROFILE] = {
6864 		.name = "mtr_profile",
6865 		.help = "meter profile id to use",
6866 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
6867 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6868 	},
6869 	[ACTION_METER_PROFILE_ID2PTR] = {
6870 		.name = "{mtr_profile_id}",
6871 		.type = "PROFILE_ID",
6872 		.help = "meter profile id",
6873 		.next = NEXT(action_meter_mark),
6874 		.call = parse_meter_profile_id2ptr,
6875 		.comp = comp_none,
6876 	},
6877 	[ACTION_METER_POLICY] = {
6878 		.name = "mtr_policy",
6879 		.help = "meter policy id to use",
6880 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
6881 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6882 	},
6883 	[ACTION_METER_POLICY_ID2PTR] = {
6884 		.name = "{mtr_policy_id}",
6885 		.type = "POLICY_ID",
6886 		.help = "meter policy id",
6887 		.next = NEXT(action_meter_mark),
6888 		.call = parse_meter_policy_id2ptr,
6889 		.comp = comp_none,
6890 	},
6891 	[ACTION_METER_COLOR_MODE] = {
6892 		.name = "mtr_color_mode",
6893 		.help = "meter color awareness mode",
6894 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6895 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
6896 		.call = parse_vc_conf,
6897 	},
6898 	[ACTION_METER_STATE] = {
6899 		.name = "mtr_state",
6900 		.help = "meter state",
6901 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
6902 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
6903 		.call = parse_vc_conf,
6904 	},
6905 	[ACTION_OF_DEC_NW_TTL] = {
6906 		.name = "of_dec_nw_ttl",
6907 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
6908 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
6909 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6910 		.call = parse_vc,
6911 	},
6912 	[ACTION_OF_POP_VLAN] = {
6913 		.name = "of_pop_vlan",
6914 		.help = "OpenFlow's OFPAT_POP_VLAN",
6915 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6916 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6917 		.call = parse_vc,
6918 	},
6919 	[ACTION_OF_PUSH_VLAN] = {
6920 		.name = "of_push_vlan",
6921 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6922 		.priv = PRIV_ACTION
6923 			(OF_PUSH_VLAN,
6924 			 sizeof(struct rte_flow_action_of_push_vlan)),
6925 		.next = NEXT(action_of_push_vlan),
6926 		.call = parse_vc,
6927 	},
6928 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6929 		.name = "ethertype",
6930 		.help = "EtherType",
6931 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6932 		.args = ARGS(ARGS_ENTRY_HTON
6933 			     (struct rte_flow_action_of_push_vlan,
6934 			      ethertype)),
6935 		.call = parse_vc_conf,
6936 	},
6937 	[ACTION_OF_SET_VLAN_VID] = {
6938 		.name = "of_set_vlan_vid",
6939 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6940 		.priv = PRIV_ACTION
6941 			(OF_SET_VLAN_VID,
6942 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6943 		.next = NEXT(action_of_set_vlan_vid),
6944 		.call = parse_vc,
6945 	},
6946 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6947 		.name = "vlan_vid",
6948 		.help = "VLAN id",
6949 		.next = NEXT(action_of_set_vlan_vid,
6950 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6951 		.args = ARGS(ARGS_ENTRY_HTON
6952 			     (struct rte_flow_action_of_set_vlan_vid,
6953 			      vlan_vid)),
6954 		.call = parse_vc_conf,
6955 	},
6956 	[ACTION_OF_SET_VLAN_PCP] = {
6957 		.name = "of_set_vlan_pcp",
6958 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6959 		.priv = PRIV_ACTION
6960 			(OF_SET_VLAN_PCP,
6961 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6962 		.next = NEXT(action_of_set_vlan_pcp),
6963 		.call = parse_vc,
6964 	},
6965 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6966 		.name = "vlan_pcp",
6967 		.help = "VLAN priority",
6968 		.next = NEXT(action_of_set_vlan_pcp,
6969 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6970 		.args = ARGS(ARGS_ENTRY_HTON
6971 			     (struct rte_flow_action_of_set_vlan_pcp,
6972 			      vlan_pcp)),
6973 		.call = parse_vc_conf,
6974 	},
6975 	[ACTION_OF_POP_MPLS] = {
6976 		.name = "of_pop_mpls",
6977 		.help = "OpenFlow's OFPAT_POP_MPLS",
6978 		.priv = PRIV_ACTION(OF_POP_MPLS,
6979 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6980 		.next = NEXT(action_of_pop_mpls),
6981 		.call = parse_vc,
6982 	},
6983 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6984 		.name = "ethertype",
6985 		.help = "EtherType",
6986 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6987 		.args = ARGS(ARGS_ENTRY_HTON
6988 			     (struct rte_flow_action_of_pop_mpls,
6989 			      ethertype)),
6990 		.call = parse_vc_conf,
6991 	},
6992 	[ACTION_OF_PUSH_MPLS] = {
6993 		.name = "of_push_mpls",
6994 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6995 		.priv = PRIV_ACTION
6996 			(OF_PUSH_MPLS,
6997 			 sizeof(struct rte_flow_action_of_push_mpls)),
6998 		.next = NEXT(action_of_push_mpls),
6999 		.call = parse_vc,
7000 	},
7001 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
7002 		.name = "ethertype",
7003 		.help = "EtherType",
7004 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
7005 		.args = ARGS(ARGS_ENTRY_HTON
7006 			     (struct rte_flow_action_of_push_mpls,
7007 			      ethertype)),
7008 		.call = parse_vc_conf,
7009 	},
7010 	[ACTION_VXLAN_ENCAP] = {
7011 		.name = "vxlan_encap",
7012 		.help = "VXLAN encapsulation, uses configuration set by \"set"
7013 			" vxlan\"",
7014 		.priv = PRIV_ACTION(VXLAN_ENCAP,
7015 				    sizeof(struct action_vxlan_encap_data)),
7016 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7017 		.call = parse_vc_action_vxlan_encap,
7018 	},
7019 	[ACTION_VXLAN_DECAP] = {
7020 		.name = "vxlan_decap",
7021 		.help = "Performs a decapsulation action by stripping all"
7022 			" headers of the VXLAN tunnel network overlay from the"
7023 			" matched flow.",
7024 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
7025 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7026 		.call = parse_vc,
7027 	},
7028 	[ACTION_NVGRE_ENCAP] = {
7029 		.name = "nvgre_encap",
7030 		.help = "NVGRE encapsulation, uses configuration set by \"set"
7031 			" nvgre\"",
7032 		.priv = PRIV_ACTION(NVGRE_ENCAP,
7033 				    sizeof(struct action_nvgre_encap_data)),
7034 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7035 		.call = parse_vc_action_nvgre_encap,
7036 	},
7037 	[ACTION_NVGRE_DECAP] = {
7038 		.name = "nvgre_decap",
7039 		.help = "Performs a decapsulation action by stripping all"
7040 			" headers of the NVGRE tunnel network overlay from the"
7041 			" matched flow.",
7042 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
7043 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7044 		.call = parse_vc,
7045 	},
7046 	[ACTION_L2_ENCAP] = {
7047 		.name = "l2_encap",
7048 		.help = "l2 encap, uses configuration set by"
7049 			" \"set l2_encap\"",
7050 		.priv = PRIV_ACTION(RAW_ENCAP,
7051 				    sizeof(struct action_raw_encap_data)),
7052 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7053 		.call = parse_vc_action_l2_encap,
7054 	},
7055 	[ACTION_L2_DECAP] = {
7056 		.name = "l2_decap",
7057 		.help = "l2 decap, uses configuration set by"
7058 			" \"set l2_decap\"",
7059 		.priv = PRIV_ACTION(RAW_DECAP,
7060 				    sizeof(struct action_raw_decap_data)),
7061 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7062 		.call = parse_vc_action_l2_decap,
7063 	},
7064 	[ACTION_MPLSOGRE_ENCAP] = {
7065 		.name = "mplsogre_encap",
7066 		.help = "mplsogre encapsulation, uses configuration set by"
7067 			" \"set mplsogre_encap\"",
7068 		.priv = PRIV_ACTION(RAW_ENCAP,
7069 				    sizeof(struct action_raw_encap_data)),
7070 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7071 		.call = parse_vc_action_mplsogre_encap,
7072 	},
7073 	[ACTION_MPLSOGRE_DECAP] = {
7074 		.name = "mplsogre_decap",
7075 		.help = "mplsogre decapsulation, uses configuration set by"
7076 			" \"set mplsogre_decap\"",
7077 		.priv = PRIV_ACTION(RAW_DECAP,
7078 				    sizeof(struct action_raw_decap_data)),
7079 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7080 		.call = parse_vc_action_mplsogre_decap,
7081 	},
7082 	[ACTION_MPLSOUDP_ENCAP] = {
7083 		.name = "mplsoudp_encap",
7084 		.help = "mplsoudp encapsulation, uses configuration set by"
7085 			" \"set mplsoudp_encap\"",
7086 		.priv = PRIV_ACTION(RAW_ENCAP,
7087 				    sizeof(struct action_raw_encap_data)),
7088 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7089 		.call = parse_vc_action_mplsoudp_encap,
7090 	},
7091 	[ACTION_MPLSOUDP_DECAP] = {
7092 		.name = "mplsoudp_decap",
7093 		.help = "mplsoudp decapsulation, uses configuration set by"
7094 			" \"set mplsoudp_decap\"",
7095 		.priv = PRIV_ACTION(RAW_DECAP,
7096 				    sizeof(struct action_raw_decap_data)),
7097 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7098 		.call = parse_vc_action_mplsoudp_decap,
7099 	},
7100 	[ACTION_SET_IPV4_SRC] = {
7101 		.name = "set_ipv4_src",
7102 		.help = "Set a new IPv4 source address in the outermost"
7103 			" IPv4 header",
7104 		.priv = PRIV_ACTION(SET_IPV4_SRC,
7105 			sizeof(struct rte_flow_action_set_ipv4)),
7106 		.next = NEXT(action_set_ipv4_src),
7107 		.call = parse_vc,
7108 	},
7109 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
7110 		.name = "ipv4_addr",
7111 		.help = "new IPv4 source address to set",
7112 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7113 		.args = ARGS(ARGS_ENTRY_HTON
7114 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7115 		.call = parse_vc_conf,
7116 	},
7117 	[ACTION_SET_IPV4_DST] = {
7118 		.name = "set_ipv4_dst",
7119 		.help = "Set a new IPv4 destination address in the outermost"
7120 			" IPv4 header",
7121 		.priv = PRIV_ACTION(SET_IPV4_DST,
7122 			sizeof(struct rte_flow_action_set_ipv4)),
7123 		.next = NEXT(action_set_ipv4_dst),
7124 		.call = parse_vc,
7125 	},
7126 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
7127 		.name = "ipv4_addr",
7128 		.help = "new IPv4 destination address to set",
7129 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
7130 		.args = ARGS(ARGS_ENTRY_HTON
7131 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
7132 		.call = parse_vc_conf,
7133 	},
7134 	[ACTION_SET_IPV6_SRC] = {
7135 		.name = "set_ipv6_src",
7136 		.help = "Set a new IPv6 source address in the outermost"
7137 			" IPv6 header",
7138 		.priv = PRIV_ACTION(SET_IPV6_SRC,
7139 			sizeof(struct rte_flow_action_set_ipv6)),
7140 		.next = NEXT(action_set_ipv6_src),
7141 		.call = parse_vc,
7142 	},
7143 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
7144 		.name = "ipv6_addr",
7145 		.help = "new IPv6 source address to set",
7146 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7147 		.args = ARGS(ARGS_ENTRY_HTON
7148 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7149 		.call = parse_vc_conf,
7150 	},
7151 	[ACTION_SET_IPV6_DST] = {
7152 		.name = "set_ipv6_dst",
7153 		.help = "Set a new IPv6 destination address in the outermost"
7154 			" IPv6 header",
7155 		.priv = PRIV_ACTION(SET_IPV6_DST,
7156 			sizeof(struct rte_flow_action_set_ipv6)),
7157 		.next = NEXT(action_set_ipv6_dst),
7158 		.call = parse_vc,
7159 	},
7160 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
7161 		.name = "ipv6_addr",
7162 		.help = "new IPv6 destination address to set",
7163 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
7164 		.args = ARGS(ARGS_ENTRY_HTON
7165 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
7166 		.call = parse_vc_conf,
7167 	},
7168 	[ACTION_SET_TP_SRC] = {
7169 		.name = "set_tp_src",
7170 		.help = "set a new source port number in the outermost"
7171 			" TCP/UDP header",
7172 		.priv = PRIV_ACTION(SET_TP_SRC,
7173 			sizeof(struct rte_flow_action_set_tp)),
7174 		.next = NEXT(action_set_tp_src),
7175 		.call = parse_vc,
7176 	},
7177 	[ACTION_SET_TP_SRC_TP_SRC] = {
7178 		.name = "port",
7179 		.help = "new source port number to set",
7180 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
7181 		.args = ARGS(ARGS_ENTRY_HTON
7182 			     (struct rte_flow_action_set_tp, port)),
7183 		.call = parse_vc_conf,
7184 	},
7185 	[ACTION_SET_TP_DST] = {
7186 		.name = "set_tp_dst",
7187 		.help = "set a new destination port number in the outermost"
7188 			" TCP/UDP header",
7189 		.priv = PRIV_ACTION(SET_TP_DST,
7190 			sizeof(struct rte_flow_action_set_tp)),
7191 		.next = NEXT(action_set_tp_dst),
7192 		.call = parse_vc,
7193 	},
7194 	[ACTION_SET_TP_DST_TP_DST] = {
7195 		.name = "port",
7196 		.help = "new destination port number to set",
7197 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
7198 		.args = ARGS(ARGS_ENTRY_HTON
7199 			     (struct rte_flow_action_set_tp, port)),
7200 		.call = parse_vc_conf,
7201 	},
7202 	[ACTION_MAC_SWAP] = {
7203 		.name = "mac_swap",
7204 		.help = "Swap the source and destination MAC addresses"
7205 			" in the outermost Ethernet header",
7206 		.priv = PRIV_ACTION(MAC_SWAP, 0),
7207 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7208 		.call = parse_vc,
7209 	},
7210 	[ACTION_DEC_TTL] = {
7211 		.name = "dec_ttl",
7212 		.help = "decrease network TTL if available",
7213 		.priv = PRIV_ACTION(DEC_TTL, 0),
7214 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7215 		.call = parse_vc,
7216 	},
7217 	[ACTION_SET_TTL] = {
7218 		.name = "set_ttl",
7219 		.help = "set ttl value",
7220 		.priv = PRIV_ACTION(SET_TTL,
7221 			sizeof(struct rte_flow_action_set_ttl)),
7222 		.next = NEXT(action_set_ttl),
7223 		.call = parse_vc,
7224 	},
7225 	[ACTION_SET_TTL_TTL] = {
7226 		.name = "ttl_value",
7227 		.help = "new ttl value to set",
7228 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
7229 		.args = ARGS(ARGS_ENTRY_HTON
7230 			     (struct rte_flow_action_set_ttl, ttl_value)),
7231 		.call = parse_vc_conf,
7232 	},
7233 	[ACTION_SET_MAC_SRC] = {
7234 		.name = "set_mac_src",
7235 		.help = "set source mac address",
7236 		.priv = PRIV_ACTION(SET_MAC_SRC,
7237 			sizeof(struct rte_flow_action_set_mac)),
7238 		.next = NEXT(action_set_mac_src),
7239 		.call = parse_vc,
7240 	},
7241 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
7242 		.name = "mac_addr",
7243 		.help = "new source mac address",
7244 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
7245 		.args = ARGS(ARGS_ENTRY_HTON
7246 			     (struct rte_flow_action_set_mac, mac_addr)),
7247 		.call = parse_vc_conf,
7248 	},
7249 	[ACTION_SET_MAC_DST] = {
7250 		.name = "set_mac_dst",
7251 		.help = "set destination mac address",
7252 		.priv = PRIV_ACTION(SET_MAC_DST,
7253 			sizeof(struct rte_flow_action_set_mac)),
7254 		.next = NEXT(action_set_mac_dst),
7255 		.call = parse_vc,
7256 	},
7257 	[ACTION_SET_MAC_DST_MAC_DST] = {
7258 		.name = "mac_addr",
7259 		.help = "new destination mac address to set",
7260 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
7261 		.args = ARGS(ARGS_ENTRY_HTON
7262 			     (struct rte_flow_action_set_mac, mac_addr)),
7263 		.call = parse_vc_conf,
7264 	},
7265 	[ACTION_INC_TCP_SEQ] = {
7266 		.name = "inc_tcp_seq",
7267 		.help = "increase TCP sequence number",
7268 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
7269 		.next = NEXT(action_inc_tcp_seq),
7270 		.call = parse_vc,
7271 	},
7272 	[ACTION_INC_TCP_SEQ_VALUE] = {
7273 		.name = "value",
7274 		.help = "the value to increase TCP sequence number by",
7275 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7276 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7277 		.call = parse_vc_conf,
7278 	},
7279 	[ACTION_DEC_TCP_SEQ] = {
7280 		.name = "dec_tcp_seq",
7281 		.help = "decrease TCP sequence number",
7282 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
7283 		.next = NEXT(action_dec_tcp_seq),
7284 		.call = parse_vc,
7285 	},
7286 	[ACTION_DEC_TCP_SEQ_VALUE] = {
7287 		.name = "value",
7288 		.help = "the value to decrease TCP sequence number by",
7289 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
7290 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7291 		.call = parse_vc_conf,
7292 	},
7293 	[ACTION_INC_TCP_ACK] = {
7294 		.name = "inc_tcp_ack",
7295 		.help = "increase TCP acknowledgment number",
7296 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
7297 		.next = NEXT(action_inc_tcp_ack),
7298 		.call = parse_vc,
7299 	},
7300 	[ACTION_INC_TCP_ACK_VALUE] = {
7301 		.name = "value",
7302 		.help = "the value to increase TCP acknowledgment number by",
7303 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7304 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7305 		.call = parse_vc_conf,
7306 	},
7307 	[ACTION_DEC_TCP_ACK] = {
7308 		.name = "dec_tcp_ack",
7309 		.help = "decrease TCP acknowledgment number",
7310 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
7311 		.next = NEXT(action_dec_tcp_ack),
7312 		.call = parse_vc,
7313 	},
7314 	[ACTION_DEC_TCP_ACK_VALUE] = {
7315 		.name = "value",
7316 		.help = "the value to decrease TCP acknowledgment number by",
7317 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
7318 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
7319 		.call = parse_vc_conf,
7320 	},
7321 	[ACTION_RAW_ENCAP] = {
7322 		.name = "raw_encap",
7323 		.help = "encapsulation data, defined by set raw_encap",
7324 		.priv = PRIV_ACTION(RAW_ENCAP,
7325 			sizeof(struct action_raw_encap_data)),
7326 		.next = NEXT(action_raw_encap),
7327 		.call = parse_vc_action_raw_encap,
7328 	},
7329 	[ACTION_RAW_ENCAP_SIZE] = {
7330 		.name = "size",
7331 		.help = "raw encap size",
7332 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7333 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7334 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)),
7335 		.call = parse_vc_conf,
7336 	},
7337 	[ACTION_RAW_ENCAP_INDEX] = {
7338 		.name = "index",
7339 		.help = "the index of raw_encap_confs",
7340 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
7341 	},
7342 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
7343 		.name = "{index}",
7344 		.type = "UNSIGNED",
7345 		.help = "unsigned integer value",
7346 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7347 		.call = parse_vc_action_raw_encap_index,
7348 		.comp = comp_set_raw_index,
7349 	},
7350 	[ACTION_RAW_DECAP] = {
7351 		.name = "raw_decap",
7352 		.help = "decapsulation data, defined by set raw_encap",
7353 		.priv = PRIV_ACTION(RAW_DECAP,
7354 			sizeof(struct action_raw_decap_data)),
7355 		.next = NEXT(action_raw_decap),
7356 		.call = parse_vc_action_raw_decap,
7357 	},
7358 	[ACTION_RAW_DECAP_INDEX] = {
7359 		.name = "index",
7360 		.help = "the index of raw_encap_confs",
7361 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
7362 	},
7363 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
7364 		.name = "{index}",
7365 		.type = "UNSIGNED",
7366 		.help = "unsigned integer value",
7367 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7368 		.call = parse_vc_action_raw_decap_index,
7369 		.comp = comp_set_raw_index,
7370 	},
7371 	[ACTION_MODIFY_FIELD] = {
7372 		.name = "modify_field",
7373 		.help = "modify destination field with data from source field",
7374 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
7375 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
7376 		.call = parse_vc,
7377 	},
7378 	[ACTION_MODIFY_FIELD_OP] = {
7379 		.name = "op",
7380 		.help = "operation type",
7381 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
7382 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
7383 		.call = parse_vc_conf,
7384 	},
7385 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
7386 		.name = "{operation}",
7387 		.help = "operation type value",
7388 		.call = parse_vc_modify_field_op,
7389 		.comp = comp_set_modify_field_op,
7390 	},
7391 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
7392 		.name = "dst_type",
7393 		.help = "destination field type",
7394 		.next = NEXT(action_modify_field_dst,
7395 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
7396 		.call = parse_vc_conf,
7397 	},
7398 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
7399 		.name = "{dst_type}",
7400 		.help = "destination field type value",
7401 		.call = parse_vc_modify_field_id,
7402 		.comp = comp_set_modify_field_id,
7403 	},
7404 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
7405 		.name = "dst_level",
7406 		.help = "destination field level",
7407 		.next = NEXT(action_modify_field_dst,
7408 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
7409 		.call = parse_vc_conf,
7410 	},
7411 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
7412 		.name = "{dst_level}",
7413 		.help = "destination field level value",
7414 		.call = parse_vc_modify_field_level,
7415 		.comp = comp_none,
7416 	},
7417 	[ACTION_MODIFY_FIELD_DST_TAG_INDEX] = {
7418 		.name = "dst_tag_index",
7419 		.help = "destination field tag array",
7420 		.next = NEXT(action_modify_field_dst,
7421 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7422 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7423 					dst.tag_index)),
7424 		.call = parse_vc_conf,
7425 	},
7426 	[ACTION_MODIFY_FIELD_DST_TYPE_ID] = {
7427 		.name = "dst_type_id",
7428 		.help = "destination field type ID",
7429 		.next = NEXT(action_modify_field_dst,
7430 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7431 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7432 					dst.type)),
7433 		.call = parse_vc_conf,
7434 	},
7435 	[ACTION_MODIFY_FIELD_DST_CLASS_ID] = {
7436 		.name = "dst_class",
7437 		.help = "destination field class ID",
7438 		.next = NEXT(action_modify_field_dst,
7439 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7440 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7441 					     dst.class_id)),
7442 		.call = parse_vc_conf,
7443 	},
7444 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
7445 		.name = "dst_offset",
7446 		.help = "destination field bit offset",
7447 		.next = NEXT(action_modify_field_dst,
7448 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7449 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7450 					dst.offset)),
7451 		.call = parse_vc_conf,
7452 	},
7453 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
7454 		.name = "src_type",
7455 		.help = "source field type",
7456 		.next = NEXT(action_modify_field_src,
7457 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
7458 		.call = parse_vc_conf,
7459 	},
7460 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
7461 		.name = "{src_type}",
7462 		.help = "source field type value",
7463 		.call = parse_vc_modify_field_id,
7464 		.comp = comp_set_modify_field_id,
7465 	},
7466 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
7467 		.name = "src_level",
7468 		.help = "source field level",
7469 		.next = NEXT(action_modify_field_src,
7470 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
7471 		.call = parse_vc_conf,
7472 	},
7473 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
7474 		.name = "{src_level}",
7475 		.help = "source field level value",
7476 		.call = parse_vc_modify_field_level,
7477 		.comp = comp_none,
7478 	},
7479 	[ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = {
7480 		.name = "src_tag_index",
7481 		.help = "source field tag array",
7482 		.next = NEXT(action_modify_field_src,
7483 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7484 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7485 					src.tag_index)),
7486 		.call = parse_vc_conf,
7487 	},
7488 	[ACTION_MODIFY_FIELD_SRC_TYPE_ID] = {
7489 		.name = "src_type_id",
7490 		.help = "source field type ID",
7491 		.next = NEXT(action_modify_field_src,
7492 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7493 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7494 					src.type)),
7495 		.call = parse_vc_conf,
7496 	},
7497 	[ACTION_MODIFY_FIELD_SRC_CLASS_ID] = {
7498 		.name = "src_class",
7499 		.help = "source field class ID",
7500 		.next = NEXT(action_modify_field_src,
7501 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7502 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field,
7503 					     src.class_id)),
7504 		.call = parse_vc_conf,
7505 	},
7506 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
7507 		.name = "src_offset",
7508 		.help = "source field bit offset",
7509 		.next = NEXT(action_modify_field_src,
7510 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7511 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7512 					src.offset)),
7513 		.call = parse_vc_conf,
7514 	},
7515 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
7516 		.name = "src_value",
7517 		.help = "source immediate value",
7518 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7519 			     NEXT_ENTRY(COMMON_HEX)),
7520 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
7521 			     ARGS_ENTRY_ARB(0, 0),
7522 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
7523 					src.value)),
7524 		.call = parse_vc_conf,
7525 	},
7526 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
7527 		.name = "src_ptr",
7528 		.help = "pointer to source immediate value",
7529 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
7530 			     NEXT_ENTRY(COMMON_HEX)),
7531 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7532 					src.pvalue),
7533 			     ARGS_ENTRY_ARB(0, 0),
7534 			     ARGS_ENTRY_ARB
7535 				(sizeof(struct rte_flow_action_modify_field),
7536 				 FLOW_FIELD_PATTERN_SIZE)),
7537 		.call = parse_vc_conf,
7538 	},
7539 	[ACTION_MODIFY_FIELD_WIDTH] = {
7540 		.name = "width",
7541 		.help = "number of bits to copy",
7542 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
7543 			NEXT_ENTRY(COMMON_UNSIGNED)),
7544 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
7545 					width)),
7546 		.call = parse_vc_conf,
7547 	},
7548 	[ACTION_SEND_TO_KERNEL] = {
7549 		.name = "send_to_kernel",
7550 		.help = "send packets to kernel",
7551 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
7552 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7553 		.call = parse_vc,
7554 	},
7555 	[ACTION_IPV6_EXT_REMOVE] = {
7556 		.name = "ipv6_ext_remove",
7557 		.help = "IPv6 extension type, defined by set ipv6_ext_remove",
7558 		.priv = PRIV_ACTION(IPV6_EXT_REMOVE,
7559 			sizeof(struct action_ipv6_ext_remove_data)),
7560 		.next = NEXT(action_ipv6_ext_remove),
7561 		.call = parse_vc_action_ipv6_ext_remove,
7562 	},
7563 	[ACTION_IPV6_EXT_REMOVE_INDEX] = {
7564 		.name = "index",
7565 		.help = "the index of ipv6_ext_remove",
7566 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)),
7567 	},
7568 	[ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = {
7569 		.name = "{index}",
7570 		.type = "UNSIGNED",
7571 		.help = "unsigned integer value",
7572 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7573 		.call = parse_vc_action_ipv6_ext_remove_index,
7574 		.comp = comp_set_ipv6_ext_index,
7575 	},
7576 	[ACTION_IPV6_EXT_PUSH] = {
7577 		.name = "ipv6_ext_push",
7578 		.help = "IPv6 extension data, defined by set ipv6_ext_push",
7579 		.priv = PRIV_ACTION(IPV6_EXT_PUSH,
7580 			sizeof(struct action_ipv6_ext_push_data)),
7581 		.next = NEXT(action_ipv6_ext_push),
7582 		.call = parse_vc_action_ipv6_ext_push,
7583 	},
7584 	[ACTION_IPV6_EXT_PUSH_INDEX] = {
7585 		.name = "index",
7586 		.help = "the index of ipv6_ext_push",
7587 		.next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)),
7588 	},
7589 	[ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = {
7590 		.name = "{index}",
7591 		.type = "UNSIGNED",
7592 		.help = "unsigned integer value",
7593 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7594 		.call = parse_vc_action_ipv6_ext_push_index,
7595 		.comp = comp_set_ipv6_ext_index,
7596 	},
7597 	[ACTION_NAT64] = {
7598 		.name = "nat64",
7599 		.help = "NAT64 IP headers translation",
7600 		.priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)),
7601 		.next = NEXT(action_nat64),
7602 		.call = parse_vc,
7603 	},
7604 	[ACTION_NAT64_MODE] = {
7605 		.name = "type",
7606 		.help = "NAT64 translation type",
7607 		.next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)),
7608 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)),
7609 		.call = parse_vc_conf,
7610 	},
7611 	[ACTION_JUMP_TO_TABLE_INDEX] = {
7612 		.name = "jump_to_table_index",
7613 		.help = "Jump to table index",
7614 		.priv = PRIV_ACTION(JUMP_TO_TABLE_INDEX,
7615 				    sizeof(struct rte_flow_action_jump_to_table_index)),
7616 		.next = NEXT(action_jump_to_table_index),
7617 		.call = parse_vc,
7618 	},
7619 	[ACTION_JUMP_TO_TABLE_INDEX_TABLE] = {
7620 		.name = "table",
7621 		.help = "table to redirect traffic to",
7622 		.next = NEXT(action_jump_to_table_index, NEXT_ENTRY(COMMON_UNSIGNED)),
7623 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump_to_table_index, table)),
7624 		.call = parse_vc_conf,
7625 	},
7626 	[ACTION_JUMP_TO_TABLE_INDEX_INDEX] = {
7627 		.name = "index",
7628 		.help = "rule index to redirect traffic to",
7629 		.next = NEXT(action_jump_to_table_index, NEXT_ENTRY(COMMON_UNSIGNED)),
7630 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump_to_table_index, index)),
7631 		.call = parse_vc_conf,
7632 	},
7633 
7634 	/* Top level command. */
7635 	[SET] = {
7636 		.name = "set",
7637 		.help = "set raw encap/decap/sample data",
7638 		.type = "set raw_encap|raw_decap <index> <pattern>"
7639 				" or set sample_actions <index> <action>",
7640 		.next = NEXT(NEXT_ENTRY
7641 			     (SET_RAW_ENCAP,
7642 			      SET_RAW_DECAP,
7643 			      SET_SAMPLE_ACTIONS,
7644 			      SET_IPV6_EXT_REMOVE,
7645 			      SET_IPV6_EXT_PUSH)),
7646 		.call = parse_set_init,
7647 	},
7648 	/* Sub-level commands. */
7649 	[SET_RAW_ENCAP] = {
7650 		.name = "raw_encap",
7651 		.help = "set raw encap data",
7652 		.next = NEXT(next_set_raw),
7653 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7654 				(offsetof(struct buffer, port),
7655 				 sizeof(((struct buffer *)0)->port),
7656 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7657 		.call = parse_set_raw_encap_decap,
7658 	},
7659 	[SET_RAW_DECAP] = {
7660 		.name = "raw_decap",
7661 		.help = "set raw decap data",
7662 		.next = NEXT(next_set_raw),
7663 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7664 				(offsetof(struct buffer, port),
7665 				 sizeof(((struct buffer *)0)->port),
7666 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
7667 		.call = parse_set_raw_encap_decap,
7668 	},
7669 	[SET_RAW_INDEX] = {
7670 		.name = "{index}",
7671 		.type = "COMMON_UNSIGNED",
7672 		.help = "index of raw_encap/raw_decap data",
7673 		.next = NEXT(next_item),
7674 		.call = parse_port,
7675 	},
7676 	[SET_SAMPLE_INDEX] = {
7677 		.name = "{index}",
7678 		.type = "UNSIGNED",
7679 		.help = "index of sample actions",
7680 		.next = NEXT(next_action_sample),
7681 		.call = parse_port,
7682 	},
7683 	[SET_SAMPLE_ACTIONS] = {
7684 		.name = "sample_actions",
7685 		.help = "set sample actions list",
7686 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
7687 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7688 				(offsetof(struct buffer, port),
7689 				 sizeof(((struct buffer *)0)->port),
7690 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
7691 		.call = parse_set_sample_action,
7692 	},
7693 	[SET_IPV6_EXT_PUSH] = {
7694 		.name = "ipv6_ext_push",
7695 		.help = "set IPv6 extension header",
7696 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7697 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7698 				(offsetof(struct buffer, port),
7699 				 sizeof(((struct buffer *)0)->port),
7700 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7701 		.call = parse_set_ipv6_ext_action,
7702 	},
7703 	[SET_IPV6_EXT_REMOVE] = {
7704 		.name = "ipv6_ext_remove",
7705 		.help = "set IPv6 extension header",
7706 		.next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)),
7707 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
7708 				(offsetof(struct buffer, port),
7709 				 sizeof(((struct buffer *)0)->port),
7710 				 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)),
7711 		.call = parse_set_ipv6_ext_action,
7712 	},
7713 	[SET_IPV6_EXT_INDEX] = {
7714 		.name = "{index}",
7715 		.type = "UNSIGNED",
7716 		.help = "index of ipv6 extension push/remove actions",
7717 		.next = NEXT(item_ipv6_push_ext),
7718 		.call = parse_port,
7719 	},
7720 	[ITEM_IPV6_PUSH_REMOVE_EXT] = {
7721 		.name = "ipv6_ext",
7722 		.help = "set IPv6 extension header",
7723 		.priv = PRIV_ITEM(IPV6_EXT,
7724 				  sizeof(struct rte_flow_item_ipv6_ext)),
7725 		.next = NEXT(item_ipv6_push_ext_type),
7726 		.call = parse_vc,
7727 	},
7728 	[ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = {
7729 		.name = "type",
7730 		.help = "set IPv6 extension type",
7731 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
7732 					     next_hdr)),
7733 		.next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED),
7734 			     item_param),
7735 	},
7736 	[ACTION_SET_TAG] = {
7737 		.name = "set_tag",
7738 		.help = "set tag",
7739 		.priv = PRIV_ACTION(SET_TAG,
7740 			sizeof(struct rte_flow_action_set_tag)),
7741 		.next = NEXT(action_set_tag),
7742 		.call = parse_vc,
7743 	},
7744 	[ACTION_SET_TAG_INDEX] = {
7745 		.name = "index",
7746 		.help = "index of tag array",
7747 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7748 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
7749 		.call = parse_vc_conf,
7750 	},
7751 	[ACTION_SET_TAG_DATA] = {
7752 		.name = "data",
7753 		.help = "tag value",
7754 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7755 		.args = ARGS(ARGS_ENTRY
7756 			     (struct rte_flow_action_set_tag, data)),
7757 		.call = parse_vc_conf,
7758 	},
7759 	[ACTION_SET_TAG_MASK] = {
7760 		.name = "mask",
7761 		.help = "mask for tag value",
7762 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
7763 		.args = ARGS(ARGS_ENTRY
7764 			     (struct rte_flow_action_set_tag, mask)),
7765 		.call = parse_vc_conf,
7766 	},
7767 	[ACTION_SET_META] = {
7768 		.name = "set_meta",
7769 		.help = "set metadata",
7770 		.priv = PRIV_ACTION(SET_META,
7771 			sizeof(struct rte_flow_action_set_meta)),
7772 		.next = NEXT(action_set_meta),
7773 		.call = parse_vc_action_set_meta,
7774 	},
7775 	[ACTION_SET_META_DATA] = {
7776 		.name = "data",
7777 		.help = "metadata value",
7778 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7779 		.args = ARGS(ARGS_ENTRY
7780 			     (struct rte_flow_action_set_meta, data)),
7781 		.call = parse_vc_conf,
7782 	},
7783 	[ACTION_SET_META_MASK] = {
7784 		.name = "mask",
7785 		.help = "mask for metadata value",
7786 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
7787 		.args = ARGS(ARGS_ENTRY
7788 			     (struct rte_flow_action_set_meta, mask)),
7789 		.call = parse_vc_conf,
7790 	},
7791 	[ACTION_SET_IPV4_DSCP] = {
7792 		.name = "set_ipv4_dscp",
7793 		.help = "set DSCP value",
7794 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
7795 			sizeof(struct rte_flow_action_set_dscp)),
7796 		.next = NEXT(action_set_ipv4_dscp),
7797 		.call = parse_vc,
7798 	},
7799 	[ACTION_SET_IPV4_DSCP_VALUE] = {
7800 		.name = "dscp_value",
7801 		.help = "new IPv4 DSCP value to set",
7802 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7803 		.args = ARGS(ARGS_ENTRY
7804 			     (struct rte_flow_action_set_dscp, dscp)),
7805 		.call = parse_vc_conf,
7806 	},
7807 	[ACTION_SET_IPV6_DSCP] = {
7808 		.name = "set_ipv6_dscp",
7809 		.help = "set DSCP value",
7810 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
7811 			sizeof(struct rte_flow_action_set_dscp)),
7812 		.next = NEXT(action_set_ipv6_dscp),
7813 		.call = parse_vc,
7814 	},
7815 	[ACTION_SET_IPV6_DSCP_VALUE] = {
7816 		.name = "dscp_value",
7817 		.help = "new IPv6 DSCP value to set",
7818 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
7819 		.args = ARGS(ARGS_ENTRY
7820 			     (struct rte_flow_action_set_dscp, dscp)),
7821 		.call = parse_vc_conf,
7822 	},
7823 	[ACTION_AGE] = {
7824 		.name = "age",
7825 		.help = "set a specific metadata header",
7826 		.next = NEXT(action_age),
7827 		.priv = PRIV_ACTION(AGE,
7828 			sizeof(struct rte_flow_action_age)),
7829 		.call = parse_vc,
7830 	},
7831 	[ACTION_AGE_TIMEOUT] = {
7832 		.name = "timeout",
7833 		.help = "flow age timeout value",
7834 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
7835 					   timeout, 24)),
7836 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
7837 		.call = parse_vc_conf,
7838 	},
7839 	[ACTION_AGE_UPDATE] = {
7840 		.name = "age_update",
7841 		.help = "update aging parameter",
7842 		.next = NEXT(action_age_update),
7843 		.priv = PRIV_ACTION(AGE,
7844 				    sizeof(struct rte_flow_update_age)),
7845 		.call = parse_vc,
7846 	},
7847 	[ACTION_AGE_UPDATE_TIMEOUT] = {
7848 		.name = "timeout",
7849 		.help = "age timeout update value",
7850 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7851 					   timeout, 24)),
7852 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7853 		.call = parse_vc_conf_timeout,
7854 	},
7855 	[ACTION_AGE_UPDATE_TOUCH] = {
7856 		.name = "touch",
7857 		.help = "this flow is touched",
7858 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
7859 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
7860 					   touch, 1)),
7861 		.call = parse_vc_conf,
7862 	},
7863 	[ACTION_SAMPLE] = {
7864 		.name = "sample",
7865 		.help = "set a sample action",
7866 		.next = NEXT(action_sample),
7867 		.priv = PRIV_ACTION(SAMPLE,
7868 			sizeof(struct action_sample_data)),
7869 		.call = parse_vc_action_sample,
7870 	},
7871 	[ACTION_SAMPLE_RATIO] = {
7872 		.name = "ratio",
7873 		.help = "flow sample ratio value",
7874 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
7875 		.args = ARGS(ARGS_ENTRY_ARB
7876 			     (offsetof(struct action_sample_data, conf) +
7877 			      offsetof(struct rte_flow_action_sample, ratio),
7878 			      sizeof(((struct rte_flow_action_sample *)0)->
7879 				     ratio))),
7880 	},
7881 	[ACTION_SAMPLE_INDEX] = {
7882 		.name = "index",
7883 		.help = "the index of sample actions list",
7884 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
7885 	},
7886 	[ACTION_SAMPLE_INDEX_VALUE] = {
7887 		.name = "{index}",
7888 		.type = "COMMON_UNSIGNED",
7889 		.help = "unsigned integer value",
7890 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7891 		.call = parse_vc_action_sample_index,
7892 		.comp = comp_set_sample_index,
7893 	},
7894 	[ACTION_CONNTRACK] = {
7895 		.name = "conntrack",
7896 		.help = "create a conntrack object",
7897 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
7898 		.priv = PRIV_ACTION(CONNTRACK,
7899 				    sizeof(struct rte_flow_action_conntrack)),
7900 		.call = parse_vc,
7901 	},
7902 	[ACTION_CONNTRACK_UPDATE] = {
7903 		.name = "conntrack_update",
7904 		.help = "update a conntrack object",
7905 		.next = NEXT(action_update_conntrack),
7906 		.priv = PRIV_ACTION(CONNTRACK,
7907 				    sizeof(struct rte_flow_modify_conntrack)),
7908 		.call = parse_vc,
7909 	},
7910 	[ACTION_CONNTRACK_UPDATE_DIR] = {
7911 		.name = "dir",
7912 		.help = "update a conntrack object direction",
7913 		.next = NEXT(action_update_conntrack),
7914 		.call = parse_vc_action_conntrack_update,
7915 	},
7916 	[ACTION_CONNTRACK_UPDATE_CTX] = {
7917 		.name = "ctx",
7918 		.help = "update a conntrack object context",
7919 		.next = NEXT(action_update_conntrack),
7920 		.call = parse_vc_action_conntrack_update,
7921 	},
7922 	[ACTION_PORT_REPRESENTOR] = {
7923 		.name = "port_representor",
7924 		.help = "at embedded switch level, send matching traffic to the given ethdev",
7925 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
7926 				    sizeof(struct rte_flow_action_ethdev)),
7927 		.next = NEXT(action_port_representor),
7928 		.call = parse_vc,
7929 	},
7930 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
7931 		.name = "port_id",
7932 		.help = "ethdev port ID",
7933 		.next = NEXT(action_port_representor,
7934 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7935 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7936 					port_id)),
7937 		.call = parse_vc_conf,
7938 	},
7939 	[ACTION_REPRESENTED_PORT] = {
7940 		.name = "represented_port",
7941 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
7942 		.priv = PRIV_ACTION(REPRESENTED_PORT,
7943 				sizeof(struct rte_flow_action_ethdev)),
7944 		.next = NEXT(action_represented_port),
7945 		.call = parse_vc,
7946 	},
7947 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
7948 		.name = "ethdev_port_id",
7949 		.help = "ethdev port ID",
7950 		.next = NEXT(action_represented_port,
7951 			     NEXT_ENTRY(COMMON_UNSIGNED)),
7952 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
7953 					port_id)),
7954 		.call = parse_vc_conf,
7955 	},
7956 	/* Indirect action destroy arguments. */
7957 	[INDIRECT_ACTION_DESTROY_ID] = {
7958 		.name = "action_id",
7959 		.help = "specify a indirect action id to destroy",
7960 		.next = NEXT(next_ia_destroy_attr,
7961 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7962 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
7963 					    args.ia_destroy.action_id)),
7964 		.call = parse_ia_destroy,
7965 	},
7966 	/* Indirect action create arguments. */
7967 	[INDIRECT_ACTION_CREATE_ID] = {
7968 		.name = "action_id",
7969 		.help = "specify a indirect action id to create",
7970 		.next = NEXT(next_ia_create_attr,
7971 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
7972 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
7973 	},
7974 	[ACTION_INDIRECT] = {
7975 		.name = "indirect",
7976 		.help = "apply indirect action by id",
7977 		.priv = PRIV_ACTION(INDIRECT, 0),
7978 		.next = NEXT(next_ia),
7979 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7980 		.call = parse_vc,
7981 	},
7982 	[ACTION_INDIRECT_LIST] = {
7983 		.name = "indirect_list",
7984 		.help = "apply indirect list action by id",
7985 		.priv = PRIV_ACTION(INDIRECT_LIST,
7986 				    sizeof(struct
7987 					   rte_flow_action_indirect_list)),
7988 		.next = NEXT(next_ial),
7989 		.call = parse_vc,
7990 	},
7991 	[ACTION_INDIRECT_LIST_HANDLE] = {
7992 		.name = "handle",
7993 		.help = "indirect list handle",
7994 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
7995 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
7996 	},
7997 	[ACTION_INDIRECT_LIST_CONF] = {
7998 		.name = "conf",
7999 		.help = "indirect list configuration",
8000 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
8001 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
8002 	},
8003 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
8004 		.type = "UNSIGNED",
8005 		.help = "unsigned integer value",
8006 		.call = parse_indlst_id2ptr,
8007 		.comp = comp_none,
8008 	},
8009 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
8010 		.type = "UNSIGNED",
8011 		.help = "unsigned integer value",
8012 		.call = parse_indlst_id2ptr,
8013 		.comp = comp_none,
8014 	},
8015 	[ACTION_SHARED_INDIRECT] = {
8016 		.name = "shared_indirect",
8017 		.help = "apply indirect action by id and port",
8018 		.priv = PRIV_ACTION(INDIRECT, 0),
8019 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
8020 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
8021 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
8022 		.call = parse_vc,
8023 	},
8024 	[INDIRECT_ACTION_PORT] = {
8025 		.name = "{indirect_action_port}",
8026 		.type = "INDIRECT_ACTION_PORT",
8027 		.help = "indirect action port",
8028 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
8029 		.call = parse_ia_port,
8030 		.comp = comp_none,
8031 	},
8032 	[INDIRECT_ACTION_ID2PTR] = {
8033 		.name = "{action_id}",
8034 		.type = "INDIRECT_ACTION_ID",
8035 		.help = "indirect action id",
8036 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
8037 		.call = parse_ia_id2ptr,
8038 		.comp = comp_none,
8039 	},
8040 	[INDIRECT_ACTION_INGRESS] = {
8041 		.name = "ingress",
8042 		.help = "affect rule to ingress",
8043 		.next = NEXT(next_ia_create_attr),
8044 		.call = parse_ia,
8045 	},
8046 	[INDIRECT_ACTION_EGRESS] = {
8047 		.name = "egress",
8048 		.help = "affect rule to egress",
8049 		.next = NEXT(next_ia_create_attr),
8050 		.call = parse_ia,
8051 	},
8052 	[INDIRECT_ACTION_TRANSFER] = {
8053 		.name = "transfer",
8054 		.help = "affect rule to transfer",
8055 		.next = NEXT(next_ia_create_attr),
8056 		.call = parse_ia,
8057 	},
8058 	[INDIRECT_ACTION_SPEC] = {
8059 		.name = "action",
8060 		.help = "specify action to create indirect handle",
8061 		.next = NEXT(next_action),
8062 	},
8063 	[INDIRECT_ACTION_LIST] = {
8064 		.name = "list",
8065 		.help = "specify actions for indirect handle list",
8066 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8067 		.call = parse_ia,
8068 	},
8069 	[INDIRECT_ACTION_FLOW_CONF] = {
8070 		.name = "flow_conf",
8071 		.help = "specify actions configuration for indirect handle list",
8072 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
8073 		.call = parse_ia,
8074 	},
8075 	[ACTION_POL_G] = {
8076 		.name = "g_actions",
8077 		.help = "submit a list of associated actions for green",
8078 		.next = NEXT(next_action),
8079 		.call = parse_mp,
8080 	},
8081 	[ACTION_POL_Y] = {
8082 		.name = "y_actions",
8083 		.help = "submit a list of associated actions for yellow",
8084 		.next = NEXT(next_action),
8085 	},
8086 	[ACTION_POL_R] = {
8087 		.name = "r_actions",
8088 		.help = "submit a list of associated actions for red",
8089 		.next = NEXT(next_action),
8090 	},
8091 	[ACTION_QUOTA_CREATE] = {
8092 		.name = "quota_create",
8093 		.help = "create quota action",
8094 		.priv = PRIV_ACTION(QUOTA,
8095 				    sizeof(struct rte_flow_action_quota)),
8096 		.next = NEXT(action_quota_create),
8097 		.call = parse_vc
8098 	},
8099 	[ACTION_QUOTA_CREATE_LIMIT] = {
8100 		.name = "limit",
8101 		.help = "quota limit",
8102 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
8103 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
8104 		.call = parse_vc_conf
8105 	},
8106 	[ACTION_QUOTA_CREATE_MODE] = {
8107 		.name = "mode",
8108 		.help = "quota mode",
8109 		.next = NEXT(action_quota_create,
8110 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
8111 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
8112 		.call = parse_vc_conf
8113 	},
8114 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
8115 		.name = "mode_name",
8116 		.help = "quota mode name",
8117 		.call = parse_quota_mode_name,
8118 		.comp = comp_quota_mode_name
8119 	},
8120 	[ACTION_QUOTA_QU] = {
8121 		.name = "quota_update",
8122 		.help = "update quota action",
8123 		.priv = PRIV_ACTION(QUOTA,
8124 				    sizeof(struct rte_flow_update_quota)),
8125 		.next = NEXT(action_quota_update),
8126 		.call = parse_vc
8127 	},
8128 	[ACTION_QUOTA_QU_LIMIT] = {
8129 		.name = "limit",
8130 		.help = "quota limit",
8131 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
8132 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
8133 		.call = parse_vc_conf
8134 	},
8135 	[ACTION_QUOTA_QU_UPDATE_OP] = {
8136 		.name = "update_op",
8137 		.help = "query update op SET|ADD",
8138 		.next = NEXT(action_quota_update,
8139 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
8140 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
8141 		.call = parse_vc_conf
8142 	},
8143 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
8144 		.name = "update_op_name",
8145 		.help = "quota update op name",
8146 		.call = parse_quota_update_name,
8147 		.comp = comp_quota_update_name
8148 	},
8149 
8150 	/* Top-level command. */
8151 	[ADD] = {
8152 		.name = "add",
8153 		.type = "port meter policy {port_id} {arg}",
8154 		.help = "add port meter policy",
8155 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
8156 		.call = parse_init,
8157 	},
8158 	/* Sub-level commands. */
8159 	[ITEM_POL_PORT] = {
8160 		.name = "port",
8161 		.help = "add port meter policy",
8162 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
8163 	},
8164 	[ITEM_POL_METER] = {
8165 		.name = "meter",
8166 		.help = "add port meter policy",
8167 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
8168 	},
8169 	[ITEM_POL_POLICY] = {
8170 		.name = "policy",
8171 		.help = "add port meter policy",
8172 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
8173 				NEXT_ENTRY(ACTION_POL_Y),
8174 				NEXT_ENTRY(ACTION_POL_G),
8175 				NEXT_ENTRY(COMMON_POLICY_ID),
8176 				NEXT_ENTRY(COMMON_PORT_ID)),
8177 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
8178 				ARGS_ENTRY(struct buffer, port)),
8179 		.call = parse_mp,
8180 	},
8181 	[ITEM_AGGR_AFFINITY] = {
8182 		.name = "aggr_affinity",
8183 		.help = "match on the aggregated port receiving the packets",
8184 		.priv = PRIV_ITEM(AGGR_AFFINITY,
8185 				  sizeof(struct rte_flow_item_aggr_affinity)),
8186 		.next = NEXT(item_aggr_affinity),
8187 		.call = parse_vc,
8188 	},
8189 	[ITEM_AGGR_AFFINITY_VALUE] = {
8190 		.name = "affinity",
8191 		.help = "aggregated affinity value",
8192 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
8193 			     item_param),
8194 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
8195 					affinity)),
8196 	},
8197 	[ITEM_TX_QUEUE] = {
8198 		.name = "tx_queue",
8199 		.help = "match on the tx queue of send packet",
8200 		.priv = PRIV_ITEM(TX_QUEUE,
8201 				  sizeof(struct rte_flow_item_tx_queue)),
8202 		.next = NEXT(item_tx_queue),
8203 		.call = parse_vc,
8204 	},
8205 	[ITEM_TX_QUEUE_VALUE] = {
8206 		.name = "tx_queue_value",
8207 		.help = "tx queue value",
8208 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
8209 			     item_param),
8210 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
8211 					tx_queue)),
8212 	},
8213 };
8214 
8215 /** Remove and return last entry from argument stack. */
8216 static const struct arg *
8217 pop_args(struct context *ctx)
8218 {
8219 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
8220 }
8221 
8222 /** Add entry on top of the argument stack. */
8223 static int
8224 push_args(struct context *ctx, const struct arg *arg)
8225 {
8226 	if (ctx->args_num == CTX_STACK_SIZE)
8227 		return -1;
8228 	ctx->args[ctx->args_num++] = arg;
8229 	return 0;
8230 }
8231 
8232 /** Spread value into buffer according to bit-mask. */
8233 static size_t
8234 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
8235 {
8236 	uint32_t i = arg->size;
8237 	uint32_t end = 0;
8238 	int sub = 1;
8239 	int add = 0;
8240 	size_t len = 0;
8241 
8242 	if (!arg->mask)
8243 		return 0;
8244 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8245 	if (!arg->hton) {
8246 		i = 0;
8247 		end = arg->size;
8248 		sub = 0;
8249 		add = 1;
8250 	}
8251 #endif
8252 	while (i != end) {
8253 		unsigned int shift = 0;
8254 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
8255 
8256 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
8257 			if (!(arg->mask[i] & (1 << shift)))
8258 				continue;
8259 			++len;
8260 			if (!dst)
8261 				continue;
8262 			*buf &= ~(1 << shift);
8263 			*buf |= (val & 1) << shift;
8264 			val >>= 1;
8265 		}
8266 		i += add;
8267 	}
8268 	return len;
8269 }
8270 
8271 /** Compare a string with a partial one of a given length. */
8272 static int
8273 strcmp_partial(const char *full, const char *partial, size_t partial_len)
8274 {
8275 	int r = strncmp(full, partial, partial_len);
8276 
8277 	if (r)
8278 		return r;
8279 	if (strlen(full) <= partial_len)
8280 		return 0;
8281 	return full[partial_len];
8282 }
8283 
8284 /**
8285  * Parse a prefix length and generate a bit-mask.
8286  *
8287  * Last argument (ctx->args) is retrieved to determine mask size, storage
8288  * location and whether the result must use network byte ordering.
8289  */
8290 static int
8291 parse_prefix(struct context *ctx, const struct token *token,
8292 	     const char *str, unsigned int len,
8293 	     void *buf, unsigned int size)
8294 {
8295 	const struct arg *arg = pop_args(ctx);
8296 	static const uint8_t conv[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0,
8297 					0xf8, 0xfc, 0xfe, 0xff };
8298 	char *end;
8299 	uintmax_t u;
8300 	unsigned int bytes;
8301 	unsigned int extra;
8302 
8303 	(void)token;
8304 	/* Argument is expected. */
8305 	if (!arg)
8306 		return -1;
8307 	errno = 0;
8308 	u = strtoumax(str, &end, 0);
8309 	if (errno || (size_t)(end - str) != len)
8310 		goto error;
8311 	if (arg->mask) {
8312 		uintmax_t v = 0;
8313 
8314 		extra = arg_entry_bf_fill(NULL, 0, arg);
8315 		if (u > extra)
8316 			goto error;
8317 		if (!ctx->object)
8318 			return len;
8319 		extra -= u;
8320 		while (u--)
8321 			(v <<= 1, v |= 1);
8322 		v <<= extra;
8323 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
8324 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
8325 			goto error;
8326 		return len;
8327 	}
8328 	bytes = u / 8;
8329 	extra = u % 8;
8330 	size = arg->size;
8331 	if (bytes > size || bytes + !!extra > size)
8332 		goto error;
8333 	if (!ctx->object)
8334 		return len;
8335 	buf = (uint8_t *)ctx->object + arg->offset;
8336 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
8337 	if (!arg->hton) {
8338 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
8339 		memset(buf, 0x00, size - bytes);
8340 		if (extra)
8341 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
8342 	} else
8343 #endif
8344 	{
8345 		memset(buf, 0xff, bytes);
8346 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
8347 		if (extra)
8348 			((uint8_t *)buf)[bytes] = conv[extra];
8349 	}
8350 	if (ctx->objmask)
8351 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
8352 	return len;
8353 error:
8354 	push_args(ctx, arg);
8355 	return -1;
8356 }
8357 
8358 /** Default parsing function for token name matching. */
8359 static int
8360 parse_default(struct context *ctx, const struct token *token,
8361 	      const char *str, unsigned int len,
8362 	      void *buf, unsigned int size)
8363 {
8364 	(void)ctx;
8365 	(void)buf;
8366 	(void)size;
8367 	if (strcmp_partial(token->name, str, len))
8368 		return -1;
8369 	return len;
8370 }
8371 
8372 /** Parse flow command, initialize output buffer for subsequent tokens. */
8373 static int
8374 parse_init(struct context *ctx, const struct token *token,
8375 	   const char *str, unsigned int len,
8376 	   void *buf, unsigned int size)
8377 {
8378 	struct buffer *out = buf;
8379 
8380 	/* Token name must match. */
8381 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8382 		return -1;
8383 	/* Nothing else to do if there is no buffer. */
8384 	if (!out)
8385 		return len;
8386 	/* Make sure buffer is large enough. */
8387 	if (size < sizeof(*out))
8388 		return -1;
8389 	/* Initialize buffer. */
8390 	memset(out, 0x00, sizeof(*out));
8391 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
8392 	ctx->objdata = 0;
8393 	ctx->object = out;
8394 	ctx->objmask = NULL;
8395 	return len;
8396 }
8397 
8398 /** Parse tokens for indirect action commands. */
8399 static int
8400 parse_ia(struct context *ctx, const struct token *token,
8401 	 const char *str, unsigned int len,
8402 	 void *buf, unsigned int size)
8403 {
8404 	struct buffer *out = buf;
8405 
8406 	/* Token name must match. */
8407 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8408 		return -1;
8409 	/* Nothing else to do if there is no buffer. */
8410 	if (!out)
8411 		return len;
8412 	if (!out->command) {
8413 		if (ctx->curr != INDIRECT_ACTION)
8414 			return -1;
8415 		if (sizeof(*out) > size)
8416 			return -1;
8417 		out->command = ctx->curr;
8418 		ctx->objdata = 0;
8419 		ctx->object = out;
8420 		ctx->objmask = NULL;
8421 		out->args.vc.data = (uint8_t *)out + size;
8422 		return len;
8423 	}
8424 	switch (ctx->curr) {
8425 	case INDIRECT_ACTION_CREATE:
8426 	case INDIRECT_ACTION_UPDATE:
8427 	case INDIRECT_ACTION_QUERY_UPDATE:
8428 		out->args.vc.actions =
8429 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8430 					       sizeof(double));
8431 		out->args.vc.attr.group = UINT32_MAX;
8432 		/* fallthrough */
8433 	case INDIRECT_ACTION_QUERY:
8434 		out->command = ctx->curr;
8435 		ctx->objdata = 0;
8436 		ctx->object = out;
8437 		ctx->objmask = NULL;
8438 		return len;
8439 	case INDIRECT_ACTION_EGRESS:
8440 		out->args.vc.attr.egress = 1;
8441 		return len;
8442 	case INDIRECT_ACTION_INGRESS:
8443 		out->args.vc.attr.ingress = 1;
8444 		return len;
8445 	case INDIRECT_ACTION_TRANSFER:
8446 		out->args.vc.attr.transfer = 1;
8447 		return len;
8448 	case INDIRECT_ACTION_QU_MODE:
8449 		return len;
8450 	case INDIRECT_ACTION_LIST:
8451 		out->command = INDIRECT_ACTION_LIST_CREATE;
8452 		return len;
8453 	case INDIRECT_ACTION_FLOW_CONF:
8454 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
8455 		return len;
8456 	default:
8457 		return -1;
8458 	}
8459 }
8460 
8461 
8462 /** Parse tokens for indirect action destroy command. */
8463 static int
8464 parse_ia_destroy(struct context *ctx, const struct token *token,
8465 		 const char *str, unsigned int len,
8466 		 void *buf, unsigned int size)
8467 {
8468 	struct buffer *out = buf;
8469 	uint32_t *action_id;
8470 
8471 	/* Token name must match. */
8472 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8473 		return -1;
8474 	/* Nothing else to do if there is no buffer. */
8475 	if (!out)
8476 		return len;
8477 	if (!out->command || out->command == INDIRECT_ACTION) {
8478 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
8479 			return -1;
8480 		if (sizeof(*out) > size)
8481 			return -1;
8482 		out->command = ctx->curr;
8483 		ctx->objdata = 0;
8484 		ctx->object = out;
8485 		ctx->objmask = NULL;
8486 		out->args.ia_destroy.action_id =
8487 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8488 					       sizeof(double));
8489 		return len;
8490 	}
8491 	action_id = out->args.ia_destroy.action_id
8492 		    + out->args.ia_destroy.action_id_n++;
8493 	if ((uint8_t *)action_id > (uint8_t *)out + size)
8494 		return -1;
8495 	ctx->objdata = 0;
8496 	ctx->object = action_id;
8497 	ctx->objmask = NULL;
8498 	return len;
8499 }
8500 
8501 /** Parse tokens for indirect action commands. */
8502 static int
8503 parse_qia(struct context *ctx, const struct token *token,
8504 	  const char *str, unsigned int len,
8505 	  void *buf, unsigned int size)
8506 {
8507 	struct buffer *out = buf;
8508 
8509 	/* Token name must match. */
8510 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8511 		return -1;
8512 	/* Nothing else to do if there is no buffer. */
8513 	if (!out)
8514 		return len;
8515 	if (!out->command) {
8516 		if (ctx->curr != QUEUE)
8517 			return -1;
8518 		if (sizeof(*out) > size)
8519 			return -1;
8520 		out->args.vc.data = (uint8_t *)out + size;
8521 		return len;
8522 	}
8523 	switch (ctx->curr) {
8524 	case QUEUE_INDIRECT_ACTION:
8525 		return len;
8526 	case QUEUE_INDIRECT_ACTION_CREATE:
8527 	case QUEUE_INDIRECT_ACTION_UPDATE:
8528 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
8529 		out->args.vc.actions =
8530 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8531 					       sizeof(double));
8532 		out->args.vc.attr.group = UINT32_MAX;
8533 		/* fallthrough */
8534 	case QUEUE_INDIRECT_ACTION_QUERY:
8535 		out->command = ctx->curr;
8536 		ctx->objdata = 0;
8537 		ctx->object = out;
8538 		ctx->objmask = NULL;
8539 		return len;
8540 	case QUEUE_INDIRECT_ACTION_EGRESS:
8541 		out->args.vc.attr.egress = 1;
8542 		return len;
8543 	case QUEUE_INDIRECT_ACTION_INGRESS:
8544 		out->args.vc.attr.ingress = 1;
8545 		return len;
8546 	case QUEUE_INDIRECT_ACTION_TRANSFER:
8547 		out->args.vc.attr.transfer = 1;
8548 		return len;
8549 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
8550 		return len;
8551 	case QUEUE_INDIRECT_ACTION_QU_MODE:
8552 		return len;
8553 	case QUEUE_INDIRECT_ACTION_LIST:
8554 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
8555 		return len;
8556 	default:
8557 		return -1;
8558 	}
8559 }
8560 
8561 /** Parse tokens for indirect action destroy command. */
8562 static int
8563 parse_qia_destroy(struct context *ctx, const struct token *token,
8564 		  const char *str, unsigned int len,
8565 		  void *buf, unsigned int size)
8566 {
8567 	struct buffer *out = buf;
8568 	uint32_t *action_id;
8569 
8570 	/* Token name must match. */
8571 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8572 		return -1;
8573 	/* Nothing else to do if there is no buffer. */
8574 	if (!out)
8575 		return len;
8576 	if (!out->command || out->command == QUEUE) {
8577 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
8578 			return -1;
8579 		if (sizeof(*out) > size)
8580 			return -1;
8581 		out->command = ctx->curr;
8582 		ctx->objdata = 0;
8583 		ctx->object = out;
8584 		ctx->objmask = NULL;
8585 		out->args.ia_destroy.action_id =
8586 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8587 					       sizeof(double));
8588 		return len;
8589 	}
8590 	switch (ctx->curr) {
8591 	case QUEUE_INDIRECT_ACTION:
8592 		out->command = ctx->curr;
8593 		ctx->objdata = 0;
8594 		ctx->object = out;
8595 		ctx->objmask = NULL;
8596 		return len;
8597 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
8598 		action_id = out->args.ia_destroy.action_id
8599 				+ out->args.ia_destroy.action_id_n++;
8600 		if ((uint8_t *)action_id > (uint8_t *)out + size)
8601 			return -1;
8602 		ctx->objdata = 0;
8603 		ctx->object = action_id;
8604 		ctx->objmask = NULL;
8605 		return len;
8606 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
8607 		return len;
8608 	default:
8609 		return -1;
8610 	}
8611 }
8612 
8613 /** Parse tokens for meter policy action commands. */
8614 static int
8615 parse_mp(struct context *ctx, const struct token *token,
8616 	const char *str, unsigned int len,
8617 	void *buf, unsigned int size)
8618 {
8619 	struct buffer *out = buf;
8620 
8621 	/* Token name must match. */
8622 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8623 		return -1;
8624 	/* Nothing else to do if there is no buffer. */
8625 	if (!out)
8626 		return len;
8627 	if (!out->command) {
8628 		if (ctx->curr != ITEM_POL_POLICY)
8629 			return -1;
8630 		if (sizeof(*out) > size)
8631 			return -1;
8632 		out->command = ctx->curr;
8633 		ctx->objdata = 0;
8634 		ctx->object = out;
8635 		ctx->objmask = NULL;
8636 		out->args.vc.data = (uint8_t *)out + size;
8637 		return len;
8638 	}
8639 	switch (ctx->curr) {
8640 	case ACTION_POL_G:
8641 		out->args.vc.actions =
8642 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8643 					sizeof(double));
8644 		out->command = ctx->curr;
8645 		ctx->objdata = 0;
8646 		ctx->object = out;
8647 		ctx->objmask = NULL;
8648 		return len;
8649 	default:
8650 		return -1;
8651 	}
8652 }
8653 
8654 /** Parse tokens for validate/create commands. */
8655 static int
8656 parse_vc(struct context *ctx, const struct token *token,
8657 	 const char *str, unsigned int len,
8658 	 void *buf, unsigned int size)
8659 {
8660 	struct buffer *out = buf;
8661 	uint8_t *data;
8662 	uint32_t data_size;
8663 
8664 	/* Token name must match. */
8665 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8666 		return -1;
8667 	/* Nothing else to do if there is no buffer. */
8668 	if (!out)
8669 		return len;
8670 	if (!out->command) {
8671 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
8672 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
8673 		    ctx->curr != ACTIONS_TEMPLATE_CREATE &&
8674 		    ctx->curr != UPDATE)
8675 			return -1;
8676 		if (ctx->curr == UPDATE)
8677 			out->args.vc.pattern =
8678 				(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8679 						       sizeof(double));
8680 		if (sizeof(*out) > size)
8681 			return -1;
8682 		out->command = ctx->curr;
8683 		ctx->objdata = 0;
8684 		ctx->object = out;
8685 		ctx->objmask = NULL;
8686 		out->args.vc.data = (uint8_t *)out + size;
8687 		return len;
8688 	}
8689 	ctx->objdata = 0;
8690 	switch (ctx->curr) {
8691 	default:
8692 		ctx->object = &out->args.vc.attr;
8693 		break;
8694 	case VC_TUNNEL_SET:
8695 	case VC_TUNNEL_MATCH:
8696 		ctx->object = &out->args.vc.tunnel_ops;
8697 		break;
8698 	case VC_USER_ID:
8699 		ctx->object = out;
8700 		break;
8701 	}
8702 	ctx->objmask = NULL;
8703 	switch (ctx->curr) {
8704 	case VC_GROUP:
8705 	case VC_PRIORITY:
8706 	case VC_USER_ID:
8707 		return len;
8708 	case VC_TUNNEL_SET:
8709 		out->args.vc.tunnel_ops.enabled = 1;
8710 		out->args.vc.tunnel_ops.actions = 1;
8711 		return len;
8712 	case VC_TUNNEL_MATCH:
8713 		out->args.vc.tunnel_ops.enabled = 1;
8714 		out->args.vc.tunnel_ops.items = 1;
8715 		return len;
8716 	case VC_INGRESS:
8717 		out->args.vc.attr.ingress = 1;
8718 		return len;
8719 	case VC_EGRESS:
8720 		out->args.vc.attr.egress = 1;
8721 		return len;
8722 	case VC_TRANSFER:
8723 		out->args.vc.attr.transfer = 1;
8724 		return len;
8725 	case ITEM_PATTERN:
8726 		out->args.vc.pattern =
8727 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8728 					       sizeof(double));
8729 		ctx->object = out->args.vc.pattern;
8730 		ctx->objmask = NULL;
8731 		return len;
8732 	case ITEM_END:
8733 		if ((out->command == VALIDATE || out->command == CREATE) &&
8734 		    ctx->last)
8735 			return -1;
8736 		if (out->command == PATTERN_TEMPLATE_CREATE &&
8737 		    !ctx->last)
8738 			return -1;
8739 		break;
8740 	case ACTIONS:
8741 		out->args.vc.actions = out->args.vc.pattern ?
8742 			(void *)RTE_ALIGN_CEIL((uintptr_t)
8743 					       (out->args.vc.pattern +
8744 						out->args.vc.pattern_n),
8745 					       sizeof(double)) :
8746 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
8747 					       sizeof(double));
8748 		ctx->object = out->args.vc.actions;
8749 		ctx->objmask = NULL;
8750 		return len;
8751 	case VC_IS_USER_ID:
8752 		out->args.vc.user_id = true;
8753 		return len;
8754 	default:
8755 		if (!token->priv)
8756 			return -1;
8757 		break;
8758 	}
8759 	if (!out->args.vc.actions) {
8760 		const struct parse_item_priv *priv = token->priv;
8761 		struct rte_flow_item *item =
8762 			out->args.vc.pattern + out->args.vc.pattern_n;
8763 
8764 		data_size = priv->size * 3; /* spec, last, mask */
8765 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8766 					       (out->args.vc.data - data_size),
8767 					       sizeof(double));
8768 		if ((uint8_t *)item + sizeof(*item) > data)
8769 			return -1;
8770 		*item = (struct rte_flow_item){
8771 			.type = priv->type,
8772 		};
8773 		++out->args.vc.pattern_n;
8774 		ctx->object = item;
8775 		ctx->objmask = NULL;
8776 	} else {
8777 		const struct parse_action_priv *priv = token->priv;
8778 		struct rte_flow_action *action =
8779 			out->args.vc.actions + out->args.vc.actions_n;
8780 
8781 		data_size = priv->size; /* configuration */
8782 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
8783 					       (out->args.vc.data - data_size),
8784 					       sizeof(double));
8785 		if ((uint8_t *)action + sizeof(*action) > data)
8786 			return -1;
8787 		*action = (struct rte_flow_action){
8788 			.type = priv->type,
8789 			.conf = data_size ? data : NULL,
8790 		};
8791 		++out->args.vc.actions_n;
8792 		ctx->object = action;
8793 		ctx->objmask = NULL;
8794 	}
8795 	memset(data, 0, data_size);
8796 	out->args.vc.data = data;
8797 	ctx->objdata = data_size;
8798 	return len;
8799 }
8800 
8801 /** Parse pattern item parameter type. */
8802 static int
8803 parse_vc_spec(struct context *ctx, const struct token *token,
8804 	      const char *str, unsigned int len,
8805 	      void *buf, unsigned int size)
8806 {
8807 	struct buffer *out = buf;
8808 	struct rte_flow_item *item;
8809 	uint32_t data_size;
8810 	int index;
8811 	int objmask = 0;
8812 
8813 	(void)size;
8814 	/* Token name must match. */
8815 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8816 		return -1;
8817 	/* Parse parameter types. */
8818 	switch (ctx->curr) {
8819 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
8820 
8821 	case ITEM_PARAM_IS:
8822 		index = 0;
8823 		objmask = 1;
8824 		break;
8825 	case ITEM_PARAM_SPEC:
8826 		index = 0;
8827 		break;
8828 	case ITEM_PARAM_LAST:
8829 		index = 1;
8830 		break;
8831 	case ITEM_PARAM_PREFIX:
8832 		/* Modify next token to expect a prefix. */
8833 		if (ctx->next_num < 2)
8834 			return -1;
8835 		ctx->next[ctx->next_num - 2] = prefix;
8836 		/* Fall through. */
8837 	case ITEM_PARAM_MASK:
8838 		index = 2;
8839 		break;
8840 	default:
8841 		return -1;
8842 	}
8843 	/* Nothing else to do if there is no buffer. */
8844 	if (!out)
8845 		return len;
8846 	if (!out->args.vc.pattern_n)
8847 		return -1;
8848 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8849 	data_size = ctx->objdata / 3; /* spec, last, mask */
8850 	/* Point to selected object. */
8851 	ctx->object = out->args.vc.data + (data_size * index);
8852 	if (objmask) {
8853 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
8854 		item->mask = ctx->objmask;
8855 	} else
8856 		ctx->objmask = NULL;
8857 	/* Update relevant item pointer. */
8858 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
8859 		ctx->object;
8860 	return len;
8861 }
8862 
8863 /** Parse action configuration field. */
8864 static int
8865 parse_vc_conf(struct context *ctx, const struct token *token,
8866 	      const char *str, unsigned int len,
8867 	      void *buf, unsigned int size)
8868 {
8869 	struct buffer *out = buf;
8870 
8871 	(void)size;
8872 	/* Token name must match. */
8873 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8874 		return -1;
8875 	/* Nothing else to do if there is no buffer. */
8876 	if (!out)
8877 		return len;
8878 	/* Point to selected object. */
8879 	ctx->object = out->args.vc.data;
8880 	ctx->objmask = NULL;
8881 	return len;
8882 }
8883 
8884 /** Parse action configuration field. */
8885 static int
8886 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
8887 		      const char *str, unsigned int len,
8888 		      void *buf, unsigned int size)
8889 {
8890 	struct buffer *out = buf;
8891 	struct rte_flow_update_age *update;
8892 
8893 	(void)size;
8894 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
8895 		return -1;
8896 	/* Token name must match. */
8897 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8898 		return -1;
8899 	/* Nothing else to do if there is no buffer. */
8900 	if (!out)
8901 		return len;
8902 	/* Point to selected object. */
8903 	ctx->object = out->args.vc.data;
8904 	ctx->objmask = NULL;
8905 	/* Update the timeout is valid. */
8906 	update = (struct rte_flow_update_age *)out->args.vc.data;
8907 	update->timeout_valid = 1;
8908 	return len;
8909 }
8910 
8911 /** Parse eCPRI common header type field. */
8912 static int
8913 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
8914 			 const char *str, unsigned int len,
8915 			 void *buf, unsigned int size)
8916 {
8917 	struct rte_flow_item_ecpri *ecpri;
8918 	struct rte_flow_item_ecpri *ecpri_mask;
8919 	struct rte_flow_item *item;
8920 	uint32_t data_size;
8921 	uint8_t msg_type;
8922 	struct buffer *out = buf;
8923 	const struct arg *arg;
8924 
8925 	(void)size;
8926 	/* Token name must match. */
8927 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8928 		return -1;
8929 	switch (ctx->curr) {
8930 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
8931 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
8932 		break;
8933 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
8934 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
8935 		break;
8936 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
8937 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
8938 		break;
8939 	default:
8940 		return -1;
8941 	}
8942 	if (!ctx->object)
8943 		return len;
8944 	arg = pop_args(ctx);
8945 	if (!arg)
8946 		return -1;
8947 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
8948 	ecpri->hdr.common.type = msg_type;
8949 	data_size = ctx->objdata / 3; /* spec, last, mask */
8950 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
8951 						    (data_size * 2));
8952 	ecpri_mask->hdr.common.type = 0xFF;
8953 	if (arg->hton) {
8954 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
8955 		ecpri_mask->hdr.common.u32 =
8956 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
8957 	}
8958 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
8959 	item->spec = ecpri;
8960 	item->mask = ecpri_mask;
8961 	return len;
8962 }
8963 
8964 /** Parse L2TPv2 common header type field. */
8965 static int
8966 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
8967 			 const char *str, unsigned int len,
8968 			 void *buf, unsigned int size)
8969 {
8970 	struct rte_flow_item_l2tpv2 *l2tpv2;
8971 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
8972 	struct rte_flow_item *item;
8973 	uint32_t data_size;
8974 	uint16_t msg_type = 0;
8975 	struct buffer *out = buf;
8976 	const struct arg *arg;
8977 
8978 	(void)size;
8979 	/* Token name must match. */
8980 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8981 		return -1;
8982 	switch (ctx->curr) {
8983 	case ITEM_L2TPV2_TYPE_DATA:
8984 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
8985 		break;
8986 	case ITEM_L2TPV2_TYPE_DATA_L:
8987 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
8988 		break;
8989 	case ITEM_L2TPV2_TYPE_DATA_S:
8990 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
8991 		break;
8992 	case ITEM_L2TPV2_TYPE_DATA_O:
8993 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
8994 		break;
8995 	case ITEM_L2TPV2_TYPE_DATA_L_S:
8996 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
8997 		break;
8998 	case ITEM_L2TPV2_TYPE_CTRL:
8999 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
9000 		break;
9001 	default:
9002 		return -1;
9003 	}
9004 	if (!ctx->object)
9005 		return len;
9006 	arg = pop_args(ctx);
9007 	if (!arg)
9008 		return -1;
9009 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
9010 	l2tpv2->hdr.common.flags_version |= msg_type;
9011 	data_size = ctx->objdata / 3; /* spec, last, mask */
9012 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
9013 						    (data_size * 2));
9014 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
9015 	if (arg->hton) {
9016 		l2tpv2->hdr.common.flags_version =
9017 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
9018 		l2tpv2_mask->hdr.common.flags_version =
9019 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
9020 	}
9021 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
9022 	item->spec = l2tpv2;
9023 	item->mask = l2tpv2_mask;
9024 	return len;
9025 }
9026 
9027 /** Parse operation for compare match item. */
9028 static int
9029 parse_vc_compare_op(struct context *ctx, const struct token *token,
9030 			 const char *str, unsigned int len, void *buf,
9031 			 unsigned int size)
9032 {
9033 	struct rte_flow_item_compare *compare_item;
9034 	unsigned int i;
9035 
9036 	(void)token;
9037 	(void)buf;
9038 	(void)size;
9039 	if (ctx->curr != ITEM_COMPARE_OP_VALUE)
9040 		return -1;
9041 	for (i = 0; compare_ops[i]; ++i)
9042 		if (!strcmp_partial(compare_ops[i], str, len))
9043 			break;
9044 	if (!compare_ops[i])
9045 		return -1;
9046 	if (!ctx->object)
9047 		return len;
9048 	compare_item = ctx->object;
9049 	compare_item->operation = (enum rte_flow_item_compare_op)i;
9050 	return len;
9051 }
9052 
9053 /** Parse id for compare match item. */
9054 static int
9055 parse_vc_compare_field_id(struct context *ctx, const struct token *token,
9056 			  const char *str, unsigned int len, void *buf,
9057 			  unsigned int size)
9058 {
9059 	struct rte_flow_item_compare *compare_item;
9060 	unsigned int i;
9061 
9062 	(void)token;
9063 	(void)buf;
9064 	(void)size;
9065 	if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE &&
9066 		ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE)
9067 		return -1;
9068 	for (i = 0; flow_field_ids[i]; ++i)
9069 		if (!strcmp_partial(flow_field_ids[i], str, len))
9070 			break;
9071 	if (!flow_field_ids[i])
9072 		return -1;
9073 	if (!ctx->object)
9074 		return len;
9075 	compare_item = ctx->object;
9076 	if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE)
9077 		compare_item->a.field = (enum rte_flow_field_id)i;
9078 	else
9079 		compare_item->b.field = (enum rte_flow_field_id)i;
9080 	return len;
9081 }
9082 
9083 /** Parse level for compare match item. */
9084 static int
9085 parse_vc_compare_field_level(struct context *ctx, const struct token *token,
9086 			     const char *str, unsigned int len, void *buf,
9087 			     unsigned int size)
9088 {
9089 	struct rte_flow_item_compare *compare_item;
9090 	struct flex_item *fp = NULL;
9091 	uint32_t val;
9092 	struct buffer *out = buf;
9093 	char *end;
9094 
9095 	(void)token;
9096 	(void)size;
9097 	if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9098 		ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE)
9099 		return -1;
9100 	if (!ctx->object)
9101 		return len;
9102 	compare_item = ctx->object;
9103 	errno = 0;
9104 	val = strtoumax(str, &end, 0);
9105 	if (errno || (size_t)(end - str) != len)
9106 		return -1;
9107 	/* No need to validate action template mask value */
9108 	if (out->args.vc.masks) {
9109 		if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE)
9110 			compare_item->a.level = val;
9111 		else
9112 			compare_item->b.level = val;
9113 		return len;
9114 	}
9115 	if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE &&
9116 		compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9117 		(ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE &&
9118 		compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9119 		if (val >= FLEX_MAX_PARSERS_NUM) {
9120 			printf("Bad flex item handle\n");
9121 			return -1;
9122 		}
9123 		fp = flex_items[ctx->port][val];
9124 		if (!fp) {
9125 			printf("Bad flex item handle\n");
9126 			return -1;
9127 		}
9128 	}
9129 	if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) {
9130 		if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM)
9131 			compare_item->a.level = val;
9132 		else
9133 			compare_item->a.flex_handle = fp->flex_handle;
9134 	} else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) {
9135 		if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM)
9136 			compare_item->b.level = val;
9137 		else
9138 			compare_item->b.flex_handle = fp->flex_handle;
9139 	}
9140 	return len;
9141 }
9142 
9143 /** Parse meter color action type. */
9144 static int
9145 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
9146 				const char *str, unsigned int len,
9147 				void *buf, unsigned int size)
9148 {
9149 	struct rte_flow_action *action_data;
9150 	struct rte_flow_action_meter_color *conf;
9151 	enum rte_color color;
9152 
9153 	(void)buf;
9154 	(void)size;
9155 	/* Token name must match. */
9156 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9157 		return -1;
9158 	switch (ctx->curr) {
9159 	case ACTION_METER_COLOR_GREEN:
9160 		color = RTE_COLOR_GREEN;
9161 	break;
9162 	case ACTION_METER_COLOR_YELLOW:
9163 		color = RTE_COLOR_YELLOW;
9164 	break;
9165 	case ACTION_METER_COLOR_RED:
9166 		color = RTE_COLOR_RED;
9167 	break;
9168 	default:
9169 		return -1;
9170 	}
9171 
9172 	if (!ctx->object)
9173 		return len;
9174 	action_data = ctx->object;
9175 	conf = (struct rte_flow_action_meter_color *)
9176 					(uintptr_t)(action_data->conf);
9177 	conf->color = color;
9178 	return len;
9179 }
9180 
9181 /** Parse RSS action. */
9182 static int
9183 parse_vc_action_rss(struct context *ctx, const struct token *token,
9184 		    const char *str, unsigned int len,
9185 		    void *buf, unsigned int size)
9186 {
9187 	struct buffer *out = buf;
9188 	struct rte_flow_action *action;
9189 	struct action_rss_data *action_rss_data;
9190 	unsigned int i;
9191 	int ret;
9192 
9193 	ret = parse_vc(ctx, token, str, len, buf, size);
9194 	if (ret < 0)
9195 		return ret;
9196 	/* Nothing else to do if there is no buffer. */
9197 	if (!out)
9198 		return ret;
9199 	if (!out->args.vc.actions_n)
9200 		return -1;
9201 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9202 	/* Point to selected object. */
9203 	ctx->object = out->args.vc.data;
9204 	ctx->objmask = NULL;
9205 	/* Set up default configuration. */
9206 	action_rss_data = ctx->object;
9207 	*action_rss_data = (struct action_rss_data){
9208 		.conf = (struct rte_flow_action_rss){
9209 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
9210 			.level = 0,
9211 			.types = rss_hf,
9212 			.key_len = 0,
9213 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
9214 			.key = NULL,
9215 			.queue = action_rss_data->queue,
9216 		},
9217 		.queue = { 0 },
9218 	};
9219 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
9220 		action_rss_data->queue[i] = i;
9221 	action->conf = &action_rss_data->conf;
9222 	return ret;
9223 }
9224 
9225 /**
9226  * Parse func field for RSS action.
9227  *
9228  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
9229  * ACTION_RSS_FUNC_* index that called this function.
9230  */
9231 static int
9232 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
9233 			 const char *str, unsigned int len,
9234 			 void *buf, unsigned int size)
9235 {
9236 	struct action_rss_data *action_rss_data;
9237 	enum rte_eth_hash_function func;
9238 
9239 	(void)buf;
9240 	(void)size;
9241 	/* Token name must match. */
9242 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9243 		return -1;
9244 	switch (ctx->curr) {
9245 	case ACTION_RSS_FUNC_DEFAULT:
9246 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
9247 		break;
9248 	case ACTION_RSS_FUNC_TOEPLITZ:
9249 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
9250 		break;
9251 	case ACTION_RSS_FUNC_SIMPLE_XOR:
9252 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
9253 		break;
9254 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
9255 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
9256 		break;
9257 	default:
9258 		return -1;
9259 	}
9260 	if (!ctx->object)
9261 		return len;
9262 	action_rss_data = ctx->object;
9263 	action_rss_data->conf.func = func;
9264 	return len;
9265 }
9266 
9267 /**
9268  * Parse type field for RSS action.
9269  *
9270  * Valid tokens are type field names and the "end" token.
9271  */
9272 static int
9273 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
9274 			  const char *str, unsigned int len,
9275 			  void *buf, unsigned int size)
9276 {
9277 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
9278 	struct action_rss_data *action_rss_data;
9279 	unsigned int i;
9280 
9281 	(void)token;
9282 	(void)buf;
9283 	(void)size;
9284 	if (ctx->curr != ACTION_RSS_TYPE)
9285 		return -1;
9286 	if (!(ctx->objdata >> 16) && ctx->object) {
9287 		action_rss_data = ctx->object;
9288 		action_rss_data->conf.types = 0;
9289 	}
9290 	if (!strcmp_partial("end", str, len)) {
9291 		ctx->objdata &= 0xffff;
9292 		return len;
9293 	}
9294 	for (i = 0; rss_type_table[i].str; ++i)
9295 		if (!strcmp_partial(rss_type_table[i].str, str, len))
9296 			break;
9297 	if (!rss_type_table[i].str)
9298 		return -1;
9299 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
9300 	/* Repeat token. */
9301 	if (ctx->next_num == RTE_DIM(ctx->next))
9302 		return -1;
9303 	ctx->next[ctx->next_num++] = next;
9304 	if (!ctx->object)
9305 		return len;
9306 	action_rss_data = ctx->object;
9307 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
9308 	return len;
9309 }
9310 
9311 /**
9312  * Parse queue field for RSS action.
9313  *
9314  * Valid tokens are queue indices and the "end" token.
9315  */
9316 static int
9317 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
9318 			  const char *str, unsigned int len,
9319 			  void *buf, unsigned int size)
9320 {
9321 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
9322 	struct action_rss_data *action_rss_data;
9323 	const struct arg *arg;
9324 	int ret;
9325 	int i;
9326 
9327 	(void)token;
9328 	(void)buf;
9329 	(void)size;
9330 	if (ctx->curr != ACTION_RSS_QUEUE)
9331 		return -1;
9332 	i = ctx->objdata >> 16;
9333 	if (!strcmp_partial("end", str, len)) {
9334 		ctx->objdata &= 0xffff;
9335 		goto end;
9336 	}
9337 	if (i >= ACTION_RSS_QUEUE_NUM)
9338 		return -1;
9339 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
9340 			     i * sizeof(action_rss_data->queue[i]),
9341 			     sizeof(action_rss_data->queue[i]));
9342 	if (push_args(ctx, arg))
9343 		return -1;
9344 	ret = parse_int(ctx, token, str, len, NULL, 0);
9345 	if (ret < 0) {
9346 		pop_args(ctx);
9347 		return -1;
9348 	}
9349 	++i;
9350 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
9351 	/* Repeat token. */
9352 	if (ctx->next_num == RTE_DIM(ctx->next))
9353 		return -1;
9354 	ctx->next[ctx->next_num++] = next;
9355 end:
9356 	if (!ctx->object)
9357 		return len;
9358 	action_rss_data = ctx->object;
9359 	action_rss_data->conf.queue_num = i;
9360 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
9361 	return len;
9362 }
9363 
9364 /** Setup VXLAN encap configuration. */
9365 static int
9366 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
9367 {
9368 	/* Set up default configuration. */
9369 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
9370 		.conf = (struct rte_flow_action_vxlan_encap){
9371 			.definition = action_vxlan_encap_data->items,
9372 		},
9373 		.items = {
9374 			{
9375 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9376 				.spec = &action_vxlan_encap_data->item_eth,
9377 				.mask = &rte_flow_item_eth_mask,
9378 			},
9379 			{
9380 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9381 				.spec = &action_vxlan_encap_data->item_vlan,
9382 				.mask = &rte_flow_item_vlan_mask,
9383 			},
9384 			{
9385 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9386 				.spec = &action_vxlan_encap_data->item_ipv4,
9387 				.mask = &rte_flow_item_ipv4_mask,
9388 			},
9389 			{
9390 				.type = RTE_FLOW_ITEM_TYPE_UDP,
9391 				.spec = &action_vxlan_encap_data->item_udp,
9392 				.mask = &rte_flow_item_udp_mask,
9393 			},
9394 			{
9395 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
9396 				.spec = &action_vxlan_encap_data->item_vxlan,
9397 				.mask = &rte_flow_item_vxlan_mask,
9398 			},
9399 			{
9400 				.type = RTE_FLOW_ITEM_TYPE_END,
9401 			},
9402 		},
9403 		.item_eth.hdr.ether_type = 0,
9404 		.item_vlan = {
9405 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
9406 			.hdr.eth_proto = 0,
9407 		},
9408 		.item_ipv4.hdr = {
9409 			.src_addr = vxlan_encap_conf.ipv4_src,
9410 			.dst_addr = vxlan_encap_conf.ipv4_dst,
9411 		},
9412 		.item_udp.hdr = {
9413 			.src_port = vxlan_encap_conf.udp_src,
9414 			.dst_port = vxlan_encap_conf.udp_dst,
9415 		},
9416 		.item_vxlan.hdr.flags = 0,
9417 	};
9418 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9419 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9420 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
9421 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9422 	if (!vxlan_encap_conf.select_ipv4) {
9423 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
9424 		       &vxlan_encap_conf.ipv6_src,
9425 		       sizeof(vxlan_encap_conf.ipv6_src));
9426 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
9427 		       &vxlan_encap_conf.ipv6_dst,
9428 		       sizeof(vxlan_encap_conf.ipv6_dst));
9429 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
9430 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9431 			.spec = &action_vxlan_encap_data->item_ipv6,
9432 			.mask = &rte_flow_item_ipv6_mask,
9433 		};
9434 	}
9435 	if (!vxlan_encap_conf.select_vlan)
9436 		action_vxlan_encap_data->items[1].type =
9437 			RTE_FLOW_ITEM_TYPE_VOID;
9438 	if (vxlan_encap_conf.select_tos_ttl) {
9439 		if (vxlan_encap_conf.select_ipv4) {
9440 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
9441 
9442 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
9443 			       sizeof(ipv4_mask_tos));
9444 			ipv4_mask_tos.hdr.type_of_service = 0xff;
9445 			ipv4_mask_tos.hdr.time_to_live = 0xff;
9446 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
9447 					vxlan_encap_conf.ip_tos;
9448 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
9449 					vxlan_encap_conf.ip_ttl;
9450 			action_vxlan_encap_data->items[2].mask =
9451 							&ipv4_mask_tos;
9452 		} else {
9453 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
9454 
9455 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
9456 			       sizeof(ipv6_mask_tos));
9457 			ipv6_mask_tos.hdr.vtc_flow |=
9458 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
9459 			ipv6_mask_tos.hdr.hop_limits = 0xff;
9460 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
9461 				rte_cpu_to_be_32
9462 					((uint32_t)vxlan_encap_conf.ip_tos <<
9463 					 RTE_IPV6_HDR_TC_SHIFT);
9464 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
9465 					vxlan_encap_conf.ip_ttl;
9466 			action_vxlan_encap_data->items[2].mask =
9467 							&ipv6_mask_tos;
9468 		}
9469 	}
9470 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
9471 	       RTE_DIM(vxlan_encap_conf.vni));
9472 	return 0;
9473 }
9474 
9475 /** Parse VXLAN encap action. */
9476 static int
9477 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
9478 			    const char *str, unsigned int len,
9479 			    void *buf, unsigned int size)
9480 {
9481 	struct buffer *out = buf;
9482 	struct rte_flow_action *action;
9483 	struct action_vxlan_encap_data *action_vxlan_encap_data;
9484 	int ret;
9485 
9486 	ret = parse_vc(ctx, token, str, len, buf, size);
9487 	if (ret < 0)
9488 		return ret;
9489 	/* Nothing else to do if there is no buffer. */
9490 	if (!out)
9491 		return ret;
9492 	if (!out->args.vc.actions_n)
9493 		return -1;
9494 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9495 	/* Point to selected object. */
9496 	ctx->object = out->args.vc.data;
9497 	ctx->objmask = NULL;
9498 	action_vxlan_encap_data = ctx->object;
9499 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
9500 	action->conf = &action_vxlan_encap_data->conf;
9501 	return ret;
9502 }
9503 
9504 /** Setup NVGRE encap configuration. */
9505 static int
9506 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
9507 {
9508 	/* Set up default configuration. */
9509 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
9510 		.conf = (struct rte_flow_action_nvgre_encap){
9511 			.definition = action_nvgre_encap_data->items,
9512 		},
9513 		.items = {
9514 			{
9515 				.type = RTE_FLOW_ITEM_TYPE_ETH,
9516 				.spec = &action_nvgre_encap_data->item_eth,
9517 				.mask = &rte_flow_item_eth_mask,
9518 			},
9519 			{
9520 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
9521 				.spec = &action_nvgre_encap_data->item_vlan,
9522 				.mask = &rte_flow_item_vlan_mask,
9523 			},
9524 			{
9525 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
9526 				.spec = &action_nvgre_encap_data->item_ipv4,
9527 				.mask = &rte_flow_item_ipv4_mask,
9528 			},
9529 			{
9530 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
9531 				.spec = &action_nvgre_encap_data->item_nvgre,
9532 				.mask = &rte_flow_item_nvgre_mask,
9533 			},
9534 			{
9535 				.type = RTE_FLOW_ITEM_TYPE_END,
9536 			},
9537 		},
9538 		.item_eth.hdr.ether_type = 0,
9539 		.item_vlan = {
9540 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
9541 			.hdr.eth_proto = 0,
9542 		},
9543 		.item_ipv4.hdr = {
9544 		       .src_addr = nvgre_encap_conf.ipv4_src,
9545 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
9546 		},
9547 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
9548 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
9549 		.item_nvgre.flow_id = 0,
9550 	};
9551 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
9552 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9553 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
9554 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9555 	if (!nvgre_encap_conf.select_ipv4) {
9556 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
9557 		       &nvgre_encap_conf.ipv6_src,
9558 		       sizeof(nvgre_encap_conf.ipv6_src));
9559 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
9560 		       &nvgre_encap_conf.ipv6_dst,
9561 		       sizeof(nvgre_encap_conf.ipv6_dst));
9562 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
9563 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
9564 			.spec = &action_nvgre_encap_data->item_ipv6,
9565 			.mask = &rte_flow_item_ipv6_mask,
9566 		};
9567 	}
9568 	if (!nvgre_encap_conf.select_vlan)
9569 		action_nvgre_encap_data->items[1].type =
9570 			RTE_FLOW_ITEM_TYPE_VOID;
9571 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
9572 	       RTE_DIM(nvgre_encap_conf.tni));
9573 	return 0;
9574 }
9575 
9576 /** Parse NVGRE encap action. */
9577 static int
9578 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
9579 			    const char *str, unsigned int len,
9580 			    void *buf, unsigned int size)
9581 {
9582 	struct buffer *out = buf;
9583 	struct rte_flow_action *action;
9584 	struct action_nvgre_encap_data *action_nvgre_encap_data;
9585 	int ret;
9586 
9587 	ret = parse_vc(ctx, token, str, len, buf, size);
9588 	if (ret < 0)
9589 		return ret;
9590 	/* Nothing else to do if there is no buffer. */
9591 	if (!out)
9592 		return ret;
9593 	if (!out->args.vc.actions_n)
9594 		return -1;
9595 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9596 	/* Point to selected object. */
9597 	ctx->object = out->args.vc.data;
9598 	ctx->objmask = NULL;
9599 	action_nvgre_encap_data = ctx->object;
9600 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
9601 	action->conf = &action_nvgre_encap_data->conf;
9602 	return ret;
9603 }
9604 
9605 /** Parse l2 encap action. */
9606 static int
9607 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
9608 			 const char *str, unsigned int len,
9609 			 void *buf, unsigned int size)
9610 {
9611 	struct buffer *out = buf;
9612 	struct rte_flow_action *action;
9613 	struct action_raw_encap_data *action_encap_data;
9614 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9615 	struct rte_flow_item_vlan vlan = {
9616 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9617 		.hdr.eth_proto = 0,
9618 	};
9619 	uint8_t *header;
9620 	int ret;
9621 
9622 	ret = parse_vc(ctx, token, str, len, buf, size);
9623 	if (ret < 0)
9624 		return ret;
9625 	/* Nothing else to do if there is no buffer. */
9626 	if (!out)
9627 		return ret;
9628 	if (!out->args.vc.actions_n)
9629 		return -1;
9630 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9631 	/* Point to selected object. */
9632 	ctx->object = out->args.vc.data;
9633 	ctx->objmask = NULL;
9634 	/* Copy the headers to the buffer. */
9635 	action_encap_data = ctx->object;
9636 	*action_encap_data = (struct action_raw_encap_data) {
9637 		.conf = (struct rte_flow_action_raw_encap){
9638 			.data = action_encap_data->data,
9639 		},
9640 		.data = {},
9641 	};
9642 	header = action_encap_data->data;
9643 	if (l2_encap_conf.select_vlan)
9644 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9645 	else if (l2_encap_conf.select_ipv4)
9646 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9647 	else
9648 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9649 	memcpy(eth.hdr.dst_addr.addr_bytes,
9650 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9651 	memcpy(eth.hdr.src_addr.addr_bytes,
9652 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9653 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9654 	header += sizeof(struct rte_ether_hdr);
9655 	if (l2_encap_conf.select_vlan) {
9656 		if (l2_encap_conf.select_ipv4)
9657 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9658 		else
9659 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9660 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9661 		header += sizeof(struct rte_vlan_hdr);
9662 	}
9663 	action_encap_data->conf.size = header -
9664 		action_encap_data->data;
9665 	action->conf = &action_encap_data->conf;
9666 	return ret;
9667 }
9668 
9669 /** Parse l2 decap action. */
9670 static int
9671 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
9672 			 const char *str, unsigned int len,
9673 			 void *buf, unsigned int size)
9674 {
9675 	struct buffer *out = buf;
9676 	struct rte_flow_action *action;
9677 	struct action_raw_decap_data *action_decap_data;
9678 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9679 	struct rte_flow_item_vlan vlan = {
9680 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9681 		.hdr.eth_proto = 0,
9682 	};
9683 	uint8_t *header;
9684 	int ret;
9685 
9686 	ret = parse_vc(ctx, token, str, len, buf, size);
9687 	if (ret < 0)
9688 		return ret;
9689 	/* Nothing else to do if there is no buffer. */
9690 	if (!out)
9691 		return ret;
9692 	if (!out->args.vc.actions_n)
9693 		return -1;
9694 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9695 	/* Point to selected object. */
9696 	ctx->object = out->args.vc.data;
9697 	ctx->objmask = NULL;
9698 	/* Copy the headers to the buffer. */
9699 	action_decap_data = ctx->object;
9700 	*action_decap_data = (struct action_raw_decap_data) {
9701 		.conf = (struct rte_flow_action_raw_decap){
9702 			.data = action_decap_data->data,
9703 		},
9704 		.data = {},
9705 	};
9706 	header = action_decap_data->data;
9707 	if (l2_decap_conf.select_vlan)
9708 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9709 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9710 	header += sizeof(struct rte_ether_hdr);
9711 	if (l2_decap_conf.select_vlan) {
9712 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9713 		header += sizeof(struct rte_vlan_hdr);
9714 	}
9715 	action_decap_data->conf.size = header -
9716 		action_decap_data->data;
9717 	action->conf = &action_decap_data->conf;
9718 	return ret;
9719 }
9720 
9721 #define ETHER_TYPE_MPLS_UNICAST 0x8847
9722 
9723 /** Parse MPLSOGRE encap action. */
9724 static int
9725 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
9726 			       const char *str, unsigned int len,
9727 			       void *buf, unsigned int size)
9728 {
9729 	struct buffer *out = buf;
9730 	struct rte_flow_action *action;
9731 	struct action_raw_encap_data *action_encap_data;
9732 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9733 	struct rte_flow_item_vlan vlan = {
9734 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
9735 		.hdr.eth_proto = 0,
9736 	};
9737 	struct rte_flow_item_ipv4 ipv4 = {
9738 		.hdr =  {
9739 			.src_addr = mplsogre_encap_conf.ipv4_src,
9740 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
9741 			.next_proto_id = IPPROTO_GRE,
9742 			.version_ihl = RTE_IPV4_VHL_DEF,
9743 			.time_to_live = IPDEFTTL,
9744 		},
9745 	};
9746 	struct rte_flow_item_ipv6 ipv6 = {
9747 		.hdr =  {
9748 			.proto = IPPROTO_GRE,
9749 			.hop_limits = IPDEFTTL,
9750 		},
9751 	};
9752 	struct rte_flow_item_gre gre = {
9753 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9754 	};
9755 	struct rte_flow_item_mpls mpls = {
9756 		.ttl = 0,
9757 	};
9758 	uint8_t *header;
9759 	int ret;
9760 
9761 	ret = parse_vc(ctx, token, str, len, buf, size);
9762 	if (ret < 0)
9763 		return ret;
9764 	/* Nothing else to do if there is no buffer. */
9765 	if (!out)
9766 		return ret;
9767 	if (!out->args.vc.actions_n)
9768 		return -1;
9769 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9770 	/* Point to selected object. */
9771 	ctx->object = out->args.vc.data;
9772 	ctx->objmask = NULL;
9773 	/* Copy the headers to the buffer. */
9774 	action_encap_data = ctx->object;
9775 	*action_encap_data = (struct action_raw_encap_data) {
9776 		.conf = (struct rte_flow_action_raw_encap){
9777 			.data = action_encap_data->data,
9778 		},
9779 		.data = {},
9780 		.preserve = {},
9781 	};
9782 	header = action_encap_data->data;
9783 	if (mplsogre_encap_conf.select_vlan)
9784 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9785 	else if (mplsogre_encap_conf.select_ipv4)
9786 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9787 	else
9788 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9789 	memcpy(eth.hdr.dst_addr.addr_bytes,
9790 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9791 	memcpy(eth.hdr.src_addr.addr_bytes,
9792 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9793 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9794 	header += sizeof(struct rte_ether_hdr);
9795 	if (mplsogre_encap_conf.select_vlan) {
9796 		if (mplsogre_encap_conf.select_ipv4)
9797 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9798 		else
9799 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9800 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9801 		header += sizeof(struct rte_vlan_hdr);
9802 	}
9803 	if (mplsogre_encap_conf.select_ipv4) {
9804 		memcpy(header, &ipv4, sizeof(ipv4));
9805 		header += sizeof(ipv4);
9806 	} else {
9807 		memcpy(&ipv6.hdr.src_addr,
9808 		       &mplsogre_encap_conf.ipv6_src,
9809 		       sizeof(mplsogre_encap_conf.ipv6_src));
9810 		memcpy(&ipv6.hdr.dst_addr,
9811 		       &mplsogre_encap_conf.ipv6_dst,
9812 		       sizeof(mplsogre_encap_conf.ipv6_dst));
9813 		memcpy(header, &ipv6, sizeof(ipv6));
9814 		header += sizeof(ipv6);
9815 	}
9816 	memcpy(header, &gre, sizeof(gre));
9817 	header += sizeof(gre);
9818 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
9819 	       RTE_DIM(mplsogre_encap_conf.label));
9820 	mpls.label_tc_s[2] |= 0x1;
9821 	memcpy(header, &mpls, sizeof(mpls));
9822 	header += sizeof(mpls);
9823 	action_encap_data->conf.size = header -
9824 		action_encap_data->data;
9825 	action->conf = &action_encap_data->conf;
9826 	return ret;
9827 }
9828 
9829 /** Parse MPLSOGRE decap action. */
9830 static int
9831 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
9832 			       const char *str, unsigned int len,
9833 			       void *buf, unsigned int size)
9834 {
9835 	struct buffer *out = buf;
9836 	struct rte_flow_action *action;
9837 	struct action_raw_decap_data *action_decap_data;
9838 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9839 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
9840 	struct rte_flow_item_ipv4 ipv4 = {
9841 		.hdr =  {
9842 			.next_proto_id = IPPROTO_GRE,
9843 		},
9844 	};
9845 	struct rte_flow_item_ipv6 ipv6 = {
9846 		.hdr =  {
9847 			.proto = IPPROTO_GRE,
9848 		},
9849 	};
9850 	struct rte_flow_item_gre gre = {
9851 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
9852 	};
9853 	struct rte_flow_item_mpls mpls;
9854 	uint8_t *header;
9855 	int ret;
9856 
9857 	ret = parse_vc(ctx, token, str, len, buf, size);
9858 	if (ret < 0)
9859 		return ret;
9860 	/* Nothing else to do if there is no buffer. */
9861 	if (!out)
9862 		return ret;
9863 	if (!out->args.vc.actions_n)
9864 		return -1;
9865 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9866 	/* Point to selected object. */
9867 	ctx->object = out->args.vc.data;
9868 	ctx->objmask = NULL;
9869 	/* Copy the headers to the buffer. */
9870 	action_decap_data = ctx->object;
9871 	*action_decap_data = (struct action_raw_decap_data) {
9872 		.conf = (struct rte_flow_action_raw_decap){
9873 			.data = action_decap_data->data,
9874 		},
9875 		.data = {},
9876 	};
9877 	header = action_decap_data->data;
9878 	if (mplsogre_decap_conf.select_vlan)
9879 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9880 	else if (mplsogre_encap_conf.select_ipv4)
9881 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9882 	else
9883 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9884 	memcpy(eth.hdr.dst_addr.addr_bytes,
9885 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9886 	memcpy(eth.hdr.src_addr.addr_bytes,
9887 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9888 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9889 	header += sizeof(struct rte_ether_hdr);
9890 	if (mplsogre_encap_conf.select_vlan) {
9891 		if (mplsogre_encap_conf.select_ipv4)
9892 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9893 		else
9894 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9895 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9896 		header += sizeof(struct rte_vlan_hdr);
9897 	}
9898 	if (mplsogre_encap_conf.select_ipv4) {
9899 		memcpy(header, &ipv4, sizeof(ipv4));
9900 		header += sizeof(ipv4);
9901 	} else {
9902 		memcpy(header, &ipv6, sizeof(ipv6));
9903 		header += sizeof(ipv6);
9904 	}
9905 	memcpy(header, &gre, sizeof(gre));
9906 	header += sizeof(gre);
9907 	memset(&mpls, 0, sizeof(mpls));
9908 	memcpy(header, &mpls, sizeof(mpls));
9909 	header += sizeof(mpls);
9910 	action_decap_data->conf.size = header -
9911 		action_decap_data->data;
9912 	action->conf = &action_decap_data->conf;
9913 	return ret;
9914 }
9915 
9916 /** Parse MPLSOUDP encap action. */
9917 static int
9918 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
9919 			       const char *str, unsigned int len,
9920 			       void *buf, unsigned int size)
9921 {
9922 	struct buffer *out = buf;
9923 	struct rte_flow_action *action;
9924 	struct action_raw_encap_data *action_encap_data;
9925 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
9926 	struct rte_flow_item_vlan vlan = {
9927 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
9928 		.hdr.eth_proto = 0,
9929 	};
9930 	struct rte_flow_item_ipv4 ipv4 = {
9931 		.hdr =  {
9932 			.src_addr = mplsoudp_encap_conf.ipv4_src,
9933 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
9934 			.next_proto_id = IPPROTO_UDP,
9935 			.version_ihl = RTE_IPV4_VHL_DEF,
9936 			.time_to_live = IPDEFTTL,
9937 		},
9938 	};
9939 	struct rte_flow_item_ipv6 ipv6 = {
9940 		.hdr =  {
9941 			.proto = IPPROTO_UDP,
9942 			.hop_limits = IPDEFTTL,
9943 		},
9944 	};
9945 	struct rte_flow_item_udp udp = {
9946 		.hdr = {
9947 			.src_port = mplsoudp_encap_conf.udp_src,
9948 			.dst_port = mplsoudp_encap_conf.udp_dst,
9949 		},
9950 	};
9951 	struct rte_flow_item_mpls mpls;
9952 	uint8_t *header;
9953 	int ret;
9954 
9955 	ret = parse_vc(ctx, token, str, len, buf, size);
9956 	if (ret < 0)
9957 		return ret;
9958 	/* Nothing else to do if there is no buffer. */
9959 	if (!out)
9960 		return ret;
9961 	if (!out->args.vc.actions_n)
9962 		return -1;
9963 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9964 	/* Point to selected object. */
9965 	ctx->object = out->args.vc.data;
9966 	ctx->objmask = NULL;
9967 	/* Copy the headers to the buffer. */
9968 	action_encap_data = ctx->object;
9969 	*action_encap_data = (struct action_raw_encap_data) {
9970 		.conf = (struct rte_flow_action_raw_encap){
9971 			.data = action_encap_data->data,
9972 		},
9973 		.data = {},
9974 		.preserve = {},
9975 	};
9976 	header = action_encap_data->data;
9977 	if (mplsoudp_encap_conf.select_vlan)
9978 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
9979 	else if (mplsoudp_encap_conf.select_ipv4)
9980 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9981 	else
9982 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9983 	memcpy(eth.hdr.dst_addr.addr_bytes,
9984 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
9985 	memcpy(eth.hdr.src_addr.addr_bytes,
9986 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
9987 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
9988 	header += sizeof(struct rte_ether_hdr);
9989 	if (mplsoudp_encap_conf.select_vlan) {
9990 		if (mplsoudp_encap_conf.select_ipv4)
9991 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
9992 		else
9993 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
9994 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
9995 		header += sizeof(struct rte_vlan_hdr);
9996 	}
9997 	if (mplsoudp_encap_conf.select_ipv4) {
9998 		memcpy(header, &ipv4, sizeof(ipv4));
9999 		header += sizeof(ipv4);
10000 	} else {
10001 		memcpy(&ipv6.hdr.src_addr,
10002 		       &mplsoudp_encap_conf.ipv6_src,
10003 		       sizeof(mplsoudp_encap_conf.ipv6_src));
10004 		memcpy(&ipv6.hdr.dst_addr,
10005 		       &mplsoudp_encap_conf.ipv6_dst,
10006 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
10007 		memcpy(header, &ipv6, sizeof(ipv6));
10008 		header += sizeof(ipv6);
10009 	}
10010 	memcpy(header, &udp, sizeof(udp));
10011 	header += sizeof(udp);
10012 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
10013 	       RTE_DIM(mplsoudp_encap_conf.label));
10014 	mpls.label_tc_s[2] |= 0x1;
10015 	memcpy(header, &mpls, sizeof(mpls));
10016 	header += sizeof(mpls);
10017 	action_encap_data->conf.size = header -
10018 		action_encap_data->data;
10019 	action->conf = &action_encap_data->conf;
10020 	return ret;
10021 }
10022 
10023 /** Parse MPLSOUDP decap action. */
10024 static int
10025 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
10026 			       const char *str, unsigned int len,
10027 			       void *buf, unsigned int size)
10028 {
10029 	struct buffer *out = buf;
10030 	struct rte_flow_action *action;
10031 	struct action_raw_decap_data *action_decap_data;
10032 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
10033 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
10034 	struct rte_flow_item_ipv4 ipv4 = {
10035 		.hdr =  {
10036 			.next_proto_id = IPPROTO_UDP,
10037 		},
10038 	};
10039 	struct rte_flow_item_ipv6 ipv6 = {
10040 		.hdr =  {
10041 			.proto = IPPROTO_UDP,
10042 		},
10043 	};
10044 	struct rte_flow_item_udp udp = {
10045 		.hdr = {
10046 			.dst_port = rte_cpu_to_be_16(6635),
10047 		},
10048 	};
10049 	struct rte_flow_item_mpls mpls;
10050 	uint8_t *header;
10051 	int ret;
10052 
10053 	ret = parse_vc(ctx, token, str, len, buf, size);
10054 	if (ret < 0)
10055 		return ret;
10056 	/* Nothing else to do if there is no buffer. */
10057 	if (!out)
10058 		return ret;
10059 	if (!out->args.vc.actions_n)
10060 		return -1;
10061 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10062 	/* Point to selected object. */
10063 	ctx->object = out->args.vc.data;
10064 	ctx->objmask = NULL;
10065 	/* Copy the headers to the buffer. */
10066 	action_decap_data = ctx->object;
10067 	*action_decap_data = (struct action_raw_decap_data) {
10068 		.conf = (struct rte_flow_action_raw_decap){
10069 			.data = action_decap_data->data,
10070 		},
10071 		.data = {},
10072 	};
10073 	header = action_decap_data->data;
10074 	if (mplsoudp_decap_conf.select_vlan)
10075 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
10076 	else if (mplsoudp_encap_conf.select_ipv4)
10077 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10078 	else
10079 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10080 	memcpy(eth.hdr.dst_addr.addr_bytes,
10081 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
10082 	memcpy(eth.hdr.src_addr.addr_bytes,
10083 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
10084 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
10085 	header += sizeof(struct rte_ether_hdr);
10086 	if (mplsoudp_encap_conf.select_vlan) {
10087 		if (mplsoudp_encap_conf.select_ipv4)
10088 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10089 		else
10090 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10091 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
10092 		header += sizeof(struct rte_vlan_hdr);
10093 	}
10094 	if (mplsoudp_encap_conf.select_ipv4) {
10095 		memcpy(header, &ipv4, sizeof(ipv4));
10096 		header += sizeof(ipv4);
10097 	} else {
10098 		memcpy(header, &ipv6, sizeof(ipv6));
10099 		header += sizeof(ipv6);
10100 	}
10101 	memcpy(header, &udp, sizeof(udp));
10102 	header += sizeof(udp);
10103 	memset(&mpls, 0, sizeof(mpls));
10104 	memcpy(header, &mpls, sizeof(mpls));
10105 	header += sizeof(mpls);
10106 	action_decap_data->conf.size = header -
10107 		action_decap_data->data;
10108 	action->conf = &action_decap_data->conf;
10109 	return ret;
10110 }
10111 
10112 static int
10113 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
10114 				const char *str, unsigned int len, void *buf,
10115 				unsigned int size)
10116 {
10117 	struct action_raw_decap_data *action_raw_decap_data;
10118 	struct rte_flow_action *action;
10119 	const struct arg *arg;
10120 	struct buffer *out = buf;
10121 	int ret;
10122 	uint16_t idx;
10123 
10124 	RTE_SET_USED(token);
10125 	RTE_SET_USED(buf);
10126 	RTE_SET_USED(size);
10127 	arg = ARGS_ENTRY_ARB_BOUNDED
10128 		(offsetof(struct action_raw_decap_data, idx),
10129 		 sizeof(((struct action_raw_decap_data *)0)->idx),
10130 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10131 	if (push_args(ctx, arg))
10132 		return -1;
10133 	ret = parse_int(ctx, token, str, len, NULL, 0);
10134 	if (ret < 0) {
10135 		pop_args(ctx);
10136 		return -1;
10137 	}
10138 	if (!ctx->object)
10139 		return len;
10140 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10141 	action_raw_decap_data = ctx->object;
10142 	idx = action_raw_decap_data->idx;
10143 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
10144 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
10145 	action->conf = &action_raw_decap_data->conf;
10146 	return len;
10147 }
10148 
10149 
10150 static int
10151 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
10152 				const char *str, unsigned int len, void *buf,
10153 				unsigned int size)
10154 {
10155 	struct action_raw_encap_data *action_raw_encap_data;
10156 	struct rte_flow_action *action;
10157 	const struct arg *arg;
10158 	struct buffer *out = buf;
10159 	int ret;
10160 	uint16_t idx;
10161 
10162 	RTE_SET_USED(token);
10163 	RTE_SET_USED(buf);
10164 	RTE_SET_USED(size);
10165 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
10166 		return -1;
10167 	arg = ARGS_ENTRY_ARB_BOUNDED
10168 		(offsetof(struct action_raw_encap_data, idx),
10169 		 sizeof(((struct action_raw_encap_data *)0)->idx),
10170 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
10171 	if (push_args(ctx, arg))
10172 		return -1;
10173 	ret = parse_int(ctx, token, str, len, NULL, 0);
10174 	if (ret < 0) {
10175 		pop_args(ctx);
10176 		return -1;
10177 	}
10178 	if (!ctx->object)
10179 		return len;
10180 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10181 	action_raw_encap_data = ctx->object;
10182 	idx = action_raw_encap_data->idx;
10183 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
10184 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
10185 	action_raw_encap_data->conf.preserve = NULL;
10186 	action->conf = &action_raw_encap_data->conf;
10187 	return len;
10188 }
10189 
10190 static int
10191 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
10192 			  const char *str, unsigned int len, void *buf,
10193 			  unsigned int size)
10194 {
10195 	struct buffer *out = buf;
10196 	int ret;
10197 
10198 	ret = parse_vc(ctx, token, str, len, buf, size);
10199 	if (ret < 0)
10200 		return ret;
10201 	/* Nothing else to do if there is no buffer. */
10202 	if (!out)
10203 		return ret;
10204 	if (!out->args.vc.actions_n)
10205 		return -1;
10206 	/* Point to selected object. */
10207 	ctx->object = out->args.vc.data;
10208 	ctx->objmask = NULL;
10209 	return ret;
10210 }
10211 
10212 static int
10213 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
10214 			  const char *str, unsigned int len, void *buf,
10215 			  unsigned int size)
10216 {
10217 	struct buffer *out = buf;
10218 	struct rte_flow_action *action;
10219 	struct action_raw_decap_data *action_raw_decap_data = NULL;
10220 	int ret;
10221 
10222 	ret = parse_vc(ctx, token, str, len, buf, size);
10223 	if (ret < 0)
10224 		return ret;
10225 	/* Nothing else to do if there is no buffer. */
10226 	if (!out)
10227 		return ret;
10228 	if (!out->args.vc.actions_n)
10229 		return -1;
10230 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10231 	/* Point to selected object. */
10232 	ctx->object = out->args.vc.data;
10233 	ctx->objmask = NULL;
10234 	/* Copy the headers to the buffer. */
10235 	action_raw_decap_data = ctx->object;
10236 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
10237 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
10238 	action->conf = &action_raw_decap_data->conf;
10239 	return ret;
10240 }
10241 
10242 static int
10243 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token,
10244 				const char *str, unsigned int len, void *buf,
10245 				unsigned int size)
10246 {
10247 	struct buffer *out = buf;
10248 	struct rte_flow_action *action;
10249 	struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL;
10250 	int ret;
10251 
10252 	ret = parse_vc(ctx, token, str, len, buf, size);
10253 	if (ret < 0)
10254 		return ret;
10255 	/* Nothing else to do if there is no buffer. */
10256 	if (!out)
10257 		return ret;
10258 	if (!out->args.vc.actions_n)
10259 		return -1;
10260 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10261 	/* Point to selected object. */
10262 	ctx->object = out->args.vc.data;
10263 	ctx->objmask = NULL;
10264 	/* Copy the headers to the buffer. */
10265 	ipv6_ext_remove_data = ctx->object;
10266 	ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type;
10267 	action->conf = &ipv6_ext_remove_data->conf;
10268 	return ret;
10269 }
10270 
10271 static int
10272 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token,
10273 				      const char *str, unsigned int len, void *buf,
10274 				      unsigned int size)
10275 {
10276 	struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data;
10277 	struct rte_flow_action *action;
10278 	const struct arg *arg;
10279 	struct buffer *out = buf;
10280 	int ret;
10281 	uint16_t idx;
10282 
10283 	RTE_SET_USED(token);
10284 	RTE_SET_USED(buf);
10285 	RTE_SET_USED(size);
10286 	arg = ARGS_ENTRY_ARB_BOUNDED
10287 		(offsetof(struct action_ipv6_ext_remove_data, idx),
10288 		 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx),
10289 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10290 	if (push_args(ctx, arg))
10291 		return -1;
10292 	ret = parse_int(ctx, token, str, len, NULL, 0);
10293 	if (ret < 0) {
10294 		pop_args(ctx);
10295 		return -1;
10296 	}
10297 	if (!ctx->object)
10298 		return len;
10299 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10300 	action_ipv6_ext_remove_data = ctx->object;
10301 	idx = action_ipv6_ext_remove_data->idx;
10302 	action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type;
10303 	action->conf = &action_ipv6_ext_remove_data->conf;
10304 	return len;
10305 }
10306 
10307 static int
10308 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token,
10309 			      const char *str, unsigned int len, void *buf,
10310 			      unsigned int size)
10311 {
10312 	struct buffer *out = buf;
10313 	struct rte_flow_action *action;
10314 	struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL;
10315 	int ret;
10316 
10317 	ret = parse_vc(ctx, token, str, len, buf, size);
10318 	if (ret < 0)
10319 		return ret;
10320 	/* Nothing else to do if there is no buffer. */
10321 	if (!out)
10322 		return ret;
10323 	if (!out->args.vc.actions_n)
10324 		return -1;
10325 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10326 	/* Point to selected object. */
10327 	ctx->object = out->args.vc.data;
10328 	ctx->objmask = NULL;
10329 	/* Copy the headers to the buffer. */
10330 	ipv6_ext_push_data = ctx->object;
10331 	ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type;
10332 	ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data;
10333 	ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size;
10334 	action->conf = &ipv6_ext_push_data->conf;
10335 	return ret;
10336 }
10337 
10338 static int
10339 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token,
10340 				    const char *str, unsigned int len, void *buf,
10341 				    unsigned int size)
10342 {
10343 	struct action_ipv6_ext_push_data *action_ipv6_ext_push_data;
10344 	struct rte_flow_action *action;
10345 	const struct arg *arg;
10346 	struct buffer *out = buf;
10347 	int ret;
10348 	uint16_t idx;
10349 
10350 	RTE_SET_USED(token);
10351 	RTE_SET_USED(buf);
10352 	RTE_SET_USED(size);
10353 	arg = ARGS_ENTRY_ARB_BOUNDED
10354 		(offsetof(struct action_ipv6_ext_push_data, idx),
10355 		 sizeof(((struct action_ipv6_ext_push_data *)0)->idx),
10356 		 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1);
10357 	if (push_args(ctx, arg))
10358 		return -1;
10359 	ret = parse_int(ctx, token, str, len, NULL, 0);
10360 	if (ret < 0) {
10361 		pop_args(ctx);
10362 		return -1;
10363 	}
10364 	if (!ctx->object)
10365 		return len;
10366 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10367 	action_ipv6_ext_push_data = ctx->object;
10368 	idx = action_ipv6_ext_push_data->idx;
10369 	action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type;
10370 	action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size;
10371 	action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data;
10372 	action->conf = &action_ipv6_ext_push_data->conf;
10373 	return len;
10374 }
10375 
10376 static int
10377 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
10378 			 const char *str, unsigned int len, void *buf,
10379 			 unsigned int size)
10380 {
10381 	int ret;
10382 
10383 	ret = parse_vc(ctx, token, str, len, buf, size);
10384 	if (ret < 0)
10385 		return ret;
10386 	ret = rte_flow_dynf_metadata_register();
10387 	if (ret < 0)
10388 		return -1;
10389 	return len;
10390 }
10391 
10392 static int
10393 parse_vc_action_sample(struct context *ctx, const struct token *token,
10394 			 const char *str, unsigned int len, void *buf,
10395 			 unsigned int size)
10396 {
10397 	struct buffer *out = buf;
10398 	struct rte_flow_action *action;
10399 	struct action_sample_data *action_sample_data = NULL;
10400 	static struct rte_flow_action end_action = {
10401 		RTE_FLOW_ACTION_TYPE_END, 0
10402 	};
10403 	int ret;
10404 
10405 	ret = parse_vc(ctx, token, str, len, buf, size);
10406 	if (ret < 0)
10407 		return ret;
10408 	/* Nothing else to do if there is no buffer. */
10409 	if (!out)
10410 		return ret;
10411 	if (!out->args.vc.actions_n)
10412 		return -1;
10413 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10414 	/* Point to selected object. */
10415 	ctx->object = out->args.vc.data;
10416 	ctx->objmask = NULL;
10417 	/* Copy the headers to the buffer. */
10418 	action_sample_data = ctx->object;
10419 	action_sample_data->conf.actions = &end_action;
10420 	action->conf = &action_sample_data->conf;
10421 	return ret;
10422 }
10423 
10424 static int
10425 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
10426 				const char *str, unsigned int len, void *buf,
10427 				unsigned int size)
10428 {
10429 	struct action_sample_data *action_sample_data;
10430 	struct rte_flow_action *action;
10431 	const struct arg *arg;
10432 	struct buffer *out = buf;
10433 	int ret;
10434 	uint16_t idx;
10435 
10436 	RTE_SET_USED(token);
10437 	RTE_SET_USED(buf);
10438 	RTE_SET_USED(size);
10439 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
10440 		return -1;
10441 	arg = ARGS_ENTRY_ARB_BOUNDED
10442 		(offsetof(struct action_sample_data, idx),
10443 		 sizeof(((struct action_sample_data *)0)->idx),
10444 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
10445 	if (push_args(ctx, arg))
10446 		return -1;
10447 	ret = parse_int(ctx, token, str, len, NULL, 0);
10448 	if (ret < 0) {
10449 		pop_args(ctx);
10450 		return -1;
10451 	}
10452 	if (!ctx->object)
10453 		return len;
10454 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
10455 	action_sample_data = ctx->object;
10456 	idx = action_sample_data->idx;
10457 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
10458 	action->conf = &action_sample_data->conf;
10459 	return len;
10460 }
10461 
10462 /** Parse operation for modify_field command. */
10463 static int
10464 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
10465 			 const char *str, unsigned int len, void *buf,
10466 			 unsigned int size)
10467 {
10468 	struct rte_flow_action_modify_field *action_modify_field;
10469 	unsigned int i;
10470 
10471 	(void)token;
10472 	(void)buf;
10473 	(void)size;
10474 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
10475 		return -1;
10476 	for (i = 0; modify_field_ops[i]; ++i)
10477 		if (!strcmp_partial(modify_field_ops[i], str, len))
10478 			break;
10479 	if (!modify_field_ops[i])
10480 		return -1;
10481 	if (!ctx->object)
10482 		return len;
10483 	action_modify_field = ctx->object;
10484 	action_modify_field->operation = (enum rte_flow_modify_op)i;
10485 	return len;
10486 }
10487 
10488 /** Parse id for modify_field command. */
10489 static int
10490 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
10491 			 const char *str, unsigned int len, void *buf,
10492 			 unsigned int size)
10493 {
10494 	struct rte_flow_action_modify_field *action_modify_field;
10495 	unsigned int i;
10496 
10497 	(void)token;
10498 	(void)buf;
10499 	(void)size;
10500 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
10501 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
10502 		return -1;
10503 	for (i = 0; flow_field_ids[i]; ++i)
10504 		if (!strcmp_partial(flow_field_ids[i], str, len))
10505 			break;
10506 	if (!flow_field_ids[i])
10507 		return -1;
10508 	if (!ctx->object)
10509 		return len;
10510 	action_modify_field = ctx->object;
10511 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
10512 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
10513 	else
10514 		action_modify_field->src.field = (enum rte_flow_field_id)i;
10515 	return len;
10516 }
10517 
10518 /** Parse level for modify_field command. */
10519 static int
10520 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
10521 			 const char *str, unsigned int len, void *buf,
10522 			 unsigned int size)
10523 {
10524 	struct rte_flow_action_modify_field *action;
10525 	struct flex_item *fp = NULL;
10526 	uint32_t val;
10527 	struct buffer *out = buf;
10528 	char *end;
10529 
10530 	(void)token;
10531 	(void)size;
10532 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10533 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
10534 		return -1;
10535 	if (!ctx->object)
10536 		return len;
10537 	action = ctx->object;
10538 	errno = 0;
10539 	val = strtoumax(str, &end, 0);
10540 	if (errno || (size_t)(end - str) != len)
10541 		return -1;
10542 	/* No need to validate action template mask value */
10543 	if (out->args.vc.masks) {
10544 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
10545 			action->dst.level = val;
10546 		else
10547 			action->src.level = val;
10548 		return len;
10549 	}
10550 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
10551 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
10552 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
10553 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
10554 		if (val >= FLEX_MAX_PARSERS_NUM) {
10555 			printf("Bad flex item handle\n");
10556 			return -1;
10557 		}
10558 		fp = flex_items[ctx->port][val];
10559 		if (!fp) {
10560 			printf("Bad flex item handle\n");
10561 			return -1;
10562 		}
10563 	}
10564 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
10565 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
10566 			action->dst.level = val;
10567 		else
10568 			action->dst.flex_handle = fp->flex_handle;
10569 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
10570 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
10571 			action->src.level = val;
10572 		else
10573 			action->src.flex_handle = fp->flex_handle;
10574 	}
10575 	return len;
10576 }
10577 
10578 /** Parse the conntrack update, not a rte_flow_action. */
10579 static int
10580 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
10581 			 const char *str, unsigned int len, void *buf,
10582 			 unsigned int size)
10583 {
10584 	struct buffer *out = buf;
10585 	struct rte_flow_modify_conntrack *ct_modify = NULL;
10586 
10587 	(void)size;
10588 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
10589 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
10590 		return -1;
10591 	/* Token name must match. */
10592 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10593 		return -1;
10594 	/* Nothing else to do if there is no buffer. */
10595 	if (!out)
10596 		return len;
10597 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
10598 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
10599 		ct_modify->new_ct.is_original_dir =
10600 				conntrack_context.is_original_dir;
10601 		ct_modify->direction = 1;
10602 	} else {
10603 		uint32_t old_dir;
10604 
10605 		old_dir = ct_modify->new_ct.is_original_dir;
10606 		memcpy(&ct_modify->new_ct, &conntrack_context,
10607 		       sizeof(conntrack_context));
10608 		ct_modify->new_ct.is_original_dir = old_dir;
10609 		ct_modify->state = 1;
10610 	}
10611 	return len;
10612 }
10613 
10614 /** Parse tokens for destroy command. */
10615 static int
10616 parse_destroy(struct context *ctx, const struct token *token,
10617 	      const char *str, unsigned int len,
10618 	      void *buf, unsigned int size)
10619 {
10620 	struct buffer *out = buf;
10621 
10622 	/* Token name must match. */
10623 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10624 		return -1;
10625 	/* Nothing else to do if there is no buffer. */
10626 	if (!out)
10627 		return len;
10628 	if (!out->command) {
10629 		if (ctx->curr != DESTROY)
10630 			return -1;
10631 		if (sizeof(*out) > size)
10632 			return -1;
10633 		out->command = ctx->curr;
10634 		ctx->objdata = 0;
10635 		ctx->object = out;
10636 		ctx->objmask = NULL;
10637 		out->args.destroy.rule =
10638 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10639 					       sizeof(double));
10640 		return len;
10641 	}
10642 	if (ctx->curr == DESTROY_IS_USER_ID) {
10643 		out->args.destroy.is_user_id = true;
10644 		return len;
10645 	}
10646 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
10647 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
10648 		return -1;
10649 	ctx->objdata = 0;
10650 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
10651 	ctx->objmask = NULL;
10652 	return len;
10653 }
10654 
10655 /** Parse tokens for flush command. */
10656 static int
10657 parse_flush(struct context *ctx, const struct token *token,
10658 	    const char *str, unsigned int len,
10659 	    void *buf, unsigned int size)
10660 {
10661 	struct buffer *out = buf;
10662 
10663 	/* Token name must match. */
10664 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10665 		return -1;
10666 	/* Nothing else to do if there is no buffer. */
10667 	if (!out)
10668 		return len;
10669 	if (!out->command) {
10670 		if (ctx->curr != FLUSH)
10671 			return -1;
10672 		if (sizeof(*out) > size)
10673 			return -1;
10674 		out->command = ctx->curr;
10675 		ctx->objdata = 0;
10676 		ctx->object = out;
10677 		ctx->objmask = NULL;
10678 	}
10679 	return len;
10680 }
10681 
10682 /** Parse tokens for dump command. */
10683 static int
10684 parse_dump(struct context *ctx, const struct token *token,
10685 	    const char *str, unsigned int len,
10686 	    void *buf, unsigned int size)
10687 {
10688 	struct buffer *out = buf;
10689 
10690 	/* Token name must match. */
10691 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10692 		return -1;
10693 	/* Nothing else to do if there is no buffer. */
10694 	if (!out)
10695 		return len;
10696 	if (!out->command) {
10697 		if (ctx->curr != DUMP)
10698 			return -1;
10699 		if (sizeof(*out) > size)
10700 			return -1;
10701 		out->command = ctx->curr;
10702 		ctx->objdata = 0;
10703 		ctx->object = out;
10704 		ctx->objmask = NULL;
10705 		return len;
10706 	}
10707 	switch (ctx->curr) {
10708 	case DUMP_ALL:
10709 	case DUMP_ONE:
10710 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
10711 		out->command = ctx->curr;
10712 		ctx->objdata = 0;
10713 		ctx->object = out;
10714 		ctx->objmask = NULL;
10715 		return len;
10716 	case DUMP_IS_USER_ID:
10717 		out->args.dump.is_user_id = true;
10718 		return len;
10719 	default:
10720 		return -1;
10721 	}
10722 }
10723 
10724 /** Parse tokens for query command. */
10725 static int
10726 parse_query(struct context *ctx, const struct token *token,
10727 	    const char *str, unsigned int len,
10728 	    void *buf, unsigned int size)
10729 {
10730 	struct buffer *out = buf;
10731 
10732 	/* Token name must match. */
10733 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10734 		return -1;
10735 	/* Nothing else to do if there is no buffer. */
10736 	if (!out)
10737 		return len;
10738 	if (!out->command) {
10739 		if (ctx->curr != QUERY)
10740 			return -1;
10741 		if (sizeof(*out) > size)
10742 			return -1;
10743 		out->command = ctx->curr;
10744 		ctx->objdata = 0;
10745 		ctx->object = out;
10746 		ctx->objmask = NULL;
10747 	}
10748 	if (ctx->curr == QUERY_IS_USER_ID) {
10749 		out->args.query.is_user_id = true;
10750 		return len;
10751 	}
10752 	return len;
10753 }
10754 
10755 /** Parse action names. */
10756 static int
10757 parse_action(struct context *ctx, const struct token *token,
10758 	     const char *str, unsigned int len,
10759 	     void *buf, unsigned int size)
10760 {
10761 	struct buffer *out = buf;
10762 	const struct arg *arg = pop_args(ctx);
10763 	unsigned int i;
10764 
10765 	(void)size;
10766 	/* Argument is expected. */
10767 	if (!arg)
10768 		return -1;
10769 	/* Parse action name. */
10770 	for (i = 0; next_action[i]; ++i) {
10771 		const struct parse_action_priv *priv;
10772 
10773 		token = &token_list[next_action[i]];
10774 		if (strcmp_partial(token->name, str, len))
10775 			continue;
10776 		priv = token->priv;
10777 		if (!priv)
10778 			goto error;
10779 		if (out)
10780 			memcpy((uint8_t *)ctx->object + arg->offset,
10781 			       &priv->type,
10782 			       arg->size);
10783 		return len;
10784 	}
10785 error:
10786 	push_args(ctx, arg);
10787 	return -1;
10788 }
10789 
10790 /** Parse tokens for list command. */
10791 static int
10792 parse_list(struct context *ctx, const struct token *token,
10793 	   const char *str, unsigned int len,
10794 	   void *buf, unsigned int size)
10795 {
10796 	struct buffer *out = buf;
10797 
10798 	/* Token name must match. */
10799 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10800 		return -1;
10801 	/* Nothing else to do if there is no buffer. */
10802 	if (!out)
10803 		return len;
10804 	if (!out->command) {
10805 		if (ctx->curr != LIST)
10806 			return -1;
10807 		if (sizeof(*out) > size)
10808 			return -1;
10809 		out->command = ctx->curr;
10810 		ctx->objdata = 0;
10811 		ctx->object = out;
10812 		ctx->objmask = NULL;
10813 		out->args.list.group =
10814 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10815 					       sizeof(double));
10816 		return len;
10817 	}
10818 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
10819 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
10820 		return -1;
10821 	ctx->objdata = 0;
10822 	ctx->object = out->args.list.group + out->args.list.group_n++;
10823 	ctx->objmask = NULL;
10824 	return len;
10825 }
10826 
10827 /** Parse tokens for list all aged flows command. */
10828 static int
10829 parse_aged(struct context *ctx, const struct token *token,
10830 	   const char *str, unsigned int len,
10831 	   void *buf, unsigned int size)
10832 {
10833 	struct buffer *out = buf;
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 || out->command == QUEUE) {
10842 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
10843 			return -1;
10844 		if (sizeof(*out) > size)
10845 			return -1;
10846 		out->command = ctx->curr;
10847 		ctx->objdata = 0;
10848 		ctx->object = out;
10849 		ctx->objmask = NULL;
10850 	}
10851 	if (ctx->curr == AGED_DESTROY)
10852 		out->args.aged.destroy = 1;
10853 	return len;
10854 }
10855 
10856 /** Parse tokens for isolate command. */
10857 static int
10858 parse_isolate(struct context *ctx, const struct token *token,
10859 	      const char *str, unsigned int len,
10860 	      void *buf, unsigned int size)
10861 {
10862 	struct buffer *out = buf;
10863 
10864 	/* Token name must match. */
10865 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10866 		return -1;
10867 	/* Nothing else to do if there is no buffer. */
10868 	if (!out)
10869 		return len;
10870 	if (!out->command) {
10871 		if (ctx->curr != ISOLATE)
10872 			return -1;
10873 		if (sizeof(*out) > size)
10874 			return -1;
10875 		out->command = ctx->curr;
10876 		ctx->objdata = 0;
10877 		ctx->object = out;
10878 		ctx->objmask = NULL;
10879 	}
10880 	return len;
10881 }
10882 
10883 /** Parse tokens for info/configure command. */
10884 static int
10885 parse_configure(struct context *ctx, const struct token *token,
10886 		const char *str, unsigned int len,
10887 		void *buf, unsigned int size)
10888 {
10889 	struct buffer *out = buf;
10890 
10891 	/* Token name must match. */
10892 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10893 		return -1;
10894 	/* Nothing else to do if there is no buffer. */
10895 	if (!out)
10896 		return len;
10897 	if (!out->command) {
10898 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
10899 			return -1;
10900 		if (sizeof(*out) > size)
10901 			return -1;
10902 		out->command = ctx->curr;
10903 		ctx->objdata = 0;
10904 		ctx->object = out;
10905 		ctx->objmask = NULL;
10906 	}
10907 	return len;
10908 }
10909 
10910 /** Parse tokens for template create command. */
10911 static int
10912 parse_template(struct context *ctx, const struct token *token,
10913 	       const char *str, unsigned int len,
10914 	       void *buf, unsigned int size)
10915 {
10916 	struct buffer *out = buf;
10917 
10918 	/* Token name must match. */
10919 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10920 		return -1;
10921 	/* Nothing else to do if there is no buffer. */
10922 	if (!out)
10923 		return len;
10924 	if (!out->command) {
10925 		if (ctx->curr != PATTERN_TEMPLATE &&
10926 		    ctx->curr != ACTIONS_TEMPLATE)
10927 			return -1;
10928 		if (sizeof(*out) > size)
10929 			return -1;
10930 		out->command = ctx->curr;
10931 		ctx->objdata = 0;
10932 		ctx->object = out;
10933 		ctx->objmask = NULL;
10934 		out->args.vc.data = (uint8_t *)out + size;
10935 		return len;
10936 	}
10937 	switch (ctx->curr) {
10938 	case PATTERN_TEMPLATE_CREATE:
10939 		out->args.vc.pattern =
10940 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10941 					       sizeof(double));
10942 		out->args.vc.pat_templ_id = UINT32_MAX;
10943 		out->command = ctx->curr;
10944 		ctx->objdata = 0;
10945 		ctx->object = out;
10946 		ctx->objmask = NULL;
10947 		return len;
10948 	case PATTERN_TEMPLATE_EGRESS:
10949 		out->args.vc.attr.egress = 1;
10950 		return len;
10951 	case PATTERN_TEMPLATE_INGRESS:
10952 		out->args.vc.attr.ingress = 1;
10953 		return len;
10954 	case PATTERN_TEMPLATE_TRANSFER:
10955 		out->args.vc.attr.transfer = 1;
10956 		return len;
10957 	case ACTIONS_TEMPLATE_CREATE:
10958 		out->args.vc.act_templ_id = UINT32_MAX;
10959 		out->command = ctx->curr;
10960 		ctx->objdata = 0;
10961 		ctx->object = out;
10962 		ctx->objmask = NULL;
10963 		return len;
10964 	case ACTIONS_TEMPLATE_SPEC:
10965 		out->args.vc.actions =
10966 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10967 					       sizeof(double));
10968 		ctx->object = out->args.vc.actions;
10969 		ctx->objmask = NULL;
10970 		return len;
10971 	case ACTIONS_TEMPLATE_MASK:
10972 		out->args.vc.masks =
10973 			(void *)RTE_ALIGN_CEIL((uintptr_t)
10974 					       (out->args.vc.actions +
10975 						out->args.vc.actions_n),
10976 					       sizeof(double));
10977 		ctx->object = out->args.vc.masks;
10978 		ctx->objmask = NULL;
10979 		return len;
10980 	case ACTIONS_TEMPLATE_EGRESS:
10981 		out->args.vc.attr.egress = 1;
10982 		return len;
10983 	case ACTIONS_TEMPLATE_INGRESS:
10984 		out->args.vc.attr.ingress = 1;
10985 		return len;
10986 	case ACTIONS_TEMPLATE_TRANSFER:
10987 		out->args.vc.attr.transfer = 1;
10988 		return len;
10989 	default:
10990 		return -1;
10991 	}
10992 }
10993 
10994 /** Parse tokens for template destroy command. */
10995 static int
10996 parse_template_destroy(struct context *ctx, const struct token *token,
10997 		       const char *str, unsigned int len,
10998 		       void *buf, unsigned int size)
10999 {
11000 	struct buffer *out = buf;
11001 	uint32_t *template_id;
11002 
11003 	/* Token name must match. */
11004 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11005 		return -1;
11006 	/* Nothing else to do if there is no buffer. */
11007 	if (!out)
11008 		return len;
11009 	if (!out->command ||
11010 		out->command == PATTERN_TEMPLATE ||
11011 		out->command == ACTIONS_TEMPLATE) {
11012 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
11013 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
11014 			return -1;
11015 		if (sizeof(*out) > size)
11016 			return -1;
11017 		out->command = ctx->curr;
11018 		ctx->objdata = 0;
11019 		ctx->object = out;
11020 		ctx->objmask = NULL;
11021 		out->args.templ_destroy.template_id =
11022 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11023 					       sizeof(double));
11024 		return len;
11025 	}
11026 	template_id = out->args.templ_destroy.template_id
11027 		    + out->args.templ_destroy.template_id_n++;
11028 	if ((uint8_t *)template_id > (uint8_t *)out + size)
11029 		return -1;
11030 	ctx->objdata = 0;
11031 	ctx->object = template_id;
11032 	ctx->objmask = NULL;
11033 	return len;
11034 }
11035 
11036 /** Parse tokens for table create command. */
11037 static int
11038 parse_table(struct context *ctx, const struct token *token,
11039 	    const char *str, unsigned int len,
11040 	    void *buf, unsigned int size)
11041 {
11042 	struct buffer *out = buf;
11043 	uint32_t *template_id;
11044 
11045 	/* Token name must match. */
11046 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11047 		return -1;
11048 	/* Nothing else to do if there is no buffer. */
11049 	if (!out)
11050 		return len;
11051 	if (!out->command) {
11052 		if (ctx->curr != TABLE)
11053 			return -1;
11054 		if (sizeof(*out) > size)
11055 			return -1;
11056 		out->command = ctx->curr;
11057 		ctx->objdata = 0;
11058 		ctx->object = out;
11059 		ctx->objmask = NULL;
11060 		return len;
11061 	}
11062 	switch (ctx->curr) {
11063 	case TABLE_CREATE:
11064 	case TABLE_RESIZE:
11065 		out->command = ctx->curr;
11066 		ctx->objdata = 0;
11067 		ctx->object = out;
11068 		ctx->objmask = NULL;
11069 		out->args.table.id = UINT32_MAX;
11070 		return len;
11071 	case TABLE_PATTERN_TEMPLATE:
11072 		out->args.table.pat_templ_id =
11073 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11074 					       sizeof(double));
11075 		template_id = out->args.table.pat_templ_id
11076 				+ out->args.table.pat_templ_id_n++;
11077 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11078 			return -1;
11079 		ctx->objdata = 0;
11080 		ctx->object = template_id;
11081 		ctx->objmask = NULL;
11082 		return len;
11083 	case TABLE_ACTIONS_TEMPLATE:
11084 		out->args.table.act_templ_id =
11085 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11086 					       (out->args.table.pat_templ_id +
11087 						out->args.table.pat_templ_id_n),
11088 					       sizeof(double));
11089 		template_id = out->args.table.act_templ_id
11090 				+ out->args.table.act_templ_id_n++;
11091 		if ((uint8_t *)template_id > (uint8_t *)out + size)
11092 			return -1;
11093 		ctx->objdata = 0;
11094 		ctx->object = template_id;
11095 		ctx->objmask = NULL;
11096 		return len;
11097 	case TABLE_INGRESS:
11098 		out->args.table.attr.flow_attr.ingress = 1;
11099 		return len;
11100 	case TABLE_EGRESS:
11101 		out->args.table.attr.flow_attr.egress = 1;
11102 		return len;
11103 	case TABLE_TRANSFER:
11104 		out->args.table.attr.flow_attr.transfer = 1;
11105 		return len;
11106 	case TABLE_TRANSFER_WIRE_ORIG:
11107 		if (!out->args.table.attr.flow_attr.transfer)
11108 			return -1;
11109 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
11110 		return len;
11111 	case TABLE_TRANSFER_VPORT_ORIG:
11112 		if (!out->args.table.attr.flow_attr.transfer)
11113 			return -1;
11114 		out->args.table.attr.specialize |= RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
11115 		return len;
11116 	case TABLE_RESIZABLE:
11117 		out->args.table.attr.specialize |=
11118 			RTE_FLOW_TABLE_SPECIALIZE_RESIZABLE;
11119 		return len;
11120 	case TABLE_RULES_NUMBER:
11121 		ctx->objdata = 0;
11122 		ctx->object = out;
11123 		ctx->objmask = NULL;
11124 		return len;
11125 	case TABLE_RESIZE_ID:
11126 	case TABLE_RESIZE_RULES_NUMBER:
11127 		return len;
11128 	default:
11129 		return -1;
11130 	}
11131 }
11132 
11133 /** Parse tokens for table destroy command. */
11134 static int
11135 parse_table_destroy(struct context *ctx, const struct token *token,
11136 		    const char *str, unsigned int len,
11137 		    void *buf, unsigned int size)
11138 {
11139 	struct buffer *out = buf;
11140 	uint32_t *table_id;
11141 
11142 	/* Token name must match. */
11143 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11144 		return -1;
11145 	/* Nothing else to do if there is no buffer. */
11146 	if (!out)
11147 		return len;
11148 	if (!out->command || out->command == TABLE) {
11149 		if (ctx->curr != TABLE_DESTROY &&
11150 		    ctx->curr != TABLE_RESIZE_COMPLETE)
11151 			return -1;
11152 		if (sizeof(*out) > size)
11153 			return -1;
11154 		out->command = ctx->curr;
11155 		ctx->objdata = 0;
11156 		ctx->object = out;
11157 		ctx->objmask = NULL;
11158 		out->args.table_destroy.table_id =
11159 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11160 					       sizeof(double));
11161 		return len;
11162 	}
11163 	table_id = out->args.table_destroy.table_id
11164 		    + out->args.table_destroy.table_id_n++;
11165 	if ((uint8_t *)table_id > (uint8_t *)out + size)
11166 		return -1;
11167 	ctx->objdata = 0;
11168 	ctx->object = table_id;
11169 	ctx->objmask = NULL;
11170 	return len;
11171 }
11172 
11173 /** Parse tokens for queue create commands. */
11174 static int
11175 parse_qo(struct context *ctx, const struct token *token,
11176 	 const char *str, unsigned int len,
11177 	 void *buf, unsigned int size)
11178 {
11179 	struct buffer *out = buf;
11180 
11181 	/* Token name must match. */
11182 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11183 		return -1;
11184 	/* Nothing else to do if there is no buffer. */
11185 	if (!out)
11186 		return len;
11187 	if (!out->command) {
11188 		if (ctx->curr != QUEUE)
11189 			return -1;
11190 		if (sizeof(*out) > size)
11191 			return -1;
11192 		out->command = ctx->curr;
11193 		ctx->objdata = 0;
11194 		ctx->object = out;
11195 		ctx->objmask = NULL;
11196 		out->args.vc.data = (uint8_t *)out + size;
11197 		return len;
11198 	}
11199 	switch (ctx->curr) {
11200 	case QUEUE_CREATE:
11201 	case QUEUE_UPDATE:
11202 		out->command = ctx->curr;
11203 		ctx->objdata = 0;
11204 		ctx->object = out;
11205 		ctx->objmask = NULL;
11206 		out->args.vc.rule_id = UINT32_MAX;
11207 		return len;
11208 	case QUEUE_TEMPLATE_TABLE:
11209 	case QUEUE_PATTERN_TEMPLATE:
11210 	case QUEUE_ACTIONS_TEMPLATE:
11211 	case QUEUE_CREATE_POSTPONE:
11212 	case QUEUE_RULE_ID:
11213 	case QUEUE_UPDATE_ID:
11214 		return len;
11215 	case ITEM_PATTERN:
11216 		out->args.vc.pattern =
11217 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11218 					       sizeof(double));
11219 		ctx->object = out->args.vc.pattern;
11220 		ctx->objmask = NULL;
11221 		return len;
11222 	case ACTIONS:
11223 		out->args.vc.actions =
11224 			(void *)RTE_ALIGN_CEIL((uintptr_t)
11225 					       (out->args.vc.pattern +
11226 						out->args.vc.pattern_n),
11227 					       sizeof(double));
11228 		ctx->object = out->args.vc.actions;
11229 		ctx->objmask = NULL;
11230 		return len;
11231 	default:
11232 		return -1;
11233 	}
11234 }
11235 
11236 /** Parse tokens for queue destroy command. */
11237 static int
11238 parse_qo_destroy(struct context *ctx, const struct token *token,
11239 		 const char *str, unsigned int len,
11240 		 void *buf, unsigned int size)
11241 {
11242 	struct buffer *out = buf;
11243 	uint64_t *flow_id;
11244 
11245 	/* Token name must match. */
11246 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11247 		return -1;
11248 	/* Nothing else to do if there is no buffer. */
11249 	if (!out)
11250 		return len;
11251 	if (!out->command || out->command == QUEUE) {
11252 		if (ctx->curr != QUEUE_DESTROY &&
11253 		    ctx->curr != QUEUE_FLOW_UPDATE_RESIZED)
11254 			return -1;
11255 		if (sizeof(*out) > size)
11256 			return -1;
11257 		out->command = ctx->curr;
11258 		ctx->objdata = 0;
11259 		ctx->object = out;
11260 		ctx->objmask = NULL;
11261 		out->args.destroy.rule =
11262 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11263 					       sizeof(double));
11264 		return len;
11265 	}
11266 	switch (ctx->curr) {
11267 	case QUEUE_DESTROY_ID:
11268 		flow_id = out->args.destroy.rule
11269 				+ out->args.destroy.rule_n++;
11270 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
11271 			return -1;
11272 		ctx->objdata = 0;
11273 		ctx->object = flow_id;
11274 		ctx->objmask = NULL;
11275 		return len;
11276 	case QUEUE_DESTROY_POSTPONE:
11277 		return len;
11278 	default:
11279 		return -1;
11280 	}
11281 }
11282 
11283 /** Parse tokens for push queue command. */
11284 static int
11285 parse_push(struct context *ctx, const struct token *token,
11286 	   const char *str, unsigned int len,
11287 	   void *buf, unsigned int size)
11288 {
11289 	struct buffer *out = buf;
11290 
11291 	/* Token name must match. */
11292 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11293 		return -1;
11294 	/* Nothing else to do if there is no buffer. */
11295 	if (!out)
11296 		return len;
11297 	if (!out->command) {
11298 		if (ctx->curr != PUSH)
11299 			return -1;
11300 		if (sizeof(*out) > size)
11301 			return -1;
11302 		out->command = ctx->curr;
11303 		ctx->objdata = 0;
11304 		ctx->object = out;
11305 		ctx->objmask = NULL;
11306 		out->args.vc.data = (uint8_t *)out + size;
11307 	}
11308 	return len;
11309 }
11310 
11311 /** Parse tokens for pull command. */
11312 static int
11313 parse_pull(struct context *ctx, const struct token *token,
11314 	   const char *str, unsigned int len,
11315 	   void *buf, unsigned int size)
11316 {
11317 	struct buffer *out = buf;
11318 
11319 	/* Token name must match. */
11320 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11321 		return -1;
11322 	/* Nothing else to do if there is no buffer. */
11323 	if (!out)
11324 		return len;
11325 	if (!out->command) {
11326 		if (ctx->curr != PULL)
11327 			return -1;
11328 		if (sizeof(*out) > size)
11329 			return -1;
11330 		out->command = ctx->curr;
11331 		ctx->objdata = 0;
11332 		ctx->object = out;
11333 		ctx->objmask = NULL;
11334 		out->args.vc.data = (uint8_t *)out + size;
11335 	}
11336 	return len;
11337 }
11338 
11339 /** Parse tokens for hash calculation commands. */
11340 static int
11341 parse_hash(struct context *ctx, const struct token *token,
11342 	 const char *str, unsigned int len,
11343 	 void *buf, unsigned int size)
11344 {
11345 	struct buffer *out = buf;
11346 
11347 	/* Token name must match. */
11348 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11349 		return -1;
11350 	/* Nothing else to do if there is no buffer. */
11351 	if (!out)
11352 		return len;
11353 	if (!out->command) {
11354 		if (ctx->curr != HASH)
11355 			return -1;
11356 		if (sizeof(*out) > size)
11357 			return -1;
11358 		out->command = ctx->curr;
11359 		ctx->objdata = 0;
11360 		ctx->object = out;
11361 		ctx->objmask = NULL;
11362 		out->args.vc.data = (uint8_t *)out + size;
11363 		return len;
11364 	}
11365 	switch (ctx->curr) {
11366 	case HASH_CALC_TABLE:
11367 	case HASH_CALC_PATTERN_INDEX:
11368 		return len;
11369 	case ITEM_PATTERN:
11370 		out->args.vc.pattern =
11371 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11372 					       sizeof(double));
11373 		ctx->object = out->args.vc.pattern;
11374 		ctx->objmask = NULL;
11375 		return len;
11376 	case HASH_CALC_ENCAP:
11377 		out->args.vc.encap_hash = 1;
11378 		return len;
11379 	case ENCAP_HASH_FIELD_SRC_PORT:
11380 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
11381 		return len;
11382 	case ENCAP_HASH_FIELD_GRE_FLOW_ID:
11383 		out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
11384 		return len;
11385 	default:
11386 		return -1;
11387 	}
11388 }
11389 
11390 static int
11391 parse_group(struct context *ctx, const struct token *token,
11392 	    const char *str, unsigned int len,
11393 	    void *buf, unsigned int size)
11394 {
11395 	struct buffer *out = buf;
11396 
11397 	/* Token name must match. */
11398 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11399 		return -1;
11400 	/* Nothing else to do if there is no buffer. */
11401 	if (!out)
11402 		return len;
11403 	if (!out->command) {
11404 		if (ctx->curr != FLOW_GROUP)
11405 			return -1;
11406 		if (sizeof(*out) > size)
11407 			return -1;
11408 		out->command = ctx->curr;
11409 		ctx->objdata = 0;
11410 		ctx->object = out;
11411 		ctx->objmask = NULL;
11412 		out->args.vc.data = (uint8_t *)out + size;
11413 		return len;
11414 	}
11415 	switch (ctx->curr) {
11416 	case GROUP_INGRESS:
11417 		out->args.vc.attr.ingress = 1;
11418 		return len;
11419 	case GROUP_EGRESS:
11420 		out->args.vc.attr.egress = 1;
11421 		return len;
11422 	case GROUP_TRANSFER:
11423 		out->args.vc.attr.transfer = 1;
11424 		return len;
11425 	case GROUP_SET_MISS_ACTIONS:
11426 		out->command = ctx->curr;
11427 		ctx->objdata = 0;
11428 		ctx->object = out;
11429 		ctx->objmask = NULL;
11430 		out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
11431 							       sizeof(double));
11432 		return len;
11433 	default:
11434 		return -1;
11435 	}
11436 }
11437 
11438 static int
11439 parse_flex(struct context *ctx, const struct token *token,
11440 	     const char *str, unsigned int len,
11441 	     void *buf, unsigned int size)
11442 {
11443 	struct buffer *out = buf;
11444 
11445 	/* Token name must match. */
11446 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11447 		return -1;
11448 	/* Nothing else to do if there is no buffer. */
11449 	if (!out)
11450 		return len;
11451 	if (out->command == ZERO) {
11452 		if (ctx->curr != FLEX)
11453 			return -1;
11454 		if (sizeof(*out) > size)
11455 			return -1;
11456 		out->command = ctx->curr;
11457 		ctx->objdata = 0;
11458 		ctx->object = out;
11459 		ctx->objmask = NULL;
11460 	} else {
11461 		switch (ctx->curr) {
11462 		default:
11463 			break;
11464 		case FLEX_ITEM_CREATE:
11465 		case FLEX_ITEM_DESTROY:
11466 			out->command = ctx->curr;
11467 			break;
11468 		}
11469 	}
11470 
11471 	return len;
11472 }
11473 
11474 static int
11475 parse_tunnel(struct context *ctx, const struct token *token,
11476 	     const char *str, unsigned int len,
11477 	     void *buf, unsigned int size)
11478 {
11479 	struct buffer *out = buf;
11480 
11481 	/* Token name must match. */
11482 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
11483 		return -1;
11484 	/* Nothing else to do if there is no buffer. */
11485 	if (!out)
11486 		return len;
11487 	if (!out->command) {
11488 		if (ctx->curr != TUNNEL)
11489 			return -1;
11490 		if (sizeof(*out) > size)
11491 			return -1;
11492 		out->command = ctx->curr;
11493 		ctx->objdata = 0;
11494 		ctx->object = out;
11495 		ctx->objmask = NULL;
11496 	} else {
11497 		switch (ctx->curr) {
11498 		default:
11499 			break;
11500 		case TUNNEL_CREATE:
11501 		case TUNNEL_DESTROY:
11502 		case TUNNEL_LIST:
11503 			out->command = ctx->curr;
11504 			break;
11505 		case TUNNEL_CREATE_TYPE:
11506 		case TUNNEL_DESTROY_ID:
11507 			ctx->object = &out->args.vc.tunnel_ops;
11508 			break;
11509 		}
11510 	}
11511 
11512 	return len;
11513 }
11514 
11515 /**
11516  * Parse signed/unsigned integers 8 to 64-bit long.
11517  *
11518  * Last argument (ctx->args) is retrieved to determine integer type and
11519  * storage location.
11520  */
11521 static int
11522 parse_int(struct context *ctx, const struct token *token,
11523 	  const char *str, unsigned int len,
11524 	  void *buf, unsigned int size)
11525 {
11526 	const struct arg *arg = pop_args(ctx);
11527 	uintmax_t u;
11528 	char *end;
11529 
11530 	(void)token;
11531 	/* Argument is expected. */
11532 	if (!arg)
11533 		return -1;
11534 	errno = 0;
11535 	u = arg->sign ?
11536 		(uintmax_t)strtoimax(str, &end, 0) :
11537 		strtoumax(str, &end, 0);
11538 	if (errno || (size_t)(end - str) != len)
11539 		goto error;
11540 	if (arg->bounded &&
11541 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
11542 			    (intmax_t)u > (intmax_t)arg->max)) ||
11543 	     (!arg->sign && (u < arg->min || u > arg->max))))
11544 		goto error;
11545 	if (!ctx->object)
11546 		return len;
11547 	if (arg->mask) {
11548 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
11549 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
11550 			goto error;
11551 		return len;
11552 	}
11553 	buf = (uint8_t *)ctx->object + arg->offset;
11554 	size = arg->size;
11555 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
11556 		return -1;
11557 objmask:
11558 	switch (size) {
11559 	case sizeof(uint8_t):
11560 		*(uint8_t *)buf = u;
11561 		break;
11562 	case sizeof(uint16_t):
11563 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
11564 		break;
11565 	case sizeof(uint8_t [3]):
11566 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
11567 		if (!arg->hton) {
11568 			((uint8_t *)buf)[0] = u;
11569 			((uint8_t *)buf)[1] = u >> 8;
11570 			((uint8_t *)buf)[2] = u >> 16;
11571 			break;
11572 		}
11573 #endif
11574 		((uint8_t *)buf)[0] = u >> 16;
11575 		((uint8_t *)buf)[1] = u >> 8;
11576 		((uint8_t *)buf)[2] = u;
11577 		break;
11578 	case sizeof(uint32_t):
11579 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
11580 		break;
11581 	case sizeof(uint64_t):
11582 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
11583 		break;
11584 	default:
11585 		goto error;
11586 	}
11587 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
11588 		u = -1;
11589 		buf = (uint8_t *)ctx->objmask + arg->offset;
11590 		goto objmask;
11591 	}
11592 	return len;
11593 error:
11594 	push_args(ctx, arg);
11595 	return -1;
11596 }
11597 
11598 /**
11599  * Parse a string.
11600  *
11601  * Three arguments (ctx->args) are retrieved from the stack to store data,
11602  * its actual length and address (in that order).
11603  */
11604 static int
11605 parse_string(struct context *ctx, const struct token *token,
11606 	     const char *str, unsigned int len,
11607 	     void *buf, unsigned int size)
11608 {
11609 	const struct arg *arg_data = pop_args(ctx);
11610 	const struct arg *arg_len = pop_args(ctx);
11611 	const struct arg *arg_addr = pop_args(ctx);
11612 	char tmp[16]; /* Ought to be enough. */
11613 	int ret;
11614 
11615 	/* Arguments are expected. */
11616 	if (!arg_data)
11617 		return -1;
11618 	if (!arg_len) {
11619 		push_args(ctx, arg_data);
11620 		return -1;
11621 	}
11622 	if (!arg_addr) {
11623 		push_args(ctx, arg_len);
11624 		push_args(ctx, arg_data);
11625 		return -1;
11626 	}
11627 	size = arg_data->size;
11628 	/* Bit-mask fill is not supported. */
11629 	if (arg_data->mask || size < len)
11630 		goto error;
11631 	if (!ctx->object)
11632 		return len;
11633 	/* Let parse_int() fill length information first. */
11634 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
11635 	if (ret < 0)
11636 		goto error;
11637 	push_args(ctx, arg_len);
11638 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11639 	if (ret < 0) {
11640 		pop_args(ctx);
11641 		goto error;
11642 	}
11643 	buf = (uint8_t *)ctx->object + arg_data->offset;
11644 	/* Output buffer is not necessarily NUL-terminated. */
11645 	memcpy(buf, str, len);
11646 	memset((uint8_t *)buf + len, 0x00, size - len);
11647 	if (ctx->objmask)
11648 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11649 	/* Save address if requested. */
11650 	if (arg_addr->size) {
11651 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11652 		       (void *[]){
11653 			(uint8_t *)ctx->object + arg_data->offset
11654 		       },
11655 		       arg_addr->size);
11656 		if (ctx->objmask)
11657 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11658 			       (void *[]){
11659 				(uint8_t *)ctx->objmask + arg_data->offset
11660 			       },
11661 			       arg_addr->size);
11662 	}
11663 	return len;
11664 error:
11665 	push_args(ctx, arg_addr);
11666 	push_args(ctx, arg_len);
11667 	push_args(ctx, arg_data);
11668 	return -1;
11669 }
11670 
11671 static int
11672 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
11673 {
11674 	const uint8_t *head = dst;
11675 	uint32_t left;
11676 
11677 	if (*size == 0)
11678 		return -1;
11679 
11680 	left = *size;
11681 
11682 	/* Convert chars to bytes */
11683 	while (left) {
11684 		char tmp[3], *end = tmp;
11685 		uint32_t read_lim = left & 1 ? 1 : 2;
11686 
11687 		snprintf(tmp, read_lim + 1, "%s", src);
11688 		*dst = strtoul(tmp, &end, 16);
11689 		if (*end) {
11690 			*dst = 0;
11691 			*size = (uint32_t)(dst - head);
11692 			return -1;
11693 		}
11694 		left -= read_lim;
11695 		src += read_lim;
11696 		dst++;
11697 	}
11698 	*dst = 0;
11699 	*size = (uint32_t)(dst - head);
11700 	return 0;
11701 }
11702 
11703 static int
11704 parse_hex(struct context *ctx, const struct token *token,
11705 		const char *str, unsigned int len,
11706 		void *buf, unsigned int size)
11707 {
11708 	const struct arg *arg_data = pop_args(ctx);
11709 	const struct arg *arg_len = pop_args(ctx);
11710 	const struct arg *arg_addr = pop_args(ctx);
11711 	char tmp[16]; /* Ought to be enough. */
11712 	int ret;
11713 	unsigned int hexlen = len;
11714 	unsigned int length = 256;
11715 	uint8_t hex_tmp[length];
11716 
11717 	/* Arguments are expected. */
11718 	if (!arg_data)
11719 		return -1;
11720 	if (!arg_len) {
11721 		push_args(ctx, arg_data);
11722 		return -1;
11723 	}
11724 	if (!arg_addr) {
11725 		push_args(ctx, arg_len);
11726 		push_args(ctx, arg_data);
11727 		return -1;
11728 	}
11729 	size = arg_data->size;
11730 	/* Bit-mask fill is not supported. */
11731 	if (arg_data->mask)
11732 		goto error;
11733 	if (!ctx->object)
11734 		return len;
11735 
11736 	/* translate bytes string to array. */
11737 	if (str[0] == '0' && ((str[1] == 'x') ||
11738 			(str[1] == 'X'))) {
11739 		str += 2;
11740 		hexlen -= 2;
11741 	}
11742 	if (hexlen > length)
11743 		goto error;
11744 	ret = parse_hex_string(str, hex_tmp, &hexlen);
11745 	if (ret < 0)
11746 		goto error;
11747 	/* Check the converted binary fits into data buffer. */
11748 	if (hexlen > size)
11749 		goto error;
11750 	/* Let parse_int() fill length information first. */
11751 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
11752 	if (ret < 0)
11753 		goto error;
11754 	/* Save length if requested. */
11755 	if (arg_len->size) {
11756 		push_args(ctx, arg_len);
11757 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
11758 		if (ret < 0) {
11759 			pop_args(ctx);
11760 			goto error;
11761 		}
11762 	}
11763 	buf = (uint8_t *)ctx->object + arg_data->offset;
11764 	/* Output buffer is not necessarily NUL-terminated. */
11765 	memcpy(buf, hex_tmp, hexlen);
11766 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
11767 	if (ctx->objmask)
11768 		memset((uint8_t *)ctx->objmask + arg_data->offset,
11769 					0xff, hexlen);
11770 	/* Save address if requested. */
11771 	if (arg_addr->size) {
11772 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
11773 		       (void *[]){
11774 			(uint8_t *)ctx->object + arg_data->offset
11775 		       },
11776 		       arg_addr->size);
11777 		if (ctx->objmask)
11778 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
11779 			       (void *[]){
11780 				(uint8_t *)ctx->objmask + arg_data->offset
11781 			       },
11782 			       arg_addr->size);
11783 	}
11784 	return len;
11785 error:
11786 	push_args(ctx, arg_addr);
11787 	push_args(ctx, arg_len);
11788 	push_args(ctx, arg_data);
11789 	return -1;
11790 
11791 }
11792 
11793 /**
11794  * Parse a zero-ended string.
11795  */
11796 static int
11797 parse_string0(struct context *ctx, const struct token *token __rte_unused,
11798 	     const char *str, unsigned int len,
11799 	     void *buf, unsigned int size)
11800 {
11801 	const struct arg *arg_data = pop_args(ctx);
11802 
11803 	/* Arguments are expected. */
11804 	if (!arg_data)
11805 		return -1;
11806 	size = arg_data->size;
11807 	/* Bit-mask fill is not supported. */
11808 	if (arg_data->mask || size < len + 1)
11809 		goto error;
11810 	if (!ctx->object)
11811 		return len;
11812 	buf = (uint8_t *)ctx->object + arg_data->offset;
11813 	strncpy(buf, str, len);
11814 	if (ctx->objmask)
11815 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
11816 	return len;
11817 error:
11818 	push_args(ctx, arg_data);
11819 	return -1;
11820 }
11821 
11822 /**
11823  * Parse a MAC address.
11824  *
11825  * Last argument (ctx->args) is retrieved to determine storage size and
11826  * location.
11827  */
11828 static int
11829 parse_mac_addr(struct context *ctx, const struct token *token,
11830 	       const char *str, unsigned int len,
11831 	       void *buf, unsigned int size)
11832 {
11833 	const struct arg *arg = pop_args(ctx);
11834 	struct rte_ether_addr tmp;
11835 	int ret;
11836 
11837 	(void)token;
11838 	/* Argument is expected. */
11839 	if (!arg)
11840 		return -1;
11841 	size = arg->size;
11842 	/* Bit-mask fill is not supported. */
11843 	if (arg->mask || size != sizeof(tmp))
11844 		goto error;
11845 	/* Only network endian is supported. */
11846 	if (!arg->hton)
11847 		goto error;
11848 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
11849 	if (ret < 0 || (unsigned int)ret != len)
11850 		goto error;
11851 	if (!ctx->object)
11852 		return len;
11853 	buf = (uint8_t *)ctx->object + arg->offset;
11854 	memcpy(buf, &tmp, size);
11855 	if (ctx->objmask)
11856 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11857 	return len;
11858 error:
11859 	push_args(ctx, arg);
11860 	return -1;
11861 }
11862 
11863 /**
11864  * Parse an IPv4 address.
11865  *
11866  * Last argument (ctx->args) is retrieved to determine storage size and
11867  * location.
11868  */
11869 static int
11870 parse_ipv4_addr(struct context *ctx, const struct token *token,
11871 		const char *str, unsigned int len,
11872 		void *buf, unsigned int size)
11873 {
11874 	const struct arg *arg = pop_args(ctx);
11875 	char str2[len + 1];
11876 	struct in_addr tmp;
11877 	int ret;
11878 
11879 	/* Argument is expected. */
11880 	if (!arg)
11881 		return -1;
11882 	size = arg->size;
11883 	/* Bit-mask fill is not supported. */
11884 	if (arg->mask || size != sizeof(tmp))
11885 		goto error;
11886 	/* Only network endian is supported. */
11887 	if (!arg->hton)
11888 		goto error;
11889 	memcpy(str2, str, len);
11890 	str2[len] = '\0';
11891 	ret = inet_pton(AF_INET, str2, &tmp);
11892 	if (ret != 1) {
11893 		/* Attempt integer parsing. */
11894 		push_args(ctx, arg);
11895 		return parse_int(ctx, token, str, len, buf, size);
11896 	}
11897 	if (!ctx->object)
11898 		return len;
11899 	buf = (uint8_t *)ctx->object + arg->offset;
11900 	memcpy(buf, &tmp, size);
11901 	if (ctx->objmask)
11902 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11903 	return len;
11904 error:
11905 	push_args(ctx, arg);
11906 	return -1;
11907 }
11908 
11909 /**
11910  * Parse an IPv6 address.
11911  *
11912  * Last argument (ctx->args) is retrieved to determine storage size and
11913  * location.
11914  */
11915 static int
11916 parse_ipv6_addr(struct context *ctx, const struct token *token,
11917 		const char *str, unsigned int len,
11918 		void *buf, unsigned int size)
11919 {
11920 	const struct arg *arg = pop_args(ctx);
11921 	char str2[len + 1];
11922 	struct in6_addr tmp;
11923 	int ret;
11924 
11925 	(void)token;
11926 	/* Argument is expected. */
11927 	if (!arg)
11928 		return -1;
11929 	size = arg->size;
11930 	/* Bit-mask fill is not supported. */
11931 	if (arg->mask || size != sizeof(tmp))
11932 		goto error;
11933 	/* Only network endian is supported. */
11934 	if (!arg->hton)
11935 		goto error;
11936 	memcpy(str2, str, len);
11937 	str2[len] = '\0';
11938 	ret = inet_pton(AF_INET6, str2, &tmp);
11939 	if (ret != 1)
11940 		goto error;
11941 	if (!ctx->object)
11942 		return len;
11943 	buf = (uint8_t *)ctx->object + arg->offset;
11944 	memcpy(buf, &tmp, size);
11945 	if (ctx->objmask)
11946 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
11947 	return len;
11948 error:
11949 	push_args(ctx, arg);
11950 	return -1;
11951 }
11952 
11953 /** Boolean values (even indices stand for false). */
11954 static const char *const boolean_name[] = {
11955 	"0", "1",
11956 	"false", "true",
11957 	"no", "yes",
11958 	"N", "Y",
11959 	"off", "on",
11960 	NULL,
11961 };
11962 
11963 /**
11964  * Parse a boolean value.
11965  *
11966  * Last argument (ctx->args) is retrieved to determine storage size and
11967  * location.
11968  */
11969 static int
11970 parse_boolean(struct context *ctx, const struct token *token,
11971 	      const char *str, unsigned int len,
11972 	      void *buf, unsigned int size)
11973 {
11974 	const struct arg *arg = pop_args(ctx);
11975 	unsigned int i;
11976 	int ret;
11977 
11978 	/* Argument is expected. */
11979 	if (!arg)
11980 		return -1;
11981 	for (i = 0; boolean_name[i]; ++i)
11982 		if (!strcmp_partial(boolean_name[i], str, len))
11983 			break;
11984 	/* Process token as integer. */
11985 	if (boolean_name[i])
11986 		str = i & 1 ? "1" : "0";
11987 	push_args(ctx, arg);
11988 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
11989 	return ret > 0 ? (int)len : ret;
11990 }
11991 
11992 /** Parse port and update context. */
11993 static int
11994 parse_port(struct context *ctx, const struct token *token,
11995 	   const char *str, unsigned int len,
11996 	   void *buf, unsigned int size)
11997 {
11998 	struct buffer *out = &(struct buffer){ .port = 0 };
11999 	int ret;
12000 
12001 	if (buf)
12002 		out = buf;
12003 	else {
12004 		ctx->objdata = 0;
12005 		ctx->object = out;
12006 		ctx->objmask = NULL;
12007 		size = sizeof(*out);
12008 	}
12009 	ret = parse_int(ctx, token, str, len, out, size);
12010 	if (ret >= 0)
12011 		ctx->port = out->port;
12012 	if (!buf)
12013 		ctx->object = NULL;
12014 	return ret;
12015 }
12016 
12017 /** Parse tokens for shared indirect actions. */
12018 static int
12019 parse_ia_port(struct context *ctx, const struct token *token,
12020 	      const char *str, unsigned int len,
12021 	      void *buf, unsigned int size)
12022 {
12023 	struct rte_flow_action *action = ctx->object;
12024 	uint32_t id;
12025 	int ret;
12026 
12027 	(void)buf;
12028 	(void)size;
12029 	ctx->objdata = 0;
12030 	ctx->object = &id;
12031 	ctx->objmask = NULL;
12032 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12033 	ctx->object = action;
12034 	if (ret != (int)len)
12035 		return ret;
12036 	/* set indirect action */
12037 	if (action)
12038 		action->conf = (void *)(uintptr_t)id;
12039 	return ret;
12040 }
12041 
12042 static int
12043 parse_ia_id2ptr(struct context *ctx, const struct token *token,
12044 		const char *str, unsigned int len,
12045 		void *buf, unsigned int size)
12046 {
12047 	struct rte_flow_action *action = ctx->object;
12048 	uint32_t id;
12049 	int ret;
12050 
12051 	(void)buf;
12052 	(void)size;
12053 	ctx->objdata = 0;
12054 	ctx->object = &id;
12055 	ctx->objmask = NULL;
12056 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12057 	ctx->object = action;
12058 	if (ret != (int)len)
12059 		return ret;
12060 	/* set indirect action */
12061 	if (action) {
12062 		portid_t port_id = ctx->port;
12063 		if (ctx->prev == INDIRECT_ACTION_PORT)
12064 			port_id = (portid_t)(uintptr_t)action->conf;
12065 		action->conf = port_action_handle_get_by_id(port_id, id);
12066 		ret = (action->conf) ? ret : -1;
12067 	}
12068 	return ret;
12069 }
12070 
12071 static int
12072 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
12073 		    const char *str, unsigned int len,
12074 		    __rte_unused void *buf, __rte_unused unsigned int size)
12075 {
12076 	struct rte_flow_action *action = ctx->object;
12077 	struct rte_flow_action_indirect_list *action_conf;
12078 	const struct indlst_conf *indlst_conf;
12079 	uint32_t id;
12080 	int ret;
12081 
12082 	ctx->objdata = 0;
12083 	ctx->object = &id;
12084 	ctx->objmask = NULL;
12085 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12086 	ctx->object = action;
12087 	if (ret != (int)len)
12088 		return ret;
12089 
12090 	/* set handle and conf */
12091 	if (action) {
12092 		action_conf = (void *)(uintptr_t)action->conf;
12093 		action_conf->conf = NULL;
12094 		switch (ctx->curr) {
12095 		case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
12096 		action_conf->handle = (typeof(action_conf->handle))
12097 					port_action_handle_get_by_id(ctx->port, id);
12098 			if (!action_conf->handle) {
12099 				printf("no indirect list handle for id %u\n", id);
12100 				return -1;
12101 			}
12102 			break;
12103 		case INDIRECT_LIST_ACTION_ID2PTR_CONF:
12104 			indlst_conf = indirect_action_list_conf_get(id);
12105 			if (!indlst_conf)
12106 				return -1;
12107 			action_conf->conf = (const void **)indlst_conf->conf;
12108 			break;
12109 		default:
12110 			break;
12111 		}
12112 	}
12113 	return ret;
12114 }
12115 
12116 static int
12117 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
12118 		const char *str, unsigned int len,
12119 		void *buf, unsigned int size)
12120 {
12121 	struct rte_flow_action *action = ctx->object;
12122 	struct rte_flow_action_meter_mark *meter;
12123 	struct rte_flow_meter_profile *profile = NULL;
12124 	uint32_t id = 0;
12125 	int ret;
12126 
12127 	(void)buf;
12128 	(void)size;
12129 	ctx->objdata = 0;
12130 	ctx->object = &id;
12131 	ctx->objmask = NULL;
12132 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12133 	ctx->object = action;
12134 	if (ret != (int)len)
12135 		return ret;
12136 	/* set meter profile */
12137 	if (action) {
12138 		meter = (struct rte_flow_action_meter_mark *)
12139 			(uintptr_t)(action->conf);
12140 		profile = port_meter_profile_get_by_id(ctx->port, id);
12141 		meter->profile = profile;
12142 		ret = (profile) ? ret : -1;
12143 	}
12144 	return ret;
12145 }
12146 
12147 static int
12148 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
12149 		const char *str, unsigned int len,
12150 		void *buf, unsigned int size)
12151 {
12152 	struct rte_flow_action *action = ctx->object;
12153 	struct rte_flow_action_meter_mark *meter;
12154 	struct rte_flow_meter_policy *policy = NULL;
12155 	uint32_t id = 0;
12156 	int ret;
12157 
12158 	(void)buf;
12159 	(void)size;
12160 	ctx->objdata = 0;
12161 	ctx->object = &id;
12162 	ctx->objmask = NULL;
12163 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
12164 	ctx->object = action;
12165 	if (ret != (int)len)
12166 		return ret;
12167 	/* set meter policy */
12168 	if (action) {
12169 		meter = (struct rte_flow_action_meter_mark *)
12170 			(uintptr_t)(action->conf);
12171 		policy = port_meter_policy_get_by_id(ctx->port, id);
12172 		meter->policy = policy;
12173 		ret = (policy) ? ret : -1;
12174 	}
12175 	return ret;
12176 }
12177 
12178 /** Parse set command, initialize output buffer for subsequent tokens. */
12179 static int
12180 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
12181 			  const char *str, unsigned int len,
12182 			  void *buf, unsigned int size)
12183 {
12184 	struct buffer *out = buf;
12185 
12186 	/* Token name must match. */
12187 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12188 		return -1;
12189 	/* Nothing else to do if there is no buffer. */
12190 	if (!out)
12191 		return len;
12192 	/* Make sure buffer is large enough. */
12193 	if (size < sizeof(*out))
12194 		return -1;
12195 	ctx->objdata = 0;
12196 	ctx->objmask = NULL;
12197 	ctx->object = out;
12198 	if (!out->command)
12199 		return -1;
12200 	out->command = ctx->curr;
12201 	/* For encap/decap we need is pattern */
12202 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12203 						       sizeof(double));
12204 	return len;
12205 }
12206 
12207 /** Parse set command, initialize output buffer for subsequent tokens. */
12208 static int
12209 parse_set_sample_action(struct context *ctx, const struct token *token,
12210 			  const char *str, unsigned int len,
12211 			  void *buf, unsigned int size)
12212 {
12213 	struct buffer *out = buf;
12214 
12215 	/* Token name must match. */
12216 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12217 		return -1;
12218 	/* Nothing else to do if there is no buffer. */
12219 	if (!out)
12220 		return len;
12221 	/* Make sure buffer is large enough. */
12222 	if (size < sizeof(*out))
12223 		return -1;
12224 	ctx->objdata = 0;
12225 	ctx->objmask = NULL;
12226 	ctx->object = out;
12227 	if (!out->command)
12228 		return -1;
12229 	out->command = ctx->curr;
12230 	/* For sampler we need is actions */
12231 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12232 						       sizeof(double));
12233 	return len;
12234 }
12235 
12236 /** Parse set command, initialize output buffer for subsequent tokens. */
12237 static int
12238 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token,
12239 			  const char *str, unsigned int len,
12240 			  void *buf, unsigned int size)
12241 {
12242 	struct buffer *out = buf;
12243 
12244 	/* Token name must match. */
12245 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12246 		return -1;
12247 	/* Nothing else to do if there is no buffer. */
12248 	if (!out)
12249 		return len;
12250 	/* Make sure buffer is large enough. */
12251 	if (size < sizeof(*out))
12252 		return -1;
12253 	ctx->objdata = 0;
12254 	ctx->objmask = NULL;
12255 	ctx->object = out;
12256 	if (!out->command)
12257 		return -1;
12258 	out->command = ctx->curr;
12259 	/* For ipv6_ext_push/remove we need is pattern */
12260 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12261 						       sizeof(double));
12262 	return len;
12263 }
12264 
12265 /**
12266  * Parse set raw_encap/raw_decap command,
12267  * initialize output buffer for subsequent tokens.
12268  */
12269 static int
12270 parse_set_init(struct context *ctx, const struct token *token,
12271 	       const char *str, unsigned int len,
12272 	       void *buf, unsigned int size)
12273 {
12274 	struct buffer *out = buf;
12275 
12276 	/* Token name must match. */
12277 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
12278 		return -1;
12279 	/* Nothing else to do if there is no buffer. */
12280 	if (!out)
12281 		return len;
12282 	/* Make sure buffer is large enough. */
12283 	if (size < sizeof(*out))
12284 		return -1;
12285 	/* Initialize buffer. */
12286 	memset(out, 0x00, sizeof(*out));
12287 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
12288 	ctx->objdata = 0;
12289 	ctx->object = out;
12290 	ctx->objmask = NULL;
12291 	if (!out->command) {
12292 		if (ctx->curr != SET)
12293 			return -1;
12294 		if (sizeof(*out) > size)
12295 			return -1;
12296 		out->command = ctx->curr;
12297 		out->args.vc.data = (uint8_t *)out + size;
12298 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
12299 						       sizeof(double));
12300 	}
12301 	return len;
12302 }
12303 
12304 /*
12305  * Replace testpmd handles in a flex flow item with real values.
12306  */
12307 static int
12308 parse_flex_handle(struct context *ctx, const struct token *token,
12309 		  const char *str, unsigned int len,
12310 		  void *buf, unsigned int size)
12311 {
12312 	struct rte_flow_item_flex *spec, *mask;
12313 	const struct rte_flow_item_flex *src_spec, *src_mask;
12314 	const struct arg *arg = pop_args(ctx);
12315 	uint32_t offset;
12316 	uint16_t handle;
12317 	int ret;
12318 
12319 	if (!arg) {
12320 		printf("Bad environment\n");
12321 		return -1;
12322 	}
12323 	offset = arg->offset;
12324 	push_args(ctx, arg);
12325 	ret = parse_int(ctx, token, str, len, buf, size);
12326 	if (ret <= 0 || !ctx->object)
12327 		return ret;
12328 	if (ctx->port >= RTE_MAX_ETHPORTS) {
12329 		printf("Bad port\n");
12330 		return -1;
12331 	}
12332 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
12333 		const struct flex_item *fp;
12334 		spec = ctx->object;
12335 		handle = (uint16_t)(uintptr_t)spec->handle;
12336 		if (handle >= FLEX_MAX_PARSERS_NUM) {
12337 			printf("Bad flex item handle\n");
12338 			return -1;
12339 		}
12340 		fp = flex_items[ctx->port][handle];
12341 		if (!fp) {
12342 			printf("Bad flex item handle\n");
12343 			return -1;
12344 		}
12345 		spec->handle = fp->flex_handle;
12346 		mask = spec + 2; /* spec, last, mask */
12347 		mask->handle = fp->flex_handle;
12348 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
12349 		handle = (uint16_t)(uintptr_t)
12350 			((struct rte_flow_item_flex *)ctx->object)->pattern;
12351 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
12352 			printf("Bad pattern handle\n");
12353 			return -1;
12354 		}
12355 		src_spec = &flex_patterns[handle].spec;
12356 		src_mask = &flex_patterns[handle].mask;
12357 		spec = ctx->object;
12358 		mask = spec + 2; /* spec, last, mask */
12359 		/* fill flow rule spec and mask parameters */
12360 		spec->length = src_spec->length;
12361 		spec->pattern = src_spec->pattern;
12362 		mask->length = src_mask->length;
12363 		mask->pattern = src_mask->pattern;
12364 	} else {
12365 		printf("Bad arguments - unknown flex item offset\n");
12366 		return -1;
12367 	}
12368 	return ret;
12369 }
12370 
12371 /** Parse Meter color name */
12372 static int
12373 parse_meter_color(struct context *ctx, const struct token *token,
12374 		  const char *str, unsigned int len, void *buf,
12375 		  unsigned int size)
12376 {
12377 	struct rte_flow_item_meter_color *meter_color;
12378 	unsigned int i;
12379 
12380 	(void)token;
12381 	(void)buf;
12382 	(void)size;
12383 	for (i = 0; meter_colors[i]; ++i)
12384 		if (!strcmp_partial(meter_colors[i], str, len))
12385 			break;
12386 	if (!meter_colors[i])
12387 		return -1;
12388 	if (!ctx->object)
12389 		return len;
12390 	meter_color = ctx->object;
12391 	meter_color->color = (enum rte_color)i;
12392 	return len;
12393 }
12394 
12395 /** Parse Insertion Table Type name */
12396 static int
12397 parse_insertion_table_type(struct context *ctx, const struct token *token,
12398 			   const char *str, unsigned int len, void *buf,
12399 			   unsigned int size)
12400 {
12401 	const struct arg *arg = pop_args(ctx);
12402 	unsigned int i;
12403 	char tmp[2];
12404 	int ret;
12405 
12406 	(void)size;
12407 	/* Argument is expected. */
12408 	if (!arg)
12409 		return -1;
12410 	for (i = 0; table_insertion_types[i]; ++i)
12411 		if (!strcmp_partial(table_insertion_types[i], str, len))
12412 			break;
12413 	if (!table_insertion_types[i])
12414 		return -1;
12415 	push_args(ctx, arg);
12416 	snprintf(tmp, sizeof(tmp), "%u", i);
12417 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12418 	return ret > 0 ? (int)len : ret;
12419 }
12420 
12421 /** Parse Hash Calculation Table Type name */
12422 static int
12423 parse_hash_table_type(struct context *ctx, const struct token *token,
12424 		      const char *str, unsigned int len, void *buf,
12425 		      unsigned int size)
12426 {
12427 	const struct arg *arg = pop_args(ctx);
12428 	unsigned int i;
12429 	char tmp[2];
12430 	int ret;
12431 
12432 	(void)size;
12433 	/* Argument is expected. */
12434 	if (!arg)
12435 		return -1;
12436 	for (i = 0; table_hash_funcs[i]; ++i)
12437 		if (!strcmp_partial(table_hash_funcs[i], str, len))
12438 			break;
12439 	if (!table_hash_funcs[i])
12440 		return -1;
12441 	push_args(ctx, arg);
12442 	snprintf(tmp, sizeof(tmp), "%u", i);
12443 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
12444 	return ret > 0 ? (int)len : ret;
12445 }
12446 
12447 static int
12448 parse_name_to_index(struct context *ctx, const struct token *token,
12449 		    const char *str, unsigned int len, void *buf,
12450 		    unsigned int size,
12451 		    const char *const names[], size_t names_size, uint32_t *dst)
12452 {
12453 	int ret;
12454 	uint32_t i;
12455 
12456 	RTE_SET_USED(token);
12457 	RTE_SET_USED(buf);
12458 	RTE_SET_USED(size);
12459 	if (!ctx->object)
12460 		return len;
12461 	for (i = 0; i < names_size; i++) {
12462 		if (!names[i])
12463 			continue;
12464 		ret = strcmp_partial(names[i], str,
12465 				     RTE_MIN(len, strlen(names[i])));
12466 		if (!ret) {
12467 			*dst = i;
12468 			return len;
12469 		}
12470 	}
12471 	return -1;
12472 }
12473 
12474 static const char *const quota_mode_names[] = {
12475 	NULL,
12476 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
12477 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
12478 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
12479 };
12480 
12481 static const char *const quota_state_names[] = {
12482 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
12483 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
12484 };
12485 
12486 static const char *const quota_update_names[] = {
12487 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
12488 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
12489 };
12490 
12491 static const char *const query_update_mode_names[] = {
12492 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
12493 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
12494 };
12495 
12496 static int
12497 parse_quota_state_name(struct context *ctx, const struct token *token,
12498 		       const char *str, unsigned int len, void *buf,
12499 		       unsigned int size)
12500 {
12501 	struct rte_flow_item_quota *quota = ctx->object;
12502 
12503 	return parse_name_to_index(ctx, token, str, len, buf, size,
12504 				   quota_state_names,
12505 				   RTE_DIM(quota_state_names),
12506 				   (uint32_t *)&quota->state);
12507 }
12508 
12509 static int
12510 parse_quota_mode_name(struct context *ctx, const struct token *token,
12511 		      const char *str, unsigned int len, void *buf,
12512 		      unsigned int size)
12513 {
12514 	struct rte_flow_action_quota *quota = ctx->object;
12515 
12516 	return parse_name_to_index(ctx, token, str, len, buf, size,
12517 				   quota_mode_names,
12518 				   RTE_DIM(quota_mode_names),
12519 				   (uint32_t *)&quota->mode);
12520 }
12521 
12522 static int
12523 parse_quota_update_name(struct context *ctx, const struct token *token,
12524 			const char *str, unsigned int len, void *buf,
12525 			unsigned int size)
12526 {
12527 	struct rte_flow_update_quota *update = ctx->object;
12528 
12529 	return parse_name_to_index(ctx, token, str, len, buf, size,
12530 				   quota_update_names,
12531 				   RTE_DIM(quota_update_names),
12532 				   (uint32_t *)&update->op);
12533 }
12534 
12535 static int
12536 parse_qu_mode_name(struct context *ctx, const struct token *token,
12537 		   const char *str, unsigned int len, void *buf,
12538 		   unsigned int size)
12539 {
12540 	struct buffer *out = ctx->object;
12541 
12542 	return parse_name_to_index(ctx, token, str, len, buf, size,
12543 				   query_update_mode_names,
12544 				   RTE_DIM(query_update_mode_names),
12545 				   (uint32_t *)&out->args.ia.qu_mode);
12546 }
12547 
12548 /** No completion. */
12549 static int
12550 comp_none(struct context *ctx, const struct token *token,
12551 	  unsigned int ent, char *buf, unsigned int size)
12552 {
12553 	(void)ctx;
12554 	(void)token;
12555 	(void)ent;
12556 	(void)buf;
12557 	(void)size;
12558 	return 0;
12559 }
12560 
12561 /** Complete boolean values. */
12562 static int
12563 comp_boolean(struct context *ctx, const struct token *token,
12564 	     unsigned int ent, char *buf, unsigned int size)
12565 {
12566 	unsigned int i;
12567 
12568 	(void)ctx;
12569 	(void)token;
12570 	for (i = 0; boolean_name[i]; ++i)
12571 		if (buf && i == ent)
12572 			return strlcpy(buf, boolean_name[i], size);
12573 	if (buf)
12574 		return -1;
12575 	return i;
12576 }
12577 
12578 /** Complete action names. */
12579 static int
12580 comp_action(struct context *ctx, const struct token *token,
12581 	    unsigned int ent, char *buf, unsigned int size)
12582 {
12583 	unsigned int i;
12584 
12585 	(void)ctx;
12586 	(void)token;
12587 	for (i = 0; next_action[i]; ++i)
12588 		if (buf && i == ent)
12589 			return strlcpy(buf, token_list[next_action[i]].name,
12590 				       size);
12591 	if (buf)
12592 		return -1;
12593 	return i;
12594 }
12595 
12596 /** Complete available ports. */
12597 static int
12598 comp_port(struct context *ctx, const struct token *token,
12599 	  unsigned int ent, char *buf, unsigned int size)
12600 {
12601 	unsigned int i = 0;
12602 	portid_t p;
12603 
12604 	(void)ctx;
12605 	(void)token;
12606 	RTE_ETH_FOREACH_DEV(p) {
12607 		if (buf && i == ent)
12608 			return snprintf(buf, size, "%u", p);
12609 		++i;
12610 	}
12611 	if (buf)
12612 		return -1;
12613 	return i;
12614 }
12615 
12616 /** Complete available rule IDs. */
12617 static int
12618 comp_rule_id(struct context *ctx, const struct token *token,
12619 	     unsigned int ent, char *buf, unsigned int size)
12620 {
12621 	unsigned int i = 0;
12622 	struct rte_port *port;
12623 	struct port_flow *pf;
12624 
12625 	(void)token;
12626 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12627 	    ctx->port == (portid_t)RTE_PORT_ALL)
12628 		return -1;
12629 	port = &ports[ctx->port];
12630 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
12631 		if (buf && i == ent)
12632 			return snprintf(buf, size, "%"PRIu64, pf->id);
12633 		++i;
12634 	}
12635 	if (buf)
12636 		return -1;
12637 	return i;
12638 }
12639 
12640 /** Complete operation for compare match item. */
12641 static int
12642 comp_set_compare_op(struct context *ctx, const struct token *token,
12643 		    unsigned int ent, char *buf, unsigned int size)
12644 {
12645 	RTE_SET_USED(ctx);
12646 	RTE_SET_USED(token);
12647 	if (!buf)
12648 		return RTE_DIM(compare_ops);
12649 	if (ent < RTE_DIM(compare_ops) - 1)
12650 		return strlcpy(buf, compare_ops[ent], size);
12651 	return -1;
12652 }
12653 
12654 /** Complete field id for compare match item. */
12655 static int
12656 comp_set_compare_field_id(struct context *ctx, const struct token *token,
12657 			  unsigned int ent, char *buf, unsigned int size)
12658 {
12659 	const char *name;
12660 
12661 	RTE_SET_USED(token);
12662 	if (!buf)
12663 		return RTE_DIM(flow_field_ids);
12664 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12665 		return -1;
12666 	name = flow_field_ids[ent];
12667 	if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE ||
12668 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12669 		return strlcpy(buf, name, size);
12670 	return -1;
12671 }
12672 
12673 /** Complete type field for RSS action. */
12674 static int
12675 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
12676 			unsigned int ent, char *buf, unsigned int size)
12677 {
12678 	unsigned int i;
12679 
12680 	(void)ctx;
12681 	(void)token;
12682 	for (i = 0; rss_type_table[i].str; ++i)
12683 		;
12684 	if (!buf)
12685 		return i + 1;
12686 	if (ent < i)
12687 		return strlcpy(buf, rss_type_table[ent].str, size);
12688 	if (ent == i)
12689 		return snprintf(buf, size, "end");
12690 	return -1;
12691 }
12692 
12693 /** Complete queue field for RSS action. */
12694 static int
12695 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
12696 			 unsigned int ent, char *buf, unsigned int size)
12697 {
12698 	(void)ctx;
12699 	(void)token;
12700 	if (!buf)
12701 		return nb_rxq + 1;
12702 	if (ent < nb_rxq)
12703 		return snprintf(buf, size, "%u", ent);
12704 	if (ent == nb_rxq)
12705 		return snprintf(buf, size, "end");
12706 	return -1;
12707 }
12708 
12709 /** Complete index number for set raw_encap/raw_decap commands. */
12710 static int
12711 comp_set_raw_index(struct context *ctx, const struct token *token,
12712 		   unsigned int ent, char *buf, unsigned int size)
12713 {
12714 	uint16_t idx = 0;
12715 	uint16_t nb = 0;
12716 
12717 	RTE_SET_USED(ctx);
12718 	RTE_SET_USED(token);
12719 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
12720 		if (buf && idx == ent)
12721 			return snprintf(buf, size, "%u", idx);
12722 		++nb;
12723 	}
12724 	return nb;
12725 }
12726 
12727 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */
12728 static int
12729 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token,
12730 			unsigned int ent, char *buf, unsigned int size)
12731 {
12732 	uint16_t idx = 0;
12733 	uint16_t nb = 0;
12734 
12735 	RTE_SET_USED(ctx);
12736 	RTE_SET_USED(token);
12737 	for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) {
12738 		if (buf && idx == ent)
12739 			return snprintf(buf, size, "%u", idx);
12740 		++nb;
12741 	}
12742 	return nb;
12743 }
12744 
12745 /** Complete index number for set raw_encap/raw_decap commands. */
12746 static int
12747 comp_set_sample_index(struct context *ctx, const struct token *token,
12748 		   unsigned int ent, char *buf, unsigned int size)
12749 {
12750 	uint16_t idx = 0;
12751 	uint16_t nb = 0;
12752 
12753 	RTE_SET_USED(ctx);
12754 	RTE_SET_USED(token);
12755 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
12756 		if (buf && idx == ent)
12757 			return snprintf(buf, size, "%u", idx);
12758 		++nb;
12759 	}
12760 	return nb;
12761 }
12762 
12763 /** Complete operation for modify_field command. */
12764 static int
12765 comp_set_modify_field_op(struct context *ctx, const struct token *token,
12766 		   unsigned int ent, char *buf, unsigned int size)
12767 {
12768 	RTE_SET_USED(ctx);
12769 	RTE_SET_USED(token);
12770 	if (!buf)
12771 		return RTE_DIM(modify_field_ops);
12772 	if (ent < RTE_DIM(modify_field_ops) - 1)
12773 		return strlcpy(buf, modify_field_ops[ent], size);
12774 	return -1;
12775 }
12776 
12777 /** Complete field id for modify_field command. */
12778 static int
12779 comp_set_modify_field_id(struct context *ctx, const struct token *token,
12780 		   unsigned int ent, char *buf, unsigned int size)
12781 {
12782 	const char *name;
12783 
12784 	RTE_SET_USED(token);
12785 	if (!buf)
12786 		return RTE_DIM(flow_field_ids);
12787 	if (ent >= RTE_DIM(flow_field_ids) - 1)
12788 		return -1;
12789 	name = flow_field_ids[ent];
12790 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
12791 	    (strcmp(name, "pointer") && strcmp(name, "value")))
12792 		return strlcpy(buf, name, size);
12793 	return -1;
12794 }
12795 
12796 /** Complete available pattern template IDs. */
12797 static int
12798 comp_pattern_template_id(struct context *ctx, const struct token *token,
12799 			 unsigned int ent, char *buf, unsigned int size)
12800 {
12801 	unsigned int i = 0;
12802 	struct rte_port *port;
12803 	struct port_template *pt;
12804 
12805 	(void)token;
12806 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12807 	    ctx->port == (portid_t)RTE_PORT_ALL)
12808 		return -1;
12809 	port = &ports[ctx->port];
12810 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
12811 		if (buf && i == ent)
12812 			return snprintf(buf, size, "%u", pt->id);
12813 		++i;
12814 	}
12815 	if (buf)
12816 		return -1;
12817 	return i;
12818 }
12819 
12820 /** Complete available actions template IDs. */
12821 static int
12822 comp_actions_template_id(struct context *ctx, const struct token *token,
12823 			 unsigned int ent, char *buf, unsigned int size)
12824 {
12825 	unsigned int i = 0;
12826 	struct rte_port *port;
12827 	struct port_template *pt;
12828 
12829 	(void)token;
12830 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12831 	    ctx->port == (portid_t)RTE_PORT_ALL)
12832 		return -1;
12833 	port = &ports[ctx->port];
12834 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
12835 		if (buf && i == ent)
12836 			return snprintf(buf, size, "%u", pt->id);
12837 		++i;
12838 	}
12839 	if (buf)
12840 		return -1;
12841 	return i;
12842 }
12843 
12844 /** Complete available table IDs. */
12845 static int
12846 comp_table_id(struct context *ctx, const struct token *token,
12847 	      unsigned int ent, char *buf, unsigned int size)
12848 {
12849 	unsigned int i = 0;
12850 	struct rte_port *port;
12851 	struct port_table *pt;
12852 
12853 	(void)token;
12854 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12855 	    ctx->port == (portid_t)RTE_PORT_ALL)
12856 		return -1;
12857 	port = &ports[ctx->port];
12858 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
12859 		if (buf && i == ent)
12860 			return snprintf(buf, size, "%u", pt->id);
12861 		++i;
12862 	}
12863 	if (buf)
12864 		return -1;
12865 	return i;
12866 }
12867 
12868 /** Complete available queue IDs. */
12869 static int
12870 comp_queue_id(struct context *ctx, const struct token *token,
12871 	      unsigned int ent, char *buf, unsigned int size)
12872 {
12873 	unsigned int i = 0;
12874 	struct rte_port *port;
12875 
12876 	(void)token;
12877 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
12878 	    ctx->port == (portid_t)RTE_PORT_ALL)
12879 		return -1;
12880 	port = &ports[ctx->port];
12881 	for (i = 0; i < port->queue_nb; i++) {
12882 		if (buf && i == ent)
12883 			return snprintf(buf, size, "%u", i);
12884 	}
12885 	if (buf)
12886 		return -1;
12887 	return i;
12888 }
12889 
12890 static int
12891 comp_names_to_index(struct context *ctx, const struct token *token,
12892 		    unsigned int ent, char *buf, unsigned int size,
12893 		    const char *const names[], size_t names_size)
12894 {
12895 	RTE_SET_USED(ctx);
12896 	RTE_SET_USED(token);
12897 	if (!buf)
12898 		return names_size;
12899 	if (names[ent] && ent < names_size)
12900 		return rte_strscpy(buf, names[ent], size);
12901 	return -1;
12902 
12903 }
12904 
12905 /** Complete available Meter colors. */
12906 static int
12907 comp_meter_color(struct context *ctx, const struct token *token,
12908 		 unsigned int ent, char *buf, unsigned int size)
12909 {
12910 	RTE_SET_USED(ctx);
12911 	RTE_SET_USED(token);
12912 	if (!buf)
12913 		return RTE_DIM(meter_colors);
12914 	if (ent < RTE_DIM(meter_colors) - 1)
12915 		return strlcpy(buf, meter_colors[ent], size);
12916 	return -1;
12917 }
12918 
12919 /** Complete available Insertion Table types. */
12920 static int
12921 comp_insertion_table_type(struct context *ctx, const struct token *token,
12922 			  unsigned int ent, char *buf, unsigned int size)
12923 {
12924 	RTE_SET_USED(ctx);
12925 	RTE_SET_USED(token);
12926 	if (!buf)
12927 		return RTE_DIM(table_insertion_types);
12928 	if (ent < RTE_DIM(table_insertion_types) - 1)
12929 		return rte_strscpy(buf, table_insertion_types[ent], size);
12930 	return -1;
12931 }
12932 
12933 /** Complete available Hash Calculation Table types. */
12934 static int
12935 comp_hash_table_type(struct context *ctx, const struct token *token,
12936 		     unsigned int ent, char *buf, unsigned int size)
12937 {
12938 	RTE_SET_USED(ctx);
12939 	RTE_SET_USED(token);
12940 	if (!buf)
12941 		return RTE_DIM(table_hash_funcs);
12942 	if (ent < RTE_DIM(table_hash_funcs) - 1)
12943 		return rte_strscpy(buf, table_hash_funcs[ent], size);
12944 	return -1;
12945 }
12946 
12947 static int
12948 comp_quota_state_name(struct context *ctx, const struct token *token,
12949 		      unsigned int ent, char *buf, unsigned int size)
12950 {
12951 	return comp_names_to_index(ctx, token, ent, buf, size,
12952 				   quota_state_names,
12953 				   RTE_DIM(quota_state_names));
12954 }
12955 
12956 static int
12957 comp_quota_mode_name(struct context *ctx, const struct token *token,
12958 		     unsigned int ent, char *buf, unsigned int size)
12959 {
12960 	return comp_names_to_index(ctx, token, ent, buf, size,
12961 				   quota_mode_names,
12962 				   RTE_DIM(quota_mode_names));
12963 }
12964 
12965 static int
12966 comp_quota_update_name(struct context *ctx, const struct token *token,
12967 		       unsigned int ent, char *buf, unsigned int size)
12968 {
12969 	return comp_names_to_index(ctx, token, ent, buf, size,
12970 				   quota_update_names,
12971 				   RTE_DIM(quota_update_names));
12972 }
12973 
12974 static int
12975 comp_qu_mode_name(struct context *ctx, const struct token *token,
12976 		  unsigned int ent, char *buf, unsigned int size)
12977 {
12978 	return comp_names_to_index(ctx, token, ent, buf, size,
12979 				   query_update_mode_names,
12980 				   RTE_DIM(query_update_mode_names));
12981 }
12982 
12983 /** Internal context. */
12984 static struct context cmd_flow_context;
12985 
12986 /** Global parser instance (cmdline API). */
12987 cmdline_parse_inst_t cmd_flow;
12988 cmdline_parse_inst_t cmd_set_raw;
12989 
12990 /** Initialize context. */
12991 static void
12992 cmd_flow_context_init(struct context *ctx)
12993 {
12994 	/* A full memset() is not necessary. */
12995 	ctx->curr = ZERO;
12996 	ctx->prev = ZERO;
12997 	ctx->next_num = 0;
12998 	ctx->args_num = 0;
12999 	ctx->eol = 0;
13000 	ctx->last = 0;
13001 	ctx->port = 0;
13002 	ctx->objdata = 0;
13003 	ctx->object = NULL;
13004 	ctx->objmask = NULL;
13005 }
13006 
13007 /** Parse a token (cmdline API). */
13008 static int
13009 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
13010 	       unsigned int size)
13011 {
13012 	struct context *ctx = &cmd_flow_context;
13013 	const struct token *token;
13014 	const enum index *list;
13015 	int len;
13016 	int i;
13017 
13018 	(void)hdr;
13019 	token = &token_list[ctx->curr];
13020 	/* Check argument length. */
13021 	ctx->eol = 0;
13022 	ctx->last = 1;
13023 	for (len = 0; src[len]; ++len)
13024 		if (src[len] == '#' || isspace(src[len]))
13025 			break;
13026 	if (!len)
13027 		return -1;
13028 	/* Last argument and EOL detection. */
13029 	for (i = len; src[i]; ++i)
13030 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
13031 			break;
13032 		else if (!isspace(src[i])) {
13033 			ctx->last = 0;
13034 			break;
13035 		}
13036 	for (; src[i]; ++i)
13037 		if (src[i] == '\r' || src[i] == '\n') {
13038 			ctx->eol = 1;
13039 			break;
13040 		}
13041 	/* Initialize context if necessary. */
13042 	if (!ctx->next_num) {
13043 		if (!token->next)
13044 			return 0;
13045 		ctx->next[ctx->next_num++] = token->next[0];
13046 	}
13047 	/* Process argument through candidates. */
13048 	ctx->prev = ctx->curr;
13049 	list = ctx->next[ctx->next_num - 1];
13050 	for (i = 0; list[i]; ++i) {
13051 		const struct token *next = &token_list[list[i]];
13052 		int tmp;
13053 
13054 		ctx->curr = list[i];
13055 		if (next->call)
13056 			tmp = next->call(ctx, next, src, len, result, size);
13057 		else
13058 			tmp = parse_default(ctx, next, src, len, result, size);
13059 		if (tmp == -1 || tmp != len)
13060 			continue;
13061 		token = next;
13062 		break;
13063 	}
13064 	if (!list[i])
13065 		return -1;
13066 	--ctx->next_num;
13067 	/* Push subsequent tokens if any. */
13068 	if (token->next)
13069 		for (i = 0; token->next[i]; ++i) {
13070 			if (ctx->next_num == RTE_DIM(ctx->next))
13071 				return -1;
13072 			ctx->next[ctx->next_num++] = token->next[i];
13073 		}
13074 	/* Push arguments if any. */
13075 	if (token->args)
13076 		for (i = 0; token->args[i]; ++i) {
13077 			if (ctx->args_num == RTE_DIM(ctx->args))
13078 				return -1;
13079 			ctx->args[ctx->args_num++] = token->args[i];
13080 		}
13081 	return len;
13082 }
13083 
13084 int
13085 flow_parse(const char *src, void *result, unsigned int size,
13086 	   struct rte_flow_attr **attr,
13087 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
13088 {
13089 	int ret;
13090 	struct context saved_flow_ctx = cmd_flow_context;
13091 
13092 	cmd_flow_context_init(&cmd_flow_context);
13093 	do {
13094 		ret = cmd_flow_parse(NULL, src, result, size);
13095 		if (ret > 0) {
13096 			src += ret;
13097 			while (isspace(*src))
13098 				src++;
13099 		}
13100 	} while (ret > 0 && strlen(src));
13101 	cmd_flow_context = saved_flow_ctx;
13102 	*attr = &((struct buffer *)result)->args.vc.attr;
13103 	*pattern = ((struct buffer *)result)->args.vc.pattern;
13104 	*actions = ((struct buffer *)result)->args.vc.actions;
13105 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
13106 }
13107 
13108 /** Return number of completion entries (cmdline API). */
13109 static int
13110 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
13111 {
13112 	struct context *ctx = &cmd_flow_context;
13113 	const struct token *token = &token_list[ctx->curr];
13114 	const enum index *list;
13115 	int i;
13116 
13117 	(void)hdr;
13118 	/* Count number of tokens in current list. */
13119 	if (ctx->next_num)
13120 		list = ctx->next[ctx->next_num - 1];
13121 	else
13122 		list = token->next[0];
13123 	for (i = 0; list[i]; ++i)
13124 		;
13125 	if (!i)
13126 		return 0;
13127 	/*
13128 	 * If there is a single token, use its completion callback, otherwise
13129 	 * return the number of entries.
13130 	 */
13131 	token = &token_list[list[0]];
13132 	if (i == 1 && token->comp) {
13133 		/* Save index for cmd_flow_get_help(). */
13134 		ctx->prev = list[0];
13135 		return token->comp(ctx, token, 0, NULL, 0);
13136 	}
13137 	return i;
13138 }
13139 
13140 /** Return a completion entry (cmdline API). */
13141 static int
13142 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
13143 			  char *dst, unsigned int size)
13144 {
13145 	struct context *ctx = &cmd_flow_context;
13146 	const struct token *token = &token_list[ctx->curr];
13147 	const enum index *list;
13148 	int i;
13149 
13150 	(void)hdr;
13151 	/* Count number of tokens in current list. */
13152 	if (ctx->next_num)
13153 		list = ctx->next[ctx->next_num - 1];
13154 	else
13155 		list = token->next[0];
13156 	for (i = 0; list[i]; ++i)
13157 		;
13158 	if (!i)
13159 		return -1;
13160 	/* If there is a single token, use its completion callback. */
13161 	token = &token_list[list[0]];
13162 	if (i == 1 && token->comp) {
13163 		/* Save index for cmd_flow_get_help(). */
13164 		ctx->prev = list[0];
13165 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
13166 	}
13167 	/* Otherwise make sure the index is valid and use defaults. */
13168 	if (index >= i)
13169 		return -1;
13170 	token = &token_list[list[index]];
13171 	strlcpy(dst, token->name, size);
13172 	/* Save index for cmd_flow_get_help(). */
13173 	ctx->prev = list[index];
13174 	return 0;
13175 }
13176 
13177 /** Populate help strings for current token (cmdline API). */
13178 static int
13179 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
13180 {
13181 	struct context *ctx = &cmd_flow_context;
13182 	const struct token *token = &token_list[ctx->prev];
13183 
13184 	(void)hdr;
13185 	if (!size)
13186 		return -1;
13187 	/* Set token type and update global help with details. */
13188 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
13189 	if (token->help)
13190 		cmd_flow.help_str = token->help;
13191 	else
13192 		cmd_flow.help_str = token->name;
13193 	return 0;
13194 }
13195 
13196 /** Token definition template (cmdline API). */
13197 static struct cmdline_token_hdr cmd_flow_token_hdr = {
13198 	.ops = &(struct cmdline_token_ops){
13199 		.parse = cmd_flow_parse,
13200 		.complete_get_nb = cmd_flow_complete_get_nb,
13201 		.complete_get_elt = cmd_flow_complete_get_elt,
13202 		.get_help = cmd_flow_get_help,
13203 	},
13204 	.offset = 0,
13205 };
13206 
13207 /** Populate the next dynamic token. */
13208 static void
13209 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
13210 	     cmdline_parse_token_hdr_t **hdr_inst)
13211 {
13212 	struct context *ctx = &cmd_flow_context;
13213 
13214 	/* Always reinitialize context before requesting the first token. */
13215 	if (!(hdr_inst - cmd_flow.tokens))
13216 		cmd_flow_context_init(ctx);
13217 	/* Return NULL when no more tokens are expected. */
13218 	if (!ctx->next_num && ctx->curr) {
13219 		*hdr = NULL;
13220 		return;
13221 	}
13222 	/* Determine if command should end here. */
13223 	if (ctx->eol && ctx->last && ctx->next_num) {
13224 		const enum index *list = ctx->next[ctx->next_num - 1];
13225 		int i;
13226 
13227 		for (i = 0; list[i]; ++i) {
13228 			if (list[i] != END)
13229 				continue;
13230 			*hdr = NULL;
13231 			return;
13232 		}
13233 	}
13234 	*hdr = &cmd_flow_token_hdr;
13235 }
13236 
13237 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
13238 	SLIST_HEAD_INITIALIZER();
13239 
13240 static void
13241 indirect_action_flow_conf_create(const struct buffer *in)
13242 {
13243 	int len, ret;
13244 	uint32_t i;
13245 	struct indlst_conf *indlst_conf = NULL;
13246 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
13247 	struct rte_flow_action *src = in->args.vc.actions;
13248 
13249 	if (!in->args.vc.actions_n)
13250 		goto end;
13251 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
13252 	if (len <= 0)
13253 		goto end;
13254 	len = RTE_ALIGN(len, 16);
13255 
13256 	indlst_conf = calloc(1, base + len +
13257 			     in->args.vc.actions_n * sizeof(uintptr_t));
13258 	if (!indlst_conf)
13259 		goto end;
13260 	indlst_conf->id = in->args.vc.attr.group;
13261 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
13262 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
13263 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
13264 			    len, src, NULL);
13265 	if (ret <= 0) {
13266 		free(indlst_conf);
13267 		indlst_conf = NULL;
13268 		goto end;
13269 	}
13270 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
13271 	for (i = 0; i < indlst_conf->conf_num; i++)
13272 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
13273 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
13274 end:
13275 	if (indlst_conf)
13276 		printf("created indirect action list configuration %u\n",
13277 		       in->args.vc.attr.group);
13278 	else
13279 		printf("cannot create indirect action list configuration %u\n",
13280 		       in->args.vc.attr.group);
13281 }
13282 
13283 static const struct indlst_conf *
13284 indirect_action_list_conf_get(uint32_t conf_id)
13285 {
13286 	const struct indlst_conf *conf;
13287 
13288 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
13289 		if (conf->id == conf_id)
13290 			return conf;
13291 	}
13292 	return NULL;
13293 }
13294 
13295 /** Dispatch parsed buffer to function calls. */
13296 static void
13297 cmd_flow_parsed(const struct buffer *in)
13298 {
13299 	switch (in->command) {
13300 	case INFO:
13301 		port_flow_get_info(in->port);
13302 		break;
13303 	case CONFIGURE:
13304 		port_flow_configure(in->port,
13305 				    &in->args.configure.port_attr,
13306 				    in->args.configure.nb_queue,
13307 				    &in->args.configure.queue_attr);
13308 		break;
13309 	case PATTERN_TEMPLATE_CREATE:
13310 		port_flow_pattern_template_create(in->port,
13311 				in->args.vc.pat_templ_id,
13312 				&((const struct rte_flow_pattern_template_attr) {
13313 					.relaxed_matching = in->args.vc.attr.reserved,
13314 					.ingress = in->args.vc.attr.ingress,
13315 					.egress = in->args.vc.attr.egress,
13316 					.transfer = in->args.vc.attr.transfer,
13317 				}),
13318 				in->args.vc.pattern);
13319 		break;
13320 	case PATTERN_TEMPLATE_DESTROY:
13321 		port_flow_pattern_template_destroy(in->port,
13322 				in->args.templ_destroy.template_id_n,
13323 				in->args.templ_destroy.template_id);
13324 		break;
13325 	case ACTIONS_TEMPLATE_CREATE:
13326 		port_flow_actions_template_create(in->port,
13327 				in->args.vc.act_templ_id,
13328 				&((const struct rte_flow_actions_template_attr) {
13329 					.ingress = in->args.vc.attr.ingress,
13330 					.egress = in->args.vc.attr.egress,
13331 					.transfer = in->args.vc.attr.transfer,
13332 				}),
13333 				in->args.vc.actions,
13334 				in->args.vc.masks);
13335 		break;
13336 	case ACTIONS_TEMPLATE_DESTROY:
13337 		port_flow_actions_template_destroy(in->port,
13338 				in->args.templ_destroy.template_id_n,
13339 				in->args.templ_destroy.template_id);
13340 		break;
13341 	case TABLE_CREATE:
13342 		port_flow_template_table_create(in->port, in->args.table.id,
13343 			&in->args.table.attr, in->args.table.pat_templ_id_n,
13344 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
13345 			in->args.table.act_templ_id);
13346 		break;
13347 	case TABLE_DESTROY:
13348 		port_flow_template_table_destroy(in->port,
13349 					in->args.table_destroy.table_id_n,
13350 					in->args.table_destroy.table_id);
13351 		break;
13352 	case TABLE_RESIZE_COMPLETE:
13353 		port_flow_template_table_resize_complete
13354 			(in->port, in->args.table_destroy.table_id[0]);
13355 		break;
13356 	case GROUP_SET_MISS_ACTIONS:
13357 		port_queue_group_set_miss_actions(in->port, &in->args.vc.attr,
13358 						  in->args.vc.actions);
13359 		break;
13360 	case TABLE_RESIZE:
13361 		port_flow_template_table_resize(in->port, in->args.table.id,
13362 						in->args.table.attr.nb_flows);
13363 		break;
13364 	case QUEUE_CREATE:
13365 		port_queue_flow_create(in->port, in->queue, in->postpone,
13366 			in->args.vc.table_id, in->args.vc.rule_id,
13367 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
13368 			in->args.vc.pattern, in->args.vc.actions);
13369 		break;
13370 	case QUEUE_DESTROY:
13371 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
13372 					in->args.destroy.rule_n,
13373 					in->args.destroy.rule);
13374 		break;
13375 	case QUEUE_FLOW_UPDATE_RESIZED:
13376 		port_queue_flow_update_resized(in->port, in->queue,
13377 					       in->postpone,
13378 					       in->args.destroy.rule[0]);
13379 		break;
13380 	case QUEUE_UPDATE:
13381 		port_queue_flow_update(in->port, in->queue, in->postpone,
13382 				in->args.vc.rule_id, in->args.vc.act_templ_id,
13383 				in->args.vc.actions);
13384 		break;
13385 	case PUSH:
13386 		port_queue_flow_push(in->port, in->queue);
13387 		break;
13388 	case PULL:
13389 		port_queue_flow_pull(in->port, in->queue);
13390 		break;
13391 	case HASH:
13392 		if (!in->args.vc.encap_hash)
13393 			port_flow_hash_calc(in->port, in->args.vc.table_id,
13394 					    in->args.vc.pat_templ_id,
13395 					    in->args.vc.pattern);
13396 		else
13397 			port_flow_hash_calc_encap(in->port, in->args.vc.field,
13398 						  in->args.vc.pattern);
13399 		break;
13400 	case QUEUE_AGED:
13401 		port_queue_flow_aged(in->port, in->queue,
13402 				     in->args.aged.destroy);
13403 		break;
13404 	case QUEUE_INDIRECT_ACTION_CREATE:
13405 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
13406 		port_queue_action_handle_create(
13407 				in->port, in->queue, in->postpone,
13408 				in->args.vc.attr.group,
13409 				in->command == QUEUE_INDIRECT_ACTION_LIST_CREATE,
13410 				&((const struct rte_flow_indir_action_conf) {
13411 					.ingress = in->args.vc.attr.ingress,
13412 					.egress = in->args.vc.attr.egress,
13413 					.transfer = in->args.vc.attr.transfer,
13414 				}),
13415 				in->args.vc.actions);
13416 		break;
13417 	case QUEUE_INDIRECT_ACTION_DESTROY:
13418 		port_queue_action_handle_destroy(in->port,
13419 					   in->queue, in->postpone,
13420 					   in->args.ia_destroy.action_id_n,
13421 					   in->args.ia_destroy.action_id);
13422 		break;
13423 	case QUEUE_INDIRECT_ACTION_UPDATE:
13424 		port_queue_action_handle_update(in->port,
13425 						in->queue, in->postpone,
13426 						in->args.vc.attr.group,
13427 						in->args.vc.actions);
13428 		break;
13429 	case QUEUE_INDIRECT_ACTION_QUERY:
13430 		port_queue_action_handle_query(in->port,
13431 					       in->queue, in->postpone,
13432 					       in->args.ia.action_id);
13433 		break;
13434 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
13435 		port_queue_action_handle_query_update(in->port, in->queue,
13436 						      in->postpone,
13437 						      in->args.ia.action_id,
13438 						      in->args.ia.qu_mode,
13439 						      in->args.vc.actions);
13440 		break;
13441 	case INDIRECT_ACTION_CREATE:
13442 	case INDIRECT_ACTION_LIST_CREATE:
13443 		port_action_handle_create(
13444 				in->port, in->args.vc.attr.group,
13445 				in->command == INDIRECT_ACTION_LIST_CREATE,
13446 				&((const struct rte_flow_indir_action_conf) {
13447 					.ingress = in->args.vc.attr.ingress,
13448 					.egress = in->args.vc.attr.egress,
13449 					.transfer = in->args.vc.attr.transfer,
13450 				}),
13451 				in->args.vc.actions);
13452 		break;
13453 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
13454 		indirect_action_flow_conf_create(in);
13455 		break;
13456 	case INDIRECT_ACTION_DESTROY:
13457 		port_action_handle_destroy(in->port,
13458 					   in->args.ia_destroy.action_id_n,
13459 					   in->args.ia_destroy.action_id);
13460 		break;
13461 	case INDIRECT_ACTION_UPDATE:
13462 		port_action_handle_update(in->port, in->args.vc.attr.group,
13463 					  in->args.vc.actions);
13464 		break;
13465 	case INDIRECT_ACTION_QUERY:
13466 		port_action_handle_query(in->port, in->args.ia.action_id);
13467 		break;
13468 	case INDIRECT_ACTION_QUERY_UPDATE:
13469 		port_action_handle_query_update(in->port,
13470 						in->args.ia.action_id,
13471 						in->args.ia.qu_mode,
13472 						in->args.vc.actions);
13473 		break;
13474 	case VALIDATE:
13475 		port_flow_validate(in->port, &in->args.vc.attr,
13476 				   in->args.vc.pattern, in->args.vc.actions,
13477 				   &in->args.vc.tunnel_ops);
13478 		break;
13479 	case CREATE:
13480 		port_flow_create(in->port, &in->args.vc.attr,
13481 				 in->args.vc.pattern, in->args.vc.actions,
13482 				 &in->args.vc.tunnel_ops, in->args.vc.user_id);
13483 		break;
13484 	case DESTROY:
13485 		port_flow_destroy(in->port, in->args.destroy.rule_n,
13486 				  in->args.destroy.rule,
13487 				  in->args.destroy.is_user_id);
13488 		break;
13489 	case UPDATE:
13490 		port_flow_update(in->port, in->args.vc.rule_id,
13491 				 in->args.vc.actions, in->args.vc.user_id);
13492 		break;
13493 	case FLUSH:
13494 		port_flow_flush(in->port);
13495 		break;
13496 	case DUMP_ONE:
13497 	case DUMP_ALL:
13498 		port_flow_dump(in->port, in->args.dump.mode,
13499 				in->args.dump.rule, in->args.dump.file,
13500 				in->args.dump.is_user_id);
13501 		break;
13502 	case QUERY:
13503 		port_flow_query(in->port, in->args.query.rule,
13504 				&in->args.query.action,
13505 				in->args.query.is_user_id);
13506 		break;
13507 	case LIST:
13508 		port_flow_list(in->port, in->args.list.group_n,
13509 			       in->args.list.group);
13510 		break;
13511 	case ISOLATE:
13512 		port_flow_isolate(in->port, in->args.isolate.set);
13513 		break;
13514 	case AGED:
13515 		port_flow_aged(in->port, in->args.aged.destroy);
13516 		break;
13517 	case TUNNEL_CREATE:
13518 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
13519 		break;
13520 	case TUNNEL_DESTROY:
13521 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
13522 		break;
13523 	case TUNNEL_LIST:
13524 		port_flow_tunnel_list(in->port);
13525 		break;
13526 	case ACTION_POL_G:
13527 		port_meter_policy_add(in->port, in->args.policy.policy_id,
13528 					in->args.vc.actions);
13529 		break;
13530 	case FLEX_ITEM_CREATE:
13531 		flex_item_create(in->port, in->args.flex.token,
13532 				 in->args.flex.filename);
13533 		break;
13534 	case FLEX_ITEM_DESTROY:
13535 		flex_item_destroy(in->port, in->args.flex.token);
13536 		break;
13537 	default:
13538 		break;
13539 	}
13540 	fflush(stdout);
13541 }
13542 
13543 /** Token generator and output processing callback (cmdline API). */
13544 static void
13545 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
13546 {
13547 	if (cl == NULL)
13548 		cmd_flow_tok(arg0, arg2);
13549 	else
13550 		cmd_flow_parsed(arg0);
13551 }
13552 
13553 /** Global parser instance (cmdline API). */
13554 cmdline_parse_inst_t cmd_flow = {
13555 	.f = cmd_flow_cb,
13556 	.data = NULL, /**< Unused. */
13557 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
13558 	.tokens = {
13559 		NULL,
13560 	}, /**< Tokens are returned by cmd_flow_tok(). */
13561 };
13562 
13563 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
13564 
13565 static void
13566 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
13567 {
13568 	struct rte_ipv4_hdr *ipv4;
13569 	struct rte_ether_hdr *eth;
13570 	struct rte_ipv6_hdr *ipv6;
13571 	struct rte_vxlan_hdr *vxlan;
13572 	struct rte_vxlan_gpe_hdr *gpe;
13573 	struct rte_flow_item_nvgre *nvgre;
13574 	uint32_t ipv6_vtc_flow;
13575 
13576 	switch (item->type) {
13577 	case RTE_FLOW_ITEM_TYPE_ETH:
13578 		eth = (struct rte_ether_hdr *)buf;
13579 		if (next_proto)
13580 			eth->ether_type = rte_cpu_to_be_16(next_proto);
13581 		break;
13582 	case RTE_FLOW_ITEM_TYPE_IPV4:
13583 		ipv4 = (struct rte_ipv4_hdr *)buf;
13584 		if (!ipv4->version_ihl)
13585 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
13586 		if (next_proto && ipv4->next_proto_id == 0)
13587 			ipv4->next_proto_id = (uint8_t)next_proto;
13588 		break;
13589 	case RTE_FLOW_ITEM_TYPE_IPV6:
13590 		ipv6 = (struct rte_ipv6_hdr *)buf;
13591 		if (next_proto && ipv6->proto == 0)
13592 			ipv6->proto = (uint8_t)next_proto;
13593 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
13594 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
13595 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
13596 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
13597 		break;
13598 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13599 		vxlan = (struct rte_vxlan_hdr *)buf;
13600 		vxlan->vx_flags = 0x08;
13601 		break;
13602 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13603 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
13604 		gpe->vx_flags = 0x0C;
13605 		break;
13606 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13607 		nvgre = (struct rte_flow_item_nvgre *)buf;
13608 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
13609 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
13610 		break;
13611 	default:
13612 		break;
13613 	}
13614 }
13615 
13616 /** Helper of get item's default mask. */
13617 static const void *
13618 flow_item_default_mask(const struct rte_flow_item *item)
13619 {
13620 	const void *mask = NULL;
13621 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
13622 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
13623 		.hdr = {
13624 			.next_hdr = 0xff,
13625 			.type = 0xff,
13626 			.segments_left = 0xff,
13627 		},
13628 	};
13629 
13630 	switch (item->type) {
13631 	case RTE_FLOW_ITEM_TYPE_ANY:
13632 		mask = &rte_flow_item_any_mask;
13633 		break;
13634 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
13635 		mask = &rte_flow_item_port_id_mask;
13636 		break;
13637 	case RTE_FLOW_ITEM_TYPE_RAW:
13638 		mask = &rte_flow_item_raw_mask;
13639 		break;
13640 	case RTE_FLOW_ITEM_TYPE_ETH:
13641 		mask = &rte_flow_item_eth_mask;
13642 		break;
13643 	case RTE_FLOW_ITEM_TYPE_VLAN:
13644 		mask = &rte_flow_item_vlan_mask;
13645 		break;
13646 	case RTE_FLOW_ITEM_TYPE_IPV4:
13647 		mask = &rte_flow_item_ipv4_mask;
13648 		break;
13649 	case RTE_FLOW_ITEM_TYPE_IPV6:
13650 		mask = &rte_flow_item_ipv6_mask;
13651 		break;
13652 	case RTE_FLOW_ITEM_TYPE_ICMP:
13653 		mask = &rte_flow_item_icmp_mask;
13654 		break;
13655 	case RTE_FLOW_ITEM_TYPE_UDP:
13656 		mask = &rte_flow_item_udp_mask;
13657 		break;
13658 	case RTE_FLOW_ITEM_TYPE_TCP:
13659 		mask = &rte_flow_item_tcp_mask;
13660 		break;
13661 	case RTE_FLOW_ITEM_TYPE_SCTP:
13662 		mask = &rte_flow_item_sctp_mask;
13663 		break;
13664 	case RTE_FLOW_ITEM_TYPE_VXLAN:
13665 		mask = &rte_flow_item_vxlan_mask;
13666 		break;
13667 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
13668 		mask = &rte_flow_item_vxlan_gpe_mask;
13669 		break;
13670 	case RTE_FLOW_ITEM_TYPE_E_TAG:
13671 		mask = &rte_flow_item_e_tag_mask;
13672 		break;
13673 	case RTE_FLOW_ITEM_TYPE_NVGRE:
13674 		mask = &rte_flow_item_nvgre_mask;
13675 		break;
13676 	case RTE_FLOW_ITEM_TYPE_MPLS:
13677 		mask = &rte_flow_item_mpls_mask;
13678 		break;
13679 	case RTE_FLOW_ITEM_TYPE_GRE:
13680 		mask = &rte_flow_item_gre_mask;
13681 		break;
13682 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
13683 		mask = &gre_key_default_mask;
13684 		break;
13685 	case RTE_FLOW_ITEM_TYPE_META:
13686 		mask = &rte_flow_item_meta_mask;
13687 		break;
13688 	case RTE_FLOW_ITEM_TYPE_RANDOM:
13689 		mask = &rte_flow_item_random_mask;
13690 		break;
13691 	case RTE_FLOW_ITEM_TYPE_FUZZY:
13692 		mask = &rte_flow_item_fuzzy_mask;
13693 		break;
13694 	case RTE_FLOW_ITEM_TYPE_GTP:
13695 		mask = &rte_flow_item_gtp_mask;
13696 		break;
13697 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
13698 		mask = &rte_flow_item_gtp_psc_mask;
13699 		break;
13700 	case RTE_FLOW_ITEM_TYPE_GENEVE:
13701 		mask = &rte_flow_item_geneve_mask;
13702 		break;
13703 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
13704 		mask = &rte_flow_item_geneve_opt_mask;
13705 		break;
13706 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
13707 		mask = &rte_flow_item_pppoe_proto_id_mask;
13708 		break;
13709 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
13710 		mask = &rte_flow_item_l2tpv3oip_mask;
13711 		break;
13712 	case RTE_FLOW_ITEM_TYPE_ESP:
13713 		mask = &rte_flow_item_esp_mask;
13714 		break;
13715 	case RTE_FLOW_ITEM_TYPE_AH:
13716 		mask = &rte_flow_item_ah_mask;
13717 		break;
13718 	case RTE_FLOW_ITEM_TYPE_PFCP:
13719 		mask = &rte_flow_item_pfcp_mask;
13720 		break;
13721 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
13722 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
13723 		mask = &rte_flow_item_ethdev_mask;
13724 		break;
13725 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
13726 		mask = &rte_flow_item_l2tpv2_mask;
13727 		break;
13728 	case RTE_FLOW_ITEM_TYPE_PPP:
13729 		mask = &rte_flow_item_ppp_mask;
13730 		break;
13731 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
13732 		mask = &rte_flow_item_meter_color_mask;
13733 		break;
13734 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13735 		mask = &ipv6_routing_ext_default_mask;
13736 		break;
13737 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
13738 		mask = &rte_flow_item_aggr_affinity_mask;
13739 		break;
13740 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
13741 		mask = &rte_flow_item_tx_queue_mask;
13742 		break;
13743 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
13744 		mask = &rte_flow_item_ib_bth_mask;
13745 		break;
13746 	case RTE_FLOW_ITEM_TYPE_PTYPE:
13747 		mask = &rte_flow_item_ptype_mask;
13748 		break;
13749 	default:
13750 		break;
13751 	}
13752 	return mask;
13753 }
13754 
13755 /** Dispatch parsed buffer to function calls. */
13756 static void
13757 cmd_set_ipv6_ext_parsed(const struct buffer *in)
13758 {
13759 	uint32_t n = in->args.vc.pattern_n;
13760 	int i = 0;
13761 	struct rte_flow_item *item = NULL;
13762 	size_t size = 0;
13763 	uint8_t *data = NULL;
13764 	uint8_t *type = NULL;
13765 	size_t *total_size = NULL;
13766 	uint16_t idx = in->port; /* We borrow port field as index */
13767 	struct rte_flow_item_ipv6_routing_ext *ext;
13768 	const struct rte_flow_item_ipv6_ext *ipv6_ext;
13769 
13770 	RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH ||
13771 		   in->command == SET_IPV6_EXT_REMOVE);
13772 
13773 	if (in->command == SET_IPV6_EXT_REMOVE) {
13774 		if (n != 1 || in->args.vc.pattern->type !=
13775 		    RTE_FLOW_ITEM_TYPE_IPV6_EXT) {
13776 			fprintf(stderr, "Error - Not supported item\n");
13777 			return;
13778 		}
13779 		type = (uint8_t *)&ipv6_ext_remove_confs[idx].type;
13780 		item = in->args.vc.pattern;
13781 		ipv6_ext = item->spec;
13782 		*type = ipv6_ext->next_hdr;
13783 		return;
13784 	}
13785 
13786 	total_size = &ipv6_ext_push_confs[idx].size;
13787 	data = (uint8_t *)&ipv6_ext_push_confs[idx].data;
13788 	type = (uint8_t *)&ipv6_ext_push_confs[idx].type;
13789 
13790 	*total_size = 0;
13791 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13792 	for (i = n - 1 ; i >= 0; --i) {
13793 		item = in->args.vc.pattern + i;
13794 		switch (item->type) {
13795 		case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
13796 			ipv6_ext = item->spec;
13797 			*type = ipv6_ext->next_hdr;
13798 			break;
13799 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
13800 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
13801 			if (!ext->hdr.hdr_len) {
13802 				size = sizeof(struct rte_ipv6_routing_ext) +
13803 				(ext->hdr.segments_left << 4);
13804 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
13805 				/* Indicate no TLV once SRH. */
13806 				if (ext->hdr.type == 4)
13807 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
13808 			} else {
13809 				size = sizeof(struct rte_ipv6_routing_ext) +
13810 				(ext->hdr.hdr_len << 3);
13811 			}
13812 			*total_size += size;
13813 			memcpy(data, ext, size);
13814 			break;
13815 		default:
13816 			fprintf(stderr, "Error - Not supported item\n");
13817 			goto error;
13818 		}
13819 	}
13820 	RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA);
13821 	return;
13822 error:
13823 	*total_size = 0;
13824 	memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA);
13825 }
13826 
13827 /** Dispatch parsed buffer to function calls. */
13828 static void
13829 cmd_set_raw_parsed_sample(const struct buffer *in)
13830 {
13831 	uint32_t n = in->args.vc.actions_n;
13832 	uint32_t i = 0;
13833 	struct rte_flow_action *action = NULL;
13834 	struct rte_flow_action *data = NULL;
13835 	const struct rte_flow_action_rss *rss = NULL;
13836 	size_t size = 0;
13837 	uint16_t idx = in->port; /* We borrow port field as index */
13838 	uint32_t max_size = sizeof(struct rte_flow_action) *
13839 						ACTION_SAMPLE_ACTIONS_NUM;
13840 
13841 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
13842 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
13843 	memset(data, 0x00, max_size);
13844 	for (; i <= n - 1; i++) {
13845 		action = in->args.vc.actions + i;
13846 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
13847 			break;
13848 		switch (action->type) {
13849 		case RTE_FLOW_ACTION_TYPE_MARK:
13850 			size = sizeof(struct rte_flow_action_mark);
13851 			rte_memcpy(&sample_mark[idx],
13852 				(const void *)action->conf, size);
13853 			action->conf = &sample_mark[idx];
13854 			break;
13855 		case RTE_FLOW_ACTION_TYPE_COUNT:
13856 			size = sizeof(struct rte_flow_action_count);
13857 			rte_memcpy(&sample_count[idx],
13858 				(const void *)action->conf, size);
13859 			action->conf = &sample_count[idx];
13860 			break;
13861 		case RTE_FLOW_ACTION_TYPE_QUEUE:
13862 			size = sizeof(struct rte_flow_action_queue);
13863 			rte_memcpy(&sample_queue[idx],
13864 				(const void *)action->conf, size);
13865 			action->conf = &sample_queue[idx];
13866 			break;
13867 		case RTE_FLOW_ACTION_TYPE_RSS:
13868 			size = sizeof(struct rte_flow_action_rss);
13869 			rss = action->conf;
13870 			rte_memcpy(&sample_rss_data[idx].conf,
13871 				   (const void *)rss, size);
13872 			if (rss->key_len && rss->key) {
13873 				sample_rss_data[idx].conf.key =
13874 						sample_rss_data[idx].key;
13875 				rte_memcpy((void *)((uintptr_t)
13876 					   sample_rss_data[idx].conf.key),
13877 					   (const void *)rss->key,
13878 					   sizeof(uint8_t) * rss->key_len);
13879 			}
13880 			if (rss->queue_num && rss->queue) {
13881 				sample_rss_data[idx].conf.queue =
13882 						sample_rss_data[idx].queue;
13883 				rte_memcpy((void *)((uintptr_t)
13884 					   sample_rss_data[idx].conf.queue),
13885 					   (const void *)rss->queue,
13886 					   sizeof(uint16_t) * rss->queue_num);
13887 			}
13888 			action->conf = &sample_rss_data[idx].conf;
13889 			break;
13890 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
13891 			size = sizeof(struct rte_flow_action_raw_encap);
13892 			rte_memcpy(&sample_encap[idx],
13893 				(const void *)action->conf, size);
13894 			action->conf = &sample_encap[idx];
13895 			break;
13896 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
13897 			size = sizeof(struct rte_flow_action_port_id);
13898 			rte_memcpy(&sample_port_id[idx],
13899 				(const void *)action->conf, size);
13900 			action->conf = &sample_port_id[idx];
13901 			break;
13902 		case RTE_FLOW_ACTION_TYPE_PF:
13903 			break;
13904 		case RTE_FLOW_ACTION_TYPE_VF:
13905 			size = sizeof(struct rte_flow_action_vf);
13906 			rte_memcpy(&sample_vf[idx],
13907 					(const void *)action->conf, size);
13908 			action->conf = &sample_vf[idx];
13909 			break;
13910 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
13911 			size = sizeof(struct rte_flow_action_vxlan_encap);
13912 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
13913 			action->conf = &sample_vxlan_encap[idx].conf;
13914 			break;
13915 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
13916 			size = sizeof(struct rte_flow_action_nvgre_encap);
13917 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
13918 			action->conf = &sample_nvgre_encap[idx];
13919 			break;
13920 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
13921 			size = sizeof(struct rte_flow_action_ethdev);
13922 			rte_memcpy(&sample_port_representor[idx],
13923 					(const void *)action->conf, size);
13924 			action->conf = &sample_port_representor[idx];
13925 			break;
13926 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
13927 			size = sizeof(struct rte_flow_action_ethdev);
13928 			rte_memcpy(&sample_represented_port[idx],
13929 					(const void *)action->conf, size);
13930 			action->conf = &sample_represented_port[idx];
13931 			break;
13932 		default:
13933 			fprintf(stderr, "Error - Not supported action\n");
13934 			return;
13935 		}
13936 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
13937 		data++;
13938 	}
13939 }
13940 
13941 /** Dispatch parsed buffer to function calls. */
13942 static void
13943 cmd_set_raw_parsed(const struct buffer *in)
13944 {
13945 	uint32_t n = in->args.vc.pattern_n;
13946 	int i = 0;
13947 	struct rte_flow_item *item = NULL;
13948 	size_t size = 0;
13949 	uint8_t *data = NULL;
13950 	uint8_t *data_tail = NULL;
13951 	size_t *total_size = NULL;
13952 	uint16_t upper_layer = 0;
13953 	uint16_t proto = 0;
13954 	uint16_t idx = in->port; /* We borrow port field as index */
13955 	int gtp_psc = -1; /* GTP PSC option index. */
13956 	const void *src_spec;
13957 
13958 	if (in->command == SET_SAMPLE_ACTIONS)
13959 		return cmd_set_raw_parsed_sample(in);
13960 	else if (in->command == SET_IPV6_EXT_PUSH ||
13961 		 in->command == SET_IPV6_EXT_REMOVE)
13962 		return cmd_set_ipv6_ext_parsed(in);
13963 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
13964 		   in->command == SET_RAW_DECAP);
13965 	if (in->command == SET_RAW_ENCAP) {
13966 		total_size = &raw_encap_confs[idx].size;
13967 		data = (uint8_t *)&raw_encap_confs[idx].data;
13968 	} else {
13969 		total_size = &raw_decap_confs[idx].size;
13970 		data = (uint8_t *)&raw_decap_confs[idx].data;
13971 	}
13972 	*total_size = 0;
13973 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
13974 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
13975 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
13976 	for (i = n - 1 ; i >= 0; --i) {
13977 		const struct rte_flow_item_gtp *gtp;
13978 		const struct rte_flow_item_geneve_opt *opt;
13979 		struct rte_flow_item_ipv6_routing_ext *ext;
13980 
13981 		item = in->args.vc.pattern + i;
13982 		if (item->spec == NULL)
13983 			item->spec = flow_item_default_mask(item);
13984 		src_spec = item->spec;
13985 		switch (item->type) {
13986 		case RTE_FLOW_ITEM_TYPE_ETH:
13987 			size = sizeof(struct rte_ether_hdr);
13988 			break;
13989 		case RTE_FLOW_ITEM_TYPE_VLAN:
13990 			size = sizeof(struct rte_vlan_hdr);
13991 			proto = RTE_ETHER_TYPE_VLAN;
13992 			break;
13993 		case RTE_FLOW_ITEM_TYPE_IPV4:
13994 			size = sizeof(struct rte_ipv4_hdr);
13995 			proto = RTE_ETHER_TYPE_IPV4;
13996 			break;
13997 		case RTE_FLOW_ITEM_TYPE_IPV6:
13998 			size = sizeof(struct rte_ipv6_hdr);
13999 			proto = RTE_ETHER_TYPE_IPV6;
14000 			break;
14001 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
14002 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
14003 			if (!ext->hdr.hdr_len) {
14004 				size = sizeof(struct rte_ipv6_routing_ext) +
14005 					(ext->hdr.segments_left << 4);
14006 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
14007 				/* SRv6 without TLV. */
14008 				if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4)
14009 					ext->hdr.last_entry = ext->hdr.segments_left - 1;
14010 			} else {
14011 				size = sizeof(struct rte_ipv6_routing_ext) +
14012 					(ext->hdr.hdr_len << 3);
14013 			}
14014 			proto = IPPROTO_ROUTING;
14015 			break;
14016 		case RTE_FLOW_ITEM_TYPE_UDP:
14017 			size = sizeof(struct rte_udp_hdr);
14018 			proto = 0x11;
14019 			break;
14020 		case RTE_FLOW_ITEM_TYPE_TCP:
14021 			size = sizeof(struct rte_tcp_hdr);
14022 			proto = 0x06;
14023 			break;
14024 		case RTE_FLOW_ITEM_TYPE_VXLAN:
14025 			size = sizeof(struct rte_vxlan_hdr);
14026 			break;
14027 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
14028 			size = sizeof(struct rte_vxlan_gpe_hdr);
14029 			break;
14030 		case RTE_FLOW_ITEM_TYPE_GRE:
14031 			size = sizeof(struct rte_gre_hdr);
14032 			proto = 0x2F;
14033 			break;
14034 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
14035 			size = sizeof(rte_be32_t);
14036 			proto = 0x0;
14037 			break;
14038 		case RTE_FLOW_ITEM_TYPE_MPLS:
14039 			size = sizeof(struct rte_mpls_hdr);
14040 			proto = 0x0;
14041 			break;
14042 		case RTE_FLOW_ITEM_TYPE_NVGRE:
14043 			size = sizeof(struct rte_flow_item_nvgre);
14044 			proto = 0x2F;
14045 			break;
14046 		case RTE_FLOW_ITEM_TYPE_GENEVE:
14047 			size = sizeof(struct rte_geneve_hdr);
14048 			break;
14049 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
14050 			opt = (const struct rte_flow_item_geneve_opt *)
14051 								item->spec;
14052 			size = offsetof(struct rte_flow_item_geneve_opt,
14053 					option_len) + sizeof(uint8_t);
14054 			if (opt->option_len && opt->data) {
14055 				*total_size += opt->option_len *
14056 					       sizeof(uint32_t);
14057 				rte_memcpy(data_tail - (*total_size),
14058 					   opt->data,
14059 					   opt->option_len * sizeof(uint32_t));
14060 			}
14061 			break;
14062 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
14063 			size = sizeof(rte_be32_t);
14064 			proto = 0x73;
14065 			break;
14066 		case RTE_FLOW_ITEM_TYPE_ESP:
14067 			size = sizeof(struct rte_esp_hdr);
14068 			proto = 0x32;
14069 			break;
14070 		case RTE_FLOW_ITEM_TYPE_AH:
14071 			size = sizeof(struct rte_flow_item_ah);
14072 			proto = 0x33;
14073 			break;
14074 		case RTE_FLOW_ITEM_TYPE_GTP:
14075 			if (gtp_psc < 0) {
14076 				size = sizeof(struct rte_gtp_hdr);
14077 				break;
14078 			}
14079 			if (gtp_psc != i + 1) {
14080 				fprintf(stderr,
14081 					"Error - GTP PSC does not follow GTP\n");
14082 				goto error;
14083 			}
14084 			gtp = item->spec;
14085 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
14086 				/* Only E flag should be set. */
14087 				fprintf(stderr,
14088 					"Error - GTP unsupported flags\n");
14089 				goto error;
14090 			} else {
14091 				struct rte_gtp_hdr_ext_word ext_word = {
14092 					.next_ext = 0x85
14093 				};
14094 
14095 				/* We have to add GTP header extra word. */
14096 				*total_size += sizeof(ext_word);
14097 				rte_memcpy(data_tail - (*total_size),
14098 					   &ext_word, sizeof(ext_word));
14099 			}
14100 			size = sizeof(struct rte_gtp_hdr);
14101 			break;
14102 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
14103 			if (gtp_psc >= 0) {
14104 				fprintf(stderr,
14105 					"Error - Multiple GTP PSC items\n");
14106 				goto error;
14107 			} else {
14108 				const struct rte_flow_item_gtp_psc
14109 					*opt = item->spec;
14110 				struct rte_gtp_psc_generic_hdr *hdr;
14111 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
14112 							 sizeof(int32_t));
14113 
14114 				*total_size += hdr_size;
14115 				hdr = (typeof(hdr))(data_tail - (*total_size));
14116 				memset(hdr, 0, hdr_size);
14117 				*hdr = opt->hdr;
14118 				hdr->ext_hdr_len = 1;
14119 				gtp_psc = i;
14120 				size = 0;
14121 			}
14122 			break;
14123 		case RTE_FLOW_ITEM_TYPE_PFCP:
14124 			size = sizeof(struct rte_flow_item_pfcp);
14125 			break;
14126 		case RTE_FLOW_ITEM_TYPE_FLEX:
14127 			if (item->spec != NULL) {
14128 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
14129 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
14130 			} else {
14131 				size = 0;
14132 				src_spec = NULL;
14133 			}
14134 			break;
14135 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
14136 			size = 0;
14137 			if (item->spec) {
14138 				const struct rte_flow_item_gre_opt
14139 					*opt = item->spec;
14140 				if (opt->checksum_rsvd.checksum) {
14141 					*total_size +=
14142 						sizeof(opt->checksum_rsvd);
14143 					rte_memcpy(data_tail - (*total_size),
14144 						   &opt->checksum_rsvd,
14145 						   sizeof(opt->checksum_rsvd));
14146 				}
14147 				if (opt->key.key) {
14148 					*total_size += sizeof(opt->key.key);
14149 					rte_memcpy(data_tail - (*total_size),
14150 						   &opt->key.key,
14151 						   sizeof(opt->key.key));
14152 				}
14153 				if (opt->sequence.sequence) {
14154 					*total_size += sizeof(opt->sequence.sequence);
14155 					rte_memcpy(data_tail - (*total_size),
14156 						   &opt->sequence.sequence,
14157 						   sizeof(opt->sequence.sequence));
14158 				}
14159 			}
14160 			proto = 0x2F;
14161 			break;
14162 		default:
14163 			fprintf(stderr, "Error - Not supported item\n");
14164 			goto error;
14165 		}
14166 		if (size) {
14167 			*total_size += size;
14168 			rte_memcpy(data_tail - (*total_size), src_spec, size);
14169 			/* update some fields which cannot be set by cmdline */
14170 			update_fields((data_tail - (*total_size)), item,
14171 				      upper_layer);
14172 			upper_layer = proto;
14173 		}
14174 	}
14175 	if (verbose_level & 0x1)
14176 		printf("total data size is %zu\n", (*total_size));
14177 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
14178 	memmove(data, (data_tail - (*total_size)), *total_size);
14179 	return;
14180 
14181 error:
14182 	*total_size = 0;
14183 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
14184 }
14185 
14186 /** Populate help strings for current token (cmdline API). */
14187 static int
14188 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
14189 		     unsigned int size)
14190 {
14191 	struct context *ctx = &cmd_flow_context;
14192 	const struct token *token = &token_list[ctx->prev];
14193 
14194 	(void)hdr;
14195 	if (!size)
14196 		return -1;
14197 	/* Set token type and update global help with details. */
14198 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
14199 	if (token->help)
14200 		cmd_set_raw.help_str = token->help;
14201 	else
14202 		cmd_set_raw.help_str = token->name;
14203 	return 0;
14204 }
14205 
14206 /** Token definition template (cmdline API). */
14207 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
14208 	.ops = &(struct cmdline_token_ops){
14209 		.parse = cmd_flow_parse,
14210 		.complete_get_nb = cmd_flow_complete_get_nb,
14211 		.complete_get_elt = cmd_flow_complete_get_elt,
14212 		.get_help = cmd_set_raw_get_help,
14213 	},
14214 	.offset = 0,
14215 };
14216 
14217 /** Populate the next dynamic token. */
14218 static void
14219 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
14220 	     cmdline_parse_token_hdr_t **hdr_inst)
14221 {
14222 	struct context *ctx = &cmd_flow_context;
14223 
14224 	/* Always reinitialize context before requesting the first token. */
14225 	if (!(hdr_inst - cmd_set_raw.tokens)) {
14226 		cmd_flow_context_init(ctx);
14227 		ctx->curr = START_SET;
14228 	}
14229 	/* Return NULL when no more tokens are expected. */
14230 	if (!ctx->next_num && (ctx->curr != START_SET)) {
14231 		*hdr = NULL;
14232 		return;
14233 	}
14234 	/* Determine if command should end here. */
14235 	if (ctx->eol && ctx->last && ctx->next_num) {
14236 		const enum index *list = ctx->next[ctx->next_num - 1];
14237 		int i;
14238 
14239 		for (i = 0; list[i]; ++i) {
14240 			if (list[i] != END)
14241 				continue;
14242 			*hdr = NULL;
14243 			return;
14244 		}
14245 	}
14246 	*hdr = &cmd_set_raw_token_hdr;
14247 }
14248 
14249 /** Token generator and output processing callback (cmdline API). */
14250 static void
14251 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
14252 {
14253 	if (cl == NULL)
14254 		cmd_set_raw_tok(arg0, arg2);
14255 	else
14256 		cmd_set_raw_parsed(arg0);
14257 }
14258 
14259 /** Global parser instance (cmdline API). */
14260 cmdline_parse_inst_t cmd_set_raw = {
14261 	.f = cmd_set_raw_cb,
14262 	.data = NULL, /**< Unused. */
14263 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
14264 	.tokens = {
14265 		NULL,
14266 	}, /**< Tokens are returned by cmd_flow_tok(). */
14267 };
14268 
14269 /* *** display raw_encap/raw_decap buf */
14270 struct cmd_show_set_raw_result {
14271 	cmdline_fixed_string_t cmd_show;
14272 	cmdline_fixed_string_t cmd_what;
14273 	cmdline_fixed_string_t cmd_all;
14274 	uint16_t cmd_index;
14275 };
14276 
14277 static void
14278 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
14279 {
14280 	struct cmd_show_set_raw_result *res = parsed_result;
14281 	uint16_t index = res->cmd_index;
14282 	uint8_t all = 0;
14283 	uint8_t *raw_data = NULL;
14284 	size_t raw_size = 0;
14285 	char title[16] = {0};
14286 
14287 	RTE_SET_USED(cl);
14288 	RTE_SET_USED(data);
14289 	if (!strcmp(res->cmd_all, "all")) {
14290 		all = 1;
14291 		index = 0;
14292 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
14293 		fprintf(stderr, "index should be 0-%u\n",
14294 			RAW_ENCAP_CONFS_MAX_NUM - 1);
14295 		return;
14296 	}
14297 	do {
14298 		if (!strcmp(res->cmd_what, "raw_encap")) {
14299 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
14300 			raw_size = raw_encap_confs[index].size;
14301 			snprintf(title, 16, "\nindex: %u", index);
14302 			rte_hexdump(stdout, title, raw_data, raw_size);
14303 		} else {
14304 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
14305 			raw_size = raw_decap_confs[index].size;
14306 			snprintf(title, 16, "\nindex: %u", index);
14307 			rte_hexdump(stdout, title, raw_data, raw_size);
14308 		}
14309 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
14310 }
14311 
14312 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
14313 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14314 			cmd_show, "show");
14315 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
14316 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14317 			cmd_what, "raw_encap#raw_decap");
14318 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
14319 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
14320 			cmd_index, RTE_UINT16);
14321 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
14322 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
14323 			cmd_all, "all");
14324 cmdline_parse_inst_t cmd_show_set_raw = {
14325 	.f = cmd_show_set_raw_parsed,
14326 	.data = NULL,
14327 	.help_str = "show <raw_encap|raw_decap> <index>",
14328 	.tokens = {
14329 		(void *)&cmd_show_set_raw_cmd_show,
14330 		(void *)&cmd_show_set_raw_cmd_what,
14331 		(void *)&cmd_show_set_raw_cmd_index,
14332 		NULL,
14333 	},
14334 };
14335 cmdline_parse_inst_t cmd_show_set_raw_all = {
14336 	.f = cmd_show_set_raw_parsed,
14337 	.data = NULL,
14338 	.help_str = "show <raw_encap|raw_decap> all",
14339 	.tokens = {
14340 		(void *)&cmd_show_set_raw_cmd_show,
14341 		(void *)&cmd_show_set_raw_cmd_what,
14342 		(void *)&cmd_show_set_raw_cmd_all,
14343 		NULL,
14344 	},
14345 };
14346