xref: /dpdk/app/test-pmd/cmdline_flow.c (revision f5057be340e44f3edc0fe90fa875eb89a4c49b4f)
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 #include <arpa/inet.h>
14 #include <sys/socket.h>
15 
16 #include <rte_string_fns.h>
17 #include <rte_common.h>
18 #include <rte_ethdev.h>
19 #include <rte_byteorder.h>
20 #include <cmdline_parse.h>
21 #include <cmdline_parse_etheraddr.h>
22 #include <cmdline_parse_string.h>
23 #include <cmdline_parse_num.h>
24 #include <rte_flow.h>
25 #include <rte_hexdump.h>
26 
27 #include "testpmd.h"
28 
29 /** Parser token indices. */
30 enum index {
31 	/* Special tokens. */
32 	ZERO = 0,
33 	END,
34 	START_SET,
35 	END_SET,
36 
37 	/* Common tokens. */
38 	INTEGER,
39 	UNSIGNED,
40 	PREFIX,
41 	BOOLEAN,
42 	STRING,
43 	HEX,
44 	FILE_PATH,
45 	MAC_ADDR,
46 	IPV4_ADDR,
47 	IPV6_ADDR,
48 	RULE_ID,
49 	PORT_ID,
50 	GROUP_ID,
51 	PRIORITY_LEVEL,
52 
53 	/* Top-level command. */
54 	SET,
55 	/* Sub-leve commands. */
56 	SET_RAW_ENCAP,
57 	SET_RAW_DECAP,
58 	SET_RAW_INDEX,
59 
60 	/* Top-level command. */
61 	FLOW,
62 	/* Sub-level commands. */
63 	VALIDATE,
64 	CREATE,
65 	DESTROY,
66 	FLUSH,
67 	DUMP,
68 	QUERY,
69 	LIST,
70 	AGED,
71 	ISOLATE,
72 
73 	/* Destroy arguments. */
74 	DESTROY_RULE,
75 
76 	/* Query arguments. */
77 	QUERY_ACTION,
78 
79 	/* List arguments. */
80 	LIST_GROUP,
81 
82 	/* Destroy aged flow arguments. */
83 	AGED_DESTROY,
84 
85 	/* Validate/create arguments. */
86 	GROUP,
87 	PRIORITY,
88 	INGRESS,
89 	EGRESS,
90 	TRANSFER,
91 
92 	/* Validate/create pattern. */
93 	PATTERN,
94 	ITEM_PARAM_IS,
95 	ITEM_PARAM_SPEC,
96 	ITEM_PARAM_LAST,
97 	ITEM_PARAM_MASK,
98 	ITEM_PARAM_PREFIX,
99 	ITEM_NEXT,
100 	ITEM_END,
101 	ITEM_VOID,
102 	ITEM_INVERT,
103 	ITEM_ANY,
104 	ITEM_ANY_NUM,
105 	ITEM_PF,
106 	ITEM_VF,
107 	ITEM_VF_ID,
108 	ITEM_PHY_PORT,
109 	ITEM_PHY_PORT_INDEX,
110 	ITEM_PORT_ID,
111 	ITEM_PORT_ID_ID,
112 	ITEM_MARK,
113 	ITEM_MARK_ID,
114 	ITEM_RAW,
115 	ITEM_RAW_RELATIVE,
116 	ITEM_RAW_SEARCH,
117 	ITEM_RAW_OFFSET,
118 	ITEM_RAW_LIMIT,
119 	ITEM_RAW_PATTERN,
120 	ITEM_ETH,
121 	ITEM_ETH_DST,
122 	ITEM_ETH_SRC,
123 	ITEM_ETH_TYPE,
124 	ITEM_VLAN,
125 	ITEM_VLAN_TCI,
126 	ITEM_VLAN_PCP,
127 	ITEM_VLAN_DEI,
128 	ITEM_VLAN_VID,
129 	ITEM_VLAN_INNER_TYPE,
130 	ITEM_IPV4,
131 	ITEM_IPV4_TOS,
132 	ITEM_IPV4_TTL,
133 	ITEM_IPV4_PROTO,
134 	ITEM_IPV4_SRC,
135 	ITEM_IPV4_DST,
136 	ITEM_IPV6,
137 	ITEM_IPV6_TC,
138 	ITEM_IPV6_FLOW,
139 	ITEM_IPV6_PROTO,
140 	ITEM_IPV6_HOP,
141 	ITEM_IPV6_SRC,
142 	ITEM_IPV6_DST,
143 	ITEM_ICMP,
144 	ITEM_ICMP_TYPE,
145 	ITEM_ICMP_CODE,
146 	ITEM_ICMP_IDENT,
147 	ITEM_ICMP_SEQ,
148 	ITEM_UDP,
149 	ITEM_UDP_SRC,
150 	ITEM_UDP_DST,
151 	ITEM_TCP,
152 	ITEM_TCP_SRC,
153 	ITEM_TCP_DST,
154 	ITEM_TCP_FLAGS,
155 	ITEM_SCTP,
156 	ITEM_SCTP_SRC,
157 	ITEM_SCTP_DST,
158 	ITEM_SCTP_TAG,
159 	ITEM_SCTP_CKSUM,
160 	ITEM_VXLAN,
161 	ITEM_VXLAN_VNI,
162 	ITEM_E_TAG,
163 	ITEM_E_TAG_GRP_ECID_B,
164 	ITEM_NVGRE,
165 	ITEM_NVGRE_TNI,
166 	ITEM_MPLS,
167 	ITEM_MPLS_LABEL,
168 	ITEM_MPLS_TC,
169 	ITEM_MPLS_S,
170 	ITEM_GRE,
171 	ITEM_GRE_PROTO,
172 	ITEM_GRE_C_RSVD0_VER,
173 	ITEM_GRE_C_BIT,
174 	ITEM_GRE_K_BIT,
175 	ITEM_GRE_S_BIT,
176 	ITEM_FUZZY,
177 	ITEM_FUZZY_THRESH,
178 	ITEM_GTP,
179 	ITEM_GTP_FLAGS,
180 	ITEM_GTP_MSG_TYPE,
181 	ITEM_GTP_TEID,
182 	ITEM_GTPC,
183 	ITEM_GTPU,
184 	ITEM_GENEVE,
185 	ITEM_GENEVE_VNI,
186 	ITEM_GENEVE_PROTO,
187 	ITEM_VXLAN_GPE,
188 	ITEM_VXLAN_GPE_VNI,
189 	ITEM_ARP_ETH_IPV4,
190 	ITEM_ARP_ETH_IPV4_SHA,
191 	ITEM_ARP_ETH_IPV4_SPA,
192 	ITEM_ARP_ETH_IPV4_THA,
193 	ITEM_ARP_ETH_IPV4_TPA,
194 	ITEM_IPV6_EXT,
195 	ITEM_IPV6_EXT_NEXT_HDR,
196 	ITEM_ICMP6,
197 	ITEM_ICMP6_TYPE,
198 	ITEM_ICMP6_CODE,
199 	ITEM_ICMP6_ND_NS,
200 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
201 	ITEM_ICMP6_ND_NA,
202 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
203 	ITEM_ICMP6_ND_OPT,
204 	ITEM_ICMP6_ND_OPT_TYPE,
205 	ITEM_ICMP6_ND_OPT_SLA_ETH,
206 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
207 	ITEM_ICMP6_ND_OPT_TLA_ETH,
208 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
209 	ITEM_META,
210 	ITEM_META_DATA,
211 	ITEM_GRE_KEY,
212 	ITEM_GRE_KEY_VALUE,
213 	ITEM_GTP_PSC,
214 	ITEM_GTP_PSC_QFI,
215 	ITEM_GTP_PSC_PDU_T,
216 	ITEM_PPPOES,
217 	ITEM_PPPOED,
218 	ITEM_PPPOE_SEID,
219 	ITEM_PPPOE_PROTO_ID,
220 	ITEM_HIGIG2,
221 	ITEM_HIGIG2_CLASSIFICATION,
222 	ITEM_HIGIG2_VID,
223 	ITEM_TAG,
224 	ITEM_TAG_DATA,
225 	ITEM_TAG_INDEX,
226 	ITEM_L2TPV3OIP,
227 	ITEM_L2TPV3OIP_SESSION_ID,
228 	ITEM_ESP,
229 	ITEM_ESP_SPI,
230 	ITEM_AH,
231 	ITEM_AH_SPI,
232 	ITEM_PFCP,
233 	ITEM_PFCP_S_FIELD,
234 	ITEM_PFCP_SEID,
235 	ITEM_ECPRI,
236 	ITEM_ECPRI_COMMON,
237 	ITEM_ECPRI_COMMON_TYPE,
238 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
239 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
240 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
241 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
242 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
243 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
244 
245 	/* Validate/create actions. */
246 	ACTIONS,
247 	ACTION_NEXT,
248 	ACTION_END,
249 	ACTION_VOID,
250 	ACTION_PASSTHRU,
251 	ACTION_JUMP,
252 	ACTION_JUMP_GROUP,
253 	ACTION_MARK,
254 	ACTION_MARK_ID,
255 	ACTION_FLAG,
256 	ACTION_QUEUE,
257 	ACTION_QUEUE_INDEX,
258 	ACTION_DROP,
259 	ACTION_COUNT,
260 	ACTION_COUNT_SHARED,
261 	ACTION_COUNT_ID,
262 	ACTION_RSS,
263 	ACTION_RSS_FUNC,
264 	ACTION_RSS_LEVEL,
265 	ACTION_RSS_FUNC_DEFAULT,
266 	ACTION_RSS_FUNC_TOEPLITZ,
267 	ACTION_RSS_FUNC_SIMPLE_XOR,
268 	ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
269 	ACTION_RSS_TYPES,
270 	ACTION_RSS_TYPE,
271 	ACTION_RSS_KEY,
272 	ACTION_RSS_KEY_LEN,
273 	ACTION_RSS_QUEUES,
274 	ACTION_RSS_QUEUE,
275 	ACTION_PF,
276 	ACTION_VF,
277 	ACTION_VF_ORIGINAL,
278 	ACTION_VF_ID,
279 	ACTION_PHY_PORT,
280 	ACTION_PHY_PORT_ORIGINAL,
281 	ACTION_PHY_PORT_INDEX,
282 	ACTION_PORT_ID,
283 	ACTION_PORT_ID_ORIGINAL,
284 	ACTION_PORT_ID_ID,
285 	ACTION_METER,
286 	ACTION_METER_ID,
287 	ACTION_OF_SET_MPLS_TTL,
288 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
289 	ACTION_OF_DEC_MPLS_TTL,
290 	ACTION_OF_SET_NW_TTL,
291 	ACTION_OF_SET_NW_TTL_NW_TTL,
292 	ACTION_OF_DEC_NW_TTL,
293 	ACTION_OF_COPY_TTL_OUT,
294 	ACTION_OF_COPY_TTL_IN,
295 	ACTION_OF_POP_VLAN,
296 	ACTION_OF_PUSH_VLAN,
297 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
298 	ACTION_OF_SET_VLAN_VID,
299 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
300 	ACTION_OF_SET_VLAN_PCP,
301 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
302 	ACTION_OF_POP_MPLS,
303 	ACTION_OF_POP_MPLS_ETHERTYPE,
304 	ACTION_OF_PUSH_MPLS,
305 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
306 	ACTION_VXLAN_ENCAP,
307 	ACTION_VXLAN_DECAP,
308 	ACTION_NVGRE_ENCAP,
309 	ACTION_NVGRE_DECAP,
310 	ACTION_L2_ENCAP,
311 	ACTION_L2_DECAP,
312 	ACTION_MPLSOGRE_ENCAP,
313 	ACTION_MPLSOGRE_DECAP,
314 	ACTION_MPLSOUDP_ENCAP,
315 	ACTION_MPLSOUDP_DECAP,
316 	ACTION_SET_IPV4_SRC,
317 	ACTION_SET_IPV4_SRC_IPV4_SRC,
318 	ACTION_SET_IPV4_DST,
319 	ACTION_SET_IPV4_DST_IPV4_DST,
320 	ACTION_SET_IPV6_SRC,
321 	ACTION_SET_IPV6_SRC_IPV6_SRC,
322 	ACTION_SET_IPV6_DST,
323 	ACTION_SET_IPV6_DST_IPV6_DST,
324 	ACTION_SET_TP_SRC,
325 	ACTION_SET_TP_SRC_TP_SRC,
326 	ACTION_SET_TP_DST,
327 	ACTION_SET_TP_DST_TP_DST,
328 	ACTION_MAC_SWAP,
329 	ACTION_DEC_TTL,
330 	ACTION_SET_TTL,
331 	ACTION_SET_TTL_TTL,
332 	ACTION_SET_MAC_SRC,
333 	ACTION_SET_MAC_SRC_MAC_SRC,
334 	ACTION_SET_MAC_DST,
335 	ACTION_SET_MAC_DST_MAC_DST,
336 	ACTION_INC_TCP_SEQ,
337 	ACTION_INC_TCP_SEQ_VALUE,
338 	ACTION_DEC_TCP_SEQ,
339 	ACTION_DEC_TCP_SEQ_VALUE,
340 	ACTION_INC_TCP_ACK,
341 	ACTION_INC_TCP_ACK_VALUE,
342 	ACTION_DEC_TCP_ACK,
343 	ACTION_DEC_TCP_ACK_VALUE,
344 	ACTION_RAW_ENCAP,
345 	ACTION_RAW_DECAP,
346 	ACTION_RAW_ENCAP_INDEX,
347 	ACTION_RAW_ENCAP_INDEX_VALUE,
348 	ACTION_RAW_DECAP_INDEX,
349 	ACTION_RAW_DECAP_INDEX_VALUE,
350 	ACTION_SET_TAG,
351 	ACTION_SET_TAG_DATA,
352 	ACTION_SET_TAG_INDEX,
353 	ACTION_SET_TAG_MASK,
354 	ACTION_SET_META,
355 	ACTION_SET_META_DATA,
356 	ACTION_SET_META_MASK,
357 	ACTION_SET_IPV4_DSCP,
358 	ACTION_SET_IPV4_DSCP_VALUE,
359 	ACTION_SET_IPV6_DSCP,
360 	ACTION_SET_IPV6_DSCP_VALUE,
361 	ACTION_AGE,
362 	ACTION_AGE_TIMEOUT,
363 };
364 
365 /** Maximum size for pattern in struct rte_flow_item_raw. */
366 #define ITEM_RAW_PATTERN_SIZE 40
367 
368 /** Storage size for struct rte_flow_item_raw including pattern. */
369 #define ITEM_RAW_SIZE \
370 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
371 
372 /** Maximum number of queue indices in struct rte_flow_action_rss. */
373 #define ACTION_RSS_QUEUE_NUM 128
374 
375 /** Storage for struct rte_flow_action_rss including external data. */
376 struct action_rss_data {
377 	struct rte_flow_action_rss conf;
378 	uint8_t key[RSS_HASH_KEY_LENGTH];
379 	uint16_t queue[ACTION_RSS_QUEUE_NUM];
380 };
381 
382 /** Maximum data size in struct rte_flow_action_raw_encap. */
383 #define ACTION_RAW_ENCAP_MAX_DATA 128
384 #define RAW_ENCAP_CONFS_MAX_NUM 8
385 
386 /** Storage for struct rte_flow_action_raw_encap. */
387 struct raw_encap_conf {
388 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
389 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
390 	size_t size;
391 };
392 
393 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
394 
395 /** Storage for struct rte_flow_action_raw_encap including external data. */
396 struct action_raw_encap_data {
397 	struct rte_flow_action_raw_encap conf;
398 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
399 	uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
400 	uint16_t idx;
401 };
402 
403 /** Storage for struct rte_flow_action_raw_decap. */
404 struct raw_decap_conf {
405 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
406 	size_t size;
407 };
408 
409 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
410 
411 /** Storage for struct rte_flow_action_raw_decap including external data. */
412 struct action_raw_decap_data {
413 	struct rte_flow_action_raw_decap conf;
414 	uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
415 	uint16_t idx;
416 };
417 
418 struct vxlan_encap_conf vxlan_encap_conf = {
419 	.select_ipv4 = 1,
420 	.select_vlan = 0,
421 	.select_tos_ttl = 0,
422 	.vni = "\x00\x00\x00",
423 	.udp_src = 0,
424 	.udp_dst = RTE_BE16(4789),
425 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
426 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
427 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
428 		"\x00\x00\x00\x00\x00\x00\x00\x01",
429 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
430 		"\x00\x00\x00\x00\x00\x00\x11\x11",
431 	.vlan_tci = 0,
432 	.ip_tos = 0,
433 	.ip_ttl = 255,
434 	.eth_src = "\x00\x00\x00\x00\x00\x00",
435 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
436 };
437 
438 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
439 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
440 
441 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
442 struct action_vxlan_encap_data {
443 	struct rte_flow_action_vxlan_encap conf;
444 	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
445 	struct rte_flow_item_eth item_eth;
446 	struct rte_flow_item_vlan item_vlan;
447 	union {
448 		struct rte_flow_item_ipv4 item_ipv4;
449 		struct rte_flow_item_ipv6 item_ipv6;
450 	};
451 	struct rte_flow_item_udp item_udp;
452 	struct rte_flow_item_vxlan item_vxlan;
453 };
454 
455 struct nvgre_encap_conf nvgre_encap_conf = {
456 	.select_ipv4 = 1,
457 	.select_vlan = 0,
458 	.tni = "\x00\x00\x00",
459 	.ipv4_src = RTE_IPV4(127, 0, 0, 1),
460 	.ipv4_dst = RTE_IPV4(255, 255, 255, 255),
461 	.ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
462 		"\x00\x00\x00\x00\x00\x00\x00\x01",
463 	.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
464 		"\x00\x00\x00\x00\x00\x00\x11\x11",
465 	.vlan_tci = 0,
466 	.eth_src = "\x00\x00\x00\x00\x00\x00",
467 	.eth_dst = "\xff\xff\xff\xff\xff\xff",
468 };
469 
470 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
471 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
472 
473 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
474 struct action_nvgre_encap_data {
475 	struct rte_flow_action_nvgre_encap conf;
476 	struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
477 	struct rte_flow_item_eth item_eth;
478 	struct rte_flow_item_vlan item_vlan;
479 	union {
480 		struct rte_flow_item_ipv4 item_ipv4;
481 		struct rte_flow_item_ipv6 item_ipv6;
482 	};
483 	struct rte_flow_item_nvgre item_nvgre;
484 };
485 
486 struct l2_encap_conf l2_encap_conf;
487 
488 struct l2_decap_conf l2_decap_conf;
489 
490 struct mplsogre_encap_conf mplsogre_encap_conf;
491 
492 struct mplsogre_decap_conf mplsogre_decap_conf;
493 
494 struct mplsoudp_encap_conf mplsoudp_encap_conf;
495 
496 struct mplsoudp_decap_conf mplsoudp_decap_conf;
497 
498 /** Maximum number of subsequent tokens and arguments on the stack. */
499 #define CTX_STACK_SIZE 16
500 
501 /** Parser context. */
502 struct context {
503 	/** Stack of subsequent token lists to process. */
504 	const enum index *next[CTX_STACK_SIZE];
505 	/** Arguments for stacked tokens. */
506 	const void *args[CTX_STACK_SIZE];
507 	enum index curr; /**< Current token index. */
508 	enum index prev; /**< Index of the last token seen. */
509 	int next_num; /**< Number of entries in next[]. */
510 	int args_num; /**< Number of entries in args[]. */
511 	uint32_t eol:1; /**< EOL has been detected. */
512 	uint32_t last:1; /**< No more arguments. */
513 	portid_t port; /**< Current port ID (for completions). */
514 	uint32_t objdata; /**< Object-specific data. */
515 	void *object; /**< Address of current object for relative offsets. */
516 	void *objmask; /**< Object a full mask must be written to. */
517 };
518 
519 /** Token argument. */
520 struct arg {
521 	uint32_t hton:1; /**< Use network byte ordering. */
522 	uint32_t sign:1; /**< Value is signed. */
523 	uint32_t bounded:1; /**< Value is bounded. */
524 	uintmax_t min; /**< Minimum value if bounded. */
525 	uintmax_t max; /**< Maximum value if bounded. */
526 	uint32_t offset; /**< Relative offset from ctx->object. */
527 	uint32_t size; /**< Field size. */
528 	const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
529 };
530 
531 /** Parser token definition. */
532 struct token {
533 	/** Type displayed during completion (defaults to "TOKEN"). */
534 	const char *type;
535 	/** Help displayed during completion (defaults to token name). */
536 	const char *help;
537 	/** Private data used by parser functions. */
538 	const void *priv;
539 	/**
540 	 * Lists of subsequent tokens to push on the stack. Each call to the
541 	 * parser consumes the last entry of that stack.
542 	 */
543 	const enum index *const *next;
544 	/** Arguments stack for subsequent tokens that need them. */
545 	const struct arg *const *args;
546 	/**
547 	 * Token-processing callback, returns -1 in case of error, the
548 	 * length of the matched string otherwise. If NULL, attempts to
549 	 * match the token name.
550 	 *
551 	 * If buf is not NULL, the result should be stored in it according
552 	 * to context. An error is returned if not large enough.
553 	 */
554 	int (*call)(struct context *ctx, const struct token *token,
555 		    const char *str, unsigned int len,
556 		    void *buf, unsigned int size);
557 	/**
558 	 * Callback that provides possible values for this token, used for
559 	 * completion. Returns -1 in case of error, the number of possible
560 	 * values otherwise. If NULL, the token name is used.
561 	 *
562 	 * If buf is not NULL, entry index ent is written to buf and the
563 	 * full length of the entry is returned (same behavior as
564 	 * snprintf()).
565 	 */
566 	int (*comp)(struct context *ctx, const struct token *token,
567 		    unsigned int ent, char *buf, unsigned int size);
568 	/** Mandatory token name, no default value. */
569 	const char *name;
570 };
571 
572 /** Static initializer for the next field. */
573 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
574 
575 /** Static initializer for a NEXT() entry. */
576 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
577 
578 /** Static initializer for the args field. */
579 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
580 
581 /** Static initializer for ARGS() to target a field. */
582 #define ARGS_ENTRY(s, f) \
583 	(&(const struct arg){ \
584 		.offset = offsetof(s, f), \
585 		.size = sizeof(((s *)0)->f), \
586 	})
587 
588 /** Static initializer for ARGS() to target a bit-field. */
589 #define ARGS_ENTRY_BF(s, f, b) \
590 	(&(const struct arg){ \
591 		.size = sizeof(s), \
592 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
593 	})
594 
595 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
596 #define ARGS_ENTRY_MASK(s, f, m) \
597 	(&(const struct arg){ \
598 		.offset = offsetof(s, f), \
599 		.size = sizeof(((s *)0)->f), \
600 		.mask = (const void *)(m), \
601 	})
602 
603 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
604 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
605 	(&(const struct arg){ \
606 		.hton = 1, \
607 		.offset = offsetof(s, f), \
608 		.size = sizeof(((s *)0)->f), \
609 		.mask = (const void *)(m), \
610 	})
611 
612 /** Static initializer for ARGS() to target a pointer. */
613 #define ARGS_ENTRY_PTR(s, f) \
614 	(&(const struct arg){ \
615 		.size = sizeof(*((s *)0)->f), \
616 	})
617 
618 /** Static initializer for ARGS() with arbitrary offset and size. */
619 #define ARGS_ENTRY_ARB(o, s) \
620 	(&(const struct arg){ \
621 		.offset = (o), \
622 		.size = (s), \
623 	})
624 
625 /** Same as ARGS_ENTRY_ARB() with bounded values. */
626 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
627 	(&(const struct arg){ \
628 		.bounded = 1, \
629 		.min = (i), \
630 		.max = (a), \
631 		.offset = (o), \
632 		.size = (s), \
633 	})
634 
635 /** Same as ARGS_ENTRY() using network byte ordering. */
636 #define ARGS_ENTRY_HTON(s, f) \
637 	(&(const struct arg){ \
638 		.hton = 1, \
639 		.offset = offsetof(s, f), \
640 		.size = sizeof(((s *)0)->f), \
641 	})
642 
643 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
644 #define ARG_ENTRY_HTON(s) \
645 	(&(const struct arg){ \
646 		.hton = 1, \
647 		.offset = 0, \
648 		.size = sizeof(s), \
649 	})
650 
651 /** Parser output buffer layout expected by cmd_flow_parsed(). */
652 struct buffer {
653 	enum index command; /**< Flow command. */
654 	portid_t port; /**< Affected port ID. */
655 	union {
656 		struct {
657 			struct rte_flow_attr attr;
658 			struct rte_flow_item *pattern;
659 			struct rte_flow_action *actions;
660 			uint32_t pattern_n;
661 			uint32_t actions_n;
662 			uint8_t *data;
663 		} vc; /**< Validate/create arguments. */
664 		struct {
665 			uint32_t *rule;
666 			uint32_t rule_n;
667 		} destroy; /**< Destroy arguments. */
668 		struct {
669 			char file[128];
670 		} dump; /**< Dump arguments. */
671 		struct {
672 			uint32_t rule;
673 			struct rte_flow_action action;
674 		} query; /**< Query arguments. */
675 		struct {
676 			uint32_t *group;
677 			uint32_t group_n;
678 		} list; /**< List arguments. */
679 		struct {
680 			int set;
681 		} isolate; /**< Isolated mode arguments. */
682 		struct {
683 			int destroy;
684 		} aged; /**< Aged arguments. */
685 	} args; /**< Command arguments. */
686 };
687 
688 /** Private data for pattern items. */
689 struct parse_item_priv {
690 	enum rte_flow_item_type type; /**< Item type. */
691 	uint32_t size; /**< Size of item specification structure. */
692 };
693 
694 #define PRIV_ITEM(t, s) \
695 	(&(const struct parse_item_priv){ \
696 		.type = RTE_FLOW_ITEM_TYPE_ ## t, \
697 		.size = s, \
698 	})
699 
700 /** Private data for actions. */
701 struct parse_action_priv {
702 	enum rte_flow_action_type type; /**< Action type. */
703 	uint32_t size; /**< Size of action configuration structure. */
704 };
705 
706 #define PRIV_ACTION(t, s) \
707 	(&(const struct parse_action_priv){ \
708 		.type = RTE_FLOW_ACTION_TYPE_ ## t, \
709 		.size = s, \
710 	})
711 
712 static const enum index next_vc_attr[] = {
713 	GROUP,
714 	PRIORITY,
715 	INGRESS,
716 	EGRESS,
717 	TRANSFER,
718 	PATTERN,
719 	ZERO,
720 };
721 
722 static const enum index next_destroy_attr[] = {
723 	DESTROY_RULE,
724 	END,
725 	ZERO,
726 };
727 
728 static const enum index next_dump_attr[] = {
729 	FILE_PATH,
730 	END,
731 	ZERO,
732 };
733 
734 static const enum index next_list_attr[] = {
735 	LIST_GROUP,
736 	END,
737 	ZERO,
738 };
739 
740 static const enum index next_aged_attr[] = {
741 	AGED_DESTROY,
742 	END,
743 	ZERO,
744 };
745 
746 static const enum index item_param[] = {
747 	ITEM_PARAM_IS,
748 	ITEM_PARAM_SPEC,
749 	ITEM_PARAM_LAST,
750 	ITEM_PARAM_MASK,
751 	ITEM_PARAM_PREFIX,
752 	ZERO,
753 };
754 
755 static const enum index next_item[] = {
756 	ITEM_END,
757 	ITEM_VOID,
758 	ITEM_INVERT,
759 	ITEM_ANY,
760 	ITEM_PF,
761 	ITEM_VF,
762 	ITEM_PHY_PORT,
763 	ITEM_PORT_ID,
764 	ITEM_MARK,
765 	ITEM_RAW,
766 	ITEM_ETH,
767 	ITEM_VLAN,
768 	ITEM_IPV4,
769 	ITEM_IPV6,
770 	ITEM_ICMP,
771 	ITEM_UDP,
772 	ITEM_TCP,
773 	ITEM_SCTP,
774 	ITEM_VXLAN,
775 	ITEM_E_TAG,
776 	ITEM_NVGRE,
777 	ITEM_MPLS,
778 	ITEM_GRE,
779 	ITEM_FUZZY,
780 	ITEM_GTP,
781 	ITEM_GTPC,
782 	ITEM_GTPU,
783 	ITEM_GENEVE,
784 	ITEM_VXLAN_GPE,
785 	ITEM_ARP_ETH_IPV4,
786 	ITEM_IPV6_EXT,
787 	ITEM_ICMP6,
788 	ITEM_ICMP6_ND_NS,
789 	ITEM_ICMP6_ND_NA,
790 	ITEM_ICMP6_ND_OPT,
791 	ITEM_ICMP6_ND_OPT_SLA_ETH,
792 	ITEM_ICMP6_ND_OPT_TLA_ETH,
793 	ITEM_META,
794 	ITEM_GRE_KEY,
795 	ITEM_GTP_PSC,
796 	ITEM_PPPOES,
797 	ITEM_PPPOED,
798 	ITEM_PPPOE_PROTO_ID,
799 	ITEM_HIGIG2,
800 	ITEM_TAG,
801 	ITEM_L2TPV3OIP,
802 	ITEM_ESP,
803 	ITEM_AH,
804 	ITEM_PFCP,
805 	ITEM_ECPRI,
806 	END_SET,
807 	ZERO,
808 };
809 
810 static const enum index item_fuzzy[] = {
811 	ITEM_FUZZY_THRESH,
812 	ITEM_NEXT,
813 	ZERO,
814 };
815 
816 static const enum index item_any[] = {
817 	ITEM_ANY_NUM,
818 	ITEM_NEXT,
819 	ZERO,
820 };
821 
822 static const enum index item_vf[] = {
823 	ITEM_VF_ID,
824 	ITEM_NEXT,
825 	ZERO,
826 };
827 
828 static const enum index item_phy_port[] = {
829 	ITEM_PHY_PORT_INDEX,
830 	ITEM_NEXT,
831 	ZERO,
832 };
833 
834 static const enum index item_port_id[] = {
835 	ITEM_PORT_ID_ID,
836 	ITEM_NEXT,
837 	ZERO,
838 };
839 
840 static const enum index item_mark[] = {
841 	ITEM_MARK_ID,
842 	ITEM_NEXT,
843 	ZERO,
844 };
845 
846 static const enum index item_raw[] = {
847 	ITEM_RAW_RELATIVE,
848 	ITEM_RAW_SEARCH,
849 	ITEM_RAW_OFFSET,
850 	ITEM_RAW_LIMIT,
851 	ITEM_RAW_PATTERN,
852 	ITEM_NEXT,
853 	ZERO,
854 };
855 
856 static const enum index item_eth[] = {
857 	ITEM_ETH_DST,
858 	ITEM_ETH_SRC,
859 	ITEM_ETH_TYPE,
860 	ITEM_NEXT,
861 	ZERO,
862 };
863 
864 static const enum index item_vlan[] = {
865 	ITEM_VLAN_TCI,
866 	ITEM_VLAN_PCP,
867 	ITEM_VLAN_DEI,
868 	ITEM_VLAN_VID,
869 	ITEM_VLAN_INNER_TYPE,
870 	ITEM_NEXT,
871 	ZERO,
872 };
873 
874 static const enum index item_ipv4[] = {
875 	ITEM_IPV4_TOS,
876 	ITEM_IPV4_TTL,
877 	ITEM_IPV4_PROTO,
878 	ITEM_IPV4_SRC,
879 	ITEM_IPV4_DST,
880 	ITEM_NEXT,
881 	ZERO,
882 };
883 
884 static const enum index item_ipv6[] = {
885 	ITEM_IPV6_TC,
886 	ITEM_IPV6_FLOW,
887 	ITEM_IPV6_PROTO,
888 	ITEM_IPV6_HOP,
889 	ITEM_IPV6_SRC,
890 	ITEM_IPV6_DST,
891 	ITEM_NEXT,
892 	ZERO,
893 };
894 
895 static const enum index item_icmp[] = {
896 	ITEM_ICMP_TYPE,
897 	ITEM_ICMP_CODE,
898 	ITEM_ICMP_IDENT,
899 	ITEM_ICMP_SEQ,
900 	ITEM_NEXT,
901 	ZERO,
902 };
903 
904 static const enum index item_udp[] = {
905 	ITEM_UDP_SRC,
906 	ITEM_UDP_DST,
907 	ITEM_NEXT,
908 	ZERO,
909 };
910 
911 static const enum index item_tcp[] = {
912 	ITEM_TCP_SRC,
913 	ITEM_TCP_DST,
914 	ITEM_TCP_FLAGS,
915 	ITEM_NEXT,
916 	ZERO,
917 };
918 
919 static const enum index item_sctp[] = {
920 	ITEM_SCTP_SRC,
921 	ITEM_SCTP_DST,
922 	ITEM_SCTP_TAG,
923 	ITEM_SCTP_CKSUM,
924 	ITEM_NEXT,
925 	ZERO,
926 };
927 
928 static const enum index item_vxlan[] = {
929 	ITEM_VXLAN_VNI,
930 	ITEM_NEXT,
931 	ZERO,
932 };
933 
934 static const enum index item_e_tag[] = {
935 	ITEM_E_TAG_GRP_ECID_B,
936 	ITEM_NEXT,
937 	ZERO,
938 };
939 
940 static const enum index item_nvgre[] = {
941 	ITEM_NVGRE_TNI,
942 	ITEM_NEXT,
943 	ZERO,
944 };
945 
946 static const enum index item_mpls[] = {
947 	ITEM_MPLS_LABEL,
948 	ITEM_MPLS_TC,
949 	ITEM_MPLS_S,
950 	ITEM_NEXT,
951 	ZERO,
952 };
953 
954 static const enum index item_gre[] = {
955 	ITEM_GRE_PROTO,
956 	ITEM_GRE_C_RSVD0_VER,
957 	ITEM_GRE_C_BIT,
958 	ITEM_GRE_K_BIT,
959 	ITEM_GRE_S_BIT,
960 	ITEM_NEXT,
961 	ZERO,
962 };
963 
964 static const enum index item_gre_key[] = {
965 	ITEM_GRE_KEY_VALUE,
966 	ITEM_NEXT,
967 	ZERO,
968 };
969 
970 static const enum index item_gtp[] = {
971 	ITEM_GTP_FLAGS,
972 	ITEM_GTP_MSG_TYPE,
973 	ITEM_GTP_TEID,
974 	ITEM_NEXT,
975 	ZERO,
976 };
977 
978 static const enum index item_geneve[] = {
979 	ITEM_GENEVE_VNI,
980 	ITEM_GENEVE_PROTO,
981 	ITEM_NEXT,
982 	ZERO,
983 };
984 
985 static const enum index item_vxlan_gpe[] = {
986 	ITEM_VXLAN_GPE_VNI,
987 	ITEM_NEXT,
988 	ZERO,
989 };
990 
991 static const enum index item_arp_eth_ipv4[] = {
992 	ITEM_ARP_ETH_IPV4_SHA,
993 	ITEM_ARP_ETH_IPV4_SPA,
994 	ITEM_ARP_ETH_IPV4_THA,
995 	ITEM_ARP_ETH_IPV4_TPA,
996 	ITEM_NEXT,
997 	ZERO,
998 };
999 
1000 static const enum index item_ipv6_ext[] = {
1001 	ITEM_IPV6_EXT_NEXT_HDR,
1002 	ITEM_NEXT,
1003 	ZERO,
1004 };
1005 
1006 static const enum index item_icmp6[] = {
1007 	ITEM_ICMP6_TYPE,
1008 	ITEM_ICMP6_CODE,
1009 	ITEM_NEXT,
1010 	ZERO,
1011 };
1012 
1013 static const enum index item_icmp6_nd_ns[] = {
1014 	ITEM_ICMP6_ND_NS_TARGET_ADDR,
1015 	ITEM_NEXT,
1016 	ZERO,
1017 };
1018 
1019 static const enum index item_icmp6_nd_na[] = {
1020 	ITEM_ICMP6_ND_NA_TARGET_ADDR,
1021 	ITEM_NEXT,
1022 	ZERO,
1023 };
1024 
1025 static const enum index item_icmp6_nd_opt[] = {
1026 	ITEM_ICMP6_ND_OPT_TYPE,
1027 	ITEM_NEXT,
1028 	ZERO,
1029 };
1030 
1031 static const enum index item_icmp6_nd_opt_sla_eth[] = {
1032 	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
1033 	ITEM_NEXT,
1034 	ZERO,
1035 };
1036 
1037 static const enum index item_icmp6_nd_opt_tla_eth[] = {
1038 	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
1039 	ITEM_NEXT,
1040 	ZERO,
1041 };
1042 
1043 static const enum index item_meta[] = {
1044 	ITEM_META_DATA,
1045 	ITEM_NEXT,
1046 	ZERO,
1047 };
1048 
1049 static const enum index item_gtp_psc[] = {
1050 	ITEM_GTP_PSC_QFI,
1051 	ITEM_GTP_PSC_PDU_T,
1052 	ITEM_NEXT,
1053 	ZERO,
1054 };
1055 
1056 static const enum index item_pppoed[] = {
1057 	ITEM_PPPOE_SEID,
1058 	ITEM_NEXT,
1059 	ZERO,
1060 };
1061 
1062 static const enum index item_pppoes[] = {
1063 	ITEM_PPPOE_SEID,
1064 	ITEM_NEXT,
1065 	ZERO,
1066 };
1067 
1068 static const enum index item_pppoe_proto_id[] = {
1069 	ITEM_NEXT,
1070 	ZERO,
1071 };
1072 
1073 static const enum index item_higig2[] = {
1074 	ITEM_HIGIG2_CLASSIFICATION,
1075 	ITEM_HIGIG2_VID,
1076 	ITEM_NEXT,
1077 	ZERO,
1078 };
1079 
1080 static const enum index item_esp[] = {
1081 	ITEM_ESP_SPI,
1082 	ITEM_NEXT,
1083 	ZERO,
1084 };
1085 
1086 static const enum index item_ah[] = {
1087 	ITEM_AH_SPI,
1088 	ITEM_NEXT,
1089 	ZERO,
1090 };
1091 
1092 static const enum index item_pfcp[] = {
1093 	ITEM_PFCP_S_FIELD,
1094 	ITEM_PFCP_SEID,
1095 	ITEM_NEXT,
1096 	ZERO,
1097 };
1098 
1099 static const enum index next_set_raw[] = {
1100 	SET_RAW_INDEX,
1101 	ITEM_ETH,
1102 	ZERO,
1103 };
1104 
1105 static const enum index item_tag[] = {
1106 	ITEM_TAG_DATA,
1107 	ITEM_TAG_INDEX,
1108 	ITEM_NEXT,
1109 	ZERO,
1110 };
1111 
1112 static const enum index item_l2tpv3oip[] = {
1113 	ITEM_L2TPV3OIP_SESSION_ID,
1114 	ITEM_NEXT,
1115 	ZERO,
1116 };
1117 
1118 static const enum index item_ecpri[] = {
1119 	ITEM_ECPRI_COMMON,
1120 	ITEM_NEXT,
1121 	ZERO,
1122 };
1123 
1124 static const enum index item_ecpri_common[] = {
1125 	ITEM_ECPRI_COMMON_TYPE,
1126 	ZERO,
1127 };
1128 
1129 static const enum index item_ecpri_common_type[] = {
1130 	ITEM_ECPRI_COMMON_TYPE_IQ_DATA,
1131 	ITEM_ECPRI_COMMON_TYPE_RTC_CTRL,
1132 	ITEM_ECPRI_COMMON_TYPE_DLY_MSR,
1133 	ZERO,
1134 };
1135 
1136 static const enum index next_action[] = {
1137 	ACTION_END,
1138 	ACTION_VOID,
1139 	ACTION_PASSTHRU,
1140 	ACTION_JUMP,
1141 	ACTION_MARK,
1142 	ACTION_FLAG,
1143 	ACTION_QUEUE,
1144 	ACTION_DROP,
1145 	ACTION_COUNT,
1146 	ACTION_RSS,
1147 	ACTION_PF,
1148 	ACTION_VF,
1149 	ACTION_PHY_PORT,
1150 	ACTION_PORT_ID,
1151 	ACTION_METER,
1152 	ACTION_OF_SET_MPLS_TTL,
1153 	ACTION_OF_DEC_MPLS_TTL,
1154 	ACTION_OF_SET_NW_TTL,
1155 	ACTION_OF_DEC_NW_TTL,
1156 	ACTION_OF_COPY_TTL_OUT,
1157 	ACTION_OF_COPY_TTL_IN,
1158 	ACTION_OF_POP_VLAN,
1159 	ACTION_OF_PUSH_VLAN,
1160 	ACTION_OF_SET_VLAN_VID,
1161 	ACTION_OF_SET_VLAN_PCP,
1162 	ACTION_OF_POP_MPLS,
1163 	ACTION_OF_PUSH_MPLS,
1164 	ACTION_VXLAN_ENCAP,
1165 	ACTION_VXLAN_DECAP,
1166 	ACTION_NVGRE_ENCAP,
1167 	ACTION_NVGRE_DECAP,
1168 	ACTION_L2_ENCAP,
1169 	ACTION_L2_DECAP,
1170 	ACTION_MPLSOGRE_ENCAP,
1171 	ACTION_MPLSOGRE_DECAP,
1172 	ACTION_MPLSOUDP_ENCAP,
1173 	ACTION_MPLSOUDP_DECAP,
1174 	ACTION_SET_IPV4_SRC,
1175 	ACTION_SET_IPV4_DST,
1176 	ACTION_SET_IPV6_SRC,
1177 	ACTION_SET_IPV6_DST,
1178 	ACTION_SET_TP_SRC,
1179 	ACTION_SET_TP_DST,
1180 	ACTION_MAC_SWAP,
1181 	ACTION_DEC_TTL,
1182 	ACTION_SET_TTL,
1183 	ACTION_SET_MAC_SRC,
1184 	ACTION_SET_MAC_DST,
1185 	ACTION_INC_TCP_SEQ,
1186 	ACTION_DEC_TCP_SEQ,
1187 	ACTION_INC_TCP_ACK,
1188 	ACTION_DEC_TCP_ACK,
1189 	ACTION_RAW_ENCAP,
1190 	ACTION_RAW_DECAP,
1191 	ACTION_SET_TAG,
1192 	ACTION_SET_META,
1193 	ACTION_SET_IPV4_DSCP,
1194 	ACTION_SET_IPV6_DSCP,
1195 	ACTION_AGE,
1196 	ZERO,
1197 };
1198 
1199 static const enum index action_mark[] = {
1200 	ACTION_MARK_ID,
1201 	ACTION_NEXT,
1202 	ZERO,
1203 };
1204 
1205 static const enum index action_queue[] = {
1206 	ACTION_QUEUE_INDEX,
1207 	ACTION_NEXT,
1208 	ZERO,
1209 };
1210 
1211 static const enum index action_count[] = {
1212 	ACTION_COUNT_ID,
1213 	ACTION_COUNT_SHARED,
1214 	ACTION_NEXT,
1215 	ZERO,
1216 };
1217 
1218 static const enum index action_rss[] = {
1219 	ACTION_RSS_FUNC,
1220 	ACTION_RSS_LEVEL,
1221 	ACTION_RSS_TYPES,
1222 	ACTION_RSS_KEY,
1223 	ACTION_RSS_KEY_LEN,
1224 	ACTION_RSS_QUEUES,
1225 	ACTION_NEXT,
1226 	ZERO,
1227 };
1228 
1229 static const enum index action_vf[] = {
1230 	ACTION_VF_ORIGINAL,
1231 	ACTION_VF_ID,
1232 	ACTION_NEXT,
1233 	ZERO,
1234 };
1235 
1236 static const enum index action_phy_port[] = {
1237 	ACTION_PHY_PORT_ORIGINAL,
1238 	ACTION_PHY_PORT_INDEX,
1239 	ACTION_NEXT,
1240 	ZERO,
1241 };
1242 
1243 static const enum index action_port_id[] = {
1244 	ACTION_PORT_ID_ORIGINAL,
1245 	ACTION_PORT_ID_ID,
1246 	ACTION_NEXT,
1247 	ZERO,
1248 };
1249 
1250 static const enum index action_meter[] = {
1251 	ACTION_METER_ID,
1252 	ACTION_NEXT,
1253 	ZERO,
1254 };
1255 
1256 static const enum index action_of_set_mpls_ttl[] = {
1257 	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
1258 	ACTION_NEXT,
1259 	ZERO,
1260 };
1261 
1262 static const enum index action_of_set_nw_ttl[] = {
1263 	ACTION_OF_SET_NW_TTL_NW_TTL,
1264 	ACTION_NEXT,
1265 	ZERO,
1266 };
1267 
1268 static const enum index action_of_push_vlan[] = {
1269 	ACTION_OF_PUSH_VLAN_ETHERTYPE,
1270 	ACTION_NEXT,
1271 	ZERO,
1272 };
1273 
1274 static const enum index action_of_set_vlan_vid[] = {
1275 	ACTION_OF_SET_VLAN_VID_VLAN_VID,
1276 	ACTION_NEXT,
1277 	ZERO,
1278 };
1279 
1280 static const enum index action_of_set_vlan_pcp[] = {
1281 	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
1282 	ACTION_NEXT,
1283 	ZERO,
1284 };
1285 
1286 static const enum index action_of_pop_mpls[] = {
1287 	ACTION_OF_POP_MPLS_ETHERTYPE,
1288 	ACTION_NEXT,
1289 	ZERO,
1290 };
1291 
1292 static const enum index action_of_push_mpls[] = {
1293 	ACTION_OF_PUSH_MPLS_ETHERTYPE,
1294 	ACTION_NEXT,
1295 	ZERO,
1296 };
1297 
1298 static const enum index action_set_ipv4_src[] = {
1299 	ACTION_SET_IPV4_SRC_IPV4_SRC,
1300 	ACTION_NEXT,
1301 	ZERO,
1302 };
1303 
1304 static const enum index action_set_mac_src[] = {
1305 	ACTION_SET_MAC_SRC_MAC_SRC,
1306 	ACTION_NEXT,
1307 	ZERO,
1308 };
1309 
1310 static const enum index action_set_ipv4_dst[] = {
1311 	ACTION_SET_IPV4_DST_IPV4_DST,
1312 	ACTION_NEXT,
1313 	ZERO,
1314 };
1315 
1316 static const enum index action_set_ipv6_src[] = {
1317 	ACTION_SET_IPV6_SRC_IPV6_SRC,
1318 	ACTION_NEXT,
1319 	ZERO,
1320 };
1321 
1322 static const enum index action_set_ipv6_dst[] = {
1323 	ACTION_SET_IPV6_DST_IPV6_DST,
1324 	ACTION_NEXT,
1325 	ZERO,
1326 };
1327 
1328 static const enum index action_set_tp_src[] = {
1329 	ACTION_SET_TP_SRC_TP_SRC,
1330 	ACTION_NEXT,
1331 	ZERO,
1332 };
1333 
1334 static const enum index action_set_tp_dst[] = {
1335 	ACTION_SET_TP_DST_TP_DST,
1336 	ACTION_NEXT,
1337 	ZERO,
1338 };
1339 
1340 static const enum index action_set_ttl[] = {
1341 	ACTION_SET_TTL_TTL,
1342 	ACTION_NEXT,
1343 	ZERO,
1344 };
1345 
1346 static const enum index action_jump[] = {
1347 	ACTION_JUMP_GROUP,
1348 	ACTION_NEXT,
1349 	ZERO,
1350 };
1351 
1352 static const enum index action_set_mac_dst[] = {
1353 	ACTION_SET_MAC_DST_MAC_DST,
1354 	ACTION_NEXT,
1355 	ZERO,
1356 };
1357 
1358 static const enum index action_inc_tcp_seq[] = {
1359 	ACTION_INC_TCP_SEQ_VALUE,
1360 	ACTION_NEXT,
1361 	ZERO,
1362 };
1363 
1364 static const enum index action_dec_tcp_seq[] = {
1365 	ACTION_DEC_TCP_SEQ_VALUE,
1366 	ACTION_NEXT,
1367 	ZERO,
1368 };
1369 
1370 static const enum index action_inc_tcp_ack[] = {
1371 	ACTION_INC_TCP_ACK_VALUE,
1372 	ACTION_NEXT,
1373 	ZERO,
1374 };
1375 
1376 static const enum index action_dec_tcp_ack[] = {
1377 	ACTION_DEC_TCP_ACK_VALUE,
1378 	ACTION_NEXT,
1379 	ZERO,
1380 };
1381 
1382 static const enum index action_raw_encap[] = {
1383 	ACTION_RAW_ENCAP_INDEX,
1384 	ACTION_NEXT,
1385 	ZERO,
1386 };
1387 
1388 static const enum index action_raw_decap[] = {
1389 	ACTION_RAW_DECAP_INDEX,
1390 	ACTION_NEXT,
1391 	ZERO,
1392 };
1393 
1394 static const enum index action_set_tag[] = {
1395 	ACTION_SET_TAG_DATA,
1396 	ACTION_SET_TAG_INDEX,
1397 	ACTION_SET_TAG_MASK,
1398 	ACTION_NEXT,
1399 	ZERO,
1400 };
1401 
1402 static const enum index action_set_meta[] = {
1403 	ACTION_SET_META_DATA,
1404 	ACTION_SET_META_MASK,
1405 	ACTION_NEXT,
1406 	ZERO,
1407 };
1408 
1409 static const enum index action_set_ipv4_dscp[] = {
1410 	ACTION_SET_IPV4_DSCP_VALUE,
1411 	ACTION_NEXT,
1412 	ZERO,
1413 };
1414 
1415 static const enum index action_set_ipv6_dscp[] = {
1416 	ACTION_SET_IPV6_DSCP_VALUE,
1417 	ACTION_NEXT,
1418 	ZERO,
1419 };
1420 
1421 static const enum index action_age[] = {
1422 	ACTION_AGE,
1423 	ACTION_AGE_TIMEOUT,
1424 	ACTION_NEXT,
1425 	ZERO,
1426 };
1427 
1428 static int parse_set_raw_encap_decap(struct context *, const struct token *,
1429 				     const char *, unsigned int,
1430 				     void *, unsigned int);
1431 static int parse_set_init(struct context *, const struct token *,
1432 			  const char *, unsigned int,
1433 			  void *, unsigned int);
1434 static int parse_init(struct context *, const struct token *,
1435 		      const char *, unsigned int,
1436 		      void *, unsigned int);
1437 static int parse_vc(struct context *, const struct token *,
1438 		    const char *, unsigned int,
1439 		    void *, unsigned int);
1440 static int parse_vc_spec(struct context *, const struct token *,
1441 			 const char *, unsigned int, void *, unsigned int);
1442 static int parse_vc_conf(struct context *, const struct token *,
1443 			 const char *, unsigned int, void *, unsigned int);
1444 static int parse_vc_item_ecpri_type(struct context *, const struct token *,
1445 				    const char *, unsigned int,
1446 				    void *, unsigned int);
1447 static int parse_vc_action_rss(struct context *, const struct token *,
1448 			       const char *, unsigned int, void *,
1449 			       unsigned int);
1450 static int parse_vc_action_rss_func(struct context *, const struct token *,
1451 				    const char *, unsigned int, void *,
1452 				    unsigned int);
1453 static int parse_vc_action_rss_type(struct context *, const struct token *,
1454 				    const char *, unsigned int, void *,
1455 				    unsigned int);
1456 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1457 				     const char *, unsigned int, void *,
1458 				     unsigned int);
1459 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1460 				       const char *, unsigned int, void *,
1461 				       unsigned int);
1462 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1463 				       const char *, unsigned int, void *,
1464 				       unsigned int);
1465 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1466 				    const char *, unsigned int, void *,
1467 				    unsigned int);
1468 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1469 				    const char *, unsigned int, void *,
1470 				    unsigned int);
1471 static int parse_vc_action_mplsogre_encap(struct context *,
1472 					  const struct token *, const char *,
1473 					  unsigned int, void *, unsigned int);
1474 static int parse_vc_action_mplsogre_decap(struct context *,
1475 					  const struct token *, const char *,
1476 					  unsigned int, void *, unsigned int);
1477 static int parse_vc_action_mplsoudp_encap(struct context *,
1478 					  const struct token *, const char *,
1479 					  unsigned int, void *, unsigned int);
1480 static int parse_vc_action_mplsoudp_decap(struct context *,
1481 					  const struct token *, const char *,
1482 					  unsigned int, void *, unsigned int);
1483 static int parse_vc_action_raw_encap(struct context *,
1484 				     const struct token *, const char *,
1485 				     unsigned int, void *, unsigned int);
1486 static int parse_vc_action_raw_decap(struct context *,
1487 				     const struct token *, const char *,
1488 				     unsigned int, void *, unsigned int);
1489 static int parse_vc_action_raw_encap_index(struct context *,
1490 					   const struct token *, const char *,
1491 					   unsigned int, void *, unsigned int);
1492 static int parse_vc_action_raw_decap_index(struct context *,
1493 					   const struct token *, const char *,
1494 					   unsigned int, void *, unsigned int);
1495 static int parse_vc_action_set_meta(struct context *ctx,
1496 				    const struct token *token, const char *str,
1497 				    unsigned int len, void *buf,
1498 				    unsigned int size);
1499 static int parse_destroy(struct context *, const struct token *,
1500 			 const char *, unsigned int,
1501 			 void *, unsigned int);
1502 static int parse_flush(struct context *, const struct token *,
1503 		       const char *, unsigned int,
1504 		       void *, unsigned int);
1505 static int parse_dump(struct context *, const struct token *,
1506 		      const char *, unsigned int,
1507 		      void *, unsigned int);
1508 static int parse_query(struct context *, const struct token *,
1509 		       const char *, unsigned int,
1510 		       void *, unsigned int);
1511 static int parse_action(struct context *, const struct token *,
1512 			const char *, unsigned int,
1513 			void *, unsigned int);
1514 static int parse_list(struct context *, const struct token *,
1515 		      const char *, unsigned int,
1516 		      void *, unsigned int);
1517 static int parse_aged(struct context *, const struct token *,
1518 		      const char *, unsigned int,
1519 		      void *, unsigned int);
1520 static int parse_isolate(struct context *, const struct token *,
1521 			 const char *, unsigned int,
1522 			 void *, unsigned int);
1523 static int parse_int(struct context *, const struct token *,
1524 		     const char *, unsigned int,
1525 		     void *, unsigned int);
1526 static int parse_prefix(struct context *, const struct token *,
1527 			const char *, unsigned int,
1528 			void *, unsigned int);
1529 static int parse_boolean(struct context *, const struct token *,
1530 			 const char *, unsigned int,
1531 			 void *, unsigned int);
1532 static int parse_string(struct context *, const struct token *,
1533 			const char *, unsigned int,
1534 			void *, unsigned int);
1535 static int parse_hex(struct context *ctx, const struct token *token,
1536 			const char *str, unsigned int len,
1537 			void *buf, unsigned int size);
1538 static int parse_string0(struct context *, const struct token *,
1539 			const char *, unsigned int,
1540 			void *, unsigned int);
1541 static int parse_mac_addr(struct context *, const struct token *,
1542 			  const char *, unsigned int,
1543 			  void *, unsigned int);
1544 static int parse_ipv4_addr(struct context *, const struct token *,
1545 			   const char *, unsigned int,
1546 			   void *, unsigned int);
1547 static int parse_ipv6_addr(struct context *, const struct token *,
1548 			   const char *, unsigned int,
1549 			   void *, unsigned int);
1550 static int parse_port(struct context *, const struct token *,
1551 		      const char *, unsigned int,
1552 		      void *, unsigned int);
1553 static int comp_none(struct context *, const struct token *,
1554 		     unsigned int, char *, unsigned int);
1555 static int comp_boolean(struct context *, const struct token *,
1556 			unsigned int, char *, unsigned int);
1557 static int comp_action(struct context *, const struct token *,
1558 		       unsigned int, char *, unsigned int);
1559 static int comp_port(struct context *, const struct token *,
1560 		     unsigned int, char *, unsigned int);
1561 static int comp_rule_id(struct context *, const struct token *,
1562 			unsigned int, char *, unsigned int);
1563 static int comp_vc_action_rss_type(struct context *, const struct token *,
1564 				   unsigned int, char *, unsigned int);
1565 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1566 				    unsigned int, char *, unsigned int);
1567 static int comp_set_raw_index(struct context *, const struct token *,
1568 			      unsigned int, char *, unsigned int);
1569 
1570 /** Token definitions. */
1571 static const struct token token_list[] = {
1572 	/* Special tokens. */
1573 	[ZERO] = {
1574 		.name = "ZERO",
1575 		.help = "null entry, abused as the entry point",
1576 		.next = NEXT(NEXT_ENTRY(FLOW)),
1577 	},
1578 	[END] = {
1579 		.name = "",
1580 		.type = "RETURN",
1581 		.help = "command may end here",
1582 	},
1583 	[START_SET] = {
1584 		.name = "START_SET",
1585 		.help = "null entry, abused as the entry point for set",
1586 		.next = NEXT(NEXT_ENTRY(SET)),
1587 	},
1588 	[END_SET] = {
1589 		.name = "end_set",
1590 		.type = "RETURN",
1591 		.help = "set command may end here",
1592 	},
1593 	/* Common tokens. */
1594 	[INTEGER] = {
1595 		.name = "{int}",
1596 		.type = "INTEGER",
1597 		.help = "integer value",
1598 		.call = parse_int,
1599 		.comp = comp_none,
1600 	},
1601 	[UNSIGNED] = {
1602 		.name = "{unsigned}",
1603 		.type = "UNSIGNED",
1604 		.help = "unsigned integer value",
1605 		.call = parse_int,
1606 		.comp = comp_none,
1607 	},
1608 	[PREFIX] = {
1609 		.name = "{prefix}",
1610 		.type = "PREFIX",
1611 		.help = "prefix length for bit-mask",
1612 		.call = parse_prefix,
1613 		.comp = comp_none,
1614 	},
1615 	[BOOLEAN] = {
1616 		.name = "{boolean}",
1617 		.type = "BOOLEAN",
1618 		.help = "any boolean value",
1619 		.call = parse_boolean,
1620 		.comp = comp_boolean,
1621 	},
1622 	[STRING] = {
1623 		.name = "{string}",
1624 		.type = "STRING",
1625 		.help = "fixed string",
1626 		.call = parse_string,
1627 		.comp = comp_none,
1628 	},
1629 	[HEX] = {
1630 		.name = "{hex}",
1631 		.type = "HEX",
1632 		.help = "fixed string",
1633 		.call = parse_hex,
1634 	},
1635 	[FILE_PATH] = {
1636 		.name = "{file path}",
1637 		.type = "STRING",
1638 		.help = "file path",
1639 		.call = parse_string0,
1640 		.comp = comp_none,
1641 	},
1642 	[MAC_ADDR] = {
1643 		.name = "{MAC address}",
1644 		.type = "MAC-48",
1645 		.help = "standard MAC address notation",
1646 		.call = parse_mac_addr,
1647 		.comp = comp_none,
1648 	},
1649 	[IPV4_ADDR] = {
1650 		.name = "{IPv4 address}",
1651 		.type = "IPV4 ADDRESS",
1652 		.help = "standard IPv4 address notation",
1653 		.call = parse_ipv4_addr,
1654 		.comp = comp_none,
1655 	},
1656 	[IPV6_ADDR] = {
1657 		.name = "{IPv6 address}",
1658 		.type = "IPV6 ADDRESS",
1659 		.help = "standard IPv6 address notation",
1660 		.call = parse_ipv6_addr,
1661 		.comp = comp_none,
1662 	},
1663 	[RULE_ID] = {
1664 		.name = "{rule id}",
1665 		.type = "RULE ID",
1666 		.help = "rule identifier",
1667 		.call = parse_int,
1668 		.comp = comp_rule_id,
1669 	},
1670 	[PORT_ID] = {
1671 		.name = "{port_id}",
1672 		.type = "PORT ID",
1673 		.help = "port identifier",
1674 		.call = parse_port,
1675 		.comp = comp_port,
1676 	},
1677 	[GROUP_ID] = {
1678 		.name = "{group_id}",
1679 		.type = "GROUP ID",
1680 		.help = "group identifier",
1681 		.call = parse_int,
1682 		.comp = comp_none,
1683 	},
1684 	[PRIORITY_LEVEL] = {
1685 		.name = "{level}",
1686 		.type = "PRIORITY",
1687 		.help = "priority level",
1688 		.call = parse_int,
1689 		.comp = comp_none,
1690 	},
1691 	/* Top-level command. */
1692 	[FLOW] = {
1693 		.name = "flow",
1694 		.type = "{command} {port_id} [{arg} [...]]",
1695 		.help = "manage ingress/egress flow rules",
1696 		.next = NEXT(NEXT_ENTRY
1697 			     (VALIDATE,
1698 			      CREATE,
1699 			      DESTROY,
1700 			      FLUSH,
1701 			      DUMP,
1702 			      LIST,
1703 			      AGED,
1704 			      QUERY,
1705 			      ISOLATE)),
1706 		.call = parse_init,
1707 	},
1708 	/* Sub-level commands. */
1709 	[VALIDATE] = {
1710 		.name = "validate",
1711 		.help = "check whether a flow rule can be created",
1712 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1713 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1714 		.call = parse_vc,
1715 	},
1716 	[CREATE] = {
1717 		.name = "create",
1718 		.help = "create a flow rule",
1719 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1720 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1721 		.call = parse_vc,
1722 	},
1723 	[DESTROY] = {
1724 		.name = "destroy",
1725 		.help = "destroy specific flow rules",
1726 		.next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
1727 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1728 		.call = parse_destroy,
1729 	},
1730 	[FLUSH] = {
1731 		.name = "flush",
1732 		.help = "destroy all flow rules",
1733 		.next = NEXT(NEXT_ENTRY(PORT_ID)),
1734 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1735 		.call = parse_flush,
1736 	},
1737 	[DUMP] = {
1738 		.name = "dump",
1739 		.help = "dump all flow rules to file",
1740 		.next = NEXT(next_dump_attr, NEXT_ENTRY(PORT_ID)),
1741 		.args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
1742 			     ARGS_ENTRY(struct buffer, port)),
1743 		.call = parse_dump,
1744 	},
1745 	[QUERY] = {
1746 		.name = "query",
1747 		.help = "query an existing flow rule",
1748 		.next = NEXT(NEXT_ENTRY(QUERY_ACTION),
1749 			     NEXT_ENTRY(RULE_ID),
1750 			     NEXT_ENTRY(PORT_ID)),
1751 		.args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
1752 			     ARGS_ENTRY(struct buffer, args.query.rule),
1753 			     ARGS_ENTRY(struct buffer, port)),
1754 		.call = parse_query,
1755 	},
1756 	[LIST] = {
1757 		.name = "list",
1758 		.help = "list existing flow rules",
1759 		.next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
1760 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1761 		.call = parse_list,
1762 	},
1763 	[AGED] = {
1764 		.name = "aged",
1765 		.help = "list and destroy aged flows",
1766 		.next = NEXT(next_aged_attr, NEXT_ENTRY(PORT_ID)),
1767 		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
1768 		.call = parse_aged,
1769 	},
1770 	[ISOLATE] = {
1771 		.name = "isolate",
1772 		.help = "restrict ingress traffic to the defined flow rules",
1773 		.next = NEXT(NEXT_ENTRY(BOOLEAN),
1774 			     NEXT_ENTRY(PORT_ID)),
1775 		.args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
1776 			     ARGS_ENTRY(struct buffer, port)),
1777 		.call = parse_isolate,
1778 	},
1779 	/* Destroy arguments. */
1780 	[DESTROY_RULE] = {
1781 		.name = "rule",
1782 		.help = "specify a rule identifier",
1783 		.next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
1784 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
1785 		.call = parse_destroy,
1786 	},
1787 	/* Query arguments. */
1788 	[QUERY_ACTION] = {
1789 		.name = "{action}",
1790 		.type = "ACTION",
1791 		.help = "action to query, must be part of the rule",
1792 		.call = parse_action,
1793 		.comp = comp_action,
1794 	},
1795 	/* List arguments. */
1796 	[LIST_GROUP] = {
1797 		.name = "group",
1798 		.help = "specify a group",
1799 		.next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
1800 		.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
1801 		.call = parse_list,
1802 	},
1803 	[AGED_DESTROY] = {
1804 		.name = "destroy",
1805 		.help = "specify aged flows need be destroyed",
1806 		.call = parse_aged,
1807 		.comp = comp_none,
1808 	},
1809 	/* Validate/create attributes. */
1810 	[GROUP] = {
1811 		.name = "group",
1812 		.help = "specify a group",
1813 		.next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
1814 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
1815 		.call = parse_vc,
1816 	},
1817 	[PRIORITY] = {
1818 		.name = "priority",
1819 		.help = "specify a priority level",
1820 		.next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
1821 		.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
1822 		.call = parse_vc,
1823 	},
1824 	[INGRESS] = {
1825 		.name = "ingress",
1826 		.help = "affect rule to ingress",
1827 		.next = NEXT(next_vc_attr),
1828 		.call = parse_vc,
1829 	},
1830 	[EGRESS] = {
1831 		.name = "egress",
1832 		.help = "affect rule to egress",
1833 		.next = NEXT(next_vc_attr),
1834 		.call = parse_vc,
1835 	},
1836 	[TRANSFER] = {
1837 		.name = "transfer",
1838 		.help = "apply rule directly to endpoints found in pattern",
1839 		.next = NEXT(next_vc_attr),
1840 		.call = parse_vc,
1841 	},
1842 	/* Validate/create pattern. */
1843 	[PATTERN] = {
1844 		.name = "pattern",
1845 		.help = "submit a list of pattern items",
1846 		.next = NEXT(next_item),
1847 		.call = parse_vc,
1848 	},
1849 	[ITEM_PARAM_IS] = {
1850 		.name = "is",
1851 		.help = "match value perfectly (with full bit-mask)",
1852 		.call = parse_vc_spec,
1853 	},
1854 	[ITEM_PARAM_SPEC] = {
1855 		.name = "spec",
1856 		.help = "match value according to configured bit-mask",
1857 		.call = parse_vc_spec,
1858 	},
1859 	[ITEM_PARAM_LAST] = {
1860 		.name = "last",
1861 		.help = "specify upper bound to establish a range",
1862 		.call = parse_vc_spec,
1863 	},
1864 	[ITEM_PARAM_MASK] = {
1865 		.name = "mask",
1866 		.help = "specify bit-mask with relevant bits set to one",
1867 		.call = parse_vc_spec,
1868 	},
1869 	[ITEM_PARAM_PREFIX] = {
1870 		.name = "prefix",
1871 		.help = "generate bit-mask from a prefix length",
1872 		.call = parse_vc_spec,
1873 	},
1874 	[ITEM_NEXT] = {
1875 		.name = "/",
1876 		.help = "specify next pattern item",
1877 		.next = NEXT(next_item),
1878 	},
1879 	[ITEM_END] = {
1880 		.name = "end",
1881 		.help = "end list of pattern items",
1882 		.priv = PRIV_ITEM(END, 0),
1883 		.next = NEXT(NEXT_ENTRY(ACTIONS)),
1884 		.call = parse_vc,
1885 	},
1886 	[ITEM_VOID] = {
1887 		.name = "void",
1888 		.help = "no-op pattern item",
1889 		.priv = PRIV_ITEM(VOID, 0),
1890 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1891 		.call = parse_vc,
1892 	},
1893 	[ITEM_INVERT] = {
1894 		.name = "invert",
1895 		.help = "perform actions when pattern does not match",
1896 		.priv = PRIV_ITEM(INVERT, 0),
1897 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1898 		.call = parse_vc,
1899 	},
1900 	[ITEM_ANY] = {
1901 		.name = "any",
1902 		.help = "match any protocol for the current layer",
1903 		.priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
1904 		.next = NEXT(item_any),
1905 		.call = parse_vc,
1906 	},
1907 	[ITEM_ANY_NUM] = {
1908 		.name = "num",
1909 		.help = "number of layers covered",
1910 		.next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
1911 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
1912 	},
1913 	[ITEM_PF] = {
1914 		.name = "pf",
1915 		.help = "match traffic from/to the physical function",
1916 		.priv = PRIV_ITEM(PF, 0),
1917 		.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1918 		.call = parse_vc,
1919 	},
1920 	[ITEM_VF] = {
1921 		.name = "vf",
1922 		.help = "match traffic from/to a virtual function ID",
1923 		.priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
1924 		.next = NEXT(item_vf),
1925 		.call = parse_vc,
1926 	},
1927 	[ITEM_VF_ID] = {
1928 		.name = "id",
1929 		.help = "VF ID",
1930 		.next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
1931 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
1932 	},
1933 	[ITEM_PHY_PORT] = {
1934 		.name = "phy_port",
1935 		.help = "match traffic from/to a specific physical port",
1936 		.priv = PRIV_ITEM(PHY_PORT,
1937 				  sizeof(struct rte_flow_item_phy_port)),
1938 		.next = NEXT(item_phy_port),
1939 		.call = parse_vc,
1940 	},
1941 	[ITEM_PHY_PORT_INDEX] = {
1942 		.name = "index",
1943 		.help = "physical port index",
1944 		.next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
1945 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
1946 	},
1947 	[ITEM_PORT_ID] = {
1948 		.name = "port_id",
1949 		.help = "match traffic from/to a given DPDK port ID",
1950 		.priv = PRIV_ITEM(PORT_ID,
1951 				  sizeof(struct rte_flow_item_port_id)),
1952 		.next = NEXT(item_port_id),
1953 		.call = parse_vc,
1954 	},
1955 	[ITEM_PORT_ID_ID] = {
1956 		.name = "id",
1957 		.help = "DPDK port ID",
1958 		.next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
1959 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
1960 	},
1961 	[ITEM_MARK] = {
1962 		.name = "mark",
1963 		.help = "match traffic against value set in previously matched rule",
1964 		.priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
1965 		.next = NEXT(item_mark),
1966 		.call = parse_vc,
1967 	},
1968 	[ITEM_MARK_ID] = {
1969 		.name = "id",
1970 		.help = "Integer value to match against",
1971 		.next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
1972 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
1973 	},
1974 	[ITEM_RAW] = {
1975 		.name = "raw",
1976 		.help = "match an arbitrary byte string",
1977 		.priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
1978 		.next = NEXT(item_raw),
1979 		.call = parse_vc,
1980 	},
1981 	[ITEM_RAW_RELATIVE] = {
1982 		.name = "relative",
1983 		.help = "look for pattern after the previous item",
1984 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1985 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1986 					   relative, 1)),
1987 	},
1988 	[ITEM_RAW_SEARCH] = {
1989 		.name = "search",
1990 		.help = "search pattern from offset (see also limit)",
1991 		.next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1992 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1993 					   search, 1)),
1994 	},
1995 	[ITEM_RAW_OFFSET] = {
1996 		.name = "offset",
1997 		.help = "absolute or relative offset for pattern",
1998 		.next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
1999 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
2000 	},
2001 	[ITEM_RAW_LIMIT] = {
2002 		.name = "limit",
2003 		.help = "search area limit for start of pattern",
2004 		.next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
2005 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
2006 	},
2007 	[ITEM_RAW_PATTERN] = {
2008 		.name = "pattern",
2009 		.help = "byte string to look for",
2010 		.next = NEXT(item_raw,
2011 			     NEXT_ENTRY(STRING),
2012 			     NEXT_ENTRY(ITEM_PARAM_IS,
2013 					ITEM_PARAM_SPEC,
2014 					ITEM_PARAM_MASK)),
2015 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
2016 			     ARGS_ENTRY(struct rte_flow_item_raw, length),
2017 			     ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
2018 					    ITEM_RAW_PATTERN_SIZE)),
2019 	},
2020 	[ITEM_ETH] = {
2021 		.name = "eth",
2022 		.help = "match Ethernet header",
2023 		.priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
2024 		.next = NEXT(item_eth),
2025 		.call = parse_vc,
2026 	},
2027 	[ITEM_ETH_DST] = {
2028 		.name = "dst",
2029 		.help = "destination MAC",
2030 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
2031 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
2032 	},
2033 	[ITEM_ETH_SRC] = {
2034 		.name = "src",
2035 		.help = "source MAC",
2036 		.next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
2037 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
2038 	},
2039 	[ITEM_ETH_TYPE] = {
2040 		.name = "type",
2041 		.help = "EtherType",
2042 		.next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
2043 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
2044 	},
2045 	[ITEM_VLAN] = {
2046 		.name = "vlan",
2047 		.help = "match 802.1Q/ad VLAN tag",
2048 		.priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
2049 		.next = NEXT(item_vlan),
2050 		.call = parse_vc,
2051 	},
2052 	[ITEM_VLAN_TCI] = {
2053 		.name = "tci",
2054 		.help = "tag control information",
2055 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
2056 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
2057 	},
2058 	[ITEM_VLAN_PCP] = {
2059 		.name = "pcp",
2060 		.help = "priority code point",
2061 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
2062 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2063 						  tci, "\xe0\x00")),
2064 	},
2065 	[ITEM_VLAN_DEI] = {
2066 		.name = "dei",
2067 		.help = "drop eligible indicator",
2068 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
2069 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2070 						  tci, "\x10\x00")),
2071 	},
2072 	[ITEM_VLAN_VID] = {
2073 		.name = "vid",
2074 		.help = "VLAN identifier",
2075 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
2076 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
2077 						  tci, "\x0f\xff")),
2078 	},
2079 	[ITEM_VLAN_INNER_TYPE] = {
2080 		.name = "inner_type",
2081 		.help = "inner EtherType",
2082 		.next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
2083 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
2084 					     inner_type)),
2085 	},
2086 	[ITEM_IPV4] = {
2087 		.name = "ipv4",
2088 		.help = "match IPv4 header",
2089 		.priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
2090 		.next = NEXT(item_ipv4),
2091 		.call = parse_vc,
2092 	},
2093 	[ITEM_IPV4_TOS] = {
2094 		.name = "tos",
2095 		.help = "type of service",
2096 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
2097 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2098 					     hdr.type_of_service)),
2099 	},
2100 	[ITEM_IPV4_TTL] = {
2101 		.name = "ttl",
2102 		.help = "time to live",
2103 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
2104 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2105 					     hdr.time_to_live)),
2106 	},
2107 	[ITEM_IPV4_PROTO] = {
2108 		.name = "proto",
2109 		.help = "next protocol ID",
2110 		.next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
2111 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2112 					     hdr.next_proto_id)),
2113 	},
2114 	[ITEM_IPV4_SRC] = {
2115 		.name = "src",
2116 		.help = "source address",
2117 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
2118 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2119 					     hdr.src_addr)),
2120 	},
2121 	[ITEM_IPV4_DST] = {
2122 		.name = "dst",
2123 		.help = "destination address",
2124 		.next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
2125 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
2126 					     hdr.dst_addr)),
2127 	},
2128 	[ITEM_IPV6] = {
2129 		.name = "ipv6",
2130 		.help = "match IPv6 header",
2131 		.priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
2132 		.next = NEXT(item_ipv6),
2133 		.call = parse_vc,
2134 	},
2135 	[ITEM_IPV6_TC] = {
2136 		.name = "tc",
2137 		.help = "traffic class",
2138 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2139 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2140 						  hdr.vtc_flow,
2141 						  "\x0f\xf0\x00\x00")),
2142 	},
2143 	[ITEM_IPV6_FLOW] = {
2144 		.name = "flow",
2145 		.help = "flow label",
2146 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2147 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
2148 						  hdr.vtc_flow,
2149 						  "\x00\x0f\xff\xff")),
2150 	},
2151 	[ITEM_IPV6_PROTO] = {
2152 		.name = "proto",
2153 		.help = "protocol (next header)",
2154 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2155 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2156 					     hdr.proto)),
2157 	},
2158 	[ITEM_IPV6_HOP] = {
2159 		.name = "hop",
2160 		.help = "hop limit",
2161 		.next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
2162 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2163 					     hdr.hop_limits)),
2164 	},
2165 	[ITEM_IPV6_SRC] = {
2166 		.name = "src",
2167 		.help = "source address",
2168 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
2169 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2170 					     hdr.src_addr)),
2171 	},
2172 	[ITEM_IPV6_DST] = {
2173 		.name = "dst",
2174 		.help = "destination address",
2175 		.next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
2176 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
2177 					     hdr.dst_addr)),
2178 	},
2179 	[ITEM_ICMP] = {
2180 		.name = "icmp",
2181 		.help = "match ICMP header",
2182 		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
2183 		.next = NEXT(item_icmp),
2184 		.call = parse_vc,
2185 	},
2186 	[ITEM_ICMP_TYPE] = {
2187 		.name = "type",
2188 		.help = "ICMP packet type",
2189 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2190 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2191 					     hdr.icmp_type)),
2192 	},
2193 	[ITEM_ICMP_CODE] = {
2194 		.name = "code",
2195 		.help = "ICMP packet code",
2196 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2197 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2198 					     hdr.icmp_code)),
2199 	},
2200 	[ITEM_ICMP_IDENT] = {
2201 		.name = "ident",
2202 		.help = "ICMP packet identifier",
2203 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2204 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2205 					     hdr.icmp_ident)),
2206 	},
2207 	[ITEM_ICMP_SEQ] = {
2208 		.name = "seq",
2209 		.help = "ICMP packet sequence number",
2210 		.next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
2211 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
2212 					     hdr.icmp_seq_nb)),
2213 	},
2214 	[ITEM_UDP] = {
2215 		.name = "udp",
2216 		.help = "match UDP header",
2217 		.priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
2218 		.next = NEXT(item_udp),
2219 		.call = parse_vc,
2220 	},
2221 	[ITEM_UDP_SRC] = {
2222 		.name = "src",
2223 		.help = "UDP source port",
2224 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
2225 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2226 					     hdr.src_port)),
2227 	},
2228 	[ITEM_UDP_DST] = {
2229 		.name = "dst",
2230 		.help = "UDP destination port",
2231 		.next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
2232 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
2233 					     hdr.dst_port)),
2234 	},
2235 	[ITEM_TCP] = {
2236 		.name = "tcp",
2237 		.help = "match TCP header",
2238 		.priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
2239 		.next = NEXT(item_tcp),
2240 		.call = parse_vc,
2241 	},
2242 	[ITEM_TCP_SRC] = {
2243 		.name = "src",
2244 		.help = "TCP source port",
2245 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2246 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2247 					     hdr.src_port)),
2248 	},
2249 	[ITEM_TCP_DST] = {
2250 		.name = "dst",
2251 		.help = "TCP destination port",
2252 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2253 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2254 					     hdr.dst_port)),
2255 	},
2256 	[ITEM_TCP_FLAGS] = {
2257 		.name = "flags",
2258 		.help = "TCP flags",
2259 		.next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
2260 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
2261 					     hdr.tcp_flags)),
2262 	},
2263 	[ITEM_SCTP] = {
2264 		.name = "sctp",
2265 		.help = "match SCTP header",
2266 		.priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
2267 		.next = NEXT(item_sctp),
2268 		.call = parse_vc,
2269 	},
2270 	[ITEM_SCTP_SRC] = {
2271 		.name = "src",
2272 		.help = "SCTP source port",
2273 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2274 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2275 					     hdr.src_port)),
2276 	},
2277 	[ITEM_SCTP_DST] = {
2278 		.name = "dst",
2279 		.help = "SCTP destination port",
2280 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2281 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2282 					     hdr.dst_port)),
2283 	},
2284 	[ITEM_SCTP_TAG] = {
2285 		.name = "tag",
2286 		.help = "validation tag",
2287 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2288 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2289 					     hdr.tag)),
2290 	},
2291 	[ITEM_SCTP_CKSUM] = {
2292 		.name = "cksum",
2293 		.help = "checksum",
2294 		.next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
2295 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
2296 					     hdr.cksum)),
2297 	},
2298 	[ITEM_VXLAN] = {
2299 		.name = "vxlan",
2300 		.help = "match VXLAN header",
2301 		.priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
2302 		.next = NEXT(item_vxlan),
2303 		.call = parse_vc,
2304 	},
2305 	[ITEM_VXLAN_VNI] = {
2306 		.name = "vni",
2307 		.help = "VXLAN identifier",
2308 		.next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
2309 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
2310 	},
2311 	[ITEM_E_TAG] = {
2312 		.name = "e_tag",
2313 		.help = "match E-Tag header",
2314 		.priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
2315 		.next = NEXT(item_e_tag),
2316 		.call = parse_vc,
2317 	},
2318 	[ITEM_E_TAG_GRP_ECID_B] = {
2319 		.name = "grp_ecid_b",
2320 		.help = "GRP and E-CID base",
2321 		.next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
2322 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
2323 						  rsvd_grp_ecid_b,
2324 						  "\x3f\xff")),
2325 	},
2326 	[ITEM_NVGRE] = {
2327 		.name = "nvgre",
2328 		.help = "match NVGRE header",
2329 		.priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
2330 		.next = NEXT(item_nvgre),
2331 		.call = parse_vc,
2332 	},
2333 	[ITEM_NVGRE_TNI] = {
2334 		.name = "tni",
2335 		.help = "virtual subnet ID",
2336 		.next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
2337 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
2338 	},
2339 	[ITEM_MPLS] = {
2340 		.name = "mpls",
2341 		.help = "match MPLS header",
2342 		.priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
2343 		.next = NEXT(item_mpls),
2344 		.call = parse_vc,
2345 	},
2346 	[ITEM_MPLS_LABEL] = {
2347 		.name = "label",
2348 		.help = "MPLS label",
2349 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2350 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2351 						  label_tc_s,
2352 						  "\xff\xff\xf0")),
2353 	},
2354 	[ITEM_MPLS_TC] = {
2355 		.name = "tc",
2356 		.help = "MPLS Traffic Class",
2357 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2358 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2359 						  label_tc_s,
2360 						  "\x00\x00\x0e")),
2361 	},
2362 	[ITEM_MPLS_S] = {
2363 		.name = "s",
2364 		.help = "MPLS Bottom-of-Stack",
2365 		.next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
2366 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
2367 						  label_tc_s,
2368 						  "\x00\x00\x01")),
2369 	},
2370 	[ITEM_GRE] = {
2371 		.name = "gre",
2372 		.help = "match GRE header",
2373 		.priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
2374 		.next = NEXT(item_gre),
2375 		.call = parse_vc,
2376 	},
2377 	[ITEM_GRE_PROTO] = {
2378 		.name = "protocol",
2379 		.help = "GRE protocol type",
2380 		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
2381 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2382 					     protocol)),
2383 	},
2384 	[ITEM_GRE_C_RSVD0_VER] = {
2385 		.name = "c_rsvd0_ver",
2386 		.help =
2387 			"checksum (1b), undefined (1b), key bit (1b),"
2388 			" sequence number (1b), reserved 0 (9b),"
2389 			" version (3b)",
2390 		.next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
2391 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
2392 					     c_rsvd0_ver)),
2393 	},
2394 	[ITEM_GRE_C_BIT] = {
2395 		.name = "c_bit",
2396 		.help = "checksum bit (C)",
2397 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2398 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2399 						  c_rsvd0_ver,
2400 						  "\x80\x00\x00\x00")),
2401 	},
2402 	[ITEM_GRE_S_BIT] = {
2403 		.name = "s_bit",
2404 		.help = "sequence number bit (S)",
2405 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2406 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2407 						  c_rsvd0_ver,
2408 						  "\x10\x00\x00\x00")),
2409 	},
2410 	[ITEM_GRE_K_BIT] = {
2411 		.name = "k_bit",
2412 		.help = "key bit (K)",
2413 		.next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
2414 		.args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
2415 						  c_rsvd0_ver,
2416 						  "\x20\x00\x00\x00")),
2417 	},
2418 	[ITEM_FUZZY] = {
2419 		.name = "fuzzy",
2420 		.help = "fuzzy pattern match, expect faster than default",
2421 		.priv = PRIV_ITEM(FUZZY,
2422 				sizeof(struct rte_flow_item_fuzzy)),
2423 		.next = NEXT(item_fuzzy),
2424 		.call = parse_vc,
2425 	},
2426 	[ITEM_FUZZY_THRESH] = {
2427 		.name = "thresh",
2428 		.help = "match accuracy threshold",
2429 		.next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
2430 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
2431 					thresh)),
2432 	},
2433 	[ITEM_GTP] = {
2434 		.name = "gtp",
2435 		.help = "match GTP header",
2436 		.priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
2437 		.next = NEXT(item_gtp),
2438 		.call = parse_vc,
2439 	},
2440 	[ITEM_GTP_FLAGS] = {
2441 		.name = "v_pt_rsv_flags",
2442 		.help = "GTP flags",
2443 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
2444 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
2445 					v_pt_rsv_flags)),
2446 	},
2447 	[ITEM_GTP_MSG_TYPE] = {
2448 		.name = "msg_type",
2449 		.help = "GTP message type",
2450 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
2451 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
2452 	},
2453 	[ITEM_GTP_TEID] = {
2454 		.name = "teid",
2455 		.help = "tunnel endpoint identifier",
2456 		.next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
2457 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
2458 	},
2459 	[ITEM_GTPC] = {
2460 		.name = "gtpc",
2461 		.help = "match GTP header",
2462 		.priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
2463 		.next = NEXT(item_gtp),
2464 		.call = parse_vc,
2465 	},
2466 	[ITEM_GTPU] = {
2467 		.name = "gtpu",
2468 		.help = "match GTP header",
2469 		.priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
2470 		.next = NEXT(item_gtp),
2471 		.call = parse_vc,
2472 	},
2473 	[ITEM_GENEVE] = {
2474 		.name = "geneve",
2475 		.help = "match GENEVE header",
2476 		.priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
2477 		.next = NEXT(item_geneve),
2478 		.call = parse_vc,
2479 	},
2480 	[ITEM_GENEVE_VNI] = {
2481 		.name = "vni",
2482 		.help = "virtual network identifier",
2483 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2484 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
2485 	},
2486 	[ITEM_GENEVE_PROTO] = {
2487 		.name = "protocol",
2488 		.help = "GENEVE protocol type",
2489 		.next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
2490 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
2491 					     protocol)),
2492 	},
2493 	[ITEM_VXLAN_GPE] = {
2494 		.name = "vxlan-gpe",
2495 		.help = "match VXLAN-GPE header",
2496 		.priv = PRIV_ITEM(VXLAN_GPE,
2497 				  sizeof(struct rte_flow_item_vxlan_gpe)),
2498 		.next = NEXT(item_vxlan_gpe),
2499 		.call = parse_vc,
2500 	},
2501 	[ITEM_VXLAN_GPE_VNI] = {
2502 		.name = "vni",
2503 		.help = "VXLAN-GPE identifier",
2504 		.next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
2505 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
2506 					     vni)),
2507 	},
2508 	[ITEM_ARP_ETH_IPV4] = {
2509 		.name = "arp_eth_ipv4",
2510 		.help = "match ARP header for Ethernet/IPv4",
2511 		.priv = PRIV_ITEM(ARP_ETH_IPV4,
2512 				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
2513 		.next = NEXT(item_arp_eth_ipv4),
2514 		.call = parse_vc,
2515 	},
2516 	[ITEM_ARP_ETH_IPV4_SHA] = {
2517 		.name = "sha",
2518 		.help = "sender hardware address",
2519 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2520 			     item_param),
2521 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2522 					     sha)),
2523 	},
2524 	[ITEM_ARP_ETH_IPV4_SPA] = {
2525 		.name = "spa",
2526 		.help = "sender IPv4 address",
2527 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2528 			     item_param),
2529 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2530 					     spa)),
2531 	},
2532 	[ITEM_ARP_ETH_IPV4_THA] = {
2533 		.name = "tha",
2534 		.help = "target hardware address",
2535 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
2536 			     item_param),
2537 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2538 					     tha)),
2539 	},
2540 	[ITEM_ARP_ETH_IPV4_TPA] = {
2541 		.name = "tpa",
2542 		.help = "target IPv4 address",
2543 		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
2544 			     item_param),
2545 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2546 					     tpa)),
2547 	},
2548 	[ITEM_IPV6_EXT] = {
2549 		.name = "ipv6_ext",
2550 		.help = "match presence of any IPv6 extension header",
2551 		.priv = PRIV_ITEM(IPV6_EXT,
2552 				  sizeof(struct rte_flow_item_ipv6_ext)),
2553 		.next = NEXT(item_ipv6_ext),
2554 		.call = parse_vc,
2555 	},
2556 	[ITEM_IPV6_EXT_NEXT_HDR] = {
2557 		.name = "next_hdr",
2558 		.help = "next header",
2559 		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
2560 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
2561 					     next_hdr)),
2562 	},
2563 	[ITEM_ICMP6] = {
2564 		.name = "icmp6",
2565 		.help = "match any ICMPv6 header",
2566 		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
2567 		.next = NEXT(item_icmp6),
2568 		.call = parse_vc,
2569 	},
2570 	[ITEM_ICMP6_TYPE] = {
2571 		.name = "type",
2572 		.help = "ICMPv6 type",
2573 		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2574 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2575 					     type)),
2576 	},
2577 	[ITEM_ICMP6_CODE] = {
2578 		.name = "code",
2579 		.help = "ICMPv6 code",
2580 		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2581 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2582 					     code)),
2583 	},
2584 	[ITEM_ICMP6_ND_NS] = {
2585 		.name = "icmp6_nd_ns",
2586 		.help = "match ICMPv6 neighbor discovery solicitation",
2587 		.priv = PRIV_ITEM(ICMP6_ND_NS,
2588 				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
2589 		.next = NEXT(item_icmp6_nd_ns),
2590 		.call = parse_vc,
2591 	},
2592 	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
2593 		.name = "target_addr",
2594 		.help = "target address",
2595 		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
2596 			     item_param),
2597 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
2598 					     target_addr)),
2599 	},
2600 	[ITEM_ICMP6_ND_NA] = {
2601 		.name = "icmp6_nd_na",
2602 		.help = "match ICMPv6 neighbor discovery advertisement",
2603 		.priv = PRIV_ITEM(ICMP6_ND_NA,
2604 				  sizeof(struct rte_flow_item_icmp6_nd_na)),
2605 		.next = NEXT(item_icmp6_nd_na),
2606 		.call = parse_vc,
2607 	},
2608 	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
2609 		.name = "target_addr",
2610 		.help = "target address",
2611 		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
2612 			     item_param),
2613 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
2614 					     target_addr)),
2615 	},
2616 	[ITEM_ICMP6_ND_OPT] = {
2617 		.name = "icmp6_nd_opt",
2618 		.help = "match presence of any ICMPv6 neighbor discovery"
2619 			" option",
2620 		.priv = PRIV_ITEM(ICMP6_ND_OPT,
2621 				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
2622 		.next = NEXT(item_icmp6_nd_opt),
2623 		.call = parse_vc,
2624 	},
2625 	[ITEM_ICMP6_ND_OPT_TYPE] = {
2626 		.name = "type",
2627 		.help = "ND option type",
2628 		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
2629 			     item_param),
2630 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
2631 					     type)),
2632 	},
2633 	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
2634 		.name = "icmp6_nd_opt_sla_eth",
2635 		.help = "match ICMPv6 neighbor discovery source Ethernet"
2636 			" link-layer address option",
2637 		.priv = PRIV_ITEM
2638 			(ICMP6_ND_OPT_SLA_ETH,
2639 			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
2640 		.next = NEXT(item_icmp6_nd_opt_sla_eth),
2641 		.call = parse_vc,
2642 	},
2643 	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
2644 		.name = "sla",
2645 		.help = "source Ethernet LLA",
2646 		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
2647 			     item_param),
2648 		.args = ARGS(ARGS_ENTRY_HTON
2649 			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
2650 	},
2651 	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
2652 		.name = "icmp6_nd_opt_tla_eth",
2653 		.help = "match ICMPv6 neighbor discovery target Ethernet"
2654 			" link-layer address option",
2655 		.priv = PRIV_ITEM
2656 			(ICMP6_ND_OPT_TLA_ETH,
2657 			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
2658 		.next = NEXT(item_icmp6_nd_opt_tla_eth),
2659 		.call = parse_vc,
2660 	},
2661 	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
2662 		.name = "tla",
2663 		.help = "target Ethernet LLA",
2664 		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
2665 			     item_param),
2666 		.args = ARGS(ARGS_ENTRY_HTON
2667 			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
2668 	},
2669 	[ITEM_META] = {
2670 		.name = "meta",
2671 		.help = "match metadata header",
2672 		.priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
2673 		.next = NEXT(item_meta),
2674 		.call = parse_vc,
2675 	},
2676 	[ITEM_META_DATA] = {
2677 		.name = "data",
2678 		.help = "metadata value",
2679 		.next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
2680 		.args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
2681 					     data, "\xff\xff\xff\xff")),
2682 	},
2683 	[ITEM_GRE_KEY] = {
2684 		.name = "gre_key",
2685 		.help = "match GRE key",
2686 		.priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
2687 		.next = NEXT(item_gre_key),
2688 		.call = parse_vc,
2689 	},
2690 	[ITEM_GRE_KEY_VALUE] = {
2691 		.name = "value",
2692 		.help = "key value",
2693 		.next = NEXT(item_gre_key, NEXT_ENTRY(UNSIGNED), item_param),
2694 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
2695 	},
2696 	[ITEM_GTP_PSC] = {
2697 		.name = "gtp_psc",
2698 		.help = "match GTP extension header with type 0x85",
2699 		.priv = PRIV_ITEM(GTP_PSC,
2700 				sizeof(struct rte_flow_item_gtp_psc)),
2701 		.next = NEXT(item_gtp_psc),
2702 		.call = parse_vc,
2703 	},
2704 	[ITEM_GTP_PSC_QFI] = {
2705 		.name = "qfi",
2706 		.help = "QoS flow identifier",
2707 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
2708 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
2709 					qfi)),
2710 	},
2711 	[ITEM_GTP_PSC_PDU_T] = {
2712 		.name = "pdu_t",
2713 		.help = "PDU type",
2714 		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
2715 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
2716 					pdu_type)),
2717 	},
2718 	[ITEM_PPPOES] = {
2719 		.name = "pppoes",
2720 		.help = "match PPPoE session header",
2721 		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
2722 		.next = NEXT(item_pppoes),
2723 		.call = parse_vc,
2724 	},
2725 	[ITEM_PPPOED] = {
2726 		.name = "pppoed",
2727 		.help = "match PPPoE discovery header",
2728 		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
2729 		.next = NEXT(item_pppoed),
2730 		.call = parse_vc,
2731 	},
2732 	[ITEM_PPPOE_SEID] = {
2733 		.name = "seid",
2734 		.help = "session identifier",
2735 		.next = NEXT(item_pppoes, NEXT_ENTRY(UNSIGNED), item_param),
2736 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
2737 					session_id)),
2738 	},
2739 	[ITEM_PPPOE_PROTO_ID] = {
2740 		.name = "pppoe_proto_id",
2741 		.help = "match PPPoE session protocol identifier",
2742 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
2743 				sizeof(struct rte_flow_item_pppoe_proto_id)),
2744 		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(UNSIGNED),
2745 			     item_param),
2746 		.args = ARGS(ARGS_ENTRY_HTON
2747 			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
2748 		.call = parse_vc,
2749 	},
2750 	[ITEM_HIGIG2] = {
2751 		.name = "higig2",
2752 		.help = "matches higig2 header",
2753 		.priv = PRIV_ITEM(HIGIG2,
2754 				sizeof(struct rte_flow_item_higig2_hdr)),
2755 		.next = NEXT(item_higig2),
2756 		.call = parse_vc,
2757 	},
2758 	[ITEM_HIGIG2_CLASSIFICATION] = {
2759 		.name = "classification",
2760 		.help = "matches classification of higig2 header",
2761 		.next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
2762 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
2763 					hdr.ppt1.classification)),
2764 	},
2765 	[ITEM_HIGIG2_VID] = {
2766 		.name = "vid",
2767 		.help = "matches vid of higig2 header",
2768 		.next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
2769 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
2770 					hdr.ppt1.vid)),
2771 	},
2772 	[ITEM_TAG] = {
2773 		.name = "tag",
2774 		.help = "match tag value",
2775 		.priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
2776 		.next = NEXT(item_tag),
2777 		.call = parse_vc,
2778 	},
2779 	[ITEM_TAG_DATA] = {
2780 		.name = "data",
2781 		.help = "tag value to match",
2782 		.next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), item_param),
2783 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
2784 	},
2785 	[ITEM_TAG_INDEX] = {
2786 		.name = "index",
2787 		.help = "index of tag array to match",
2788 		.next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED),
2789 			     NEXT_ENTRY(ITEM_PARAM_IS)),
2790 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
2791 	},
2792 	[ITEM_L2TPV3OIP] = {
2793 		.name = "l2tpv3oip",
2794 		.help = "match L2TPv3 over IP header",
2795 		.priv = PRIV_ITEM(L2TPV3OIP,
2796 				  sizeof(struct rte_flow_item_l2tpv3oip)),
2797 		.next = NEXT(item_l2tpv3oip),
2798 		.call = parse_vc,
2799 	},
2800 	[ITEM_L2TPV3OIP_SESSION_ID] = {
2801 		.name = "session_id",
2802 		.help = "session identifier",
2803 		.next = NEXT(item_l2tpv3oip, NEXT_ENTRY(UNSIGNED), item_param),
2804 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
2805 					     session_id)),
2806 	},
2807 	[ITEM_ESP] = {
2808 		.name = "esp",
2809 		.help = "match ESP header",
2810 		.priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
2811 		.next = NEXT(item_esp),
2812 		.call = parse_vc,
2813 	},
2814 	[ITEM_ESP_SPI] = {
2815 		.name = "spi",
2816 		.help = "security policy index",
2817 		.next = NEXT(item_esp, NEXT_ENTRY(UNSIGNED), item_param),
2818 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
2819 				hdr.spi)),
2820 	},
2821 	[ITEM_AH] = {
2822 		.name = "ah",
2823 		.help = "match AH header",
2824 		.priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
2825 		.next = NEXT(item_ah),
2826 		.call = parse_vc,
2827 	},
2828 	[ITEM_AH_SPI] = {
2829 		.name = "spi",
2830 		.help = "security parameters index",
2831 		.next = NEXT(item_ah, NEXT_ENTRY(UNSIGNED), item_param),
2832 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
2833 	},
2834 	[ITEM_PFCP] = {
2835 		.name = "pfcp",
2836 		.help = "match pfcp header",
2837 		.priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
2838 		.next = NEXT(item_pfcp),
2839 		.call = parse_vc,
2840 	},
2841 	[ITEM_PFCP_S_FIELD] = {
2842 		.name = "s_field",
2843 		.help = "S field",
2844 		.next = NEXT(item_pfcp, NEXT_ENTRY(UNSIGNED), item_param),
2845 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
2846 				s_field)),
2847 	},
2848 	[ITEM_PFCP_SEID] = {
2849 		.name = "seid",
2850 		.help = "session endpoint identifier",
2851 		.next = NEXT(item_pfcp, NEXT_ENTRY(UNSIGNED), item_param),
2852 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
2853 	},
2854 	[ITEM_ECPRI] = {
2855 		.name = "ecpri",
2856 		.help = "match eCPRI header",
2857 		.priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
2858 		.next = NEXT(item_ecpri),
2859 		.call = parse_vc,
2860 	},
2861 	[ITEM_ECPRI_COMMON] = {
2862 		.name = "common",
2863 		.help = "eCPRI common header",
2864 		.next = NEXT(item_ecpri_common),
2865 	},
2866 	[ITEM_ECPRI_COMMON_TYPE] = {
2867 		.name = "type",
2868 		.help = "type of common header",
2869 		.next = NEXT(item_ecpri_common_type),
2870 		.args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)),
2871 	},
2872 	[ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = {
2873 		.name = "iq_data",
2874 		.help = "Type #0: IQ Data",
2875 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID,
2876 					ITEM_NEXT)),
2877 		.call = parse_vc_item_ecpri_type,
2878 	},
2879 	[ITEM_ECPRI_MSG_IQ_DATA_PCID] = {
2880 		.name = "pc_id",
2881 		.help = "Physical Channel ID",
2882 		.next = NEXT(item_ecpri, NEXT_ENTRY(UNSIGNED), item_param),
2883 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
2884 				hdr.type0.pc_id)),
2885 	},
2886 	[ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = {
2887 		.name = "rtc_ctrl",
2888 		.help = "Type #2: Real-Time Control Data",
2889 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
2890 					ITEM_NEXT)),
2891 		.call = parse_vc_item_ecpri_type,
2892 	},
2893 	[ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = {
2894 		.name = "rtc_id",
2895 		.help = "Real-Time Control Data ID",
2896 		.next = NEXT(item_ecpri, NEXT_ENTRY(UNSIGNED), item_param),
2897 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
2898 				hdr.type2.rtc_id)),
2899 	},
2900 	[ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = {
2901 		.name = "delay_measure",
2902 		.help = "Type #5: One-Way Delay Measurement",
2903 		.next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID,
2904 					ITEM_NEXT)),
2905 		.call = parse_vc_item_ecpri_type,
2906 	},
2907 	[ITEM_ECPRI_MSG_DLY_MSR_MSRID] = {
2908 		.name = "msr_id",
2909 		.help = "Measurement ID",
2910 		.next = NEXT(item_ecpri, NEXT_ENTRY(UNSIGNED), item_param),
2911 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
2912 				hdr.type5.msr_id)),
2913 	},
2914 	/* Validate/create actions. */
2915 	[ACTIONS] = {
2916 		.name = "actions",
2917 		.help = "submit a list of associated actions",
2918 		.next = NEXT(next_action),
2919 		.call = parse_vc,
2920 	},
2921 	[ACTION_NEXT] = {
2922 		.name = "/",
2923 		.help = "specify next action",
2924 		.next = NEXT(next_action),
2925 	},
2926 	[ACTION_END] = {
2927 		.name = "end",
2928 		.help = "end list of actions",
2929 		.priv = PRIV_ACTION(END, 0),
2930 		.call = parse_vc,
2931 	},
2932 	[ACTION_VOID] = {
2933 		.name = "void",
2934 		.help = "no-op action",
2935 		.priv = PRIV_ACTION(VOID, 0),
2936 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2937 		.call = parse_vc,
2938 	},
2939 	[ACTION_PASSTHRU] = {
2940 		.name = "passthru",
2941 		.help = "let subsequent rule process matched packets",
2942 		.priv = PRIV_ACTION(PASSTHRU, 0),
2943 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2944 		.call = parse_vc,
2945 	},
2946 	[ACTION_JUMP] = {
2947 		.name = "jump",
2948 		.help = "redirect traffic to a given group",
2949 		.priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
2950 		.next = NEXT(action_jump),
2951 		.call = parse_vc,
2952 	},
2953 	[ACTION_JUMP_GROUP] = {
2954 		.name = "group",
2955 		.help = "group to redirect traffic to",
2956 		.next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
2957 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
2958 		.call = parse_vc_conf,
2959 	},
2960 	[ACTION_MARK] = {
2961 		.name = "mark",
2962 		.help = "attach 32 bit value to packets",
2963 		.priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
2964 		.next = NEXT(action_mark),
2965 		.call = parse_vc,
2966 	},
2967 	[ACTION_MARK_ID] = {
2968 		.name = "id",
2969 		.help = "32 bit value to return with packets",
2970 		.next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
2971 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
2972 		.call = parse_vc_conf,
2973 	},
2974 	[ACTION_FLAG] = {
2975 		.name = "flag",
2976 		.help = "flag packets",
2977 		.priv = PRIV_ACTION(FLAG, 0),
2978 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2979 		.call = parse_vc,
2980 	},
2981 	[ACTION_QUEUE] = {
2982 		.name = "queue",
2983 		.help = "assign packets to a given queue index",
2984 		.priv = PRIV_ACTION(QUEUE,
2985 				    sizeof(struct rte_flow_action_queue)),
2986 		.next = NEXT(action_queue),
2987 		.call = parse_vc,
2988 	},
2989 	[ACTION_QUEUE_INDEX] = {
2990 		.name = "index",
2991 		.help = "queue index to use",
2992 		.next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
2993 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
2994 		.call = parse_vc_conf,
2995 	},
2996 	[ACTION_DROP] = {
2997 		.name = "drop",
2998 		.help = "drop packets (note: passthru has priority)",
2999 		.priv = PRIV_ACTION(DROP, 0),
3000 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3001 		.call = parse_vc,
3002 	},
3003 	[ACTION_COUNT] = {
3004 		.name = "count",
3005 		.help = "enable counters for this rule",
3006 		.priv = PRIV_ACTION(COUNT,
3007 				    sizeof(struct rte_flow_action_count)),
3008 		.next = NEXT(action_count),
3009 		.call = parse_vc,
3010 	},
3011 	[ACTION_COUNT_ID] = {
3012 		.name = "identifier",
3013 		.help = "counter identifier to use",
3014 		.next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
3015 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
3016 		.call = parse_vc_conf,
3017 	},
3018 	[ACTION_COUNT_SHARED] = {
3019 		.name = "shared",
3020 		.help = "shared counter",
3021 		.next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
3022 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
3023 					   shared, 1)),
3024 		.call = parse_vc_conf,
3025 	},
3026 	[ACTION_RSS] = {
3027 		.name = "rss",
3028 		.help = "spread packets among several queues",
3029 		.priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
3030 		.next = NEXT(action_rss),
3031 		.call = parse_vc_action_rss,
3032 	},
3033 	[ACTION_RSS_FUNC] = {
3034 		.name = "func",
3035 		.help = "RSS hash function to apply",
3036 		.next = NEXT(action_rss,
3037 			     NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
3038 					ACTION_RSS_FUNC_TOEPLITZ,
3039 					ACTION_RSS_FUNC_SIMPLE_XOR,
3040 					ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
3041 	},
3042 	[ACTION_RSS_FUNC_DEFAULT] = {
3043 		.name = "default",
3044 		.help = "default hash function",
3045 		.call = parse_vc_action_rss_func,
3046 	},
3047 	[ACTION_RSS_FUNC_TOEPLITZ] = {
3048 		.name = "toeplitz",
3049 		.help = "Toeplitz hash function",
3050 		.call = parse_vc_action_rss_func,
3051 	},
3052 	[ACTION_RSS_FUNC_SIMPLE_XOR] = {
3053 		.name = "simple_xor",
3054 		.help = "simple XOR hash function",
3055 		.call = parse_vc_action_rss_func,
3056 	},
3057 	[ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
3058 		.name = "symmetric_toeplitz",
3059 		.help = "Symmetric Toeplitz hash function",
3060 		.call = parse_vc_action_rss_func,
3061 	},
3062 	[ACTION_RSS_LEVEL] = {
3063 		.name = "level",
3064 		.help = "encapsulation level for \"types\"",
3065 		.next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
3066 		.args = ARGS(ARGS_ENTRY_ARB
3067 			     (offsetof(struct action_rss_data, conf) +
3068 			      offsetof(struct rte_flow_action_rss, level),
3069 			      sizeof(((struct rte_flow_action_rss *)0)->
3070 				     level))),
3071 	},
3072 	[ACTION_RSS_TYPES] = {
3073 		.name = "types",
3074 		.help = "specific RSS hash types",
3075 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
3076 	},
3077 	[ACTION_RSS_TYPE] = {
3078 		.name = "{type}",
3079 		.help = "RSS hash type",
3080 		.call = parse_vc_action_rss_type,
3081 		.comp = comp_vc_action_rss_type,
3082 	},
3083 	[ACTION_RSS_KEY] = {
3084 		.name = "key",
3085 		.help = "RSS hash key",
3086 		.next = NEXT(action_rss, NEXT_ENTRY(HEX)),
3087 		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
3088 			     ARGS_ENTRY_ARB
3089 			     (offsetof(struct action_rss_data, conf) +
3090 			      offsetof(struct rte_flow_action_rss, key_len),
3091 			      sizeof(((struct rte_flow_action_rss *)0)->
3092 				     key_len)),
3093 			     ARGS_ENTRY(struct action_rss_data, key)),
3094 	},
3095 	[ACTION_RSS_KEY_LEN] = {
3096 		.name = "key_len",
3097 		.help = "RSS hash key length in bytes",
3098 		.next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
3099 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3100 			     (offsetof(struct action_rss_data, conf) +
3101 			      offsetof(struct rte_flow_action_rss, key_len),
3102 			      sizeof(((struct rte_flow_action_rss *)0)->
3103 				     key_len),
3104 			      0,
3105 			      RSS_HASH_KEY_LENGTH)),
3106 	},
3107 	[ACTION_RSS_QUEUES] = {
3108 		.name = "queues",
3109 		.help = "queue indices to use",
3110 		.next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
3111 		.call = parse_vc_conf,
3112 	},
3113 	[ACTION_RSS_QUEUE] = {
3114 		.name = "{queue}",
3115 		.help = "queue index",
3116 		.call = parse_vc_action_rss_queue,
3117 		.comp = comp_vc_action_rss_queue,
3118 	},
3119 	[ACTION_PF] = {
3120 		.name = "pf",
3121 		.help = "direct traffic to physical function",
3122 		.priv = PRIV_ACTION(PF, 0),
3123 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3124 		.call = parse_vc,
3125 	},
3126 	[ACTION_VF] = {
3127 		.name = "vf",
3128 		.help = "direct traffic to a virtual function ID",
3129 		.priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
3130 		.next = NEXT(action_vf),
3131 		.call = parse_vc,
3132 	},
3133 	[ACTION_VF_ORIGINAL] = {
3134 		.name = "original",
3135 		.help = "use original VF ID if possible",
3136 		.next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
3137 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
3138 					   original, 1)),
3139 		.call = parse_vc_conf,
3140 	},
3141 	[ACTION_VF_ID] = {
3142 		.name = "id",
3143 		.help = "VF ID",
3144 		.next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
3145 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
3146 		.call = parse_vc_conf,
3147 	},
3148 	[ACTION_PHY_PORT] = {
3149 		.name = "phy_port",
3150 		.help = "direct packets to physical port index",
3151 		.priv = PRIV_ACTION(PHY_PORT,
3152 				    sizeof(struct rte_flow_action_phy_port)),
3153 		.next = NEXT(action_phy_port),
3154 		.call = parse_vc,
3155 	},
3156 	[ACTION_PHY_PORT_ORIGINAL] = {
3157 		.name = "original",
3158 		.help = "use original port index if possible",
3159 		.next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
3160 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
3161 					   original, 1)),
3162 		.call = parse_vc_conf,
3163 	},
3164 	[ACTION_PHY_PORT_INDEX] = {
3165 		.name = "index",
3166 		.help = "physical port index",
3167 		.next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
3168 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
3169 					index)),
3170 		.call = parse_vc_conf,
3171 	},
3172 	[ACTION_PORT_ID] = {
3173 		.name = "port_id",
3174 		.help = "direct matching traffic to a given DPDK port ID",
3175 		.priv = PRIV_ACTION(PORT_ID,
3176 				    sizeof(struct rte_flow_action_port_id)),
3177 		.next = NEXT(action_port_id),
3178 		.call = parse_vc,
3179 	},
3180 	[ACTION_PORT_ID_ORIGINAL] = {
3181 		.name = "original",
3182 		.help = "use original DPDK port ID if possible",
3183 		.next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
3184 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
3185 					   original, 1)),
3186 		.call = parse_vc_conf,
3187 	},
3188 	[ACTION_PORT_ID_ID] = {
3189 		.name = "id",
3190 		.help = "DPDK port ID",
3191 		.next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
3192 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
3193 		.call = parse_vc_conf,
3194 	},
3195 	[ACTION_METER] = {
3196 		.name = "meter",
3197 		.help = "meter the directed packets at given id",
3198 		.priv = PRIV_ACTION(METER,
3199 				    sizeof(struct rte_flow_action_meter)),
3200 		.next = NEXT(action_meter),
3201 		.call = parse_vc,
3202 	},
3203 	[ACTION_METER_ID] = {
3204 		.name = "mtr_id",
3205 		.help = "meter id to use",
3206 		.next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
3207 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
3208 		.call = parse_vc_conf,
3209 	},
3210 	[ACTION_OF_SET_MPLS_TTL] = {
3211 		.name = "of_set_mpls_ttl",
3212 		.help = "OpenFlow's OFPAT_SET_MPLS_TTL",
3213 		.priv = PRIV_ACTION
3214 			(OF_SET_MPLS_TTL,
3215 			 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
3216 		.next = NEXT(action_of_set_mpls_ttl),
3217 		.call = parse_vc,
3218 	},
3219 	[ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
3220 		.name = "mpls_ttl",
3221 		.help = "MPLS TTL",
3222 		.next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
3223 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
3224 					mpls_ttl)),
3225 		.call = parse_vc_conf,
3226 	},
3227 	[ACTION_OF_DEC_MPLS_TTL] = {
3228 		.name = "of_dec_mpls_ttl",
3229 		.help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
3230 		.priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
3231 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3232 		.call = parse_vc,
3233 	},
3234 	[ACTION_OF_SET_NW_TTL] = {
3235 		.name = "of_set_nw_ttl",
3236 		.help = "OpenFlow's OFPAT_SET_NW_TTL",
3237 		.priv = PRIV_ACTION
3238 			(OF_SET_NW_TTL,
3239 			 sizeof(struct rte_flow_action_of_set_nw_ttl)),
3240 		.next = NEXT(action_of_set_nw_ttl),
3241 		.call = parse_vc,
3242 	},
3243 	[ACTION_OF_SET_NW_TTL_NW_TTL] = {
3244 		.name = "nw_ttl",
3245 		.help = "IP TTL",
3246 		.next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
3247 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
3248 					nw_ttl)),
3249 		.call = parse_vc_conf,
3250 	},
3251 	[ACTION_OF_DEC_NW_TTL] = {
3252 		.name = "of_dec_nw_ttl",
3253 		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
3254 		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
3255 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3256 		.call = parse_vc,
3257 	},
3258 	[ACTION_OF_COPY_TTL_OUT] = {
3259 		.name = "of_copy_ttl_out",
3260 		.help = "OpenFlow's OFPAT_COPY_TTL_OUT",
3261 		.priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
3262 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3263 		.call = parse_vc,
3264 	},
3265 	[ACTION_OF_COPY_TTL_IN] = {
3266 		.name = "of_copy_ttl_in",
3267 		.help = "OpenFlow's OFPAT_COPY_TTL_IN",
3268 		.priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
3269 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3270 		.call = parse_vc,
3271 	},
3272 	[ACTION_OF_POP_VLAN] = {
3273 		.name = "of_pop_vlan",
3274 		.help = "OpenFlow's OFPAT_POP_VLAN",
3275 		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
3276 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3277 		.call = parse_vc,
3278 	},
3279 	[ACTION_OF_PUSH_VLAN] = {
3280 		.name = "of_push_vlan",
3281 		.help = "OpenFlow's OFPAT_PUSH_VLAN",
3282 		.priv = PRIV_ACTION
3283 			(OF_PUSH_VLAN,
3284 			 sizeof(struct rte_flow_action_of_push_vlan)),
3285 		.next = NEXT(action_of_push_vlan),
3286 		.call = parse_vc,
3287 	},
3288 	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
3289 		.name = "ethertype",
3290 		.help = "EtherType",
3291 		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
3292 		.args = ARGS(ARGS_ENTRY_HTON
3293 			     (struct rte_flow_action_of_push_vlan,
3294 			      ethertype)),
3295 		.call = parse_vc_conf,
3296 	},
3297 	[ACTION_OF_SET_VLAN_VID] = {
3298 		.name = "of_set_vlan_vid",
3299 		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
3300 		.priv = PRIV_ACTION
3301 			(OF_SET_VLAN_VID,
3302 			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
3303 		.next = NEXT(action_of_set_vlan_vid),
3304 		.call = parse_vc,
3305 	},
3306 	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
3307 		.name = "vlan_vid",
3308 		.help = "VLAN id",
3309 		.next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
3310 		.args = ARGS(ARGS_ENTRY_HTON
3311 			     (struct rte_flow_action_of_set_vlan_vid,
3312 			      vlan_vid)),
3313 		.call = parse_vc_conf,
3314 	},
3315 	[ACTION_OF_SET_VLAN_PCP] = {
3316 		.name = "of_set_vlan_pcp",
3317 		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
3318 		.priv = PRIV_ACTION
3319 			(OF_SET_VLAN_PCP,
3320 			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
3321 		.next = NEXT(action_of_set_vlan_pcp),
3322 		.call = parse_vc,
3323 	},
3324 	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
3325 		.name = "vlan_pcp",
3326 		.help = "VLAN priority",
3327 		.next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
3328 		.args = ARGS(ARGS_ENTRY_HTON
3329 			     (struct rte_flow_action_of_set_vlan_pcp,
3330 			      vlan_pcp)),
3331 		.call = parse_vc_conf,
3332 	},
3333 	[ACTION_OF_POP_MPLS] = {
3334 		.name = "of_pop_mpls",
3335 		.help = "OpenFlow's OFPAT_POP_MPLS",
3336 		.priv = PRIV_ACTION(OF_POP_MPLS,
3337 				    sizeof(struct rte_flow_action_of_pop_mpls)),
3338 		.next = NEXT(action_of_pop_mpls),
3339 		.call = parse_vc,
3340 	},
3341 	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
3342 		.name = "ethertype",
3343 		.help = "EtherType",
3344 		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
3345 		.args = ARGS(ARGS_ENTRY_HTON
3346 			     (struct rte_flow_action_of_pop_mpls,
3347 			      ethertype)),
3348 		.call = parse_vc_conf,
3349 	},
3350 	[ACTION_OF_PUSH_MPLS] = {
3351 		.name = "of_push_mpls",
3352 		.help = "OpenFlow's OFPAT_PUSH_MPLS",
3353 		.priv = PRIV_ACTION
3354 			(OF_PUSH_MPLS,
3355 			 sizeof(struct rte_flow_action_of_push_mpls)),
3356 		.next = NEXT(action_of_push_mpls),
3357 		.call = parse_vc,
3358 	},
3359 	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
3360 		.name = "ethertype",
3361 		.help = "EtherType",
3362 		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
3363 		.args = ARGS(ARGS_ENTRY_HTON
3364 			     (struct rte_flow_action_of_push_mpls,
3365 			      ethertype)),
3366 		.call = parse_vc_conf,
3367 	},
3368 	[ACTION_VXLAN_ENCAP] = {
3369 		.name = "vxlan_encap",
3370 		.help = "VXLAN encapsulation, uses configuration set by \"set"
3371 			" vxlan\"",
3372 		.priv = PRIV_ACTION(VXLAN_ENCAP,
3373 				    sizeof(struct action_vxlan_encap_data)),
3374 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3375 		.call = parse_vc_action_vxlan_encap,
3376 	},
3377 	[ACTION_VXLAN_DECAP] = {
3378 		.name = "vxlan_decap",
3379 		.help = "Performs a decapsulation action by stripping all"
3380 			" headers of the VXLAN tunnel network overlay from the"
3381 			" matched flow.",
3382 		.priv = PRIV_ACTION(VXLAN_DECAP, 0),
3383 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3384 		.call = parse_vc,
3385 	},
3386 	[ACTION_NVGRE_ENCAP] = {
3387 		.name = "nvgre_encap",
3388 		.help = "NVGRE encapsulation, uses configuration set by \"set"
3389 			" nvgre\"",
3390 		.priv = PRIV_ACTION(NVGRE_ENCAP,
3391 				    sizeof(struct action_nvgre_encap_data)),
3392 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3393 		.call = parse_vc_action_nvgre_encap,
3394 	},
3395 	[ACTION_NVGRE_DECAP] = {
3396 		.name = "nvgre_decap",
3397 		.help = "Performs a decapsulation action by stripping all"
3398 			" headers of the NVGRE tunnel network overlay from the"
3399 			" matched flow.",
3400 		.priv = PRIV_ACTION(NVGRE_DECAP, 0),
3401 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3402 		.call = parse_vc,
3403 	},
3404 	[ACTION_L2_ENCAP] = {
3405 		.name = "l2_encap",
3406 		.help = "l2 encap, uses configuration set by"
3407 			" \"set l2_encap\"",
3408 		.priv = PRIV_ACTION(RAW_ENCAP,
3409 				    sizeof(struct action_raw_encap_data)),
3410 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3411 		.call = parse_vc_action_l2_encap,
3412 	},
3413 	[ACTION_L2_DECAP] = {
3414 		.name = "l2_decap",
3415 		.help = "l2 decap, uses configuration set by"
3416 			" \"set l2_decap\"",
3417 		.priv = PRIV_ACTION(RAW_DECAP,
3418 				    sizeof(struct action_raw_decap_data)),
3419 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3420 		.call = parse_vc_action_l2_decap,
3421 	},
3422 	[ACTION_MPLSOGRE_ENCAP] = {
3423 		.name = "mplsogre_encap",
3424 		.help = "mplsogre encapsulation, uses configuration set by"
3425 			" \"set mplsogre_encap\"",
3426 		.priv = PRIV_ACTION(RAW_ENCAP,
3427 				    sizeof(struct action_raw_encap_data)),
3428 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3429 		.call = parse_vc_action_mplsogre_encap,
3430 	},
3431 	[ACTION_MPLSOGRE_DECAP] = {
3432 		.name = "mplsogre_decap",
3433 		.help = "mplsogre decapsulation, uses configuration set by"
3434 			" \"set mplsogre_decap\"",
3435 		.priv = PRIV_ACTION(RAW_DECAP,
3436 				    sizeof(struct action_raw_decap_data)),
3437 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3438 		.call = parse_vc_action_mplsogre_decap,
3439 	},
3440 	[ACTION_MPLSOUDP_ENCAP] = {
3441 		.name = "mplsoudp_encap",
3442 		.help = "mplsoudp encapsulation, uses configuration set by"
3443 			" \"set mplsoudp_encap\"",
3444 		.priv = PRIV_ACTION(RAW_ENCAP,
3445 				    sizeof(struct action_raw_encap_data)),
3446 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3447 		.call = parse_vc_action_mplsoudp_encap,
3448 	},
3449 	[ACTION_MPLSOUDP_DECAP] = {
3450 		.name = "mplsoudp_decap",
3451 		.help = "mplsoudp decapsulation, uses configuration set by"
3452 			" \"set mplsoudp_decap\"",
3453 		.priv = PRIV_ACTION(RAW_DECAP,
3454 				    sizeof(struct action_raw_decap_data)),
3455 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3456 		.call = parse_vc_action_mplsoudp_decap,
3457 	},
3458 	[ACTION_SET_IPV4_SRC] = {
3459 		.name = "set_ipv4_src",
3460 		.help = "Set a new IPv4 source address in the outermost"
3461 			" IPv4 header",
3462 		.priv = PRIV_ACTION(SET_IPV4_SRC,
3463 			sizeof(struct rte_flow_action_set_ipv4)),
3464 		.next = NEXT(action_set_ipv4_src),
3465 		.call = parse_vc,
3466 	},
3467 	[ACTION_SET_IPV4_SRC_IPV4_SRC] = {
3468 		.name = "ipv4_addr",
3469 		.help = "new IPv4 source address to set",
3470 		.next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
3471 		.args = ARGS(ARGS_ENTRY_HTON
3472 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
3473 		.call = parse_vc_conf,
3474 	},
3475 	[ACTION_SET_IPV4_DST] = {
3476 		.name = "set_ipv4_dst",
3477 		.help = "Set a new IPv4 destination address in the outermost"
3478 			" IPv4 header",
3479 		.priv = PRIV_ACTION(SET_IPV4_DST,
3480 			sizeof(struct rte_flow_action_set_ipv4)),
3481 		.next = NEXT(action_set_ipv4_dst),
3482 		.call = parse_vc,
3483 	},
3484 	[ACTION_SET_IPV4_DST_IPV4_DST] = {
3485 		.name = "ipv4_addr",
3486 		.help = "new IPv4 destination address to set",
3487 		.next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
3488 		.args = ARGS(ARGS_ENTRY_HTON
3489 			(struct rte_flow_action_set_ipv4, ipv4_addr)),
3490 		.call = parse_vc_conf,
3491 	},
3492 	[ACTION_SET_IPV6_SRC] = {
3493 		.name = "set_ipv6_src",
3494 		.help = "Set a new IPv6 source address in the outermost"
3495 			" IPv6 header",
3496 		.priv = PRIV_ACTION(SET_IPV6_SRC,
3497 			sizeof(struct rte_flow_action_set_ipv6)),
3498 		.next = NEXT(action_set_ipv6_src),
3499 		.call = parse_vc,
3500 	},
3501 	[ACTION_SET_IPV6_SRC_IPV6_SRC] = {
3502 		.name = "ipv6_addr",
3503 		.help = "new IPv6 source address to set",
3504 		.next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
3505 		.args = ARGS(ARGS_ENTRY_HTON
3506 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
3507 		.call = parse_vc_conf,
3508 	},
3509 	[ACTION_SET_IPV6_DST] = {
3510 		.name = "set_ipv6_dst",
3511 		.help = "Set a new IPv6 destination address in the outermost"
3512 			" IPv6 header",
3513 		.priv = PRIV_ACTION(SET_IPV6_DST,
3514 			sizeof(struct rte_flow_action_set_ipv6)),
3515 		.next = NEXT(action_set_ipv6_dst),
3516 		.call = parse_vc,
3517 	},
3518 	[ACTION_SET_IPV6_DST_IPV6_DST] = {
3519 		.name = "ipv6_addr",
3520 		.help = "new IPv6 destination address to set",
3521 		.next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
3522 		.args = ARGS(ARGS_ENTRY_HTON
3523 			(struct rte_flow_action_set_ipv6, ipv6_addr)),
3524 		.call = parse_vc_conf,
3525 	},
3526 	[ACTION_SET_TP_SRC] = {
3527 		.name = "set_tp_src",
3528 		.help = "set a new source port number in the outermost"
3529 			" TCP/UDP header",
3530 		.priv = PRIV_ACTION(SET_TP_SRC,
3531 			sizeof(struct rte_flow_action_set_tp)),
3532 		.next = NEXT(action_set_tp_src),
3533 		.call = parse_vc,
3534 	},
3535 	[ACTION_SET_TP_SRC_TP_SRC] = {
3536 		.name = "port",
3537 		.help = "new source port number to set",
3538 		.next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
3539 		.args = ARGS(ARGS_ENTRY_HTON
3540 			     (struct rte_flow_action_set_tp, port)),
3541 		.call = parse_vc_conf,
3542 	},
3543 	[ACTION_SET_TP_DST] = {
3544 		.name = "set_tp_dst",
3545 		.help = "set a new destination port number in the outermost"
3546 			" TCP/UDP header",
3547 		.priv = PRIV_ACTION(SET_TP_DST,
3548 			sizeof(struct rte_flow_action_set_tp)),
3549 		.next = NEXT(action_set_tp_dst),
3550 		.call = parse_vc,
3551 	},
3552 	[ACTION_SET_TP_DST_TP_DST] = {
3553 		.name = "port",
3554 		.help = "new destination port number to set",
3555 		.next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
3556 		.args = ARGS(ARGS_ENTRY_HTON
3557 			     (struct rte_flow_action_set_tp, port)),
3558 		.call = parse_vc_conf,
3559 	},
3560 	[ACTION_MAC_SWAP] = {
3561 		.name = "mac_swap",
3562 		.help = "Swap the source and destination MAC addresses"
3563 			" in the outermost Ethernet header",
3564 		.priv = PRIV_ACTION(MAC_SWAP, 0),
3565 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3566 		.call = parse_vc,
3567 	},
3568 	[ACTION_DEC_TTL] = {
3569 		.name = "dec_ttl",
3570 		.help = "decrease network TTL if available",
3571 		.priv = PRIV_ACTION(DEC_TTL, 0),
3572 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3573 		.call = parse_vc,
3574 	},
3575 	[ACTION_SET_TTL] = {
3576 		.name = "set_ttl",
3577 		.help = "set ttl value",
3578 		.priv = PRIV_ACTION(SET_TTL,
3579 			sizeof(struct rte_flow_action_set_ttl)),
3580 		.next = NEXT(action_set_ttl),
3581 		.call = parse_vc,
3582 	},
3583 	[ACTION_SET_TTL_TTL] = {
3584 		.name = "ttl_value",
3585 		.help = "new ttl value to set",
3586 		.next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
3587 		.args = ARGS(ARGS_ENTRY_HTON
3588 			     (struct rte_flow_action_set_ttl, ttl_value)),
3589 		.call = parse_vc_conf,
3590 	},
3591 	[ACTION_SET_MAC_SRC] = {
3592 		.name = "set_mac_src",
3593 		.help = "set source mac address",
3594 		.priv = PRIV_ACTION(SET_MAC_SRC,
3595 			sizeof(struct rte_flow_action_set_mac)),
3596 		.next = NEXT(action_set_mac_src),
3597 		.call = parse_vc,
3598 	},
3599 	[ACTION_SET_MAC_SRC_MAC_SRC] = {
3600 		.name = "mac_addr",
3601 		.help = "new source mac address",
3602 		.next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
3603 		.args = ARGS(ARGS_ENTRY_HTON
3604 			     (struct rte_flow_action_set_mac, mac_addr)),
3605 		.call = parse_vc_conf,
3606 	},
3607 	[ACTION_SET_MAC_DST] = {
3608 		.name = "set_mac_dst",
3609 		.help = "set destination mac address",
3610 		.priv = PRIV_ACTION(SET_MAC_DST,
3611 			sizeof(struct rte_flow_action_set_mac)),
3612 		.next = NEXT(action_set_mac_dst),
3613 		.call = parse_vc,
3614 	},
3615 	[ACTION_SET_MAC_DST_MAC_DST] = {
3616 		.name = "mac_addr",
3617 		.help = "new destination mac address to set",
3618 		.next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
3619 		.args = ARGS(ARGS_ENTRY_HTON
3620 			     (struct rte_flow_action_set_mac, mac_addr)),
3621 		.call = parse_vc_conf,
3622 	},
3623 	[ACTION_INC_TCP_SEQ] = {
3624 		.name = "inc_tcp_seq",
3625 		.help = "increase TCP sequence number",
3626 		.priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
3627 		.next = NEXT(action_inc_tcp_seq),
3628 		.call = parse_vc,
3629 	},
3630 	[ACTION_INC_TCP_SEQ_VALUE] = {
3631 		.name = "value",
3632 		.help = "the value to increase TCP sequence number by",
3633 		.next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(UNSIGNED)),
3634 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3635 		.call = parse_vc_conf,
3636 	},
3637 	[ACTION_DEC_TCP_SEQ] = {
3638 		.name = "dec_tcp_seq",
3639 		.help = "decrease TCP sequence number",
3640 		.priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
3641 		.next = NEXT(action_dec_tcp_seq),
3642 		.call = parse_vc,
3643 	},
3644 	[ACTION_DEC_TCP_SEQ_VALUE] = {
3645 		.name = "value",
3646 		.help = "the value to decrease TCP sequence number by",
3647 		.next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(UNSIGNED)),
3648 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3649 		.call = parse_vc_conf,
3650 	},
3651 	[ACTION_INC_TCP_ACK] = {
3652 		.name = "inc_tcp_ack",
3653 		.help = "increase TCP acknowledgment number",
3654 		.priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
3655 		.next = NEXT(action_inc_tcp_ack),
3656 		.call = parse_vc,
3657 	},
3658 	[ACTION_INC_TCP_ACK_VALUE] = {
3659 		.name = "value",
3660 		.help = "the value to increase TCP acknowledgment number by",
3661 		.next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(UNSIGNED)),
3662 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3663 		.call = parse_vc_conf,
3664 	},
3665 	[ACTION_DEC_TCP_ACK] = {
3666 		.name = "dec_tcp_ack",
3667 		.help = "decrease TCP acknowledgment number",
3668 		.priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
3669 		.next = NEXT(action_dec_tcp_ack),
3670 		.call = parse_vc,
3671 	},
3672 	[ACTION_DEC_TCP_ACK_VALUE] = {
3673 		.name = "value",
3674 		.help = "the value to decrease TCP acknowledgment number by",
3675 		.next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(UNSIGNED)),
3676 		.args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
3677 		.call = parse_vc_conf,
3678 	},
3679 	[ACTION_RAW_ENCAP] = {
3680 		.name = "raw_encap",
3681 		.help = "encapsulation data, defined by set raw_encap",
3682 		.priv = PRIV_ACTION(RAW_ENCAP,
3683 			sizeof(struct action_raw_encap_data)),
3684 		.next = NEXT(action_raw_encap),
3685 		.call = parse_vc_action_raw_encap,
3686 	},
3687 	[ACTION_RAW_ENCAP_INDEX] = {
3688 		.name = "index",
3689 		.help = "the index of raw_encap_confs",
3690 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
3691 	},
3692 	[ACTION_RAW_ENCAP_INDEX_VALUE] = {
3693 		.name = "{index}",
3694 		.type = "UNSIGNED",
3695 		.help = "unsigned integer value",
3696 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3697 		.call = parse_vc_action_raw_encap_index,
3698 		.comp = comp_set_raw_index,
3699 	},
3700 	[ACTION_RAW_DECAP] = {
3701 		.name = "raw_decap",
3702 		.help = "decapsulation data, defined by set raw_encap",
3703 		.priv = PRIV_ACTION(RAW_DECAP,
3704 			sizeof(struct action_raw_decap_data)),
3705 		.next = NEXT(action_raw_decap),
3706 		.call = parse_vc_action_raw_decap,
3707 	},
3708 	[ACTION_RAW_DECAP_INDEX] = {
3709 		.name = "index",
3710 		.help = "the index of raw_encap_confs",
3711 		.next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
3712 	},
3713 	[ACTION_RAW_DECAP_INDEX_VALUE] = {
3714 		.name = "{index}",
3715 		.type = "UNSIGNED",
3716 		.help = "unsigned integer value",
3717 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
3718 		.call = parse_vc_action_raw_decap_index,
3719 		.comp = comp_set_raw_index,
3720 	},
3721 	/* Top level command. */
3722 	[SET] = {
3723 		.name = "set",
3724 		.help = "set raw encap/decap data",
3725 		.type = "set raw_encap|raw_decap <index> <pattern>",
3726 		.next = NEXT(NEXT_ENTRY
3727 			     (SET_RAW_ENCAP,
3728 			      SET_RAW_DECAP)),
3729 		.call = parse_set_init,
3730 	},
3731 	/* Sub-level commands. */
3732 	[SET_RAW_ENCAP] = {
3733 		.name = "raw_encap",
3734 		.help = "set raw encap data",
3735 		.next = NEXT(next_set_raw),
3736 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3737 				(offsetof(struct buffer, port),
3738 				 sizeof(((struct buffer *)0)->port),
3739 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
3740 		.call = parse_set_raw_encap_decap,
3741 	},
3742 	[SET_RAW_DECAP] = {
3743 		.name = "raw_decap",
3744 		.help = "set raw decap data",
3745 		.next = NEXT(next_set_raw),
3746 		.args = ARGS(ARGS_ENTRY_ARB_BOUNDED
3747 				(offsetof(struct buffer, port),
3748 				 sizeof(((struct buffer *)0)->port),
3749 				 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
3750 		.call = parse_set_raw_encap_decap,
3751 	},
3752 	[SET_RAW_INDEX] = {
3753 		.name = "{index}",
3754 		.type = "UNSIGNED",
3755 		.help = "index of raw_encap/raw_decap data",
3756 		.next = NEXT(next_item),
3757 		.call = parse_port,
3758 	},
3759 	[ACTION_SET_TAG] = {
3760 		.name = "set_tag",
3761 		.help = "set tag",
3762 		.priv = PRIV_ACTION(SET_TAG,
3763 			sizeof(struct rte_flow_action_set_tag)),
3764 		.next = NEXT(action_set_tag),
3765 		.call = parse_vc,
3766 	},
3767 	[ACTION_SET_TAG_INDEX] = {
3768 		.name = "index",
3769 		.help = "index of tag array",
3770 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3771 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
3772 		.call = parse_vc_conf,
3773 	},
3774 	[ACTION_SET_TAG_DATA] = {
3775 		.name = "data",
3776 		.help = "tag value",
3777 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3778 		.args = ARGS(ARGS_ENTRY
3779 			     (struct rte_flow_action_set_tag, data)),
3780 		.call = parse_vc_conf,
3781 	},
3782 	[ACTION_SET_TAG_MASK] = {
3783 		.name = "mask",
3784 		.help = "mask for tag value",
3785 		.next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
3786 		.args = ARGS(ARGS_ENTRY
3787 			     (struct rte_flow_action_set_tag, mask)),
3788 		.call = parse_vc_conf,
3789 	},
3790 	[ACTION_SET_META] = {
3791 		.name = "set_meta",
3792 		.help = "set metadata",
3793 		.priv = PRIV_ACTION(SET_META,
3794 			sizeof(struct rte_flow_action_set_meta)),
3795 		.next = NEXT(action_set_meta),
3796 		.call = parse_vc_action_set_meta,
3797 	},
3798 	[ACTION_SET_META_DATA] = {
3799 		.name = "data",
3800 		.help = "metadata value",
3801 		.next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
3802 		.args = ARGS(ARGS_ENTRY
3803 			     (struct rte_flow_action_set_meta, data)),
3804 		.call = parse_vc_conf,
3805 	},
3806 	[ACTION_SET_META_MASK] = {
3807 		.name = "mask",
3808 		.help = "mask for metadata value",
3809 		.next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
3810 		.args = ARGS(ARGS_ENTRY
3811 			     (struct rte_flow_action_set_meta, mask)),
3812 		.call = parse_vc_conf,
3813 	},
3814 	[ACTION_SET_IPV4_DSCP] = {
3815 		.name = "set_ipv4_dscp",
3816 		.help = "set DSCP value",
3817 		.priv = PRIV_ACTION(SET_IPV4_DSCP,
3818 			sizeof(struct rte_flow_action_set_dscp)),
3819 		.next = NEXT(action_set_ipv4_dscp),
3820 		.call = parse_vc,
3821 	},
3822 	[ACTION_SET_IPV4_DSCP_VALUE] = {
3823 		.name = "dscp_value",
3824 		.help = "new IPv4 DSCP value to set",
3825 		.next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(UNSIGNED)),
3826 		.args = ARGS(ARGS_ENTRY
3827 			     (struct rte_flow_action_set_dscp, dscp)),
3828 		.call = parse_vc_conf,
3829 	},
3830 	[ACTION_SET_IPV6_DSCP] = {
3831 		.name = "set_ipv6_dscp",
3832 		.help = "set DSCP value",
3833 		.priv = PRIV_ACTION(SET_IPV6_DSCP,
3834 			sizeof(struct rte_flow_action_set_dscp)),
3835 		.next = NEXT(action_set_ipv6_dscp),
3836 		.call = parse_vc,
3837 	},
3838 	[ACTION_SET_IPV6_DSCP_VALUE] = {
3839 		.name = "dscp_value",
3840 		.help = "new IPv6 DSCP value to set",
3841 		.next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(UNSIGNED)),
3842 		.args = ARGS(ARGS_ENTRY
3843 			     (struct rte_flow_action_set_dscp, dscp)),
3844 		.call = parse_vc_conf,
3845 	},
3846 	[ACTION_AGE] = {
3847 		.name = "age",
3848 		.help = "set a specific metadata header",
3849 		.next = NEXT(action_age),
3850 		.priv = PRIV_ACTION(AGE,
3851 			sizeof(struct rte_flow_action_age)),
3852 		.call = parse_vc,
3853 	},
3854 	[ACTION_AGE_TIMEOUT] = {
3855 		.name = "timeout",
3856 		.help = "flow age timeout value",
3857 		.args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
3858 					   timeout, 24)),
3859 		.next = NEXT(action_age, NEXT_ENTRY(UNSIGNED)),
3860 		.call = parse_vc_conf,
3861 	},
3862 };
3863 
3864 /** Remove and return last entry from argument stack. */
3865 static const struct arg *
3866 pop_args(struct context *ctx)
3867 {
3868 	return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
3869 }
3870 
3871 /** Add entry on top of the argument stack. */
3872 static int
3873 push_args(struct context *ctx, const struct arg *arg)
3874 {
3875 	if (ctx->args_num == CTX_STACK_SIZE)
3876 		return -1;
3877 	ctx->args[ctx->args_num++] = arg;
3878 	return 0;
3879 }
3880 
3881 /** Spread value into buffer according to bit-mask. */
3882 static size_t
3883 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
3884 {
3885 	uint32_t i = arg->size;
3886 	uint32_t end = 0;
3887 	int sub = 1;
3888 	int add = 0;
3889 	size_t len = 0;
3890 
3891 	if (!arg->mask)
3892 		return 0;
3893 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3894 	if (!arg->hton) {
3895 		i = 0;
3896 		end = arg->size;
3897 		sub = 0;
3898 		add = 1;
3899 	}
3900 #endif
3901 	while (i != end) {
3902 		unsigned int shift = 0;
3903 		uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
3904 
3905 		for (shift = 0; arg->mask[i] >> shift; ++shift) {
3906 			if (!(arg->mask[i] & (1 << shift)))
3907 				continue;
3908 			++len;
3909 			if (!dst)
3910 				continue;
3911 			*buf &= ~(1 << shift);
3912 			*buf |= (val & 1) << shift;
3913 			val >>= 1;
3914 		}
3915 		i += add;
3916 	}
3917 	return len;
3918 }
3919 
3920 /** Compare a string with a partial one of a given length. */
3921 static int
3922 strcmp_partial(const char *full, const char *partial, size_t partial_len)
3923 {
3924 	int r = strncmp(full, partial, partial_len);
3925 
3926 	if (r)
3927 		return r;
3928 	if (strlen(full) <= partial_len)
3929 		return 0;
3930 	return full[partial_len];
3931 }
3932 
3933 /**
3934  * Parse a prefix length and generate a bit-mask.
3935  *
3936  * Last argument (ctx->args) is retrieved to determine mask size, storage
3937  * location and whether the result must use network byte ordering.
3938  */
3939 static int
3940 parse_prefix(struct context *ctx, const struct token *token,
3941 	     const char *str, unsigned int len,
3942 	     void *buf, unsigned int size)
3943 {
3944 	const struct arg *arg = pop_args(ctx);
3945 	static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
3946 	char *end;
3947 	uintmax_t u;
3948 	unsigned int bytes;
3949 	unsigned int extra;
3950 
3951 	(void)token;
3952 	/* Argument is expected. */
3953 	if (!arg)
3954 		return -1;
3955 	errno = 0;
3956 	u = strtoumax(str, &end, 0);
3957 	if (errno || (size_t)(end - str) != len)
3958 		goto error;
3959 	if (arg->mask) {
3960 		uintmax_t v = 0;
3961 
3962 		extra = arg_entry_bf_fill(NULL, 0, arg);
3963 		if (u > extra)
3964 			goto error;
3965 		if (!ctx->object)
3966 			return len;
3967 		extra -= u;
3968 		while (u--)
3969 			(v <<= 1, v |= 1);
3970 		v <<= extra;
3971 		if (!arg_entry_bf_fill(ctx->object, v, arg) ||
3972 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
3973 			goto error;
3974 		return len;
3975 	}
3976 	bytes = u / 8;
3977 	extra = u % 8;
3978 	size = arg->size;
3979 	if (bytes > size || bytes + !!extra > size)
3980 		goto error;
3981 	if (!ctx->object)
3982 		return len;
3983 	buf = (uint8_t *)ctx->object + arg->offset;
3984 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3985 	if (!arg->hton) {
3986 		memset((uint8_t *)buf + size - bytes, 0xff, bytes);
3987 		memset(buf, 0x00, size - bytes);
3988 		if (extra)
3989 			((uint8_t *)buf)[size - bytes - 1] = conv[extra];
3990 	} else
3991 #endif
3992 	{
3993 		memset(buf, 0xff, bytes);
3994 		memset((uint8_t *)buf + bytes, 0x00, size - bytes);
3995 		if (extra)
3996 			((uint8_t *)buf)[bytes] = conv[extra];
3997 	}
3998 	if (ctx->objmask)
3999 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4000 	return len;
4001 error:
4002 	push_args(ctx, arg);
4003 	return -1;
4004 }
4005 
4006 /** Default parsing function for token name matching. */
4007 static int
4008 parse_default(struct context *ctx, const struct token *token,
4009 	      const char *str, unsigned int len,
4010 	      void *buf, unsigned int size)
4011 {
4012 	(void)ctx;
4013 	(void)buf;
4014 	(void)size;
4015 	if (strcmp_partial(token->name, str, len))
4016 		return -1;
4017 	return len;
4018 }
4019 
4020 /** Parse flow command, initialize output buffer for subsequent tokens. */
4021 static int
4022 parse_init(struct context *ctx, const struct token *token,
4023 	   const char *str, unsigned int len,
4024 	   void *buf, unsigned int size)
4025 {
4026 	struct buffer *out = buf;
4027 
4028 	/* Token name must match. */
4029 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4030 		return -1;
4031 	/* Nothing else to do if there is no buffer. */
4032 	if (!out)
4033 		return len;
4034 	/* Make sure buffer is large enough. */
4035 	if (size < sizeof(*out))
4036 		return -1;
4037 	/* Initialize buffer. */
4038 	memset(out, 0x00, sizeof(*out));
4039 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
4040 	ctx->objdata = 0;
4041 	ctx->object = out;
4042 	ctx->objmask = NULL;
4043 	return len;
4044 }
4045 
4046 /** Parse tokens for validate/create commands. */
4047 static int
4048 parse_vc(struct context *ctx, const struct token *token,
4049 	 const char *str, unsigned int len,
4050 	 void *buf, unsigned int size)
4051 {
4052 	struct buffer *out = buf;
4053 	uint8_t *data;
4054 	uint32_t data_size;
4055 
4056 	/* Token name must match. */
4057 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4058 		return -1;
4059 	/* Nothing else to do if there is no buffer. */
4060 	if (!out)
4061 		return len;
4062 	if (!out->command) {
4063 		if (ctx->curr != VALIDATE && ctx->curr != CREATE)
4064 			return -1;
4065 		if (sizeof(*out) > size)
4066 			return -1;
4067 		out->command = ctx->curr;
4068 		ctx->objdata = 0;
4069 		ctx->object = out;
4070 		ctx->objmask = NULL;
4071 		out->args.vc.data = (uint8_t *)out + size;
4072 		return len;
4073 	}
4074 	ctx->objdata = 0;
4075 	ctx->object = &out->args.vc.attr;
4076 	ctx->objmask = NULL;
4077 	switch (ctx->curr) {
4078 	case GROUP:
4079 	case PRIORITY:
4080 		return len;
4081 	case INGRESS:
4082 		out->args.vc.attr.ingress = 1;
4083 		return len;
4084 	case EGRESS:
4085 		out->args.vc.attr.egress = 1;
4086 		return len;
4087 	case TRANSFER:
4088 		out->args.vc.attr.transfer = 1;
4089 		return len;
4090 	case PATTERN:
4091 		out->args.vc.pattern =
4092 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4093 					       sizeof(double));
4094 		ctx->object = out->args.vc.pattern;
4095 		ctx->objmask = NULL;
4096 		return len;
4097 	case ACTIONS:
4098 		out->args.vc.actions =
4099 			(void *)RTE_ALIGN_CEIL((uintptr_t)
4100 					       (out->args.vc.pattern +
4101 						out->args.vc.pattern_n),
4102 					       sizeof(double));
4103 		ctx->object = out->args.vc.actions;
4104 		ctx->objmask = NULL;
4105 		return len;
4106 	default:
4107 		if (!token->priv)
4108 			return -1;
4109 		break;
4110 	}
4111 	if (!out->args.vc.actions) {
4112 		const struct parse_item_priv *priv = token->priv;
4113 		struct rte_flow_item *item =
4114 			out->args.vc.pattern + out->args.vc.pattern_n;
4115 
4116 		data_size = priv->size * 3; /* spec, last, mask */
4117 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
4118 					       (out->args.vc.data - data_size),
4119 					       sizeof(double));
4120 		if ((uint8_t *)item + sizeof(*item) > data)
4121 			return -1;
4122 		*item = (struct rte_flow_item){
4123 			.type = priv->type,
4124 		};
4125 		++out->args.vc.pattern_n;
4126 		ctx->object = item;
4127 		ctx->objmask = NULL;
4128 	} else {
4129 		const struct parse_action_priv *priv = token->priv;
4130 		struct rte_flow_action *action =
4131 			out->args.vc.actions + out->args.vc.actions_n;
4132 
4133 		data_size = priv->size; /* configuration */
4134 		data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
4135 					       (out->args.vc.data - data_size),
4136 					       sizeof(double));
4137 		if ((uint8_t *)action + sizeof(*action) > data)
4138 			return -1;
4139 		*action = (struct rte_flow_action){
4140 			.type = priv->type,
4141 			.conf = data_size ? data : NULL,
4142 		};
4143 		++out->args.vc.actions_n;
4144 		ctx->object = action;
4145 		ctx->objmask = NULL;
4146 	}
4147 	memset(data, 0, data_size);
4148 	out->args.vc.data = data;
4149 	ctx->objdata = data_size;
4150 	return len;
4151 }
4152 
4153 /** Parse pattern item parameter type. */
4154 static int
4155 parse_vc_spec(struct context *ctx, const struct token *token,
4156 	      const char *str, unsigned int len,
4157 	      void *buf, unsigned int size)
4158 {
4159 	struct buffer *out = buf;
4160 	struct rte_flow_item *item;
4161 	uint32_t data_size;
4162 	int index;
4163 	int objmask = 0;
4164 
4165 	(void)size;
4166 	/* Token name must match. */
4167 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4168 		return -1;
4169 	/* Parse parameter types. */
4170 	switch (ctx->curr) {
4171 		static const enum index prefix[] = NEXT_ENTRY(PREFIX);
4172 
4173 	case ITEM_PARAM_IS:
4174 		index = 0;
4175 		objmask = 1;
4176 		break;
4177 	case ITEM_PARAM_SPEC:
4178 		index = 0;
4179 		break;
4180 	case ITEM_PARAM_LAST:
4181 		index = 1;
4182 		break;
4183 	case ITEM_PARAM_PREFIX:
4184 		/* Modify next token to expect a prefix. */
4185 		if (ctx->next_num < 2)
4186 			return -1;
4187 		ctx->next[ctx->next_num - 2] = prefix;
4188 		/* Fall through. */
4189 	case ITEM_PARAM_MASK:
4190 		index = 2;
4191 		break;
4192 	default:
4193 		return -1;
4194 	}
4195 	/* Nothing else to do if there is no buffer. */
4196 	if (!out)
4197 		return len;
4198 	if (!out->args.vc.pattern_n)
4199 		return -1;
4200 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
4201 	data_size = ctx->objdata / 3; /* spec, last, mask */
4202 	/* Point to selected object. */
4203 	ctx->object = out->args.vc.data + (data_size * index);
4204 	if (objmask) {
4205 		ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
4206 		item->mask = ctx->objmask;
4207 	} else
4208 		ctx->objmask = NULL;
4209 	/* Update relevant item pointer. */
4210 	*((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
4211 		ctx->object;
4212 	return len;
4213 }
4214 
4215 /** Parse action configuration field. */
4216 static int
4217 parse_vc_conf(struct context *ctx, const struct token *token,
4218 	      const char *str, unsigned int len,
4219 	      void *buf, unsigned int size)
4220 {
4221 	struct buffer *out = buf;
4222 
4223 	(void)size;
4224 	/* Token name must match. */
4225 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4226 		return -1;
4227 	/* Nothing else to do if there is no buffer. */
4228 	if (!out)
4229 		return len;
4230 	/* Point to selected object. */
4231 	ctx->object = out->args.vc.data;
4232 	ctx->objmask = NULL;
4233 	return len;
4234 }
4235 
4236 /** Parse eCPRI common header type field. */
4237 static int
4238 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token,
4239 			 const char *str, unsigned int len,
4240 			 void *buf, unsigned int size)
4241 {
4242 	struct rte_flow_item_ecpri *ecpri;
4243 	struct rte_flow_item_ecpri *ecpri_mask;
4244 	struct rte_flow_item *item;
4245 	uint32_t data_size;
4246 	uint8_t msg_type;
4247 	struct buffer *out = buf;
4248 	const struct arg *arg;
4249 
4250 	(void)size;
4251 	/* Token name must match. */
4252 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4253 		return -1;
4254 	switch (ctx->curr) {
4255 	case ITEM_ECPRI_COMMON_TYPE_IQ_DATA:
4256 		msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA;
4257 		break;
4258 	case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL:
4259 		msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL;
4260 		break;
4261 	case ITEM_ECPRI_COMMON_TYPE_DLY_MSR:
4262 		msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR;
4263 		break;
4264 	default:
4265 		return -1;
4266 	}
4267 	if (!ctx->object)
4268 		return len;
4269 	arg = pop_args(ctx);
4270 	if (!arg)
4271 		return -1;
4272 	ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data;
4273 	ecpri->hdr.common.type = msg_type;
4274 	data_size = ctx->objdata / 3; /* spec, last, mask */
4275 	ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data +
4276 						    (data_size * 2));
4277 	ecpri_mask->hdr.common.type = 0xFF;
4278 	if (arg->hton) {
4279 		ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32);
4280 		ecpri_mask->hdr.common.u32 =
4281 				rte_cpu_to_be_32(ecpri_mask->hdr.common.u32);
4282 	}
4283 	item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
4284 	item->spec = ecpri;
4285 	item->mask = ecpri_mask;
4286 	return len;
4287 }
4288 
4289 /** Parse RSS action. */
4290 static int
4291 parse_vc_action_rss(struct context *ctx, const struct token *token,
4292 		    const char *str, unsigned int len,
4293 		    void *buf, unsigned int size)
4294 {
4295 	struct buffer *out = buf;
4296 	struct rte_flow_action *action;
4297 	struct action_rss_data *action_rss_data;
4298 	unsigned int i;
4299 	int ret;
4300 
4301 	ret = parse_vc(ctx, token, str, len, buf, size);
4302 	if (ret < 0)
4303 		return ret;
4304 	/* Nothing else to do if there is no buffer. */
4305 	if (!out)
4306 		return ret;
4307 	if (!out->args.vc.actions_n)
4308 		return -1;
4309 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4310 	/* Point to selected object. */
4311 	ctx->object = out->args.vc.data;
4312 	ctx->objmask = NULL;
4313 	/* Set up default configuration. */
4314 	action_rss_data = ctx->object;
4315 	*action_rss_data = (struct action_rss_data){
4316 		.conf = (struct rte_flow_action_rss){
4317 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
4318 			.level = 0,
4319 			.types = rss_hf,
4320 			.key_len = sizeof(action_rss_data->key),
4321 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
4322 			.key = action_rss_data->key,
4323 			.queue = action_rss_data->queue,
4324 		},
4325 		.key = "testpmd's default RSS hash key, "
4326 			"override it for better balancing",
4327 		.queue = { 0 },
4328 	};
4329 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
4330 		action_rss_data->queue[i] = i;
4331 	if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
4332 	    ctx->port != (portid_t)RTE_PORT_ALL) {
4333 		struct rte_eth_dev_info info;
4334 		int ret2;
4335 
4336 		ret2 = rte_eth_dev_info_get(ctx->port, &info);
4337 		if (ret2 != 0)
4338 			return ret2;
4339 
4340 		action_rss_data->conf.key_len =
4341 			RTE_MIN(sizeof(action_rss_data->key),
4342 				info.hash_key_size);
4343 	}
4344 	action->conf = &action_rss_data->conf;
4345 	return ret;
4346 }
4347 
4348 /**
4349  * Parse func field for RSS action.
4350  *
4351  * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
4352  * ACTION_RSS_FUNC_* index that called this function.
4353  */
4354 static int
4355 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
4356 			 const char *str, unsigned int len,
4357 			 void *buf, unsigned int size)
4358 {
4359 	struct action_rss_data *action_rss_data;
4360 	enum rte_eth_hash_function func;
4361 
4362 	(void)buf;
4363 	(void)size;
4364 	/* Token name must match. */
4365 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4366 		return -1;
4367 	switch (ctx->curr) {
4368 	case ACTION_RSS_FUNC_DEFAULT:
4369 		func = RTE_ETH_HASH_FUNCTION_DEFAULT;
4370 		break;
4371 	case ACTION_RSS_FUNC_TOEPLITZ:
4372 		func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
4373 		break;
4374 	case ACTION_RSS_FUNC_SIMPLE_XOR:
4375 		func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
4376 		break;
4377 	case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
4378 		func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
4379 		break;
4380 	default:
4381 		return -1;
4382 	}
4383 	if (!ctx->object)
4384 		return len;
4385 	action_rss_data = ctx->object;
4386 	action_rss_data->conf.func = func;
4387 	return len;
4388 }
4389 
4390 /**
4391  * Parse type field for RSS action.
4392  *
4393  * Valid tokens are type field names and the "end" token.
4394  */
4395 static int
4396 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
4397 			  const char *str, unsigned int len,
4398 			  void *buf, unsigned int size)
4399 {
4400 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
4401 	struct action_rss_data *action_rss_data;
4402 	unsigned int i;
4403 
4404 	(void)token;
4405 	(void)buf;
4406 	(void)size;
4407 	if (ctx->curr != ACTION_RSS_TYPE)
4408 		return -1;
4409 	if (!(ctx->objdata >> 16) && ctx->object) {
4410 		action_rss_data = ctx->object;
4411 		action_rss_data->conf.types = 0;
4412 	}
4413 	if (!strcmp_partial("end", str, len)) {
4414 		ctx->objdata &= 0xffff;
4415 		return len;
4416 	}
4417 	for (i = 0; rss_type_table[i].str; ++i)
4418 		if (!strcmp_partial(rss_type_table[i].str, str, len))
4419 			break;
4420 	if (!rss_type_table[i].str)
4421 		return -1;
4422 	ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
4423 	/* Repeat token. */
4424 	if (ctx->next_num == RTE_DIM(ctx->next))
4425 		return -1;
4426 	ctx->next[ctx->next_num++] = next;
4427 	if (!ctx->object)
4428 		return len;
4429 	action_rss_data = ctx->object;
4430 	action_rss_data->conf.types |= rss_type_table[i].rss_type;
4431 	return len;
4432 }
4433 
4434 /**
4435  * Parse queue field for RSS action.
4436  *
4437  * Valid tokens are queue indices and the "end" token.
4438  */
4439 static int
4440 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
4441 			  const char *str, unsigned int len,
4442 			  void *buf, unsigned int size)
4443 {
4444 	static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
4445 	struct action_rss_data *action_rss_data;
4446 	const struct arg *arg;
4447 	int ret;
4448 	int i;
4449 
4450 	(void)token;
4451 	(void)buf;
4452 	(void)size;
4453 	if (ctx->curr != ACTION_RSS_QUEUE)
4454 		return -1;
4455 	i = ctx->objdata >> 16;
4456 	if (!strcmp_partial("end", str, len)) {
4457 		ctx->objdata &= 0xffff;
4458 		goto end;
4459 	}
4460 	if (i >= ACTION_RSS_QUEUE_NUM)
4461 		return -1;
4462 	arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
4463 			     i * sizeof(action_rss_data->queue[i]),
4464 			     sizeof(action_rss_data->queue[i]));
4465 	if (push_args(ctx, arg))
4466 		return -1;
4467 	ret = parse_int(ctx, token, str, len, NULL, 0);
4468 	if (ret < 0) {
4469 		pop_args(ctx);
4470 		return -1;
4471 	}
4472 	++i;
4473 	ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
4474 	/* Repeat token. */
4475 	if (ctx->next_num == RTE_DIM(ctx->next))
4476 		return -1;
4477 	ctx->next[ctx->next_num++] = next;
4478 end:
4479 	if (!ctx->object)
4480 		return len;
4481 	action_rss_data = ctx->object;
4482 	action_rss_data->conf.queue_num = i;
4483 	action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
4484 	return len;
4485 }
4486 
4487 /** Parse VXLAN encap action. */
4488 static int
4489 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
4490 			    const char *str, unsigned int len,
4491 			    void *buf, unsigned int size)
4492 {
4493 	struct buffer *out = buf;
4494 	struct rte_flow_action *action;
4495 	struct action_vxlan_encap_data *action_vxlan_encap_data;
4496 	int ret;
4497 
4498 	ret = parse_vc(ctx, token, str, len, buf, size);
4499 	if (ret < 0)
4500 		return ret;
4501 	/* Nothing else to do if there is no buffer. */
4502 	if (!out)
4503 		return ret;
4504 	if (!out->args.vc.actions_n)
4505 		return -1;
4506 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4507 	/* Point to selected object. */
4508 	ctx->object = out->args.vc.data;
4509 	ctx->objmask = NULL;
4510 	/* Set up default configuration. */
4511 	action_vxlan_encap_data = ctx->object;
4512 	*action_vxlan_encap_data = (struct action_vxlan_encap_data){
4513 		.conf = (struct rte_flow_action_vxlan_encap){
4514 			.definition = action_vxlan_encap_data->items,
4515 		},
4516 		.items = {
4517 			{
4518 				.type = RTE_FLOW_ITEM_TYPE_ETH,
4519 				.spec = &action_vxlan_encap_data->item_eth,
4520 				.mask = &rte_flow_item_eth_mask,
4521 			},
4522 			{
4523 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
4524 				.spec = &action_vxlan_encap_data->item_vlan,
4525 				.mask = &rte_flow_item_vlan_mask,
4526 			},
4527 			{
4528 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
4529 				.spec = &action_vxlan_encap_data->item_ipv4,
4530 				.mask = &rte_flow_item_ipv4_mask,
4531 			},
4532 			{
4533 				.type = RTE_FLOW_ITEM_TYPE_UDP,
4534 				.spec = &action_vxlan_encap_data->item_udp,
4535 				.mask = &rte_flow_item_udp_mask,
4536 			},
4537 			{
4538 				.type = RTE_FLOW_ITEM_TYPE_VXLAN,
4539 				.spec = &action_vxlan_encap_data->item_vxlan,
4540 				.mask = &rte_flow_item_vxlan_mask,
4541 			},
4542 			{
4543 				.type = RTE_FLOW_ITEM_TYPE_END,
4544 			},
4545 		},
4546 		.item_eth.type = 0,
4547 		.item_vlan = {
4548 			.tci = vxlan_encap_conf.vlan_tci,
4549 			.inner_type = 0,
4550 		},
4551 		.item_ipv4.hdr = {
4552 			.src_addr = vxlan_encap_conf.ipv4_src,
4553 			.dst_addr = vxlan_encap_conf.ipv4_dst,
4554 		},
4555 		.item_udp.hdr = {
4556 			.src_port = vxlan_encap_conf.udp_src,
4557 			.dst_port = vxlan_encap_conf.udp_dst,
4558 		},
4559 		.item_vxlan.flags = 0,
4560 	};
4561 	memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
4562 	       vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4563 	memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
4564 	       vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4565 	if (!vxlan_encap_conf.select_ipv4) {
4566 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
4567 		       &vxlan_encap_conf.ipv6_src,
4568 		       sizeof(vxlan_encap_conf.ipv6_src));
4569 		memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
4570 		       &vxlan_encap_conf.ipv6_dst,
4571 		       sizeof(vxlan_encap_conf.ipv6_dst));
4572 		action_vxlan_encap_data->items[2] = (struct rte_flow_item){
4573 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
4574 			.spec = &action_vxlan_encap_data->item_ipv6,
4575 			.mask = &rte_flow_item_ipv6_mask,
4576 		};
4577 	}
4578 	if (!vxlan_encap_conf.select_vlan)
4579 		action_vxlan_encap_data->items[1].type =
4580 			RTE_FLOW_ITEM_TYPE_VOID;
4581 	if (vxlan_encap_conf.select_tos_ttl) {
4582 		if (vxlan_encap_conf.select_ipv4) {
4583 			static struct rte_flow_item_ipv4 ipv4_mask_tos;
4584 
4585 			memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
4586 			       sizeof(ipv4_mask_tos));
4587 			ipv4_mask_tos.hdr.type_of_service = 0xff;
4588 			ipv4_mask_tos.hdr.time_to_live = 0xff;
4589 			action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
4590 					vxlan_encap_conf.ip_tos;
4591 			action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
4592 					vxlan_encap_conf.ip_ttl;
4593 			action_vxlan_encap_data->items[2].mask =
4594 							&ipv4_mask_tos;
4595 		} else {
4596 			static struct rte_flow_item_ipv6 ipv6_mask_tos;
4597 
4598 			memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
4599 			       sizeof(ipv6_mask_tos));
4600 			ipv6_mask_tos.hdr.vtc_flow |=
4601 				RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
4602 			ipv6_mask_tos.hdr.hop_limits = 0xff;
4603 			action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
4604 				rte_cpu_to_be_32
4605 					((uint32_t)vxlan_encap_conf.ip_tos <<
4606 					 RTE_IPV6_HDR_TC_SHIFT);
4607 			action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
4608 					vxlan_encap_conf.ip_ttl;
4609 			action_vxlan_encap_data->items[2].mask =
4610 							&ipv6_mask_tos;
4611 		}
4612 	}
4613 	memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
4614 	       RTE_DIM(vxlan_encap_conf.vni));
4615 	action->conf = &action_vxlan_encap_data->conf;
4616 	return ret;
4617 }
4618 
4619 /** Parse NVGRE encap action. */
4620 static int
4621 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
4622 			    const char *str, unsigned int len,
4623 			    void *buf, unsigned int size)
4624 {
4625 	struct buffer *out = buf;
4626 	struct rte_flow_action *action;
4627 	struct action_nvgre_encap_data *action_nvgre_encap_data;
4628 	int ret;
4629 
4630 	ret = parse_vc(ctx, token, str, len, buf, size);
4631 	if (ret < 0)
4632 		return ret;
4633 	/* Nothing else to do if there is no buffer. */
4634 	if (!out)
4635 		return ret;
4636 	if (!out->args.vc.actions_n)
4637 		return -1;
4638 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4639 	/* Point to selected object. */
4640 	ctx->object = out->args.vc.data;
4641 	ctx->objmask = NULL;
4642 	/* Set up default configuration. */
4643 	action_nvgre_encap_data = ctx->object;
4644 	*action_nvgre_encap_data = (struct action_nvgre_encap_data){
4645 		.conf = (struct rte_flow_action_nvgre_encap){
4646 			.definition = action_nvgre_encap_data->items,
4647 		},
4648 		.items = {
4649 			{
4650 				.type = RTE_FLOW_ITEM_TYPE_ETH,
4651 				.spec = &action_nvgre_encap_data->item_eth,
4652 				.mask = &rte_flow_item_eth_mask,
4653 			},
4654 			{
4655 				.type = RTE_FLOW_ITEM_TYPE_VLAN,
4656 				.spec = &action_nvgre_encap_data->item_vlan,
4657 				.mask = &rte_flow_item_vlan_mask,
4658 			},
4659 			{
4660 				.type = RTE_FLOW_ITEM_TYPE_IPV4,
4661 				.spec = &action_nvgre_encap_data->item_ipv4,
4662 				.mask = &rte_flow_item_ipv4_mask,
4663 			},
4664 			{
4665 				.type = RTE_FLOW_ITEM_TYPE_NVGRE,
4666 				.spec = &action_nvgre_encap_data->item_nvgre,
4667 				.mask = &rte_flow_item_nvgre_mask,
4668 			},
4669 			{
4670 				.type = RTE_FLOW_ITEM_TYPE_END,
4671 			},
4672 		},
4673 		.item_eth.type = 0,
4674 		.item_vlan = {
4675 			.tci = nvgre_encap_conf.vlan_tci,
4676 			.inner_type = 0,
4677 		},
4678 		.item_ipv4.hdr = {
4679 		       .src_addr = nvgre_encap_conf.ipv4_src,
4680 		       .dst_addr = nvgre_encap_conf.ipv4_dst,
4681 		},
4682 		.item_nvgre.flow_id = 0,
4683 	};
4684 	memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
4685 	       nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4686 	memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
4687 	       nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4688 	if (!nvgre_encap_conf.select_ipv4) {
4689 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
4690 		       &nvgre_encap_conf.ipv6_src,
4691 		       sizeof(nvgre_encap_conf.ipv6_src));
4692 		memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
4693 		       &nvgre_encap_conf.ipv6_dst,
4694 		       sizeof(nvgre_encap_conf.ipv6_dst));
4695 		action_nvgre_encap_data->items[2] = (struct rte_flow_item){
4696 			.type = RTE_FLOW_ITEM_TYPE_IPV6,
4697 			.spec = &action_nvgre_encap_data->item_ipv6,
4698 			.mask = &rte_flow_item_ipv6_mask,
4699 		};
4700 	}
4701 	if (!nvgre_encap_conf.select_vlan)
4702 		action_nvgre_encap_data->items[1].type =
4703 			RTE_FLOW_ITEM_TYPE_VOID;
4704 	memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
4705 	       RTE_DIM(nvgre_encap_conf.tni));
4706 	action->conf = &action_nvgre_encap_data->conf;
4707 	return ret;
4708 }
4709 
4710 /** Parse l2 encap action. */
4711 static int
4712 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
4713 			 const char *str, unsigned int len,
4714 			 void *buf, unsigned int size)
4715 {
4716 	struct buffer *out = buf;
4717 	struct rte_flow_action *action;
4718 	struct action_raw_encap_data *action_encap_data;
4719 	struct rte_flow_item_eth eth = { .type = 0, };
4720 	struct rte_flow_item_vlan vlan = {
4721 		.tci = mplsoudp_encap_conf.vlan_tci,
4722 		.inner_type = 0,
4723 	};
4724 	uint8_t *header;
4725 	int ret;
4726 
4727 	ret = parse_vc(ctx, token, str, len, buf, size);
4728 	if (ret < 0)
4729 		return ret;
4730 	/* Nothing else to do if there is no buffer. */
4731 	if (!out)
4732 		return ret;
4733 	if (!out->args.vc.actions_n)
4734 		return -1;
4735 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4736 	/* Point to selected object. */
4737 	ctx->object = out->args.vc.data;
4738 	ctx->objmask = NULL;
4739 	/* Copy the headers to the buffer. */
4740 	action_encap_data = ctx->object;
4741 	*action_encap_data = (struct action_raw_encap_data) {
4742 		.conf = (struct rte_flow_action_raw_encap){
4743 			.data = action_encap_data->data,
4744 		},
4745 		.data = {},
4746 	};
4747 	header = action_encap_data->data;
4748 	if (l2_encap_conf.select_vlan)
4749 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4750 	else if (l2_encap_conf.select_ipv4)
4751 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4752 	else
4753 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4754 	memcpy(eth.dst.addr_bytes,
4755 	       l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4756 	memcpy(eth.src.addr_bytes,
4757 	       l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4758 	memcpy(header, &eth, sizeof(eth));
4759 	header += sizeof(eth);
4760 	if (l2_encap_conf.select_vlan) {
4761 		if (l2_encap_conf.select_ipv4)
4762 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4763 		else
4764 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4765 		memcpy(header, &vlan, sizeof(vlan));
4766 		header += sizeof(vlan);
4767 	}
4768 	action_encap_data->conf.size = header -
4769 		action_encap_data->data;
4770 	action->conf = &action_encap_data->conf;
4771 	return ret;
4772 }
4773 
4774 /** Parse l2 decap action. */
4775 static int
4776 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
4777 			 const char *str, unsigned int len,
4778 			 void *buf, unsigned int size)
4779 {
4780 	struct buffer *out = buf;
4781 	struct rte_flow_action *action;
4782 	struct action_raw_decap_data *action_decap_data;
4783 	struct rte_flow_item_eth eth = { .type = 0, };
4784 	struct rte_flow_item_vlan vlan = {
4785 		.tci = mplsoudp_encap_conf.vlan_tci,
4786 		.inner_type = 0,
4787 	};
4788 	uint8_t *header;
4789 	int ret;
4790 
4791 	ret = parse_vc(ctx, token, str, len, buf, size);
4792 	if (ret < 0)
4793 		return ret;
4794 	/* Nothing else to do if there is no buffer. */
4795 	if (!out)
4796 		return ret;
4797 	if (!out->args.vc.actions_n)
4798 		return -1;
4799 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4800 	/* Point to selected object. */
4801 	ctx->object = out->args.vc.data;
4802 	ctx->objmask = NULL;
4803 	/* Copy the headers to the buffer. */
4804 	action_decap_data = ctx->object;
4805 	*action_decap_data = (struct action_raw_decap_data) {
4806 		.conf = (struct rte_flow_action_raw_decap){
4807 			.data = action_decap_data->data,
4808 		},
4809 		.data = {},
4810 	};
4811 	header = action_decap_data->data;
4812 	if (l2_decap_conf.select_vlan)
4813 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4814 	memcpy(header, &eth, sizeof(eth));
4815 	header += sizeof(eth);
4816 	if (l2_decap_conf.select_vlan) {
4817 		memcpy(header, &vlan, sizeof(vlan));
4818 		header += sizeof(vlan);
4819 	}
4820 	action_decap_data->conf.size = header -
4821 		action_decap_data->data;
4822 	action->conf = &action_decap_data->conf;
4823 	return ret;
4824 }
4825 
4826 #define ETHER_TYPE_MPLS_UNICAST 0x8847
4827 
4828 /** Parse MPLSOGRE encap action. */
4829 static int
4830 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
4831 			       const char *str, unsigned int len,
4832 			       void *buf, unsigned int size)
4833 {
4834 	struct buffer *out = buf;
4835 	struct rte_flow_action *action;
4836 	struct action_raw_encap_data *action_encap_data;
4837 	struct rte_flow_item_eth eth = { .type = 0, };
4838 	struct rte_flow_item_vlan vlan = {
4839 		.tci = mplsogre_encap_conf.vlan_tci,
4840 		.inner_type = 0,
4841 	};
4842 	struct rte_flow_item_ipv4 ipv4 = {
4843 		.hdr =  {
4844 			.src_addr = mplsogre_encap_conf.ipv4_src,
4845 			.dst_addr = mplsogre_encap_conf.ipv4_dst,
4846 			.next_proto_id = IPPROTO_GRE,
4847 			.version_ihl = RTE_IPV4_VHL_DEF,
4848 			.time_to_live = IPDEFTTL,
4849 		},
4850 	};
4851 	struct rte_flow_item_ipv6 ipv6 = {
4852 		.hdr =  {
4853 			.proto = IPPROTO_GRE,
4854 			.hop_limits = IPDEFTTL,
4855 		},
4856 	};
4857 	struct rte_flow_item_gre gre = {
4858 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
4859 	};
4860 	struct rte_flow_item_mpls mpls = {
4861 		.ttl = 0,
4862 	};
4863 	uint8_t *header;
4864 	int ret;
4865 
4866 	ret = parse_vc(ctx, token, str, len, buf, size);
4867 	if (ret < 0)
4868 		return ret;
4869 	/* Nothing else to do if there is no buffer. */
4870 	if (!out)
4871 		return ret;
4872 	if (!out->args.vc.actions_n)
4873 		return -1;
4874 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4875 	/* Point to selected object. */
4876 	ctx->object = out->args.vc.data;
4877 	ctx->objmask = NULL;
4878 	/* Copy the headers to the buffer. */
4879 	action_encap_data = ctx->object;
4880 	*action_encap_data = (struct action_raw_encap_data) {
4881 		.conf = (struct rte_flow_action_raw_encap){
4882 			.data = action_encap_data->data,
4883 		},
4884 		.data = {},
4885 		.preserve = {},
4886 	};
4887 	header = action_encap_data->data;
4888 	if (mplsogre_encap_conf.select_vlan)
4889 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4890 	else if (mplsogre_encap_conf.select_ipv4)
4891 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4892 	else
4893 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4894 	memcpy(eth.dst.addr_bytes,
4895 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4896 	memcpy(eth.src.addr_bytes,
4897 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4898 	memcpy(header, &eth, sizeof(eth));
4899 	header += sizeof(eth);
4900 	if (mplsogre_encap_conf.select_vlan) {
4901 		if (mplsogre_encap_conf.select_ipv4)
4902 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4903 		else
4904 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4905 		memcpy(header, &vlan, sizeof(vlan));
4906 		header += sizeof(vlan);
4907 	}
4908 	if (mplsogre_encap_conf.select_ipv4) {
4909 		memcpy(header, &ipv4, sizeof(ipv4));
4910 		header += sizeof(ipv4);
4911 	} else {
4912 		memcpy(&ipv6.hdr.src_addr,
4913 		       &mplsogre_encap_conf.ipv6_src,
4914 		       sizeof(mplsogre_encap_conf.ipv6_src));
4915 		memcpy(&ipv6.hdr.dst_addr,
4916 		       &mplsogre_encap_conf.ipv6_dst,
4917 		       sizeof(mplsogre_encap_conf.ipv6_dst));
4918 		memcpy(header, &ipv6, sizeof(ipv6));
4919 		header += sizeof(ipv6);
4920 	}
4921 	memcpy(header, &gre, sizeof(gre));
4922 	header += sizeof(gre);
4923 	memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
4924 	       RTE_DIM(mplsogre_encap_conf.label));
4925 	mpls.label_tc_s[2] |= 0x1;
4926 	memcpy(header, &mpls, sizeof(mpls));
4927 	header += sizeof(mpls);
4928 	action_encap_data->conf.size = header -
4929 		action_encap_data->data;
4930 	action->conf = &action_encap_data->conf;
4931 	return ret;
4932 }
4933 
4934 /** Parse MPLSOGRE decap action. */
4935 static int
4936 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
4937 			       const char *str, unsigned int len,
4938 			       void *buf, unsigned int size)
4939 {
4940 	struct buffer *out = buf;
4941 	struct rte_flow_action *action;
4942 	struct action_raw_decap_data *action_decap_data;
4943 	struct rte_flow_item_eth eth = { .type = 0, };
4944 	struct rte_flow_item_vlan vlan = {.tci = 0};
4945 	struct rte_flow_item_ipv4 ipv4 = {
4946 		.hdr =  {
4947 			.next_proto_id = IPPROTO_GRE,
4948 		},
4949 	};
4950 	struct rte_flow_item_ipv6 ipv6 = {
4951 		.hdr =  {
4952 			.proto = IPPROTO_GRE,
4953 		},
4954 	};
4955 	struct rte_flow_item_gre gre = {
4956 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
4957 	};
4958 	struct rte_flow_item_mpls mpls;
4959 	uint8_t *header;
4960 	int ret;
4961 
4962 	ret = parse_vc(ctx, token, str, len, buf, size);
4963 	if (ret < 0)
4964 		return ret;
4965 	/* Nothing else to do if there is no buffer. */
4966 	if (!out)
4967 		return ret;
4968 	if (!out->args.vc.actions_n)
4969 		return -1;
4970 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
4971 	/* Point to selected object. */
4972 	ctx->object = out->args.vc.data;
4973 	ctx->objmask = NULL;
4974 	/* Copy the headers to the buffer. */
4975 	action_decap_data = ctx->object;
4976 	*action_decap_data = (struct action_raw_decap_data) {
4977 		.conf = (struct rte_flow_action_raw_decap){
4978 			.data = action_decap_data->data,
4979 		},
4980 		.data = {},
4981 	};
4982 	header = action_decap_data->data;
4983 	if (mplsogre_decap_conf.select_vlan)
4984 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
4985 	else if (mplsogre_encap_conf.select_ipv4)
4986 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4987 	else
4988 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
4989 	memcpy(eth.dst.addr_bytes,
4990 	       mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
4991 	memcpy(eth.src.addr_bytes,
4992 	       mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
4993 	memcpy(header, &eth, sizeof(eth));
4994 	header += sizeof(eth);
4995 	if (mplsogre_encap_conf.select_vlan) {
4996 		if (mplsogre_encap_conf.select_ipv4)
4997 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
4998 		else
4999 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5000 		memcpy(header, &vlan, sizeof(vlan));
5001 		header += sizeof(vlan);
5002 	}
5003 	if (mplsogre_encap_conf.select_ipv4) {
5004 		memcpy(header, &ipv4, sizeof(ipv4));
5005 		header += sizeof(ipv4);
5006 	} else {
5007 		memcpy(header, &ipv6, sizeof(ipv6));
5008 		header += sizeof(ipv6);
5009 	}
5010 	memcpy(header, &gre, sizeof(gre));
5011 	header += sizeof(gre);
5012 	memset(&mpls, 0, sizeof(mpls));
5013 	memcpy(header, &mpls, sizeof(mpls));
5014 	header += sizeof(mpls);
5015 	action_decap_data->conf.size = header -
5016 		action_decap_data->data;
5017 	action->conf = &action_decap_data->conf;
5018 	return ret;
5019 }
5020 
5021 /** Parse MPLSOUDP encap action. */
5022 static int
5023 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
5024 			       const char *str, unsigned int len,
5025 			       void *buf, unsigned int size)
5026 {
5027 	struct buffer *out = buf;
5028 	struct rte_flow_action *action;
5029 	struct action_raw_encap_data *action_encap_data;
5030 	struct rte_flow_item_eth eth = { .type = 0, };
5031 	struct rte_flow_item_vlan vlan = {
5032 		.tci = mplsoudp_encap_conf.vlan_tci,
5033 		.inner_type = 0,
5034 	};
5035 	struct rte_flow_item_ipv4 ipv4 = {
5036 		.hdr =  {
5037 			.src_addr = mplsoudp_encap_conf.ipv4_src,
5038 			.dst_addr = mplsoudp_encap_conf.ipv4_dst,
5039 			.next_proto_id = IPPROTO_UDP,
5040 			.version_ihl = RTE_IPV4_VHL_DEF,
5041 			.time_to_live = IPDEFTTL,
5042 		},
5043 	};
5044 	struct rte_flow_item_ipv6 ipv6 = {
5045 		.hdr =  {
5046 			.proto = IPPROTO_UDP,
5047 			.hop_limits = IPDEFTTL,
5048 		},
5049 	};
5050 	struct rte_flow_item_udp udp = {
5051 		.hdr = {
5052 			.src_port = mplsoudp_encap_conf.udp_src,
5053 			.dst_port = mplsoudp_encap_conf.udp_dst,
5054 		},
5055 	};
5056 	struct rte_flow_item_mpls mpls;
5057 	uint8_t *header;
5058 	int ret;
5059 
5060 	ret = parse_vc(ctx, token, str, len, buf, size);
5061 	if (ret < 0)
5062 		return ret;
5063 	/* Nothing else to do if there is no buffer. */
5064 	if (!out)
5065 		return ret;
5066 	if (!out->args.vc.actions_n)
5067 		return -1;
5068 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5069 	/* Point to selected object. */
5070 	ctx->object = out->args.vc.data;
5071 	ctx->objmask = NULL;
5072 	/* Copy the headers to the buffer. */
5073 	action_encap_data = ctx->object;
5074 	*action_encap_data = (struct action_raw_encap_data) {
5075 		.conf = (struct rte_flow_action_raw_encap){
5076 			.data = action_encap_data->data,
5077 		},
5078 		.data = {},
5079 		.preserve = {},
5080 	};
5081 	header = action_encap_data->data;
5082 	if (mplsoudp_encap_conf.select_vlan)
5083 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5084 	else if (mplsoudp_encap_conf.select_ipv4)
5085 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5086 	else
5087 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5088 	memcpy(eth.dst.addr_bytes,
5089 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5090 	memcpy(eth.src.addr_bytes,
5091 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5092 	memcpy(header, &eth, sizeof(eth));
5093 	header += sizeof(eth);
5094 	if (mplsoudp_encap_conf.select_vlan) {
5095 		if (mplsoudp_encap_conf.select_ipv4)
5096 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5097 		else
5098 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5099 		memcpy(header, &vlan, sizeof(vlan));
5100 		header += sizeof(vlan);
5101 	}
5102 	if (mplsoudp_encap_conf.select_ipv4) {
5103 		memcpy(header, &ipv4, sizeof(ipv4));
5104 		header += sizeof(ipv4);
5105 	} else {
5106 		memcpy(&ipv6.hdr.src_addr,
5107 		       &mplsoudp_encap_conf.ipv6_src,
5108 		       sizeof(mplsoudp_encap_conf.ipv6_src));
5109 		memcpy(&ipv6.hdr.dst_addr,
5110 		       &mplsoudp_encap_conf.ipv6_dst,
5111 		       sizeof(mplsoudp_encap_conf.ipv6_dst));
5112 		memcpy(header, &ipv6, sizeof(ipv6));
5113 		header += sizeof(ipv6);
5114 	}
5115 	memcpy(header, &udp, sizeof(udp));
5116 	header += sizeof(udp);
5117 	memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
5118 	       RTE_DIM(mplsoudp_encap_conf.label));
5119 	mpls.label_tc_s[2] |= 0x1;
5120 	memcpy(header, &mpls, sizeof(mpls));
5121 	header += sizeof(mpls);
5122 	action_encap_data->conf.size = header -
5123 		action_encap_data->data;
5124 	action->conf = &action_encap_data->conf;
5125 	return ret;
5126 }
5127 
5128 /** Parse MPLSOUDP decap action. */
5129 static int
5130 parse_vc_action_mplsoudp_decap(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 	struct rte_flow_action *action;
5136 	struct action_raw_decap_data *action_decap_data;
5137 	struct rte_flow_item_eth eth = { .type = 0, };
5138 	struct rte_flow_item_vlan vlan = {.tci = 0};
5139 	struct rte_flow_item_ipv4 ipv4 = {
5140 		.hdr =  {
5141 			.next_proto_id = IPPROTO_UDP,
5142 		},
5143 	};
5144 	struct rte_flow_item_ipv6 ipv6 = {
5145 		.hdr =  {
5146 			.proto = IPPROTO_UDP,
5147 		},
5148 	};
5149 	struct rte_flow_item_udp udp = {
5150 		.hdr = {
5151 			.dst_port = rte_cpu_to_be_16(6635),
5152 		},
5153 	};
5154 	struct rte_flow_item_mpls mpls;
5155 	uint8_t *header;
5156 	int ret;
5157 
5158 	ret = parse_vc(ctx, token, str, len, buf, size);
5159 	if (ret < 0)
5160 		return ret;
5161 	/* Nothing else to do if there is no buffer. */
5162 	if (!out)
5163 		return ret;
5164 	if (!out->args.vc.actions_n)
5165 		return -1;
5166 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5167 	/* Point to selected object. */
5168 	ctx->object = out->args.vc.data;
5169 	ctx->objmask = NULL;
5170 	/* Copy the headers to the buffer. */
5171 	action_decap_data = ctx->object;
5172 	*action_decap_data = (struct action_raw_decap_data) {
5173 		.conf = (struct rte_flow_action_raw_decap){
5174 			.data = action_decap_data->data,
5175 		},
5176 		.data = {},
5177 	};
5178 	header = action_decap_data->data;
5179 	if (mplsoudp_decap_conf.select_vlan)
5180 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
5181 	else if (mplsoudp_encap_conf.select_ipv4)
5182 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5183 	else
5184 		eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5185 	memcpy(eth.dst.addr_bytes,
5186 	       mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
5187 	memcpy(eth.src.addr_bytes,
5188 	       mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
5189 	memcpy(header, &eth, sizeof(eth));
5190 	header += sizeof(eth);
5191 	if (mplsoudp_encap_conf.select_vlan) {
5192 		if (mplsoudp_encap_conf.select_ipv4)
5193 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
5194 		else
5195 			vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
5196 		memcpy(header, &vlan, sizeof(vlan));
5197 		header += sizeof(vlan);
5198 	}
5199 	if (mplsoudp_encap_conf.select_ipv4) {
5200 		memcpy(header, &ipv4, sizeof(ipv4));
5201 		header += sizeof(ipv4);
5202 	} else {
5203 		memcpy(header, &ipv6, sizeof(ipv6));
5204 		header += sizeof(ipv6);
5205 	}
5206 	memcpy(header, &udp, sizeof(udp));
5207 	header += sizeof(udp);
5208 	memset(&mpls, 0, sizeof(mpls));
5209 	memcpy(header, &mpls, sizeof(mpls));
5210 	header += sizeof(mpls);
5211 	action_decap_data->conf.size = header -
5212 		action_decap_data->data;
5213 	action->conf = &action_decap_data->conf;
5214 	return ret;
5215 }
5216 
5217 static int
5218 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
5219 				const char *str, unsigned int len, void *buf,
5220 				unsigned int size)
5221 {
5222 	struct action_raw_decap_data *action_raw_decap_data;
5223 	struct rte_flow_action *action;
5224 	const struct arg *arg;
5225 	struct buffer *out = buf;
5226 	int ret;
5227 	uint16_t idx;
5228 
5229 	RTE_SET_USED(token);
5230 	RTE_SET_USED(buf);
5231 	RTE_SET_USED(size);
5232 	arg = ARGS_ENTRY_ARB_BOUNDED
5233 		(offsetof(struct action_raw_decap_data, idx),
5234 		 sizeof(((struct action_raw_decap_data *)0)->idx),
5235 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
5236 	if (push_args(ctx, arg))
5237 		return -1;
5238 	ret = parse_int(ctx, token, str, len, NULL, 0);
5239 	if (ret < 0) {
5240 		pop_args(ctx);
5241 		return -1;
5242 	}
5243 	if (!ctx->object)
5244 		return len;
5245 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5246 	action_raw_decap_data = ctx->object;
5247 	idx = action_raw_decap_data->idx;
5248 	action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
5249 	action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
5250 	action->conf = &action_raw_decap_data->conf;
5251 	return len;
5252 }
5253 
5254 
5255 static int
5256 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
5257 				const char *str, unsigned int len, void *buf,
5258 				unsigned int size)
5259 {
5260 	struct action_raw_encap_data *action_raw_encap_data;
5261 	struct rte_flow_action *action;
5262 	const struct arg *arg;
5263 	struct buffer *out = buf;
5264 	int ret;
5265 	uint16_t idx;
5266 
5267 	RTE_SET_USED(token);
5268 	RTE_SET_USED(buf);
5269 	RTE_SET_USED(size);
5270 	if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
5271 		return -1;
5272 	arg = ARGS_ENTRY_ARB_BOUNDED
5273 		(offsetof(struct action_raw_encap_data, idx),
5274 		 sizeof(((struct action_raw_encap_data *)0)->idx),
5275 		 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
5276 	if (push_args(ctx, arg))
5277 		return -1;
5278 	ret = parse_int(ctx, token, str, len, NULL, 0);
5279 	if (ret < 0) {
5280 		pop_args(ctx);
5281 		return -1;
5282 	}
5283 	if (!ctx->object)
5284 		return len;
5285 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5286 	action_raw_encap_data = ctx->object;
5287 	idx = action_raw_encap_data->idx;
5288 	action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
5289 	action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
5290 	action_raw_encap_data->conf.preserve = NULL;
5291 	action->conf = &action_raw_encap_data->conf;
5292 	return len;
5293 }
5294 
5295 static int
5296 parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
5297 			  const char *str, unsigned int len, void *buf,
5298 			  unsigned int size)
5299 {
5300 	struct buffer *out = buf;
5301 	struct rte_flow_action *action;
5302 	struct action_raw_encap_data *action_raw_encap_data = NULL;
5303 	int ret;
5304 
5305 	ret = parse_vc(ctx, token, str, len, buf, size);
5306 	if (ret < 0)
5307 		return ret;
5308 	/* Nothing else to do if there is no buffer. */
5309 	if (!out)
5310 		return ret;
5311 	if (!out->args.vc.actions_n)
5312 		return -1;
5313 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5314 	/* Point to selected object. */
5315 	ctx->object = out->args.vc.data;
5316 	ctx->objmask = NULL;
5317 	/* Copy the headers to the buffer. */
5318 	action_raw_encap_data = ctx->object;
5319 	action_raw_encap_data->conf.data = raw_encap_confs[0].data;
5320 	action_raw_encap_data->conf.preserve = NULL;
5321 	action_raw_encap_data->conf.size = raw_encap_confs[0].size;
5322 	action->conf = &action_raw_encap_data->conf;
5323 	return ret;
5324 }
5325 
5326 static int
5327 parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
5328 			  const char *str, unsigned int len, void *buf,
5329 			  unsigned int size)
5330 {
5331 	struct buffer *out = buf;
5332 	struct rte_flow_action *action;
5333 	struct action_raw_decap_data *action_raw_decap_data = NULL;
5334 	int ret;
5335 
5336 	ret = parse_vc(ctx, token, str, len, buf, size);
5337 	if (ret < 0)
5338 		return ret;
5339 	/* Nothing else to do if there is no buffer. */
5340 	if (!out)
5341 		return ret;
5342 	if (!out->args.vc.actions_n)
5343 		return -1;
5344 	action = &out->args.vc.actions[out->args.vc.actions_n - 1];
5345 	/* Point to selected object. */
5346 	ctx->object = out->args.vc.data;
5347 	ctx->objmask = NULL;
5348 	/* Copy the headers to the buffer. */
5349 	action_raw_decap_data = ctx->object;
5350 	action_raw_decap_data->conf.data = raw_decap_confs[0].data;
5351 	action_raw_decap_data->conf.size = raw_decap_confs[0].size;
5352 	action->conf = &action_raw_decap_data->conf;
5353 	return ret;
5354 }
5355 
5356 static int
5357 parse_vc_action_set_meta(struct context *ctx, const struct token *token,
5358 			 const char *str, unsigned int len, void *buf,
5359 			 unsigned int size)
5360 {
5361 	int ret;
5362 
5363 	ret = parse_vc(ctx, token, str, len, buf, size);
5364 	if (ret < 0)
5365 		return ret;
5366 	ret = rte_flow_dynf_metadata_register();
5367 	if (ret < 0)
5368 		return -1;
5369 	return len;
5370 }
5371 
5372 /** Parse tokens for destroy command. */
5373 static int
5374 parse_destroy(struct context *ctx, const struct token *token,
5375 	      const char *str, unsigned int len,
5376 	      void *buf, unsigned int size)
5377 {
5378 	struct buffer *out = buf;
5379 
5380 	/* Token name must match. */
5381 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5382 		return -1;
5383 	/* Nothing else to do if there is no buffer. */
5384 	if (!out)
5385 		return len;
5386 	if (!out->command) {
5387 		if (ctx->curr != DESTROY)
5388 			return -1;
5389 		if (sizeof(*out) > size)
5390 			return -1;
5391 		out->command = ctx->curr;
5392 		ctx->objdata = 0;
5393 		ctx->object = out;
5394 		ctx->objmask = NULL;
5395 		out->args.destroy.rule =
5396 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5397 					       sizeof(double));
5398 		return len;
5399 	}
5400 	if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
5401 	     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
5402 		return -1;
5403 	ctx->objdata = 0;
5404 	ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
5405 	ctx->objmask = NULL;
5406 	return len;
5407 }
5408 
5409 /** Parse tokens for flush command. */
5410 static int
5411 parse_flush(struct context *ctx, const struct token *token,
5412 	    const char *str, unsigned int len,
5413 	    void *buf, unsigned int size)
5414 {
5415 	struct buffer *out = buf;
5416 
5417 	/* Token name must match. */
5418 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5419 		return -1;
5420 	/* Nothing else to do if there is no buffer. */
5421 	if (!out)
5422 		return len;
5423 	if (!out->command) {
5424 		if (ctx->curr != FLUSH)
5425 			return -1;
5426 		if (sizeof(*out) > size)
5427 			return -1;
5428 		out->command = ctx->curr;
5429 		ctx->objdata = 0;
5430 		ctx->object = out;
5431 		ctx->objmask = NULL;
5432 	}
5433 	return len;
5434 }
5435 
5436 /** Parse tokens for dump command. */
5437 static int
5438 parse_dump(struct context *ctx, const struct token *token,
5439 	    const char *str, unsigned int len,
5440 	    void *buf, unsigned int size)
5441 {
5442 	struct buffer *out = buf;
5443 
5444 	/* Token name must match. */
5445 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5446 		return -1;
5447 	/* Nothing else to do if there is no buffer. */
5448 	if (!out)
5449 		return len;
5450 	if (!out->command) {
5451 		if (ctx->curr != DUMP)
5452 			return -1;
5453 		if (sizeof(*out) > size)
5454 			return -1;
5455 		out->command = ctx->curr;
5456 		ctx->objdata = 0;
5457 		ctx->object = out;
5458 		ctx->objmask = NULL;
5459 	}
5460 	return len;
5461 }
5462 
5463 /** Parse tokens for query command. */
5464 static int
5465 parse_query(struct context *ctx, const struct token *token,
5466 	    const char *str, unsigned int len,
5467 	    void *buf, unsigned int size)
5468 {
5469 	struct buffer *out = buf;
5470 
5471 	/* Token name must match. */
5472 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5473 		return -1;
5474 	/* Nothing else to do if there is no buffer. */
5475 	if (!out)
5476 		return len;
5477 	if (!out->command) {
5478 		if (ctx->curr != QUERY)
5479 			return -1;
5480 		if (sizeof(*out) > size)
5481 			return -1;
5482 		out->command = ctx->curr;
5483 		ctx->objdata = 0;
5484 		ctx->object = out;
5485 		ctx->objmask = NULL;
5486 	}
5487 	return len;
5488 }
5489 
5490 /** Parse action names. */
5491 static int
5492 parse_action(struct context *ctx, const struct token *token,
5493 	     const char *str, unsigned int len,
5494 	     void *buf, unsigned int size)
5495 {
5496 	struct buffer *out = buf;
5497 	const struct arg *arg = pop_args(ctx);
5498 	unsigned int i;
5499 
5500 	(void)size;
5501 	/* Argument is expected. */
5502 	if (!arg)
5503 		return -1;
5504 	/* Parse action name. */
5505 	for (i = 0; next_action[i]; ++i) {
5506 		const struct parse_action_priv *priv;
5507 
5508 		token = &token_list[next_action[i]];
5509 		if (strcmp_partial(token->name, str, len))
5510 			continue;
5511 		priv = token->priv;
5512 		if (!priv)
5513 			goto error;
5514 		if (out)
5515 			memcpy((uint8_t *)ctx->object + arg->offset,
5516 			       &priv->type,
5517 			       arg->size);
5518 		return len;
5519 	}
5520 error:
5521 	push_args(ctx, arg);
5522 	return -1;
5523 }
5524 
5525 /** Parse tokens for list command. */
5526 static int
5527 parse_list(struct context *ctx, const struct token *token,
5528 	   const char *str, unsigned int len,
5529 	   void *buf, unsigned int size)
5530 {
5531 	struct buffer *out = buf;
5532 
5533 	/* Token name must match. */
5534 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5535 		return -1;
5536 	/* Nothing else to do if there is no buffer. */
5537 	if (!out)
5538 		return len;
5539 	if (!out->command) {
5540 		if (ctx->curr != LIST)
5541 			return -1;
5542 		if (sizeof(*out) > size)
5543 			return -1;
5544 		out->command = ctx->curr;
5545 		ctx->objdata = 0;
5546 		ctx->object = out;
5547 		ctx->objmask = NULL;
5548 		out->args.list.group =
5549 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
5550 					       sizeof(double));
5551 		return len;
5552 	}
5553 	if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
5554 	     sizeof(*out->args.list.group)) > (uint8_t *)out + size)
5555 		return -1;
5556 	ctx->objdata = 0;
5557 	ctx->object = out->args.list.group + out->args.list.group_n++;
5558 	ctx->objmask = NULL;
5559 	return len;
5560 }
5561 
5562 /** Parse tokens for list all aged flows command. */
5563 static int
5564 parse_aged(struct context *ctx, const struct token *token,
5565 	   const char *str, unsigned int len,
5566 	   void *buf, unsigned int size)
5567 {
5568 	struct buffer *out = buf;
5569 
5570 	/* Token name must match. */
5571 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5572 		return -1;
5573 	/* Nothing else to do if there is no buffer. */
5574 	if (!out)
5575 		return len;
5576 	if (!out->command) {
5577 		if (ctx->curr != AGED)
5578 			return -1;
5579 		if (sizeof(*out) > size)
5580 			return -1;
5581 		out->command = ctx->curr;
5582 		ctx->objdata = 0;
5583 		ctx->object = out;
5584 		ctx->objmask = NULL;
5585 	}
5586 	if (ctx->curr == AGED_DESTROY)
5587 		out->args.aged.destroy = 1;
5588 	return len;
5589 }
5590 
5591 /** Parse tokens for isolate command. */
5592 static int
5593 parse_isolate(struct context *ctx, const struct token *token,
5594 	      const char *str, unsigned int len,
5595 	      void *buf, unsigned int size)
5596 {
5597 	struct buffer *out = buf;
5598 
5599 	/* Token name must match. */
5600 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
5601 		return -1;
5602 	/* Nothing else to do if there is no buffer. */
5603 	if (!out)
5604 		return len;
5605 	if (!out->command) {
5606 		if (ctx->curr != ISOLATE)
5607 			return -1;
5608 		if (sizeof(*out) > size)
5609 			return -1;
5610 		out->command = ctx->curr;
5611 		ctx->objdata = 0;
5612 		ctx->object = out;
5613 		ctx->objmask = NULL;
5614 	}
5615 	return len;
5616 }
5617 
5618 /**
5619  * Parse signed/unsigned integers 8 to 64-bit long.
5620  *
5621  * Last argument (ctx->args) is retrieved to determine integer type and
5622  * storage location.
5623  */
5624 static int
5625 parse_int(struct context *ctx, const struct token *token,
5626 	  const char *str, unsigned int len,
5627 	  void *buf, unsigned int size)
5628 {
5629 	const struct arg *arg = pop_args(ctx);
5630 	uintmax_t u;
5631 	char *end;
5632 
5633 	(void)token;
5634 	/* Argument is expected. */
5635 	if (!arg)
5636 		return -1;
5637 	errno = 0;
5638 	u = arg->sign ?
5639 		(uintmax_t)strtoimax(str, &end, 0) :
5640 		strtoumax(str, &end, 0);
5641 	if (errno || (size_t)(end - str) != len)
5642 		goto error;
5643 	if (arg->bounded &&
5644 	    ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
5645 			    (intmax_t)u > (intmax_t)arg->max)) ||
5646 	     (!arg->sign && (u < arg->min || u > arg->max))))
5647 		goto error;
5648 	if (!ctx->object)
5649 		return len;
5650 	if (arg->mask) {
5651 		if (!arg_entry_bf_fill(ctx->object, u, arg) ||
5652 		    !arg_entry_bf_fill(ctx->objmask, -1, arg))
5653 			goto error;
5654 		return len;
5655 	}
5656 	buf = (uint8_t *)ctx->object + arg->offset;
5657 	size = arg->size;
5658 	if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
5659 		return -1;
5660 objmask:
5661 	switch (size) {
5662 	case sizeof(uint8_t):
5663 		*(uint8_t *)buf = u;
5664 		break;
5665 	case sizeof(uint16_t):
5666 		*(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
5667 		break;
5668 	case sizeof(uint8_t [3]):
5669 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
5670 		if (!arg->hton) {
5671 			((uint8_t *)buf)[0] = u;
5672 			((uint8_t *)buf)[1] = u >> 8;
5673 			((uint8_t *)buf)[2] = u >> 16;
5674 			break;
5675 		}
5676 #endif
5677 		((uint8_t *)buf)[0] = u >> 16;
5678 		((uint8_t *)buf)[1] = u >> 8;
5679 		((uint8_t *)buf)[2] = u;
5680 		break;
5681 	case sizeof(uint32_t):
5682 		*(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
5683 		break;
5684 	case sizeof(uint64_t):
5685 		*(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
5686 		break;
5687 	default:
5688 		goto error;
5689 	}
5690 	if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
5691 		u = -1;
5692 		buf = (uint8_t *)ctx->objmask + arg->offset;
5693 		goto objmask;
5694 	}
5695 	return len;
5696 error:
5697 	push_args(ctx, arg);
5698 	return -1;
5699 }
5700 
5701 /**
5702  * Parse a string.
5703  *
5704  * Three arguments (ctx->args) are retrieved from the stack to store data,
5705  * its actual length and address (in that order).
5706  */
5707 static int
5708 parse_string(struct context *ctx, const struct token *token,
5709 	     const char *str, unsigned int len,
5710 	     void *buf, unsigned int size)
5711 {
5712 	const struct arg *arg_data = pop_args(ctx);
5713 	const struct arg *arg_len = pop_args(ctx);
5714 	const struct arg *arg_addr = pop_args(ctx);
5715 	char tmp[16]; /* Ought to be enough. */
5716 	int ret;
5717 
5718 	/* Arguments are expected. */
5719 	if (!arg_data)
5720 		return -1;
5721 	if (!arg_len) {
5722 		push_args(ctx, arg_data);
5723 		return -1;
5724 	}
5725 	if (!arg_addr) {
5726 		push_args(ctx, arg_len);
5727 		push_args(ctx, arg_data);
5728 		return -1;
5729 	}
5730 	size = arg_data->size;
5731 	/* Bit-mask fill is not supported. */
5732 	if (arg_data->mask || size < len)
5733 		goto error;
5734 	if (!ctx->object)
5735 		return len;
5736 	/* Let parse_int() fill length information first. */
5737 	ret = snprintf(tmp, sizeof(tmp), "%u", len);
5738 	if (ret < 0)
5739 		goto error;
5740 	push_args(ctx, arg_len);
5741 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
5742 	if (ret < 0) {
5743 		pop_args(ctx);
5744 		goto error;
5745 	}
5746 	buf = (uint8_t *)ctx->object + arg_data->offset;
5747 	/* Output buffer is not necessarily NUL-terminated. */
5748 	memcpy(buf, str, len);
5749 	memset((uint8_t *)buf + len, 0x00, size - len);
5750 	if (ctx->objmask)
5751 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
5752 	/* Save address if requested. */
5753 	if (arg_addr->size) {
5754 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
5755 		       (void *[]){
5756 			(uint8_t *)ctx->object + arg_data->offset
5757 		       },
5758 		       arg_addr->size);
5759 		if (ctx->objmask)
5760 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
5761 			       (void *[]){
5762 				(uint8_t *)ctx->objmask + arg_data->offset
5763 			       },
5764 			       arg_addr->size);
5765 	}
5766 	return len;
5767 error:
5768 	push_args(ctx, arg_addr);
5769 	push_args(ctx, arg_len);
5770 	push_args(ctx, arg_data);
5771 	return -1;
5772 }
5773 
5774 static int
5775 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
5776 {
5777 	char *c = NULL;
5778 	uint32_t i, len;
5779 	char tmp[3];
5780 
5781 	/* Check input parameters */
5782 	if ((src == NULL) ||
5783 		(dst == NULL) ||
5784 		(size == NULL) ||
5785 		(*size == 0))
5786 		return -1;
5787 
5788 	/* Convert chars to bytes */
5789 	for (i = 0, len = 0; i < *size; i += 2) {
5790 		snprintf(tmp, 3, "%s", src + i);
5791 		dst[len++] = strtoul(tmp, &c, 16);
5792 		if (*c != 0) {
5793 			len--;
5794 			dst[len] = 0;
5795 			*size = len;
5796 			return -1;
5797 		}
5798 	}
5799 	dst[len] = 0;
5800 	*size = len;
5801 
5802 	return 0;
5803 }
5804 
5805 static int
5806 parse_hex(struct context *ctx, const struct token *token,
5807 		const char *str, unsigned int len,
5808 		void *buf, unsigned int size)
5809 {
5810 	const struct arg *arg_data = pop_args(ctx);
5811 	const struct arg *arg_len = pop_args(ctx);
5812 	const struct arg *arg_addr = pop_args(ctx);
5813 	char tmp[16]; /* Ought to be enough. */
5814 	int ret;
5815 	unsigned int hexlen = len;
5816 	unsigned int length = 256;
5817 	uint8_t hex_tmp[length];
5818 
5819 	/* Arguments are expected. */
5820 	if (!arg_data)
5821 		return -1;
5822 	if (!arg_len) {
5823 		push_args(ctx, arg_data);
5824 		return -1;
5825 	}
5826 	if (!arg_addr) {
5827 		push_args(ctx, arg_len);
5828 		push_args(ctx, arg_data);
5829 		return -1;
5830 	}
5831 	size = arg_data->size;
5832 	/* Bit-mask fill is not supported. */
5833 	if (arg_data->mask)
5834 		goto error;
5835 	if (!ctx->object)
5836 		return len;
5837 
5838 	/* translate bytes string to array. */
5839 	if (str[0] == '0' && ((str[1] == 'x') ||
5840 			(str[1] == 'X'))) {
5841 		str += 2;
5842 		hexlen -= 2;
5843 	}
5844 	if (hexlen > length)
5845 		return -1;
5846 	ret = parse_hex_string(str, hex_tmp, &hexlen);
5847 	if (ret < 0)
5848 		goto error;
5849 	/* Let parse_int() fill length information first. */
5850 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
5851 	if (ret < 0)
5852 		goto error;
5853 	push_args(ctx, arg_len);
5854 	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
5855 	if (ret < 0) {
5856 		pop_args(ctx);
5857 		goto error;
5858 	}
5859 	buf = (uint8_t *)ctx->object + arg_data->offset;
5860 	/* Output buffer is not necessarily NUL-terminated. */
5861 	memcpy(buf, hex_tmp, hexlen);
5862 	memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
5863 	if (ctx->objmask)
5864 		memset((uint8_t *)ctx->objmask + arg_data->offset,
5865 					0xff, hexlen);
5866 	/* Save address if requested. */
5867 	if (arg_addr->size) {
5868 		memcpy((uint8_t *)ctx->object + arg_addr->offset,
5869 		       (void *[]){
5870 			(uint8_t *)ctx->object + arg_data->offset
5871 		       },
5872 		       arg_addr->size);
5873 		if (ctx->objmask)
5874 			memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
5875 			       (void *[]){
5876 				(uint8_t *)ctx->objmask + arg_data->offset
5877 			       },
5878 			       arg_addr->size);
5879 	}
5880 	return len;
5881 error:
5882 	push_args(ctx, arg_addr);
5883 	push_args(ctx, arg_len);
5884 	push_args(ctx, arg_data);
5885 	return -1;
5886 
5887 }
5888 
5889 /**
5890  * Parse a zero-ended string.
5891  */
5892 static int
5893 parse_string0(struct context *ctx, const struct token *token __rte_unused,
5894 	     const char *str, unsigned int len,
5895 	     void *buf, unsigned int size)
5896 {
5897 	const struct arg *arg_data = pop_args(ctx);
5898 
5899 	/* Arguments are expected. */
5900 	if (!arg_data)
5901 		return -1;
5902 	size = arg_data->size;
5903 	/* Bit-mask fill is not supported. */
5904 	if (arg_data->mask || size < len + 1)
5905 		goto error;
5906 	if (!ctx->object)
5907 		return len;
5908 	buf = (uint8_t *)ctx->object + arg_data->offset;
5909 	strncpy(buf, str, len);
5910 	if (ctx->objmask)
5911 		memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
5912 	return len;
5913 error:
5914 	push_args(ctx, arg_data);
5915 	return -1;
5916 }
5917 
5918 /**
5919  * Parse a MAC address.
5920  *
5921  * Last argument (ctx->args) is retrieved to determine storage size and
5922  * location.
5923  */
5924 static int
5925 parse_mac_addr(struct context *ctx, const struct token *token,
5926 	       const char *str, unsigned int len,
5927 	       void *buf, unsigned int size)
5928 {
5929 	const struct arg *arg = pop_args(ctx);
5930 	struct rte_ether_addr tmp;
5931 	int ret;
5932 
5933 	(void)token;
5934 	/* Argument is expected. */
5935 	if (!arg)
5936 		return -1;
5937 	size = arg->size;
5938 	/* Bit-mask fill is not supported. */
5939 	if (arg->mask || size != sizeof(tmp))
5940 		goto error;
5941 	/* Only network endian is supported. */
5942 	if (!arg->hton)
5943 		goto error;
5944 	ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
5945 	if (ret < 0 || (unsigned int)ret != len)
5946 		goto error;
5947 	if (!ctx->object)
5948 		return len;
5949 	buf = (uint8_t *)ctx->object + arg->offset;
5950 	memcpy(buf, &tmp, size);
5951 	if (ctx->objmask)
5952 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5953 	return len;
5954 error:
5955 	push_args(ctx, arg);
5956 	return -1;
5957 }
5958 
5959 /**
5960  * Parse an IPv4 address.
5961  *
5962  * Last argument (ctx->args) is retrieved to determine storage size and
5963  * location.
5964  */
5965 static int
5966 parse_ipv4_addr(struct context *ctx, const struct token *token,
5967 		const char *str, unsigned int len,
5968 		void *buf, unsigned int size)
5969 {
5970 	const struct arg *arg = pop_args(ctx);
5971 	char str2[len + 1];
5972 	struct in_addr tmp;
5973 	int ret;
5974 
5975 	/* Argument is expected. */
5976 	if (!arg)
5977 		return -1;
5978 	size = arg->size;
5979 	/* Bit-mask fill is not supported. */
5980 	if (arg->mask || size != sizeof(tmp))
5981 		goto error;
5982 	/* Only network endian is supported. */
5983 	if (!arg->hton)
5984 		goto error;
5985 	memcpy(str2, str, len);
5986 	str2[len] = '\0';
5987 	ret = inet_pton(AF_INET, str2, &tmp);
5988 	if (ret != 1) {
5989 		/* Attempt integer parsing. */
5990 		push_args(ctx, arg);
5991 		return parse_int(ctx, token, str, len, buf, size);
5992 	}
5993 	if (!ctx->object)
5994 		return len;
5995 	buf = (uint8_t *)ctx->object + arg->offset;
5996 	memcpy(buf, &tmp, size);
5997 	if (ctx->objmask)
5998 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
5999 	return len;
6000 error:
6001 	push_args(ctx, arg);
6002 	return -1;
6003 }
6004 
6005 /**
6006  * Parse an IPv6 address.
6007  *
6008  * Last argument (ctx->args) is retrieved to determine storage size and
6009  * location.
6010  */
6011 static int
6012 parse_ipv6_addr(struct context *ctx, const struct token *token,
6013 		const char *str, unsigned int len,
6014 		void *buf, unsigned int size)
6015 {
6016 	const struct arg *arg = pop_args(ctx);
6017 	char str2[len + 1];
6018 	struct in6_addr tmp;
6019 	int ret;
6020 
6021 	(void)token;
6022 	/* Argument is expected. */
6023 	if (!arg)
6024 		return -1;
6025 	size = arg->size;
6026 	/* Bit-mask fill is not supported. */
6027 	if (arg->mask || size != sizeof(tmp))
6028 		goto error;
6029 	/* Only network endian is supported. */
6030 	if (!arg->hton)
6031 		goto error;
6032 	memcpy(str2, str, len);
6033 	str2[len] = '\0';
6034 	ret = inet_pton(AF_INET6, str2, &tmp);
6035 	if (ret != 1)
6036 		goto error;
6037 	if (!ctx->object)
6038 		return len;
6039 	buf = (uint8_t *)ctx->object + arg->offset;
6040 	memcpy(buf, &tmp, size);
6041 	if (ctx->objmask)
6042 		memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
6043 	return len;
6044 error:
6045 	push_args(ctx, arg);
6046 	return -1;
6047 }
6048 
6049 /** Boolean values (even indices stand for false). */
6050 static const char *const boolean_name[] = {
6051 	"0", "1",
6052 	"false", "true",
6053 	"no", "yes",
6054 	"N", "Y",
6055 	"off", "on",
6056 	NULL,
6057 };
6058 
6059 /**
6060  * Parse a boolean value.
6061  *
6062  * Last argument (ctx->args) is retrieved to determine storage size and
6063  * location.
6064  */
6065 static int
6066 parse_boolean(struct context *ctx, const struct token *token,
6067 	      const char *str, unsigned int len,
6068 	      void *buf, unsigned int size)
6069 {
6070 	const struct arg *arg = pop_args(ctx);
6071 	unsigned int i;
6072 	int ret;
6073 
6074 	/* Argument is expected. */
6075 	if (!arg)
6076 		return -1;
6077 	for (i = 0; boolean_name[i]; ++i)
6078 		if (!strcmp_partial(boolean_name[i], str, len))
6079 			break;
6080 	/* Process token as integer. */
6081 	if (boolean_name[i])
6082 		str = i & 1 ? "1" : "0";
6083 	push_args(ctx, arg);
6084 	ret = parse_int(ctx, token, str, strlen(str), buf, size);
6085 	return ret > 0 ? (int)len : ret;
6086 }
6087 
6088 /** Parse port and update context. */
6089 static int
6090 parse_port(struct context *ctx, const struct token *token,
6091 	   const char *str, unsigned int len,
6092 	   void *buf, unsigned int size)
6093 {
6094 	struct buffer *out = &(struct buffer){ .port = 0 };
6095 	int ret;
6096 
6097 	if (buf)
6098 		out = buf;
6099 	else {
6100 		ctx->objdata = 0;
6101 		ctx->object = out;
6102 		ctx->objmask = NULL;
6103 		size = sizeof(*out);
6104 	}
6105 	ret = parse_int(ctx, token, str, len, out, size);
6106 	if (ret >= 0)
6107 		ctx->port = out->port;
6108 	if (!buf)
6109 		ctx->object = NULL;
6110 	return ret;
6111 }
6112 
6113 /** Parse set command, initialize output buffer for subsequent tokens. */
6114 static int
6115 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
6116 			  const char *str, unsigned int len,
6117 			  void *buf, unsigned int size)
6118 {
6119 	struct buffer *out = buf;
6120 
6121 	/* Token name must match. */
6122 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6123 		return -1;
6124 	/* Nothing else to do if there is no buffer. */
6125 	if (!out)
6126 		return len;
6127 	/* Make sure buffer is large enough. */
6128 	if (size < sizeof(*out))
6129 		return -1;
6130 	ctx->objdata = 0;
6131 	ctx->objmask = NULL;
6132 	ctx->object = out;
6133 	if (!out->command)
6134 		return -1;
6135 	out->command = ctx->curr;
6136 	return len;
6137 }
6138 
6139 /**
6140  * Parse set raw_encap/raw_decap command,
6141  * initialize output buffer for subsequent tokens.
6142  */
6143 static int
6144 parse_set_init(struct context *ctx, const struct token *token,
6145 	       const char *str, unsigned int len,
6146 	       void *buf, unsigned int size)
6147 {
6148 	struct buffer *out = buf;
6149 
6150 	/* Token name must match. */
6151 	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
6152 		return -1;
6153 	/* Nothing else to do if there is no buffer. */
6154 	if (!out)
6155 		return len;
6156 	/* Make sure buffer is large enough. */
6157 	if (size < sizeof(*out))
6158 		return -1;
6159 	/* Initialize buffer. */
6160 	memset(out, 0x00, sizeof(*out));
6161 	memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
6162 	ctx->objdata = 0;
6163 	ctx->object = out;
6164 	ctx->objmask = NULL;
6165 	if (!out->command) {
6166 		if (ctx->curr != SET)
6167 			return -1;
6168 		if (sizeof(*out) > size)
6169 			return -1;
6170 		out->command = ctx->curr;
6171 		out->args.vc.data = (uint8_t *)out + size;
6172 		/* All we need is pattern */
6173 		out->args.vc.pattern =
6174 			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
6175 					       sizeof(double));
6176 		ctx->object = out->args.vc.pattern;
6177 	}
6178 	return len;
6179 }
6180 
6181 /** No completion. */
6182 static int
6183 comp_none(struct context *ctx, const struct token *token,
6184 	  unsigned int ent, char *buf, unsigned int size)
6185 {
6186 	(void)ctx;
6187 	(void)token;
6188 	(void)ent;
6189 	(void)buf;
6190 	(void)size;
6191 	return 0;
6192 }
6193 
6194 /** Complete boolean values. */
6195 static int
6196 comp_boolean(struct context *ctx, const struct token *token,
6197 	     unsigned int ent, char *buf, unsigned int size)
6198 {
6199 	unsigned int i;
6200 
6201 	(void)ctx;
6202 	(void)token;
6203 	for (i = 0; boolean_name[i]; ++i)
6204 		if (buf && i == ent)
6205 			return strlcpy(buf, boolean_name[i], size);
6206 	if (buf)
6207 		return -1;
6208 	return i;
6209 }
6210 
6211 /** Complete action names. */
6212 static int
6213 comp_action(struct context *ctx, const struct token *token,
6214 	    unsigned int ent, char *buf, unsigned int size)
6215 {
6216 	unsigned int i;
6217 
6218 	(void)ctx;
6219 	(void)token;
6220 	for (i = 0; next_action[i]; ++i)
6221 		if (buf && i == ent)
6222 			return strlcpy(buf, token_list[next_action[i]].name,
6223 				       size);
6224 	if (buf)
6225 		return -1;
6226 	return i;
6227 }
6228 
6229 /** Complete available ports. */
6230 static int
6231 comp_port(struct context *ctx, const struct token *token,
6232 	  unsigned int ent, char *buf, unsigned int size)
6233 {
6234 	unsigned int i = 0;
6235 	portid_t p;
6236 
6237 	(void)ctx;
6238 	(void)token;
6239 	RTE_ETH_FOREACH_DEV(p) {
6240 		if (buf && i == ent)
6241 			return snprintf(buf, size, "%u", p);
6242 		++i;
6243 	}
6244 	if (buf)
6245 		return -1;
6246 	return i;
6247 }
6248 
6249 /** Complete available rule IDs. */
6250 static int
6251 comp_rule_id(struct context *ctx, const struct token *token,
6252 	     unsigned int ent, char *buf, unsigned int size)
6253 {
6254 	unsigned int i = 0;
6255 	struct rte_port *port;
6256 	struct port_flow *pf;
6257 
6258 	(void)token;
6259 	if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
6260 	    ctx->port == (portid_t)RTE_PORT_ALL)
6261 		return -1;
6262 	port = &ports[ctx->port];
6263 	for (pf = port->flow_list; pf != NULL; pf = pf->next) {
6264 		if (buf && i == ent)
6265 			return snprintf(buf, size, "%u", pf->id);
6266 		++i;
6267 	}
6268 	if (buf)
6269 		return -1;
6270 	return i;
6271 }
6272 
6273 /** Complete type field for RSS action. */
6274 static int
6275 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
6276 			unsigned int ent, char *buf, unsigned int size)
6277 {
6278 	unsigned int i;
6279 
6280 	(void)ctx;
6281 	(void)token;
6282 	for (i = 0; rss_type_table[i].str; ++i)
6283 		;
6284 	if (!buf)
6285 		return i + 1;
6286 	if (ent < i)
6287 		return strlcpy(buf, rss_type_table[ent].str, size);
6288 	if (ent == i)
6289 		return snprintf(buf, size, "end");
6290 	return -1;
6291 }
6292 
6293 /** Complete queue field for RSS action. */
6294 static int
6295 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
6296 			 unsigned int ent, char *buf, unsigned int size)
6297 {
6298 	(void)ctx;
6299 	(void)token;
6300 	if (!buf)
6301 		return nb_rxq + 1;
6302 	if (ent < nb_rxq)
6303 		return snprintf(buf, size, "%u", ent);
6304 	if (ent == nb_rxq)
6305 		return snprintf(buf, size, "end");
6306 	return -1;
6307 }
6308 
6309 /** Complete index number for set raw_encap/raw_decap commands. */
6310 static int
6311 comp_set_raw_index(struct context *ctx, const struct token *token,
6312 		   unsigned int ent, char *buf, unsigned int size)
6313 {
6314 	uint16_t idx = 0;
6315 	uint16_t nb = 0;
6316 
6317 	RTE_SET_USED(ctx);
6318 	RTE_SET_USED(token);
6319 	for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
6320 		if (buf && idx == ent)
6321 			return snprintf(buf, size, "%u", idx);
6322 		++nb;
6323 	}
6324 	return nb;
6325 }
6326 
6327 /** Internal context. */
6328 static struct context cmd_flow_context;
6329 
6330 /** Global parser instance (cmdline API). */
6331 cmdline_parse_inst_t cmd_flow;
6332 cmdline_parse_inst_t cmd_set_raw;
6333 
6334 /** Initialize context. */
6335 static void
6336 cmd_flow_context_init(struct context *ctx)
6337 {
6338 	/* A full memset() is not necessary. */
6339 	ctx->curr = ZERO;
6340 	ctx->prev = ZERO;
6341 	ctx->next_num = 0;
6342 	ctx->args_num = 0;
6343 	ctx->eol = 0;
6344 	ctx->last = 0;
6345 	ctx->port = 0;
6346 	ctx->objdata = 0;
6347 	ctx->object = NULL;
6348 	ctx->objmask = NULL;
6349 }
6350 
6351 /** Parse a token (cmdline API). */
6352 static int
6353 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
6354 	       unsigned int size)
6355 {
6356 	struct context *ctx = &cmd_flow_context;
6357 	const struct token *token;
6358 	const enum index *list;
6359 	int len;
6360 	int i;
6361 
6362 	(void)hdr;
6363 	token = &token_list[ctx->curr];
6364 	/* Check argument length. */
6365 	ctx->eol = 0;
6366 	ctx->last = 1;
6367 	for (len = 0; src[len]; ++len)
6368 		if (src[len] == '#' || isspace(src[len]))
6369 			break;
6370 	if (!len)
6371 		return -1;
6372 	/* Last argument and EOL detection. */
6373 	for (i = len; src[i]; ++i)
6374 		if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
6375 			break;
6376 		else if (!isspace(src[i])) {
6377 			ctx->last = 0;
6378 			break;
6379 		}
6380 	for (; src[i]; ++i)
6381 		if (src[i] == '\r' || src[i] == '\n') {
6382 			ctx->eol = 1;
6383 			break;
6384 		}
6385 	/* Initialize context if necessary. */
6386 	if (!ctx->next_num) {
6387 		if (!token->next)
6388 			return 0;
6389 		ctx->next[ctx->next_num++] = token->next[0];
6390 	}
6391 	/* Process argument through candidates. */
6392 	ctx->prev = ctx->curr;
6393 	list = ctx->next[ctx->next_num - 1];
6394 	for (i = 0; list[i]; ++i) {
6395 		const struct token *next = &token_list[list[i]];
6396 		int tmp;
6397 
6398 		ctx->curr = list[i];
6399 		if (next->call)
6400 			tmp = next->call(ctx, next, src, len, result, size);
6401 		else
6402 			tmp = parse_default(ctx, next, src, len, result, size);
6403 		if (tmp == -1 || tmp != len)
6404 			continue;
6405 		token = next;
6406 		break;
6407 	}
6408 	if (!list[i])
6409 		return -1;
6410 	--ctx->next_num;
6411 	/* Push subsequent tokens if any. */
6412 	if (token->next)
6413 		for (i = 0; token->next[i]; ++i) {
6414 			if (ctx->next_num == RTE_DIM(ctx->next))
6415 				return -1;
6416 			ctx->next[ctx->next_num++] = token->next[i];
6417 		}
6418 	/* Push arguments if any. */
6419 	if (token->args)
6420 		for (i = 0; token->args[i]; ++i) {
6421 			if (ctx->args_num == RTE_DIM(ctx->args))
6422 				return -1;
6423 			ctx->args[ctx->args_num++] = token->args[i];
6424 		}
6425 	return len;
6426 }
6427 
6428 /** Return number of completion entries (cmdline API). */
6429 static int
6430 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
6431 {
6432 	struct context *ctx = &cmd_flow_context;
6433 	const struct token *token = &token_list[ctx->curr];
6434 	const enum index *list;
6435 	int i;
6436 
6437 	(void)hdr;
6438 	/* Count number of tokens in current list. */
6439 	if (ctx->next_num)
6440 		list = ctx->next[ctx->next_num - 1];
6441 	else
6442 		list = token->next[0];
6443 	for (i = 0; list[i]; ++i)
6444 		;
6445 	if (!i)
6446 		return 0;
6447 	/*
6448 	 * If there is a single token, use its completion callback, otherwise
6449 	 * return the number of entries.
6450 	 */
6451 	token = &token_list[list[0]];
6452 	if (i == 1 && token->comp) {
6453 		/* Save index for cmd_flow_get_help(). */
6454 		ctx->prev = list[0];
6455 		return token->comp(ctx, token, 0, NULL, 0);
6456 	}
6457 	return i;
6458 }
6459 
6460 /** Return a completion entry (cmdline API). */
6461 static int
6462 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
6463 			  char *dst, unsigned int size)
6464 {
6465 	struct context *ctx = &cmd_flow_context;
6466 	const struct token *token = &token_list[ctx->curr];
6467 	const enum index *list;
6468 	int i;
6469 
6470 	(void)hdr;
6471 	/* Count number of tokens in current list. */
6472 	if (ctx->next_num)
6473 		list = ctx->next[ctx->next_num - 1];
6474 	else
6475 		list = token->next[0];
6476 	for (i = 0; list[i]; ++i)
6477 		;
6478 	if (!i)
6479 		return -1;
6480 	/* If there is a single token, use its completion callback. */
6481 	token = &token_list[list[0]];
6482 	if (i == 1 && token->comp) {
6483 		/* Save index for cmd_flow_get_help(). */
6484 		ctx->prev = list[0];
6485 		return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
6486 	}
6487 	/* Otherwise make sure the index is valid and use defaults. */
6488 	if (index >= i)
6489 		return -1;
6490 	token = &token_list[list[index]];
6491 	strlcpy(dst, token->name, size);
6492 	/* Save index for cmd_flow_get_help(). */
6493 	ctx->prev = list[index];
6494 	return 0;
6495 }
6496 
6497 /** Populate help strings for current token (cmdline API). */
6498 static int
6499 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
6500 {
6501 	struct context *ctx = &cmd_flow_context;
6502 	const struct token *token = &token_list[ctx->prev];
6503 
6504 	(void)hdr;
6505 	if (!size)
6506 		return -1;
6507 	/* Set token type and update global help with details. */
6508 	strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
6509 	if (token->help)
6510 		cmd_flow.help_str = token->help;
6511 	else
6512 		cmd_flow.help_str = token->name;
6513 	return 0;
6514 }
6515 
6516 /** Token definition template (cmdline API). */
6517 static struct cmdline_token_hdr cmd_flow_token_hdr = {
6518 	.ops = &(struct cmdline_token_ops){
6519 		.parse = cmd_flow_parse,
6520 		.complete_get_nb = cmd_flow_complete_get_nb,
6521 		.complete_get_elt = cmd_flow_complete_get_elt,
6522 		.get_help = cmd_flow_get_help,
6523 	},
6524 	.offset = 0,
6525 };
6526 
6527 /** Populate the next dynamic token. */
6528 static void
6529 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
6530 	     cmdline_parse_token_hdr_t **hdr_inst)
6531 {
6532 	struct context *ctx = &cmd_flow_context;
6533 
6534 	/* Always reinitialize context before requesting the first token. */
6535 	if (!(hdr_inst - cmd_flow.tokens))
6536 		cmd_flow_context_init(ctx);
6537 	/* Return NULL when no more tokens are expected. */
6538 	if (!ctx->next_num && ctx->curr) {
6539 		*hdr = NULL;
6540 		return;
6541 	}
6542 	/* Determine if command should end here. */
6543 	if (ctx->eol && ctx->last && ctx->next_num) {
6544 		const enum index *list = ctx->next[ctx->next_num - 1];
6545 		int i;
6546 
6547 		for (i = 0; list[i]; ++i) {
6548 			if (list[i] != END)
6549 				continue;
6550 			*hdr = NULL;
6551 			return;
6552 		}
6553 	}
6554 	*hdr = &cmd_flow_token_hdr;
6555 }
6556 
6557 /** Dispatch parsed buffer to function calls. */
6558 static void
6559 cmd_flow_parsed(const struct buffer *in)
6560 {
6561 	switch (in->command) {
6562 	case VALIDATE:
6563 		port_flow_validate(in->port, &in->args.vc.attr,
6564 				   in->args.vc.pattern, in->args.vc.actions);
6565 		break;
6566 	case CREATE:
6567 		port_flow_create(in->port, &in->args.vc.attr,
6568 				 in->args.vc.pattern, in->args.vc.actions);
6569 		break;
6570 	case DESTROY:
6571 		port_flow_destroy(in->port, in->args.destroy.rule_n,
6572 				  in->args.destroy.rule);
6573 		break;
6574 	case FLUSH:
6575 		port_flow_flush(in->port);
6576 		break;
6577 	case DUMP:
6578 		port_flow_dump(in->port, in->args.dump.file);
6579 		break;
6580 	case QUERY:
6581 		port_flow_query(in->port, in->args.query.rule,
6582 				&in->args.query.action);
6583 		break;
6584 	case LIST:
6585 		port_flow_list(in->port, in->args.list.group_n,
6586 			       in->args.list.group);
6587 		break;
6588 	case ISOLATE:
6589 		port_flow_isolate(in->port, in->args.isolate.set);
6590 		break;
6591 	case AGED:
6592 		port_flow_aged(in->port, in->args.aged.destroy);
6593 		break;
6594 	default:
6595 		break;
6596 	}
6597 }
6598 
6599 /** Token generator and output processing callback (cmdline API). */
6600 static void
6601 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
6602 {
6603 	if (cl == NULL)
6604 		cmd_flow_tok(arg0, arg2);
6605 	else
6606 		cmd_flow_parsed(arg0);
6607 }
6608 
6609 /** Global parser instance (cmdline API). */
6610 cmdline_parse_inst_t cmd_flow = {
6611 	.f = cmd_flow_cb,
6612 	.data = NULL, /**< Unused. */
6613 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
6614 	.tokens = {
6615 		NULL,
6616 	}, /**< Tokens are returned by cmd_flow_tok(). */
6617 };
6618 
6619 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
6620 
6621 static void
6622 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
6623 {
6624 	struct rte_flow_item_ipv4 *ipv4;
6625 	struct rte_flow_item_eth *eth;
6626 	struct rte_flow_item_ipv6 *ipv6;
6627 	struct rte_flow_item_vxlan *vxlan;
6628 	struct rte_flow_item_vxlan_gpe *gpe;
6629 	struct rte_flow_item_nvgre *nvgre;
6630 	uint32_t ipv6_vtc_flow;
6631 
6632 	switch (item->type) {
6633 	case RTE_FLOW_ITEM_TYPE_ETH:
6634 		eth = (struct rte_flow_item_eth *)buf;
6635 		if (next_proto)
6636 			eth->type = rte_cpu_to_be_16(next_proto);
6637 		break;
6638 	case RTE_FLOW_ITEM_TYPE_IPV4:
6639 		ipv4 = (struct rte_flow_item_ipv4 *)buf;
6640 		ipv4->hdr.version_ihl = 0x45;
6641 		if (next_proto && ipv4->hdr.next_proto_id == 0)
6642 			ipv4->hdr.next_proto_id = (uint8_t)next_proto;
6643 		break;
6644 	case RTE_FLOW_ITEM_TYPE_IPV6:
6645 		ipv6 = (struct rte_flow_item_ipv6 *)buf;
6646 		if (next_proto && ipv6->hdr.proto == 0)
6647 			ipv6->hdr.proto = (uint8_t)next_proto;
6648 		ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow);
6649 		ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
6650 		ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
6651 		ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
6652 		break;
6653 	case RTE_FLOW_ITEM_TYPE_VXLAN:
6654 		vxlan = (struct rte_flow_item_vxlan *)buf;
6655 		vxlan->flags = 0x08;
6656 		break;
6657 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6658 		gpe = (struct rte_flow_item_vxlan_gpe *)buf;
6659 		gpe->flags = 0x0C;
6660 		break;
6661 	case RTE_FLOW_ITEM_TYPE_NVGRE:
6662 		nvgre = (struct rte_flow_item_nvgre *)buf;
6663 		nvgre->protocol = rte_cpu_to_be_16(0x6558);
6664 		nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
6665 		break;
6666 	default:
6667 		break;
6668 	}
6669 }
6670 
6671 /** Helper of get item's default mask. */
6672 static const void *
6673 flow_item_default_mask(const struct rte_flow_item *item)
6674 {
6675 	const void *mask = NULL;
6676 	static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
6677 
6678 	switch (item->type) {
6679 	case RTE_FLOW_ITEM_TYPE_ANY:
6680 		mask = &rte_flow_item_any_mask;
6681 		break;
6682 	case RTE_FLOW_ITEM_TYPE_VF:
6683 		mask = &rte_flow_item_vf_mask;
6684 		break;
6685 	case RTE_FLOW_ITEM_TYPE_PORT_ID:
6686 		mask = &rte_flow_item_port_id_mask;
6687 		break;
6688 	case RTE_FLOW_ITEM_TYPE_RAW:
6689 		mask = &rte_flow_item_raw_mask;
6690 		break;
6691 	case RTE_FLOW_ITEM_TYPE_ETH:
6692 		mask = &rte_flow_item_eth_mask;
6693 		break;
6694 	case RTE_FLOW_ITEM_TYPE_VLAN:
6695 		mask = &rte_flow_item_vlan_mask;
6696 		break;
6697 	case RTE_FLOW_ITEM_TYPE_IPV4:
6698 		mask = &rte_flow_item_ipv4_mask;
6699 		break;
6700 	case RTE_FLOW_ITEM_TYPE_IPV6:
6701 		mask = &rte_flow_item_ipv6_mask;
6702 		break;
6703 	case RTE_FLOW_ITEM_TYPE_ICMP:
6704 		mask = &rte_flow_item_icmp_mask;
6705 		break;
6706 	case RTE_FLOW_ITEM_TYPE_UDP:
6707 		mask = &rte_flow_item_udp_mask;
6708 		break;
6709 	case RTE_FLOW_ITEM_TYPE_TCP:
6710 		mask = &rte_flow_item_tcp_mask;
6711 		break;
6712 	case RTE_FLOW_ITEM_TYPE_SCTP:
6713 		mask = &rte_flow_item_sctp_mask;
6714 		break;
6715 	case RTE_FLOW_ITEM_TYPE_VXLAN:
6716 		mask = &rte_flow_item_vxlan_mask;
6717 		break;
6718 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6719 		mask = &rte_flow_item_vxlan_gpe_mask;
6720 		break;
6721 	case RTE_FLOW_ITEM_TYPE_E_TAG:
6722 		mask = &rte_flow_item_e_tag_mask;
6723 		break;
6724 	case RTE_FLOW_ITEM_TYPE_NVGRE:
6725 		mask = &rte_flow_item_nvgre_mask;
6726 		break;
6727 	case RTE_FLOW_ITEM_TYPE_MPLS:
6728 		mask = &rte_flow_item_mpls_mask;
6729 		break;
6730 	case RTE_FLOW_ITEM_TYPE_GRE:
6731 		mask = &rte_flow_item_gre_mask;
6732 		break;
6733 	case RTE_FLOW_ITEM_TYPE_GRE_KEY:
6734 		mask = &gre_key_default_mask;
6735 		break;
6736 	case RTE_FLOW_ITEM_TYPE_META:
6737 		mask = &rte_flow_item_meta_mask;
6738 		break;
6739 	case RTE_FLOW_ITEM_TYPE_FUZZY:
6740 		mask = &rte_flow_item_fuzzy_mask;
6741 		break;
6742 	case RTE_FLOW_ITEM_TYPE_GTP:
6743 		mask = &rte_flow_item_gtp_mask;
6744 		break;
6745 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
6746 		mask = &rte_flow_item_gtp_psc_mask;
6747 		break;
6748 	case RTE_FLOW_ITEM_TYPE_GENEVE:
6749 		mask = &rte_flow_item_geneve_mask;
6750 		break;
6751 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
6752 		mask = &rte_flow_item_pppoe_proto_id_mask;
6753 		break;
6754 	case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
6755 		mask = &rte_flow_item_l2tpv3oip_mask;
6756 		break;
6757 	case RTE_FLOW_ITEM_TYPE_ESP:
6758 		mask = &rte_flow_item_esp_mask;
6759 		break;
6760 	case RTE_FLOW_ITEM_TYPE_AH:
6761 		mask = &rte_flow_item_ah_mask;
6762 		break;
6763 	case RTE_FLOW_ITEM_TYPE_PFCP:
6764 		mask = &rte_flow_item_pfcp_mask;
6765 		break;
6766 	default:
6767 		break;
6768 	}
6769 	return mask;
6770 }
6771 
6772 
6773 
6774 /** Dispatch parsed buffer to function calls. */
6775 static void
6776 cmd_set_raw_parsed(const struct buffer *in)
6777 {
6778 	uint32_t n = in->args.vc.pattern_n;
6779 	int i = 0;
6780 	struct rte_flow_item *item = NULL;
6781 	size_t size = 0;
6782 	uint8_t *data = NULL;
6783 	uint8_t *data_tail = NULL;
6784 	size_t *total_size = NULL;
6785 	uint16_t upper_layer = 0;
6786 	uint16_t proto = 0;
6787 	uint16_t idx = in->port; /* We borrow port field as index */
6788 
6789 	RTE_ASSERT(in->command == SET_RAW_ENCAP ||
6790 		   in->command == SET_RAW_DECAP);
6791 	if (in->command == SET_RAW_ENCAP) {
6792 		total_size = &raw_encap_confs[idx].size;
6793 		data = (uint8_t *)&raw_encap_confs[idx].data;
6794 	} else {
6795 		total_size = &raw_decap_confs[idx].size;
6796 		data = (uint8_t *)&raw_decap_confs[idx].data;
6797 	}
6798 	*total_size = 0;
6799 	memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
6800 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
6801 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
6802 	for (i = n - 1 ; i >= 0; --i) {
6803 		item = in->args.vc.pattern + i;
6804 		if (item->spec == NULL)
6805 			item->spec = flow_item_default_mask(item);
6806 		switch (item->type) {
6807 		case RTE_FLOW_ITEM_TYPE_ETH:
6808 			size = sizeof(struct rte_flow_item_eth);
6809 			break;
6810 		case RTE_FLOW_ITEM_TYPE_VLAN:
6811 			size = sizeof(struct rte_flow_item_vlan);
6812 			proto = RTE_ETHER_TYPE_VLAN;
6813 			break;
6814 		case RTE_FLOW_ITEM_TYPE_IPV4:
6815 			size = sizeof(struct rte_flow_item_ipv4);
6816 			proto = RTE_ETHER_TYPE_IPV4;
6817 			break;
6818 		case RTE_FLOW_ITEM_TYPE_IPV6:
6819 			size = sizeof(struct rte_flow_item_ipv6);
6820 			proto = RTE_ETHER_TYPE_IPV6;
6821 			break;
6822 		case RTE_FLOW_ITEM_TYPE_UDP:
6823 			size = sizeof(struct rte_flow_item_udp);
6824 			proto = 0x11;
6825 			break;
6826 		case RTE_FLOW_ITEM_TYPE_TCP:
6827 			size = sizeof(struct rte_flow_item_tcp);
6828 			proto = 0x06;
6829 			break;
6830 		case RTE_FLOW_ITEM_TYPE_VXLAN:
6831 			size = sizeof(struct rte_flow_item_vxlan);
6832 			break;
6833 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
6834 			size = sizeof(struct rte_flow_item_vxlan_gpe);
6835 			break;
6836 		case RTE_FLOW_ITEM_TYPE_GRE:
6837 			size = sizeof(struct rte_flow_item_gre);
6838 			proto = 0x2F;
6839 			break;
6840 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
6841 			size = sizeof(rte_be32_t);
6842 			proto = 0x0;
6843 			break;
6844 		case RTE_FLOW_ITEM_TYPE_MPLS:
6845 			size = sizeof(struct rte_flow_item_mpls);
6846 			proto = 0x0;
6847 			break;
6848 		case RTE_FLOW_ITEM_TYPE_NVGRE:
6849 			size = sizeof(struct rte_flow_item_nvgre);
6850 			proto = 0x2F;
6851 			break;
6852 		case RTE_FLOW_ITEM_TYPE_GENEVE:
6853 			size = sizeof(struct rte_flow_item_geneve);
6854 			break;
6855 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
6856 			size = sizeof(struct rte_flow_item_l2tpv3oip);
6857 			proto = 0x73;
6858 			break;
6859 		case RTE_FLOW_ITEM_TYPE_ESP:
6860 			size = sizeof(struct rte_flow_item_esp);
6861 			proto = 0x32;
6862 			break;
6863 		case RTE_FLOW_ITEM_TYPE_AH:
6864 			size = sizeof(struct rte_flow_item_ah);
6865 			proto = 0x33;
6866 			break;
6867 		case RTE_FLOW_ITEM_TYPE_GTP:
6868 			size = sizeof(struct rte_flow_item_gtp);
6869 			break;
6870 		case RTE_FLOW_ITEM_TYPE_PFCP:
6871 			size = sizeof(struct rte_flow_item_pfcp);
6872 			break;
6873 		default:
6874 			printf("Error - Not supported item\n");
6875 			*total_size = 0;
6876 			memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
6877 			return;
6878 		}
6879 		*total_size += size;
6880 		rte_memcpy(data_tail - (*total_size), item->spec, size);
6881 		/* update some fields which cannot be set by cmdline */
6882 		update_fields((data_tail - (*total_size)), item,
6883 			      upper_layer);
6884 		upper_layer = proto;
6885 	}
6886 	if (verbose_level & 0x1)
6887 		printf("total data size is %zu\n", (*total_size));
6888 	RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
6889 	memmove(data, (data_tail - (*total_size)), *total_size);
6890 }
6891 
6892 /** Populate help strings for current token (cmdline API). */
6893 static int
6894 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
6895 		     unsigned int size)
6896 {
6897 	struct context *ctx = &cmd_flow_context;
6898 	const struct token *token = &token_list[ctx->prev];
6899 
6900 	(void)hdr;
6901 	if (!size)
6902 		return -1;
6903 	/* Set token type and update global help with details. */
6904 	snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
6905 	if (token->help)
6906 		cmd_set_raw.help_str = token->help;
6907 	else
6908 		cmd_set_raw.help_str = token->name;
6909 	return 0;
6910 }
6911 
6912 /** Token definition template (cmdline API). */
6913 static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
6914 	.ops = &(struct cmdline_token_ops){
6915 		.parse = cmd_flow_parse,
6916 		.complete_get_nb = cmd_flow_complete_get_nb,
6917 		.complete_get_elt = cmd_flow_complete_get_elt,
6918 		.get_help = cmd_set_raw_get_help,
6919 	},
6920 	.offset = 0,
6921 };
6922 
6923 /** Populate the next dynamic token. */
6924 static void
6925 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
6926 	     cmdline_parse_token_hdr_t **hdr_inst)
6927 {
6928 	struct context *ctx = &cmd_flow_context;
6929 
6930 	/* Always reinitialize context before requesting the first token. */
6931 	if (!(hdr_inst - cmd_set_raw.tokens)) {
6932 		cmd_flow_context_init(ctx);
6933 		ctx->curr = START_SET;
6934 	}
6935 	/* Return NULL when no more tokens are expected. */
6936 	if (!ctx->next_num && (ctx->curr != START_SET)) {
6937 		*hdr = NULL;
6938 		return;
6939 	}
6940 	/* Determine if command should end here. */
6941 	if (ctx->eol && ctx->last && ctx->next_num) {
6942 		const enum index *list = ctx->next[ctx->next_num - 1];
6943 		int i;
6944 
6945 		for (i = 0; list[i]; ++i) {
6946 			if (list[i] != END)
6947 				continue;
6948 			*hdr = NULL;
6949 			return;
6950 		}
6951 	}
6952 	*hdr = &cmd_set_raw_token_hdr;
6953 }
6954 
6955 /** Token generator and output processing callback (cmdline API). */
6956 static void
6957 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
6958 {
6959 	if (cl == NULL)
6960 		cmd_set_raw_tok(arg0, arg2);
6961 	else
6962 		cmd_set_raw_parsed(arg0);
6963 }
6964 
6965 /** Global parser instance (cmdline API). */
6966 cmdline_parse_inst_t cmd_set_raw = {
6967 	.f = cmd_set_raw_cb,
6968 	.data = NULL, /**< Unused. */
6969 	.help_str = NULL, /**< Updated by cmd_flow_get_help(). */
6970 	.tokens = {
6971 		NULL,
6972 	}, /**< Tokens are returned by cmd_flow_tok(). */
6973 };
6974 
6975 /* *** display raw_encap/raw_decap buf */
6976 struct cmd_show_set_raw_result {
6977 	cmdline_fixed_string_t cmd_show;
6978 	cmdline_fixed_string_t cmd_what;
6979 	cmdline_fixed_string_t cmd_all;
6980 	uint16_t cmd_index;
6981 };
6982 
6983 static void
6984 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
6985 {
6986 	struct cmd_show_set_raw_result *res = parsed_result;
6987 	uint16_t index = res->cmd_index;
6988 	uint8_t all = 0;
6989 	uint8_t *raw_data = NULL;
6990 	size_t raw_size = 0;
6991 	char title[16] = {0};
6992 
6993 	RTE_SET_USED(cl);
6994 	RTE_SET_USED(data);
6995 	if (!strcmp(res->cmd_all, "all")) {
6996 		all = 1;
6997 		index = 0;
6998 	} else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
6999 		printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1);
7000 		return;
7001 	}
7002 	do {
7003 		if (!strcmp(res->cmd_what, "raw_encap")) {
7004 			raw_data = (uint8_t *)&raw_encap_confs[index].data;
7005 			raw_size = raw_encap_confs[index].size;
7006 			snprintf(title, 16, "\nindex: %u", index);
7007 			rte_hexdump(stdout, title, raw_data, raw_size);
7008 		} else {
7009 			raw_data = (uint8_t *)&raw_decap_confs[index].data;
7010 			raw_size = raw_decap_confs[index].size;
7011 			snprintf(title, 16, "\nindex: %u", index);
7012 			rte_hexdump(stdout, title, raw_data, raw_size);
7013 		}
7014 	} while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
7015 }
7016 
7017 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
7018 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
7019 			cmd_show, "show");
7020 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
7021 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
7022 			cmd_what, "raw_encap#raw_decap");
7023 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
7024 	TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
7025 			cmd_index, UINT16);
7026 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
7027 	TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
7028 			cmd_all, "all");
7029 cmdline_parse_inst_t cmd_show_set_raw = {
7030 	.f = cmd_show_set_raw_parsed,
7031 	.data = NULL,
7032 	.help_str = "show <raw_encap|raw_decap> <index>",
7033 	.tokens = {
7034 		(void *)&cmd_show_set_raw_cmd_show,
7035 		(void *)&cmd_show_set_raw_cmd_what,
7036 		(void *)&cmd_show_set_raw_cmd_index,
7037 		NULL,
7038 	},
7039 };
7040 cmdline_parse_inst_t cmd_show_set_raw_all = {
7041 	.f = cmd_show_set_raw_parsed,
7042 	.data = NULL,
7043 	.help_str = "show <raw_encap|raw_decap> all",
7044 	.tokens = {
7045 		(void *)&cmd_show_set_raw_cmd_show,
7046 		(void *)&cmd_show_set_raw_cmd_what,
7047 		(void *)&cmd_show_set_raw_cmd_all,
7048 		NULL,
7049 	},
7050 };
7051