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