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