xref: /dpdk/app/test-pmd/cmdline_flow.c (revision e30aa5255e3b7fa345055040f50f4f9e4ae26e96)
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 
78 	/* Top-level command. */
79 	FLOW,
80 	/* Sub-level commands. */
81 	INFO,
82 	CONFIGURE,
83 	PATTERN_TEMPLATE,
84 	ACTIONS_TEMPLATE,
85 	TABLE,
86 	INDIRECT_ACTION,
87 	VALIDATE,
88 	CREATE,
89 	DESTROY,
90 	FLUSH,
91 	DUMP,
92 	QUERY,
93 	LIST,
94 	AGED,
95 	ISOLATE,
96 	TUNNEL,
97 	FLEX,
98 	QUEUE,
99 	PUSH,
100 	PULL,
101 
102 	/* Flex arguments */
103 	FLEX_ITEM_INIT,
104 	FLEX_ITEM_CREATE,
105 	FLEX_ITEM_DESTROY,
106 
107 	/* Pattern template arguments. */
108 	PATTERN_TEMPLATE_CREATE,
109 	PATTERN_TEMPLATE_DESTROY,
110 	PATTERN_TEMPLATE_CREATE_ID,
111 	PATTERN_TEMPLATE_DESTROY_ID,
112 	PATTERN_TEMPLATE_RELAXED_MATCHING,
113 	PATTERN_TEMPLATE_INGRESS,
114 	PATTERN_TEMPLATE_EGRESS,
115 	PATTERN_TEMPLATE_TRANSFER,
116 	PATTERN_TEMPLATE_SPEC,
117 
118 	/* Actions template arguments. */
119 	ACTIONS_TEMPLATE_CREATE,
120 	ACTIONS_TEMPLATE_DESTROY,
121 	ACTIONS_TEMPLATE_CREATE_ID,
122 	ACTIONS_TEMPLATE_DESTROY_ID,
123 	ACTIONS_TEMPLATE_INGRESS,
124 	ACTIONS_TEMPLATE_EGRESS,
125 	ACTIONS_TEMPLATE_TRANSFER,
126 	ACTIONS_TEMPLATE_SPEC,
127 	ACTIONS_TEMPLATE_MASK,
128 
129 	/* Queue arguments. */
130 	QUEUE_CREATE,
131 	QUEUE_DESTROY,
132 	QUEUE_AGED,
133 	QUEUE_INDIRECT_ACTION,
134 
135 	/* Queue create arguments. */
136 	QUEUE_CREATE_POSTPONE,
137 	QUEUE_TEMPLATE_TABLE,
138 	QUEUE_PATTERN_TEMPLATE,
139 	QUEUE_ACTIONS_TEMPLATE,
140 	QUEUE_RULE_ID,
141 
142 	/* Queue destroy arguments. */
143 	QUEUE_DESTROY_ID,
144 	QUEUE_DESTROY_POSTPONE,
145 
146 	/* Queue indirect action arguments */
147 	QUEUE_INDIRECT_ACTION_CREATE,
148 	QUEUE_INDIRECT_ACTION_LIST_CREATE,
149 	QUEUE_INDIRECT_ACTION_UPDATE,
150 	QUEUE_INDIRECT_ACTION_DESTROY,
151 	QUEUE_INDIRECT_ACTION_QUERY,
152 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
153 
154 	/* Queue indirect action create arguments */
155 	QUEUE_INDIRECT_ACTION_CREATE_ID,
156 	QUEUE_INDIRECT_ACTION_INGRESS,
157 	QUEUE_INDIRECT_ACTION_EGRESS,
158 	QUEUE_INDIRECT_ACTION_TRANSFER,
159 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
160 	QUEUE_INDIRECT_ACTION_SPEC,
161 	QUEUE_INDIRECT_ACTION_LIST,
162 
163 	/* Queue indirect action update arguments */
164 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
165 
166 	/* Queue indirect action destroy arguments */
167 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
168 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
169 
170 	/* Queue indirect action query arguments */
171 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
172 
173 	/* Queue indirect action query_update arguments */
174 	QUEUE_INDIRECT_ACTION_QU_MODE,
175 
176 	/* Push arguments. */
177 	PUSH_QUEUE,
178 
179 	/* Pull arguments. */
180 	PULL_QUEUE,
181 
182 	/* Table arguments. */
183 	TABLE_CREATE,
184 	TABLE_DESTROY,
185 	TABLE_CREATE_ID,
186 	TABLE_DESTROY_ID,
187 	TABLE_INSERTION_TYPE,
188 	TABLE_INSERTION_TYPE_NAME,
189 	TABLE_HASH_FUNC,
190 	TABLE_HASH_FUNC_NAME,
191 	TABLE_GROUP,
192 	TABLE_PRIORITY,
193 	TABLE_INGRESS,
194 	TABLE_EGRESS,
195 	TABLE_TRANSFER,
196 	TABLE_TRANSFER_WIRE_ORIG,
197 	TABLE_TRANSFER_VPORT_ORIG,
198 	TABLE_RULES_NUMBER,
199 	TABLE_PATTERN_TEMPLATE,
200 	TABLE_ACTIONS_TEMPLATE,
201 
202 	/* Tunnel arguments. */
203 	TUNNEL_CREATE,
204 	TUNNEL_CREATE_TYPE,
205 	TUNNEL_LIST,
206 	TUNNEL_DESTROY,
207 	TUNNEL_DESTROY_ID,
208 
209 	/* Destroy arguments. */
210 	DESTROY_RULE,
211 
212 	/* Query arguments. */
213 	QUERY_ACTION,
214 
215 	/* List arguments. */
216 	LIST_GROUP,
217 
218 	/* Destroy aged flow arguments. */
219 	AGED_DESTROY,
220 
221 	/* Validate/create arguments. */
222 	VC_GROUP,
223 	VC_PRIORITY,
224 	VC_INGRESS,
225 	VC_EGRESS,
226 	VC_TRANSFER,
227 	VC_TUNNEL_SET,
228 	VC_TUNNEL_MATCH,
229 
230 	/* Dump arguments */
231 	DUMP_ALL,
232 	DUMP_ONE,
233 
234 	/* Configure arguments */
235 	CONFIG_QUEUES_NUMBER,
236 	CONFIG_QUEUES_SIZE,
237 	CONFIG_COUNTERS_NUMBER,
238 	CONFIG_AGING_OBJECTS_NUMBER,
239 	CONFIG_METERS_NUMBER,
240 	CONFIG_CONN_TRACK_NUMBER,
241 	CONFIG_QUOTAS_NUMBER,
242 	CONFIG_FLAGS,
243 	CONFIG_HOST_PORT,
244 
245 	/* Indirect action arguments */
246 	INDIRECT_ACTION_CREATE,
247 	INDIRECT_ACTION_LIST_CREATE,
248 	INDIRECT_ACTION_FLOW_CONF_CREATE,
249 	INDIRECT_ACTION_UPDATE,
250 	INDIRECT_ACTION_DESTROY,
251 	INDIRECT_ACTION_QUERY,
252 	INDIRECT_ACTION_QUERY_UPDATE,
253 
254 	/* Indirect action create arguments */
255 	INDIRECT_ACTION_CREATE_ID,
256 	INDIRECT_ACTION_INGRESS,
257 	INDIRECT_ACTION_EGRESS,
258 	INDIRECT_ACTION_TRANSFER,
259 	INDIRECT_ACTION_SPEC,
260 	INDIRECT_ACTION_LIST,
261 	INDIRECT_ACTION_FLOW_CONF,
262 
263 	/* Indirect action destroy arguments */
264 	INDIRECT_ACTION_DESTROY_ID,
265 
266 	/* Indirect action query-and-update arguments */
267 	INDIRECT_ACTION_QU_MODE,
268 	INDIRECT_ACTION_QU_MODE_NAME,
269 
270 	/* Validate/create pattern. */
271 	ITEM_PATTERN,
272 	ITEM_PARAM_IS,
273 	ITEM_PARAM_SPEC,
274 	ITEM_PARAM_LAST,
275 	ITEM_PARAM_MASK,
276 	ITEM_PARAM_PREFIX,
277 	ITEM_NEXT,
278 	ITEM_END,
279 	ITEM_VOID,
280 	ITEM_INVERT,
281 	ITEM_ANY,
282 	ITEM_ANY_NUM,
283 	ITEM_PORT_ID,
284 	ITEM_PORT_ID_ID,
285 	ITEM_MARK,
286 	ITEM_MARK_ID,
287 	ITEM_RAW,
288 	ITEM_RAW_RELATIVE,
289 	ITEM_RAW_SEARCH,
290 	ITEM_RAW_OFFSET,
291 	ITEM_RAW_LIMIT,
292 	ITEM_RAW_PATTERN,
293 	ITEM_RAW_PATTERN_HEX,
294 	ITEM_ETH,
295 	ITEM_ETH_DST,
296 	ITEM_ETH_SRC,
297 	ITEM_ETH_TYPE,
298 	ITEM_ETH_HAS_VLAN,
299 	ITEM_VLAN,
300 	ITEM_VLAN_TCI,
301 	ITEM_VLAN_PCP,
302 	ITEM_VLAN_DEI,
303 	ITEM_VLAN_VID,
304 	ITEM_VLAN_INNER_TYPE,
305 	ITEM_VLAN_HAS_MORE_VLAN,
306 	ITEM_IPV4,
307 	ITEM_IPV4_VER_IHL,
308 	ITEM_IPV4_TOS,
309 	ITEM_IPV4_ID,
310 	ITEM_IPV4_FRAGMENT_OFFSET,
311 	ITEM_IPV4_TTL,
312 	ITEM_IPV4_PROTO,
313 	ITEM_IPV4_SRC,
314 	ITEM_IPV4_DST,
315 	ITEM_IPV6,
316 	ITEM_IPV6_TC,
317 	ITEM_IPV6_FLOW,
318 	ITEM_IPV6_PROTO,
319 	ITEM_IPV6_HOP,
320 	ITEM_IPV6_SRC,
321 	ITEM_IPV6_DST,
322 	ITEM_IPV6_HAS_FRAG_EXT,
323 	ITEM_IPV6_ROUTING_EXT,
324 	ITEM_IPV6_ROUTING_EXT_TYPE,
325 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
326 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
327 	ITEM_ICMP,
328 	ITEM_ICMP_TYPE,
329 	ITEM_ICMP_CODE,
330 	ITEM_ICMP_IDENT,
331 	ITEM_ICMP_SEQ,
332 	ITEM_UDP,
333 	ITEM_UDP_SRC,
334 	ITEM_UDP_DST,
335 	ITEM_TCP,
336 	ITEM_TCP_SRC,
337 	ITEM_TCP_DST,
338 	ITEM_TCP_FLAGS,
339 	ITEM_SCTP,
340 	ITEM_SCTP_SRC,
341 	ITEM_SCTP_DST,
342 	ITEM_SCTP_TAG,
343 	ITEM_SCTP_CKSUM,
344 	ITEM_VXLAN,
345 	ITEM_VXLAN_VNI,
346 	ITEM_VXLAN_LAST_RSVD,
347 	ITEM_E_TAG,
348 	ITEM_E_TAG_GRP_ECID_B,
349 	ITEM_NVGRE,
350 	ITEM_NVGRE_TNI,
351 	ITEM_MPLS,
352 	ITEM_MPLS_LABEL,
353 	ITEM_MPLS_TC,
354 	ITEM_MPLS_S,
355 	ITEM_GRE,
356 	ITEM_GRE_PROTO,
357 	ITEM_GRE_C_RSVD0_VER,
358 	ITEM_GRE_C_BIT,
359 	ITEM_GRE_K_BIT,
360 	ITEM_GRE_S_BIT,
361 	ITEM_FUZZY,
362 	ITEM_FUZZY_THRESH,
363 	ITEM_GTP,
364 	ITEM_GTP_FLAGS,
365 	ITEM_GTP_MSG_TYPE,
366 	ITEM_GTP_TEID,
367 	ITEM_GTPC,
368 	ITEM_GTPU,
369 	ITEM_GENEVE,
370 	ITEM_GENEVE_VNI,
371 	ITEM_GENEVE_PROTO,
372 	ITEM_GENEVE_OPTLEN,
373 	ITEM_VXLAN_GPE,
374 	ITEM_VXLAN_GPE_VNI,
375 	ITEM_ARP_ETH_IPV4,
376 	ITEM_ARP_ETH_IPV4_SHA,
377 	ITEM_ARP_ETH_IPV4_SPA,
378 	ITEM_ARP_ETH_IPV4_THA,
379 	ITEM_ARP_ETH_IPV4_TPA,
380 	ITEM_IPV6_EXT,
381 	ITEM_IPV6_EXT_NEXT_HDR,
382 	ITEM_IPV6_FRAG_EXT,
383 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
384 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
385 	ITEM_IPV6_FRAG_EXT_ID,
386 	ITEM_ICMP6,
387 	ITEM_ICMP6_TYPE,
388 	ITEM_ICMP6_CODE,
389 	ITEM_ICMP6_ECHO_REQUEST,
390 	ITEM_ICMP6_ECHO_REQUEST_ID,
391 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
392 	ITEM_ICMP6_ECHO_REPLY,
393 	ITEM_ICMP6_ECHO_REPLY_ID,
394 	ITEM_ICMP6_ECHO_REPLY_SEQ,
395 	ITEM_ICMP6_ND_NS,
396 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
397 	ITEM_ICMP6_ND_NA,
398 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
399 	ITEM_ICMP6_ND_OPT,
400 	ITEM_ICMP6_ND_OPT_TYPE,
401 	ITEM_ICMP6_ND_OPT_SLA_ETH,
402 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
403 	ITEM_ICMP6_ND_OPT_TLA_ETH,
404 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
405 	ITEM_META,
406 	ITEM_META_DATA,
407 	ITEM_GRE_KEY,
408 	ITEM_GRE_KEY_VALUE,
409 	ITEM_GRE_OPTION,
410 	ITEM_GRE_OPTION_CHECKSUM,
411 	ITEM_GRE_OPTION_KEY,
412 	ITEM_GRE_OPTION_SEQUENCE,
413 	ITEM_GTP_PSC,
414 	ITEM_GTP_PSC_QFI,
415 	ITEM_GTP_PSC_PDU_T,
416 	ITEM_PPPOES,
417 	ITEM_PPPOED,
418 	ITEM_PPPOE_SEID,
419 	ITEM_PPPOE_PROTO_ID,
420 	ITEM_HIGIG2,
421 	ITEM_HIGIG2_CLASSIFICATION,
422 	ITEM_HIGIG2_VID,
423 	ITEM_TAG,
424 	ITEM_TAG_DATA,
425 	ITEM_TAG_INDEX,
426 	ITEM_L2TPV3OIP,
427 	ITEM_L2TPV3OIP_SESSION_ID,
428 	ITEM_ESP,
429 	ITEM_ESP_SPI,
430 	ITEM_AH,
431 	ITEM_AH_SPI,
432 	ITEM_PFCP,
433 	ITEM_PFCP_S_FIELD,
434 	ITEM_PFCP_SEID,
435 	ITEM_ECPRI,
436 	ITEM_ECPRI_COMMON,
437 	ITEM_ECPRI_COMMON_TYPE,
438 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
439 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
440 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
441 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
442 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
443 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
444 	ITEM_GENEVE_OPT,
445 	ITEM_GENEVE_OPT_CLASS,
446 	ITEM_GENEVE_OPT_TYPE,
447 	ITEM_GENEVE_OPT_LENGTH,
448 	ITEM_GENEVE_OPT_DATA,
449 	ITEM_INTEGRITY,
450 	ITEM_INTEGRITY_LEVEL,
451 	ITEM_INTEGRITY_VALUE,
452 	ITEM_CONNTRACK,
453 	ITEM_POL_PORT,
454 	ITEM_POL_METER,
455 	ITEM_POL_POLICY,
456 	ITEM_PORT_REPRESENTOR,
457 	ITEM_PORT_REPRESENTOR_PORT_ID,
458 	ITEM_REPRESENTED_PORT,
459 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
460 	ITEM_FLEX,
461 	ITEM_FLEX_ITEM_HANDLE,
462 	ITEM_FLEX_PATTERN_HANDLE,
463 	ITEM_L2TPV2,
464 	ITEM_L2TPV2_TYPE,
465 	ITEM_L2TPV2_TYPE_DATA,
466 	ITEM_L2TPV2_TYPE_DATA_L,
467 	ITEM_L2TPV2_TYPE_DATA_S,
468 	ITEM_L2TPV2_TYPE_DATA_O,
469 	ITEM_L2TPV2_TYPE_DATA_L_S,
470 	ITEM_L2TPV2_TYPE_CTRL,
471 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
472 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
473 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
474 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
475 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
476 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
477 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
478 	ITEM_L2TPV2_MSG_DATA_S_NS,
479 	ITEM_L2TPV2_MSG_DATA_S_NR,
480 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
481 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
482 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
483 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
484 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
485 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
486 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
487 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
488 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
489 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
490 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
491 	ITEM_L2TPV2_MSG_CTRL_NS,
492 	ITEM_L2TPV2_MSG_CTRL_NR,
493 	ITEM_PPP,
494 	ITEM_PPP_ADDR,
495 	ITEM_PPP_CTRL,
496 	ITEM_PPP_PROTO_ID,
497 	ITEM_METER,
498 	ITEM_METER_COLOR,
499 	ITEM_METER_COLOR_NAME,
500 	ITEM_QUOTA,
501 	ITEM_QUOTA_STATE,
502 	ITEM_QUOTA_STATE_NAME,
503 	ITEM_AGGR_AFFINITY,
504 	ITEM_AGGR_AFFINITY_VALUE,
505 	ITEM_TX_QUEUE,
506 	ITEM_TX_QUEUE_VALUE,
507 	ITEM_IB_BTH,
508 	ITEM_IB_BTH_OPCODE,
509 	ITEM_IB_BTH_PKEY,
510 	ITEM_IB_BTH_DST_QPN,
511 	ITEM_IB_BTH_PSN,
512 
513 	/* Validate/create actions. */
514 	ACTIONS,
515 	ACTION_NEXT,
516 	ACTION_END,
517 	ACTION_VOID,
518 	ACTION_PASSTHRU,
519 	ACTION_SKIP_CMAN,
520 	ACTION_JUMP,
521 	ACTION_JUMP_GROUP,
522 	ACTION_MARK,
523 	ACTION_MARK_ID,
524 	ACTION_FLAG,
525 	ACTION_QUEUE,
526 	ACTION_QUEUE_INDEX,
527 	ACTION_DROP,
528 	ACTION_COUNT,
529 	ACTION_COUNT_ID,
530 	ACTION_RSS,
531 	ACTION_RSS_FUNC,
532 	ACTION_RSS_LEVEL,
533 	ACTION_RSS_FUNC_DEFAULT,
534 	ACTION_RSS_FUNC_TOEPLITZ,
535 	ACTION_RSS_FUNC_SIMPLE_XOR,
536 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
537 	ACTION_RSS_TYPES,
538 	ACTION_RSS_TYPE,
539 	ACTION_RSS_KEY,
540 	ACTION_RSS_KEY_LEN,
541 	ACTION_RSS_QUEUES,
542 	ACTION_RSS_QUEUE,
543 	ACTION_PF,
544 	ACTION_VF,
545 	ACTION_VF_ORIGINAL,
546 	ACTION_VF_ID,
547 	ACTION_PORT_ID,
548 	ACTION_PORT_ID_ORIGINAL,
549 	ACTION_PORT_ID_ID,
550 	ACTION_METER,
551 	ACTION_METER_COLOR,
552 	ACTION_METER_COLOR_TYPE,
553 	ACTION_METER_COLOR_GREEN,
554 	ACTION_METER_COLOR_YELLOW,
555 	ACTION_METER_COLOR_RED,
556 	ACTION_METER_ID,
557 	ACTION_METER_MARK,
558 	ACTION_METER_PROFILE,
559 	ACTION_METER_PROFILE_ID2PTR,
560 	ACTION_METER_POLICY,
561 	ACTION_METER_POLICY_ID2PTR,
562 	ACTION_METER_COLOR_MODE,
563 	ACTION_METER_INIT_COLOR,
564 	ACTION_METER_STATE,
565 	ACTION_OF_DEC_NW_TTL,
566 	ACTION_OF_POP_VLAN,
567 	ACTION_OF_PUSH_VLAN,
568 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
569 	ACTION_OF_SET_VLAN_VID,
570 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
571 	ACTION_OF_SET_VLAN_PCP,
572 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
573 	ACTION_OF_POP_MPLS,
574 	ACTION_OF_POP_MPLS_ETHERTYPE,
575 	ACTION_OF_PUSH_MPLS,
576 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
577 	ACTION_VXLAN_ENCAP,
578 	ACTION_VXLAN_DECAP,
579 	ACTION_NVGRE_ENCAP,
580 	ACTION_NVGRE_DECAP,
581 	ACTION_L2_ENCAP,
582 	ACTION_L2_DECAP,
583 	ACTION_MPLSOGRE_ENCAP,
584 	ACTION_MPLSOGRE_DECAP,
585 	ACTION_MPLSOUDP_ENCAP,
586 	ACTION_MPLSOUDP_DECAP,
587 	ACTION_SET_IPV4_SRC,
588 	ACTION_SET_IPV4_SRC_IPV4_SRC,
589 	ACTION_SET_IPV4_DST,
590 	ACTION_SET_IPV4_DST_IPV4_DST,
591 	ACTION_SET_IPV6_SRC,
592 	ACTION_SET_IPV6_SRC_IPV6_SRC,
593 	ACTION_SET_IPV6_DST,
594 	ACTION_SET_IPV6_DST_IPV6_DST,
595 	ACTION_SET_TP_SRC,
596 	ACTION_SET_TP_SRC_TP_SRC,
597 	ACTION_SET_TP_DST,
598 	ACTION_SET_TP_DST_TP_DST,
599 	ACTION_MAC_SWAP,
600 	ACTION_DEC_TTL,
601 	ACTION_SET_TTL,
602 	ACTION_SET_TTL_TTL,
603 	ACTION_SET_MAC_SRC,
604 	ACTION_SET_MAC_SRC_MAC_SRC,
605 	ACTION_SET_MAC_DST,
606 	ACTION_SET_MAC_DST_MAC_DST,
607 	ACTION_INC_TCP_SEQ,
608 	ACTION_INC_TCP_SEQ_VALUE,
609 	ACTION_DEC_TCP_SEQ,
610 	ACTION_DEC_TCP_SEQ_VALUE,
611 	ACTION_INC_TCP_ACK,
612 	ACTION_INC_TCP_ACK_VALUE,
613 	ACTION_DEC_TCP_ACK,
614 	ACTION_DEC_TCP_ACK_VALUE,
615 	ACTION_RAW_ENCAP,
616 	ACTION_RAW_DECAP,
617 	ACTION_RAW_ENCAP_INDEX,
618 	ACTION_RAW_ENCAP_INDEX_VALUE,
619 	ACTION_RAW_DECAP_INDEX,
620 	ACTION_RAW_DECAP_INDEX_VALUE,
621 	ACTION_SET_TAG,
622 	ACTION_SET_TAG_DATA,
623 	ACTION_SET_TAG_INDEX,
624 	ACTION_SET_TAG_MASK,
625 	ACTION_SET_META,
626 	ACTION_SET_META_DATA,
627 	ACTION_SET_META_MASK,
628 	ACTION_SET_IPV4_DSCP,
629 	ACTION_SET_IPV4_DSCP_VALUE,
630 	ACTION_SET_IPV6_DSCP,
631 	ACTION_SET_IPV6_DSCP_VALUE,
632 	ACTION_AGE,
633 	ACTION_AGE_TIMEOUT,
634 	ACTION_AGE_UPDATE,
635 	ACTION_AGE_UPDATE_TIMEOUT,
636 	ACTION_AGE_UPDATE_TOUCH,
637 	ACTION_SAMPLE,
638 	ACTION_SAMPLE_RATIO,
639 	ACTION_SAMPLE_INDEX,
640 	ACTION_SAMPLE_INDEX_VALUE,
641 	ACTION_INDIRECT,
642 	ACTION_INDIRECT_LIST,
643 	ACTION_INDIRECT_LIST_HANDLE,
644 	ACTION_INDIRECT_LIST_CONF,
645 	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
646 	INDIRECT_LIST_ACTION_ID2PTR_CONF,
647 	ACTION_SHARED_INDIRECT,
648 	INDIRECT_ACTION_PORT,
649 	INDIRECT_ACTION_ID2PTR,
650 	ACTION_MODIFY_FIELD,
651 	ACTION_MODIFY_FIELD_OP,
652 	ACTION_MODIFY_FIELD_OP_VALUE,
653 	ACTION_MODIFY_FIELD_DST_TYPE,
654 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
655 	ACTION_MODIFY_FIELD_DST_LEVEL,
656 	ACTION_MODIFY_FIELD_DST_LEVEL_VALUE,
657 	ACTION_MODIFY_FIELD_DST_OFFSET,
658 	ACTION_MODIFY_FIELD_SRC_TYPE,
659 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
660 	ACTION_MODIFY_FIELD_SRC_LEVEL,
661 	ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE,
662 	ACTION_MODIFY_FIELD_SRC_OFFSET,
663 	ACTION_MODIFY_FIELD_SRC_VALUE,
664 	ACTION_MODIFY_FIELD_SRC_POINTER,
665 	ACTION_MODIFY_FIELD_WIDTH,
666 	ACTION_CONNTRACK,
667 	ACTION_CONNTRACK_UPDATE,
668 	ACTION_CONNTRACK_UPDATE_DIR,
669 	ACTION_CONNTRACK_UPDATE_CTX,
670 	ACTION_POL_G,
671 	ACTION_POL_Y,
672 	ACTION_POL_R,
673 	ACTION_PORT_REPRESENTOR,
674 	ACTION_PORT_REPRESENTOR_PORT_ID,
675 	ACTION_REPRESENTED_PORT,
676 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
677 	ACTION_SEND_TO_KERNEL,
678 	ACTION_QUOTA_CREATE,
679 	ACTION_QUOTA_CREATE_LIMIT,
680 	ACTION_QUOTA_CREATE_MODE,
681 	ACTION_QUOTA_CREATE_MODE_NAME,
682 	ACTION_QUOTA_QU,
683 	ACTION_QUOTA_QU_LIMIT,
684 	ACTION_QUOTA_QU_UPDATE_OP,
685 	ACTION_QUOTA_QU_UPDATE_OP_NAME,
686 };
687 
688 /** Maximum size for pattern in struct rte_flow_item_raw. */
689 #define ITEM_RAW_PATTERN_SIZE 512
690 
691 /** Maximum size for GENEVE option data pattern in bytes. */
692 #define ITEM_GENEVE_OPT_DATA_SIZE 124
693 
694 /** Storage size for struct rte_flow_item_raw including pattern. */
695 #define ITEM_RAW_SIZE \
696 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
697 
698 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */
699 #define ACTION_MODIFY_PATTERN_SIZE 32
700 
701 /** Storage size for struct rte_flow_action_modify_field including pattern. */
702 #define ACTION_MODIFY_SIZE \
703 	(sizeof(struct rte_flow_action_modify_field) + \
704 	ACTION_MODIFY_PATTERN_SIZE)
705 
706 /** Maximum number of queue indices in struct rte_flow_action_rss. */
707 #define ACTION_RSS_QUEUE_NUM 128
708 
709 /** Storage for struct rte_flow_action_rss including external data. */
710 struct action_rss_data {
711 	struct rte_flow_action_rss conf;
712 	uint8_t key[RSS_HASH_KEY_LENGTH];
713 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
714 };
715 
716 /** Maximum data size in struct rte_flow_action_raw_encap. */
717 #define ACTION_RAW_ENCAP_MAX_DATA 512
718 #define RAW_ENCAP_CONFS_MAX_NUM 8
719 
720 /** Storage for struct rte_flow_action_raw_encap. */
721 struct raw_encap_conf {
722 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
723 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
724 	size_t size;
725 };
726 
727 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
728 
729 /** Storage for struct rte_flow_action_raw_encap including external data. */
730 struct action_raw_encap_data {
731 	struct rte_flow_action_raw_encap conf;
732 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
733 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
734 	uint16_t idx;
735 };
736 
737 /** Storage for struct rte_flow_action_raw_decap. */
738 struct raw_decap_conf {
739 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
740 	size_t size;
741 };
742 
743 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
744 
745 /** Storage for struct rte_flow_action_raw_decap including external data. */
746 struct action_raw_decap_data {
747 	struct rte_flow_action_raw_decap conf;
748 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
749 	uint16_t idx;
750 };
751 
752 struct vxlan_encap_conf vxlan_encap_conf = {
753 	.select_ipv4 = 1,
754 	.select_vlan = 0,
755 	.select_tos_ttl = 0,
756 	.vni = "\x00\x00\x00",
757 	.udp_src = 0,
758 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
759 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
760 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
761 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
762 		"\x00\x00\x00\x00\x00\x00\x00\x01",
763 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
764 		"\x00\x00\x00\x00\x00\x00\x11\x11",
765 	.vlan_tci = 0,
766 	.ip_tos = 0,
767 	.ip_ttl = 255,
768 	.eth_src = "\x00\x00\x00\x00\x00\x00",
769 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
770 };
771 
772 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
773 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
774 
775 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
776 struct action_vxlan_encap_data {
777 	struct rte_flow_action_vxlan_encap conf;
778 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
779 	struct rte_flow_item_eth item_eth;
780 	struct rte_flow_item_vlan item_vlan;
781 	union {
782 		struct rte_flow_item_ipv4 item_ipv4;
783 		struct rte_flow_item_ipv6 item_ipv6;
784 	};
785 	struct rte_flow_item_udp item_udp;
786 	struct rte_flow_item_vxlan item_vxlan;
787 };
788 
789 struct nvgre_encap_conf nvgre_encap_conf = {
790 	.select_ipv4 = 1,
791 	.select_vlan = 0,
792 	.tni = "\x00\x00\x00",
793 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
794 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
795 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
796 		"\x00\x00\x00\x00\x00\x00\x00\x01",
797 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
798 		"\x00\x00\x00\x00\x00\x00\x11\x11",
799 	.vlan_tci = 0,
800 	.eth_src = "\x00\x00\x00\x00\x00\x00",
801 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
802 };
803 
804 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
805 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
806 
807 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
808 struct action_nvgre_encap_data {
809 	struct rte_flow_action_nvgre_encap conf;
810 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
811 	struct rte_flow_item_eth item_eth;
812 	struct rte_flow_item_vlan item_vlan;
813 	union {
814 		struct rte_flow_item_ipv4 item_ipv4;
815 		struct rte_flow_item_ipv6 item_ipv6;
816 	};
817 	struct rte_flow_item_nvgre item_nvgre;
818 };
819 
820 struct l2_encap_conf l2_encap_conf;
821 
822 struct l2_decap_conf l2_decap_conf;
823 
824 struct mplsogre_encap_conf mplsogre_encap_conf;
825 
826 struct mplsogre_decap_conf mplsogre_decap_conf;
827 
828 struct mplsoudp_encap_conf mplsoudp_encap_conf;
829 
830 struct mplsoudp_decap_conf mplsoudp_decap_conf;
831 
832 struct rte_flow_action_conntrack conntrack_context;
833 
834 #define ACTION_SAMPLE_ACTIONS_NUM 10
835 #define RAW_SAMPLE_CONFS_MAX_NUM 8
836 /** Storage for struct rte_flow_action_sample including external data. */
837 struct action_sample_data {
838 	struct rte_flow_action_sample conf;
839 	uint32_t idx;
840 };
841 /** Storage for struct rte_flow_action_sample. */
842 struct raw_sample_conf {
843 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
844 };
845 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
846 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
847 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
848 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
849 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
850 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
851 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
852 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
853 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
854 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
855 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM];
856 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM];
857 
858 static const char *const modify_field_ops[] = {
859 	"set", "add", "sub", NULL
860 };
861 
862 static const char *const modify_field_ids[] = {
863 	"start", "mac_dst", "mac_src",
864 	"vlan_type", "vlan_id", "mac_type",
865 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
866 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
867 	"tcp_port_src", "tcp_port_dst",
868 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
869 	"udp_port_src", "udp_port_dst",
870 	"vxlan_vni", "geneve_vni", "gtp_teid",
871 	"tag", "mark", "meta", "pointer", "value",
872 	"ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color",
873 	"ipv6_proto",
874 	"flex_item",
875 	"hash_result", NULL
876 };
877 
878 static const char *const meter_colors[] = {
879 	"green", "yellow", "red", "all", NULL
880 };
881 
882 static const char *const table_insertion_types[] = {
883 	"pattern", "index", NULL
884 };
885 
886 static const char *const table_hash_funcs[] = {
887 	"default", "linear", "crc32", "crc16", NULL
888 };
889 
890 #define RAW_IPSEC_CONFS_MAX_NUM 8
891 
892 /** Maximum number of subsequent tokens and arguments on the stack. */
893 #define CTX_STACK_SIZE 16
894 
895 /** Parser context. */
896 struct context {
897 	/** Stack of subsequent token lists to process. */
898 	const enum index *next[CTX_STACK_SIZE];
899 	/** Arguments for stacked tokens. */
900 	const void *args[CTX_STACK_SIZE];
901 	enum index curr; /**< Current token index. */
902 	enum index prev; /**< Index of the last token seen. */
903 	int next_num; /**< Number of entries in next[]. */
904 	int args_num; /**< Number of entries in args[]. */
905 	uint32_t eol:1; /**< EOL has been detected. */
906 	uint32_t last:1; /**< No more arguments. */
907 	portid_t port; /**< Current port ID (for completions). */
908 	uint32_t objdata; /**< Object-specific data. */
909 	void *object; /**< Address of current object for relative offsets. */
910 	void *objmask; /**< Object a full mask must be written to. */
911 };
912 
913 /** Token argument. */
914 struct arg {
915 	uint32_t hton:1; /**< Use network byte ordering. */
916 	uint32_t sign:1; /**< Value is signed. */
917 	uint32_t bounded:1; /**< Value is bounded. */
918 	uintmax_t min; /**< Minimum value if bounded. */
919 	uintmax_t max; /**< Maximum value if bounded. */
920 	uint32_t offset; /**< Relative offset from ctx->object. */
921 	uint32_t size; /**< Field size. */
922 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
923 };
924 
925 /** Parser token definition. */
926 struct token {
927 	/** Type displayed during completion (defaults to "TOKEN"). */
928 	const char *type;
929 	/** Help displayed during completion (defaults to token name). */
930 	const char *help;
931 	/** Private data used by parser functions. */
932 	const void *priv;
933 	/**
934 	 * Lists of subsequent tokens to push on the stack. Each call to the
935 	 * parser consumes the last entry of that stack.
936 	 */
937 	const enum index *const *next;
938 	/** Arguments stack for subsequent tokens that need them. */
939 	const struct arg *const *args;
940 	/**
941 	 * Token-processing callback, returns -1 in case of error, the
942 	 * length of the matched string otherwise. If NULL, attempts to
943 	 * match the token name.
944 	 *
945 	 * If buf is not NULL, the result should be stored in it according
946 	 * to context. An error is returned if not large enough.
947 	 */
948 	int (*call)(struct context *ctx, const struct token *token,
949 		    const char *str, unsigned int len,
950 		    void *buf, unsigned int size);
951 	/**
952 	 * Callback that provides possible values for this token, used for
953 	 * completion. Returns -1 in case of error, the number of possible
954 	 * values otherwise. If NULL, the token name is used.
955 	 *
956 	 * If buf is not NULL, entry index ent is written to buf and the
957 	 * full length of the entry is returned (same behavior as
958 	 * snprintf()).
959 	 */
960 	int (*comp)(struct context *ctx, const struct token *token,
961 		    unsigned int ent, char *buf, unsigned int size);
962 	/** Mandatory token name, no default value. */
963 	const char *name;
964 };
965 
966 /** Static initializer for the next field. */
967 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
968 
969 /** Static initializer for a NEXT() entry. */
970 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
971 
972 /** Static initializer for the args field. */
973 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
974 
975 /** Static initializer for ARGS() to target a field. */
976 #define ARGS_ENTRY(s, f) \
977 	(&(const struct arg){ \
978 		.offset = offsetof(s, f), \
979 		.size = sizeof(((s *)0)->f), \
980 	})
981 
982 /** Static initializer for ARGS() to target a bit-field. */
983 #define ARGS_ENTRY_BF(s, f, b) \
984 	(&(const struct arg){ \
985 		.size = sizeof(s), \
986 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
987 	})
988 
989 /** Static initializer for ARGS() to target a field with limits. */
990 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
991 	(&(const struct arg){ \
992 		.bounded = 1, \
993 		.min = (i), \
994 		.max = (a), \
995 		.offset = offsetof(s, f), \
996 		.size = sizeof(((s *)0)->f), \
997 	})
998 
999 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
1000 #define ARGS_ENTRY_MASK(s, f, m) \
1001 	(&(const struct arg){ \
1002 		.offset = offsetof(s, f), \
1003 		.size = sizeof(((s *)0)->f), \
1004 		.mask = (const void *)(m), \
1005 	})
1006 
1007 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
1008 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
1009 	(&(const struct arg){ \
1010 		.hton = 1, \
1011 		.offset = offsetof(s, f), \
1012 		.size = sizeof(((s *)0)->f), \
1013 		.mask = (const void *)(m), \
1014 	})
1015 
1016 /** Static initializer for ARGS() to target a pointer. */
1017 #define ARGS_ENTRY_PTR(s, f) \
1018 	(&(const struct arg){ \
1019 		.size = sizeof(*((s *)0)->f), \
1020 	})
1021 
1022 /** Static initializer for ARGS() with arbitrary offset and size. */
1023 #define ARGS_ENTRY_ARB(o, s) \
1024 	(&(const struct arg){ \
1025 		.offset = (o), \
1026 		.size = (s), \
1027 	})
1028 
1029 /** Same as ARGS_ENTRY_ARB() with bounded values. */
1030 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
1031 	(&(const struct arg){ \
1032 		.bounded = 1, \
1033 		.min = (i), \
1034 		.max = (a), \
1035 		.offset = (o), \
1036 		.size = (s), \
1037 	})
1038 
1039 /** Same as ARGS_ENTRY() using network byte ordering. */
1040 #define ARGS_ENTRY_HTON(s, f) \
1041 	(&(const struct arg){ \
1042 		.hton = 1, \
1043 		.offset = offsetof(s, f), \
1044 		.size = sizeof(((s *)0)->f), \
1045 	})
1046 
1047 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
1048 #define ARG_ENTRY_HTON(s) \
1049 	(&(const struct arg){ \
1050 		.hton = 1, \
1051 		.offset = 0, \
1052 		.size = sizeof(s), \
1053 	})
1054 
1055 /** Parser output buffer layout expected by cmd_flow_parsed(). */
1056 struct buffer {
1057 	enum index command; /**< Flow command. */
1058 	portid_t port; /**< Affected port ID. */
1059 	queueid_t queue; /** Async queue ID. */
1060 	bool postpone; /** Postpone async operation */
1061 	union {
1062 		struct {
1063 			struct rte_flow_port_attr port_attr;
1064 			uint32_t nb_queue;
1065 			struct rte_flow_queue_attr queue_attr;
1066 		} configure; /**< Configuration arguments. */
1067 		struct {
1068 			uint32_t *template_id;
1069 			uint32_t template_id_n;
1070 		} templ_destroy; /**< Template destroy arguments. */
1071 		struct {
1072 			uint32_t id;
1073 			struct rte_flow_template_table_attr attr;
1074 			uint32_t *pat_templ_id;
1075 			uint32_t pat_templ_id_n;
1076 			uint32_t *act_templ_id;
1077 			uint32_t act_templ_id_n;
1078 		} table; /**< Table arguments. */
1079 		struct {
1080 			uint32_t *table_id;
1081 			uint32_t table_id_n;
1082 		} table_destroy; /**< Template destroy arguments. */
1083 		struct {
1084 			uint32_t *action_id;
1085 			uint32_t action_id_n;
1086 		} ia_destroy; /**< Indirect action destroy arguments. */
1087 		struct {
1088 			uint32_t action_id;
1089 			enum rte_flow_query_update_mode qu_mode;
1090 		} ia; /* Indirect action query arguments */
1091 		struct {
1092 			uint32_t table_id;
1093 			uint32_t pat_templ_id;
1094 			uint32_t rule_id;
1095 			uint32_t act_templ_id;
1096 			struct rte_flow_attr attr;
1097 			struct tunnel_ops tunnel_ops;
1098 			struct rte_flow_item *pattern;
1099 			struct rte_flow_action *actions;
1100 			struct rte_flow_action *masks;
1101 			uint32_t pattern_n;
1102 			uint32_t actions_n;
1103 			uint8_t *data;
1104 		} vc; /**< Validate/create arguments. */
1105 		struct {
1106 			uint32_t *rule;
1107 			uint32_t rule_n;
1108 		} destroy; /**< Destroy arguments. */
1109 		struct {
1110 			char file[128];
1111 			bool mode;
1112 			uint32_t rule;
1113 		} dump; /**< Dump arguments. */
1114 		struct {
1115 			uint32_t rule;
1116 			struct rte_flow_action action;
1117 		} query; /**< Query arguments. */
1118 		struct {
1119 			uint32_t *group;
1120 			uint32_t group_n;
1121 		} list; /**< List arguments. */
1122 		struct {
1123 			int set;
1124 		} isolate; /**< Isolated mode arguments. */
1125 		struct {
1126 			int destroy;
1127 		} aged; /**< Aged arguments. */
1128 		struct {
1129 			uint32_t policy_id;
1130 		} policy;/**< Policy arguments. */
1131 		struct {
1132 			uint16_t token;
1133 			uintptr_t uintptr;
1134 			char filename[128];
1135 		} flex; /**< Flex arguments*/
1136 	} args; /**< Command arguments. */
1137 };
1138 
1139 /** Private data for pattern items. */
1140 struct parse_item_priv {
1141 	enum rte_flow_item_type type; /**< Item type. */
1142 	uint32_t size; /**< Size of item specification structure. */
1143 };
1144 
1145 #define PRIV_ITEM(t, s) \
1146 	(&(const struct parse_item_priv){ \
1147 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
1148 		.size = s, \
1149 	})
1150 
1151 /** Private data for actions. */
1152 struct parse_action_priv {
1153 	enum rte_flow_action_type type; /**< Action type. */
1154 	uint32_t size; /**< Size of action configuration structure. */
1155 };
1156 
1157 #define PRIV_ACTION(t, s) \
1158 	(&(const struct parse_action_priv){ \
1159 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
1160 		.size = s, \
1161 	})
1162 
1163 static const enum index next_flex_item[] = {
1164 	FLEX_ITEM_INIT,
1165 	FLEX_ITEM_CREATE,
1166 	FLEX_ITEM_DESTROY,
1167 	ZERO,
1168 };
1169 
1170 static const enum index next_config_attr[] = {
1171 	CONFIG_QUEUES_NUMBER,
1172 	CONFIG_QUEUES_SIZE,
1173 	CONFIG_COUNTERS_NUMBER,
1174 	CONFIG_AGING_OBJECTS_NUMBER,
1175 	CONFIG_METERS_NUMBER,
1176 	CONFIG_CONN_TRACK_NUMBER,
1177 	CONFIG_QUOTAS_NUMBER,
1178 	CONFIG_FLAGS,
1179 	CONFIG_HOST_PORT,
1180 	END,
1181 	ZERO,
1182 };
1183 
1184 static const enum index next_pt_subcmd[] = {
1185 	PATTERN_TEMPLATE_CREATE,
1186 	PATTERN_TEMPLATE_DESTROY,
1187 	ZERO,
1188 };
1189 
1190 static const enum index next_pt_attr[] = {
1191 	PATTERN_TEMPLATE_CREATE_ID,
1192 	PATTERN_TEMPLATE_RELAXED_MATCHING,
1193 	PATTERN_TEMPLATE_INGRESS,
1194 	PATTERN_TEMPLATE_EGRESS,
1195 	PATTERN_TEMPLATE_TRANSFER,
1196 	PATTERN_TEMPLATE_SPEC,
1197 	ZERO,
1198 };
1199 
1200 static const enum index next_pt_destroy_attr[] = {
1201 	PATTERN_TEMPLATE_DESTROY_ID,
1202 	END,
1203 	ZERO,
1204 };
1205 
1206 static const enum index next_at_subcmd[] = {
1207 	ACTIONS_TEMPLATE_CREATE,
1208 	ACTIONS_TEMPLATE_DESTROY,
1209 	ZERO,
1210 };
1211 
1212 static const enum index next_at_attr[] = {
1213 	ACTIONS_TEMPLATE_CREATE_ID,
1214 	ACTIONS_TEMPLATE_INGRESS,
1215 	ACTIONS_TEMPLATE_EGRESS,
1216 	ACTIONS_TEMPLATE_TRANSFER,
1217 	ACTIONS_TEMPLATE_SPEC,
1218 	ZERO,
1219 };
1220 
1221 static const enum index next_at_destroy_attr[] = {
1222 	ACTIONS_TEMPLATE_DESTROY_ID,
1223 	END,
1224 	ZERO,
1225 };
1226 
1227 static const enum index next_table_subcmd[] = {
1228 	TABLE_CREATE,
1229 	TABLE_DESTROY,
1230 	ZERO,
1231 };
1232 
1233 static const enum index next_table_attr[] = {
1234 	TABLE_CREATE_ID,
1235 	TABLE_GROUP,
1236 	TABLE_INSERTION_TYPE,
1237 	TABLE_HASH_FUNC,
1238 	TABLE_PRIORITY,
1239 	TABLE_INGRESS,
1240 	TABLE_EGRESS,
1241 	TABLE_TRANSFER,
1242 	TABLE_TRANSFER_WIRE_ORIG,
1243 	TABLE_TRANSFER_VPORT_ORIG,
1244 	TABLE_RULES_NUMBER,
1245 	TABLE_PATTERN_TEMPLATE,
1246 	TABLE_ACTIONS_TEMPLATE,
1247 	END,
1248 	ZERO,
1249 };
1250 
1251 static const enum index next_table_destroy_attr[] = {
1252 	TABLE_DESTROY_ID,
1253 	END,
1254 	ZERO,
1255 };
1256 
1257 static const enum index next_queue_subcmd[] = {
1258 	QUEUE_CREATE,
1259 	QUEUE_DESTROY,
1260 	QUEUE_AGED,
1261 	QUEUE_INDIRECT_ACTION,
1262 	ZERO,
1263 };
1264 
1265 static const enum index next_queue_destroy_attr[] = {
1266 	QUEUE_DESTROY_ID,
1267 	END,
1268 	ZERO,
1269 };
1270 
1271 static const enum index next_qia_subcmd[] = {
1272 	QUEUE_INDIRECT_ACTION_CREATE,
1273 	QUEUE_INDIRECT_ACTION_UPDATE,
1274 	QUEUE_INDIRECT_ACTION_DESTROY,
1275 	QUEUE_INDIRECT_ACTION_QUERY,
1276 	QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
1277 	ZERO,
1278 };
1279 
1280 static const enum index next_qia_create_attr[] = {
1281 	QUEUE_INDIRECT_ACTION_CREATE_ID,
1282 	QUEUE_INDIRECT_ACTION_INGRESS,
1283 	QUEUE_INDIRECT_ACTION_EGRESS,
1284 	QUEUE_INDIRECT_ACTION_TRANSFER,
1285 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
1286 	QUEUE_INDIRECT_ACTION_SPEC,
1287 	QUEUE_INDIRECT_ACTION_LIST,
1288 	ZERO,
1289 };
1290 
1291 static const enum index next_qia_update_attr[] = {
1292 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1293 	QUEUE_INDIRECT_ACTION_SPEC,
1294 	ZERO,
1295 };
1296 
1297 static const enum index next_qia_destroy_attr[] = {
1298 	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
1299 	QUEUE_INDIRECT_ACTION_DESTROY_ID,
1300 	END,
1301 	ZERO,
1302 };
1303 
1304 static const enum index next_qia_query_attr[] = {
1305 	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
1306 	END,
1307 	ZERO,
1308 };
1309 
1310 static const enum index next_ia_create_attr[] = {
1311 	INDIRECT_ACTION_CREATE_ID,
1312 	INDIRECT_ACTION_INGRESS,
1313 	INDIRECT_ACTION_EGRESS,
1314 	INDIRECT_ACTION_TRANSFER,
1315 	INDIRECT_ACTION_SPEC,
1316 	INDIRECT_ACTION_LIST,
1317 	INDIRECT_ACTION_FLOW_CONF,
1318 	ZERO,
1319 };
1320 
1321 static const enum index next_ia[] = {
1322 	INDIRECT_ACTION_ID2PTR,
1323 	ACTION_NEXT,
1324 	ZERO
1325 };
1326 
1327 static const enum index next_ial[] = {
1328 	ACTION_INDIRECT_LIST_HANDLE,
1329 	ACTION_INDIRECT_LIST_CONF,
1330 	ACTION_NEXT,
1331 	ZERO
1332 };
1333 
1334 static const enum index next_qia_qu_attr[] = {
1335 	QUEUE_INDIRECT_ACTION_QU_MODE,
1336 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
1337 	INDIRECT_ACTION_SPEC,
1338 	ZERO
1339 };
1340 
1341 static const enum index next_ia_qu_attr[] = {
1342 	INDIRECT_ACTION_QU_MODE,
1343 	INDIRECT_ACTION_SPEC,
1344 	ZERO
1345 };
1346 
1347 static const enum index next_dump_subcmd[] = {
1348 	DUMP_ALL,
1349 	DUMP_ONE,
1350 	ZERO,
1351 };
1352 
1353 static const enum index next_ia_subcmd[] = {
1354 	INDIRECT_ACTION_CREATE,
1355 	INDIRECT_ACTION_UPDATE,
1356 	INDIRECT_ACTION_DESTROY,
1357 	INDIRECT_ACTION_QUERY,
1358 	INDIRECT_ACTION_QUERY_UPDATE,
1359 	ZERO,
1360 };
1361 
1362 static const enum index next_vc_attr[] = {
1363 	VC_GROUP,
1364 	VC_PRIORITY,
1365 	VC_INGRESS,
1366 	VC_EGRESS,
1367 	VC_TRANSFER,
1368 	VC_TUNNEL_SET,
1369 	VC_TUNNEL_MATCH,
1370 	ITEM_PATTERN,
1371 	ZERO,
1372 };
1373 
1374 static const enum index next_destroy_attr[] = {
1375 	DESTROY_RULE,
1376 	END,
1377 	ZERO,
1378 };
1379 
1380 static const enum index next_dump_attr[] = {
1381 	COMMON_FILE_PATH,
1382 	END,
1383 	ZERO,
1384 };
1385 
1386 static const enum index next_list_attr[] = {
1387 	LIST_GROUP,
1388 	END,
1389 	ZERO,
1390 };
1391 
1392 static const enum index next_aged_attr[] = {
1393 	AGED_DESTROY,
1394 	END,
1395 	ZERO,
1396 };
1397 
1398 static const enum index next_ia_destroy_attr[] = {
1399 	INDIRECT_ACTION_DESTROY_ID,
1400 	END,
1401 	ZERO,
1402 };
1403 
1404 static const enum index next_async_insert_subcmd[] = {
1405 	QUEUE_PATTERN_TEMPLATE,
1406 	QUEUE_RULE_ID,
1407 	ZERO,
1408 };
1409 
1410 static const enum index item_param[] = {
1411 	ITEM_PARAM_IS,
1412 	ITEM_PARAM_SPEC,
1413 	ITEM_PARAM_LAST,
1414 	ITEM_PARAM_MASK,
1415 	ITEM_PARAM_PREFIX,
1416 	ZERO,
1417 };
1418 
1419 static const enum index next_item[] = {
1420 	ITEM_END,
1421 	ITEM_VOID,
1422 	ITEM_INVERT,
1423 	ITEM_ANY,
1424 	ITEM_PORT_ID,
1425 	ITEM_MARK,
1426 	ITEM_RAW,
1427 	ITEM_ETH,
1428 	ITEM_VLAN,
1429 	ITEM_IPV4,
1430 	ITEM_IPV6,
1431 	ITEM_ICMP,
1432 	ITEM_UDP,
1433 	ITEM_TCP,
1434 	ITEM_SCTP,
1435 	ITEM_VXLAN,
1436 	ITEM_E_TAG,
1437 	ITEM_NVGRE,
1438 	ITEM_MPLS,
1439 	ITEM_GRE,
1440 	ITEM_FUZZY,
1441 	ITEM_GTP,
1442 	ITEM_GTPC,
1443 	ITEM_GTPU,
1444 	ITEM_GENEVE,
1445 	ITEM_VXLAN_GPE,
1446 	ITEM_ARP_ETH_IPV4,
1447 	ITEM_IPV6_EXT,
1448 	ITEM_IPV6_FRAG_EXT,
1449 	ITEM_IPV6_ROUTING_EXT,
1450 	ITEM_ICMP6,
1451 	ITEM_ICMP6_ECHO_REQUEST,
1452 	ITEM_ICMP6_ECHO_REPLY,
1453 	ITEM_ICMP6_ND_NS,
1454 	ITEM_ICMP6_ND_NA,
1455 	ITEM_ICMP6_ND_OPT,
1456 	ITEM_ICMP6_ND_OPT_SLA_ETH,
1457 	ITEM_ICMP6_ND_OPT_TLA_ETH,
1458 	ITEM_META,
1459 	ITEM_GRE_KEY,
1460 	ITEM_GRE_OPTION,
1461 	ITEM_GTP_PSC,
1462 	ITEM_PPPOES,
1463 	ITEM_PPPOED,
1464 	ITEM_PPPOE_PROTO_ID,
1465 	ITEM_HIGIG2,
1466 	ITEM_TAG,
1467 	ITEM_L2TPV3OIP,
1468 	ITEM_ESP,
1469 	ITEM_AH,
1470 	ITEM_PFCP,
1471 	ITEM_ECPRI,
1472 	ITEM_GENEVE_OPT,
1473 	ITEM_INTEGRITY,
1474 	ITEM_CONNTRACK,
1475 	ITEM_PORT_REPRESENTOR,
1476 	ITEM_REPRESENTED_PORT,
1477 	ITEM_FLEX,
1478 	ITEM_L2TPV2,
1479 	ITEM_PPP,
1480 	ITEM_METER,
1481 	ITEM_QUOTA,
1482 	ITEM_AGGR_AFFINITY,
1483 	ITEM_TX_QUEUE,
1484 	ITEM_IB_BTH,
1485 	END_SET,
1486 	ZERO,
1487 };
1488 
1489 static const enum index item_fuzzy[] = {
1490 	ITEM_FUZZY_THRESH,
1491 	ITEM_NEXT,
1492 	ZERO,
1493 };
1494 
1495 static const enum index item_any[] = {
1496 	ITEM_ANY_NUM,
1497 	ITEM_NEXT,
1498 	ZERO,
1499 };
1500 
1501 static const enum index item_port_id[] = {
1502 	ITEM_PORT_ID_ID,
1503 	ITEM_NEXT,
1504 	ZERO,
1505 };
1506 
1507 static const enum index item_mark[] = {
1508 	ITEM_MARK_ID,
1509 	ITEM_NEXT,
1510 	ZERO,
1511 };
1512 
1513 static const enum index item_raw[] = {
1514 	ITEM_RAW_RELATIVE,
1515 	ITEM_RAW_SEARCH,
1516 	ITEM_RAW_OFFSET,
1517 	ITEM_RAW_LIMIT,
1518 	ITEM_RAW_PATTERN,
1519 	ITEM_RAW_PATTERN_HEX,
1520 	ITEM_NEXT,
1521 	ZERO,
1522 };
1523 
1524 static const enum index item_eth[] = {
1525 	ITEM_ETH_DST,
1526 	ITEM_ETH_SRC,
1527 	ITEM_ETH_TYPE,
1528 	ITEM_ETH_HAS_VLAN,
1529 	ITEM_NEXT,
1530 	ZERO,
1531 };
1532 
1533 static const enum index item_vlan[] = {
1534 	ITEM_VLAN_TCI,
1535 	ITEM_VLAN_PCP,
1536 	ITEM_VLAN_DEI,
1537 	ITEM_VLAN_VID,
1538 	ITEM_VLAN_INNER_TYPE,
1539 	ITEM_VLAN_HAS_MORE_VLAN,
1540 	ITEM_NEXT,
1541 	ZERO,
1542 };
1543 
1544 static const enum index item_ipv4[] = {
1545 	ITEM_IPV4_VER_IHL,
1546 	ITEM_IPV4_TOS,
1547 	ITEM_IPV4_ID,
1548 	ITEM_IPV4_FRAGMENT_OFFSET,
1549 	ITEM_IPV4_TTL,
1550 	ITEM_IPV4_PROTO,
1551 	ITEM_IPV4_SRC,
1552 	ITEM_IPV4_DST,
1553 	ITEM_NEXT,
1554 	ZERO,
1555 };
1556 
1557 static const enum index item_ipv6[] = {
1558 	ITEM_IPV6_TC,
1559 	ITEM_IPV6_FLOW,
1560 	ITEM_IPV6_PROTO,
1561 	ITEM_IPV6_HOP,
1562 	ITEM_IPV6_SRC,
1563 	ITEM_IPV6_DST,
1564 	ITEM_IPV6_HAS_FRAG_EXT,
1565 	ITEM_IPV6_ROUTING_EXT,
1566 	ITEM_NEXT,
1567 	ZERO,
1568 };
1569 
1570 static const enum index item_ipv6_routing_ext[] = {
1571 	ITEM_IPV6_ROUTING_EXT_TYPE,
1572 	ITEM_IPV6_ROUTING_EXT_NEXT_HDR,
1573 	ITEM_IPV6_ROUTING_EXT_SEG_LEFT,
1574 	ITEM_NEXT,
1575 	ZERO,
1576 };
1577 
1578 static const enum index item_icmp[] = {
1579 	ITEM_ICMP_TYPE,
1580 	ITEM_ICMP_CODE,
1581 	ITEM_ICMP_IDENT,
1582 	ITEM_ICMP_SEQ,
1583 	ITEM_NEXT,
1584 	ZERO,
1585 };
1586 
1587 static const enum index item_udp[] = {
1588 	ITEM_UDP_SRC,
1589 	ITEM_UDP_DST,
1590 	ITEM_NEXT,
1591 	ZERO,
1592 };
1593 
1594 static const enum index item_tcp[] = {
1595 	ITEM_TCP_SRC,
1596 	ITEM_TCP_DST,
1597 	ITEM_TCP_FLAGS,
1598 	ITEM_NEXT,
1599 	ZERO,
1600 };
1601 
1602 static const enum index item_sctp[] = {
1603 	ITEM_SCTP_SRC,
1604 	ITEM_SCTP_DST,
1605 	ITEM_SCTP_TAG,
1606 	ITEM_SCTP_CKSUM,
1607 	ITEM_NEXT,
1608 	ZERO,
1609 };
1610 
1611 static const enum index item_vxlan[] = {
1612 	ITEM_VXLAN_VNI,
1613 	ITEM_VXLAN_LAST_RSVD,
1614 	ITEM_NEXT,
1615 	ZERO,
1616 };
1617 
1618 static const enum index item_e_tag[] = {
1619 	ITEM_E_TAG_GRP_ECID_B,
1620 	ITEM_NEXT,
1621 	ZERO,
1622 };
1623 
1624 static const enum index item_nvgre[] = {
1625 	ITEM_NVGRE_TNI,
1626 	ITEM_NEXT,
1627 	ZERO,
1628 };
1629 
1630 static const enum index item_mpls[] = {
1631 	ITEM_MPLS_LABEL,
1632 	ITEM_MPLS_TC,
1633 	ITEM_MPLS_S,
1634 	ITEM_NEXT,
1635 	ZERO,
1636 };
1637 
1638 static const enum index item_gre[] = {
1639 	ITEM_GRE_PROTO,
1640 	ITEM_GRE_C_RSVD0_VER,
1641 	ITEM_GRE_C_BIT,
1642 	ITEM_GRE_K_BIT,
1643 	ITEM_GRE_S_BIT,
1644 	ITEM_NEXT,
1645 	ZERO,
1646 };
1647 
1648 static const enum index item_gre_key[] = {
1649 	ITEM_GRE_KEY_VALUE,
1650 	ITEM_NEXT,
1651 	ZERO,
1652 };
1653 
1654 static const enum index item_gre_option[] = {
1655 	ITEM_GRE_OPTION_CHECKSUM,
1656 	ITEM_GRE_OPTION_KEY,
1657 	ITEM_GRE_OPTION_SEQUENCE,
1658 	ITEM_NEXT,
1659 	ZERO,
1660 };
1661 
1662 static const enum index item_gtp[] = {
1663 	ITEM_GTP_FLAGS,
1664 	ITEM_GTP_MSG_TYPE,
1665 	ITEM_GTP_TEID,
1666 	ITEM_NEXT,
1667 	ZERO,
1668 };
1669 
1670 static const enum index item_geneve[] = {
1671 	ITEM_GENEVE_VNI,
1672 	ITEM_GENEVE_PROTO,
1673 	ITEM_GENEVE_OPTLEN,
1674 	ITEM_NEXT,
1675 	ZERO,
1676 };
1677 
1678 static const enum index item_vxlan_gpe[] = {
1679 	ITEM_VXLAN_GPE_VNI,
1680 	ITEM_NEXT,
1681 	ZERO,
1682 };
1683 
1684 static const enum index item_arp_eth_ipv4[] = {
1685 	ITEM_ARP_ETH_IPV4_SHA,
1686 	ITEM_ARP_ETH_IPV4_SPA,
1687 	ITEM_ARP_ETH_IPV4_THA,
1688 	ITEM_ARP_ETH_IPV4_TPA,
1689 	ITEM_NEXT,
1690 	ZERO,
1691 };
1692 
1693 static const enum index item_ipv6_ext[] = {
1694 	ITEM_IPV6_EXT_NEXT_HDR,
1695 	ITEM_NEXT,
1696 	ZERO,
1697 };
1698 
1699 static const enum index item_ipv6_frag_ext[] = {
1700 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1701 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1702 	ITEM_IPV6_FRAG_EXT_ID,
1703 	ITEM_NEXT,
1704 	ZERO,
1705 };
1706 
1707 static const enum index item_icmp6[] = {
1708 	ITEM_ICMP6_TYPE,
1709 	ITEM_ICMP6_CODE,
1710 	ITEM_NEXT,
1711 	ZERO,
1712 };
1713 
1714 static const enum index item_icmp6_echo_request[] = {
1715 	ITEM_ICMP6_ECHO_REQUEST_ID,
1716 	ITEM_ICMP6_ECHO_REQUEST_SEQ,
1717 	ITEM_NEXT,
1718 	ZERO,
1719 };
1720 
1721 static const enum index item_icmp6_echo_reply[] = {
1722 	ITEM_ICMP6_ECHO_REPLY_ID,
1723 	ITEM_ICMP6_ECHO_REPLY_SEQ,
1724 	ITEM_NEXT,
1725 	ZERO,
1726 };
1727 
1728 static const enum index item_icmp6_nd_ns[] = {
1729 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1730 	ITEM_NEXT,
1731 	ZERO,
1732 };
1733 
1734 static const enum index item_icmp6_nd_na[] = {
1735 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1736 	ITEM_NEXT,
1737 	ZERO,
1738 };
1739 
1740 static const enum index item_icmp6_nd_opt[] = {
1741 	ITEM_ICMP6_ND_OPT_TYPE,
1742 	ITEM_NEXT,
1743 	ZERO,
1744 };
1745 
1746 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1747 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1748 	ITEM_NEXT,
1749 	ZERO,
1750 };
1751 
1752 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1753 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1754 	ITEM_NEXT,
1755 	ZERO,
1756 };
1757 
1758 static const enum index item_meta[] = {
1759 	ITEM_META_DATA,
1760 	ITEM_NEXT,
1761 	ZERO,
1762 };
1763 
1764 static const enum index item_gtp_psc[] = {
1765 	ITEM_GTP_PSC_QFI,
1766 	ITEM_GTP_PSC_PDU_T,
1767 	ITEM_NEXT,
1768 	ZERO,
1769 };
1770 
1771 static const enum index item_pppoed[] = {
1772 	ITEM_PPPOE_SEID,
1773 	ITEM_NEXT,
1774 	ZERO,
1775 };
1776 
1777 static const enum index item_pppoes[] = {
1778 	ITEM_PPPOE_SEID,
1779 	ITEM_NEXT,
1780 	ZERO,
1781 };
1782 
1783 static const enum index item_pppoe_proto_id[] = {
1784 	ITEM_NEXT,
1785 	ZERO,
1786 };
1787 
1788 static const enum index item_higig2[] = {
1789 	ITEM_HIGIG2_CLASSIFICATION,
1790 	ITEM_HIGIG2_VID,
1791 	ITEM_NEXT,
1792 	ZERO,
1793 };
1794 
1795 static const enum index item_esp[] = {
1796 	ITEM_ESP_SPI,
1797 	ITEM_NEXT,
1798 	ZERO,
1799 };
1800 
1801 static const enum index item_ah[] = {
1802 	ITEM_AH_SPI,
1803 	ITEM_NEXT,
1804 	ZERO,
1805 };
1806 
1807 static const enum index item_pfcp[] = {
1808 	ITEM_PFCP_S_FIELD,
1809 	ITEM_PFCP_SEID,
1810 	ITEM_NEXT,
1811 	ZERO,
1812 };
1813 
1814 static const enum index next_set_raw[] = {
1815 	SET_RAW_INDEX,
1816 	ITEM_ETH,
1817 	ZERO,
1818 };
1819 
1820 static const enum index item_tag[] = {
1821 	ITEM_TAG_DATA,
1822 	ITEM_TAG_INDEX,
1823 	ITEM_NEXT,
1824 	ZERO,
1825 };
1826 
1827 static const enum index item_l2tpv3oip[] = {
1828 	ITEM_L2TPV3OIP_SESSION_ID,
1829 	ITEM_NEXT,
1830 	ZERO,
1831 };
1832 
1833 static const enum index item_ecpri[] = {
1834 	ITEM_ECPRI_COMMON,
1835 	ITEM_NEXT,
1836 	ZERO,
1837 };
1838 
1839 static const enum index item_ecpri_common[] = {
1840 	ITEM_ECPRI_COMMON_TYPE,
1841 	ZERO,
1842 };
1843 
1844 static const enum index item_ecpri_common_type[] = {
1845 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1846 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1847 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1848 	ZERO,
1849 };
1850 
1851 static const enum index item_geneve_opt[] = {
1852 	ITEM_GENEVE_OPT_CLASS,
1853 	ITEM_GENEVE_OPT_TYPE,
1854 	ITEM_GENEVE_OPT_LENGTH,
1855 	ITEM_GENEVE_OPT_DATA,
1856 	ITEM_NEXT,
1857 	ZERO,
1858 };
1859 
1860 static const enum index item_integrity[] = {
1861 	ITEM_INTEGRITY_LEVEL,
1862 	ITEM_INTEGRITY_VALUE,
1863 	ZERO,
1864 };
1865 
1866 static const enum index item_integrity_lv[] = {
1867 	ITEM_INTEGRITY_LEVEL,
1868 	ITEM_INTEGRITY_VALUE,
1869 	ITEM_NEXT,
1870 	ZERO,
1871 };
1872 
1873 static const enum index item_port_representor[] = {
1874 	ITEM_PORT_REPRESENTOR_PORT_ID,
1875 	ITEM_NEXT,
1876 	ZERO,
1877 };
1878 
1879 static const enum index item_represented_port[] = {
1880 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1881 	ITEM_NEXT,
1882 	ZERO,
1883 };
1884 
1885 static const enum index item_flex[] = {
1886 	ITEM_FLEX_PATTERN_HANDLE,
1887 	ITEM_FLEX_ITEM_HANDLE,
1888 	ITEM_NEXT,
1889 	ZERO,
1890 };
1891 
1892 static const enum index item_l2tpv2[] = {
1893 	ITEM_L2TPV2_TYPE,
1894 	ITEM_NEXT,
1895 	ZERO,
1896 };
1897 
1898 static const enum index item_l2tpv2_type[] = {
1899 	ITEM_L2TPV2_TYPE_DATA,
1900 	ITEM_L2TPV2_TYPE_DATA_L,
1901 	ITEM_L2TPV2_TYPE_DATA_S,
1902 	ITEM_L2TPV2_TYPE_DATA_O,
1903 	ITEM_L2TPV2_TYPE_DATA_L_S,
1904 	ITEM_L2TPV2_TYPE_CTRL,
1905 	ZERO,
1906 };
1907 
1908 static const enum index item_l2tpv2_type_data[] = {
1909 	ITEM_L2TPV2_MSG_DATA_TUNNEL_ID,
1910 	ITEM_L2TPV2_MSG_DATA_SESSION_ID,
1911 	ITEM_NEXT,
1912 	ZERO,
1913 };
1914 
1915 static const enum index item_l2tpv2_type_data_l[] = {
1916 	ITEM_L2TPV2_MSG_DATA_L_LENGTH,
1917 	ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID,
1918 	ITEM_L2TPV2_MSG_DATA_L_SESSION_ID,
1919 	ITEM_NEXT,
1920 	ZERO,
1921 };
1922 
1923 static const enum index item_l2tpv2_type_data_s[] = {
1924 	ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID,
1925 	ITEM_L2TPV2_MSG_DATA_S_SESSION_ID,
1926 	ITEM_L2TPV2_MSG_DATA_S_NS,
1927 	ITEM_L2TPV2_MSG_DATA_S_NR,
1928 	ITEM_NEXT,
1929 	ZERO,
1930 };
1931 
1932 static const enum index item_l2tpv2_type_data_o[] = {
1933 	ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID,
1934 	ITEM_L2TPV2_MSG_DATA_O_SESSION_ID,
1935 	ITEM_L2TPV2_MSG_DATA_O_OFFSET,
1936 	ITEM_NEXT,
1937 	ZERO,
1938 };
1939 
1940 static const enum index item_l2tpv2_type_data_l_s[] = {
1941 	ITEM_L2TPV2_MSG_DATA_L_S_LENGTH,
1942 	ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID,
1943 	ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID,
1944 	ITEM_L2TPV2_MSG_DATA_L_S_NS,
1945 	ITEM_L2TPV2_MSG_DATA_L_S_NR,
1946 	ITEM_NEXT,
1947 	ZERO,
1948 };
1949 
1950 static const enum index item_l2tpv2_type_ctrl[] = {
1951 	ITEM_L2TPV2_MSG_CTRL_LENGTH,
1952 	ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID,
1953 	ITEM_L2TPV2_MSG_CTRL_SESSION_ID,
1954 	ITEM_L2TPV2_MSG_CTRL_NS,
1955 	ITEM_L2TPV2_MSG_CTRL_NR,
1956 	ITEM_NEXT,
1957 	ZERO,
1958 };
1959 
1960 static const enum index item_ppp[] = {
1961 	ITEM_PPP_ADDR,
1962 	ITEM_PPP_CTRL,
1963 	ITEM_PPP_PROTO_ID,
1964 	ITEM_NEXT,
1965 	ZERO,
1966 };
1967 
1968 static const enum index item_meter[] = {
1969 	ITEM_METER_COLOR,
1970 	ITEM_NEXT,
1971 	ZERO,
1972 };
1973 
1974 static const enum index item_quota[] = {
1975 	ITEM_QUOTA_STATE,
1976 	ITEM_NEXT,
1977 	ZERO,
1978 };
1979 
1980 static const enum index item_aggr_affinity[] = {
1981 	ITEM_AGGR_AFFINITY_VALUE,
1982 	ITEM_NEXT,
1983 	ZERO,
1984 };
1985 
1986 static const enum index item_tx_queue[] = {
1987 	ITEM_TX_QUEUE_VALUE,
1988 	ITEM_NEXT,
1989 	ZERO,
1990 };
1991 
1992 static const enum index item_ib_bth[] = {
1993 	ITEM_IB_BTH_OPCODE,
1994 	ITEM_IB_BTH_PKEY,
1995 	ITEM_IB_BTH_DST_QPN,
1996 	ITEM_IB_BTH_PSN,
1997 	ITEM_NEXT,
1998 	ZERO,
1999 };
2000 
2001 static const enum index next_action[] = {
2002 	ACTION_END,
2003 	ACTION_VOID,
2004 	ACTION_PASSTHRU,
2005 	ACTION_SKIP_CMAN,
2006 	ACTION_JUMP,
2007 	ACTION_MARK,
2008 	ACTION_FLAG,
2009 	ACTION_QUEUE,
2010 	ACTION_DROP,
2011 	ACTION_COUNT,
2012 	ACTION_RSS,
2013 	ACTION_PF,
2014 	ACTION_VF,
2015 	ACTION_PORT_ID,
2016 	ACTION_METER,
2017 	ACTION_METER_COLOR,
2018 	ACTION_METER_MARK,
2019 	ACTION_OF_DEC_NW_TTL,
2020 	ACTION_OF_POP_VLAN,
2021 	ACTION_OF_PUSH_VLAN,
2022 	ACTION_OF_SET_VLAN_VID,
2023 	ACTION_OF_SET_VLAN_PCP,
2024 	ACTION_OF_POP_MPLS,
2025 	ACTION_OF_PUSH_MPLS,
2026 	ACTION_VXLAN_ENCAP,
2027 	ACTION_VXLAN_DECAP,
2028 	ACTION_NVGRE_ENCAP,
2029 	ACTION_NVGRE_DECAP,
2030 	ACTION_L2_ENCAP,
2031 	ACTION_L2_DECAP,
2032 	ACTION_MPLSOGRE_ENCAP,
2033 	ACTION_MPLSOGRE_DECAP,
2034 	ACTION_MPLSOUDP_ENCAP,
2035 	ACTION_MPLSOUDP_DECAP,
2036 	ACTION_SET_IPV4_SRC,
2037 	ACTION_SET_IPV4_DST,
2038 	ACTION_SET_IPV6_SRC,
2039 	ACTION_SET_IPV6_DST,
2040 	ACTION_SET_TP_SRC,
2041 	ACTION_SET_TP_DST,
2042 	ACTION_MAC_SWAP,
2043 	ACTION_DEC_TTL,
2044 	ACTION_SET_TTL,
2045 	ACTION_SET_MAC_SRC,
2046 	ACTION_SET_MAC_DST,
2047 	ACTION_INC_TCP_SEQ,
2048 	ACTION_DEC_TCP_SEQ,
2049 	ACTION_INC_TCP_ACK,
2050 	ACTION_DEC_TCP_ACK,
2051 	ACTION_RAW_ENCAP,
2052 	ACTION_RAW_DECAP,
2053 	ACTION_SET_TAG,
2054 	ACTION_SET_META,
2055 	ACTION_SET_IPV4_DSCP,
2056 	ACTION_SET_IPV6_DSCP,
2057 	ACTION_AGE,
2058 	ACTION_AGE_UPDATE,
2059 	ACTION_SAMPLE,
2060 	ACTION_INDIRECT,
2061 	ACTION_INDIRECT_LIST,
2062 	ACTION_SHARED_INDIRECT,
2063 	ACTION_MODIFY_FIELD,
2064 	ACTION_CONNTRACK,
2065 	ACTION_CONNTRACK_UPDATE,
2066 	ACTION_PORT_REPRESENTOR,
2067 	ACTION_REPRESENTED_PORT,
2068 	ACTION_SEND_TO_KERNEL,
2069 	ACTION_QUOTA_CREATE,
2070 	ACTION_QUOTA_QU,
2071 	ZERO,
2072 };
2073 
2074 static const enum index action_quota_create[] = {
2075 	ACTION_QUOTA_CREATE_LIMIT,
2076 	ACTION_QUOTA_CREATE_MODE,
2077 	ACTION_NEXT,
2078 	ZERO
2079 };
2080 
2081 static const enum index action_quota_update[] = {
2082 	ACTION_QUOTA_QU_LIMIT,
2083 	ACTION_QUOTA_QU_UPDATE_OP,
2084 	ACTION_NEXT,
2085 	ZERO
2086 };
2087 
2088 static const enum index action_mark[] = {
2089 	ACTION_MARK_ID,
2090 	ACTION_NEXT,
2091 	ZERO,
2092 };
2093 
2094 static const enum index action_queue[] = {
2095 	ACTION_QUEUE_INDEX,
2096 	ACTION_NEXT,
2097 	ZERO,
2098 };
2099 
2100 static const enum index action_count[] = {
2101 	ACTION_COUNT_ID,
2102 	ACTION_NEXT,
2103 	ZERO,
2104 };
2105 
2106 static const enum index action_rss[] = {
2107 	ACTION_RSS_FUNC,
2108 	ACTION_RSS_LEVEL,
2109 	ACTION_RSS_TYPES,
2110 	ACTION_RSS_KEY,
2111 	ACTION_RSS_KEY_LEN,
2112 	ACTION_RSS_QUEUES,
2113 	ACTION_NEXT,
2114 	ZERO,
2115 };
2116 
2117 static const enum index action_vf[] = {
2118 	ACTION_VF_ORIGINAL,
2119 	ACTION_VF_ID,
2120 	ACTION_NEXT,
2121 	ZERO,
2122 };
2123 
2124 static const enum index action_port_id[] = {
2125 	ACTION_PORT_ID_ORIGINAL,
2126 	ACTION_PORT_ID_ID,
2127 	ACTION_NEXT,
2128 	ZERO,
2129 };
2130 
2131 static const enum index action_meter[] = {
2132 	ACTION_METER_ID,
2133 	ACTION_NEXT,
2134 	ZERO,
2135 };
2136 
2137 static const enum index action_meter_color[] = {
2138 	ACTION_METER_COLOR_TYPE,
2139 	ACTION_NEXT,
2140 	ZERO,
2141 };
2142 
2143 static const enum index action_meter_mark[] = {
2144 	ACTION_METER_PROFILE,
2145 	ACTION_METER_POLICY,
2146 	ACTION_METER_COLOR_MODE,
2147 	ACTION_METER_INIT_COLOR,
2148 	ACTION_METER_STATE,
2149 	ACTION_NEXT,
2150 	ZERO,
2151 };
2152 
2153 static const enum index action_of_push_vlan[] = {
2154 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
2155 	ACTION_NEXT,
2156 	ZERO,
2157 };
2158 
2159 static const enum index action_of_set_vlan_vid[] = {
2160 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
2161 	ACTION_NEXT,
2162 	ZERO,
2163 };
2164 
2165 static const enum index action_of_set_vlan_pcp[] = {
2166 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
2167 	ACTION_NEXT,
2168 	ZERO,
2169 };
2170 
2171 static const enum index action_of_pop_mpls[] = {
2172 	ACTION_OF_POP_MPLS_ETHERTYPE,
2173 	ACTION_NEXT,
2174 	ZERO,
2175 };
2176 
2177 static const enum index action_of_push_mpls[] = {
2178 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
2179 	ACTION_NEXT,
2180 	ZERO,
2181 };
2182 
2183 static const enum index action_set_ipv4_src[] = {
2184 	ACTION_SET_IPV4_SRC_IPV4_SRC,
2185 	ACTION_NEXT,
2186 	ZERO,
2187 };
2188 
2189 static const enum index action_set_mac_src[] = {
2190 	ACTION_SET_MAC_SRC_MAC_SRC,
2191 	ACTION_NEXT,
2192 	ZERO,
2193 };
2194 
2195 static const enum index action_set_ipv4_dst[] = {
2196 	ACTION_SET_IPV4_DST_IPV4_DST,
2197 	ACTION_NEXT,
2198 	ZERO,
2199 };
2200 
2201 static const enum index action_set_ipv6_src[] = {
2202 	ACTION_SET_IPV6_SRC_IPV6_SRC,
2203 	ACTION_NEXT,
2204 	ZERO,
2205 };
2206 
2207 static const enum index action_set_ipv6_dst[] = {
2208 	ACTION_SET_IPV6_DST_IPV6_DST,
2209 	ACTION_NEXT,
2210 	ZERO,
2211 };
2212 
2213 static const enum index action_set_tp_src[] = {
2214 	ACTION_SET_TP_SRC_TP_SRC,
2215 	ACTION_NEXT,
2216 	ZERO,
2217 };
2218 
2219 static const enum index action_set_tp_dst[] = {
2220 	ACTION_SET_TP_DST_TP_DST,
2221 	ACTION_NEXT,
2222 	ZERO,
2223 };
2224 
2225 static const enum index action_set_ttl[] = {
2226 	ACTION_SET_TTL_TTL,
2227 	ACTION_NEXT,
2228 	ZERO,
2229 };
2230 
2231 static const enum index action_jump[] = {
2232 	ACTION_JUMP_GROUP,
2233 	ACTION_NEXT,
2234 	ZERO,
2235 };
2236 
2237 static const enum index action_set_mac_dst[] = {
2238 	ACTION_SET_MAC_DST_MAC_DST,
2239 	ACTION_NEXT,
2240 	ZERO,
2241 };
2242 
2243 static const enum index action_inc_tcp_seq[] = {
2244 	ACTION_INC_TCP_SEQ_VALUE,
2245 	ACTION_NEXT,
2246 	ZERO,
2247 };
2248 
2249 static const enum index action_dec_tcp_seq[] = {
2250 	ACTION_DEC_TCP_SEQ_VALUE,
2251 	ACTION_NEXT,
2252 	ZERO,
2253 };
2254 
2255 static const enum index action_inc_tcp_ack[] = {
2256 	ACTION_INC_TCP_ACK_VALUE,
2257 	ACTION_NEXT,
2258 	ZERO,
2259 };
2260 
2261 static const enum index action_dec_tcp_ack[] = {
2262 	ACTION_DEC_TCP_ACK_VALUE,
2263 	ACTION_NEXT,
2264 	ZERO,
2265 };
2266 
2267 static const enum index action_raw_encap[] = {
2268 	ACTION_RAW_ENCAP_INDEX,
2269 	ACTION_NEXT,
2270 	ZERO,
2271 };
2272 
2273 static const enum index action_raw_decap[] = {
2274 	ACTION_RAW_DECAP_INDEX,
2275 	ACTION_NEXT,
2276 	ZERO,
2277 };
2278 
2279 static const enum index action_set_tag[] = {
2280 	ACTION_SET_TAG_DATA,
2281 	ACTION_SET_TAG_INDEX,
2282 	ACTION_SET_TAG_MASK,
2283 	ACTION_NEXT,
2284 	ZERO,
2285 };
2286 
2287 static const enum index action_set_meta[] = {
2288 	ACTION_SET_META_DATA,
2289 	ACTION_SET_META_MASK,
2290 	ACTION_NEXT,
2291 	ZERO,
2292 };
2293 
2294 static const enum index action_set_ipv4_dscp[] = {
2295 	ACTION_SET_IPV4_DSCP_VALUE,
2296 	ACTION_NEXT,
2297 	ZERO,
2298 };
2299 
2300 static const enum index action_set_ipv6_dscp[] = {
2301 	ACTION_SET_IPV6_DSCP_VALUE,
2302 	ACTION_NEXT,
2303 	ZERO,
2304 };
2305 
2306 static const enum index action_age[] = {
2307 	ACTION_AGE,
2308 	ACTION_AGE_TIMEOUT,
2309 	ACTION_NEXT,
2310 	ZERO,
2311 };
2312 
2313 static const enum index action_age_update[] = {
2314 	ACTION_AGE_UPDATE,
2315 	ACTION_AGE_UPDATE_TIMEOUT,
2316 	ACTION_AGE_UPDATE_TOUCH,
2317 	ACTION_NEXT,
2318 	ZERO,
2319 };
2320 
2321 static const enum index action_sample[] = {
2322 	ACTION_SAMPLE,
2323 	ACTION_SAMPLE_RATIO,
2324 	ACTION_SAMPLE_INDEX,
2325 	ACTION_NEXT,
2326 	ZERO,
2327 };
2328 
2329 static const enum index next_action_sample[] = {
2330 	ACTION_QUEUE,
2331 	ACTION_RSS,
2332 	ACTION_MARK,
2333 	ACTION_COUNT,
2334 	ACTION_PORT_ID,
2335 	ACTION_RAW_ENCAP,
2336 	ACTION_VXLAN_ENCAP,
2337 	ACTION_NVGRE_ENCAP,
2338 	ACTION_REPRESENTED_PORT,
2339 	ACTION_NEXT,
2340 	ZERO,
2341 };
2342 
2343 static const enum index action_modify_field_dst[] = {
2344 	ACTION_MODIFY_FIELD_DST_LEVEL,
2345 	ACTION_MODIFY_FIELD_DST_OFFSET,
2346 	ACTION_MODIFY_FIELD_SRC_TYPE,
2347 	ZERO,
2348 };
2349 
2350 static const enum index action_modify_field_src[] = {
2351 	ACTION_MODIFY_FIELD_SRC_LEVEL,
2352 	ACTION_MODIFY_FIELD_SRC_OFFSET,
2353 	ACTION_MODIFY_FIELD_SRC_VALUE,
2354 	ACTION_MODIFY_FIELD_SRC_POINTER,
2355 	ACTION_MODIFY_FIELD_WIDTH,
2356 	ZERO,
2357 };
2358 
2359 static const enum index action_update_conntrack[] = {
2360 	ACTION_CONNTRACK_UPDATE_DIR,
2361 	ACTION_CONNTRACK_UPDATE_CTX,
2362 	ACTION_NEXT,
2363 	ZERO,
2364 };
2365 
2366 static const enum index action_port_representor[] = {
2367 	ACTION_PORT_REPRESENTOR_PORT_ID,
2368 	ACTION_NEXT,
2369 	ZERO,
2370 };
2371 
2372 static const enum index action_represented_port[] = {
2373 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
2374 	ACTION_NEXT,
2375 	ZERO,
2376 };
2377 
2378 static int parse_set_raw_encap_decap(struct context *, const struct token *,
2379 				     const char *, unsigned int,
2380 				     void *, unsigned int);
2381 static int parse_set_sample_action(struct context *, const struct token *,
2382 				   const char *, unsigned int,
2383 				   void *, unsigned int);
2384 static int parse_set_init(struct context *, const struct token *,
2385 			  const char *, unsigned int,
2386 			  void *, unsigned int);
2387 static int
2388 parse_flex_handle(struct context *, const struct token *,
2389 		  const char *, unsigned int, void *, unsigned int);
2390 static int parse_init(struct context *, const struct token *,
2391 		      const char *, unsigned int,
2392 		      void *, unsigned int);
2393 static int parse_vc(struct context *, const struct token *,
2394 		    const char *, unsigned int,
2395 		    void *, unsigned int);
2396 static int parse_vc_spec(struct context *, const struct token *,
2397 			 const char *, unsigned int, void *, unsigned int);
2398 static int parse_vc_conf(struct context *, const struct token *,
2399 			 const char *, unsigned int, void *, unsigned int);
2400 static int parse_vc_conf_timeout(struct context *, const struct token *,
2401 				 const char *, unsigned int, void *,
2402 				 unsigned int);
2403 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
2404 				    const char *, unsigned int,
2405 				    void *, unsigned int);
2406 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *,
2407 				    const char *, unsigned int,
2408 				    void *, unsigned int);
2409 static int parse_vc_action_meter_color_type(struct context *,
2410 					const struct token *,
2411 					const char *, unsigned int, void *,
2412 					unsigned int);
2413 static int parse_vc_action_rss(struct context *, const struct token *,
2414 			       const char *, unsigned int, void *,
2415 			       unsigned int);
2416 static int parse_vc_action_rss_func(struct context *, const struct token *,
2417 				    const char *, unsigned int, void *,
2418 				    unsigned int);
2419 static int parse_vc_action_rss_type(struct context *, const struct token *,
2420 				    const char *, unsigned int, void *,
2421 				    unsigned int);
2422 static int parse_vc_action_rss_queue(struct context *, const struct token *,
2423 				     const char *, unsigned int, void *,
2424 				     unsigned int);
2425 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
2426 				       const char *, unsigned int, void *,
2427 				       unsigned int);
2428 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
2429 				       const char *, unsigned int, void *,
2430 				       unsigned int);
2431 static int parse_vc_action_l2_encap(struct context *, const struct token *,
2432 				    const char *, unsigned int, void *,
2433 				    unsigned int);
2434 static int parse_vc_action_l2_decap(struct context *, const struct token *,
2435 				    const char *, unsigned int, void *,
2436 				    unsigned int);
2437 static int parse_vc_action_mplsogre_encap(struct context *,
2438 					  const struct token *, const char *,
2439 					  unsigned int, void *, unsigned int);
2440 static int parse_vc_action_mplsogre_decap(struct context *,
2441 					  const struct token *, const char *,
2442 					  unsigned int, void *, unsigned int);
2443 static int parse_vc_action_mplsoudp_encap(struct context *,
2444 					  const struct token *, const char *,
2445 					  unsigned int, void *, unsigned int);
2446 static int parse_vc_action_mplsoudp_decap(struct context *,
2447 					  const struct token *, const char *,
2448 					  unsigned int, void *, unsigned int);
2449 static int parse_vc_action_raw_encap(struct context *,
2450 				     const struct token *, const char *,
2451 				     unsigned int, void *, unsigned int);
2452 static int parse_vc_action_raw_decap(struct context *,
2453 				     const struct token *, const char *,
2454 				     unsigned int, void *, unsigned int);
2455 static int parse_vc_action_raw_encap_index(struct context *,
2456 					   const struct token *, const char *,
2457 					   unsigned int, void *, unsigned int);
2458 static int parse_vc_action_raw_decap_index(struct context *,
2459 					   const struct token *, const char *,
2460 					   unsigned int, void *, unsigned int);
2461 static int parse_vc_action_set_meta(struct context *ctx,
2462 				    const struct token *token, const char *str,
2463 				    unsigned int len, void *buf,
2464 					unsigned int size);
2465 static int parse_vc_action_sample(struct context *ctx,
2466 				    const struct token *token, const char *str,
2467 				    unsigned int len, void *buf,
2468 				    unsigned int size);
2469 static int
2470 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
2471 				const char *str, unsigned int len, void *buf,
2472 				unsigned int size);
2473 static int
2474 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
2475 				const char *str, unsigned int len, void *buf,
2476 				unsigned int size);
2477 static int
2478 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
2479 				const char *str, unsigned int len, void *buf,
2480 				unsigned int size);
2481 static int
2482 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
2483 				const char *str, unsigned int len, void *buf,
2484 				unsigned int size);
2485 static int
2486 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
2487 			 const char *str, unsigned int len, void *buf,
2488 			 unsigned int size);
2489 static int parse_destroy(struct context *, const struct token *,
2490 			 const char *, unsigned int,
2491 			 void *, unsigned int);
2492 static int parse_flush(struct context *, const struct token *,
2493 		       const char *, unsigned int,
2494 		       void *, unsigned int);
2495 static int parse_dump(struct context *, const struct token *,
2496 		      const char *, unsigned int,
2497 		      void *, unsigned int);
2498 static int parse_query(struct context *, const struct token *,
2499 		       const char *, unsigned int,
2500 		       void *, unsigned int);
2501 static int parse_action(struct context *, const struct token *,
2502 			const char *, unsigned int,
2503 			void *, unsigned int);
2504 static int parse_list(struct context *, const struct token *,
2505 		      const char *, unsigned int,
2506 		      void *, unsigned int);
2507 static int parse_aged(struct context *, const struct token *,
2508 		      const char *, unsigned int,
2509 		      void *, unsigned int);
2510 static int parse_isolate(struct context *, const struct token *,
2511 			 const char *, unsigned int,
2512 			 void *, unsigned int);
2513 static int parse_configure(struct context *, const struct token *,
2514 			   const char *, unsigned int,
2515 			   void *, unsigned int);
2516 static int parse_template(struct context *, const struct token *,
2517 			  const char *, unsigned int,
2518 			  void *, unsigned int);
2519 static int parse_template_destroy(struct context *, const struct token *,
2520 				  const char *, unsigned int,
2521 				  void *, unsigned int);
2522 static int parse_table(struct context *, const struct token *,
2523 		       const char *, unsigned int, void *, unsigned int);
2524 static int parse_table_destroy(struct context *, const struct token *,
2525 			       const char *, unsigned int,
2526 			       void *, unsigned int);
2527 static int parse_qo(struct context *, const struct token *,
2528 		    const char *, unsigned int,
2529 		    void *, unsigned int);
2530 static int parse_qo_destroy(struct context *, const struct token *,
2531 			    const char *, unsigned int,
2532 			    void *, unsigned int);
2533 static int parse_qia(struct context *, const struct token *,
2534 		     const char *, unsigned int,
2535 		     void *, unsigned int);
2536 static int parse_qia_destroy(struct context *, const struct token *,
2537 			     const char *, unsigned int,
2538 			     void *, unsigned int);
2539 static int parse_push(struct context *, const struct token *,
2540 		      const char *, unsigned int,
2541 		      void *, unsigned int);
2542 static int parse_pull(struct context *, const struct token *,
2543 		      const char *, unsigned int,
2544 		      void *, unsigned int);
2545 static int parse_tunnel(struct context *, const struct token *,
2546 			const char *, unsigned int,
2547 			void *, unsigned int);
2548 static int parse_flex(struct context *, const struct token *,
2549 		      const char *, unsigned int, void *, unsigned int);
2550 static int parse_int(struct context *, const struct token *,
2551 		     const char *, unsigned int,
2552 		     void *, unsigned int);
2553 static int parse_prefix(struct context *, const struct token *,
2554 			const char *, unsigned int,
2555 			void *, unsigned int);
2556 static int parse_boolean(struct context *, const struct token *,
2557 			 const char *, unsigned int,
2558 			 void *, unsigned int);
2559 static int parse_string(struct context *, const struct token *,
2560 			const char *, unsigned int,
2561 			void *, unsigned int);
2562 static int parse_hex(struct context *ctx, const struct token *token,
2563 			const char *str, unsigned int len,
2564 			void *buf, unsigned int size);
2565 static int parse_string0(struct context *, const struct token *,
2566 			const char *, unsigned int,
2567 			void *, unsigned int);
2568 static int parse_mac_addr(struct context *, const struct token *,
2569 			  const char *, unsigned int,
2570 			  void *, unsigned int);
2571 static int parse_ipv4_addr(struct context *, const struct token *,
2572 			   const char *, unsigned int,
2573 			   void *, unsigned int);
2574 static int parse_ipv6_addr(struct context *, const struct token *,
2575 			   const char *, unsigned int,
2576 			   void *, unsigned int);
2577 static int parse_port(struct context *, const struct token *,
2578 		      const char *, unsigned int,
2579 		      void *, unsigned int);
2580 static int parse_ia(struct context *, const struct token *,
2581 		    const char *, unsigned int,
2582 		    void *, unsigned int);
2583 static int parse_ia_destroy(struct context *ctx, const struct token *token,
2584 			    const char *str, unsigned int len,
2585 			    void *buf, unsigned int size);
2586 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
2587 			   const char *str, unsigned int len, void *buf,
2588 			   unsigned int size);
2589 
2590 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
2591 			       const char *str, unsigned int len, void *buf,
2592 			       unsigned int size);
2593 static int parse_ia_port(struct context *ctx, const struct token *token,
2594 			 const char *str, unsigned int len, void *buf,
2595 			 unsigned int size);
2596 static int parse_mp(struct context *, const struct token *,
2597 		    const char *, unsigned int,
2598 		    void *, unsigned int);
2599 static int parse_meter_profile_id2ptr(struct context *ctx,
2600 				      const struct token *token,
2601 				      const char *str, unsigned int len,
2602 				      void *buf, unsigned int size);
2603 static int parse_meter_policy_id2ptr(struct context *ctx,
2604 				     const struct token *token,
2605 				     const char *str, unsigned int len,
2606 				     void *buf, unsigned int size);
2607 static int parse_meter_color(struct context *ctx, const struct token *token,
2608 			     const char *str, unsigned int len, void *buf,
2609 			     unsigned int size);
2610 static int parse_insertion_table_type(struct context *ctx, const struct token *token,
2611 				      const char *str, unsigned int len, void *buf,
2612 				      unsigned int size);
2613 static int parse_hash_table_type(struct context *ctx, const struct token *token,
2614 				 const char *str, unsigned int len, void *buf,
2615 				 unsigned int size);
2616 static int
2617 parse_quota_state_name(struct context *ctx, const struct token *token,
2618 		       const char *str, unsigned int len, void *buf,
2619 		       unsigned int size);
2620 static int
2621 parse_quota_mode_name(struct context *ctx, const struct token *token,
2622 		      const char *str, unsigned int len, void *buf,
2623 		      unsigned int size);
2624 static int
2625 parse_quota_update_name(struct context *ctx, const struct token *token,
2626 			const char *str, unsigned int len, void *buf,
2627 			unsigned int size);
2628 static int
2629 parse_qu_mode_name(struct context *ctx, const struct token *token,
2630 		   const char *str, unsigned int len, void *buf,
2631 		   unsigned int size);
2632 static int comp_none(struct context *, const struct token *,
2633 		     unsigned int, char *, unsigned int);
2634 static int comp_boolean(struct context *, const struct token *,
2635 			unsigned int, char *, unsigned int);
2636 static int comp_action(struct context *, const struct token *,
2637 		       unsigned int, char *, unsigned int);
2638 static int comp_port(struct context *, const struct token *,
2639 		     unsigned int, char *, unsigned int);
2640 static int comp_rule_id(struct context *, const struct token *,
2641 			unsigned int, char *, unsigned int);
2642 static int comp_vc_action_rss_type(struct context *, const struct token *,
2643 				   unsigned int, char *, unsigned int);
2644 static int comp_vc_action_rss_queue(struct context *, const struct token *,
2645 				    unsigned int, char *, unsigned int);
2646 static int comp_set_raw_index(struct context *, const struct token *,
2647 			      unsigned int, char *, unsigned int);
2648 static int comp_set_sample_index(struct context *, const struct token *,
2649 			      unsigned int, char *, unsigned int);
2650 static int comp_set_modify_field_op(struct context *, const struct token *,
2651 			      unsigned int, char *, unsigned int);
2652 static int comp_set_modify_field_id(struct context *, const struct token *,
2653 			      unsigned int, char *, unsigned int);
2654 static int comp_pattern_template_id(struct context *, const struct token *,
2655 				    unsigned int, char *, unsigned int);
2656 static int comp_actions_template_id(struct context *, const struct token *,
2657 				    unsigned int, char *, unsigned int);
2658 static int comp_table_id(struct context *, const struct token *,
2659 			 unsigned int, char *, unsigned int);
2660 static int comp_queue_id(struct context *, const struct token *,
2661 			 unsigned int, char *, unsigned int);
2662 static int comp_meter_color(struct context *, const struct token *,
2663 			    unsigned int, char *, unsigned int);
2664 static int comp_insertion_table_type(struct context *, const struct token *,
2665 				     unsigned int, char *, unsigned int);
2666 static int comp_hash_table_type(struct context *, const struct token *,
2667 				unsigned int, char *, unsigned int);
2668 static int
2669 comp_quota_state_name(struct context *ctx, const struct token *token,
2670 		      unsigned int ent, char *buf, unsigned int size);
2671 static int
2672 comp_quota_mode_name(struct context *ctx, const struct token *token,
2673 		     unsigned int ent, char *buf, unsigned int size);
2674 static int
2675 comp_quota_update_name(struct context *ctx, const struct token *token,
2676 		       unsigned int ent, char *buf, unsigned int size);
2677 static int
2678 comp_qu_mode_name(struct context *ctx, const struct token *token,
2679 		  unsigned int ent, char *buf, unsigned int size);
2680 
2681 struct indlst_conf {
2682 	uint32_t id;
2683 	uint32_t conf_num;
2684 	struct rte_flow_action *actions;
2685 	const void **conf;
2686 	SLIST_ENTRY(indlst_conf) next;
2687 };
2688 
2689 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
2690 
2691 /** Token definitions. */
2692 static const struct token token_list[] = {
2693 	/* Special tokens. */
2694 	[ZERO] = {
2695 		.name = "ZERO",
2696 		.help = "null entry, abused as the entry point",
2697 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
2698 	},
2699 	[END] = {
2700 		.name = "",
2701 		.type = "RETURN",
2702 		.help = "command may end here",
2703 	},
2704 	[START_SET] = {
2705 		.name = "START_SET",
2706 		.help = "null entry, abused as the entry point for set",
2707 		.next = NEXT(NEXT_ENTRY(SET)),
2708 	},
2709 	[END_SET] = {
2710 		.name = "end_set",
2711 		.type = "RETURN",
2712 		.help = "set command may end here",
2713 	},
2714 	/* Common tokens. */
2715 	[COMMON_INTEGER] = {
2716 		.name = "{int}",
2717 		.type = "INTEGER",
2718 		.help = "integer value",
2719 		.call = parse_int,
2720 		.comp = comp_none,
2721 	},
2722 	[COMMON_UNSIGNED] = {
2723 		.name = "{unsigned}",
2724 		.type = "UNSIGNED",
2725 		.help = "unsigned integer value",
2726 		.call = parse_int,
2727 		.comp = comp_none,
2728 	},
2729 	[COMMON_PREFIX] = {
2730 		.name = "{prefix}",
2731 		.type = "PREFIX",
2732 		.help = "prefix length for bit-mask",
2733 		.call = parse_prefix,
2734 		.comp = comp_none,
2735 	},
2736 	[COMMON_BOOLEAN] = {
2737 		.name = "{boolean}",
2738 		.type = "BOOLEAN",
2739 		.help = "any boolean value",
2740 		.call = parse_boolean,
2741 		.comp = comp_boolean,
2742 	},
2743 	[COMMON_STRING] = {
2744 		.name = "{string}",
2745 		.type = "STRING",
2746 		.help = "fixed string",
2747 		.call = parse_string,
2748 		.comp = comp_none,
2749 	},
2750 	[COMMON_HEX] = {
2751 		.name = "{hex}",
2752 		.type = "HEX",
2753 		.help = "fixed string",
2754 		.call = parse_hex,
2755 	},
2756 	[COMMON_FILE_PATH] = {
2757 		.name = "{file path}",
2758 		.type = "STRING",
2759 		.help = "file path",
2760 		.call = parse_string0,
2761 		.comp = comp_none,
2762 	},
2763 	[COMMON_MAC_ADDR] = {
2764 		.name = "{MAC address}",
2765 		.type = "MAC-48",
2766 		.help = "standard MAC address notation",
2767 		.call = parse_mac_addr,
2768 		.comp = comp_none,
2769 	},
2770 	[COMMON_IPV4_ADDR] = {
2771 		.name = "{IPv4 address}",
2772 		.type = "IPV4 ADDRESS",
2773 		.help = "standard IPv4 address notation",
2774 		.call = parse_ipv4_addr,
2775 		.comp = comp_none,
2776 	},
2777 	[COMMON_IPV6_ADDR] = {
2778 		.name = "{IPv6 address}",
2779 		.type = "IPV6 ADDRESS",
2780 		.help = "standard IPv6 address notation",
2781 		.call = parse_ipv6_addr,
2782 		.comp = comp_none,
2783 	},
2784 	[COMMON_RULE_ID] = {
2785 		.name = "{rule id}",
2786 		.type = "RULE ID",
2787 		.help = "rule identifier",
2788 		.call = parse_int,
2789 		.comp = comp_rule_id,
2790 	},
2791 	[COMMON_PORT_ID] = {
2792 		.name = "{port_id}",
2793 		.type = "PORT ID",
2794 		.help = "port identifier",
2795 		.call = parse_port,
2796 		.comp = comp_port,
2797 	},
2798 	[COMMON_GROUP_ID] = {
2799 		.name = "{group_id}",
2800 		.type = "GROUP ID",
2801 		.help = "group identifier",
2802 		.call = parse_int,
2803 		.comp = comp_none,
2804 	},
2805 	[COMMON_PRIORITY_LEVEL] = {
2806 		.name = "{level}",
2807 		.type = "PRIORITY",
2808 		.help = "priority level",
2809 		.call = parse_int,
2810 		.comp = comp_none,
2811 	},
2812 	[COMMON_INDIRECT_ACTION_ID] = {
2813 		.name = "{indirect_action_id}",
2814 		.type = "INDIRECT_ACTION_ID",
2815 		.help = "indirect action id",
2816 		.call = parse_int,
2817 		.comp = comp_none,
2818 	},
2819 	[COMMON_PROFILE_ID] = {
2820 		.name = "{profile_id}",
2821 		.type = "PROFILE_ID",
2822 		.help = "profile id",
2823 		.call = parse_int,
2824 		.comp = comp_none,
2825 	},
2826 	[COMMON_POLICY_ID] = {
2827 		.name = "{policy_id}",
2828 		.type = "POLICY_ID",
2829 		.help = "policy id",
2830 		.call = parse_int,
2831 		.comp = comp_none,
2832 	},
2833 	[COMMON_FLEX_TOKEN] = {
2834 		.name = "{flex token}",
2835 		.type = "flex token",
2836 		.help = "flex token",
2837 		.call = parse_int,
2838 		.comp = comp_none,
2839 	},
2840 	[COMMON_FLEX_HANDLE] = {
2841 		.name = "{flex handle}",
2842 		.type = "FLEX HANDLE",
2843 		.help = "fill flex item data",
2844 		.call = parse_flex_handle,
2845 		.comp = comp_none,
2846 	},
2847 	[COMMON_PATTERN_TEMPLATE_ID] = {
2848 		.name = "{pattern_template_id}",
2849 		.type = "PATTERN_TEMPLATE_ID",
2850 		.help = "pattern template id",
2851 		.call = parse_int,
2852 		.comp = comp_pattern_template_id,
2853 	},
2854 	[COMMON_ACTIONS_TEMPLATE_ID] = {
2855 		.name = "{actions_template_id}",
2856 		.type = "ACTIONS_TEMPLATE_ID",
2857 		.help = "actions template id",
2858 		.call = parse_int,
2859 		.comp = comp_actions_template_id,
2860 	},
2861 	[COMMON_TABLE_ID] = {
2862 		.name = "{table_id}",
2863 		.type = "TABLE_ID",
2864 		.help = "table id",
2865 		.call = parse_int,
2866 		.comp = comp_table_id,
2867 	},
2868 	[COMMON_QUEUE_ID] = {
2869 		.name = "{queue_id}",
2870 		.type = "QUEUE_ID",
2871 		.help = "queue id",
2872 		.call = parse_int,
2873 		.comp = comp_queue_id,
2874 	},
2875 	/* Top-level command. */
2876 	[FLOW] = {
2877 		.name = "flow",
2878 		.type = "{command} {port_id} [{arg} [...]]",
2879 		.help = "manage ingress/egress flow rules",
2880 		.next = NEXT(NEXT_ENTRY
2881 			     (INFO,
2882 			      CONFIGURE,
2883 			      PATTERN_TEMPLATE,
2884 			      ACTIONS_TEMPLATE,
2885 			      TABLE,
2886 			      INDIRECT_ACTION,
2887 			      VALIDATE,
2888 			      CREATE,
2889 			      DESTROY,
2890 			      FLUSH,
2891 			      DUMP,
2892 			      LIST,
2893 			      AGED,
2894 			      QUERY,
2895 			      ISOLATE,
2896 			      TUNNEL,
2897 			      FLEX,
2898 			      QUEUE,
2899 			      PUSH,
2900 			      PULL)),
2901 		.call = parse_init,
2902 	},
2903 	/* Top-level command. */
2904 	[INFO] = {
2905 		.name = "info",
2906 		.help = "get information about flow engine",
2907 		.next = NEXT(NEXT_ENTRY(END),
2908 			     NEXT_ENTRY(COMMON_PORT_ID)),
2909 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2910 		.call = parse_configure,
2911 	},
2912 	/* Top-level command. */
2913 	[CONFIGURE] = {
2914 		.name = "configure",
2915 		.help = "configure flow engine",
2916 		.next = NEXT(next_config_attr,
2917 			     NEXT_ENTRY(COMMON_PORT_ID)),
2918 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2919 		.call = parse_configure,
2920 	},
2921 	/* Configure arguments. */
2922 	[CONFIG_QUEUES_NUMBER] = {
2923 		.name = "queues_number",
2924 		.help = "number of queues",
2925 		.next = NEXT(next_config_attr,
2926 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2927 		.args = ARGS(ARGS_ENTRY(struct buffer,
2928 					args.configure.nb_queue)),
2929 	},
2930 	[CONFIG_QUEUES_SIZE] = {
2931 		.name = "queues_size",
2932 		.help = "number of elements in queues",
2933 		.next = NEXT(next_config_attr,
2934 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2935 		.args = ARGS(ARGS_ENTRY(struct buffer,
2936 					args.configure.queue_attr.size)),
2937 	},
2938 	[CONFIG_COUNTERS_NUMBER] = {
2939 		.name = "counters_number",
2940 		.help = "number of counters",
2941 		.next = NEXT(next_config_attr,
2942 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2943 		.args = ARGS(ARGS_ENTRY(struct buffer,
2944 					args.configure.port_attr.nb_counters)),
2945 	},
2946 	[CONFIG_AGING_OBJECTS_NUMBER] = {
2947 		.name = "aging_counters_number",
2948 		.help = "number of aging objects",
2949 		.next = NEXT(next_config_attr,
2950 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2951 		.args = ARGS(ARGS_ENTRY(struct buffer,
2952 					args.configure.port_attr.nb_aging_objects)),
2953 	},
2954 	[CONFIG_QUOTAS_NUMBER] = {
2955 		.name = "quotas_number",
2956 		.help = "number of quotas",
2957 		.next = NEXT(next_config_attr,
2958 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2959 		.args = ARGS(ARGS_ENTRY(struct buffer,
2960 				     args.configure.port_attr.nb_quotas)),
2961 	},
2962 	[CONFIG_METERS_NUMBER] = {
2963 		.name = "meters_number",
2964 		.help = "number of meters",
2965 		.next = NEXT(next_config_attr,
2966 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2967 		.args = ARGS(ARGS_ENTRY(struct buffer,
2968 					args.configure.port_attr.nb_meters)),
2969 	},
2970 	[CONFIG_CONN_TRACK_NUMBER] = {
2971 		.name = "conn_tracks_number",
2972 		.help = "number of connection trackings",
2973 		.next = NEXT(next_config_attr,
2974 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2975 		.args = ARGS(ARGS_ENTRY(struct buffer,
2976 					args.configure.port_attr.nb_conn_tracks)),
2977 	},
2978 	[CONFIG_FLAGS] = {
2979 		.name = "flags",
2980 		.help = "configuration flags",
2981 		.next = NEXT(next_config_attr,
2982 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2983 		.args = ARGS(ARGS_ENTRY(struct buffer,
2984 					args.configure.port_attr.flags)),
2985 	},
2986 	[CONFIG_HOST_PORT] = {
2987 		.name = "host_port",
2988 		.help = "host port for shared objects",
2989 		.next = NEXT(next_config_attr,
2990 			     NEXT_ENTRY(COMMON_UNSIGNED)),
2991 		.args = ARGS(ARGS_ENTRY(struct buffer,
2992 					args.configure.port_attr.host_port_id)),
2993 	},
2994 	/* Top-level command. */
2995 	[PATTERN_TEMPLATE] = {
2996 		.name = "pattern_template",
2997 		.type = "{command} {port_id} [{arg} [...]]",
2998 		.help = "manage pattern templates",
2999 		.next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3000 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3001 		.call = parse_template,
3002 	},
3003 	/* Sub-level commands. */
3004 	[PATTERN_TEMPLATE_CREATE] = {
3005 		.name = "create",
3006 		.help = "create pattern template",
3007 		.next = NEXT(next_pt_attr),
3008 		.call = parse_template,
3009 	},
3010 	[PATTERN_TEMPLATE_DESTROY] = {
3011 		.name = "destroy",
3012 		.help = "destroy pattern template",
3013 		.next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)),
3014 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3015 		.call = parse_template_destroy,
3016 	},
3017 	/* Pattern template arguments. */
3018 	[PATTERN_TEMPLATE_CREATE_ID] = {
3019 		.name = "pattern_template_id",
3020 		.help = "specify a pattern template id to create",
3021 		.next = NEXT(next_pt_attr,
3022 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3023 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)),
3024 	},
3025 	[PATTERN_TEMPLATE_DESTROY_ID] = {
3026 		.name = "pattern_template",
3027 		.help = "specify a pattern template id to destroy",
3028 		.next = NEXT(next_pt_destroy_attr,
3029 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3030 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3031 					    args.templ_destroy.template_id)),
3032 		.call = parse_template_destroy,
3033 	},
3034 	[PATTERN_TEMPLATE_RELAXED_MATCHING] = {
3035 		.name = "relaxed",
3036 		.help = "is matching relaxed",
3037 		.next = NEXT(next_pt_attr,
3038 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3039 		.args = ARGS(ARGS_ENTRY_BF(struct buffer,
3040 			     args.vc.attr.reserved, 1)),
3041 	},
3042 	[PATTERN_TEMPLATE_INGRESS] = {
3043 		.name = "ingress",
3044 		.help = "attribute pattern to ingress",
3045 		.next = NEXT(next_pt_attr),
3046 		.call = parse_template,
3047 	},
3048 	[PATTERN_TEMPLATE_EGRESS] = {
3049 		.name = "egress",
3050 		.help = "attribute pattern to egress",
3051 		.next = NEXT(next_pt_attr),
3052 		.call = parse_template,
3053 	},
3054 	[PATTERN_TEMPLATE_TRANSFER] = {
3055 		.name = "transfer",
3056 		.help = "attribute pattern to transfer",
3057 		.next = NEXT(next_pt_attr),
3058 		.call = parse_template,
3059 	},
3060 	[PATTERN_TEMPLATE_SPEC] = {
3061 		.name = "template",
3062 		.help = "specify item to create pattern template",
3063 		.next = NEXT(next_item),
3064 	},
3065 	/* Top-level command. */
3066 	[ACTIONS_TEMPLATE] = {
3067 		.name = "actions_template",
3068 		.type = "{command} {port_id} [{arg} [...]]",
3069 		.help = "manage actions templates",
3070 		.next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3071 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3072 		.call = parse_template,
3073 	},
3074 	/* Sub-level commands. */
3075 	[ACTIONS_TEMPLATE_CREATE] = {
3076 		.name = "create",
3077 		.help = "create actions template",
3078 		.next = NEXT(next_at_attr),
3079 		.call = parse_template,
3080 	},
3081 	[ACTIONS_TEMPLATE_DESTROY] = {
3082 		.name = "destroy",
3083 		.help = "destroy actions template",
3084 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)),
3085 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3086 		.call = parse_template_destroy,
3087 	},
3088 	/* Actions template arguments. */
3089 	[ACTIONS_TEMPLATE_CREATE_ID] = {
3090 		.name = "actions_template_id",
3091 		.help = "specify an actions template id to create",
3092 		.next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK),
3093 			     NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC),
3094 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3095 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)),
3096 	},
3097 	[ACTIONS_TEMPLATE_DESTROY_ID] = {
3098 		.name = "actions_template",
3099 		.help = "specify an actions template id to destroy",
3100 		.next = NEXT(next_at_destroy_attr,
3101 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3102 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3103 					    args.templ_destroy.template_id)),
3104 		.call = parse_template_destroy,
3105 	},
3106 	[ACTIONS_TEMPLATE_INGRESS] = {
3107 		.name = "ingress",
3108 		.help = "attribute actions to ingress",
3109 		.next = NEXT(next_at_attr),
3110 		.call = parse_template,
3111 	},
3112 	[ACTIONS_TEMPLATE_EGRESS] = {
3113 		.name = "egress",
3114 		.help = "attribute actions to egress",
3115 		.next = NEXT(next_at_attr),
3116 		.call = parse_template,
3117 	},
3118 	[ACTIONS_TEMPLATE_TRANSFER] = {
3119 		.name = "transfer",
3120 		.help = "attribute actions to transfer",
3121 		.next = NEXT(next_at_attr),
3122 		.call = parse_template,
3123 	},
3124 	[ACTIONS_TEMPLATE_SPEC] = {
3125 		.name = "template",
3126 		.help = "specify action to create actions template",
3127 		.next = NEXT(next_action),
3128 		.call = parse_template,
3129 	},
3130 	[ACTIONS_TEMPLATE_MASK] = {
3131 		.name = "mask",
3132 		.help = "specify action mask to create actions template",
3133 		.next = NEXT(next_action),
3134 		.call = parse_template,
3135 	},
3136 	/* Top-level command. */
3137 	[TABLE] = {
3138 		.name = "template_table",
3139 		.type = "{command} {port_id} [{arg} [...]]",
3140 		.help = "manage template tables",
3141 		.next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3142 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3143 		.call = parse_table,
3144 	},
3145 	/* Sub-level commands. */
3146 	[TABLE_CREATE] = {
3147 		.name = "create",
3148 		.help = "create template table",
3149 		.next = NEXT(next_table_attr),
3150 		.call = parse_table,
3151 	},
3152 	[TABLE_DESTROY] = {
3153 		.name = "destroy",
3154 		.help = "destroy template table",
3155 		.next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)),
3156 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3157 		.call = parse_table_destroy,
3158 	},
3159 	/* Table  arguments. */
3160 	[TABLE_CREATE_ID] = {
3161 		.name = "table_id",
3162 		.help = "specify table id to create",
3163 		.next = NEXT(next_table_attr,
3164 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3165 		.args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)),
3166 	},
3167 	[TABLE_DESTROY_ID] = {
3168 		.name = "table",
3169 		.help = "specify table id to destroy",
3170 		.next = NEXT(next_table_destroy_attr,
3171 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3172 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3173 					    args.table_destroy.table_id)),
3174 		.call = parse_table_destroy,
3175 	},
3176 	[TABLE_INSERTION_TYPE] = {
3177 		.name = "insertion_type",
3178 		.help = "specify insertion type",
3179 		.next = NEXT(next_table_attr,
3180 			     NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)),
3181 		.args = ARGS(ARGS_ENTRY(struct buffer,
3182 					args.table.attr.insertion_type)),
3183 	},
3184 	[TABLE_INSERTION_TYPE_NAME] = {
3185 		.name = "insertion_type_name",
3186 		.help = "insertion type name",
3187 		.call = parse_insertion_table_type,
3188 		.comp = comp_insertion_table_type,
3189 	},
3190 	[TABLE_HASH_FUNC] = {
3191 		.name = "hash_func",
3192 		.help = "specify hash calculation function",
3193 		.next = NEXT(next_table_attr,
3194 			     NEXT_ENTRY(TABLE_HASH_FUNC_NAME)),
3195 		.args = ARGS(ARGS_ENTRY(struct buffer,
3196 					args.table.attr.hash_func)),
3197 	},
3198 	[TABLE_HASH_FUNC_NAME] = {
3199 		.name = "hash_func_name",
3200 		.help = "hash calculation function name",
3201 		.call = parse_hash_table_type,
3202 		.comp = comp_hash_table_type,
3203 	},
3204 	[TABLE_GROUP] = {
3205 		.name = "group",
3206 		.help = "specify a group",
3207 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3208 		.args = ARGS(ARGS_ENTRY(struct buffer,
3209 					args.table.attr.flow_attr.group)),
3210 	},
3211 	[TABLE_PRIORITY] = {
3212 		.name = "priority",
3213 		.help = "specify a priority level",
3214 		.next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3215 		.args = ARGS(ARGS_ENTRY(struct buffer,
3216 					args.table.attr.flow_attr.priority)),
3217 	},
3218 	[TABLE_EGRESS] = {
3219 		.name = "egress",
3220 		.help = "affect rule to egress",
3221 		.next = NEXT(next_table_attr),
3222 		.call = parse_table,
3223 	},
3224 	[TABLE_INGRESS] = {
3225 		.name = "ingress",
3226 		.help = "affect rule to ingress",
3227 		.next = NEXT(next_table_attr),
3228 		.call = parse_table,
3229 	},
3230 	[TABLE_TRANSFER] = {
3231 		.name = "transfer",
3232 		.help = "affect rule to transfer",
3233 		.next = NEXT(next_table_attr),
3234 		.call = parse_table,
3235 	},
3236 	[TABLE_TRANSFER_WIRE_ORIG] = {
3237 		.name = "wire_orig",
3238 		.help = "affect rule direction to transfer",
3239 		.next = NEXT(next_table_attr),
3240 		.call = parse_table,
3241 	},
3242 	[TABLE_TRANSFER_VPORT_ORIG] = {
3243 		.name = "vport_orig",
3244 		.help = "affect rule direction to transfer",
3245 		.next = NEXT(next_table_attr),
3246 		.call = parse_table,
3247 	},
3248 	[TABLE_RULES_NUMBER] = {
3249 		.name = "rules_number",
3250 		.help = "number of rules in table",
3251 		.next = NEXT(next_table_attr,
3252 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3253 		.args = ARGS(ARGS_ENTRY(struct buffer,
3254 					args.table.attr.nb_flows)),
3255 	},
3256 	[TABLE_PATTERN_TEMPLATE] = {
3257 		.name = "pattern_template",
3258 		.help = "specify pattern template id",
3259 		.next = NEXT(next_table_attr,
3260 			     NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)),
3261 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3262 					    args.table.pat_templ_id)),
3263 		.call = parse_table,
3264 	},
3265 	[TABLE_ACTIONS_TEMPLATE] = {
3266 		.name = "actions_template",
3267 		.help = "specify actions template id",
3268 		.next = NEXT(next_table_attr,
3269 			     NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)),
3270 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3271 					    args.table.act_templ_id)),
3272 		.call = parse_table,
3273 	},
3274 	/* Top-level command. */
3275 	[QUEUE] = {
3276 		.name = "queue",
3277 		.help = "queue a flow rule operation",
3278 		.next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3279 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3280 		.call = parse_qo,
3281 	},
3282 	/* Sub-level commands. */
3283 	[QUEUE_CREATE] = {
3284 		.name = "create",
3285 		.help = "create a flow rule",
3286 		.next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE),
3287 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3288 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3289 		.call = parse_qo,
3290 	},
3291 	[QUEUE_DESTROY] = {
3292 		.name = "destroy",
3293 		.help = "destroy a flow rule",
3294 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3295 			     NEXT_ENTRY(COMMON_QUEUE_ID)),
3296 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3297 		.call = parse_qo_destroy,
3298 	},
3299 	[QUEUE_AGED] = {
3300 		.name = "aged",
3301 		.help = "list and destroy aged flows",
3302 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)),
3303 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3304 		.call = parse_aged,
3305 	},
3306 	[QUEUE_INDIRECT_ACTION] = {
3307 		.name = "indirect_action",
3308 		.help = "queue indirect actions",
3309 		.next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
3310 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3311 		.call = parse_qia,
3312 	},
3313 	/* Queue  arguments. */
3314 	[QUEUE_TEMPLATE_TABLE] = {
3315 		.name = "template_table",
3316 		.help = "specify table id",
3317 		.next = NEXT(next_async_insert_subcmd,
3318 			     NEXT_ENTRY(COMMON_TABLE_ID)),
3319 		.args = ARGS(ARGS_ENTRY(struct buffer,
3320 					args.vc.table_id)),
3321 		.call = parse_qo,
3322 	},
3323 	[QUEUE_PATTERN_TEMPLATE] = {
3324 		.name = "pattern_template",
3325 		.help = "specify pattern template index",
3326 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3327 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3328 		.args = ARGS(ARGS_ENTRY(struct buffer,
3329 					args.vc.pat_templ_id)),
3330 		.call = parse_qo,
3331 	},
3332 	[QUEUE_ACTIONS_TEMPLATE] = {
3333 		.name = "actions_template",
3334 		.help = "specify actions template index",
3335 		.next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE),
3336 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3337 		.args = ARGS(ARGS_ENTRY(struct buffer,
3338 					args.vc.act_templ_id)),
3339 		.call = parse_qo,
3340 	},
3341 	[QUEUE_RULE_ID] = {
3342 		.name = "rule_index",
3343 		.help = "specify flow rule index",
3344 		.next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE),
3345 			     NEXT_ENTRY(COMMON_UNSIGNED)),
3346 		.args = ARGS(ARGS_ENTRY(struct buffer,
3347 					args.vc.rule_id)),
3348 		.call = parse_qo,
3349 	},
3350 	[QUEUE_CREATE_POSTPONE] = {
3351 		.name = "postpone",
3352 		.help = "postpone create operation",
3353 		.next = NEXT(NEXT_ENTRY(ITEM_PATTERN),
3354 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3355 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3356 		.call = parse_qo,
3357 	},
3358 	[QUEUE_DESTROY_POSTPONE] = {
3359 		.name = "postpone",
3360 		.help = "postpone destroy operation",
3361 		.next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID),
3362 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3363 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3364 		.call = parse_qo_destroy,
3365 	},
3366 	[QUEUE_DESTROY_ID] = {
3367 		.name = "rule",
3368 		.help = "specify rule id to destroy",
3369 		.next = NEXT(next_queue_destroy_attr,
3370 			NEXT_ENTRY(COMMON_UNSIGNED)),
3371 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3372 					    args.destroy.rule)),
3373 		.call = parse_qo_destroy,
3374 	},
3375 	/* Queue indirect action arguments */
3376 	[QUEUE_INDIRECT_ACTION_CREATE] = {
3377 		.name = "create",
3378 		.help = "create indirect action",
3379 		.next = NEXT(next_qia_create_attr),
3380 		.call = parse_qia,
3381 	},
3382 	[QUEUE_INDIRECT_ACTION_UPDATE] = {
3383 		.name = "update",
3384 		.help = "update indirect action",
3385 		.next = NEXT(next_qia_update_attr,
3386 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3387 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3388 		.call = parse_qia,
3389 	},
3390 	[QUEUE_INDIRECT_ACTION_DESTROY] = {
3391 		.name = "destroy",
3392 		.help = "destroy indirect action",
3393 		.next = NEXT(next_qia_destroy_attr),
3394 		.call = parse_qia_destroy,
3395 	},
3396 	[QUEUE_INDIRECT_ACTION_QUERY] = {
3397 		.name = "query",
3398 		.help = "query indirect action",
3399 		.next = NEXT(next_qia_query_attr,
3400 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3401 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3402 		.call = parse_qia,
3403 	},
3404 	/* Indirect action destroy arguments. */
3405 	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
3406 		.name = "postpone",
3407 		.help = "postpone destroy operation",
3408 		.next = NEXT(next_qia_destroy_attr,
3409 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3410 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3411 	},
3412 	[QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
3413 		.name = "action_id",
3414 		.help = "specify a indirect action id to destroy",
3415 		.next = NEXT(next_qia_destroy_attr,
3416 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3417 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
3418 					    args.ia_destroy.action_id)),
3419 		.call = parse_qia_destroy,
3420 	},
3421 	[QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
3422 		.name = "query_update",
3423 		.help = "indirect query [and|or] update action",
3424 		.next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3425 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3426 		.call = parse_qia
3427 	},
3428 	[QUEUE_INDIRECT_ACTION_QU_MODE] = {
3429 		.name = "mode",
3430 		.help = "indirect query [and|or] update action",
3431 		.next = NEXT(next_qia_qu_attr,
3432 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3433 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3434 		.call = parse_qia
3435 	},
3436 	/* Indirect action update arguments. */
3437 	[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
3438 		.name = "postpone",
3439 		.help = "postpone update operation",
3440 		.next = NEXT(next_qia_update_attr,
3441 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3442 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3443 	},
3444 	/* Indirect action update arguments. */
3445 	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
3446 		.name = "postpone",
3447 		.help = "postpone query operation",
3448 		.next = NEXT(next_qia_query_attr,
3449 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3450 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3451 	},
3452 	/* Indirect action create arguments. */
3453 	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
3454 		.name = "action_id",
3455 		.help = "specify a indirect action id to create",
3456 		.next = NEXT(next_qia_create_attr,
3457 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3458 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3459 	},
3460 	[QUEUE_INDIRECT_ACTION_INGRESS] = {
3461 		.name = "ingress",
3462 		.help = "affect rule to ingress",
3463 		.next = NEXT(next_qia_create_attr),
3464 		.call = parse_qia,
3465 	},
3466 	[QUEUE_INDIRECT_ACTION_EGRESS] = {
3467 		.name = "egress",
3468 		.help = "affect rule to egress",
3469 		.next = NEXT(next_qia_create_attr),
3470 		.call = parse_qia,
3471 	},
3472 	[QUEUE_INDIRECT_ACTION_TRANSFER] = {
3473 		.name = "transfer",
3474 		.help = "affect rule to transfer",
3475 		.next = NEXT(next_qia_create_attr),
3476 		.call = parse_qia,
3477 	},
3478 	[QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = {
3479 		.name = "postpone",
3480 		.help = "postpone create operation",
3481 		.next = NEXT(next_qia_create_attr,
3482 			     NEXT_ENTRY(COMMON_BOOLEAN)),
3483 		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
3484 	},
3485 	[QUEUE_INDIRECT_ACTION_SPEC] = {
3486 		.name = "action",
3487 		.help = "specify action to create indirect handle",
3488 		.next = NEXT(next_action),
3489 	},
3490 	[QUEUE_INDIRECT_ACTION_LIST] = {
3491 		.name = "list",
3492 		.help = "specify actions for indirect handle list",
3493 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3494 		.call = parse_qia,
3495 	},
3496 	/* Top-level command. */
3497 	[PUSH] = {
3498 		.name = "push",
3499 		.help = "push enqueued operations",
3500 		.next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3501 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3502 		.call = parse_push,
3503 	},
3504 	/* Sub-level commands. */
3505 	[PUSH_QUEUE] = {
3506 		.name = "queue",
3507 		.help = "specify queue id",
3508 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3509 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3510 	},
3511 	/* Top-level command. */
3512 	[PULL] = {
3513 		.name = "pull",
3514 		.help = "pull flow operations results",
3515 		.next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)),
3516 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3517 		.call = parse_pull,
3518 	},
3519 	/* Sub-level commands. */
3520 	[PULL_QUEUE] = {
3521 		.name = "queue",
3522 		.help = "specify queue id",
3523 		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)),
3524 		.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
3525 	},
3526 	/* Top-level command. */
3527 	[INDIRECT_ACTION] = {
3528 		.name = "indirect_action",
3529 		.type = "{command} {port_id} [{arg} [...]]",
3530 		.help = "manage indirect actions",
3531 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3532 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3533 		.call = parse_ia,
3534 	},
3535 	/* Sub-level commands. */
3536 	[INDIRECT_ACTION_CREATE] = {
3537 		.name = "create",
3538 		.help = "create indirect action",
3539 		.next = NEXT(next_ia_create_attr),
3540 		.call = parse_ia,
3541 	},
3542 	[INDIRECT_ACTION_UPDATE] = {
3543 		.name = "update",
3544 		.help = "update indirect action",
3545 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
3546 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3547 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
3548 		.call = parse_ia,
3549 	},
3550 	[INDIRECT_ACTION_DESTROY] = {
3551 		.name = "destroy",
3552 		.help = "destroy indirect action",
3553 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
3554 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3555 		.call = parse_ia_destroy,
3556 	},
3557 	[INDIRECT_ACTION_QUERY] = {
3558 		.name = "query",
3559 		.help = "query indirect action",
3560 		.next = NEXT(NEXT_ENTRY(END),
3561 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3562 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3563 		.call = parse_ia,
3564 	},
3565 	[INDIRECT_ACTION_QUERY_UPDATE] = {
3566 		.name = "query_update",
3567 		.help = "query [and|or] update",
3568 		.next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
3569 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
3570 		.call = parse_ia
3571 	},
3572 	[INDIRECT_ACTION_QU_MODE] = {
3573 		.name = "mode",
3574 		.help = "query_update mode",
3575 		.next = NEXT(next_ia_qu_attr,
3576 			     NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
3577 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
3578 		.call = parse_ia,
3579 	},
3580 	[INDIRECT_ACTION_QU_MODE_NAME] = {
3581 		.name = "mode_name",
3582 		.help = "query-update mode name",
3583 		.call = parse_qu_mode_name,
3584 		.comp = comp_qu_mode_name,
3585 	},
3586 	[VALIDATE] = {
3587 		.name = "validate",
3588 		.help = "check whether a flow rule can be created",
3589 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3590 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3591 		.call = parse_vc,
3592 	},
3593 	[CREATE] = {
3594 		.name = "create",
3595 		.help = "create a flow rule",
3596 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3597 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3598 		.call = parse_vc,
3599 	},
3600 	[DESTROY] = {
3601 		.name = "destroy",
3602 		.help = "destroy specific flow rules",
3603 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE),
3604 			     NEXT_ENTRY(COMMON_PORT_ID)),
3605 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3606 		.call = parse_destroy,
3607 	},
3608 	[FLUSH] = {
3609 		.name = "flush",
3610 		.help = "destroy all flow rules",
3611 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3612 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3613 		.call = parse_flush,
3614 	},
3615 	[DUMP] = {
3616 		.name = "dump",
3617 		.help = "dump single/all flow rules to file",
3618 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
3619 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3620 		.call = parse_dump,
3621 	},
3622 	[QUERY] = {
3623 		.name = "query",
3624 		.help = "query an existing flow rule",
3625 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
3626 			     NEXT_ENTRY(COMMON_RULE_ID),
3627 			     NEXT_ENTRY(COMMON_PORT_ID)),
3628 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
3629 			     ARGS_ENTRY(struct buffer, args.query.rule),
3630 			     ARGS_ENTRY(struct buffer, port)),
3631 		.call = parse_query,
3632 	},
3633 	[LIST] = {
3634 		.name = "list",
3635 		.help = "list existing flow rules",
3636 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3637 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3638 		.call = parse_list,
3639 	},
3640 	[AGED] = {
3641 		.name = "aged",
3642 		.help = "list and destroy aged flows",
3643 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
3644 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3645 		.call = parse_aged,
3646 	},
3647 	[ISOLATE] = {
3648 		.name = "isolate",
3649 		.help = "restrict ingress traffic to the defined flow rules",
3650 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
3651 			     NEXT_ENTRY(COMMON_PORT_ID)),
3652 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
3653 			     ARGS_ENTRY(struct buffer, port)),
3654 		.call = parse_isolate,
3655 	},
3656 	[FLEX] = {
3657 		.name = "flex_item",
3658 		.help = "flex item API",
3659 		.next = NEXT(next_flex_item),
3660 		.call = parse_flex,
3661 	},
3662 	[FLEX_ITEM_INIT] = {
3663 		.name = "init",
3664 		.help = "flex item init",
3665 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3666 			     ARGS_ENTRY(struct buffer, port)),
3667 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3668 			     NEXT_ENTRY(COMMON_PORT_ID)),
3669 		.call = parse_flex
3670 	},
3671 	[FLEX_ITEM_CREATE] = {
3672 		.name = "create",
3673 		.help = "flex item create",
3674 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename),
3675 			     ARGS_ENTRY(struct buffer, args.flex.token),
3676 			     ARGS_ENTRY(struct buffer, port)),
3677 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH),
3678 			     NEXT_ENTRY(COMMON_FLEX_TOKEN),
3679 			     NEXT_ENTRY(COMMON_PORT_ID)),
3680 		.call = parse_flex
3681 	},
3682 	[FLEX_ITEM_DESTROY] = {
3683 		.name = "destroy",
3684 		.help = "flex item destroy",
3685 		.args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token),
3686 			     ARGS_ENTRY(struct buffer, port)),
3687 		.next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN),
3688 			     NEXT_ENTRY(COMMON_PORT_ID)),
3689 		.call = parse_flex
3690 	},
3691 	[TUNNEL] = {
3692 		.name = "tunnel",
3693 		.help = "new tunnel API",
3694 		.next = NEXT(NEXT_ENTRY
3695 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
3696 		.call = parse_tunnel,
3697 	},
3698 	/* Tunnel arguments. */
3699 	[TUNNEL_CREATE] = {
3700 		.name = "create",
3701 		.help = "create new tunnel object",
3702 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
3703 			     NEXT_ENTRY(COMMON_PORT_ID)),
3704 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3705 		.call = parse_tunnel,
3706 	},
3707 	[TUNNEL_CREATE_TYPE] = {
3708 		.name = "type",
3709 		.help = "create new tunnel",
3710 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
3711 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
3712 		.call = parse_tunnel,
3713 	},
3714 	[TUNNEL_DESTROY] = {
3715 		.name = "destroy",
3716 		.help = "destroy tunnel",
3717 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
3718 			     NEXT_ENTRY(COMMON_PORT_ID)),
3719 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3720 		.call = parse_tunnel,
3721 	},
3722 	[TUNNEL_DESTROY_ID] = {
3723 		.name = "id",
3724 		.help = "tunnel identifier to destroy",
3725 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
3726 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3727 		.call = parse_tunnel,
3728 	},
3729 	[TUNNEL_LIST] = {
3730 		.name = "list",
3731 		.help = "list existing tunnels",
3732 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
3733 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
3734 		.call = parse_tunnel,
3735 	},
3736 	/* Destroy arguments. */
3737 	[DESTROY_RULE] = {
3738 		.name = "rule",
3739 		.help = "specify a rule identifier",
3740 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3741 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
3742 		.call = parse_destroy,
3743 	},
3744 	/* Dump arguments. */
3745 	[DUMP_ALL] = {
3746 		.name = "all",
3747 		.help = "dump all",
3748 		.next = NEXT(next_dump_attr),
3749 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
3750 		.call = parse_dump,
3751 	},
3752 	[DUMP_ONE] = {
3753 		.name = "rule",
3754 		.help = "dump one rule",
3755 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
3756 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
3757 				ARGS_ENTRY(struct buffer, args.dump.rule)),
3758 		.call = parse_dump,
3759 	},
3760 	/* Query arguments. */
3761 	[QUERY_ACTION] = {
3762 		.name = "{action}",
3763 		.type = "ACTION",
3764 		.help = "action to query, must be part of the rule",
3765 		.call = parse_action,
3766 		.comp = comp_action,
3767 	},
3768 	/* List arguments. */
3769 	[LIST_GROUP] = {
3770 		.name = "group",
3771 		.help = "specify a group",
3772 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3773 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
3774 		.call = parse_list,
3775 	},
3776 	[AGED_DESTROY] = {
3777 		.name = "destroy",
3778 		.help = "specify aged flows need be destroyed",
3779 		.call = parse_aged,
3780 		.comp = comp_none,
3781 	},
3782 	/* Validate/create attributes. */
3783 	[VC_GROUP] = {
3784 		.name = "group",
3785 		.help = "specify a group",
3786 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
3787 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
3788 		.call = parse_vc,
3789 	},
3790 	[VC_PRIORITY] = {
3791 		.name = "priority",
3792 		.help = "specify a priority level",
3793 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
3794 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
3795 		.call = parse_vc,
3796 	},
3797 	[VC_INGRESS] = {
3798 		.name = "ingress",
3799 		.help = "affect rule to ingress",
3800 		.next = NEXT(next_vc_attr),
3801 		.call = parse_vc,
3802 	},
3803 	[VC_EGRESS] = {
3804 		.name = "egress",
3805 		.help = "affect rule to egress",
3806 		.next = NEXT(next_vc_attr),
3807 		.call = parse_vc,
3808 	},
3809 	[VC_TRANSFER] = {
3810 		.name = "transfer",
3811 		.help = "apply rule directly to endpoints found in pattern",
3812 		.next = NEXT(next_vc_attr),
3813 		.call = parse_vc,
3814 	},
3815 	[VC_TUNNEL_SET] = {
3816 		.name = "tunnel_set",
3817 		.help = "tunnel steer rule",
3818 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3819 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3820 		.call = parse_vc,
3821 	},
3822 	[VC_TUNNEL_MATCH] = {
3823 		.name = "tunnel_match",
3824 		.help = "tunnel match rule",
3825 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
3826 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
3827 		.call = parse_vc,
3828 	},
3829 	/* Validate/create pattern. */
3830 	[ITEM_PATTERN] = {
3831 		.name = "pattern",
3832 		.help = "submit a list of pattern items",
3833 		.next = NEXT(next_item),
3834 		.call = parse_vc,
3835 	},
3836 	[ITEM_PARAM_IS] = {
3837 		.name = "is",
3838 		.help = "match value perfectly (with full bit-mask)",
3839 		.call = parse_vc_spec,
3840 	},
3841 	[ITEM_PARAM_SPEC] = {
3842 		.name = "spec",
3843 		.help = "match value according to configured bit-mask",
3844 		.call = parse_vc_spec,
3845 	},
3846 	[ITEM_PARAM_LAST] = {
3847 		.name = "last",
3848 		.help = "specify upper bound to establish a range",
3849 		.call = parse_vc_spec,
3850 	},
3851 	[ITEM_PARAM_MASK] = {
3852 		.name = "mask",
3853 		.help = "specify bit-mask with relevant bits set to one",
3854 		.call = parse_vc_spec,
3855 	},
3856 	[ITEM_PARAM_PREFIX] = {
3857 		.name = "prefix",
3858 		.help = "generate bit-mask from a prefix length",
3859 		.call = parse_vc_spec,
3860 	},
3861 	[ITEM_NEXT] = {
3862 		.name = "/",
3863 		.help = "specify next pattern item",
3864 		.next = NEXT(next_item),
3865 	},
3866 	[ITEM_END] = {
3867 		.name = "end",
3868 		.help = "end list of pattern items",
3869 		.priv = PRIV_ITEM(END, 0),
3870 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
3871 		.call = parse_vc,
3872 	},
3873 	[ITEM_VOID] = {
3874 		.name = "void",
3875 		.help = "no-op pattern item",
3876 		.priv = PRIV_ITEM(VOID, 0),
3877 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3878 		.call = parse_vc,
3879 	},
3880 	[ITEM_INVERT] = {
3881 		.name = "invert",
3882 		.help = "perform actions when pattern does not match",
3883 		.priv = PRIV_ITEM(INVERT, 0),
3884 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
3885 		.call = parse_vc,
3886 	},
3887 	[ITEM_ANY] = {
3888 		.name = "any",
3889 		.help = "match any protocol for the current layer",
3890 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
3891 		.next = NEXT(item_any),
3892 		.call = parse_vc,
3893 	},
3894 	[ITEM_ANY_NUM] = {
3895 		.name = "num",
3896 		.help = "number of layers covered",
3897 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3898 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
3899 	},
3900 	[ITEM_PORT_ID] = {
3901 		.name = "port_id",
3902 		.help = "match traffic from/to a given DPDK port ID",
3903 		.priv = PRIV_ITEM(PORT_ID,
3904 				  sizeof(struct rte_flow_item_port_id)),
3905 		.next = NEXT(item_port_id),
3906 		.call = parse_vc,
3907 	},
3908 	[ITEM_PORT_ID_ID] = {
3909 		.name = "id",
3910 		.help = "DPDK port ID",
3911 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
3912 			     item_param),
3913 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
3914 	},
3915 	[ITEM_MARK] = {
3916 		.name = "mark",
3917 		.help = "match traffic against value set in previously matched rule",
3918 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
3919 		.next = NEXT(item_mark),
3920 		.call = parse_vc,
3921 	},
3922 	[ITEM_MARK_ID] = {
3923 		.name = "id",
3924 		.help = "Integer value to match against",
3925 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
3926 			     item_param),
3927 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
3928 	},
3929 	[ITEM_RAW] = {
3930 		.name = "raw",
3931 		.help = "match an arbitrary byte string",
3932 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
3933 		.next = NEXT(item_raw),
3934 		.call = parse_vc,
3935 	},
3936 	[ITEM_RAW_RELATIVE] = {
3937 		.name = "relative",
3938 		.help = "look for pattern after the previous item",
3939 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3940 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3941 					   relative, 1)),
3942 	},
3943 	[ITEM_RAW_SEARCH] = {
3944 		.name = "search",
3945 		.help = "search pattern from offset (see also limit)",
3946 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3947 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
3948 					   search, 1)),
3949 	},
3950 	[ITEM_RAW_OFFSET] = {
3951 		.name = "offset",
3952 		.help = "absolute or relative offset for pattern",
3953 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
3954 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
3955 	},
3956 	[ITEM_RAW_LIMIT] = {
3957 		.name = "limit",
3958 		.help = "search area limit for start of pattern",
3959 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3960 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
3961 	},
3962 	[ITEM_RAW_PATTERN] = {
3963 		.name = "pattern",
3964 		.help = "byte string to look for",
3965 		.next = NEXT(item_raw,
3966 			     NEXT_ENTRY(COMMON_STRING),
3967 			     NEXT_ENTRY(ITEM_PARAM_IS,
3968 					ITEM_PARAM_SPEC,
3969 					ITEM_PARAM_MASK)),
3970 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3971 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
3972 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3973 					    ITEM_RAW_PATTERN_SIZE)),
3974 	},
3975 	[ITEM_RAW_PATTERN_HEX] = {
3976 		.name = "pattern_hex",
3977 		.help = "hex string to look for",
3978 		.next = NEXT(item_raw,
3979 			     NEXT_ENTRY(COMMON_HEX),
3980 			     NEXT_ENTRY(ITEM_PARAM_IS,
3981 					ITEM_PARAM_SPEC,
3982 					ITEM_PARAM_MASK)),
3983 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
3984 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
3985 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
3986 					    ITEM_RAW_PATTERN_SIZE)),
3987 	},
3988 	[ITEM_ETH] = {
3989 		.name = "eth",
3990 		.help = "match Ethernet header",
3991 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
3992 		.next = NEXT(item_eth),
3993 		.call = parse_vc,
3994 	},
3995 	[ITEM_ETH_DST] = {
3996 		.name = "dst",
3997 		.help = "destination MAC",
3998 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3999 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)),
4000 	},
4001 	[ITEM_ETH_SRC] = {
4002 		.name = "src",
4003 		.help = "source MAC",
4004 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4005 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)),
4006 	},
4007 	[ITEM_ETH_TYPE] = {
4008 		.name = "type",
4009 		.help = "EtherType",
4010 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4011 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)),
4012 	},
4013 	[ITEM_ETH_HAS_VLAN] = {
4014 		.name = "has_vlan",
4015 		.help = "packet header contains VLAN",
4016 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4017 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
4018 					   has_vlan, 1)),
4019 	},
4020 	[ITEM_VLAN] = {
4021 		.name = "vlan",
4022 		.help = "match 802.1Q/ad VLAN tag",
4023 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
4024 		.next = NEXT(item_vlan),
4025 		.call = parse_vc,
4026 	},
4027 	[ITEM_VLAN_TCI] = {
4028 		.name = "tci",
4029 		.help = "tag control information",
4030 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4031 			     item_param),
4032 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)),
4033 	},
4034 	[ITEM_VLAN_PCP] = {
4035 		.name = "pcp",
4036 		.help = "priority code point",
4037 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4038 			     item_param),
4039 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4040 						  hdr.vlan_tci, "\xe0\x00")),
4041 	},
4042 	[ITEM_VLAN_DEI] = {
4043 		.name = "dei",
4044 		.help = "drop eligible indicator",
4045 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4046 			     item_param),
4047 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4048 						  hdr.vlan_tci, "\x10\x00")),
4049 	},
4050 	[ITEM_VLAN_VID] = {
4051 		.name = "vid",
4052 		.help = "VLAN identifier",
4053 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4054 			     item_param),
4055 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
4056 						  hdr.vlan_tci, "\x0f\xff")),
4057 	},
4058 	[ITEM_VLAN_INNER_TYPE] = {
4059 		.name = "inner_type",
4060 		.help = "inner EtherType",
4061 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4062 			     item_param),
4063 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
4064 					     hdr.eth_proto)),
4065 	},
4066 	[ITEM_VLAN_HAS_MORE_VLAN] = {
4067 		.name = "has_more_vlan",
4068 		.help = "packet header contains another VLAN",
4069 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
4070 			     item_param),
4071 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
4072 					   has_more_vlan, 1)),
4073 	},
4074 	[ITEM_IPV4] = {
4075 		.name = "ipv4",
4076 		.help = "match IPv4 header",
4077 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
4078 		.next = NEXT(item_ipv4),
4079 		.call = parse_vc,
4080 	},
4081 	[ITEM_IPV4_VER_IHL] = {
4082 		.name = "version_ihl",
4083 		.help = "match header length",
4084 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4085 			     item_param),
4086 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
4087 				     hdr.version_ihl)),
4088 	},
4089 	[ITEM_IPV4_TOS] = {
4090 		.name = "tos",
4091 		.help = "type of service",
4092 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4093 			     item_param),
4094 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4095 					     hdr.type_of_service)),
4096 	},
4097 	[ITEM_IPV4_ID] = {
4098 		.name = "packet_id",
4099 		.help = "fragment packet id",
4100 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4101 			     item_param),
4102 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4103 					     hdr.packet_id)),
4104 	},
4105 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
4106 		.name = "fragment_offset",
4107 		.help = "fragmentation flags and fragment offset",
4108 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4109 			     item_param),
4110 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4111 					     hdr.fragment_offset)),
4112 	},
4113 	[ITEM_IPV4_TTL] = {
4114 		.name = "ttl",
4115 		.help = "time to live",
4116 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4117 			     item_param),
4118 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4119 					     hdr.time_to_live)),
4120 	},
4121 	[ITEM_IPV4_PROTO] = {
4122 		.name = "proto",
4123 		.help = "next protocol ID",
4124 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
4125 			     item_param),
4126 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4127 					     hdr.next_proto_id)),
4128 	},
4129 	[ITEM_IPV4_SRC] = {
4130 		.name = "src",
4131 		.help = "source address",
4132 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4133 			     item_param),
4134 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4135 					     hdr.src_addr)),
4136 	},
4137 	[ITEM_IPV4_DST] = {
4138 		.name = "dst",
4139 		.help = "destination address",
4140 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4141 			     item_param),
4142 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
4143 					     hdr.dst_addr)),
4144 	},
4145 	[ITEM_IPV6] = {
4146 		.name = "ipv6",
4147 		.help = "match IPv6 header",
4148 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
4149 		.next = NEXT(item_ipv6),
4150 		.call = parse_vc,
4151 	},
4152 	[ITEM_IPV6_TC] = {
4153 		.name = "tc",
4154 		.help = "traffic class",
4155 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4156 			     item_param),
4157 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4158 						  hdr.vtc_flow,
4159 						  "\x0f\xf0\x00\x00")),
4160 	},
4161 	[ITEM_IPV6_FLOW] = {
4162 		.name = "flow",
4163 		.help = "flow label",
4164 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4165 			     item_param),
4166 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
4167 						  hdr.vtc_flow,
4168 						  "\x00\x0f\xff\xff")),
4169 	},
4170 	[ITEM_IPV6_PROTO] = {
4171 		.name = "proto",
4172 		.help = "protocol (next header)",
4173 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4174 			     item_param),
4175 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4176 					     hdr.proto)),
4177 	},
4178 	[ITEM_IPV6_HOP] = {
4179 		.name = "hop",
4180 		.help = "hop limit",
4181 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4182 			     item_param),
4183 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4184 					     hdr.hop_limits)),
4185 	},
4186 	[ITEM_IPV6_SRC] = {
4187 		.name = "src",
4188 		.help = "source address",
4189 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4190 			     item_param),
4191 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4192 					     hdr.src_addr)),
4193 	},
4194 	[ITEM_IPV6_DST] = {
4195 		.name = "dst",
4196 		.help = "destination address",
4197 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
4198 			     item_param),
4199 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
4200 					     hdr.dst_addr)),
4201 	},
4202 	[ITEM_IPV6_HAS_FRAG_EXT] = {
4203 		.name = "has_frag_ext",
4204 		.help = "fragment packet attribute",
4205 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
4206 			     item_param),
4207 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
4208 					   has_frag_ext, 1)),
4209 	},
4210 	[ITEM_IPV6_ROUTING_EXT] = {
4211 		.name = "ipv6_routing_ext",
4212 		.help = "match IPv6 routing extension header",
4213 		.priv = PRIV_ITEM(IPV6_ROUTING_EXT,
4214 				  sizeof(struct rte_flow_item_ipv6_routing_ext)),
4215 		.next = NEXT(item_ipv6_routing_ext),
4216 		.call = parse_vc,
4217 	},
4218 	[ITEM_IPV6_ROUTING_EXT_TYPE] = {
4219 		.name = "ext_type",
4220 		.help = "match IPv6 routing extension header type",
4221 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4222 			     item_param),
4223 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4224 					     hdr.type)),
4225 	},
4226 	[ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = {
4227 		.name = "ext_next_hdr",
4228 		.help = "match IPv6 routing extension header next header type",
4229 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4230 			     item_param),
4231 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4232 					     hdr.next_hdr)),
4233 	},
4234 	[ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = {
4235 		.name = "ext_seg_left",
4236 		.help = "match IPv6 routing extension header segment left",
4237 		.next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4238 			     item_param),
4239 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext,
4240 					     hdr.segments_left)),
4241 	},
4242 	[ITEM_ICMP] = {
4243 		.name = "icmp",
4244 		.help = "match ICMP header",
4245 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
4246 		.next = NEXT(item_icmp),
4247 		.call = parse_vc,
4248 	},
4249 	[ITEM_ICMP_TYPE] = {
4250 		.name = "type",
4251 		.help = "ICMP packet type",
4252 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4253 			     item_param),
4254 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4255 					     hdr.icmp_type)),
4256 	},
4257 	[ITEM_ICMP_CODE] = {
4258 		.name = "code",
4259 		.help = "ICMP packet code",
4260 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4261 			     item_param),
4262 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4263 					     hdr.icmp_code)),
4264 	},
4265 	[ITEM_ICMP_IDENT] = {
4266 		.name = "ident",
4267 		.help = "ICMP packet identifier",
4268 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4269 			     item_param),
4270 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4271 					     hdr.icmp_ident)),
4272 	},
4273 	[ITEM_ICMP_SEQ] = {
4274 		.name = "seq",
4275 		.help = "ICMP packet sequence number",
4276 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
4277 			     item_param),
4278 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
4279 					     hdr.icmp_seq_nb)),
4280 	},
4281 	[ITEM_UDP] = {
4282 		.name = "udp",
4283 		.help = "match UDP header",
4284 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
4285 		.next = NEXT(item_udp),
4286 		.call = parse_vc,
4287 	},
4288 	[ITEM_UDP_SRC] = {
4289 		.name = "src",
4290 		.help = "UDP source port",
4291 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
4292 			     item_param),
4293 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4294 					     hdr.src_port)),
4295 	},
4296 	[ITEM_UDP_DST] = {
4297 		.name = "dst",
4298 		.help = "UDP destination port",
4299 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4300 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
4301 					     hdr.dst_port)),
4302 	},
4303 	[ITEM_TCP] = {
4304 		.name = "tcp",
4305 		.help = "match TCP header",
4306 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
4307 		.next = NEXT(item_tcp),
4308 		.call = parse_vc,
4309 	},
4310 	[ITEM_TCP_SRC] = {
4311 		.name = "src",
4312 		.help = "TCP source port",
4313 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4314 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4315 					     hdr.src_port)),
4316 	},
4317 	[ITEM_TCP_DST] = {
4318 		.name = "dst",
4319 		.help = "TCP destination port",
4320 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4321 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4322 					     hdr.dst_port)),
4323 	},
4324 	[ITEM_TCP_FLAGS] = {
4325 		.name = "flags",
4326 		.help = "TCP flags",
4327 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4328 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
4329 					     hdr.tcp_flags)),
4330 	},
4331 	[ITEM_SCTP] = {
4332 		.name = "sctp",
4333 		.help = "match SCTP header",
4334 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
4335 		.next = NEXT(item_sctp),
4336 		.call = parse_vc,
4337 	},
4338 	[ITEM_SCTP_SRC] = {
4339 		.name = "src",
4340 		.help = "SCTP source port",
4341 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4342 			     item_param),
4343 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4344 					     hdr.src_port)),
4345 	},
4346 	[ITEM_SCTP_DST] = {
4347 		.name = "dst",
4348 		.help = "SCTP destination port",
4349 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4350 			     item_param),
4351 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4352 					     hdr.dst_port)),
4353 	},
4354 	[ITEM_SCTP_TAG] = {
4355 		.name = "tag",
4356 		.help = "validation tag",
4357 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4358 			     item_param),
4359 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4360 					     hdr.tag)),
4361 	},
4362 	[ITEM_SCTP_CKSUM] = {
4363 		.name = "cksum",
4364 		.help = "checksum",
4365 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
4366 			     item_param),
4367 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
4368 					     hdr.cksum)),
4369 	},
4370 	[ITEM_VXLAN] = {
4371 		.name = "vxlan",
4372 		.help = "match VXLAN header",
4373 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
4374 		.next = NEXT(item_vxlan),
4375 		.call = parse_vc,
4376 	},
4377 	[ITEM_VXLAN_VNI] = {
4378 		.name = "vni",
4379 		.help = "VXLAN identifier",
4380 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4381 			     item_param),
4382 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)),
4383 	},
4384 	[ITEM_VXLAN_LAST_RSVD] = {
4385 		.name = "last_rsvd",
4386 		.help = "VXLAN last reserved bits",
4387 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
4388 			     item_param),
4389 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
4390 					     hdr.rsvd1)),
4391 	},
4392 	[ITEM_E_TAG] = {
4393 		.name = "e_tag",
4394 		.help = "match E-Tag header",
4395 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
4396 		.next = NEXT(item_e_tag),
4397 		.call = parse_vc,
4398 	},
4399 	[ITEM_E_TAG_GRP_ECID_B] = {
4400 		.name = "grp_ecid_b",
4401 		.help = "GRP and E-CID base",
4402 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
4403 			     item_param),
4404 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
4405 						  rsvd_grp_ecid_b,
4406 						  "\x3f\xff")),
4407 	},
4408 	[ITEM_NVGRE] = {
4409 		.name = "nvgre",
4410 		.help = "match NVGRE header",
4411 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
4412 		.next = NEXT(item_nvgre),
4413 		.call = parse_vc,
4414 	},
4415 	[ITEM_NVGRE_TNI] = {
4416 		.name = "tni",
4417 		.help = "virtual subnet ID",
4418 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
4419 			     item_param),
4420 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
4421 	},
4422 	[ITEM_MPLS] = {
4423 		.name = "mpls",
4424 		.help = "match MPLS header",
4425 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
4426 		.next = NEXT(item_mpls),
4427 		.call = parse_vc,
4428 	},
4429 	[ITEM_MPLS_LABEL] = {
4430 		.name = "label",
4431 		.help = "MPLS label",
4432 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4433 			     item_param),
4434 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4435 						  label_tc_s,
4436 						  "\xff\xff\xf0")),
4437 	},
4438 	[ITEM_MPLS_TC] = {
4439 		.name = "tc",
4440 		.help = "MPLS Traffic Class",
4441 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4442 			     item_param),
4443 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4444 						  label_tc_s,
4445 						  "\x00\x00\x0e")),
4446 	},
4447 	[ITEM_MPLS_S] = {
4448 		.name = "s",
4449 		.help = "MPLS Bottom-of-Stack",
4450 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
4451 			     item_param),
4452 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
4453 						  label_tc_s,
4454 						  "\x00\x00\x01")),
4455 	},
4456 	[ITEM_GRE] = {
4457 		.name = "gre",
4458 		.help = "match GRE header",
4459 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
4460 		.next = NEXT(item_gre),
4461 		.call = parse_vc,
4462 	},
4463 	[ITEM_GRE_PROTO] = {
4464 		.name = "protocol",
4465 		.help = "GRE protocol type",
4466 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4467 			     item_param),
4468 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4469 					     protocol)),
4470 	},
4471 	[ITEM_GRE_C_RSVD0_VER] = {
4472 		.name = "c_rsvd0_ver",
4473 		.help =
4474 			"checksum (1b), undefined (1b), key bit (1b),"
4475 			" sequence number (1b), reserved 0 (9b),"
4476 			" version (3b)",
4477 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
4478 			     item_param),
4479 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
4480 					     c_rsvd0_ver)),
4481 	},
4482 	[ITEM_GRE_C_BIT] = {
4483 		.name = "c_bit",
4484 		.help = "checksum bit (C)",
4485 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
4486 			     item_param),
4487 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4488 						  c_rsvd0_ver,
4489 						  "\x80\x00\x00\x00")),
4490 	},
4491 	[ITEM_GRE_S_BIT] = {
4492 		.name = "s_bit",
4493 		.help = "sequence number bit (S)",
4494 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4495 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4496 						  c_rsvd0_ver,
4497 						  "\x10\x00\x00\x00")),
4498 	},
4499 	[ITEM_GRE_K_BIT] = {
4500 		.name = "k_bit",
4501 		.help = "key bit (K)",
4502 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
4503 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
4504 						  c_rsvd0_ver,
4505 						  "\x20\x00\x00\x00")),
4506 	},
4507 	[ITEM_FUZZY] = {
4508 		.name = "fuzzy",
4509 		.help = "fuzzy pattern match, expect faster than default",
4510 		.priv = PRIV_ITEM(FUZZY,
4511 				sizeof(struct rte_flow_item_fuzzy)),
4512 		.next = NEXT(item_fuzzy),
4513 		.call = parse_vc,
4514 	},
4515 	[ITEM_FUZZY_THRESH] = {
4516 		.name = "thresh",
4517 		.help = "match accuracy threshold",
4518 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
4519 			     item_param),
4520 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
4521 					thresh)),
4522 	},
4523 	[ITEM_GTP] = {
4524 		.name = "gtp",
4525 		.help = "match GTP header",
4526 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
4527 		.next = NEXT(item_gtp),
4528 		.call = parse_vc,
4529 	},
4530 	[ITEM_GTP_FLAGS] = {
4531 		.name = "v_pt_rsv_flags",
4532 		.help = "GTP flags",
4533 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4534 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
4535 					hdr.gtp_hdr_info)),
4536 	},
4537 	[ITEM_GTP_MSG_TYPE] = {
4538 		.name = "msg_type",
4539 		.help = "GTP message type",
4540 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4541 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
4542 	},
4543 	[ITEM_GTP_TEID] = {
4544 		.name = "teid",
4545 		.help = "tunnel endpoint identifier",
4546 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
4547 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
4548 	},
4549 	[ITEM_GTPC] = {
4550 		.name = "gtpc",
4551 		.help = "match GTP header",
4552 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
4553 		.next = NEXT(item_gtp),
4554 		.call = parse_vc,
4555 	},
4556 	[ITEM_GTPU] = {
4557 		.name = "gtpu",
4558 		.help = "match GTP header",
4559 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
4560 		.next = NEXT(item_gtp),
4561 		.call = parse_vc,
4562 	},
4563 	[ITEM_GENEVE] = {
4564 		.name = "geneve",
4565 		.help = "match GENEVE header",
4566 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
4567 		.next = NEXT(item_geneve),
4568 		.call = parse_vc,
4569 	},
4570 	[ITEM_GENEVE_VNI] = {
4571 		.name = "vni",
4572 		.help = "virtual network identifier",
4573 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4574 			     item_param),
4575 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
4576 	},
4577 	[ITEM_GENEVE_PROTO] = {
4578 		.name = "protocol",
4579 		.help = "GENEVE protocol type",
4580 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4581 			     item_param),
4582 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
4583 					     protocol)),
4584 	},
4585 	[ITEM_GENEVE_OPTLEN] = {
4586 		.name = "optlen",
4587 		.help = "GENEVE options length in dwords",
4588 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
4589 			     item_param),
4590 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
4591 						  ver_opt_len_o_c_rsvd0,
4592 						  "\x3f\x00")),
4593 	},
4594 	[ITEM_VXLAN_GPE] = {
4595 		.name = "vxlan-gpe",
4596 		.help = "match VXLAN-GPE header",
4597 		.priv = PRIV_ITEM(VXLAN_GPE,
4598 				  sizeof(struct rte_flow_item_vxlan_gpe)),
4599 		.next = NEXT(item_vxlan_gpe),
4600 		.call = parse_vc,
4601 	},
4602 	[ITEM_VXLAN_GPE_VNI] = {
4603 		.name = "vni",
4604 		.help = "VXLAN-GPE identifier",
4605 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
4606 			     item_param),
4607 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
4608 					     hdr.vni)),
4609 	},
4610 	[ITEM_ARP_ETH_IPV4] = {
4611 		.name = "arp_eth_ipv4",
4612 		.help = "match ARP header for Ethernet/IPv4",
4613 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
4614 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
4615 		.next = NEXT(item_arp_eth_ipv4),
4616 		.call = parse_vc,
4617 	},
4618 	[ITEM_ARP_ETH_IPV4_SHA] = {
4619 		.name = "sha",
4620 		.help = "sender hardware address",
4621 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4622 			     item_param),
4623 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4624 					     hdr.arp_data.arp_sha)),
4625 	},
4626 	[ITEM_ARP_ETH_IPV4_SPA] = {
4627 		.name = "spa",
4628 		.help = "sender IPv4 address",
4629 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4630 			     item_param),
4631 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4632 					     hdr.arp_data.arp_sip)),
4633 	},
4634 	[ITEM_ARP_ETH_IPV4_THA] = {
4635 		.name = "tha",
4636 		.help = "target hardware address",
4637 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
4638 			     item_param),
4639 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4640 					     hdr.arp_data.arp_tha)),
4641 	},
4642 	[ITEM_ARP_ETH_IPV4_TPA] = {
4643 		.name = "tpa",
4644 		.help = "target IPv4 address",
4645 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
4646 			     item_param),
4647 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
4648 					     hdr.arp_data.arp_tip)),
4649 	},
4650 	[ITEM_IPV6_EXT] = {
4651 		.name = "ipv6_ext",
4652 		.help = "match presence of any IPv6 extension header",
4653 		.priv = PRIV_ITEM(IPV6_EXT,
4654 				  sizeof(struct rte_flow_item_ipv6_ext)),
4655 		.next = NEXT(item_ipv6_ext),
4656 		.call = parse_vc,
4657 	},
4658 	[ITEM_IPV6_EXT_NEXT_HDR] = {
4659 		.name = "next_hdr",
4660 		.help = "next header",
4661 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4662 			     item_param),
4663 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
4664 					     next_hdr)),
4665 	},
4666 	[ITEM_IPV6_FRAG_EXT] = {
4667 		.name = "ipv6_frag_ext",
4668 		.help = "match presence of IPv6 fragment extension header",
4669 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
4670 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
4671 		.next = NEXT(item_ipv6_frag_ext),
4672 		.call = parse_vc,
4673 	},
4674 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
4675 		.name = "next_hdr",
4676 		.help = "next header",
4677 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4678 			     item_param),
4679 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
4680 					hdr.next_header)),
4681 	},
4682 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
4683 		.name = "frag_data",
4684 		.help = "fragment flags and offset",
4685 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4686 			     item_param),
4687 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4688 					     hdr.frag_data)),
4689 	},
4690 	[ITEM_IPV6_FRAG_EXT_ID] = {
4691 		.name = "packet_id",
4692 		.help = "fragment packet id",
4693 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
4694 			     item_param),
4695 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
4696 					     hdr.id)),
4697 	},
4698 	[ITEM_ICMP6] = {
4699 		.name = "icmp6",
4700 		.help = "match any ICMPv6 header",
4701 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
4702 		.next = NEXT(item_icmp6),
4703 		.call = parse_vc,
4704 	},
4705 	[ITEM_ICMP6_TYPE] = {
4706 		.name = "type",
4707 		.help = "ICMPv6 type",
4708 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4709 			     item_param),
4710 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4711 					     type)),
4712 	},
4713 	[ITEM_ICMP6_CODE] = {
4714 		.name = "code",
4715 		.help = "ICMPv6 code",
4716 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
4717 			     item_param),
4718 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
4719 					     code)),
4720 	},
4721 	[ITEM_ICMP6_ECHO_REQUEST] = {
4722 		.name = "icmp6_echo_request",
4723 		.help = "match ICMPv6 echo request",
4724 		.priv = PRIV_ITEM(ICMP6_ECHO_REQUEST,
4725 				  sizeof(struct rte_flow_item_icmp6_echo)),
4726 		.next = NEXT(item_icmp6_echo_request),
4727 		.call = parse_vc,
4728 	},
4729 	[ITEM_ICMP6_ECHO_REQUEST_ID] = {
4730 		.name = "ident",
4731 		.help = "ICMPv6 echo request identifier",
4732 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
4733 			     item_param),
4734 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4735 					     hdr.identifier)),
4736 	},
4737 	[ITEM_ICMP6_ECHO_REQUEST_SEQ] = {
4738 		.name = "seq",
4739 		.help = "ICMPv6 echo request sequence",
4740 		.next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED),
4741 			     item_param),
4742 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4743 					     hdr.sequence)),
4744 	},
4745 	[ITEM_ICMP6_ECHO_REPLY] = {
4746 		.name = "icmp6_echo_reply",
4747 		.help = "match ICMPv6 echo reply",
4748 		.priv = PRIV_ITEM(ICMP6_ECHO_REPLY,
4749 				  sizeof(struct rte_flow_item_icmp6_echo)),
4750 		.next = NEXT(item_icmp6_echo_reply),
4751 		.call = parse_vc,
4752 	},
4753 	[ITEM_ICMP6_ECHO_REPLY_ID] = {
4754 		.name = "ident",
4755 		.help = "ICMPv6 echo reply identifier",
4756 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
4757 			     item_param),
4758 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4759 					     hdr.identifier)),
4760 	},
4761 	[ITEM_ICMP6_ECHO_REPLY_SEQ] = {
4762 		.name = "seq",
4763 		.help = "ICMPv6 echo reply sequence",
4764 		.next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED),
4765 			     item_param),
4766 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo,
4767 					     hdr.sequence)),
4768 	},
4769 	[ITEM_ICMP6_ND_NS] = {
4770 		.name = "icmp6_nd_ns",
4771 		.help = "match ICMPv6 neighbor discovery solicitation",
4772 		.priv = PRIV_ITEM(ICMP6_ND_NS,
4773 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
4774 		.next = NEXT(item_icmp6_nd_ns),
4775 		.call = parse_vc,
4776 	},
4777 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
4778 		.name = "target_addr",
4779 		.help = "target address",
4780 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
4781 			     item_param),
4782 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
4783 					     target_addr)),
4784 	},
4785 	[ITEM_ICMP6_ND_NA] = {
4786 		.name = "icmp6_nd_na",
4787 		.help = "match ICMPv6 neighbor discovery advertisement",
4788 		.priv = PRIV_ITEM(ICMP6_ND_NA,
4789 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
4790 		.next = NEXT(item_icmp6_nd_na),
4791 		.call = parse_vc,
4792 	},
4793 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
4794 		.name = "target_addr",
4795 		.help = "target address",
4796 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
4797 			     item_param),
4798 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
4799 					     target_addr)),
4800 	},
4801 	[ITEM_ICMP6_ND_OPT] = {
4802 		.name = "icmp6_nd_opt",
4803 		.help = "match presence of any ICMPv6 neighbor discovery"
4804 			" option",
4805 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
4806 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
4807 		.next = NEXT(item_icmp6_nd_opt),
4808 		.call = parse_vc,
4809 	},
4810 	[ITEM_ICMP6_ND_OPT_TYPE] = {
4811 		.name = "type",
4812 		.help = "ND option type",
4813 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
4814 			     item_param),
4815 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
4816 					     type)),
4817 	},
4818 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
4819 		.name = "icmp6_nd_opt_sla_eth",
4820 		.help = "match ICMPv6 neighbor discovery source Ethernet"
4821 			" link-layer address option",
4822 		.priv = PRIV_ITEM
4823 			(ICMP6_ND_OPT_SLA_ETH,
4824 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
4825 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
4826 		.call = parse_vc,
4827 	},
4828 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
4829 		.name = "sla",
4830 		.help = "source Ethernet LLA",
4831 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
4832 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4833 		.args = ARGS(ARGS_ENTRY_HTON
4834 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
4835 	},
4836 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
4837 		.name = "icmp6_nd_opt_tla_eth",
4838 		.help = "match ICMPv6 neighbor discovery target Ethernet"
4839 			" link-layer address option",
4840 		.priv = PRIV_ITEM
4841 			(ICMP6_ND_OPT_TLA_ETH,
4842 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
4843 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
4844 		.call = parse_vc,
4845 	},
4846 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
4847 		.name = "tla",
4848 		.help = "target Ethernet LLA",
4849 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
4850 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
4851 		.args = ARGS(ARGS_ENTRY_HTON
4852 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
4853 	},
4854 	[ITEM_META] = {
4855 		.name = "meta",
4856 		.help = "match metadata header",
4857 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
4858 		.next = NEXT(item_meta),
4859 		.call = parse_vc,
4860 	},
4861 	[ITEM_META_DATA] = {
4862 		.name = "data",
4863 		.help = "metadata value",
4864 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
4865 			     item_param),
4866 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
4867 					     data, "\xff\xff\xff\xff")),
4868 	},
4869 	[ITEM_GRE_KEY] = {
4870 		.name = "gre_key",
4871 		.help = "match GRE key",
4872 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
4873 		.next = NEXT(item_gre_key),
4874 		.call = parse_vc,
4875 	},
4876 	[ITEM_GRE_KEY_VALUE] = {
4877 		.name = "value",
4878 		.help = "key value",
4879 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
4880 			     item_param),
4881 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4882 	},
4883 	[ITEM_GRE_OPTION] = {
4884 		.name = "gre_option",
4885 		.help = "match GRE optional fields",
4886 		.priv = PRIV_ITEM(GRE_OPTION,
4887 				  sizeof(struct rte_flow_item_gre_opt)),
4888 		.next = NEXT(item_gre_option),
4889 		.call = parse_vc,
4890 	},
4891 	[ITEM_GRE_OPTION_CHECKSUM] = {
4892 		.name = "checksum",
4893 		.help = "match GRE checksum",
4894 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4895 			     item_param),
4896 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4897 					     checksum_rsvd.checksum)),
4898 	},
4899 	[ITEM_GRE_OPTION_KEY] = {
4900 		.name = "key",
4901 		.help = "match GRE key",
4902 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4903 			     item_param),
4904 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4905 					     key.key)),
4906 	},
4907 	[ITEM_GRE_OPTION_SEQUENCE] = {
4908 		.name = "sequence",
4909 		.help = "match GRE sequence",
4910 		.next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED),
4911 			     item_param),
4912 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt,
4913 					     sequence.sequence)),
4914 	},
4915 	[ITEM_GTP_PSC] = {
4916 		.name = "gtp_psc",
4917 		.help = "match GTP extension header with type 0x85",
4918 		.priv = PRIV_ITEM(GTP_PSC,
4919 				sizeof(struct rte_flow_item_gtp_psc)),
4920 		.next = NEXT(item_gtp_psc),
4921 		.call = parse_vc,
4922 	},
4923 	[ITEM_GTP_PSC_QFI] = {
4924 		.name = "qfi",
4925 		.help = "QoS flow identifier",
4926 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4927 			     item_param),
4928 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4929 					hdr.qfi, 6)),
4930 	},
4931 	[ITEM_GTP_PSC_PDU_T] = {
4932 		.name = "pdu_t",
4933 		.help = "PDU type",
4934 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
4935 			     item_param),
4936 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
4937 					hdr.type, 4)),
4938 	},
4939 	[ITEM_PPPOES] = {
4940 		.name = "pppoes",
4941 		.help = "match PPPoE session header",
4942 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
4943 		.next = NEXT(item_pppoes),
4944 		.call = parse_vc,
4945 	},
4946 	[ITEM_PPPOED] = {
4947 		.name = "pppoed",
4948 		.help = "match PPPoE discovery header",
4949 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
4950 		.next = NEXT(item_pppoed),
4951 		.call = parse_vc,
4952 	},
4953 	[ITEM_PPPOE_SEID] = {
4954 		.name = "seid",
4955 		.help = "session identifier",
4956 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
4957 			     item_param),
4958 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
4959 					session_id)),
4960 	},
4961 	[ITEM_PPPOE_PROTO_ID] = {
4962 		.name = "pppoe_proto_id",
4963 		.help = "match PPPoE session protocol identifier",
4964 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
4965 				sizeof(struct rte_flow_item_pppoe_proto_id)),
4966 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
4967 			     item_param),
4968 		.args = ARGS(ARGS_ENTRY_HTON
4969 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
4970 		.call = parse_vc,
4971 	},
4972 	[ITEM_HIGIG2] = {
4973 		.name = "higig2",
4974 		.help = "matches higig2 header",
4975 		.priv = PRIV_ITEM(HIGIG2,
4976 				sizeof(struct rte_flow_item_higig2_hdr)),
4977 		.next = NEXT(item_higig2),
4978 		.call = parse_vc,
4979 	},
4980 	[ITEM_HIGIG2_CLASSIFICATION] = {
4981 		.name = "classification",
4982 		.help = "matches classification of higig2 header",
4983 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4984 			     item_param),
4985 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4986 					hdr.ppt1.classification)),
4987 	},
4988 	[ITEM_HIGIG2_VID] = {
4989 		.name = "vid",
4990 		.help = "matches vid of higig2 header",
4991 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
4992 			     item_param),
4993 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
4994 					hdr.ppt1.vid)),
4995 	},
4996 	[ITEM_TAG] = {
4997 		.name = "tag",
4998 		.help = "match tag value",
4999 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
5000 		.next = NEXT(item_tag),
5001 		.call = parse_vc,
5002 	},
5003 	[ITEM_TAG_DATA] = {
5004 		.name = "data",
5005 		.help = "tag value to match",
5006 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5007 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
5008 	},
5009 	[ITEM_TAG_INDEX] = {
5010 		.name = "index",
5011 		.help = "index of tag array to match",
5012 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
5013 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5014 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
5015 	},
5016 	[ITEM_L2TPV3OIP] = {
5017 		.name = "l2tpv3oip",
5018 		.help = "match L2TPv3 over IP header",
5019 		.priv = PRIV_ITEM(L2TPV3OIP,
5020 				  sizeof(struct rte_flow_item_l2tpv3oip)),
5021 		.next = NEXT(item_l2tpv3oip),
5022 		.call = parse_vc,
5023 	},
5024 	[ITEM_L2TPV3OIP_SESSION_ID] = {
5025 		.name = "session_id",
5026 		.help = "session identifier",
5027 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
5028 			     item_param),
5029 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
5030 					     session_id)),
5031 	},
5032 	[ITEM_ESP] = {
5033 		.name = "esp",
5034 		.help = "match ESP header",
5035 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
5036 		.next = NEXT(item_esp),
5037 		.call = parse_vc,
5038 	},
5039 	[ITEM_ESP_SPI] = {
5040 		.name = "spi",
5041 		.help = "security policy index",
5042 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5043 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
5044 				hdr.spi)),
5045 	},
5046 	[ITEM_AH] = {
5047 		.name = "ah",
5048 		.help = "match AH header",
5049 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
5050 		.next = NEXT(item_ah),
5051 		.call = parse_vc,
5052 	},
5053 	[ITEM_AH_SPI] = {
5054 		.name = "spi",
5055 		.help = "security parameters index",
5056 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5057 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
5058 	},
5059 	[ITEM_PFCP] = {
5060 		.name = "pfcp",
5061 		.help = "match pfcp header",
5062 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
5063 		.next = NEXT(item_pfcp),
5064 		.call = parse_vc,
5065 	},
5066 	[ITEM_PFCP_S_FIELD] = {
5067 		.name = "s_field",
5068 		.help = "S field",
5069 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5070 			     item_param),
5071 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
5072 				s_field)),
5073 	},
5074 	[ITEM_PFCP_SEID] = {
5075 		.name = "seid",
5076 		.help = "session endpoint identifier",
5077 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
5078 			     item_param),
5079 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
5080 	},
5081 	[ITEM_ECPRI] = {
5082 		.name = "ecpri",
5083 		.help = "match eCPRI header",
5084 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
5085 		.next = NEXT(item_ecpri),
5086 		.call = parse_vc,
5087 	},
5088 	[ITEM_ECPRI_COMMON] = {
5089 		.name = "common",
5090 		.help = "eCPRI common header",
5091 		.next = NEXT(item_ecpri_common),
5092 	},
5093 	[ITEM_ECPRI_COMMON_TYPE] = {
5094 		.name = "type",
5095 		.help = "type of common header",
5096 		.next = NEXT(item_ecpri_common_type),
5097 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
5098 	},
5099 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
5100 		.name = "iq_data",
5101 		.help = "Type #0: IQ Data",
5102 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5103 					ITEM_NEXT)),
5104 		.call = parse_vc_item_ecpri_type,
5105 	},
5106 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
5107 		.name = "pc_id",
5108 		.help = "Physical Channel ID",
5109 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
5110 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5111 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5112 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5113 				hdr.type0.pc_id)),
5114 	},
5115 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
5116 		.name = "rtc_ctrl",
5117 		.help = "Type #2: Real-Time Control Data",
5118 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5119 					ITEM_NEXT)),
5120 		.call = parse_vc_item_ecpri_type,
5121 	},
5122 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
5123 		.name = "rtc_id",
5124 		.help = "Real-Time Control Data ID",
5125 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
5126 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5127 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5128 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5129 				hdr.type2.rtc_id)),
5130 	},
5131 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
5132 		.name = "delay_measure",
5133 		.help = "Type #5: One-Way Delay Measurement",
5134 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5135 					ITEM_NEXT)),
5136 		.call = parse_vc_item_ecpri_type,
5137 	},
5138 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
5139 		.name = "msr_id",
5140 		.help = "Measurement ID",
5141 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
5142 				ITEM_ECPRI_COMMON, ITEM_NEXT),
5143 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
5144 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
5145 				hdr.type5.msr_id)),
5146 	},
5147 	[ITEM_GENEVE_OPT] = {
5148 		.name = "geneve-opt",
5149 		.help = "GENEVE header option",
5150 		.priv = PRIV_ITEM(GENEVE_OPT,
5151 				  sizeof(struct rte_flow_item_geneve_opt) +
5152 				  ITEM_GENEVE_OPT_DATA_SIZE),
5153 		.next = NEXT(item_geneve_opt),
5154 		.call = parse_vc,
5155 	},
5156 	[ITEM_GENEVE_OPT_CLASS]	= {
5157 		.name = "class",
5158 		.help = "GENEVE option class",
5159 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5160 			     item_param),
5161 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
5162 					     option_class)),
5163 	},
5164 	[ITEM_GENEVE_OPT_TYPE] = {
5165 		.name = "type",
5166 		.help = "GENEVE option type",
5167 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5168 			     item_param),
5169 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
5170 					option_type)),
5171 	},
5172 	[ITEM_GENEVE_OPT_LENGTH] = {
5173 		.name = "length",
5174 		.help = "GENEVE option data length (in 32b words)",
5175 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
5176 			     item_param),
5177 		.args = ARGS(ARGS_ENTRY_BOUNDED(
5178 				struct rte_flow_item_geneve_opt, option_len,
5179 				0, 31)),
5180 	},
5181 	[ITEM_GENEVE_OPT_DATA] = {
5182 		.name = "data",
5183 		.help = "GENEVE option data pattern",
5184 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
5185 			     item_param),
5186 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
5187 			     ARGS_ENTRY_ARB(0, 0),
5188 			     ARGS_ENTRY_ARB
5189 				(sizeof(struct rte_flow_item_geneve_opt),
5190 				ITEM_GENEVE_OPT_DATA_SIZE)),
5191 	},
5192 	[ITEM_INTEGRITY] = {
5193 		.name = "integrity",
5194 		.help = "match packet integrity",
5195 		.priv = PRIV_ITEM(INTEGRITY,
5196 				  sizeof(struct rte_flow_item_integrity)),
5197 		.next = NEXT(item_integrity),
5198 		.call = parse_vc,
5199 	},
5200 	[ITEM_INTEGRITY_LEVEL] = {
5201 		.name = "level",
5202 		.help = "integrity level",
5203 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5204 			     item_param),
5205 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
5206 	},
5207 	[ITEM_INTEGRITY_VALUE] = {
5208 		.name = "value",
5209 		.help = "integrity value",
5210 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
5211 			     item_param),
5212 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
5213 	},
5214 	[ITEM_CONNTRACK] = {
5215 		.name = "conntrack",
5216 		.help = "conntrack state",
5217 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
5218 			     item_param),
5219 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
5220 	},
5221 	[ITEM_PORT_REPRESENTOR] = {
5222 		.name = "port_representor",
5223 		.help = "match traffic entering the embedded switch from the given ethdev",
5224 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
5225 				  sizeof(struct rte_flow_item_ethdev)),
5226 		.next = NEXT(item_port_representor),
5227 		.call = parse_vc,
5228 	},
5229 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
5230 		.name = "port_id",
5231 		.help = "ethdev port ID",
5232 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
5233 			     item_param),
5234 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5235 	},
5236 	[ITEM_REPRESENTED_PORT] = {
5237 		.name = "represented_port",
5238 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
5239 		.priv = PRIV_ITEM(REPRESENTED_PORT,
5240 				  sizeof(struct rte_flow_item_ethdev)),
5241 		.next = NEXT(item_represented_port),
5242 		.call = parse_vc,
5243 	},
5244 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
5245 		.name = "ethdev_port_id",
5246 		.help = "ethdev port ID",
5247 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
5248 			     item_param),
5249 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
5250 	},
5251 	[ITEM_FLEX] = {
5252 		.name = "flex",
5253 		.help = "match flex header",
5254 		.priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)),
5255 		.next = NEXT(item_flex),
5256 		.call = parse_vc,
5257 	},
5258 	[ITEM_FLEX_ITEM_HANDLE] = {
5259 		.name = "item",
5260 		.help = "flex item handle",
5261 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5262 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5263 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)),
5264 	},
5265 	[ITEM_FLEX_PATTERN_HANDLE] = {
5266 		.name = "pattern",
5267 		.help = "flex pattern handle",
5268 		.next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE),
5269 			     NEXT_ENTRY(ITEM_PARAM_IS)),
5270 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)),
5271 	},
5272 	[ITEM_L2TPV2] = {
5273 		.name = "l2tpv2",
5274 		.help = "match L2TPv2 header",
5275 		.priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
5276 		.next = NEXT(item_l2tpv2),
5277 		.call = parse_vc,
5278 	},
5279 	[ITEM_L2TPV2_TYPE] = {
5280 		.name = "type",
5281 		.help = "type of l2tpv2",
5282 		.next = NEXT(item_l2tpv2_type),
5283 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)),
5284 	},
5285 	[ITEM_L2TPV2_TYPE_DATA] = {
5286 		.name = "data",
5287 		.help = "Type #7: data message without any options",
5288 		.next = NEXT(item_l2tpv2_type_data),
5289 		.call = parse_vc_item_l2tpv2_type,
5290 	},
5291 	[ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = {
5292 		.name = "tunnel_id",
5293 		.help = "tunnel identifier",
5294 		.next = NEXT(item_l2tpv2_type_data,
5295 			     NEXT_ENTRY(COMMON_UNSIGNED),
5296 			     item_param),
5297 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5298 					     hdr.type7.tunnel_id)),
5299 	},
5300 	[ITEM_L2TPV2_MSG_DATA_SESSION_ID] = {
5301 		.name = "session_id",
5302 		.help = "session identifier",
5303 		.next = NEXT(item_l2tpv2_type_data,
5304 			     NEXT_ENTRY(COMMON_UNSIGNED),
5305 			     item_param),
5306 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5307 					     hdr.type7.session_id)),
5308 	},
5309 	[ITEM_L2TPV2_TYPE_DATA_L] = {
5310 		.name = "data_l",
5311 		.help = "Type #6: data message with length option",
5312 		.next = NEXT(item_l2tpv2_type_data_l),
5313 		.call = parse_vc_item_l2tpv2_type,
5314 	},
5315 	[ITEM_L2TPV2_MSG_DATA_L_LENGTH] = {
5316 		.name = "length",
5317 		.help = "message length",
5318 		.next = NEXT(item_l2tpv2_type_data_l,
5319 			     NEXT_ENTRY(COMMON_UNSIGNED),
5320 			     item_param),
5321 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5322 					     hdr.type6.length)),
5323 	},
5324 	[ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = {
5325 		.name = "tunnel_id",
5326 		.help = "tunnel identifier",
5327 		.next = NEXT(item_l2tpv2_type_data_l,
5328 			     NEXT_ENTRY(COMMON_UNSIGNED),
5329 			     item_param),
5330 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5331 					     hdr.type6.tunnel_id)),
5332 	},
5333 	[ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = {
5334 		.name = "session_id",
5335 		.help = "session identifier",
5336 		.next = NEXT(item_l2tpv2_type_data_l,
5337 			     NEXT_ENTRY(COMMON_UNSIGNED),
5338 			     item_param),
5339 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5340 					     hdr.type6.session_id)),
5341 	},
5342 	[ITEM_L2TPV2_TYPE_DATA_S] = {
5343 		.name = "data_s",
5344 		.help = "Type #5: data message with ns, nr option",
5345 		.next = NEXT(item_l2tpv2_type_data_s),
5346 		.call = parse_vc_item_l2tpv2_type,
5347 	},
5348 	[ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = {
5349 		.name = "tunnel_id",
5350 		.help = "tunnel identifier",
5351 		.next = NEXT(item_l2tpv2_type_data_s,
5352 			     NEXT_ENTRY(COMMON_UNSIGNED),
5353 			     item_param),
5354 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5355 					     hdr.type5.tunnel_id)),
5356 	},
5357 	[ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = {
5358 		.name = "session_id",
5359 		.help = "session identifier",
5360 		.next = NEXT(item_l2tpv2_type_data_s,
5361 			     NEXT_ENTRY(COMMON_UNSIGNED),
5362 			     item_param),
5363 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5364 					     hdr.type5.session_id)),
5365 	},
5366 	[ITEM_L2TPV2_MSG_DATA_S_NS] = {
5367 		.name = "ns",
5368 		.help = "sequence number for message",
5369 		.next = NEXT(item_l2tpv2_type_data_s,
5370 			     NEXT_ENTRY(COMMON_UNSIGNED),
5371 			     item_param),
5372 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5373 					     hdr.type5.ns)),
5374 	},
5375 	[ITEM_L2TPV2_MSG_DATA_S_NR] = {
5376 		.name = "nr",
5377 		.help = "sequence number for next receive message",
5378 		.next = NEXT(item_l2tpv2_type_data_s,
5379 			     NEXT_ENTRY(COMMON_UNSIGNED),
5380 			     item_param),
5381 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5382 					     hdr.type5.nr)),
5383 	},
5384 	[ITEM_L2TPV2_TYPE_DATA_O] = {
5385 		.name = "data_o",
5386 		.help = "Type #4: data message with offset option",
5387 		.next = NEXT(item_l2tpv2_type_data_o),
5388 		.call = parse_vc_item_l2tpv2_type,
5389 	},
5390 	[ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = {
5391 		.name = "tunnel_id",
5392 		.help = "tunnel identifier",
5393 		.next = NEXT(item_l2tpv2_type_data_o,
5394 			     NEXT_ENTRY(COMMON_UNSIGNED),
5395 			     item_param),
5396 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5397 					     hdr.type4.tunnel_id)),
5398 	},
5399 	[ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = {
5400 		.name = "session_id",
5401 		.help = "session identifier",
5402 		.next = NEXT(item_l2tpv2_type_data_o,
5403 			     NEXT_ENTRY(COMMON_UNSIGNED),
5404 			     item_param),
5405 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5406 					     hdr.type5.session_id)),
5407 	},
5408 	[ITEM_L2TPV2_MSG_DATA_O_OFFSET] = {
5409 		.name = "offset_size",
5410 		.help = "the size of offset padding",
5411 		.next = NEXT(item_l2tpv2_type_data_o,
5412 			     NEXT_ENTRY(COMMON_UNSIGNED),
5413 			     item_param),
5414 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5415 					     hdr.type4.offset_size)),
5416 	},
5417 	[ITEM_L2TPV2_TYPE_DATA_L_S] = {
5418 		.name = "data_l_s",
5419 		.help = "Type #3: data message contains length, ns, nr "
5420 			"options",
5421 		.next = NEXT(item_l2tpv2_type_data_l_s),
5422 		.call = parse_vc_item_l2tpv2_type,
5423 	},
5424 	[ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = {
5425 		.name = "length",
5426 		.help = "message length",
5427 		.next = NEXT(item_l2tpv2_type_data_l_s,
5428 			     NEXT_ENTRY(COMMON_UNSIGNED),
5429 			     item_param),
5430 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5431 					     hdr.type3.length)),
5432 	},
5433 	[ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = {
5434 		.name = "tunnel_id",
5435 		.help = "tunnel identifier",
5436 		.next = NEXT(item_l2tpv2_type_data_l_s,
5437 			     NEXT_ENTRY(COMMON_UNSIGNED),
5438 			     item_param),
5439 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5440 					     hdr.type3.tunnel_id)),
5441 	},
5442 	[ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = {
5443 		.name = "session_id",
5444 		.help = "session identifier",
5445 		.next = NEXT(item_l2tpv2_type_data_l_s,
5446 			     NEXT_ENTRY(COMMON_UNSIGNED),
5447 			     item_param),
5448 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5449 					     hdr.type3.session_id)),
5450 	},
5451 	[ITEM_L2TPV2_MSG_DATA_L_S_NS] = {
5452 		.name = "ns",
5453 		.help = "sequence number for message",
5454 		.next = NEXT(item_l2tpv2_type_data_l_s,
5455 			     NEXT_ENTRY(COMMON_UNSIGNED),
5456 			     item_param),
5457 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5458 					     hdr.type3.ns)),
5459 	},
5460 	[ITEM_L2TPV2_MSG_DATA_L_S_NR] = {
5461 		.name = "nr",
5462 		.help = "sequence number for next receive message",
5463 		.next = NEXT(item_l2tpv2_type_data_l_s,
5464 			     NEXT_ENTRY(COMMON_UNSIGNED),
5465 			     item_param),
5466 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5467 					     hdr.type3.nr)),
5468 	},
5469 	[ITEM_L2TPV2_TYPE_CTRL] = {
5470 		.name = "control",
5471 		.help = "Type #3: conrtol message contains length, ns, nr "
5472 			"options",
5473 		.next = NEXT(item_l2tpv2_type_ctrl),
5474 		.call = parse_vc_item_l2tpv2_type,
5475 	},
5476 	[ITEM_L2TPV2_MSG_CTRL_LENGTH] = {
5477 		.name = "length",
5478 		.help = "message length",
5479 		.next = NEXT(item_l2tpv2_type_ctrl,
5480 			     NEXT_ENTRY(COMMON_UNSIGNED),
5481 			     item_param),
5482 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5483 					     hdr.type3.length)),
5484 	},
5485 	[ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = {
5486 		.name = "tunnel_id",
5487 		.help = "tunnel identifier",
5488 		.next = NEXT(item_l2tpv2_type_ctrl,
5489 			     NEXT_ENTRY(COMMON_UNSIGNED),
5490 			     item_param),
5491 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5492 					     hdr.type3.tunnel_id)),
5493 	},
5494 	[ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = {
5495 		.name = "session_id",
5496 		.help = "session identifier",
5497 		.next = NEXT(item_l2tpv2_type_ctrl,
5498 			     NEXT_ENTRY(COMMON_UNSIGNED),
5499 			     item_param),
5500 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5501 					     hdr.type3.session_id)),
5502 	},
5503 	[ITEM_L2TPV2_MSG_CTRL_NS] = {
5504 		.name = "ns",
5505 		.help = "sequence number for message",
5506 		.next = NEXT(item_l2tpv2_type_ctrl,
5507 			     NEXT_ENTRY(COMMON_UNSIGNED),
5508 			     item_param),
5509 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5510 					     hdr.type3.ns)),
5511 	},
5512 	[ITEM_L2TPV2_MSG_CTRL_NR] = {
5513 		.name = "nr",
5514 		.help = "sequence number for next receive message",
5515 		.next = NEXT(item_l2tpv2_type_ctrl,
5516 			     NEXT_ENTRY(COMMON_UNSIGNED),
5517 			     item_param),
5518 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2,
5519 					     hdr.type3.nr)),
5520 	},
5521 	[ITEM_PPP] = {
5522 		.name = "ppp",
5523 		.help = "match PPP header",
5524 		.priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
5525 		.next = NEXT(item_ppp),
5526 		.call = parse_vc,
5527 	},
5528 	[ITEM_PPP_ADDR] = {
5529 		.name = "addr",
5530 		.help = "PPP address",
5531 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5532 			     item_param),
5533 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)),
5534 	},
5535 	[ITEM_PPP_CTRL] = {
5536 		.name = "ctrl",
5537 		.help = "PPP control",
5538 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5539 			     item_param),
5540 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)),
5541 	},
5542 	[ITEM_PPP_PROTO_ID] = {
5543 		.name = "proto_id",
5544 		.help = "PPP protocol identifier",
5545 		.next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED),
5546 			     item_param),
5547 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp,
5548 					hdr.proto_id)),
5549 	},
5550 	[ITEM_METER] = {
5551 		.name = "meter",
5552 		.help = "match meter color",
5553 		.priv = PRIV_ITEM(METER_COLOR,
5554 				  sizeof(struct rte_flow_item_meter_color)),
5555 		.next = NEXT(item_meter),
5556 		.call = parse_vc,
5557 	},
5558 	[ITEM_METER_COLOR] = {
5559 		.name = "color",
5560 		.help = "meter color",
5561 		.next = NEXT(item_meter,
5562 			     NEXT_ENTRY(ITEM_METER_COLOR_NAME),
5563 			     item_param),
5564 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color,
5565 					color)),
5566 	},
5567 	[ITEM_METER_COLOR_NAME] = {
5568 		.name = "color_name",
5569 		.help = "meter color name",
5570 		.call = parse_meter_color,
5571 		.comp = comp_meter_color,
5572 	},
5573 	[ITEM_QUOTA] = {
5574 		.name = "quota",
5575 		.help = "match quota",
5576 		.priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
5577 		.next = NEXT(item_quota),
5578 		.call = parse_vc
5579 	},
5580 	[ITEM_QUOTA_STATE] = {
5581 		.name = "quota_state",
5582 		.help = "quota state",
5583 		.next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
5584 			     NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
5585 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
5586 	},
5587 	[ITEM_QUOTA_STATE_NAME] = {
5588 		.name = "state_name",
5589 		.help = "quota state name",
5590 		.call = parse_quota_state_name,
5591 		.comp = comp_quota_state_name
5592 	},
5593 	[ITEM_IB_BTH] = {
5594 		.name = "ib_bth",
5595 		.help = "match ib bth fields",
5596 		.priv = PRIV_ITEM(IB_BTH,
5597 				  sizeof(struct rte_flow_item_ib_bth)),
5598 		.next = NEXT(item_ib_bth),
5599 		.call = parse_vc,
5600 	},
5601 	[ITEM_IB_BTH_OPCODE] = {
5602 		.name = "opcode",
5603 		.help = "match ib bth opcode",
5604 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
5605 				 item_param),
5606 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
5607 						 hdr.opcode)),
5608 	},
5609 	[ITEM_IB_BTH_PKEY] = {
5610 		.name = "pkey",
5611 		.help = "partition key",
5612 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
5613 				 item_param),
5614 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
5615 						 hdr.pkey)),
5616 	},
5617 	[ITEM_IB_BTH_DST_QPN] = {
5618 		.name = "dst_qp",
5619 		.help = "destination qp",
5620 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
5621 				 item_param),
5622 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
5623 						 hdr.dst_qp)),
5624 	},
5625 	[ITEM_IB_BTH_PSN] = {
5626 		.name = "psn",
5627 		.help = "packet sequence number",
5628 		.next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED),
5629 				 item_param),
5630 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth,
5631 						 hdr.psn)),
5632 	},
5633 	/* Validate/create actions. */
5634 	[ACTIONS] = {
5635 		.name = "actions",
5636 		.help = "submit a list of associated actions",
5637 		.next = NEXT(next_action),
5638 		.call = parse_vc,
5639 	},
5640 	[ACTION_NEXT] = {
5641 		.name = "/",
5642 		.help = "specify next action",
5643 		.next = NEXT(next_action),
5644 	},
5645 	[ACTION_END] = {
5646 		.name = "end",
5647 		.help = "end list of actions",
5648 		.priv = PRIV_ACTION(END, 0),
5649 		.call = parse_vc,
5650 	},
5651 	[ACTION_VOID] = {
5652 		.name = "void",
5653 		.help = "no-op action",
5654 		.priv = PRIV_ACTION(VOID, 0),
5655 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5656 		.call = parse_vc,
5657 	},
5658 	[ACTION_PASSTHRU] = {
5659 		.name = "passthru",
5660 		.help = "let subsequent rule process matched packets",
5661 		.priv = PRIV_ACTION(PASSTHRU, 0),
5662 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5663 		.call = parse_vc,
5664 	},
5665 	[ACTION_SKIP_CMAN] = {
5666 		.name = "skip_cman",
5667 		.help = "bypass cman on received packets",
5668 		.priv = PRIV_ACTION(SKIP_CMAN, 0),
5669 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5670 		.call = parse_vc,
5671 	},
5672 	[ACTION_JUMP] = {
5673 		.name = "jump",
5674 		.help = "redirect traffic to a given group",
5675 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
5676 		.next = NEXT(action_jump),
5677 		.call = parse_vc,
5678 	},
5679 	[ACTION_JUMP_GROUP] = {
5680 		.name = "group",
5681 		.help = "group to redirect traffic to",
5682 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
5683 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
5684 		.call = parse_vc_conf,
5685 	},
5686 	[ACTION_MARK] = {
5687 		.name = "mark",
5688 		.help = "attach 32 bit value to packets",
5689 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
5690 		.next = NEXT(action_mark),
5691 		.call = parse_vc,
5692 	},
5693 	[ACTION_MARK_ID] = {
5694 		.name = "id",
5695 		.help = "32 bit value to return with packets",
5696 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
5697 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
5698 		.call = parse_vc_conf,
5699 	},
5700 	[ACTION_FLAG] = {
5701 		.name = "flag",
5702 		.help = "flag packets",
5703 		.priv = PRIV_ACTION(FLAG, 0),
5704 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5705 		.call = parse_vc,
5706 	},
5707 	[ACTION_QUEUE] = {
5708 		.name = "queue",
5709 		.help = "assign packets to a given queue index",
5710 		.priv = PRIV_ACTION(QUEUE,
5711 				    sizeof(struct rte_flow_action_queue)),
5712 		.next = NEXT(action_queue),
5713 		.call = parse_vc,
5714 	},
5715 	[ACTION_QUEUE_INDEX] = {
5716 		.name = "index",
5717 		.help = "queue index to use",
5718 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
5719 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
5720 		.call = parse_vc_conf,
5721 	},
5722 	[ACTION_DROP] = {
5723 		.name = "drop",
5724 		.help = "drop packets (note: passthru has priority)",
5725 		.priv = PRIV_ACTION(DROP, 0),
5726 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5727 		.call = parse_vc,
5728 	},
5729 	[ACTION_COUNT] = {
5730 		.name = "count",
5731 		.help = "enable counters for this rule",
5732 		.priv = PRIV_ACTION(COUNT,
5733 				    sizeof(struct rte_flow_action_count)),
5734 		.next = NEXT(action_count),
5735 		.call = parse_vc,
5736 	},
5737 	[ACTION_COUNT_ID] = {
5738 		.name = "identifier",
5739 		.help = "counter identifier to use",
5740 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
5741 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
5742 		.call = parse_vc_conf,
5743 	},
5744 	[ACTION_RSS] = {
5745 		.name = "rss",
5746 		.help = "spread packets among several queues",
5747 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
5748 		.next = NEXT(action_rss),
5749 		.call = parse_vc_action_rss,
5750 	},
5751 	[ACTION_RSS_FUNC] = {
5752 		.name = "func",
5753 		.help = "RSS hash function to apply",
5754 		.next = NEXT(action_rss,
5755 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
5756 					ACTION_RSS_FUNC_TOEPLITZ,
5757 					ACTION_RSS_FUNC_SIMPLE_XOR,
5758 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
5759 	},
5760 	[ACTION_RSS_FUNC_DEFAULT] = {
5761 		.name = "default",
5762 		.help = "default hash function",
5763 		.call = parse_vc_action_rss_func,
5764 	},
5765 	[ACTION_RSS_FUNC_TOEPLITZ] = {
5766 		.name = "toeplitz",
5767 		.help = "Toeplitz hash function",
5768 		.call = parse_vc_action_rss_func,
5769 	},
5770 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
5771 		.name = "simple_xor",
5772 		.help = "simple XOR hash function",
5773 		.call = parse_vc_action_rss_func,
5774 	},
5775 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
5776 		.name = "symmetric_toeplitz",
5777 		.help = "Symmetric Toeplitz hash function",
5778 		.call = parse_vc_action_rss_func,
5779 	},
5780 	[ACTION_RSS_LEVEL] = {
5781 		.name = "level",
5782 		.help = "encapsulation level for \"types\"",
5783 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5784 		.args = ARGS(ARGS_ENTRY_ARB
5785 			     (offsetof(struct action_rss_data, conf) +
5786 			      offsetof(struct rte_flow_action_rss, level),
5787 			      sizeof(((struct rte_flow_action_rss *)0)->
5788 				     level))),
5789 	},
5790 	[ACTION_RSS_TYPES] = {
5791 		.name = "types",
5792 		.help = "specific RSS hash types",
5793 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
5794 	},
5795 	[ACTION_RSS_TYPE] = {
5796 		.name = "{type}",
5797 		.help = "RSS hash type",
5798 		.call = parse_vc_action_rss_type,
5799 		.comp = comp_vc_action_rss_type,
5800 	},
5801 	[ACTION_RSS_KEY] = {
5802 		.name = "key",
5803 		.help = "RSS hash key",
5804 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
5805 		.args = ARGS(ARGS_ENTRY_ARB
5806 			     (offsetof(struct action_rss_data, conf) +
5807 			      offsetof(struct rte_flow_action_rss, key),
5808 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
5809 			     ARGS_ENTRY_ARB
5810 			     (offsetof(struct action_rss_data, conf) +
5811 			      offsetof(struct rte_flow_action_rss, key_len),
5812 			      sizeof(((struct rte_flow_action_rss *)0)->
5813 				     key_len)),
5814 			     ARGS_ENTRY(struct action_rss_data, key)),
5815 	},
5816 	[ACTION_RSS_KEY_LEN] = {
5817 		.name = "key_len",
5818 		.help = "RSS hash key length in bytes",
5819 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
5820 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
5821 			     (offsetof(struct action_rss_data, conf) +
5822 			      offsetof(struct rte_flow_action_rss, key_len),
5823 			      sizeof(((struct rte_flow_action_rss *)0)->
5824 				     key_len),
5825 			      0,
5826 			      RSS_HASH_KEY_LENGTH)),
5827 	},
5828 	[ACTION_RSS_QUEUES] = {
5829 		.name = "queues",
5830 		.help = "queue indices to use",
5831 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
5832 		.call = parse_vc_conf,
5833 	},
5834 	[ACTION_RSS_QUEUE] = {
5835 		.name = "{queue}",
5836 		.help = "queue index",
5837 		.call = parse_vc_action_rss_queue,
5838 		.comp = comp_vc_action_rss_queue,
5839 	},
5840 	[ACTION_PF] = {
5841 		.name = "pf",
5842 		.help = "direct traffic to physical function",
5843 		.priv = PRIV_ACTION(PF, 0),
5844 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5845 		.call = parse_vc,
5846 	},
5847 	[ACTION_VF] = {
5848 		.name = "vf",
5849 		.help = "direct traffic to a virtual function ID",
5850 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
5851 		.next = NEXT(action_vf),
5852 		.call = parse_vc,
5853 	},
5854 	[ACTION_VF_ORIGINAL] = {
5855 		.name = "original",
5856 		.help = "use original VF ID if possible",
5857 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
5858 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
5859 					   original, 1)),
5860 		.call = parse_vc_conf,
5861 	},
5862 	[ACTION_VF_ID] = {
5863 		.name = "id",
5864 		.help = "VF ID",
5865 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
5866 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
5867 		.call = parse_vc_conf,
5868 	},
5869 	[ACTION_PORT_ID] = {
5870 		.name = "port_id",
5871 		.help = "direct matching traffic to a given DPDK port ID",
5872 		.priv = PRIV_ACTION(PORT_ID,
5873 				    sizeof(struct rte_flow_action_port_id)),
5874 		.next = NEXT(action_port_id),
5875 		.call = parse_vc,
5876 	},
5877 	[ACTION_PORT_ID_ORIGINAL] = {
5878 		.name = "original",
5879 		.help = "use original DPDK port ID if possible",
5880 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
5881 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
5882 					   original, 1)),
5883 		.call = parse_vc_conf,
5884 	},
5885 	[ACTION_PORT_ID_ID] = {
5886 		.name = "id",
5887 		.help = "DPDK port ID",
5888 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
5889 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
5890 		.call = parse_vc_conf,
5891 	},
5892 	[ACTION_METER] = {
5893 		.name = "meter",
5894 		.help = "meter the directed packets at given id",
5895 		.priv = PRIV_ACTION(METER,
5896 				    sizeof(struct rte_flow_action_meter)),
5897 		.next = NEXT(action_meter),
5898 		.call = parse_vc,
5899 	},
5900 	[ACTION_METER_COLOR] = {
5901 		.name = "color",
5902 		.help = "meter color for the packets",
5903 		.priv = PRIV_ACTION(METER_COLOR,
5904 				sizeof(struct rte_flow_action_meter_color)),
5905 		.next = NEXT(action_meter_color),
5906 		.call = parse_vc,
5907 	},
5908 	[ACTION_METER_COLOR_TYPE] = {
5909 		.name = "type",
5910 		.help = "specific meter color",
5911 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
5912 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
5913 					ACTION_METER_COLOR_YELLOW,
5914 					ACTION_METER_COLOR_RED)),
5915 	},
5916 	[ACTION_METER_COLOR_GREEN] = {
5917 		.name = "green",
5918 		.help = "meter color green",
5919 		.call = parse_vc_action_meter_color_type,
5920 	},
5921 	[ACTION_METER_COLOR_YELLOW] = {
5922 		.name = "yellow",
5923 		.help = "meter color yellow",
5924 		.call = parse_vc_action_meter_color_type,
5925 	},
5926 	[ACTION_METER_COLOR_RED] = {
5927 		.name = "red",
5928 		.help = "meter color red",
5929 		.call = parse_vc_action_meter_color_type,
5930 	},
5931 	[ACTION_METER_ID] = {
5932 		.name = "mtr_id",
5933 		.help = "meter id to use",
5934 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
5935 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
5936 		.call = parse_vc_conf,
5937 	},
5938 	[ACTION_METER_MARK] = {
5939 		.name = "meter_mark",
5940 		.help = "meter the directed packets using profile and policy",
5941 		.priv = PRIV_ACTION(METER_MARK,
5942 				    sizeof(struct rte_flow_action_meter_mark)),
5943 		.next = NEXT(action_meter_mark),
5944 		.call = parse_vc,
5945 	},
5946 	[ACTION_METER_PROFILE] = {
5947 		.name = "mtr_profile",
5948 		.help = "meter profile id to use",
5949 		.next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)),
5950 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5951 	},
5952 	[ACTION_METER_PROFILE_ID2PTR] = {
5953 		.name = "{mtr_profile_id}",
5954 		.type = "PROFILE_ID",
5955 		.help = "meter profile id",
5956 		.next = NEXT(action_meter_mark),
5957 		.call = parse_meter_profile_id2ptr,
5958 		.comp = comp_none,
5959 	},
5960 	[ACTION_METER_POLICY] = {
5961 		.name = "mtr_policy",
5962 		.help = "meter policy id to use",
5963 		.next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)),
5964 		ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
5965 	},
5966 	[ACTION_METER_POLICY_ID2PTR] = {
5967 		.name = "{mtr_policy_id}",
5968 		.type = "POLICY_ID",
5969 		.help = "meter policy id",
5970 		.next = NEXT(action_meter_mark),
5971 		.call = parse_meter_policy_id2ptr,
5972 		.comp = comp_none,
5973 	},
5974 	[ACTION_METER_COLOR_MODE] = {
5975 		.name = "mtr_color_mode",
5976 		.help = "meter color awareness mode",
5977 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
5978 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)),
5979 		.call = parse_vc_conf,
5980 	},
5981 	[ACTION_METER_INIT_COLOR] = {
5982 		.name = "mtr_init_color",
5983 		.help = "meter initial color",
5984 		.next = NEXT(action_meter_mark, NEXT_ENTRY(ITEM_METER_COLOR_NAME)),
5985 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, init_color)),
5986 	},
5987 	[ACTION_METER_STATE] = {
5988 		.name = "mtr_state",
5989 		.help = "meter state",
5990 		.next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
5991 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)),
5992 		.call = parse_vc_conf,
5993 	},
5994 	[ACTION_OF_DEC_NW_TTL] = {
5995 		.name = "of_dec_nw_ttl",
5996 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
5997 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
5998 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
5999 		.call = parse_vc,
6000 	},
6001 	[ACTION_OF_POP_VLAN] = {
6002 		.name = "of_pop_vlan",
6003 		.help = "OpenFlow's OFPAT_POP_VLAN",
6004 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
6005 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6006 		.call = parse_vc,
6007 	},
6008 	[ACTION_OF_PUSH_VLAN] = {
6009 		.name = "of_push_vlan",
6010 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
6011 		.priv = PRIV_ACTION
6012 			(OF_PUSH_VLAN,
6013 			 sizeof(struct rte_flow_action_of_push_vlan)),
6014 		.next = NEXT(action_of_push_vlan),
6015 		.call = parse_vc,
6016 	},
6017 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
6018 		.name = "ethertype",
6019 		.help = "EtherType",
6020 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
6021 		.args = ARGS(ARGS_ENTRY_HTON
6022 			     (struct rte_flow_action_of_push_vlan,
6023 			      ethertype)),
6024 		.call = parse_vc_conf,
6025 	},
6026 	[ACTION_OF_SET_VLAN_VID] = {
6027 		.name = "of_set_vlan_vid",
6028 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
6029 		.priv = PRIV_ACTION
6030 			(OF_SET_VLAN_VID,
6031 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
6032 		.next = NEXT(action_of_set_vlan_vid),
6033 		.call = parse_vc,
6034 	},
6035 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
6036 		.name = "vlan_vid",
6037 		.help = "VLAN id",
6038 		.next = NEXT(action_of_set_vlan_vid,
6039 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6040 		.args = ARGS(ARGS_ENTRY_HTON
6041 			     (struct rte_flow_action_of_set_vlan_vid,
6042 			      vlan_vid)),
6043 		.call = parse_vc_conf,
6044 	},
6045 	[ACTION_OF_SET_VLAN_PCP] = {
6046 		.name = "of_set_vlan_pcp",
6047 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
6048 		.priv = PRIV_ACTION
6049 			(OF_SET_VLAN_PCP,
6050 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
6051 		.next = NEXT(action_of_set_vlan_pcp),
6052 		.call = parse_vc,
6053 	},
6054 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
6055 		.name = "vlan_pcp",
6056 		.help = "VLAN priority",
6057 		.next = NEXT(action_of_set_vlan_pcp,
6058 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6059 		.args = ARGS(ARGS_ENTRY_HTON
6060 			     (struct rte_flow_action_of_set_vlan_pcp,
6061 			      vlan_pcp)),
6062 		.call = parse_vc_conf,
6063 	},
6064 	[ACTION_OF_POP_MPLS] = {
6065 		.name = "of_pop_mpls",
6066 		.help = "OpenFlow's OFPAT_POP_MPLS",
6067 		.priv = PRIV_ACTION(OF_POP_MPLS,
6068 				    sizeof(struct rte_flow_action_of_pop_mpls)),
6069 		.next = NEXT(action_of_pop_mpls),
6070 		.call = parse_vc,
6071 	},
6072 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
6073 		.name = "ethertype",
6074 		.help = "EtherType",
6075 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6076 		.args = ARGS(ARGS_ENTRY_HTON
6077 			     (struct rte_flow_action_of_pop_mpls,
6078 			      ethertype)),
6079 		.call = parse_vc_conf,
6080 	},
6081 	[ACTION_OF_PUSH_MPLS] = {
6082 		.name = "of_push_mpls",
6083 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
6084 		.priv = PRIV_ACTION
6085 			(OF_PUSH_MPLS,
6086 			 sizeof(struct rte_flow_action_of_push_mpls)),
6087 		.next = NEXT(action_of_push_mpls),
6088 		.call = parse_vc,
6089 	},
6090 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
6091 		.name = "ethertype",
6092 		.help = "EtherType",
6093 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
6094 		.args = ARGS(ARGS_ENTRY_HTON
6095 			     (struct rte_flow_action_of_push_mpls,
6096 			      ethertype)),
6097 		.call = parse_vc_conf,
6098 	},
6099 	[ACTION_VXLAN_ENCAP] = {
6100 		.name = "vxlan_encap",
6101 		.help = "VXLAN encapsulation, uses configuration set by \"set"
6102 			" vxlan\"",
6103 		.priv = PRIV_ACTION(VXLAN_ENCAP,
6104 				    sizeof(struct action_vxlan_encap_data)),
6105 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6106 		.call = parse_vc_action_vxlan_encap,
6107 	},
6108 	[ACTION_VXLAN_DECAP] = {
6109 		.name = "vxlan_decap",
6110 		.help = "Performs a decapsulation action by stripping all"
6111 			" headers of the VXLAN tunnel network overlay from the"
6112 			" matched flow.",
6113 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
6114 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6115 		.call = parse_vc,
6116 	},
6117 	[ACTION_NVGRE_ENCAP] = {
6118 		.name = "nvgre_encap",
6119 		.help = "NVGRE encapsulation, uses configuration set by \"set"
6120 			" nvgre\"",
6121 		.priv = PRIV_ACTION(NVGRE_ENCAP,
6122 				    sizeof(struct action_nvgre_encap_data)),
6123 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6124 		.call = parse_vc_action_nvgre_encap,
6125 	},
6126 	[ACTION_NVGRE_DECAP] = {
6127 		.name = "nvgre_decap",
6128 		.help = "Performs a decapsulation action by stripping all"
6129 			" headers of the NVGRE tunnel network overlay from the"
6130 			" matched flow.",
6131 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
6132 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6133 		.call = parse_vc,
6134 	},
6135 	[ACTION_L2_ENCAP] = {
6136 		.name = "l2_encap",
6137 		.help = "l2 encap, uses configuration set by"
6138 			" \"set l2_encap\"",
6139 		.priv = PRIV_ACTION(RAW_ENCAP,
6140 				    sizeof(struct action_raw_encap_data)),
6141 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6142 		.call = parse_vc_action_l2_encap,
6143 	},
6144 	[ACTION_L2_DECAP] = {
6145 		.name = "l2_decap",
6146 		.help = "l2 decap, uses configuration set by"
6147 			" \"set l2_decap\"",
6148 		.priv = PRIV_ACTION(RAW_DECAP,
6149 				    sizeof(struct action_raw_decap_data)),
6150 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6151 		.call = parse_vc_action_l2_decap,
6152 	},
6153 	[ACTION_MPLSOGRE_ENCAP] = {
6154 		.name = "mplsogre_encap",
6155 		.help = "mplsogre encapsulation, uses configuration set by"
6156 			" \"set mplsogre_encap\"",
6157 		.priv = PRIV_ACTION(RAW_ENCAP,
6158 				    sizeof(struct action_raw_encap_data)),
6159 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6160 		.call = parse_vc_action_mplsogre_encap,
6161 	},
6162 	[ACTION_MPLSOGRE_DECAP] = {
6163 		.name = "mplsogre_decap",
6164 		.help = "mplsogre decapsulation, uses configuration set by"
6165 			" \"set mplsogre_decap\"",
6166 		.priv = PRIV_ACTION(RAW_DECAP,
6167 				    sizeof(struct action_raw_decap_data)),
6168 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6169 		.call = parse_vc_action_mplsogre_decap,
6170 	},
6171 	[ACTION_MPLSOUDP_ENCAP] = {
6172 		.name = "mplsoudp_encap",
6173 		.help = "mplsoudp encapsulation, uses configuration set by"
6174 			" \"set mplsoudp_encap\"",
6175 		.priv = PRIV_ACTION(RAW_ENCAP,
6176 				    sizeof(struct action_raw_encap_data)),
6177 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6178 		.call = parse_vc_action_mplsoudp_encap,
6179 	},
6180 	[ACTION_MPLSOUDP_DECAP] = {
6181 		.name = "mplsoudp_decap",
6182 		.help = "mplsoudp decapsulation, uses configuration set by"
6183 			" \"set mplsoudp_decap\"",
6184 		.priv = PRIV_ACTION(RAW_DECAP,
6185 				    sizeof(struct action_raw_decap_data)),
6186 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6187 		.call = parse_vc_action_mplsoudp_decap,
6188 	},
6189 	[ACTION_SET_IPV4_SRC] = {
6190 		.name = "set_ipv4_src",
6191 		.help = "Set a new IPv4 source address in the outermost"
6192 			" IPv4 header",
6193 		.priv = PRIV_ACTION(SET_IPV4_SRC,
6194 			sizeof(struct rte_flow_action_set_ipv4)),
6195 		.next = NEXT(action_set_ipv4_src),
6196 		.call = parse_vc,
6197 	},
6198 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
6199 		.name = "ipv4_addr",
6200 		.help = "new IPv4 source address to set",
6201 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6202 		.args = ARGS(ARGS_ENTRY_HTON
6203 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6204 		.call = parse_vc_conf,
6205 	},
6206 	[ACTION_SET_IPV4_DST] = {
6207 		.name = "set_ipv4_dst",
6208 		.help = "Set a new IPv4 destination address in the outermost"
6209 			" IPv4 header",
6210 		.priv = PRIV_ACTION(SET_IPV4_DST,
6211 			sizeof(struct rte_flow_action_set_ipv4)),
6212 		.next = NEXT(action_set_ipv4_dst),
6213 		.call = parse_vc,
6214 	},
6215 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
6216 		.name = "ipv4_addr",
6217 		.help = "new IPv4 destination address to set",
6218 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
6219 		.args = ARGS(ARGS_ENTRY_HTON
6220 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
6221 		.call = parse_vc_conf,
6222 	},
6223 	[ACTION_SET_IPV6_SRC] = {
6224 		.name = "set_ipv6_src",
6225 		.help = "Set a new IPv6 source address in the outermost"
6226 			" IPv6 header",
6227 		.priv = PRIV_ACTION(SET_IPV6_SRC,
6228 			sizeof(struct rte_flow_action_set_ipv6)),
6229 		.next = NEXT(action_set_ipv6_src),
6230 		.call = parse_vc,
6231 	},
6232 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
6233 		.name = "ipv6_addr",
6234 		.help = "new IPv6 source address to set",
6235 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6236 		.args = ARGS(ARGS_ENTRY_HTON
6237 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6238 		.call = parse_vc_conf,
6239 	},
6240 	[ACTION_SET_IPV6_DST] = {
6241 		.name = "set_ipv6_dst",
6242 		.help = "Set a new IPv6 destination address in the outermost"
6243 			" IPv6 header",
6244 		.priv = PRIV_ACTION(SET_IPV6_DST,
6245 			sizeof(struct rte_flow_action_set_ipv6)),
6246 		.next = NEXT(action_set_ipv6_dst),
6247 		.call = parse_vc,
6248 	},
6249 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
6250 		.name = "ipv6_addr",
6251 		.help = "new IPv6 destination address to set",
6252 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
6253 		.args = ARGS(ARGS_ENTRY_HTON
6254 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
6255 		.call = parse_vc_conf,
6256 	},
6257 	[ACTION_SET_TP_SRC] = {
6258 		.name = "set_tp_src",
6259 		.help = "set a new source port number in the outermost"
6260 			" TCP/UDP header",
6261 		.priv = PRIV_ACTION(SET_TP_SRC,
6262 			sizeof(struct rte_flow_action_set_tp)),
6263 		.next = NEXT(action_set_tp_src),
6264 		.call = parse_vc,
6265 	},
6266 	[ACTION_SET_TP_SRC_TP_SRC] = {
6267 		.name = "port",
6268 		.help = "new source port number to set",
6269 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
6270 		.args = ARGS(ARGS_ENTRY_HTON
6271 			     (struct rte_flow_action_set_tp, port)),
6272 		.call = parse_vc_conf,
6273 	},
6274 	[ACTION_SET_TP_DST] = {
6275 		.name = "set_tp_dst",
6276 		.help = "set a new destination port number in the outermost"
6277 			" TCP/UDP header",
6278 		.priv = PRIV_ACTION(SET_TP_DST,
6279 			sizeof(struct rte_flow_action_set_tp)),
6280 		.next = NEXT(action_set_tp_dst),
6281 		.call = parse_vc,
6282 	},
6283 	[ACTION_SET_TP_DST_TP_DST] = {
6284 		.name = "port",
6285 		.help = "new destination port number to set",
6286 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
6287 		.args = ARGS(ARGS_ENTRY_HTON
6288 			     (struct rte_flow_action_set_tp, port)),
6289 		.call = parse_vc_conf,
6290 	},
6291 	[ACTION_MAC_SWAP] = {
6292 		.name = "mac_swap",
6293 		.help = "Swap the source and destination MAC addresses"
6294 			" in the outermost Ethernet header",
6295 		.priv = PRIV_ACTION(MAC_SWAP, 0),
6296 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6297 		.call = parse_vc,
6298 	},
6299 	[ACTION_DEC_TTL] = {
6300 		.name = "dec_ttl",
6301 		.help = "decrease network TTL if available",
6302 		.priv = PRIV_ACTION(DEC_TTL, 0),
6303 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6304 		.call = parse_vc,
6305 	},
6306 	[ACTION_SET_TTL] = {
6307 		.name = "set_ttl",
6308 		.help = "set ttl value",
6309 		.priv = PRIV_ACTION(SET_TTL,
6310 			sizeof(struct rte_flow_action_set_ttl)),
6311 		.next = NEXT(action_set_ttl),
6312 		.call = parse_vc,
6313 	},
6314 	[ACTION_SET_TTL_TTL] = {
6315 		.name = "ttl_value",
6316 		.help = "new ttl value to set",
6317 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
6318 		.args = ARGS(ARGS_ENTRY_HTON
6319 			     (struct rte_flow_action_set_ttl, ttl_value)),
6320 		.call = parse_vc_conf,
6321 	},
6322 	[ACTION_SET_MAC_SRC] = {
6323 		.name = "set_mac_src",
6324 		.help = "set source mac address",
6325 		.priv = PRIV_ACTION(SET_MAC_SRC,
6326 			sizeof(struct rte_flow_action_set_mac)),
6327 		.next = NEXT(action_set_mac_src),
6328 		.call = parse_vc,
6329 	},
6330 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
6331 		.name = "mac_addr",
6332 		.help = "new source mac address",
6333 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
6334 		.args = ARGS(ARGS_ENTRY_HTON
6335 			     (struct rte_flow_action_set_mac, mac_addr)),
6336 		.call = parse_vc_conf,
6337 	},
6338 	[ACTION_SET_MAC_DST] = {
6339 		.name = "set_mac_dst",
6340 		.help = "set destination mac address",
6341 		.priv = PRIV_ACTION(SET_MAC_DST,
6342 			sizeof(struct rte_flow_action_set_mac)),
6343 		.next = NEXT(action_set_mac_dst),
6344 		.call = parse_vc,
6345 	},
6346 	[ACTION_SET_MAC_DST_MAC_DST] = {
6347 		.name = "mac_addr",
6348 		.help = "new destination mac address to set",
6349 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
6350 		.args = ARGS(ARGS_ENTRY_HTON
6351 			     (struct rte_flow_action_set_mac, mac_addr)),
6352 		.call = parse_vc_conf,
6353 	},
6354 	[ACTION_INC_TCP_SEQ] = {
6355 		.name = "inc_tcp_seq",
6356 		.help = "increase TCP sequence number",
6357 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
6358 		.next = NEXT(action_inc_tcp_seq),
6359 		.call = parse_vc,
6360 	},
6361 	[ACTION_INC_TCP_SEQ_VALUE] = {
6362 		.name = "value",
6363 		.help = "the value to increase TCP sequence number by",
6364 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
6365 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6366 		.call = parse_vc_conf,
6367 	},
6368 	[ACTION_DEC_TCP_SEQ] = {
6369 		.name = "dec_tcp_seq",
6370 		.help = "decrease TCP sequence number",
6371 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
6372 		.next = NEXT(action_dec_tcp_seq),
6373 		.call = parse_vc,
6374 	},
6375 	[ACTION_DEC_TCP_SEQ_VALUE] = {
6376 		.name = "value",
6377 		.help = "the value to decrease TCP sequence number by",
6378 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
6379 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6380 		.call = parse_vc_conf,
6381 	},
6382 	[ACTION_INC_TCP_ACK] = {
6383 		.name = "inc_tcp_ack",
6384 		.help = "increase TCP acknowledgment number",
6385 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
6386 		.next = NEXT(action_inc_tcp_ack),
6387 		.call = parse_vc,
6388 	},
6389 	[ACTION_INC_TCP_ACK_VALUE] = {
6390 		.name = "value",
6391 		.help = "the value to increase TCP acknowledgment number by",
6392 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
6393 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6394 		.call = parse_vc_conf,
6395 	},
6396 	[ACTION_DEC_TCP_ACK] = {
6397 		.name = "dec_tcp_ack",
6398 		.help = "decrease TCP acknowledgment number",
6399 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
6400 		.next = NEXT(action_dec_tcp_ack),
6401 		.call = parse_vc,
6402 	},
6403 	[ACTION_DEC_TCP_ACK_VALUE] = {
6404 		.name = "value",
6405 		.help = "the value to decrease TCP acknowledgment number by",
6406 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
6407 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
6408 		.call = parse_vc_conf,
6409 	},
6410 	[ACTION_RAW_ENCAP] = {
6411 		.name = "raw_encap",
6412 		.help = "encapsulation data, defined by set raw_encap",
6413 		.priv = PRIV_ACTION(RAW_ENCAP,
6414 			sizeof(struct action_raw_encap_data)),
6415 		.next = NEXT(action_raw_encap),
6416 		.call = parse_vc_action_raw_encap,
6417 	},
6418 	[ACTION_RAW_ENCAP_INDEX] = {
6419 		.name = "index",
6420 		.help = "the index of raw_encap_confs",
6421 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
6422 	},
6423 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
6424 		.name = "{index}",
6425 		.type = "UNSIGNED",
6426 		.help = "unsigned integer value",
6427 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6428 		.call = parse_vc_action_raw_encap_index,
6429 		.comp = comp_set_raw_index,
6430 	},
6431 	[ACTION_RAW_DECAP] = {
6432 		.name = "raw_decap",
6433 		.help = "decapsulation data, defined by set raw_encap",
6434 		.priv = PRIV_ACTION(RAW_DECAP,
6435 			sizeof(struct action_raw_decap_data)),
6436 		.next = NEXT(action_raw_decap),
6437 		.call = parse_vc_action_raw_decap,
6438 	},
6439 	[ACTION_RAW_DECAP_INDEX] = {
6440 		.name = "index",
6441 		.help = "the index of raw_encap_confs",
6442 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
6443 	},
6444 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
6445 		.name = "{index}",
6446 		.type = "UNSIGNED",
6447 		.help = "unsigned integer value",
6448 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6449 		.call = parse_vc_action_raw_decap_index,
6450 		.comp = comp_set_raw_index,
6451 	},
6452 	[ACTION_MODIFY_FIELD] = {
6453 		.name = "modify_field",
6454 		.help = "modify destination field with data from source field",
6455 		.priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE),
6456 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
6457 		.call = parse_vc,
6458 	},
6459 	[ACTION_MODIFY_FIELD_OP] = {
6460 		.name = "op",
6461 		.help = "operation type",
6462 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
6463 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
6464 		.call = parse_vc_conf,
6465 	},
6466 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
6467 		.name = "{operation}",
6468 		.help = "operation type value",
6469 		.call = parse_vc_modify_field_op,
6470 		.comp = comp_set_modify_field_op,
6471 	},
6472 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
6473 		.name = "dst_type",
6474 		.help = "destination field type",
6475 		.next = NEXT(action_modify_field_dst,
6476 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
6477 		.call = parse_vc_conf,
6478 	},
6479 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
6480 		.name = "{dst_type}",
6481 		.help = "destination field type value",
6482 		.call = parse_vc_modify_field_id,
6483 		.comp = comp_set_modify_field_id,
6484 	},
6485 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
6486 		.name = "dst_level",
6487 		.help = "destination field level",
6488 		.next = NEXT(action_modify_field_dst,
6489 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)),
6490 		.call = parse_vc_conf,
6491 	},
6492 	[ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = {
6493 		.name = "{dst_level}",
6494 		.help = "destination field level value",
6495 		.call = parse_vc_modify_field_level,
6496 		.comp = comp_none,
6497 	},
6498 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
6499 		.name = "dst_offset",
6500 		.help = "destination field bit offset",
6501 		.next = NEXT(action_modify_field_dst,
6502 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6503 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6504 					dst.offset)),
6505 		.call = parse_vc_conf,
6506 	},
6507 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
6508 		.name = "src_type",
6509 		.help = "source field type",
6510 		.next = NEXT(action_modify_field_src,
6511 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
6512 		.call = parse_vc_conf,
6513 	},
6514 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
6515 		.name = "{src_type}",
6516 		.help = "source field type value",
6517 		.call = parse_vc_modify_field_id,
6518 		.comp = comp_set_modify_field_id,
6519 	},
6520 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
6521 		.name = "src_level",
6522 		.help = "source field level",
6523 		.next = NEXT(action_modify_field_src,
6524 			     NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)),
6525 		.call = parse_vc_conf,
6526 	},
6527 	[ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = {
6528 		.name = "{src_level}",
6529 		.help = "source field level value",
6530 		.call = parse_vc_modify_field_level,
6531 		.comp = comp_none,
6532 	},
6533 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
6534 		.name = "src_offset",
6535 		.help = "source field bit offset",
6536 		.next = NEXT(action_modify_field_src,
6537 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6538 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6539 					src.offset)),
6540 		.call = parse_vc_conf,
6541 	},
6542 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
6543 		.name = "src_value",
6544 		.help = "source immediate value",
6545 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
6546 			     NEXT_ENTRY(COMMON_HEX)),
6547 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
6548 			     ARGS_ENTRY_ARB(0, 0),
6549 			     ARGS_ENTRY(struct rte_flow_action_modify_field,
6550 					src.value)),
6551 		.call = parse_vc_conf,
6552 	},
6553 	[ACTION_MODIFY_FIELD_SRC_POINTER] = {
6554 		.name = "src_ptr",
6555 		.help = "pointer to source immediate value",
6556 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
6557 			     NEXT_ENTRY(COMMON_HEX)),
6558 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6559 					src.pvalue),
6560 			     ARGS_ENTRY_ARB(0, 0),
6561 			     ARGS_ENTRY_ARB
6562 				(sizeof(struct rte_flow_action_modify_field),
6563 				 ACTION_MODIFY_PATTERN_SIZE)),
6564 		.call = parse_vc_conf,
6565 	},
6566 	[ACTION_MODIFY_FIELD_WIDTH] = {
6567 		.name = "width",
6568 		.help = "number of bits to copy",
6569 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
6570 			NEXT_ENTRY(COMMON_UNSIGNED)),
6571 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
6572 					width)),
6573 		.call = parse_vc_conf,
6574 	},
6575 	[ACTION_SEND_TO_KERNEL] = {
6576 		.name = "send_to_kernel",
6577 		.help = "send packets to kernel",
6578 		.priv = PRIV_ACTION(SEND_TO_KERNEL, 0),
6579 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6580 		.call = parse_vc,
6581 	},
6582 	/* Top level command. */
6583 	[SET] = {
6584 		.name = "set",
6585 		.help = "set raw encap/decap/sample data",
6586 		.type = "set raw_encap|raw_decap <index> <pattern>"
6587 				" or set sample_actions <index> <action>",
6588 		.next = NEXT(NEXT_ENTRY
6589 			     (SET_RAW_ENCAP,
6590 			      SET_RAW_DECAP,
6591 			      SET_SAMPLE_ACTIONS)),
6592 		.call = parse_set_init,
6593 	},
6594 	/* Sub-level commands. */
6595 	[SET_RAW_ENCAP] = {
6596 		.name = "raw_encap",
6597 		.help = "set raw encap data",
6598 		.next = NEXT(next_set_raw),
6599 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6600 				(offsetof(struct buffer, port),
6601 				 sizeof(((struct buffer *)0)->port),
6602 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
6603 		.call = parse_set_raw_encap_decap,
6604 	},
6605 	[SET_RAW_DECAP] = {
6606 		.name = "raw_decap",
6607 		.help = "set raw decap data",
6608 		.next = NEXT(next_set_raw),
6609 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6610 				(offsetof(struct buffer, port),
6611 				 sizeof(((struct buffer *)0)->port),
6612 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
6613 		.call = parse_set_raw_encap_decap,
6614 	},
6615 	[SET_RAW_INDEX] = {
6616 		.name = "{index}",
6617 		.type = "COMMON_UNSIGNED",
6618 		.help = "index of raw_encap/raw_decap data",
6619 		.next = NEXT(next_item),
6620 		.call = parse_port,
6621 	},
6622 	[SET_SAMPLE_INDEX] = {
6623 		.name = "{index}",
6624 		.type = "UNSIGNED",
6625 		.help = "index of sample actions",
6626 		.next = NEXT(next_action_sample),
6627 		.call = parse_port,
6628 	},
6629 	[SET_SAMPLE_ACTIONS] = {
6630 		.name = "sample_actions",
6631 		.help = "set sample actions list",
6632 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
6633 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
6634 				(offsetof(struct buffer, port),
6635 				 sizeof(((struct buffer *)0)->port),
6636 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
6637 		.call = parse_set_sample_action,
6638 	},
6639 	[ACTION_SET_TAG] = {
6640 		.name = "set_tag",
6641 		.help = "set tag",
6642 		.priv = PRIV_ACTION(SET_TAG,
6643 			sizeof(struct rte_flow_action_set_tag)),
6644 		.next = NEXT(action_set_tag),
6645 		.call = parse_vc,
6646 	},
6647 	[ACTION_SET_TAG_INDEX] = {
6648 		.name = "index",
6649 		.help = "index of tag array",
6650 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6651 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
6652 		.call = parse_vc_conf,
6653 	},
6654 	[ACTION_SET_TAG_DATA] = {
6655 		.name = "data",
6656 		.help = "tag value",
6657 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6658 		.args = ARGS(ARGS_ENTRY
6659 			     (struct rte_flow_action_set_tag, data)),
6660 		.call = parse_vc_conf,
6661 	},
6662 	[ACTION_SET_TAG_MASK] = {
6663 		.name = "mask",
6664 		.help = "mask for tag value",
6665 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
6666 		.args = ARGS(ARGS_ENTRY
6667 			     (struct rte_flow_action_set_tag, mask)),
6668 		.call = parse_vc_conf,
6669 	},
6670 	[ACTION_SET_META] = {
6671 		.name = "set_meta",
6672 		.help = "set metadata",
6673 		.priv = PRIV_ACTION(SET_META,
6674 			sizeof(struct rte_flow_action_set_meta)),
6675 		.next = NEXT(action_set_meta),
6676 		.call = parse_vc_action_set_meta,
6677 	},
6678 	[ACTION_SET_META_DATA] = {
6679 		.name = "data",
6680 		.help = "metadata value",
6681 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
6682 		.args = ARGS(ARGS_ENTRY
6683 			     (struct rte_flow_action_set_meta, data)),
6684 		.call = parse_vc_conf,
6685 	},
6686 	[ACTION_SET_META_MASK] = {
6687 		.name = "mask",
6688 		.help = "mask for metadata value",
6689 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
6690 		.args = ARGS(ARGS_ENTRY
6691 			     (struct rte_flow_action_set_meta, mask)),
6692 		.call = parse_vc_conf,
6693 	},
6694 	[ACTION_SET_IPV4_DSCP] = {
6695 		.name = "set_ipv4_dscp",
6696 		.help = "set DSCP value",
6697 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
6698 			sizeof(struct rte_flow_action_set_dscp)),
6699 		.next = NEXT(action_set_ipv4_dscp),
6700 		.call = parse_vc,
6701 	},
6702 	[ACTION_SET_IPV4_DSCP_VALUE] = {
6703 		.name = "dscp_value",
6704 		.help = "new IPv4 DSCP value to set",
6705 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
6706 		.args = ARGS(ARGS_ENTRY
6707 			     (struct rte_flow_action_set_dscp, dscp)),
6708 		.call = parse_vc_conf,
6709 	},
6710 	[ACTION_SET_IPV6_DSCP] = {
6711 		.name = "set_ipv6_dscp",
6712 		.help = "set DSCP value",
6713 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
6714 			sizeof(struct rte_flow_action_set_dscp)),
6715 		.next = NEXT(action_set_ipv6_dscp),
6716 		.call = parse_vc,
6717 	},
6718 	[ACTION_SET_IPV6_DSCP_VALUE] = {
6719 		.name = "dscp_value",
6720 		.help = "new IPv6 DSCP value to set",
6721 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
6722 		.args = ARGS(ARGS_ENTRY
6723 			     (struct rte_flow_action_set_dscp, dscp)),
6724 		.call = parse_vc_conf,
6725 	},
6726 	[ACTION_AGE] = {
6727 		.name = "age",
6728 		.help = "set a specific metadata header",
6729 		.next = NEXT(action_age),
6730 		.priv = PRIV_ACTION(AGE,
6731 			sizeof(struct rte_flow_action_age)),
6732 		.call = parse_vc,
6733 	},
6734 	[ACTION_AGE_TIMEOUT] = {
6735 		.name = "timeout",
6736 		.help = "flow age timeout value",
6737 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
6738 					   timeout, 24)),
6739 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
6740 		.call = parse_vc_conf,
6741 	},
6742 	[ACTION_AGE_UPDATE] = {
6743 		.name = "age_update",
6744 		.help = "update aging parameter",
6745 		.next = NEXT(action_age_update),
6746 		.priv = PRIV_ACTION(AGE,
6747 				    sizeof(struct rte_flow_update_age)),
6748 		.call = parse_vc,
6749 	},
6750 	[ACTION_AGE_UPDATE_TIMEOUT] = {
6751 		.name = "timeout",
6752 		.help = "age timeout update value",
6753 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
6754 					   timeout, 24)),
6755 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)),
6756 		.call = parse_vc_conf_timeout,
6757 	},
6758 	[ACTION_AGE_UPDATE_TOUCH] = {
6759 		.name = "touch",
6760 		.help = "this flow is touched",
6761 		.next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)),
6762 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age,
6763 					   touch, 1)),
6764 		.call = parse_vc_conf,
6765 	},
6766 	[ACTION_SAMPLE] = {
6767 		.name = "sample",
6768 		.help = "set a sample action",
6769 		.next = NEXT(action_sample),
6770 		.priv = PRIV_ACTION(SAMPLE,
6771 			sizeof(struct action_sample_data)),
6772 		.call = parse_vc_action_sample,
6773 	},
6774 	[ACTION_SAMPLE_RATIO] = {
6775 		.name = "ratio",
6776 		.help = "flow sample ratio value",
6777 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
6778 		.args = ARGS(ARGS_ENTRY_ARB
6779 			     (offsetof(struct action_sample_data, conf) +
6780 			      offsetof(struct rte_flow_action_sample, ratio),
6781 			      sizeof(((struct rte_flow_action_sample *)0)->
6782 				     ratio))),
6783 	},
6784 	[ACTION_SAMPLE_INDEX] = {
6785 		.name = "index",
6786 		.help = "the index of sample actions list",
6787 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
6788 	},
6789 	[ACTION_SAMPLE_INDEX_VALUE] = {
6790 		.name = "{index}",
6791 		.type = "COMMON_UNSIGNED",
6792 		.help = "unsigned integer value",
6793 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6794 		.call = parse_vc_action_sample_index,
6795 		.comp = comp_set_sample_index,
6796 	},
6797 	[ACTION_CONNTRACK] = {
6798 		.name = "conntrack",
6799 		.help = "create a conntrack object",
6800 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6801 		.priv = PRIV_ACTION(CONNTRACK,
6802 				    sizeof(struct rte_flow_action_conntrack)),
6803 		.call = parse_vc,
6804 	},
6805 	[ACTION_CONNTRACK_UPDATE] = {
6806 		.name = "conntrack_update",
6807 		.help = "update a conntrack object",
6808 		.next = NEXT(action_update_conntrack),
6809 		.priv = PRIV_ACTION(CONNTRACK,
6810 				    sizeof(struct rte_flow_modify_conntrack)),
6811 		.call = parse_vc,
6812 	},
6813 	[ACTION_CONNTRACK_UPDATE_DIR] = {
6814 		.name = "dir",
6815 		.help = "update a conntrack object direction",
6816 		.next = NEXT(action_update_conntrack),
6817 		.call = parse_vc_action_conntrack_update,
6818 	},
6819 	[ACTION_CONNTRACK_UPDATE_CTX] = {
6820 		.name = "ctx",
6821 		.help = "update a conntrack object context",
6822 		.next = NEXT(action_update_conntrack),
6823 		.call = parse_vc_action_conntrack_update,
6824 	},
6825 	[ACTION_PORT_REPRESENTOR] = {
6826 		.name = "port_representor",
6827 		.help = "at embedded switch level, send matching traffic to the given ethdev",
6828 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
6829 				    sizeof(struct rte_flow_action_ethdev)),
6830 		.next = NEXT(action_port_representor),
6831 		.call = parse_vc,
6832 	},
6833 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
6834 		.name = "port_id",
6835 		.help = "ethdev port ID",
6836 		.next = NEXT(action_port_representor,
6837 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6838 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6839 					port_id)),
6840 		.call = parse_vc_conf,
6841 	},
6842 	[ACTION_REPRESENTED_PORT] = {
6843 		.name = "represented_port",
6844 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
6845 		.priv = PRIV_ACTION(REPRESENTED_PORT,
6846 				sizeof(struct rte_flow_action_ethdev)),
6847 		.next = NEXT(action_represented_port),
6848 		.call = parse_vc,
6849 	},
6850 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
6851 		.name = "ethdev_port_id",
6852 		.help = "ethdev port ID",
6853 		.next = NEXT(action_represented_port,
6854 			     NEXT_ENTRY(COMMON_UNSIGNED)),
6855 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
6856 					port_id)),
6857 		.call = parse_vc_conf,
6858 	},
6859 	/* Indirect action destroy arguments. */
6860 	[INDIRECT_ACTION_DESTROY_ID] = {
6861 		.name = "action_id",
6862 		.help = "specify a indirect action id to destroy",
6863 		.next = NEXT(next_ia_destroy_attr,
6864 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6865 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
6866 					    args.ia_destroy.action_id)),
6867 		.call = parse_ia_destroy,
6868 	},
6869 	/* Indirect action create arguments. */
6870 	[INDIRECT_ACTION_CREATE_ID] = {
6871 		.name = "action_id",
6872 		.help = "specify a indirect action id to create",
6873 		.next = NEXT(next_ia_create_attr,
6874 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
6875 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
6876 	},
6877 	[ACTION_INDIRECT] = {
6878 		.name = "indirect",
6879 		.help = "apply indirect action by id",
6880 		.priv = PRIV_ACTION(INDIRECT, 0),
6881 		.next = NEXT(next_ia),
6882 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6883 		.call = parse_vc,
6884 	},
6885 	[ACTION_INDIRECT_LIST] = {
6886 		.name = "indirect_list",
6887 		.help = "apply indirect list action by id",
6888 		.priv = PRIV_ACTION(INDIRECT_LIST,
6889 				    sizeof(struct
6890 					   rte_flow_action_indirect_list)),
6891 		.next = NEXT(next_ial),
6892 		.call = parse_vc,
6893 	},
6894 	[ACTION_INDIRECT_LIST_HANDLE] = {
6895 		.name = "handle",
6896 		.help = "indirect list handle",
6897 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
6898 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
6899 	},
6900 	[ACTION_INDIRECT_LIST_CONF] = {
6901 		.name = "conf",
6902 		.help = "indirect list configuration",
6903 		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
6904 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
6905 	},
6906 	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
6907 		.type = "UNSIGNED",
6908 		.help = "unsigned integer value",
6909 		.call = parse_indlst_id2ptr,
6910 	},
6911 	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
6912 		.type = "UNSIGNED",
6913 		.help = "unsigned integer value",
6914 		.call = parse_indlst_id2ptr,
6915 	},
6916 	[ACTION_SHARED_INDIRECT] = {
6917 		.name = "shared_indirect",
6918 		.help = "apply indirect action by id and port",
6919 		.priv = PRIV_ACTION(INDIRECT, 0),
6920 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)),
6921 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)),
6922 			     ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
6923 		.call = parse_vc,
6924 	},
6925 	[INDIRECT_ACTION_PORT] = {
6926 		.name = "{indirect_action_port}",
6927 		.type = "INDIRECT_ACTION_PORT",
6928 		.help = "indirect action port",
6929 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
6930 		.call = parse_ia_port,
6931 		.comp = comp_none,
6932 	},
6933 	[INDIRECT_ACTION_ID2PTR] = {
6934 		.name = "{action_id}",
6935 		.type = "INDIRECT_ACTION_ID",
6936 		.help = "indirect action id",
6937 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
6938 		.call = parse_ia_id2ptr,
6939 		.comp = comp_none,
6940 	},
6941 	[INDIRECT_ACTION_INGRESS] = {
6942 		.name = "ingress",
6943 		.help = "affect rule to ingress",
6944 		.next = NEXT(next_ia_create_attr),
6945 		.call = parse_ia,
6946 	},
6947 	[INDIRECT_ACTION_EGRESS] = {
6948 		.name = "egress",
6949 		.help = "affect rule to egress",
6950 		.next = NEXT(next_ia_create_attr),
6951 		.call = parse_ia,
6952 	},
6953 	[INDIRECT_ACTION_TRANSFER] = {
6954 		.name = "transfer",
6955 		.help = "affect rule to transfer",
6956 		.next = NEXT(next_ia_create_attr),
6957 		.call = parse_ia,
6958 	},
6959 	[INDIRECT_ACTION_SPEC] = {
6960 		.name = "action",
6961 		.help = "specify action to create indirect handle",
6962 		.next = NEXT(next_action),
6963 	},
6964 	[INDIRECT_ACTION_LIST] = {
6965 		.name = "list",
6966 		.help = "specify actions for indirect handle list",
6967 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
6968 		.call = parse_ia,
6969 	},
6970 	[INDIRECT_ACTION_FLOW_CONF] = {
6971 		.name = "flow_conf",
6972 		.help = "specify actions configuration for indirect handle list",
6973 		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
6974 		.call = parse_ia,
6975 	},
6976 	[ACTION_POL_G] = {
6977 		.name = "g_actions",
6978 		.help = "submit a list of associated actions for green",
6979 		.next = NEXT(next_action),
6980 		.call = parse_mp,
6981 	},
6982 	[ACTION_POL_Y] = {
6983 		.name = "y_actions",
6984 		.help = "submit a list of associated actions for yellow",
6985 		.next = NEXT(next_action),
6986 	},
6987 	[ACTION_POL_R] = {
6988 		.name = "r_actions",
6989 		.help = "submit a list of associated actions for red",
6990 		.next = NEXT(next_action),
6991 	},
6992 	[ACTION_QUOTA_CREATE] = {
6993 		.name = "quota_create",
6994 		.help = "create quota action",
6995 		.priv = PRIV_ACTION(QUOTA,
6996 				    sizeof(struct rte_flow_action_quota)),
6997 		.next = NEXT(action_quota_create),
6998 		.call = parse_vc
6999 	},
7000 	[ACTION_QUOTA_CREATE_LIMIT] = {
7001 		.name = "limit",
7002 		.help = "quota limit",
7003 		.next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
7004 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
7005 		.call = parse_vc_conf
7006 	},
7007 	[ACTION_QUOTA_CREATE_MODE] = {
7008 		.name = "mode",
7009 		.help = "quota mode",
7010 		.next = NEXT(action_quota_create,
7011 			     NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
7012 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
7013 		.call = parse_vc_conf
7014 	},
7015 	[ACTION_QUOTA_CREATE_MODE_NAME] = {
7016 		.name = "mode_name",
7017 		.help = "quota mode name",
7018 		.call = parse_quota_mode_name,
7019 		.comp = comp_quota_mode_name
7020 	},
7021 	[ACTION_QUOTA_QU] = {
7022 		.name = "quota_update",
7023 		.help = "update quota action",
7024 		.priv = PRIV_ACTION(QUOTA,
7025 				    sizeof(struct rte_flow_update_quota)),
7026 		.next = NEXT(action_quota_update),
7027 		.call = parse_vc
7028 	},
7029 	[ACTION_QUOTA_QU_LIMIT] = {
7030 		.name = "limit",
7031 		.help = "quota limit",
7032 		.next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
7033 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
7034 		.call = parse_vc_conf
7035 	},
7036 	[ACTION_QUOTA_QU_UPDATE_OP] = {
7037 		.name = "update_op",
7038 		.help = "query update op SET|ADD",
7039 		.next = NEXT(action_quota_update,
7040 			     NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
7041 		.args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
7042 		.call = parse_vc_conf
7043 	},
7044 	[ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
7045 		.name = "update_op_name",
7046 		.help = "quota update op name",
7047 		.call = parse_quota_update_name,
7048 		.comp = comp_quota_update_name
7049 	},
7050 
7051 	/* Top-level command. */
7052 	[ADD] = {
7053 		.name = "add",
7054 		.type = "port meter policy {port_id} {arg}",
7055 		.help = "add port meter policy",
7056 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
7057 		.call = parse_init,
7058 	},
7059 	/* Sub-level commands. */
7060 	[ITEM_POL_PORT] = {
7061 		.name = "port",
7062 		.help = "add port meter policy",
7063 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
7064 	},
7065 	[ITEM_POL_METER] = {
7066 		.name = "meter",
7067 		.help = "add port meter policy",
7068 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
7069 	},
7070 	[ITEM_POL_POLICY] = {
7071 		.name = "policy",
7072 		.help = "add port meter policy",
7073 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
7074 				NEXT_ENTRY(ACTION_POL_Y),
7075 				NEXT_ENTRY(ACTION_POL_G),
7076 				NEXT_ENTRY(COMMON_POLICY_ID),
7077 				NEXT_ENTRY(COMMON_PORT_ID)),
7078 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
7079 				ARGS_ENTRY(struct buffer, port)),
7080 		.call = parse_mp,
7081 	},
7082 	[ITEM_AGGR_AFFINITY] = {
7083 		.name = "aggr_affinity",
7084 		.help = "match on the aggregated port receiving the packets",
7085 		.priv = PRIV_ITEM(AGGR_AFFINITY,
7086 				  sizeof(struct rte_flow_item_aggr_affinity)),
7087 		.next = NEXT(item_aggr_affinity),
7088 		.call = parse_vc,
7089 	},
7090 	[ITEM_AGGR_AFFINITY_VALUE] = {
7091 		.name = "affinity",
7092 		.help = "aggregated affinity value",
7093 		.next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED),
7094 			     item_param),
7095 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity,
7096 					affinity)),
7097 	},
7098 	[ITEM_TX_QUEUE] = {
7099 		.name = "tx_queue",
7100 		.help = "match on the tx queue of send packet",
7101 		.priv = PRIV_ITEM(TX_QUEUE,
7102 				  sizeof(struct rte_flow_item_tx_queue)),
7103 		.next = NEXT(item_tx_queue),
7104 		.call = parse_vc,
7105 	},
7106 	[ITEM_TX_QUEUE_VALUE] = {
7107 		.name = "tx_queue_value",
7108 		.help = "tx queue value",
7109 		.next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED),
7110 			     item_param),
7111 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue,
7112 					tx_queue)),
7113 	},
7114 };
7115 
7116 /** Remove and return last entry from argument stack. */
7117 static const struct arg *
7118 pop_args(struct context *ctx)
7119 {
7120 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
7121 }
7122 
7123 /** Add entry on top of the argument stack. */
7124 static int
7125 push_args(struct context *ctx, const struct arg *arg)
7126 {
7127 	if (ctx->args_num == CTX_STACK_SIZE)
7128 		return -1;
7129 	ctx->args[ctx->args_num++] = arg;
7130 	return 0;
7131 }
7132 
7133 /** Spread value into buffer according to bit-mask. */
7134 static size_t
7135 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
7136 {
7137 	uint32_t i = arg->size;
7138 	uint32_t end = 0;
7139 	int sub = 1;
7140 	int add = 0;
7141 	size_t len = 0;
7142 
7143 	if (!arg->mask)
7144 		return 0;
7145 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7146 	if (!arg->hton) {
7147 		i = 0;
7148 		end = arg->size;
7149 		sub = 0;
7150 		add = 1;
7151 	}
7152 #endif
7153 	while (i != end) {
7154 		unsigned int shift = 0;
7155 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
7156 
7157 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
7158 			if (!(arg->mask[i] & (1 << shift)))
7159 				continue;
7160 			++len;
7161 			if (!dst)
7162 				continue;
7163 			*buf &= ~(1 << shift);
7164 			*buf |= (val & 1) << shift;
7165 			val >>= 1;
7166 		}
7167 		i += add;
7168 	}
7169 	return len;
7170 }
7171 
7172 /** Compare a string with a partial one of a given length. */
7173 static int
7174 strcmp_partial(const char *full, const char *partial, size_t partial_len)
7175 {
7176 	int r = strncmp(full, partial, partial_len);
7177 
7178 	if (r)
7179 		return r;
7180 	if (strlen(full) <= partial_len)
7181 		return 0;
7182 	return full[partial_len];
7183 }
7184 
7185 /**
7186  * Parse a prefix length and generate a bit-mask.
7187  *
7188  * Last argument (ctx->args) is retrieved to determine mask size, storage
7189  * location and whether the result must use network byte ordering.
7190  */
7191 static int
7192 parse_prefix(struct context *ctx, const struct token *token,
7193 	     const char *str, unsigned int len,
7194 	     void *buf, unsigned int size)
7195 {
7196 	const struct arg *arg = pop_args(ctx);
7197 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
7198 	char *end;
7199 	uintmax_t u;
7200 	unsigned int bytes;
7201 	unsigned int extra;
7202 
7203 	(void)token;
7204 	/* Argument is expected. */
7205 	if (!arg)
7206 		return -1;
7207 	errno = 0;
7208 	u = strtoumax(str, &end, 0);
7209 	if (errno || (size_t)(end - str) != len)
7210 		goto error;
7211 	if (arg->mask) {
7212 		uintmax_t v = 0;
7213 
7214 		extra = arg_entry_bf_fill(NULL, 0, arg);
7215 		if (u > extra)
7216 			goto error;
7217 		if (!ctx->object)
7218 			return len;
7219 		extra -= u;
7220 		while (u--)
7221 			(v <<= 1, v |= 1);
7222 		v <<= extra;
7223 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
7224 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
7225 			goto error;
7226 		return len;
7227 	}
7228 	bytes = u / 8;
7229 	extra = u % 8;
7230 	size = arg->size;
7231 	if (bytes > size || bytes + !!extra > size)
7232 		goto error;
7233 	if (!ctx->object)
7234 		return len;
7235 	buf = (uint8_t *)ctx->object + arg->offset;
7236 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7237 	if (!arg->hton) {
7238 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
7239 		memset(buf, 0x00, size - bytes);
7240 		if (extra)
7241 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
7242 	} else
7243 #endif
7244 	{
7245 		memset(buf, 0xff, bytes);
7246 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
7247 		if (extra)
7248 			((uint8_t *)buf)[bytes] = conv[extra];
7249 	}
7250 	if (ctx->objmask)
7251 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7252 	return len;
7253 error:
7254 	push_args(ctx, arg);
7255 	return -1;
7256 }
7257 
7258 /** Default parsing function for token name matching. */
7259 static int
7260 parse_default(struct context *ctx, const struct token *token,
7261 	      const char *str, unsigned int len,
7262 	      void *buf, unsigned int size)
7263 {
7264 	(void)ctx;
7265 	(void)buf;
7266 	(void)size;
7267 	if (strcmp_partial(token->name, str, len))
7268 		return -1;
7269 	return len;
7270 }
7271 
7272 /** Parse flow command, initialize output buffer for subsequent tokens. */
7273 static int
7274 parse_init(struct context *ctx, const struct token *token,
7275 	   const char *str, unsigned int len,
7276 	   void *buf, unsigned int size)
7277 {
7278 	struct buffer *out = buf;
7279 
7280 	/* Token name must match. */
7281 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7282 		return -1;
7283 	/* Nothing else to do if there is no buffer. */
7284 	if (!out)
7285 		return len;
7286 	/* Make sure buffer is large enough. */
7287 	if (size < sizeof(*out))
7288 		return -1;
7289 	/* Initialize buffer. */
7290 	memset(out, 0x00, sizeof(*out));
7291 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
7292 	ctx->objdata = 0;
7293 	ctx->object = out;
7294 	ctx->objmask = NULL;
7295 	return len;
7296 }
7297 
7298 /** Parse tokens for indirect action commands. */
7299 static int
7300 parse_ia(struct context *ctx, const struct token *token,
7301 	 const char *str, unsigned int len,
7302 	 void *buf, unsigned int size)
7303 {
7304 	struct buffer *out = buf;
7305 
7306 	/* Token name must match. */
7307 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7308 		return -1;
7309 	/* Nothing else to do if there is no buffer. */
7310 	if (!out)
7311 		return len;
7312 	if (!out->command) {
7313 		if (ctx->curr != INDIRECT_ACTION)
7314 			return -1;
7315 		if (sizeof(*out) > size)
7316 			return -1;
7317 		out->command = ctx->curr;
7318 		ctx->objdata = 0;
7319 		ctx->object = out;
7320 		ctx->objmask = NULL;
7321 		out->args.vc.data = (uint8_t *)out + size;
7322 		return len;
7323 	}
7324 	switch (ctx->curr) {
7325 	case INDIRECT_ACTION_CREATE:
7326 	case INDIRECT_ACTION_UPDATE:
7327 	case INDIRECT_ACTION_QUERY_UPDATE:
7328 		out->args.vc.actions =
7329 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7330 					       sizeof(double));
7331 		out->args.vc.attr.group = UINT32_MAX;
7332 		/* fallthrough */
7333 	case INDIRECT_ACTION_QUERY:
7334 		out->command = ctx->curr;
7335 		ctx->objdata = 0;
7336 		ctx->object = out;
7337 		ctx->objmask = NULL;
7338 		return len;
7339 	case INDIRECT_ACTION_EGRESS:
7340 		out->args.vc.attr.egress = 1;
7341 		return len;
7342 	case INDIRECT_ACTION_INGRESS:
7343 		out->args.vc.attr.ingress = 1;
7344 		return len;
7345 	case INDIRECT_ACTION_TRANSFER:
7346 		out->args.vc.attr.transfer = 1;
7347 		return len;
7348 	case INDIRECT_ACTION_QU_MODE:
7349 		return len;
7350 	case INDIRECT_ACTION_LIST:
7351 		out->command = INDIRECT_ACTION_LIST_CREATE;
7352 		return len;
7353 	case INDIRECT_ACTION_FLOW_CONF:
7354 		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
7355 		return len;
7356 	default:
7357 		return -1;
7358 	}
7359 }
7360 
7361 
7362 /** Parse tokens for indirect action destroy command. */
7363 static int
7364 parse_ia_destroy(struct context *ctx, const struct token *token,
7365 		 const char *str, unsigned int len,
7366 		 void *buf, unsigned int size)
7367 {
7368 	struct buffer *out = buf;
7369 	uint32_t *action_id;
7370 
7371 	/* Token name must match. */
7372 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7373 		return -1;
7374 	/* Nothing else to do if there is no buffer. */
7375 	if (!out)
7376 		return len;
7377 	if (!out->command || out->command == INDIRECT_ACTION) {
7378 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
7379 			return -1;
7380 		if (sizeof(*out) > size)
7381 			return -1;
7382 		out->command = ctx->curr;
7383 		ctx->objdata = 0;
7384 		ctx->object = out;
7385 		ctx->objmask = NULL;
7386 		out->args.ia_destroy.action_id =
7387 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7388 					       sizeof(double));
7389 		return len;
7390 	}
7391 	action_id = out->args.ia_destroy.action_id
7392 		    + out->args.ia_destroy.action_id_n++;
7393 	if ((uint8_t *)action_id > (uint8_t *)out + size)
7394 		return -1;
7395 	ctx->objdata = 0;
7396 	ctx->object = action_id;
7397 	ctx->objmask = NULL;
7398 	return len;
7399 }
7400 
7401 /** Parse tokens for indirect action commands. */
7402 static int
7403 parse_qia(struct context *ctx, const struct token *token,
7404 	  const char *str, unsigned int len,
7405 	  void *buf, unsigned int size)
7406 {
7407 	struct buffer *out = buf;
7408 
7409 	/* Token name must match. */
7410 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7411 		return -1;
7412 	/* Nothing else to do if there is no buffer. */
7413 	if (!out)
7414 		return len;
7415 	if (!out->command) {
7416 		if (ctx->curr != QUEUE)
7417 			return -1;
7418 		if (sizeof(*out) > size)
7419 			return -1;
7420 		out->args.vc.data = (uint8_t *)out + size;
7421 		return len;
7422 	}
7423 	switch (ctx->curr) {
7424 	case QUEUE_INDIRECT_ACTION:
7425 		return len;
7426 	case QUEUE_INDIRECT_ACTION_CREATE:
7427 	case QUEUE_INDIRECT_ACTION_UPDATE:
7428 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
7429 		out->args.vc.actions =
7430 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7431 					       sizeof(double));
7432 		out->args.vc.attr.group = UINT32_MAX;
7433 		/* fallthrough */
7434 	case QUEUE_INDIRECT_ACTION_QUERY:
7435 		out->command = ctx->curr;
7436 		ctx->objdata = 0;
7437 		ctx->object = out;
7438 		ctx->objmask = NULL;
7439 		return len;
7440 	case QUEUE_INDIRECT_ACTION_EGRESS:
7441 		out->args.vc.attr.egress = 1;
7442 		return len;
7443 	case QUEUE_INDIRECT_ACTION_INGRESS:
7444 		out->args.vc.attr.ingress = 1;
7445 		return len;
7446 	case QUEUE_INDIRECT_ACTION_TRANSFER:
7447 		out->args.vc.attr.transfer = 1;
7448 		return len;
7449 	case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
7450 		return len;
7451 	case QUEUE_INDIRECT_ACTION_QU_MODE:
7452 		return len;
7453 	case QUEUE_INDIRECT_ACTION_LIST:
7454 		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
7455 		return len;
7456 	default:
7457 		return -1;
7458 	}
7459 }
7460 
7461 /** Parse tokens for indirect action destroy command. */
7462 static int
7463 parse_qia_destroy(struct context *ctx, const struct token *token,
7464 		  const char *str, unsigned int len,
7465 		  void *buf, unsigned int size)
7466 {
7467 	struct buffer *out = buf;
7468 	uint32_t *action_id;
7469 
7470 	/* Token name must match. */
7471 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7472 		return -1;
7473 	/* Nothing else to do if there is no buffer. */
7474 	if (!out)
7475 		return len;
7476 	if (!out->command || out->command == QUEUE) {
7477 		if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
7478 			return -1;
7479 		if (sizeof(*out) > size)
7480 			return -1;
7481 		out->command = ctx->curr;
7482 		ctx->objdata = 0;
7483 		ctx->object = out;
7484 		ctx->objmask = NULL;
7485 		out->args.ia_destroy.action_id =
7486 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7487 					       sizeof(double));
7488 		return len;
7489 	}
7490 	switch (ctx->curr) {
7491 	case QUEUE_INDIRECT_ACTION:
7492 		out->command = ctx->curr;
7493 		ctx->objdata = 0;
7494 		ctx->object = out;
7495 		ctx->objmask = NULL;
7496 		return len;
7497 	case QUEUE_INDIRECT_ACTION_DESTROY_ID:
7498 		action_id = out->args.ia_destroy.action_id
7499 				+ out->args.ia_destroy.action_id_n++;
7500 		if ((uint8_t *)action_id > (uint8_t *)out + size)
7501 			return -1;
7502 		ctx->objdata = 0;
7503 		ctx->object = action_id;
7504 		ctx->objmask = NULL;
7505 		return len;
7506 	case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE:
7507 		return len;
7508 	default:
7509 		return -1;
7510 	}
7511 }
7512 
7513 /** Parse tokens for meter policy action commands. */
7514 static int
7515 parse_mp(struct context *ctx, const struct token *token,
7516 	const char *str, unsigned int len,
7517 	void *buf, unsigned int size)
7518 {
7519 	struct buffer *out = buf;
7520 
7521 	/* Token name must match. */
7522 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7523 		return -1;
7524 	/* Nothing else to do if there is no buffer. */
7525 	if (!out)
7526 		return len;
7527 	if (!out->command) {
7528 		if (ctx->curr != ITEM_POL_POLICY)
7529 			return -1;
7530 		if (sizeof(*out) > size)
7531 			return -1;
7532 		out->command = ctx->curr;
7533 		ctx->objdata = 0;
7534 		ctx->object = out;
7535 		ctx->objmask = NULL;
7536 		out->args.vc.data = (uint8_t *)out + size;
7537 		return len;
7538 	}
7539 	switch (ctx->curr) {
7540 	case ACTION_POL_G:
7541 		out->args.vc.actions =
7542 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7543 					sizeof(double));
7544 		out->command = ctx->curr;
7545 		ctx->objdata = 0;
7546 		ctx->object = out;
7547 		ctx->objmask = NULL;
7548 		return len;
7549 	default:
7550 		return -1;
7551 	}
7552 }
7553 
7554 /** Parse tokens for validate/create commands. */
7555 static int
7556 parse_vc(struct context *ctx, const struct token *token,
7557 	 const char *str, unsigned int len,
7558 	 void *buf, unsigned int size)
7559 {
7560 	struct buffer *out = buf;
7561 	uint8_t *data;
7562 	uint32_t data_size;
7563 
7564 	/* Token name must match. */
7565 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7566 		return -1;
7567 	/* Nothing else to do if there is no buffer. */
7568 	if (!out)
7569 		return len;
7570 	if (!out->command) {
7571 		if (ctx->curr != VALIDATE && ctx->curr != CREATE &&
7572 		    ctx->curr != PATTERN_TEMPLATE_CREATE &&
7573 		    ctx->curr != ACTIONS_TEMPLATE_CREATE)
7574 			return -1;
7575 		if (sizeof(*out) > size)
7576 			return -1;
7577 		out->command = ctx->curr;
7578 		ctx->objdata = 0;
7579 		ctx->object = out;
7580 		ctx->objmask = NULL;
7581 		out->args.vc.data = (uint8_t *)out + size;
7582 		return len;
7583 	}
7584 	ctx->objdata = 0;
7585 	switch (ctx->curr) {
7586 	default:
7587 		ctx->object = &out->args.vc.attr;
7588 		break;
7589 	case VC_TUNNEL_SET:
7590 	case VC_TUNNEL_MATCH:
7591 		ctx->object = &out->args.vc.tunnel_ops;
7592 		break;
7593 	}
7594 	ctx->objmask = NULL;
7595 	switch (ctx->curr) {
7596 	case VC_GROUP:
7597 	case VC_PRIORITY:
7598 		return len;
7599 	case VC_TUNNEL_SET:
7600 		out->args.vc.tunnel_ops.enabled = 1;
7601 		out->args.vc.tunnel_ops.actions = 1;
7602 		return len;
7603 	case VC_TUNNEL_MATCH:
7604 		out->args.vc.tunnel_ops.enabled = 1;
7605 		out->args.vc.tunnel_ops.items = 1;
7606 		return len;
7607 	case VC_INGRESS:
7608 		out->args.vc.attr.ingress = 1;
7609 		return len;
7610 	case VC_EGRESS:
7611 		out->args.vc.attr.egress = 1;
7612 		return len;
7613 	case VC_TRANSFER:
7614 		out->args.vc.attr.transfer = 1;
7615 		return len;
7616 	case ITEM_PATTERN:
7617 		out->args.vc.pattern =
7618 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7619 					       sizeof(double));
7620 		ctx->object = out->args.vc.pattern;
7621 		ctx->objmask = NULL;
7622 		return len;
7623 	case ITEM_END:
7624 		if ((out->command == VALIDATE || out->command == CREATE) &&
7625 		    ctx->last)
7626 			return -1;
7627 		if (out->command == PATTERN_TEMPLATE_CREATE &&
7628 		    !ctx->last)
7629 			return -1;
7630 		break;
7631 	case ACTIONS:
7632 		out->args.vc.actions = out->args.vc.pattern ?
7633 			(void *)RTE_ALIGN_CEIL((uintptr_t)
7634 					       (out->args.vc.pattern +
7635 						out->args.vc.pattern_n),
7636 					       sizeof(double)) :
7637 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7638 					       sizeof(double));
7639 		ctx->object = out->args.vc.actions;
7640 		ctx->objmask = NULL;
7641 		return len;
7642 	default:
7643 		if (!token->priv)
7644 			return -1;
7645 		break;
7646 	}
7647 	if (!out->args.vc.actions) {
7648 		const struct parse_item_priv *priv = token->priv;
7649 		struct rte_flow_item *item =
7650 			out->args.vc.pattern + out->args.vc.pattern_n;
7651 
7652 		data_size = priv->size * 3; /* spec, last, mask */
7653 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
7654 					       (out->args.vc.data - data_size),
7655 					       sizeof(double));
7656 		if ((uint8_t *)item + sizeof(*item) > data)
7657 			return -1;
7658 		*item = (struct rte_flow_item){
7659 			.type = priv->type,
7660 		};
7661 		++out->args.vc.pattern_n;
7662 		ctx->object = item;
7663 		ctx->objmask = NULL;
7664 	} else {
7665 		const struct parse_action_priv *priv = token->priv;
7666 		struct rte_flow_action *action =
7667 			out->args.vc.actions + out->args.vc.actions_n;
7668 
7669 		data_size = priv->size; /* configuration */
7670 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
7671 					       (out->args.vc.data - data_size),
7672 					       sizeof(double));
7673 		if ((uint8_t *)action + sizeof(*action) > data)
7674 			return -1;
7675 		*action = (struct rte_flow_action){
7676 			.type = priv->type,
7677 			.conf = data_size ? data : NULL,
7678 		};
7679 		++out->args.vc.actions_n;
7680 		ctx->object = action;
7681 		ctx->objmask = NULL;
7682 	}
7683 	memset(data, 0, data_size);
7684 	out->args.vc.data = data;
7685 	ctx->objdata = data_size;
7686 	return len;
7687 }
7688 
7689 /** Parse pattern item parameter type. */
7690 static int
7691 parse_vc_spec(struct context *ctx, const struct token *token,
7692 	      const char *str, unsigned int len,
7693 	      void *buf, unsigned int size)
7694 {
7695 	struct buffer *out = buf;
7696 	struct rte_flow_item *item;
7697 	uint32_t data_size;
7698 	int index;
7699 	int objmask = 0;
7700 
7701 	(void)size;
7702 	/* Token name must match. */
7703 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7704 		return -1;
7705 	/* Parse parameter types. */
7706 	switch (ctx->curr) {
7707 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
7708 
7709 	case ITEM_PARAM_IS:
7710 		index = 0;
7711 		objmask = 1;
7712 		break;
7713 	case ITEM_PARAM_SPEC:
7714 		index = 0;
7715 		break;
7716 	case ITEM_PARAM_LAST:
7717 		index = 1;
7718 		break;
7719 	case ITEM_PARAM_PREFIX:
7720 		/* Modify next token to expect a prefix. */
7721 		if (ctx->next_num < 2)
7722 			return -1;
7723 		ctx->next[ctx->next_num - 2] = prefix;
7724 		/* Fall through. */
7725 	case ITEM_PARAM_MASK:
7726 		index = 2;
7727 		break;
7728 	default:
7729 		return -1;
7730 	}
7731 	/* Nothing else to do if there is no buffer. */
7732 	if (!out)
7733 		return len;
7734 	if (!out->args.vc.pattern_n)
7735 		return -1;
7736 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7737 	data_size = ctx->objdata / 3; /* spec, last, mask */
7738 	/* Point to selected object. */
7739 	ctx->object = out->args.vc.data + (data_size * index);
7740 	if (objmask) {
7741 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
7742 		item->mask = ctx->objmask;
7743 	} else
7744 		ctx->objmask = NULL;
7745 	/* Update relevant item pointer. */
7746 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
7747 		ctx->object;
7748 	return len;
7749 }
7750 
7751 /** Parse action configuration field. */
7752 static int
7753 parse_vc_conf(struct context *ctx, const struct token *token,
7754 	      const char *str, unsigned int len,
7755 	      void *buf, unsigned int size)
7756 {
7757 	struct buffer *out = buf;
7758 
7759 	(void)size;
7760 	/* Token name must match. */
7761 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7762 		return -1;
7763 	/* Nothing else to do if there is no buffer. */
7764 	if (!out)
7765 		return len;
7766 	/* Point to selected object. */
7767 	ctx->object = out->args.vc.data;
7768 	ctx->objmask = NULL;
7769 	return len;
7770 }
7771 
7772 /** Parse action configuration field. */
7773 static int
7774 parse_vc_conf_timeout(struct context *ctx, const struct token *token,
7775 		      const char *str, unsigned int len,
7776 		      void *buf, unsigned int size)
7777 {
7778 	struct buffer *out = buf;
7779 	struct rte_flow_update_age *update;
7780 
7781 	(void)size;
7782 	if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT)
7783 		return -1;
7784 	/* Token name must match. */
7785 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7786 		return -1;
7787 	/* Nothing else to do if there is no buffer. */
7788 	if (!out)
7789 		return len;
7790 	/* Point to selected object. */
7791 	ctx->object = out->args.vc.data;
7792 	ctx->objmask = NULL;
7793 	/* Update the timeout is valid. */
7794 	update = (struct rte_flow_update_age *)out->args.vc.data;
7795 	update->timeout_valid = 1;
7796 	return len;
7797 }
7798 
7799 /** Parse eCPRI common header type field. */
7800 static int
7801 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
7802 			 const char *str, unsigned int len,
7803 			 void *buf, unsigned int size)
7804 {
7805 	struct rte_flow_item_ecpri *ecpri;
7806 	struct rte_flow_item_ecpri *ecpri_mask;
7807 	struct rte_flow_item *item;
7808 	uint32_t data_size;
7809 	uint8_t msg_type;
7810 	struct buffer *out = buf;
7811 	const struct arg *arg;
7812 
7813 	(void)size;
7814 	/* Token name must match. */
7815 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7816 		return -1;
7817 	switch (ctx->curr) {
7818 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
7819 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
7820 		break;
7821 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
7822 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
7823 		break;
7824 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
7825 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
7826 		break;
7827 	default:
7828 		return -1;
7829 	}
7830 	if (!ctx->object)
7831 		return len;
7832 	arg = pop_args(ctx);
7833 	if (!arg)
7834 		return -1;
7835 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
7836 	ecpri->hdr.common.type = msg_type;
7837 	data_size = ctx->objdata / 3; /* spec, last, mask */
7838 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
7839 						    (data_size * 2));
7840 	ecpri_mask->hdr.common.type = 0xFF;
7841 	if (arg->hton) {
7842 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
7843 		ecpri_mask->hdr.common.u32 =
7844 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
7845 	}
7846 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7847 	item->spec = ecpri;
7848 	item->mask = ecpri_mask;
7849 	return len;
7850 }
7851 
7852 /** Parse L2TPv2 common header type field. */
7853 static int
7854 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token,
7855 			 const char *str, unsigned int len,
7856 			 void *buf, unsigned int size)
7857 {
7858 	struct rte_flow_item_l2tpv2 *l2tpv2;
7859 	struct rte_flow_item_l2tpv2 *l2tpv2_mask;
7860 	struct rte_flow_item *item;
7861 	uint32_t data_size;
7862 	uint16_t msg_type = 0;
7863 	struct buffer *out = buf;
7864 	const struct arg *arg;
7865 
7866 	(void)size;
7867 	/* Token name must match. */
7868 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7869 		return -1;
7870 	switch (ctx->curr) {
7871 	case ITEM_L2TPV2_TYPE_DATA:
7872 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA;
7873 		break;
7874 	case ITEM_L2TPV2_TYPE_DATA_L:
7875 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L;
7876 		break;
7877 	case ITEM_L2TPV2_TYPE_DATA_S:
7878 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S;
7879 		break;
7880 	case ITEM_L2TPV2_TYPE_DATA_O:
7881 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O;
7882 		break;
7883 	case ITEM_L2TPV2_TYPE_DATA_L_S:
7884 		msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S;
7885 		break;
7886 	case ITEM_L2TPV2_TYPE_CTRL:
7887 		msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL;
7888 		break;
7889 	default:
7890 		return -1;
7891 	}
7892 	if (!ctx->object)
7893 		return len;
7894 	arg = pop_args(ctx);
7895 	if (!arg)
7896 		return -1;
7897 	l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data;
7898 	l2tpv2->hdr.common.flags_version |= msg_type;
7899 	data_size = ctx->objdata / 3; /* spec, last, mask */
7900 	l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data +
7901 						    (data_size * 2));
7902 	l2tpv2_mask->hdr.common.flags_version = 0xFFFF;
7903 	if (arg->hton) {
7904 		l2tpv2->hdr.common.flags_version =
7905 			rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version);
7906 		l2tpv2_mask->hdr.common.flags_version =
7907 		    rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version);
7908 	}
7909 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
7910 	item->spec = l2tpv2;
7911 	item->mask = l2tpv2_mask;
7912 	return len;
7913 }
7914 
7915 /** Parse meter color action type. */
7916 static int
7917 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
7918 				const char *str, unsigned int len,
7919 				void *buf, unsigned int size)
7920 {
7921 	struct rte_flow_action *action_data;
7922 	struct rte_flow_action_meter_color *conf;
7923 	enum rte_color color;
7924 
7925 	(void)buf;
7926 	(void)size;
7927 	/* Token name must match. */
7928 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7929 		return -1;
7930 	switch (ctx->curr) {
7931 	case ACTION_METER_COLOR_GREEN:
7932 		color = RTE_COLOR_GREEN;
7933 	break;
7934 	case ACTION_METER_COLOR_YELLOW:
7935 		color = RTE_COLOR_YELLOW;
7936 	break;
7937 	case ACTION_METER_COLOR_RED:
7938 		color = RTE_COLOR_RED;
7939 	break;
7940 	default:
7941 		return -1;
7942 	}
7943 
7944 	if (!ctx->object)
7945 		return len;
7946 	action_data = ctx->object;
7947 	conf = (struct rte_flow_action_meter_color *)
7948 					(uintptr_t)(action_data->conf);
7949 	conf->color = color;
7950 	return len;
7951 }
7952 
7953 /** Parse RSS action. */
7954 static int
7955 parse_vc_action_rss(struct context *ctx, const struct token *token,
7956 		    const char *str, unsigned int len,
7957 		    void *buf, unsigned int size)
7958 {
7959 	struct buffer *out = buf;
7960 	struct rte_flow_action *action;
7961 	struct action_rss_data *action_rss_data;
7962 	unsigned int i;
7963 	int ret;
7964 
7965 	ret = parse_vc(ctx, token, str, len, buf, size);
7966 	if (ret < 0)
7967 		return ret;
7968 	/* Nothing else to do if there is no buffer. */
7969 	if (!out)
7970 		return ret;
7971 	if (!out->args.vc.actions_n)
7972 		return -1;
7973 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
7974 	/* Point to selected object. */
7975 	ctx->object = out->args.vc.data;
7976 	ctx->objmask = NULL;
7977 	/* Set up default configuration. */
7978 	action_rss_data = ctx->object;
7979 	*action_rss_data = (struct action_rss_data){
7980 		.conf = (struct rte_flow_action_rss){
7981 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
7982 			.level = 0,
7983 			.types = rss_hf,
7984 			.key_len = 0,
7985 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
7986 			.key = NULL,
7987 			.queue = action_rss_data->queue,
7988 		},
7989 		.queue = { 0 },
7990 	};
7991 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
7992 		action_rss_data->queue[i] = i;
7993 	action->conf = &action_rss_data->conf;
7994 	return ret;
7995 }
7996 
7997 /**
7998  * Parse func field for RSS action.
7999  *
8000  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
8001  * ACTION_RSS_FUNC_* index that called this function.
8002  */
8003 static int
8004 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
8005 			 const char *str, unsigned int len,
8006 			 void *buf, unsigned int size)
8007 {
8008 	struct action_rss_data *action_rss_data;
8009 	enum rte_eth_hash_function func;
8010 
8011 	(void)buf;
8012 	(void)size;
8013 	/* Token name must match. */
8014 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
8015 		return -1;
8016 	switch (ctx->curr) {
8017 	case ACTION_RSS_FUNC_DEFAULT:
8018 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
8019 		break;
8020 	case ACTION_RSS_FUNC_TOEPLITZ:
8021 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
8022 		break;
8023 	case ACTION_RSS_FUNC_SIMPLE_XOR:
8024 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
8025 		break;
8026 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
8027 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
8028 		break;
8029 	default:
8030 		return -1;
8031 	}
8032 	if (!ctx->object)
8033 		return len;
8034 	action_rss_data = ctx->object;
8035 	action_rss_data->conf.func = func;
8036 	return len;
8037 }
8038 
8039 /**
8040  * Parse type field for RSS action.
8041  *
8042  * Valid tokens are type field names and the "end" token.
8043  */
8044 static int
8045 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
8046 			  const char *str, unsigned int len,
8047 			  void *buf, unsigned int size)
8048 {
8049 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
8050 	struct action_rss_data *action_rss_data;
8051 	unsigned int i;
8052 
8053 	(void)token;
8054 	(void)buf;
8055 	(void)size;
8056 	if (ctx->curr != ACTION_RSS_TYPE)
8057 		return -1;
8058 	if (!(ctx->objdata >> 16) && ctx->object) {
8059 		action_rss_data = ctx->object;
8060 		action_rss_data->conf.types = 0;
8061 	}
8062 	if (!strcmp_partial("end", str, len)) {
8063 		ctx->objdata &= 0xffff;
8064 		return len;
8065 	}
8066 	for (i = 0; rss_type_table[i].str; ++i)
8067 		if (!strcmp_partial(rss_type_table[i].str, str, len))
8068 			break;
8069 	if (!rss_type_table[i].str)
8070 		return -1;
8071 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
8072 	/* Repeat token. */
8073 	if (ctx->next_num == RTE_DIM(ctx->next))
8074 		return -1;
8075 	ctx->next[ctx->next_num++] = next;
8076 	if (!ctx->object)
8077 		return len;
8078 	action_rss_data = ctx->object;
8079 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
8080 	return len;
8081 }
8082 
8083 /**
8084  * Parse queue field for RSS action.
8085  *
8086  * Valid tokens are queue indices and the "end" token.
8087  */
8088 static int
8089 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
8090 			  const char *str, unsigned int len,
8091 			  void *buf, unsigned int size)
8092 {
8093 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
8094 	struct action_rss_data *action_rss_data;
8095 	const struct arg *arg;
8096 	int ret;
8097 	int i;
8098 
8099 	(void)token;
8100 	(void)buf;
8101 	(void)size;
8102 	if (ctx->curr != ACTION_RSS_QUEUE)
8103 		return -1;
8104 	i = ctx->objdata >> 16;
8105 	if (!strcmp_partial("end", str, len)) {
8106 		ctx->objdata &= 0xffff;
8107 		goto end;
8108 	}
8109 	if (i >= ACTION_RSS_QUEUE_NUM)
8110 		return -1;
8111 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
8112 			     i * sizeof(action_rss_data->queue[i]),
8113 			     sizeof(action_rss_data->queue[i]));
8114 	if (push_args(ctx, arg))
8115 		return -1;
8116 	ret = parse_int(ctx, token, str, len, NULL, 0);
8117 	if (ret < 0) {
8118 		pop_args(ctx);
8119 		return -1;
8120 	}
8121 	++i;
8122 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
8123 	/* Repeat token. */
8124 	if (ctx->next_num == RTE_DIM(ctx->next))
8125 		return -1;
8126 	ctx->next[ctx->next_num++] = next;
8127 end:
8128 	if (!ctx->object)
8129 		return len;
8130 	action_rss_data = ctx->object;
8131 	action_rss_data->conf.queue_num = i;
8132 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
8133 	return len;
8134 }
8135 
8136 /** Setup VXLAN encap configuration. */
8137 static int
8138 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
8139 {
8140 	/* Set up default configuration. */
8141 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
8142 		.conf = (struct rte_flow_action_vxlan_encap){
8143 			.definition = action_vxlan_encap_data->items,
8144 		},
8145 		.items = {
8146 			{
8147 				.type = RTE_FLOW_ITEM_TYPE_ETH,
8148 				.spec = &action_vxlan_encap_data->item_eth,
8149 				.mask = &rte_flow_item_eth_mask,
8150 			},
8151 			{
8152 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
8153 				.spec = &action_vxlan_encap_data->item_vlan,
8154 				.mask = &rte_flow_item_vlan_mask,
8155 			},
8156 			{
8157 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
8158 				.spec = &action_vxlan_encap_data->item_ipv4,
8159 				.mask = &rte_flow_item_ipv4_mask,
8160 			},
8161 			{
8162 				.type = RTE_FLOW_ITEM_TYPE_UDP,
8163 				.spec = &action_vxlan_encap_data->item_udp,
8164 				.mask = &rte_flow_item_udp_mask,
8165 			},
8166 			{
8167 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
8168 				.spec = &action_vxlan_encap_data->item_vxlan,
8169 				.mask = &rte_flow_item_vxlan_mask,
8170 			},
8171 			{
8172 				.type = RTE_FLOW_ITEM_TYPE_END,
8173 			},
8174 		},
8175 		.item_eth.hdr.ether_type = 0,
8176 		.item_vlan = {
8177 			.hdr.vlan_tci = vxlan_encap_conf.vlan_tci,
8178 			.hdr.eth_proto = 0,
8179 		},
8180 		.item_ipv4.hdr = {
8181 			.src_addr = vxlan_encap_conf.ipv4_src,
8182 			.dst_addr = vxlan_encap_conf.ipv4_dst,
8183 		},
8184 		.item_udp.hdr = {
8185 			.src_port = vxlan_encap_conf.udp_src,
8186 			.dst_port = vxlan_encap_conf.udp_dst,
8187 		},
8188 		.item_vxlan.hdr.flags = 0,
8189 	};
8190 	memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes,
8191 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8192 	memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes,
8193 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8194 	if (!vxlan_encap_conf.select_ipv4) {
8195 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
8196 		       &vxlan_encap_conf.ipv6_src,
8197 		       sizeof(vxlan_encap_conf.ipv6_src));
8198 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
8199 		       &vxlan_encap_conf.ipv6_dst,
8200 		       sizeof(vxlan_encap_conf.ipv6_dst));
8201 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
8202 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
8203 			.spec = &action_vxlan_encap_data->item_ipv6,
8204 			.mask = &rte_flow_item_ipv6_mask,
8205 		};
8206 	}
8207 	if (!vxlan_encap_conf.select_vlan)
8208 		action_vxlan_encap_data->items[1].type =
8209 			RTE_FLOW_ITEM_TYPE_VOID;
8210 	if (vxlan_encap_conf.select_tos_ttl) {
8211 		if (vxlan_encap_conf.select_ipv4) {
8212 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
8213 
8214 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
8215 			       sizeof(ipv4_mask_tos));
8216 			ipv4_mask_tos.hdr.type_of_service = 0xff;
8217 			ipv4_mask_tos.hdr.time_to_live = 0xff;
8218 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
8219 					vxlan_encap_conf.ip_tos;
8220 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
8221 					vxlan_encap_conf.ip_ttl;
8222 			action_vxlan_encap_data->items[2].mask =
8223 							&ipv4_mask_tos;
8224 		} else {
8225 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
8226 
8227 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
8228 			       sizeof(ipv6_mask_tos));
8229 			ipv6_mask_tos.hdr.vtc_flow |=
8230 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
8231 			ipv6_mask_tos.hdr.hop_limits = 0xff;
8232 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
8233 				rte_cpu_to_be_32
8234 					((uint32_t)vxlan_encap_conf.ip_tos <<
8235 					 RTE_IPV6_HDR_TC_SHIFT);
8236 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
8237 					vxlan_encap_conf.ip_ttl;
8238 			action_vxlan_encap_data->items[2].mask =
8239 							&ipv6_mask_tos;
8240 		}
8241 	}
8242 	memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni,
8243 	       RTE_DIM(vxlan_encap_conf.vni));
8244 	return 0;
8245 }
8246 
8247 /** Parse VXLAN encap action. */
8248 static int
8249 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
8250 			    const char *str, unsigned int len,
8251 			    void *buf, unsigned int size)
8252 {
8253 	struct buffer *out = buf;
8254 	struct rte_flow_action *action;
8255 	struct action_vxlan_encap_data *action_vxlan_encap_data;
8256 	int ret;
8257 
8258 	ret = parse_vc(ctx, token, str, len, buf, size);
8259 	if (ret < 0)
8260 		return ret;
8261 	/* Nothing else to do if there is no buffer. */
8262 	if (!out)
8263 		return ret;
8264 	if (!out->args.vc.actions_n)
8265 		return -1;
8266 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8267 	/* Point to selected object. */
8268 	ctx->object = out->args.vc.data;
8269 	ctx->objmask = NULL;
8270 	action_vxlan_encap_data = ctx->object;
8271 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
8272 	action->conf = &action_vxlan_encap_data->conf;
8273 	return ret;
8274 }
8275 
8276 /** Setup NVGRE encap configuration. */
8277 static int
8278 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
8279 {
8280 	/* Set up default configuration. */
8281 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
8282 		.conf = (struct rte_flow_action_nvgre_encap){
8283 			.definition = action_nvgre_encap_data->items,
8284 		},
8285 		.items = {
8286 			{
8287 				.type = RTE_FLOW_ITEM_TYPE_ETH,
8288 				.spec = &action_nvgre_encap_data->item_eth,
8289 				.mask = &rte_flow_item_eth_mask,
8290 			},
8291 			{
8292 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
8293 				.spec = &action_nvgre_encap_data->item_vlan,
8294 				.mask = &rte_flow_item_vlan_mask,
8295 			},
8296 			{
8297 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
8298 				.spec = &action_nvgre_encap_data->item_ipv4,
8299 				.mask = &rte_flow_item_ipv4_mask,
8300 			},
8301 			{
8302 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
8303 				.spec = &action_nvgre_encap_data->item_nvgre,
8304 				.mask = &rte_flow_item_nvgre_mask,
8305 			},
8306 			{
8307 				.type = RTE_FLOW_ITEM_TYPE_END,
8308 			},
8309 		},
8310 		.item_eth.hdr.ether_type = 0,
8311 		.item_vlan = {
8312 			.hdr.vlan_tci = nvgre_encap_conf.vlan_tci,
8313 			.hdr.eth_proto = 0,
8314 		},
8315 		.item_ipv4.hdr = {
8316 		       .src_addr = nvgre_encap_conf.ipv4_src,
8317 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
8318 		},
8319 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
8320 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
8321 		.item_nvgre.flow_id = 0,
8322 	};
8323 	memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes,
8324 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8325 	memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes,
8326 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8327 	if (!nvgre_encap_conf.select_ipv4) {
8328 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
8329 		       &nvgre_encap_conf.ipv6_src,
8330 		       sizeof(nvgre_encap_conf.ipv6_src));
8331 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
8332 		       &nvgre_encap_conf.ipv6_dst,
8333 		       sizeof(nvgre_encap_conf.ipv6_dst));
8334 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
8335 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
8336 			.spec = &action_nvgre_encap_data->item_ipv6,
8337 			.mask = &rte_flow_item_ipv6_mask,
8338 		};
8339 	}
8340 	if (!nvgre_encap_conf.select_vlan)
8341 		action_nvgre_encap_data->items[1].type =
8342 			RTE_FLOW_ITEM_TYPE_VOID;
8343 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
8344 	       RTE_DIM(nvgre_encap_conf.tni));
8345 	return 0;
8346 }
8347 
8348 /** Parse NVGRE encap action. */
8349 static int
8350 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
8351 			    const char *str, unsigned int len,
8352 			    void *buf, unsigned int size)
8353 {
8354 	struct buffer *out = buf;
8355 	struct rte_flow_action *action;
8356 	struct action_nvgre_encap_data *action_nvgre_encap_data;
8357 	int ret;
8358 
8359 	ret = parse_vc(ctx, token, str, len, buf, size);
8360 	if (ret < 0)
8361 		return ret;
8362 	/* Nothing else to do if there is no buffer. */
8363 	if (!out)
8364 		return ret;
8365 	if (!out->args.vc.actions_n)
8366 		return -1;
8367 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8368 	/* Point to selected object. */
8369 	ctx->object = out->args.vc.data;
8370 	ctx->objmask = NULL;
8371 	action_nvgre_encap_data = ctx->object;
8372 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
8373 	action->conf = &action_nvgre_encap_data->conf;
8374 	return ret;
8375 }
8376 
8377 /** Parse l2 encap action. */
8378 static int
8379 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
8380 			 const char *str, unsigned int len,
8381 			 void *buf, unsigned int size)
8382 {
8383 	struct buffer *out = buf;
8384 	struct rte_flow_action *action;
8385 	struct action_raw_encap_data *action_encap_data;
8386 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8387 	struct rte_flow_item_vlan vlan = {
8388 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
8389 		.hdr.eth_proto = 0,
8390 	};
8391 	uint8_t *header;
8392 	int ret;
8393 
8394 	ret = parse_vc(ctx, token, str, len, buf, size);
8395 	if (ret < 0)
8396 		return ret;
8397 	/* Nothing else to do if there is no buffer. */
8398 	if (!out)
8399 		return ret;
8400 	if (!out->args.vc.actions_n)
8401 		return -1;
8402 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8403 	/* Point to selected object. */
8404 	ctx->object = out->args.vc.data;
8405 	ctx->objmask = NULL;
8406 	/* Copy the headers to the buffer. */
8407 	action_encap_data = ctx->object;
8408 	*action_encap_data = (struct action_raw_encap_data) {
8409 		.conf = (struct rte_flow_action_raw_encap){
8410 			.data = action_encap_data->data,
8411 		},
8412 		.data = {},
8413 	};
8414 	header = action_encap_data->data;
8415 	if (l2_encap_conf.select_vlan)
8416 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8417 	else if (l2_encap_conf.select_ipv4)
8418 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8419 	else
8420 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8421 	memcpy(eth.hdr.dst_addr.addr_bytes,
8422 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8423 	memcpy(eth.hdr.src_addr.addr_bytes,
8424 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8425 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
8426 	header += sizeof(struct rte_ether_hdr);
8427 	if (l2_encap_conf.select_vlan) {
8428 		if (l2_encap_conf.select_ipv4)
8429 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8430 		else
8431 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8432 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
8433 		header += sizeof(struct rte_vlan_hdr);
8434 	}
8435 	action_encap_data->conf.size = header -
8436 		action_encap_data->data;
8437 	action->conf = &action_encap_data->conf;
8438 	return ret;
8439 }
8440 
8441 /** Parse l2 decap action. */
8442 static int
8443 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
8444 			 const char *str, unsigned int len,
8445 			 void *buf, unsigned int size)
8446 {
8447 	struct buffer *out = buf;
8448 	struct rte_flow_action *action;
8449 	struct action_raw_decap_data *action_decap_data;
8450 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8451 	struct rte_flow_item_vlan vlan = {
8452 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
8453 		.hdr.eth_proto = 0,
8454 	};
8455 	uint8_t *header;
8456 	int ret;
8457 
8458 	ret = parse_vc(ctx, token, str, len, buf, size);
8459 	if (ret < 0)
8460 		return ret;
8461 	/* Nothing else to do if there is no buffer. */
8462 	if (!out)
8463 		return ret;
8464 	if (!out->args.vc.actions_n)
8465 		return -1;
8466 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8467 	/* Point to selected object. */
8468 	ctx->object = out->args.vc.data;
8469 	ctx->objmask = NULL;
8470 	/* Copy the headers to the buffer. */
8471 	action_decap_data = ctx->object;
8472 	*action_decap_data = (struct action_raw_decap_data) {
8473 		.conf = (struct rte_flow_action_raw_decap){
8474 			.data = action_decap_data->data,
8475 		},
8476 		.data = {},
8477 	};
8478 	header = action_decap_data->data;
8479 	if (l2_decap_conf.select_vlan)
8480 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8481 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
8482 	header += sizeof(struct rte_ether_hdr);
8483 	if (l2_decap_conf.select_vlan) {
8484 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
8485 		header += sizeof(struct rte_vlan_hdr);
8486 	}
8487 	action_decap_data->conf.size = header -
8488 		action_decap_data->data;
8489 	action->conf = &action_decap_data->conf;
8490 	return ret;
8491 }
8492 
8493 #define ETHER_TYPE_MPLS_UNICAST 0x8847
8494 
8495 /** Parse MPLSOGRE encap action. */
8496 static int
8497 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
8498 			       const char *str, unsigned int len,
8499 			       void *buf, unsigned int size)
8500 {
8501 	struct buffer *out = buf;
8502 	struct rte_flow_action *action;
8503 	struct action_raw_encap_data *action_encap_data;
8504 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8505 	struct rte_flow_item_vlan vlan = {
8506 		.hdr.vlan_tci = mplsogre_encap_conf.vlan_tci,
8507 		.hdr.eth_proto = 0,
8508 	};
8509 	struct rte_flow_item_ipv4 ipv4 = {
8510 		.hdr =  {
8511 			.src_addr = mplsogre_encap_conf.ipv4_src,
8512 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
8513 			.next_proto_id = IPPROTO_GRE,
8514 			.version_ihl = RTE_IPV4_VHL_DEF,
8515 			.time_to_live = IPDEFTTL,
8516 		},
8517 	};
8518 	struct rte_flow_item_ipv6 ipv6 = {
8519 		.hdr =  {
8520 			.proto = IPPROTO_GRE,
8521 			.hop_limits = IPDEFTTL,
8522 		},
8523 	};
8524 	struct rte_flow_item_gre gre = {
8525 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
8526 	};
8527 	struct rte_flow_item_mpls mpls = {
8528 		.ttl = 0,
8529 	};
8530 	uint8_t *header;
8531 	int ret;
8532 
8533 	ret = parse_vc(ctx, token, str, len, buf, size);
8534 	if (ret < 0)
8535 		return ret;
8536 	/* Nothing else to do if there is no buffer. */
8537 	if (!out)
8538 		return ret;
8539 	if (!out->args.vc.actions_n)
8540 		return -1;
8541 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8542 	/* Point to selected object. */
8543 	ctx->object = out->args.vc.data;
8544 	ctx->objmask = NULL;
8545 	/* Copy the headers to the buffer. */
8546 	action_encap_data = ctx->object;
8547 	*action_encap_data = (struct action_raw_encap_data) {
8548 		.conf = (struct rte_flow_action_raw_encap){
8549 			.data = action_encap_data->data,
8550 		},
8551 		.data = {},
8552 		.preserve = {},
8553 	};
8554 	header = action_encap_data->data;
8555 	if (mplsogre_encap_conf.select_vlan)
8556 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8557 	else if (mplsogre_encap_conf.select_ipv4)
8558 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8559 	else
8560 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8561 	memcpy(eth.hdr.dst_addr.addr_bytes,
8562 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8563 	memcpy(eth.hdr.src_addr.addr_bytes,
8564 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8565 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
8566 	header += sizeof(struct rte_ether_hdr);
8567 	if (mplsogre_encap_conf.select_vlan) {
8568 		if (mplsogre_encap_conf.select_ipv4)
8569 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8570 		else
8571 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8572 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
8573 		header += sizeof(struct rte_vlan_hdr);
8574 	}
8575 	if (mplsogre_encap_conf.select_ipv4) {
8576 		memcpy(header, &ipv4, sizeof(ipv4));
8577 		header += sizeof(ipv4);
8578 	} else {
8579 		memcpy(&ipv6.hdr.src_addr,
8580 		       &mplsogre_encap_conf.ipv6_src,
8581 		       sizeof(mplsogre_encap_conf.ipv6_src));
8582 		memcpy(&ipv6.hdr.dst_addr,
8583 		       &mplsogre_encap_conf.ipv6_dst,
8584 		       sizeof(mplsogre_encap_conf.ipv6_dst));
8585 		memcpy(header, &ipv6, sizeof(ipv6));
8586 		header += sizeof(ipv6);
8587 	}
8588 	memcpy(header, &gre, sizeof(gre));
8589 	header += sizeof(gre);
8590 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
8591 	       RTE_DIM(mplsogre_encap_conf.label));
8592 	mpls.label_tc_s[2] |= 0x1;
8593 	memcpy(header, &mpls, sizeof(mpls));
8594 	header += sizeof(mpls);
8595 	action_encap_data->conf.size = header -
8596 		action_encap_data->data;
8597 	action->conf = &action_encap_data->conf;
8598 	return ret;
8599 }
8600 
8601 /** Parse MPLSOGRE decap action. */
8602 static int
8603 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
8604 			       const char *str, unsigned int len,
8605 			       void *buf, unsigned int size)
8606 {
8607 	struct buffer *out = buf;
8608 	struct rte_flow_action *action;
8609 	struct action_raw_decap_data *action_decap_data;
8610 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8611 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
8612 	struct rte_flow_item_ipv4 ipv4 = {
8613 		.hdr =  {
8614 			.next_proto_id = IPPROTO_GRE,
8615 		},
8616 	};
8617 	struct rte_flow_item_ipv6 ipv6 = {
8618 		.hdr =  {
8619 			.proto = IPPROTO_GRE,
8620 		},
8621 	};
8622 	struct rte_flow_item_gre gre = {
8623 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
8624 	};
8625 	struct rte_flow_item_mpls mpls;
8626 	uint8_t *header;
8627 	int ret;
8628 
8629 	ret = parse_vc(ctx, token, str, len, buf, size);
8630 	if (ret < 0)
8631 		return ret;
8632 	/* Nothing else to do if there is no buffer. */
8633 	if (!out)
8634 		return ret;
8635 	if (!out->args.vc.actions_n)
8636 		return -1;
8637 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8638 	/* Point to selected object. */
8639 	ctx->object = out->args.vc.data;
8640 	ctx->objmask = NULL;
8641 	/* Copy the headers to the buffer. */
8642 	action_decap_data = ctx->object;
8643 	*action_decap_data = (struct action_raw_decap_data) {
8644 		.conf = (struct rte_flow_action_raw_decap){
8645 			.data = action_decap_data->data,
8646 		},
8647 		.data = {},
8648 	};
8649 	header = action_decap_data->data;
8650 	if (mplsogre_decap_conf.select_vlan)
8651 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8652 	else if (mplsogre_encap_conf.select_ipv4)
8653 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8654 	else
8655 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8656 	memcpy(eth.hdr.dst_addr.addr_bytes,
8657 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8658 	memcpy(eth.hdr.src_addr.addr_bytes,
8659 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8660 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
8661 	header += sizeof(struct rte_ether_hdr);
8662 	if (mplsogre_encap_conf.select_vlan) {
8663 		if (mplsogre_encap_conf.select_ipv4)
8664 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8665 		else
8666 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8667 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
8668 		header += sizeof(struct rte_vlan_hdr);
8669 	}
8670 	if (mplsogre_encap_conf.select_ipv4) {
8671 		memcpy(header, &ipv4, sizeof(ipv4));
8672 		header += sizeof(ipv4);
8673 	} else {
8674 		memcpy(header, &ipv6, sizeof(ipv6));
8675 		header += sizeof(ipv6);
8676 	}
8677 	memcpy(header, &gre, sizeof(gre));
8678 	header += sizeof(gre);
8679 	memset(&mpls, 0, sizeof(mpls));
8680 	memcpy(header, &mpls, sizeof(mpls));
8681 	header += sizeof(mpls);
8682 	action_decap_data->conf.size = header -
8683 		action_decap_data->data;
8684 	action->conf = &action_decap_data->conf;
8685 	return ret;
8686 }
8687 
8688 /** Parse MPLSOUDP encap action. */
8689 static int
8690 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
8691 			       const char *str, unsigned int len,
8692 			       void *buf, unsigned int size)
8693 {
8694 	struct buffer *out = buf;
8695 	struct rte_flow_action *action;
8696 	struct action_raw_encap_data *action_encap_data;
8697 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8698 	struct rte_flow_item_vlan vlan = {
8699 		.hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci,
8700 		.hdr.eth_proto = 0,
8701 	};
8702 	struct rte_flow_item_ipv4 ipv4 = {
8703 		.hdr =  {
8704 			.src_addr = mplsoudp_encap_conf.ipv4_src,
8705 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
8706 			.next_proto_id = IPPROTO_UDP,
8707 			.version_ihl = RTE_IPV4_VHL_DEF,
8708 			.time_to_live = IPDEFTTL,
8709 		},
8710 	};
8711 	struct rte_flow_item_ipv6 ipv6 = {
8712 		.hdr =  {
8713 			.proto = IPPROTO_UDP,
8714 			.hop_limits = IPDEFTTL,
8715 		},
8716 	};
8717 	struct rte_flow_item_udp udp = {
8718 		.hdr = {
8719 			.src_port = mplsoudp_encap_conf.udp_src,
8720 			.dst_port = mplsoudp_encap_conf.udp_dst,
8721 		},
8722 	};
8723 	struct rte_flow_item_mpls mpls;
8724 	uint8_t *header;
8725 	int ret;
8726 
8727 	ret = parse_vc(ctx, token, str, len, buf, size);
8728 	if (ret < 0)
8729 		return ret;
8730 	/* Nothing else to do if there is no buffer. */
8731 	if (!out)
8732 		return ret;
8733 	if (!out->args.vc.actions_n)
8734 		return -1;
8735 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8736 	/* Point to selected object. */
8737 	ctx->object = out->args.vc.data;
8738 	ctx->objmask = NULL;
8739 	/* Copy the headers to the buffer. */
8740 	action_encap_data = ctx->object;
8741 	*action_encap_data = (struct action_raw_encap_data) {
8742 		.conf = (struct rte_flow_action_raw_encap){
8743 			.data = action_encap_data->data,
8744 		},
8745 		.data = {},
8746 		.preserve = {},
8747 	};
8748 	header = action_encap_data->data;
8749 	if (mplsoudp_encap_conf.select_vlan)
8750 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8751 	else if (mplsoudp_encap_conf.select_ipv4)
8752 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8753 	else
8754 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8755 	memcpy(eth.hdr.dst_addr.addr_bytes,
8756 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8757 	memcpy(eth.hdr.src_addr.addr_bytes,
8758 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8759 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
8760 	header += sizeof(struct rte_ether_hdr);
8761 	if (mplsoudp_encap_conf.select_vlan) {
8762 		if (mplsoudp_encap_conf.select_ipv4)
8763 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8764 		else
8765 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8766 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
8767 		header += sizeof(struct rte_vlan_hdr);
8768 	}
8769 	if (mplsoudp_encap_conf.select_ipv4) {
8770 		memcpy(header, &ipv4, sizeof(ipv4));
8771 		header += sizeof(ipv4);
8772 	} else {
8773 		memcpy(&ipv6.hdr.src_addr,
8774 		       &mplsoudp_encap_conf.ipv6_src,
8775 		       sizeof(mplsoudp_encap_conf.ipv6_src));
8776 		memcpy(&ipv6.hdr.dst_addr,
8777 		       &mplsoudp_encap_conf.ipv6_dst,
8778 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
8779 		memcpy(header, &ipv6, sizeof(ipv6));
8780 		header += sizeof(ipv6);
8781 	}
8782 	memcpy(header, &udp, sizeof(udp));
8783 	header += sizeof(udp);
8784 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
8785 	       RTE_DIM(mplsoudp_encap_conf.label));
8786 	mpls.label_tc_s[2] |= 0x1;
8787 	memcpy(header, &mpls, sizeof(mpls));
8788 	header += sizeof(mpls);
8789 	action_encap_data->conf.size = header -
8790 		action_encap_data->data;
8791 	action->conf = &action_encap_data->conf;
8792 	return ret;
8793 }
8794 
8795 /** Parse MPLSOUDP decap action. */
8796 static int
8797 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
8798 			       const char *str, unsigned int len,
8799 			       void *buf, unsigned int size)
8800 {
8801 	struct buffer *out = buf;
8802 	struct rte_flow_action *action;
8803 	struct action_raw_decap_data *action_decap_data;
8804 	struct rte_flow_item_eth eth = { .hdr.ether_type = 0, };
8805 	struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0};
8806 	struct rte_flow_item_ipv4 ipv4 = {
8807 		.hdr =  {
8808 			.next_proto_id = IPPROTO_UDP,
8809 		},
8810 	};
8811 	struct rte_flow_item_ipv6 ipv6 = {
8812 		.hdr =  {
8813 			.proto = IPPROTO_UDP,
8814 		},
8815 	};
8816 	struct rte_flow_item_udp udp = {
8817 		.hdr = {
8818 			.dst_port = rte_cpu_to_be_16(6635),
8819 		},
8820 	};
8821 	struct rte_flow_item_mpls mpls;
8822 	uint8_t *header;
8823 	int ret;
8824 
8825 	ret = parse_vc(ctx, token, str, len, buf, size);
8826 	if (ret < 0)
8827 		return ret;
8828 	/* Nothing else to do if there is no buffer. */
8829 	if (!out)
8830 		return ret;
8831 	if (!out->args.vc.actions_n)
8832 		return -1;
8833 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8834 	/* Point to selected object. */
8835 	ctx->object = out->args.vc.data;
8836 	ctx->objmask = NULL;
8837 	/* Copy the headers to the buffer. */
8838 	action_decap_data = ctx->object;
8839 	*action_decap_data = (struct action_raw_decap_data) {
8840 		.conf = (struct rte_flow_action_raw_decap){
8841 			.data = action_decap_data->data,
8842 		},
8843 		.data = {},
8844 	};
8845 	header = action_decap_data->data;
8846 	if (mplsoudp_decap_conf.select_vlan)
8847 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
8848 	else if (mplsoudp_encap_conf.select_ipv4)
8849 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8850 	else
8851 		eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8852 	memcpy(eth.hdr.dst_addr.addr_bytes,
8853 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
8854 	memcpy(eth.hdr.src_addr.addr_bytes,
8855 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
8856 	memcpy(header, &eth.hdr, sizeof(struct rte_ether_hdr));
8857 	header += sizeof(struct rte_ether_hdr);
8858 	if (mplsoudp_encap_conf.select_vlan) {
8859 		if (mplsoudp_encap_conf.select_ipv4)
8860 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
8861 		else
8862 			vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
8863 		memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr));
8864 		header += sizeof(struct rte_vlan_hdr);
8865 	}
8866 	if (mplsoudp_encap_conf.select_ipv4) {
8867 		memcpy(header, &ipv4, sizeof(ipv4));
8868 		header += sizeof(ipv4);
8869 	} else {
8870 		memcpy(header, &ipv6, sizeof(ipv6));
8871 		header += sizeof(ipv6);
8872 	}
8873 	memcpy(header, &udp, sizeof(udp));
8874 	header += sizeof(udp);
8875 	memset(&mpls, 0, sizeof(mpls));
8876 	memcpy(header, &mpls, sizeof(mpls));
8877 	header += sizeof(mpls);
8878 	action_decap_data->conf.size = header -
8879 		action_decap_data->data;
8880 	action->conf = &action_decap_data->conf;
8881 	return ret;
8882 }
8883 
8884 static int
8885 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
8886 				const char *str, unsigned int len, void *buf,
8887 				unsigned int size)
8888 {
8889 	struct action_raw_decap_data *action_raw_decap_data;
8890 	struct rte_flow_action *action;
8891 	const struct arg *arg;
8892 	struct buffer *out = buf;
8893 	int ret;
8894 	uint16_t idx;
8895 
8896 	RTE_SET_USED(token);
8897 	RTE_SET_USED(buf);
8898 	RTE_SET_USED(size);
8899 	arg = ARGS_ENTRY_ARB_BOUNDED
8900 		(offsetof(struct action_raw_decap_data, idx),
8901 		 sizeof(((struct action_raw_decap_data *)0)->idx),
8902 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
8903 	if (push_args(ctx, arg))
8904 		return -1;
8905 	ret = parse_int(ctx, token, str, len, NULL, 0);
8906 	if (ret < 0) {
8907 		pop_args(ctx);
8908 		return -1;
8909 	}
8910 	if (!ctx->object)
8911 		return len;
8912 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8913 	action_raw_decap_data = ctx->object;
8914 	idx = action_raw_decap_data->idx;
8915 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
8916 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
8917 	action->conf = &action_raw_decap_data->conf;
8918 	return len;
8919 }
8920 
8921 
8922 static int
8923 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
8924 				const char *str, unsigned int len, void *buf,
8925 				unsigned int size)
8926 {
8927 	struct action_raw_encap_data *action_raw_encap_data;
8928 	struct rte_flow_action *action;
8929 	const struct arg *arg;
8930 	struct buffer *out = buf;
8931 	int ret;
8932 	uint16_t idx;
8933 
8934 	RTE_SET_USED(token);
8935 	RTE_SET_USED(buf);
8936 	RTE_SET_USED(size);
8937 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
8938 		return -1;
8939 	arg = ARGS_ENTRY_ARB_BOUNDED
8940 		(offsetof(struct action_raw_encap_data, idx),
8941 		 sizeof(((struct action_raw_encap_data *)0)->idx),
8942 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
8943 	if (push_args(ctx, arg))
8944 		return -1;
8945 	ret = parse_int(ctx, token, str, len, NULL, 0);
8946 	if (ret < 0) {
8947 		pop_args(ctx);
8948 		return -1;
8949 	}
8950 	if (!ctx->object)
8951 		return len;
8952 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8953 	action_raw_encap_data = ctx->object;
8954 	idx = action_raw_encap_data->idx;
8955 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
8956 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
8957 	action_raw_encap_data->conf.preserve = NULL;
8958 	action->conf = &action_raw_encap_data->conf;
8959 	return len;
8960 }
8961 
8962 static int
8963 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
8964 			  const char *str, unsigned int len, void *buf,
8965 			  unsigned int size)
8966 {
8967 	struct buffer *out = buf;
8968 	struct rte_flow_action *action;
8969 	struct action_raw_encap_data *action_raw_encap_data = NULL;
8970 	int ret;
8971 
8972 	ret = parse_vc(ctx, token, str, len, buf, size);
8973 	if (ret < 0)
8974 		return ret;
8975 	/* Nothing else to do if there is no buffer. */
8976 	if (!out)
8977 		return ret;
8978 	if (!out->args.vc.actions_n)
8979 		return -1;
8980 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
8981 	/* Point to selected object. */
8982 	ctx->object = out->args.vc.data;
8983 	ctx->objmask = NULL;
8984 	/* Copy the headers to the buffer. */
8985 	action_raw_encap_data = ctx->object;
8986 	action_raw_encap_data->conf.data = raw_encap_confs[0].data;
8987 	action_raw_encap_data->conf.preserve = NULL;
8988 	action_raw_encap_data->conf.size = raw_encap_confs[0].size;
8989 	action->conf = &action_raw_encap_data->conf;
8990 	return ret;
8991 }
8992 
8993 static int
8994 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
8995 			  const char *str, unsigned int len, void *buf,
8996 			  unsigned int size)
8997 {
8998 	struct buffer *out = buf;
8999 	struct rte_flow_action *action;
9000 	struct action_raw_decap_data *action_raw_decap_data = NULL;
9001 	int ret;
9002 
9003 	ret = parse_vc(ctx, token, str, len, buf, size);
9004 	if (ret < 0)
9005 		return ret;
9006 	/* Nothing else to do if there is no buffer. */
9007 	if (!out)
9008 		return ret;
9009 	if (!out->args.vc.actions_n)
9010 		return -1;
9011 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9012 	/* Point to selected object. */
9013 	ctx->object = out->args.vc.data;
9014 	ctx->objmask = NULL;
9015 	/* Copy the headers to the buffer. */
9016 	action_raw_decap_data = ctx->object;
9017 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
9018 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
9019 	action->conf = &action_raw_decap_data->conf;
9020 	return ret;
9021 }
9022 
9023 static int
9024 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
9025 			 const char *str, unsigned int len, void *buf,
9026 			 unsigned int size)
9027 {
9028 	int ret;
9029 
9030 	ret = parse_vc(ctx, token, str, len, buf, size);
9031 	if (ret < 0)
9032 		return ret;
9033 	ret = rte_flow_dynf_metadata_register();
9034 	if (ret < 0)
9035 		return -1;
9036 	return len;
9037 }
9038 
9039 static int
9040 parse_vc_action_sample(struct context *ctx, const struct token *token,
9041 			 const char *str, unsigned int len, void *buf,
9042 			 unsigned int size)
9043 {
9044 	struct buffer *out = buf;
9045 	struct rte_flow_action *action;
9046 	struct action_sample_data *action_sample_data = NULL;
9047 	static struct rte_flow_action end_action = {
9048 		RTE_FLOW_ACTION_TYPE_END, 0
9049 	};
9050 	int ret;
9051 
9052 	ret = parse_vc(ctx, token, str, len, buf, size);
9053 	if (ret < 0)
9054 		return ret;
9055 	/* Nothing else to do if there is no buffer. */
9056 	if (!out)
9057 		return ret;
9058 	if (!out->args.vc.actions_n)
9059 		return -1;
9060 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9061 	/* Point to selected object. */
9062 	ctx->object = out->args.vc.data;
9063 	ctx->objmask = NULL;
9064 	/* Copy the headers to the buffer. */
9065 	action_sample_data = ctx->object;
9066 	action_sample_data->conf.actions = &end_action;
9067 	action->conf = &action_sample_data->conf;
9068 	return ret;
9069 }
9070 
9071 static int
9072 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
9073 				const char *str, unsigned int len, void *buf,
9074 				unsigned int size)
9075 {
9076 	struct action_sample_data *action_sample_data;
9077 	struct rte_flow_action *action;
9078 	const struct arg *arg;
9079 	struct buffer *out = buf;
9080 	int ret;
9081 	uint16_t idx;
9082 
9083 	RTE_SET_USED(token);
9084 	RTE_SET_USED(buf);
9085 	RTE_SET_USED(size);
9086 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
9087 		return -1;
9088 	arg = ARGS_ENTRY_ARB_BOUNDED
9089 		(offsetof(struct action_sample_data, idx),
9090 		 sizeof(((struct action_sample_data *)0)->idx),
9091 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
9092 	if (push_args(ctx, arg))
9093 		return -1;
9094 	ret = parse_int(ctx, token, str, len, NULL, 0);
9095 	if (ret < 0) {
9096 		pop_args(ctx);
9097 		return -1;
9098 	}
9099 	if (!ctx->object)
9100 		return len;
9101 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
9102 	action_sample_data = ctx->object;
9103 	idx = action_sample_data->idx;
9104 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
9105 	action->conf = &action_sample_data->conf;
9106 	return len;
9107 }
9108 
9109 /** Parse operation for modify_field command. */
9110 static int
9111 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
9112 			 const char *str, unsigned int len, void *buf,
9113 			 unsigned int size)
9114 {
9115 	struct rte_flow_action_modify_field *action_modify_field;
9116 	unsigned int i;
9117 
9118 	(void)token;
9119 	(void)buf;
9120 	(void)size;
9121 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
9122 		return -1;
9123 	for (i = 0; modify_field_ops[i]; ++i)
9124 		if (!strcmp_partial(modify_field_ops[i], str, len))
9125 			break;
9126 	if (!modify_field_ops[i])
9127 		return -1;
9128 	if (!ctx->object)
9129 		return len;
9130 	action_modify_field = ctx->object;
9131 	action_modify_field->operation = (enum rte_flow_modify_op)i;
9132 	return len;
9133 }
9134 
9135 /** Parse id for modify_field command. */
9136 static int
9137 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
9138 			 const char *str, unsigned int len, void *buf,
9139 			 unsigned int size)
9140 {
9141 	struct rte_flow_action_modify_field *action_modify_field;
9142 	unsigned int i;
9143 
9144 	(void)token;
9145 	(void)buf;
9146 	(void)size;
9147 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
9148 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
9149 		return -1;
9150 	for (i = 0; modify_field_ids[i]; ++i)
9151 		if (!strcmp_partial(modify_field_ids[i], str, len))
9152 			break;
9153 	if (!modify_field_ids[i])
9154 		return -1;
9155 	if (!ctx->object)
9156 		return len;
9157 	action_modify_field = ctx->object;
9158 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
9159 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
9160 	else
9161 		action_modify_field->src.field = (enum rte_flow_field_id)i;
9162 	return len;
9163 }
9164 
9165 /** Parse level for modify_field command. */
9166 static int
9167 parse_vc_modify_field_level(struct context *ctx, const struct token *token,
9168 			 const char *str, unsigned int len, void *buf,
9169 			 unsigned int size)
9170 {
9171 	struct rte_flow_action_modify_field *action;
9172 	struct flex_item *fp = NULL;
9173 	uint32_t val;
9174 	struct buffer *out = buf;
9175 	char *end;
9176 
9177 	(void)token;
9178 	(void)size;
9179 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
9180 		ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)
9181 		return -1;
9182 	if (!ctx->object)
9183 		return len;
9184 	action = ctx->object;
9185 	errno = 0;
9186 	val = strtoumax(str, &end, 0);
9187 	if (errno || (size_t)(end - str) != len)
9188 		return -1;
9189 	/* No need to validate action template mask value */
9190 	if (out->args.vc.masks) {
9191 		if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)
9192 			action->dst.level = val;
9193 		else
9194 			action->src.level = val;
9195 		return len;
9196 	}
9197 	if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE &&
9198 		action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) ||
9199 		(ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE &&
9200 		action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) {
9201 		if (val >= FLEX_MAX_PARSERS_NUM) {
9202 			printf("Bad flex item handle\n");
9203 			return -1;
9204 		}
9205 		fp = flex_items[ctx->port][val];
9206 		if (!fp) {
9207 			printf("Bad flex item handle\n");
9208 			return -1;
9209 		}
9210 	}
9211 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) {
9212 		if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM)
9213 			action->dst.level = val;
9214 		else
9215 			action->dst.flex_handle = fp->flex_handle;
9216 	} else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) {
9217 		if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM)
9218 			action->src.level = val;
9219 		else
9220 			action->src.flex_handle = fp->flex_handle;
9221 	}
9222 	return len;
9223 }
9224 
9225 /** Parse the conntrack update, not a rte_flow_action. */
9226 static int
9227 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
9228 			 const char *str, unsigned int len, void *buf,
9229 			 unsigned int size)
9230 {
9231 	struct buffer *out = buf;
9232 	struct rte_flow_modify_conntrack *ct_modify = NULL;
9233 
9234 	(void)size;
9235 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
9236 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
9237 		return -1;
9238 	/* Token name must match. */
9239 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9240 		return -1;
9241 	/* Nothing else to do if there is no buffer. */
9242 	if (!out)
9243 		return len;
9244 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
9245 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
9246 		ct_modify->new_ct.is_original_dir =
9247 				conntrack_context.is_original_dir;
9248 		ct_modify->direction = 1;
9249 	} else {
9250 		uint32_t old_dir;
9251 
9252 		old_dir = ct_modify->new_ct.is_original_dir;
9253 		memcpy(&ct_modify->new_ct, &conntrack_context,
9254 		       sizeof(conntrack_context));
9255 		ct_modify->new_ct.is_original_dir = old_dir;
9256 		ct_modify->state = 1;
9257 	}
9258 	return len;
9259 }
9260 
9261 /** Parse tokens for destroy command. */
9262 static int
9263 parse_destroy(struct context *ctx, const struct token *token,
9264 	      const char *str, unsigned int len,
9265 	      void *buf, unsigned int size)
9266 {
9267 	struct buffer *out = buf;
9268 
9269 	/* Token name must match. */
9270 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9271 		return -1;
9272 	/* Nothing else to do if there is no buffer. */
9273 	if (!out)
9274 		return len;
9275 	if (!out->command) {
9276 		if (ctx->curr != DESTROY)
9277 			return -1;
9278 		if (sizeof(*out) > size)
9279 			return -1;
9280 		out->command = ctx->curr;
9281 		ctx->objdata = 0;
9282 		ctx->object = out;
9283 		ctx->objmask = NULL;
9284 		out->args.destroy.rule =
9285 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9286 					       sizeof(double));
9287 		return len;
9288 	}
9289 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
9290 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
9291 		return -1;
9292 	ctx->objdata = 0;
9293 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
9294 	ctx->objmask = NULL;
9295 	return len;
9296 }
9297 
9298 /** Parse tokens for flush command. */
9299 static int
9300 parse_flush(struct context *ctx, const struct token *token,
9301 	    const char *str, unsigned int len,
9302 	    void *buf, unsigned int size)
9303 {
9304 	struct buffer *out = buf;
9305 
9306 	/* Token name must match. */
9307 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9308 		return -1;
9309 	/* Nothing else to do if there is no buffer. */
9310 	if (!out)
9311 		return len;
9312 	if (!out->command) {
9313 		if (ctx->curr != FLUSH)
9314 			return -1;
9315 		if (sizeof(*out) > size)
9316 			return -1;
9317 		out->command = ctx->curr;
9318 		ctx->objdata = 0;
9319 		ctx->object = out;
9320 		ctx->objmask = NULL;
9321 	}
9322 	return len;
9323 }
9324 
9325 /** Parse tokens for dump command. */
9326 static int
9327 parse_dump(struct context *ctx, const struct token *token,
9328 	    const char *str, unsigned int len,
9329 	    void *buf, unsigned int size)
9330 {
9331 	struct buffer *out = buf;
9332 
9333 	/* Token name must match. */
9334 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9335 		return -1;
9336 	/* Nothing else to do if there is no buffer. */
9337 	if (!out)
9338 		return len;
9339 	if (!out->command) {
9340 		if (ctx->curr != DUMP)
9341 			return -1;
9342 		if (sizeof(*out) > size)
9343 			return -1;
9344 		out->command = ctx->curr;
9345 		ctx->objdata = 0;
9346 		ctx->object = out;
9347 		ctx->objmask = NULL;
9348 		return len;
9349 	}
9350 	switch (ctx->curr) {
9351 	case DUMP_ALL:
9352 	case DUMP_ONE:
9353 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
9354 		out->command = ctx->curr;
9355 		ctx->objdata = 0;
9356 		ctx->object = out;
9357 		ctx->objmask = NULL;
9358 		return len;
9359 	default:
9360 		return -1;
9361 	}
9362 }
9363 
9364 /** Parse tokens for query command. */
9365 static int
9366 parse_query(struct context *ctx, const struct token *token,
9367 	    const char *str, unsigned int len,
9368 	    void *buf, unsigned int size)
9369 {
9370 	struct buffer *out = buf;
9371 
9372 	/* Token name must match. */
9373 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9374 		return -1;
9375 	/* Nothing else to do if there is no buffer. */
9376 	if (!out)
9377 		return len;
9378 	if (!out->command) {
9379 		if (ctx->curr != QUERY)
9380 			return -1;
9381 		if (sizeof(*out) > size)
9382 			return -1;
9383 		out->command = ctx->curr;
9384 		ctx->objdata = 0;
9385 		ctx->object = out;
9386 		ctx->objmask = NULL;
9387 	}
9388 	return len;
9389 }
9390 
9391 /** Parse action names. */
9392 static int
9393 parse_action(struct context *ctx, const struct token *token,
9394 	     const char *str, unsigned int len,
9395 	     void *buf, unsigned int size)
9396 {
9397 	struct buffer *out = buf;
9398 	const struct arg *arg = pop_args(ctx);
9399 	unsigned int i;
9400 
9401 	(void)size;
9402 	/* Argument is expected. */
9403 	if (!arg)
9404 		return -1;
9405 	/* Parse action name. */
9406 	for (i = 0; next_action[i]; ++i) {
9407 		const struct parse_action_priv *priv;
9408 
9409 		token = &token_list[next_action[i]];
9410 		if (strcmp_partial(token->name, str, len))
9411 			continue;
9412 		priv = token->priv;
9413 		if (!priv)
9414 			goto error;
9415 		if (out)
9416 			memcpy((uint8_t *)ctx->object + arg->offset,
9417 			       &priv->type,
9418 			       arg->size);
9419 		return len;
9420 	}
9421 error:
9422 	push_args(ctx, arg);
9423 	return -1;
9424 }
9425 
9426 /** Parse tokens for list command. */
9427 static int
9428 parse_list(struct context *ctx, const struct token *token,
9429 	   const char *str, unsigned int len,
9430 	   void *buf, unsigned int size)
9431 {
9432 	struct buffer *out = buf;
9433 
9434 	/* Token name must match. */
9435 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9436 		return -1;
9437 	/* Nothing else to do if there is no buffer. */
9438 	if (!out)
9439 		return len;
9440 	if (!out->command) {
9441 		if (ctx->curr != LIST)
9442 			return -1;
9443 		if (sizeof(*out) > size)
9444 			return -1;
9445 		out->command = ctx->curr;
9446 		ctx->objdata = 0;
9447 		ctx->object = out;
9448 		ctx->objmask = NULL;
9449 		out->args.list.group =
9450 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9451 					       sizeof(double));
9452 		return len;
9453 	}
9454 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
9455 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
9456 		return -1;
9457 	ctx->objdata = 0;
9458 	ctx->object = out->args.list.group + out->args.list.group_n++;
9459 	ctx->objmask = NULL;
9460 	return len;
9461 }
9462 
9463 /** Parse tokens for list all aged flows command. */
9464 static int
9465 parse_aged(struct context *ctx, const struct token *token,
9466 	   const char *str, unsigned int len,
9467 	   void *buf, unsigned int size)
9468 {
9469 	struct buffer *out = buf;
9470 
9471 	/* Token name must match. */
9472 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9473 		return -1;
9474 	/* Nothing else to do if there is no buffer. */
9475 	if (!out)
9476 		return len;
9477 	if (!out->command || out->command == QUEUE) {
9478 		if (ctx->curr != AGED && ctx->curr != QUEUE_AGED)
9479 			return -1;
9480 		if (sizeof(*out) > size)
9481 			return -1;
9482 		out->command = ctx->curr;
9483 		ctx->objdata = 0;
9484 		ctx->object = out;
9485 		ctx->objmask = NULL;
9486 	}
9487 	if (ctx->curr == AGED_DESTROY)
9488 		out->args.aged.destroy = 1;
9489 	return len;
9490 }
9491 
9492 /** Parse tokens for isolate command. */
9493 static int
9494 parse_isolate(struct context *ctx, const struct token *token,
9495 	      const char *str, unsigned int len,
9496 	      void *buf, unsigned int size)
9497 {
9498 	struct buffer *out = buf;
9499 
9500 	/* Token name must match. */
9501 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9502 		return -1;
9503 	/* Nothing else to do if there is no buffer. */
9504 	if (!out)
9505 		return len;
9506 	if (!out->command) {
9507 		if (ctx->curr != ISOLATE)
9508 			return -1;
9509 		if (sizeof(*out) > size)
9510 			return -1;
9511 		out->command = ctx->curr;
9512 		ctx->objdata = 0;
9513 		ctx->object = out;
9514 		ctx->objmask = NULL;
9515 	}
9516 	return len;
9517 }
9518 
9519 /** Parse tokens for info/configure command. */
9520 static int
9521 parse_configure(struct context *ctx, const struct token *token,
9522 		const char *str, unsigned int len,
9523 		void *buf, unsigned int size)
9524 {
9525 	struct buffer *out = buf;
9526 
9527 	/* Token name must match. */
9528 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9529 		return -1;
9530 	/* Nothing else to do if there is no buffer. */
9531 	if (!out)
9532 		return len;
9533 	if (!out->command) {
9534 		if (ctx->curr != INFO && ctx->curr != CONFIGURE)
9535 			return -1;
9536 		if (sizeof(*out) > size)
9537 			return -1;
9538 		out->command = ctx->curr;
9539 		ctx->objdata = 0;
9540 		ctx->object = out;
9541 		ctx->objmask = NULL;
9542 	}
9543 	return len;
9544 }
9545 
9546 /** Parse tokens for template create command. */
9547 static int
9548 parse_template(struct context *ctx, const struct token *token,
9549 	       const char *str, unsigned int len,
9550 	       void *buf, unsigned int size)
9551 {
9552 	struct buffer *out = buf;
9553 
9554 	/* Token name must match. */
9555 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9556 		return -1;
9557 	/* Nothing else to do if there is no buffer. */
9558 	if (!out)
9559 		return len;
9560 	if (!out->command) {
9561 		if (ctx->curr != PATTERN_TEMPLATE &&
9562 		    ctx->curr != ACTIONS_TEMPLATE)
9563 			return -1;
9564 		if (sizeof(*out) > size)
9565 			return -1;
9566 		out->command = ctx->curr;
9567 		ctx->objdata = 0;
9568 		ctx->object = out;
9569 		ctx->objmask = NULL;
9570 		out->args.vc.data = (uint8_t *)out + size;
9571 		return len;
9572 	}
9573 	switch (ctx->curr) {
9574 	case PATTERN_TEMPLATE_CREATE:
9575 		out->args.vc.pattern =
9576 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9577 					       sizeof(double));
9578 		out->args.vc.pat_templ_id = UINT32_MAX;
9579 		out->command = ctx->curr;
9580 		ctx->objdata = 0;
9581 		ctx->object = out;
9582 		ctx->objmask = NULL;
9583 		return len;
9584 	case PATTERN_TEMPLATE_EGRESS:
9585 		out->args.vc.attr.egress = 1;
9586 		return len;
9587 	case PATTERN_TEMPLATE_INGRESS:
9588 		out->args.vc.attr.ingress = 1;
9589 		return len;
9590 	case PATTERN_TEMPLATE_TRANSFER:
9591 		out->args.vc.attr.transfer = 1;
9592 		return len;
9593 	case ACTIONS_TEMPLATE_CREATE:
9594 		out->args.vc.act_templ_id = UINT32_MAX;
9595 		out->command = ctx->curr;
9596 		ctx->objdata = 0;
9597 		ctx->object = out;
9598 		ctx->objmask = NULL;
9599 		return len;
9600 	case ACTIONS_TEMPLATE_SPEC:
9601 		out->args.vc.actions =
9602 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9603 					       sizeof(double));
9604 		ctx->object = out->args.vc.actions;
9605 		ctx->objmask = NULL;
9606 		return len;
9607 	case ACTIONS_TEMPLATE_MASK:
9608 		out->args.vc.masks =
9609 			(void *)RTE_ALIGN_CEIL((uintptr_t)
9610 					       (out->args.vc.actions +
9611 						out->args.vc.actions_n),
9612 					       sizeof(double));
9613 		ctx->object = out->args.vc.masks;
9614 		ctx->objmask = NULL;
9615 		return len;
9616 	case ACTIONS_TEMPLATE_EGRESS:
9617 		out->args.vc.attr.egress = 1;
9618 		return len;
9619 	case ACTIONS_TEMPLATE_INGRESS:
9620 		out->args.vc.attr.ingress = 1;
9621 		return len;
9622 	case ACTIONS_TEMPLATE_TRANSFER:
9623 		out->args.vc.attr.transfer = 1;
9624 		return len;
9625 	default:
9626 		return -1;
9627 	}
9628 }
9629 
9630 /** Parse tokens for template destroy command. */
9631 static int
9632 parse_template_destroy(struct context *ctx, const struct token *token,
9633 		       const char *str, unsigned int len,
9634 		       void *buf, unsigned int size)
9635 {
9636 	struct buffer *out = buf;
9637 	uint32_t *template_id;
9638 
9639 	/* Token name must match. */
9640 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9641 		return -1;
9642 	/* Nothing else to do if there is no buffer. */
9643 	if (!out)
9644 		return len;
9645 	if (!out->command ||
9646 		out->command == PATTERN_TEMPLATE ||
9647 		out->command == ACTIONS_TEMPLATE) {
9648 		if (ctx->curr != PATTERN_TEMPLATE_DESTROY &&
9649 			ctx->curr != ACTIONS_TEMPLATE_DESTROY)
9650 			return -1;
9651 		if (sizeof(*out) > size)
9652 			return -1;
9653 		out->command = ctx->curr;
9654 		ctx->objdata = 0;
9655 		ctx->object = out;
9656 		ctx->objmask = NULL;
9657 		out->args.templ_destroy.template_id =
9658 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9659 					       sizeof(double));
9660 		return len;
9661 	}
9662 	template_id = out->args.templ_destroy.template_id
9663 		    + out->args.templ_destroy.template_id_n++;
9664 	if ((uint8_t *)template_id > (uint8_t *)out + size)
9665 		return -1;
9666 	ctx->objdata = 0;
9667 	ctx->object = template_id;
9668 	ctx->objmask = NULL;
9669 	return len;
9670 }
9671 
9672 /** Parse tokens for table create command. */
9673 static int
9674 parse_table(struct context *ctx, const struct token *token,
9675 	    const char *str, unsigned int len,
9676 	    void *buf, unsigned int size)
9677 {
9678 	struct buffer *out = buf;
9679 	uint32_t *template_id;
9680 
9681 	/* Token name must match. */
9682 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9683 		return -1;
9684 	/* Nothing else to do if there is no buffer. */
9685 	if (!out)
9686 		return len;
9687 	if (!out->command) {
9688 		if (ctx->curr != TABLE)
9689 			return -1;
9690 		if (sizeof(*out) > size)
9691 			return -1;
9692 		out->command = ctx->curr;
9693 		ctx->objdata = 0;
9694 		ctx->object = out;
9695 		ctx->objmask = NULL;
9696 		return len;
9697 	}
9698 	switch (ctx->curr) {
9699 	case TABLE_CREATE:
9700 		out->command = ctx->curr;
9701 		ctx->objdata = 0;
9702 		ctx->object = out;
9703 		ctx->objmask = NULL;
9704 		out->args.table.id = UINT32_MAX;
9705 		return len;
9706 	case TABLE_PATTERN_TEMPLATE:
9707 		out->args.table.pat_templ_id =
9708 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9709 					       sizeof(double));
9710 		template_id = out->args.table.pat_templ_id
9711 				+ out->args.table.pat_templ_id_n++;
9712 		if ((uint8_t *)template_id > (uint8_t *)out + size)
9713 			return -1;
9714 		ctx->objdata = 0;
9715 		ctx->object = template_id;
9716 		ctx->objmask = NULL;
9717 		return len;
9718 	case TABLE_ACTIONS_TEMPLATE:
9719 		out->args.table.act_templ_id =
9720 			(void *)RTE_ALIGN_CEIL((uintptr_t)
9721 					       (out->args.table.pat_templ_id +
9722 						out->args.table.pat_templ_id_n),
9723 					       sizeof(double));
9724 		template_id = out->args.table.act_templ_id
9725 				+ out->args.table.act_templ_id_n++;
9726 		if ((uint8_t *)template_id > (uint8_t *)out + size)
9727 			return -1;
9728 		ctx->objdata = 0;
9729 		ctx->object = template_id;
9730 		ctx->objmask = NULL;
9731 		return len;
9732 	case TABLE_INGRESS:
9733 		out->args.table.attr.flow_attr.ingress = 1;
9734 		return len;
9735 	case TABLE_EGRESS:
9736 		out->args.table.attr.flow_attr.egress = 1;
9737 		return len;
9738 	case TABLE_TRANSFER:
9739 		out->args.table.attr.flow_attr.transfer = 1;
9740 		return len;
9741 	case TABLE_TRANSFER_WIRE_ORIG:
9742 		if (!out->args.table.attr.flow_attr.transfer)
9743 			return -1;
9744 		out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG;
9745 		return len;
9746 	case TABLE_TRANSFER_VPORT_ORIG:
9747 		if (!out->args.table.attr.flow_attr.transfer)
9748 			return -1;
9749 		out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG;
9750 		return len;
9751 	default:
9752 		return -1;
9753 	}
9754 }
9755 
9756 /** Parse tokens for table destroy command. */
9757 static int
9758 parse_table_destroy(struct context *ctx, const struct token *token,
9759 		    const char *str, unsigned int len,
9760 		    void *buf, unsigned int size)
9761 {
9762 	struct buffer *out = buf;
9763 	uint32_t *table_id;
9764 
9765 	/* Token name must match. */
9766 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9767 		return -1;
9768 	/* Nothing else to do if there is no buffer. */
9769 	if (!out)
9770 		return len;
9771 	if (!out->command || out->command == TABLE) {
9772 		if (ctx->curr != TABLE_DESTROY)
9773 			return -1;
9774 		if (sizeof(*out) > size)
9775 			return -1;
9776 		out->command = ctx->curr;
9777 		ctx->objdata = 0;
9778 		ctx->object = out;
9779 		ctx->objmask = NULL;
9780 		out->args.table_destroy.table_id =
9781 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9782 					       sizeof(double));
9783 		return len;
9784 	}
9785 	table_id = out->args.table_destroy.table_id
9786 		    + out->args.table_destroy.table_id_n++;
9787 	if ((uint8_t *)table_id > (uint8_t *)out + size)
9788 		return -1;
9789 	ctx->objdata = 0;
9790 	ctx->object = table_id;
9791 	ctx->objmask = NULL;
9792 	return len;
9793 }
9794 
9795 /** Parse tokens for queue create commands. */
9796 static int
9797 parse_qo(struct context *ctx, const struct token *token,
9798 	 const char *str, unsigned int len,
9799 	 void *buf, unsigned int size)
9800 {
9801 	struct buffer *out = buf;
9802 
9803 	/* Token name must match. */
9804 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9805 		return -1;
9806 	/* Nothing else to do if there is no buffer. */
9807 	if (!out)
9808 		return len;
9809 	if (!out->command) {
9810 		if (ctx->curr != QUEUE)
9811 			return -1;
9812 		if (sizeof(*out) > size)
9813 			return -1;
9814 		out->command = ctx->curr;
9815 		ctx->objdata = 0;
9816 		ctx->object = out;
9817 		ctx->objmask = NULL;
9818 		out->args.vc.data = (uint8_t *)out + size;
9819 		return len;
9820 	}
9821 	switch (ctx->curr) {
9822 	case QUEUE_CREATE:
9823 		out->command = ctx->curr;
9824 		ctx->objdata = 0;
9825 		ctx->object = out;
9826 		ctx->objmask = NULL;
9827 		out->args.vc.rule_id = UINT32_MAX;
9828 		return len;
9829 	case QUEUE_TEMPLATE_TABLE:
9830 	case QUEUE_PATTERN_TEMPLATE:
9831 	case QUEUE_ACTIONS_TEMPLATE:
9832 	case QUEUE_CREATE_POSTPONE:
9833 	case QUEUE_RULE_ID:
9834 		return len;
9835 	case ITEM_PATTERN:
9836 		out->args.vc.pattern =
9837 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9838 					       sizeof(double));
9839 		ctx->object = out->args.vc.pattern;
9840 		ctx->objmask = NULL;
9841 		return len;
9842 	case ACTIONS:
9843 		out->args.vc.actions =
9844 			(void *)RTE_ALIGN_CEIL((uintptr_t)
9845 					       (out->args.vc.pattern +
9846 						out->args.vc.pattern_n),
9847 					       sizeof(double));
9848 		ctx->object = out->args.vc.actions;
9849 		ctx->objmask = NULL;
9850 		return len;
9851 	default:
9852 		return -1;
9853 	}
9854 }
9855 
9856 /** Parse tokens for queue destroy command. */
9857 static int
9858 parse_qo_destroy(struct context *ctx, const struct token *token,
9859 		 const char *str, unsigned int len,
9860 		 void *buf, unsigned int size)
9861 {
9862 	struct buffer *out = buf;
9863 	uint32_t *flow_id;
9864 
9865 	/* Token name must match. */
9866 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9867 		return -1;
9868 	/* Nothing else to do if there is no buffer. */
9869 	if (!out)
9870 		return len;
9871 	if (!out->command || out->command == QUEUE) {
9872 		if (ctx->curr != QUEUE_DESTROY)
9873 			return -1;
9874 		if (sizeof(*out) > size)
9875 			return -1;
9876 		out->command = ctx->curr;
9877 		ctx->objdata = 0;
9878 		ctx->object = out;
9879 		ctx->objmask = NULL;
9880 		out->args.destroy.rule =
9881 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
9882 					       sizeof(double));
9883 		return len;
9884 	}
9885 	switch (ctx->curr) {
9886 	case QUEUE_DESTROY_ID:
9887 		flow_id = out->args.destroy.rule
9888 				+ out->args.destroy.rule_n++;
9889 		if ((uint8_t *)flow_id > (uint8_t *)out + size)
9890 			return -1;
9891 		ctx->objdata = 0;
9892 		ctx->object = flow_id;
9893 		ctx->objmask = NULL;
9894 		return len;
9895 	case QUEUE_DESTROY_POSTPONE:
9896 		return len;
9897 	default:
9898 		return -1;
9899 	}
9900 }
9901 
9902 /** Parse tokens for push queue command. */
9903 static int
9904 parse_push(struct context *ctx, const struct token *token,
9905 	   const char *str, unsigned int len,
9906 	   void *buf, unsigned int size)
9907 {
9908 	struct buffer *out = buf;
9909 
9910 	/* Token name must match. */
9911 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9912 		return -1;
9913 	/* Nothing else to do if there is no buffer. */
9914 	if (!out)
9915 		return len;
9916 	if (!out->command) {
9917 		if (ctx->curr != PUSH)
9918 			return -1;
9919 		if (sizeof(*out) > size)
9920 			return -1;
9921 		out->command = ctx->curr;
9922 		ctx->objdata = 0;
9923 		ctx->object = out;
9924 		ctx->objmask = NULL;
9925 		out->args.vc.data = (uint8_t *)out + size;
9926 	}
9927 	return len;
9928 }
9929 
9930 /** Parse tokens for pull command. */
9931 static int
9932 parse_pull(struct context *ctx, const struct token *token,
9933 	   const char *str, unsigned int len,
9934 	   void *buf, unsigned int size)
9935 {
9936 	struct buffer *out = buf;
9937 
9938 	/* Token name must match. */
9939 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9940 		return -1;
9941 	/* Nothing else to do if there is no buffer. */
9942 	if (!out)
9943 		return len;
9944 	if (!out->command) {
9945 		if (ctx->curr != PULL)
9946 			return -1;
9947 		if (sizeof(*out) > size)
9948 			return -1;
9949 		out->command = ctx->curr;
9950 		ctx->objdata = 0;
9951 		ctx->object = out;
9952 		ctx->objmask = NULL;
9953 		out->args.vc.data = (uint8_t *)out + size;
9954 	}
9955 	return len;
9956 }
9957 
9958 static int
9959 parse_flex(struct context *ctx, const struct token *token,
9960 	     const char *str, unsigned int len,
9961 	     void *buf, unsigned int size)
9962 {
9963 	struct buffer *out = buf;
9964 
9965 	/* Token name must match. */
9966 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
9967 		return -1;
9968 	/* Nothing else to do if there is no buffer. */
9969 	if (!out)
9970 		return len;
9971 	if (out->command == ZERO) {
9972 		if (ctx->curr != FLEX)
9973 			return -1;
9974 		if (sizeof(*out) > size)
9975 			return -1;
9976 		out->command = ctx->curr;
9977 		ctx->objdata = 0;
9978 		ctx->object = out;
9979 		ctx->objmask = NULL;
9980 	} else {
9981 		switch (ctx->curr) {
9982 		default:
9983 			break;
9984 		case FLEX_ITEM_INIT:
9985 		case FLEX_ITEM_CREATE:
9986 		case FLEX_ITEM_DESTROY:
9987 			out->command = ctx->curr;
9988 			break;
9989 		}
9990 	}
9991 
9992 	return len;
9993 }
9994 
9995 static int
9996 parse_tunnel(struct context *ctx, const struct token *token,
9997 	     const char *str, unsigned int len,
9998 	     void *buf, unsigned int size)
9999 {
10000 	struct buffer *out = buf;
10001 
10002 	/* Token name must match. */
10003 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10004 		return -1;
10005 	/* Nothing else to do if there is no buffer. */
10006 	if (!out)
10007 		return len;
10008 	if (!out->command) {
10009 		if (ctx->curr != TUNNEL)
10010 			return -1;
10011 		if (sizeof(*out) > size)
10012 			return -1;
10013 		out->command = ctx->curr;
10014 		ctx->objdata = 0;
10015 		ctx->object = out;
10016 		ctx->objmask = NULL;
10017 	} else {
10018 		switch (ctx->curr) {
10019 		default:
10020 			break;
10021 		case TUNNEL_CREATE:
10022 		case TUNNEL_DESTROY:
10023 		case TUNNEL_LIST:
10024 			out->command = ctx->curr;
10025 			break;
10026 		case TUNNEL_CREATE_TYPE:
10027 		case TUNNEL_DESTROY_ID:
10028 			ctx->object = &out->args.vc.tunnel_ops;
10029 			break;
10030 		}
10031 	}
10032 
10033 	return len;
10034 }
10035 
10036 /**
10037  * Parse signed/unsigned integers 8 to 64-bit long.
10038  *
10039  * Last argument (ctx->args) is retrieved to determine integer type and
10040  * storage location.
10041  */
10042 static int
10043 parse_int(struct context *ctx, const struct token *token,
10044 	  const char *str, unsigned int len,
10045 	  void *buf, unsigned int size)
10046 {
10047 	const struct arg *arg = pop_args(ctx);
10048 	uintmax_t u;
10049 	char *end;
10050 
10051 	(void)token;
10052 	/* Argument is expected. */
10053 	if (!arg)
10054 		return -1;
10055 	errno = 0;
10056 	u = arg->sign ?
10057 		(uintmax_t)strtoimax(str, &end, 0) :
10058 		strtoumax(str, &end, 0);
10059 	if (errno || (size_t)(end - str) != len)
10060 		goto error;
10061 	if (arg->bounded &&
10062 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
10063 			    (intmax_t)u > (intmax_t)arg->max)) ||
10064 	     (!arg->sign && (u < arg->min || u > arg->max))))
10065 		goto error;
10066 	if (!ctx->object)
10067 		return len;
10068 	if (arg->mask) {
10069 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
10070 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
10071 			goto error;
10072 		return len;
10073 	}
10074 	buf = (uint8_t *)ctx->object + arg->offset;
10075 	size = arg->size;
10076 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
10077 		return -1;
10078 objmask:
10079 	switch (size) {
10080 	case sizeof(uint8_t):
10081 		*(uint8_t *)buf = u;
10082 		break;
10083 	case sizeof(uint16_t):
10084 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
10085 		break;
10086 	case sizeof(uint8_t [3]):
10087 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
10088 		if (!arg->hton) {
10089 			((uint8_t *)buf)[0] = u;
10090 			((uint8_t *)buf)[1] = u >> 8;
10091 			((uint8_t *)buf)[2] = u >> 16;
10092 			break;
10093 		}
10094 #endif
10095 		((uint8_t *)buf)[0] = u >> 16;
10096 		((uint8_t *)buf)[1] = u >> 8;
10097 		((uint8_t *)buf)[2] = u;
10098 		break;
10099 	case sizeof(uint32_t):
10100 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
10101 		break;
10102 	case sizeof(uint64_t):
10103 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
10104 		break;
10105 	default:
10106 		goto error;
10107 	}
10108 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
10109 		u = -1;
10110 		buf = (uint8_t *)ctx->objmask + arg->offset;
10111 		goto objmask;
10112 	}
10113 	return len;
10114 error:
10115 	push_args(ctx, arg);
10116 	return -1;
10117 }
10118 
10119 /**
10120  * Parse a string.
10121  *
10122  * Three arguments (ctx->args) are retrieved from the stack to store data,
10123  * its actual length and address (in that order).
10124  */
10125 static int
10126 parse_string(struct context *ctx, const struct token *token,
10127 	     const char *str, unsigned int len,
10128 	     void *buf, unsigned int size)
10129 {
10130 	const struct arg *arg_data = pop_args(ctx);
10131 	const struct arg *arg_len = pop_args(ctx);
10132 	const struct arg *arg_addr = pop_args(ctx);
10133 	char tmp[16]; /* Ought to be enough. */
10134 	int ret;
10135 
10136 	/* Arguments are expected. */
10137 	if (!arg_data)
10138 		return -1;
10139 	if (!arg_len) {
10140 		push_args(ctx, arg_data);
10141 		return -1;
10142 	}
10143 	if (!arg_addr) {
10144 		push_args(ctx, arg_len);
10145 		push_args(ctx, arg_data);
10146 		return -1;
10147 	}
10148 	size = arg_data->size;
10149 	/* Bit-mask fill is not supported. */
10150 	if (arg_data->mask || size < len)
10151 		goto error;
10152 	if (!ctx->object)
10153 		return len;
10154 	/* Let parse_int() fill length information first. */
10155 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
10156 	if (ret < 0)
10157 		goto error;
10158 	push_args(ctx, arg_len);
10159 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
10160 	if (ret < 0) {
10161 		pop_args(ctx);
10162 		goto error;
10163 	}
10164 	buf = (uint8_t *)ctx->object + arg_data->offset;
10165 	/* Output buffer is not necessarily NUL-terminated. */
10166 	memcpy(buf, str, len);
10167 	memset((uint8_t *)buf + len, 0x00, size - len);
10168 	if (ctx->objmask)
10169 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
10170 	/* Save address if requested. */
10171 	if (arg_addr->size) {
10172 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
10173 		       (void *[]){
10174 			(uint8_t *)ctx->object + arg_data->offset
10175 		       },
10176 		       arg_addr->size);
10177 		if (ctx->objmask)
10178 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
10179 			       (void *[]){
10180 				(uint8_t *)ctx->objmask + arg_data->offset
10181 			       },
10182 			       arg_addr->size);
10183 	}
10184 	return len;
10185 error:
10186 	push_args(ctx, arg_addr);
10187 	push_args(ctx, arg_len);
10188 	push_args(ctx, arg_data);
10189 	return -1;
10190 }
10191 
10192 static int
10193 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
10194 {
10195 	const uint8_t *head = dst;
10196 	uint32_t left;
10197 
10198 	if (*size == 0)
10199 		return -1;
10200 
10201 	left = *size;
10202 
10203 	/* Convert chars to bytes */
10204 	while (left) {
10205 		char tmp[3], *end = tmp;
10206 		uint32_t read_lim = left & 1 ? 1 : 2;
10207 
10208 		snprintf(tmp, read_lim + 1, "%s", src);
10209 		*dst = strtoul(tmp, &end, 16);
10210 		if (*end) {
10211 			*dst = 0;
10212 			*size = (uint32_t)(dst - head);
10213 			return -1;
10214 		}
10215 		left -= read_lim;
10216 		src += read_lim;
10217 		dst++;
10218 	}
10219 	*dst = 0;
10220 	*size = (uint32_t)(dst - head);
10221 	return 0;
10222 }
10223 
10224 static int
10225 parse_hex(struct context *ctx, const struct token *token,
10226 		const char *str, unsigned int len,
10227 		void *buf, unsigned int size)
10228 {
10229 	const struct arg *arg_data = pop_args(ctx);
10230 	const struct arg *arg_len = pop_args(ctx);
10231 	const struct arg *arg_addr = pop_args(ctx);
10232 	char tmp[16]; /* Ought to be enough. */
10233 	int ret;
10234 	unsigned int hexlen = len;
10235 	unsigned int length = 256;
10236 	uint8_t hex_tmp[length];
10237 
10238 	/* Arguments are expected. */
10239 	if (!arg_data)
10240 		return -1;
10241 	if (!arg_len) {
10242 		push_args(ctx, arg_data);
10243 		return -1;
10244 	}
10245 	if (!arg_addr) {
10246 		push_args(ctx, arg_len);
10247 		push_args(ctx, arg_data);
10248 		return -1;
10249 	}
10250 	size = arg_data->size;
10251 	/* Bit-mask fill is not supported. */
10252 	if (arg_data->mask)
10253 		goto error;
10254 	if (!ctx->object)
10255 		return len;
10256 
10257 	/* translate bytes string to array. */
10258 	if (str[0] == '0' && ((str[1] == 'x') ||
10259 			(str[1] == 'X'))) {
10260 		str += 2;
10261 		hexlen -= 2;
10262 	}
10263 	if (hexlen > length)
10264 		goto error;
10265 	ret = parse_hex_string(str, hex_tmp, &hexlen);
10266 	if (ret < 0)
10267 		goto error;
10268 	/* Check the converted binary fits into data buffer. */
10269 	if (hexlen > size)
10270 		goto error;
10271 	/* Let parse_int() fill length information first. */
10272 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
10273 	if (ret < 0)
10274 		goto error;
10275 	/* Save length if requested. */
10276 	if (arg_len->size) {
10277 		push_args(ctx, arg_len);
10278 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
10279 		if (ret < 0) {
10280 			pop_args(ctx);
10281 			goto error;
10282 		}
10283 	}
10284 	buf = (uint8_t *)ctx->object + arg_data->offset;
10285 	/* Output buffer is not necessarily NUL-terminated. */
10286 	memcpy(buf, hex_tmp, hexlen);
10287 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
10288 	if (ctx->objmask)
10289 		memset((uint8_t *)ctx->objmask + arg_data->offset,
10290 					0xff, hexlen);
10291 	/* Save address if requested. */
10292 	if (arg_addr->size) {
10293 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
10294 		       (void *[]){
10295 			(uint8_t *)ctx->object + arg_data->offset
10296 		       },
10297 		       arg_addr->size);
10298 		if (ctx->objmask)
10299 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
10300 			       (void *[]){
10301 				(uint8_t *)ctx->objmask + arg_data->offset
10302 			       },
10303 			       arg_addr->size);
10304 	}
10305 	return len;
10306 error:
10307 	push_args(ctx, arg_addr);
10308 	push_args(ctx, arg_len);
10309 	push_args(ctx, arg_data);
10310 	return -1;
10311 
10312 }
10313 
10314 /**
10315  * Parse a zero-ended string.
10316  */
10317 static int
10318 parse_string0(struct context *ctx, const struct token *token __rte_unused,
10319 	     const char *str, unsigned int len,
10320 	     void *buf, unsigned int size)
10321 {
10322 	const struct arg *arg_data = pop_args(ctx);
10323 
10324 	/* Arguments are expected. */
10325 	if (!arg_data)
10326 		return -1;
10327 	size = arg_data->size;
10328 	/* Bit-mask fill is not supported. */
10329 	if (arg_data->mask || size < len + 1)
10330 		goto error;
10331 	if (!ctx->object)
10332 		return len;
10333 	buf = (uint8_t *)ctx->object + arg_data->offset;
10334 	strncpy(buf, str, len);
10335 	if (ctx->objmask)
10336 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
10337 	return len;
10338 error:
10339 	push_args(ctx, arg_data);
10340 	return -1;
10341 }
10342 
10343 /**
10344  * Parse a MAC address.
10345  *
10346  * Last argument (ctx->args) is retrieved to determine storage size and
10347  * location.
10348  */
10349 static int
10350 parse_mac_addr(struct context *ctx, const struct token *token,
10351 	       const char *str, unsigned int len,
10352 	       void *buf, unsigned int size)
10353 {
10354 	const struct arg *arg = pop_args(ctx);
10355 	struct rte_ether_addr tmp;
10356 	int ret;
10357 
10358 	(void)token;
10359 	/* Argument is expected. */
10360 	if (!arg)
10361 		return -1;
10362 	size = arg->size;
10363 	/* Bit-mask fill is not supported. */
10364 	if (arg->mask || size != sizeof(tmp))
10365 		goto error;
10366 	/* Only network endian is supported. */
10367 	if (!arg->hton)
10368 		goto error;
10369 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
10370 	if (ret < 0 || (unsigned int)ret != len)
10371 		goto error;
10372 	if (!ctx->object)
10373 		return len;
10374 	buf = (uint8_t *)ctx->object + arg->offset;
10375 	memcpy(buf, &tmp, size);
10376 	if (ctx->objmask)
10377 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
10378 	return len;
10379 error:
10380 	push_args(ctx, arg);
10381 	return -1;
10382 }
10383 
10384 /**
10385  * Parse an IPv4 address.
10386  *
10387  * Last argument (ctx->args) is retrieved to determine storage size and
10388  * location.
10389  */
10390 static int
10391 parse_ipv4_addr(struct context *ctx, const struct token *token,
10392 		const char *str, unsigned int len,
10393 		void *buf, unsigned int size)
10394 {
10395 	const struct arg *arg = pop_args(ctx);
10396 	char str2[len + 1];
10397 	struct in_addr tmp;
10398 	int ret;
10399 
10400 	/* Argument is expected. */
10401 	if (!arg)
10402 		return -1;
10403 	size = arg->size;
10404 	/* Bit-mask fill is not supported. */
10405 	if (arg->mask || size != sizeof(tmp))
10406 		goto error;
10407 	/* Only network endian is supported. */
10408 	if (!arg->hton)
10409 		goto error;
10410 	memcpy(str2, str, len);
10411 	str2[len] = '\0';
10412 	ret = inet_pton(AF_INET, str2, &tmp);
10413 	if (ret != 1) {
10414 		/* Attempt integer parsing. */
10415 		push_args(ctx, arg);
10416 		return parse_int(ctx, token, str, len, buf, size);
10417 	}
10418 	if (!ctx->object)
10419 		return len;
10420 	buf = (uint8_t *)ctx->object + arg->offset;
10421 	memcpy(buf, &tmp, size);
10422 	if (ctx->objmask)
10423 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
10424 	return len;
10425 error:
10426 	push_args(ctx, arg);
10427 	return -1;
10428 }
10429 
10430 /**
10431  * Parse an IPv6 address.
10432  *
10433  * Last argument (ctx->args) is retrieved to determine storage size and
10434  * location.
10435  */
10436 static int
10437 parse_ipv6_addr(struct context *ctx, const struct token *token,
10438 		const char *str, unsigned int len,
10439 		void *buf, unsigned int size)
10440 {
10441 	const struct arg *arg = pop_args(ctx);
10442 	char str2[len + 1];
10443 	struct in6_addr tmp;
10444 	int ret;
10445 
10446 	(void)token;
10447 	/* Argument is expected. */
10448 	if (!arg)
10449 		return -1;
10450 	size = arg->size;
10451 	/* Bit-mask fill is not supported. */
10452 	if (arg->mask || size != sizeof(tmp))
10453 		goto error;
10454 	/* Only network endian is supported. */
10455 	if (!arg->hton)
10456 		goto error;
10457 	memcpy(str2, str, len);
10458 	str2[len] = '\0';
10459 	ret = inet_pton(AF_INET6, str2, &tmp);
10460 	if (ret != 1)
10461 		goto error;
10462 	if (!ctx->object)
10463 		return len;
10464 	buf = (uint8_t *)ctx->object + arg->offset;
10465 	memcpy(buf, &tmp, size);
10466 	if (ctx->objmask)
10467 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
10468 	return len;
10469 error:
10470 	push_args(ctx, arg);
10471 	return -1;
10472 }
10473 
10474 /** Boolean values (even indices stand for false). */
10475 static const char *const boolean_name[] = {
10476 	"0", "1",
10477 	"false", "true",
10478 	"no", "yes",
10479 	"N", "Y",
10480 	"off", "on",
10481 	NULL,
10482 };
10483 
10484 /**
10485  * Parse a boolean value.
10486  *
10487  * Last argument (ctx->args) is retrieved to determine storage size and
10488  * location.
10489  */
10490 static int
10491 parse_boolean(struct context *ctx, const struct token *token,
10492 	      const char *str, unsigned int len,
10493 	      void *buf, unsigned int size)
10494 {
10495 	const struct arg *arg = pop_args(ctx);
10496 	unsigned int i;
10497 	int ret;
10498 
10499 	/* Argument is expected. */
10500 	if (!arg)
10501 		return -1;
10502 	for (i = 0; boolean_name[i]; ++i)
10503 		if (!strcmp_partial(boolean_name[i], str, len))
10504 			break;
10505 	/* Process token as integer. */
10506 	if (boolean_name[i])
10507 		str = i & 1 ? "1" : "0";
10508 	push_args(ctx, arg);
10509 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
10510 	return ret > 0 ? (int)len : ret;
10511 }
10512 
10513 /** Parse port and update context. */
10514 static int
10515 parse_port(struct context *ctx, const struct token *token,
10516 	   const char *str, unsigned int len,
10517 	   void *buf, unsigned int size)
10518 {
10519 	struct buffer *out = &(struct buffer){ .port = 0 };
10520 	int ret;
10521 
10522 	if (buf)
10523 		out = buf;
10524 	else {
10525 		ctx->objdata = 0;
10526 		ctx->object = out;
10527 		ctx->objmask = NULL;
10528 		size = sizeof(*out);
10529 	}
10530 	ret = parse_int(ctx, token, str, len, out, size);
10531 	if (ret >= 0)
10532 		ctx->port = out->port;
10533 	if (!buf)
10534 		ctx->object = NULL;
10535 	return ret;
10536 }
10537 
10538 /** Parse tokens for shared indirect actions. */
10539 static int
10540 parse_ia_port(struct context *ctx, const struct token *token,
10541 	      const char *str, unsigned int len,
10542 	      void *buf, unsigned int size)
10543 {
10544 	struct rte_flow_action *action = ctx->object;
10545 	uint32_t id;
10546 	int ret;
10547 
10548 	(void)buf;
10549 	(void)size;
10550 	ctx->objdata = 0;
10551 	ctx->object = &id;
10552 	ctx->objmask = NULL;
10553 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10554 	ctx->object = action;
10555 	if (ret != (int)len)
10556 		return ret;
10557 	/* set indirect action */
10558 	if (action)
10559 		action->conf = (void *)(uintptr_t)id;
10560 	return ret;
10561 }
10562 
10563 static int
10564 parse_ia_id2ptr(struct context *ctx, const struct token *token,
10565 		const char *str, unsigned int len,
10566 		void *buf, unsigned int size)
10567 {
10568 	struct rte_flow_action *action = ctx->object;
10569 	uint32_t id;
10570 	int ret;
10571 
10572 	(void)buf;
10573 	(void)size;
10574 	ctx->objdata = 0;
10575 	ctx->object = &id;
10576 	ctx->objmask = NULL;
10577 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10578 	ctx->object = action;
10579 	if (ret != (int)len)
10580 		return ret;
10581 	/* set indirect action */
10582 	if (action) {
10583 		portid_t port_id = ctx->port;
10584 		if (ctx->prev == INDIRECT_ACTION_PORT)
10585 			port_id = (portid_t)(uintptr_t)action->conf;
10586 		action->conf = port_action_handle_get_by_id(port_id, id);
10587 		ret = (action->conf) ? ret : -1;
10588 	}
10589 	return ret;
10590 }
10591 
10592 static int
10593 parse_indlst_id2ptr(struct context *ctx, const struct token *token,
10594 		    const char *str, unsigned int len,
10595 		    __rte_unused void *buf, __rte_unused unsigned int size)
10596 {
10597 	struct rte_flow_action *action = ctx->object;
10598 	struct rte_flow_action_indirect_list *action_conf;
10599 	const struct indlst_conf *indlst_conf;
10600 	uint32_t id;
10601 	int ret;
10602 
10603 	if (!action)
10604 		return -1;
10605 	ctx->objdata = 0;
10606 	ctx->object = &id;
10607 	ctx->objmask = NULL;
10608 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10609 	if (ret != (int)len)
10610 		return ret;
10611 	ctx->object = action;
10612 	action_conf = (void *)(uintptr_t)action->conf;
10613 	action_conf->conf = NULL;
10614 	switch (ctx->curr) {
10615 	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
10616 	action_conf->handle = (typeof(action_conf->handle))
10617 				port_action_handle_get_by_id(ctx->port, id);
10618 		if (!action_conf->handle) {
10619 			printf("no indirect list handle for id %u\n", id);
10620 			return -1;
10621 		}
10622 		break;
10623 	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
10624 		indlst_conf = indirect_action_list_conf_get(id);
10625 		if (!indlst_conf)
10626 			return -1;
10627 		action_conf->conf = (const void **)indlst_conf->conf;
10628 		break;
10629 	default:
10630 		break;
10631 	}
10632 	return ret;
10633 }
10634 
10635 static int
10636 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
10637 		const char *str, unsigned int len,
10638 		void *buf, unsigned int size)
10639 {
10640 	struct rte_flow_action *action = ctx->object;
10641 	struct rte_flow_action_meter_mark *meter;
10642 	struct rte_flow_meter_profile *profile = NULL;
10643 	uint32_t id = 0;
10644 	int ret;
10645 
10646 	(void)buf;
10647 	(void)size;
10648 	ctx->objdata = 0;
10649 	ctx->object = &id;
10650 	ctx->objmask = NULL;
10651 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10652 	ctx->object = action;
10653 	if (ret != (int)len)
10654 		return ret;
10655 	/* set meter profile */
10656 	if (action) {
10657 		meter = (struct rte_flow_action_meter_mark *)
10658 			(uintptr_t)(action->conf);
10659 		profile = port_meter_profile_get_by_id(ctx->port, id);
10660 		meter->profile = profile;
10661 		ret = (profile) ? ret : -1;
10662 	}
10663 	return ret;
10664 }
10665 
10666 static int
10667 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token,
10668 		const char *str, unsigned int len,
10669 		void *buf, unsigned int size)
10670 {
10671 	struct rte_flow_action *action = ctx->object;
10672 	struct rte_flow_action_meter_mark *meter;
10673 	struct rte_flow_meter_policy *policy = NULL;
10674 	uint32_t id = 0;
10675 	int ret;
10676 
10677 	(void)buf;
10678 	(void)size;
10679 	ctx->objdata = 0;
10680 	ctx->object = &id;
10681 	ctx->objmask = NULL;
10682 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
10683 	ctx->object = action;
10684 	if (ret != (int)len)
10685 		return ret;
10686 	/* set meter policy */
10687 	if (action) {
10688 		meter = (struct rte_flow_action_meter_mark *)
10689 			(uintptr_t)(action->conf);
10690 		policy = port_meter_policy_get_by_id(ctx->port, id);
10691 		meter->policy = policy;
10692 		ret = (policy) ? ret : -1;
10693 	}
10694 	return ret;
10695 }
10696 
10697 /** Parse set command, initialize output buffer for subsequent tokens. */
10698 static int
10699 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
10700 			  const char *str, unsigned int len,
10701 			  void *buf, unsigned int size)
10702 {
10703 	struct buffer *out = buf;
10704 
10705 	/* Token name must match. */
10706 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10707 		return -1;
10708 	/* Nothing else to do if there is no buffer. */
10709 	if (!out)
10710 		return len;
10711 	/* Make sure buffer is large enough. */
10712 	if (size < sizeof(*out))
10713 		return -1;
10714 	ctx->objdata = 0;
10715 	ctx->objmask = NULL;
10716 	ctx->object = out;
10717 	if (!out->command)
10718 		return -1;
10719 	out->command = ctx->curr;
10720 	/* For encap/decap we need is pattern */
10721 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10722 						       sizeof(double));
10723 	return len;
10724 }
10725 
10726 /** Parse set command, initialize output buffer for subsequent tokens. */
10727 static int
10728 parse_set_sample_action(struct context *ctx, const struct token *token,
10729 			  const char *str, unsigned int len,
10730 			  void *buf, unsigned int size)
10731 {
10732 	struct buffer *out = buf;
10733 
10734 	/* Token name must match. */
10735 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10736 		return -1;
10737 	/* Nothing else to do if there is no buffer. */
10738 	if (!out)
10739 		return len;
10740 	/* Make sure buffer is large enough. */
10741 	if (size < sizeof(*out))
10742 		return -1;
10743 	ctx->objdata = 0;
10744 	ctx->objmask = NULL;
10745 	ctx->object = out;
10746 	if (!out->command)
10747 		return -1;
10748 	out->command = ctx->curr;
10749 	/* For sampler we need is actions */
10750 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10751 						       sizeof(double));
10752 	return len;
10753 }
10754 
10755 /**
10756  * Parse set raw_encap/raw_decap command,
10757  * initialize output buffer for subsequent tokens.
10758  */
10759 static int
10760 parse_set_init(struct context *ctx, const struct token *token,
10761 	       const char *str, unsigned int len,
10762 	       void *buf, unsigned int size)
10763 {
10764 	struct buffer *out = buf;
10765 
10766 	/* Token name must match. */
10767 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
10768 		return -1;
10769 	/* Nothing else to do if there is no buffer. */
10770 	if (!out)
10771 		return len;
10772 	/* Make sure buffer is large enough. */
10773 	if (size < sizeof(*out))
10774 		return -1;
10775 	/* Initialize buffer. */
10776 	memset(out, 0x00, sizeof(*out));
10777 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
10778 	ctx->objdata = 0;
10779 	ctx->object = out;
10780 	ctx->objmask = NULL;
10781 	if (!out->command) {
10782 		if (ctx->curr != SET)
10783 			return -1;
10784 		if (sizeof(*out) > size)
10785 			return -1;
10786 		out->command = ctx->curr;
10787 		out->args.vc.data = (uint8_t *)out + size;
10788 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
10789 						       sizeof(double));
10790 	}
10791 	return len;
10792 }
10793 
10794 /*
10795  * Replace testpmd handles in a flex flow item with real values.
10796  */
10797 static int
10798 parse_flex_handle(struct context *ctx, const struct token *token,
10799 		  const char *str, unsigned int len,
10800 		  void *buf, unsigned int size)
10801 {
10802 	struct rte_flow_item_flex *spec, *mask;
10803 	const struct rte_flow_item_flex *src_spec, *src_mask;
10804 	const struct arg *arg = pop_args(ctx);
10805 	uint32_t offset;
10806 	uint16_t handle;
10807 	int ret;
10808 
10809 	if (!arg) {
10810 		printf("Bad environment\n");
10811 		return -1;
10812 	}
10813 	offset = arg->offset;
10814 	push_args(ctx, arg);
10815 	ret = parse_int(ctx, token, str, len, buf, size);
10816 	if (ret <= 0 || !ctx->object)
10817 		return ret;
10818 	if (ctx->port >= RTE_MAX_ETHPORTS) {
10819 		printf("Bad port\n");
10820 		return -1;
10821 	}
10822 	if (offset == offsetof(struct rte_flow_item_flex, handle)) {
10823 		const struct flex_item *fp;
10824 		spec = ctx->object;
10825 		handle = (uint16_t)(uintptr_t)spec->handle;
10826 		if (handle >= FLEX_MAX_PARSERS_NUM) {
10827 			printf("Bad flex item handle\n");
10828 			return -1;
10829 		}
10830 		fp = flex_items[ctx->port][handle];
10831 		if (!fp) {
10832 			printf("Bad flex item handle\n");
10833 			return -1;
10834 		}
10835 		spec->handle = fp->flex_handle;
10836 		mask = spec + 2; /* spec, last, mask */
10837 		mask->handle = fp->flex_handle;
10838 	} else if (offset == offsetof(struct rte_flow_item_flex, pattern)) {
10839 		handle = (uint16_t)(uintptr_t)
10840 			((struct rte_flow_item_flex *)ctx->object)->pattern;
10841 		if (handle >= FLEX_MAX_PATTERNS_NUM) {
10842 			printf("Bad pattern handle\n");
10843 			return -1;
10844 		}
10845 		src_spec = &flex_patterns[handle].spec;
10846 		src_mask = &flex_patterns[handle].mask;
10847 		spec = ctx->object;
10848 		mask = spec + 2; /* spec, last, mask */
10849 		/* fill flow rule spec and mask parameters */
10850 		spec->length = src_spec->length;
10851 		spec->pattern = src_spec->pattern;
10852 		mask->length = src_mask->length;
10853 		mask->pattern = src_mask->pattern;
10854 	} else {
10855 		printf("Bad arguments - unknown flex item offset\n");
10856 		return -1;
10857 	}
10858 	return ret;
10859 }
10860 
10861 /** Parse Meter color name */
10862 static int
10863 parse_meter_color(struct context *ctx, const struct token *token,
10864 		  const char *str, unsigned int len, void *buf,
10865 		  unsigned int size)
10866 {
10867 	struct rte_flow_item_meter_color *meter_color;
10868 	unsigned int i;
10869 
10870 	(void)token;
10871 	(void)buf;
10872 	(void)size;
10873 	for (i = 0; meter_colors[i]; ++i)
10874 		if (!strcmp_partial(meter_colors[i], str, len))
10875 			break;
10876 	if (!meter_colors[i])
10877 		return -1;
10878 	if (!ctx->object)
10879 		return len;
10880 	meter_color = ctx->object;
10881 	meter_color->color = (enum rte_color)i;
10882 	return len;
10883 }
10884 
10885 /** Parse Insertion Table Type name */
10886 static int
10887 parse_insertion_table_type(struct context *ctx, const struct token *token,
10888 			   const char *str, unsigned int len, void *buf,
10889 			   unsigned int size)
10890 {
10891 	const struct arg *arg = pop_args(ctx);
10892 	unsigned int i;
10893 	char tmp[2];
10894 	int ret;
10895 
10896 	(void)size;
10897 	/* Argument is expected. */
10898 	if (!arg)
10899 		return -1;
10900 	for (i = 0; table_insertion_types[i]; ++i)
10901 		if (!strcmp_partial(table_insertion_types[i], str, len))
10902 			break;
10903 	if (!table_insertion_types[i])
10904 		return -1;
10905 	push_args(ctx, arg);
10906 	snprintf(tmp, sizeof(tmp), "%u", i);
10907 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
10908 	return ret > 0 ? (int)len : ret;
10909 }
10910 
10911 /** Parse Hash Calculation Table Type name */
10912 static int
10913 parse_hash_table_type(struct context *ctx, const struct token *token,
10914 		      const char *str, unsigned int len, void *buf,
10915 		      unsigned int size)
10916 {
10917 	const struct arg *arg = pop_args(ctx);
10918 	unsigned int i;
10919 	char tmp[2];
10920 	int ret;
10921 
10922 	(void)size;
10923 	/* Argument is expected. */
10924 	if (!arg)
10925 		return -1;
10926 	for (i = 0; table_hash_funcs[i]; ++i)
10927 		if (!strcmp_partial(table_hash_funcs[i], str, len))
10928 			break;
10929 	if (!table_hash_funcs[i])
10930 		return -1;
10931 	push_args(ctx, arg);
10932 	snprintf(tmp, sizeof(tmp), "%u", i);
10933 	ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i));
10934 	return ret > 0 ? (int)len : ret;
10935 }
10936 
10937 static int
10938 parse_name_to_index(struct context *ctx, const struct token *token,
10939 		    const char *str, unsigned int len, void *buf,
10940 		    unsigned int size,
10941 		    const char *const names[], size_t names_size, uint32_t *dst)
10942 {
10943 	int ret;
10944 	uint32_t i;
10945 
10946 	RTE_SET_USED(token);
10947 	RTE_SET_USED(buf);
10948 	RTE_SET_USED(size);
10949 	if (!ctx->object)
10950 		return len;
10951 	for (i = 0; i < names_size; i++) {
10952 		if (!names[i])
10953 			continue;
10954 		ret = strcmp_partial(names[i], str,
10955 				     RTE_MIN(len, strlen(names[i])));
10956 		if (!ret) {
10957 			*dst = i;
10958 			return len;
10959 		}
10960 	}
10961 	return -1;
10962 }
10963 
10964 static const char *const quota_mode_names[] = {
10965 	NULL,
10966 	[RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
10967 	[RTE_FLOW_QUOTA_MODE_L2] = "l2",
10968 	[RTE_FLOW_QUOTA_MODE_L3] = "l3"
10969 };
10970 
10971 static const char *const quota_state_names[] = {
10972 	[RTE_FLOW_QUOTA_STATE_PASS] = "pass",
10973 	[RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
10974 };
10975 
10976 static const char *const quota_update_names[] = {
10977 	[RTE_FLOW_UPDATE_QUOTA_SET] = "set",
10978 	[RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
10979 };
10980 
10981 static const char *const query_update_mode_names[] = {
10982 	[RTE_FLOW_QU_QUERY_FIRST] = "query_first",
10983 	[RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
10984 };
10985 
10986 static int
10987 parse_quota_state_name(struct context *ctx, const struct token *token,
10988 		       const char *str, unsigned int len, void *buf,
10989 		       unsigned int size)
10990 {
10991 	struct rte_flow_item_quota *quota = ctx->object;
10992 
10993 	return parse_name_to_index(ctx, token, str, len, buf, size,
10994 				   quota_state_names,
10995 				   RTE_DIM(quota_state_names),
10996 				   (uint32_t *)&quota->state);
10997 }
10998 
10999 static int
11000 parse_quota_mode_name(struct context *ctx, const struct token *token,
11001 		      const char *str, unsigned int len, void *buf,
11002 		      unsigned int size)
11003 {
11004 	struct rte_flow_action_quota *quota = ctx->object;
11005 
11006 	return parse_name_to_index(ctx, token, str, len, buf, size,
11007 				   quota_mode_names,
11008 				   RTE_DIM(quota_mode_names),
11009 				   (uint32_t *)&quota->mode);
11010 }
11011 
11012 static int
11013 parse_quota_update_name(struct context *ctx, const struct token *token,
11014 			const char *str, unsigned int len, void *buf,
11015 			unsigned int size)
11016 {
11017 	struct rte_flow_update_quota *update = ctx->object;
11018 
11019 	return parse_name_to_index(ctx, token, str, len, buf, size,
11020 				   quota_update_names,
11021 				   RTE_DIM(quota_update_names),
11022 				   (uint32_t *)&update->op);
11023 }
11024 
11025 static int
11026 parse_qu_mode_name(struct context *ctx, const struct token *token,
11027 		   const char *str, unsigned int len, void *buf,
11028 		   unsigned int size)
11029 {
11030 	struct buffer *out = ctx->object;
11031 
11032 	return parse_name_to_index(ctx, token, str, len, buf, size,
11033 				   query_update_mode_names,
11034 				   RTE_DIM(query_update_mode_names),
11035 				   (uint32_t *)&out->args.ia.qu_mode);
11036 }
11037 
11038 /** No completion. */
11039 static int
11040 comp_none(struct context *ctx, const struct token *token,
11041 	  unsigned int ent, char *buf, unsigned int size)
11042 {
11043 	(void)ctx;
11044 	(void)token;
11045 	(void)ent;
11046 	(void)buf;
11047 	(void)size;
11048 	return 0;
11049 }
11050 
11051 /** Complete boolean values. */
11052 static int
11053 comp_boolean(struct context *ctx, const struct token *token,
11054 	     unsigned int ent, char *buf, unsigned int size)
11055 {
11056 	unsigned int i;
11057 
11058 	(void)ctx;
11059 	(void)token;
11060 	for (i = 0; boolean_name[i]; ++i)
11061 		if (buf && i == ent)
11062 			return strlcpy(buf, boolean_name[i], size);
11063 	if (buf)
11064 		return -1;
11065 	return i;
11066 }
11067 
11068 /** Complete action names. */
11069 static int
11070 comp_action(struct context *ctx, const struct token *token,
11071 	    unsigned int ent, char *buf, unsigned int size)
11072 {
11073 	unsigned int i;
11074 
11075 	(void)ctx;
11076 	(void)token;
11077 	for (i = 0; next_action[i]; ++i)
11078 		if (buf && i == ent)
11079 			return strlcpy(buf, token_list[next_action[i]].name,
11080 				       size);
11081 	if (buf)
11082 		return -1;
11083 	return i;
11084 }
11085 
11086 /** Complete available ports. */
11087 static int
11088 comp_port(struct context *ctx, const struct token *token,
11089 	  unsigned int ent, char *buf, unsigned int size)
11090 {
11091 	unsigned int i = 0;
11092 	portid_t p;
11093 
11094 	(void)ctx;
11095 	(void)token;
11096 	RTE_ETH_FOREACH_DEV(p) {
11097 		if (buf && i == ent)
11098 			return snprintf(buf, size, "%u", p);
11099 		++i;
11100 	}
11101 	if (buf)
11102 		return -1;
11103 	return i;
11104 }
11105 
11106 /** Complete available rule IDs. */
11107 static int
11108 comp_rule_id(struct context *ctx, const struct token *token,
11109 	     unsigned int ent, char *buf, unsigned int size)
11110 {
11111 	unsigned int i = 0;
11112 	struct rte_port *port;
11113 	struct port_flow *pf;
11114 
11115 	(void)token;
11116 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11117 	    ctx->port == (portid_t)RTE_PORT_ALL)
11118 		return -1;
11119 	port = &ports[ctx->port];
11120 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
11121 		if (buf && i == ent)
11122 			return snprintf(buf, size, "%u", pf->id);
11123 		++i;
11124 	}
11125 	if (buf)
11126 		return -1;
11127 	return i;
11128 }
11129 
11130 /** Complete type field for RSS action. */
11131 static int
11132 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
11133 			unsigned int ent, char *buf, unsigned int size)
11134 {
11135 	unsigned int i;
11136 
11137 	(void)ctx;
11138 	(void)token;
11139 	for (i = 0; rss_type_table[i].str; ++i)
11140 		;
11141 	if (!buf)
11142 		return i + 1;
11143 	if (ent < i)
11144 		return strlcpy(buf, rss_type_table[ent].str, size);
11145 	if (ent == i)
11146 		return snprintf(buf, size, "end");
11147 	return -1;
11148 }
11149 
11150 /** Complete queue field for RSS action. */
11151 static int
11152 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
11153 			 unsigned int ent, char *buf, unsigned int size)
11154 {
11155 	(void)ctx;
11156 	(void)token;
11157 	if (!buf)
11158 		return nb_rxq + 1;
11159 	if (ent < nb_rxq)
11160 		return snprintf(buf, size, "%u", ent);
11161 	if (ent == nb_rxq)
11162 		return snprintf(buf, size, "end");
11163 	return -1;
11164 }
11165 
11166 /** Complete index number for set raw_encap/raw_decap commands. */
11167 static int
11168 comp_set_raw_index(struct context *ctx, const struct token *token,
11169 		   unsigned int ent, char *buf, unsigned int size)
11170 {
11171 	uint16_t idx = 0;
11172 	uint16_t nb = 0;
11173 
11174 	RTE_SET_USED(ctx);
11175 	RTE_SET_USED(token);
11176 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
11177 		if (buf && idx == ent)
11178 			return snprintf(buf, size, "%u", idx);
11179 		++nb;
11180 	}
11181 	return nb;
11182 }
11183 
11184 /** Complete index number for set raw_encap/raw_decap commands. */
11185 static int
11186 comp_set_sample_index(struct context *ctx, const struct token *token,
11187 		   unsigned int ent, char *buf, unsigned int size)
11188 {
11189 	uint16_t idx = 0;
11190 	uint16_t nb = 0;
11191 
11192 	RTE_SET_USED(ctx);
11193 	RTE_SET_USED(token);
11194 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
11195 		if (buf && idx == ent)
11196 			return snprintf(buf, size, "%u", idx);
11197 		++nb;
11198 	}
11199 	return nb;
11200 }
11201 
11202 /** Complete operation for modify_field command. */
11203 static int
11204 comp_set_modify_field_op(struct context *ctx, const struct token *token,
11205 		   unsigned int ent, char *buf, unsigned int size)
11206 {
11207 	RTE_SET_USED(ctx);
11208 	RTE_SET_USED(token);
11209 	if (!buf)
11210 		return RTE_DIM(modify_field_ops);
11211 	if (ent < RTE_DIM(modify_field_ops) - 1)
11212 		return strlcpy(buf, modify_field_ops[ent], size);
11213 	return -1;
11214 }
11215 
11216 /** Complete field id for modify_field command. */
11217 static int
11218 comp_set_modify_field_id(struct context *ctx, const struct token *token,
11219 		   unsigned int ent, char *buf, unsigned int size)
11220 {
11221 	const char *name;
11222 
11223 	RTE_SET_USED(token);
11224 	if (!buf)
11225 		return RTE_DIM(modify_field_ids);
11226 	if (ent >= RTE_DIM(modify_field_ids) - 1)
11227 		return -1;
11228 	name = modify_field_ids[ent];
11229 	if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE ||
11230 	    (strcmp(name, "pointer") && strcmp(name, "value")))
11231 		return strlcpy(buf, name, size);
11232 	return -1;
11233 }
11234 
11235 /** Complete available pattern template IDs. */
11236 static int
11237 comp_pattern_template_id(struct context *ctx, const struct token *token,
11238 			 unsigned int ent, char *buf, unsigned int size)
11239 {
11240 	unsigned int i = 0;
11241 	struct rte_port *port;
11242 	struct port_template *pt;
11243 
11244 	(void)token;
11245 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11246 	    ctx->port == (portid_t)RTE_PORT_ALL)
11247 		return -1;
11248 	port = &ports[ctx->port];
11249 	for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) {
11250 		if (buf && i == ent)
11251 			return snprintf(buf, size, "%u", pt->id);
11252 		++i;
11253 	}
11254 	if (buf)
11255 		return -1;
11256 	return i;
11257 }
11258 
11259 /** Complete available actions template IDs. */
11260 static int
11261 comp_actions_template_id(struct context *ctx, const struct token *token,
11262 			 unsigned int ent, char *buf, unsigned int size)
11263 {
11264 	unsigned int i = 0;
11265 	struct rte_port *port;
11266 	struct port_template *pt;
11267 
11268 	(void)token;
11269 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11270 	    ctx->port == (portid_t)RTE_PORT_ALL)
11271 		return -1;
11272 	port = &ports[ctx->port];
11273 	for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) {
11274 		if (buf && i == ent)
11275 			return snprintf(buf, size, "%u", pt->id);
11276 		++i;
11277 	}
11278 	if (buf)
11279 		return -1;
11280 	return i;
11281 }
11282 
11283 /** Complete available table IDs. */
11284 static int
11285 comp_table_id(struct context *ctx, const struct token *token,
11286 	      unsigned int ent, char *buf, unsigned int size)
11287 {
11288 	unsigned int i = 0;
11289 	struct rte_port *port;
11290 	struct port_table *pt;
11291 
11292 	(void)token;
11293 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11294 	    ctx->port == (portid_t)RTE_PORT_ALL)
11295 		return -1;
11296 	port = &ports[ctx->port];
11297 	for (pt = port->table_list; pt != NULL; pt = pt->next) {
11298 		if (buf && i == ent)
11299 			return snprintf(buf, size, "%u", pt->id);
11300 		++i;
11301 	}
11302 	if (buf)
11303 		return -1;
11304 	return i;
11305 }
11306 
11307 /** Complete available queue IDs. */
11308 static int
11309 comp_queue_id(struct context *ctx, const struct token *token,
11310 	      unsigned int ent, char *buf, unsigned int size)
11311 {
11312 	unsigned int i = 0;
11313 	struct rte_port *port;
11314 
11315 	(void)token;
11316 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
11317 	    ctx->port == (portid_t)RTE_PORT_ALL)
11318 		return -1;
11319 	port = &ports[ctx->port];
11320 	for (i = 0; i < port->queue_nb; i++) {
11321 		if (buf && i == ent)
11322 			return snprintf(buf, size, "%u", i);
11323 	}
11324 	if (buf)
11325 		return -1;
11326 	return i;
11327 }
11328 
11329 static int
11330 comp_names_to_index(struct context *ctx, const struct token *token,
11331 		    unsigned int ent, char *buf, unsigned int size,
11332 		    const char *const names[], size_t names_size)
11333 {
11334 	RTE_SET_USED(ctx);
11335 	RTE_SET_USED(token);
11336 	if (!buf)
11337 		return names_size;
11338 	if (names[ent] && ent < names_size)
11339 		return rte_strscpy(buf, names[ent], size);
11340 	return -1;
11341 
11342 }
11343 
11344 /** Complete available Meter colors. */
11345 static int
11346 comp_meter_color(struct context *ctx, const struct token *token,
11347 		 unsigned int ent, char *buf, unsigned int size)
11348 {
11349 	RTE_SET_USED(ctx);
11350 	RTE_SET_USED(token);
11351 	if (!buf)
11352 		return RTE_DIM(meter_colors);
11353 	if (ent < RTE_DIM(meter_colors) - 1)
11354 		return strlcpy(buf, meter_colors[ent], size);
11355 	return -1;
11356 }
11357 
11358 /** Complete available Insertion Table types. */
11359 static int
11360 comp_insertion_table_type(struct context *ctx, const struct token *token,
11361 			  unsigned int ent, char *buf, unsigned int size)
11362 {
11363 	RTE_SET_USED(ctx);
11364 	RTE_SET_USED(token);
11365 	if (!buf)
11366 		return RTE_DIM(table_insertion_types);
11367 	if (ent < RTE_DIM(table_insertion_types) - 1)
11368 		return rte_strscpy(buf, table_insertion_types[ent], size);
11369 	return -1;
11370 }
11371 
11372 /** Complete available Hash Calculation Table types. */
11373 static int
11374 comp_hash_table_type(struct context *ctx, const struct token *token,
11375 		     unsigned int ent, char *buf, unsigned int size)
11376 {
11377 	RTE_SET_USED(ctx);
11378 	RTE_SET_USED(token);
11379 	if (!buf)
11380 		return RTE_DIM(table_hash_funcs);
11381 	if (ent < RTE_DIM(table_hash_funcs) - 1)
11382 		return rte_strscpy(buf, table_hash_funcs[ent], size);
11383 	return -1;
11384 }
11385 
11386 static int
11387 comp_quota_state_name(struct context *ctx, const struct token *token,
11388 		      unsigned int ent, char *buf, unsigned int size)
11389 {
11390 	return comp_names_to_index(ctx, token, ent, buf, size,
11391 				   quota_state_names,
11392 				   RTE_DIM(quota_state_names));
11393 }
11394 
11395 static int
11396 comp_quota_mode_name(struct context *ctx, const struct token *token,
11397 		     unsigned int ent, char *buf, unsigned int size)
11398 {
11399 	return comp_names_to_index(ctx, token, ent, buf, size,
11400 				   quota_mode_names,
11401 				   RTE_DIM(quota_mode_names));
11402 }
11403 
11404 static int
11405 comp_quota_update_name(struct context *ctx, const struct token *token,
11406 		       unsigned int ent, char *buf, unsigned int size)
11407 {
11408 	return comp_names_to_index(ctx, token, ent, buf, size,
11409 				   quota_update_names,
11410 				   RTE_DIM(quota_update_names));
11411 }
11412 
11413 static int
11414 comp_qu_mode_name(struct context *ctx, const struct token *token,
11415 		  unsigned int ent, char *buf, unsigned int size)
11416 {
11417 	return comp_names_to_index(ctx, token, ent, buf, size,
11418 				   query_update_mode_names,
11419 				   RTE_DIM(query_update_mode_names));
11420 }
11421 
11422 /** Internal context. */
11423 static struct context cmd_flow_context;
11424 
11425 /** Global parser instance (cmdline API). */
11426 cmdline_parse_inst_t cmd_flow;
11427 cmdline_parse_inst_t cmd_set_raw;
11428 
11429 /** Initialize context. */
11430 static void
11431 cmd_flow_context_init(struct context *ctx)
11432 {
11433 	/* A full memset() is not necessary. */
11434 	ctx->curr = ZERO;
11435 	ctx->prev = ZERO;
11436 	ctx->next_num = 0;
11437 	ctx->args_num = 0;
11438 	ctx->eol = 0;
11439 	ctx->last = 0;
11440 	ctx->port = 0;
11441 	ctx->objdata = 0;
11442 	ctx->object = NULL;
11443 	ctx->objmask = NULL;
11444 }
11445 
11446 /** Parse a token (cmdline API). */
11447 static int
11448 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
11449 	       unsigned int size)
11450 {
11451 	struct context *ctx = &cmd_flow_context;
11452 	const struct token *token;
11453 	const enum index *list;
11454 	int len;
11455 	int i;
11456 
11457 	(void)hdr;
11458 	token = &token_list[ctx->curr];
11459 	/* Check argument length. */
11460 	ctx->eol = 0;
11461 	ctx->last = 1;
11462 	for (len = 0; src[len]; ++len)
11463 		if (src[len] == '#' || isspace(src[len]))
11464 			break;
11465 	if (!len)
11466 		return -1;
11467 	/* Last argument and EOL detection. */
11468 	for (i = len; src[i]; ++i)
11469 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
11470 			break;
11471 		else if (!isspace(src[i])) {
11472 			ctx->last = 0;
11473 			break;
11474 		}
11475 	for (; src[i]; ++i)
11476 		if (src[i] == '\r' || src[i] == '\n') {
11477 			ctx->eol = 1;
11478 			break;
11479 		}
11480 	/* Initialize context if necessary. */
11481 	if (!ctx->next_num) {
11482 		if (!token->next)
11483 			return 0;
11484 		ctx->next[ctx->next_num++] = token->next[0];
11485 	}
11486 	/* Process argument through candidates. */
11487 	ctx->prev = ctx->curr;
11488 	list = ctx->next[ctx->next_num - 1];
11489 	for (i = 0; list[i]; ++i) {
11490 		const struct token *next = &token_list[list[i]];
11491 		int tmp;
11492 
11493 		ctx->curr = list[i];
11494 		if (next->call)
11495 			tmp = next->call(ctx, next, src, len, result, size);
11496 		else
11497 			tmp = parse_default(ctx, next, src, len, result, size);
11498 		if (tmp == -1 || tmp != len)
11499 			continue;
11500 		token = next;
11501 		break;
11502 	}
11503 	if (!list[i])
11504 		return -1;
11505 	--ctx->next_num;
11506 	/* Push subsequent tokens if any. */
11507 	if (token->next)
11508 		for (i = 0; token->next[i]; ++i) {
11509 			if (ctx->next_num == RTE_DIM(ctx->next))
11510 				return -1;
11511 			ctx->next[ctx->next_num++] = token->next[i];
11512 		}
11513 	/* Push arguments if any. */
11514 	if (token->args)
11515 		for (i = 0; token->args[i]; ++i) {
11516 			if (ctx->args_num == RTE_DIM(ctx->args))
11517 				return -1;
11518 			ctx->args[ctx->args_num++] = token->args[i];
11519 		}
11520 	return len;
11521 }
11522 
11523 int
11524 flow_parse(const char *src, void *result, unsigned int size,
11525 	   struct rte_flow_attr **attr,
11526 	   struct rte_flow_item **pattern, struct rte_flow_action **actions)
11527 {
11528 	int ret;
11529 	struct context saved_flow_ctx = cmd_flow_context;
11530 
11531 	cmd_flow_context_init(&cmd_flow_context);
11532 	do {
11533 		ret = cmd_flow_parse(NULL, src, result, size);
11534 		if (ret > 0) {
11535 			src += ret;
11536 			while (isspace(*src))
11537 				src++;
11538 		}
11539 	} while (ret > 0 && strlen(src));
11540 	cmd_flow_context = saved_flow_ctx;
11541 	*attr = &((struct buffer *)result)->args.vc.attr;
11542 	*pattern = ((struct buffer *)result)->args.vc.pattern;
11543 	*actions = ((struct buffer *)result)->args.vc.actions;
11544 	return (ret >= 0 && !strlen(src)) ? 0 : -1;
11545 }
11546 
11547 /** Return number of completion entries (cmdline API). */
11548 static int
11549 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
11550 {
11551 	struct context *ctx = &cmd_flow_context;
11552 	const struct token *token = &token_list[ctx->curr];
11553 	const enum index *list;
11554 	int i;
11555 
11556 	(void)hdr;
11557 	/* Count number of tokens in current list. */
11558 	if (ctx->next_num)
11559 		list = ctx->next[ctx->next_num - 1];
11560 	else
11561 		list = token->next[0];
11562 	for (i = 0; list[i]; ++i)
11563 		;
11564 	if (!i)
11565 		return 0;
11566 	/*
11567 	 * If there is a single token, use its completion callback, otherwise
11568 	 * return the number of entries.
11569 	 */
11570 	token = &token_list[list[0]];
11571 	if (i == 1 && token->comp) {
11572 		/* Save index for cmd_flow_get_help(). */
11573 		ctx->prev = list[0];
11574 		return token->comp(ctx, token, 0, NULL, 0);
11575 	}
11576 	return i;
11577 }
11578 
11579 /** Return a completion entry (cmdline API). */
11580 static int
11581 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
11582 			  char *dst, unsigned int size)
11583 {
11584 	struct context *ctx = &cmd_flow_context;
11585 	const struct token *token = &token_list[ctx->curr];
11586 	const enum index *list;
11587 	int i;
11588 
11589 	(void)hdr;
11590 	/* Count number of tokens in current list. */
11591 	if (ctx->next_num)
11592 		list = ctx->next[ctx->next_num - 1];
11593 	else
11594 		list = token->next[0];
11595 	for (i = 0; list[i]; ++i)
11596 		;
11597 	if (!i)
11598 		return -1;
11599 	/* If there is a single token, use its completion callback. */
11600 	token = &token_list[list[0]];
11601 	if (i == 1 && token->comp) {
11602 		/* Save index for cmd_flow_get_help(). */
11603 		ctx->prev = list[0];
11604 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
11605 	}
11606 	/* Otherwise make sure the index is valid and use defaults. */
11607 	if (index >= i)
11608 		return -1;
11609 	token = &token_list[list[index]];
11610 	strlcpy(dst, token->name, size);
11611 	/* Save index for cmd_flow_get_help(). */
11612 	ctx->prev = list[index];
11613 	return 0;
11614 }
11615 
11616 /** Populate help strings for current token (cmdline API). */
11617 static int
11618 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
11619 {
11620 	struct context *ctx = &cmd_flow_context;
11621 	const struct token *token = &token_list[ctx->prev];
11622 
11623 	(void)hdr;
11624 	if (!size)
11625 		return -1;
11626 	/* Set token type and update global help with details. */
11627 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
11628 	if (token->help)
11629 		cmd_flow.help_str = token->help;
11630 	else
11631 		cmd_flow.help_str = token->name;
11632 	return 0;
11633 }
11634 
11635 /** Token definition template (cmdline API). */
11636 static struct cmdline_token_hdr cmd_flow_token_hdr = {
11637 	.ops = &(struct cmdline_token_ops){
11638 		.parse = cmd_flow_parse,
11639 		.complete_get_nb = cmd_flow_complete_get_nb,
11640 		.complete_get_elt = cmd_flow_complete_get_elt,
11641 		.get_help = cmd_flow_get_help,
11642 	},
11643 	.offset = 0,
11644 };
11645 
11646 /** Populate the next dynamic token. */
11647 static void
11648 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
11649 	     cmdline_parse_token_hdr_t **hdr_inst)
11650 {
11651 	struct context *ctx = &cmd_flow_context;
11652 
11653 	/* Always reinitialize context before requesting the first token. */
11654 	if (!(hdr_inst - cmd_flow.tokens))
11655 		cmd_flow_context_init(ctx);
11656 	/* Return NULL when no more tokens are expected. */
11657 	if (!ctx->next_num && ctx->curr) {
11658 		*hdr = NULL;
11659 		return;
11660 	}
11661 	/* Determine if command should end here. */
11662 	if (ctx->eol && ctx->last && ctx->next_num) {
11663 		const enum index *list = ctx->next[ctx->next_num - 1];
11664 		int i;
11665 
11666 		for (i = 0; list[i]; ++i) {
11667 			if (list[i] != END)
11668 				continue;
11669 			*hdr = NULL;
11670 			return;
11671 		}
11672 	}
11673 	*hdr = &cmd_flow_token_hdr;
11674 }
11675 
11676 static SLIST_HEAD(, indlst_conf) indlst_conf_head =
11677 	SLIST_HEAD_INITIALIZER();
11678 
11679 static void
11680 indirect_action_flow_conf_create(const struct buffer *in)
11681 {
11682 	int len, ret;
11683 	uint32_t i;
11684 	struct indlst_conf *indlst_conf = NULL;
11685 	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
11686 	struct rte_flow_action *src = in->args.vc.actions;
11687 
11688 	if (!in->args.vc.actions_n)
11689 		goto end;
11690 	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
11691 	if (len <= 0)
11692 		goto end;
11693 	len = RTE_ALIGN(len, 16);
11694 
11695 	indlst_conf = calloc(1, base + len +
11696 			     in->args.vc.actions_n * sizeof(uintptr_t));
11697 	if (!indlst_conf)
11698 		goto end;
11699 	indlst_conf->id = in->args.vc.attr.group;
11700 	indlst_conf->conf_num = in->args.vc.actions_n - 1;
11701 	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
11702 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
11703 			    len, src, NULL);
11704 	if (ret <= 0) {
11705 		free(indlst_conf);
11706 		indlst_conf = NULL;
11707 		goto end;
11708 	}
11709 	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
11710 	for (i = 0; i < indlst_conf->conf_num; i++)
11711 		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
11712 	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
11713 end:
11714 	if (indlst_conf)
11715 		printf("created indirect action list configuration %u\n",
11716 		       in->args.vc.attr.group);
11717 	else
11718 		printf("cannot create indirect action list configuration %u\n",
11719 		       in->args.vc.attr.group);
11720 }
11721 
11722 static const struct indlst_conf *
11723 indirect_action_list_conf_get(uint32_t conf_id)
11724 {
11725 	const struct indlst_conf *conf;
11726 
11727 	SLIST_FOREACH(conf, &indlst_conf_head, next) {
11728 		if (conf->id == conf_id)
11729 			return conf;
11730 	}
11731 	return NULL;
11732 }
11733 
11734 /** Dispatch parsed buffer to function calls. */
11735 static void
11736 cmd_flow_parsed(const struct buffer *in)
11737 {
11738 	switch (in->command) {
11739 	case INFO:
11740 		port_flow_get_info(in->port);
11741 		break;
11742 	case CONFIGURE:
11743 		port_flow_configure(in->port,
11744 				    &in->args.configure.port_attr,
11745 				    in->args.configure.nb_queue,
11746 				    &in->args.configure.queue_attr);
11747 		break;
11748 	case PATTERN_TEMPLATE_CREATE:
11749 		port_flow_pattern_template_create(in->port,
11750 				in->args.vc.pat_templ_id,
11751 				&((const struct rte_flow_pattern_template_attr) {
11752 					.relaxed_matching = in->args.vc.attr.reserved,
11753 					.ingress = in->args.vc.attr.ingress,
11754 					.egress = in->args.vc.attr.egress,
11755 					.transfer = in->args.vc.attr.transfer,
11756 				}),
11757 				in->args.vc.pattern);
11758 		break;
11759 	case PATTERN_TEMPLATE_DESTROY:
11760 		port_flow_pattern_template_destroy(in->port,
11761 				in->args.templ_destroy.template_id_n,
11762 				in->args.templ_destroy.template_id);
11763 		break;
11764 	case ACTIONS_TEMPLATE_CREATE:
11765 		port_flow_actions_template_create(in->port,
11766 				in->args.vc.act_templ_id,
11767 				&((const struct rte_flow_actions_template_attr) {
11768 					.ingress = in->args.vc.attr.ingress,
11769 					.egress = in->args.vc.attr.egress,
11770 					.transfer = in->args.vc.attr.transfer,
11771 				}),
11772 				in->args.vc.actions,
11773 				in->args.vc.masks);
11774 		break;
11775 	case ACTIONS_TEMPLATE_DESTROY:
11776 		port_flow_actions_template_destroy(in->port,
11777 				in->args.templ_destroy.template_id_n,
11778 				in->args.templ_destroy.template_id);
11779 		break;
11780 	case TABLE_CREATE:
11781 		port_flow_template_table_create(in->port, in->args.table.id,
11782 			&in->args.table.attr, in->args.table.pat_templ_id_n,
11783 			in->args.table.pat_templ_id, in->args.table.act_templ_id_n,
11784 			in->args.table.act_templ_id);
11785 		break;
11786 	case TABLE_DESTROY:
11787 		port_flow_template_table_destroy(in->port,
11788 					in->args.table_destroy.table_id_n,
11789 					in->args.table_destroy.table_id);
11790 		break;
11791 	case QUEUE_CREATE:
11792 		port_queue_flow_create(in->port, in->queue, in->postpone,
11793 			in->args.vc.table_id, in->args.vc.rule_id,
11794 			in->args.vc.pat_templ_id, in->args.vc.act_templ_id,
11795 			in->args.vc.pattern, in->args.vc.actions);
11796 		break;
11797 	case QUEUE_DESTROY:
11798 		port_queue_flow_destroy(in->port, in->queue, in->postpone,
11799 					in->args.destroy.rule_n,
11800 					in->args.destroy.rule);
11801 		break;
11802 	case PUSH:
11803 		port_queue_flow_push(in->port, in->queue);
11804 		break;
11805 	case PULL:
11806 		port_queue_flow_pull(in->port, in->queue);
11807 		break;
11808 	case QUEUE_AGED:
11809 		port_queue_flow_aged(in->port, in->queue,
11810 				     in->args.aged.destroy);
11811 		break;
11812 	case QUEUE_INDIRECT_ACTION_CREATE:
11813 	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
11814 		port_queue_action_handle_create(
11815 				in->port, in->queue, in->postpone,
11816 				in->args.vc.attr.group,
11817 				&((const struct rte_flow_indir_action_conf) {
11818 					.ingress = in->args.vc.attr.ingress,
11819 					.egress = in->args.vc.attr.egress,
11820 					.transfer = in->args.vc.attr.transfer,
11821 				}),
11822 				in->args.vc.actions);
11823 		break;
11824 	case QUEUE_INDIRECT_ACTION_DESTROY:
11825 		port_queue_action_handle_destroy(in->port,
11826 					   in->queue, in->postpone,
11827 					   in->args.ia_destroy.action_id_n,
11828 					   in->args.ia_destroy.action_id);
11829 		break;
11830 	case QUEUE_INDIRECT_ACTION_UPDATE:
11831 		port_queue_action_handle_update(in->port,
11832 						in->queue, in->postpone,
11833 						in->args.vc.attr.group,
11834 						in->args.vc.actions);
11835 		break;
11836 	case QUEUE_INDIRECT_ACTION_QUERY:
11837 		port_queue_action_handle_query(in->port,
11838 					       in->queue, in->postpone,
11839 					       in->args.ia.action_id);
11840 		break;
11841 	case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
11842 		port_queue_action_handle_query_update(in->port, in->queue,
11843 						      in->postpone,
11844 						      in->args.ia.action_id,
11845 						      in->args.ia.qu_mode,
11846 						      in->args.vc.actions);
11847 		break;
11848 	case INDIRECT_ACTION_CREATE:
11849 	case INDIRECT_ACTION_LIST_CREATE:
11850 		port_action_handle_create(
11851 				in->port, in->args.vc.attr.group,
11852 				in->command == INDIRECT_ACTION_LIST_CREATE,
11853 				&((const struct rte_flow_indir_action_conf) {
11854 					.ingress = in->args.vc.attr.ingress,
11855 					.egress = in->args.vc.attr.egress,
11856 					.transfer = in->args.vc.attr.transfer,
11857 				}),
11858 				in->args.vc.actions);
11859 		break;
11860 	case INDIRECT_ACTION_FLOW_CONF_CREATE:
11861 		indirect_action_flow_conf_create(in);
11862 		break;
11863 	case INDIRECT_ACTION_DESTROY:
11864 		port_action_handle_destroy(in->port,
11865 					   in->args.ia_destroy.action_id_n,
11866 					   in->args.ia_destroy.action_id);
11867 		break;
11868 	case INDIRECT_ACTION_UPDATE:
11869 		port_action_handle_update(in->port, in->args.vc.attr.group,
11870 					  in->args.vc.actions);
11871 		break;
11872 	case INDIRECT_ACTION_QUERY:
11873 		port_action_handle_query(in->port, in->args.ia.action_id);
11874 		break;
11875 	case INDIRECT_ACTION_QUERY_UPDATE:
11876 		port_action_handle_query_update(in->port,
11877 						in->args.ia.action_id,
11878 						in->args.ia.qu_mode,
11879 						in->args.vc.actions);
11880 		break;
11881 	case VALIDATE:
11882 		port_flow_validate(in->port, &in->args.vc.attr,
11883 				   in->args.vc.pattern, in->args.vc.actions,
11884 				   &in->args.vc.tunnel_ops);
11885 		break;
11886 	case CREATE:
11887 		port_flow_create(in->port, &in->args.vc.attr,
11888 				 in->args.vc.pattern, in->args.vc.actions,
11889 				 &in->args.vc.tunnel_ops);
11890 		break;
11891 	case DESTROY:
11892 		port_flow_destroy(in->port, in->args.destroy.rule_n,
11893 				  in->args.destroy.rule);
11894 		break;
11895 	case FLUSH:
11896 		port_flow_flush(in->port);
11897 		break;
11898 	case DUMP_ONE:
11899 	case DUMP_ALL:
11900 		port_flow_dump(in->port, in->args.dump.mode,
11901 				in->args.dump.rule, in->args.dump.file);
11902 		break;
11903 	case QUERY:
11904 		port_flow_query(in->port, in->args.query.rule,
11905 				&in->args.query.action);
11906 		break;
11907 	case LIST:
11908 		port_flow_list(in->port, in->args.list.group_n,
11909 			       in->args.list.group);
11910 		break;
11911 	case ISOLATE:
11912 		port_flow_isolate(in->port, in->args.isolate.set);
11913 		break;
11914 	case AGED:
11915 		port_flow_aged(in->port, in->args.aged.destroy);
11916 		break;
11917 	case TUNNEL_CREATE:
11918 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
11919 		break;
11920 	case TUNNEL_DESTROY:
11921 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
11922 		break;
11923 	case TUNNEL_LIST:
11924 		port_flow_tunnel_list(in->port);
11925 		break;
11926 	case ACTION_POL_G:
11927 		port_meter_policy_add(in->port, in->args.policy.policy_id,
11928 					in->args.vc.actions);
11929 		break;
11930 	case FLEX_ITEM_CREATE:
11931 		flex_item_create(in->port, in->args.flex.token,
11932 				 in->args.flex.filename);
11933 		break;
11934 	case FLEX_ITEM_DESTROY:
11935 		flex_item_destroy(in->port, in->args.flex.token);
11936 		break;
11937 	default:
11938 		break;
11939 	}
11940 	fflush(stdout);
11941 }
11942 
11943 /** Token generator and output processing callback (cmdline API). */
11944 static void
11945 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
11946 {
11947 	if (cl == NULL)
11948 		cmd_flow_tok(arg0, arg2);
11949 	else
11950 		cmd_flow_parsed(arg0);
11951 }
11952 
11953 /** Global parser instance (cmdline API). */
11954 cmdline_parse_inst_t cmd_flow = {
11955 	.f = cmd_flow_cb,
11956 	.data = NULL, /**< Unused. */
11957 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
11958 	.tokens = {
11959 		NULL,
11960 	}, /**< Tokens are returned by cmd_flow_tok(). */
11961 };
11962 
11963 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
11964 
11965 static void
11966 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
11967 {
11968 	struct rte_ipv4_hdr *ipv4;
11969 	struct rte_ether_hdr *eth;
11970 	struct rte_ipv6_hdr *ipv6;
11971 	struct rte_vxlan_hdr *vxlan;
11972 	struct rte_vxlan_gpe_hdr *gpe;
11973 	struct rte_flow_item_nvgre *nvgre;
11974 	uint32_t ipv6_vtc_flow;
11975 
11976 	switch (item->type) {
11977 	case RTE_FLOW_ITEM_TYPE_ETH:
11978 		eth = (struct rte_ether_hdr *)buf;
11979 		if (next_proto)
11980 			eth->ether_type = rte_cpu_to_be_16(next_proto);
11981 		break;
11982 	case RTE_FLOW_ITEM_TYPE_IPV4:
11983 		ipv4 = (struct rte_ipv4_hdr *)buf;
11984 		if (!ipv4->version_ihl)
11985 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
11986 		if (next_proto && ipv4->next_proto_id == 0)
11987 			ipv4->next_proto_id = (uint8_t)next_proto;
11988 		break;
11989 	case RTE_FLOW_ITEM_TYPE_IPV6:
11990 		ipv6 = (struct rte_ipv6_hdr *)buf;
11991 		if (next_proto && ipv6->proto == 0)
11992 			ipv6->proto = (uint8_t)next_proto;
11993 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
11994 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
11995 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
11996 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
11997 		break;
11998 	case RTE_FLOW_ITEM_TYPE_VXLAN:
11999 		vxlan = (struct rte_vxlan_hdr *)buf;
12000 		vxlan->vx_flags = 0x08;
12001 		break;
12002 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
12003 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
12004 		gpe->vx_flags = 0x0C;
12005 		break;
12006 	case RTE_FLOW_ITEM_TYPE_NVGRE:
12007 		nvgre = (struct rte_flow_item_nvgre *)buf;
12008 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
12009 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
12010 		break;
12011 	default:
12012 		break;
12013 	}
12014 }
12015 
12016 /** Helper of get item's default mask. */
12017 static const void *
12018 flow_item_default_mask(const struct rte_flow_item *item)
12019 {
12020 	const void *mask = NULL;
12021 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
12022 	static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = {
12023 		.hdr = {
12024 			.next_hdr = 0xff,
12025 			.type = 0xff,
12026 			.segments_left = 0xff,
12027 		},
12028 	};
12029 
12030 	switch (item->type) {
12031 	case RTE_FLOW_ITEM_TYPE_ANY:
12032 		mask = &rte_flow_item_any_mask;
12033 		break;
12034 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
12035 		mask = &rte_flow_item_port_id_mask;
12036 		break;
12037 	case RTE_FLOW_ITEM_TYPE_RAW:
12038 		mask = &rte_flow_item_raw_mask;
12039 		break;
12040 	case RTE_FLOW_ITEM_TYPE_ETH:
12041 		mask = &rte_flow_item_eth_mask;
12042 		break;
12043 	case RTE_FLOW_ITEM_TYPE_VLAN:
12044 		mask = &rte_flow_item_vlan_mask;
12045 		break;
12046 	case RTE_FLOW_ITEM_TYPE_IPV4:
12047 		mask = &rte_flow_item_ipv4_mask;
12048 		break;
12049 	case RTE_FLOW_ITEM_TYPE_IPV6:
12050 		mask = &rte_flow_item_ipv6_mask;
12051 		break;
12052 	case RTE_FLOW_ITEM_TYPE_ICMP:
12053 		mask = &rte_flow_item_icmp_mask;
12054 		break;
12055 	case RTE_FLOW_ITEM_TYPE_UDP:
12056 		mask = &rte_flow_item_udp_mask;
12057 		break;
12058 	case RTE_FLOW_ITEM_TYPE_TCP:
12059 		mask = &rte_flow_item_tcp_mask;
12060 		break;
12061 	case RTE_FLOW_ITEM_TYPE_SCTP:
12062 		mask = &rte_flow_item_sctp_mask;
12063 		break;
12064 	case RTE_FLOW_ITEM_TYPE_VXLAN:
12065 		mask = &rte_flow_item_vxlan_mask;
12066 		break;
12067 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
12068 		mask = &rte_flow_item_vxlan_gpe_mask;
12069 		break;
12070 	case RTE_FLOW_ITEM_TYPE_E_TAG:
12071 		mask = &rte_flow_item_e_tag_mask;
12072 		break;
12073 	case RTE_FLOW_ITEM_TYPE_NVGRE:
12074 		mask = &rte_flow_item_nvgre_mask;
12075 		break;
12076 	case RTE_FLOW_ITEM_TYPE_MPLS:
12077 		mask = &rte_flow_item_mpls_mask;
12078 		break;
12079 	case RTE_FLOW_ITEM_TYPE_GRE:
12080 		mask = &rte_flow_item_gre_mask;
12081 		break;
12082 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
12083 		mask = &gre_key_default_mask;
12084 		break;
12085 	case RTE_FLOW_ITEM_TYPE_META:
12086 		mask = &rte_flow_item_meta_mask;
12087 		break;
12088 	case RTE_FLOW_ITEM_TYPE_FUZZY:
12089 		mask = &rte_flow_item_fuzzy_mask;
12090 		break;
12091 	case RTE_FLOW_ITEM_TYPE_GTP:
12092 		mask = &rte_flow_item_gtp_mask;
12093 		break;
12094 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
12095 		mask = &rte_flow_item_gtp_psc_mask;
12096 		break;
12097 	case RTE_FLOW_ITEM_TYPE_GENEVE:
12098 		mask = &rte_flow_item_geneve_mask;
12099 		break;
12100 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
12101 		mask = &rte_flow_item_geneve_opt_mask;
12102 		break;
12103 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
12104 		mask = &rte_flow_item_pppoe_proto_id_mask;
12105 		break;
12106 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
12107 		mask = &rte_flow_item_l2tpv3oip_mask;
12108 		break;
12109 	case RTE_FLOW_ITEM_TYPE_ESP:
12110 		mask = &rte_flow_item_esp_mask;
12111 		break;
12112 	case RTE_FLOW_ITEM_TYPE_AH:
12113 		mask = &rte_flow_item_ah_mask;
12114 		break;
12115 	case RTE_FLOW_ITEM_TYPE_PFCP:
12116 		mask = &rte_flow_item_pfcp_mask;
12117 		break;
12118 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
12119 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
12120 		mask = &rte_flow_item_ethdev_mask;
12121 		break;
12122 	case RTE_FLOW_ITEM_TYPE_L2TPV2:
12123 		mask = &rte_flow_item_l2tpv2_mask;
12124 		break;
12125 	case RTE_FLOW_ITEM_TYPE_PPP:
12126 		mask = &rte_flow_item_ppp_mask;
12127 		break;
12128 	case RTE_FLOW_ITEM_TYPE_METER_COLOR:
12129 		mask = &rte_flow_item_meter_color_mask;
12130 		break;
12131 	case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
12132 		mask = &ipv6_routing_ext_default_mask;
12133 		break;
12134 	case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY:
12135 		mask = &rte_flow_item_aggr_affinity_mask;
12136 		break;
12137 	case RTE_FLOW_ITEM_TYPE_TX_QUEUE:
12138 		mask = &rte_flow_item_tx_queue_mask;
12139 		break;
12140 	case RTE_FLOW_ITEM_TYPE_IB_BTH:
12141 		mask = &rte_flow_item_ib_bth_mask;
12142 		break;
12143 	default:
12144 		break;
12145 	}
12146 	return mask;
12147 }
12148 
12149 /** Dispatch parsed buffer to function calls. */
12150 static void
12151 cmd_set_raw_parsed_sample(const struct buffer *in)
12152 {
12153 	uint32_t n = in->args.vc.actions_n;
12154 	uint32_t i = 0;
12155 	struct rte_flow_action *action = NULL;
12156 	struct rte_flow_action *data = NULL;
12157 	const struct rte_flow_action_rss *rss = NULL;
12158 	size_t size = 0;
12159 	uint16_t idx = in->port; /* We borrow port field as index */
12160 	uint32_t max_size = sizeof(struct rte_flow_action) *
12161 						ACTION_SAMPLE_ACTIONS_NUM;
12162 
12163 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
12164 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
12165 	memset(data, 0x00, max_size);
12166 	for (; i <= n - 1; i++) {
12167 		action = in->args.vc.actions + i;
12168 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
12169 			break;
12170 		switch (action->type) {
12171 		case RTE_FLOW_ACTION_TYPE_MARK:
12172 			size = sizeof(struct rte_flow_action_mark);
12173 			rte_memcpy(&sample_mark[idx],
12174 				(const void *)action->conf, size);
12175 			action->conf = &sample_mark[idx];
12176 			break;
12177 		case RTE_FLOW_ACTION_TYPE_COUNT:
12178 			size = sizeof(struct rte_flow_action_count);
12179 			rte_memcpy(&sample_count[idx],
12180 				(const void *)action->conf, size);
12181 			action->conf = &sample_count[idx];
12182 			break;
12183 		case RTE_FLOW_ACTION_TYPE_QUEUE:
12184 			size = sizeof(struct rte_flow_action_queue);
12185 			rte_memcpy(&sample_queue[idx],
12186 				(const void *)action->conf, size);
12187 			action->conf = &sample_queue[idx];
12188 			break;
12189 		case RTE_FLOW_ACTION_TYPE_RSS:
12190 			size = sizeof(struct rte_flow_action_rss);
12191 			rss = action->conf;
12192 			rte_memcpy(&sample_rss_data[idx].conf,
12193 				   (const void *)rss, size);
12194 			if (rss->key_len && rss->key) {
12195 				sample_rss_data[idx].conf.key =
12196 						sample_rss_data[idx].key;
12197 				rte_memcpy((void *)((uintptr_t)
12198 					   sample_rss_data[idx].conf.key),
12199 					   (const void *)rss->key,
12200 					   sizeof(uint8_t) * rss->key_len);
12201 			}
12202 			if (rss->queue_num && rss->queue) {
12203 				sample_rss_data[idx].conf.queue =
12204 						sample_rss_data[idx].queue;
12205 				rte_memcpy((void *)((uintptr_t)
12206 					   sample_rss_data[idx].conf.queue),
12207 					   (const void *)rss->queue,
12208 					   sizeof(uint16_t) * rss->queue_num);
12209 			}
12210 			action->conf = &sample_rss_data[idx].conf;
12211 			break;
12212 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
12213 			size = sizeof(struct rte_flow_action_raw_encap);
12214 			rte_memcpy(&sample_encap[idx],
12215 				(const void *)action->conf, size);
12216 			action->conf = &sample_encap[idx];
12217 			break;
12218 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
12219 			size = sizeof(struct rte_flow_action_port_id);
12220 			rte_memcpy(&sample_port_id[idx],
12221 				(const void *)action->conf, size);
12222 			action->conf = &sample_port_id[idx];
12223 			break;
12224 		case RTE_FLOW_ACTION_TYPE_PF:
12225 			break;
12226 		case RTE_FLOW_ACTION_TYPE_VF:
12227 			size = sizeof(struct rte_flow_action_vf);
12228 			rte_memcpy(&sample_vf[idx],
12229 					(const void *)action->conf, size);
12230 			action->conf = &sample_vf[idx];
12231 			break;
12232 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
12233 			size = sizeof(struct rte_flow_action_vxlan_encap);
12234 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
12235 			action->conf = &sample_vxlan_encap[idx].conf;
12236 			break;
12237 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
12238 			size = sizeof(struct rte_flow_action_nvgre_encap);
12239 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
12240 			action->conf = &sample_nvgre_encap[idx];
12241 			break;
12242 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
12243 			size = sizeof(struct rte_flow_action_ethdev);
12244 			rte_memcpy(&sample_port_representor[idx],
12245 					(const void *)action->conf, size);
12246 			action->conf = &sample_port_representor[idx];
12247 			break;
12248 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
12249 			size = sizeof(struct rte_flow_action_ethdev);
12250 			rte_memcpy(&sample_represented_port[idx],
12251 					(const void *)action->conf, size);
12252 			action->conf = &sample_represented_port[idx];
12253 			break;
12254 		default:
12255 			fprintf(stderr, "Error - Not supported action\n");
12256 			return;
12257 		}
12258 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
12259 		data++;
12260 	}
12261 }
12262 
12263 /** Dispatch parsed buffer to function calls. */
12264 static void
12265 cmd_set_raw_parsed(const struct buffer *in)
12266 {
12267 	uint32_t n = in->args.vc.pattern_n;
12268 	int i = 0;
12269 	struct rte_flow_item *item = NULL;
12270 	size_t size = 0;
12271 	uint8_t *data = NULL;
12272 	uint8_t *data_tail = NULL;
12273 	size_t *total_size = NULL;
12274 	uint16_t upper_layer = 0;
12275 	uint16_t proto = 0;
12276 	uint16_t idx = in->port; /* We borrow port field as index */
12277 	int gtp_psc = -1; /* GTP PSC option index. */
12278 	const void *src_spec;
12279 
12280 	if (in->command == SET_SAMPLE_ACTIONS)
12281 		return cmd_set_raw_parsed_sample(in);
12282 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
12283 		   in->command == SET_RAW_DECAP);
12284 	if (in->command == SET_RAW_ENCAP) {
12285 		total_size = &raw_encap_confs[idx].size;
12286 		data = (uint8_t *)&raw_encap_confs[idx].data;
12287 	} else {
12288 		total_size = &raw_decap_confs[idx].size;
12289 		data = (uint8_t *)&raw_decap_confs[idx].data;
12290 	}
12291 	*total_size = 0;
12292 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
12293 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
12294 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
12295 	for (i = n - 1 ; i >= 0; --i) {
12296 		const struct rte_flow_item_gtp *gtp;
12297 		const struct rte_flow_item_geneve_opt *opt;
12298 		struct rte_flow_item_ipv6_routing_ext *ext;
12299 
12300 		item = in->args.vc.pattern + i;
12301 		if (item->spec == NULL)
12302 			item->spec = flow_item_default_mask(item);
12303 		src_spec = item->spec;
12304 		switch (item->type) {
12305 		case RTE_FLOW_ITEM_TYPE_ETH:
12306 			size = sizeof(struct rte_ether_hdr);
12307 			break;
12308 		case RTE_FLOW_ITEM_TYPE_VLAN:
12309 			size = sizeof(struct rte_vlan_hdr);
12310 			proto = RTE_ETHER_TYPE_VLAN;
12311 			break;
12312 		case RTE_FLOW_ITEM_TYPE_IPV4:
12313 			size = sizeof(struct rte_ipv4_hdr);
12314 			proto = RTE_ETHER_TYPE_IPV4;
12315 			break;
12316 		case RTE_FLOW_ITEM_TYPE_IPV6:
12317 			size = sizeof(struct rte_ipv6_hdr);
12318 			proto = RTE_ETHER_TYPE_IPV6;
12319 			break;
12320 		case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
12321 			ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec;
12322 			if (!ext->hdr.hdr_len) {
12323 				size = sizeof(struct rte_ipv6_routing_ext) +
12324 					(ext->hdr.segments_left << 4);
12325 				ext->hdr.hdr_len = ext->hdr.segments_left << 1;
12326 			} else {
12327 				size = sizeof(struct rte_ipv6_routing_ext) +
12328 					(ext->hdr.hdr_len << 3);
12329 			}
12330 			proto = IPPROTO_ROUTING;
12331 			break;
12332 		case RTE_FLOW_ITEM_TYPE_UDP:
12333 			size = sizeof(struct rte_udp_hdr);
12334 			proto = 0x11;
12335 			break;
12336 		case RTE_FLOW_ITEM_TYPE_TCP:
12337 			size = sizeof(struct rte_tcp_hdr);
12338 			proto = 0x06;
12339 			break;
12340 		case RTE_FLOW_ITEM_TYPE_VXLAN:
12341 			size = sizeof(struct rte_vxlan_hdr);
12342 			break;
12343 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
12344 			size = sizeof(struct rte_vxlan_gpe_hdr);
12345 			break;
12346 		case RTE_FLOW_ITEM_TYPE_GRE:
12347 			size = sizeof(struct rte_gre_hdr);
12348 			proto = 0x2F;
12349 			break;
12350 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
12351 			size = sizeof(rte_be32_t);
12352 			proto = 0x0;
12353 			break;
12354 		case RTE_FLOW_ITEM_TYPE_MPLS:
12355 			size = sizeof(struct rte_mpls_hdr);
12356 			proto = 0x0;
12357 			break;
12358 		case RTE_FLOW_ITEM_TYPE_NVGRE:
12359 			size = sizeof(struct rte_flow_item_nvgre);
12360 			proto = 0x2F;
12361 			break;
12362 		case RTE_FLOW_ITEM_TYPE_GENEVE:
12363 			size = sizeof(struct rte_geneve_hdr);
12364 			break;
12365 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
12366 			opt = (const struct rte_flow_item_geneve_opt *)
12367 								item->spec;
12368 			size = offsetof(struct rte_flow_item_geneve_opt,
12369 					option_len) + sizeof(uint8_t);
12370 			if (opt->option_len && opt->data) {
12371 				*total_size += opt->option_len *
12372 					       sizeof(uint32_t);
12373 				rte_memcpy(data_tail - (*total_size),
12374 					   opt->data,
12375 					   opt->option_len * sizeof(uint32_t));
12376 			}
12377 			break;
12378 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
12379 			size = sizeof(rte_be32_t);
12380 			proto = 0x73;
12381 			break;
12382 		case RTE_FLOW_ITEM_TYPE_ESP:
12383 			size = sizeof(struct rte_esp_hdr);
12384 			proto = 0x32;
12385 			break;
12386 		case RTE_FLOW_ITEM_TYPE_AH:
12387 			size = sizeof(struct rte_flow_item_ah);
12388 			proto = 0x33;
12389 			break;
12390 		case RTE_FLOW_ITEM_TYPE_GTP:
12391 			if (gtp_psc < 0) {
12392 				size = sizeof(struct rte_gtp_hdr);
12393 				break;
12394 			}
12395 			if (gtp_psc != i + 1) {
12396 				fprintf(stderr,
12397 					"Error - GTP PSC does not follow GTP\n");
12398 				goto error;
12399 			}
12400 			gtp = item->spec;
12401 			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
12402 				/* Only E flag should be set. */
12403 				fprintf(stderr,
12404 					"Error - GTP unsupported flags\n");
12405 				goto error;
12406 			} else {
12407 				struct rte_gtp_hdr_ext_word ext_word = {
12408 					.next_ext = 0x85
12409 				};
12410 
12411 				/* We have to add GTP header extra word. */
12412 				*total_size += sizeof(ext_word);
12413 				rte_memcpy(data_tail - (*total_size),
12414 					   &ext_word, sizeof(ext_word));
12415 			}
12416 			size = sizeof(struct rte_gtp_hdr);
12417 			break;
12418 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
12419 			if (gtp_psc >= 0) {
12420 				fprintf(stderr,
12421 					"Error - Multiple GTP PSC items\n");
12422 				goto error;
12423 			} else {
12424 				const struct rte_flow_item_gtp_psc
12425 					*opt = item->spec;
12426 				struct rte_gtp_psc_generic_hdr *hdr;
12427 				size_t hdr_size = RTE_ALIGN(sizeof(*hdr),
12428 							 sizeof(int32_t));
12429 
12430 				*total_size += hdr_size;
12431 				hdr = (typeof(hdr))(data_tail - (*total_size));
12432 				memset(hdr, 0, hdr_size);
12433 				*hdr = opt->hdr;
12434 				hdr->ext_hdr_len = 1;
12435 				gtp_psc = i;
12436 				size = 0;
12437 			}
12438 			break;
12439 		case RTE_FLOW_ITEM_TYPE_PFCP:
12440 			size = sizeof(struct rte_flow_item_pfcp);
12441 			break;
12442 		case RTE_FLOW_ITEM_TYPE_FLEX:
12443 			if (item->spec != NULL) {
12444 				size = ((const struct rte_flow_item_flex *)item->spec)->length;
12445 				src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern;
12446 			} else {
12447 				size = 0;
12448 				src_spec = NULL;
12449 			}
12450 			break;
12451 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
12452 			size = 0;
12453 			if (item->spec) {
12454 				const struct rte_flow_item_gre_opt
12455 					*opt = item->spec;
12456 				if (opt->checksum_rsvd.checksum) {
12457 					*total_size +=
12458 						sizeof(opt->checksum_rsvd);
12459 					rte_memcpy(data_tail - (*total_size),
12460 						   &opt->checksum_rsvd,
12461 						   sizeof(opt->checksum_rsvd));
12462 				}
12463 				if (opt->key.key) {
12464 					*total_size += sizeof(opt->key.key);
12465 					rte_memcpy(data_tail - (*total_size),
12466 						   &opt->key.key,
12467 						   sizeof(opt->key.key));
12468 				}
12469 				if (opt->sequence.sequence) {
12470 					*total_size += sizeof(opt->sequence.sequence);
12471 					rte_memcpy(data_tail - (*total_size),
12472 						   &opt->sequence.sequence,
12473 						   sizeof(opt->sequence.sequence));
12474 				}
12475 			}
12476 			proto = 0x2F;
12477 			break;
12478 		default:
12479 			fprintf(stderr, "Error - Not supported item\n");
12480 			goto error;
12481 		}
12482 		if (size) {
12483 			*total_size += size;
12484 			rte_memcpy(data_tail - (*total_size), src_spec, size);
12485 			/* update some fields which cannot be set by cmdline */
12486 			update_fields((data_tail - (*total_size)), item,
12487 				      upper_layer);
12488 			upper_layer = proto;
12489 		}
12490 	}
12491 	if (verbose_level & 0x1)
12492 		printf("total data size is %zu\n", (*total_size));
12493 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
12494 	memmove(data, (data_tail - (*total_size)), *total_size);
12495 	return;
12496 
12497 error:
12498 	*total_size = 0;
12499 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
12500 }
12501 
12502 /** Populate help strings for current token (cmdline API). */
12503 static int
12504 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
12505 		     unsigned int size)
12506 {
12507 	struct context *ctx = &cmd_flow_context;
12508 	const struct token *token = &token_list[ctx->prev];
12509 
12510 	(void)hdr;
12511 	if (!size)
12512 		return -1;
12513 	/* Set token type and update global help with details. */
12514 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
12515 	if (token->help)
12516 		cmd_set_raw.help_str = token->help;
12517 	else
12518 		cmd_set_raw.help_str = token->name;
12519 	return 0;
12520 }
12521 
12522 /** Token definition template (cmdline API). */
12523 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
12524 	.ops = &(struct cmdline_token_ops){
12525 		.parse = cmd_flow_parse,
12526 		.complete_get_nb = cmd_flow_complete_get_nb,
12527 		.complete_get_elt = cmd_flow_complete_get_elt,
12528 		.get_help = cmd_set_raw_get_help,
12529 	},
12530 	.offset = 0,
12531 };
12532 
12533 /** Populate the next dynamic token. */
12534 static void
12535 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
12536 	     cmdline_parse_token_hdr_t **hdr_inst)
12537 {
12538 	struct context *ctx = &cmd_flow_context;
12539 
12540 	/* Always reinitialize context before requesting the first token. */
12541 	if (!(hdr_inst - cmd_set_raw.tokens)) {
12542 		cmd_flow_context_init(ctx);
12543 		ctx->curr = START_SET;
12544 	}
12545 	/* Return NULL when no more tokens are expected. */
12546 	if (!ctx->next_num && (ctx->curr != START_SET)) {
12547 		*hdr = NULL;
12548 		return;
12549 	}
12550 	/* Determine if command should end here. */
12551 	if (ctx->eol && ctx->last && ctx->next_num) {
12552 		const enum index *list = ctx->next[ctx->next_num - 1];
12553 		int i;
12554 
12555 		for (i = 0; list[i]; ++i) {
12556 			if (list[i] != END)
12557 				continue;
12558 			*hdr = NULL;
12559 			return;
12560 		}
12561 	}
12562 	*hdr = &cmd_set_raw_token_hdr;
12563 }
12564 
12565 /** Token generator and output processing callback (cmdline API). */
12566 static void
12567 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
12568 {
12569 	if (cl == NULL)
12570 		cmd_set_raw_tok(arg0, arg2);
12571 	else
12572 		cmd_set_raw_parsed(arg0);
12573 }
12574 
12575 /** Global parser instance (cmdline API). */
12576 cmdline_parse_inst_t cmd_set_raw = {
12577 	.f = cmd_set_raw_cb,
12578 	.data = NULL, /**< Unused. */
12579 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
12580 	.tokens = {
12581 		NULL,
12582 	}, /**< Tokens are returned by cmd_flow_tok(). */
12583 };
12584 
12585 /* *** display raw_encap/raw_decap buf */
12586 struct cmd_show_set_raw_result {
12587 	cmdline_fixed_string_t cmd_show;
12588 	cmdline_fixed_string_t cmd_what;
12589 	cmdline_fixed_string_t cmd_all;
12590 	uint16_t cmd_index;
12591 };
12592 
12593 static void
12594 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
12595 {
12596 	struct cmd_show_set_raw_result *res = parsed_result;
12597 	uint16_t index = res->cmd_index;
12598 	uint8_t all = 0;
12599 	uint8_t *raw_data = NULL;
12600 	size_t raw_size = 0;
12601 	char title[16] = {0};
12602 
12603 	RTE_SET_USED(cl);
12604 	RTE_SET_USED(data);
12605 	if (!strcmp(res->cmd_all, "all")) {
12606 		all = 1;
12607 		index = 0;
12608 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
12609 		fprintf(stderr, "index should be 0-%u\n",
12610 			RAW_ENCAP_CONFS_MAX_NUM - 1);
12611 		return;
12612 	}
12613 	do {
12614 		if (!strcmp(res->cmd_what, "raw_encap")) {
12615 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
12616 			raw_size = raw_encap_confs[index].size;
12617 			snprintf(title, 16, "\nindex: %u", index);
12618 			rte_hexdump(stdout, title, raw_data, raw_size);
12619 		} else {
12620 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
12621 			raw_size = raw_decap_confs[index].size;
12622 			snprintf(title, 16, "\nindex: %u", index);
12623 			rte_hexdump(stdout, title, raw_data, raw_size);
12624 		}
12625 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
12626 }
12627 
12628 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
12629 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
12630 			cmd_show, "show");
12631 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
12632 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
12633 			cmd_what, "raw_encap#raw_decap");
12634 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
12635 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
12636 			cmd_index, RTE_UINT16);
12637 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
12638 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
12639 			cmd_all, "all");
12640 cmdline_parse_inst_t cmd_show_set_raw = {
12641 	.f = cmd_show_set_raw_parsed,
12642 	.data = NULL,
12643 	.help_str = "show <raw_encap|raw_decap> <index>",
12644 	.tokens = {
12645 		(void *)&cmd_show_set_raw_cmd_show,
12646 		(void *)&cmd_show_set_raw_cmd_what,
12647 		(void *)&cmd_show_set_raw_cmd_index,
12648 		NULL,
12649 	},
12650 };
12651 cmdline_parse_inst_t cmd_show_set_raw_all = {
12652 	.f = cmd_show_set_raw_parsed,
12653 	.data = NULL,
12654 	.help_str = "show <raw_encap|raw_decap> all",
12655 	.tokens = {
12656 		(void *)&cmd_show_set_raw_cmd_show,
12657 		(void *)&cmd_show_set_raw_cmd_what,
12658 		(void *)&cmd_show_set_raw_cmd_all,
12659 		NULL,
12660 	},
12661 };
12662