xref: /dpdk/app/test-pmd/cmdline_flow.c (revision 88caad251c8de3a84e353b0b2a27014bc303df87)
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 <inttypes.h>
10 #include <errno.h>
11 #include <ctype.h>
12 #include <string.h>
13 
14 #include <rte_string_fns.h>
15 #include <rte_common.h>
16 #include <rte_ethdev.h>
17 #include <rte_byteorder.h>
18 #include <cmdline_parse.h>
19 #include <cmdline_parse_etheraddr.h>
20 #include <cmdline_parse_string.h>
21 #include <cmdline_parse_num.h>
22 #include <rte_flow.h>
23 #include <rte_hexdump.h>
24 #include <rte_vxlan.h>
25 #include <rte_gre.h>
26 #include <rte_mpls.h>
27 #include <rte_gtp.h>
28 #include <rte_geneve.h>
29 
30 #include "testpmd.h"
31 
32 /** Parser token indices. */
33 enum index {
34 	/* Special tokens. */
35 	ZERO = 0,
36 	END,
37 	START_SET,
38 	END_SET,
39 
40 	/* Common tokens. */
41 	COMMON_INTEGER,
42 	COMMON_UNSIGNED,
43 	COMMON_PREFIX,
44 	COMMON_BOOLEAN,
45 	COMMON_STRING,
46 	COMMON_HEX,
47 	COMMON_FILE_PATH,
48 	COMMON_MAC_ADDR,
49 	COMMON_IPV4_ADDR,
50 	COMMON_IPV6_ADDR,
51 	COMMON_RULE_ID,
52 	COMMON_PORT_ID,
53 	COMMON_GROUP_ID,
54 	COMMON_PRIORITY_LEVEL,
55 	COMMON_INDIRECT_ACTION_ID,
56 	COMMON_POLICY_ID,
57 
58 	/* TOP-level command. */
59 	ADD,
60 
61 	/* Top-level command. */
62 	SET,
63 	/* Sub-leve commands. */
64 	SET_RAW_ENCAP,
65 	SET_RAW_DECAP,
66 	SET_RAW_INDEX,
67 	SET_SAMPLE_ACTIONS,
68 	SET_SAMPLE_INDEX,
69 
70 	/* Top-level command. */
71 	FLOW,
72 	/* Sub-level commands. */
73 	INDIRECT_ACTION,
74 	VALIDATE,
75 	CREATE,
76 	DESTROY,
77 	FLUSH,
78 	DUMP,
79 	QUERY,
80 	LIST,
81 	AGED,
82 	ISOLATE,
83 	TUNNEL,
84 
85 	/* Tunnel arguments. */
86 	TUNNEL_CREATE,
87 	TUNNEL_CREATE_TYPE,
88 	TUNNEL_LIST,
89 	TUNNEL_DESTROY,
90 	TUNNEL_DESTROY_ID,
91 
92 	/* Destroy arguments. */
93 	DESTROY_RULE,
94 
95 	/* Query arguments. */
96 	QUERY_ACTION,
97 
98 	/* List arguments. */
99 	LIST_GROUP,
100 
101 	/* Destroy aged flow arguments. */
102 	AGED_DESTROY,
103 
104 	/* Validate/create arguments. */
105 	VC_GROUP,
106 	VC_PRIORITY,
107 	VC_INGRESS,
108 	VC_EGRESS,
109 	VC_TRANSFER,
110 	VC_TUNNEL_SET,
111 	VC_TUNNEL_MATCH,
112 
113 	/* Dump arguments */
114 	DUMP_ALL,
115 	DUMP_ONE,
116 
117 	/* Indirect action arguments */
118 	INDIRECT_ACTION_CREATE,
119 	INDIRECT_ACTION_UPDATE,
120 	INDIRECT_ACTION_DESTROY,
121 	INDIRECT_ACTION_QUERY,
122 
123 	/* Indirect action create arguments */
124 	INDIRECT_ACTION_CREATE_ID,
125 	INDIRECT_ACTION_INGRESS,
126 	INDIRECT_ACTION_EGRESS,
127 	INDIRECT_ACTION_TRANSFER,
128 	INDIRECT_ACTION_SPEC,
129 
130 	/* Indirect action destroy arguments */
131 	INDIRECT_ACTION_DESTROY_ID,
132 
133 	/* Validate/create pattern. */
134 	ITEM_PATTERN,
135 	ITEM_PARAM_IS,
136 	ITEM_PARAM_SPEC,
137 	ITEM_PARAM_LAST,
138 	ITEM_PARAM_MASK,
139 	ITEM_PARAM_PREFIX,
140 	ITEM_NEXT,
141 	ITEM_END,
142 	ITEM_VOID,
143 	ITEM_INVERT,
144 	ITEM_ANY,
145 	ITEM_ANY_NUM,
146 	ITEM_PF,
147 	ITEM_VF,
148 	ITEM_VF_ID,
149 	ITEM_PHY_PORT,
150 	ITEM_PHY_PORT_INDEX,
151 	ITEM_PORT_ID,
152 	ITEM_PORT_ID_ID,
153 	ITEM_MARK,
154 	ITEM_MARK_ID,
155 	ITEM_RAW,
156 	ITEM_RAW_RELATIVE,
157 	ITEM_RAW_SEARCH,
158 	ITEM_RAW_OFFSET,
159 	ITEM_RAW_LIMIT,
160 	ITEM_RAW_PATTERN,
161 	ITEM_ETH,
162 	ITEM_ETH_DST,
163 	ITEM_ETH_SRC,
164 	ITEM_ETH_TYPE,
165 	ITEM_ETH_HAS_VLAN,
166 	ITEM_VLAN,
167 	ITEM_VLAN_TCI,
168 	ITEM_VLAN_PCP,
169 	ITEM_VLAN_DEI,
170 	ITEM_VLAN_VID,
171 	ITEM_VLAN_INNER_TYPE,
172 	ITEM_VLAN_HAS_MORE_VLAN,
173 	ITEM_IPV4,
174 	ITEM_IPV4_VER_IHL,
175 	ITEM_IPV4_TOS,
176 	ITEM_IPV4_ID,
177 	ITEM_IPV4_FRAGMENT_OFFSET,
178 	ITEM_IPV4_TTL,
179 	ITEM_IPV4_PROTO,
180 	ITEM_IPV4_SRC,
181 	ITEM_IPV4_DST,
182 	ITEM_IPV6,
183 	ITEM_IPV6_TC,
184 	ITEM_IPV6_FLOW,
185 	ITEM_IPV6_PROTO,
186 	ITEM_IPV6_HOP,
187 	ITEM_IPV6_SRC,
188 	ITEM_IPV6_DST,
189 	ITEM_IPV6_HAS_FRAG_EXT,
190 	ITEM_ICMP,
191 	ITEM_ICMP_TYPE,
192 	ITEM_ICMP_CODE,
193 	ITEM_ICMP_IDENT,
194 	ITEM_ICMP_SEQ,
195 	ITEM_UDP,
196 	ITEM_UDP_SRC,
197 	ITEM_UDP_DST,
198 	ITEM_TCP,
199 	ITEM_TCP_SRC,
200 	ITEM_TCP_DST,
201 	ITEM_TCP_FLAGS,
202 	ITEM_SCTP,
203 	ITEM_SCTP_SRC,
204 	ITEM_SCTP_DST,
205 	ITEM_SCTP_TAG,
206 	ITEM_SCTP_CKSUM,
207 	ITEM_VXLAN,
208 	ITEM_VXLAN_VNI,
209 	ITEM_VXLAN_LAST_RSVD,
210 	ITEM_E_TAG,
211 	ITEM_E_TAG_GRP_ECID_B,
212 	ITEM_NVGRE,
213 	ITEM_NVGRE_TNI,
214 	ITEM_MPLS,
215 	ITEM_MPLS_LABEL,
216 	ITEM_MPLS_TC,
217 	ITEM_MPLS_S,
218 	ITEM_GRE,
219 	ITEM_GRE_PROTO,
220 	ITEM_GRE_C_RSVD0_VER,
221 	ITEM_GRE_C_BIT,
222 	ITEM_GRE_K_BIT,
223 	ITEM_GRE_S_BIT,
224 	ITEM_FUZZY,
225 	ITEM_FUZZY_THRESH,
226 	ITEM_GTP,
227 	ITEM_GTP_FLAGS,
228 	ITEM_GTP_MSG_TYPE,
229 	ITEM_GTP_TEID,
230 	ITEM_GTPC,
231 	ITEM_GTPU,
232 	ITEM_GENEVE,
233 	ITEM_GENEVE_VNI,
234 	ITEM_GENEVE_PROTO,
235 	ITEM_GENEVE_OPTLEN,
236 	ITEM_VXLAN_GPE,
237 	ITEM_VXLAN_GPE_VNI,
238 	ITEM_ARP_ETH_IPV4,
239 	ITEM_ARP_ETH_IPV4_SHA,
240 	ITEM_ARP_ETH_IPV4_SPA,
241 	ITEM_ARP_ETH_IPV4_THA,
242 	ITEM_ARP_ETH_IPV4_TPA,
243 	ITEM_IPV6_EXT,
244 	ITEM_IPV6_EXT_NEXT_HDR,
245 	ITEM_IPV6_FRAG_EXT,
246 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
247 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
248 	ITEM_IPV6_FRAG_EXT_ID,
249 	ITEM_ICMP6,
250 	ITEM_ICMP6_TYPE,
251 	ITEM_ICMP6_CODE,
252 	ITEM_ICMP6_ND_NS,
253 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
254 	ITEM_ICMP6_ND_NA,
255 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
256 	ITEM_ICMP6_ND_OPT,
257 	ITEM_ICMP6_ND_OPT_TYPE,
258 	ITEM_ICMP6_ND_OPT_SLA_ETH,
259 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
260 	ITEM_ICMP6_ND_OPT_TLA_ETH,
261 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
262 	ITEM_META,
263 	ITEM_META_DATA,
264 	ITEM_GRE_KEY,
265 	ITEM_GRE_KEY_VALUE,
266 	ITEM_GTP_PSC,
267 	ITEM_GTP_PSC_QFI,
268 	ITEM_GTP_PSC_PDU_T,
269 	ITEM_PPPOES,
270 	ITEM_PPPOED,
271 	ITEM_PPPOE_SEID,
272 	ITEM_PPPOE_PROTO_ID,
273 	ITEM_HIGIG2,
274 	ITEM_HIGIG2_CLASSIFICATION,
275 	ITEM_HIGIG2_VID,
276 	ITEM_TAG,
277 	ITEM_TAG_DATA,
278 	ITEM_TAG_INDEX,
279 	ITEM_L2TPV3OIP,
280 	ITEM_L2TPV3OIP_SESSION_ID,
281 	ITEM_ESP,
282 	ITEM_ESP_SPI,
283 	ITEM_AH,
284 	ITEM_AH_SPI,
285 	ITEM_PFCP,
286 	ITEM_PFCP_S_FIELD,
287 	ITEM_PFCP_SEID,
288 	ITEM_ECPRI,
289 	ITEM_ECPRI_COMMON,
290 	ITEM_ECPRI_COMMON_TYPE,
291 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
292 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
293 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
294 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
295 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
296 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
297 	ITEM_GENEVE_OPT,
298 	ITEM_GENEVE_OPT_CLASS,
299 	ITEM_GENEVE_OPT_TYPE,
300 	ITEM_GENEVE_OPT_LENGTH,
301 	ITEM_GENEVE_OPT_DATA,
302 	ITEM_INTEGRITY,
303 	ITEM_INTEGRITY_LEVEL,
304 	ITEM_INTEGRITY_VALUE,
305 	ITEM_CONNTRACK,
306 	ITEM_POL_PORT,
307 	ITEM_POL_METER,
308 	ITEM_POL_POLICY,
309 	ITEM_PORT_REPRESENTOR,
310 	ITEM_PORT_REPRESENTOR_PORT_ID,
311 	ITEM_REPRESENTED_PORT,
312 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
313 
314 	/* Validate/create actions. */
315 	ACTIONS,
316 	ACTION_NEXT,
317 	ACTION_END,
318 	ACTION_VOID,
319 	ACTION_PASSTHRU,
320 	ACTION_JUMP,
321 	ACTION_JUMP_GROUP,
322 	ACTION_MARK,
323 	ACTION_MARK_ID,
324 	ACTION_FLAG,
325 	ACTION_QUEUE,
326 	ACTION_QUEUE_INDEX,
327 	ACTION_DROP,
328 	ACTION_COUNT,
329 	ACTION_COUNT_ID,
330 	ACTION_RSS,
331 	ACTION_RSS_FUNC,
332 	ACTION_RSS_LEVEL,
333 	ACTION_RSS_FUNC_DEFAULT,
334 	ACTION_RSS_FUNC_TOEPLITZ,
335 	ACTION_RSS_FUNC_SIMPLE_XOR,
336 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
337 	ACTION_RSS_TYPES,
338 	ACTION_RSS_TYPE,
339 	ACTION_RSS_KEY,
340 	ACTION_RSS_KEY_LEN,
341 	ACTION_RSS_QUEUES,
342 	ACTION_RSS_QUEUE,
343 	ACTION_PF,
344 	ACTION_VF,
345 	ACTION_VF_ORIGINAL,
346 	ACTION_VF_ID,
347 	ACTION_PHY_PORT,
348 	ACTION_PHY_PORT_ORIGINAL,
349 	ACTION_PHY_PORT_INDEX,
350 	ACTION_PORT_ID,
351 	ACTION_PORT_ID_ORIGINAL,
352 	ACTION_PORT_ID_ID,
353 	ACTION_METER,
354 	ACTION_METER_COLOR,
355 	ACTION_METER_COLOR_TYPE,
356 	ACTION_METER_COLOR_GREEN,
357 	ACTION_METER_COLOR_YELLOW,
358 	ACTION_METER_COLOR_RED,
359 	ACTION_METER_ID,
360 	ACTION_OF_SET_MPLS_TTL,
361 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
362 	ACTION_OF_DEC_MPLS_TTL,
363 	ACTION_OF_SET_NW_TTL,
364 	ACTION_OF_SET_NW_TTL_NW_TTL,
365 	ACTION_OF_DEC_NW_TTL,
366 	ACTION_OF_COPY_TTL_OUT,
367 	ACTION_OF_COPY_TTL_IN,
368 	ACTION_OF_POP_VLAN,
369 	ACTION_OF_PUSH_VLAN,
370 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
371 	ACTION_OF_SET_VLAN_VID,
372 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
373 	ACTION_OF_SET_VLAN_PCP,
374 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
375 	ACTION_OF_POP_MPLS,
376 	ACTION_OF_POP_MPLS_ETHERTYPE,
377 	ACTION_OF_PUSH_MPLS,
378 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
379 	ACTION_VXLAN_ENCAP,
380 	ACTION_VXLAN_DECAP,
381 	ACTION_NVGRE_ENCAP,
382 	ACTION_NVGRE_DECAP,
383 	ACTION_L2_ENCAP,
384 	ACTION_L2_DECAP,
385 	ACTION_MPLSOGRE_ENCAP,
386 	ACTION_MPLSOGRE_DECAP,
387 	ACTION_MPLSOUDP_ENCAP,
388 	ACTION_MPLSOUDP_DECAP,
389 	ACTION_SET_IPV4_SRC,
390 	ACTION_SET_IPV4_SRC_IPV4_SRC,
391 	ACTION_SET_IPV4_DST,
392 	ACTION_SET_IPV4_DST_IPV4_DST,
393 	ACTION_SET_IPV6_SRC,
394 	ACTION_SET_IPV6_SRC_IPV6_SRC,
395 	ACTION_SET_IPV6_DST,
396 	ACTION_SET_IPV6_DST_IPV6_DST,
397 	ACTION_SET_TP_SRC,
398 	ACTION_SET_TP_SRC_TP_SRC,
399 	ACTION_SET_TP_DST,
400 	ACTION_SET_TP_DST_TP_DST,
401 	ACTION_MAC_SWAP,
402 	ACTION_DEC_TTL,
403 	ACTION_SET_TTL,
404 	ACTION_SET_TTL_TTL,
405 	ACTION_SET_MAC_SRC,
406 	ACTION_SET_MAC_SRC_MAC_SRC,
407 	ACTION_SET_MAC_DST,
408 	ACTION_SET_MAC_DST_MAC_DST,
409 	ACTION_INC_TCP_SEQ,
410 	ACTION_INC_TCP_SEQ_VALUE,
411 	ACTION_DEC_TCP_SEQ,
412 	ACTION_DEC_TCP_SEQ_VALUE,
413 	ACTION_INC_TCP_ACK,
414 	ACTION_INC_TCP_ACK_VALUE,
415 	ACTION_DEC_TCP_ACK,
416 	ACTION_DEC_TCP_ACK_VALUE,
417 	ACTION_RAW_ENCAP,
418 	ACTION_RAW_DECAP,
419 	ACTION_RAW_ENCAP_INDEX,
420 	ACTION_RAW_ENCAP_INDEX_VALUE,
421 	ACTION_RAW_DECAP_INDEX,
422 	ACTION_RAW_DECAP_INDEX_VALUE,
423 	ACTION_SET_TAG,
424 	ACTION_SET_TAG_DATA,
425 	ACTION_SET_TAG_INDEX,
426 	ACTION_SET_TAG_MASK,
427 	ACTION_SET_META,
428 	ACTION_SET_META_DATA,
429 	ACTION_SET_META_MASK,
430 	ACTION_SET_IPV4_DSCP,
431 	ACTION_SET_IPV4_DSCP_VALUE,
432 	ACTION_SET_IPV6_DSCP,
433 	ACTION_SET_IPV6_DSCP_VALUE,
434 	ACTION_AGE,
435 	ACTION_AGE_TIMEOUT,
436 	ACTION_SAMPLE,
437 	ACTION_SAMPLE_RATIO,
438 	ACTION_SAMPLE_INDEX,
439 	ACTION_SAMPLE_INDEX_VALUE,
440 	ACTION_INDIRECT,
441 	INDIRECT_ACTION_ID2PTR,
442 	ACTION_MODIFY_FIELD,
443 	ACTION_MODIFY_FIELD_OP,
444 	ACTION_MODIFY_FIELD_OP_VALUE,
445 	ACTION_MODIFY_FIELD_DST_TYPE,
446 	ACTION_MODIFY_FIELD_DST_TYPE_VALUE,
447 	ACTION_MODIFY_FIELD_DST_LEVEL,
448 	ACTION_MODIFY_FIELD_DST_OFFSET,
449 	ACTION_MODIFY_FIELD_SRC_TYPE,
450 	ACTION_MODIFY_FIELD_SRC_TYPE_VALUE,
451 	ACTION_MODIFY_FIELD_SRC_LEVEL,
452 	ACTION_MODIFY_FIELD_SRC_OFFSET,
453 	ACTION_MODIFY_FIELD_SRC_VALUE,
454 	ACTION_MODIFY_FIELD_WIDTH,
455 	ACTION_CONNTRACK,
456 	ACTION_CONNTRACK_UPDATE,
457 	ACTION_CONNTRACK_UPDATE_DIR,
458 	ACTION_CONNTRACK_UPDATE_CTX,
459 	ACTION_POL_G,
460 	ACTION_POL_Y,
461 	ACTION_POL_R,
462 	ACTION_PORT_REPRESENTOR,
463 	ACTION_PORT_REPRESENTOR_PORT_ID,
464 	ACTION_REPRESENTED_PORT,
465 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
466 };
467 
468 /** Maximum size for pattern in struct rte_flow_item_raw. */
469 #define ITEM_RAW_PATTERN_SIZE 40
470 
471 /** Maximum size for GENEVE option data pattern in bytes. */
472 #define ITEM_GENEVE_OPT_DATA_SIZE 124
473 
474 /** Storage size for struct rte_flow_item_raw including pattern. */
475 #define ITEM_RAW_SIZE \
476 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
477 
478 /** Maximum number of queue indices in struct rte_flow_action_rss. */
479 #define ACTION_RSS_QUEUE_NUM 128
480 
481 /** Storage for struct rte_flow_action_rss including external data. */
482 struct action_rss_data {
483 	struct rte_flow_action_rss conf;
484 	uint8_t key[RSS_HASH_KEY_LENGTH];
485 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
486 };
487 
488 /** Maximum data size in struct rte_flow_action_raw_encap. */
489 #define ACTION_RAW_ENCAP_MAX_DATA 512
490 #define RAW_ENCAP_CONFS_MAX_NUM 8
491 
492 /** Storage for struct rte_flow_action_raw_encap. */
493 struct raw_encap_conf {
494 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
495 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
496 	size_t size;
497 };
498 
499 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
500 
501 /** Storage for struct rte_flow_action_raw_encap including external data. */
502 struct action_raw_encap_data {
503 	struct rte_flow_action_raw_encap conf;
504 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
505 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
506 	uint16_t idx;
507 };
508 
509 /** Storage for struct rte_flow_action_raw_decap. */
510 struct raw_decap_conf {
511 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
512 	size_t size;
513 };
514 
515 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
516 
517 /** Storage for struct rte_flow_action_raw_decap including external data. */
518 struct action_raw_decap_data {
519 	struct rte_flow_action_raw_decap conf;
520 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
521 	uint16_t idx;
522 };
523 
524 struct vxlan_encap_conf vxlan_encap_conf = {
525 	.select_ipv4 = 1,
526 	.select_vlan = 0,
527 	.select_tos_ttl = 0,
528 	.vni = "\x00\x00\x00",
529 	.udp_src = 0,
530 	.udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT),
531 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
532 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
533 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
534 		"\x00\x00\x00\x00\x00\x00\x00\x01",
535 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
536 		"\x00\x00\x00\x00\x00\x00\x11\x11",
537 	.vlan_tci = 0,
538 	.ip_tos = 0,
539 	.ip_ttl = 255,
540 	.eth_src = "\x00\x00\x00\x00\x00\x00",
541 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
542 };
543 
544 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
545 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
546 
547 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
548 struct action_vxlan_encap_data {
549 	struct rte_flow_action_vxlan_encap conf;
550 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
551 	struct rte_flow_item_eth item_eth;
552 	struct rte_flow_item_vlan item_vlan;
553 	union {
554 		struct rte_flow_item_ipv4 item_ipv4;
555 		struct rte_flow_item_ipv6 item_ipv6;
556 	};
557 	struct rte_flow_item_udp item_udp;
558 	struct rte_flow_item_vxlan item_vxlan;
559 };
560 
561 struct nvgre_encap_conf nvgre_encap_conf = {
562 	.select_ipv4 = 1,
563 	.select_vlan = 0,
564 	.tni = "\x00\x00\x00",
565 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
566 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
567 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
568 		"\x00\x00\x00\x00\x00\x00\x00\x01",
569 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
570 		"\x00\x00\x00\x00\x00\x00\x11\x11",
571 	.vlan_tci = 0,
572 	.eth_src = "\x00\x00\x00\x00\x00\x00",
573 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
574 };
575 
576 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
577 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
578 
579 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
580 struct action_nvgre_encap_data {
581 	struct rte_flow_action_nvgre_encap conf;
582 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
583 	struct rte_flow_item_eth item_eth;
584 	struct rte_flow_item_vlan item_vlan;
585 	union {
586 		struct rte_flow_item_ipv4 item_ipv4;
587 		struct rte_flow_item_ipv6 item_ipv6;
588 	};
589 	struct rte_flow_item_nvgre item_nvgre;
590 };
591 
592 struct l2_encap_conf l2_encap_conf;
593 
594 struct l2_decap_conf l2_decap_conf;
595 
596 struct mplsogre_encap_conf mplsogre_encap_conf;
597 
598 struct mplsogre_decap_conf mplsogre_decap_conf;
599 
600 struct mplsoudp_encap_conf mplsoudp_encap_conf;
601 
602 struct mplsoudp_decap_conf mplsoudp_decap_conf;
603 
604 struct rte_flow_action_conntrack conntrack_context;
605 
606 #define ACTION_SAMPLE_ACTIONS_NUM 10
607 #define RAW_SAMPLE_CONFS_MAX_NUM 8
608 /** Storage for struct rte_flow_action_sample including external data. */
609 struct action_sample_data {
610 	struct rte_flow_action_sample conf;
611 	uint32_t idx;
612 };
613 /** Storage for struct rte_flow_action_sample. */
614 struct raw_sample_conf {
615 	struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM];
616 };
617 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM];
618 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM];
619 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM];
620 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM];
621 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM];
622 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM];
623 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM];
624 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM];
625 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM];
626 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM];
627 
628 static const char *const modify_field_ops[] = {
629 	"set", "add", "sub", NULL
630 };
631 
632 static const char *const modify_field_ids[] = {
633 	"start", "mac_dst", "mac_src",
634 	"vlan_type", "vlan_id", "mac_type",
635 	"ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst",
636 	"ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst",
637 	"tcp_port_src", "tcp_port_dst",
638 	"tcp_seq_num", "tcp_ack_num", "tcp_flags",
639 	"udp_port_src", "udp_port_dst",
640 	"vxlan_vni", "geneve_vni", "gtp_teid",
641 	"tag", "mark", "meta", "pointer", "value", NULL
642 };
643 
644 /** Maximum number of subsequent tokens and arguments on the stack. */
645 #define CTX_STACK_SIZE 16
646 
647 /** Parser context. */
648 struct context {
649 	/** Stack of subsequent token lists to process. */
650 	const enum index *next[CTX_STACK_SIZE];
651 	/** Arguments for stacked tokens. */
652 	const void *args[CTX_STACK_SIZE];
653 	enum index curr; /**< Current token index. */
654 	enum index prev; /**< Index of the last token seen. */
655 	int next_num; /**< Number of entries in next[]. */
656 	int args_num; /**< Number of entries in args[]. */
657 	uint32_t eol:1; /**< EOL has been detected. */
658 	uint32_t last:1; /**< No more arguments. */
659 	portid_t port; /**< Current port ID (for completions). */
660 	uint32_t objdata; /**< Object-specific data. */
661 	void *object; /**< Address of current object for relative offsets. */
662 	void *objmask; /**< Object a full mask must be written to. */
663 };
664 
665 /** Token argument. */
666 struct arg {
667 	uint32_t hton:1; /**< Use network byte ordering. */
668 	uint32_t sign:1; /**< Value is signed. */
669 	uint32_t bounded:1; /**< Value is bounded. */
670 	uintmax_t min; /**< Minimum value if bounded. */
671 	uintmax_t max; /**< Maximum value if bounded. */
672 	uint32_t offset; /**< Relative offset from ctx->object. */
673 	uint32_t size; /**< Field size. */
674 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
675 };
676 
677 /** Parser token definition. */
678 struct token {
679 	/** Type displayed during completion (defaults to "TOKEN"). */
680 	const char *type;
681 	/** Help displayed during completion (defaults to token name). */
682 	const char *help;
683 	/** Private data used by parser functions. */
684 	const void *priv;
685 	/**
686 	 * Lists of subsequent tokens to push on the stack. Each call to the
687 	 * parser consumes the last entry of that stack.
688 	 */
689 	const enum index *const *next;
690 	/** Arguments stack for subsequent tokens that need them. */
691 	const struct arg *const *args;
692 	/**
693 	 * Token-processing callback, returns -1 in case of error, the
694 	 * length of the matched string otherwise. If NULL, attempts to
695 	 * match the token name.
696 	 *
697 	 * If buf is not NULL, the result should be stored in it according
698 	 * to context. An error is returned if not large enough.
699 	 */
700 	int (*call)(struct context *ctx, const struct token *token,
701 		    const char *str, unsigned int len,
702 		    void *buf, unsigned int size);
703 	/**
704 	 * Callback that provides possible values for this token, used for
705 	 * completion. Returns -1 in case of error, the number of possible
706 	 * values otherwise. If NULL, the token name is used.
707 	 *
708 	 * If buf is not NULL, entry index ent is written to buf and the
709 	 * full length of the entry is returned (same behavior as
710 	 * snprintf()).
711 	 */
712 	int (*comp)(struct context *ctx, const struct token *token,
713 		    unsigned int ent, char *buf, unsigned int size);
714 	/** Mandatory token name, no default value. */
715 	const char *name;
716 };
717 
718 /** Static initializer for the next field. */
719 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
720 
721 /** Static initializer for a NEXT() entry. */
722 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
723 
724 /** Static initializer for the args field. */
725 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
726 
727 /** Static initializer for ARGS() to target a field. */
728 #define ARGS_ENTRY(s, f) \
729 	(&(const struct arg){ \
730 		.offset = offsetof(s, f), \
731 		.size = sizeof(((s *)0)->f), \
732 	})
733 
734 /** Static initializer for ARGS() to target a bit-field. */
735 #define ARGS_ENTRY_BF(s, f, b) \
736 	(&(const struct arg){ \
737 		.size = sizeof(s), \
738 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
739 	})
740 
741 /** Static initializer for ARGS() to target a field with limits. */
742 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \
743 	(&(const struct arg){ \
744 		.bounded = 1, \
745 		.min = (i), \
746 		.max = (a), \
747 		.offset = offsetof(s, f), \
748 		.size = sizeof(((s *)0)->f), \
749 	})
750 
751 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
752 #define ARGS_ENTRY_MASK(s, f, m) \
753 	(&(const struct arg){ \
754 		.offset = offsetof(s, f), \
755 		.size = sizeof(((s *)0)->f), \
756 		.mask = (const void *)(m), \
757 	})
758 
759 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
760 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
761 	(&(const struct arg){ \
762 		.hton = 1, \
763 		.offset = offsetof(s, f), \
764 		.size = sizeof(((s *)0)->f), \
765 		.mask = (const void *)(m), \
766 	})
767 
768 /** Static initializer for ARGS() to target a pointer. */
769 #define ARGS_ENTRY_PTR(s, f) \
770 	(&(const struct arg){ \
771 		.size = sizeof(*((s *)0)->f), \
772 	})
773 
774 /** Static initializer for ARGS() with arbitrary offset and size. */
775 #define ARGS_ENTRY_ARB(o, s) \
776 	(&(const struct arg){ \
777 		.offset = (o), \
778 		.size = (s), \
779 	})
780 
781 /** Same as ARGS_ENTRY_ARB() with bounded values. */
782 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
783 	(&(const struct arg){ \
784 		.bounded = 1, \
785 		.min = (i), \
786 		.max = (a), \
787 		.offset = (o), \
788 		.size = (s), \
789 	})
790 
791 /** Same as ARGS_ENTRY() using network byte ordering. */
792 #define ARGS_ENTRY_HTON(s, f) \
793 	(&(const struct arg){ \
794 		.hton = 1, \
795 		.offset = offsetof(s, f), \
796 		.size = sizeof(((s *)0)->f), \
797 	})
798 
799 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
800 #define ARG_ENTRY_HTON(s) \
801 	(&(const struct arg){ \
802 		.hton = 1, \
803 		.offset = 0, \
804 		.size = sizeof(s), \
805 	})
806 
807 /** Parser output buffer layout expected by cmd_flow_parsed(). */
808 struct buffer {
809 	enum index command; /**< Flow command. */
810 	portid_t port; /**< Affected port ID. */
811 	union {
812 		struct {
813 			uint32_t *action_id;
814 			uint32_t action_id_n;
815 		} ia_destroy; /**< Indirect action destroy arguments. */
816 		struct {
817 			uint32_t action_id;
818 		} ia; /* Indirect action query arguments */
819 		struct {
820 			struct rte_flow_attr attr;
821 			struct tunnel_ops tunnel_ops;
822 			struct rte_flow_item *pattern;
823 			struct rte_flow_action *actions;
824 			uint32_t pattern_n;
825 			uint32_t actions_n;
826 			uint8_t *data;
827 		} vc; /**< Validate/create arguments. */
828 		struct {
829 			uint32_t *rule;
830 			uint32_t rule_n;
831 		} destroy; /**< Destroy arguments. */
832 		struct {
833 			char file[128];
834 			bool mode;
835 			uint32_t rule;
836 		} dump; /**< Dump arguments. */
837 		struct {
838 			uint32_t rule;
839 			struct rte_flow_action action;
840 		} query; /**< Query arguments. */
841 		struct {
842 			uint32_t *group;
843 			uint32_t group_n;
844 		} list; /**< List arguments. */
845 		struct {
846 			int set;
847 		} isolate; /**< Isolated mode arguments. */
848 		struct {
849 			int destroy;
850 		} aged; /**< Aged arguments. */
851 		struct {
852 			uint32_t policy_id;
853 		} policy;/**< Policy arguments. */
854 	} args; /**< Command arguments. */
855 };
856 
857 /** Private data for pattern items. */
858 struct parse_item_priv {
859 	enum rte_flow_item_type type; /**< Item type. */
860 	uint32_t size; /**< Size of item specification structure. */
861 };
862 
863 #define PRIV_ITEM(t, s) \
864 	(&(const struct parse_item_priv){ \
865 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
866 		.size = s, \
867 	})
868 
869 /** Private data for actions. */
870 struct parse_action_priv {
871 	enum rte_flow_action_type type; /**< Action type. */
872 	uint32_t size; /**< Size of action configuration structure. */
873 };
874 
875 #define PRIV_ACTION(t, s) \
876 	(&(const struct parse_action_priv){ \
877 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
878 		.size = s, \
879 	})
880 
881 static const enum index next_ia_create_attr[] = {
882 	INDIRECT_ACTION_CREATE_ID,
883 	INDIRECT_ACTION_INGRESS,
884 	INDIRECT_ACTION_EGRESS,
885 	INDIRECT_ACTION_TRANSFER,
886 	INDIRECT_ACTION_SPEC,
887 	ZERO,
888 };
889 
890 static const enum index next_dump_subcmd[] = {
891 	DUMP_ALL,
892 	DUMP_ONE,
893 	ZERO,
894 };
895 
896 static const enum index next_ia_subcmd[] = {
897 	INDIRECT_ACTION_CREATE,
898 	INDIRECT_ACTION_UPDATE,
899 	INDIRECT_ACTION_DESTROY,
900 	INDIRECT_ACTION_QUERY,
901 	ZERO,
902 };
903 
904 static const enum index next_vc_attr[] = {
905 	VC_GROUP,
906 	VC_PRIORITY,
907 	VC_INGRESS,
908 	VC_EGRESS,
909 	VC_TRANSFER,
910 	VC_TUNNEL_SET,
911 	VC_TUNNEL_MATCH,
912 	ITEM_PATTERN,
913 	ZERO,
914 };
915 
916 static const enum index next_destroy_attr[] = {
917 	DESTROY_RULE,
918 	END,
919 	ZERO,
920 };
921 
922 static const enum index next_dump_attr[] = {
923 	COMMON_FILE_PATH,
924 	END,
925 	ZERO,
926 };
927 
928 static const enum index next_list_attr[] = {
929 	LIST_GROUP,
930 	END,
931 	ZERO,
932 };
933 
934 static const enum index next_aged_attr[] = {
935 	AGED_DESTROY,
936 	END,
937 	ZERO,
938 };
939 
940 static const enum index next_ia_destroy_attr[] = {
941 	INDIRECT_ACTION_DESTROY_ID,
942 	END,
943 	ZERO,
944 };
945 
946 static const enum index item_param[] = {
947 	ITEM_PARAM_IS,
948 	ITEM_PARAM_SPEC,
949 	ITEM_PARAM_LAST,
950 	ITEM_PARAM_MASK,
951 	ITEM_PARAM_PREFIX,
952 	ZERO,
953 };
954 
955 static const enum index next_item[] = {
956 	ITEM_END,
957 	ITEM_VOID,
958 	ITEM_INVERT,
959 	ITEM_ANY,
960 	ITEM_PF,
961 	ITEM_VF,
962 	ITEM_PHY_PORT,
963 	ITEM_PORT_ID,
964 	ITEM_MARK,
965 	ITEM_RAW,
966 	ITEM_ETH,
967 	ITEM_VLAN,
968 	ITEM_IPV4,
969 	ITEM_IPV6,
970 	ITEM_ICMP,
971 	ITEM_UDP,
972 	ITEM_TCP,
973 	ITEM_SCTP,
974 	ITEM_VXLAN,
975 	ITEM_E_TAG,
976 	ITEM_NVGRE,
977 	ITEM_MPLS,
978 	ITEM_GRE,
979 	ITEM_FUZZY,
980 	ITEM_GTP,
981 	ITEM_GTPC,
982 	ITEM_GTPU,
983 	ITEM_GENEVE,
984 	ITEM_VXLAN_GPE,
985 	ITEM_ARP_ETH_IPV4,
986 	ITEM_IPV6_EXT,
987 	ITEM_IPV6_FRAG_EXT,
988 	ITEM_ICMP6,
989 	ITEM_ICMP6_ND_NS,
990 	ITEM_ICMP6_ND_NA,
991 	ITEM_ICMP6_ND_OPT,
992 	ITEM_ICMP6_ND_OPT_SLA_ETH,
993 	ITEM_ICMP6_ND_OPT_TLA_ETH,
994 	ITEM_META,
995 	ITEM_GRE_KEY,
996 	ITEM_GTP_PSC,
997 	ITEM_PPPOES,
998 	ITEM_PPPOED,
999 	ITEM_PPPOE_PROTO_ID,
1000 	ITEM_HIGIG2,
1001 	ITEM_TAG,
1002 	ITEM_L2TPV3OIP,
1003 	ITEM_ESP,
1004 	ITEM_AH,
1005 	ITEM_PFCP,
1006 	ITEM_ECPRI,
1007 	ITEM_GENEVE_OPT,
1008 	ITEM_INTEGRITY,
1009 	ITEM_CONNTRACK,
1010 	ITEM_PORT_REPRESENTOR,
1011 	ITEM_REPRESENTED_PORT,
1012 	END_SET,
1013 	ZERO,
1014 };
1015 
1016 static const enum index item_fuzzy[] = {
1017 	ITEM_FUZZY_THRESH,
1018 	ITEM_NEXT,
1019 	ZERO,
1020 };
1021 
1022 static const enum index item_any[] = {
1023 	ITEM_ANY_NUM,
1024 	ITEM_NEXT,
1025 	ZERO,
1026 };
1027 
1028 static const enum index item_vf[] = {
1029 	ITEM_VF_ID,
1030 	ITEM_NEXT,
1031 	ZERO,
1032 };
1033 
1034 static const enum index item_phy_port[] = {
1035 	ITEM_PHY_PORT_INDEX,
1036 	ITEM_NEXT,
1037 	ZERO,
1038 };
1039 
1040 static const enum index item_port_id[] = {
1041 	ITEM_PORT_ID_ID,
1042 	ITEM_NEXT,
1043 	ZERO,
1044 };
1045 
1046 static const enum index item_mark[] = {
1047 	ITEM_MARK_ID,
1048 	ITEM_NEXT,
1049 	ZERO,
1050 };
1051 
1052 static const enum index item_raw[] = {
1053 	ITEM_RAW_RELATIVE,
1054 	ITEM_RAW_SEARCH,
1055 	ITEM_RAW_OFFSET,
1056 	ITEM_RAW_LIMIT,
1057 	ITEM_RAW_PATTERN,
1058 	ITEM_NEXT,
1059 	ZERO,
1060 };
1061 
1062 static const enum index item_eth[] = {
1063 	ITEM_ETH_DST,
1064 	ITEM_ETH_SRC,
1065 	ITEM_ETH_TYPE,
1066 	ITEM_ETH_HAS_VLAN,
1067 	ITEM_NEXT,
1068 	ZERO,
1069 };
1070 
1071 static const enum index item_vlan[] = {
1072 	ITEM_VLAN_TCI,
1073 	ITEM_VLAN_PCP,
1074 	ITEM_VLAN_DEI,
1075 	ITEM_VLAN_VID,
1076 	ITEM_VLAN_INNER_TYPE,
1077 	ITEM_VLAN_HAS_MORE_VLAN,
1078 	ITEM_NEXT,
1079 	ZERO,
1080 };
1081 
1082 static const enum index item_ipv4[] = {
1083 	ITEM_IPV4_VER_IHL,
1084 	ITEM_IPV4_TOS,
1085 	ITEM_IPV4_ID,
1086 	ITEM_IPV4_FRAGMENT_OFFSET,
1087 	ITEM_IPV4_TTL,
1088 	ITEM_IPV4_PROTO,
1089 	ITEM_IPV4_SRC,
1090 	ITEM_IPV4_DST,
1091 	ITEM_NEXT,
1092 	ZERO,
1093 };
1094 
1095 static const enum index item_ipv6[] = {
1096 	ITEM_IPV6_TC,
1097 	ITEM_IPV6_FLOW,
1098 	ITEM_IPV6_PROTO,
1099 	ITEM_IPV6_HOP,
1100 	ITEM_IPV6_SRC,
1101 	ITEM_IPV6_DST,
1102 	ITEM_IPV6_HAS_FRAG_EXT,
1103 	ITEM_NEXT,
1104 	ZERO,
1105 };
1106 
1107 static const enum index item_icmp[] = {
1108 	ITEM_ICMP_TYPE,
1109 	ITEM_ICMP_CODE,
1110 	ITEM_ICMP_IDENT,
1111 	ITEM_ICMP_SEQ,
1112 	ITEM_NEXT,
1113 	ZERO,
1114 };
1115 
1116 static const enum index item_udp[] = {
1117 	ITEM_UDP_SRC,
1118 	ITEM_UDP_DST,
1119 	ITEM_NEXT,
1120 	ZERO,
1121 };
1122 
1123 static const enum index item_tcp[] = {
1124 	ITEM_TCP_SRC,
1125 	ITEM_TCP_DST,
1126 	ITEM_TCP_FLAGS,
1127 	ITEM_NEXT,
1128 	ZERO,
1129 };
1130 
1131 static const enum index item_sctp[] = {
1132 	ITEM_SCTP_SRC,
1133 	ITEM_SCTP_DST,
1134 	ITEM_SCTP_TAG,
1135 	ITEM_SCTP_CKSUM,
1136 	ITEM_NEXT,
1137 	ZERO,
1138 };
1139 
1140 static const enum index item_vxlan[] = {
1141 	ITEM_VXLAN_VNI,
1142 	ITEM_VXLAN_LAST_RSVD,
1143 	ITEM_NEXT,
1144 	ZERO,
1145 };
1146 
1147 static const enum index item_e_tag[] = {
1148 	ITEM_E_TAG_GRP_ECID_B,
1149 	ITEM_NEXT,
1150 	ZERO,
1151 };
1152 
1153 static const enum index item_nvgre[] = {
1154 	ITEM_NVGRE_TNI,
1155 	ITEM_NEXT,
1156 	ZERO,
1157 };
1158 
1159 static const enum index item_mpls[] = {
1160 	ITEM_MPLS_LABEL,
1161 	ITEM_MPLS_TC,
1162 	ITEM_MPLS_S,
1163 	ITEM_NEXT,
1164 	ZERO,
1165 };
1166 
1167 static const enum index item_gre[] = {
1168 	ITEM_GRE_PROTO,
1169 	ITEM_GRE_C_RSVD0_VER,
1170 	ITEM_GRE_C_BIT,
1171 	ITEM_GRE_K_BIT,
1172 	ITEM_GRE_S_BIT,
1173 	ITEM_NEXT,
1174 	ZERO,
1175 };
1176 
1177 static const enum index item_gre_key[] = {
1178 	ITEM_GRE_KEY_VALUE,
1179 	ITEM_NEXT,
1180 	ZERO,
1181 };
1182 
1183 static const enum index item_gtp[] = {
1184 	ITEM_GTP_FLAGS,
1185 	ITEM_GTP_MSG_TYPE,
1186 	ITEM_GTP_TEID,
1187 	ITEM_NEXT,
1188 	ZERO,
1189 };
1190 
1191 static const enum index item_geneve[] = {
1192 	ITEM_GENEVE_VNI,
1193 	ITEM_GENEVE_PROTO,
1194 	ITEM_GENEVE_OPTLEN,
1195 	ITEM_NEXT,
1196 	ZERO,
1197 };
1198 
1199 static const enum index item_vxlan_gpe[] = {
1200 	ITEM_VXLAN_GPE_VNI,
1201 	ITEM_NEXT,
1202 	ZERO,
1203 };
1204 
1205 static const enum index item_arp_eth_ipv4[] = {
1206 	ITEM_ARP_ETH_IPV4_SHA,
1207 	ITEM_ARP_ETH_IPV4_SPA,
1208 	ITEM_ARP_ETH_IPV4_THA,
1209 	ITEM_ARP_ETH_IPV4_TPA,
1210 	ITEM_NEXT,
1211 	ZERO,
1212 };
1213 
1214 static const enum index item_ipv6_ext[] = {
1215 	ITEM_IPV6_EXT_NEXT_HDR,
1216 	ITEM_NEXT,
1217 	ZERO,
1218 };
1219 
1220 static const enum index item_ipv6_frag_ext[] = {
1221 	ITEM_IPV6_FRAG_EXT_NEXT_HDR,
1222 	ITEM_IPV6_FRAG_EXT_FRAG_DATA,
1223 	ITEM_IPV6_FRAG_EXT_ID,
1224 	ITEM_NEXT,
1225 	ZERO,
1226 };
1227 
1228 static const enum index item_icmp6[] = {
1229 	ITEM_ICMP6_TYPE,
1230 	ITEM_ICMP6_CODE,
1231 	ITEM_NEXT,
1232 	ZERO,
1233 };
1234 
1235 static const enum index item_icmp6_nd_ns[] = {
1236 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1237 	ITEM_NEXT,
1238 	ZERO,
1239 };
1240 
1241 static const enum index item_icmp6_nd_na[] = {
1242 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1243 	ITEM_NEXT,
1244 	ZERO,
1245 };
1246 
1247 static const enum index item_icmp6_nd_opt[] = {
1248 	ITEM_ICMP6_ND_OPT_TYPE,
1249 	ITEM_NEXT,
1250 	ZERO,
1251 };
1252 
1253 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1254 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1255 	ITEM_NEXT,
1256 	ZERO,
1257 };
1258 
1259 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1260 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1261 	ITEM_NEXT,
1262 	ZERO,
1263 };
1264 
1265 static const enum index item_meta[] = {
1266 	ITEM_META_DATA,
1267 	ITEM_NEXT,
1268 	ZERO,
1269 };
1270 
1271 static const enum index item_gtp_psc[] = {
1272 	ITEM_GTP_PSC_QFI,
1273 	ITEM_GTP_PSC_PDU_T,
1274 	ITEM_NEXT,
1275 	ZERO,
1276 };
1277 
1278 static const enum index item_pppoed[] = {
1279 	ITEM_PPPOE_SEID,
1280 	ITEM_NEXT,
1281 	ZERO,
1282 };
1283 
1284 static const enum index item_pppoes[] = {
1285 	ITEM_PPPOE_SEID,
1286 	ITEM_NEXT,
1287 	ZERO,
1288 };
1289 
1290 static const enum index item_pppoe_proto_id[] = {
1291 	ITEM_NEXT,
1292 	ZERO,
1293 };
1294 
1295 static const enum index item_higig2[] = {
1296 	ITEM_HIGIG2_CLASSIFICATION,
1297 	ITEM_HIGIG2_VID,
1298 	ITEM_NEXT,
1299 	ZERO,
1300 };
1301 
1302 static const enum index item_esp[] = {
1303 	ITEM_ESP_SPI,
1304 	ITEM_NEXT,
1305 	ZERO,
1306 };
1307 
1308 static const enum index item_ah[] = {
1309 	ITEM_AH_SPI,
1310 	ITEM_NEXT,
1311 	ZERO,
1312 };
1313 
1314 static const enum index item_pfcp[] = {
1315 	ITEM_PFCP_S_FIELD,
1316 	ITEM_PFCP_SEID,
1317 	ITEM_NEXT,
1318 	ZERO,
1319 };
1320 
1321 static const enum index next_set_raw[] = {
1322 	SET_RAW_INDEX,
1323 	ITEM_ETH,
1324 	ZERO,
1325 };
1326 
1327 static const enum index item_tag[] = {
1328 	ITEM_TAG_DATA,
1329 	ITEM_TAG_INDEX,
1330 	ITEM_NEXT,
1331 	ZERO,
1332 };
1333 
1334 static const enum index item_l2tpv3oip[] = {
1335 	ITEM_L2TPV3OIP_SESSION_ID,
1336 	ITEM_NEXT,
1337 	ZERO,
1338 };
1339 
1340 static const enum index item_ecpri[] = {
1341 	ITEM_ECPRI_COMMON,
1342 	ITEM_NEXT,
1343 	ZERO,
1344 };
1345 
1346 static const enum index item_ecpri_common[] = {
1347 	ITEM_ECPRI_COMMON_TYPE,
1348 	ZERO,
1349 };
1350 
1351 static const enum index item_ecpri_common_type[] = {
1352 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1353 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1354 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1355 	ZERO,
1356 };
1357 
1358 static const enum index item_geneve_opt[] = {
1359 	ITEM_GENEVE_OPT_CLASS,
1360 	ITEM_GENEVE_OPT_TYPE,
1361 	ITEM_GENEVE_OPT_LENGTH,
1362 	ITEM_GENEVE_OPT_DATA,
1363 	ITEM_NEXT,
1364 	ZERO,
1365 };
1366 
1367 static const enum index item_integrity[] = {
1368 	ITEM_INTEGRITY_LEVEL,
1369 	ITEM_INTEGRITY_VALUE,
1370 	ZERO,
1371 };
1372 
1373 static const enum index item_integrity_lv[] = {
1374 	ITEM_INTEGRITY_LEVEL,
1375 	ITEM_INTEGRITY_VALUE,
1376 	ITEM_NEXT,
1377 	ZERO,
1378 };
1379 
1380 static const enum index item_port_representor[] = {
1381 	ITEM_PORT_REPRESENTOR_PORT_ID,
1382 	ITEM_NEXT,
1383 	ZERO,
1384 };
1385 
1386 static const enum index item_represented_port[] = {
1387 	ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID,
1388 	ITEM_NEXT,
1389 	ZERO,
1390 };
1391 
1392 static const enum index next_action[] = {
1393 	ACTION_END,
1394 	ACTION_VOID,
1395 	ACTION_PASSTHRU,
1396 	ACTION_JUMP,
1397 	ACTION_MARK,
1398 	ACTION_FLAG,
1399 	ACTION_QUEUE,
1400 	ACTION_DROP,
1401 	ACTION_COUNT,
1402 	ACTION_RSS,
1403 	ACTION_PF,
1404 	ACTION_VF,
1405 	ACTION_PHY_PORT,
1406 	ACTION_PORT_ID,
1407 	ACTION_METER,
1408 	ACTION_METER_COLOR,
1409 	ACTION_OF_SET_MPLS_TTL,
1410 	ACTION_OF_DEC_MPLS_TTL,
1411 	ACTION_OF_SET_NW_TTL,
1412 	ACTION_OF_DEC_NW_TTL,
1413 	ACTION_OF_COPY_TTL_OUT,
1414 	ACTION_OF_COPY_TTL_IN,
1415 	ACTION_OF_POP_VLAN,
1416 	ACTION_OF_PUSH_VLAN,
1417 	ACTION_OF_SET_VLAN_VID,
1418 	ACTION_OF_SET_VLAN_PCP,
1419 	ACTION_OF_POP_MPLS,
1420 	ACTION_OF_PUSH_MPLS,
1421 	ACTION_VXLAN_ENCAP,
1422 	ACTION_VXLAN_DECAP,
1423 	ACTION_NVGRE_ENCAP,
1424 	ACTION_NVGRE_DECAP,
1425 	ACTION_L2_ENCAP,
1426 	ACTION_L2_DECAP,
1427 	ACTION_MPLSOGRE_ENCAP,
1428 	ACTION_MPLSOGRE_DECAP,
1429 	ACTION_MPLSOUDP_ENCAP,
1430 	ACTION_MPLSOUDP_DECAP,
1431 	ACTION_SET_IPV4_SRC,
1432 	ACTION_SET_IPV4_DST,
1433 	ACTION_SET_IPV6_SRC,
1434 	ACTION_SET_IPV6_DST,
1435 	ACTION_SET_TP_SRC,
1436 	ACTION_SET_TP_DST,
1437 	ACTION_MAC_SWAP,
1438 	ACTION_DEC_TTL,
1439 	ACTION_SET_TTL,
1440 	ACTION_SET_MAC_SRC,
1441 	ACTION_SET_MAC_DST,
1442 	ACTION_INC_TCP_SEQ,
1443 	ACTION_DEC_TCP_SEQ,
1444 	ACTION_INC_TCP_ACK,
1445 	ACTION_DEC_TCP_ACK,
1446 	ACTION_RAW_ENCAP,
1447 	ACTION_RAW_DECAP,
1448 	ACTION_SET_TAG,
1449 	ACTION_SET_META,
1450 	ACTION_SET_IPV4_DSCP,
1451 	ACTION_SET_IPV6_DSCP,
1452 	ACTION_AGE,
1453 	ACTION_SAMPLE,
1454 	ACTION_INDIRECT,
1455 	ACTION_MODIFY_FIELD,
1456 	ACTION_CONNTRACK,
1457 	ACTION_CONNTRACK_UPDATE,
1458 	ACTION_PORT_REPRESENTOR,
1459 	ACTION_REPRESENTED_PORT,
1460 	ZERO,
1461 };
1462 
1463 static const enum index action_mark[] = {
1464 	ACTION_MARK_ID,
1465 	ACTION_NEXT,
1466 	ZERO,
1467 };
1468 
1469 static const enum index action_queue[] = {
1470 	ACTION_QUEUE_INDEX,
1471 	ACTION_NEXT,
1472 	ZERO,
1473 };
1474 
1475 static const enum index action_count[] = {
1476 	ACTION_COUNT_ID,
1477 	ACTION_NEXT,
1478 	ZERO,
1479 };
1480 
1481 static const enum index action_rss[] = {
1482 	ACTION_RSS_FUNC,
1483 	ACTION_RSS_LEVEL,
1484 	ACTION_RSS_TYPES,
1485 	ACTION_RSS_KEY,
1486 	ACTION_RSS_KEY_LEN,
1487 	ACTION_RSS_QUEUES,
1488 	ACTION_NEXT,
1489 	ZERO,
1490 };
1491 
1492 static const enum index action_vf[] = {
1493 	ACTION_VF_ORIGINAL,
1494 	ACTION_VF_ID,
1495 	ACTION_NEXT,
1496 	ZERO,
1497 };
1498 
1499 static const enum index action_phy_port[] = {
1500 	ACTION_PHY_PORT_ORIGINAL,
1501 	ACTION_PHY_PORT_INDEX,
1502 	ACTION_NEXT,
1503 	ZERO,
1504 };
1505 
1506 static const enum index action_port_id[] = {
1507 	ACTION_PORT_ID_ORIGINAL,
1508 	ACTION_PORT_ID_ID,
1509 	ACTION_NEXT,
1510 	ZERO,
1511 };
1512 
1513 static const enum index action_meter[] = {
1514 	ACTION_METER_ID,
1515 	ACTION_NEXT,
1516 	ZERO,
1517 };
1518 
1519 static const enum index action_meter_color[] = {
1520 	ACTION_METER_COLOR_TYPE,
1521 	ACTION_NEXT,
1522 	ZERO,
1523 };
1524 
1525 static const enum index action_of_set_mpls_ttl[] = {
1526 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1527 	ACTION_NEXT,
1528 	ZERO,
1529 };
1530 
1531 static const enum index action_of_set_nw_ttl[] = {
1532 	ACTION_OF_SET_NW_TTL_NW_TTL,
1533 	ACTION_NEXT,
1534 	ZERO,
1535 };
1536 
1537 static const enum index action_of_push_vlan[] = {
1538 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
1539 	ACTION_NEXT,
1540 	ZERO,
1541 };
1542 
1543 static const enum index action_of_set_vlan_vid[] = {
1544 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
1545 	ACTION_NEXT,
1546 	ZERO,
1547 };
1548 
1549 static const enum index action_of_set_vlan_pcp[] = {
1550 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1551 	ACTION_NEXT,
1552 	ZERO,
1553 };
1554 
1555 static const enum index action_of_pop_mpls[] = {
1556 	ACTION_OF_POP_MPLS_ETHERTYPE,
1557 	ACTION_NEXT,
1558 	ZERO,
1559 };
1560 
1561 static const enum index action_of_push_mpls[] = {
1562 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
1563 	ACTION_NEXT,
1564 	ZERO,
1565 };
1566 
1567 static const enum index action_set_ipv4_src[] = {
1568 	ACTION_SET_IPV4_SRC_IPV4_SRC,
1569 	ACTION_NEXT,
1570 	ZERO,
1571 };
1572 
1573 static const enum index action_set_mac_src[] = {
1574 	ACTION_SET_MAC_SRC_MAC_SRC,
1575 	ACTION_NEXT,
1576 	ZERO,
1577 };
1578 
1579 static const enum index action_set_ipv4_dst[] = {
1580 	ACTION_SET_IPV4_DST_IPV4_DST,
1581 	ACTION_NEXT,
1582 	ZERO,
1583 };
1584 
1585 static const enum index action_set_ipv6_src[] = {
1586 	ACTION_SET_IPV6_SRC_IPV6_SRC,
1587 	ACTION_NEXT,
1588 	ZERO,
1589 };
1590 
1591 static const enum index action_set_ipv6_dst[] = {
1592 	ACTION_SET_IPV6_DST_IPV6_DST,
1593 	ACTION_NEXT,
1594 	ZERO,
1595 };
1596 
1597 static const enum index action_set_tp_src[] = {
1598 	ACTION_SET_TP_SRC_TP_SRC,
1599 	ACTION_NEXT,
1600 	ZERO,
1601 };
1602 
1603 static const enum index action_set_tp_dst[] = {
1604 	ACTION_SET_TP_DST_TP_DST,
1605 	ACTION_NEXT,
1606 	ZERO,
1607 };
1608 
1609 static const enum index action_set_ttl[] = {
1610 	ACTION_SET_TTL_TTL,
1611 	ACTION_NEXT,
1612 	ZERO,
1613 };
1614 
1615 static const enum index action_jump[] = {
1616 	ACTION_JUMP_GROUP,
1617 	ACTION_NEXT,
1618 	ZERO,
1619 };
1620 
1621 static const enum index action_set_mac_dst[] = {
1622 	ACTION_SET_MAC_DST_MAC_DST,
1623 	ACTION_NEXT,
1624 	ZERO,
1625 };
1626 
1627 static const enum index action_inc_tcp_seq[] = {
1628 	ACTION_INC_TCP_SEQ_VALUE,
1629 	ACTION_NEXT,
1630 	ZERO,
1631 };
1632 
1633 static const enum index action_dec_tcp_seq[] = {
1634 	ACTION_DEC_TCP_SEQ_VALUE,
1635 	ACTION_NEXT,
1636 	ZERO,
1637 };
1638 
1639 static const enum index action_inc_tcp_ack[] = {
1640 	ACTION_INC_TCP_ACK_VALUE,
1641 	ACTION_NEXT,
1642 	ZERO,
1643 };
1644 
1645 static const enum index action_dec_tcp_ack[] = {
1646 	ACTION_DEC_TCP_ACK_VALUE,
1647 	ACTION_NEXT,
1648 	ZERO,
1649 };
1650 
1651 static const enum index action_raw_encap[] = {
1652 	ACTION_RAW_ENCAP_INDEX,
1653 	ACTION_NEXT,
1654 	ZERO,
1655 };
1656 
1657 static const enum index action_raw_decap[] = {
1658 	ACTION_RAW_DECAP_INDEX,
1659 	ACTION_NEXT,
1660 	ZERO,
1661 };
1662 
1663 static const enum index action_set_tag[] = {
1664 	ACTION_SET_TAG_DATA,
1665 	ACTION_SET_TAG_INDEX,
1666 	ACTION_SET_TAG_MASK,
1667 	ACTION_NEXT,
1668 	ZERO,
1669 };
1670 
1671 static const enum index action_set_meta[] = {
1672 	ACTION_SET_META_DATA,
1673 	ACTION_SET_META_MASK,
1674 	ACTION_NEXT,
1675 	ZERO,
1676 };
1677 
1678 static const enum index action_set_ipv4_dscp[] = {
1679 	ACTION_SET_IPV4_DSCP_VALUE,
1680 	ACTION_NEXT,
1681 	ZERO,
1682 };
1683 
1684 static const enum index action_set_ipv6_dscp[] = {
1685 	ACTION_SET_IPV6_DSCP_VALUE,
1686 	ACTION_NEXT,
1687 	ZERO,
1688 };
1689 
1690 static const enum index action_age[] = {
1691 	ACTION_AGE,
1692 	ACTION_AGE_TIMEOUT,
1693 	ACTION_NEXT,
1694 	ZERO,
1695 };
1696 
1697 static const enum index action_sample[] = {
1698 	ACTION_SAMPLE,
1699 	ACTION_SAMPLE_RATIO,
1700 	ACTION_SAMPLE_INDEX,
1701 	ACTION_NEXT,
1702 	ZERO,
1703 };
1704 
1705 static const enum index next_action_sample[] = {
1706 	ACTION_QUEUE,
1707 	ACTION_RSS,
1708 	ACTION_MARK,
1709 	ACTION_COUNT,
1710 	ACTION_PORT_ID,
1711 	ACTION_RAW_ENCAP,
1712 	ACTION_VXLAN_ENCAP,
1713 	ACTION_NVGRE_ENCAP,
1714 	ACTION_NEXT,
1715 	ZERO,
1716 };
1717 
1718 static const enum index action_modify_field_dst[] = {
1719 	ACTION_MODIFY_FIELD_DST_LEVEL,
1720 	ACTION_MODIFY_FIELD_DST_OFFSET,
1721 	ACTION_MODIFY_FIELD_SRC_TYPE,
1722 	ZERO,
1723 };
1724 
1725 static const enum index action_modify_field_src[] = {
1726 	ACTION_MODIFY_FIELD_SRC_LEVEL,
1727 	ACTION_MODIFY_FIELD_SRC_OFFSET,
1728 	ACTION_MODIFY_FIELD_SRC_VALUE,
1729 	ACTION_MODIFY_FIELD_WIDTH,
1730 	ZERO,
1731 };
1732 
1733 static const enum index action_update_conntrack[] = {
1734 	ACTION_CONNTRACK_UPDATE_DIR,
1735 	ACTION_CONNTRACK_UPDATE_CTX,
1736 	ACTION_NEXT,
1737 	ZERO,
1738 };
1739 
1740 static const enum index action_port_representor[] = {
1741 	ACTION_PORT_REPRESENTOR_PORT_ID,
1742 	ACTION_NEXT,
1743 	ZERO,
1744 };
1745 
1746 static const enum index action_represented_port[] = {
1747 	ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
1748 	ACTION_NEXT,
1749 	ZERO,
1750 };
1751 
1752 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1753 				     const char *, unsigned int,
1754 				     void *, unsigned int);
1755 static int parse_set_sample_action(struct context *, const struct token *,
1756 				   const char *, unsigned int,
1757 				   void *, unsigned int);
1758 static int parse_set_init(struct context *, const struct token *,
1759 			  const char *, unsigned int,
1760 			  void *, unsigned int);
1761 static int parse_init(struct context *, const struct token *,
1762 		      const char *, unsigned int,
1763 		      void *, unsigned int);
1764 static int parse_vc(struct context *, const struct token *,
1765 		    const char *, unsigned int,
1766 		    void *, unsigned int);
1767 static int parse_vc_spec(struct context *, const struct token *,
1768 			 const char *, unsigned int, void *, unsigned int);
1769 static int parse_vc_conf(struct context *, const struct token *,
1770 			 const char *, unsigned int, void *, unsigned int);
1771 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1772 				    const char *, unsigned int,
1773 				    void *, unsigned int);
1774 static int parse_vc_action_meter_color_type(struct context *,
1775 					const struct token *,
1776 					const char *, unsigned int, void *,
1777 					unsigned int);
1778 static int parse_vc_action_rss(struct context *, const struct token *,
1779 			       const char *, unsigned int, void *,
1780 			       unsigned int);
1781 static int parse_vc_action_rss_func(struct context *, const struct token *,
1782 				    const char *, unsigned int, void *,
1783 				    unsigned int);
1784 static int parse_vc_action_rss_type(struct context *, const struct token *,
1785 				    const char *, unsigned int, void *,
1786 				    unsigned int);
1787 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1788 				     const char *, unsigned int, void *,
1789 				     unsigned int);
1790 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1791 				       const char *, unsigned int, void *,
1792 				       unsigned int);
1793 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1794 				       const char *, unsigned int, void *,
1795 				       unsigned int);
1796 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1797 				    const char *, unsigned int, void *,
1798 				    unsigned int);
1799 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1800 				    const char *, unsigned int, void *,
1801 				    unsigned int);
1802 static int parse_vc_action_mplsogre_encap(struct context *,
1803 					  const struct token *, const char *,
1804 					  unsigned int, void *, unsigned int);
1805 static int parse_vc_action_mplsogre_decap(struct context *,
1806 					  const struct token *, const char *,
1807 					  unsigned int, void *, unsigned int);
1808 static int parse_vc_action_mplsoudp_encap(struct context *,
1809 					  const struct token *, const char *,
1810 					  unsigned int, void *, unsigned int);
1811 static int parse_vc_action_mplsoudp_decap(struct context *,
1812 					  const struct token *, const char *,
1813 					  unsigned int, void *, unsigned int);
1814 static int parse_vc_action_raw_encap(struct context *,
1815 				     const struct token *, const char *,
1816 				     unsigned int, void *, unsigned int);
1817 static int parse_vc_action_raw_decap(struct context *,
1818 				     const struct token *, const char *,
1819 				     unsigned int, void *, unsigned int);
1820 static int parse_vc_action_raw_encap_index(struct context *,
1821 					   const struct token *, const char *,
1822 					   unsigned int, void *, unsigned int);
1823 static int parse_vc_action_raw_decap_index(struct context *,
1824 					   const struct token *, const char *,
1825 					   unsigned int, void *, unsigned int);
1826 static int parse_vc_action_set_meta(struct context *ctx,
1827 				    const struct token *token, const char *str,
1828 				    unsigned int len, void *buf,
1829 					unsigned int size);
1830 static int parse_vc_action_sample(struct context *ctx,
1831 				    const struct token *token, const char *str,
1832 				    unsigned int len, void *buf,
1833 				    unsigned int size);
1834 static int
1835 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
1836 				const char *str, unsigned int len, void *buf,
1837 				unsigned int size);
1838 static int
1839 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
1840 				const char *str, unsigned int len, void *buf,
1841 				unsigned int size);
1842 static int
1843 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
1844 				const char *str, unsigned int len, void *buf,
1845 				unsigned int size);
1846 static int
1847 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
1848 			 const char *str, unsigned int len, void *buf,
1849 			 unsigned int size);
1850 static int parse_destroy(struct context *, const struct token *,
1851 			 const char *, unsigned int,
1852 			 void *, unsigned int);
1853 static int parse_flush(struct context *, const struct token *,
1854 		       const char *, unsigned int,
1855 		       void *, unsigned int);
1856 static int parse_dump(struct context *, const struct token *,
1857 		      const char *, unsigned int,
1858 		      void *, unsigned int);
1859 static int parse_query(struct context *, const struct token *,
1860 		       const char *, unsigned int,
1861 		       void *, unsigned int);
1862 static int parse_action(struct context *, const struct token *,
1863 			const char *, unsigned int,
1864 			void *, unsigned int);
1865 static int parse_list(struct context *, const struct token *,
1866 		      const char *, unsigned int,
1867 		      void *, unsigned int);
1868 static int parse_aged(struct context *, const struct token *,
1869 		      const char *, unsigned int,
1870 		      void *, unsigned int);
1871 static int parse_isolate(struct context *, const struct token *,
1872 			 const char *, unsigned int,
1873 			 void *, unsigned int);
1874 static int parse_tunnel(struct context *, const struct token *,
1875 			const char *, unsigned int,
1876 			void *, unsigned int);
1877 static int parse_int(struct context *, const struct token *,
1878 		     const char *, unsigned int,
1879 		     void *, unsigned int);
1880 static int parse_prefix(struct context *, const struct token *,
1881 			const char *, unsigned int,
1882 			void *, unsigned int);
1883 static int parse_boolean(struct context *, const struct token *,
1884 			 const char *, unsigned int,
1885 			 void *, unsigned int);
1886 static int parse_string(struct context *, const struct token *,
1887 			const char *, unsigned int,
1888 			void *, unsigned int);
1889 static int parse_hex(struct context *ctx, const struct token *token,
1890 			const char *str, unsigned int len,
1891 			void *buf, unsigned int size);
1892 static int parse_string0(struct context *, const struct token *,
1893 			const char *, unsigned int,
1894 			void *, unsigned int);
1895 static int parse_mac_addr(struct context *, const struct token *,
1896 			  const char *, unsigned int,
1897 			  void *, unsigned int);
1898 static int parse_ipv4_addr(struct context *, const struct token *,
1899 			   const char *, unsigned int,
1900 			   void *, unsigned int);
1901 static int parse_ipv6_addr(struct context *, const struct token *,
1902 			   const char *, unsigned int,
1903 			   void *, unsigned int);
1904 static int parse_port(struct context *, const struct token *,
1905 		      const char *, unsigned int,
1906 		      void *, unsigned int);
1907 static int parse_ia(struct context *, const struct token *,
1908 		    const char *, unsigned int,
1909 		    void *, unsigned int);
1910 static int parse_ia_destroy(struct context *ctx, const struct token *token,
1911 			    const char *str, unsigned int len,
1912 			    void *buf, unsigned int size);
1913 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
1914 			   const char *str, unsigned int len, void *buf,
1915 			   unsigned int size);
1916 static int parse_mp(struct context *, const struct token *,
1917 		    const char *, unsigned int,
1918 		    void *, unsigned int);
1919 static int comp_none(struct context *, const struct token *,
1920 		     unsigned int, char *, unsigned int);
1921 static int comp_boolean(struct context *, const struct token *,
1922 			unsigned int, char *, unsigned int);
1923 static int comp_action(struct context *, const struct token *,
1924 		       unsigned int, char *, unsigned int);
1925 static int comp_port(struct context *, const struct token *,
1926 		     unsigned int, char *, unsigned int);
1927 static int comp_rule_id(struct context *, const struct token *,
1928 			unsigned int, char *, unsigned int);
1929 static int comp_vc_action_rss_type(struct context *, const struct token *,
1930 				   unsigned int, char *, unsigned int);
1931 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1932 				    unsigned int, char *, unsigned int);
1933 static int comp_set_raw_index(struct context *, const struct token *,
1934 			      unsigned int, char *, unsigned int);
1935 static int comp_set_sample_index(struct context *, const struct token *,
1936 			      unsigned int, char *, unsigned int);
1937 static int comp_set_modify_field_op(struct context *, const struct token *,
1938 			      unsigned int, char *, unsigned int);
1939 static int comp_set_modify_field_id(struct context *, const struct token *,
1940 			      unsigned int, char *, unsigned int);
1941 
1942 /** Token definitions. */
1943 static const struct token token_list[] = {
1944 	/* Special tokens. */
1945 	[ZERO] = {
1946 		.name = "ZERO",
1947 		.help = "null entry, abused as the entry point",
1948 		.next = NEXT(NEXT_ENTRY(FLOW, ADD)),
1949 	},
1950 	[END] = {
1951 		.name = "",
1952 		.type = "RETURN",
1953 		.help = "command may end here",
1954 	},
1955 	[START_SET] = {
1956 		.name = "START_SET",
1957 		.help = "null entry, abused as the entry point for set",
1958 		.next = NEXT(NEXT_ENTRY(SET)),
1959 	},
1960 	[END_SET] = {
1961 		.name = "end_set",
1962 		.type = "RETURN",
1963 		.help = "set command may end here",
1964 	},
1965 	/* Common tokens. */
1966 	[COMMON_INTEGER] = {
1967 		.name = "{int}",
1968 		.type = "INTEGER",
1969 		.help = "integer value",
1970 		.call = parse_int,
1971 		.comp = comp_none,
1972 	},
1973 	[COMMON_UNSIGNED] = {
1974 		.name = "{unsigned}",
1975 		.type = "UNSIGNED",
1976 		.help = "unsigned integer value",
1977 		.call = parse_int,
1978 		.comp = comp_none,
1979 	},
1980 	[COMMON_PREFIX] = {
1981 		.name = "{prefix}",
1982 		.type = "PREFIX",
1983 		.help = "prefix length for bit-mask",
1984 		.call = parse_prefix,
1985 		.comp = comp_none,
1986 	},
1987 	[COMMON_BOOLEAN] = {
1988 		.name = "{boolean}",
1989 		.type = "BOOLEAN",
1990 		.help = "any boolean value",
1991 		.call = parse_boolean,
1992 		.comp = comp_boolean,
1993 	},
1994 	[COMMON_STRING] = {
1995 		.name = "{string}",
1996 		.type = "STRING",
1997 		.help = "fixed string",
1998 		.call = parse_string,
1999 		.comp = comp_none,
2000 	},
2001 	[COMMON_HEX] = {
2002 		.name = "{hex}",
2003 		.type = "HEX",
2004 		.help = "fixed string",
2005 		.call = parse_hex,
2006 	},
2007 	[COMMON_FILE_PATH] = {
2008 		.name = "{file path}",
2009 		.type = "STRING",
2010 		.help = "file path",
2011 		.call = parse_string0,
2012 		.comp = comp_none,
2013 	},
2014 	[COMMON_MAC_ADDR] = {
2015 		.name = "{MAC address}",
2016 		.type = "MAC-48",
2017 		.help = "standard MAC address notation",
2018 		.call = parse_mac_addr,
2019 		.comp = comp_none,
2020 	},
2021 	[COMMON_IPV4_ADDR] = {
2022 		.name = "{IPv4 address}",
2023 		.type = "IPV4 ADDRESS",
2024 		.help = "standard IPv4 address notation",
2025 		.call = parse_ipv4_addr,
2026 		.comp = comp_none,
2027 	},
2028 	[COMMON_IPV6_ADDR] = {
2029 		.name = "{IPv6 address}",
2030 		.type = "IPV6 ADDRESS",
2031 		.help = "standard IPv6 address notation",
2032 		.call = parse_ipv6_addr,
2033 		.comp = comp_none,
2034 	},
2035 	[COMMON_RULE_ID] = {
2036 		.name = "{rule id}",
2037 		.type = "RULE ID",
2038 		.help = "rule identifier",
2039 		.call = parse_int,
2040 		.comp = comp_rule_id,
2041 	},
2042 	[COMMON_PORT_ID] = {
2043 		.name = "{port_id}",
2044 		.type = "PORT ID",
2045 		.help = "port identifier",
2046 		.call = parse_port,
2047 		.comp = comp_port,
2048 	},
2049 	[COMMON_GROUP_ID] = {
2050 		.name = "{group_id}",
2051 		.type = "GROUP ID",
2052 		.help = "group identifier",
2053 		.call = parse_int,
2054 		.comp = comp_none,
2055 	},
2056 	[COMMON_PRIORITY_LEVEL] = {
2057 		.name = "{level}",
2058 		.type = "PRIORITY",
2059 		.help = "priority level",
2060 		.call = parse_int,
2061 		.comp = comp_none,
2062 	},
2063 	[COMMON_INDIRECT_ACTION_ID] = {
2064 		.name = "{indirect_action_id}",
2065 		.type = "INDIRECT_ACTION_ID",
2066 		.help = "indirect action id",
2067 		.call = parse_int,
2068 		.comp = comp_none,
2069 	},
2070 	[COMMON_POLICY_ID] = {
2071 		.name = "{policy_id}",
2072 		.type = "POLCIY_ID",
2073 		.help = "policy id",
2074 		.call = parse_int,
2075 		.comp = comp_none,
2076 	},
2077 	/* Top-level command. */
2078 	[FLOW] = {
2079 		.name = "flow",
2080 		.type = "{command} {port_id} [{arg} [...]]",
2081 		.help = "manage ingress/egress flow rules",
2082 		.next = NEXT(NEXT_ENTRY
2083 			     (INDIRECT_ACTION,
2084 			      VALIDATE,
2085 			      CREATE,
2086 			      DESTROY,
2087 			      FLUSH,
2088 			      DUMP,
2089 			      LIST,
2090 			      AGED,
2091 			      QUERY,
2092 			      ISOLATE,
2093 			      TUNNEL)),
2094 		.call = parse_init,
2095 	},
2096 	/* Top-level command. */
2097 	[INDIRECT_ACTION] = {
2098 		.name = "indirect_action",
2099 		.type = "{command} {port_id} [{arg} [...]]",
2100 		.help = "manage indirect actions",
2101 		.next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2102 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2103 		.call = parse_ia,
2104 	},
2105 	/* Sub-level commands. */
2106 	[INDIRECT_ACTION_CREATE] = {
2107 		.name = "create",
2108 		.help = "create indirect action",
2109 		.next = NEXT(next_ia_create_attr),
2110 		.call = parse_ia,
2111 	},
2112 	[INDIRECT_ACTION_UPDATE] = {
2113 		.name = "update",
2114 		.help = "update indirect action",
2115 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC),
2116 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2117 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
2118 		.call = parse_ia,
2119 	},
2120 	[INDIRECT_ACTION_DESTROY] = {
2121 		.name = "destroy",
2122 		.help = "destroy indirect action",
2123 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)),
2124 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2125 		.call = parse_ia_destroy,
2126 	},
2127 	[INDIRECT_ACTION_QUERY] = {
2128 		.name = "query",
2129 		.help = "query indirect action",
2130 		.next = NEXT(NEXT_ENTRY(END),
2131 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
2132 		.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
2133 		.call = parse_ia,
2134 	},
2135 	[VALIDATE] = {
2136 		.name = "validate",
2137 		.help = "check whether a flow rule can be created",
2138 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2139 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2140 		.call = parse_vc,
2141 	},
2142 	[CREATE] = {
2143 		.name = "create",
2144 		.help = "create a flow rule",
2145 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2146 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2147 		.call = parse_vc,
2148 	},
2149 	[DESTROY] = {
2150 		.name = "destroy",
2151 		.help = "destroy specific flow rules",
2152 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE),
2153 			     NEXT_ENTRY(COMMON_PORT_ID)),
2154 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2155 		.call = parse_destroy,
2156 	},
2157 	[FLUSH] = {
2158 		.name = "flush",
2159 		.help = "destroy all flow rules",
2160 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2161 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2162 		.call = parse_flush,
2163 	},
2164 	[DUMP] = {
2165 		.name = "dump",
2166 		.help = "dump single/all flow rules to file",
2167 		.next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
2168 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2169 		.call = parse_dump,
2170 	},
2171 	[QUERY] = {
2172 		.name = "query",
2173 		.help = "query an existing flow rule",
2174 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
2175 			     NEXT_ENTRY(COMMON_RULE_ID),
2176 			     NEXT_ENTRY(COMMON_PORT_ID)),
2177 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
2178 			     ARGS_ENTRY(struct buffer, args.query.rule),
2179 			     ARGS_ENTRY(struct buffer, port)),
2180 		.call = parse_query,
2181 	},
2182 	[LIST] = {
2183 		.name = "list",
2184 		.help = "list existing flow rules",
2185 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2186 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2187 		.call = parse_list,
2188 	},
2189 	[AGED] = {
2190 		.name = "aged",
2191 		.help = "list and destroy aged flows",
2192 		.next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)),
2193 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2194 		.call = parse_aged,
2195 	},
2196 	[ISOLATE] = {
2197 		.name = "isolate",
2198 		.help = "restrict ingress traffic to the defined flow rules",
2199 		.next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN),
2200 			     NEXT_ENTRY(COMMON_PORT_ID)),
2201 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
2202 			     ARGS_ENTRY(struct buffer, port)),
2203 		.call = parse_isolate,
2204 	},
2205 	[TUNNEL] = {
2206 		.name = "tunnel",
2207 		.help = "new tunnel API",
2208 		.next = NEXT(NEXT_ENTRY
2209 			     (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)),
2210 		.call = parse_tunnel,
2211 	},
2212 	/* Tunnel arguments. */
2213 	[TUNNEL_CREATE] = {
2214 		.name = "create",
2215 		.help = "create new tunnel object",
2216 		.next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE),
2217 			     NEXT_ENTRY(COMMON_PORT_ID)),
2218 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2219 		.call = parse_tunnel,
2220 	},
2221 	[TUNNEL_CREATE_TYPE] = {
2222 		.name = "type",
2223 		.help = "create new tunnel",
2224 		.next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)),
2225 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)),
2226 		.call = parse_tunnel,
2227 	},
2228 	[TUNNEL_DESTROY] = {
2229 		.name = "destroy",
2230 		.help = "destroy tunel",
2231 		.next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID),
2232 			     NEXT_ENTRY(COMMON_PORT_ID)),
2233 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2234 		.call = parse_tunnel,
2235 	},
2236 	[TUNNEL_DESTROY_ID] = {
2237 		.name = "id",
2238 		.help = "tunnel identifier to testroy",
2239 		.next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)),
2240 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2241 		.call = parse_tunnel,
2242 	},
2243 	[TUNNEL_LIST] = {
2244 		.name = "list",
2245 		.help = "list existing tunnels",
2246 		.next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)),
2247 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
2248 		.call = parse_tunnel,
2249 	},
2250 	/* Destroy arguments. */
2251 	[DESTROY_RULE] = {
2252 		.name = "rule",
2253 		.help = "specify a rule identifier",
2254 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2255 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
2256 		.call = parse_destroy,
2257 	},
2258 	/* Dump arguments. */
2259 	[DUMP_ALL] = {
2260 		.name = "all",
2261 		.help = "dump all",
2262 		.next = NEXT(next_dump_attr),
2263 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)),
2264 		.call = parse_dump,
2265 	},
2266 	[DUMP_ONE] = {
2267 		.name = "rule",
2268 		.help = "dump one rule",
2269 		.next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)),
2270 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
2271 				ARGS_ENTRY(struct buffer, args.dump.rule)),
2272 		.call = parse_dump,
2273 	},
2274 	/* Query arguments. */
2275 	[QUERY_ACTION] = {
2276 		.name = "{action}",
2277 		.type = "ACTION",
2278 		.help = "action to query, must be part of the rule",
2279 		.call = parse_action,
2280 		.comp = comp_action,
2281 	},
2282 	/* List arguments. */
2283 	[LIST_GROUP] = {
2284 		.name = "group",
2285 		.help = "specify a group",
2286 		.next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2287 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
2288 		.call = parse_list,
2289 	},
2290 	[AGED_DESTROY] = {
2291 		.name = "destroy",
2292 		.help = "specify aged flows need be destroyed",
2293 		.call = parse_aged,
2294 		.comp = comp_none,
2295 	},
2296 	/* Validate/create attributes. */
2297 	[VC_GROUP] = {
2298 		.name = "group",
2299 		.help = "specify a group",
2300 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)),
2301 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
2302 		.call = parse_vc,
2303 	},
2304 	[VC_PRIORITY] = {
2305 		.name = "priority",
2306 		.help = "specify a priority level",
2307 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)),
2308 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
2309 		.call = parse_vc,
2310 	},
2311 	[VC_INGRESS] = {
2312 		.name = "ingress",
2313 		.help = "affect rule to ingress",
2314 		.next = NEXT(next_vc_attr),
2315 		.call = parse_vc,
2316 	},
2317 	[VC_EGRESS] = {
2318 		.name = "egress",
2319 		.help = "affect rule to egress",
2320 		.next = NEXT(next_vc_attr),
2321 		.call = parse_vc,
2322 	},
2323 	[VC_TRANSFER] = {
2324 		.name = "transfer",
2325 		.help = "apply rule directly to endpoints found in pattern",
2326 		.next = NEXT(next_vc_attr),
2327 		.call = parse_vc,
2328 	},
2329 	[VC_TUNNEL_SET] = {
2330 		.name = "tunnel_set",
2331 		.help = "tunnel steer rule",
2332 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2333 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2334 		.call = parse_vc,
2335 	},
2336 	[VC_TUNNEL_MATCH] = {
2337 		.name = "tunnel_match",
2338 		.help = "tunnel match rule",
2339 		.next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
2340 		.args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
2341 		.call = parse_vc,
2342 	},
2343 	/* Validate/create pattern. */
2344 	[ITEM_PATTERN] = {
2345 		.name = "pattern",
2346 		.help = "submit a list of pattern items",
2347 		.next = NEXT(next_item),
2348 		.call = parse_vc,
2349 	},
2350 	[ITEM_PARAM_IS] = {
2351 		.name = "is",
2352 		.help = "match value perfectly (with full bit-mask)",
2353 		.call = parse_vc_spec,
2354 	},
2355 	[ITEM_PARAM_SPEC] = {
2356 		.name = "spec",
2357 		.help = "match value according to configured bit-mask",
2358 		.call = parse_vc_spec,
2359 	},
2360 	[ITEM_PARAM_LAST] = {
2361 		.name = "last",
2362 		.help = "specify upper bound to establish a range",
2363 		.call = parse_vc_spec,
2364 	},
2365 	[ITEM_PARAM_MASK] = {
2366 		.name = "mask",
2367 		.help = "specify bit-mask with relevant bits set to one",
2368 		.call = parse_vc_spec,
2369 	},
2370 	[ITEM_PARAM_PREFIX] = {
2371 		.name = "prefix",
2372 		.help = "generate bit-mask from a prefix length",
2373 		.call = parse_vc_spec,
2374 	},
2375 	[ITEM_NEXT] = {
2376 		.name = "/",
2377 		.help = "specify next pattern item",
2378 		.next = NEXT(next_item),
2379 	},
2380 	[ITEM_END] = {
2381 		.name = "end",
2382 		.help = "end list of pattern items",
2383 		.priv = PRIV_ITEM(END, 0),
2384 		.next = NEXT(NEXT_ENTRY(ACTIONS)),
2385 		.call = parse_vc,
2386 	},
2387 	[ITEM_VOID] = {
2388 		.name = "void",
2389 		.help = "no-op pattern item",
2390 		.priv = PRIV_ITEM(VOID, 0),
2391 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2392 		.call = parse_vc,
2393 	},
2394 	[ITEM_INVERT] = {
2395 		.name = "invert",
2396 		.help = "perform actions when pattern does not match",
2397 		.priv = PRIV_ITEM(INVERT, 0),
2398 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2399 		.call = parse_vc,
2400 	},
2401 	[ITEM_ANY] = {
2402 		.name = "any",
2403 		.help = "match any protocol for the current layer",
2404 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
2405 		.next = NEXT(item_any),
2406 		.call = parse_vc,
2407 	},
2408 	[ITEM_ANY_NUM] = {
2409 		.name = "num",
2410 		.help = "number of layers covered",
2411 		.next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2412 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
2413 	},
2414 	[ITEM_PF] = {
2415 		.name = "pf",
2416 		.help = "match traffic from/to the physical function",
2417 		.priv = PRIV_ITEM(PF, 0),
2418 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
2419 		.call = parse_vc,
2420 	},
2421 	[ITEM_VF] = {
2422 		.name = "vf",
2423 		.help = "match traffic from/to a virtual function ID",
2424 		.priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
2425 		.next = NEXT(item_vf),
2426 		.call = parse_vc,
2427 	},
2428 	[ITEM_VF_ID] = {
2429 		.name = "id",
2430 		.help = "VF ID",
2431 		.next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2432 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
2433 	},
2434 	[ITEM_PHY_PORT] = {
2435 		.name = "phy_port",
2436 		.help = "match traffic from/to a specific physical port",
2437 		.priv = PRIV_ITEM(PHY_PORT,
2438 				  sizeof(struct rte_flow_item_phy_port)),
2439 		.next = NEXT(item_phy_port),
2440 		.call = parse_vc,
2441 	},
2442 	[ITEM_PHY_PORT_INDEX] = {
2443 		.name = "index",
2444 		.help = "physical port index",
2445 		.next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED),
2446 			     item_param),
2447 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
2448 	},
2449 	[ITEM_PORT_ID] = {
2450 		.name = "port_id",
2451 		.help = "match traffic from/to a given DPDK port ID",
2452 		.priv = PRIV_ITEM(PORT_ID,
2453 				  sizeof(struct rte_flow_item_port_id)),
2454 		.next = NEXT(item_port_id),
2455 		.call = parse_vc,
2456 	},
2457 	[ITEM_PORT_ID_ID] = {
2458 		.name = "id",
2459 		.help = "DPDK port ID",
2460 		.next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED),
2461 			     item_param),
2462 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
2463 	},
2464 	[ITEM_MARK] = {
2465 		.name = "mark",
2466 		.help = "match traffic against value set in previously matched rule",
2467 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
2468 		.next = NEXT(item_mark),
2469 		.call = parse_vc,
2470 	},
2471 	[ITEM_MARK_ID] = {
2472 		.name = "id",
2473 		.help = "Integer value to match against",
2474 		.next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED),
2475 			     item_param),
2476 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
2477 	},
2478 	[ITEM_RAW] = {
2479 		.name = "raw",
2480 		.help = "match an arbitrary byte string",
2481 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
2482 		.next = NEXT(item_raw),
2483 		.call = parse_vc,
2484 	},
2485 	[ITEM_RAW_RELATIVE] = {
2486 		.name = "relative",
2487 		.help = "look for pattern after the previous item",
2488 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2489 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2490 					   relative, 1)),
2491 	},
2492 	[ITEM_RAW_SEARCH] = {
2493 		.name = "search",
2494 		.help = "search pattern from offset (see also limit)",
2495 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2496 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
2497 					   search, 1)),
2498 	},
2499 	[ITEM_RAW_OFFSET] = {
2500 		.name = "offset",
2501 		.help = "absolute or relative offset for pattern",
2502 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param),
2503 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2504 	},
2505 	[ITEM_RAW_LIMIT] = {
2506 		.name = "limit",
2507 		.help = "search area limit for start of pattern",
2508 		.next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2509 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2510 	},
2511 	[ITEM_RAW_PATTERN] = {
2512 		.name = "pattern",
2513 		.help = "byte string to look for",
2514 		.next = NEXT(item_raw,
2515 			     NEXT_ENTRY(COMMON_STRING),
2516 			     NEXT_ENTRY(ITEM_PARAM_IS,
2517 					ITEM_PARAM_SPEC,
2518 					ITEM_PARAM_MASK)),
2519 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2520 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
2521 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2522 					    ITEM_RAW_PATTERN_SIZE)),
2523 	},
2524 	[ITEM_ETH] = {
2525 		.name = "eth",
2526 		.help = "match Ethernet header",
2527 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2528 		.next = NEXT(item_eth),
2529 		.call = parse_vc,
2530 	},
2531 	[ITEM_ETH_DST] = {
2532 		.name = "dst",
2533 		.help = "destination MAC",
2534 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2535 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2536 	},
2537 	[ITEM_ETH_SRC] = {
2538 		.name = "src",
2539 		.help = "source MAC",
2540 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
2541 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2542 	},
2543 	[ITEM_ETH_TYPE] = {
2544 		.name = "type",
2545 		.help = "EtherType",
2546 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2547 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2548 	},
2549 	[ITEM_ETH_HAS_VLAN] = {
2550 		.name = "has_vlan",
2551 		.help = "packet header contains VLAN",
2552 		.next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2553 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth,
2554 					   has_vlan, 1)),
2555 	},
2556 	[ITEM_VLAN] = {
2557 		.name = "vlan",
2558 		.help = "match 802.1Q/ad VLAN tag",
2559 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2560 		.next = NEXT(item_vlan),
2561 		.call = parse_vc,
2562 	},
2563 	[ITEM_VLAN_TCI] = {
2564 		.name = "tci",
2565 		.help = "tag control information",
2566 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2567 			     item_param),
2568 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2569 	},
2570 	[ITEM_VLAN_PCP] = {
2571 		.name = "pcp",
2572 		.help = "priority code point",
2573 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2574 			     item_param),
2575 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2576 						  tci, "\xe0\x00")),
2577 	},
2578 	[ITEM_VLAN_DEI] = {
2579 		.name = "dei",
2580 		.help = "drop eligible indicator",
2581 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2582 			     item_param),
2583 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2584 						  tci, "\x10\x00")),
2585 	},
2586 	[ITEM_VLAN_VID] = {
2587 		.name = "vid",
2588 		.help = "VLAN identifier",
2589 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2590 			     item_param),
2591 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2592 						  tci, "\x0f\xff")),
2593 	},
2594 	[ITEM_VLAN_INNER_TYPE] = {
2595 		.name = "inner_type",
2596 		.help = "inner EtherType",
2597 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2598 			     item_param),
2599 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2600 					     inner_type)),
2601 	},
2602 	[ITEM_VLAN_HAS_MORE_VLAN] = {
2603 		.name = "has_more_vlan",
2604 		.help = "packet header contains another VLAN",
2605 		.next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED),
2606 			     item_param),
2607 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan,
2608 					   has_more_vlan, 1)),
2609 	},
2610 	[ITEM_IPV4] = {
2611 		.name = "ipv4",
2612 		.help = "match IPv4 header",
2613 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2614 		.next = NEXT(item_ipv4),
2615 		.call = parse_vc,
2616 	},
2617 	[ITEM_IPV4_VER_IHL] = {
2618 		.name = "version_ihl",
2619 		.help = "match header length",
2620 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2621 			     item_param),
2622 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4,
2623 				     hdr.version_ihl)),
2624 	},
2625 	[ITEM_IPV4_TOS] = {
2626 		.name = "tos",
2627 		.help = "type of service",
2628 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2629 			     item_param),
2630 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2631 					     hdr.type_of_service)),
2632 	},
2633 	[ITEM_IPV4_ID] = {
2634 		.name = "packet_id",
2635 		.help = "fragment packet id",
2636 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2637 			     item_param),
2638 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2639 					     hdr.packet_id)),
2640 	},
2641 	[ITEM_IPV4_FRAGMENT_OFFSET] = {
2642 		.name = "fragment_offset",
2643 		.help = "fragmentation flags and fragment offset",
2644 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2645 			     item_param),
2646 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2647 					     hdr.fragment_offset)),
2648 	},
2649 	[ITEM_IPV4_TTL] = {
2650 		.name = "ttl",
2651 		.help = "time to live",
2652 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2653 			     item_param),
2654 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2655 					     hdr.time_to_live)),
2656 	},
2657 	[ITEM_IPV4_PROTO] = {
2658 		.name = "proto",
2659 		.help = "next protocol ID",
2660 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED),
2661 			     item_param),
2662 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2663 					     hdr.next_proto_id)),
2664 	},
2665 	[ITEM_IPV4_SRC] = {
2666 		.name = "src",
2667 		.help = "source address",
2668 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2669 			     item_param),
2670 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2671 					     hdr.src_addr)),
2672 	},
2673 	[ITEM_IPV4_DST] = {
2674 		.name = "dst",
2675 		.help = "destination address",
2676 		.next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
2677 			     item_param),
2678 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2679 					     hdr.dst_addr)),
2680 	},
2681 	[ITEM_IPV6] = {
2682 		.name = "ipv6",
2683 		.help = "match IPv6 header",
2684 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2685 		.next = NEXT(item_ipv6),
2686 		.call = parse_vc,
2687 	},
2688 	[ITEM_IPV6_TC] = {
2689 		.name = "tc",
2690 		.help = "traffic class",
2691 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2692 			     item_param),
2693 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2694 						  hdr.vtc_flow,
2695 						  "\x0f\xf0\x00\x00")),
2696 	},
2697 	[ITEM_IPV6_FLOW] = {
2698 		.name = "flow",
2699 		.help = "flow label",
2700 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2701 			     item_param),
2702 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2703 						  hdr.vtc_flow,
2704 						  "\x00\x0f\xff\xff")),
2705 	},
2706 	[ITEM_IPV6_PROTO] = {
2707 		.name = "proto",
2708 		.help = "protocol (next header)",
2709 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2710 			     item_param),
2711 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2712 					     hdr.proto)),
2713 	},
2714 	[ITEM_IPV6_HOP] = {
2715 		.name = "hop",
2716 		.help = "hop limit",
2717 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2718 			     item_param),
2719 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2720 					     hdr.hop_limits)),
2721 	},
2722 	[ITEM_IPV6_SRC] = {
2723 		.name = "src",
2724 		.help = "source address",
2725 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2726 			     item_param),
2727 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2728 					     hdr.src_addr)),
2729 	},
2730 	[ITEM_IPV6_DST] = {
2731 		.name = "dst",
2732 		.help = "destination address",
2733 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR),
2734 			     item_param),
2735 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2736 					     hdr.dst_addr)),
2737 	},
2738 	[ITEM_IPV6_HAS_FRAG_EXT] = {
2739 		.name = "has_frag_ext",
2740 		.help = "fragment packet attribute",
2741 		.next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED),
2742 			     item_param),
2743 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6,
2744 					   has_frag_ext, 1)),
2745 	},
2746 	[ITEM_ICMP] = {
2747 		.name = "icmp",
2748 		.help = "match ICMP header",
2749 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2750 		.next = NEXT(item_icmp),
2751 		.call = parse_vc,
2752 	},
2753 	[ITEM_ICMP_TYPE] = {
2754 		.name = "type",
2755 		.help = "ICMP packet type",
2756 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2757 			     item_param),
2758 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2759 					     hdr.icmp_type)),
2760 	},
2761 	[ITEM_ICMP_CODE] = {
2762 		.name = "code",
2763 		.help = "ICMP packet code",
2764 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2765 			     item_param),
2766 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2767 					     hdr.icmp_code)),
2768 	},
2769 	[ITEM_ICMP_IDENT] = {
2770 		.name = "ident",
2771 		.help = "ICMP packet identifier",
2772 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2773 			     item_param),
2774 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2775 					     hdr.icmp_ident)),
2776 	},
2777 	[ITEM_ICMP_SEQ] = {
2778 		.name = "seq",
2779 		.help = "ICMP packet sequence number",
2780 		.next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED),
2781 			     item_param),
2782 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2783 					     hdr.icmp_seq_nb)),
2784 	},
2785 	[ITEM_UDP] = {
2786 		.name = "udp",
2787 		.help = "match UDP header",
2788 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
2789 		.next = NEXT(item_udp),
2790 		.call = parse_vc,
2791 	},
2792 	[ITEM_UDP_SRC] = {
2793 		.name = "src",
2794 		.help = "UDP source port",
2795 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED),
2796 			     item_param),
2797 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2798 					     hdr.src_port)),
2799 	},
2800 	[ITEM_UDP_DST] = {
2801 		.name = "dst",
2802 		.help = "UDP destination port",
2803 		.next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2804 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2805 					     hdr.dst_port)),
2806 	},
2807 	[ITEM_TCP] = {
2808 		.name = "tcp",
2809 		.help = "match TCP header",
2810 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
2811 		.next = NEXT(item_tcp),
2812 		.call = parse_vc,
2813 	},
2814 	[ITEM_TCP_SRC] = {
2815 		.name = "src",
2816 		.help = "TCP source port",
2817 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2818 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2819 					     hdr.src_port)),
2820 	},
2821 	[ITEM_TCP_DST] = {
2822 		.name = "dst",
2823 		.help = "TCP destination port",
2824 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2825 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2826 					     hdr.dst_port)),
2827 	},
2828 	[ITEM_TCP_FLAGS] = {
2829 		.name = "flags",
2830 		.help = "TCP flags",
2831 		.next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
2832 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2833 					     hdr.tcp_flags)),
2834 	},
2835 	[ITEM_SCTP] = {
2836 		.name = "sctp",
2837 		.help = "match SCTP header",
2838 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
2839 		.next = NEXT(item_sctp),
2840 		.call = parse_vc,
2841 	},
2842 	[ITEM_SCTP_SRC] = {
2843 		.name = "src",
2844 		.help = "SCTP source port",
2845 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2846 			     item_param),
2847 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2848 					     hdr.src_port)),
2849 	},
2850 	[ITEM_SCTP_DST] = {
2851 		.name = "dst",
2852 		.help = "SCTP destination port",
2853 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2854 			     item_param),
2855 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2856 					     hdr.dst_port)),
2857 	},
2858 	[ITEM_SCTP_TAG] = {
2859 		.name = "tag",
2860 		.help = "validation tag",
2861 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2862 			     item_param),
2863 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2864 					     hdr.tag)),
2865 	},
2866 	[ITEM_SCTP_CKSUM] = {
2867 		.name = "cksum",
2868 		.help = "checksum",
2869 		.next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED),
2870 			     item_param),
2871 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2872 					     hdr.cksum)),
2873 	},
2874 	[ITEM_VXLAN] = {
2875 		.name = "vxlan",
2876 		.help = "match VXLAN header",
2877 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
2878 		.next = NEXT(item_vxlan),
2879 		.call = parse_vc,
2880 	},
2881 	[ITEM_VXLAN_VNI] = {
2882 		.name = "vni",
2883 		.help = "VXLAN identifier",
2884 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
2885 			     item_param),
2886 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
2887 	},
2888 	[ITEM_VXLAN_LAST_RSVD] = {
2889 		.name = "last_rsvd",
2890 		.help = "VXLAN last reserved bits",
2891 		.next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED),
2892 			     item_param),
2893 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan,
2894 					     rsvd1)),
2895 	},
2896 	[ITEM_E_TAG] = {
2897 		.name = "e_tag",
2898 		.help = "match E-Tag header",
2899 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
2900 		.next = NEXT(item_e_tag),
2901 		.call = parse_vc,
2902 	},
2903 	[ITEM_E_TAG_GRP_ECID_B] = {
2904 		.name = "grp_ecid_b",
2905 		.help = "GRP and E-CID base",
2906 		.next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED),
2907 			     item_param),
2908 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
2909 						  rsvd_grp_ecid_b,
2910 						  "\x3f\xff")),
2911 	},
2912 	[ITEM_NVGRE] = {
2913 		.name = "nvgre",
2914 		.help = "match NVGRE header",
2915 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
2916 		.next = NEXT(item_nvgre),
2917 		.call = parse_vc,
2918 	},
2919 	[ITEM_NVGRE_TNI] = {
2920 		.name = "tni",
2921 		.help = "virtual subnet ID",
2922 		.next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED),
2923 			     item_param),
2924 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
2925 	},
2926 	[ITEM_MPLS] = {
2927 		.name = "mpls",
2928 		.help = "match MPLS header",
2929 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
2930 		.next = NEXT(item_mpls),
2931 		.call = parse_vc,
2932 	},
2933 	[ITEM_MPLS_LABEL] = {
2934 		.name = "label",
2935 		.help = "MPLS label",
2936 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2937 			     item_param),
2938 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2939 						  label_tc_s,
2940 						  "\xff\xff\xf0")),
2941 	},
2942 	[ITEM_MPLS_TC] = {
2943 		.name = "tc",
2944 		.help = "MPLS Traffic Class",
2945 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2946 			     item_param),
2947 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2948 						  label_tc_s,
2949 						  "\x00\x00\x0e")),
2950 	},
2951 	[ITEM_MPLS_S] = {
2952 		.name = "s",
2953 		.help = "MPLS Bottom-of-Stack",
2954 		.next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED),
2955 			     item_param),
2956 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2957 						  label_tc_s,
2958 						  "\x00\x00\x01")),
2959 	},
2960 	[ITEM_GRE] = {
2961 		.name = "gre",
2962 		.help = "match GRE header",
2963 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
2964 		.next = NEXT(item_gre),
2965 		.call = parse_vc,
2966 	},
2967 	[ITEM_GRE_PROTO] = {
2968 		.name = "protocol",
2969 		.help = "GRE protocol type",
2970 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2971 			     item_param),
2972 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2973 					     protocol)),
2974 	},
2975 	[ITEM_GRE_C_RSVD0_VER] = {
2976 		.name = "c_rsvd0_ver",
2977 		.help =
2978 			"checksum (1b), undefined (1b), key bit (1b),"
2979 			" sequence number (1b), reserved 0 (9b),"
2980 			" version (3b)",
2981 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED),
2982 			     item_param),
2983 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2984 					     c_rsvd0_ver)),
2985 	},
2986 	[ITEM_GRE_C_BIT] = {
2987 		.name = "c_bit",
2988 		.help = "checksum bit (C)",
2989 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN),
2990 			     item_param),
2991 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2992 						  c_rsvd0_ver,
2993 						  "\x80\x00\x00\x00")),
2994 	},
2995 	[ITEM_GRE_S_BIT] = {
2996 		.name = "s_bit",
2997 		.help = "sequence number bit (S)",
2998 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
2999 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3000 						  c_rsvd0_ver,
3001 						  "\x10\x00\x00\x00")),
3002 	},
3003 	[ITEM_GRE_K_BIT] = {
3004 		.name = "k_bit",
3005 		.help = "key bit (K)",
3006 		.next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param),
3007 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
3008 						  c_rsvd0_ver,
3009 						  "\x20\x00\x00\x00")),
3010 	},
3011 	[ITEM_FUZZY] = {
3012 		.name = "fuzzy",
3013 		.help = "fuzzy pattern match, expect faster than default",
3014 		.priv = PRIV_ITEM(FUZZY,
3015 				sizeof(struct rte_flow_item_fuzzy)),
3016 		.next = NEXT(item_fuzzy),
3017 		.call = parse_vc,
3018 	},
3019 	[ITEM_FUZZY_THRESH] = {
3020 		.name = "thresh",
3021 		.help = "match accuracy threshold",
3022 		.next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED),
3023 			     item_param),
3024 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
3025 					thresh)),
3026 	},
3027 	[ITEM_GTP] = {
3028 		.name = "gtp",
3029 		.help = "match GTP header",
3030 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
3031 		.next = NEXT(item_gtp),
3032 		.call = parse_vc,
3033 	},
3034 	[ITEM_GTP_FLAGS] = {
3035 		.name = "v_pt_rsv_flags",
3036 		.help = "GTP flags",
3037 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3038 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
3039 					v_pt_rsv_flags)),
3040 	},
3041 	[ITEM_GTP_MSG_TYPE] = {
3042 		.name = "msg_type",
3043 		.help = "GTP message type",
3044 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3045 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
3046 	},
3047 	[ITEM_GTP_TEID] = {
3048 		.name = "teid",
3049 		.help = "tunnel endpoint identifier",
3050 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3051 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
3052 	},
3053 	[ITEM_GTPC] = {
3054 		.name = "gtpc",
3055 		.help = "match GTP header",
3056 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
3057 		.next = NEXT(item_gtp),
3058 		.call = parse_vc,
3059 	},
3060 	[ITEM_GTPU] = {
3061 		.name = "gtpu",
3062 		.help = "match GTP header",
3063 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
3064 		.next = NEXT(item_gtp),
3065 		.call = parse_vc,
3066 	},
3067 	[ITEM_GENEVE] = {
3068 		.name = "geneve",
3069 		.help = "match GENEVE header",
3070 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
3071 		.next = NEXT(item_geneve),
3072 		.call = parse_vc,
3073 	},
3074 	[ITEM_GENEVE_VNI] = {
3075 		.name = "vni",
3076 		.help = "virtual network identifier",
3077 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3078 			     item_param),
3079 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
3080 	},
3081 	[ITEM_GENEVE_PROTO] = {
3082 		.name = "protocol",
3083 		.help = "GENEVE protocol type",
3084 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3085 			     item_param),
3086 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
3087 					     protocol)),
3088 	},
3089 	[ITEM_GENEVE_OPTLEN] = {
3090 		.name = "optlen",
3091 		.help = "GENEVE options length in dwords",
3092 		.next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED),
3093 			     item_param),
3094 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve,
3095 						  ver_opt_len_o_c_rsvd0,
3096 						  "\x3f\x00")),
3097 	},
3098 	[ITEM_VXLAN_GPE] = {
3099 		.name = "vxlan-gpe",
3100 		.help = "match VXLAN-GPE header",
3101 		.priv = PRIV_ITEM(VXLAN_GPE,
3102 				  sizeof(struct rte_flow_item_vxlan_gpe)),
3103 		.next = NEXT(item_vxlan_gpe),
3104 		.call = parse_vc,
3105 	},
3106 	[ITEM_VXLAN_GPE_VNI] = {
3107 		.name = "vni",
3108 		.help = "VXLAN-GPE identifier",
3109 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED),
3110 			     item_param),
3111 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
3112 					     vni)),
3113 	},
3114 	[ITEM_ARP_ETH_IPV4] = {
3115 		.name = "arp_eth_ipv4",
3116 		.help = "match ARP header for Ethernet/IPv4",
3117 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
3118 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
3119 		.next = NEXT(item_arp_eth_ipv4),
3120 		.call = parse_vc,
3121 	},
3122 	[ITEM_ARP_ETH_IPV4_SHA] = {
3123 		.name = "sha",
3124 		.help = "sender hardware address",
3125 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3126 			     item_param),
3127 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3128 					     sha)),
3129 	},
3130 	[ITEM_ARP_ETH_IPV4_SPA] = {
3131 		.name = "spa",
3132 		.help = "sender IPv4 address",
3133 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3134 			     item_param),
3135 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3136 					     spa)),
3137 	},
3138 	[ITEM_ARP_ETH_IPV4_THA] = {
3139 		.name = "tha",
3140 		.help = "target hardware address",
3141 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR),
3142 			     item_param),
3143 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3144 					     tha)),
3145 	},
3146 	[ITEM_ARP_ETH_IPV4_TPA] = {
3147 		.name = "tpa",
3148 		.help = "target IPv4 address",
3149 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR),
3150 			     item_param),
3151 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
3152 					     tpa)),
3153 	},
3154 	[ITEM_IPV6_EXT] = {
3155 		.name = "ipv6_ext",
3156 		.help = "match presence of any IPv6 extension header",
3157 		.priv = PRIV_ITEM(IPV6_EXT,
3158 				  sizeof(struct rte_flow_item_ipv6_ext)),
3159 		.next = NEXT(item_ipv6_ext),
3160 		.call = parse_vc,
3161 	},
3162 	[ITEM_IPV6_EXT_NEXT_HDR] = {
3163 		.name = "next_hdr",
3164 		.help = "next header",
3165 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3166 			     item_param),
3167 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
3168 					     next_hdr)),
3169 	},
3170 	[ITEM_IPV6_FRAG_EXT] = {
3171 		.name = "ipv6_frag_ext",
3172 		.help = "match presence of IPv6 fragment extension header",
3173 		.priv = PRIV_ITEM(IPV6_FRAG_EXT,
3174 				sizeof(struct rte_flow_item_ipv6_frag_ext)),
3175 		.next = NEXT(item_ipv6_frag_ext),
3176 		.call = parse_vc,
3177 	},
3178 	[ITEM_IPV6_FRAG_EXT_NEXT_HDR] = {
3179 		.name = "next_hdr",
3180 		.help = "next header",
3181 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3182 			     item_param),
3183 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext,
3184 					hdr.next_header)),
3185 	},
3186 	[ITEM_IPV6_FRAG_EXT_FRAG_DATA] = {
3187 		.name = "frag_data",
3188 		.help = "fragment flags and offset",
3189 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3190 			     item_param),
3191 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3192 					     hdr.frag_data)),
3193 	},
3194 	[ITEM_IPV6_FRAG_EXT_ID] = {
3195 		.name = "packet_id",
3196 		.help = "fragment packet id",
3197 		.next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED),
3198 			     item_param),
3199 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext,
3200 					     hdr.id)),
3201 	},
3202 	[ITEM_ICMP6] = {
3203 		.name = "icmp6",
3204 		.help = "match any ICMPv6 header",
3205 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
3206 		.next = NEXT(item_icmp6),
3207 		.call = parse_vc,
3208 	},
3209 	[ITEM_ICMP6_TYPE] = {
3210 		.name = "type",
3211 		.help = "ICMPv6 type",
3212 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3213 			     item_param),
3214 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3215 					     type)),
3216 	},
3217 	[ITEM_ICMP6_CODE] = {
3218 		.name = "code",
3219 		.help = "ICMPv6 code",
3220 		.next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED),
3221 			     item_param),
3222 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
3223 					     code)),
3224 	},
3225 	[ITEM_ICMP6_ND_NS] = {
3226 		.name = "icmp6_nd_ns",
3227 		.help = "match ICMPv6 neighbor discovery solicitation",
3228 		.priv = PRIV_ITEM(ICMP6_ND_NS,
3229 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
3230 		.next = NEXT(item_icmp6_nd_ns),
3231 		.call = parse_vc,
3232 	},
3233 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
3234 		.name = "target_addr",
3235 		.help = "target address",
3236 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR),
3237 			     item_param),
3238 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
3239 					     target_addr)),
3240 	},
3241 	[ITEM_ICMP6_ND_NA] = {
3242 		.name = "icmp6_nd_na",
3243 		.help = "match ICMPv6 neighbor discovery advertisement",
3244 		.priv = PRIV_ITEM(ICMP6_ND_NA,
3245 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
3246 		.next = NEXT(item_icmp6_nd_na),
3247 		.call = parse_vc,
3248 	},
3249 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
3250 		.name = "target_addr",
3251 		.help = "target address",
3252 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR),
3253 			     item_param),
3254 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
3255 					     target_addr)),
3256 	},
3257 	[ITEM_ICMP6_ND_OPT] = {
3258 		.name = "icmp6_nd_opt",
3259 		.help = "match presence of any ICMPv6 neighbor discovery"
3260 			" option",
3261 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
3262 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
3263 		.next = NEXT(item_icmp6_nd_opt),
3264 		.call = parse_vc,
3265 	},
3266 	[ITEM_ICMP6_ND_OPT_TYPE] = {
3267 		.name = "type",
3268 		.help = "ND option type",
3269 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3270 			     item_param),
3271 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
3272 					     type)),
3273 	},
3274 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
3275 		.name = "icmp6_nd_opt_sla_eth",
3276 		.help = "match ICMPv6 neighbor discovery source Ethernet"
3277 			" link-layer address option",
3278 		.priv = PRIV_ITEM
3279 			(ICMP6_ND_OPT_SLA_ETH,
3280 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
3281 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
3282 		.call = parse_vc,
3283 	},
3284 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
3285 		.name = "sla",
3286 		.help = "source Ethernet LLA",
3287 		.next = NEXT(item_icmp6_nd_opt_sla_eth,
3288 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3289 		.args = ARGS(ARGS_ENTRY_HTON
3290 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
3291 	},
3292 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
3293 		.name = "icmp6_nd_opt_tla_eth",
3294 		.help = "match ICMPv6 neighbor discovery target Ethernet"
3295 			" link-layer address option",
3296 		.priv = PRIV_ITEM
3297 			(ICMP6_ND_OPT_TLA_ETH,
3298 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
3299 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
3300 		.call = parse_vc,
3301 	},
3302 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
3303 		.name = "tla",
3304 		.help = "target Ethernet LLA",
3305 		.next = NEXT(item_icmp6_nd_opt_tla_eth,
3306 			     NEXT_ENTRY(COMMON_MAC_ADDR), item_param),
3307 		.args = ARGS(ARGS_ENTRY_HTON
3308 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
3309 	},
3310 	[ITEM_META] = {
3311 		.name = "meta",
3312 		.help = "match metadata header",
3313 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
3314 		.next = NEXT(item_meta),
3315 		.call = parse_vc,
3316 	},
3317 	[ITEM_META_DATA] = {
3318 		.name = "data",
3319 		.help = "metadata value",
3320 		.next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED),
3321 			     item_param),
3322 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
3323 					     data, "\xff\xff\xff\xff")),
3324 	},
3325 	[ITEM_GRE_KEY] = {
3326 		.name = "gre_key",
3327 		.help = "match GRE key",
3328 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
3329 		.next = NEXT(item_gre_key),
3330 		.call = parse_vc,
3331 	},
3332 	[ITEM_GRE_KEY_VALUE] = {
3333 		.name = "value",
3334 		.help = "key value",
3335 		.next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED),
3336 			     item_param),
3337 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3338 	},
3339 	[ITEM_GTP_PSC] = {
3340 		.name = "gtp_psc",
3341 		.help = "match GTP extension header with type 0x85",
3342 		.priv = PRIV_ITEM(GTP_PSC,
3343 				sizeof(struct rte_flow_item_gtp_psc)),
3344 		.next = NEXT(item_gtp_psc),
3345 		.call = parse_vc,
3346 	},
3347 	[ITEM_GTP_PSC_QFI] = {
3348 		.name = "qfi",
3349 		.help = "QoS flow identifier",
3350 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3351 			     item_param),
3352 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3353 					hdr.qfi, 6)),
3354 	},
3355 	[ITEM_GTP_PSC_PDU_T] = {
3356 		.name = "pdu_t",
3357 		.help = "PDU type",
3358 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED),
3359 			     item_param),
3360 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc,
3361 					hdr.type, 4)),
3362 	},
3363 	[ITEM_PPPOES] = {
3364 		.name = "pppoes",
3365 		.help = "match PPPoE session header",
3366 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
3367 		.next = NEXT(item_pppoes),
3368 		.call = parse_vc,
3369 	},
3370 	[ITEM_PPPOED] = {
3371 		.name = "pppoed",
3372 		.help = "match PPPoE discovery header",
3373 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
3374 		.next = NEXT(item_pppoed),
3375 		.call = parse_vc,
3376 	},
3377 	[ITEM_PPPOE_SEID] = {
3378 		.name = "seid",
3379 		.help = "session identifier",
3380 		.next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED),
3381 			     item_param),
3382 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
3383 					session_id)),
3384 	},
3385 	[ITEM_PPPOE_PROTO_ID] = {
3386 		.name = "pppoe_proto_id",
3387 		.help = "match PPPoE session protocol identifier",
3388 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
3389 				sizeof(struct rte_flow_item_pppoe_proto_id)),
3390 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED),
3391 			     item_param),
3392 		.args = ARGS(ARGS_ENTRY_HTON
3393 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
3394 		.call = parse_vc,
3395 	},
3396 	[ITEM_HIGIG2] = {
3397 		.name = "higig2",
3398 		.help = "matches higig2 header",
3399 		.priv = PRIV_ITEM(HIGIG2,
3400 				sizeof(struct rte_flow_item_higig2_hdr)),
3401 		.next = NEXT(item_higig2),
3402 		.call = parse_vc,
3403 	},
3404 	[ITEM_HIGIG2_CLASSIFICATION] = {
3405 		.name = "classification",
3406 		.help = "matches classification of higig2 header",
3407 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3408 			     item_param),
3409 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3410 					hdr.ppt1.classification)),
3411 	},
3412 	[ITEM_HIGIG2_VID] = {
3413 		.name = "vid",
3414 		.help = "matches vid of higig2 header",
3415 		.next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED),
3416 			     item_param),
3417 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
3418 					hdr.ppt1.vid)),
3419 	},
3420 	[ITEM_TAG] = {
3421 		.name = "tag",
3422 		.help = "match tag value",
3423 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
3424 		.next = NEXT(item_tag),
3425 		.call = parse_vc,
3426 	},
3427 	[ITEM_TAG_DATA] = {
3428 		.name = "data",
3429 		.help = "tag value to match",
3430 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3431 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
3432 	},
3433 	[ITEM_TAG_INDEX] = {
3434 		.name = "index",
3435 		.help = "index of tag array to match",
3436 		.next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED),
3437 			     NEXT_ENTRY(ITEM_PARAM_IS)),
3438 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
3439 	},
3440 	[ITEM_L2TPV3OIP] = {
3441 		.name = "l2tpv3oip",
3442 		.help = "match L2TPv3 over IP header",
3443 		.priv = PRIV_ITEM(L2TPV3OIP,
3444 				  sizeof(struct rte_flow_item_l2tpv3oip)),
3445 		.next = NEXT(item_l2tpv3oip),
3446 		.call = parse_vc,
3447 	},
3448 	[ITEM_L2TPV3OIP_SESSION_ID] = {
3449 		.name = "session_id",
3450 		.help = "session identifier",
3451 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED),
3452 			     item_param),
3453 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
3454 					     session_id)),
3455 	},
3456 	[ITEM_ESP] = {
3457 		.name = "esp",
3458 		.help = "match ESP header",
3459 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
3460 		.next = NEXT(item_esp),
3461 		.call = parse_vc,
3462 	},
3463 	[ITEM_ESP_SPI] = {
3464 		.name = "spi",
3465 		.help = "security policy index",
3466 		.next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3467 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
3468 				hdr.spi)),
3469 	},
3470 	[ITEM_AH] = {
3471 		.name = "ah",
3472 		.help = "match AH header",
3473 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
3474 		.next = NEXT(item_ah),
3475 		.call = parse_vc,
3476 	},
3477 	[ITEM_AH_SPI] = {
3478 		.name = "spi",
3479 		.help = "security parameters index",
3480 		.next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3481 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
3482 	},
3483 	[ITEM_PFCP] = {
3484 		.name = "pfcp",
3485 		.help = "match pfcp header",
3486 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
3487 		.next = NEXT(item_pfcp),
3488 		.call = parse_vc,
3489 	},
3490 	[ITEM_PFCP_S_FIELD] = {
3491 		.name = "s_field",
3492 		.help = "S field",
3493 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3494 			     item_param),
3495 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
3496 				s_field)),
3497 	},
3498 	[ITEM_PFCP_SEID] = {
3499 		.name = "seid",
3500 		.help = "session endpoint identifier",
3501 		.next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED),
3502 			     item_param),
3503 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
3504 	},
3505 	[ITEM_ECPRI] = {
3506 		.name = "ecpri",
3507 		.help = "match eCPRI header",
3508 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
3509 		.next = NEXT(item_ecpri),
3510 		.call = parse_vc,
3511 	},
3512 	[ITEM_ECPRI_COMMON] = {
3513 		.name = "common",
3514 		.help = "eCPRI common header",
3515 		.next = NEXT(item_ecpri_common),
3516 	},
3517 	[ITEM_ECPRI_COMMON_TYPE] = {
3518 		.name = "type",
3519 		.help = "type of common header",
3520 		.next = NEXT(item_ecpri_common_type),
3521 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
3522 	},
3523 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
3524 		.name = "iq_data",
3525 		.help = "Type #0: IQ Data",
3526 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3527 					ITEM_NEXT)),
3528 		.call = parse_vc_item_ecpri_type,
3529 	},
3530 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
3531 		.name = "pc_id",
3532 		.help = "Physical Channel ID",
3533 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
3534 				ITEM_ECPRI_COMMON, ITEM_NEXT),
3535 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3536 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3537 				hdr.type0.pc_id)),
3538 	},
3539 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
3540 		.name = "rtc_ctrl",
3541 		.help = "Type #2: Real-Time Control Data",
3542 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3543 					ITEM_NEXT)),
3544 		.call = parse_vc_item_ecpri_type,
3545 	},
3546 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
3547 		.name = "rtc_id",
3548 		.help = "Real-Time Control Data ID",
3549 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
3550 				ITEM_ECPRI_COMMON, ITEM_NEXT),
3551 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3552 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3553 				hdr.type2.rtc_id)),
3554 	},
3555 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
3556 		.name = "delay_measure",
3557 		.help = "Type #5: One-Way Delay Measurement",
3558 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3559 					ITEM_NEXT)),
3560 		.call = parse_vc_item_ecpri_type,
3561 	},
3562 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
3563 		.name = "msr_id",
3564 		.help = "Measurement ID",
3565 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
3566 				ITEM_ECPRI_COMMON, ITEM_NEXT),
3567 				NEXT_ENTRY(COMMON_UNSIGNED), item_param),
3568 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
3569 				hdr.type5.msr_id)),
3570 	},
3571 	[ITEM_GENEVE_OPT] = {
3572 		.name = "geneve-opt",
3573 		.help = "GENEVE header option",
3574 		.priv = PRIV_ITEM(GENEVE_OPT,
3575 				  sizeof(struct rte_flow_item_geneve_opt) +
3576 				  ITEM_GENEVE_OPT_DATA_SIZE),
3577 		.next = NEXT(item_geneve_opt),
3578 		.call = parse_vc,
3579 	},
3580 	[ITEM_GENEVE_OPT_CLASS]	= {
3581 		.name = "class",
3582 		.help = "GENEVE option class",
3583 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3584 			     item_param),
3585 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
3586 					     option_class)),
3587 	},
3588 	[ITEM_GENEVE_OPT_TYPE] = {
3589 		.name = "type",
3590 		.help = "GENEVE option type",
3591 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3592 			     item_param),
3593 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
3594 					option_type)),
3595 	},
3596 	[ITEM_GENEVE_OPT_LENGTH] = {
3597 		.name = "length",
3598 		.help = "GENEVE option data length (in 32b words)",
3599 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
3600 			     item_param),
3601 		.args = ARGS(ARGS_ENTRY_BOUNDED(
3602 				struct rte_flow_item_geneve_opt, option_len,
3603 				0, 31)),
3604 	},
3605 	[ITEM_GENEVE_OPT_DATA] = {
3606 		.name = "data",
3607 		.help = "GENEVE option data pattern",
3608 		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX),
3609 			     item_param),
3610 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
3611 			     ARGS_ENTRY_ARB(0, 0),
3612 			     ARGS_ENTRY_ARB
3613 				(sizeof(struct rte_flow_item_geneve_opt),
3614 				ITEM_GENEVE_OPT_DATA_SIZE)),
3615 	},
3616 	[ITEM_INTEGRITY] = {
3617 		.name = "integrity",
3618 		.help = "match packet integrity",
3619 		.priv = PRIV_ITEM(INTEGRITY,
3620 				  sizeof(struct rte_flow_item_integrity)),
3621 		.next = NEXT(item_integrity),
3622 		.call = parse_vc,
3623 	},
3624 	[ITEM_INTEGRITY_LEVEL] = {
3625 		.name = "level",
3626 		.help = "integrity level",
3627 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3628 			     item_param),
3629 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)),
3630 	},
3631 	[ITEM_INTEGRITY_VALUE] = {
3632 		.name = "value",
3633 		.help = "integrity value",
3634 		.next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED),
3635 			     item_param),
3636 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
3637 	},
3638 	[ITEM_CONNTRACK] = {
3639 		.name = "conntrack",
3640 		.help = "conntrack state",
3641 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED),
3642 			     item_param),
3643 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
3644 	},
3645 	[ITEM_PORT_REPRESENTOR] = {
3646 		.name = "port_representor",
3647 		.help = "match traffic entering the embedded switch from the given ethdev",
3648 		.priv = PRIV_ITEM(PORT_REPRESENTOR,
3649 				  sizeof(struct rte_flow_item_ethdev)),
3650 		.next = NEXT(item_port_representor),
3651 		.call = parse_vc,
3652 	},
3653 	[ITEM_PORT_REPRESENTOR_PORT_ID] = {
3654 		.name = "port_id",
3655 		.help = "ethdev port ID",
3656 		.next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED),
3657 			     item_param),
3658 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
3659 	},
3660 	[ITEM_REPRESENTED_PORT] = {
3661 		.name = "represented_port",
3662 		.help = "match traffic entering the embedded switch from the entity represented by the given ethdev",
3663 		.priv = PRIV_ITEM(REPRESENTED_PORT,
3664 				  sizeof(struct rte_flow_item_ethdev)),
3665 		.next = NEXT(item_represented_port),
3666 		.call = parse_vc,
3667 	},
3668 	[ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
3669 		.name = "ethdev_port_id",
3670 		.help = "ethdev port ID",
3671 		.next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED),
3672 			     item_param),
3673 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)),
3674 	},
3675 	/* Validate/create actions. */
3676 	[ACTIONS] = {
3677 		.name = "actions",
3678 		.help = "submit a list of associated actions",
3679 		.next = NEXT(next_action),
3680 		.call = parse_vc,
3681 	},
3682 	[ACTION_NEXT] = {
3683 		.name = "/",
3684 		.help = "specify next action",
3685 		.next = NEXT(next_action),
3686 	},
3687 	[ACTION_END] = {
3688 		.name = "end",
3689 		.help = "end list of actions",
3690 		.priv = PRIV_ACTION(END, 0),
3691 		.call = parse_vc,
3692 	},
3693 	[ACTION_VOID] = {
3694 		.name = "void",
3695 		.help = "no-op action",
3696 		.priv = PRIV_ACTION(VOID, 0),
3697 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3698 		.call = parse_vc,
3699 	},
3700 	[ACTION_PASSTHRU] = {
3701 		.name = "passthru",
3702 		.help = "let subsequent rule process matched packets",
3703 		.priv = PRIV_ACTION(PASSTHRU, 0),
3704 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3705 		.call = parse_vc,
3706 	},
3707 	[ACTION_JUMP] = {
3708 		.name = "jump",
3709 		.help = "redirect traffic to a given group",
3710 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
3711 		.next = NEXT(action_jump),
3712 		.call = parse_vc,
3713 	},
3714 	[ACTION_JUMP_GROUP] = {
3715 		.name = "group",
3716 		.help = "group to redirect traffic to",
3717 		.next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)),
3718 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
3719 		.call = parse_vc_conf,
3720 	},
3721 	[ACTION_MARK] = {
3722 		.name = "mark",
3723 		.help = "attach 32 bit value to packets",
3724 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
3725 		.next = NEXT(action_mark),
3726 		.call = parse_vc,
3727 	},
3728 	[ACTION_MARK_ID] = {
3729 		.name = "id",
3730 		.help = "32 bit value to return with packets",
3731 		.next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)),
3732 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
3733 		.call = parse_vc_conf,
3734 	},
3735 	[ACTION_FLAG] = {
3736 		.name = "flag",
3737 		.help = "flag packets",
3738 		.priv = PRIV_ACTION(FLAG, 0),
3739 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3740 		.call = parse_vc,
3741 	},
3742 	[ACTION_QUEUE] = {
3743 		.name = "queue",
3744 		.help = "assign packets to a given queue index",
3745 		.priv = PRIV_ACTION(QUEUE,
3746 				    sizeof(struct rte_flow_action_queue)),
3747 		.next = NEXT(action_queue),
3748 		.call = parse_vc,
3749 	},
3750 	[ACTION_QUEUE_INDEX] = {
3751 		.name = "index",
3752 		.help = "queue index to use",
3753 		.next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)),
3754 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
3755 		.call = parse_vc_conf,
3756 	},
3757 	[ACTION_DROP] = {
3758 		.name = "drop",
3759 		.help = "drop packets (note: passthru has priority)",
3760 		.priv = PRIV_ACTION(DROP, 0),
3761 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3762 		.call = parse_vc,
3763 	},
3764 	[ACTION_COUNT] = {
3765 		.name = "count",
3766 		.help = "enable counters for this rule",
3767 		.priv = PRIV_ACTION(COUNT,
3768 				    sizeof(struct rte_flow_action_count)),
3769 		.next = NEXT(action_count),
3770 		.call = parse_vc,
3771 	},
3772 	[ACTION_COUNT_ID] = {
3773 		.name = "identifier",
3774 		.help = "counter identifier to use",
3775 		.next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)),
3776 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
3777 		.call = parse_vc_conf,
3778 	},
3779 	[ACTION_RSS] = {
3780 		.name = "rss",
3781 		.help = "spread packets among several queues",
3782 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
3783 		.next = NEXT(action_rss),
3784 		.call = parse_vc_action_rss,
3785 	},
3786 	[ACTION_RSS_FUNC] = {
3787 		.name = "func",
3788 		.help = "RSS hash function to apply",
3789 		.next = NEXT(action_rss,
3790 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
3791 					ACTION_RSS_FUNC_TOEPLITZ,
3792 					ACTION_RSS_FUNC_SIMPLE_XOR,
3793 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
3794 	},
3795 	[ACTION_RSS_FUNC_DEFAULT] = {
3796 		.name = "default",
3797 		.help = "default hash function",
3798 		.call = parse_vc_action_rss_func,
3799 	},
3800 	[ACTION_RSS_FUNC_TOEPLITZ] = {
3801 		.name = "toeplitz",
3802 		.help = "Toeplitz hash function",
3803 		.call = parse_vc_action_rss_func,
3804 	},
3805 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
3806 		.name = "simple_xor",
3807 		.help = "simple XOR hash function",
3808 		.call = parse_vc_action_rss_func,
3809 	},
3810 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
3811 		.name = "symmetric_toeplitz",
3812 		.help = "Symmetric Toeplitz hash function",
3813 		.call = parse_vc_action_rss_func,
3814 	},
3815 	[ACTION_RSS_LEVEL] = {
3816 		.name = "level",
3817 		.help = "encapsulation level for \"types\"",
3818 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3819 		.args = ARGS(ARGS_ENTRY_ARB
3820 			     (offsetof(struct action_rss_data, conf) +
3821 			      offsetof(struct rte_flow_action_rss, level),
3822 			      sizeof(((struct rte_flow_action_rss *)0)->
3823 				     level))),
3824 	},
3825 	[ACTION_RSS_TYPES] = {
3826 		.name = "types",
3827 		.help = "specific RSS hash types",
3828 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
3829 	},
3830 	[ACTION_RSS_TYPE] = {
3831 		.name = "{type}",
3832 		.help = "RSS hash type",
3833 		.call = parse_vc_action_rss_type,
3834 		.comp = comp_vc_action_rss_type,
3835 	},
3836 	[ACTION_RSS_KEY] = {
3837 		.name = "key",
3838 		.help = "RSS hash key",
3839 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)),
3840 		.args = ARGS(ARGS_ENTRY_ARB
3841 			     (offsetof(struct action_rss_data, conf) +
3842 			      offsetof(struct rte_flow_action_rss, key),
3843 			      sizeof(((struct rte_flow_action_rss *)0)->key)),
3844 			     ARGS_ENTRY_ARB
3845 			     (offsetof(struct action_rss_data, conf) +
3846 			      offsetof(struct rte_flow_action_rss, key_len),
3847 			      sizeof(((struct rte_flow_action_rss *)0)->
3848 				     key_len)),
3849 			     ARGS_ENTRY(struct action_rss_data, key)),
3850 	},
3851 	[ACTION_RSS_KEY_LEN] = {
3852 		.name = "key_len",
3853 		.help = "RSS hash key length in bytes",
3854 		.next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)),
3855 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3856 			     (offsetof(struct action_rss_data, conf) +
3857 			      offsetof(struct rte_flow_action_rss, key_len),
3858 			      sizeof(((struct rte_flow_action_rss *)0)->
3859 				     key_len),
3860 			      0,
3861 			      RSS_HASH_KEY_LENGTH)),
3862 	},
3863 	[ACTION_RSS_QUEUES] = {
3864 		.name = "queues",
3865 		.help = "queue indices to use",
3866 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
3867 		.call = parse_vc_conf,
3868 	},
3869 	[ACTION_RSS_QUEUE] = {
3870 		.name = "{queue}",
3871 		.help = "queue index",
3872 		.call = parse_vc_action_rss_queue,
3873 		.comp = comp_vc_action_rss_queue,
3874 	},
3875 	[ACTION_PF] = {
3876 		.name = "pf",
3877 		.help = "direct traffic to physical function",
3878 		.priv = PRIV_ACTION(PF, 0),
3879 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3880 		.call = parse_vc,
3881 	},
3882 	[ACTION_VF] = {
3883 		.name = "vf",
3884 		.help = "direct traffic to a virtual function ID",
3885 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
3886 		.next = NEXT(action_vf),
3887 		.call = parse_vc,
3888 	},
3889 	[ACTION_VF_ORIGINAL] = {
3890 		.name = "original",
3891 		.help = "use original VF ID if possible",
3892 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)),
3893 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
3894 					   original, 1)),
3895 		.call = parse_vc_conf,
3896 	},
3897 	[ACTION_VF_ID] = {
3898 		.name = "id",
3899 		.help = "VF ID",
3900 		.next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)),
3901 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
3902 		.call = parse_vc_conf,
3903 	},
3904 	[ACTION_PHY_PORT] = {
3905 		.name = "phy_port",
3906 		.help = "direct packets to physical port index",
3907 		.priv = PRIV_ACTION(PHY_PORT,
3908 				    sizeof(struct rte_flow_action_phy_port)),
3909 		.next = NEXT(action_phy_port),
3910 		.call = parse_vc,
3911 	},
3912 	[ACTION_PHY_PORT_ORIGINAL] = {
3913 		.name = "original",
3914 		.help = "use original port index if possible",
3915 		.next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)),
3916 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
3917 					   original, 1)),
3918 		.call = parse_vc_conf,
3919 	},
3920 	[ACTION_PHY_PORT_INDEX] = {
3921 		.name = "index",
3922 		.help = "physical port index",
3923 		.next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)),
3924 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
3925 					index)),
3926 		.call = parse_vc_conf,
3927 	},
3928 	[ACTION_PORT_ID] = {
3929 		.name = "port_id",
3930 		.help = "direct matching traffic to a given DPDK port ID",
3931 		.priv = PRIV_ACTION(PORT_ID,
3932 				    sizeof(struct rte_flow_action_port_id)),
3933 		.next = NEXT(action_port_id),
3934 		.call = parse_vc,
3935 	},
3936 	[ACTION_PORT_ID_ORIGINAL] = {
3937 		.name = "original",
3938 		.help = "use original DPDK port ID if possible",
3939 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)),
3940 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
3941 					   original, 1)),
3942 		.call = parse_vc_conf,
3943 	},
3944 	[ACTION_PORT_ID_ID] = {
3945 		.name = "id",
3946 		.help = "DPDK port ID",
3947 		.next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)),
3948 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
3949 		.call = parse_vc_conf,
3950 	},
3951 	[ACTION_METER] = {
3952 		.name = "meter",
3953 		.help = "meter the directed packets at given id",
3954 		.priv = PRIV_ACTION(METER,
3955 				    sizeof(struct rte_flow_action_meter)),
3956 		.next = NEXT(action_meter),
3957 		.call = parse_vc,
3958 	},
3959 	[ACTION_METER_COLOR] = {
3960 		.name = "color",
3961 		.help = "meter color for the packets",
3962 		.priv = PRIV_ACTION(METER_COLOR,
3963 				sizeof(struct rte_flow_action_meter_color)),
3964 		.next = NEXT(action_meter_color),
3965 		.call = parse_vc,
3966 	},
3967 	[ACTION_METER_COLOR_TYPE] = {
3968 		.name = "type",
3969 		.help = "specific meter color",
3970 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
3971 				NEXT_ENTRY(ACTION_METER_COLOR_GREEN,
3972 					ACTION_METER_COLOR_YELLOW,
3973 					ACTION_METER_COLOR_RED)),
3974 	},
3975 	[ACTION_METER_COLOR_GREEN] = {
3976 		.name = "green",
3977 		.help = "meter color green",
3978 		.call = parse_vc_action_meter_color_type,
3979 	},
3980 	[ACTION_METER_COLOR_YELLOW] = {
3981 		.name = "yellow",
3982 		.help = "meter color yellow",
3983 		.call = parse_vc_action_meter_color_type,
3984 	},
3985 	[ACTION_METER_COLOR_RED] = {
3986 		.name = "red",
3987 		.help = "meter color red",
3988 		.call = parse_vc_action_meter_color_type,
3989 	},
3990 	[ACTION_METER_ID] = {
3991 		.name = "mtr_id",
3992 		.help = "meter id to use",
3993 		.next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)),
3994 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
3995 		.call = parse_vc_conf,
3996 	},
3997 	[ACTION_OF_SET_MPLS_TTL] = {
3998 		.name = "of_set_mpls_ttl",
3999 		.help = "OpenFlow's OFPAT_SET_MPLS_TTL",
4000 		.priv = PRIV_ACTION
4001 			(OF_SET_MPLS_TTL,
4002 			 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
4003 		.next = NEXT(action_of_set_mpls_ttl),
4004 		.call = parse_vc,
4005 	},
4006 	[ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
4007 		.name = "mpls_ttl",
4008 		.help = "MPLS TTL",
4009 		.next = NEXT(action_of_set_mpls_ttl,
4010 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4011 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
4012 					mpls_ttl)),
4013 		.call = parse_vc_conf,
4014 	},
4015 	[ACTION_OF_DEC_MPLS_TTL] = {
4016 		.name = "of_dec_mpls_ttl",
4017 		.help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
4018 		.priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
4019 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4020 		.call = parse_vc,
4021 	},
4022 	[ACTION_OF_SET_NW_TTL] = {
4023 		.name = "of_set_nw_ttl",
4024 		.help = "OpenFlow's OFPAT_SET_NW_TTL",
4025 		.priv = PRIV_ACTION
4026 			(OF_SET_NW_TTL,
4027 			 sizeof(struct rte_flow_action_of_set_nw_ttl)),
4028 		.next = NEXT(action_of_set_nw_ttl),
4029 		.call = parse_vc,
4030 	},
4031 	[ACTION_OF_SET_NW_TTL_NW_TTL] = {
4032 		.name = "nw_ttl",
4033 		.help = "IP TTL",
4034 		.next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4035 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
4036 					nw_ttl)),
4037 		.call = parse_vc_conf,
4038 	},
4039 	[ACTION_OF_DEC_NW_TTL] = {
4040 		.name = "of_dec_nw_ttl",
4041 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
4042 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
4043 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4044 		.call = parse_vc,
4045 	},
4046 	[ACTION_OF_COPY_TTL_OUT] = {
4047 		.name = "of_copy_ttl_out",
4048 		.help = "OpenFlow's OFPAT_COPY_TTL_OUT",
4049 		.priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
4050 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4051 		.call = parse_vc,
4052 	},
4053 	[ACTION_OF_COPY_TTL_IN] = {
4054 		.name = "of_copy_ttl_in",
4055 		.help = "OpenFlow's OFPAT_COPY_TTL_IN",
4056 		.priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
4057 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4058 		.call = parse_vc,
4059 	},
4060 	[ACTION_OF_POP_VLAN] = {
4061 		.name = "of_pop_vlan",
4062 		.help = "OpenFlow's OFPAT_POP_VLAN",
4063 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
4064 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4065 		.call = parse_vc,
4066 	},
4067 	[ACTION_OF_PUSH_VLAN] = {
4068 		.name = "of_push_vlan",
4069 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
4070 		.priv = PRIV_ACTION
4071 			(OF_PUSH_VLAN,
4072 			 sizeof(struct rte_flow_action_of_push_vlan)),
4073 		.next = NEXT(action_of_push_vlan),
4074 		.call = parse_vc,
4075 	},
4076 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
4077 		.name = "ethertype",
4078 		.help = "EtherType",
4079 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)),
4080 		.args = ARGS(ARGS_ENTRY_HTON
4081 			     (struct rte_flow_action_of_push_vlan,
4082 			      ethertype)),
4083 		.call = parse_vc_conf,
4084 	},
4085 	[ACTION_OF_SET_VLAN_VID] = {
4086 		.name = "of_set_vlan_vid",
4087 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
4088 		.priv = PRIV_ACTION
4089 			(OF_SET_VLAN_VID,
4090 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
4091 		.next = NEXT(action_of_set_vlan_vid),
4092 		.call = parse_vc,
4093 	},
4094 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
4095 		.name = "vlan_vid",
4096 		.help = "VLAN id",
4097 		.next = NEXT(action_of_set_vlan_vid,
4098 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4099 		.args = ARGS(ARGS_ENTRY_HTON
4100 			     (struct rte_flow_action_of_set_vlan_vid,
4101 			      vlan_vid)),
4102 		.call = parse_vc_conf,
4103 	},
4104 	[ACTION_OF_SET_VLAN_PCP] = {
4105 		.name = "of_set_vlan_pcp",
4106 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
4107 		.priv = PRIV_ACTION
4108 			(OF_SET_VLAN_PCP,
4109 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
4110 		.next = NEXT(action_of_set_vlan_pcp),
4111 		.call = parse_vc,
4112 	},
4113 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
4114 		.name = "vlan_pcp",
4115 		.help = "VLAN priority",
4116 		.next = NEXT(action_of_set_vlan_pcp,
4117 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4118 		.args = ARGS(ARGS_ENTRY_HTON
4119 			     (struct rte_flow_action_of_set_vlan_pcp,
4120 			      vlan_pcp)),
4121 		.call = parse_vc_conf,
4122 	},
4123 	[ACTION_OF_POP_MPLS] = {
4124 		.name = "of_pop_mpls",
4125 		.help = "OpenFlow's OFPAT_POP_MPLS",
4126 		.priv = PRIV_ACTION(OF_POP_MPLS,
4127 				    sizeof(struct rte_flow_action_of_pop_mpls)),
4128 		.next = NEXT(action_of_pop_mpls),
4129 		.call = parse_vc,
4130 	},
4131 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
4132 		.name = "ethertype",
4133 		.help = "EtherType",
4134 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4135 		.args = ARGS(ARGS_ENTRY_HTON
4136 			     (struct rte_flow_action_of_pop_mpls,
4137 			      ethertype)),
4138 		.call = parse_vc_conf,
4139 	},
4140 	[ACTION_OF_PUSH_MPLS] = {
4141 		.name = "of_push_mpls",
4142 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
4143 		.priv = PRIV_ACTION
4144 			(OF_PUSH_MPLS,
4145 			 sizeof(struct rte_flow_action_of_push_mpls)),
4146 		.next = NEXT(action_of_push_mpls),
4147 		.call = parse_vc,
4148 	},
4149 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
4150 		.name = "ethertype",
4151 		.help = "EtherType",
4152 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)),
4153 		.args = ARGS(ARGS_ENTRY_HTON
4154 			     (struct rte_flow_action_of_push_mpls,
4155 			      ethertype)),
4156 		.call = parse_vc_conf,
4157 	},
4158 	[ACTION_VXLAN_ENCAP] = {
4159 		.name = "vxlan_encap",
4160 		.help = "VXLAN encapsulation, uses configuration set by \"set"
4161 			" vxlan\"",
4162 		.priv = PRIV_ACTION(VXLAN_ENCAP,
4163 				    sizeof(struct action_vxlan_encap_data)),
4164 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4165 		.call = parse_vc_action_vxlan_encap,
4166 	},
4167 	[ACTION_VXLAN_DECAP] = {
4168 		.name = "vxlan_decap",
4169 		.help = "Performs a decapsulation action by stripping all"
4170 			" headers of the VXLAN tunnel network overlay from the"
4171 			" matched flow.",
4172 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
4173 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4174 		.call = parse_vc,
4175 	},
4176 	[ACTION_NVGRE_ENCAP] = {
4177 		.name = "nvgre_encap",
4178 		.help = "NVGRE encapsulation, uses configuration set by \"set"
4179 			" nvgre\"",
4180 		.priv = PRIV_ACTION(NVGRE_ENCAP,
4181 				    sizeof(struct action_nvgre_encap_data)),
4182 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4183 		.call = parse_vc_action_nvgre_encap,
4184 	},
4185 	[ACTION_NVGRE_DECAP] = {
4186 		.name = "nvgre_decap",
4187 		.help = "Performs a decapsulation action by stripping all"
4188 			" headers of the NVGRE tunnel network overlay from the"
4189 			" matched flow.",
4190 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
4191 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4192 		.call = parse_vc,
4193 	},
4194 	[ACTION_L2_ENCAP] = {
4195 		.name = "l2_encap",
4196 		.help = "l2 encap, uses configuration set by"
4197 			" \"set l2_encap\"",
4198 		.priv = PRIV_ACTION(RAW_ENCAP,
4199 				    sizeof(struct action_raw_encap_data)),
4200 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4201 		.call = parse_vc_action_l2_encap,
4202 	},
4203 	[ACTION_L2_DECAP] = {
4204 		.name = "l2_decap",
4205 		.help = "l2 decap, uses configuration set by"
4206 			" \"set l2_decap\"",
4207 		.priv = PRIV_ACTION(RAW_DECAP,
4208 				    sizeof(struct action_raw_decap_data)),
4209 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4210 		.call = parse_vc_action_l2_decap,
4211 	},
4212 	[ACTION_MPLSOGRE_ENCAP] = {
4213 		.name = "mplsogre_encap",
4214 		.help = "mplsogre encapsulation, uses configuration set by"
4215 			" \"set mplsogre_encap\"",
4216 		.priv = PRIV_ACTION(RAW_ENCAP,
4217 				    sizeof(struct action_raw_encap_data)),
4218 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4219 		.call = parse_vc_action_mplsogre_encap,
4220 	},
4221 	[ACTION_MPLSOGRE_DECAP] = {
4222 		.name = "mplsogre_decap",
4223 		.help = "mplsogre decapsulation, uses configuration set by"
4224 			" \"set mplsogre_decap\"",
4225 		.priv = PRIV_ACTION(RAW_DECAP,
4226 				    sizeof(struct action_raw_decap_data)),
4227 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4228 		.call = parse_vc_action_mplsogre_decap,
4229 	},
4230 	[ACTION_MPLSOUDP_ENCAP] = {
4231 		.name = "mplsoudp_encap",
4232 		.help = "mplsoudp encapsulation, uses configuration set by"
4233 			" \"set mplsoudp_encap\"",
4234 		.priv = PRIV_ACTION(RAW_ENCAP,
4235 				    sizeof(struct action_raw_encap_data)),
4236 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4237 		.call = parse_vc_action_mplsoudp_encap,
4238 	},
4239 	[ACTION_MPLSOUDP_DECAP] = {
4240 		.name = "mplsoudp_decap",
4241 		.help = "mplsoudp decapsulation, uses configuration set by"
4242 			" \"set mplsoudp_decap\"",
4243 		.priv = PRIV_ACTION(RAW_DECAP,
4244 				    sizeof(struct action_raw_decap_data)),
4245 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4246 		.call = parse_vc_action_mplsoudp_decap,
4247 	},
4248 	[ACTION_SET_IPV4_SRC] = {
4249 		.name = "set_ipv4_src",
4250 		.help = "Set a new IPv4 source address in the outermost"
4251 			" IPv4 header",
4252 		.priv = PRIV_ACTION(SET_IPV4_SRC,
4253 			sizeof(struct rte_flow_action_set_ipv4)),
4254 		.next = NEXT(action_set_ipv4_src),
4255 		.call = parse_vc,
4256 	},
4257 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
4258 		.name = "ipv4_addr",
4259 		.help = "new IPv4 source address to set",
4260 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4261 		.args = ARGS(ARGS_ENTRY_HTON
4262 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
4263 		.call = parse_vc_conf,
4264 	},
4265 	[ACTION_SET_IPV4_DST] = {
4266 		.name = "set_ipv4_dst",
4267 		.help = "Set a new IPv4 destination address in the outermost"
4268 			" IPv4 header",
4269 		.priv = PRIV_ACTION(SET_IPV4_DST,
4270 			sizeof(struct rte_flow_action_set_ipv4)),
4271 		.next = NEXT(action_set_ipv4_dst),
4272 		.call = parse_vc,
4273 	},
4274 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
4275 		.name = "ipv4_addr",
4276 		.help = "new IPv4 destination address to set",
4277 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)),
4278 		.args = ARGS(ARGS_ENTRY_HTON
4279 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
4280 		.call = parse_vc_conf,
4281 	},
4282 	[ACTION_SET_IPV6_SRC] = {
4283 		.name = "set_ipv6_src",
4284 		.help = "Set a new IPv6 source address in the outermost"
4285 			" IPv6 header",
4286 		.priv = PRIV_ACTION(SET_IPV6_SRC,
4287 			sizeof(struct rte_flow_action_set_ipv6)),
4288 		.next = NEXT(action_set_ipv6_src),
4289 		.call = parse_vc,
4290 	},
4291 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
4292 		.name = "ipv6_addr",
4293 		.help = "new IPv6 source address to set",
4294 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4295 		.args = ARGS(ARGS_ENTRY_HTON
4296 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
4297 		.call = parse_vc_conf,
4298 	},
4299 	[ACTION_SET_IPV6_DST] = {
4300 		.name = "set_ipv6_dst",
4301 		.help = "Set a new IPv6 destination address in the outermost"
4302 			" IPv6 header",
4303 		.priv = PRIV_ACTION(SET_IPV6_DST,
4304 			sizeof(struct rte_flow_action_set_ipv6)),
4305 		.next = NEXT(action_set_ipv6_dst),
4306 		.call = parse_vc,
4307 	},
4308 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
4309 		.name = "ipv6_addr",
4310 		.help = "new IPv6 destination address to set",
4311 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)),
4312 		.args = ARGS(ARGS_ENTRY_HTON
4313 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
4314 		.call = parse_vc_conf,
4315 	},
4316 	[ACTION_SET_TP_SRC] = {
4317 		.name = "set_tp_src",
4318 		.help = "set a new source port number in the outermost"
4319 			" TCP/UDP header",
4320 		.priv = PRIV_ACTION(SET_TP_SRC,
4321 			sizeof(struct rte_flow_action_set_tp)),
4322 		.next = NEXT(action_set_tp_src),
4323 		.call = parse_vc,
4324 	},
4325 	[ACTION_SET_TP_SRC_TP_SRC] = {
4326 		.name = "port",
4327 		.help = "new source port number to set",
4328 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)),
4329 		.args = ARGS(ARGS_ENTRY_HTON
4330 			     (struct rte_flow_action_set_tp, port)),
4331 		.call = parse_vc_conf,
4332 	},
4333 	[ACTION_SET_TP_DST] = {
4334 		.name = "set_tp_dst",
4335 		.help = "set a new destination port number in the outermost"
4336 			" TCP/UDP header",
4337 		.priv = PRIV_ACTION(SET_TP_DST,
4338 			sizeof(struct rte_flow_action_set_tp)),
4339 		.next = NEXT(action_set_tp_dst),
4340 		.call = parse_vc,
4341 	},
4342 	[ACTION_SET_TP_DST_TP_DST] = {
4343 		.name = "port",
4344 		.help = "new destination port number to set",
4345 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)),
4346 		.args = ARGS(ARGS_ENTRY_HTON
4347 			     (struct rte_flow_action_set_tp, port)),
4348 		.call = parse_vc_conf,
4349 	},
4350 	[ACTION_MAC_SWAP] = {
4351 		.name = "mac_swap",
4352 		.help = "Swap the source and destination MAC addresses"
4353 			" in the outermost Ethernet header",
4354 		.priv = PRIV_ACTION(MAC_SWAP, 0),
4355 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4356 		.call = parse_vc,
4357 	},
4358 	[ACTION_DEC_TTL] = {
4359 		.name = "dec_ttl",
4360 		.help = "decrease network TTL if available",
4361 		.priv = PRIV_ACTION(DEC_TTL, 0),
4362 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4363 		.call = parse_vc,
4364 	},
4365 	[ACTION_SET_TTL] = {
4366 		.name = "set_ttl",
4367 		.help = "set ttl value",
4368 		.priv = PRIV_ACTION(SET_TTL,
4369 			sizeof(struct rte_flow_action_set_ttl)),
4370 		.next = NEXT(action_set_ttl),
4371 		.call = parse_vc,
4372 	},
4373 	[ACTION_SET_TTL_TTL] = {
4374 		.name = "ttl_value",
4375 		.help = "new ttl value to set",
4376 		.next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)),
4377 		.args = ARGS(ARGS_ENTRY_HTON
4378 			     (struct rte_flow_action_set_ttl, ttl_value)),
4379 		.call = parse_vc_conf,
4380 	},
4381 	[ACTION_SET_MAC_SRC] = {
4382 		.name = "set_mac_src",
4383 		.help = "set source mac address",
4384 		.priv = PRIV_ACTION(SET_MAC_SRC,
4385 			sizeof(struct rte_flow_action_set_mac)),
4386 		.next = NEXT(action_set_mac_src),
4387 		.call = parse_vc,
4388 	},
4389 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
4390 		.name = "mac_addr",
4391 		.help = "new source mac address",
4392 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)),
4393 		.args = ARGS(ARGS_ENTRY_HTON
4394 			     (struct rte_flow_action_set_mac, mac_addr)),
4395 		.call = parse_vc_conf,
4396 	},
4397 	[ACTION_SET_MAC_DST] = {
4398 		.name = "set_mac_dst",
4399 		.help = "set destination mac address",
4400 		.priv = PRIV_ACTION(SET_MAC_DST,
4401 			sizeof(struct rte_flow_action_set_mac)),
4402 		.next = NEXT(action_set_mac_dst),
4403 		.call = parse_vc,
4404 	},
4405 	[ACTION_SET_MAC_DST_MAC_DST] = {
4406 		.name = "mac_addr",
4407 		.help = "new destination mac address to set",
4408 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)),
4409 		.args = ARGS(ARGS_ENTRY_HTON
4410 			     (struct rte_flow_action_set_mac, mac_addr)),
4411 		.call = parse_vc_conf,
4412 	},
4413 	[ACTION_INC_TCP_SEQ] = {
4414 		.name = "inc_tcp_seq",
4415 		.help = "increase TCP sequence number",
4416 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
4417 		.next = NEXT(action_inc_tcp_seq),
4418 		.call = parse_vc,
4419 	},
4420 	[ACTION_INC_TCP_SEQ_VALUE] = {
4421 		.name = "value",
4422 		.help = "the value to increase TCP sequence number by",
4423 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4424 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4425 		.call = parse_vc_conf,
4426 	},
4427 	[ACTION_DEC_TCP_SEQ] = {
4428 		.name = "dec_tcp_seq",
4429 		.help = "decrease TCP sequence number",
4430 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
4431 		.next = NEXT(action_dec_tcp_seq),
4432 		.call = parse_vc,
4433 	},
4434 	[ACTION_DEC_TCP_SEQ_VALUE] = {
4435 		.name = "value",
4436 		.help = "the value to decrease TCP sequence number by",
4437 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)),
4438 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4439 		.call = parse_vc_conf,
4440 	},
4441 	[ACTION_INC_TCP_ACK] = {
4442 		.name = "inc_tcp_ack",
4443 		.help = "increase TCP acknowledgment number",
4444 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
4445 		.next = NEXT(action_inc_tcp_ack),
4446 		.call = parse_vc,
4447 	},
4448 	[ACTION_INC_TCP_ACK_VALUE] = {
4449 		.name = "value",
4450 		.help = "the value to increase TCP acknowledgment number by",
4451 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4452 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4453 		.call = parse_vc_conf,
4454 	},
4455 	[ACTION_DEC_TCP_ACK] = {
4456 		.name = "dec_tcp_ack",
4457 		.help = "decrease TCP acknowledgment number",
4458 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
4459 		.next = NEXT(action_dec_tcp_ack),
4460 		.call = parse_vc,
4461 	},
4462 	[ACTION_DEC_TCP_ACK_VALUE] = {
4463 		.name = "value",
4464 		.help = "the value to decrease TCP acknowledgment number by",
4465 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)),
4466 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
4467 		.call = parse_vc_conf,
4468 	},
4469 	[ACTION_RAW_ENCAP] = {
4470 		.name = "raw_encap",
4471 		.help = "encapsulation data, defined by set raw_encap",
4472 		.priv = PRIV_ACTION(RAW_ENCAP,
4473 			sizeof(struct action_raw_encap_data)),
4474 		.next = NEXT(action_raw_encap),
4475 		.call = parse_vc_action_raw_encap,
4476 	},
4477 	[ACTION_RAW_ENCAP_INDEX] = {
4478 		.name = "index",
4479 		.help = "the index of raw_encap_confs",
4480 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
4481 	},
4482 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
4483 		.name = "{index}",
4484 		.type = "UNSIGNED",
4485 		.help = "unsigned integer value",
4486 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4487 		.call = parse_vc_action_raw_encap_index,
4488 		.comp = comp_set_raw_index,
4489 	},
4490 	[ACTION_RAW_DECAP] = {
4491 		.name = "raw_decap",
4492 		.help = "decapsulation data, defined by set raw_encap",
4493 		.priv = PRIV_ACTION(RAW_DECAP,
4494 			sizeof(struct action_raw_decap_data)),
4495 		.next = NEXT(action_raw_decap),
4496 		.call = parse_vc_action_raw_decap,
4497 	},
4498 	[ACTION_RAW_DECAP_INDEX] = {
4499 		.name = "index",
4500 		.help = "the index of raw_encap_confs",
4501 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
4502 	},
4503 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
4504 		.name = "{index}",
4505 		.type = "UNSIGNED",
4506 		.help = "unsigned integer value",
4507 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4508 		.call = parse_vc_action_raw_decap_index,
4509 		.comp = comp_set_raw_index,
4510 	},
4511 	[ACTION_MODIFY_FIELD] = {
4512 		.name = "modify_field",
4513 		.help = "modify destination field with data from source field",
4514 		.priv = PRIV_ACTION(MODIFY_FIELD,
4515 			sizeof(struct rte_flow_action_modify_field)),
4516 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)),
4517 		.call = parse_vc,
4518 	},
4519 	[ACTION_MODIFY_FIELD_OP] = {
4520 		.name = "op",
4521 		.help = "operation type",
4522 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE),
4523 			NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)),
4524 		.call = parse_vc_conf,
4525 	},
4526 	[ACTION_MODIFY_FIELD_OP_VALUE] = {
4527 		.name = "{operation}",
4528 		.help = "operation type value",
4529 		.call = parse_vc_modify_field_op,
4530 		.comp = comp_set_modify_field_op,
4531 	},
4532 	[ACTION_MODIFY_FIELD_DST_TYPE] = {
4533 		.name = "dst_type",
4534 		.help = "destination field type",
4535 		.next = NEXT(action_modify_field_dst,
4536 			NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)),
4537 		.call = parse_vc_conf,
4538 	},
4539 	[ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = {
4540 		.name = "{dst_type}",
4541 		.help = "destination field type value",
4542 		.call = parse_vc_modify_field_id,
4543 		.comp = comp_set_modify_field_id,
4544 	},
4545 	[ACTION_MODIFY_FIELD_DST_LEVEL] = {
4546 		.name = "dst_level",
4547 		.help = "destination field level",
4548 		.next = NEXT(action_modify_field_dst,
4549 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4550 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4551 					dst.level)),
4552 		.call = parse_vc_conf,
4553 	},
4554 	[ACTION_MODIFY_FIELD_DST_OFFSET] = {
4555 		.name = "dst_offset",
4556 		.help = "destination field bit offset",
4557 		.next = NEXT(action_modify_field_dst,
4558 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4559 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4560 					dst.offset)),
4561 		.call = parse_vc_conf,
4562 	},
4563 	[ACTION_MODIFY_FIELD_SRC_TYPE] = {
4564 		.name = "src_type",
4565 		.help = "source field type",
4566 		.next = NEXT(action_modify_field_src,
4567 			NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)),
4568 		.call = parse_vc_conf,
4569 	},
4570 	[ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = {
4571 		.name = "{src_type}",
4572 		.help = "source field type value",
4573 		.call = parse_vc_modify_field_id,
4574 		.comp = comp_set_modify_field_id,
4575 	},
4576 	[ACTION_MODIFY_FIELD_SRC_LEVEL] = {
4577 		.name = "src_level",
4578 		.help = "source field level",
4579 		.next = NEXT(action_modify_field_src,
4580 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4581 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4582 					src.level)),
4583 		.call = parse_vc_conf,
4584 	},
4585 	[ACTION_MODIFY_FIELD_SRC_OFFSET] = {
4586 		.name = "src_offset",
4587 		.help = "source field bit offset",
4588 		.next = NEXT(action_modify_field_src,
4589 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4590 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4591 					src.offset)),
4592 		.call = parse_vc_conf,
4593 	},
4594 	[ACTION_MODIFY_FIELD_SRC_VALUE] = {
4595 		.name = "src_value",
4596 		.help = "source immediate value",
4597 		.next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH),
4598 			NEXT_ENTRY(COMMON_UNSIGNED)),
4599 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4600 					src.value)),
4601 		.call = parse_vc_conf,
4602 	},
4603 	[ACTION_MODIFY_FIELD_WIDTH] = {
4604 		.name = "width",
4605 		.help = "number of bits to copy",
4606 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT),
4607 			NEXT_ENTRY(COMMON_UNSIGNED)),
4608 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field,
4609 					width)),
4610 		.call = parse_vc_conf,
4611 	},
4612 	/* Top level command. */
4613 	[SET] = {
4614 		.name = "set",
4615 		.help = "set raw encap/decap/sample data",
4616 		.type = "set raw_encap|raw_decap <index> <pattern>"
4617 				" or set sample_actions <index> <action>",
4618 		.next = NEXT(NEXT_ENTRY
4619 			     (SET_RAW_ENCAP,
4620 			      SET_RAW_DECAP,
4621 			      SET_SAMPLE_ACTIONS)),
4622 		.call = parse_set_init,
4623 	},
4624 	/* Sub-level commands. */
4625 	[SET_RAW_ENCAP] = {
4626 		.name = "raw_encap",
4627 		.help = "set raw encap data",
4628 		.next = NEXT(next_set_raw),
4629 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4630 				(offsetof(struct buffer, port),
4631 				 sizeof(((struct buffer *)0)->port),
4632 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4633 		.call = parse_set_raw_encap_decap,
4634 	},
4635 	[SET_RAW_DECAP] = {
4636 		.name = "raw_decap",
4637 		.help = "set raw decap data",
4638 		.next = NEXT(next_set_raw),
4639 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4640 				(offsetof(struct buffer, port),
4641 				 sizeof(((struct buffer *)0)->port),
4642 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
4643 		.call = parse_set_raw_encap_decap,
4644 	},
4645 	[SET_RAW_INDEX] = {
4646 		.name = "{index}",
4647 		.type = "COMMON_UNSIGNED",
4648 		.help = "index of raw_encap/raw_decap data",
4649 		.next = NEXT(next_item),
4650 		.call = parse_port,
4651 	},
4652 	[SET_SAMPLE_INDEX] = {
4653 		.name = "{index}",
4654 		.type = "UNSIGNED",
4655 		.help = "index of sample actions",
4656 		.next = NEXT(next_action_sample),
4657 		.call = parse_port,
4658 	},
4659 	[SET_SAMPLE_ACTIONS] = {
4660 		.name = "sample_actions",
4661 		.help = "set sample actions list",
4662 		.next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)),
4663 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
4664 				(offsetof(struct buffer, port),
4665 				 sizeof(((struct buffer *)0)->port),
4666 				 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)),
4667 		.call = parse_set_sample_action,
4668 	},
4669 	[ACTION_SET_TAG] = {
4670 		.name = "set_tag",
4671 		.help = "set tag",
4672 		.priv = PRIV_ACTION(SET_TAG,
4673 			sizeof(struct rte_flow_action_set_tag)),
4674 		.next = NEXT(action_set_tag),
4675 		.call = parse_vc,
4676 	},
4677 	[ACTION_SET_TAG_INDEX] = {
4678 		.name = "index",
4679 		.help = "index of tag array",
4680 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4681 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
4682 		.call = parse_vc_conf,
4683 	},
4684 	[ACTION_SET_TAG_DATA] = {
4685 		.name = "data",
4686 		.help = "tag value",
4687 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4688 		.args = ARGS(ARGS_ENTRY
4689 			     (struct rte_flow_action_set_tag, data)),
4690 		.call = parse_vc_conf,
4691 	},
4692 	[ACTION_SET_TAG_MASK] = {
4693 		.name = "mask",
4694 		.help = "mask for tag value",
4695 		.next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)),
4696 		.args = ARGS(ARGS_ENTRY
4697 			     (struct rte_flow_action_set_tag, mask)),
4698 		.call = parse_vc_conf,
4699 	},
4700 	[ACTION_SET_META] = {
4701 		.name = "set_meta",
4702 		.help = "set metadata",
4703 		.priv = PRIV_ACTION(SET_META,
4704 			sizeof(struct rte_flow_action_set_meta)),
4705 		.next = NEXT(action_set_meta),
4706 		.call = parse_vc_action_set_meta,
4707 	},
4708 	[ACTION_SET_META_DATA] = {
4709 		.name = "data",
4710 		.help = "metadata value",
4711 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4712 		.args = ARGS(ARGS_ENTRY
4713 			     (struct rte_flow_action_set_meta, data)),
4714 		.call = parse_vc_conf,
4715 	},
4716 	[ACTION_SET_META_MASK] = {
4717 		.name = "mask",
4718 		.help = "mask for metadata value",
4719 		.next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)),
4720 		.args = ARGS(ARGS_ENTRY
4721 			     (struct rte_flow_action_set_meta, mask)),
4722 		.call = parse_vc_conf,
4723 	},
4724 	[ACTION_SET_IPV4_DSCP] = {
4725 		.name = "set_ipv4_dscp",
4726 		.help = "set DSCP value",
4727 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
4728 			sizeof(struct rte_flow_action_set_dscp)),
4729 		.next = NEXT(action_set_ipv4_dscp),
4730 		.call = parse_vc,
4731 	},
4732 	[ACTION_SET_IPV4_DSCP_VALUE] = {
4733 		.name = "dscp_value",
4734 		.help = "new IPv4 DSCP value to set",
4735 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4736 		.args = ARGS(ARGS_ENTRY
4737 			     (struct rte_flow_action_set_dscp, dscp)),
4738 		.call = parse_vc_conf,
4739 	},
4740 	[ACTION_SET_IPV6_DSCP] = {
4741 		.name = "set_ipv6_dscp",
4742 		.help = "set DSCP value",
4743 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
4744 			sizeof(struct rte_flow_action_set_dscp)),
4745 		.next = NEXT(action_set_ipv6_dscp),
4746 		.call = parse_vc,
4747 	},
4748 	[ACTION_SET_IPV6_DSCP_VALUE] = {
4749 		.name = "dscp_value",
4750 		.help = "new IPv6 DSCP value to set",
4751 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)),
4752 		.args = ARGS(ARGS_ENTRY
4753 			     (struct rte_flow_action_set_dscp, dscp)),
4754 		.call = parse_vc_conf,
4755 	},
4756 	[ACTION_AGE] = {
4757 		.name = "age",
4758 		.help = "set a specific metadata header",
4759 		.next = NEXT(action_age),
4760 		.priv = PRIV_ACTION(AGE,
4761 			sizeof(struct rte_flow_action_age)),
4762 		.call = parse_vc,
4763 	},
4764 	[ACTION_AGE_TIMEOUT] = {
4765 		.name = "timeout",
4766 		.help = "flow age timeout value",
4767 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
4768 					   timeout, 24)),
4769 		.next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)),
4770 		.call = parse_vc_conf,
4771 	},
4772 	[ACTION_SAMPLE] = {
4773 		.name = "sample",
4774 		.help = "set a sample action",
4775 		.next = NEXT(action_sample),
4776 		.priv = PRIV_ACTION(SAMPLE,
4777 			sizeof(struct action_sample_data)),
4778 		.call = parse_vc_action_sample,
4779 	},
4780 	[ACTION_SAMPLE_RATIO] = {
4781 		.name = "ratio",
4782 		.help = "flow sample ratio value",
4783 		.next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)),
4784 		.args = ARGS(ARGS_ENTRY_ARB
4785 			     (offsetof(struct action_sample_data, conf) +
4786 			      offsetof(struct rte_flow_action_sample, ratio),
4787 			      sizeof(((struct rte_flow_action_sample *)0)->
4788 				     ratio))),
4789 	},
4790 	[ACTION_SAMPLE_INDEX] = {
4791 		.name = "index",
4792 		.help = "the index of sample actions list",
4793 		.next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)),
4794 	},
4795 	[ACTION_SAMPLE_INDEX_VALUE] = {
4796 		.name = "{index}",
4797 		.type = "COMMON_UNSIGNED",
4798 		.help = "unsigned integer value",
4799 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4800 		.call = parse_vc_action_sample_index,
4801 		.comp = comp_set_sample_index,
4802 	},
4803 	[ACTION_CONNTRACK] = {
4804 		.name = "conntrack",
4805 		.help = "create a conntrack object",
4806 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4807 		.priv = PRIV_ACTION(CONNTRACK,
4808 				    sizeof(struct rte_flow_action_conntrack)),
4809 		.call = parse_vc,
4810 	},
4811 	[ACTION_CONNTRACK_UPDATE] = {
4812 		.name = "conntrack_update",
4813 		.help = "update a conntrack object",
4814 		.next = NEXT(action_update_conntrack),
4815 		.priv = PRIV_ACTION(CONNTRACK,
4816 				    sizeof(struct rte_flow_modify_conntrack)),
4817 		.call = parse_vc,
4818 	},
4819 	[ACTION_CONNTRACK_UPDATE_DIR] = {
4820 		.name = "dir",
4821 		.help = "update a conntrack object direction",
4822 		.next = NEXT(action_update_conntrack),
4823 		.call = parse_vc_action_conntrack_update,
4824 	},
4825 	[ACTION_CONNTRACK_UPDATE_CTX] = {
4826 		.name = "ctx",
4827 		.help = "update a conntrack object context",
4828 		.next = NEXT(action_update_conntrack),
4829 		.call = parse_vc_action_conntrack_update,
4830 	},
4831 	[ACTION_PORT_REPRESENTOR] = {
4832 		.name = "port_representor",
4833 		.help = "at embedded switch level, send matching traffic to the given ethdev",
4834 		.priv = PRIV_ACTION(PORT_REPRESENTOR,
4835 				    sizeof(struct rte_flow_action_ethdev)),
4836 		.next = NEXT(action_port_representor),
4837 		.call = parse_vc,
4838 	},
4839 	[ACTION_PORT_REPRESENTOR_PORT_ID] = {
4840 		.name = "port_id",
4841 		.help = "ethdev port ID",
4842 		.next = NEXT(action_port_representor,
4843 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4844 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
4845 					port_id)),
4846 		.call = parse_vc_conf,
4847 	},
4848 	[ACTION_REPRESENTED_PORT] = {
4849 		.name = "represented_port",
4850 		.help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev",
4851 		.priv = PRIV_ACTION(REPRESENTED_PORT,
4852 				sizeof(struct rte_flow_action_ethdev)),
4853 		.next = NEXT(action_represented_port),
4854 		.call = parse_vc,
4855 	},
4856 	[ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = {
4857 		.name = "ethdev_port_id",
4858 		.help = "ethdev port ID",
4859 		.next = NEXT(action_represented_port,
4860 			     NEXT_ENTRY(COMMON_UNSIGNED)),
4861 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev,
4862 					port_id)),
4863 		.call = parse_vc_conf,
4864 	},
4865 	/* Indirect action destroy arguments. */
4866 	[INDIRECT_ACTION_DESTROY_ID] = {
4867 		.name = "action_id",
4868 		.help = "specify a indirect action id to destroy",
4869 		.next = NEXT(next_ia_destroy_attr,
4870 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4871 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
4872 					    args.ia_destroy.action_id)),
4873 		.call = parse_ia_destroy,
4874 	},
4875 	/* Indirect action create arguments. */
4876 	[INDIRECT_ACTION_CREATE_ID] = {
4877 		.name = "action_id",
4878 		.help = "specify a indirect action id to create",
4879 		.next = NEXT(next_ia_create_attr,
4880 			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
4881 		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
4882 	},
4883 	[ACTION_INDIRECT] = {
4884 		.name = "indirect",
4885 		.help = "apply indirect action by id",
4886 		.priv = PRIV_ACTION(INDIRECT, 0),
4887 		.next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
4888 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
4889 		.call = parse_vc,
4890 	},
4891 	[INDIRECT_ACTION_ID2PTR] = {
4892 		.name = "{action_id}",
4893 		.type = "INDIRECT_ACTION_ID",
4894 		.help = "indirect action id",
4895 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
4896 		.call = parse_ia_id2ptr,
4897 		.comp = comp_none,
4898 	},
4899 	[INDIRECT_ACTION_INGRESS] = {
4900 		.name = "ingress",
4901 		.help = "affect rule to ingress",
4902 		.next = NEXT(next_ia_create_attr),
4903 		.call = parse_ia,
4904 	},
4905 	[INDIRECT_ACTION_EGRESS] = {
4906 		.name = "egress",
4907 		.help = "affect rule to egress",
4908 		.next = NEXT(next_ia_create_attr),
4909 		.call = parse_ia,
4910 	},
4911 	[INDIRECT_ACTION_TRANSFER] = {
4912 		.name = "transfer",
4913 		.help = "affect rule to transfer",
4914 		.next = NEXT(next_ia_create_attr),
4915 		.call = parse_ia,
4916 	},
4917 	[INDIRECT_ACTION_SPEC] = {
4918 		.name = "action",
4919 		.help = "specify action to create indirect handle",
4920 		.next = NEXT(next_action),
4921 	},
4922 	[ACTION_POL_G] = {
4923 		.name = "g_actions",
4924 		.help = "submit a list of associated actions for green",
4925 		.next = NEXT(next_action),
4926 		.call = parse_mp,
4927 	},
4928 	[ACTION_POL_Y] = {
4929 		.name = "y_actions",
4930 		.help = "submit a list of associated actions for yellow",
4931 		.next = NEXT(next_action),
4932 	},
4933 	[ACTION_POL_R] = {
4934 		.name = "r_actions",
4935 		.help = "submit a list of associated actions for red",
4936 		.next = NEXT(next_action),
4937 	},
4938 
4939 	/* Top-level command. */
4940 	[ADD] = {
4941 		.name = "add",
4942 		.type = "port meter policy {port_id} {arg}",
4943 		.help = "add port meter policy",
4944 		.next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)),
4945 		.call = parse_init,
4946 	},
4947 	/* Sub-level commands. */
4948 	[ITEM_POL_PORT] = {
4949 		.name = "port",
4950 		.help = "add port meter policy",
4951 		.next = NEXT(NEXT_ENTRY(ITEM_POL_METER)),
4952 	},
4953 	[ITEM_POL_METER] = {
4954 		.name = "meter",
4955 		.help = "add port meter policy",
4956 		.next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)),
4957 	},
4958 	[ITEM_POL_POLICY] = {
4959 		.name = "policy",
4960 		.help = "add port meter policy",
4961 		.next = NEXT(NEXT_ENTRY(ACTION_POL_R),
4962 				NEXT_ENTRY(ACTION_POL_Y),
4963 				NEXT_ENTRY(ACTION_POL_G),
4964 				NEXT_ENTRY(COMMON_POLICY_ID),
4965 				NEXT_ENTRY(COMMON_PORT_ID)),
4966 		.args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id),
4967 				ARGS_ENTRY(struct buffer, port)),
4968 		.call = parse_mp,
4969 	},
4970 };
4971 
4972 /** Remove and return last entry from argument stack. */
4973 static const struct arg *
4974 pop_args(struct context *ctx)
4975 {
4976 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
4977 }
4978 
4979 /** Add entry on top of the argument stack. */
4980 static int
4981 push_args(struct context *ctx, const struct arg *arg)
4982 {
4983 	if (ctx->args_num == CTX_STACK_SIZE)
4984 		return -1;
4985 	ctx->args[ctx->args_num++] = arg;
4986 	return 0;
4987 }
4988 
4989 /** Spread value into buffer according to bit-mask. */
4990 static size_t
4991 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
4992 {
4993 	uint32_t i = arg->size;
4994 	uint32_t end = 0;
4995 	int sub = 1;
4996 	int add = 0;
4997 	size_t len = 0;
4998 
4999 	if (!arg->mask)
5000 		return 0;
5001 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5002 	if (!arg->hton) {
5003 		i = 0;
5004 		end = arg->size;
5005 		sub = 0;
5006 		add = 1;
5007 	}
5008 #endif
5009 	while (i != end) {
5010 		unsigned int shift = 0;
5011 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
5012 
5013 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
5014 			if (!(arg->mask[i] & (1 << shift)))
5015 				continue;
5016 			++len;
5017 			if (!dst)
5018 				continue;
5019 			*buf &= ~(1 << shift);
5020 			*buf |= (val & 1) << shift;
5021 			val >>= 1;
5022 		}
5023 		i += add;
5024 	}
5025 	return len;
5026 }
5027 
5028 /** Compare a string with a partial one of a given length. */
5029 static int
5030 strcmp_partial(const char *full, const char *partial, size_t partial_len)
5031 {
5032 	int r = strncmp(full, partial, partial_len);
5033 
5034 	if (r)
5035 		return r;
5036 	if (strlen(full) <= partial_len)
5037 		return 0;
5038 	return full[partial_len];
5039 }
5040 
5041 /**
5042  * Parse a prefix length and generate a bit-mask.
5043  *
5044  * Last argument (ctx->args) is retrieved to determine mask size, storage
5045  * location and whether the result must use network byte ordering.
5046  */
5047 static int
5048 parse_prefix(struct context *ctx, const struct token *token,
5049 	     const char *str, unsigned int len,
5050 	     void *buf, unsigned int size)
5051 {
5052 	const struct arg *arg = pop_args(ctx);
5053 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
5054 	char *end;
5055 	uintmax_t u;
5056 	unsigned int bytes;
5057 	unsigned int extra;
5058 
5059 	(void)token;
5060 	/* Argument is expected. */
5061 	if (!arg)
5062 		return -1;
5063 	errno = 0;
5064 	u = strtoumax(str, &end, 0);
5065 	if (errno || (size_t)(end - str) != len)
5066 		goto error;
5067 	if (arg->mask) {
5068 		uintmax_t v = 0;
5069 
5070 		extra = arg_entry_bf_fill(NULL, 0, arg);
5071 		if (u > extra)
5072 			goto error;
5073 		if (!ctx->object)
5074 			return len;
5075 		extra -= u;
5076 		while (u--)
5077 			(v <<= 1, v |= 1);
5078 		v <<= extra;
5079 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
5080 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
5081 			goto error;
5082 		return len;
5083 	}
5084 	bytes = u / 8;
5085 	extra = u % 8;
5086 	size = arg->size;
5087 	if (bytes > size || bytes + !!extra > size)
5088 		goto error;
5089 	if (!ctx->object)
5090 		return len;
5091 	buf = (uint8_t *)ctx->object + arg->offset;
5092 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5093 	if (!arg->hton) {
5094 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
5095 		memset(buf, 0x00, size - bytes);
5096 		if (extra)
5097 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
5098 	} else
5099 #endif
5100 	{
5101 		memset(buf, 0xff, bytes);
5102 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
5103 		if (extra)
5104 			((uint8_t *)buf)[bytes] = conv[extra];
5105 	}
5106 	if (ctx->objmask)
5107 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5108 	return len;
5109 error:
5110 	push_args(ctx, arg);
5111 	return -1;
5112 }
5113 
5114 /** Default parsing function for token name matching. */
5115 static int
5116 parse_default(struct context *ctx, const struct token *token,
5117 	      const char *str, unsigned int len,
5118 	      void *buf, unsigned int size)
5119 {
5120 	(void)ctx;
5121 	(void)buf;
5122 	(void)size;
5123 	if (strcmp_partial(token->name, str, len))
5124 		return -1;
5125 	return len;
5126 }
5127 
5128 /** Parse flow command, initialize output buffer for subsequent tokens. */
5129 static int
5130 parse_init(struct context *ctx, const struct token *token,
5131 	   const char *str, unsigned int len,
5132 	   void *buf, unsigned int size)
5133 {
5134 	struct buffer *out = buf;
5135 
5136 	/* Token name must match. */
5137 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5138 		return -1;
5139 	/* Nothing else to do if there is no buffer. */
5140 	if (!out)
5141 		return len;
5142 	/* Make sure buffer is large enough. */
5143 	if (size < sizeof(*out))
5144 		return -1;
5145 	/* Initialize buffer. */
5146 	memset(out, 0x00, sizeof(*out));
5147 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
5148 	ctx->objdata = 0;
5149 	ctx->object = out;
5150 	ctx->objmask = NULL;
5151 	return len;
5152 }
5153 
5154 /** Parse tokens for indirect action commands. */
5155 static int
5156 parse_ia(struct context *ctx, const struct token *token,
5157 	 const char *str, unsigned int len,
5158 	 void *buf, unsigned int size)
5159 {
5160 	struct buffer *out = buf;
5161 
5162 	/* Token name must match. */
5163 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5164 		return -1;
5165 	/* Nothing else to do if there is no buffer. */
5166 	if (!out)
5167 		return len;
5168 	if (!out->command) {
5169 		if (ctx->curr != INDIRECT_ACTION)
5170 			return -1;
5171 		if (sizeof(*out) > size)
5172 			return -1;
5173 		out->command = ctx->curr;
5174 		ctx->objdata = 0;
5175 		ctx->object = out;
5176 		ctx->objmask = NULL;
5177 		out->args.vc.data = (uint8_t *)out + size;
5178 		return len;
5179 	}
5180 	switch (ctx->curr) {
5181 	case INDIRECT_ACTION_CREATE:
5182 	case INDIRECT_ACTION_UPDATE:
5183 		out->args.vc.actions =
5184 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5185 					       sizeof(double));
5186 		out->args.vc.attr.group = UINT32_MAX;
5187 		/* fallthrough */
5188 	case INDIRECT_ACTION_QUERY:
5189 		out->command = ctx->curr;
5190 		ctx->objdata = 0;
5191 		ctx->object = out;
5192 		ctx->objmask = NULL;
5193 		return len;
5194 	case INDIRECT_ACTION_EGRESS:
5195 		out->args.vc.attr.egress = 1;
5196 		return len;
5197 	case INDIRECT_ACTION_INGRESS:
5198 		out->args.vc.attr.ingress = 1;
5199 		return len;
5200 	case INDIRECT_ACTION_TRANSFER:
5201 		out->args.vc.attr.transfer = 1;
5202 		return len;
5203 	default:
5204 		return -1;
5205 	}
5206 }
5207 
5208 
5209 /** Parse tokens for indirect action destroy command. */
5210 static int
5211 parse_ia_destroy(struct context *ctx, const struct token *token,
5212 		 const char *str, unsigned int len,
5213 		 void *buf, unsigned int size)
5214 {
5215 	struct buffer *out = buf;
5216 	uint32_t *action_id;
5217 
5218 	/* Token name must match. */
5219 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5220 		return -1;
5221 	/* Nothing else to do if there is no buffer. */
5222 	if (!out)
5223 		return len;
5224 	if (!out->command || out->command == INDIRECT_ACTION) {
5225 		if (ctx->curr != INDIRECT_ACTION_DESTROY)
5226 			return -1;
5227 		if (sizeof(*out) > size)
5228 			return -1;
5229 		out->command = ctx->curr;
5230 		ctx->objdata = 0;
5231 		ctx->object = out;
5232 		ctx->objmask = NULL;
5233 		out->args.ia_destroy.action_id =
5234 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5235 					       sizeof(double));
5236 		return len;
5237 	}
5238 	action_id = out->args.ia_destroy.action_id
5239 		    + out->args.ia_destroy.action_id_n++;
5240 	if ((uint8_t *)action_id > (uint8_t *)out + size)
5241 		return -1;
5242 	ctx->objdata = 0;
5243 	ctx->object = action_id;
5244 	ctx->objmask = NULL;
5245 	return len;
5246 }
5247 
5248 /** Parse tokens for meter policy action commands. */
5249 static int
5250 parse_mp(struct context *ctx, const struct token *token,
5251 	const char *str, unsigned int len,
5252 	void *buf, unsigned int size)
5253 {
5254 	struct buffer *out = buf;
5255 
5256 	/* Token name must match. */
5257 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5258 		return -1;
5259 	/* Nothing else to do if there is no buffer. */
5260 	if (!out)
5261 		return len;
5262 	if (!out->command) {
5263 		if (ctx->curr != ITEM_POL_POLICY)
5264 			return -1;
5265 		if (sizeof(*out) > size)
5266 			return -1;
5267 		out->command = ctx->curr;
5268 		ctx->objdata = 0;
5269 		ctx->object = out;
5270 		ctx->objmask = NULL;
5271 		out->args.vc.data = (uint8_t *)out + size;
5272 		return len;
5273 	}
5274 	switch (ctx->curr) {
5275 	case ACTION_POL_G:
5276 		out->args.vc.actions =
5277 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5278 					sizeof(double));
5279 		out->command = ctx->curr;
5280 		ctx->objdata = 0;
5281 		ctx->object = out;
5282 		ctx->objmask = NULL;
5283 		return len;
5284 	default:
5285 		return -1;
5286 	}
5287 }
5288 
5289 /** Parse tokens for validate/create commands. */
5290 static int
5291 parse_vc(struct context *ctx, const struct token *token,
5292 	 const char *str, unsigned int len,
5293 	 void *buf, unsigned int size)
5294 {
5295 	struct buffer *out = buf;
5296 	uint8_t *data;
5297 	uint32_t data_size;
5298 
5299 	/* Token name must match. */
5300 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5301 		return -1;
5302 	/* Nothing else to do if there is no buffer. */
5303 	if (!out)
5304 		return len;
5305 	if (!out->command) {
5306 		if (ctx->curr != VALIDATE && ctx->curr != CREATE)
5307 			return -1;
5308 		if (sizeof(*out) > size)
5309 			return -1;
5310 		out->command = ctx->curr;
5311 		ctx->objdata = 0;
5312 		ctx->object = out;
5313 		ctx->objmask = NULL;
5314 		out->args.vc.data = (uint8_t *)out + size;
5315 		return len;
5316 	}
5317 	ctx->objdata = 0;
5318 	switch (ctx->curr) {
5319 	default:
5320 		ctx->object = &out->args.vc.attr;
5321 		break;
5322 	case VC_TUNNEL_SET:
5323 	case VC_TUNNEL_MATCH:
5324 		ctx->object = &out->args.vc.tunnel_ops;
5325 		break;
5326 	}
5327 	ctx->objmask = NULL;
5328 	switch (ctx->curr) {
5329 	case VC_GROUP:
5330 	case VC_PRIORITY:
5331 		return len;
5332 	case VC_TUNNEL_SET:
5333 		out->args.vc.tunnel_ops.enabled = 1;
5334 		out->args.vc.tunnel_ops.actions = 1;
5335 		return len;
5336 	case VC_TUNNEL_MATCH:
5337 		out->args.vc.tunnel_ops.enabled = 1;
5338 		out->args.vc.tunnel_ops.items = 1;
5339 		return len;
5340 	case VC_INGRESS:
5341 		out->args.vc.attr.ingress = 1;
5342 		return len;
5343 	case VC_EGRESS:
5344 		out->args.vc.attr.egress = 1;
5345 		return len;
5346 	case VC_TRANSFER:
5347 		out->args.vc.attr.transfer = 1;
5348 		return len;
5349 	case ITEM_PATTERN:
5350 		out->args.vc.pattern =
5351 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5352 					       sizeof(double));
5353 		ctx->object = out->args.vc.pattern;
5354 		ctx->objmask = NULL;
5355 		return len;
5356 	case ACTIONS:
5357 		out->args.vc.actions =
5358 			(void *)RTE_ALIGN_CEIL((uintptr_t)
5359 					       (out->args.vc.pattern +
5360 						out->args.vc.pattern_n),
5361 					       sizeof(double));
5362 		ctx->object = out->args.vc.actions;
5363 		ctx->objmask = NULL;
5364 		return len;
5365 	default:
5366 		if (!token->priv)
5367 			return -1;
5368 		break;
5369 	}
5370 	if (!out->args.vc.actions) {
5371 		const struct parse_item_priv *priv = token->priv;
5372 		struct rte_flow_item *item =
5373 			out->args.vc.pattern + out->args.vc.pattern_n;
5374 
5375 		data_size = priv->size * 3; /* spec, last, mask */
5376 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5377 					       (out->args.vc.data - data_size),
5378 					       sizeof(double));
5379 		if ((uint8_t *)item + sizeof(*item) > data)
5380 			return -1;
5381 		*item = (struct rte_flow_item){
5382 			.type = priv->type,
5383 		};
5384 		++out->args.vc.pattern_n;
5385 		ctx->object = item;
5386 		ctx->objmask = NULL;
5387 	} else {
5388 		const struct parse_action_priv *priv = token->priv;
5389 		struct rte_flow_action *action =
5390 			out->args.vc.actions + out->args.vc.actions_n;
5391 
5392 		data_size = priv->size; /* configuration */
5393 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
5394 					       (out->args.vc.data - data_size),
5395 					       sizeof(double));
5396 		if ((uint8_t *)action + sizeof(*action) > data)
5397 			return -1;
5398 		*action = (struct rte_flow_action){
5399 			.type = priv->type,
5400 			.conf = data_size ? data : NULL,
5401 		};
5402 		++out->args.vc.actions_n;
5403 		ctx->object = action;
5404 		ctx->objmask = NULL;
5405 	}
5406 	memset(data, 0, data_size);
5407 	out->args.vc.data = data;
5408 	ctx->objdata = data_size;
5409 	return len;
5410 }
5411 
5412 /** Parse pattern item parameter type. */
5413 static int
5414 parse_vc_spec(struct context *ctx, const struct token *token,
5415 	      const char *str, unsigned int len,
5416 	      void *buf, unsigned int size)
5417 {
5418 	struct buffer *out = buf;
5419 	struct rte_flow_item *item;
5420 	uint32_t data_size;
5421 	int index;
5422 	int objmask = 0;
5423 
5424 	(void)size;
5425 	/* Token name must match. */
5426 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5427 		return -1;
5428 	/* Parse parameter types. */
5429 	switch (ctx->curr) {
5430 		static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX);
5431 
5432 	case ITEM_PARAM_IS:
5433 		index = 0;
5434 		objmask = 1;
5435 		break;
5436 	case ITEM_PARAM_SPEC:
5437 		index = 0;
5438 		break;
5439 	case ITEM_PARAM_LAST:
5440 		index = 1;
5441 		break;
5442 	case ITEM_PARAM_PREFIX:
5443 		/* Modify next token to expect a prefix. */
5444 		if (ctx->next_num < 2)
5445 			return -1;
5446 		ctx->next[ctx->next_num - 2] = prefix;
5447 		/* Fall through. */
5448 	case ITEM_PARAM_MASK:
5449 		index = 2;
5450 		break;
5451 	default:
5452 		return -1;
5453 	}
5454 	/* Nothing else to do if there is no buffer. */
5455 	if (!out)
5456 		return len;
5457 	if (!out->args.vc.pattern_n)
5458 		return -1;
5459 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5460 	data_size = ctx->objdata / 3; /* spec, last, mask */
5461 	/* Point to selected object. */
5462 	ctx->object = out->args.vc.data + (data_size * index);
5463 	if (objmask) {
5464 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
5465 		item->mask = ctx->objmask;
5466 	} else
5467 		ctx->objmask = NULL;
5468 	/* Update relevant item pointer. */
5469 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
5470 		ctx->object;
5471 	return len;
5472 }
5473 
5474 /** Parse action configuration field. */
5475 static int
5476 parse_vc_conf(struct context *ctx, const struct token *token,
5477 	      const char *str, unsigned int len,
5478 	      void *buf, unsigned int size)
5479 {
5480 	struct buffer *out = buf;
5481 
5482 	(void)size;
5483 	/* Token name must match. */
5484 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5485 		return -1;
5486 	/* Nothing else to do if there is no buffer. */
5487 	if (!out)
5488 		return len;
5489 	/* Point to selected object. */
5490 	ctx->object = out->args.vc.data;
5491 	ctx->objmask = NULL;
5492 	return len;
5493 }
5494 
5495 /** Parse eCPRI common header type field. */
5496 static int
5497 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
5498 			 const char *str, unsigned int len,
5499 			 void *buf, unsigned int size)
5500 {
5501 	struct rte_flow_item_ecpri *ecpri;
5502 	struct rte_flow_item_ecpri *ecpri_mask;
5503 	struct rte_flow_item *item;
5504 	uint32_t data_size;
5505 	uint8_t msg_type;
5506 	struct buffer *out = buf;
5507 	const struct arg *arg;
5508 
5509 	(void)size;
5510 	/* Token name must match. */
5511 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5512 		return -1;
5513 	switch (ctx->curr) {
5514 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
5515 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
5516 		break;
5517 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
5518 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
5519 		break;
5520 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
5521 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
5522 		break;
5523 	default:
5524 		return -1;
5525 	}
5526 	if (!ctx->object)
5527 		return len;
5528 	arg = pop_args(ctx);
5529 	if (!arg)
5530 		return -1;
5531 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
5532 	ecpri->hdr.common.type = msg_type;
5533 	data_size = ctx->objdata / 3; /* spec, last, mask */
5534 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
5535 						    (data_size * 2));
5536 	ecpri_mask->hdr.common.type = 0xFF;
5537 	if (arg->hton) {
5538 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
5539 		ecpri_mask->hdr.common.u32 =
5540 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
5541 	}
5542 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
5543 	item->spec = ecpri;
5544 	item->mask = ecpri_mask;
5545 	return len;
5546 }
5547 
5548 /** Parse meter color action type. */
5549 static int
5550 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token,
5551 				const char *str, unsigned int len,
5552 				void *buf, unsigned int size)
5553 {
5554 	struct rte_flow_action *action_data;
5555 	struct rte_flow_action_meter_color *conf;
5556 	enum rte_color color;
5557 
5558 	(void)buf;
5559 	(void)size;
5560 	/* Token name must match. */
5561 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5562 		return -1;
5563 	switch (ctx->curr) {
5564 	case ACTION_METER_COLOR_GREEN:
5565 		color = RTE_COLOR_GREEN;
5566 	break;
5567 	case ACTION_METER_COLOR_YELLOW:
5568 		color = RTE_COLOR_YELLOW;
5569 	break;
5570 	case ACTION_METER_COLOR_RED:
5571 		color = RTE_COLOR_RED;
5572 	break;
5573 	default:
5574 		return -1;
5575 	}
5576 
5577 	if (!ctx->object)
5578 		return len;
5579 	action_data = ctx->object;
5580 	conf = (struct rte_flow_action_meter_color *)
5581 					(uintptr_t)(action_data->conf);
5582 	conf->color = color;
5583 	return len;
5584 }
5585 
5586 /** Parse RSS action. */
5587 static int
5588 parse_vc_action_rss(struct context *ctx, const struct token *token,
5589 		    const char *str, unsigned int len,
5590 		    void *buf, unsigned int size)
5591 {
5592 	struct buffer *out = buf;
5593 	struct rte_flow_action *action;
5594 	struct action_rss_data *action_rss_data;
5595 	unsigned int i;
5596 	int ret;
5597 
5598 	ret = parse_vc(ctx, token, str, len, buf, size);
5599 	if (ret < 0)
5600 		return ret;
5601 	/* Nothing else to do if there is no buffer. */
5602 	if (!out)
5603 		return ret;
5604 	if (!out->args.vc.actions_n)
5605 		return -1;
5606 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5607 	/* Point to selected object. */
5608 	ctx->object = out->args.vc.data;
5609 	ctx->objmask = NULL;
5610 	/* Set up default configuration. */
5611 	action_rss_data = ctx->object;
5612 	*action_rss_data = (struct action_rss_data){
5613 		.conf = (struct rte_flow_action_rss){
5614 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
5615 			.level = 0,
5616 			.types = rss_hf,
5617 			.key_len = 0,
5618 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
5619 			.key = NULL,
5620 			.queue = action_rss_data->queue,
5621 		},
5622 		.queue = { 0 },
5623 	};
5624 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
5625 		action_rss_data->queue[i] = i;
5626 	action->conf = &action_rss_data->conf;
5627 	return ret;
5628 }
5629 
5630 /**
5631  * Parse func field for RSS action.
5632  *
5633  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
5634  * ACTION_RSS_FUNC_* index that called this function.
5635  */
5636 static int
5637 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
5638 			 const char *str, unsigned int len,
5639 			 void *buf, unsigned int size)
5640 {
5641 	struct action_rss_data *action_rss_data;
5642 	enum rte_eth_hash_function func;
5643 
5644 	(void)buf;
5645 	(void)size;
5646 	/* Token name must match. */
5647 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5648 		return -1;
5649 	switch (ctx->curr) {
5650 	case ACTION_RSS_FUNC_DEFAULT:
5651 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
5652 		break;
5653 	case ACTION_RSS_FUNC_TOEPLITZ:
5654 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
5655 		break;
5656 	case ACTION_RSS_FUNC_SIMPLE_XOR:
5657 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
5658 		break;
5659 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
5660 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
5661 		break;
5662 	default:
5663 		return -1;
5664 	}
5665 	if (!ctx->object)
5666 		return len;
5667 	action_rss_data = ctx->object;
5668 	action_rss_data->conf.func = func;
5669 	return len;
5670 }
5671 
5672 /**
5673  * Parse type field for RSS action.
5674  *
5675  * Valid tokens are type field names and the "end" token.
5676  */
5677 static int
5678 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
5679 			  const char *str, unsigned int len,
5680 			  void *buf, unsigned int size)
5681 {
5682 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
5683 	struct action_rss_data *action_rss_data;
5684 	unsigned int i;
5685 
5686 	(void)token;
5687 	(void)buf;
5688 	(void)size;
5689 	if (ctx->curr != ACTION_RSS_TYPE)
5690 		return -1;
5691 	if (!(ctx->objdata >> 16) && ctx->object) {
5692 		action_rss_data = ctx->object;
5693 		action_rss_data->conf.types = 0;
5694 	}
5695 	if (!strcmp_partial("end", str, len)) {
5696 		ctx->objdata &= 0xffff;
5697 		return len;
5698 	}
5699 	for (i = 0; rss_type_table[i].str; ++i)
5700 		if (!strcmp_partial(rss_type_table[i].str, str, len))
5701 			break;
5702 	if (!rss_type_table[i].str)
5703 		return -1;
5704 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
5705 	/* Repeat token. */
5706 	if (ctx->next_num == RTE_DIM(ctx->next))
5707 		return -1;
5708 	ctx->next[ctx->next_num++] = next;
5709 	if (!ctx->object)
5710 		return len;
5711 	action_rss_data = ctx->object;
5712 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
5713 	return len;
5714 }
5715 
5716 /**
5717  * Parse queue field for RSS action.
5718  *
5719  * Valid tokens are queue indices and the "end" token.
5720  */
5721 static int
5722 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
5723 			  const char *str, unsigned int len,
5724 			  void *buf, unsigned int size)
5725 {
5726 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
5727 	struct action_rss_data *action_rss_data;
5728 	const struct arg *arg;
5729 	int ret;
5730 	int i;
5731 
5732 	(void)token;
5733 	(void)buf;
5734 	(void)size;
5735 	if (ctx->curr != ACTION_RSS_QUEUE)
5736 		return -1;
5737 	i = ctx->objdata >> 16;
5738 	if (!strcmp_partial("end", str, len)) {
5739 		ctx->objdata &= 0xffff;
5740 		goto end;
5741 	}
5742 	if (i >= ACTION_RSS_QUEUE_NUM)
5743 		return -1;
5744 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
5745 			     i * sizeof(action_rss_data->queue[i]),
5746 			     sizeof(action_rss_data->queue[i]));
5747 	if (push_args(ctx, arg))
5748 		return -1;
5749 	ret = parse_int(ctx, token, str, len, NULL, 0);
5750 	if (ret < 0) {
5751 		pop_args(ctx);
5752 		return -1;
5753 	}
5754 	++i;
5755 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
5756 	/* Repeat token. */
5757 	if (ctx->next_num == RTE_DIM(ctx->next))
5758 		return -1;
5759 	ctx->next[ctx->next_num++] = next;
5760 end:
5761 	if (!ctx->object)
5762 		return len;
5763 	action_rss_data = ctx->object;
5764 	action_rss_data->conf.queue_num = i;
5765 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
5766 	return len;
5767 }
5768 
5769 /** Setup VXLAN encap configuration. */
5770 static int
5771 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data)
5772 {
5773 	/* Set up default configuration. */
5774 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
5775 		.conf = (struct rte_flow_action_vxlan_encap){
5776 			.definition = action_vxlan_encap_data->items,
5777 		},
5778 		.items = {
5779 			{
5780 				.type = RTE_FLOW_ITEM_TYPE_ETH,
5781 				.spec = &action_vxlan_encap_data->item_eth,
5782 				.mask = &rte_flow_item_eth_mask,
5783 			},
5784 			{
5785 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
5786 				.spec = &action_vxlan_encap_data->item_vlan,
5787 				.mask = &rte_flow_item_vlan_mask,
5788 			},
5789 			{
5790 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
5791 				.spec = &action_vxlan_encap_data->item_ipv4,
5792 				.mask = &rte_flow_item_ipv4_mask,
5793 			},
5794 			{
5795 				.type = RTE_FLOW_ITEM_TYPE_UDP,
5796 				.spec = &action_vxlan_encap_data->item_udp,
5797 				.mask = &rte_flow_item_udp_mask,
5798 			},
5799 			{
5800 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
5801 				.spec = &action_vxlan_encap_data->item_vxlan,
5802 				.mask = &rte_flow_item_vxlan_mask,
5803 			},
5804 			{
5805 				.type = RTE_FLOW_ITEM_TYPE_END,
5806 			},
5807 		},
5808 		.item_eth.type = 0,
5809 		.item_vlan = {
5810 			.tci = vxlan_encap_conf.vlan_tci,
5811 			.inner_type = 0,
5812 		},
5813 		.item_ipv4.hdr = {
5814 			.src_addr = vxlan_encap_conf.ipv4_src,
5815 			.dst_addr = vxlan_encap_conf.ipv4_dst,
5816 		},
5817 		.item_udp.hdr = {
5818 			.src_port = vxlan_encap_conf.udp_src,
5819 			.dst_port = vxlan_encap_conf.udp_dst,
5820 		},
5821 		.item_vxlan.flags = 0,
5822 	};
5823 	memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
5824 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5825 	memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
5826 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5827 	if (!vxlan_encap_conf.select_ipv4) {
5828 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
5829 		       &vxlan_encap_conf.ipv6_src,
5830 		       sizeof(vxlan_encap_conf.ipv6_src));
5831 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
5832 		       &vxlan_encap_conf.ipv6_dst,
5833 		       sizeof(vxlan_encap_conf.ipv6_dst));
5834 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
5835 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
5836 			.spec = &action_vxlan_encap_data->item_ipv6,
5837 			.mask = &rte_flow_item_ipv6_mask,
5838 		};
5839 	}
5840 	if (!vxlan_encap_conf.select_vlan)
5841 		action_vxlan_encap_data->items[1].type =
5842 			RTE_FLOW_ITEM_TYPE_VOID;
5843 	if (vxlan_encap_conf.select_tos_ttl) {
5844 		if (vxlan_encap_conf.select_ipv4) {
5845 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
5846 
5847 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
5848 			       sizeof(ipv4_mask_tos));
5849 			ipv4_mask_tos.hdr.type_of_service = 0xff;
5850 			ipv4_mask_tos.hdr.time_to_live = 0xff;
5851 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
5852 					vxlan_encap_conf.ip_tos;
5853 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
5854 					vxlan_encap_conf.ip_ttl;
5855 			action_vxlan_encap_data->items[2].mask =
5856 							&ipv4_mask_tos;
5857 		} else {
5858 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
5859 
5860 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
5861 			       sizeof(ipv6_mask_tos));
5862 			ipv6_mask_tos.hdr.vtc_flow |=
5863 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
5864 			ipv6_mask_tos.hdr.hop_limits = 0xff;
5865 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
5866 				rte_cpu_to_be_32
5867 					((uint32_t)vxlan_encap_conf.ip_tos <<
5868 					 RTE_IPV6_HDR_TC_SHIFT);
5869 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
5870 					vxlan_encap_conf.ip_ttl;
5871 			action_vxlan_encap_data->items[2].mask =
5872 							&ipv6_mask_tos;
5873 		}
5874 	}
5875 	memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
5876 	       RTE_DIM(vxlan_encap_conf.vni));
5877 	return 0;
5878 }
5879 
5880 /** Parse VXLAN encap action. */
5881 static int
5882 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
5883 			    const char *str, unsigned int len,
5884 			    void *buf, unsigned int size)
5885 {
5886 	struct buffer *out = buf;
5887 	struct rte_flow_action *action;
5888 	struct action_vxlan_encap_data *action_vxlan_encap_data;
5889 	int ret;
5890 
5891 	ret = parse_vc(ctx, token, str, len, buf, size);
5892 	if (ret < 0)
5893 		return ret;
5894 	/* Nothing else to do if there is no buffer. */
5895 	if (!out)
5896 		return ret;
5897 	if (!out->args.vc.actions_n)
5898 		return -1;
5899 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5900 	/* Point to selected object. */
5901 	ctx->object = out->args.vc.data;
5902 	ctx->objmask = NULL;
5903 	action_vxlan_encap_data = ctx->object;
5904 	parse_setup_vxlan_encap_data(action_vxlan_encap_data);
5905 	action->conf = &action_vxlan_encap_data->conf;
5906 	return ret;
5907 }
5908 
5909 /** Setup NVGRE encap configuration. */
5910 static int
5911 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data)
5912 {
5913 	/* Set up default configuration. */
5914 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
5915 		.conf = (struct rte_flow_action_nvgre_encap){
5916 			.definition = action_nvgre_encap_data->items,
5917 		},
5918 		.items = {
5919 			{
5920 				.type = RTE_FLOW_ITEM_TYPE_ETH,
5921 				.spec = &action_nvgre_encap_data->item_eth,
5922 				.mask = &rte_flow_item_eth_mask,
5923 			},
5924 			{
5925 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
5926 				.spec = &action_nvgre_encap_data->item_vlan,
5927 				.mask = &rte_flow_item_vlan_mask,
5928 			},
5929 			{
5930 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
5931 				.spec = &action_nvgre_encap_data->item_ipv4,
5932 				.mask = &rte_flow_item_ipv4_mask,
5933 			},
5934 			{
5935 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
5936 				.spec = &action_nvgre_encap_data->item_nvgre,
5937 				.mask = &rte_flow_item_nvgre_mask,
5938 			},
5939 			{
5940 				.type = RTE_FLOW_ITEM_TYPE_END,
5941 			},
5942 		},
5943 		.item_eth.type = 0,
5944 		.item_vlan = {
5945 			.tci = nvgre_encap_conf.vlan_tci,
5946 			.inner_type = 0,
5947 		},
5948 		.item_ipv4.hdr = {
5949 		       .src_addr = nvgre_encap_conf.ipv4_src,
5950 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
5951 		},
5952 		.item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000),
5953 		.item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB),
5954 		.item_nvgre.flow_id = 0,
5955 	};
5956 	memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
5957 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5958 	memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
5959 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5960 	if (!nvgre_encap_conf.select_ipv4) {
5961 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
5962 		       &nvgre_encap_conf.ipv6_src,
5963 		       sizeof(nvgre_encap_conf.ipv6_src));
5964 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
5965 		       &nvgre_encap_conf.ipv6_dst,
5966 		       sizeof(nvgre_encap_conf.ipv6_dst));
5967 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
5968 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
5969 			.spec = &action_nvgre_encap_data->item_ipv6,
5970 			.mask = &rte_flow_item_ipv6_mask,
5971 		};
5972 	}
5973 	if (!nvgre_encap_conf.select_vlan)
5974 		action_nvgre_encap_data->items[1].type =
5975 			RTE_FLOW_ITEM_TYPE_VOID;
5976 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
5977 	       RTE_DIM(nvgre_encap_conf.tni));
5978 	return 0;
5979 }
5980 
5981 /** Parse NVGRE encap action. */
5982 static int
5983 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
5984 			    const char *str, unsigned int len,
5985 			    void *buf, unsigned int size)
5986 {
5987 	struct buffer *out = buf;
5988 	struct rte_flow_action *action;
5989 	struct action_nvgre_encap_data *action_nvgre_encap_data;
5990 	int ret;
5991 
5992 	ret = parse_vc(ctx, token, str, len, buf, size);
5993 	if (ret < 0)
5994 		return ret;
5995 	/* Nothing else to do if there is no buffer. */
5996 	if (!out)
5997 		return ret;
5998 	if (!out->args.vc.actions_n)
5999 		return -1;
6000 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6001 	/* Point to selected object. */
6002 	ctx->object = out->args.vc.data;
6003 	ctx->objmask = NULL;
6004 	action_nvgre_encap_data = ctx->object;
6005 	parse_setup_nvgre_encap_data(action_nvgre_encap_data);
6006 	action->conf = &action_nvgre_encap_data->conf;
6007 	return ret;
6008 }
6009 
6010 /** Parse l2 encap action. */
6011 static int
6012 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
6013 			 const char *str, unsigned int len,
6014 			 void *buf, unsigned int size)
6015 {
6016 	struct buffer *out = buf;
6017 	struct rte_flow_action *action;
6018 	struct action_raw_encap_data *action_encap_data;
6019 	struct rte_flow_item_eth eth = { .type = 0, };
6020 	struct rte_flow_item_vlan vlan = {
6021 		.tci = mplsoudp_encap_conf.vlan_tci,
6022 		.inner_type = 0,
6023 	};
6024 	uint8_t *header;
6025 	int ret;
6026 
6027 	ret = parse_vc(ctx, token, str, len, buf, size);
6028 	if (ret < 0)
6029 		return ret;
6030 	/* Nothing else to do if there is no buffer. */
6031 	if (!out)
6032 		return ret;
6033 	if (!out->args.vc.actions_n)
6034 		return -1;
6035 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6036 	/* Point to selected object. */
6037 	ctx->object = out->args.vc.data;
6038 	ctx->objmask = NULL;
6039 	/* Copy the headers to the buffer. */
6040 	action_encap_data = ctx->object;
6041 	*action_encap_data = (struct action_raw_encap_data) {
6042 		.conf = (struct rte_flow_action_raw_encap){
6043 			.data = action_encap_data->data,
6044 		},
6045 		.data = {},
6046 	};
6047 	header = action_encap_data->data;
6048 	if (l2_encap_conf.select_vlan)
6049 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6050 	else if (l2_encap_conf.select_ipv4)
6051 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6052 	else
6053 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6054 	memcpy(eth.dst.addr_bytes,
6055 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6056 	memcpy(eth.src.addr_bytes,
6057 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6058 	memcpy(header, &eth, sizeof(eth));
6059 	header += sizeof(eth);
6060 	if (l2_encap_conf.select_vlan) {
6061 		if (l2_encap_conf.select_ipv4)
6062 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6063 		else
6064 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6065 		memcpy(header, &vlan, sizeof(vlan));
6066 		header += sizeof(vlan);
6067 	}
6068 	action_encap_data->conf.size = header -
6069 		action_encap_data->data;
6070 	action->conf = &action_encap_data->conf;
6071 	return ret;
6072 }
6073 
6074 /** Parse l2 decap action. */
6075 static int
6076 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
6077 			 const char *str, unsigned int len,
6078 			 void *buf, unsigned int size)
6079 {
6080 	struct buffer *out = buf;
6081 	struct rte_flow_action *action;
6082 	struct action_raw_decap_data *action_decap_data;
6083 	struct rte_flow_item_eth eth = { .type = 0, };
6084 	struct rte_flow_item_vlan vlan = {
6085 		.tci = mplsoudp_encap_conf.vlan_tci,
6086 		.inner_type = 0,
6087 	};
6088 	uint8_t *header;
6089 	int ret;
6090 
6091 	ret = parse_vc(ctx, token, str, len, buf, size);
6092 	if (ret < 0)
6093 		return ret;
6094 	/* Nothing else to do if there is no buffer. */
6095 	if (!out)
6096 		return ret;
6097 	if (!out->args.vc.actions_n)
6098 		return -1;
6099 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6100 	/* Point to selected object. */
6101 	ctx->object = out->args.vc.data;
6102 	ctx->objmask = NULL;
6103 	/* Copy the headers to the buffer. */
6104 	action_decap_data = ctx->object;
6105 	*action_decap_data = (struct action_raw_decap_data) {
6106 		.conf = (struct rte_flow_action_raw_decap){
6107 			.data = action_decap_data->data,
6108 		},
6109 		.data = {},
6110 	};
6111 	header = action_decap_data->data;
6112 	if (l2_decap_conf.select_vlan)
6113 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6114 	memcpy(header, &eth, sizeof(eth));
6115 	header += sizeof(eth);
6116 	if (l2_decap_conf.select_vlan) {
6117 		memcpy(header, &vlan, sizeof(vlan));
6118 		header += sizeof(vlan);
6119 	}
6120 	action_decap_data->conf.size = header -
6121 		action_decap_data->data;
6122 	action->conf = &action_decap_data->conf;
6123 	return ret;
6124 }
6125 
6126 #define ETHER_TYPE_MPLS_UNICAST 0x8847
6127 
6128 /** Parse MPLSOGRE encap action. */
6129 static int
6130 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
6131 			       const char *str, unsigned int len,
6132 			       void *buf, unsigned int size)
6133 {
6134 	struct buffer *out = buf;
6135 	struct rte_flow_action *action;
6136 	struct action_raw_encap_data *action_encap_data;
6137 	struct rte_flow_item_eth eth = { .type = 0, };
6138 	struct rte_flow_item_vlan vlan = {
6139 		.tci = mplsogre_encap_conf.vlan_tci,
6140 		.inner_type = 0,
6141 	};
6142 	struct rte_flow_item_ipv4 ipv4 = {
6143 		.hdr =  {
6144 			.src_addr = mplsogre_encap_conf.ipv4_src,
6145 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
6146 			.next_proto_id = IPPROTO_GRE,
6147 			.version_ihl = RTE_IPV4_VHL_DEF,
6148 			.time_to_live = IPDEFTTL,
6149 		},
6150 	};
6151 	struct rte_flow_item_ipv6 ipv6 = {
6152 		.hdr =  {
6153 			.proto = IPPROTO_GRE,
6154 			.hop_limits = IPDEFTTL,
6155 		},
6156 	};
6157 	struct rte_flow_item_gre gre = {
6158 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6159 	};
6160 	struct rte_flow_item_mpls mpls = {
6161 		.ttl = 0,
6162 	};
6163 	uint8_t *header;
6164 	int ret;
6165 
6166 	ret = parse_vc(ctx, token, str, len, buf, size);
6167 	if (ret < 0)
6168 		return ret;
6169 	/* Nothing else to do if there is no buffer. */
6170 	if (!out)
6171 		return ret;
6172 	if (!out->args.vc.actions_n)
6173 		return -1;
6174 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6175 	/* Point to selected object. */
6176 	ctx->object = out->args.vc.data;
6177 	ctx->objmask = NULL;
6178 	/* Copy the headers to the buffer. */
6179 	action_encap_data = ctx->object;
6180 	*action_encap_data = (struct action_raw_encap_data) {
6181 		.conf = (struct rte_flow_action_raw_encap){
6182 			.data = action_encap_data->data,
6183 		},
6184 		.data = {},
6185 		.preserve = {},
6186 	};
6187 	header = action_encap_data->data;
6188 	if (mplsogre_encap_conf.select_vlan)
6189 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6190 	else if (mplsogre_encap_conf.select_ipv4)
6191 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6192 	else
6193 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6194 	memcpy(eth.dst.addr_bytes,
6195 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6196 	memcpy(eth.src.addr_bytes,
6197 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6198 	memcpy(header, &eth, sizeof(eth));
6199 	header += sizeof(eth);
6200 	if (mplsogre_encap_conf.select_vlan) {
6201 		if (mplsogre_encap_conf.select_ipv4)
6202 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6203 		else
6204 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6205 		memcpy(header, &vlan, sizeof(vlan));
6206 		header += sizeof(vlan);
6207 	}
6208 	if (mplsogre_encap_conf.select_ipv4) {
6209 		memcpy(header, &ipv4, sizeof(ipv4));
6210 		header += sizeof(ipv4);
6211 	} else {
6212 		memcpy(&ipv6.hdr.src_addr,
6213 		       &mplsogre_encap_conf.ipv6_src,
6214 		       sizeof(mplsogre_encap_conf.ipv6_src));
6215 		memcpy(&ipv6.hdr.dst_addr,
6216 		       &mplsogre_encap_conf.ipv6_dst,
6217 		       sizeof(mplsogre_encap_conf.ipv6_dst));
6218 		memcpy(header, &ipv6, sizeof(ipv6));
6219 		header += sizeof(ipv6);
6220 	}
6221 	memcpy(header, &gre, sizeof(gre));
6222 	header += sizeof(gre);
6223 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
6224 	       RTE_DIM(mplsogre_encap_conf.label));
6225 	mpls.label_tc_s[2] |= 0x1;
6226 	memcpy(header, &mpls, sizeof(mpls));
6227 	header += sizeof(mpls);
6228 	action_encap_data->conf.size = header -
6229 		action_encap_data->data;
6230 	action->conf = &action_encap_data->conf;
6231 	return ret;
6232 }
6233 
6234 /** Parse MPLSOGRE decap action. */
6235 static int
6236 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
6237 			       const char *str, unsigned int len,
6238 			       void *buf, unsigned int size)
6239 {
6240 	struct buffer *out = buf;
6241 	struct rte_flow_action *action;
6242 	struct action_raw_decap_data *action_decap_data;
6243 	struct rte_flow_item_eth eth = { .type = 0, };
6244 	struct rte_flow_item_vlan vlan = {.tci = 0};
6245 	struct rte_flow_item_ipv4 ipv4 = {
6246 		.hdr =  {
6247 			.next_proto_id = IPPROTO_GRE,
6248 		},
6249 	};
6250 	struct rte_flow_item_ipv6 ipv6 = {
6251 		.hdr =  {
6252 			.proto = IPPROTO_GRE,
6253 		},
6254 	};
6255 	struct rte_flow_item_gre gre = {
6256 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
6257 	};
6258 	struct rte_flow_item_mpls mpls;
6259 	uint8_t *header;
6260 	int ret;
6261 
6262 	ret = parse_vc(ctx, token, str, len, buf, size);
6263 	if (ret < 0)
6264 		return ret;
6265 	/* Nothing else to do if there is no buffer. */
6266 	if (!out)
6267 		return ret;
6268 	if (!out->args.vc.actions_n)
6269 		return -1;
6270 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6271 	/* Point to selected object. */
6272 	ctx->object = out->args.vc.data;
6273 	ctx->objmask = NULL;
6274 	/* Copy the headers to the buffer. */
6275 	action_decap_data = ctx->object;
6276 	*action_decap_data = (struct action_raw_decap_data) {
6277 		.conf = (struct rte_flow_action_raw_decap){
6278 			.data = action_decap_data->data,
6279 		},
6280 		.data = {},
6281 	};
6282 	header = action_decap_data->data;
6283 	if (mplsogre_decap_conf.select_vlan)
6284 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6285 	else if (mplsogre_encap_conf.select_ipv4)
6286 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6287 	else
6288 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6289 	memcpy(eth.dst.addr_bytes,
6290 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6291 	memcpy(eth.src.addr_bytes,
6292 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6293 	memcpy(header, &eth, sizeof(eth));
6294 	header += sizeof(eth);
6295 	if (mplsogre_encap_conf.select_vlan) {
6296 		if (mplsogre_encap_conf.select_ipv4)
6297 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6298 		else
6299 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6300 		memcpy(header, &vlan, sizeof(vlan));
6301 		header += sizeof(vlan);
6302 	}
6303 	if (mplsogre_encap_conf.select_ipv4) {
6304 		memcpy(header, &ipv4, sizeof(ipv4));
6305 		header += sizeof(ipv4);
6306 	} else {
6307 		memcpy(header, &ipv6, sizeof(ipv6));
6308 		header += sizeof(ipv6);
6309 	}
6310 	memcpy(header, &gre, sizeof(gre));
6311 	header += sizeof(gre);
6312 	memset(&mpls, 0, sizeof(mpls));
6313 	memcpy(header, &mpls, sizeof(mpls));
6314 	header += sizeof(mpls);
6315 	action_decap_data->conf.size = header -
6316 		action_decap_data->data;
6317 	action->conf = &action_decap_data->conf;
6318 	return ret;
6319 }
6320 
6321 /** Parse MPLSOUDP encap action. */
6322 static int
6323 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
6324 			       const char *str, unsigned int len,
6325 			       void *buf, unsigned int size)
6326 {
6327 	struct buffer *out = buf;
6328 	struct rte_flow_action *action;
6329 	struct action_raw_encap_data *action_encap_data;
6330 	struct rte_flow_item_eth eth = { .type = 0, };
6331 	struct rte_flow_item_vlan vlan = {
6332 		.tci = mplsoudp_encap_conf.vlan_tci,
6333 		.inner_type = 0,
6334 	};
6335 	struct rte_flow_item_ipv4 ipv4 = {
6336 		.hdr =  {
6337 			.src_addr = mplsoudp_encap_conf.ipv4_src,
6338 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
6339 			.next_proto_id = IPPROTO_UDP,
6340 			.version_ihl = RTE_IPV4_VHL_DEF,
6341 			.time_to_live = IPDEFTTL,
6342 		},
6343 	};
6344 	struct rte_flow_item_ipv6 ipv6 = {
6345 		.hdr =  {
6346 			.proto = IPPROTO_UDP,
6347 			.hop_limits = IPDEFTTL,
6348 		},
6349 	};
6350 	struct rte_flow_item_udp udp = {
6351 		.hdr = {
6352 			.src_port = mplsoudp_encap_conf.udp_src,
6353 			.dst_port = mplsoudp_encap_conf.udp_dst,
6354 		},
6355 	};
6356 	struct rte_flow_item_mpls mpls;
6357 	uint8_t *header;
6358 	int ret;
6359 
6360 	ret = parse_vc(ctx, token, str, len, buf, size);
6361 	if (ret < 0)
6362 		return ret;
6363 	/* Nothing else to do if there is no buffer. */
6364 	if (!out)
6365 		return ret;
6366 	if (!out->args.vc.actions_n)
6367 		return -1;
6368 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6369 	/* Point to selected object. */
6370 	ctx->object = out->args.vc.data;
6371 	ctx->objmask = NULL;
6372 	/* Copy the headers to the buffer. */
6373 	action_encap_data = ctx->object;
6374 	*action_encap_data = (struct action_raw_encap_data) {
6375 		.conf = (struct rte_flow_action_raw_encap){
6376 			.data = action_encap_data->data,
6377 		},
6378 		.data = {},
6379 		.preserve = {},
6380 	};
6381 	header = action_encap_data->data;
6382 	if (mplsoudp_encap_conf.select_vlan)
6383 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6384 	else if (mplsoudp_encap_conf.select_ipv4)
6385 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6386 	else
6387 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6388 	memcpy(eth.dst.addr_bytes,
6389 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6390 	memcpy(eth.src.addr_bytes,
6391 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6392 	memcpy(header, &eth, sizeof(eth));
6393 	header += sizeof(eth);
6394 	if (mplsoudp_encap_conf.select_vlan) {
6395 		if (mplsoudp_encap_conf.select_ipv4)
6396 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6397 		else
6398 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6399 		memcpy(header, &vlan, sizeof(vlan));
6400 		header += sizeof(vlan);
6401 	}
6402 	if (mplsoudp_encap_conf.select_ipv4) {
6403 		memcpy(header, &ipv4, sizeof(ipv4));
6404 		header += sizeof(ipv4);
6405 	} else {
6406 		memcpy(&ipv6.hdr.src_addr,
6407 		       &mplsoudp_encap_conf.ipv6_src,
6408 		       sizeof(mplsoudp_encap_conf.ipv6_src));
6409 		memcpy(&ipv6.hdr.dst_addr,
6410 		       &mplsoudp_encap_conf.ipv6_dst,
6411 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
6412 		memcpy(header, &ipv6, sizeof(ipv6));
6413 		header += sizeof(ipv6);
6414 	}
6415 	memcpy(header, &udp, sizeof(udp));
6416 	header += sizeof(udp);
6417 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
6418 	       RTE_DIM(mplsoudp_encap_conf.label));
6419 	mpls.label_tc_s[2] |= 0x1;
6420 	memcpy(header, &mpls, sizeof(mpls));
6421 	header += sizeof(mpls);
6422 	action_encap_data->conf.size = header -
6423 		action_encap_data->data;
6424 	action->conf = &action_encap_data->conf;
6425 	return ret;
6426 }
6427 
6428 /** Parse MPLSOUDP decap action. */
6429 static int
6430 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
6431 			       const char *str, unsigned int len,
6432 			       void *buf, unsigned int size)
6433 {
6434 	struct buffer *out = buf;
6435 	struct rte_flow_action *action;
6436 	struct action_raw_decap_data *action_decap_data;
6437 	struct rte_flow_item_eth eth = { .type = 0, };
6438 	struct rte_flow_item_vlan vlan = {.tci = 0};
6439 	struct rte_flow_item_ipv4 ipv4 = {
6440 		.hdr =  {
6441 			.next_proto_id = IPPROTO_UDP,
6442 		},
6443 	};
6444 	struct rte_flow_item_ipv6 ipv6 = {
6445 		.hdr =  {
6446 			.proto = IPPROTO_UDP,
6447 		},
6448 	};
6449 	struct rte_flow_item_udp udp = {
6450 		.hdr = {
6451 			.dst_port = rte_cpu_to_be_16(6635),
6452 		},
6453 	};
6454 	struct rte_flow_item_mpls mpls;
6455 	uint8_t *header;
6456 	int ret;
6457 
6458 	ret = parse_vc(ctx, token, str, len, buf, size);
6459 	if (ret < 0)
6460 		return ret;
6461 	/* Nothing else to do if there is no buffer. */
6462 	if (!out)
6463 		return ret;
6464 	if (!out->args.vc.actions_n)
6465 		return -1;
6466 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6467 	/* Point to selected object. */
6468 	ctx->object = out->args.vc.data;
6469 	ctx->objmask = NULL;
6470 	/* Copy the headers to the buffer. */
6471 	action_decap_data = ctx->object;
6472 	*action_decap_data = (struct action_raw_decap_data) {
6473 		.conf = (struct rte_flow_action_raw_decap){
6474 			.data = action_decap_data->data,
6475 		},
6476 		.data = {},
6477 	};
6478 	header = action_decap_data->data;
6479 	if (mplsoudp_decap_conf.select_vlan)
6480 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
6481 	else if (mplsoudp_encap_conf.select_ipv4)
6482 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6483 	else
6484 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6485 	memcpy(eth.dst.addr_bytes,
6486 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
6487 	memcpy(eth.src.addr_bytes,
6488 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
6489 	memcpy(header, &eth, sizeof(eth));
6490 	header += sizeof(eth);
6491 	if (mplsoudp_encap_conf.select_vlan) {
6492 		if (mplsoudp_encap_conf.select_ipv4)
6493 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
6494 		else
6495 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
6496 		memcpy(header, &vlan, sizeof(vlan));
6497 		header += sizeof(vlan);
6498 	}
6499 	if (mplsoudp_encap_conf.select_ipv4) {
6500 		memcpy(header, &ipv4, sizeof(ipv4));
6501 		header += sizeof(ipv4);
6502 	} else {
6503 		memcpy(header, &ipv6, sizeof(ipv6));
6504 		header += sizeof(ipv6);
6505 	}
6506 	memcpy(header, &udp, sizeof(udp));
6507 	header += sizeof(udp);
6508 	memset(&mpls, 0, sizeof(mpls));
6509 	memcpy(header, &mpls, sizeof(mpls));
6510 	header += sizeof(mpls);
6511 	action_decap_data->conf.size = header -
6512 		action_decap_data->data;
6513 	action->conf = &action_decap_data->conf;
6514 	return ret;
6515 }
6516 
6517 static int
6518 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
6519 				const char *str, unsigned int len, void *buf,
6520 				unsigned int size)
6521 {
6522 	struct action_raw_decap_data *action_raw_decap_data;
6523 	struct rte_flow_action *action;
6524 	const struct arg *arg;
6525 	struct buffer *out = buf;
6526 	int ret;
6527 	uint16_t idx;
6528 
6529 	RTE_SET_USED(token);
6530 	RTE_SET_USED(buf);
6531 	RTE_SET_USED(size);
6532 	arg = ARGS_ENTRY_ARB_BOUNDED
6533 		(offsetof(struct action_raw_decap_data, idx),
6534 		 sizeof(((struct action_raw_decap_data *)0)->idx),
6535 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6536 	if (push_args(ctx, arg))
6537 		return -1;
6538 	ret = parse_int(ctx, token, str, len, NULL, 0);
6539 	if (ret < 0) {
6540 		pop_args(ctx);
6541 		return -1;
6542 	}
6543 	if (!ctx->object)
6544 		return len;
6545 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6546 	action_raw_decap_data = ctx->object;
6547 	idx = action_raw_decap_data->idx;
6548 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
6549 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
6550 	action->conf = &action_raw_decap_data->conf;
6551 	return len;
6552 }
6553 
6554 
6555 static int
6556 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
6557 				const char *str, unsigned int len, void *buf,
6558 				unsigned int size)
6559 {
6560 	struct action_raw_encap_data *action_raw_encap_data;
6561 	struct rte_flow_action *action;
6562 	const struct arg *arg;
6563 	struct buffer *out = buf;
6564 	int ret;
6565 	uint16_t idx;
6566 
6567 	RTE_SET_USED(token);
6568 	RTE_SET_USED(buf);
6569 	RTE_SET_USED(size);
6570 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
6571 		return -1;
6572 	arg = ARGS_ENTRY_ARB_BOUNDED
6573 		(offsetof(struct action_raw_encap_data, idx),
6574 		 sizeof(((struct action_raw_encap_data *)0)->idx),
6575 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
6576 	if (push_args(ctx, arg))
6577 		return -1;
6578 	ret = parse_int(ctx, token, str, len, NULL, 0);
6579 	if (ret < 0) {
6580 		pop_args(ctx);
6581 		return -1;
6582 	}
6583 	if (!ctx->object)
6584 		return len;
6585 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6586 	action_raw_encap_data = ctx->object;
6587 	idx = action_raw_encap_data->idx;
6588 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
6589 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
6590 	action_raw_encap_data->conf.preserve = NULL;
6591 	action->conf = &action_raw_encap_data->conf;
6592 	return len;
6593 }
6594 
6595 static int
6596 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
6597 			  const char *str, unsigned int len, void *buf,
6598 			  unsigned int size)
6599 {
6600 	struct buffer *out = buf;
6601 	struct rte_flow_action *action;
6602 	struct action_raw_encap_data *action_raw_encap_data = NULL;
6603 	int ret;
6604 
6605 	ret = parse_vc(ctx, token, str, len, buf, size);
6606 	if (ret < 0)
6607 		return ret;
6608 	/* Nothing else to do if there is no buffer. */
6609 	if (!out)
6610 		return ret;
6611 	if (!out->args.vc.actions_n)
6612 		return -1;
6613 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6614 	/* Point to selected object. */
6615 	ctx->object = out->args.vc.data;
6616 	ctx->objmask = NULL;
6617 	/* Copy the headers to the buffer. */
6618 	action_raw_encap_data = ctx->object;
6619 	action_raw_encap_data->conf.data = raw_encap_confs[0].data;
6620 	action_raw_encap_data->conf.preserve = NULL;
6621 	action_raw_encap_data->conf.size = raw_encap_confs[0].size;
6622 	action->conf = &action_raw_encap_data->conf;
6623 	return ret;
6624 }
6625 
6626 static int
6627 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
6628 			  const char *str, unsigned int len, void *buf,
6629 			  unsigned int size)
6630 {
6631 	struct buffer *out = buf;
6632 	struct rte_flow_action *action;
6633 	struct action_raw_decap_data *action_raw_decap_data = NULL;
6634 	int ret;
6635 
6636 	ret = parse_vc(ctx, token, str, len, buf, size);
6637 	if (ret < 0)
6638 		return ret;
6639 	/* Nothing else to do if there is no buffer. */
6640 	if (!out)
6641 		return ret;
6642 	if (!out->args.vc.actions_n)
6643 		return -1;
6644 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6645 	/* Point to selected object. */
6646 	ctx->object = out->args.vc.data;
6647 	ctx->objmask = NULL;
6648 	/* Copy the headers to the buffer. */
6649 	action_raw_decap_data = ctx->object;
6650 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
6651 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
6652 	action->conf = &action_raw_decap_data->conf;
6653 	return ret;
6654 }
6655 
6656 static int
6657 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
6658 			 const char *str, unsigned int len, void *buf,
6659 			 unsigned int size)
6660 {
6661 	int ret;
6662 
6663 	ret = parse_vc(ctx, token, str, len, buf, size);
6664 	if (ret < 0)
6665 		return ret;
6666 	ret = rte_flow_dynf_metadata_register();
6667 	if (ret < 0)
6668 		return -1;
6669 	return len;
6670 }
6671 
6672 static int
6673 parse_vc_action_sample(struct context *ctx, const struct token *token,
6674 			 const char *str, unsigned int len, void *buf,
6675 			 unsigned int size)
6676 {
6677 	struct buffer *out = buf;
6678 	struct rte_flow_action *action;
6679 	struct action_sample_data *action_sample_data = NULL;
6680 	static struct rte_flow_action end_action = {
6681 		RTE_FLOW_ACTION_TYPE_END, 0
6682 	};
6683 	int ret;
6684 
6685 	ret = parse_vc(ctx, token, str, len, buf, size);
6686 	if (ret < 0)
6687 		return ret;
6688 	/* Nothing else to do if there is no buffer. */
6689 	if (!out)
6690 		return ret;
6691 	if (!out->args.vc.actions_n)
6692 		return -1;
6693 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6694 	/* Point to selected object. */
6695 	ctx->object = out->args.vc.data;
6696 	ctx->objmask = NULL;
6697 	/* Copy the headers to the buffer. */
6698 	action_sample_data = ctx->object;
6699 	action_sample_data->conf.actions = &end_action;
6700 	action->conf = &action_sample_data->conf;
6701 	return ret;
6702 }
6703 
6704 static int
6705 parse_vc_action_sample_index(struct context *ctx, const struct token *token,
6706 				const char *str, unsigned int len, void *buf,
6707 				unsigned int size)
6708 {
6709 	struct action_sample_data *action_sample_data;
6710 	struct rte_flow_action *action;
6711 	const struct arg *arg;
6712 	struct buffer *out = buf;
6713 	int ret;
6714 	uint16_t idx;
6715 
6716 	RTE_SET_USED(token);
6717 	RTE_SET_USED(buf);
6718 	RTE_SET_USED(size);
6719 	if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE)
6720 		return -1;
6721 	arg = ARGS_ENTRY_ARB_BOUNDED
6722 		(offsetof(struct action_sample_data, idx),
6723 		 sizeof(((struct action_sample_data *)0)->idx),
6724 		 0, RAW_SAMPLE_CONFS_MAX_NUM - 1);
6725 	if (push_args(ctx, arg))
6726 		return -1;
6727 	ret = parse_int(ctx, token, str, len, NULL, 0);
6728 	if (ret < 0) {
6729 		pop_args(ctx);
6730 		return -1;
6731 	}
6732 	if (!ctx->object)
6733 		return len;
6734 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
6735 	action_sample_data = ctx->object;
6736 	idx = action_sample_data->idx;
6737 	action_sample_data->conf.actions = raw_sample_confs[idx].data;
6738 	action->conf = &action_sample_data->conf;
6739 	return len;
6740 }
6741 
6742 /** Parse operation for modify_field command. */
6743 static int
6744 parse_vc_modify_field_op(struct context *ctx, const struct token *token,
6745 			 const char *str, unsigned int len, void *buf,
6746 			 unsigned int size)
6747 {
6748 	struct rte_flow_action_modify_field *action_modify_field;
6749 	unsigned int i;
6750 
6751 	(void)token;
6752 	(void)buf;
6753 	(void)size;
6754 	if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE)
6755 		return -1;
6756 	for (i = 0; modify_field_ops[i]; ++i)
6757 		if (!strcmp_partial(modify_field_ops[i], str, len))
6758 			break;
6759 	if (!modify_field_ops[i])
6760 		return -1;
6761 	if (!ctx->object)
6762 		return len;
6763 	action_modify_field = ctx->object;
6764 	action_modify_field->operation = (enum rte_flow_modify_op)i;
6765 	return len;
6766 }
6767 
6768 /** Parse id for modify_field command. */
6769 static int
6770 parse_vc_modify_field_id(struct context *ctx, const struct token *token,
6771 			 const char *str, unsigned int len, void *buf,
6772 			 unsigned int size)
6773 {
6774 	struct rte_flow_action_modify_field *action_modify_field;
6775 	unsigned int i;
6776 
6777 	(void)token;
6778 	(void)buf;
6779 	(void)size;
6780 	if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE &&
6781 		ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)
6782 		return -1;
6783 	for (i = 0; modify_field_ids[i]; ++i)
6784 		if (!strcmp_partial(modify_field_ids[i], str, len))
6785 			break;
6786 	if (!modify_field_ids[i])
6787 		return -1;
6788 	if (!ctx->object)
6789 		return len;
6790 	action_modify_field = ctx->object;
6791 	if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE)
6792 		action_modify_field->dst.field = (enum rte_flow_field_id)i;
6793 	else
6794 		action_modify_field->src.field = (enum rte_flow_field_id)i;
6795 	return len;
6796 }
6797 
6798 /** Parse the conntrack update, not a rte_flow_action. */
6799 static int
6800 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
6801 			 const char *str, unsigned int len, void *buf,
6802 			 unsigned int size)
6803 {
6804 	struct buffer *out = buf;
6805 	struct rte_flow_modify_conntrack *ct_modify = NULL;
6806 
6807 	(void)size;
6808 	if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
6809 	    ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
6810 		return -1;
6811 	/* Token name must match. */
6812 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6813 		return -1;
6814 	/* Nothing else to do if there is no buffer. */
6815 	if (!out)
6816 		return len;
6817 	ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
6818 	if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
6819 		ct_modify->new_ct.is_original_dir =
6820 				conntrack_context.is_original_dir;
6821 		ct_modify->direction = 1;
6822 	} else {
6823 		uint32_t old_dir;
6824 
6825 		old_dir = ct_modify->new_ct.is_original_dir;
6826 		memcpy(&ct_modify->new_ct, &conntrack_context,
6827 		       sizeof(conntrack_context));
6828 		ct_modify->new_ct.is_original_dir = old_dir;
6829 		ct_modify->state = 1;
6830 	}
6831 	return len;
6832 }
6833 
6834 /** Parse tokens for destroy command. */
6835 static int
6836 parse_destroy(struct context *ctx, const struct token *token,
6837 	      const char *str, unsigned int len,
6838 	      void *buf, unsigned int size)
6839 {
6840 	struct buffer *out = buf;
6841 
6842 	/* Token name must match. */
6843 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6844 		return -1;
6845 	/* Nothing else to do if there is no buffer. */
6846 	if (!out)
6847 		return len;
6848 	if (!out->command) {
6849 		if (ctx->curr != DESTROY)
6850 			return -1;
6851 		if (sizeof(*out) > size)
6852 			return -1;
6853 		out->command = ctx->curr;
6854 		ctx->objdata = 0;
6855 		ctx->object = out;
6856 		ctx->objmask = NULL;
6857 		out->args.destroy.rule =
6858 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6859 					       sizeof(double));
6860 		return len;
6861 	}
6862 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
6863 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
6864 		return -1;
6865 	ctx->objdata = 0;
6866 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
6867 	ctx->objmask = NULL;
6868 	return len;
6869 }
6870 
6871 /** Parse tokens for flush command. */
6872 static int
6873 parse_flush(struct context *ctx, const struct token *token,
6874 	    const char *str, unsigned int len,
6875 	    void *buf, unsigned int size)
6876 {
6877 	struct buffer *out = buf;
6878 
6879 	/* Token name must match. */
6880 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6881 		return -1;
6882 	/* Nothing else to do if there is no buffer. */
6883 	if (!out)
6884 		return len;
6885 	if (!out->command) {
6886 		if (ctx->curr != FLUSH)
6887 			return -1;
6888 		if (sizeof(*out) > size)
6889 			return -1;
6890 		out->command = ctx->curr;
6891 		ctx->objdata = 0;
6892 		ctx->object = out;
6893 		ctx->objmask = NULL;
6894 	}
6895 	return len;
6896 }
6897 
6898 /** Parse tokens for dump command. */
6899 static int
6900 parse_dump(struct context *ctx, const struct token *token,
6901 	    const char *str, unsigned int len,
6902 	    void *buf, unsigned int size)
6903 {
6904 	struct buffer *out = buf;
6905 
6906 	/* Token name must match. */
6907 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6908 		return -1;
6909 	/* Nothing else to do if there is no buffer. */
6910 	if (!out)
6911 		return len;
6912 	if (!out->command) {
6913 		if (ctx->curr != DUMP)
6914 			return -1;
6915 		if (sizeof(*out) > size)
6916 			return -1;
6917 		out->command = ctx->curr;
6918 		ctx->objdata = 0;
6919 		ctx->object = out;
6920 		ctx->objmask = NULL;
6921 		return len;
6922 	}
6923 	switch (ctx->curr) {
6924 	case DUMP_ALL:
6925 	case DUMP_ONE:
6926 		out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false;
6927 		out->command = ctx->curr;
6928 		ctx->objdata = 0;
6929 		ctx->object = out;
6930 		ctx->objmask = NULL;
6931 		return len;
6932 	default:
6933 		return -1;
6934 	}
6935 }
6936 
6937 /** Parse tokens for query command. */
6938 static int
6939 parse_query(struct context *ctx, const struct token *token,
6940 	    const char *str, unsigned int len,
6941 	    void *buf, unsigned int size)
6942 {
6943 	struct buffer *out = buf;
6944 
6945 	/* Token name must match. */
6946 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6947 		return -1;
6948 	/* Nothing else to do if there is no buffer. */
6949 	if (!out)
6950 		return len;
6951 	if (!out->command) {
6952 		if (ctx->curr != QUERY)
6953 			return -1;
6954 		if (sizeof(*out) > size)
6955 			return -1;
6956 		out->command = ctx->curr;
6957 		ctx->objdata = 0;
6958 		ctx->object = out;
6959 		ctx->objmask = NULL;
6960 	}
6961 	return len;
6962 }
6963 
6964 /** Parse action names. */
6965 static int
6966 parse_action(struct context *ctx, const struct token *token,
6967 	     const char *str, unsigned int len,
6968 	     void *buf, unsigned int size)
6969 {
6970 	struct buffer *out = buf;
6971 	const struct arg *arg = pop_args(ctx);
6972 	unsigned int i;
6973 
6974 	(void)size;
6975 	/* Argument is expected. */
6976 	if (!arg)
6977 		return -1;
6978 	/* Parse action name. */
6979 	for (i = 0; next_action[i]; ++i) {
6980 		const struct parse_action_priv *priv;
6981 
6982 		token = &token_list[next_action[i]];
6983 		if (strcmp_partial(token->name, str, len))
6984 			continue;
6985 		priv = token->priv;
6986 		if (!priv)
6987 			goto error;
6988 		if (out)
6989 			memcpy((uint8_t *)ctx->object + arg->offset,
6990 			       &priv->type,
6991 			       arg->size);
6992 		return len;
6993 	}
6994 error:
6995 	push_args(ctx, arg);
6996 	return -1;
6997 }
6998 
6999 /** Parse tokens for list command. */
7000 static int
7001 parse_list(struct context *ctx, const struct token *token,
7002 	   const char *str, unsigned int len,
7003 	   void *buf, unsigned int size)
7004 {
7005 	struct buffer *out = buf;
7006 
7007 	/* Token name must match. */
7008 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7009 		return -1;
7010 	/* Nothing else to do if there is no buffer. */
7011 	if (!out)
7012 		return len;
7013 	if (!out->command) {
7014 		if (ctx->curr != LIST)
7015 			return -1;
7016 		if (sizeof(*out) > size)
7017 			return -1;
7018 		out->command = ctx->curr;
7019 		ctx->objdata = 0;
7020 		ctx->object = out;
7021 		ctx->objmask = NULL;
7022 		out->args.list.group =
7023 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7024 					       sizeof(double));
7025 		return len;
7026 	}
7027 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
7028 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
7029 		return -1;
7030 	ctx->objdata = 0;
7031 	ctx->object = out->args.list.group + out->args.list.group_n++;
7032 	ctx->objmask = NULL;
7033 	return len;
7034 }
7035 
7036 /** Parse tokens for list all aged flows command. */
7037 static int
7038 parse_aged(struct context *ctx, const struct token *token,
7039 	   const char *str, unsigned int len,
7040 	   void *buf, unsigned int size)
7041 {
7042 	struct buffer *out = buf;
7043 
7044 	/* Token name must match. */
7045 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7046 		return -1;
7047 	/* Nothing else to do if there is no buffer. */
7048 	if (!out)
7049 		return len;
7050 	if (!out->command) {
7051 		if (ctx->curr != AGED)
7052 			return -1;
7053 		if (sizeof(*out) > size)
7054 			return -1;
7055 		out->command = ctx->curr;
7056 		ctx->objdata = 0;
7057 		ctx->object = out;
7058 		ctx->objmask = NULL;
7059 	}
7060 	if (ctx->curr == AGED_DESTROY)
7061 		out->args.aged.destroy = 1;
7062 	return len;
7063 }
7064 
7065 /** Parse tokens for isolate command. */
7066 static int
7067 parse_isolate(struct context *ctx, const struct token *token,
7068 	      const char *str, unsigned int len,
7069 	      void *buf, unsigned int size)
7070 {
7071 	struct buffer *out = buf;
7072 
7073 	/* Token name must match. */
7074 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7075 		return -1;
7076 	/* Nothing else to do if there is no buffer. */
7077 	if (!out)
7078 		return len;
7079 	if (!out->command) {
7080 		if (ctx->curr != ISOLATE)
7081 			return -1;
7082 		if (sizeof(*out) > size)
7083 			return -1;
7084 		out->command = ctx->curr;
7085 		ctx->objdata = 0;
7086 		ctx->object = out;
7087 		ctx->objmask = NULL;
7088 	}
7089 	return len;
7090 }
7091 
7092 static int
7093 parse_tunnel(struct context *ctx, const struct token *token,
7094 	     const char *str, unsigned int len,
7095 	     void *buf, unsigned int size)
7096 {
7097 	struct buffer *out = buf;
7098 
7099 	/* Token name must match. */
7100 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7101 		return -1;
7102 	/* Nothing else to do if there is no buffer. */
7103 	if (!out)
7104 		return len;
7105 	if (!out->command) {
7106 		if (ctx->curr != TUNNEL)
7107 			return -1;
7108 		if (sizeof(*out) > size)
7109 			return -1;
7110 		out->command = ctx->curr;
7111 		ctx->objdata = 0;
7112 		ctx->object = out;
7113 		ctx->objmask = NULL;
7114 	} else {
7115 		switch (ctx->curr) {
7116 		default:
7117 			break;
7118 		case TUNNEL_CREATE:
7119 		case TUNNEL_DESTROY:
7120 		case TUNNEL_LIST:
7121 			out->command = ctx->curr;
7122 			break;
7123 		case TUNNEL_CREATE_TYPE:
7124 		case TUNNEL_DESTROY_ID:
7125 			ctx->object = &out->args.vc.tunnel_ops;
7126 			break;
7127 		}
7128 	}
7129 
7130 	return len;
7131 }
7132 
7133 /**
7134  * Parse signed/unsigned integers 8 to 64-bit long.
7135  *
7136  * Last argument (ctx->args) is retrieved to determine integer type and
7137  * storage location.
7138  */
7139 static int
7140 parse_int(struct context *ctx, const struct token *token,
7141 	  const char *str, unsigned int len,
7142 	  void *buf, unsigned int size)
7143 {
7144 	const struct arg *arg = pop_args(ctx);
7145 	uintmax_t u;
7146 	char *end;
7147 
7148 	(void)token;
7149 	/* Argument is expected. */
7150 	if (!arg)
7151 		return -1;
7152 	errno = 0;
7153 	u = arg->sign ?
7154 		(uintmax_t)strtoimax(str, &end, 0) :
7155 		strtoumax(str, &end, 0);
7156 	if (errno || (size_t)(end - str) != len)
7157 		goto error;
7158 	if (arg->bounded &&
7159 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
7160 			    (intmax_t)u > (intmax_t)arg->max)) ||
7161 	     (!arg->sign && (u < arg->min || u > arg->max))))
7162 		goto error;
7163 	if (!ctx->object)
7164 		return len;
7165 	if (arg->mask) {
7166 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
7167 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
7168 			goto error;
7169 		return len;
7170 	}
7171 	buf = (uint8_t *)ctx->object + arg->offset;
7172 	size = arg->size;
7173 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
7174 		return -1;
7175 objmask:
7176 	switch (size) {
7177 	case sizeof(uint8_t):
7178 		*(uint8_t *)buf = u;
7179 		break;
7180 	case sizeof(uint16_t):
7181 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
7182 		break;
7183 	case sizeof(uint8_t [3]):
7184 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
7185 		if (!arg->hton) {
7186 			((uint8_t *)buf)[0] = u;
7187 			((uint8_t *)buf)[1] = u >> 8;
7188 			((uint8_t *)buf)[2] = u >> 16;
7189 			break;
7190 		}
7191 #endif
7192 		((uint8_t *)buf)[0] = u >> 16;
7193 		((uint8_t *)buf)[1] = u >> 8;
7194 		((uint8_t *)buf)[2] = u;
7195 		break;
7196 	case sizeof(uint32_t):
7197 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
7198 		break;
7199 	case sizeof(uint64_t):
7200 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
7201 		break;
7202 	default:
7203 		goto error;
7204 	}
7205 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
7206 		u = -1;
7207 		buf = (uint8_t *)ctx->objmask + arg->offset;
7208 		goto objmask;
7209 	}
7210 	return len;
7211 error:
7212 	push_args(ctx, arg);
7213 	return -1;
7214 }
7215 
7216 /**
7217  * Parse a string.
7218  *
7219  * Three arguments (ctx->args) are retrieved from the stack to store data,
7220  * its actual length and address (in that order).
7221  */
7222 static int
7223 parse_string(struct context *ctx, const struct token *token,
7224 	     const char *str, unsigned int len,
7225 	     void *buf, unsigned int size)
7226 {
7227 	const struct arg *arg_data = pop_args(ctx);
7228 	const struct arg *arg_len = pop_args(ctx);
7229 	const struct arg *arg_addr = pop_args(ctx);
7230 	char tmp[16]; /* Ought to be enough. */
7231 	int ret;
7232 
7233 	/* Arguments are expected. */
7234 	if (!arg_data)
7235 		return -1;
7236 	if (!arg_len) {
7237 		push_args(ctx, arg_data);
7238 		return -1;
7239 	}
7240 	if (!arg_addr) {
7241 		push_args(ctx, arg_len);
7242 		push_args(ctx, arg_data);
7243 		return -1;
7244 	}
7245 	size = arg_data->size;
7246 	/* Bit-mask fill is not supported. */
7247 	if (arg_data->mask || size < len)
7248 		goto error;
7249 	if (!ctx->object)
7250 		return len;
7251 	/* Let parse_int() fill length information first. */
7252 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
7253 	if (ret < 0)
7254 		goto error;
7255 	push_args(ctx, arg_len);
7256 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7257 	if (ret < 0) {
7258 		pop_args(ctx);
7259 		goto error;
7260 	}
7261 	buf = (uint8_t *)ctx->object + arg_data->offset;
7262 	/* Output buffer is not necessarily NUL-terminated. */
7263 	memcpy(buf, str, len);
7264 	memset((uint8_t *)buf + len, 0x00, size - len);
7265 	if (ctx->objmask)
7266 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7267 	/* Save address if requested. */
7268 	if (arg_addr->size) {
7269 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
7270 		       (void *[]){
7271 			(uint8_t *)ctx->object + arg_data->offset
7272 		       },
7273 		       arg_addr->size);
7274 		if (ctx->objmask)
7275 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7276 			       (void *[]){
7277 				(uint8_t *)ctx->objmask + arg_data->offset
7278 			       },
7279 			       arg_addr->size);
7280 	}
7281 	return len;
7282 error:
7283 	push_args(ctx, arg_addr);
7284 	push_args(ctx, arg_len);
7285 	push_args(ctx, arg_data);
7286 	return -1;
7287 }
7288 
7289 static int
7290 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
7291 {
7292 	char *c = NULL;
7293 	uint32_t i, len;
7294 	char tmp[3];
7295 
7296 	/* Check input parameters */
7297 	if ((src == NULL) ||
7298 		(dst == NULL) ||
7299 		(size == NULL) ||
7300 		(*size == 0))
7301 		return -1;
7302 
7303 	/* Convert chars to bytes */
7304 	for (i = 0, len = 0; i < *size; i += 2) {
7305 		snprintf(tmp, 3, "%s", src + i);
7306 		dst[len++] = strtoul(tmp, &c, 16);
7307 		if (*c != 0) {
7308 			len--;
7309 			dst[len] = 0;
7310 			*size = len;
7311 			return -1;
7312 		}
7313 	}
7314 	dst[len] = 0;
7315 	*size = len;
7316 
7317 	return 0;
7318 }
7319 
7320 static int
7321 parse_hex(struct context *ctx, const struct token *token,
7322 		const char *str, unsigned int len,
7323 		void *buf, unsigned int size)
7324 {
7325 	const struct arg *arg_data = pop_args(ctx);
7326 	const struct arg *arg_len = pop_args(ctx);
7327 	const struct arg *arg_addr = pop_args(ctx);
7328 	char tmp[16]; /* Ought to be enough. */
7329 	int ret;
7330 	unsigned int hexlen = len;
7331 	unsigned int length = 256;
7332 	uint8_t hex_tmp[length];
7333 
7334 	/* Arguments are expected. */
7335 	if (!arg_data)
7336 		return -1;
7337 	if (!arg_len) {
7338 		push_args(ctx, arg_data);
7339 		return -1;
7340 	}
7341 	if (!arg_addr) {
7342 		push_args(ctx, arg_len);
7343 		push_args(ctx, arg_data);
7344 		return -1;
7345 	}
7346 	size = arg_data->size;
7347 	/* Bit-mask fill is not supported. */
7348 	if (arg_data->mask)
7349 		goto error;
7350 	if (!ctx->object)
7351 		return len;
7352 
7353 	/* translate bytes string to array. */
7354 	if (str[0] == '0' && ((str[1] == 'x') ||
7355 			(str[1] == 'X'))) {
7356 		str += 2;
7357 		hexlen -= 2;
7358 	}
7359 	if (hexlen > length)
7360 		return -1;
7361 	ret = parse_hex_string(str, hex_tmp, &hexlen);
7362 	if (ret < 0)
7363 		goto error;
7364 	/* Let parse_int() fill length information first. */
7365 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
7366 	if (ret < 0)
7367 		goto error;
7368 	/* Save length if requested. */
7369 	if (arg_len->size) {
7370 		push_args(ctx, arg_len);
7371 		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
7372 		if (ret < 0) {
7373 			pop_args(ctx);
7374 			goto error;
7375 		}
7376 	}
7377 	buf = (uint8_t *)ctx->object + arg_data->offset;
7378 	/* Output buffer is not necessarily NUL-terminated. */
7379 	memcpy(buf, hex_tmp, hexlen);
7380 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
7381 	if (ctx->objmask)
7382 		memset((uint8_t *)ctx->objmask + arg_data->offset,
7383 					0xff, hexlen);
7384 	/* Save address if requested. */
7385 	if (arg_addr->size) {
7386 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
7387 		       (void *[]){
7388 			(uint8_t *)ctx->object + arg_data->offset
7389 		       },
7390 		       arg_addr->size);
7391 		if (ctx->objmask)
7392 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
7393 			       (void *[]){
7394 				(uint8_t *)ctx->objmask + arg_data->offset
7395 			       },
7396 			       arg_addr->size);
7397 	}
7398 	return len;
7399 error:
7400 	push_args(ctx, arg_addr);
7401 	push_args(ctx, arg_len);
7402 	push_args(ctx, arg_data);
7403 	return -1;
7404 
7405 }
7406 
7407 /**
7408  * Parse a zero-ended string.
7409  */
7410 static int
7411 parse_string0(struct context *ctx, const struct token *token __rte_unused,
7412 	     const char *str, unsigned int len,
7413 	     void *buf, unsigned int size)
7414 {
7415 	const struct arg *arg_data = pop_args(ctx);
7416 
7417 	/* Arguments are expected. */
7418 	if (!arg_data)
7419 		return -1;
7420 	size = arg_data->size;
7421 	/* Bit-mask fill is not supported. */
7422 	if (arg_data->mask || size < len + 1)
7423 		goto error;
7424 	if (!ctx->object)
7425 		return len;
7426 	buf = (uint8_t *)ctx->object + arg_data->offset;
7427 	strncpy(buf, str, len);
7428 	if (ctx->objmask)
7429 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
7430 	return len;
7431 error:
7432 	push_args(ctx, arg_data);
7433 	return -1;
7434 }
7435 
7436 /**
7437  * Parse a MAC address.
7438  *
7439  * Last argument (ctx->args) is retrieved to determine storage size and
7440  * location.
7441  */
7442 static int
7443 parse_mac_addr(struct context *ctx, const struct token *token,
7444 	       const char *str, unsigned int len,
7445 	       void *buf, unsigned int size)
7446 {
7447 	const struct arg *arg = pop_args(ctx);
7448 	struct rte_ether_addr tmp;
7449 	int ret;
7450 
7451 	(void)token;
7452 	/* Argument is expected. */
7453 	if (!arg)
7454 		return -1;
7455 	size = arg->size;
7456 	/* Bit-mask fill is not supported. */
7457 	if (arg->mask || size != sizeof(tmp))
7458 		goto error;
7459 	/* Only network endian is supported. */
7460 	if (!arg->hton)
7461 		goto error;
7462 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
7463 	if (ret < 0 || (unsigned int)ret != len)
7464 		goto error;
7465 	if (!ctx->object)
7466 		return len;
7467 	buf = (uint8_t *)ctx->object + arg->offset;
7468 	memcpy(buf, &tmp, size);
7469 	if (ctx->objmask)
7470 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7471 	return len;
7472 error:
7473 	push_args(ctx, arg);
7474 	return -1;
7475 }
7476 
7477 /**
7478  * Parse an IPv4 address.
7479  *
7480  * Last argument (ctx->args) is retrieved to determine storage size and
7481  * location.
7482  */
7483 static int
7484 parse_ipv4_addr(struct context *ctx, const struct token *token,
7485 		const char *str, unsigned int len,
7486 		void *buf, unsigned int size)
7487 {
7488 	const struct arg *arg = pop_args(ctx);
7489 	char str2[len + 1];
7490 	struct in_addr tmp;
7491 	int ret;
7492 
7493 	/* Argument is expected. */
7494 	if (!arg)
7495 		return -1;
7496 	size = arg->size;
7497 	/* Bit-mask fill is not supported. */
7498 	if (arg->mask || size != sizeof(tmp))
7499 		goto error;
7500 	/* Only network endian is supported. */
7501 	if (!arg->hton)
7502 		goto error;
7503 	memcpy(str2, str, len);
7504 	str2[len] = '\0';
7505 	ret = inet_pton(AF_INET, str2, &tmp);
7506 	if (ret != 1) {
7507 		/* Attempt integer parsing. */
7508 		push_args(ctx, arg);
7509 		return parse_int(ctx, token, str, len, buf, size);
7510 	}
7511 	if (!ctx->object)
7512 		return len;
7513 	buf = (uint8_t *)ctx->object + arg->offset;
7514 	memcpy(buf, &tmp, size);
7515 	if (ctx->objmask)
7516 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7517 	return len;
7518 error:
7519 	push_args(ctx, arg);
7520 	return -1;
7521 }
7522 
7523 /**
7524  * Parse an IPv6 address.
7525  *
7526  * Last argument (ctx->args) is retrieved to determine storage size and
7527  * location.
7528  */
7529 static int
7530 parse_ipv6_addr(struct context *ctx, const struct token *token,
7531 		const char *str, unsigned int len,
7532 		void *buf, unsigned int size)
7533 {
7534 	const struct arg *arg = pop_args(ctx);
7535 	char str2[len + 1];
7536 	struct in6_addr tmp;
7537 	int ret;
7538 
7539 	(void)token;
7540 	/* Argument is expected. */
7541 	if (!arg)
7542 		return -1;
7543 	size = arg->size;
7544 	/* Bit-mask fill is not supported. */
7545 	if (arg->mask || size != sizeof(tmp))
7546 		goto error;
7547 	/* Only network endian is supported. */
7548 	if (!arg->hton)
7549 		goto error;
7550 	memcpy(str2, str, len);
7551 	str2[len] = '\0';
7552 	ret = inet_pton(AF_INET6, str2, &tmp);
7553 	if (ret != 1)
7554 		goto error;
7555 	if (!ctx->object)
7556 		return len;
7557 	buf = (uint8_t *)ctx->object + arg->offset;
7558 	memcpy(buf, &tmp, size);
7559 	if (ctx->objmask)
7560 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
7561 	return len;
7562 error:
7563 	push_args(ctx, arg);
7564 	return -1;
7565 }
7566 
7567 /** Boolean values (even indices stand for false). */
7568 static const char *const boolean_name[] = {
7569 	"0", "1",
7570 	"false", "true",
7571 	"no", "yes",
7572 	"N", "Y",
7573 	"off", "on",
7574 	NULL,
7575 };
7576 
7577 /**
7578  * Parse a boolean value.
7579  *
7580  * Last argument (ctx->args) is retrieved to determine storage size and
7581  * location.
7582  */
7583 static int
7584 parse_boolean(struct context *ctx, const struct token *token,
7585 	      const char *str, unsigned int len,
7586 	      void *buf, unsigned int size)
7587 {
7588 	const struct arg *arg = pop_args(ctx);
7589 	unsigned int i;
7590 	int ret;
7591 
7592 	/* Argument is expected. */
7593 	if (!arg)
7594 		return -1;
7595 	for (i = 0; boolean_name[i]; ++i)
7596 		if (!strcmp_partial(boolean_name[i], str, len))
7597 			break;
7598 	/* Process token as integer. */
7599 	if (boolean_name[i])
7600 		str = i & 1 ? "1" : "0";
7601 	push_args(ctx, arg);
7602 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
7603 	return ret > 0 ? (int)len : ret;
7604 }
7605 
7606 /** Parse port and update context. */
7607 static int
7608 parse_port(struct context *ctx, const struct token *token,
7609 	   const char *str, unsigned int len,
7610 	   void *buf, unsigned int size)
7611 {
7612 	struct buffer *out = &(struct buffer){ .port = 0 };
7613 	int ret;
7614 
7615 	if (buf)
7616 		out = buf;
7617 	else {
7618 		ctx->objdata = 0;
7619 		ctx->object = out;
7620 		ctx->objmask = NULL;
7621 		size = sizeof(*out);
7622 	}
7623 	ret = parse_int(ctx, token, str, len, out, size);
7624 	if (ret >= 0)
7625 		ctx->port = out->port;
7626 	if (!buf)
7627 		ctx->object = NULL;
7628 	return ret;
7629 }
7630 
7631 static int
7632 parse_ia_id2ptr(struct context *ctx, const struct token *token,
7633 		const char *str, unsigned int len,
7634 		void *buf, unsigned int size)
7635 {
7636 	struct rte_flow_action *action = ctx->object;
7637 	uint32_t id;
7638 	int ret;
7639 
7640 	(void)buf;
7641 	(void)size;
7642 	ctx->objdata = 0;
7643 	ctx->object = &id;
7644 	ctx->objmask = NULL;
7645 	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
7646 	ctx->object = action;
7647 	if (ret != (int)len)
7648 		return ret;
7649 	/* set indirect action */
7650 	if (action) {
7651 		action->conf = port_action_handle_get_by_id(ctx->port, id);
7652 		ret = (action->conf) ? ret : -1;
7653 	}
7654 	return ret;
7655 }
7656 
7657 /** Parse set command, initialize output buffer for subsequent tokens. */
7658 static int
7659 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
7660 			  const char *str, unsigned int len,
7661 			  void *buf, unsigned int size)
7662 {
7663 	struct buffer *out = buf;
7664 
7665 	/* Token name must match. */
7666 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7667 		return -1;
7668 	/* Nothing else to do if there is no buffer. */
7669 	if (!out)
7670 		return len;
7671 	/* Make sure buffer is large enough. */
7672 	if (size < sizeof(*out))
7673 		return -1;
7674 	ctx->objdata = 0;
7675 	ctx->objmask = NULL;
7676 	ctx->object = out;
7677 	if (!out->command)
7678 		return -1;
7679 	out->command = ctx->curr;
7680 	/* For encap/decap we need is pattern */
7681 	out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7682 						       sizeof(double));
7683 	return len;
7684 }
7685 
7686 /** Parse set command, initialize output buffer for subsequent tokens. */
7687 static int
7688 parse_set_sample_action(struct context *ctx, const struct token *token,
7689 			  const char *str, unsigned int len,
7690 			  void *buf, unsigned int size)
7691 {
7692 	struct buffer *out = buf;
7693 
7694 	/* Token name must match. */
7695 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7696 		return -1;
7697 	/* Nothing else to do if there is no buffer. */
7698 	if (!out)
7699 		return len;
7700 	/* Make sure buffer is large enough. */
7701 	if (size < sizeof(*out))
7702 		return -1;
7703 	ctx->objdata = 0;
7704 	ctx->objmask = NULL;
7705 	ctx->object = out;
7706 	if (!out->command)
7707 		return -1;
7708 	out->command = ctx->curr;
7709 	/* For sampler we need is actions */
7710 	out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7711 						       sizeof(double));
7712 	return len;
7713 }
7714 
7715 /**
7716  * Parse set raw_encap/raw_decap command,
7717  * initialize output buffer for subsequent tokens.
7718  */
7719 static int
7720 parse_set_init(struct context *ctx, const struct token *token,
7721 	       const char *str, unsigned int len,
7722 	       void *buf, unsigned int size)
7723 {
7724 	struct buffer *out = buf;
7725 
7726 	/* Token name must match. */
7727 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
7728 		return -1;
7729 	/* Nothing else to do if there is no buffer. */
7730 	if (!out)
7731 		return len;
7732 	/* Make sure buffer is large enough. */
7733 	if (size < sizeof(*out))
7734 		return -1;
7735 	/* Initialize buffer. */
7736 	memset(out, 0x00, sizeof(*out));
7737 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
7738 	ctx->objdata = 0;
7739 	ctx->object = out;
7740 	ctx->objmask = NULL;
7741 	if (!out->command) {
7742 		if (ctx->curr != SET)
7743 			return -1;
7744 		if (sizeof(*out) > size)
7745 			return -1;
7746 		out->command = ctx->curr;
7747 		out->args.vc.data = (uint8_t *)out + size;
7748 		ctx->object  = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
7749 						       sizeof(double));
7750 	}
7751 	return len;
7752 }
7753 
7754 /** No completion. */
7755 static int
7756 comp_none(struct context *ctx, const struct token *token,
7757 	  unsigned int ent, char *buf, unsigned int size)
7758 {
7759 	(void)ctx;
7760 	(void)token;
7761 	(void)ent;
7762 	(void)buf;
7763 	(void)size;
7764 	return 0;
7765 }
7766 
7767 /** Complete boolean values. */
7768 static int
7769 comp_boolean(struct context *ctx, const struct token *token,
7770 	     unsigned int ent, char *buf, unsigned int size)
7771 {
7772 	unsigned int i;
7773 
7774 	(void)ctx;
7775 	(void)token;
7776 	for (i = 0; boolean_name[i]; ++i)
7777 		if (buf && i == ent)
7778 			return strlcpy(buf, boolean_name[i], size);
7779 	if (buf)
7780 		return -1;
7781 	return i;
7782 }
7783 
7784 /** Complete action names. */
7785 static int
7786 comp_action(struct context *ctx, const struct token *token,
7787 	    unsigned int ent, char *buf, unsigned int size)
7788 {
7789 	unsigned int i;
7790 
7791 	(void)ctx;
7792 	(void)token;
7793 	for (i = 0; next_action[i]; ++i)
7794 		if (buf && i == ent)
7795 			return strlcpy(buf, token_list[next_action[i]].name,
7796 				       size);
7797 	if (buf)
7798 		return -1;
7799 	return i;
7800 }
7801 
7802 /** Complete available ports. */
7803 static int
7804 comp_port(struct context *ctx, const struct token *token,
7805 	  unsigned int ent, char *buf, unsigned int size)
7806 {
7807 	unsigned int i = 0;
7808 	portid_t p;
7809 
7810 	(void)ctx;
7811 	(void)token;
7812 	RTE_ETH_FOREACH_DEV(p) {
7813 		if (buf && i == ent)
7814 			return snprintf(buf, size, "%u", p);
7815 		++i;
7816 	}
7817 	if (buf)
7818 		return -1;
7819 	return i;
7820 }
7821 
7822 /** Complete available rule IDs. */
7823 static int
7824 comp_rule_id(struct context *ctx, const struct token *token,
7825 	     unsigned int ent, char *buf, unsigned int size)
7826 {
7827 	unsigned int i = 0;
7828 	struct rte_port *port;
7829 	struct port_flow *pf;
7830 
7831 	(void)token;
7832 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
7833 	    ctx->port == (portid_t)RTE_PORT_ALL)
7834 		return -1;
7835 	port = &ports[ctx->port];
7836 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
7837 		if (buf && i == ent)
7838 			return snprintf(buf, size, "%u", pf->id);
7839 		++i;
7840 	}
7841 	if (buf)
7842 		return -1;
7843 	return i;
7844 }
7845 
7846 /** Complete type field for RSS action. */
7847 static int
7848 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
7849 			unsigned int ent, char *buf, unsigned int size)
7850 {
7851 	unsigned int i;
7852 
7853 	(void)ctx;
7854 	(void)token;
7855 	for (i = 0; rss_type_table[i].str; ++i)
7856 		;
7857 	if (!buf)
7858 		return i + 1;
7859 	if (ent < i)
7860 		return strlcpy(buf, rss_type_table[ent].str, size);
7861 	if (ent == i)
7862 		return snprintf(buf, size, "end");
7863 	return -1;
7864 }
7865 
7866 /** Complete queue field for RSS action. */
7867 static int
7868 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
7869 			 unsigned int ent, char *buf, unsigned int size)
7870 {
7871 	(void)ctx;
7872 	(void)token;
7873 	if (!buf)
7874 		return nb_rxq + 1;
7875 	if (ent < nb_rxq)
7876 		return snprintf(buf, size, "%u", ent);
7877 	if (ent == nb_rxq)
7878 		return snprintf(buf, size, "end");
7879 	return -1;
7880 }
7881 
7882 /** Complete index number for set raw_encap/raw_decap commands. */
7883 static int
7884 comp_set_raw_index(struct context *ctx, const struct token *token,
7885 		   unsigned int ent, char *buf, unsigned int size)
7886 {
7887 	uint16_t idx = 0;
7888 	uint16_t nb = 0;
7889 
7890 	RTE_SET_USED(ctx);
7891 	RTE_SET_USED(token);
7892 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
7893 		if (buf && idx == ent)
7894 			return snprintf(buf, size, "%u", idx);
7895 		++nb;
7896 	}
7897 	return nb;
7898 }
7899 
7900 /** Complete index number for set raw_encap/raw_decap commands. */
7901 static int
7902 comp_set_sample_index(struct context *ctx, const struct token *token,
7903 		   unsigned int ent, char *buf, unsigned int size)
7904 {
7905 	uint16_t idx = 0;
7906 	uint16_t nb = 0;
7907 
7908 	RTE_SET_USED(ctx);
7909 	RTE_SET_USED(token);
7910 	for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) {
7911 		if (buf && idx == ent)
7912 			return snprintf(buf, size, "%u", idx);
7913 		++nb;
7914 	}
7915 	return nb;
7916 }
7917 
7918 /** Complete operation for modify_field command. */
7919 static int
7920 comp_set_modify_field_op(struct context *ctx, const struct token *token,
7921 		   unsigned int ent, char *buf, unsigned int size)
7922 {
7923 	uint16_t idx = 0;
7924 
7925 	RTE_SET_USED(ctx);
7926 	RTE_SET_USED(token);
7927 	for (idx = 0; modify_field_ops[idx]; ++idx)
7928 		;
7929 	if (!buf)
7930 		return idx + 1;
7931 	if (ent < idx)
7932 		return strlcpy(buf, modify_field_ops[ent], size);
7933 	return -1;
7934 }
7935 
7936 /** Complete field id for modify_field command. */
7937 static int
7938 comp_set_modify_field_id(struct context *ctx, const struct token *token,
7939 		   unsigned int ent, char *buf, unsigned int size)
7940 {
7941 	uint16_t idx = 0;
7942 
7943 	RTE_SET_USED(ctx);
7944 	RTE_SET_USED(token);
7945 	for (idx = 0; modify_field_ids[idx]; ++idx)
7946 		;
7947 	if (!buf)
7948 		return idx + 1;
7949 	if (ent < idx)
7950 		return strlcpy(buf, modify_field_ids[ent], size);
7951 	return -1;
7952 }
7953 
7954 /** Internal context. */
7955 static struct context cmd_flow_context;
7956 
7957 /** Global parser instance (cmdline API). */
7958 cmdline_parse_inst_t cmd_flow;
7959 cmdline_parse_inst_t cmd_set_raw;
7960 
7961 /** Initialize context. */
7962 static void
7963 cmd_flow_context_init(struct context *ctx)
7964 {
7965 	/* A full memset() is not necessary. */
7966 	ctx->curr = ZERO;
7967 	ctx->prev = ZERO;
7968 	ctx->next_num = 0;
7969 	ctx->args_num = 0;
7970 	ctx->eol = 0;
7971 	ctx->last = 0;
7972 	ctx->port = 0;
7973 	ctx->objdata = 0;
7974 	ctx->object = NULL;
7975 	ctx->objmask = NULL;
7976 }
7977 
7978 /** Parse a token (cmdline API). */
7979 static int
7980 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
7981 	       unsigned int size)
7982 {
7983 	struct context *ctx = &cmd_flow_context;
7984 	const struct token *token;
7985 	const enum index *list;
7986 	int len;
7987 	int i;
7988 
7989 	(void)hdr;
7990 	token = &token_list[ctx->curr];
7991 	/* Check argument length. */
7992 	ctx->eol = 0;
7993 	ctx->last = 1;
7994 	for (len = 0; src[len]; ++len)
7995 		if (src[len] == '#' || isspace(src[len]))
7996 			break;
7997 	if (!len)
7998 		return -1;
7999 	/* Last argument and EOL detection. */
8000 	for (i = len; src[i]; ++i)
8001 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
8002 			break;
8003 		else if (!isspace(src[i])) {
8004 			ctx->last = 0;
8005 			break;
8006 		}
8007 	for (; src[i]; ++i)
8008 		if (src[i] == '\r' || src[i] == '\n') {
8009 			ctx->eol = 1;
8010 			break;
8011 		}
8012 	/* Initialize context if necessary. */
8013 	if (!ctx->next_num) {
8014 		if (!token->next)
8015 			return 0;
8016 		ctx->next[ctx->next_num++] = token->next[0];
8017 	}
8018 	/* Process argument through candidates. */
8019 	ctx->prev = ctx->curr;
8020 	list = ctx->next[ctx->next_num - 1];
8021 	for (i = 0; list[i]; ++i) {
8022 		const struct token *next = &token_list[list[i]];
8023 		int tmp;
8024 
8025 		ctx->curr = list[i];
8026 		if (next->call)
8027 			tmp = next->call(ctx, next, src, len, result, size);
8028 		else
8029 			tmp = parse_default(ctx, next, src, len, result, size);
8030 		if (tmp == -1 || tmp != len)
8031 			continue;
8032 		token = next;
8033 		break;
8034 	}
8035 	if (!list[i])
8036 		return -1;
8037 	--ctx->next_num;
8038 	/* Push subsequent tokens if any. */
8039 	if (token->next)
8040 		for (i = 0; token->next[i]; ++i) {
8041 			if (ctx->next_num == RTE_DIM(ctx->next))
8042 				return -1;
8043 			ctx->next[ctx->next_num++] = token->next[i];
8044 		}
8045 	/* Push arguments if any. */
8046 	if (token->args)
8047 		for (i = 0; token->args[i]; ++i) {
8048 			if (ctx->args_num == RTE_DIM(ctx->args))
8049 				return -1;
8050 			ctx->args[ctx->args_num++] = token->args[i];
8051 		}
8052 	return len;
8053 }
8054 
8055 /** Return number of completion entries (cmdline API). */
8056 static int
8057 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
8058 {
8059 	struct context *ctx = &cmd_flow_context;
8060 	const struct token *token = &token_list[ctx->curr];
8061 	const enum index *list;
8062 	int i;
8063 
8064 	(void)hdr;
8065 	/* Count number of tokens in current list. */
8066 	if (ctx->next_num)
8067 		list = ctx->next[ctx->next_num - 1];
8068 	else
8069 		list = token->next[0];
8070 	for (i = 0; list[i]; ++i)
8071 		;
8072 	if (!i)
8073 		return 0;
8074 	/*
8075 	 * If there is a single token, use its completion callback, otherwise
8076 	 * return the number of entries.
8077 	 */
8078 	token = &token_list[list[0]];
8079 	if (i == 1 && token->comp) {
8080 		/* Save index for cmd_flow_get_help(). */
8081 		ctx->prev = list[0];
8082 		return token->comp(ctx, token, 0, NULL, 0);
8083 	}
8084 	return i;
8085 }
8086 
8087 /** Return a completion entry (cmdline API). */
8088 static int
8089 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
8090 			  char *dst, unsigned int size)
8091 {
8092 	struct context *ctx = &cmd_flow_context;
8093 	const struct token *token = &token_list[ctx->curr];
8094 	const enum index *list;
8095 	int i;
8096 
8097 	(void)hdr;
8098 	/* Count number of tokens in current list. */
8099 	if (ctx->next_num)
8100 		list = ctx->next[ctx->next_num - 1];
8101 	else
8102 		list = token->next[0];
8103 	for (i = 0; list[i]; ++i)
8104 		;
8105 	if (!i)
8106 		return -1;
8107 	/* If there is a single token, use its completion callback. */
8108 	token = &token_list[list[0]];
8109 	if (i == 1 && token->comp) {
8110 		/* Save index for cmd_flow_get_help(). */
8111 		ctx->prev = list[0];
8112 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
8113 	}
8114 	/* Otherwise make sure the index is valid and use defaults. */
8115 	if (index >= i)
8116 		return -1;
8117 	token = &token_list[list[index]];
8118 	strlcpy(dst, token->name, size);
8119 	/* Save index for cmd_flow_get_help(). */
8120 	ctx->prev = list[index];
8121 	return 0;
8122 }
8123 
8124 /** Populate help strings for current token (cmdline API). */
8125 static int
8126 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
8127 {
8128 	struct context *ctx = &cmd_flow_context;
8129 	const struct token *token = &token_list[ctx->prev];
8130 
8131 	(void)hdr;
8132 	if (!size)
8133 		return -1;
8134 	/* Set token type and update global help with details. */
8135 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
8136 	if (token->help)
8137 		cmd_flow.help_str = token->help;
8138 	else
8139 		cmd_flow.help_str = token->name;
8140 	return 0;
8141 }
8142 
8143 /** Token definition template (cmdline API). */
8144 static struct cmdline_token_hdr cmd_flow_token_hdr = {
8145 	.ops = &(struct cmdline_token_ops){
8146 		.parse = cmd_flow_parse,
8147 		.complete_get_nb = cmd_flow_complete_get_nb,
8148 		.complete_get_elt = cmd_flow_complete_get_elt,
8149 		.get_help = cmd_flow_get_help,
8150 	},
8151 	.offset = 0,
8152 };
8153 
8154 /** Populate the next dynamic token. */
8155 static void
8156 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
8157 	     cmdline_parse_token_hdr_t **hdr_inst)
8158 {
8159 	struct context *ctx = &cmd_flow_context;
8160 
8161 	/* Always reinitialize context before requesting the first token. */
8162 	if (!(hdr_inst - cmd_flow.tokens))
8163 		cmd_flow_context_init(ctx);
8164 	/* Return NULL when no more tokens are expected. */
8165 	if (!ctx->next_num && ctx->curr) {
8166 		*hdr = NULL;
8167 		return;
8168 	}
8169 	/* Determine if command should end here. */
8170 	if (ctx->eol && ctx->last && ctx->next_num) {
8171 		const enum index *list = ctx->next[ctx->next_num - 1];
8172 		int i;
8173 
8174 		for (i = 0; list[i]; ++i) {
8175 			if (list[i] != END)
8176 				continue;
8177 			*hdr = NULL;
8178 			return;
8179 		}
8180 	}
8181 	*hdr = &cmd_flow_token_hdr;
8182 }
8183 
8184 /** Dispatch parsed buffer to function calls. */
8185 static void
8186 cmd_flow_parsed(const struct buffer *in)
8187 {
8188 	switch (in->command) {
8189 	case INDIRECT_ACTION_CREATE:
8190 		port_action_handle_create(
8191 				in->port, in->args.vc.attr.group,
8192 				&((const struct rte_flow_indir_action_conf) {
8193 					.ingress = in->args.vc.attr.ingress,
8194 					.egress = in->args.vc.attr.egress,
8195 					.transfer = in->args.vc.attr.transfer,
8196 				}),
8197 				in->args.vc.actions);
8198 		break;
8199 	case INDIRECT_ACTION_DESTROY:
8200 		port_action_handle_destroy(in->port,
8201 					   in->args.ia_destroy.action_id_n,
8202 					   in->args.ia_destroy.action_id);
8203 		break;
8204 	case INDIRECT_ACTION_UPDATE:
8205 		port_action_handle_update(in->port, in->args.vc.attr.group,
8206 					  in->args.vc.actions);
8207 		break;
8208 	case INDIRECT_ACTION_QUERY:
8209 		port_action_handle_query(in->port, in->args.ia.action_id);
8210 		break;
8211 	case VALIDATE:
8212 		port_flow_validate(in->port, &in->args.vc.attr,
8213 				   in->args.vc.pattern, in->args.vc.actions,
8214 				   &in->args.vc.tunnel_ops);
8215 		break;
8216 	case CREATE:
8217 		port_flow_create(in->port, &in->args.vc.attr,
8218 				 in->args.vc.pattern, in->args.vc.actions,
8219 				 &in->args.vc.tunnel_ops);
8220 		break;
8221 	case DESTROY:
8222 		port_flow_destroy(in->port, in->args.destroy.rule_n,
8223 				  in->args.destroy.rule);
8224 		break;
8225 	case FLUSH:
8226 		port_flow_flush(in->port);
8227 		break;
8228 	case DUMP_ONE:
8229 	case DUMP_ALL:
8230 		port_flow_dump(in->port, in->args.dump.mode,
8231 				in->args.dump.rule, in->args.dump.file);
8232 		break;
8233 	case QUERY:
8234 		port_flow_query(in->port, in->args.query.rule,
8235 				&in->args.query.action);
8236 		break;
8237 	case LIST:
8238 		port_flow_list(in->port, in->args.list.group_n,
8239 			       in->args.list.group);
8240 		break;
8241 	case ISOLATE:
8242 		port_flow_isolate(in->port, in->args.isolate.set);
8243 		break;
8244 	case AGED:
8245 		port_flow_aged(in->port, in->args.aged.destroy);
8246 		break;
8247 	case TUNNEL_CREATE:
8248 		port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops);
8249 		break;
8250 	case TUNNEL_DESTROY:
8251 		port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id);
8252 		break;
8253 	case TUNNEL_LIST:
8254 		port_flow_tunnel_list(in->port);
8255 		break;
8256 	case ACTION_POL_G:
8257 		port_meter_policy_add(in->port, in->args.policy.policy_id,
8258 					in->args.vc.actions);
8259 		break;
8260 	default:
8261 		break;
8262 	}
8263 }
8264 
8265 /** Token generator and output processing callback (cmdline API). */
8266 static void
8267 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
8268 {
8269 	if (cl == NULL)
8270 		cmd_flow_tok(arg0, arg2);
8271 	else
8272 		cmd_flow_parsed(arg0);
8273 }
8274 
8275 /** Global parser instance (cmdline API). */
8276 cmdline_parse_inst_t cmd_flow = {
8277 	.f = cmd_flow_cb,
8278 	.data = NULL, /**< Unused. */
8279 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8280 	.tokens = {
8281 		NULL,
8282 	}, /**< Tokens are returned by cmd_flow_tok(). */
8283 };
8284 
8285 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
8286 
8287 static void
8288 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
8289 {
8290 	struct rte_ipv4_hdr *ipv4;
8291 	struct rte_ether_hdr *eth;
8292 	struct rte_ipv6_hdr *ipv6;
8293 	struct rte_vxlan_hdr *vxlan;
8294 	struct rte_vxlan_gpe_hdr *gpe;
8295 	struct rte_flow_item_nvgre *nvgre;
8296 	uint32_t ipv6_vtc_flow;
8297 
8298 	switch (item->type) {
8299 	case RTE_FLOW_ITEM_TYPE_ETH:
8300 		eth = (struct rte_ether_hdr *)buf;
8301 		if (next_proto)
8302 			eth->ether_type = rte_cpu_to_be_16(next_proto);
8303 		break;
8304 	case RTE_FLOW_ITEM_TYPE_IPV4:
8305 		ipv4 = (struct rte_ipv4_hdr *)buf;
8306 		if (!ipv4->version_ihl)
8307 			ipv4->version_ihl = RTE_IPV4_VHL_DEF;
8308 		if (next_proto && ipv4->next_proto_id == 0)
8309 			ipv4->next_proto_id = (uint8_t)next_proto;
8310 		break;
8311 	case RTE_FLOW_ITEM_TYPE_IPV6:
8312 		ipv6 = (struct rte_ipv6_hdr *)buf;
8313 		if (next_proto && ipv6->proto == 0)
8314 			ipv6->proto = (uint8_t)next_proto;
8315 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow);
8316 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
8317 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
8318 		ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
8319 		break;
8320 	case RTE_FLOW_ITEM_TYPE_VXLAN:
8321 		vxlan = (struct rte_vxlan_hdr *)buf;
8322 		vxlan->vx_flags = 0x08;
8323 		break;
8324 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8325 		gpe = (struct rte_vxlan_gpe_hdr *)buf;
8326 		gpe->vx_flags = 0x0C;
8327 		break;
8328 	case RTE_FLOW_ITEM_TYPE_NVGRE:
8329 		nvgre = (struct rte_flow_item_nvgre *)buf;
8330 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
8331 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
8332 		break;
8333 	default:
8334 		break;
8335 	}
8336 }
8337 
8338 /** Helper of get item's default mask. */
8339 static const void *
8340 flow_item_default_mask(const struct rte_flow_item *item)
8341 {
8342 	const void *mask = NULL;
8343 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
8344 
8345 	switch (item->type) {
8346 	case RTE_FLOW_ITEM_TYPE_ANY:
8347 		mask = &rte_flow_item_any_mask;
8348 		break;
8349 	case RTE_FLOW_ITEM_TYPE_VF:
8350 		mask = &rte_flow_item_vf_mask;
8351 		break;
8352 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
8353 		mask = &rte_flow_item_port_id_mask;
8354 		break;
8355 	case RTE_FLOW_ITEM_TYPE_RAW:
8356 		mask = &rte_flow_item_raw_mask;
8357 		break;
8358 	case RTE_FLOW_ITEM_TYPE_ETH:
8359 		mask = &rte_flow_item_eth_mask;
8360 		break;
8361 	case RTE_FLOW_ITEM_TYPE_VLAN:
8362 		mask = &rte_flow_item_vlan_mask;
8363 		break;
8364 	case RTE_FLOW_ITEM_TYPE_IPV4:
8365 		mask = &rte_flow_item_ipv4_mask;
8366 		break;
8367 	case RTE_FLOW_ITEM_TYPE_IPV6:
8368 		mask = &rte_flow_item_ipv6_mask;
8369 		break;
8370 	case RTE_FLOW_ITEM_TYPE_ICMP:
8371 		mask = &rte_flow_item_icmp_mask;
8372 		break;
8373 	case RTE_FLOW_ITEM_TYPE_UDP:
8374 		mask = &rte_flow_item_udp_mask;
8375 		break;
8376 	case RTE_FLOW_ITEM_TYPE_TCP:
8377 		mask = &rte_flow_item_tcp_mask;
8378 		break;
8379 	case RTE_FLOW_ITEM_TYPE_SCTP:
8380 		mask = &rte_flow_item_sctp_mask;
8381 		break;
8382 	case RTE_FLOW_ITEM_TYPE_VXLAN:
8383 		mask = &rte_flow_item_vxlan_mask;
8384 		break;
8385 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8386 		mask = &rte_flow_item_vxlan_gpe_mask;
8387 		break;
8388 	case RTE_FLOW_ITEM_TYPE_E_TAG:
8389 		mask = &rte_flow_item_e_tag_mask;
8390 		break;
8391 	case RTE_FLOW_ITEM_TYPE_NVGRE:
8392 		mask = &rte_flow_item_nvgre_mask;
8393 		break;
8394 	case RTE_FLOW_ITEM_TYPE_MPLS:
8395 		mask = &rte_flow_item_mpls_mask;
8396 		break;
8397 	case RTE_FLOW_ITEM_TYPE_GRE:
8398 		mask = &rte_flow_item_gre_mask;
8399 		break;
8400 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8401 		mask = &gre_key_default_mask;
8402 		break;
8403 	case RTE_FLOW_ITEM_TYPE_META:
8404 		mask = &rte_flow_item_meta_mask;
8405 		break;
8406 	case RTE_FLOW_ITEM_TYPE_FUZZY:
8407 		mask = &rte_flow_item_fuzzy_mask;
8408 		break;
8409 	case RTE_FLOW_ITEM_TYPE_GTP:
8410 		mask = &rte_flow_item_gtp_mask;
8411 		break;
8412 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8413 		mask = &rte_flow_item_gtp_psc_mask;
8414 		break;
8415 	case RTE_FLOW_ITEM_TYPE_GENEVE:
8416 		mask = &rte_flow_item_geneve_mask;
8417 		break;
8418 	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8419 		mask = &rte_flow_item_geneve_opt_mask;
8420 		break;
8421 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
8422 		mask = &rte_flow_item_pppoe_proto_id_mask;
8423 		break;
8424 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8425 		mask = &rte_flow_item_l2tpv3oip_mask;
8426 		break;
8427 	case RTE_FLOW_ITEM_TYPE_ESP:
8428 		mask = &rte_flow_item_esp_mask;
8429 		break;
8430 	case RTE_FLOW_ITEM_TYPE_AH:
8431 		mask = &rte_flow_item_ah_mask;
8432 		break;
8433 	case RTE_FLOW_ITEM_TYPE_PFCP:
8434 		mask = &rte_flow_item_pfcp_mask;
8435 		break;
8436 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
8437 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
8438 		mask = &rte_flow_item_ethdev_mask;
8439 		break;
8440 	default:
8441 		break;
8442 	}
8443 	return mask;
8444 }
8445 
8446 /** Dispatch parsed buffer to function calls. */
8447 static void
8448 cmd_set_raw_parsed_sample(const struct buffer *in)
8449 {
8450 	uint32_t n = in->args.vc.actions_n;
8451 	uint32_t i = 0;
8452 	struct rte_flow_action *action = NULL;
8453 	struct rte_flow_action *data = NULL;
8454 	const struct rte_flow_action_rss *rss = NULL;
8455 	size_t size = 0;
8456 	uint16_t idx = in->port; /* We borrow port field as index */
8457 	uint32_t max_size = sizeof(struct rte_flow_action) *
8458 						ACTION_SAMPLE_ACTIONS_NUM;
8459 
8460 	RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS);
8461 	data = (struct rte_flow_action *)&raw_sample_confs[idx].data;
8462 	memset(data, 0x00, max_size);
8463 	for (; i <= n - 1; i++) {
8464 		action = in->args.vc.actions + i;
8465 		if (action->type == RTE_FLOW_ACTION_TYPE_END)
8466 			break;
8467 		switch (action->type) {
8468 		case RTE_FLOW_ACTION_TYPE_MARK:
8469 			size = sizeof(struct rte_flow_action_mark);
8470 			rte_memcpy(&sample_mark[idx],
8471 				(const void *)action->conf, size);
8472 			action->conf = &sample_mark[idx];
8473 			break;
8474 		case RTE_FLOW_ACTION_TYPE_COUNT:
8475 			size = sizeof(struct rte_flow_action_count);
8476 			rte_memcpy(&sample_count[idx],
8477 				(const void *)action->conf, size);
8478 			action->conf = &sample_count[idx];
8479 			break;
8480 		case RTE_FLOW_ACTION_TYPE_QUEUE:
8481 			size = sizeof(struct rte_flow_action_queue);
8482 			rte_memcpy(&sample_queue[idx],
8483 				(const void *)action->conf, size);
8484 			action->conf = &sample_queue[idx];
8485 			break;
8486 		case RTE_FLOW_ACTION_TYPE_RSS:
8487 			size = sizeof(struct rte_flow_action_rss);
8488 			rss = action->conf;
8489 			rte_memcpy(&sample_rss_data[idx].conf,
8490 				   (const void *)rss, size);
8491 			if (rss->key_len && rss->key) {
8492 				sample_rss_data[idx].conf.key =
8493 						sample_rss_data[idx].key;
8494 				rte_memcpy((void *)((uintptr_t)
8495 					   sample_rss_data[idx].conf.key),
8496 					   (const void *)rss->key,
8497 					   sizeof(uint8_t) * rss->key_len);
8498 			}
8499 			if (rss->queue_num && rss->queue) {
8500 				sample_rss_data[idx].conf.queue =
8501 						sample_rss_data[idx].queue;
8502 				rte_memcpy((void *)((uintptr_t)
8503 					   sample_rss_data[idx].conf.queue),
8504 					   (const void *)rss->queue,
8505 					   sizeof(uint16_t) * rss->queue_num);
8506 			}
8507 			action->conf = &sample_rss_data[idx].conf;
8508 			break;
8509 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
8510 			size = sizeof(struct rte_flow_action_raw_encap);
8511 			rte_memcpy(&sample_encap[idx],
8512 				(const void *)action->conf, size);
8513 			action->conf = &sample_encap[idx];
8514 			break;
8515 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
8516 			size = sizeof(struct rte_flow_action_port_id);
8517 			rte_memcpy(&sample_port_id[idx],
8518 				(const void *)action->conf, size);
8519 			action->conf = &sample_port_id[idx];
8520 			break;
8521 		case RTE_FLOW_ACTION_TYPE_PF:
8522 			break;
8523 		case RTE_FLOW_ACTION_TYPE_VF:
8524 			size = sizeof(struct rte_flow_action_vf);
8525 			rte_memcpy(&sample_vf[idx],
8526 					(const void *)action->conf, size);
8527 			action->conf = &sample_vf[idx];
8528 			break;
8529 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
8530 			size = sizeof(struct rte_flow_action_vxlan_encap);
8531 			parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]);
8532 			action->conf = &sample_vxlan_encap[idx].conf;
8533 			break;
8534 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
8535 			size = sizeof(struct rte_flow_action_nvgre_encap);
8536 			parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]);
8537 			action->conf = &sample_nvgre_encap[idx];
8538 			break;
8539 		default:
8540 			fprintf(stderr, "Error - Not supported action\n");
8541 			return;
8542 		}
8543 		rte_memcpy(data, action, sizeof(struct rte_flow_action));
8544 		data++;
8545 	}
8546 }
8547 
8548 /** Dispatch parsed buffer to function calls. */
8549 static void
8550 cmd_set_raw_parsed(const struct buffer *in)
8551 {
8552 	uint32_t n = in->args.vc.pattern_n;
8553 	int i = 0;
8554 	struct rte_flow_item *item = NULL;
8555 	size_t size = 0;
8556 	uint8_t *data = NULL;
8557 	uint8_t *data_tail = NULL;
8558 	size_t *total_size = NULL;
8559 	uint16_t upper_layer = 0;
8560 	uint16_t proto = 0;
8561 	uint16_t idx = in->port; /* We borrow port field as index */
8562 	int gtp_psc = -1; /* GTP PSC option index. */
8563 
8564 	if (in->command == SET_SAMPLE_ACTIONS)
8565 		return cmd_set_raw_parsed_sample(in);
8566 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
8567 		   in->command == SET_RAW_DECAP);
8568 	if (in->command == SET_RAW_ENCAP) {
8569 		total_size = &raw_encap_confs[idx].size;
8570 		data = (uint8_t *)&raw_encap_confs[idx].data;
8571 	} else {
8572 		total_size = &raw_decap_confs[idx].size;
8573 		data = (uint8_t *)&raw_decap_confs[idx].data;
8574 	}
8575 	*total_size = 0;
8576 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8577 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
8578 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
8579 	for (i = n - 1 ; i >= 0; --i) {
8580 		const struct rte_flow_item_gtp *gtp;
8581 		const struct rte_flow_item_geneve_opt *opt;
8582 
8583 		item = in->args.vc.pattern + i;
8584 		if (item->spec == NULL)
8585 			item->spec = flow_item_default_mask(item);
8586 		switch (item->type) {
8587 		case RTE_FLOW_ITEM_TYPE_ETH:
8588 			size = sizeof(struct rte_ether_hdr);
8589 			break;
8590 		case RTE_FLOW_ITEM_TYPE_VLAN:
8591 			size = sizeof(struct rte_vlan_hdr);
8592 			proto = RTE_ETHER_TYPE_VLAN;
8593 			break;
8594 		case RTE_FLOW_ITEM_TYPE_IPV4:
8595 			size = sizeof(struct rte_ipv4_hdr);
8596 			proto = RTE_ETHER_TYPE_IPV4;
8597 			break;
8598 		case RTE_FLOW_ITEM_TYPE_IPV6:
8599 			size = sizeof(struct rte_ipv6_hdr);
8600 			proto = RTE_ETHER_TYPE_IPV6;
8601 			break;
8602 		case RTE_FLOW_ITEM_TYPE_UDP:
8603 			size = sizeof(struct rte_udp_hdr);
8604 			proto = 0x11;
8605 			break;
8606 		case RTE_FLOW_ITEM_TYPE_TCP:
8607 			size = sizeof(struct rte_tcp_hdr);
8608 			proto = 0x06;
8609 			break;
8610 		case RTE_FLOW_ITEM_TYPE_VXLAN:
8611 			size = sizeof(struct rte_vxlan_hdr);
8612 			break;
8613 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
8614 			size = sizeof(struct rte_vxlan_gpe_hdr);
8615 			break;
8616 		case RTE_FLOW_ITEM_TYPE_GRE:
8617 			size = sizeof(struct rte_gre_hdr);
8618 			proto = 0x2F;
8619 			break;
8620 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
8621 			size = sizeof(rte_be32_t);
8622 			proto = 0x0;
8623 			break;
8624 		case RTE_FLOW_ITEM_TYPE_MPLS:
8625 			size = sizeof(struct rte_mpls_hdr);
8626 			proto = 0x0;
8627 			break;
8628 		case RTE_FLOW_ITEM_TYPE_NVGRE:
8629 			size = sizeof(struct rte_flow_item_nvgre);
8630 			proto = 0x2F;
8631 			break;
8632 		case RTE_FLOW_ITEM_TYPE_GENEVE:
8633 			size = sizeof(struct rte_geneve_hdr);
8634 			break;
8635 		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
8636 			opt = (const struct rte_flow_item_geneve_opt *)
8637 								item->spec;
8638 			size = offsetof(struct rte_flow_item_geneve_opt, data);
8639 			if (opt->option_len && opt->data) {
8640 				*total_size += opt->option_len *
8641 					       sizeof(uint32_t);
8642 				rte_memcpy(data_tail - (*total_size),
8643 					   opt->data,
8644 					   opt->option_len * sizeof(uint32_t));
8645 			}
8646 			break;
8647 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
8648 			size = sizeof(rte_be32_t);
8649 			proto = 0x73;
8650 			break;
8651 		case RTE_FLOW_ITEM_TYPE_ESP:
8652 			size = sizeof(struct rte_esp_hdr);
8653 			proto = 0x32;
8654 			break;
8655 		case RTE_FLOW_ITEM_TYPE_AH:
8656 			size = sizeof(struct rte_flow_item_ah);
8657 			proto = 0x33;
8658 			break;
8659 		case RTE_FLOW_ITEM_TYPE_GTP:
8660 			if (gtp_psc < 0) {
8661 				size = sizeof(struct rte_gtp_hdr);
8662 				break;
8663 			}
8664 			if (gtp_psc != i + 1) {
8665 				fprintf(stderr,
8666 					"Error - GTP PSC does not follow GTP\n");
8667 				goto error;
8668 			}
8669 			gtp = item->spec;
8670 			if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
8671 				/* Only E flag should be set. */
8672 				fprintf(stderr,
8673 					"Error - GTP unsupported flags\n");
8674 				goto error;
8675 			} else {
8676 				struct rte_gtp_hdr_ext_word ext_word = {
8677 					.next_ext = 0x85
8678 				};
8679 
8680 				/* We have to add GTP header extra word. */
8681 				*total_size += sizeof(ext_word);
8682 				rte_memcpy(data_tail - (*total_size),
8683 					   &ext_word, sizeof(ext_word));
8684 			}
8685 			size = sizeof(struct rte_gtp_hdr);
8686 			break;
8687 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
8688 			if (gtp_psc >= 0) {
8689 				fprintf(stderr,
8690 					"Error - Multiple GTP PSC items\n");
8691 				goto error;
8692 			} else {
8693 				const struct rte_flow_item_gtp_psc
8694 					*opt = item->spec;
8695 				struct {
8696 					uint8_t len;
8697 					uint8_t pdu_type:4;
8698 					uint8_t qfi:6;
8699 					uint8_t next;
8700 				} psc;
8701 				psc.len = sizeof(psc);
8702 				psc.pdu_type = opt->hdr.type;
8703 				psc.qfi = opt->hdr.qfi;
8704 				psc.next = 0;
8705 				*total_size += sizeof(psc);
8706 				rte_memcpy(data_tail - (*total_size),
8707 					   &psc, sizeof(psc));
8708 				gtp_psc = i;
8709 				size = 0;
8710 			}
8711 			break;
8712 		case RTE_FLOW_ITEM_TYPE_PFCP:
8713 			size = sizeof(struct rte_flow_item_pfcp);
8714 			break;
8715 		default:
8716 			fprintf(stderr, "Error - Not supported item\n");
8717 			goto error;
8718 		}
8719 		*total_size += size;
8720 		rte_memcpy(data_tail - (*total_size), item->spec, size);
8721 		/* update some fields which cannot be set by cmdline */
8722 		update_fields((data_tail - (*total_size)), item,
8723 			      upper_layer);
8724 		upper_layer = proto;
8725 	}
8726 	if (verbose_level & 0x1)
8727 		printf("total data size is %zu\n", (*total_size));
8728 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
8729 	memmove(data, (data_tail - (*total_size)), *total_size);
8730 	return;
8731 
8732 error:
8733 	*total_size = 0;
8734 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
8735 }
8736 
8737 /** Populate help strings for current token (cmdline API). */
8738 static int
8739 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
8740 		     unsigned int size)
8741 {
8742 	struct context *ctx = &cmd_flow_context;
8743 	const struct token *token = &token_list[ctx->prev];
8744 
8745 	(void)hdr;
8746 	if (!size)
8747 		return -1;
8748 	/* Set token type and update global help with details. */
8749 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
8750 	if (token->help)
8751 		cmd_set_raw.help_str = token->help;
8752 	else
8753 		cmd_set_raw.help_str = token->name;
8754 	return 0;
8755 }
8756 
8757 /** Token definition template (cmdline API). */
8758 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
8759 	.ops = &(struct cmdline_token_ops){
8760 		.parse = cmd_flow_parse,
8761 		.complete_get_nb = cmd_flow_complete_get_nb,
8762 		.complete_get_elt = cmd_flow_complete_get_elt,
8763 		.get_help = cmd_set_raw_get_help,
8764 	},
8765 	.offset = 0,
8766 };
8767 
8768 /** Populate the next dynamic token. */
8769 static void
8770 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
8771 	     cmdline_parse_token_hdr_t **hdr_inst)
8772 {
8773 	struct context *ctx = &cmd_flow_context;
8774 
8775 	/* Always reinitialize context before requesting the first token. */
8776 	if (!(hdr_inst - cmd_set_raw.tokens)) {
8777 		cmd_flow_context_init(ctx);
8778 		ctx->curr = START_SET;
8779 	}
8780 	/* Return NULL when no more tokens are expected. */
8781 	if (!ctx->next_num && (ctx->curr != START_SET)) {
8782 		*hdr = NULL;
8783 		return;
8784 	}
8785 	/* Determine if command should end here. */
8786 	if (ctx->eol && ctx->last && ctx->next_num) {
8787 		const enum index *list = ctx->next[ctx->next_num - 1];
8788 		int i;
8789 
8790 		for (i = 0; list[i]; ++i) {
8791 			if (list[i] != END)
8792 				continue;
8793 			*hdr = NULL;
8794 			return;
8795 		}
8796 	}
8797 	*hdr = &cmd_set_raw_token_hdr;
8798 }
8799 
8800 /** Token generator and output processing callback (cmdline API). */
8801 static void
8802 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
8803 {
8804 	if (cl == NULL)
8805 		cmd_set_raw_tok(arg0, arg2);
8806 	else
8807 		cmd_set_raw_parsed(arg0);
8808 }
8809 
8810 /** Global parser instance (cmdline API). */
8811 cmdline_parse_inst_t cmd_set_raw = {
8812 	.f = cmd_set_raw_cb,
8813 	.data = NULL, /**< Unused. */
8814 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
8815 	.tokens = {
8816 		NULL,
8817 	}, /**< Tokens are returned by cmd_flow_tok(). */
8818 };
8819 
8820 /* *** display raw_encap/raw_decap buf */
8821 struct cmd_show_set_raw_result {
8822 	cmdline_fixed_string_t cmd_show;
8823 	cmdline_fixed_string_t cmd_what;
8824 	cmdline_fixed_string_t cmd_all;
8825 	uint16_t cmd_index;
8826 };
8827 
8828 static void
8829 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
8830 {
8831 	struct cmd_show_set_raw_result *res = parsed_result;
8832 	uint16_t index = res->cmd_index;
8833 	uint8_t all = 0;
8834 	uint8_t *raw_data = NULL;
8835 	size_t raw_size = 0;
8836 	char title[16] = {0};
8837 
8838 	RTE_SET_USED(cl);
8839 	RTE_SET_USED(data);
8840 	if (!strcmp(res->cmd_all, "all")) {
8841 		all = 1;
8842 		index = 0;
8843 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
8844 		fprintf(stderr, "index should be 0-%u\n",
8845 			RAW_ENCAP_CONFS_MAX_NUM - 1);
8846 		return;
8847 	}
8848 	do {
8849 		if (!strcmp(res->cmd_what, "raw_encap")) {
8850 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
8851 			raw_size = raw_encap_confs[index].size;
8852 			snprintf(title, 16, "\nindex: %u", index);
8853 			rte_hexdump(stdout, title, raw_data, raw_size);
8854 		} else {
8855 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
8856 			raw_size = raw_decap_confs[index].size;
8857 			snprintf(title, 16, "\nindex: %u", index);
8858 			rte_hexdump(stdout, title, raw_data, raw_size);
8859 		}
8860 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
8861 }
8862 
8863 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
8864 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8865 			cmd_show, "show");
8866 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
8867 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8868 			cmd_what, "raw_encap#raw_decap");
8869 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
8870 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
8871 			cmd_index, RTE_UINT16);
8872 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
8873 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
8874 			cmd_all, "all");
8875 cmdline_parse_inst_t cmd_show_set_raw = {
8876 	.f = cmd_show_set_raw_parsed,
8877 	.data = NULL,
8878 	.help_str = "show <raw_encap|raw_decap> <index>",
8879 	.tokens = {
8880 		(void *)&cmd_show_set_raw_cmd_show,
8881 		(void *)&cmd_show_set_raw_cmd_what,
8882 		(void *)&cmd_show_set_raw_cmd_index,
8883 		NULL,
8884 	},
8885 };
8886 cmdline_parse_inst_t cmd_show_set_raw_all = {
8887 	.f = cmd_show_set_raw_parsed,
8888 	.data = NULL,
8889 	.help_str = "show <raw_encap|raw_decap> all",
8890 	.tokens = {
8891 		(void *)&cmd_show_set_raw_cmd_show,
8892 		(void *)&cmd_show_set_raw_cmd_what,
8893 		(void *)&cmd_show_set_raw_cmd_all,
8894 		NULL,
8895 	},
8896 };
8897